@salla.sa/twilight-components 2.14.486 → 2.14.487

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 (336) hide show
  1. package/dist/cjs/{Helper-DvyEpCgx.js → Helper-B2B-kxAI.js} +7 -2
  2. package/dist/cjs/{filepond-BtDP9OW9.js → filepond-D8YNIT7U.js} +1 -1
  3. package/dist/cjs/{filepond-plugin-file-poster-CTf1Ej_n.js → filepond-plugin-file-poster-DSZGbtH3.js} +1 -1
  4. package/dist/cjs/{filepond-plugin-file-validate-size-_wVJpYXF.js → filepond-plugin-file-validate-size-CDPCt-vD.js} +1 -1
  5. package/dist/cjs/{filepond-plugin-file-validate-type-DWoo5Lcs.js → filepond-plugin-file-validate-type-PPR9wk_f.js} +1 -1
  6. package/dist/cjs/{filepond-plugin-image-edit-DBb_5aN9.js → filepond-plugin-image-edit-CbzNxXz5.js} +1 -1
  7. package/dist/cjs/{filepond-plugin-image-exif-orientation-Nnwt-m9k.js → filepond-plugin-image-exif-orientation-CHOCkxIA.js} +1 -1
  8. package/dist/cjs/{filepond-plugin-image-preview-CjBwZm3E.js → filepond-plugin-image-preview-DPzPSwHT.js} +1 -1
  9. package/dist/cjs/{functions-DkS9Jmao.js → functions-BJ567SZR.js} +1 -1
  10. package/dist/cjs/{index-C0yFagl6.js → index-AuVRM2C2.js} +1 -1
  11. package/dist/cjs/{index-C_WIlgE2.js → index-KEg0BIuu.js} +6 -2
  12. package/dist/cjs/loader.cjs.js +2 -2
  13. package/dist/cjs/salla-accordion-body_2.cjs.entry.js +1 -1
  14. package/dist/cjs/salla-accordion_6.cjs.entry.js +2 -2
  15. package/dist/cjs/salla-add-product-button_5.cjs.entry.js +2 -2
  16. package/dist/cjs/salla-advertisement.cjs.entry.js +1 -1
  17. package/dist/cjs/salla-alert_2.cjs.entry.js +1 -1
  18. package/dist/cjs/salla-app-install-alert.cjs.entry.js +1 -1
  19. package/dist/cjs/salla-apps-icons.cjs.entry.js +1 -1
  20. package/dist/cjs/salla-badge.cjs.entry.js +1 -1
  21. package/dist/cjs/salla-booking-field_7.cjs.entry.js +11 -11
  22. package/dist/cjs/salla-bullet-delivery_2.cjs.entry.js +1 -1
  23. package/dist/cjs/salla-cart-coupons.cjs.entry.js +1 -1
  24. package/dist/cjs/salla-cart-item-offers_2.cjs.entry.js +1 -1
  25. package/dist/cjs/salla-cart-summary-card.cjs.entry.js +349 -0
  26. package/dist/cjs/salla-cashback-banner.cjs.entry.js +1 -1
  27. package/dist/cjs/salla-comment-form_8.cjs.entry.js +2 -2
  28. package/dist/cjs/salla-conditional-offer.cjs.entry.js +1 -1
  29. package/dist/cjs/salla-contacts.cjs.entry.js +1 -1
  30. package/dist/cjs/salla-cookies-bar.cjs.entry.js +1 -1
  31. package/dist/cjs/salla-count-down.cjs.entry.js +1 -1
  32. package/dist/cjs/salla-custom-fields.cjs.entry.js +1 -1
  33. package/dist/cjs/salla-delivery-promise.cjs.entry.js +1 -1
  34. package/dist/cjs/salla-edit-order-button.cjs.entry.js +1 -1
  35. package/dist/cjs/salla-filters-widget.cjs.entry.js +15 -8
  36. package/dist/cjs/salla-filters.cjs.entry.js +101 -13
  37. package/dist/cjs/salla-fulfillment-methods.cjs.entry.js +1 -1
  38. package/dist/cjs/salla-gifting.cjs.entry.js +1 -1
  39. package/dist/cjs/salla-hook.cjs.entry.js +1 -1
  40. package/dist/cjs/salla-infinite-scroll.cjs.entry.js +2 -2
  41. package/dist/cjs/salla-installment.cjs.entry.js +1 -1
  42. package/dist/cjs/salla-list-tile.cjs.entry.js +1 -1
  43. package/dist/cjs/salla-localization-modal.cjs.entry.js +1 -1
  44. package/dist/cjs/salla-login-modal.cjs.entry.js +1 -1
  45. package/dist/cjs/salla-loyalty-banner.cjs.entry.js +2 -2
  46. package/dist/cjs/salla-loyalty-hero_2.cjs.entry.js +2 -2
  47. package/dist/cjs/salla-loyalty-panel.cjs.entry.js +3 -3
  48. package/dist/cjs/salla-loyalty-points-banner.cjs.entry.js +1 -1
  49. package/dist/cjs/salla-loyalty-points-history.cjs.entry.js +1 -1
  50. package/dist/cjs/salla-loyalty-prize-item.cjs.entry.js +1 -1
  51. package/dist/cjs/salla-loyalty-program.cjs.entry.js +3 -3
  52. package/dist/cjs/salla-loyalty-reward.cjs.entry.js +2 -2
  53. package/dist/cjs/salla-loyalty.cjs.entry.js +1 -1
  54. package/dist/cjs/salla-maintenance-alert.cjs.entry.js +1 -1
  55. package/dist/cjs/salla-map_2.cjs.entry.js +1 -1
  56. package/dist/cjs/salla-menu.cjs.entry.js +1 -1
  57. package/dist/cjs/salla-metadata.cjs.entry.js +1 -1
  58. package/dist/cjs/salla-multiple-bundle-product-cart_2.cjs.entry.js +1 -1
  59. package/dist/cjs/salla-multiple-bundle-product-options-modal_2.cjs.entry.js +1 -1
  60. package/dist/cjs/salla-multiple-bundle-product.cjs.entry.js +1 -1
  61. package/dist/cjs/salla-next-order-coupon.cjs.entry.js +1 -1
  62. package/dist/cjs/salla-notification-item.cjs.entry.js +1 -1
  63. package/dist/cjs/salla-notifications.cjs.entry.js +2 -2
  64. package/dist/cjs/salla-offer-modal.cjs.entry.js +1 -1
  65. package/dist/cjs/salla-offer.cjs.entry.js +1 -1
  66. package/dist/cjs/salla-order-branch.cjs.entry.js +1 -1
  67. package/dist/cjs/salla-order-details-multiple-bundle-product.cjs.entry.js +1 -1
  68. package/dist/cjs/salla-order-details-options.cjs.entry.js +1 -1
  69. package/dist/cjs/salla-order-details.cjs.entry.js +1 -1
  70. package/dist/cjs/salla-order-edit-item.cjs.entry.js +1 -1
  71. package/dist/cjs/salla-order-edit-product-card.cjs.entry.js +1 -1
  72. package/dist/cjs/salla-order-edit.cjs.entry.js +1 -1
  73. package/dist/cjs/salla-order-options-modal_3.cjs.entry.js +2 -2
  74. package/dist/cjs/salla-order-summary.cjs.entry.js +1 -1
  75. package/dist/cjs/salla-order-totals-card.cjs.entry.js +1 -1
  76. package/dist/cjs/salla-orders.cjs.entry.js +2 -2
  77. package/dist/cjs/salla-payments.cjs.entry.js +1 -1
  78. package/dist/cjs/salla-placeholder.cjs.entry.js +1 -1
  79. package/dist/cjs/salla-price-range.cjs.entry.js +1 -1
  80. package/dist/cjs/salla-product-card-embed.cjs.entry.js +1 -1
  81. package/dist/cjs/salla-product-size-guide.cjs.entry.js +1 -1
  82. package/dist/cjs/salla-products-list.cjs.entry.js +21 -9
  83. package/dist/cjs/salla-quick-order.cjs.entry.js +1 -1
  84. package/dist/cjs/salla-rating-modal.cjs.entry.js +2 -2
  85. package/dist/cjs/salla-reward-action_4.cjs.entry.js +3 -3
  86. package/dist/cjs/salla-scopes.cjs.entry.js +1 -1
  87. package/dist/cjs/salla-search.cjs.entry.js +2 -2
  88. package/dist/cjs/salla-skeleton.cjs.entry.js +1 -1
  89. package/dist/cjs/salla-slider.cjs.entry.js +1 -1
  90. package/dist/cjs/salla-social-share.cjs.entry.js +1 -1
  91. package/dist/cjs/salla-social.cjs.entry.js +1 -1
  92. package/dist/cjs/salla-tab-content_3.cjs.entry.js +1 -1
  93. package/dist/cjs/salla-tiered-offer.cjs.entry.js +1 -1
  94. package/dist/cjs/salla-tooltip.cjs.entry.js +1 -1
  95. package/dist/cjs/salla-trust-badges.cjs.entry.js +1 -1
  96. package/dist/cjs/salla-user-menu.cjs.entry.js +1 -1
  97. package/dist/cjs/salla-user-profile.cjs.entry.js +1 -1
  98. package/dist/cjs/salla-user-settings.cjs.entry.js +1 -1
  99. package/dist/cjs/salla-verify.cjs.entry.js +1 -1
  100. package/dist/cjs/salla-wallet.cjs.entry.js +1 -1
  101. package/dist/cjs/salla-wishlist-actions.cjs.entry.js +1 -1
  102. package/dist/cjs/{tracked-promise-TyxTPR6e.js → tracked-promise-DFl5fI3j.js} +1 -1
  103. package/dist/cjs/twilight.cjs.js +2 -2
  104. package/dist/cjs/{vanilla-picker-DyJFw96R.js → vanilla-picker-CUpM_-PS.js} +1 -1
  105. package/dist/collection/Helpers/Helper.js +7 -2
  106. package/dist/collection/collection-manifest.json +1 -0
  107. package/dist/collection/components/salla-cart-summary-card/salla-cart-summary-card.js +401 -0
  108. package/dist/collection/components/salla-filters/salla-filters.css +5 -0
  109. package/dist/collection/components/salla-filters/salla-filters.js +101 -11
  110. package/dist/collection/components/salla-filters-widget/salla-filters-widget.js +13 -6
  111. package/dist/collection/components/salla-products-list/salla-products-list.js +19 -7
  112. package/dist/components/Helper.js +7 -2
  113. package/dist/components/index.js +2 -2
  114. package/dist/components/salla-cart-summary-card.d.ts +11 -0
  115. package/dist/components/salla-cart-summary-card.js +404 -0
  116. package/dist/components/salla-filters-widget2.js +13 -6
  117. package/dist/components/salla-filters.js +101 -11
  118. package/dist/components/salla-products-list2.js +19 -7
  119. package/dist/esm/{Helper-CD8d-Brd.js → Helper-BQ9mvrt9.js} +7 -2
  120. package/dist/esm/{filepond-ZiatSU0Y.js → filepond-BsLighF8.js} +1 -1
  121. package/dist/esm/{filepond-plugin-file-poster-2WAWdRm2.js → filepond-plugin-file-poster-Bm-5APBo.js} +1 -1
  122. package/dist/esm/{filepond-plugin-file-validate-size-DhLjP7aF.js → filepond-plugin-file-validate-size-DkYobKMY.js} +1 -1
  123. package/dist/esm/{filepond-plugin-file-validate-type-HH8AZXAq.js → filepond-plugin-file-validate-type-BXKbNDGH.js} +1 -1
  124. package/dist/esm/{filepond-plugin-image-edit-BWBtBfk1.js → filepond-plugin-image-edit-B64dqBYZ.js} +1 -1
  125. package/dist/esm/{filepond-plugin-image-exif-orientation-CQyPB3lV.js → filepond-plugin-image-exif-orientation-BelOzBrj.js} +1 -1
  126. package/dist/esm/{filepond-plugin-image-preview-D6MiVWr1.js → filepond-plugin-image-preview-X67Ek3oE.js} +1 -1
  127. package/dist/esm/{functions-DflaFDbL.js → functions-DobdGlrA.js} +1 -1
  128. package/dist/esm/{index-BF901xIc.js → index-DBMDFsFH.js} +6 -2
  129. package/dist/esm/{index-Co2lT5R8.js → index-yDeCyY3S.js} +1 -1
  130. package/dist/esm/loader.js +3 -3
  131. package/dist/esm/salla-accordion-body_2.entry.js +1 -1
  132. package/dist/esm/salla-accordion_6.entry.js +2 -2
  133. package/dist/esm/salla-add-product-button_5.entry.js +2 -2
  134. package/dist/esm/salla-advertisement.entry.js +1 -1
  135. package/dist/esm/salla-alert_2.entry.js +1 -1
  136. package/dist/esm/salla-app-install-alert.entry.js +1 -1
  137. package/dist/esm/salla-apps-icons.entry.js +1 -1
  138. package/dist/esm/salla-badge.entry.js +1 -1
  139. package/dist/esm/salla-booking-field_7.entry.js +11 -11
  140. package/dist/esm/salla-bullet-delivery_2.entry.js +1 -1
  141. package/dist/esm/salla-cart-coupons.entry.js +1 -1
  142. package/dist/esm/salla-cart-item-offers_2.entry.js +1 -1
  143. package/dist/esm/salla-cart-summary-card.entry.js +347 -0
  144. package/dist/esm/salla-cashback-banner.entry.js +1 -1
  145. package/dist/esm/salla-comment-form_8.entry.js +2 -2
  146. package/dist/esm/salla-conditional-offer.entry.js +1 -1
  147. package/dist/esm/salla-contacts.entry.js +1 -1
  148. package/dist/esm/salla-cookies-bar.entry.js +1 -1
  149. package/dist/esm/salla-count-down.entry.js +1 -1
  150. package/dist/esm/salla-custom-fields.entry.js +1 -1
  151. package/dist/esm/salla-delivery-promise.entry.js +1 -1
  152. package/dist/esm/salla-edit-order-button.entry.js +1 -1
  153. package/dist/esm/salla-filters-widget.entry.js +15 -8
  154. package/dist/esm/salla-filters.entry.js +101 -13
  155. package/dist/esm/salla-fulfillment-methods.entry.js +1 -1
  156. package/dist/esm/salla-gifting.entry.js +1 -1
  157. package/dist/esm/salla-hook.entry.js +1 -1
  158. package/dist/esm/salla-infinite-scroll.entry.js +2 -2
  159. package/dist/esm/salla-installment.entry.js +1 -1
  160. package/dist/esm/salla-list-tile.entry.js +1 -1
  161. package/dist/esm/salla-localization-modal.entry.js +1 -1
  162. package/dist/esm/salla-login-modal.entry.js +1 -1
  163. package/dist/esm/salla-loyalty-banner.entry.js +2 -2
  164. package/dist/esm/salla-loyalty-hero_2.entry.js +2 -2
  165. package/dist/esm/salla-loyalty-panel.entry.js +3 -3
  166. package/dist/esm/salla-loyalty-points-banner.entry.js +1 -1
  167. package/dist/esm/salla-loyalty-points-history.entry.js +1 -1
  168. package/dist/esm/salla-loyalty-prize-item.entry.js +1 -1
  169. package/dist/esm/salla-loyalty-program.entry.js +3 -3
  170. package/dist/esm/salla-loyalty-reward.entry.js +2 -2
  171. package/dist/esm/salla-loyalty.entry.js +1 -1
  172. package/dist/esm/salla-maintenance-alert.entry.js +1 -1
  173. package/dist/esm/salla-map_2.entry.js +1 -1
  174. package/dist/esm/salla-menu.entry.js +1 -1
  175. package/dist/esm/salla-metadata.entry.js +1 -1
  176. package/dist/esm/salla-multiple-bundle-product-cart_2.entry.js +1 -1
  177. package/dist/esm/salla-multiple-bundle-product-options-modal_2.entry.js +1 -1
  178. package/dist/esm/salla-multiple-bundle-product.entry.js +1 -1
  179. package/dist/esm/salla-next-order-coupon.entry.js +1 -1
  180. package/dist/esm/salla-notification-item.entry.js +1 -1
  181. package/dist/esm/salla-notifications.entry.js +2 -2
  182. package/dist/esm/salla-offer-modal.entry.js +1 -1
  183. package/dist/esm/salla-offer.entry.js +1 -1
  184. package/dist/esm/salla-order-branch.entry.js +1 -1
  185. package/dist/esm/salla-order-details-multiple-bundle-product.entry.js +1 -1
  186. package/dist/esm/salla-order-details-options.entry.js +1 -1
  187. package/dist/esm/salla-order-details.entry.js +1 -1
  188. package/dist/esm/salla-order-edit-item.entry.js +1 -1
  189. package/dist/esm/salla-order-edit-product-card.entry.js +1 -1
  190. package/dist/esm/salla-order-edit.entry.js +1 -1
  191. package/dist/esm/salla-order-options-modal_3.entry.js +2 -2
  192. package/dist/esm/salla-order-summary.entry.js +1 -1
  193. package/dist/esm/salla-order-totals-card.entry.js +1 -1
  194. package/dist/esm/salla-orders.entry.js +2 -2
  195. package/dist/esm/salla-payments.entry.js +1 -1
  196. package/dist/esm/salla-placeholder.entry.js +1 -1
  197. package/dist/esm/salla-price-range.entry.js +1 -1
  198. package/dist/esm/salla-product-card-embed.entry.js +1 -1
  199. package/dist/esm/salla-product-size-guide.entry.js +1 -1
  200. package/dist/esm/salla-products-list.entry.js +21 -9
  201. package/dist/esm/salla-quick-order.entry.js +1 -1
  202. package/dist/esm/salla-rating-modal.entry.js +2 -2
  203. package/dist/esm/salla-reward-action_4.entry.js +3 -3
  204. package/dist/esm/salla-scopes.entry.js +1 -1
  205. package/dist/esm/salla-search.entry.js +2 -2
  206. package/dist/esm/salla-skeleton.entry.js +1 -1
  207. package/dist/esm/salla-slider.entry.js +1 -1
  208. package/dist/esm/salla-social-share.entry.js +1 -1
  209. package/dist/esm/salla-social.entry.js +1 -1
  210. package/dist/esm/salla-tab-content_3.entry.js +1 -1
  211. package/dist/esm/salla-tiered-offer.entry.js +1 -1
  212. package/dist/esm/salla-tooltip.entry.js +1 -1
  213. package/dist/esm/salla-trust-badges.entry.js +1 -1
  214. package/dist/esm/salla-user-menu.entry.js +1 -1
  215. package/dist/esm/salla-user-profile.entry.js +1 -1
  216. package/dist/esm/salla-user-settings.entry.js +1 -1
  217. package/dist/esm/salla-verify.entry.js +1 -1
  218. package/dist/esm/salla-wallet.entry.js +1 -1
  219. package/dist/esm/salla-wishlist-actions.entry.js +1 -1
  220. package/dist/esm/{tracked-promise-CNdO8SSl.js → tracked-promise-6uJz7V9Q.js} +1 -1
  221. package/dist/esm/twilight.js +3 -3
  222. package/dist/esm/{vanilla-picker-YVpipuL-.js → vanilla-picker-Bw2Vk5YA.js} +1 -1
  223. package/dist/twilight/{p-d6da8710.entry.js → p-000022be.entry.js} +1 -1
  224. package/dist/twilight/{p-aa928350.entry.js → p-00fcfe8e.entry.js} +1 -1
  225. package/dist/twilight/{p-c01e3f1d.entry.js → p-0412fe67.entry.js} +1 -1
  226. package/dist/twilight/{p-2192d7c2.entry.js → p-08dfa3c5.entry.js} +1 -1
  227. package/dist/twilight/{p-22405eaa.entry.js → p-0c219cad.entry.js} +1 -1
  228. package/dist/twilight/{p-bcfe04fa.entry.js → p-11f843fd.entry.js} +1 -1
  229. package/dist/twilight/{p-ce8571e3.entry.js → p-130633cc.entry.js} +1 -1
  230. package/dist/twilight/{p-ad5c8d34.entry.js → p-1450bf80.entry.js} +1 -1
  231. package/dist/twilight/{p-a5895e0f.entry.js → p-14e936b0.entry.js} +1 -1
  232. package/dist/twilight/{p-beb2df03.entry.js → p-1547f282.entry.js} +1 -1
  233. package/dist/twilight/p-18efb27e.entry.js +4 -0
  234. package/dist/twilight/{p-1d3efd00.entry.js → p-18f264f9.entry.js} +1 -1
  235. package/dist/twilight/p-1b4fd0db.entry.js +4 -0
  236. package/dist/twilight/{p-77b6fbf2.entry.js → p-1bb06699.entry.js} +1 -1
  237. package/dist/twilight/{p-518bab79.entry.js → p-1e418b8f.entry.js} +1 -1
  238. package/dist/twilight/p-24d268c7.entry.js +4 -0
  239. package/dist/twilight/{p-2eb78125.entry.js → p-29620c50.entry.js} +1 -1
  240. package/dist/twilight/{p-9db7e318.entry.js → p-2f48e8e1.entry.js} +1 -1
  241. package/dist/twilight/{p-67b225d5.entry.js → p-37ced7ab.entry.js} +1 -1
  242. package/dist/twilight/{p-1c4e7c18.entry.js → p-39a49ae9.entry.js} +1 -1
  243. package/dist/twilight/{p-6976c445.entry.js → p-3a7f5c6e.entry.js} +1 -1
  244. package/dist/twilight/{p-e304cb5e.entry.js → p-3f153e79.entry.js} +1 -1
  245. package/dist/twilight/{p-4e2f144a.entry.js → p-4336dce1.entry.js} +1 -1
  246. package/dist/twilight/{p-7ce2c5ca.entry.js → p-44f67d40.entry.js} +1 -1
  247. package/dist/twilight/{p-e692322c.entry.js → p-46294bef.entry.js} +1 -1
  248. package/dist/twilight/{p-18ad7499.entry.js → p-4836c3eb.entry.js} +1 -1
  249. package/dist/twilight/{p-be632d40.entry.js → p-49275f85.entry.js} +1 -1
  250. package/dist/twilight/{p-43ab561c.entry.js → p-4a3ccff2.entry.js} +1 -1
  251. package/dist/twilight/{p-a7d99355.entry.js → p-4f8ec3a6.entry.js} +1 -1
  252. package/dist/twilight/{p-2e4fe427.entry.js → p-5119fe5d.entry.js} +1 -1
  253. package/dist/twilight/{p-ed1e0c2e.entry.js → p-519551ab.entry.js} +1 -1
  254. package/dist/twilight/{p-b8d180fe.entry.js → p-51fbf1bb.entry.js} +1 -1
  255. package/dist/twilight/{p-fe69512c.entry.js → p-52cab4a6.entry.js} +1 -1
  256. package/dist/twilight/{p-0fcc3b26.entry.js → p-546b31a3.entry.js} +1 -1
  257. package/dist/twilight/{p-5476bd33.entry.js → p-57785b92.entry.js} +1 -1
  258. package/dist/twilight/{p-90c58cc5.entry.js → p-5dfb7601.entry.js} +1 -1
  259. package/dist/twilight/{p-02350ded.entry.js → p-5e14fbf5.entry.js} +1 -1
  260. package/dist/twilight/{p-0e2a2a9a.entry.js → p-60545378.entry.js} +1 -1
  261. package/dist/twilight/{p-b7b29da3.entry.js → p-61332673.entry.js} +1 -1
  262. package/dist/twilight/{p-2b58b700.entry.js → p-636e6994.entry.js} +1 -1
  263. package/dist/twilight/{p-a445225d.entry.js → p-67ce35b0.entry.js} +1 -1
  264. package/dist/twilight/{p-c92915e0.entry.js → p-6bdcd67d.entry.js} +1 -1
  265. package/dist/twilight/{p-5c37420e.entry.js → p-6e2b2072.entry.js} +1 -1
  266. package/dist/twilight/{p-9b2f674f.entry.js → p-76672fe3.entry.js} +1 -1
  267. package/dist/twilight/{p-d3f904d0.entry.js → p-79bff80a.entry.js} +1 -1
  268. package/dist/twilight/{p-1a8525af.entry.js → p-7a5894fb.entry.js} +1 -1
  269. package/dist/twilight/{p-0c36ee7c.entry.js → p-7b0f537a.entry.js} +1 -1
  270. package/dist/twilight/{p-8f9e0a7a.entry.js → p-7bd7baa5.entry.js} +1 -1
  271. package/dist/twilight/{p-a047ed06.entry.js → p-8336df51.entry.js} +1 -1
  272. package/dist/twilight/{p-04f5d67b.entry.js → p-8a7f48ce.entry.js} +1 -1
  273. package/dist/twilight/{p-a853a50f.entry.js → p-96779a0c.entry.js} +1 -1
  274. package/dist/twilight/{p-368d3b26.entry.js → p-967d356e.entry.js} +1 -1
  275. package/dist/twilight/{p-a4107435.entry.js → p-9ab52d09.entry.js} +1 -1
  276. package/dist/twilight/{p-BuOjsqYX.js → p-BR9zeoCF.js} +1 -1
  277. package/dist/twilight/{p-BPGtYFVu.js → p-BTYXaopE.js} +1 -1
  278. package/dist/twilight/{p-BrcsejOr.js → p-CDTIhPDr.js} +1 -1
  279. package/dist/twilight/{p-gacShRe2.js → p-CMW3pjiL.js} +1 -1
  280. package/dist/twilight/{p-CMmiX5T8.js → p-C_htBBK4.js} +1 -1
  281. package/dist/twilight/{p-DwHaUky6.js → p-C_vo3xPL.js} +1 -1
  282. package/dist/twilight/{p-Bmy5YF6e.js → p-CcfoPQKG.js} +1 -1
  283. package/dist/twilight/{p-BF901xIc.js → p-DBMDFsFH.js} +1 -1
  284. package/dist/twilight/{p-KNG8mGcV.js → p-Dwu1e7SR.js} +1 -1
  285. package/dist/twilight/p-XnA1YTjA.js +4 -0
  286. package/dist/twilight/{p-8f006eca.entry.js → p-a767d9fe.entry.js} +1 -1
  287. package/dist/twilight/{p-506a2720.entry.js → p-ab404907.entry.js} +1 -1
  288. package/dist/twilight/{p-9f6a0804.entry.js → p-acd8aa32.entry.js} +1 -1
  289. package/dist/twilight/{p-b32e5ad7.entry.js → p-ad1d3cdf.entry.js} +1 -1
  290. package/dist/twilight/{p-f3b24cce.entry.js → p-b3b050e7.entry.js} +1 -1
  291. package/dist/twilight/{p-4b0aa371.entry.js → p-b3b78bf5.entry.js} +1 -1
  292. package/dist/twilight/p-b3f26711.entry.js +4 -0
  293. package/dist/twilight/{p-134988db.entry.js → p-b4f4e0b7.entry.js} +1 -1
  294. package/dist/twilight/{p-4288893b.entry.js → p-b7da726a.entry.js} +1 -1
  295. package/dist/twilight/{p-85b235dc.entry.js → p-b835777d.entry.js} +1 -1
  296. package/dist/twilight/{p-cd4b2301.entry.js → p-c253f69c.entry.js} +1 -1
  297. package/dist/twilight/{p-3eb54d75.entry.js → p-c46cf468.entry.js} +1 -1
  298. package/dist/twilight/{p-c5050e10.entry.js → p-c9608410.entry.js} +1 -1
  299. package/dist/twilight/{p-a6afc8ab.entry.js → p-cc75ae11.entry.js} +1 -1
  300. package/dist/twilight/{p-f4564fdc.entry.js → p-ce0685d1.entry.js} +1 -1
  301. package/dist/twilight/{p-dc093d27.entry.js → p-ce1bc4b0.entry.js} +1 -1
  302. package/dist/twilight/{p-d1048676.entry.js → p-cf1b9798.entry.js} +1 -1
  303. package/dist/twilight/{p-632766e3.entry.js → p-cf96947a.entry.js} +1 -1
  304. package/dist/twilight/{p-bd0075c9.entry.js → p-d01178f0.entry.js} +1 -1
  305. package/dist/twilight/{p-ce633fa0.entry.js → p-d3d2a114.entry.js} +1 -1
  306. package/dist/twilight/{p-f32df318.entry.js → p-d8fb7f9a.entry.js} +1 -1
  307. package/dist/twilight/{p-f5e55c13.entry.js → p-da827143.entry.js} +1 -1
  308. package/dist/twilight/{p-f5e943bb.entry.js → p-ddd22625.entry.js} +1 -1
  309. package/dist/twilight/{p-6b9780be.entry.js → p-de41e9b5.entry.js} +1 -1
  310. package/dist/twilight/p-e21a23d2.entry.js +4 -0
  311. package/dist/twilight/{p-a3a1bf15.entry.js → p-e5022e8f.entry.js} +1 -1
  312. package/dist/twilight/{p-d4eeed4b.entry.js → p-e84f7790.entry.js} +1 -1
  313. package/dist/twilight/{p-f71a7a24.entry.js → p-ef06457d.entry.js} +1 -1
  314. package/dist/twilight/{p-ce38e5a1.entry.js → p-f12670a1.entry.js} +1 -1
  315. package/dist/twilight/{p-d2cc8587.entry.js → p-f267ac72.entry.js} +1 -1
  316. package/dist/twilight/{p-4427e994.entry.js → p-f5d229a7.entry.js} +1 -1
  317. package/dist/twilight/{p-4544ca7d.entry.js → p-f856fe4d.entry.js} +1 -1
  318. package/dist/twilight/{p-4b558e37.entry.js → p-fa900f26.entry.js} +1 -1
  319. package/dist/twilight/{p-c590dcf0.entry.js → p-fd99de6e.entry.js} +1 -1
  320. package/dist/twilight/p-fdb0f6cc.entry.js +4 -0
  321. package/dist/twilight/{p-d92a7d91.entry.js → p-ffd6ad27.entry.js} +1 -1
  322. package/dist/twilight/{p-CwLXCdYY.js → p-lQbFKmnv.js} +1 -1
  323. package/dist/twilight/{p-DVM0Orh8.js → p-qj0-UBFk.js} +1 -1
  324. package/dist/twilight/{p-BEb9UIZ7.js → p-uiIu01tD.js} +1 -1
  325. package/dist/twilight/twilight.esm.js +1 -1
  326. package/dist/types/components/salla-cart-summary-card/salla-cart-summary-card.d.ts +67 -0
  327. package/dist/types/components/salla-filters/salla-filters.d.ts +14 -0
  328. package/dist/types/components/salla-products-list/salla-products-list.d.ts +1 -0
  329. package/dist/types/components.d.ts +37 -0
  330. package/package.json +5 -5
  331. package/dist/twilight/p-0d94f890.entry.js +0 -4
  332. package/dist/twilight/p-2cc32d1f.entry.js +0 -4
  333. package/dist/twilight/p-3d732135.entry.js +0 -4
  334. package/dist/twilight/p-C-3GuKNW.js +0 -4
  335. package/dist/twilight/p-b2a11170.entry.js +0 -4
  336. package/dist/twilight/p-d2cdd923.entry.js +0 -4
