@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
package/src/router.ts DELETED
@@ -1,49 +0,0 @@
1
- import React, { useEffect, useState } from 'react'
2
- import { hashRouterAdapter } from '@fayz-ai/core'
3
-
4
- // Minimal hash router for the storefront. Deliberately not react-router:
5
- // an SDK package shipping a router dependency creates singleton hazards
6
- // under source-alias dev setups, and six routes don't justify one.
7
-
8
- const adapter = hashRouterAdapter()
9
-
10
- export function navigateTo(to: string): void {
11
- adapter.navigate(to)
12
- }
13
-
14
- export function useHashPath(): string {
15
- const [path, setPath] = useState(() => adapter.getCurrentPath() || '/')
16
- useEffect(() => {
17
- const unsub = adapter.onPathChange((p) => {
18
- setPath(p || '/')
19
- window.scrollTo(0, 0)
20
- })
21
- return unsub
22
- }, [])
23
- return path
24
- }
25
-
26
- /** Match '/product/:slug' against '/product/leather-backpack' → { slug: 'leather-backpack' } */
27
- export function matchPath(pattern: string, path: string): Record<string, string> | null {
28
- const cleanPath = (path.split('?')[0] ?? '').replace(/\/+$/, '') || '/'
29
- const patternParts = pattern.split('/').filter(Boolean)
30
- const pathParts = cleanPath.split('/').filter(Boolean)
31
- if (patternParts.length !== pathParts.length) return null
32
- const params: Record<string, string> = {}
33
- for (let i = 0; i < patternParts.length; i++) {
34
- const pat = patternParts[i]!
35
- const part = pathParts[i]!
36
- if (pat.startsWith(':')) params[pat.slice(1)] = decodeURIComponent(part)
37
- else if (pat !== part) return null
38
- }
39
- return params
40
- }
41
-
42
- export interface LinkProps extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
43
- to: string
44
- }
45
-
46
- /** Real anchor (#/path) — middle-click/cmd-click friendly, Playwright friendly. */
47
- export function Link({ to, children, ...rest }: LinkProps) {
48
- return React.createElement('a', { href: `#${to}`, ...rest }, children)
49
- }
package/src/scaffold.tsx DELETED
@@ -1,115 +0,0 @@
1
- import React from 'react'
2
- import { registerScaffold, defineApp } from '@fayz-ai/core'
3
- import type { AppManifest, BackendProvider } from '@fayz-ai/core'
4
- import { StorefrontConfigProvider, resolveConfig } from './config'
5
- import type { StorefrontConfig } from './config'
6
- import type { StorefrontTheme } from './theme'
7
- import type { HomeConfig, NavLink, FooterConfig } from './sections'
8
- import { initStorefrontRuntime, StorefrontShell } from './createStorefrontApp'
9
- import './blocks' // ensure section blocks are registered
10
-
11
- type StorefrontBackendProvider = NonNullable<StorefrontConfig['backend']>['provider']
12
- const runtimeConfigRegistry = new Map<string, StorefrontConfig>()
13
-
14
- // ---------------------------------------------------------------------------
15
- // Storefront scaffold — renders a store from a pure-data AppManifest. The
16
- // storefront surface keeps its declarative config under surface.options, so the
17
- // mapping is loss-free for the serializable fields (the code escape hatches —
18
- // custom provider/adapter/logo — arrive via the registries instead).
19
- // ---------------------------------------------------------------------------
20
-
21
- function slug(name: string): string {
22
- return name.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '') || 'app'
23
- }
24
-
25
- /** StorefrontConfig → AppManifest (the sugar-to-data direction). */
26
- export function defineStorefront(config: StorefrontConfig): AppManifest {
27
- const id = slug(config.name)
28
- runtimeConfigRegistry.set(id, config)
29
- const backendProvider = (config.backend?.provider ?? (config.provider ? 'custom' : 'mock')) as BackendProvider
30
-
31
- return defineApp({
32
- id,
33
- name: config.name,
34
- backend: {
35
- provider: backendProvider,
36
- url: config.backend?.url,
37
- },
38
- locale: {
39
- default: config.locale ?? 'pt-BR',
40
- supported: [config.locale ?? 'pt-BR'],
41
- currency: config.currency ?? 'BRL',
42
- },
43
- theme: config.theme as Record<string, unknown> | undefined,
44
- surfaces: {
45
- storefront: {
46
- scaffold: 'storefront',
47
- options: {
48
- announcement: config.announcement,
49
- home: config.home,
50
- nav: config.nav,
51
- footer: config.footer,
52
- shipping: config.shipping,
53
- features: config.features,
54
- catalog: config.catalog,
55
- },
56
- },
57
- },
58
- })
59
- }
60
-
61
- /** AppManifest → StorefrontConfig (the data-to-render direction). */
62
- function manifestToStorefrontConfig(manifest: AppManifest, surfaceName: string): StorefrontConfig {
63
- const runtimeConfig = runtimeConfigRegistry.get(manifest.id)
64
- const surface = manifest.surfaces[surfaceName]
65
- const o = (surface?.options ?? {}) as Record<string, unknown>
66
- return {
67
- ...runtimeConfig,
68
- name: manifest.name,
69
- currency: (manifest.locale as { currency?: string } | undefined)?.currency,
70
- locale: (manifest.locale as { default?: string } | undefined)?.default,
71
- theme: manifest.theme as StorefrontTheme | undefined,
72
- announcement: o.announcement as string | undefined,
73
- home: o.home as HomeConfig | undefined,
74
- nav: o.nav as NavLink[] | undefined,
75
- footer: o.footer as FooterConfig | undefined,
76
- shipping: o.shipping as StorefrontConfig['shipping'],
77
- features: o.features as StorefrontConfig['features'],
78
- catalog: o.catalog as StorefrontConfig['catalog'],
79
- backend: {
80
- provider: manifest.backend?.provider as StorefrontBackendProvider,
81
- url: manifest.backend?.url,
82
- },
83
- components: runtimeConfig?.components,
84
- routes: runtimeConfig?.routes,
85
- provider: runtimeConfig?.provider,
86
- auth: runtimeConfig?.auth,
87
- logo: runtimeConfig?.logo,
88
- }
89
- }
90
-
91
- export function StorefrontScaffold({ manifest, surface }: { manifest: AppManifest; surface: string }) {
92
- const config = React.useMemo(() => manifestToStorefrontConfig(manifest, surface), [manifest, surface])
93
- const resolved = React.useMemo(() => resolveConfig(config), [config])
94
- const inited = React.useRef(false)
95
- if (!inited.current) {
96
- initStorefrontRuntime(config)
97
- inited.current = true
98
- }
99
- return (
100
- <StorefrontConfigProvider value={resolved}>
101
- <StorefrontShell />
102
- </StorefrontConfigProvider>
103
- )
104
- }
105
- StorefrontScaffold.displayName = 'StorefrontScaffold'
106
-
107
- // Registration is lazy (called from the storefront renderApp wrapper and
108
- // createStorefront*) so that importing the @fayz-ai/storefront barrel stays
109
- // side-effect-free and tree-shakable.
110
- let storefrontScaffoldRegistered = false
111
- export function registerStorefrontScaffold(): void {
112
- if (storefrontScaffoldRegistered) return
113
- storefrontScaffoldRegistered = true
114
- registerScaffold('storefront', StorefrontScaffold, { source: 'sdk', label: 'Storefront' })
115
- }
package/src/sections.ts DELETED
@@ -1,116 +0,0 @@
1
- import type { HeroVariant } from './theme'
2
- import type React from 'react'
3
-
4
- // ---------------------------------------------------------------------------
5
- // Home-page section blueprint — the storefront's PageConfig equivalent.
6
- // A template (or the Fayz agent) declares the home as an ordered list of
7
- // typed sections; HomePage renders them. Every recurring block found in the
8
- // Nuvemshop research maps to one section type.
9
- // ---------------------------------------------------------------------------
10
-
11
- export interface HeroSlide {
12
- title: string
13
- subtitle?: string
14
- cta?: string
15
- href?: string
16
- /** Image URL; omit for a gradient placeholder derived from `hue` */
17
- image?: string
18
- hue?: number
19
- /** Editorial boxed copy block (Uyuni) instead of free overlay */
20
- boxed?: boolean
21
- }
22
-
23
- export interface MediaCarouselItem {
24
- title: string
25
- subtitle?: string
26
- eyebrow?: string
27
- cta?: string
28
- href?: string
29
- image: string
30
- imageAlt?: string
31
- align?: 'start' | 'center' | 'end'
32
- }
33
-
34
- export type StorefrontSection =
35
- | { type: 'hero'; variant: HeroVariant; slides: HeroSlide[]; height?: 'tall' | 'medium' }
36
- | {
37
- type: 'mediaCarousel'
38
- items: MediaCarouselItem[]
39
- height?: 'medium' | 'tall' | 'screen'
40
- autoplayMs?: number
41
- overlay?: 'dark' | 'soft' | 'none'
42
- className?: string
43
- }
44
- | { type: 'categories'; style: 'bubbles' | 'tiles'; title?: string }
45
- | {
46
- type: 'products'
47
- title: string
48
- subtitle?: string
49
- /** Small-caps label above the title (e.g. 'curadoria') */
50
- eyebrow?: string
51
- /** 'sale' = compareAtPrice set; 'new' = newest first; 'all' = catalog order */
52
- filter?: 'sale' | 'new' | 'all'
53
- limit?: number
54
- }
55
- | {
56
- type: 'productSlider'
57
- title: string
58
- subtitle?: string
59
- eyebrow?: string
60
- filter?: 'sale' | 'new' | 'all'
61
- categoryName?: string
62
- collection?: string
63
- limit?: number
64
- cta?: string
65
- href?: string
66
- className?: string
67
- }
68
- | { type: 'benefits'; items: Array<{ icon: string; title: string; text?: string }> }
69
- | { type: 'banner'; title: string; subtitle?: string; eyebrow?: string; cta?: string; href?: string; image?: string; hue?: number }
70
- | { type: 'manifesto'; title?: string; text: string }
71
- | { type: 'testimonials'; title?: string; items: Array<{ quote: string; author: string }> }
72
- | { type: 'newsletter'; title?: string; subtitle?: string }
73
-
74
- /** @deprecated Use StorefrontSection. Kept for existing generated stores. */
75
- export type HomeSection = StorefrontSection
76
-
77
- export interface HomeConfig {
78
- sections: readonly StorefrontSection[]
79
- }
80
-
81
- export interface NavLink {
82
- label: string
83
- to: string
84
- }
85
-
86
- export interface FooterConfig {
87
- about?: string
88
- contact?: { phone?: string; email?: string; address?: string }
89
- social?: Array<{ label: string; href: string }>
90
- credit?: React.ReactNode
91
- labels?: {
92
- categories?: string
93
- navigation?: string
94
- contact?: string
95
- viewAll?: string
96
- purchases?: string
97
- privacy?: string
98
- terms?: string
99
- returns?: string
100
- }
101
- }
102
-
103
- /** Wide gradient SVG data-URI — deterministic hero/banner art, no network. */
104
- export function bannerPlaceholder(label: string, hueA: number, hueB: number, w = 1600, h = 700): string {
105
- const svg =
106
- `<svg xmlns="http://www.w3.org/2000/svg" width="${w}" height="${h}">` +
107
- `<defs><linearGradient id="g" x1="0" y1="0" x2="1" y2="1">` +
108
- `<stop offset="0" stop-color="hsl(${hueA},40%,78%)"/>` +
109
- `<stop offset="1" stop-color="hsl(${hueB},45%,55%)"/>` +
110
- `</linearGradient></defs>` +
111
- `<rect width="${w}" height="${h}" fill="url(#g)"/>` +
112
- `<circle cx="${w * 0.8}" cy="${h * 0.3}" r="${h * 0.45}" fill="hsla(${hueB},50%,90%,0.25)"/>` +
113
- `<circle cx="${w * 0.15}" cy="${h * 0.85}" r="${h * 0.35}" fill="hsla(${hueA},45%,30%,0.12)"/>` +
114
- `</svg>`
115
- return `data:image/svg+xml;utf8,${encodeURIComponent(svg)}`
116
- }
package/src/shop.ts DELETED
@@ -1,4 +0,0 @@
1
- // Front-door re-export of the Fayz API shop provider (@fayz-ai/sdk/shop) so
2
- // storefront apps import `createFayzShopProvider` from
3
- // `@fayz-ai/storefront/shop` instead of depending on @fayz-ai/sdk directly.
4
- export * from '@fayz-ai/sdk/shop'
@@ -1,185 +0,0 @@
1
- import { create } from 'zustand'
2
- import { persist } from 'zustand/middleware'
3
- import type { Product } from '@fayz-ai/shop/types'
4
- import { roundCents } from '../format'
5
- import type { ResolvedStorefrontConfig } from '../config'
6
- import { useDeliveryStore, selectQuotedShipping } from './delivery.store'
7
- import {
8
- formatProductOptionSelection,
9
- normalizeProductOptionSelection,
10
- productOptionSelectionKey,
11
- type ProductOptionSelection,
12
- } from '../product-options'
13
-
14
- export interface CartLine {
15
- lineId: string
16
- productId: string
17
- slug: string
18
- name: string
19
- sku: string | null
20
- options: ProductOptionSelection
21
- optionsLabel: string
22
- unitPrice: number
23
- quantity: number
24
- imageUrl: string | null
25
- /** inventoryCount at add time — clamps quantity */
26
- maxQuantity: number
27
- }
28
-
29
- export interface CartState {
30
- lines: CartLine[]
31
- discountCode: string | null
32
- discountPercent: number
33
- isOpen: boolean
34
- /** Line most recently added — lets the drawer briefly highlight it. */
35
- justAddedLineId: string | null
36
- addItem(product: Product, qty?: number, options?: ProductOptionSelection): void
37
- setQuantity(lineId: string, qty: number): void
38
- removeItem(lineId: string): void
39
- applyDiscount(code: string, percent: number): void
40
- clearDiscount(): void
41
- clear(): void
42
- openDrawer(): void
43
- closeDrawer(): void
44
- /** Drop persisted lines the active backend can no longer resolve (e.g. a cart
45
- * built in an earlier mock-mode session, whose ids don't exist live). The
46
- * resolver returns false only for a definitive "not found"; on error it must
47
- * return true so a transient failure never discards a legit line. */
48
- reconcile(resolve: (line: CartLine) => Promise<boolean>): Promise<void>
49
- }
50
-
51
- export const useCartStore = create<CartState>()(
52
- persist(
53
- (set, get) => ({
54
- lines: [],
55
- discountCode: null,
56
- discountPercent: 0,
57
- isOpen: false,
58
- justAddedLineId: null,
59
-
60
- addItem: (product, qty = 1, options) =>
61
- set((state) => {
62
- const normalizedOptions = normalizeProductOptionSelection(options)
63
- const optionKey = productOptionSelectionKey(normalizedOptions)
64
- const lineId = optionKey ? `${product.id}:${optionKey}` : product.id
65
- const existing = state.lines.find((l) => (l.lineId ?? l.productId) === lineId)
66
- if (existing) {
67
- const nextQty = Math.min(existing.quantity + qty, existing.maxQuantity || Infinity)
68
- return {
69
- // Auto-open the cart on add — the standard premium "slide-in cart"
70
- // signal — and flag the line so the drawer can highlight it.
71
- isOpen: true,
72
- justAddedLineId: lineId,
73
- lines: state.lines.map((l) =>
74
- (l.lineId ?? l.productId) === lineId ? { ...l, lineId, quantity: nextQty } : l,
75
- ),
76
- }
77
- }
78
- const image = product.images.find((i) => i.isPrimary) ?? product.images[0]
79
- const line: CartLine = {
80
- lineId,
81
- productId: product.id,
82
- slug: product.slug,
83
- name: product.name,
84
- sku: product.sku,
85
- options: normalizedOptions,
86
- optionsLabel: formatProductOptionSelection(normalizedOptions),
87
- unitPrice: product.price,
88
- quantity: Math.min(qty, product.inventoryCount || Infinity),
89
- imageUrl: image?.url ?? null,
90
- maxQuantity: product.inventoryCount,
91
- }
92
- return { isOpen: true, justAddedLineId: lineId, lines: [...state.lines, line] }
93
- }),
94
-
95
- setQuantity: (lineId, qty) =>
96
- set((state) => {
97
- if (qty <= 0) return { lines: state.lines.filter((l) => (l.lineId ?? l.productId) !== lineId) }
98
- return {
99
- lines: state.lines.map((l) =>
100
- (l.lineId ?? l.productId) === lineId
101
- ? { ...l, quantity: Math.min(qty, l.maxQuantity || Infinity) }
102
- : l,
103
- ),
104
- }
105
- }),
106
-
107
- removeItem: (lineId) =>
108
- set((state) => ({ lines: state.lines.filter((l) => (l.lineId ?? l.productId) !== lineId) })),
109
-
110
- applyDiscount: (code, percent) => set({ discountCode: code, discountPercent: percent }),
111
- clearDiscount: () => set({ discountCode: null, discountPercent: 0 }),
112
- clear: () => set({ lines: [], discountCode: null, discountPercent: 0 }),
113
- openDrawer: () => set({ isOpen: true }),
114
- closeDrawer: () => set({ isOpen: false, justAddedLineId: null }),
115
-
116
- reconcile: async (resolve) => {
117
- const lines = get().lines
118
- if (lines.length === 0) return
119
- const keep = await Promise.all(
120
- lines.map((line) => resolve(line).catch(() => true)),
121
- )
122
- const kept = lines.filter((_, i) => keep[i])
123
- if (kept.length !== lines.length) set({ lines: kept })
124
- },
125
- }),
126
- {
127
- name: 'fayz.storefront.cart.v1',
128
- partialize: (state) => ({
129
- lines: state.lines,
130
- discountCode: state.discountCode,
131
- discountPercent: state.discountPercent,
132
- }),
133
- },
134
- ),
135
- )
136
-
137
- // ---------------------------------------------------------------------------
138
- // Money selectors — the single place cart math happens. Checkout passes these
139
- // exact values to createOrder so drawer totals always match order totals.
140
- // ---------------------------------------------------------------------------
141
-
142
- export const selectCount = (s: Pick<CartState, 'lines'>): number =>
143
- s.lines.reduce((n, l) => n + l.quantity, 0)
144
-
145
- export const selectSubtotal = (s: Pick<CartState, 'lines'>): number =>
146
- roundCents(s.lines.reduce((sum, l) => sum + l.unitPrice * l.quantity, 0))
147
-
148
- export const selectDiscountTotal = (s: Pick<CartState, 'lines' | 'discountPercent'>): number =>
149
- roundCents(selectSubtotal(s) * (s.discountPercent / 100))
150
-
151
- /**
152
- * Freight to display.
153
- *
154
- * When the shopper has given a CEP and the store quoted it, that quote wins —
155
- * it came from the same shipping_zones rows shop_place_order will charge from.
156
- * Otherwise this falls back to the store-wide rate in config, which is what
157
- * every storefront did before zones existed.
158
- *
159
- * The subtotal is PRE-discount on both sides of this. That is 0017's rule, and
160
- * the quote is requested against the same number, so a coupon can never make
161
- * the cart and the order disagree.
162
- *
163
- * Read through getState() rather than a hook because this is a plain selector
164
- * called from several screens; components that render the value subscribe to
165
- * useDeliveryStore themselves so a fresh quote re-renders them.
166
- */
167
- export const selectShipping = (
168
- s: Pick<CartState, 'lines'>,
169
- cfg: ResolvedStorefrontConfig,
170
- ): number => {
171
- if (s.lines.length === 0) return 0
172
- const subtotal = selectSubtotal(s)
173
-
174
- const quoted = selectQuotedShipping(useDeliveryStore.getState(), subtotal)
175
- if (quoted != null) return quoted
176
-
177
- if (cfg.shipping.freeAbove != null && subtotal >= cfg.shipping.freeAbove) return 0
178
- return cfg.shipping.flatRate
179
- }
180
-
181
- export const selectTotal = (
182
- s: Pick<CartState, 'lines' | 'discountPercent'>,
183
- cfg: ResolvedStorefrontConfig,
184
- ): number =>
185
- roundCents(selectSubtotal(s) - selectDiscountTotal(s) + selectShipping(s, cfg))
@@ -1,39 +0,0 @@
1
- import { create } from 'zustand'
2
-
3
- export type CatalogSort = 'newest' | 'price-asc' | 'price-desc' | 'name'
4
-
5
- export interface CatalogState {
6
- search: string
7
- categoryId: string | null
8
- priceMin: number | null
9
- priceMax: number | null
10
- inStockOnly: boolean
11
- sort: CatalogSort
12
- setSearch(search: string): void
13
- setCategoryId(categoryId: string | null): void
14
- setPriceMin(priceMin: number | null): void
15
- setPriceMax(priceMax: number | null): void
16
- setInStockOnly(inStockOnly: boolean): void
17
- setSort(sort: CatalogSort): void
18
- reset(): void
19
- }
20
-
21
- const initial = {
22
- search: '',
23
- categoryId: null,
24
- priceMin: null,
25
- priceMax: null,
26
- inStockOnly: false,
27
- sort: 'newest' as CatalogSort,
28
- }
29
-
30
- export const useCatalogStore = create<CatalogState>()((set) => ({
31
- ...initial,
32
- setSearch: (search) => set({ search }),
33
- setCategoryId: (categoryId) => set({ categoryId }),
34
- setPriceMin: (priceMin) => set({ priceMin }),
35
- setPriceMax: (priceMax) => set({ priceMax }),
36
- setInStockOnly: (inStockOnly) => set({ inStockOnly }),
37
- setSort: (sort) => set({ sort }),
38
- reset: () => set(initial),
39
- }))
@@ -1,152 +0,0 @@
1
- import { create } from 'zustand'
2
- import { persist } from 'zustand/middleware'
3
- import { lookupPostalCode, normalizePostalCode, type PostalAddress } from '@fayz-ai/core'
4
- import { getShopProvider } from '@fayz-ai/shop/runtime'
5
- import type { ShippingQuoteOption } from '@fayz-ai/shop/types'
6
-
7
- /**
8
- * Where the shopper wants it delivered, decided before the cart exists.
9
- *
10
- * Two different things live here and they are persisted differently on purpose:
11
- *
12
- * the ADDRESS is durable — a CEP maps to the same street for years, and
13
- * carrying it to checkout is the whole point (the buyer types the number and
14
- * nothing else);
15
- *
16
- * the QUOTE is not persisted at all. It is a price, and a price restored from
17
- * localStorage is a price the shopper can edit with devtools. It is re-asked
18
- * on demand, and resolved for the current cart through resolveOptionRate —
19
- * the same rule shop_shipping_for applies — so it can never go stale. The
20
- * order is charged from shop_place_order, which recomputes from the same
21
- * zones and ignores anything the client sends.
22
- */
23
-
24
- export type DeliveryStatus = 'idle' | 'loading' | 'served' | 'unserved' | 'error'
25
-
26
- export interface DeliveryState {
27
- postalCode: string
28
- address: PostalAddress | null
29
- options: ShippingQuoteOption[]
30
- selectedZoneId: string | null
31
- status: DeliveryStatus
32
- error: string | null
33
-
34
- /** Look the CEP up and quote it. `subtotal` decides free-above thresholds. */
35
- resolve: (postalCode: string, subtotal: number) => Promise<void>
36
- selectZone: (zoneId: string) => void
37
- clear: () => void
38
- }
39
-
40
- const EMPTY = {
41
- postalCode: '',
42
- address: null,
43
- options: [] as ShippingQuoteOption[],
44
- selectedZoneId: null,
45
- status: 'idle' as DeliveryStatus,
46
- error: null,
47
- }
48
-
49
- export const useDeliveryStore = create<DeliveryState>()(
50
- persist(
51
- (set, get) => ({
52
- ...EMPTY,
53
-
54
- async resolve(postalCode: string, subtotal: number) {
55
- const code = normalizePostalCode(postalCode)
56
- if (code.length !== 8) {
57
- set({ ...EMPTY, postalCode, status: 'error', error: 'Digite os 8 dígitos do CEP.' })
58
- return
59
- }
60
-
61
- set({ postalCode: code, status: 'loading', error: null })
62
-
63
- // The QUOTE comes first and is the answer that matters. Whether we
64
- // deliver to a postcode, and for how much, is decided entirely by our
65
- // own zones against eight digits — it does not need to know the street.
66
- //
67
- // Doing it the other way round made the delivery answer depend on a
68
- // third party: with ViaCEP slow or rate-limited, a perfectly serviceable
69
- // address reported an error instead of a price.
70
- let options: ShippingQuoteOption[] = []
71
- try {
72
- options = (await getShopProvider().quoteShipping?.(code, subtotal)) ?? []
73
- } catch {
74
- set({ ...EMPTY, postalCode: code, status: 'error',
75
- error: 'Não foi possível calcular o frete agora. Tente de novo.' })
76
- return
77
- }
78
-
79
- // The ADDRESS is the convenience layer: it saves the buyer typing, and
80
- // losing it costs typing, not the sale. Failures here never change the
81
- // delivery verdict already decided above.
82
- let address: PostalAddress | null = null
83
- let notFound = false
84
- try {
85
- address = await lookupPostalCode(code)
86
- notFound = address === null
87
- } catch {
88
- address = null
89
- }
90
-
91
- set({
92
- postalCode: code,
93
- address,
94
- options,
95
- selectedZoneId: options[0]?.zoneId ?? null,
96
- // A store with no zones configured quotes nothing, and that must NOT
97
- // read as "we don't deliver here" — it falls back to the store-wide
98
- // flat rate, which the cart already knows how to show.
99
- status: options.length > 0 ? 'served' : 'unserved',
100
- // Reported alongside the price, not instead of it: the CEP may be
101
- // mistyped even though its range is covered.
102
- error: notFound ? 'CEP não encontrado. Confira os números.' : null,
103
- })
104
- },
105
-
106
- selectZone(zoneId: string) {
107
- if (get().options.some((option) => option.zoneId === zoneId)) set({ selectedZoneId: zoneId })
108
- },
109
-
110
- clear() {
111
- set({ ...EMPTY })
112
- },
113
- }),
114
- {
115
- name: 'fayz.storefront.delivery.v1',
116
- // Deliberately NOT persisting `options`: a rehydrated
117
- // price would be shown as current without anything having quoted it. The
118
- // address survives, the money is asked for again.
119
- partialize: (state) => ({ postalCode: state.postalCode, address: state.address }),
120
- onRehydrateStorage: () => (state) => {
121
- if (state?.address) state.status = 'idle'
122
- },
123
- },
124
- ),
125
- )
126
-
127
- /**
128
- * The freight for the chosen zone at THIS subtotal, or null when there is no
129
- * zone in play (no CEP yet, or a store that configured none) and the caller
130
- * should use the store-wide rate. Null never means free.
131
- *
132
- * The free-above rule is applied here rather than trusting the `rate` the
133
- * server resolved, because that one was resolved for whatever the cart held at
134
- * quote time. Re-deriving from `baseRate`/`freeAbove` — the same CASE
135
- * shop_shipping_for runs — means adding an item can never leave a stale price
136
- * on screen. An earlier version fell back to the config flat rate when the
137
- * quote went stale, which showed R$ 8 (the flat rate) for an address in an
138
- * R$ 18 zone: shown one number, charged another.
139
- */
140
- export function resolveOptionRate(option: ShippingQuoteOption, subtotal: number): number {
141
- if (option.freeAbove != null && subtotal >= option.freeAbove) return 0
142
- return option.baseRate
143
- }
144
-
145
- export const selectQuotedShipping = (
146
- state: Pick<DeliveryState, 'options' | 'selectedZoneId' | 'status'>,
147
- subtotal: number,
148
- ): number | null => {
149
- if (state.status !== 'served') return null
150
- const option = state.options.find((o) => o.zoneId === state.selectedZoneId) ?? state.options[0]
151
- return option ? resolveOptionRate(option, subtotal) : null
152
- }