@salla.sa/twilight-components 3.0.17 → 3.0.19

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 (408) hide show
  1. package/dist/cjs/{Helper-DSYelC4c.js → Helper-DqKJCL8G.js} +1 -1
  2. package/dist/cjs/{filepond-l9D0Yv7b.js → filepond-Byu0lc8z.js} +1 -1
  3. package/dist/cjs/{filepond-plugin-file-poster-8SrbLptI.js → filepond-plugin-file-poster-qwx7lYZ-.js} +1 -1
  4. package/dist/cjs/{filepond-plugin-file-validate-size-DGD6oJy0.js → filepond-plugin-file-validate-size-C-n0P4TT.js} +1 -1
  5. package/dist/cjs/{filepond-plugin-file-validate-type-BIvrhp3w.js → filepond-plugin-file-validate-type-C8VOOXdT.js} +1 -1
  6. package/dist/cjs/{filepond-plugin-image-edit-4xKikdXG.js → filepond-plugin-image-edit-B9KG763Y.js} +1 -1
  7. package/dist/cjs/{filepond-plugin-image-exif-orientation-C3BvwxQh.js → filepond-plugin-image-exif-orientation-Czt4pYzU.js} +1 -1
  8. package/dist/cjs/{filepond-plugin-image-preview-CBq_GY0V.js → filepond-plugin-image-preview-BFm1Zl0o.js} +1 -1
  9. package/dist/cjs/free-shipping-timer-6QBe5BNS.js +156 -0
  10. package/dist/cjs/helpers-NV7wgP50.js +602 -0
  11. package/dist/cjs/{index-BAwxpXnB.js → index-CFW798jX.js} +2 -2
  12. package/dist/cjs/{intlTelInput-xw-HaAEN.js → intlTelInput-CLa2B89b.js} +1 -1
  13. package/dist/cjs/loader.cjs.js +2 -2
  14. package/dist/cjs/salla-accordion-body_2.cjs.entry.js +1 -1
  15. package/dist/cjs/salla-accordion_6.cjs.entry.js +2 -2
  16. package/dist/cjs/salla-add-product-button_5.cjs.entry.js +46 -3
  17. package/dist/cjs/salla-advertisement.cjs.entry.js +1 -1
  18. package/dist/cjs/salla-alert_2.cjs.entry.js +1 -1
  19. package/dist/cjs/salla-app-install-alert.cjs.entry.js +1 -1
  20. package/dist/cjs/salla-applied-filters.cjs.entry.js +2 -2
  21. package/dist/cjs/salla-apps-icons.cjs.entry.js +1 -1
  22. package/dist/cjs/salla-attachment-view_9.cjs.entry.js +11 -11
  23. package/dist/cjs/salla-badge.cjs.entry.js +1 -1
  24. package/dist/cjs/salla-basket-gap.cjs.entry.js +1 -1
  25. package/dist/cjs/salla-bullet-delivery_3.cjs.entry.js +590 -134
  26. package/dist/cjs/salla-cart-coupons.cjs.entry.js +1 -1
  27. package/dist/cjs/salla-cart-item-offers_2.cjs.entry.js +1 -1
  28. package/dist/cjs/salla-cart-summary-card.cjs.entry.js +1 -1
  29. package/dist/cjs/salla-cashback-banner.cjs.entry.js +1 -1
  30. package/dist/cjs/salla-comment-factors.cjs.entry.js +1 -1
  31. package/dist/cjs/salla-comment-form_9.cjs.entry.js +2 -2
  32. package/dist/cjs/salla-conditional-offer.cjs.entry.js +1 -1
  33. package/dist/cjs/salla-contacts.cjs.entry.js +1 -1
  34. package/dist/cjs/salla-cookies-bar.cjs.entry.js +1 -1
  35. package/dist/cjs/salla-count-down.cjs.entry.js +1 -1
  36. package/dist/cjs/salla-custom-fields.cjs.entry.js +1 -1
  37. package/dist/cjs/salla-delivery-promise.cjs.entry.js +2 -2
  38. package/dist/cjs/salla-edit-order-button.cjs.entry.js +1 -1
  39. package/dist/cjs/salla-filters-widget.cjs.entry.js +2 -2
  40. package/dist/cjs/salla-filters.cjs.entry.js +2 -2
  41. package/dist/cjs/salla-free-shipping-banner.cjs.entry.js +95 -9
  42. package/dist/cjs/salla-free-shipping-tag.cjs.entry.js +18 -5
  43. package/dist/cjs/salla-fulfillment-methods.cjs.entry.js +1 -1
  44. package/dist/cjs/salla-gift-card-redeem_2.cjs.entry.js +1 -1
  45. package/dist/cjs/salla-gifting.cjs.entry.js +13 -6
  46. package/dist/cjs/salla-hook.cjs.entry.js +1 -1
  47. package/dist/cjs/salla-infinite-scroll.cjs.entry.js +2 -2
  48. package/dist/cjs/salla-installment.cjs.entry.js +1 -1
  49. package/dist/cjs/salla-list-tile.cjs.entry.js +1 -1
  50. package/dist/cjs/salla-localization-modal.cjs.entry.js +1 -1
  51. package/dist/cjs/salla-login-modal.cjs.entry.js +7 -2
  52. package/dist/cjs/salla-loyalty-banner_10.cjs.entry.js +1 -1
  53. package/dist/cjs/salla-loyalty-exchange-product-card.cjs.entry.js +1 -1
  54. package/dist/cjs/salla-loyalty-points-banner.cjs.entry.js +1 -1
  55. package/dist/cjs/salla-loyalty-points-history.cjs.entry.js +1 -1
  56. package/dist/cjs/salla-loyalty-prize-item.cjs.entry.js +1 -1
  57. package/dist/cjs/salla-loyalty.cjs.entry.js +1 -1
  58. package/dist/cjs/salla-maintenance-alert.cjs.entry.js +1 -1
  59. package/dist/cjs/salla-map_3.cjs.entry.js +1 -1
  60. package/dist/cjs/salla-menu.cjs.entry.js +1 -1
  61. package/dist/cjs/salla-metadata.cjs.entry.js +1 -1
  62. package/dist/cjs/salla-multiple-bundle-product-cart_2.cjs.entry.js +1 -1
  63. package/dist/cjs/salla-multiple-bundle-product-options-modal_2.cjs.entry.js +1 -1
  64. package/dist/cjs/salla-multiple-bundle-product.cjs.entry.js +1 -1
  65. package/dist/cjs/salla-next-order-coupon.cjs.entry.js +1 -1
  66. package/dist/cjs/salla-notification-item_2.cjs.entry.js +2 -2
  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-items.cjs.entry.js +1 -1
  78. package/dist/cjs/salla-order-options-modal.cjs.entry.js +1 -1
  79. package/dist/cjs/salla-order-payment.cjs.entry.js +1 -1
  80. package/dist/cjs/salla-order-rewards.cjs.entry.js +1 -1
  81. package/dist/cjs/salla-order-shipments.cjs.entry.js +1 -1
  82. package/dist/cjs/salla-order-summary.cjs.entry.js +1 -1
  83. package/dist/cjs/salla-order-totals-card.cjs.entry.js +1 -1
  84. package/dist/cjs/salla-orders.cjs.entry.js +2 -2
  85. package/dist/cjs/salla-payments.cjs.entry.js +1 -1
  86. package/dist/cjs/salla-placeholder.cjs.entry.js +1 -1
  87. package/dist/cjs/salla-price-range.cjs.entry.js +1 -1
  88. package/dist/cjs/salla-product-card-embed.cjs.entry.js +1 -1
  89. package/dist/cjs/salla-product-card.cjs.entry.js +1 -1
  90. package/dist/cjs/salla-product-size-guide.cjs.entry.js +1 -1
  91. package/dist/cjs/salla-products-list.cjs.entry.js +13 -5
  92. package/dist/cjs/salla-products-slider.cjs.entry.js +2 -2
  93. package/dist/cjs/salla-quick-order.cjs.entry.js +1 -1
  94. package/dist/cjs/salla-rating-modal-v2.cjs.entry.js +7 -4
  95. package/dist/cjs/salla-rating-modal.cjs.entry.js +2 -2
  96. package/dist/cjs/salla-review-factors-tags.cjs.entry.js +1 -1
  97. package/dist/cjs/salla-review-order-item.cjs.entry.js +1 -1
  98. package/dist/cjs/salla-scopes.cjs.entry.js +1 -1
  99. package/dist/cjs/salla-search-product-card.cjs.entry.js +1 -1
  100. package/dist/cjs/salla-search.cjs.entry.js +2 -2
  101. package/dist/cjs/salla-skeleton.cjs.entry.js +1 -1
  102. package/dist/cjs/salla-social-share.cjs.entry.js +1 -1
  103. package/dist/cjs/salla-social.cjs.entry.js +1 -1
  104. package/dist/cjs/salla-tab-content_3.cjs.entry.js +1 -1
  105. package/dist/cjs/salla-thank-you-header.cjs.entry.js +1 -1
  106. package/dist/cjs/salla-thank-you-page.cjs.entry.js +1 -1
  107. package/dist/cjs/salla-tiered-offer.cjs.entry.js +1 -1
  108. package/dist/cjs/salla-trust-badges.cjs.entry.js +1 -1
  109. package/dist/cjs/salla-user-menu.cjs.entry.js +1 -1
  110. package/dist/cjs/salla-user-profile.cjs.entry.js +1 -1
  111. package/dist/cjs/salla-user-settings.cjs.entry.js +1 -1
  112. package/dist/cjs/salla-verify.cjs.entry.js +1 -1
  113. package/dist/cjs/salla-wallet.cjs.entry.js +1 -1
  114. package/dist/cjs/salla-wishlist-actions.cjs.entry.js +1 -1
  115. package/dist/cjs/salla-wishlist-summary.cjs.entry.js +2 -2
  116. package/dist/cjs/twilight.cjs.js +2 -2
  117. package/dist/cjs/{vanilla-picker-Cm_uNdps.js → vanilla-picker-Vx_7G7bs.js} +1 -1
  118. package/dist/collection/components/salla-bullet-delivery/api-service.js +156 -25
  119. package/dist/collection/components/salla-bullet-delivery/helpers.js +143 -15
  120. package/dist/collection/components/salla-bullet-delivery/icons.js +17 -0
  121. package/dist/collection/components/salla-bullet-delivery/salla-bullet-delivery.css +490 -52
  122. package/dist/collection/components/salla-bullet-delivery/salla-bullet-delivery.js +489 -106
  123. package/dist/collection/components/salla-bullet-delivery/selector-tracker.js +106 -0
  124. package/dist/collection/components/salla-free-shipping-banner/salla-free-shipping-banner.css +18 -4
  125. package/dist/collection/components/salla-free-shipping-banner/salla-free-shipping-banner.js +94 -11
  126. package/dist/collection/components/salla-free-shipping-tag/salla-free-shipping-tag.css +6 -0
  127. package/dist/collection/components/salla-free-shipping-tag/salla-free-shipping-tag.js +18 -2
  128. package/dist/collection/components/salla-gifting/salla-gifting.css +16 -1
  129. package/dist/collection/components/salla-gifting/salla-gifting.js +11 -4
  130. package/dist/collection/components/salla-login-modal/salla-login-modal.js +6 -1
  131. package/dist/collection/components/salla-products-list/salla-products-list.js +11 -3
  132. package/dist/collection/components/salla-quick-buy/salla-quick-buy.js +44 -1
  133. package/dist/collection/components/salla-rating-modal/salla-rating-modal-v2.js +5 -2
  134. package/dist/collection/shared/free-shipping-timer.js +130 -0
  135. package/dist/components/free-shipping-timer.js +150 -0
  136. package/dist/components/helpers.js +299 -40
  137. package/dist/components/index.js +2 -2
  138. package/dist/components/salla-bullet-delivery.js +595 -133
  139. package/dist/components/salla-free-shipping-banner.js +95 -8
  140. package/dist/components/salla-free-shipping-tag.js +17 -3
  141. package/dist/components/salla-gifting.js +12 -5
  142. package/dist/components/salla-login-modal2.js +6 -1
  143. package/dist/components/salla-products-list2.js +11 -3
  144. package/dist/components/salla-quick-buy2.js +44 -1
  145. package/dist/components/salla-rating-modal-v22.js +5 -2
  146. package/dist/docs.json +25 -5
  147. package/dist/esm/{Helper-POCi7J93.js → Helper-I0CAizv1.js} +1 -1
  148. package/dist/esm/{filepond-Ct76xW02.js → filepond-DTUYXV0J.js} +1 -1
  149. package/dist/esm/{filepond-plugin-file-poster-C1OkzGRs.js → filepond-plugin-file-poster-DydZjneT.js} +1 -1
  150. package/dist/esm/{filepond-plugin-file-validate-size-gdd-69cO.js → filepond-plugin-file-validate-size-nbsCU2t9.js} +1 -1
  151. package/dist/esm/{filepond-plugin-file-validate-type-BaZ2QTzl.js → filepond-plugin-file-validate-type-Cl5B_DIy.js} +1 -1
  152. package/dist/esm/{filepond-plugin-image-edit-CsoNvf0i.js → filepond-plugin-image-edit-bzskFyFR.js} +1 -1
  153. package/dist/esm/{filepond-plugin-image-exif-orientation-BHDSe3nH.js → filepond-plugin-image-exif-orientation-MBDuxLaX.js} +1 -1
  154. package/dist/esm/{filepond-plugin-image-preview-CD_S17z3.js → filepond-plugin-image-preview-N6wzEryW.js} +1 -1
  155. package/dist/esm/free-shipping-timer-CnTwkF6y.js +150 -0
  156. package/dist/esm/helpers-Cnh7Qptl.js +568 -0
  157. package/dist/esm/{index-DmGAR42j.js → index-C9zdeQFI.js} +2 -2
  158. package/dist/esm/{intlTelInput-D76Q4XFx.js → intlTelInput-B5L9nYtO.js} +1 -1
  159. package/dist/esm/loader.js +3 -3
  160. package/dist/esm/salla-accordion-body_2.entry.js +1 -1
  161. package/dist/esm/salla-accordion_6.entry.js +2 -2
  162. package/dist/esm/salla-add-product-button_5.entry.js +46 -3
  163. package/dist/esm/salla-advertisement.entry.js +1 -1
  164. package/dist/esm/salla-alert_2.entry.js +1 -1
  165. package/dist/esm/salla-app-install-alert.entry.js +1 -1
  166. package/dist/esm/salla-applied-filters.entry.js +2 -2
  167. package/dist/esm/salla-apps-icons.entry.js +1 -1
  168. package/dist/esm/salla-attachment-view_9.entry.js +11 -11
  169. package/dist/esm/salla-badge.entry.js +1 -1
  170. package/dist/esm/salla-basket-gap.entry.js +1 -1
  171. package/dist/esm/salla-bullet-delivery_3.entry.js +590 -134
  172. package/dist/esm/salla-cart-coupons.entry.js +1 -1
  173. package/dist/esm/salla-cart-item-offers_2.entry.js +1 -1
  174. package/dist/esm/salla-cart-summary-card.entry.js +1 -1
  175. package/dist/esm/salla-cashback-banner.entry.js +1 -1
  176. package/dist/esm/salla-comment-factors.entry.js +1 -1
  177. package/dist/esm/salla-comment-form_9.entry.js +2 -2
  178. package/dist/esm/salla-conditional-offer.entry.js +1 -1
  179. package/dist/esm/salla-contacts.entry.js +1 -1
  180. package/dist/esm/salla-cookies-bar.entry.js +1 -1
  181. package/dist/esm/salla-count-down.entry.js +1 -1
  182. package/dist/esm/salla-custom-fields.entry.js +1 -1
  183. package/dist/esm/salla-delivery-promise.entry.js +2 -2
  184. package/dist/esm/salla-edit-order-button.entry.js +1 -1
  185. package/dist/esm/salla-filters-widget.entry.js +2 -2
  186. package/dist/esm/salla-filters.entry.js +2 -2
  187. package/dist/esm/salla-free-shipping-banner.entry.js +94 -8
  188. package/dist/esm/salla-free-shipping-tag.entry.js +17 -4
  189. package/dist/esm/salla-fulfillment-methods.entry.js +1 -1
  190. package/dist/esm/salla-gift-card-redeem_2.entry.js +1 -1
  191. package/dist/esm/salla-gifting.entry.js +13 -6
  192. package/dist/esm/salla-hook.entry.js +1 -1
  193. package/dist/esm/salla-infinite-scroll.entry.js +2 -2
  194. package/dist/esm/salla-installment.entry.js +1 -1
  195. package/dist/esm/salla-list-tile.entry.js +1 -1
  196. package/dist/esm/salla-localization-modal.entry.js +1 -1
  197. package/dist/esm/salla-login-modal.entry.js +7 -2
  198. package/dist/esm/salla-loyalty-banner_10.entry.js +1 -1
  199. package/dist/esm/salla-loyalty-exchange-product-card.entry.js +1 -1
  200. package/dist/esm/salla-loyalty-points-banner.entry.js +1 -1
  201. package/dist/esm/salla-loyalty-points-history.entry.js +1 -1
  202. package/dist/esm/salla-loyalty-prize-item.entry.js +1 -1
  203. package/dist/esm/salla-loyalty.entry.js +1 -1
  204. package/dist/esm/salla-maintenance-alert.entry.js +1 -1
  205. package/dist/esm/salla-map_3.entry.js +1 -1
  206. package/dist/esm/salla-menu.entry.js +1 -1
  207. package/dist/esm/salla-metadata.entry.js +1 -1
  208. package/dist/esm/salla-multiple-bundle-product-cart_2.entry.js +1 -1
  209. package/dist/esm/salla-multiple-bundle-product-options-modal_2.entry.js +1 -1
  210. package/dist/esm/salla-multiple-bundle-product.entry.js +1 -1
  211. package/dist/esm/salla-next-order-coupon.entry.js +1 -1
  212. package/dist/esm/salla-notification-item_2.entry.js +2 -2
  213. package/dist/esm/salla-offer-modal.entry.js +1 -1
  214. package/dist/esm/salla-offer.entry.js +1 -1
  215. package/dist/esm/salla-order-branch.entry.js +1 -1
  216. package/dist/esm/salla-order-cancel.entry.js +1 -1
  217. package/dist/esm/salla-order-details-multiple-bundle-product.entry.js +1 -1
  218. package/dist/esm/salla-order-details-options.entry.js +1 -1
  219. package/dist/esm/salla-order-details.entry.js +1 -1
  220. package/dist/esm/salla-order-edit-item.entry.js +1 -1
  221. package/dist/esm/salla-order-edit-product-card.entry.js +1 -1
  222. package/dist/esm/salla-order-edit.entry.js +1 -1
  223. package/dist/esm/salla-order-items.entry.js +1 -1
  224. package/dist/esm/salla-order-options-modal.entry.js +1 -1
  225. package/dist/esm/salla-order-payment.entry.js +1 -1
  226. package/dist/esm/salla-order-rewards.entry.js +1 -1
  227. package/dist/esm/salla-order-shipments.entry.js +1 -1
  228. package/dist/esm/salla-order-summary.entry.js +1 -1
  229. package/dist/esm/salla-order-totals-card.entry.js +1 -1
  230. package/dist/esm/salla-orders.entry.js +2 -2
  231. package/dist/esm/salla-payments.entry.js +1 -1
  232. package/dist/esm/salla-placeholder.entry.js +1 -1
  233. package/dist/esm/salla-price-range.entry.js +1 -1
  234. package/dist/esm/salla-product-card-embed.entry.js +1 -1
  235. package/dist/esm/salla-product-card.entry.js +1 -1
  236. package/dist/esm/salla-product-size-guide.entry.js +1 -1
  237. package/dist/esm/salla-products-list.entry.js +13 -5
  238. package/dist/esm/salla-products-slider.entry.js +2 -2
  239. package/dist/esm/salla-quick-order.entry.js +1 -1
  240. package/dist/esm/salla-rating-modal-v2.entry.js +7 -4
  241. package/dist/esm/salla-rating-modal.entry.js +2 -2
  242. package/dist/esm/salla-review-factors-tags.entry.js +1 -1
  243. package/dist/esm/salla-review-order-item.entry.js +1 -1
  244. package/dist/esm/salla-scopes.entry.js +1 -1
  245. package/dist/esm/salla-search-product-card.entry.js +1 -1
  246. package/dist/esm/salla-search.entry.js +2 -2
  247. package/dist/esm/salla-skeleton.entry.js +1 -1
  248. package/dist/esm/salla-social-share.entry.js +1 -1
  249. package/dist/esm/salla-social.entry.js +1 -1
  250. package/dist/esm/salla-tab-content_3.entry.js +1 -1
  251. package/dist/esm/salla-thank-you-header.entry.js +1 -1
  252. package/dist/esm/salla-thank-you-page.entry.js +1 -1
  253. package/dist/esm/salla-tiered-offer.entry.js +1 -1
  254. package/dist/esm/salla-trust-badges.entry.js +1 -1
  255. package/dist/esm/salla-user-menu.entry.js +1 -1
  256. package/dist/esm/salla-user-profile.entry.js +1 -1
  257. package/dist/esm/salla-user-settings.entry.js +1 -1
  258. package/dist/esm/salla-verify.entry.js +1 -1
  259. package/dist/esm/salla-wallet.entry.js +1 -1
  260. package/dist/esm/salla-wishlist-actions.entry.js +1 -1
  261. package/dist/esm/salla-wishlist-summary.entry.js +2 -2
  262. package/dist/esm/twilight.js +3 -3
  263. package/dist/esm/{vanilla-picker-BlIXJyvJ.js → vanilla-picker-CAeu4f87.js} +1 -1
  264. package/dist/twilight/{p-84d725d4.entry.js → p-01d5cd61.entry.js} +1 -1
  265. package/dist/twilight/{p-60f4357f.entry.js → p-0213fde4.entry.js} +1 -1
  266. package/dist/twilight/{p-8f0af317.entry.js → p-036fbfc0.entry.js} +1 -1
  267. package/dist/twilight/{p-90d4129f.entry.js → p-0add41ce.entry.js} +1 -1
  268. package/dist/twilight/{p-fed66bcb.entry.js → p-0b0d4942.entry.js} +1 -1
  269. package/dist/twilight/{p-86ca22d5.entry.js → p-17bcbf9b.entry.js} +1 -1
  270. package/dist/twilight/{p-b66df976.entry.js → p-1867f7d4.entry.js} +1 -1
  271. package/dist/twilight/p-194ff38c.entry.js +4 -0
  272. package/dist/twilight/{p-4057b692.entry.js → p-20f9c62f.entry.js} +1 -1
  273. package/dist/twilight/{p-783c6346.entry.js → p-252748d9.entry.js} +1 -1
  274. package/dist/twilight/{p-3d5e862c.entry.js → p-290ce0bc.entry.js} +1 -1
  275. package/dist/twilight/{p-d68625f7.entry.js → p-2b930157.entry.js} +1 -1
  276. package/dist/twilight/{p-184ea04c.entry.js → p-2e4e15c5.entry.js} +1 -1
  277. package/dist/twilight/p-2e6537a3.entry.js +4 -0
  278. package/dist/twilight/{p-2a3e2404.entry.js → p-30d64bd1.entry.js} +1 -1
  279. package/dist/twilight/{p-5d4fadd2.entry.js → p-32495dd2.entry.js} +1 -1
  280. package/dist/twilight/{p-cd7029fc.entry.js → p-32d9da31.entry.js} +1 -1
  281. package/dist/twilight/{p-7e854633.entry.js → p-32f100f8.entry.js} +1 -1
  282. package/dist/twilight/{p-dc3ff1f0.entry.js → p-386b3dcd.entry.js} +1 -1
  283. package/dist/twilight/{p-e8090773.entry.js → p-3a4e86d1.entry.js} +1 -1
  284. package/dist/twilight/{p-a0a57259.entry.js → p-3b766a79.entry.js} +1 -1
  285. package/dist/twilight/{p-a5d2ad5e.entry.js → p-3b7a45ec.entry.js} +1 -1
  286. package/dist/twilight/{p-33ff7967.entry.js → p-3bb0e184.entry.js} +1 -1
  287. package/dist/twilight/{p-8b39a9f7.entry.js → p-3cc6ca6c.entry.js} +1 -1
  288. package/dist/twilight/{p-0a794d6f.entry.js → p-4070f808.entry.js} +1 -1
  289. package/dist/twilight/{p-d2c1457e.entry.js → p-412fb721.entry.js} +1 -1
  290. package/dist/twilight/{p-fce39869.entry.js → p-427c13b6.entry.js} +1 -1
  291. package/dist/twilight/{p-49195cb6.entry.js → p-45e0a5d0.entry.js} +1 -1
  292. package/dist/twilight/{p-cd866be6.entry.js → p-4d615f9f.entry.js} +1 -1
  293. package/dist/twilight/{p-4f794057.entry.js → p-4d7fc363.entry.js} +1 -1
  294. package/dist/twilight/{p-9eb92980.entry.js → p-5009f654.entry.js} +1 -1
  295. package/dist/twilight/{p-f4411a04.entry.js → p-50853b76.entry.js} +1 -1
  296. package/dist/twilight/{p-b9695308.entry.js → p-550ad1a6.entry.js} +1 -1
  297. package/dist/twilight/{p-4839d408.entry.js → p-575014c4.entry.js} +1 -1
  298. package/dist/twilight/{p-f10b887a.entry.js → p-5aee5e44.entry.js} +1 -1
  299. package/dist/twilight/{p-622bfb21.entry.js → p-619c709c.entry.js} +1 -1
  300. package/dist/twilight/{p-74f206cf.entry.js → p-6d572fe0.entry.js} +1 -1
  301. package/dist/twilight/{p-26fec98c.entry.js → p-6f84c662.entry.js} +1 -1
  302. package/dist/twilight/{p-4a1aa85f.entry.js → p-703b9253.entry.js} +1 -1
  303. package/dist/twilight/{p-509ad773.entry.js → p-73dea22d.entry.js} +1 -1
  304. package/dist/twilight/{p-6c7cae8a.entry.js → p-74285af9.entry.js} +1 -1
  305. package/dist/twilight/{p-31260fae.entry.js → p-777d28f6.entry.js} +1 -1
  306. package/dist/twilight/{p-4702959a.entry.js → p-7db6ccfe.entry.js} +1 -1
  307. package/dist/twilight/{p-e89a1905.entry.js → p-7db8d545.entry.js} +1 -1
  308. package/dist/twilight/{p-0c6a024f.entry.js → p-7fa4d0b6.entry.js} +1 -1
  309. package/dist/twilight/{p-2e8f95d0.entry.js → p-825c5b73.entry.js} +1 -1
  310. package/dist/twilight/{p-e5545546.entry.js → p-8262e669.entry.js} +1 -1
  311. package/dist/twilight/{p-bab5d057.entry.js → p-86d55a6b.entry.js} +1 -1
  312. package/dist/twilight/{p-0225f396.entry.js → p-8712f7c7.entry.js} +1 -1
  313. package/dist/twilight/{p-a53e2c74.entry.js → p-8948b58c.entry.js} +1 -1
  314. package/dist/twilight/{p-37b68ef3.entry.js → p-8b8cf457.entry.js} +1 -1
  315. package/dist/twilight/{p-8e8e40bc.entry.js → p-8c2992e7.entry.js} +1 -1
  316. package/dist/twilight/{p-eb160c2e.entry.js → p-8c548259.entry.js} +1 -1
  317. package/dist/twilight/{p-5d775867.entry.js → p-8eb3fd92.entry.js} +1 -1
  318. package/dist/twilight/p-908716fb.entry.js +4 -0
  319. package/dist/twilight/{p-62ba0971.entry.js → p-90a59027.entry.js} +1 -1
  320. package/dist/twilight/{p-ae9c0abe.entry.js → p-9683535f.entry.js} +1 -1
  321. package/dist/twilight/{p-89cff0c8.entry.js → p-982e9124.entry.js} +1 -1
  322. package/dist/twilight/{p-a17784e6.entry.js → p-995b898f.entry.js} +1 -1
  323. package/dist/twilight/{p-3a3d4cb7.entry.js → p-99cb3dba.entry.js} +1 -1
  324. package/dist/twilight/{p-6757344a.entry.js → p-9a0218a6.entry.js} +1 -1
  325. package/dist/twilight/{p-7d337f25.entry.js → p-9cf31ff4.entry.js} +1 -1
  326. package/dist/twilight/{p-d495cce0.entry.js → p-9d1a5007.entry.js} +1 -1
  327. package/dist/twilight/{p-57b93850.entry.js → p-9e429047.entry.js} +1 -1
  328. package/dist/twilight/{p-40083f25.entry.js → p-9e542951.entry.js} +1 -1
  329. package/dist/twilight/{p-Dhq3oJAe.js → p-BcT9tEVW.js} +1 -1
  330. package/dist/twilight/{p-Dza6OBFg.js → p-Bgu5gtOF.js} +1 -1
  331. package/dist/twilight/p-C9zdeQFI.js +5 -0
  332. package/dist/twilight/{p-BbZqYBfp.js → p-CSGj1pY-.js} +1 -1
  333. package/dist/twilight/{p-Nyk6-1lq.js → p-CWWgpQ8Q.js} +1 -1
  334. package/dist/twilight/{p-BwzmoZpm.js → p-Cfz9xit3.js} +1 -1
  335. package/dist/twilight/{p-iCJI7qYe.js → p-CmYSalnM.js} +1 -1
  336. package/dist/twilight/p-CnTwkF6y.js +4 -0
  337. package/dist/twilight/p-Cnh7Qptl.js +4 -0
  338. package/dist/twilight/{p-DVWVl151.js → p-Dav_R_d2.js} +1 -1
  339. package/dist/twilight/{p-B7rn1taO.js → p-JGEddAgs.js} +1 -1
  340. package/dist/twilight/{p-CAc7tX2K.js → p-RflSBQNB.js} +1 -1
  341. package/dist/twilight/{p-De2wEjqS.js → p-Xgbueas7.js} +1 -1
  342. package/dist/twilight/{p-64d49f5d.entry.js → p-a070cce0.entry.js} +1 -1
  343. package/dist/twilight/p-a0bfedad.entry.js +4 -0
  344. package/dist/twilight/{p-bf29daf3.entry.js → p-a22d9931.entry.js} +1 -1
  345. package/dist/twilight/{p-2153c6fd.entry.js → p-a3959219.entry.js} +1 -1
  346. package/dist/twilight/p-a3ca61af.entry.js +4 -0
  347. package/dist/twilight/{p-0e1248c4.entry.js → p-a55b5c44.entry.js} +1 -1
  348. package/dist/twilight/{p-24423a8d.entry.js → p-a5fc8358.entry.js} +1 -1
  349. package/dist/twilight/{p-66f6d722.entry.js → p-aabcd09f.entry.js} +1 -1
  350. package/dist/twilight/{p-4c801f91.entry.js → p-ad00021e.entry.js} +1 -1
  351. package/dist/twilight/{p-fae2a8d0.entry.js → p-ade9a68c.entry.js} +1 -1
  352. package/dist/twilight/{p-83ccad19.entry.js → p-b5e0065a.entry.js} +1 -1
  353. package/dist/twilight/{p-2a8d6e7e.entry.js → p-bbb09d92.entry.js} +1 -1
  354. package/dist/twilight/{p-f034968b.entry.js → p-c2df20f8.entry.js} +1 -1
  355. package/dist/twilight/{p-b38c38fe.entry.js → p-c4274188.entry.js} +1 -1
  356. package/dist/twilight/{p-d63ce284.entry.js → p-c5e2c781.entry.js} +1 -1
  357. package/dist/twilight/{p-07450aed.entry.js → p-c64b2b22.entry.js} +1 -1
  358. package/dist/twilight/{p-14752d03.entry.js → p-c92cc92f.entry.js} +1 -1
  359. package/dist/twilight/{p-d6c5bf2a.entry.js → p-cb54adac.entry.js} +1 -1
  360. package/dist/twilight/{p-7750bace.entry.js → p-ce1e45a3.entry.js} +1 -1
  361. package/dist/twilight/{p-e4d90663.entry.js → p-d0acd7ff.entry.js} +1 -1
  362. package/dist/twilight/{p-f9b9af72.entry.js → p-d0f903ac.entry.js} +1 -1
  363. package/dist/twilight/{p-7df4ee74.entry.js → p-d57b49ff.entry.js} +1 -1
  364. package/dist/twilight/p-db3efb27.entry.js +4 -0
  365. package/dist/twilight/{p-e81c4521.entry.js → p-db73d0bf.entry.js} +1 -1
  366. package/dist/twilight/{p-bfb70998.entry.js → p-e20d5e75.entry.js} +1 -1
  367. package/dist/twilight/{p-1982520c.entry.js → p-e223beca.entry.js} +1 -1
  368. package/dist/twilight/{p-20939237.entry.js → p-e37da59f.entry.js} +1 -1
  369. package/dist/twilight/p-e3991836.entry.js +4 -0
  370. package/dist/twilight/{p-fe413496.entry.js → p-e455709f.entry.js} +1 -1
  371. package/dist/twilight/{p-cc2c52bb.entry.js → p-e921b2d1.entry.js} +1 -1
  372. package/dist/twilight/{p-acd48ae7.entry.js → p-ec356e5a.entry.js} +1 -1
  373. package/dist/twilight/{p-7a985c8c.entry.js → p-eeefc285.entry.js} +1 -1
  374. package/dist/twilight/{p-120b4694.entry.js → p-f3b12754.entry.js} +1 -1
  375. package/dist/twilight/{p-c3c99d9e.entry.js → p-f6279a13.entry.js} +1 -1
  376. package/dist/twilight/{p-b819de23.entry.js → p-f83efc62.entry.js} +1 -1
  377. package/dist/twilight/{p-8b43035f.entry.js → p-fa622715.entry.js} +1 -1
  378. package/dist/twilight/{p-b87ea253.entry.js → p-faf00404.entry.js} +1 -1
  379. package/dist/twilight/twilight.esm.js +1 -1
  380. package/dist/types/components/salla-bullet-delivery/api-service.d.ts +23 -7
  381. package/dist/types/components/salla-bullet-delivery/helpers.d.ts +61 -6
  382. package/dist/types/components/salla-bullet-delivery/icons.d.ts +14 -0
  383. package/dist/types/components/salla-bullet-delivery/interfaces.d.ts +36 -1
  384. package/dist/types/components/salla-bullet-delivery/salla-bullet-delivery.d.ts +82 -3
  385. package/dist/types/components/salla-bullet-delivery/selector-tracker.d.ts +30 -0
  386. package/dist/types/components/salla-free-shipping-banner/salla-free-shipping-banner.d.ts +19 -5
  387. package/dist/types/components/salla-free-shipping-tag/salla-free-shipping-tag.d.ts +6 -1
  388. package/dist/types/components/salla-gifting/salla-gifting.d.ts +1 -0
  389. package/dist/types/components/salla-quick-buy/salla-quick-buy.d.ts +6 -0
  390. package/dist/types/components/salla-rating-modal/salla-rating-modal-v2.d.ts +1 -0
  391. package/dist/types/components.d.ts +11 -25
  392. package/dist/types/shared/free-shipping-timer.d.ts +36 -0
  393. package/package.json +5 -5
  394. package/dist/cjs/free-shipping-DkIKD6ch.js +0 -31
  395. package/dist/cjs/helpers-8bMfm_mm.js +0 -329
  396. package/dist/components/free-shipping.js +0 -29
  397. package/dist/esm/free-shipping-Brg4wsgg.js +0 -29
  398. package/dist/esm/helpers-DqzaeXrL.js +0 -309
  399. package/dist/twilight/p-12a8aed8.entry.js +0 -4
  400. package/dist/twilight/p-4f443e36.entry.js +0 -4
  401. package/dist/twilight/p-5b81a3d9.entry.js +0 -4
  402. package/dist/twilight/p-93f26336.entry.js +0 -4
  403. package/dist/twilight/p-Brg4wsgg.js +0 -4
  404. package/dist/twilight/p-DmGAR42j.js +0 -5
  405. package/dist/twilight/p-DqzaeXrL.js +0 -4
  406. package/dist/twilight/p-c7c868b4.entry.js +0 -4
  407. package/dist/twilight/p-d5a2ba68.entry.js +0 -4
  408. package/dist/twilight/p-f8ff074f.entry.js +0 -4
