@salla.sa/twilight-components 2.14.500 → 2.14.502

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 (349) hide show
  1. package/dist/cjs/catalog-recommendations-Bzt0HRy8.js +94 -0
  2. package/dist/cjs/{filepond-B9PtMjXt.js → filepond-CIptScDL.js} +1 -1
  3. package/dist/cjs/{filepond-plugin-file-poster-CMd-UUZx.js → filepond-plugin-file-poster-DwHNuiWd.js} +1 -1
  4. package/dist/cjs/{filepond-plugin-file-validate-size-DpJalosf.js → filepond-plugin-file-validate-size-BMLUB-u0.js} +1 -1
  5. package/dist/cjs/{filepond-plugin-file-validate-type-CZjeYI0w.js → filepond-plugin-file-validate-type-DiRunNiR.js} +1 -1
  6. package/dist/cjs/{filepond-plugin-image-edit-Bl6fwgrn.js → filepond-plugin-image-edit-DujWvbF5.js} +1 -1
  7. package/dist/cjs/{filepond-plugin-image-exif-orientation-BeQ8iCyg.js → filepond-plugin-image-exif-orientation-CzdpRTlH.js} +1 -1
  8. package/dist/cjs/{filepond-plugin-image-preview-BkGKXzOB.js → filepond-plugin-image-preview-CpEEysug.js} +1 -1
  9. package/dist/cjs/{functions-UaOjMOb2.js → functions-DL46a-BT.js} +1 -1
  10. package/dist/cjs/{index-Cd5xdrCT.js → index-CeCWRg4V.js} +6 -2
  11. package/dist/cjs/{index-CQPk27Eg.js → index-D7i3cgiE.js} +1 -1
  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 +1 -1
  15. package/dist/cjs/salla-add-product-button_5.cjs.entry.js +70 -30
  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-basket-gap.cjs.entry.js +269 -0
  22. package/dist/cjs/salla-booking-field_7.cjs.entry.js +10 -10
  23. package/dist/cjs/salla-bullet-delivery_2.cjs.entry.js +1 -1
  24. package/dist/cjs/salla-cart-coupons.cjs.entry.js +1 -1
  25. package/dist/cjs/salla-cart-item-offers_2.cjs.entry.js +1 -1
  26. package/dist/cjs/salla-cart-summary-card.cjs.entry.js +1 -1
  27. package/dist/cjs/salla-cashback-banner.cjs.entry.js +1 -1
  28. package/dist/cjs/salla-comment-factors.cjs.entry.js +1 -1
  29. package/dist/cjs/salla-comment-form_8.cjs.entry.js +1 -1
  30. package/dist/cjs/salla-conditional-offer.cjs.entry.js +1 -1
  31. package/dist/cjs/salla-contacts.cjs.entry.js +1 -1
  32. package/dist/cjs/salla-cookies-bar.cjs.entry.js +1 -1
  33. package/dist/cjs/salla-count-down_2.cjs.entry.js +4 -3
  34. package/dist/cjs/salla-custom-fields.cjs.entry.js +1 -1
  35. package/dist/cjs/salla-delivery-promise.cjs.entry.js +1 -1
  36. package/dist/cjs/salla-edit-order-button.cjs.entry.js +1 -1
  37. package/dist/cjs/salla-filters-widget.cjs.entry.js +1 -1
  38. package/dist/cjs/salla-filters.cjs.entry.js +1 -1
  39. package/dist/cjs/salla-fulfillment-methods.cjs.entry.js +1 -1
  40. package/dist/cjs/salla-gifting.cjs.entry.js +1 -1
  41. package/dist/cjs/salla-hook.cjs.entry.js +1 -1
  42. package/dist/cjs/salla-infinite-scroll.cjs.entry.js +1 -1
  43. package/dist/cjs/salla-installment.cjs.entry.js +1 -1
  44. package/dist/cjs/salla-list-tile.cjs.entry.js +1 -1
  45. package/dist/cjs/salla-localization-modal.cjs.entry.js +1 -1
  46. package/dist/cjs/salla-login-modal.cjs.entry.js +1 -1
  47. package/dist/cjs/salla-loyalty-banner.cjs.entry.js +2 -2
  48. package/dist/cjs/salla-loyalty-exchange-product-card_5.cjs.entry.js +3 -3
  49. package/dist/cjs/salla-loyalty-hero_2.cjs.entry.js +2 -2
  50. package/dist/cjs/salla-loyalty-panel.cjs.entry.js +3 -3
  51. package/dist/cjs/salla-loyalty-points-banner.cjs.entry.js +1 -1
  52. package/dist/cjs/salla-loyalty-points-history.cjs.entry.js +1 -1
  53. package/dist/cjs/salla-loyalty-prize-item.cjs.entry.js +1 -1
  54. package/dist/cjs/salla-loyalty-program.cjs.entry.js +3 -3
  55. package/dist/cjs/salla-loyalty-reward.cjs.entry.js +2 -2
  56. package/dist/cjs/salla-loyalty.cjs.entry.js +1 -1
  57. package/dist/cjs/salla-maintenance-alert.cjs.entry.js +1 -1
  58. package/dist/cjs/salla-map_2.cjs.entry.js +1 -1
  59. package/dist/cjs/salla-menu.cjs.entry.js +1 -1
  60. package/dist/cjs/salla-metadata.cjs.entry.js +1 -1
  61. package/dist/cjs/salla-multiple-bundle-product-cart_2.cjs.entry.js +1 -1
  62. package/dist/cjs/salla-multiple-bundle-product-options-modal_2.cjs.entry.js +1 -1
  63. package/dist/cjs/salla-multiple-bundle-product.cjs.entry.js +1 -1
  64. package/dist/cjs/salla-next-order-coupon.cjs.entry.js +1 -1
  65. package/dist/cjs/salla-notification-item.cjs.entry.js +1 -1
  66. package/dist/cjs/salla-notifications.cjs.entry.js +1 -1
  67. package/dist/cjs/salla-offer-modal.cjs.entry.js +1 -1
  68. package/dist/cjs/salla-offer.cjs.entry.js +1 -1
  69. package/dist/cjs/salla-order-branch.cjs.entry.js +1 -1
  70. package/dist/cjs/salla-order-cancel.cjs.entry.js +1 -1
  71. package/dist/cjs/salla-order-details-multiple-bundle-product.cjs.entry.js +1 -1
  72. package/dist/cjs/salla-order-details-options.cjs.entry.js +1 -1
  73. package/dist/cjs/salla-order-details.cjs.entry.js +1 -1
  74. package/dist/cjs/salla-order-edit-item.cjs.entry.js +1 -1
  75. package/dist/cjs/salla-order-edit-product-card.cjs.entry.js +1 -1
  76. package/dist/cjs/salla-order-edit.cjs.entry.js +1 -1
  77. package/dist/cjs/salla-order-summary.cjs.entry.js +1 -1
  78. package/dist/cjs/salla-order-totals-card.cjs.entry.js +1 -1
  79. package/dist/cjs/salla-orders.cjs.entry.js +1 -1
  80. package/dist/cjs/salla-payments.cjs.entry.js +1 -1
  81. package/dist/cjs/salla-placeholder.cjs.entry.js +1 -1
  82. package/dist/cjs/salla-price-range.cjs.entry.js +1 -1
  83. package/dist/cjs/salla-product-card-embed.cjs.entry.js +1 -1
  84. package/dist/cjs/salla-product-card_2.cjs.entry.js +1 -1
  85. package/dist/cjs/salla-product-size-guide.cjs.entry.js +1 -1
  86. package/dist/cjs/salla-products-list.cjs.entry.js +1 -1
  87. package/dist/cjs/salla-quick-order.cjs.entry.js +1 -1
  88. package/dist/cjs/salla-rating-modal-v2.cjs.entry.js +1 -1
  89. package/dist/cjs/salla-rating-modal.cjs.entry.js +1 -1
  90. package/dist/cjs/salla-review-factors-tags.cjs.entry.js +1 -1
  91. package/dist/cjs/salla-scopes.cjs.entry.js +1 -1
  92. package/dist/cjs/salla-search.cjs.entry.js +1 -1
  93. package/dist/cjs/salla-skeleton.cjs.entry.js +1 -1
  94. package/dist/cjs/salla-slider.cjs.entry.js +1 -1
  95. package/dist/cjs/salla-social-share.cjs.entry.js +1 -1
  96. package/dist/cjs/salla-social.cjs.entry.js +1 -1
  97. package/dist/cjs/salla-tab-content_3.cjs.entry.js +1 -1
  98. package/dist/cjs/salla-tiered-offer.cjs.entry.js +1 -1
  99. package/dist/cjs/salla-tooltip.cjs.entry.js +1 -1
  100. package/dist/cjs/salla-trust-badges.cjs.entry.js +1 -1
  101. package/dist/cjs/salla-user-menu.cjs.entry.js +1 -1
  102. package/dist/cjs/salla-user-profile.cjs.entry.js +1 -1
  103. package/dist/cjs/salla-user-settings.cjs.entry.js +1 -1
  104. package/dist/cjs/salla-verify.cjs.entry.js +1 -1
  105. package/dist/cjs/salla-wallet.cjs.entry.js +1 -1
  106. package/dist/cjs/salla-wishlist-actions.cjs.entry.js +1 -1
  107. package/dist/cjs/{tracked-promise-DwUVHl1m.js → tracked-promise-DQhIwhjv.js} +1 -1
  108. package/dist/cjs/twilight.cjs.js +2 -2
  109. package/dist/cjs/{vanilla-picker-BTiOI13l.js → vanilla-picker-DlMSPnXD.js} +1 -1
  110. package/dist/collection/collection-manifest.json +1 -0
  111. package/dist/collection/components/salla-basket-gap/salla-basket-gap.css +3 -0
  112. package/dist/collection/components/salla-basket-gap/salla-basket-gap.js +306 -0
  113. package/dist/collection/components/salla-bought-together/salla-bought-together.js +5 -17
  114. package/dist/collection/components/salla-count-down/salla-count-down.js +3 -2
  115. package/dist/collection/components/salla-quick-buy/salla-quick-buy.js +87 -7
  116. package/dist/collection/shared/catalog-recommendations.js +89 -0
  117. package/dist/components/catalog-recommendations.js +91 -0
  118. package/dist/components/index.js +2 -2
  119. package/dist/components/salla-basket-gap.d.ts +11 -0
  120. package/dist/components/salla-basket-gap.js +402 -0
  121. package/dist/components/salla-bought-together.js +5 -17
  122. package/dist/components/salla-count-down2.js +3 -2
  123. package/dist/components/salla-quick-buy2.js +66 -12
  124. package/dist/esm/catalog-recommendations-9fzJJ_Ox.js +91 -0
  125. package/dist/esm/{filepond-DjtqIoeD.js → filepond--jRYda4S.js} +1 -1
  126. package/dist/esm/{filepond-plugin-file-poster-CFxoEHLP.js → filepond-plugin-file-poster-CckDj7tB.js} +1 -1
  127. package/dist/esm/{filepond-plugin-file-validate-size-BnBRYL0y.js → filepond-plugin-file-validate-size-9b6v_l6Z.js} +1 -1
  128. package/dist/esm/{filepond-plugin-file-validate-type-Dr5ofT9v.js → filepond-plugin-file-validate-type-CjGNB5Pv.js} +1 -1
  129. package/dist/esm/{filepond-plugin-image-edit-DyMeCzTZ.js → filepond-plugin-image-edit-UIthhs_A.js} +1 -1
  130. package/dist/esm/{filepond-plugin-image-exif-orientation-ngtve06j.js → filepond-plugin-image-exif-orientation-DPcDqfwl.js} +1 -1
  131. package/dist/esm/{filepond-plugin-image-preview-aqxBqAYf.js → filepond-plugin-image-preview-BWlnovlW.js} +1 -1
  132. package/dist/esm/{functions-Drikk4uf.js → functions-Vnk4zyHS.js} +1 -1
  133. package/dist/esm/{index-DuoSRdS5.js → index-BOjfFBGe.js} +6 -2
  134. package/dist/esm/{index-CaZkz-p0.js → index-D8XjJYaY.js} +1 -1
  135. package/dist/esm/loader.js +3 -3
  136. package/dist/esm/salla-accordion-body_2.entry.js +1 -1
  137. package/dist/esm/salla-accordion_6.entry.js +1 -1
  138. package/dist/esm/salla-add-product-button_5.entry.js +70 -30
  139. package/dist/esm/salla-advertisement.entry.js +1 -1
  140. package/dist/esm/salla-alert_2.entry.js +1 -1
  141. package/dist/esm/salla-app-install-alert.entry.js +1 -1
  142. package/dist/esm/salla-apps-icons.entry.js +1 -1
  143. package/dist/esm/salla-badge.entry.js +1 -1
  144. package/dist/esm/salla-basket-gap.entry.js +267 -0
  145. package/dist/esm/salla-booking-field_7.entry.js +10 -10
  146. package/dist/esm/salla-bullet-delivery_2.entry.js +1 -1
  147. package/dist/esm/salla-cart-coupons.entry.js +1 -1
  148. package/dist/esm/salla-cart-item-offers_2.entry.js +1 -1
  149. package/dist/esm/salla-cart-summary-card.entry.js +1 -1
  150. package/dist/esm/salla-cashback-banner.entry.js +1 -1
  151. package/dist/esm/salla-comment-factors.entry.js +1 -1
  152. package/dist/esm/salla-comment-form_8.entry.js +1 -1
  153. package/dist/esm/salla-conditional-offer.entry.js +1 -1
  154. package/dist/esm/salla-contacts.entry.js +1 -1
  155. package/dist/esm/salla-cookies-bar.entry.js +1 -1
  156. package/dist/esm/salla-count-down_2.entry.js +4 -3
  157. package/dist/esm/salla-custom-fields.entry.js +1 -1
  158. package/dist/esm/salla-delivery-promise.entry.js +1 -1
  159. package/dist/esm/salla-edit-order-button.entry.js +1 -1
  160. package/dist/esm/salla-filters-widget.entry.js +1 -1
  161. package/dist/esm/salla-filters.entry.js +1 -1
  162. package/dist/esm/salla-fulfillment-methods.entry.js +1 -1
  163. package/dist/esm/salla-gifting.entry.js +1 -1
  164. package/dist/esm/salla-hook.entry.js +1 -1
  165. package/dist/esm/salla-infinite-scroll.entry.js +1 -1
  166. package/dist/esm/salla-installment.entry.js +1 -1
  167. package/dist/esm/salla-list-tile.entry.js +1 -1
  168. package/dist/esm/salla-localization-modal.entry.js +1 -1
  169. package/dist/esm/salla-login-modal.entry.js +1 -1
  170. package/dist/esm/salla-loyalty-banner.entry.js +2 -2
  171. package/dist/esm/salla-loyalty-exchange-product-card_5.entry.js +3 -3
  172. package/dist/esm/salla-loyalty-hero_2.entry.js +2 -2
  173. package/dist/esm/salla-loyalty-panel.entry.js +3 -3
  174. package/dist/esm/salla-loyalty-points-banner.entry.js +1 -1
  175. package/dist/esm/salla-loyalty-points-history.entry.js +1 -1
  176. package/dist/esm/salla-loyalty-prize-item.entry.js +1 -1
  177. package/dist/esm/salla-loyalty-program.entry.js +3 -3
  178. package/dist/esm/salla-loyalty-reward.entry.js +2 -2
  179. package/dist/esm/salla-loyalty.entry.js +1 -1
  180. package/dist/esm/salla-maintenance-alert.entry.js +1 -1
  181. package/dist/esm/salla-map_2.entry.js +1 -1
  182. package/dist/esm/salla-menu.entry.js +1 -1
  183. package/dist/esm/salla-metadata.entry.js +1 -1
  184. package/dist/esm/salla-multiple-bundle-product-cart_2.entry.js +1 -1
  185. package/dist/esm/salla-multiple-bundle-product-options-modal_2.entry.js +1 -1
  186. package/dist/esm/salla-multiple-bundle-product.entry.js +1 -1
  187. package/dist/esm/salla-next-order-coupon.entry.js +1 -1
  188. package/dist/esm/salla-notification-item.entry.js +1 -1
  189. package/dist/esm/salla-notifications.entry.js +1 -1
  190. package/dist/esm/salla-offer-modal.entry.js +1 -1
  191. package/dist/esm/salla-offer.entry.js +1 -1
  192. package/dist/esm/salla-order-branch.entry.js +1 -1
  193. package/dist/esm/salla-order-cancel.entry.js +1 -1
  194. package/dist/esm/salla-order-details-multiple-bundle-product.entry.js +1 -1
  195. package/dist/esm/salla-order-details-options.entry.js +1 -1
  196. package/dist/esm/salla-order-details.entry.js +1 -1
  197. package/dist/esm/salla-order-edit-item.entry.js +1 -1
  198. package/dist/esm/salla-order-edit-product-card.entry.js +1 -1
  199. package/dist/esm/salla-order-edit.entry.js +1 -1
  200. package/dist/esm/salla-order-summary.entry.js +1 -1
  201. package/dist/esm/salla-order-totals-card.entry.js +1 -1
  202. package/dist/esm/salla-orders.entry.js +1 -1
  203. package/dist/esm/salla-payments.entry.js +1 -1
  204. package/dist/esm/salla-placeholder.entry.js +1 -1
  205. package/dist/esm/salla-price-range.entry.js +1 -1
  206. package/dist/esm/salla-product-card-embed.entry.js +1 -1
  207. package/dist/esm/salla-product-card_2.entry.js +1 -1
  208. package/dist/esm/salla-product-size-guide.entry.js +1 -1
  209. package/dist/esm/salla-products-list.entry.js +1 -1
  210. package/dist/esm/salla-quick-order.entry.js +1 -1
  211. package/dist/esm/salla-rating-modal-v2.entry.js +1 -1
  212. package/dist/esm/salla-rating-modal.entry.js +1 -1
  213. package/dist/esm/salla-review-factors-tags.entry.js +1 -1
  214. package/dist/esm/salla-scopes.entry.js +1 -1
  215. package/dist/esm/salla-search.entry.js +1 -1
  216. package/dist/esm/salla-skeleton.entry.js +1 -1
  217. package/dist/esm/salla-slider.entry.js +1 -1
  218. package/dist/esm/salla-social-share.entry.js +1 -1
  219. package/dist/esm/salla-social.entry.js +1 -1
  220. package/dist/esm/salla-tab-content_3.entry.js +1 -1
  221. package/dist/esm/salla-tiered-offer.entry.js +1 -1
  222. package/dist/esm/salla-tooltip.entry.js +1 -1
  223. package/dist/esm/salla-trust-badges.entry.js +1 -1
  224. package/dist/esm/salla-user-menu.entry.js +1 -1
  225. package/dist/esm/salla-user-profile.entry.js +1 -1
  226. package/dist/esm/salla-user-settings.entry.js +1 -1
  227. package/dist/esm/salla-verify.entry.js +1 -1
  228. package/dist/esm/salla-wallet.entry.js +1 -1
  229. package/dist/esm/salla-wishlist-actions.entry.js +1 -1
  230. package/dist/esm/{tracked-promise-CUM6cNiF.js → tracked-promise-DPZbMaax.js} +1 -1
  231. package/dist/esm/twilight.js +3 -3
  232. package/dist/esm/{vanilla-picker-kF8Cgi5q.js → vanilla-picker-Db2JkkPK.js} +1 -1
  233. package/dist/twilight/{p-74cac8a8.entry.js → p-0076e440.entry.js} +1 -1
  234. package/dist/twilight/{p-c3530e7a.entry.js → p-0245e2c0.entry.js} +1 -1
  235. package/dist/twilight/{p-00d73870.entry.js → p-05533207.entry.js} +1 -1
  236. package/dist/twilight/{p-a5eeb082.entry.js → p-0809ec4c.entry.js} +1 -1
  237. package/dist/twilight/{p-404d3645.entry.js → p-0846a39c.entry.js} +1 -1
  238. package/dist/twilight/{p-0604eb27.entry.js → p-0a36a8df.entry.js} +1 -1
  239. package/dist/twilight/{p-2c4f4539.entry.js → p-0c4b50a8.entry.js} +1 -1
  240. package/dist/twilight/{p-9a161a84.entry.js → p-145f51a4.entry.js} +1 -1
  241. package/dist/twilight/{p-a1d3a45f.entry.js → p-16060f64.entry.js} +1 -1
  242. package/dist/twilight/{p-cd65e560.entry.js → p-16407a84.entry.js} +1 -1
  243. package/dist/twilight/{p-ca0a62f9.entry.js → p-166287b8.entry.js} +1 -1
  244. package/dist/twilight/{p-2104f800.entry.js → p-1ad1e565.entry.js} +1 -1
  245. package/dist/twilight/{p-92d37b3e.entry.js → p-1d7a5517.entry.js} +1 -1
  246. package/dist/twilight/{p-ca52add5.entry.js → p-2495ba63.entry.js} +1 -1
  247. package/dist/twilight/{p-95d8a11b.entry.js → p-24af33da.entry.js} +1 -1
  248. package/dist/twilight/p-24cdca69.entry.js +4 -0
  249. package/dist/twilight/{p-4fb48be8.entry.js → p-25be867c.entry.js} +1 -1
  250. package/dist/twilight/{p-0daa8221.entry.js → p-27ed0bb7.entry.js} +1 -1
  251. package/dist/twilight/{p-d3a9573e.entry.js → p-2f0b08a4.entry.js} +1 -1
  252. package/dist/twilight/{p-a34c031b.entry.js → p-3075687f.entry.js} +1 -1
  253. package/dist/twilight/{p-0a1f28c9.entry.js → p-3330e9b1.entry.js} +1 -1
  254. package/dist/twilight/{p-1d75fdd9.entry.js → p-3431ad47.entry.js} +1 -1
  255. package/dist/twilight/{p-dc6b3dfb.entry.js → p-36d820e1.entry.js} +1 -1
  256. package/dist/twilight/{p-d8c9d454.entry.js → p-3ed4357e.entry.js} +1 -1
  257. package/dist/twilight/{p-72291ad7.entry.js → p-3f137515.entry.js} +1 -1
  258. package/dist/twilight/{p-67d7bd8b.entry.js → p-404e7d5b.entry.js} +1 -1
  259. package/dist/twilight/{p-b0437615.entry.js → p-45b6ec5f.entry.js} +1 -1
  260. package/dist/twilight/{p-2c9c0815.entry.js → p-490e83b7.entry.js} +1 -1
  261. package/dist/twilight/{p-99ff235e.entry.js → p-4a9fbb6e.entry.js} +1 -1
  262. package/dist/twilight/{p-d39bf8b5.entry.js → p-4cf257b2.entry.js} +1 -1
  263. package/dist/twilight/{p-0c1721e1.entry.js → p-4d32ef06.entry.js} +1 -1
  264. package/dist/twilight/{p-74e009df.entry.js → p-5259181e.entry.js} +1 -1
  265. package/dist/twilight/{p-f8d642b2.entry.js → p-534c5ce0.entry.js} +1 -1
  266. package/dist/twilight/{p-d54b75de.entry.js → p-540b7c0c.entry.js} +1 -1
  267. package/dist/twilight/{p-9e27778a.entry.js → p-5492fef2.entry.js} +1 -1
  268. package/dist/twilight/{p-0b814320.entry.js → p-558eef65.entry.js} +1 -1
  269. package/dist/twilight/{p-be973f87.entry.js → p-56c55c15.entry.js} +1 -1
  270. package/dist/twilight/{p-7df52f7b.entry.js → p-5804914e.entry.js} +1 -1
  271. package/dist/twilight/p-591dc47b.entry.js +4 -0
  272. package/dist/twilight/{p-7b9ed1e4.entry.js → p-5cbeee21.entry.js} +1 -1
  273. package/dist/twilight/{p-01636f53.entry.js → p-5f0565be.entry.js} +1 -1
  274. package/dist/twilight/{p-92ec265b.entry.js → p-5f3b36fe.entry.js} +1 -1
  275. package/dist/twilight/{p-51bc9c4d.entry.js → p-628fb2e7.entry.js} +1 -1
  276. package/dist/twilight/{p-ae83c325.entry.js → p-62d4e685.entry.js} +1 -1
  277. package/dist/twilight/{p-5fe29fcf.entry.js → p-648704dc.entry.js} +1 -1
  278. package/dist/twilight/{p-9196b7a9.entry.js → p-67d5bded.entry.js} +1 -1
  279. package/dist/twilight/{p-19c6d83a.entry.js → p-6bdbd0f3.entry.js} +1 -1
  280. package/dist/twilight/{p-5a215130.entry.js → p-71d90a27.entry.js} +1 -1
  281. package/dist/twilight/{p-56ba7f94.entry.js → p-73acf48f.entry.js} +1 -1
  282. package/dist/twilight/{p-9cc2e54c.entry.js → p-7460706e.entry.js} +1 -1
  283. package/dist/twilight/{p-39389b31.entry.js → p-7ab7f179.entry.js} +1 -1
  284. package/dist/twilight/{p-aed6d4eb.entry.js → p-7be94cc2.entry.js} +1 -1
  285. package/dist/twilight/{p-286d9ba3.entry.js → p-7d10ae17.entry.js} +1 -1
  286. package/dist/twilight/{p-5cb10852.entry.js → p-7ef4cd2e.entry.js} +1 -1
  287. package/dist/twilight/{p-f5ac65b4.entry.js → p-85333282.entry.js} +1 -1
  288. package/dist/twilight/{p-c6b82041.entry.js → p-8e298b27.entry.js} +1 -1
  289. package/dist/twilight/{p-a2e8a9d1.entry.js → p-9018a13b.entry.js} +1 -1
  290. package/dist/twilight/{p-953da0b5.entry.js → p-91853c93.entry.js} +1 -1
  291. package/dist/twilight/{p-15c3b0cc.entry.js → p-95e6774b.entry.js} +1 -1
  292. package/dist/twilight/{p-77d816b8.entry.js → p-980deae9.entry.js} +1 -1
  293. package/dist/twilight/{p-0e6a0989.entry.js → p-9b9eb649.entry.js} +1 -1
  294. package/dist/twilight/p-9fzJJ_Ox.js +4 -0
  295. package/dist/twilight/p-B-m0e6tL.js +4 -0
  296. package/dist/twilight/{p-lYj74H1f.js → p-B93EBMau.js} +1 -1
  297. package/dist/twilight/{p-Ca84RIBI.js → p-BI-CCdbp.js} +1 -1
  298. package/dist/twilight/{p-DuoSRdS5.js → p-BOjfFBGe.js} +1 -1
  299. package/dist/twilight/{p-DQXp-sN5.js → p-BTd4Mp32.js} +1 -1
  300. package/dist/twilight/{p-BYpv9A8D.js → p-Bdy-19kn.js} +1 -1
  301. package/dist/twilight/{p-DYcV7UW8.js → p-Be0gsl2J.js} +1 -1
  302. package/dist/twilight/{p-KZ7SFw0C.js → p-BeJV4WrP.js} +1 -1
  303. package/dist/twilight/{p-DYgnIxqR.js → p-BsrZms1J.js} +1 -1
  304. package/dist/twilight/{p-kflOqry6.js → p-CIW_DqnB.js} +1 -1
  305. package/dist/twilight/{p-DMHhYV48.js → p-CZFiZZq_.js} +1 -1
  306. package/dist/twilight/{p-CHOv1Smw.js → p-CkIv9zJH.js} +1 -1
  307. package/dist/twilight/{p-061fdc55.entry.js → p-a38b58ca.entry.js} +1 -1
  308. package/dist/twilight/{p-47c9e882.entry.js → p-a60c4d82.entry.js} +1 -1
  309. package/dist/twilight/{p-3c96d5af.entry.js → p-a6a3a2af.entry.js} +1 -1
  310. package/dist/twilight/{p-eb2e3e67.entry.js → p-a8683925.entry.js} +1 -1
  311. package/dist/twilight/{p-04fadfb3.entry.js → p-a9dd59e6.entry.js} +1 -1
  312. package/dist/twilight/{p-98186fb3.entry.js → p-ae1d9d25.entry.js} +1 -1
  313. package/dist/twilight/{p-e5c2df5a.entry.js → p-aec3c134.entry.js} +1 -1
  314. package/dist/twilight/{p-f9a3f3f4.entry.js → p-b879c791.entry.js} +1 -1
  315. package/dist/twilight/{p-bd2672ee.entry.js → p-b8875211.entry.js} +1 -1
  316. package/dist/twilight/{p-4fff03a8.entry.js → p-b9d30af2.entry.js} +1 -1
  317. package/dist/twilight/{p-5f47eb12.entry.js → p-bb4774ef.entry.js} +1 -1
  318. package/dist/twilight/{p-6e535738.entry.js → p-bd3b3b56.entry.js} +1 -1
  319. package/dist/twilight/{p-72c9cd44.entry.js → p-bf22b091.entry.js} +1 -1
  320. package/dist/twilight/{p-9c798a1a.entry.js → p-c23d9868.entry.js} +1 -1
  321. package/dist/twilight/{p-90d53c9b.entry.js → p-c2fd3800.entry.js} +1 -1
  322. package/dist/twilight/p-c3598ac9.entry.js +4 -0
  323. package/dist/twilight/{p-c6d64b53.entry.js → p-cbe499ec.entry.js} +1 -1
  324. package/dist/twilight/{p-ecdf7027.entry.js → p-cdc167c6.entry.js} +1 -1
  325. package/dist/twilight/{p-022343f3.entry.js → p-d3807e1d.entry.js} +1 -1
  326. package/dist/twilight/{p-f9912293.entry.js → p-d3a91c42.entry.js} +1 -1
  327. package/dist/twilight/{p-d49130fc.entry.js → p-d4242231.entry.js} +1 -1
  328. package/dist/twilight/p-d454c6ac.entry.js +4 -0
  329. package/dist/twilight/{p-a96e5e06.entry.js → p-d86136e7.entry.js} +1 -1
  330. package/dist/twilight/{p-8658fefd.entry.js → p-dfc06251.entry.js} +1 -1
  331. package/dist/twilight/{p-930ff69a.entry.js → p-e033c3ad.entry.js} +1 -1
  332. package/dist/twilight/{p-03db477f.entry.js → p-e416ee2b.entry.js} +1 -1
  333. package/dist/twilight/{p-7e730733.entry.js → p-ef0ff326.entry.js} +1 -1
  334. package/dist/twilight/{p-f4eba1d1.entry.js → p-f00e25a1.entry.js} +1 -1
  335. package/dist/twilight/{p-0bc04e3f.entry.js → p-f5a960be.entry.js} +1 -1
  336. package/dist/twilight/{p-168e3ad8.entry.js → p-f6623828.entry.js} +1 -1
  337. package/dist/twilight/{p-54e43314.entry.js → p-fb79a1b4.entry.js} +1 -1
  338. package/dist/twilight/{p-f060a3dd.entry.js → p-fb8e031a.entry.js} +1 -1
  339. package/dist/twilight/{p-bdda14f6.entry.js → p-fd53f57a.entry.js} +1 -1
  340. package/dist/twilight/twilight.esm.js +1 -1
  341. package/dist/types/components/salla-basket-gap/salla-basket-gap.d.ts +52 -0
  342. package/dist/types/components/salla-quick-buy/salla-quick-buy.d.ts +20 -0
  343. package/dist/types/components.d.ts +43 -0
  344. package/dist/types/shared/catalog-recommendations.d.ts +2 -0
  345. package/package.json +5 -5
  346. package/dist/twilight/p-25ZR4Fc8.js +0 -4
  347. package/dist/twilight/p-2985e01e.entry.js +0 -4
  348. package/dist/twilight/p-931c44fb.entry.js +0 -4
  349. package/dist/twilight/p-982ccb80.entry.js +0 -4
