@salla.sa/twilight-theme-engine 1.0.94 → 1.0.96

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 (353) hide show
  1. package/dist/{AddToCartForm-MASXVJOI.js → AddToCartForm-DASRXMY7.js} +3 -3
  2. package/dist/{AddToCartForm-MASXVJOI.js.map → AddToCartForm-DASRXMY7.js.map} +1 -1
  3. package/dist/{BlogAuthorPage-KRT7MRTC.js → BlogAuthorPage-WFZGYSUB.js} +26 -24
  4. package/dist/BlogAuthorPage-WFZGYSUB.js.map +1 -0
  5. package/dist/{BlogCategoryPage-OP3ETAMT.js → BlogCategoryPage-23PFOVVP.js} +26 -24
  6. package/dist/BlogCategoryPage-23PFOVVP.js.map +1 -0
  7. package/dist/{BlogPage-RGAQVUDI.js → BlogPage-4RFI56TW.js} +24 -22
  8. package/dist/BlogPage-4RFI56TW.js.map +1 -0
  9. package/dist/{BlogSinglePage-VG4UXBTL.js → BlogSinglePage-KMGBQUG5.js} +24 -22
  10. package/dist/BlogSinglePage-KMGBQUG5.js.map +1 -0
  11. package/dist/{BlogTagPage-G4IVHJD5.js → BlogTagPage-ZPQJKPBO.js} +26 -24
  12. package/dist/BlogTagPage-ZPQJKPBO.js.map +1 -0
  13. package/dist/{BrandsPage-2JMPPOOU.js → BrandsPage-FIHOZYMB.js} +25 -23
  14. package/dist/BrandsPage-FIHOZYMB.js.map +1 -0
  15. package/dist/{Breadcrumb-I3ZOGG2Y.js → Breadcrumb-2IXFQL6L.js} +24 -22
  16. package/dist/Breadcrumb-2IXFQL6L.js.map +1 -0
  17. package/dist/{CartItem-YTPYETW6.js → CartItem-GRFH5BED.js} +24 -22
  18. package/dist/CartItem-GRFH5BED.js.map +1 -0
  19. package/dist/{CartSummary-DND7BO26.js → CartSummary-IOCZJL26.js} +24 -22
  20. package/dist/CartSummary-IOCZJL26.js.map +1 -0
  21. package/dist/{Copyright-RWML3BQV.js → Copyright-MDKYCKML.js} +3 -3
  22. package/dist/{Copyright-RWML3BQV.js.map → Copyright-MDKYCKML.js.map} +1 -1
  23. package/dist/{CustomerLayout-HCYVBODI.js → CustomerLayout-4737YCAK.js} +24 -22
  24. package/dist/CustomerLayout-4737YCAK.js.map +1 -0
  25. package/dist/{Footer-3GEKWEQD.js → Footer-2F652QDB.js} +4 -4
  26. package/dist/{Footer-3GEKWEQD.js.map → Footer-2F652QDB.js.map} +1 -1
  27. package/dist/Header-4OATF4LX.js +22 -0
  28. package/dist/{Header-QG4UO3MF.js.map → Header-4OATF4LX.js.map} +1 -1
  29. package/dist/{LoyaltyPage-ZMFYQMQY.js → LoyaltyPage-POFUTIPB.js} +24 -22
  30. package/dist/LoyaltyPage-POFUTIPB.js.map +1 -0
  31. package/dist/{LoyaltyPointsPage-5PB6IFLY.js → LoyaltyPointsPage-L4S4NZA2.js} +8 -7
  32. package/dist/LoyaltyPointsPage-L4S4NZA2.js.map +1 -0
  33. package/dist/{MainMenu-SAUMNMBF.js → MainMenu-ROGX37TG.js} +7 -6
  34. package/dist/MainMenu-ROGX37TG.js.map +1 -0
  35. package/dist/{MasterLayout-TY223YR7.js → MasterLayout-PGL5YU2B.js} +24 -22
  36. package/dist/{MasterLayout-TY223YR7.js.map → MasterLayout-PGL5YU2B.js.map} +1 -1
  37. package/dist/{MobileMenu-2WOWOFQB.js → MobileMenu-VGXWJHEF.js} +25 -23
  38. package/dist/MobileMenu-VGXWJHEF.js.map +1 -0
  39. package/dist/{NotificationsPage-6FX4SOZU.js → NotificationsPage-PZAEKKJO.js} +24 -22
  40. package/dist/NotificationsPage-PZAEKKJO.js.map +1 -0
  41. package/dist/{OrderSinglePage-RUMSJIFD.js → OrderSinglePage-KTKLXTUX.js} +25 -23
  42. package/dist/OrderSinglePage-KTKLXTUX.js.map +1 -0
  43. package/dist/{OrdersPage-B4Q4QIEM.js → OrdersPage-BY6LYV5M.js} +24 -22
  44. package/dist/OrdersPage-BY6LYV5M.js.map +1 -0
  45. package/dist/{PageSingle-F4TDNKUM.js → PageSingle-CJRT3HJZ.js} +6 -5
  46. package/dist/PageSingle-CJRT3HJZ.js.map +1 -0
  47. package/dist/{ProductDetails-BNVVUDBH.js → ProductDetails-O2VJVIZC.js} +7 -6
  48. package/dist/ProductDetails-O2VJVIZC.js.map +1 -0
  49. package/dist/{ProfilePage-OJSAXSC2.js → ProfilePage-TB7PBODI.js} +24 -22
  50. package/dist/ProfilePage-TB7PBODI.js.map +1 -0
  51. package/dist/{RenderWhenVisible-F44J5MMG.js → RenderWhenVisible-KWAXEJOJ.js} +8 -5
  52. package/dist/RenderWhenVisible-KWAXEJOJ.js.map +1 -0
  53. package/dist/{ReviewsPage-3IJKJKTY.js → ReviewsPage-5KGCKLFR.js} +3 -3
  54. package/dist/{ReviewsPage-3IJKJKTY.js.map → ReviewsPage-5KGCKLFR.js.map} +1 -1
  55. package/dist/{SeoCartWidget-4PN2DW54.js → SeoCartWidget-6BU7WCTP.js} +24 -22
  56. package/dist/SeoCartWidget-6BU7WCTP.js.map +1 -0
  57. package/dist/{SettingsPage-BCRNV4GU.js → SettingsPage-G55AM2KS.js} +24 -22
  58. package/dist/SettingsPage-G55AM2KS.js.map +1 -0
  59. package/dist/{StoreClosedNotification-IRUTRLIH.js → StoreClosedNotification-C3BBFGAA.js} +25 -23
  60. package/dist/{StoreClosedNotification-IRUTRLIH.js.map → StoreClosedNotification-C3BBFGAA.js.map} +1 -1
  61. package/dist/{TestimonialsPage-YU4PLOLR.js → TestimonialsPage-EA4PSO7E.js} +6 -5
  62. package/dist/TestimonialsPage-EA4PSO7E.js.map +1 -0
  63. package/dist/{ThankYouPage-MUDELEIQ.js → ThankYouPage-R2OEK7ZZ.js} +24 -22
  64. package/dist/ThankYouPage-R2OEK7ZZ.js.map +1 -0
  65. package/dist/{WalletPage-2I4KTR5E.js → WalletPage-MEWHIHUE.js} +25 -23
  66. package/dist/WalletPage-MEWHIHUE.js.map +1 -0
  67. package/dist/{WishlistPage-7AYL3RUD.js → WishlistPage-YFKG7CXU.js} +26 -24
  68. package/dist/WishlistPage-YFKG7CXU.js.map +1 -0
  69. package/dist/ambient/virtual-modules.d.ts +43 -1
  70. package/dist/api/advertisement.js +4 -3
  71. package/dist/api/apps.js +4 -3
  72. package/dist/api/blog.js +6 -5
  73. package/dist/api/brands.js +6 -5
  74. package/dist/api/cart.js +6 -5
  75. package/dist/api/category.js +6 -5
  76. package/dist/api/client.js +3 -2
  77. package/dist/api/home.js +4 -3
  78. package/dist/api/loyalty.js +6 -5
  79. package/dist/api/menu.js +4 -3
  80. package/dist/api/notification.js +4 -3
  81. package/dist/api/order.js +6 -5
  82. package/dist/api/page.js +6 -5
  83. package/dist/api/product.js +6 -5
  84. package/dist/api/profile.js +3 -2
  85. package/dist/api/profile.js.map +1 -1
  86. package/dist/api/store.js +4 -3
  87. package/dist/api/translations.js +4 -3
  88. package/dist/api/user.js +4 -3
  89. package/dist/api/wallet.js +4 -3
  90. package/dist/api/wishlist.js +7 -6
  91. package/dist/{chunk-LA7KZ2XY.js → chunk-2D5TFSVG.js} +8 -8
  92. package/dist/{chunk-LA7KZ2XY.js.map → chunk-2D5TFSVG.js.map} +1 -1
  93. package/dist/{chunk-HQAFPDJK.js → chunk-2FDLEB5J.js} +3 -3
  94. package/dist/{chunk-HQAFPDJK.js.map → chunk-2FDLEB5J.js.map} +1 -1
  95. package/dist/chunk-2FKZAAV7.js +90 -0
  96. package/dist/chunk-2FKZAAV7.js.map +1 -0
  97. package/dist/{chunk-YDFOJBEY.js → chunk-3GW3VFR6.js} +3 -3
  98. package/dist/{chunk-YDFOJBEY.js.map → chunk-3GW3VFR6.js.map} +1 -1
  99. package/dist/{chunk-CEYT3JER.js → chunk-56T47K7P.js} +4 -4
  100. package/dist/{chunk-CEYT3JER.js.map → chunk-56T47K7P.js.map} +1 -1
  101. package/dist/{chunk-LPQ5FUMJ.js → chunk-5SDCUGYR.js} +4 -4
  102. package/dist/{chunk-LPQ5FUMJ.js.map → chunk-5SDCUGYR.js.map} +1 -1
  103. package/dist/{chunk-QGOPTVV5.js → chunk-6EQ7G3SZ.js} +4 -3
  104. package/dist/chunk-6EQ7G3SZ.js.map +1 -0
  105. package/dist/{chunk-H7CVJFTK.js → chunk-6RHU4TEF.js} +7 -7
  106. package/dist/{chunk-H7CVJFTK.js.map → chunk-6RHU4TEF.js.map} +1 -1
  107. package/dist/{chunk-FZYR4BA2.js → chunk-7WTUA4WY.js} +3 -3
  108. package/dist/{chunk-FZYR4BA2.js.map → chunk-7WTUA4WY.js.map} +1 -1
  109. package/dist/{chunk-3PXONLUK.js → chunk-BH7YNCYB.js} +3 -3
  110. package/dist/{chunk-3PXONLUK.js.map → chunk-BH7YNCYB.js.map} +1 -1
  111. package/dist/{chunk-DBW7XXNE.js → chunk-BPL5H33B.js} +4 -4
  112. package/dist/{chunk-DBW7XXNE.js.map → chunk-BPL5H33B.js.map} +1 -1
  113. package/dist/{chunk-66K5P5ZX.js → chunk-CNUBL24W.js} +3 -3
  114. package/dist/{chunk-66K5P5ZX.js.map → chunk-CNUBL24W.js.map} +1 -1
  115. package/dist/chunk-COJH52VR.js +443 -0
  116. package/dist/chunk-COJH52VR.js.map +1 -0
  117. package/dist/{chunk-6OOTDFC7.js → chunk-D56TVNOG.js} +3 -3
  118. package/dist/{chunk-6OOTDFC7.js.map → chunk-D56TVNOG.js.map} +1 -1
  119. package/dist/{chunk-Y7XVWQXG.js → chunk-DNPQ2JBM.js} +4 -4
  120. package/dist/{chunk-Y7XVWQXG.js.map → chunk-DNPQ2JBM.js.map} +1 -1
  121. package/dist/{chunk-JJARU7YP.js → chunk-EWLVLDRP.js} +3 -3
  122. package/dist/{chunk-JJARU7YP.js.map → chunk-EWLVLDRP.js.map} +1 -1
  123. package/dist/{chunk-Y357MBJI.js → chunk-FNHZEBA5.js} +9 -8
  124. package/dist/chunk-FNHZEBA5.js.map +1 -0
  125. package/dist/{chunk-HSWRYXC7.js → chunk-FO4WVGUQ.js} +3 -88
  126. package/dist/chunk-FO4WVGUQ.js.map +1 -0
  127. package/dist/{chunk-BNI6SKFL.js → chunk-G3UTLICK.js} +4 -4
  128. package/dist/{chunk-BNI6SKFL.js.map → chunk-G3UTLICK.js.map} +1 -1
  129. package/dist/{chunk-C4RXPVDF.js → chunk-GMXI6V2D.js} +6 -5
  130. package/dist/chunk-GMXI6V2D.js.map +1 -0
  131. package/dist/{chunk-RKQH63G2.js → chunk-GXHJXZBG.js} +4 -4
  132. package/dist/{chunk-RKQH63G2.js.map → chunk-GXHJXZBG.js.map} +1 -1
  133. package/dist/{chunk-43D2CG4F.js → chunk-IBSQO6LW.js} +4 -4
  134. package/dist/{chunk-43D2CG4F.js.map → chunk-IBSQO6LW.js.map} +1 -1
  135. package/dist/{chunk-ZVZGLEZ6.js → chunk-IU4KTCS3.js} +3 -3
  136. package/dist/{chunk-ZVZGLEZ6.js.map → chunk-IU4KTCS3.js.map} +1 -1
  137. package/dist/{chunk-ZFNLX3F7.js → chunk-J3G4ZD76.js} +13 -12
  138. package/dist/chunk-J3G4ZD76.js.map +1 -0
  139. package/dist/{chunk-ENJ3CM5M.js → chunk-J5X4LXNM.js} +3 -3
  140. package/dist/{chunk-ENJ3CM5M.js.map → chunk-J5X4LXNM.js.map} +1 -1
  141. package/dist/{chunk-TJF6YZ5I.js → chunk-JKBLG344.js} +8 -7
  142. package/dist/chunk-JKBLG344.js.map +1 -0
  143. package/dist/{chunk-RPDMNNRW.js → chunk-JVIPOD6M.js} +20 -19
  144. package/dist/chunk-JVIPOD6M.js.map +1 -0
  145. package/dist/{chunk-4WAUITU2.js → chunk-KNIGLCRV.js} +3 -3
  146. package/dist/{chunk-4WAUITU2.js.map → chunk-KNIGLCRV.js.map} +1 -1
  147. package/dist/{chunk-OMKLPCBA.js → chunk-KQW6I5CD.js} +4 -4
  148. package/dist/{chunk-OMKLPCBA.js.map → chunk-KQW6I5CD.js.map} +1 -1
  149. package/dist/{chunk-HR3QJ3LW.js → chunk-LXNS6CMT.js} +4 -4
  150. package/dist/{chunk-HR3QJ3LW.js.map → chunk-LXNS6CMT.js.map} +1 -1
  151. package/dist/chunk-MGDCJQ5P.js +14 -0
  152. package/dist/{chunk-KZM7HXJ3.js.map → chunk-MGDCJQ5P.js.map} +1 -1
  153. package/dist/chunk-N45X7D55.js +63 -0
  154. package/dist/chunk-N45X7D55.js.map +1 -0
  155. package/dist/{chunk-OH2L4U2C.js → chunk-NZRJOAA7.js} +3 -3
  156. package/dist/{chunk-OH2L4U2C.js.map → chunk-NZRJOAA7.js.map} +1 -1
  157. package/dist/{chunk-TEOVJ6WU.js → chunk-O7B5JL6H.js} +4 -4
  158. package/dist/{chunk-TEOVJ6WU.js.map → chunk-O7B5JL6H.js.map} +1 -1
  159. package/dist/{chunk-UURVAJ42.js → chunk-OZP2FID7.js} +4 -4
  160. package/dist/{chunk-UURVAJ42.js.map → chunk-OZP2FID7.js.map} +1 -1
  161. package/dist/{chunk-HCA2TE4G.js → chunk-PGUKRWOY.js} +5 -5
  162. package/dist/{chunk-HCA2TE4G.js.map → chunk-PGUKRWOY.js.map} +1 -1
  163. package/dist/{chunk-3MIFT4VQ.js → chunk-Q62YEBIA.js} +4 -4
  164. package/dist/{chunk-3MIFT4VQ.js.map → chunk-Q62YEBIA.js.map} +1 -1
  165. package/dist/{chunk-6DMNJPLW.js → chunk-QS4EDTEX.js} +3 -3
  166. package/dist/{chunk-6DMNJPLW.js.map → chunk-QS4EDTEX.js.map} +1 -1
  167. package/dist/{chunk-SAGXF3MU.js → chunk-QZEQOVA5.js} +3 -3
  168. package/dist/{chunk-SAGXF3MU.js.map → chunk-QZEQOVA5.js.map} +1 -1
  169. package/dist/{chunk-JTOVO3ZU.js → chunk-RWBTMHLR.js} +5 -5
  170. package/dist/{chunk-JTOVO3ZU.js.map → chunk-RWBTMHLR.js.map} +1 -1
  171. package/dist/{chunk-DV6SJHL5.js → chunk-S34G5DL4.js} +4 -4
  172. package/dist/{chunk-DV6SJHL5.js.map → chunk-S34G5DL4.js.map} +1 -1
  173. package/dist/{chunk-MKVCFBVF.js → chunk-TIPR4JUO.js} +4 -4
  174. package/dist/{chunk-MKVCFBVF.js.map → chunk-TIPR4JUO.js.map} +1 -1
  175. package/dist/{chunk-WHJZP3QJ.js → chunk-ULMSO2XZ.js} +7 -7
  176. package/dist/{chunk-WHJZP3QJ.js.map → chunk-ULMSO2XZ.js.map} +1 -1
  177. package/dist/{chunk-IVBOLREE.js → chunk-VWVCSD3N.js} +3 -3
  178. package/dist/{chunk-IVBOLREE.js.map → chunk-VWVCSD3N.js.map} +1 -1
  179. package/dist/{chunk-5G7NYNX6.js → chunk-W2LNKEBF.js} +3 -3
  180. package/dist/{chunk-5G7NYNX6.js.map → chunk-W2LNKEBF.js.map} +1 -1
  181. package/dist/{chunk-AV6AAVNU.js → chunk-XGNML7XM.js} +7 -7
  182. package/dist/{chunk-AV6AAVNU.js.map → chunk-XGNML7XM.js.map} +1 -1
  183. package/dist/{chunk-46NBPXAI.js → chunk-XT6CLGF5.js} +3 -3
  184. package/dist/{chunk-46NBPXAI.js.map → chunk-XT6CLGF5.js.map} +1 -1
  185. package/dist/{chunk-SFZ7IIWL.js → chunk-ZEGNYJOR.js} +4 -4
  186. package/dist/{chunk-SFZ7IIWL.js.map → chunk-ZEGNYJOR.js.map} +1 -1
  187. package/dist/{chunk-OM26SAHA.js → chunk-ZPVLBXDY.js} +4 -4
  188. package/dist/{chunk-OM26SAHA.js.map → chunk-ZPVLBXDY.js.map} +1 -1
  189. package/dist/components/cart/index.js +1 -1
  190. package/dist/components/common/RenderWhenVisible.d.ts +3 -1
  191. package/dist/components/common/RenderWhenVisible.d.ts.map +1 -1
  192. package/dist/components/common/index.js +1 -1
  193. package/dist/components/common/lazy.d.ts +1 -1
  194. package/dist/components/common/lazy.d.ts.map +1 -1
  195. package/dist/components/drawer/index.js +22 -20
  196. package/dist/components/home/HomePageRenderer.d.ts.map +1 -1
  197. package/dist/components/home/index.js +26 -24
  198. package/dist/components/layout/index.js +6 -5
  199. package/dist/components/product/index.js +23 -21
  200. package/dist/components/store/index.js +24 -22
  201. package/dist/components/store/index.js.map +1 -1
  202. package/dist/components/toast/index.js +4 -3
  203. package/dist/components/toast/index.js.map +1 -1
  204. package/dist/components/tracking/index.js +1 -1
  205. package/dist/dev/DevSettingsWidget.d.ts +6 -7
  206. package/dist/dev/DevSettingsWidget.d.ts.map +1 -1
  207. package/dist/dev/dev-settings-store.d.ts +89 -46
  208. package/dist/dev/dev-settings-store.d.ts.map +1 -1
  209. package/dist/dev/editor/AddElementDrawer.d.ts +17 -0
  210. package/dist/dev/editor/AddElementDrawer.d.ts.map +1 -0
  211. package/dist/dev/editor/BuilderPanel.d.ts +23 -0
  212. package/dist/dev/editor/BuilderPanel.d.ts.map +1 -0
  213. package/dist/dev/editor/SettingsPanel.d.ts +9 -0
  214. package/dist/dev/editor/SettingsPanel.d.ts.map +1 -0
  215. package/dist/dev/editor/ThemeEditor.d.ts +20 -0
  216. package/dist/dev/editor/ThemeEditor.d.ts.map +1 -0
  217. package/dist/dev/editor/catalog.d.ts +10 -0
  218. package/dist/dev/editor/catalog.d.ts.map +1 -0
  219. package/dist/dev/editor/fields.d.ts +18 -0
  220. package/dist/dev/editor/fields.d.ts.map +1 -0
  221. package/dist/dev/editor/i18n.d.ts +72 -0
  222. package/dist/dev/editor/i18n.d.ts.map +1 -0
  223. package/dist/dev/editor/icons.d.ts +21 -0
  224. package/dist/dev/editor/icons.d.ts.map +1 -0
  225. package/dist/dev/editor/index.d.ts +8 -0
  226. package/dist/dev/editor/index.d.ts.map +1 -0
  227. package/dist/dev/editor/index.js +2059 -0
  228. package/dist/dev/editor/index.js.map +1 -0
  229. package/dist/dev/editor/lookup.d.ts +22 -0
  230. package/dist/dev/editor/lookup.d.ts.map +1 -0
  231. package/dist/dev/editor/mount.d.ts +4 -0
  232. package/dist/dev/editor/mount.d.ts.map +1 -0
  233. package/dist/dev/editor/paths.d.ts +44 -0
  234. package/dist/dev/editor/paths.d.ts.map +1 -0
  235. package/dist/dev/editor/pickers.d.ts +12 -0
  236. package/dist/dev/editor/pickers.d.ts.map +1 -0
  237. package/dist/dev/editor/styles.d.ts +8 -0
  238. package/dist/dev/editor/styles.d.ts.map +1 -0
  239. package/dist/dev/index.d.ts +1 -1
  240. package/dist/dev/index.d.ts.map +1 -1
  241. package/dist/dev/index.js +35 -309
  242. package/dist/dev/index.js.map +1 -1
  243. package/dist/dev/schema-types.d.ts +124 -4
  244. package/dist/dev/schema-types.d.ts.map +1 -1
  245. package/dist/dev/store-lookup.d.ts +13 -0
  246. package/dist/dev/store-lookup.d.ts.map +1 -0
  247. package/dist/document-class-2RROXH4K.js +29 -0
  248. package/dist/{document-class-AJGI7GKJ.js.map → document-class-2RROXH4K.js.map} +1 -1
  249. package/dist/hooks/index.js +22 -20
  250. package/dist/hooks/useComments.js +3 -2
  251. package/dist/hooks/useGtm.js +22 -20
  252. package/dist/hooks/useMoney.js +22 -20
  253. package/dist/hooks/useProduct.js +3 -2
  254. package/dist/hooks/useStore.js +22 -20
  255. package/dist/hooks/useUser.js +5 -4
  256. package/dist/hooks/useWishlist.js +3 -2
  257. package/dist/index.js +22 -20
  258. package/dist/index.js.map +1 -1
  259. package/dist/native-app/index.js +3 -2
  260. package/dist/{navigation-KTFJWOWI.js → navigation-JB2CJXBF.js} +7 -6
  261. package/dist/navigation-JB2CJXBF.js.map +1 -0
  262. package/dist/navigation-KTMLD4VB.js +14 -0
  263. package/dist/{navigation-BARZWXJZ.js.map → navigation-KTMLD4VB.js.map} +1 -1
  264. package/dist/{not-found-NK6ZFJ7H.js → not-found-ZM6VIELR.js} +25 -23
  265. package/dist/not-found-ZM6VIELR.js.map +1 -0
  266. package/dist/providers/index.js +22 -20
  267. package/dist/routes/account/orders.js +7 -6
  268. package/dist/routes/account.js +16 -15
  269. package/dist/routes/account.js.map +1 -1
  270. package/dist/routes/blog.js +11 -10
  271. package/dist/routes/blog.js.map +1 -1
  272. package/dist/routes/brands.js +7 -6
  273. package/dist/routes/brands.js.map +1 -1
  274. package/dist/routes/cart.js +30 -28
  275. package/dist/routes/cart.js.map +1 -1
  276. package/dist/routes/home/HomePage.d.ts.map +1 -1
  277. package/dist/routes/home.js +27 -25
  278. package/dist/routes/index.js +6 -5
  279. package/dist/routes/loyalty.js +8 -7
  280. package/dist/routes/loyalty.js.map +1 -1
  281. package/dist/routes/page.js +7 -6
  282. package/dist/routes/page.js.map +1 -1
  283. package/dist/routes/product-listing/index.d.ts +27 -0
  284. package/dist/routes/product-listing/index.d.ts.map +1 -1
  285. package/dist/routes/product-listing.js +52 -27
  286. package/dist/routes/product-listing.js.map +1 -1
  287. package/dist/routes/product.js +26 -24
  288. package/dist/routes/product.js.map +1 -1
  289. package/dist/routes/seo-redirects.js +6 -5
  290. package/dist/routes/testimonials.js +2 -2
  291. package/dist/routes/thank-you.js +7 -6
  292. package/dist/routes/thank-you.js.map +1 -1
  293. package/dist/skeleton.js +27 -25
  294. package/dist/store-lookup-T4TK7CKA.js +114 -0
  295. package/dist/store-lookup-T4TK7CKA.js.map +1 -0
  296. package/dist/tanstack.js +17 -16
  297. package/dist/tanstack.js.map +1 -1
  298. package/dist/utils/index.js +6 -5
  299. package/dist/utils/index.js.map +1 -1
  300. package/dist/vite/adapters/tanstack.adapter.d.ts.map +1 -1
  301. package/dist/vite/index.js +424 -47
  302. package/dist/vite/index.js.map +1 -1
  303. package/dist/vite/plugins/twilight-schema.d.ts +7 -2
  304. package/dist/vite/plugins/twilight-schema.d.ts.map +1 -1
  305. package/dist/vite/plugins/twilight-schema.plugin.d.ts +26 -0
  306. package/dist/vite/plugins/twilight-schema.plugin.d.ts.map +1 -1
  307. package/package.json +5 -1
  308. package/tailwind/components/common/RenderWhenVisible.tsx.txt +9 -2
  309. package/tailwind/components/home/HomePageRenderer.tsx.txt +2 -0
  310. package/tailwind/routes/home/HomePage.tsx.txt +7 -6
  311. package/tailwind/routes/product-listing/index.tsx.txt +42 -0
  312. package/dist/BlogAuthorPage-KRT7MRTC.js.map +0 -1
  313. package/dist/BlogCategoryPage-OP3ETAMT.js.map +0 -1
  314. package/dist/BlogPage-RGAQVUDI.js.map +0 -1
  315. package/dist/BlogSinglePage-VG4UXBTL.js.map +0 -1
  316. package/dist/BlogTagPage-G4IVHJD5.js.map +0 -1
  317. package/dist/BrandsPage-2JMPPOOU.js.map +0 -1
  318. package/dist/Breadcrumb-I3ZOGG2Y.js.map +0 -1
  319. package/dist/CartItem-YTPYETW6.js.map +0 -1
  320. package/dist/CartSummary-DND7BO26.js.map +0 -1
  321. package/dist/CustomerLayout-HCYVBODI.js.map +0 -1
  322. package/dist/Header-QG4UO3MF.js +0 -21
  323. package/dist/LoyaltyPage-ZMFYQMQY.js.map +0 -1
  324. package/dist/LoyaltyPointsPage-5PB6IFLY.js.map +0 -1
  325. package/dist/MainMenu-SAUMNMBF.js.map +0 -1
  326. package/dist/MobileMenu-2WOWOFQB.js.map +0 -1
  327. package/dist/NotificationsPage-6FX4SOZU.js.map +0 -1
  328. package/dist/OrderSinglePage-RUMSJIFD.js.map +0 -1
  329. package/dist/OrdersPage-B4Q4QIEM.js.map +0 -1
  330. package/dist/PageSingle-F4TDNKUM.js.map +0 -1
  331. package/dist/ProductDetails-BNVVUDBH.js.map +0 -1
  332. package/dist/ProfilePage-OJSAXSC2.js.map +0 -1
  333. package/dist/RenderWhenVisible-F44J5MMG.js.map +0 -1
  334. package/dist/SeoCartWidget-4PN2DW54.js.map +0 -1
  335. package/dist/SettingsPage-BCRNV4GU.js.map +0 -1
  336. package/dist/TestimonialsPage-YU4PLOLR.js.map +0 -1
  337. package/dist/ThankYouPage-MUDELEIQ.js.map +0 -1
  338. package/dist/WalletPage-2I4KTR5E.js.map +0 -1
  339. package/dist/WishlistPage-7AYL3RUD.js.map +0 -1
  340. package/dist/chunk-2JV6WZ6O.js +0 -136
  341. package/dist/chunk-2JV6WZ6O.js.map +0 -1
  342. package/dist/chunk-C4RXPVDF.js.map +0 -1
  343. package/dist/chunk-HSWRYXC7.js.map +0 -1
  344. package/dist/chunk-KZM7HXJ3.js +0 -14
  345. package/dist/chunk-QGOPTVV5.js.map +0 -1
  346. package/dist/chunk-RPDMNNRW.js.map +0 -1
  347. package/dist/chunk-TJF6YZ5I.js.map +0 -1
  348. package/dist/chunk-Y357MBJI.js.map +0 -1
  349. package/dist/chunk-ZFNLX3F7.js.map +0 -1
  350. package/dist/document-class-AJGI7GKJ.js +0 -28
  351. package/dist/navigation-BARZWXJZ.js +0 -13
  352. package/dist/navigation-KTFJWOWI.js.map +0 -1
  353. package/dist/not-found-NK6ZFJ7H.js.map +0 -1