@@ -0,0 +1,401 @@
1
+ /*!
2
+ * Crafted with ❤ by Salla
3
+ */
4
+ import { h, Host } from "@stencil/core";
5
+ const SKELETON_ROWS = [
6
+ { label: '100px', value: '56px' },
7
+ { label: '72px', value: '64px' },
8
+ { label: '96px', value: '48px' },
9
+ ];
10
+ /**
11
+ * Cart summary card. Inline on desktop (≥1024px), sticky bar with
12
+ * collapsible sheet on mobile.
13
+ */
14
+ export class SallaCartSummaryCard {
15
+ constructor() {
16
+ this.validateForms = true;
17
+ this.cartCount = 0;
18
+ this.cartTotal = 0;
19
+ this.cartTotalDiscount = 0;
20
+ this.cartSubTotal = 0;
21
+ this.cartOptionsTotal = 0;
22
+ this.cartShippingCost = 0;
23
+ this.cartTaxAmount = 0;
24
+ this.cartHasShipping = false;
25
+ this.isOpen = false;
26
+ this.isDesktop = false;
27
+ /** True until the first cart payload (API response or cart event) arrives. */
28
+ this.isLoading = true;
29
+ // Original DOM location — needed to restore the host on the mobile→desktop flip.
30
+ this.originalParent = null;
31
+ this.originalNextSibling = null;
32
+ this.bodyObserver = null;
33
+ this.mediaQueryList = null;
34
+ this.submitObserver = null;
35
+ this.isSubmitting = false;
36
+ // Stable handler refs — anonymous functions can't be unbound from listeners.
37
+ this.mqlChangeHandler = (e) => {
38
+ this.isDesktop = e.matches;
39
+ this.applyMode();
40
+ };
41
+ this.cartEventNames = [
42
+ 'cart::details.fetched',
43
+ 'cart::updated',
44
+ 'cart::latest.fetched',
45
+ 'cart::coupon.added',
46
+ 'cart::coupon.deleted',
47
+ ];
48
+ this.cartEventHandler = (payload) => this.applyCartData(this.extractCart(payload));
49
+ this.toggleSheet = () => {
50
+ if (!this.isDesktop)
51
+ this.isOpen = !this.isOpen;
52
+ };
53
+ this.handleSubmit = async (event) => {
54
+ // Re-entrancy guard, set before the async validation so a second tap during
55
+ // that window can't fire a second submit. Covers all user types.
56
+ if (this.isSubmitting) {
57
+ event.preventDefault();
58
+ return;
59
+ }
60
+ this.isSubmitting = true;
61
+ if (this.validateForms && !(await this.validateCartForms())) {
62
+ event.preventDefault();
63
+ salla.notify?.error?.(salla.lang?.get?.('common.messages.required_fields'));
64
+ this.isSubmitting = false; // validation failed → allow retry
65
+ return;
66
+ }
67
+ const btn = this.host.querySelector('#s-cart-summary-card-submit');
68
+ if (typeof salla !== 'undefined' && salla.config?.get?.('user.type') !== 'guest' && btn) {
69
+ btn.load?.();
70
+ // Pin loading across re-renders; auto-clear after 10s so a failed submit
71
+ // doesn't lock the button forever.
72
+ this.submitObserver?.disconnect();
73
+ if (this.submitObserverTimeout)
74
+ clearTimeout(this.submitObserverTimeout);
75
+ this.submitObserver = new MutationObserver(() => {
76
+ if (!btn.hasAttribute('loading'))
77
+ btn.setAttribute('loading', '');
78
+ });
79
+ this.submitObserver.observe(btn, { attributes: true, attributeFilter: ['loading'] });
80
+ this.submitObserverTimeout = window.setTimeout(() => {
81
+ this.submitObserver?.disconnect();
82
+ this.submitObserver = null;
83
+ btn.removeAttribute?.('loading');
84
+ }, 10000);
85
+ }
86
+ salla.cart?.submit?.();
87
+ // Release after submit kicks off: success navigates away, a guest opens the
88
+ // login modal. Short delay blocks the double-tap race without a long lock.
89
+ window.setTimeout(() => { this.isSubmitting = false; }, 1500);
90
+ };
91
+ }
92
+ // Sync: returning a promise would make Stencil defer first paint. init() runs async.
93
+ componentWillLoad() {
94
+ this.mediaQueryList = window.matchMedia(this.desktopMediaQuery());
95
+ this.isDesktop = this.mediaQueryList.matches;
96
+ if (this.isDesktop)
97
+ this.isOpen = true;
98
+ // isLoading is true by default → first paint is the skeleton.
99
+ this.init();
100
+ }
101
+ // Not awaited by componentWillLoad, so it can't block first paint.
102
+ async init() {
103
+ await salla.onReady();
104
+ await salla.lang.onLoaded();
105
+ this.loadTranslations();
106
+ // 'cart::updated' is in cartEventNames — don't also use onUpdated (it leaks, no off()).
107
+ this.cartEventNames.forEach(name => salla.event.on(name, this.cartEventHandler));
108
+ this.fetchCart();
109
+ }
110
+ loadTranslations() {
111
+ this.summaryLabel = salla.lang.get('pages.cart.summary');
112
+ this.itemsTotalLabel = salla.lang.get('pages.cart.items_total');
113
+ this.itemsTotalNoTaxLabel = salla.lang.get('pages.cart.items_total_without_tax');
114
+ this.optionsTotalLabel = salla.lang.get('pages.cart.order_options_total');
115
+ this.shippingCostLabel = salla.lang.get('pages.cart.shipping_cost');
116
+ this.vatTaxLabel = salla.lang.get('pages.cart.VAT_tax_amount');
117
+ this.savedLabel = salla.lang.get('pages.cart.discount');
118
+ this.discountBadge = salla.lang.get('pages.cart.saved');
119
+ this.finalTotalLabel = salla.lang.get('pages.cart.final_total');
120
+ this.pricesTaxedLabel = salla.lang.get('pages.cart.prices_taxed');
121
+ this.completeOrderLabel = salla.lang.get('pages.cart.complete_order');
122
+ this.openSummaryLabel = salla.lang.get('pages.cart.open_summary');
123
+ this.closeSummaryLabel = salla.lang.get('pages.cart.close_summary');
124
+ this.itemsCountTemplate = salla.lang.get('pages.cart.items_with_count');
125
+ }
126
+ /** Coerces PHP cart values: numbers, strings, and Money/MoneyTaxable objects. */
127
+ num(v) {
128
+ if (v === null || v === undefined)
129
+ return 0;
130
+ if (typeof v === 'number')
131
+ return isFinite(v) ? v : 0;
132
+ if (typeof v === 'string')
133
+ return parseFloat(v) || 0;
134
+ if (typeof v === 'object') {
135
+ if ('amount' in v)
136
+ return this.num(v.amount);
137
+ if ('value' in v)
138
+ return this.num(v.value);
139
+ if ('formatted' in v)
140
+ return this.num(v.formatted);
141
+ }
142
+ return 0;
143
+ }
144
+ // Desktop cutoff — must match the SCSS media queries so JS and CSS never diverge.
145
+ breakpointPx() {
146
+ return 1024;
147
+ }
148
+ desktopMediaQuery() {
149
+ return `(min-width: ${this.breakpointPx()}px)`;
150
+ }
151
+ componentDidLoad() {
152
+ // Capture original location BEFORE the portal relocates the host.
153
+ this.originalParent = this.host.parentElement;
154
+ this.originalNextSibling = this.host.nextSibling;
155
+ // Re-init if componentWillLoad failed to set it (rare hydration/race edge case).
156
+ if (!this.mediaQueryList) {
157
+ this.mediaQueryList = window.matchMedia(this.desktopMediaQuery());
158
+ this.isDesktop = this.mediaQueryList.matches;
159
+ }
160
+ this.applyMode();
161
+ // iOS Safari < 14 lacks addEventListener on MediaQueryList — fall back to addListener.
162
+ if (this.mediaQueryList.addEventListener) {
163
+ this.mediaQueryList.addEventListener('change', this.mqlChangeHandler);
164
+ }
165
+ else {
166
+ this.mediaQueryList.addListener(this.mqlChangeHandler);
167
+ }
168
+ }
169
+ // Mobile: portal host to <body> so position:fixed escapes any transformed
170
+ // ancestor. Desktop: restore to its original DOM location.
171
+ applyMode() {
172
+ if (this.isDesktop) {
173
+ this.isOpen = true;
174
+ this.bodyObserver?.disconnect();
175
+ this.bodyObserver = null;
176
+ if (this.originalParent && this.host.parentElement !== this.originalParent) {
177
+ // Sibling may have been removed while we were portaled — fall back
178
+ // to appendChild instead of letting insertBefore throw.
179
+ const ref = this.originalNextSibling?.parentNode === this.originalParent
180
+ ? this.originalNextSibling
181
+ : null;
182
+ this.originalParent.insertBefore(this.host, ref);
183
+ }
184
+ }
185
+ else {
186
+ this.pinToBodyEnd();
187
+ }
188
+ }
189
+ // Re-pin via MutationObserver so a late-mounted footer can't paint over us.
190
+ pinToBodyEnd() {
191
+ if (this.host.parentElement !== document.body || document.body.lastElementChild !== this.host) {
192
+ document.body.appendChild(this.host);
193
+ }
194
+ if (!this.bodyObserver) {
195
+ this.bodyObserver = new MutationObserver(() => {
196
+ if (!this.isDesktop && document.body.lastElementChild !== this.host) {
197
+ document.body.appendChild(this.host);
198
+ }
199
+ });
200
+ this.bodyObserver.observe(document.body, { childList: true });
201
+ }
202
+ }
203
+ disconnectedCallback() {
204
+ // Fires synchronously on every removal, incl. our own reparenting — defer a
205
+ // microtask and bail if reconnected, else the portal loses its listeners.
206
+ Promise.resolve().then(() => {
207
+ if (this.host.isConnected)
208
+ return;
209
+ this.bodyObserver?.disconnect();
210
+ this.submitObserver?.disconnect();
211
+ if (this.submitObserverTimeout) {
212
+ clearTimeout(this.submitObserverTimeout);
213
+ this.submitObserverTimeout = undefined;
214
+ }
215
+ // Mirror the iOS-Safari-<14 path used in componentDidLoad.
216
+ if (this.mediaQueryList?.removeEventListener) {
217
+ this.mediaQueryList.removeEventListener('change', this.mqlChangeHandler);
218
+ }
219
+ else {
220
+ this.mediaQueryList?.removeListener(this.mqlChangeHandler);
221
+ }
222
+ this.mediaQueryList = null;
223
+ this.cartEventNames.forEach(name => salla.event.off(name, this.cartEventHandler));
224
+ });
225
+ }
226
+ fetchCart() {
227
+ const cartId = salla.config?.get?.('page.id');
228
+ const result = salla.cart?.api?.details?.(cartId);
229
+ if (result && typeof result.then === 'function') {
230
+ result
231
+ .then((res) => this.applyCartData(this.extractCart(res)))
232
+ // On failure, fall back to the cached summary instead of stranding the skeleton.
233
+ .catch(() => this.applyCachedSummary());
234
+ }
235
+ else {
236
+ this.applyCachedSummary();
237
+ }
238
+ }
239
+ // Cart API failed → use the SDK's cached summary (localStorage, set on
240
+ // cart::updated). May be stale but beats zeros; events refresh it. Clears the
241
+ // skeleton either way so the CTA always renders.
242
+ applyCachedSummary() {
243
+ const summary = salla.storage?.get?.('cart.summary');
244
+ if (summary && typeof summary === 'object')
245
+ this.applyCartData(summary);
246
+ this.isLoading = false;
247
+ }
248
+ extractCart(payload) {
249
+ if (!payload)
250
+ return null;
251
+ if (payload.data?.cart)
252
+ return payload.data.cart;
253
+ if (payload.cart)
254
+ return payload.cart;
255
+ return payload;
256
+ }
257
+ applyCartData(data) {
258
+ if (!data)
259
+ return;
260
+ // First real payload ends the skeleton.
261
+ this.isLoading = false;
262
+ if (data.count !== undefined)
263
+ this.cartCount = this.num(data.count);
264
+ if (data.total !== undefined)
265
+ this.cartTotal = this.num(data.total);
266
+ // `total_discount` is the live field (untyped); `discount` is the typed fallback.
267
+ const discount = data.total_discount ?? data.discount;
268
+ if (discount !== undefined)
269
+ this.cartTotalDiscount = this.num(discount);
270
+ if (data.sub_total !== undefined)
271
+ this.cartSubTotal = this.num(data.sub_total);
272
+ if (data.options_total !== undefined)
273
+ this.cartOptionsTotal = this.num(data.options_total);
274
+ if (data.tax_amount !== undefined)
275
+ this.cartTaxAmount = this.num(data.tax_amount);
276
+ // Shipping cost (free-shipping aware): prefer `shipping_cost`, else `real_shipping_cost`.
277
+ const hasFreeShipping = !!data.free_shipping_bar?.has_free_shipping;
278
+ if (data.shipping_cost !== undefined)
279
+ this.cartShippingCost = this.num(data.shipping_cost);
280
+ else if (data.real_shipping_cost !== undefined)
281
+ this.cartShippingCost = hasFreeShipping ? 0 : this.num(data.real_shipping_cost);
282
+ // `has_shipping` isn't in the API response — derive row visibility from the cost.
283
+ this.cartHasShipping = this.cartShippingCost > 0 || !!data.has_shipping;
284
+ }
285
+ // Native reportValidity() covers standard fields; custom product options
286
+ // validate via their own async reportValidity() (incl. multi-option required
287
+ // logic), so await that too — else option validation is skipped at checkout.
288
+ async validateCartForms() {
289
+ let isValid = true;
290
+ document
291
+ .querySelectorAll('form[id^="item-"]')
292
+ .forEach(f => {
293
+ if (!f.reportValidity())
294
+ isValid = false;
295
+ });
296
+ const optionEls = Array.from(document.querySelectorAll('form[id^="item-"] salla-product-options'));
297
+ for (const el of optionEls) {
298
+ if (typeof el.reportValidity === 'function' && !(await el.reportValidity()))
299
+ isValid = false;
300
+ }
301
+ return isValid;
302
+ }
303
+ money(value) {
304
+ try {
305
+ if (typeof salla !== 'undefined' && typeof salla.money === 'function') {
306
+ return salla.money(value);
307
+ }
308
+ }
309
+ catch (_) { }
310
+ return String(value ?? 0);
311
+ }
312
+ getItemsLabel() {
313
+ return this.itemsCountTemplate?.replace(':count', String(this.cartCount)) ?? '';
314
+ }
315
+ // Skeleton during the initial fetch
316
+ renderSkeleton() {
317
+ return (h(Host, { class: {
318
+ 's-cart-summary-card': true,
319
+ 's-cart-summary-card--loading': true,
320
+ 's-cart-summary-card--desktop': this.isDesktop,
321
+ 's-cart-summary-card--mobile': !this.isDesktop,
322
+ } }, this.isDesktop && (h("div", { class: "s-cart-summary-card-sheet-wrap s-cart-summary-card-sheet-wrap--open" }, h("div", { class: "s-cart-summary-card-sheet" }, h("header", { class: "s-cart-summary-card-sheet-header" }, h("h3", { class: "s-cart-summary-card-sheet-title" }, h("salla-skeleton", { width: "140px", height: "16px" }))), SKELETON_ROWS.map(({ label, value }, i) => (h("div", { class: "s-cart-summary-card-line", key: i }, h("salla-skeleton", { width: label, height: "16px" }), h("salla-skeleton", { width: value, height: "16px" }))))))), h("div", { class: "s-cart-summary-card-bar" }, h("div", { class: "s-cart-summary-card-bar-label" }, h("div", { class: "s-cart-summary-card-bar-label-main" }, h("salla-skeleton", { width: "90px", height: "16px" }), h("salla-skeleton", { width: "48px", height: "12px" }))), h("div", { class: "s-cart-summary-card-bar-totals" }, h("div", { class: "s-cart-summary-card-bar-totals-row" }, h("salla-skeleton", { width: "80px", height: "20px" })))), h("div", { class: "s-cart-summary-card-action" }, h("salla-skeleton", { width: "100%", height: "44px" }))));
323
+ }
324
+ render() {
325
+ if (this.isLoading)
326
+ return this.renderSkeleton();
327
+ const showSavings = this.cartTotalDiscount > 0;
328
+ const subTotalLabel = this.cartTaxAmount ? this.itemsTotalNoTaxLabel : this.itemsTotalLabel;
329
+ // Inline transform so sheet motion doesn't depend on SCSS load order.
330
+ const sheetStyle = this.isDesktop
331
+ ? {}
332
+ : {
333
+ transform: this.isOpen ? 'translateY(0)' : 'translateY(100%)',
334
+ transition: 'transform 0.4s cubic-bezier(0.32, 0.72, 0, 1)',
335
+ };
336
+ return (h(Host, { class: {
337
+ 's-cart-summary-card': true,
338
+ 's-cart-summary-card--open': this.isOpen,
339
+ 's-cart-summary-card--desktop': this.isDesktop,
340
+ 's-cart-summary-card--mobile': !this.isDesktop,
341
+ } }, h("div", { class: {
342
+ 's-cart-summary-card-sheet-wrap': true,
343
+ 's-cart-summary-card-sheet-wrap--open': this.isOpen,
344
+ }, "aria-hidden": this.isOpen ? 'false' : 'true' }, h("div", { class: "s-cart-summary-card-sheet", style: sheetStyle }, h("header", { class: "s-cart-summary-card-sheet-header" }, h("h3", { class: "s-cart-summary-card-sheet-title" }, this.summaryLabel)), h("div", { class: "s-cart-summary-card-line" }, h("span", null, subTotalLabel), h("b", { innerHTML: this.money(this.cartSubTotal) })), this.cartOptionsTotal > 0 && (h("div", { class: "s-cart-summary-card-line" }, h("span", null, this.optionsTotalLabel), h("b", { innerHTML: this.money(this.cartOptionsTotal) }))), this.cartHasShipping && (h("div", { class: "s-cart-summary-card-line" }, h("span", null, this.shippingCostLabel), h("b", { innerHTML: this.money(this.cartShippingCost) }))), this.cartTaxAmount > 0 && (h("div", { class: "s-cart-summary-card-line" }, h("span", null, this.vatTaxLabel), h("b", { innerHTML: this.money(this.cartTaxAmount) }))), showSavings && (h("div", { class: "s-cart-summary-card-line s-cart-summary-card-line--discount" }, h("span", null, this.savedLabel), h("b", null, "\u2212 ", h("span", { innerHTML: this.money(this.cartTotalDiscount) })))))), h("div", { class: "s-cart-summary-card-bar" }, h("div", { class: "s-cart-summary-card-bar-label" }, h("div", { class: "s-cart-summary-card-bar-label-main" }, h("span", { class: "s-cart-summary-card-bar-label-text" }, this.finalTotalLabel), h("span", { class: "s-cart-summary-card-bar-count" }, this.getItemsLabel())), this.cartTaxAmount > 0 && (h("div", { class: "s-cart-summary-card-bar-label-sub" }, this.pricesTaxedLabel))), h("div", { class: "s-cart-summary-card-bar-totals" }, h("div", { class: "s-cart-summary-card-bar-totals-row" }, showSavings && (h("s", { class: "s-cart-summary-card-bar-original" }, salla.helpers.number(this.cartTotal + this.cartTotalDiscount))), h("b", { class: "s-cart-summary-card-bar-total", innerHTML: this.money(this.cartTotal) }), !this.isDesktop && (h("button", { type: "button", class: "s-cart-summary-card-chevron", "aria-label": this.isOpen ? this.closeSummaryLabel : this.openSummaryLabel, "aria-expanded": this.isOpen ? 'true' : 'false', onClick: this.toggleSheet }, h("i", { class: "sicon-keyboard_arrow_up s-cart-summary-card-chevron-icon" })))), showSavings && (h("div", { class: "s-cart-summary-card-bar-savings-badge" }, h("span", { "aria-hidden": "true" }, "\uD83C\uDF89"), h("span", null, this.discountBadge, " ", h("span", { innerHTML: this.money(this.cartTotalDiscount) })))))), h("div", { class: "s-cart-summary-card-action" }, h("salla-button", { id: "s-cart-summary-card-submit", width: "wide", "loader-position": "center", onClick: this.handleSubmit }, this.completeOrderLabel))));
345
+ }
346
+ static get is() { return "salla-cart-summary-card"; }
347
+ static get properties() {
348
+ return {
349
+ "validateForms": {
350
+ "type": "boolean",
351
+ "attribute": "validate-forms",
352
+ "mutable": false,
353
+ "complexType": {
354
+ "original": "boolean",
355
+ "resolved": "boolean",
356
+ "references": {}
357
+ },
358
+ "required": false,
359
+ "optional": false,
360
+ "docs": {
361
+ "tags": [],
362
+ "text": ""
363
+ },
364
+ "getter": false,
365
+ "setter": false,
366
+ "reflect": false,
367
+ "defaultValue": "true"
368
+ }
369
+ };
370
+ }
371
+ static get states() {
372
+ return {
373
+ "cartCount": {},
374
+ "cartTotal": {},
375
+ "cartTotalDiscount": {},
376
+ "cartSubTotal": {},
377
+ "cartOptionsTotal": {},
378
+ "cartShippingCost": {},
379
+ "cartTaxAmount": {},
380
+ "cartHasShipping": {},
381
+ "isOpen": {},
382
+ "isDesktop": {},
383
+ "isLoading": {},
384
+ "summaryLabel": {},
385
+ "itemsTotalLabel": {},
386
+ "itemsTotalNoTaxLabel": {},
387
+ "optionsTotalLabel": {},
388
+ "shippingCostLabel": {},
389
+ "vatTaxLabel": {},
390
+ "savedLabel": {},
391
+ "discountBadge": {},
392
+ "finalTotalLabel": {},
393
+ "pricesTaxedLabel": {},
394
+ "completeOrderLabel": {},
395
+ "openSummaryLabel": {},
396
+ "closeSummaryLabel": {},
397
+ "itemsCountTemplate": {}
398
+ };
399
+ }
400
+ static get elementRef() { return "host"; }
401
+ }
@@ -8,4 +8,9 @@
8
8
 
