@vtex/faststore 0.0.1

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 (538) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/LICENSE +21 -0
  3. package/README.md +95 -0
  4. package/dist/actions.json +334 -0
  5. package/dist/catalog.json +6615 -0
  6. package/dist/client.d.ts +17 -0
  7. package/dist/client.js +8 -0
  8. package/dist/components.d.ts +87 -0
  9. package/dist/components.js +87 -0
  10. package/dist/content-types.json +684 -0
  11. package/dist/core/dist/actions/mock-action.d.ts +24 -0
  12. package/dist/core/dist/actions/mock-action.js +28 -0
  13. package/dist/core/dist/actions/mock-action.js.map +1 -0
  14. package/dist/core/dist/actions/registry.d.ts +24 -0
  15. package/dist/core/dist/actions/registry.js +28 -0
  16. package/dist/core/dist/actions/registry.js.map +1 -0
  17. package/dist/core/dist/define-component.d.ts +100 -0
  18. package/dist/core/dist/define-component.js +8 -0
  19. package/dist/core/dist/define-component.js.map +1 -0
  20. package/dist/core/dist/define-content-type.d.ts +95 -0
  21. package/dist/core/dist/define-content-type.js +283 -0
  22. package/dist/core/dist/define-content-type.js.map +1 -0
  23. package/dist/core/dist/index.d.ts +7 -0
  24. package/dist/core/dist/index.js +5 -0
  25. package/dist/core/dist/schema/generated/schema.d.ts +28 -0
  26. package/dist/core/dist/types.d.ts +1 -0
  27. package/dist/docs/access-code-field.md +100 -0
  28. package/dist/docs/access-code-sign-in.md +174 -0
  29. package/dist/docs/account-entry-point.md +155 -0
  30. package/dist/docs/address-summary.md +50 -0
  31. package/dist/docs/buy-button.md +162 -0
  32. package/dist/docs/carousel.md +105 -0
  33. package/dist/docs/cart-item.md +162 -0
  34. package/dist/docs/cart-totalizer.md +197 -0
  35. package/dist/docs/cart.md +495 -0
  36. package/dist/docs/client-preferences.md +184 -0
  37. package/dist/docs/client-profile-form.md +192 -0
  38. package/dist/docs/client-profile.md +117 -0
  39. package/dist/docs/container.md +97 -0
  40. package/dist/docs/document-field.md +97 -0
  41. package/dist/docs/email-field.md +93 -0
  42. package/dist/docs/email-identification.md +102 -0
  43. package/dist/docs/footer-copyright.md +112 -0
  44. package/dist/docs/footer-link-group.md +162 -0
  45. package/dist/docs/footer-root.md +145 -0
  46. package/dist/docs/footer-social.md +151 -0
  47. package/dist/docs/free-shipping-progress.md +87 -0
  48. package/dist/docs/gallery.md +84 -0
  49. package/dist/docs/header-root.md +150 -0
  50. package/dist/docs/identity-edit.md +88 -0
  51. package/dist/docs/identity-summary.md +106 -0
  52. package/dist/docs/incentives.md +151 -0
  53. package/dist/docs/logo.md +135 -0
  54. package/dist/docs/meter.md +67 -0
  55. package/dist/docs/navigation-link-list.md +171 -0
  56. package/dist/docs/navigation-link.md +163 -0
  57. package/dist/docs/navigation-menu.md +264 -0
  58. package/dist/docs/payment-methods.md +139 -0
  59. package/dist/docs/phone-field.md +106 -0
  60. package/dist/docs/postal-code-field.md +126 -0
  61. package/dist/docs/pricing.md +499 -0
  62. package/dist/docs/product-gallery.md +409 -0
  63. package/dist/docs/product-information.md +295 -0
  64. package/dist/docs/product-list.md +170 -0
  65. package/dist/docs/product-quantity.md +88 -0
  66. package/dist/docs/product-shelf.md +141 -0
  67. package/dist/docs/promotion.md +109 -0
  68. package/dist/docs/region.md +225 -0
  69. package/dist/docs/session.md +123 -0
  70. package/dist/docs/shipping-address.md +390 -0
  71. package/dist/docs/shipping-simulator.md +147 -0
  72. package/dist/docs/sign-in-form.md +117 -0
  73. package/dist/docs/tabs.md +176 -0
  74. package/dist/docs/toast.md +124 -0
  75. package/dist/docs/variant-selector.md +450 -0
  76. package/dist/graphql/define-subgraph.d.ts +12 -0
  77. package/dist/graphql/define-subgraph.js +15 -0
  78. package/dist/graphql/define-subgraph.js.map +1 -0
  79. package/dist/graphql/gql.d.ts +10 -0
  80. package/dist/graphql/gql.js +16 -0
  81. package/dist/graphql/gql.js.map +1 -0
  82. package/dist/graphql/types.d.ts +88 -0
  83. package/dist/graphql.d.ts +4 -0
  84. package/dist/graphql.js +3 -0
  85. package/dist/index.d.ts +19 -0
  86. package/dist/index.js +5 -0
  87. package/dist/internal/client.d.ts +24 -0
  88. package/dist/internal/client.js +23 -0
  89. package/dist/internal/content.d.ts +2 -0
  90. package/dist/internal/content.js +2 -0
  91. package/dist/internal/server.d.ts +7 -0
  92. package/dist/internal/server.js +6 -0
  93. package/dist/matter/access-code-sign-in/access-code-sign-in.d.ts +111 -0
  94. package/dist/matter/access-code-sign-in/access-code-sign-in.js +387 -0
  95. package/dist/matter/access-code-sign-in/access-code-sign-in.js.map +1 -0
  96. package/dist/matter/account-entry-point/account-entry-point.d.ts +64 -0
  97. package/dist/matter/account-entry-point/account-entry-point.js +151 -0
  98. package/dist/matter/account-entry-point/account-entry-point.js.map +1 -0
  99. package/dist/matter/breadcrumb/breadcrumb.d.ts +40 -0
  100. package/dist/matter/breadcrumb/breadcrumb.js +155 -0
  101. package/dist/matter/breadcrumb/breadcrumb.js.map +1 -0
  102. package/dist/matter/buy-button/buy-button.d.ts +95 -0
  103. package/dist/matter/buy-button/buy-button.js +259 -0
  104. package/dist/matter/buy-button/buy-button.js.map +1 -0
  105. package/dist/matter/cart/cart-namespace.d.ts +48 -0
  106. package/dist/matter/cart/cart-namespace.js +50 -0
  107. package/dist/matter/cart/cart-namespace.js.map +1 -0
  108. package/dist/matter/cart/cart.d.ts +312 -0
  109. package/dist/matter/cart/cart.js +1034 -0
  110. package/dist/matter/cart/cart.js.map +1 -0
  111. package/dist/matter/cart-item/cart-item.d.ts +103 -0
  112. package/dist/matter/cart-item/cart-item.js +672 -0
  113. package/dist/matter/cart-item/cart-item.js.map +1 -0
  114. package/dist/matter/cart-item-compositions/cart-item-compositions.d.ts +49 -0
  115. package/dist/matter/cart-item-compositions/cart-item-compositions.js +165 -0
  116. package/dist/matter/cart-item-compositions/cart-item-compositions.js.map +1 -0
  117. package/dist/matter/cart-item-customizations/cart-item-customizations.d.ts +28 -0
  118. package/dist/matter/cart-item-customizations/cart-item-customizations.js +73 -0
  119. package/dist/matter/cart-item-customizations/cart-item-customizations.js.map +1 -0
  120. package/dist/matter/cart-item-discounts/cart-item-discounts.d.ts +33 -0
  121. package/dist/matter/cart-item-discounts/cart-item-discounts.js +70 -0
  122. package/dist/matter/cart-item-discounts/cart-item-discounts.js.map +1 -0
  123. package/dist/matter/cart-item-seller-info/cart-item-seller-info.d.ts +24 -0
  124. package/dist/matter/cart-item-seller-info/cart-item-seller-info.js +54 -0
  125. package/dist/matter/cart-item-seller-info/cart-item-seller-info.js.map +1 -0
  126. package/dist/matter/cart-item-variations/cart-item-variations.d.ts +27 -0
  127. package/dist/matter/cart-item-variations/cart-item-variations.js +69 -0
  128. package/dist/matter/cart-item-variations/cart-item-variations.js.map +1 -0
  129. package/dist/matter/cart-totalizer/cart-totalizer.d.ts +78 -0
  130. package/dist/matter/cart-totalizer/cart-totalizer.js +220 -0
  131. package/dist/matter/cart-totalizer/cart-totalizer.js.map +1 -0
  132. package/dist/matter/client-preferences/client-preferences.d.ts +50 -0
  133. package/dist/matter/client-preferences/client-preferences.js +206 -0
  134. package/dist/matter/client-preferences/client-preferences.js.map +1 -0
  135. package/dist/matter/client-profile/client-profile.d.ts +59 -0
  136. package/dist/matter/client-profile/client-profile.js +185 -0
  137. package/dist/matter/client-profile/client-profile.js.map +1 -0
  138. package/dist/matter/client-profile-form/client-profile-form.d.ts +126 -0
  139. package/dist/matter/client-profile-form/client-profile-form.js +660 -0
  140. package/dist/matter/client-profile-form/client-profile-form.js.map +1 -0
  141. package/dist/matter/delivery-options/delivery-options-accordion.d.ts +30 -0
  142. package/dist/matter/delivery-options/delivery-options-accordion.js +189 -0
  143. package/dist/matter/delivery-options/delivery-options-accordion.js.map +1 -0
  144. package/dist/matter/delivery-options/delivery-options-controller.d.ts +49 -0
  145. package/dist/matter/delivery-options/delivery-options-controller.js +203 -0
  146. package/dist/matter/delivery-options/delivery-options-controller.js.map +1 -0
  147. package/dist/matter/delivery-options/delivery-options.d.ts +31 -0
  148. package/dist/matter/delivery-options/delivery-options.js +103 -0
  149. package/dist/matter/delivery-options/delivery-options.js.map +1 -0
  150. package/dist/matter/delivery-options/use-delivery-option-selection.d.ts +9 -0
  151. package/dist/matter/delivery-options/use-delivery-option-selection.js +76 -0
  152. package/dist/matter/delivery-options/use-delivery-option-selection.js.map +1 -0
  153. package/dist/matter/email-identification/email-identification.d.ts +37 -0
  154. package/dist/matter/email-identification/email-identification.js +111 -0
  155. package/dist/matter/email-identification/email-identification.js.map +1 -0
  156. package/dist/matter/free-shipping-progress/free-shipping-progress.d.ts +44 -0
  157. package/dist/matter/free-shipping-progress/free-shipping-progress.js +170 -0
  158. package/dist/matter/free-shipping-progress/free-shipping-progress.js.map +1 -0
  159. package/dist/matter/identity-edit/identity-edit.d.ts +52 -0
  160. package/dist/matter/identity-edit/identity-edit.js +148 -0
  161. package/dist/matter/identity-edit/identity-edit.js.map +1 -0
  162. package/dist/matter/identity-summary/identity-summary.d.ts +128 -0
  163. package/dist/matter/identity-summary/identity-summary.js +344 -0
  164. package/dist/matter/identity-summary/identity-summary.js.map +1 -0
  165. package/dist/matter/pricing/pricing.d.ts +162 -0
  166. package/dist/matter/pricing/pricing.js +793 -0
  167. package/dist/matter/pricing/pricing.js.map +1 -0
  168. package/dist/matter/product-gallery/product-gallery.d.ts +23 -0
  169. package/dist/matter/product-gallery/product-gallery.js +188 -0
  170. package/dist/matter/product-gallery/product-gallery.js.map +1 -0
  171. package/dist/matter/product-information/product-information.d.ts +61 -0
  172. package/dist/matter/product-information/product-information.js +355 -0
  173. package/dist/matter/product-information/product-information.js.map +1 -0
  174. package/dist/matter/product-list/product-list.d.ts +86 -0
  175. package/dist/matter/product-list/product-list.js +342 -0
  176. package/dist/matter/product-list/product-list.js.map +1 -0
  177. package/dist/matter/product-quantity/product-quantity.d.ts +50 -0
  178. package/dist/matter/product-quantity/product-quantity.js +111 -0
  179. package/dist/matter/product-quantity/product-quantity.js.map +1 -0
  180. package/dist/matter/product-shelf/product-shelf.d.ts +125 -0
  181. package/dist/matter/product-shelf/product-shelf.js +376 -0
  182. package/dist/matter/product-shelf/product-shelf.js.map +1 -0
  183. package/dist/matter/region/region.d.ts +211 -0
  184. package/dist/matter/region/region.js +579 -0
  185. package/dist/matter/region/region.js.map +1 -0
  186. package/dist/matter/session/session.d.ts +58 -0
  187. package/dist/matter/session/session.js +112 -0
  188. package/dist/matter/session/session.js.map +1 -0
  189. package/dist/matter/shipping-address/country-descriptors.js +101 -0
  190. package/dist/matter/shipping-address/country-descriptors.js.map +1 -0
  191. package/dist/matter/shipping-address/shipping-address.d.ts +284 -0
  192. package/dist/matter/shipping-address/shipping-address.js +1036 -0
  193. package/dist/matter/shipping-address/shipping-address.js.map +1 -0
  194. package/dist/matter/shipping-simulator/shipping-simulator.d.ts +143 -0
  195. package/dist/matter/shipping-simulator/shipping-simulator.js +644 -0
  196. package/dist/matter/shipping-simulator/shipping-simulator.js.map +1 -0
  197. package/dist/matter/sign-in-form/sign-in-form.d.ts +79 -0
  198. package/dist/matter/sign-in-form/sign-in-form.js +226 -0
  199. package/dist/matter/sign-in-form/sign-in-form.js.map +1 -0
  200. package/dist/matter/variant-selector/variant-selector.d.ts +183 -0
  201. package/dist/matter/variant-selector/variant-selector.js +840 -0
  202. package/dist/matter/variant-selector/variant-selector.js.map +1 -0
  203. package/dist/message-locales.json +7 -0
  204. package/dist/particles/access-code-field/access-code-field.d.ts +33 -0
  205. package/dist/particles/access-code-field/access-code-field.js +95 -0
  206. package/dist/particles/access-code-field/access-code-field.js.map +1 -0
  207. package/dist/particles/accordion/accordion.d.ts +45 -0
  208. package/dist/particles/accordion/accordion.js +156 -0
  209. package/dist/particles/accordion/accordion.js.map +1 -0
  210. package/dist/particles/address-summary/address-summary.d.ts +50 -0
  211. package/dist/particles/address-summary/address-summary.js +129 -0
  212. package/dist/particles/address-summary/address-summary.js.map +1 -0
  213. package/dist/particles/badge/badge.d.ts +10 -0
  214. package/dist/particles/badge/badge.js +27 -0
  215. package/dist/particles/badge/badge.js.map +1 -0
  216. package/dist/particles/button/button.d.ts +18 -0
  217. package/dist/particles/button/button.js +37 -0
  218. package/dist/particles/button/button.js.map +1 -0
  219. package/dist/particles/carousel/carousel.d.ts +60 -0
  220. package/dist/particles/carousel/carousel.js +335 -0
  221. package/dist/particles/carousel/carousel.js.map +1 -0
  222. package/dist/particles/checkbox/checkbox.d.ts +40 -0
  223. package/dist/particles/checkbox/checkbox.js +82 -0
  224. package/dist/particles/checkbox/checkbox.js.map +1 -0
  225. package/dist/particles/container/container.d.ts +20 -0
  226. package/dist/particles/container/container.js +36 -0
  227. package/dist/particles/container/container.js.map +1 -0
  228. package/dist/particles/dialog/dialog.d.ts +54 -0
  229. package/dist/particles/dialog/dialog.js +192 -0
  230. package/dist/particles/dialog/dialog.js.map +1 -0
  231. package/dist/particles/document-field/document-field.d.ts +61 -0
  232. package/dist/particles/document-field/document-field.js +146 -0
  233. package/dist/particles/document-field/document-field.js.map +1 -0
  234. package/dist/particles/drawer/drawer.d.ts +52 -0
  235. package/dist/particles/drawer/drawer.js +183 -0
  236. package/dist/particles/drawer/drawer.js.map +1 -0
  237. package/dist/particles/email-field/email-field.d.ts +37 -0
  238. package/dist/particles/email-field/email-field.js +106 -0
  239. package/dist/particles/email-field/email-field.js.map +1 -0
  240. package/dist/particles/field/field.d.ts +50 -0
  241. package/dist/particles/field/field.js +133 -0
  242. package/dist/particles/field/field.js.map +1 -0
  243. package/dist/particles/fieldset/fieldset.d.ts +16 -0
  244. package/dist/particles/fieldset/fieldset.js +52 -0
  245. package/dist/particles/fieldset/fieldset.js.map +1 -0
  246. package/dist/particles/footer-copyright/footer-copyright.d.ts +32 -0
  247. package/dist/particles/footer-copyright/footer-copyright.js +50 -0
  248. package/dist/particles/footer-copyright/footer-copyright.js.map +1 -0
  249. package/dist/particles/footer-link-group/footer-link-group.d.ts +66 -0
  250. package/dist/particles/footer-link-group/footer-link-group.js +154 -0
  251. package/dist/particles/footer-link-group/footer-link-group.js.map +1 -0
  252. package/dist/particles/footer-root/footer-root.d.ts +21 -0
  253. package/dist/particles/footer-root/footer-root.js +38 -0
  254. package/dist/particles/footer-root/footer-root.js.map +1 -0
  255. package/dist/particles/footer-social/footer-social.d.ts +79 -0
  256. package/dist/particles/footer-social/footer-social.js +176 -0
  257. package/dist/particles/footer-social/footer-social.js.map +1 -0
  258. package/dist/particles/gallery/gallery.d.ts +181 -0
  259. package/dist/particles/gallery/gallery.js +920 -0
  260. package/dist/particles/gallery/gallery.js.map +1 -0
  261. package/dist/particles/header-root/header-root.d.ts +21 -0
  262. package/dist/particles/header-root/header-root.js +38 -0
  263. package/dist/particles/header-root/header-root.js.map +1 -0
  264. package/dist/particles/icon/icon.d.ts +22 -0
  265. package/dist/particles/icon/icon.js +48 -0
  266. package/dist/particles/icon/icon.js.map +1 -0
  267. package/dist/particles/image/image.d.ts +13 -0
  268. package/dist/particles/image/image.js +59 -0
  269. package/dist/particles/image/image.js.map +1 -0
  270. package/dist/particles/incentives/incentives.d.ts +85 -0
  271. package/dist/particles/incentives/incentives.js +200 -0
  272. package/dist/particles/incentives/incentives.js.map +1 -0
  273. package/dist/particles/input/input.d.ts +9 -0
  274. package/dist/particles/input/input.js +28 -0
  275. package/dist/particles/input/input.js.map +1 -0
  276. package/dist/particles/logo/logo.d.ts +55 -0
  277. package/dist/particles/logo/logo.js +96 -0
  278. package/dist/particles/logo/logo.js.map +1 -0
  279. package/dist/particles/menu/menu.d.ts +103 -0
  280. package/dist/particles/menu/menu.js +409 -0
  281. package/dist/particles/menu/menu.js.map +1 -0
  282. package/dist/particles/menubar/menubar.d.ts +18 -0
  283. package/dist/particles/menubar/menubar.js +42 -0
  284. package/dist/particles/menubar/menubar.js.map +1 -0
  285. package/dist/particles/meter/meter.d.ts +36 -0
  286. package/dist/particles/meter/meter.js +132 -0
  287. package/dist/particles/meter/meter.js.map +1 -0
  288. package/dist/particles/navigation-link/navigation-link.d.ts +43 -0
  289. package/dist/particles/navigation-link/navigation-link.js +82 -0
  290. package/dist/particles/navigation-link/navigation-link.js.map +1 -0
  291. package/dist/particles/navigation-link-list/navigation-link-list.d.ts +59 -0
  292. package/dist/particles/navigation-link-list/navigation-link-list.js +103 -0
  293. package/dist/particles/navigation-link-list/navigation-link-list.js.map +1 -0
  294. package/dist/particles/navigation-menu/navigation-menu.d.ts +78 -0
  295. package/dist/particles/navigation-menu/navigation-menu.js +295 -0
  296. package/dist/particles/navigation-menu/navigation-menu.js.map +1 -0
  297. package/dist/particles/number-field/number-field.d.ts +46 -0
  298. package/dist/particles/number-field/number-field.js +169 -0
  299. package/dist/particles/number-field/number-field.js.map +1 -0
  300. package/dist/particles/password-field/password-field.d.ts +31 -0
  301. package/dist/particles/password-field/password-field.js +109 -0
  302. package/dist/particles/password-field/password-field.js.map +1 -0
  303. package/dist/particles/payment-methods/payment-methods.d.ts +72 -0
  304. package/dist/particles/payment-methods/payment-methods.js +151 -0
  305. package/dist/particles/payment-methods/payment-methods.js.map +1 -0
  306. package/dist/particles/phone-field/phone-field.d.ts +67 -0
  307. package/dist/particles/phone-field/phone-field.js +250 -0
  308. package/dist/particles/phone-field/phone-field.js.map +1 -0
  309. package/dist/particles/popover/popover.d.ts +68 -0
  310. package/dist/particles/popover/popover.js +284 -0
  311. package/dist/particles/popover/popover.js.map +1 -0
  312. package/dist/particles/postal-code-field/postal-code-field.d.ts +75 -0
  313. package/dist/particles/postal-code-field/postal-code-field.js +169 -0
  314. package/dist/particles/postal-code-field/postal-code-field.js.map +1 -0
  315. package/dist/particles/promotion/promotion.d.ts +46 -0
  316. package/dist/particles/promotion/promotion.js +78 -0
  317. package/dist/particles/promotion/promotion.js.map +1 -0
  318. package/dist/particles/quantity-selector/quantity-selector.d.ts +30 -0
  319. package/dist/particles/quantity-selector/quantity-selector.js +116 -0
  320. package/dist/particles/quantity-selector/quantity-selector.js.map +1 -0
  321. package/dist/particles/radio/radio.d.ts +36 -0
  322. package/dist/particles/radio/radio.js +76 -0
  323. package/dist/particles/radio/radio.js.map +1 -0
  324. package/dist/particles/scroll-area/scroll-area.d.ts +36 -0
  325. package/dist/particles/scroll-area/scroll-area.js +145 -0
  326. package/dist/particles/scroll-area/scroll-area.js.map +1 -0
  327. package/dist/particles/select/select.d.ts +125 -0
  328. package/dist/particles/select/select.js +478 -0
  329. package/dist/particles/select/select.js.map +1 -0
  330. package/dist/particles/separator/separator.d.ts +12 -0
  331. package/dist/particles/separator/separator.js +33 -0
  332. package/dist/particles/separator/separator.js.map +1 -0
  333. package/dist/particles/shared/input-mask.d.ts +5 -0
  334. package/dist/particles/shared/input-mask.js +58 -0
  335. package/dist/particles/shared/input-mask.js.map +1 -0
  336. package/dist/particles/spinner/spinner.d.ts +13 -0
  337. package/dist/particles/spinner/spinner.js +31 -0
  338. package/dist/particles/spinner/spinner.js.map +1 -0
  339. package/dist/particles/switch/switch.d.ts +27 -0
  340. package/dist/particles/switch/switch.js +59 -0
  341. package/dist/particles/switch/switch.js.map +1 -0
  342. package/dist/particles/tabs/tabs.d.ts +45 -0
  343. package/dist/particles/tabs/tabs.js +164 -0
  344. package/dist/particles/tabs/tabs.js.map +1 -0
  345. package/dist/particles/text/text.d.ts +24 -0
  346. package/dist/particles/text/text.js +40 -0
  347. package/dist/particles/text/text.js.map +1 -0
  348. package/dist/particles/toast/toast.d.ts +83 -0
  349. package/dist/particles/toast/toast.js +194 -0
  350. package/dist/particles/toast/toast.js.map +1 -0
  351. package/dist/particles/toggle/toggle.d.ts +26 -0
  352. package/dist/particles/toggle/toggle.js +61 -0
  353. package/dist/particles/toggle/toggle.js.map +1 -0
  354. package/dist/particles/tooltip/tooltip.d.ts +61 -0
  355. package/dist/particles/tooltip/tooltip.js +240 -0
  356. package/dist/particles/tooltip/tooltip.js.map +1 -0
  357. package/dist/schema.graphql +2953 -0
  358. package/dist/sdk/actions/cart-action-provider.d.ts +19 -0
  359. package/dist/sdk/actions/cart-action-provider.js +23 -0
  360. package/dist/sdk/actions/cart-action-provider.js.map +1 -0
  361. package/dist/sdk/actions/identity-action-provider.d.ts +15 -0
  362. package/dist/sdk/actions/identity-action-provider.js +19 -0
  363. package/dist/sdk/actions/identity-action-provider.js.map +1 -0
  364. package/dist/sdk/actions/index.d.ts +7 -0
  365. package/dist/sdk/actions/index.js +6 -0
  366. package/dist/sdk/actions/inject-actions.d.ts +14 -0
  367. package/dist/sdk/actions/inject-actions.js +36 -0
  368. package/dist/sdk/actions/inject-actions.js.map +1 -0
  369. package/dist/sdk/actions/region-action-provider.d.ts +15 -0
  370. package/dist/sdk/actions/region-action-provider.js +19 -0
  371. package/dist/sdk/actions/region-action-provider.js.map +1 -0
  372. package/dist/sdk/actions/session-action-provider.d.ts +15 -0
  373. package/dist/sdk/actions/session-action-provider.js +19 -0
  374. package/dist/sdk/actions/session-action-provider.js.map +1 -0
  375. package/dist/sdk/actions/shipping-action-provider.d.ts +15 -0
  376. package/dist/sdk/actions/shipping-action-provider.js +19 -0
  377. package/dist/sdk/actions/shipping-action-provider.js.map +1 -0
  378. package/dist/sdk/actions/types.d.ts +21 -0
  379. package/dist/sdk/cache/storefront-cache.js +35 -0
  380. package/dist/sdk/cache/storefront-cache.js.map +1 -0
  381. package/dist/sdk/cart/operations.d.ts +31 -0
  382. package/dist/sdk/cart/operations.js +215 -0
  383. package/dist/sdk/cart/operations.js.map +1 -0
  384. package/dist/sdk/cart/optimistic.d.ts +24 -0
  385. package/dist/sdk/cart/optimistic.js +164 -0
  386. package/dist/sdk/cart/optimistic.js.map +1 -0
  387. package/dist/sdk/cart/use-cart-actions.d.ts +56 -0
  388. package/dist/sdk/cart/use-cart-actions.js +348 -0
  389. package/dist/sdk/cart/use-cart-actions.js.map +1 -0
  390. package/dist/sdk/cart/use-cart-validate-on-open.js +50 -0
  391. package/dist/sdk/cart/use-cart-validate-on-open.js.map +1 -0
  392. package/dist/sdk/cart/write-gate.js +54 -0
  393. package/dist/sdk/cart/write-gate.js.map +1 -0
  394. package/dist/sdk/client/assert-api-url.js +20 -0
  395. package/dist/sdk/client/assert-api-url.js.map +1 -0
  396. package/dist/sdk/client/create-client.d.ts +23 -0
  397. package/dist/sdk/client/create-client.js +46 -0
  398. package/dist/sdk/client/create-client.js.map +1 -0
  399. package/dist/sdk/client/fetch-page-data.d.ts +39 -0
  400. package/dist/sdk/client/fetch-page-data.js +33 -0
  401. package/dist/sdk/client/fetch-page-data.js.map +1 -0
  402. package/dist/sdk/client/register-preload-query.d.ts +24 -0
  403. package/dist/sdk/client/register-preload-query.js +33 -0
  404. package/dist/sdk/client/register-preload-query.js.map +1 -0
  405. package/dist/sdk/content/create-content-runtime.d.ts +68 -0
  406. package/dist/sdk/content/create-content-runtime.js +503 -0
  407. package/dist/sdk/content/create-content-runtime.js.map +1 -0
  408. package/dist/sdk/context/headers.d.ts +15 -0
  409. package/dist/sdk/context/headers.js +21 -0
  410. package/dist/sdk/context/headers.js.map +1 -0
  411. package/dist/sdk/context/storefront-context.d.ts +11 -0
  412. package/dist/sdk/context/storefront-context.js +29 -0
  413. package/dist/sdk/context/storefront-context.js.map +1 -0
  414. package/dist/sdk/data/data-override-context.d.ts +12 -0
  415. package/dist/sdk/data/data-override-context.js +19 -0
  416. package/dist/sdk/data/data-override-context.js.map +1 -0
  417. package/dist/sdk/data/entity-subscriber.js +28 -0
  418. package/dist/sdk/data/entity-subscriber.js.map +1 -0
  419. package/dist/sdk/data/hot-data-provider.d.ts +19 -0
  420. package/dist/sdk/data/hot-data-provider.js +33 -0
  421. package/dist/sdk/data/hot-data-provider.js.map +1 -0
  422. package/dist/sdk/data/index.d.ts +8 -0
  423. package/dist/sdk/data/index.js +8 -0
  424. package/dist/sdk/data/list-item-ref-context.d.ts +20 -0
  425. package/dist/sdk/data/list-item-ref-context.js +11 -0
  426. package/dist/sdk/data/list-item-ref-context.js.map +1 -0
  427. package/dist/sdk/data/multiple-reactive-data-provider.d.ts +32 -0
  428. package/dist/sdk/data/multiple-reactive-data-provider.js +20 -0
  429. package/dist/sdk/data/multiple-reactive-data-provider.js.map +1 -0
  430. package/dist/sdk/data/page-reactive-data-root.d.ts +53 -0
  431. package/dist/sdk/data/page-reactive-data-root.js +153 -0
  432. package/dist/sdk/data/page-reactive-data-root.js.map +1 -0
  433. package/dist/sdk/data/reactive-data-provider.d.ts +25 -0
  434. package/dist/sdk/data/reactive-data-provider.js +24 -0
  435. package/dist/sdk/data/reactive-data-provider.js.map +1 -0
  436. package/dist/sdk/data/reactive-list-item-data-provider.d.ts +26 -0
  437. package/dist/sdk/data/reactive-list-item-data-provider.js +42 -0
  438. package/dist/sdk/data/reactive-list-item-data-provider.js.map +1 -0
  439. package/dist/sdk/data/use-reactive-entity.js +40 -0
  440. package/dist/sdk/data/use-reactive-entity.js.map +1 -0
  441. package/dist/sdk/format/client.d.ts +12 -0
  442. package/dist/sdk/format/client.js +20 -0
  443. package/dist/sdk/format/client.js.map +1 -0
  444. package/dist/sdk/format/formatters.d.ts +32 -0
  445. package/dist/sdk/format/formatters.js +45 -0
  446. package/dist/sdk/format/formatters.js.map +1 -0
  447. package/dist/sdk/generated/fragment-types.js +23 -0
  448. package/dist/sdk/generated/fragment-types.js.map +1 -0
  449. package/dist/sdk/generated/gql.js +51 -0
  450. package/dist/sdk/generated/gql.js.map +1 -0
  451. package/dist/sdk/generated/graphql.d.ts +622 -0
  452. package/dist/sdk/generated/graphql.js +11917 -0
  453. package/dist/sdk/generated/graphql.js.map +1 -0
  454. package/dist/sdk/graphql-tag.d.ts +10 -0
  455. package/dist/sdk/graphql-tag.js +21 -0
  456. package/dist/sdk/graphql-tag.js.map +1 -0
  457. package/dist/sdk/i18n/client.d.ts +4 -0
  458. package/dist/sdk/i18n/client.js +4 -0
  459. package/dist/sdk/i18n/locales.d.ts +8 -0
  460. package/dist/sdk/i18n/locales.js +57 -0
  461. package/dist/sdk/i18n/locales.js.map +1 -0
  462. package/dist/sdk/i18n/messages/en-US.js +24 -0
  463. package/dist/sdk/i18n/messages/en-US.js.map +1 -0
  464. package/dist/sdk/i18n/messages/en-US.json +19 -0
  465. package/dist/sdk/i18n/messages/en-US.json.d.ts +23 -0
  466. package/dist/sdk/i18n/messages/es-ES.js +24 -0
  467. package/dist/sdk/i18n/messages/es-ES.js.map +1 -0
  468. package/dist/sdk/i18n/messages/es-ES.json +19 -0
  469. package/dist/sdk/i18n/messages/pt-BR.js +24 -0
  470. package/dist/sdk/i18n/messages/pt-BR.js.map +1 -0
  471. package/dist/sdk/i18n/messages/pt-BR.json +19 -0
  472. package/dist/sdk/i18n/provider.d.ts +1 -0
  473. package/dist/sdk/i18n/provider.js +30 -0
  474. package/dist/sdk/i18n/provider.js.map +1 -0
  475. package/dist/sdk/i18n/server.d.ts +28 -0
  476. package/dist/sdk/i18n/server.js +59 -0
  477. package/dist/sdk/i18n/server.js.map +1 -0
  478. package/dist/sdk/identity/operations.d.ts +34 -0
  479. package/dist/sdk/identity/operations.js +78 -0
  480. package/dist/sdk/identity/operations.js.map +1 -0
  481. package/dist/sdk/identity/use-identity-actions.d.ts +62 -0
  482. package/dist/sdk/identity/use-identity-actions.js +180 -0
  483. package/dist/sdk/identity/use-identity-actions.js.map +1 -0
  484. package/dist/sdk/provider/index.d.ts +2 -0
  485. package/dist/sdk/provider/index.js +2 -0
  486. package/dist/sdk/provider/storefront-provider.d.ts +32 -0
  487. package/dist/sdk/provider/storefront-provider.js +111 -0
  488. package/dist/sdk/provider/storefront-provider.js.map +1 -0
  489. package/dist/sdk/region/operations.d.ts +6 -0
  490. package/dist/sdk/region/region-operations.d.ts +30 -0
  491. package/dist/sdk/region/region-operations.js +23 -0
  492. package/dist/sdk/region/region-operations.js.map +1 -0
  493. package/dist/sdk/region/use-region-actions.d.ts +23 -0
  494. package/dist/sdk/region/use-region-actions.js +66 -0
  495. package/dist/sdk/region/use-region-actions.js.map +1 -0
  496. package/dist/sdk/seller.js +11 -0
  497. package/dist/sdk/seller.js.map +1 -0
  498. package/dist/sdk/session/auth-operations.d.ts +47 -0
  499. package/dist/sdk/session/auth-operations.js +79 -0
  500. package/dist/sdk/session/auth-operations.js.map +1 -0
  501. package/dist/sdk/session/operations.d.ts +6 -0
  502. package/dist/sdk/session/use-session-actions.d.ts +27 -0
  503. package/dist/sdk/session/use-session-actions.js +126 -0
  504. package/dist/sdk/session/use-session-actions.js.map +1 -0
  505. package/dist/sdk/shipping/cart-operations.d.ts +3 -0
  506. package/dist/sdk/shipping/cart-operations.js +33 -0
  507. package/dist/sdk/shipping/cart-operations.js.map +1 -0
  508. package/dist/sdk/shipping/operations.d.ts +3 -0
  509. package/dist/sdk/shipping/operations.js +33 -0
  510. package/dist/sdk/shipping/operations.js.map +1 -0
  511. package/dist/sdk/shipping/option-select-operations.d.ts +24 -0
  512. package/dist/sdk/shipping/option-select-operations.js +45 -0
  513. package/dist/sdk/shipping/option-select-operations.js.map +1 -0
  514. package/dist/sdk/shipping/request-timeout.js +41 -0
  515. package/dist/sdk/shipping/request-timeout.js.map +1 -0
  516. package/dist/sdk/shipping/shipping-operations.d.ts +38 -0
  517. package/dist/sdk/shipping/shipping-operations.js +77 -0
  518. package/dist/sdk/shipping/shipping-operations.js.map +1 -0
  519. package/dist/sdk/shipping/use-cart-shipping-simulation.d.ts +7 -0
  520. package/dist/sdk/shipping/use-cart-shipping-simulation.js +72 -0
  521. package/dist/sdk/shipping/use-cart-shipping-simulation.js.map +1 -0
  522. package/dist/sdk/shipping/use-shipping-actions.d.ts +27 -0
  523. package/dist/sdk/shipping/use-shipping-actions.js +113 -0
  524. package/dist/sdk/shipping/use-shipping-actions.js.map +1 -0
  525. package/dist/sdk/shipping/use-shipping-simulation.d.ts +7 -0
  526. package/dist/sdk/shipping/use-shipping-simulation.js +72 -0
  527. package/dist/sdk/shipping/use-shipping-simulation.js.map +1 -0
  528. package/dist/sdk/state/cart.d.ts +42 -0
  529. package/dist/sdk/state/cart.js +64 -0
  530. package/dist/sdk/state/cart.js.map +1 -0
  531. package/dist/sdk/state/index.js +3 -0
  532. package/dist/sdk/state/variant-selector.d.ts +17 -0
  533. package/dist/sdk/state/variant-selector.js +14 -0
  534. package/dist/sdk/state/variant-selector.js.map +1 -0
  535. package/dist/utils/safe-href.js +63 -0
  536. package/dist/utils/safe-href.js.map +1 -0
  537. package/package.json +84 -0
  538. package/src/styles/tailwind.css +32 -0
