@lime-bundles/react 1.0.0 → 2.1.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/README.md +54 -60
- package/dist/index.cjs +134 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +24 -2
- package/dist/index.d.ts +24 -2
- package/dist/index.js +133 -8
- package/dist/index.js.map +1 -1
- package/docs/README.md +81 -0
- package/docs/css-variables.md +158 -0
- package/docs/hydrogen.md +185 -0
- package/docs/react-nextjs.md +379 -0
- package/docs/web-component.md +282 -0
- package/package.json +5 -4
package/README.md
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# @lime-bundles/react
|
|
2
2
|
|
|
3
|
-
React components and hooks for Lime Bundles on Hydrogen, Next.js, Vite, Remix, or any React renderer.
|
|
3
|
+
React components and hooks for the **Lime Bundles Shopify app**. Use on Hydrogen, Next.js, Vite, Remix, or any React renderer. If you're not a merchant using Lime Bundles, this package probably isn't what you're looking for.
|
|
4
|
+
|
|
5
|
+
Bring your own cart via an `onAddToCart` callback; the SDK handles data fetching, rendering, and analytics.
|
|
4
6
|
|
|
5
7
|
## Install
|
|
6
8
|
|
|
@@ -10,10 +12,10 @@ npm install @lime-bundles/react @lime-bundles/core
|
|
|
10
12
|
|
|
11
13
|
Peer dependencies: `react >=18`, `react-dom >=18`.
|
|
12
14
|
|
|
13
|
-
##
|
|
15
|
+
## Drop-in components
|
|
14
16
|
|
|
15
17
|
```tsx
|
|
16
|
-
import { FixedBundle
|
|
18
|
+
import { FixedBundle } from "@lime-bundles/react";
|
|
17
19
|
|
|
18
20
|
<FixedBundle
|
|
19
21
|
shopDomain="my-shop.myshopify.com"
|
|
@@ -26,107 +28,99 @@ import { FixedBundle, VolumeBundle, MixMatchBundle } from "@lime-bundles/react";
|
|
|
26
28
|
/>
|
|
27
29
|
```
|
|
28
30
|
|
|
29
|
-
|
|
31
|
+
Same props for `<VolumeBundle>` and `<MixMatchBundle>`.
|
|
32
|
+
|
|
33
|
+
### Props: `BundleComponentProps`
|
|
30
34
|
|
|
31
35
|
| Prop | Type | Required | Notes |
|
|
32
36
|
|---|---|:-:|---|
|
|
33
|
-
| `shopDomain` | `string` | ✓ | Your
|
|
34
|
-
| `storefrontAccessToken` | `string` | ✓ |
|
|
37
|
+
| `shopDomain` | `string` | ✓ | Your `*.myshopify.com` domain. |
|
|
38
|
+
| `storefrontAccessToken` | `string` | ✓ | Generated in `/app/settings/headless`. |
|
|
35
39
|
| `bundleGid` | `string` | ✓ | Bundle metaobject GID. |
|
|
36
|
-
| `onAddToCart` | `(lines: CartLineInput[]) => Promise<void>` | ✓ | Must return a Promise
|
|
37
|
-
| `appUrl` | `string` | | Required only if
|
|
38
|
-
| `analyticsEnabled` | `boolean` | | Default `true`.
|
|
39
|
-
| `onError` | `(error: Error) => void` | | Fires on
|
|
40
|
-
| `locale` | `string` | | BCP-47
|
|
40
|
+
| `onAddToCart` | `(lines: CartLineInput[]) => Promise<void>` | ✓ | Must return a Promise; components await it for loading states. |
|
|
41
|
+
| `appUrl` | `string` | | Required only if analytics are enabled. |
|
|
42
|
+
| `analyticsEnabled` | `boolean` | | Default `true`. `false` suppresses impression + add-to-cart POSTs. |
|
|
43
|
+
| `onError` | `(error: Error) => void` | | Fires on fetch, parse, or cart failure. |
|
|
44
|
+
| `locale` | `string` | | BCP-47 tag forwarded to the Storefront API. |
|
|
41
45
|
| `className` | `string` | | Applied to the outer wrapper. |
|
|
42
46
|
|
|
43
|
-
|
|
47
|
+
`CartLineInput` matches Shopify Hydrogen's shape. A structural-compat test guards the contract across versions. Always preserve `attributes[]` so `_lime_bundle_gid` reaches Shopify; the `orders/create` webhook keys off it for purchase attribution.
|
|
44
48
|
|
|
45
49
|
## Hooks
|
|
46
50
|
|
|
47
|
-
### `useBundleData`
|
|
51
|
+
### `useBundleData({ shopDomain, storefrontAccessToken, bundleGid })`
|
|
48
52
|
|
|
49
|
-
|
|
53
|
+
Fetches a single bundle by GID. Discriminated-union result.
|
|
50
54
|
|
|
51
55
|
```tsx
|
|
52
56
|
import { useBundleData } from "@lime-bundles/react";
|
|
53
57
|
|
|
54
58
|
function MyBundle({ bundleGid }: { bundleGid: string }) {
|
|
55
|
-
const result = useBundleData({
|
|
56
|
-
shopDomain: "my-shop.myshopify.com",
|
|
57
|
-
storefrontAccessToken: TOKEN,
|
|
58
|
-
bundleGid,
|
|
59
|
-
});
|
|
60
|
-
|
|
59
|
+
const result = useBundleData({ shopDomain, storefrontAccessToken, bundleGid });
|
|
61
60
|
if (result.status === "loading") return <Skeleton />;
|
|
62
61
|
if (result.status === "error") return <Error message={result.error.message} />;
|
|
63
|
-
|
|
64
|
-
// result.status === "success": result.bundle is a ParsedBundle
|
|
65
62
|
return <pre>{JSON.stringify(result.bundle, null, 2)}</pre>;
|
|
66
63
|
}
|
|
67
64
|
```
|
|
68
65
|
|
|
69
|
-
|
|
66
|
+
### `useBundlesForProduct({ shopDomain, storefrontAccessToken, productHandle })`
|
|
67
|
+
|
|
68
|
+
Fetches every active bundle configured against a product. Equivalent to the web component's auto-detect mode. Inactive and out-of-schedule bundles are filtered out.
|
|
69
|
+
|
|
70
|
+
```tsx
|
|
71
|
+
import { useBundlesForProduct } from "@lime-bundles/react";
|
|
72
|
+
|
|
73
|
+
const result = useBundlesForProduct({ shopDomain, storefrontAccessToken, productHandle });
|
|
74
|
+
if (result.status === "success") {
|
|
75
|
+
return result.bundles.map((b) => <FixedBundle key={b.id} bundleGid={b.id} {...cartProps} />);
|
|
76
|
+
}
|
|
77
|
+
```
|
|
70
78
|
|
|
71
|
-
|
|
79
|
+
Both hooks auto-fetch merchant custom CSS and inject it as a scoped `<style>` tag. Unmount / dependency change cancels the in-flight request.
|
|
72
80
|
|
|
73
|
-
## Async
|
|
81
|
+
## Async fetchers for SSR / RSC
|
|
74
82
|
|
|
75
|
-
|
|
83
|
+
For Hydrogen loaders, Next.js Server Components, or `getServerSideProps`: skip the hook and use the async helpers directly.
|
|
76
84
|
|
|
77
85
|
```ts
|
|
78
|
-
import { fetchBundleData } from "@lime-bundles/react";
|
|
86
|
+
import { fetchBundleData, fetchBundlesForProduct } from "@lime-bundles/react";
|
|
79
87
|
|
|
80
88
|
const bundle = await fetchBundleData({
|
|
81
|
-
shopDomain
|
|
82
|
-
storefrontAccessToken
|
|
83
|
-
bundleGid
|
|
84
|
-
buyerIp: request.headers.get("x-forwarded-for")?.split(",")[0].trim()
|
|
89
|
+
shopDomain,
|
|
90
|
+
storefrontAccessToken,
|
|
91
|
+
bundleGid,
|
|
92
|
+
buyerIp: request.headers.get("x-forwarded-for")?.split(",")[0].trim(),
|
|
85
93
|
});
|
|
86
94
|
```
|
|
87
95
|
|
|
88
|
-
`buyerIp` is
|
|
89
|
-
|
|
90
|
-
Throws:
|
|
91
|
-
- `StorefrontApiError`: network, HTTP, or GraphQL errors.
|
|
92
|
-
- `BundleParseError`: metaobject missing, invalid type, inactive, not started, or expired. `error.reason` is a typed literal.
|
|
93
|
-
|
|
94
|
-
## The cart contract
|
|
96
|
+
`buyerIp` is mandatory on SSR. Shopify returns 430 Security Rejection for server-originated traffic without it.
|
|
95
97
|
|
|
96
|
-
|
|
98
|
+
## Build your own UI
|
|
97
99
|
|
|
98
|
-
|
|
99
|
-
type CartLineInput = {
|
|
100
|
-
merchandiseId: string; // variant GID
|
|
101
|
-
quantity: number;
|
|
102
|
-
attributes: Array<{ key: string; value: string }>;
|
|
103
|
-
};
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
Always preserve `attributes[].{key: "_lime_bundle_gid"}` on its way to Shopify. The `orders/create` webhook uses it for purchase attribution.
|
|
100
|
+
Everything the built-in components use is re-exported for DIY consumers: pricing math, CSS-variable flatteners, image CDN transforms, countdown formatter, A/B merge, etc. See the [Build your own UI](./docs/react-nextjs.md#build-your-own-ui-diy-path) doc for the full primitives list.
|
|
107
101
|
|
|
108
102
|
## Styling
|
|
109
103
|
|
|
110
|
-
|
|
104
|
+
Merchant widget styling is applied automatically when you use `<FixedBundle>` / `<VolumeBundle>` / `<MixMatchBundle>`. For DIY UI, apply the config yourself:
|
|
111
105
|
|
|
112
106
|
```tsx
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
107
|
+
import { applyWidgetConfigVars } from "@lime-bundles/react";
|
|
108
|
+
|
|
109
|
+
useEffect(() => {
|
|
110
|
+
if (ref.current) applyWidgetConfigVars(ref.current, bundle.widgetConfig);
|
|
111
|
+
}, [bundle.widgetConfig]);
|
|
116
112
|
```
|
|
117
113
|
|
|
118
|
-
Full reference: [css-variables.md](
|
|
114
|
+
Full CSS variable reference: [css-variables.md](./docs/css-variables.md).
|
|
119
115
|
|
|
120
|
-
##
|
|
116
|
+
## Version policy
|
|
121
117
|
|
|
122
|
-
|
|
118
|
+
`BundleComponentProps`, `UseBundleDataResult`, and `UseBundlesForProductResult` are locked at v2.0.0. All three packages (`core`, `react`, `widget`) bump majors together.
|
|
123
119
|
|
|
124
120
|
## License
|
|
125
121
|
|
|
126
|
-
MIT.
|
|
122
|
+
MIT.
|
|
127
123
|
|
|
128
|
-
##
|
|
124
|
+
## Support
|
|
129
125
|
|
|
130
|
-
|
|
131
|
-
- [React / Next.js guide](https://github.com/lime-app-dev/lime-bundles-app/blob/main/docs/headless/react-nextjs.md)
|
|
132
|
-
- [Report issues](https://github.com/lime-app-dev/lime-bundles-app/issues)
|
|
126
|
+
Merchant support and bug reports: email via the Lime Bundles listing on the Shopify App Store.
|
package/dist/index.cjs
CHANGED
|
@@ -20,15 +20,47 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
-
|
|
23
|
+
BUNDLES_FOR_PRODUCT_QUERY: () => import_core10.BUNDLES_FOR_PRODUCT_QUERY,
|
|
24
|
+
BUNDLE_METAOBJECT_QUERY: () => import_core10.BUNDLE_METAOBJECT_QUERY,
|
|
25
|
+
BundleParseError: () => import_core9.BundleParseError,
|
|
24
26
|
FixedBundle: () => FixedBundle,
|
|
25
27
|
MixMatchBundle: () => MixMatchBundle,
|
|
26
|
-
|
|
28
|
+
SHOP_CUSTOM_CSS_QUERY: () => import_core10.SHOP_CUSTOM_CSS_QUERY,
|
|
29
|
+
StorefrontApiError: () => import_core9.StorefrontApiError,
|
|
27
30
|
VolumeBundle: () => VolumeBundle,
|
|
31
|
+
WIDGET_CONFIG_DEFAULTS: () => import_core10.WIDGET_CONFIG_DEFAULTS,
|
|
32
|
+
applyABVariantB: () => import_core10.applyABVariantB,
|
|
33
|
+
applyWidgetConfigVars: () => import_core10.applyWidgetConfigVars,
|
|
34
|
+
calculateDiscount: () => import_core10.calculateDiscount,
|
|
35
|
+
calculateTierSavings: () => import_core10.calculateTierSavings,
|
|
36
|
+
computeBundleSaleCents: () => import_core10.computeBundleSaleCents,
|
|
37
|
+
computeFixedPricing: () => import_core10.computeFixedPricing,
|
|
38
|
+
createStorefrontClient: () => import_core10.createStorefrontClient,
|
|
28
39
|
fetchBundleData: () => fetchBundleData,
|
|
40
|
+
fetchBundlesForProduct: () => import_core10.fetchBundlesForProduct,
|
|
29
41
|
fetchShopCustomCss: () => fetchShopCustomCss,
|
|
42
|
+
formatCents: () => import_core10.formatCents,
|
|
43
|
+
formatCountdown: () => import_core10.formatCountdown,
|
|
44
|
+
formatMoney: () => import_core10.formatMoney,
|
|
45
|
+
getABTestAssignment: () => import_core10.getABTestAssignment,
|
|
46
|
+
getActiveTier: () => import_core10.getActiveTier,
|
|
47
|
+
hasConsent: () => import_core10.hasConsent,
|
|
48
|
+
injectCustomCss: () => import_core10.injectCustomCss,
|
|
49
|
+
mergeWidgetConfig: () => import_core10.mergeWidgetConfig,
|
|
50
|
+
observeImpression: () => import_core10.observeImpression,
|
|
51
|
+
parseCents: () => import_core10.parseCents,
|
|
52
|
+
parseMetaobjectBundle: () => import_core10.parseMetaobjectBundle,
|
|
53
|
+
parseMetaobjectBundleStrict: () => import_core10.parseMetaobjectBundleStrict,
|
|
54
|
+
percentageDiscountUnit: () => import_core10.percentageDiscountUnit,
|
|
55
|
+
reportAddToCart: () => import_core10.reportAddToCart,
|
|
56
|
+
reportImpression: () => import_core10.reportImpression,
|
|
57
|
+
sanitizeCustomCss: () => import_core10.sanitizeCustomCss,
|
|
58
|
+
setConsent: () => import_core10.setConsent,
|
|
59
|
+
transformImageUrl: () => import_core10.transformImageUrl,
|
|
30
60
|
useAnalytics: () => useAnalytics,
|
|
31
|
-
useBundleData: () => useBundleData
|
|
61
|
+
useBundleData: () => useBundleData,
|
|
62
|
+
useBundlesForProduct: () => useBundlesForProduct,
|
|
63
|
+
validateQuantity: () => import_core10.validateQuantity
|
|
32
64
|
});
|
|
33
65
|
module.exports = __toCommonJS(index_exports);
|
|
34
66
|
|
|
@@ -328,7 +360,7 @@ function FixedBundle(props) {
|
|
|
328
360
|
onClick: handleAddToCart,
|
|
329
361
|
disabled: addingToCart,
|
|
330
362
|
"aria-busy": addingToCart,
|
|
331
|
-
children: addingToCart ? "Adding..." : bundle.widgetConfig.ctaText ?? "Add Bundle to Cart"
|
|
363
|
+
children: addingToCart ? "Adding..." : bundle.widgetConfig.cta.ctaText ?? "Add Bundle to Cart"
|
|
332
364
|
}
|
|
333
365
|
)
|
|
334
366
|
]
|
|
@@ -554,7 +586,7 @@ function MixMatchBundle(props) {
|
|
|
554
586
|
onClick: handleAddToCart,
|
|
555
587
|
disabled: addingToCart || !validation.valid,
|
|
556
588
|
"aria-busy": addingToCart,
|
|
557
|
-
children: addingToCart ? "Adding..." : bundle.widgetConfig.ctaText ?? `Add ${totalQuantity} Items to Cart`
|
|
589
|
+
children: addingToCart ? "Adding..." : bundle.widgetConfig.cta.ctaText ?? `Add ${totalQuantity} Items to Cart`
|
|
558
590
|
}
|
|
559
591
|
)
|
|
560
592
|
]
|
|
@@ -609,7 +641,12 @@ function VolumeBundle(props) {
|
|
|
609
641
|
const product = bundle?.products[0];
|
|
610
642
|
const basePrice = product ? parseFloat(product.priceRange.minVariantPrice.amount) : 0;
|
|
611
643
|
const currency = product?.priceRange.minVariantPrice.currencyCode ?? "USD";
|
|
612
|
-
const tierSavings = bundle ? (0, import_core7.calculateTierSavings)(
|
|
644
|
+
const tierSavings = bundle ? (0, import_core7.calculateTierSavings)(
|
|
645
|
+
bundle.volumeTiers,
|
|
646
|
+
basePrice,
|
|
647
|
+
quantity,
|
|
648
|
+
bundle.discountConfig.discountType
|
|
649
|
+
) : [];
|
|
613
650
|
const activeTier = bundle ? (0, import_core7.getActiveTier)(bundle.volumeTiers, quantity) : null;
|
|
614
651
|
const handleAddToCart = (0, import_react5.useCallback)(async () => {
|
|
615
652
|
if (!bundle || !product) return;
|
|
@@ -629,7 +666,7 @@ function VolumeBundle(props) {
|
|
|
629
666
|
setCartError(null);
|
|
630
667
|
try {
|
|
631
668
|
await onAddToCart(lines);
|
|
632
|
-
const unitPrice =
|
|
669
|
+
const unitPrice = tierSavings.find((ts) => ts.tier === activeTier)?.unitPrice ?? basePrice;
|
|
633
670
|
trackAddToCart({
|
|
634
671
|
productId: product.id,
|
|
635
672
|
quantity,
|
|
@@ -712,8 +749,7 @@ function VolumeBundle(props) {
|
|
|
712
749
|
"Save ",
|
|
713
750
|
ts.savingsPercent.toFixed(0),
|
|
714
751
|
"%"
|
|
715
|
-
] })
|
|
716
|
-
ts.tier.label && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "lb-bundle__tier-label", role: "cell", children: ts.tier.label })
|
|
752
|
+
] })
|
|
717
753
|
]
|
|
718
754
|
},
|
|
719
755
|
ts.tier.minQuantity
|
|
@@ -763,7 +799,7 @@ function VolumeBundle(props) {
|
|
|
763
799
|
onClick: handleAddToCart,
|
|
764
800
|
disabled: addingToCart,
|
|
765
801
|
"aria-busy": addingToCart,
|
|
766
|
-
children: addingToCart ? "Adding..." : bundle.widgetConfig.ctaText ?? `Add ${quantity} to Cart`
|
|
802
|
+
children: addingToCart ? "Adding..." : bundle.widgetConfig.cta.ctaText ?? `Add ${quantity} to Cart`
|
|
767
803
|
}
|
|
768
804
|
)
|
|
769
805
|
]
|
|
@@ -771,18 +807,104 @@ function VolumeBundle(props) {
|
|
|
771
807
|
);
|
|
772
808
|
}
|
|
773
809
|
|
|
774
|
-
// src/
|
|
810
|
+
// src/hooks/useBundlesForProduct.ts
|
|
811
|
+
var import_react6 = require("react");
|
|
775
812
|
var import_core8 = require("@lime-bundles/core");
|
|
813
|
+
var INITIAL_STATE2 = {
|
|
814
|
+
status: "loading",
|
|
815
|
+
bundles: null,
|
|
816
|
+
error: null
|
|
817
|
+
};
|
|
818
|
+
function useBundlesForProduct(options) {
|
|
819
|
+
const [state, setState] = (0, import_react6.useState)(
|
|
820
|
+
INITIAL_STATE2
|
|
821
|
+
);
|
|
822
|
+
(0, import_react6.useEffect)(() => {
|
|
823
|
+
const controller = new AbortController();
|
|
824
|
+
setState(INITIAL_STATE2);
|
|
825
|
+
(0, import_core8.fetchBundlesForProduct)({
|
|
826
|
+
shopDomain: options.shopDomain,
|
|
827
|
+
storefrontAccessToken: options.storefrontAccessToken,
|
|
828
|
+
productHandle: options.productHandle,
|
|
829
|
+
buyerIp: options.buyerIp,
|
|
830
|
+
signal: controller.signal
|
|
831
|
+
}).then((bundles) => {
|
|
832
|
+
if (controller.signal.aborted) return;
|
|
833
|
+
setState({ status: "success", bundles, error: null });
|
|
834
|
+
}).catch((err) => {
|
|
835
|
+
if (controller.signal.aborted) return;
|
|
836
|
+
setState({
|
|
837
|
+
status: "error",
|
|
838
|
+
bundles: null,
|
|
839
|
+
error: err instanceof Error ? err : new Error(String(err))
|
|
840
|
+
});
|
|
841
|
+
});
|
|
842
|
+
fetchShopCustomCss({
|
|
843
|
+
shopDomain: options.shopDomain,
|
|
844
|
+
storefrontAccessToken: options.storefrontAccessToken,
|
|
845
|
+
signal: controller.signal
|
|
846
|
+
}).then((css) => {
|
|
847
|
+
if (controller.signal.aborted) return;
|
|
848
|
+
(0, import_core8.injectCustomCss)(options.shopDomain, css);
|
|
849
|
+
}).catch(() => {
|
|
850
|
+
});
|
|
851
|
+
return () => {
|
|
852
|
+
controller.abort();
|
|
853
|
+
};
|
|
854
|
+
}, [
|
|
855
|
+
options.shopDomain,
|
|
856
|
+
options.storefrontAccessToken,
|
|
857
|
+
options.productHandle,
|
|
858
|
+
options.buyerIp
|
|
859
|
+
]);
|
|
860
|
+
return state;
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
// src/index.ts
|
|
864
|
+
var import_core9 = require("@lime-bundles/core");
|
|
865
|
+
var import_core10 = require("@lime-bundles/core");
|
|
776
866
|
// Annotate the CommonJS export names for ESM import in node:
|
|
777
867
|
0 && (module.exports = {
|
|
868
|
+
BUNDLES_FOR_PRODUCT_QUERY,
|
|
869
|
+
BUNDLE_METAOBJECT_QUERY,
|
|
778
870
|
BundleParseError,
|
|
779
871
|
FixedBundle,
|
|
780
872
|
MixMatchBundle,
|
|
873
|
+
SHOP_CUSTOM_CSS_QUERY,
|
|
781
874
|
StorefrontApiError,
|
|
782
875
|
VolumeBundle,
|
|
876
|
+
WIDGET_CONFIG_DEFAULTS,
|
|
877
|
+
applyABVariantB,
|
|
878
|
+
applyWidgetConfigVars,
|
|
879
|
+
calculateDiscount,
|
|
880
|
+
calculateTierSavings,
|
|
881
|
+
computeBundleSaleCents,
|
|
882
|
+
computeFixedPricing,
|
|
883
|
+
createStorefrontClient,
|
|
783
884
|
fetchBundleData,
|
|
885
|
+
fetchBundlesForProduct,
|
|
784
886
|
fetchShopCustomCss,
|
|
887
|
+
formatCents,
|
|
888
|
+
formatCountdown,
|
|
889
|
+
formatMoney,
|
|
890
|
+
getABTestAssignment,
|
|
891
|
+
getActiveTier,
|
|
892
|
+
hasConsent,
|
|
893
|
+
injectCustomCss,
|
|
894
|
+
mergeWidgetConfig,
|
|
895
|
+
observeImpression,
|
|
896
|
+
parseCents,
|
|
897
|
+
parseMetaobjectBundle,
|
|
898
|
+
parseMetaobjectBundleStrict,
|
|
899
|
+
percentageDiscountUnit,
|
|
900
|
+
reportAddToCart,
|
|
901
|
+
reportImpression,
|
|
902
|
+
sanitizeCustomCss,
|
|
903
|
+
setConsent,
|
|
904
|
+
transformImageUrl,
|
|
785
905
|
useAnalytics,
|
|
786
|
-
useBundleData
|
|
906
|
+
useBundleData,
|
|
907
|
+
useBundlesForProduct,
|
|
908
|
+
validateQuantity
|
|
787
909
|
});
|
|
788
910
|
//# sourceMappingURL=index.cjs.map
|