@@ -3,17 +3,18 @@ export { REACT_THEME_TYPE, describeThemeTypeIssue, getThemeType, isReactThemeMan
3
3
  import { tanstackHeadAdapter } from '../chunk-N2A72R2I.js';
4
4
  import { nextjsHeadAdapter } from '../chunk-HOSHJBPS.js';
5
5
  import '../chunk-RV54D2D7.js';
6
+ import { EMPTY_DEV_SCHEMA, DEV_PREVIEW_GLOBAL, DEV_PREVIEW_ENDPOINT, normalizePreviewState, DEV_PREVIEW_EVENT, DEV_EDITOR_PATH, DEV_PREVIEW_IMAGE_ENDPOINT, DEV_PREVIEW_IMAGE_MAX_BYTES } from '../chunk-N45X7D55.js';
6
7
  import { setHeadAdapter } from '../chunk-GD26FI4J.js';
7
8
  import '../chunk-4SZZPXM2.js';
8
9
  import { RouteId } from '../chunk-OUW6WESU.js';
9
10
  import '../chunk-N2S25NXP.js';
10
11
  import '../chunk-T72DAX7R.js';
11
12
  import '../chunk-DGUM43GV.js';
12
- import { readFile, readdir } from 'fs/promises';
13
+ import { readFile, readdir, writeFile, mkdir } from 'fs/promises';
13
14
  import { dirname, join, relative, resolve, basename, sep } from 'path';
15
+ import { createHash } from 'crypto';
14
16
  import { parseSync } from 'oxc-parser';
15
17
  import { existsSync, mkdirSync, writeFileSync, readFileSync, rmSync, readdirSync, statSync } from 'fs';
16
- import { createHash } from 'crypto';
17
18
  import { fileURLToPath, pathToFileURL } from 'url';
18
19
  import Module, { createRequire } from 'module';
19
20
  import { transformSync } from 'esbuild';
@@ -160,7 +161,33 @@ ${entries.join(",\n")}
160
161
  }
