@salla.sa/twilight-theme-engine 1.0.85 → 1.0.87

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 (390) hide show
  1. package/README.md +4 -3
  2. package/bin/twilight-check-manifest.mjs +16 -0
  3. package/dist/{AddToCartForm-B5C2M4OZ.js → AddToCartForm-P644O2QL.js} +4 -4
  4. package/dist/{AddToCartForm-B5C2M4OZ.js.map → AddToCartForm-P644O2QL.js.map} +1 -1
  5. package/dist/{BlogAuthorPage-GTF4UGSS.js → BlogAuthorPage-VWSO6MPY.js} +13 -11
  6. package/dist/BlogAuthorPage-VWSO6MPY.js.map +1 -0
  7. package/dist/{BlogCategoryPage-TN7Y4NBP.js → BlogCategoryPage-K2KSQ6T6.js} +13 -11
  8. package/dist/BlogCategoryPage-K2KSQ6T6.js.map +1 -0
  9. package/dist/{BlogPage-TDB3M3PI.js → BlogPage-XRM7VWOZ.js} +12 -10
  10. package/dist/BlogPage-XRM7VWOZ.js.map +1 -0
  11. package/dist/{BlogSinglePage-4A52Q5QW.js → BlogSinglePage-XIAXT54H.js} +12 -10
  12. package/dist/BlogSinglePage-XIAXT54H.js.map +1 -0
  13. package/dist/{BlogTagPage-TOVPBETA.js → BlogTagPage-IHOA267V.js} +13 -11
  14. package/dist/BlogTagPage-IHOA267V.js.map +1 -0
  15. package/dist/{BrandsPage-VUDGYSQI.js → BrandsPage-ZFEILRT3.js} +12 -10
  16. package/dist/BrandsPage-ZFEILRT3.js.map +1 -0
  17. package/dist/{Breadcrumb-CI3SN5YR.js → Breadcrumb-CVSISL2K.js} +12 -10
  18. package/dist/Breadcrumb-CVSISL2K.js.map +1 -0
  19. package/dist/{CartItem-BHLEURAB.js → CartItem-EOI7P3JA.js} +12 -10
  20. package/dist/CartItem-EOI7P3JA.js.map +1 -0
  21. package/dist/{CartSummary-QERVESYN.js → CartSummary-RZGUBDKJ.js} +12 -10
  22. package/dist/CartSummary-RZGUBDKJ.js.map +1 -0
  23. package/dist/{Copyright-RL6ALKRC.js → Copyright-5BLYSP24.js} +4 -4
  24. package/dist/{Copyright-RL6ALKRC.js.map → Copyright-5BLYSP24.js.map} +1 -1
  25. package/dist/{CustomerLayout-VRZUWGQK.js → CustomerLayout-6F4BJAMU.js} +12 -10
  26. package/dist/CustomerLayout-6F4BJAMU.js.map +1 -0
  27. package/dist/{Footer-ZWBZCMDL.js → Footer-NF2NLDLR.js} +6 -6
  28. package/dist/{Footer-ZWBZCMDL.js.map → Footer-NF2NLDLR.js.map} +1 -1
  29. package/dist/{Header-WNK4O66B.js → Header-6DQJ5X7J.js} +9 -7
  30. package/dist/{Header-WNK4O66B.js.map → Header-6DQJ5X7J.js.map} +1 -1
  31. package/dist/{LoyaltyPage-CGTHWJ76.js → LoyaltyPage-YHWHIWCS.js} +12 -10
  32. package/dist/LoyaltyPage-YHWHIWCS.js.map +1 -0
  33. package/dist/{LoyaltyPointsPage-QSU6K3PW.js → LoyaltyPointsPage-T6K3H5A5.js} +10 -3
  34. package/dist/LoyaltyPointsPage-T6K3H5A5.js.map +1 -0
  35. package/dist/{MainMenu-V3T7F32R.js → MainMenu-Y2TAM7DK.js} +4 -4
  36. package/dist/{MainMenu-V3T7F32R.js.map → MainMenu-Y2TAM7DK.js.map} +1 -1
  37. package/dist/{MasterLayout-XQF644LD.js → MasterLayout-GBEEFFPG.js} +12 -10
  38. package/dist/{MasterLayout-XQF644LD.js.map → MasterLayout-GBEEFFPG.js.map} +1 -1
  39. package/dist/{MobileMenu-U4BVQYKH.js → MobileMenu-RE5XVGZL.js} +12 -10
  40. package/dist/MobileMenu-RE5XVGZL.js.map +1 -0
  41. package/dist/{NotificationsPage-ZRRQY7TF.js → NotificationsPage-QAFWZAS3.js} +12 -10
  42. package/dist/NotificationsPage-QAFWZAS3.js.map +1 -0
  43. package/dist/{OrderSinglePage-O3XYVMG5.js → OrderSinglePage-T4PRXTKG.js} +12 -10
  44. package/dist/OrderSinglePage-T4PRXTKG.js.map +1 -0
  45. package/dist/{OrdersPage-CMXZF5MI.js → OrdersPage-3S6ZS56E.js} +12 -10
  46. package/dist/OrdersPage-3S6ZS56E.js.map +1 -0
  47. package/dist/{PageSingle-IIG2US43.js → PageSingle-W3UTXDOW.js} +4 -4
  48. package/dist/{PageSingle-IIG2US43.js.map → PageSingle-W3UTXDOW.js.map} +1 -1
  49. package/dist/{ProductDetails-65GDABI7.js → ProductDetails-X5A7TG3F.js} +14 -7
  50. package/dist/ProductDetails-X5A7TG3F.js.map +1 -0
  51. package/dist/{ProfilePage-SNJ4WXU4.js → ProfilePage-DUH3AILJ.js} +12 -10
  52. package/dist/ProfilePage-DUH3AILJ.js.map +1 -0
  53. package/dist/{ReviewsPage-UT7UT55J.js → ReviewsPage-2C2P7VS3.js} +4 -4
  54. package/dist/{ReviewsPage-UT7UT55J.js.map → ReviewsPage-2C2P7VS3.js.map} +1 -1
  55. package/dist/{SeoCartWidget-DBJAXJKT.js → SeoCartWidget-VYLGEW2I.js} +12 -10
  56. package/dist/SeoCartWidget-VYLGEW2I.js.map +1 -0
  57. package/dist/{SettingsPage-FLTIOPU5.js → SettingsPage-OZJEW6CW.js} +12 -10
  58. package/dist/SettingsPage-OZJEW6CW.js.map +1 -0
  59. package/dist/{StoreClosedNotification-ZT3QKDKS.js → StoreClosedNotification-QHIZBNXO.js} +13 -11
  60. package/dist/{StoreClosedNotification-ZT3QKDKS.js.map → StoreClosedNotification-QHIZBNXO.js.map} +1 -1
  61. package/dist/{TestimonialsPage-CU7HKU4O.js → TestimonialsPage-K6WJKKME.js} +4 -4
  62. package/dist/{TestimonialsPage-CU7HKU4O.js.map → TestimonialsPage-K6WJKKME.js.map} +1 -1
  63. package/dist/{ThankYouPage-5X6B4X3T.js → ThankYouPage-H6QQEI5R.js} +12 -10
  64. package/dist/ThankYouPage-H6QQEI5R.js.map +1 -0
  65. package/dist/{WalletPage-H2BKIDPA.js → WalletPage-G5IBGN6B.js} +12 -10
  66. package/dist/WalletPage-G5IBGN6B.js.map +1 -0
  67. package/dist/{WishlistPage-RS5UCIQ3.js → WishlistPage-AIOTAB6L.js} +12 -10
  68. package/dist/WishlistPage-AIOTAB6L.js.map +1 -0
  69. package/dist/api/advertisement.d.ts +33 -0
  70. package/dist/api/advertisement.d.ts.map +1 -0
  71. package/dist/api/advertisement.js +8 -0
  72. package/dist/api/advertisement.js.map +1 -0
  73. package/dist/boot/critical-style.d.ts +3 -0
  74. package/dist/boot/critical-style.d.ts.map +1 -0
  75. package/dist/boot/index.d.ts +15 -0
  76. package/dist/boot/index.d.ts.map +1 -0
  77. package/dist/boot.d.ts +1 -0
  78. package/dist/boot.js +69 -0
  79. package/dist/boot.js.map +1 -0
  80. package/dist/chunk-4FJGZQD3.js +6 -0
  81. package/dist/chunk-4FJGZQD3.js.map +1 -0
  82. package/dist/{chunk-SDFDS4Q3.js → chunk-BCJTF3V7.js} +20 -4
  83. package/dist/chunk-BCJTF3V7.js.map +1 -0
  84. package/dist/chunk-DBW7XXNE.js +103 -0
  85. package/dist/chunk-DBW7XXNE.js.map +1 -0
  86. package/dist/{chunk-22SH7OVF.js → chunk-E7WWO3V3.js} +3 -3
  87. package/dist/{chunk-22SH7OVF.js.map → chunk-E7WWO3V3.js.map} +1 -1
  88. package/dist/{chunk-SE5JYWOK.js → chunk-EZHXVHXY.js} +4 -4
  89. package/dist/{chunk-SE5JYWOK.js.map → chunk-EZHXVHXY.js.map} +1 -1
  90. package/dist/{chunk-JO7JWV34.js → chunk-FWYKOQV5.js} +5 -5
  91. package/dist/chunk-FWYKOQV5.js.map +1 -0
  92. package/dist/{chunk-JRNH3FUF.js → chunk-FYHF62KI.js} +4 -4
  93. package/dist/{chunk-JRNH3FUF.js.map → chunk-FYHF62KI.js.map} +1 -1
  94. package/dist/{chunk-UJKFBZFJ.js → chunk-GJ5IMPNY.js} +7 -7
  95. package/dist/{chunk-UJKFBZFJ.js.map → chunk-GJ5IMPNY.js.map} +1 -1
  96. package/dist/chunk-IVBOLREE.js +29 -0
  97. package/dist/chunk-IVBOLREE.js.map +1 -0
  98. package/dist/chunk-LWPKBVIE.js +14 -0
  99. package/dist/{chunk-7WAXN2PP.js.map → chunk-LWPKBVIE.js.map} +1 -1
  100. package/dist/{chunk-SX5MF2YA.js → chunk-N3BCZIGS.js} +4 -4
  101. package/dist/{chunk-SX5MF2YA.js.map → chunk-N3BCZIGS.js.map} +1 -1
  102. package/dist/{chunk-NZVR4OF7.js → chunk-NXQZ4RLM.js} +8 -8
  103. package/dist/chunk-NXQZ4RLM.js.map +1 -0
  104. package/dist/{chunk-NXQJA7D3.js → chunk-PCURRKIH.js} +3 -3
  105. package/dist/{chunk-NXQJA7D3.js.map → chunk-PCURRKIH.js.map} +1 -1
  106. package/dist/{chunk-4CZRUAZB.js → chunk-PU2LHFDQ.js} +10 -11
  107. package/dist/chunk-PU2LHFDQ.js.map +1 -0
  108. package/dist/{chunk-OWX2CPNQ.js → chunk-UQIVX4YA.js} +3 -3
  109. package/dist/{chunk-OWX2CPNQ.js.map → chunk-UQIVX4YA.js.map} +1 -1
  110. package/dist/chunk-X5NK4TZH.js +228 -0
  111. package/dist/chunk-X5NK4TZH.js.map +1 -0
  112. package/dist/{chunk-6SWDSRIL.js → chunk-XKNXYQ2K.js} +6 -6
  113. package/dist/{chunk-6SWDSRIL.js.map → chunk-XKNXYQ2K.js.map} +1 -1
  114. package/dist/{chunk-KHBSGD2D.js → chunk-XO7B3VWS.js} +3 -3
  115. package/dist/{chunk-KHBSGD2D.js.map → chunk-XO7B3VWS.js.map} +1 -1
  116. package/dist/cli/check-manifest.d.ts +10 -0
  117. package/dist/cli/check-manifest.d.ts.map +1 -0
  118. package/dist/cli/check-manifest.js +44 -0
  119. package/dist/cli/check-manifest.js.map +1 -0
  120. package/dist/components/cart/index.js +1 -1
  121. package/dist/components/common/index.js +2 -2
  122. package/dist/components/drawer/index.js +10 -8
  123. package/dist/components/home/index.js +12 -10
  124. package/dist/components/layout/Footer.d.ts.map +1 -1
  125. package/dist/components/layout/MasterLayout.d.ts.map +1 -1
  126. package/dist/components/layout/PageAdvertisements.d.ts +7 -0
  127. package/dist/components/layout/PageAdvertisements.d.ts.map +1 -0
  128. package/dist/components/layout/index.d.ts +1 -0
  129. package/dist/components/layout/index.d.ts.map +1 -1
  130. package/dist/components/layout/index.js +8 -1
  131. package/dist/components/product/index.js +11 -9
  132. package/dist/components/store/index.js +12 -10
  133. package/dist/components/store/index.js.map +1 -1
  134. package/dist/{document-class-67HTP45G.js → document-class-FRL7JHWD.js} +6 -5
  135. package/dist/{document-class-67HTP45G.js.map → document-class-FRL7JHWD.js.map} +1 -1
  136. package/dist/hooks/index.js +10 -8
  137. package/dist/hooks/useGtm.js +10 -8
  138. package/dist/hooks/useMoney.js +10 -8
  139. package/dist/hooks/useStore.js +10 -8
  140. package/dist/index.js +10 -8
  141. package/dist/index.js.map +1 -1
  142. package/dist/{not-found-QTHBFPNT.js → not-found-E6AR4CZ4.js} +12 -10
  143. package/dist/not-found-E6AR4CZ4.js.map +1 -0
  144. package/dist/providers/index.js +10 -8
  145. package/dist/routes/account/orders.js +1 -1
  146. package/dist/routes/account.js +6 -6
  147. package/dist/routes/blog.js +5 -5
  148. package/dist/routes/brands.js +1 -1
  149. package/dist/routes/cart.js +14 -12
  150. package/dist/routes/cart.js.map +1 -1
  151. package/dist/routes/home.js +13 -11
  152. package/dist/routes/loyalty.js +2 -2
  153. package/dist/routes/page.js +1 -1
  154. package/dist/routes/product-listing.js +12 -10
  155. package/dist/routes/product-listing.js.map +1 -1
  156. package/dist/routes/product.js +12 -10
  157. package/dist/routes/product.js.map +1 -1
  158. package/dist/routes/root/beforeLoad.d.ts +2 -2
  159. package/dist/routes/root/beforeLoad.d.ts.map +1 -1
  160. package/dist/routes/root/head.d.ts.map +1 -1
  161. package/dist/routes/testimonials.js +2 -2
  162. package/dist/routes/thank-you.js +1 -1
  163. package/dist/skeleton.js +13 -11
  164. package/dist/tanstack/document-class.d.ts.map +1 -1
  165. package/dist/tanstack/index.d.ts +1 -0
  166. package/dist/tanstack/index.d.ts.map +1 -1
  167. package/dist/tanstack/stylesheet.d.ts +15 -0
  168. package/dist/tanstack/stylesheet.d.ts.map +1 -0
  169. package/dist/tanstack.js +33 -4
  170. package/dist/tanstack.js.map +1 -1
  171. package/dist/utils/index.js +2 -2
  172. package/dist/vite/index.d.ts +1 -1
  173. package/dist/vite/index.d.ts.map +1 -1
  174. package/dist/vite/index.js +14 -25
  175. package/dist/vite/index.js.map +1 -1
  176. package/dist/vite/plugins/twilight-manifest.d.ts +23 -0
  177. package/dist/vite/plugins/twilight-manifest.d.ts.map +1 -1
  178. package/dist/vite/plugins/twilight-schema.plugin.d.ts.map +1 -1
  179. package/package.json +16 -3
  180. package/tailwind/components/Component.tsx.txt +21 -0
  181. package/tailwind/components/ComponentRegistry.ts.txt +66 -0
  182. package/tailwind/components/cart/CartItem.tsx.txt +211 -0
  183. package/tailwind/components/cart/CartSummary.tsx.txt +269 -0
  184. package/tailwind/components/cart/PreOrderNotification.tsx.txt +16 -0
  185. package/tailwind/components/cart/PriceQuoteButton.tsx.txt +21 -0
  186. package/tailwind/components/cart/SeoCartWidget.tsx.txt +99 -0
  187. package/tailwind/components/cart/index.ts.txt +11 -0
  188. package/tailwind/components/cart/lazy.ts.txt +15 -0
  189. package/tailwind/components/collapse/Collapse.tsx.txt +95 -0
  190. package/tailwind/components/collapse/index.ts.txt +41 -0
  191. package/tailwind/components/common/Breadcrumb.tsx.txt +27 -0
  192. package/tailwind/components/common/BreadcrumbJsonLd.tsx.txt +40 -0
  193. package/tailwind/components/common/BreadcrumbTrail.tsx.txt +97 -0
  194. package/tailwind/components/common/CurrencySymbol.tsx.txt +8 -0
  195. package/tailwind/components/common/DeferredData.tsx.txt +122 -0
  196. package/tailwind/components/common/ErrorPage.tsx.txt +69 -0
  197. package/tailwind/components/common/Image.tsx.txt +119 -0
  198. package/tailwind/components/common/Link.tsx.txt +36 -0
  199. package/tailwind/components/common/Link.types.ts.txt +85 -0
  200. package/tailwind/components/common/NoContent.tsx.txt +27 -0
  201. package/tailwind/components/common/RenderWhenVisible.tsx.txt +92 -0
  202. package/tailwind/components/common/index.ts.txt +42 -0
  203. package/tailwind/components/common/lazy.ts.txt +28 -0
  204. package/tailwind/components/defineComponent.ts.txt +32 -0
  205. package/tailwind/components/drawer/Drawer.tsx.txt +219 -0
  206. package/tailwind/components/drawer/index.ts.txt +38 -0
  207. package/tailwind/components/dropdown/Dropdown.tsx.txt +166 -0
  208. package/tailwind/components/dropdown/index.ts.txt +40 -0
  209. package/tailwind/components/home/BundleComponent.tsx.txt +35 -0
  210. package/tailwind/components/home/ComponentErrorBoundary.tsx.txt +98 -0
  211. package/tailwind/components/home/FeaturedProductsStyle1.tsx.txt +125 -0
  212. package/tailwind/components/home/FeaturedProductsStyle2.tsx.txt +127 -0
  213. package/tailwind/components/home/FeaturedProductsStyle3.tsx.txt +71 -0
  214. package/tailwind/components/home/FixedBanner.tsx.txt +68 -0
  215. package/tailwind/components/home/FixedProducts.tsx.txt +72 -0
  216. package/tailwind/components/home/HomePageRenderer.tsx.txt +284 -0
  217. package/tailwind/components/home/PageBlocks.tsx.txt +24 -0
  218. package/tailwind/components/home/ParallaxBackground.tsx.txt +50 -0
  219. package/tailwind/components/home/PhotosSlider.tsx.txt +61 -0
  220. package/tailwind/components/home/ProductsSlider.tsx.txt +87 -0
  221. package/tailwind/components/home/ReorderProducts.tsx.txt +38 -0
  222. package/tailwind/components/home/SquarePhotos.tsx.txt +68 -0
  223. package/tailwind/components/home/StoreFeatures.tsx.txt +34 -0
  224. package/tailwind/components/home/Testimonials.tsx.txt +36 -0
  225. package/tailwind/components/home/Youtube.tsx.txt +48 -0
  226. package/tailwind/components/home/index.ts.txt +50 -0
  227. package/tailwind/components/home/lazy.ts.txt +17 -0
  228. package/tailwind/components/home/register.ts.txt +44 -0
  229. package/tailwind/components/home/reorder-hooks.ts.txt +52 -0
  230. package/tailwind/components/home/types.ts.txt +4 -0
  231. package/tailwind/components/layout/Copyright.tsx.txt +23 -0
  232. package/tailwind/components/layout/CustomerLayout.tsx.txt +91 -0
  233. package/tailwind/components/layout/Footer.tsx.txt +341 -0
  234. package/tailwind/components/layout/Header.tsx.txt +154 -0
  235. package/tailwind/components/layout/MasterLayout.tsx.txt +62 -0
  236. package/tailwind/components/layout/PageAdvertisements.tsx.txt +131 -0
  237. package/tailwind/components/layout/WidgetHead.tsx.txt +53 -0
  238. package/tailwind/components/layout/index.ts.txt +27 -0
  239. package/tailwind/components/layout/lazy.ts.txt +25 -0
  240. package/tailwind/components/layout/types.ts.txt +11 -0
  241. package/tailwind/components/modal/ImageModal.tsx.txt +70 -0
  242. package/tailwind/components/modal/Modal.tsx.txt +245 -0
  243. package/tailwind/components/modal/index.ts.txt +39 -0
  244. package/tailwind/components/modal/lazy.ts.txt +10 -0
  245. package/tailwind/components/navigation/MainMenu.tsx.txt +94 -0
  246. package/tailwind/components/navigation/MobileMenu.tsx.txt +160 -0
  247. package/tailwind/components/navigation/index.ts.txt +4 -0
  248. package/tailwind/components/navigation/lazy.ts.txt +11 -0
  249. package/tailwind/components/product/AddToCartForm.tsx.txt +365 -0
  250. package/tailwind/components/product/ProductCard.tsx.txt +305 -0
  251. package/tailwind/components/product/ProductDetails.tsx.txt +267 -0
  252. package/tailwind/components/product/ProductGallery.tsx.txt +234 -0
  253. package/tailwind/components/product/index.ts.txt +15 -0
  254. package/tailwind/components/product/lazy.ts.txt +9 -0
  255. package/tailwind/components/snippets/AppsSnippets.tsx.txt +225 -0
  256. package/tailwind/components/snippets/SallaSdkScripts.tsx.txt +14 -0
  257. package/tailwind/components/snippets/index.ts.txt +4 -0
  258. package/tailwind/components/store/StoreClosedNotification.tsx.txt +73 -0
  259. package/tailwind/components/store/index.ts.txt +8 -0
  260. package/tailwind/components/store/lazy.ts.txt +8 -0
  261. package/tailwind/components/toast/Toaster.tsx.txt +177 -0
  262. package/tailwind/components/toast/index.ts.txt +10 -0
  263. package/tailwind/components/toast/types.ts.txt +38 -0
  264. package/tailwind/components/toast/useToast.ts.txt +61 -0
  265. package/tailwind/components/tracking/GoogleTag.tsx.txt +77 -0
  266. package/tailwind/components/tracking/SiftSnippet.tsx.txt +49 -0
  267. package/tailwind/components/tracking/TwilightBundles.tsx.txt +67 -0
  268. package/tailwind/components/tracking/index.ts.txt +11 -0
  269. package/tailwind/components/tracking/lazy.ts.txt +11 -0
  270. package/tailwind/components/useComponent.ts.txt +12 -0
  271. package/tailwind/routes/account/index.tsx.txt +16 -0
  272. package/tailwind/routes/account/notifications/NotificationsPage.tsx.txt +54 -0
  273. package/tailwind/routes/account/notifications/index.tsx.txt +39 -0
  274. package/tailwind/routes/account/notifications/loader.ts.txt +22 -0
  275. package/tailwind/routes/account/notifications/types.ts.txt +18 -0
  276. package/tailwind/routes/account/orders/OrderSinglePage.tsx.txt +181 -0
  277. package/tailwind/routes/account/orders/OrdersPage.tsx.txt +28 -0
  278. package/tailwind/routes/account/orders/index.tsx.txt +86 -0
  279. package/tailwind/routes/account/orders/loader.ts.txt +66 -0
  280. package/tailwind/routes/account/orders/single/OrderActions.tsx.txt +197 -0
  281. package/tailwind/routes/account/orders/single/OrderHeader.tsx.txt +143 -0
  282. package/tailwind/routes/account/orders/single/OrderItemRow.tsx.txt +209 -0
  283. package/tailwind/routes/account/orders/single/OrderSections.tsx.txt +215 -0
  284. package/tailwind/routes/account/orders/single/types.ts.txt +38 -0
  285. package/tailwind/routes/account/orders/types.ts.txt +29 -0
  286. package/tailwind/routes/account/profile/ProfilePage.tsx.txt +30 -0
  287. package/tailwind/routes/account/profile/index.tsx.txt +39 -0
  288. package/tailwind/routes/account/profile/loader.ts.txt +16 -0
  289. package/tailwind/routes/account/profile/types.ts.txt +5 -0
  290. package/tailwind/routes/account/settings/SettingsPage.tsx.txt +13 -0
  291. package/tailwind/routes/account/settings/index.tsx.txt +39 -0
  292. package/tailwind/routes/account/settings/loader.ts.txt +13 -0
  293. package/tailwind/routes/account/settings/types.ts.txt +5 -0
  294. package/tailwind/routes/account/types.ts.txt +320 -0
  295. package/tailwind/routes/account/wallet/WalletPage.tsx.txt +195 -0
  296. package/tailwind/routes/account/wallet/index.tsx.txt +38 -0
  297. package/tailwind/routes/account/wallet/loader.ts.txt +27 -0
  298. package/tailwind/routes/account/wallet/types.ts.txt +11 -0
  299. package/tailwind/routes/account/wishlist/WishlistPage.tsx.txt +314 -0
  300. package/tailwind/routes/account/wishlist/WishlistShare.tsx.txt +248 -0
  301. package/tailwind/routes/account/wishlist/index.tsx.txt +40 -0
  302. package/tailwind/routes/account/wishlist/loader.ts.txt +26 -0
  303. package/tailwind/routes/account/wishlist/types.ts.txt +9 -0
  304. package/tailwind/routes/blog/BlogAuthorPage.tsx.txt +82 -0
  305. package/tailwind/routes/blog/BlogCategoryPage.tsx.txt +84 -0
  306. package/tailwind/routes/blog/BlogPage.tsx.txt +191 -0
  307. package/tailwind/routes/blog/BlogSinglePage.tsx.txt +168 -0
  308. package/tailwind/routes/blog/BlogTagPage.tsx.txt +84 -0
  309. package/tailwind/routes/blog/BlogTags.tsx.txt +54 -0
  310. package/tailwind/routes/blog/components.tsx.txt +87 -0
  311. package/tailwind/routes/blog/index.tsx.txt +238 -0
  312. package/tailwind/routes/blog/loader.ts.txt +173 -0
  313. package/tailwind/routes/blog/types.ts.txt +106 -0
  314. package/tailwind/routes/brands/BrandsPage.tsx.txt +179 -0
  315. package/tailwind/routes/brands/index.tsx.txt +47 -0
  316. package/tailwind/routes/brands/loader.ts.txt +14 -0
  317. package/tailwind/routes/brands/types.ts.txt +53 -0
  318. package/tailwind/routes/cart/CartPage.tsx.txt +112 -0
  319. package/tailwind/routes/cart/index.tsx.txt +39 -0
  320. package/tailwind/routes/cart/loader.ts.txt +15 -0
  321. package/tailwind/routes/cart/types.ts.txt +6 -0
  322. package/tailwind/routes/home/HomePage.tsx.txt +53 -0
  323. package/tailwind/routes/home/index.tsx.txt +56 -0
  324. package/tailwind/routes/home/loader.ts.txt +24 -0
  325. package/tailwind/routes/home/types.ts.txt +11 -0
  326. package/tailwind/routes/index.ts.txt +94 -0
  327. package/tailwind/routes/lazy.ts.txt +105 -0
  328. package/tailwind/routes/loyalty/LoyaltyPage.tsx.txt +17 -0
  329. package/tailwind/routes/loyalty/LoyaltyPointsPage.tsx.txt +11 -0
  330. package/tailwind/routes/loyalty/index.tsx.txt +81 -0
  331. package/tailwind/routes/loyalty/loader.ts.txt +53 -0
  332. package/tailwind/routes/loyalty/types.ts.txt +109 -0
  333. package/tailwind/routes/not-found.tsx.txt +50 -0
  334. package/tailwind/routes/page/PageSingle.tsx.txt +34 -0
  335. package/tailwind/routes/page/index.tsx.txt +60 -0
  336. package/tailwind/routes/page/loader.ts.txt +19 -0
  337. package/tailwind/routes/page/types.ts.txt +34 -0
  338. package/tailwind/routes/product/ProductPage.tsx.txt +77 -0
  339. package/tailwind/routes/product/index.tsx.txt +157 -0
  340. package/tailwind/routes/product/loader.ts.txt +35 -0
  341. package/tailwind/routes/product/types.ts.txt +6 -0
  342. package/tailwind/routes/product-listing/ProductListPage.tsx.txt +321 -0
  343. package/tailwind/routes/product-listing/index.tsx.txt +95 -0
  344. package/tailwind/routes/product-listing/loader.ts.txt +323 -0
  345. package/tailwind/routes/product-listing/types.ts.txt +96 -0
  346. package/tailwind/routes/product-listing/useAppliedFilters.ts.txt +130 -0
  347. package/tailwind/routes/product-short-link.ts.txt +104 -0
  348. package/tailwind/routes/root/beforeLoad.ts.txt +354 -0
  349. package/tailwind/routes/root/head.ts.txt +424 -0
  350. package/tailwind/routes/root/index.ts.txt +2 -0
  351. package/tailwind/routes/seo-redirects.ts.txt +82 -0
  352. package/tailwind/routes/testimonials/ReviewsPage.tsx.txt +12 -0
  353. package/tailwind/routes/testimonials/TestimonialsPage.tsx.txt +80 -0
  354. package/tailwind/routes/testimonials/index.tsx.txt +80 -0
  355. package/tailwind/routes/testimonials/loader.ts.txt +29 -0
  356. package/tailwind/routes/testimonials/types.ts.txt +9 -0
  357. package/tailwind/routes/thank-you/ThankYouPage.tsx.txt +241 -0
  358. package/tailwind/routes/thank-you/index.tsx.txt +49 -0
  359. package/tailwind/routes/thank-you/loader.ts.txt +40 -0
  360. package/tailwind/routes/thank-you/types.ts.txt +16 -0
  361. package/tailwind/routes/types.ts.txt +41 -0
  362. package/dist/BlogAuthorPage-GTF4UGSS.js.map +0 -1
  363. package/dist/BlogCategoryPage-TN7Y4NBP.js.map +0 -1
  364. package/dist/BlogPage-TDB3M3PI.js.map +0 -1
  365. package/dist/BlogSinglePage-4A52Q5QW.js.map +0 -1
  366. package/dist/BlogTagPage-TOVPBETA.js.map +0 -1
  367. package/dist/BrandsPage-VUDGYSQI.js.map +0 -1
  368. package/dist/Breadcrumb-CI3SN5YR.js.map +0 -1
  369. package/dist/CartItem-BHLEURAB.js.map +0 -1
  370. package/dist/CartSummary-QERVESYN.js.map +0 -1
  371. package/dist/CustomerLayout-VRZUWGQK.js.map +0 -1
  372. package/dist/LoyaltyPage-CGTHWJ76.js.map +0 -1
  373. package/dist/LoyaltyPointsPage-QSU6K3PW.js.map +0 -1
  374. package/dist/MobileMenu-U4BVQYKH.js.map +0 -1
  375. package/dist/NotificationsPage-ZRRQY7TF.js.map +0 -1
  376. package/dist/OrderSinglePage-O3XYVMG5.js.map +0 -1
  377. package/dist/OrdersPage-CMXZF5MI.js.map +0 -1
  378. package/dist/ProductDetails-65GDABI7.js.map +0 -1
  379. package/dist/ProfilePage-SNJ4WXU4.js.map +0 -1
  380. package/dist/SeoCartWidget-DBJAXJKT.js.map +0 -1
  381. package/dist/SettingsPage-FLTIOPU5.js.map +0 -1
  382. package/dist/ThankYouPage-5X6B4X3T.js.map +0 -1
  383. package/dist/WalletPage-H2BKIDPA.js.map +0 -1
  384. package/dist/WishlistPage-RS5UCIQ3.js.map +0 -1
  385. package/dist/chunk-4CZRUAZB.js.map +0 -1
  386. package/dist/chunk-7WAXN2PP.js +0 -14
  387. package/dist/chunk-JO7JWV34.js.map +0 -1
  388. package/dist/chunk-NZVR4OF7.js.map +0 -1
  389. package/dist/chunk-SDFDS4Q3.js.map +0 -1
  390. package/dist/not-found-QTHBFPNT.js.map +0 -1
