@thorprovider/blocks 3.0.2 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (234) hide show
  1. package/README.md +61 -21
  2. package/dist/blocks/designs/checkout-commerce-v1/block.d.ts +49 -0
  3. package/dist/blocks/designs/checkout-commerce-v1/block.d.ts.map +1 -0
  4. package/dist/blocks/designs/checkout-commerce-v1/block.js +2487 -0
  5. package/dist/blocks/designs/checkout-commerce-v1/block.js.map +1 -0
  6. package/dist/blocks/designs/checkout-commerce-v1/block.mjs +2467 -0
  7. package/dist/blocks/designs/checkout-commerce-v1/block.mjs.map +1 -0
  8. package/dist/blocks/designs/checkout-commerce-v1/data-context.d.ts +8 -0
  9. package/dist/blocks/designs/checkout-commerce-v1/data-context.d.ts.map +1 -0
  10. package/dist/blocks/designs/checkout-commerce-v1/data-context.js +44 -0
  11. package/dist/blocks/designs/checkout-commerce-v1/data-context.js.map +1 -0
  12. package/dist/blocks/designs/checkout-commerce-v1/data-context.mjs +19 -0
  13. package/dist/blocks/designs/checkout-commerce-v1/data-context.mjs.map +1 -0
  14. package/dist/blocks/designs/checkout-commerce-v1/index.d.ts +3 -0
  15. package/dist/blocks/designs/checkout-commerce-v1/index.d.ts.map +1 -0
  16. package/dist/blocks/designs/checkout-commerce-v1/index.js +36 -0
  17. package/dist/blocks/designs/checkout-commerce-v1/index.js.map +1 -0
  18. package/dist/blocks/designs/checkout-commerce-v1/index.mjs +6 -0
  19. package/dist/blocks/designs/checkout-commerce-v1/index.mjs.map +1 -0
  20. package/dist/blocks/designs/marketplace-product-card/block.d.ts +12 -0
  21. package/dist/blocks/designs/marketplace-product-card/block.d.ts.map +1 -0
  22. package/dist/blocks/designs/marketplace-product-card/block.js +243 -0
  23. package/dist/blocks/designs/marketplace-product-card/block.js.map +1 -0
  24. package/dist/blocks/designs/marketplace-product-card/block.mjs +233 -0
  25. package/dist/blocks/designs/marketplace-product-card/block.mjs.map +1 -0
  26. package/dist/blocks/designs/marketplace-product-card/index.d.ts +3 -0
  27. package/dist/blocks/designs/marketplace-product-card/index.d.ts.map +1 -0
  28. package/dist/blocks/designs/marketplace-product-card/index.js +36 -0
  29. package/dist/blocks/designs/marketplace-product-card/index.js.map +1 -0
  30. package/dist/blocks/designs/marketplace-product-card/index.mjs +6 -0
  31. package/dist/blocks/designs/marketplace-product-card/index.mjs.map +1 -0
  32. package/dist/blocks/designs/marketplace-product-card/normalize.d.ts +13 -0
  33. package/dist/blocks/designs/marketplace-product-card/normalize.d.ts.map +1 -0
  34. package/dist/blocks/designs/marketplace-product-card/normalize.js +36 -0
  35. package/dist/blocks/designs/marketplace-product-card/normalize.js.map +1 -0
  36. package/dist/blocks/designs/marketplace-product-card/normalize.mjs +12 -0
  37. package/dist/blocks/designs/marketplace-product-card/normalize.mjs.map +1 -0
  38. package/dist/blocks/designs/marketplace-product-card/variants.d.ts +72 -0
  39. package/dist/blocks/designs/marketplace-product-card/variants.d.ts.map +1 -0
  40. package/dist/blocks/designs/marketplace-product-card/variants.js +123 -0
  41. package/dist/blocks/designs/marketplace-product-card/variants.js.map +1 -0
  42. package/dist/blocks/designs/marketplace-product-card/variants.mjs +89 -0
  43. package/dist/blocks/designs/marketplace-product-card/variants.mjs.map +1 -0
  44. package/dist/blocks/e-commerce/account/account-frame.d.ts +38 -0
  45. package/dist/blocks/e-commerce/account/account-frame.d.ts.map +1 -0
  46. package/dist/blocks/e-commerce/account/account-frame.js +102 -0
  47. package/dist/blocks/e-commerce/account/account-frame.js.map +1 -0
  48. package/dist/blocks/e-commerce/account/account-frame.mjs +78 -0
  49. package/dist/blocks/e-commerce/account/account-frame.mjs.map +1 -0
  50. package/dist/blocks/e-commerce/account/address-book.d.ts +79 -0
  51. package/dist/blocks/e-commerce/account/address-book.d.ts.map +1 -0
  52. package/dist/blocks/e-commerce/account/address-book.js +250 -0
  53. package/dist/blocks/e-commerce/account/address-book.js.map +1 -0
  54. package/dist/blocks/e-commerce/account/address-book.mjs +225 -0
  55. package/dist/blocks/e-commerce/account/address-book.mjs.map +1 -0
  56. package/dist/blocks/e-commerce/account/profile-form.d.ts +35 -0
  57. package/dist/blocks/e-commerce/account/profile-form.d.ts.map +1 -0
  58. package/dist/blocks/e-commerce/account/profile-form.js +100 -0
  59. package/dist/blocks/e-commerce/account/profile-form.js.map +1 -0
  60. package/dist/blocks/e-commerce/account/profile-form.mjs +76 -0
  61. package/dist/blocks/e-commerce/account/profile-form.mjs.map +1 -0
  62. package/dist/blocks/e-commerce/checkout-forms/checkbox-check.js +1 -1
  63. package/dist/blocks/e-commerce/checkout-forms/checkbox-check.js.map +1 -1
  64. package/dist/blocks/e-commerce/checkout-forms/checkbox-check.mjs +1 -1
  65. package/dist/blocks/e-commerce/checkout-forms/checkbox-check.mjs.map +1 -1
  66. package/dist/blocks/e-commerce/checkout-forms/checkout-address-equality.d.ts +11 -0
  67. package/dist/blocks/e-commerce/checkout-forms/checkout-address-equality.d.ts.map +1 -0
  68. package/dist/blocks/e-commerce/checkout-forms/checkout-address-equality.js +46 -0
  69. package/dist/blocks/e-commerce/checkout-forms/checkout-address-equality.js.map +1 -0
  70. package/dist/blocks/e-commerce/checkout-forms/checkout-address-equality.mjs +22 -0
  71. package/dist/blocks/e-commerce/checkout-forms/checkout-address-equality.mjs.map +1 -0
  72. package/dist/blocks/e-commerce/checkout-forms/checkout-address-fields.d.ts +28 -0
  73. package/dist/blocks/e-commerce/checkout-forms/checkout-address-fields.d.ts.map +1 -0
  74. package/dist/blocks/e-commerce/checkout-forms/checkout-address-fields.js +278 -0
  75. package/dist/blocks/e-commerce/checkout-forms/checkout-address-fields.js.map +1 -0
  76. package/dist/blocks/e-commerce/checkout-forms/checkout-address-fields.mjs +260 -0
  77. package/dist/blocks/e-commerce/checkout-forms/checkout-address-fields.mjs.map +1 -0
  78. package/dist/blocks/e-commerce/checkout-forms/checkout-contact-step.d.ts +12 -9
  79. package/dist/blocks/e-commerce/checkout-forms/checkout-contact-step.d.ts.map +1 -1
  80. package/dist/blocks/e-commerce/checkout-forms/checkout-contact-step.js +49 -71
  81. package/dist/blocks/e-commerce/checkout-forms/checkout-contact-step.js.map +1 -1
  82. package/dist/blocks/e-commerce/checkout-forms/checkout-contact-step.mjs +50 -72
  83. package/dist/blocks/e-commerce/checkout-forms/checkout-contact-step.mjs.map +1 -1
  84. package/dist/blocks/e-commerce/checkout-forms/checkout-country-field.d.ts.map +1 -1
  85. package/dist/blocks/e-commerce/checkout-forms/checkout-country-field.js +6 -3
  86. package/dist/blocks/e-commerce/checkout-forms/checkout-country-field.js.map +1 -1
  87. package/dist/blocks/e-commerce/checkout-forms/checkout-country-field.mjs +6 -3
  88. package/dist/blocks/e-commerce/checkout-forms/checkout-country-field.mjs.map +1 -1
  89. package/dist/blocks/e-commerce/checkout-forms/checkout-id-context.d.ts +7 -0
  90. package/dist/blocks/e-commerce/checkout-forms/checkout-id-context.d.ts.map +1 -0
  91. package/dist/blocks/e-commerce/checkout-forms/checkout-id-context.js +41 -0
  92. package/dist/blocks/e-commerce/checkout-forms/checkout-id-context.js.map +1 -0
  93. package/dist/blocks/e-commerce/checkout-forms/checkout-id-context.mjs +16 -0
  94. package/dist/blocks/e-commerce/checkout-forms/checkout-id-context.mjs.map +1 -0
  95. package/dist/blocks/e-commerce/checkout-forms/checkout-location-select.d.ts +24 -0
  96. package/dist/blocks/e-commerce/checkout-forms/checkout-location-select.d.ts.map +1 -0
  97. package/dist/blocks/e-commerce/checkout-forms/checkout-location-select.js +75 -0
  98. package/dist/blocks/e-commerce/checkout-forms/checkout-location-select.js.map +1 -0
  99. package/dist/blocks/e-commerce/checkout-forms/checkout-location-select.mjs +58 -0
  100. package/dist/blocks/e-commerce/checkout-forms/checkout-location-select.mjs.map +1 -0
  101. package/dist/blocks/e-commerce/checkout-forms/checkout-order-summary.d.ts +3 -2
  102. package/dist/blocks/e-commerce/checkout-forms/checkout-order-summary.d.ts.map +1 -1
  103. package/dist/blocks/e-commerce/checkout-forms/checkout-order-summary.js +9 -2
  104. package/dist/blocks/e-commerce/checkout-forms/checkout-order-summary.js.map +1 -1
  105. package/dist/blocks/e-commerce/checkout-forms/checkout-order-summary.mjs +9 -2
  106. package/dist/blocks/e-commerce/checkout-forms/checkout-order-summary.mjs.map +1 -1
  107. package/dist/blocks/e-commerce/checkout-forms/checkout-payment-step.d.ts +23 -8
  108. package/dist/blocks/e-commerce/checkout-forms/checkout-payment-step.d.ts.map +1 -1
  109. package/dist/blocks/e-commerce/checkout-forms/checkout-payment-step.js +136 -31
  110. package/dist/blocks/e-commerce/checkout-forms/checkout-payment-step.js.map +1 -1
  111. package/dist/blocks/e-commerce/checkout-forms/checkout-payment-step.mjs +143 -32
  112. package/dist/blocks/e-commerce/checkout-forms/checkout-payment-step.mjs.map +1 -1
  113. package/dist/blocks/e-commerce/checkout-forms/checkout-review-step.d.ts +13 -7
  114. package/dist/blocks/e-commerce/checkout-forms/checkout-review-step.d.ts.map +1 -1
  115. package/dist/blocks/e-commerce/checkout-forms/checkout-review-step.js +179 -28
  116. package/dist/blocks/e-commerce/checkout-forms/checkout-review-step.js.map +1 -1
  117. package/dist/blocks/e-commerce/checkout-forms/checkout-review-step.mjs +180 -29
  118. package/dist/blocks/e-commerce/checkout-forms/checkout-review-step.mjs.map +1 -1
  119. package/dist/blocks/e-commerce/checkout-forms/checkout-saved-addresses.d.ts +20 -0
  120. package/dist/blocks/e-commerce/checkout-forms/checkout-saved-addresses.d.ts.map +1 -0
  121. package/dist/blocks/e-commerce/checkout-forms/checkout-saved-addresses.js +199 -0
  122. package/dist/blocks/e-commerce/checkout-forms/checkout-saved-addresses.js.map +1 -0
  123. package/dist/blocks/e-commerce/checkout-forms/checkout-saved-addresses.mjs +175 -0
  124. package/dist/blocks/e-commerce/checkout-forms/checkout-saved-addresses.mjs.map +1 -0
  125. package/dist/blocks/e-commerce/checkout-forms/checkout-section-nav.d.ts +14 -0
  126. package/dist/blocks/e-commerce/checkout-forms/checkout-section-nav.d.ts.map +1 -0
  127. package/dist/blocks/e-commerce/checkout-forms/checkout-section-nav.js +136 -0
  128. package/dist/blocks/e-commerce/checkout-forms/checkout-section-nav.js.map +1 -0
  129. package/dist/blocks/e-commerce/checkout-forms/checkout-section-nav.mjs +109 -0
  130. package/dist/blocks/e-commerce/checkout-forms/checkout-section-nav.mjs.map +1 -0
  131. package/dist/blocks/e-commerce/checkout-forms/checkout-shipping-step.d.ts +32 -10
  132. package/dist/blocks/e-commerce/checkout-forms/checkout-shipping-step.d.ts.map +1 -1
  133. package/dist/blocks/e-commerce/checkout-forms/checkout-shipping-step.js +265 -147
  134. package/dist/blocks/e-commerce/checkout-forms/checkout-shipping-step.js.map +1 -1
  135. package/dist/blocks/e-commerce/checkout-forms/checkout-shipping-step.mjs +272 -148
  136. package/dist/blocks/e-commerce/checkout-forms/checkout-shipping-step.mjs.map +1 -1
  137. package/dist/blocks/e-commerce/checkout-forms/checkout-step-header.d.ts +13 -0
  138. package/dist/blocks/e-commerce/checkout-forms/checkout-step-header.d.ts.map +1 -0
  139. package/dist/blocks/e-commerce/checkout-forms/checkout-step-header.js +74 -0
  140. package/dist/blocks/e-commerce/checkout-forms/checkout-step-header.js.map +1 -0
  141. package/dist/blocks/e-commerce/checkout-forms/checkout-step-header.mjs +50 -0
  142. package/dist/blocks/e-commerce/checkout-forms/checkout-step-header.mjs.map +1 -0
  143. package/dist/blocks/e-commerce/checkout-forms/checkout-step-summary.d.ts +7 -0
  144. package/dist/blocks/e-commerce/checkout-forms/checkout-step-summary.d.ts.map +1 -0
  145. package/dist/blocks/e-commerce/checkout-forms/checkout-step-summary.js +91 -0
  146. package/dist/blocks/e-commerce/checkout-forms/checkout-step-summary.js.map +1 -0
  147. package/dist/blocks/e-commerce/checkout-forms/checkout-step-summary.mjs +65 -0
  148. package/dist/blocks/e-commerce/checkout-forms/checkout-step-summary.mjs.map +1 -0
  149. package/dist/blocks/e-commerce/checkout-forms/checkout.d.ts +174 -44
  150. package/dist/blocks/e-commerce/checkout-forms/checkout.d.ts.map +1 -1
  151. package/dist/blocks/e-commerce/checkout-forms/checkout.js +532 -108
  152. package/dist/blocks/e-commerce/checkout-forms/checkout.js.map +1 -1
  153. package/dist/blocks/e-commerce/checkout-forms/checkout.mjs +542 -109
  154. package/dist/blocks/e-commerce/checkout-forms/checkout.mjs.map +1 -1
  155. package/dist/blocks/e-commerce/navigation/storefront-navbar-cart-sheet.d.ts.map +1 -1
  156. package/dist/blocks/e-commerce/navigation/storefront-navbar-cart-sheet.js +44 -20
  157. package/dist/blocks/e-commerce/navigation/storefront-navbar-cart-sheet.js.map +1 -1
  158. package/dist/blocks/e-commerce/navigation/storefront-navbar-cart-sheet.mjs +44 -20
  159. package/dist/blocks/e-commerce/navigation/storefront-navbar-cart-sheet.mjs.map +1 -1
  160. package/dist/blocks/e-commerce/navigation/storefront-navbar.d.ts.map +1 -1
  161. package/dist/blocks/e-commerce/navigation/storefront-navbar.js +21 -10
  162. package/dist/blocks/e-commerce/navigation/storefront-navbar.js.map +1 -1
  163. package/dist/blocks/e-commerce/navigation/storefront-navbar.mjs +21 -10
  164. package/dist/blocks/e-commerce/navigation/storefront-navbar.mjs.map +1 -1
  165. package/dist/blocks/e-commerce/product-list/product-card.d.ts.map +1 -1
  166. package/dist/blocks/e-commerce/product-list/product-card.js +36 -9
  167. package/dist/blocks/e-commerce/product-list/product-card.js.map +1 -1
  168. package/dist/blocks/e-commerce/product-list/product-card.mjs +36 -9
  169. package/dist/blocks/e-commerce/product-list/product-card.mjs.map +1 -1
  170. package/dist/blocks/e-commerce/product-list/product-showcase-1.d.ts.map +1 -1
  171. package/dist/blocks/e-commerce/product-list/product-showcase-1.js +7 -2
  172. package/dist/blocks/e-commerce/product-list/product-showcase-1.js.map +1 -1
  173. package/dist/blocks/e-commerce/product-list/product-showcase-1.mjs +7 -2
  174. package/dist/blocks/e-commerce/product-list/product-showcase-1.mjs.map +1 -1
  175. package/dist/blocks/e-commerce/product-overview/product-quick-view-dialog.d.ts.map +1 -1
  176. package/dist/blocks/e-commerce/product-overview/product-quick-view-dialog.js +5 -1
  177. package/dist/blocks/e-commerce/product-overview/product-quick-view-dialog.js.map +1 -1
  178. package/dist/blocks/e-commerce/product-overview/product-quick-view-dialog.mjs +5 -1
  179. package/dist/blocks/e-commerce/product-overview/product-quick-view-dialog.mjs.map +1 -1
  180. package/dist/blocks/e-commerce/storefront-hero/storefront-hero.d.ts.map +1 -1
  181. package/dist/blocks/e-commerce/storefront-hero/storefront-hero.js +71 -51
  182. package/dist/blocks/e-commerce/storefront-hero/storefront-hero.js.map +1 -1
  183. package/dist/blocks/e-commerce/storefront-hero/storefront-hero.mjs +71 -51
  184. package/dist/blocks/e-commerce/storefront-hero/storefront-hero.mjs.map +1 -1
  185. package/dist/blocks/marketing/banners/banner-1.d.ts.map +1 -1
  186. package/dist/blocks/marketing/banners/banner-1.js +15 -27
  187. package/dist/blocks/marketing/banners/banner-1.js.map +1 -1
  188. package/dist/blocks/marketing/banners/banner-1.mjs +16 -28
  189. package/dist/blocks/marketing/banners/banner-1.mjs.map +1 -1
  190. package/dist/index.d.ts +16 -4
  191. package/dist/index.d.ts.map +1 -1
  192. package/dist/index.js +19 -0
  193. package/dist/index.js.map +1 -1
  194. package/dist/index.mjs +13 -0
  195. package/dist/index.mjs.map +1 -1
  196. package/dist/lib/contracts/checkout-commerce-v1.d.ts +2350 -0
  197. package/dist/lib/contracts/checkout-commerce-v1.d.ts.map +1 -0
  198. package/dist/lib/contracts/checkout-commerce-v1.js +417 -0
  199. package/dist/lib/contracts/checkout-commerce-v1.js.map +1 -0
  200. package/dist/lib/contracts/checkout-commerce-v1.mjs +392 -0
  201. package/dist/lib/contracts/checkout-commerce-v1.mjs.map +1 -0
  202. package/dist/lib/contracts/marketplace-product-card.d.ts +324 -0
  203. package/dist/lib/contracts/marketplace-product-card.d.ts.map +1 -0
  204. package/dist/lib/contracts/marketplace-product-card.js +85 -0
  205. package/dist/lib/contracts/marketplace-product-card.js.map +1 -0
  206. package/dist/lib/contracts/marketplace-product-card.mjs +61 -0
  207. package/dist/lib/contracts/marketplace-product-card.mjs.map +1 -0
  208. package/dist/lib/contracts.d.ts +2289 -178
  209. package/dist/lib/contracts.d.ts.map +1 -1
  210. package/dist/lib/contracts.js +332 -25
  211. package/dist/lib/contracts.js.map +1 -1
  212. package/dist/lib/contracts.mjs +278 -5
  213. package/dist/lib/contracts.mjs.map +1 -1
  214. package/dist/lib/money-schema.d.ts +19 -0
  215. package/dist/lib/money-schema.d.ts.map +1 -0
  216. package/dist/lib/money-schema.js +33 -0
  217. package/dist/lib/money-schema.js.map +1 -0
  218. package/dist/lib/money-schema.mjs +9 -0
  219. package/dist/lib/money-schema.mjs.map +1 -0
  220. package/dist/lib/motion.d.ts +29 -0
  221. package/dist/lib/motion.d.ts.map +1 -0
  222. package/dist/lib/motion.js +65 -0
  223. package/dist/lib/motion.js.map +1 -0
  224. package/dist/lib/motion.mjs +41 -0
  225. package/dist/lib/motion.mjs.map +1 -0
  226. package/dist/ui/accordion.d.ts +3 -1
  227. package/dist/ui/accordion.d.ts.map +1 -1
  228. package/dist/ui/accordion.js +21 -5
  229. package/dist/ui/accordion.js.map +1 -1
  230. package/dist/ui/accordion.mjs +21 -5
  231. package/dist/ui/accordion.mjs.map +1 -1
  232. package/dist/ui/input-group.d.ts +1 -1
  233. package/package.json +18 -3
  234. package/dist/.tsbuildinfo +0 -1