161
162
 
162
163
  // src/vite/plugins/twilight-schema.ts
163
- var TEXTUAL_FORMATS = /* @__PURE__ */ new Set(["text", "textarea", "image", "icon", "line"]);
164
+ var TEXT_FORMATS = /* @__PURE__ */ new Set(["text", "icon", "line", "hidden", "url", "email", "color"]);
165
+ function text(value) {
166
+ return typeof value === "string" && value.trim() ? value : void 0;
167
+ }
168
+ function num(value) {
169
+ return typeof value === "number" && Number.isFinite(value) ? value : void 0;
170
+ }
171
+ function toConditions(raw) {
172
+ if (!Array.isArray(raw)) return void 0;
173
+ const conditions = raw.flatMap((c) => {
174
+ const obj = c ?? {};
175
+ if (typeof obj.id !== "string" || !obj.id) return [];
176
+ const operation = typeof obj.operation === "string" && obj.operation ? obj.operation : "=";
177
+ return [{ id: obj.id, operation, value: obj.value }];
178
+ });
179
+ return conditions.length ? conditions : void 0;
180
+ }
181
+ function extras(entry) {
182
+ const out = {};
183
+ const description = text(entry.description);
184
+ const placeholder = text(entry.placeholder);
185
+ const conditions = toConditions(entry.conditions);
186
+ if (description) out.description = description;
187
+ if (placeholder) out.placeholder = placeholder;
188
+ if (conditions) out.conditions = conditions;
189
+ return out;
190
+ }
164
191
  function labelOf(entry, fallback) {
165
192
  return typeof entry.label === "string" && entry.label.trim() ? entry.label : fallback;
166
193
  }
