@salla.sa/twilight-theme-engine 1.0.95 → 1.0.97

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 (354) hide show
  1. package/dist/{AddToCartForm-6M57VCZU.js → AddToCartForm-OV4OJ6ZI.js} +3 -3
  2. package/dist/{AddToCartForm-6M57VCZU.js.map → AddToCartForm-OV4OJ6ZI.js.map} +1 -1
  3. package/dist/{BlogAuthorPage-F6RKZEXT.js → BlogAuthorPage-RFJMRGTW.js} +26 -24
  4. package/dist/BlogAuthorPage-RFJMRGTW.js.map +1 -0
  5. package/dist/{BlogCategoryPage-TMADZWDK.js → BlogCategoryPage-UB27VWXE.js} +26 -24
  6. package/dist/BlogCategoryPage-UB27VWXE.js.map +1 -0
  7. package/dist/{BlogPage-KUNTYL2L.js → BlogPage-E6SWRULY.js} +24 -22
  8. package/dist/BlogPage-E6SWRULY.js.map +1 -0
  9. package/dist/{BlogSinglePage-JCI5KX6K.js → BlogSinglePage-SFQRA6EC.js} +24 -22
  10. package/dist/BlogSinglePage-SFQRA6EC.js.map +1 -0
  11. package/dist/{BlogTagPage-6IC6HRXA.js → BlogTagPage-UQ7AG7IY.js} +26 -24
  12. package/dist/BlogTagPage-UQ7AG7IY.js.map +1 -0
  13. package/dist/{BrandsPage-CK7LZ4ZR.js → BrandsPage-54TYVIIH.js} +25 -23
  14. package/dist/BrandsPage-54TYVIIH.js.map +1 -0
  15. package/dist/{Breadcrumb-5RWSAJKQ.js → Breadcrumb-5PRKPMLH.js} +24 -22
  16. package/dist/Breadcrumb-5PRKPMLH.js.map +1 -0
  17. package/dist/{CartItem-AEIRNYUK.js → CartItem-YYZHPLOW.js} +24 -22
  18. package/dist/CartItem-YYZHPLOW.js.map +1 -0
  19. package/dist/{CartSummary-WCQL3GV5.js → CartSummary-55QHAA2D.js} +24 -22
  20. package/dist/CartSummary-55QHAA2D.js.map +1 -0
  21. package/dist/{Copyright-HRQKNNC3.js → Copyright-M5PLSEJB.js} +3 -3
  22. package/dist/{Copyright-HRQKNNC3.js.map → Copyright-M5PLSEJB.js.map} +1 -1
  23. package/dist/{CustomerLayout-ET4OD3VV.js → CustomerLayout-5SAJUVCD.js} +24 -22
  24. package/dist/CustomerLayout-5SAJUVCD.js.map +1 -0
  25. package/dist/{Footer-N2DCHQMO.js → Footer-APIPC5PU.js} +4 -4
  26. package/dist/{Footer-N2DCHQMO.js.map → Footer-APIPC5PU.js.map} +1 -1
  27. package/dist/Header-5DTS6TVG.js +22 -0
  28. package/dist/{Header-SGRINHMD.js.map → Header-5DTS6TVG.js.map} +1 -1
  29. package/dist/{LoyaltyPage-FLTNW6G3.js → LoyaltyPage-AUOTLLDU.js} +24 -22
  30. package/dist/LoyaltyPage-AUOTLLDU.js.map +1 -0
  31. package/dist/{LoyaltyPointsPage-W4QU4RDU.js → LoyaltyPointsPage-QS74LPGZ.js} +8 -7
  32. package/dist/LoyaltyPointsPage-QS74LPGZ.js.map +1 -0
  33. package/dist/{MainMenu-D5CFVBNQ.js → MainMenu-CF6EYHYR.js} +7 -6
  34. package/dist/MainMenu-CF6EYHYR.js.map +1 -0
  35. package/dist/{MasterLayout-DKUMEBDQ.js → MasterLayout-UQ6UJIS2.js} +24 -22
  36. package/dist/{MasterLayout-DKUMEBDQ.js.map → MasterLayout-UQ6UJIS2.js.map} +1 -1
  37. package/dist/{MobileMenu-3LCM35WP.js → MobileMenu-Y3IEUQD7.js} +25 -23
  38. package/dist/MobileMenu-Y3IEUQD7.js.map +1 -0
  39. package/dist/{NotificationsPage-KJ6WDEVH.js → NotificationsPage-LTTYF45A.js} +24 -22
  40. package/dist/NotificationsPage-LTTYF45A.js.map +1 -0
  41. package/dist/{OrderSinglePage-H6TGX43N.js → OrderSinglePage-RG5GJQ7H.js} +25 -23
  42. package/dist/OrderSinglePage-RG5GJQ7H.js.map +1 -0
  43. package/dist/{OrdersPage-BEBXUZGC.js → OrdersPage-ILD4GC4Q.js} +24 -22
  44. package/dist/OrdersPage-ILD4GC4Q.js.map +1 -0
  45. package/dist/{PageSingle-P5PI65M5.js → PageSingle-5QJOHIFO.js} +6 -5
  46. package/dist/PageSingle-5QJOHIFO.js.map +1 -0
  47. package/dist/{ProductDetails-PWS4VZWO.js → ProductDetails-ASAPGMTN.js} +7 -6
  48. package/dist/ProductDetails-ASAPGMTN.js.map +1 -0
  49. package/dist/{ProfilePage-25NC72CQ.js → ProfilePage-4GPD5OJA.js} +24 -22
  50. package/dist/ProfilePage-4GPD5OJA.js.map +1 -0
  51. package/dist/{RenderWhenVisible-F44J5MMG.js → RenderWhenVisible-KWAXEJOJ.js} +8 -5
  52. package/dist/RenderWhenVisible-KWAXEJOJ.js.map +1 -0
  53. package/dist/{ReviewsPage-JQJEEKR3.js → ReviewsPage-VZX65JNB.js} +3 -3
  54. package/dist/{ReviewsPage-JQJEEKR3.js.map → ReviewsPage-VZX65JNB.js.map} +1 -1
  55. package/dist/{SeoCartWidget-A7MCWGQ2.js → SeoCartWidget-5W42B33H.js} +24 -22
  56. package/dist/SeoCartWidget-5W42B33H.js.map +1 -0
  57. package/dist/{SettingsPage-6W32UA32.js → SettingsPage-AIHWRJXR.js} +24 -22
  58. package/dist/SettingsPage-AIHWRJXR.js.map +1 -0
  59. package/dist/{StoreClosedNotification-B3MQFPFY.js → StoreClosedNotification-N3RS2Y6Q.js} +25 -23
  60. package/dist/{StoreClosedNotification-B3MQFPFY.js.map → StoreClosedNotification-N3RS2Y6Q.js.map} +1 -1
  61. package/dist/{TestimonialsPage-MDYX65Z3.js → TestimonialsPage-TLHRLY4O.js} +6 -5
  62. package/dist/TestimonialsPage-TLHRLY4O.js.map +1 -0
  63. package/dist/{ThankYouPage-AFJCN3AH.js → ThankYouPage-BXDQRBQW.js} +24 -22
  64. package/dist/ThankYouPage-BXDQRBQW.js.map +1 -0
  65. package/dist/{WalletPage-S6S5ZV3A.js → WalletPage-Q3HSJ6DX.js} +25 -23
  66. package/dist/WalletPage-Q3HSJ6DX.js.map +1 -0
  67. package/dist/{WishlistPage-YH4OQPXP.js → WishlistPage-TZ7NZX4K.js} +26 -24
  68. package/dist/WishlistPage-TZ7NZX4K.js.map +1 -0
  69. package/dist/ambient/virtual-modules.d.ts +43 -1
  70. package/dist/api/advertisement.js +4 -3
  71. package/dist/api/apps.js +4 -3
  72. package/dist/api/blog.js +6 -5
  73. package/dist/api/brands.js +6 -5
  74. package/dist/api/cart.js +6 -5
  75. package/dist/api/category.js +6 -5
  76. package/dist/api/client.js +3 -2
  77. package/dist/api/home.js +4 -3
  78. package/dist/api/loyalty.js +6 -5
  79. package/dist/api/menu.js +4 -3
  80. package/dist/api/notification.js +4 -3
  81. package/dist/api/order.js +6 -5
  82. package/dist/api/page.js +6 -5
  83. package/dist/api/product.js +6 -5
  84. package/dist/api/profile.js +3 -2
  85. package/dist/api/profile.js.map +1 -1
  86. package/dist/api/store.js +4 -3
  87. package/dist/api/translations.js +4 -3
  88. package/dist/api/user.js +4 -3
  89. package/dist/api/wallet.js +4 -3
  90. package/dist/api/wishlist.js +7 -6
  91. package/dist/{chunk-HQAFPDJK.js → chunk-2FDLEB5J.js} +3 -3
  92. package/dist/{chunk-HQAFPDJK.js.map → chunk-2FDLEB5J.js.map} +1 -1
  93. package/dist/chunk-2FKZAAV7.js +90 -0
  94. package/dist/chunk-2FKZAAV7.js.map +1 -0
  95. package/dist/{chunk-ZTXEXO4W.js → chunk-4P77DKHC.js} +7 -7
  96. package/dist/{chunk-ZTXEXO4W.js.map → chunk-4P77DKHC.js.map} +1 -1
  97. package/dist/{chunk-CEYT3JER.js → chunk-56T47K7P.js} +4 -4
  98. package/dist/{chunk-CEYT3JER.js.map → chunk-56T47K7P.js.map} +1 -1
  99. package/dist/{chunk-LPQ5FUMJ.js → chunk-5SDCUGYR.js} +4 -4
  100. package/dist/{chunk-LPQ5FUMJ.js.map → chunk-5SDCUGYR.js.map} +1 -1
  101. package/dist/{chunk-QGOPTVV5.js → chunk-6EQ7G3SZ.js} +4 -3
  102. package/dist/chunk-6EQ7G3SZ.js.map +1 -0
  103. package/dist/{chunk-FZYR4BA2.js → chunk-7WTUA4WY.js} +3 -3
  104. package/dist/{chunk-FZYR4BA2.js.map → chunk-7WTUA4WY.js.map} +1 -1
  105. package/dist/{chunk-3PXONLUK.js → chunk-BH7YNCYB.js} +3 -3
  106. package/dist/{chunk-3PXONLUK.js.map → chunk-BH7YNCYB.js.map} +1 -1
  107. package/dist/{chunk-DBW7XXNE.js → chunk-BPL5H33B.js} +4 -4
  108. package/dist/{chunk-DBW7XXNE.js.map → chunk-BPL5H33B.js.map} +1 -1
  109. package/dist/{chunk-66K5P5ZX.js → chunk-CNUBL24W.js} +3 -3
  110. package/dist/{chunk-66K5P5ZX.js.map → chunk-CNUBL24W.js.map} +1 -1
  111. package/dist/chunk-COJH52VR.js +443 -0
  112. package/dist/chunk-COJH52VR.js.map +1 -0
  113. package/dist/{chunk-6OOTDFC7.js → chunk-D56TVNOG.js} +3 -3
  114. package/dist/{chunk-6OOTDFC7.js.map → chunk-D56TVNOG.js.map} +1 -1
  115. package/dist/{chunk-N6OPDLCU.js → chunk-DMOXGVMT.js} +13 -12
  116. package/dist/chunk-DMOXGVMT.js.map +1 -0
  117. package/dist/{chunk-Y7XVWQXG.js → chunk-DNPQ2JBM.js} +4 -4
  118. package/dist/{chunk-Y7XVWQXG.js.map → chunk-DNPQ2JBM.js.map} +1 -1
  119. package/dist/{chunk-JJARU7YP.js → chunk-EWLVLDRP.js} +3 -3
  120. package/dist/{chunk-JJARU7YP.js.map → chunk-EWLVLDRP.js.map} +1 -1
  121. package/dist/{chunk-J47OCHM7.js → chunk-EXREO7W6.js} +20 -19
  122. package/dist/chunk-EXREO7W6.js.map +1 -0
  123. package/dist/{chunk-HSWRYXC7.js → chunk-FO4WVGUQ.js} +3 -88
  124. package/dist/chunk-FO4WVGUQ.js.map +1 -0
  125. package/dist/{chunk-FCTL7IV6.js → chunk-FXIX4O3Q.js} +3 -3
  126. package/dist/{chunk-FCTL7IV6.js.map → chunk-FXIX4O3Q.js.map} +1 -1
  127. package/dist/{chunk-BNI6SKFL.js → chunk-G3UTLICK.js} +4 -4
  128. package/dist/{chunk-BNI6SKFL.js.map → chunk-G3UTLICK.js.map} +1 -1
  129. package/dist/{chunk-C4RXPVDF.js → chunk-GMXI6V2D.js} +6 -5
  130. package/dist/chunk-GMXI6V2D.js.map +1 -0
  131. package/dist/{chunk-RKQH63G2.js → chunk-GXHJXZBG.js} +4 -4
  132. package/dist/{chunk-RKQH63G2.js.map → chunk-GXHJXZBG.js.map} +1 -1
  133. package/dist/{chunk-43D2CG4F.js → chunk-IBSQO6LW.js} +4 -4
  134. package/dist/{chunk-43D2CG4F.js.map → chunk-IBSQO6LW.js.map} +1 -1
  135. package/dist/{chunk-ZVZGLEZ6.js → chunk-IU4KTCS3.js} +3 -3
  136. package/dist/{chunk-ZVZGLEZ6.js.map → chunk-IU4KTCS3.js.map} +1 -1
  137. package/dist/{chunk-ENJ3CM5M.js → chunk-J5X4LXNM.js} +3 -3
  138. package/dist/{chunk-ENJ3CM5M.js.map → chunk-J5X4LXNM.js.map} +1 -1
  139. package/dist/{chunk-4WAUITU2.js → chunk-KNIGLCRV.js} +3 -3
  140. package/dist/{chunk-4WAUITU2.js.map → chunk-KNIGLCRV.js.map} +1 -1
  141. package/dist/{chunk-IR47RORL.js → chunk-M63VKFWB.js} +7 -7
  142. package/dist/{chunk-IR47RORL.js.map → chunk-M63VKFWB.js.map} +1 -1
  143. package/dist/chunk-N45X7D55.js +63 -0
  144. package/dist/chunk-N45X7D55.js.map +1 -0
  145. package/dist/{chunk-OH2L4U2C.js → chunk-NZRJOAA7.js} +3 -3
  146. package/dist/{chunk-OH2L4U2C.js.map → chunk-NZRJOAA7.js.map} +1 -1
  147. package/dist/{chunk-TEOVJ6WU.js → chunk-O7B5JL6H.js} +4 -4
  148. package/dist/{chunk-TEOVJ6WU.js.map → chunk-O7B5JL6H.js.map} +1 -1
  149. package/dist/{chunk-RNCISHJT.js → chunk-O7U7O434.js} +8 -7
  150. package/dist/chunk-O7U7O434.js.map +1 -0
  151. package/dist/{chunk-UURVAJ42.js → chunk-OZP2FID7.js} +4 -4
  152. package/dist/{chunk-UURVAJ42.js.map → chunk-OZP2FID7.js.map} +1 -1
  153. package/dist/{chunk-HCA2TE4G.js → chunk-PGUKRWOY.js} +5 -5
  154. package/dist/{chunk-HCA2TE4G.js.map → chunk-PGUKRWOY.js.map} +1 -1
  155. package/dist/{chunk-3MIFT4VQ.js → chunk-Q62YEBIA.js} +4 -4
  156. package/dist/{chunk-3MIFT4VQ.js.map → chunk-Q62YEBIA.js.map} +1 -1
  157. package/dist/{chunk-6DMNJPLW.js → chunk-QS4EDTEX.js} +3 -3
  158. package/dist/{chunk-6DMNJPLW.js.map → chunk-QS4EDTEX.js.map} +1 -1
  159. package/dist/{chunk-H64QXA6N.js → chunk-QWYXFQUZ.js} +4 -4
  160. package/dist/{chunk-H64QXA6N.js.map → chunk-QWYXFQUZ.js.map} +1 -1
  161. package/dist/{chunk-SAGXF3MU.js → chunk-QZEQOVA5.js} +3 -3
  162. package/dist/{chunk-SAGXF3MU.js.map → chunk-QZEQOVA5.js.map} +1 -1
  163. package/dist/{chunk-JTOVO3ZU.js → chunk-RWBTMHLR.js} +5 -5
  164. package/dist/{chunk-JTOVO3ZU.js.map → chunk-RWBTMHLR.js.map} +1 -1
  165. package/dist/{chunk-DV6SJHL5.js → chunk-S34G5DL4.js} +4 -4
  166. package/dist/{chunk-DV6SJHL5.js.map → chunk-S34G5DL4.js.map} +1 -1
  167. package/dist/{chunk-MKVCFBVF.js → chunk-TIPR4JUO.js} +4 -4
  168. package/dist/{chunk-MKVCFBVF.js.map → chunk-TIPR4JUO.js.map} +1 -1
  169. package/dist/{chunk-UOQR643Q.js → chunk-UUFUJZFE.js} +4 -4
  170. package/dist/{chunk-UOQR643Q.js.map → chunk-UUFUJZFE.js.map} +1 -1
  171. package/dist/{chunk-IVBOLREE.js → chunk-VWVCSD3N.js} +3 -3
  172. package/dist/{chunk-IVBOLREE.js.map → chunk-VWVCSD3N.js.map} +1 -1
  173. package/dist/{chunk-5G7NYNX6.js → chunk-W2LNKEBF.js} +3 -3
  174. package/dist/{chunk-5G7NYNX6.js.map → chunk-W2LNKEBF.js.map} +1 -1
  175. package/dist/{chunk-LV6J5FMT.js → chunk-W7K4IFI3.js} +20 -17
  176. package/dist/chunk-W7K4IFI3.js.map +1 -0
  177. package/dist/chunk-WRLEZ2WR.js +14 -0
  178. package/dist/{chunk-7GBNI3AU.js.map → chunk-WRLEZ2WR.js.map} +1 -1
  179. package/dist/{chunk-QFS2SHJ4.js → chunk-X52JCIUM.js} +7 -7
  180. package/dist/{chunk-QFS2SHJ4.js.map → chunk-X52JCIUM.js.map} +1 -1
  181. package/dist/{chunk-46NBPXAI.js → chunk-XT6CLGF5.js} +3 -3
  182. package/dist/{chunk-46NBPXAI.js.map → chunk-XT6CLGF5.js.map} +1 -1
  183. package/dist/{chunk-6ELXANJG.js → chunk-YFAZT6XB.js} +4 -4
  184. package/dist/{chunk-6ELXANJG.js.map → chunk-YFAZT6XB.js.map} +1 -1
  185. package/dist/{chunk-DTS3AGXT.js → chunk-Z7N242DF.js} +9 -8
  186. package/dist/chunk-Z7N242DF.js.map +1 -0
  187. package/dist/{chunk-SFZ7IIWL.js → chunk-ZEGNYJOR.js} +4 -4
  188. package/dist/{chunk-SFZ7IIWL.js.map → chunk-ZEGNYJOR.js.map} +1 -1
  189. package/dist/components/cart/index.js +1 -1
  190. package/dist/components/common/RenderWhenVisible.d.ts +3 -1
  191. package/dist/components/common/RenderWhenVisible.d.ts.map +1 -1
  192. package/dist/components/common/index.js +1 -1
  193. package/dist/components/common/lazy.d.ts +1 -1
  194. package/dist/components/common/lazy.d.ts.map +1 -1
  195. package/dist/components/drawer/index.js +22 -20
  196. package/dist/components/home/HomePageRenderer.d.ts.map +1 -1
  197. package/dist/components/home/index.js +26 -24
  198. package/dist/components/layout/index.js +6 -5
  199. package/dist/components/product/ProductGallery.d.ts.map +1 -1
  200. package/dist/components/product/index.js +23 -21
  201. package/dist/components/store/index.js +24 -22
  202. package/dist/components/store/index.js.map +1 -1
  203. package/dist/components/toast/index.js +4 -3
  204. package/dist/components/toast/index.js.map +1 -1
  205. package/dist/components/tracking/index.js +1 -1
  206. package/dist/dev/DevSettingsWidget.d.ts +6 -7
  207. package/dist/dev/DevSettingsWidget.d.ts.map +1 -1
  208. package/dist/dev/dev-settings-store.d.ts +89 -46
  209. package/dist/dev/dev-settings-store.d.ts.map +1 -1
  210. package/dist/dev/editor/AddElementDrawer.d.ts +17 -0
  211. package/dist/dev/editor/AddElementDrawer.d.ts.map +1 -0
  212. package/dist/dev/editor/BuilderPanel.d.ts +23 -0
  213. package/dist/dev/editor/BuilderPanel.d.ts.map +1 -0
  214. package/dist/dev/editor/SettingsPanel.d.ts +9 -0
  215. package/dist/dev/editor/SettingsPanel.d.ts.map +1 -0
  216. package/dist/dev/editor/ThemeEditor.d.ts +20 -0
  217. package/dist/dev/editor/ThemeEditor.d.ts.map +1 -0
  218. package/dist/dev/editor/catalog.d.ts +10 -0
  219. package/dist/dev/editor/catalog.d.ts.map +1 -0
  220. package/dist/dev/editor/fields.d.ts +18 -0
  221. package/dist/dev/editor/fields.d.ts.map +1 -0
  222. package/dist/dev/editor/i18n.d.ts +72 -0
  223. package/dist/dev/editor/i18n.d.ts.map +1 -0
  224. package/dist/dev/editor/icons.d.ts +21 -0
  225. package/dist/dev/editor/icons.d.ts.map +1 -0
  226. package/dist/dev/editor/index.d.ts +8 -0
  227. package/dist/dev/editor/index.d.ts.map +1 -0
  228. package/dist/dev/editor/index.js +2059 -0
  229. package/dist/dev/editor/index.js.map +1 -0
  230. package/dist/dev/editor/lookup.d.ts +22 -0
  231. package/dist/dev/editor/lookup.d.ts.map +1 -0
  232. package/dist/dev/editor/mount.d.ts +4 -0
  233. package/dist/dev/editor/mount.d.ts.map +1 -0
  234. package/dist/dev/editor/paths.d.ts +44 -0
  235. package/dist/dev/editor/paths.d.ts.map +1 -0
  236. package/dist/dev/editor/pickers.d.ts +12 -0
  237. package/dist/dev/editor/pickers.d.ts.map +1 -0
  238. package/dist/dev/editor/styles.d.ts +8 -0
  239. package/dist/dev/editor/styles.d.ts.map +1 -0
  240. package/dist/dev/index.d.ts +1 -1
  241. package/dist/dev/index.d.ts.map +1 -1
  242. package/dist/dev/index.js +35 -309
  243. package/dist/dev/index.js.map +1 -1
  244. package/dist/dev/schema-types.d.ts +124 -4
  245. package/dist/dev/schema-types.d.ts.map +1 -1
  246. package/dist/dev/store-lookup.d.ts +13 -0
  247. package/dist/dev/store-lookup.d.ts.map +1 -0
  248. package/dist/document-class-3QOJVTQL.js +29 -0
  249. package/dist/{document-class-BRRNAIKV.js.map → document-class-3QOJVTQL.js.map} +1 -1
  250. package/dist/hooks/index.js +22 -20
  251. package/dist/hooks/useComments.js +3 -2
  252. package/dist/hooks/useGtm.js +22 -20
  253. package/dist/hooks/useMoney.js +22 -20
  254. package/dist/hooks/useProduct.js +3 -2
  255. package/dist/hooks/useStore.js +22 -20
  256. package/dist/hooks/useUser.js +5 -4
  257. package/dist/hooks/useWishlist.js +3 -2
  258. package/dist/index.js +22 -20
  259. package/dist/index.js.map +1 -1
  260. package/dist/native-app/index.js +3 -2
  261. package/dist/{navigation-KTFJWOWI.js → navigation-JB2CJXBF.js} +7 -6
  262. package/dist/navigation-JB2CJXBF.js.map +1 -0
  263. package/dist/navigation-KTMLD4VB.js +14 -0
  264. package/dist/{navigation-BARZWXJZ.js.map → navigation-KTMLD4VB.js.map} +1 -1
  265. package/dist/{not-found-VJDPMT6N.js → not-found-XVRNO2WE.js} +25 -23
  266. package/dist/not-found-XVRNO2WE.js.map +1 -0
  267. package/dist/providers/index.js +22 -20
  268. package/dist/routes/account/orders.js +7 -6
  269. package/dist/routes/account.js +16 -15
  270. package/dist/routes/account.js.map +1 -1
  271. package/dist/routes/blog.js +11 -10
  272. package/dist/routes/blog.js.map +1 -1
  273. package/dist/routes/brands.js +7 -6
  274. package/dist/routes/brands.js.map +1 -1
  275. package/dist/routes/cart.js +30 -28
  276. package/dist/routes/cart.js.map +1 -1
  277. package/dist/routes/home/HomePage.d.ts.map +1 -1
  278. package/dist/routes/home.js +27 -25
  279. package/dist/routes/index.js +6 -5
  280. package/dist/routes/loyalty.js +8 -7
  281. package/dist/routes/loyalty.js.map +1 -1
  282. package/dist/routes/page.js +7 -6
  283. package/dist/routes/page.js.map +1 -1
  284. package/dist/routes/product-listing.js +28 -26
  285. package/dist/routes/product-listing.js.map +1 -1
  286. package/dist/routes/product.js +26 -24
  287. package/dist/routes/product.js.map +1 -1
  288. package/dist/routes/seo-redirects.js +6 -5
  289. package/dist/routes/testimonials.js +2 -2
  290. package/dist/routes/thank-you.js +7 -6
  291. package/dist/routes/thank-you.js.map +1 -1
  292. package/dist/skeleton.js +27 -25
  293. package/dist/store-lookup-T4TK7CKA.js +114 -0
  294. package/dist/store-lookup-T4TK7CKA.js.map +1 -0
  295. package/dist/tanstack.js +17 -16
  296. package/dist/tanstack.js.map +1 -1
  297. package/dist/types/salla-sdk.d.ts +7 -0
  298. package/dist/types/salla-sdk.d.ts.map +1 -1
  299. package/dist/utils/index.js +6 -5
  300. package/dist/utils/index.js.map +1 -1
  301. package/dist/vite/index.js +415 -23
  302. package/dist/vite/index.js.map +1 -1
  303. package/dist/vite/plugins/twilight-schema.d.ts +7 -2
  304. package/dist/vite/plugins/twilight-schema.d.ts.map +1 -1
  305. package/dist/vite/plugins/twilight-schema.plugin.d.ts +26 -0
  306. package/dist/vite/plugins/twilight-schema.plugin.d.ts.map +1 -1
  307. package/package.json +5 -1
  308. package/tailwind/components/common/RenderWhenVisible.tsx.txt +9 -2
  309. package/tailwind/components/home/HomePageRenderer.tsx.txt +2 -0
  310. package/tailwind/components/product/ProductGallery.tsx.txt +19 -10
  311. package/tailwind/routes/home/HomePage.tsx.txt +7 -6
  312. package/dist/BlogAuthorPage-F6RKZEXT.js.map +0 -1
  313. package/dist/BlogCategoryPage-TMADZWDK.js.map +0 -1
  314. package/dist/BlogPage-KUNTYL2L.js.map +0 -1
  315. package/dist/BlogSinglePage-JCI5KX6K.js.map +0 -1
  316. package/dist/BlogTagPage-6IC6HRXA.js.map +0 -1
  317. package/dist/BrandsPage-CK7LZ4ZR.js.map +0 -1
  318. package/dist/Breadcrumb-5RWSAJKQ.js.map +0 -1
  319. package/dist/CartItem-AEIRNYUK.js.map +0 -1
  320. package/dist/CartSummary-WCQL3GV5.js.map +0 -1
  321. package/dist/CustomerLayout-ET4OD3VV.js.map +0 -1
  322. package/dist/Header-SGRINHMD.js +0 -21
  323. package/dist/LoyaltyPage-FLTNW6G3.js.map +0 -1
  324. package/dist/LoyaltyPointsPage-W4QU4RDU.js.map +0 -1
  325. package/dist/MainMenu-D5CFVBNQ.js.map +0 -1
  326. package/dist/MobileMenu-3LCM35WP.js.map +0 -1
  327. package/dist/NotificationsPage-KJ6WDEVH.js.map +0 -1
  328. package/dist/OrderSinglePage-H6TGX43N.js.map +0 -1
  329. package/dist/OrdersPage-BEBXUZGC.js.map +0 -1
  330. package/dist/PageSingle-P5PI65M5.js.map +0 -1
  331. package/dist/ProductDetails-PWS4VZWO.js.map +0 -1
  332. package/dist/ProfilePage-25NC72CQ.js.map +0 -1
  333. package/dist/RenderWhenVisible-F44J5MMG.js.map +0 -1
  334. package/dist/SeoCartWidget-A7MCWGQ2.js.map +0 -1
  335. package/dist/SettingsPage-6W32UA32.js.map +0 -1
  336. package/dist/TestimonialsPage-MDYX65Z3.js.map +0 -1
  337. package/dist/ThankYouPage-AFJCN3AH.js.map +0 -1
  338. package/dist/WalletPage-S6S5ZV3A.js.map +0 -1
  339. package/dist/WishlistPage-YH4OQPXP.js.map +0 -1
  340. package/dist/chunk-2JV6WZ6O.js +0 -136
  341. package/dist/chunk-2JV6WZ6O.js.map +0 -1
  342. package/dist/chunk-7GBNI3AU.js +0 -14
  343. package/dist/chunk-C4RXPVDF.js.map +0 -1
  344. package/dist/chunk-DTS3AGXT.js.map +0 -1
  345. package/dist/chunk-HSWRYXC7.js.map +0 -1
  346. package/dist/chunk-J47OCHM7.js.map +0 -1
  347. package/dist/chunk-LV6J5FMT.js.map +0 -1
  348. package/dist/chunk-N6OPDLCU.js.map +0 -1
  349. package/dist/chunk-QGOPTVV5.js.map +0 -1
  350. package/dist/chunk-RNCISHJT.js.map +0 -1
  351. package/dist/document-class-BRRNAIKV.js +0 -28
  352. package/dist/navigation-BARZWXJZ.js +0 -13
  353. package/dist/navigation-KTFJWOWI.js.map +0 -1
  354. package/dist/not-found-VJDPMT6N.js.map +0 -1
