@liquidcommerce/elements-sdk 2.6.0-beta.9 → 2.6.0-beta.91

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.
Files changed (226) hide show
  1. package/README.md +84 -2520
  2. package/dist/index.checkout.esm.js +16946 -0
  3. package/dist/index.esm.js +24448 -21193
  4. package/dist/ssr-stub.checkout.esm.js +18 -0
  5. package/dist/ssr-stub.esm.js +270 -0
  6. package/dist/types/auto-initialize/checkout.d.ts +2 -0
  7. package/dist/types/auto-initialize/shared-utils.d.ts +50 -0
  8. package/dist/types/{elements-base-client.d.ts → clients/base.d.ts} +15 -2
  9. package/dist/types/clients/builder.d.ts +3 -0
  10. package/dist/types/clients/checkout.d.ts +6 -0
  11. package/dist/types/{elements-client-helper.d.ts → clients/helpers.d.ts} +2 -1
  12. package/dist/types/clients/main.d.ts +3 -0
  13. package/dist/types/constants/core.constant.d.ts +2 -6
  14. package/dist/types/core/api/api-client.service.d.ts +20 -18
  15. package/dist/types/core/api/api-result.d.ts +19 -0
  16. package/dist/types/core/api/auth-client.service.d.ts +37 -13
  17. package/dist/types/core/api/http-client.service.d.ts +0 -8
  18. package/dist/types/core/base-component.service.d.ts +2 -1
  19. package/dist/types/core/client/actions/base-action.service.d.ts +22 -0
  20. package/dist/types/core/client/actions/client-address-action.service.d.ts +18 -0
  21. package/dist/types/core/client/actions/client-cart-action.service.d.ts +38 -0
  22. package/dist/types/core/client/actions/client-checkout-action.service.d.ts +69 -0
  23. package/dist/types/core/client/actions/client-product-action.service.d.ts +15 -0
  24. package/dist/types/core/client/client-action.service.d.ts +6 -74
  25. package/dist/types/core/client/client-config.service.d.ts +8 -5
  26. package/dist/types/core/google-tag-manager.service.d.ts +2 -1
  27. package/dist/types/core/logger/logger.service.d.ts +1 -1
  28. package/dist/types/core/pubsub/interfaces/address.interface.d.ts +3 -0
  29. package/dist/types/core/pubsub/interfaces/cart.interface.d.ts +1 -1
  30. package/dist/types/core/pubsub/interfaces/checkout.interface.d.ts +36 -51
  31. package/dist/types/core/pubsub/interfaces/core.interface.d.ts +11 -6
  32. package/dist/types/core/pubsub/pubsub.service.d.ts +1 -2
  33. package/dist/types/core/singleton-manager.service.d.ts +12 -8
  34. package/dist/types/core/store/interfaces/cart.interface.d.ts +2 -3
  35. package/dist/types/core/store/interfaces/checkout.interface.d.ts +18 -108
  36. package/dist/types/core/store/interfaces/core.interface.d.ts +12 -2
  37. package/dist/types/core/store/interfaces/metadata.interface.d.ts +11 -0
  38. package/dist/types/core/store/interfaces/product-list.interface.d.ts +30 -0
  39. package/dist/types/core/store/interfaces/product.interface.d.ts +1 -0
  40. package/dist/types/core/store/store.constant.d.ts +5 -0
  41. package/dist/types/core/store/store.service.d.ts +1 -0
  42. package/dist/types/core/telemetry/telemetry.service.d.ts +1 -0
  43. package/dist/types/enums/core.enum.d.ts +39 -1
  44. package/dist/types/enums/index.d.ts +0 -1
  45. package/dist/types/index.checkout.d.ts +8 -0
  46. package/dist/types/index.checkout.umd.d.ts +4 -0
  47. package/dist/types/index.d.ts +8 -3
  48. package/dist/types/interfaces/api/cart.interface.d.ts +12 -7
  49. package/dist/types/interfaces/api/checkout.interface.d.ts +239 -0
  50. package/dist/types/interfaces/api/index.d.ts +5 -0
  51. package/dist/types/interfaces/api/product-list.interface.d.ts +39 -0
  52. package/dist/types/interfaces/api/product.interface.d.ts +10 -4
  53. package/dist/types/interfaces/client.interface.d.ts +72 -0
  54. package/dist/types/interfaces/component.interface.d.ts +7 -0
  55. package/dist/types/interfaces/config.interface.d.ts +40 -0
  56. package/dist/types/interfaces/configs/address.interface.d.ts +1 -1
  57. package/dist/types/interfaces/configs/cart.interface.d.ts +1 -1
  58. package/dist/types/interfaces/configs/checkout.interface.d.ts +2 -1
  59. package/dist/types/interfaces/configs/global.interface.d.ts +5 -3
  60. package/dist/types/interfaces/configs/index.d.ts +1 -0
  61. package/dist/types/interfaces/configs/product-list.interface.d.ts +49 -0
  62. package/dist/types/interfaces/configs/product.interface.d.ts +3 -1
  63. package/dist/types/interfaces/injection.interface.d.ts +49 -0
  64. package/dist/types/modules/address/address.command.d.ts +2 -1
  65. package/dist/types/modules/address/styles/register-styles.d.ts +1 -0
  66. package/dist/types/modules/cart/cart.commands.d.ts +4 -4
  67. package/dist/types/modules/cart/styles/register-styles.d.ts +1 -0
  68. package/dist/types/modules/checkout/checkout.commands.d.ts +26 -10
  69. package/dist/types/modules/checkout/checkout.component.d.ts +2 -0
  70. package/dist/types/modules/checkout/components/checkout-billing.component.d.ts +2 -2
  71. package/dist/types/modules/checkout/components/checkout-completed.component.d.ts +3 -0
  72. package/dist/types/modules/checkout/components/checkout-header.component.d.ts +1 -0
  73. package/dist/types/modules/checkout/components/checkout-item-quantity.component.d.ts +3 -0
  74. package/dist/types/modules/checkout/components/checkout-items.component.d.ts +4 -3
  75. package/dist/types/modules/checkout/components/checkout-payment.component.d.ts +1 -1
  76. package/dist/types/modules/checkout/components/checkout-presale-countdown.component.d.ts +14 -1
  77. package/dist/types/modules/checkout/components/checkout-presale-expired.component.d.ts +7 -1
  78. package/dist/types/modules/checkout/components/checkout-stripe-form.component.d.ts +2 -1
  79. package/dist/types/modules/checkout/components/checkout-tips.component.d.ts +2 -2
  80. package/dist/types/modules/checkout/components/promo-pc-gc.component.d.ts +0 -2
  81. package/dist/types/modules/checkout/constant.d.ts +3 -0
  82. package/dist/types/modules/checkout/styles/register-styles.d.ts +1 -0
  83. package/dist/types/modules/product/components/product-add-to-cart-section.component.d.ts +1 -0
  84. package/dist/types/modules/product/components/product-description.component.d.ts +1 -0
  85. package/dist/types/modules/product/components/product-image-carousel.component.d.ts +3 -0
  86. package/dist/types/modules/product/components/product-options.component.d.ts +2 -1
  87. package/dist/types/modules/product/components/product-retailers-carousel.component.d.ts +3 -0
  88. package/dist/types/modules/product/components/product-retailers-popup-list.component.d.ts +5 -2
  89. package/dist/types/modules/product/product.commands.d.ts +3 -3
  90. package/dist/types/modules/product/styles/register-styles.d.ts +1 -0
  91. package/dist/types/modules/product-list/components/card-components/index.d.ts +5 -0
  92. package/dist/types/modules/product-list/components/card-components/product-badge.d.ts +9 -0
  93. package/dist/types/modules/product-list/components/card-components/product-button.d.ts +11 -0
  94. package/dist/types/modules/product-list/components/card-components/product-price-and-personalization.d.ts +13 -0
  95. package/dist/types/modules/product-list/components/card-components/product-quantity-selector.d.ts +10 -0
  96. package/dist/types/modules/product-list/components/card-components/product-sizes-list.d.ts +13 -0
  97. package/dist/types/modules/product-list/components/filter-components/index.d.ts +7 -0
  98. package/dist/types/modules/product-list/components/filter-components/product-list-apply-filter-button.d.ts +1 -0
  99. package/dist/types/modules/product-list/components/filter-components/product-list-chip.d.ts +5 -0
  100. package/dist/types/modules/product-list/components/filter-components/product-list-filters-chips.d.ts +13 -0
  101. package/dist/types/modules/product-list/components/filter-components/product-list-fulfillment-filter.d.ts +14 -0
  102. package/dist/types/modules/product-list/components/{product-list-filters-subcomponents/product-list-price-filter.components.d.ts → filter-components/product-list-price-filter.d.ts} +1 -1
  103. package/dist/types/modules/product-list/components/filter-components/product-list-toggle-filters.d.ts +7 -0
  104. package/dist/types/modules/product-list/components/index.d.ts +6 -2
  105. package/dist/types/modules/product-list/components/product-list-card-loading.component.d.ts +3 -1
  106. package/dist/types/modules/product-list/components/product-list-card.component.d.ts +36 -31
  107. package/dist/types/modules/product-list/components/product-list-engraving.component.d.ts +12 -0
  108. package/dist/types/modules/product-list/components/product-list-filters.component.d.ts +55 -36
  109. package/dist/types/modules/product-list/components/product-list-product-engraving-lines.component.d.ts +22 -0
  110. package/dist/types/modules/product-list/components/product-list-product-pre-cart.component.d.ts +50 -0
  111. package/dist/types/modules/product-list/components/product-list-search.component.d.ts +25 -0
  112. package/dist/types/modules/product-list/product-list-filter.utils.d.ts +8 -0
  113. package/dist/types/modules/product-list/product-list-query-params.utils.d.ts +3 -0
  114. package/dist/types/modules/product-list/product-list.commands.d.ts +23 -8
  115. package/dist/types/modules/product-list/product-list.component.d.ts +14 -47
  116. package/dist/types/modules/product-list/product-list.constants.d.ts +38 -0
  117. package/dist/types/modules/product-list/product-list.interface.d.ts +20 -35
  118. package/dist/types/modules/product-list/styles/product-list-card.style.d.ts +1 -0
  119. package/dist/types/modules/product-list/styles/product-list-filters.style.d.ts +1 -0
  120. package/dist/types/modules/product-list/styles/register-styles.d.ts +1 -0
  121. package/dist/types/modules/theme-provider/constants/component-groupings.d.ts +1 -0
  122. package/dist/types/modules/theme-provider/constants/css-variable-mappings.d.ts +1 -1
  123. package/dist/types/modules/theme-provider/services/style-registry.service.d.ts +16 -0
  124. package/dist/types/modules/theme-provider/services/stylesheet-generator.service.d.ts +0 -1
  125. package/dist/types/modules/theme-provider/styles/register-styles.d.ts +1 -0
  126. package/dist/types/modules/theme-provider/theme-provider.service.d.ts +2 -2
  127. package/dist/types/modules/ui-components/drawer/drawer.component.d.ts +1 -0
  128. package/dist/types/modules/ui-components/engraving/engraving-form.component.d.ts +6 -1
  129. package/dist/types/modules/ui-components/engraving/engraving-view.component.d.ts +6 -1
  130. package/dist/types/modules/ui-components/input/index.d.ts +0 -1
  131. package/dist/types/modules/ui-components/input/input.component.d.ts +8 -1
  132. package/dist/types/modules/ui-components/lce-element/lce-element.component.d.ts +2 -1
  133. package/dist/types/modules/ui-components/promo-code-ticker/promo-code-ticker.component.d.ts +1 -1
  134. package/dist/types/modules/ui-components/ui.commands.d.ts +5 -1
  135. package/dist/types/ssr/stub.checkout.d.ts +6 -0
  136. package/dist/types/ssr/stub.d.ts +10 -0
  137. package/dist/types/static/icon/check.icon.d.ts +2 -0
  138. package/dist/types/static/icon/index.d.ts +1 -0
  139. package/dist/types/utils/dom-compat.d.ts +2 -0
  140. package/dist/types/utils/format.d.ts +0 -14
  141. package/dist/types/utils/image-bg-removal.d.ts +3 -0
  142. package/dist/types/utils/product-selection.d.ts +16 -0
  143. package/dist/types/utils/product.d.ts +15 -0
  144. package/docs/v1/README.md +210 -0
  145. package/docs/v1/api/actions/address-actions.md +286 -0
  146. package/docs/v1/api/actions/cart-actions.md +357 -0
  147. package/docs/v1/api/actions/checkout-actions.md +525 -0
  148. package/docs/v1/api/actions/product-actions.md +204 -0
  149. package/docs/v1/api/client.md +517 -0
  150. package/docs/v1/api/configuration.md +532 -0
  151. package/docs/v1/api/injection-methods.md +292 -0
  152. package/docs/v1/api/typescript-types.md +419 -0
  153. package/docs/v1/api/ui-helpers.md +200 -0
  154. package/docs/v1/examples/advanced-patterns.md +199 -0
  155. package/docs/v1/examples/checkout-flow.md +90 -0
  156. package/docs/v1/examples/custom-theming.md +63 -0
  157. package/docs/v1/examples/multi-product-page.md +90 -0
  158. package/docs/v1/examples/simple-product-page.md +89 -0
  159. package/docs/v1/getting-started/concepts.md +502 -0
  160. package/docs/v1/getting-started/installation.md +328 -0
  161. package/docs/v1/getting-started/quick-start.md +405 -0
  162. package/docs/v1/guides/address-component.md +435 -0
  163. package/docs/v1/guides/best-practices.md +365 -0
  164. package/docs/v1/guides/cart-component.md +725 -0
  165. package/docs/v1/guides/checkout-component.md +670 -0
  166. package/docs/v1/guides/events.md +926 -0
  167. package/docs/v1/guides/product-component.md +731 -0
  168. package/docs/v1/guides/product-list-component.md +631 -0
  169. package/docs/v1/guides/theming.md +213 -0
  170. package/docs/v1/integration/angular.md +39 -0
  171. package/docs/v1/integration/laravel.md +41 -0
  172. package/docs/v1/integration/nextjs.md +69 -0
  173. package/docs/v1/integration/proxy-setup.md +106 -0
  174. package/docs/v1/integration/react.md +64 -0
  175. package/docs/v1/integration/vanilla-js.md +84 -0
  176. package/docs/v1/integration/vue.md +58 -0
  177. package/docs/v1/reference/browser-support.md +45 -0
  178. package/docs/v1/reference/error-handling.md +75 -0
  179. package/docs/v1/reference/performance.md +52 -0
  180. package/docs/v1/reference/troubleshooting.md +136 -0
  181. package/package.json +33 -37
  182. package/dist/types/elements-builder-client.d.ts +0 -2
  183. package/dist/types/elements-client.d.ts +0 -2
  184. package/dist/types/enums/cloud.enum.d.ts +0 -106
  185. package/dist/types/interfaces/cloud/catalog.interface.d.ts +0 -42
  186. package/dist/types/interfaces/cloud/checkout.interface.d.ts +0 -218
  187. package/dist/types/interfaces/cloud/core.interface.d.ts +0 -22
  188. package/dist/types/interfaces/cloud/index.d.ts +0 -4
  189. package/dist/types/interfaces/cloud/retailer.interface.d.ts +0 -67
  190. package/dist/types/interfaces/cloud/user.interface.d.ts +0 -100
  191. package/dist/types/interfaces/core.interface.d.ts +0 -111
  192. package/dist/types/modules/checkout/components/checkout.type.d.ts +0 -4
  193. package/dist/types/modules/product-list/components/product-list-filters-subcomponents/index.d.ts +0 -6
  194. package/dist/types/modules/product-list/components/product-list-filters-subcomponents/product-list-apply-filter-button.component.d.ts +0 -1
  195. package/dist/types/modules/product-list/components/product-list-filters-subcomponents/product-list-delivery-options-filter.components.d.ts +0 -16
  196. package/dist/types/modules/product-list/components/product-list-filters-subcomponents/product-list-search.component.d.ts +0 -16
  197. package/dist/types/modules/product-list/components/product-list-filters-subcomponents/product-list-toggle-filters.components.d.ts +0 -18
  198. package/dist/types/modules/theme-provider/styles/address/index.d.ts +0 -1
  199. package/dist/types/modules/theme-provider/styles/cart/index.d.ts +0 -1
  200. package/dist/types/modules/theme-provider/styles/checkout/index.d.ts +0 -1
  201. package/dist/types/modules/theme-provider/styles/product/index.d.ts +0 -3
  202. package/dist/types/modules/theme-provider/styles/product-list/index.d.ts +0 -1
  203. package/dist/types/modules/theme-provider/styles/ui/index.d.ts +0 -3
  204. package/dist/types/modules/ui-components/input/birthdate-input.component.d.ts +0 -53
  205. package/dist/types/utils/helper.d.ts +0 -28
  206. package/docs/ACTIONS.md +0 -1300
  207. package/docs/BROWSER_SUPPORT.md +0 -279
  208. package/docs/CONFIGURATION.md +0 -853
  209. package/docs/DOCUMENTATION_INDEX.md +0 -311
  210. package/docs/EVENTS.md +0 -798
  211. package/docs/PROXY.md +0 -228
  212. package/docs/THEMING.md +0 -592
  213. package/docs/TROUBLESHOOTING.md +0 -793
  214. package/umd/elements.js +0 -1
  215. /package/dist/types/{auto-initialize.d.ts → auto-initialize/main.d.ts} +0 -0
  216. /package/dist/types/modules/{theme-provider/styles/address → address/styles}/address.style.d.ts +0 -0
  217. /package/dist/types/modules/{theme-provider/styles/cart → cart/styles}/cart.style.d.ts +0 -0
  218. /package/dist/types/modules/{theme-provider/styles/checkout → checkout/styles}/checkout.style.d.ts +0 -0
  219. /package/dist/types/modules/{theme-provider/styles/product → product/styles}/image-carousel.style.d.ts +0 -0
  220. /package/dist/types/modules/{theme-provider/styles/product → product/styles}/product.style.d.ts +0 -0
  221. /package/dist/types/modules/{theme-provider/styles/product → product/styles}/retailers.style.d.ts +0 -0
  222. /package/dist/types/modules/product-list/components/{product-list-filters-subcomponents/product-list-checkbox-filter.components.d.ts → filter-components/product-list-checkbox-filter.d.ts} +0 -0
  223. /package/dist/types/modules/{theme-provider/styles/product-list → product-list/styles}/product-list.style.d.ts +0 -0
  224. /package/dist/types/modules/{theme-provider/styles/ui → ui-components/styles}/drawer.style.d.ts +0 -0
  225. /package/dist/types/modules/{theme-provider/styles/ui → ui-components/styles}/loading.style.d.ts +0 -0
  226. /package/dist/types/modules/{theme-provider/styles/ui → ui-components/styles}/promo-code-ticker.style.d.ts +0 -0