package/README.md CHANGED
@@ -15,6 +15,7 @@ Reusable storefront UI blocks for Thor Commerce, built from [ShadcnStore](https:
15
15
  - **Single source of primitives.** The vendored shadcn primitives under `src/ui/` are the only copy; consumers import them from this package instead of installing their own.
16
16
  - **No over-abstraction.** Values are split into props vs internal detail with judgment. A prop is added only when the value is genuinely content or configuration; layout and decoration stay internal.
17
17
  - **Shared contracts only when reused.** A type like `CTA` is promoted to `src/lib/types.ts` only once two blocks share it.
18
+ - **Consistent motion.** State transitions use the shared motion scale and honor reduced-motion preferences; see the [block motion standard](docs/standards/motion.md).
18
19
 
19
20
  ## Structure
20
21
 
@@ -62,7 +63,7 @@ Blocks follow `src/blocks/<category>/<section>/<block>.tsx`. Each block co-locat
62
63
  | `ProductCategory` | E-commerce | Canonical category block; bounded `presentation` `grid` (image cards) / `icons` (compact icon grid) / `list` (rows with subcategory chips and optional controlled search) |
63
64
  | `CategoryListing` | E-commerce | Canonical category listing (results + pagination) with a controlled query and bounded `presentation` `sidebar` (persistent desktop panel + mobile sheet) / `toolbar` (sticky mobile toolbar + drawers); generic facet groups render only from real metadata |
64
65
  | `ShoppingCart` | E-commerce | Canonical cart; backend-authoritative `Money` totals and item lines, optional promo entry and recently-viewed suggestions; `presentation` `compact` (collapsible card) or `page` (full-width review) |
65
- | `Checkout` | E-commerce | Canonical page-level checkout; controlled values, backend-authoritative `Money` totals, `PaymentMethod[]` data with no raw card input; `presentation` `single-page` or `stepper`, optional `showReviewStep` |
66
+ | `Checkout` | E-commerce | Canonical page-level checkout; controlled values, backend-authoritative `Money` totals, `PaymentMethod[]` data with no raw card input; `presentation` `single-page`, `accordion`, or `stepper`, optional `showReviewStep` |
66
67
  | `CheckoutConfirmation` | E-commerce | Order confirmation with fulfilment timeline |
67
68
  | `OrderHistory` | E-commerce | Canonical order-history collection; `presentation` `cards` or `rows`, order-level `Money` totals rendered verbatim, status as data, host-owned pagination and actions |
68
69
  | `OrderLine` | E-commerce | Canonical order-line item cell (`name`, optional image/details, quantity, `Money` line total) used inside `OrderHistory` |
@@ -317,32 +318,51 @@ with Spanish defaults (`Agregar al carrito`, `Precio no disponible`, …).
317
318
 
318
319
  ## Checkout block (page-level, controlled)
319
320
 
320
- `Checkout` is the single public checkout surface; it replaces the numbered `CheckoutForm1`, `CheckoutForm2`, and `CheckoutForm3` blocks. It is a **controlled component**: field values arrive through `values` and every edit is reported through `onChange`, so the host owns all commercial state. The block owns only the ephemeral step index of the `stepper` presentation.
321
-
322
- - `presentation: 'single-page' | 'stepper'` (required) — `single-page` renders every section visible at once (summary first in DOM order on mobile); `stepper` shows one step at a time with an accessible progress indicator. Both accept the same props and emit the same callbacks.
323
- - `showReviewStep?: boolean` — appends a confirmation step (`stepper`) or section (`single-page`) before submission.
324
- - `values: CheckoutValues` — `email`, `firstName`, `lastName`, `phone`, `address`, `city`, `state`, `zipCode`, `country`, `paymentMethod`, `saveInfo`, `newsletter`, `promoCode`. There are no card fields.
325
- - `onChange: (field, value) => void` — reported per edit. The block holds no private copy of the form data and applies no masking.
326
- - `orderSummary?: { items, totals? }` — line identity, name, quantity, optional variant/image, optional canonical `Money` `lineTotal` and `unitPrice`, plus backend `totals` (`subtotal`, optional `discount`/`tax`/`shipping`, `total`). Amounts render verbatim; required totals that are absent or malformed render as unavailable with the retry action, never as zero. No local arithmetic, tax rate, shipping cost, threshold, or hardcoded currency.
327
- - `totalsState?: 'idle' | 'pending' | 'error'` and `onRetryTotals?` — controlled reads; pending and failed states render status/alert copy without inventing amounts.
328
- - `countries?: { value, label }[]`, `shippingOptions?`, `selectedShippingOptionId?`, `onSelectShippingOption?` — host-owned options and selection. With no country list the block renders a text input; with no shipping options it renders no method section; nothing is pre-selected.
329
- - `paymentMethods?: PaymentMethod[]` — payment methods as data (canonical `@thorprovider/types`). One option per method, the selected method's description, an empty state for an empty list, and a non-selectable rendering for `isEnabled === false`. The block renders **no raw card fields**: card collection belongs to the host payment-provider surface.
330
- - `labels?: Partial<CheckoutLabels>` and `formatMoney?: (money: Money) => string` — every user-facing string is overridable (neutral English defaults) and amounts format through canonical `Money` with no hardcoded symbol.
331
- - `fieldErrors?` / `fieldDescriptions?` — per-field messages and helper text, rendered with `role="alert"` and `aria-invalid`/`aria-describedby` wiring.
332
- - `validateStep?: (step: CheckoutStepId) => boolean` and `onStepChange?` — the block consults `validateStep` before advancing and for every applicable step before submitting; `onStepChange` is a notification only, never a controlled value. Without the callback the block advances and leaves submit protection to the host.
333
- - `onSubmit?`, `submitting?`, `submitError?`, `onRetrySubmit?` — submission is reported, with a pending guard and a recoverable error state; the block never creates an order, clears a cart, or claims success.
321
+ `Checkout` is the single public checkout surface; it replaces the numbered `CheckoutForm1`, `CheckoutForm2`, and `CheckoutForm3` blocks. It is a **controlled component**: contact, shipping, billing, selections, and totals arrive as props; edits are reported through callbacks. The block owns only ephemeral UI state (step index, gift-card input, saved-address create mode and delete confirmation). It performs no HTTP, reads no session/customer/address book, computes no totals, and never creates an order.
322
+
323
+ - `presentation: 'single-page' | 'accordion' | 'stepper'` and `showReviewStep?` — all three presentations accept the same data and emit the same callbacks; the summary is first in DOM order on `single-page`.
324
+ - `single-page` keeps every numbered folio section visible and includes an in-page index that reports the section in view, not completion.
325
+ - `accordion` keeps every step header visible with one section expanded. Closed headers show supplied-value summaries when available, never a completion check; header navigation is not gated by validation.
326
+ - `stepper` shows one step at a time with a compact progress indicator and Continue/Back actions.
327
+ - `contact: CheckoutContactValues`, `onContactChange`, `customer?`, `onSignIn?`, `onSignOut?` — guest email or a host-supplied authenticated identity. No password, token, or credential fields are rendered.
328
+ - `shippingAddress`, `billingAddress?`, `sameAsShipping`, `onShippingAddressChange`, `onBillingAddressChange?`, `onSameAsShippingChange` — structured addresses. `billingAddress` may be supplied while `sameAsShipping` is true; it is rendered only when the shopper unchecks it.
329
+ - `savedAddresses?`, `onSelectSavedAddress?`, `onCreateSavedAddress?`, `onUpdateSavedAddress?`, `onDeleteSavedAddress?`, `onStartNewAddress?`, `onCancelNewAddress?`, `savedAddressState?` — saved addresses are host data. The shipping picker reports the selection and shows contextual create/update/delete actions only when the corresponding callbacks are supplied; the host mutates and returns the refreshed list. `savedAddressState` carries `pendingId`, `error`, `lastSavedId`, and `lastAction` so the block can render per-entry pending/error states and politely announce saved/deleted results. `CheckoutSavedAddress` carries both `isDefaultShipping` and `isDefaultBilling`. Billing saved-address management is out of scope.
330
+ - `shippingLocations?`, `billingLocations?`, `onRetryLocations?` — host-supplied country, province/state, and city options with per-level loading/error/unavailable states. The block disables a child until its parent is selected. There is no free-text fallback.
331
+ - `shippingGroups?`, `shippingState?`, `onSelectShippingOption?`, `onRetryShipping?` — opaque delivery groups with one selection per group and explicit unavailable groups. The MVP may supply one group. Each group may carry optional `items: CheckoutShippingGroupItem[]` (`{ lineId, quantity? }`) for the review projection. With two or more groups, the review renders one card per group with the selected method, the host-formatted estimate, the per-group price, and the group items; with one group it keeps the compact delivery row and the flat lines list. Group item lists render only when every group item resolves to an order line and every line's quantity is assigned exactly once; otherwise the review falls back to the flat lines list. Prices and estimates are host-supplied and rendered verbatim; the block never sums group prices, allocates the shipping total, or formats dates.
332
+ - `paymentMethods?`, `paymentState?`, `paymentMethod`, `onSelectPaymentMethod`, `onRetryPayment?` — payment methods as data. No raw card fields.
333
+ - `adjustmentPayments?`, `onApplyGiftCard?`, `giftCardState?`, `giftCardMessage?`, `onRemoveAdjustment?`, `storeCredit?` — optional host-wired gift card and store credit. Applied amounts render verbatim; the block never computes a remaining balance.
334
+ - `orderSummary?`, `totalsState?`, `onRetryTotals?`, `promoCode?`, `onPromoCodeChange?`, `onApplyPromo?`, `promoPending?`, `trustNotes?` — backend-authoritative lines and `Money` totals, rendered verbatim. Required totals that are absent or malformed render unavailable, never zero.
335
+ - `labels?`, `formatMoney?`, `fieldErrors?`, `fieldDescriptions?` — every user-facing string is overridable and amounts format through canonical `Money` with no hardcoded symbol. Errors use structured nested maps for `contact`, `shippingAddress`, `billingAddress`, and `paymentMethod`. Delivery-group copy uses `reviewDeliveryGroupsLabel`, `reviewGroupLabel` (`{n}`/`{total}` placeholders), and `reviewGroupItemsLabel`.
336
+ - `validateStep?`, `onStepChange?`, `availability?`, `interruption?`, `onInterruptionAction?`, `submitting?`, `submitError?`, `onRetrySubmit?`, `onSubmit?` — the block consults injected validation before advancing and submitting, renders host-classified availability/interruption states, reports one submission, and never declares success. `onSubmit` receives a `CheckoutSubmission` snapshot.
337
+
338
+ In `single-page`, every visible step begins with a numbered folio heading (`01`,
339
+ `02`, …) and a hairline separator. The number sits in a desktop gutter while the
340
+ heading, description, and fields share one aligned content column; the form stays
341
+ one continuous surface rather than nesting a card for each step. All sections
342
+ remain expanded, so the ordinal communicates sequence without implying that a
343
+ section is complete.
344
+
345
+ The shipping form groups the **recipient** first: `firstName`, `lastName`, `company`, and `phone` sit under `recipientHeading` with `recipientDescription`. These fields identify the person receiving the order, not necessarily the signed-in buyer, and are independent of the `contact` identity. The delivery address follows in this order: `address1` (required, labelled “Address line 1”), `address2` (optional, labelled “Address line 2 (optional)”), `countryCode`, `province`, `city`, and `postalCode`; country therefore sits immediately above state/province. Billing reuses the same fields under its own heading without the recipient legend.
346
+
347
+ Phone labels follow the same copy convention as other checkout fields: optional phones append `optionalIndicatorLabel` (default “optional”), while required phones have no suffix and set `aria-required`. Buyer/contact and recipient/shipping phone requirements are declared independently with `requireContactPhone` and `requireShippingPhone`; the block does not enforce phone presence.
348
+
349
+ Prefill is host-owned. The host reads the authenticated customer's profile and default addresses, fills only empty fields, and never overwrites cart or shopper-entered values; guests receive no customer prefill. The block receives the mapped `customer`, `savedAddresses`, and controlled values and does not fetch or choose defaults.
334
350
 
335
351
  Validation itself is **not** implemented in the block. Declare checks in your store spec's validation configuration (built-in `required`/`email`/`pattern`/`minLength`/`maxLength`/cross-field `requiredIf`/`equalTo`/`lessThan`/`greaterThan`, plus catalog-registered custom functions) and evaluate them with the renderer; the messages live in the spec so they are per-store and per-language.
336
352
 
337
353
  The order summary is an internal projection of `Checkout`, not a separate block. Order receipt and fulfilment progress remain `CheckoutConfirmation`.
338
354
 
339
- ### Migrating from the numbered checkout blocks
355
+ ### Migrating to the structured checkout contract
340
356
 
341
- | Retired | Replacement |
342
- | --- | --- |
343
- | `CheckoutForm1` | `<Checkout presentation="stepper" />` — same controlled values minus `cardNumber`/`expiryDate`/`cvv`/`cardName`/`sameAsBilling`; `validateStep` now receives a `CheckoutStepId` (`'contact' \| 'shipping' \| 'payment' \| 'review'`) instead of a number |
344
- | `CheckoutForm2` | `<Checkout presentation="single-page" />` — the host supplies `Money` totals; the block no longer computes tax, shipping, or free-shipping thresholds |
345
- | `CheckoutForm3` | `<Checkout presentation="stepper" showReviewStep />` — values become controlled; `apartment`, card fields, per-step icons, and internal `isStepComplete` state are gone |
357
+ This is a **breaking major** for `@thorprovider/blocks`. The flat `CheckoutValues` contract is replaced.
358
+
359
+ - Replace `values` + `onChange` with `contact` + `onContactChange`, `shippingAddress` + `onShippingAddressChange`, `billingAddress` + `onBillingAddressChange`, and `sameAsShipping` + `onSameAsShippingChange`.
360
+ - Replace the flat address fields (`address`, `state`, `zipCode`, `country`) with `CheckoutAddressValues` (`address1`, `address2`, `company`, `city`, `province`, `postalCode`, `countryCode`, `phone`).
361
+ - Replace `countries` with `shippingLocations` / `billingLocations`; country, province/state, and city are selectors, never free-text inputs.
362
+ - Replace `shippingOptions` / `selectedShippingOptionId` / `onSelectShippingOption(id)` with `shippingGroups` / `onSelectShippingOption(groupId, optionId)`.
363
+ - Add `customer`, `savedAddresses`, `paymentState`, `shippingState`, `availability`, `interruption`, `fieldErrors`, and the new labels as needed.
364
+ - `validateStep` still receives a `CheckoutStepId` (`'contact' | 'shipping' | 'payment' | 'review'`); `onSubmit` now receives a `CheckoutSubmission` snapshot instead of the flat values.
365
+ - Update the storefront template, showcase consumers, and every fixture in the same change; publish a major changeset.
346
366
 
347
367
 
348
368
  ## Order history (canonical)
@@ -478,6 +498,26 @@ yarn workspace @thorprovider/blocks build # dist/ with .d.ts
478
498
 
479
499
  The `'use client'` banner is injected at build time (tsup `banner`) so the bundled library is consumed correctly by Next.js.
480
500
 
501
+ ## Block audit
502
+
503
+ `audit/` renders a public block directly in Chromium through Vitest Browser Mode
504
+ with a typed fixture. No Next.js app, showcase, storefront, or Storybook is
505
+ required.
506
+
507
+ ```bash
508
+ yarn workspace @thorprovider/blocks audit --block ProductCard
509
+ yarn workspace @thorprovider/blocks workflow status ProductCard
510
+ ```
511
+
512
+ Fixtures live in `audit/fixtures/` and are keyed by the public export name. A
513
+ block without a fixture is reported as unauditable, not silently skipped.
514
+ Findings and screenshots are written to `.blocks-audit/<Block>/` (gitignored).
515
+ The repo-level `blocks-audit` skill documents the audit -> propose -> fix ->
516
+ review workflow, its two approval gates, and the coordinator/worker execution
517
+ contract. Screenshots use a deterministic system font stack and are
518
+ illustrative; pixel baselines and the committed accepted-findings baseline are
519
+ deferred. The pilot is report-only.
520
+
481
521
  ## Adding a new block
482
522
 
483
523
  1. Install the raw block as a seed: `npx shadcn@latest add @shadcnstore/<block> --cwd packages/blocks`
@@ -0,0 +1,49 @@
1
+ import type { CheckoutCommerceV1Data } from '../../../lib/contracts/checkout-commerce-v1';
2
+ type AssociatePayload = {
3
+ associateId: string;
4
+ parentLineId: string;
5
+ lineId: string;
6
+ groupId: string;
7
+ quantity: number;
8
+ unitCents: number;
9
+ };
10
+ type AddressData = {
11
+ id: string;
12
+ label: string;
13
+ recipient: string;
14
+ line1: string;
15
+ line2: string;
16
+ city: string;
17
+ province: string;
18
+ postalCode: string;
19
+ phone: string;
20
+ isDefault: boolean;
21
+ };
22
+ type CreatedAddressPayload = AddressData & {
23
+ saveToAccount: boolean;
24
+ };
25
+ type GuestContact = {
26
+ name: string;
27
+ email: string;
28
+ phone: string;
29
+ };
30
+ type OrderSnapshot = {
31
+ reference: string;
32
+ totalCents: number;
33
+ paymentId: string;
34
+ groupIds: string[];
35
+ };
36
+ export type CheckoutCommerceV1Props = {
37
+ data: CheckoutCommerceV1Data;
38
+ onQuantityChange?: (lineId: string, quantity: number) => void;
39
+ onRemoveItem?: (lineId: string) => void;
40
+ onSelectAddress?: (addressId: string) => void;
41
+ onCreateAddress?: (payload: CreatedAddressPayload) => void;
42
+ onStartRegistration?: (contact: GuestContact) => void;
43
+ onAddAssociate?: (payload: AssociatePayload) => void;
44
+ onConfirmOrder?: (snapshot: OrderSnapshot) => void;
45
+ onContinueShopping?: () => void;
46
+ };
47
+ export default function CheckoutCommerceV1({ data, ...props }: CheckoutCommerceV1Props): import("react").JSX.Element;
48
+ export {};
49
+ //# sourceMappingURL=block.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"block.d.ts","sourceRoot":"","sources":["../../../../src/blocks/designs/checkout-commerce-v1/block.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,6CAA6C,CAAA;AAwBzF,KAAK,gBAAgB,GAAG;IACtB,WAAW,EAAE,MAAM,CAAA;IACnB,YAAY,EAAE,MAAM,CAAA;IACpB,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,KAAK,WAAW,GAAG;IACjB,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;IAClB,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,OAAO,CAAA;CACnB,CAAA;AAiCD,KAAK,qBAAqB,GAAG,WAAW,GAAG;IAAE,aAAa,EAAE,OAAO,CAAA;CAAE,CAAA;AAErE,KAAK,YAAY,GAAG;IAClB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAED,KAAK,aAAa,GAAG;IACnB,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAA;CACnB,CAAA;AAkCD,MAAM,MAAM,uBAAuB,GAAG;IACpC,IAAI,EAAE,sBAAsB,CAAC;IAC7B,gBAAgB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAA;IAC7D,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAA;IACvC,eAAe,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAA;IAC7C,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,qBAAqB,KAAK,IAAI,CAAA;IAC1D,mBAAmB,CAAC,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,IAAI,CAAA;IACrD,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,IAAI,CAAA;IACpD,cAAc,CAAC,EAAE,CAAC,QAAQ,EAAE,aAAa,KAAK,IAAI,CAAA;IAClD,kBAAkB,CAAC,EAAE,MAAM,IAAI,CAAA;CAChC,CAAA;AAugGD,MAAM,CAAC,OAAO,UAAU,kBAAkB,CAAC,EAAE,IAAI,EAAE,GAAG,KAAK,EAAE,EAAE,uBAAuB,+BAMrF"}