@@ -0,0 +1,90 @@
1
+ import { resolveStoreIdentifier } from './chunk-FO4WVGUQ.js';
2
+
3
+ // src/utils/sdk-helpers.ts
4
+ var isBrowser = typeof window !== "undefined";
5
+ function getStoreIdentifier(explicit) {
6
+ return resolveStoreIdentifier(explicit);
7
+ }
8
+ function getSallaSDK() {
9
+ if (!isBrowser) return void 0;
10
+ return window.salla;
11
+ }
12
+ var SDK_CREATED_EVENT = "salla::created";
13
+ var noop = () => {
14
+ };
15
+ function isLoaded(sdk) {
16
+ return typeof sdk?.init === "function" || typeof sdk?.event?.on === "function";
17
+ }
18
+ function hasEventBus(sdk) {
19
+ return typeof sdk?.event?.on === "function";
20
+ }
21
+ function whenSallaLoaded(callback) {
22
+ return whenSalla(isLoaded, callback);
23
+ }
24
+ function whenSalla(isUsable, callback) {
25
+ if (!isBrowser) return noop;
26
+ if (isUsable(window.salla)) {
27
+ callback(window.salla);
28
+ return noop;
29
+ }
30
+ let settled = false;
31
+ const onCreated = () => {
32
+ const sdk = window.salla;
33
+ if (settled || !isUsable(sdk)) return;
34
+ settled = true;
35
+ window.removeEventListener(SDK_CREATED_EVENT, onCreated);
36
+ callback(sdk);
37
+ };
38
+ window.addEventListener(SDK_CREATED_EVENT, onCreated);
39
+ return () => {
40
+ settled = true;
41
+ window.removeEventListener(SDK_CREATED_EVENT, onCreated);
42
+ };
43
+ }
44
+ function whenSallaReady(callback) {
45
+ let cancelled = false;
46
+ const cancel = whenSallaLoaded((sdk) => {
47
+ void new Promise((resolve) => resolve(sdk.onReady?.())).catch(noop).then(() => {
48
+ if (!cancelled) callback(sdk);
49
+ });
50
+ });
51
+ return () => {
52
+ cancelled = true;
53
+ cancel();
54
+ };
55
+ }
56
+ function onSallaEvent(name, listener) {
57
+ let bus;
58
+ const cancel = whenSalla(hasEventBus, (sdk) => {
59
+ bus = sdk.event;
60
+ bus.on(name, listener);
61
+ });
62
+ return () => {
63
+ cancel();
64
+ bus?.off?.(name, listener);
65
+ };
66
+ }
67
+ function syncSdkLocale(locale) {
68
+ const sdk = getSallaSDK();
69
+ if (!sdk || !locale) return;
70
+ try {
71
+ sdk.lang?.setLocale?.(locale);
72
+ sdk.api?.setHeader?.("accept-language", locale);
73
+ sdk.config?.set?.("user.language_code", locale);
74
+ } catch {
75
+ }
76
+ }
77
+ function syncSdkThemeVersion(headers) {
78
+ const sdk = getSallaSDK();
79
+ if (!sdk) return;
80
+ const versionId = headers?.["s-version-id"];
81
+ try {
82
+ if (versionId != null) sdk.api?.setHeader?.("s-version-id", String(versionId));
83
+ else delete sdk.api?.axios?.defaults?.headers?.common?.["s-version-id"];
84
+ } catch {
85
+ }
86
+ }
87
+
88
+ export { getSallaSDK, getStoreIdentifier, onSallaEvent, syncSdkLocale, syncSdkThemeVersion, whenSallaLoaded, whenSallaReady };
89
+ //# sourceMappingURL=chunk-2FKZAAV7.js.map
90
+ //# sourceMappingURL=chunk-2FKZAAV7.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/sdk-helpers.ts"],"names":[],"mappings":"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","file":"chunk-2FKZAAV7.js","sourcesContent":["export type { StoreContext } from '../api/store';\nimport type { StoreContext } from '../api/store';\nimport type { SallaSDK } from '../types/salla-sdk';\nimport { resolveStoreIdentifier } from './store-identity';\n\nconst isBrowser = typeof window !== 'undefined';\n\n/**\n * Which store to ask the API about — see {@link resolveStoreIdentifier}.\n *\n * A delegation, not a second implementation. This name is the one on the wire\n * (`api/client.ts` sets the `store-identifier` header from it) and the one\n * themes import from `@salla.sa/twilight-theme-engine/utils`, so it stays; what\n * it must never do again is answer differently from the resolver everything\n * else asks. It had its own copy of the order once, missing the store the\n * request names and preferring the build-time `VITE_STORE_DOMAIN` that a\n * deployed worker does not have — so every published theme sent an empty\n * identifier and rendered \"Store Unavailable\".\n */\nexport function getStoreIdentifier(explicit?: string): string {\n return resolveStoreIdentifier(explicit);\n}\n\n/**\n * Get Salla SDK instance if available\n */\nexport function getSallaSDK(): typeof window.salla | undefined {\n if (!isBrowser) return undefined;\n return window.salla;\n}\n\n/** Dispatched on `window` by the SDK as the last step of loading (twilight `src/index.js`). */\nconst SDK_CREATED_EVENT = 'salla::created';\n\nconst noop = () => {};\n\n/**\n * Whether `window.salla` is the SDK, rather than the stub that stands in for it.\n *\n * ⚠️ `window.salla` exists from the first bytes of the page. The `twilight-init`\n * head script defines it with an `onReady`, so app snippets can queue work, and\n * the SDK — a deferred module — fills it in later. React can hydrate and run\n * effects in between, and there `window.salla?.event.on(…)` passes its `?.` and\n * throws `Cannot read properties of undefined (reading 'on')`.\n *\n * The SDK defines `init` and `event` in one synchronous module evaluation and the\n * stub has neither, so either one means it has loaded.\n */\nfunction isLoaded(sdk: typeof window.salla): sdk is SallaSDK {\n return typeof sdk?.init === 'function' || typeof sdk?.event?.on === 'function';\n}\n\n/** An SDK whose event bus can take a listener — what {@link onSallaEvent} needs. */\nfunction hasEventBus(sdk: typeof window.salla): sdk is SallaSDK {\n return typeof sdk?.event?.on === 'function';\n}\n\n/**\n * Run `callback` with the SDK as soon as it has loaded: now if it has, otherwise\n * when it announces itself.\n *\n * Returns a cancel for an effect's cleanup, so a component that unmounts first\n * never has the callback run. An effect that returned early when the SDK was not\n * there yet never ran again — on a cold load, where hydration beats the SDK, the\n * engine never initialised it at all.\n */\nexport function whenSallaLoaded(callback: (sdk: SallaSDK) => void): () => void {\n return whenSalla(isLoaded, callback);\n}\n\nfunction whenSalla(\n isUsable: (sdk: typeof window.salla) => sdk is SallaSDK,\n callback: (sdk: SallaSDK) => void\n): () => void {\n if (!isBrowser) return noop;\n\n if (isUsable(window.salla)) {\n callback(window.salla);\n return noop;\n }\n\n let settled = false;\n const onCreated = () => {\n const sdk = window.salla;\n if (settled || !isUsable(sdk)) return;\n settled = true;\n window.removeEventListener(SDK_CREATED_EVENT, onCreated);\n callback(sdk);\n };\n window.addEventListener(SDK_CREATED_EVENT, onCreated);\n\n return () => {\n settled = true;\n window.removeEventListener(SDK_CREATED_EVENT, onCreated);\n };\n}\n\n/**\n * Run `callback` once the SDK has loaded **and been initialised** — for work that\n * talks to the API, which needs the store config `init` sets.\n *\n * Loaded is not enough for that: `init` finishes asynchronously, so a cart lookup\n * made the moment the SDK announces itself goes out without a store identifier\n * and is answered `Store Identifier not found`. Returns a cancel, as\n * {@link whenSallaLoaded} does.\n *\n * A rejected `onReady` still runs `callback`, as `useTwilightInit` carries on past\n * one: it means a partial initialisation, and waiting on it would leave the caller\n * waiting for good.\n */\nexport function whenSallaReady(callback: (sdk: SallaSDK) => void): () => void {\n let cancelled = false;\n const cancel = whenSallaLoaded((sdk) => {\n void new Promise((resolve) => resolve(sdk.onReady?.())).catch(noop).then(() => {\n if (!cancelled) callback(sdk);\n });\n });\n return () => {\n cancelled = true;\n cancel();\n };\n}\n\n/**\n * `salla.event.on(name, listener)` once the SDK has loaded. Returns the matching\n * unsubscribe, which also cancels a subscription still waiting for the SDK.\n *\n * Removed from the emitter it was added to, not from whatever `window.salla` is\n * by the time the component unmounts.\n *\n * Waits for an event bus specifically, not for \"loaded\": an SDK is recognised by\n * `init` alone, and subscribing on one without a bus would throw.\n */\nexport function onSallaEvent(name: string, listener: (...args: unknown[]) => void): () => void {\n let bus: SallaSDK['event'] | undefined;\n const cancel = whenSalla(hasEventBus, (sdk) => {\n bus = sdk.event;\n bus.on(name, listener);\n });\n return () => {\n cancel();\n bus?.off?.(name, listener);\n };\n}\n\n/**\n * Push the active route locale onto the Salla SDK.\n *\n * Why this is needed (and why it must run on every navigation):\n * - The SDK seeds its locale from `navigator.language` — the theme sets no `s-lang`\n * cookie or `window.locale` — so an English browser starts the SDK in `en` even on\n * an `/ar` store.\n * - The SDK fixes its axios `accept-language` header ONCE, at init. `salla.lang.setLocale`\n * only swaps UI translations (it never touches the header), and `salla.init()` is a\n * no-op after `Salla.status === 'ready'`, so the header never refreshes on its own.\n * - `profile::info.fetched` (login / profile refresh on navigation) overrides the header\n * to the *account's* language.\n *\n * Net result without this: `salla.api.*` calls (cart/product details) return data in the\n * wrong locale — e.g. English cart item names on `/ar/cart` — intermittently, depending on\n * load order and whether a profile fetch ran. Re-asserting the URL locale here keeps the\n * header correct. No-op on the server and until the SDK exposes the methods.\n */\nexport function syncSdkLocale(locale: string): void {\n const sdk = getSallaSDK();\n if (!sdk || !locale) return;\n try {\n sdk.lang?.setLocale?.(locale);\n sdk.api?.setHeader?.('accept-language', locale);\n // The localization modal swaps `/${user.language_code}/` in the URL on submit;\n // the SDK never sets this locally, so without it the switch reloads the same page.\n sdk.config?.set?.('user.language_code', locale);\n } catch {\n // SDK partially loaded — the header is re-asserted on the next navigation.\n }\n}\n\n/**\n * Push the theme version the current settings name onto the Salla SDK.\n *\n * The SDK copies `settings.headers` into its axios defaults ONCE, at init, and\n * `s-version-id` is one of them. Settings refetched on the client — the shopper\n * switched market, and each market has its own version — name a different one,\n * and without this every `salla.api.*` call keeps asking for the previous\n * market's version until a full page load. Settings that name no version take\n * the header off instead, so the SDK asks for the live one like the engine's own\n * client does. No-op on the server and until the SDK exposes its api.\n */\nexport function syncSdkThemeVersion(headers: StoreContext['headers']): void {\n const sdk = getSallaSDK();\n if (!sdk) return;\n const versionId = headers?.['s-version-id'];\n try {\n if (versionId != null) sdk.api?.setHeader?.('s-version-id', String(versionId));\n else delete sdk.api?.axios?.defaults?.headers?.common?.['s-version-id'];\n } catch {\n // SDK partially loaded — the header is re-asserted on the next navigation.\n }\n}\n"]}
@@ -1,8 +1,8 @@
1
- import { order } from './chunk-TEOVJ6WU.js';
1
+ import { order } from './chunk-O7B5JL6H.js';
2
2
  import { buildHreflangAlternates } from './chunk-4SZZPXM2.js';