@@ -0,0 +1,162 @@
1
+ # BuyButton
2
+
3
+ **Category:** commerce
4
+ **Purpose:** Add-to-cart button. Reads a product variant and dispatches the cart `addItem` action on click. Disables automatically when the variant is unavailable. Canonical use is on PDPs, but also valid in any product card context (related products, shelf) when product data is passed via `$data`.
5
+
6
+ ---
7
+
8
+ ## Visual cues (how to identify in an image)
9
+
10
+ A BuyButton block is present when you see:
11
+
12
+ - A **primary CTA button** with a label like "Comprar", "Adicionar ao carrinho", "Buy now", or similar.
13
+ - The button may appear **disabled or grayed out** with text like "Indisponível" or "Out of stock" — that is still a `BuyButtonButton`.
14
+
15
+ ---
16
+
17
+ ## When to use
18
+
19
+ - PDP purchase CTA — the canonical use, with data from the GraphQL fragment.
20
+ - Product cards in shelves or related products sections — pass the product data via `$data` prop instead of relying on the fragment.
21
+
22
+ ## When NOT to use
23
+
24
+ - Cart summary page CTAs — use cart-specific components.
25
+ - Non-purchasable links (wishlist, share) — use a plain button or link element.
26
+
27
+ ---
28
+
29
+ ## Composition
30
+
31
+ `BuyButtonRoot` is the data provider. `BuyButtonButton` is the rendered button. Always use both together.
32
+
33
+ ```
34
+ BuyButtonRoot
35
+ └── BuyButtonButton
36
+ ```
37
+
38
+ `BuyButtonButton` dispatches the cart `addItem` action through the compiler-injected `$actions.cart.addItem` prop. The add-to-cart write is **context-free** — it reads and writes the Apollo cache directly — so `BuyButton` needs **no `CartRoot` ancestor** (specs/actions.md, ADR-0010). Drop it on a PDP, a product card, a shelf, or the header alike.
39
+
40
+ Child order reflects visual order.
41
+
42
+ ---
43
+
44
+ ## Adding the selected quantity (ProductQuantity)
45
+
46
+ By default `BuyButtonButton` adds quantity 1. To add the quantity chosen in a PDP quantity selector, wrap the purchase area in a `ProductQuantityRoot` (a headless provider that holds the selected quantity): `BuyButtonButton` reads it via `useProductQuantity()`. Without a `ProductQuantityRoot` ancestor it falls back to quantity 1, so the BuyButton stays usable standalone.
47
+
48
+ `ProductQuantityRoot` renders no DOM, so it can sit high in the tree and the BuyButton and selector may live in different layout blocks:
49
+
50
+ ```text
51
+ ProductQuantityRoot (headless — no DOM; holds the quantity)
52
+ ├── ... BuyButtonRoot → BuyButtonButton ...
53
+ └── ... ProductQuantitySelector → NumberFieldGroup → controls ...
54
+ ```
55
+
56
+ See product-quantity.md.
57
+
58
+ ---
59
+
60
+ ## Components
61
+
62
+ ### BuyButtonRoot
63
+
64
+ Root data provider. Declares the GraphQL fragment and exposes product/variant context to `BuyButtonButton`.
65
+
66
+ | Prop | Type | Default | Notes |
67
+ |------|------|---------|-------|
68
+ | `selectedVariantId` | string | — | Page-supplied viewed SKU (a variant Node ID). Pre-selects the variant to add before the shopper interacts; a published swatch selection wins over it once set. |
69
+
70
+ **Data:** declares `fragment BuyButtonData on Query`. Fetches the first variant's `availableForSale` flag, `skuId`, and default seller ID as the fallback slice.
71
+
72
+ **Variant reactivity:** `BuyButtonRoot` reads the shopper's published variant selection (the same reactive state the VariantSelector swatches write). When a swatch is picked, the button adds **that variant** to the cart — its SKU (`variantId`) and its default seller — and its **availability** (disabled state and available/unavailable label) reflects the selected variant. The selected variant is fetched lazily and scoped to the product on screen; on a fetch error or null result it falls back to the product's first variant for both the payload and availability. Before any swatch interaction the optional `selectedVariantId` prop pre-selects the variant to add, and the live published selection wins once set. If the selected variant has no purchasable offer the button does not render, consistent with the pricing block.
73
+
74
+ ---
75
+
76
+ ### BuyButtonButton
77
+
78
+ The rendered button. Dispatches `$actions.cart.addItem(...)` on click.
79
+
80
+ | Prop | Type | Default | Notes |
81
+ |------|------|---------|-------|
82
+ | `availableLabel` | string | `"Comprar"` | Label shown when the variant is available for sale |
83
+ | `unavailableLabel` | string | `"Indisponivel"` | Label shown when the variant is not available |
84
+
85
+ **Actions:** declares `actions: { cart: ['addItem'] }`; the compiler threads the `addItem` handler in via `$actions.cart`. Renders `null` when `BuyButtonRoot` has no valid variant data. Disabled (and `aria-busy`) while the add is in-flight (the button tracks its own pending state). Must be a descendant of `BuyButtonRoot`.
86
+
87
+ ---
88
+
89
+ ## No CartRoot requirement
90
+
91
+ `BuyButtonButton` writes through `$actions.cart.addItem`, which the compiler injects from its `actions` selector. The handler reads and writes the cache directly, so **`BuyButton` needs no `CartRoot` ancestor**. A PDP schema can render `BuyButtonRoot` → `BuyButtonButton` directly under the page `Container`.
92
+
93
+ A `CartRoot` is still hosted by the layout so cart **reads** (mini-cart count, total, line items) work — but that is the layout's concern, not the buy button's, and it is never declared in the page schema.
94
+
95
+ ---
96
+
97
+ ## Canonical schema example
98
+
99
+ Minimal PDP buy button — no `CartRoot` in the page schema:
100
+
101
+ ```json
102
+ {
103
+ "root": {
104
+ "type": "Container",
105
+ "children": ["gallery", "product-info", "pricing", "buy-button"]
106
+ },
107
+ "buy-button": {
108
+ "type": "BuyButtonRoot",
109
+ "children": ["buy-button-action"]
110
+ },
111
+ "buy-button-action": {
112
+ "type": "BuyButtonButton",
113
+ "props": { "availableLabel": "Comprar", "unavailableLabel": "Indisponível" }
114
+ }
115
+ }
116
+ ```
117
+
118
+ ---
119
+
120
+ ## Common mistakes
121
+
122
+ - **Inventing `BuyButton` (without Root).** There is no standalone `BuyButton` component. The entry point is `BuyButtonRoot` and the button itself is `BuyButtonButton`.
123
+ - **Adding `CartRoot` to the page for the buy button.** Add-to-cart is context-free — it does not need a cart provider. The layout already hosts `CartRoot` for cart reads; never add one to a PDP schema just to enable the buy button.
124
+ - **Passing a `disabled` prop to control availability.** Availability is handled automatically from the variant's `availableForSale` flag — do not set `disabled` manually.
125
+
126
+ ---
127
+
128
+ ## Styling
129
+
130
+ Fill each element's `style` array with Tailwind classes read off the image. Typical patterns:
131
+
132
+ | Component | What you style | Plausible classes |
133
+ |---|---|---|
134
+ | `BuyButtonRoot` | Layout wrapper only — it renders no box of its own | `block w-full mt-[8px]` |
135
+ | `BuyButtonButton` | The CTA: full-width pill in the brand color, with hover and disabled states | `inline-flex items-center justify-center w-full h-[44px] px-[20px] bg-[#C8102E] text-white rounded-[4px] text-[14px] font-bold uppercase cursor-pointer transition-colors hover:bg-[#A50D26] disabled:opacity-50 disabled:cursor-not-allowed` |
136
+
137
+ Read the button's fill color straight off the image as an arbitrary hex (`bg-[#C8102E]`); derive the hover shade as a slightly darker value. Always include `disabled:` styling — the button auto-disables when the variant is unavailable. Do not invent a swatch or token for the brand color; inline hex only.
138
+
139
+ Styled example:
140
+
141
+ ```json
142
+ {
143
+ "buy-button": {
144
+ "type": "BuyButtonRoot",
145
+ "children": ["buy-button-action"],
146
+ "style": ["block", "w-full", "mt-[8px]"]
147
+ },
148
+ "buy-button-action": {
149
+ "type": "BuyButtonButton",
150
+ "props": { "availableLabel": "Comprar", "unavailableLabel": "Indisponível" },
151
+ "style": ["inline-flex", "items-center", "justify-center", "w-full", "h-[44px]", "px-[20px]", "bg-[#C8102E]", "text-white", "rounded-[4px]", "text-[14px]", "font-bold", "tracking-[0.06em]", "uppercase", "cursor-pointer", "transition-colors", "duration-150", "hover:bg-[#A50D26]", "active:bg-[#8A0B20]", "disabled:opacity-50", "disabled:cursor-not-allowed"]
152
+ }
153
+ }
154
+ ```
155
+
156
+ ---
157
+
158
+ ## Related
159
+
160
+ - [[cart]] — cart read provider (`CartRoot`) and line-item particles; the buy button shares the cart via the cache, not via this provider.
161
+ - [[pricing]] — price block that sits alongside the buy button on a PDP.
162
+ - [[product-information]] — title and description block on the same PDP.
@@ -0,0 +1,105 @@
1
+ # Carousel
2
+
3
+ **Category:** layout
4
+ **Purpose:** Generic horizontal carousel. Arranges arbitrary children into a navigable, paged track with previous/next arrows and pagination bullets. Holds no product, media, or GraphQL data — it is pure layout, reusable anywhere a set of children needs a navigable track (e.g. a product shelf).
5
+
6
+ ---
7
+
8
+ ## When to use
9
+
10
+ - Any horizontally-paged track of arbitrary children: product cards, banners, testimonials, thumbnails.
11
+ - When you need infinite looping, native-scroll vs. transform-slide movement, and composable controls.
12
+
13
+ ## When NOT to use
14
+
15
+ - Product media on a PDP → use `ProductGalleryRoot`. For a non-PDP media array → use `GalleryRoot`. `Gallery` is media-typed (image/video, zoom, fullscreen); `Carousel` arranges any children and knows nothing about their content.
16
+
17
+ ---
18
+
19
+ ## Behavior model
20
+
21
+ - **Paging is derived from children.** `CarouselTrack` counts its children; `totalPages = ceil(itemCount / itemsPerPage)`. There is no `itemCount` prop.
22
+ - **Controls are composed parts, not an enum.** Place `CarouselPrevious` / `CarouselNext` / `CarouselBullets` to get "arrows only", "bullets only", or "complete". Omit what you don't want.
23
+ - **`infiniteMode`** wraps navigation seamlessly and never disables the arrows. With it off, the arrow at the reached end is `disabled`.
24
+ - **`variant`** — `slide` moves the track with a `translateX` transform; `scroll` uses native overflow scrolling with scroll-snap.
25
+
26
+ ---
27
+
28
+ ## Props
29
+
30
+ ### CarouselRoot
31
+
32
+ | Prop | Type | Default | Notes |
33
+ |------|------|---------|-------|
34
+ | `infiniteMode` | boolean | `false` | Loop seamlessly; arrows never disable |
35
+ | `variant` | `'slide' \| 'scroll'` | `'slide'` | Transform slide vs. native overflow scroll |
36
+ | `itemsPerPage` | number | `1` | How many children are visible per page |
37
+ | `defaultPage` | number | `0` | Page selected on first render |
38
+ | `label` | string | `'Carousel'` | `aria-label` for the carousel region |
39
+
40
+ ### CarouselTrack
41
+
42
+ Lays out and counts the children. No props beyond standard `div` attributes. Place the items (e.g. product cards) directly inside.
43
+
44
+ ### CarouselPrevious / CarouselNext
45
+
46
+ Buttons that move one page. No props beyond standard `button` attributes; accept any children (Icon, text). Disabled at the respective end when `infiniteMode` is off.
47
+
48
+ ### CarouselBullets
49
+
50
+ | Prop | Type | Default | Notes |
51
+ |------|------|---------|-------|
52
+ | `ariaLabel` | string | `'Choose page'` | Label for the bullets group |
53
+ | `bulletLabel` | string | `'Go to page {page}'` | Per-bullet label; `{page}` is the 1-based page number |
54
+ | `hideWhenSingle` | boolean | `true` | Render nothing when there is a single page |
55
+
56
+ Bullets support `ArrowLeft` / `ArrowRight` / `Home` / `End` keyboard navigation and mark the active page with `data-fs-carousel-bullet-selected="true"` and `aria-current`.
57
+
58
+ ---
59
+
60
+ ## Composition
61
+
62
+ ```text
63
+ CarouselRoot
64
+ ├── CarouselTrack
65
+ │ ├── <item 1>
66
+ │ ├── <item 2>
67
+ │ └── …
68
+ ├── CarouselPrevious
69
+ ├── CarouselNext
70
+ └── CarouselBullets
71
+ ```
72
+
73
+ Every part must be inside `CarouselRoot`. `useCarousel()` throws if used outside it.
74
+
75
+ ---
76
+
77
+ ## Minimal schema example
78
+
79
+ ```json
80
+ {
81
+ "carousel": {
82
+ "type": "CarouselRoot",
83
+ "props": { "infiniteMode": false, "variant": "slide", "itemsPerPage": 4 },
84
+ "children": ["carousel-track", "carousel-prev", "carousel-next", "carousel-bullets"]
85
+ },
86
+ "carousel-track": {
87
+ "type": "CarouselTrack",
88
+ "children": ["card"]
89
+ },
90
+ "carousel-prev": { "type": "CarouselPrevious", "children": ["icon-chevron-left"] },
91
+ "carousel-next": { "type": "CarouselNext", "children": ["icon-chevron-right"] },
92
+ "carousel-bullets": { "type": "CarouselBullets" }
93
+ }
94
+ ```
95
+
96
+ ---
97
+
98
+ ## Styling
99
+
100
+ Functional layout (flex track, `translateX`, overflow, scroll-snap) is built in. All appearance is chosen by swatches keyed off the `data-fs-carousel-*` hooks:
101
+
102
+ - `data-fs-carousel` / `data-fs-carousel-variant`
103
+ - `data-fs-carousel-track` / `data-fs-carousel-viewport` / `data-fs-carousel-item`
104
+ - `data-fs-carousel-previous` / `data-fs-carousel-next` (native `disabled` at ends)
105
+ - `data-fs-carousel-bullets` / `data-fs-carousel-bullet` / `data-fs-carousel-bullet-selected`
@@ -0,0 +1,162 @@
1
+ # CartItem
2
+
3
+ **Category:** commerce
4
+ **Purpose:** The reusable cart **line-item template** — the unit both the mini-cart and the checkout compose once per cart line. `CartItemRoot` owns the per-line core data and delivers each line its own slice; the `CartItem*` particles render fields of that slice.
5
+
6
+ This matter is delivered on ADR-0012 **Option B**: `CartItemRoot` (`fetchStrategy: 'reactive-list-item'`) owns the core-scalar fragment and subscribes per line to `CartItem:<id>` in the normalized cache, so a per-line change re-renders only that line. `CartRoot` (the cart read root, in the layout) provides only item refs.
7
+
8
+ ---
9
+
10
+ ## Visual cues (how to identify in an image)
11
+
12
+ A **cart line** — a repeated row in a cart or mini-cart list: a product thumbnail, name, price, a quantity stepper, a remove control, one row per item. Each such row is one `CartItemRoot` wrapping the row's particles.
13
+
14
+ ---
15
+
16
+ ## Composition
17
+
18
+ **`CartItemRoot` wraps the line-item template inside `CartList`.** The nesting is always:
19
+
20
+ ```text
21
+ CartList (iterator — renders its children once per cart line)
22
+ └─ CartItemRoot (per-line data provider — owns the core slice)
23
+ ├─ CartItemImage (optionally wrapped in CartItemProductLink; see below)
24
+ ├─ CartItemName
25
+ ├─ CartItemPrice / CartItemListPrice / CartItemDiscountPercentage
26
+ ├─ CartItemQuantity (stepper) / CartItemQuantityValue
27
+ ├─ CartItemLineTotal
28
+ ├─ CartItemOwnTotal / CartItemAggregateTotal
29
+ ├─ CartItemRemove
30
+ ├─ CartItemAvailable / CartItemUnavailable
31
+ ├─ CartItemGift (free marker; renders only on a gift line)
32
+ ├─ CartItemSellerInfo (optional per-line owner; see below)
33
+ ├─ CartItemDiscounts (optional per-line owner; see below)
34
+ ├─ CartItemCustomizations (optional per-line owner; see below)
35
+ ├─ CartItemCompositions (optional per-line owner; see below)
36
+ └─ CartItemVariations (optional per-line owner; see below)
37
+ ```
38
+
39
+ - **`CartItemRoot` is required.** Every `CartItem*` core particle reads its data from the nearest `CartItemRoot` (build-time `requiresContext: 'cart-item-data'`). Placing a core particle directly inside `CartList` with no `CartItemRoot` between them is a build error. When authoring a cart or mini-cart line template, always insert a `CartItemRoot` between the `CartList` and the row's particles — it carries no visible styling of its own, so put the row layout classes on it (or on a `Container` inside it).
40
+ - **`CartItemRoot` must be inside `CartList`.** It requires the `cart-item` iteration context that `CartList` provides.
41
+
42
+ ## PDP link composition
43
+
44
+ `CartItemProductLink` links a line to its product page. It reads the `product.detailUrl` the core slice already carries, so it owns no fragment and placing it adds nothing to the page query. Wrap the image in it:
45
+
46
+ ```text
47
+ CartItemRoot
48
+ └─ CartItemProductLink (anchor to this line's product page)
49
+ └─ CartItemImage (unchanged — its alt text names the link)
50
+ ```
51
+
52
+ **Placing it is the switch.** There is no prop to turn the link on or off: a mini-cart line composes it, a checkout line omits it. That is why `CartItemImage` on its own still renders a plain `<img>` with no anchor, exactly as before.
53
+
54
+ **It names itself from what it wraps.** The link adds no `aria-label`, so its accessible name is the image's alt text (`image.altText ?? variant.name`). On a line whose `variant.image` is `null` the leaf renders its children unwrapped instead of wrapping nothing, because an anchor with no content is a keyboard focus stop with no accessible name.
55
+
56
+ **No usable product URL, no link.** The leaf runs `detailUrl` through `resolveSafeHref`, the same allowlist the navigation particle applies to CMS-authored destinations, and renders its children unwrapped when the destination is blank or refused: `javascript:`, `data:`, protocol-relative, or malformed. The particle gates only `$content.href`, so a platform URL arriving on the `href` prop is this leaf's to validate. Either way the image still shows: the leaf never self-hides, unlike the data-bearing leaves below, because hiding a wrapper would take its content with it. A refusal logs its reason and never the value; a blank URL is ordinary and stays quiet.
57
+
58
+ Navigation is client-side through the `NavigationLink` particle, which also owns `rel` hardening. The link is same-tab, and `target` is omitted from the props type rather than merely left out of the schema, because an image-only link cannot carry the "(opens in new tab)" cue a `_blank` destination needs.
59
+
60
+ **Known gap:** a mini-cart drawer does **not** dismiss itself when a client-side navigation leaves it, so the overlay stays open over the product page. This is not specific to this leaf — `CartGoCheckout` behaves the same way — and it belongs to the drawer composition, not to a line leaf.
61
+
62
+ Renders `a[data-fs-cart-item-product-link]`, which also carries the particle's `data-fs-navigation-link`.
63
+
64
+ ## Remove-on-alert composition
65
+
66
+ `CartItemUnavailable` renders its children, so a `CartItemRemove` placed inside it gives the unavailable alert its own remove control — no new component, both require the same `cart-item-data` context under `CartItemRoot`:
67
+
68
+ ```text
69
+ CartItemRoot
70
+ └─ CartItemUnavailable (renders only when the line is NOT available)
71
+ ├─ Text "Out of stock" (explicit label — see the nuance below)
72
+ └─ CartItemRemove (removes this line from within its alert)
73
+ ```
74
+
75
+ **Label-vs-children nuance:** passing children to `CartItemUnavailable` **replaces** its built-in state label (`children ?? unavailableLabel(availability)`). A remove-on-alert composition therefore renders the label as an explicit child (e.g. a `Text`) next to the `CartItemRemove`; nesting the remove control alone leaves the alert without a label. The whole subtree is availability-gated: when the line is `AVAILABLE`, neither the label nor the nested remove control renders.
76
+
77
+ For the cart-level counterparts (the "N items unavailable" summary and the bulk "remove all unavailable" button), see `cart.md` — Unavailable-item recovery.
78
+
79
+ ## Gift lines
80
+
81
+ A promotion can add a line the shopper never chose. `CartItem.gift` marks it, and three things follow from that one flag — none of them requiring a different template, because `CartList` renders the same children for every row:
82
+
83
+ ```text
84
+ CartItemRoot (row carries data-fs-cart-item-gift-line on a gift line)
85
+ ├─ CartItemListPrice (renders: a gift's sellingPrice is 0, so listPrice > sellingPrice)
86
+ ├─ CartItemGift (renders "Free")
87
+ └─ CartItemRemove (renders nothing)
88
+ ```
89
+
90
+ - **`CartItemGift`** is the free marker: a `span[data-fs-cart-item-gift][data-fs-text]` that renders **only** on a gift line, with the built-in English label `Free`. Passing children **replaces** the label (`children ?? 'Free'`), the same nuance `CartItemUnavailable` has. It is an **inline marker, not a wrapper** — its children are the label, so do not nest a block subtree in it. Place it beside `CartItemPrice`/`CartItemListPrice`.
91
+ - **`CartItemRemove` suppresses itself** on a gift line. A gift is not the shopper's to discard in this phase, and since one template serves every row, the rule lives in the component rather than in the composition. This covers the remove-on-alert composition too: an unavailable gift renders its alert with no remove control, and recovery is the cart-level `CartRemoveUnavailable` batch (which still batches gift lines) plus server-side cart validation.
92
+ - **`CartItemQuantity` suppresses itself** on a gift line too, the same way `CartItemRemove` does: a gift's quantity is promotion-controlled, and a `removeOnDecrement` stepper would otherwise let a shopper discard the gift by stepping it below the minimum — the one path the remove-control suppression did not cover. A store showing a gift's fixed quantity composes the read-only `CartItemQuantityValue`, which dispatches nothing.
93
+ - **The row is marked** with `data-fs-cart-item-gift-line`, so a swatch can restyle a gift row without a component per variation — that is how a store hides the `R$ 0,00` selling price on a gift row.
94
+
95
+ A gift whose `listPrice` is also 0 renders no list price (`CartItemListPrice`'s existing `listPrice <= sellingPrice` rule) and the marker carries the row alone.
96
+
97
+ ## Owned data
98
+
99
+ `CartItemRoot`'s core fragment owns each line's `id`, `quantity`, `price`/`listPrice`/`sellingPrice`, `gift`, `ownTotal`/`total`, `variant { variantId, sku, name, image, availability }`, and the `product` core. `variant.availability` stays here (not a sub-matter) because it is read cross-cuttingly: `CartItemAvailable`/`CartItemUnavailable` gate on it, and `CartCheckoutGuard` reads it across all lines. `gift` stays here for the same reason — `CartItemGift`, `CartItemRemove`'s suppression, and the row's state hook all read it.
100
+
101
+ Every per-line field this fragment selects must also be selected by the **mutation** fragment (`CartItemFragment` in `sdk/cart/operations.ts`). The per-line subscriber resolves `complete ? data : fallbackData`, and the fallback is the cart-level slice, which carries no product or prices — so a field selected here but not there makes every row incomplete after a cart write. Two tests in `cart-item.test.tsx` guard it.
102
+
103
+ ### CartItemOwnTotal and CartItemAggregateTotal
104
+
105
+ Two core-slice leaves render the line total, siblings to `CartItemLineTotal`:
106
+
107
+ - **`CartItemOwnTotal`** renders `ownTotal` — the line's **own** total (own unit selling price × quantity, rounding-exact), **excluding** composition children.
108
+ - **`CartItemAggregateTotal`** renders `total` — the line's **aggregate** total, **including** all nested composition children recursively. On a bundled line this is the price the shopper actually pays.
109
+
110
+ `total == ownTotal` on any line with no compositions, so either leaf is safe to place unconditionally: a plain line renders the same value from both. Both `Number()`-coerce the string `Money.amount` before formatting from the active storefront context, emit `data-fs-cart-item-own-total` / `data-fs-cart-item-aggregate-total` (both with `data-fs-text`), and accept a `children` override. `CartItemLineTotal` (`sellingPrice × quantity`, the line's own total) is unchanged and independent — the `Own`/`Aggregate` naming is deliberately self-documenting.
111
+
112
+ ## CartItemQuantity and the unit multiplier
113
+
114
+ The stepper shows the line's quantity **in the unit the merchant sells in**, not the raw purchasable count. The order form counts purchasable units, so a SKU sold in 500 g portions carries `unitMultiplier: 0.5` and a shopper holding 1.5 kg has `quantity: 3` — the stepper reads `1.5`. A six-pack SKU (`unitMultiplier: 6`) at `quantity: 2` reads `12`. The multiplier is read from the line, never configured: `1` is the identity, so a SKU sold by the unit behaves exactly as before.
115
+
116
+ `unitMultiplier` is **optional per-line data owned by `CartItemQuantity`'s own fragment** (ADR-0011), not by `CartItemRoot`'s core slice, so a cart or checkout line that shows only the read-only `CartItemQuantityValue` never fetches it. The stepper still reads `id` and `quantity` from the core slice, which is why it keeps requiring `cart-item-data` and must stay inside `CartItemRoot`.
117
+
118
+ **`min`, `max`, and `step` are authored in purchasable units** and converted for display by the component. `min: 1, max: 10` on a 0.5-multiplier line yields a reachable range of `0.5` to `5` in steps of `0.5`. That is deliberate: one line template renders SKUs with different multipliers, so bounds expressed in purchasable units keep meaning the same thing across every line and need no re-authoring when a SKU's packaging changes. A merchant wanting a 500 g floor writes `min: 1`, not `min: 0.5`.
119
+
120
+ Enforcement happens **on commit** — blur after typing, pointer release on the buttons, or a keyboard interaction — not per keystroke. A committed amount that is out of bounds or off the multiplier grid is clamped and snapped to the nearest valid amount (ties round up), then the remaining delta is dispatched as `increaseQuantity` / `decreaseQuantity` in purchasable units. No non-integer quantity can reach a mutation. Nothing is corrected at render time: a quantity already outside the authored bounds is displayed as-is and fires no write.
121
+
122
+ A snap renders a notice as the last child of the stepper: `div[role="alert"][data-fs-cart-item-quantity-validation]`, carrying the `validationMessage` prop, whose `{value}` placeholder is replaced with the corrected displayed amount (default `Quantity adjusted to {value}.`). The root also carries `data-fs-cart-item-quantity-adjusted` plus `data-fs-cart-item-quantity-adjusted-reason="min" | "max" | "multiple"` for per-reason styling, and `data-fs-cart-item-quantity-multiplier="<value>"` whenever the multiplier is not `1`, so a measured line can be styled differently from a counted one.
123
+
124
+ `removeOnDecrement`: a committed amount below the configured minimum removes the line instead of clamping, and no notice is raised. In that mode the decrement control is **not** disabled at the minimum — removal is the intended outcome there — and `data-fs-cart-item-at-min` still keys off the purchasable count. This never applies to a gift line: the stepper renders nothing there, so `removeOnDecrement` cannot discard a gift.
125
+
126
+ The measurement unit itself (`kg`, `un`) is not fetched, so a measured line renders `1.5` with no suffix.
127
+
128
+ ## Optional per-line owners
129
+
130
+ `CartItemSellerInfo` is an **optional** per-line data owner: it owns `variant.seller.name` via its own `reactive-list-item` fragment and requires only `cart-item` (so it sits inside `CartList`, alongside or within `CartItemRoot`). Its seller subtree is fetched **only** on pages that place it — stores that omit it never over-fetch `variant.seller`.
131
+
132
+ ### CartItemDiscounts
133
+
134
+ `CartItemDiscounts` is another **optional** per-line data owner: it owns the line's `discounts` subtree via its own `reactive-list-item` fragment and requires only `cart-item`, so its data is fetched **only** on pages that place it. It renders one labeled row per featured promotion applied to the current cart line — the promotion `name` plus its amount (e.g. `Black Friday −R$ 20,00`, `Cupom −10%`) — so a shopper sees *which* promotion took *how much* off *this* item. It is the itemized companion to the aggregated `Discounts` totalizer line in the footer.
135
+
136
+ Each row branches on `isPercentual`: a currency discount (`false`) formats the amount from the active storefront context; a percentual discount (`true`) renders `−N%` and is **not** currency-formatted. Every amount carries a presentational leading `−` — the source `value` is a positive amount. It **renders null when the line has no discounts** (empty or unresolved), so it appears only where a promotion actually fired. Place it under the line, near the price area. Must be inside `CartList`.
137
+
138
+ **Distinct from `CartItemDiscountPercentage`.** `CartItemDiscountPercentage` is a single derived `−N%` **badge** computed from `listPrice`/`sellingPrice` with **no** promotion name; `CartItemDiscounts` is the **named list** of promotions sourced from the line's `discounts` field. They cover different concerns and may coexist on a line — the badge next to the price, the named list beneath it.
139
+
140
+ Renders a `div[data-fs-cart-item-discounts]` container with one `span[data-fs-cart-item-discount]` per discount; each row wraps a `span[data-fs-cart-item-discount-name]` (the promotion name) and a `span[data-fs-cart-item-discount-value]` (the amount). No props beyond the standard `div` attributes; the list is data-driven and `children` is not used to override it.
141
+
142
+ ### CartItemCustomizations
143
+
144
+ `CartItemCustomizations` is an **optional** per-line data owner: it owns the line's `customizations` subtree via its own `reactive-list-item` fragment and requires only `cart-item`, so its data is fetched **only** on pages that place it. It renders the form-based personalization a shopper applied to the line — engraving text, a size selection, an uploaded file's URL — as one group per assembly, each group listing its `entries` as `name` / `value` rows (e.g. `Text: MARIA`). It **renders null when the line has no customizations** (empty or unresolved). Must be inside `CartList`.
145
+
146
+ The group heading is the raw assembly `id` (e.g. `Engraving`); pretty display names are deferred (836 Decision 2). An uploaded-file value surfaces as its URL string and is rendered verbatim — there is no file-preview/download widget in v0 (836 exposes no file metadata; at parity with fastcheckout).
147
+
148
+ Renders a `div[data-fs-cart-item-customizations]` container with one `div[data-fs-cart-item-customization]` per group (carrying `data-fs-cart-item-customization-id` for per-group styling); each entry is a `span[data-fs-cart-item-customization-entry]` wrapping a `span[data-fs-cart-item-customization-name]` and a `span[data-fs-cart-item-customization-value]`. The list is data-driven; `children` is not used to override it.
149
+
150
+ ### CartItemCompositions
151
+
152
+ `CartItemCompositions` is an **optional** per-line data owner: it owns the line's `compositions` subtree via its own `reactive-list-item` fragment and requires only `cart-item`, so its data is fetched **only** on pages that place it. It renders the nested bundle/assembly tree a shopper built under the line — each child row shows the child's `name`, `quantity` (`×N`), and formatted unit `price`. It **renders null when the line has no compositions** (empty or unresolved). Must be inside `CartList`.
153
+
154
+ **Recursion.** A composition child is itself an order-form line, so it can carry its own nested `compositions` (a sub-bundle) and its own `customizations` (836 Decision 8). The matter recurses over the in-slice `compositions` array with an internal render function: each node renders its row, its own customization groups (using the same `name`/`value` anatomy as `CartItemCustomizations`, so one swatch styles both), then its nested children at `depth + 1`. Recursion is over finite data — the server guarantees acyclic compositions (836 visited-index) and depth is bounded by the assembly config. React keys use the node `id`.
155
+
156
+ Renders a `div[data-fs-cart-item-compositions]` container with one `div[data-fs-cart-item-composition]` per child; each child carries `data-fs-cart-item-composition-depth="N"` (the indent hook for nesting) and wraps `span[data-fs-cart-item-composition-name]`, `span[data-fs-cart-item-composition-quantity]`, `span[data-fs-cart-item-composition-price]`, then any customization groups, then its nested children. The tree is data-driven; `children` is not used to override it.
157
+
158
+ ### CartItemVariations
159
+
160
+ `CartItemVariations` is another **optional** per-line data owner: it owns the line's `variant.selectedOptions` subtree via its own `reactive-list-item` fragment and requires only `cart-item`, so its data is fetched **only** on pages that place it. It renders one labeled row per variation selected on the current cart line (e.g. `Cor: Vermelho`, `Tamanho: M`), so a shopper can tell two lines of the same product apart. It **renders null when the line has no selected options** (empty or unresolved), so it appears only where the SKU actually has variations. Place it near the product name. Must be inside `CartList`.
161
+
162
+ Renders a `div[data-fs-cart-item-variations]` container with one `span[data-fs-cart-item-variation]` per option; each row wraps a `span[data-fs-cart-item-variation-name]` (e.g. `Cor`), a `span[data-fs-cart-item-variation-separator]` holding the `": "` delimiter, and a `span[data-fs-cart-item-variation-value]` (e.g. `Vermelho`). The separator is a hook of its own so a store can restyle or hide the delimiter without the punctuation riding along with the label; with no swatch applied a row still reads `Cor: Vermelho`. No props beyond the standard `div` attributes; the list is data-driven and `children` is not used to override it.
@@ -0,0 +1,197 @@
1
+ # CartTotalizer
2
+
3
+ **Category:** commerce
4
+ **Purpose:** Focused reactive data provider for cart totalizers and grand total. Fetches only the `totalizers` and `total` fields — a narrower slice than `CartRoot`. Use it to compose an **order summary** — the subtotal / discount / shipping / total breakdown — in either a **mini-cart drawer footer** (alongside the layout `CartRoot`) or a **checkout summary panel** (standalone). Use it on summary-only pages where it is the sole reactive data root, or alongside `CartRoot` when the page already hosts the full cart context.
5
+
6
+ ---
7
+
8
+ ## Visual cues (how to identify in an image)
9
+
10
+ Look for an **order summary** listing individual cost lines (subtotal, discounts, shipping) and a grand total, typically with a checkout CTA below. Examples:
11
+
12
+ - A card labeled "Order Summary" or "Resumo do Pedido" with line-by-line cost breakdown.
13
+ - A sidebar showing subtotal + discount + shipping + total, separated from the cart item list.
14
+ - The **footer of a mini-cart drawer**, below the item list: a subtotal row, an optional discount row, a shipping row, and a bold grand-total row, above the checkout button.
15
+
16
+ ---
17
+
18
+ ## When to use
19
+
20
+ - In a **mini-cart drawer footer** — the layout root is a `CartRoot` wrapping the drawer (item list + footer), and the footer composes a `CartTotalizerRoot` subtree for the order summary. Both roots select the same top-level `cart {}` field, so the compiler merges them into one query and the runtime issues one fetch. This is the mini-cart order-summary pattern; the americanas `default.json` footer uses it.
21
+ - On a **summary-only page** (no cart item list) — `CartTotalizerRoot` wraps the summary card and acts as the sole reactive data root. The checkout page currently uses this pattern.
22
+ - **Alongside `CartRoot`** on the same page — the compiler merges both components' fragments into one query (same `cart {}` field, no double fetch). Use this when the page already needs full cart context and you want to add a separate summary widget.
23
+
24
+ ## When NOT to use
25
+
26
+ - As a replacement for `CartRoot` when the page also renders `CartList`, `CartCount`, or other `useCart()`-dependent components — those require `CartRoot`.
27
+ - Nested inside `CartRoot` as a redundant provider — the contexts compose automatically when both are on the same page; no explicit nesting is needed.
28
+
29
+ > **Note (americanas checkout layout):** The current `checkout` layout hosts no `CartRoot` — it is intentionally bare. The checkout page uses `CartTotalizerRoot` standalone. When a future checkout step needs full cart mutations, the layout (or page) should add `CartRoot`.
30
+
31
+ ---
32
+
33
+ ## Composition
34
+
35
+ ```
36
+ CartTotalizerRoot ← reactive data provider (totalizers + total)
37
+ ├── CartTotalizerLine ← one cost row, selected by totalizerId
38
+ │ totalizerId="Items"
39
+ ├── CartTotalizerLine
40
+ │ totalizerId="Discounts" variant="discount" ← hides when amount = 0
41
+ ├── CartTotalizerLine
42
+ │ totalizerId="Shipping" zeroLabel="Free"
43
+ ├── <hr /> / Separator
44
+ └── CartTotal label="Total" ← root-agnostic grand total (set label for a labeled total row)
45
+ ```
46
+
47
+ ### Key particles
48
+
49
+ | Component | Props | Notes |
50
+ |---|---|---|
51
+ | `CartTotalizerRoot` | `$data` | Provides `CartTotalizerContext` and `CartTotalValueContext`; lines format from the active storefront context |
52
+ | `CartTotalizerLine` | `totalizerId`, `label?`, `variant?`, `zeroLabel?` | `variant="discount"` auto-hides when `amount === 0` |
53
+ | `CartDiscountLine` | `otherLabel?` | Itemized discount breakdown: one line per promotion/coupon plus the residual. Self-hides when empty. Owns its own `Cart.discounts` slice |
54
+ | `CartMarkdownLine` | `label?` | Aggregate item-level catalog markdown (`Σ listPrice − price`): a single negative line, self-hides at zero. Distinct money from the `Discounts` totalizer / `CartDiscountLine` — may be shown alongside them. Owns its own `Cart.itemMarkdownTotal` slice |
55
+ | `CartTotal` | `label?` | The single root-agnostic grand total; reads `CartTotalValueContext` provided by either root. Set `label` to render a labeled total row (e.g. "Total") |
56
+
57
+ ---
58
+
59
+ ## CartDiscountLine — itemized discounts (F11)
60
+
61
+ `CartDiscountLine` renders the cart's discounts as **one labeled line per promotion and coupon**, plus a
62
+ residual line for anything they do not account for. It reads `Cart.discounts` (each entry a `name`, a
63
+ positive `value`, and a `kind` of `PROMOTION | COUPON | OTHER`) and renders each amount as a negative
64
+ value formatted in the store's currency. It renders nothing when the cart has no discounts.
65
+
66
+ It owns its own cart slice: the `Cart.discounts` selection is fetched only when this leaf is placed and
67
+ merges with the `CartTotalizerRoot` / `CartRoot` cart query into one fetch. Place it in the order
68
+ summary, typically inside `CartTotalizerRoot` for the cart slice; money formats from the active
69
+ storefront context wherever it renders.
70
+
71
+ **Itemized versus aggregate — choose one.** The itemized entries are the companion to the aggregate
72
+ `Discounts` totalizer and sum to it, so compose **either** `CartDiscountLine` **or**
73
+ `CartTotalizerLine totalizerId="Discounts"`, never both — showing both double-counts the same money. Use
74
+ `CartDiscountLine` when the summary should name each promotion and coupon; use the aggregate line when a
75
+ single "Discounts" figure is enough.
76
+
77
+ The `name` a promotion or coupon carries comes from the platform; the API leaves the residual (and any
78
+ unnamed promotion) without a name, so `otherLabel` supplies the label for those (default
79
+ `"Other discounts"`, override per store).
80
+
81
+ Style hooks: `data-fs-cart-discount-lines` on the group, and per row
82
+ `data-fs-cart-discount-line` (with `data-fs-cart-discount-line-kind` = `promotion` / `coupon` / `other`),
83
+ `data-fs-cart-discount-line-label`, and `data-fs-cart-discount-line-value`.
84
+
85
+ ```json
86
+ {
87
+ "type": "CartTotalizerRoot",
88
+ "children": [
89
+ { "type": "CartTotalizerLine", "props": { "totalizerId": "Items" } },
90
+ { "type": "CartDiscountLine", "props": { "otherLabel": "Other discounts" } },
91
+ { "type": "CartTotalizerLine", "props": { "totalizerId": "Shipping", "zeroLabel": "Free" } },
92
+ { "type": "CartTotal", "props": { "label": "Total" } }
93
+ ]
94
+ }
95
+ ```
96
+
97
+ ---
98
+
99
+ ## CartMarkdownLine — item-level catalog markdown (F11 scenario 1)
100
+
101
+ `CartMarkdownLine` renders the cart's **aggregate item-level catalog markdown** — the sum of
102
+ `(listPrice − price) × quantity` across non-gift lines — as a single negative summary line. This is the
103
+ "de/por" savings baked into the catalog price, computed server-side and exposed as `Cart.itemMarkdownTotal`;
104
+ the component reads that one `Money` field, negates it so the currency format supplies the sign, and renders
105
+ nothing when it is zero.
106
+
107
+ It owns its own cart slice: `Cart.itemMarkdownTotal` is fetched only when this leaf is placed and merges with
108
+ the `CartTotalizerRoot` / `CartRoot` cart query into one fetch. Place it in the order summary, typically inside
109
+ `CartTotalizerRoot` for the cart slice; money formats from the active storefront context wherever it renders.
110
+
111
+ **Distinct money — coexists with the discount line.** Item markdown is `listPrice − price`, the reduction from
112
+ list *down to* the "Items" subtotal; the `Discounts` totalizer and `CartDiscountLine` are `price − sellingPrice`,
113
+ the cart-level promotions and coupons *below* the subtotal. They are different money, so — unlike the
114
+ itemized-versus-aggregate choice for `CartDiscountLine` — you compose `CartMarkdownLine` **alongside** the
115
+ discount line, not instead of it. It is never part of `totalizers` and never summed into `total`; it is an
116
+ informational savings line.
117
+
118
+ **Presentation — give the reduction a referent.** Because the `Items` subtotal already reflects the
119
+ markdown, a bare `−R$ 36,00` row dropped into the running column does not foot (`Items − markdown −
120
+ Discounts ≠ total`) and reads as an error. Compose it so the reduction reconciles something visible:
121
+ either render a **"List price" row** (the pre-markdown `Σ listPrice × qty` — a derived display value no
122
+ totalizer carries) immediately above it, so `list − markdown = Items subtotal` and the column foots
123
+ (`346 − 36 = 310`, then `310 − 40 = 270`); or present it as a **distinct "you saved" note** set apart
124
+ from the running total. What you must not do is interleave it as a plain negative line between the
125
+ subtotal and the total, because it is not part of that sum. The `ItemMarkdown` story shows the
126
+ list-price framing.
127
+
128
+ The `label` prop words the row (default `"Item discounts"`, override per store).
129
+
130
+ Style hooks: `data-fs-cart-markdown-line` on the row (also `data-fs-text`), with
131
+ `data-fs-cart-markdown-line-label` and `data-fs-cart-markdown-line-value`.
132
+
133
+ Per the reconciliation rule above, this example places `CartMarkdownLine` **after** `CartTotal` — an
134
+ informational savings note set apart from the running total, not a line between the subtotal and the
135
+ total (the markdown is already reflected in `Items`).
136
+
137
+ ```json
138
+ {
139
+ "type": "CartTotalizerRoot",
140
+ "children": [
141
+ { "type": "CartTotalizerLine", "props": { "totalizerId": "Items", "label": "Items subtotal" } },
142
+ { "type": "CartDiscountLine", "props": { "otherLabel": "Other discounts" } },
143
+ { "type": "CartTotalizerLine", "props": { "totalizerId": "Shipping", "zeroLabel": "Free" } },
144
+ { "type": "CartTotal", "props": { "label": "Total" } },
145
+ { "type": "CartMarkdownLine", "props": { "label": "Savings off list price" } }
146
+ ]
147
+ }
148
+ ```
149
+
150
+ ---
151
+
152
+ ## Schema
153
+
154
+ ```json
155
+ {
156
+ "type": "CartTotalizerRoot",
157
+ "children": [
158
+ { "type": "CartTotalizerLine", "props": { "totalizerId": "Items" } },
159
+ { "type": "CartTotalizerLine", "props": { "totalizerId": "Discounts", "variant": "discount" } },
160
+ { "type": "CartTotalizerLine", "props": { "totalizerId": "Shipping", "zeroLabel": "Free" } },
161
+ { "type": "CartTotal" }
162
+ ]
163
+ }
164
+ ```
165
+
166
+ ### Mini-cart drawer footer
167
+
168
+ In a mini-cart, the layout root is a `CartRoot` wrapping the drawer (item list + footer). The footer composes a `CartTotalizerRoot` subtree as the order summary — the two roots select the same top-level `cart {}` field, so the compiler merges them into one query (no double fetch). Render the grand total with `CartTotal label="Total"`; there is no `CartTotalizerTotal`. A divider above the total is purely visual — style it, do not model it as a structural node.
169
+
170
+ ```json
171
+ {
172
+ "footer-summary": {
173
+ "type": "CartTotalizerRoot",
174
+ "children": ["summary-subtotal", "summary-discount", "summary-shipping", "summary-total"]
175
+ },
176
+ "summary-subtotal": {
177
+ "type": "CartTotalizerLine",
178
+ "props": { "totalizerId": "Items" },
179
+ "children": []
180
+ },
181
+ "summary-discount": {
182
+ "type": "CartTotalizerLine",
183
+ "props": { "totalizerId": "Discounts", "variant": "discount" },
184
+ "children": []
185
+ },
186
+ "summary-shipping": {
187
+ "type": "CartTotalizerLine",
188
+ "props": { "totalizerId": "Shipping", "zeroLabel": "Free" },
189
+ "children": []
190
+ },
191
+ "summary-total": {
192
+ "type": "CartTotal",
193
+ "props": { "label": "Total" },
194
+ "children": []
195
+ }
196
+ }
197
+ ```