@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,602 @@
1
+ /*!
2
+ * Crafted with ❤ by Salla
3
+ */
4
+ 'use strict';
5
+
6
+ /**
7
+ * API Service for salla-bullet-delivery component
8
+ * Uses Salla's shipping API and scope API for delivery location management
9
+ */
10
+ const API_LOG_PREFIX = 'BulletDeliveryAPI';
11
+ const validId = (id) => {
12
+ const n = id == null ? Number.NaN : Number(id);
13
+ return !Number.isNaN(n) && n !== 0;
14
+ };
15
+ async function withApiErrorHandling(fn, fallback, logLabel) {
16
+ try {
17
+ return await fn();
18
+ }
19
+ catch (error) {
20
+ console.error(`${API_LOG_PREFIX}: ${logLabel}`, error);
21
+ return fallback;
22
+ }
23
+ }
24
+ const apiCache = new Map();
25
+ const CACHE_TTL = 5 * 60 * 1000;
26
+ let branchCacheGeneration = 0;
27
+ const resolvedBranchPages = new WeakMap();
28
+ function getCached(key) {
29
+ const entry = apiCache.get(key);
30
+ if (!entry || Date.now() - entry.timestamp > CACHE_TTL) {
31
+ apiCache.delete(key);
32
+ return null;
33
+ }
34
+ return entry.data;
35
+ }
36
+ function setCache(key, data) {
37
+ apiCache.set(key, { data, timestamp: Date.now() });
38
+ }
39
+ function getCountryBranches(branches, countryId) {
40
+ if (!branches || countryId == null)
41
+ return branches;
42
+ if (branches.some(branch => branch.country?.id == null))
43
+ return null;
44
+ const matches = branches.filter(branch => String(branch.country?.id) === String(countryId));
45
+ return matches.length ? matches : null;
46
+ }
47
+ function getBranchPage({ query, lat, lng, country_id, city_id, page, per_page = 20 }, cachePage = true) {
48
+ const params = { per_page };
49
+ if (query && query.trim().length >= 2)
50
+ params.query = query;
51
+ if (lat)
52
+ params.lat = Number(lat).toFixed(6);
53
+ if (lng)
54
+ params.lng = Number(lng).toFixed(6);
55
+ if (country_id)
56
+ params.country_id = country_id;
57
+ if (city_id)
58
+ params.city_id = city_id;
59
+ if (page && page > 1)
60
+ params.page = page;
61
+ const cacheKey = `branches_${JSON.stringify(params)}`;
62
+ const cached = cachePage ? getCached(cacheKey) : null;
63
+ if (cached)
64
+ return cached;
65
+ const request = (async () => {
66
+ const res = await salla.api.request('branches', { params });
67
+ if (!Array.isArray(res?.data))
68
+ throw new Error('Invalid branches response');
69
+ return { branches: res.data, perPage: per_page, pagination: res.pagination };
70
+ })();
71
+ if (cachePage)
72
+ setCache(cacheKey, request);
73
+ void request.then(page => { resolvedBranchPages.set(request, page); }, () => { });
74
+ void request.catch(() => {
75
+ if (apiCache.get(cacheKey)?.data === request)
76
+ apiCache.delete(cacheKey);
77
+ });
78
+ return request;
79
+ }
80
+ /** Uses country code from API (e.g. 'SA'). */
81
+ const isSaudiArabia = (countryCode) => String(countryCode).toUpperCase() === 'SA';
82
+ /**
83
+ * Fast Delivery API Service
84
+ * Uses Salla's shipping API and scopes API. Branch and address data are used as returned by the API (no mapping).
85
+ */
86
+ const bulletDeliveryAPI = {
87
+ /**
88
+ * Get available countries from Salla shipping API
89
+ * @param forBranch - when true, use for_branch=1 (e.g. for pickup/branches tab)
90
+ */
91
+ async getCountries(forBranch = false, query) {
92
+ const cacheKey = !query?.trim() ? `countries_${forBranch ? 1 : 0}` : null;
93
+ if (cacheKey) {
94
+ const cached = getCached(cacheKey);
95
+ if (cached)
96
+ return cached;
97
+ }
98
+ const result = await withApiErrorHandling(async () => {
99
+ const params = { for_branch: forBranch ? 1 : 0 };
100
+ if (forBranch) {
101
+ params.for_allocation = 1;
102
+ }
103
+ if (query?.trim())
104
+ params.query = query.trim();
105
+ const data = (await salla.api.request("shipping/countries", { params }))?.data ?? [];
106
+ return data.map((c) => ({ id: c.id, code: c.code, name: c.name, has_regions: isSaudiArabia(c.code) }));
107
+ }, [], 'Error getting countries');
108
+ if (cacheKey && result.length > 0)
109
+ setCache(cacheKey, result);
110
+ return result;
111
+ },
112
+ /**
113
+ * Get regions for a country from Salla shipping API
114
+ * Endpoint: GET /shipping/countries/<COUNTRY_ID>/region
115
+ */
116
+ async getRegions(countryId, query) {
117
+ if (!validId(countryId)) {
118
+ console.warn(`${API_LOG_PREFIX}: getRegions called without valid country_id`);
119
+ return [];
120
+ }
121
+ const cacheKey = !query?.trim() ? `regions_${countryId}` : null;
122
+ if (cacheKey) {
123
+ const cached = getCached(cacheKey);
124
+ if (cached)
125
+ return cached;
126
+ }
127
+ const result = await withApiErrorHandling(async () => {
128
+ const params = {};
129
+ if (query?.trim())
130
+ params.query = query.trim();
131
+ const data = (await salla.api.request(`shipping/countries/${countryId}/regions`, { params }))?.data ?? [];
132
+ return data.map((r) => ({ id: r.id, name: r.name, code: r.code, country_id: Number(countryId) }));
133
+ }, [], 'Error fetching regions');
134
+ if (cacheKey && result.length > 0)
135
+ setCache(cacheKey, result);
136
+ return result;
137
+ },
138
+ /**
139
+ * Get cities from Salla shipping API
140
+ * @param regionId - Optional; when provided (e.g. for SA), cities are filtered by region
141
+ */
142
+ async getCities(countryId, regionId, query) {
143
+ if (!validId(countryId)) {
144
+ console.warn(`${API_LOG_PREFIX}: getCities called without valid country_id`);
145
+ return [];
146
+ }
147
+ const cacheKey = !query?.trim() ? `cities_${countryId}_${regionId || 'all'}` : null;
148
+ if (cacheKey) {
149
+ const cached = getCached(cacheKey);
150
+ if (cached)
151
+ return cached;
152
+ }
153
+ const result = await withApiErrorHandling(async () => {
154
+ const params = { for_branch: 0, country_id: countryId };
155
+ if (regionId)
156
+ params.region_id = regionId;
157
+ if (query?.trim())
158
+ params.query = query.trim();
159
+ const data = (await salla.api.request("shipping/cities", { params }))?.data ?? [];
160
+ return data.map((c) => ({ id: c.id, name: c.name, country_id: countryId, ...(c.region_id != null && { region_id: c.region_id }) }));
161
+ }, [], 'Error fetching cities');
162
+ if (cacheKey && result.length > 0)
163
+ setCache(cacheKey, result);
164
+ return result;
165
+ },
166
+ /**
167
+ * Get districts from Salla shipping API
168
+ */
169
+ async getDistricts(cityId, query) {
170
+ if (!validId(cityId)) {
171
+ console.warn(`${API_LOG_PREFIX}: getDistricts called without valid city_id`);
172
+ return [];
173
+ }
174
+ return withApiErrorHandling(async () => {
175
+ const params = { for_branch: 0, city_id: cityId };
176
+ if (query?.trim())
177
+ params.query = query.trim();
178
+ const raw = (await salla.api.request("shipping/districts", { params }))?.data;
179
+ const list = Array.isArray(raw) ? raw : (Array.isArray(raw?.districts) ? raw.districts : []);
180
+ return list.map((d) => ({ id: d.id, name: d.name, name_en: d.name_en, city_id: cityId }));
181
+ }, [], 'Error fetching districts');
182
+ },
183
+ async getSavedAddresses() {
184
+ return withApiErrorHandling(async () => {
185
+ const data = (await salla.api.request("address"))?.data;
186
+ return Array.isArray(data) ? data : [];
187
+ }, [], 'Error fetching user addresses');
188
+ },
189
+ /** Complete country rows for the city picker; incomplete reads remain retryable. */
190
+ async getAllBranches(country_id, per_page = 20) {
191
+ const collection = await this.getBranchCollection(country_id, per_page, { maxPages: Number.POSITIVE_INFINITY });
192
+ if (!collection.complete)
193
+ throw Object.assign(new Error('Incomplete branch city collection'), { branches: collection.branches });
194
+ return collection.branches;
195
+ },
196
+ /** Keeps loaded branches separate from whether the collection is complete. */
197
+ async getBranchCollection(country_id, per_page = 20, { maxPages = 10, requireComplete = false } = {}) {
198
+ const generation = branchCacheGeneration;
199
+ const cacheKey = `branches_all_${JSON.stringify([country_id ?? null, per_page, maxPages, requireComplete])}`;
200
+ const cached = Number.isFinite(maxPages) ? getCached(cacheKey) : null;
201
+ if (cached)
202
+ return cached;
203
+ const storeBranches = country_id != null ? getCached('branches_all') : null;
204
+ if (country_id == null)
205
+ setCache('branches_first', getBranchPage({ per_page, page: 1 }));
206
+ const partial = { branches: [], complete: false };
207
+ const request = withApiErrorHandling(async () => {
208
+ const sharedFirstPage = storeBranches ? getCached('branches_first') : null;
209
+ const first = sharedFirstPage ? resolvedBranchPages.get(sharedFirstPage) : null;
210
+ if (storeBranches && getCountryBranches(first?.branches ?? null, country_id)) {
211
+ const collection = await storeBranches;
212
+ if (generation !== branchCacheGeneration)
213
+ return { branches: [], complete: false };
214
+ const branches = collection.complete ? getCountryBranches(collection.branches, country_id) : null;
215
+ if (branches)
216
+ return { branches, complete: true };
217
+ }
218
+ for (let page = 1; page <= maxPages; page++) {
219
+ const { branches, pagination } = await getBranchPage({ country_id, per_page, page }, Number.isFinite(maxPages) || page === 1);
220
+ if (generation !== branchCacheGeneration)
221
+ return { branches: [], complete: false };
222
+ const currentPage = Number(pagination?.currentPage ?? page);
223
+ const totalPages = Number(pagination?.totalPages);
224
+ if (page === 1 && totalPages === 0 && !branches.length)
225
+ return { branches: [], complete: true };
226
+ if (pagination && (currentPage !== page || !Number.isInteger(totalPages) || totalPages < page)) {
227
+ throw new Error('Invalid branches pagination');
228
+ }
229
+ partial.branches.push(...branches);
230
+ if (pagination) {
231
+ if (requireComplete && totalPages > maxPages)
232
+ return partial;
233
+ if (page === totalPages)
234
+ return { branches: partial.branches, complete: true };
235
+ if (!branches.length)
236
+ throw new Error('Incomplete branches response');
237
+ }
238
+ else if (branches.length < per_page) {
239
+ return { branches: partial.branches, complete: true };
240
+ }
241
+ }
242
+ return partial;
243
+ }, partial, 'Error fetching all branches');
244
+ setCache(cacheKey, request);
245
+ if (country_id == null)
246
+ setCache('branches_all', request);
247
+ void request.then(collection => {
248
+ if (collection.complete) {
249
+ if (generation === branchCacheGeneration && apiCache.get('branches_all')?.data === request) {
250
+ setCache('branches_complete', collection.branches);
251
+ }
252
+ return;
253
+ }
254
+ if (apiCache.get(cacheKey)?.data === request)
255
+ apiCache.delete(cacheKey);
256
+ if (apiCache.get('branches_all')?.data === request)
257
+ apiCache.delete('branches_all');
258
+ });
259
+ return request;
260
+ },
261
+ async getBranches(filters = {}) {
262
+ const generation = branchCacheGeneration;
263
+ const hasSearchParams = (filters.query && filters.query.trim().length >= 2) || filters.lat || filters.lng || filters.city_id;
264
+ const perPage = filters.per_page ?? 20;
265
+ const offset = ((filters.page ?? 1) - 1) * perPage;
266
+ if (!hasSearchParams) {
267
+ const branches = getCountryBranches(getCached('branches_complete'), filters.country_id);
268
+ if (branches) {
269
+ return branches.slice(offset, offset + perPage);
270
+ }
271
+ const firstPage = getCached('branches_first');
272
+ if (firstPage) {
273
+ const result = resolvedBranchPages.get(firstPage);
274
+ if (generation !== branchCacheGeneration)
275
+ return [];
276
+ if (result) {
277
+ const first = getCountryBranches(result.branches, filters.country_id);
278
+ const complete = result.pagination
279
+ ? Number(result.pagination.totalPages) === 1
280
+ : result.branches.length < result.perPage;
281
+ if (first && (first.length >= offset + perPage || complete)) {
282
+ return first.slice(offset, offset + perPage);
283
+ }
284
+ }
285
+ }
286
+ }
287
+ return withApiErrorHandling(async () => (await getBranchPage(filters)).branches, [], 'Error fetching branches');
288
+ },
289
+ async saveAddressLocation(payload) {
290
+ return withApiErrorHandling(async () => {
291
+ const res = await salla.api.request('address/location', { ...payload, for_allocation: true }, 'post');
292
+ const data = res?.data ?? res;
293
+ const address = typeof data === 'object' && data != null && 'id' in data ? data : undefined;
294
+ return { success: true, address };
295
+ }, { success: false }, 'Error saving address/location');
296
+ },
297
+ async setDeliveryScope(scopeId) {
298
+ return withApiErrorHandling(async () => {
299
+ await salla.api.withoutNotifier(() => salla.scope.change({ id: scopeId }));
300
+ salla.storage.set("scope", { ...(salla.storage.get("scope") || {}), id: scopeId });
301
+ return true;
302
+ }, false, 'Error setting delivery scope');
303
+ },
304
+ async allocateScope(payload) {
305
+ // A field reason (e.g. branch_id "not accepting orders") is more useful than the generic "invalid fields" message.
306
+ const errMsg = (d) => {
307
+ const body = d;
308
+ const fieldReason = Object.values(body?.error?.fields ?? {}).flat().find((m) => typeof m === 'string' && m.trim());
309
+ return fieldReason ?? body?.error?.message ?? body?.message ?? 'Failed to allocate scope';
310
+ };
311
+ try {
312
+ const response = await salla.api.withoutNotifier(() => salla.api.request("scopes/allocation", payload, 'post'));
313
+ // SDK resolves with { data } and throws on non-2xx; any resolved value is success
314
+ const data = response?.data ?? response;
315
+ return { success: true, data: data };
316
+ }
317
+ catch (error) {
318
+ console.error(`${API_LOG_PREFIX}: Error allocating scope`, error);
319
+ const err = error;
320
+ return { success: false, error: err?.response?.data != null ? errMsg(err.response.data) : (err?.message ?? 'Unknown error') };
321
+ }
322
+ },
323
+ async getAddressToken() {
324
+ return withApiErrorHandling(async () => {
325
+ const res = await salla.api.request('address/autocomplete-token');
326
+ return res?.data?.token ?? null;
327
+ }, null, 'Error fetching address autocomplete token');
328
+ },
329
+ };
330
+ function clearApiCache() {
331
+ branchCacheGeneration++;
332
+ apiCache.clear();
333
+ }
334
+ function clearBranchCache() {
335
+ branchCacheGeneration++;
336
+ for (const key of apiCache.keys()) {
337
+ if (key.startsWith('branches_'))
338
+ apiCache.delete(key);
339
+ }
340
+ }
341
+
342
+ /**
343
+ * Helper functions for salla-bullet-delivery component
344
+ */
345
+ const EARTH_RADIUS_KM = 6371;
346
+ const deg2rad = (deg) => deg * (Math.PI / 180);
347
+ /** Haversine distance in km */
348
+ function calculateDistance(lat1, lon1, lat2, lon2) {
349
+ const dLat = deg2rad(lat2 - lat1);
350
+ const dLon = deg2rad(lon2 - lon1);
351
+ const a = Math.sin(dLat / 2) ** 2 +
352
+ Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * Math.sin(dLon / 2) ** 2;
353
+ return EARTH_RADIUS_KM * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
354
+ }
355
+ /**
356
+ * Whether a pickup branch can be selected.
357
+ *
358
+ * `pickup_readiness` is the richer, backend-computed verdict (INV-357) and wins whenever the API
359
+ * sends it. Not every store's `GET /branches` returns it though, so we fall back to the original
360
+ * `is_open` rule instead of treating a missing object as "not selectable" — otherwise every branch
361
+ * in the list renders disabled and pickup cannot be chosen at all (SP-22202).
362
+ */
363
+ const isBranchSelectable = (branch) => {
364
+ if (!branch)
365
+ return false;
366
+ const selectable = branch.pickup_readiness?.selectable;
367
+ return typeof selectable === 'boolean' ? selectable : branch.is_open !== false;
368
+ };
369
+ /** Backend readiness label ("استلمه غدًا", "جاهز {date}") when pickup is not today; null otherwise. */
370
+ const getBranchReadinessLabel = (branch) => {
371
+ const readiness = branch?.pickup_readiness;
372
+ return readiness?.label && ['tomorrow', 'later'].includes(readiness.state) ? readiness.label : null;
373
+ };
374
+ /** Branch-clock "HH:mm" a branch that is closed now becomes ready at later today; null otherwise. */
375
+ const getBranchReadyTodayTime = (branch) => {
376
+ const readiness = branch?.pickup_readiness;
377
+ if (readiness?.state !== 'same_day' || branch?.is_open !== false)
378
+ return null;
379
+ return readiness.ready_at?.match(/T(\d{2}:\d{2})/)?.[1] ?? null;
380
+ };
381
+ /** Busy branches (stock at the merchant's stop-orders threshold) stay listed but dimmed and unselectable. */
382
+ const isBranchBusy = (branch) => branch?.pickup_readiness?.state === 'orders_paused';
383
+ /** Distinct cities of a branch list, in first-seen order (the API lists nearest first). */
384
+ const getBranchCities = (branches) => {
385
+ const seen = new Set();
386
+ const cities = [];
387
+ for (const { city } of branches) {
388
+ if (!city?.id || seen.has(String(city.id)))
389
+ continue;
390
+ seen.add(String(city.id));
391
+ cities.push({ id: city.id, name: city.name });
392
+ }
393
+ return cities;
394
+ };
395
+ /** "3.52" / "12" — at most two decimals, as the checkout picker shows it; '' when the distance is unknown. */
396
+ const formatBranchDistance = (km) => {
397
+ if (km == null || Number.isNaN(Number(km)))
398
+ return '';
399
+ return String(Math.round(Number(km) * 100) / 100);
400
+ };
401
+ /**
402
+ * Readiness states the picker hides outright instead of showing as a disabled card: closed and not
403
+ * taking pickup orders at all. Busy/out-of-stock stay visible-but-disabled so the shopper sees why
404
+ * (same rule as the checkout picker, INV-1414).
405
+ */
406
+ const HIDDEN_READINESS_STATES = ['closed', 'unavailable'];
407
+ const isBranchVisible = (branch) => !!branch && !HIDDEN_READINESS_STATES.includes(branch.pickup_readiness?.state);
408
+ /** The branch's pickup offer (INV-1416); null when it has none, or a zero one, so "خصم 0%" never shows. */
409
+ const getBranchDiscount = (branch) => {
410
+ const type = branch?.discount?.type;
411
+ const amount = Number(branch?.discount?.amount);
412
+ if ((type !== 'percentage' && type !== 'fixed_amount') || !(amount > 0))
413
+ return null;
414
+ return { type, amount };
415
+ };
416
+ /**
417
+ * Min–max pickup offer across the listed branches, for the pickup tab badge; null when none has one.
418
+ * Branches the picker hides are left out so the tab never advertises an offer the shopper can't pick.
419
+ * A percentage and a fixed amount can't share one range, so percentages win when both are set.
420
+ */
421
+ const getBranchDiscountRange = (branches) => {
422
+ const discounts = branches.filter(isBranchVisible).map(getBranchDiscount).filter((d) => !!d);
423
+ if (!discounts.length)
424
+ return null;
425
+ const type = discounts.some(d => d.type === 'percentage') ? 'percentage' : 'fixed_amount';
426
+ const amounts = discounts.filter(d => d.type === type).map(d => d.amount);
427
+ return { type, min: Math.min(...amounts), max: Math.max(...amounts) };
428
+ };
429
+ /** The storefront's working_hours and ready_at use 24h "HH:mm"; null for anything else. */
430
+ const parseBranchTime = (time) => {
431
+ const match = String(time ?? '').trim().match(/^(\d{1,2}):(\d{2})(?::\d{2})?$/);
432
+ if (!match || Number(match[1]) > 24)
433
+ return null;
434
+ return { hours: Number(match[1]) % 24, minutes: Number(match[2]) };
435
+ };
436
+ /** Date#getDay() keys for the day names the storefront API may send (Arabic or English). */
437
+ const DAY_KEYS = {
438
+ sunday: 0, 'الاحد': 0,
439
+ monday: 1, 'الاثنين': 1,
440
+ tuesday: 2, 'الثلاثاء': 2,
441
+ wednesday: 3, 'الاربعاء': 3,
442
+ thursday: 4, 'الخميس': 4,
443
+ friday: 5, 'الجمعة': 5,
444
+ saturday: 6, 'السبت': 6,
445
+ };
446
+ const dayKeyFromName = (name) => DAY_KEYS[String(name ?? '').trim().toLowerCase().replace(/[أإآ]/g, 'ا')];
447
+ /**
448
+ * The storefront's `working_hours` (`{ name, times: [{ from, to }] }`, 24h times) as weekly
449
+ * schedule rows for the hours dropdown.
450
+ */
451
+ const getBranchWeekSchedule = (branch) => (branch.working_hours || [])
452
+ .filter(day => day?.name)
453
+ .map(day => ({
454
+ day_key: dayKeyFromName(day.name),
455
+ day: day.name,
456
+ times: (day.times || []).map(t => ({ start: t.from, end: t.to })),
457
+ }));
458
+ const isBranchAlwaysOpen = (branch) => !!branch.always_open;
459
+ /**
460
+ * "11:00 م" / "11:00 PM". ar-SA's ICU pattern puts the day period first, which the bidi algorithm
461
+ * scrambles inside RTL text, so the parts are joined in a fixed "h:mm period" order instead.
462
+ */
463
+ const formatBranchClockTime = (time, locale) => {
464
+ const parsed = parseBranchTime(time);
465
+ if (!parsed)
466
+ return '';
467
+ const date = new Date(Date.UTC(2000, 0, 1, parsed.hours, parsed.minutes));
468
+ const parts = new Intl.DateTimeFormat(locale === 'ar' ? 'ar-SA-u-nu-latn' : 'en', {
469
+ timeZone: 'UTC',
470
+ hour: '2-digit',
471
+ minute: '2-digit',
472
+ hour12: true,
473
+ }).formatToParts(date);
474
+ const get = (type) => parts.find(p => p.type === type)?.value ?? '';
475
+ return `${get('hour')}:${get('minute')} ${get('dayPeriod')}`;
476
+ };
477
+ const sameTimes = (a, b) => a.length === b.length && a.every((t, i) => t.start === b[i].start && t.end === b[i].end);
478
+ /** Consecutive days with identical hours collapse into one row; the largest groups come first. */
479
+ const groupBranchSchedule = (weekSchedule) => {
480
+ const groups = [];
481
+ const days = [...(weekSchedule || [])].filter(s => s.times?.length).sort((a, b) => (a.day_key ?? 0) - (b.day_key ?? 0));
482
+ for (const day of days) {
483
+ const last = groups[groups.length - 1];
484
+ if (last && day.day_key === last.lastDayKey + 1 && sameTimes(last.times, day.times)) {
485
+ last.days.push(day.day);
486
+ last.lastDayKey = day.day_key;
487
+ }
488
+ else {
489
+ groups.push({ days: [day.day], times: day.times, lastDayKey: day.day_key ?? 0 });
490
+ }
491
+ }
492
+ return groups.sort((a, b) => b.days.length - a.days.length).map(({ days, times }) => ({ days, times }));
493
+ };
494
+ /** Keeps the digits and a leading "+" the merchant typed; drops spaces, dashes and brackets. */
495
+ const cleanPhone = (value) => String(value ?? '').trim().replace(/[^\d+]/g, '');
496
+ const getBranchPhoneHref = (branch) => {
497
+ const phone = cleanPhone(branch.contacts?.phone);
498
+ return phone ? `tel:${phone}` : null;
499
+ };
500
+ /** wa.me wants the international number as bare digits ("+966…" / "00966…" → "966…"). */
501
+ const getBranchWhatsappHref = (branch) => {
502
+ const digits = cleanPhone(branch.contacts?.whatsapp).replace(/^\+/, '').replace(/^00/, '').replace(/\D/g, '');
503
+ return digits ? `https://wa.me/${digits}` : null;
504
+ };
505
+ const getBranchDirectionsHref = (branch) => branch.location?.lat != null && branch.location?.lng != null
506
+ ? `https://www.google.com/maps?q=${branch.location.lat},${branch.location.lng}`
507
+ : null;
508
+ /** Nearest selectable branch by distance; single pass O(n). */
509
+ function findNearestBranch(branches, userLat, userLon) {
510
+ let nearest = null;
511
+ let minD = Number.POSITIVE_INFINITY;
512
+ for (const b of branches) {
513
+ const lat = b.location?.lat != null ? Number(b.location.lat) : Number.NaN;
514
+ const lng = b.location?.lng != null ? Number(b.location.lng) : Number.NaN;
515
+ // Closed branches that still take orders are selectable too, so gate on selectability, not is_open.
516
+ if (Number.isNaN(lat) || Number.isNaN(lng) || !isBranchSelectable(b))
517
+ continue;
518
+ const d = calculateDistance(userLat, userLon, lat, lng);
519
+ if (d < minD) {
520
+ minD = d;
521
+ nearest = b;
522
+ }
523
+ }
524
+ return nearest;
525
+ }
526
+ /** Matches the fields the branches API searches: branch, city and country names (either language). */
527
+ const filterBranches = (branches, searchQuery) => {
528
+ if (!searchQuery)
529
+ return branches;
530
+ const q = searchQuery.toLowerCase();
531
+ return branches.filter((b) => [b.name, b.city?.name, b.city?.name_en, b.country?.name, b.country?.name_en].some((name) => name?.toLowerCase().includes(q)));
532
+ };
533
+ const getIntentSubtitle = (intent, toAddress, fromBranch) => {
534
+ if (intent.type === 'branch') {
535
+ const loc = [intent.branch_details?.country, intent.branch_details?.city, intent.branch_details?.district].filter(Boolean).join('، ');
536
+ return loc ? `${fromBranch} ${loc}`.trim() : '';
537
+ }
538
+ if (intent.type === 'address' && intent.address_details) {
539
+ const addr = [intent.address_details.country?.name, intent.address_details.city?.name, intent.address_details.district?.name].filter(Boolean).join('، ') || intent.address_details.short_address || '';
540
+ return addr ? `${toAddress} ${addr}`.trim() : '';
541
+ }
542
+ return '';
543
+ };
544
+ const idFrom = (val) => (val != null ? Number(val) : undefined);
545
+ const getIntentCountryId = (i) => idFrom(i?.address_details?.country?.id);
546
+ const getIntentCountryCode = (i) => i?.country_code ?? i?.address_details?.country?.code ?? '';
547
+ const getIntentRegionId = (i) => idFrom(i?.address_details?.region?.id);
548
+ const getIntentCityId = (i) => idFrom(i?.address_details?.city?.id);
549
+ const getIntentDistrictId = (i) => idFrom(i?.address_details?.district?.id);
550
+ const getIntentBranchId = (i) => i?.branch_details?.id;
551
+ const isMapOriginIntent = (i) => !!i && i.type === 'address' && i.address_details?.lat != null && i.address_details?.lng != null;
552
+ const hasSessionAddressIntent = (intent) => {
553
+ if (!intent || intent.type !== 'address' || intent.address_id)
554
+ return false;
555
+ if (isMapOriginIntent(intent))
556
+ return true;
557
+ const c = getIntentCountryId(intent);
558
+ const city = getIntentCityId(intent);
559
+ const d = getIntentDistrictId(intent);
560
+ const code = getIntentCountryCode(intent);
561
+ const hasDistrictId = d != null && Number(d) !== 0;
562
+ const hasDistrictName = Boolean(intent.address_details?.district?.name?.trim());
563
+ const districtOk = !isSaudiArabia(code) || hasDistrictId || hasDistrictName;
564
+ return !!(c && city && districtOk);
565
+ };
566
+ const requireRegionAndDistrictForSA = (countryCode, regionId, districtIdOrName) => !countryCode || !isSaudiArabia(countryCode)
567
+ ? true
568
+ : (regionId != null && Number(regionId) !== 0) && (districtIdOrName != null && (typeof districtIdOrName === 'number' ? districtIdOrName !== 0 : String(districtIdOrName).trim().length > 0));
569
+
570
+ exports.CACHE_TTL = CACHE_TTL;
571
+ exports.bulletDeliveryAPI = bulletDeliveryAPI;
572
+ exports.clearApiCache = clearApiCache;
573
+ exports.clearBranchCache = clearBranchCache;
574
+ exports.filterBranches = filterBranches;
575
+ exports.findNearestBranch = findNearestBranch;
576
+ exports.formatBranchClockTime = formatBranchClockTime;
577
+ exports.formatBranchDistance = formatBranchDistance;
578
+ exports.getBranchCities = getBranchCities;
579
+ exports.getBranchDirectionsHref = getBranchDirectionsHref;
580
+ exports.getBranchDiscount = getBranchDiscount;
581
+ exports.getBranchDiscountRange = getBranchDiscountRange;
582
+ exports.getBranchPhoneHref = getBranchPhoneHref;
583
+ exports.getBranchReadinessLabel = getBranchReadinessLabel;
584
+ exports.getBranchReadyTodayTime = getBranchReadyTodayTime;
585
+ exports.getBranchWeekSchedule = getBranchWeekSchedule;
586
+ exports.getBranchWhatsappHref = getBranchWhatsappHref;
587
+ exports.getIntentBranchId = getIntentBranchId;
588
+ exports.getIntentCityId = getIntentCityId;
589
+ exports.getIntentCountryCode = getIntentCountryCode;
590
+ exports.getIntentCountryId = getIntentCountryId;
591
+ exports.getIntentDistrictId = getIntentDistrictId;
592
+ exports.getIntentRegionId = getIntentRegionId;
593
+ exports.getIntentSubtitle = getIntentSubtitle;
594
+ exports.groupBranchSchedule = groupBranchSchedule;
595
+ exports.hasSessionAddressIntent = hasSessionAddressIntent;
596
+ exports.isBranchAlwaysOpen = isBranchAlwaysOpen;
597
+ exports.isBranchBusy = isBranchBusy;
598
+ exports.isBranchSelectable = isBranchSelectable;
599
+ exports.isBranchVisible = isBranchVisible;
600
+ exports.isMapOriginIntent = isMapOriginIntent;
601
+ exports.isSaudiArabia = isSaudiArabia;
602
+ exports.requireRegionAndDistrictForSA = requireRegionAndDistrictForSA;