3
- import { unauthorized, orUnauthorized, orThrow } from './chunk-JTOVO3ZU.js';
3
+ import { unauthorized, orUnauthorized, orThrow } from './chunk-RWBTMHLR.js';
4
4
  import { RouteId } from './chunk-OUW6WESU.js';
5
- import { getAuthToken } from './chunk-QGOPTVV5.js';
5
+ import { getAuthToken } from './chunk-6EQ7G3SZ.js';
6
6
  import { getTwilightContext } from './chunk-N2S25NXP.js';
7
7
  import { lazy } from 'react';
8
8
 
@@ -55,9 +55,9 @@ async function orderSingleLoader({
55
55
  }
56
56
 
57
57
  // src/routes/account/orders/index.tsx
58
- var LazyOrdersPage = lazy(() => import('./OrdersPage-BEBXUZGC.js').then((m) => ({ default: m.OrdersPage })));
58
+ var LazyOrdersPage = lazy(() => import('./OrdersPage-ILD4GC4Q.js').then((m) => ({ default: m.OrdersPage })));
59
59
  var LazyOrderSinglePage = lazy(
60
- () => import('./OrderSinglePage-H6TGX43N.js').then((m) => ({ default: m.OrderSinglePage }))
60
+ () => import('./OrderSinglePage-RG5GJQ7H.js').then((m) => ({ default: m.OrderSinglePage }))
61
61
  );
62
62
  var OrdersPage = LazyOrdersPage;
63
63
  var OrderSinglePage = LazyOrderSinglePage;
@@ -104,5 +104,5 @@ var OrderSingle = {
104
104
  };
105
105
 
106
106
  export { OrderSingle, OrderSinglePage, Orders, OrdersPage, orderSingleLoader, ordersLoader };
107
- //# sourceMappingURL=chunk-ZTXEXO4W.js.map
108
- //# sourceMappingURL=chunk-ZTXEXO4W.js.map
107
+ //# sourceMappingURL=chunk-4P77DKHC.js.map
108
+ //# sourceMappingURL=chunk-4P77DKHC.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/routes/account/orders/loader.ts","../src/routes/account/orders/index.tsx"],"names":[],"mappings":"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","file":"chunk-ZTXEXO4W.js","sourcesContent":["import { order } from '../../../api/order';\nimport { getTwilightContext } from '../../../twilight/context';\nimport { RouteId } from '../../../router/route-ids';\nimport { orThrow, orUnauthorized, unauthorized } from '../../../providers/NavigationProvider';\nimport { getAuthToken } from '../../../api/client';\nimport type { OrdersPageProps, OrderSinglePageProps, OrdersQuery } from './types';\nimport type { IdParams } from '../../types';\n\nexport async function ordersLoader(\n ctx: { query?: OrdersQuery; with_items?: boolean | number },\n extend?: (\n data: OrdersPageProps,\n ctx: { params: Record<string, never> }\n ) => Promise<Record<string, unknown>> | Record<string, unknown>\n): Promise<OrdersPageProps> {\n if (!getAuthToken()) throw unauthorized();\n const query = ctx.query;\n const isPending = query?.status === 'pending';\n const response = await orUnauthorized(\n order.list({\n // Only decides the empty state; <salla-orders> applies its own review filter (`?tab=waiting`).\n status: query?.status,\n ...(ctx.with_items ? { with_items: ctx.with_items } : {}),\n })\n );\n const i18n = getTwilightContext().i18n;\n const pageData: OrdersPageProps = {\n page: {\n title: isPending ? i18n.t('common.titles.pending_orders') : i18n.t('common.titles.orders'),\n slug: RouteId.CUSTOMER_ORDERS_INDEX,\n },\n orders: response.data,\n cursor: response.cursor,\n query,\n };\n\n if (extend) {\n const extra = await extend(pageData, { params: {} });\n return { ...pageData, ...extra } as OrdersPageProps;\n }\n return pageData;\n}\n\nexport async function orderSingleLoader({\n params,\n}: {\n params: IdParams;\n}): Promise<OrderSinglePageProps> {\n if (!getAuthToken()) throw unauthorized();\n const [data, componentsOrder] = await Promise.all([\n order.findOrThrow(params.id),\n orThrow(orUnauthorized(order.findForComponents(params.id))),\n ]);\n const i18n = getTwilightContext().i18n;\n return {\n page: {\n slug: RouteId.CUSTOMER_ORDERS_SINGLE,\n id: String(params.id),\n title: i18n\n .t('pages.orders.order_details')\n .replace(':id', String(data.order.reference_id ?? params.id)),\n },\n order: data.order,\n componentsOrder,\n };\n}\n","import type { HeadDescriptor } from '../../../utils/head';\nimport { buildHreflangAlternates } from '../../../utils/baseHead';\nimport { lazy } from 'react';\nimport { ordersLoader, orderSingleLoader } from './loader';\nimport type { OrdersPageProps, OrderSinglePageProps, OrdersSearchParams } from './types';\nimport type { IdParams } from '../../types';\nimport type { TwilightContext } from '../../../twilight/context';\nimport { RouteId } from '../../../router/route-ids';\n\n// Lazy-load components for code-splitting\nconst LazyOrdersPage = lazy(() => import('./OrdersPage').then((m) => ({ default: m.OrdersPage })));\nconst LazyOrderSinglePage = lazy(() =>\n import('./OrderSinglePage').then((m) => ({ default: m.OrderSinglePage }))\n);\n\nexport const OrdersPage = LazyOrdersPage;\nexport const OrderSinglePage = LazyOrderSinglePage;\nexport { ordersLoader, orderSingleLoader } from './loader';\nexport type {\n OrdersPageProps,\n OrderSinglePageProps,\n OrdersSearchParams,\n OrdersQuery,\n} from './types';\n\nasync function ordersLoaderWithExtend(\n ctx: { search?: OrdersSearchParams; locale?: string; with_items?: boolean | number },\n extend?: (\n data: OrdersPageProps,\n ctx: { params: Record<string, never> }\n ) => Promise<Record<string, unknown>> | Record<string, unknown>\n): Promise<OrdersPageProps> {\n const query = ctx.search;\n // ordersLoader already merges the result of `extend`; calling it again here ran it twice.\n return ordersLoader({ query, with_items: ctx.with_items }, extend);\n}\n\nfunction ordersHead(ctx: TwilightContext, data: OrdersPageProps): HeadDescriptor {\n const isPending = data.query?.status === 'pending';\n const base: HeadDescriptor = {\n title: ctx.i18n.t(isPending ? 'common.titles.pending_orders' : 'common.titles.orders'),\n description: data.page.description,\n alternateLanguages: buildHreflangAlternates(ctx.settings, ctx.location.pathname),\n };\n\n return base;\n}\n\nasync function orderSingleLoaderWithExtend(\n ctx: { params: IdParams; locale?: string },\n extend?: (\n data: OrderSinglePageProps,\n ctx: { params: IdParams }\n ) => Promise<Record<string, unknown>> | Record<string, unknown>\n): Promise<OrderSinglePageProps> {\n const data = await orderSingleLoader({ params: ctx.params });\n\n if (extend) {\n const extra = await extend(data, ctx);\n return { ...data, ...extra } as OrderSinglePageProps;\n }\n return data;\n}\n\nfunction orderSingleHead(ctx: TwilightContext, data: OrderSinglePageProps): HeadDescriptor {\n const base: HeadDescriptor = {\n title: data.page.title,\n description: data.page.description,\n alternateLanguages: buildHreflangAlternates(ctx.settings, ctx.location.pathname),\n };\n\n return base;\n}\n\nexport const Orders = {\n id: RouteId.CUSTOMER_ORDERS_INDEX,\n loader: ordersLoaderWithExtend,\n head: ordersHead,\n Component: LazyOrdersPage,\n} as const;\nexport const OrderSingle = {\n id: RouteId.CUSTOMER_ORDERS_SINGLE,\n loader: orderSingleLoaderWithExtend,\n head: orderSingleHead,\n Component: LazyOrderSinglePage,\n} as const;\n"]}
1
+ {"version":3,"sources":["../src/routes/account/orders/loader.ts","../src/routes/account/orders/index.tsx"],"names":[],"mappings":";;;;;;;;;AAQA,eAAsB,YAAA,CACpB,KACA,MAAA,EAI0B;AAC1B,EAAA,IAAI,CAAC,YAAA,EAAa,EAAG,MAAM,YAAA,EAAa;AACxC,EAAA,MAAM,QAAQ,GAAA,CAAI,KAAA;AAClB,EAAA,MAAM,SAAA,GAAY,OAAO,MAAA,KAAW,SAAA;AACpC,EAAA,MAAM,WAAW,MAAM,cAAA;AAAA,IACrB,MAAM,IAAA,CAAK;AAAA;AAAA,MAET,QAAQ,KAAA,EAAO,MAAA;AAAA,MACf,GAAI,IAAI,UAAA,GAAa,EAAE,YAAY,GAAA,CAAI,UAAA,KAAe;AAAC,KACxD;AAAA,GACH;AACA,EAAA,MAAM,IAAA,GAAO,oBAAmB,CAAE,IAAA;AAClC,EAAA,MAAM,QAAA,GAA4B;AAAA,IAChC,IAAA,EAAM;AAAA,MACJ,KAAA,EAAO,YAAY,IAAA,CAAK,CAAA,CAAE,8BAA8B,CAAA,GAAI,IAAA,CAAK,EAAE,sBAAsB,CAAA;AAAA,MACzF,MAAM,OAAA,CAAQ;AAAA,KAChB;AAAA,IACA,QAAQ,QAAA,CAAS,IAAA;AAAA,IACjB,QAAQ,QAAA,CAAS,MAAA;AAAA,IACjB;AAAA,GACF;AAEA,EAAA,IAAI,MAAA,EAAQ;AACV,IAAA,MAAM,KAAA,GAAQ,MAAM,MAAA,CAAO,QAAA,EAAU,EAAE,MAAA,EAAQ,IAAI,CAAA;AACnD,IAAA,OAAO,EAAE,GAAG,QAAA,EAAU,GAAG,KAAA,EAAM;AAAA,EACjC;AACA,EAAA,OAAO,QAAA;AACT;AAEA,eAAsB,iBAAA,CAAkB;AAAA,EACtC;AACF,CAAA,EAEkC;AAChC,EAAA,IAAI,CAAC,YAAA,EAAa,EAAG,MAAM,YAAA,EAAa;AACxC,EAAA,MAAM,CAAC,IAAA,EAAM,eAAe,CAAA,GAAI,MAAM,QAAQ,GAAA,CAAI;AAAA,IAChD,KAAA,CAAM,WAAA,CAAY,MAAA,CAAO,EAAE,CAAA;AAAA,IAC3B,QAAQ,cAAA,CAAe,KAAA,CAAM,kBAAkB,MAAA,CAAO,EAAE,CAAC,CAAC;AAAA,GAC3D,CAAA;AACD,EAAA,MAAM,IAAA,GAAO,oBAAmB,CAAE,IAAA;AAClC,EAAA,OAAO;AAAA,IACL,IAAA,EAAM;AAAA,MACJ,MAAM,OAAA,CAAQ,sBAAA;AAAA,MACd,EAAA,EAAI,MAAA,CAAO,MAAA,CAAO,EAAE,CAAA;AAAA,MACpB,KAAA,EAAO,IAAA,CACJ,CAAA,CAAE,4BAA4B,CAAA,CAC9B,OAAA,CAAQ,KAAA,EAAO,MAAA,CAAO,IAAA,CAAK,KAAA,CAAM,YAAA,IAAgB,MAAA,CAAO,EAAE,CAAC;AAAA,KAChE;AAAA,IACA,OAAO,IAAA,CAAK,KAAA;AAAA,IACZ;AAAA,GACF;AACF;;;ACvDA,IAAM,cAAA,GAAiB,IAAA,CAAK,MAAM,OAAO,0BAAc,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,MAAO,EAAE,OAAA,EAAS,CAAA,CAAE,UAAA,GAAa,CAAC,CAAA;AACjG,IAAM,mBAAA,GAAsB,IAAA;AAAA,EAAK,MAC/B,OAAO,+BAAmB,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,MAAO,EAAE,OAAA,EAAS,CAAA,CAAE,eAAA,EAAgB,CAAE;AAC1E,CAAA;AAEO,IAAM,UAAA,GAAa;AACnB,IAAM,eAAA,GAAkB;AAS/B,eAAe,sBAAA,CACb,KACA,MAAA,EAI0B;AAC1B,EAAA,MAAM,QAAQ,GAAA,CAAI,MAAA;AAElB,EAAA,OAAO,aAAa,EAAE,KAAA,EAAO,YAAY,GAAA,CAAI,UAAA,IAAc,MAAM,CAAA;AACnE;AAEA,SAAS,UAAA,CAAW,KAAsB,IAAA,EAAuC;AAC/E,EAAA,MAAM,SAAA,GAAY,IAAA,CAAK,KAAA,EAAO,MAAA,KAAW,SAAA;AACzC,EAAA,MAAM,IAAA,GAAuB;AAAA,IAC3B,OAAO,GAAA,CAAI,IAAA,CAAK,CAAA,CAAE,SAAA,GAAY,iCAAiC,sBAAsB,CAAA;AAAA,IACrF,WAAA,EAAa,KAAK,IAAA,CAAK,WAAA;AAAA,IACvB,oBAAoB,uBAAA,CAAwB,GAAA,CAAI,QAAA,EAAU,GAAA,CAAI,SAAS,QAAQ;AAAA,GACjF;AAEA,EAAA,OAAO,IAAA;AACT;AAEA,eAAe,2BAAA,CACb,KACA,MAAA,EAI+B;AAC/B,EAAA,MAAM,OAAO,MAAM,iBAAA,CAAkB,EAAE,MAAA,EAAQ,GAAA,CAAI,QAAQ,CAAA;AAE3D,EAAA,IAAI,MAAA,EAAQ;AACV,IAAA,MAAM,KAAA,GAAQ,MAAM,MAAA,CAAO,IAAA,EAAM,GAAG,CAAA;AACpC,IAAA,OAAO,EAAE,GAAG,IAAA,EAAM,GAAG,KAAA,EAAM;AAAA,EAC7B;AACA,EAAA,OAAO,IAAA;AACT;AAEA,SAAS,eAAA,CAAgB,KAAsB,IAAA,EAA4C;AACzF,EAAA,MAAM,IAAA,GAAuB;AAAA,IAC3B,KAAA,EAAO,KAAK,IAAA,CAAK,KAAA;AAAA,IACjB,WAAA,EAAa,KAAK,IAAA,CAAK,WAAA;AAAA,IACvB,oBAAoB,uBAAA,CAAwB,GAAA,CAAI,QAAA,EAAU,GAAA,CAAI,SAAS,QAAQ;AAAA,GACjF;AAEA,EAAA,OAAO,IAAA;AACT;AAEO,IAAM,MAAA,GAAS;AAAA,EACpB,IAAI,OAAA,CAAQ,qBAAA;AAAA,EACZ,MAAA,EAAQ,sBAAA;AAAA,EACR,IAAA,EAAM,UAAA;AAAA,EACN,SAAA,EAAW;AACb;AACO,IAAM,WAAA,GAAc;AAAA,EACzB,IAAI,OAAA,CAAQ,sBAAA;AAAA,EACZ,MAAA,EAAQ,2BAAA;AAAA,EACR,IAAA,EAAM,eAAA;AAAA,EACN,SAAA,EAAW;AACb","file":"chunk-4P77DKHC.js","sourcesContent":["import { order } from '../../../api/order';\nimport { getTwilightContext } from '../../../twilight/context';\nimport { RouteId } from '../../../router/route-ids';\nimport { orThrow, orUnauthorized, unauthorized } from '../../../providers/NavigationProvider';\nimport { getAuthToken } from '../../../api/client';\nimport type { OrdersPageProps, OrderSinglePageProps, OrdersQuery } from './types';\nimport type { IdParams } from '../../types';\n\nexport async function ordersLoader(\n ctx: { query?: OrdersQuery; with_items?: boolean | number },\n extend?: (\n data: OrdersPageProps,\n ctx: { params: Record<string, never> }\n ) => Promise<Record<string, unknown>> | Record<string, unknown>\n): Promise<OrdersPageProps> {\n if (!getAuthToken()) throw unauthorized();\n const query = ctx.query;\n const isPending = query?.status === 'pending';\n const response = await orUnauthorized(\n order.list({\n // Only decides the empty state; <salla-orders> applies its own review filter (`?tab=waiting`).\n status: query?.status,\n ...(ctx.with_items ? { with_items: ctx.with_items } : {}),\n })\n );\n const i18n = getTwilightContext().i18n;\n const pageData: OrdersPageProps = {\n page: {\n title: isPending ? i18n.t('common.titles.pending_orders') : i18n.t('common.titles.orders'),\n slug: RouteId.CUSTOMER_ORDERS_INDEX,\n },\n orders: response.data,\n cursor: response.cursor,\n query,\n };\n\n if (extend) {\n const extra = await extend(pageData, { params: {} });\n return { ...pageData, ...extra } as OrdersPageProps;\n }\n return pageData;\n}\n\nexport async function orderSingleLoader({\n params,\n}: {\n params: IdParams;\n}): Promise<OrderSinglePageProps> {\n if (!getAuthToken()) throw unauthorized();\n const [data, componentsOrder] = await Promise.all([\n order.findOrThrow(params.id),\n orThrow(orUnauthorized(order.findForComponents(params.id))),\n ]);\n const i18n = getTwilightContext().i18n;\n return {\n page: {\n slug: RouteId.CUSTOMER_ORDERS_SINGLE,\n id: String(params.id),\n title: i18n\n .t('pages.orders.order_details')\n .replace(':id', String(data.order.reference_id ?? params.id)),\n },\n order: data.order,\n componentsOrder,\n };\n}\n","import type { HeadDescriptor } from '../../../utils/head';\nimport { buildHreflangAlternates } from '../../../utils/baseHead';\nimport { lazy } from 'react';\nimport { ordersLoader, orderSingleLoader } from './loader';\nimport type { OrdersPageProps, OrderSinglePageProps, OrdersSearchParams } from './types';\nimport type { IdParams } from '../../types';\nimport type { TwilightContext } from '../../../twilight/context';\nimport { RouteId } from '../../../router/route-ids';\n\n// Lazy-load components for code-splitting\nconst LazyOrdersPage = lazy(() => import('./OrdersPage').then((m) => ({ default: m.OrdersPage })));\nconst LazyOrderSinglePage = lazy(() =>\n import('./OrderSinglePage').then((m) => ({ default: m.OrderSinglePage }))\n);\n\nexport const OrdersPage = LazyOrdersPage;\nexport const OrderSinglePage = LazyOrderSinglePage;\nexport { ordersLoader, orderSingleLoader } from './loader';\nexport type {\n OrdersPageProps,\n OrderSinglePageProps,\n OrdersSearchParams,\n OrdersQuery,\n} from './types';\n\nasync function ordersLoaderWithExtend(\n ctx: { search?: OrdersSearchParams; locale?: string; with_items?: boolean | number },\n extend?: (\n data: OrdersPageProps,\n ctx: { params: Record<string, never> }\n ) => Promise<Record<string, unknown>> | Record<string, unknown>\n): Promise<OrdersPageProps> {\n const query = ctx.search;\n // ordersLoader already merges the result of `extend`; calling it again here ran it twice.\n return ordersLoader({ query, with_items: ctx.with_items }, extend);\n}\n\nfunction ordersHead(ctx: TwilightContext, data: OrdersPageProps): HeadDescriptor {\n const isPending = data.query?.status === 'pending';\n const base: HeadDescriptor = {\n title: ctx.i18n.t(isPending ? 'common.titles.pending_orders' : 'common.titles.orders'),\n description: data.page.description,\n alternateLanguages: buildHreflangAlternates(ctx.settings, ctx.location.pathname),\n };\n\n return base;\n}\n\nasync function orderSingleLoaderWithExtend(\n ctx: { params: IdParams; locale?: string },\n extend?: (\n data: OrderSinglePageProps,\n ctx: { params: IdParams }\n ) => Promise<Record<string, unknown>> | Record<string, unknown>\n): Promise<OrderSinglePageProps> {\n const data = await orderSingleLoader({ params: ctx.params });\n\n if (extend) {\n const extra = await extend(data, ctx);\n return { ...data, ...extra } as OrderSinglePageProps;\n }\n return data;\n}\n\nfunction orderSingleHead(ctx: TwilightContext, data: OrderSinglePageProps): HeadDescriptor {\n const base: HeadDescriptor = {\n title: data.page.title,\n description: data.page.description,\n alternateLanguages: buildHreflangAlternates(ctx.settings, ctx.location.pathname),\n };\n\n return base;\n}\n\nexport const Orders = {\n id: RouteId.CUSTOMER_ORDERS_INDEX,\n loader: ordersLoaderWithExtend,\n head: ordersHead,\n Component: LazyOrdersPage,\n} as const;\nexport const OrderSingle = {\n id: RouteId.CUSTOMER_ORDERS_SINGLE,\n loader: orderSingleLoaderWithExtend,\n head: orderSingleHead,\n Component: LazyOrderSinglePage,\n} as const;\n"]}
@@ -1,5 +1,5 @@
1
- import { orThrow } from './chunk-JTOVO3ZU.js';
2
- import { getActiveScope, api } from './chunk-QGOPTVV5.js';
1
+ import { orThrow } from './chunk-RWBTMHLR.js';
2
+ import { getActiveScope, api } from './chunk-6EQ7G3SZ.js';
3
3
  import { getTwilightContext } from './chunk-N2S25NXP.js';
4
4
  import { defaultShouldDehydrateQuery, queryOptions } from '@tanstack/react-query';
5
5
 
@@ -194,5 +194,5 @@ var product = {
194
194
  };
195
195
 
196
196
  export { getProductPreview, isProductPreviewQuery, parseNextPageToken, product, productDetailQueryKey, productPreviewQueryKey, rememberProductPreview, shouldDehydrateQuery };
197
- //# sourceMappingURL=chunk-CEYT3JER.js.map
198
- //# sourceMappingURL=chunk-CEYT3JER.js.map
197
+ //# sourceMappingURL=chunk-56T47K7P.js.map
198
+ //# sourceMappingURL=chunk-56T47K7P.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/api/product.ts"],"names":["product"],"mappings":"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","file":"chunk-CEYT3JER.js","sourcesContent":["import { queryOptions, defaultShouldDehydrateQuery } from '@tanstack/react-query';\nimport { api, getActiveScope } from './client';\nimport type { Product } from '../types';\nimport type { Pagination, PaginatedResult } from './types';\nimport { orThrow } from '../providers/NavigationProvider';\nimport { getTwilightContext } from '../twilight/context';\nimport type { ActiveScope } from '../utils/cookies';\n\n// ===== Filter Types =====\n\nexport interface FilterValue {\n key?: string;\n count?: number;\n value?: string;\n from?: number | '*';\n to?: number | '*';\n}\n\nexport interface Filter {\n key?: string;\n label?: string;\n type?: string;\n values?: FilterValue[];\n max?: number;\n min?: number;\n}\n\n// ===== Product List Types =====\n\nexport type ProductsListSource =\n | 'brands'\n | 'categories'\n | 'json'\n | 'landing-page'\n | 'latest'\n | 'offers'\n | 'recently'\n | 'related'\n | 'selected'\n | 'tags'\n | 'top-rated'\n | 'wishlist'\n | 'search'\n | 'sales'\n | 'reorder'\n | 'best_selling';\n\nexport interface ProductsListParams {\n /** Source type (wishlist, latest, brands, etc.) */\n source: ProductsListSource;\n /**\n * The ids the source reads, as an array: category, brand, tag or product ids\n * (`sourceValue: [708738657]`). Sent as `source_value[]`.\n */\n sourceValue?: string | number | number[] | null;\n /** The search words when `source` is `'search'`. Sent as `keyword`; other sources ignore it. */\n keyword?: string;\n /** Page number for offset-based pagination */\n page?: number;\n /** Cursor for cursor-based pagination (from previous response) */\n cursor?: string | null;\n /** Items per page (default: 15) */\n perPage?: number;\n /** Sort option */\n sort?: string;\n /** Enable filters on the response */\n filterable?: boolean;\n /** Applied `<salla-filters>` selection (the `salla-filters::changed` payload). */\n filters?: ProductListFilters;\n /** Abort signal for cancellation */\n signal?: AbortSignal;\n}\n\n/** One `<salla-filters>` value: a scalar, a list, or a nested `{ sub-key: value }` (variants). */\nexport type ProductListFilterValue =\n string | number | Array<string | number> | { [key: string]: ProductListFilterValue };\n\n/** A `<salla-filters>` selection, i.e. the `salla-filters::changed` payload. */\nexport type ProductListFilters = Record<string, ProductListFilterValue>;\n\nexport type ProductsListResult = PaginatedResult<Product> & {\n filters?: Filter[];\n};\n\nexport interface ProductsListResponse {\n data: Product[];\n cursor?: Pagination;\n filters?: Filter[];\n}\n\n// ===== List-card preview cache =====\n// List payloads are a subset of details (one `image`, no `options` / `images[]`).\n// They live on a separate query key so they can paint a sheet/quick-view without\n// being treated as a successful `products/{id}/details` fetch.\n\nfunction queryClientOrNull() {\n try {\n const queryClient = getTwilightContext().queryClient;\n return queryClient && typeof queryClient.setQueryData === 'function' ? queryClient : null;\n } catch {\n return null;\n }\n}\n\nexport function productPreviewQueryKey(id: string) {\n return ['products', 'preview', String(id), { scope: getActiveScope() }] as const;\n}\n\nexport function productDetailQueryKey(id: string) {\n return ['products', 'detail', id, { scope: getActiveScope() }] as const;\n}\n\n/** True when this query is a list-card stand-in — skip it when dehydrating SSR. */\nexport function isProductPreviewQuery(query: { queryKey: readonly unknown[] }): boolean {\n return query.queryKey[0] === 'products' && query.queryKey[1] === 'preview';\n}\n\n/**\n * Default dehydrate policy (success) plus pending SSR-stream queries, minus\n * list-card stand-ins. Replacing the default wholesale would ship error states.\n */\nexport function shouldDehydrateQuery(\n query: Parameters<typeof defaultShouldDehydrateQuery>[0]\n): boolean {\n return (\n !isProductPreviewQuery(query) &&\n (defaultShouldDehydrateQuery(query) || query.state.status === 'pending')\n );\n}\n\n/**\n * Remember a list/card product so `product.queries.detail(id)` can use it as\n * `placeholderData` while details load. No-op if details for this id are already\n * cached. Themes that fetch products outside `product.list` should call this.\n */\nexport function rememberProductPreview(product: Product): void {\n const queryClient = queryClientOrNull();\n if (!queryClient || product?.id == null) return;\n const id = String(product.id);\n if (queryClient.getQueryState(productDetailQueryKey(id))?.status === 'success') return;\n queryClient.setQueryData(productPreviewQueryKey(id), product);\n}\n\nfunction scopeFromQueryKey(queryKey: readonly unknown[]): ActiveScope | null | undefined {\n const last = queryKey[queryKey.length - 1];\n if (last == null || typeof last !== 'object' || !('scope' in last)) return undefined;\n return (last as { scope: ActiveScope | null }).scope;\n}\n\nfunction isSameScope(a: ActiveScope | null | undefined, b: ActiveScope | null): boolean {\n if (a === undefined) return false;\n if (a === b) return true;\n if (a == null || b == null) return a == null && b == null;\n return (\n a.id === b.id &&\n a.type === b.type &&\n a.allocation_id === b.allocation_id &&\n a.allocation_type === b.allocation_type\n );\n}\n\nconst LIST_QUERY_PREFIXES = [\n ['products', 'list'],\n ['wishlist', 'list'],\n] as const;\n\n/**\n * Rebuild the scoped preview index from hydrated list/wishlist queries (SSR\n * dehydrate drops preview keys). Subsequent lookups hit `productPreviewQueryKey`.\n */\nfunction findProductInScopedLists(\n queryClient: NonNullable<ReturnType<typeof queryClientOrNull>>,\n id: string\n): Product | undefined {\n const scope = getActiveScope();\n let found: Product | undefined;\n for (const prefix of LIST_QUERY_PREFIXES) {\n for (const [queryKey, data] of queryClient.getQueriesData<ProductsListResult>({\n queryKey: prefix,\n })) {\n if (!isSameScope(scopeFromQueryKey(queryKey), scope)) continue;\n for (const item of data?.items ?? []) {\n if (item?.id == null) continue;\n rememberProductPreview(item);\n if (!found && String(item.id) === id) found = item;\n }\n }\n }\n return found;\n}\n\n/**\n * List-card product for `placeholderData`. Prefers the preview key; if that was\n * dropped on SSR dehydrate, rebuilds it from the current-scope list/wishlist.\n */\nexport function getProductPreview(id: string): Product | undefined {\n const queryClient = queryClientOrNull();\n if (!queryClient) return undefined;\n const key = String(id);\n return (\n queryClient.getQueryData(productPreviewQueryKey(key)) ??\n findProductInScopedLists(queryClient, key)\n );\n}\n\nfunction rememberProductPreviews(items: Product[]): void {\n for (const item of items) rememberProductPreview(item);\n}\n\n/**\n * Search sends its words as `keyword` (a `sourceValue` string is still read there, as before);\n * every other source sends its ids as `source_value[]`, which the API requires as an array.\n */\nfunction appendSourceParams(\n searchParams: URLSearchParams,\n { source, sourceValue, keyword }: Pick<ProductsListParams, 'source' | 'sourceValue' | 'keyword'>\n): void {\n if (source === 'search') {\n const words = keyword ?? sourceValue;\n if (words !== undefined) searchParams.set('keyword', String(words));\n } else if (Array.isArray(sourceValue)) {\n sourceValue.forEach((val) => searchParams.append('source_value[]', String(val)));\n } else if (sourceValue !== undefined) {\n searchParams.append('source_value[]', String(sourceValue));\n }\n}\n\n/**\n * Sends an applied filter selection the way the SDK's `<salla-products-list>` does:\n * `filters[key]=v`, `filters[key][]=v` or `filters[key][sub]=v`.\n */\nfunction appendFilterParams(\n searchParams: URLSearchParams,\n filters?: Record<string, ProductListFilterValue>,\n parentKey = 'filters'\n): void {\n if (!filters) return;\n for (const [key, value] of Object.entries(filters)) {\n const fullKey = `${parentKey}[${key}]`;\n if (Array.isArray(value)) {\n value.forEach((item) => searchParams.append(`${fullKey}[]`, String(item)));\n } else if (value !== null && typeof value === 'object') {\n appendFilterParams(searchParams, value, fullKey);\n } else if (value !== undefined && value !== null) {\n searchParams.append(fullKey, String(value));\n }\n }\n}\n\n/** A `category_id` filter replaces the page's category as the list source (as in the SDK). */\nfunction categoryFilterIds(filters?: ProductListFilters): number[] | null {\n const raw = filters?.category_id;\n if (raw === undefined || raw === null) return null;\n const ids = Array.isArray(raw) ? raw : typeof raw === 'object' ? Object.values(raw) : [raw];\n return ids.map(Number);\n}\n\n// ===== Pagination =====\n\n/**\n * The API's own `cursor.next` (the previous page's response) is usually a\n * bare opaque cursor token, but for sources that don't support true\n * cursor-based pagination (observed: `source=offers`) it's instead a full\n * next-page URL carrying its own `page=N` — and no `cursor=` param at all.\n *\n * Passing that whole URL straight through as `list()`'s own `cursor` used to\n * smuggle its embedded `source` / `per_page` / `sort` into the request on\n * top of the ones `list()` already sets unconditionally, producing a\n * doubled query string (`source=offers&source=offers&...`) the API can't\n * paginate from correctly — every subsequent scroll re-fetched the exact\n * same first page instead of advancing. Pulling just the `page` number back\n * out here, the same way an actual `cursor=` is already pulled out, keeps\n * `list()`'s request to the one copy of each param it's supposed to have.\n */\nexport function parseNextPageToken(nextUrl: string | null | undefined): {\n cursor?: string;\n page?: number;\n} {\n if (!nextUrl) return {};\n\n const cursorMatch = nextUrl.match(/[?&]cursor=([^&]+)/);\n if (cursorMatch) return { cursor: decodeURIComponent(cursorMatch[1]) };\n\n const pageMatch = nextUrl.match(/[?&]page=([^&]+)/);\n if (pageMatch) {\n const page = Number(decodeURIComponent(pageMatch[1]));\n if (Number.isFinite(page)) return { page };\n }\n\n // Neither pattern matched: not a URL at all, just the bare opaque token itself.\n return { cursor: nextUrl };\n}\n\n// ===== API Functions =====\n\nexport const product = {\n find: async (id: string): Promise<Product> => {\n const endpoint = `products/${id}/details?with[]=images&with[]=category&with[]=rating&with[]=notify_availability&with[]=tags&with[]=brand&with[]=options&with[]=skus&with[]=skus_availability&with[]=included_products&with[]=bundle&with[]=sold_quantity`;\n const { data } = await api.get(endpoint).json<{ data: Product }>();\n return data;\n },\n\n findOrThrow: (id: string): Promise<Product> => orThrow(product.find(id)),\n\n /** A tag's name. The list endpoint returns every product for an unknown tag; this one answers 410. */\n tag: async (id: string): Promise<{ id: number; name: string }> => {\n const { tag } = await api\n .get(`products/tags/${id}`)\n .json<{ tag: { id: number; name: string } }>();\n return tag;\n },\n\n /**\n * Fetch products list with pagination support\n * Used by native ProductsList component for SSR loaders\n *\n * API pattern: GET /products?source=wishlist&page=1\n */\n list: async (params: ProductsListParams): Promise<ProductsListResult> => {\n const {\n source,\n sourceValue,\n keyword,\n page,\n cursor,\n perPage = 16,\n sort,\n filterable,\n filters,\n signal,\n } = params;\n\n // Build URL with query parameters\n const searchParams = new URLSearchParams();\n searchParams.set('source', source);\n // Only send page when explicitly provided — cursor-based callers omit it entirely\n if (page !== undefined) searchParams.set('page', String(page));\n searchParams.set('per_page', String(perPage));\n\n appendSourceParams(searchParams, {\n source,\n sourceValue: (source === 'categories' && categoryFilterIds(filters)) || sourceValue,\n keyword,\n });\n appendFilterParams(searchParams, filters);\n\n // Add filterable parameter\n if (filterable !== undefined) {\n searchParams.set('filterable', filterable ? '1' : '0');\n }\n\n // Add sort parameter\n if (sort) {\n searchParams.set('sort', sort);\n }\n\n // Add cursor for cursor-based pagination\n if (cursor) {\n searchParams.set('cursor', cursor);\n }\n\n // Make the request\n const options: Record<string, unknown> = {};\n if (signal) options.signal = signal;\n\n const response = await api\n .get(`products?${searchParams.toString()}`, options as any)\n .json<ProductsListResponse>();\n\n const items = response.data ?? [];\n rememberProductPreviews(items);\n\n return {\n items,\n next: response.cursor?.next ?? null,\n filters: response.filters,\n };\n },\n\n queries: {\n detail: (id: string) =>\n queryOptions({\n // Stock and availability are resolved per branch allocation — same as the list.\n queryKey: productDetailQueryKey(id),\n queryFn: () => product.find(id),\n // List-card product, if one was remembered. Not written as the detail\n // cache entry — `queryFn` still hits products/{id}/details.\n placeholderData: () => getProductPreview(id),\n }),\n tag: (id: string) =>\n queryOptions({\n queryKey: ['products', 'tag', id],\n queryFn: () => product.tag(id),\n }),\n list: (params: Omit<ProductsListParams, 'signal'>) =>\n queryOptions({\n // Scope (branch) varies product availability — key must include it.\n queryKey: ['products', 'list', params, { scope: getActiveScope() }],\n queryFn: ({ signal }) => product.list({ ...params, signal }),\n }),\n },\n};\n"]}
1
+ {"version":3,"sources":["../src/api/product.ts"],"names":["product"],"mappings":"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","file":"chunk-56T47K7P.js","sourcesContent":["import { queryOptions, defaultShouldDehydrateQuery } from '@tanstack/react-query';\nimport { api, getActiveScope } from './client';\nimport type { Product } from '../types';\nimport type { Pagination, PaginatedResult } from './types';\nimport { orThrow } from '../providers/NavigationProvider';\nimport { getTwilightContext } from '../twilight/context';\nimport type { ActiveScope } from '../utils/cookies';\n\n// ===== Filter Types =====\n\nexport interface FilterValue {\n key?: string;\n count?: number;\n value?: string;\n from?: number | '*';\n to?: number | '*';\n}\n\nexport interface Filter {\n key?: string;\n label?: string;\n type?: string;\n values?: FilterValue[];\n max?: number;\n min?: number;\n}\n\n// ===== Product List Types =====\n\nexport type ProductsListSource =\n | 'brands'\n | 'categories'\n | 'json'\n | 'landing-page'\n | 'latest'\n | 'offers'\n | 'recently'\n | 'related'\n | 'selected'\n | 'tags'\n | 'top-rated'\n | 'wishlist'\n | 'search'\n | 'sales'\n | 'reorder'\n | 'best_selling';\n\nexport interface ProductsListParams {\n /** Source type (wishlist, latest, brands, etc.) */\n source: ProductsListSource;\n /**\n * The ids the source reads, as an array: category, brand, tag or product ids\n * (`sourceValue: [708738657]`). Sent as `source_value[]`.\n */\n sourceValue?: string | number | number[] | null;\n /** The search words when `source` is `'search'`. Sent as `keyword`; other sources ignore it. */\n keyword?: string;\n /** Page number for offset-based pagination */\n page?: number;\n /** Cursor for cursor-based pagination (from previous response) */\n cursor?: string | null;\n /** Items per page (default: 15) */\n perPage?: number;\n /** Sort option */\n sort?: string;\n /** Enable filters on the response */\n filterable?: boolean;\n /** Applied `<salla-filters>` selection (the `salla-filters::changed` payload). */\n filters?: ProductListFilters;\n /** Abort signal for cancellation */\n signal?: AbortSignal;\n}\n\n/** One `<salla-filters>` value: a scalar, a list, or a nested `{ sub-key: value }` (variants). */\nexport type ProductListFilterValue =\n string | number | Array<string | number> | { [key: string]: ProductListFilterValue };\n\n/** A `<salla-filters>` selection, i.e. the `salla-filters::changed` payload. */\nexport type ProductListFilters = Record<string, ProductListFilterValue>;\n\nexport type ProductsListResult = PaginatedResult<Product> & {\n filters?: Filter[];\n};\n\nexport interface ProductsListResponse {\n data: Product[];\n cursor?: Pagination;\n filters?: Filter[];\n}\n\n// ===== List-card preview cache =====\n// List payloads are a subset of details (one `image`, no `options` / `images[]`).\n// They live on a separate query key so they can paint a sheet/quick-view without\n// being treated as a successful `products/{id}/details` fetch.\n\nfunction queryClientOrNull() {\n try {\n const queryClient = getTwilightContext().queryClient;\n return queryClient && typeof queryClient.setQueryData === 'function' ? queryClient : null;\n } catch {\n return null;\n }\n}\n\nexport function productPreviewQueryKey(id: string) {\n return ['products', 'preview', String(id), { scope: getActiveScope() }] as const;\n}\n\nexport function productDetailQueryKey(id: string) {\n return ['products', 'detail', id, { scope: getActiveScope() }] as const;\n}\n\n/** True when this query is a list-card stand-in — skip it when dehydrating SSR. */\nexport function isProductPreviewQuery(query: { queryKey: readonly unknown[] }): boolean {\n return query.queryKey[0] === 'products' && query.queryKey[1] === 'preview';\n}\n\n/**\n * Default dehydrate policy (success) plus pending SSR-stream queries, minus\n * list-card stand-ins. Replacing the default wholesale would ship error states.\n */\nexport function shouldDehydrateQuery(\n query: Parameters<typeof defaultShouldDehydrateQuery>[0]\n): boolean {\n return (\n !isProductPreviewQuery(query) &&\n (defaultShouldDehydrateQuery(query) || query.state.status === 'pending')\n );\n}\n\n/**\n * Remember a list/card product so `product.queries.detail(id)` can use it as\n * `placeholderData` while details load. No-op if details for this id are already\n * cached. Themes that fetch products outside `product.list` should call this.\n */\nexport function rememberProductPreview(product: Product): void {\n const queryClient = queryClientOrNull();\n if (!queryClient || product?.id == null) return;\n const id = String(product.id);\n if (queryClient.getQueryState(productDetailQueryKey(id))?.status === 'success') return;\n queryClient.setQueryData(productPreviewQueryKey(id), product);\n}\n\nfunction scopeFromQueryKey(queryKey: readonly unknown[]): ActiveScope | null | undefined {\n const last = queryKey[queryKey.length - 1];\n if (last == null || typeof last !== 'object' || !('scope' in last)) return undefined;\n return (last as { scope: ActiveScope | null }).scope;\n}\n\nfunction isSameScope(a: ActiveScope | null | undefined, b: ActiveScope | null): boolean {\n if (a === undefined) return false;\n if (a === b) return true;\n if (a == null || b == null) return a == null && b == null;\n return (\n a.id === b.id &&\n a.type === b.type &&\n a.allocation_id === b.allocation_id &&\n a.allocation_type === b.allocation_type\n );\n}\n\nconst LIST_QUERY_PREFIXES = [\n ['products', 'list'],\n ['wishlist', 'list'],\n] as const;\n\n/**\n * Rebuild the scoped preview index from hydrated list/wishlist queries (SSR\n * dehydrate drops preview keys). Subsequent lookups hit `productPreviewQueryKey`.\n */\nfunction findProductInScopedLists(\n queryClient: NonNullable<ReturnType<typeof queryClientOrNull>>,\n id: string\n): Product | undefined {\n const scope = getActiveScope();\n let found: Product | undefined;\n for (const prefix of LIST_QUERY_PREFIXES) {\n for (const [queryKey, data] of queryClient.getQueriesData<ProductsListResult>({\n queryKey: prefix,\n })) {\n if (!isSameScope(scopeFromQueryKey(queryKey), scope)) continue;\n for (const item of data?.items ?? []) {\n if (item?.id == null) continue;\n rememberProductPreview(item);\n if (!found && String(item.id) === id) found = item;\n }\n }\n }\n return found;\n}\n\n/**\n * List-card product for `placeholderData`. Prefers the preview key; if that was\n * dropped on SSR dehydrate, rebuilds it from the current-scope list/wishlist.\n */\nexport function getProductPreview(id: string): Product | undefined {\n const queryClient = queryClientOrNull();\n if (!queryClient) return undefined;\n const key = String(id);\n return (\n queryClient.getQueryData(productPreviewQueryKey(key)) ??\n findProductInScopedLists(queryClient, key)\n );\n}\n\nfunction rememberProductPreviews(items: Product[]): void {\n for (const item of items) rememberProductPreview(item);\n}\n\n/**\n * Search sends its words as `keyword` (a `sourceValue` string is still read there, as before);\n * every other source sends its ids as `source_value[]`, which the API requires as an array.\n */\nfunction appendSourceParams(\n searchParams: URLSearchParams,\n { source, sourceValue, keyword }: Pick<ProductsListParams, 'source' | 'sourceValue' | 'keyword'>\n): void {\n if (source === 'search') {\n const words = keyword ?? sourceValue;\n if (words !== undefined) searchParams.set('keyword', String(words));\n } else if (Array.isArray(sourceValue)) {\n sourceValue.forEach((val) => searchParams.append('source_value[]', String(val)));\n } else if (sourceValue !== undefined) {\n searchParams.append('source_value[]', String(sourceValue));\n }\n}\n\n/**\n * Sends an applied filter selection the way the SDK's `<salla-products-list>` does:\n * `filters[key]=v`, `filters[key][]=v` or `filters[key][sub]=v`.\n */\nfunction appendFilterParams(\n searchParams: URLSearchParams,\n filters?: Record<string, ProductListFilterValue>,\n parentKey = 'filters'\n): void {\n if (!filters) return;\n for (const [key, value] of Object.entries(filters)) {\n const fullKey = `${parentKey}[${key}]`;\n if (Array.isArray(value)) {\n value.forEach((item) => searchParams.append(`${fullKey}[]`, String(item)));\n } else if (value !== null && typeof value === 'object') {\n appendFilterParams(searchParams, value, fullKey);\n } else if (value !== undefined && value !== null) {\n searchParams.append(fullKey, String(value));\n }\n }\n}\n\n/** A `category_id` filter replaces the page's category as the list source (as in the SDK). */\nfunction categoryFilterIds(filters?: ProductListFilters): number[] | null {\n const raw = filters?.category_id;\n if (raw === undefined || raw === null) return null;\n const ids = Array.isArray(raw) ? raw : typeof raw === 'object' ? Object.values(raw) : [raw];\n return ids.map(Number);\n}\n\n// ===== Pagination =====\n\n/**\n * The API's own `cursor.next` (the previous page's response) is usually a\n * bare opaque cursor token, but for sources that don't support true\n * cursor-based pagination (observed: `source=offers`) it's instead a full\n * next-page URL carrying its own `page=N` — and no `cursor=` param at all.\n *\n * Passing that whole URL straight through as `list()`'s own `cursor` used to\n * smuggle its embedded `source` / `per_page` / `sort` into the request on\n * top of the ones `list()` already sets unconditionally, producing a\n * doubled query string (`source=offers&source=offers&...`) the API can't\n * paginate from correctly — every subsequent scroll re-fetched the exact\n * same first page instead of advancing. Pulling just the `page` number back\n * out here, the same way an actual `cursor=` is already pulled out, keeps\n * `list()`'s request to the one copy of each param it's supposed to have.\n */\nexport function parseNextPageToken(nextUrl: string | null | undefined): {\n cursor?: string;\n page?: number;\n} {\n if (!nextUrl) return {};\n\n const cursorMatch = nextUrl.match(/[?&]cursor=([^&]+)/);\n if (cursorMatch) return { cursor: decodeURIComponent(cursorMatch[1]) };\n\n const pageMatch = nextUrl.match(/[?&]page=([^&]+)/);\n if (pageMatch) {\n const page = Number(decodeURIComponent(pageMatch[1]));\n if (Number.isFinite(page)) return { page };\n }\n\n // Neither pattern matched: not a URL at all, just the bare opaque token itself.\n return { cursor: nextUrl };\n}\n\n// ===== API Functions =====\n\nexport const product = {\n find: async (id: string): Promise<Product> => {\n const endpoint = `products/${id}/details?with[]=images&with[]=category&with[]=rating&with[]=notify_availability&with[]=tags&with[]=brand&with[]=options&with[]=skus&with[]=skus_availability&with[]=included_products&with[]=bundle&with[]=sold_quantity`;\n const { data } = await api.get(endpoint).json<{ data: Product }>();\n return data;\n },\n\n findOrThrow: (id: string): Promise<Product> => orThrow(product.find(id)),\n\n /** A tag's name. The list endpoint returns every product for an unknown tag; this one answers 410. */\n tag: async (id: string): Promise<{ id: number; name: string }> => {\n const { tag } = await api\n .get(`products/tags/${id}`)\n .json<{ tag: { id: number; name: string } }>();\n return tag;\n },\n\n /**\n * Fetch products list with pagination support\n * Used by native ProductsList component for SSR loaders\n *\n * API pattern: GET /products?source=wishlist&page=1\n */\n list: async (params: ProductsListParams): Promise<ProductsListResult> => {\n const {\n source,\n sourceValue,\n keyword,\n page,\n cursor,\n perPage = 16,\n sort,\n filterable,\n filters,\n signal,\n } = params;\n\n // Build URL with query parameters\n const searchParams = new URLSearchParams();\n searchParams.set('source', source);\n // Only send page when explicitly provided — cursor-based callers omit it entirely\n if (page !== undefined) searchParams.set('page', String(page));\n searchParams.set('per_page', String(perPage));\n\n appendSourceParams(searchParams, {\n source,\n sourceValue: (source === 'categories' && categoryFilterIds(filters)) || sourceValue,\n keyword,\n });\n appendFilterParams(searchParams, filters);\n\n // Add filterable parameter\n if (filterable !== undefined) {\n searchParams.set('filterable', filterable ? '1' : '0');\n }\n\n // Add sort parameter\n if (sort) {\n searchParams.set('sort', sort);\n }\n\n // Add cursor for cursor-based pagination\n if (cursor) {\n searchParams.set('cursor', cursor);\n }\n\n // Make the request\n const options: Record<string, unknown> = {};\n if (signal) options.signal = signal;\n\n const response = await api\n .get(`products?${searchParams.toString()}`, options as any)\n .json<ProductsListResponse>();\n\n const items = response.data ?? [];\n rememberProductPreviews(items);\n\n return {\n items,\n next: response.cursor?.next ?? null,\n filters: response.filters,\n };\n },\n\n queries: {\n detail: (id: string) =>\n queryOptions({\n // Stock and availability are resolved per branch allocation — same as the list.\n queryKey: productDetailQueryKey(id),\n queryFn: () => product.find(id),\n // List-card product, if one was remembered. Not written as the detail\n // cache entry — `queryFn` still hits products/{id}/details.\n placeholderData: () => getProductPreview(id),\n }),\n tag: (id: string) =>\n queryOptions({\n queryKey: ['products', 'tag', id],\n queryFn: () => product.tag(id),\n }),\n list: (params: Omit<ProductsListParams, 'signal'>) =>\n queryOptions({\n // Scope (branch) varies product availability — key must include it.\n queryKey: ['products', 'list', params, { scope: getActiveScope() }],\n queryFn: ({ signal }) => product.list({ ...params, signal }),\n }),\n },\n};\n"]}
@@ -1,5 +1,5 @@
1
- import { orThrow } from './chunk-JTOVO3ZU.js';
2
- import { api } from './chunk-QGOPTVV5.js';
1
+ import { orThrow } from './chunk-RWBTMHLR.js';
2
+ import { api } from './chunk-6EQ7G3SZ.js';
3
3
  import { queryOptions } from '@tanstack/react-query';
4
4
 
5
5
  var brand = {
@@ -25,5 +25,5 @@ var brand = {
25
25
  };
26
26
 
27
27
  export { brand };
28
- //# sourceMappingURL=chunk-LPQ5FUMJ.js.map
29
- //# sourceMappingURL=chunk-LPQ5FUMJ.js.map
28
+ //# sourceMappingURL=chunk-5SDCUGYR.js.map
29
+ //# sourceMappingURL=chunk-5SDCUGYR.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/api/brands.ts"],"names":[],"mappings":";;;;AAMO,IAAM,KAAA,GAAQ;AAAA,EACnB,IAAA,EAAM,OAAO,IAAA,KAAmD;AAC9D,IAAA,MAAM,EAAE,IAAA,EAAM,MAAA,EAAO,GAAI,MAAM,GAAA,CAC5B,GAAA,CAAI,IAAA,GAAO,CAAA,YAAA,EAAe,IAAI,CAAA,CAAA,GAAK,QAAQ,EAC3C,IAAA,EAAoD;AACvD,IAAA,OAAO,EAAE,OAAO,IAAA,IAAQ,IAAI,IAAA,EAAM,MAAA,EAAQ,QAAQ,IAAA,EAAK;AAAA,EACzD,CAAA;AAAA,EAEA,IAAA,EAAM,OAAO,EAAA,KAA+B;AAC1C,IAAA,MAAM,EAAE,IAAA,EAAK,GAAI,MAAM,GAAA,CAAI,IAAI,CAAA,OAAA,EAAU,EAAE,CAAA,CAAE,CAAA,CAAE,IAAA,EAAsB;AACrE,IAAA,OAAO,IAAA;AAAA,EACT,CAAA;AAAA,EAEA,aAAa,CAAC,EAAA,KAA+B,QAAQ,KAAA,CAAM,IAAA,CAAK,EAAE,CAAC,CAAA;AAAA,EAEnE,OAAA,EAAS;AAAA,IACP,IAAA,EAAM,CAAC,IAAA,KACL,YAAA,CAAa;AAAA,MACX,QAAA,EAAU,CAAC,QAAA,EAAU,MAAA,EAAQ,QAAQ,CAAC,CAAA;AAAA,MACtC,OAAA,EAAS,MAAM,KAAA,CAAM,IAAA,CAAK,IAAI;AAAA,KAC/B,CAAA;AAAA,IACH,MAAA,EAAQ,CAAC,EAAA,KACP,YAAA,CAAa;AAAA,MACX,QAAA,EAAU,CAAC,QAAA,EAAU,QAAA,EAAU,EAAE,CAAA;AAAA,MACjC,OAAA,EAAS,MAAM,KAAA,CAAM,IAAA,CAAK,EAAE;AAAA,KAC7B;AAAA;AAEP","file":"chunk-LPQ5FUMJ.js","sourcesContent":["import { queryOptions } from '@tanstack/react-query';\nimport { api } from './client';\nimport type { Brand } from '../routes/brands/types';\nimport type { PaginatedResult, Pagination } from './types';\nimport { orThrow } from '../providers/NavigationProvider';\n\nexport const brand = {\n list: async (page?: number): Promise<PaginatedResult<Brand>> => {\n const { data, cursor } = await api\n .get(page ? `brands?page=${page}` : 'brands')\n .json<{ data: Brand[] | null; cursor?: Pagination }>();\n return { items: data ?? [], next: cursor?.next ?? null };\n },\n\n find: async (id: string): Promise<Brand> => {\n const { data } = await api.get(`brands/${id}`).json<{ data: Brand }>();\n return data;\n },\n\n findOrThrow: (id: string): Promise<Brand> => orThrow(brand.find(id)),\n\n queries: {\n list: (page?: number) =>\n queryOptions({\n queryKey: ['brands', 'list', page ?? 1],\n queryFn: () => brand.list(page),\n }),\n detail: (id: string) =>\n queryOptions({\n queryKey: ['brands', 'detail', id],\n queryFn: () => brand.find(id),\n }),\n },\n};\n"]}
1
+ {"version":3,"sources":["../src/api/brands.ts"],"names":[],"mappings":";;;;AAMO,IAAM,KAAA,GAAQ;AAAA,EACnB,IAAA,EAAM,OAAO,IAAA,KAAmD;AAC9D,IAAA,MAAM,EAAE,IAAA,EAAM,MAAA,EAAO,GAAI,MAAM,GAAA,CAC5B,GAAA,CAAI,IAAA,GAAO,CAAA,YAAA,EAAe,IAAI,CAAA,CAAA,GAAK,QAAQ,EAC3C,IAAA,EAAoD;AACvD,IAAA,OAAO,EAAE,OAAO,IAAA,IAAQ,IAAI,IAAA,EAAM,MAAA,EAAQ,QAAQ,IAAA,EAAK;AAAA,EACzD,CAAA;AAAA,EAEA,IAAA,EAAM,OAAO,EAAA,KAA+B;AAC1C,IAAA,MAAM,EAAE,IAAA,EAAK,GAAI,MAAM,GAAA,CAAI,IAAI,CAAA,OAAA,EAAU,EAAE,CAAA,CAAE,CAAA,CAAE,IAAA,EAAsB;AACrE,IAAA,OAAO,IAAA;AAAA,EACT,CAAA;AAAA,EAEA,aAAa,CAAC,EAAA,KAA+B,QAAQ,KAAA,CAAM,IAAA,CAAK,EAAE,CAAC,CAAA;AAAA,EAEnE,OAAA,EAAS;AAAA,IACP,IAAA,EAAM,CAAC,IAAA,KACL,YAAA,CAAa;AAAA,MACX,QAAA,EAAU,CAAC,QAAA,EAAU,MAAA,EAAQ,QAAQ,CAAC,CAAA;AAAA,MACtC,OAAA,EAAS,MAAM,KAAA,CAAM,IAAA,CAAK,IAAI;AAAA,KAC/B,CAAA;AAAA,IACH,MAAA,EAAQ,CAAC,EAAA,KACP,YAAA,CAAa;AAAA,MACX,QAAA,EAAU,CAAC,QAAA,EAAU,QAAA,EAAU,EAAE,CAAA;AAAA,MACjC,OAAA,EAAS,MAAM,KAAA,CAAM,IAAA,CAAK,EAAE;AAAA,KAC7B;AAAA;AAEP","file":"chunk-5SDCUGYR.js","sourcesContent":["import { queryOptions } from '@tanstack/react-query';\nimport { api } from './client';\nimport type { Brand } from '../routes/brands/types';\nimport type { PaginatedResult, Pagination } from './types';\nimport { orThrow } from '../providers/NavigationProvider';\n\nexport const brand = {\n list: async (page?: number): Promise<PaginatedResult<Brand>> => {\n const { data, cursor } = await api\n .get(page ? `brands?page=${page}` : 'brands')\n .json<{ data: Brand[] | null; cursor?: Pagination }>();\n return { items: data ?? [], next: cursor?.next ?? null };\n },\n\n find: async (id: string): Promise<Brand> => {\n const { data } = await api.get(`brands/${id}`).json<{ data: Brand }>();\n return data;\n },\n\n findOrThrow: (id: string): Promise<Brand> => orThrow(brand.find(id)),\n\n queries: {\n list: (page?: number) =>\n queryOptions({\n queryKey: ['brands', 'list', page ?? 1],\n queryFn: () => brand.list(page),\n }),\n detail: (id: string) =>\n queryOptions({\n queryKey: ['brands', 'detail', id],\n queryFn: () => brand.find(id),\n }),\n },\n};\n"]}
@@ -1,4 +1,5 @@
1
- import { AUTH_TOKEN_COOKIE_NAME, extractTokenFromCookies, toCurrencyCode, CURRENCY_COOKIE_NAME, getInjectedRuntimeEnv, readEnv, getStoreIdentifier, readSdkScope, extractScopeFromCookies, extractCurrencyFromCookies } from './chunk-HSWRYXC7.js';
1
+ import { getStoreIdentifier } from './chunk-2FKZAAV7.js';
2
+ import { AUTH_TOKEN_COOKIE_NAME, extractTokenFromCookies, toCurrencyCode, CURRENCY_COOKIE_NAME, getInjectedRuntimeEnv, readEnv, readSdkScope, extractScopeFromCookies, extractCurrencyFromCookies } from './chunk-FO4WVGUQ.js';
2
3
  import { getTwilightContext, getRequestStore } from './chunk-N2S25NXP.js';
3
4
  import ky from 'ky';
4
5
  import { createIsomorphicFn } from '@tanstack/react-start';
@@ -152,5 +153,5 @@ var filesCdn = ky.extend({
152
153
  });
153
154
 
154
155
  export { STORE_IDENTIFIER_HEADER, api, cdn, filesCdn, getActiveCurrency, getActiveScope, getActiveScopeId, getAuthToken, requestedThemeVersionId };
155
- //# sourceMappingURL=chunk-QGOPTVV5.js.map
156
- //# sourceMappingURL=chunk-QGOPTVV5.js.map
156
+ //# sourceMappingURL=chunk-6EQ7G3SZ.js.map
157
+ //# sourceMappingURL=chunk-6EQ7G3SZ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/theme-version.ts","../src/api/client.ts"],"names":[],"mappings":"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","file":"chunk-6EQ7G3SZ.js","sourcesContent":["/**\n * @fileoverview Which version of the theme's settings to render — the one answer,\n * in one place.\n *\n * A merchant's theme settings are versioned. An ordinary storefront visit names\n * no version and gets the live one; the API decides, and reports it back as\n * `theme.profile.id`. Two surfaces need a different one, and both address it in\n * the URL of an iframe:\n *\n * - the merchant's theme editor at `s.salla.sa/themes/editor/…`, which shows a\n * draft version beside the controls that are editing it;\n * - a partner running the theme locally, whose dev server is the iframe.\n *\n * Written as a module of its own rather than inline at the one call site,\n * because `store-identity.ts` exists for exactly this reason: the identifier a\n * request resolved and the identifier it sent were two different values for\n * days, in two files, and every test passed. A second implementation of this is\n * the bug, not a refactor away from one.\n */\nimport { getRequestStore, getTwilightContext } from '../twilight/context';\nimport type { StoreContext } from '../api/store';\nimport { getInjectedRuntimeEnv } from './runtime-env';\n\n/**\n * The version this request asked for, or null when it asked for none.\n *\n * Deliberately excludes the version the *settings* name. This is the answer to\n * \"what did the caller address?\", and it has to be available before any settings\n * exist — React Query keys are built from it, and a key that means one thing\n * during SSR and another after hydration is how a page refetches everything it\n * was just handed.\n *\n * 1. what the request named, seeded by `twilightMiddleware` on a host permitted\n * to name one;\n * 2. what SSR resolved and published into the head, which is all the browser has\n * once the dispatcher has stripped `?versionId=` from the URL.\n */\nexport function requestedThemeVersionId(): string | null {\n const { versionId } = getRequestStore();\n if (versionId) return versionId;\n\n return getInjectedRuntimeEnv().versionId || null;\n}\n\n/**\n * The version every Salla API call is answered with — what goes in `s-version-id`.\n *\n * The requested version outranks the settings, because a request that named one\n * is the only reason this is ever anything but the live version: falling back to\n * the settings there would let the first answer overwrite the question.\n *\n * The settings' own `theme.profile.id` stays as the fallback, unchanged. It is\n * what this header has always carried, and on an ordinary storefront it still\n * is — it keeps the rest of a page's calls pinned to the version the settings\n * call resolved, rather than letting a version go live mid-render.\n *\n * That pin is only good for the scope the settings were requested with. Each\n * market (scope) has its own version, and the API lets a named version outrank\n * the market's: once the shopper switches market, the loaded settings still\n * describe the previous one, and replaying their version — on the settings call\n * for the new market first of all — gets the previous market's theme back, for\n * good. So the version is replayed only while the active scope is the one the\n * settings were answered for (`store.scope`), which is not always the one they\n * were requested for (`requestedScopeId`): the API falls back to another scope\n * when it does not accept the requested one, and that scope's version must not\n * ride along on the next request for the requested one. With no active scope it\n * is replayed only for settings requested without one. Otherwise nothing is\n * sent and the API picks the version of the scope on the request.\n *\n * `activeScopeId` is passed in by the caller that already resolved the scope for\n * its `s-scope-*` headers.\n *\n * Reading the settings is guarded because `getTwilightContext().settings` throws\n * a `SettingsError` when they have not loaded — which is the normal state on the\n * very first call, the settings call itself.\n */\n/** Whether `settings` were answered for `activeScopeId` (see {@link resolveThemeVersionId}). */\nfunction answersScope(settings: StoreContext | null | undefined, activeScopeId: string | null) {\n const requestedScopeId = settings?.requestedScopeId ?? null;\n if (activeScopeId == null) return requestedScopeId == null;\n const answeredScopeId = settings?.store?.scope?.id;\n return (answeredScopeId != null ? String(answeredScopeId) : requestedScopeId) === activeScopeId;\n}\n\nexport function resolveThemeVersionId(activeScopeId: string | null = null): string | null {\n const requested = requestedThemeVersionId();\n if (requested) return requested;\n\n try {\n const settings = getTwilightContext().settings;\n if (!answersScope(settings, activeScopeId)) return null;\n\n const profileId = settings?.theme?.profile?.id;\n return profileId != null ? String(profileId) : null;\n } catch {\n return null;\n }\n}\n","import ky from 'ky';\nimport { createIsomorphicFn } from '@tanstack/react-start';\nimport { getCookie } from '@tanstack/react-start/server';\nimport { getStoreIdentifier } from '../utils/sdk-helpers';\nimport { resolveThemeVersionId } from '../utils/theme-version';\nimport { getInjectedRuntimeEnv, readEnv } from '../utils/runtime-env';\nimport { getTwilightContext } from '../twilight/context';\nimport {\n AUTH_TOKEN_COOKIE_NAME,\n CURRENCY_COOKIE_NAME,\n extractCurrencyFromCookies,\n extractScopeFromCookies,\n toCurrencyCode,\n extractTokenFromCookies,\n readSdkScope,\n type ActiveScope,\n} from '../utils/cookies';\n\n// The twilight module store doesn't reliably carry authToken into every scope: on the\n// SERVER workerd has no AsyncLocalStorage, and on BOTH sides this api client can live in a\n// different module instance than the one rootBeforeLoad populates (engine subpath import vs\n// engine-internal relative import). So `getTwilightContext().authToken` is often null even\n// for logged-in users → API calls (orders/customer/…) return `token_not_provided` (400).\n// Read the token directly from the request cookie (server) or document.cookie / salla.storage\n// (client) as a fallback. The server-only import is stripped from the client bundle by\n// createIsomorphicFn.\nconst readFallbackToken = createIsomorphicFn()\n .server((): string | null => {\n try {\n return getCookie(AUTH_TOKEN_COOKIE_NAME) ?? null;\n } catch {\n return null;\n }\n })\n .client((): string | null => {\n const fromCookie =\n typeof document !== 'undefined'\n ? extractTokenFromCookies(document.cookie, AUTH_TOKEN_COOKIE_NAME)\n : null;\n if (fromCookie) return fromCookie;\n const storage = typeof window !== 'undefined' ? window.salla?.storage : undefined;\n const fromStorage =\n typeof storage?.get === 'function' ? storage.get(AUTH_TOKEN_COOKIE_NAME) : null;\n if (typeof fromStorage === 'string' && fromStorage) return fromStorage;\n // `?token=` webview injection lands only on the SDK's axios instance\n const fromSdkApi = typeof window !== 'undefined' ? window.salla?.api?.token : undefined;\n return typeof fromSdkApi === 'string' && fromSdkApi ? fromSdkApi : null;\n });\n\n/**\n * The auth token as the api client sees it: twilight context first, cookie/storage fallback.\n * Use this (not `getTwilightContext().authToken`, which is often null for logged-in users —\n * see the note above) to decide whether an authenticated-only query should run.\n */\nexport const getAuthToken = (): string | null =>\n getTwilightContext().authToken ?? readFallbackToken();\n\nconst readRequestCurrency = createIsomorphicFn()\n .server((): string | null => {\n try {\n return toCurrencyCode(getCookie(CURRENCY_COOKIE_NAME));\n } catch {\n return null;\n }\n })\n .client((): string | null => null);\n\n/**\n * The currency the visitor chose, from the `s-curr` cookie the SDK writes: the API\n * answers in the store's own currency unless the request names one.\n */\nexport function getActiveCurrency(): string | null;\nexport function getActiveCurrency(fallback: string): string;\nexport function getActiveCurrency(fallback: string | null = null): string | null {\n const chosen =\n typeof document !== 'undefined'\n ? extractCurrencyFromCookies(document.cookie)\n : readRequestCurrency();\n return chosen ?? fallback;\n}\n\nconst API_HEADERS = {\n ACCEPT: 'accept',\n ACCEPT_LANGUAGE: 'accept-language',\n APP_OS: 's-app-os',\n APP_VERSION: 's-app-version',\n RAY: 's-ray',\n SOURCE: 's-source',\n THEME_TYPE: 's-theme-type',\n STORE_API_VERSION: 's-store-api-version',\n REQUESTED_WITH: 'x-requested-with',\n CF_PROXY_WHITELIST: 's-cf-proxy-whitelist-id',\n STORE_IDENTIFIER: 'store-identifier',\n CURRENCY: 'currency',\n AUTHORIZATION: 'Authorization',\n VERSION_ID: 's-version-id',\n SCOPE_ID: 's-scope-id',\n SCOPE_TYPE: 's-scope-type',\n SCOPE_ALLOCATION_TYPE: 's-scope-allocation-type',\n SCOPE_ALLOCATION_ID: 's-scope-allocation-id',\n} as const;\n\n/**\n * The header every Salla API call is answered by store.\n *\n * Exported because a caller that already knows which store it is asking about\n * must be able to say so on the request itself — see `store.settings`. Without\n * it the only way to name a store is the ambient resolver, and \"the identifier\n * I checked\" and \"the identifier that was sent\" become two different things.\n */\nexport const STORE_IDENTIFIER_HEADER = API_HEADERS.STORE_IDENTIFIER;\n\n/**\n * Active scope: the market plus its branch allocation, as the SDK stores it. On the\n * client it comes from `salla.storage.get('scope')`; before the SDK hydrates storage\n * it falls back to the `scope` cookie the theme mirrors that selection into (see\n * writeScopeCookie), then to the scope twilightMiddleware seeded from the same\n * cookie on the server. Requests vary by the `s-scope-*` headers, so React Query\n * keys must include this to avoid serving another branch's cached categories/products.\n *\n * The cookie step matters for hydration: the SDK is not guaranteed to have\n * populated `salla.storage` by the time the client rebuilds a dehydrated query\n * key, and without it the client would compute null against a scoped SSR key.\n */\nexport const getActiveScope = (): ActiveScope | null => {\n // `!== undefined`, not `!= null`: a null here is the SDK authoritatively saying \"no branch\n // selected\", which must beat a cookie left over from the previous selection. Only a\n // not-yet-ready storage API (undefined) falls through to the cookie.\n const fromStorage = readSdkScope();\n if (fromStorage !== undefined) return fromStorage;\n\n if (typeof document !== 'undefined') {\n const fromCookie = extractScopeFromCookies(document.cookie);\n if (fromCookie != null) return fromCookie;\n }\n\n try {\n return getTwilightContext().scope;\n } catch {\n return null;\n }\n};\n\n/** {@link getActiveScope} reduced to the market id. */\nexport const getActiveScopeId = (): string | null => getActiveScope()?.id ?? null;\n\nconst sharedHeaders = (locale: string) => ({\n [API_HEADERS.ACCEPT]: 'application/json' as const,\n [API_HEADERS.ACCEPT_LANGUAGE]: locale,\n [API_HEADERS.APP_OS]: 'browser',\n [API_HEADERS.APP_VERSION]: '2.14.363',\n [API_HEADERS.RAY]: '50',\n [API_HEADERS.SOURCE]: 'twilight',\n [API_HEADERS.THEME_TYPE]: 'react',\n [API_HEADERS.STORE_API_VERSION]: 'swoole',\n [API_HEADERS.REQUESTED_WITH]: 'XMLHttpRequest',\n [API_HEADERS.CF_PROXY_WHITELIST]: '019a2f78-a64c-7edb-proxy-whitelist-id-9a3a-17afda90f03a',\n});\n\n/**\n * Store API base. `VITE_API_URL` override points a preview at a branch backend; unset → prod\n * `api.salla.dev`. Resolution order matters: the value the SSR worker resolved (published into\n * the head, since worker `vars` are server-only `process.env` and never reach the browser\n * bundle) wins, so the hydrated client keeps talking to the backend that rendered the page.\n */\n\nconst STORE_API_BASE =\n getInjectedRuntimeEnv().apiBase || readEnv('VITE_API_URL') || 'https://api.salla.dev/store/v1';\n\nexport const api = ky.extend({\n prefix: STORE_API_BASE,\n timeout: 8000,\n hooks: {\n beforeRequest: [\n ({ request }) => {\n const { locale, authToken } = getTwilightContext();\n const headers = sharedHeaders(locale);\n for (const [key, value] of Object.entries(headers)) {\n request.headers.set(key, value);\n }\n // Only when the caller did not say. `headers.set` here would otherwise\n // overwrite a per-request identifier with the ambient one, which is a\n // silent way to answer a question about one store with another's data.\n if (!request.headers.get(API_HEADERS.STORE_IDENTIFIER)) {\n request.headers.set(API_HEADERS.STORE_IDENTIFIER, getStoreIdentifier());\n }\n\n const scope = getActiveScope();\n\n // The version the request asked for, else the one the settings named for\n // this scope. Absent means \"whatever is live\", which is what an ordinary\n // storefront visit wants — so a null is left off rather than sent empty.\n const versionId = resolveThemeVersionId(scope?.id ?? null);\n if (versionId) {\n request.headers.set(API_HEADERS.VERSION_ID, versionId);\n }\n\n const currency = getActiveCurrency();\n if (currency) request.headers.set(API_HEADERS.CURRENCY, currency);\n\n const token = authToken ?? readFallbackToken();\n if (token) {\n request.headers.set(API_HEADERS.AUTHORIZATION, `Bearer ${token}`);\n }\n\n // The same four the SDK's own client sends. The API resolves stock per\n // allocation: id alone asks about the market, not the branch the shopper chose.\n if (scope) {\n request.headers.set(API_HEADERS.SCOPE_ID, scope.id);\n if (scope.type) request.headers.set(API_HEADERS.SCOPE_TYPE, scope.type);\n if (scope.allocation_type)\n request.headers.set(API_HEADERS.SCOPE_ALLOCATION_TYPE, scope.allocation_type);\n if (scope.allocation_id)\n request.headers.set(API_HEADERS.SCOPE_ALLOCATION_ID, scope.allocation_id);\n }\n },\n ],\n },\n});\n\nexport const cdn = ky.extend({\n prefix: 'https://cdn.salla.network',\n timeout: 5000,\n});\n\n/**\n * The merchant uploader's public bucket, `admin-uploader-prod`.\n *\n * A different host from {@link cdn} and a different thing behind it: this one\n * is an R2 custom domain, so a read never passes through a worker. Storefront\n * translations live here, per language, under `translations/` — see\n * `api/translations.ts`.\n */\nexport const filesCdn = ky.extend({\n prefix: 'https://cdn.files.salla.network',\n timeout: 5000,\n});\n"]}
@@ -1,4 +1,4 @@
1
- import { getActiveScope, api } from './chunk-QGOPTVV5.js';
1
+ import { getActiveScope, api } from './chunk-6EQ7G3SZ.js';
2
2
  import { queryOptions } from '@tanstack/react-query';
3
3
 
4
4
  async function list(params) {
@@ -45,5 +45,5 @@ var home = {
45
45
  };
46
46
 
47
47
  export { home };
48
- //# sourceMappingURL=chunk-FZYR4BA2.js.map
49
- //# sourceMappingURL=chunk-FZYR4BA2.js.map
48
+ //# sourceMappingURL=chunk-7WTUA4WY.js.map
49
+ //# sourceMappingURL=chunk-7WTUA4WY.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/api/home.ts"],"names":[],"mappings":";;;AAQA,eAAe,KAAK,MAAA,EAA+D;AACjF,EAAA,MAAM,KAAA,GAAQ,SAAS,CAAA,CAAA,EAAI,IAAI,gBAAgB,MAAM,CAAA,CAAE,QAAA,EAAU,CAAA,CAAA,GAAK,EAAA;AACtE,EAAA,MAAM,EAAE,IAAA,EAAK,GAAI,MAAM,GAAA,CAAI,IAAI,CAAA,cAAA,EAAiB,KAAK,CAAA,CAAE,CAAA,CAAE,IAAA,EAAoC;AAC7F,EAAA,OAAO,QAAQ,EAAC;AAClB;AAGA,SAAS,OAAA,CAAQ,QAA6B,QAAA,EAAoD;AAChG,EAAA,IAAI,CAAC,QAAA,CAAS,MAAA,EAAQ,OAAO,MAAA;AAC7B,EAAA,MAAM,KAAA,GAAQ,IAAI,GAAA,CAAI,QAAA,CAAS,IAAI,CAAC,KAAA,KAAU,KAAA,CAAM,IAAI,CAAC,CAAA;AACzD,EAAA,MAAM,IAAA,GAAO,SAAS,GAAA,CAAI,CAAC,UAAU,IAAA,CAAK,SAAA,CAAU,KAAK,CAAC,CAAA;AAC1D,EAAA,OAAO,MAAA,CAAO,MAAA,CAAO,CAAC,KAAA,KAAU;AAC9B,IAAA,IAAI,CAAC,KAAA,CAAM,GAAA,CAAI,KAAA,CAAM,IAAI,GAAG,OAAO,IAAA;AACnC,IAAA,MAAM,QAAQ,IAAA,CAAK,OAAA,CAAQ,IAAA,CAAK,SAAA,CAAU,KAAK,CAAC,CAAA;AAChD,IAAA,IAAI,KAAA,KAAU,IAAI,OAAO,IAAA;AACzB,IAAA,IAAA,CAAK,MAAA,CAAO,OAAO,CAAC,CAAA;AACpB,IAAA,OAAO,KAAA;AAAA,EACT,CAAC,CAAA;AACH;AAEO,IAAM,IAAA,GAAO;AAAA,EAClB,YAAY,YAA0C;AAEpD,IAAA,MAAM,CAAC,MAAA,EAAQ,UAAU,CAAA,GAAI,MAAM,QAAQ,GAAA,CAAI,CAAC,IAAA,EAAK,EAAG,KAAK,EAAE,OAAA,EAAS,OAAA,EAAS,CAAC,CAAC,CAAA;AACnF,IAAA,OAAO,OAAA,CAAQ,QAAQ,UAAU,CAAA;AAAA,EACnC,CAAA;AAAA;AAAA,EAGA,MAAA,EAAQ,OAAO,IAAA,EAAc,KAAA,KAAoD;AAC/E,IAAA,MAAM,cAAc,MAAA,CAAO,WAAA;AAAA,MACzB,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAA,CAAE,IAAI,CAAC,CAAC,GAAA,EAAK,EAAE,MAAM,CAAC,GAAA,EAAK,MAAA,CAAO,EAAE,CAAC,CAAC;AAAA,KAC5D;AACA,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,EAAE,OAAO,IAAA,EAAM,GAAG,aAAa,CAAA;AACzD,IAAA,OAAO,MAAA,CAAO,GAAA,CAAI,CAAC,KAAA,MAAW,EAAE,GAAG,KAAA,EAAO,IAAA,EAAM,KAAA,CAAM,IAAA,CAAK,OAAA,CAAQ,OAAA,EAAS,EAAE,GAAE,CAAE,CAAA;AAAA,EACpF,CAAA;AAAA,EAEA,OAAA,EAAS;AAAA,IACP,UAAA,EAAY,MACV,YAAA,CAAa;AAAA;AAAA,MAEX,QAAA,EAAU,CAAC,MAAA,EAAQ,YAAA,EAAc,EAAE,KAAA,EAAO,cAAA,IAAkB,CAAA;AAAA,MAC5D,OAAA,EAAS,MAAM,IAAA,CAAK,UAAA;AAAW,KAChC,CAAA;AAAA,IAEH,MAAA,EAAQ,CAAC,IAAA,EAAc,KAAA,KACrB,YAAA,CAAa;AAAA,MACX,QAAA,EAAU,CAAC,MAAA,EAAQ,QAAA,EAAU,MAAM,KAAK,CAAA;AAAA,MACxC,OAAA,EAAS,MAAM,IAAA,CAAK,MAAA,CAAO,MAAM,KAAK;AAAA,KACvC;AAAA;AAEP","file":"chunk-FZYR4BA2.js","sourcesContent":["import { queryOptions } from '@tanstack/react-query';\nimport { api, getActiveScope } from './client';\nimport type { HomeComponentData } from '../types';\n\n/** The page a hook's blocks render on; blocks can target specific products, categories or pages. */\nexport type BlockScope =\n { product_id: number | string } | { category_id: number | string } | { page_id: number | string };\n\nasync function list(params?: Record<string, string>): Promise<HomeComponentData[]> {\n const query = params ? `?${new URLSearchParams(params).toString()}` : '';\n const { data } = await api.get(`component/list${query}`).json<{ data: HomeComponentData[] }>();\n return data ?? [];\n}\n\n/** `blocks` minus each of `excluded`, matched by content: the API sends no id or order to match on. */\nfunction without(blocks: HomeComponentData[], excluded: HomeComponentData[]): HomeComponentData[] {\n if (!excluded.length) return blocks;\n const paths = new Set(excluded.map((block) => block.path));\n const left = excluded.map((block) => JSON.stringify(block));\n return blocks.filter((block) => {\n if (!paths.has(block.path)) return true;\n const index = left.indexOf(JSON.stringify(block));\n if (index === -1) return true;\n left.splice(index, 1);\n return false;\n });\n}\n\nexport const home = {\n components: async (): Promise<HomeComponentData[]> => {\n // The unfiltered list also has the product, category and page blocks, which the home leaves out.\n const [blocks, pageBlocks] = await Promise.all([list(), list({ show_in: 'pages' })]);\n return without(blocks, pageBlocks);\n },\n\n /** The blocks the merchant placed at `hook` on a product, category or page. */\n blocks: async (hook: string, scope: BlockScope): Promise<HomeComponentData[]> => {\n const scopeParams = Object.fromEntries(\n Object.entries(scope).map(([key, id]) => [key, String(id)])\n );\n const blocks = await list({ hooks: hook, ...scopeParams });\n return blocks.map((block) => ({ ...block, path: block.path.replace('home.', '') }));\n },\n\n queries: {\n components: () =>\n queryOptions({\n // Each market (scope) has its own theme version, and its own home page with it.\n queryKey: ['home', 'components', { scope: getActiveScope() }],\n queryFn: () => home.components(),\n }),\n\n blocks: (hook: string, scope: BlockScope) =>\n queryOptions({\n queryKey: ['home', 'blocks', hook, scope],\n queryFn: () => home.blocks(hook, scope),\n }),\n },\n};\n"]}
1
+ {"version":3,"sources":["../src/api/home.ts"],"names":[],"mappings":";;;AAQA,eAAe,KAAK,MAAA,EAA+D;AACjF,EAAA,MAAM,KAAA,GAAQ,SAAS,CAAA,CAAA,EAAI,IAAI,gBAAgB,MAAM,CAAA,CAAE,QAAA,EAAU,CAAA,CAAA,GAAK,EAAA;AACtE,EAAA,MAAM,EAAE,IAAA,EAAK,GAAI,MAAM,GAAA,CAAI,IAAI,CAAA,cAAA,EAAiB,KAAK,CAAA,CAAE,CAAA,CAAE,IAAA,EAAoC;AAC7F,EAAA,OAAO,QAAQ,EAAC;AAClB;AAGA,SAAS,OAAA,CAAQ,QAA6B,QAAA,EAAoD;AAChG,EAAA,IAAI,CAAC,QAAA,CAAS,MAAA,EAAQ,OAAO,MAAA;AAC7B,EAAA,MAAM,KAAA,GAAQ,IAAI,GAAA,CAAI,QAAA,CAAS,IAAI,CAAC,KAAA,KAAU,KAAA,CAAM,IAAI,CAAC,CAAA;AACzD,EAAA,MAAM,IAAA,GAAO,SAAS,GAAA,CAAI,CAAC,UAAU,IAAA,CAAK,SAAA,CAAU,KAAK,CAAC,CAAA;AAC1D,EAAA,OAAO,MAAA,CAAO,MAAA,CAAO,CAAC,KAAA,KAAU;AAC9B,IAAA,IAAI,CAAC,KAAA,CAAM,GAAA,CAAI,KAAA,CAAM,IAAI,GAAG,OAAO,IAAA;AACnC,IAAA,MAAM,QAAQ,IAAA,CAAK,OAAA,CAAQ,IAAA,CAAK,SAAA,CAAU,KAAK,CAAC,CAAA;AAChD,IAAA,IAAI,KAAA,KAAU,IAAI,OAAO,IAAA;AACzB,IAAA,IAAA,CAAK,MAAA,CAAO,OAAO,CAAC,CAAA;AACpB,IAAA,OAAO,KAAA;AAAA,EACT,CAAC,CAAA;AACH;AAEO,IAAM,IAAA,GAAO;AAAA,EAClB,YAAY,YAA0C;AAEpD,IAAA,MAAM,CAAC,MAAA,EAAQ,UAAU,CAAA,GAAI,MAAM,QAAQ,GAAA,CAAI,CAAC,IAAA,EAAK,EAAG,KAAK,EAAE,OAAA,EAAS,OAAA,EAAS,CAAC,CAAC,CAAA;AACnF,IAAA,OAAO,OAAA,CAAQ,QAAQ,UAAU,CAAA;AAAA,EACnC,CAAA;AAAA;AAAA,EAGA,MAAA,EAAQ,OAAO,IAAA,EAAc,KAAA,KAAoD;AAC/E,IAAA,MAAM,cAAc,MAAA,CAAO,WAAA;AAAA,MACzB,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAA,CAAE,IAAI,CAAC,CAAC,GAAA,EAAK,EAAE,MAAM,CAAC,GAAA,EAAK,MAAA,CAAO,EAAE,CAAC,CAAC;AAAA,KAC5D;AACA,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,EAAE,OAAO,IAAA,EAAM,GAAG,aAAa,CAAA;AACzD,IAAA,OAAO,MAAA,CAAO,GAAA,CAAI,CAAC,KAAA,MAAW,EAAE,GAAG,KAAA,EAAO,IAAA,EAAM,KAAA,CAAM,IAAA,CAAK,OAAA,CAAQ,OAAA,EAAS,EAAE,GAAE,CAAE,CAAA;AAAA,EACpF,CAAA;AAAA,EAEA,OAAA,EAAS;AAAA,IACP,UAAA,EAAY,MACV,YAAA,CAAa;AAAA;AAAA,MAEX,QAAA,EAAU,CAAC,MAAA,EAAQ,YAAA,EAAc,EAAE,KAAA,EAAO,cAAA,IAAkB,CAAA;AAAA,MAC5D,OAAA,EAAS,MAAM,IAAA,CAAK,UAAA;AAAW,KAChC,CAAA;AAAA,IAEH,MAAA,EAAQ,CAAC,IAAA,EAAc,KAAA,KACrB,YAAA,CAAa;AAAA,MACX,QAAA,EAAU,CAAC,MAAA,EAAQ,QAAA,EAAU,MAAM,KAAK,CAAA;AAAA,MACxC,OAAA,EAAS,MAAM,IAAA,CAAK,MAAA,CAAO,MAAM,KAAK;AAAA,KACvC;AAAA;AAEP","file":"chunk-7WTUA4WY.js","sourcesContent":["import { queryOptions } from '@tanstack/react-query';\nimport { api, getActiveScope } from './client';\nimport type { HomeComponentData } from '../types';\n\n/** The page a hook's blocks render on; blocks can target specific products, categories or pages. */\nexport type BlockScope =\n { product_id: number | string } | { category_id: number | string } | { page_id: number | string };\n\nasync function list(params?: Record<string, string>): Promise<HomeComponentData[]> {\n const query = params ? `?${new URLSearchParams(params).toString()}` : '';\n const { data } = await api.get(`component/list${query}`).json<{ data: HomeComponentData[] }>();\n return data ?? [];\n}\n\n/** `blocks` minus each of `excluded`, matched by content: the API sends no id or order to match on. */\nfunction without(blocks: HomeComponentData[], excluded: HomeComponentData[]): HomeComponentData[] {\n if (!excluded.length) return blocks;\n const paths = new Set(excluded.map((block) => block.path));\n const left = excluded.map((block) => JSON.stringify(block));\n return blocks.filter((block) => {\n if (!paths.has(block.path)) return true;\n const index = left.indexOf(JSON.stringify(block));\n if (index === -1) return true;\n left.splice(index, 1);\n return false;\n });\n}\n\nexport const home = {\n components: async (): Promise<HomeComponentData[]> => {\n // The unfiltered list also has the product, category and page blocks, which the home leaves out.\n const [blocks, pageBlocks] = await Promise.all([list(), list({ show_in: 'pages' })]);\n return without(blocks, pageBlocks);\n },\n\n /** The blocks the merchant placed at `hook` on a product, category or page. */\n blocks: async (hook: string, scope: BlockScope): Promise<HomeComponentData[]> => {\n const scopeParams = Object.fromEntries(\n Object.entries(scope).map(([key, id]) => [key, String(id)])\n );\n const blocks = await list({ hooks: hook, ...scopeParams });\n return blocks.map((block) => ({ ...block, path: block.path.replace('home.', '') }));\n },\n\n queries: {\n components: () =>\n queryOptions({\n // Each market (scope) has its own theme version, and its own home page with it.\n queryKey: ['home', 'components', { scope: getActiveScope() }],\n queryFn: () => home.components(),\n }),\n\n blocks: (hook: string, scope: BlockScope) =>\n queryOptions({\n queryKey: ['home', 'blocks', hook, scope],\n queryFn: () => home.blocks(hook, scope),\n }),\n },\n};\n"]}
@@ -1,4 +1,4 @@
1
- import { isNativeApp } from './chunk-JJARU7YP.js';
1
+ import { isNativeApp } from './chunk-EWLVLDRP.js';
2
2
  import { useTwilight } from './chunk-DF6FBKDN.js';
3
3
  import { useRef, useState, useEffect } from 'react';
4
4
  import { toast, Toaster as Toaster$1 } from 'sonner';
@@ -137,5 +137,5 @@ function Toaster({
137
137
  }
138
138
 
139
139
  export { Toaster };
140
- //# sourceMappingURL=chunk-3PXONLUK.js.map
141
- //# sourceMappingURL=chunk-3PXONLUK.js.map
140
+ //# sourceMappingURL=chunk-BH7YNCYB.js.map
141
+ //# sourceMappingURL=chunk-BH7YNCYB.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/toast/Toaster.tsx"],"names":["SonnerToaster"],"mappings":"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","file":"chunk-3PXONLUK.js","sourcesContent":["import { useEffect, useRef, useState } from 'react';\nimport { Toaster as SonnerToaster, toast } from 'sonner';\nimport { useTwilight } from '../../providers/twilight-context';\nimport { isNativeApp } from '../../native-app';\nimport type { ToastPosition } from './types';\n\nconst toastClassNames = {\n toast: 'group bg-white border-2 rounded-xl shadow-2xl p-4 font-primary',\n title: 'text-base font-bold',\n description: 'text-sm mt-1 text-gray-600',\n actionButton: 'bg-primary text-white px-3 py-1 rounded',\n cancelButton: 'bg-gray-100 px-3 py-1 rounded',\n success: 'border-green-500 [&_svg]:text-green-500 [&_aside]:text-green-700',\n error: 'border-red-500 [&_svg]:text-red-500 [&_aside]:text-red-700',\n warning: 'border-yellow-500 [&_svg]:text-yellow-500 [&_aside]:text-yellow-700',\n info: 'border-blue-500 [&_svg]:text-blue-500 [&_aside]:text-blue-700',\n loading: 'border-gray-400',\n};\n\ntype RawMessage = string | { title?: string; text?: string; icon?: string };\ntype ToastVariant = 'success' | 'error' | 'warning' | 'info';\n\nconst MOBILE_BREAKPOINT = 768;\nconst NATIVE_ALERT_EVENT = 'ui::alert';\n\nfunction dispatchNativeAlert(type: ToastVariant, message: string, title?: string) {\n const salla = window.salla;\n if (!isNativeApp() || !salla?.event?.dispatch) return false;\n\n salla.event.dispatch(NATIVE_ALERT_EVENT, {\n type,\n message,\n ...(title ? { title } : {}),\n });\n return true;\n}\n\nexport function Toaster({\n mobilePosition = 'bottom-center',\n addToCartToast = true,\n}: {\n mobilePosition?: ToastPosition;\n /** Show the default add-to-cart toast. Themes whose cart badge is the feedback can turn it off. */\n addToCartToast?: boolean;\n}) {\n const { theme } = useTwilight();\n const themeRef = useRef(theme);\n themeRef.current = theme;\n const flashShownRef = useRef(false);\n\n const isRtl = theme.is_rtl;\n const desktopPosition: ToastPosition = isRtl ? 'top-left' : 'top-right';\n\n const [position, setPosition] = useState<ToastPosition>(() => {\n if (typeof window === 'undefined') return desktopPosition;\n return window.innerWidth < MOBILE_BREAKPOINT ? mobilePosition : desktopPosition;\n });\n\n useEffect(() => {\n const handleResize = () => {\n setPosition(window.innerWidth < MOBILE_BREAKPOINT ? mobilePosition : desktopPosition);\n };\n window.addEventListener('resize', handleResize);\n return () => window.removeEventListener('resize', handleResize);\n }, [desktopPosition, mobilePosition]);\n\n useEffect(() => {\n const salla = window.salla;\n if (!salla) return;\n let active = true;\n\n const handleNotify = (message: RawMessage, type: string, data?: unknown) => {\n const eventData = data as { data?: { googleTags?: { event?: string } } } | undefined;\n const shouldSuppressAddToCartToast =\n (!addToCartToast || themeRef.current.settings?.enable_add_product_toast) &&\n eventData?.data?.googleTags?.event === 'addToCart';\n let title: string;\n let toastType: ToastVariant;\n\n if (typeof message === 'object' && message !== null) {\n title = message.title || message.text || '';\n toastType = (message.icon || type || 'info') as ToastVariant;\n } else {\n title = message;\n toastType = (type || 'info') as ToastVariant;\n }\n\n // Suppress the default addToCart toast when the theme opted out (addToCartToast=false)\n // or renders its own rich toast (enable_add_product_toast) so they don't double up.\n if (shouldSuppressAddToCartToast) {\n return;\n }\n\n if (dispatchNativeAlert(toastType, title)) {\n return;\n }\n\n if (toastType === 'success') {\n toast.success(title, { duration: 3000 });\n } else if (toastType === 'error') {\n toast.error(title, { duration: 3000 });\n } else if (toastType === 'warning') {\n toast.warning(title, { duration: 3000 });\n } else {\n toast.info(title, { duration: 3000 });\n }\n };\n\n // Before the SDK loads `salla` is the head stub, and the SDK's default notifier is alert().\n void (async () => {\n try {\n await salla.onReady?.();\n } catch {\n // onReady() may fail during partial initialization; the toast still beats alert().\n }\n if (active) salla.notify?.setNotifier?.(handleNotify);\n })();\n return () => {\n active = false;\n salla.notify?.setNotifier?.(() => {});\n };\n }, [addToCartToast]);\n\n useEffect(() => {\n if (flashShownRef.current || typeof window === 'undefined') return;\n\n const params = new URLSearchParams(window.location.search);\n const successMsg = params.get('success');\n const dangerMsg = params.get('danger');\n\n if (!successMsg && !dangerMsg) return;\n\n flashShownRef.current = true;\n\n const message = successMsg || dangerMsg || '';\n const toastType = dangerMsg ? 'error' : 'success';\n\n const url = new URL(window.location.href);\n url.searchParams.delete('success');\n url.searchParams.delete('danger');\n window.history.replaceState({}, '', url.toString());\n\n const timer = setTimeout(() => {\n if (dispatchNativeAlert(toastType, message)) return;\n\n if (toastType === 'success') {\n toast.success(message, { duration: 3000 });\n } else {\n toast.error(message, { duration: 3000 });\n }\n }, 100);\n\n return () => clearTimeout(timer);\n }, []);\n\n return (\n <SonnerToaster\n position={position}\n // Keep sonner's default gaps (24px desktop / 16px mobile) but clear the\n // native status bar inset (--app-safe-area-top, set by useSafeAreaInset)\n // so top-positioned toasts aren't covered in the app webview.\n offset={{ top: 'calc(var(--app-safe-area-top, 0px) + 24px)' }}\n mobileOffset={{ top: 'calc(var(--app-safe-area-top, 0px) + 16px)' }}\n toastOptions={{\n classNames: toastClassNames,\n style: {\n fontFamily: 'var(--font-main, inherit)',\n },\n }}\n style={{\n fontFamily: 'var(--font-main, inherit)',\n }}\n />\n );\n}\n\nexport type { ToasterProps } from 'sonner';\n"]}
1
+ {"version":3,"sources":["../src/components/toast/Toaster.tsx"],"names":["SonnerToaster"],"mappings":"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","file":"chunk-BH7YNCYB.js","sourcesContent":["import { useEffect, useRef, useState } from 'react';\nimport { Toaster as SonnerToaster, toast } from 'sonner';\nimport { useTwilight } from '../../providers/twilight-context';\nimport { isNativeApp } from '../../native-app';\nimport type { ToastPosition } from './types';\n\nconst toastClassNames = {\n toast: 'group bg-white border-2 rounded-xl shadow-2xl p-4 font-primary',\n title: 'text-base font-bold',\n description: 'text-sm mt-1 text-gray-600',\n actionButton: 'bg-primary text-white px-3 py-1 rounded',\n cancelButton: 'bg-gray-100 px-3 py-1 rounded',\n success: 'border-green-500 [&_svg]:text-green-500 [&_aside]:text-green-700',\n error: 'border-red-500 [&_svg]:text-red-500 [&_aside]:text-red-700',\n warning: 'border-yellow-500 [&_svg]:text-yellow-500 [&_aside]:text-yellow-700',\n info: 'border-blue-500 [&_svg]:text-blue-500 [&_aside]:text-blue-700',\n loading: 'border-gray-400',\n};\n\ntype RawMessage = string | { title?: string; text?: string; icon?: string };\ntype ToastVariant = 'success' | 'error' | 'warning' | 'info';\n\nconst MOBILE_BREAKPOINT = 768;\nconst NATIVE_ALERT_EVENT = 'ui::alert';\n\nfunction dispatchNativeAlert(type: ToastVariant, message: string, title?: string) {\n const salla = window.salla;\n if (!isNativeApp() || !salla?.event?.dispatch) return false;\n\n salla.event.dispatch(NATIVE_ALERT_EVENT, {\n type,\n message,\n ...(title ? { title } : {}),\n });\n return true;\n}\n\nexport function Toaster({\n mobilePosition = 'bottom-center',\n addToCartToast = true,\n}: {\n mobilePosition?: ToastPosition;\n /** Show the default add-to-cart toast. Themes whose cart badge is the feedback can turn it off. */\n addToCartToast?: boolean;\n}) {\n const { theme } = useTwilight();\n const themeRef = useRef(theme);\n themeRef.current = theme;\n const flashShownRef = useRef(false);\n\n const isRtl = theme.is_rtl;\n const desktopPosition: ToastPosition = isRtl ? 'top-left' : 'top-right';\n\n const [position, setPosition] = useState<ToastPosition>(() => {\n if (typeof window === 'undefined') return desktopPosition;\n return window.innerWidth < MOBILE_BREAKPOINT ? mobilePosition : desktopPosition;\n });\n\n useEffect(() => {\n const handleResize = () => {\n setPosition(window.innerWidth < MOBILE_BREAKPOINT ? mobilePosition : desktopPosition);\n };\n window.addEventListener('resize', handleResize);\n return () => window.removeEventListener('resize', handleResize);\n }, [desktopPosition, mobilePosition]);\n\n useEffect(() => {\n const salla = window.salla;\n if (!salla) return;\n let active = true;\n\n const handleNotify = (message: RawMessage, type: string, data?: unknown) => {\n const eventData = data as { data?: { googleTags?: { event?: string } } } | undefined;\n const shouldSuppressAddToCartToast =\n (!addToCartToast || themeRef.current.settings?.enable_add_product_toast) &&\n eventData?.data?.googleTags?.event === 'addToCart';\n let title: string;\n let toastType: ToastVariant;\n\n if (typeof message === 'object' && message !== null) {\n title = message.title || message.text || '';\n toastType = (message.icon || type || 'info') as ToastVariant;\n } else {\n title = message;\n toastType = (type || 'info') as ToastVariant;\n }\n\n // Suppress the default addToCart toast when the theme opted out (addToCartToast=false)\n // or renders its own rich toast (enable_add_product_toast) so they don't double up.\n if (shouldSuppressAddToCartToast) {\n return;\n }\n\n if (dispatchNativeAlert(toastType, title)) {\n return;\n }\n\n if (toastType === 'success') {\n toast.success(title, { duration: 3000 });\n } else if (toastType === 'error') {\n toast.error(title, { duration: 3000 });\n } else if (toastType === 'warning') {\n toast.warning(title, { duration: 3000 });\n } else {\n toast.info(title, { duration: 3000 });\n }\n };\n\n // Before the SDK loads `salla` is the head stub, and the SDK's default notifier is alert().\n void (async () => {\n try {\n await salla.onReady?.();\n } catch {\n // onReady() may fail during partial initialization; the toast still beats alert().\n }\n if (active) salla.notify?.setNotifier?.(handleNotify);\n })();\n return () => {\n active = false;\n salla.notify?.setNotifier?.(() => {});\n };\n }, [addToCartToast]);\n\n useEffect(() => {\n if (flashShownRef.current || typeof window === 'undefined') return;\n\n const params = new URLSearchParams(window.location.search);\n const successMsg = params.get('success');\n const dangerMsg = params.get('danger');\n\n if (!successMsg && !dangerMsg) return;\n\n flashShownRef.current = true;\n\n const message = successMsg || dangerMsg || '';\n const toastType = dangerMsg ? 'error' : 'success';\n\n const url = new URL(window.location.href);\n url.searchParams.delete('success');\n url.searchParams.delete('danger');\n window.history.replaceState({}, '', url.toString());\n\n const timer = setTimeout(() => {\n if (dispatchNativeAlert(toastType, message)) return;\n\n if (toastType === 'success') {\n toast.success(message, { duration: 3000 });\n } else {\n toast.error(message, { duration: 3000 });\n }\n }, 100);\n\n return () => clearTimeout(timer);\n }, []);\n\n return (\n <SonnerToaster\n position={position}\n // Keep sonner's default gaps (24px desktop / 16px mobile) but clear the\n // native status bar inset (--app-safe-area-top, set by useSafeAreaInset)\n // so top-positioned toasts aren't covered in the app webview.\n offset={{ top: 'calc(var(--app-safe-area-top, 0px) + 24px)' }}\n mobileOffset={{ top: 'calc(var(--app-safe-area-top, 0px) + 16px)' }}\n toastOptions={{\n classNames: toastClassNames,\n style: {\n fontFamily: 'var(--font-main, inherit)',\n },\n }}\n style={{\n fontFamily: 'var(--font-main, inherit)',\n }}\n />\n );\n}\n\nexport type { ToasterProps } from 'sonner';\n"]}
@@ -1,6 +1,6 @@
1
- import { advertisement, advertisementsFor } from './chunk-IVBOLREE.js';
1
+ import { advertisement, advertisementsFor } from './chunk-VWVCSD3N.js';
2
2
  import { useTranslation } from './chunk-TYNZ5B2B.js';
3
- import { whenSallaReady } from './chunk-HSWRYXC7.js';
3
+ import { whenSallaReady } from './chunk-2FKZAAV7.js';
4
4
  import { subscribeTwilight, getTwilightContext } from './chunk-N2S25NXP.js';
5
5
  import { useSyncExternalStore, useState, useEffect } from 'react';
6
6
  import { useQuery } from '@tanstack/react-query';
@@ -99,5 +99,5 @@ function PageAdvertisements() {
99
99
  }
100
100
 
101
101
  export { PageAdvertisements };
102
- //# sourceMappingURL=chunk-DBW7XXNE.js.map
103
- //# sourceMappingURL=chunk-DBW7XXNE.js.map
102
+ //# sourceMappingURL=chunk-BPL5H33B.js.map
103
+ //# sourceMappingURL=chunk-BPL5H33B.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/layout/PageAdvertisements.tsx"],"names":[],"mappings":"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","file":"chunk-DBW7XXNE.js","sourcesContent":["import { useEffect, useState, useSyncExternalStore } from 'react';\nimport { useQuery } from '@tanstack/react-query';\nimport { advertisement, advertisementsFor, type Advertisement } from '../../api/advertisement';\nimport { whenSallaReady } from '../../utils/sdk-helpers';\nimport { useTranslation } from '../../providers/I18nProvider';\nimport { getTwilightContext, subscribeTwilight } from '../../twilight/context';\n\nconst currentPageSlug = () => getTwilightContext().page?.slug;\n\n/** The key `<salla-advertisement>` marks a closed ad with, through `salla.storage` (store.js, JSON). */\nconst dismissedKey = (id: number) => `statusAd-${id}`;\n\n/** Stable while the query has no data, so the effect below doesn't rerun on every render. */\nconst NO_ADS: Advertisement[] = [];\n\n/** Hides the ads this visitor closed before the first paint; the effect then drops them. */\nconst HIDE_DISMISSED_SCRIPT =\n \"(function(){try{if(window.self!==window.top)return;document.currentScript.parentNode.querySelectorAll('.s-advertisement[data-id]').forEach(function(e){if(localStorage.getItem('statusAd-'+e.getAttribute('data-id')))e.hidden=true})}catch(e){}})();\";\n\nfunction isDismissed(id: number): boolean {\n try {\n return Boolean(window.localStorage.getItem(dismissedKey(id)));\n } catch {\n return false;\n }\n}\n\nfunction dismiss(id: number): void {\n const storage = window.salla?.storage;\n if (typeof storage?.set === 'function') storage.set(dismissedKey(id), 'dismissed');\n else {\n try {\n window.localStorage.setItem(dismissedKey(id), JSON.stringify('dismissed'));\n } catch {\n // Storage disabled: the ad hides for this page view only.\n }\n }\n}\n\ninterface ClientView {\n /** The theme editor's iframe, or the SDK's debug flag: every ad shows, closed or not. */\n preview: boolean;\n /** Inside the Salla mobile app, which shows no ads. */\n inApp: boolean;\n dismissed: Set<number>;\n}\n\n/**\n * The merchant's announcement bars, in place of `<salla-advertisement>`. Same data, rules and\n * markup, but rendered on the server (the ads are prefetched in the root `beforeLoad`), so the\n * bar is in the first paint instead of pushing the page down when the web component fetches it.\n */\nexport function PageAdvertisements() {\n const { t } = useTranslation();\n // The deepest route loader's `page`, the page `salla.config` reports.\n const pageSlug = useSyncExternalStore(subscribeTwilight, currentPageSlug, currentPageSlug);\n // The query's `retry: 0` only bounds the server wait; the browser may retry.\n const { data: ads = NO_ADS } = useQuery({ ...advertisement.queries.list(), retry: 2 });\n const [view, setView] = useState<ClientView | null>(null);\n\n useEffect(() => {\n const dismissed = new Set(ads.filter((ad) => isDismissed(ad.id)).map((ad) => ad.id));\n setView({ preview: window.self !== window.top, inApp: false, dismissed });\n return whenSallaReady((sdk) => {\n const config = sdk.config as { isMobileApp?: () => boolean; isDebug?: () => boolean };\n const inApp = Boolean(config?.isMobileApp?.());\n const debug = Boolean(config?.isDebug?.());\n if (inApp || debug) {\n setView((current) =>\n current ? { ...current, inApp, preview: current.preview || debug } : current\n );\n }\n });\n }, [ads]);\n\n if (view?.inApp) return null;\n const shown = view?.preview\n ? ads\n : advertisementsFor(ads, pageSlug).filter((ad) => !view?.dismissed.has(ad.id));\n if (!shown.length) return null;\n\n const close = (id: number) => {\n dismiss(id);\n setView((current) =>\n current ? { ...current, dismissed: new Set(current.dismissed).add(id) } : current\n );\n };\n\n return (\n <>\n {shown.map((ad) => (\n <div\n key={ad.id}\n className=\"s-advertisement\"\n data-id={ad.id}\n style={{ backgroundColor: ad.colors?.bg, color: ad.colors?.text }}\n >\n <div className=\"s-advertisement-content container flex justify-between items-center py-2.5\">\n <span className=\"s-advertisement-content-main flex-1 font-bold text-center text-sm\">\n {/* Rendered without an icon too, as the SDK does: its margin is part of the layout. */}\n <i\n className={`s-advertisement-content-icon inline-block align-middle me-2 text-base ${ad.icon ?? ''}`}\n />\n {ad.url ? (\n <a\n href={ad.url}\n target={ad.target ?? undefined}\n rel={ad.target === '_blank' ? 'noopener' : undefined}\n >\n {ad.description}\n </a>\n ) : (\n ad.description\n )}\n </span>\n <button\n type=\"button\"\n className=\"s-advertisement-action px-1\"\n aria-label={t('common.buttons.close', 'Close')}\n onClick={() => close(ad.id)}\n >\n {/* `inline-block`: before the icon CSS loads, an empty inline `<i>` leaves the button 0px tall. */}\n <i className=\"sicon-cancel inline-block\" />\n </button>\n </div>\n </div>\n ))}\n <script suppressHydrationWarning>{HIDE_DISMISSED_SCRIPT}</script>\n </>\n );\n}\n"]}
1
+ {"version":3,"sources":["../src/components/layout/PageAdvertisements.tsx"],"names":[],"mappings":"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","file":"chunk-BPL5H33B.js","sourcesContent":["import { useEffect, useState, useSyncExternalStore } from 'react';\nimport { useQuery } from '@tanstack/react-query';\nimport { advertisement, advertisementsFor, type Advertisement } from '../../api/advertisement';\nimport { whenSallaReady } from '../../utils/sdk-helpers';\nimport { useTranslation } from '../../providers/I18nProvider';\nimport { getTwilightContext, subscribeTwilight } from '../../twilight/context';\n\nconst currentPageSlug = () => getTwilightContext().page?.slug;\n\n/** The key `<salla-advertisement>` marks a closed ad with, through `salla.storage` (store.js, JSON). */\nconst dismissedKey = (id: number) => `statusAd-${id}`;\n\n/** Stable while the query has no data, so the effect below doesn't rerun on every render. */\nconst NO_ADS: Advertisement[] = [];\n\n/** Hides the ads this visitor closed before the first paint; the effect then drops them. */\nconst HIDE_DISMISSED_SCRIPT =\n \"(function(){try{if(window.self!==window.top)return;document.currentScript.parentNode.querySelectorAll('.s-advertisement[data-id]').forEach(function(e){if(localStorage.getItem('statusAd-'+e.getAttribute('data-id')))e.hidden=true})}catch(e){}})();\";\n\nfunction isDismissed(id: number): boolean {\n try {\n return Boolean(window.localStorage.getItem(dismissedKey(id)));\n } catch {\n return false;\n }\n}\n\nfunction dismiss(id: number): void {\n const storage = window.salla?.storage;\n if (typeof storage?.set === 'function') storage.set(dismissedKey(id), 'dismissed');\n else {\n try {\n window.localStorage.setItem(dismissedKey(id), JSON.stringify('dismissed'));\n } catch {\n // Storage disabled: the ad hides for this page view only.\n }\n }\n}\n\ninterface ClientView {\n /** The theme editor's iframe, or the SDK's debug flag: every ad shows, closed or not. */\n preview: boolean;\n /** Inside the Salla mobile app, which shows no ads. */\n inApp: boolean;\n dismissed: Set<number>;\n}\n\n/**\n * The merchant's announcement bars, in place of `<salla-advertisement>`. Same data, rules and\n * markup, but rendered on the server (the ads are prefetched in the root `beforeLoad`), so the\n * bar is in the first paint instead of pushing the page down when the web component fetches it.\n */\nexport function PageAdvertisements() {\n const { t } = useTranslation();\n // The deepest route loader's `page`, the page `salla.config` reports.\n const pageSlug = useSyncExternalStore(subscribeTwilight, currentPageSlug, currentPageSlug);\n // The query's `retry: 0` only bounds the server wait; the browser may retry.\n const { data: ads = NO_ADS } = useQuery({ ...advertisement.queries.list(), retry: 2 });\n const [view, setView] = useState<ClientView | null>(null);\n\n useEffect(() => {\n const dismissed = new Set(ads.filter((ad) => isDismissed(ad.id)).map((ad) => ad.id));\n setView({ preview: window.self !== window.top, inApp: false, dismissed });\n return whenSallaReady((sdk) => {\n const config = sdk.config as { isMobileApp?: () => boolean; isDebug?: () => boolean };\n const inApp = Boolean(config?.isMobileApp?.());\n const debug = Boolean(config?.isDebug?.());\n if (inApp || debug) {\n setView((current) =>\n current ? { ...current, inApp, preview: current.preview || debug } : current\n );\n }\n });\n }, [ads]);\n\n if (view?.inApp) return null;\n const shown = view?.preview\n ? ads\n : advertisementsFor(ads, pageSlug).filter((ad) => !view?.dismissed.has(ad.id));\n if (!shown.length) return null;\n\n const close = (id: number) => {\n dismiss(id);\n setView((current) =>\n current ? { ...current, dismissed: new Set(current.dismissed).add(id) } : current\n );\n };\n\n return (\n <>\n {shown.map((ad) => (\n <div\n key={ad.id}\n className=\"s-advertisement\"\n data-id={ad.id}\n style={{ backgroundColor: ad.colors?.bg, color: ad.colors?.text }}\n >\n <div className=\"s-advertisement-content container flex justify-between items-center py-2.5\">\n <span className=\"s-advertisement-content-main flex-1 font-bold text-center text-sm\">\n {/* Rendered without an icon too, as the SDK does: its margin is part of the layout. */}\n <i\n className={`s-advertisement-content-icon inline-block align-middle me-2 text-base ${ad.icon ?? ''}`}\n />\n {ad.url ? (\n <a\n href={ad.url}\n target={ad.target ?? undefined}\n rel={ad.target === '_blank' ? 'noopener' : undefined}\n >\n {ad.description}\n </a>\n ) : (\n ad.description\n )}\n </span>\n <button\n type=\"button\"\n className=\"s-advertisement-action px-1\"\n aria-label={t('common.buttons.close', 'Close')}\n onClick={() => close(ad.id)}\n >\n {/* `inline-block`: before the icon CSS loads, an empty inline `<i>` leaves the button 0px tall. */}\n <i className=\"sicon-cancel inline-block\" />\n </button>\n </div>\n </div>\n ))}\n <script suppressHydrationWarning>{HIDE_DISMISSED_SCRIPT}</script>\n </>\n );\n}\n"]}