@@ -196,6 +223,47 @@ function firstScalar(v) {
196
223
  }
197
224
  return v;
198
225
  }
226
+ var ENTITY_SOURCES = ["products", "categories", "brands"];
227
+ function isEntitySource(source) {
228
+ return ENTITY_SOURCES.includes(source);
229
+ }
230
+ function classifyString(entry, id, label) {
231
+ const { format } = entry;
232
+ const value = typeof entry.value === "string" ? entry.value : "";
233
+ const base = { id, label, default: value, ...extras(entry) };
234
+ if (format === "textarea") return { ...base, kind: "textarea" };
235
+ if (format === "image") return { ...base, kind: "image" };
236
+ if (typeof format === "string" && TEXT_FORMATS.has(format)) return { ...base, kind: "text" };
237
+ return null;
238
+ }
239
+ function classifyCollection(entry, id, label) {
240
+ const prefix = `${id}.`;
241
+ const fields = [];
242
+ for (const sub of Array.isArray(entry.fields) ? entry.fields : []) {
243
+ const subId = typeof sub.id === "string" && sub.id.startsWith(prefix) ? sub.id.slice(prefix.length) : sub.id;
244
+ const field = classify({ ...sub, id: subId });
245
+ if (!field) continue;
246
+ field.conditions = field.conditions?.map(
247
+ (c) => c.id.startsWith(prefix) ? { ...c, id: c.id.slice(prefix.length) } : c
248
+ );
249
+ if (!field.conditions) delete field.conditions;
250
+ fields.push(field);
251
+ }
252
+ const min = num(entry.minLength);
253
+ const max = num(entry.maxLength);
254
+ const itemLabel = text(entry.item_label);
255
+ return {
256
+ id,
257
+ label,
258
+ kind: "collection",
259
+ default: collectionRows(entry),
260
+ fields,
261
+ ...min !== void 0 ? { min } : {},
262
+ ...max !== void 0 ? { max } : {},
263
+ ...itemLabel ? { itemLabel } : {},
264
+ ...extras(entry)
265
+ };
266
+ }
199
267
  function classify(entry) {
200
268
  const id = typeof entry.id === "string" ? entry.id : "";
201
269
  if (!id) return null;
@@ -207,35 +275,103 @@ function classify(entry) {
207
275
  id,
208
276
  label,
209
277
  kind: "toggle",
210
- default: typeof entry.value === "boolean" ? entry.value : false
278
+ default: typeof entry.value === "boolean" ? entry.value : false,
279
+ ...extras(entry)
211
280
  };
212
281
  }