@@ -0,0 +1,631 @@
1
+ # Product List Component
2
+
3
+ The Product List component provides a filterable, searchable product catalog with infinite scroll for building category pages and search results.
4
+
5
+ ## Overview
6
+
7
+ The Product List component:
8
+ - Displays products in a responsive grid
9
+ - Supports infinite scroll pagination
10
+ - Provides search functionality
11
+ - Offers advanced filtering options
12
+ - Links to product detail pages
13
+ - Shows real-time availability
14
+ - Supports add-to-cart from list view
15
+
16
+ ## Basic Usage
17
+
18
+ ### Declarative Setup
19
+
20
+ Use data attributes to configure the product list:
21
+
22
+ ```html
23
+ <script
24
+ defer
25
+ data-liquid-commerce-elements
26
+ data-token="YOUR_API_KEY"
27
+ data-env="production"
28
+ src="https://elements.reservebar-worker.workers.dev/all/elements.js"
29
+ ></script>
30
+
31
+ <div
32
+ data-liquid-commerce-elements-products-list="my-collection-slug"
33
+ data-rows="3"
34
+ data-columns="4"
35
+ data-filters="price,brands,categories"
36
+ data-product-url="/product/{grouping}"
37
+ ></div>
38
+ ```
39
+
40
+ **Attributes:**
41
+ - `data-liquid-commerce-elements-products-list`: Product list container; value is the collection slug
42
+ - `data-rows`: Number of rows to display (default: 4)
43
+ - `data-columns`: Number of columns (default: 4)
44
+ - `data-filters`: Comma-separated filter types
45
+ - `data-product-url`: URL pattern for product detail pages (optional)
46
+
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.
54
+
55
+ ### With Search and Filters
56
+
57
+ Separate containers for search and filters:
58
+
59
+ ```html
60
+ <!-- Search container -->
61
+ <div data-liquid-commerce-elements-products-list-search="my-collection-slug"></div>
62
+
63
+ <!-- Filters container -->
64
+ <div data-liquid-commerce-elements-products-list-filters="my-collection-slug" data-filters="price,brands,fulfillment"></div>
65
+
66
+ <!-- Product list -->
67
+ <div
68
+ data-liquid-commerce-elements-products-list="my-collection-slug"
69
+ data-rows="4"
70
+ data-columns="3"
71
+ data-product-url="/products/{grouping}"
72
+ ></div>
73
+ ```
74
+
75
+ ### Programmatic Setup
76
+
77
+ Use JavaScript for dynamic configuration:
78
+
79
+ ```javascript
80
+ const client = await Elements('YOUR_API_KEY', { env: 'production' });
81
+
82
+ // Inject product list
83
+ await client.injectProductList({
84
+ containerId: 'products',
85
+ slug: 'my-collection-slug',
86
+ rows: 3,
87
+ columns: 4,
88
+ filters: ['price', 'brands', 'categories', 'fulfillment'],
89
+ productUrl: '/product/{grouping}'
90
+ });
91
+
92
+ // Inject search (optional)
93
+ await client.injectProductListSearch({
94
+ containerId: 'search',
95
+ slug: 'my-collection-slug'
96
+ });
97
+
98
+ // Inject filters (optional)
99
+ await client.injectProductListFilters({
100
+ containerId: 'filters',
101
+ slug: 'my-collection-slug',
102
+ filters: ['price', 'brands']
103
+ });
104
+ ```
105
+
106
+ ## Available Filters
107
+
108
+ The following filter type values can be used in the `filters` array:
109
+
110
+ | Filter Value | Description |
111
+ |----------------|------------------------------------------|
112
+ | `'price'` | Price range slider with min/max values |
113
+ | `'brands'` | Checkboxes for available brands |
114
+ | `'categories'` | Category selection checkboxes |
115
+ | `'fulfillment'`| Shipping vs. on-demand delivery toggle |
116
+ | `'engraving'` | Filter by personalization support |
117
+ | `'sizes'` | Filter by product size/volume |
118
+ | `'flavor'` | Filter by flavor profile |
119
+ | `'region'` | Filter by region of origin |
120
+ | `'variety'` | Filter by product variety |
121
+ | `'vintage'` | Filter by vintage year |
122
+ | `'country'` | Filter by country of origin |
123
+ | `'appellation'`| Filter by appellation |
124
+ | `'materials'` | Filter by materials |
125
+
126
+ ```javascript
127
+ // Example: use multiple filters
128
+ filters: ['price', 'brands', 'categories', 'fulfillment', 'sizes']
129
+ ```
130
+
131
+ ## URL Query Param Filters
132
+
133
+ The product list auto-applies filters from the page URL on first load. Useful for category landing pages, "shop the look" links, marketing emails, or any flow where you want to deep-link into a pre-filtered list.
134
+
135
+ ### Whitelist
136
+
137
+ Only filter keys that are configured for the list are honored — anything else in the URL is silently ignored. The whitelist resolves in this priority order:
138
+
139
+ 1. `data-filters` on `<div data-liquid-commerce-elements-products-list>` (use this when the page does **not** mount a filters UI but you still want URL filtering — e.g. a curated category page).
140
+ 2. `data-filters` on the matching `<... -products-list-filters>` container (the common case when a filters panel is mounted).
141
+ 3. `filters` array passed to `injectProductList(...)` programmatically.
142
+ 4. `availableFilters` from the theme config for the list slug (fallback only).
143
+
144
+ ### Supported formats
145
+
146
+ | Filter | URL format | Example |
147
+ | --- | --- | --- |
148
+ | Multi-value (`brands`, `categories`, `flavor`, `region`, `variety`, `vintage`, `country`, `appellation`, `materials`, `sizes`) | Comma-separated **or** repeated keys | `?brands=Bacardi,Glenlivet` or `?brands=Bacardi&brands=Glenlivet` |
149
+ | `fulfillment` | Single value: `all`, `shipping`, or `onDemand` | `?fulfillment=shipping` |
150
+ | `engraving` | `true` or `false` | `?engraving=true` |
151
+ | `price` | `min-max` range; `min-` or `-max` are accepted | `?price=20-150`, `?price=20-`, `?price=-150` |
152
+
153
+ Invalid values are dropped (e.g. `?fulfillment=garbage`, `?price=abc` — no error, the filter just isn't applied). Combining params is supported:
154
+
155
+ ```
156
+ https://yoursite.com/best-sellers?brands=Bacardi&categories=Wine&price=20-150&fulfillment=shipping
157
+ ```
158
+
159
+ ### Behavior
160
+
161
+ - URL params win over any state persisted from a previous session.
162
+ - Once the list mounts, the filters panel (if present) reflects the seeded values, and the initial product fetch is filtered.
163
+ - Subsequent in-page interactions (toggling filters, scrolling, etc.) do not write back to the URL — the URL is read-only at load time.
164
+
165
+ ### Standalone use (no filters component)
166
+
167
+ URL filtering works without injecting a filters panel. Declare the whitelist on the products-list container itself:
168
+
169
+ ```html
170
+ <div
171
+ data-liquid-commerce-elements-products-list="curated-page"
172
+ data-filters="price,brands,categories"
173
+ data-rows="4"
174
+ data-columns="4"
175
+ ></div>
176
+ ```
177
+
178
+ Now `https://yoursite.com/curated-page?brands=Bacardi&price=20-150` filters the list on load even though no filters UI is present.
179
+
180
+ ## Search Functionality
181
+
182
+ ### Search Box
183
+
184
+ The search component provides full-text search across:
185
+ - Product names
186
+ - Descriptions
187
+ - Brand names
188
+ - Categories
189
+ - SKUs/UPCs
190
+
191
+ ### Search Behavior
192
+
193
+ - Real-time search as user types (500ms debounce; fires on any non-empty input — no minimum character count)
194
+ - Input is limited to 100 characters; allowed characters: letters, numbers, spaces, and `- _ ' . , & ( )`
195
+ - Server-side filtering by the search term
196
+ - "Clear search" button appears when active
197
+
198
+ ### Programmatic Search
199
+
200
+ Search is controlled through the injected search component. Use `injectProductListSearch()` to add a search box that automatically filters the associated product list.
201
+
202
+ ## Grid Layout
203
+
204
+ ### Responsive Grid
205
+
206
+ The grid automatically adjusts for screen sizes:
207
+
208
+ **Desktop** (> 1024px):
209
+ - Uses configured columns (e.g., 4 columns)
210
+
211
+ **Tablet** (768px - 1024px):
212
+ - Reduces to 3 or 2 columns
213
+
214
+ **Mobile** (< 768px):
215
+ - Single column or 2 columns depending on space
216
+
217
+ ### Configuring Layout
218
+
219
+ ```javascript
220
+ await client.injectProductList({
221
+ containerId: 'products',
222
+ slug: 'my-collection',
223
+ rows: 5, // Number of rows per page
224
+ columns: 4 // Columns in grid (desktop)
225
+ });
226
+ ```
227
+
228
+ Total products per page = rows × columns (e.g., 5 × 4 = 20 products)
229
+
230
+ ## Infinite Scroll
231
+
232
+ ### How It Works
233
+
234
+ 1. Initial products load (rows × columns)
235
+ 2. User scrolls to bottom
236
+ 3. Next page loads automatically
237
+ 4. Appends to existing products
238
+ 5. Continues until all products shown
239
+
240
+ ### Loading States
241
+
242
+ Shows loading indicator:
243
+ - On initial load
244
+ - When loading next page
245
+ - When applying filters
246
+ - When searching
247
+
248
+ ### End of Results
249
+
250
+ When all products are shown:
251
+ - Infinite scroll stops
252
+ - Shows "No more products" message
253
+ - Scroll to top button may appear
254
+
255
+ ## Product Cards
256
+
257
+ Each product card shows:
258
+
259
+ - Product image
260
+ - Product name
261
+ - Brand
262
+ - Price (or price range for multiple sizes)
263
+ - Rating (if available)
264
+ - Clickable image/card linking to the product detail page (when `productUrl` is configured)
265
+ - "Add to Cart" button (optional)
266
+ - Availability indicator
267
+
268
+ ### Card Interaction
269
+
270
+ **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).
271
+
272
+ **Quick Add:** Add product to cart directly from list view (if enabled)
273
+
274
+ **Click on image:** Open image in lightbox or navigate to product page
275
+
276
+ ## Customization
277
+
278
+ ### Theme Configuration
279
+
280
+ Product list theming is applied per-list using the collection slug as a key:
281
+
282
+ ```javascript
283
+ const client = await Elements('YOUR_API_KEY', {
284
+ env: 'production',
285
+ customTheme: {
286
+ productList: {
287
+ theme: {
288
+ backgroundColor: '#ffffff'
289
+ },
290
+ layout: {
291
+ lists: {
292
+ 'my-collection-slug': {
293
+ productCard: {
294
+ style: 'card', // 'card' or 'ghost'
295
+ cornerRadius: '8px',
296
+ showPrice: true,
297
+ showSizes: true,
298
+ showRetailerName: true,
299
+ showFulfillmentOptions: true,
300
+ enableShippingFulfillment: true,
301
+ enableOnDemandFulfillment: true,
302
+ enablePersonalization: true,
303
+ showQuantityCounter: true,
304
+ enablePreCart: true,
305
+ showCollectionTags: false
306
+ },
307
+ presentationMode: 'drawer', // 'drawer' or 'modal'
308
+ rows: 4,
309
+ columns: 3
310
+ }
311
+ }
312
+ }
313
+ }
314
+ }
315
+ });
316
+ ```
317
+
318
+ See [Configuration Reference](../api/configuration.md#product-list-theme) for the complete list of options.
319
+
320
+ ## Use Cases
321
+
322
+ ### Category Page
323
+
324
+ ```html
325
+ <!DOCTYPE html>
326
+ <html>
327
+ <head>
328
+ <title>Whiskey Collection</title>
329
+ <script
330
+ defer
331
+ data-liquid-commerce-elements
332
+ data-token="YOUR_API_KEY"
333
+ data-env="production"
334
+ src="https://elements.reservebar-worker.workers.dev/all/elements.js"
335
+ ></script>
336
+ </head>
337
+ <body>
338
+ <h1>Whiskey Collection</h1>
339
+
340
+ <!-- Search -->
341
+ <div data-liquid-commerce-elements-products-list-search="whiskey-collection"></div>
342
+
343
+ <div class="catalog">
344
+ <!-- Filters sidebar -->
345
+ <aside>
346
+ <div data-liquid-commerce-elements-products-list-filters="whiskey-collection" data-filters="price,brands,sizes"></div>
347
+ </aside>
348
+
349
+ <!-- Product grid -->
350
+ <main>
351
+ <div
352
+ data-liquid-commerce-elements-products-list="whiskey-collection"
353
+ data-rows="4"
354
+ data-columns="3"
355
+ data-product-url="/whiskey/{grouping}"
356
+ ></div>
357
+ </main>
358
+ </div>
359
+ </body>
360
+ </html>
361
+ ```
362
+
363
+ ### Search Results Page
364
+
365
+ ```javascript
366
+ import { Elements } from '@liquidcommerce/elements-sdk';
367
+
368
+ const client = await Elements('YOUR_API_KEY', { env: 'production' });
369
+
370
+ // Inject product list with search
371
+ await client.injectProductList({
372
+ containerId: 'search-results',
373
+ slug: 'all-products',
374
+ rows: 5,
375
+ columns: 4,
376
+ filters: ['price', 'brands', 'categories']
377
+ });
378
+
379
+ await client.injectProductListSearch({
380
+ containerId: 'search-box',
381
+ slug: 'all-products'
382
+ });
383
+ ```
384
+
385
+ ### Custom Product URL Patterns
386
+
387
+ Different URL patterns for different product types:
388
+
389
+ ```javascript
390
+ // Get product type from data
391
+ const productType = getProductTypeFromData();
392
+
393
+ let urlPattern;
394
+ switch (productType) {
395
+ case 'whiskey':
396
+ urlPattern = '/spirits/whiskey/{grouping}';
397
+ break;
398
+ case 'wine':
399
+ urlPattern = '/wine/{grouping}';
400
+ break;
401
+ default:
402
+ urlPattern = '/products/{grouping}';
403
+ }
404
+
405
+ await client.injectProductList({
406
+ containerId: 'products',
407
+ slug: 'all-products',
408
+ rows: 3,
409
+ columns: 4,
410
+ productUrl: urlPattern
411
+ });
412
+ ```
413
+
414
+ ### Product URL Map
415
+
416
+ For partners whose PDPs have hand-curated URLs that aren't derivable from a
417
+ single placeholder (e.g. dedicated marketing pages, Shopify handles, WordPress
418
+ slugs), pass a **map** instead of a string template. Keys are product
419
+ identifiers — either a UPC or a salsifyGrouping ID, the same identifier types
420
+ accepted by `injectProductElement`. The card looks up UPC first, then grouping
421
+ ID; products not in the map render without a link.
422
+
423
+ #### Declarative — JSON script tag
424
+
425
+ Drop a single `<script type="application/json">` tag anywhere on the page,
426
+ keyed by list slug → identifier → URL. Generate it server-side from your CMS.
427
+
428
+ ```html
429
+ <script data-liquid-commerce-elements-product-urls type="application/json">
430
+ {
431
+ "best-sellers": {
432
+ "GROUPING-33277": "/wines/macallan-12-special-edition",
433
+ "00832889005513": "/spirits/cabernet-2018-club-only"
434
+ },
435
+ "limited-releases": {
436
+ "GROUPING-78941": "/exclusive/pappy-23-allocation"
437
+ }
438
+ }
439
+ </script>
440
+
441
+ <div data-liquid-commerce-elements-products-list="best-sellers"></div>
442
+ ```
443
+
444
+ When both `data-product-url` and a slug entry in this script are present for
445
+ the same list, the **map wins** — it's the more specific intent.
446
+
447
+ ##### Shopify Liquid
448
+
449
+ ```liquid
450
+ <script data-liquid-commerce-elements-product-urls type="application/json">
451
+ {
452
+ "best-sellers": {
453
+ {% for p in collections.best-sellers.products %}
454
+ "{{ p.metafields.lc.grouping_id }}": "{{ p.url }}"{% unless forloop.last %},{% endunless %}
455
+ {% endfor %}
456
+ }
457
+ }
458
+ </script>
459
+ ```
460
+
461
+ ##### WordPress / WooCommerce (PHP)
462
+
463
+ ```php
464
+ <script data-liquid-commerce-elements-product-urls type="application/json">
465
+ <?= json_encode(['best-sellers' => $lc_identifier_to_pdp_url_map]) ?>
466
+ </script>
467
+ ```
468
+
469
+ #### Programmatic
470
+
471
+ ```javascript
472
+ await client.injectProductList({
473
+ containerId: 'products',
474
+ slug: 'best-sellers',
475
+ rows: 3,
476
+ columns: 4,
477
+ productUrl: {
478
+ 'GROUPING-33277': '/wines/macallan-12-special-edition',
479
+ '00832889005513': '/spirits/cabernet-2018-club-only',
480
+ },
481
+ });
482
+ ```
483
+
484
+ ## Events
485
+
486
+ While product list events are primarily internal, you can listen for cart events when users add products:
487
+
488
+ ```javascript
489
+ window.addEventListener('lce:actions.cart_item_added', (event) => {
490
+ const { itemId, quantity } = event.detail.data;
491
+ console.log(`Product added from list: ${itemId}`);
492
+ });
493
+ ```
494
+
495
+ ## Accessibility
496
+
497
+ The product list component includes:
498
+
499
+ - Keyboard navigation support
500
+ - Screen reader labels
501
+ - ARIA attributes for filters and search
502
+ - Focus management
503
+ - High contrast support
504
+
505
+ ### Keyboard Shortcuts
506
+
507
+ - `Tab`: Navigate between products and filters
508
+ - `Enter/Space`: Select product or toggle filter
509
+ - `Escape`: Clear search or close filters
510
+ - `Arrow keys`: Navigate grid (when focused)
511
+
512
+ ## Performance
513
+
514
+ ### Optimization Features
515
+
516
+ - **Image lazy loading**: Images load as they enter viewport
517
+ - **Virtual scrolling**: Only renders visible products
518
+ - **Debounced search**: Reduces API calls during typing
519
+ - **Filter caching**: Caches filter results
520
+ - **Progressive loading**: Loads in batches
521
+
522
+ ### Large Catalogs
523
+
524
+ For catalogs with thousands of products:
525
+
526
+ ```javascript
527
+ await client.injectProductList({
528
+ containerId: 'products',
529
+ slug: 'all-products',
530
+ rows: 3,
531
+ columns: 4,
532
+ filters: ['price', 'brands'], // Limit filters to most useful
533
+ // More rows = larger pages = fewer API calls
534
+ });
535
+ ```
536
+
537
+ ## Best Practices
538
+
539
+ ### Provide Clear Navigation
540
+
541
+ ```html
542
+ <nav class="breadcrumb">
543
+ <a href="/">Home</a> &gt;
544
+ <a href="/products">Products</a> &gt;
545
+ <span>Whiskey</span>
546
+ </nav>
547
+ ```
548
+
549
+ ### Show Result Counts
550
+
551
+ The product list component automatically displays the number of results. You can also track cart additions from the list using standard cart events:
552
+
553
+ ```javascript
554
+ window.addEventListener('lce:actions.cart_item_added', (event) => {
555
+ console.log('Item added from product list:', event.detail.data);
556
+ });
557
+ ```
558
+
559
+ ### Mobile-First Design
560
+
561
+ Ensure filters work well on mobile:
562
+
563
+ ```css
564
+ @media (max-width: 768px) {
565
+ .filters-sidebar {
566
+ position: fixed;
567
+ bottom: 0;
568
+ left: 0;
569
+ right: 0;
570
+ transform: translateY(100%);
571
+ transition: transform 0.3s;
572
+ }
573
+
574
+ .filters-sidebar.open {
575
+ transform: translateY(0);
576
+ }
577
+ }
578
+ ```
579
+
580
+ ### Default to Relevant Filters
581
+
582
+ For category pages, pre-select relevant filters:
583
+
584
+ ```javascript
585
+ // On whiskey category page
586
+ await client.injectProductList({
587
+ containerId: 'products',
588
+ slug: 'whiskey-collection',
589
+ rows: 4,
590
+ columns: 3,
591
+ filters: ['price', 'brands', 'sizes'] // Most relevant for whiskey
592
+ });
593
+ ```
594
+
595
+ ## Troubleshooting
596
+
597
+ ### Products Not Loading
598
+
599
+ 1. Check browser console for errors
600
+ 2. Verify API key is correct
601
+ 3. Ensure container ID exists
602
+ 4. Check network tab for API responses
603
+ 5. Verify products exist in catalog
604
+
605
+ ### Filters Not Working
606
+
607
+ 1. Ensure filter types are spelled correctly
608
+ 2. Check that products have filterable attributes
609
+ 3. Verify theme config allows filters
610
+ 4. Look for JavaScript errors
611
+
612
+ ### Infinite Scroll Not Triggering
613
+
614
+ 1. Check container has finite height
615
+ 2. Verify scroll event listeners are attached
616
+ 3. Ensure there are more products to load
617
+ 4. Check console for errors
618
+
619
+ ### Search Not Finding Products
620
+
621
+ 1. Verify the input uses allowed characters and is under the 100-character limit
622
+ 2. Check search is not case-sensitive (it shouldn't be)
623
+ 3. Ensure products have searchable text fields
624
+ 4. Look for API errors in network tab
625
+
626
+ ## See Also
627
+
628
+ - [Product Component](./product-component.md) - Individual product display
629
+ - [Cart Component](./cart-component.md) - Add products to cart
630
+ - [Theming](./theming.md) - Customize appearance
631
+ - [Events](./events.md) - Available events