@vtex/faststore 0.0.7 → 0.0.10

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 (498) hide show
  1. package/CHANGELOG.md +102 -0
  2. package/dist/actions.json +194 -1
  3. package/dist/catalog.json +3449 -1612
  4. package/dist/cli/index.d.ts +512 -63
  5. package/dist/cli/index.js +2098 -686
  6. package/dist/cli/index.js.map +1 -1
  7. package/dist/cli/server-runtime.js +44 -24
  8. package/dist/cli/server-runtime.js.map +1 -1
  9. package/dist/client.d.ts +5 -1
  10. package/dist/client.js +5 -1
  11. package/dist/components.d.ts +42 -10
  12. package/dist/components.js +47 -15
  13. package/dist/content-types.json +823 -0
  14. package/dist/core/dist/define-component.d.ts +12 -2
  15. package/dist/docs/account-access-gate.md +4 -4
  16. package/dist/docs/account-address-book.md +519 -0
  17. package/dist/docs/account-entry-point.md +5 -5
  18. package/dist/docs/account-menu.md +7 -7
  19. package/dist/docs/account-saved-cards.md +301 -0
  20. package/dist/docs/alert-dialog.md +2 -2
  21. package/dist/docs/billing-address.md +17 -9
  22. package/dist/docs/binding-switcher.md +154 -0
  23. package/dist/docs/card-entry.md +38 -7
  24. package/dist/docs/card-summary.md +175 -0
  25. package/dist/docs/cardholder-document.md +16 -14
  26. package/dist/docs/cart-destination.md +238 -0
  27. package/dist/docs/cart-item.md +22 -4
  28. package/dist/docs/cart-totalizer.md +1 -1
  29. package/dist/docs/cart.md +126 -19
  30. package/dist/docs/client-profile-fieldset.md +7 -5
  31. package/dist/docs/copy-text.md +84 -0
  32. package/dist/docs/document-field.md +8 -8
  33. package/dist/docs/footer-link-group.md +2 -2
  34. package/dist/docs/footer-social.md +1 -1
  35. package/dist/docs/free-shipping-progress.md +13 -9
  36. package/dist/docs/header-root.md +1 -1
  37. package/dist/docs/incentives.md +4 -4
  38. package/dist/docs/logo.md +6 -6
  39. package/dist/docs/my-account-profile.md +4 -4
  40. package/dist/docs/navigation-link-list.md +2 -2
  41. package/dist/docs/navigation-link.md +3 -3
  42. package/dist/docs/order-cancel.md +52 -0
  43. package/dist/docs/order-delivery-address.md +63 -0
  44. package/dist/docs/order-delivery-group.md +83 -0
  45. package/dist/docs/order-details-back.md +41 -0
  46. package/dist/docs/order-details-header.md +48 -0
  47. package/dist/docs/order-list-row.md +46 -0
  48. package/dist/docs/order-list-search.md +101 -0
  49. package/dist/docs/order-list-views.md +97 -0
  50. package/dist/docs/order-list.md +94 -0
  51. package/dist/docs/order-payment.md +94 -0
  52. package/dist/docs/order-placed-date.md +49 -0
  53. package/dist/docs/order-placed-payment-summary.md +13 -15
  54. package/dist/docs/order-placed.md +225 -0
  55. package/dist/docs/order-progress.md +88 -0
  56. package/dist/docs/order-status-badge.md +91 -0
  57. package/dist/docs/order-summary.md +53 -0
  58. package/dist/docs/payment-method-badges.md +16 -5
  59. package/dist/docs/payment-methods.md +1 -1
  60. package/dist/docs/place-order.md +13 -9
  61. package/dist/docs/product-information.md +2 -2
  62. package/dist/docs/product-shelf.md +7 -0
  63. package/dist/docs/saved-cards.md +2 -2
  64. package/dist/docs/select.md +22 -10
  65. package/dist/docs/session.md +1 -1
  66. package/dist/docs/shipping-address.md +1 -1
  67. package/dist/docs/sign-in-redirect.md +7 -7
  68. package/dist/docs/toast.md +35 -13
  69. package/dist/index.d.ts +7 -2
  70. package/dist/index.js +2 -1
  71. package/dist/internal/client.d.ts +9 -1
  72. package/dist/internal/client.js +10 -2
  73. package/dist/internal/server.d.ts +8 -2
  74. package/dist/internal/server.js +8 -2
  75. package/dist/matter/account-access-gate/account-access-gate.d.ts +2 -1
  76. package/dist/matter/account-access-gate/account-access-gate.js +19 -16
  77. package/dist/matter/account-access-gate/account-access-gate.js.map +1 -1
  78. package/dist/matter/account-address-book/account-address-book-delete.d.ts +60 -0
  79. package/dist/matter/account-address-book/account-address-book-delete.js +184 -0
  80. package/dist/matter/account-address-book/account-address-book-delete.js.map +1 -0
  81. package/dist/matter/account-address-book/account-address-book-deliverability.d.ts +19 -0
  82. package/dist/matter/account-address-book/account-address-book-deliverability.js +50 -0
  83. package/dist/matter/account-address-book/account-address-book-deliverability.js.map +1 -0
  84. package/dist/matter/account-address-book/account-address-book-form-parts.d.ts +42 -0
  85. package/dist/matter/account-address-book/account-address-book-form-parts.js +146 -0
  86. package/dist/matter/account-address-book/account-address-book-form-parts.js.map +1 -0
  87. package/dist/matter/account-address-book/account-address-book-profile-notice.d.ts +25 -0
  88. package/dist/matter/account-address-book/account-address-book-profile-notice.js +72 -0
  89. package/dist/matter/account-address-book/account-address-book-profile-notice.js.map +1 -0
  90. package/dist/matter/account-address-book/account-address-book.d.ts +120 -0
  91. package/dist/matter/account-address-book/account-address-book.js +469 -0
  92. package/dist/matter/account-address-book/account-address-book.js.map +1 -0
  93. package/dist/matter/account-address-book/account-address-country-switch.js +59 -0
  94. package/dist/matter/account-address-book/account-address-country-switch.js.map +1 -0
  95. package/dist/matter/account-address-book/account-address-country.d.ts +36 -0
  96. package/dist/matter/account-address-book/account-address-country.js +151 -0
  97. package/dist/matter/account-address-book/account-address-country.js.map +1 -0
  98. package/dist/matter/account-address-book/account-address-first-line.js +11 -0
  99. package/dist/matter/account-address-book/account-address-first-line.js.map +1 -0
  100. package/dist/matter/account-address-book/account-address-form-context.d.ts +55 -0
  101. package/dist/matter/account-address-book/account-address-form-context.js +14 -0
  102. package/dist/matter/account-address-book/account-address-form-context.js.map +1 -0
  103. package/dist/matter/account-address-book/account-address-form.d.ts +85 -0
  104. package/dist/matter/account-address-book/account-address-form.js +946 -0
  105. package/dist/matter/account-address-book/account-address-form.js.map +1 -0
  106. package/dist/matter/account-address-book/account-address-postal-autofill.js +189 -0
  107. package/dist/matter/account-address-book/account-address-postal-autofill.js.map +1 -0
  108. package/dist/matter/account-address-book/account-address-record.d.ts +26 -0
  109. package/dist/matter/account-address-book/account-address-record.js +138 -0
  110. package/dist/matter/account-address-book/account-address-record.js.map +1 -0
  111. package/dist/matter/account-entry-point/account-entry-point.js +11 -11
  112. package/dist/matter/account-entry-point/account-entry-point.js.map +1 -1
  113. package/dist/matter/account-menu/account-menu.d.ts +7 -3
  114. package/dist/matter/account-menu/account-menu.js +69 -28
  115. package/dist/matter/account-menu/account-menu.js.map +1 -1
  116. package/dist/matter/account-saved-cards/account-saved-cards.d.ts +383 -0
  117. package/dist/matter/account-saved-cards/account-saved-cards.js +956 -0
  118. package/dist/matter/account-saved-cards/account-saved-cards.js.map +1 -0
  119. package/dist/matter/billing-address/billing-address.d.ts +30 -17
  120. package/dist/matter/billing-address/billing-address.js +128 -33
  121. package/dist/matter/billing-address/billing-address.js.map +1 -1
  122. package/dist/matter/breadcrumb/breadcrumb.js +2 -2
  123. package/dist/matter/breadcrumb/breadcrumb.js.map +1 -1
  124. package/dist/matter/card-entry/card-capture.js +4 -3
  125. package/dist/matter/card-entry/card-capture.js.map +1 -1
  126. package/dist/matter/card-entry/card-entry.d.ts +5 -3
  127. package/dist/matter/card-entry/card-entry.js +77 -27
  128. package/dist/matter/card-entry/card-entry.js.map +1 -1
  129. package/dist/matter/cardholder-document/cardholder-document.d.ts +10 -9
  130. package/dist/matter/cardholder-document/cardholder-document.js +36 -16
  131. package/dist/matter/cardholder-document/cardholder-document.js.map +1 -1
  132. package/dist/matter/cart/cart-namespace.d.ts +5 -1
  133. package/dist/matter/cart/cart-namespace.js +5 -1
  134. package/dist/matter/cart/cart-namespace.js.map +1 -1
  135. package/dist/matter/cart/cart.d.ts +41 -6
  136. package/dist/matter/cart/cart.js +267 -54
  137. package/dist/matter/cart/cart.js.map +1 -1
  138. package/dist/matter/cart-destination/cart-destination.d.ts +222 -0
  139. package/dist/matter/cart-destination/cart-destination.js +613 -0
  140. package/dist/matter/cart-destination/cart-destination.js.map +1 -0
  141. package/dist/matter/cart-item/cart-item.d.ts +4 -2
  142. package/dist/matter/cart-item/cart-item.js +76 -17
  143. package/dist/matter/cart-item/cart-item.js.map +1 -1
  144. package/dist/matter/cart-totalizer/cart-totalizer.js +3 -2
  145. package/dist/matter/cart-totalizer/cart-totalizer.js.map +1 -1
  146. package/dist/matter/client-preferences/client-preferences-fieldset.js +1 -1
  147. package/dist/matter/client-profile-form/client-profile-fieldset.js +8 -5
  148. package/dist/matter/client-profile-form/client-profile-fieldset.js.map +1 -1
  149. package/dist/matter/free-shipping-progress/free-shipping-progress.d.ts +6 -3
  150. package/dist/matter/free-shipping-progress/free-shipping-progress.js +76 -33
  151. package/dist/matter/free-shipping-progress/free-shipping-progress.js.map +1 -1
  152. package/dist/matter/identity-edit/identity-edit.js +3 -3
  153. package/dist/matter/identity-edit/identity-edit.js.map +1 -1
  154. package/dist/matter/identity-summary/identity-summary.js +2 -2
  155. package/dist/matter/identity-summary/identity-summary.js.map +1 -1
  156. package/dist/matter/my-account-profile/my-account-profile.d.ts +3 -3
  157. package/dist/matter/my-account-profile/my-account-profile.js +4 -4
  158. package/dist/matter/my-account-profile/my-account-profile.js.map +1 -1
  159. package/dist/matter/order-cancel/order-cancel.d.ts +110 -0
  160. package/dist/matter/order-cancel/order-cancel.js +344 -0
  161. package/dist/matter/order-cancel/order-cancel.js.map +1 -0
  162. package/dist/matter/order-delivery-address/order-delivery-address.d.ts +73 -0
  163. package/dist/matter/order-delivery-address/order-delivery-address.js +172 -0
  164. package/dist/matter/order-delivery-address/order-delivery-address.js.map +1 -0
  165. package/dist/matter/order-delivery-group/order-delivery-group.d.ts +128 -0
  166. package/dist/matter/order-delivery-group/order-delivery-group.js +408 -0
  167. package/dist/matter/order-delivery-group/order-delivery-group.js.map +1 -0
  168. package/dist/matter/order-details-header/order-details-header.d.ts +104 -0
  169. package/dist/matter/order-details-header/order-details-header.js +190 -0
  170. package/dist/matter/order-details-header/order-details-header.js.map +1 -0
  171. package/dist/matter/order-list/customer-orders-filter.d.ts +12 -0
  172. package/dist/matter/order-list/customer-orders-filter.js +30 -0
  173. package/dist/matter/order-list/customer-orders-filter.js.map +1 -0
  174. package/dist/matter/order-list/order-list.d.ts +121 -0
  175. package/dist/matter/order-list/order-list.js +395 -0
  176. package/dist/matter/order-list/order-list.js.map +1 -0
  177. package/dist/matter/order-list-row/order-list-row.d.ts +44 -0
  178. package/dist/matter/order-list-row/order-list-row.js +127 -0
  179. package/dist/matter/order-list-row/order-list-row.js.map +1 -0
  180. package/dist/matter/order-list-search/order-list-search.d.ts +72 -0
  181. package/dist/matter/order-list-search/order-list-search.js +296 -0
  182. package/dist/matter/order-list-search/order-list-search.js.map +1 -0
  183. package/dist/matter/order-list-views/order-list-views.d.ts +65 -0
  184. package/dist/matter/order-list-views/order-list-views.js +154 -0
  185. package/dist/matter/order-list-views/order-list-views.js.map +1 -0
  186. package/dist/matter/order-payment/order-payment.d.ts +83 -0
  187. package/dist/matter/order-payment/order-payment.js +258 -0
  188. package/dist/matter/order-payment/order-payment.js.map +1 -0
  189. package/dist/matter/order-placed/order-placed-deliveries.d.ts +145 -0
  190. package/dist/matter/order-placed/order-placed-deliveries.js +380 -0
  191. package/dist/matter/order-placed/order-placed-deliveries.js.map +1 -0
  192. package/dist/matter/order-placed/order-placed.d.ts +122 -0
  193. package/dist/matter/order-placed/order-placed.js +452 -0
  194. package/dist/matter/order-placed/order-placed.js.map +1 -0
  195. package/dist/matter/order-placed-date/order-placed-date.d.ts +45 -0
  196. package/dist/matter/order-placed-date/order-placed-date.js +92 -0
  197. package/dist/matter/order-placed-date/order-placed-date.js.map +1 -0
  198. package/dist/matter/order-placed-payment-summary/order-placed-payment-summary.d.ts +5 -8
  199. package/dist/matter/order-placed-payment-summary/order-placed-payment-summary.js +29 -81
  200. package/dist/matter/order-placed-payment-summary/order-placed-payment-summary.js.map +1 -1
  201. package/dist/matter/order-progress/order-progress.d.ts +85 -0
  202. package/dist/matter/order-progress/order-progress.js +203 -0
  203. package/dist/matter/order-progress/order-progress.js.map +1 -0
  204. package/dist/matter/order-summary/order-summary.d.ts +81 -0
  205. package/dist/matter/order-summary/order-summary.js +192 -0
  206. package/dist/matter/order-summary/order-summary.js.map +1 -0
  207. package/dist/matter/payment/cardholder-document-rule.d.ts +35 -0
  208. package/dist/matter/payment/cardholder-document-rule.js +35 -0
  209. package/dist/matter/payment/cardholder-document-rule.js.map +1 -0
  210. package/dist/matter/payment/payment-card-capture.js +38 -23
  211. package/dist/matter/payment/payment-card-capture.js.map +1 -1
  212. package/dist/matter/payment/payment-controller.js +11 -0
  213. package/dist/matter/payment/payment-controller.js.map +1 -1
  214. package/dist/matter/payment/payment-method-badges.js +4 -2
  215. package/dist/matter/payment/payment-method-badges.js.map +1 -1
  216. package/dist/matter/payment/payment.js +11 -0
  217. package/dist/matter/payment/payment.js.map +1 -1
  218. package/dist/matter/payment/use-payment-method-selection.d.ts +39 -0
  219. package/dist/matter/payment/use-payment-method-selection.js +30 -2
  220. package/dist/matter/payment/use-payment-method-selection.js.map +1 -1
  221. package/dist/matter/payment/use-payment-submit-gate.d.ts +16 -2
  222. package/dist/matter/payment/use-payment-submit-gate.js +42 -14
  223. package/dist/matter/payment/use-payment-submit-gate.js.map +1 -1
  224. package/dist/matter/place-order/place-order.d.ts +12 -7
  225. package/dist/matter/place-order/place-order.js +126 -103
  226. package/dist/matter/place-order/place-order.js.map +1 -1
  227. package/dist/matter/pricing/pricing.js +5 -5
  228. package/dist/matter/pricing/pricing.js.map +1 -1
  229. package/dist/matter/product-shelf/product-shelf.d.ts +7 -0
  230. package/dist/matter/product-shelf/product-shelf.js +115 -1
  231. package/dist/matter/product-shelf/product-shelf.js.map +1 -1
  232. package/dist/matter/region/region.js +1 -1
  233. package/dist/matter/saved-cards/saved-cards.js +26 -15
  234. package/dist/matter/saved-cards/saved-cards.js.map +1 -1
  235. package/dist/matter/session/session.js +2 -2
  236. package/dist/matter/session/session.js.map +1 -1
  237. package/dist/matter/shipping-address/country-descriptors.d.ts +1 -0
  238. package/dist/matter/shipping-address/country-descriptors.js +23 -1
  239. package/dist/matter/shipping-address/country-descriptors.js.map +1 -1
  240. package/dist/matter/shipping-address/shipping-address.js +62 -14
  241. package/dist/matter/shipping-address/shipping-address.js.map +1 -1
  242. package/dist/matter/shipping-simulator/shipping-simulator.d.ts +2 -2
  243. package/dist/matter/shipping-simulator/shipping-simulator.js +6 -2
  244. package/dist/matter/shipping-simulator/shipping-simulator.js.map +1 -1
  245. package/dist/matter/sign-in-redirect/sign-in-redirect.js +48 -10
  246. package/dist/matter/sign-in-redirect/sign-in-redirect.js.map +1 -1
  247. package/dist/matter/variant-selector/variant-selector.js +2 -2
  248. package/dist/matter/variant-selector/variant-selector.js.map +1 -1
  249. package/dist/particles/address-summary/address-summary.js +2 -2
  250. package/dist/particles/address-summary/address-summary.js.map +1 -1
  251. package/dist/particles/alert-dialog/alert-dialog.d.ts +5 -1
  252. package/dist/particles/alert-dialog/alert-dialog.js +5 -2
  253. package/dist/particles/alert-dialog/alert-dialog.js.map +1 -1
  254. package/dist/particles/binding-switcher/binding-switcher.d.ts +38 -0
  255. package/dist/particles/binding-switcher/binding-switcher.js +183 -0
  256. package/dist/particles/binding-switcher/binding-switcher.js.map +1 -0
  257. package/dist/particles/card-summary/card-network.d.ts +17 -0
  258. package/dist/particles/card-summary/card-network.js +25 -0
  259. package/dist/particles/card-summary/card-network.js.map +1 -0
  260. package/dist/particles/card-summary/card-summary.d.ts +83 -0
  261. package/dist/particles/card-summary/card-summary.js +188 -0
  262. package/dist/particles/card-summary/card-summary.js.map +1 -0
  263. package/dist/particles/copy-text/copy-text.d.ts +28 -0
  264. package/dist/particles/copy-text/copy-text.js +140 -0
  265. package/dist/particles/copy-text/copy-text.js.map +1 -0
  266. package/dist/particles/document-field/document-field.d.ts +34 -5
  267. package/dist/particles/document-field/document-field.js +115 -19
  268. package/dist/particles/document-field/document-field.js.map +1 -1
  269. package/dist/particles/field/field.js +1 -1
  270. package/dist/particles/field/field.js.map +1 -1
  271. package/dist/particles/footer-link-group/footer-link-group.d.ts +6 -2
  272. package/dist/particles/footer-link-group/footer-link-group.js +18 -7
  273. package/dist/particles/footer-link-group/footer-link-group.js.map +1 -1
  274. package/dist/particles/footer-social/footer-social.d.ts +1 -1
  275. package/dist/particles/footer-social/footer-social.js +1 -1
  276. package/dist/particles/footer-social/footer-social.js.map +1 -1
  277. package/dist/particles/incentives/incentives.d.ts +7 -3
  278. package/dist/particles/incentives/incentives.js +8 -3
  279. package/dist/particles/incentives/incentives.js.map +1 -1
  280. package/dist/particles/logo/logo.d.ts +3 -2
  281. package/dist/particles/logo/logo.js +20 -8
  282. package/dist/particles/logo/logo.js.map +1 -1
  283. package/dist/particles/navigation-link/navigation-link.d.ts +2 -3
  284. package/dist/particles/navigation-link/navigation-link.js +4 -4
  285. package/dist/particles/navigation-link/navigation-link.js.map +1 -1
  286. package/dist/particles/navigation-link-list/navigation-link-list.d.ts +6 -2
  287. package/dist/particles/navigation-link-list/navigation-link-list.js +18 -7
  288. package/dist/particles/navigation-link-list/navigation-link-list.js.map +1 -1
  289. package/dist/particles/order-details-back/order-details-back.d.ts +28 -0
  290. package/dist/particles/order-details-back/order-details-back.js +52 -0
  291. package/dist/particles/order-details-back/order-details-back.js.map +1 -0
  292. package/dist/particles/order-status-badge/order-status-badge.d.ts +19 -0
  293. package/dist/particles/order-status-badge/order-status-badge.js +50 -0
  294. package/dist/particles/order-status-badge/order-status-badge.js.map +1 -0
  295. package/dist/particles/payment-methods/payment-methods.d.ts +1 -1
  296. package/dist/particles/payment-methods/payment-methods.js +1 -1
  297. package/dist/particles/payment-methods/payment-methods.js.map +1 -1
  298. package/dist/particles/phone-field/phone-field.js +2 -2
  299. package/dist/particles/phone-field/phone-field.js.map +1 -1
  300. package/dist/particles/select/select.js +6 -6
  301. package/dist/particles/select/select.js.map +1 -1
  302. package/dist/particles/toast/toast.d.ts +21 -7
  303. package/dist/particles/toast/toast.js +76 -8
  304. package/dist/particles/toast/toast.js.map +1 -1
  305. package/dist/schema.graphql +1376 -126
  306. package/dist/sdk/actions/address-action-provider.d.ts +16 -0
  307. package/dist/sdk/actions/address-action-provider.js +20 -0
  308. package/dist/sdk/actions/address-action-provider.js.map +1 -0
  309. package/dist/sdk/actions/analytics-action-provider.js +1 -1
  310. package/dist/sdk/actions/index.d.ts +5 -1
  311. package/dist/sdk/actions/index.js +5 -1
  312. package/dist/sdk/actions/locale-action-provider.d.ts +16 -0
  313. package/dist/sdk/actions/locale-action-provider.js +20 -0
  314. package/dist/sdk/actions/locale-action-provider.js.map +1 -0
  315. package/dist/sdk/actions/order-action-provider.d.ts +12 -0
  316. package/dist/sdk/actions/order-action-provider.js +16 -0
  317. package/dist/sdk/actions/order-action-provider.js.map +1 -0
  318. package/dist/sdk/actions/saved-card-action-provider.d.ts +12 -0
  319. package/dist/sdk/actions/saved-card-action-provider.js +16 -0
  320. package/dist/sdk/actions/saved-card-action-provider.js.map +1 -0
  321. package/dist/sdk/actions/types.d.ts +10 -2
  322. package/dist/sdk/address/address-fields.js +38 -0
  323. package/dist/sdk/address/address-fields.js.map +1 -0
  324. package/dist/sdk/address/checkout-readiness.js +17 -0
  325. package/dist/sdk/address/checkout-readiness.js.map +1 -0
  326. package/dist/sdk/address/constants.js +60 -0
  327. package/dist/sdk/address/constants.js.map +1 -0
  328. package/dist/sdk/address/country-display.js +19 -0
  329. package/dist/sdk/address/country-display.js.map +1 -0
  330. package/dist/sdk/address/country-rules.js +30 -0
  331. package/dist/sdk/address/country-rules.js.map +1 -0
  332. package/dist/sdk/address/format-address.js +18 -0
  333. package/dist/sdk/address/format-address.js.map +1 -0
  334. package/dist/sdk/address/iso-countries.js +262 -0
  335. package/dist/sdk/address/iso-countries.js.map +1 -0
  336. package/dist/sdk/address/layouts.js +56 -0
  337. package/dist/sdk/address/layouts.js.map +1 -0
  338. package/dist/sdk/address/messages.js +97 -0
  339. package/dist/sdk/address/messages.js.map +1 -0
  340. package/dist/sdk/address/operations.d.ts +54 -0
  341. package/dist/sdk/address/operations.js +83 -0
  342. package/dist/sdk/address/operations.js.map +1 -0
  343. package/dist/sdk/address/postal-code-lookup-operations.js +23 -0
  344. package/dist/sdk/address/postal-code-lookup-operations.js.map +1 -0
  345. package/dist/sdk/address/postal-code.js +11 -0
  346. package/dist/sdk/address/postal-code.js.map +1 -0
  347. package/dist/sdk/address/schema.js +14 -0
  348. package/dist/sdk/address/schema.js.map +1 -0
  349. package/dist/sdk/address/server-fields.js +25 -0
  350. package/dist/sdk/address/server-fields.js.map +1 -0
  351. package/dist/sdk/address/switch-country.js +57 -0
  352. package/dist/sdk/address/switch-country.js.map +1 -0
  353. package/dist/sdk/address/types.d.ts +26 -0
  354. package/dist/sdk/address/use-address-actions.d.ts +29 -0
  355. package/dist/sdk/address/use-address-actions.js +247 -0
  356. package/dist/sdk/address/use-address-actions.js.map +1 -0
  357. package/dist/sdk/address/use-address-by-postal-code.js +57 -0
  358. package/dist/sdk/address/use-address-by-postal-code.js.map +1 -0
  359. package/dist/sdk/address/validate-address.js +62 -0
  360. package/dist/sdk/address/validate-address.js.map +1 -0
  361. package/dist/sdk/cache/storefront-cache.js +30 -4
  362. package/dist/sdk/cache/storefront-cache.js.map +1 -1
  363. package/dist/sdk/cart/operations.d.ts +2 -1
  364. package/dist/sdk/cart/operations.js +55 -1
  365. package/dist/sdk/cart/operations.js.map +1 -1
  366. package/dist/sdk/cart/optimistic.d.ts +30 -7
  367. package/dist/sdk/cart/optimistic.js +78 -41
  368. package/dist/sdk/cart/optimistic.js.map +1 -1
  369. package/dist/sdk/cart/use-cart-actions.d.ts +7 -0
  370. package/dist/sdk/cart/use-cart-actions.js +61 -15
  371. package/dist/sdk/cart/use-cart-actions.js.map +1 -1
  372. package/dist/sdk/cart/use-cart-sync-sales-channel.js +70 -0
  373. package/dist/sdk/cart/use-cart-sync-sales-channel.js.map +1 -0
  374. package/dist/sdk/client/fetch-page-data.d.ts +11 -0
  375. package/dist/sdk/client/fetch-page-data.js +12 -1
  376. package/dist/sdk/client/fetch-page-data.js.map +1 -1
  377. package/dist/sdk/content/create-content-runtime.js +1 -8
  378. package/dist/sdk/content/create-content-runtime.js.map +1 -1
  379. package/dist/sdk/data/failed-fields.js +23 -0
  380. package/dist/sdk/data/failed-fields.js.map +1 -0
  381. package/dist/sdk/data/index.js +2 -2
  382. package/dist/sdk/data/page-reactive-data-root.d.ts +45 -7
  383. package/dist/sdk/data/page-reactive-data-root.js +88 -12
  384. package/dist/sdk/data/page-reactive-data-root.js.map +1 -1
  385. package/dist/sdk/data/reactive-list-item-data-provider.js +2 -2
  386. package/dist/sdk/generated/fragment-types.js +2 -0
  387. package/dist/sdk/generated/fragment-types.js.map +1 -1
  388. package/dist/sdk/generated/gql.js +17 -11
  389. package/dist/sdk/generated/gql.js.map +1 -1
  390. package/dist/sdk/generated/graphql.d.ts +185 -46
  391. package/dist/sdk/generated/graphql.js +2587 -155
  392. package/dist/sdk/generated/graphql.js.map +1 -1
  393. package/dist/sdk/i18n/messages/en-US.js +157 -1
  394. package/dist/sdk/i18n/messages/en-US.json +157 -1
  395. package/dist/sdk/i18n/messages/en-US.json.d.ts +156 -0
  396. package/dist/sdk/i18n/messages/es-ES.js +157 -1
  397. package/dist/sdk/i18n/messages/es-ES.json +157 -1
  398. package/dist/sdk/i18n/messages/pt-BR.js +157 -1
  399. package/dist/sdk/i18n/messages/pt-BR.json +157 -1
  400. package/dist/sdk/i18n/provider.js +1 -1
  401. package/dist/sdk/i18n/provider.js.map +1 -1
  402. package/dist/sdk/locale/binding-switch-provider.d.ts +13 -0
  403. package/dist/sdk/locale/binding-switch-provider.js +20 -0
  404. package/dist/sdk/locale/binding-switch-provider.js.map +1 -0
  405. package/dist/sdk/locale/use-locale-actions.d.ts +16 -0
  406. package/dist/sdk/locale/use-locale-actions.js +70 -0
  407. package/dist/sdk/locale/use-locale-actions.js.map +1 -0
  408. package/dist/sdk/navigation/binding-switch.d.ts +39 -0
  409. package/dist/sdk/navigation/binding-switch.js +129 -0
  410. package/dist/sdk/navigation/binding-switch.js.map +1 -0
  411. package/dist/sdk/navigation/current-page.js +30 -0
  412. package/dist/sdk/navigation/current-page.js.map +1 -0
  413. package/dist/sdk/navigation/decode-route-params.d.ts +11 -0
  414. package/dist/sdk/navigation/decode-route-params.js +32 -0
  415. package/dist/sdk/navigation/decode-route-params.js.map +1 -0
  416. package/dist/sdk/navigation/not-found-log.d.ts +28 -0
  417. package/dist/sdk/navigation/not-found-log.js +133 -0
  418. package/dist/sdk/navigation/not-found-log.js.map +1 -0
  419. package/dist/sdk/navigation/path.js +25 -0
  420. package/dist/sdk/navigation/path.js.map +1 -0
  421. package/dist/sdk/navigation/redirect.d.ts +11 -0
  422. package/dist/sdk/navigation/redirect.js +22 -0
  423. package/dist/sdk/navigation/redirect.js.map +1 -0
  424. package/dist/sdk/navigation/report.js +70 -0
  425. package/dist/sdk/navigation/report.js.map +1 -0
  426. package/dist/sdk/navigation/resolve-storefront-href.d.ts +12 -0
  427. package/dist/sdk/navigation/resolve-storefront-href.js +214 -0
  428. package/dist/sdk/navigation/resolve-storefront-href.js.map +1 -0
  429. package/dist/sdk/navigation/route-identity-provider.d.ts +11 -0
  430. package/dist/sdk/navigation/route-identity-provider.js +20 -0
  431. package/dist/sdk/navigation/route-identity-provider.js.map +1 -0
  432. package/dist/sdk/navigation/route-map-provider.d.ts +19 -0
  433. package/dist/sdk/navigation/route-map-provider.js +29 -0
  434. package/dist/sdk/navigation/route-map-provider.js.map +1 -0
  435. package/dist/sdk/navigation/storefront-link.d.ts +16 -0
  436. package/dist/sdk/navigation/storefront-link.js +66 -0
  437. package/dist/sdk/navigation/storefront-link.js.map +1 -0
  438. package/dist/sdk/navigation/types.d.ts +45 -0
  439. package/dist/sdk/navigation/use-storefront-navigation.d.ts +26 -0
  440. package/dist/sdk/navigation/use-storefront-navigation.js +73 -0
  441. package/dist/sdk/navigation/use-storefront-navigation.js.map +1 -0
  442. package/dist/sdk/navigation/use-storefront-route.d.ts +26 -0
  443. package/dist/sdk/navigation/use-storefront-route.js +87 -0
  444. package/dist/sdk/navigation/use-storefront-route.js.map +1 -0
  445. package/dist/sdk/navigation/use-storefront-search-params.d.ts +11 -0
  446. package/dist/sdk/navigation/use-storefront-search-params.js +16 -0
  447. package/dist/sdk/navigation/use-storefront-search-params.js.map +1 -0
  448. package/dist/sdk/orders/completion-badge.d.ts +8 -0
  449. package/dist/sdk/orders/completion-badge.js +47 -0
  450. package/dist/sdk/orders/completion-badge.js.map +1 -0
  451. package/dist/sdk/orders/order-operations.d.ts +19 -0
  452. package/dist/sdk/orders/order-operations.js +21 -0
  453. package/dist/sdk/orders/order-operations.js.map +1 -0
  454. package/dist/sdk/orders/use-order-actions.d.ts +23 -0
  455. package/dist/sdk/orders/use-order-actions.js +62 -0
  456. package/dist/sdk/orders/use-order-actions.js.map +1 -0
  457. package/dist/sdk/payment/gateway-origin.js +26 -13
  458. package/dist/sdk/payment/gateway-origin.js.map +1 -1
  459. package/dist/sdk/payment/gateway.d.ts +14 -2
  460. package/dist/sdk/payment/gateway.js +32 -14
  461. package/dist/sdk/payment/gateway.js.map +1 -1
  462. package/dist/sdk/payment/operations.js +11 -0
  463. package/dist/sdk/payment/operations.js.map +1 -1
  464. package/dist/sdk/payment/submission-registry.d.ts +2 -1
  465. package/dist/sdk/payment/submission-registry.js +12 -8
  466. package/dist/sdk/payment/submission-registry.js.map +1 -1
  467. package/dist/sdk/payment/use-payment-actions.d.ts +5 -3
  468. package/dist/sdk/payment/use-payment-actions.js +5 -2
  469. package/dist/sdk/payment/use-payment-actions.js.map +1 -1
  470. package/dist/sdk/payment/use-place-order.d.ts +6 -3
  471. package/dist/sdk/payment/use-place-order.js +333 -143
  472. package/dist/sdk/payment/use-place-order.js.map +1 -1
  473. package/dist/sdk/saved-cards/operations.d.ts +16 -0
  474. package/dist/sdk/saved-cards/operations.js +41 -0
  475. package/dist/sdk/saved-cards/operations.js.map +1 -0
  476. package/dist/sdk/saved-cards/use-saved-card-actions.d.ts +26 -0
  477. package/dist/sdk/saved-cards/use-saved-card-actions.js +86 -0
  478. package/dist/sdk/saved-cards/use-saved-card-actions.js.map +1 -0
  479. package/dist/sdk/seo/page-alternates.d.ts +57 -0
  480. package/dist/sdk/seo/page-alternates.js +127 -0
  481. package/dist/sdk/seo/page-alternates.js.map +1 -0
  482. package/dist/sdk/shipping/shipping-operations.d.ts +1 -1
  483. package/dist/sdk/shipping/shipping-operations.js +13 -0
  484. package/dist/sdk/shipping/shipping-operations.js.map +1 -1
  485. package/dist/sdk/state/cart.d.ts +9 -2
  486. package/dist/sdk/state/cart.js +9 -2
  487. package/dist/sdk/state/cart.js.map +1 -1
  488. package/dist/utils/own-value.js +19 -0
  489. package/dist/utils/own-value.js.map +1 -0
  490. package/dist/utils/safe-href.d.ts +4 -4
  491. package/dist/utils/safe-href.js +31 -22
  492. package/dist/utils/safe-href.js.map +1 -1
  493. package/package.json +5 -1
  494. package/skills/storefront-asset/SKILL.md +111 -0
  495. package/skills/storefront-asset/references/api-side.md +153 -0
  496. package/skills/storefront-asset/references/findings.md +40 -0
  497. package/skills/storefront-asset/references/ui-side.md +94 -0
  498. package/src/styles/tailwind.css +28 -2
