@lime-bundles/widget 4.5.1 → 4.6.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 +5 -2
- package/dist/index.cjs +37 -9
- package/dist/index.d.cts +17 -3
- package/dist/index.d.ts +17 -3
- package/dist/index.js +39 -10
- package/dist/lime-bundle.global.js +20 -20
- package/dist/lime-bundle.global.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -62,9 +62,12 @@ document.querySelector("lime-bundle").addEventListener(
|
|
|
62
62
|
| `app-url` | | Enables impression + add-to-cart analytics when set. |
|
|
63
63
|
| `analytics` | | `"false"` suppresses analytics even when `app-url` is set. |
|
|
64
64
|
| `locale` | | BCP-47 tag forwarded to the Storefront API. |
|
|
65
|
-
| `country` | | ISO-3166 alpha-2 (e.g. `"US"`). Adds `@inContext(country:)` to Storefront queries — Markets pricing + currency. |
|
|
65
|
+
| `country` | | ISO-3166 alpha-2 (e.g. `"US"`). Adds `@inContext(country:)` to Storefront queries — Markets pricing + currency — and matches market-restricted bundles' projected country codes. |
|
|
66
66
|
| `language` | | ISO-639-1 (e.g. `"EN"`). Adds `@inContext(language:)`. |
|
|
67
|
-
| `market-id` | | Current visitor's Market GID.
|
|
67
|
+
| `market-id` | | Current visitor's Market GID. Legacy market-gate signal; prefer `country` (retail) and the `buyer` property (B2B) — a B2B buyer's company-location market has no storefront market context. |
|
|
68
|
+
| `currency-rate` | | Store→presentment currency rate. Merchant-configured amounts (fixed-amount discounts, flat prices, volume tier amounts) are stored in the shop's store currency; on a "local currencies" market, pass the buyer's rate (on a Liquid-adjacent page, `window.Shopify.currency.rate`) so quoted sale prices match what checkout charges. Defaults to `1` (no conversion); invalid or non-positive values also fall back to `1`. Percentages are unaffected. |
|
|
69
|
+
|
|
70
|
+
A market-restricted bundle renders when any signal matches: `country` vs the bundle's projected country codes, the resolved `buyer` property's `companyLocationId` vs its projected company locations, or `market-id` vs its market allow-list.
|
|
68
71
|
|
|
69
72
|
**Product resolution** (when `bundle-gid` is absent): explicit `product-handle` → `<meta name="shopify:product-handle">` → `/products/<handle>` URL segment.
|
|
70
73
|
|
package/dist/index.cjs
CHANGED
|
@@ -7212,7 +7212,8 @@ var LimeBundleElement = class extends HTMLElement {
|
|
|
7212
7212
|
"locale",
|
|
7213
7213
|
"country",
|
|
7214
7214
|
"language",
|
|
7215
|
-
"market-id"
|
|
7215
|
+
"market-id",
|
|
7216
|
+
"currency-rate"
|
|
7216
7217
|
];
|
|
7217
7218
|
/**
|
|
7218
7219
|
* B2B buyer identity. Set programmatically — `element.buyer = {...}` or
|
|
@@ -7267,7 +7268,7 @@ var LimeBundleElement = class extends HTMLElement {
|
|
|
7267
7268
|
}
|
|
7268
7269
|
attributeChangedCallback(name, oldValue, newValue) {
|
|
7269
7270
|
if (oldValue === newValue || !this.isConnected) return;
|
|
7270
|
-
if (name === "bundle-gid" || name === "product-handle" || name === "product-id" || name === "shop-domain" || name === "storefront-token") {
|
|
7271
|
+
if (name === "bundle-gid" || name === "product-handle" || name === "product-id" || name === "shop-domain" || name === "storefront-token" || name === "currency-rate") {
|
|
7271
7272
|
if (this.shopDomain && this.storefrontToken) {
|
|
7272
7273
|
this.fetchBundle();
|
|
7273
7274
|
}
|
|
@@ -7310,6 +7311,17 @@ var LimeBundleElement = class extends HTMLElement {
|
|
|
7310
7311
|
get marketId() {
|
|
7311
7312
|
return this.getAttribute("market-id") ?? void 0;
|
|
7312
7313
|
}
|
|
7314
|
+
/**
|
|
7315
|
+
* Store→presentment currency rate. Merchant-configured amounts
|
|
7316
|
+
* (fixed_amount / flat_price values, volume tier amounts) are stored in
|
|
7317
|
+
* the shop's store currency; set this to the buyer's currency rate so
|
|
7318
|
+
* quoted sale prices match what the checkout's discount function
|
|
7319
|
+
* charges. Anything unparseable or non-positive falls back to 1 —
|
|
7320
|
+
* no conversion — via `normalizeCurrencyRate`.
|
|
7321
|
+
*/
|
|
7322
|
+
get currencyRate() {
|
|
7323
|
+
return this.getAttribute("currency-rate") ?? void 0;
|
|
7324
|
+
}
|
|
7313
7325
|
/**
|
|
7314
7326
|
* Returns the @inContext-wrapped query when any context field is set;
|
|
7315
7327
|
* otherwise the plain query. Keeps responses publicly cacheable when
|
|
@@ -7324,14 +7336,23 @@ var LimeBundleElement = class extends HTMLElement {
|
|
|
7324
7336
|
buyer: this.buyer
|
|
7325
7337
|
}) ? (0, import_core6.withInContext)(query) : query;
|
|
7326
7338
|
}
|
|
7339
|
+
/** Buyer resolved once per fetch so the market gate can read the
|
|
7340
|
+
* company location without invoking a callback resolver twice. */
|
|
7341
|
+
resolvedBuyer = void 0;
|
|
7327
7342
|
/**
|
|
7328
|
-
* Returns true if this bundle should be hidden for the current
|
|
7343
|
+
* Returns true if this bundle should be hidden for the current buyer.
|
|
7329
7344
|
* For "all" bundles, always returns false (visible). For "specific"
|
|
7330
|
-
* bundles,
|
|
7331
|
-
*
|
|
7345
|
+
* bundles, visibility needs a matching signal: the `country` attribute
|
|
7346
|
+
* against the bundle's projected country codes (retail markets), the
|
|
7347
|
+
* resolved buyer's companyLocationId against its projected company
|
|
7348
|
+
* locations (B2B markets), or a legacy `market-id` match.
|
|
7332
7349
|
*/
|
|
7333
7350
|
isMarketHidden(bundle) {
|
|
7334
|
-
return !(0, import_core6.
|
|
7351
|
+
return !(0, import_core6.isVisibleToBuyer)(bundle, {
|
|
7352
|
+
marketId: this.marketId,
|
|
7353
|
+
countryCode: this.country,
|
|
7354
|
+
companyLocationId: this.resolvedBuyer?.companyLocationId
|
|
7355
|
+
});
|
|
7335
7356
|
}
|
|
7336
7357
|
async fetchBundle() {
|
|
7337
7358
|
if (!this.shopDomain || !this.storefrontToken) {
|
|
@@ -7344,12 +7365,17 @@ var LimeBundleElement = class extends HTMLElement {
|
|
|
7344
7365
|
const controller = new AbortController();
|
|
7345
7366
|
this.abortController = controller;
|
|
7346
7367
|
this.renderLoading();
|
|
7368
|
+
try {
|
|
7369
|
+
this.resolvedBuyer = typeof this.buyer === "function" ? await this.buyer() : this.buyer;
|
|
7370
|
+
} catch {
|
|
7371
|
+
this.resolvedBuyer = void 0;
|
|
7372
|
+
}
|
|
7347
7373
|
const client = (0, import_core6.createStorefrontClient)({
|
|
7348
7374
|
shopDomain: this.shopDomain,
|
|
7349
7375
|
accessToken: this.storefrontToken,
|
|
7350
7376
|
country: this.country,
|
|
7351
7377
|
language: this.language,
|
|
7352
|
-
buyer: this.
|
|
7378
|
+
buyer: this.resolvedBuyer
|
|
7353
7379
|
});
|
|
7354
7380
|
try {
|
|
7355
7381
|
let bundlePromise;
|
|
@@ -7414,7 +7440,7 @@ var LimeBundleElement = class extends HTMLElement {
|
|
|
7414
7440
|
data.metaobject.id,
|
|
7415
7441
|
data.metaobject.fields
|
|
7416
7442
|
);
|
|
7417
|
-
this.bundles = parsed && !this.isMarketHidden(parsed) ? [parsed] : [];
|
|
7443
|
+
this.bundles = parsed && !this.isMarketHidden(parsed) ? [(0, import_core6.convertBundleToPresentment)(parsed, this.currencyRate)] : [];
|
|
7418
7444
|
}
|
|
7419
7445
|
async fetchProductBundles(client, signal, productHandle) {
|
|
7420
7446
|
const data = await client.query(
|
|
@@ -7430,7 +7456,9 @@ var LimeBundleElement = class extends HTMLElement {
|
|
|
7430
7456
|
const bundles = [];
|
|
7431
7457
|
for (const ref of refs) {
|
|
7432
7458
|
const parsed = (0, import_core6.parseMetaobjectBundle)(ref.id, ref.fields);
|
|
7433
|
-
if (parsed && !this.isMarketHidden(parsed))
|
|
7459
|
+
if (parsed && !this.isMarketHidden(parsed)) {
|
|
7460
|
+
bundles.push((0, import_core6.convertBundleToPresentment)(parsed, this.currencyRate));
|
|
7461
|
+
}
|
|
7434
7462
|
}
|
|
7435
7463
|
this.bundles = (0, import_core6.resolveAbTests)(bundles, (0, import_core6.getVisitorId)());
|
|
7436
7464
|
}
|
package/dist/index.d.cts
CHANGED
|
@@ -109,17 +109,31 @@ declare class LimeBundleElement extends HTMLElement {
|
|
|
109
109
|
private get country();
|
|
110
110
|
private get language();
|
|
111
111
|
private get marketId();
|
|
112
|
+
/**
|
|
113
|
+
* Store→presentment currency rate. Merchant-configured amounts
|
|
114
|
+
* (fixed_amount / flat_price values, volume tier amounts) are stored in
|
|
115
|
+
* the shop's store currency; set this to the buyer's currency rate so
|
|
116
|
+
* quoted sale prices match what the checkout's discount function
|
|
117
|
+
* charges. Anything unparseable or non-positive falls back to 1 —
|
|
118
|
+
* no conversion — via `normalizeCurrencyRate`.
|
|
119
|
+
*/
|
|
120
|
+
private get currencyRate();
|
|
112
121
|
/**
|
|
113
122
|
* Returns the @inContext-wrapped query when any context field is set;
|
|
114
123
|
* otherwise the plain query. Keeps responses publicly cacheable when
|
|
115
124
|
* no buyer/country/language is set.
|
|
116
125
|
*/
|
|
117
126
|
private wrapQueryForContext;
|
|
127
|
+
/** Buyer resolved once per fetch so the market gate can read the
|
|
128
|
+
* company location without invoking a callback resolver twice. */
|
|
129
|
+
private resolvedBuyer;
|
|
118
130
|
/**
|
|
119
|
-
* Returns true if this bundle should be hidden for the current
|
|
131
|
+
* Returns true if this bundle should be hidden for the current buyer.
|
|
120
132
|
* For "all" bundles, always returns false (visible). For "specific"
|
|
121
|
-
* bundles,
|
|
122
|
-
*
|
|
133
|
+
* bundles, visibility needs a matching signal: the `country` attribute
|
|
134
|
+
* against the bundle's projected country codes (retail markets), the
|
|
135
|
+
* resolved buyer's companyLocationId against its projected company
|
|
136
|
+
* locations (B2B markets), or a legacy `market-id` match.
|
|
123
137
|
*/
|
|
124
138
|
private isMarketHidden;
|
|
125
139
|
private fetchBundle;
|
package/dist/index.d.ts
CHANGED
|
@@ -109,17 +109,31 @@ declare class LimeBundleElement extends HTMLElement {
|
|
|
109
109
|
private get country();
|
|
110
110
|
private get language();
|
|
111
111
|
private get marketId();
|
|
112
|
+
/**
|
|
113
|
+
* Store→presentment currency rate. Merchant-configured amounts
|
|
114
|
+
* (fixed_amount / flat_price values, volume tier amounts) are stored in
|
|
115
|
+
* the shop's store currency; set this to the buyer's currency rate so
|
|
116
|
+
* quoted sale prices match what the checkout's discount function
|
|
117
|
+
* charges. Anything unparseable or non-positive falls back to 1 —
|
|
118
|
+
* no conversion — via `normalizeCurrencyRate`.
|
|
119
|
+
*/
|
|
120
|
+
private get currencyRate();
|
|
112
121
|
/**
|
|
113
122
|
* Returns the @inContext-wrapped query when any context field is set;
|
|
114
123
|
* otherwise the plain query. Keeps responses publicly cacheable when
|
|
115
124
|
* no buyer/country/language is set.
|
|
116
125
|
*/
|
|
117
126
|
private wrapQueryForContext;
|
|
127
|
+
/** Buyer resolved once per fetch so the market gate can read the
|
|
128
|
+
* company location without invoking a callback resolver twice. */
|
|
129
|
+
private resolvedBuyer;
|
|
118
130
|
/**
|
|
119
|
-
* Returns true if this bundle should be hidden for the current
|
|
131
|
+
* Returns true if this bundle should be hidden for the current buyer.
|
|
120
132
|
* For "all" bundles, always returns false (visible). For "specific"
|
|
121
|
-
* bundles,
|
|
122
|
-
*
|
|
133
|
+
* bundles, visibility needs a matching signal: the `country` attribute
|
|
134
|
+
* against the bundle's projected country codes (retail markets), the
|
|
135
|
+
* resolved buyer's companyLocationId against its projected company
|
|
136
|
+
* locations (B2B markets), or a legacy `market-id` match.
|
|
123
137
|
*/
|
|
124
138
|
private isMarketHidden;
|
|
125
139
|
private fetchBundle;
|
package/dist/index.js
CHANGED
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
CART_LINES_REMOVE_MUTATION,
|
|
10
10
|
SHOP_SETTINGS_QUERY,
|
|
11
11
|
parseMetaobjectBundle,
|
|
12
|
+
convertBundleToPresentment,
|
|
12
13
|
observeImpression,
|
|
13
14
|
reportImpression,
|
|
14
15
|
reportAddToCart,
|
|
@@ -16,7 +17,7 @@ import {
|
|
|
16
17
|
sanitizeCustomCss,
|
|
17
18
|
hasInContext,
|
|
18
19
|
withInContext,
|
|
19
|
-
|
|
20
|
+
isVisibleToBuyer,
|
|
20
21
|
getVisitorId,
|
|
21
22
|
resolveAbTests
|
|
22
23
|
} from "@lime-bundles/core";
|
|
@@ -7220,7 +7221,8 @@ var LimeBundleElement = class extends HTMLElement {
|
|
|
7220
7221
|
"locale",
|
|
7221
7222
|
"country",
|
|
7222
7223
|
"language",
|
|
7223
|
-
"market-id"
|
|
7224
|
+
"market-id",
|
|
7225
|
+
"currency-rate"
|
|
7224
7226
|
];
|
|
7225
7227
|
/**
|
|
7226
7228
|
* B2B buyer identity. Set programmatically — `element.buyer = {...}` or
|
|
@@ -7275,7 +7277,7 @@ var LimeBundleElement = class extends HTMLElement {
|
|
|
7275
7277
|
}
|
|
7276
7278
|
attributeChangedCallback(name, oldValue, newValue) {
|
|
7277
7279
|
if (oldValue === newValue || !this.isConnected) return;
|
|
7278
|
-
if (name === "bundle-gid" || name === "product-handle" || name === "product-id" || name === "shop-domain" || name === "storefront-token") {
|
|
7280
|
+
if (name === "bundle-gid" || name === "product-handle" || name === "product-id" || name === "shop-domain" || name === "storefront-token" || name === "currency-rate") {
|
|
7279
7281
|
if (this.shopDomain && this.storefrontToken) {
|
|
7280
7282
|
this.fetchBundle();
|
|
7281
7283
|
}
|
|
@@ -7318,6 +7320,17 @@ var LimeBundleElement = class extends HTMLElement {
|
|
|
7318
7320
|
get marketId() {
|
|
7319
7321
|
return this.getAttribute("market-id") ?? void 0;
|
|
7320
7322
|
}
|
|
7323
|
+
/**
|
|
7324
|
+
* Store→presentment currency rate. Merchant-configured amounts
|
|
7325
|
+
* (fixed_amount / flat_price values, volume tier amounts) are stored in
|
|
7326
|
+
* the shop's store currency; set this to the buyer's currency rate so
|
|
7327
|
+
* quoted sale prices match what the checkout's discount function
|
|
7328
|
+
* charges. Anything unparseable or non-positive falls back to 1 —
|
|
7329
|
+
* no conversion — via `normalizeCurrencyRate`.
|
|
7330
|
+
*/
|
|
7331
|
+
get currencyRate() {
|
|
7332
|
+
return this.getAttribute("currency-rate") ?? void 0;
|
|
7333
|
+
}
|
|
7321
7334
|
/**
|
|
7322
7335
|
* Returns the @inContext-wrapped query when any context field is set;
|
|
7323
7336
|
* otherwise the plain query. Keeps responses publicly cacheable when
|
|
@@ -7332,14 +7345,23 @@ var LimeBundleElement = class extends HTMLElement {
|
|
|
7332
7345
|
buyer: this.buyer
|
|
7333
7346
|
}) ? withInContext(query) : query;
|
|
7334
7347
|
}
|
|
7348
|
+
/** Buyer resolved once per fetch so the market gate can read the
|
|
7349
|
+
* company location without invoking a callback resolver twice. */
|
|
7350
|
+
resolvedBuyer = void 0;
|
|
7335
7351
|
/**
|
|
7336
|
-
* Returns true if this bundle should be hidden for the current
|
|
7352
|
+
* Returns true if this bundle should be hidden for the current buyer.
|
|
7337
7353
|
* For "all" bundles, always returns false (visible). For "specific"
|
|
7338
|
-
* bundles,
|
|
7339
|
-
*
|
|
7354
|
+
* bundles, visibility needs a matching signal: the `country` attribute
|
|
7355
|
+
* against the bundle's projected country codes (retail markets), the
|
|
7356
|
+
* resolved buyer's companyLocationId against its projected company
|
|
7357
|
+
* locations (B2B markets), or a legacy `market-id` match.
|
|
7340
7358
|
*/
|
|
7341
7359
|
isMarketHidden(bundle) {
|
|
7342
|
-
return !
|
|
7360
|
+
return !isVisibleToBuyer(bundle, {
|
|
7361
|
+
marketId: this.marketId,
|
|
7362
|
+
countryCode: this.country,
|
|
7363
|
+
companyLocationId: this.resolvedBuyer?.companyLocationId
|
|
7364
|
+
});
|
|
7343
7365
|
}
|
|
7344
7366
|
async fetchBundle() {
|
|
7345
7367
|
if (!this.shopDomain || !this.storefrontToken) {
|
|
@@ -7352,12 +7374,17 @@ var LimeBundleElement = class extends HTMLElement {
|
|
|
7352
7374
|
const controller = new AbortController();
|
|
7353
7375
|
this.abortController = controller;
|
|
7354
7376
|
this.renderLoading();
|
|
7377
|
+
try {
|
|
7378
|
+
this.resolvedBuyer = typeof this.buyer === "function" ? await this.buyer() : this.buyer;
|
|
7379
|
+
} catch {
|
|
7380
|
+
this.resolvedBuyer = void 0;
|
|
7381
|
+
}
|
|
7355
7382
|
const client = createStorefrontClient({
|
|
7356
7383
|
shopDomain: this.shopDomain,
|
|
7357
7384
|
accessToken: this.storefrontToken,
|
|
7358
7385
|
country: this.country,
|
|
7359
7386
|
language: this.language,
|
|
7360
|
-
buyer: this.
|
|
7387
|
+
buyer: this.resolvedBuyer
|
|
7361
7388
|
});
|
|
7362
7389
|
try {
|
|
7363
7390
|
let bundlePromise;
|
|
@@ -7422,7 +7449,7 @@ var LimeBundleElement = class extends HTMLElement {
|
|
|
7422
7449
|
data.metaobject.id,
|
|
7423
7450
|
data.metaobject.fields
|
|
7424
7451
|
);
|
|
7425
|
-
this.bundles = parsed && !this.isMarketHidden(parsed) ? [parsed] : [];
|
|
7452
|
+
this.bundles = parsed && !this.isMarketHidden(parsed) ? [convertBundleToPresentment(parsed, this.currencyRate)] : [];
|
|
7426
7453
|
}
|
|
7427
7454
|
async fetchProductBundles(client, signal, productHandle) {
|
|
7428
7455
|
const data = await client.query(
|
|
@@ -7438,7 +7465,9 @@ var LimeBundleElement = class extends HTMLElement {
|
|
|
7438
7465
|
const bundles = [];
|
|
7439
7466
|
for (const ref of refs) {
|
|
7440
7467
|
const parsed = parseMetaobjectBundle(ref.id, ref.fields);
|
|
7441
|
-
if (parsed && !this.isMarketHidden(parsed))
|
|
7468
|
+
if (parsed && !this.isMarketHidden(parsed)) {
|
|
7469
|
+
bundles.push(convertBundleToPresentment(parsed, this.currencyRate));
|
|
7470
|
+
}
|
|
7442
7471
|
}
|
|
7443
7472
|
this.bundles = resolveAbTests(bundles, getVisitorId());
|
|
7444
7473
|
}
|