@salla.sa/twilight-components 2.14.590 → 2.14.591

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 (341) hide show
  1. package/dist/cjs/{filepond-Dt4Nihdd.js → filepond-DkObEO32.js} +1 -1
  2. package/dist/cjs/{filepond-plugin-file-poster-DwwSoJTP.js → filepond-plugin-file-poster-wXgeY5cU.js} +1 -1
  3. package/dist/cjs/{filepond-plugin-file-validate-size-DsVYh3H7.js → filepond-plugin-file-validate-size-CWleid1C.js} +1 -1
  4. package/dist/cjs/{filepond-plugin-file-validate-type-D5SqBZyw.js → filepond-plugin-file-validate-type-CJLl2hbe.js} +1 -1
  5. package/dist/cjs/{filepond-plugin-image-edit-CTTRxQHm.js → filepond-plugin-image-edit-Bp6AxXM9.js} +1 -1
  6. package/dist/cjs/{filepond-plugin-image-exif-orientation-CN52oBp4.js → filepond-plugin-image-exif-orientation-abWKSX9-.js} +1 -1
  7. package/dist/cjs/{filepond-plugin-image-preview-DgSWBJVB.js → filepond-plugin-image-preview-DxprNycS.js} +1 -1
  8. package/dist/cjs/{index-CgZ8Pldm.js → index-DBN0LueR.js} +10 -14
  9. package/dist/cjs/{intlTelInput-DBBilzGk.js → intlTelInput-B6H18Td2.js} +1 -1
  10. package/dist/cjs/loader.cjs.js +2 -2
  11. package/dist/cjs/salla-accordion-body_2.cjs.entry.js +1 -1
  12. package/dist/cjs/salla-accordion_6.cjs.entry.js +1 -1
  13. package/dist/cjs/salla-add-product-button_5.cjs.entry.js +1 -1
  14. package/dist/cjs/salla-advertisement.cjs.entry.js +1 -1
  15. package/dist/cjs/salla-alert_2.cjs.entry.js +1 -1
  16. package/dist/cjs/salla-app-install-alert.cjs.entry.js +1 -1
  17. package/dist/cjs/salla-applied-filters.cjs.entry.js +1 -1
  18. package/dist/cjs/salla-apps-icons.cjs.entry.js +1 -1
  19. package/dist/cjs/salla-attachment-view_9.cjs.entry.js +10 -10
  20. package/dist/cjs/salla-badge.cjs.entry.js +1 -1
  21. package/dist/cjs/salla-basket-gap.cjs.entry.js +1 -1
  22. package/dist/cjs/salla-bullet-delivery_3.cjs.entry.js +1 -1
  23. package/dist/cjs/salla-cart-coupons.cjs.entry.js +1 -1
  24. package/dist/cjs/salla-cart-item-offers_2.cjs.entry.js +1 -1
  25. package/dist/cjs/salla-cart-summary-card.cjs.entry.js +1 -1
  26. package/dist/cjs/salla-cashback-banner.cjs.entry.js +1 -1
  27. package/dist/cjs/salla-comment-factors.cjs.entry.js +1 -1
  28. package/dist/cjs/salla-comment-form_9.cjs.entry.js +1 -1
  29. package/dist/cjs/salla-conditional-offer.cjs.entry.js +2664 -106
  30. package/dist/cjs/salla-contacts.cjs.entry.js +1 -1
  31. package/dist/cjs/salla-cookies-bar.cjs.entry.js +1 -1
  32. package/dist/cjs/salla-count-down.cjs.entry.js +1 -1
  33. package/dist/cjs/salla-custom-fields.cjs.entry.js +1 -1
  34. package/dist/cjs/salla-delivery-promise.cjs.entry.js +1 -1
  35. package/dist/cjs/salla-edit-order-button.cjs.entry.js +1 -1
  36. package/dist/cjs/salla-filters-widget.cjs.entry.js +1 -1
  37. package/dist/cjs/salla-filters.cjs.entry.js +1 -1
  38. package/dist/cjs/salla-fulfillment-methods.cjs.entry.js +1 -1
  39. package/dist/cjs/{salla-gift-card-redeem.cjs.entry.js → salla-gift-card-redeem_2.cjs.entry.js} +36 -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_10.cjs.entry.js +1 -1
  48. package/dist/cjs/salla-loyalty-exchange-product-card.cjs.entry.js +1 -1
  49. package/dist/cjs/salla-loyalty-points-banner.cjs.entry.js +1 -1
  50. package/dist/cjs/salla-loyalty-points-history.cjs.entry.js +1 -1
  51. package/dist/cjs/salla-loyalty-prize-item.cjs.entry.js +1 -1
  52. package/dist/cjs/salla-loyalty.cjs.entry.js +1 -1
  53. package/dist/cjs/salla-maintenance-alert.cjs.entry.js +1 -1
  54. package/dist/cjs/salla-map_3.cjs.entry.js +1 -1
  55. package/dist/cjs/salla-menu.cjs.entry.js +1 -1
  56. package/dist/cjs/salla-metadata.cjs.entry.js +1 -1
  57. package/dist/cjs/salla-multiple-bundle-product-cart_2.cjs.entry.js +1 -1
  58. package/dist/cjs/salla-multiple-bundle-product-options-modal_2.cjs.entry.js +1 -1
  59. package/dist/cjs/salla-multiple-bundle-product.cjs.entry.js +1 -1
  60. package/dist/cjs/salla-next-order-coupon.cjs.entry.js +1 -1
  61. package/dist/cjs/salla-notification-item_2.cjs.entry.js +1 -1
  62. package/dist/cjs/salla-offer-modal.cjs.entry.js +1 -1
  63. package/dist/cjs/salla-offer.cjs.entry.js +1 -1
  64. package/dist/cjs/salla-order-branch.cjs.entry.js +1 -1
  65. package/dist/cjs/salla-order-cancel.cjs.entry.js +1 -1
  66. package/dist/cjs/salla-order-details-multiple-bundle-product.cjs.entry.js +1 -1
  67. package/dist/cjs/salla-order-details-options.cjs.entry.js +1 -1
  68. package/dist/cjs/salla-order-details.cjs.entry.js +1 -1
  69. package/dist/cjs/salla-order-edit-item.cjs.entry.js +1 -1
  70. package/dist/cjs/salla-order-edit-product-card.cjs.entry.js +1 -1
  71. package/dist/cjs/salla-order-edit.cjs.entry.js +1 -1
  72. package/dist/cjs/salla-order-options-modal.cjs.entry.js +1 -1
  73. package/dist/cjs/salla-order-shipments.cjs.entry.js +1 -1
  74. package/dist/cjs/salla-order-summary.cjs.entry.js +1 -1
  75. package/dist/cjs/salla-order-totals-card.cjs.entry.js +1 -1
  76. package/dist/cjs/salla-orders.cjs.entry.js +1 -1
  77. package/dist/cjs/salla-payments.cjs.entry.js +1 -1
  78. package/dist/cjs/salla-placeholder.cjs.entry.js +1 -1
  79. package/dist/cjs/salla-price-range.cjs.entry.js +1 -1
  80. package/dist/cjs/salla-product-card-embed.cjs.entry.js +1 -1
  81. package/dist/cjs/salla-product-card.cjs.entry.js +1 -1
  82. package/dist/cjs/salla-product-size-guide.cjs.entry.js +1 -1
  83. package/dist/cjs/salla-products-list.cjs.entry.js +1 -1
  84. package/dist/cjs/salla-products-slider.cjs.entry.js +1 -1
  85. package/dist/cjs/salla-quick-order.cjs.entry.js +1 -1
  86. package/dist/cjs/salla-rating-modal-v2.cjs.entry.js +1 -1
  87. package/dist/cjs/salla-rating-modal.cjs.entry.js +1 -1
  88. package/dist/cjs/salla-review-factors-tags.cjs.entry.js +1 -1
  89. package/dist/cjs/salla-review-order-item.cjs.entry.js +1 -1
  90. package/dist/cjs/salla-scopes.cjs.entry.js +1 -1
  91. package/dist/cjs/salla-search-product-card.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-social-share.cjs.entry.js +1 -1
  95. package/dist/cjs/salla-social.cjs.entry.js +1 -1
  96. package/dist/cjs/salla-tab-content_3.cjs.entry.js +1 -1
  97. package/dist/cjs/salla-tiered-offer.cjs.entry.js +1 -1
  98. package/dist/cjs/salla-trust-badges.cjs.entry.js +1 -1
  99. package/dist/cjs/salla-user-menu.cjs.entry.js +1 -1
  100. package/dist/cjs/salla-user-profile.cjs.entry.js +1 -1
  101. package/dist/cjs/salla-user-settings.cjs.entry.js +1 -1
  102. package/dist/cjs/salla-verify.cjs.entry.js +1 -1
  103. package/dist/cjs/salla-wallet.cjs.entry.js +1 -1
  104. package/dist/cjs/salla-wishlist-actions.cjs.entry.js +1 -1
  105. package/dist/cjs/salla-wishlist-summary.cjs.entry.js +1 -1
  106. package/dist/cjs/twilight.cjs.js +2 -2
  107. package/dist/cjs/{vanilla-picker-DMOjok7F.js → vanilla-picker-Cm71HMBs.js} +1 -1
  108. package/dist/collection/components/salla-conditional-offer/cart-update-window.js +34 -0
  109. package/dist/collection/components/salla-conditional-offer/interfaces.js +1 -0
  110. package/dist/collection/components/salla-conditional-offer/salla-conditional-offer.css +456 -191
  111. package/dist/collection/components/salla-conditional-offer/salla-conditional-offer.js +1790 -106
  112. package/dist/collection/shared/cart-free-gifts.js +448 -0
  113. package/dist/collection/shared/offer-stages.js +453 -0
  114. package/dist/components/index.js +2 -2
  115. package/dist/components/salla-conditional-offer.js +2672 -116
  116. package/dist/docs.json +21 -8
  117. package/dist/esm/{filepond-wzh5HaPr.js → filepond-Cstf5r6K.js} +1 -1
  118. package/dist/esm/{filepond-plugin-file-poster-DInGlcq6.js → filepond-plugin-file-poster-GibBgGHW.js} +1 -1
  119. package/dist/esm/{filepond-plugin-file-validate-size-BaLOl1L7.js → filepond-plugin-file-validate-size-CLc6zco6.js} +1 -1
  120. package/dist/esm/{filepond-plugin-file-validate-type-D_DVE5xS.js → filepond-plugin-file-validate-type-Ca3dc8p0.js} +1 -1
  121. package/dist/esm/{filepond-plugin-image-edit-B9vWgHyi.js → filepond-plugin-image-edit-CNGBLi7d.js} +1 -1
  122. package/dist/esm/{filepond-plugin-image-exif-orientation-lJrZF6xG.js → filepond-plugin-image-exif-orientation-Dmmu9-UQ.js} +1 -1
  123. package/dist/esm/{filepond-plugin-image-preview-Bbk7m1Yt.js → filepond-plugin-image-preview-KX15tx60.js} +1 -1
  124. package/dist/esm/{index-klFskvc_.js → index-UnmOIma5.js} +10 -14
  125. package/dist/esm/{intlTelInput-pS6pc-iA.js → intlTelInput-C-F-rxZ3.js} +1 -1
  126. package/dist/esm/loader.js +3 -3
  127. package/dist/esm/salla-accordion-body_2.entry.js +1 -1
  128. package/dist/esm/salla-accordion_6.entry.js +1 -1
  129. package/dist/esm/salla-add-product-button_5.entry.js +1 -1
  130. package/dist/esm/salla-advertisement.entry.js +1 -1
  131. package/dist/esm/salla-alert_2.entry.js +1 -1
  132. package/dist/esm/salla-app-install-alert.entry.js +1 -1
  133. package/dist/esm/salla-applied-filters.entry.js +1 -1
  134. package/dist/esm/salla-apps-icons.entry.js +1 -1
  135. package/dist/esm/salla-attachment-view_9.entry.js +10 -10
  136. package/dist/esm/salla-badge.entry.js +1 -1
  137. package/dist/esm/salla-basket-gap.entry.js +1 -1
  138. package/dist/esm/salla-bullet-delivery_3.entry.js +1 -1
  139. package/dist/esm/salla-cart-coupons.entry.js +1 -1
  140. package/dist/esm/salla-cart-item-offers_2.entry.js +1 -1
  141. package/dist/esm/salla-cart-summary-card.entry.js +1 -1
  142. package/dist/esm/salla-cashback-banner.entry.js +1 -1
  143. package/dist/esm/salla-comment-factors.entry.js +1 -1
  144. package/dist/esm/salla-comment-form_9.entry.js +1 -1
  145. package/dist/esm/salla-conditional-offer.entry.js +2664 -106
  146. package/dist/esm/salla-contacts.entry.js +1 -1
  147. package/dist/esm/salla-cookies-bar.entry.js +1 -1
  148. package/dist/esm/salla-count-down.entry.js +1 -1
  149. package/dist/esm/salla-custom-fields.entry.js +1 -1
  150. package/dist/esm/salla-delivery-promise.entry.js +1 -1
  151. package/dist/esm/salla-edit-order-button.entry.js +1 -1
  152. package/dist/esm/salla-filters-widget.entry.js +1 -1
  153. package/dist/esm/salla-filters.entry.js +1 -1
  154. package/dist/esm/salla-fulfillment-methods.entry.js +1 -1
  155. package/dist/esm/{salla-gift-card-redeem.entry.js → salla-gift-card-redeem_2.entry.js} +36 -2
  156. package/dist/esm/salla-gifting.entry.js +1 -1
  157. package/dist/esm/salla-hook.entry.js +1 -1
  158. package/dist/esm/salla-infinite-scroll.entry.js +1 -1
  159. package/dist/esm/salla-installment.entry.js +1 -1
  160. package/dist/esm/salla-list-tile.entry.js +1 -1
  161. package/dist/esm/salla-localization-modal.entry.js +1 -1
  162. package/dist/esm/salla-login-modal.entry.js +1 -1
  163. package/dist/esm/salla-loyalty-banner_10.entry.js +1 -1
  164. package/dist/esm/salla-loyalty-exchange-product-card.entry.js +1 -1
  165. package/dist/esm/salla-loyalty-points-banner.entry.js +1 -1
  166. package/dist/esm/salla-loyalty-points-history.entry.js +1 -1
  167. package/dist/esm/salla-loyalty-prize-item.entry.js +1 -1
  168. package/dist/esm/salla-loyalty.entry.js +1 -1
  169. package/dist/esm/salla-maintenance-alert.entry.js +1 -1
  170. package/dist/esm/salla-map_3.entry.js +1 -1
  171. package/dist/esm/salla-menu.entry.js +1 -1
  172. package/dist/esm/salla-metadata.entry.js +1 -1
  173. package/dist/esm/salla-multiple-bundle-product-cart_2.entry.js +1 -1
  174. package/dist/esm/salla-multiple-bundle-product-options-modal_2.entry.js +1 -1
  175. package/dist/esm/salla-multiple-bundle-product.entry.js +1 -1
  176. package/dist/esm/salla-next-order-coupon.entry.js +1 -1
  177. package/dist/esm/salla-notification-item_2.entry.js +1 -1
  178. package/dist/esm/salla-offer-modal.entry.js +1 -1
  179. package/dist/esm/salla-offer.entry.js +1 -1
  180. package/dist/esm/salla-order-branch.entry.js +1 -1
  181. package/dist/esm/salla-order-cancel.entry.js +1 -1
  182. package/dist/esm/salla-order-details-multiple-bundle-product.entry.js +1 -1
  183. package/dist/esm/salla-order-details-options.entry.js +1 -1
  184. package/dist/esm/salla-order-details.entry.js +1 -1
  185. package/dist/esm/salla-order-edit-item.entry.js +1 -1
  186. package/dist/esm/salla-order-edit-product-card.entry.js +1 -1
  187. package/dist/esm/salla-order-edit.entry.js +1 -1
  188. package/dist/esm/salla-order-options-modal.entry.js +1 -1
  189. package/dist/esm/salla-order-shipments.entry.js +1 -1
  190. package/dist/esm/salla-order-summary.entry.js +1 -1
  191. package/dist/esm/salla-order-totals-card.entry.js +1 -1
  192. package/dist/esm/salla-orders.entry.js +1 -1
  193. package/dist/esm/salla-payments.entry.js +1 -1
  194. package/dist/esm/salla-placeholder.entry.js +1 -1
  195. package/dist/esm/salla-price-range.entry.js +1 -1
  196. package/dist/esm/salla-product-card-embed.entry.js +1 -1
  197. package/dist/esm/salla-product-card.entry.js +1 -1
  198. package/dist/esm/salla-product-size-guide.entry.js +1 -1
  199. package/dist/esm/salla-products-list.entry.js +1 -1
  200. package/dist/esm/salla-products-slider.entry.js +1 -1
  201. package/dist/esm/salla-quick-order.entry.js +1 -1
  202. package/dist/esm/salla-rating-modal-v2.entry.js +1 -1
  203. package/dist/esm/salla-rating-modal.entry.js +1 -1
  204. package/dist/esm/salla-review-factors-tags.entry.js +1 -1
  205. package/dist/esm/salla-review-order-item.entry.js +1 -1
  206. package/dist/esm/salla-scopes.entry.js +1 -1
  207. package/dist/esm/salla-search-product-card.entry.js +1 -1
  208. package/dist/esm/salla-search.entry.js +1 -1
  209. package/dist/esm/salla-skeleton.entry.js +1 -1
  210. package/dist/esm/salla-social-share.entry.js +1 -1
  211. package/dist/esm/salla-social.entry.js +1 -1
  212. package/dist/esm/salla-tab-content_3.entry.js +1 -1
  213. package/dist/esm/salla-tiered-offer.entry.js +1 -1
  214. package/dist/esm/salla-trust-badges.entry.js +1 -1
  215. package/dist/esm/salla-user-menu.entry.js +1 -1
  216. package/dist/esm/salla-user-profile.entry.js +1 -1
  217. package/dist/esm/salla-user-settings.entry.js +1 -1
  218. package/dist/esm/salla-verify.entry.js +1 -1
  219. package/dist/esm/salla-wallet.entry.js +1 -1
  220. package/dist/esm/salla-wishlist-actions.entry.js +1 -1
  221. package/dist/esm/salla-wishlist-summary.entry.js +1 -1
  222. package/dist/esm/twilight.js +3 -3
  223. package/dist/esm/{vanilla-picker-BhmFKXIB.js → vanilla-picker-DMAcm04D.js} +1 -1
  224. package/dist/twilight/{p-ddb65e87.entry.js → p-06268aeb.entry.js} +1 -1
  225. package/dist/twilight/{p-6ea4f06c.entry.js → p-0bee12ba.entry.js} +1 -1
  226. package/dist/twilight/{p-6b767b19.entry.js → p-13215fa2.entry.js} +1 -1
  227. package/dist/twilight/{p-53f8972b.entry.js → p-170a29db.entry.js} +1 -1
  228. package/dist/twilight/{p-74ba0473.entry.js → p-1762cfe3.entry.js} +1 -1
  229. package/dist/twilight/{p-7836ad45.entry.js → p-18b786f4.entry.js} +1 -1
  230. package/dist/twilight/{p-1d8c6adc.entry.js → p-1a7bee69.entry.js} +1 -1
  231. package/dist/twilight/{p-21f2167e.entry.js → p-1aaed68f.entry.js} +1 -1
  232. package/dist/twilight/{p-a64f2fff.entry.js → p-1dc68727.entry.js} +1 -1
  233. package/dist/twilight/{p-655c7f90.entry.js → p-2059ac26.entry.js} +1 -1
  234. package/dist/twilight/{p-9897606c.entry.js → p-21358994.entry.js} +1 -1
  235. package/dist/twilight/{p-a0869ee6.entry.js → p-2308e70c.entry.js} +1 -1
  236. package/dist/twilight/{p-d35c3f7d.entry.js → p-27366663.entry.js} +1 -1
  237. package/dist/twilight/{p-da05ae96.entry.js → p-2d983198.entry.js} +1 -1
  238. package/dist/twilight/{p-bd1dbd4b.entry.js → p-2e204cbc.entry.js} +1 -1
  239. package/dist/twilight/{p-09300a8d.entry.js → p-2e971549.entry.js} +1 -1
  240. package/dist/twilight/{p-efeae895.entry.js → p-2f1c8e60.entry.js} +1 -1
  241. package/dist/twilight/{p-23e45bd7.entry.js → p-328e352d.entry.js} +1 -1
  242. package/dist/twilight/{p-f407afee.entry.js → p-35163279.entry.js} +1 -1
  243. package/dist/twilight/{p-3acbfe00.entry.js → p-36ac5a06.entry.js} +1 -1
  244. package/dist/twilight/{p-d4f3905f.entry.js → p-3845541d.entry.js} +1 -1
  245. package/dist/twilight/{p-917ce4f9.entry.js → p-38956156.entry.js} +1 -1
  246. package/dist/twilight/{p-6ea8b4a8.entry.js → p-398e864d.entry.js} +1 -1
  247. package/dist/twilight/{p-48f26c20.entry.js → p-3d535509.entry.js} +1 -1
  248. package/dist/twilight/{p-3ba09a8e.entry.js → p-3d7fdd11.entry.js} +1 -1
  249. package/dist/twilight/p-40a7f8c6.entry.js +4 -0
  250. package/dist/twilight/{p-dd775629.entry.js → p-426ac7ab.entry.js} +1 -1
  251. package/dist/twilight/{p-294f6c8e.entry.js → p-42d6eb6b.entry.js} +1 -1
  252. package/dist/twilight/{p-0746fded.entry.js → p-46ef2b4e.entry.js} +1 -1
  253. package/dist/twilight/{p-0446f8e3.entry.js → p-47e519e4.entry.js} +1 -1
  254. package/dist/twilight/{p-799a0589.entry.js → p-48f9cd45.entry.js} +1 -1
  255. package/dist/twilight/{p-027b5233.entry.js → p-49f2ad4a.entry.js} +1 -1
  256. package/dist/twilight/{p-f757ba41.entry.js → p-4b135194.entry.js} +1 -1
  257. package/dist/twilight/p-4b175320.entry.js +4 -0
  258. package/dist/twilight/{p-a0f2b1b7.entry.js → p-51d7a9f2.entry.js} +1 -1
  259. package/dist/twilight/{p-0b10b315.entry.js → p-52b99743.entry.js} +1 -1
  260. package/dist/twilight/{p-788ffe88.entry.js → p-540992c1.entry.js} +1 -1
  261. package/dist/twilight/{p-9950bd4f.entry.js → p-5c313f74.entry.js} +1 -1
  262. package/dist/twilight/{p-d566b402.entry.js → p-62842639.entry.js} +1 -1
  263. package/dist/twilight/{p-0ccf7bde.entry.js → p-635cf0ae.entry.js} +1 -1
  264. package/dist/twilight/{p-6e45ec66.entry.js → p-6a68c551.entry.js} +1 -1
  265. package/dist/twilight/{p-cb47fc80.entry.js → p-6b277129.entry.js} +1 -1
  266. package/dist/twilight/{p-b98b2cda.entry.js → p-6dcfc119.entry.js} +1 -1
  267. package/dist/twilight/{p-78ff082d.entry.js → p-6e7a12dd.entry.js} +1 -1
  268. package/dist/twilight/{p-a0f0a176.entry.js → p-700cf9fc.entry.js} +1 -1
  269. package/dist/twilight/{p-62b8c2cc.entry.js → p-71372771.entry.js} +1 -1
  270. package/dist/twilight/{p-945eec73.entry.js → p-78d1e145.entry.js} +1 -1
  271. package/dist/twilight/{p-85f185cc.entry.js → p-7f23b98d.entry.js} +1 -1
  272. package/dist/twilight/{p-c273ff37.entry.js → p-7f93ea69.entry.js} +1 -1
  273. package/dist/twilight/{p-6fcf17d4.entry.js → p-81294230.entry.js} +1 -1
  274. package/dist/twilight/{p-e28f4afc.entry.js → p-833fb416.entry.js} +1 -1
  275. package/dist/twilight/{p-3de1d01b.entry.js → p-8e938bfa.entry.js} +1 -1
  276. package/dist/twilight/{p-36f4e851.entry.js → p-8ec3b9f0.entry.js} +1 -1
  277. package/dist/twilight/{p-0de54240.entry.js → p-9b01e5c2.entry.js} +1 -1
  278. package/dist/twilight/{p-0156dfe8.entry.js → p-9c284764.entry.js} +1 -1
  279. package/dist/twilight/{p-8fbf8044.entry.js → p-9d0658a0.entry.js} +1 -1
  280. package/dist/twilight/{p-8c7614fb.entry.js → p-9d680306.entry.js} +1 -1
  281. package/dist/twilight/{p-7foc7ca2.js → p-BOWrmsKT.js} +1 -1
  282. package/dist/twilight/{p-rKbQj-u0.js → p-C3HaKgMG.js} +1 -1
  283. package/dist/twilight/{p-4asjbsmx.js → p-CjeoBv5q.js} +1 -1
  284. package/dist/twilight/{p-PcxCrM8A.js → p-CtQLzZ1X.js} +1 -1
  285. package/dist/twilight/{p-BcMiEHs_.js → p-DVatlmKV.js} +1 -1
  286. package/dist/twilight/{p-ClbVN5Nv.js → p-D_C0F9n5.js} +1 -1
  287. package/dist/twilight/{p-HZVqfCuE.js → p-Dq91sWJh.js} +1 -1
  288. package/dist/twilight/{p-klFskvc_.js → p-UnmOIma5.js} +1 -1
  289. package/dist/twilight/{p-6536466c.entry.js → p-a0e1d5f7.entry.js} +1 -1
  290. package/dist/twilight/{p-089f0d34.entry.js → p-a192abb7.entry.js} +1 -1
  291. package/dist/twilight/{p-0f951af1.entry.js → p-a1d0c650.entry.js} +1 -1
  292. package/dist/twilight/{p-317048c4.entry.js → p-a1d251d4.entry.js} +1 -1
  293. package/dist/twilight/{p-d524d26e.entry.js → p-a32fb61e.entry.js} +1 -1
  294. package/dist/twilight/{p-864959d8.entry.js → p-a5c693c1.entry.js} +1 -1
  295. package/dist/twilight/{p-52d1d467.entry.js → p-acd9c538.entry.js} +1 -1
  296. package/dist/twilight/{p-a7a64c45.entry.js → p-adfc54e4.entry.js} +1 -1
  297. package/dist/twilight/{p-1a875a94.entry.js → p-b5d6ddd7.entry.js} +1 -1
  298. package/dist/twilight/{p-009048d0.entry.js → p-b70cdf88.entry.js} +1 -1
  299. package/dist/twilight/{p-31b7fbdc.entry.js → p-b7399739.entry.js} +1 -1
  300. package/dist/twilight/{p-7ddae4df.entry.js → p-bb4a95d9.entry.js} +1 -1
  301. package/dist/twilight/{p-ce0a4802.entry.js → p-c1eab306.entry.js} +1 -1
  302. package/dist/twilight/{p-45a13d19.entry.js → p-c1eaf8c3.entry.js} +1 -1
  303. package/dist/twilight/{p-0fca7ee0.entry.js → p-ca47204f.entry.js} +1 -1
  304. package/dist/twilight/{p-39325cfc.entry.js → p-caec4a90.entry.js} +1 -1
  305. package/dist/twilight/{p-a97a0636.entry.js → p-ce0c6667.entry.js} +1 -1
  306. package/dist/twilight/{p-a1d43865.entry.js → p-ce7450a9.entry.js} +1 -1
  307. package/dist/twilight/{p-34b91d42.entry.js → p-d11b211f.entry.js} +1 -1
  308. package/dist/twilight/{p-8bc3a449.entry.js → p-d62c6529.entry.js} +1 -1
  309. package/dist/twilight/{p-482fee31.entry.js → p-da14ac3f.entry.js} +1 -1
  310. package/dist/twilight/{p-a4b9f482.entry.js → p-e0ce5d4c.entry.js} +1 -1
  311. package/dist/twilight/{p-56ce31f2.entry.js → p-e1d59b7e.entry.js} +1 -1
  312. package/dist/twilight/{p-7495249f.entry.js → p-e3066c95.entry.js} +1 -1
  313. package/dist/twilight/{p-32ea6fff.entry.js → p-e34ff202.entry.js} +1 -1
  314. package/dist/twilight/{p-c62b3757.entry.js → p-e3c46eea.entry.js} +1 -1
  315. package/dist/twilight/{p-2667efd6.entry.js → p-e6de2f79.entry.js} +1 -1
  316. package/dist/twilight/{p-d266e9ad.entry.js → p-ea07afaa.entry.js} +1 -1
  317. package/dist/twilight/{p-45cc68ce.entry.js → p-efb67446.entry.js} +1 -1
  318. package/dist/twilight/{p-55f765dc.entry.js → p-efb9f953.entry.js} +1 -1
  319. package/dist/twilight/{p-d21e8092.entry.js → p-f08ff103.entry.js} +1 -1
  320. package/dist/twilight/{p-23ccf145.entry.js → p-f5605df6.entry.js} +1 -1
  321. package/dist/twilight/{p-1a1f04ac.entry.js → p-f69a3e84.entry.js} +1 -1
  322. package/dist/twilight/{p-c33ed919.entry.js → p-f7b65338.entry.js} +1 -1
  323. package/dist/twilight/{p-5b65fffc.entry.js → p-f92f10c7.entry.js} +1 -1
  324. package/dist/twilight/{p-f6bae25a.entry.js → p-fa3c4bcf.entry.js} +1 -1
  325. package/dist/twilight/{p-94eddc5c.entry.js → p-fb8395de.entry.js} +1 -1
  326. package/dist/twilight/{p-1988457b.entry.js → p-ff65be76.entry.js} +1 -1
  327. package/dist/twilight/p-iC3SM6Ji.js +9 -0
  328. package/dist/twilight/{p-BHXx247M.js → p-xX3a9YdQ.js} +1 -1
  329. package/dist/twilight/twilight.esm.js +1 -1
  330. package/dist/types/components/salla-conditional-offer/cart-update-window.d.ts +31 -0
  331. package/dist/types/components/salla-conditional-offer/interfaces.d.ts +70 -13
  332. package/dist/types/components/salla-conditional-offer/salla-conditional-offer.d.ts +656 -10
  333. package/dist/types/shared/cart-free-gifts.d.ts +141 -0
  334. package/dist/types/shared/offer-stages.d.ts +288 -0
  335. package/package.json +5 -5
  336. package/dist/cjs/salla-tooltip.cjs.entry.js +0 -42
  337. package/dist/esm/salla-tooltip.entry.js +0 -40
  338. package/dist/twilight/p-0e206ed7.entry.js +0 -4
  339. package/dist/twilight/p-8f5929a9.entry.js +0 -4
  340. package/dist/twilight/p-Ba21M-o3.js +0 -9
  341. package/dist/twilight/p-e47f5ec9.entry.js +0 -4