@@ -0,0 +1,106 @@
1
+ /*!
2
+ * Crafted with ❤ by Salla
3
+ */
4
+ const SESSION_STORAGE_NAME = "sc_selector_session";
5
+ const TRACKING_TIMEOUT_MS = 5000;
6
+ const CLOSE_REASONS = {
7
+ closeButtonClick: "close_button",
8
+ backdropClick: "backdrop",
9
+ };
10
+ export const toCloseReason = (reason) => CLOSE_REASONS[reason ?? ""] ?? "escape";
11
+ const uuid = () => typeof crypto.randomUUID === "function"
12
+ ? crypto.randomUUID()
13
+ : "10000000-1000-4000-8000-100000000000".replace(/[018]/g, (c) => (Number(c) ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (Number(c) / 4)))).toString(16));
14
+ export const allocatedBranchIds = (intent) => {
15
+ const value = intent?.allocation_headers?.["s-scope-allocation-id"] ?? intent?.branch_id;
16
+ const ids = String(value ?? "")
17
+ .split(",")
18
+ .map(Number)
19
+ .filter((id) => Number.isSafeInteger(id) && id > 0);
20
+ return [...new Set(ids)].sort((a, b) => a - b);
21
+ };
22
+ const sameIds = (a, b) => a.length === b.length && a.every((id) => b.includes(id));
23
+ export class SelectorTracker {
24
+ constructor() {
25
+ this.impressionId = null;
26
+ this.visibleAt = 0;
27
+ }
28
+ viewed(context) {
29
+ this.guarded(() => {
30
+ this.impressionId = uuid();
31
+ this.visibleAt = Date.now();
32
+ this.send("Branch Selector Viewed", { ...context });
33
+ });
34
+ }
35
+ dismissed(context, reason, hadAcceptedSelection) {
36
+ this.guarded(() => this.send("Branch Selector Dismissed", {
37
+ ...context,
38
+ close_reason: reason,
39
+ had_accepted_selection: hadAcceptedSelection,
40
+ elapsed_ms: this.visibleAt ? Date.now() - this.visibleAt : 0,
41
+ }));
42
+ }
43
+ result(context, result) {
44
+ this.guarded(() => {
45
+ const session = this.session();
46
+ const seq = session.seq + 1;
47
+ const accepted = result.outcome === "accepted";
48
+ const firstAccepted = session.first_accepted_branch_ids ?? (accepted ? result.new_branch_ids : null);
49
+ // A draft or a failed attempt replaces the stored intent, so the last accepted branches live here.
50
+ const previous = session.last_accepted_branch_ids ?? result.previous_branch_ids;
51
+ this.save({
52
+ ...session,
53
+ seq,
54
+ first_accepted_branch_ids: firstAccepted,
55
+ last_accepted_branch_ids: accepted ? result.new_branch_ids : previous,
56
+ });
57
+ this.send("Branch Selector Completed", {
58
+ ...context,
59
+ ...result,
60
+ previous_branch_ids: previous,
61
+ selection_attempt_id: uuid(),
62
+ selection_seq: seq,
63
+ first_accepted_branch_ids: firstAccepted,
64
+ changed: accepted && previous.length > 0 && !sameIds(previous, result.new_branch_ids),
65
+ });
66
+ });
67
+ }
68
+ guarded(track) {
69
+ try {
70
+ track();
71
+ }
72
+ catch {
73
+ // Tracking must never break the selector.
74
+ }
75
+ }
76
+ send(event, properties) {
77
+ const body = {
78
+ event,
79
+ session_id: this.session().id,
80
+ impression_id: this.impressionId,
81
+ ...properties,
82
+ };
83
+ // Use the configured transport without the SDK's shared notification suppression.
84
+ // Tracking failures stay silent while concurrent customer requests keep their alerts.
85
+ // keepalive lets the request outlive the reload that follows a confirmed selection.
86
+ Promise.resolve(salla.api.axios.post("selector-events", body, {
87
+ timeout: TRACKING_TIMEOUT_MS,
88
+ adapter: ["fetch", "xhr"],
89
+ fetchOptions: { keepalive: true },
90
+ })).catch(() => undefined);
91
+ }
92
+ session() {
93
+ const stored = Salla.storage.session.get(this.storageName());
94
+ if (stored?.id)
95
+ return stored;
96
+ const fresh = { id: uuid(), seq: 0, first_accepted_branch_ids: null };
97
+ this.save(fresh);
98
+ return fresh;
99
+ }
100
+ storageName() {
101
+ return `${SESSION_STORAGE_NAME}:${Salla.config.get("store.id")}`;
102
+ }
103
+ save(session) {
104
+ Salla.storage.session.set(this.storageName(), session);
105
+ }
106
+ }
@@ -93,7 +93,7 @@
93
93
  overflow: hidden;