9
9
  .s-filters-radio {
10
10
  background-image: none !important;
11
+ }
12
+
13
+ .s-filters-applied-remove {
14
+ pointer-events: auto !important;
15
+ cursor: pointer;
11
16
  }
@@ -7,11 +7,14 @@ import Helper from "../../Helpers/Helper";
7
7
  export class SallaFilters {
8
8
  constructor() {
9
9
  this.isReady = false; //to avoid triggering the changed event
10
+ this.isInitialFetch = true; //the base-category auto-append may only run on the first filters::fetched
10
11
  this.filtersData = {};
12
+ this.appliedOpen = true;
11
13
  salla.event.on('filters::hidden', () => this.host.style.display = 'none');
12
14
  salla.lang.onLoaded(() => {
13
15
  this.apply = salla.lang.get('pages.checkout.apply');
14
16
  this.reset = salla.lang.get('pages.categories.filters_reset');
17
+ this.selectedTitle = salla.lang.getWithDefault('pages.categories.selected_filters', 'لقد اخترت');
15
18
  });
16
19
  salla.event.on('filters::fetched', ({ filters }) => {
17
20
  this.host.style.display = '';
@@ -46,7 +49,9 @@ export class SallaFilters {
46
49
  break; // No need to continue checking once a match is found
47
50
  }
48
51
  }
49
- if (salla.config.get('page.slug') == "product.index" && Object.keys(freshFilterData).length == 0 && !hasFilters) {
52
+ // only on the first fetch after page load re-appending on later fetches
53
+ // would silently undo an explicit "remove all filters" (COD-10662)
54
+ if (this.isInitialFetch && salla.config.get('page.slug') == "product.index" && Object.keys(freshFilterData).length == 0 && !hasFilters) {
50
55
  // Append the current category to the url if there are no pre-selected filters
51
56
  let currentUrl = window.location.href;
52
57
  let filterValue = salla.config.get('page.id');
@@ -57,6 +62,7 @@ export class SallaFilters {
57
62
  }
58
63
  return filter;
59
64
  });
65
+ this.isInitialFetch = false;
60
66
  this.filtersData = freshFilterData;
61
67
  this.host.childNodes.forEach(async (widget) => widget.setWidgetHeight && await widget.setWidgetHeight());
62
68
  });
@@ -118,9 +124,7 @@ export class SallaFilters {
118
124
  const value = filters[key];
119
125
  const fullKey = parentKey ? `${parentKey}[${key}]` : key;
120
126
  if (Array.isArray(value)) {
121
- for (let i = 0; i < value.length; i++) {
122
- encodedFilters.push(`${fullKey}[${i}]=${value[i]}`);
123
- }
127
+ value.forEach(item => encodedFilters.push(`${fullKey}[]=${item}`));
124
128
  }
125
129
  else if (typeof value === 'object' && value !== null) {
126
130
  encodedFilters.push(this.encodeFilters(value, fullKey));
@@ -175,21 +179,105 @@ export class SallaFilters {
175
179
  isChecked && (this.filtersData[option.key] = value);
176
180
  isChecked || (delete this.filtersData[option.key]);
177
181
  }
178
- //it's checkbox
179
- // add if condition to avoid error when the filter is not existed in the filtersData
182
+ //it's checkbox (multi-select / OR within the same group)
180
183
  else if (event.target.type == "checkbox") {
181
- this.filtersData[option.key] = this.filtersData[option.key] || [];
184
+ const current = this.filtersData[option.key];
185
+ // coerce legacy scalar values (e.g. ?filters[brand_id]=1) into an array
186
+ this.filtersData[option.key] = Array.isArray(current) ? current : (current != null ? [current] : []);
182
187
  if (isChecked) {
183
188
  this.filtersData[option.key].push(value);
184
189
  }
185
- this.filtersData[option.key] = this.filtersData[option.key].filter(val => val != value);
190
+ else {
191
+ this.filtersData[option.key] = this.filtersData[option.key].filter(val => val != value);
192
+ }
193
+ if (!this.filtersData[option.key].length) {
194
+ delete this.filtersData[option.key];
195
+ }
196
+ }
197
+ this.filtersData = { ...this.filtersData }; // reassign so @State re-renders the applied chips
198
+ this.applyFilters();
199
+ }
200
+ /**
201
+ * Flatten the selected filtersData into displayable chips, resolving the
202
+ * human label for each group + option from `this.filters`. Selections that
203
+ * can't be resolved to a known option (e.g. the auto-added base category)
204
+ * are skipped.
205
+ */
206
+ getAppliedFilters() {
207
+ const chips = [];
208
+ const data = this.filtersData || {};
209
+ for (const key of Object.keys(data)) {
210
+ if (key === 'variants') {
211
+ const variantFilter = this.filters?.find(f => f.type === FilterOptionTypes.VARIANTS);
212
+ for (const variantKey of Object.keys(data.variants || {})) {
213
+ const value = data.variants[variantKey];
214
+ const opt = variantFilter?.values?.find(o => (o.key || o.value) == value);
215
+ if (!opt)
216
+ continue;
217
+ chips.push({ key, variantKey, value, type: FilterOptionTypes.VARIANTS, groupLabel: variantFilter?.label, optionLabel: opt.value });
218
+ }
219
+ continue;
220
+ }
221
+ const group = this.filters?.find(f => f.key === key);
222
+ if (!group)
223
+ continue;
224
+ const raw = data[key];
225
+ // RANGE (e.g. price) is stored as a { min, max } object
226
+ if (group.type === FilterOptionTypes.RANGE || (raw && typeof raw === 'object' && !Array.isArray(raw))) {
227
+ chips.push({ key, value: raw, type: FilterOptionTypes.RANGE, groupLabel: group.label, optionLabel: `${raw.min} - ${raw.max}` });
228
+ continue;
229
+ }
230
+ // the auto-appended base category (see filters::fetched) is page scoping, not a user
231
+ // selection — skip it. It's stored as a scalar; user selections are always arrays.
232
+ if (key === 'category_id' && !Array.isArray(raw) && salla.config.get('page.slug') == 'product.index' && raw == salla.config.get('page.id')) {
233
+ continue;
234
+ }
235
+ const values = Array.isArray(raw) ? raw : [raw];
236
+ for (const value of values) {
237
+ // rating values are bare numbers; everything else maps key -> value label
238
+ const opt = group.values?.find(o => (typeof o === 'number' ? o : (o.key || o.value)) == value);
239
+ const optionLabel = group.key === 'rating' ? `${value}` : (opt && typeof opt !== 'number' ? opt.value : undefined);
240
+ if (optionLabel == null)
241
+ continue;
242
+ chips.push({ key, value, type: group.type, groupLabel: group.label, optionLabel });
243
+ }
244
+ }
245
+ return chips;
246
+ }
247
+ /**
248
+ * Remove a single applied filter — the direct inverse of handleOptionChange.
249
+ */
250
+ removeFilter(chip) {
251
+ if (chip.type === FilterOptionTypes.VARIANTS) {
252
+ if (this.filtersData.variants) {
253
+ delete this.filtersData.variants[chip.variantKey];
254
+ if (!Object.keys(this.filtersData.variants).length)
255
+ delete this.filtersData.variants;
256
+ }
257
+ }
258
+ else if (chip.type === FilterOptionTypes.RANGE) {
259
+ delete this.filtersData[chip.key];
260
+ }
261
+ else {
262
+ const raw = this.filtersData[chip.key];
263
+ if (Array.isArray(raw)) {
264
+ this.filtersData[chip.key] = raw.filter(val => val != chip.value);
265
+ if (!this.filtersData[chip.key].length)
266
+ delete this.filtersData[chip.key];
267
+ }
268
+ else {
269
+ delete this.filtersData[chip.key];
270
+ }
186
271
  }
272
+ this.filtersData = { ...this.filtersData }; // reassign so the panel + widgets re-render immediately
187
273
  this.applyFilters();
188
274
  }
189
275
  render() {
190
- return h(Host, { key: 'f94496fa176d99cf04b98fea8732b7c7c5912159' }, this.filters?.map(option => h("salla-filters-widget", { option: option, filtersData: this.filtersData, onChanged: ({ detail: { event, option, value } }) => {
276
+ const appliedFilters = this.getAppliedFilters();
277
+ const removeText = salla.lang.getWithDefault('common.elements.delete', 'Remove');
278
+ return h(Host, { key: 'd6dacbf458eadefda7ec2b2c6845c54f553abea8' }, appliedFilters.length ? h("div", { class: "s-filters-applied s-filters-widget-container" }, h("h3", { class: "s-filters-widget-title", onClick: () => this.appliedOpen = !this.appliedOpen }, h("span", null, this.selectedTitle), h("span", { class: `s-filters-widget-plusminus ${this.appliedOpen ? 's-filters-widget-plusminus-active' : ''}` })), h("div", { class: `s-filters-widget-content ${this.appliedOpen ? 's-filters-widget-opened' : 's-filters-widget-closed'}` }, h("div", { class: "s-filters-widget-values" }, appliedFilters.map(chip => h("div", { class: "s-filters-label s-filters-applied-item" }, h("span", { class: "s-filters-option-name" }, chip.groupLabel, ": ", chip.optionLabel), h("button", { type: "button", class: "s-filters-applied-remove", "aria-label": `${removeText} ${chip.groupLabel}: ${chip.optionLabel}`, onClick: () => this.removeFilter(chip) }, h("i", { class: "sicon-cancel", "aria-hidden": "true" }))))), h("div", { class: "s-filters-footer" }, h("salla-button", { color: 'gray', fill: 'outline', onClick: () => this.resetFilters() }, this.reset)))) : '', this.filters?.map(option => h("salla-filters-widget", { option: option, filtersData: this.filtersData, onChanged: ({ detail: { event, option, value } }) => {
191
279
  this.handleOptionChange(event, option, value);
192
- } })), this.filters?.length ? h("div", { class: "s-filters-footer" }, h("salla-button", { color: 'gray', fill: 'outline', onClick: () => this.resetFilters() }, this.reset)) : '');
280
+ } })));
193
281
  }
194
282
  componentDidLoad() {
195
283
  this.isReady = true;
@@ -238,7 +326,9 @@ export class SallaFilters {
238
326
  "isSidebarOpen": {},
239
327
  "filtersData": {},
240
328
  "apply": {},
241
- "reset": {}
329
+ "reset": {},
330
+ "selectedTitle": {},
331
+ "appliedOpen": {}
242
332
  };
243
333
  }
244
334
  static get events() {
@@ -135,7 +135,7 @@ export class SallaFiltersWidget {
135
135
  //@ts-ignore
136
136
  return filteredValues.map((filterOption, index) => {
137
137
  let value = typeof filterOption == 'number' ? filterOption : (filterOption.key || filterOption.value);
138
- return h("label", { class: "s-filters-label", htmlFor: `${option.key}-option-${value}`, key: `${option.key}-option-${value}` }, h("input", { id: `${option.key}-option-${value}`, name: option.key, type: "radio", checked: this.isSelectedOption(option, value), class: `s-filters-radio`, onChange: event => this.changed.emit({ event, option, value }) }), this.getOptionLabel(option, filterOption));
138
+ return h("label", { class: "s-filters-label", htmlFor: `${option.key}-option-${value}`, key: `${option.key}-option-${value}` }, h("input", { id: `${option.key}-option-${value}`, name: option.key, type: option.type === FilterOptionTypes.VALUES ? 'checkbox' : 'radio', checked: this.isSelectedOption(option, value), class: option.type === FilterOptionTypes.VALUES ? 's-filters-checkbox' : 's-filters-radio', onChange: event => this.changed.emit({ event, option, value }) }), this.getOptionLabel(option, filterOption));
139
139
  });
140
140
  }
141
141
  isSelectedOption(option, value) {
@@ -143,13 +143,18 @@ export class SallaFiltersWidget {
143
143
  return this.filtersData[option.key] == value;
144
144
  }
145
145
  if (option.type === FilterOptionTypes.VARIANTS) {
146
- return this.filtersData[option.type] && this.filtersData[option.type][Object.keys(this.filtersData[option.type])[0]] == value;
146
+ // selections are stored per widget key (handleOptionChange: filtersData.variants[option.key])
147
+ return this.filtersData[option.type] && this.filtersData[option.type][option.key] == value;
147
148
  }
148
149
  if (option.type === FilterOptionTypes.RANGE) {
149
150
  return this.filtersData[option.key] && this.filtersData[option.key].min == value.min && this.filtersData[option.key].max == value.max;
150
151
  }
151
152
  if (option.type === FilterOptionTypes.VALUES) {
152
- return this.filtersData[option.key] && Number(this.filtersData[option.key]) == Number(value);
153
+ const selected = this.filtersData[option.key];
154
+ if (Array.isArray(selected)) {
155
+ return selected.some(v => Number(v) === Number(value));
156
+ }
157
+ return selected != null && Number(selected) === Number(value);
153
158
  }
154
159
  return false;
155
160
  }
@@ -159,16 +164,18 @@ export class SallaFiltersWidget {
159
164
  return h("salla-rating-stars", { size: "small", value: filterOption });
160
165
  }
161
166
  let label = filterOption.value || 'null';
162
- //label+=filterOption.count ? ` (${salla.helpers.number(filterOption.count)})` : '';
167
+ if (filterOption.count != null) {
168
+ label += ` (${salla.helpers.number(filterOption.count)})`;
169
+ }
163
170
  return h("span", { class: "s-filters-option-name" }, label);
164
171
  }
165
172
  render() {
166
- return (h(Host, { key: '2cdd3bbc88b473e9b5d52bf5e95de16f9ad47a51', class: "s-filters-widget-container" }, h("h3", { key: '4d3d522469681c5d7cde040938b0ce15324d7cc3', class: "s-filters-widget-title", onClick: () => this.toggleWidget() }, h("span", { key: '60fa18c667a1b00f03e8eebc484da68e78fa8d90' }, this.option.label), h("span", { key: 'ac8cff411fbb76c43e0134b0c7381b682a8afcd0', class: `s-filters-widget-plusminus ${this.isOpen ? 's-filters-widget-plusminus-active' : ''}` })), h("div", { key: '5705ab244d712512e156994bbf21d9bb49dbb43b', class: "s-filters-widget-content", ref: (el) => this.widgetContent = el }, Array.isArray(this.option.values) && this.option.values.length > 5 && (h("div", { key: 'a59f45a5fbd803dcd65f0a5b40060a1dcfed00e0', class: "s-filters-widget-search-wrapper", style: { padding: '8px 0', marginBottom: '8px' } }, h("input", { key: '3275790105bfe9b84df564b9385c4a9556c2f03a', type: "text", class: "s-filters-widget-search-input", placeholder: salla.lang.get('blocks.header.search_placeholder') || 'بحث...', value: this.searchQuery, onInput: (e) => this.searchQuery = e.target.value }))), h("div", { key: '70d57184a8089422d96ea62ddaa7697f7f207441', class: "s-filters-widget-values", ref: (el) => this.widgetValues = el }, h("slot", { key: '959512d2256b5a29236572fc8078c5baa5d9a571' }), this.option.type !== FilterOptionTypes.RANGE
173
+ return (h(Host, { key: '3ea32331738365fc422b500b3e70fa590d4dbdb5', class: "s-filters-widget-container" }, h("h3", { key: 'c5cb7a27841bf85e4c108e15d606c1c45059e5ca', class: "s-filters-widget-title", onClick: () => this.toggleWidget() }, h("span", { key: '641164d403dd4c9b79a540f4da5829f5238cded4' }, this.option.label), h("span", { key: '5cf687d80ff627f306f5876f69b799b6b7a3813d', class: `s-filters-widget-plusminus ${this.isOpen ? 's-filters-widget-plusminus-active' : ''}` })), h("div", { key: 'd9b753223b4fb1c468ed6c4c3a269b861bc5b34b', class: "s-filters-widget-content", ref: (el) => this.widgetContent = el }, Array.isArray(this.option.values) && this.option.values.length > 5 && (h("div", { key: '0ca4f8c598e5965e23ef56610df7afc31799f168', class: "s-filters-widget-search-wrapper", style: { padding: '8px 0', marginBottom: '8px' } }, h("input", { key: '7b43ec84dcbeb5b7f9cbe9335133e32c278c00fd', type: "text", class: "s-filters-widget-search-input", placeholder: salla.lang.get('blocks.header.search_placeholder') || 'بحث...', value: this.searchQuery, onInput: (e) => this.searchQuery = e.target.value }))), h("div", { key: '5bf79fc5f51389d087fed93acee51a097a46af65', class: "s-filters-widget-values", ref: (el) => this.widgetValues = el }, h("slot", { key: '8dacd49ba003562d347a6c1b62e85ac447a62fcb' }), this.option.type !== FilterOptionTypes.RANGE
167
174
  ? this.renderFilterOption(this.option)
168
175
  : h("salla-price-range", { onChanged: (event) => {
169
176
  this.changed.emit(event.detail);
170
177
  }, ref: price => this.priceRange = price, filtersData: this.filtersData, option: this.option })), this.withLoadMore && (!this.searchQuery || this.filteredCount > this.initialItemCount) &&
171
- h("a", { key: '305b4a155c2b3705bcf139c81b5f8bcb3d744d05', class: "s-filters-widget-more", onClick: () => this.showMore() }, !this.isShowMore ? this.showMoreLabel : this.showLessLabel))));
178
+ h("a", { key: '85ca188ff9f0db7c0a23b94e4705ae2ca5c38d55', class: "s-filters-widget-more", onClick: () => this.showMore() }, !this.isShowMore ? this.showMoreLabel : this.showLessLabel))));
172
179
  }
173
180
  static get is() { return "salla-filters-widget"; }
174
181
  static get originalStyleUrls() {