213
282
  if (type === "items" && format === "dropdown-list") {
214
283
  const options = toOptions(entry.options);
284
+ if (!options && isEntitySource(entry.source)) {
285
+ const min = num(entry.minLength);
286
+ const max = num(entry.maxLength);
287
+ return {
288
+ id,
289
+ label,
290
+ kind: "entities",
291
+ source: entry.source,
292
+ multiple: entry.multichoice === true,
293
+ default: Array.isArray(entry.value) ? entry.value : [],
294
+ ...min !== void 0 ? { min } : {},
295
+ ...max !== void 0 ? { max } : {},
296
+ ...extras(entry)
297
+ };
298
+ }
215
299
  if (!options) {
216
300
  return {
217
301
  id,
218
302
  label,
219
303
  kind: "readonly",
220
304
  default: null,
221
- note: `remote (${entry.source ?? "dynamic"})`
305
+ note: `remote (${entry.source ?? "dynamic"})`,
306
+ ...extras(entry)
222
307
  };
223
308
  }
224
309
  const fallback = options[0]?.value;
225
310
  const def = firstScalar(entry.value) ?? firstScalar(entry.selected) ?? fallback;
226
- return { id, label, kind: "select", default: def ?? "", options };
311
+ return { id, label, kind: "select", default: def ?? "", options, ...extras(entry) };
227
312
  }
