@fayz-ai/storefront 0.9.0 → 0.10.0

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 (368) hide show
  1. package/README.md +3 -3
  2. package/dist/app/createStorefrontApp.d.ts +65 -0
  3. package/dist/app/createStorefrontApp.d.ts.map +1 -0
  4. package/dist/{define.d.ts → app/define.d.ts} +3 -3
  5. package/dist/app/define.d.ts.map +1 -0
  6. package/dist/app/hydration.d.ts +37 -0
  7. package/dist/app/hydration.d.ts.map +1 -0
  8. package/dist/app/prerender.d.ts +57 -0
  9. package/dist/app/prerender.d.ts.map +1 -0
  10. package/dist/{router.d.ts → app/router.d.ts} +140 -113
  11. package/dist/app/router.d.ts.map +1 -0
  12. package/dist/{scaffold.d.ts → app/scaffold.d.ts} +2 -2
  13. package/dist/app/scaffold.d.ts.map +1 -0
  14. package/dist/app/serving.d.ts +70 -0
  15. package/dist/app/serving.d.ts.map +1 -0
  16. package/dist/app/static-render.d.ts +46 -0
  17. package/dist/app/static-render.d.ts.map +1 -0
  18. package/dist/blocks/block-at-path.d.ts +59 -0
  19. package/dist/blocks/block-at-path.d.ts.map +1 -0
  20. package/dist/blocks/page-blocks.d.ts +163 -0
  21. package/dist/blocks/page-blocks.d.ts.map +1 -0
  22. package/dist/blocks/page-data.d.ts +105 -0
  23. package/dist/blocks/page-data.d.ts.map +1 -0
  24. package/dist/{blocks.d.ts → blocks/registry.d.ts} +1 -1
  25. package/dist/blocks/registry.d.ts.map +1 -0
  26. package/dist/{sections.d.ts → blocks/sections.d.ts} +40 -2
  27. package/dist/blocks/sections.d.ts.map +1 -0
  28. package/dist/chunk-6B7H3IZ6.js +10232 -0
  29. package/dist/chunk-6B7H3IZ6.js.map +1 -0
  30. package/dist/chunk-6IXTENLB.js +162 -0
  31. package/dist/chunk-6IXTENLB.js.map +1 -0
  32. package/dist/components/PaymentTerms.d.ts +34 -0
  33. package/dist/components/PaymentTerms.d.ts.map +1 -0
  34. package/dist/components/SmoothImage.d.ts +1 -1
  35. package/dist/components/SmoothImage.d.ts.map +1 -1
  36. package/dist/components/account/CustomerAccountShell.d.ts.map +1 -0
  37. package/dist/components/account/SignInModal.d.ts.map +1 -0
  38. package/dist/components/cart/CartDrawer.d.ts.map +1 -0
  39. package/dist/components/cart/QuantityInput.d.ts.map +1 -0
  40. package/dist/components/checkout/DeliveryEstimator.d.ts.map +1 -0
  41. package/dist/components/collection/CategoryShowcase.d.ts +44 -0
  42. package/dist/components/collection/CategoryShowcase.d.ts.map +1 -0
  43. package/dist/components/collection/FiltersPanel.d.ts +19 -0
  44. package/dist/components/collection/FiltersPanel.d.ts.map +1 -0
  45. package/dist/components/collection/ProductGrid.d.ts.map +1 -0
  46. package/dist/components/layout/PageBodyBlocks.d.ts +40 -0
  47. package/dist/components/layout/PageBodyBlocks.d.ts.map +1 -0
  48. package/dist/components/layout/SearchOverlay.d.ts +13 -0
  49. package/dist/components/layout/SearchOverlay.d.ts.map +1 -0
  50. package/dist/components/layout/StorefrontErrorBoundary.d.ts.map +1 -0
  51. package/dist/components/layout/StorefrontFooter.d.ts.map +1 -0
  52. package/dist/components/layout/StorefrontHeader.d.ts.map +1 -0
  53. package/dist/components/layout/Toaster.d.ts.map +1 -0
  54. package/dist/components/marketing/CollectionSections.d.ts +463 -0
  55. package/dist/components/marketing/CollectionSections.d.ts.map +1 -0
  56. package/dist/components/marketing/ConversionSections.d.ts +221 -0
  57. package/dist/components/marketing/ConversionSections.d.ts.map +1 -0
  58. package/dist/components/marketing/EditorialSections.d.ts +248 -0
  59. package/dist/components/marketing/EditorialSections.d.ts.map +1 -0
  60. package/dist/components/marketing/EntityList.d.ts +97 -0
  61. package/dist/components/marketing/EntityList.d.ts.map +1 -0
  62. package/dist/components/marketing/FormBlock.d.ts +167 -0
  63. package/dist/components/marketing/FormBlock.d.ts.map +1 -0
  64. package/dist/components/marketing/HeroSection.d.ts +125 -0
  65. package/dist/components/marketing/HeroSection.d.ts.map +1 -0
  66. package/dist/components/marketing/MediaCarousel.d.ts +135 -0
  67. package/dist/components/marketing/MediaCarousel.d.ts.map +1 -0
  68. package/dist/components/marketing/MiscSections.d.ts +252 -0
  69. package/dist/components/marketing/MiscSections.d.ts.map +1 -0
  70. package/dist/components/order/OrderTrackingTimeline.d.ts.map +1 -0
  71. package/dist/components/product/ProductCard.d.ts +14 -0
  72. package/dist/components/product/ProductCard.d.ts.map +1 -0
  73. package/dist/components/product/ProductEnquiryForm.d.ts.map +1 -0
  74. package/dist/components/product/ProductGallery.d.ts +36 -0
  75. package/dist/components/product/ProductGallery.d.ts.map +1 -0
  76. package/dist/components/{ProductOptionSelector.d.ts → product/ProductOptionSelector.d.ts} +1 -1
  77. package/dist/components/product/ProductOptionSelector.d.ts.map +1 -0
  78. package/dist/components/product/ProductRail.d.ts +93 -0
  79. package/dist/components/product/ProductRail.d.ts.map +1 -0
  80. package/dist/components/product/ProductReviews.d.ts +39 -0
  81. package/dist/components/product/ProductReviews.d.ts.map +1 -0
  82. package/dist/components/product/ProductSlider.d.ts +169 -0
  83. package/dist/components/product/ProductSlider.d.ts.map +1 -0
  84. package/dist/components/product/ProductSpecs.d.ts.map +1 -0
  85. package/dist/components/product/RelatedProducts.d.ts.map +1 -0
  86. package/dist/{auth.d.ts → data/auth.d.ts} +9 -0
  87. package/dist/data/auth.d.ts.map +1 -0
  88. package/dist/data/facets.d.ts +39 -0
  89. package/dist/data/facets.d.ts.map +1 -0
  90. package/dist/data/loaders.d.ts +56 -0
  91. package/dist/data/loaders.d.ts.map +1 -0
  92. package/dist/data/order-status.d.ts.map +1 -0
  93. package/dist/data/product-options.d.ts +36 -0
  94. package/dist/data/product-options.d.ts.map +1 -0
  95. package/dist/diagnostics/seo-audit.d.ts +54 -0
  96. package/dist/diagnostics/seo-audit.d.ts.map +1 -0
  97. package/dist/diagnostics/seo-audit.js +3 -0
  98. package/dist/diagnostics/seo-audit.js.map +1 -0
  99. package/dist/document/change.d.ts +100 -0
  100. package/dist/document/change.d.ts.map +1 -0
  101. package/dist/{config.d.ts → document/config.d.ts} +126 -7
  102. package/dist/document/config.d.ts.map +1 -0
  103. package/dist/document/describe.d.ts +135 -0
  104. package/dist/document/describe.d.ts.map +1 -0
  105. package/dist/document/overlay.d.ts +58 -0
  106. package/dist/document/overlay.d.ts.map +1 -0
  107. package/dist/{presets.d.ts → document/presets.d.ts} +2 -2
  108. package/dist/document/presets.d.ts.map +1 -0
  109. package/dist/document/render.d.ts +171 -0
  110. package/dist/document/render.d.ts.map +1 -0
  111. package/dist/document/round-trip.d.ts +46 -0
  112. package/dist/document/round-trip.d.ts.map +1 -0
  113. package/dist/document/sections.d.ts +194 -0
  114. package/dist/document/sections.d.ts.map +1 -0
  115. package/dist/document/upgrade.d.ts +112 -0
  116. package/dist/document/upgrade.d.ts.map +1 -0
  117. package/dist/document/validate.d.ts +24 -0
  118. package/dist/document/validate.d.ts.map +1 -0
  119. package/dist/{component-contracts.d.ts → extend/component-contracts.d.ts} +74 -22
  120. package/dist/extend/component-contracts.d.ts.map +1 -0
  121. package/dist/extend/component-override.d.ts +38 -0
  122. package/dist/extend/component-override.d.ts.map +1 -0
  123. package/dist/extend/component-selectors.d.ts.map +1 -0
  124. package/dist/extend/editor-bridge.d.ts +59 -0
  125. package/dist/extend/editor-bridge.d.ts.map +1 -0
  126. package/dist/extend/extension-points.d.ts +103 -0
  127. package/dist/extend/extension-points.d.ts.map +1 -0
  128. package/dist/extend/slots.d.ts +216 -0
  129. package/dist/extend/slots.d.ts.map +1 -0
  130. package/dist/hooks/index.d.ts +25 -6
  131. package/dist/hooks/index.d.ts.map +1 -1
  132. package/dist/hooks/use-address.d.ts +26 -0
  133. package/dist/hooks/use-address.d.ts.map +1 -0
  134. package/dist/hooks/use-cart.d.ts +3 -0
  135. package/dist/hooks/use-cart.d.ts.map +1 -0
  136. package/dist/hooks/use-catalog.d.ts +24 -0
  137. package/dist/hooks/use-catalog.d.ts.map +1 -0
  138. package/dist/hooks/use-categories.d.ts +19 -0
  139. package/dist/hooks/use-categories.d.ts.map +1 -0
  140. package/dist/hooks/use-checkout.d.ts +41 -0
  141. package/dist/hooks/use-checkout.d.ts.map +1 -0
  142. package/dist/hooks/use-discount-validator.d.ts +20 -0
  143. package/dist/hooks/use-discount-validator.d.ts.map +1 -0
  144. package/dist/hooks/use-enquiry.d.ts +7 -0
  145. package/dist/hooks/use-enquiry.d.ts.map +1 -0
  146. package/dist/hooks/{useMyOrders.d.ts → use-my-orders.d.ts} +1 -1
  147. package/dist/hooks/use-my-orders.d.ts.map +1 -0
  148. package/dist/hooks/use-order.d.ts +17 -0
  149. package/dist/hooks/use-order.d.ts.map +1 -0
  150. package/dist/hooks/use-payment-methods.d.ts +19 -0
  151. package/dist/hooks/use-payment-methods.d.ts.map +1 -0
  152. package/dist/hooks/use-policies.d.ts +25 -0
  153. package/dist/hooks/use-policies.d.ts.map +1 -0
  154. package/dist/hooks/use-product.d.ts +15 -0
  155. package/dist/hooks/use-product.d.ts.map +1 -0
  156. package/dist/hooks/{useProducts.d.ts → use-products.d.ts} +1 -1
  157. package/dist/hooks/use-products.d.ts.map +1 -0
  158. package/dist/hooks/use-region.d.ts +15 -0
  159. package/dist/hooks/use-region.d.ts.map +1 -0
  160. package/dist/hooks/use-shipping.d.ts +29 -0
  161. package/dist/hooks/use-shipping.d.ts.map +1 -0
  162. package/dist/hooks/use-storefront-actions.d.ts +12 -0
  163. package/dist/hooks/use-storefront-actions.d.ts.map +1 -0
  164. package/dist/hooks/use-storefront-head.d.ts +19 -0
  165. package/dist/hooks/use-storefront-head.d.ts.map +1 -0
  166. package/dist/hooks/use-storefront.d.ts +3 -0
  167. package/dist/hooks/use-storefront.d.ts.map +1 -0
  168. package/dist/index.d.ts +123 -54
  169. package/dist/index.d.ts.map +1 -1
  170. package/dist/index.js +1311 -5012
  171. package/dist/index.js.map +1 -1
  172. package/dist/lib/format.d.ts.map +1 -0
  173. package/dist/lib/motion.d.ts.map +1 -0
  174. package/dist/lib/seo.d.ts +26 -0
  175. package/dist/lib/seo.d.ts.map +1 -0
  176. package/dist/{testids.d.ts → lib/testids.d.ts} +21 -0
  177. package/dist/lib/testids.d.ts.map +1 -0
  178. package/dist/{theme.d.ts → lib/theme.d.ts} +41 -3
  179. package/dist/lib/theme.d.ts.map +1 -0
  180. package/dist/render.d.ts +5 -0
  181. package/dist/render.d.ts.map +1 -0
  182. package/dist/render.js +359 -0
  183. package/dist/render.js.map +1 -0
  184. package/dist/stores/cart.store.d.ts +6 -2
  185. package/dist/stores/cart.store.d.ts.map +1 -1
  186. package/dist/stores/catalog.store.d.ts +11 -0
  187. package/dist/stores/catalog.store.d.ts.map +1 -1
  188. package/dist/views/CatalogPage.d.ts.map +1 -0
  189. package/dist/views/CheckoutPage.d.ts.map +1 -0
  190. package/dist/views/ContentPage.d.ts +11 -0
  191. package/dist/views/ContentPage.d.ts.map +1 -0
  192. package/dist/views/HomePage.d.ts +9 -0
  193. package/dist/views/HomePage.d.ts.map +1 -0
  194. package/dist/views/MyPurchasesPage.d.ts.map +1 -0
  195. package/dist/views/NotFoundPage.d.ts.map +1 -0
  196. package/dist/{pages → views}/OrderConfirmationPage.d.ts.map +1 -1
  197. package/dist/{pages → views}/PolicyPage.d.ts.map +1 -1
  198. package/dist/views/ProductDetailPage.d.ts.map +1 -0
  199. package/dist/views/StorefrontPage.d.ts +35 -0
  200. package/dist/views/StorefrontPage.d.ts.map +1 -0
  201. package/dist/workflows/checkout.d.ts +1 -1
  202. package/dist/workflows/checkout.d.ts.map +1 -1
  203. package/package.json +21 -14
  204. package/dist/auth.d.ts.map +0 -1
  205. package/dist/blocks.d.ts.map +0 -1
  206. package/dist/component-contracts.d.ts.map +0 -1
  207. package/dist/component-selectors.d.ts.map +0 -1
  208. package/dist/components/CartDrawer.d.ts.map +0 -1
  209. package/dist/components/CustomerAccountShell.d.ts.map +0 -1
  210. package/dist/components/DeliveryEstimator.d.ts.map +0 -1
  211. package/dist/components/FiltersPanel.d.ts +0 -3
  212. package/dist/components/FiltersPanel.d.ts.map +0 -1
  213. package/dist/components/OrderTrackingTimeline.d.ts.map +0 -1
  214. package/dist/components/ProductCard.d.ts +0 -4
  215. package/dist/components/ProductCard.d.ts.map +0 -1
  216. package/dist/components/ProductEnquiryForm.d.ts.map +0 -1
  217. package/dist/components/ProductGallery.d.ts +0 -22
  218. package/dist/components/ProductGallery.d.ts.map +0 -1
  219. package/dist/components/ProductGrid.d.ts.map +0 -1
  220. package/dist/components/ProductOptionSelector.d.ts.map +0 -1
  221. package/dist/components/ProductSpecs.d.ts.map +0 -1
  222. package/dist/components/QuantityInput.d.ts.map +0 -1
  223. package/dist/components/RelatedProducts.d.ts.map +0 -1
  224. package/dist/components/SignInModal.d.ts.map +0 -1
  225. package/dist/components/StorefrontErrorBoundary.d.ts.map +0 -1
  226. package/dist/components/StorefrontFooter.d.ts.map +0 -1
  227. package/dist/components/StorefrontHeader.d.ts.map +0 -1
  228. package/dist/components/Toaster.d.ts.map +0 -1
  229. package/dist/components/sections/CategoryShowcase.d.ts +0 -6
  230. package/dist/components/sections/CategoryShowcase.d.ts.map +0 -1
  231. package/dist/components/sections/HeroSection.d.ts +0 -9
  232. package/dist/components/sections/HeroSection.d.ts.map +0 -1
  233. package/dist/components/sections/MediaCarousel.d.ts +0 -11
  234. package/dist/components/sections/MediaCarousel.d.ts.map +0 -1
  235. package/dist/components/sections/MiscSections.d.ts +0 -33
  236. package/dist/components/sections/MiscSections.d.ts.map +0 -1
  237. package/dist/components/sections/ProductRail.d.ts +0 -9
  238. package/dist/components/sections/ProductRail.d.ts.map +0 -1
  239. package/dist/components/sections/ProductSlider.d.ts +0 -15
  240. package/dist/components/sections/ProductSlider.d.ts.map +0 -1
  241. package/dist/config.d.ts.map +0 -1
  242. package/dist/createStorefrontApp.d.ts +0 -28
  243. package/dist/createStorefrontApp.d.ts.map +0 -1
  244. package/dist/define.d.ts.map +0 -1
  245. package/dist/format.d.ts.map +0 -1
  246. package/dist/hooks/useCategories.d.ts +0 -6
  247. package/dist/hooks/useCategories.d.ts.map +0 -1
  248. package/dist/hooks/useDiscountValidator.d.ts +0 -14
  249. package/dist/hooks/useDiscountValidator.d.ts.map +0 -1
  250. package/dist/hooks/useMyOrders.d.ts.map +0 -1
  251. package/dist/hooks/useProduct.d.ts +0 -7
  252. package/dist/hooks/useProduct.d.ts.map +0 -1
  253. package/dist/hooks/useProducts.d.ts.map +0 -1
  254. package/dist/hooks/useStorefront.d.ts +0 -35
  255. package/dist/hooks/useStorefront.d.ts.map +0 -1
  256. package/dist/hooks/useStorefrontHead.d.ts +0 -11
  257. package/dist/hooks/useStorefrontHead.d.ts.map +0 -1
  258. package/dist/motion.d.ts.map +0 -1
  259. package/dist/order-status.d.ts.map +0 -1
  260. package/dist/pages/CatalogPage.d.ts.map +0 -1
  261. package/dist/pages/CheckoutPage.d.ts.map +0 -1
  262. package/dist/pages/HomePage.d.ts +0 -9
  263. package/dist/pages/HomePage.d.ts.map +0 -1
  264. package/dist/pages/MyPurchasesPage.d.ts.map +0 -1
  265. package/dist/pages/NotFoundPage.d.ts.map +0 -1
  266. package/dist/pages/ProductDetailPage.d.ts.map +0 -1
  267. package/dist/presets.d.ts.map +0 -1
  268. package/dist/product-options.d.ts +0 -12
  269. package/dist/product-options.d.ts.map +0 -1
  270. package/dist/router.d.ts.map +0 -1
  271. package/dist/scaffold.d.ts.map +0 -1
  272. package/dist/sections.d.ts.map +0 -1
  273. package/dist/testids.d.ts.map +0 -1
  274. package/dist/theme.d.ts.map +0 -1
  275. package/src/auth.ts +0 -227
  276. package/src/blocks.tsx +0 -51
  277. package/src/catalog.ts +0 -3
  278. package/src/component-contracts.ts +0 -154
  279. package/src/component-selectors.ts +0 -31
  280. package/src/components/CartDrawer.tsx +0 -279
  281. package/src/components/CustomerAccountShell.tsx +0 -102
  282. package/src/components/DeliveryEstimator.tsx +0 -157
  283. package/src/components/FiltersPanel.tsx +0 -109
  284. package/src/components/OrderTrackingTimeline.tsx +0 -135
  285. package/src/components/Price.tsx +0 -32
  286. package/src/components/ProductCard.tsx +0 -120
  287. package/src/components/ProductEnquiryForm.tsx +0 -175
  288. package/src/components/ProductGallery.tsx +0 -174
  289. package/src/components/ProductGrid.tsx +0 -43
  290. package/src/components/ProductOptionSelector.tsx +0 -50
  291. package/src/components/ProductSpecs.tsx +0 -75
  292. package/src/components/QuantityInput.tsx +0 -52
  293. package/src/components/RelatedProducts.tsx +0 -40
  294. package/src/components/SignInModal.tsx +0 -120
  295. package/src/components/SmoothImage.tsx +0 -59
  296. package/src/components/StorefrontErrorBoundary.tsx +0 -51
  297. package/src/components/StorefrontFooter.tsx +0 -110
  298. package/src/components/StorefrontHeader.tsx +0 -477
  299. package/src/components/Toaster.tsx +0 -60
  300. package/src/components/sections/CategoryShowcase.tsx +0 -80
  301. package/src/components/sections/HeroSection.tsx +0 -193
  302. package/src/components/sections/MediaCarousel.tsx +0 -141
  303. package/src/components/sections/MiscSections.tsx +0 -158
  304. package/src/components/sections/ProductRail.tsx +0 -81
  305. package/src/components/sections/ProductSlider.tsx +0 -119
  306. package/src/config.ts +0 -229
  307. package/src/createStorefrontApp.tsx +0 -247
  308. package/src/define.ts +0 -34
  309. package/src/format.ts +0 -7
  310. package/src/hooks/index.ts +0 -6
  311. package/src/hooks/useCategories.ts +0 -26
  312. package/src/hooks/useDiscountValidator.ts +0 -43
  313. package/src/hooks/useMyOrders.ts +0 -41
  314. package/src/hooks/useProduct.ts +0 -36
  315. package/src/hooks/useProducts.ts +0 -39
  316. package/src/hooks/useStorefront.ts +0 -58
  317. package/src/hooks/useStorefrontHead.ts +0 -25
  318. package/src/index.ts +0 -202
  319. package/src/motion.tsx +0 -94
  320. package/src/order-status.ts +0 -33
  321. package/src/pages/CatalogPage.tsx +0 -118
  322. package/src/pages/CheckoutPage.tsx +0 -689
  323. package/src/pages/HomePage.tsx +0 -16
  324. package/src/pages/MyPurchasesPage.tsx +0 -311
  325. package/src/pages/NotFoundPage.tsx +0 -25
  326. package/src/pages/OrderConfirmationPage.tsx +0 -190
  327. package/src/pages/PolicyPage.tsx +0 -47
  328. package/src/pages/ProductDetailPage.tsx +0 -264
  329. package/src/presets.ts +0 -324
  330. package/src/product-options.ts +0 -63
  331. package/src/router.ts +0 -49
  332. package/src/scaffold.tsx +0 -115
  333. package/src/sections.ts +0 -116
  334. package/src/shop.ts +0 -4
  335. package/src/stores/cart.store.ts +0 -185
  336. package/src/stores/catalog.store.ts +0 -39
  337. package/src/stores/delivery.store.ts +0 -152
  338. package/src/stores/session.store.ts +0 -28
  339. package/src/stores/toast.store.ts +0 -43
  340. package/src/testids.ts +0 -136
  341. package/src/theme.ts +0 -194
  342. package/src/ui.ts +0 -5
  343. package/src/workflows/checkout.ts +0 -119
  344. /package/dist/components/{CustomerAccountShell.d.ts → account/CustomerAccountShell.d.ts} +0 -0
  345. /package/dist/components/{SignInModal.d.ts → account/SignInModal.d.ts} +0 -0
  346. /package/dist/components/{CartDrawer.d.ts → cart/CartDrawer.d.ts} +0 -0
  347. /package/dist/components/{QuantityInput.d.ts → cart/QuantityInput.d.ts} +0 -0
  348. /package/dist/components/{DeliveryEstimator.d.ts → checkout/DeliveryEstimator.d.ts} +0 -0
  349. /package/dist/components/{ProductGrid.d.ts → collection/ProductGrid.d.ts} +0 -0
  350. /package/dist/components/{StorefrontErrorBoundary.d.ts → layout/StorefrontErrorBoundary.d.ts} +0 -0
  351. /package/dist/components/{StorefrontFooter.d.ts → layout/StorefrontFooter.d.ts} +0 -0
  352. /package/dist/components/{StorefrontHeader.d.ts → layout/StorefrontHeader.d.ts} +0 -0
  353. /package/dist/components/{Toaster.d.ts → layout/Toaster.d.ts} +0 -0
  354. /package/dist/components/{OrderTrackingTimeline.d.ts → order/OrderTrackingTimeline.d.ts} +0 -0
  355. /package/dist/components/{ProductEnquiryForm.d.ts → product/ProductEnquiryForm.d.ts} +0 -0
  356. /package/dist/components/{ProductSpecs.d.ts → product/ProductSpecs.d.ts} +0 -0
  357. /package/dist/components/{RelatedProducts.d.ts → product/RelatedProducts.d.ts} +0 -0
  358. /package/dist/{order-status.d.ts → data/order-status.d.ts} +0 -0
  359. /package/dist/{component-selectors.d.ts → extend/component-selectors.d.ts} +0 -0
  360. /package/dist/{format.d.ts → lib/format.d.ts} +0 -0
  361. /package/dist/{motion.d.ts → lib/motion.d.ts} +0 -0
  362. /package/dist/{pages → views}/CatalogPage.d.ts +0 -0
  363. /package/dist/{pages → views}/CheckoutPage.d.ts +0 -0
  364. /package/dist/{pages → views}/MyPurchasesPage.d.ts +0 -0
  365. /package/dist/{pages → views}/NotFoundPage.d.ts +0 -0
  366. /package/dist/{pages → views}/OrderConfirmationPage.d.ts +0 -0
  367. /package/dist/{pages → views}/PolicyPage.d.ts +0 -0
  368. /package/dist/{pages → views}/ProductDetailPage.d.ts +0 -0
