@salla.sa/twilight-theme-engine 1.0.126 → 1.0.128

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 (276) hide show
  1. package/dist/{AddToCartForm-BY24SGTR.js → AddToCartForm-NBU3MIEW.js} +3 -3
  2. package/dist/{AddToCartForm-BY24SGTR.js.map → AddToCartForm-NBU3MIEW.js.map} +1 -1
  3. package/dist/{BlogAuthorPage-UAQ6266M.js → BlogAuthorPage-4HGFVIG2.js} +17 -16
  4. package/dist/BlogAuthorPage-4HGFVIG2.js.map +1 -0
  5. package/dist/{BlogCategoryPage-UX5OZZRZ.js → BlogCategoryPage-67TZRH3C.js} +17 -16
  6. package/dist/BlogCategoryPage-67TZRH3C.js.map +1 -0
  7. package/dist/{BlogPage-AAITQ3UZ.js → BlogPage-HINCPIQO.js} +15 -14
  8. package/dist/BlogPage-HINCPIQO.js.map +1 -0
  9. package/dist/{BlogSinglePage-R7VG3WNP.js → BlogSinglePage-4BWHLJU6.js} +15 -14
  10. package/dist/BlogSinglePage-4BWHLJU6.js.map +1 -0
  11. package/dist/{BlogTagPage-YCJL3FNS.js → BlogTagPage-BGPLVWGM.js} +17 -16
  12. package/dist/BlogTagPage-BGPLVWGM.js.map +1 -0
  13. package/dist/{BrandsPage-4M4J7YH5.js → BrandsPage-2NC3RCZK.js} +16 -15
  14. package/dist/BrandsPage-2NC3RCZK.js.map +1 -0
  15. package/dist/{Breadcrumb-WB5NXLLA.js → Breadcrumb-CCYDVGCS.js} +15 -14
  16. package/dist/Breadcrumb-CCYDVGCS.js.map +1 -0
  17. package/dist/{CartItem-UWCMEGW7.js → CartItem-M5PC54CM.js} +15 -14
  18. package/dist/CartItem-M5PC54CM.js.map +1 -0
  19. package/dist/{CartSummary-TK55II7A.js → CartSummary-YQI7XI4D.js} +15 -14
  20. package/dist/CartSummary-YQI7XI4D.js.map +1 -0
  21. package/dist/{Copyright-PHLEOCO4.js → Copyright-67E3ANPE.js} +3 -3
  22. package/dist/{Copyright-PHLEOCO4.js.map → Copyright-67E3ANPE.js.map} +1 -1
  23. package/dist/{CustomerLayout-BCTFI56B.js → CustomerLayout-HPLKOG7R.js} +15 -14
  24. package/dist/CustomerLayout-HPLKOG7R.js.map +1 -0
  25. package/dist/{Footer-AXIXSATN.js → Footer-56IXUTHF.js} +4 -4
  26. package/dist/{Footer-AXIXSATN.js.map → Footer-56IXUTHF.js.map} +1 -1
  27. package/dist/{Header-5GD53HC5.js → Header-67Q5OA63.js} +9 -8
  28. package/dist/{Header-5GD53HC5.js.map → Header-67Q5OA63.js.map} +1 -1
  29. package/dist/{LoyaltyPage-MBYLZF7B.js → LoyaltyPage-GC7B5FXF.js} +15 -14
  30. package/dist/LoyaltyPage-GC7B5FXF.js.map +1 -0
  31. package/dist/{LoyaltyPointsPage-SFAL3TOO.js → LoyaltyPointsPage-UAZQ2GZT.js} +7 -6
  32. package/dist/LoyaltyPointsPage-UAZQ2GZT.js.map +1 -0
  33. package/dist/{MainMenu-VEZTUNCZ.js → MainMenu-7SXJ2DU4.js} +6 -5
  34. package/dist/MainMenu-7SXJ2DU4.js.map +1 -0
  35. package/dist/{MasterLayout-TFHNWIRE.js → MasterLayout-53MYQBTT.js} +15 -14
  36. package/dist/{MasterLayout-TFHNWIRE.js.map → MasterLayout-53MYQBTT.js.map} +1 -1
  37. package/dist/{MobileMenu-JWD22FVU.js → MobileMenu-U6W2XQYI.js} +16 -15
  38. package/dist/MobileMenu-U6W2XQYI.js.map +1 -0
  39. package/dist/{NotificationsPage-QVE7AOCV.js → NotificationsPage-2WFW7GCV.js} +15 -14
  40. package/dist/NotificationsPage-2WFW7GCV.js.map +1 -0
  41. package/dist/{OrderSinglePage-QSNZVQ22.js → OrderSinglePage-VN3IBWOO.js} +16 -15
  42. package/dist/OrderSinglePage-VN3IBWOO.js.map +1 -0
  43. package/dist/{OrdersPage-WGIHZJNJ.js → OrdersPage-NOUGRTHI.js} +15 -14
  44. package/dist/OrdersPage-NOUGRTHI.js.map +1 -0
  45. package/dist/{PageSingle-3HXGOYLZ.js → PageSingle-MP5THOR4.js} +3 -3
  46. package/dist/{PageSingle-3HXGOYLZ.js.map → PageSingle-MP5THOR4.js.map} +1 -1
  47. package/dist/{ProductDetails-ALVRCBP4.js → ProductDetails-GONQFVV2.js} +5 -4
  48. package/dist/ProductDetails-GONQFVV2.js.map +1 -0
  49. package/dist/{ProfilePage-AVJYAQOG.js → ProfilePage-RHK3OHFF.js} +15 -14
  50. package/dist/ProfilePage-RHK3OHFF.js.map +1 -0
  51. package/dist/{ReviewsPage-ULGQMLGH.js → ReviewsPage-3PODTNEP.js} +3 -3
  52. package/dist/{ReviewsPage-ULGQMLGH.js.map → ReviewsPage-3PODTNEP.js.map} +1 -1
  53. package/dist/{SeoCartWidget-5WY6AV2F.js → SeoCartWidget-MHOPTGWV.js} +15 -14
  54. package/dist/SeoCartWidget-MHOPTGWV.js.map +1 -0
  55. package/dist/{SettingsPage-ZHTSKKBD.js → SettingsPage-RLNSTOCG.js} +15 -14
  56. package/dist/SettingsPage-RLNSTOCG.js.map +1 -0
  57. package/dist/{StoreClosedNotification-5V7QGKMC.js → StoreClosedNotification-AUQCK2MP.js} +16 -15
  58. package/dist/{StoreClosedNotification-5V7QGKMC.js.map → StoreClosedNotification-AUQCK2MP.js.map} +1 -1
  59. package/dist/{TestimonialsPage-7YS7QRTY.js → TestimonialsPage-GXKXWGDA.js} +3 -3
  60. package/dist/{TestimonialsPage-7YS7QRTY.js.map → TestimonialsPage-GXKXWGDA.js.map} +1 -1
  61. package/dist/{ThankYouPage-PLCUI7LC.js → ThankYouPage-GILEXBPL.js} +15 -14
  62. package/dist/ThankYouPage-GILEXBPL.js.map +1 -0
  63. package/dist/{WalletPage-C6ZFJTSA.js → WalletPage-4OOHX65H.js} +16 -15
  64. package/dist/WalletPage-4OOHX65H.js.map +1 -0
  65. package/dist/{WishlistPage-3CIW7AIZ.js → WishlistPage-Z2TPPFFM.js} +17 -16
  66. package/dist/WishlistPage-Z2TPPFFM.js.map +1 -0
  67. package/dist/api/advertisement.js +3 -2
  68. package/dist/api/apps.js +3 -2
  69. package/dist/api/blog.js +4 -3
  70. package/dist/api/brands.js +4 -3
  71. package/dist/api/cart.js +4 -3
  72. package/dist/api/category.js +4 -3
  73. package/dist/api/client.d.ts.map +1 -1
  74. package/dist/api/client.js +2 -1
  75. package/dist/api/dev-settings-cache.d.ts +50 -0
  76. package/dist/api/dev-settings-cache.d.ts.map +1 -0
  77. package/dist/api/home.js +3 -2
  78. package/dist/api/loyalty.js +4 -3
  79. package/dist/api/menu.js +3 -2
  80. package/dist/api/notification.js +3 -2
  81. package/dist/api/order.js +4 -3
  82. package/dist/api/page.js +4 -3
  83. package/dist/api/product.js +4 -3
  84. package/dist/api/profile.js +2 -1
  85. package/dist/api/profile.js.map +1 -1
  86. package/dist/api/store.d.ts +6 -0
  87. package/dist/api/store.d.ts.map +1 -1
  88. package/dist/api/store.js +3 -2
  89. package/dist/api/translations.js +3 -2
  90. package/dist/api/user.js +3 -2
  91. package/dist/api/wallet.js +3 -2
  92. package/dist/api/wishlist.js +5 -4
  93. package/dist/{chunk-SGET4UYI.js → chunk-2VRMQZXF.js} +3 -3
  94. package/dist/{chunk-SGET4UYI.js.map → chunk-2VRMQZXF.js.map} +1 -1
  95. package/dist/{chunk-A6AAG7U6.js → chunk-3FMJHVRY.js} +4 -4
  96. package/dist/{chunk-A6AAG7U6.js.map → chunk-3FMJHVRY.js.map} +1 -1
  97. package/dist/{chunk-KKOFHYTI.js → chunk-3OGFV27B.js} +3 -3
  98. package/dist/{chunk-KKOFHYTI.js.map → chunk-3OGFV27B.js.map} +1 -1
  99. package/dist/{chunk-UHCNMJDI.js → chunk-3U6BZUQL.js} +7 -7
  100. package/dist/{chunk-UHCNMJDI.js.map → chunk-3U6BZUQL.js.map} +1 -1
  101. package/dist/{chunk-MHLKLADI.js → chunk-4LR7N76Q.js} +52 -14
  102. package/dist/chunk-4LR7N76Q.js.map +1 -0
  103. package/dist/{chunk-FN2GQ2B5.js → chunk-5GCOUJ7T.js} +3 -3
  104. package/dist/{chunk-FN2GQ2B5.js.map → chunk-5GCOUJ7T.js.map} +1 -1
  105. package/dist/{chunk-6PK4GITC.js → chunk-5U7LPEFE.js} +3 -3
  106. package/dist/{chunk-6PK4GITC.js.map → chunk-5U7LPEFE.js.map} +1 -1
  107. package/dist/{chunk-IGGIH6GL.js → chunk-6GDNC6DS.js} +3 -3
  108. package/dist/{chunk-IGGIH6GL.js.map → chunk-6GDNC6DS.js.map} +1 -1
  109. package/dist/{chunk-NHJ5U6WK.js → chunk-6NT6RC2H.js} +3 -3
  110. package/dist/{chunk-NHJ5U6WK.js.map → chunk-6NT6RC2H.js.map} +1 -1
  111. package/dist/{chunk-WFSKX5AI.js → chunk-7SBSV5DD.js} +3 -3
  112. package/dist/{chunk-WFSKX5AI.js.map → chunk-7SBSV5DD.js.map} +1 -1
  113. package/dist/{chunk-TNUK62YF.js → chunk-CGABIBZZ.js} +4 -4
  114. package/dist/{chunk-TNUK62YF.js.map → chunk-CGABIBZZ.js.map} +1 -1
  115. package/dist/{chunk-WBDU6KDP.js → chunk-CN4U4EWY.js} +4 -4
  116. package/dist/{chunk-WBDU6KDP.js.map → chunk-CN4U4EWY.js.map} +1 -1
  117. package/dist/{chunk-XRDQAJW5.js → chunk-DI463VGL.js} +3 -3
  118. package/dist/{chunk-XRDQAJW5.js.map → chunk-DI463VGL.js.map} +1 -1
  119. package/dist/{chunk-BWTUGXHI.js → chunk-DJN6JAF7.js} +5 -5
  120. package/dist/{chunk-BWTUGXHI.js.map → chunk-DJN6JAF7.js.map} +1 -1
  121. package/dist/{chunk-53IXPTVY.js → chunk-EXK6VVXU.js} +4 -4
  122. package/dist/{chunk-53IXPTVY.js.map → chunk-EXK6VVXU.js.map} +1 -1
  123. package/dist/{chunk-5SJRY6P3.js → chunk-EZK2WD75.js} +4 -4
  124. package/dist/{chunk-5SJRY6P3.js.map → chunk-EZK2WD75.js.map} +1 -1
  125. package/dist/{chunk-IM5NMPNU.js → chunk-FWGHTOGZ.js} +7 -7
  126. package/dist/{chunk-IM5NMPNU.js.map → chunk-FWGHTOGZ.js.map} +1 -1
  127. package/dist/{chunk-RE4QQM4Q.js → chunk-GFOAMXSO.js} +3 -3
  128. package/dist/{chunk-RE4QQM4Q.js.map → chunk-GFOAMXSO.js.map} +1 -1
  129. package/dist/{chunk-4C76FZV4.js → chunk-GN5V4IQI.js} +4 -4
  130. package/dist/{chunk-4C76FZV4.js.map → chunk-GN5V4IQI.js.map} +1 -1
  131. package/dist/{chunk-KEOCLT62.js → chunk-HAS46CRI.js} +8 -5
  132. package/dist/chunk-HAS46CRI.js.map +1 -0
  133. package/dist/{chunk-TCRZSLXH.js → chunk-HRDCUTC6.js} +6 -6
  134. package/dist/{chunk-TCRZSLXH.js.map → chunk-HRDCUTC6.js.map} +1 -1
  135. package/dist/{chunk-GLE6TNJ3.js → chunk-HZIQK63A.js} +3 -3
  136. package/dist/{chunk-GLE6TNJ3.js.map → chunk-HZIQK63A.js.map} +1 -1
  137. package/dist/{chunk-LWPIGNCW.js → chunk-JAP5KTIG.js} +4 -4
  138. package/dist/{chunk-LWPIGNCW.js.map → chunk-JAP5KTIG.js.map} +1 -1
  139. package/dist/{chunk-JAKLD546.js → chunk-JUKKXGHR.js} +3 -3
  140. package/dist/{chunk-JAKLD546.js.map → chunk-JUKKXGHR.js.map} +1 -1
  141. package/dist/{chunk-4VYKXIYA.js → chunk-KNTHVSUL.js} +8 -7
  142. package/dist/chunk-KNTHVSUL.js.map +1 -0
  143. package/dist/{chunk-A6IKHCIA.js → chunk-L36ZEKBI.js} +4 -4
  144. package/dist/{chunk-A6IKHCIA.js.map → chunk-L36ZEKBI.js.map} +1 -1
  145. package/dist/chunk-L4FKJ3ZN.js +14 -0
  146. package/dist/{chunk-UE65NYZF.js.map → chunk-L4FKJ3ZN.js.map} +1 -1
  147. package/dist/{chunk-JL7MKSCD.js → chunk-LIQHWHYV.js} +10 -10
  148. package/dist/{chunk-JL7MKSCD.js.map → chunk-LIQHWHYV.js.map} +1 -1
  149. package/dist/{chunk-KDV6WZYJ.js → chunk-M6Z7KIDX.js} +3 -3
  150. package/dist/{chunk-KDV6WZYJ.js.map → chunk-M6Z7KIDX.js.map} +1 -1
  151. package/dist/{chunk-HFCZIPYO.js → chunk-O3BZBI27.js} +3 -3
  152. package/dist/{chunk-HFCZIPYO.js.map → chunk-O3BZBI27.js.map} +1 -1
  153. package/dist/{chunk-47BPYZJF.js → chunk-OOQTZ7N7.js} +3 -3
  154. package/dist/{chunk-47BPYZJF.js.map → chunk-OOQTZ7N7.js.map} +1 -1
  155. package/dist/{chunk-R2FXTCRK.js → chunk-QLFRNPPF.js} +15 -14
  156. package/dist/chunk-QLFRNPPF.js.map +1 -0
  157. package/dist/{chunk-75STIRBZ.js → chunk-RA5O7L7Q.js} +4 -4
  158. package/dist/{chunk-75STIRBZ.js.map → chunk-RA5O7L7Q.js.map} +1 -1
  159. package/dist/{chunk-5LP2K2J7.js → chunk-S7QZUBXM.js} +112 -6
  160. package/dist/chunk-S7QZUBXM.js.map +1 -0
  161. package/dist/{chunk-4ZYJDSYQ.js → chunk-U2UDXLAE.js} +3 -3
  162. package/dist/{chunk-4ZYJDSYQ.js.map → chunk-U2UDXLAE.js.map} +1 -1
  163. package/dist/{chunk-CKH5HDHS.js → chunk-UGJ24VNF.js} +4 -4
  164. package/dist/{chunk-CKH5HDHS.js.map → chunk-UGJ24VNF.js.map} +1 -1
  165. package/dist/{chunk-Z76YTG4W.js → chunk-UWE2QL3O.js} +3 -3
  166. package/dist/{chunk-Z76YTG4W.js.map → chunk-UWE2QL3O.js.map} +1 -1
  167. package/dist/{chunk-GHLPK63Q.js → chunk-XCS62X6X.js} +7 -7
  168. package/dist/{chunk-GHLPK63Q.js.map → chunk-XCS62X6X.js.map} +1 -1
  169. package/dist/chunk-Z5M4YYWT.js +9 -0
  170. package/dist/chunk-Z5M4YYWT.js.map +1 -0
  171. package/dist/{chunk-ANLG2WBG.js → chunk-ZWV6YNIB.js} +4 -4
  172. package/dist/{chunk-ANLG2WBG.js.map → chunk-ZWV6YNIB.js.map} +1 -1
  173. package/dist/components/cart/index.js +1 -1
  174. package/dist/components/common/index.js +1 -1
  175. package/dist/components/drawer/index.js +13 -12
  176. package/dist/components/home/HomePageRenderer.d.ts.map +1 -1
  177. package/dist/components/home/index.js +17 -16
  178. package/dist/components/layout/index.js +5 -4
  179. package/dist/components/product/index.js +14 -13
  180. package/dist/components/store/index.js +14 -13
  181. package/dist/dev/dev-settings-store.d.ts +20 -0
  182. package/dist/dev/dev-settings-store.d.ts.map +1 -1
  183. package/dist/dev/editor/ThemeEditor.d.ts.map +1 -1
  184. package/dist/dev/editor/i18n.d.ts +3 -0
  185. package/dist/dev/editor/i18n.d.ts.map +1 -1
  186. package/dist/dev/editor/index.js +64 -4
  187. package/dist/dev/editor/index.js.map +1 -1
  188. package/dist/dev/editor/relative-time.d.ts +8 -0
  189. package/dist/dev/editor/relative-time.d.ts.map +1 -0
  190. package/dist/dev/editor/styles.d.ts +1 -1
  191. package/dist/dev/editor/styles.d.ts.map +1 -1
  192. package/dist/dev/index.js +1 -1
  193. package/dist/{document-class-P2H6HKXA.js → document-class-DSRV5LZK.js} +12 -11
  194. package/dist/{document-class-P2H6HKXA.js.map → document-class-DSRV5LZK.js.map} +1 -1
  195. package/dist/hooks/index.js +13 -12
  196. package/dist/hooks/useGtm.js +13 -12
  197. package/dist/hooks/useMoney.js +13 -12
  198. package/dist/hooks/useStore.js +13 -12
  199. package/dist/hooks/useUser.js +4 -3
  200. package/dist/index.js +13 -12
  201. package/dist/index.js.map +1 -1
  202. package/dist/{navigation-4STP3ZMK.js → navigation-ATD4DRST.js} +5 -4
  203. package/dist/navigation-ATD4DRST.js.map +1 -0
  204. package/dist/{navigation-6Y2SKWH3.js → navigation-XCZMJSNS.js} +6 -5
  205. package/dist/{navigation-6Y2SKWH3.js.map → navigation-XCZMJSNS.js.map} +1 -1
  206. package/dist/{not-found-LLCXGKVS.js → not-found-ZE4Y7RLW.js} +16 -15
  207. package/dist/not-found-ZE4Y7RLW.js.map +1 -0
  208. package/dist/providers/index.js +13 -12
  209. package/dist/providers/twilight-init.d.ts.map +1 -1
  210. package/dist/routes/account/orders.js +5 -4
  211. package/dist/routes/account.js +14 -13
  212. package/dist/routes/account.js.map +1 -1
  213. package/dist/routes/blog.js +9 -8
  214. package/dist/routes/blog.js.map +1 -1
  215. package/dist/routes/brands.js +5 -4
  216. package/dist/routes/brands.js.map +1 -1
  217. package/dist/routes/cart.js +21 -20
  218. package/dist/routes/cart.js.map +1 -1
  219. package/dist/routes/home.js +18 -17
  220. package/dist/routes/index.js +4 -3
  221. package/dist/routes/loyalty.js +6 -5
  222. package/dist/routes/loyalty.js.map +1 -1
  223. package/dist/routes/page.js +5 -4
  224. package/dist/routes/page.js.map +1 -1
  225. package/dist/routes/product-listing.js +19 -18
  226. package/dist/routes/product-listing.js.map +1 -1
  227. package/dist/routes/product.js +17 -16
  228. package/dist/routes/product.js.map +1 -1
  229. package/dist/routes/seo-redirects.js +4 -3
  230. package/dist/routes/testimonials.js +2 -2
  231. package/dist/routes/thank-you.js +5 -4
  232. package/dist/routes/thank-you.js.map +1 -1
  233. package/dist/skeleton.js +18 -17
  234. package/dist/{store-lookup-XKL42Y4H.js → store-lookup-TG6RV6NV.js} +9 -8
  235. package/dist/store-lookup-TG6RV6NV.js.map +1 -0
  236. package/dist/tanstack.js +12 -11
  237. package/dist/tanstack.js.map +1 -1
  238. package/dist/utils/dev-settings-refresh.d.ts +14 -0
  239. package/dist/utils/dev-settings-refresh.d.ts.map +1 -0
  240. package/dist/utils/index.js +3 -2
  241. package/dist/utils/index.js.map +1 -1
  242. package/package.json +1 -1
  243. package/tailwind/components/home/HomePageRenderer.tsx.txt +5 -2
  244. package/dist/BlogAuthorPage-UAQ6266M.js.map +0 -1
  245. package/dist/BlogCategoryPage-UX5OZZRZ.js.map +0 -1
  246. package/dist/BlogPage-AAITQ3UZ.js.map +0 -1
  247. package/dist/BlogSinglePage-R7VG3WNP.js.map +0 -1
  248. package/dist/BlogTagPage-YCJL3FNS.js.map +0 -1
  249. package/dist/BrandsPage-4M4J7YH5.js.map +0 -1
  250. package/dist/Breadcrumb-WB5NXLLA.js.map +0 -1
  251. package/dist/CartItem-UWCMEGW7.js.map +0 -1
  252. package/dist/CartSummary-TK55II7A.js.map +0 -1
  253. package/dist/CustomerLayout-BCTFI56B.js.map +0 -1
  254. package/dist/LoyaltyPage-MBYLZF7B.js.map +0 -1
  255. package/dist/LoyaltyPointsPage-SFAL3TOO.js.map +0 -1
  256. package/dist/MainMenu-VEZTUNCZ.js.map +0 -1
  257. package/dist/MobileMenu-JWD22FVU.js.map +0 -1
  258. package/dist/NotificationsPage-QVE7AOCV.js.map +0 -1
  259. package/dist/OrderSinglePage-QSNZVQ22.js.map +0 -1
  260. package/dist/OrdersPage-WGIHZJNJ.js.map +0 -1
  261. package/dist/ProductDetails-ALVRCBP4.js.map +0 -1
  262. package/dist/ProfilePage-AVJYAQOG.js.map +0 -1
  263. package/dist/SeoCartWidget-5WY6AV2F.js.map +0 -1
  264. package/dist/SettingsPage-ZHTSKKBD.js.map +0 -1
  265. package/dist/ThankYouPage-PLCUI7LC.js.map +0 -1
  266. package/dist/WalletPage-C6ZFJTSA.js.map +0 -1
  267. package/dist/WishlistPage-3CIW7AIZ.js.map +0 -1
  268. package/dist/chunk-4VYKXIYA.js.map +0 -1
  269. package/dist/chunk-5LP2K2J7.js.map +0 -1
  270. package/dist/chunk-KEOCLT62.js.map +0 -1
  271. package/dist/chunk-MHLKLADI.js.map +0 -1
  272. package/dist/chunk-R2FXTCRK.js.map +0 -1
  273. package/dist/chunk-UE65NYZF.js +0 -14
  274. package/dist/navigation-4STP3ZMK.js.map +0 -1
  275. package/dist/not-found-LLCXGKVS.js.map +0 -1
  276. package/dist/store-lookup-XKL42Y4H.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/api/page.ts"],"names":[],"mappings":";;;;AAKO,IAAM,IAAA,GAAO;AAAA,EAClB,IAAA,EAAM,OAAO,IAAA,KAA2C;AACtD,IAAA,MAAM,EAAE,IAAA,EAAK,GAAI,MAAM,GAAA,CAAI,IAAI,CAAA,MAAA,EAAS,IAAI,CAAA,CAAE,CAAA,CAAE,IAAA,EAAgC;AAChF,IAAA,OAAO,IAAA;AAAA,EACT,CAAA;AAAA,EAEA,aAAa,CAAC,IAAA,KAA2C,QAAQ,IAAA,CAAK,IAAA,CAAK,IAAI,CAAC,CAAA;AAAA,EAEhF,OAAA,EAAS;AAAA,IACP,MAAA,EAAQ,CAAC,IAAA,KACP,YAAA,CAAa;AAAA,MACX,QAAA,EAAU,CAAC,OAAA,EAAS,QAAA,EAAU,IAAI,CAAA;AAAA,MAClC,OAAA,EAAS,MAAM,IAAA,CAAK,IAAA,CAAK,IAAI;AAAA,KAC9B;AAAA;AAEP","file":"chunk-A6AAG7U6.js","sourcesContent":["import { queryOptions } from '@tanstack/react-query';\nimport { api } from './client';\nimport type { ApiPageResponse } from '../routes/page/types';\nimport { orThrow } from '../providers/NavigationProvider';\n\nexport const page = {\n find: async (slug: string): Promise<ApiPageResponse> => {\n const { data } = await api.get(`pages/${slug}`).json<{ data: ApiPageResponse }>();\n return data;\n },\n\n findOrThrow: (slug: string): Promise<ApiPageResponse> => orThrow(page.find(slug)),\n\n queries: {\n detail: (slug: string) =>\n queryOptions({\n queryKey: ['pages', 'detail', slug],\n queryFn: () => page.find(slug),\n }),\n },\n};\n"]}
