@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,495 @@
1
+ # Cart
2
+
3
+ **Category:** commerce
4
+ **Purpose:** Cart **read** layer for the store. `CartRoot` loads the active cart and exposes it (and the cart query error) to descendants, keeping them in sync as the cart changes. It is **hosted by the layout** (shared shell), wrapping the page slot — so every page, including PDPs, consumes its context without declaring it.
5
+
6
+ Cart **writes** (add / remove / quantity) no longer flow through `CartRoot`. A component declares the cart methods it needs as an `actions: { cart: [...] }` selector on its definition and dispatches through the compiler-injected `$actions.cart.*` prop — the write-side mirror of `fragment` → `$data`. Cart writes are **context-free**: an add-to-cart button works on a PDP, a product card, a search result, or the header with **no `CartRoot` ancestor** (specs/actions.md, ADR-0010).
7
+
8
+ This doc covers `CartRoot` — hosted in the layout, never emitted in page schemas — plus the **mini-cart footer checkout CTA** ([below](#mini-cart-footer-checkout-cta)), the composition of `CartCheckoutGuard` → (`CartTotal` + `CartGoCheckout`). The remaining cart line-item and summary particles (`CartList`, `CartItem*`, `CartCount`, `CartError`) exist in the catalog and will be documented when the full cart page enters scope.
9
+
10
+ ---
11
+
12
+ ## Visual cues (how to identify in an image)
13
+
14
+ `CartRoot` is a data provider, not a visible widget — you do not see it directly. The image is the source of truth for layout. The cart-aware element that requires it is a **cart read**:
15
+
16
+ - A **mini-cart count, total, or line-item list** anywhere on the page reads cart state and needs a `CartRoot` ancestor.
17
+ - An **empty cart panel** — a drawer or panel with no line items showing a short "your cart is empty" line and a "continue shopping" button, often paired with an illustration — is the `CartEmpty` branch: compose `CartEmptyMessage` for the sentence and `CartContinueShopping` for the button, never a plain `Text` plus `DrawerClose`.
18
+
19
+ An **add-to-cart CTA** ("Comprar", "Adicionar ao carrinho") does **not** require `CartRoot`: it writes through `$actions.cart.addItem`, which reads and writes the cache directly (context-free).
20
+
21
+ When the image shows a cart read, the page must render under a layout that hosts `CartRoot` — the default layout already does. **Do not add `CartRoot` to the page schema**: the layout's instance wraps the page slot, so the ancestor requirement is already satisfied.
22
+
23
+ ---
24
+
25
+ ## When to use
26
+
27
+ - In the **layout** (shared shell), as the root element wrapping header, page slot, and footer — the canonical and only standard placement. Every page under that layout (PDP, category, checkout) consumes its context.
28
+ - On a dedicated cart/mini-cart page **only when its layout does not already host `CartRoot`** (rare, custom shells) — then it wraps the cart line items and summary.
29
+
30
+ ## When NOT to use
31
+
32
+ - **In a page schema whose layout already hosts `CartRoot`** — that duplicates the provider (one per tree, never two), triggers the nested-reactive-root warning (AD-D8), and moves the cart query into the server-side page fetch, where no user cookie exists — the server mints a throwaway cart on every render.
33
+ - As a generic layout wrapper for centering content — that is `Container`. `CartRoot` is specifically the cart data provider.
34
+ - Around only the buy button — cart context comes from the layout; the buy button needs no local wrapper.
35
+
36
+ ---
37
+
38
+ ## Composition
39
+
40
+ `CartRoot` is the cart **read** context provider. It declares a GraphQL fragment for the active cart (the server resolves it from the session cookie) and uses a reactive fetch strategy so cache writes propagate to descendants without a refetch. It lives in the layout, wrapping the page slot:
41
+
42
+ ```
43
+ Layout
44
+ └── CartRoot
45
+ ├── Header (mini-cart count, drawer)
46
+ ├── Slot ← page content renders here
47
+ │ └── Container (PDP page schema — no CartRoot)
48
+ │ ├── ProductGalleryRoot
49
+ │ ├── ProductInformationRoot
50
+ │ ├── PricingRoot
51
+ │ └── BuyButtonRoot
52
+ │ └── BuyButtonButton
53
+ └── Footer
54
+ ```
55
+
56
+ Cart **read** particles (`CartCount`, `CartTotal`, `CartList`, and the `CartItem*` line-item particles) read from `CartRoot` via the `useCart()` hook and throw at render time if no `CartRoot` ancestor exists. The layout's instance satisfies that requirement for every page it hosts — a provider declared on the layout satisfies a consumer declared on the page.
57
+
58
+ Cart **write** consumers (`BuyButtonButton`, `ProductCardAddToCart`, `CartItemQuantity`, `CartItemRemove`) declare `actions: { cart: [...] }` and dispatch via `$actions.cart.*`. They need no `CartRoot` ancestor; the compiler wraps each one with a provider that supplies the handlers. `CartError` surfaces cart write errors from a module-level reactive var, so it too works without reading the cart context.
59
+
60
+ ---
61
+
62
+ ## Post-add behavior (open the mini-cart vs. redirect to checkout)
63
+
64
+ What happens after a successful add to cart is a **per-store choice made by composition**, not a config flag. The store composes exactly one of two behavior components — there is no `global.json` switch deciding it.
65
+
66
+ - **Mini-cart store → `CartOpenOnAdd`.** When the store has a mini-cart drawer, compose `CartOpenOnAdd` as the **parent of the mini-cart `DrawerRoot`** (its single child). It opens the drawer automatically on each successful add, with the new item visible and the count updated. It controls the drawer internally, so **do not set raw `open` / `onOpenChange` on `DrawerRoot`** — those are not authorable props, and the header `DrawerTrigger` plus manual close (Escape / backdrop / close button) keep working through the encapsulated wiring.
67
+
68
+ - **No-mini-cart store → `CartRedirectOnAdd`.** When the store has **no** mini-cart and adding a product should send the shopper straight to checkout, compose `CartRedirectOnAdd` (and omit the drawer entirely). It navigates to `href` (default `/checkout`) after each successful add. It renders no UI of its own; place it once in the layout.
69
+
70
+ The two are **mutually exclusive — compose exactly one**. A store with a mini-cart uses `CartOpenOnAdd` and never `CartRedirectOnAdd`; a store without one uses `CartRedirectOnAdd` and omits the drawer. Both react only to a **successful** add (a failed add or one returning user errors triggers neither).
71
+
72
+ ### Composition — `CartOpenOnAdd` around the mini-cart drawer
73
+
74
+ ```
75
+ CartRoot (layout)
76
+ └── Header
77
+ └── CartOpenOnAdd ← post-add behavior; controls the drawer below
78
+ └── DrawerRoot ← no raw open/onOpenChange props
79
+ ├── DrawerTrigger (CartCount badge — "minha cesta")
80
+ └── DrawerPortal
81
+ ├── DrawerBackdrop
82
+ └── DrawerPopup (CartList body + CartTotal / CartGoCheckout footer + DrawerClose)
83
+ ```
84
+
85
+ ### Composition — `CartRedirectOnAdd` in a no-mini-cart store
86
+
87
+ ```
88
+ CartRoot (layout)
89
+ ├── Header (add-to-cart CTAs elsewhere; no drawer)
90
+ └── CartRedirectOnAdd ← navigates to /checkout on a successful add
91
+ ```
92
+
93
+ ---
94
+
95
+ ## Components
96
+
97
+ ### CartRoot
98
+
99
+ Top-level cart **read** wrapper and data provider. Loads the active cart and exposes it (and the cart query error) to all descendants. Writes are dispatched through `$actions.cart.*`, not this provider.
100
+
101
+ Cart prices and the total are formatted from the active storefront context (the resolved binding's
102
+ locale and currency), not from props — there is nothing to author here.
103
+
104
+ **Data:** declares `fragment CartData on Query` for the active cart and uses a reactive fetch strategy — cache writes from the `cart` action re-render every descendant particle without a refetch.
105
+
106
+ ---
107
+
108
+ ### CartItemDiscountPercentage
109
+
110
+ Per-line discount badge. Renders the integer discount percentage of the current cart line — the `listPrice`-vs-`sellingPrice` difference (e.g. `-20%`) — so a shopper sees how deep each line's promotion is. It reads the line from the surrounding `CartList` item context and **renders null when the line has no discount** (`sellingPrice >= listPrice`), so it only ever appears on promotional lines. Place it alongside `CartItemPrice` and `CartItemListPrice` in the line-item template. Must be inside `CartList`.
111
+
112
+ The percentage matches the PDP `PricingDiscount` badge for the same product — both round with `Math.round` — so a 19.5% discount shows `-20%` on both surfaces.
113
+
114
+ | Prop | Type | Default | Notes |
115
+ |------|------|---------|-------|
116
+ | `template` | string | `"-{percentage}%"` | Output format; `{percentage}` is replaced by the integer percent (e.g. `"{percentage}% OFF"`) |
117
+
118
+ ---
119
+
120
+ ### CartEmptyMessage
121
+
122
+ The empty-cart message, rendered as a paragraph (`data-fs-cart-empty-message`, plus the `data-fs-text` identity). Place it inside `CartEmpty`. The wording is **merchant-editable**: a published CMS entry for the element wins over the `text` prop, and blank copy (an empty or whitespace-only string, from either source) renders nothing. It carries **no layout** — group and space it with `Container`.
123
+
124
+ | Prop | Type | Default | Notes |
125
+ |------|------|---------|-------|
126
+ | `text` | string | `"Your cart is empty"` | Non-CMS fallback. A CMS entry's `text` wins over it |
127
+
128
+ **Content:** declares the `cart-empty-message` content model (one `text` property), so the copy can change without a deploy.
129
+
130
+ ---
131
+
132
+ ### CartContinueShopping
133
+
134
+ The control that returns the shopper to browsing, rendered as a button (`data-fs-cart-continue-shopping`, alongside `data-fs-drawer-close` and `data-fs-button`). It **dismisses the overlay and dispatches no cart write**. Composed children replace the label, which is how an icon goes inside the button.
135
+
136
+ It is the drawer's own close control, so it **requires a `DrawerRoot` ancestor** — on a cart page with no drawer, compose a `NavigationLink` back to browsing instead. Placing it outside a drawer fails the render rather than degrading.
137
+
138
+ | Prop | Type | Default | Notes |
139
+ |------|------|---------|-------|
140
+ | `label` | string | `"Continue shopping"` | Non-CMS fallback. A CMS entry's `label` wins over it; composed children win over both |
141
+
142
+ **Content:** declares the `cart-continue-shopping` content model (one `label` property). Authored independently of the message, so publishing one does not require restating the other.
143
+
144
+ ---
145
+
146
+ ## Coupon
147
+
148
+ Four root-agnostic components wire up the cart coupon flow — apply a code, list the applied coupons, remove one, and surface apply/remove errors. They read `useCart()` (for the applied list) and dispatch through `$actions.cart.applyCoupon` / `$actions.cart.removeCoupon`, so they compose anywhere inside a `CartRoot` subtree. In a mini-cart they sit in the `DrawerPopup` footer, above the totals.
149
+
150
+ The applied coupons are a **list of chips (1..N)**, not a single-coupon slot — forward-compatible with multi-coupon stores. The server recomputes totals on every apply/remove and returns the updated cart, so `CartTotal` and the totalizer rows update automatically; no optimistic state is used.
151
+
152
+ | Component | Element | Purpose | Notes |
153
+ |-----------|---------|---------|-------|
154
+ | `CartCouponForm` | `form` | Coupon code input + apply button | Dispatches `$actions.cart.applyCoupon`. Disables input + button and exposes `data-fs-cart-coupon-pending` while an apply is in flight; clears the input on success. |
155
+ | `CartAppliedCoupons` | `div` | Renders one chip per applied coupon | Reads `cart.appliedCoupons`; renders nothing when empty (no container). Each chip shows the `code` inline and a `CartCouponRemove`. An applied-but-no-discount coupon (`isUnmatchedCondition`) is exposed via the `data-fs-cart-coupon-unmatched` hook for the store to style/label (no baked copy). |
156
+ | `CartCouponRemove` | `button` | The per-chip remove control (the X) | Dispatches `$actions.cart.removeCoupon` for the chip's code. Use inside a `CartAppliedCoupons` chip, which supplies the code via context. |
157
+ | `CartCouponError` | `div` (`role="alert"`) | Inline coupon error banner | Reads a **dedicated** coupon error channel, separate from `CartError` (which carries item-write errors). Renders the first error, or nothing when there are none. |
158
+
159
+ `CartAppliedCoupons` repeats its `children` once per applied coupon (like `CartList` repeats per item): place the chip template — an optional code element plus a `CartCouponRemove` — as its children, and it is cloned per coupon with the coupon supplied via context. Omit `children` to get a built-in chip (code inline + a remove X).
160
+
161
+ **Errors:** coupon apply/remove `userErrors` (e.g. `COUPON_NOT_FOUND`, `COUPON_EXPIRED`) publish to a dedicated reactive var that only `CartCouponError` reads, so coupon feedback never collides with item-write errors shown by `CartError`. On a single-coupon store, a rejected second code surfaces here as a normal apply error.
162
+
163
+ **Styling split:** these components own behaviour and the `data-fs-*` hooks (`data-fs-cart-coupon-form`, `-input`, `-apply`, `-pending`, `data-fs-cart-applied-coupons`, `data-fs-cart-coupon`, `-code`, `-unmatched`, `data-fs-cart-coupon-remove`, `data-fs-cart-coupon-error`). Chip and X **visuals (swatch values) are authored by the styling pipeline**, not these components.
164
+
165
+ Coupon block inside a mini-cart `DrawerPopup` footer, at the top of the footer above the totals and checkout CTA (the footer lives inside the `CartFilled` branch — coupons only matter for a non-empty cart):
166
+
167
+ ```json
168
+ {
169
+ "popup-footer": { "type": "Container", "children": ["coupon-block", "footer-summary", "checkout-cta", "footer-keep-shopping"] },
170
+ "coupon-block": { "type": "Container", "children": ["coupon-form", "applied-coupons", "coupon-error"] },
171
+ "coupon-form": { "type": "CartCouponForm", "props": { "placeholder": "Coupon code", "applyLabel": "Apply" } },
172
+ "applied-coupons": { "type": "CartAppliedCoupons", "children": ["coupon-remove"] },
173
+ "coupon-remove": { "type": "CartCouponRemove" },
174
+ "coupon-error": { "type": "CartCouponError" }
175
+ }
176
+ ```
177
+
178
+ ---
179
+
180
+ ## Canonical schema example
181
+
182
+ Layout hosting `CartRoot` as its root, wrapping the page slot:
183
+
184
+ ```json
185
+ {
186
+ "root": { "type": "CartRoot", "children": ["header", "main", "footer"] },
187
+ "header": { "type": "Container", "children": ["mini-cart-count"] },
188
+ "mini-cart-count": { "type": "CartCount" },
189
+ "main": { "type": "Container", "children": ["slot"] },
190
+ "slot": { "type": "Slot" },
191
+ "footer": { "type": "Container" }
192
+ }
193
+ ```
194
+
195
+ PDP page schema under that layout — **no `CartRoot`**; the buy button consumes the layout's context:
196
+
197
+ ```json
198
+ {
199
+ "root": { "type": "Container", "children": ["gallery", "product-info", "pricing", "buy-button"] },
200
+ "gallery": { "type": "ProductGalleryRoot" },
201
+ "product-info": { "type": "ProductInformationRoot", "children": ["title", "description"] },
202
+ "title": { "type": "ProductInformationTitle" },
203
+ "description": { "type": "ProductInformationDescription" },
204
+ "pricing": { "type": "PricingRoot", "children": ["pricing-selling"] },
205
+ "pricing-selling": { "type": "PricingSellingPrice" },
206
+ "buy-button": { "type": "BuyButtonRoot", "children": ["buy-button-action"] },
207
+ "buy-button-action": { "type": "BuyButtonButton", "props": { "availableLabel": "Comprar", "unavailableLabel": "Indisponível" } }
208
+ }
209
+ ```
210
+
211
+ ---
212
+
213
+ ## Mini-cart loading / empty / filled state
214
+
215
+ A mini-cart (or any cart surface) must show a different surface in each of three states. While the reactive cart is still loading it shows a skeleton placeholder. Once it resolves with items, it shows the line-item list, the order summary, and the checkout CTA. Resolved-empty, it shows a short message and a way back to browsing — and it must **not** show a "R$ 0,00" total or a checkout button that leads nowhere.
216
+
217
+ This is pure composition with three mutually-exclusive self-hide branches — `CartLoading`, `CartEmpty`, `CartFilled`. All read the cart from `CartRoot` and render their children only for their case; **exactly one renders at a time** (loading → empty → filled):
218
+
219
+ - **`CartLoading`** renders its children only while the cart has **not** resolved (`cart == null`, the initial reactive load). It carries **no content of its own** — supply a skeleton placeholder as its child so the drawer body shows a skeleton during load instead of a blank surface. Do **not** put `CartList` here — `CartList` lives inside `CartFilled` and renders its own skeleton window when used standalone; reusing it under `CartLoading` would double-compose. Use simple placeholder rows (a few `Container`/`Text` skeleton blocks) instead.
220
+ - **`CartFilled`** renders its children only when the cart has resolved with one or more items. Wrap the `CartList`, the `CartTotal` rows, and `CartGoCheckout` in it — `CartTotal` falls back to "R$ 0,00" and `CartGoCheckout` still routes to checkout on their own, so wrapping them in `CartFilled` is what hides them when the cart is empty.
221
+ - **`CartEmpty`** renders its children only when the cart has resolved and is empty (zero items). It never shows while the cart is loading (`CartLoading` owns that window), so the empty message does not flash before the cart resolves. It carries **no copy of its own** — compose `CartEmptyMessage` and `CartContinueShopping` inside it.
222
+
223
+ The empty panel's copy lives in two leaves, one string each, so the panel is a composition rather than a configured block:
224
+
225
+ - **`CartEmptyMessage`** renders the message as a paragraph (`data-fs-cart-empty-message`). The wording is merchant-editable: a CMS entry wins over the `text` prop, which defaults to "Your cart is empty"; blank copy renders nothing.
226
+ - **`CartContinueShopping`** renders the control that returns the shopper to browsing (`data-fs-cart-continue-shopping`). Its `label` is merchant-editable the same way, and composed children replace the label when you want an icon inside the button.
227
+
228
+ Neither leaf renders a wrapper or carries spacing, so **order, grouping, and any illustration are yours**: put an `Icon` above the message, wrap the pair in a `Container`, pin the control to a footer `Container`. Both self-hide independently, so composing only one is valid.
229
+
230
+ Continue-shopping is a **non-mutating** control, not a cart action. Which control depends on the surface:
231
+
232
+ - **Inside the mini-cart drawer**, use `CartContinueShopping` — it closes the drawer through the drawer's own contract and dispatches no cart write.
233
+ - **On a cart or checkout page** (no drawer to close), use a storefront `NavigationLink` (e.g. `href="/"`) back to browsing. Do **not** place `CartContinueShopping` there: it is a drawer close, and without a `DrawerRoot` ancestor the render fails.
234
+
235
+ ```text
236
+ CartRoot (layout)
237
+ └── DrawerPopup body + footer
238
+ ├── CartLoading ← only while cart == null (initial load)
239
+ │ └── skeleton placeholder rows
240
+ ├── CartFilled ← only when items.length > 0
241
+ │ ├── CartList ← line-item template
242
+ │ ├── CartTotal (subtotal)
243
+ │ ├── CartTotal (total)
244
+ │ └── CartGoCheckout
245
+ └── CartEmpty ← only when the cart resolved to 0 items
246
+ ├── Icon ← optional illustration (any particle, any position)
247
+ ├── CartEmptyMessage ← "sua cesta está vazia" (CMS copy + prop fallback)
248
+ └── Container ← the store's footer grouping
249
+ └── CartContinueShopping ← "continuar comprando" (closes the drawer; no cart action)
250
+ ```
251
+
252
+ ```json
253
+ {
254
+ "cart-loading": { "type": "CartLoading", "children": ["skeleton-row-1", "skeleton-row-2"] },
255
+ "skeleton-row-1": { "type": "Container", "style": ["h-16", "animate-pulse", "rounded", "bg-gray-200"] },
256
+ "skeleton-row-2": { "type": "Container", "style": ["h-16", "animate-pulse", "rounded", "bg-gray-200"] },
257
+
258
+ "cart-filled": { "type": "CartFilled", "children": ["popup-body", "subtotal-row", "total-row", "checkout-btn"] },
259
+ "popup-body": { "type": "CartList", "children": ["cart-item-template"] },
260
+ "subtotal-row": { "type": "CartTotal", "props": { "label": "subtotal" } },
261
+ "total-row": { "type": "CartTotal", "props": { "label": "total" } },
262
+ "checkout-btn": { "type": "CartGoCheckout", "props": { "href": "/checkout", "children": "continuar" } },
263
+
264
+ "cart-empty": { "type": "CartEmpty", "children": ["empty-illustration", "empty-msg", "empty-footer"] },
265
+ "empty-illustration": { "type": "Icon", "props": { "name": "shopping-bag" } },
266
+ "empty-msg": { "type": "CartEmptyMessage", "props": { "text": "sua cesta está vazia" } },
267
+ "empty-footer": { "type": "Container", "children": ["keep-shopping-btn"] },
268
+ "keep-shopping-btn": { "type": "CartContinueShopping", "props": { "label": "continuar comprando" } }
269
+ }
270
+ ```
271
+
272
+ On a cart/checkout page there is no drawer to close, so the empty branch keeps `CartEmptyMessage` and swaps `CartContinueShopping` for a storefront `NavigationLink`:
273
+
274
+ ```json
275
+ {
276
+ "cart-empty": { "type": "CartEmpty", "children": ["empty-msg", "keep-shopping-link"] },
277
+ "empty-msg": { "type": "CartEmptyMessage", "props": { "text": "sua cesta está vazia" } },
278
+ "keep-shopping-link": { "type": "NavigationLink", "props": { "href": "/", "children": "continuar comprando" } }
279
+ }
280
+ ```
281
+
282
+ The `text` and `label` props are the non-CMS fallback. When the store publishes a content entry for the element, that entry's copy wins — the two elements are authored independently, so publishing the message does not force you to restate the label.
283
+
284
+ ---
285
+
286
+ ## Common mistakes
287
+
288
+ - **Adding `CartRoot` to a PDP / standard page schema.** The layout already hosts it wrapping the slot — a page-level instance duplicates the provider and runs the cart query in the server-side page fetch (no user cookie → throwaway cart minted per render).
289
+ - **Nesting two `CartRoot` elements.** There must be exactly one per tree — the layout's.
290
+ - **Using `CartRoot` as a layout box.** For centering and grouping, use `Container`.
291
+ - **Inventing `Cart` (without `Root`).** The entry point is `CartRoot`.
292
+ - **Placing `CartTotal` / `CartGoCheckout` outside `CartFilled`.** They do not self-hide — outside `CartFilled` they render "R$ 0,00" and a dead checkout button over an empty cart. Wrap the list, summary, and checkout in `CartFilled`.
293
+ - **Dropping the loading branch.** Because `CartFilled` (which owns `CartList`) returns null while the cart is loading, the skeleton window only shows if you add a `CartLoading` branch with a skeleton placeholder child. Without it the drawer body is blank until the cart resolves.
294
+ - **Reusing `CartList` inside `CartLoading`.** `CartList` already renders its own skeletons during load — nesting it under `CartLoading` double-composes. Put simple placeholder rows under `CartLoading` instead.
295
+ - **Making continue-shopping a cart action.** It is drawer dismissal, not a mutation — use `CartContinueShopping` inside a drawer and a storefront `NavigationLink` on a page. Never a `$actions.cart.*` call.
296
+ - **Putting the empty message inside `CartEmpty` as a component prop.** `CartEmpty` is copy-free; the copy belongs to the `CartEmptyMessage` leaf composed inside it.
297
+ - **Placing `CartContinueShopping` outside a drawer.** It is the drawer's close control, so a cart page without a `DrawerRoot` ancestor fails to render — compose a `NavigationLink` there instead.
298
+ - **Wrapping the empty copy to get spacing you expect the leaves to provide.** Neither leaf ships layout by design; use `Container` and swatches.
299
+ - **Hard-coding the checkout wording when a CMS is bound.** `CartGoCheckout`'s `label` (and the older `children`) is the fallback; content editors expect the `cart-checkout-label` entry to win.
300
+ - **Expecting a CMS entry to change where checkout goes.** The content channel is the label alone. `href` stays an authored prop.
301
+
302
+ ---
303
+
304
+ ## Mini-cart footer checkout CTA
305
+
306
+ The mini-cart drawer (the layout composition described on `CartRoot`) ends in a `DrawerPopup` footer that holds the **enriched checkout CTA**: `CartCheckoutGuard` wrapping `CartTotal` and `CartGoCheckout`. Three existing components, composed — there is no `MiniCart` or `CartCheckoutCTA` component to place.
307
+
308
+ - **`CartCheckoutGuard`** is the outer wrapper. It reads cart availability and, while any line item is not `AVAILABLE`, makes its whole subtree non-interactive (`inert` + `aria-disabled`) and exposes `data-fs-cart-checkout-blocked` for styling the disabled state. The shopper cannot proceed with an undeliverable item. It updates reactively from cache — no refetch, no reload — so the block clears the moment the offending line is removed or becomes available.
309
+ - **`CartTotal`** sits inside the guard, on or next to the button, so the grand total the shopper is about to pay is visible at the CTA. It reads the nearest `CartRoot`/`CartTotalizerRoot` and reformats reactively on every cart change.
310
+ - **`CartGoCheckout`** is the link to checkout (default `href` `/checkout`). During a **client-side** route transition it surfaces a loading state on its content wrapper — `aria-busy` plus `data-fs-cart-go-checkout-pending` — so the shopper sees the click registered. There is **no built-in spinner**: opt into one by styling that attribute (or composing a `Spinner` on it). For an **external or hard** checkout navigation (a non-Next route, a different origin, or a full page load — common for the real VTEX checkout) there is no client-side transition window, so the loading state simply does not show. That is the documented, graceful no-op, not a bug.
311
+
312
+ **The button wording is CMS content.** It resolves in a fixed order: the `cart-checkout-label` entry, then the `label` prop, then `children`, then the package default `"Checkout"`. So a merchant rewords the CTA — `"Finalizar compra"`, `"Ir para o pagamento"` — with a CMS save and no deployment, while a store with no CMS binding renders its authored value. `children` stays supported because that is where stores labelled the button before `label` existed; a CMS entry overrides it with no schema edit. A blank or whitespace-only entry value counts as unconfigured and falls through. Non-compiler hosts (Storybook, tests) pass a typed `$content` fixture directly.
313
+
314
+ **The destination is not content-editable.** `href` is an authored prop only. The content channel carries the label alone, so a content editor can change what the button says but never where it goes.
315
+
316
+ | Prop | Type | Required | Notes |
317
+ |-------|------|----------|-------|
318
+ | `href` | string | no | Checkout destination, default `/checkout`. Never content-editable |
319
+ | `label` | string | no | Authored fallback for the wording. Ignored when an entry supplies a label |
320
+ | `children` | node | no | Legacy label channel, still honoured. Element children are replaced when an entry supplies a label |
321
+
322
+ Content model (`cart-checkout-label`) fields, edited in the CMS:
323
+
324
+ | Field | Type | Required | Notes |
325
+ |-------|------|----------|-------|
326
+ | `label` | string | yes | The button wording, rendered verbatim |
327
+
328
+ Schema shape (inside the `DrawerPopup` footer `Container`):
329
+
330
+ ```json
331
+ {
332
+ "popup-footer": { "type": "Container", "children": ["checkout-cta"] },
333
+ "checkout-cta": { "type": "CartCheckoutGuard", "children": ["checkout-total", "checkout-btn"] },
334
+ "checkout-total": { "type": "CartTotal", "props": { "label": "Total" } },
335
+ "checkout-btn": { "type": "CartGoCheckout", "props": { "href": "/checkout", "label": "Finalizar compra" } }
336
+ }
337
+ ```
338
+
339
+ The element id is the CTA's content key — its slot inside the scope's one content entry — so name it for the region rather than its styling. Renaming it orphans the merchant's wording: the copy stays in the Content Platform while the component reads a key nobody writes.
340
+
341
+ Everything stays a layout composition: the guard, total, and link are independently reusable and the mini-cart adds no dedicated component type. To render a visible spinner while the CTA is pending, style `data-fs-cart-go-checkout-pending` or compose a `Spinner` on it; the attribute is the contract.
342
+
343
+ ---
344
+
345
+ ## Unavailable-item recovery
346
+
347
+ `CartCheckoutGuard` blocks checkout while any line is not `AVAILABLE`; the recovery affordances let the shopper resolve the block from inside the cart. Three pieces, all reading the availability already on the cart:
348
+
349
+ - **`CartUnavailableCount`** — cart-level summary of how many lines are unavailable (e.g. "2 items unavailable"). Renders a `<span data-fs-cart-unavailable-count>` with a `template` prop (`{count}` is replaced by the integer count; default `'{count} items unavailable'`; children override the text). **Self-hides** (`null`) when every line is available — including while the cart is still loading — so it never shows a false "0 items unavailable". Must be inside `CartRoot`.
350
+ - **`CartRemoveUnavailable`** — the bulk "remove all unavailable" button (`<button data-fs-cart-remove-unavailable>`). On click it dispatches **one** `$actions.cart.removeItems({ ids })` call carrying every unavailable line id: one mutation, one upstream write, one cache update — no per-line flicker. **Self-hides** when there is nothing to remove. Children are the label (default "Remove unavailable items"). Must be inside `CartRoot` (it reads the cart for the ids; the write itself is context-free).
351
+ - **Per-item remove-on-alert** — a `CartItemRemove` nested inside `CartItemUnavailable` in the line-item template, so each unavailable alert carries its own remove control. Composition only, no new component — see `cart-item.md` (including the label-vs-children nuance: children replace the built-in label).
352
+
353
+ Both cart-level components update reactively: removing the last unavailable line hides them and clears the `CartCheckoutGuard` block with no refetch. Mutation errors surface through the existing `CartError` banner.
354
+
355
+ Schema shape (mini-cart footer, above the checkout CTA):
356
+
357
+ ```json
358
+ {
359
+ "popup-footer": { "type": "Container", "children": ["unavailable-summary", "remove-unavailable", "checkout-cta"] },
360
+ "unavailable-summary": { "type": "CartUnavailableCount", "props": { "template": "{count} items unavailable" } },
361
+ "remove-unavailable": { "type": "CartRemoveUnavailable", "props": { "children": "Remove unavailable items" } },
362
+ "checkout-cta": { "type": "CartCheckoutGuard", "children": ["checkout-total", "checkout-btn"] }
363
+ }
364
+ ```
365
+
366
+ ---
367
+
368
+ ## Merchant alert banner
369
+
370
+ `CartAlertRoot` + `CartAlertIcon` + `CartAlertText` carry the **merchant's own** message inside the overlay — a minimum order, a running promotion, a policy note. The copy is CMS-editable, so changing it needs no schema edit and no deploy.
371
+
372
+ It is a **family, not a single component**: the arrangement is the composition. Compose the two parts in the order the design wants; there is no `iconPosition` prop and never will be.
373
+
374
+ ```text
375
+ DrawerPopup
376
+ ├── CartAlertRoot ← resolves the copy + glyph, self-hides, provides `cart-alert` context
377
+ │ ├── CartAlertIcon ← the glyph (uploaded image, or predefined sprite name)
378
+ │ └── CartAlertText ← the message
379
+ ├── Container (mini-cart body)
380
+ └── …
381
+ ```
382
+
383
+ Swap the two children and the glyph renders after the copy. Omit `CartAlertIcon` and no glyph renders at all, even when the merchant configured one — composition decides what *can* appear, state decides what *does*. Compose `CartAlertRoot` with **no** children and it falls back to the built-in arrangement (glyph then copy), so the simplest placement is one element.
384
+
385
+ ### Which message surface is this?
386
+
387
+ | Component | Source | Appears when |
388
+ |---|---|---|
389
+ | `CartAlert*` | **Merchant-authored** (CMS entry, or props) | Always, while a message is configured |
390
+ | `CartError` | Cart mutation `userErrors` | A write failed |
391
+ | `CartCouponError` | Coupon apply/remove errors | A coupon write failed |
392
+ | `CartUnavailableCount` | Cart data (`variant.availability`) | A line cannot be delivered |
393
+ | `cart.messages` | Platform order-form messages | *Not rendered by any component today* |
394
+
395
+ Do not route merchant copy through `CartError`, and do not route write errors through `CartAlert*`.
396
+
397
+ ### Components
398
+
399
+ #### CartAlertRoot
400
+
401
+ Owns **all** resolution and provides `cart-alert` context. The message resolves CMS-first, prop-second. The glyph resolves as a whole channel: a glyph configured in the CMS (an uploaded image or a sprite name) wins over any glyph set through the props, so a merchant who picks an icon in the CMS is never overridden by a developer's fallback `iconUrl` prop. **Self-hides** (`null`) when no non-blank message resolves — an unconfigured banner leaves no empty box, and because the parts are its children, nothing downstream renders either.
402
+
403
+ Reads **no cart data**: no `CartRoot` ancestor is required, and it adds nothing to the cart query. It is also cart-state agnostic — place it inside `CartFilled` if the banner should disappear on an empty cart.
404
+
405
+ | Prop | Type | Default | Notes |
406
+ |------|------|---------|-------|
407
+ | `text` | string | — | Fallback message. No default on purpose: an invented one would ship copy no merchant wrote |
408
+ | `icon` | icon | — | Fallback sprite name. **Unbounded** — the compiler collects the literal and fails the build on a name it cannot resolve |
409
+ | `iconUrl` | string | — | Fallback uploaded glyph; wins over `icon` when both resolve |
410
+ | `iconAlt` | string | `""` | Alt text for the uploaded glyph |
411
+
412
+ **Content model** — `cart-alert`: `text`, `icon`, `iconUrl`, `iconAlt`. Nothing is `required`, deliberately: a page's or layout's content lives in **one composite entry**, validated as a whole at read time, so a required property would let one blank field invalidate the entry and drop every other content-backed component in that layout with it.
413
+
414
+ #### CartAlertIcon
415
+
416
+ The glyph. Prefers the uploaded `iconUrl` (an `<img>`) and falls back to the sprite `icon` name (an `<svg>`); renders nothing when neither resolves. One hook, `data-fs-cart-alert-icon`, covers both element types — so a swatch that sizes it must cover both. Decorative: the message carries the meaning. Must be inside `CartAlertRoot`.
417
+
418
+ #### CartAlertText
419
+
420
+ The message, as `<span data-fs-cart-alert-text data-fs-text>`. Copy comes from the Root, so `children` here are a **display override**, not an authoring channel — composing literal copy inside it while the Root has no message renders nothing, because the Root self-hides first. Must be inside `CartAlertRoot`.
421
+
422
+ ### The `icons.include` obligation
423
+
424
+ `Icon` resolves names against a **compile-time** sprite with no runtime fallback. An `icon` **prop** is a literal the compiler can see, so it is collected automatically. A **CMS-chosen** name does not exist at build time, so a store whose merchants pick the icon must register the admitted names in `global.json`:
425
+
426
+ ```json
427
+ { "icons": { "include": ["bell", "bell-ringing", "tag", "shopping-cart", "map-pin", "star"] } }
428
+ ```
429
+
430
+ Import `CART_ALERT_ICON_NAMES` rather than retyping the list — it is read off the content model, so the two cannot drift. **Skip this and a merchant-chosen glyph renders as an empty `<svg>`: no build error, no console message.** The uploaded-icon channel has no such obligation; it is an `Image` and never touches the sprite.
431
+
432
+ Every admitted name is a base-dialect icon, so each resolves in any store regardless of its configured collection. A value outside the set arriving from a stale entry is dropped rather than passed to the sprite lookup.
433
+
434
+ Schema shape (top of the mini-cart popup):
435
+
436
+ ```json
437
+ {
438
+ "popup": { "type": "DrawerPopup", "children": ["minicart-alert", "minicart-body", "popup-footer"] },
439
+ "minicart-alert": { "type": "CartAlertRoot", "props": { "text": "frete grátis acima de R$ 199", "icon": "tag" }, "children": ["minicart-alert-icon", "minicart-alert-text"] },
440
+ "minicart-alert-icon": { "type": "CartAlertIcon" },
441
+ "minicart-alert-text": { "type": "CartAlertText" }
442
+ }
443
+ ```
444
+
445
+ Copy first, glyph second — the same components, reordered in `children`, no prop and no component change:
446
+
447
+ ```json
448
+ {
449
+ "minicart-alert": { "type": "CartAlertRoot", "props": { "text": "pedido mínimo de R$ 50", "icon": "bell" }, "children": ["minicart-alert-text", "minicart-alert-icon"] },
450
+ "minicart-alert-text": { "type": "CartAlertText" },
451
+ "minicart-alert-icon": { "type": "CartAlertIcon" }
452
+ }
453
+ ```
454
+ ---
455
+
456
+ ## Merchant disclaimer
457
+
458
+ `CartDisclaimer` is the merchant's plain-text notice before the shopper commits — conditions, purchase limits, or legal wording. It renders a `<p data-fs-cart-disclaimer data-fs-text>` and nothing else: no icon, no dismissal, no rich text, and no inline links.
459
+
460
+ **Two gates, in order.** It renders only when the cart has **resolved with items**, so it stays out of the empty state and out of the loading window on its own — the rule belongs to the component, not to where it is placed, so a disclaimer composed outside `CartFilled` still never appears on an empty overlay. Then the copy must be non-blank: a whitespace-only CMS value counts as **unconfigured**, not as an empty paragraph. Trimming decides whether to render, never what to render — the authored value reaches the DOM verbatim.
461
+
462
+ **Copy comes from the CMS, with the prop as the fallback.** The component declares the `cart-disclaimer` content model, so `$content.text` wins whenever a content entry supplies it; the `text` prop is the fallback in a non-CMS store, which issues no content read at all. **Neither carries a default**, so a leaf composed before anyone authors copy renders nothing — a package-written disclaimer would assert conditions no merchant agreed to.
463
+
464
+ **Composed `children` are the highest-precedence override.** As with the other cart leaves (`CartTotal`, `CartCount`, `CartError`), passing `children` in JSX renders them in place of both copy channels — full precedence is `children ?? $content?.text ?? text`. The blank-copy gate only applies to the resolved text; supplied `children` render even when no `text` or content entry exists (the items gate still applies).
465
+
466
+ **Placement is composition order.** There is no position prop: place it inside `CartFilled`, either below the order summary or immediately above the checkout CTA. Both of those satisfy the design; pick one and order the children accordingly. Must be inside `CartRoot` — it reads the cart to gate itself, and throws without that ancestor like every other cart read component.
467
+
468
+ Because the mini-cart is a **layout** composition, a disclaimer placed there keys into the **layout's** composite content entry, so its copy is store-wide — the right scope for standing conditions. A store that also wants a different disclaimer on its full cart page places a second instance in that page's schema, which keys into the page's own entry and is authored independently.
469
+
470
+ | Prop | Type | Default | Notes |
471
+ |------|------|---------|-------|
472
+ | `text` | string | — | Authored fallback, rendered when no CMS entry supplies the notice |
473
+
474
+ Schema shape (mini-cart footer, between the summary and the checkout CTA):
475
+
476
+ ```json
477
+ {
478
+ "popup-footer": { "type": "Container", "children": ["footer-total", "footer-disclaimer", "checkout-cta"] },
479
+ "footer-total": { "type": "CartTotal", "props": { "label": "Total" } },
480
+ "footer-disclaimer": { "type": "CartDisclaimer", "props": { "text": "Prices and delivery estimates are confirmed at checkout." } },
481
+ "checkout-cta": { "type": "CartCheckoutGuard", "children": ["checkout-btn"] }
482
+ }
483
+ ```
484
+
485
+ `$content` is never authored in a schema — it is compiler-reserved and injected from the entry. The `text` prop above is what a pre-CMS store ships; once the store is CMS-bound, a merchant edits the entry and the prop stays as the fallback.
486
+
487
+ ---
488
+
489
+ ## Related
490
+
491
+ - [[container]] — layout wrapper that usually sits directly under `CartRoot` to group the page blocks.
492
+ - [[buy-button]] — purchase CTA whose `BuyButtonButton` dispatches `$actions.cart.addItem` (context-free; no `CartRoot` needed).
493
+ - [[drawer]] — overlay primitive the mini-cart composes; `CartOpenOnAdd` wraps the `DrawerRoot` to open it on a successful add.
494
+ - [[pricing]] — price block shown alongside the buy button; reads product offer data, not cart data.
495
+ - [[product-information]] — title/description block on the same PDP.