@@ -1,264 +0,0 @@
1
- import React, { useEffect, useState } from 'react'
2
- import { ChevronLeft, RefreshCcw, ShieldCheck, Truck } from 'lucide-react'
3
- import { useProduct } from '../hooks/useProduct'
4
- import { useCartStore } from '../stores/cart.store'
5
- import { getStorefrontComponents, useStorefrontConfig } from '../config'
6
- import { useStorefrontHead } from '../hooks/useStorefrontHead'
7
- import { useStorefrontActions } from '../hooks/useStorefront'
8
- import { Link } from '../router'
9
- import { Price } from '../components/Price'
10
- import { QuantityInput } from '../components/QuantityInput'
11
- import { ProductOptionSelector } from '../components/ProductOptionSelector'
12
- import { ProductSpecs } from '../components/ProductSpecs'
13
- import { RelatedProducts } from '../components/RelatedProducts'
14
- import { ProductEnquiryForm } from '../components/ProductEnquiryForm'
15
- import { SmoothImage } from '../components/SmoothImage'
16
- import { ProductGallery } from '../components/ProductGallery'
17
- import { DeliveryEstimator } from '../components/DeliveryEstimator'
18
- import { getProductOptionGroups, type ProductOptionSelection } from '../product-options'
19
- import { storefrontComponentContracts } from '../component-selectors'
20
- import { TID } from '../testids'
21
-
22
- export function ProductDetailPage({ slug }: { slug: string }) {
23
- const config = useStorefrontConfig()
24
- const actions = useStorefrontActions()
25
- const { product, loading } = useProduct(slug)
26
- const addItem = useCartStore((s) => s.addItem)
27
- const [qty, setQty] = useState(1)
28
- const [selectedOptions, setSelectedOptions] = useState<ProductOptionSelection>({})
29
-
30
- const optionGroups = product ? getProductOptionGroups(product) : []
31
- useStorefrontHead({
32
- title: product ? `${product.name} — ${config.name}` : config.name,
33
- description: product?.description,
34
- })
35
-
36
- useEffect(() => {
37
- if (!product) return
38
- const defaults = Object.fromEntries(
39
- getProductOptionGroups(product).map((group) => [group.label, group.values[0] ?? '']),
40
- )
41
- setSelectedOptions(defaults)
42
- }, [product?.id])
43
-
44
- if (loading) {
45
- return (
46
- <main className="mx-auto max-w-5xl px-4 py-8 sm:px-6">
47
- <div className="grid animate-pulse gap-10 md:grid-cols-2">
48
- <div className="aspect-square rounded-2xl bg-muted" />
49
- <div className="space-y-4 py-4">
50
- <div className="h-8 w-3/4 rounded bg-muted" />
51
- <div className="h-6 w-1/3 rounded bg-muted" />
52
- <div className="h-24 rounded bg-muted" />
53
- </div>
54
- </div>
55
- </main>
56
- )
57
- }
58
-
59
- if (!product) {
60
- return (
61
- <main className="mx-auto max-w-5xl px-4 py-20 text-center sm:px-6">
62
- <p className="text-lg text-muted-foreground">Produto não encontrado.</p>
63
- <Link to="/" className="mt-4 inline-block text-primary underline">Voltar à loja</Link>
64
- </main>
65
- )
66
- }
67
-
68
- const soldOut = product.inventoryCount <= 0
69
- const lowStock = !soldOut && product.inventoryCount <= 5
70
- const image = product.images.find((i) => i.isPrimary) ?? product.images[0]
71
- const components = getStorefrontComponents(config)
72
- const ProductDetailComponent = components.ProductDetail
73
- // Honours the ProductGallery override contract, which has existed in
74
- // component-contracts.ts since before any component implemented it.
75
- const GalleryComponent = components.ProductGallery ?? ProductGallery
76
- const addToCart = () => addItem(product, qty, selectedOptions)
77
- const openEnquiry = () => {
78
- document.getElementById('storefront-product-enquiry')?.scrollIntoView({ behavior: 'smooth', block: 'start' })
79
- }
80
- const discountPct =
81
- product.compareAtPrice && product.compareAtPrice > product.price
82
- ? Math.round((1 - product.price / product.compareAtPrice) * 100)
83
- : 0
84
-
85
- if (ProductDetailComponent) {
86
- return (
87
- <ProductDetailComponent
88
- product={product}
89
- config={config}
90
- commerceMode={config.commerceMode}
91
- primaryImage={image}
92
- optionGroups={optionGroups}
93
- selectedOptions={selectedOptions}
94
- setSelectedOptions={setSelectedOptions}
95
- quantity={qty}
96
- setQuantity={setQty}
97
- soldOut={soldOut}
98
- lowStock={lowStock}
99
- actions={actions}
100
- addToCart={addToCart}
101
- openEnquiry={openEnquiry}
102
- />
103
- )
104
- }
105
-
106
- return (
107
- <main {...storefrontComponentContracts.productDetail.root} className="mx-auto max-w-5xl px-4 py-8 sm:px-6">
108
- <Link to="/" className="mb-6 inline-flex items-center gap-1 text-sm text-muted-foreground hover:text-foreground">
109
- <ChevronLeft className="h-4 w-4" /> Continuar comprando
110
- </Link>
111
-
112
- <div className="grid animate-fade-up grid-cols-1 gap-10 md:grid-cols-2">
113
- <GalleryComponent
114
- product={product}
115
- images={product.images}
116
- primaryImage={image}
117
- config={config}
118
- commerceMode={config.commerceMode}
119
- />
120
-
121
- <div className="flex flex-col py-2 lg:sticky lg:top-24 lg:self-start">
122
- <nav className="mb-3 flex flex-wrap items-center gap-1.5 text-xs text-muted-foreground">
123
- <Link to="/" className="transition-colors hover:text-foreground">Início</Link>
124
- {product.categoryName && (
125
- <>
126
- <span aria-hidden>/</span>
127
- <span>{product.categoryName}</span>
128
- </>
129
- )}
130
- <span aria-hidden>/</span>
131
- <span className="text-foreground">{product.name}</span>
132
- </nav>
133
-
134
- <h1 data-testid={TID.pdpName} className="sf-heading text-3xl font-bold tracking-tight">
135
- {product.name}
136
- </h1>
137
-
138
- {config.commerceMode === 'checkout' && (
139
- <div className="mt-3 flex items-center gap-3">
140
- <div className="text-xl">
141
- <Price
142
- value={product.price}
143
- compareAt={product.compareAtPrice}
144
- testId={TID.pdpPrice}
145
- compareTestId={TID.pdpComparePrice}
146
- />
147
- </div>
148
- {discountPct > 0 && (
149
- <span className="rounded-full bg-primary/10 px-2.5 py-1 text-xs font-bold text-primary">
150
- −{discountPct}%
151
- </span>
152
- )}
153
- </div>
154
- )}
155
-
156
- <p data-testid={TID.pdpDescription} className="mt-5 leading-relaxed text-muted-foreground">
157
- {product.description}
158
- </p>
159
-
160
- {config.commerceMode === 'checkout' && (
161
- <div className="mt-4 flex flex-wrap items-center gap-x-3 gap-y-1 text-sm">
162
- {soldOut ? (
163
- <span className="inline-flex items-center gap-2 font-medium text-muted-foreground">
164
- <span className="h-2 w-2 rounded-full bg-muted-foreground" /> Sem estoque
165
- </span>
166
- ) : lowStock ? (
167
- <span className="inline-flex items-center gap-2 font-semibold text-amber-600">
168
- <span className="h-2 w-2 animate-pulse rounded-full bg-amber-500" />
169
- Últimas unidades — só {product.inventoryCount} restantes
170
- </span>
171
- ) : (
172
- <span className="inline-flex items-center gap-2 font-medium text-emerald-600">
173
- <span className="h-2 w-2 rounded-full bg-emerald-500" /> Em estoque
174
- </span>
175
- )}
176
- {product.sku && <span className="text-muted-foreground">SKU: {product.sku}</span>}
177
- </div>
178
- )}
179
-
180
- <ProductOptionSelector
181
- groups={optionGroups}
182
- value={selectedOptions}
183
- onChange={setSelectedOptions}
184
- />
185
-
186
- <div {...storefrontComponentContracts.productDetail.actions} className="mt-8">
187
- {config.commerceMode === 'checkout' ? (
188
- <div className="flex items-center gap-4">
189
- <QuantityInput
190
- value={qty}
191
- onChange={setQty}
192
- max={soldOut ? 1 : product.inventoryCount}
193
- testId={TID.pdpQtyInput}
194
- />
195
- <button
196
- type="button"
197
- data-testid={TID.pdpAddToCart}
198
- disabled={soldOut}
199
- onClick={addToCart}
200
- className="sf-cta flex-1 bg-primary py-3.5 font-semibold text-primary-foreground shadow-md transition-all hover:-translate-y-0.5 hover:shadow-lg disabled:cursor-not-allowed disabled:opacity-40 disabled:shadow-none disabled:hover:translate-y-0"
201
- style={{ borderRadius: 'var(--sf-radius-button)' }}
202
- >
203
- {soldOut ? 'Esgotado' : 'Adicionar ao carrinho'}
204
- </button>
205
- </div>
206
- ) : config.commerceMode === 'enquiry' ? (
207
- <button
208
- type="button"
209
- {...storefrontComponentContracts.productDetail.enquiryButton}
210
- onClick={openEnquiry}
211
- className="sf-cta w-full bg-primary py-3.5 font-semibold text-primary-foreground shadow-md transition-all hover:-translate-y-0.5 hover:shadow-lg"
212
- style={{ borderRadius: 'var(--sf-radius-button)' }}
213
- >
214
- {config.enquiry.label}
215
- </button>
216
- ) : (
217
- <Link
218
- to={config.catalogPath}
219
- className="inline-flex border px-5 py-3 text-sm font-semibold transition-colors hover:bg-muted"
220
- style={{ borderRadius: 'var(--sf-radius-button)' }}
221
- >
222
- Voltar ao catálogo
223
- </Link>
224
- )}
225
- </div>
226
-
227
- {/* Asked here, before the cart exists: "do you deliver to me and for
228
- how much" is the question that decides whether this page converts,
229
- and it used to be answerable only at the end of checkout. */}
230
- {config.commerceMode === 'checkout' && <DeliveryEstimator />}
231
-
232
- {config.commerceMode === 'checkout' && (
233
- <div className="mt-6 grid grid-cols-3 gap-3 border-t pt-6 text-center">
234
- <div className="flex flex-col items-center gap-1.5 text-[11px] font-medium text-muted-foreground">
235
- <Truck className="h-5 w-5 text-primary" /> Envio rápido
236
- </div>
237
- <div className="flex flex-col items-center gap-1.5 text-[11px] font-medium text-muted-foreground">
238
- <RefreshCcw className="h-5 w-5 text-primary" /> Troca fácil
239
- </div>
240
- <div className="flex flex-col items-center gap-1.5 text-[11px] font-medium text-muted-foreground">
241
- <ShieldCheck className="h-5 w-5 text-primary" /> Pagamento seguro
242
- </div>
243
- </div>
244
- )}
245
- </div>
246
- </div>
247
-
248
- {config.commerceMode === 'enquiry' && (
249
- <section id="storefront-product-enquiry" className="mt-12 border-t pt-10">
250
- <div className="mx-auto max-w-3xl">
251
- <h2 className="sf-heading text-2xl font-semibold">Need more information?</h2>
252
- <p className="mt-2 text-muted-foreground">Send an enquiry about this product.</p>
253
- <div className="mt-6">
254
- <ProductEnquiryForm product={product} />
255
- </div>
256
- </div>
257
- </section>
258
- )}
259
-
260
- <ProductSpecs product={product} />
261
- <RelatedProducts product={product} />
262
- </main>
263
- )
264
- }
package/src/presets.ts DELETED
@@ -1,324 +0,0 @@
1
- import type { StorefrontTheme } from './theme'
2
- import type { HomeConfig } from './sections'
3
-
4
- // ---------------------------------------------------------------------------
5
- // Template presets — recreations of the four Nuvemshop patterns selected in
6
- // docs/storefront-templates-research.md. Each is { theme, home() } so an app
7
- // (or the Fayz agent) starts from a complete professional store and overrides
8
- // copy, colors, hero images and sections — the saas-core theming workflow.
9
- // ---------------------------------------------------------------------------
10
-
11
- /** Real imagery for a template home — resolved at build time (e.g. via
12
- * scripts/fetch-unsplash.mjs); falls back to gradient placeholders when omitted. */
13
- export interface TemplateImages {
14
- hero?: Array<string | undefined>
15
- banners?: Array<string | undefined>
16
- }
17
-
18
- export interface StorefrontTemplate {
19
- id: string
20
- /** The Nuvemshop pattern this recreates */
21
- inspiration: string
22
- theme: StorefrontTheme
23
- /** Default home blueprint — pass the store name for copy interpolation */
24
- home: (storeName: string, images?: TemplateImages) => HomeConfig
25
- announcement?: string
26
- }
27
-
28
- /** maré — elegant fashion (Rio): airy warm paper, olive ink, sand CTA, centered logo. */
29
- export const mareTemplate: StorefrontTemplate = {
30
- id: 'mare',
31
- inspiration: 'Nuvemshop Rio',
32
- announcement: 'FRETE GRÁTIS EM COMPRAS ACIMA DE R$ 300',
33
- theme: {
34
- name: 'mare',
35
- colors: {
36
- background: '40 14% 93%',
37
- foreground: '90 8% 38%',
38
- primary: '42 32% 61%',
39
- primaryForeground: '40 30% 12%',
40
- card: '40 20% 97%',
41
- cardForeground: '90 10% 25%',
42
- muted: '40 12% 88%',
43
- mutedForeground: '90 6% 50%',
44
- border: '40 10% 82%',
45
- announcementBackground: '90 10% 30%',
46
- announcementForeground: '40 20% 95%',
47
- },
48
- font: { heading: 'Plus Jakarta Sans', body: 'Plus Jakarta Sans' },
49
- radius: 'soft',
50
- header: { variant: 'centered' },
51
- productCard: { style: 'editorial', imageAspect: 'portrait' },
52
- },
53
- home: (storeName, images) => ({
54
- sections: [
55
- {
56
- type: 'hero',
57
- variant: 'banner',
58
- height: 'tall',
59
- slides: [
60
- { title: 'Feito para durar', subtitle: `A nova coleção ${storeName} chegou — peças atemporais em materiais honestos.`, cta: 'Ver coleção', hue: 75, image: images?.hero?.[0] },
61
- ],
62
- },
63
- { type: 'categories', style: 'bubbles' },
64
- { type: 'products', title: 'Destaques', filter: 'all', limit: 4 },
65
- { type: 'banner', title: 'Até 30% off', eyebrow: 'por tempo limitado', subtitle: 'Peças selecionadas da estação', cta: 'Aproveitar', hue: 40, image: images?.banners?.[0] },
66
- { type: 'products', title: 'Promoções', filter: 'sale', limit: 4 },
67
- { type: 'products', title: 'Lançamentos', filter: 'new', limit: 4 },
68
- { type: 'newsletter', title: 'Assine nossa newsletter', subtitle: 'Novidades e ofertas exclusivas, sem spam.' },
69
- ],
70
- }),
71
- }
72
-
73
- /** sertão — editorial organic (Uyuni): cream paper, coffee serif ink, boxed hero, manifesto. */
74
- export const sertaoTemplate: StorefrontTemplate = {
75
- id: 'sertao',
76
- inspiration: 'Nuvemshop Uyuni',
77
- theme: {
78
- name: 'sertao',
79
- colors: {
80
- background: '30 100% 98%',
81
- foreground: '28 42% 32%',
82
- primary: '28 42% 32%',
83
- primaryForeground: '30 100% 97%',
84
- card: '32 60% 96%',
85
- cardForeground: '28 40% 26%',
86
- muted: '32 40% 92%',
87
- mutedForeground: '28 22% 48%',
88
- border: '28 30% 80%',
89
- },
90
- font: { heading: 'Marcellus', body: 'Marcellus', fallback: 'serif' },
91
- radius: 'none',
92
- header: { variant: 'minimal', uppercaseNav: true },
93
- productCard: { style: 'editorial', imageAspect: 'portrait' },
94
- uppercaseButtons: true,
95
- },
96
- home: (storeName, images) => ({
97
- sections: [
98
- {
99
- type: 'hero',
100
- variant: 'banner',
101
- height: 'tall',
102
- slides: [
103
- { title: 'Essenciais naturais', subtitle: 'Conheça nossa coleção', cta: 'Ver mais', hue: 28, boxed: true, image: images?.hero?.[0] },
104
- ],
105
- },
106
- {
107
- type: 'manifesto',
108
- text: `Num mundo de pressa e excesso, ${storeName} escolhe o caminho lento: ingredientes honestos, produção pequena e cuidado em cada detalhe.`,
109
- },
110
- { type: 'categories', style: 'tiles' },
111
- { type: 'products', title: 'ESSENCIAIS', filter: 'all', limit: 4 },
112
- {
113
- type: 'testimonials',
114
- title: 'Nossos clientes',
115
- items: [
116
- { quote: 'Qualidade impecável e um cheiro que abraça.', author: 'Helena M.' },
117
- { quote: 'Compro há dois anos e nunca me decepcionou.', author: 'Rafael T.' },
118
- { quote: 'Entrega rápida e embalagem linda, dá gosto de presentear.', author: 'Cláudia P.' },
119
- ],
120
- },
121
- { type: 'products', title: 'NOVIDADES', filter: 'new', limit: 4 },
122
- {
123
- type: 'benefits',
124
- items: [
125
- { icon: 'Truck', title: 'Frete para todo o Brasil', text: 'Envio em até 48h' },
126
- { icon: 'Leaf', title: '100% vegano', text: 'Sem testes em animais' },
127
- { icon: 'RotateCcw', title: 'Troca fácil', text: '30 dias para trocar' },
128
- ],
129
- },
130
- { type: 'newsletter', title: 'NEWSLETTER', subtitle: 'Histórias, lançamentos e cuidado — direto no seu e-mail.' },
131
- ],
132
- }),
133
- }
134
-
135
- /** volt — bold tech (Brasília): white canvas, near-black ink, vivid CTA, dark search-first header, split hero. */
136
- export const voltTemplate: StorefrontTemplate = {
137
- id: 'volt',
138
- inspiration: 'Nuvemshop Brasília',
139
- announcement: 'CUPOM BEMVINDO10 — 10% DE DESCONTO NA PRIMEIRA COMPRA',
140
- theme: {
141
- name: 'volt',
142
- colors: {
143
- background: '0 0% 100%',
144
- foreground: '0 0% 7%',
145
- primary: '341 100% 45%',
146
- primaryForeground: '0 0% 100%',
147
- card: '0 0% 98%',
148
- cardForeground: '0 0% 10%',
149
- muted: '0 0% 94%',
150
- mutedForeground: '0 0% 40%',
151
- border: '0 0% 88%',
152
- headerBackground: '0 0% 6%',
153
- headerForeground: '0 0% 98%',
154
- announcementBackground: '341 100% 45%',
155
- announcementForeground: '0 0% 100%',
156
- },
157
- font: { heading: 'Chakra Petch', body: 'Rubik' },
158
- radius: 'soft',
159
- header: { variant: 'search', uppercaseNav: true },
160
- productCard: { style: 'card', imageAspect: 'square' },
161
- },
162
- home: (storeName, images) => ({
163
- sections: [
164
- {
165
- type: 'hero',
166
- variant: 'split',
167
- slides: [
168
- { title: 'Tecnologia', subtitle: 'O melhor do hardware e dos acessórios', hue: 250, image: images?.hero?.[0] },
169
- { title: 'Ofertas', subtitle: `Descontos semanais ${storeName}`, hue: 341, href: '/catalog', image: images?.hero?.[1] },
170
- ],
171
- },
172
- {
173
- type: 'benefits',
174
- items: [
175
- { icon: 'CreditCard', title: '3x sem juros', text: 'Em todo o site' },
176
- { icon: 'Truck', title: 'Envio em 24h', text: 'Para todo o Brasil' },
177
- { icon: 'ShieldCheck', title: 'Compra segura', text: 'Seus dados protegidos' },
178
- ],
179
- },
180
- { type: 'products', title: 'NOVIDADES', filter: 'new', limit: 4 },
181
- { type: 'banner', title: 'DESCONTOS SEMANAIS', eyebrow: 'toda sexta', subtitle: 'Ofertas novas, estoque limitado', cta: 'Conferir', hue: 341, image: images?.banners?.[0] },
182
- { type: 'products', title: 'PROMOÇÕES', filter: 'sale', limit: 4 },
183
- { type: 'newsletter', title: 'Entre para o clube', subtitle: 'Cupons e lançamentos antes de todo mundo.' },
184
- ],
185
- }),
186
- }
187
-
188
- /** atelier — classic premium retail (Flex): white, near-black, gold accent, slider hero, trust badges. */
189
- export const atelierTemplate: StorefrontTemplate = {
190
- id: 'atelier',
191
- inspiration: 'Nuvemshop Flex',
192
- theme: {
193
- name: 'atelier',
194
- colors: {
195
- background: '0 0% 100%',
196
- foreground: '0 0% 9%',
197
- primary: '40 45% 48%',
198
- primaryForeground: '0 0% 100%',
199
- card: '0 0% 99%',
200
- cardForeground: '0 0% 9%',
201
- muted: '40 10% 95%',
202
- mutedForeground: '0 0% 42%',
203
- border: '0 0% 88%',
204
- announcementBackground: '0 0% 9%',
205
- announcementForeground: '0 0% 98%',
206
- },
207
- font: { heading: 'Outfit', body: 'Outfit' },
208
- radius: 'none',
209
- header: { variant: 'centered', uppercaseNav: true },
210
- productCard: { style: 'card', imageAspect: 'square' },
211
- uppercaseButtons: true,
212
- },
213
- announcement: 'PARCELE EM ATÉ 10X · 5% OFF NO PIX',
214
- home: (storeName, images) => ({
215
- sections: [
216
- {
217
- type: 'hero',
218
- variant: 'slider',
219
- height: 'medium',
220
- slides: [
221
- { title: 'Feito para quem valoriza detalhes', subtitle: `Coleção exclusiva ${storeName}`, cta: 'APROVEITE', hue: 40, image: images?.hero?.[0] },
222
- { title: 'Clássicos que não saem de moda', subtitle: 'Peças autorais, produção limitada', cta: 'VER COLEÇÃO', hue: 210, image: images?.hero?.[1] },
223
- ],
224
- },
225
- {
226
- type: 'benefits',
227
- items: [
228
- { icon: 'CreditCard', title: 'Parcele em até 10x', text: 'Ou 5% off no PIX' },
229
- { icon: 'Lock', title: 'Site 100% seguro', text: 'Seus dados protegidos' },
230
- { icon: 'Award', title: 'Peças exclusivas', text: 'Produtos 100% autorais' },
231
- ],
232
- },
233
- { type: 'categories', style: 'tiles' },
234
- { type: 'products', title: 'Novidades', filter: 'new', limit: 4 },
235
- { type: 'banner', title: 'Promoções', eyebrow: 'seleção especial', subtitle: 'Selecionados com até 25% off', cta: 'Ver ofertas', hue: 40, image: images?.banners?.[0] },
236
- { type: 'products', title: 'Promoções', filter: 'sale', limit: 4 },
237
- {
238
- type: 'testimonials',
239
- title: 'O que dizem sobre nós',
240
- items: [
241
- { quote: 'Acabamento perfeito, superou a expectativa.', author: 'Mariana C.' },
242
- { quote: 'Atendimento impecável do pedido à entrega.', author: 'Jorge L.' },
243
- { quote: 'Virou minha loja favorita para presentes.', author: 'Paula R.' },
244
- ],
245
- },
246
- { type: 'newsletter' },
247
- ],
248
- }),
249
- }
250
-
251
- /** food — warm appetizing delivery (steakhouse / burger / comfort food): dark inviting
252
- * header, ember CTA, cream canvas, rounded cards, menu-first home with "mais pedidos"
253
- * rail and social proof. Built for restaurant/food stores — override to go fully dark. */
254
- export const foodTemplate: StorefrontTemplate = {
255
- id: 'food',
256
- inspiration: 'Delivery / restaurant storefront',
257
- announcement: 'ENTREGA GRÁTIS ACIMA DE R$ 150 · PEÇA JÁ',
258
- theme: {
259
- name: 'food',
260
- colors: {
261
- background: '30 33% 97%',
262
- foreground: '20 14% 15%',
263
- primary: '14 84% 50%',
264
- primaryForeground: '0 0% 100%',
265
- card: '30 33% 99%',
266
- cardForeground: '20 14% 15%',
267
- muted: '28 20% 92%',
268
- mutedForeground: '22 10% 42%',
269
- border: '28 18% 85%',
270
- headerBackground: '20 14% 11%',
271
- headerForeground: '30 24% 96%',
272
- announcementBackground: '14 84% 50%',
273
- announcementForeground: '0 0% 100%',
274
- },
275
- font: { heading: 'Poppins', body: 'Inter' },
276
- radius: 'round',
277
- header: { variant: 'classic' },
278
- productCard: { style: 'card', imageAspect: 'square' },
279
- },
280
- home: (storeName, images) => ({
281
- sections: [
282
- {
283
- type: 'hero',
284
- variant: 'banner',
285
- height: 'tall',
286
- slides: [
287
- { title: 'Sabor de verdade, na sua porta', subtitle: `${storeName} — feito na hora, do jeito que você ama.`, cta: 'Ver cardápio', href: '/catalog', hue: 20, image: images?.hero?.[0] },
288
- ],
289
- },
290
- {
291
- type: 'benefits',
292
- items: [
293
- { icon: 'Flame', title: 'Feito na hora', text: 'Preparado com capricho' },
294
- { icon: 'Truck', title: 'Entrega rápida', text: 'Frete grátis acima de R$ 150' },
295
- { icon: 'CreditCard', title: 'Pagamento fácil', text: 'Pix, cartão e mais' },
296
- ],
297
- },
298
- { type: 'categories', style: 'tiles', title: 'Nosso cardápio' },
299
- { type: 'products', title: 'Mais pedidos', eyebrow: 'favoritos da casa', filter: 'all', limit: 8 },
300
- { type: 'banner', title: 'Combo do dia', eyebrow: 'oferta', subtitle: 'Seleção especial com desconto', cta: 'Aproveitar', hue: 14, image: images?.banners?.[0] },
301
- { type: 'products', title: 'Novidades no cardápio', filter: 'new', limit: 4 },
302
- {
303
- type: 'testimonials',
304
- title: 'O que dizem por aí',
305
- items: [
306
- { quote: 'Chegou quentinho e absurdo de bom. Virei cliente!', author: 'Rafael M.' },
307
- { quote: 'Sabor de restaurante em casa, sem complicação.', author: 'Beatriz L.' },
308
- { quote: 'Entrega rápida e porção generosa. Recomendo demais.', author: 'Diego S.' },
309
- ],
310
- },
311
- { type: 'newsletter', title: 'Receba nossas ofertas', subtitle: 'Promoções e novidades do cardápio, direto no seu e-mail.' },
312
- ],
313
- }),
314
- }
315
-
316
- export const storefrontTemplates = {
317
- mare: mareTemplate,
318
- sertao: sertaoTemplate,
319
- volt: voltTemplate,
320
- atelier: atelierTemplate,
321
- food: foodTemplate,
322
- } as const
323
-
324
- export type StorefrontTemplateId = keyof typeof storefrontTemplates
@@ -1,63 +0,0 @@
1
- import type { Product } from '@fayz-ai/shop/types'
2
-
3
- export interface ProductOptionGroup {
4
- id: string
5
- label: string
6
- values: string[]
7
- }
8
-
9
- export type ProductOptionSelection = Record<string, string>
10
-
11
- function cleanValues(value: unknown): string[] {
12
- if (!Array.isArray(value)) return []
13
- return Array.from(new Set(value.filter((item): item is string => typeof item === 'string' && item.trim().length > 0)))
14
- }
15
-
16
- function cleanOptionGroup(value: unknown): ProductOptionGroup | null {
17
- if (!value || typeof value !== 'object') return null
18
- const record = value as Record<string, unknown>
19
- const id = typeof record.id === 'string' ? record.id : typeof record.name === 'string' ? record.name : null
20
- const label = typeof record.label === 'string' ? record.label : typeof record.name === 'string' ? record.name : id
21
- const values = cleanValues(record.values)
22
- if (!id || !label || values.length === 0) return null
23
- return { id, label, values }
24
- }
25
-
26
- export function getProductOptionGroups(product: Product): ProductOptionGroup[] {
27
- const options = product.metadata.options
28
- const explicit = Array.isArray(options)
29
- ? options.map(cleanOptionGroup).filter((group): group is ProductOptionGroup => Boolean(group))
30
- : []
31
-
32
- if (explicit.length > 0) return explicit
33
-
34
- const groups: ProductOptionGroup[] = []
35
- const sizes = cleanValues(product.metadata.sizes)
36
- const colors = cleanValues(product.metadata.colors)
37
-
38
- if (sizes.length > 0) groups.push({ id: 'Tamanho', label: 'Tamanho', values: sizes })
39
- if (colors.length > 0) groups.push({ id: 'Cor', label: 'Cor', values: colors })
40
-
41
- return groups
42
- }
43
-
44
- export function normalizeProductOptionSelection(selection?: ProductOptionSelection | null): ProductOptionSelection {
45
- if (!selection) return {}
46
- return Object.fromEntries(
47
- Object.entries(selection)
48
- .filter((entry): entry is [string, string] => entry[0].trim().length > 0 && entry[1].trim().length > 0)
49
- .sort(([a], [b]) => a.localeCompare(b)),
50
- )
51
- }
52
-
53
- export function formatProductOptionSelection(selection?: ProductOptionSelection | null): string {
54
- return Object.entries(normalizeProductOptionSelection(selection))
55
- .map(([label, value]) => `${label}: ${value}`)
56
- .join(' · ')
57
- }
58
-
59
- export function productOptionSelectionKey(selection?: ProductOptionSelection | null): string {
60
- const normalized = normalizeProductOptionSelection(selection)
61
- const entries = Object.entries(normalized)
62
- return entries.length > 0 ? JSON.stringify(entries) : ''
63
- }