@liquidcommerce/elements-sdk 2.6.0-beta.11 → 2.6.0-beta.110

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 (270) hide show
  1. package/README.md +99 -2518
  2. package/dist/index.checkout.esm.js +18210 -0
  3. package/dist/index.esm.js +26253 -20673
  4. package/dist/ssr-stub.checkout.esm.js +17 -0
  5. package/dist/ssr-stub.esm.js +269 -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 +13 -18
  14. package/dist/types/core/a11y/announcer.service.d.ts +16 -0
  15. package/dist/types/core/a11y/focus-manager.service.d.ts +21 -0
  16. package/dist/types/core/a11y/focusable.d.ts +5 -0
  17. package/dist/types/core/a11y/glyph-button.d.ts +8 -0
  18. package/dist/types/core/a11y/index.d.ts +6 -0
  19. package/dist/types/core/a11y/required.d.ts +1 -0
  20. package/dist/types/core/a11y/single-select.d.ts +20 -0
  21. package/dist/types/core/api/api-client.service.d.ts +19 -18
  22. package/dist/types/core/api/api-result.d.ts +19 -0
  23. package/dist/types/core/api/auth-client.service.d.ts +37 -13
  24. package/dist/types/core/api/http-client.service.d.ts +0 -8
  25. package/dist/types/core/base-component.service.d.ts +4 -1
  26. package/dist/types/core/client/actions/base-action.service.d.ts +22 -0
  27. package/dist/types/core/client/actions/client-address-action.service.d.ts +18 -0
  28. package/dist/types/core/client/actions/client-cart-action.service.d.ts +38 -0
  29. package/dist/types/core/client/actions/client-checkout-action.service.d.ts +69 -0
  30. package/dist/types/core/client/actions/client-product-action.service.d.ts +15 -0
  31. package/dist/types/core/client/client-action.service.d.ts +6 -74
  32. package/dist/types/core/client/client-config.service.d.ts +8 -5
  33. package/dist/types/core/debug-panel/debug-panel.styles.d.ts +1 -1
  34. package/dist/types/core/google-tag-manager.service.d.ts +3 -1
  35. package/dist/types/core/logger/logger.service.d.ts +1 -1
  36. package/dist/types/core/pubsub/interfaces/address.interface.d.ts +3 -0
  37. package/dist/types/core/pubsub/interfaces/cart.interface.d.ts +1 -1
  38. package/dist/types/core/pubsub/interfaces/checkout.interface.d.ts +36 -51
  39. package/dist/types/core/pubsub/interfaces/core.interface.d.ts +11 -6
  40. package/dist/types/core/pubsub/pubsub.service.d.ts +1 -2
  41. package/dist/types/core/singleton-manager.service.d.ts +12 -8
  42. package/dist/types/core/store/interfaces/cart.interface.d.ts +2 -3
  43. package/dist/types/core/store/interfaces/checkout.interface.d.ts +19 -108
  44. package/dist/types/core/store/interfaces/core.interface.d.ts +12 -2
  45. package/dist/types/core/store/interfaces/metadata.interface.d.ts +11 -0
  46. package/dist/types/core/store/interfaces/product-list.interface.d.ts +30 -0
  47. package/dist/types/core/store/interfaces/product.interface.d.ts +1 -0
  48. package/dist/types/core/store/store.constant.d.ts +5 -0
  49. package/dist/types/core/store/store.service.d.ts +1 -0
  50. package/dist/types/core/telemetry/telemetry.service.d.ts +1 -0
  51. package/dist/types/enums/core.enum.d.ts +39 -2
  52. package/dist/types/enums/index.d.ts +0 -1
  53. package/dist/types/index.checkout.d.ts +8 -0
  54. package/dist/types/index.checkout.umd.d.ts +4 -0
  55. package/dist/types/index.d.ts +8 -3
  56. package/dist/types/interfaces/api/cart.interface.d.ts +12 -7
  57. package/dist/types/interfaces/api/checkout.interface.d.ts +239 -0
  58. package/dist/types/interfaces/api/index.d.ts +5 -0
  59. package/dist/types/interfaces/api/product-list.interface.d.ts +15 -6
  60. package/dist/types/interfaces/api/product.interface.d.ts +10 -4
  61. package/dist/types/interfaces/client.interface.d.ts +72 -0
  62. package/dist/types/interfaces/component.interface.d.ts +7 -0
  63. package/dist/types/interfaces/config.interface.d.ts +40 -0
  64. package/dist/types/interfaces/configs/address.interface.d.ts +1 -1
  65. package/dist/types/interfaces/configs/cart.interface.d.ts +1 -1
  66. package/dist/types/interfaces/configs/checkout.interface.d.ts +2 -1
  67. package/dist/types/interfaces/configs/global.interface.d.ts +9 -3
  68. package/dist/types/interfaces/configs/index.d.ts +1 -0
  69. package/dist/types/interfaces/configs/product-list.interface.d.ts +49 -0
  70. package/dist/types/interfaces/configs/product.interface.d.ts +5 -1
  71. package/dist/types/interfaces/injection.interface.d.ts +50 -0
  72. package/dist/types/modules/address/address-display.component.d.ts +3 -1
  73. package/dist/types/modules/address/address-input.component.d.ts +10 -1
  74. package/dist/types/modules/address/address.command.d.ts +2 -1
  75. package/dist/types/modules/address/styles/register-styles.d.ts +1 -0
  76. package/dist/types/modules/cart/cart.commands.d.ts +4 -4
  77. package/dist/types/modules/cart/components/cart-body.component.d.ts +1 -0
  78. package/dist/types/modules/cart/components/cart-item-quantity-price.component.d.ts +5 -0
  79. package/dist/types/modules/cart/components/cart-item.component.d.ts +6 -0
  80. package/dist/types/modules/cart/styles/register-styles.d.ts +1 -0
  81. package/dist/types/modules/checkout/checkout.commands.d.ts +34 -11
  82. package/dist/types/modules/checkout/checkout.component.d.ts +6 -1
  83. package/dist/types/modules/checkout/components/checkout-billing.component.d.ts +5 -2
  84. package/dist/types/modules/checkout/components/checkout-completed.component.d.ts +5 -0
  85. package/dist/types/modules/checkout/components/checkout-header.component.d.ts +1 -0
  86. package/dist/types/modules/checkout/components/checkout-item-quantity.component.d.ts +4 -0
  87. package/dist/types/modules/checkout/components/checkout-items.component.d.ts +4 -3
  88. package/dist/types/modules/checkout/components/checkout-order-summary.component.d.ts +2 -0
  89. package/dist/types/modules/checkout/components/checkout-payment.component.d.ts +2 -1
  90. package/dist/types/modules/checkout/components/checkout-place-order-button.component.d.ts +2 -0
  91. package/dist/types/modules/checkout/components/checkout-presale-countdown.component.d.ts +15 -1
  92. package/dist/types/modules/checkout/components/checkout-presale-expired.component.d.ts +7 -1
  93. package/dist/types/modules/checkout/components/checkout-send-as-gift.component.d.ts +3 -0
  94. package/dist/types/modules/checkout/components/checkout-stripe-form.component.d.ts +4 -2
  95. package/dist/types/modules/checkout/components/checkout-tips.component.d.ts +4 -2
  96. package/dist/types/modules/checkout/components/promo-pc-gc.component.d.ts +0 -2
  97. package/dist/types/modules/checkout/components/required-fields-legend.d.ts +1 -0
  98. package/dist/types/modules/checkout/constant.d.ts +3 -0
  99. package/dist/types/modules/checkout/payment-session-error.d.ts +4 -0
  100. package/dist/types/modules/checkout/styles/register-styles.d.ts +1 -0
  101. package/dist/types/modules/product/components/components.d.ts +26 -2
  102. package/dist/types/modules/product/components/product-add-to-cart-section.component.d.ts +7 -1
  103. package/dist/types/modules/product/components/product-description.component.d.ts +1 -0
  104. package/dist/types/modules/product/components/product-drawer.component.d.ts +6 -0
  105. package/dist/types/modules/product/components/product-image-carousel.component.d.ts +5 -0
  106. package/dist/types/modules/product/components/product-options.component.d.ts +2 -1
  107. package/dist/types/modules/product/components/product-retailers-carousel.component.d.ts +6 -0
  108. package/dist/types/modules/product/components/product-retailers-popup-list.component.d.ts +12 -2
  109. package/dist/types/modules/product/product.commands.d.ts +5 -5
  110. package/dist/types/modules/product/styles/register-styles.d.ts +1 -0
  111. package/dist/types/modules/product-list/components/card-components/index.d.ts +5 -0
  112. package/dist/types/modules/product-list/components/card-components/product-badge.d.ts +9 -0
  113. package/dist/types/modules/product-list/components/card-components/product-button.d.ts +11 -0
  114. package/dist/types/modules/product-list/components/card-components/product-price-and-personalization.d.ts +14 -0
  115. package/dist/types/modules/product-list/components/card-components/product-quantity-selector.d.ts +11 -0
  116. package/dist/types/modules/product-list/components/card-components/product-sizes-list.d.ts +14 -0
  117. package/dist/types/modules/product-list/components/filter-components/index.d.ts +7 -0
  118. package/dist/types/modules/product-list/components/filter-components/product-list-apply-filter-button.d.ts +1 -0
  119. 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} +1 -0
  120. package/dist/types/modules/product-list/components/filter-components/product-list-chip.d.ts +5 -0
  121. package/dist/types/modules/product-list/components/filter-components/product-list-filters-chips.d.ts +13 -0
  122. package/dist/types/modules/product-list/components/filter-components/product-list-fulfillment-filter.d.ts +15 -0
  123. 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} +2 -1
  124. package/dist/types/modules/product-list/components/filter-components/product-list-toggle-filters.d.ts +7 -0
  125. package/dist/types/modules/product-list/components/index.d.ts +6 -2
  126. package/dist/types/modules/product-list/components/product-list-card-loading.component.d.ts +3 -1
  127. package/dist/types/modules/product-list/components/product-list-card.component.d.ts +37 -31
  128. package/dist/types/modules/product-list/components/product-list-engraving.component.d.ts +12 -0
  129. package/dist/types/modules/product-list/components/product-list-filters.component.d.ts +58 -36
  130. package/dist/types/modules/product-list/components/product-list-product-engraving-lines.component.d.ts +22 -0
  131. package/dist/types/modules/product-list/components/product-list-product-pre-cart.component.d.ts +53 -0
  132. package/dist/types/modules/product-list/components/product-list-search.component.d.ts +25 -0
  133. package/dist/types/modules/product-list/product-list-filter.registry.d.ts +42 -0
  134. package/dist/types/modules/product-list/product-list-filter.utils.d.ts +7 -0
  135. package/dist/types/modules/product-list/product-list-order.utils.d.ts +3 -0
  136. package/dist/types/modules/product-list/product-list-query-params.utils.d.ts +3 -0
  137. package/dist/types/modules/product-list/product-list.commands.d.ts +22 -7
  138. package/dist/types/modules/product-list/product-list.component.d.ts +23 -47
  139. package/dist/types/modules/product-list/product-list.constants.d.ts +38 -0
  140. package/dist/types/modules/product-list/product-list.interface.d.ts +17 -28
  141. package/dist/types/modules/product-list/styles/product-list-card.style.d.ts +1 -0
  142. package/dist/types/modules/product-list/styles/product-list-filters.style.d.ts +1 -0
  143. package/dist/types/modules/product-list/styles/register-styles.d.ts +1 -0
  144. package/dist/types/modules/theme-provider/constants/component-groupings.d.ts +1 -0
  145. package/dist/types/modules/theme-provider/constants/css-variable-mappings.d.ts +1 -1
  146. package/dist/types/modules/theme-provider/services/style-registry.service.d.ts +16 -0
  147. package/dist/types/modules/theme-provider/services/stylesheet-generator.service.d.ts +0 -1
  148. package/dist/types/modules/theme-provider/styles/register-styles.d.ts +1 -0
  149. package/dist/types/modules/theme-provider/theme-provider.service.d.ts +2 -2
  150. package/dist/types/modules/ui-components/alert/alert.component.d.ts +1 -1
  151. package/dist/types/modules/ui-components/buttons/buttons-open-cart.component.d.ts +5 -0
  152. package/dist/types/modules/ui-components/drawer/drawer.component.d.ts +15 -0
  153. package/dist/types/modules/ui-components/engraving/engraving-form.component.d.ts +8 -1
  154. package/dist/types/modules/ui-components/engraving/engraving-view.component.d.ts +7 -1
  155. package/dist/types/modules/ui-components/input/index.d.ts +0 -1
  156. package/dist/types/modules/ui-components/input/input.component.d.ts +14 -1
  157. package/dist/types/modules/ui-components/lce-element/lce-element.component.d.ts +2 -1
  158. package/dist/types/modules/ui-components/promo-code-ticker/promo-code-ticker.component.d.ts +1 -1
  159. package/dist/types/modules/ui-components/ui.commands.d.ts +7 -1
  160. package/dist/types/ssr/stub.checkout.d.ts +6 -0
  161. package/dist/types/ssr/stub.d.ts +10 -0
  162. package/dist/types/static/icon/arrow-right.icon.d.ts +1 -1
  163. package/dist/types/static/icon/bag.icon.d.ts +1 -1
  164. package/dist/types/static/icon/check.icon.d.ts +2 -0
  165. package/dist/types/static/icon/checkbox.icon.d.ts +1 -1
  166. package/dist/types/static/icon/chevron-down.icon.d.ts +1 -1
  167. package/dist/types/static/icon/chevron-left.icon.d.ts +1 -1
  168. package/dist/types/static/icon/chevron-up.icon.d.ts +1 -1
  169. package/dist/types/static/icon/close.icon.d.ts +1 -1
  170. package/dist/types/static/icon/error-info.icon.d.ts +1 -1
  171. package/dist/types/static/icon/filter.icon.d.ts +1 -1
  172. package/dist/types/static/icon/icon.a11y.d.ts +1 -0
  173. package/dist/types/static/icon/icon.types.d.ts +1 -0
  174. package/dist/types/static/icon/index.d.ts +2 -0
  175. package/dist/types/static/icon/info.icon.d.ts +1 -1
  176. package/dist/types/static/icon/loading-spinner.icon.d.ts +1 -1
  177. package/dist/types/static/icon/search.icon.d.ts +1 -1
  178. package/dist/types/static/icon/success.icon.d.ts +1 -1
  179. package/dist/types/static/icon/trash.icon.d.ts +1 -1
  180. package/dist/types/static/icon/warning.icon.d.ts +1 -1
  181. package/dist/types/utils/dom-compat.d.ts +2 -0
  182. package/dist/types/utils/format.d.ts +5 -14
  183. package/dist/types/utils/image-bg-removal.d.ts +3 -0
  184. package/dist/types/utils/product-selection.d.ts +16 -0
  185. package/dist/types/utils/product.d.ts +18 -0
  186. package/dist/types/utils/timezone.d.ts +6 -0
  187. package/docs/v1/README.md +213 -0
  188. package/docs/v1/api/actions/address-actions.md +286 -0
  189. package/docs/v1/api/actions/cart-actions.md +364 -0
  190. package/docs/v1/api/actions/checkout-actions.md +527 -0
  191. package/docs/v1/api/actions/product-actions.md +204 -0
  192. package/docs/v1/api/client.md +596 -0
  193. package/docs/v1/api/configuration.md +557 -0
  194. package/docs/v1/api/injection-methods.md +331 -0
  195. package/docs/v1/api/typescript-types.md +424 -0
  196. package/docs/v1/api/ui-helpers.md +200 -0
  197. package/docs/v1/examples/advanced-patterns.md +199 -0
  198. package/docs/v1/examples/checkout-flow.md +90 -0
  199. package/docs/v1/examples/custom-theming.md +63 -0
  200. package/docs/v1/examples/multi-product-page.md +90 -0
  201. package/docs/v1/examples/simple-product-page.md +89 -0
  202. package/docs/v1/getting-started/concepts.md +521 -0
  203. package/docs/v1/getting-started/installation.md +349 -0
  204. package/docs/v1/getting-started/quick-start.md +410 -0
  205. package/docs/v1/guides/accessibility.md +214 -0
  206. package/docs/v1/guides/address-component.md +435 -0
  207. package/docs/v1/guides/best-practices.md +365 -0
  208. package/docs/v1/guides/cart-component.md +757 -0
  209. package/docs/v1/guides/checkout-component.md +670 -0
  210. package/docs/v1/guides/events.md +939 -0
  211. package/docs/v1/guides/product-component.md +736 -0
  212. package/docs/v1/guides/product-list-component.md +730 -0
  213. package/docs/v1/guides/theming.md +229 -0
  214. package/docs/v1/integration/angular.md +39 -0
  215. package/docs/v1/integration/laravel.md +41 -0
  216. package/docs/v1/integration/nextjs.md +69 -0
  217. package/docs/v1/integration/proxy-setup.md +106 -0
  218. package/docs/v1/integration/react.md +64 -0
  219. package/docs/v1/integration/vanilla-js.md +84 -0
  220. package/docs/v1/integration/vue.md +58 -0
  221. package/docs/v1/reference/analytics.md +107 -0
  222. package/docs/v1/reference/browser-support.md +47 -0
  223. package/docs/v1/reference/error-handling.md +83 -0
  224. package/docs/v1/reference/performance.md +52 -0
  225. package/docs/v1/reference/telemetry.md +85 -0
  226. package/docs/v1/reference/troubleshooting.md +135 -0
  227. package/package.json +75 -45
  228. package/dist/types/elements-builder-client.d.ts +0 -2
  229. package/dist/types/elements-client.d.ts +0 -2
  230. package/dist/types/enums/cloud.enum.d.ts +0 -97
  231. package/dist/types/interfaces/cloud/checkout.interface.d.ts +0 -218
  232. package/dist/types/interfaces/cloud/core.interface.d.ts +0 -22
  233. package/dist/types/interfaces/cloud/index.d.ts +0 -3
  234. package/dist/types/interfaces/cloud/retailer.interface.d.ts +0 -67
  235. package/dist/types/interfaces/cloud/user.interface.d.ts +0 -100
  236. package/dist/types/interfaces/core.interface.d.ts +0 -111
  237. package/dist/types/modules/checkout/components/checkout.type.d.ts +0 -4
  238. package/dist/types/modules/product-list/components/product-list-filters-subcomponents/index.d.ts +0 -6
  239. package/dist/types/modules/product-list/components/product-list-filters-subcomponents/product-list-apply-filter-button.component.d.ts +0 -1
  240. package/dist/types/modules/product-list/components/product-list-filters-subcomponents/product-list-delivery-options-filter.components.d.ts +0 -16
  241. package/dist/types/modules/product-list/components/product-list-filters-subcomponents/product-list-search.component.d.ts +0 -16
  242. package/dist/types/modules/product-list/components/product-list-filters-subcomponents/product-list-toggle-filters.components.d.ts +0 -18
  243. package/dist/types/modules/theme-provider/styles/address/index.d.ts +0 -1
  244. package/dist/types/modules/theme-provider/styles/cart/index.d.ts +0 -1
  245. package/dist/types/modules/theme-provider/styles/checkout/index.d.ts +0 -1
  246. package/dist/types/modules/theme-provider/styles/product/index.d.ts +0 -3
  247. package/dist/types/modules/theme-provider/styles/product-list/index.d.ts +0 -1
  248. package/dist/types/modules/theme-provider/styles/ui/index.d.ts +0 -3
  249. package/dist/types/modules/ui-components/input/birthdate-input.component.d.ts +0 -53
  250. package/dist/types/utils/helper.d.ts +0 -28
  251. package/docs/ACTIONS.md +0 -1300
  252. package/docs/BROWSER_SUPPORT.md +0 -279
  253. package/docs/CONFIGURATION.md +0 -853
  254. package/docs/DOCUMENTATION_INDEX.md +0 -311
  255. package/docs/EVENTS.md +0 -798
  256. package/docs/PROXY.md +0 -228
  257. package/docs/THEMING.md +0 -592
  258. package/docs/TROUBLESHOOTING.md +0 -793
  259. package/umd/elements.js +0 -1
  260. /package/dist/types/{auto-initialize.d.ts → auto-initialize/main.d.ts} +0 -0
  261. /package/dist/types/modules/{theme-provider/styles/address → address/styles}/address.style.d.ts +0 -0
  262. /package/dist/types/modules/{theme-provider/styles/cart → cart/styles}/cart.style.d.ts +0 -0
  263. /package/dist/types/modules/{theme-provider/styles/checkout → checkout/styles}/checkout.style.d.ts +0 -0
  264. /package/dist/types/modules/{theme-provider/styles/product → product/styles}/image-carousel.style.d.ts +0 -0
  265. /package/dist/types/modules/{theme-provider/styles/product → product/styles}/product.style.d.ts +0 -0
  266. /package/dist/types/modules/{theme-provider/styles/product → product/styles}/retailers.style.d.ts +0 -0
  267. /package/dist/types/modules/{theme-provider/styles/product-list → product-list/styles}/product-list.style.d.ts +0 -0
  268. /package/dist/types/modules/{theme-provider/styles/ui → ui-components/styles}/drawer.style.d.ts +0 -0
  269. /package/dist/types/modules/{theme-provider/styles/ui → ui-components/styles}/loading.style.d.ts +0 -0
  270. /package/dist/types/modules/{theme-provider/styles/ui → ui-components/styles}/promo-code-ticker.style.d.ts +0 -0