@@ -0,0 +1,141 @@
1
+ /**
2
+ * Shared free-gift lookup for the cart.
3
+ *
4
+ * The gift feature is twilight-only: no theme passes `added-by-offer` /
5
+ * `free-gift-quantity` attributes. `salla-conditional-offer` resolves the gift LINES it
6
+ * lists (read-only, as information) and the cart line count from here, never from theme
7
+ * attributes.
8
+ *
9
+ * Data source: `salla.api.cart.details()` — it hits the `api.cart.show`
10
+ * route, which IS in `CartPresenter::$routesWithItems`, so the response
11
+ * carries `data.cart.items[]` with the per-item keys `added_by_offer`
12
+ * (bool), `offer_id` (int|null) and `free_gift_quantity` (int) set by
13
+ * `CartItemTransformer.php`. Those three names are a pinned
14
+ * contract — do not rename them here or on the components that consume them.
15
+ *
16
+ * We deliberately never read these fields off a `cart::updated` payload:
17
+ * that event fires from `latest()` too, and `api.cart.latest` is NOT in
18
+ * `$routesWithItems`, so a `cart::updated` payload legitimately carries no
19
+ * `items` at all. Callers must fetch on mount and call
20
+ * `refreshCartFreeGifts()` on the event — this module never derives from
21
+ * event payloads.
22
+ *
23
+ * The banner asks for the gift lines and the cart line count on the same tick (initial
24
+ * mount, and again on every `cart::updated`). Concurrent callers share a
25
+ * single in-flight promise, mirroring `_pendingOffersRequest` in
26
+ * `twilight/packages/twilight/src/api/cart.js:831-846`.
27
+ */
28
+ /**
29
+ * A gift cart LINE, with the few display fields `salla-conditional-offer` needs to
30
+ * render its free-gifts card: a thumbnail, the
31
+ * product name, the price it would have cost, and the cart-item id it is keyed by.
32
+ *
33
+ * `originalPrice` is the price the shopper is NOT paying. Cart items report the price
34
+ * under several near-synonymous keys (`original_price`, `product_price`, `price`) whose
35
+ * shapes differ — `Money` objects serialize as `{amount, currency}`, plain columns as
36
+ * numbers — so it is coerced here rather than at each call site, and is `null` when
37
+ * nothing usable was sent (render nothing, never "0").
38
+ */
39
+ export interface CartFreeGiftItem {
40
+ /** Cart-item id (already a route key / string). */
41
+ id: string;
42
+ offerId: number | null;
43
+ /** Free units granted by the offer, i.e. what the gifts card shows as "free". */
44
+ quantity: number;
45
+ /**
46
+ * The two halves of a MERGED line, kept separate and unfused.
47
+ *
48
+ * `AddToCart.php:543-544` grants a gift by incrementing an EXISTING line when the
49
+ * shopper already owns that product, so one line can be quantity 3 of which
50
+ * `free_gift_quantity` is 1 and the other 2 were PAID for. `quantity` (the free half)
51
+ * is what the gifts card shows; `lineQuantity` is the whole line.
52
+ */
53
+ freeQuantity: number;
54
+ lineQuantity: number;
55
+ name: string;
56
+ imageUrl: string;
57
+ imageAlt: string;
58
+ url: string;
59
+ originalPrice: number | null;
60
+ }
61
+ /**
62
+ * The SDK's own name for "this visitor has no cart at all".
63
+ *
64
+ * `salla.api.cart.details()` resolves its id through
65
+ * `getCurrentCartId(false, …, allowCreate = false)`, which returns `null` for a guest with
66
+ * no stored cart id rather than creating one server-side; `details()` then throws this
67
+ * (twilight/src/api/cart.js:192-199). It is a STATEMENT ABOUT THE CART, not a failure to
68
+ * reach the server — no cart means no items — so it is the one rejection that resolves to
69
+ * a hard 0 instead of "unknown".
70
+ *
71
+ * Matched on `name`, never on message text: the wording is not a contract, the name is.
72
+ */
73
+ export declare const CART_NOT_CREATED = "CartNotCreated";
74
+ export declare function isCartNotCreated(error: any): boolean;
75
+ /**
76
+ * Every free-gift LINE currently in the cart, in cart order.
77
+ *
78
+ * Shares the cache, the in-flight promise and the generation guard with
79
+ * `getCartItemCount()` — the banner asking for both still issues exactly ONE
80
+ * `details()` request per cart mutation.
81
+ */
82
+ export declare function getCartFreeGiftItems(): Promise<CartFreeGiftItem[]>;
83
+ /**
84
+ * Whether the cached cart picture came from a response that was actually reached and
85
+ * parsed, rather than from the fallback a rejected lookup publishes.
86
+ *
87
+ * For the ONE consumer that has to tell "the cart is empty" apart from "the lookup could
88
+ * not say, and guessed empty": `salla-conditional-offer` stops before it even asks for the
89
+ * offer when the count is `0`, which is unrecoverable if that `0` was a guess. Everything
90
+ * else should just read the values — they are already the best available answer.
91
+ *
92
+ * Synchronous and side-effect free: it reports on what is cached NOW, so a caller that
93
+ * wants a fresh answer must still await one of the lookups above.
94
+ */
95
+ export declare function hasAuthoritativeCartData(): boolean;
96
+ /**
97
+ * How many LINES the cart holds — `null` while that is genuinely UNKNOWN (nothing has
98
+ * loaded yet, or the lookup failed), never `0` for either.
99
+ *
100
+ * The distinction is the whole point: `salla-conditional-offer` hides its banner on an
101
+ * empty cart, and a `0` that really meant "still loading" would make the banner flicker
102
+ * or disappear on a populated one. Shares the cache, the in-flight promise and the
103
+ * generation guard with `getCartFreeGiftItems()`, so asking for the count costs no
104
+ * request of its own.
105
+ */
106
+ export declare function getCartItemCount(): Promise<number | null>;
107
+ /**
108
+ * Invalidates the cache and re-fetches — call this from a `cart::updated`
109
+ * handler, ignoring the event payload entirely.
110
+ *
111
+ * Bumps `generation` first so that any request already in flight (started
112
+ * before this invalidation) can no longer publish into `cache` when it
113
+ * settles — mirrors `salla.event.on('cart::updated', () => { Salla.api.cart._pendingOffersRequest = null; })`
114
+ * in `twilight/packages/twilight/src/api/cart.js:81`, which abandons its
115
+ * own in-flight promise on cart update for the same reason.
116
+ *
117
+ * Then chains a fresh fetch BEHIND whatever was already in flight (rather
118
+ * than firing a second request in parallel): once that prior request
119
+ * settles — its result now guaranteed to be discarded by the generation
120
+ * check above — `fetchAndCache()` starts a request under the new
121
+ * generation, which is free to publish.
122
+ *
123
+ * `pendingRefresh` de-dupes concurrent callers of THIS function the same
124
+ * way `pendingRequest` de-dupes concurrent fetches: N components all
125
+ * invalidating within the same synchronous `cart::updated` dispatch share
126
+ * one refresh chain and therefore, ultimately, one fresh HTTP request.
127
+ *
128
+ * That sharing window is deliberately NARROW — it closes the instant the
129
+ * fresh request goes out, NOT when it comes back. Holding it open for the
130
+ * whole round trip silently coalesced two DIFFERENT cart mutations into one
131
+ * refresh: the second `cart::updated` got handed the first one's promise, so
132
+ * it never bumped `generation` and never issued a request, and the response
133
+ * that eventually published had been asked for BEFORE the second mutation
134
+ * happened. The cart then sat on pre-mutation gift data — a merged line
135
+ * showing yesterday's paid quantity beside yesterday's corrected total —
136
+ * until some later mutation happened to come along. A shopper clicking "+"
137
+ * twice inside one round trip is all it took.
138
+ */
139
+ export declare function refreshCartFreeGifts(): Promise<void>;
140
+ /** @internal exported for tests only — resets module-level state between specs. */
141
+ export declare function __resetCartFreeGiftsForTests(): void;
@@ -0,0 +1,288 @@
1
+ /**
2
+ * Multi-stage promotion progress.
3
+ *
4
+ * Pure, component-agnostic helpers for turning a shopper's current cart value
5
+ * plus a list of stage thresholds into "which stage is Locked / Current /
6
+ * Completed, and how full is each segment".
7
+ *
8
+ * Deliberately NOT shared with `salla-tiered-offer`'s `TierUtils`:
9
+ * - `TierUtils.findCurrentTierIndex` is 1-based with `0` overloaded to mean
10
+ * "no tier reached", which cannot express "stage 0 is reached".
11
+ * - It takes `TieredOfferTier[]`, a shape a conditional-offer `Discount` does
12
+ * not share a single field with.
13
+ * - It assumes its caller already sorted; the conditional-offer payload is
14
+ * emitted UNSORTED by the backend.
15
+ *
16
+ * So this module takes plain numbers, is 0-based, uses an explicit
17
+ * `NO_STAGE_REACHED` sentinel, and sorts defensively on every call.
18
+ *
19
+ * ONE deliberate exception to "pure": `getCurrencyDecimals()` reads the store's money
20
+ * precision off `salla.config` so that `getRemainingToStage()` can round AT THE SOURCE
21
+ * and every consumer — including the `products_count` path that never touches
22
+ * `salla.money()` — benefits without each of them remembering to. It is fully guarded and
23
+ * falls back to `DEFAULT_CURRENCY_DECIMALS`, so a missing SDK degrades rather than throws;
24
+ * callers that want it hermetic can pass the measure and stub `salla.config`.
25
+ *
26
+ * ---------------------------------------------------------------------------
27
+ * WHO DECIDES A TIER IS UNLOCKED
28
+ * ---------------------------------------------------------------------------
29
+ * The ENGINE does, and it now says so: every `details.discounts[]` entry carries
30
+ * `is_applied`. Threshold arithmetic here is a PROJECTION ("how far to go"), never a
31
+ * CLAIM about what the engine granted, because the engine's formula
32
+ *
33
+ * ($subtotal - $alreadyAppliedDiscount) - $excludedItemsAmount >= min_spend
34
+ *
35
+ * uses two terms that are not in the payload at all. On beta a gift tier at `min_spend`
36
+ * 300 with `current_value` 300 rendered as unlocked while the engine had refused it (the
37
+ * gift's own price is in that tier's excluded set), so no arithmetic over shipped keys
38
+ * could ever have agreed with it.
39
+ *
40
+ * BUT `is_applied` IS NOT "THE SHOPPER IS PAST THIS TIER". It answers a narrower
41
+ * question, and reading it as the broader one is what produced the second beta report.
42
+ * `CartOfferDiscount::apply()` walks the tiers, keeps the LAST one whose conditions pass
43
+ * and calls `discountItem()` ONCE after the loop, so a cart offer grants EXACTLY ONE
44
+ * reward — the best qualifying tier. Every earlier tier is therefore `is_applied: false`
45
+ * even for a shopper who sailed past it: its reward is SUPERSEDED, not out of reach. A
46
+ * cart at `current_value` 510 came back as `false / false / true` and the badge row read
47
+ * LOCKED / LOCKED / CHECKED, which is unreadable as a progress stepper.
48
+ *
49
+ * So there are TWO questions and this module answers both, separately:
50
+ * - "which tier gave the reward" — the single winner, `appliedIndex`.
51
+ * - "is the shopper past this tier" — cumulative, `met`, which is what the ✓, the
52
+ * strikethrough, the lock and the "N of M" count render from.
53
+ *
54
+ * The passed tiers carry a ✓ AND a strikethrough while the tier ahead carries a lock.
55
+ * Struck-through means superseded, so a ✓ means THRESHOLD PASSED, not REWARD GRANTED.
56
+ *
57
+ * Hence the split, and it is load-bearing:
58
+ * - `met` / `metCount` / `nextUnmetIndex` / `allMet` are the ENGINE-DERIVED verdict.
59
+ * Render from these.
60
+ * - `appliedIndex` names the one tier that actually paid out. Diagnostics only so far.
61
+ * - `lastReachedIndex` / `currentIndex` / `isComplete` / `fills` / `overallPercentage`
62
+ * are pure threshold projections. Use them for distance and bar geometry only.
63
+ *
64
+ * `is_applied` is TRI-STATE, because twilight and the Store package deploy independently:
65
+ * absent means "this backend does not report it yet" and falls back to the arithmetic,
66
+ * while `false` is a real verdict and outranks the arithmetic. See `readAppliedFlag`.
67
+ *
68
+ * `salla-tiered-offer` keeps its own copy of the defensive ascending sort and the
69
+ * completed/total ratio; that duplication is deliberate and not migrated here.
70
+ */
71
+ /** Explicit sentinel: no stage has been reached yet (or there is no next stage). */
72
+ export declare const NO_STAGE_REACHED = -1;
73
+ export declare enum OfferStageState {
74
+ LOCKED = "locked",
75
+ CURRENT = "current",
76
+ COMPLETED = "completed"
77
+ }
78
+ /** The backend sends `end_value` as a string under `s-source: mobile`, so every numeric field is coerced. */
79
+ export type NumericLike = number | string | null | undefined;
80
+ /**
81
+ * The engine's verdict for one tier, as a TRI-STATE.
82
+ *
83
+ * - `true` the engine granted this tier.
84
+ * - `false` the engine did NOT grant it. A REAL answer — never overridden by arithmetic.
85
+ * - `undefined` the backend said nothing (older Store/SpecialOffer-Module deploy). Only
86
+ * this case falls back to `current_value >= min_spend`.
87
+ *
88
+ * Distinguishing the middle case from the last one IS the fix, so anything that is not an
89
+ * unambiguous yes/no is read as `undefined` — a half-understood value must degrade to the
90
+ * old behaviour, not invent a verdict.
91
+ */
92
+ export type AppliedFlag = boolean | undefined;
93
+ export interface OfferStageProgress {
94
+ /** Defensively ascending-sorted, numeric-coerced copy of the thresholds. */
95
+ thresholds: number[];
96
+ /**
97
+ * THE STEPPER, index-aligned with `thresholds`: has the shopper got past this tier?
98
+ *
99
+ * Everything shopper-visible — badge, tooltip row, ✓/lock, strikethrough, "N of M" —
100
+ * renders from HERE, never from `lastReachedIndex` and never from `applied` directly.
101
+ *
102
+ * MONOTONIC BY CONSTRUCTION: `true`s form a prefix, so a lock can never sit below a ✓.
103
+ * That is the fix. Derived as `index <= appliedIndex` once the engine has granted
104
+ * anything, all-`false` when the engine granted nothing, and `value >= threshold` only
105
+ * when this backend reports no verdict at all. See `computeOfferStageProgress`.
106
+ */
107
+ met: boolean[];
108
+ /** The raw tri-state flags, index-aligned with `thresholds`. `undefined` = the backend sent none. */
109
+ applied: AppliedFlag[];
110
+ /**
111
+ * 0-based index of the tier that actually PAID OUT — the highest `is_applied: true` —
112
+ * or `NO_STAGE_REACHED` when the engine granted nothing or reported nothing.
113
+ *
114
+ * A cart offer grants one reward, so this is the winner. `met` is the prefix it closes;
115
+ * do not render a ✓ from this field alone.
116
+ */
117
+ appliedIndex: number;
118
+ /** True when at least one tier carried a real `is_applied`, i.e. this backend reports the verdict. */
119
+ hasEngineVerdict: boolean;
120
+ /** How many tiers are met. `appliedIndex + 1` under a verdict — see `met`. */
121
+ metCount: number;
122
+ /** 0-based index of the FIRST tier that is not met, or `NO_STAGE_REACHED` when all are. */
123
+ nextUnmetIndex: number;
124
+ /**
125
+ * True when every tier is met. The congratulations gate — `isComplete` is not.
126
+ *
127
+ * Under a verdict this means the LAST tier is the winner, which is exactly when the
128
+ * shopper has the offer's best reward in the cart and "you have unlocked this offer" is
129
+ * true. It stays false whenever the engine granted nothing, however affordable the
130
+ * thresholds look.
131
+ */
132
+ allMet: boolean;
133
+ /**
134
+ * 0-based index of the highest stage whose THRESHOLD is reached, or `NO_STAGE_REACHED`.
135
+ * A projection, not a verdict: it drives the bar, not the ✓. See `met`.
136
+ */
137
+ lastReachedIndex: number;
138
+ /**
139
+ * 0-based index of the first stage whose THRESHOLD is unreached, or `NO_STAGE_REACHED`.
140
+ * A projection, not a verdict — for the next TARGET use `nextUnmetIndex`.
141
+ */
142
+ currentIndex: number;
143
+ /** True when the final THRESHOLD has been reached. A projection, not a verdict — see `allMet`. */
144
+ isComplete: boolean;
145
+ /** `currentValue`, clamped to `[0, finalThreshold]` so a stale/overshooting server value can never render out of range. */
146
+ value: number;
147
+ /**
148
+ * The cart's progress AS EACH TIER COUNTS IT, index-aligned with `thresholds` and clamped
149
+ * like `value`.
150
+ *
151
+ * The engine measures every tier by that tier's own rule — it leaves a tier's gift
152
+ * product out of the count toward that tier — so the progress toward tier 2 can be lower
153
+ * than the offer-level figure, and "how far to tier 2" is only right against tier 2's
154
+ * own number. An entry is the tier's `current_value` when the backend sent a readable
155
+ * one and `value` otherwise, so on a backend that sends none every entry IS `value`.
156
+ */
157
+ values: number[];
158
+ /** Baseline the first segment fills from (`details.start_value`). */
159
+ startValue: number;
160
+ /** 0..100 fill of the segment leading INTO each stage, index-aligned with `thresholds`. */
161
+ fills: number[];
162
+ /** 0..100 overall completion across all stages. Exactly 100 when `isComplete`. */
163
+ overallPercentage: number;
164
+ }
165
+ /**
166
+ * Read one tier's `is_applied` as a tri-state.
167
+ *
168
+ * `true`/`false` booleans are what `CartOffersTransformer` casts and emits. The numeric
169
+ * and string spellings are accepted too because the `s-source: mobile` pipeline already
170
+ * stringifies numeric fields in this very payload (`end_value`), and reading a `0` there
171
+ * as "absent" would silently restore the bug this exists to fix.
172
+ *
173
+ * EVERYTHING ELSE — key missing, `undefined`, `null`, `''`, an object — is ABSENT, not
174
+ * `false`: a value we cannot interpret is not the engine saying no, and must degrade to
175
+ * the arithmetic fallback rather than lock a tier the shopper has genuinely earned.
176
+ */
177
+ export declare function readAppliedFlag(value: unknown): AppliedFlag;
178
+ /**
179
+ * Whether a THRESHOLD is usable.
180
+ *
181
+ * Thresholds get the opposite policy to values: an unparseable threshold is DROPPED,
182
+ * never coerced to 0, because a 0 threshold is satisfied by an empty cart and would
183
+ * render as an already-COMPLETED stage — reintroducing exactly the synthetic-zeroth-
184
+ * checkpoint bug this component was rewritten to remove.
185
+ *
186
+ * Callers that keep their own parallel array of stage objects MUST filter it with this
187
+ * predicate so their index alignment with `progress.thresholds` survives the drop.
188
+ */
189
+ export declare function isUsableThreshold(value: NumericLike): boolean;
190
+ /**
191
+ * Stable ascending sort of arbitrary items by a numeric threshold accessor.
192
+ *
193
+ * Ties are broken by `getIdentity` when supplied and readable on BOTH sides — the tier
194
+ * `id` (0 = base tier, 1..N = configured options in the order the engine walks them), so
195
+ * two tiers sharing a `min_spend` order by what they ARE rather than by where they
196
+ * happened to land in an unsorted payload. Without it (or when either id is unreadable)
197
+ * ties keep their original relative order, which is the previous behaviour exactly.
198
+ */
199
+ export declare function sortByThreshold<T>(items: T[], getThreshold: (item: T) => NumericLike, getIdentity?: (item: T) => NumericLike): T[];
200
+ /**
201
+ * Derive the full stage picture from the server's `current_value`.
202
+ *
203
+ * @param currentValue the server-computed cart value — never recomputed client-side.
204
+ * @param rawThresholds each stage's `min_spend`, in any order.
205
+ * @param rawStartValue the baseline the first segment fills from (`details.start_value`).
206
+ * @param rawApplied each stage's `is_applied`, POSITIONALLY ALIGNED WITH `rawThresholds`
207
+ * before any sorting or dropping happens here. Omit it and every tier reads as
208
+ * absent, i.e. the threshold behaviour, unchanged.
209
+ * @param rawTierValues each stage's OWN `current_value`, aligned the same way. A tier
210
+ * without a readable one is measured by `currentValue`, so omitting it — an older
211
+ * backend — changes nothing. See `OfferStageProgress.values`.
212
+ */
213
+ export declare function computeOfferStageProgress(currentValue: NumericLike, rawThresholds: NumericLike[], rawStartValue?: NumericLike, rawApplied?: unknown[], rawTierValues?: NumericLike[]): OfferStageProgress;
214
+ /**
215
+ * Locked / Current / Completed for one 0-based stage index — from `met`, so a tier the
216
+ * engine withheld outright reads LOCKED even with its threshold met, and every tier the
217
+ * shopper has passed on the way to a granted one reads COMPLETED.
218
+ *
219
+ * - Completed: `met[index]` — index at or below the winner.
220
+ * - Current: exactly `nextUnmetIndex`, the first tier ABOVE the winner.
221
+ * - Locked: every other unmet stage, and any out-of-range index.
222
+ */
223
+ export declare function getStageState(index: number, progress: OfferStageProgress): OfferStageState;
224
+ /**
225
+ * How the offer MEASURES its thresholds, which is also what its remainder rounds to.
226
+ *
227
+ * Mirrors `OfferType` in `salla-conditional-offer/interfaces.ts` without importing it —
228
+ * this module stays free of the component's payload types (see the header) — so a caller
229
+ * maps `details.based_on` onto it at the call site.
230
+ */
231
+ export declare enum OfferStageMeasure {
232
+ /** `order_amount` — a money value, rounded to the store's currency precision. */
233
+ CURRENCY = "currency",
234
+ /** `products_count` — whole products, so the remainder is a whole number. */
235
+ COUNT = "count"
236
+ }
237
+ /**
238
+ * The precision to fall back to when the store publishes none.
239
+ *
240
+ * 2 is the platform default (SAR/USD/AED); a store on a 3-decimal currency (KWD, BHD)
241
+ * that reports its precision gets 3, and only a store that reports NOTHING readable
242
+ * lands here.
243
+ */
244
+ export declare const DEFAULT_CURRENCY_DECIMALS = 2;
245
+ /**
246
+ * The store's money precision — THE ONE IMPURITY IN THIS MODULE (see the header note).
247
+ *
248
+ * Asked in the order the platform answers it:
249
+ * 1. `salla.config.currency()` — the ACTIVE currency's own precision, which is the only
250
+ * source that can differ per currency (a store displaying KWD wants 3 while its SAR
251
+ * prices want 2).
252
+ * 2. `salla.config.get('store.currency.decimals')` — the store-level key
253
+ * `salla-bought-together.tsx:142` already rounds its basket total by.
254
+ * 3. `DEFAULT_CURRENCY_DECIMALS`.
255
+ *
256
+ * Every step is guarded: this runs inside `render()`, where an SDK that is not on the
257
+ * page yet (or a `config` that throws) must degrade to the default, never take the banner
258
+ * down.
259
+ */
260
+ export declare function getCurrencyDecimals(): number;
261
+ /**
262
+ * How much more of the cart value is needed to reach the given stage, rounded UP at the
263
+ * display precision. Never negative.
264
+ *
265
+ * `threshold - value` is raw IEEE-754 subtraction over two server-sent floats, so
266
+ * `300 - 289.599993` is `10.400007000000012`. Nothing downstream cleans that up:
267
+ * `salla.money()` only swaps digits and appends a symbol (`base/src/helpers/numbers.ts:74-84`).
268
+ * Rounding here, at the source, covers every consumer, including the `products_count`
269
+ * path that never reaches `salla.money`.
270
+ *
271
+ * Rounding goes UP, never to the nearest unit: the displayed amount must be enough to
272
+ * unlock the tier. Rounding 10.400007 to 10.40 asks for an amount that leaves the cart
273
+ * at 299.999993, still below the threshold. Float noise is guarded (see `CEIL_TOLERANCE`)
274
+ * so an exact 10.40 stays 10.40.
275
+ *
276
+ * A count remainder is a WHOLE number, because `salla.lang.choice('blocks.header.products_count', 10.4)`
277
+ * matches no plural interval and a shopper cannot add 0.4 of a product.
278
+ *
279
+ * Only the derived remainder is rounded. `progress.values` and `progress.thresholds` are
280
+ * server facts and stay as sent: rounding them would move the unlocked/locked boundary,
281
+ * which is the engine's call.
282
+ *
283
+ * A positive remainder never becomes 0: `getGuidanceMessage` drops its line on
284
+ * `remaining <= 0`, so a genuinely unmet tier must still ask for at least one unit of the
285
+ * precision (0.01 for a 2-decimal currency, 1 for a count). Exact zero, a met tier,
286
+ * still returns 0.
287
+ */
288
+ export declare function getRemainingToStage(index: number, progress: OfferStageProgress, measure?: OfferStageMeasure): number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salla.sa/twilight-components",
3
- "version": "2.14.590",
3
+ "version": "2.14.591",
4
4
  "license": "GPL-3.0",
