@salla.sa/twilight-theme-engine 1.0.84 → 1.0.86

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 (377) hide show
  1. package/dist/{AddToCartForm-JUMFLSKN.js → AddToCartForm-5X2WZDWR.js} +3 -3
  2. package/dist/{AddToCartForm-JUMFLSKN.js.map → AddToCartForm-5X2WZDWR.js.map} +1 -1
  3. package/dist/{BlogAuthorPage-LFAUMKC7.js → BlogAuthorPage-LO7FSSJR.js} +12 -10
  4. package/dist/BlogAuthorPage-LO7FSSJR.js.map +1 -0
  5. package/dist/{BlogCategoryPage-NWYFFPCD.js → BlogCategoryPage-KKFQ3PGR.js} +12 -10
  6. package/dist/BlogCategoryPage-KKFQ3PGR.js.map +1 -0
  7. package/dist/{BlogPage-BOHXFV7E.js → BlogPage-VLF3NSGE.js} +11 -9
  8. package/dist/BlogPage-VLF3NSGE.js.map +1 -0
  9. package/dist/{BlogSinglePage-FYEXQPMB.js → BlogSinglePage-AVK535IW.js} +11 -9
  10. package/dist/BlogSinglePage-AVK535IW.js.map +1 -0
  11. package/dist/{BlogTagPage-DAM3RNVA.js → BlogTagPage-F3T4D7RH.js} +12 -10
  12. package/dist/BlogTagPage-F3T4D7RH.js.map +1 -0
  13. package/dist/{BrandsPage-GAKQCE6O.js → BrandsPage-LVSBZSVC.js} +11 -9
  14. package/dist/BrandsPage-LVSBZSVC.js.map +1 -0
  15. package/dist/{Breadcrumb-NAYSZNRV.js → Breadcrumb-VLFTXRFC.js} +11 -9
  16. package/dist/Breadcrumb-VLFTXRFC.js.map +1 -0
  17. package/dist/{CartItem-ZRVLIZT3.js → CartItem-G3H34GW6.js} +11 -9
  18. package/dist/CartItem-G3H34GW6.js.map +1 -0
  19. package/dist/{CartSummary-U2TVLG35.js → CartSummary-VH37RPUI.js} +11 -9
  20. package/dist/CartSummary-VH37RPUI.js.map +1 -0
  21. package/dist/{Copyright-2LSBADZD.js → Copyright-HE5ZWINZ.js} +3 -3
  22. package/dist/{Copyright-2LSBADZD.js.map → Copyright-HE5ZWINZ.js.map} +1 -1
  23. package/dist/{CustomerLayout-WSKXWI7D.js → CustomerLayout-LKBLOAVW.js} +11 -9
  24. package/dist/CustomerLayout-LKBLOAVW.js.map +1 -0
  25. package/dist/{Footer-ONNRJU4G.js → Footer-HHXAST72.js} +5 -5
  26. package/dist/{Footer-ONNRJU4G.js.map → Footer-HHXAST72.js.map} +1 -1
  27. package/dist/{Header-C6VXLLUC.js → Header-GEVZM2YG.js} +8 -6
  28. package/dist/{Header-C6VXLLUC.js.map → Header-GEVZM2YG.js.map} +1 -1
  29. package/dist/{LoyaltyPage-IG5KSYNO.js → LoyaltyPage-M5CT3CFD.js} +11 -9
  30. package/dist/LoyaltyPage-M5CT3CFD.js.map +1 -0
  31. package/dist/{LoyaltyPointsPage-RKO56ZER.js → LoyaltyPointsPage-SDJB52U6.js} +10 -3
  32. package/dist/LoyaltyPointsPage-SDJB52U6.js.map +1 -0
  33. package/dist/{MainMenu-USOYTKPU.js → MainMenu-I7EYS752.js} +3 -3
  34. package/dist/{MainMenu-USOYTKPU.js.map → MainMenu-I7EYS752.js.map} +1 -1
  35. package/dist/{MasterLayout-2W24ACEK.js → MasterLayout-QDK4T3NE.js} +11 -9
  36. package/dist/{MasterLayout-2W24ACEK.js.map → MasterLayout-QDK4T3NE.js.map} +1 -1
  37. package/dist/{MobileMenu-E4X2GOZ3.js → MobileMenu-7VTCWAVJ.js} +11 -9
  38. package/dist/MobileMenu-7VTCWAVJ.js.map +1 -0
  39. package/dist/{NotificationsPage-BJ5XVWEG.js → NotificationsPage-QCABE6QD.js} +11 -9
  40. package/dist/NotificationsPage-QCABE6QD.js.map +1 -0
  41. package/dist/{OrderSinglePage-544E36FJ.js → OrderSinglePage-2HVBKBG4.js} +11 -9
  42. package/dist/OrderSinglePage-2HVBKBG4.js.map +1 -0
  43. package/dist/{OrdersPage-AFBWVTZU.js → OrdersPage-5MNCPCM3.js} +11 -9
  44. package/dist/OrdersPage-5MNCPCM3.js.map +1 -0
  45. package/dist/{PageSingle-H2EJIL74.js → PageSingle-EN5XIM2B.js} +3 -3
  46. package/dist/{PageSingle-H2EJIL74.js.map → PageSingle-EN5XIM2B.js.map} +1 -1
  47. package/dist/{ProductDetails-SDZHALU6.js → ProductDetails-UEWQPPDZ.js} +13 -6
  48. package/dist/ProductDetails-UEWQPPDZ.js.map +1 -0
  49. package/dist/{ProfilePage-V5KV6GQK.js → ProfilePage-TZSU3GHZ.js} +11 -9
  50. package/dist/ProfilePage-TZSU3GHZ.js.map +1 -0
  51. package/dist/{ReviewsPage-CXKJABXP.js → ReviewsPage-WYZ6CHF2.js} +3 -3
  52. package/dist/{ReviewsPage-CXKJABXP.js.map → ReviewsPage-WYZ6CHF2.js.map} +1 -1
  53. package/dist/{SeoCartWidget-JAV6M3X5.js → SeoCartWidget-5JR5RXQM.js} +11 -9
  54. package/dist/SeoCartWidget-5JR5RXQM.js.map +1 -0
  55. package/dist/{SettingsPage-43SUCLQR.js → SettingsPage-DIDRQXMM.js} +11 -9
  56. package/dist/SettingsPage-DIDRQXMM.js.map +1 -0
  57. package/dist/{StoreClosedNotification-MINBJOGZ.js → StoreClosedNotification-C2G32E34.js} +12 -10
  58. package/dist/{StoreClosedNotification-MINBJOGZ.js.map → StoreClosedNotification-C2G32E34.js.map} +1 -1
  59. package/dist/{TestimonialsPage-RLLIDLOA.js → TestimonialsPage-XPHFRBZ7.js} +3 -3
  60. package/dist/{TestimonialsPage-RLLIDLOA.js.map → TestimonialsPage-XPHFRBZ7.js.map} +1 -1
  61. package/dist/{ThankYouPage-52SSZ7FV.js → ThankYouPage-UA6YYFB2.js} +11 -9
  62. package/dist/ThankYouPage-UA6YYFB2.js.map +1 -0
  63. package/dist/{WalletPage-4AN4UJ52.js → WalletPage-AJVV7LVL.js} +11 -9
  64. package/dist/WalletPage-AJVV7LVL.js.map +1 -0
  65. package/dist/{WishlistPage-L6IYJUJZ.js → WishlistPage-UW6LJLSW.js} +11 -9
  66. package/dist/WishlistPage-UW6LJLSW.js.map +1 -0
  67. package/dist/api/advertisement.d.ts +33 -0
  68. package/dist/api/advertisement.d.ts.map +1 -0
  69. package/dist/api/advertisement.js +8 -0
  70. package/dist/api/advertisement.js.map +1 -0
  71. package/dist/boot/critical-style.d.ts +3 -0
  72. package/dist/boot/critical-style.d.ts.map +1 -0
  73. package/dist/boot/index.d.ts +15 -0
  74. package/dist/boot/index.d.ts.map +1 -0
  75. package/dist/boot.d.ts +1 -0
  76. package/dist/boot.js +69 -0
  77. package/dist/boot.js.map +1 -0
  78. package/dist/{chunk-R5BQDCDK.js → chunk-2HCCIHU7.js} +4 -4
  79. package/dist/{chunk-R5BQDCDK.js.map → chunk-2HCCIHU7.js.map} +1 -1
  80. package/dist/chunk-4FJGZQD3.js +6 -0
  81. package/dist/chunk-4FJGZQD3.js.map +1 -0
  82. package/dist/{chunk-UNEZZMQA.js → chunk-4WVJJ7SN.js} +20 -4
  83. package/dist/chunk-4WVJJ7SN.js.map +1 -0
  84. package/dist/{chunk-FFWSQJLV.js → chunk-BAYGWTNM.js} +3 -3
  85. package/dist/{chunk-FFWSQJLV.js.map → chunk-BAYGWTNM.js.map} +1 -1
  86. package/dist/{chunk-WSRVPR7V.js → chunk-CLBFF2CY.js} +3 -3
  87. package/dist/{chunk-WSRVPR7V.js.map → chunk-CLBFF2CY.js.map} +1 -1
  88. package/dist/chunk-DBW7XXNE.js +103 -0
  89. package/dist/chunk-DBW7XXNE.js.map +1 -0
  90. package/dist/{chunk-CCUE2FMU.js → chunk-DBXH3EMJ.js} +3 -3
  91. package/dist/{chunk-CCUE2FMU.js.map → chunk-DBXH3EMJ.js.map} +1 -1
  92. package/dist/{chunk-MECSOKS7.js → chunk-E26YG3AO.js} +4 -4
  93. package/dist/{chunk-MECSOKS7.js.map → chunk-E26YG3AO.js.map} +1 -1
  94. package/dist/{chunk-22SH7OVF.js → chunk-E7WWO3V3.js} +3 -3
  95. package/dist/{chunk-22SH7OVF.js.map → chunk-E7WWO3V3.js.map} +1 -1
  96. package/dist/{chunk-IC6XW3PD.js → chunk-HQ7WA37L.js} +7 -7
  97. package/dist/{chunk-IC6XW3PD.js.map → chunk-HQ7WA37L.js.map} +1 -1
  98. package/dist/chunk-IVBOLREE.js +29 -0
  99. package/dist/chunk-IVBOLREE.js.map +1 -0
  100. package/dist/{chunk-RRGEASAL.js → chunk-KP3VYG4F.js} +6 -6
  101. package/dist/{chunk-RRGEASAL.js.map → chunk-KP3VYG4F.js.map} +1 -1
  102. package/dist/{chunk-EFF2WO6W.js → chunk-PWTXR4RR.js} +10 -10
  103. package/dist/{chunk-EFF2WO6W.js.map → chunk-PWTXR4RR.js.map} +1 -1
  104. package/dist/chunk-QJYUTRAQ.js +14 -0
  105. package/dist/{chunk-4EA56R6I.js.map → chunk-QJYUTRAQ.js.map} +1 -1
  106. package/dist/{chunk-YFQUSAET.js → chunk-U55ZJC2X.js} +4 -4
  107. package/dist/{chunk-YFQUSAET.js.map → chunk-U55ZJC2X.js.map} +1 -1
  108. package/dist/{chunk-R54GSKJS.js → chunk-WSDG4ZRI.js} +30 -16
  109. package/dist/chunk-WSDG4ZRI.js.map +1 -0
  110. package/dist/{chunk-3PWARKZX.js → chunk-X54QP332.js} +8 -8
  111. package/dist/chunk-X54QP332.js.map +1 -0
  112. package/dist/components/cart/index.js +1 -1
  113. package/dist/components/common/index.js +1 -1
  114. package/dist/components/drawer/index.js +9 -7
  115. package/dist/components/home/HomePageRenderer.d.ts +6 -0
  116. package/dist/components/home/HomePageRenderer.d.ts.map +1 -1
  117. package/dist/components/home/index.js +11 -9
  118. package/dist/components/layout/PageAdvertisements.d.ts +7 -0
  119. package/dist/components/layout/PageAdvertisements.d.ts.map +1 -0
  120. package/dist/components/layout/index.d.ts +1 -0
  121. package/dist/components/layout/index.d.ts.map +1 -1
  122. package/dist/components/layout/index.js +8 -1
  123. package/dist/components/product/index.js +10 -8
  124. package/dist/components/store/index.js +11 -9
  125. package/dist/components/store/index.js.map +1 -1
  126. package/dist/{document-class-SD6BUMZN.js → document-class-7AXAAWGZ.js} +6 -5
  127. package/dist/{document-class-SD6BUMZN.js.map → document-class-7AXAAWGZ.js.map} +1 -1
  128. package/dist/hooks/index.js +9 -7
  129. package/dist/hooks/useGtm.js +9 -7
  130. package/dist/hooks/useMoney.js +9 -7
  131. package/dist/hooks/useStore.js +9 -7
  132. package/dist/index.js +9 -7
  133. package/dist/index.js.map +1 -1
  134. package/dist/{not-found-TUU7WQLL.js → not-found-3EEMQZMU.js} +11 -9
  135. package/dist/not-found-3EEMQZMU.js.map +1 -0
  136. package/dist/providers/index.js +9 -7
  137. package/dist/routes/account/orders.js +1 -1
  138. package/dist/routes/account.js +6 -6
  139. package/dist/routes/blog.js +5 -5
  140. package/dist/routes/brands.js +1 -1
  141. package/dist/routes/cart.js +13 -11
  142. package/dist/routes/cart.js.map +1 -1
  143. package/dist/routes/home.js +12 -10
  144. package/dist/routes/loyalty.js +2 -2
  145. package/dist/routes/page.js +1 -1
  146. package/dist/routes/product-listing.js +11 -9
  147. package/dist/routes/product-listing.js.map +1 -1
  148. package/dist/routes/product.js +11 -9
  149. package/dist/routes/product.js.map +1 -1
  150. package/dist/routes/root/beforeLoad.d.ts +2 -2
  151. package/dist/routes/root/beforeLoad.d.ts.map +1 -1
  152. package/dist/routes/root/head.d.ts.map +1 -1
  153. package/dist/routes/testimonials.js +2 -2
  154. package/dist/routes/thank-you.js +1 -1
  155. package/dist/skeleton.js +12 -10
  156. package/dist/tanstack/document-class.d.ts.map +1 -1
  157. package/dist/tanstack/index.d.ts +1 -0
  158. package/dist/tanstack/index.d.ts.map +1 -1
  159. package/dist/tanstack/stylesheet.d.ts +15 -0
  160. package/dist/tanstack/stylesheet.d.ts.map +1 -0
  161. package/dist/tanstack.js +34 -5
  162. package/dist/tanstack.js.map +1 -1
  163. package/dist/types/index.d.ts +5 -0
  164. package/dist/types/index.d.ts.map +1 -1
  165. package/dist/utils/index.js +1 -1
  166. package/dist/vite/index.js +1 -1
  167. package/package.json +12 -3
  168. package/tailwind/components/Component.tsx.txt +21 -0
  169. package/tailwind/components/ComponentRegistry.ts.txt +66 -0
  170. package/tailwind/components/cart/CartItem.tsx.txt +211 -0
  171. package/tailwind/components/cart/CartSummary.tsx.txt +269 -0
  172. package/tailwind/components/cart/PreOrderNotification.tsx.txt +16 -0
  173. package/tailwind/components/cart/PriceQuoteButton.tsx.txt +21 -0
  174. package/tailwind/components/cart/SeoCartWidget.tsx.txt +99 -0
  175. package/tailwind/components/cart/index.ts.txt +11 -0
  176. package/tailwind/components/cart/lazy.ts.txt +15 -0
  177. package/tailwind/components/collapse/Collapse.tsx.txt +95 -0
  178. package/tailwind/components/collapse/index.ts.txt +41 -0
  179. package/tailwind/components/common/Breadcrumb.tsx.txt +27 -0
  180. package/tailwind/components/common/BreadcrumbJsonLd.tsx.txt +40 -0
  181. package/tailwind/components/common/BreadcrumbTrail.tsx.txt +97 -0
  182. package/tailwind/components/common/CurrencySymbol.tsx.txt +8 -0
  183. package/tailwind/components/common/DeferredData.tsx.txt +122 -0
  184. package/tailwind/components/common/ErrorPage.tsx.txt +69 -0
  185. package/tailwind/components/common/Image.tsx.txt +119 -0
  186. package/tailwind/components/common/Link.tsx.txt +36 -0
  187. package/tailwind/components/common/Link.types.ts.txt +85 -0
  188. package/tailwind/components/common/NoContent.tsx.txt +27 -0
  189. package/tailwind/components/common/RenderWhenVisible.tsx.txt +92 -0
  190. package/tailwind/components/common/index.ts.txt +42 -0
  191. package/tailwind/components/common/lazy.ts.txt +28 -0
  192. package/tailwind/components/defineComponent.ts.txt +32 -0
  193. package/tailwind/components/drawer/Drawer.tsx.txt +219 -0
  194. package/tailwind/components/drawer/index.ts.txt +38 -0
  195. package/tailwind/components/dropdown/Dropdown.tsx.txt +166 -0
  196. package/tailwind/components/dropdown/index.ts.txt +40 -0
  197. package/tailwind/components/home/BundleComponent.tsx.txt +35 -0
  198. package/tailwind/components/home/ComponentErrorBoundary.tsx.txt +98 -0
  199. package/tailwind/components/home/FeaturedProductsStyle1.tsx.txt +125 -0
  200. package/tailwind/components/home/FeaturedProductsStyle2.tsx.txt +127 -0
  201. package/tailwind/components/home/FeaturedProductsStyle3.tsx.txt +71 -0
  202. package/tailwind/components/home/FixedBanner.tsx.txt +68 -0
  203. package/tailwind/components/home/FixedProducts.tsx.txt +72 -0
  204. package/tailwind/components/home/HomePageRenderer.tsx.txt +284 -0
  205. package/tailwind/components/home/PageBlocks.tsx.txt +24 -0
  206. package/tailwind/components/home/ParallaxBackground.tsx.txt +50 -0
  207. package/tailwind/components/home/PhotosSlider.tsx.txt +61 -0
  208. package/tailwind/components/home/ProductsSlider.tsx.txt +87 -0
  209. package/tailwind/components/home/ReorderProducts.tsx.txt +38 -0
  210. package/tailwind/components/home/SquarePhotos.tsx.txt +68 -0
  211. package/tailwind/components/home/StoreFeatures.tsx.txt +34 -0
  212. package/tailwind/components/home/Testimonials.tsx.txt +36 -0
  213. package/tailwind/components/home/Youtube.tsx.txt +48 -0
  214. package/tailwind/components/home/index.ts.txt +50 -0
  215. package/tailwind/components/home/lazy.ts.txt +17 -0
  216. package/tailwind/components/home/register.ts.txt +44 -0
  217. package/tailwind/components/home/reorder-hooks.ts.txt +52 -0
  218. package/tailwind/components/home/types.ts.txt +4 -0
  219. package/tailwind/components/layout/Copyright.tsx.txt +23 -0
  220. package/tailwind/components/layout/CustomerLayout.tsx.txt +91 -0
  221. package/tailwind/components/layout/Footer.tsx.txt +343 -0
  222. package/tailwind/components/layout/Header.tsx.txt +154 -0
  223. package/tailwind/components/layout/MasterLayout.tsx.txt +63 -0
  224. package/tailwind/components/layout/PageAdvertisements.tsx.txt +131 -0
  225. package/tailwind/components/layout/WidgetHead.tsx.txt +53 -0
  226. package/tailwind/components/layout/index.ts.txt +27 -0
  227. package/tailwind/components/layout/lazy.ts.txt +25 -0
  228. package/tailwind/components/layout/types.ts.txt +11 -0
  229. package/tailwind/components/modal/ImageModal.tsx.txt +70 -0
  230. package/tailwind/components/modal/Modal.tsx.txt +245 -0
  231. package/tailwind/components/modal/index.ts.txt +39 -0
  232. package/tailwind/components/modal/lazy.ts.txt +10 -0
  233. package/tailwind/components/navigation/MainMenu.tsx.txt +94 -0
  234. package/tailwind/components/navigation/MobileMenu.tsx.txt +160 -0
  235. package/tailwind/components/navigation/index.ts.txt +4 -0
  236. package/tailwind/components/navigation/lazy.ts.txt +11 -0
  237. package/tailwind/components/product/AddToCartForm.tsx.txt +365 -0
  238. package/tailwind/components/product/ProductCard.tsx.txt +305 -0
  239. package/tailwind/components/product/ProductDetails.tsx.txt +267 -0
  240. package/tailwind/components/product/ProductGallery.tsx.txt +234 -0
  241. package/tailwind/components/product/index.ts.txt +15 -0
  242. package/tailwind/components/product/lazy.ts.txt +9 -0
  243. package/tailwind/components/snippets/AppsSnippets.tsx.txt +225 -0
  244. package/tailwind/components/snippets/SallaSdkScripts.tsx.txt +14 -0
  245. package/tailwind/components/snippets/index.ts.txt +4 -0
  246. package/tailwind/components/store/StoreClosedNotification.tsx.txt +73 -0
  247. package/tailwind/components/store/index.ts.txt +8 -0
  248. package/tailwind/components/store/lazy.ts.txt +8 -0
  249. package/tailwind/components/toast/Toaster.tsx.txt +177 -0
  250. package/tailwind/components/toast/index.ts.txt +10 -0
  251. package/tailwind/components/toast/types.ts.txt +38 -0
  252. package/tailwind/components/toast/useToast.ts.txt +61 -0
  253. package/tailwind/components/tracking/GoogleTag.tsx.txt +77 -0
  254. package/tailwind/components/tracking/SiftSnippet.tsx.txt +49 -0
  255. package/tailwind/components/tracking/TwilightBundles.tsx.txt +67 -0
  256. package/tailwind/components/tracking/index.ts.txt +11 -0
  257. package/tailwind/components/tracking/lazy.ts.txt +11 -0
  258. package/tailwind/components/useComponent.ts.txt +12 -0
  259. package/tailwind/routes/account/index.tsx.txt +16 -0
  260. package/tailwind/routes/account/notifications/NotificationsPage.tsx.txt +54 -0
  261. package/tailwind/routes/account/notifications/index.tsx.txt +39 -0
  262. package/tailwind/routes/account/notifications/loader.ts.txt +22 -0
  263. package/tailwind/routes/account/notifications/types.ts.txt +18 -0
  264. package/tailwind/routes/account/orders/OrderSinglePage.tsx.txt +181 -0
  265. package/tailwind/routes/account/orders/OrdersPage.tsx.txt +28 -0
  266. package/tailwind/routes/account/orders/index.tsx.txt +86 -0
  267. package/tailwind/routes/account/orders/loader.ts.txt +66 -0
  268. package/tailwind/routes/account/orders/single/OrderActions.tsx.txt +197 -0
  269. package/tailwind/routes/account/orders/single/OrderHeader.tsx.txt +143 -0
  270. package/tailwind/routes/account/orders/single/OrderItemRow.tsx.txt +209 -0
  271. package/tailwind/routes/account/orders/single/OrderSections.tsx.txt +215 -0
  272. package/tailwind/routes/account/orders/single/types.ts.txt +38 -0
  273. package/tailwind/routes/account/orders/types.ts.txt +29 -0
  274. package/tailwind/routes/account/profile/ProfilePage.tsx.txt +30 -0
  275. package/tailwind/routes/account/profile/index.tsx.txt +39 -0
  276. package/tailwind/routes/account/profile/loader.ts.txt +16 -0
  277. package/tailwind/routes/account/profile/types.ts.txt +5 -0
  278. package/tailwind/routes/account/settings/SettingsPage.tsx.txt +13 -0
  279. package/tailwind/routes/account/settings/index.tsx.txt +39 -0
  280. package/tailwind/routes/account/settings/loader.ts.txt +13 -0
  281. package/tailwind/routes/account/settings/types.ts.txt +5 -0
  282. package/tailwind/routes/account/types.ts.txt +320 -0
  283. package/tailwind/routes/account/wallet/WalletPage.tsx.txt +195 -0
  284. package/tailwind/routes/account/wallet/index.tsx.txt +38 -0
  285. package/tailwind/routes/account/wallet/loader.ts.txt +27 -0
  286. package/tailwind/routes/account/wallet/types.ts.txt +11 -0
  287. package/tailwind/routes/account/wishlist/WishlistPage.tsx.txt +314 -0
  288. package/tailwind/routes/account/wishlist/WishlistShare.tsx.txt +248 -0
  289. package/tailwind/routes/account/wishlist/index.tsx.txt +40 -0
  290. package/tailwind/routes/account/wishlist/loader.ts.txt +26 -0
  291. package/tailwind/routes/account/wishlist/types.ts.txt +9 -0
  292. package/tailwind/routes/blog/BlogAuthorPage.tsx.txt +82 -0
  293. package/tailwind/routes/blog/BlogCategoryPage.tsx.txt +84 -0
  294. package/tailwind/routes/blog/BlogPage.tsx.txt +191 -0
  295. package/tailwind/routes/blog/BlogSinglePage.tsx.txt +168 -0
  296. package/tailwind/routes/blog/BlogTagPage.tsx.txt +84 -0
  297. package/tailwind/routes/blog/BlogTags.tsx.txt +54 -0
  298. package/tailwind/routes/blog/components.tsx.txt +87 -0
  299. package/tailwind/routes/blog/index.tsx.txt +238 -0
  300. package/tailwind/routes/blog/loader.ts.txt +173 -0
  301. package/tailwind/routes/blog/types.ts.txt +106 -0
  302. package/tailwind/routes/brands/BrandsPage.tsx.txt +179 -0
  303. package/tailwind/routes/brands/index.tsx.txt +47 -0
  304. package/tailwind/routes/brands/loader.ts.txt +14 -0
  305. package/tailwind/routes/brands/types.ts.txt +53 -0
  306. package/tailwind/routes/cart/CartPage.tsx.txt +112 -0
  307. package/tailwind/routes/cart/index.tsx.txt +39 -0
  308. package/tailwind/routes/cart/loader.ts.txt +15 -0
  309. package/tailwind/routes/cart/types.ts.txt +6 -0
  310. package/tailwind/routes/home/HomePage.tsx.txt +53 -0
  311. package/tailwind/routes/home/index.tsx.txt +56 -0
  312. package/tailwind/routes/home/loader.ts.txt +24 -0
  313. package/tailwind/routes/home/types.ts.txt +11 -0
  314. package/tailwind/routes/index.ts.txt +94 -0
  315. package/tailwind/routes/lazy.ts.txt +105 -0
  316. package/tailwind/routes/loyalty/LoyaltyPage.tsx.txt +17 -0
  317. package/tailwind/routes/loyalty/LoyaltyPointsPage.tsx.txt +11 -0
  318. package/tailwind/routes/loyalty/index.tsx.txt +81 -0
  319. package/tailwind/routes/loyalty/loader.ts.txt +53 -0
  320. package/tailwind/routes/loyalty/types.ts.txt +109 -0
  321. package/tailwind/routes/not-found.tsx.txt +50 -0
  322. package/tailwind/routes/page/PageSingle.tsx.txt +34 -0
  323. package/tailwind/routes/page/index.tsx.txt +60 -0
  324. package/tailwind/routes/page/loader.ts.txt +19 -0
  325. package/tailwind/routes/page/types.ts.txt +34 -0
  326. package/tailwind/routes/product/ProductPage.tsx.txt +77 -0
  327. package/tailwind/routes/product/index.tsx.txt +157 -0
  328. package/tailwind/routes/product/loader.ts.txt +35 -0
  329. package/tailwind/routes/product/types.ts.txt +6 -0
  330. package/tailwind/routes/product-listing/ProductListPage.tsx.txt +321 -0
  331. package/tailwind/routes/product-listing/index.tsx.txt +95 -0
  332. package/tailwind/routes/product-listing/loader.ts.txt +323 -0
  333. package/tailwind/routes/product-listing/types.ts.txt +96 -0
  334. package/tailwind/routes/product-listing/useAppliedFilters.ts.txt +130 -0
  335. package/tailwind/routes/product-short-link.ts.txt +104 -0
  336. package/tailwind/routes/root/beforeLoad.ts.txt +354 -0
  337. package/tailwind/routes/root/head.ts.txt +424 -0
  338. package/tailwind/routes/root/index.ts.txt +2 -0
  339. package/tailwind/routes/seo-redirects.ts.txt +82 -0
  340. package/tailwind/routes/testimonials/ReviewsPage.tsx.txt +12 -0
  341. package/tailwind/routes/testimonials/TestimonialsPage.tsx.txt +80 -0
  342. package/tailwind/routes/testimonials/index.tsx.txt +80 -0
  343. package/tailwind/routes/testimonials/loader.ts.txt +29 -0
  344. package/tailwind/routes/testimonials/types.ts.txt +9 -0
  345. package/tailwind/routes/thank-you/ThankYouPage.tsx.txt +241 -0
  346. package/tailwind/routes/thank-you/index.tsx.txt +49 -0
  347. package/tailwind/routes/thank-you/loader.ts.txt +40 -0
  348. package/tailwind/routes/thank-you/types.ts.txt +16 -0
  349. package/tailwind/routes/types.ts.txt +41 -0
  350. package/dist/BlogAuthorPage-LFAUMKC7.js.map +0 -1
  351. package/dist/BlogCategoryPage-NWYFFPCD.js.map +0 -1
  352. package/dist/BlogPage-BOHXFV7E.js.map +0 -1
  353. package/dist/BlogSinglePage-FYEXQPMB.js.map +0 -1
  354. package/dist/BlogTagPage-DAM3RNVA.js.map +0 -1
  355. package/dist/BrandsPage-GAKQCE6O.js.map +0 -1
  356. package/dist/Breadcrumb-NAYSZNRV.js.map +0 -1
  357. package/dist/CartItem-ZRVLIZT3.js.map +0 -1
  358. package/dist/CartSummary-U2TVLG35.js.map +0 -1
  359. package/dist/CustomerLayout-WSKXWI7D.js.map +0 -1
  360. package/dist/LoyaltyPage-IG5KSYNO.js.map +0 -1
  361. package/dist/LoyaltyPointsPage-RKO56ZER.js.map +0 -1
  362. package/dist/MobileMenu-E4X2GOZ3.js.map +0 -1
  363. package/dist/NotificationsPage-BJ5XVWEG.js.map +0 -1
  364. package/dist/OrderSinglePage-544E36FJ.js.map +0 -1
  365. package/dist/OrdersPage-AFBWVTZU.js.map +0 -1
  366. package/dist/ProductDetails-SDZHALU6.js.map +0 -1
  367. package/dist/ProfilePage-V5KV6GQK.js.map +0 -1
  368. package/dist/SeoCartWidget-JAV6M3X5.js.map +0 -1
  369. package/dist/SettingsPage-43SUCLQR.js.map +0 -1
  370. package/dist/ThankYouPage-52SSZ7FV.js.map +0 -1
  371. package/dist/WalletPage-4AN4UJ52.js.map +0 -1
  372. package/dist/WishlistPage-L6IYJUJZ.js.map +0 -1
  373. package/dist/chunk-3PWARKZX.js.map +0 -1
  374. package/dist/chunk-4EA56R6I.js +0 -14
  375. package/dist/chunk-R54GSKJS.js.map +0 -1
  376. package/dist/chunk-UNEZZMQA.js.map +0 -1
  377. package/dist/not-found-TUU7WQLL.js.map +0 -1
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Drawer Component System
3
+ *
4
+ * A slide-in panel for mobile navigation and side content.
5
+ * Eager-loaded because it uses compound component pattern (Drawer.Header, Drawer.Body).
6
+ *
7
+ * @example
8
+ * ```tsx
9
+ * import { Drawer } from '@salla.sa/twilight-theme-engine/components/drawer';
10
+ *
11
+ * function MobileNav() {
12
+ * const [isOpen, setIsOpen] = useState(false);
13
+ *
14
+ * return (
15
+ * <>
16
+ * <button onClick={() => setIsOpen(true)}>☰ Menu</button>
17
+ * <Drawer isOpen={isOpen} onClose={() => setIsOpen(false)} position="left">
18
+ * <Drawer.Header onClose={() => setIsOpen(false)}>Menu</Drawer.Header>
19
+ * <Drawer.Body>
20
+ * <nav className="space-y-2">
21
+ * <a href="/" className="block py-2">Home</a>
22
+ * <a href="/products" className="block py-2">Products</a>
23
+ * </nav>
24
+ * </Drawer.Body>
25
+ * </Drawer>
26
+ * </>
27
+ * );
28
+ * }
29
+ * ```
30
+ */
31
+
32
+ export {
33
+ Drawer,
34
+ type DrawerProps,
35
+ type DrawerHeaderProps,
36
+ type DrawerBodyProps,
37
+ type DrawerFooterProps,
38
+ } from './Drawer';
@@ -0,0 +1,166 @@
1
+ /**
2
+ * Dropdown Component
3
+ *
4
+ * A controlled dropdown menu with keyboard navigation and click-away support.
5
+ *
6
+ * @example
7
+ * ```tsx
8
+ * function UserMenu() {
9
+ * const [isOpen, setIsOpen] = useState(false);
10
+ *
11
+ * return (
12
+ * <Dropdown isOpen={isOpen} onClose={() => setIsOpen(false)}>
13
+ * <Dropdown.Trigger onClick={() => setIsOpen(!isOpen)}>
14
+ * <button>Account ▼</button>
15
+ * </Dropdown.Trigger>
16
+ * <Dropdown.Menu>
17
+ * <Dropdown.Item href="/profile">Profile</Dropdown.Item>
18
+ * <Dropdown.Item href="/orders">Orders</Dropdown.Item>
19
+ * <Dropdown.Item onClick={handleLogout}>Logout</Dropdown.Item>
20
+ * </Dropdown.Menu>
21
+ * </Dropdown>
22
+ * );
23
+ * }
24
+ * ```
25
+ */
26
+
27
+ import { type ReactNode, type HTMLAttributes } from 'react';
28
+ import { useClickAway } from '@uidotdev/usehooks';
29
+
30
+ export interface DropdownProps {
31
+ isOpen: boolean;
32
+ onClose: () => void;
33
+ children: ReactNode;
34
+ /**
35
+ * Position of the dropdown menu
36
+ * @default 'bottom-start'
37
+ */
38
+ position?: 'bottom-start' | 'bottom-end' | 'top-start' | 'top-end';
39
+ /**
40
+ * Additional className for the dropdown container
41
+ */
42
+ className?: string;
43
+ }
44
+
45
+ const positionClasses = {
46
+ 'bottom-start': 'top-full start-0',
47
+ 'bottom-end': 'top-full end-0',
48
+ 'top-start': 'bottom-full start-0',
49
+ 'top-end': 'bottom-full end-0',
50
+ };
51
+
52
+ export function Dropdown({ isOpen, onClose, children, className }: DropdownProps) {
53
+ // useClickAway returns a ref that we attach to the container
54
+ // It calls the callback when clicking outside the element
55
+ const dropdownRef = useClickAway<HTMLDivElement>(() => {
56
+ if (isOpen) {
57
+ onClose();
58
+ }
59
+ });
60
+
61
+ return (
62
+ <div ref={dropdownRef} className={`relative inline-block ${className || ''}`}>
63
+ {children}
64
+ </div>
65
+ );
66
+ }
67
+
68
+ // Trigger Component
69
+ export interface DropdownTriggerProps extends HTMLAttributes<HTMLDivElement> {
70
+ children: ReactNode;
71
+ }
72
+
73
+ Dropdown.Trigger = function DropdownTrigger({
74
+ children,
75
+ className,
76
+ ...props
77
+ }: DropdownTriggerProps) {
78
+ return (
79
+ <div className={`inline-block ${className || ''}`} {...props}>
80
+ {children}
81
+ </div>
82
+ );
83
+ };
84
+
85
+ // Menu Component
86
+ export interface DropdownMenuProps extends HTMLAttributes<HTMLUListElement> {
87
+ children: ReactNode;
88
+ isOpen?: boolean;
89
+ position?: DropdownProps['position'];
90
+ }
91
+
92
+ Dropdown.Menu = function DropdownMenu({
93
+ children,
94
+ isOpen = false,
95
+ position = 'bottom-start',
96
+ className,
97
+ ...props
98
+ }: DropdownMenuProps) {
99
+ if (!isOpen) {
100
+ return null;
101
+ }
102
+
103
+ return (
104
+ <ul
105
+ className={`absolute z-40 mt-1 min-w-[10rem] rounded-lg bg-white py-1 shadow-lg ring-1 ring-black/5 animate-in fade-in slide-in-from-top-1 duration-100 ${positionClasses[position]} ${className || ''}`}
106
+ role="menu"
107
+ {...props}
108
+ >
109
+ {children}
110
+ </ul>
111
+ );
112
+ };
113
+
114
+ // Item Component
115
+ export interface DropdownItemProps extends HTMLAttributes<HTMLLIElement> {
116
+ children: ReactNode;
117
+ href?: string;
118
+ onClick?: () => void;
119
+ disabled?: boolean;
120
+ active?: boolean;
121
+ }
122
+
123
+ Dropdown.Item = function DropdownItem({
124
+ children,
125
+ href,
126
+ onClick,
127
+ disabled = false,
128
+ active = false,
129
+ className,
130
+ ...props
131
+ }: DropdownItemProps) {
132
+ const classes = `flex cursor-pointer items-center px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900 ${active ? 'bg-gray-100 text-gray-900' : ''} ${disabled ? 'cursor-not-allowed opacity-50 hover:bg-transparent' : ''} ${className || ''}`;
133
+
134
+ if (href) {
135
+ return (
136
+ <li role="menuitem" {...props}>
137
+ <a href={href} className={classes}>
138
+ {children}
139
+ </a>
140
+ </li>
141
+ );
142
+ }
143
+
144
+ return (
145
+ <li
146
+ role="menuitem"
147
+ onClick={disabled ? undefined : onClick}
148
+ onKeyDown={(e) => {
149
+ if (!disabled && (e.key === 'Enter' || e.key === ' ')) {
150
+ e.preventDefault();
151
+ onClick?.();
152
+ }
153
+ }}
154
+ tabIndex={disabled ? -1 : 0}
155
+ className={classes}
156
+ {...props}
157
+ >
158
+ {children}
159
+ </li>
160
+ );
161
+ };
162
+
163
+ // Divider Component
164
+ Dropdown.Divider = function DropdownDivider({ className }: HTMLAttributes<HTMLLIElement>) {
165
+ return <li className={`my-1 h-px bg-gray-200 ${className || ''}`} />;
166
+ };
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Dropdown Component System
3
+ *
4
+ * A controlled dropdown menu with keyboard navigation.
5
+ * Eager-loaded because it uses compound component pattern (Dropdown.Trigger, Dropdown.Menu).
6
+ *
7
+ * @example
8
+ * ```tsx
9
+ * import { Dropdown } from '@salla.sa/twilight-theme-engine/components/dropdown';
10
+ *
11
+ * function SortDropdown() {
12
+ * const [isOpen, setIsOpen] = useState(false);
13
+ * const [sort, setSort] = useState('newest');
14
+ *
15
+ * return (
16
+ * <Dropdown isOpen={isOpen} onClose={() => setIsOpen(false)}>
17
+ * <Dropdown.Trigger onClick={() => setIsOpen(!isOpen)}>
18
+ * <button>Sort: {sort}</button>
19
+ * </Dropdown.Trigger>
20
+ * <Dropdown.Menu isOpen={isOpen}>
21
+ * <Dropdown.Item onClick={() => { setSort('newest'); setIsOpen(false); }}>
22
+ * Newest
23
+ * </Dropdown.Item>
24
+ * <Dropdown.Item onClick={() => { setSort('price-asc'); setIsOpen(false); }}>
25
+ * Price: Low to High
26
+ * </Dropdown.Item>
27
+ * </Dropdown.Menu>
28
+ * </Dropdown>
29
+ * );
30
+ * }
31
+ * ```
32
+ */
33
+
34
+ export {
35
+ Dropdown,
36
+ type DropdownProps,
37
+ type DropdownTriggerProps,
38
+ type DropdownMenuProps,
39
+ type DropdownItemProps,
40
+ } from './Dropdown';
@@ -0,0 +1,35 @@
1
+ import { memo, useState, useEffect } from 'react';
2
+
3
+ export interface BundleComponentProps {
4
+ data: {
5
+ component_name: string;
6
+ bundle_id: string;
7
+ [key: string]: unknown;
8
+ };
9
+ }
10
+
11
+ export const BundleComponent = memo(function BundleComponent(props: BundleComponentProps) {
12
+ const [mounted, setMounted] = useState(false);
13
+
14
+ useEffect(() => {
15
+ setMounted(true);
16
+ }, []);
17
+
18
+ if (!mounted) {
19
+ return null;
20
+ }
21
+
22
+ const { component_name: componentName, bundle_id: bundleId, ...rest } = props.data;
23
+ const config = JSON.stringify(rest);
24
+
25
+ return (
26
+ <>
27
+ <salla-custom-component
28
+ component-name={componentName}
29
+ bundle-id={bundleId}
30
+ config={config}
31
+ suppressHydrationWarning
32
+ />
33
+ </>
34
+ );
35
+ });
@@ -0,0 +1,98 @@
1
+ import { Component, type ReactNode, type ErrorInfo } from 'react';
2
+ import { TwilightContext } from '../../providers/twilight-context';
3
+ import type { TwilightContextValue } from '../../types/twilight';
4
+ import type { HomeComponentData } from '../../types';
5
+
6
+ interface ComponentErrorBoundaryProps {
7
+ children: ReactNode;
8
+ data: HomeComponentData;
9
+ position: number;
10
+ }
11
+
12
+ interface ComponentErrorBoundaryState {
13
+ hasError: boolean;
14
+ error: Error | null;
15
+ }
16
+
17
+ function DevelopmentErrorCard({ error, data }: { error: Error; data: HomeComponentData }) {
18
+ return (
19
+ <section
20
+ dir="ltr"
21
+ className="s-block container overflow-hidden bg-red-50 border border-red-300 p-4"
22
+ >
23
+ <p className="text-red-800 text-sm font-bold">Home Component Error: {data.path}</p>
24
+ <p className="text-red-700 text-sm mt-2">{error.message}</p>
25
+ <details className="mt-2">
26
+ <summary className="text-xs cursor-pointer text-red-600">Stack Trace</summary>
27
+ <pre className="text-xs mt-1 overflow-auto max-h-32 text-red-700">{error.stack}</pre>
28
+ </details>
29
+ <details className="mt-2">
30
+ <summary className="text-xs cursor-pointer text-red-600">Component Data</summary>
31
+ <pre className="text-xs mt-1 overflow-auto max-h-32 text-red-700">
32
+ {JSON.stringify(data, null, 2)}
33
+ </pre>
34
+ </details>
35
+ </section>
36
+ );
37
+ }
38
+
39
+ export class ComponentErrorBoundary extends Component<
40
+ ComponentErrorBoundaryProps,
41
+ ComponentErrorBoundaryState
42
+ > {
43
+ static contextType = TwilightContext;
44
+
45
+ declare context: TwilightContextValue | null;
46
+
47
+ constructor(props: ComponentErrorBoundaryProps) {
48
+ super(props);
49
+ this.state = { hasError: false, error: null };
50
+ }
51
+
52
+ static getDerivedStateFromError(error: Error): ComponentErrorBoundaryState {
53
+ return { hasError: true, error };
54
+ }
55
+
56
+ // Blocks are keyed by position, so a replacement block at the same position reuses
57
+ // this boundary. An error belongs to the block that threw it, not the position.
58
+ componentDidUpdate(prevProps: ComponentErrorBoundaryProps): void {
59
+ if (this.state.hasError && prevProps.data !== this.props.data) {
60
+ this.setState({ hasError: false, error: null });
61
+ }
62
+ }
63
+
64
+ componentDidCatch(error: Error, errorInfo: ErrorInfo): void {
65
+ if (!this.context) {
66
+ console.error('[ComponentErrorBoundary] Must be used within TwilightProvider');
67
+ return;
68
+ }
69
+ const { log } = this.context;
70
+ const { data, position } = this.props;
71
+
72
+ log.groupCollapsed(`HomeComponent Error: ${data.path || 'unknown'}`);
73
+ log.error('ERROR', error.message);
74
+ log.label('COMPONENT', data.path || 'unknown');
75
+ log.label('POSITION', position);
76
+ log.label('URL', typeof window !== 'undefined' ? window.location.href : 'SSR');
77
+ log.label('TIME', new Date().toISOString());
78
+ log.trace('STACK TRACE', error.stack || '');
79
+ log.trace('COMPONENT STACK', errorInfo.componentStack || '');
80
+ log.dir('COMPONENT DATA', data);
81
+ log.groupEnd();
82
+ }
83
+
84
+ render(): ReactNode {
85
+ const { hasError, error } = this.state;
86
+ const { children, data } = this.props;
87
+
88
+ if (hasError && error) {
89
+ if (process.env.NODE_ENV === 'production') {
90
+ return null;
91
+ }
92
+
93
+ return <DevelopmentErrorCard error={error} data={data} />;
94
+ }
95
+
96
+ return children;
97
+ }
98
+ }
@@ -0,0 +1,125 @@
1
+ import { memo, useState, useCallback } from 'react';
2
+ import { SallaButton } from '@salla.sa/twilight-components-react/button';
3
+ import type { Product } from '../../types';
4
+
5
+ interface SectionItem {
6
+ title?: string;
7
+ name?: string;
8
+ type?: string;
9
+ id?: string;
10
+ products?: Product[];
11
+ limit?: number;
12
+ }
13
+
14
+ interface MainProduct {
15
+ id?: string;
16
+ title?: string;
17
+ value?: string;
18
+ product?: Product;
19
+ }
20
+
21
+ export interface FeaturedProductsStyle1Props {
22
+ data: {
23
+ items: SectionItem[];
24
+ main_product?: MainProduct;
25
+ position?: number;
26
+ [key: string]: unknown;
27
+ };
28
+ }
29
+
30
+ export const FeaturedProductsStyle1 = memo(function FeaturedProductsStyle1({
31
+ data,
32
+ }: FeaturedProductsStyle1Props) {
33
+ const items = data.items || [];
34
+ const mainProduct = data.main_product;
35
+
36
+ const [activeTab, setActiveTab] = useState<string>(items[0]?.id || '');
37
+ const [isAnimating, setIsAnimating] = useState(false);
38
+
39
+ const handleTabClick = useCallback(
40
+ (tabId: string) => {
41
+ if (tabId === activeTab) return;
42
+ setIsAnimating(true);
43
+ setActiveTab(tabId);
44
+ setTimeout(() => setIsAnimating(false), 100);
45
+ },
46
+ [activeTab]
47
+ );
48
+
49
+ if (!items.length) return null;
50
+
51
+ const hasMultipleSections = items.length > 1;
52
+
53
+ return (
54
+ <>
55
+ <div className="s-block__title">
56
+ <div className="right-side">
57
+ <h2>{mainProduct?.title}</h2>
58
+ </div>
59
+ {hasMultipleSections && (
60
+ <div className="tabs hide-scroll hidden lg:flex">
61
+ {items.map((section) => (
62
+ <SallaButton
63
+ key={section.id}
64
+ shape="link"
65
+ onClick={() => handleTabClick(section.id || '')}
66
+ className={`tab-trigger ${activeTab === section.id ? 'is-active' : ''}`}
67
+ >
68
+ {section.title || section.name}
69
+ </SallaButton>
70
+ ))}
71
+ </div>
72
+ )}
73
+ </div>
74
+
75
+ <div className={`grid grid-cols-1 gap-8 ${mainProduct?.product ? 'lg:grid-cols-2' : ''}`}>
76
+ {mainProduct?.product && (
77
+ <div className="flex flex-col">
78
+ <custom-salla-product-card
79
+ shadow-on-hover
80
+ product={JSON.stringify(mainProduct.product)}
81
+ isSpecial
82
+ ></custom-salla-product-card>
83
+ </div>
84
+ )}
85
+ <div className="flex flex-col">
86
+ {hasMultipleSections && (
87
+ <div className="tabs mb-4 sm:mb-8 hide-scroll lg:hidden">
88
+ {items.map((section) => (
89
+ <SallaButton
90
+ key={section.id}
91
+ shape="link"
92
+ onClick={() => handleTabClick(section.id || '')}
93
+ className={`tab-trigger ${activeTab === section.id ? 'is-active' : ''}`}
94
+ >
95
+ {section.title || section.name}
96
+ </SallaButton>
97
+ ))}
98
+ </div>
99
+ )}
100
+
101
+ <div className="tabs-wrapper flex flex-1">
102
+ {items.map((section) => {
103
+ const isActive = activeTab === section.id;
104
+ return (
105
+ <div
106
+ key={section.id}
107
+ className={`tabs__item grid-cols-2 ${mainProduct?.product ? '' : 'lg:grid-cols-4'} ${isActive ? 'is-active' : ''} ${isAnimating && isActive ? 'opacity-0 translate-y-3' : ''} ${!isAnimating && isActive ? 'opacity-100 translate-y-0' : ''}`}
108
+ >
109
+ {section.products
110
+ ?.slice(0, mainProduct?.product ? 4 : 8)
111
+ .map((product, productIndex) => (
112
+ <custom-salla-product-card
113
+ key={product.id || productIndex}
114
+ product={JSON.stringify(product)}
115
+ ></custom-salla-product-card>
116
+ ))}
117
+ </div>
118
+ );
119
+ })}
120
+ </div>
121
+ </div>
122
+ </div>
123
+ </>
124
+ );
125
+ });
@@ -0,0 +1,127 @@
1
+ import { memo, useState, useCallback } from 'react';
2
+ import { SallaButton } from '@salla.sa/twilight-components-react/button';
3
+ import { SallaProductsList } from '@salla.sa/twilight-components-react';
4
+ import { SallaProductsSlider } from '@salla.sa/twilight-components-react';
5
+ import { product, ProductsListSource } from '../../api/product';
6
+ import { ProductCard } from '../../components/product';
7
+
8
+ interface ProductSource {
9
+ source: ProductsListSource;
10
+ limit?: number;
11
+ source_value?: number | number[];
12
+ }
13
+
14
+ interface SectionItem {
15
+ title?: string;
16
+ name?: string;
17
+ type?: string;
18
+ id?: string;
19
+ products: ProductSource;
20
+ limit?: number;
21
+ }
22
+
23
+ export interface FeaturedProductsStyle2Props {
24
+ data: {
25
+ items: SectionItem[];
26
+ position?: number;
27
+ is_slider?: boolean;
28
+ [key: string]: unknown;
29
+ };
30
+ }
31
+
32
+ export const FeaturedProductsStyle2 = memo(function FeaturedProductsStyle2({
33
+ data,
34
+ }: FeaturedProductsStyle2Props) {
35
+ const items = data.items || [];
36
+ const isSlider = data.is_slider ?? true;
37
+
38
+ const [activeTab, setActiveTab] = useState<string>(items[0]?.id || '');
39
+ const [isAnimating, setIsAnimating] = useState(false);
40
+
41
+ const handleTabClick = useCallback(
42
+ (tabId: string) => {
43
+ if (tabId === activeTab) return;
44
+ setIsAnimating(true);
45
+ setActiveTab(tabId);
46
+ setTimeout(() => setIsAnimating(false), 100);
47
+ },
48
+ [activeTab]
49
+ );
50
+
51
+ const loader = useCallback(
52
+ (source: ProductsListSource, value?: number | number[], limit?: number) => {
53
+ return () =>
54
+ product.list({
55
+ source: source,
56
+ sourceValue: value,
57
+ perPage: limit,
58
+ });
59
+ },
60
+ []
61
+ );
62
+
63
+ if (!items.length) return null;
64
+
65
+ const hasMultipleSections = items.length > 1;
66
+
67
+ return (
68
+ <>
69
+ <div className="container">
70
+ {hasMultipleSections && (
71
+ <div className="tabs hide-scroll">
72
+ {items.map((section) => (
73
+ <SallaButton
74
+ key={section.id}
75
+ fill="outline"
76
+ onClick={() => handleTabClick(section.id || '')}
77
+ className={`tab-trigger ${activeTab === section.id ? 'is-active' : ''}`}
78
+ >
79
+ {section.title || section.name}
80
+ </SallaButton>
81
+ ))}
82
+ </div>
83
+ )}
84
+
85
+ <div className="tabs-wrapper">
86
+ {items.map((section) => {
87
+ const isActive = activeTab === section.id;
88
+ return (
89
+ <div
90
+ key={section.id}
91
+ className={`tabs__item ${isActive ? 'is-active' : ''} ${isAnimating && isActive ? 'opacity-0 translate-y-3' : ''} ${!isAnimating && isActive ? 'opacity-100 translate-y-0' : ''}`}
92
+ >
93
+ {isSlider ? (
94
+ <SallaProductsSlider
95
+ loader={loader(
96
+ section.products.source,
97
+ section.products?.source_value,
98
+ section.products?.limit
99
+ )}
100
+ sliderProps={{ id: `section-${section.id}-slider` }}
101
+ >
102
+ {(product) => (
103
+ <ProductCard className="s-products-slider-card" product={product} />
104
+ )}
105
+ </SallaProductsSlider>
106
+ ) : (
107
+ <SallaProductsList
108
+ loader={loader(
109
+ section.products.source,
110
+ section.products?.source_value,
111
+ section.products?.limit
112
+ )}
113
+ itemsClassName="s-products-list-horizontal-cards"
114
+ >
115
+ {(products) =>
116
+ products.map((product) => <ProductCard key={product.id} product={product} />)
117
+ }
118
+ </SallaProductsList>
119
+ )}
120
+ </div>
121
+ );
122
+ })}
123
+ </div>
124
+ </div>
125
+ </>
126
+ );
127
+ });
@@ -0,0 +1,71 @@
1
+ import { memo } from 'react';
2
+ import { ProductCard } from '../product/ProductCard';
3
+ import type { Product } from '../../types';
4
+
5
+ interface SectionItem {
6
+ title?: string;
7
+ name?: string;
8
+ type?: string;
9
+ products?: Product[];
10
+ featured_product?: Product;
11
+ limit?: number;
12
+ id?: string;
13
+ }
14
+
15
+ export interface FeaturedProductsStyle3Props {
16
+ data: {
17
+ items: SectionItem[];
18
+ position?: number;
19
+ [key: string]: unknown;
20
+ };
21
+ }
22
+
23
+ export const FeaturedProductsStyle3 = memo(function FeaturedProductsStyle3({
24
+ data,
25
+ }: FeaturedProductsStyle3Props) {
26
+ const items = data.items || [];
27
+
28
+ if (!items.length) return null;
29
+
30
+ return (
31
+ <>
32
+ <div className="inner">
33
+ {items.map((section, sectionIndex) => (
34
+ <div key={section.id || sectionIndex}>
35
+ <div className="s-block__title">
36
+ <h2>{section.title}</h2>
37
+ </div>
38
+ <div className="flex-1 grid lg:grid-cols-2 gap-4 sm:gap-8">
39
+ {section.featured_product ? (
40
+ <>
41
+ <ProductCard product={section.featured_product} layout="fullImage" withShadow />
42
+ <div className="grid gap-4 sm:gap-8">
43
+ {section.products?.slice(0, 3).map((product, idx) => (
44
+ <ProductCard
45
+ key={product.id}
46
+ product={product}
47
+ layout="minimal"
48
+ withShadow
49
+ index={idx}
50
+ />
51
+ ))}
52
+ </div>
53
+ </>
54
+ ) : (
55
+ section.products?.map((product, idx) => (
56
+ <ProductCard
57
+ key={product.id}
58
+ product={product}
59
+ layout="minimal"
60
+ withShadow
61
+ index={idx}
62
+ />
63
+ ))
64
+ )}
65
+ </div>
66
+ </div>
67
+ ))}
68
+ </div>
69
+ </>
70
+ );
71
+ });