@@ -0,0 +1,730 @@
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
+ - `data-product-order`: Comma-separated product identifiers setting the display order (optional) — see [Product Order](#product-order)
47
+
48
+ `data-product-url` accepts a string template with one of two placeholders:
49
+ - `{grouping}` — replaced with the product's salsifyGrouping ID
50
+ - `{upc}` — replaced with the selected size's UPC
51
+
52
+ If your PDP URLs aren't derivable from a single placeholder (e.g. each
53
+ product has a hand-curated marketing slug), use the
54
+ [Product URL Map](#product-url-map) instead.
55
+
56
+ ### With Search and Filters
57
+
58
+ Separate containers for search and filters:
59
+
60
+ ```html
61
+ <!-- Search container -->
62
+ <div data-liquid-commerce-elements-products-list-search="my-collection-slug"></div>
63
+
64
+ <!-- Filters container -->
65
+ <div data-liquid-commerce-elements-products-list-filters="my-collection-slug" data-filters="price,brands,fulfillment"></div>
66
+
67
+ <!-- Product list -->
68
+ <div
69
+ data-liquid-commerce-elements-products-list="my-collection-slug"
70
+ data-rows="4"
71
+ data-columns="3"
72
+ data-product-url="/products/{grouping}"
73
+ ></div>
74
+ ```
75
+
76
+ ### Programmatic Setup
77
+
78
+ Use JavaScript for dynamic configuration:
79
+
80
+ ```javascript
81
+ const client = await Elements('YOUR_API_KEY', { env: 'production' });
82
+
83
+ // Inject product list
84
+ await client.injectProductList({
85
+ containerId: 'products',
86
+ slug: 'my-collection-slug',
87
+ rows: 3,
88
+ columns: 4,
89
+ filters: ['price', 'brands', 'categories', 'fulfillment'],
90
+ productUrl: '/product/{grouping}'
91
+ });
92
+
93
+ // Inject search (optional)
94
+ await client.injectProductListSearch({
95
+ containerId: 'search',
96
+ slug: 'my-collection-slug'
97
+ });
98
+
99
+ // Inject filters (optional)
100
+ await client.injectProductListFilters({
101
+ containerId: 'filters',
102
+ slug: 'my-collection-slug',
103
+ filters: ['price', 'brands']
104
+ });
105
+ ```
106
+
107
+ ## Available Filters
108
+
109
+ The following filter type values can be used in the `filters` array:
110
+
111
+ | Filter Value | Description |
112
+ |----------------|------------------------------------------|
113
+ | `'price'` | Price range slider with min/max values |
114
+ | `'brands'` | Checkboxes for available brands |
115
+ | `'categories'` | Category selection checkboxes |
116
+ | `'fulfillment'`| Shipping vs. on-demand delivery toggle |
117
+ | `'engraving'` | Toggle: on shows only personalizable products, off shows all |
118
+ | `'sizes'` | Filter by product size/volume |
119
+ | `'flavor'` | Filter by flavor profile |
120
+ | `'region'` | Filter by region of origin |
121
+ | `'variety'` | Filter by product variety |
122
+ | `'vintage'` | Filter by vintage year |
123
+ | `'country'` | Filter by country of origin |
124
+ | `'appellation'`| Filter by appellation |
125
+ | `'materials'` | Filter by materials |
126
+
127
+ ```javascript
128
+ // Example: use multiple filters
129
+ filters: ['price', 'brands', 'categories', 'fulfillment', 'sizes']
130
+ ```
131
+
132
+ Every section of the filters panel is opt-in — `'price'`, `'fulfillment'` and `'engraving'`
133
+ included. A value you leave out of the array is not rendered, and an empty array draws no
134
+ filters panel at all. Omit `filters` entirely and the list falls back to the server-configured
135
+ defaults for that slug.
136
+
137
+ Sections render **collapsed**; the shopper opens the ones they care about. Nothing is
138
+ auto-expanded, not even a filter seeded from the URL — an applied value shows as a removable
139
+ chip above the sections, so it stays visible without opening anything.
140
+
141
+ ## URL Query Param Filters
142
+
143
+ 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.
144
+
145
+ ### Whitelist
146
+
147
+ 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:
148
+
149
+ 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).
150
+ 2. `data-filters` on the matching `<... -products-list-filters>` container (the common case when a filters panel is mounted).
151
+ 3. `filters` array passed to `injectProductList(...)` programmatically.
152
+ 4. `availableFilters` from the theme config for the list slug (fallback only).
153
+
154
+ ### Supported formats
155
+
156
+ | Filter | URL format | Example |
157
+ | --- | --- | --- |
158
+ | 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` |
159
+ | `fulfillment` | Single value: `all`, `shipping`, or `onDemand` | `?fulfillment=shipping` |
160
+ | `engraving` | `true` or `false` | `?engraving=true` |
161
+ | `price` | `min-max` range; `min-` or `-max` are accepted | `?price=20-150`, `?price=20-`, `?price=-150` |
162
+
163
+ `engraving=true` narrows the list to products that support personalization. `engraving=false` is
164
+ the filter's unset state and narrows nothing — it is equivalent to leaving the param off, not a
165
+ request for products that cannot be personalized.
166
+
167
+ Invalid values are dropped (e.g. `?fulfillment=garbage`, `?price=abc` — no error, the filter just isn't applied). Combining params is supported:
168
+
169
+ ```
170
+ https://yoursite.com/best-sellers?brands=Bacardi&categories=Wine&price=20-150&fulfillment=shipping
171
+ ```
172
+
173
+ ### Behavior
174
+
175
+ - URL params win over any state persisted from a previous session.
176
+ - Once the list mounts, the filters panel (if present) reflects the seeded values, and the initial product fetch is filtered.
177
+ - Subsequent in-page interactions (toggling filters, scrolling, etc.) do not write back to the URL — the URL is read-only at load time.
178
+
179
+ ### Standalone use (no filters component)
180
+
181
+ URL filtering works without injecting a filters panel. Declare the whitelist on the products-list container itself:
182
+
183
+ ```html
184
+ <div
185
+ data-liquid-commerce-elements-products-list="curated-page"
186
+ data-filters="price,brands,categories"
187
+ data-rows="4"
188
+ data-columns="4"
189
+ ></div>
190
+ ```
191
+
192
+ Now `https://yoursite.com/curated-page?brands=Bacardi&price=20-150` filters the list on load even though no filters UI is present.
193
+
194
+ ## Search Functionality
195
+
196
+ ### Search Box
197
+
198
+ The search component provides full-text search across:
199
+ - Product names
200
+ - Descriptions
201
+ - Brand names
202
+ - Categories
203
+ - SKUs/UPCs
204
+
205
+ ### Search Behavior
206
+
207
+ - Real-time search as user types (500ms debounce; fires on any non-empty input — no minimum character count)
208
+ - Input is limited to 100 characters; allowed characters: letters, numbers, spaces, and `- _ ' . , & ( )`
209
+ - Server-side filtering by the search term
210
+ - "Clear search" button appears when active
211
+
212
+ ### Programmatic Search
213
+
214
+ Search is controlled through the injected search component. Use `injectProductListSearch()` to add a search box that automatically filters the associated product list.
215
+
216
+ ## Grid Layout
217
+
218
+ ### Responsive Grid
219
+
220
+ The grid automatically adjusts for screen sizes:
221
+
222
+ **Desktop** (> 1024px):
223
+ - Uses configured columns (e.g., 4 columns)
224
+
225
+ **Tablet** (768px - 1024px):
226
+ - Reduces to 3 or 2 columns
227
+
228
+ **Mobile** (< 768px):
229
+ - Single column or 2 columns depending on space
230
+
231
+ ### Configuring Layout
232
+
233
+ ```javascript
234
+ await client.injectProductList({
235
+ containerId: 'products',
236
+ slug: 'my-collection',
237
+ rows: 5, // Number of rows per page
238
+ columns: 4 // Columns in grid (desktop)
239
+ });
240
+ ```
241
+
242
+ Total products per page = rows × columns (e.g., 5 × 4 = 20 products)
243
+
244
+ ## Product Order
245
+
246
+ By default the grid renders products in the order the API returns them for the
247
+ list's slug. `productOrder` overrides that with an explicit order you control
248
+ from the page.
249
+
250
+ ```javascript
251
+ await client.injectProductList({
252
+ containerId: 'products',
253
+ slug: 'my-collection-slug',
254
+ productOrder: [
255
+ '00832889005513',
256
+ 'GROUPING-33277',
257
+ '00619947000020',
258
+ ],
259
+ });
260
+ ```
261
+
262
+ ```html
263
+ <div
264
+ data-liquid-commerce-elements-products-list="my-collection-slug"
265
+ data-product-order="00832889005513,GROUPING-33277,00619947000020"
266
+ ></div>
267
+ ```
268
+
269
+ **Identifiers.** Each entry is a UPC or a `salsifyGrouping` ID — the same identifier
270
+ concept the [Product URL Map](#product-url-map) keys on and `injectProductElement`
271
+ accepts. The two forms mix freely in one array. A UPC identifies a single size, so
272
+ naming any size of a product positions that product.
273
+
274
+ **It reorders; it does not select.** The slug still decides which products the list
275
+ contains. An identifier for a product outside the list matches nothing, and no error
276
+ is raised. Products the array doesn't name render after the ones it does, keeping
277
+ their API order among themselves — so a partial list reorders only what it names.
278
+
279
+ **Pagination.** A product named early keeps its position even if the API returns it on
280
+ a later page. Each new page is spliced into the grid at the right slots rather than
281
+ appended, so cards already on screen are left untouched — scroll position and keyboard
282
+ focus survive loading a page. For a small curated set, size `rows × columns` to cover
283
+ it in a single page so no scroll is needed at all.
284
+
285
+ **Search and filters** re-query the API for a narrower result set. The order is
286
+ re-applied to whatever comes back, so named products keep their relative order among
287
+ the results that survive.
288
+
289
+ **Nothing about `productOrder` throws.** Ordering is presentational and the grid
290
+ renders fine without it, so a malformed value costs you the ordering and nothing
291
+ else — never the product list itself.
292
+
293
+ - An entry that isn't a non-empty string is skipped with a console warning, the way
294
+ an unrecognized `filters` value is. The surviving entries keep their relative
295
+ order, so the rest of your ordering still applies around the dropped one.
296
+ - A `productOrder` that isn't an array is ignored entirely with a warning, and the
297
+ list renders in the order the API returns.
298
+
299
+ > The warning goes through the SDK logger, which is silent in production and at the
300
+ > default `debugMode: 'none'`. On a live storefront a dropped entry produces no
301
+ > console output at all, so validate the array you generate rather than relying on
302
+ > the warning to surface a bad one.
303
+
304
+ ## Infinite Scroll
305
+
306
+ ### How It Works
307
+
308
+ 1. Initial products load (rows × columns)
309
+ 2. User scrolls to bottom
310
+ 3. Next page loads automatically
311
+ 4. Appends to existing products
312
+ 5. Continues until all products shown
313
+
314
+ ### Loading States
315
+
316
+ Shows loading indicator:
317
+ - On initial load
318
+ - When loading next page
319
+ - When applying filters
320
+ - When searching
321
+
322
+ ### End of Results
323
+
324
+ When all products are shown:
325
+ - Infinite scroll stops
326
+ - Shows "No more products" message
327
+ - Scroll to top button may appear
328
+
329
+ ## Product Cards
330
+
331
+ Each product card shows:
332
+
333
+ - Product image
334
+ - Product name
335
+ - Brand
336
+ - Price (or price range for multiple sizes)
337
+ - Clickable image/card linking to the product detail page (when `productUrl` is configured)
338
+ - "Add to Cart" button (optional)
339
+ - Availability indicator
340
+
341
+ Product card images automatically have their white/near-white backgrounds removed so the product blends into the surrounding card and page background. This treatment is applied at render time and is not host-configurable.
342
+
343
+ ### Card Interaction
344
+
345
+ **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).
346
+
347
+ **Quick Add:** Add product to cart directly from list view (if enabled)
348
+
349
+ **Click on image:** Navigate to the configured `productUrl` (only when `productUrl` is set — otherwise the image is not a link)
350
+
351
+ ### Card Identifiers
352
+
353
+ Each `product-list-card-lc` host carries the product's identifiers as data
354
+ attributes, so a card can be traced back to catalogue data while inspecting the
355
+ page:
356
+
357
+ ```html
358
+ <product-list-card-lc data-grouping="GROUPING-33277" data-upc="00832889005513">
359
+ ```
360
+
361
+ - `data-grouping` — the product's `salsifyGrouping` ID. Fixed for the life of the card.
362
+ - `data-upc` — the **selected size's** UPC, the same value `{upc}` resolves to in a
363
+ `productUrl` template. It updates when the shopper changes size.
364
+
365
+ Both use the identifier forms accepted everywhere else in the SDK, so a value read
366
+ off a card can be pasted straight into `productOrder`, a `productUrl` map key, or
367
+ `injectProductElement`.
368
+
369
+ > **These are for inspection, not for scripting.** Cards render inside the SDK's
370
+ > shadow root, which is **always closed in production** — `openShadowDom` is forced
371
+ > to `false` there and only has effect in development. Chrome DevTools displays
372
+ > closed shadow roots, so the attributes are visible when inspecting the page, but
373
+ > `document.querySelector('[data-upc]')` from partner JavaScript will not reach them
374
+ > on a live storefront. To react to card activity from your own code, use the
375
+ > [events](#events) instead.
376
+
377
+ ## Customization
378
+
379
+ ### Theme Configuration
380
+
381
+ Product list theming is applied per-list using the collection slug as a key:
382
+
383
+ ```javascript
384
+ const client = await Elements('YOUR_API_KEY', {
385
+ env: 'production',
386
+ customTheme: {
387
+ productList: {
388
+ theme: {
389
+ backgroundColor: '#ffffff'
390
+ },
391
+ layout: {
392
+ lists: {
393
+ 'my-collection-slug': {
394
+ productCard: {
395
+ style: 'card', // 'card' or 'ghost'
396
+ cornerRadius: '8px',
397
+ showPrice: true,
398
+ showSizes: true,
399
+ showRetailerName: true,
400
+ showFulfillmentOptions: true,
401
+ enableShippingFulfillment: true,
402
+ enableOnDemandFulfillment: true,
403
+ enablePersonalization: true,
404
+ showQuantityCounter: true,
405
+ enablePreCart: true,
406
+ showCollectionTags: false
407
+ },
408
+ presentationMode: 'drawer', // 'drawer' or 'modal'
409
+ rows: 4,
410
+ columns: 3
411
+ }
412
+ }
413
+ }
414
+ }
415
+ }
416
+ });
417
+ ```
418
+
419
+ See [Configuration Reference](../api/configuration.md#product-list-theme) for the complete list of options.
420
+
421
+ ## Use Cases
422
+
423
+ ### Category Page
424
+
425
+ ```html
426
+ <!DOCTYPE html>
427
+ <html>
428
+ <head>
429
+ <title>Whiskey Collection</title>
430
+ <script
431
+ defer
432
+ data-liquid-commerce-elements
433
+ data-token="YOUR_API_KEY"
434
+ data-env="production"
435
+ src="https://elements.reservebar-worker.workers.dev/all/elements.js"
436
+ ></script>
437
+ </head>
438
+ <body>
439
+ <h1>Whiskey Collection</h1>
440
+
441
+ <!-- Search -->
442
+ <div data-liquid-commerce-elements-products-list-search="whiskey-collection"></div>
443
+
444
+ <div class="catalog">
445
+ <!-- Filters sidebar -->
446
+ <aside>
447
+ <div data-liquid-commerce-elements-products-list-filters="whiskey-collection" data-filters="price,brands,sizes"></div>
448
+ </aside>
449
+
450
+ <!-- Product grid -->
451
+ <main>
452
+ <div
453
+ data-liquid-commerce-elements-products-list="whiskey-collection"
454
+ data-rows="4"
455
+ data-columns="3"
456
+ data-product-url="/whiskey/{grouping}"
457
+ ></div>
458
+ </main>
459
+ </div>
460
+ </body>
461
+ </html>
462
+ ```
463
+
464
+ ### Search Results Page
465
+
466
+ ```javascript
467
+ import { Elements } from '@liquidcommerce/elements-sdk';
468
+
469
+ const client = await Elements('YOUR_API_KEY', { env: 'production' });
470
+
471
+ // Inject product list with search
472
+ await client.injectProductList({
473
+ containerId: 'search-results',
474
+ slug: 'all-products',
475
+ rows: 5,
476
+ columns: 4,
477
+ filters: ['price', 'brands', 'categories']
478
+ });
479
+
480
+ await client.injectProductListSearch({
481
+ containerId: 'search-box',
482
+ slug: 'all-products'
483
+ });
484
+ ```
485
+
486
+ ### Custom Product URL Patterns
487
+
488
+ Different URL patterns for different product types:
489
+
490
+ ```javascript
491
+ // Get product type from data
492
+ const productType = getProductTypeFromData();
493
+
494
+ let urlPattern;
495
+ switch (productType) {
496
+ case 'whiskey':
497
+ urlPattern = '/spirits/whiskey/{grouping}';
498
+ break;
499
+ case 'wine':
500
+ urlPattern = '/wine/{grouping}';
501
+ break;
502
+ default:
503
+ urlPattern = '/products/{grouping}';
504
+ }
505
+
506
+ await client.injectProductList({
507
+ containerId: 'products',
508
+ slug: 'all-products',
509
+ rows: 3,
510
+ columns: 4,
511
+ productUrl: urlPattern
512
+ });
513
+ ```
514
+
515
+ ### Product URL Map
516
+
517
+ For partners whose PDPs have hand-curated URLs that aren't derivable from a
518
+ single placeholder (e.g. dedicated marketing pages, Shopify handles, WordPress
519
+ slugs), pass a **map** instead of a string template. Keys are product
520
+ identifiers — either a UPC or a salsifyGrouping ID, the same identifier types
521
+ accepted by `injectProductElement`. The card looks up UPC first, then grouping
522
+ ID; products not in the map render without a link.
523
+
524
+ #### Declarative — JSON script tag
525
+
526
+ Drop a single `<script type="application/json">` tag anywhere on the page,
527
+ keyed by list slug → identifier → URL. Generate it server-side from your CMS.
528
+
529
+ ```html
530
+ <script data-liquid-commerce-elements-product-urls type="application/json">
531
+ {
532
+ "best-sellers": {
533
+ "GROUPING-33277": "/wines/macallan-12-special-edition",
534
+ "00832889005513": "/spirits/cabernet-2018-club-only"
535
+ },
536
+ "limited-releases": {
537
+ "GROUPING-78941": "/exclusive/pappy-23-allocation"
538
+ }
539
+ }
540
+ </script>
541
+
542
+ <div data-liquid-commerce-elements-products-list="best-sellers"></div>
543
+ ```
544
+
545
+ When both `data-product-url` and a slug entry in this script are present for
546
+ the same list, the **map wins** — it's the more specific intent.
547
+
548
+ ##### Shopify Liquid
549
+
550
+ ```liquid
551
+ <script data-liquid-commerce-elements-product-urls type="application/json">
552
+ {
553
+ "best-sellers": {
554
+ {% for p in collections.best-sellers.products %}
555
+ "{{ p.metafields.lc.grouping_id }}": "{{ p.url }}"{% unless forloop.last %},{% endunless %}
556
+ {% endfor %}
557
+ }
558
+ }
559
+ </script>
560
+ ```
561
+
562
+ ##### WordPress / WooCommerce (PHP)
563
+
564
+ ```php
565
+ <script data-liquid-commerce-elements-product-urls type="application/json">
566
+ <?= json_encode(['best-sellers' => $lc_identifier_to_pdp_url_map]) ?>
567
+ </script>
568
+ ```
569
+
570
+ #### Programmatic
571
+
572
+ ```javascript
573
+ await client.injectProductList({
574
+ containerId: 'products',
575
+ slug: 'best-sellers',
576
+ rows: 3,
577
+ columns: 4,
578
+ productUrl: {
579
+ 'GROUPING-33277': '/wines/macallan-12-special-edition',
580
+ '00832889005513': '/spirits/cabernet-2018-club-only',
581
+ },
582
+ });
583
+ ```
584
+
585
+ ## Events
586
+
587
+ While product list events are primarily internal, you can listen for cart events when users add products:
588
+
589
+ ```javascript
590
+ window.addEventListener('lce:actions.cart_item_added', (event) => {
591
+ const { itemId, quantity } = event.detail.data;
592
+ console.log(`Product added from list: ${itemId}`);
593
+ });
594
+ ```
595
+
596
+ ## Accessibility
597
+
598
+ The product list component includes:
599
+
600
+ - Keyboard navigation support
601
+ - Screen reader labels
602
+ - ARIA attributes for filters and search
603
+ - Focus management
604
+ - High contrast support
605
+
606
+ ### Keyboard Shortcuts
607
+
608
+ - `Tab`: Navigate between products and filters
609
+ - `Enter/Space`: Select product or toggle filter
610
+ - `Escape`: Clear search or close filters
611
+ - `Arrow keys`: Navigate grid (when focused)
612
+
613
+ ## Performance
614
+
615
+ ### Optimization Features
616
+
617
+ - **Image lazy loading**: Images load as they enter viewport
618
+ - **Progressive loading**: Products load in batches via an `IntersectionObserver` sentinel as you scroll — each page is appended to the grid and loaded cards remain in the DOM
619
+ - **Debounced search**: Reduces API calls during typing
620
+
621
+ ### Large Catalogs
622
+
623
+ For catalogs with thousands of products:
624
+
625
+ ```javascript
626
+ await client.injectProductList({
627
+ containerId: 'products',
628
+ slug: 'all-products',
629
+ rows: 3,
630
+ columns: 4,
631
+ filters: ['price', 'brands'], // Limit filters to most useful
632
+ // More rows = larger pages = fewer API calls
633
+ });
634
+ ```
635
+
636
+ ## Best Practices
637
+
638
+ ### Provide Clear Navigation
639
+
640
+ ```html
641
+ <nav class="breadcrumb">
642
+ <a href="/">Home</a> &gt;
643
+ <a href="/products">Products</a> &gt;
644
+ <span>Whiskey</span>
645
+ </nav>
646
+ ```
647
+
648
+ ### Show Result Counts
649
+
650
+ The product list component automatically displays the number of results. You can also track cart additions from the list using standard cart events:
651
+
652
+ ```javascript
653
+ window.addEventListener('lce:actions.cart_item_added', (event) => {
654
+ console.log('Item added from product list:', event.detail.data);
655
+ });
656
+ ```
657
+
658
+ ### Mobile-First Design
659
+
660
+ Ensure filters work well on mobile:
661
+
662
+ ```css
663
+ @media (max-width: 768px) {
664
+ .filters-sidebar {
665
+ position: fixed;
666
+ bottom: 0;
667
+ left: 0;
668
+ right: 0;
669
+ transform: translateY(100%);
670
+ transition: transform 0.3s;
671
+ }
672
+
673
+ .filters-sidebar.open {
674
+ transform: translateY(0);
675
+ }
676
+ }
677
+ ```
678
+
679
+ ### Default to Relevant Filters
680
+
681
+ For category pages, pre-select relevant filters:
682
+
683
+ ```javascript
684
+ // On whiskey category page
685
+ await client.injectProductList({
686
+ containerId: 'products',
687
+ slug: 'whiskey-collection',
688
+ rows: 4,
689
+ columns: 3,
690
+ filters: ['price', 'brands', 'sizes'] // Most relevant for whiskey
691
+ });
692
+ ```
693
+
694
+ ## Troubleshooting
695
+
696
+ ### Products Not Loading
697
+
698
+ 1. Check browser console for errors
699
+ 2. Verify API key is correct
700
+ 3. Ensure container ID exists
701
+ 4. Check network tab for API responses
702
+ 5. Verify products exist in catalog
703
+
704
+ ### Filters Not Working
705
+
706
+ 1. Ensure filter types are spelled correctly
707
+ 2. Check that products have filterable attributes
708
+ 3. Verify theme config allows filters
709
+ 4. Look for JavaScript errors
710
+
711
+ ### Infinite Scroll Not Triggering
712
+
713
+ 1. Check container has finite height
714
+ 2. Verify scroll event listeners are attached
715
+ 3. Ensure there are more products to load
716
+ 4. Check console for errors
717
+
718
+ ### Search Not Finding Products
719
+
720
+ 1. Verify the input uses allowed characters and is under the 100-character limit
721
+ 2. Check search is not case-sensitive (it shouldn't be)
722
+ 3. Ensure products have searchable text fields
723
+ 4. Look for API errors in network tab
724
+
725
+ ## See Also
726
+
727
+ - [Product Component](./product-component.md) - Individual product display
728
+ - [Cart Component](./cart-component.md) - Add products to cart
729
+ - [Theming](./theming.md) - Customize appearance
730
+ - [Events](./events.md) - Available events