1
+ {"version":3,"sources":["../src/api/page.ts"],"names":[],"mappings":";;;;AAKO,IAAM,IAAA,GAAO;AAAA,EAClB,IAAA,EAAM,OAAO,IAAA,KAA2C;AACtD,IAAA,MAAM,EAAE,IAAA,EAAK,GAAI,MAAM,GAAA,CAAI,IAAI,CAAA,MAAA,EAAS,IAAI,CAAA,CAAE,CAAA,CAAE,IAAA,EAAgC;AAChF,IAAA,OAAO,IAAA;AAAA,EACT,CAAA;AAAA,EAEA,aAAa,CAAC,IAAA,KAA2C,QAAQ,IAAA,CAAK,IAAA,CAAK,IAAI,CAAC,CAAA;AAAA,EAEhF,OAAA,EAAS;AAAA,IACP,MAAA,EAAQ,CAAC,IAAA,KACP,YAAA,CAAa;AAAA,MACX,QAAA,EAAU,CAAC,OAAA,EAAS,QAAA,EAAU,IAAI,CAAA;AAAA,MAClC,OAAA,EAAS,MAAM,IAAA,CAAK,IAAA,CAAK,IAAI;AAAA,KAC9B;AAAA;AAEP","file":"chunk-3FMJHVRY.js","sourcesContent":["import { queryOptions } from '@tanstack/react-query';\nimport { api } from './client';\nimport type { ApiPageResponse } from '../routes/page/types';\nimport { orThrow } from '../providers/NavigationProvider';\n\nexport const page = {\n find: async (slug: string): Promise<ApiPageResponse> => {\n const { data } = await api.get(`pages/${slug}`).json<{ data: ApiPageResponse }>();\n return data;\n },\n\n findOrThrow: (slug: string): Promise<ApiPageResponse> => orThrow(page.find(slug)),\n\n queries: {\n detail: (slug: string) =>\n queryOptions({\n queryKey: ['pages', 'detail', slug],\n queryFn: () => page.find(slug),\n }),\n },\n};\n"]}
@@ -1,4 +1,4 @@
1
- import { api } from './chunk-5LP2K2J7.js';
1
+ import { api } from './chunk-S7QZUBXM.js';
2
2
  import { getTwilightContext } from './chunk-7VNVCHID.js';
3
3
  import { queryOptions } from '@tanstack/react-query';
4
4
 
@@ -23,5 +23,5 @@ var menu = {
23
23
  };
24
24
 
25
25
  export { menu };
26
- //# sourceMappingURL=chunk-KKOFHYTI.js.map
27
- //# sourceMappingURL=chunk-KKOFHYTI.js.map
26
+ //# sourceMappingURL=chunk-3OGFV27B.js.map
27
+ //# sourceMappingURL=chunk-3OGFV27B.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/api/menu.ts"],"names":[],"mappings":";;;;AAKO,IAAM,IAAA,GAAO;AAAA,EAClB,QAAQ,YAAiC;AACvC,IAAA,MAAM,EAAE,MAAA,EAAO,GAAI,kBAAA,EAAmB;AACtC,IAAA,MAAM,EAAE,IAAA,EAAK,GAAI,MAAM,GAAA,CAAI,IAAI,CAAA,kBAAA,EAAqB,MAAM,CAAA,CAAE,CAAA,CAAE,IAAA,EAA2B;AACzF,IAAA,OAAO,QAAQ,EAAC;AAAA,EAClB,CAAA;AAAA,EAEA,QAAQ,YAAiC;AACvC,IAAA,MAAM,EAAE,MAAA,EAAO,GAAI,kBAAA,EAAmB;AACtC,IAAA,MAAM,EAAE,IAAA,EAAK,GAAI,MAAM,GAAA,CAAI,IAAI,CAAA,kBAAA,EAAqB,MAAM,CAAA,CAAE,CAAA,CAAE,IAAA,EAA2B;AACzF,IAAA,OAAO,QAAQ,EAAC;AAAA,EAClB,CAAA;AAAA,EAEA,OAAA,EAAS;AAAA,IACP,MAAA,EAAQ,MACN,YAAA,CAAa;AAAA,MACX,UAAU,CAAC,OAAA,EAAS,QAAA,EAAU,kBAAA,GAAqB,MAAM,CAAA;AAAA,MACzD,OAAA,EAAS,MAAM,IAAA,CAAK,MAAA,EAAO;AAAA,MAC3B,SAAA,EAAW,IAAI,EAAA,GAAK;AAAA,KACrB;AAAA;AAEP","file":"chunk-KKOFHYTI.js","sourcesContent":["import { queryOptions } from '@tanstack/react-query';\nimport { api } from './client';\nimport { getTwilightContext } from '../twilight/context';\nimport type { MenuItem } from '../types';\n\nexport const menu = {\n header: async (): Promise<MenuItem[]> => {\n const { locale } = getTwilightContext();\n const { data } = await api.get(`menus/header?lang=${locale}`).json<{ data: MenuItem[] }>();\n return data || [];\n },\n\n footer: async (): Promise<MenuItem[]> => {\n const { locale } = getTwilightContext();\n const { data } = await api.get(`menus/footer?lang=${locale}`).json<{ data: MenuItem[] }>();\n return data || [];\n },\n\n queries: {\n header: () =>\n queryOptions({\n queryKey: ['menus', 'header', getTwilightContext().locale],\n queryFn: () => menu.header(),\n staleTime: 5 * 60 * 1000,\n }),\n },\n};\n"]}
1
+ {"version":3,"sources":["../src/api/menu.ts"],"names":[],"mappings":";;;;AAKO,IAAM,IAAA,GAAO;AAAA,EAClB,QAAQ,YAAiC;AACvC,IAAA,MAAM,EAAE,MAAA,EAAO,GAAI,kBAAA,EAAmB;AACtC,IAAA,MAAM,EAAE,IAAA,EAAK,GAAI,MAAM,GAAA,CAAI,IAAI,CAAA,kBAAA,EAAqB,MAAM,CAAA,CAAE,CAAA,CAAE,IAAA,EAA2B;AACzF,IAAA,OAAO,QAAQ,EAAC;AAAA,EAClB,CAAA;AAAA,EAEA,QAAQ,YAAiC;AACvC,IAAA,MAAM,EAAE,MAAA,EAAO,GAAI,kBAAA,EAAmB;AACtC,IAAA,MAAM,EAAE,IAAA,EAAK,GAAI,MAAM,GAAA,CAAI,IAAI,CAAA,kBAAA,EAAqB,MAAM,CAAA,CAAE,CAAA,CAAE,IAAA,EAA2B;AACzF,IAAA,OAAO,QAAQ,EAAC;AAAA,EAClB,CAAA;AAAA,EAEA,OAAA,EAAS;AAAA,IACP,MAAA,EAAQ,MACN,YAAA,CAAa;AAAA,MACX,UAAU,CAAC,OAAA,EAAS,QAAA,EAAU,kBAAA,GAAqB,MAAM,CAAA;AAAA,MACzD,OAAA,EAAS,MAAM,IAAA,CAAK,MAAA,EAAO;AAAA,MAC3B,SAAA,EAAW,IAAI,EAAA,GAAK;AAAA,KACrB;AAAA;AAEP","file":"chunk-3OGFV27B.js","sourcesContent":["import { queryOptions } from '@tanstack/react-query';\nimport { api } from './client';\nimport { getTwilightContext } from '../twilight/context';\nimport type { MenuItem } from '../types';\n\nexport const menu = {\n header: async (): Promise<MenuItem[]> => {\n const { locale } = getTwilightContext();\n const { data } = await api.get(`menus/header?lang=${locale}`).json<{ data: MenuItem[] }>();\n return data || [];\n },\n\n footer: async (): Promise<MenuItem[]> => {\n const { locale } = getTwilightContext();\n const { data } = await api.get(`menus/footer?lang=${locale}`).json<{ data: MenuItem[] }>();\n return data || [];\n },\n\n queries: {\n header: () =>\n queryOptions({\n queryKey: ['menus', 'header', getTwilightContext().locale],\n queryFn: () => menu.header(),\n staleTime: 5 * 60 * 1000,\n }),\n },\n};\n"]}
@@ -1,21 +1,21 @@
1
1
  import { lazy } from 'react';