@@ -4,6 +4,7 @@ import "../../core/dist/index.js";
4
4
  import { useDataOverride } from "../../sdk/data/data-override-context.js";
5
5
  import { Icon } from "../../particles/icon/icon.js";
6
6
  import { usePayment } from "./payment.js";
7
+ import { ownValue } from "../../utils/own-value.js";
7
8
  import { NETWORK_ICON_BY_KEY } from "../card-entry/card-entry.js";
8
9
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
9
10
  //#region src/matter/payment/payment-method-badges.tsx
@@ -67,7 +68,8 @@ function paymentMethodNameTokens(name) {
67
68
  function paymentMethodIconName(name) {
68
69
  const tokens = paymentMethodNameTokens(name);
69
70
  for (let start = 0; start < tokens.length; start += 1) for (let end = tokens.length; end > start; end -= 1) {
70
- const icon = PAYMENT_METHOD_ICON_BY_KEY[tokens.slice(start, end).join("")];
71
+ const key = tokens.slice(start, end).join("");
72
+ const icon = ownValue(PAYMENT_METHOD_ICON_BY_KEY, key);
71
73
  if (icon) return icon;
72
74
  }
73
75
  return null;
@@ -187,6 +189,6 @@ function AcceptedPaymentMethodBadges({ heading, className, $data: $dataProp, ...
187
189
  });
188
190
  }
189
191
  //#endregion
190
- export { AcceptedPaymentMethodBadges, AcceptedPaymentMethodBadgesDefinition, PAYMENT_METHOD_ICON_BY_KEY, PaymentMethodBadges, PaymentMethodBadgesDefinition };
192
+ export { AcceptedPaymentMethodBadges, AcceptedPaymentMethodBadgesDefinition, PAYMENT_METHOD_ICON_BY_KEY, PaymentMethodBadges, PaymentMethodBadgesDefinition, paymentMethodIconName };
191
193
 
192
194
  //# sourceMappingURL=payment-method-badges.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"payment-method-badges.js","names":[],"sources":["../../../src/matter/payment/payment-method-badges.tsx"],"sourcesContent":["'use client';\n\nimport { defineComponent } from '@vtex/fs-core';\nimport type { ComponentPropsWithRef } from 'react';\nimport { Icon } from '../../particles/icon/icon.js';\nimport { useDataOverride } from '../../sdk/data/data-override-context.js';\nimport { NETWORK_ICON_BY_KEY } from '../card-entry/card-entry.js';\nimport { usePayment } from './payment.js';\n\n/**\n * `PaymentMethodBadges` (specs/render-the-accepted-payment-method-badges.md, T75 of the Credit Card\n * epic). Requirement 12.19's payment-step half: a section-level, data-driven, non-interactive strip —\n * one badge per payment method the store currently accepts, read off `usePayment()` on every render.\n * Never a prop, never local state, never CMS content.\n *\n * Three components render something visually similar and are not this (Decision 1):\n * - `CardEntry`'s own detected-network mark (T71/T172) — a single mark (0 or 1), shown only once a\n * network is recognized from typed digits — lives inside the card-number field's own box, scoped\n * to the card group. It cannot be placed independently and cannot carry a wallet method.\n * - The `PaymentMethods` particle (`particles/payment-methods/`) renders the same look from CMS\n * content. It serves store footers and does not react to a method being enabled or disabled in the\n * payment configuration.\n * - `PaymentMethodList` is the selectable radio picker, not reassurance.\n *\n * Reads `allMethods` — the section's unfiltered list — rather than the group-scoped `methods` every\n * picker and rendering leaf otherwise reads (Decision 3): the wallet methods this requirement names\n * (PayPal, Google Pay) arrive under a different `groupName` and would never reach a `methods`-scoped\n * leaf. See `allMethods`'s own doc comment in `use-payment-method-selection.ts` for the exception this\n * strip is recorded as. Apple Pay itself carries no key in the map below: it is not a payment system in\n * this read model at all (T133 tracks it as its own, separately blocked task).\n */\n\n// ---------------------------------------------------------------------------\n// Icon resolution (Decision 4, engineer gate + spike, 2026-08-26; matching redesigned in the review\n// pass that followed, same day). `PAYMENT_METHOD_ICON_BY_KEY` supersets T71's `NETWORK_ICON_BY_KEY`\n// (imported, never duplicated or mutated — INV-4) with the wallet glyphs this strip also needs.\n// Frozen: this map renders a brand mark for whatever the store called the method, so a value\n// silently overwritten at runtime would spoof that mark for every shopper who sees the strip.\n// ---------------------------------------------------------------------------\n\nexport const PAYMENT_METHOD_ICON_BY_KEY: Record<string, string> = Object.freeze({\n ...NETWORK_ICON_BY_KEY,\n paypal: 'paypal',\n googlepay: 'google-pay',\n pix: 'pix',\n stripe: 'stripe',\n});\n\n/**\n * Splits a store-configured name into lowercase a-z-only words. Every run of characters outside\n * a-z — spaces, punctuation, digits, accents — is a word *boundary*, never a character silently\n * stripped in place: `\"WH Google Pay\"` → `[\"wh\", \"google\", \"pay\"]`; `\"Boleto Bancário\"` →\n * `[\"boleto\", \"banc\", \"rio\"]` (the \"á\" splits the word instead of vanishing from inside it).\n */\nfunction paymentMethodNameTokens(name: string): string[] {\n return name\n .toLowerCase()\n .split(/[^a-z]+/)\n .filter(Boolean);\n}\n\n/**\n * Resolves a store-configured method name to a base-dialect icon name by matching a key against one\n * token, or a run of adjacent tokens joined back together — never a raw substring of the whole name\n * (review fix, 2026-08-26). The previous implementation normalised the whole name to one string and\n * checked `String.includes`, which matched `elo` inside real, unrelated Brazilian payment-system and\n * acquirer names — \"Cielo\" and \"Visanet\" resolved to a network they are not, \"Pague pelo Pix\" and\n * \"Nubank pelo Pix\" resolved to Elo instead of Pix, and \"Alelo Refeição\" (a real meal-voucher brand)\n * resolved to Elo too — because the key's letters simply occur in that order somewhere in the name.\n * Token equality cannot do that: `\"cielo\"` is one token, and it is never *equal* to `\"elo\"`, only\n * spelled with it in the middle.\n *\n * This still resolves `\"WH Google Pay\"` → `googlepay`, the false negative containment was introduced\n * to fix: joining tokens 1 and 2 (`google` + `pay`) produces a string equal to that key, even though\n * neither token alone is. For each start position the longest run of adjacent tokens is tried first,\n * falling back to shorter ones only when the longer run matches no key — \"Mastercard Debit\" needs\n * exactly that fallback (`mastercarddebit` is not a key; `mastercard` alone is) — which is also what\n * disambiguates a shorter key from a longer one built out of the same tokens (`diners` vs\n * `dinersclub`) without a separate sort step whose removal a test cannot observe.\n */\nfunction paymentMethodIconName(name: string): string | null {\n const tokens = paymentMethodNameTokens(name);\n for (let start = 0; start < tokens.length; start += 1) {\n for (let end = tokens.length; end > start; end -= 1) {\n const icon = PAYMENT_METHOD_ICON_BY_KEY[tokens.slice(start, end).join('')];\n if (icon) return icon;\n }\n }\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// The strip's own presence state (FR-4), resolved the same way `methodListState` (payment.tsx) is.\n// ---------------------------------------------------------------------------\n\nfunction badgesState({ loading, count }: { loading: boolean; count: number }): 'loading' | 'empty' | 'ready' {\n if (loading) return 'loading';\n if (count === 0) return 'empty';\n return 'ready';\n}\n\n/** One badge. Derived on every render; never stored, never a prop. */\ntype PaymentMethodBadge = {\n /** `PaymentSectionMethod.id` — the value of `data-fs-payment-method-badge-id`. */\n id: string;\n /** `PaymentSectionMethod.name`, store-configured free text. The visible text when `icon` is null. */\n name: string;\n /** A `BASE_ICON_DIALECT` name, or `null` when the name maps to none (FR-3). */\n icon: string | null;\n};\n\nexport type PaymentMethodBadgesProps = ComponentPropsWithRef<'div'> & {\n /** Names the strip. Absent or blank renders no heading and leaves the list unnamed (FR-5) — no invented default. */\n heading?: string;\n};\n\nexport const PaymentMethodBadgesDefinition = defineComponent<PaymentMethodBadgesProps>({\n name: 'PaymentMethodBadges',\n importPath: '@vtex/faststore/components',\n component: PaymentMethodBadges,\n requiresContext: 'payment',\n editor: { label: 'Payment Method Badges', category: 'commerce' },\n schema: { heading: { type: 'string', label: 'Heading' } },\n guideline:\n \"A read-only strip of one badge per payment method the store currently accepts, derived from the live order form on every render — never authored, never CMS content — so it updates the moment a method is enabled or disabled in the payment configuration. Place it inside a PaymentSectionRoot or PaymentSectionController, alongside PaymentMethodList and CardEntry; it renders nothing selectable and dispatches no action. Not PaymentMethods, which is the CMS-authored footer strip that cannot reflect the store's live configuration. See payment-method-badges.md.\",\n});\n\n/**\n * Shared render path (Decision 3, T121): both `PaymentMethodBadges` and `AcceptedPaymentMethodBadges`\n * below call this one function, so the DOM contract cannot drift between the payment-step and the\n * cart-order-summary surface (FR-9). Takes the raw method list rather than either caller's own\n * already-resolved badge array, because icon resolution (`paymentMethodIconName`) belongs to this one\n * path, never duplicated per caller.\n */\nfunction renderPaymentMethodBadges({\n methods,\n loading,\n heading,\n className,\n rest,\n}: {\n methods: ReadonlyArray<{ id: string; name: string }>;\n loading: boolean;\n heading?: string;\n className?: string;\n rest: ComponentPropsWithRef<'div'>;\n}) {\n const badges: PaymentMethodBadge[] = methods.map((method) => ({\n id: method.id,\n name: method.name,\n icon: paymentMethodIconName(method.name),\n }));\n\n const named = Boolean(heading?.trim());\n\n return (\n <div\n {...rest}\n className={className}\n data-fs-payment-method-badges=\"\"\n data-fs-payment-method-badges-state={badgesState({ loading, count: methods.length })}\n >\n {named ? (\n <h3 data-fs-text=\"\" data-fs-payment-method-badges-heading=\"\">\n {heading}\n </h3>\n ) : null}\n {badges.length > 0 ? (\n // biome-ignore lint/a11y/noRedundantRoles: WebKit drops the implicit list role from a ul whose computed `list-style` is `none` — exactly what this component's swatch sets — so the explicit role is what holds the semantics the named list was chosen for.\n <ul role=\"list\" data-fs-payment-method-badges-list=\"\" aria-label={named ? heading : undefined}>\n {badges.map((badge) => (\n <li\n key={badge.id}\n data-fs-payment-method-badge=\"\"\n data-fs-payment-method-badge-id={badge.id}\n // A method whose `name` is blank has nothing to show (no glyph, no text) — hide the\n // otherwise-empty item from assistive tech rather than exposing a nameless list entry.\n aria-hidden={badge.icon || badge.name ? undefined : true}\n >\n {badge.icon ? (\n <>\n <Icon name={badge.icon} data-fs-payment-method-badge-icon=\"\" />\n <span data-fs-sr-only=\"\" className=\"sr-only\">\n {badge.name}\n </span>\n </>\n ) : (\n badge.name\n )}\n </li>\n ))}\n </ul>\n ) : null}\n </div>\n );\n}\n\nexport function PaymentMethodBadges({ heading, className, ...props }: PaymentMethodBadgesProps) {\n const { allMethods, loading } = usePayment();\n return renderPaymentMethodBadges({ methods: allMethods, loading, heading, className, rest: props });\n}\n\n// ---------------------------------------------------------------------------\n// AcceptedPaymentMethodBadges (credit-card epic, T121 — the cart-order-summary half of requirement\n// 12.19; specs/render-the-accepted-payment-method-badges-cart-summary.md). Same render contract as\n// `PaymentMethodBadges` above — both call `renderPaymentMethodBadges` — but a different data source:\n// this component owns its own `Query.payment` fragment and declares no `requiresContext`, so it\n// composes on any surface outside a payment section, a cart order summary above all, with no\n// `PaymentSectionRoot` / `PaymentSectionController` ancestor. This is the settled ruling recorded at\n// `docs/features/credit-card/decisions.md:2575` — reuse the render contract, swap the data source —\n// mechanically expressed the way `PaymentSummary` already composes standalone off its own fragment.\n//\n// Reads `Payment.methods` unfiltered (Decision 2): the read model has one field, and `allMethods` vs\n// `methods` is a client-side `groupName` filter, not two sources — so this strip and T75's both show\n// every method the store accepts, wallets included, with no `group` prop to scope either one.\n// ---------------------------------------------------------------------------\n\nconst fragment = /* GraphQL */ `\n fragment AcceptedPaymentMethodBadgesData on Query {\n payment {\n __typename\n id\n methods {\n __typename\n id\n name\n }\n }\n }\n`;\n\n/**\n * The unwrapped value of the fragment's single top-level `payment` field (arity-1, ADR-0015) — never\n * a `{ payment: … }` wrapper. `methods` is optional: a resolved-but-partial slice is legal and\n * collapses to the `empty` state, mirroring `usePaymentMethodSelection`'s R1 note. Nullable, matching\n * every sibling slice type in this package (`PaymentSummaryData`, `CardEntryData`,\n * `InstallmentsSelectData`, `PaymentSectionData`, …): `null`/absent until the entity resolves, which\n * is exactly the `$data == null` branch below.\n */\nexport type AcceptedPaymentMethodBadgesData = {\n methods?: Array<{ id: string; name: string }>;\n} | null;\n\nexport type AcceptedPaymentMethodBadgesProps = ComponentPropsWithRef<'div'> & {\n /** Names the strip. Absent or blank renders no heading and leaves the list unnamed (FR-6) — no invented default. */\n heading?: string;\n /** Slice forwarded by the reactive runtime. `null`/absent until the entity resolves. */\n $data?: AcceptedPaymentMethodBadgesData;\n};\n\nexport const AcceptedPaymentMethodBadgesDefinition = defineComponent<AcceptedPaymentMethodBadgesProps>({\n name: 'AcceptedPaymentMethodBadges',\n importPath: '@vtex/faststore/components',\n component: AcceptedPaymentMethodBadges,\n fragment,\n fetchStrategy: 'reactive',\n editor: { label: 'Accepted Payment Method Badges', category: 'commerce' },\n schema: { heading: { type: 'string', label: 'Heading' } },\n guideline:\n \"A read-only strip of one badge per payment method the store currently accepts, derived from the live order form on every render — never authored, never CMS content. Owns its own Query.payment fragment — no PaymentSectionRoot or PaymentSectionController ancestor required — so place it on the cart order summary or another checkout-adjacent surface that already has a live cart. Placing it on a page with no cart context (a footer, home, or PDP) still resolves Query.payment on every server render, which mints a fresh upstream order form each time — a real cost in logs and upstream state, not a correctness error. Use PaymentMethodBadges instead for the strip inside a payment section; the two share one render contract and differ only in where their data comes from. Not PaymentMethods, the CMS-authored footer strip that cannot reflect the store's live configuration; not PaymentMethodList, the selectable picker; not CardEntry's own in-field network row. See payment-method-badges.md.\",\n});\n\nexport function AcceptedPaymentMethodBadges({\n heading,\n className,\n $data: $dataProp,\n ...props\n}: AcceptedPaymentMethodBadgesProps) {\n const $data = useDataOverride($dataProp);\n return renderPaymentMethodBadges({\n methods: $data?.methods ?? [],\n loading: $data == null,\n heading,\n className,\n rest: props,\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwCA,MAAa,6BAAqD,OAAO,OAAO;CAC9E,GAAG;CACH,QAAQ;CACR,WAAW;CACX,KAAK;CACL,QAAQ;AACV,CAAC;;;;;;;AAQD,SAAS,wBAAwB,MAAwB;CACvD,OAAO,KACJ,YAAY,CAAC,CACb,MAAM,SAAS,CAAC,CAChB,OAAO,OAAO;AACnB;;;;;;;;;;;;;;;;;;;;AAqBA,SAAS,sBAAsB,MAA6B;CAC1D,MAAM,SAAS,wBAAwB,IAAI;CAC3C,KAAK,IAAI,QAAQ,GAAG,QAAQ,OAAO,QAAQ,SAAS,GAClD,KAAK,IAAI,MAAM,OAAO,QAAQ,MAAM,OAAO,OAAO,GAAG;EACnD,MAAM,OAAO,2BAA2B,OAAO,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,EAAE;EACxE,IAAI,MAAM,OAAO;CACnB;CAEF,OAAO;AACT;AAMA,SAAS,YAAY,EAAE,SAAS,SAA6E;CAC3G,IAAI,SAAS,OAAO;CACpB,IAAI,UAAU,GAAG,OAAO;CACxB,OAAO;AACT;AAiBA,MAAa,gCAAgC,gBAA0C;CACrF,MAAM;CACN,YAAY;CACZ,WAAW;CACX,iBAAiB;CACjB,QAAQ;EAAE,OAAO;EAAyB,UAAU;CAAW;CAC/D,QAAQ,EAAE,SAAS;EAAE,MAAM;EAAU,OAAO;CAAU,EAAE;CACxD,WACE;AACJ,CAAC;;;;;;;;AASD,SAAS,0BAA0B,EACjC,SACA,SACA,SACA,WACA,QAOC;CACD,MAAM,SAA+B,QAAQ,KAAK,YAAY;EAC5D,IAAI,OAAO;EACX,MAAM,OAAO;EACb,MAAM,sBAAsB,OAAO,IAAI;CACzC,EAAE;CAEF,MAAM,QAAQ,QAAQ,SAAS,KAAK,CAAC;CAErC,OACE,qBAAC,OAAD;EACE,GAAI;EACO;EACX,iCAA8B;EAC9B,uCAAqC,YAAY;GAAE;GAAS,OAAO,QAAQ;EAAO,CAAC;EAJrF,UAAA,CAMG,QACC,oBAAC,MAAD;GAAI,gBAAa;GAAG,yCAAsC;GACvD,UAAA;EACC,CAAA,IACF,MACH,OAAO,SAAS,IAEf,oBAAC,MAAD;GAAI,MAAK;GAAO,sCAAmC;GAAG,cAAY,QAAQ,UAAU,KAAA;GACjF,UAAA,OAAO,KAAK,UACX,oBAAC,MAAD;IAEE,gCAA6B;IAC7B,mCAAiC,MAAM;IAGvC,eAAa,MAAM,QAAQ,MAAM,OAAO,KAAA,IAAY;IAEnD,UAAA,MAAM,OACL,qBAAA,UAAA,EAAA,UAAA,CACE,oBAAC,MAAD;KAAM,MAAM,MAAM;KAAM,qCAAkC;IAAI,CAAA,GAC9D,oBAAC,QAAD;KAAM,mBAAgB;KAAG,WAAU;KAChC,UAAA,MAAM;IACH,CAAA,CACN,EAAA,CAAA,IAEF,MAAM;GAEN,GAjBG,MAAM,EAiBT,CACL;EACC,CAAA,IACF,IACD;;AAET;AAEA,SAAgB,oBAAoB,EAAE,SAAS,WAAW,GAAG,SAAmC;CAC9F,MAAM,EAAE,YAAY,YAAY,WAAW;CAC3C,OAAO,0BAA0B;EAAE,SAAS;EAAY;EAAS;EAAS;EAAW,MAAM;CAAM,CAAC;AACpG;AAkDA,MAAa,wCAAwC,gBAAkD;CACrG,MAAM;CACN,YAAY;CACZ,WAAW;CACX;;;;;;;;;;;;;CACA,eAAe;CACf,QAAQ;EAAE,OAAO;EAAkC,UAAU;CAAW;CACxE,QAAQ,EAAE,SAAS;EAAE,MAAM;EAAU,OAAO;CAAU,EAAE;CACxD,WACE;AACJ,CAAC;AAED,SAAgB,4BAA4B,EAC1C,SACA,WACA,OAAO,WACP,GAAG,SACgC;CACnC,MAAM,QAAQ,gBAAgB,SAAS;CACvC,OAAO,0BAA0B;EAC/B,SAAS,OAAO,WAAW,CAAC;EAC5B,SAAS,SAAS;EAClB;EACA;EACA,MAAM;CACR,CAAC;AACH"}
1
+ {"version":3,"file":"payment-method-badges.js","names":[],"sources":["../../../src/matter/payment/payment-method-badges.tsx"],"sourcesContent":["'use client';\n\nimport { defineComponent } from '@vtex/fs-core';\nimport type { ComponentPropsWithRef } from 'react';\nimport { Icon } from '../../particles/icon/icon.js';\nimport { useDataOverride } from '../../sdk/data/data-override-context.js';\nimport { ownValue } from '../../utils/own-value.js';\nimport { NETWORK_ICON_BY_KEY } from '../card-entry/card-entry.js';\nimport { usePayment } from './payment.js';\n\n/**\n * `PaymentMethodBadges` (specs/render-the-accepted-payment-method-badges.md, T75 of the Credit Card\n * epic). Requirement 12.19's payment-step half: a section-level, data-driven, non-interactive strip —\n * one badge per payment method the store currently accepts, read off `usePayment()` on every render.\n * Never a prop, never local state, never CMS content.\n *\n * Three components render something visually similar and are not this (Decision 1):\n * - `CardEntry`'s own detected-network mark (T71/T172) — a single mark (0 or 1), shown only once a\n * network is recognized from typed digits — lives inside the card-number field's own box, scoped\n * to the card group. It cannot be placed independently and cannot carry a wallet method.\n * - The `PaymentMethods` particle (`particles/payment-methods/`) renders the same look from CMS\n * content. It serves store footers and does not react to a method being enabled or disabled in the\n * payment configuration.\n * - `PaymentMethodList` is the selectable radio picker, not reassurance.\n *\n * Reads `allMethods` — the section's unfiltered list — rather than the group-scoped `methods` every\n * picker and rendering leaf otherwise reads (Decision 3): the wallet methods this requirement names\n * (PayPal, Google Pay) arrive under a different `groupName` and would never reach a `methods`-scoped\n * leaf. See `allMethods`'s own doc comment in `use-payment-method-selection.ts` for the exception this\n * strip is recorded as. Apple Pay itself carries no key in the map below: it is not a payment system in\n * this read model at all (T133 tracks it as its own, separately blocked task).\n */\n\n// ---------------------------------------------------------------------------\n// Icon resolution (Decision 4, engineer gate + spike, 2026-08-26; matching redesigned in the review\n// pass that followed, same day). `PAYMENT_METHOD_ICON_BY_KEY` supersets T71's `NETWORK_ICON_BY_KEY`\n// (imported, never duplicated or mutated — INV-4) with the wallet glyphs this strip also needs.\n// Frozen: this map renders a brand mark for whatever the store called the method, so a value\n// silently overwritten at runtime would spoof that mark for every shopper who sees the strip.\n// ---------------------------------------------------------------------------\n\nexport const PAYMENT_METHOD_ICON_BY_KEY: Record<string, string> = Object.freeze({\n ...NETWORK_ICON_BY_KEY,\n paypal: 'paypal',\n googlepay: 'google-pay',\n pix: 'pix',\n stripe: 'stripe',\n});\n\n/**\n * Splits a store-configured name into lowercase a-z-only words. Every run of characters outside\n * a-z — spaces, punctuation, digits, accents — is a word *boundary*, never a character silently\n * stripped in place: `\"WH Google Pay\"` → `[\"wh\", \"google\", \"pay\"]`; `\"Boleto Bancário\"` →\n * `[\"boleto\", \"banc\", \"rio\"]` (the \"á\" splits the word instead of vanishing from inside it).\n */\nfunction paymentMethodNameTokens(name: string): string[] {\n return name\n .toLowerCase()\n .split(/[^a-z]+/)\n .filter(Boolean);\n}\n\n/**\n * Resolves a store-configured method name to a base-dialect icon name by matching a key against one\n * token, or a run of adjacent tokens joined back together — never a raw substring of the whole name\n * (review fix, 2026-08-26). The previous implementation normalised the whole name to one string and\n * checked `String.includes`, which matched `elo` inside real, unrelated Brazilian payment-system and\n * acquirer names — \"Cielo\" and \"Visanet\" resolved to a network they are not, \"Pague pelo Pix\" and\n * \"Nubank pelo Pix\" resolved to Elo instead of Pix, and \"Alelo Refeição\" (a real meal-voucher brand)\n * resolved to Elo too — because the key's letters simply occur in that order somewhere in the name.\n * Token equality cannot do that: `\"cielo\"` is one token, and it is never *equal* to `\"elo\"`, only\n * spelled with it in the middle.\n *\n * This still resolves `\"WH Google Pay\"` → `googlepay`, the false negative containment was introduced\n * to fix: joining tokens 1 and 2 (`google` + `pay`) produces a string equal to that key, even though\n * neither token alone is. For each start position the longest run of adjacent tokens is tried first,\n * falling back to shorter ones only when the longer run matches no key — \"Mastercard Debit\" needs\n * exactly that fallback (`mastercarddebit` is not a key; `mastercard` alone is) — which is also what\n * disambiguates a shorter key from a longer one built out of the same tokens (`diners` vs\n * `dinersclub`) without a separate sort step whose removal a test cannot observe.\n */\nexport function paymentMethodIconName(name: string): string | null {\n const tokens = paymentMethodNameTokens(name);\n for (let start = 0; start < tokens.length; start += 1) {\n for (let end = tokens.length; end > start; end -= 1) {\n const key = tokens.slice(start, end).join('');\n const icon = ownValue(PAYMENT_METHOD_ICON_BY_KEY, key);\n if (icon) return icon;\n }\n }\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// The strip's own presence state (FR-4), resolved the same way `methodListState` (payment.tsx) is.\n// ---------------------------------------------------------------------------\n\nfunction badgesState({ loading, count }: { loading: boolean; count: number }): 'loading' | 'empty' | 'ready' {\n if (loading) return 'loading';\n if (count === 0) return 'empty';\n return 'ready';\n}\n\n/** One badge. Derived on every render; never stored, never a prop. */\ntype PaymentMethodBadge = {\n /** `PaymentSectionMethod.id` — the value of `data-fs-payment-method-badge-id`. */\n id: string;\n /** `PaymentSectionMethod.name`, store-configured free text. The visible text when `icon` is null. */\n name: string;\n /** A `BASE_ICON_DIALECT` name, or `null` when the name maps to none (FR-3). */\n icon: string | null;\n};\n\nexport type PaymentMethodBadgesProps = ComponentPropsWithRef<'div'> & {\n /** Names the strip. Absent or blank renders no heading and leaves the list unnamed (FR-5) — no invented default. */\n heading?: string;\n};\n\nexport const PaymentMethodBadgesDefinition = defineComponent<PaymentMethodBadgesProps>({\n name: 'PaymentMethodBadges',\n importPath: '@vtex/faststore/components',\n component: PaymentMethodBadges,\n requiresContext: 'payment',\n editor: { label: 'Payment Method Badges', category: 'commerce' },\n schema: { heading: { type: 'string', label: 'Heading' } },\n guideline:\n \"A read-only strip of one badge per payment method the store currently accepts, derived from the live order form on every render — never authored, never CMS content — so it updates the moment a method is enabled or disabled in the payment configuration. Place it inside a PaymentSectionRoot or PaymentSectionController, alongside PaymentMethodList and CardEntry; it renders nothing selectable and dispatches no action. Not PaymentMethods, which is the CMS-authored footer strip that cannot reflect the store's live configuration. See payment-method-badges.md.\",\n});\n\n/**\n * Shared render path (Decision 3, T121): both `PaymentMethodBadges` and `AcceptedPaymentMethodBadges`\n * below call this one function, so the DOM contract cannot drift between the payment-step and the\n * cart-order-summary surface (FR-9). Takes the raw method list rather than either caller's own\n * already-resolved badge array, because icon resolution (`paymentMethodIconName`) belongs to this one\n * path, never duplicated per caller.\n */\nfunction renderPaymentMethodBadges({\n methods,\n loading,\n heading,\n className,\n rest,\n}: {\n methods: ReadonlyArray<{ id: string; name: string }>;\n loading: boolean;\n heading?: string;\n className?: string;\n rest: ComponentPropsWithRef<'div'>;\n}) {\n const badges: PaymentMethodBadge[] = methods.map((method) => ({\n id: method.id,\n name: method.name,\n icon: paymentMethodIconName(method.name),\n }));\n\n const named = Boolean(heading?.trim());\n\n return (\n <div\n {...rest}\n className={className}\n data-fs-payment-method-badges=\"\"\n data-fs-payment-method-badges-state={badgesState({ loading, count: methods.length })}\n >\n {named ? (\n <h3 data-fs-text=\"\" data-fs-payment-method-badges-heading=\"\">\n {heading}\n </h3>\n ) : null}\n {badges.length > 0 ? (\n // biome-ignore lint/a11y/noRedundantRoles: WebKit drops the implicit list role from a ul whose computed `list-style` is `none` — exactly what this component's swatch sets — so the explicit role is what holds the semantics the named list was chosen for.\n <ul role=\"list\" data-fs-payment-method-badges-list=\"\" aria-label={named ? heading : undefined}>\n {badges.map((badge) => (\n <li\n key={badge.id}\n data-fs-payment-method-badge=\"\"\n data-fs-payment-method-badge-id={badge.id}\n // A method whose `name` is blank has nothing to show (no glyph, no text) — hide the\n // otherwise-empty item from assistive tech rather than exposing a nameless list entry.\n aria-hidden={badge.icon || badge.name ? undefined : true}\n >\n {badge.icon ? (\n <>\n <Icon name={badge.icon} data-fs-payment-method-badge-icon=\"\" />\n <span data-fs-sr-only=\"\" className=\"sr-only\">\n {badge.name}\n </span>\n </>\n ) : (\n badge.name\n )}\n </li>\n ))}\n </ul>\n ) : null}\n </div>\n );\n}\n\nexport function PaymentMethodBadges({ heading, className, ...props }: PaymentMethodBadgesProps) {\n const { allMethods, loading } = usePayment();\n return renderPaymentMethodBadges({ methods: allMethods, loading, heading, className, rest: props });\n}\n\n// ---------------------------------------------------------------------------\n// AcceptedPaymentMethodBadges (credit-card epic, T121 — the cart-order-summary half of requirement\n// 12.19; specs/render-the-accepted-payment-method-badges-cart-summary.md). Same render contract as\n// `PaymentMethodBadges` above — both call `renderPaymentMethodBadges` — but a different data source:\n// this component owns its own `Query.payment` fragment and declares no `requiresContext`, so it\n// composes on any surface outside a payment section, a cart order summary above all, with no\n// `PaymentSectionRoot` / `PaymentSectionController` ancestor. This is the settled ruling recorded at\n// `docs/features/credit-card/decisions.md:2575` — reuse the render contract, swap the data source —\n// mechanically expressed the way `PaymentSummary` already composes standalone off its own fragment.\n//\n// Reads `Payment.methods` unfiltered (Decision 2): the read model has one field, and `allMethods` vs\n// `methods` is a client-side `groupName` filter, not two sources — so this strip and T75's both show\n// every method the store accepts, wallets included, with no `group` prop to scope either one.\n// ---------------------------------------------------------------------------\n\nconst fragment = /* GraphQL */ `\n fragment AcceptedPaymentMethodBadgesData on Query {\n payment {\n __typename\n id\n methods {\n __typename\n id\n name\n }\n }\n }\n`;\n\n/**\n * The unwrapped value of the fragment's single top-level `payment` field (arity-1, ADR-0015) — never\n * a `{ payment: … }` wrapper. `methods` is optional: a resolved-but-partial slice is legal and\n * collapses to the `empty` state, mirroring `usePaymentMethodSelection`'s R1 note. Nullable, matching\n * every sibling slice type in this package (`PaymentSummaryData`, `CardEntryData`,\n * `InstallmentsSelectData`, `PaymentSectionData`, …): `null`/absent until the entity resolves, which\n * is exactly the `$data == null` branch below.\n */\nexport type AcceptedPaymentMethodBadgesData = {\n methods?: Array<{ id: string; name: string }>;\n} | null;\n\nexport type AcceptedPaymentMethodBadgesProps = ComponentPropsWithRef<'div'> & {\n /** Names the strip. Absent or blank renders no heading and leaves the list unnamed (FR-6) — no invented default. */\n heading?: string;\n /** Slice forwarded by the reactive runtime. `null`/absent until the entity resolves. */\n $data?: AcceptedPaymentMethodBadgesData;\n};\n\nexport const AcceptedPaymentMethodBadgesDefinition = defineComponent<AcceptedPaymentMethodBadgesProps>({\n name: 'AcceptedPaymentMethodBadges',\n importPath: '@vtex/faststore/components',\n component: AcceptedPaymentMethodBadges,\n fragment,\n fetchStrategy: 'reactive',\n editor: { label: 'Accepted Payment Method Badges', category: 'commerce' },\n schema: { heading: { type: 'string', label: 'Heading' } },\n guideline:\n \"A read-only strip of one badge per payment method the store currently accepts, derived from the live order form on every render — never authored, never CMS content. Owns its own Query.payment fragment — no PaymentSectionRoot or PaymentSectionController ancestor required — so place it on the cart order summary or another checkout-adjacent surface that already has a live cart. Placing it on a page with no cart context (a footer, home, or PDP) still resolves Query.payment on every server render, which mints a fresh upstream order form each time — a real cost in logs and upstream state, not a correctness error. Use PaymentMethodBadges instead for the strip inside a payment section; the two share one render contract and differ only in where their data comes from. Not PaymentMethods, the CMS-authored footer strip that cannot reflect the store's live configuration; not PaymentMethodList, the selectable picker; not CardEntry's own in-field network row. See payment-method-badges.md.\",\n});\n\nexport function AcceptedPaymentMethodBadges({\n heading,\n className,\n $data: $dataProp,\n ...props\n}: AcceptedPaymentMethodBadgesProps) {\n const $data = useDataOverride($dataProp);\n return renderPaymentMethodBadges({\n methods: $data?.methods ?? [],\n loading: $data == null,\n heading,\n className,\n rest: props,\n });\n}\n"],"mappings":"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"}
@@ -59,6 +59,17 @@ const fragment = `
59
59
  selectedMethodId
60
60
  selectedAccountId
61
61
  selectedBin
62
+ storeCountryCode
63
+ countries {
64
+ __typename
65
+ countryCode
66
+ documents {
67
+ __typename
68
+ type
69
+ displayable
70
+ required
71
+ }
72
+ }
62
73
  }
63
74
  cart {
64
75
  __typename
@@ -1 +1 @@
1
- {"version":3,"file":"payment.js","names":[],"sources":["../../../src/matter/payment/payment.tsx"],"sourcesContent":["'use client';\n\nimport { defineComponent } from '@vtex/fs-core';\nimport { type ComponentPropsWithRef, createContext, useContext, useId, useLayoutEffect, useMemo } from 'react';\nimport { Fieldset } from '../../particles/fieldset/fieldset.js';\nimport { RadioGroup, RadioIndicator, RadioRoot } from '../../particles/radio/radio.js';\nimport { useActionsOverride } from '../../sdk/actions/actions-override-context.js';\nimport type { ComponentActions } from '../../sdk/actions/types.js';\nimport { useDataOverride } from '../../sdk/data/data-override-context.js';\nimport { PaymentSubmissionProvider } from '../../sdk/payment/submission-registry.js';\nimport { resolveAuthoredCopy } from '../../utils/resolve-authored-copy.js';\nimport { PaymentCardCaptureProvider, type PaymentCartData } from './payment-card-capture.js';\nimport {\n type PaymentMethodSelection,\n type PaymentSectionData,\n resolveCanRevealCardPayment,\n resolvePreselectionCandidateId,\n splitCardMethods,\n usePaymentMethodSelection,\n} from './use-payment-method-selection.js';\n\n/**\n * The `PaymentSection` matter root (specs/payment-section-root.md, T5 of the Credit Card epic;\n * docs/features/credit-card/rfc.md § D1). `PaymentSectionRoot` is the always-visible presentation\n * variant over the `Payment` entity T1 projects: it owns a thin `fragment` (the method list with its\n * server-driven validator config, plus the current selection), runs the shared\n * `usePaymentMethodSelection` engine, and provides the `payment` context its leaves read — the card\n * entry (T7), cardholder document (T8), installments (T9), save-card (T10), billing address (T11),\n * saved cards (T12), and place-order CTA (T14) — through the guarded `usePayment()` hook rather than\n * drilled props (ADR-0009). `PaymentSectionController` (payment-controller.tsx) is the second provider\n * of the same context for a collapsed overlay surface; ADR-0009 matches by contract identifier, so the\n * two substitute for one another with zero edits to any consumer.\n *\n * \"Thin\" means no `installmentOptions` (T9's own fragment), no `savedCards` (T12's), and no\n * `selectedInstallment` (T6's) — the heavy, optional, and iterated subtrees ADR-0011/ADR-0012 split out.\n * `methods[].validator` *is* selected here: it is a non-normalized value object off `Payment.methods`\n * that cannot be subscribed separately, and T7 tests every method's `numberRegex` to detect a network.\n *\n * `children` is the section composition, not a per-method template — the method picker is\n * `PaymentMethodList`, an independently placeable part with its own hooks.\n */\n\n// ---------------------------------------------------------------------------\n// GraphQL Fragment — raw template literal, matching the merged `payment-summary` sibling. The codegen\n// `documents` glob does not scan `src/matter/payment*`, so the typed `graphql()` factory is\n// unavailable here; `data-component-contract.test.ts` validates this fragment against the real schema.\n//\n// Selects `payment { id }` so Apollo's InMemoryCache normalizes `Payment` by id — required for the\n// `Payment` entity that `paymentMethodSelect` echoes back to update the same cache entity this\n// fragment reads. `fetchStrategy: 'reactive'`'s no-refetch guarantee holds only if both sides\n// normalize to one entity.\n// ---------------------------------------------------------------------------\n\nconst fragment = /* GraphQL */ `\n fragment PaymentSectionData on Query {\n payment {\n __typename\n id\n methods {\n __typename\n id\n name\n groupName\n validator {\n __typename\n numberMask\n numberRegex\n cvvMask\n cvvRegex\n cvvRequired\n expirationRequired\n holderNameRequired\n billingAddressRequired\n documentDisplayable\n documentRequired\n }\n }\n selectedMethodId\n selectedAccountId\n selectedBin\n }\n cart {\n __typename\n id\n total {\n __typename\n amount\n currencyCode\n }\n }\n }\n`;\n\n/**\n * The default payment-group scope: credit and debit (T140, FR-2, Decision 2). Both strings are\n * store-configured, so a store whose groups differ must set `group` explicitly; `group: ''` scopes\n * nothing (specs/payment-section-root.md § Documentation Gaps item 1). Widened from a single string to\n * a set (Decision 1) — a public API break for any consumer importing it directly (Interfaces).\n */\n/**\n * The roots' keyed `$data` (ADR-0015, arity 2): the `Payment` slice the selection engine reads, and the\n * cart total `add_payment_info` needs (moved here from `CardEntry`, which reads no cart).\n */\nexport type PaymentSectionRootData = {\n payment?: PaymentSectionData;\n cart?: PaymentCartData;\n} | null;\n\nexport const DEFAULT_METHOD_GROUP: readonly string[] = ['creditCardPaymentGroup', 'debitCardPaymentGroup'];\n\n// ---------------------------------------------------------------------------\n// Payment context — provided by both section roots, read by every leaf\n// ---------------------------------------------------------------------------\n\n/**\n * The `payment` context contract, normative for T7–T12 and T14. Everything the selection engine\n * resolves, plus the overlay disclosure. What is deliberately absent is part of the contract too: no\n * card number, CVV, expiration, or holder name (RFC D13 — they live only in the card entry's local\n * state); no submission channel for the place-order sequence, which is the separate, narrow\n * `PaymentSubmissionProvider` below (T13) precisely so no card-shaped value ever joins this contract;\n * no `installmentOptions` / `savedCards` / `selectedInstallment` (their owners' fragments); and no\n * optimistic mirror of the persisted selection.\n */\nexport type PaymentContextValue = Readonly<\n PaymentMethodSelection & {\n /** The collapsed surface's disclosure state. Always `true` under `PaymentSectionRoot`. */\n open: boolean;\n /**\n * Drives the collapsed surface. A no-op under `PaymentSectionRoot`, so a leaf written for the\n * overlay composes unchanged inline. Selecting a method never closes the surface on its own — the\n * shopper still has a card to type — so closing is the composition's call (Decision 5).\n */\n setOpen: (open: boolean) => void;\n }\n>;\n\nconst PAYMENT_CONTEXT_UNSET = Symbol('PaymentContextUnset');\n\nconst PaymentContextInternal = createContext<PaymentContextValue | typeof PAYMENT_CONTEXT_UNSET>(PAYMENT_CONTEXT_UNSET);\n\n/** The provider both section roots render. Exported for `PaymentSectionController`. */\nexport const PaymentContext = PaymentContextInternal as React.Context<PaymentContextValue>;\n\n/**\n * Read the payment section's selection state, draft, and overlay disclosure from the nearest\n * `PaymentSectionRoot` or `PaymentSectionController`. Throws outside either subtree — a misplaced\n * consumer is a composition bug the author should see immediately, not a silent degrade to an empty\n * selection — mirroring `useSession()` / `useDeliveryOptions()`. ADR-0009's compiler check catches the\n * same mistake before emission for schema-authored pages; this is the defense-in-depth layer for\n * Storybook, tests, and hand-written JSX.\n */\nexport function usePayment(): PaymentContextValue {\n const ctx = useContext(PaymentContextInternal);\n if (ctx === PAYMENT_CONTEXT_UNSET) {\n throw new Error('usePayment() must be used inside a <PaymentSectionRoot> or <PaymentSectionController> subtree.');\n }\n return ctx;\n}\n\nconst NO_DISCLOSURE = () => {};\n\n// ---------------------------------------------------------------------------\n// Props\n// ---------------------------------------------------------------------------\n\nexport type PaymentSectionRootProps = ComponentPropsWithRef<'div'> & {\n /**\n * Scopes the method list to a **set** of `PaymentMethod.groupName` values — a method is in scope\n * when its `groupName` is a member (T140, FR-1, Decision 1). A single string is still accepted and\n * scopes to exactly that one group (FR-4, US-3). T1's read model is method-agnostic and assigns the\n * narrowing to the consumer; this prop supplies no method, label, or ordering — the list itself is\n * fragment data. An empty string scopes nothing.\n */\n group?: string | readonly string[];\n /** Keyed `{ payment, cart }` forwarded by the reactive runtime (arity-2 fragment, ADR-0015). */\n $data?: PaymentSectionRootData;\n /** Compiler-injected action surface; carries `payment.setMethod`, `payment.sendPayments`, and `analytics.track`. */\n $actions?: ComponentActions;\n};\n\n/** Renders its own controls from the context's method list — `children` would have nothing to template. */\nexport type PaymentMethodListProps = Omit<ComponentPropsWithRef<'div'>, 'children'> & {\n /**\n * The radio group's accessible name, rendered as a visible `Fieldset.Legend` (T38, Decision 1).\n * Resolved through `resolveAuthoredCopy`: an authored empty or whitespace-only string falls back to\n * the default rather than rendering a nameless group.\n */\n legend?: string;\n /**\n * The single card control's name (T171, Decision 8). The control stands for every in-scope\n * credit/debit method at once, so it cannot take its name from one of their `method.name` values the\n * way a per-network row did — it is authored copy instead, defaulting to the PRD's own string.\n * Resolved through `resolveAuthoredCopy` exactly as `legend` is, so an authored empty or\n * whitespace-only string falls back rather than rendering a nameless control.\n */\n cardLabel?: string;\n};\n\n// ---------------------------------------------------------------------------\n// Definitions\n// ---------------------------------------------------------------------------\n\nexport const PaymentSectionRootDefinition = defineComponent<PaymentSectionRootProps>({\n name: 'PaymentSectionRoot',\n importPath: '@vtex/faststore/components',\n component: PaymentSectionRoot,\n fragment,\n fetchStrategy: 'reactive',\n actions: { payment: ['setMethod', 'sendPayments'], analytics: ['track'] },\n providesContext: ['payment', 'card-capture'],\n hardened: true,\n editor: { label: 'Payment Section', category: 'commerce' },\n schema: {\n // A literal, not `DEFAULT_METHOD_GROUP`: the native catalog builder extracts `schema` statically\n // and silently drops an identifier-valued default, so the built entry would carry no default and\n // the compiler would emit the section unscoped. `payment.test.tsx` asserts the literal matches the\n // constant, and that the built catalog kept the default.\n // T140, Decision 2/OQ-6: `type: 'array'` — no code path in packages/sukima/crates/sukima-core/\n // validates an authored prop's JSON value against this declared type, so a store's existing bare\n // string keeps compiling. No `items`: an enum would validate against a closed set of group names,\n // which is wrong for a store that renamed its group (OQ-3) — the exact fragility Decision 1 closes.\n group: {\n type: 'array',\n default: ['creditCardPaymentGroup', 'debitCardPaymentGroup'],\n label: 'Payment method group',\n },\n },\n guideline:\n \"Root of the checkout payment section: reads the payment methods and the current selection from the order form and provides the 'payment' context every payment leaf needs and the 'card-capture' context CardEntry needs, so place CardEntry, CardholderDocument, Installments, SaveCard, BillingAddress, SavedCards, PlaceOrder, and PaymentMethodList as its children — none of them render without a payment root ancestor. Renders one container div and no chrome or copy of its own; headings and layout belong to the composition. Selecting a payment option dispatches $actions.payment.setMethod and every subscriber re-renders from the cache with no refetch — and for a card it is the number the shopper types that decides the network, not an option they pick, so PaymentMethodList shows every in-scope credit and debit method as ONE card option. Which methods exist is always real data — never author them as props; group only scopes the list by the store's payment group(s) — defaults to credit and debit together, accepts one group name or a set of them, and set it to \\\"\\\" to show every method, one option each, with no card option. Use PaymentSectionController instead when the section should live in a drawer or modal. See payment.md.\",\n});\n\nexport const PaymentMethodListDefinition = defineComponent<PaymentMethodListProps>({\n name: 'PaymentMethodList',\n importPath: '@vtex/faststore/components',\n component: PaymentMethodList,\n requiresContext: 'payment',\n editor: { label: 'Payment Method List', category: 'commerce' },\n schema: {\n // T38/T171: inline literals, never identifiers — the native catalog builder extracts `schema`\n // statically and silently drops an identifier-valued default (INV-8).\n legend: { type: 'string', default: 'Payment method', label: 'Legend' },\n cardLabel: { type: 'string', default: 'Pay with Credit / Debit Card', label: 'Card option label' },\n },\n guideline:\n 'The payment-method picker: a radio group of the payment options the order form offers, plus the inline selection error (role=\"alert\"). Every in-scope credit and debit method is ONE option — the network comes from the card number the shopper types, never from a row they pick — and any other in-scope method (e.g. Pix) keeps a row of its own; set group to \"\" on the root to switch that off and get one row per method. Selecting an option dispatches the method selection. Selecting a non-card option hides the card form, and the card option brings it back. Place it inside a PaymentSectionRoot, or inside the DialogPopup/DrawerPopup of a PaymentSectionController. It renders its own options from real data, so it takes no children and no method props; author the card option\\'s wording with cardLabel. Keep it composed: it is the only element that surfaces a rejected selection, and the only control that can recover a selection this section does not serve — omit it and a shopper whose persisted method sits outside group has no reachable way back. Must be inside a payment root.',\n});\n\n// ---------------------------------------------------------------------------\n// Implementations\n// ---------------------------------------------------------------------------\n\nexport function PaymentSectionRoot({\n group = DEFAULT_METHOD_GROUP,\n $data: $dataProp,\n $actions: $actionsProp,\n className,\n children,\n ...props\n}: PaymentSectionRootProps) {\n const $data = useDataOverride($dataProp);\n const $actions = useActionsOverride($actionsProp);\n const selection = usePaymentMethodSelection({ group, $data: $data?.payment ?? null, $actions });\n const payment = useMemo<PaymentContextValue>(\n () => ({ ...selection, open: true, setOpen: NO_DISCLOSURE }),\n [selection],\n );\n\n return (\n <PaymentContextInternal value={payment}>\n <PaymentSubmissionProvider path={selection.draft.path}>\n <PaymentCardCaptureProvider selection={selection} cart={$data?.cart} $actions={$actions}>\n <div\n {...props}\n className={className}\n data-fs-payment-section=\"\"\n {...(selection.draft.path ? { 'data-fs-payment-section-path': selection.draft.path } : {})}\n // T28, Decision 5: presence attribute only, deliberately never `inert` — `PlaceOrder` composes\n // as a child of this same container (FR-6), so making it inert here would swallow the CTA's\n // own role=\"alert\"/role=\"status\" regions, the shopper's only channel for the outcome.\n {...(selection.placing ? { 'data-fs-payment-section-placing': '' } : {})}\n >\n {children}\n </div>\n </PaymentCardCaptureProvider>\n </PaymentSubmissionProvider>\n </PaymentContextInternal>\n );\n}\n\n/**\n * The picker's presence state, always emitted so a swatch can surface a row-less container — otherwise\n * a zero-height element under any stacking swatch, and the \"visible empty region\" the section's\n * group-default risk is accepted on. `loading` (still resolving) and `empty` (resolved, nothing in\n * scope) stay distinct: one is a wait, the other a misconfiguration.\n */\nfunction methodListState({ loading, count }: { loading: boolean; count: number }): 'loading' | 'empty' | 'ready' {\n if (loading) return 'loading';\n if (count === 0) return 'empty';\n return 'ready';\n}\n\n/**\n * The DOM value the collapsed card control carries inside the `RadioGroup`. Base UI requires every\n * radio root to have one, and this control stands for N methods, so there is no `method.id` it could\n * use.\n *\n * It is a radio-group value and nothing else — **never a method id** (INV-1, ADR-0023). It is never\n * dispatched: `handleValueChange` below maps it back to `resolvePreselectionCandidateId`'s answer\n * before calling `selectMethod`, and records card mode through `selectNewCard()`, which dispatches\n * nothing, when there is no candidate (T191, FR-6). The prefix keeps it from ever colliding with a\n * `PaymentMethod.id` a standalone row is bound to.\n */\nconst CARD_CONTROL_VALUE = '__fs-card-control';\n\nexport function PaymentMethodList({ legend, cardLabel, className, ...props }: PaymentMethodListProps) {\n const {\n methods,\n allMethods,\n persistedMethodId,\n selectedMethodId,\n selectionError,\n selectMethod,\n selectNewCard,\n cardModeActive,\n loading,\n placing,\n setMethodListMounted,\n } = usePayment();\n\n // T171, FR-1/FR-2: one control for the in-scope card methods, one row for every other in-scope\n // method. Memoized off the two lists only (NFR-5) — nothing here may widen what re-creates the\n // `payment` context value, which a keystroke already churns enough.\n const { collapsedCardMethods, standaloneMethods } = useMemo(\n () => splitCardMethods({ methods, allMethods }),\n [methods, allMethods],\n );\n // Decision 3: the collapsed control dispatches the *shared* preselection candidate, so the escape\n // hatch and the preselection can never disagree about whether an id is available.\n const cardCandidateId = useMemo(() => resolvePreselectionCandidateId(methods), [methods]);\n const canRevealCardPayment = resolveCanRevealCardPayment({ collapsedCardMethods, standaloneMethods });\n\n // Decision 2: derived, never bound to one `method.id` — a control standing for N methods has none.\n // Checked when the persisted selection resolves inside the collapsed set, and when nothing is\n // persisted at all (PRD REQ-02's \"the card payment option is selected by default\"). The second arm\n // is a deliberate divergence from the pre-T171 bound-to-`$data` behaviour: the control can read\n // checked while `$data.selectedMethodId` is still null, having dispatched nothing. `persistedMethodId`\n // is the raw, unscoped fact on purpose — a persisted method this section does not serve must leave the\n // control unchecked, which is what keeps it activatable as US-5's way back. T191 (FR-6): card mode is\n // the third arm, the card option chosen over such a selection or over a non-card one.\n const cardControlChecked =\n collapsedCardMethods.length > 0 &&\n (persistedMethodId === null ||\n collapsedCardMethods.some((method) => method.id === selectedMethodId) ||\n cardModeActive);\n\n // Fix pass, finding R2: registers this instance with the shared engine so the card leaves know an\n // escape hatch exists before they ever collapse — a section composed with no `PaymentMethodList` at\n // all must never hide the only remaining way to change the method (typing a new card number).\n // Retracted unconditionally on unmount, unlike `setPlacing`'s own \"leave it if still placing\"\n // carve-out: there is no in-flight sequence here for an abandoned instance to still be part of.\n //\n // T191, Decision 5 (after T171's Decision 4): what is registered is `canRevealCardPayment`, not the\n // bare fact of being mounted — whether this list can bring the card form back. A rendered card\n // option always can, since card mode needs no method id; without one, only a row bound to a card\n // method can. See `resolveCanRevealCardPayment`'s own doc comment. The dependency list carries it,\n // so the registration re-runs when the method list resolves.\n //\n // Fix pass round 2 (flash regression): `useLayoutEffect`, not `useEffect` — mirroring\n // `place-order.tsx`'s own `setPlacing` registration, the structurally identical precedent for\n // publishing a ref-counted fact to this shared engine from a leaf's mount. A passive effect runs\n // after the browser has already painted, so a root whose persisted selection is genuinely out of\n // scope committed one real frame with `methodListMounted` still `false` — the collapse (then\n // `selectionOutOfScope && methodListMounted`, now `cardPaymentCollapsed`) computed `false` for that\n // frame, painting the card form visible, focusable, and with its security code not yet cleared,\n // before the registration ever landed and a second commit hid it. A layout effect's own state update\n // is guaranteed to flush synchronously before the browser paints, so the very first frame a shopper\n // can ever see already reflects `methodListMounted`. The card leaves read it purely at render time,\n // not from an effect of their own, so this reorders nothing on that side: whichever commit this\n // layout effect's own update produces is the one their next render (still pre-paint) sees.\n const instanceKey = useId();\n useLayoutEffect(() => {\n setMethodListMounted(instanceKey, canRevealCardPayment);\n return () => setMethodListMounted(instanceKey, false);\n }, [instanceKey, setMethodListMounted, canRevealCardPayment]);\n\n // INV-1: only an id the read model supplied is ever dispatched. A standalone row's value *is* its own\n // `method.id`; the collapsed control's value is a DOM value with no method behind it, so it routes\n // through the shared candidate instead (FR-4). With no candidate to name it records card mode, which\n // brings the card form back and sends nothing (T191, FR-6, Decision 6).\n function handleValueChange(value: string) {\n if (value === CARD_CONTROL_VALUE) {\n if (cardCandidateId !== null) {\n selectMethod({ methodId: cardCandidateId });\n } else {\n selectNewCard();\n }\n return;\n }\n selectMethod({ methodId: value });\n }\n\n return (\n <div\n {...props}\n className={className}\n inert={placing}\n aria-disabled={placing || undefined}\n data-fs-payment-method-list=\"\"\n data-fs-payment-method-list-state={methodListState({ loading, count: methods.length })}\n {...(placing ? { 'data-fs-payment-method-list-placing': '' } : {})}\n >\n {selectionError ? (\n <div role=\"alert\" data-fs-payment-method-list-error=\"\">\n {selectionError}\n </div>\n ) : null}\n {methods.length > 0 ? (\n // T38, Decision 1: Fieldset.Root + Fieldset.Legend, exactly what card-entry.tsx:1101-1112\n // already ships — Base UI propagates the legend's id as aria-labelledby onto the descendant\n // RadioGroup, so this one wrapper names both the fieldset and the radiogroup (measured).\n <Fieldset.Root data-fs-payment-method-list-fieldset=\"\">\n <Fieldset.Legend>{resolveAuthoredCopy(legend, 'Payment method')}</Fieldset.Legend>\n <RadioGroup\n value={cardControlChecked ? CARD_CONTROL_VALUE : (selectedMethodId ?? '')}\n onValueChange={handleValueChange}\n >\n {collapsedCardMethods.length > 0 ? (\n // One control for every in-scope credit and debit method (FR-1, Decision 1). Both\n // styling hooks stay exactly where a per-network row carried them — `payment.md`'s\n // styling table documents them, so a store's swatch keeps its selectors.\n <RadioRoot value={CARD_CONTROL_VALUE}>\n <RadioIndicator data-fs-payment-method-indicator=\"\" />\n <span data-fs-payment-method-name=\"\">\n {resolveAuthoredCopy(cardLabel, 'Pay with Credit / Debit Card')}\n </span>\n </RadioRoot>\n ) : null}\n {standaloneMethods.map((method) => (\n <RadioRoot key={method.id} value={method.id}>\n <RadioIndicator data-fs-payment-method-indicator=\"\" />\n <span data-fs-payment-method-name=\"\">{method.name}</span>\n </RadioRoot>\n ))}\n </RadioGroup>\n </Fieldset.Root>\n ) : null}\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"payment.js","names":[],"sources":["../../../src/matter/payment/payment.tsx"],"sourcesContent":["'use client';\n\nimport { defineComponent } from '@vtex/fs-core';\nimport { type ComponentPropsWithRef, createContext, useContext, useId, useLayoutEffect, useMemo } from 'react';\nimport { Fieldset } from '../../particles/fieldset/fieldset.js';\nimport { RadioGroup, RadioIndicator, RadioRoot } from '../../particles/radio/radio.js';\nimport { useActionsOverride } from '../../sdk/actions/actions-override-context.js';\nimport type { ComponentActions } from '../../sdk/actions/types.js';\nimport { useDataOverride } from '../../sdk/data/data-override-context.js';\nimport { PaymentSubmissionProvider } from '../../sdk/payment/submission-registry.js';\nimport { resolveAuthoredCopy } from '../../utils/resolve-authored-copy.js';\nimport { PaymentCardCaptureProvider, type PaymentCartData } from './payment-card-capture.js';\nimport {\n type PaymentMethodSelection,\n type PaymentSectionData,\n resolveCanRevealCardPayment,\n resolvePreselectionCandidateId,\n splitCardMethods,\n usePaymentMethodSelection,\n} from './use-payment-method-selection.js';\n\n/**\n * The `PaymentSection` matter root (specs/payment-section-root.md, T5 of the Credit Card epic;\n * docs/features/credit-card/rfc.md § D1). `PaymentSectionRoot` is the always-visible presentation\n * variant over the `Payment` entity T1 projects: it owns a thin `fragment` (the method list with its\n * server-driven validator config, plus the current selection), runs the shared\n * `usePaymentMethodSelection` engine, and provides the `payment` context its leaves read — the card\n * entry (T7), cardholder document (T8), installments (T9), save-card (T10), billing address (T11),\n * saved cards (T12), and place-order CTA (T14) — through the guarded `usePayment()` hook rather than\n * drilled props (ADR-0009). `PaymentSectionController` (payment-controller.tsx) is the second provider\n * of the same context for a collapsed overlay surface; ADR-0009 matches by contract identifier, so the\n * two substitute for one another with zero edits to any consumer.\n *\n * \"Thin\" means no `installmentOptions` (T9's own fragment), no `savedCards` (T12's), and no\n * `selectedInstallment` (T6's) — the heavy, optional, and iterated subtrees ADR-0011/ADR-0012 split out.\n * `methods[].validator` *is* selected here: it is a non-normalized value object off `Payment.methods`\n * that cannot be subscribed separately, and T7 tests every method's `numberRegex` to detect a network.\n *\n * `children` is the section composition, not a per-method template — the method picker is\n * `PaymentMethodList`, an independently placeable part with its own hooks.\n */\n\n// ---------------------------------------------------------------------------\n// GraphQL Fragment — raw template literal, matching the merged `payment-summary` sibling. The codegen\n// `documents` glob does not scan `src/matter/payment*`, so the typed `graphql()` factory is\n// unavailable here; `data-component-contract.test.ts` validates this fragment against the real schema.\n//\n// Selects `payment { id }` so Apollo's InMemoryCache normalizes `Payment` by id — required for the\n// `Payment` entity that `paymentMethodSelect` echoes back to update the same cache entity this\n// fragment reads. `fetchStrategy: 'reactive'`'s no-refetch guarantee holds only if both sides\n// normalize to one entity.\n// ---------------------------------------------------------------------------\n\nconst fragment = /* GraphQL */ `\n fragment PaymentSectionData on Query {\n payment {\n __typename\n id\n methods {\n __typename\n id\n name\n groupName\n validator {\n __typename\n numberMask\n numberRegex\n cvvMask\n cvvRegex\n cvvRequired\n expirationRequired\n holderNameRequired\n billingAddressRequired\n documentDisplayable\n documentRequired\n }\n }\n selectedMethodId\n selectedAccountId\n selectedBin\n storeCountryCode\n countries {\n __typename\n countryCode\n documents {\n __typename\n type\n displayable\n required\n }\n }\n }\n cart {\n __typename\n id\n total {\n __typename\n amount\n currencyCode\n }\n }\n }\n`;\n\n/**\n * The default payment-group scope: credit and debit (T140, FR-2, Decision 2). Both strings are\n * store-configured, so a store whose groups differ must set `group` explicitly; `group: ''` scopes\n * nothing (specs/payment-section-root.md § Documentation Gaps item 1). Widened from a single string to\n * a set (Decision 1) — a public API break for any consumer importing it directly (Interfaces).\n */\n/**\n * The roots' keyed `$data` (ADR-0015, arity 2): the `Payment` slice the selection engine reads, and the\n * cart total `add_payment_info` needs (moved here from `CardEntry`, which reads no cart).\n */\nexport type PaymentSectionRootData = {\n payment?: PaymentSectionData;\n cart?: PaymentCartData;\n} | null;\n\nexport const DEFAULT_METHOD_GROUP: readonly string[] = ['creditCardPaymentGroup', 'debitCardPaymentGroup'];\n\n// ---------------------------------------------------------------------------\n// Payment context — provided by both section roots, read by every leaf\n// ---------------------------------------------------------------------------\n\n/**\n * The `payment` context contract, normative for T7–T12 and T14. Everything the selection engine\n * resolves, plus the overlay disclosure. What is deliberately absent is part of the contract too: no\n * card number, CVV, expiration, or holder name (RFC D13 — they live only in the card entry's local\n * state); no submission channel for the place-order sequence, which is the separate, narrow\n * `PaymentSubmissionProvider` below (T13) precisely so no card-shaped value ever joins this contract;\n * no `installmentOptions` / `savedCards` / `selectedInstallment` (their owners' fragments); and no\n * optimistic mirror of the persisted selection.\n */\nexport type PaymentContextValue = Readonly<\n PaymentMethodSelection & {\n /** The collapsed surface's disclosure state. Always `true` under `PaymentSectionRoot`. */\n open: boolean;\n /**\n * Drives the collapsed surface. A no-op under `PaymentSectionRoot`, so a leaf written for the\n * overlay composes unchanged inline. Selecting a method never closes the surface on its own — the\n * shopper still has a card to type — so closing is the composition's call (Decision 5).\n */\n setOpen: (open: boolean) => void;\n }\n>;\n\nconst PAYMENT_CONTEXT_UNSET = Symbol('PaymentContextUnset');\n\nconst PaymentContextInternal = createContext<PaymentContextValue | typeof PAYMENT_CONTEXT_UNSET>(PAYMENT_CONTEXT_UNSET);\n\n/** The provider both section roots render. Exported for `PaymentSectionController`. */\nexport const PaymentContext = PaymentContextInternal as React.Context<PaymentContextValue>;\n\n/**\n * Read the payment section's selection state, draft, and overlay disclosure from the nearest\n * `PaymentSectionRoot` or `PaymentSectionController`. Throws outside either subtree — a misplaced\n * consumer is a composition bug the author should see immediately, not a silent degrade to an empty\n * selection — mirroring `useSession()` / `useDeliveryOptions()`. ADR-0009's compiler check catches the\n * same mistake before emission for schema-authored pages; this is the defense-in-depth layer for\n * Storybook, tests, and hand-written JSX.\n */\nexport function usePayment(): PaymentContextValue {\n const ctx = useContext(PaymentContextInternal);\n if (ctx === PAYMENT_CONTEXT_UNSET) {\n throw new Error('usePayment() must be used inside a <PaymentSectionRoot> or <PaymentSectionController> subtree.');\n }\n return ctx;\n}\n\nconst NO_DISCLOSURE = () => {};\n\n// ---------------------------------------------------------------------------\n// Props\n// ---------------------------------------------------------------------------\n\nexport type PaymentSectionRootProps = ComponentPropsWithRef<'div'> & {\n /**\n * Scopes the method list to a **set** of `PaymentMethod.groupName` values — a method is in scope\n * when its `groupName` is a member (T140, FR-1, Decision 1). A single string is still accepted and\n * scopes to exactly that one group (FR-4, US-3). T1's read model is method-agnostic and assigns the\n * narrowing to the consumer; this prop supplies no method, label, or ordering — the list itself is\n * fragment data. An empty string scopes nothing.\n */\n group?: string | readonly string[];\n /** Keyed `{ payment, cart }` forwarded by the reactive runtime (arity-2 fragment, ADR-0015). */\n $data?: PaymentSectionRootData;\n /** Compiler-injected action surface; carries `payment.setMethod`, `payment.sendPayments`, and `analytics.track`. */\n $actions?: ComponentActions;\n};\n\n/** Renders its own controls from the context's method list — `children` would have nothing to template. */\nexport type PaymentMethodListProps = Omit<ComponentPropsWithRef<'div'>, 'children'> & {\n /**\n * The radio group's accessible name, rendered as a visible `Fieldset.Legend` (T38, Decision 1).\n * Resolved through `resolveAuthoredCopy`: an authored empty or whitespace-only string falls back to\n * the default rather than rendering a nameless group.\n */\n legend?: string;\n /**\n * The single card control's name (T171, Decision 8). The control stands for every in-scope\n * credit/debit method at once, so it cannot take its name from one of their `method.name` values the\n * way a per-network row did — it is authored copy instead, defaulting to the PRD's own string.\n * Resolved through `resolveAuthoredCopy` exactly as `legend` is, so an authored empty or\n * whitespace-only string falls back rather than rendering a nameless control.\n */\n cardLabel?: string;\n};\n\n// ---------------------------------------------------------------------------\n// Definitions\n// ---------------------------------------------------------------------------\n\nexport const PaymentSectionRootDefinition = defineComponent<PaymentSectionRootProps>({\n name: 'PaymentSectionRoot',\n importPath: '@vtex/faststore/components',\n component: PaymentSectionRoot,\n fragment,\n fetchStrategy: 'reactive',\n actions: { payment: ['setMethod', 'sendPayments'], analytics: ['track'] },\n providesContext: ['payment', 'card-capture'],\n hardened: true,\n editor: { label: 'Payment Section', category: 'commerce' },\n schema: {\n // A literal, not `DEFAULT_METHOD_GROUP`: the native catalog builder extracts `schema` statically\n // and silently drops an identifier-valued default, so the built entry would carry no default and\n // the compiler would emit the section unscoped. `payment.test.tsx` asserts the literal matches the\n // constant, and that the built catalog kept the default.\n // T140, Decision 2/OQ-6: `type: 'array'` — no code path in packages/sukima/crates/sukima-core/\n // validates an authored prop's JSON value against this declared type, so a store's existing bare\n // string keeps compiling. No `items`: an enum would validate against a closed set of group names,\n // which is wrong for a store that renamed its group (OQ-3) — the exact fragility Decision 1 closes.\n group: {\n type: 'array',\n default: ['creditCardPaymentGroup', 'debitCardPaymentGroup'],\n label: 'Payment method group',\n },\n },\n guideline:\n \"Root of the checkout payment section: reads the payment methods and the current selection from the order form and provides the 'payment' context every payment leaf needs and the 'card-capture' context CardEntry needs, so place CardEntry, CardholderDocument, Installments, SaveCard, BillingAddress, SavedCards, PlaceOrder, and PaymentMethodList as its children — none of them render without a payment root ancestor. Renders one container div and no chrome or copy of its own; headings and layout belong to the composition. Selecting a payment option dispatches $actions.payment.setMethod and every subscriber re-renders from the cache with no refetch — and for a card it is the number the shopper types that decides the network, not an option they pick, so PaymentMethodList shows every in-scope credit and debit method as ONE card option. Which methods exist is always real data — never author them as props; group only scopes the list by the store's payment group(s) — defaults to credit and debit together, accepts one group name or a set of them, and set it to \\\"\\\" to show every method, one option each, with no card option. Use PaymentSectionController instead when the section should live in a drawer or modal. See payment.md.\",\n});\n\nexport const PaymentMethodListDefinition = defineComponent<PaymentMethodListProps>({\n name: 'PaymentMethodList',\n importPath: '@vtex/faststore/components',\n component: PaymentMethodList,\n requiresContext: 'payment',\n editor: { label: 'Payment Method List', category: 'commerce' },\n schema: {\n // T38/T171: inline literals, never identifiers — the native catalog builder extracts `schema`\n // statically and silently drops an identifier-valued default (INV-8).\n legend: { type: 'string', default: 'Payment method', label: 'Legend' },\n cardLabel: { type: 'string', default: 'Pay with Credit / Debit Card', label: 'Card option label' },\n },\n guideline:\n 'The payment-method picker: a radio group of the payment options the order form offers, plus the inline selection error (role=\"alert\"). Every in-scope credit and debit method is ONE option — the network comes from the card number the shopper types, never from a row they pick — and any other in-scope method (e.g. Pix) keeps a row of its own; set group to \"\" on the root to switch that off and get one row per method. Selecting an option dispatches the method selection. Selecting a non-card option hides the card form, and the card option brings it back. Place it inside a PaymentSectionRoot, or inside the DialogPopup/DrawerPopup of a PaymentSectionController. It renders its own options from real data, so it takes no children and no method props; author the card option\\'s wording with cardLabel. Keep it composed: it is the only element that surfaces a rejected selection, and the only control that can recover a selection this section does not serve — omit it and a shopper whose persisted method sits outside group has no reachable way back. Must be inside a payment root.',\n});\n\n// ---------------------------------------------------------------------------\n// Implementations\n// ---------------------------------------------------------------------------\n\nexport function PaymentSectionRoot({\n group = DEFAULT_METHOD_GROUP,\n $data: $dataProp,\n $actions: $actionsProp,\n className,\n children,\n ...props\n}: PaymentSectionRootProps) {\n const $data = useDataOverride($dataProp);\n const $actions = useActionsOverride($actionsProp);\n const selection = usePaymentMethodSelection({ group, $data: $data?.payment ?? null, $actions });\n const payment = useMemo<PaymentContextValue>(\n () => ({ ...selection, open: true, setOpen: NO_DISCLOSURE }),\n [selection],\n );\n\n return (\n <PaymentContextInternal value={payment}>\n <PaymentSubmissionProvider path={selection.draft.path}>\n <PaymentCardCaptureProvider selection={selection} cart={$data?.cart} $actions={$actions}>\n <div\n {...props}\n className={className}\n data-fs-payment-section=\"\"\n {...(selection.draft.path ? { 'data-fs-payment-section-path': selection.draft.path } : {})}\n // T28, Decision 5: presence attribute only, deliberately never `inert` — `PlaceOrder` composes\n // as a child of this same container (FR-6), so making it inert here would swallow the CTA's\n // own role=\"alert\"/role=\"status\" regions, the shopper's only channel for the outcome.\n {...(selection.placing ? { 'data-fs-payment-section-placing': '' } : {})}\n >\n {children}\n </div>\n </PaymentCardCaptureProvider>\n </PaymentSubmissionProvider>\n </PaymentContextInternal>\n );\n}\n\n/**\n * The picker's presence state, always emitted so a swatch can surface a row-less container — otherwise\n * a zero-height element under any stacking swatch, and the \"visible empty region\" the section's\n * group-default risk is accepted on. `loading` (still resolving) and `empty` (resolved, nothing in\n * scope) stay distinct: one is a wait, the other a misconfiguration.\n */\nfunction methodListState({ loading, count }: { loading: boolean; count: number }): 'loading' | 'empty' | 'ready' {\n if (loading) return 'loading';\n if (count === 0) return 'empty';\n return 'ready';\n}\n\n/**\n * The DOM value the collapsed card control carries inside the `RadioGroup`. Base UI requires every\n * radio root to have one, and this control stands for N methods, so there is no `method.id` it could\n * use.\n *\n * It is a radio-group value and nothing else — **never a method id** (INV-1, ADR-0023). It is never\n * dispatched: `handleValueChange` below maps it back to `resolvePreselectionCandidateId`'s answer\n * before calling `selectMethod`, and records card mode through `selectNewCard()`, which dispatches\n * nothing, when there is no candidate (T191, FR-6). The prefix keeps it from ever colliding with a\n * `PaymentMethod.id` a standalone row is bound to.\n */\nconst CARD_CONTROL_VALUE = '__fs-card-control';\n\nexport function PaymentMethodList({ legend, cardLabel, className, ...props }: PaymentMethodListProps) {\n const {\n methods,\n allMethods,\n persistedMethodId,\n selectedMethodId,\n selectionError,\n selectMethod,\n selectNewCard,\n cardModeActive,\n loading,\n placing,\n setMethodListMounted,\n } = usePayment();\n\n // T171, FR-1/FR-2: one control for the in-scope card methods, one row for every other in-scope\n // method. Memoized off the two lists only (NFR-5) — nothing here may widen what re-creates the\n // `payment` context value, which a keystroke already churns enough.\n const { collapsedCardMethods, standaloneMethods } = useMemo(\n () => splitCardMethods({ methods, allMethods }),\n [methods, allMethods],\n );\n // Decision 3: the collapsed control dispatches the *shared* preselection candidate, so the escape\n // hatch and the preselection can never disagree about whether an id is available.\n const cardCandidateId = useMemo(() => resolvePreselectionCandidateId(methods), [methods]);\n const canRevealCardPayment = resolveCanRevealCardPayment({ collapsedCardMethods, standaloneMethods });\n\n // Decision 2: derived, never bound to one `method.id` — a control standing for N methods has none.\n // Checked when the persisted selection resolves inside the collapsed set, and when nothing is\n // persisted at all (PRD REQ-02's \"the card payment option is selected by default\"). The second arm\n // is a deliberate divergence from the pre-T171 bound-to-`$data` behaviour: the control can read\n // checked while `$data.selectedMethodId` is still null, having dispatched nothing. `persistedMethodId`\n // is the raw, unscoped fact on purpose — a persisted method this section does not serve must leave the\n // control unchecked, which is what keeps it activatable as US-5's way back. T191 (FR-6): card mode is\n // the third arm, the card option chosen over such a selection or over a non-card one.\n const cardControlChecked =\n collapsedCardMethods.length > 0 &&\n (persistedMethodId === null ||\n collapsedCardMethods.some((method) => method.id === selectedMethodId) ||\n cardModeActive);\n\n // Fix pass, finding R2: registers this instance with the shared engine so the card leaves know an\n // escape hatch exists before they ever collapse — a section composed with no `PaymentMethodList` at\n // all must never hide the only remaining way to change the method (typing a new card number).\n // Retracted unconditionally on unmount, unlike `setPlacing`'s own \"leave it if still placing\"\n // carve-out: there is no in-flight sequence here for an abandoned instance to still be part of.\n //\n // T191, Decision 5 (after T171's Decision 4): what is registered is `canRevealCardPayment`, not the\n // bare fact of being mounted — whether this list can bring the card form back. A rendered card\n // option always can, since card mode needs no method id; without one, only a row bound to a card\n // method can. See `resolveCanRevealCardPayment`'s own doc comment. The dependency list carries it,\n // so the registration re-runs when the method list resolves.\n //\n // Fix pass round 2 (flash regression): `useLayoutEffect`, not `useEffect` — mirroring\n // `place-order.tsx`'s own `setPlacing` registration, the structurally identical precedent for\n // publishing a ref-counted fact to this shared engine from a leaf's mount. A passive effect runs\n // after the browser has already painted, so a root whose persisted selection is genuinely out of\n // scope committed one real frame with `methodListMounted` still `false` — the collapse (then\n // `selectionOutOfScope && methodListMounted`, now `cardPaymentCollapsed`) computed `false` for that\n // frame, painting the card form visible, focusable, and with its security code not yet cleared,\n // before the registration ever landed and a second commit hid it. A layout effect's own state update\n // is guaranteed to flush synchronously before the browser paints, so the very first frame a shopper\n // can ever see already reflects `methodListMounted`. The card leaves read it purely at render time,\n // not from an effect of their own, so this reorders nothing on that side: whichever commit this\n // layout effect's own update produces is the one their next render (still pre-paint) sees.\n const instanceKey = useId();\n useLayoutEffect(() => {\n setMethodListMounted(instanceKey, canRevealCardPayment);\n return () => setMethodListMounted(instanceKey, false);\n }, [instanceKey, setMethodListMounted, canRevealCardPayment]);\n\n // INV-1: only an id the read model supplied is ever dispatched. A standalone row's value *is* its own\n // `method.id`; the collapsed control's value is a DOM value with no method behind it, so it routes\n // through the shared candidate instead (FR-4). With no candidate to name it records card mode, which\n // brings the card form back and sends nothing (T191, FR-6, Decision 6).\n function handleValueChange(value: string) {\n if (value === CARD_CONTROL_VALUE) {\n if (cardCandidateId !== null) {\n selectMethod({ methodId: cardCandidateId });\n } else {\n selectNewCard();\n }\n return;\n }\n selectMethod({ methodId: value });\n }\n\n return (\n <div\n {...props}\n className={className}\n inert={placing}\n aria-disabled={placing || undefined}\n data-fs-payment-method-list=\"\"\n data-fs-payment-method-list-state={methodListState({ loading, count: methods.length })}\n {...(placing ? { 'data-fs-payment-method-list-placing': '' } : {})}\n >\n {selectionError ? (\n <div role=\"alert\" data-fs-payment-method-list-error=\"\">\n {selectionError}\n </div>\n ) : null}\n {methods.length > 0 ? (\n // T38, Decision 1: Fieldset.Root + Fieldset.Legend, exactly what card-entry.tsx:1101-1112\n // already ships — Base UI propagates the legend's id as aria-labelledby onto the descendant\n // RadioGroup, so this one wrapper names both the fieldset and the radiogroup (measured).\n <Fieldset.Root data-fs-payment-method-list-fieldset=\"\">\n <Fieldset.Legend>{resolveAuthoredCopy(legend, 'Payment method')}</Fieldset.Legend>\n <RadioGroup\n value={cardControlChecked ? CARD_CONTROL_VALUE : (selectedMethodId ?? '')}\n onValueChange={handleValueChange}\n >\n {collapsedCardMethods.length > 0 ? (\n // One control for every in-scope credit and debit method (FR-1, Decision 1). Both\n // styling hooks stay exactly where a per-network row carried them — `payment.md`'s\n // styling table documents them, so a store's swatch keeps its selectors.\n <RadioRoot value={CARD_CONTROL_VALUE}>\n <RadioIndicator data-fs-payment-method-indicator=\"\" />\n <span data-fs-payment-method-name=\"\">\n {resolveAuthoredCopy(cardLabel, 'Pay with Credit / Debit Card')}\n </span>\n </RadioRoot>\n ) : null}\n {standaloneMethods.map((method) => (\n <RadioRoot key={method.id} value={method.id}>\n <RadioIndicator data-fs-payment-method-indicator=\"\" />\n <span data-fs-payment-method-name=\"\">{method.name}</span>\n </RadioRoot>\n ))}\n </RadioGroup>\n </Fieldset.Root>\n ) : null}\n </div>\n );\n}\n"],"mappings":"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"}
@@ -1,7 +1,9 @@
1
1
  import { PaymentMethodSelectInput } from "../../sdk/payment/operations.js";
2
2
  import "../../sdk/actions/types.js";
3
3
  import { PaymentSubmissionPath } from "../../sdk/payment/submission-registry.js";
4
+ import { DocumentType } from "../../particles/document-field/document-field.js";
4
5
  import { PlaceOrderAttempt, SetPlaceOrderAttempt } from "../../sdk/payment/use-place-order.js";
6
+ import { PaymentRefusalTarget } from "./use-payment-submit-gate.js";
5
7
  //#region src/matter/payment/use-payment-method-selection.d.ts
6
8
  /**
7
9
  * The payment section's selection engine (specs/payment-section-root.md, T5 of the Credit Card epic).
@@ -34,12 +36,27 @@ export type PaymentSectionMethod = Readonly<{
34
36
  groupName: string;
35
37
  validator: PaymentSectionValidator;
36
38
  }>;
39
+ /** One document type a country's table lists. `type` is the API's lower-case id (`ssn`, `cpf`, `sin`, `rfc`). */
40
+ export type PaymentSectionCountryDocument = Readonly<{
41
+ type: string;
42
+ displayable: boolean;
43
+ required: boolean;
44
+ }>;
45
+ /** One row of `Payment.countries` (T213). */
46
+ export type PaymentSectionCountry = Readonly<{
47
+ countryCode: string;
48
+ documents: readonly PaymentSectionCountryDocument[];
49
+ }>;
37
50
  export type PaymentSectionData = {
38
51
  methods?: readonly PaymentSectionMethod[];
39
52
  selectedMethodId?: string | null;
40
53
  selectedAccountId?: string | null;
41
54
  /** Persisted BIN off `payments[0]`. `undefined` while the entity resolves or when a hand-written slice omits it. */
42
55
  selectedBin?: string | null;
56
+ /** The store's ISO 3166-1 alpha-3 country (`USA`), or `null` when the order form carries none (T213). */
57
+ storeCountryCode?: string | null;
58
+ /** The per-country document table (T213). `undefined` when a hand-written slice omits it. */
59
+ countries?: readonly PaymentSectionCountry[];
43
60
  } | null;
44
61
  /**
45
62
  * Which entry path the shopper is on. Aliases the submission channel's key type (T13), which the
@@ -138,6 +155,12 @@ export type PaymentMethodSelection = {
138
155
  * `selectedMethodId` (T74, Decision 4/7).
139
156
  */
140
157
  persistedMethodId: string | null;
158
+ /**
159
+ * The document type the store's country asks for (`resolveCountryDocumentType`, T42), or `null` when
160
+ * the country is unlisted, absent or has no displayable type this build knows. The country half of the
161
+ * cardholder-document rule; the selected method supplies the other half (`resolveCardholderDocument`).
162
+ */
163
+ countryDocumentType: DocumentType | null;
141
164
  /**
142
165
  * The persisted selection **as this section serves it** — `selectedMethod?.id ?? null`. `null` both
143
166
  * when nothing is persisted and when what is persisted sits outside `group`; `persistedMethodId`
@@ -297,6 +320,22 @@ export type PaymentMethodSelection = {
297
320
  * clobbering a newer outcome.
298
321
  */
299
322
  setAttempt: SetPlaceOrderAttempt;
323
+ /**
324
+ * Registers how one leaf takes focus when a refusal names it (T212, docs/features/credit-card-r2/rfc.md
325
+ * § D21). `focus` returns `true` only when the element took focus. Returns a function that removes
326
+ * exactly this entry; calling it twice is a no-op. Backed by a ref, so registering or unregistering
327
+ * never changes this object's identity or re-renders the section (NFR-2); identity is stable for the
328
+ * root's lifetime.
329
+ */
330
+ registerRefusalFocus: (target: PaymentRefusalTarget, focus: () => boolean) => () => void;
331
+ /**
332
+ * Calls the target's registered functions in registration order and stops at the first that returns
333
+ * `true`. `false` when none did, including when none is registered. A function that throws counts as
334
+ * having declined: the error is contained here so a third-party leaf's `focus` can never become an
335
+ * unhandled rejection in the click that called this, and the next entry is still tried. Identity is
336
+ * stable for the root's lifetime.
337
+ */
338
+ focusRefusal: (target: PaymentRefusalTarget) => boolean;
300
339
  };
301
340
  //#endregion
302
341
  //# sourceMappingURL=use-payment-method-selection.d.ts.map
@@ -1,4 +1,5 @@
1
1
  "use client";
2
+ import { resolveCountryDocumentType } from "./cardholder-document-rule.js";
2
3
  import { useCallback, useEffect, useMemo, useRef, useState } from "react";
3
4
  //#region src/matter/payment/use-payment-method-selection.ts
4
5
  const EMPTY_METHODS = [];
@@ -200,6 +201,12 @@ function usePaymentMethodSelection({ group, $data, $actions }) {
200
201
  const allMethods = $data?.methods ?? EMPTY_METHODS;
201
202
  const persistedMethodId = $data?.selectedMethodId ?? null;
202
203
  const selectedAccountId = $data?.selectedAccountId ?? null;
204
+ const storeCountryCode = $data?.storeCountryCode;
205
+ const countries = $data?.countries;
206
+ const countryDocumentType = useMemo(() => resolveCountryDocumentType({
207
+ storeCountryCode,
208
+ countries
209
+ }), [storeCountryCode, countries]);
203
210
  const methods = useMemo(() => {
204
211
  if (group === "") return allMethods;
205
212
  const groups = typeof group === "string" ? [group] : group;
@@ -344,6 +351,21 @@ function usePaymentMethodSelection({ group, $data, $actions }) {
344
351
  return { mountedKeys: nextKeys };
345
352
  });
346
353
  }, []);
354
+ const refusalFocusRef = useRef(/* @__PURE__ */ new Map());
355
+ const registerRefusalFocus = useCallback((target, focus) => {
356
+ const entry = { focus };
357
+ refusalFocusRef.current.set(target, [...refusalFocusRef.current.get(target) ?? [], entry]);
358
+ return () => {
359
+ const entries = refusalFocusRef.current.get(target);
360
+ if (entries) refusalFocusRef.current.set(target, entries.filter((candidate) => candidate !== entry));
361
+ };
362
+ }, []);
363
+ const focusRefusal = useCallback((target) => {
364
+ for (const { focus } of refusalFocusRef.current.get(target) ?? []) try {
365
+ if (focus()) return true;
366
+ } catch {}
367
+ return false;
368
+ }, []);
347
369
  const attemptResolved = attempt !== null && (attempt.phase === "refused" || attempt.phase === "settled");
348
370
  const placing = placingState.placingKeys.size > 0 && !attemptResolved;
349
371
  const attemptedPreselectionIdsRef = useRef(/* @__PURE__ */ new Set());
@@ -401,6 +423,7 @@ function usePaymentMethodSelection({ group, $data, $actions }) {
401
423
  methods,
402
424
  allMethods,
403
425
  persistedMethodId,
426
+ countryDocumentType,
404
427
  selectedMethodId,
405
428
  selectionOutOfScope,
406
429
  methodListMounted,
@@ -425,11 +448,14 @@ function usePaymentMethodSelection({ group, $data, $actions }) {
425
448
  placing,
426
449
  setPlacing,
427
450
  attempt,
428
- setAttempt
451
+ setAttempt,
452
+ registerRefusalFocus,
453
+ focusRefusal
429
454
  }), [
430
455
  methods,
431
456
  allMethods,
432
457
  persistedMethodId,
458
+ countryDocumentType,
433
459
  selectedMethodId,
434
460
  selectionOutOfScope,
435
461
  methodListMounted,
@@ -449,7 +475,9 @@ function usePaymentMethodSelection({ group, $data, $actions }) {
449
475
  setDraftBillingAddressUnsaved,
450
476
  placing,
451
477
  setPlacing,
452
- attempt
478
+ attempt,
479
+ registerRefusalFocus,
480
+ focusRefusal
453
481
  ]);
454
482
  }
455
483
  //#endregion