@fayz-ai/storefront 0.9.0 → 0.11.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 (391) 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-6IXTENLB.js +162 -0
  29. package/dist/chunk-6IXTENLB.js.map +1 -0
  30. package/dist/chunk-SX3J3QIT.js +11046 -0
  31. package/dist/chunk-SX3J3QIT.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/Skeleton.d.ts +17 -0
  35. package/dist/components/Skeleton.d.ts.map +1 -0
  36. package/dist/components/SmoothImage.d.ts +1 -1
  37. package/dist/components/SmoothImage.d.ts.map +1 -1
  38. package/dist/components/account/CustomerAccountShell.d.ts +17 -0
  39. package/dist/components/account/CustomerAccountShell.d.ts.map +1 -0
  40. package/dist/components/account/SignInModal.d.ts.map +1 -0
  41. package/dist/components/account/section.d.ts +15 -0
  42. package/dist/components/account/section.d.ts.map +1 -0
  43. package/dist/components/cart/CartDrawer.d.ts.map +1 -0
  44. package/dist/components/cart/QuantityInput.d.ts.map +1 -0
  45. package/dist/components/checkout/CheckoutPayment.d.ts +17 -0
  46. package/dist/components/checkout/CheckoutPayment.d.ts.map +1 -0
  47. package/dist/components/checkout/CheckoutSteps.d.ts +9 -0
  48. package/dist/components/checkout/CheckoutSteps.d.ts.map +1 -0
  49. package/dist/components/checkout/DeliveryEstimator.d.ts.map +1 -0
  50. package/dist/components/collection/CategoryShowcase.d.ts +44 -0
  51. package/dist/components/collection/CategoryShowcase.d.ts.map +1 -0
  52. package/dist/components/collection/FiltersPanel.d.ts +19 -0
  53. package/dist/components/collection/FiltersPanel.d.ts.map +1 -0
  54. package/dist/components/collection/ProductGrid.d.ts.map +1 -0
  55. package/dist/components/layout/PageBodyBlocks.d.ts +40 -0
  56. package/dist/components/layout/PageBodyBlocks.d.ts.map +1 -0
  57. package/dist/components/layout/SearchOverlay.d.ts +13 -0
  58. package/dist/components/layout/SearchOverlay.d.ts.map +1 -0
  59. package/dist/components/layout/StorefrontErrorBoundary.d.ts.map +1 -0
  60. package/dist/components/layout/StorefrontFooter.d.ts.map +1 -0
  61. package/dist/components/layout/StorefrontHeader.d.ts.map +1 -0
  62. package/dist/components/layout/Toaster.d.ts.map +1 -0
  63. package/dist/components/marketing/CollectionSections.d.ts +463 -0
  64. package/dist/components/marketing/CollectionSections.d.ts.map +1 -0
  65. package/dist/components/marketing/ConversionSections.d.ts +221 -0
  66. package/dist/components/marketing/ConversionSections.d.ts.map +1 -0
  67. package/dist/components/marketing/EditorialSections.d.ts +248 -0
  68. package/dist/components/marketing/EditorialSections.d.ts.map +1 -0
  69. package/dist/components/marketing/EntityList.d.ts +97 -0
  70. package/dist/components/marketing/EntityList.d.ts.map +1 -0
  71. package/dist/components/marketing/FormBlock.d.ts +167 -0
  72. package/dist/components/marketing/FormBlock.d.ts.map +1 -0
  73. package/dist/components/marketing/HeroSection.d.ts +125 -0
  74. package/dist/components/marketing/HeroSection.d.ts.map +1 -0
  75. package/dist/components/marketing/MediaCarousel.d.ts +135 -0
  76. package/dist/components/marketing/MediaCarousel.d.ts.map +1 -0
  77. package/dist/components/marketing/MiscSections.d.ts +252 -0
  78. package/dist/components/marketing/MiscSections.d.ts.map +1 -0
  79. package/dist/components/order/OrderTrackingTimeline.d.ts.map +1 -0
  80. package/dist/components/order/SuccessMark.d.ts +10 -0
  81. package/dist/components/order/SuccessMark.d.ts.map +1 -0
  82. package/dist/components/product/ProductCard.d.ts +14 -0
  83. package/dist/components/product/ProductCard.d.ts.map +1 -0
  84. package/dist/components/product/ProductEnquiryForm.d.ts.map +1 -0
  85. package/dist/components/product/ProductGallery.d.ts +36 -0
  86. package/dist/components/product/ProductGallery.d.ts.map +1 -0
  87. package/dist/components/{ProductOptionSelector.d.ts → product/ProductOptionSelector.d.ts} +1 -1
  88. package/dist/components/product/ProductOptionSelector.d.ts.map +1 -0
  89. package/dist/components/product/ProductRail.d.ts +93 -0
  90. package/dist/components/product/ProductRail.d.ts.map +1 -0
  91. package/dist/components/product/ProductReviews.d.ts +39 -0
  92. package/dist/components/product/ProductReviews.d.ts.map +1 -0
  93. package/dist/components/product/ProductSlider.d.ts +169 -0
  94. package/dist/components/product/ProductSlider.d.ts.map +1 -0
  95. package/dist/components/product/ProductSpecs.d.ts.map +1 -0
  96. package/dist/components/product/RelatedProducts.d.ts.map +1 -0
  97. package/dist/{auth.d.ts → data/auth.d.ts} +9 -0
  98. package/dist/data/auth.d.ts.map +1 -0
  99. package/dist/data/facets.d.ts +39 -0
  100. package/dist/data/facets.d.ts.map +1 -0
  101. package/dist/data/loaders.d.ts +52 -0
  102. package/dist/data/loaders.d.ts.map +1 -0
  103. package/dist/data/local-orders.d.ts +5 -0
  104. package/dist/data/local-orders.d.ts.map +1 -0
  105. package/dist/data/order-status.d.ts.map +1 -0
  106. package/dist/data/product-options.d.ts +36 -0
  107. package/dist/data/product-options.d.ts.map +1 -0
  108. package/dist/data/shipping-items.d.ts +20 -0
  109. package/dist/data/shipping-items.d.ts.map +1 -0
  110. package/dist/diagnostics/seo-audit.d.ts +54 -0
  111. package/dist/diagnostics/seo-audit.d.ts.map +1 -0
  112. package/dist/diagnostics/seo-audit.js +3 -0
  113. package/dist/diagnostics/seo-audit.js.map +1 -0
  114. package/dist/document/change.d.ts +100 -0
  115. package/dist/document/change.d.ts.map +1 -0
  116. package/dist/document/config.d.ts +311 -0
  117. package/dist/document/config.d.ts.map +1 -0
  118. package/dist/document/describe.d.ts +135 -0
  119. package/dist/document/describe.d.ts.map +1 -0
  120. package/dist/document/overlay.d.ts +58 -0
  121. package/dist/document/overlay.d.ts.map +1 -0
  122. package/dist/{presets.d.ts → document/presets.d.ts} +2 -2
  123. package/dist/document/presets.d.ts.map +1 -0
  124. package/dist/document/render.d.ts +171 -0
  125. package/dist/document/render.d.ts.map +1 -0
  126. package/dist/document/round-trip.d.ts +46 -0
  127. package/dist/document/round-trip.d.ts.map +1 -0
  128. package/dist/document/sections.d.ts +194 -0
  129. package/dist/document/sections.d.ts.map +1 -0
  130. package/dist/document/store-policy.d.ts +29 -0
  131. package/dist/document/store-policy.d.ts.map +1 -0
  132. package/dist/document/upgrade.d.ts +112 -0
  133. package/dist/document/upgrade.d.ts.map +1 -0
  134. package/dist/document/validate.d.ts +24 -0
  135. package/dist/document/validate.d.ts.map +1 -0
  136. package/dist/{component-contracts.d.ts → extend/component-contracts.d.ts} +74 -22
  137. package/dist/extend/component-contracts.d.ts.map +1 -0
  138. package/dist/extend/component-override.d.ts +38 -0
  139. package/dist/extend/component-override.d.ts.map +1 -0
  140. package/dist/extend/component-selectors.d.ts.map +1 -0
  141. package/dist/extend/editor-bridge.d.ts +59 -0
  142. package/dist/extend/editor-bridge.d.ts.map +1 -0
  143. package/dist/extend/extension-points.d.ts +103 -0
  144. package/dist/extend/extension-points.d.ts.map +1 -0
  145. package/dist/extend/slots.d.ts +216 -0
  146. package/dist/extend/slots.d.ts.map +1 -0
  147. package/dist/hooks/index.d.ts +25 -6
  148. package/dist/hooks/index.d.ts.map +1 -1
  149. package/dist/hooks/use-address.d.ts +26 -0
  150. package/dist/hooks/use-address.d.ts.map +1 -0
  151. package/dist/hooks/use-cart.d.ts +3 -0
  152. package/dist/hooks/use-cart.d.ts.map +1 -0
  153. package/dist/hooks/use-catalog.d.ts +24 -0
  154. package/dist/hooks/use-catalog.d.ts.map +1 -0
  155. package/dist/hooks/use-categories.d.ts +19 -0
  156. package/dist/hooks/use-categories.d.ts.map +1 -0
  157. package/dist/hooks/use-checkout.d.ts +41 -0
  158. package/dist/hooks/use-checkout.d.ts.map +1 -0
  159. package/dist/hooks/use-discount-validator.d.ts +20 -0
  160. package/dist/hooks/use-discount-validator.d.ts.map +1 -0
  161. package/dist/hooks/use-enquiry.d.ts +7 -0
  162. package/dist/hooks/use-enquiry.d.ts.map +1 -0
  163. package/dist/hooks/{useMyOrders.d.ts → use-my-orders.d.ts} +1 -1
  164. package/dist/hooks/use-my-orders.d.ts.map +1 -0
  165. package/dist/hooks/use-order.d.ts +17 -0
  166. package/dist/hooks/use-order.d.ts.map +1 -0
  167. package/dist/hooks/use-payment-methods.d.ts +19 -0
  168. package/dist/hooks/use-payment-methods.d.ts.map +1 -0
  169. package/dist/hooks/use-policies.d.ts +25 -0
  170. package/dist/hooks/use-policies.d.ts.map +1 -0
  171. package/dist/hooks/use-product.d.ts +15 -0
  172. package/dist/hooks/use-product.d.ts.map +1 -0
  173. package/dist/hooks/{useProducts.d.ts → use-products.d.ts} +1 -1
  174. package/dist/hooks/use-products.d.ts.map +1 -0
  175. package/dist/hooks/use-region.d.ts +15 -0
  176. package/dist/hooks/use-region.d.ts.map +1 -0
  177. package/dist/hooks/use-shipping.d.ts +32 -0
  178. package/dist/hooks/use-shipping.d.ts.map +1 -0
  179. package/dist/hooks/use-storefront-actions.d.ts +12 -0
  180. package/dist/hooks/use-storefront-actions.d.ts.map +1 -0
  181. package/dist/hooks/use-storefront-head.d.ts +19 -0
  182. package/dist/hooks/use-storefront-head.d.ts.map +1 -0
  183. package/dist/hooks/use-storefront.d.ts +3 -0
  184. package/dist/hooks/use-storefront.d.ts.map +1 -0
  185. package/dist/index.d.ts +124 -54
  186. package/dist/index.d.ts.map +1 -1
  187. package/dist/index.js +1310 -5010
  188. package/dist/index.js.map +1 -1
  189. package/dist/lib/errors.d.ts +9 -0
  190. package/dist/lib/errors.d.ts.map +1 -0
  191. package/dist/lib/format.d.ts.map +1 -0
  192. package/dist/lib/motion.d.ts.map +1 -0
  193. package/dist/lib/seo.d.ts +26 -0
  194. package/dist/lib/seo.d.ts.map +1 -0
  195. package/dist/{testids.d.ts → lib/testids.d.ts} +33 -0
  196. package/dist/lib/testids.d.ts.map +1 -0
  197. package/dist/{theme.d.ts → lib/theme.d.ts} +41 -3
  198. package/dist/lib/theme.d.ts.map +1 -0
  199. package/dist/render.d.ts +5 -0
  200. package/dist/render.d.ts.map +1 -0
  201. package/dist/render.js +359 -0
  202. package/dist/render.js.map +1 -0
  203. package/dist/stores/cart.store.d.ts +34 -2
  204. package/dist/stores/cart.store.d.ts.map +1 -1
  205. package/dist/stores/catalog.store.d.ts +11 -0
  206. package/dist/stores/catalog.store.d.ts.map +1 -1
  207. package/dist/stores/delivery.store.d.ts +9 -0
  208. package/dist/stores/delivery.store.d.ts.map +1 -1
  209. package/dist/views/CatalogPage.d.ts.map +1 -0
  210. package/dist/views/CheckoutPage.d.ts.map +1 -0
  211. package/dist/views/ContentPage.d.ts +11 -0
  212. package/dist/views/ContentPage.d.ts.map +1 -0
  213. package/dist/views/HomePage.d.ts +9 -0
  214. package/dist/views/HomePage.d.ts.map +1 -0
  215. package/dist/views/MyPurchasesPage.d.ts.map +1 -0
  216. package/dist/views/NotFoundPage.d.ts.map +1 -0
  217. package/dist/views/OrderConfirmationPage.d.ts.map +1 -0
  218. package/dist/{pages → views}/PolicyPage.d.ts.map +1 -1
  219. package/dist/views/ProductDetailPage.d.ts.map +1 -0
  220. package/dist/views/StorefrontPage.d.ts +35 -0
  221. package/dist/views/StorefrontPage.d.ts.map +1 -0
  222. package/dist/workflows/checkout.d.ts +1 -1
  223. package/dist/workflows/checkout.d.ts.map +1 -1
  224. package/package.json +21 -14
  225. package/dist/auth.d.ts.map +0 -1
  226. package/dist/blocks.d.ts.map +0 -1
  227. package/dist/component-contracts.d.ts.map +0 -1
  228. package/dist/component-selectors.d.ts.map +0 -1
  229. package/dist/components/CartDrawer.d.ts.map +0 -1
  230. package/dist/components/CustomerAccountShell.d.ts +0 -13
  231. package/dist/components/CustomerAccountShell.d.ts.map +0 -1
  232. package/dist/components/DeliveryEstimator.d.ts.map +0 -1
  233. package/dist/components/FiltersPanel.d.ts +0 -3
  234. package/dist/components/FiltersPanel.d.ts.map +0 -1
  235. package/dist/components/OrderTrackingTimeline.d.ts.map +0 -1
  236. package/dist/components/ProductCard.d.ts +0 -4
  237. package/dist/components/ProductCard.d.ts.map +0 -1
  238. package/dist/components/ProductEnquiryForm.d.ts.map +0 -1
  239. package/dist/components/ProductGallery.d.ts +0 -22
  240. package/dist/components/ProductGallery.d.ts.map +0 -1
  241. package/dist/components/ProductGrid.d.ts.map +0 -1
  242. package/dist/components/ProductOptionSelector.d.ts.map +0 -1
  243. package/dist/components/ProductSpecs.d.ts.map +0 -1
  244. package/dist/components/QuantityInput.d.ts.map +0 -1
  245. package/dist/components/RelatedProducts.d.ts.map +0 -1
  246. package/dist/components/SignInModal.d.ts.map +0 -1
  247. package/dist/components/StorefrontErrorBoundary.d.ts.map +0 -1
  248. package/dist/components/StorefrontFooter.d.ts.map +0 -1
  249. package/dist/components/StorefrontHeader.d.ts.map +0 -1
  250. package/dist/components/Toaster.d.ts.map +0 -1
  251. package/dist/components/sections/CategoryShowcase.d.ts +0 -6
  252. package/dist/components/sections/CategoryShowcase.d.ts.map +0 -1
  253. package/dist/components/sections/HeroSection.d.ts +0 -9
  254. package/dist/components/sections/HeroSection.d.ts.map +0 -1
  255. package/dist/components/sections/MediaCarousel.d.ts +0 -11
  256. package/dist/components/sections/MediaCarousel.d.ts.map +0 -1
  257. package/dist/components/sections/MiscSections.d.ts +0 -33
  258. package/dist/components/sections/MiscSections.d.ts.map +0 -1
  259. package/dist/components/sections/ProductRail.d.ts +0 -9
  260. package/dist/components/sections/ProductRail.d.ts.map +0 -1
  261. package/dist/components/sections/ProductSlider.d.ts +0 -15
  262. package/dist/components/sections/ProductSlider.d.ts.map +0 -1
  263. package/dist/config.d.ts +0 -174
  264. package/dist/config.d.ts.map +0 -1
  265. package/dist/createStorefrontApp.d.ts +0 -28
  266. package/dist/createStorefrontApp.d.ts.map +0 -1
  267. package/dist/define.d.ts.map +0 -1
  268. package/dist/format.d.ts.map +0 -1
  269. package/dist/hooks/useCategories.d.ts +0 -6
  270. package/dist/hooks/useCategories.d.ts.map +0 -1
  271. package/dist/hooks/useDiscountValidator.d.ts +0 -14
  272. package/dist/hooks/useDiscountValidator.d.ts.map +0 -1
  273. package/dist/hooks/useMyOrders.d.ts.map +0 -1
  274. package/dist/hooks/useProduct.d.ts +0 -7
  275. package/dist/hooks/useProduct.d.ts.map +0 -1
  276. package/dist/hooks/useProducts.d.ts.map +0 -1
  277. package/dist/hooks/useStorefront.d.ts +0 -35
  278. package/dist/hooks/useStorefront.d.ts.map +0 -1
  279. package/dist/hooks/useStorefrontHead.d.ts +0 -11
  280. package/dist/hooks/useStorefrontHead.d.ts.map +0 -1
  281. package/dist/motion.d.ts.map +0 -1
  282. package/dist/order-status.d.ts.map +0 -1
  283. package/dist/pages/CatalogPage.d.ts.map +0 -1
  284. package/dist/pages/CheckoutPage.d.ts.map +0 -1
  285. package/dist/pages/HomePage.d.ts +0 -9
  286. package/dist/pages/HomePage.d.ts.map +0 -1
  287. package/dist/pages/MyPurchasesPage.d.ts.map +0 -1
  288. package/dist/pages/NotFoundPage.d.ts.map +0 -1
  289. package/dist/pages/OrderConfirmationPage.d.ts.map +0 -1
  290. package/dist/pages/ProductDetailPage.d.ts.map +0 -1
  291. package/dist/presets.d.ts.map +0 -1
  292. package/dist/product-options.d.ts +0 -12
  293. package/dist/product-options.d.ts.map +0 -1
  294. package/dist/router.d.ts.map +0 -1
  295. package/dist/scaffold.d.ts.map +0 -1
  296. package/dist/sections.d.ts.map +0 -1
  297. package/dist/testids.d.ts.map +0 -1
  298. package/dist/theme.d.ts.map +0 -1
  299. package/src/auth.ts +0 -227
  300. package/src/blocks.tsx +0 -51
  301. package/src/catalog.ts +0 -3
  302. package/src/component-contracts.ts +0 -154
  303. package/src/component-selectors.ts +0 -31
  304. package/src/components/CartDrawer.tsx +0 -279
  305. package/src/components/CustomerAccountShell.tsx +0 -102
  306. package/src/components/DeliveryEstimator.tsx +0 -157
  307. package/src/components/FiltersPanel.tsx +0 -109
  308. package/src/components/OrderTrackingTimeline.tsx +0 -135
  309. package/src/components/Price.tsx +0 -32
  310. package/src/components/ProductCard.tsx +0 -120
  311. package/src/components/ProductEnquiryForm.tsx +0 -175
  312. package/src/components/ProductGallery.tsx +0 -174
  313. package/src/components/ProductGrid.tsx +0 -43
  314. package/src/components/ProductOptionSelector.tsx +0 -50
  315. package/src/components/ProductSpecs.tsx +0 -75
  316. package/src/components/QuantityInput.tsx +0 -52
  317. package/src/components/RelatedProducts.tsx +0 -40
  318. package/src/components/SignInModal.tsx +0 -120
  319. package/src/components/SmoothImage.tsx +0 -59
  320. package/src/components/StorefrontErrorBoundary.tsx +0 -51
  321. package/src/components/StorefrontFooter.tsx +0 -110
  322. package/src/components/StorefrontHeader.tsx +0 -477
  323. package/src/components/Toaster.tsx +0 -60
  324. package/src/components/sections/CategoryShowcase.tsx +0 -80
  325. package/src/components/sections/HeroSection.tsx +0 -193
  326. package/src/components/sections/MediaCarousel.tsx +0 -141
  327. package/src/components/sections/MiscSections.tsx +0 -158
  328. package/src/components/sections/ProductRail.tsx +0 -81
  329. package/src/components/sections/ProductSlider.tsx +0 -119
  330. package/src/config.ts +0 -229
  331. package/src/createStorefrontApp.tsx +0 -247
  332. package/src/define.ts +0 -34
  333. package/src/format.ts +0 -7
  334. package/src/hooks/index.ts +0 -6
  335. package/src/hooks/useCategories.ts +0 -26
  336. package/src/hooks/useDiscountValidator.ts +0 -43
  337. package/src/hooks/useMyOrders.ts +0 -41
  338. package/src/hooks/useProduct.ts +0 -36
  339. package/src/hooks/useProducts.ts +0 -39
  340. package/src/hooks/useStorefront.ts +0 -58
  341. package/src/hooks/useStorefrontHead.ts +0 -25
  342. package/src/index.ts +0 -202
  343. package/src/motion.tsx +0 -94
  344. package/src/order-status.ts +0 -33
  345. package/src/pages/CatalogPage.tsx +0 -118
  346. package/src/pages/CheckoutPage.tsx +0 -689
  347. package/src/pages/HomePage.tsx +0 -16
  348. package/src/pages/MyPurchasesPage.tsx +0 -311
  349. package/src/pages/NotFoundPage.tsx +0 -25
  350. package/src/pages/OrderConfirmationPage.tsx +0 -190
  351. package/src/pages/PolicyPage.tsx +0 -47
  352. package/src/pages/ProductDetailPage.tsx +0 -264
  353. package/src/presets.ts +0 -324
  354. package/src/product-options.ts +0 -63
  355. package/src/router.ts +0 -49
  356. package/src/scaffold.tsx +0 -115
  357. package/src/sections.ts +0 -116
  358. package/src/shop.ts +0 -4
  359. package/src/stores/cart.store.ts +0 -185
  360. package/src/stores/catalog.store.ts +0 -39
  361. package/src/stores/delivery.store.ts +0 -152
  362. package/src/stores/session.store.ts +0 -28
  363. package/src/stores/toast.store.ts +0 -43
  364. package/src/testids.ts +0 -136
  365. package/src/theme.ts +0 -194
  366. package/src/ui.ts +0 -5
  367. package/src/workflows/checkout.ts +0 -119
  368. /package/dist/components/{SignInModal.d.ts → account/SignInModal.d.ts} +0 -0
  369. /package/dist/components/{CartDrawer.d.ts → cart/CartDrawer.d.ts} +0 -0
  370. /package/dist/components/{QuantityInput.d.ts → cart/QuantityInput.d.ts} +0 -0
  371. /package/dist/components/{DeliveryEstimator.d.ts → checkout/DeliveryEstimator.d.ts} +0 -0
  372. /package/dist/components/{ProductGrid.d.ts → collection/ProductGrid.d.ts} +0 -0
  373. /package/dist/components/{StorefrontErrorBoundary.d.ts → layout/StorefrontErrorBoundary.d.ts} +0 -0
  374. /package/dist/components/{StorefrontFooter.d.ts → layout/StorefrontFooter.d.ts} +0 -0
  375. /package/dist/components/{StorefrontHeader.d.ts → layout/StorefrontHeader.d.ts} +0 -0
  376. /package/dist/components/{Toaster.d.ts → layout/Toaster.d.ts} +0 -0
  377. /package/dist/components/{OrderTrackingTimeline.d.ts → order/OrderTrackingTimeline.d.ts} +0 -0
  378. /package/dist/components/{ProductEnquiryForm.d.ts → product/ProductEnquiryForm.d.ts} +0 -0
  379. /package/dist/components/{ProductSpecs.d.ts → product/ProductSpecs.d.ts} +0 -0
  380. /package/dist/components/{RelatedProducts.d.ts → product/RelatedProducts.d.ts} +0 -0
  381. /package/dist/{order-status.d.ts → data/order-status.d.ts} +0 -0
  382. /package/dist/{component-selectors.d.ts → extend/component-selectors.d.ts} +0 -0
  383. /package/dist/{format.d.ts → lib/format.d.ts} +0 -0
  384. /package/dist/{motion.d.ts → lib/motion.d.ts} +0 -0
  385. /package/dist/{pages → views}/CatalogPage.d.ts +0 -0
  386. /package/dist/{pages → views}/CheckoutPage.d.ts +0 -0
  387. /package/dist/{pages → views}/MyPurchasesPage.d.ts +0 -0
  388. /package/dist/{pages → views}/NotFoundPage.d.ts +0 -0
  389. /package/dist/{pages → views}/OrderConfirmationPage.d.ts +0 -0
  390. /package/dist/{pages → views}/PolicyPage.d.ts +0 -0
  391. /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
- }