94
94
  text-overflow: ellipsis;
95
95
  }
96
- .s-free-shipping-banner__chip {
96
+ .s-free-shipping-banner__timer {
97
97
  position: relative;
98
98
  overflow: hidden;
99
99
  flex: none;
@@ -108,11 +108,11 @@
108
108
  white-space: nowrap;
109
109
  background: var(--s-fsb-tint-2);
110
110
  }
111
- .s-free-shipping-banner__chip svg {
111
+ .s-free-shipping-banner__timer svg {
112
112
  inline-size: 15px;
113
113
  block-size: 15px;
114
114
  }
115
- .s-free-shipping-banner__chip::after {
115
+ .s-free-shipping-banner__timer::after {
116
116
  content: "";
117
117
  position: absolute;
118
118
  top: 0;
@@ -124,6 +124,17 @@
124
124
  animation: s-fsb-shine 5s ease-in-out infinite;
125
125
  pointer-events: none;
126
126
  }
127
+ .s-free-shipping-banner__clock {
128
+ font-size: 13.5px;
129
+ font-variant-numeric: tabular-nums;
130
+ font-feature-settings: "tnum";
131
+ direction: ltr;
132
+ unicode-bidi: isolate;
133
+ }
134
+ .s-free-shipping-banner.has-paper .s-free-shipping-banner__timer {
135
+ background: var(--s-fsb-ink);
136
+ color: var(--s-fsb-paper);
137
+ }
127
138
  @media (prefers-reduced-motion: reduce) {
128
139
  .s-free-shipping-banner *, .s-free-shipping-banner *::after {
129
140
  animation: none !important;
@@ -136,7 +147,10 @@
136
147
  -webkit-line-clamp: 2;
137
148
  -webkit-box-orient: vertical;
138
149
  }
139
- .s-free-shipping-banner__chip {
150
+ .s-free-shipping-banner__label {
151
+ display: none;
152
+ }
153
+ .s-free-shipping-banner__timer {
140
154
  padding-inline: 9px;
141
155
  }
142
156
  }
@@ -3,6 +3,7 @@
3
3
  */
4
4
  import { Host, h } from "@stencil/core";
5
5
  import { isEligibleForFreeShipping } from "../../shared/free-shipping";
6
+ import { getFreeShippingTimerState, isTimerEnabled, startTimerIfNeeded, subscribeToFreeShippingTimer, } from "../../shared/free-shipping-timer";
6
7
  const LABELS = {
7
8
  title: {
8
9
  ar: 'الشحن علينا!',
@@ -12,22 +13,45 @@ const LABELS = {
12
13
  ar: 'لفترة محدودة! تسوّق واستفد من الشحن المجاني',
13
14
  en: 'Shop now and save on delivery for a limited time.',
14
15
  },
15
- limited: {
16
- ar: 'عرض لفترة محدودة',
17
- en: 'Limited-time offer',
16
+ ends_in: {
17
+ ar: 'ينتهي خلال',
18
+ en: 'Ends in',
18
19
  },
19
20
  };
20
- /**
21
- * Non-dismissible banner announcing the store's free shipping offer.
22
- * Where it is rendered (`placement`) decides which banner data is requested, and the
23
- * response decides whether it is shown.
24
- */
21
+ const pad = (n) => (n < 10 ? '0' : '') + n;
22
+ function formatClock(ms) {
23
+ const seconds = Math.max(0, Math.floor(ms / 1000));
24
+ return `${pad(Math.floor(seconds / 3600))}:${pad(Math.floor((seconds % 3600) / 60))}:${pad(seconds % 60)}`;
25
+ }
26
+ function luminance(rgb) {
27
+ const m = /rgba?\((\d+),\s*(\d+),\s*(\d+)/.exec(rgb || '');
28
+ if (!m)
29
+ return null;
30
+ const f = (c) => {
31
+ c /= 255;
32
+ return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
33
+ };
34
+ return 0.2126 * f(+m[1]) + 0.7152 * f(+m[2]) + 0.0722 * f(+m[3]);
35
+ }
36
+ const isTransparent = (bg) => !bg || bg === 'transparent' || /rgba\(\d+,\s*\d+,\s*\d+,\s*0\)/.test(bg);
25
37
  export class SallaFreeShippingBanner {
26
38
  constructor() {
27
39
  /** Where the banner is rendered: the home page or the product page. */
28
40
  this.placement = 'home';
29
41
  this.locale = 'ar';
42
+ /** Whether free shipping applies here (feature on and the eligibility check passed). */
30
43
  this.visible = false;
44
+ this.timer = null;
45
+ this.onColorSchemeChange = () => this.measureInkAndPaper();
46
+ }
47
+ connectedCallback() {
48
+ this.colorScheme = window.matchMedia?.('(prefers-color-scheme: dark)');
49
+ this.colorScheme?.addEventListener?.('change', this.onColorSchemeChange);
50
+ }
51
+ disconnectedCallback() {
52
+ this.unsubscribe?.();
53
+ this.stopTick();
54
+ this.colorScheme?.removeEventListener?.('change', this.onColorSchemeChange);
31
55
  }
32
56
  async componentWillLoad() {
33
57
  try {
@@ -43,21 +67,78 @@ export class SallaFreeShippingBanner {
43
67
  // home: is the store offering free shipping; product page: is this product eligible
44
68
  const productId = this.placement === 'product' ? salla.config.get('page.id') : undefined;
45
69
  this.visible = await isEligibleForFreeShipping(productId);
70
+ if (this.visible) {
71
+ // The visitor sees the banner now: remember when, the first time only.
72
+ startTimerIfNeeded();
73
+ // Only a banner that can show, and has a timer, follows it (to hide at the end and come back after).
74
+ if (isTimerEnabled()) {
75
+ this.unsubscribe = subscribeToFreeShippingTimer(() => this.refreshTimer());
76
+ }
77
+ }
78
+ this.refreshTimer();
46
79
  }
47
80
  catch (e) {
48
81
  salla?.logger?.warn?.('salla-free-shipping-banner: init failed', e);
49
82
  }
50
83
  }
84
+ refreshTimer() {
85
+ this.timer = getFreeShippingTimerState();
86
+ if (this.visible && this.timer?.visible) {
87
+ this.tick = this.tick ?? setInterval(() => this.refreshTimer(), 1000);
88
+ }
89
+ else {
90
+ this.stopTick();
91
+ }
92
+ }
93
+ stopTick() {
94
+ clearInterval(this.tick);
95
+ this.tick = undefined;
96
+ }
97
+ /**
98
+ * The timer chip is drawn from the theme's own colours: solid in the text colour ("ink")
99
+ * with the nearest opaque background behind the banner ("paper") as its text colour.
100
+ */
101
+ measureInkAndPaper() {
102
+ const bar = this.host?.querySelector('.s-free-shipping-banner');
103
+ if (!bar)
104
+ return;
105
+ this.measuredBar = bar;
106
+ const ink = getComputedStyle(bar.parentElement || bar).color;
107
+ let paper = null;
108
+ for (let node = bar.parentElement; node; node = node.parentElement) {
109
+ const bg = getComputedStyle(node).backgroundColor;
110
+ if (!isTransparent(bg)) {
111
+ paper = bg;
112
+ break;
113
+ }
114
+ }
115
+ if (!paper) {
116
+ const l = luminance(ink);
117
+ paper = l != null && l > 0.5 ? '#111418' : '#ffffff';
118
+ }
119
+ bar.style.setProperty('--s-fsb-ink', ink);
120
+ bar.style.setProperty('--s-fsb-paper', paper);
121
+ bar.classList.add('has-paper');
122
+ }
123
+ componentDidRender() {
124
+ // The colours do not change with the countdown: measure once per banner element (it is a new
125
+ // element each time the banner comes back), and again on a colour scheme change.
126
+ const bar = this.host?.querySelector('.s-free-shipping-banner');
127
+ if (bar && bar !== this.measuredBar) {
128
+ this.measureInkAndPaper();
129
+ }
130
+ }
51
131
  /** Store translation wins, the built-in label is the fallback for the current language. */
52
132
  label(name) {
53
133
  const label = LABELS?.[name]?.[this.locale];
54
134
  return salla.lang.getWithDefault?.(`blocks.free_shipping_banner.${name}`, label) || label;
55
135
  }
56
136
  render() {
57
- if (!this.visible) {
137
+ const timer = this.timer;
138
+ if (!this.visible || !timer?.visible) {
58
139
  return null;
59
140
  }
60
- return (h(Host, null, h("div", { class: "container" }, h("section", { class: "s-free-shipping-banner", "aria-label": this.label('title') }, h("div", { class: "s-free-shipping-banner__inner" }, h("svg", { class: "s-free-shipping-banner__icon", viewBox: "0 0 48 32", "aria-hidden": "true" }, h("g", { class: "s-fsb-speed" }, h("path", { class: "s-fsb-line", d: "M3 11h7" }), h("path", { class: "s-fsb-line", d: "M1 16h5" }), h("path", { class: "s-fsb-line", d: "M4 21h6" })), h("g", { class: "s-fsb-body" }, h("rect", { class: "s-fsb-fill", x: "12", y: "5", width: "21", height: "16", rx: "2.5" }), h("path", { class: "s-fsb-fill", d: "M33 10h6.5a2 2 0 0 1 1.6.8l4.1 5.5c.5.7.8 1.5.8 2.4V21H33z" }), h("rect", { class: "s-fsb-fill", x: "12", y: "20", width: "34", height: "3.5", rx: "1.2" }), h("rect", { class: "s-fsb-window", x: "35", y: "12", width: "5.5", height: "4", rx: "1" })), h("circle", { class: "s-fsb-wheel", cx: "19.5", cy: "25.5", r: "3" }), h("circle", { class: "s-fsb-wheel", cx: "38", cy: "25.5", r: "3" })), h("p", { class: "s-free-shipping-banner__text" }, h("strong", null, this.label('title')), h("span", { class: "s-free-shipping-banner__desc" }, this.label('description'))), h("span", { class: "s-free-shipping-banner__chip" }, h("svg", { viewBox: "0 0 24 24", "aria-hidden": "true" }, h("circle", { cx: "12", cy: "13.5", r: "7" }), h("path", { d: "M10 2.5h4M12 2.5v4M12 13.5V9.5M18 7.5l1.5-1.5" })), h("span", null, this.label('limited'))))))));
141
+ return (h(Host, null, h("div", { class: "container" }, h("section", { class: "s-free-shipping-banner", "aria-label": this.label('title') }, h("div", { class: "s-free-shipping-banner__inner" }, h("svg", { class: "s-free-shipping-banner__icon", viewBox: "0 0 48 32", "aria-hidden": "true" }, h("g", { class: "s-fsb-speed" }, h("path", { class: "s-fsb-line", d: "M3 11h7" }), h("path", { class: "s-fsb-line", d: "M1 16h5" }), h("path", { class: "s-fsb-line", d: "M4 21h6" })), h("g", { class: "s-fsb-body" }, h("rect", { class: "s-fsb-fill", x: "12", y: "5", width: "21", height: "16", rx: "2.5" }), h("path", { class: "s-fsb-fill", d: "M33 10h6.5a2 2 0 0 1 1.6.8l4.1 5.5c.5.7.8 1.5.8 2.4V21H33z" }), h("rect", { class: "s-fsb-fill", x: "12", y: "20", width: "34", height: "3.5", rx: "1.2" }), h("rect", { class: "s-fsb-window", x: "35", y: "12", width: "5.5", height: "4", rx: "1" })), h("circle", { class: "s-fsb-wheel", cx: "19.5", cy: "25.5", r: "3" }), h("circle", { class: "s-fsb-wheel", cx: "38", cy: "25.5", r: "3" })), h("p", { class: "s-free-shipping-banner__text" }, h("strong", null, this.label('title')), h("span", { class: "s-free-shipping-banner__desc" }, this.label('description'))), h("span", { class: "s-free-shipping-banner__timer" }, h("svg", { viewBox: "0 0 24 24", "aria-hidden": "true" }, h("circle", { cx: "12", cy: "12", r: "8" }), h("path", { d: "M12 8v4l3 2" })), h("span", { class: "s-free-shipping-banner__label" }, this.label('ends_in')), h("span", { class: "s-free-shipping-banner__clock", role: "timer" }, formatClock(timer.remainingMs))))))));
61
142
  }
62
143
  static get is() { return "salla-free-shipping-banner"; }
63
144
  static get originalStyleUrls() {
@@ -103,7 +184,9 @@ export class SallaFreeShippingBanner {
103
184
  static get states() {
104
185
  return {
105
186
  "locale": {},
106
- "visible": {}
187
+ "visible": {},
188
+ "timer": {}
107
189
  };
108
190
  }
191
+ static get elementRef() { return "host"; }
109
192
  }
@@ -25,3 +25,9 @@
25
25
  stroke-linecap: round;
26
26
  stroke-linejoin: round;
27
27
  }
28
+ .visible {
29
+ visibility: visible;
30
+ }
31
+ .hidden {
32
+ display: none;
33
+ }
@@ -3,9 +3,11 @@
3
3
  */
4
4
  import { Host, h } from "@stencil/core";
5
5
  import { isEligibleForFreeShipping } from "../../shared/free-shipping";
6
+ import { getFreeShippingTimerState, isTimerEnabled, subscribeToFreeShippingTimer } from "../../shared/free-shipping-timer";
6
7
  /**
7
8
  * Small "free shipping" tag for a product. Meant to be placed below the price in any
8
- * product card.
9
+ * product card. It follows the free shipping banner: while the banner's countdown is over and the
10
+ * banner is hidden, the tag is hidden too.
9
11
  */
10
12
  export class SallaFreeShippingTag {
11
13
  constructor() {
@@ -14,13 +16,26 @@ export class SallaFreeShippingTag {
14
16
  /** With `fromProductCard`, whether the tag is shown. */
15
17
  this.showFreeShipping = false;
16
18
  this.isFree = false;
19
+ this.timerHidden = false;
17
20
  this.label = '';
18
21
  }
22
+ disconnectedCallback() {
23
+ this.unsubscribe?.();
24
+ }
25
+ // The banner records when the visitor first saw it. Until then, or with the feature off, nothing hides the tag.
26
+ refreshTimer() {
27
+ this.timerHidden = getFreeShippingTimerState()?.visible === false;
28
+ }
19
29
  async componentWillLoad() {
20
30
  try {
21
31
  await salla.onReady();
22
32
  await salla.lang.onLoaded();
23
33
  const fallback = salla.lang.getLocale?.() === 'en' ? 'Free shipping' : 'شحن مجاني';
34
+ // Only follow the timer when there is one (feature on and timer settings present).
35
+ if (isTimerEnabled()) {
36
+ this.unsubscribe = subscribeToFreeShippingTimer(() => this.refreshTimer());
37
+ }
38
+ this.refreshTimer();
24
39
  this.label =
25
40
  salla.lang.getWithDefault?.('pages.products.free_shipping', fallback) || fallback;
26
41
  if (this.fromProductCard) {
@@ -35,7 +50,7 @@ export class SallaFreeShippingTag {
35
50
  }
36
51
  }
37
52
  render() {
38
- if (!this.isFree) {
53
+ if (!this.isFree || this.timerHidden) {
39
54
  return null;
40
55
  }
41
56
  return (h(Host, null, h("div", { class: "s-free-shipping-tag" }, h("svg", { viewBox: "0 0 24 24", "aria-hidden": "true" }, h("path", { d: "M3 6.5h11v9H3zM14 9.5h3.6l2.9 3.2v2.8H14" }), h("circle", { cx: "7.5", cy: "17", r: "1.8" }), h("circle", { cx: "17", cy: "17", r: "1.8" })), h("span", { class: "s-free-shipping-tag-label" }, this.label))));
@@ -117,6 +132,7 @@ export class SallaFreeShippingTag {
117
132
  static get states() {
118
133
  return {
119
134
  "isFree": {},
135
+ "timerHidden": {},
120
136
  "label": {}
121
137
  };
122
138
  }
@@ -403,6 +403,9 @@
403
403
  .pointer-events-auto {
404
404
  pointer-events: auto;
405
405
  }
406
+ .visible {
407
+ visibility: visible;
408
+ }
406
409
  .static {
407
410
  position: static;
408
411
  }
@@ -930,9 +933,21 @@
930
933
  opacity: 1;
931
934
  }
932
935
  .s-gifting-textarea.shown {
933
- height: 122px;
936
+ height: 142px;
934
937
  opacity: 1;
935
938
  }
939
+ .s-gifting-textarea-counter {
940
+ margin-top: 0.25rem;
941
+ text-align: end;
942
+ font-size: 0.75rem;
943
+ line-height: 1rem;
944
+ --tw-text-opacity: 1;
945
+ color: rgb(107 114 128 / var(--tw-text-opacity, 1));
946
+ }
947
+ .s-gifting-textarea-counter.limit {
948
+ --tw-text-opacity: 1;
949
+ color: rgb(239 68 68 / var(--tw-text-opacity, 1));
950
+ }
936
951
  .s-gifting-calendar.hide {
937
952
  pointer-events: none;
938
953
  visibility: hidden;
@@ -460,7 +460,9 @@ export class SallaGifting {
460
460
  this.showGiftText = customID;
461
461
  if (dataID) {
462
462
  this.selectedGiftTextOption = dataID;
463
- customID ? this.selectedText = undefined : this.selectedText = event.target.value;
463
+ // Returning to the custom option keeps whatever is still typed in the box,
464
+ // so the counter and the submitted payload match the visible text.
465
+ customID ? this.selectedText = this.textArea?.value || undefined : this.selectedText = event.target.value;
464
466
  }
465
467
  else {
466
468
  // empty textarea value
@@ -851,7 +853,7 @@ export class SallaGifting {
851
853
  }
852
854
  render() {
853
855
  return [
854
- h("div", { key: '1211d713eaad2cddb4c36111ea67c867eecb3f41' }, h("salla-list-tile", { key: 'b994a3b555a568a0abf8f09acc0af68188363326', class: this.generateClass() }, h("div", { key: '579ee8a105b7fe2f9b9182f49deae77313e61ce5', slot: "title" }, this.vertical ? h("span", { innerHTML: GiftSharing }) : '', h("h3", { key: 'e0d1d5d731e9533398b5234aaff8d38bdd4fb63c' }, !!this.widgetTitle ? this.widgetTitle : this.sectionTitle)), h("div", { key: '358100f7148b29ffda793e81b4b5dd9bfc154025', slot: "subtitle" }, h("div", { key: '605920e1f9236fd09e51623ac1dd645c41929252' }, !!this.widgetSubtitle ? this.widgetSubtitle : this.sectionSubtitle)), h("div", { key: '5bd6e1c009e7a75cd920bdc0ac7f221b2b4ec30e', slot: "action" }, h("salla-button", { key: 'bf9900e5f76ac0492a64fac4a3bfbfadaf055135', color: "primary", fill: "outline", width: "wide", class: "s-gifting-widget-action", onClick: () => this.handleGiftButtonClick() }, h("slot", { key: 'b1f86fe483fea048c07284549dde0e6a0b6ffb48', name: "widget-btn-content" }, h("div", { key: 'acd7d213f553cc0154326dfb3641c8379171c732', class: "s-gifting-widget-action-content" }, h("span", { key: 'd6fbeaf056e8bccf48036f0e0ade47791a009025', innerHTML: GiftSharing }), " \u00A0", h("span", { key: '3647dd0a2797036060ec6d07bc1833caf74ae9df' }, this.sectionBtnText)))))), h("salla-modal", { key: 'bafbb84d6779189eee79d2c7c0ded404a85f09ac', id: this.hostId, isLoading: true, class: "s-gifting-modal", width: "sm", ref: modal => this.modal = modal }, h("div", { key: 'b9dedbfe55475ce2a4add90c2bc2733c719f0e7b', slot: "loading" }, h("div", { key: '1e36230096fb71e8859650de12f199719ad3adc8', class: "s-gifting-skeleton" }, h("div", { key: '17bee6df4d5d9758e952301e5a6bc3ef4d49b303', class: "s-gifting-modal-header" }, h("salla-skeleton", { key: 'b4665fa2bcd5c6bcd4f8bdb1930b69a63cce9e92', type: 'circle', height: '5rem', width: '5rem' }), h("h2", { key: '6a0feb57e5883e998d43eb924f0b84d81741436d', class: "s-gifting-modal-title" }, h("div", { key: 'b04fa98fc15c72f92f05d691456166670a0595ac', class: "s-gifting-modal-badge-wrapper" }, h("salla-skeleton", { key: '9c01e90f6877f498d9f89e584bcffb6802c81eab', height: '15px', width: '150px' })))), h("div", { key: '37a2bb5685b861f57ac6fd01d761cc13f10c1577', class: "s-gifting-skeleton-content" }, h("salla-skeleton", { key: '567484e0efed52dbb336ac4b14d1ff5971a331d4', height: '10px', width: '150px' }), h("salla-skeleton", { key: 'f5dbad3a9e32a1ee72259d9a459585836f1f6c98', height: '230px' }), h("salla-skeleton", { key: 'fc042b78c2ce49fcbe6a86f14b025504018c4236', height: '10px', width: '150px' }), h("salla-skeleton", { key: 'e7c707cb720e1e98cca9aa9d9de8e80b2a4b9b15', height: '30px' }), h("salla-skeleton", { key: '5b333361fc20890d1584135111dc2fdbb68c411f', height: '40px' })))), h("slot", { key: '27025859ab5e5b1f1e59c0c48a54edebd8e20da4', name: "header" }), !!this.hasError ?
856
+ h("div", { key: '3c86d3d5d9e610d9e6b802dce4355289c90329b0' }, h("salla-list-tile", { key: '5476098174aa8cb222c3240c8b07b3cbe757484e', class: this.generateClass() }, h("div", { key: '3759c2830dd8353c9a2294e936ae7b69d823ee36', slot: "title" }, this.vertical ? h("span", { innerHTML: GiftSharing }) : '', h("h3", { key: '603c25804e96cc80bbe2b8c802ae764947466ad2' }, !!this.widgetTitle ? this.widgetTitle : this.sectionTitle)), h("div", { key: '605f42d920a49ca2e761b99d6539cd404e89f498', slot: "subtitle" }, h("div", { key: 'd06dd23bf140007156dc2653653c809fd5c11feb' }, !!this.widgetSubtitle ? this.widgetSubtitle : this.sectionSubtitle)), h("div", { key: 'a344e34b453f1ff0289fc57ad08935434d774b4f', slot: "action" }, h("salla-button", { key: '2e6af7eabf350b60513edb9252fd110f0eccb4b7', color: "primary", fill: "outline", width: "wide", class: "s-gifting-widget-action", onClick: () => this.handleGiftButtonClick() }, h("slot", { key: '8bf491757bca99df94abbe2e6dacf54e15155e05', name: "widget-btn-content" }, h("div", { key: '9d45121e40c1f49936f9b2b6eb57a5605eca0e45', class: "s-gifting-widget-action-content" }, h("span", { key: '1a7524843066252c6148f1d57c6c08a255b2d70d', innerHTML: GiftSharing }), " \u00A0", h("span", { key: '5b82d168b21ee5651f28a80776303137af6cf81d' }, this.sectionBtnText)))))), h("salla-modal", { key: '7901154aa0aa9925ca79df482566b69e2c30ad0a', id: this.hostId, isLoading: true, class: "s-gifting-modal", width: "sm", ref: modal => this.modal = modal }, h("div", { key: '4de9f1e21e6bae9eac1a58a419809befeef4aa9b', slot: "loading" }, h("div", { key: '483d223daa491ebb09bcf6a814ef1f8de7ca2ada', class: "s-gifting-skeleton" }, h("div", { key: '495b5fc2978480dcc52abbba0d3da92b503901b4', class: "s-gifting-modal-header" }, h("salla-skeleton", { key: '993e9d6d0a9f7df11746b925296308576ea22cd2', type: 'circle', height: '5rem', width: '5rem' }), h("h2", { key: '08d6a35d3084a32c71437e4a00e789b154645f87', class: "s-gifting-modal-title" }, h("div", { key: '02a659c96a2039e4c7b28857348d2d5c246d4a40', class: "s-gifting-modal-badge-wrapper" }, h("salla-skeleton", { key: '3e1fb71d0cf7ed41f8dccd7dda035ed6c3463cbc', height: '15px', width: '150px' })))), h("div", { key: 'dd6a845ceff281683981b5685663b24c586abeb1', class: "s-gifting-skeleton-content" }, h("salla-skeleton", { key: 'f46a265bdb7e84e35ee7f78d8b039a29549ef235', height: '10px', width: '150px' }), h("salla-skeleton", { key: '6522ab7db38190320322d9cb7487d0873a03585a', height: '230px' }), h("salla-skeleton", { key: 'a17ae0ee2c71fa81ff346be989eb1db14d21c989', height: '10px', width: '150px' }), h("salla-skeleton", { key: '4f80b722d3b24ed9ee11e88b63e5f831b4eae377', height: '30px' }), h("salla-skeleton", { key: 'e4a9d769197cc6f58f96ce92affdf9dd2b38b8a6', height: '40px' })))), h("slot", { key: '7d76198a32dffd257d97873b0971ea8fa5aa8a0f', name: "header" }), !!this.hasError ?
855
857
  h("salla-placeholder", { alignment: "center" }, h("span", { slot: "title" }, this.errorMessage || salla.lang.get('common.errors.empty_results')), h("span", { slot: "description" }, " "))
856
858
  :
857
859
  [
@@ -863,7 +865,10 @@ export class SallaGifting {
863
865
  this.gift?.gift_images.map((item) => h("a", { class: "s-gifting-clickable s-gifting-image", onClick: () => this.setPreview(item) }, h("img", { src: item.url, alt: `${item.id}` }))) : ''))
864
866
  : "")), this.gift && this.gift.show_texts ?
865
867
  h("div", { class: "anime-item" }, h("div", { class: "s-gifting-modal-uploader-title s-gifting-text-title" }, this.giftText), h("div", { class: "s-form-group s-gifting-selectText", ref: el => this.textSelect = el }, h("select", { id: "gift-text-selection", name: "gift-text-selection", class: "s-form-control s-gifting-select", onChange: e => this.toggleGiftText(e) }, h("option", { "data-id": null, selected: !this.selectedGiftTextOption }, this.selectGiftMessage), this.gift && this.gift.gift_texts ?
866
- this.gift?.gift_texts.map((txt) => h("option", { "data-id": txt.id, value: txt.text, key: txt.id, selected: String(this.selectedGiftTextOption) === String(txt.id) }, txt.text)) : '', this.gift && this.gift.show_custom_text ? h("option", { "data-id": "custom", selected: this.selectedGiftTextOption === 'custom' }, this.giftCustomText) : null)), h("div", { class: this.showGiftText && this.gift && this.gift.show_custom_text ? "s-form-group s-gifting-textarea shown" : "s-form-group s-gifting-textarea hide", ref: (el) => this.customTextArea = el }, h("label", { htmlFor: "gift-custom-text", class: "s-form-label" }, this.giftCustomText), h("div", { class: "mt-1" }, h("textarea", { onInput: (event) => this.handleTextAreaChange(event), rows: 4, ref: (el) => this.textArea = el, name: "gift-custom-text", id: "gift-custom-text", class: "s-form-control" })))) : null, h("div", { class: "anime-item" }, h("salla-button", { color: "primary", width: "wide", onClick: () => this.goToStep2(!!this.gift?.show_texts) }, h("span", null, this.nextStep)))), h("div", { class: "s-gifting-step-two gift-step-2", style: this.skipStep1() ? { opacity: '1', transform: 'translateX(0)', position: 'relative' } : undefined, ref: el => this.step2Elems = el }, h("div", { class: this.step2ItemClass(this.errors?.['sender_name'] ? 's-form-group s-form-has-error' : 's-form-group') }, h("label", { htmlFor: "sender_name", class: "s-form-label" }, this.senderNameLabel), h("input", { type: "text", class: "s-form-control", name: "sender_name", id: "sender_name", value: this.senderName, onInput: (event) => this.handleSenderName(event), placeholder: "" }), this.errors && this.errors['sender_name'] ?
868
+ this.gift?.gift_texts.map((txt) => h("option", { "data-id": txt.id, value: txt.text, key: txt.id, selected: String(this.selectedGiftTextOption) === String(txt.id) }, txt.text)) : '', this.gift && this.gift.show_custom_text ? h("option", { "data-id": "custom", selected: this.selectedGiftTextOption === 'custom' }, this.giftCustomText) : null)), h("div", { class: this.showGiftText && this.gift && this.gift.show_custom_text ? "s-form-group s-gifting-textarea shown" : "s-form-group s-gifting-textarea hide", ref: (el) => this.customTextArea = el }, h("label", { htmlFor: "gift-custom-text", class: "s-form-label" }, this.giftCustomText), h("div", { class: "mt-1" }, h("textarea", { onInput: (event) => this.handleTextAreaChange(event), rows: 4, maxLength: SallaGifting.CUSTOM_TEXT_MAX_LENGTH, ref: (el) => this.textArea = el, name: "gift-custom-text", id: "gift-custom-text", class: "s-form-control" })), h("p", { class: {
869
+ 's-gifting-textarea-counter': true,
870
+ 'limit': (this.selectedText?.length || 0) >= SallaGifting.CUSTOM_TEXT_MAX_LENGTH,
871
+ } }, SallaGifting.CUSTOM_TEXT_MAX_LENGTH, "/", this.selectedText?.length || 0))) : null, h("div", { class: "anime-item" }, h("salla-button", { color: "primary", width: "wide", onClick: () => this.goToStep2(!!this.gift?.show_texts) }, h("span", null, this.nextStep)))), h("div", { class: "s-gifting-step-two gift-step-2", style: this.skipStep1() ? { opacity: '1', transform: 'translateX(0)', position: 'relative' } : undefined, ref: el => this.step2Elems = el }, h("div", { class: this.step2ItemClass(this.errors?.['sender_name'] ? 's-form-group s-form-has-error' : 's-form-group') }, h("label", { htmlFor: "sender_name", class: "s-form-label" }, this.senderNameLabel), h("input", { type: "text", class: "s-form-control", name: "sender_name", id: "sender_name", value: this.senderName, onInput: (event) => this.handleSenderName(event), placeholder: "" }), this.errors && this.errors['sender_name'] ?
867
872
  h("span", { class: "s-gifting-error" }, this.errors['sender_name']) : ''), h("div", { class: this.step2ItemClass(this.errors?.['receiver.name'] ? 's-form-group s-form-has-error' : 's-form-group') }, h("label", { htmlFor: "receiver_name", class: "s-form-label" }, this.receiverNameFieldLabel), h("input", { type: "text", class: "s-form-control", name: "receiver_name", id: "receiver_name", value: "", onInput: (event) => this.handleReceiverName(event), placeholder: "" }), this.errors && this.errors['receiver.name'] ?
868
873
  h("span", { class: "s-gifting-error" }, this.errors['receiver.name']) : ''), h("div", { class: this.step2ItemClass(this.errors?.['receiver.mobile'] ? 's-form-group s-form-has-error' : 's-form-group') }, h("label", { class: "s-form-label" }, this.receiverMobileFieldLabel), h("salla-tel-input", { class: "s-gifting-tel-input", phone: this.receiverMobile, countryCode: this.receiverCountryCode, onPhoneEntered: (e) => this.handlePhoneInputChange(e) }), this.errors && this.errors['receiver.mobile'] ?
869
874
  h("span", { class: "s-gifting-error" }, this.errors['receiver.mobile']) : ''), this.isPhysical() &&
@@ -874,7 +879,7 @@ export class SallaGifting {
874
879
  h("div", { class: this.step2ItemClass(this.errors?.['receiver.city_id'] ? 's-form-group s-form-has-error' : 's-form-group') }, h("label", { class: "s-form-label", htmlFor: `${this.hostId}-city` }, this.receiverCityFieldLabel), h("salla-searchable-dropdown", { placeholder: this.selectCity, items: this.displayedCities, selectedItem: this.selectedCity, loading: this.loadingCities, searching: this.searchingCities, disabled: this.loadingCities || (this.isKSA && !this.selectedRegionId), required: true, inputId: `${this.hostId}-city`, searchQuery: this.citySearchQuery, clientSearch: !this.enableCityAjaxSearch, dropUp: true, keepParentScroll: true, onItemSelected: (e) => this.handleCitySelected(e.detail), onSearchInput: (e) => this.handleCitySearch(e.detail), onDropdownClosed: () => this.handleCityDropdownClosed() }), this.errors && this.errors['receiver.city_id'] ?
875
880
  h("span", { class: "s-gifting-error" }, this.errors['receiver.city_id']) : ''), this.isPhysical() && this.cityNoticeText() &&
876
881
  h("div", { class: this.step2ItemClass('s-gifting-info') }, h("span", { innerHTML: Alert }), h("span", null, this.cityNoticeText())), !this.isPhysical() && h("div", { class: this.step2ItemClass() }, h("label", { class: "s-gifting-schedule s-gifting-clickable", htmlFor: `schedule-${this.hostId}` }, h("input", { type: "checkbox", name: 'schedule', id: `schedule-${this.hostId}`, onChange: () => this.toggleCalendar(), class: "s-checkbox" }), h("span", { class: "s-form-label" }, " ", this.sendLater, " "))), h("div", { class: this.getCalendarClasses(), ref: (el) => this.calendarFormGroup = el }, h("label", { class: "s-form-label" }, this.selectSendDateAndTime), h("salla-datetime-picker", { value: this.deliveryDate, placeholder: this.selectSendDateAndTime, "enable-time": true, "date-format": "Y-m-d h:i K", onPicked: (event) => this.handleDateTimePicker(event) }), h("span", { class: "s-gifting-calendar-hint" }, this.canNotEditOrderAfterSelectDate)), h("div", { class: this.step2ItemClass('s-gifting-step-two-footer') }, !this.skipStep1() && h("a", { href: "#!", innerHTML: LeftArrow, onClick: (e) => this.goToStep1(e) }), h("salla-button", { onClick: () => this.submitForm(), color: "primary", width: 'wide' }, h("span", null, this.sendGift)))))
877
- ], h("slot", { key: 'f927e423d09dfcdc986fe28cebd0185ec9f54660', name: "footer" })))
882
+ ], h("slot", { key: '187d744793464098a2eb9592ec7ad8ec3777918f', name: "footer" })))
878
883
  ];
879
884
  }
880
885
  static get is() { return "salla-gifting"; }
@@ -1166,4 +1171,6 @@ export class SallaGifting {
1166
1171
  }
1167
1172
  }
1168
1173
  SallaGifting.CITY_AJAX_THRESHOLD = 400;
1174
+ // Mirrors the API's `text => max:140` rule on AddItemAsGiftRequest.
1175
+ SallaGifting.CUSTOM_TEXT_MAX_LENGTH = 140;
1169
1176
  SallaGifting.CITY_SEARCH_DEBOUNCE_MS = 100;
@@ -343,9 +343,14 @@ export class SallaLoginModal {
343
343
  });
344
344
  }
345
345
  async handleGuestCheckout() {
346
+ // buy now resumes its own flow; emitted before closing so the dismissal doesn't race it
347
+ if (this.source === 'buy-now') {
348
+ Salla.event.emit('salla-login::guest-chosen', { source: this.source });
349
+ return this.modal.close();
350
+ }
346
351
  this.modal.close();
347
352
  if (salla.config.isGuest()) {
348
- return salla.cart.submit(false, true);
353
+ return salla.cart.submit(false, true, true);
349
354
  }
350
355
  }
351
356
  openModal() {
@@ -131,7 +131,7 @@ export class SallaProductsList {
131
131
  * @param filters
132
132
  */
133
133
  async setFilters(filters) {
134
- if (!filters || JSON.stringify(filters) === JSON.stringify(this.parsedFilters)) {
134
+ if (this.filtersResults !== true || !filters || JSON.stringify(filters) === JSON.stringify(this.parsedFilters)) {
135
135
  return;
136
136
  }
137
137
  window.scrollTo({ top: 0, behavior: 'smooth' });
@@ -1042,8 +1042,9 @@ export class SallaProductsList {
1042
1042
  // A theme's catalog default must not replace the relevance order used by the search popup.
1043
1043
  // A shopper's explicit sort, and subsequent sortBy updates followed by reload(), still apply.
1044
1044
  this.sortBy = this.isSearchPageList() ? requestedSort || undefined : this.sortBy || requestedSort;
1045
- this.parsedFilters = Helper.extractFiltersFromUrl(searchParams);
1046
- if (this.parsedFilters && this.parsedFilters.category_id) {
1045
+ // Page filters belong to the main listing, not independently configured sections.
1046
+ this.parsedFilters = this.filtersResults === true ? Helper.extractFiltersFromUrl(searchParams) : {};
1047
+ if (this.filtersResults === true && this.parsedFilters?.category_id) {
1047
1048
  this.currentCategoryIdFilter = this.toCategoryIdFilter(this.parsedFilters.category_id);
1048
1049
  }
1049
1050
  }
@@ -1180,6 +1181,13 @@ export class SallaProductsList {
1180
1181
  ?.find(filter => filter.key === 'category_id')
1181
1182
  // loose == : catId may be a number (auto-appended page.id) while API keys are strings
1182
1183
  ?.values?.find(cat => cat.key == catId)?.value ?? '';
1184
+ // without the filters feature the response has no `filters`, so the lookup above finds no name and the
1185
+ // theme would swap the page heading for a bare count; the page itself still names its own list.
1186
+ // page.title is raw text that themes drop into innerHTML, so it's escaped like the search term
1187
+ const pageId = salla.config.get('page.id');
1188
+ if (!title && catId != null && pageId != null && String(catId) === String(pageId)) {
1189
+ title = Helper.escapeHtml(salla.config.get('page.title'));
1190
+ }
1183
1191
  }
1184
1192
  title +=
1185
1193
  (title ? ' - ' : '') +
@@ -47,6 +47,9 @@ export class SallaQuickBuy {
47
47
  /** Session from the initial gesture; begun later when there are no order options. */
48
48
  this.pendingApplePaySession = null;
49
49
  this.quickBuy = salla.lang.get('pages.products.buy_now');
50
+ /** The guest picked "continue as guest" on the login step, so don't ask again. */
51
+ this.choseGuest = false;
52
+ this.cancelLoginAsk = null;
50
53
  /** Apple Pay onStartedSession: first call defers begin() to run the OO check; second (resolved) begins. */
51
54
  this.handleApplePaySessionStarted = (session) => {
52
55
  // Previously gated on `order_options.mandatory`, which is unrelated to CP-2836: a store with
@@ -114,6 +117,7 @@ export class SallaQuickBuy {
114
117
  salla?.event?.off?.('product-options::donation-changed', this.donationChangedListener);
115
118
  salla?.product?.event?.offPriceUpdated?.(this.priceUpdatedListener);
116
119
  this.langUnsubscribe?.();
120
+ this.cancelLoginAsk?.();
117
121
  }
118
122
  quickBuyHandler() {
119
123
  if (salla.config.isGuest() && !this.isGuestCheckout()) {
@@ -121,6 +125,10 @@ export class SallaQuickBuy {
121
125
  salla.api.auth.requireLoginThen('salla-quick-buy::user.logged-in', () => this.quickBuyHandler());
122
126
  return;
123
127
  }
128
+ if (this.shouldAskLoginFirst()) {
129
+ this.askLoginFirst();
130
+ return;
131
+ }
124
132
  // Sync validate — AP needs the gesture preserved for new ApplePaySession().
125
133
  if (!this.validatePdpOptionsSync())
126
134
  return;
@@ -188,7 +196,10 @@ export class SallaQuickBuy {
188
196
  injectFreeProductsIntoPayload(data, this.collectedFreeProducts);
189
197
  // if the store doesn't have Apple Pay , just create a cart and then redirect to check out page
190
198
  if (!this.isApplePayActive) {
191
- return salla.api.request('checkout/mini', data, 'post')
199
+ // tells checkout the guest already chose guest, so it opens on the guest form —
200
+ // re-check isGuest(): a login since the choice must not send guest params authenticated
201
+ const options = this.choseGuest && salla.config.isGuest() ? { params: { guest_checkout: 1, chose_guest: 1 } } : {};
202
+ return salla.api.request('checkout/mini', data, 'post', options)
192
203
  .catch(err => this.legacyQuickPurchaseFallback(err, data))
193
204
  .then(resp => {
194
205
  // mini-checkout answers {to, url}; legacy quick-purchase answered {redirect}
@@ -313,6 +324,38 @@ export class SallaQuickBuy {
313
324
  salla.logger.warn('quick-buy: falling back to quick-purchase because of token_not_provided');
314
325
  return salla.api.request('checkout/quick-purchase/' + this.productId, data, 'post');
315
326
  }
327
+ /** login-before-checkout variant: offer login or guest before buy now. Not for Apple Pay, which must open on the tap. */
328
+ shouldAskLoginFirst() {
329
+ return salla.config.isGuest()
330
+ && !this.choseGuest
331
+ && !this.isApplePayActive
332
+ && salla.cart.loginBeforeCheckoutGroup?.() === 'variant';
333
+ }
334
+ askLoginFirst() {
335
+ // a second click before the popup settles must replace the pending ask, not stack a listener
336
+ this.cancelLoginAsk?.();
337
+ const stop = () => {
338
+ salla.event.off('salla-login::guest-chosen', onGuest);
339
+ salla.event.off('salla-login::dismissed', stop);
340
+ this.cancelLoginAsk = null;
341
+ };
342
+ this.cancelLoginAsk = stop;
343
+ const onGuest = (detail) => {
344
+ if (detail?.source !== 'buy-now')
345
+ return;
346
+ stop();
347
+ this.choseGuest = true;
348
+ this.quickBuyHandler();
349
+ };
350
+ salla.event.on('salla-login::guest-chosen', onGuest);
351
+ salla.event.on('salla-login::dismissed', stop);
352
+ this.requireLogin.emit({ productId: this.productId });
353
+ salla.api.auth.requireLoginThen('salla-quick-buy::user.logged-in', () => {
354
+ stop();
355
+ this.choseGuest = false;
356
+ this.quickBuyHandler();
357
+ }, null, 'buy-now');
358
+ }
316
359
  isGuestCheckout() {
317
360
  return salla.config.isGuest() && this.isGuestCheckoutAllowed() && this.isPhysicalProduct();
318
361
  }