2
2
 
3
3
  // src/components/layout/lazy.ts
4
- var LazyHeader = lazy(() => import('./Header-5GD53HC5.js').then((m) => ({ default: m.Header })));
5
- var LazyFooter = lazy(() => import('./Footer-AXIXSATN.js').then((m) => ({ default: m.Footer })));
4
+ var LazyHeader = lazy(() => import('./Header-67Q5OA63.js').then((m) => ({ default: m.Header })));
5
+ var LazyFooter = lazy(() => import('./Footer-56IXUTHF.js').then((m) => ({ default: m.Footer })));
6
6
  var LazyCopyright = lazy(
7
- () => import('./Copyright-PHLEOCO4.js').then((m) => ({ default: m.Copyright }))
7
+ () => import('./Copyright-67E3ANPE.js').then((m) => ({ default: m.Copyright }))
8
8
  );
9
9
  var LazyMasterLayout = lazy(
10
- () => import('./MasterLayout-TFHNWIRE.js').then((m) => ({ default: m.MasterLayout }))
10
+ () => import('./MasterLayout-53MYQBTT.js').then((m) => ({ default: m.MasterLayout }))
11
11
  );
12
12
  var LazyWidgetHead = lazy(
13
13
  () => import('./WidgetHead-BCRIXIJQ.js').then((m) => ({ default: m.WidgetHead }))
14
14
  );
15
15
  var LazyCustomerLayout = lazy(
16
- () => import('./CustomerLayout-BCTFI56B.js').then((m) => ({ default: m.CustomerLayout }))
16
+ () => import('./CustomerLayout-HPLKOG7R.js').then((m) => ({ default: m.CustomerLayout }))
17
17
  );
18
18
 
19
19
  export { LazyCopyright, LazyCustomerLayout, LazyFooter, LazyHeader, LazyMasterLayout, LazyWidgetHead };
20
- //# sourceMappingURL=chunk-UHCNMJDI.js.map
21
- //# sourceMappingURL=chunk-UHCNMJDI.js.map
20
+ //# sourceMappingURL=chunk-3U6BZUQL.js.map
21
+ //# sourceMappingURL=chunk-3U6BZUQL.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/layout/lazy.ts"],"names":[],"mappings":";;;AAMO,IAAM,UAAA,GAAa,IAAA,CAAK,MAAM,OAAO,sBAAU,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,MAAO,EAAE,OAAA,EAAS,CAAA,CAAE,MAAA,GAAS,CAAC;AAErF,IAAM,UAAA,GAAa,IAAA,CAAK,MAAM,OAAO,sBAAU,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,MAAO,EAAE,OAAA,EAAS,CAAA,CAAE,MAAA,GAAS,CAAC;AAErF,IAAM,aAAA,GAAgB,IAAA;AAAA,EAAK,MAChC,OAAO,yBAAa,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,MAAO,EAAE,OAAA,EAAS,CAAA,CAAE,SAAA,EAAU,CAAE;AAC9D;AAEO,IAAM,gBAAA,GAAmB,IAAA;AAAA,EAAK,MACnC,OAAO,4BAAgB,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,MAAO,EAAE,OAAA,EAAS,CAAA,CAAE,YAAA,EAAa,CAAE;AACpE;AAEO,IAAM,cAAA,GAAiB,IAAA;AAAA,EAAK,MACjC,OAAO,0BAAc,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,MAAO,EAAE,OAAA,EAAS,CAAA,CAAE,UAAA,EAAW,CAAE;AAChE;AAEO,IAAM,kBAAA,GAAqB,IAAA;AAAA,EAAK,MACrC,OAAO,8BAAkB,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,MAAO,EAAE,OAAA,EAAS,CAAA,CAAE,cAAA,EAAe,CAAE;AACxE","file":"chunk-UHCNMJDI.js","sourcesContent":["import { lazy } from 'react';\n\n/**\n * Lazy-loaded layout components\n * Use these for code-splitting layout sections\n */\nexport const LazyHeader = lazy(() => import('./Header').then((m) => ({ default: m.Header })));\n\nexport const LazyFooter = lazy(() => import('./Footer').then((m) => ({ default: m.Footer })));\n\nexport const LazyCopyright = lazy(() =>\n import('./Copyright').then((m) => ({ default: m.Copyright }))\n);\n\nexport const LazyMasterLayout = lazy(() =>\n import('./MasterLayout').then((m) => ({ default: m.MasterLayout }))\n);\n\nexport const LazyWidgetHead = lazy(() =>\n import('./WidgetHead').then((m) => ({ default: m.WidgetHead }))\n);\n\nexport const LazyCustomerLayout = lazy(() =>\n import('./CustomerLayout').then((m) => ({ default: m.CustomerLayout }))\n);\n"]}
1
+ {"version":3,"sources":["../src/components/layout/lazy.ts"],"names":[],"mappings":";;;AAMO,IAAM,UAAA,GAAa,IAAA,CAAK,MAAM,OAAO,sBAAU,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,MAAO,EAAE,OAAA,EAAS,CAAA,CAAE,MAAA,GAAS,CAAC;AAErF,IAAM,UAAA,GAAa,IAAA,CAAK,MAAM,OAAO,sBAAU,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,MAAO,EAAE,OAAA,EAAS,CAAA,CAAE,MAAA,GAAS,CAAC;AAErF,IAAM,aAAA,GAAgB,IAAA;AAAA,EAAK,MAChC,OAAO,yBAAa,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,MAAO,EAAE,OAAA,EAAS,CAAA,CAAE,SAAA,EAAU,CAAE;AAC9D;AAEO,IAAM,gBAAA,GAAmB,IAAA;AAAA,EAAK,MACnC,OAAO,4BAAgB,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,MAAO,EAAE,OAAA,EAAS,CAAA,CAAE,YAAA,EAAa,CAAE;AACpE;AAEO,IAAM,cAAA,GAAiB,IAAA;AAAA,EAAK,MACjC,OAAO,0BAAc,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,MAAO,EAAE,OAAA,EAAS,CAAA,CAAE,UAAA,EAAW,CAAE;AAChE;AAEO,IAAM,kBAAA,GAAqB,IAAA;AAAA,EAAK,MACrC,OAAO,8BAAkB,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,MAAO,EAAE,OAAA,EAAS,CAAA,CAAE,cAAA,EAAe,CAAE;AACxE","file":"chunk-3U6BZUQL.js","sourcesContent":["import { lazy } from 'react';\n\n/**\n * Lazy-loaded layout components\n * Use these for code-splitting layout sections\n */\nexport const LazyHeader = lazy(() => import('./Header').then((m) => ({ default: m.Header })));\n\nexport const LazyFooter = lazy(() => import('./Footer').then((m) => ({ default: m.Footer })));\n\nexport const LazyCopyright = lazy(() =>\n import('./Copyright').then((m) => ({ default: m.Copyright }))\n);\n\nexport const LazyMasterLayout = lazy(() =>\n import('./MasterLayout').then((m) => ({ default: m.MasterLayout }))\n);\n\nexport const LazyWidgetHead = lazy(() =>\n import('./WidgetHead').then((m) => ({ default: m.WidgetHead }))\n);\n\nexport const LazyCustomerLayout = lazy(() =>\n import('./CustomerLayout').then((m) => ({ default: m.CustomerLayout }))\n);\n"]}
@@ -1,6 +1,6 @@
1
1
  import { EMPTY_PREVIEW_STATE, DEV_LOOKUP_TIMEOUT_MS, isEditorFrame, normalizePreviewState, DEV_PREVIEW_GLOBAL, DEV_PREVIEW_EVENT, DEV_PREVIEW_ENDPOINT } from './chunk-OXMUPNMH.js';
2
2
  import { resolveStoreBase } from './chunk-FHU2MXZA.js';
3
- import { useSyncExternalStore, useRef, useEffect, useMemo } from 'react';
3
+ import { useSyncExternalStore, useEffect, useRef, useMemo } from 'react';
4
4
 
5
5
  var LEGACY_STORAGE_KEY = "twilight:dev-settings";
6
6
  var SAVE_DELAY_MS = 250;