228
- if (type === "string" && typeof format === "string" && TEXTUAL_FORMATS.has(format)) {
229
- return { id, label, kind: "text", default: typeof entry.value === "string" ? entry.value : "" };
313
+ if (type === "string") {
314
+ const field = classifyString(entry, id, label);
315
+ if (field) return field;
316
+ }
317
+ if (type === "number") {
318
+ const min = num(entry.minimum);
319
+ const max = num(entry.maximum);
320
+ return {
321
+ id,
322
+ label,
323
+ kind: "number",
324
+ default: num(entry.value) ?? null,
325
+ ...min !== void 0 ? { min } : {},
326
+ ...max !== void 0 ? { max } : {},
327
+ ...extras(entry)
328
+ };
329
+ }
330
+ if (type === "collection") return classifyCollection(entry, id, label);
331
+ if (type === "items" && format === "variable-list") {
332
+ const linkSources = toOptions(entry.sources);
333
+ return {
334
+ id,
335
+ label,
336
+ kind: "link",
337
+ default: typeof entry.value === "string" ? entry.value : "",
338
+ ...linkSources ? { linkSources } : {},
339
+ ...extras(entry)
340
+ };
230
341
  }
231
342
  return {
232
343
  id,
233
344
  label,
234
345
  kind: "readonly",
235
346
  default: null,
236
- note: `${type ?? "unknown"}/${format ?? "?"}`
347
+ note: `${type ?? "unknown"}/${format ?? "?"}`,
348
+ ...extras(entry)
237
349
  };
238
350
  }