@@ -0,0 +1,306 @@
1
+ /*!
2
+ * Crafted with ❤ by Salla
3
+ */
4
+ import { Host, h } from "@stencil/core";
5
+ import { fetchCartBoughtTogether } from "../../shared/catalog-recommendations";
6
+ export class SallaBasketGap {
7
+ constructor() {
8
+ /**
9
+ * Maximum number of recommendations to fetch.
10
+ */
11
+ this.limit = 10;
12
+ this.products = [];
13
+ this.isLoading = true;
14
+ this.canRender = true;
15
+ this.title = '';
16
+ this.addToCartLabel = '';
17
+ this.weightLabel = '';
18
+ this.discountLabel = '';
19
+ this.placeholder = '';
20
+ this.fetchGeneration = 0;
21
+ this.isSyncingCart = false;
22
+ this.cartItemChangedHandler = (response) => {
23
+ const items = response?.data?.cart?.items ?? [];
24
+ const ids = items.map((i) => String(i.product_id)).filter(Boolean);
25
+ // Reflect a newly added product in the cart list without a full page refresh.
26
+ this.syncCartItemsDom(items);
27
+ this.fetchRecommendations(ids);
28
+ };
29
+ this.beforeAddItemHandler = (data) => {
30
+ const id = String(data?.id ?? '');
31
+ if (id && this.products.some((p) => String(p.id) === id) && salla.cart?.api) {
32
+ salla.cart.api.addToCartSource = 'basket_gap';
33
+ }
34
+ };
35
+ this.addButtonSuccessHandler = (event) => {
36
+ const productId = event?.target?.getAttribute?.('product-id');
37
+ if (!productId)
38
+ return;
39
+ const product = this.products.find((p) => String(p.id) === String(productId));
40
+ if (!product)
41
+ return;
42
+ const items = event?.detail?.data?.items ?? [];
43
+ const cartItem = items.find((i) => String(i.product_id) === String(product.id)) ?? items.slice(-1)[0];
44
+ salla.event.emit('salla-basket-gap::product.added', [{
45
+ product,
46
+ position: this.products.indexOf(product) + 1,
47
+ cartItem,
48
+ cartId: event?.detail?.data?.id,
49
+ source: 'basket_gap',
50
+ }]);
51
+ };
52
+ salla.lang.onLoaded(() => {
53
+ this.title = salla.lang.get('pages.cart.basket_gap_title');
54
+ this.addToCartLabel = salla.lang.get('pages.cart.add_to_cart');
55
+ this.weightLabel = salla.lang.get('pages.products.weight');
56
+ this.discountLabel = salla.lang.get('pages.products.discount');
57
+ });
58
+ }
59
+ componentWillLoad() {
60
+ salla.onReady().then(() => {
61
+ if (!salla.config.get('store.settings.cart.basket_gap')) {
62
+ this.canRender = false;
63
+ this.isLoading = false;
64
+ return;
65
+ }
66
+ this.title = salla.lang.get('pages.cart.basket_gap_title');
67
+ this.addToCartLabel = salla.lang.get('pages.cart.add_to_cart');
68
+ this.weightLabel = salla.lang.get('pages.products.weight');
69
+ this.discountLabel = salla.lang.get('pages.products.discount');
70
+ this.placeholder = salla.url.asset(salla.config.get('theme.settings.placeholder'));
71
+ const cachedCart = salla.storage.get('cart');
72
+ const cachedIds = (cachedCart?.items ?? []).map((i) => String(i.product_id)).filter(Boolean);
73
+ if (cachedIds.length) {
74
+ return this.fetchRecommendations(cachedIds);
75
+ }
76
+ return salla.api.cart.details()
77
+ .then(({ data: { cart } }) => {
78
+ const objectIDs = (cart?.items ?? []).map((i) => String(i.product_id)).filter(Boolean);
79
+ return this.fetchRecommendations(objectIDs);
80
+ })
81
+ .catch(() => {
82
+ this.canRender = false;
83
+ this.isLoading = false;
84
+ });
85
+ });
86
+ }
87
+ componentDidLoad() {
88
+ this.positionUnderCartItems();
89
+ }
90
+ componentDidUpdate() {
91
+ document.lazyLoadInstance?.update(this.host.querySelectorAll('.lazy'));
92
+ this.positionUnderCartItems();
93
+ }
94
+ /**
95
+ * Cart item rows on the storefront cart page (excluding the order-options block).
96
+ * Kept defensive: themes that don't use the `form[id^="item-"]` pattern return none.
97
+ */
98
+ getCartItemForms(root = document) {
99
+ return Array.from(root.querySelectorAll('form[id^="item-"]'))
100
+ .filter((form) => !form.closest('.cart-options'));
101
+ }
102
+ /**
103
+ * The component is injected at the theme's `cart:items.end` hook, which may sit
104
+ * below the order options/offers. Move the host to render directly under the
105
+ * cart items. No-ops when the cart item pattern isn't present.
106
+ */
107
+ positionUnderCartItems() {
108
+ const items = this.getCartItemForms();
109
+ const lastItem = items[items.length - 1];
110
+ if (lastItem && lastItem.nextElementSibling !== this.host) {
111
+ lastItem.after(this.host);
112
+ }
113
+ }
114
+ /**
115
+ * Reflect a newly added product in the cart list without a full page reload.
116
+ * The whole item list is replaced with the fresh server-rendered rows because
117
+ * Salla re-assigns cart line-item ids on add, so diffing by id would duplicate
118
+ * the existing rows. No-ops on themes without the cart item markup.
119
+ */
120
+ syncCartItemsDom(cartItems) {
121
+ if (!cartItems?.length || this.isSyncingCart)
122
+ return;
123
+ const missing = cartItems.filter((item) => !document.getElementById('item-' + item.id));
124
+ if (!missing.length)
125
+ return;
126
+ this.isSyncingCart = true;
127
+ fetch(window.location.href, { headers: { 'X-Requested-With': 'XMLHttpRequest' }, credentials: 'same-origin' })
128
+ .then((res) => res.text())
129
+ .then((html) => {
130
+ const doc = new DOMParser().parseFromString(html, 'text/html');
131
+ const freshForms = this.getCartItemForms(doc);
132
+ const currentForms = this.getCartItemForms();
133
+ if (!freshForms.length || !currentForms.length)
134
+ return;
135
+ const firstCurrent = currentForms[0];
136
+ const parent = firstCurrent.parentElement;
137
+ if (!parent)
138
+ return;
139
+ // Insert the fresh rows in place of the current ones, then drop the old rows.
140
+ freshForms.forEach((form) => {
141
+ parent.insertBefore(document.importNode(form, true), firstCurrent);
142
+ });
143
+ currentForms.forEach((form) => form.remove());
144
+ document.lazyLoadInstance?.update?.();
145
+ this.positionUnderCartItems();
146
+ })
147
+ .catch(() => { })
148
+ .finally(() => { this.isSyncingCart = false; });
149
+ }
150
+ connectedCallback() {
151
+ salla.event.on('cart::item.added', this.cartItemChangedHandler);
152
+ salla.event.on('cart::item.deleted', this.cartItemChangedHandler);
153
+ // Tag adds originating from a basket-gap recommendation so the cart auto-track
154
+ // is suppressed in favour of our attributed `salla-basket-gap::product.added`.
155
+ salla.event.on('cart::before.add.item', this.beforeAddItemHandler);
156
+ this.host.addEventListener('success', this.addButtonSuccessHandler);
157
+ }
158
+ disconnectedCallback() {
159
+ salla.event.off('cart::item.added', this.cartItemChangedHandler);
160
+ salla.event.off('cart::item.deleted', this.cartItemChangedHandler);
161
+ salla.event.off('cart::before.add.item', this.beforeAddItemHandler);
162
+ this.host.removeEventListener('success', this.addButtonSuccessHandler);
163
+ }
164
+ // The recommendation API receives at most 5 cart product IDs, so it can return
165
+ // products that are already in the cart (those beyond the 5-item payload limit).
166
+ // We filter them out here to avoid showing items the customer already has.
167
+ // cartProductIds may be passed in directly from a live event payload; otherwise
168
+ // we fall back to storage (which can lag behind on the initial load path).
169
+ getCartProductIds(knownIds) {
170
+ if (knownIds?.length)
171
+ return new Set(knownIds);
172
+ const cart = salla.storage.get('cart');
173
+ return new Set((cart?.items ?? []).map((i) => String(i.product_id)).filter(Boolean));
174
+ }
175
+ fetchRecommendations(objectIDs) {
176
+ if (!objectIDs.length) {
177
+ this.canRender = false;
178
+ this.isLoading = false;
179
+ return Promise.resolve();
180
+ }
181
+ const generation = ++this.fetchGeneration;
182
+ return fetchCartBoughtTogether(objectIDs)
183
+ .then((ids) => {
184
+ if (generation !== this.fetchGeneration)
185
+ return;
186
+ // Pass objectIDs as the authoritative cart list so the filter is not
187
+ // affected by stale storage when called from a live cart event.
188
+ const cartIds = this.getCartProductIds(objectIDs);
189
+ const filteredIds = ids.filter(id => !cartIds.has(id));
190
+ if (!filteredIds.length) {
191
+ this.canRender = false;
192
+ return;
193
+ }
194
+ return this.fetchProducts(filteredIds.slice(0, this.limit), generation);
195
+ })
196
+ .catch(() => {
197
+ if (generation !== this.fetchGeneration)
198
+ return;
199
+ this.canRender = false;
200
+ })
201
+ .finally(() => {
202
+ if (generation !== this.fetchGeneration)
203
+ return;
204
+ this.isLoading = false;
205
+ });
206
+ }
207
+ fetchProducts(ids, generation) {
208
+ return salla.api.withoutNotifier(() => salla.product.api.fetch({
209
+ source: 'selected',
210
+ source_value: ids,
211
+ limit: this.limit,
212
+ })).then((response) => {
213
+ if (generation !== this.fetchGeneration)
214
+ return;
215
+ this.products = response?.data ?? [];
216
+ this.canRender = this.products.length > 0;
217
+ }).catch(() => {
218
+ if (generation !== this.fetchGeneration)
219
+ return;
220
+ this.canRender = false;
221
+ });
222
+ }
223
+ getDiscountLabel(product) {
224
+ if (product.promotion_title)
225
+ return product.promotion_title;
226
+ if (product.is_on_sale && product.regular_price > 0 && product.sale_price > 0) {
227
+ const percent = Math.round((1 - product.sale_price / product.regular_price) * 100);
228
+ return percent > 0 ? `${this.discountLabel} ${percent}%` : null;
229
+ }
230
+ return null;
231
+ }
232
+ formatDate(timestamp) {
233
+ const d = new Date(timestamp * 1000);
234
+ const mm = String(d.getMonth() + 1).padStart(2, '0');
235
+ const dd = String(d.getDate()).padStart(2, '0');
236
+ return `${d.getFullYear()}-${mm}-${dd}`;
237
+ }
238
+ getSkeletonView() {
239
+ return (h(Host, { class: "s-basket-gap-entry" }, h("div", { class: "s-basket-gap-skeleton" }, h("salla-skeleton", { height: "16px", width: "40%", style: { marginBottom: '16px' } }), Array(3).fill(null).map((_, i) => (h("div", { key: i, class: "s-basket-gap-skeleton-card" }, h("salla-skeleton", { height: "64px", width: "64px", style: { borderRadius: '8px', flexShrink: '0' } }), h("div", { class: "s-basket-gap-skeleton-info" }, h("salla-skeleton", { height: "14px", width: "50%" }), h("salla-skeleton", { height: "12px", width: "25%", style: { marginTop: '6px' } }), h("salla-skeleton", { height: "10px", width: "35%", style: { marginTop: '4px' } })), h("salla-skeleton", { height: "36px", width: "100px", style: { borderRadius: '6px', flexShrink: '0', marginInlineStart: 'auto' } })))))));
240
+ }
241
+ getProductCard(product) {
242
+ const discountLabel = this.getDiscountLabel(product);
243
+ return (h("div", { key: product.id, class: "s-basket-gap-card" }, h("a", { href: product.url, class: "s-basket-gap-card-image" }, h("img", { class: "lazy", src: this.placeholder, "data-src": product.image?.url, alt: product.image?.alt || product.name })), h("div", { class: "s-basket-gap-card-info" }, h("h3", { class: "s-basket-gap-card-name" }, h("a", { href: product.url }, product.name)), product.is_on_sale
244
+ ? h("div", { class: "s-basket-gap-card-sale-price" }, h("span", { innerHTML: salla.money(product.sale_price) }), h("del", { innerHTML: salla.money(product.regular_price) }))
245
+ : h("span", { class: "s-basket-gap-card-price", innerHTML: salla.money(product.price) }), product.weight_label && (h("span", { class: "s-basket-gap-card-weight" }, this.weightLabel, " ", product.weight_label))), (product.promotion_title || product.discount_ends || product.is_on_sale) && (h("div", { class: "s-basket-gap-card-offer" }, h("i", { class: "sicon-gift" }), discountLabel && h("span", null, discountLabel), product.discount_ends && [
246
+ h("salla-count-down", { date: this.formatDate(product.discount_ends), "end-of-day": true, digits: "en" }),
247
+ h("i", { class: "sicon-alarm" }),
248
+ ])), h("salla-add-product-button", { class: "s-basket-gap-card-btn", "product-id": product.id, "product-status": product.status, "product-type": product.type }, this.addToCartLabel)));
249
+ }
250
+ render() {
251
+ if (!this.canRender)
252
+ return null;
253
+ if (this.isLoading)
254
+ return this.getSkeletonView();
255
+ if (!this.products.length)
256
+ return null;
257
+ return (h(Host, { class: "s-basket-gap-entry" }, this.title && h("h2", { class: "s-basket-gap-title" }, this.title), h("div", { class: "s-basket-gap-list" }, this.products.map(product => this.getProductCard(product)))));
258
+ }
259
+ static get is() { return "salla-basket-gap"; }
260
+ static get originalStyleUrls() {
261
+ return {
262
+ "$": ["salla-basket-gap.scss"]
263
+ };
264
+ }
265
+ static get styleUrls() {
266
+ return {
267
+ "$": ["salla-basket-gap.css"]
268
+ };
269
+ }
270
+ static get properties() {
271
+ return {
272
+ "limit": {
273
+ "type": "number",
274
+ "attribute": "limit",
275
+ "mutable": false,
276
+ "complexType": {
277
+ "original": "number",
278
+ "resolved": "number",
279
+ "references": {}
280
+ },
281
+ "required": false,
282
+ "optional": false,
283
+ "docs": {
284
+ "tags": [],
285
+ "text": "Maximum number of recommendations to fetch."
286
+ },
287
+ "getter": false,
288
+ "setter": false,
289
+ "reflect": false,
290
+ "defaultValue": "10"
291
+ }
292
+ };
293
+ }
294
+ static get states() {
295
+ return {
296
+ "products": {},
297
+ "isLoading": {},
298
+ "canRender": {},
299
+ "title": {},
300
+ "addToCartLabel": {},
301
+ "weightLabel": {},
302
+ "discountLabel": {}
303
+ };
304
+ }
305
+ static get elementRef() { return "host"; }
306
+ }
@@ -2,8 +2,7 @@
2
2
  * Crafted with ❤ by Salla