@@ -38,7 +38,7 @@ function singleton() {
38
38
  state: readSeed(),
39
39
  listeners: /* @__PURE__ */ new Set(),
40
40
  ownBlocks: null,
41
- meta: { liveBlocks: null, saveStatus: "idle", frameBase: void 0 },
41
+ meta: { liveBlocks: null, saveStatus: "idle", frameBase: void 0, settingsFetchedAt: null },
42
42
  metaListeners: /* @__PURE__ */ new Set(),
43
43
  saveTimer: void 0,
44
44
  dirty: false,
@@ -46,6 +46,7 @@ function singleton() {
46
46
  legacyPending: false,
47
47
  channel: null,
48
48
  getFrame: null,
49
+ settingsFetchedAt: null,
49
50
  dispose: () => {
50
51
  }
51
52
  };
@@ -112,6 +113,8 @@ function sendToFrame(message) {
112
113
  function reportToEditor(s) {
113
114
  sendToEditor({ kind: "frame-info", base: resolveStoreBase() });
114
115
  sendToEditor({ kind: "live-blocks", blocks: s.ownBlocks });
116
+ if (s.settingsFetchedAt != null)
117
+ sendToEditor({ kind: "settings-fetched", at: s.settingsFetchedAt });
115
118
  }
116
119
  function listenForFrameMessages(s, signal) {
117
120
  window.addEventListener(
@@ -120,24 +123,31 @@ function listenForFrameMessages(s, signal) {
120
123
  if (event.origin !== window.location.origin || event.data?.type !== FRAME_MESSAGE) return;
121
124
  const message = event.data.message;
122
125
  if (window.parent !== window && event.source === window.parent) {
123
- if (message.kind === "request-live-blocks") reportToEditor(s);
124
- else if (message.kind === "focus-block") scrollToBlock(message.index);
125
- else if (message.kind === "lookup") void answerLookup(message);
126
+ answerEditor(s, message);
126
127
  return;
127
128
  }
128
129
  const frame = s.getFrame?.();
129
- if (!frame || event.source !== frame) return;
130
- if (message.kind === "lookup-result") settleLookup(message);
131
- else if (message.kind === "live-blocks") setMeta({ liveBlocks: message.blocks });
132
- else if (message.kind === "frame-info") setMeta({ frameBase: message.base });
130
+ if (frame && event.source === frame) takeFrameReport(message);
133
131
  },
134
132
  { signal }
135
133
  );
136
134
  }
135
+ function answerEditor(s, message) {
136
+ if (message.kind === "request-live-blocks") reportToEditor(s);
137
+ else if (message.kind === "focus-block") scrollToBlock(message.index);
138
+ else if (message.kind === "lookup") void answerLookup(message);
139
+ }
140
+ function takeFrameReport(message) {
141
+ if (message.kind === "lookup-result") settleLookup(message);
142
+ else if (message.kind === "live-blocks") setMeta({ liveBlocks: message.blocks });
143
+ else if (message.kind === "frame-info") setMeta({ frameBase: message.base });
144
+ else if (message.kind === "settings-fetched" && Number.isFinite(message.at))
145
+ setMeta({ settingsFetchedAt: message.at });
146
+ }
137
147
  async function answerLookup(message) {
138
148
  const { requestId, source, query } = message;
139
149
  try {
140
- const { lookupInStore } = await import('./store-lookup-XKL42Y4H.js');
150
+ const { lookupInStore } = await import('./store-lookup-TG6RV6NV.js');
141
151
  sendToEditor({ kind: "lookup-result", requestId, items: await lookupInStore(source, query) });
142
152
  } catch (error) {
143
153
  sendToEditor({
@@ -316,6 +326,15 @@ var devSettingsStore = {
316
326
  requestLiveBlocks() {
317
327
  sendToFrame({ kind: "request-live-blocks" });
318
328
  },
329
+ /**
330
+ * In the editor: a page loaded in the frame. The fetch time the last page
331
+ * reported says nothing about this one, and a page whose settings failed reports
332
+ * none, so it is dropped before this page is asked for its report.
333
+ */
334
+ frameLoaded() {
335
+ setMeta({ settingsFetchedAt: null });
336
+ sendToFrame({ kind: "request-live-blocks" });
337
+ },
319
338
  /**
320
339
  * Search the dev store through the editor's frame. Rejects when there is no
321
340
  * frame, it doesn't answer in time, or the store refuses; pickers then fall
@@ -338,6 +357,13 @@ var devSettingsStore = {
338
357
  focusBlock(index) {
339
358
  sendToFrame({ kind: "focus-block", index });
340
359
  },
360
+ /** In the frame: tell the editor when the server fetched the settings this page rendered with. */
361
+ reportSettingsFetchedAt(at) {
362
+ const s = singleton();
363
+ if (s.settingsFetchedAt === at) return;
364
+ s.settingsFetchedAt = at;
365
+ sendToEditor({ kind: "settings-fetched", at });
366
+ },
341
367
  getMeta: () => singleton().meta,
342
368
  subscribeMeta(listener) {
343
369
  const s = singleton();
@@ -407,7 +433,12 @@ var devSettingsStore = {
407
433
  );
408
434
  }
409
435
  };
410
- var SERVER_META = { liveBlocks: null, saveStatus: "idle", frameBase: void 0 };
436
+ var SERVER_META = {
437
+ liveBlocks: null,
438
+ saveStatus: "idle",
439
+ frameBase: void 0,
440
+ settingsFetchedAt: null
441
+ };
411
442
  function useDevEditorMeta() {
412
443
  return useSyncExternalStore(
413
444
  devSettingsStore.subscribeMeta,
@@ -423,6 +454,13 @@ function useDevSettingsState() {
423
454
  );
424
455
  }
425
456
  var useDevSettingsOverrides = import.meta.env.DEV ? useDevSettingsState : () => EMPTY_PREVIEW_STATE;
457
+ function useReportSettingsFetchedAt(at) {
458
+ useEffect(() => {
459
+ if (at != null) devSettingsStore.reportSettingsFetchedAt(at);
460
+ }, [at]);
461
+ }
462
+ var useDevReportSettingsFetchedAt = import.meta.env.DEV ? useReportSettingsFetchedAt : () => {
463
+ };
426
464
  function listsReshaped(before, after) {
427
465
  for (const key of /* @__PURE__ */ new Set([...Object.keys(before), ...Object.keys(after)])) {
428
466
  const a = before[key];
@@ -456,6 +494,6 @@ function useDevLayoutBlocks(components) {
456
494
  }
457
495
  var useDevHomeBlocks = import.meta.env.DEV ? useDevLayoutBlocks : (components) => components;
458
496
 
459
- export { blockPath, devSettingsStore, useDevEditorMeta, useDevHomeBlocks, useDevSettingsOverrides, useDevSettingsState };
460
- //# sourceMappingURL=chunk-MHLKLADI.js.map
461
- //# sourceMappingURL=chunk-MHLKLADI.js.map
497
+ export { blockPath, devSettingsStore, useDevEditorMeta, useDevHomeBlocks, useDevReportSettingsFetchedAt, useDevSettingsOverrides, useDevSettingsState };
498
+ //# sourceMappingURL=chunk-4LR7N76Q.js.map
499
+ //# sourceMappingURL=chunk-4LR7N76Q.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/dev/dev-settings-store.ts"],"names":["block"],"mappings":"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","file":"chunk-4LR7N76Q.js","sourcesContent":["/**\n * Client-side store for the dev editor: theme-setting overrides and a dev-owned\n * home layout. Saved to `twilight.preview.json` through the dev server (see\n * `twilight-schema.plugin.ts`), not to localStorage, for three reasons: the\n * server render can read a file, so the page hydrates with the edited layout\n * instead of flashing the store's; the state survives a port or browser\n * change; and the developer can open, diff or delete it.\n *\n * The saved state reaches this module through `virtual:twilight/schema`, which\n * the root route imports on both sides before anything renders and which puts\n * it on `globalThis[DEV_PREVIEW_GLOBAL]`. Server snapshots read that value\n * (the server's modules are re-run after each save); the browser copies it once\n * and then owns the state.\n *\n * The theme editor (`/__twilight/editor`) frames the storefront, so two copies\n * of this store run side by side. Edits reach every copy on the origin at once\n * over a `BroadcastChannel` (the file save is debounced), and only the copy\n * that made an edit saves it. Everything else between an editor and its frame\n * (the home page's blocks, the store base, scroll-to-block) goes by\n * `postMessage` to that one window, so another storefront tab never answers.\n */\n\nimport { useEffect, useMemo, useRef, useSyncExternalStore } from 'react';\nimport {\n DEV_LOOKUP_TIMEOUT_MS,\n DEV_PREVIEW_ENDPOINT,\n DEV_PREVIEW_EVENT,\n DEV_PREVIEW_GLOBAL,\n EMPTY_PREVIEW_STATE,\n isEditorFrame,\n normalizePreviewState,\n type DevLookupItem,\n type DevLookupSource,\n type DevPreviewBlock,\n type DevPreviewState,\n type DevSchema,\n} from './schema-types';\nimport { resolveStoreBase } from '../utils/store-identity';\n\nexport type DevSettingsState = DevPreviewState;\nexport type DevSaveStatus = 'idle' | 'saving' | 'saved' | 'error';\ntype LiveBlocks = { path?: string }[];\n\n/** Where the old localStorage-backed widget kept its state; migrated once. */\nconst LEGACY_STORAGE_KEY = 'twilight:dev-settings';\n/** Batch keystrokes into one write. */\nconst SAVE_DELAY_MS = 250;\n/** Same-browser channel every copy of the store listens on, for edits. */\nconst CHANNEL_NAME = 'twilight:preview';\n/** Envelope type of the editor ↔ frame `postMessage`s. */\nconst FRAME_MESSAGE = 'twilight:editor';\n/** How long the frame keeps looking for a block that is still rendering (just added, say). */\nconst FOCUS_WAIT_MS = 2000;\nconst FOCUS_FLASH_MS = 1200;\n\n/** Editor ↔ the storefront it frames. */\ntype FrameMessage =\n | { kind: 'live-blocks'; blocks: LiveBlocks | null }\n | { kind: 'frame-info'; base: string | null }\n | { kind: 'settings-fetched'; at: number }\n | { kind: 'request-live-blocks' }\n | { kind: 'focus-block'; index: number }\n | { kind: 'lookup'; requestId: string; source: DevLookupSource; query: string }\n | { kind: 'lookup-result'; requestId: string; items?: DevLookupItem[]; error?: string };\n\ninterface PendingLookup {\n resolve: (items: DevLookupItem[]) => void;\n reject: (error: Error) => void;\n timer: ReturnType<typeof setTimeout>;\n}\nconst pendingLookups = new Map<string, PendingLookup>();\n\n/** What the editor shows besides the saved state. */\nexport interface DevEditorMeta {\n /** The blocks the framed home page shows; `null` when it is not on the home page. */\n liveBlocks: LiveBlocks | null;\n saveStatus: DevSaveStatus;\n /** The frame's store segment; `undefined` until the frame has said. */\n frameBase: string | null | undefined;\n /**\n * When the dev server last asked the API for the frame's store settings (epoch\n * ms), which it reuses for a while (see `api/dev-settings-cache.ts`); `null`\n * until the frame says.\n */\n settingsFetchedAt: number | null;\n}\n\n/**\n * A short random hex id. `getRandomValues`, not `randomUUID`: the latter only\n * exists in secure contexts, and the dev server may be opened on a LAN address.\n */\nfunction randomId(bytes = 6): string {\n const values = globalThis.crypto.getRandomValues(new Uint8Array(bytes));\n return Array.from(values, (b) => b.toString(16).padStart(2, '0')).join('');\n}\n\nlet tabId: string | undefined;\n\n/**\n * Sent with every save so this tab can ignore its own broadcast. Made on first\n * use, never at module load: Cloudflare Workers refuse random values in global\n * scope, and this module is in the worker bundle (its use is dev-only, its\n * top level is not).\n */\nfunction myTabId(): string {\n tabId ??= randomId();\n return tabId;\n}\n\nlet seedSource: unknown;\nlet seedState: DevPreviewState = EMPTY_PREVIEW_STATE;\n\n/** The saved file as this page loaded it, normalized once per value so snapshots keep their identity. */\nfunction readSeed(): DevPreviewState {\n const raw = (globalThis as Record<string, unknown>)[DEV_PREVIEW_GLOBAL];\n if (raw !== seedSource) {\n seedSource = raw;\n seedState = normalizePreviewState(raw) ?? EMPTY_PREVIEW_STATE;\n }\n return seedState;\n}\n\n// The widget (bundled into the `/dev` entry) and the theme merge (bundled into\n// the engine index via `useTwilightInit`) import this module from two different\n// chunks, so each would otherwise get its OWN copy of the state — the widget\n// would enable a store the merge never reads. Back the state with a single\n// globalThis-keyed instance so every copy shares one source of truth. Dev-only,\n// so a global is acceptable (and lazy, so the module stays side-effect free and\n// tree-shakes out of production).\ninterface DevStoreSingleton {\n state: DevPreviewState;\n listeners: Set<() => void>;\n /** This page's own home blocks, when it is a storefront on its home page. Never saved. */\n ownBlocks: LiveBlocks | null;\n meta: DevEditorMeta;\n metaListeners: Set<() => void>;\n saveTimer: ReturnType<typeof setTimeout> | undefined;\n /** An edit that has not been sent yet. */\n dirty: boolean;\n /** A save request on its way; the next one waits for it, so saves land in order. */\n inFlight: boolean;\n /** The old localStorage copy is removed only once the file has the migrated values. */\n legacyPending: boolean;\n channel: BroadcastChannel | null;\n /** In the editor: the storefront frame's window. */\n getFrame: (() => Window | null) | null;\n /** In the frame: when the server fetched the settings this page rendered with. */\n settingsFetchedAt: number | null;\n /** Detach this copy's listeners and channel. A page keeps one copy for good; tests swap them. */\n dispose: () => void;\n}\n\nconst SINGLETON_KEY = '__twilightDevSettingsStore__';\n\nfunction singleton(): DevStoreSingleton {\n const g = globalThis as unknown as Record<string, DevStoreSingleton | undefined>;\n let s = g[SINGLETON_KEY];\n if (!s) {\n const seeded = (globalThis as Record<string, unknown>)[DEV_PREVIEW_GLOBAL] != null;\n s = {\n state: readSeed(),\n listeners: new Set(),\n ownBlocks: null,\n meta: { liveBlocks: null, saveStatus: 'idle', frameBase: undefined, settingsFetchedAt: null },\n metaListeners: new Set(),\n saveTimer: undefined,\n dirty: false,\n inFlight: false,\n legacyPending: false,\n channel: null,\n getFrame: null,\n settingsFetchedAt: null,\n dispose: () => {},\n };\n g[SINGLETON_KEY] = s;\n if (typeof window !== 'undefined') setUpBrowser(s, seeded);\n }\n return s;\n}\n\nfunction setUpBrowser(s: DevStoreSingleton, seeded: boolean): void {\n const listeners = new AbortController();\n const { signal } = listeners;\n if (!seeded) migrateLegacy(s);\n listenForOtherTabs();\n s.channel = openChannel();\n listenForFrameMessages(s, signal);\n window.addEventListener('pagehide', () => flushOnExit(s), { signal });\n s.dispose = () => {\n listeners.abort();\n s.channel?.close();\n clearTimeout(s.saveTimer);\n };\n if (isEditorFrame()) sendToEditor({ kind: 'frame-info', base: resolveStoreBase() });\n}\n\n/** Carry the old widget's settings over; its per-block patches don't map to a layout. */\nfunction migrateLegacy(s: DevStoreSingleton): void {\n try {\n const raw = window.localStorage.getItem(LEGACY_STORAGE_KEY);\n if (!raw) return;\n const legacy = normalizePreviewState(JSON.parse(raw));\n if (!legacy) return;\n s.state = { enabled: legacy.enabled, settings: legacy.settings, layout: null };\n s.legacyPending = true;\n scheduleSave(s);\n } catch {\n // Storage blocked or the old value is corrupt: nothing worth keeping.\n }\n}\n\n/** Vite's HMR client, typed locally: the engine's `ImportMeta` must not clash with `vite/client`. */\ninterface HotContext {\n on(event: string, cb: (payload: { state?: unknown; from?: unknown }) => void): void;\n}\n\n/**\n * Take a state another copy committed. Not while this copy has an edit of its\n * own waiting to be saved: that edit is newer, and saving it will tell the rest.\n */\nfunction receive(raw: unknown): void {\n const s = singleton();\n if (s.dirty || s.inFlight || s.saveTimer) return;\n const next = normalizePreviewState(raw);\n if (next && JSON.stringify(next) !== JSON.stringify(s.state)) emit(next);\n}\n\n/** Tabs in another browser hear about a save from the dev server. */\nfunction listenForOtherTabs(): void {\n const hot = (import.meta as ImportMeta & { hot?: HotContext }).hot;\n if (!hot) return;\n hot.on(DEV_PREVIEW_EVENT, (payload) => {\n if (payload?.from !== myTabId()) receive(payload?.state);\n });\n}\n\nfunction openChannel(): BroadcastChannel | null {\n if (typeof BroadcastChannel === 'undefined') return null;\n const channel = new BroadcastChannel(CHANNEL_NAME);\n channel.onmessage = ({ data }: MessageEvent<{ state?: unknown; from?: string }>) => {\n if (data && data.from !== myTabId()) receive(data.state);\n };\n return channel;\n}\n\nfunction sendToEditor(message: FrameMessage): void {\n if (isEditorFrame())\n window.parent.postMessage({ type: FRAME_MESSAGE, message }, window.location.origin);\n}\n\nfunction sendToFrame(message: FrameMessage): void {\n singleton().getFrame?.()?.postMessage({ type: FRAME_MESSAGE, message }, window.location.origin);\n}\n\nfunction reportToEditor(s: DevStoreSingleton): void {\n sendToEditor({ kind: 'frame-info', base: resolveStoreBase() });\n sendToEditor({ kind: 'live-blocks', blocks: s.ownBlocks });\n if (s.settingsFetchedAt != null)\n sendToEditor({ kind: 'settings-fetched', at: s.settingsFetchedAt });\n}\n\n/**\n * The editor ↔ frame conversation. A frame only takes requests from its own\n * parent; an editor only takes reports from the frame it shows.\n */\nfunction listenForFrameMessages(s: DevStoreSingleton, signal: AbortSignal): void {\n window.addEventListener(\n 'message',\n (event: MessageEvent) => {\n if (event.origin !== window.location.origin || event.data?.type !== FRAME_MESSAGE) return;\n const message = event.data.message as FrameMessage;\n if (window.parent !== window && event.source === window.parent) {\n answerEditor(s, message);\n return;\n }\n const frame = s.getFrame?.();\n if (frame && event.source === frame) takeFrameReport(message);\n },\n { signal }\n );\n}\n\n/** In the frame: what its editor asks for. */\nfunction answerEditor(s: DevStoreSingleton, message: FrameMessage): void {\n if (message.kind === 'request-live-blocks') reportToEditor(s);\n else if (message.kind === 'focus-block') scrollToBlock(message.index);\n else if (message.kind === 'lookup') void answerLookup(message);\n}\n\n/** In the editor: what its frame reports. */\nfunction takeFrameReport(message: FrameMessage): void {\n if (message.kind === 'lookup-result') settleLookup(message);\n else if (message.kind === 'live-blocks') setMeta({ liveBlocks: message.blocks });\n else if (message.kind === 'frame-info') setMeta({ frameBase: message.base });\n else if (message.kind === 'settings-fetched' && Number.isFinite(message.at))\n setMeta({ settingsFetchedAt: message.at });\n}\n\n/** In the frame: look the request up in the store and send back what was found, or why not. */\nasync function answerLookup(message: Extract<FrameMessage, { kind: 'lookup' }>): Promise<void> {\n const { requestId, source, query } = message;\n try {\n const { lookupInStore } = await import('./store-lookup');\n sendToEditor({ kind: 'lookup-result', requestId, items: await lookupInStore(source, query) });\n } catch (error) {\n sendToEditor({\n kind: 'lookup-result',\n requestId,\n error: error instanceof Error ? error.message : 'lookup failed',\n });\n }\n}\n\nfunction settleLookup(message: Extract<FrameMessage, { kind: 'lookup-result' }>): void {\n const pending = pendingLookups.get(message.requestId);\n if (!pending) return;\n pendingLookups.delete(message.requestId);\n clearTimeout(pending.timer);\n if (message.items) pending.resolve(message.items);\n else pending.reject(new Error(message.error ?? 'lookup failed'));\n}\n\n/**\n * In the editor's frame: bring a home block into view and flash an outline on\n * it. Dev-only editor chrome, so it styles the element directly rather than\n * through the theme's React tree. A block added a moment ago may not be in the\n * DOM yet, so look for it for a little while.\n */\nfunction scrollToBlock(index: number): void {\n const started = Date.now();\n const find = () => {\n const el = document.querySelector<HTMLElement>(`[data-home-block=\"${index}\"]`);\n if (!el) {\n if (Date.now() - started < FOCUS_WAIT_MS) requestAnimationFrame(find);\n return;\n }\n const { outline, outlineOffset, scrollMarginTop } = el.style;\n // Clear a sticky header, which would otherwise cover the block's top.\n el.style.scrollMarginTop = '80px';\n el.scrollIntoView({ behavior: 'smooth', block: 'start' });\n el.style.outline = '2px solid #0d9488';\n el.style.outlineOffset = '-2px';\n setTimeout(() => {\n el.style.outline = outline;\n el.style.outlineOffset = outlineOffset;\n el.style.scrollMarginTop = scrollMarginTop;\n }, FOCUS_FLASH_MS);\n };\n find();\n}\n\nfunction emit(next: DevPreviewState): void {\n const s = singleton();\n s.state = next;\n s.listeners.forEach((l) => l());\n}\n\nfunction setMeta(patch: Partial<DevEditorMeta>): void {\n const s = singleton();\n s.meta = { ...s.meta, ...patch };\n s.metaListeners.forEach((l) => l());\n}\n\nfunction saveRequest(s: DevStoreSingleton, keepalive = false): Promise<Response> {\n return fetch(DEV_PREVIEW_ENDPOINT, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ state: s.state, from: myTabId() }),\n keepalive,\n });\n}\n\n/** Send the current state, one request at a time; edits made meanwhile go in the next one. */\nasync function flush(s: DevStoreSingleton): Promise<void> {\n if (s.inFlight || !s.dirty) return;\n s.inFlight = true;\n s.dirty = false;\n let failed = false;\n try {\n const res = await saveRequest(s);\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n if (s.legacyPending) {\n s.legacyPending = false;\n try {\n window.localStorage.removeItem(LEGACY_STORAGE_KEY);\n } catch {\n // Storage went away; the file has the values now either way.\n }\n }\n if (!s.dirty && !s.saveTimer) setMeta({ saveStatus: 'saved' });\n } catch (error) {\n // Still unsaved: another tab's state must not replace it, and leaving the\n // page still sends it. Edits made while this request was out are sent once\n // more; the failed one alone waits for the next edit, so nothing loops.\n failed = !s.dirty;\n s.dirty = true;\n setMeta({ saveStatus: 'error' });\n console.error('[twilight-react:preview] could not save twilight.preview.json', error);\n } finally {\n s.inFlight = false;\n if (!failed && s.dirty && !s.saveTimer) void flush(s);\n }\n}\n\nfunction scheduleSave(s: DevStoreSingleton): void {\n if (typeof window === 'undefined' || typeof fetch === 'undefined') return;\n s.dirty = true;\n clearTimeout(s.saveTimer);\n setMeta({ saveStatus: 'saving' });\n s.saveTimer = setTimeout(() => {\n s.saveTimer = undefined;\n void flush(s);\n }, SAVE_DELAY_MS);\n}\n\n/** Closing or reloading the editor must not drop the last edit: send it on the way out. */\nfunction flushOnExit(s: DevStoreSingleton): void {\n if (!s.dirty) return;\n clearTimeout(s.saveTimer);\n s.saveTimer = undefined;\n s.dirty = false;\n void saveRequest(s, true).catch(() => {});\n}\n\nfunction commit(next: DevPreviewState): void {\n const s = singleton();\n emit(next);\n try {\n s.channel?.postMessage({ state: next, from: myTabId() });\n } catch {\n // A value that can't be cloned: the other copies pick it up from the save instead.\n }\n scheduleSave(s);\n}\n\nfunction newBlockId(): string {\n return `b-${randomId()}`;\n}\n\n/** Home loader spelling of a twilight.json path. */\nexport function blockPath(path: string): string {\n return path.replace(/^home\\./, '');\n}\n\nfunction updateLayout(update: (layout: DevPreviewBlock[]) => DevPreviewBlock[]): void {\n const { state } = singleton();\n commit({ ...state, layout: update(state.layout ?? []) });\n}\n\n/** A new block for a twilight.json component, filled with its defaults. */\nfunction blockFor(schema: DevSchema, path: string): DevPreviewBlock {\n const component = schema.components.find((c) => c.path === path);\n const defaults = schema.blockDefaults?.[path] ?? schema.componentDefaults[path] ?? {};\n return {\n id: newBlockId(),\n path: blockPath(path),\n fields: { ...(component?.key ? { key: component.key } : {}), ...defaults },\n };\n}\n\nexport const devSettingsStore = {\n get: (): DevPreviewState => singleton().state,\n /** What the server rendered: the saved file as of this page load. */\n getServer: (): DevPreviewState => readSeed(),\n subscribe(listener: () => void): () => void {\n const s = singleton();\n s.listeners.add(listener);\n return () => {\n s.listeners.delete(listener);\n };\n },\n /** Turn overrides on, seeding any unset setting with its twilight.json default. */\n enable(schema: DevSchema): void {\n const { state } = singleton();\n commit({\n ...state,\n enabled: true,\n settings: { ...schema.settingsDefaults, ...state.settings },\n });\n },\n disable(): void {\n commit({ ...singleton().state, enabled: false });\n },\n setSetting(id: string, value: unknown): void {\n const { state } = singleton();\n commit({ ...state, settings: { ...state.settings, [id]: value } });\n },\n /** Restore every setting to its twilight.json default (keeps enabled and the layout). */\n resetSettings(schema: DevSchema): void {\n commit({ ...singleton().state, settings: { ...schema.settingsDefaults } });\n },\n\n // ── Editor ↔ frame ───────────────────────────────────────────────────────\n\n /** The editor tells the store which window is its storefront frame. */\n connectFrame(getFrame: () => Window | null): () => void {\n const s = singleton();\n s.getFrame = getFrame;\n return () => {\n if (s.getFrame === getFrame) s.getFrame = null;\n };\n },\n /** A storefront's home page reports its blocks (`null` when it leaves); in the editor's frame they go to the editor. Not saved. */\n setLiveBlocks(blocks: LiveBlocks | null): void {\n const s = singleton();\n s.ownBlocks = blocks;\n sendToEditor({ kind: 'live-blocks', blocks });\n },\n /** Ask the frame for its home page's blocks and its store base. */\n requestLiveBlocks(): void {\n sendToFrame({ kind: 'request-live-blocks' });\n },\n /**\n * In the editor: a page loaded in the frame. The fetch time the last page\n * reported says nothing about this one, and a page whose settings failed reports\n * none, so it is dropped before this page is asked for its report.\n */\n frameLoaded(): void {\n setMeta({ settingsFetchedAt: null });\n sendToFrame({ kind: 'request-live-blocks' });\n },\n /**\n * Search the dev store through the editor's frame. Rejects when there is no\n * frame, it doesn't answer in time, or the store refuses; pickers then fall\n * back to samples.\n */\n lookup(source: DevLookupSource, query: string): Promise<DevLookupItem[]> {\n const frame = singleton().getFrame?.();\n if (!frame) return Promise.reject(new Error('no storefront frame'));\n const requestId = randomId();\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n pendingLookups.delete(requestId);\n reject(new Error('the storefront did not answer'));\n }, DEV_LOOKUP_TIMEOUT_MS);\n pendingLookups.set(requestId, { resolve, reject, timer });\n sendToFrame({ kind: 'lookup', requestId, source, query });\n });\n },\n /** Scroll the editor's frame to the home block at `index`. */\n focusBlock(index: number): void {\n sendToFrame({ kind: 'focus-block', index });\n },\n /** In the frame: tell the editor when the server fetched the settings this page rendered with. */\n reportSettingsFetchedAt(at: number): void {\n const s = singleton();\n if (s.settingsFetchedAt === at) return;\n s.settingsFetchedAt = at;\n sendToEditor({ kind: 'settings-fetched', at });\n },\n getMeta: (): DevEditorMeta => singleton().meta,\n subscribeMeta(listener: () => void): () => void {\n const s = singleton();\n s.metaListeners.add(listener);\n return () => {\n s.metaListeners.delete(listener);\n };\n },\n\n // ── Home layout ──────────────────────────────────────────────────────────\n\n /**\n * Take over the home layout. Starts from the blocks the home page showed (the\n * frame's in the editor; an empty page stays empty), otherwise from every\n * twilight.json component.\n */\n customizeLayout(schema: DevSchema): void {\n const s = singleton();\n const live = s.meta.liveBlocks ?? s.ownBlocks;\n const layout: DevPreviewBlock[] =\n live !== null\n ? live\n .filter((block): block is { path: string } => typeof block.path === 'string')\n .filter((block) => block.path !== '')\n .map(({ path, ...fields }) => ({ id: newBlockId(), path: blockPath(path), fields }))\n : schema.components.map((component) => blockFor(schema, component.path));\n commit({ ...s.state, enabled: true, layout });\n },\n startEmptyLayout(): void {\n commit({ ...singleton().state, enabled: true, layout: [] });\n },\n /** Back to the store's own blocks. */\n clearLayout(): void {\n commit({ ...singleton().state, layout: null });\n },\n /** Insert a twilight.json component at `at` (default: the end); returns the new block's id. */\n addBlock(schema: DevSchema, path: string, at?: number): string {\n const block = blockFor(schema, path);\n updateLayout((layout) => {\n const next = [...layout];\n next.splice(at ?? next.length, 0, block);\n return next;\n });\n return block.id;\n },\n removeBlock(id: string): void {\n updateLayout((layout) => layout.filter((block) => block.id !== id));\n },\n duplicateBlock(id: string): void {\n updateLayout((layout) => {\n const index = layout.findIndex((block) => block.id === id);\n if (index === -1) return layout;\n const copy = { ...layout[index], id: newBlockId(), fields: { ...layout[index].fields } };\n return [...layout.slice(0, index + 1), copy, ...layout.slice(index + 1)];\n });\n },\n /** Move a block to index `to` (its position after the move). */\n moveBlock(id: string, to: number): void {\n updateLayout((layout) => {\n const from = layout.findIndex((block) => block.id === id);\n if (from === -1) return layout;\n const target = Math.max(0, Math.min(to, layout.length - 1));\n if (target === from) return layout;\n const next = [...layout];\n const [block] = next.splice(from, 1);\n next.splice(target, 0, block);\n return next;\n });\n },\n setBlockField(id: string, fieldId: string, value: unknown): void {\n updateLayout((layout) =>\n layout.map((block) =>\n block.id === id ? { ...block, fields: { ...block.fields, [fieldId]: value } } : block\n )\n );\n },\n};\n\nconst SERVER_META: DevEditorMeta = {\n liveBlocks: null,\n saveStatus: 'idle',\n frameBase: undefined,\n settingsFetchedAt: null,\n};\n\n/** The frame's blocks and store base, and the save status, for the editor. */\nexport function useDevEditorMeta(): DevEditorMeta {\n return useSyncExternalStore(\n devSettingsStore.subscribeMeta,\n devSettingsStore.getMeta,\n () => SERVER_META\n );\n}\n\n/** Raw store subscription. */\nexport function useDevSettingsState(): DevPreviewState {\n return useSyncExternalStore(\n devSettingsStore.subscribe,\n devSettingsStore.get,\n devSettingsStore.getServer\n );\n}\n\n/**\n * Overrides for SSR-rendered consumers (the theme). The server and the first\n * browser render both read the saved file, so they agree and nothing flashes.\n *\n * Which hook this is gets decided once, when the module loads: in production\n * `import.meta.env.DEV` is a static `false`, so only the empty one survives\n * bundling and the store subscription (and the whole store module, which has\n * no other prod consumer) is dead-code-eliminated. No hook is ever called\n * conditionally.\n */\nexport const useDevSettingsOverrides: () => DevPreviewState = import.meta.env.DEV\n ? useDevSettingsState\n : () => EMPTY_PREVIEW_STATE;\n\nfunction useReportSettingsFetchedAt(at: number | undefined): void {\n useEffect(() => {\n if (at != null) devSettingsStore.reportSettingsFetchedAt(at);\n }, [at]);\n}\n\n/**\n * In the editor's frame: report when the dev server fetched this page's store\n * settings, so the editor can say how old they are. A no-op in production, decided\n * once at load like {@link useDevSettingsOverrides}.\n */\nexport const useDevReportSettingsFetchedAt: (at: number | undefined) => void = import.meta.env.DEV\n ? useReportSettingsFetchedAt\n : () => {};\n\n/** A rendered home block; `__dev_id` keys a dev-layout block across reorders. */\nexport type DevHomeBlock<T> = T & { __dev_id?: string };\n\n/**\n * Whether a list in a block's fields gained, lost or reordered items. Blocks\n * often hand their items to a web component that takes them once when it\n * starts (a slider moves its slides into its own track), so such a change\n * never reaches the page until the block mounts again. Editing an item's\n * values is not one: the nodes stay put and update in place.\n */\nexport function listsReshaped(\n before: Record<string, unknown>,\n after: Record<string, unknown>\n): boolean {\n for (const key of new Set([...Object.keys(before), ...Object.keys(after)])) {\n const a = before[key];\n const b = after[key];\n if (!Array.isArray(a) && !Array.isArray(b)) continue;\n if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) return true;\n const aItems = a.map((item) => JSON.stringify(item));\n const bItems = b.map((item) => JSON.stringify(item));\n const moved = aItems.some((item, i) => item !== bItems[i]);\n if (moved && [...aItems].sort().join('\\n') === [...bItems].sort().join('\\n')) return true;\n }\n return false;\n}\n\n/**\n * The home page's blocks: the dev layout when one is saved and enabled, else\n * the store's own blocks untouched. Also reports the store's blocks to the\n * editor so \"Customize\" can start from what the page showed, and withdraws\n * them when the page goes.\n *\n * Same production story as {@link useDevSettingsOverrides}: chosen once at\n * module load, so production keeps only the passthrough.\n */\nfunction useDevLayoutBlocks<T extends { path?: string }>(components: T[]): DevHomeBlock<T>[] {\n const overrides = useDevSettingsState();\n // Per block: the fields last rendered, and how often its lists were reshaped.\n const seen = useRef(new Map<string, { fields: Record<string, unknown>; mounts: number }>());\n useEffect(() => {\n devSettingsStore.setLiveBlocks(components);\n return () => devSettingsStore.setLiveBlocks(null);\n }, [components]);\n return useMemo(() => {\n if (!overrides.enabled || !overrides.layout) return components;\n return overrides.layout.map((block) => {\n const last = seen.current.get(block.id);\n const mounts =\n (last?.mounts ?? 0) + (last && listsReshaped(last.fields, block.fields) ? 1 : 0);\n seen.current.set(block.id, { fields: block.fields, mounts });\n // A new key mounts the block again, so a reshaped list reaches the page.\n const devId = mounts ? `${block.id}~${mounts}` : block.id;\n return { ...block.fields, path: block.path, __dev_id: devId } as DevHomeBlock<T>;\n });\n }, [components, overrides]);\n}\n\nexport const useDevHomeBlocks: <T extends { path?: string }>(components: T[]) => DevHomeBlock<T>[] =\n import.meta.env.DEV ? useDevLayoutBlocks : (components) => components;\n"]}
@@ -1,4 +1,4 @@
1
- import { getActiveScope, api } from './chunk-5LP2K2J7.js';
1
+ import { getActiveScope, api } from './chunk-S7QZUBXM.js';
2
2
  import { getTwilightContext } from './chunk-7VNVCHID.js';
3
3
  import { queryOptions } from '@tanstack/react-query';
4
4
 
@@ -25,5 +25,5 @@ var advertisement = {
25
25
  };
26
26
 
27
27
  export { advertisement, advertisementsFor };
28
- //# sourceMappingURL=chunk-FN2GQ2B5.js.map
29
- //# sourceMappingURL=chunk-FN2GQ2B5.js.map
28
+ //# sourceMappingURL=chunk-5GCOUJ7T.js.map
29
+ //# sourceMappingURL=chunk-5GCOUJ7T.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/api/advertisement.ts"],"names":[],"mappings":";;;;AAkBO,SAAS,iBAAA,CACd,KACA,QAAA,EACiB;AACjB,EAAA,OAAO,GAAA,CAAI,MAAA;AAAA,IACT,CAAC,EAAA,KACC,KAAA,CAAM,QAAQ,EAAA,CAAG,KAAK,MACrB,EAAA,CAAG,KAAA,CAAM,QAAA,CAAS,KAAK,KAAM,CAAC,CAAC,YAAY,EAAA,CAAG,KAAA,CAAM,SAAS,QAAQ,CAAA;AAAA,GAC1E;AACF;AAEO,IAAM,aAAA,GAAgB;AAAA;AAAA,EAE3B,MAAM,YAAsC;AAE1C,IAAA,MAAM,EAAE,IAAA,EAAK,GAAI,MAAM,GAAA,CACpB,GAAA,CAAI,gBAAA,EAAkB,EAAE,OAAA,EAAS,GAAA,EAAM,CAAA,CACvC,IAAA,EAAiC;AACpC,IAAA,OAAO,KAAA,CAAM,OAAA,CAAQ,IAAI,CAAA,GAAI,OAAO,EAAC;AAAA,EACvC,CAAA;AAAA,EAEA,OAAA,EAAS;AAAA,IACP,IAAA,EAAM,MACJ,YAAA,CAAa;AAAA,MACX,QAAA,EAAU,CAAC,gBAAA,EAAkB,kBAAA,EAAmB,CAAE,QAAQ,EAAE,KAAA,EAAO,cAAA,EAAe,EAAG,CAAA;AAAA,MACrF,OAAA,EAAS,MAAM,aAAA,CAAc,IAAA,EAAK;AAAA,MAClC,SAAA,EAAW,QAAA;AAAA;AAAA,MAEX,KAAA,EAAO;AAAA,KACR;AAAA;AAEP","file":"chunk-FN2GQ2B5.js","sourcesContent":["import { queryOptions } from '@tanstack/react-query';\nimport { api, getActiveScope } from './client';\nimport { getTwilightContext } from '../twilight/context';\n\n/** A merchant's announcement bar, as `GET advertisements` returns it. */\nexport interface Advertisement {\n id: number;\n title?: string;\n description?: string;\n icon?: string | null;\n url?: string | null;\n target?: string | null;\n colors?: { bg?: string; text?: string };\n /** Page slugs the ad shows on (`salla.config` `page.slug`), or `all`. */\n pages?: string[];\n}\n\n/** The ads a page shows: the rule the API applies to `?page=`, run on the full list. */\nexport function advertisementsFor(\n ads: readonly Advertisement[],\n pageSlug: string | null | undefined\n): Advertisement[] {\n return ads.filter(\n (ad) =>\n Array.isArray(ad.pages) &&\n (ad.pages.includes('all') || (!!pageSlug && ad.pages.includes(pageSlug)))\n );\n}\n\nexport const advertisement = {\n /** Every active ad, unfiltered: one request serves all pages, filtered with `advertisementsFor`. */\n list: async (): Promise<Advertisement[]> => {\n // Short timeout: it is fetched with the store settings on every server render.\n const { data } = await api\n .get('advertisements', { timeout: 3000 })\n .json<{ data?: Advertisement[] }>();\n return Array.isArray(data) ? data : [];\n },\n\n queries: {\n list: () =>\n queryOptions({\n queryKey: ['advertisements', getTwilightContext().locale, { scope: getActiveScope() }],\n queryFn: () => advertisement.list(),\n staleTime: Infinity,\n // Awaited in rootBeforeLoad: a retry would double the 3s budget. `PageAdvertisements` retries.\n retry: 0,\n }),\n },\n};\n"]}
1
+ {"version":3,"sources":["../src/api/advertisement.ts"],"names":[],"mappings":";;;;AAkBO,SAAS,iBAAA,CACd,KACA,QAAA,EACiB;AACjB,EAAA,OAAO,GAAA,CAAI,MAAA;AAAA,IACT,CAAC,EAAA,KACC,KAAA,CAAM,QAAQ,EAAA,CAAG,KAAK,MACrB,EAAA,CAAG,KAAA,CAAM,QAAA,CAAS,KAAK,KAAM,CAAC,CAAC,YAAY,EAAA,CAAG,KAAA,CAAM,SAAS,QAAQ,CAAA;AAAA,GAC1E;AACF;AAEO,IAAM,aAAA,GAAgB;AAAA;AAAA,EAE3B,MAAM,YAAsC;AAE1C,IAAA,MAAM,EAAE,IAAA,EAAK,GAAI,MAAM,GAAA,CACpB,GAAA,CAAI,gBAAA,EAAkB,EAAE,OAAA,EAAS,GAAA,EAAM,CAAA,CACvC,IAAA,EAAiC;AACpC,IAAA,OAAO,KAAA,CAAM,OAAA,CAAQ,IAAI,CAAA,GAAI,OAAO,EAAC;AAAA,EACvC,CAAA;AAAA,EAEA,OAAA,EAAS;AAAA,IACP,IAAA,EAAM,MACJ,YAAA,CAAa;AAAA,MACX,QAAA,EAAU,CAAC,gBAAA,EAAkB,kBAAA,EAAmB,CAAE,QAAQ,EAAE,KAAA,EAAO,cAAA,EAAe,EAAG,CAAA;AAAA,MACrF,OAAA,EAAS,MAAM,aAAA,CAAc,IAAA,EAAK;AAAA,MAClC,SAAA,EAAW,QAAA;AAAA;AAAA,MAEX,KAAA,EAAO;AAAA,KACR;AAAA;AAEP","file":"chunk-5GCOUJ7T.js","sourcesContent":["import { queryOptions } from '@tanstack/react-query';\nimport { api, getActiveScope } from './client';\nimport { getTwilightContext } from '../twilight/context';\n\n/** A merchant's announcement bar, as `GET advertisements` returns it. */\nexport interface Advertisement {\n id: number;\n title?: string;\n description?: string;\n icon?: string | null;\n url?: string | null;\n target?: string | null;\n colors?: { bg?: string; text?: string };\n /** Page slugs the ad shows on (`salla.config` `page.slug`), or `all`. */\n pages?: string[];\n}\n\n/** The ads a page shows: the rule the API applies to `?page=`, run on the full list. */\nexport function advertisementsFor(\n ads: readonly Advertisement[],\n pageSlug: string | null | undefined\n): Advertisement[] {\n return ads.filter(\n (ad) =>\n Array.isArray(ad.pages) &&\n (ad.pages.includes('all') || (!!pageSlug && ad.pages.includes(pageSlug)))\n );\n}\n\nexport const advertisement = {\n /** Every active ad, unfiltered: one request serves all pages, filtered with `advertisementsFor`. */\n list: async (): Promise<Advertisement[]> => {\n // Short timeout: it is fetched with the store settings on every server render.\n const { data } = await api\n .get('advertisements', { timeout: 3000 })\n .json<{ data?: Advertisement[] }>();\n return Array.isArray(data) ? data : [];\n },\n\n queries: {\n list: () =>\n queryOptions({\n queryKey: ['advertisements', getTwilightContext().locale, { scope: getActiveScope() }],\n queryFn: () => advertisement.list(),\n staleTime: Infinity,\n // Awaited in rootBeforeLoad: a retry would double the 3s budget. `PageAdvertisements` retries.\n retry: 0,\n }),\n },\n};\n"]}
@@ -1,7 +1,7 @@
1
1
  import { MadeWithSalla } from './chunk-OQIIJRAS.js';
2
2
  import { HookSlot, useIsClient } from './chunk-5XDPAKF5.js';
3
3
  import { useTranslation } from './chunk-TYNZ5B2B.js';
4
- import { Image } from './chunk-JAKLD546.js';
4
+ import { Image } from './chunk-JUKKXGHR.js';
5
5
  import { Link } from './chunk-AXW67SY7.js';
6
6
  import { LazyImageModal } from './chunk-7V5HOZW4.js';
7
7
  import { useTwilight } from './chunk-DF6FBKDN.js';
@@ -281,5 +281,5 @@ function Footer({ inSheet = false } = {}) {
281
281
  }
282
282
 
283
283
  export { Footer };
284
- //# sourceMappingURL=chunk-6PK4GITC.js.map
285
- //# sourceMappingURL=chunk-6PK4GITC.js.map
284
+ //# sourceMappingURL=chunk-5U7LPEFE.js.map
285
+ //# sourceMappingURL=chunk-5U7LPEFE.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/layout/Footer.tsx"],"names":[],"mappings":"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","file":"chunk-6PK4GITC.js","sourcesContent":["import { useState } from 'react';\nimport { SallaAppsIcons } from '@salla.sa/twilight-components-react/apps-icons';\nimport { SallaContacts } from '@salla.sa/twilight-components-react/contacts';\nimport { SallaSocial } from '@salla.sa/twilight-components-react/social';\nimport { SallaMenu } from '@salla.sa/twilight-components-react/menu';\nimport { SallaTrustBadges } from '@salla.sa/twilight-components-react/trust-badges';\nimport { SallaPayments } from '@salla.sa/twilight-components-react/payments';\nimport { useTwilight } from '../../providers/twilight-context';\nimport { useTranslation } from '../../providers/I18nProvider';\nimport { HookSlot } from '../../hooks/HookSlot';\nimport { useIsClient } from '../../hooks/useIsClient';\nimport { Link, Image } from '../common';\nimport { ImageModal } from '../modal';\nimport { MadeWithSalla } from './MadeWithSalla';\n\n/** Salla's value-added-tax badge icon (70×70, CDN-resized) — a platform\n * asset shared by every store, not specific to any one theme. */\nconst TAX_ICON_URL =\n 'https://cdn.salla.network/cdn-cgi/image/fit=scale-down,width=70,height=70,onerror=redirect,format=auto/images/tax.png?v=2.0.5';\n\n/**\n * The store's value-added-tax registration: the tax number, plus the certificate as\n * the tax icon that opens the certificate image full size in a modal. Nothing shows\n * when the store has no tax number.\n */\nfunction FooterTax({ dark }: { dark: boolean }) {\n const { store } = useTwilight();\n const { t } = useTranslation();\n const [open, setOpen] = useState(false);\n const number = store.settings?.tax?.number;\n const certificate = store.settings?.tax?.certificate;\n if (!number) return null;\n\n return (\n <div\n data-testid=\"store-footer-tax\"\n className=\"store-footer__tax flex items-end gap-2 rtl:space-x-reverse\"\n >\n {certificate && (\n <>\n <button\n type=\"button\"\n data-testid=\"store-footer-tax-certificate\"\n className=\"store-footer__tax-cert shrink-0\"\n aria-label={t('common.elements.tax_certificate', 'Tax Certificate')}\n aria-haspopup=\"dialog\"\n onClick={() => setOpen(true)}\n >\n <img\n src={TAX_ICON_URL}\n alt={t('common.elements.tax_certificate', 'Tax Certificate')}\n width={40}\n height={50}\n loading=\"lazy\"\n decoding=\"async\"\n className=\"w-10 rounded-sm transition-opacity hover:opacity-80\"\n />\n </button>\n <ImageModal\n isOpen={open}\n onClose={() => setOpen(false)}\n src={certificate}\n alt={t('common.elements.tax_certificate', 'Tax Certificate')}\n title={t('common.elements.tax_certificate', 'Tax Certificate')}\n />\n </>\n )}\n <div>\n <p className={`mb-1 text-sm opacity-70 ${dark ? 'text-white' : ''}`}>\n {t('common.elements.tax_number', 'Tax Number')}\n </p>\n <b className=\"text-sm\">{number}</b>\n </div>\n </div>\n );\n}\n\n/** Saudi Business Center (SBC) logo, CDN-versioned like the tax icon -- also a\n * platform asset, not theme-specific. */\nconst SBC_ICON_URL = 'https://cdn.salla.network/images/sbc.png?v=2.0.5';\n\n/**\n * The store's Saudi Business Center certificate: a \"Trusted by Business Platform\" badge that\n * opens the certificate's page on the SBC site so visitors can verify the merchant. Nothing\n * shows when the store has no certificate.\n */\nfunction FooterSbc({ dark }: { dark: boolean }) {\n const { store } = useTwilight();\n const { t } = useTranslation();\n const id = store.settings?.certificate?.id;\n if (!id) return null;\n\n return (\n <a\n href={`https://eauthenticate.saudibusiness.gov.sa/certificate-details/${encodeURIComponent(id)}`}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n data-testid=\"store-footer-sbc\"\n className=\"store-footer__sbc flex items-center gap-2.5 transition-opacity hover:opacity-75\"\n >\n <img\n src={SBC_ICON_URL}\n alt={`SBC ${id}`}\n width={56}\n height={40}\n loading=\"lazy\"\n decoding=\"async\"\n className=\"h-10 w-14 rounded-sm\"\n />\n <div>\n <p className={`text-xs opacity-70 ${dark ? 'text-white' : ''}`}>\n {t('blocks.footer.sbc_trusted_by', 'Trusted by')}\n </p>\n <b className=\"text-sm\">{t('blocks.footer.sbc_platform', 'Business Platform')}</b>\n </div>\n </a>\n );\n}\n\n/** Trust badges, the tax registration and the SBC badge, side by side (wrapping on narrow columns). */\nfunction FooterTrust({ dark, centered }: { dark: boolean; centered: boolean }) {\n return (\n <div\n data-testid=\"store-footer-trust\"\n className={`store-footer__trust flex flex-wrap items-end gap-x-6 gap-y-3${centered ? ' justify-center' : ''}`}\n >\n <FooterTax dark={dark} />\n <FooterSbc dark={dark} />\n <SallaTrustBadges {...(dark ? { dark: true } : {})} />\n </div>\n );\n}\n\n/**\n * The footer's own menu of (\"important\") links -- skipped entirely when\n * `inSheet`, for a theme that opens it from somewhere else of its own (a\n * mobile account sheet, a dedicated links screen, …) instead; showing it\n * again down here would just be a redundant second copy. `heading` wraps it\n * in the grid layout's own `.store-footer__links` column; the centered\n * layout's inline row has none.\n */\nfunction FooterLinksMenu({\n inSheet,\n className,\n heading,\n dark,\n}: {\n inSheet: boolean;\n className: string;\n heading?: string;\n dark: boolean;\n}) {\n if (inSheet) return null;\n\n const menu = <SallaMenu source=\"footer\" className={className} suppressHydrationWarning />;\n if (!heading) return menu;\n\n return (\n <div className=\"store-footer__links\">\n <h3 className={`mb-3 text-lg font-bold lg:mb-5 ${dark ? 'text-white' : 'text-gray-900'}`}>\n {heading}\n </h3>\n {menu}\n </div>\n );\n}\n\n/** App-store / Google-Play buttons. Nothing shows -- not even the wrapping\n * div -- when the store has neither link set. */\nfunction FooterApps({ className }: { className: string }) {\n const { store } = useTwilight();\n const { t } = useTranslation();\n // The web component fills its light DOM before React hydrates the footer, a hydration error.\n const isClient = useIsClient();\n if (!store.apps?.appstore && !store.apps?.googleplay) return null;\n\n return (\n <div data-testid=\"store-footer-apps\" className={`store-footer__apps ${className}`}>\n {isClient && (\n <SallaAppsIcons\n apps={store.apps}\n appsTitle={t('blocks.footer.download_apps', 'Get our apps')}\n />\n )}\n </div>\n );\n}\n\n/** The logo link, same shape in both layouts -- only its own spacing differs. */\nfunction FooterLogo({ className }: { className: string }) {\n const { store } = useTwilight();\n return (\n <Link\n to=\"/\"\n className={`store-footer__logo inline-flex items-center m-0 transition-opacity hover:opacity-75 ${className}`}\n >\n <Image\n src={store.logo}\n alt={store.name || 'Store'}\n width={150}\n height={44}\n objectFit=\"contain\"\n className=\"h-11 w-auto max-w-[180px]\"\n />\n </Link>\n );\n}\n\n/** Merchant-authored description HTML -- mirrors the Twig theme's\n * `store.description|raw`. Renders nothing when the store has none set. */\nfunction FooterDescription({ className }: { className: string }) {\n const { store } = useTwilight();\n if (!store.description) return null;\n return (\n <div\n className={`store-footer__desc opacity-80 ${className}`}\n dangerouslySetInnerHTML={{ __html: store.description }}\n />\n );\n}\n\n/** The store's phone and email as one \"Contact us: …\" row under the description\n * (`<salla-contacts>`'s compact `isHeader` layout, which shows only those two).\n * Renders nothing when the store has neither. */\nfunction FooterContacts({ className }: { className: string }) {\n const { store } = useTwilight();\n const { t } = useTranslation();\n // The web component fills its light DOM once the SDK is ready, which can come before\n // React hydrates the footer's Suspense boundary: a hydration error (React #418).\n const isClient = useIsClient();\n if (!store.contacts?.phone && !store.contacts?.email) return null;\n return (\n <div className={`store-footer__contacts ${className}`}>\n {isClient && (\n <SallaContacts\n contacts={store.contacts}\n contactsTitle={t('blocks.footer.social', 'Contact us')}\n isHeader\n />\n )}\n </div>\n );\n}\n\n/** Centered layout: logo, description, contacts, social, footer menu, trust\n * badges and app buttons stacked as one centered column. */\nfunction FooterCenteredBody({ inSheet, isDark }: { inSheet: boolean; isDark: boolean }) {\n return (\n <div className=\"container mx-auto flex max-w-2xl flex-col items-center gap-6 text-center\">\n <FooterLogo className=\"\" />\n <FooterDescription className=\"\" />\n <FooterContacts className=\"\" />\n <SallaSocial />\n\n <FooterLinksMenu\n inSheet={inSheet}\n className=\"store-footer__menu store-footer__menu--inline\"\n dark={isDark}\n />\n\n <FooterTrust dark={isDark} centered />\n\n <FooterApps className=\"flex flex-col items-center gap-3\" />\n </div>\n );\n}\n\n/** Columns layout: brand (logo / description / contacts / social / trust) and app\n * buttons side by side, with the footer menu as its own labeled column. */\nfunction FooterColumnsBody({ inSheet, isDark }: { inSheet: boolean; isDark: boolean }) {\n const { t } = useTranslation();\n\n return (\n <div className=\"container grid grid-cols-1 gap-10 sm:grid-cols-2 lg:grid-cols-4 lg:gap-16\">\n <div className=\"store-footer__brand rtl:lg:pl-16 ltr:lg:pr-16 sm:col-span-2\">\n <FooterLogo className=\"mb-5\" />\n <FooterDescription className=\"max-w-sm leading-6 my-5\" />\n <FooterContacts className=\"mb-6\" />\n <SallaSocial className=\"block mb-6\" />\n <FooterTrust dark={isDark} centered={false} />\n </div>\n\n <FooterLinksMenu\n inSheet={inSheet}\n className=\"store-footer__menu store-footer__menu--stacked\"\n heading={t('blocks.footer.important_links', 'Important links')}\n dark={isDark}\n />\n\n <FooterApps className=\"\" />\n </div>\n );\n}\n\nexport interface FooterProps {\n /**\n * Renders as a plain `<div>` (no second `<footer>` landmark) with the\n * `footer:start` / `footer:end` hook slots skipped -- for a theme that\n * repeats these widgets somewhere other than the page's own footer (a\n * mobile sheet, for example) rather than rendering the real page footer a\n * second time.\n */\n inSheet?: boolean;\n}\n\n/**\n * Storefront footer.\n *\n * Two layouts, chosen by the `footer_layout` theme setting:\n * - **columns** (default): logo / description / social / trust badges, the\n * footer menu (\"important links\"), and app-store buttons, side by side.\n * - **centered**: the same pieces stacked as one centered column, with the\n * footer menu laid out as an inline, pipe-separated row.\n *\n * Styling for the handful of pieces rendered by web components this owns no\n * markup for (`<salla-social>`'s `.social-link` icons, `<salla-menu>`'s\n * `.s-menu-footer-item` rows, `<salla-payments>`'s `.s-payments-list-item`\n * icons) is the consuming theme's own responsibility, the same way\n * `inSheet`'s own presentation is -- this component owns structure and data,\n * not every pixel.\n */\nexport function Footer({ inSheet = false }: FooterProps = {}) {\n const { store, theme } = useTwilight();\n const { t } = useTranslation();\n const year = new Date().getFullYear();\n const isCentered = theme.settings?.footer_layout === 'centered';\n const isDark = !!theme.settings?.footer_is_dark;\n\n const Root = inSheet ? 'div' : 'footer';\n\n return (\n <Root\n className={`store-footer store-footer--${isCentered ? 'centered' : 'columns'}${\n inSheet ? ' store-footer--sheet' : ''\n } relative mt-8 sm:mt-16 ${isDark ? 'bg-[#0E0F0F] text-white' : 'bg-[#F4F7F2] text-gray-600'}`}\n suppressHydrationWarning\n >\n {!inSheet && <HookSlot name=\"footer:start\" />}\n\n <div\n aria-label=\"footer\"\n className={`store-footer__inner border-b py-8 lg:py-16 ${\n isDark ? 'bg-[#1D1F1F] border-dashed border-white/10' : 'bg-transparent border-gray-200'\n }`}\n >\n {isCentered ? (\n <FooterCenteredBody inSheet={inSheet} isDark={isDark} />\n ) : (\n <FooterColumnsBody inSheet={inSheet} isDark={isDark} />\n )}\n </div>\n\n <div className=\"store-footer__bottom container md:flex items-center justify-between gap-4 py-4 lg:py-7 text-center\">\n <span className={`text-sm copyright-text ${isDark ? 'text-gray-400' : 'text-gray-700'}`}>\n <HookSlot\n name=\"copyright\"\n context={{ storeName: store.name }}\n fallback={\n <>\n {t('blocks.footer.copyright', 'All rights reserved')}{' '}\n <Link to=\"/\" className=\"transition-opacity hover:opacity-75 hover:text-primary\">\n {store.name}\n </Link>{' '}\n © {year}\n <MadeWithSalla className=\"ms-2\" />\n </>\n }\n />\n </span>\n\n <SallaPayments />\n </div>\n\n {!inSheet && <HookSlot name=\"footer:end\" />}\n </Root>\n );\n}\n"]}
1
+ {"version":3,"sources":["../src/components/layout/Footer.tsx"],"names":[],"mappings":"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","file":"chunk-5U7LPEFE.js","sourcesContent":["import { useState } from 'react';\nimport { SallaAppsIcons } from '@salla.sa/twilight-components-react/apps-icons';\nimport { SallaContacts } from '@salla.sa/twilight-components-react/contacts';\nimport { SallaSocial } from '@salla.sa/twilight-components-react/social';\nimport { SallaMenu } from '@salla.sa/twilight-components-react/menu';\nimport { SallaTrustBadges } from '@salla.sa/twilight-components-react/trust-badges';\nimport { SallaPayments } from '@salla.sa/twilight-components-react/payments';\nimport { useTwilight } from '../../providers/twilight-context';\nimport { useTranslation } from '../../providers/I18nProvider';\nimport { HookSlot } from '../../hooks/HookSlot';\nimport { useIsClient } from '../../hooks/useIsClient';\nimport { Link, Image } from '../common';\nimport { ImageModal } from '../modal';\nimport { MadeWithSalla } from './MadeWithSalla';\n\n/** Salla's value-added-tax badge icon (70×70, CDN-resized) — a platform\n * asset shared by every store, not specific to any one theme. */\nconst TAX_ICON_URL =\n 'https://cdn.salla.network/cdn-cgi/image/fit=scale-down,width=70,height=70,onerror=redirect,format=auto/images/tax.png?v=2.0.5';\n\n/**\n * The store's value-added-tax registration: the tax number, plus the certificate as\n * the tax icon that opens the certificate image full size in a modal. Nothing shows\n * when the store has no tax number.\n */\nfunction FooterTax({ dark }: { dark: boolean }) {\n const { store } = useTwilight();\n const { t } = useTranslation();\n const [open, setOpen] = useState(false);\n const number = store.settings?.tax?.number;\n const certificate = store.settings?.tax?.certificate;\n if (!number) return null;\n\n return (\n <div\n data-testid=\"store-footer-tax\"\n className=\"store-footer__tax flex items-end gap-2 rtl:space-x-reverse\"\n >\n {certificate && (\n <>\n <button\n type=\"button\"\n data-testid=\"store-footer-tax-certificate\"\n className=\"store-footer__tax-cert shrink-0\"\n aria-label={t('common.elements.tax_certificate', 'Tax Certificate')}\n aria-haspopup=\"dialog\"\n onClick={() => setOpen(true)}\n >\n <img\n src={TAX_ICON_URL}\n alt={t('common.elements.tax_certificate', 'Tax Certificate')}\n width={40}\n height={50}\n loading=\"lazy\"\n decoding=\"async\"\n className=\"w-10 rounded-sm transition-opacity hover:opacity-80\"\n />\n </button>\n <ImageModal\n isOpen={open}\n onClose={() => setOpen(false)}\n src={certificate}\n alt={t('common.elements.tax_certificate', 'Tax Certificate')}\n title={t('common.elements.tax_certificate', 'Tax Certificate')}\n />\n </>\n )}\n <div>\n <p className={`mb-1 text-sm opacity-70 ${dark ? 'text-white' : ''}`}>\n {t('common.elements.tax_number', 'Tax Number')}\n </p>\n <b className=\"text-sm\">{number}</b>\n </div>\n </div>\n );\n}\n\n/** Saudi Business Center (SBC) logo, CDN-versioned like the tax icon -- also a\n * platform asset, not theme-specific. */\nconst SBC_ICON_URL = 'https://cdn.salla.network/images/sbc.png?v=2.0.5';\n\n/**\n * The store's Saudi Business Center certificate: a \"Trusted by Business Platform\" badge that\n * opens the certificate's page on the SBC site so visitors can verify the merchant. Nothing\n * shows when the store has no certificate.\n */\nfunction FooterSbc({ dark }: { dark: boolean }) {\n const { store } = useTwilight();\n const { t } = useTranslation();\n const id = store.settings?.certificate?.id;\n if (!id) return null;\n\n return (\n <a\n href={`https://eauthenticate.saudibusiness.gov.sa/certificate-details/${encodeURIComponent(id)}`}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n data-testid=\"store-footer-sbc\"\n className=\"store-footer__sbc flex items-center gap-2.5 transition-opacity hover:opacity-75\"\n >\n <img\n src={SBC_ICON_URL}\n alt={`SBC ${id}`}\n width={56}\n height={40}\n loading=\"lazy\"\n decoding=\"async\"\n className=\"h-10 w-14 rounded-sm\"\n />\n <div>\n <p className={`text-xs opacity-70 ${dark ? 'text-white' : ''}`}>\n {t('blocks.footer.sbc_trusted_by', 'Trusted by')}\n </p>\n <b className=\"text-sm\">{t('blocks.footer.sbc_platform', 'Business Platform')}</b>\n </div>\n </a>\n );\n}\n\n/** Trust badges, the tax registration and the SBC badge, side by side (wrapping on narrow columns). */\nfunction FooterTrust({ dark, centered }: { dark: boolean; centered: boolean }) {\n return (\n <div\n data-testid=\"store-footer-trust\"\n className={`store-footer__trust flex flex-wrap items-end gap-x-6 gap-y-3${centered ? ' justify-center' : ''}`}\n >\n <FooterTax dark={dark} />\n <FooterSbc dark={dark} />\n <SallaTrustBadges {...(dark ? { dark: true } : {})} />\n </div>\n );\n}\n\n/**\n * The footer's own menu of (\"important\") links -- skipped entirely when\n * `inSheet`, for a theme that opens it from somewhere else of its own (a\n * mobile account sheet, a dedicated links screen, …) instead; showing it\n * again down here would just be a redundant second copy. `heading` wraps it\n * in the grid layout's own `.store-footer__links` column; the centered\n * layout's inline row has none.\n */\nfunction FooterLinksMenu({\n inSheet,\n className,\n heading,\n dark,\n}: {\n inSheet: boolean;\n className: string;\n heading?: string;\n dark: boolean;\n}) {\n if (inSheet) return null;\n\n const menu = <SallaMenu source=\"footer\" className={className} suppressHydrationWarning />;\n if (!heading) return menu;\n\n return (\n <div className=\"store-footer__links\">\n <h3 className={`mb-3 text-lg font-bold lg:mb-5 ${dark ? 'text-white' : 'text-gray-900'}`}>\n {heading}\n </h3>\n {menu}\n </div>\n );\n}\n\n/** App-store / Google-Play buttons. Nothing shows -- not even the wrapping\n * div -- when the store has neither link set. */\nfunction FooterApps({ className }: { className: string }) {\n const { store } = useTwilight();\n const { t } = useTranslation();\n // The web component fills its light DOM before React hydrates the footer, a hydration error.\n const isClient = useIsClient();\n if (!store.apps?.appstore && !store.apps?.googleplay) return null;\n\n return (\n <div data-testid=\"store-footer-apps\" className={`store-footer__apps ${className}`}>\n {isClient && (\n <SallaAppsIcons\n apps={store.apps}\n appsTitle={t('blocks.footer.download_apps', 'Get our apps')}\n />\n )}\n </div>\n );\n}\n\n/** The logo link, same shape in both layouts -- only its own spacing differs. */\nfunction FooterLogo({ className }: { className: string }) {\n const { store } = useTwilight();\n return (\n <Link\n to=\"/\"\n className={`store-footer__logo inline-flex items-center m-0 transition-opacity hover:opacity-75 ${className}`}\n >\n <Image\n src={store.logo}\n alt={store.name || 'Store'}\n width={150}\n height={44}\n objectFit=\"contain\"\n className=\"h-11 w-auto max-w-[180px]\"\n />\n </Link>\n );\n}\n\n/** Merchant-authored description HTML -- mirrors the Twig theme's\n * `store.description|raw`. Renders nothing when the store has none set. */\nfunction FooterDescription({ className }: { className: string }) {\n const { store } = useTwilight();\n if (!store.description) return null;\n return (\n <div\n className={`store-footer__desc opacity-80 ${className}`}\n dangerouslySetInnerHTML={{ __html: store.description }}\n />\n );\n}\n\n/** The store's phone and email as one \"Contact us: …\" row under the description\n * (`<salla-contacts>`'s compact `isHeader` layout, which shows only those two).\n * Renders nothing when the store has neither. */\nfunction FooterContacts({ className }: { className: string }) {\n const { store } = useTwilight();\n const { t } = useTranslation();\n // The web component fills its light DOM once the SDK is ready, which can come before\n // React hydrates the footer's Suspense boundary: a hydration error (React #418).\n const isClient = useIsClient();\n if (!store.contacts?.phone && !store.contacts?.email) return null;\n return (\n <div className={`store-footer__contacts ${className}`}>\n {isClient && (\n <SallaContacts\n contacts={store.contacts}\n contactsTitle={t('blocks.footer.social', 'Contact us')}\n isHeader\n />\n )}\n </div>\n );\n}\n\n/** Centered layout: logo, description, contacts, social, footer menu, trust\n * badges and app buttons stacked as one centered column. */\nfunction FooterCenteredBody({ inSheet, isDark }: { inSheet: boolean; isDark: boolean }) {\n return (\n <div className=\"container mx-auto flex max-w-2xl flex-col items-center gap-6 text-center\">\n <FooterLogo className=\"\" />\n <FooterDescription className=\"\" />\n <FooterContacts className=\"\" />\n <SallaSocial />\n\n <FooterLinksMenu\n inSheet={inSheet}\n className=\"store-footer__menu store-footer__menu--inline\"\n dark={isDark}\n />\n\n <FooterTrust dark={isDark} centered />\n\n <FooterApps className=\"flex flex-col items-center gap-3\" />\n </div>\n );\n}\n\n/** Columns layout: brand (logo / description / contacts / social / trust) and app\n * buttons side by side, with the footer menu as its own labeled column. */\nfunction FooterColumnsBody({ inSheet, isDark }: { inSheet: boolean; isDark: boolean }) {\n const { t } = useTranslation();\n\n return (\n <div className=\"container grid grid-cols-1 gap-10 sm:grid-cols-2 lg:grid-cols-4 lg:gap-16\">\n <div className=\"store-footer__brand rtl:lg:pl-16 ltr:lg:pr-16 sm:col-span-2\">\n <FooterLogo className=\"mb-5\" />\n <FooterDescription className=\"max-w-sm leading-6 my-5\" />\n <FooterContacts className=\"mb-6\" />\n <SallaSocial className=\"block mb-6\" />\n <FooterTrust dark={isDark} centered={false} />\n </div>\n\n <FooterLinksMenu\n inSheet={inSheet}\n className=\"store-footer__menu store-footer__menu--stacked\"\n heading={t('blocks.footer.important_links', 'Important links')}\n dark={isDark}\n />\n\n <FooterApps className=\"\" />\n </div>\n );\n}\n\nexport interface FooterProps {\n /**\n * Renders as a plain `<div>` (no second `<footer>` landmark) with the\n * `footer:start` / `footer:end` hook slots skipped -- for a theme that\n * repeats these widgets somewhere other than the page's own footer (a\n * mobile sheet, for example) rather than rendering the real page footer a\n * second time.\n */\n inSheet?: boolean;\n}\n\n/**\n * Storefront footer.\n *\n * Two layouts, chosen by the `footer_layout` theme setting:\n * - **columns** (default): logo / description / social / trust badges, the\n * footer menu (\"important links\"), and app-store buttons, side by side.\n * - **centered**: the same pieces stacked as one centered column, with the\n * footer menu laid out as an inline, pipe-separated row.\n *\n * Styling for the handful of pieces rendered by web components this owns no\n * markup for (`<salla-social>`'s `.social-link` icons, `<salla-menu>`'s\n * `.s-menu-footer-item` rows, `<salla-payments>`'s `.s-payments-list-item`\n * icons) is the consuming theme's own responsibility, the same way\n * `inSheet`'s own presentation is -- this component owns structure and data,\n * not every pixel.\n */\nexport function Footer({ inSheet = false }: FooterProps = {}) {\n const { store, theme } = useTwilight();\n const { t } = useTranslation();\n const year = new Date().getFullYear();\n const isCentered = theme.settings?.footer_layout === 'centered';\n const isDark = !!theme.settings?.footer_is_dark;\n\n const Root = inSheet ? 'div' : 'footer';\n\n return (\n <Root\n className={`store-footer store-footer--${isCentered ? 'centered' : 'columns'}${\n inSheet ? ' store-footer--sheet' : ''\n } relative mt-8 sm:mt-16 ${isDark ? 'bg-[#0E0F0F] text-white' : 'bg-[#F4F7F2] text-gray-600'}`}\n suppressHydrationWarning\n >\n {!inSheet && <HookSlot name=\"footer:start\" />}\n\n <div\n aria-label=\"footer\"\n className={`store-footer__inner border-b py-8 lg:py-16 ${\n isDark ? 'bg-[#1D1F1F] border-dashed border-white/10' : 'bg-transparent border-gray-200'\n }`}\n >\n {isCentered ? (\n <FooterCenteredBody inSheet={inSheet} isDark={isDark} />\n ) : (\n <FooterColumnsBody inSheet={inSheet} isDark={isDark} />\n )}\n </div>\n\n <div className=\"store-footer__bottom container md:flex items-center justify-between gap-4 py-4 lg:py-7 text-center\">\n <span className={`text-sm copyright-text ${isDark ? 'text-gray-400' : 'text-gray-700'}`}>\n <HookSlot\n name=\"copyright\"\n context={{ storeName: store.name }}\n fallback={\n <>\n {t('blocks.footer.copyright', 'All rights reserved')}{' '}\n <Link to=\"/\" className=\"transition-opacity hover:opacity-75 hover:text-primary\">\n {store.name}\n </Link>{' '}\n © {year}\n <MadeWithSalla className=\"ms-2\" />\n </>\n }\n />\n </span>\n\n <SallaPayments />\n </div>\n\n {!inSheet && <HookSlot name=\"footer:end\" />}\n </Root>\n );\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { getActiveCurrency } from './chunk-5LP2K2J7.js';
1
+ import { getActiveCurrency } from './chunk-S7QZUBXM.js';
2
2
  import { whenSallaLoaded } from './chunk-GYXUYHKO.js';
3
3
  import { getTwilightContext } from './chunk-7VNVCHID.js';
4
4
 
@@ -36,5 +36,5 @@ function dispatchProductViewed(product) {
36
36
  }
37
37
 
38
38
  export { dispatchProductViewed, dispatchRouteChanged };
39
- //# sourceMappingURL=chunk-IGGIH6GL.js.map
40
- //# sourceMappingURL=chunk-IGGIH6GL.js.map
39
+ //# sourceMappingURL=chunk-6GDNC6DS.js.map
40
+ //# sourceMappingURL=chunk-6GDNC6DS.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils/sdk-events.ts"],"names":[],"mappings":";;;;;AA6BO,SAAS,oBAAA,GAA6B;AAC3C,EAAA,IAAI,OAAO,WAAW,WAAA,EAAa;AAEnC,EAAA,MAAM,QAAQ,MAAA,CAAO,KAAA;AACrB,EAAA,IAAI,CAAC,KAAA,EAAO,KAAA,EAAO,QAAA,EAAU;AAE7B,EAAA,MAAM,MAAM,kBAAA,EAAmB;AAC/B,EAAA,KAAA,CAAM,MAAM,QAAA,CAAS,gBAAA,EAAkB,GAAA,CAAI,IAAA,IAAQ,EAAE,CAAA;AACvD;AAMO,SAAS,sBAAsB,OAAA,EAAwB;AAC5D,EAAA,IAAI,OAAO,WAAW,WAAA,EAAa;AACnC,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAA,IAAK,CAAA;AACvC,EAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,KAAA,EAAO,GAAA,IAAO,EAAA;AACpC,EAAA,MAAM,OAAA,GAAU;AAAA,IACd,IAAI,OAAA,CAAQ,EAAA;AAAA,IACZ,MAAM,OAAA,CAAQ,IAAA;AAAA,IACd,UAAA,EAAY,OAAA,CAAQ,QAAA,GAAW,CAAC,EAAE,EAAA,EAAI,OAAA,CAAQ,QAAA,CAAS,EAAA,EAAI,MAAM,OAAA,CAAQ,QAAA,CAAS,IAAA,EAAM,IAAI,EAAC;AAAA,IAC7F,QAAA,EAAU,OAAA,CAAQ,QAAA,EAAU,IAAA,IAAQ,EAAA;AAAA,IACpC,KAAA;AAAA,IACA,QAAA,EAAU,CAAA;AAAA,IACV,OAAA,EAAS,EAAA;AAAA,IACT,KAAA,EAAO,OAAA,CAAQ,KAAA,EAAO,IAAA,IAAQ,EAAA;AAAA,IAC9B,KAAA;AAAA,IACA,QAAA,EAAU,iBAAA,CAAkB,OAAA,CAAQ,QAAQ,CAAA;AAAA,IAC5C,GAAA,EAAK,QAAQ,GAAA,IAAO,EAAA;AAAA,IACpB,KAAA,EAAO,KAAA;AAAA,IACP,KAAK,OAAA,CAAQ,GAAA;AAAA,IACb,SAAA,EAAW;AAAA,GACb;AAEA,EAAA,eAAA;AAAA,IACE,CAAC,GAAA,KAAQ,KAAK,GAAA,CAAI,SAAQ,CAAE,IAAA,CAAK,MAAM,GAAA,CAAI,MAAM,QAAA,CAAS,gBAAA,EAAkB,CAAC,OAAO,CAAC,CAAC;AAAA,GACxF;AACF","file":"chunk-IGGIH6GL.js","sourcesContent":["import { getTwilightContext } from '../twilight/context';\nimport type { PageContext } from '../twilight/context';\nimport type { Product } from '../types';\nimport { getActiveCurrency } from '../api/client';\nimport { whenSallaLoaded } from './sdk-helpers';\n\n/**\n * Payload dispatched via `salla.event.dispatch('route::changed', payload)`\n * after each client-side navigation completes.\n *\n * The page config fields are spread at root level. When the matched route\n * has no page data (e.g., 404, error boundary), an empty object is dispatched.\n *\n * @example\n * ```ts\n * salla.event.on('route::changed', (page: RouteChangedEvent) => {\n * console.log(page.slug, page.title, page.id);\n * });\n * ```\n */\nexport type RouteChangedEvent = PageContext;\n\n/**\n * Dispatch the `route::changed` Salla SDK event with the current page config.\n *\n * Framework-agnostic — reads from the twilight context store which is\n * populated by whichever framework adapter is active (TanStack, Next.js, etc.).\n * Each adapter should call this after navigation resolves.\n */\nexport function dispatchRouteChanged(): void {\n if (typeof window === 'undefined') return;\n\n const salla = window.salla;\n if (!salla?.event?.dispatch) return;\n\n const ctx = getTwilightContext();\n salla.event.dispatch('route::changed', ctx.page ?? {});\n}\n\n/**\n * Dispatch `Product Viewed`, which Twig's product page hands the SDK through `salla.init`'s\n * `events`: store analytics, pixels and apps that remember viewed products listen for it.\n */\nexport function dispatchProductViewed(product: Product): void {\n if (typeof window === 'undefined') return;\n const price = Number(product.price) || 0;\n const image = product.image?.url ?? '';\n const payload = {\n id: product.id,\n name: product.name,\n categories: product.category ? [{ id: product.category.id, name: product.category.name }] : [],\n category: product.category?.name ?? '',\n price,\n quantity: 1,\n variant: '',\n brand: product.brand?.name ?? '',\n image,\n currency: getActiveCurrency(product.currency),\n sku: product.sku ?? '',\n value: price,\n url: product.url,\n image_url: image,\n };\n // After init: analytics drops events until `salla.init` has merged the store's `jitsu` list.\n whenSallaLoaded(\n (sdk) => void sdk.onReady().then(() => sdk.event.dispatch('Product Viewed', [payload]))\n );\n}\n"]}
1
+ {"version":3,"sources":["../src/utils/sdk-events.ts"],"names":[],"mappings":";;;;;AA6BO,SAAS,oBAAA,GAA6B;AAC3C,EAAA,IAAI,OAAO,WAAW,WAAA,EAAa;AAEnC,EAAA,MAAM,QAAQ,MAAA,CAAO,KAAA;AACrB,EAAA,IAAI,CAAC,KAAA,EAAO,KAAA,EAAO,QAAA,EAAU;AAE7B,EAAA,MAAM,MAAM,kBAAA,EAAmB;AAC/B,EAAA,KAAA,CAAM,MAAM,QAAA,CAAS,gBAAA,EAAkB,GAAA,CAAI,IAAA,IAAQ,EAAE,CAAA;AACvD;AAMO,SAAS,sBAAsB,OAAA,EAAwB;AAC5D,EAAA,IAAI,OAAO,WAAW,WAAA,EAAa;AACnC,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAA,IAAK,CAAA;AACvC,EAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,KAAA,EAAO,GAAA,IAAO,EAAA;AACpC,EAAA,MAAM,OAAA,GAAU;AAAA,IACd,IAAI,OAAA,CAAQ,EAAA;AAAA,IACZ,MAAM,OAAA,CAAQ,IAAA;AAAA,IACd,UAAA,EAAY,OAAA,CAAQ,QAAA,GAAW,CAAC,EAAE,EAAA,EAAI,OAAA,CAAQ,QAAA,CAAS,EAAA,EAAI,MAAM,OAAA,CAAQ,QAAA,CAAS,IAAA,EAAM,IAAI,EAAC;AAAA,IAC7F,QAAA,EAAU,OAAA,CAAQ,QAAA,EAAU,IAAA,IAAQ,EAAA;AAAA,IACpC,KAAA;AAAA,IACA,QAAA,EAAU,CAAA;AAAA,IACV,OAAA,EAAS,EAAA;AAAA,IACT,KAAA,EAAO,OAAA,CAAQ,KAAA,EAAO,IAAA,IAAQ,EAAA;AAAA,IAC9B,KAAA;AAAA,IACA,QAAA,EAAU,iBAAA,CAAkB,OAAA,CAAQ,QAAQ,CAAA;AAAA,IAC5C,GAAA,EAAK,QAAQ,GAAA,IAAO,EAAA;AAAA,IACpB,KAAA,EAAO,KAAA;AAAA,IACP,KAAK,OAAA,CAAQ,GAAA;AAAA,IACb,SAAA,EAAW;AAAA,GACb;AAEA,EAAA,eAAA;AAAA,IACE,CAAC,GAAA,KAAQ,KAAK,GAAA,CAAI,SAAQ,CAAE,IAAA,CAAK,MAAM,GAAA,CAAI,MAAM,QAAA,CAAS,gBAAA,EAAkB,CAAC,OAAO,CAAC,CAAC;AAAA,GACxF;AACF","file":"chunk-6GDNC6DS.js","sourcesContent":["import { getTwilightContext } from '../twilight/context';\nimport type { PageContext } from '../twilight/context';\nimport type { Product } from '../types';\nimport { getActiveCurrency } from '../api/client';\nimport { whenSallaLoaded } from './sdk-helpers';\n\n/**\n * Payload dispatched via `salla.event.dispatch('route::changed', payload)`\n * after each client-side navigation completes.\n *\n * The page config fields are spread at root level. When the matched route\n * has no page data (e.g., 404, error boundary), an empty object is dispatched.\n *\n * @example\n * ```ts\n * salla.event.on('route::changed', (page: RouteChangedEvent) => {\n * console.log(page.slug, page.title, page.id);\n * });\n * ```\n */\nexport type RouteChangedEvent = PageContext;\n\n/**\n * Dispatch the `route::changed` Salla SDK event with the current page config.\n *\n * Framework-agnostic — reads from the twilight context store which is\n * populated by whichever framework adapter is active (TanStack, Next.js, etc.).\n * Each adapter should call this after navigation resolves.\n */\nexport function dispatchRouteChanged(): void {\n if (typeof window === 'undefined') return;\n\n const salla = window.salla;\n if (!salla?.event?.dispatch) return;\n\n const ctx = getTwilightContext();\n salla.event.dispatch('route::changed', ctx.page ?? {});\n}\n\n/**\n * Dispatch `Product Viewed`, which Twig's product page hands the SDK through `salla.init`'s\n * `events`: store analytics, pixels and apps that remember viewed products listen for it.\n */\nexport function dispatchProductViewed(product: Product): void {\n if (typeof window === 'undefined') return;\n const price = Number(product.price) || 0;\n const image = product.image?.url ?? '';\n const payload = {\n id: product.id,\n name: product.name,\n categories: product.category ? [{ id: product.category.id, name: product.category.name }] : [],\n category: product.category?.name ?? '',\n price,\n quantity: 1,\n variant: '',\n brand: product.brand?.name ?? '',\n image,\n currency: getActiveCurrency(product.currency),\n sku: product.sku ?? '',\n value: price,\n url: product.url,\n image_url: image,\n };\n // After init: analytics drops events until `salla.init` has merged the store's `jitsu` list.\n whenSallaLoaded(\n (sdk) => void sdk.onReady().then(() => sdk.event.dispatch('Product Viewed', [payload]))\n );\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { api } from './chunk-5LP2K2J7.js';
1
+ import { api } from './chunk-S7QZUBXM.js';
2
2
  import { queryOptions } from '@tanstack/react-query';
3
3
 
4
4
  var user = {
@@ -19,5 +19,5 @@ var user = {
19
19
  };
20
20
 
21
21
  export { user };
22
- //# sourceMappingURL=chunk-NHJ5U6WK.js.map
23
- //# sourceMappingURL=chunk-NHJ5U6WK.js.map
22
+ //# sourceMappingURL=chunk-6NT6RC2H.js.map
23
+ //# sourceMappingURL=chunk-6NT6RC2H.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/api/user.ts"],"names":[],"mappings":";;;AAIO,IAAM,IAAA,GAAO;AAAA,EAClB,KAAK,YAAkC;AACrC,IAAA,IAAI;AACF,MAAA,OAAO,MAAM,GAAA,CACV,GAAA,CAAI,WAAW,CAAA,CACf,MAAmC,CACnC,IAAA,CAAK,CAAC,CAAA,MAAO,EAAE,GAAG,CAAA,CAAE,IAAA,EAAM,IAAA,EAAM,QAAgB,CAAE,CAAA;AAAA,IACvD,SAAS,KAAA,EAAO;AACd,MAAA,OAAA,CAAQ,KAAA,CAAM,sBAAsB,KAAK,CAAA;AACzC,MAAA,OAAO,IAAA;AAAA,IACT;AAAA,EACF,CAAA;AAAA,EAEA,OAAA,EAAS;AAAA,IACP,OAAA,EAAS,MACP,YAAA,CAA0B;AAAA,MACxB,QAAA,EAAU,CAAC,MAAA,EAAQ,SAAS,CAAA;AAAA,MAC5B,SAAS,IAAA,CAAK;AAAA,KACf;AAAA;AAEP","file":"chunk-NHJ5U6WK.js","sourcesContent":["import { queryOptions } from '@tanstack/react-query';\nimport { api } from './client';\nimport type { User } from '../types';\n\nexport const user = {\n get: async (): Promise<User | null> => {\n try {\n return await api\n .get('auth/user')\n .json<{ data: Omit<User, 'type'> }>()\n .then((r) => ({ ...r.data, type: 'user' as const }));\n } catch (error) {\n console.debug('[user.get] Failed:', error);\n return null;\n }\n },\n\n queries: {\n current: () =>\n queryOptions<User | null>({\n queryKey: ['user', 'current'],\n queryFn: user.get,\n }),\n },\n};\n"]}
1
+ {"version":3,"sources":["../src/api/user.ts"],"names":[],"mappings":";;;AAIO,IAAM,IAAA,GAAO;AAAA,EAClB,KAAK,YAAkC;AACrC,IAAA,IAAI;AACF,MAAA,OAAO,MAAM,GAAA,CACV,GAAA,CAAI,WAAW,CAAA,CACf,MAAmC,CACnC,IAAA,CAAK,CAAC,CAAA,MAAO,EAAE,GAAG,CAAA,CAAE,IAAA,EAAM,IAAA,EAAM,QAAgB,CAAE,CAAA;AAAA,IACvD,SAAS,KAAA,EAAO;AACd,MAAA,OAAA,CAAQ,KAAA,CAAM,sBAAsB,KAAK,CAAA;AACzC,MAAA,OAAO,IAAA;AAAA,IACT;AAAA,EACF,CAAA;AAAA,EAEA,OAAA,EAAS;AAAA,IACP,OAAA,EAAS,MACP,YAAA,CAA0B;AAAA,MACxB,QAAA,EAAU,CAAC,MAAA,EAAQ,SAAS,CAAA;AAAA,MAC5B,SAAS,IAAA,CAAK;AAAA,KACf;AAAA;AAEP","file":"chunk-6NT6RC2H.js","sourcesContent":["import { queryOptions } from '@tanstack/react-query';\nimport { api } from './client';\nimport type { User } from '../types';\n\nexport const user = {\n get: async (): Promise<User | null> => {\n try {\n return await api\n .get('auth/user')\n .json<{ data: Omit<User, 'type'> }>()\n .then((r) => ({ ...r.data, type: 'user' as const }));\n } catch (error) {\n console.debug('[user.get] Failed:', error);\n return null;\n }\n },\n\n queries: {\n current: () =>\n queryOptions<User | null>({\n queryKey: ['user', 'current'],\n queryFn: user.get,\n }),\n },\n};\n"]}
@@ -1,4 +1,4 @@
1
- import { api } from './chunk-5LP2K2J7.js';
1
+ import { api } from './chunk-S7QZUBXM.js';
2
2
 
3
3
  // src/api/wallet.ts
4
4
  var wallet = {
@@ -20,5 +20,5 @@ var wallet = {
20
20
  };
21
21
 
22
22
  export { wallet };
23
- //# sourceMappingURL=chunk-WFSKX5AI.js.map
24
- //# sourceMappingURL=chunk-WFSKX5AI.js.map
23
+ //# sourceMappingURL=chunk-7SBSV5DD.js.map
24
+ //# sourceMappingURL=chunk-7SBSV5DD.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/api/wallet.ts"],"names":[],"mappings":";;;AAgCO,IAAM,MAAA,GAAS;AAAA,EACpB,IAAA,EAAM,OAAO,MAAA,GAA2B,EAAC,KAAiC;AACxE,IAAA,MAAM,EAAE,IAAA,GAAO,CAAA,EAAG,OAAA,GAAU,EAAA,EAAI,QAAO,GAAI,MAAA;AAE3C,IAAA,MAAM,YAAA,GAAe,IAAI,eAAA,EAAgB;AACzC,IAAA,YAAA,CAAa,GAAA,CAAI,MAAA,EAAQ,MAAA,CAAO,IAAI,CAAC,CAAA;AACrC,IAAA,YAAA,CAAa,GAAA,CAAI,UAAA,EAAY,MAAA,CAAO,OAAO,CAAC,CAAA;AAE5C,IAAA,MAAM,UAAmC,EAAC;AAC1C,IAAA,IAAI,MAAA,UAAgB,MAAA,GAAS,MAAA;AAE7B,IAAA,MAAM,QAAA,GAAW,MAAM,GAAA,CACpB,GAAA,CAAI,CAAA,eAAA,EAAkB,YAAA,CAAa,QAAA,EAAU,CAAA,CAAA,EAAI,OAAc,CAAA,CAC/D,IAAA,EAAsE;AAEzE,IAAA,MAAM,YAAA,GAAe,SAAS,IAAA,CAAK,YAAA;AAEnC,IAAA,OAAO;AAAA,MACL,KAAA,EAAO,YAAA,CAAa,IAAA,IAAQ,EAAC;AAAA,MAC7B,MAAM,YAAA,CAAa,aAAA;AAAA,MACnB,OAAA,EAAS,SAAS,IAAA,CAAK;AAAA,KACzB;AAAA,EACF;AACF","file":"chunk-WFSKX5AI.js","sourcesContent":["import { api } from './client';\n\nexport interface TransactionItem {\n id: number;\n order_id: number;\n transaction_type: string;\n action_type: string;\n type: string;\n title: string;\n description: string;\n amount: number;\n created_at: number;\n expired_at: number;\n}\n\nexport interface WalletListParams {\n page?: number;\n perPage?: number;\n signal?: AbortSignal;\n}\n\nexport interface WalletListResponse {\n data: TransactionItem[];\n next_page_url: string | null;\n}\n\nexport interface WalletListResult {\n items: TransactionItem[];\n next: string | null;\n balance: number;\n}\n\nexport const wallet = {\n list: async (params: WalletListParams = {}): Promise<WalletListResult> => {\n const { page = 1, perPage = 10, signal } = params;\n\n const searchParams = new URLSearchParams();\n searchParams.set('page', String(page));\n searchParams.set('per_page', String(perPage));\n\n const options: Record<string, unknown> = {};\n if (signal) options.signal = signal;\n\n const response = await api\n .get(`balance/wallet?${searchParams.toString()}`, options as any)\n .json<{ data: { transactions: WalletListResponse; balance: number } }>();\n\n const transactions = response.data.transactions;\n\n return {\n items: transactions.data ?? [],\n next: transactions.next_page_url,\n balance: response.data.balance,\n };\n },\n};\n"]}
1
+ {"version":3,"sources":["../src/api/wallet.ts"],"names":[],"mappings":";;;AAgCO,IAAM,MAAA,GAAS;AAAA,EACpB,IAAA,EAAM,OAAO,MAAA,GAA2B,EAAC,KAAiC;AACxE,IAAA,MAAM,EAAE,IAAA,GAAO,CAAA,EAAG,OAAA,GAAU,EAAA,EAAI,QAAO,GAAI,MAAA;AAE3C,IAAA,MAAM,YAAA,GAAe,IAAI,eAAA,EAAgB;AACzC,IAAA,YAAA,CAAa,GAAA,CAAI,MAAA,EAAQ,MAAA,CAAO,IAAI,CAAC,CAAA;AACrC,IAAA,YAAA,CAAa,GAAA,CAAI,UAAA,EAAY,MAAA,CAAO,OAAO,CAAC,CAAA;AAE5C,IAAA,MAAM,UAAmC,EAAC;AAC1C,IAAA,IAAI,MAAA,UAAgB,MAAA,GAAS,MAAA;AAE7B,IAAA,MAAM,QAAA,GAAW,MAAM,GAAA,CACpB,GAAA,CAAI,CAAA,eAAA,EAAkB,YAAA,CAAa,QAAA,EAAU,CAAA,CAAA,EAAI,OAAc,CAAA,CAC/D,IAAA,EAAsE;AAEzE,IAAA,MAAM,YAAA,GAAe,SAAS,IAAA,CAAK,YAAA;AAEnC,IAAA,OAAO;AAAA,MACL,KAAA,EAAO,YAAA,CAAa,IAAA,IAAQ,EAAC;AAAA,MAC7B,MAAM,YAAA,CAAa,aAAA;AAAA,MACnB,OAAA,EAAS,SAAS,IAAA,CAAK;AAAA,KACzB;AAAA,EACF;AACF","file":"chunk-7SBSV5DD.js","sourcesContent":["import { api } from './client';\n\nexport interface TransactionItem {\n id: number;\n order_id: number;\n transaction_type: string;\n action_type: string;\n type: string;\n title: string;\n description: string;\n amount: number;\n created_at: number;\n expired_at: number;\n}\n\nexport interface WalletListParams {\n page?: number;\n perPage?: number;\n signal?: AbortSignal;\n}\n\nexport interface WalletListResponse {\n data: TransactionItem[];\n next_page_url: string | null;\n}\n\nexport interface WalletListResult {\n items: TransactionItem[];\n next: string | null;\n balance: number;\n}\n\nexport const wallet = {\n list: async (params: WalletListParams = {}): Promise<WalletListResult> => {\n const { page = 1, perPage = 10, signal } = params;\n\n const searchParams = new URLSearchParams();\n searchParams.set('page', String(page));\n searchParams.set('per_page', String(perPage));\n\n const options: Record<string, unknown> = {};\n if (signal) options.signal = signal;\n\n const response = await api\n .get(`balance/wallet?${searchParams.toString()}`, options as any)\n .json<{ data: { transactions: WalletListResponse; balance: number } }>();\n\n const transactions = response.data.transactions;\n\n return {\n items: transactions.data ?? [],\n next: transactions.next_page_url,\n balance: response.data.balance,\n };\n },\n};\n"]}
@@ -1,5 +1,5 @@
1
- import { orThrow } from './chunk-GLE6TNJ3.js';
2
- import { getActiveScope, api } from './chunk-5LP2K2J7.js';
1
+ import { orThrow } from './chunk-HZIQK63A.js';
2
+ import { getActiveScope, api } from './chunk-S7QZUBXM.js';
3
3
  import { getTwilightContext } from './chunk-7VNVCHID.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-TNUK62YF.js.map
198
- //# sourceMappingURL=chunk-TNUK62YF.js.map
197
+ //# sourceMappingURL=chunk-CGABIBZZ.js.map
198
+ //# sourceMappingURL=chunk-CGABIBZZ.js.map