@lime-bundles/widget 3.2.2 → 3.3.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 +19 -0
- package/dist/index.cjs +54 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +75 -0
- package/dist/index.d.ts +75 -0
- package/dist/index.js +57 -7
- package/dist/index.js.map +1 -1
- package/dist/lime-bundle.global.js +21 -21
- package/dist/lime-bundle.global.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,64 @@
|
|
|
1
|
+
import { BuyerResolver } from '@lime-bundles/core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* <lime-bundle> Web Component — renders Lime Bundles on any storefront.
|
|
5
|
+
*
|
|
6
|
+
* ## The two modes
|
|
7
|
+
*
|
|
8
|
+
* Single-bundle (pinned):
|
|
9
|
+
* <lime-bundle
|
|
10
|
+
* shop-domain="my-shop.myshopify.com"
|
|
11
|
+
* storefront-token="shpat_..."
|
|
12
|
+
* bundle-gid="gid://shopify/Metaobject/42"
|
|
13
|
+
* ></lime-bundle>
|
|
14
|
+
*
|
|
15
|
+
* Product-aware (matches classic Liquid theme block behaviour — one snippet
|
|
16
|
+
* on the product page renders every active bundle configured against that
|
|
17
|
+
* product):
|
|
18
|
+
* <lime-bundle
|
|
19
|
+
* shop-domain="my-shop.myshopify.com"
|
|
20
|
+
* storefront-token="shpat_..."
|
|
21
|
+
* ></lime-bundle>
|
|
22
|
+
*
|
|
23
|
+
* Product resolution cascade (when no `bundle-gid` is set):
|
|
24
|
+
* 1. explicit `product-handle` attribute
|
|
25
|
+
* 2. <meta name="shopify:product-handle" content="..."> on the page
|
|
26
|
+
* 3. /products/<handle> segment of window.location.pathname
|
|
27
|
+
* 4. fallthrough: renders nothing, fires `lime-bundle:error`
|
|
28
|
+
*
|
|
29
|
+
* ## Add-to-cart behaviour
|
|
30
|
+
*
|
|
31
|
+
* Merchants who do nothing get a default: the widget calls Shopify's
|
|
32
|
+
* Storefront Cart API (tokenless — no extra scopes required) and redirects
|
|
33
|
+
* the browser to the returned checkoutUrl. One-click-to-checkout is the
|
|
34
|
+
* right UX for most merchants pasting the widget into Webflow / Wix /
|
|
35
|
+
* Squarespace / static HTML.
|
|
36
|
+
*
|
|
37
|
+
* Merchants with their own cart state (Hydrogen's useCart, a custom cart
|
|
38
|
+
* drawer, etc.) opt out by attaching a listener that calls
|
|
39
|
+
* `event.preventDefault()`:
|
|
40
|
+
*
|
|
41
|
+
* document.querySelector("lime-bundle").addEventListener(
|
|
42
|
+
* "lime-bundle:add-to-cart",
|
|
43
|
+
* (ev) => {
|
|
44
|
+
* ev.preventDefault(); // suppress the default redirect
|
|
45
|
+
* myCart.linesAdd(ev.detail.lines);
|
|
46
|
+
* },
|
|
47
|
+
* );
|
|
48
|
+
*
|
|
49
|
+
* The event is always dispatched; only the default action is conditional.
|
|
50
|
+
*/
|
|
51
|
+
|
|
1
52
|
declare class LimeBundleElement extends HTMLElement {
|
|
2
53
|
static observedAttributes: string[];
|
|
54
|
+
/**
|
|
55
|
+
* B2B buyer identity. Set programmatically — `element.buyer = {...}` or
|
|
56
|
+
* `element.buyer = () => fetchToken()`. NEVER expose as an HTML attribute
|
|
57
|
+
* because the customer access token would land in DOM snapshots (Sentry,
|
|
58
|
+
* analytics, browser extensions) and Referer headers. See the package
|
|
59
|
+
* README ("Markets & B2B").
|
|
60
|
+
*/
|
|
61
|
+
buyer: BuyerResolver | undefined;
|
|
3
62
|
private shadow;
|
|
4
63
|
private bundles;
|
|
5
64
|
private abortController;
|
|
@@ -28,6 +87,22 @@ declare class LimeBundleElement extends HTMLElement {
|
|
|
28
87
|
private get productHandleAttr();
|
|
29
88
|
private get appUrl();
|
|
30
89
|
private get analyticsEnabled();
|
|
90
|
+
private get country();
|
|
91
|
+
private get language();
|
|
92
|
+
private get marketId();
|
|
93
|
+
/**
|
|
94
|
+
* Returns the @inContext-wrapped query when any context field is set;
|
|
95
|
+
* otherwise the plain query. Keeps responses publicly cacheable when
|
|
96
|
+
* no buyer/country/language is set.
|
|
97
|
+
*/
|
|
98
|
+
private wrapQueryForContext;
|
|
99
|
+
/**
|
|
100
|
+
* Returns true if this bundle should be hidden for the current market.
|
|
101
|
+
* For "all" bundles, always returns false (visible). For "specific"
|
|
102
|
+
* bundles, returns true when no marketId was set or when the bundle's
|
|
103
|
+
* marketIds doesn't include the configured market.
|
|
104
|
+
*/
|
|
105
|
+
private isMarketHidden;
|
|
31
106
|
private fetchBundle;
|
|
32
107
|
/**
|
|
33
108
|
* Resolve the visitor's A/B bucket for every bundle with an active test
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,64 @@
|
|
|
1
|
+
import { BuyerResolver } from '@lime-bundles/core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* <lime-bundle> Web Component — renders Lime Bundles on any storefront.
|
|
5
|
+
*
|
|
6
|
+
* ## The two modes
|
|
7
|
+
*
|
|
8
|
+
* Single-bundle (pinned):
|
|
9
|
+
* <lime-bundle
|
|
10
|
+
* shop-domain="my-shop.myshopify.com"
|
|
11
|
+
* storefront-token="shpat_..."
|
|
12
|
+
* bundle-gid="gid://shopify/Metaobject/42"
|
|
13
|
+
* ></lime-bundle>
|
|
14
|
+
*
|
|
15
|
+
* Product-aware (matches classic Liquid theme block behaviour — one snippet
|
|
16
|
+
* on the product page renders every active bundle configured against that
|
|
17
|
+
* product):
|
|
18
|
+
* <lime-bundle
|
|
19
|
+
* shop-domain="my-shop.myshopify.com"
|
|
20
|
+
* storefront-token="shpat_..."
|
|
21
|
+
* ></lime-bundle>
|
|
22
|
+
*
|
|
23
|
+
* Product resolution cascade (when no `bundle-gid` is set):
|
|
24
|
+
* 1. explicit `product-handle` attribute
|
|
25
|
+
* 2. <meta name="shopify:product-handle" content="..."> on the page
|
|
26
|
+
* 3. /products/<handle> segment of window.location.pathname
|
|
27
|
+
* 4. fallthrough: renders nothing, fires `lime-bundle:error`
|
|
28
|
+
*
|
|
29
|
+
* ## Add-to-cart behaviour
|
|
30
|
+
*
|
|
31
|
+
* Merchants who do nothing get a default: the widget calls Shopify's
|
|
32
|
+
* Storefront Cart API (tokenless — no extra scopes required) and redirects
|
|
33
|
+
* the browser to the returned checkoutUrl. One-click-to-checkout is the
|
|
34
|
+
* right UX for most merchants pasting the widget into Webflow / Wix /
|
|
35
|
+
* Squarespace / static HTML.
|
|
36
|
+
*
|
|
37
|
+
* Merchants with their own cart state (Hydrogen's useCart, a custom cart
|
|
38
|
+
* drawer, etc.) opt out by attaching a listener that calls
|
|
39
|
+
* `event.preventDefault()`:
|
|
40
|
+
*
|
|
41
|
+
* document.querySelector("lime-bundle").addEventListener(
|
|
42
|
+
* "lime-bundle:add-to-cart",
|
|
43
|
+
* (ev) => {
|
|
44
|
+
* ev.preventDefault(); // suppress the default redirect
|
|
45
|
+
* myCart.linesAdd(ev.detail.lines);
|
|
46
|
+
* },
|
|
47
|
+
* );
|
|
48
|
+
*
|
|
49
|
+
* The event is always dispatched; only the default action is conditional.
|
|
50
|
+
*/
|
|
51
|
+
|
|
1
52
|
declare class LimeBundleElement extends HTMLElement {
|
|
2
53
|
static observedAttributes: string[];
|
|
54
|
+
/**
|
|
55
|
+
* B2B buyer identity. Set programmatically — `element.buyer = {...}` or
|
|
56
|
+
* `element.buyer = () => fetchToken()`. NEVER expose as an HTML attribute
|
|
57
|
+
* because the customer access token would land in DOM snapshots (Sentry,
|
|
58
|
+
* analytics, browser extensions) and Referer headers. See the package
|
|
59
|
+
* README ("Markets & B2B").
|
|
60
|
+
*/
|
|
61
|
+
buyer: BuyerResolver | undefined;
|
|
3
62
|
private shadow;
|
|
4
63
|
private bundles;
|
|
5
64
|
private abortController;
|
|
@@ -28,6 +87,22 @@ declare class LimeBundleElement extends HTMLElement {
|
|
|
28
87
|
private get productHandleAttr();
|
|
29
88
|
private get appUrl();
|
|
30
89
|
private get analyticsEnabled();
|
|
90
|
+
private get country();
|
|
91
|
+
private get language();
|
|
92
|
+
private get marketId();
|
|
93
|
+
/**
|
|
94
|
+
* Returns the @inContext-wrapped query when any context field is set;
|
|
95
|
+
* otherwise the plain query. Keeps responses publicly cacheable when
|
|
96
|
+
* no buyer/country/language is set.
|
|
97
|
+
*/
|
|
98
|
+
private wrapQueryForContext;
|
|
99
|
+
/**
|
|
100
|
+
* Returns true if this bundle should be hidden for the current market.
|
|
101
|
+
* For "all" bundles, always returns false (visible). For "specific"
|
|
102
|
+
* bundles, returns true when no marketId was set or when the bundle's
|
|
103
|
+
* marketIds doesn't include the configured market.
|
|
104
|
+
*/
|
|
105
|
+
private isMarketHidden;
|
|
31
106
|
private fetchBundle;
|
|
32
107
|
/**
|
|
33
108
|
* Resolve the visitor's A/B bucket for every bundle with an active test
|
package/dist/index.js
CHANGED
|
@@ -13,7 +13,9 @@ import {
|
|
|
13
13
|
injectCustomCss,
|
|
14
14
|
sanitizeCustomCss,
|
|
15
15
|
getABTestAssignment,
|
|
16
|
-
applyABVariantB
|
|
16
|
+
applyABVariantB,
|
|
17
|
+
hasInContext,
|
|
18
|
+
withInContext
|
|
17
19
|
} from "@lime-bundles/core";
|
|
18
20
|
|
|
19
21
|
// src/renderers/fixed.ts
|
|
@@ -4137,8 +4139,19 @@ var LimeBundleElement = class extends HTMLElement {
|
|
|
4137
4139
|
"product-handle",
|
|
4138
4140
|
"app-url",
|
|
4139
4141
|
"analytics",
|
|
4140
|
-
"locale"
|
|
4142
|
+
"locale",
|
|
4143
|
+
"country",
|
|
4144
|
+
"language",
|
|
4145
|
+
"market-id"
|
|
4141
4146
|
];
|
|
4147
|
+
/**
|
|
4148
|
+
* B2B buyer identity. Set programmatically — `element.buyer = {...}` or
|
|
4149
|
+
* `element.buyer = () => fetchToken()`. NEVER expose as an HTML attribute
|
|
4150
|
+
* because the customer access token would land in DOM snapshots (Sentry,
|
|
4151
|
+
* analytics, browser extensions) and Referer headers. See the package
|
|
4152
|
+
* README ("Markets & B2B").
|
|
4153
|
+
*/
|
|
4154
|
+
buyer = void 0;
|
|
4142
4155
|
shadow;
|
|
4143
4156
|
bundles = [];
|
|
4144
4157
|
abortController = null;
|
|
@@ -4201,6 +4214,40 @@ var LimeBundleElement = class extends HTMLElement {
|
|
|
4201
4214
|
get analyticsEnabled() {
|
|
4202
4215
|
return this.getAttribute("analytics") !== "false";
|
|
4203
4216
|
}
|
|
4217
|
+
get country() {
|
|
4218
|
+
return this.getAttribute("country") ?? void 0;
|
|
4219
|
+
}
|
|
4220
|
+
get language() {
|
|
4221
|
+
return this.getAttribute("language") ?? void 0;
|
|
4222
|
+
}
|
|
4223
|
+
get marketId() {
|
|
4224
|
+
return this.getAttribute("market-id") ?? void 0;
|
|
4225
|
+
}
|
|
4226
|
+
/**
|
|
4227
|
+
* Returns the @inContext-wrapped query when any context field is set;
|
|
4228
|
+
* otherwise the plain query. Keeps responses publicly cacheable when
|
|
4229
|
+
* no buyer/country/language is set.
|
|
4230
|
+
*/
|
|
4231
|
+
wrapQueryForContext(query) {
|
|
4232
|
+
return hasInContext({
|
|
4233
|
+
shopDomain: this.shopDomain,
|
|
4234
|
+
accessToken: this.storefrontToken,
|
|
4235
|
+
country: this.country,
|
|
4236
|
+
language: this.language,
|
|
4237
|
+
buyer: this.buyer
|
|
4238
|
+
}) ? withInContext(query) : query;
|
|
4239
|
+
}
|
|
4240
|
+
/**
|
|
4241
|
+
* Returns true if this bundle should be hidden for the current market.
|
|
4242
|
+
* For "all" bundles, always returns false (visible). For "specific"
|
|
4243
|
+
* bundles, returns true when no marketId was set or when the bundle's
|
|
4244
|
+
* marketIds doesn't include the configured market.
|
|
4245
|
+
*/
|
|
4246
|
+
isMarketHidden(bundle) {
|
|
4247
|
+
if (bundle.marketVisibility !== "specific") return false;
|
|
4248
|
+
if (!this.marketId) return true;
|
|
4249
|
+
return !bundle.marketIds.includes(this.marketId);
|
|
4250
|
+
}
|
|
4204
4251
|
async fetchBundle() {
|
|
4205
4252
|
if (!this.shopDomain || !this.storefrontToken) {
|
|
4206
4253
|
this.renderError(
|
|
@@ -4214,7 +4261,10 @@ var LimeBundleElement = class extends HTMLElement {
|
|
|
4214
4261
|
this.renderLoading();
|
|
4215
4262
|
const client = createStorefrontClient({
|
|
4216
4263
|
shopDomain: this.shopDomain,
|
|
4217
|
-
accessToken: this.storefrontToken
|
|
4264
|
+
accessToken: this.storefrontToken,
|
|
4265
|
+
country: this.country,
|
|
4266
|
+
language: this.language,
|
|
4267
|
+
buyer: this.buyer
|
|
4218
4268
|
});
|
|
4219
4269
|
try {
|
|
4220
4270
|
let bundlePromise;
|
|
@@ -4298,7 +4348,7 @@ var LimeBundleElement = class extends HTMLElement {
|
|
|
4298
4348
|
}
|
|
4299
4349
|
async fetchSingleBundle(client, signal) {
|
|
4300
4350
|
const data = await client.query(
|
|
4301
|
-
BUNDLE_METAOBJECT_QUERY,
|
|
4351
|
+
this.wrapQueryForContext(BUNDLE_METAOBJECT_QUERY),
|
|
4302
4352
|
{ id: this.bundleGid },
|
|
4303
4353
|
{ signal }
|
|
4304
4354
|
);
|
|
@@ -4310,11 +4360,11 @@ var LimeBundleElement = class extends HTMLElement {
|
|
|
4310
4360
|
data.metaobject.id,
|
|
4311
4361
|
data.metaobject.fields
|
|
4312
4362
|
);
|
|
4313
|
-
this.bundles = parsed ? [parsed] : [];
|
|
4363
|
+
this.bundles = parsed && !this.isMarketHidden(parsed) ? [parsed] : [];
|
|
4314
4364
|
}
|
|
4315
4365
|
async fetchProductBundles(client, signal, productHandle) {
|
|
4316
4366
|
const data = await client.query(
|
|
4317
|
-
BUNDLES_FOR_PRODUCT_QUERY,
|
|
4367
|
+
this.wrapQueryForContext(BUNDLES_FOR_PRODUCT_QUERY),
|
|
4318
4368
|
{ handle: productHandle },
|
|
4319
4369
|
{ signal }
|
|
4320
4370
|
);
|
|
@@ -4326,7 +4376,7 @@ var LimeBundleElement = class extends HTMLElement {
|
|
|
4326
4376
|
const bundles = [];
|
|
4327
4377
|
for (const ref of refs) {
|
|
4328
4378
|
const parsed = parseMetaobjectBundle(ref.id, ref.fields);
|
|
4329
|
-
if (parsed) bundles.push(parsed);
|
|
4379
|
+
if (parsed && !this.isMarketHidden(parsed)) bundles.push(parsed);
|
|
4330
4380
|
}
|
|
4331
4381
|
this.bundles = bundles;
|
|
4332
4382
|
}
|