@liquidcommerce/elements-sdk 2.6.0-beta.74 → 2.6.0-beta.76
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/index.checkout.esm.js +7065 -7083
- package/dist/index.esm.js +11241 -11179
- package/dist/types/auto-initialize/shared-utils.d.ts +3 -0
- package/dist/types/clients/helpers.d.ts +0 -1
- package/dist/types/interfaces/configs/product-list.interface.d.ts +3 -1
- package/dist/types/interfaces/configs/product.interface.d.ts +2 -2
- package/dist/types/interfaces/injection.interface.d.ts +2 -1
- package/dist/types/modules/product-list/components/product-list-card.component.d.ts +7 -1
- package/dist/types/modules/product-list/product-list.component.d.ts +2 -1
- package/docs/v1/api/injection-methods.md +25 -3
- package/docs/v1/api/typescript-types.md +17 -1
- package/docs/v1/examples/advanced-patterns.md +1 -1
- package/docs/v1/guides/product-list-component.md +85 -9
- package/package.json +4 -4
|
@@ -28,11 +28,14 @@ export declare const SHARED_ATTR: {
|
|
|
28
28
|
readonly JSON_SCRIPT: {
|
|
29
29
|
readonly DEVELOPMENT: "data-liquid-commerce-elements-development";
|
|
30
30
|
readonly CUSTOM_THEME: "data-liquid-commerce-elements-custom-theme";
|
|
31
|
+
readonly PRODUCT_URLS: "data-liquid-commerce-elements-product-urls";
|
|
31
32
|
};
|
|
32
33
|
};
|
|
34
|
+
export type ProductUrlsConfig = Record<string, Record<string, string>>;
|
|
33
35
|
export declare function startsWithLcePrefix(value: string | null): boolean;
|
|
34
36
|
export declare function getDevelopmentConfigs(): ILiquidCommerceElementsDevelopmentConfig | undefined;
|
|
35
37
|
export declare function getCustomThemeConfig(): IClientCustomThemeConfig | undefined;
|
|
38
|
+
export declare function getProductUrlsConfig(): ProductUrlsConfig | undefined;
|
|
36
39
|
export declare function triggerAutoInit(initFunction: () => Promise<void>, errorPrefix: string): void;
|
|
37
40
|
export declare function setupCheckout(script: HTMLScriptElement, injectFn: (params: IInjectCheckoutParams) => Promise<IInjectedComponent | null>, exitCheckoutFn: () => void, options: {
|
|
38
41
|
errorPrefix: string;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { type ComponentType } from '@/enums';
|
|
2
|
-
export declare function applyConfigDefaults<T extends Record<string, any>>(data: T): T;
|
|
3
2
|
export declare function normalizeProductListLists<T extends Record<string, any>>(data: T): T;
|
|
4
3
|
export declare function deepMergeConfigs<T extends Record<string, any>>(target: T, source: Partial<T>, currentPath?: string): T;
|
|
5
4
|
export declare const layoutFieldToComponentTypes: Map<string, ComponentType[]>;
|
|
@@ -3,6 +3,7 @@ import type { ProductListFilterType } from '@/interfaces/injection.interface';
|
|
|
3
3
|
export type PLCPresentationModeType = 'drawer' | 'modal';
|
|
4
4
|
export type PLCListType = 'curated' | 'dynamic';
|
|
5
5
|
export type PLCCardStyle = 'card' | 'ghost';
|
|
6
|
+
export type PLCProductUrl = string | Record<string, string>;
|
|
6
7
|
export interface IPLCProductCard {
|
|
7
8
|
style: PLCCardStyle;
|
|
8
9
|
cornerRadius: string;
|
|
@@ -16,6 +17,8 @@ export interface IPLCProductCard {
|
|
|
16
17
|
showQuantityCounter: boolean;
|
|
17
18
|
enablePreCart: boolean;
|
|
18
19
|
showCollectionTags: boolean;
|
|
20
|
+
productUrl: PLCProductUrl | null;
|
|
21
|
+
noAvailabilityText: string;
|
|
19
22
|
}
|
|
20
23
|
export interface IPLCList {
|
|
21
24
|
type: PLCListType;
|
|
@@ -27,7 +30,6 @@ export interface IPLCList {
|
|
|
27
30
|
availableFilters: ProductListFilterType[];
|
|
28
31
|
rows: number;
|
|
29
32
|
columns: number;
|
|
30
|
-
productUrl: string | null;
|
|
31
33
|
}
|
|
32
34
|
export interface IProductListLayout {
|
|
33
35
|
lists: IPLCList[];
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import type { DeepPartial } from '@/interfaces/config.interface';
|
|
2
2
|
export type FulfillmentDisplayType = 'carousel' | 'popup';
|
|
3
|
-
export type
|
|
3
|
+
export type DescriptionPositionType = 'above' | 'below';
|
|
4
4
|
export interface IProductLayout {
|
|
5
5
|
showImages: boolean;
|
|
6
6
|
showOnlyMainImage: boolean;
|
|
7
7
|
showTitle: boolean;
|
|
8
8
|
showDescription: boolean;
|
|
9
|
-
descriptionPosition:
|
|
9
|
+
descriptionPosition: DescriptionPositionType;
|
|
10
10
|
showQuantityCounter: boolean;
|
|
11
11
|
showOffHours: boolean;
|
|
12
12
|
quantityCounterStyle: 'outlined' | 'ghost';
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { PRODUCT_LIST_FILTER_TYPES } from '@/constants';
|
|
2
2
|
import type { ComponentType } from '@/enums';
|
|
3
|
+
import type { PLCProductUrl } from '@/interfaces/configs/product-list.interface';
|
|
3
4
|
import type { IAddressOptions } from '@/modules/address/address.interface';
|
|
4
5
|
export interface IInjectProductElement {
|
|
5
6
|
containerId: string;
|
|
@@ -12,7 +13,7 @@ export interface IInjectProductListParams {
|
|
|
12
13
|
rows?: number;
|
|
13
14
|
columns?: number;
|
|
14
15
|
filters?: ProductListFilterType[];
|
|
15
|
-
productUrl?:
|
|
16
|
+
productUrl?: PLCProductUrl;
|
|
16
17
|
}
|
|
17
18
|
export interface IInjectProductListSearchParams {
|
|
18
19
|
containerId: string;
|
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
import { BaseComponent, type IOnStoreChanged } from '@/core/base-component.service';
|
|
2
2
|
import type { IProductListComponent } from '@/interfaces/configs';
|
|
3
|
+
import type { PLCProductUrl } from '@/interfaces/configs/product-list.interface';
|
|
3
4
|
export interface IProductListCardParams {
|
|
4
5
|
slug: string;
|
|
5
6
|
productId: string;
|
|
6
|
-
productUrl?:
|
|
7
|
+
productUrl?: PLCProductUrl;
|
|
7
8
|
}
|
|
8
9
|
export declare class ProductListCardComponent extends BaseComponent<IProductListCardParams, IProductListComponent> {
|
|
9
10
|
private imageElement;
|
|
10
11
|
private priceElement;
|
|
11
12
|
private personalizeElement;
|
|
12
13
|
private fulfillmentTextElement;
|
|
14
|
+
private fulfillmentWrapperElement;
|
|
13
15
|
private addToCartButton;
|
|
16
|
+
private noAvailabilityElement;
|
|
14
17
|
private previousSelectedSizeId;
|
|
15
18
|
private previousSelectedFulfillmentId;
|
|
16
19
|
constructor();
|
|
@@ -27,10 +30,13 @@ export declare class ProductListCardComponent extends BaseComponent<IProductList
|
|
|
27
30
|
private updateImage;
|
|
28
31
|
private updatePersonalizeVisibility;
|
|
29
32
|
private updateAddToCartButton;
|
|
33
|
+
private syncFulfillmentWrapperContent;
|
|
30
34
|
private generateProductUrl;
|
|
31
35
|
private createImageSection;
|
|
32
36
|
private createContentSection;
|
|
37
|
+
private createNoAvailabilityMessage;
|
|
33
38
|
private createFulfillmentSectionWrapper;
|
|
39
|
+
private createDeliveryOptionsButton;
|
|
34
40
|
private createFulfillmentTextSection;
|
|
35
41
|
private createAddToCartSection;
|
|
36
42
|
}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { BaseComponent, type IOnStoreChanged } from '@/core/base-component.service';
|
|
2
2
|
import type { IProductListComponent } from '@/interfaces/configs';
|
|
3
|
+
import type { PLCProductUrl } from '@/interfaces/configs/product-list.interface';
|
|
3
4
|
import type { ProductListFilterType } from '@/interfaces/injection.interface';
|
|
4
5
|
export interface IProductListComponentParams {
|
|
5
6
|
slug: string;
|
|
6
7
|
rows: number;
|
|
7
8
|
columns: number;
|
|
8
9
|
filters: ProductListFilterType[];
|
|
9
|
-
productUrl?:
|
|
10
|
+
productUrl?: PLCProductUrl;
|
|
10
11
|
}
|
|
11
12
|
export declare class ProductListComponent extends BaseComponent<IProductListComponentParams, IProductListComponent> {
|
|
12
13
|
private products;
|
|
@@ -130,11 +130,15 @@ interface IInjectProductListParams {
|
|
|
130
130
|
rows?: number; // Default: 3
|
|
131
131
|
columns?: number; // Default: 4
|
|
132
132
|
filters?: ProductListFilterType[];
|
|
133
|
-
productUrl?:
|
|
133
|
+
productUrl?: PLCProductUrl; // string template OR Record<identifier, url> map
|
|
134
134
|
}
|
|
135
|
+
|
|
136
|
+
// String template: replace {upc} or {grouping} per product.
|
|
137
|
+
// Map: keys are product identifiers (UPC or salsifyGrouping ID); UPC checked first.
|
|
138
|
+
type PLCProductUrl = string | Record<string, string>;
|
|
135
139
|
```
|
|
136
140
|
|
|
137
|
-
### Example
|
|
141
|
+
### Example — string template
|
|
138
142
|
|
|
139
143
|
```javascript
|
|
140
144
|
await client.injectProductList({
|
|
@@ -143,7 +147,25 @@ await client.injectProductList({
|
|
|
143
147
|
rows: 4,
|
|
144
148
|
columns: 3,
|
|
145
149
|
filters: ['price', 'brands', 'categories'],
|
|
146
|
-
productUrl: '/product/{
|
|
150
|
+
productUrl: '/product/{grouping}'
|
|
151
|
+
});
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Example — URL map (partner-owned dedicated PDPs)
|
|
155
|
+
|
|
156
|
+
Use this form when each product has a hand-curated URL that can't be derived
|
|
157
|
+
from a single `{upc}` or `{grouping}` token. See the
|
|
158
|
+
[Product List guide](../guides/product-list-component.md#product-url-map) for
|
|
159
|
+
the equivalent declarative `<script type="application/json">` pattern.
|
|
160
|
+
|
|
161
|
+
```javascript
|
|
162
|
+
await client.injectProductList({
|
|
163
|
+
containerId: 'products',
|
|
164
|
+
slug: 'best-sellers',
|
|
165
|
+
productUrl: {
|
|
166
|
+
'GROUPING-33277': '/wines/macallan-12-special-edition',
|
|
167
|
+
'00832889005513': '/spirits/cabernet-2018-club-only',
|
|
168
|
+
},
|
|
147
169
|
});
|
|
148
170
|
```
|
|
149
171
|
|
|
@@ -190,10 +190,26 @@ interface IInjectProductListParams {
|
|
|
190
190
|
rows?: number;
|
|
191
191
|
columns?: number;
|
|
192
192
|
filters?: ProductListFilterType[];
|
|
193
|
-
productUrl?:
|
|
193
|
+
productUrl?: PLCProductUrl;
|
|
194
194
|
}
|
|
195
195
|
```
|
|
196
196
|
|
|
197
|
+
### PLCProductUrl
|
|
198
|
+
|
|
199
|
+
```typescript
|
|
200
|
+
/**
|
|
201
|
+
* Product card link configuration.
|
|
202
|
+
*
|
|
203
|
+
* - String: template with `{upc}` (selected size's UPC) or `{grouping}`
|
|
204
|
+
* (product's salsifyGrouping ID). Replaced per product card.
|
|
205
|
+
* - Map: keyed by product identifier (UPC or salsifyGrouping ID — same
|
|
206
|
+
* identifier types accepted by `injectProductElement`). The card looks up
|
|
207
|
+
* UPC first, then grouping ID. Use this when partner PDPs have
|
|
208
|
+
* hand-curated URLs that aren't derivable from a single token.
|
|
209
|
+
*/
|
|
210
|
+
type PLCProductUrl = string | Record<string, string>;
|
|
211
|
+
```
|
|
212
|
+
|
|
197
213
|
### IInjectProductListSearchParams
|
|
198
214
|
|
|
199
215
|
```typescript
|
|
@@ -33,7 +33,7 @@ Use data attributes to configure the product list:
|
|
|
33
33
|
data-rows="3"
|
|
34
34
|
data-columns="4"
|
|
35
35
|
data-filters="price,brands,categories"
|
|
36
|
-
data-product-url="/product/{
|
|
36
|
+
data-product-url="/product/{grouping}"
|
|
37
37
|
></div>
|
|
38
38
|
```
|
|
39
39
|
|
|
@@ -44,7 +44,13 @@ Use data attributes to configure the product list:
|
|
|
44
44
|
- `data-filters`: Comma-separated filter types
|
|
45
45
|
- `data-product-url`: URL pattern for product detail pages (optional)
|
|
46
46
|
|
|
47
|
-
|
|
47
|
+
`data-product-url` accepts a string template with one of two placeholders:
|
|
48
|
+
- `{grouping}` — replaced with the product's salsifyGrouping ID
|
|
49
|
+
- `{upc}` — replaced with the selected size's UPC
|
|
50
|
+
|
|
51
|
+
If your PDP URLs aren't derivable from a single placeholder (e.g. each
|
|
52
|
+
product has a hand-curated marketing slug), use the
|
|
53
|
+
[Product URL Map](#product-url-map) instead.
|
|
48
54
|
|
|
49
55
|
### With Search and Filters
|
|
50
56
|
|
|
@@ -62,7 +68,7 @@ Separate containers for search and filters:
|
|
|
62
68
|
data-liquid-commerce-elements-products-list="my-collection-slug"
|
|
63
69
|
data-rows="4"
|
|
64
70
|
data-columns="3"
|
|
65
|
-
data-product-url="/products/{
|
|
71
|
+
data-product-url="/products/{grouping}"
|
|
66
72
|
></div>
|
|
67
73
|
```
|
|
68
74
|
|
|
@@ -80,7 +86,7 @@ await client.injectProductList({
|
|
|
80
86
|
rows: 3,
|
|
81
87
|
columns: 4,
|
|
82
88
|
filters: ['price', 'brands', 'categories', 'fulfillment'],
|
|
83
|
-
productUrl: '/product/{
|
|
89
|
+
productUrl: '/product/{grouping}'
|
|
84
90
|
});
|
|
85
91
|
|
|
86
92
|
// Inject search (optional)
|
|
@@ -213,7 +219,7 @@ Each product card shows:
|
|
|
213
219
|
|
|
214
220
|
### Card Interaction
|
|
215
221
|
|
|
216
|
-
**Click on card:** Navigate to product detail page (if `productUrl` configured)
|
|
222
|
+
**Click on card:** Navigate to product detail page (if `productUrl` configured — see [Product URL Map](#product-url-map) for partner-owned PDP URLs that aren't derivable from a token).
|
|
217
223
|
|
|
218
224
|
**Quick Add:** Add product to cart directly from list view (if enabled)
|
|
219
225
|
|
|
@@ -298,7 +304,7 @@ See [Configuration Reference](../api/configuration.md#product-list-theme) for th
|
|
|
298
304
|
data-liquid-commerce-elements-products-list="whiskey-collection"
|
|
299
305
|
data-rows="4"
|
|
300
306
|
data-columns="3"
|
|
301
|
-
data-product-url="/whiskey/{
|
|
307
|
+
data-product-url="/whiskey/{grouping}"
|
|
302
308
|
></div>
|
|
303
309
|
</main>
|
|
304
310
|
</div>
|
|
@@ -339,13 +345,13 @@ const productType = getProductTypeFromData();
|
|
|
339
345
|
let urlPattern;
|
|
340
346
|
switch (productType) {
|
|
341
347
|
case 'whiskey':
|
|
342
|
-
urlPattern = '/spirits/whiskey/{
|
|
348
|
+
urlPattern = '/spirits/whiskey/{grouping}';
|
|
343
349
|
break;
|
|
344
350
|
case 'wine':
|
|
345
|
-
urlPattern = '/wine/{
|
|
351
|
+
urlPattern = '/wine/{grouping}';
|
|
346
352
|
break;
|
|
347
353
|
default:
|
|
348
|
-
urlPattern = '/products/{
|
|
354
|
+
urlPattern = '/products/{grouping}';
|
|
349
355
|
}
|
|
350
356
|
|
|
351
357
|
await client.injectProductList({
|
|
@@ -357,6 +363,76 @@ await client.injectProductList({
|
|
|
357
363
|
});
|
|
358
364
|
```
|
|
359
365
|
|
|
366
|
+
### Product URL Map
|
|
367
|
+
|
|
368
|
+
For partners whose PDPs have hand-curated URLs that aren't derivable from a
|
|
369
|
+
single placeholder (e.g. dedicated marketing pages, Shopify handles, WordPress
|
|
370
|
+
slugs), pass a **map** instead of a string template. Keys are product
|
|
371
|
+
identifiers — either a UPC or a salsifyGrouping ID, the same identifier types
|
|
372
|
+
accepted by `injectProductElement`. The card looks up UPC first, then grouping
|
|
373
|
+
ID; products not in the map render without a link.
|
|
374
|
+
|
|
375
|
+
#### Declarative — JSON script tag
|
|
376
|
+
|
|
377
|
+
Drop a single `<script type="application/json">` tag anywhere on the page,
|
|
378
|
+
keyed by list slug → identifier → URL. Generate it server-side from your CMS.
|
|
379
|
+
|
|
380
|
+
```html
|
|
381
|
+
<script data-liquid-commerce-elements-product-urls type="application/json">
|
|
382
|
+
{
|
|
383
|
+
"best-sellers": {
|
|
384
|
+
"GROUPING-33277": "/wines/macallan-12-special-edition",
|
|
385
|
+
"00832889005513": "/spirits/cabernet-2018-club-only"
|
|
386
|
+
},
|
|
387
|
+
"limited-releases": {
|
|
388
|
+
"GROUPING-78941": "/exclusive/pappy-23-allocation"
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
</script>
|
|
392
|
+
|
|
393
|
+
<div data-liquid-commerce-elements-products-list="best-sellers"></div>
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
When both `data-product-url` and a slug entry in this script are present for
|
|
397
|
+
the same list, the **map wins** — it's the more specific intent.
|
|
398
|
+
|
|
399
|
+
##### Shopify Liquid
|
|
400
|
+
|
|
401
|
+
```liquid
|
|
402
|
+
<script data-liquid-commerce-elements-product-urls type="application/json">
|
|
403
|
+
{
|
|
404
|
+
"best-sellers": {
|
|
405
|
+
{% for p in collections.best-sellers.products %}
|
|
406
|
+
"{{ p.metafields.lc.grouping_id }}": "{{ p.url }}"{% unless forloop.last %},{% endunless %}
|
|
407
|
+
{% endfor %}
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
</script>
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
##### WordPress / WooCommerce (PHP)
|
|
414
|
+
|
|
415
|
+
```php
|
|
416
|
+
<script data-liquid-commerce-elements-product-urls type="application/json">
|
|
417
|
+
<?= json_encode(['best-sellers' => $lc_identifier_to_pdp_url_map]) ?>
|
|
418
|
+
</script>
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
#### Programmatic
|
|
422
|
+
|
|
423
|
+
```javascript
|
|
424
|
+
await client.injectProductList({
|
|
425
|
+
containerId: 'products',
|
|
426
|
+
slug: 'best-sellers',
|
|
427
|
+
rows: 3,
|
|
428
|
+
columns: 4,
|
|
429
|
+
productUrl: {
|
|
430
|
+
'GROUPING-33277': '/wines/macallan-12-special-edition',
|
|
431
|
+
'00832889005513': '/spirits/cabernet-2018-club-only',
|
|
432
|
+
},
|
|
433
|
+
});
|
|
434
|
+
```
|
|
435
|
+
|
|
360
436
|
## Events
|
|
361
437
|
|
|
362
438
|
While product list events are primarily internal, you can listen for cart events when users add products:
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"description": "LiquidCommerce Elements SDK",
|
|
4
4
|
"license": "UNLICENSED",
|
|
5
5
|
"author": "LiquidCommerce Team",
|
|
6
|
-
"version": "2.6.0-beta.
|
|
6
|
+
"version": "2.6.0-beta.76",
|
|
7
7
|
"homepage": "https://docs.liquidcommerce.co/elements-sdk",
|
|
8
8
|
"repository": {
|
|
9
9
|
"type": "git",
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
},
|
|
15
15
|
"module": "./dist/index.esm.js",
|
|
16
16
|
"types": "./dist/types/index.d.ts",
|
|
17
|
-
"packageManager": "pnpm@10.33.
|
|
17
|
+
"packageManager": "pnpm@10.33.4",
|
|
18
18
|
"exports": {
|
|
19
19
|
".": {
|
|
20
20
|
"types": "./dist/types/index.d.ts",
|
|
@@ -77,7 +77,7 @@
|
|
|
77
77
|
"embeddable commerce"
|
|
78
78
|
],
|
|
79
79
|
"devDependencies": {
|
|
80
|
-
"@biomejs/biome": "^2.4.
|
|
80
|
+
"@biomejs/biome": "^2.4.14",
|
|
81
81
|
"@commitlint/cli": "^20.5.3",
|
|
82
82
|
"@commitlint/config-conventional": "^20.5.3",
|
|
83
83
|
"@rollup/plugin-alias": "^6.0.0",
|
|
@@ -97,7 +97,7 @@
|
|
|
97
97
|
"conventional-changelog": "^7.2.0",
|
|
98
98
|
"husky": "^9.1.7",
|
|
99
99
|
"process": "^0.11.10",
|
|
100
|
-
"rollup": "^4.60.
|
|
100
|
+
"rollup": "^4.60.3",
|
|
101
101
|
"rollup-obfuscator": "^4.1.1",
|
|
102
102
|
"rollup-plugin-typescript2": "^0.37.0",
|
|
103
103
|
"semantic-release": "^25.0.3",
|