3
3
  */
4
4
  import { Host, h } from "@stencil/core";
5
- // Read-only recommendations key confirmed safe for client-side use by the API team — no write access or sensitive scope.
6
- const XSELL_API_KEY = 'VOL5WaZu2YROp0RplCZAr1RplhL9FFGQ';
5
+ import { fetchProductCustomersAlsoBought } from "../../shared/catalog-recommendations";
7
6
  export class SallaBoughtTogether {
8
7
  constructor() {
9
8
  /**
@@ -39,25 +38,14 @@ export class SallaBoughtTogether {
39
38
  return;
40
39
  }
41
40
  this.resolvedProductId = id;
42
- return salla.api.request('https://api.salla.dev/1/indexes/*/recommendations', {
43
- requests: [{
44
- indexName: 'products',
45
- model: 'xsell-v1',
46
- priceThreshold: 2,
47
- objectID: String(id),
48
- maxRecommendations: this.limit,
49
- }]
50
- }, 'post', { headers: { 'X-Algolia-Api-Key': XSELL_API_KEY, 'X-Query-Enrichment': 'false', 'X-source': 'store' } });
41
+ return fetchProductCustomersAlsoBought(String(id));
51
42
  })
52
- .then((response) => {
53
- if (!response)
54
- return;
55
- const hits = response?.results?.[0]?.hits ?? [];
56
- if (!hits.length) {
43
+ .then((recommendedIds) => {
44
+ if (!recommendedIds?.length) {
57
45
  this.canRender = false;
58
46
  return;
59
47
  }
60
- const ids = [String(this.resolvedProductId), ...hits.map(h => h.objectID)];
48
+ const ids = [String(this.resolvedProductId), ...recommendedIds.slice(0, this.limit)];
61
49
  return salla.product.fetch({ source: 'selected', source_value: ids });
62
50
  })
63
51
  .then((response) => {
@@ -125,7 +125,8 @@ export class SallaCountDown {
125
125
  return !isNaN(Date.parse(testedDate));
126
126
  }
127
127
  number(digit) {
128
- return salla.helpers.number(digit, this.digits === 'en');
128
+ const value = String(Math.max(0, Math.floor(digit))).padStart(2, '0');
129
+ return salla.helpers.number(value, this.digits === 'en');
129
130
  }
130
131
  startCountDown() {
131
132
  const normalized = this.normalizeDate(this.date);
@@ -228,7 +229,7 @@ export class SallaCountDown {
228
229
  return this.renderCountDown();
229
230
  }
230
231
  render() {
231
- return (h(Host, { key: '966a6ce961c0cc07b937d9b8e328211377084d44', class: `s-count-down-wrapper ${this.preOrder && this.isValidDate(this.date) ? 's-count-down-pre-order' : ''} ${this.horizontal ? 's-count-down-horizontal' : ''} ${this.withButton ? 's-count-down-with-button' : ''} ${this.offerEnded ? 's-count-down-ended' : ''}` }, this.renderPrefixText(), this.renderContent(), this.offerEnded && this.renderOfferEnded(), this.renderButton()));
232
+ return (h(Host, { key: 'e2805e528a52b71ad71f4f1f16a473947dafb5bc', class: `s-count-down-wrapper ${this.preOrder && this.isValidDate(this.date) ? 's-count-down-pre-order' : ''} ${this.horizontal ? 's-count-down-horizontal' : ''} ${this.withButton ? 's-count-down-with-button' : ''} ${this.offerEnded ? 's-count-down-ended' : ''}` }, this.renderPrefixText(), this.renderContent(), this.offerEnded && this.renderOfferEnded(), this.renderButton()));
232
233
  }
233
234
  static get is() { return "salla-count-down"; }
234
235
  static get originalStyleUrls() {
@@ -125,8 +125,15 @@ export class SallaQuickBuy {
125
125
  currency: this.currency || 'SAR', // SAR
126
126
  requiredShippingContactFields: this.getRequiredShippingContactFields(),
127
127
  shippingMethods: this.isRequireShipping ? [] : undefined,
128
- supportedNetworks: salla.config.get('store.settings.buy_now.networks'),
129
- supportedCountries: salla.config.get('store.settings.buy_now.countries'),
128
+ // Legacy BE
129
+ supportedNetworks: this.isLegacyBuyNowBE()
130
+ ? salla.config.get('store.settings.buy_now.networks')
131
+ : ((Array.isArray(this.supportedNetworks) && this.supportedNetworks.length)
132
+ ? this.supportedNetworks : salla.config.get('store.settings.buy_now.supportedNetworks')),
133
+ supportedCountries: this.isLegacyBuyNowBE()
134
+ ? salla.config.get('store.settings.buy_now.countries')
135
+ : ((Array.isArray(this.supportedCountries) && this.supportedCountries.length)
136
+ ? this.supportedCountries : salla.config.get('store.settings.buy_now.supportedCountries')),
130
137
  countryCode: salla.config.get('store.store_country') || 'SA',
131
138
  onStartedSession: this.handleApplePaySessionStarted,
132
139
  validateMerchant: {
@@ -203,6 +210,35 @@ export class SallaQuickBuy {
203
210
  }
204
211
  return fields;
205
212
  }
213
+ /**
214
+ * TEMPORARY for BE Vip sync
215
+ */
216
+ isLegacyBuyNowBE() {
217
+ return salla?.config?.get?.('store.settings.buy_now.networks') != null;
218
+ }
219
+ /** Set Apple Pay amount + currency from a price payload, always keeping the pair in one currency. */
220
+ applyBaseCurrencyPrice(data) {
221
+ // Legacy BE: amount only; currency is set once in runInit.
222
+ if (this.isLegacyBuyNowBE()) {
223
+ if (data?.price != null) {
224
+ this.amount = data.price;
225
+ }
226
+ return;
227
+ }
228
+ const base = data?.base_currency_price;
229
+ // Unified BE base pair (regular products): charge in base currency.
230
+ if (base?.amount != null) {
231
+ this.amount = base.amount;
232
+ if (base?.currency) {
233
+ this.currency = base.currency;
234
+ }
235
+ // Display-only payload (e.g. donation { id, price }): pair amount with its display currency.
236
+ }
237
+ else if (data?.price != null) {
238
+ this.amount = data.price;
239
+ this.currency = salla.config.get('user.currency_code') || this.currency || 'SAR';
240
+ }
241
+ }
206
242
  componentWillLoad() {
207
243
  console.log('🍏 Pay: Quick Buy Component Loaded');
208
244
  const canMakePayments = typeof window !== 'undefined' && !!window.ApplePaySession?.canMakePayments?.();
@@ -210,7 +246,9 @@ export class SallaQuickBuy {
210
246
  const isSallaGateway = salla?.config?.get?.('store.settings.is_salla_gateway', false) ?? true;
211
247
  this.isApplePayActive = canMakePayments && storeHasApplePay && isSallaGateway;
212
248
  const runInit = async () => {
213
- if (!this.currency && salla?.config?.get) {
249
+ if (this.isLegacyBuyNowBE() && !this.currency && salla?.config?.get) {
250
+ // Legacy BE (pre-PR): currency from the multi_currency flag. The unified BE instead
251
+ // sources amount + currency from `base_currency_price` (see applyBaseCurrencyPrice).
214
252
  this.currency = salla.config.get('store.settings.buy_now.multi_currency') ? salla.config.get('user.currency_code') : 'SAR';
215
253
  }
216
254
  if (!this.productId && salla?.config?.get && salla.url?.is_page) {
@@ -222,7 +260,7 @@ export class SallaQuickBuy {
222
260
  }
223
261
  if ((!this.amount || !this.isRequireShipping) && this.productId && salla?.product?.getDetails) {
224
262
  await salla.product.getDetails(this.productId, []).then((response) => {
225
- this.amount = response.data.price;
263
+ this.applyBaseCurrencyPrice(response?.data);
226
264
  this.isRequireShipping = response?.data?.is_require_shipping || false;
227
265
  }).catch((error) => {
228
266
  salla?.logger?.warn?.('🍏 Pay: Failed load the quick buy, get the product details failed: ', error);
@@ -232,11 +270,11 @@ export class SallaQuickBuy {
232
270
  salla.event.on('product-options::donation-changed', (data) => {
233
271
  if (String(data.id) !== String(this.productId))
234
272
  return;
235
- this.amount = data.price;
273
+ this.applyBaseCurrencyPrice(data);
236
274
  });
237
275
  }
238
276
  else if (salla?.url?.is_page?.('product.single') && salla?.product?.event?.onPriceUpdated) {
239
- salla.product.event.onPriceUpdated(response => { this.amount = response.data.price; });
277
+ salla.product.event.onPriceUpdated(response => { this.applyBaseCurrencyPrice(response?.data); });
240
278
  }
241
279
  this.isApplePayActive = (salla?.helpers?.hasApplePay?.() ?? canMakePayments)
242
280
  && (salla?.config?.get?.('store.settings.payments')?.includes?.('apple_pay') ?? storeHasApplePay)
@@ -259,7 +297,7 @@ export class SallaQuickBuy {
259
297
  });
260
298
  }
261
299
  render() {
262
- return h(Host, { key: '1895bf6077b3c9d2068830ac621e8f5b8afd1193' }, this.quickBuyButton());
300
+ return h(Host, { key: '8df291680d9b59f1627c8e1185a01cb30b92c2e4' }, this.quickBuyButton());
263
301
  }
264
302
  quickBuyButton() {
265
303
  return h("apple-pay-button", { locale: salla?.config?.get?.('user.language_code') || 'ar', onClick: () => this.quickBuyHandler(), "data-quick-purchase": "applepay", class: "s-quick-buy-apple-pay", "data-is-applepay": "1", buttonstyle: "black", type: this.type });
@@ -514,6 +552,48 @@ export class SallaQuickBuy {
514
552
  "getter": false,
515
553
  "setter": false,
516
554
  "reflect": false
555
+ },
556
+ "supportedNetworks": {
557
+ "type": "unknown",
558
+ "attribute": "supported-networks",
559
+ "mutable": true,
560
+ "complexType": {
561
+ "original": "string[]",
562
+ "resolved": "string[]",
563
+ "references": {}
564
+ },
565
+ "required": false,
566
+ "optional": false,
567
+ "docs": {
568
+ "tags": [{
569
+ "name": "type",
570
+ "text": "{string[]}"
571
+ }],
572
+ "text": "Apple Pay supported card networks. Optional array override for surfaces that already hold the\nunified backend value (e.g. mini-checkout property-binds `payments.gateways.applePay.supportedNetworks`).\nWhen unset/empty, falls back to the PDP `store.settings.buy_now.supportedNetworks` config."
573
+ },
574
+ "getter": false,
575
+ "setter": false
576
+ },
577
+ "supportedCountries": {
578
+ "type": "unknown",
579
+ "attribute": "supported-countries",
580
+ "mutable": true,
581
+ "complexType": {
582
+ "original": "string[]",
583
+ "resolved": "string[]",
584
+ "references": {}
585
+ },
586
+ "required": false,
587
+ "optional": false,
588
+ "docs": {
589
+ "tags": [{
590
+ "name": "type",
591
+ "text": "{string[]}"
592
+ }],
593
+ "text": "Apple Pay supported countries. Same array override/fallback semantics as `supportedNetworks`."
594
+ },
595
+ "getter": false,
596
+ "setter": false
517
597
  }
518
598
  };
519
599
  }
@@ -0,0 +1,89 @@
1
+ /*!
2
+ * Crafted with ❤ by Salla
3
+ */
4
+ const RECOMMENDATIONS_BASE_PATH = '/recommendations/v1';
5
+ const CART_BOUGHT_TOGETHER_MAX_PRODUCT_IDS = 5;
6
+ const CATALOG_RECOMMENDATIONS_API = 'https://api.salla.dev';
7
+ function getRecommendationsBaseUrl() {
8
+ const storeApi = String(salla.config.get('store.api', '') || '').replace(/\/$/, '');
9
+ if (storeApi.includes('api.salla.dev')) {
10
+ return storeApi;
11
+ }
12
+ // Recommendations proxy is on the global catalog API host (prod-only for now),
13
+ // not on beta preview /api/v1 paths that store.api may point to.
14
+ return CATALOG_RECOMMENDATIONS_API;
15
+ }
16
+ function getRecommendationsUrl(path) {
17
+ return `${getRecommendationsBaseUrl()}${RECOMMENDATIONS_BASE_PATH}${path}`;
18
+ }
19
+ function parseHostname(value) {
20
+ if (!value) {
21
+ return null;
22
+ }
23
+ try {
24
+ const normalized = value.startsWith('http') ? value : `https://${value}`;
25
+ return new URL(normalized).hostname || null;
26
+ }
27
+ catch {
28
+ const hostname = String(value).replace(/^https?:\/\//i, '').split('/')[0];
29
+ return hostname || null;
30
+ }
31
+ }
32
+ function getStoreOriginHostname() {
33
+ const trackUrl = salla.config.get('jitsu.track_url');
34
+ const trackHostname = trackUrl ? parseHostname(String(trackUrl)) : null;
35
+ if (trackHostname) {
36
+ return trackHostname;
37
+ }
38
+ for (const candidate of [salla.config.get('store.domain'), salla.config.get('store.url')]) {
39
+ const hostname = candidate ? parseHostname(String(candidate)) : null;
40
+ if (hostname && !hostname.includes('beta.salla.group')) {
41
+ return hostname;
42
+ }
43
+ }
44
+ return window.location.hostname;
45
+ }
46
+ function getRecommendationsRequestConfig(params) {
47
+ const headers = {
48
+ 's-store-id': String(salla.config.get('store.id')),
49
+ origin: getStoreOriginHostname(),
50
+ 's-source': 'store',
51
+ lang: salla.lang.getLocale(),
52
+ };
53
+ const scopeId = salla.api.getHeader('s-scope-id');
54
+ if (scopeId) {
55
+ headers['s-scope-id'] = String(scopeId);
56
+ }
57
+ return { params, headers };
58
+ }
59
+ function extractRecommendationIds(response) {
60
+ return (response?.data ?? [])
61
+ .map(item => item?.id)
62
+ .filter((id) => Boolean(id));
63
+ }
64
+ function fetchRecommendations(path, params) {
65
+ const url = getRecommendationsUrl(path);
66
+ const config = getRecommendationsRequestConfig(params);
67
+ // Recommendations are a non-critical, best-effort feature; suppress the global
68
+ // API error notifier so transient failures stay invisible and the consuming
69
+ // component can silently hide its section via its own .catch().
70
+ return salla.api.withoutNotifier(() => salla.api.request(url, config, 'get'))
71
+ .then((response) => extractRecommendationIds(response));
72
+ }
73
+ export function fetchCartBoughtTogether(productIds) {
74
+ const ids = productIds.slice(0, CART_BOUGHT_TOGETHER_MAX_PRODUCT_IDS);
75
+ if (!ids.length) {
76
+ return Promise.resolve([]);
77
+ }
78
+ return fetchRecommendations('/carts/bought-together', {
79
+ product_ids: ids.join(','),
80
+ });
81
+ }
82
+ export function fetchProductCustomersAlsoBought(productId) {
83
+ if (!productId) {
84
+ return Promise.resolve([]);
85
+ }
86
+ return fetchRecommendations('/products/customers-also-bought', {
87
+ product_id: productId,
88
+ });
89
+ }