351
+ function collectionRows(entry) {
352
+ if (!Array.isArray(entry.value)) return [];
353
+ const prefix = `${entry.id}.`;
354
+ return entry.value.filter((row) => !!row && typeof row === "object").map(
355
+ (row) => Object.fromEntries(
356
+ Object.entries(row).map(([key, value]) => [
357
+ key.startsWith(prefix) ? key.slice(prefix.length) : key,
358
+ value
359
+ ])
360
+ )
361
+ );
362
+ }
363
+ function blockDefaultsFor(fieldsRaw, fields) {
364
+ const out = {};
365
+ for (const entry of fieldsRaw) {
366
+ if (typeof entry.id !== "string" || !entry.id || entry.type === "static") continue;
367
+ if (entry.type === "collection") out[entry.id] = collectionRows(entry);
368
+ else if (entry.type === "items" && entry.format === "variable-list")
369
+ out[entry.id] = typeof entry.value === "string" ? entry.value : "";
370
+ else if (entry.type === "items" && !toOptions(entry.options)) out[entry.id] = [];
371
+ else if (entry.value !== void 0) out[entry.id] = entry.value;
372
+ }
373
+ return { ...out, ...defaultsFor(fields) };
374
+ }
239
375
  function defaultsFor(fields) {
240
376
  const out = {};
241
377
  for (const f of fields) {
@@ -243,6 +379,14 @@ function defaultsFor(fields) {
243
379
  }
244
380
  return out;
245
381
  }
382
+ function localizedOf(name) {
383
+ if (typeof name === "string" && name) return { ar: name, en: name };
384
+ if (!name || typeof name !== "object") return void 0;
385
+ const entries = Object.entries(name).filter(
386
+ (entry) => typeof entry[1] === "string" && entry[1] !== ""
387
+ );
388
+ return entries.length ? Object.fromEntries(entries) : void 0;
389
+ }
246
390
  function buildTwilightSchema(raw) {
247
391
  const root = raw ?? {};
248
392
  const settingsRaw = Array.isArray(root.settings) ? root.settings : [];
@@ -254,6 +398,7 @@ function buildTwilightSchema(raw) {
254
398
  const componentsRaw = Array.isArray(root.components) ? root.components : [];
255
399
  const components = [];
256
400
  const componentDefaults = {};
401
+ const blockDefaults = {};
257
402
  for (const c of componentsRaw) {
258
403
  const path = typeof c.path === "string" && c.path || typeof c.key === "string" && c.key || "";
259
404
  if (!path) continue;
@@ -263,33 +408,271 @@ function buildTwilightSchema(raw) {
263
408
  const field = classify(fr);
264
409
  if (field) fields.push(field);
265
410
  }
266
- components.push({ path, title: titleOf(c), fields });
411
+ const key = typeof c.key === "string" && c.key ? c.key : void 0;
412
+ const titles = c.title && typeof c.title === "object" ? localizedOf(c.title) : void 0;
413
+ components.push({
414
+ path,
415
+ ...key ? { key } : {},
416
+ title: titleOf(c),
417
+ ...titles ? { titles } : {},
418
+ ...text(c.image) ? { image: text(c.image) } : {},
419
+ ...typeof c.icon === "string" && /^sicon-[a-z0-9-]+$/.test(c.icon) ? { icon: c.icon } : {},
420
+ fields
421
+ });
267
422
  componentDefaults[path] = defaultsFor(fields);
423
+ blockDefaults[path] = blockDefaultsFor(fieldsRaw, fields);
268
424
  }
425
+ const themeName = localizedOf(root.name);
269
426
  return {
427
+ ...themeName ? { themeName } : {},
270
428
  settings,
271
429
  components,
272
430
  settingsDefaults: defaultsFor(settings),
273
- componentDefaults
431
+ componentDefaults,
432
+ blockDefaults
274
433
  };
275
434
  }
276
435
 
277
- // src/dev/schema-types.ts
278
- var EMPTY_DEV_SCHEMA = {
279
- settings: [],
280
- components: [],
281
- settingsDefaults: {},
282
- componentDefaults: {}
283
- };
284
-
285
436
  // src/vite/plugins/twilight-schema.plugin.ts
286
437
  var VIRTUAL_ID2 = "virtual:twilight/schema";
287
438
  var RESOLVED_ID2 = "\0" + VIRTUAL_ID2;
439
+ var EDITOR_ENTRY_ID = "virtual:twilight/editor";
440
+ var RESOLVED_EDITOR_ENTRY_ID = "\0" + EDITOR_ENTRY_ID;
441
+ var EDITOR_ENTRY = [
442
+ `import schema from '${VIRTUAL_ID2}';`,
443
+ `import { mountThemeEditor } from '@salla.sa/twilight-theme-engine/dev/editor';`,
444
+ `mountThemeEditor(document.getElementById('root'), schema);`
445
+ ].join("\n");
446
+ var EDITOR_HTML = `<!doctype html>
447
+ <html lang="ar" dir="rtl">
448
+ <head>
449
+ <meta charset="utf-8" />
450
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
451
+ <title>Theme editor</title>
452
+ <link rel="stylesheet" href="https://cdn.salla.network/fonts/pingarlt.css" />
453
+ <link rel="stylesheet" href="https://cdn.salla.network/fonts/sallaicons.css" />
454
+ </head>
455
+ <body>
456
+ <div id="root"></div>
457
+ <script type="module" src="/@id/__x00__${EDITOR_ENTRY_ID}"></script>
458
+ </body>
459
+ </html>
460
+ `;
461
+ function serveEditorPage(server, onShown) {
462
+ server.middlewares.use(DEV_EDITOR_PATH, (req, res, next) => {
463
+ const rest = (req.url ?? "/").split("?")[0];
464
+ if (req.method !== "GET" || rest !== "/" && rest !== "") {
465
+ next();
466
+ return;
467
+ }
468
+ onShown();
469
+ server.transformIndexHtml(req.originalUrl ?? DEV_EDITOR_PATH, EDITOR_HTML).then((html) => {
470
+ res.statusCode = 200;
471
+ res.setHeader("content-type", "text/html; charset=utf-8");
472
+ res.end(html);
473
+ }).catch(next);
474
+ });
475
+ }
476
+ var EDITOR_OPT_OUT = /(?:^|&)editor=off(?:&|$)/;
477
+ function isStorefrontPage(path) {
478
+ if (/^\/(?:@|__|node_modules\/|_serverFn)/.test(path)) return false;
479
+ const last = path.split("/").pop() ?? "";
480
+ return !last.includes(".");
481
+ }
482
+ function openEditorFirst(server, editorShown) {
483
+ server.middlewares.use((req, res, next) => {
484
+ const url = req.url ?? "/";
485
+ const [path, query = ""] = url.split("?");
486
+ const opens = req.method === "GET" && req.headers["sec-fetch-dest"] === "document" && !EDITOR_OPT_OUT.test(query) && isStorefrontPage(path) && (path === "/" || !editorShown());
487
+ if (!opens) {
488
+ next();
489
+ return;
490
+ }
491
+ const location = url === "/" ? DEV_EDITOR_PATH : `${DEV_EDITOR_PATH}?path=${encodeURIComponent(url)}`;
492
+ res.statusCode = 302;
493
+ res.setHeader("location", location);
494
+ res.end();
495
+ });
496
+ }
497
+ function serveEditor(server) {
498
+ let shown = false;
499
+ serveEditorPage(server, () => {
500
+ shown = true;
501
+ });
502
+ openEditorFirst(server, () => shown);
503
+ }
288
504
  var EMPTY_MODULE = `export default ${JSON.stringify(EMPTY_DEV_SCHEMA)};`;
289
505
  var LOG_PREFIX = "[twilight-react:schema]";
290
506
  var MAX_REPORTED = 8;
507
+ var DEV_PREVIEW_FILE = "twilight.preview.json";
508
+ var MAX_PREVIEW_BYTES = 2 * 1024 * 1024;
509
+ async function readPreview(path) {
510
+ try {
511
+ return normalizePreviewState(JSON.parse(await readFile(path, "utf-8")));
512
+ } catch {
513
+ return null;
514
+ }
515
+ }
516
+ function readBody(req, limit) {
517
+ return new Promise((resolveBody, reject) => {
518
+ let size = 0;
519
+ const chunks = [];
520
+ req.on("data", (chunk) => {
521
+ size += chunk.length;
522
+ if (size > limit) {
523
+ reject(new Error("request too large"));
524
+ req.destroy();
525
+ return;
526
+ }
527
+ chunks.push(chunk);
528
+ });
529
+ req.on("end", () => resolveBody(Buffer.concat(chunks)));
530
+ req.on("error", reject);
531
+ });
532
+ }
533
+ function isSameOrigin(req) {
534
+ const { origin, host } = req.headers;
535
+ const site = req.headers["sec-fetch-site"];
536
+ if (site !== void 0 && site !== "same-origin" && site !== "none") return false;
537
+ if (origin === void 0) return true;
538
+ try {
539
+ return new URL(origin).host === host;
540
+ } catch {
541
+ return false;
542
+ }
543
+ }
544
+ var IMAGE_EXTENSIONS = {
545
+ "image/png": "png",
546
+ "image/jpeg": "jpg",
547
+ "image/webp": "webp",
548
+ "image/gif": "gif",
549
+ "image/avif": "avif"
550
+ };
551
+ var IMAGE_TYPES = Object.fromEntries(
552
+ Object.entries(IMAGE_EXTENSIONS).map(([type, ext]) => [ext, type])
553
+ );
554
+ var IMAGE_NAME = /^[a-f0-9]{16}\.(png|jpg|webp|gif|avif)$/;
555
+ var DEV_PREVIEW_ASSETS_DIR = "twilight-preview-assets";
556
+ function send(res, status, body, type = "text/plain") {
557
+ res.statusCode = status;
558
+ if (body !== void 0) res.setHeader("content-type", type);
559
+ res.end(body);
560
+ }
561
+ function refreshServerModules(server, resolvedId) {
562
+ const environments = Object.values(server.environments ?? {});
563
+ if (!environments.length) {
564
+ const mod = server.moduleGraph.getModuleById(resolvedId);
565
+ if (mod) server.moduleGraph.invalidateModule(mod);
566
+ return;
567
+ }
568
+ for (const environment of environments) {
569
+ const mod = environment.moduleGraph.getModuleById(resolvedId);
570
+ if (mod) environment.moduleGraph.invalidateModule(mod);
571
+ if (environment.name !== "client") environment.hot.send({ type: "full-reload" });
572
+ }
573
+ }
574
+ function imageRoutes(assets) {
575
+ const saveImage = async (req, res) => {
576
+ const ext = IMAGE_EXTENSIONS[String(req.headers["content-type"]).split(";")[0].trim()];
577
+ if (!ext) {
578
+ send(res, 415, "expected a png, jpeg, webp, gif or avif image");
579
+ return;
580
+ }
581
+ const bytes = await readBody(req, DEV_PREVIEW_IMAGE_MAX_BYTES);
582
+ const name = `${createHash("sha256").update(bytes).digest("hex").slice(0, 16)}.${ext}`;
583
+ await mkdir(assets, { recursive: true });
584
+ await writeFile(resolve(assets, name), bytes);
585
+ send(
586
+ res,
587
+ 201,
588
+ JSON.stringify({ url: `${DEV_PREVIEW_IMAGE_ENDPOINT}/${name}` }),
589
+ "application/json"
590
+ );
591
+ };
592
+ const serveImage = async (name, res) => {
593
+ if (!IMAGE_NAME.test(name)) {
594
+ send(res, 404);
595
+ return;
596
+ }
597
+ try {
598
+ const bytes = await readFile(resolve(assets, name));
599
+ res.statusCode = 200;
600
+ res.setHeader("x-content-type-options", "nosniff");
601
+ res.setHeader("content-type", IMAGE_TYPES[name.slice(name.lastIndexOf(".") + 1)]);
602
+ res.end(bytes);
603
+ } catch {
604
+ send(res, 404);
605
+ }
606
+ };
607
+ return { saveImage, serveImage };
608
+ }
609
+ function servePreviewFile(server, preview) {
610
+ let lastWritten;
611
+ let writes = Promise.resolve();
612
+ const { saveImage, serveImage } = imageRoutes(resolve(dirname(preview), DEV_PREVIEW_ASSETS_DIR));
613
+ server.watcher.add(preview);
614
+ const onPreviewFile = async (file) => {
615
+ if (file !== preview) return;
616
+ let content;
617
+ try {
618
+ content = await readFile(preview, "utf-8");
619
+ } catch {
620
+ content = void 0;
621
+ }
622
+ if (content !== void 0 && content === lastWritten) return;
623
+ refreshServerModules(server, RESOLVED_ID2);
624
+ server.ws.send({ type: "full-reload" });
625
+ };
626
+ server.watcher.on("change", (file) => void onPreviewFile(file));
627
+ server.watcher.on("add", (file) => void onPreviewFile(file));
628
+ server.watcher.on("unlink", (file) => void onPreviewFile(file));
629
+ const saveState = async (req, res) => {
630
+ if (!String(req.headers["content-type"]).startsWith("application/json")) {
631
+ send(res, 415, "expected application/json");
632
+ return;
633
+ }
634
+ const body = JSON.parse((await readBody(req, MAX_PREVIEW_BYTES)).toString("utf-8"));
635
+ const state = normalizePreviewState(body.state);
636
+ if (!state) throw new Error("not a preview state");
637
+ const content = `${JSON.stringify(state, null, 2)}
638
+ `;
639
+ const write = writes.then(async () => {
640
+ lastWritten = content;
641
+ await writeFile(preview, content);
642
+ });
643
+ writes = write.catch(() => {
644
+ });
645
+ await write;
646
+ refreshServerModules(server, RESOLVED_ID2);
647
+ server.ws.send({
648
+ type: "custom",
649
+ event: DEV_PREVIEW_EVENT,
650
+ data: { state, from: typeof body.from === "string" ? body.from : null }
651
+ });
652
+ send(res, 204);
653
+ };
654
+ server.middlewares.use(DEV_PREVIEW_ENDPOINT, (req, res) => {
655
+ const route = (req.url ?? "/").split("?")[0];
656
+ if (req.method === "GET" && route.startsWith("/image/")) {
657
+ void serveImage(route.slice("/image/".length), res);
658
+ return;
659
+ }
660
+ if (req.method !== "POST" || route !== "/" && route !== "" && route !== "/image") {
661
+ send(res, 405);
662
+ return;
663
+ }
664
+ if (!isSameOrigin(req)) {
665
+ send(res, 403, "cross-origin write refused");
666
+ return;
667
+ }
668
+ (route === "/image" ? saveImage(req, res) : saveState(req, res)).catch(
669
+ (error) => send(res, 400, error instanceof Error ? error.message : "bad request")
670
+ );
671
+ });
672
+ }
291
673
  function twilightSchemaPlugin(twilightJsonPath = "twilight.json") {
292
674
  let filePath;
675
+ let previewPath;
293
676
  let isDevServer = false;
294
677
  async function checkManifest() {
295
678
  if (!isDevServer || !filePath) return;
@@ -321,23 +704,30 @@ function twilightSchemaPlugin(twilightJsonPath = "twilight.json") {
321
704
  configResolved(config) {
322
705
  isDevServer = config.command === "serve";
323
706
  filePath = resolve(config.root, twilightJsonPath);
707
+ previewPath = resolve(config.root, DEV_PREVIEW_FILE);
324
708
  },
325
709
  buildStart() {
326
710
  return checkManifest();
327
711
  },
328
712
  resolveId(id) {
329
713
  if (id === VIRTUAL_ID2) return RESOLVED_ID2;
714
+ if (id === EDITOR_ENTRY_ID && isDevServer) return RESOLVED_EDITOR_ENTRY_ID;
330
715
  },
331
716
  async load(id) {
717
+ if (id === RESOLVED_EDITOR_ENTRY_ID) return EDITOR_ENTRY;
332
718
  if (id !== RESOLVED_ID2) return;
333
719
  if (!isDevServer || !filePath) return EMPTY_MODULE;
720
+ const preview = previewPath ? await readPreview(previewPath) : null;
721
+ let schema = EMPTY_DEV_SCHEMA;
334
722
  try {
335
- const raw = JSON.parse(await readFile(filePath, "utf-8"));
336
- const schema = buildTwilightSchema(raw);
337
- return `export default ${JSON.stringify(schema)};`;
723
+ schema = buildTwilightSchema(JSON.parse(await readFile(filePath, "utf-8")));
338
724
  } catch {
339
- return EMPTY_MODULE;
340
725
  }
726
+ return [
727
+ `const schema = ${JSON.stringify({ ...schema, preview })};`,
728
+ `globalThis[${JSON.stringify(DEV_PREVIEW_GLOBAL)}] = schema.preview;`,
729
+ "export default schema;"
730
+ ].join("\n");
341
731
  },
342
732
  configureServer(server) {
343
733
  if (!filePath) return;
@@ -354,6 +744,8 @@ function twilightSchemaPlugin(twilightJsonPath = "twilight.json") {
354
744
  };
355
745
  server.watcher.on("change", invalidate);
356
746
  server.watcher.on("add", invalidate);
747
+ if (previewPath) servePreviewFile(server, previewPath);
748
+ serveEditor(server);
357
749
  }
358
750
  };
359
751
  }
@@ -2223,29 +2615,19 @@ export const Route = createFileRoute('${tanstackRoutePath}')({
2223
2615
  }`;
2224
2616
  return `// @auto-generated
2225
2617
  import { createFileRoute } from '@tanstack/react-router';
2226
- import { ${importName} } from '${moduleImport}';${typeImport}${extraTypeImport}
2618
+ import { ${importName}, searchListingSearch } from '${moduleImport}';${typeImport}${extraTypeImport}
2227
2619
  import { withHead } from '${baseImport.replace("/routes", "")}/tanstack';
2228
2620
 
2229
2621
  /**
2230
- * Search route configuration with URL query parameter support.
2231
- * Uses validateSearch for type-safe search params and loaderDeps to pass
2232
- * them to the loader.
2622
+ * Search route configuration: \`searchListingSearch\` keeps ?q=, ?page= and ?sort=
2623
+ * and forwards them to the loader.
2233
2624
  */
2234
2625
  export const Route = createFileRoute('${tanstackRoutePath}')({
2235
- validateSearch: (search: Record<string, unknown>) => {
2236
- const page = Number(search.page) || 1;
2237
- const sort = (search.sort as string) || undefined;
2238
- return {
2239
- q: (search.q as string) || '',
2240
- ...(page > 1 ? { page } : {}),
2241
- ...(sort ? { sort } : {}),
2242
- };
2243
- },
2244
- loaderDeps: ({ search }) => ({ q: search.q, page: search.page, sort: search.sort }),
2626
+ ...searchListingSearch,
2245
2627
  loader: ({ deps, params }): Promise<${loaderType}> =>
2246
2628
  ${importName}.loader({
2247
2629
  params: { source: 'search' },
2248
- search: { q: deps.q, page: deps.page, sort: deps.sort },
2630
+ search: deps,
2249
2631
  locale: params.locale,
2250
2632
  }),
2251
2633
  head: withHead(${importName}),
@@ -2351,16 +2733,16 @@ import { ${skeletonName} } from '${skeletonModulePath}';` : "";
2351
2733
  const sortLoaderCall = hasParams ? `({ deps, params }): ${returnType} =>
2352
2734
  ${importName}.loader({
2353
2735
  params: ${paramMapping},
2354
- search: { page: deps.page, sort: deps.sort },
2736
+ search: deps,
2355
2737
  locale: params.locale,
2356
2738
  })` : `({ deps, params }): ${returnType} =>
2357
2739
  ${importName}.loader({
2358
- search: { page: deps.page, sort: deps.sort },
2740
+ search: deps,
2359
2741
  locale: params.locale,
2360
2742
  })`;
2361
2743
  return `// @auto-generated
2362
2744
  import { createFileRoute } from '@tanstack/react-router';
2363
- import { ${importName} } from '${moduleImport}';${typeImport}${skeletonImport}
2745
+ import { ${importName}, listingSearch } from '${moduleImport}';${typeImport}${skeletonImport}
2364
2746
  ${headImport}
2365
2747
 
2366
2748
  /**
@@ -2368,12 +2750,7 @@ ${headImport}
2368
2750
  * Loads page data via loader and renders the ${importName} component.
2369
2751
  */
2370
2752
  export const Route = createFileRoute('${tanstackRoutePath}')({
2371
- validateSearch: (search: Record<string, unknown>) => {
2372
- const page = Number(search.page) || 1;
2373
- const sort = (search.sort as string) || undefined;
2374
- return { ...(page > 1 ? { page } : {}), ...(sort ? { sort } : {}) };
2375
- },
2376
- loaderDeps: ({ search }) => ({ page: search.page, sort: search.sort }),
2753
+ ...listingSearch,
2377
2754
  loader: ${sortLoaderCall},
2378
2755
  head: ${headCallback},${pendingLine}
2379
2756
  component: ${importName}Component,