5
5
  "author": "Salla Team <support@salla.dev> (https://salla.dev)",
6
6
  "bugs": {
@@ -82,9 +82,9 @@
82
82
  },
83
83
  "dependencies": {
84
84
  "@googlemaps/markerclusterer": "2.6.2",
85
- "@salla.sa/applepay": "2.14.590",
86
- "@salla.sa/twilight": "2.14.590",
87
- "@salla.sa/twilight-tailwind-theme": "2.14.590",
85
+ "@salla.sa/applepay": "2.14.591",
86
+ "@salla.sa/twilight": "2.14.591",
87
+ "@salla.sa/twilight-tailwind-theme": "2.14.591",
88
88
  "@salla.sa/ui-address-autocomplete-widget": "1.2.1",
89
89
  "@salla.sa/ui-google-map-render": "1.2.1",
90
90
  "@types/node": "^20.4.8",
@@ -105,5 +105,5 @@
105
105
  "vanilla-lazyload": "^17.8.5",
106
106
  "vanilla-picker": "^2.12.2"
107
107
  },
108
- "gitHead": "675fcebfdd69e92b2d8ee6c2bb931d0c26a44144"
108
+ "gitHead": "be20f9d830b0e7869d43be890e1579b34d346467"
109
109
  }
@@ -1,42 +0,0 @@
1
- /*!
2
- * Crafted with ❤ by Salla
3
- */
4
- 'use strict';
5
-
6
- var index = require('./index-CgZ8Pldm.js');
7
-
8
- const sallaTooltipCss = "/*!twlt*/.s-tooltip-container{position:relative;display:inline-block}.s-tooltip-item{position:absolute;transform:translateX(-63%) translateY(-50%);background-color:var(--color-primary);color:var(--color-primary-reverse);bottom:100%;left:50%;text-align:center;border-radius:5px;z-index:1;white-space:nowrap;transition:opacity 0.3s;pointer-events:none;margin:0 0 16px 8px;padding:12px;max-width:150px;width:190px;white-space:normal;opacity:1}.s-tooltip-item::after{content:\"\";position:absolute;bottom:-10px;left:50%;margin-left:-5px;border-width:5px;border-style:solid;border-color:var(--color-primary) transparent transparent transparent}.s-tooltip-item:dir(ltr){transform:translateX(-72%)}.s-tooltip-item--dark{background-color:#555555;color:white;padding:5px 15px;border-radius:8px;font-size:12px;font-weight:normal;max-width:330px;width:max-content}.s-tooltip-item--dark::after{border-color:#555555 transparent transparent transparent}.block{display:block}.shadow{--tw-shadow:0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow)}";
9
-
10
- const SallaTooltip = class {
11
- constructor(hostRef) {
12
- index.registerInstance(this, hostRef);
13
- /**
14
- * The theme of the tooltip (default, dark)
15
- */
16
- this.theme = 'default';
17
- this.show = false;
18
- this.targetElement = null;
19
- }
20
- handleMouseOver(event) {
21
- if (this.targetElement && this.targetElement.contains(event.target)) {
22
- this.show = true;
23
- }
24
- }
25
- handleMouseOut(event) {
26
- if (this.targetElement && this.targetElement.contains(event.target)) {
27
- this.show = false;
28
- }
29
- }
30
- componentDidLoad() {
31
- // Find the target element based on the targetSelector prop
32
- this.targetElement = document.getElementById(this.targetId);
33
- }
34
- render() {
35
- const validTheme = ['default', 'dark'].includes(this.theme) ? this.theme : 'default';
36
- return (index.h("div", { key: '4027073cb58fa70679f54f6009ed1ca95fd3f3d0', class: "s-tooltip-container" }, index.h("div", { key: 'ea50ad74b456fa3c89cfef2b69b2c9d5630d63bd', class: `s-tooltip-item s-tooltip-item--${validTheme}`, style: { display: this.show ? 'block' : 'none' } }, this.text ? index.h("span", null, this.text) : index.h("slot", null))));
37
- }
38
- get el() { return index.getElement(this); }
39
- };
40
- SallaTooltip.style = sallaTooltipCss;
41
-
42
- exports.salla_tooltip = SallaTooltip;
@@ -1,40 +0,0 @@
1
- /*!
2
- * Crafted with ❤ by Salla
3
- */
4
- import { r as registerInstance, h, a as getElement } from './index-klFskvc_.js';
5
-
6
- const sallaTooltipCss = "/*!twlt*/.s-tooltip-container{position:relative;display:inline-block}.s-tooltip-item{position:absolute;transform:translateX(-63%) translateY(-50%);background-color:var(--color-primary);color:var(--color-primary-reverse);bottom:100%;left:50%;text-align:center;border-radius:5px;z-index:1;white-space:nowrap;transition:opacity 0.3s;pointer-events:none;margin:0 0 16px 8px;padding:12px;max-width:150px;width:190px;white-space:normal;opacity:1}.s-tooltip-item::after{content:\"\";position:absolute;bottom:-10px;left:50%;margin-left:-5px;border-width:5px;border-style:solid;border-color:var(--color-primary) transparent transparent transparent}.s-tooltip-item:dir(ltr){transform:translateX(-72%)}.s-tooltip-item--dark{background-color:#555555;color:white;padding:5px 15px;border-radius:8px;font-size:12px;font-weight:normal;max-width:330px;width:max-content}.s-tooltip-item--dark::after{border-color:#555555 transparent transparent transparent}.block{display:block}.shadow{--tw-shadow:0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow)}";
7
-
8
- const SallaTooltip = class {
9
- constructor(hostRef) {
10
- registerInstance(this, hostRef);
11
- /**
12
- * The theme of the tooltip (default, dark)
13
- */
14
- this.theme = 'default';
15
- this.show = false;
16
- this.targetElement = null;
17
- }
18
- handleMouseOver(event) {
19
- if (this.targetElement && this.targetElement.contains(event.target)) {
20
- this.show = true;
21
- }
22
- }
23
- handleMouseOut(event) {
24
- if (this.targetElement && this.targetElement.contains(event.target)) {
25
- this.show = false;
26
- }
27
- }
28
- componentDidLoad() {
29
- // Find the target element based on the targetSelector prop
30
- this.targetElement = document.getElementById(this.targetId);
31
- }
32
- render() {
33
- const validTheme = ['default', 'dark'].includes(this.theme) ? this.theme : 'default';
34
- return (h("div", { key: '4027073cb58fa70679f54f6009ed1ca95fd3f3d0', class: "s-tooltip-container" }, h("div", { key: 'ea50ad74b456fa3c89cfef2b69b2c9d5630d63bd', class: `s-tooltip-item s-tooltip-item--${validTheme}`, style: { display: this.show ? 'block' : 'none' } }, this.text ? h("span", null, this.text) : h("slot", null))));
35
- }
36
- get el() { return getElement(this); }
37
- };
38
- SallaTooltip.style = sallaTooltipCss;
39
-
40
- export { SallaTooltip as salla_tooltip };
@@ -1,4 +0,0 @@
1
- /*!
2
- * Crafted with ❤ by Salla
3
- */
4
- import{r as t,h as i,H as e}from"./p-klFskvc_.js";var r,o;!function(t){t.PERCENTAGE="percentage",t.FIXED="fixed",t.FREE_PRODUCT="free_product"}(r||(r={})),function(t){t.PRODUCT_COUNT="products_count",t.PRODUCT_PURCHASE="order_amount"}(o||(o={}));const n=class{constructor(i){t(this,i),this.offer=null,this.products={},this.isLoading=!1,this.canRender=!0}componentWillLoad(){salla.onReady().then((()=>{if(!salla.config.get("store.features")?.includes("conditional-offer")||""!==salla.storage.get("cart")&&!salla.storage.get("cart")?.summary?.count)throw new Error("feature or cart object does not existed")})).then((()=>salla.api.cart.offers())).then((({data:t})=>{if(this.offer=t.find((t=>"conditional"===t.type)),this.offer)return this.isLoading=!0,this.offer.details.discounts.unshift({value:0,min_spend:0}),this.updateInitialOfferValue();this.canRender=!1})).then((()=>{if(this.offer)return this.getProducts()})).then((()=>{this.offer&&salla.event.on("cart::updated",(t=>this.updateOfferValues(t)))})).catch((t=>{this.canRender=!1,salla.logger.warn("salla-conditional-offer:: ",t)})).finally((()=>{this.isLoading=!1}))}getProducts(){const t=this.offer.details.discounts.filter((({type:t})=>t===r.FREE_PRODUCT)).map((({value:t})=>t)).filter(Boolean);if(t.length>0)return salla.product.fetch({source:"selected",source_value:t}).then((t=>{const i=t?.data;if(i&&Array.isArray(i)){const t={...this.products};i.forEach((({id:i,url:e,image:r,name:o,price:n})=>{i&&o&&r?.url&&e&&void 0!==n&&(t[i]={url:e,image:r,name:o,price:n})})),this.products=t}}))}updateInitialOfferValue(){return salla.api.cart.details().then((({data:{cart:t}})=>this.updateOfferValues(t)))}updateOfferValues({items:t,sub_total:i}){const e=this.offer.details.based_on===o.PRODUCT_COUNT?t?.reduce(((t,{quantity:i})=>t+i),0)??0:i;return this.offer={...this.offer,details:{...this.offer?.details,current_value:e}},this.offer}renderTooltip(t){const e=t.value,r=this.products[e];return r?i("salla-tooltip",{class:"absolute left-0 -top-2",targetId:`avatar-product-${e}`,theme:"dark"},i("div",{class:"flex gap-3 text-start"},r?.image?.url&&i("img",{src:r.image.url,alt:r?.image?.alt||r.name||"",class:"w-12 h-12 object-cover rounded-lg flex-shrink-0",loading:"lazy",decoding:"async"}),i("div",{class:"flex-1"},i("div",{class:"leading-tight mb-1"},r.name),i("div",{class:"text-xs text-gray-300",innerHTML:salla.money(r.price)})))):(salla.logger.error(`salla-conditional-offer:: there is no product with id (${t.value})!`),null)}getCheckpointContent(t){if(t.type===r.PERCENTAGE)return`${t.value}%`;if(t.type===r.FIXED)return i("span",{innerHTML:salla.money(t.value)});if(t.type!==r.FREE_PRODUCT)return salla.logger.error(`salla-conditional-offer:: unexpected type (${t.type})!`),"";const e=this.products[t.value];return e?i("a",{class:"s-conditional-offer-product-link",href:e.url},i("img",{class:"s-conditional-offer-checkpoint-image-content",loading:"lazy",decoding:"async",alt:e?.image?.alt||"",src:e?.image?.url})):(salla.logger.error(`salla-conditional-offer:: there is no product with id (${t.value})!`),"")}getOfferType(t){const i=this.offer.details?.based_on;if(i===o.PRODUCT_COUNT)try{return salla.lang.choice("blocks.header.products_count",t.min_spend)}catch(i){return salla.logger.warn("salla-conditional-offer:: invalid products_count interval",i),`${t.min_spend}`}return i===o.PRODUCT_PURCHASE?salla.money(t.min_spend):(salla.logger.warn(`salla-conditional-offer:: Unexpected offer detail's based_on value: ${i}`),`${t.min_spend}`)}clamp(t,i,e){return Math.max(i,Math.min(t,e))}mapValueRanges(t,i,e,r,o){const n=(t-i)*(o-r)/(e-i)+r;return n===Number.POSITIVE_INFINITY?100:n===Number.NEGATIVE_INFINITY?0:this.clamp(n,0,100)}getCheckPointView(t,e){const o=this.offer.details.discounts.findIndex((({min_spend:i})=>i===t.min_spend)),n=this.mapValueRanges(this.offer.details.current_value,this.offer.details.discounts[o-1]?.min_spend??0,t.min_spend,0,100),a=t.min_spend<=this.offer.details.current_value;return i("div",{class:"s-conditional-offer-checkpoint-container"},e>0?[i("div",{key:"progress-line",class:"s-conditional-offer-progress-line-container"},i("div",{class:"s-conditional-offer-progress-line-inactive"}),i("div",{class:"s-conditional-offer-progress-line-active",style:{width:`${n}%`}})),i("div",{key:"checkpoint",class:"s-conditional-offer-checkpoint "+(a?"s-conditional-offer-active-checkpoint":"")},i("div",{class:"s-conditional-offer-item-avatar-content "+(a?"active":""),id:t.type===r.FREE_PRODUCT?`avatar-product-${t.value}`:`avatar-${t.value??e}`},this.products&&this.getCheckpointContent(t)),this.products&&t.type===r.FREE_PRODUCT&&this.renderTooltip(t),i("div",{class:"s-conditional-offer-checkpoint-label "+(a?"active":""),innerHTML:this.getOfferType(t)}))]:i("div",{key:"label",class:{"s-conditional-offer-checkpoint-label":!0,"first-checkpoint":0===e,active:a},innerHTML:this.getOfferType(t)}))}getLoadingSkeletonView(){return i(e,{class:"s-conditional-offer-container"},i("div",{class:"s-conditional-offer-skeleton-inner-container"},i("div",{class:"s-conditional-offer-skeleton-subtitle"},i("salla-skeleton",{height:"16px",width:"30%"})),i("div",{class:"s-conditional-offer-skeleton-subtitle"},i("salla-skeleton",{height:"16px",width:"35%"})),i("div",{class:"s-conditional-offer-skeleton-checkpoints-wrapper"},Array(3).fill(null).map((()=>[i("salla-skeleton",{key:"checkpoint-line",height:"8px"}),i("div",{key:"checkpoint"},i("salla-skeleton",{height:"60px",width:"60px",type:"circle"}))])))))}render(){return this.canRender?this.isLoading?this.getLoadingSkeletonView():this.offer?i(e,{class:"s-conditional-offer-container"},i("div",{class:"s-conditional-offer-title-wrapper"},i("div",{class:"s-conditional-offer-title"},this.offer.title),this.offer.description?i("div",{class:"s-conditional-offer-subtitle"},this.offer.description," ",i("i",{class:"sicon-information"})):null),i("div",{class:"s-conditional-offer-progress-container"},this.offer.details.discounts.map(((t,e)=>i("div",{class:{"flex-1":e>0},key:t.min_spend},this.getCheckPointView(t,e)))))):null:null}};n.style='/*!twlt*/:host{display:block}.fixed{position:fixed}.absolute{position:absolute}.-top-2{top:-0.5rem}.left-0{left:0px}.mb-1{margin-bottom:0.25rem}.flex{display:flex}.h-12{height:3rem}.w-12{width:3rem}.flex-1{flex:1 1 0%}.flex-shrink-0{flex-shrink:0}.gap-3{gap:0.75rem}.rounded-lg{border-radius:0.5rem}.object-cover{object-fit:cover}.text-start{text-align:start}.text-xs{font-size:0.75rem;line-height:1rem}.leading-tight{line-height:1.25}.text-gray-300{--tw-text-opacity:1;color:rgb(209 213 219 / var(--tw-text-opacity, 1))}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.s-conditional-offer-container{position:relative;display:inline-flex;width:100%;flex-direction:column;align-items:center;justify-content:flex-start;gap:1.25rem;border-radius:0.375rem;--tw-bg-opacity:1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1));padding-left:1.25rem;padding-right:1.25rem;padding-top:1rem;padding-bottom:4rem}@media (min-width: 768px){.s-conditional-offer-container{padding-left:2.5rem;padding-right:2.5rem;padding-top:2rem;padding-bottom:2rem}}.s-conditional-offer-title-wrapper{display:flex;flex-direction:column;align-items:center;justify-content:flex-start;align-self:stretch}.s-conditional-offer-title{text-align:center;font-size:1.25rem;line-height:1.75rem;font-weight:700;color:var(--color-primary-dark)}.s-conditional-offer-subtitle{display:inline-flex;align-items:center;justify-content:center;gap:0.25rem;align-self:stretch;text-align:center;font-size:0.75rem;line-height:1rem;font-weight:400;--tw-text-opacity:1;color:rgb(64 64 64 / var(--tw-text-opacity, 1))}.s-conditional-offer-subtitle i{position:relative}.s-conditional-offer-progress-line{height:1px;align-self:stretch;background-color:var(--color-primary)}.s-conditional-offer-checkpoint-border{display:flex;height:60px;min-width:60px;flex-direction:column;align-items:center;justify-content:center;border-radius:9999px;border-width:1px;--tw-bg-opacity:1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.s-conditional-offer-checkpoint-border-colored{border-color:var(--color-primary);color:var(--color-primary-dark)}.s-conditional-offer-product-link{display:grid;aspect-ratio:1 / 1;height:58px;place-content:center;overflow:hidden;border-radius:9999px}.s-conditional-offer-checkpoint-image-content{height:58px;width:58px;object-fit:cover}.s-conditional-offer-progress-container{position:relative;margin-bottom:2rem;display:flex;height:8rem;width:100%;align-items:center;overflow-x:auto}@media (min-width: 768px){.s-conditional-offer-progress-container{height:4rem;overflow:visible}}.s-conditional-offer-item-avatar-content{text-align:center;font-size:0.875rem;font-weight:700;line-height:1.25rem}.s-conditional-offer-item-avatar-content.active{color:var(--color-primary-dark);transition-property:all;transition-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transition-duration:500ms;transition-timing-function:cubic-bezier(0, 0, 0.2, 1)}.s-conditional-offer-checkpoint{position:relative;display:flex;height:60px;width:60px;flex-shrink:0;flex-direction:column;align-items:center;justify-content:center;border-radius:9999px;border-width:1px}.s-conditional-offer-progress-line-container{display:grid;width:100%;overflow:hidden;grid-template-areas:\'progress-line\'}.s-conditional-offer-progress-line-inactive{height:1.5px;width:100%;--tw-bg-opacity:1;background-color:rgb(209 213 219 / var(--tw-bg-opacity, 1));transition-property:all;transition-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transition-duration:500ms;transition-timing-function:cubic-bezier(0, 0, 0.2, 1);grid-area:progress-line}.s-conditional-offer-progress-line-active{height:1.5px;width:0%;background-color:var(--color-primary);transition-property:all;transition-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transition-duration:500ms;transition-timing-function:cubic-bezier(0, 0, 0.2, 1);grid-area:progress-line}.s-conditional-offer-checkpoint-label{position:absolute;top:100%;left:50%;width:max-content;--tw-translate-x:-50%;--tw-translate-y:20%;transform:translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));transition-property:all;transition-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transition-duration:500ms;transition-timing-function:cubic-bezier(0, 0, 0.2, 1)}.s-conditional-offer-checkpoint-label.active{color:var(--color-primary-dark);transition-property:all;transition-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transition-duration:500ms;transition-timing-function:cubic-bezier(0, 0, 0.2, 1)}.s-conditional-offer-checkpoint-label.first-checkpoint{--tw-translate-y:132%;transform:translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.s-conditional-offer-checkpoint-label.first-checkpoint:where([dir="ltr"],[dir="ltr"] *){--tw-translate-x:0%;transform:translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.s-conditional-offer-checkpoint-label.first-checkpoint:where([dir="rtl"],[dir="rtl"] *){--tw-translate-x:-100%;transform:translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.s-conditional-offer-checkpoint-container{position:relative;display:flex;align-items:center}.s-conditional-offer-active-checkpoint{display:flex;justify-content:center;border-color:var(--color-primary);transition-property:all;transition-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transition-duration:500ms;transition-timing-function:cubic-bezier(0, 0, 0.2, 1)}.s-conditional-offer-skeleton-inner-container{margin-bottom:2rem;width:100%}@media (min-width: 768px){.s-conditional-offer-skeleton-inner-container{margin-bottom:0px}}.s-conditional-offer-skeleton-title{margin-bottom:1rem;display:flex;justify-content:center}.s-conditional-offer-skeleton-subtitle{margin-bottom:1.5rem;display:flex;justify-content:center}.s-conditional-offer-skeleton-checkpoints-wrapper{display:flex;align-items:center}';export{n as salla_conditional_offer}
@@ -1,4 +0,0 @@
1
- /*!
2
- * Crafted with ❤ by Salla
3
- */
4
- import{r as t,c as i,h as s,H as e}from"./p-klFskvc_.js";const r=class{constructor(s){t(this,s),this.giftCardRedeemed=i(this,"giftCardRedeemed"),this.code="",this.inlineForm=!1,this.pending=!1,this.error=null,this.redeemedOnce=!1,this.isDesktop=!1,this.modalView=null,this.result=null,this.mediaQueryList=null,this.mqlChangeHandler=t=>{this.isDesktop=t.matches,"form"===this.modalView&&this.isDesktop?(this.modalView=null,this.inlineForm=!0):this.inlineForm&&!this.isDesktop&&(this.inlineForm=!1,this.openModal("form"))},this.closeModal=()=>{this.modalView=null,this.modal?.close?.()},this.start=()=>{if(this.error=null,this.code="",this.isDesktop)return this.inlineForm=!0,void setTimeout((()=>this.field?.focus()),0);this.openModal("form")},this.cancel=()=>{this.inlineForm=!1,this.code="",this.error=null,this.closeModal()},this.handleInput=t=>{const i=t.target;this.code=(i.value||"").toUpperCase().replace(/[^A-Z0-9]/g,"").slice(0,16),i.value=this.code,this.error=null},this.onKeyUp=t=>{"Enter"===t.key&&(t.preventDefault(),this.redeem())},this.shopNow=()=>{this.closeModal(),window.location.href=salla.url.get("/")}}breakpointPx(){return 768}async componentWillLoad(){await salla.onReady(),this.mediaQueryList=window.matchMedia(`(min-width: ${this.breakpointPx()}px)`),this.isDesktop=this.mediaQueryList.matches,this.mediaQueryList.addEventListener?this.mediaQueryList.addEventListener("change",this.mqlChangeHandler):this.mediaQueryList.addListener&&this.mediaQueryList.addListener(this.mqlChangeHandler),await salla.lang.onLoaded()}disconnectedCallback(){this.mediaQueryList?.removeEventListener?this.mediaQueryList.removeEventListener("change",this.mqlChangeHandler):this.mediaQueryList?.removeListener&&this.mediaQueryList.removeListener(this.mqlChangeHandler)}tFirst(t,i){for(const s of t){const t=salla.lang.get(s,i);if(t&&t!==s)return t}return""}t(t,i){return this.tFirst([`pages.checkout.${t}`],i)}get canRedeem(){const t=salla.config.get("store.features",[]);return!salla.config.isGuest()&&t.includes("wallet-gift-card")&&t.includes("giftcard-redemption-form-enabled")}get isValidCode(){return/^[A-Z0-9]{16}$/.test(this.code)}get addLabel(){return this.t(this.redeemedOnce?"gift_card_add_another":"gift_card_add")}openModal(t){this.modalView=t,this.modal?.open?.(),"form"===t&&setTimeout((()=>this.field?.focus()),0)}toDate(t){if(!t)return null;const i="object"==typeof t?t.date??t.datetime??null:t;if("number"==typeof i){const t=new Date(i<1e12?1e3*i:i);return isNaN(t.getTime())?null:t}if("string"!=typeof i)return null;const s=new Date(i.replace(" ","T"));return isNaN(s.getTime())?null:s}expiryMonths(t){const i=this.toDate(t);if(!i)return null;const s=Math.round((i.getTime()-Date.now())/2630016e3);return s>0?s:null}formatMoney(t){try{return salla.money(t)||""}catch(t){return salla.logger?.warn?.("gift-card: could not format amount",t),""}}trackRedeem(t,i,s={}){salla.event.dispatch("giftcard::redeemed",{status:t,code:i?i.slice(0,4)+"X".repeat(Math.max(0,i.length-4)):"",...s})}async redeem(){if(this.pending||!this.isValidCode||!this.canRedeem)return;this.pending=!0,this.error=null;const t=this.code;try{const i=await salla.api.request("wallet/gift-card/redeem",{code:this.code},"post"),s=i?.data||{};this.code="",this.field&&(this.field.value=""),this.inlineForm=!1,this.redeemedOnce=!0,this.result=s,this.openModal("success"),this.giftCardRedeemed.emit(s),this.trackRedeem("success",t,{amount:s.amount,new_balance:s.new_balance,expires_at:s.expires_at})}catch(i){const s=i?.response?.data?.error?.fields;this.error=s?Object.values(s).flat().join(", "):i?.response?.data?.error?.message||this.t("gift_card_redeem_error"),this.inlineForm=!1,this.openModal("error"),this.trackRedeem("failed",t,{reason:this.error})}finally{this.pending=!1}}renderPrompt(){return s("div",{class:"s-gift-card-prompt"},s("div",{class:"s-gift-card-intro"},s("span",{class:"s-gift-card-mark"},s("i",{class:"sicon-gift","aria-hidden":"true"})),s("div",{class:"s-gift-card-copy"},s("p",{class:"s-gift-card-title"},this.t("gift_card_title")),s("p",{class:"s-gift-card-subtitle"},this.t("gift_card_subtitle")))),s("salla-button",{class:"s-gift-card-trigger",color:"primary",fill:"outline",onClick:this.start},s("span",null,this.addLabel)))}renderField(){return[s("label",{class:"s-gift-card-label",htmlFor:"gift_card_redeem_field"},this.tFirst(["pages.gift.code"])),s("input",{id:"gift_card_redeem_field",ref:t=>this.field=t,type:"text",maxlength:16,autocomplete:"off",class:"s-gift-card-input",value:this.code,disabled:this.pending,placeholder:this.t("gift_card_redeem_placeholder"),onInput:this.handleInput,onKeyUp:this.onKeyUp})]}renderSubmit(t=!1){return s("salla-button",{id:"gift_card_redeem_submit",color:"primary",width:t?"wide":"normal",loading:this.pending,"loader-position":"center",disabled:this.pending||!this.isValidCode,onClick:()=>this.redeem()},s("span",null,this.t("gift_card_redeem_confirm")))}renderInlineForm(){return s("div",{class:"s-gift-card-form"},s("div",{class:"s-gift-card-field"},this.renderField()),this.renderSubmit(),s("button",{type:"button",class:"s-gift-card-cancel",disabled:this.pending,onClick:this.cancel},this.t("gift_card_cancel")))}renderSheetForm(){return s("div",{class:"s-gift-card-sheet"},s("div",{class:"s-gift-card-field"},this.renderField()),this.renderSubmit(!0))}renderSuccess(){const t=this.formatMoney(this.result?.amount),i=this.expiryMonths(this.result?.expires_at),e=this.t("gift_card_success_title");return s("div",{class:"s-gift-card-result"},s("span",{class:"s-gift-card-result-mark s-gift-card-result-mark-success",innerHTML:'\n<svg viewBox="0 0 96 96" width="72" height="72" role="img" aria-hidden="true" xmlns="http://www.w3.org/2000/svg">\n \x3c!-- burst --\x3e\n <g fill="#F5C242">\n <path d="M48 8l3.2 7.6L59 18l-6.2 5.3L54 31l-6-4-6 4 1.2-7.7L37 18l7.8-2.4z"/>\n <path d="M71 26l1.9 4.4L77 32l-3.6 3 .7 4.5-4.1-2.3-4.1 2.3.7-4.5L63 32l4.1-1.6z"/>\n <path d="M25 26l1.9 4.4L31 32l-3.6 3 .7 4.5L24 37.2 19.9 39.5l.7-4.5L17 32l4.1-1.6z"/>\n </g>\n <g fill="#E4572E" opacity=".9">\n <circle cx="30" cy="18" r="2.4"/>\n <circle cx="66" cy="18" r="2.4"/>\n <circle cx="48" cy="44" r="2.2"/>\n </g>\n \x3c!-- lid --\x3e\n <rect x="20" y="46" width="56" height="12" rx="3" fill="#2E8B57"/>\n \x3c!-- box --\x3e\n <path d="M25 58h46v26a4 4 0 0 1-4 4H29a4 4 0 0 1-4-4z" fill="#3AA76D"/>\n \x3c!-- ribbon --\x3e\n <rect x="44" y="46" width="8" height="42" fill="#F5F7F6"/>\n <rect x="20" y="46" width="56" height="12" rx="3" fill="#2E8B57" opacity="0"/>\n <rect x="44" y="46" width="8" height="12" fill="#E9EFEB"/>\n</svg>\n'}),e&&s("h3",{class:"s-gift-card-result-title"},e),s("p",{class:"s-gift-card-result-text",innerHTML:i?this.tFirst(["pages.checkout.gift_card_success_body_expiring","pages.checkout.gift_card_success_body","pages.checkout.gift_card_redeem_success"],{amount:t,months:i}):this.tFirst(["pages.checkout.gift_card_success_body","pages.checkout.gift_card_redeem_success"],{amount:t})}),s("salla-button",{color:"primary",width:"wide",onClick:this.shopNow},s("span",null,this.tFirst(["pages.loyalty_program.shop_now"]))))}renderError(){return s("div",{class:"s-gift-card-result"},s("span",{class:"s-gift-card-result-mark s-gift-card-result-mark-error"},s("i",{class:"sicon-cancel","aria-hidden":"true"})),s("h3",{class:"s-gift-card-result-title"},this.tFirst(["pages.checkout.gift_card_failure_title","pages.checkout.gift_card_redeem_error"])),s("p",{class:"s-gift-card-result-text"},this.error))}render(){return this.canRedeem?s(e,{class:"s-gift-card"},s("div",{class:"s-gift-card-panel"},this.inlineForm&&this.isDesktop?this.renderInlineForm():this.renderPrompt()),s("salla-modal",{ref:t=>this.modal=t,class:"s-gift-card-modal",width:"sm",position:this.isDesktop?"middle":"bottom","modal-title":this.t("gift_card_redeem_label"),onModalVisibilityChanged:t=>{t.detail||(this.modalView=null)}},s("div",{class:"s-gift-card-modal-body"},"form"===this.modalView&&this.renderSheetForm(),"success"===this.modalView&&this.renderSuccess(),"error"===this.modalView&&this.renderError()))):null}};r.style='/*!twlt*/@charset "UTF-8";.s-gift-card{display:block;flex:1 1 auto;min-width:0}.s-gift-card-panel{height:100%;background:#fff;border-radius:12px;padding:20px;box-sizing:border-box}.s-gift-card-prompt{display:flex;flex-direction:column;align-items:stretch;gap:16px;height:100%}.s-gift-card-intro{display:flex;align-items:center;gap:12px}.s-gift-card-mark{flex:0 0 auto;width:48px;height:48px;border-radius:9999px;background:#fdecef;color:#e8637c;display:inline-flex;align-items:center;justify-content:center;font-size:22px}.s-gift-card-copy{min-width:0}.s-gift-card-title{margin:0;font-weight:700;font-size:15px;color:#1c1c1c}.s-gift-card-subtitle{margin:2px 0 0;font-size:12px;color:#9aa0a6}.s-gift-card-trigger{display:block}.s-gift-card-form{display:flex;align-items:flex-end;gap:12px}.s-gift-card-field{flex:1 1 auto;min-width:0}.s-gift-card-label{display:block;margin-bottom:6px;font-size:13px;font-weight:700;color:#1c1c1c}.s-gift-card-input{width:100%;height:44px;padding:0 14px;box-sizing:border-box;border:1px solid #e6e8eb;border-radius:8px;background:#fff;font-size:13px;color:#1c1c1c}.s-gift-card-input::placeholder{color:#b7bcc2}.s-gift-card-input:focus{outline:none;border-color:var(--color-primary, #2e8b57)}.s-gift-card-cancel{flex:0 0 auto;height:44px;padding:0 8px;border:0;background:none;color:#6b7280;font-size:13px;cursor:pointer}.s-gift-card-cancel:disabled{opacity:0.5;cursor:default}.s-gift-card-sheet{display:flex;flex-direction:column;gap:16px;padding-top:4px}.s-gift-card-result{display:flex;flex-direction:column;align-items:center;text-align:center;padding:12px 8px 8px}.s-gift-card-result-mark{width:120px;height:120px;border-radius:9999px;display:inline-flex;align-items:center;justify-content:center;margin-bottom:20px}.s-gift-card-result-mark-success{background:#eaf7f0}.s-gift-card-result-mark-error{background:#fdeaea;color:#fff;font-size:34px}.s-gift-card-result-mark-error i{width:72px;height:72px;border-radius:9999px;background:#ea4b4b;display:inline-flex;align-items:center;justify-content:center}.s-gift-card-result-title{margin:0 0 10px;font-size:19px;font-weight:700;color:#1c1c1c}.s-gift-card-result-text{margin:0 0 22px;font-size:13px;line-height:1.7;color:#6b7280}@media screen and (min-width: 768px){.s-gift-card-panel{padding:22px 24px;display:flex;align-items:center}.s-gift-card-prompt{flex-direction:row;align-items:center;justify-content:space-between;gap:24px;width:100%}.s-gift-card-trigger{flex:0 0 auto}.s-gift-card-form{width:100%}.s-gift-card-result{padding:8px 24px 16px}}.inline{display:inline}.contents{display:contents}.resize{resize:both}.uppercase{text-transform:uppercase}.outline{outline-style:solid}';export{r as salla_gift_card_redeem}
@@ -1,9 +0,0 @@
1
- /*!
2
- * Crafted with ❤ by Salla
3
- */
4
- import{d as e}from"./p-klFskvc_.js";function t(e,t){return t.forEach((function(t){t&&"string"!=typeof t&&!Array.isArray(t)&&Object.keys(t).forEach((function(n){if("default"!==n&&!(n in e)){var i=Object.getOwnPropertyDescriptor(t,n);Object.defineProperty(e,n,i.get?i:{enumerable:!0,get:function(){return t[n]}})}}))})),Object.freeze(e)}var n,i,E={exports:{}},r=n?E.exports:(n=1,E.exports=(i=function(e){var t=e.addFilter,n=e.utils,i=n.Type,E=n.isString,r=n.replaceInString,T=n.guesstimateMimeType,u=n.getExtensionFromFilename,_=n.getFilenameFromURL,o=function(e,t){return e.some((function(e){return/\*$/.test(e)?(n=e,(/^[^/]+/.exec(t)||[]).pop()===n.slice(0,-2)):e===t;var n}))},a=function(e,t,n){if(0===t.length)return!0;var i=function(e){var t="";if(E(e)){var n=_(e),i=u(n);i&&(t=T(i))}else t=e.type;return t}(e);return n?new Promise((function(E,r){n(e,i).then((function(e){o(t,e)?E():r()})).catch(r)})):o(t,i)};return t("SET_ATTRIBUTE_TO_OPTION_MAP",(function(e){return Object.assign(e,{accept:"acceptedFileTypes"})})),t("ALLOW_HOPPER_ITEM",(function(e,t){var n=t.query;return!n("GET_ALLOW_FILE_TYPE_VALIDATION")||a(e,n("GET_ACCEPTED_FILE_TYPES"))})),t("LOAD_FILE",(function(e,t){var n=t.query;return new Promise((function(t,i){if(n("GET_ALLOW_FILE_TYPE_VALIDATION")){var E=n("GET_ACCEPTED_FILE_TYPES"),T=n("GET_FILE_VALIDATE_TYPE_DETECT_TYPE"),u=a(e,E,T),_=function(){var e,t=E.map((e=n("GET_FILE_VALIDATE_TYPE_LABEL_EXPECTED_TYPES_MAP"),function(t){return null!==e[t]&&(e[t]||t)})).filter((function(e){return!1!==e})),T=t.filter((function(e,n){return t.indexOf(e)===n}));i({status:{main:n("GET_LABEL_FILE_TYPE_NOT_ALLOWED"),sub:r(n("GET_FILE_VALIDATE_TYPE_LABEL_EXPECTED_TYPES"),{allTypes:T.join(", "),allButLastType:T.slice(0,-1).join(", "),lastType:T[T.length-1]})}})};if("boolean"==typeof u)return u?t(e):_();u.then((function(){t(e)})).catch(_)}else t(e)}))})),{options:{allowFileTypeValidation:[!0,i.BOOLEAN],acceptedFileTypes:[[],i.ARRAY],labelFileTypeNotAllowed:["File is of invalid type",i.STRING],fileValidateTypeLabelExpectedTypes:["Expects {allButLastType} or {lastType}",i.STRING],fileValidateTypeLabelExpectedTypesMap:[{},i.OBJECT],fileValidateTypeDetectType:[null,i.FUNCTION]}}},"undefined"!=typeof window&&void 0!==window.document&&document.dispatchEvent(new CustomEvent("FilePond:pluginloaded",{detail:i})),i)),T=t({__proto__:null,default:e(r)},[r]);
5
- /*!
6
- * FilePondPluginFileValidateType 1.2.9
7
- * Licensed under MIT, https://opensource.org/licenses/MIT/
8
- * Please visit https://pqina.nl/filepond/ for details.
9
- */export{T as f}
@@ -1,4 +0,0 @@
1
- /*!
2
- * Crafted with ❤ by Salla
3
- */
4
- import{r as t,h as o,a as r}from"./p-klFskvc_.js";const a=class{constructor(o){t(this,o),this.theme="default",this.show=!1,this.targetElement=null}handleMouseOver(t){this.targetElement&&this.targetElement.contains(t.target)&&(this.show=!0)}handleMouseOut(t){this.targetElement&&this.targetElement.contains(t.target)&&(this.show=!1)}componentDidLoad(){this.targetElement=document.getElementById(this.targetId)}render(){const t=["default","dark"].includes(this.theme)?this.theme:"default";return o("div",{key:"4027073cb58fa70679f54f6009ed1ca95fd3f3d0",class:"s-tooltip-container"},o("div",{key:"ea50ad74b456fa3c89cfef2b69b2c9d5630d63bd",class:`s-tooltip-item s-tooltip-item--${t}`,style:{display:this.show?"block":"none"}},this.text?o("span",null,this.text):o("slot",null)))}get el(){return r(this)}};a.style='/*!twlt*/.s-tooltip-container{position:relative;display:inline-block}.s-tooltip-item{position:absolute;transform:translateX(-63%) translateY(-50%);background-color:var(--color-primary);color:var(--color-primary-reverse);bottom:100%;left:50%;text-align:center;border-radius:5px;z-index:1;white-space:nowrap;transition:opacity 0.3s;pointer-events:none;margin:0 0 16px 8px;padding:12px;max-width:150px;width:190px;white-space:normal;opacity:1}.s-tooltip-item::after{content:"";position:absolute;bottom:-10px;left:50%;margin-left:-5px;border-width:5px;border-style:solid;border-color:var(--color-primary) transparent transparent transparent}.s-tooltip-item:dir(ltr){transform:translateX(-72%)}.s-tooltip-item--dark{background-color:#555555;color:white;padding:5px 15px;border-radius:8px;font-size:12px;font-weight:normal;max-width:330px;width:max-content}.s-tooltip-item--dark::after{border-color:#555555 transparent transparent transparent}.block{display:block}.shadow{--tw-shadow:0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow)}';export{a as salla_tooltip}