@liquidcommerce/elements-sdk 2.7.30 → 2.7.31
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 +7535 -7535
- package/dist/index.esm.js +11797 -11674
- package/dist/types/interfaces/injection.interface.d.ts +1 -0
- package/dist/types/modules/product-list/components/product-list-card.component.d.ts +1 -0
- package/dist/types/modules/product-list/product-list-order.utils.d.ts +3 -0
- package/dist/types/modules/product-list/product-list.component.d.ts +5 -0
- package/docs/v1/api/injection-methods.md +34 -0
- package/docs/v1/api/typescript-types.md +1 -0
- package/docs/v1/guides/product-list-component.md +87 -0
- package/package.json +1 -1
|
@@ -25,6 +25,7 @@ export declare class ProductListCardComponent extends BaseComponent<IProductList
|
|
|
25
25
|
private getSelectedSize;
|
|
26
26
|
private getDisplayPrice;
|
|
27
27
|
protected template(): HTMLElement[];
|
|
28
|
+
protected afterRender(): void;
|
|
28
29
|
private updatePriceDisplay;
|
|
29
30
|
private updateFulfillmentText;
|
|
30
31
|
private updateImage;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { IPLProductStore } from '@/core/store/interfaces/product-list.interface';
|
|
2
|
+
export declare function buildProductOrderIndex(productOrder: string[]): Map<string, number>;
|
|
3
|
+
export declare function sortProductsByOrder(products: IPLProductStore[], orderIndex: Map<string, number>): IPLProductStore[];
|
|
@@ -8,6 +8,7 @@ export interface IProductListComponentParams {
|
|
|
8
8
|
columns: number;
|
|
9
9
|
filters: ProductListFilterType[];
|
|
10
10
|
productUrl?: PLCProductUrl;
|
|
11
|
+
productOrder?: string[];
|
|
11
12
|
}
|
|
12
13
|
export declare class ProductListComponent extends BaseComponent<IProductListComponentParams, IProductListComponent> {
|
|
13
14
|
private products;
|
|
@@ -17,6 +18,7 @@ export declare class ProductListComponent extends BaseComponent<IProductListComp
|
|
|
17
18
|
private loadingState;
|
|
18
19
|
private scrollObserver;
|
|
19
20
|
private initializationPromise;
|
|
21
|
+
private productOrderIndex;
|
|
20
22
|
private unsubscribeFromState?;
|
|
21
23
|
get hostClasses(): string[];
|
|
22
24
|
constructor();
|
|
@@ -24,6 +26,8 @@ export declare class ProductListComponent extends BaseComponent<IProductListComp
|
|
|
24
26
|
protected afterRender(): void;
|
|
25
27
|
disconnected(): void;
|
|
26
28
|
private initializeComponent;
|
|
29
|
+
private getProductOrderIndex;
|
|
30
|
+
private hasProductOrder;
|
|
27
31
|
private toProductArray;
|
|
28
32
|
private setLoadingState;
|
|
29
33
|
private renderCurrentState;
|
|
@@ -35,6 +39,7 @@ export declare class ProductListComponent extends BaseComponent<IProductListComp
|
|
|
35
39
|
private lastAnnouncedSentinelState;
|
|
36
40
|
private renderProducts;
|
|
37
41
|
private announceResultCount;
|
|
42
|
+
private insertOrderedProducts;
|
|
38
43
|
private appendNewProducts;
|
|
39
44
|
private setupInfiniteScroll;
|
|
40
45
|
private createScrollSentinel;
|
|
@@ -134,6 +134,7 @@ interface IInjectProductListParams {
|
|
|
134
134
|
columns?: number; // Default: 4
|
|
135
135
|
filters?: ProductListFilterType[];
|
|
136
136
|
productUrl?: PLCProductUrl; // string template OR Record<identifier, url> map
|
|
137
|
+
productOrder?: string[]; // display order, by UPC or grouping ID
|
|
137
138
|
}
|
|
138
139
|
|
|
139
140
|
// String template: replace {upc} or {grouping} per product.
|
|
@@ -177,6 +178,39 @@ await client.injectProductList({
|
|
|
177
178
|
});
|
|
178
179
|
```
|
|
179
180
|
|
|
181
|
+
### Example — explicit product order
|
|
182
|
+
|
|
183
|
+
`productOrder` sets the display order of the grid. Entries are the same product
|
|
184
|
+
identifiers `productUrl` maps and `injectProductElement` accepts — a UPC (any size
|
|
185
|
+
of the product) or a `salsifyGrouping` ID — and may be mixed freely.
|
|
186
|
+
|
|
187
|
+
```javascript
|
|
188
|
+
await client.injectProductList({
|
|
189
|
+
containerId: 'products',
|
|
190
|
+
slug: 'best-sellers',
|
|
191
|
+
productOrder: [
|
|
192
|
+
'00832889005513',
|
|
193
|
+
'GROUPING-33277',
|
|
194
|
+
'00619947000020',
|
|
195
|
+
],
|
|
196
|
+
});
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
It **reorders, it does not select.** The list's `slug` still decides which products
|
|
200
|
+
are returned; an identifier for a product outside the list matches nothing. Products
|
|
201
|
+
the array doesn't name render after the ones it does, in the order the API returned
|
|
202
|
+
them, so a partial list reorders only what it names.
|
|
203
|
+
|
|
204
|
+
Ordering also applies across pagination: a product named early in the array takes its
|
|
205
|
+
place even if the API returns it on a later page. Each new page is spliced into the
|
|
206
|
+
existing grid rather than appended, so cards already on screen are never re-rendered
|
|
207
|
+
and the scroll position holds. If the curated set is small, size `rows × columns` to
|
|
208
|
+
cover it in one page so no scroll is needed at all.
|
|
209
|
+
|
|
210
|
+
> A search term or an applied filter re-queries the API for a narrower result set.
|
|
211
|
+
> `productOrder` is re-applied to whatever comes back, so named products keep their
|
|
212
|
+
> relative order among the results that survive.
|
|
213
|
+
|
|
180
214
|
---
|
|
181
215
|
|
|
182
216
|
## injectProductListSearch()
|
|
@@ -43,6 +43,7 @@ Use data attributes to configure the product list:
|
|
|
43
43
|
- `data-columns`: Number of columns (default: 4)
|
|
44
44
|
- `data-filters`: Comma-separated filter types
|
|
45
45
|
- `data-product-url`: URL pattern for product detail pages (optional)
|
|
46
|
+
- `data-product-order`: Comma-separated product identifiers setting the display order (optional) — see [Product Order](#product-order)
|
|
46
47
|
|
|
47
48
|
`data-product-url` accepts a string template with one of two placeholders:
|
|
48
49
|
- `{grouping}` — replaced with the product's salsifyGrouping ID
|
|
@@ -227,6 +228,66 @@ await client.injectProductList({
|
|
|
227
228
|
|
|
228
229
|
Total products per page = rows × columns (e.g., 5 × 4 = 20 products)
|
|
229
230
|
|
|
231
|
+
## Product Order
|
|
232
|
+
|
|
233
|
+
By default the grid renders products in the order the API returns them for the
|
|
234
|
+
list's slug. `productOrder` overrides that with an explicit order you control
|
|
235
|
+
from the page.
|
|
236
|
+
|
|
237
|
+
```javascript
|
|
238
|
+
await client.injectProductList({
|
|
239
|
+
containerId: 'products',
|
|
240
|
+
slug: 'my-collection-slug',
|
|
241
|
+
productOrder: [
|
|
242
|
+
'00832889005513',
|
|
243
|
+
'GROUPING-33277',
|
|
244
|
+
'00619947000020',
|
|
245
|
+
],
|
|
246
|
+
});
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
```html
|
|
250
|
+
<div
|
|
251
|
+
data-liquid-commerce-elements-products-list="my-collection-slug"
|
|
252
|
+
data-product-order="00832889005513,GROUPING-33277,00619947000020"
|
|
253
|
+
></div>
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
**Identifiers.** Each entry is a UPC or a `salsifyGrouping` ID — the same identifier
|
|
257
|
+
concept the [Product URL Map](#product-url-map) keys on and `injectProductElement`
|
|
258
|
+
accepts. The two forms mix freely in one array. A UPC identifies a single size, so
|
|
259
|
+
naming any size of a product positions that product.
|
|
260
|
+
|
|
261
|
+
**It reorders; it does not select.** The slug still decides which products the list
|
|
262
|
+
contains. An identifier for a product outside the list matches nothing, and no error
|
|
263
|
+
is raised. Products the array doesn't name render after the ones it does, keeping
|
|
264
|
+
their API order among themselves — so a partial list reorders only what it names.
|
|
265
|
+
|
|
266
|
+
**Pagination.** A product named early keeps its position even if the API returns it on
|
|
267
|
+
a later page. Each new page is spliced into the grid at the right slots rather than
|
|
268
|
+
appended, so cards already on screen are left untouched — scroll position and keyboard
|
|
269
|
+
focus survive loading a page. For a small curated set, size `rows × columns` to cover
|
|
270
|
+
it in a single page so no scroll is needed at all.
|
|
271
|
+
|
|
272
|
+
**Search and filters** re-query the API for a narrower result set. The order is
|
|
273
|
+
re-applied to whatever comes back, so named products keep their relative order among
|
|
274
|
+
the results that survive.
|
|
275
|
+
|
|
276
|
+
**Nothing about `productOrder` throws.** Ordering is presentational and the grid
|
|
277
|
+
renders fine without it, so a malformed value costs you the ordering and nothing
|
|
278
|
+
else — never the product list itself.
|
|
279
|
+
|
|
280
|
+
- An entry that isn't a non-empty string is skipped with a console warning, the way
|
|
281
|
+
an unrecognized `filters` value is. The surviving entries keep their relative
|
|
282
|
+
order, so the rest of your ordering still applies around the dropped one.
|
|
283
|
+
- A `productOrder` that isn't an array is ignored entirely with a warning, and the
|
|
284
|
+
list renders in the order the API returns.
|
|
285
|
+
|
|
286
|
+
> The warning goes through the SDK logger, which is silent in production and at the
|
|
287
|
+
> default `debugMode: 'none'`. On a live storefront a dropped entry produces no
|
|
288
|
+
> console output at all, so validate the array you generate rather than relying on
|
|
289
|
+
> the warning to surface a bad one.
|
|
290
|
+
|
|
230
291
|
## Infinite Scroll
|
|
231
292
|
|
|
232
293
|
### How It Works
|
|
@@ -274,6 +335,32 @@ Product card images automatically have their white/near-white backgrounds remove
|
|
|
274
335
|
|
|
275
336
|
**Click on image:** Navigate to the configured `productUrl` (only when `productUrl` is set — otherwise the image is not a link)
|
|
276
337
|
|
|
338
|
+
### Card Identifiers
|
|
339
|
+
|
|
340
|
+
Each `product-list-card-lc` host carries the product's identifiers as data
|
|
341
|
+
attributes, so a card can be traced back to catalogue data while inspecting the
|
|
342
|
+
page:
|
|
343
|
+
|
|
344
|
+
```html
|
|
345
|
+
<product-list-card-lc data-grouping="GROUPING-33277" data-upc="00832889005513">
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
- `data-grouping` — the product's `salsifyGrouping` ID. Fixed for the life of the card.
|
|
349
|
+
- `data-upc` — the **selected size's** UPC, the same value `{upc}` resolves to in a
|
|
350
|
+
`productUrl` template. It updates when the shopper changes size.
|
|
351
|
+
|
|
352
|
+
Both use the identifier forms accepted everywhere else in the SDK, so a value read
|
|
353
|
+
off a card can be pasted straight into `productOrder`, a `productUrl` map key, or
|
|
354
|
+
`injectProductElement`.
|
|
355
|
+
|
|
356
|
+
> **These are for inspection, not for scripting.** Cards render inside the SDK's
|
|
357
|
+
> shadow root, which is **always closed in production** — `openShadowDom` is forced
|
|
358
|
+
> to `false` there and only has effect in development. Chrome DevTools displays
|
|
359
|
+
> closed shadow roots, so the attributes are visible when inspecting the page, but
|
|
360
|
+
> `document.querySelector('[data-upc]')` from partner JavaScript will not reach them
|
|
361
|
+
> on a live storefront. To react to card activity from your own code, use the
|
|
362
|
+
> [events](#events) instead.
|
|
363
|
+
|
|
277
364
|
## Customization
|
|
278
365
|
|
|
279
366
|
### Theme Configuration
|
package/package.json
CHANGED