@@ -0,0 +1,160 @@
1
+ import { useState, useCallback, useEffect, memo } from 'react';
2
+ import { useQuery } from '@tanstack/react-query';
3
+ import { useTwilight } from '../../providers/twilight-context';
4
+ import { useTranslation } from '../../providers/I18nProvider';
5
+ import { Drawer } from '../../components/drawer';
6
+ import { Link } from '../common';
7
+ import { menu } from '../../api/menu';
8
+ import type { MenuItem } from '../../types';
9
+
10
+ export interface MobileMenuProps {
11
+ isOpen: boolean;
12
+ onClose: () => void;
13
+ }
14
+
15
+ const MOBILE_SKELETON_ITEMS = 5;
16
+ const SKELETON_WIDTHS = ['w-32', 'w-28', 'w-36', 'w-24', 'w-30'];
17
+
18
+ const MobileMenuSkeleton = memo(function MobileMenuSkeleton() {
19
+ return (
20
+ <ul className="divide-y divide-gray-100">
21
+ {Array.from({ length: MOBILE_SKELETON_ITEMS }, (_, i) => (
22
+ <li key={i} className="py-4">
23
+ <span
24
+ className={`inline-block animate-pulse rounded bg-gray-200 h-5 ${SKELETON_WIDTHS[i]}`}
25
+ />
26
+ </li>
27
+ ))}
28
+ </ul>
29
+ );
30
+ });
31
+
32
+ export function MobileMenu(props: MobileMenuProps) {
33
+ if (!props.isOpen) return null;
34
+ return <MobileMenuContent {...props} />;
35
+ }
36
+
37
+ function MobileMenuContent({ onClose }: MobileMenuProps) {
38
+ const { theme } = useTwilight();
39
+ const { data: menus = [], isLoading } = useQuery(menu.queries.header());
40
+ const { t } = useTranslation();
41
+
42
+ const [menuStack, setMenuStack] = useState<{ title: string; items: MenuItem[] }[]>([]);
43
+ const [isAnimating, setIsAnimating] = useState(false);
44
+
45
+ const currentLevel = menuStack[menuStack.length - 1] ?? { title: '', items: menus };
46
+ const isRootLevel = menuStack.length === 0;
47
+
48
+ const openSubmenu = useCallback((item: MenuItem) => {
49
+ if (item.children && item.children.length > 0) {
50
+ setIsAnimating(true);
51
+ setMenuStack((prev) => [...prev, { title: item.title, items: item.children! }]);
52
+ requestAnimationFrame(() => {
53
+ setIsAnimating(false);
54
+ });
55
+ }
56
+ }, []);
57
+
58
+ const goBack = useCallback(() => {
59
+ setIsAnimating(true);
60
+ setMenuStack((prev) => prev.slice(0, -1));
61
+ requestAnimationFrame(() => {
62
+ setIsAnimating(false);
63
+ });
64
+ }, []);
65
+
66
+ useEffect(() => {
67
+ document.body.classList.add('menu-opened');
68
+ return () => document.body.classList.remove('menu-opened');
69
+ }, []);
70
+
71
+ const getListAnimationClass = () => {
72
+ if (isAnimating) {
73
+ return theme.is_rtl ? 'translate-x-4 opacity-0' : '-translate-x-4 opacity-0';
74
+ }
75
+ return 'translate-x-0 opacity-100';
76
+ };
77
+
78
+ return (
79
+ <>
80
+ <Drawer
81
+ isOpen
82
+ onClose={onClose}
83
+ size="md"
84
+ closeOnBackdropClick={true}
85
+ preventBodyScroll={false}
86
+ className="overflow-visible"
87
+ >
88
+ <button
89
+ type="button"
90
+ onClick={onClose}
91
+ aria-label={t('common.buttons.close', 'Close')}
92
+ className="absolute top-0 w-12 h-12 flex items-center justify-center bg-[#d35a51] text-white hover:bg-red-600 transition-colors z-50 ltr:-right-12 rtl:-left-12"
93
+ >
94
+ <i className="sicon-cancel text-xl leading-none"></i>
95
+ </button>
96
+
97
+ <Drawer.Header showCloseButton={false} onClose={onClose}>
98
+ <div className="flex items-center gap-2 w-full">
99
+ {!isRootLevel && (
100
+ <button
101
+ type="button"
102
+ className="text-gray-500 hover:text-gray-800 transition-colors flex-shrink-0"
103
+ onClick={goBack}
104
+ aria-label={t('common.buttons.back', 'Back')}
105
+ >
106
+ <i className="sicon-keyboard_arrow_left text-xl flex items-center justify-center"></i>
107
+ </button>
108
+ )}
109
+ <span className="font-bold text-lg truncate flex-1 text-center pr-6 rtl:pl-6 rtl:pr-0">
110
+ {isRootLevel ? t('blocks.header.main_menu', 'Menu') : currentLevel.title}
111
+ </span>
112
+ </div>
113
+ </Drawer.Header>
114
+ <Drawer.Body className="p-0 overflow-hidden">
115
+ <nav className="mobile-menu h-full overflow-y-auto">
116
+ {isLoading ? (
117
+ <MobileMenuSkeleton />
118
+ ) : (
119
+ <ul
120
+ className={`divide-y divide-gray-100 transition-all duration-200 ease-out ${getListAnimationClass()}`}
121
+ >
122
+ {currentLevel.items.map((item) => {
123
+ const hasChildren =
124
+ item.has_children && item.children && item.children.length > 0;
125
+
126
+ return (
127
+ <li key={item.id} className="mobile-menu-item">
128
+ {hasChildren ? (
129
+ <button
130
+ type="button"
131
+ className="flex items-center justify-between w-full py-4 hover:text-primary transition-colors text-start group"
132
+ onClick={() => openSubmenu(item)}
133
+ >
134
+ <span className="text-gray-800 group-hover:text-primary font-medium text-base">
135
+ {item.title}
136
+ </span>
137
+ <i className="sicon-keyboard_arrow_right rtl:rotate-180 text-gray-500 group-hover:text-primary text-lg flex items-center justify-center h-full"></i>
138
+ </button>
139
+ ) : (
140
+ <Link
141
+ to={item.url}
142
+ className="block w-full py-4 hover:text-primary transition-colors text-gray-800 font-medium text-base group"
143
+ onClick={onClose}
144
+ >
145
+ <span className="group-hover:translate-x-1 rtl:group-hover:-translate-x-1 inline-block transition-transform">
146
+ {item.title}
147
+ </span>
148
+ </Link>
149
+ )}
150
+ </li>
151
+ );
152
+ })}
153
+ </ul>
154
+ )}
155
+ </nav>
156
+ </Drawer.Body>
157
+ </Drawer>
158
+ </>
159
+ );
160
+ }
@@ -0,0 +1,4 @@
1
+ import { LazyMainMenu, LazyMobileMenu } from './lazy';
2
+
3
+ // Lazy-loaded navigation components (code-split)
4
+ export { LazyMainMenu as MainMenu, LazyMobileMenu as MobileMenu };
@@ -0,0 +1,11 @@
1
+ import { lazy } from 'react';
2
+
3
+ /**
4
+ * Lazy-loaded navigation components
5
+ * Use these for code-splitting navigation sections
6
+ */
7
+ export const LazyMainMenu = lazy(() => import('./MainMenu').then((m) => ({ default: m.MainMenu })));
8
+
9
+ export const LazyMobileMenu = lazy(() =>
10
+ import('./MobileMenu').then((m) => ({ default: m.MobileMenu }))
11
+ );
@@ -0,0 +1,365 @@
1
+ import { SallaAddProductButton } from '@salla.sa/twilight-components-react/add-product-button';
2
+ import { SallaButton } from '@salla.sa/twilight-components-react/button';
3
+ import { SallaCountDown } from '@salla.sa/twilight-components-react/count-down';
4
+ import { SallaFileUpload } from '@salla.sa/twilight-components-react/file-upload';
5
+ import { SallaGifting } from '@salla.sa/twilight-components-react/gifting';
6
+ import { SallaMultipleBundleProduct } from '@salla.sa/twilight-components-react/multiple-bundle-product';
7
+ // Use the eager (non-deferred) Core export: product options are an essential form
8
+ // control, and the deferred wrapper's visibility-triggered hydration races with the
9
+ // gallery's image layout shift and gets stuck on the skeleton, so options never appear.
10
+ import { SallaProductOptionsCore as SallaProductOptions } from '@salla.sa/twilight-components-react/product-options';
11
+ import { SallaProductSizeGuide } from '@salla.sa/twilight-components-react/product-size-guide';
12
+ import { SallaQuantityInput } from '@salla.sa/twilight-components-react/quantity-input';
13
+ import { useHostAttributes } from '@salla.sa/twilight-theme-engine/hooks/useHostAttributes';
14
+ import { useTranslation } from '@salla.sa/twilight-theme-engine/i18n';
15
+ import { getActiveCurrency } from '@salla.sa/twilight-theme-engine/api/client';
16
+ import type { ReactNode } from 'react';
17
+ import { useCallback, useEffect, useState } from 'react';
18
+ import type { Product } from '../../types';
19
+ import { CurrencySymbol } from '../common';
20
+
21
+ interface AddToCartFormProps {
22
+ product: Product;
23
+ stickyAddToCart?: boolean;
24
+ giftingIntro?: string;
25
+ formStartSlot?: ReactNode;
26
+ formEndSlot?: ReactNode;
27
+ }
28
+
29
+ const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
30
+ e.preventDefault();
31
+ // Native event, like Twig's onsubmit: the SDK spins its submitter's salla-button until the add settles.
32
+ window.salla?.form.onSubmit('cart.addItem', e.nativeEvent);
33
+ };
34
+
35
+ const handleChange = (e: React.FormEvent<HTMLFormElement>) => {
36
+ const form = e.currentTarget;
37
+ // Not reportValidity(): it focuses and scrolls to the first empty required option mid-edit.
38
+ const isComplete = Array.from(form.elements).every(
39
+ (el) => !(el as HTMLInputElement).willValidate || (el as HTMLInputElement).validity.valid
40
+ );
41
+ if (isComplete) {
42
+ window.salla?.product?.getPrice(new FormData(form));
43
+ }
44
+ };
45
+
46
+ export function AddToCartForm({
47
+ product,
48
+ stickyAddToCart,
49
+ giftingIntro,
50
+ formStartSlot,
51
+ formEndSlot,
52
+ }: AddToCartFormProps) {
53
+ const { t } = useTranslation();
54
+ // The API converts the amounts but still labels them in the store's own currency.
55
+ const priceCurrency = getActiveCurrency(product.currency);
56
+ const [activeCollapse, setActiveCollapse] = useState<string | null>(null);
57
+
58
+ // stable ref: an inline arrow re-runs on every render and resets the user's selection
59
+ const optionsRef = useCallback(
60
+ (el: { setOptionsData?: (data: never[]) => void } | null) =>
61
+ void el?.setOptionsData?.(product.options as never[]),
62
+ [product.options]
63
+ );
64
+
65
+ // salla-product-options reads its `options` prop only in its constructor (no
66
+ // @Watch), and on first load that constructor runs before sdk.init has set
67
+ // page.id — so its getDetails(page.id) fallback fetches nothing and the options
68
+ // never reflect. Seed page.id (=== product.id) and wait for the SDK to be ready
69
+ // before mounting the element so its fallback resolves on first load too.
70
+ const [optionsReady, setOptionsReady] = useState(false);
71
+ useEffect(() => {
72
+ const salla = window.salla;
73
+ if (!salla) return;
74
+ let alive = true;
75
+ salla.config?.set?.('page.id', product.id);
76
+ Promise.resolve(salla.onReady?.()).finally(() => {
77
+ if (alive) setOptionsReady(true);
78
+ });
79
+ return () => {
80
+ alive = false;
81
+ };
82
+ }, [product.id]);
83
+
84
+ const handleCollapseToggle = useCallback((id: string) => {
85
+ setActiveCollapse((current) => (current === id ? null : id));
86
+ }, []);
87
+
88
+ const hasPreorder = product.has_preorder_campaign && product.preorder;
89
+ const hasWeightOrSizeGuide = product.weight || product.has_size_guide;
90
+ const hasAttachments = product.can_add_note || product.can_upload_file;
91
+ const amount =
92
+ typeof product.base_currency_price === 'object'
93
+ ? product.base_currency_price.amount
94
+ : product.base_currency_price;
95
+
96
+ const quantityRef = useHostAttributes({
97
+ max: product.max_quantity,
98
+ value: 1,
99
+ name: 'quantity',
100
+ });
101
+ const addButtonRef = useHostAttributes({
102
+ amount,
103
+ 'loader-position': 'end',
104
+ type: 'submit',
105
+ width: 'wide',
106
+ 'required-shipping': product.is_require_shipping,
107
+ 'is-subscribed': product.notify_availability?.subscribed,
108
+ });
109
+
110
+ return (
111
+ <form
112
+ className="form product-form"
113
+ encType="multipart/form-data"
114
+ method="post"
115
+ onSubmit={handleSubmit}
116
+ onChange={handleChange}
117
+ >
118
+ <input type="hidden" name="id" value={product.id} />
119
+
120
+ {formStartSlot}
121
+
122
+ {optionsReady && product.options && product.options.length > 0 && (
123
+ <SallaProductOptions
124
+ key={product.id}
125
+ // constructor-only options parse: push data via ref on client remount
126
+ ref={optionsRef}
127
+ options={JSON.stringify(product.options)}
128
+ productId={product.id}
129
+ />
130
+ )}
131
+
132
+ {product.has_bundle_products && (
133
+ <SallaMultipleBundleProduct bundleSections={JSON.stringify(product)} />
134
+ )}
135
+
136
+ {hasWeightOrSizeGuide && (
137
+ <section className="bg-white p-5 rounded-md mb-5">
138
+ {product.weight && (
139
+ <div
140
+ className={`center-between ${product.has_size_guide ? 'pb-5 mb-5 border-b-[1px]' : ''}`}
141
+ >
142
+ <b className="form-label rtl:space-x-reverse space-x-1">
143
+ <i className="sicon-luggage-cart"></i>
144
+ <span>{t('pages.products.weight', 'Weight')}</span>
145
+ </b>
146
+ <span className="product-weight text-sm">{product.weight}</span>
147
+ </div>
148
+ )}
149
+ {product.has_size_guide && (
150
+ <>
151
+ <div className="center-between">
152
+ <b className="form-label rtl:space-x-reverse space-x-1">
153
+ <i className="sicon-pencil-ruler"></i>
154
+ <span>{t('pages.products.size_guides', 'Size Guides')}</span>
155
+ </b>
156
+ <SallaButton
157
+ shape="link"
158
+ color="primary"
159
+ className="!p-0 text-sm with-arrow"
160
+ onClick={() =>
161
+ window.salla?.event?.dispatch('size-guide::open', String(product.id))
162
+ }
163
+ >
164
+ {t('pages.products.show_size_guides', 'Show Size Guides')}
165
+ <i className="sicon-keyboard_arrow_left"></i>
166
+ </SallaButton>
167
+ </div>
168
+ <SallaProductSizeGuide />
169
+ </>
170
+ )}
171
+ </section>
172
+ )}
173
+
174
+ {hasAttachments && (
175
+ <section className="bg-white p-5 rounded-md mb-5">
176
+ <div className="sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start">
177
+ <div className="form-label">
178
+ <b className="block">{t('pages.products.attachments', 'Attachments')}</b>
179
+ </div>
180
+ <div className="mt-1 sm:mt-0 sm:col-span-2 text-end">
181
+ <div className="flex rtl:space-x-reverse space-x-3">
182
+ {product.can_add_note && (
183
+ <button
184
+ type="button"
185
+ onClick={() => handleCollapseToggle(`note_${product.id}`)}
186
+ className={`btn-tab btn--collapse ${activeCollapse === `note_${product.id}` ? 'is-opened' : 'is-closed'}`}
187
+ >
188
+ <i className="font-medium sicon-chat-conversation-alt rtl:ml-1.5 ltr:mr-1.5"></i>
189
+ <span className="fix-align">{t('pages.products.add_note', 'Add Note')}</span>
190
+ </button>
191
+ )}
192
+ {product.can_upload_file && (
193
+ <button
194
+ type="button"
195
+ onClick={() => handleCollapseToggle(`file_${product.id}`)}
196
+ className={`btn-tab btn--collapse ${activeCollapse === `file_${product.id}` ? 'is-opened' : 'is-closed'}`}
197
+ >
198
+ <i className="font-medium sicon-paperclip rtl:ml-1.5 ltr:mr-1.5"></i>
199
+ <span className="fix-align">{t('pages.products.add_file', 'Add File')}</span>
200
+ </button>
201
+ )}
202
+ </div>
203
+
204
+ {product.can_add_note && (
205
+ <div
206
+ className={`collapse-content ${activeCollapse === `note_${product.id}` ? 'is-opened' : 'is-closed'}`}
207
+ >
208
+ <div className="pt-4">
209
+ <textarea
210
+ className="animated animatedfadeInDown fadeInDown form-input h-16 bg-gray-50 block"
211
+ placeholder={t('pages.products.notes_placeholder', 'Add your notes here...')}
212
+ name="notes"
213
+ cols={30}
214
+ rows={10}
215
+ defaultValue={product.notes}
216
+ ></textarea>
217
+ </div>
218
+ </div>
219
+ )}
220
+
221
+ {product.can_upload_file && (
222
+ <div
223
+ className={`collapse-content ${activeCollapse === `file_${product.id}` ? 'is-opened' : 'is-closed'}`}
224
+ >
225
+ <div className="pt-4 px-1">
226
+ <SallaFileUpload
227
+ accept="image/png, image/jpeg, image/jpg, image/gif, video/*, application/pdf"
228
+ className="product-option-uploader"
229
+ >
230
+ <div className="product-option-uploader-placholder">
231
+ <span className="product-option-uploader-placholder-icon">
232
+ <i className="sicon-camera"></i>
233
+ </span>
234
+ <p className="profile-filepond-placholder-text">
235
+ {t('common.uploader.drag_and_drop', 'Drag and drop files here')}
236
+ </p>
237
+ <span className="filepond--label-action">
238
+ {t('common.uploader.browse', 'Browse')}
239
+ </span>
240
+ </div>
241
+ </SallaFileUpload>
242
+ </div>
243
+ </div>
244
+ )}
245
+ </div>
246
+ </div>
247
+ </section>
248
+ )}
249
+
250
+ {formEndSlot}
251
+
252
+ <section className="flex bg-white p-5 sm:pb-0 rounded-md rounded-b-none">
253
+ <div className="center-between w-full">
254
+ <div className="form-label">
255
+ <b className="block">{t('pages.products.price', 'Price')}</b>
256
+ </div>
257
+
258
+ <div
259
+ className={`flex whitespace-nowrap price-wrapper gap-4 items-center ${product.is_out_of_stock ? 'hidden' : ''}`}
260
+ >
261
+ <div
262
+ className={`price_is_on_sale space-x-2 rtl:space-x-reverse whitespace-nowrap ${product.is_on_sale ? '' : 'hidden'}`}
263
+ >
264
+ <span className="total-price text-red-800 font-bold text-xl inline-block">
265
+ {product.sale_price} <CurrencySymbol currency={priceCurrency} />
266
+ </span>
267
+ <span className="before-price text-gray-500 line-through">
268
+ {product.regular_price} <CurrencySymbol currency={priceCurrency} />
269
+ </span>
270
+ </div>
271
+ <div
272
+ className={`starting-or-normal-price gap-4 ${product.is_on_sale ? 'hidden' : 'flex'}`}
273
+ >
274
+ {product.starting_price && (
275
+ <span className="starting-price-title">
276
+ {t('pages.products.starting_price', 'Starting from')}
277
+ </span>
278
+ )}
279
+ <span className="total-price font-bold text-xl inline-block">
280
+ {String(product.starting_price ?? product.price)}{' '}
281
+ <CurrencySymbol currency={priceCurrency} />
282
+ </span>
283
+ </div>
284
+ </div>
285
+
286
+ <div
287
+ className={`out-of-stock min-h-7 leading-7 text-base text-red-600 !opacity-50 font-bold ${product.is_out_of_stock ? 'scale-pulse' : 'hidden'}`}
288
+ >
289
+ {t('pages.products.out_of_stock', 'Out of Stock')}
290
+ </div>
291
+ </div>
292
+ </section>
293
+
294
+ {hasPreorder ? (
295
+ <section className="mt-5 p-5">
296
+ <SallaCountDown preOrder={JSON.stringify(product.preorder)} boxed labeled />
297
+ </section>
298
+ ) : null}
299
+
300
+ <section className="sticky-product-bar bg-white p-5 rounded-md rounded-b-none">
301
+ {product.is_hidden_quantity || product.type === 'booking' ? (
302
+ <input
303
+ type="hidden"
304
+ value="1"
305
+ name="quantity"
306
+ aria-label={t('pages.products.quantity', 'Quantity')}
307
+ />
308
+ ) : (
309
+ <div className="sticky-product-bar__quantity center-between mb-5">
310
+ <span className="form-label font-bold">{t('pages.products.quantity', 'Quantity')}</span>
311
+ <SallaQuantityInput
312
+ ref={quantityRef}
313
+ max={product.max_quantity ?? undefined}
314
+ value={1}
315
+ name="quantity"
316
+ aria-label={t('pages.products.quantity', 'Quantity')}
317
+ className="border-gray-200 flex justify-end"
318
+ />
319
+ </div>
320
+ )}
321
+
322
+ <SallaAddProductButton
323
+ ref={addButtonRef}
324
+ {...(product.can_quick_buy ? { quickBuy: true } : {})}
325
+ {...(stickyAddToCart ? { supportStickyBar: true } : {})}
326
+ {...(product.is_require_shipping ? { requiredShipping: true } : {})}
327
+ {...(hasPreorder ? { hasPreOrder: true } : {})}
328
+ amount={amount}
329
+ className="mt-5 w-full sticky-product-bar__btn"
330
+ productStatus={product.status}
331
+ productType={product.type}
332
+ productId={product.id}
333
+ loaderPosition="end"
334
+ type="submit"
335
+ width="wide"
336
+ {...(product.notify_availability
337
+ ? {
338
+ ...(product.notify_availability.subscribed ? { isSubscribed: true } : {}),
339
+ channels: product.notify_availability.channels.join(','),
340
+ ...(product.notify_availability.subscribed_options
341
+ ? {
342
+ subscribedOptions: JSON.stringify(
343
+ product.notify_availability.subscribed_options
344
+ ),
345
+ }
346
+ : {}),
347
+ ...(product.notify_availability.options ? { notifyOptionsAvailability: true } : {}),
348
+ }
349
+ : {})}
350
+ >
351
+ {product.add_to_cart_label}
352
+ </SallaAddProductButton>
353
+ </section>
354
+
355
+ {product.giftable && (
356
+ <SallaGifting
357
+ className="mt-5"
358
+ widgetSubtitle={giftingIntro}
359
+ productId={Number(product.id)}
360
+ {...(product.is_require_shipping ? { physicalProducts: true } : {})}
361
+ />
362
+ )}
363
+ </form>
364
+ );
365
+ }