@vtex/faststore 0.0.7 → 0.0.8

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 (411) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/dist/actions.json +152 -1
  3. package/dist/catalog.json +1264 -142
  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 +34 -7
  12. package/dist/components.js +38 -11
  13. package/dist/content-types.json +523 -0
  14. package/dist/core/dist/define-component.d.ts +6 -1
  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 +1 -1
  18. package/dist/docs/account-menu.md +5 -5
  19. package/dist/docs/alert-dialog.md +2 -2
  20. package/dist/docs/billing-address.md +17 -9
  21. package/dist/docs/card-entry.md +37 -6
  22. package/dist/docs/cardholder-document.md +16 -14
  23. package/dist/docs/cart-item.md +1 -1
  24. package/dist/docs/cart.md +8 -8
  25. package/dist/docs/client-profile-fieldset.md +7 -5
  26. package/dist/docs/copy-text.md +84 -0
  27. package/dist/docs/document-field.md +8 -8
  28. package/dist/docs/footer-link-group.md +2 -2
  29. package/dist/docs/header-root.md +1 -1
  30. package/dist/docs/incentives.md +2 -2
  31. package/dist/docs/logo.md +5 -5
  32. package/dist/docs/my-account-profile.md +4 -4
  33. package/dist/docs/navigation-link-list.md +2 -2
  34. package/dist/docs/navigation-link.md +3 -3
  35. package/dist/docs/order-cancel.md +52 -0
  36. package/dist/docs/order-delivery-address.md +63 -0
  37. package/dist/docs/order-delivery-group.md +83 -0
  38. package/dist/docs/order-details-back.md +41 -0
  39. package/dist/docs/order-details-header.md +48 -0
  40. package/dist/docs/order-list-row.md +46 -0
  41. package/dist/docs/order-list-search.md +101 -0
  42. package/dist/docs/order-list-views.md +97 -0
  43. package/dist/docs/order-list.md +94 -0
  44. package/dist/docs/order-payment.md +94 -0
  45. package/dist/docs/order-placed-date.md +49 -0
  46. package/dist/docs/order-placed-payment-summary.md +13 -15
  47. package/dist/docs/order-placed.md +225 -0
  48. package/dist/docs/order-progress.md +88 -0
  49. package/dist/docs/order-status-badge.md +91 -0
  50. package/dist/docs/order-summary.md +53 -0
  51. package/dist/docs/payment-method-badges.md +14 -3
  52. package/dist/docs/place-order.md +13 -9
  53. package/dist/docs/saved-cards.md +2 -2
  54. package/dist/docs/select.md +19 -6
  55. package/dist/docs/session.md +1 -1
  56. package/dist/docs/shipping-address.md +1 -1
  57. package/dist/docs/sign-in-redirect.md +6 -6
  58. package/dist/docs/toast.md +7 -3
  59. package/dist/index.d.ts +6 -2
  60. package/dist/index.js +2 -1
  61. package/dist/internal/client.d.ts +6 -1
  62. package/dist/internal/client.js +7 -2
  63. package/dist/internal/server.d.ts +6 -2
  64. package/dist/internal/server.js +6 -2
  65. package/dist/matter/account-access-gate/account-access-gate.d.ts +2 -1
  66. package/dist/matter/account-access-gate/account-access-gate.js +19 -16
  67. package/dist/matter/account-access-gate/account-access-gate.js.map +1 -1
  68. package/dist/matter/account-address-book/account-address-book-delete.d.ts +60 -0
  69. package/dist/matter/account-address-book/account-address-book-delete.js +184 -0
  70. package/dist/matter/account-address-book/account-address-book-delete.js.map +1 -0
  71. package/dist/matter/account-address-book/account-address-book-deliverability.d.ts +19 -0
  72. package/dist/matter/account-address-book/account-address-book-deliverability.js +50 -0
  73. package/dist/matter/account-address-book/account-address-book-deliverability.js.map +1 -0
  74. package/dist/matter/account-address-book/account-address-book-form-parts.d.ts +42 -0
  75. package/dist/matter/account-address-book/account-address-book-form-parts.js +146 -0
  76. package/dist/matter/account-address-book/account-address-book-form-parts.js.map +1 -0
  77. package/dist/matter/account-address-book/account-address-book-profile-notice.d.ts +25 -0
  78. package/dist/matter/account-address-book/account-address-book-profile-notice.js +72 -0
  79. package/dist/matter/account-address-book/account-address-book-profile-notice.js.map +1 -0
  80. package/dist/matter/account-address-book/account-address-book.d.ts +120 -0
  81. package/dist/matter/account-address-book/account-address-book.js +469 -0
  82. package/dist/matter/account-address-book/account-address-book.js.map +1 -0
  83. package/dist/matter/account-address-book/account-address-country-switch.js +59 -0
  84. package/dist/matter/account-address-book/account-address-country-switch.js.map +1 -0
  85. package/dist/matter/account-address-book/account-address-country.d.ts +36 -0
  86. package/dist/matter/account-address-book/account-address-country.js +151 -0
  87. package/dist/matter/account-address-book/account-address-country.js.map +1 -0
  88. package/dist/matter/account-address-book/account-address-first-line.js +11 -0
  89. package/dist/matter/account-address-book/account-address-first-line.js.map +1 -0
  90. package/dist/matter/account-address-book/account-address-form-context.d.ts +55 -0
  91. package/dist/matter/account-address-book/account-address-form-context.js +14 -0
  92. package/dist/matter/account-address-book/account-address-form-context.js.map +1 -0
  93. package/dist/matter/account-address-book/account-address-form.d.ts +85 -0
  94. package/dist/matter/account-address-book/account-address-form.js +946 -0
  95. package/dist/matter/account-address-book/account-address-form.js.map +1 -0
  96. package/dist/matter/account-address-book/account-address-postal-autofill.js +189 -0
  97. package/dist/matter/account-address-book/account-address-postal-autofill.js.map +1 -0
  98. package/dist/matter/account-address-book/account-address-record.d.ts +26 -0
  99. package/dist/matter/account-address-book/account-address-record.js +138 -0
  100. package/dist/matter/account-address-book/account-address-record.js.map +1 -0
  101. package/dist/matter/account-entry-point/account-entry-point.js +11 -11
  102. package/dist/matter/account-entry-point/account-entry-point.js.map +1 -1
  103. package/dist/matter/account-menu/account-menu.d.ts +7 -3
  104. package/dist/matter/account-menu/account-menu.js +69 -28
  105. package/dist/matter/account-menu/account-menu.js.map +1 -1
  106. package/dist/matter/billing-address/billing-address.d.ts +30 -17
  107. package/dist/matter/billing-address/billing-address.js +128 -33
  108. package/dist/matter/billing-address/billing-address.js.map +1 -1
  109. package/dist/matter/breadcrumb/breadcrumb.js +2 -2
  110. package/dist/matter/breadcrumb/breadcrumb.js.map +1 -1
  111. package/dist/matter/card-entry/card-capture.js +4 -3
  112. package/dist/matter/card-entry/card-capture.js.map +1 -1
  113. package/dist/matter/card-entry/card-entry.d.ts +5 -3
  114. package/dist/matter/card-entry/card-entry.js +77 -27
  115. package/dist/matter/card-entry/card-entry.js.map +1 -1
  116. package/dist/matter/cardholder-document/cardholder-document.d.ts +10 -9
  117. package/dist/matter/cardholder-document/cardholder-document.js +36 -16
  118. package/dist/matter/cardholder-document/cardholder-document.js.map +1 -1
  119. package/dist/matter/cart/cart.d.ts +7 -2
  120. package/dist/matter/cart/cart.js +29 -26
  121. package/dist/matter/cart/cart.js.map +1 -1
  122. package/dist/matter/cart-item/cart-item.js +2 -2
  123. package/dist/matter/cart-item/cart-item.js.map +1 -1
  124. package/dist/matter/client-preferences/client-preferences-fieldset.js +1 -1
  125. package/dist/matter/client-profile-form/client-profile-fieldset.js +8 -5
  126. package/dist/matter/client-profile-form/client-profile-fieldset.js.map +1 -1
  127. package/dist/matter/identity-edit/identity-edit.js +3 -3
  128. package/dist/matter/identity-edit/identity-edit.js.map +1 -1
  129. package/dist/matter/identity-summary/identity-summary.js +2 -2
  130. package/dist/matter/identity-summary/identity-summary.js.map +1 -1
  131. package/dist/matter/my-account-profile/my-account-profile.d.ts +3 -3
  132. package/dist/matter/my-account-profile/my-account-profile.js +4 -4
  133. package/dist/matter/my-account-profile/my-account-profile.js.map +1 -1
  134. package/dist/matter/order-cancel/order-cancel.d.ts +110 -0
  135. package/dist/matter/order-cancel/order-cancel.js +344 -0
  136. package/dist/matter/order-cancel/order-cancel.js.map +1 -0
  137. package/dist/matter/order-delivery-address/order-delivery-address.d.ts +73 -0
  138. package/dist/matter/order-delivery-address/order-delivery-address.js +172 -0
  139. package/dist/matter/order-delivery-address/order-delivery-address.js.map +1 -0
  140. package/dist/matter/order-delivery-group/order-delivery-group.d.ts +128 -0
  141. package/dist/matter/order-delivery-group/order-delivery-group.js +408 -0
  142. package/dist/matter/order-delivery-group/order-delivery-group.js.map +1 -0
  143. package/dist/matter/order-details-header/order-details-header.d.ts +104 -0
  144. package/dist/matter/order-details-header/order-details-header.js +190 -0
  145. package/dist/matter/order-details-header/order-details-header.js.map +1 -0
  146. package/dist/matter/order-list/customer-orders-filter.d.ts +12 -0
  147. package/dist/matter/order-list/customer-orders-filter.js +30 -0
  148. package/dist/matter/order-list/customer-orders-filter.js.map +1 -0
  149. package/dist/matter/order-list/order-list.d.ts +121 -0
  150. package/dist/matter/order-list/order-list.js +395 -0
  151. package/dist/matter/order-list/order-list.js.map +1 -0
  152. package/dist/matter/order-list-row/order-list-row.d.ts +44 -0
  153. package/dist/matter/order-list-row/order-list-row.js +127 -0
  154. package/dist/matter/order-list-row/order-list-row.js.map +1 -0
  155. package/dist/matter/order-list-search/order-list-search.d.ts +72 -0
  156. package/dist/matter/order-list-search/order-list-search.js +296 -0
  157. package/dist/matter/order-list-search/order-list-search.js.map +1 -0
  158. package/dist/matter/order-list-views/order-list-views.d.ts +65 -0
  159. package/dist/matter/order-list-views/order-list-views.js +154 -0
  160. package/dist/matter/order-list-views/order-list-views.js.map +1 -0
  161. package/dist/matter/order-payment/order-payment.d.ts +83 -0
  162. package/dist/matter/order-payment/order-payment.js +258 -0
  163. package/dist/matter/order-payment/order-payment.js.map +1 -0
  164. package/dist/matter/order-placed/order-placed-deliveries.d.ts +145 -0
  165. package/dist/matter/order-placed/order-placed-deliveries.js +380 -0
  166. package/dist/matter/order-placed/order-placed-deliveries.js.map +1 -0
  167. package/dist/matter/order-placed/order-placed.d.ts +122 -0
  168. package/dist/matter/order-placed/order-placed.js +452 -0
  169. package/dist/matter/order-placed/order-placed.js.map +1 -0
  170. package/dist/matter/order-placed-date/order-placed-date.d.ts +45 -0
  171. package/dist/matter/order-placed-date/order-placed-date.js +92 -0
  172. package/dist/matter/order-placed-date/order-placed-date.js.map +1 -0
  173. package/dist/matter/order-placed-payment-summary/order-placed-payment-summary.d.ts +5 -8
  174. package/dist/matter/order-placed-payment-summary/order-placed-payment-summary.js +29 -81
  175. package/dist/matter/order-placed-payment-summary/order-placed-payment-summary.js.map +1 -1
  176. package/dist/matter/order-progress/order-progress.d.ts +85 -0
  177. package/dist/matter/order-progress/order-progress.js +203 -0
  178. package/dist/matter/order-progress/order-progress.js.map +1 -0
  179. package/dist/matter/order-summary/order-summary.d.ts +81 -0
  180. package/dist/matter/order-summary/order-summary.js +192 -0
  181. package/dist/matter/order-summary/order-summary.js.map +1 -0
  182. package/dist/matter/payment/cardholder-document-rule.d.ts +35 -0
  183. package/dist/matter/payment/cardholder-document-rule.js +35 -0
  184. package/dist/matter/payment/cardholder-document-rule.js.map +1 -0
  185. package/dist/matter/payment/payment-card-capture.js +38 -23
  186. package/dist/matter/payment/payment-card-capture.js.map +1 -1
  187. package/dist/matter/payment/payment-controller.js +11 -0
  188. package/dist/matter/payment/payment-controller.js.map +1 -1
  189. package/dist/matter/payment/payment-method-badges.js +4 -2
  190. package/dist/matter/payment/payment-method-badges.js.map +1 -1
  191. package/dist/matter/payment/payment.js +11 -0
  192. package/dist/matter/payment/payment.js.map +1 -1
  193. package/dist/matter/payment/use-payment-method-selection.d.ts +39 -0
  194. package/dist/matter/payment/use-payment-method-selection.js +30 -2
  195. package/dist/matter/payment/use-payment-method-selection.js.map +1 -1
  196. package/dist/matter/payment/use-payment-submit-gate.d.ts +16 -2
  197. package/dist/matter/payment/use-payment-submit-gate.js +42 -14
  198. package/dist/matter/payment/use-payment-submit-gate.js.map +1 -1
  199. package/dist/matter/place-order/place-order.d.ts +12 -7
  200. package/dist/matter/place-order/place-order.js +126 -103
  201. package/dist/matter/place-order/place-order.js.map +1 -1
  202. package/dist/matter/pricing/pricing.js +5 -5
  203. package/dist/matter/pricing/pricing.js.map +1 -1
  204. package/dist/matter/region/region.js +1 -1
  205. package/dist/matter/saved-cards/saved-cards.js +26 -15
  206. package/dist/matter/saved-cards/saved-cards.js.map +1 -1
  207. package/dist/matter/session/session.js +2 -2
  208. package/dist/matter/session/session.js.map +1 -1
  209. package/dist/matter/shipping-address/country-descriptors.d.ts +1 -0
  210. package/dist/matter/shipping-address/country-descriptors.js +23 -1
  211. package/dist/matter/shipping-address/country-descriptors.js.map +1 -1
  212. package/dist/matter/shipping-address/shipping-address.js +62 -14
  213. package/dist/matter/shipping-address/shipping-address.js.map +1 -1
  214. package/dist/matter/shipping-simulator/shipping-simulator.d.ts +1 -1
  215. package/dist/matter/shipping-simulator/shipping-simulator.js.map +1 -1
  216. package/dist/matter/sign-in-redirect/sign-in-redirect.js +48 -10
  217. package/dist/matter/sign-in-redirect/sign-in-redirect.js.map +1 -1
  218. package/dist/matter/variant-selector/variant-selector.js +2 -2
  219. package/dist/matter/variant-selector/variant-selector.js.map +1 -1
  220. package/dist/particles/address-summary/address-summary.js +2 -2
  221. package/dist/particles/address-summary/address-summary.js.map +1 -1
  222. package/dist/particles/alert-dialog/alert-dialog.d.ts +5 -1
  223. package/dist/particles/alert-dialog/alert-dialog.js +5 -2
  224. package/dist/particles/alert-dialog/alert-dialog.js.map +1 -1
  225. package/dist/particles/copy-text/copy-text.d.ts +28 -0
  226. package/dist/particles/copy-text/copy-text.js +140 -0
  227. package/dist/particles/copy-text/copy-text.js.map +1 -0
  228. package/dist/particles/document-field/document-field.d.ts +34 -5
  229. package/dist/particles/document-field/document-field.js +115 -19
  230. package/dist/particles/document-field/document-field.js.map +1 -1
  231. package/dist/particles/field/field.js +1 -1
  232. package/dist/particles/field/field.js.map +1 -1
  233. package/dist/particles/footer-link-group/footer-link-group.d.ts +6 -2
  234. package/dist/particles/footer-link-group/footer-link-group.js +18 -7
  235. package/dist/particles/footer-link-group/footer-link-group.js.map +1 -1
  236. package/dist/particles/incentives/incentives.d.ts +6 -2
  237. package/dist/particles/incentives/incentives.js +7 -2
  238. package/dist/particles/incentives/incentives.js.map +1 -1
  239. package/dist/particles/logo/logo.d.ts +3 -2
  240. package/dist/particles/logo/logo.js +20 -8
  241. package/dist/particles/logo/logo.js.map +1 -1
  242. package/dist/particles/navigation-link/navigation-link.d.ts +2 -3
  243. package/dist/particles/navigation-link/navigation-link.js +4 -4
  244. package/dist/particles/navigation-link/navigation-link.js.map +1 -1
  245. package/dist/particles/navigation-link-list/navigation-link-list.d.ts +6 -2
  246. package/dist/particles/navigation-link-list/navigation-link-list.js +18 -7
  247. package/dist/particles/navigation-link-list/navigation-link-list.js.map +1 -1
  248. package/dist/particles/order-details-back/order-details-back.d.ts +28 -0
  249. package/dist/particles/order-details-back/order-details-back.js +52 -0
  250. package/dist/particles/order-details-back/order-details-back.js.map +1 -0
  251. package/dist/particles/order-status-badge/order-status-badge.d.ts +19 -0
  252. package/dist/particles/order-status-badge/order-status-badge.js +50 -0
  253. package/dist/particles/order-status-badge/order-status-badge.js.map +1 -0
  254. package/dist/particles/phone-field/phone-field.js +2 -2
  255. package/dist/particles/phone-field/phone-field.js.map +1 -1
  256. package/dist/particles/select/select.js +6 -6
  257. package/dist/particles/select/select.js.map +1 -1
  258. package/dist/particles/toast/toast.d.ts +1 -1
  259. package/dist/particles/toast/toast.js +32 -6
  260. package/dist/particles/toast/toast.js.map +1 -1
  261. package/dist/schema.graphql +1014 -28
  262. package/dist/sdk/actions/address-action-provider.d.ts +16 -0
  263. package/dist/sdk/actions/address-action-provider.js +20 -0
  264. package/dist/sdk/actions/address-action-provider.js.map +1 -0
  265. package/dist/sdk/actions/analytics-action-provider.js +1 -1
  266. package/dist/sdk/actions/index.d.ts +3 -1
  267. package/dist/sdk/actions/index.js +3 -1
  268. package/dist/sdk/actions/order-action-provider.d.ts +12 -0
  269. package/dist/sdk/actions/order-action-provider.js +16 -0
  270. package/dist/sdk/actions/order-action-provider.js.map +1 -0
  271. package/dist/sdk/actions/types.d.ts +6 -2
  272. package/dist/sdk/address/address-fields.js +38 -0
  273. package/dist/sdk/address/address-fields.js.map +1 -0
  274. package/dist/sdk/address/checkout-readiness.js +17 -0
  275. package/dist/sdk/address/checkout-readiness.js.map +1 -0
  276. package/dist/sdk/address/constants.js +60 -0
  277. package/dist/sdk/address/constants.js.map +1 -0
  278. package/dist/sdk/address/country-display.js +19 -0
  279. package/dist/sdk/address/country-display.js.map +1 -0
  280. package/dist/sdk/address/country-rules.js +30 -0
  281. package/dist/sdk/address/country-rules.js.map +1 -0
  282. package/dist/sdk/address/format-address.js +18 -0
  283. package/dist/sdk/address/format-address.js.map +1 -0
  284. package/dist/sdk/address/iso-countries.js +262 -0
  285. package/dist/sdk/address/iso-countries.js.map +1 -0
  286. package/dist/sdk/address/layouts.js +56 -0
  287. package/dist/sdk/address/layouts.js.map +1 -0
  288. package/dist/sdk/address/messages.js +97 -0
  289. package/dist/sdk/address/messages.js.map +1 -0
  290. package/dist/sdk/address/operations.d.ts +54 -0
  291. package/dist/sdk/address/operations.js +83 -0
  292. package/dist/sdk/address/operations.js.map +1 -0
  293. package/dist/sdk/address/postal-code-lookup-operations.js +23 -0
  294. package/dist/sdk/address/postal-code-lookup-operations.js.map +1 -0
  295. package/dist/sdk/address/postal-code.js +11 -0
  296. package/dist/sdk/address/postal-code.js.map +1 -0
  297. package/dist/sdk/address/schema.js +14 -0
  298. package/dist/sdk/address/schema.js.map +1 -0
  299. package/dist/sdk/address/server-fields.js +25 -0
  300. package/dist/sdk/address/server-fields.js.map +1 -0
  301. package/dist/sdk/address/switch-country.js +57 -0
  302. package/dist/sdk/address/switch-country.js.map +1 -0
  303. package/dist/sdk/address/types.d.ts +26 -0
  304. package/dist/sdk/address/use-address-actions.d.ts +29 -0
  305. package/dist/sdk/address/use-address-actions.js +247 -0
  306. package/dist/sdk/address/use-address-actions.js.map +1 -0
  307. package/dist/sdk/address/use-address-by-postal-code.js +57 -0
  308. package/dist/sdk/address/use-address-by-postal-code.js.map +1 -0
  309. package/dist/sdk/address/validate-address.js +62 -0
  310. package/dist/sdk/address/validate-address.js.map +1 -0
  311. package/dist/sdk/cache/storefront-cache.js +29 -4
  312. package/dist/sdk/cache/storefront-cache.js.map +1 -1
  313. package/dist/sdk/client/fetch-page-data.d.ts +11 -0
  314. package/dist/sdk/client/fetch-page-data.js +12 -1
  315. package/dist/sdk/client/fetch-page-data.js.map +1 -1
  316. package/dist/sdk/content/create-content-runtime.js +1 -8
  317. package/dist/sdk/content/create-content-runtime.js.map +1 -1
  318. package/dist/sdk/data/failed-fields.js +23 -0
  319. package/dist/sdk/data/failed-fields.js.map +1 -0
  320. package/dist/sdk/data/index.js +2 -2
  321. package/dist/sdk/data/page-reactive-data-root.d.ts +45 -7
  322. package/dist/sdk/data/page-reactive-data-root.js +88 -12
  323. package/dist/sdk/data/page-reactive-data-root.js.map +1 -1
  324. package/dist/sdk/data/reactive-list-item-data-provider.js +2 -2
  325. package/dist/sdk/generated/fragment-types.js +2 -0
  326. package/dist/sdk/generated/fragment-types.js.map +1 -1
  327. package/dist/sdk/generated/gql.js +3 -1
  328. package/dist/sdk/generated/gql.js.map +1 -1
  329. package/dist/sdk/generated/graphql.d.ts +8 -0
  330. package/dist/sdk/generated/graphql.js +212 -1
  331. package/dist/sdk/generated/graphql.js.map +1 -1
  332. package/dist/sdk/i18n/messages/en-US.js +138 -1
  333. package/dist/sdk/i18n/messages/en-US.json +138 -1
  334. package/dist/sdk/i18n/messages/en-US.json.d.ts +137 -0
  335. package/dist/sdk/i18n/messages/es-ES.js +138 -1
  336. package/dist/sdk/i18n/messages/es-ES.json +138 -1
  337. package/dist/sdk/i18n/messages/pt-BR.js +138 -1
  338. package/dist/sdk/i18n/messages/pt-BR.json +138 -1
  339. package/dist/sdk/navigation/current-page.js +30 -0
  340. package/dist/sdk/navigation/current-page.js.map +1 -0
  341. package/dist/sdk/navigation/not-found-log.d.ts +28 -0
  342. package/dist/sdk/navigation/not-found-log.js +133 -0
  343. package/dist/sdk/navigation/not-found-log.js.map +1 -0
  344. package/dist/sdk/navigation/path.js +25 -0
  345. package/dist/sdk/navigation/path.js.map +1 -0
  346. package/dist/sdk/navigation/redirect.d.ts +11 -0
  347. package/dist/sdk/navigation/redirect.js +22 -0
  348. package/dist/sdk/navigation/redirect.js.map +1 -0
  349. package/dist/sdk/navigation/report.js +70 -0
  350. package/dist/sdk/navigation/report.js.map +1 -0
  351. package/dist/sdk/navigation/resolve-storefront-href.d.ts +12 -0
  352. package/dist/sdk/navigation/resolve-storefront-href.js +214 -0
  353. package/dist/sdk/navigation/resolve-storefront-href.js.map +1 -0
  354. package/dist/sdk/navigation/route-identity-provider.d.ts +11 -0
  355. package/dist/sdk/navigation/route-identity-provider.js +20 -0
  356. package/dist/sdk/navigation/route-identity-provider.js.map +1 -0
  357. package/dist/sdk/navigation/route-map-provider.d.ts +19 -0
  358. package/dist/sdk/navigation/route-map-provider.js +29 -0
  359. package/dist/sdk/navigation/route-map-provider.js.map +1 -0
  360. package/dist/sdk/navigation/storefront-link.d.ts +16 -0
  361. package/dist/sdk/navigation/storefront-link.js +66 -0
  362. package/dist/sdk/navigation/storefront-link.js.map +1 -0
  363. package/dist/sdk/navigation/types.d.ts +45 -0
  364. package/dist/sdk/navigation/use-storefront-navigation.d.ts +26 -0
  365. package/dist/sdk/navigation/use-storefront-navigation.js +73 -0
  366. package/dist/sdk/navigation/use-storefront-navigation.js.map +1 -0
  367. package/dist/sdk/navigation/use-storefront-route.d.ts +26 -0
  368. package/dist/sdk/navigation/use-storefront-route.js +87 -0
  369. package/dist/sdk/navigation/use-storefront-route.js.map +1 -0
  370. package/dist/sdk/navigation/use-storefront-search-params.d.ts +11 -0
  371. package/dist/sdk/navigation/use-storefront-search-params.js +16 -0
  372. package/dist/sdk/navigation/use-storefront-search-params.js.map +1 -0
  373. package/dist/sdk/orders/completion-badge.d.ts +8 -0
  374. package/dist/sdk/orders/completion-badge.js +47 -0
  375. package/dist/sdk/orders/completion-badge.js.map +1 -0
  376. package/dist/sdk/orders/order-operations.d.ts +19 -0
  377. package/dist/sdk/orders/order-operations.js +21 -0
  378. package/dist/sdk/orders/order-operations.js.map +1 -0
  379. package/dist/sdk/orders/use-order-actions.d.ts +23 -0
  380. package/dist/sdk/orders/use-order-actions.js +62 -0
  381. package/dist/sdk/orders/use-order-actions.js.map +1 -0
  382. package/dist/sdk/payment/gateway-origin.js +26 -13
  383. package/dist/sdk/payment/gateway-origin.js.map +1 -1
  384. package/dist/sdk/payment/gateway.d.ts +14 -2
  385. package/dist/sdk/payment/gateway.js +32 -14
  386. package/dist/sdk/payment/gateway.js.map +1 -1
  387. package/dist/sdk/payment/operations.js +11 -0
  388. package/dist/sdk/payment/operations.js.map +1 -1
  389. package/dist/sdk/payment/submission-registry.d.ts +2 -1
  390. package/dist/sdk/payment/submission-registry.js +12 -8
  391. package/dist/sdk/payment/submission-registry.js.map +1 -1
  392. package/dist/sdk/payment/use-payment-actions.d.ts +5 -3
  393. package/dist/sdk/payment/use-payment-actions.js +5 -2
  394. package/dist/sdk/payment/use-payment-actions.js.map +1 -1
  395. package/dist/sdk/payment/use-place-order.d.ts +6 -3
  396. package/dist/sdk/payment/use-place-order.js +333 -143
  397. package/dist/sdk/payment/use-place-order.js.map +1 -1
  398. package/dist/sdk/seo/page-alternates.d.ts +55 -0
  399. package/dist/sdk/seo/page-alternates.js +132 -0
  400. package/dist/sdk/seo/page-alternates.js.map +1 -0
  401. package/dist/utils/own-value.js +19 -0
  402. package/dist/utils/own-value.js.map +1 -0
  403. package/dist/utils/safe-href.d.ts +4 -4
  404. package/dist/utils/safe-href.js +31 -22
  405. package/dist/utils/safe-href.js.map +1 -1
  406. package/package.json +5 -1
  407. package/skills/storefront-asset/SKILL.md +111 -0
  408. package/skills/storefront-asset/references/api-side.md +153 -0
  409. package/skills/storefront-asset/references/findings.md +40 -0
  410. package/skills/storefront-asset/references/ui-side.md +94 -0
  411. package/src/styles/tailwind.css +27 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"account-address-form.js","names":[],"sources":["../../../src/matter/account-address-book/account-address-form.tsx"],"sourcesContent":["'use client';\n\nimport { defineComponent } from '@vtex/fs-core';\nimport {\n type ComponentPropsWithRef,\n type ReactNode,\n useCallback,\n useEffect,\n useId,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { useFormContext, useWatch } from 'react-hook-form';\nimport { Button } from '../../particles/button/button.js';\nimport {\n Field,\n FieldsetFieldContext,\n TEXT_FIELD_VALUE,\n useBoundField,\n useFieldsetField,\n useFieldsetFieldNames,\n} from '../../particles/field/field.js';\nimport { FormRoot, type FormUserError, useFormRegistry } from '../../particles/form/form.js';\nimport { Select } from '../../particles/select/select.js';\nimport { useToast } from '../../particles/toast/toast.js';\nimport { useActionsOverride } from '../../sdk/actions/actions-override-context.js';\nimport type { ComponentActions } from '../../sdk/actions/types.js';\nimport { addressFields } from '../../sdk/address/address-fields.js';\nimport { ACCOUNT_FIELD_LABELS, ACCOUNT_MAX_LENGTH } from '../../sdk/address/constants.js';\nimport { loadCountryRules } from '../../sdk/address/country-rules.js';\nimport type {\n AddressCreatePayload,\n AddressUpdatePayload,\n CustomerAddressUserError,\n} from '../../sdk/address/operations.js';\nimport { toAddressFieldName } from '../../sdk/address/server-fields.js';\nimport type {\n AddressFieldDescriptor,\n AddressFieldError,\n AddressFieldName,\n CountryRules,\n} from '../../sdk/address/types.js';\nimport { validateAddress } from '../../sdk/address/validate-address.js';\nimport { type MessageId, useIntl } from '../../sdk/i18n/client.js';\nimport type { PageRef } from '../../sdk/navigation/types.js';\nimport { useStorefrontNavigation } from '../../sdk/navigation/use-storefront-navigation.js';\nimport { loggableErrorName } from '../../utils/loggable-error-name.js';\nimport { resolveAuthoredCopy } from '../../utils/resolve-authored-copy.js';\nimport { resolveSiteRelativeHref } from '../../utils/safe-href.js';\nimport { useSession } from '../session/session.js';\nimport { type AccountAddressBookItemSlice, useOptionalAccountAddressBook } from './account-address-book.js';\nimport { AccountAddressCountryNotice, AddressCountryControl } from './account-address-country.js';\nimport {\n type AddressCountryMemory,\n applyCountrySwitch,\n initialAddressCountry,\n} from './account-address-country-switch.js';\nimport {\n type AccountAddressCountryChange,\n AccountAddressFormContext,\n type AccountAddressFormContextValue,\n type AccountAddressFormCountryChoice,\n type AccountAddressFormDraft,\n type AccountAddressFormErrorKind,\n type AccountAddressFormFieldErrors,\n type EditableField,\n useAccountAddressForm,\n} from './account-address-form-context.js';\nimport { dependentsOf, type FilledFields, usePostalCodeAutofill } from './account-address-postal-autofill.js';\nimport { useOptionalAccountAddressRecord } from './account-address-record.js';\n\n/**\n * The form that adds an address and corrects a saved one (specs/sfs-3441-address-book-form.md, RFC\n * REQ-02 and REQ-03). The Root renders `FormRoot` and registers one fieldset with it, under the\n * `accountAddress` namespace: react-hook-form holds the draft and knows what is dirty, and the\n * fieldset owns the field errors, the form-level error, the status message and the save. It holds no\n * country rule: the fields come from `addressFields`, the verdict from `validateAddress`, and the\n * writes go through `$actions.address`.\n */\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport type AccountAddressFormRootProps = ComponentPropsWithRef<'form'> & {\n /**\n * ISO 3166-1 alpha-3 country a new address prefers: taken when the store ships there or its list\n * is unknown. A blank value falls back to `BRA`.\n */\n defaultCountry?: string;\n /** Toast after an address is added. A blank value falls back to the catalog copy. */\n addedMessage?: string;\n /** Toast after an address is saved. A blank value falls back to the catalog copy. */\n savedMessage?: string;\n /** Announced when a save is blocked. A blank value falls back to the catalog copy. */\n blockedMessage?: string;\n /** Where leaving the form goes when it stands on its own page. A page reference, or a site-relative string. A blank value falls back to the address page. */\n returnHref?: PageRef | string;\n /** Injected by the compiler from `actions: { address: [...] }`; the address write surface. */\n $actions?: ComponentActions;\n};\n\n/** `className` goes on every field's wrapper. */\nexport type AccountAddressFormFieldsProps = Readonly<{ className?: string }>;\n\nexport type AccountAddressFormLabelProps = Readonly<{\n /** The field's label. A blank value falls back to the catalog copy. */\n label?: string;\n className?: string;\n}>;\n\nexport type AccountAddressFormErrorProps = ComponentPropsWithRef<'div'> & {\n /** Each message below falls back to the catalog copy when blank. */\n unrenderedFieldMessage?: string;\n notFoundMessage?: string;\n unauthorizedMessage?: string;\n saveFailedMessage?: string;\n rulesFailedMessage?: string;\n countrySwitchFailedMessage?: string;\n unsupportedCountryMessage?: string;\n};\n\nexport type AccountAddressFormButtonProps = Omit<ComponentPropsWithRef<'button'>, 'type'> & {\n /** The button's text. A blank value falls back to the catalog copy. */\n label?: string;\n};\n\n// ---------------------------------------------------------------------------\n// Constants and helpers\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_COUNTRY = 'BRA';\n\nconst DEFAULT_RETURN_PAGE: PageRef = { standard: 'address' };\n\n/** The react-hook-form namespace every field of the form registers under. */\nconst ADDRESS_NAMESPACE = 'accountAddress';\n\n/** What `dispatch` hands `FormRoot` when it writes nothing because a write or a switch is in flight. */\nconst BUSY: readonly FormUserError[] = [{ code: 'ADDRESS_FORM_BUSY', message: '' }];\n\nconst EDITABLE_FIELDS: readonly EditableField[] = [\n 'recipientName',\n 'street',\n 'number',\n 'complement',\n 'neighborhood',\n 'city',\n 'state',\n 'postalCode',\n 'reference',\n];\n\nconst SERVER_REQUIRED: AddressFieldError = { code: 'required', messageId: 'fs/address.error.required' };\nconst SERVER_INVALID: AddressFieldError = { code: 'invalid', messageId: 'fs/address.error.invalid' };\n\nconst ERROR_MESSAGE_IDS: Readonly<Record<AccountAddressFormErrorKind, MessageId>> = {\n unrenderedField: 'fs/address-form.error.unrendered-field',\n notFound: 'fs/address-form.error.not-found',\n unauthorized: 'fs/address-form.error.unauthorized',\n saveFailed: 'fs/address-form.error.save-failed',\n rulesFailed: 'fs/address-form.error.rules-failed',\n countrySwitchFailed: 'fs/address-form.error.country-switch-failed',\n unsupportedCountry: 'fs/address-form.error.unsupported-country',\n};\n\ntype Status =\n | Readonly<{ kind: 'fields'; count: number }>\n | Readonly<{ kind: 'failed' }>\n | Readonly<{ kind: 'filled'; count: number }>;\n\nfunction toDraft(address: AccountAddressBookItemSlice | null): AccountAddressFormDraft {\n if (!address) return {};\n return Object.fromEntries(EDITABLE_FIELDS.map((field) => [field, address[field] ?? '']));\n}\n\nfunction isBlankDraft(draft: AccountAddressFormDraft): boolean {\n return EDITABLE_FIELDS.every((field) => (draft[field] ?? '').trim() === '');\n}\n\nfunction toCountry(code: string | null | undefined): string {\n return resolveAuthoredCopy(code, DEFAULT_COUNTRY).trim().toUpperCase();\n}\n\n/** A refusal's code decides the message when it names no field on screen; a named field reads as unrendered. */\nfunction toFormError({ code, field }: CustomerAddressUserError): AccountAddressFormErrorKind {\n if (code === 'UNSUPPORTED_COUNTRY') return 'unsupportedCountry';\n if (code === 'NOT_FOUND') return 'notFound';\n if (code === 'UNAUTHORIZED') return 'unauthorized';\n return field === null ? 'saveFailed' : 'unrenderedField';\n}\n\nfunction fieldPath(name: AddressFieldName): string {\n return `${ADDRESS_NAMESPACE}.${name}`;\n}\n\n/** The editable fields react-hook-form holds a value for, out of the namespace's raw values. */\nfunction pickEditable(values: unknown): AccountAddressFormDraft {\n if (typeof values !== 'object' || values === null) return {};\n const raw = values as Record<string, unknown>;\n return Object.fromEntries(\n EDITABLE_FIELDS.flatMap((field) => (typeof raw[field] === 'string' ? [[field, raw[field]]] : [])),\n );\n}\n\nfunction pick(draft: AccountAddressFormDraft, fields: readonly EditableField[]): Record<string, string> {\n return Object.fromEntries(fields.map((field) => [field, draft[field] ?? '']));\n}\n\nfunction changedFields(draft: AccountAddressFormDraft, seedDraft: AccountAddressFormDraft): EditableField[] {\n return EDITABLE_FIELDS.filter((field) => (draft[field] ?? '') !== (seedDraft[field] ?? ''));\n}\n\nfunction typedFields(draft: AccountAddressFormDraft): EditableField[] {\n return EDITABLE_FIELDS.filter((field) => (draft[field] ?? '').trim() !== '');\n}\n\ntype AddressWrite = (payload: Record<string, unknown>) => Promise<readonly CustomerAddressUserError[]>;\n\n/** The write a save sends, or `undefined` when the provider chain never delivered its action. */\nfunction resolveWrite(actions: ComponentActions | undefined, edit: boolean): AddressWrite | undefined {\n if (edit) {\n const update = actions?.address?.update;\n return update ? (payload) => update(payload as AddressUpdatePayload) : undefined;\n }\n const create = actions?.address?.create;\n return create ? (payload) => create(payload as AddressCreatePayload) : undefined;\n}\n\n/** Splits the draft's errors into those a control on screen can show, and a form-level error for any with none. */\nfunction splitByScreen(\n found: AccountAddressFormFieldErrors,\n controls: ReadonlySet<AddressFieldName>,\n): Readonly<{ onScreen: AccountAddressFormFieldErrors; formLevel: AccountAddressFormErrorKind | null }> {\n const onScreen: Partial<Record<AddressFieldName, AddressFieldError>> = {};\n let offScreen = false;\n for (const [name, error] of Object.entries(found) as [AddressFieldName, AddressFieldError][]) {\n if (controls.has(name)) onScreen[name] = error;\n else offScreen = true;\n }\n return { onScreen, formLevel: offScreen ? 'unrenderedField' : null };\n}\n\ntype SuccessTitleInput = Readonly<{\n edited: boolean;\n addedMessage: string | undefined;\n savedMessage: string | undefined;\n intl: ReturnType<typeof useIntl>;\n}>;\n\nfunction successTitle({ edited, addedMessage, savedMessage, intl }: SuccessTitleInput): string {\n if (edited) return resolveAuthoredCopy(savedMessage, intl.formatMessage({ id: 'fs/address-form.saved' }));\n return resolveAuthoredCopy(addedMessage, intl.formatMessage({ id: 'fs/address-form.added' }));\n}\n\nfunction describeStatus(\n status: Status | null,\n blockedMessage: string | undefined,\n intl: ReturnType<typeof useIntl>,\n): string {\n if (status === null) return '';\n if (status.kind === 'filled')\n return intl.formatMessage({ id: 'fs/address-form.status.filled' }, { count: status.count });\n const fallback =\n status.kind === 'fields'\n ? intl.formatMessage({ id: 'fs/address-form.status.fields' }, { count: status.count })\n : intl.formatMessage({ id: 'fs/address-form.status.failed' });\n return resolveAuthoredCopy(blockedMessage, fallback);\n}\n\nfunction focusFirstInvalid(form: HTMLFormElement | null, errors: AccountAddressFormFieldErrors) {\n if (!form) return;\n for (const wrapper of form.querySelectorAll<HTMLElement>('[data-fs-account-address-form-field]')) {\n const name = wrapper.dataset.fsAccountAddressFormField as AddressFieldName | undefined;\n if (name && errors[name]) {\n wrapper.querySelector<HTMLElement>('[data-fs-account-address-form-control]')?.focus();\n return;\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Root\n// ---------------------------------------------------------------------------\n\n/** Where the form stands decides its seed: the book's open edit form, then the record the page names, then nothing. */\nfunction useFormPlacement() {\n const book = useOptionalAccountAddressBook();\n const record = useOptionalAccountAddressRecord();\n const openForm = book?.openForm ?? null;\n const seed = (openForm?.mode === 'edit' ? openForm.address : null) ?? record?.address ?? null;\n return { book, record, seed, mode: seed ? ('edit' as const) : ('add' as const) };\n}\n\nexport function AccountAddressFormRoot({\n defaultCountry,\n addedMessage,\n savedMessage,\n blockedMessage,\n returnHref,\n $actions,\n className,\n children,\n ...props\n}: AccountAddressFormRootProps) {\n // Enforces the SessionRoot and ToastProvider ancestors: both hooks throw outside one.\n const { state: sessionState } = useSession();\n useToast();\n const { book, record, mode } = useFormPlacement();\n // Held here because `aria-busy` goes on FormRoot's <form>, which only this component renders.\n const [writing, setWriting] = useState(false);\n const setBookFormPending = book?.setFormPending;\n useEffect(() => {\n setBookFormPending?.(writing);\n return () => setBookFormPending?.(false);\n }, [writing, setBookFormPending]);\n const [switchTarget, setSwitchTarget] = useState<string | null>(null);\n\n if (sessionState !== 'loggedIn') return null;\n // A record that has not delivered its address must not read as \"add\": nothing renders until it does.\n if (!book && record && !record.address) return null;\n\n return (\n <FormRoot\n {...props}\n className={className}\n aria-busy={writing || switchTarget !== null || undefined}\n data-fs-account-address-form=\"\"\n data-fs-account-address-form-mode={mode}\n >\n <AccountAddressFieldset\n defaultCountry={defaultCountry}\n addedMessage={addedMessage}\n savedMessage={savedMessage}\n blockedMessage={blockedMessage}\n returnHref={returnHref}\n $actions={$actions}\n writing={writing}\n setWriting={setWriting}\n switchTarget={switchTarget}\n setSwitchTarget={setSwitchTarget}\n >\n {children ?? (\n <>\n <AddressCountryControl />\n <AccountAddressCountryNotice />\n <AccountAddressFormRecipientName />\n <AccountAddressFormFields />\n <AccountAddressFormReference />\n <AccountAddressFormError />\n <AccountAddressFormSubmit />\n <AccountAddressFormCancel />\n </>\n )}\n </AccountAddressFieldset>\n </FormRoot>\n );\n}\n\ntype AccountAddressFieldsetProps = Readonly<{\n defaultCountry?: string;\n addedMessage?: string;\n savedMessage?: string;\n blockedMessage?: string;\n returnHref?: PageRef | string;\n $actions?: ComponentActions;\n writing: boolean;\n setWriting: (writing: boolean) => void;\n switchTarget: string | null;\n setSwitchTarget: (target: string | null) => void;\n children: ReactNode;\n}>;\n\n/**\n * The form's one fieldset under its FormRoot. It reads and writes the draft through react-hook-form,\n * and owns the rules, the errors, the country switch, the postal-code fill and the write.\n */\nfunction AccountAddressFieldset({\n defaultCountry,\n addedMessage,\n savedMessage,\n blockedMessage,\n returnHref,\n $actions: $actionsProp,\n writing,\n setWriting,\n switchTarget,\n setSwitchTarget,\n children,\n}: AccountAddressFieldsetProps) {\n const { registerFieldset } = useFormRegistry();\n const { getValues, setValue, subscribe } = useFormContext();\n const toast = useToast();\n const intl = useIntl();\n const $actions = useActionsOverride($actionsProp);\n const { push } = useStorefrontNavigation();\n const { book, seed, mode } = useFormPlacement();\n const preferredCountry = toCountry(seed?.country ?? defaultCountry);\n const seedDraft = useMemo(() => toDraft(seed), [seed]);\n const close = book?.close;\n\n const [offered, setOffered] = useState<readonly string[] | null | undefined>(undefined);\n const [chosenCountry, setChosenCountry] = useState<string | null>(null);\n const [lastChange, setLastChange] = useState<AccountAddressCountryChange | null>(null);\n const [rules, setRules] = useState<CountryRules | null>(null);\n const [fieldErrors, setFieldErrors] = useState<AccountAddressFormFieldErrors>({});\n const [formError, setFormError] = useState<AccountAddressFormErrorKind | null>(null);\n const [status, setStatus] = useState<Status | null>(null);\n const pendingRef = useRef(false);\n // A save outlives the form that sent it when the shopper opens another address meanwhile. Only a\n // form that is still mounted may close the book's open form once the save settles.\n const mountedRef = useRef(true);\n useEffect(() => {\n mountedRef.current = true;\n return () => {\n mountedRef.current = false;\n };\n }, []);\n const dispatched = useRef(false);\n const statusRef = useRef<HTMLOutputElement>(null);\n const offers = useRef(0);\n const switchedRef = useRef(false);\n const switchToken = useRef(0);\n const asideRef = useRef<AddressCountryMemory>({});\n\n const { registry, getFieldNames } = useFieldsetFieldNames(ADDRESS_NAMESPACE);\n const watched = useWatch({ name: ADDRESS_NAMESPACE });\n // A field with no control never reaches react-hook-form, so the seed fills what it does not hold.\n const draft = useMemo<AccountAddressFormDraft>(\n () => ({ ...seedDraft, ...pickEditable(watched) }),\n [seedDraft, watched],\n );\n\n // A new address has no country until the control's list resolves it, so only its chunk loads.\n const country = mode === 'edit' ? preferredCountry : (chosenCountry ?? '');\n const latest = useRef({ mode, country, rules, seedDraft });\n useLayoutEffect(() => {\n latest.current = { mode, country, rules, seedDraft };\n });\n\n /** The draft as react-hook-form holds it now, not as the last render saw it. */\n const readDraft = useCallback(\n (): AccountAddressFormDraft => ({ ...latest.current.seedDraft, ...pickEditable(getValues(ADDRESS_NAMESPACE)) }),\n [getValues],\n );\n\n /** Writes each field whose value changes. The country switch and the postal-code fill both write through here. */\n const writeDraft = useCallback(\n (values: AccountAddressFormDraft) => {\n const current = readDraft();\n for (const [name, value] of Object.entries(values) as [EditableField, string][]) {\n if ((current[name] ?? '') !== value) setValue(fieldPath(name), value, { shouldDirty: true });\n }\n },\n [readDraft, setValue],\n );\n\n const mountedFields = useCallback(\n () => new Set(getFieldNames().map((name) => name.slice(ADDRESS_NAMESPACE.length + 1) as AddressFieldName)),\n [getFieldNames],\n );\n\n /**\n * Loads `next`'s rules and applies the switch to the draft as it is then; only the latest call applies.\n * A `silent` switch is one the shopper did not ask for, so its failure shows no error.\n */\n const startSwitch = useCallback(\n (next: string, silent = false) => {\n const to = toCountry(next);\n if (latest.current.mode !== 'add') return;\n const token = ++switchToken.current;\n if (to === latest.current.country) {\n setSwitchTarget(null);\n return;\n }\n setSwitchTarget(to);\n loadCountryRules(to).then(\n (toRules) => {\n if (token !== switchToken.current) return;\n const { rules: fromRules } = latest.current;\n if (fromRules) {\n const result = applyCountrySwitch({\n draft: readDraft(),\n aside: asideRef.current,\n from: fromRules,\n to: toRules,\n });\n asideRef.current = result.aside;\n // Every editable field, so react-hook-form keeps no value the new country did not take.\n writeDraft(Object.fromEntries(EDITABLE_FIELDS.map((field) => [field, result.draft[field] ?? ''])));\n setLastChange(result.change);\n }\n setRules(toRules);\n setChosenCountry(to);\n setSwitchTarget(null);\n setFieldErrors({});\n setFormError(null);\n setStatus(null);\n },\n () => {\n if (token !== switchToken.current) return;\n setSwitchTarget(null);\n if (!silent) setFormError('countrySwitchFailed');\n },\n );\n },\n [readDraft, writeDraft, setSwitchTarget],\n );\n\n useEffect(\n () => () => {\n switchToken.current += 1;\n },\n [],\n );\n\n const change = useCallback(\n (to: string) => {\n if (pendingRef.current) return;\n switchedRef.current = true;\n startSwitch(to);\n },\n [startSwitch],\n );\n\n const offer = useCallback((countries: readonly string[] | null) => {\n offers.current += 1;\n setOffered(countries);\n return () => {\n offers.current -= 1;\n if (offers.current === 0) setOffered(undefined);\n };\n }, []);\n\n // The control's effect runs before this one, so a list it reports is in by the next render. With no\n // control, the preferred country applies. A later list moves the country only while the shopper has\n // neither switched nor typed, and silently.\n useEffect(() => {\n if (mode !== 'add') return;\n if (offered === undefined) {\n if (offers.current === 0) setChosenCountry((current) => current ?? preferredCountry);\n return;\n }\n const initial = initialAddressCountry(offered, preferredCountry);\n if (chosenCountry === null) setChosenCountry(initial);\n else if (!switchedRef.current && initial !== chosenCountry && isBlankDraft(readDraft())) {\n startSwitch(initial, true);\n }\n }, [mode, offered, preferredCountry, chosenCountry, startSwitch, readDraft]);\n\n // The rules load once the country is known. A failed load is not remembered by `loadCountryRules`,\n // so opening the form again retries it. An edit shows the saved address's gaps as soon as it can.\n useEffect(() => {\n if (!country) return;\n let current = true;\n loadCountryRules(country).then(\n (loaded) => {\n if (!current) return;\n setRules(loaded);\n if (seed) setFieldErrors(validateAddress(seedDraft, loaded));\n },\n () => {\n if (current) setFormError('rulesFailed');\n },\n );\n return () => {\n current = false;\n };\n }, [country, seed, seedDraft]);\n\n const registerField = useCallback(\n (name: AddressFieldName) => registry.registerFieldName(fieldPath(name)),\n [registry],\n );\n\n const applyFill = useCallback(\n (filled: FilledFields) => {\n writeDraft(filled);\n setFieldErrors((previous) => {\n const next = Object.fromEntries(Object.entries(previous).filter(([name]) => !(name in filled)));\n return Object.keys(next).length === Object.keys(previous).length ? previous : next;\n });\n const count = Object.values(filled).filter((value) => value !== '').length;\n if (count > 0) setStatus({ kind: 'filled', count });\n },\n [writeDraft],\n );\n\n const autofill = usePostalCodeAutofill({ country, rules, draft, onFill: applyFill });\n const { fieldChanged, postalCodeChanged } = autofill;\n\n const setField = useCallback(\n (name: EditableField, value: string) => {\n fieldChanged(name);\n if (name === 'postalCode') postalCodeChanged(value);\n setValue(fieldPath(name), value, { shouldDirty: true });\n setFieldErrors((previous) => {\n if (!previous[name]) return previous;\n const { [name]: _cleared, ...rest } = previous;\n return rest;\n });\n setFormError((previous) => (previous === 'rulesFailed' ? previous : null));\n setStatus(null);\n },\n [fieldChanged, postalCodeChanged, setValue],\n );\n\n const destination = typeof returnHref === 'string' && returnHref.trim().length === 0 ? undefined : returnHref;\n\n // Under a book, leaving closes the form in place. On its own page there is nothing to close, so it\n // goes back to the list. A refused destination stays put: the save already happened.\n const closeForm = useCallback(() => {\n if (book) {\n close?.();\n return;\n }\n if (destination === undefined) {\n push(DEFAULT_RETURN_PAGE);\n } else if (typeof destination === 'string') {\n const target = resolveSiteRelativeHref(destination);\n if (target.safe) {\n push(target.href);\n } else {\n console.warn(`[AccountAddressFormRoot] returnHref refused (${target.reason}): ${destination}`);\n }\n } else {\n push(destination);\n }\n }, [book, close, destination, push]);\n\n function block(errors: AccountAddressFormFieldErrors, formLevel: AccountAddressFormErrorKind | null): Status {\n const count = Object.keys(errors).length;\n const blocked: Status = count > 0 ? { kind: 'fields', count } : { kind: 'failed' };\n setFieldErrors(errors);\n setFormError(formLevel);\n setStatus(blocked);\n focusFirstInvalid(statusRef.current?.closest('form') ?? null, errors);\n return blocked;\n }\n\n /** Blocks on the draft's errors and returns what `dispatch` hands `FormRoot`, or `null` when the draft passes. */\n function blockInvalid(current: AccountAddressFormDraft, currentRules: CountryRules): FormUserError[] | null {\n const { onScreen, formLevel } = splitByScreen(validateAddress(current, currentRules), mountedFields());\n if (formLevel === null && Object.keys(onScreen).length === 0) return null;\n const blocked = block(onScreen, formLevel);\n return [{ code: 'ADDRESS_FORM_BLOCKED', message: describeStatus(blocked, blockedMessage, intl) }];\n }\n\n /** Puts each refusal on the field it names, and the rest on the form: a save never fails silently. */\n function refuse(userErrors: readonly CustomerAddressUserError[]) {\n const errors: Partial<Record<AddressFieldName, AddressFieldError>> = {};\n const controls = mountedFields();\n let formLevel: AccountAddressFormErrorKind | null = null;\n\n for (const userError of userErrors) {\n const name = toAddressFieldName(userError.field);\n const onField = userError.code !== 'NOT_FOUND' && userError.code !== 'UNSUPPORTED_COUNTRY';\n if (name && controls.has(name) && onField) {\n errors[name] ??= userError.code === 'MISSING_REQUIRED_FIELD' ? SERVER_REQUIRED : SERVER_INVALID;\n } else {\n formLevel ??= toFormError(userError);\n }\n }\n block(errors, formLevel);\n }\n\n function toPayload(values: Record<string, unknown>): Record<string, unknown> {\n const current = { ...seedDraft, ...pickEditable(values) };\n if (seed) return { id: seed.id, ...pick(current, changedFields(current, seedDraft)) };\n return { country, ...pick(current, typedFields(current)) };\n }\n\n /** The form's only path to a write: FormRoot calls it when a mounted field is dirty, `settleUnsent` otherwise. */\n async function dispatch(payload: Record<string, unknown>): Promise<readonly FormUserError[]> {\n if (!rules || pendingRef.current || switchTarget !== null) return BUSY;\n\n const current = readDraft();\n const blocked = blockInvalid(current, rules);\n if (blocked) return blocked;\n if (seed && changedFields(current, seedDraft).length === 0) {\n setFieldErrors({});\n closeForm();\n return [];\n }\n\n setFieldErrors({});\n setFormError(null);\n setStatus(null);\n\n const write = resolveWrite($actions, seed !== null);\n if (!write) {\n // A composition gap (the provider chain never delivered the action) is otherwise a dead button.\n block({}, 'saveFailed');\n throw new Error('AccountAddressFormRoot requires $actions.address.');\n }\n\n pendingRef.current = true;\n setWriting(true);\n try {\n const userErrors = await write(payload);\n if (userErrors.length > 0) {\n refuse(userErrors);\n return userErrors;\n }\n toast.add({ title: successTitle({ edited: seed !== null, addedMessage, savedMessage, intl }), type: 'success' });\n if (mountedRef.current) closeForm();\n return [];\n } catch (error) {\n // Log only the error name: a message can echo a typed address.\n console.error('[AccountAddressFormRoot] address write failed', loggableErrorName(error));\n block({}, 'saveFailed');\n throw error;\n } finally {\n pendingRef.current = false;\n setWriting(false);\n }\n }\n\n /**\n * A submit FormRoot settled without calling `dispatch`, because no mounted field is dirty. The draft\n * can still differ from what was saved: a value written before its control mounted is that control's\n * dirty baseline. So the save takes the same path, which writes only what changed.\n */\n function settleUnsent() {\n // `dispatch` has already put a failed write on the form.\n dispatch(toPayload(getValues(ADDRESS_NAMESPACE) ?? {})).catch(() => undefined);\n }\n\n const handlers = useRef({ toPayload, dispatch, settleUnsent });\n useLayoutEffect(() => {\n handlers.current = { toPayload, dispatch, settleUnsent };\n });\n\n useEffect(\n () =>\n registerFieldset({\n namespace: ADDRESS_NAMESPACE,\n getFieldNames,\n toPayload: (values) => handlers.current.toPayload(values),\n dispatch: (payload) => {\n dispatched.current = true;\n return handlers.current.dispatch(payload);\n },\n label: 'account-address',\n }),\n [registerFieldset, getFieldNames],\n );\n\n // FormRoot skips a fieldset with nothing dirty and says nothing; the end of the submit is the only sign.\n useEffect(() => {\n let seen = 0;\n return subscribe({\n formState: { submitCount: true },\n callback: ({ submitCount = 0 }) => {\n if (submitCount === seen) return;\n seen = submitCount;\n if (dispatched.current) dispatched.current = false;\n else handlers.current.settleUnsent();\n },\n });\n }, [subscribe]);\n\n const selected = switchTarget ?? country;\n const countryChoice = useMemo<AccountAddressFormCountryChoice>(\n () => ({ offer, selected, change, lastChange }),\n [offer, selected, change, lastChange],\n );\n\n const value = useMemo<AccountAddressFormContextValue>(\n () => ({\n mode,\n country,\n rules,\n draft,\n fieldErrors,\n formError,\n pending: writing,\n setField,\n registerField,\n close: closeForm,\n countryChoice,\n }),\n [mode, country, rules, draft, fieldErrors, formError, writing, setField, registerField, closeForm, countryChoice],\n );\n\n return (\n <FieldsetFieldContext value={registry}>\n <AccountAddressFormContext value={value}>\n {children}\n <output\n ref={statusRef}\n aria-live=\"polite\"\n data-fs-account-address-form-status=\"\"\n data-fs-sr-only=\"\"\n className=\"sr-only\"\n >\n {describeStatus(status, blockedMessage, intl)}\n </output>\n </AccountAddressFormContext>\n </FieldsetFieldContext>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Fields\n// ---------------------------------------------------------------------------\n\nfunction fieldErrorText(error: AddressFieldError, intl: ReturnType<typeof useIntl>): string {\n return intl.formatMessage({ id: error.messageId }, error.values);\n}\n\n/** Registers the field with the form while it is on screen and returns its value. */\nfunction useAddressFieldValue(name: EditableField): string {\n const { draft } = useAccountAddressForm();\n const { getValues } = useFormContext();\n const path = useFieldsetField(ADDRESS_NAMESPACE, name);\n // Adopting a seed resets the field to it, so the seed is what the field holds when it mounts: a\n // control that first mounts after a country switch keeps the value the switch carried.\n const [seed] = useState(() => {\n const live: unknown = getValues(path);\n return typeof live === 'string' ? live : (draft[name] ?? '');\n });\n return useBoundField({ name: path, defaultValue: seed }, TEXT_FIELD_VALUE).value;\n}\n\n/** Sets a list's option and empties the fields that read their options from it. The form's only dependent reset. */\nfunction chooseOption(\n setField: AccountAddressFormContextValue['setField'],\n name: EditableField,\n value: string,\n descriptors: readonly AddressFieldDescriptor[],\n) {\n setField(name, value);\n for (const dependent of dependentsOf(name, descriptors)) setField(dependent, '');\n}\n\ntype TextFieldProps = Readonly<{\n name: EditableField;\n label: string;\n maxLength: number;\n inputMode?: AddressFieldDescriptor['inputMode'];\n placeholder?: string;\n className?: string;\n}>;\n\nfunction AddressTextField({ name, label, maxLength, inputMode, placeholder, className }: TextFieldProps) {\n const { fieldErrors, setField } = useAccountAddressForm();\n const value = useAddressFieldValue(name);\n const intl = useIntl();\n const error = fieldErrors[name];\n\n return (\n <Field.Root className={className} invalid={!!error} data-fs-account-address-form-field={name}>\n <Field.Label>{label}</Field.Label>\n <Field.Control\n value={value}\n onChange={(event) => setField(name, event.target.value)}\n maxLength={maxLength}\n inputMode={inputMode}\n placeholder={placeholder}\n data-fs-account-address-form-control=\"\"\n />\n {error ? <Field.Error match>{fieldErrorText(error, intl)}</Field.Error> : null}\n </Field.Root>\n );\n}\n\ntype SelectFieldProps = Readonly<{\n name: EditableField;\n label: string;\n options: readonly Readonly<{ value: string; label: string }>[];\n placeholder?: string;\n className?: string;\n /** Called after the value changes, with the new value, so fields that depend on it can reset. */\n onChange: (value: string) => void;\n}>;\n\nfunction AddressSelectField({ name, label, options, placeholder, className, onChange }: SelectFieldProps) {\n const { fieldErrors } = useAccountAddressForm();\n const value = useAddressFieldValue(name);\n const intl = useIntl();\n const errorId = useId();\n const error = fieldErrors[name];\n\n return (\n <div className={className} data-fs-account-address-form-field={name} {...(error ? { 'data-invalid': '' } : {})}>\n <Select.Root value={value} onValueChange={(next) => onChange(next ?? '')}>\n <Select.Label>{label}</Select.Label>\n <Select.Trigger\n aria-invalid={error ? true : undefined}\n aria-describedby={error ? errorId : undefined}\n data-fs-account-address-form-control=\"\"\n >\n <Select.Value placeholder={placeholder}>\n {(value) => options.find((option) => option.value === value)?.label ?? placeholder}\n </Select.Value>\n <Select.Icon />\n </Select.Trigger>\n <Select.Portal>\n <Select.Positioner>\n <Select.Popup>\n <Select.List>\n {options.map((option) => (\n <Select.Item key={option.value} value={option.value} label={option.label}>\n <Select.ItemText>{option.label}</Select.ItemText>\n </Select.Item>\n ))}\n </Select.List>\n </Select.Popup>\n </Select.Positioner>\n </Select.Portal>\n </Select.Root>\n {error ? (\n <p id={errorId} data-fs-account-address-form-field-error=\"\">\n {fieldErrorText(error, intl)}\n </p>\n ) : null}\n </div>\n );\n}\n\nexport function AccountAddressFormRecipientName({ label, className }: AccountAddressFormLabelProps) {\n const { rules } = useAccountAddressForm();\n const intl = useIntl();\n\n if (!rules) return null;\n\n return (\n <AddressTextField\n name=\"recipientName\"\n label={resolveAuthoredCopy(label, intl.formatMessage({ id: ACCOUNT_FIELD_LABELS.recipientName }))}\n maxLength={ACCOUNT_MAX_LENGTH.recipientName}\n className={className}\n />\n );\n}\n\nexport function AccountAddressFormReference({ label, className }: AccountAddressFormLabelProps) {\n const { rules } = useAccountAddressForm();\n const intl = useIntl();\n\n if (!rules) return null;\n\n return (\n <AddressTextField\n name=\"reference\"\n label={resolveAuthoredCopy(label, intl.formatMessage({ id: ACCOUNT_FIELD_LABELS.reference }))}\n maxLength={ACCOUNT_MAX_LENGTH.reference}\n className={className}\n />\n );\n}\n\n/**\n * One field per descriptor the country's rules give for the draft, in the order the country's form lists them.\n * A complete postal code fills the empty state, city, neighborhood and street the shopper has not typed;\n * the fill is announced once.\n */\nexport function AccountAddressFormFields({ className }: AccountAddressFormFieldsProps) {\n const { rules, draft, setField } = useAccountAddressForm();\n const intl = useIntl();\n\n if (!rules) return null;\n\n const descriptors = addressFields(rules, draft);\n\n return descriptors.map((descriptor) => {\n const { name, control, labelId, maxLength, inputMode, options, placeholder } = descriptor;\n const label = intl.formatMessage({ id: labelId });\n const hint = placeholder ? intl.formatMessage({ id: placeholder.id }, placeholder.values) : undefined;\n\n if (control === 'select') {\n return (\n <AddressSelectField\n key={name}\n name={name}\n label={label}\n options={options ?? []}\n placeholder={hint}\n className={className}\n onChange={(value) => chooseOption(setField, name, value, descriptors)}\n />\n );\n }\n\n return (\n <AddressTextField\n key={name}\n name={name}\n label={label}\n maxLength={maxLength}\n inputMode={inputMode}\n placeholder={hint}\n className={className}\n />\n );\n });\n}\n\n// ---------------------------------------------------------------------------\n// Error, submit, cancel\n// ---------------------------------------------------------------------------\n\nexport function AccountAddressFormError({\n unrenderedFieldMessage,\n notFoundMessage,\n unauthorizedMessage,\n saveFailedMessage,\n rulesFailedMessage,\n countrySwitchFailedMessage,\n unsupportedCountryMessage,\n className,\n ...props\n}: AccountAddressFormErrorProps) {\n const { formError } = useAccountAddressForm();\n const intl = useIntl();\n\n if (!formError) return null;\n\n const authored: Readonly<Record<AccountAddressFormErrorKind, string | undefined>> = {\n unrenderedField: unrenderedFieldMessage,\n notFound: notFoundMessage,\n unauthorized: unauthorizedMessage,\n saveFailed: saveFailedMessage,\n rulesFailed: rulesFailedMessage,\n countrySwitchFailed: countrySwitchFailedMessage,\n unsupportedCountry: unsupportedCountryMessage,\n };\n\n return (\n <div {...props} role=\"alert\" className={className} data-fs-account-address-form-error={formError}>\n {resolveAuthoredCopy(authored[formError], intl.formatMessage({ id: ERROR_MESSAGE_IDS[formError] }))}\n </div>\n );\n}\n\nexport function AccountAddressFormSubmit({ label, className, children, ...props }: AccountAddressFormButtonProps) {\n const { country, rules, formError, pending, countryChoice } = useAccountAddressForm();\n const intl = useIntl();\n const switching = countryChoice.selected !== country;\n\n return (\n <Button\n {...props}\n type=\"submit\"\n className={className}\n disabled={rules === null || formError === 'rulesFailed' || pending || switching}\n aria-busy={pending || undefined}\n data-fs-account-address-form-submit=\"\"\n >\n {children ?? resolveAuthoredCopy(label, intl.formatMessage({ id: 'fs/address-form.submit' }))}\n </Button>\n );\n}\n\nexport function AccountAddressFormCancel({\n label,\n className,\n children,\n onClick,\n ...props\n}: AccountAddressFormButtonProps) {\n const { close, pending } = useAccountAddressForm();\n const intl = useIntl();\n\n return (\n <Button\n {...props}\n type=\"button\"\n disabled={pending || props.disabled}\n className={className}\n onClick={(event) => {\n onClick?.(event);\n close();\n }}\n data-fs-account-address-form-cancel=\"\"\n >\n {children ?? resolveAuthoredCopy(label, intl.formatMessage({ id: 'fs/address-form.cancel' }))}\n </Button>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Definitions\n// ---------------------------------------------------------------------------\n\nexport const AccountAddressFormRootDefinition = defineComponent<AccountAddressFormRootProps>({\n name: 'AccountAddressFormRoot',\n importPath: '@vtex/faststore/components',\n component: AccountAddressFormRoot,\n requiresContext: 'session',\n providesContext: 'account-address-form',\n actions: { address: ['create', 'update'] },\n editor: { label: 'Account Address Form', category: 'identity' },\n schema: {\n defaultCountry: { type: 'string', default: 'BRA', label: 'Preferred country (ISO-3)' },\n addedMessage: { type: 'string', label: 'Address added message' },\n savedMessage: { type: 'string', label: 'Address saved message' },\n blockedMessage: { type: 'string', label: 'Save blocked message' },\n returnHref: { type: 'link', default: { standard: 'address' }, label: 'Return page' },\n },\n guideline:\n \"The form that adds an address or corrects a saved one, with the fields, order and options of the address's country. Opens through AccountAddressBookAddTrigger and AccountAddressBookEditTrigger, placed by AccountAddressBookFormSlot or AccountAddressBookFormDialog. Requires a SessionRoot and a mounted ToastProvider ancestor: saving shows a toast and closes the form. On its own page (add: no ancestor; edit: inside AccountAddressRecord) leaving the form, by a save, a save with no changes or Cancel, goes to returnHref instead, so mount the ToastProvider in the layout for the toast to outlive the navigation. A new address takes defaultCountry when the store ships there or the list is unknown, else the first country the store ships to; the shopper picks another through AddressCountryControl. A saved address keeps its own country, shown as text. A save the form or the server blocks marks each field, moves focus to the first one and announces it, and keeps what was typed. With no children it renders AddressCountryControl, AccountAddressCountryNotice, RecipientName, Fields, Reference, Error, Submit and Cancel; that control gets no list there and shows defaultCountry as text, so compose AddressCountryControl explicitly to offer the choice. See account-address-book.md.\",\n});\n\nexport const AccountAddressFormRecipientNameDefinition = defineComponent<AccountAddressFormLabelProps>({\n name: 'AccountAddressFormRecipientName',\n importPath: '@vtex/faststore/components',\n component: AccountAddressFormRecipientName,\n requiresContext: 'account-address-form',\n editor: { label: 'Account Address Form Recipient Name', category: 'input' },\n schema: {\n label: { type: 'string', label: 'Field label' },\n },\n guideline:\n \"The name of the person who receives the order. Required for every country. Place it first, before AccountAddressFormFields. Shown once the country's rules have loaded. Must be inside AccountAddressFormRoot.\",\n});\n\nexport const AccountAddressFormFieldsDefinition = defineComponent<AccountAddressFormFieldsProps>({\n name: 'AccountAddressFormFields',\n importPath: '@vtex/faststore/components',\n component: AccountAddressFormFields,\n requiresContext: 'account-address-form',\n editor: { label: 'Account Address Form Fields', category: 'input' },\n schema: {},\n guideline:\n \"One field per field the address's country asks for, in the order that country's form lists them, with its labels, limits and lists: Brazil's city is a list that follows its state. Changing a list clears the fields that depend on it. Shown once the country's rules have loaded. Must be inside AccountAddressFormRoot.\",\n});\n\nexport const AccountAddressFormReferenceDefinition = defineComponent<AccountAddressFormLabelProps>({\n name: 'AccountAddressFormReference',\n importPath: '@vtex/faststore/components',\n component: AccountAddressFormReference,\n requiresContext: 'account-address-form',\n editor: { label: 'Account Address Form Reference', category: 'input' },\n schema: {\n label: { type: 'string', label: 'Field label' },\n },\n guideline:\n \"A landmark that helps the carrier find the address. Optional. Place it after AccountAddressFormFields. Shown once the country's rules have loaded. Must be inside AccountAddressFormRoot.\",\n});\n\nexport const AccountAddressFormErrorDefinition = defineComponent<AccountAddressFormErrorProps>({\n name: 'AccountAddressFormError',\n importPath: '@vtex/faststore/components',\n component: AccountAddressFormError,\n requiresContext: 'account-address-form',\n editor: { label: 'Account Address Form Error', category: 'content' },\n schema: {\n unrenderedFieldMessage: { type: 'string', label: 'Field not shown message' },\n notFoundMessage: { type: 'string', label: 'Address gone message' },\n unauthorizedMessage: { type: 'string', label: 'Session expired message' },\n saveFailedMessage: { type: 'string', label: 'Save failed message' },\n rulesFailedMessage: { type: 'string', label: 'Form failed to load message' },\n countrySwitchFailedMessage: { type: 'string', label: 'Country change failed message' },\n unsupportedCountryMessage: { type: 'string', label: 'Country not delivered message' },\n },\n guideline:\n \"The error about the whole form, as an alert: a refusal on a field this form does not show, an address that no longer exists, an expired session, a failed save, a form that could not load, a country change that could not load, or a country the store doesn't deliver to. Renders nothing when there is none. Must be inside AccountAddressFormRoot.\",\n});\n\nexport const AccountAddressFormSubmitDefinition = defineComponent<AccountAddressFormButtonProps>({\n name: 'AccountAddressFormSubmit',\n importPath: '@vtex/faststore/components',\n component: AccountAddressFormSubmit,\n requiresContext: 'account-address-form',\n editor: { label: 'Account Address Form Submit', category: 'action' },\n schema: {\n label: { type: 'string', label: 'Button label' },\n },\n guideline:\n \"Saves the form. Disabled until the country's rules have loaded, while a country change loads, and while a save is in flight, and marked busy then. Must be inside AccountAddressFormRoot.\",\n});\n\nexport const AccountAddressFormCancelDefinition = defineComponent<AccountAddressFormButtonProps>({\n name: 'AccountAddressFormCancel',\n importPath: '@vtex/faststore/components',\n component: AccountAddressFormCancel,\n requiresContext: 'account-address-form',\n editor: { label: 'Account Address Form Cancel', category: 'action' },\n schema: {\n label: { type: 'string', label: 'Button label' },\n },\n guideline:\n 'Closes the form and drops what was typed. On its own page it goes to the returnHref of its root. Must be inside AccountAddressFormRoot.',\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqIA,MAAM,kBAAkB;AAExB,MAAM,sBAA+B,EAAE,UAAU,UAAU;;AAG3D,MAAM,oBAAoB;;AAG1B,MAAM,OAAiC,CAAC;CAAE,MAAM;CAAqB,SAAS;AAAG,CAAC;AAElF,MAAM,kBAA4C;CAChD;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAEA,MAAM,kBAAqC;CAAE,MAAM;CAAY,WAAW;AAA4B;AACtG,MAAM,iBAAoC;CAAE,MAAM;CAAW,WAAW;AAA2B;AAEnG,MAAM,oBAA8E;CAClF,iBAAiB;CACjB,UAAU;CACV,cAAc;CACd,YAAY;CACZ,aAAa;CACb,qBAAqB;CACrB,oBAAoB;AACtB;AAOA,SAAS,QAAQ,SAAsE;CACrF,IAAI,CAAC,SAAS,OAAO,CAAC;CACtB,OAAO,OAAO,YAAY,gBAAgB,KAAK,UAAU,CAAC,OAAO,QAAQ,UAAU,EAAE,CAAC,CAAC;AACzF;AAEA,SAAS,aAAa,OAAyC;CAC7D,OAAO,gBAAgB,OAAO,WAAW,MAAM,UAAU,GAAA,CAAI,KAAK,MAAM,EAAE;AAC5E;AAEA,SAAS,UAAU,MAAyC;CAC1D,OAAO,oBAAoB,MAAM,eAAe,CAAC,CAAC,KAAK,CAAC,CAAC,YAAY;AACvE;;AAGA,SAAS,YAAY,EAAE,MAAM,SAAgE;CAC3F,IAAI,SAAS,uBAAuB,OAAO;CAC3C,IAAI,SAAS,aAAa,OAAO;CACjC,IAAI,SAAS,gBAAgB,OAAO;CACpC,OAAO,UAAU,OAAO,eAAe;AACzC;AAEA,SAAS,UAAU,MAAgC;CACjD,OAAO,GAAG,kBAAkB,GAAG;AACjC;;AAGA,SAAS,aAAa,QAA0C;CAC9D,IAAI,OAAO,WAAW,YAAY,WAAW,MAAM,OAAO,CAAC;CAC3D,MAAM,MAAM;CACZ,OAAO,OAAO,YACZ,gBAAgB,SAAS,UAAW,OAAO,IAAI,WAAW,WAAW,CAAC,CAAC,OAAO,IAAI,MAAM,CAAC,IAAI,CAAC,CAAE,CAClG;AACF;AAEA,SAAS,KAAK,OAAgC,QAA0D;CACtG,OAAO,OAAO,YAAY,OAAO,KAAK,UAAU,CAAC,OAAO,MAAM,UAAU,EAAE,CAAC,CAAC;AAC9E;AAEA,SAAS,cAAc,OAAgC,WAAqD;CAC1G,OAAO,gBAAgB,QAAQ,WAAW,MAAM,UAAU,SAAS,UAAU,UAAU,GAAG;AAC5F;AAEA,SAAS,YAAY,OAAiD;CACpE,OAAO,gBAAgB,QAAQ,WAAW,MAAM,UAAU,GAAA,CAAI,KAAK,MAAM,EAAE;AAC7E;;AAKA,SAAS,aAAa,SAAuC,MAAyC;CACpG,IAAI,MAAM;EACR,MAAM,SAAS,SAAS,SAAS;EACjC,OAAO,UAAU,YAAY,OAAO,OAA+B,IAAI,KAAA;CACzE;CACA,MAAM,SAAS,SAAS,SAAS;CACjC,OAAO,UAAU,YAAY,OAAO,OAA+B,IAAI,KAAA;AACzE;;AAGA,SAAS,cACP,OACA,UACsG;CACtG,MAAM,WAAiE,CAAC;CACxE,IAAI,YAAY;CAChB,KAAK,MAAM,CAAC,MAAM,UAAU,OAAO,QAAQ,KAAK,GAC9C,IAAI,SAAS,IAAI,IAAI,GAAG,SAAS,QAAQ;MACpC,YAAY;CAEnB,OAAO;EAAE;EAAU,WAAW,YAAY,oBAAoB;CAAK;AACrE;AASA,SAAS,aAAa,EAAE,QAAQ,cAAc,cAAc,QAAmC;CAC7F,IAAI,QAAQ,OAAO,oBAAoB,cAAc,KAAK,cAAc,EAAE,IAAI,wBAAwB,CAAC,CAAC;CACxG,OAAO,oBAAoB,cAAc,KAAK,cAAc,EAAE,IAAI,wBAAwB,CAAC,CAAC;AAC9F;AAEA,SAAS,eACP,QACA,gBACA,MACQ;CACR,IAAI,WAAW,MAAM,OAAO;CAC5B,IAAI,OAAO,SAAS,UAClB,OAAO,KAAK,cAAc,EAAE,IAAI,gCAAgC,GAAG,EAAE,OAAO,OAAO,MAAM,CAAC;CAC5F,MAAM,WACJ,OAAO,SAAS,WACZ,KAAK,cAAc,EAAE,IAAI,gCAAgC,GAAG,EAAE,OAAO,OAAO,MAAM,CAAC,IACnF,KAAK,cAAc,EAAE,IAAI,gCAAgC,CAAC;CAChE,OAAO,oBAAoB,gBAAgB,QAAQ;AACrD;AAEA,SAAS,kBAAkB,MAA8B,QAAuC;CAC9F,IAAI,CAAC,MAAM;CACX,KAAK,MAAM,WAAW,KAAK,iBAA8B,sCAAsC,GAAG;EAChG,MAAM,OAAO,QAAQ,QAAQ;EAC7B,IAAI,QAAQ,OAAO,OAAO;GACxB,QAAQ,cAA2B,wCAAwC,CAAC,EAAE,MAAM;GACpF;EACF;CACF;AACF;;AAOA,SAAS,mBAAmB;CAC1B,MAAM,OAAO,8BAA8B;CAC3C,MAAM,SAAS,gCAAgC;CAC/C,MAAM,WAAW,MAAM,YAAY;CACnC,MAAM,QAAQ,UAAU,SAAS,SAAS,SAAS,UAAU,SAAS,QAAQ,WAAW;CACzF,OAAO;EAAE;EAAM;EAAQ;EAAM,MAAM,OAAQ,SAAoB;CAAgB;AACjF;AAEA,SAAgB,uBAAuB,EACrC,gBACA,cACA,cACA,gBACA,YACA,UACA,WACA,UACA,GAAG,SAC2B;CAE9B,MAAM,EAAE,OAAO,iBAAiB,WAAW;CAC3C,SAAS;CACT,MAAM,EAAE,MAAM,QAAQ,SAAS,iBAAiB;CAEhD,MAAM,CAAC,SAAS,cAAc,SAAS,KAAK;CAC5C,MAAM,qBAAqB,MAAM;CACjC,gBAAgB;EACd,qBAAqB,OAAO;EAC5B,aAAa,qBAAqB,KAAK;CACzC,GAAG,CAAC,SAAS,kBAAkB,CAAC;CAChC,MAAM,CAAC,cAAc,mBAAmB,SAAwB,IAAI;CAEpE,IAAI,iBAAiB,YAAY,OAAO;CAExC,IAAI,CAAC,QAAQ,UAAU,CAAC,OAAO,SAAS,OAAO;CAE/C,OACE,oBAAC,UAAD;EACE,GAAI;EACO;EACX,aAAW,WAAW,iBAAiB,QAAQ,KAAA;EAC/C,gCAA6B;EAC7B,qCAAmC;EAEnC,UAAA,oBAAC,wBAAD;GACkB;GACF;GACA;GACE;GACJ;GACF;GACD;GACG;GACE;GACG;GAEhB,UAAA,YACC,qBAAA,YAAA,EAAA,UAAA;IACE,oBAAC,uBAAD,CAAwB,CAAA;IACxB,oBAAC,6BAAD,CAA8B,CAAA;IAC9B,oBAAC,iCAAD,CAAkC,CAAA;IAClC,oBAAC,0BAAD,CAA2B,CAAA;IAC3B,oBAAC,6BAAD,CAA8B,CAAA;IAC9B,oBAAC,yBAAD,CAA0B,CAAA;IAC1B,oBAAC,0BAAD,CAA2B,CAAA;IAC3B,oBAAC,0BAAD,CAA2B,CAAA;GAC3B,EAAA,CAAA;EAEkB,CAAA;CAChB,CAAA;AAEd;;;;;AAoBA,SAAS,uBAAuB,EAC9B,gBACA,cACA,cACA,gBACA,YACA,UAAU,cACV,SACA,YACA,cACA,iBACA,YAC8B;CAC9B,MAAM,EAAE,qBAAqB,gBAAgB;CAC7C,MAAM,EAAE,WAAW,UAAU,cAAc,eAAe;CAC1D,MAAM,QAAQ,SAAS;CACvB,MAAM,OAAO,QAAQ;CACrB,MAAM,WAAW,mBAAmB,YAAY;CAChD,MAAM,EAAE,SAAS,wBAAwB;CACzC,MAAM,EAAE,MAAM,MAAM,SAAS,iBAAiB;CAC9C,MAAM,mBAAmB,UAAU,MAAM,WAAW,cAAc;CAClE,MAAM,YAAY,cAAc,QAAQ,IAAI,GAAG,CAAC,IAAI,CAAC;CACrD,MAAM,QAAQ,MAAM;CAEpB,MAAM,CAAC,SAAS,cAAc,SAA+C,KAAA,CAAS;CACtF,MAAM,CAAC,eAAe,oBAAoB,SAAwB,IAAI;CACtE,MAAM,CAAC,YAAY,iBAAiB,SAA6C,IAAI;CACrF,MAAM,CAAC,OAAO,YAAY,SAA8B,IAAI;CAC5D,MAAM,CAAC,aAAa,kBAAkB,SAAwC,CAAC,CAAC;CAChF,MAAM,CAAC,WAAW,gBAAgB,SAA6C,IAAI;CACnF,MAAM,CAAC,QAAQ,aAAa,SAAwB,IAAI;CACxD,MAAM,aAAa,OAAO,KAAK;CAG/B,MAAM,aAAa,OAAO,IAAI;CAC9B,gBAAgB;EACd,WAAW,UAAU;EACrB,aAAa;GACX,WAAW,UAAU;EACvB;CACF,GAAG,CAAC,CAAC;CACL,MAAM,aAAa,OAAO,KAAK;CAC/B,MAAM,YAAY,OAA0B,IAAI;CAChD,MAAM,SAAS,OAAO,CAAC;CACvB,MAAM,cAAc,OAAO,KAAK;CAChC,MAAM,cAAc,OAAO,CAAC;CAC5B,MAAM,WAAW,OAA6B,CAAC,CAAC;CAEhD,MAAM,EAAE,UAAU,kBAAkB,sBAAsB,iBAAiB;CAC3E,MAAM,UAAU,SAAS,EAAE,MAAM,kBAAkB,CAAC;CAEpD,MAAM,QAAQ,eACL;EAAE,GAAG;EAAW,GAAG,aAAa,OAAO;CAAE,IAChD,CAAC,WAAW,OAAO,CACrB;CAGA,MAAM,UAAU,SAAS,SAAS,mBAAoB,iBAAiB;CACvE,MAAM,SAAS,OAAO;EAAE;EAAM;EAAS;EAAO;CAAU,CAAC;CACzD,sBAAsB;EACpB,OAAO,UAAU;GAAE;GAAM;GAAS;GAAO;EAAU;CACrD,CAAC;;CAGD,MAAM,YAAY,mBACgB;EAAE,GAAG,OAAO,QAAQ;EAAW,GAAG,aAAa,UAAU,iBAAiB,CAAC;CAAE,IAC7G,CAAC,SAAS,CACZ;;CAGA,MAAM,aAAa,aAChB,WAAoC;EACnC,MAAM,UAAU,UAAU;EAC1B,KAAK,MAAM,CAAC,MAAM,UAAU,OAAO,QAAQ,MAAM,GAC/C,KAAK,QAAQ,SAAS,QAAQ,OAAO,SAAS,UAAU,IAAI,GAAG,OAAO,EAAE,aAAa,KAAK,CAAC;CAE/F,GACA,CAAC,WAAW,QAAQ,CACtB;CAEA,MAAM,gBAAgB,kBACd,IAAI,IAAI,cAAc,CAAC,CAAC,KAAK,SAAS,KAAK,MAAM,EAA4B,CAAqB,CAAC,GACzG,CAAC,aAAa,CAChB;;;;;CAMA,MAAM,cAAc,aACjB,MAAc,SAAS,UAAU;EAChC,MAAM,KAAK,UAAU,IAAI;EACzB,IAAI,OAAO,QAAQ,SAAS,OAAO;EACnC,MAAM,QAAQ,EAAE,YAAY;EAC5B,IAAI,OAAO,OAAO,QAAQ,SAAS;GACjC,gBAAgB,IAAI;GACpB;EACF;EACA,gBAAgB,EAAE;EAClB,iBAAiB,EAAE,CAAC,CAAC,MAClB,YAAY;GACX,IAAI,UAAU,YAAY,SAAS;GACnC,MAAM,EAAE,OAAO,cAAc,OAAO;GACpC,IAAI,WAAW;IACb,MAAM,SAAS,mBAAmB;KAChC,OAAO,UAAU;KACjB,OAAO,SAAS;KAChB,MAAM;KACN,IAAI;IACN,CAAC;IACD,SAAS,UAAU,OAAO;IAE1B,WAAW,OAAO,YAAY,gBAAgB,KAAK,UAAU,CAAC,OAAO,OAAO,MAAM,UAAU,EAAE,CAAC,CAAC,CAAC;IACjG,cAAc,OAAO,MAAM;GAC7B;GACA,SAAS,OAAO;GAChB,iBAAiB,EAAE;GACnB,gBAAgB,IAAI;GACpB,eAAe,CAAC,CAAC;GACjB,aAAa,IAAI;GACjB,UAAU,IAAI;EAChB,SACM;GACJ,IAAI,UAAU,YAAY,SAAS;GACnC,gBAAgB,IAAI;GACpB,IAAI,CAAC,QAAQ,aAAa,qBAAqB;EACjD,CACF;CACF,GACA;EAAC;EAAW;EAAY;CAAe,CACzC;CAEA,sBACc;EACV,YAAY,WAAW;CACzB,GACA,CAAC,CACH;CAEA,MAAM,SAAS,aACZ,OAAe;EACd,IAAI,WAAW,SAAS;EACxB,YAAY,UAAU;EACtB,YAAY,EAAE;CAChB,GACA,CAAC,WAAW,CACd;CAEA,MAAM,QAAQ,aAAa,cAAwC;EACjE,OAAO,WAAW;EAClB,WAAW,SAAS;EACpB,aAAa;GACX,OAAO,WAAW;GAClB,IAAI,OAAO,YAAY,GAAG,WAAW,KAAA,CAAS;EAChD;CACF,GAAG,CAAC,CAAC;CAKL,gBAAgB;EACd,IAAI,SAAS,OAAO;EACpB,IAAI,YAAY,KAAA,GAAW;GACzB,IAAI,OAAO,YAAY,GAAG,kBAAkB,YAAY,WAAW,gBAAgB;GACnF;EACF;EACA,MAAM,UAAU,sBAAsB,SAAS,gBAAgB;EAC/D,IAAI,kBAAkB,MAAM,iBAAiB,OAAO;OAC/C,IAAI,CAAC,YAAY,WAAW,YAAY,iBAAiB,aAAa,UAAU,CAAC,GACpF,YAAY,SAAS,IAAI;CAE7B,GAAG;EAAC;EAAM;EAAS;EAAkB;EAAe;EAAa;CAAS,CAAC;CAI3E,gBAAgB;EACd,IAAI,CAAC,SAAS;EACd,IAAI,UAAU;EACd,iBAAiB,OAAO,CAAC,CAAC,MACvB,WAAW;GACV,IAAI,CAAC,SAAS;GACd,SAAS,MAAM;GACf,IAAI,MAAM,eAAe,gBAAgB,WAAW,MAAM,CAAC;EAC7D,SACM;GACJ,IAAI,SAAS,aAAa,aAAa;EACzC,CACF;EACA,aAAa;GACX,UAAU;EACZ;CACF,GAAG;EAAC;EAAS;EAAM;CAAS,CAAC;CAE7B,MAAM,gBAAgB,aACnB,SAA2B,SAAS,kBAAkB,UAAU,IAAI,CAAC,GACtE,CAAC,QAAQ,CACX;CAEA,MAAM,YAAY,aACf,WAAyB;EACxB,WAAW,MAAM;EACjB,gBAAgB,aAAa;GAC3B,MAAM,OAAO,OAAO,YAAY,OAAO,QAAQ,QAAQ,CAAC,CAAC,QAAQ,CAAC,UAAU,EAAE,QAAQ,OAAO,CAAC;GAC9F,OAAO,OAAO,KAAK,IAAI,CAAC,CAAC,WAAW,OAAO,KAAK,QAAQ,CAAC,CAAC,SAAS,WAAW;EAChF,CAAC;EACD,MAAM,QAAQ,OAAO,OAAO,MAAM,CAAC,CAAC,QAAQ,UAAU,UAAU,EAAE,CAAC,CAAC;EACpE,IAAI,QAAQ,GAAG,UAAU;GAAE,MAAM;GAAU;EAAM,CAAC;CACpD,GACA,CAAC,UAAU,CACb;CAGA,MAAM,EAAE,cAAc,sBADL,sBAAsB;EAAE;EAAS;EAAO;EAAO,QAAQ;CAAU,CAC/B;CAEnD,MAAM,WAAW,aACd,MAAqB,UAAkB;EACtC,aAAa,IAAI;EACjB,IAAI,SAAS,cAAc,kBAAkB,KAAK;EAClD,SAAS,UAAU,IAAI,GAAG,OAAO,EAAE,aAAa,KAAK,CAAC;EACtD,gBAAgB,aAAa;GAC3B,IAAI,CAAC,SAAS,OAAO,OAAO;GAC5B,MAAM,GAAG,OAAO,UAAU,GAAG,SAAS;GACtC,OAAO;EACT,CAAC;EACD,cAAc,aAAc,aAAa,gBAAgB,WAAW,IAAK;EACzE,UAAU,IAAI;CAChB,GACA;EAAC;EAAc;EAAmB;CAAQ,CAC5C;CAEA,MAAM,cAAc,OAAO,eAAe,YAAY,WAAW,KAAK,CAAC,CAAC,WAAW,IAAI,KAAA,IAAY;CAInG,MAAM,YAAY,kBAAkB;EAClC,IAAI,MAAM;GACR,QAAQ;GACR;EACF;EACA,IAAI,gBAAgB,KAAA,GAClB,KAAK,mBAAmB;OACnB,IAAI,OAAO,gBAAgB,UAAU;GAC1C,MAAM,SAAS,wBAAwB,WAAW;GAClD,IAAI,OAAO,MACT,KAAK,OAAO,IAAI;QAEhB,QAAQ,KAAK,gDAAgD,OAAO,OAAO,KAAK,aAAa;EAEjG,OACE,KAAK,WAAW;CAEpB,GAAG;EAAC;EAAM;EAAO;EAAa;CAAI,CAAC;CAEnC,SAAS,MAAM,QAAuC,WAAuD;EAC3G,MAAM,QAAQ,OAAO,KAAK,MAAM,CAAC,CAAC;EAClC,MAAM,UAAkB,QAAQ,IAAI;GAAE,MAAM;GAAU;EAAM,IAAI,EAAE,MAAM,SAAS;EACjF,eAAe,MAAM;EACrB,aAAa,SAAS;EACtB,UAAU,OAAO;EACjB,kBAAkB,UAAU,SAAS,QAAQ,MAAM,KAAK,MAAM,MAAM;EACpE,OAAO;CACT;;CAGA,SAAS,aAAa,SAAkC,cAAoD;EAC1G,MAAM,EAAE,UAAU,cAAc,cAAc,gBAAgB,SAAS,YAAY,GAAG,cAAc,CAAC;EACrG,IAAI,cAAc,QAAQ,OAAO,KAAK,QAAQ,CAAC,CAAC,WAAW,GAAG,OAAO;EAErE,OAAO,CAAC;GAAE,MAAM;GAAwB,SAAS,eADjC,MAAM,UAAU,SACsC,GAAG,gBAAgB,IAAI;EAAE,CAAC;CAClG;;CAGA,SAAS,OAAO,YAAiD;EAC/D,MAAM,SAA+D,CAAC;EACtE,MAAM,WAAW,cAAc;EAC/B,IAAI,YAAgD;EAEpD,KAAK,MAAM,aAAa,YAAY;GAClC,MAAM,OAAO,mBAAmB,UAAU,KAAK;GAC/C,MAAM,UAAU,UAAU,SAAS,eAAe,UAAU,SAAS;GACrE,IAAI,QAAQ,SAAS,IAAI,IAAI,KAAK,SAChC,OAAO,UAAU,UAAU,SAAS,2BAA2B,kBAAkB;QAEjF,cAAc,YAAY,SAAS;EAEvC;EACA,MAAM,QAAQ,SAAS;CACzB;CAEA,SAAS,UAAU,QAA0D;EAC3E,MAAM,UAAU;GAAE,GAAG;GAAW,GAAG,aAAa,MAAM;EAAE;EACxD,IAAI,MAAM,OAAO;GAAE,IAAI,KAAK;GAAI,GAAG,KAAK,SAAS,cAAc,SAAS,SAAS,CAAC;EAAE;EACpF,OAAO;GAAE;GAAS,GAAG,KAAK,SAAS,YAAY,OAAO,CAAC;EAAE;CAC3D;;CAGA,eAAe,SAAS,SAAqE;EAC3F,IAAI,CAAC,SAAS,WAAW,WAAW,iBAAiB,MAAM,OAAO;EAElE,MAAM,UAAU,UAAU;EAC1B,MAAM,UAAU,aAAa,SAAS,KAAK;EAC3C,IAAI,SAAS,OAAO;EACpB,IAAI,QAAQ,cAAc,SAAS,SAAS,CAAC,CAAC,WAAW,GAAG;GAC1D,eAAe,CAAC,CAAC;GACjB,UAAU;GACV,OAAO,CAAC;EACV;EAEA,eAAe,CAAC,CAAC;EACjB,aAAa,IAAI;EACjB,UAAU,IAAI;EAEd,MAAM,QAAQ,aAAa,UAAU,SAAS,IAAI;EAClD,IAAI,CAAC,OAAO;GAEV,MAAM,CAAC,GAAG,YAAY;GACtB,MAAM,IAAI,MAAM,mDAAmD;EACrE;EAEA,WAAW,UAAU;EACrB,WAAW,IAAI;EACf,IAAI;GACF,MAAM,aAAa,MAAM,MAAM,OAAO;GACtC,IAAI,WAAW,SAAS,GAAG;IACzB,OAAO,UAAU;IACjB,OAAO;GACT;GACA,MAAM,IAAI;IAAE,OAAO,aAAa;KAAE,QAAQ,SAAS;KAAM;KAAc;KAAc;IAAK,CAAC;IAAG,MAAM;GAAU,CAAC;GAC/G,IAAI,WAAW,SAAS,UAAU;GAClC,OAAO,CAAC;EACV,SAAS,OAAO;GAEd,QAAQ,MAAM,iDAAiD,kBAAkB,KAAK,CAAC;GACvF,MAAM,CAAC,GAAG,YAAY;GACtB,MAAM;EACR,UAAU;GACR,WAAW,UAAU;GACrB,WAAW,KAAK;EAClB;CACF;;;;;;CAOA,SAAS,eAAe;EAEtB,SAAS,UAAU,UAAU,iBAAiB,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,KAAA,CAAS;CAC/E;CAEA,MAAM,WAAW,OAAO;EAAE;EAAW;EAAU;CAAa,CAAC;CAC7D,sBAAsB;EACpB,SAAS,UAAU;GAAE;GAAW;GAAU;EAAa;CACzD,CAAC;CAED,gBAEI,iBAAiB;EACf,WAAW;EACX;EACA,YAAY,WAAW,SAAS,QAAQ,UAAU,MAAM;EACxD,WAAW,YAAY;GACrB,WAAW,UAAU;GACrB,OAAO,SAAS,QAAQ,SAAS,OAAO;EAC1C;EACA,OAAO;CACT,CAAC,GACH,CAAC,kBAAkB,aAAa,CAClC;CAGA,gBAAgB;EACd,IAAI,OAAO;EACX,OAAO,UAAU;GACf,WAAW,EAAE,aAAa,KAAK;GAC/B,WAAW,EAAE,cAAc,QAAQ;IACjC,IAAI,gBAAgB,MAAM;IAC1B,OAAO;IACP,IAAI,WAAW,SAAS,WAAW,UAAU;SACxC,SAAS,QAAQ,aAAa;GACrC;EACF,CAAC;CACH,GAAG,CAAC,SAAS,CAAC;CAEd,MAAM,WAAW,gBAAgB;CACjC,MAAM,gBAAgB,eACb;EAAE;EAAO;EAAU;EAAQ;CAAW,IAC7C;EAAC;EAAO;EAAU;EAAQ;CAAU,CACtC;CAEA,MAAM,QAAQ,eACL;EACL;EACA;EACA;EACA;EACA;EACA;EACA,SAAS;EACT;EACA;EACA,OAAO;EACP;CACF,IACA;EAAC;EAAM;EAAS;EAAO;EAAO;EAAa;EAAW;EAAS;EAAU;EAAe;EAAW;CAAa,CAClH;CAEA,OACE,oBAAC,sBAAD;EAAsB,OAAO;EAC3B,UAAA,qBAAC,2BAAD;GAAkC;GAAlC,UAAA,CACG,UACD,oBAAC,UAAD;IACE,KAAK;IACL,aAAU;IACV,uCAAoC;IACpC,mBAAgB;IAChB,WAAU;IAET,UAAA,eAAe,QAAQ,gBAAgB,IAAI;GACtC,CAAA,CACiB;;CACP,CAAA;AAE1B;AAMA,SAAS,eAAe,OAA0B,MAA0C;CAC1F,OAAO,KAAK,cAAc,EAAE,IAAI,MAAM,UAAU,GAAG,MAAM,MAAM;AACjE;;AAGA,SAAS,qBAAqB,MAA6B;CACzD,MAAM,EAAE,UAAU,sBAAsB;CACxC,MAAM,EAAE,cAAc,eAAe;CACrC,MAAM,OAAO,iBAAiB,mBAAmB,IAAI;CAGrD,MAAM,CAAC,QAAQ,eAAe;EAC5B,MAAM,OAAgB,UAAU,IAAI;EACpC,OAAO,OAAO,SAAS,WAAW,OAAQ,MAAM,SAAS;CAC3D,CAAC;CACD,OAAO,cAAc;EAAE,MAAM;EAAM,cAAc;CAAK,GAAG,gBAAgB,CAAC,CAAC;AAC7E;;AAGA,SAAS,aACP,UACA,MACA,OACA,aACA;CACA,SAAS,MAAM,KAAK;CACpB,KAAK,MAAM,aAAa,aAAa,MAAM,WAAW,GAAG,SAAS,WAAW,EAAE;AACjF;AAWA,SAAS,iBAAiB,EAAE,MAAM,OAAO,WAAW,WAAW,aAAa,aAA6B;CACvG,MAAM,EAAE,aAAa,aAAa,sBAAsB;CACxD,MAAM,QAAQ,qBAAqB,IAAI;CACvC,MAAM,OAAO,QAAQ;CACrB,MAAM,QAAQ,YAAY;CAE1B,OACE,qBAAC,MAAM,MAAP;EAAuB;EAAW,SAAS,CAAC,CAAC;EAAO,sCAAoC;EAAxF,UAAA;GACE,oBAAC,MAAM,OAAP,EAAA,UAAc,MAAmB,CAAA;GACjC,oBAAC,MAAM,SAAP;IACS;IACP,WAAW,UAAU,SAAS,MAAM,MAAM,OAAO,KAAK;IAC3C;IACA;IACE;IACb,wCAAqC;GACtC,CAAA;GACA,QAAQ,oBAAC,MAAM,OAAP;IAAa,OAAA;IAAO,UAAA,eAAe,OAAO,IAAI;GAAe,CAAA,IAAI;EAChE;;AAEhB;AAYA,SAAS,mBAAmB,EAAE,MAAM,OAAO,SAAS,aAAa,WAAW,YAA8B;CACxG,MAAM,EAAE,gBAAgB,sBAAsB;CAC9C,MAAM,QAAQ,qBAAqB,IAAI;CACvC,MAAM,OAAO,QAAQ;CACrB,MAAM,UAAU,MAAM;CACtB,MAAM,QAAQ,YAAY;CAE1B,OACE,qBAAC,OAAD;EAAgB;EAAW,sCAAoC;EAAM,GAAK,QAAQ,EAAE,gBAAgB,GAAG,IAAI,CAAC;EAA5G,UAAA,CACE,qBAAC,OAAO,MAAR;GAAoB;GAAO,gBAAgB,SAAS,SAAS,QAAQ,EAAE;GAAvE,UAAA;IACE,oBAAC,OAAO,OAAR,EAAA,UAAe,MAAoB,CAAA;IACnC,qBAAC,OAAO,SAAR;KACE,gBAAc,QAAQ,OAAO,KAAA;KAC7B,oBAAkB,QAAQ,UAAU,KAAA;KACpC,wCAAqC;KAHvC,UAAA,CAKE,oBAAC,OAAO,OAAR;MAA2B;MACvB,WAAA,UAAU,QAAQ,MAAM,WAAW,OAAO,UAAU,KAAK,CAAC,EAAE,SAAS;KAC3D,CAAA,GACd,oBAAC,OAAO,MAAR,CAAc,CAAA,CACA;;IAChB,oBAAC,OAAO,QAAR,EAAA,UACE,oBAAC,OAAO,YAAR,EAAA,UACE,oBAAC,OAAO,OAAR,EAAA,UACE,oBAAC,OAAO,MAAR,EAAA,UACG,QAAQ,KAAK,WACZ,oBAAC,OAAO,MAAR;KAAgC,OAAO,OAAO;KAAO,OAAO,OAAO;KACjE,UAAA,oBAAC,OAAO,UAAR,EAAA,UAAkB,OAAO,MAAuB,CAAA;IACrC,GAFK,OAAO,KAEZ,CACd,EACU,CAAA,EACD,CAAA,EACG,CAAA,EACN,CAAA;GACJ;EACZ,CAAA,GAAA,QACC,oBAAC,KAAD;GAAG,IAAI;GAAS,4CAAyC;GACtD,UAAA,eAAe,OAAO,IAAI;EAC1B,CAAA,IACD,IACD;;AAET;AAEA,SAAgB,gCAAgC,EAAE,OAAO,aAA2C;CAClG,MAAM,EAAE,UAAU,sBAAsB;CACxC,MAAM,OAAO,QAAQ;CAErB,IAAI,CAAC,OAAO,OAAO;CAEnB,OACE,oBAAC,kBAAD;EACE,MAAK;EACL,OAAO,oBAAoB,OAAO,KAAK,cAAc,EAAE,IAAI,qBAAqB,cAAc,CAAC,CAAC;EAChG,WAAW,mBAAmB;EACnB;CACZ,CAAA;AAEL;AAEA,SAAgB,4BAA4B,EAAE,OAAO,aAA2C;CAC9F,MAAM,EAAE,UAAU,sBAAsB;CACxC,MAAM,OAAO,QAAQ;CAErB,IAAI,CAAC,OAAO,OAAO;CAEnB,OACE,oBAAC,kBAAD;EACE,MAAK;EACL,OAAO,oBAAoB,OAAO,KAAK,cAAc,EAAE,IAAI,qBAAqB,UAAU,CAAC,CAAC;EAC5F,WAAW,mBAAmB;EACnB;CACZ,CAAA;AAEL;;;;;;AAOA,SAAgB,yBAAyB,EAAE,aAA4C;CACrF,MAAM,EAAE,OAAO,OAAO,aAAa,sBAAsB;CACzD,MAAM,OAAO,QAAQ;CAErB,IAAI,CAAC,OAAO,OAAO;CAEnB,MAAM,cAAc,cAAc,OAAO,KAAK;CAE9C,OAAO,YAAY,KAAK,eAAe;EACrC,MAAM,EAAE,MAAM,SAAS,SAAS,WAAW,WAAW,SAAS,gBAAgB;EAC/E,MAAM,QAAQ,KAAK,cAAc,EAAE,IAAI,QAAQ,CAAC;EAChD,MAAM,OAAO,cAAc,KAAK,cAAc,EAAE,IAAI,YAAY,GAAG,GAAG,YAAY,MAAM,IAAI,KAAA;EAE5F,IAAI,YAAY,UACd,OACE,oBAAC,oBAAD;GAEQ;GACC;GACP,SAAS,WAAW,CAAC;GACrB,aAAa;GACF;GACX,WAAW,UAAU,aAAa,UAAU,MAAM,OAAO,WAAW;EACrE,GAPM,IAON;EAIL,OACE,oBAAC,kBAAD;GAEQ;GACC;GACI;GACA;GACX,aAAa;GACF;EACZ,GAPM,IAON;CAEL,CAAC;AACH;AAMA,SAAgB,wBAAwB,EACtC,wBACA,iBACA,qBACA,mBACA,oBACA,4BACA,2BACA,WACA,GAAG,SAC4B;CAC/B,MAAM,EAAE,cAAc,sBAAsB;CAC5C,MAAM,OAAO,QAAQ;CAErB,IAAI,CAAC,WAAW,OAAO;CAEvB,MAAM,WAA8E;EAClF,iBAAiB;EACjB,UAAU;EACV,cAAc;EACd,YAAY;EACZ,aAAa;EACb,qBAAqB;EACrB,oBAAoB;CACtB;CAEA,OACE,oBAAC,OAAD;EAAK,GAAI;EAAO,MAAK;EAAmB;EAAW,sCAAoC;EACpF,UAAA,oBAAoB,SAAS,YAAY,KAAK,cAAc,EAAE,IAAI,kBAAkB,WAAW,CAAC,CAAC;CAC/F,CAAA;AAET;AAEA,SAAgB,yBAAyB,EAAE,OAAO,WAAW,UAAU,GAAG,SAAwC;CAChH,MAAM,EAAE,SAAS,OAAO,WAAW,SAAS,kBAAkB,sBAAsB;CACpF,MAAM,OAAO,QAAQ;CACrB,MAAM,YAAY,cAAc,aAAa;CAE7C,OACE,oBAAC,QAAD;EACE,GAAI;EACJ,MAAK;EACM;EACX,UAAU,UAAU,QAAQ,cAAc,iBAAiB,WAAW;EACtE,aAAW,WAAW,KAAA;EACtB,uCAAoC;EAEnC,UAAA,YAAY,oBAAoB,OAAO,KAAK,cAAc,EAAE,IAAI,yBAAyB,CAAC,CAAC;CACtF,CAAA;AAEZ;AAEA,SAAgB,yBAAyB,EACvC,OACA,WACA,UACA,SACA,GAAG,SAC6B;CAChC,MAAM,EAAE,OAAO,YAAY,sBAAsB;CACjD,MAAM,OAAO,QAAQ;CAErB,OACE,oBAAC,QAAD;EACE,GAAI;EACJ,MAAK;EACL,UAAU,WAAW,MAAM;EAChB;EACX,UAAU,UAAU;GAClB,UAAU,KAAK;GACf,MAAM;EACR;EACA,uCAAoC;EAEnC,UAAA,YAAY,oBAAoB,OAAO,KAAK,cAAc,EAAE,IAAI,yBAAyB,CAAC,CAAC;CACtF,CAAA;AAEZ;AAMA,MAAa,mCAAmC,gBAA6C;CAC3F,MAAM;CACN,YAAY;CACZ,WAAW;CACX,iBAAiB;CACjB,iBAAiB;CACjB,SAAS,EAAE,SAAS,CAAC,UAAU,QAAQ,EAAE;CACzC,QAAQ;EAAE,OAAO;EAAwB,UAAU;CAAW;CAC9D,QAAQ;EACN,gBAAgB;GAAE,MAAM;GAAU,SAAS;GAAO,OAAO;EAA4B;EACrF,cAAc;GAAE,MAAM;GAAU,OAAO;EAAwB;EAC/D,cAAc;GAAE,MAAM;GAAU,OAAO;EAAwB;EAC/D,gBAAgB;GAAE,MAAM;GAAU,OAAO;EAAuB;EAChE,YAAY;GAAE,MAAM;GAAQ,SAAS,EAAE,UAAU,UAAU;GAAG,OAAO;EAAc;CACrF;CACA,WACE;AACJ,CAAC;AAED,MAAa,4CAA4C,gBAA8C;CACrG,MAAM;CACN,YAAY;CACZ,WAAW;CACX,iBAAiB;CACjB,QAAQ;EAAE,OAAO;EAAuC,UAAU;CAAQ;CAC1E,QAAQ,EACN,OAAO;EAAE,MAAM;EAAU,OAAO;CAAc,EAChD;CACA,WACE;AACJ,CAAC;AAED,MAAa,qCAAqC,gBAA+C;CAC/F,MAAM;CACN,YAAY;CACZ,WAAW;CACX,iBAAiB;CACjB,QAAQ;EAAE,OAAO;EAA+B,UAAU;CAAQ;CAClE,QAAQ,CAAC;CACT,WACE;AACJ,CAAC;AAED,MAAa,wCAAwC,gBAA8C;CACjG,MAAM;CACN,YAAY;CACZ,WAAW;CACX,iBAAiB;CACjB,QAAQ;EAAE,OAAO;EAAkC,UAAU;CAAQ;CACrE,QAAQ,EACN,OAAO;EAAE,MAAM;EAAU,OAAO;CAAc,EAChD;CACA,WACE;AACJ,CAAC;AAED,MAAa,oCAAoC,gBAA8C;CAC7F,MAAM;CACN,YAAY;CACZ,WAAW;CACX,iBAAiB;CACjB,QAAQ;EAAE,OAAO;EAA8B,UAAU;CAAU;CACnE,QAAQ;EACN,wBAAwB;GAAE,MAAM;GAAU,OAAO;EAA0B;EAC3E,iBAAiB;GAAE,MAAM;GAAU,OAAO;EAAuB;EACjE,qBAAqB;GAAE,MAAM;GAAU,OAAO;EAA0B;EACxE,mBAAmB;GAAE,MAAM;GAAU,OAAO;EAAsB;EAClE,oBAAoB;GAAE,MAAM;GAAU,OAAO;EAA8B;EAC3E,4BAA4B;GAAE,MAAM;GAAU,OAAO;EAAgC;EACrF,2BAA2B;GAAE,MAAM;GAAU,OAAO;EAAgC;CACtF;CACA,WACE;AACJ,CAAC;AAED,MAAa,qCAAqC,gBAA+C;CAC/F,MAAM;CACN,YAAY;CACZ,WAAW;CACX,iBAAiB;CACjB,QAAQ;EAAE,OAAO;EAA+B,UAAU;CAAS;CACnE,QAAQ,EACN,OAAO;EAAE,MAAM;EAAU,OAAO;CAAe,EACjD;CACA,WACE;AACJ,CAAC;AAED,MAAa,qCAAqC,gBAA+C;CAC/F,MAAM;CACN,YAAY;CACZ,WAAW;CACX,iBAAiB;CACjB,QAAQ;EAAE,OAAO;EAA+B,UAAU;CAAS;CACnE,QAAQ,EACN,OAAO;EAAE,MAAM;EAAU,OAAO;CAAe,EACjD;CACA,WACE;AACJ,CAAC"}
@@ -0,0 +1,189 @@
1
+ "use client";
2
+ import { addressFields } from "../../sdk/address/address-fields.js";
3
+ import { validateAddress } from "../../sdk/address/validate-address.js";
4
+ import { hasPostalCodeLookup } from "../../sdk/address/postal-code.js";
5
+ import { useAddressByPostalCode } from "../../sdk/address/use-address-by-postal-code.js";
6
+ import { useCallback, useEffect, useLayoutEffect, useRef } from "react";
7
+ /** The fields the lookup can fill, in the order it fills them: a state comes before its cities. */
8
+ const FILLABLE_FIELDS = [
9
+ "state",
10
+ "city",
11
+ "neighborhood",
12
+ "street"
13
+ ];
14
+ function fold(value) {
15
+ return value.normalize("NFD").replaceAll(/\p{Diacritic}/gu, "").toLowerCase().trim();
16
+ }
17
+ /** Every field below a changed one that reads its options from it, directly or through another field. */
18
+ function dependentsOf(name, descriptors) {
19
+ const found = /* @__PURE__ */ new Set();
20
+ const queue = [name];
21
+ for (const current of queue) for (const descriptor of descriptors) if (descriptor.dependsOn === current && !found.has(descriptor.name)) {
22
+ found.add(descriptor.name);
23
+ queue.push(descriptor.name);
24
+ }
25
+ return found;
26
+ }
27
+ /** The option a platform value names: by value, ignoring case, else by label, ignoring case and accents. */
28
+ function matchOption(descriptor, platformValue) {
29
+ const options = descriptor.options ?? [];
30
+ const lower = platformValue.toLowerCase();
31
+ const byValue = options.find(({ value }) => value.toLowerCase() === lower);
32
+ if (byValue) return byValue.value;
33
+ const folded = fold(platformValue);
34
+ return options.find(({ label }) => fold(label) === folded)?.value ?? null;
35
+ }
36
+ /**
37
+ * Which values a lookup's answer sets. A field the shopper owns (a value they typed or the address
38
+ * saved) is never changed, and neither is a select whose dependent the shopper owns, so a typed city
39
+ * is never left outside its state's list. A field an earlier lookup filled and this answer does not
40
+ * cover is cleared, so no value of the old code outlives it. A value with no match in a select, or
41
+ * too long for a text field, leaves that field as it was.
42
+ */
43
+ function fillFromLookup({ rules, draft, found, filledByLookup }) {
44
+ const owned = (name) => (draft[name] ?? "").trim() !== "" && !filledByLookup.has(name);
45
+ const working = { ...draft };
46
+ const filled = {};
47
+ for (const name of FILLABLE_FIELDS) {
48
+ if (owned(name)) continue;
49
+ const plan = planFill({
50
+ name,
51
+ platformValue: found[name]?.trim() ?? "",
52
+ rules,
53
+ working,
54
+ owned
55
+ });
56
+ if (!plan || plan.next === (working[name] ?? "")) continue;
57
+ working[name] = plan.next;
58
+ filled[name] = plan.next;
59
+ for (const dependent of plan.dependents) {
60
+ working[dependent] = "";
61
+ filled[dependent] = "";
62
+ }
63
+ }
64
+ return filled;
65
+ }
66
+ /** The value one field takes (empty when the answer does not cover it) and the dependents it clears, or null when the field must stay as it is. */
67
+ function planFill({ name, platformValue, rules, working, owned }) {
68
+ const descriptors = addressFields(rules, working);
69
+ const descriptor = descriptors.find((candidate) => candidate.name === name);
70
+ if (!descriptor) return null;
71
+ const dependents = dependentsOf(name, descriptors);
72
+ if ([...dependents].some(owned)) return null;
73
+ const next = platformValue === "" ? "" : fitValue(descriptor, platformValue);
74
+ return next === null ? null : {
75
+ next,
76
+ dependents
77
+ };
78
+ }
79
+ function fitValue(descriptor, platformValue) {
80
+ return descriptor.control === "select" ? matchOption(descriptor, platformValue) : fitText(descriptor, platformValue);
81
+ }
82
+ function fitText(descriptor, platformValue) {
83
+ return platformValue.length <= descriptor.maxLength ? platformValue : null;
84
+ }
85
+ /**
86
+ * Runs the lookup for the form: a debounced call once the shopper completes a postal code the
87
+ * country's rules accept, and a fill of the fields the shopper does not own. `postalCodeChanged`
88
+ * and `fieldChanged` are for the shopper's own changes; the fill goes back through `onFill`.
89
+ */
90
+ function usePostalCodeAutofill({ country, rules, draft, onFill }) {
91
+ const lookup = useAddressByPostalCode();
92
+ const latest = useRef({
93
+ country,
94
+ rules,
95
+ draft,
96
+ onFill,
97
+ lookup
98
+ });
99
+ useLayoutEffect(() => {
100
+ latest.current = {
101
+ country,
102
+ rules,
103
+ draft,
104
+ onFill,
105
+ lookup
106
+ };
107
+ });
108
+ const timer = useRef(null);
109
+ const last = useRef(null);
110
+ const filledByLookup = useRef(/* @__PURE__ */ new Set());
111
+ const mounted = useRef(true);
112
+ const cancel = useCallback(() => {
113
+ if (timer.current !== null) {
114
+ clearTimeout(timer.current);
115
+ timer.current = null;
116
+ }
117
+ }, []);
118
+ useEffect(() => {
119
+ mounted.current = true;
120
+ return () => {
121
+ mounted.current = false;
122
+ cancel();
123
+ };
124
+ }, [cancel]);
125
+ useEffect(() => {
126
+ cancel();
127
+ last.current = null;
128
+ filledByLookup.current.clear();
129
+ }, [country, cancel]);
130
+ const isAskable = useCallback((postalCode) => {
131
+ const { country: current, rules: currentRules, draft: currentDraft } = latest.current;
132
+ if (!currentRules || !hasPostalCodeLookup(current) || postalCode.trim() === "") return false;
133
+ return !validateAddress({
134
+ ...currentDraft,
135
+ postalCode
136
+ }, currentRules).postalCode;
137
+ }, []);
138
+ const run = useCallback(async () => {
139
+ timer.current = null;
140
+ const { country: asked, draft: askedDraft } = latest.current;
141
+ const postalCode = (askedDraft.postalCode ?? "").trim();
142
+ if (!isAskable(postalCode)) return;
143
+ const key = `${asked}:${postalCode}`;
144
+ const previous = last.current;
145
+ if (previous?.key === key && previous.status !== "failed") return;
146
+ last.current = {
147
+ key,
148
+ status: "inflight"
149
+ };
150
+ const result = await latest.current.lookup({
151
+ country: asked,
152
+ postalCode
153
+ });
154
+ const { country: now, rules: nowRules, draft: nowDraft, onFill: fill } = latest.current;
155
+ const stale = !mounted.current || now !== asked || (nowDraft.postalCode ?? "").trim() !== postalCode;
156
+ if (last.current?.key === key) last.current = stale ? null : {
157
+ key,
158
+ status: result.status
159
+ };
160
+ if (stale || result.status !== "found" || !nowRules) return;
161
+ const filled = fillFromLookup({
162
+ rules: nowRules,
163
+ draft: nowDraft,
164
+ found: result.address,
165
+ filledByLookup: filledByLookup.current
166
+ });
167
+ for (const [name, value] of Object.entries(filled)) if (value === "") filledByLookup.current.delete(name);
168
+ else filledByLookup.current.add(name);
169
+ if (Object.keys(filled).length > 0) fill(filled);
170
+ }, [isAskable]);
171
+ return {
172
+ postalCodeChanged: useCallback((postalCode) => {
173
+ cancel();
174
+ if (!isAskable(postalCode)) return;
175
+ timer.current = setTimeout(() => void run(), 400);
176
+ }, [
177
+ cancel,
178
+ isAskable,
179
+ run
180
+ ]),
181
+ fieldChanged: useCallback((name) => {
182
+ filledByLookup.current.delete(name);
183
+ }, [])
184
+ };
185
+ }
186
+ //#endregion
187
+ export { dependentsOf, fillFromLookup, usePostalCodeAutofill };
188
+
189
+ //# sourceMappingURL=account-address-postal-autofill.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"account-address-postal-autofill.js","names":[],"sources":["../../../src/matter/account-address-book/account-address-postal-autofill.ts"],"sourcesContent":["'use client';\n\nimport { useCallback, useEffect, useLayoutEffect, useRef } from 'react';\nimport { addressFields } from '../../sdk/address/address-fields.js';\nimport { hasPostalCodeLookup } from '../../sdk/address/postal-code.js';\nimport type { AddressFieldDescriptor, AddressFieldName, CountryRules } from '../../sdk/address/types.js';\nimport { type PostalCodeLookupFields, useAddressByPostalCode } from '../../sdk/address/use-address-by-postal-code.js';\nimport { validateAddress } from '../../sdk/address/validate-address.js';\n\n/**\n * The postal-code autofill of the address form:\n * when it asks, what it fills, and which answers it drops. `AccountAddressFormRoot` owns the draft;\n * this module only decides.\n */\n\ntype EditableField = Exclude<AddressFieldName, 'name'>;\n\ntype Draft = Readonly<Partial<Record<EditableField, string>>>;\n\n/** The values a lookup sets. An empty string is a dependent the fill cleared. */\nexport type FilledFields = Readonly<Partial<Record<EditableField, string>>>;\n\n/** The wait after the last change to a complete code, so typing never asks per keystroke. */\nexport const POSTAL_CODE_LOOKUP_DEBOUNCE_MS = 400;\n\n/** The fields the lookup can fill, in the order it fills them: a state comes before its cities. */\nconst FILLABLE_FIELDS = ['state', 'city', 'neighborhood', 'street'] as const satisfies readonly EditableField[];\n\nfunction fold(value: string): string {\n return value\n .normalize('NFD')\n .replaceAll(/\\p{Diacritic}/gu, '')\n .toLowerCase()\n .trim();\n}\n\n/** Every field below a changed one that reads its options from it, directly or through another field. */\nexport function dependentsOf(\n name: AddressFieldName,\n descriptors: readonly AddressFieldDescriptor[],\n): ReadonlySet<EditableField> {\n const found = new Set<EditableField>();\n const queue: AddressFieldName[] = [name];\n for (const current of queue) {\n for (const descriptor of descriptors) {\n if (descriptor.dependsOn === current && !found.has(descriptor.name)) {\n found.add(descriptor.name);\n queue.push(descriptor.name);\n }\n }\n }\n return found;\n}\n\n/** The option a platform value names: by value, ignoring case, else by label, ignoring case and accents. */\nfunction matchOption(descriptor: AddressFieldDescriptor, platformValue: string): string | null {\n const options = descriptor.options ?? [];\n const lower = platformValue.toLowerCase();\n const byValue = options.find(({ value }) => value.toLowerCase() === lower);\n if (byValue) return byValue.value;\n const folded = fold(platformValue);\n return options.find(({ label }) => fold(label) === folded)?.value ?? null;\n}\n\ntype FillInput = Readonly<{\n rules: CountryRules;\n draft: Draft;\n found: PostalCodeLookupFields;\n /** The fields an earlier lookup filled and the shopper has not changed since. */\n filledByLookup: ReadonlySet<EditableField>;\n}>;\n\n/**\n * Which values a lookup's answer sets. A field the shopper owns (a value they typed or the address\n * saved) is never changed, and neither is a select whose dependent the shopper owns, so a typed city\n * is never left outside its state's list. A field an earlier lookup filled and this answer does not\n * cover is cleared, so no value of the old code outlives it. A value with no match in a select, or\n * too long for a text field, leaves that field as it was.\n */\nexport function fillFromLookup({ rules, draft, found, filledByLookup }: FillInput): FilledFields {\n const owned = (name: EditableField) => (draft[name] ?? '').trim() !== '' && !filledByLookup.has(name);\n const working: Partial<Record<EditableField, string>> = { ...draft };\n const filled: Partial<Record<EditableField, string>> = {};\n\n for (const name of FILLABLE_FIELDS) {\n if (owned(name)) continue;\n const platformValue = found[name]?.trim() ?? '';\n\n const plan = planFill({ name, platformValue, rules, working, owned });\n if (!plan || plan.next === (working[name] ?? '')) continue;\n\n working[name] = plan.next;\n filled[name] = plan.next;\n for (const dependent of plan.dependents) {\n working[dependent] = '';\n filled[dependent] = '';\n }\n }\n\n return filled;\n}\n\ntype PlanInput = Readonly<{\n name: EditableField;\n platformValue: string;\n rules: CountryRules;\n working: Draft;\n owned: (name: EditableField) => boolean;\n}>;\n\n/** The value one field takes (empty when the answer does not cover it) and the dependents it clears, or null when the field must stay as it is. */\nfunction planFill({\n name,\n platformValue,\n rules,\n working,\n owned,\n}: PlanInput): { next: string; dependents: ReadonlySet<EditableField> } | null {\n const descriptors = addressFields(rules, working);\n const descriptor = descriptors.find((candidate) => candidate.name === name);\n if (!descriptor) return null;\n\n const dependents = dependentsOf(name, descriptors);\n if ([...dependents].some(owned)) return null;\n\n const next = platformValue === '' ? '' : fitValue(descriptor, platformValue);\n return next === null ? null : { next, dependents };\n}\n\nfunction fitValue(descriptor: AddressFieldDescriptor, platformValue: string): string | null {\n return descriptor.control === 'select' ? matchOption(descriptor, platformValue) : fitText(descriptor, platformValue);\n}\n\nfunction fitText(descriptor: AddressFieldDescriptor, platformValue: string): string | null {\n return platformValue.length <= descriptor.maxLength ? platformValue : null;\n}\n\ntype AutofillInput = Readonly<{\n country: string;\n rules: CountryRules | null;\n draft: Draft;\n onFill: (filled: FilledFields) => void;\n}>;\n\ntype Lookup = Readonly<{ key: string; status: 'inflight' | 'found' | 'notFound' | 'failed' }>;\n\n/**\n * Runs the lookup for the form: a debounced call once the shopper completes a postal code the\n * country's rules accept, and a fill of the fields the shopper does not own. `postalCodeChanged`\n * and `fieldChanged` are for the shopper's own changes; the fill goes back through `onFill`.\n */\nexport function usePostalCodeAutofill({ country, rules, draft, onFill }: AutofillInput) {\n const lookup = useAddressByPostalCode();\n\n // The debounced run and a late reply must read the form as it is when they fire, not as it was\n // when they were scheduled.\n const latest = useRef({ country, rules, draft, onFill, lookup });\n useLayoutEffect(() => {\n latest.current = { country, rules, draft, onFill, lookup };\n });\n\n const timer = useRef<ReturnType<typeof setTimeout> | null>(null);\n const last = useRef<Lookup | null>(null);\n const filledByLookup = useRef(new Set<EditableField>());\n const mounted = useRef(true);\n\n const cancel = useCallback(() => {\n if (timer.current !== null) {\n clearTimeout(timer.current);\n timer.current = null;\n }\n }, []);\n\n useEffect(() => {\n mounted.current = true;\n return () => {\n mounted.current = false;\n cancel();\n };\n }, [cancel]);\n\n // A new country starts over: the values carried across are the shopper's now.\n // biome-ignore lint/correctness/useExhaustiveDependencies: `country` is the trigger; the body reads no state.\n useEffect(() => {\n cancel();\n last.current = null;\n filledByLookup.current.clear();\n }, [country, cancel]);\n\n const isAskable = useCallback((postalCode: string): boolean => {\n const { country: current, rules: currentRules, draft: currentDraft } = latest.current;\n if (!currentRules || !hasPostalCodeLookup(current) || postalCode.trim() === '') return false;\n return !validateAddress({ ...currentDraft, postalCode }, currentRules).postalCode;\n }, []);\n\n const run = useCallback(async () => {\n timer.current = null;\n const { country: asked, draft: askedDraft } = latest.current;\n const postalCode = (askedDraft.postalCode ?? '').trim();\n if (!isAskable(postalCode)) return;\n\n const key = `${asked}:${postalCode}`;\n const previous = last.current;\n if (previous?.key === key && previous.status !== 'failed') return;\n last.current = { key, status: 'inflight' };\n\n const result = await latest.current.lookup({ country: asked, postalCode });\n const { country: now, rules: nowRules, draft: nowDraft, onFill: fill } = latest.current;\n const stale = !mounted.current || now !== asked || (nowDraft.postalCode ?? '').trim() !== postalCode;\n if (last.current?.key === key) last.current = stale ? null : { key, status: result.status };\n if (stale || result.status !== 'found' || !nowRules) return;\n\n const filled = fillFromLookup({\n rules: nowRules,\n draft: nowDraft,\n found: result.address,\n filledByLookup: filledByLookup.current,\n });\n for (const [name, value] of Object.entries(filled) as [EditableField, string][]) {\n if (value === '') filledByLookup.current.delete(name);\n else filledByLookup.current.add(name);\n }\n if (Object.keys(filled).length > 0) fill(filled);\n }, [isAskable]);\n\n /** The shopper changed the postal code to `postalCode`. */\n const postalCodeChanged = useCallback(\n (postalCode: string) => {\n cancel();\n if (!isAskable(postalCode)) return;\n timer.current = setTimeout(() => void run(), POSTAL_CODE_LOOKUP_DEBOUNCE_MS);\n },\n [cancel, isAskable, run],\n );\n\n /** The shopper changed another field, which is theirs from now on. */\n const fieldChanged = useCallback((name: EditableField) => {\n filledByLookup.current.delete(name);\n }, []);\n\n return { postalCodeChanged, fieldChanged };\n}\n"],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import { ComponentDefinition } from "../../core/dist/define-component.js";
2
+ import "../../core/dist/index.js";
3
+ import { AccountAddressBookItemSlice } from "./account-address-book.js";
4
+ import { ComponentPropsWithRef } from "react";
5
+ //#region src/matter/account-address-book/account-address-record.d.ts
6
+ export type AccountAddressRecordProps = ComponentPropsWithRef<'div'> & {
7
+ $data?: AccountAddressBookItemSlice | null;
8
+ };
9
+ export type AccountAddressRecordErrorProps = ComponentPropsWithRef<'div'> & {
10
+ /** Shown when the address could not be read. A blank value falls back to the catalog copy. */
11
+ message?: string;
12
+ /** The retry control's text. A blank value falls back to the catalog copy. */
13
+ retryLabel?: string;
14
+ };
15
+ export type AccountAddressRecordContextValue = Readonly<{
16
+ /** The address the route names; `null` until it resolved or when the read failed. */
17
+ address: AccountAddressBookItemSlice | null;
18
+ /** The read failed and no address resolved. */
19
+ failed: boolean;
20
+ }>;
21
+ export declare function AccountAddressRecord({ $data: $dataProp, className, children, ...props }: AccountAddressRecordProps): import("react/jsx-runtime").JSX.Element | null;
22
+ export declare function AccountAddressRecordError({ message, retryLabel, className, ...props }: AccountAddressRecordErrorProps): import("react/jsx-runtime").JSX.Element | null;
23
+ export declare const AccountAddressRecordDefinition: ComponentDefinition<AccountAddressRecordProps>;
24
+ export declare const AccountAddressRecordErrorDefinition: ComponentDefinition<AccountAddressRecordErrorProps>;
25
+ //#endregion
26
+ //# sourceMappingURL=account-address-record.d.ts.map
@@ -0,0 +1,138 @@
1
+ "use client";
2
+ import { defineComponent } from "../../core/dist/define-component.js";
3
+ import "../../core/dist/index.js";
4
+ import { useIntl } from "../../sdk/i18n/client.js";
5
+ import { useDataOverride } from "../../sdk/data/data-override-context.js";
6
+ import { resolveAuthoredCopy } from "../../utils/resolve-authored-copy.js";
7
+ import { useSession } from "../session/session.js";
8
+ import { Button } from "../../particles/button/button.js";
9
+ import { ReactiveRootContext } from "../../sdk/data/page-reactive-data-root.js";
10
+ import { AccountAddressBookSkeleton } from "./account-address-book.js";
11
+ import { createContext, useContext, useMemo } from "react";
12
+ import { jsx, jsxs } from "react/jsx-runtime";
13
+ //#region src/matter/account-address-book/account-address-record.tsx
14
+ /**
15
+ * The one address an own page names (specs/sfs-3438-address-form-own-pages.md, RFC REQ-03). It reads
16
+ * `customerAddress(id: $id)` through the page's reactive query and hands the result to the form
17
+ * beneath it, which opens in edit mode seeded with it.
18
+ *
19
+ * It has no not-found state: a route-identified `null` already 404s on the server, through the
20
+ * layout's not-found page, so a foreign id and a missing id are the same response by construction.
21
+ */
22
+ const fragment = `
23
+ fragment AccountAddressRecordData on Query {
24
+ customerAddress(id: $id) {
25
+ __typename
26
+ id
27
+ country
28
+ recipientName
29
+ street
30
+ number
31
+ complement
32
+ neighborhood
33
+ city
34
+ state
35
+ postalCode
36
+ reference
37
+ }
38
+ }
39
+ `;
40
+ const AccountAddressRecordContext = createContext(null);
41
+ /**
42
+ * The record above the caller, or `null` when there is none. A record whose `address` is `null` is
43
+ * still a record: the form must not read that as "add".
44
+ */
45
+ function useOptionalAccountAddressRecord() {
46
+ return useContext(AccountAddressRecordContext);
47
+ }
48
+ function useAccountAddressRecord() {
49
+ const value = useContext(AccountAddressRecordContext);
50
+ if (!value) throw new Error("Address record parts must be used inside an AccountAddressRecord.");
51
+ return value;
52
+ }
53
+ function AccountAddressRecord({ $data: $dataProp, className, children, ...props }) {
54
+ const address = useDataOverride($dataProp) ?? null;
55
+ const { error } = useContext(ReactiveRootContext);
56
+ const { state: sessionState } = useSession();
57
+ const failed = address === null && Boolean(error);
58
+ const value = useMemo(() => ({
59
+ address,
60
+ failed
61
+ }), [address, failed]);
62
+ if (sessionState !== "loggedIn") return null;
63
+ return /* @__PURE__ */ jsx(AccountAddressRecordContext, {
64
+ value,
65
+ children: /* @__PURE__ */ jsx("div", {
66
+ ...props,
67
+ className,
68
+ "data-fs-account-address-record": "",
69
+ ...failed ? { "data-fs-account-address-record-state": "error" } : {},
70
+ children
71
+ })
72
+ });
73
+ }
74
+ /** Reloads the page: the read changes nothing, so it is safe, and the page re-runs its query. */
75
+ function reloadPage() {
76
+ globalThis.location.reload();
77
+ }
78
+ function AccountAddressRecordError({ message, retryLabel, className, ...props }) {
79
+ const { failed } = useAccountAddressRecord();
80
+ const intl = useIntl();
81
+ if (!failed) return null;
82
+ return /* @__PURE__ */ jsxs("div", {
83
+ ...props,
84
+ role: "alert",
85
+ className,
86
+ "data-fs-account-address-record-error": "",
87
+ children: [/* @__PURE__ */ jsx("p", {
88
+ "data-fs-account-address-record-error-message": "",
89
+ children: resolveAuthoredCopy(message, intl.formatMessage({ id: "fs/address-record.error" }))
90
+ }), /* @__PURE__ */ jsx(Button, {
91
+ type: "button",
92
+ onClick: reloadPage,
93
+ "data-fs-account-address-record-retry": "",
94
+ children: resolveAuthoredCopy(retryLabel, intl.formatMessage({ id: "fs/address-book.retry" }))
95
+ })]
96
+ });
97
+ }
98
+ const AccountAddressRecordDefinition = defineComponent({
99
+ name: "AccountAddressRecord",
100
+ importPath: "@vtex/faststore/components",
101
+ component: AccountAddressRecord,
102
+ fragment,
103
+ fetchStrategy: "reactive",
104
+ requiresContext: "session",
105
+ providesContext: "account-address-record",
106
+ skeleton: AccountAddressBookSkeleton,
107
+ editor: {
108
+ label: "Account Address Record",
109
+ category: "identity"
110
+ },
111
+ schema: {},
112
+ guideline: "The one saved address the page's route names, read by the route's [id] segment: place it on a page whose route ends in [id], around an AccountAddressFormRoot, which then opens in edit mode seeded with it. Renders nothing unless the session is logged in, so it needs a SessionRoot ancestor. An id that is not the shopper's, or that never existed, answers with the layout's not-found page and never reaches this component. Add AccountAddressRecordError to show a read that failed. While no address has resolved, the form beneath renders nothing, so it never falls back to adding. See account-address-book.md."
113
+ });
114
+ const AccountAddressRecordErrorDefinition = defineComponent({
115
+ name: "AccountAddressRecordError",
116
+ importPath: "@vtex/faststore/components",
117
+ component: AccountAddressRecordError,
118
+ requiresContext: "account-address-record",
119
+ editor: {
120
+ label: "Account Address Record Error",
121
+ category: "content"
122
+ },
123
+ schema: {
124
+ message: {
125
+ type: "string",
126
+ label: "Error message"
127
+ },
128
+ retryLabel: {
129
+ type: "string",
130
+ label: "Retry label"
131
+ }
132
+ },
133
+ guideline: "Shown only when the address could not be read and none resolved: a message and a retry that reloads the page. Never shown for an id that does not exist, which is a not-found page. Must be inside AccountAddressRecord."
134
+ });
135
+ //#endregion
136
+ export { AccountAddressRecord, AccountAddressRecordDefinition, AccountAddressRecordError, AccountAddressRecordErrorDefinition, useOptionalAccountAddressRecord };
137
+
138
+ //# sourceMappingURL=account-address-record.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"account-address-record.js","names":[],"sources":["../../../src/matter/account-address-book/account-address-record.tsx"],"sourcesContent":["'use client';\n\nimport { defineComponent } from '@vtex/fs-core';\nimport { type ComponentPropsWithRef, createContext, useContext, useMemo } from 'react';\nimport { Button } from '../../particles/button/button.js';\nimport { useDataOverride } from '../../sdk/data/data-override-context.js';\nimport { ReactiveRootContext } from '../../sdk/data/page-reactive-data-root.js';\nimport { useIntl } from '../../sdk/i18n/client.js';\nimport { resolveAuthoredCopy } from '../../utils/resolve-authored-copy.js';\nimport { useSession } from '../session/session.js';\nimport { type AccountAddressBookItemSlice, AccountAddressBookSkeleton } from './account-address-book.js';\n\n/**\n * The one address an own page names (specs/sfs-3438-address-form-own-pages.md, RFC REQ-03). It reads\n * `customerAddress(id: $id)` through the page's reactive query and hands the result to the form\n * beneath it, which opens in edit mode seeded with it.\n *\n * It has no not-found state: a route-identified `null` already 404s on the server, through the\n * layout's not-found page, so a foreign id and a missing id are the same response by construction.\n */\n\n// ---------------------------------------------------------------------------\n// GraphQL fragment — a raw template literal, as the book's fragments are.\n// ---------------------------------------------------------------------------\n\nconst fragment = /* GraphQL */ `\n fragment AccountAddressRecordData on Query {\n customerAddress(id: $id) {\n __typename\n id\n country\n recipientName\n street\n number\n complement\n neighborhood\n city\n state\n postalCode\n reference\n }\n }\n`;\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport type AccountAddressRecordProps = ComponentPropsWithRef<'div'> & {\n $data?: AccountAddressBookItemSlice | null;\n};\n\nexport type AccountAddressRecordErrorProps = ComponentPropsWithRef<'div'> & {\n /** Shown when the address could not be read. A blank value falls back to the catalog copy. */\n message?: string;\n /** The retry control's text. A blank value falls back to the catalog copy. */\n retryLabel?: string;\n};\n\nexport type AccountAddressRecordContextValue = Readonly<{\n /** The address the route names; `null` until it resolved or when the read failed. */\n address: AccountAddressBookItemSlice | null;\n /** The read failed and no address resolved. */\n failed: boolean;\n}>;\n\n// ---------------------------------------------------------------------------\n// Context\n// ---------------------------------------------------------------------------\n\nconst AccountAddressRecordContext = createContext<AccountAddressRecordContextValue | null>(null);\n\n/**\n * The record above the caller, or `null` when there is none. A record whose `address` is `null` is\n * still a record: the form must not read that as \"add\".\n */\nexport function useOptionalAccountAddressRecord(): AccountAddressRecordContextValue | null {\n return useContext(AccountAddressRecordContext);\n}\n\nfunction useAccountAddressRecord(): AccountAddressRecordContextValue {\n const value = useContext(AccountAddressRecordContext);\n if (!value) {\n throw new Error('Address record parts must be used inside an AccountAddressRecord.');\n }\n return value;\n}\n\n// ---------------------------------------------------------------------------\n// Implementations\n// ---------------------------------------------------------------------------\n\nexport function AccountAddressRecord({ $data: $dataProp, className, children, ...props }: AccountAddressRecordProps) {\n const address = useDataOverride<AccountAddressBookItemSlice | null | undefined>($dataProp) ?? null;\n const { error } = useContext(ReactiveRootContext);\n const { state: sessionState } = useSession();\n const failed = address === null && Boolean(error);\n\n const value = useMemo(() => ({ address, failed }), [address, failed]);\n\n if (sessionState !== 'loggedIn') return null;\n\n return (\n <AccountAddressRecordContext value={value}>\n <div\n {...props}\n className={className}\n data-fs-account-address-record=\"\"\n {...(failed ? { 'data-fs-account-address-record-state': 'error' } : {})}\n >\n {children}\n </div>\n </AccountAddressRecordContext>\n );\n}\n\n/** Reloads the page: the read changes nothing, so it is safe, and the page re-runs its query. */\nfunction reloadPage() {\n globalThis.location.reload();\n}\n\nexport function AccountAddressRecordError({\n message,\n retryLabel,\n className,\n ...props\n}: AccountAddressRecordErrorProps) {\n const { failed } = useAccountAddressRecord();\n const intl = useIntl();\n\n if (!failed) return null;\n\n return (\n <div {...props} role=\"alert\" className={className} data-fs-account-address-record-error=\"\">\n <p data-fs-account-address-record-error-message=\"\">\n {resolveAuthoredCopy(message, intl.formatMessage({ id: 'fs/address-record.error' }))}\n </p>\n <Button type=\"button\" onClick={reloadPage} data-fs-account-address-record-retry=\"\">\n {resolveAuthoredCopy(retryLabel, intl.formatMessage({ id: 'fs/address-book.retry' }))}\n </Button>\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Definitions\n// ---------------------------------------------------------------------------\n\nexport const AccountAddressRecordDefinition = defineComponent<AccountAddressRecordProps>({\n name: 'AccountAddressRecord',\n importPath: '@vtex/faststore/components',\n component: AccountAddressRecord,\n fragment,\n fetchStrategy: 'reactive',\n requiresContext: 'session',\n providesContext: 'account-address-record',\n skeleton: AccountAddressBookSkeleton,\n editor: { label: 'Account Address Record', category: 'identity' },\n schema: {},\n guideline:\n \"The one saved address the page's route names, read by the route's [id] segment: place it on a page whose route ends in [id], around an AccountAddressFormRoot, which then opens in edit mode seeded with it. Renders nothing unless the session is logged in, so it needs a SessionRoot ancestor. An id that is not the shopper's, or that never existed, answers with the layout's not-found page and never reaches this component. Add AccountAddressRecordError to show a read that failed. While no address has resolved, the form beneath renders nothing, so it never falls back to adding. See account-address-book.md.\",\n});\n\nexport const AccountAddressRecordErrorDefinition = defineComponent<AccountAddressRecordErrorProps>({\n name: 'AccountAddressRecordError',\n importPath: '@vtex/faststore/components',\n component: AccountAddressRecordError,\n requiresContext: 'account-address-record',\n editor: { label: 'Account Address Record Error', category: 'content' },\n schema: {\n message: { type: 'string', label: 'Error message' },\n retryLabel: { type: 'string', label: 'Retry label' },\n },\n guideline:\n 'Shown only when the address could not be read and none resolved: a message and a retry that reloads the page. Never shown for an id that does not exist, which is a not-found page. Must be inside AccountAddressRecord.',\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAyBA,MAAM,WAAyB;;;;;;;;;;;;;;;;;;AA6C/B,MAAM,8BAA8B,cAAuD,IAAI;;;;;AAM/F,SAAgB,kCAA2E;CACzF,OAAO,WAAW,2BAA2B;AAC/C;AAEA,SAAS,0BAA4D;CACnE,MAAM,QAAQ,WAAW,2BAA2B;CACpD,IAAI,CAAC,OACH,MAAM,IAAI,MAAM,mEAAmE;CAErF,OAAO;AACT;AAMA,SAAgB,qBAAqB,EAAE,OAAO,WAAW,WAAW,UAAU,GAAG,SAAoC;CACnH,MAAM,UAAU,gBAAgE,SAAS,KAAK;CAC9F,MAAM,EAAE,UAAU,WAAW,mBAAmB;CAChD,MAAM,EAAE,OAAO,iBAAiB,WAAW;CAC3C,MAAM,SAAS,YAAY,QAAQ,QAAQ,KAAK;CAEhD,MAAM,QAAQ,eAAe;EAAE;EAAS;CAAO,IAAI,CAAC,SAAS,MAAM,CAAC;CAEpE,IAAI,iBAAiB,YAAY,OAAO;CAExC,OACE,oBAAC,6BAAD;EAAoC;EAClC,UAAA,oBAAC,OAAD;GACE,GAAI;GACO;GACX,kCAA+B;GAC/B,GAAK,SAAS,EAAE,wCAAwC,QAAQ,IAAI,CAAC;GAEpE;EACE,CAAA;CACsB,CAAA;AAEjC;;AAGA,SAAS,aAAa;CACpB,WAAW,SAAS,OAAO;AAC7B;AAEA,SAAgB,0BAA0B,EACxC,SACA,YACA,WACA,GAAG,SAC8B;CACjC,MAAM,EAAE,WAAW,wBAAwB;CAC3C,MAAM,OAAO,QAAQ;CAErB,IAAI,CAAC,QAAQ,OAAO;CAEpB,OACE,qBAAC,OAAD;EAAK,GAAI;EAAO,MAAK;EAAmB;EAAW,wCAAqC;EAAxF,UAAA,CACE,oBAAC,KAAD;GAAG,gDAA6C;GAC7C,UAAA,oBAAoB,SAAS,KAAK,cAAc,EAAE,IAAI,0BAA0B,CAAC,CAAC;EAClF,CAAA,GACH,oBAAC,QAAD;GAAQ,MAAK;GAAS,SAAS;GAAY,wCAAqC;GAC7E,UAAA,oBAAoB,YAAY,KAAK,cAAc,EAAE,IAAI,wBAAwB,CAAC,CAAC;EAC9E,CAAA,CACL;;AAET;AAMA,MAAa,iCAAiC,gBAA2C;CACvF,MAAM;CACN,YAAY;CACZ,WAAW;CACX;CACA,eAAe;CACf,iBAAiB;CACjB,iBAAiB;CACjB,UAAU;CACV,QAAQ;EAAE,OAAO;EAA0B,UAAU;CAAW;CAChE,QAAQ,CAAC;CACT,WACE;AACJ,CAAC;AAED,MAAa,sCAAsC,gBAAgD;CACjG,MAAM;CACN,YAAY;CACZ,WAAW;CACX,iBAAiB;CACjB,QAAQ;EAAE,OAAO;EAAgC,UAAU;CAAU;CACrE,QAAQ;EACN,SAAS;GAAE,MAAM;GAAU,OAAO;EAAgB;EAClD,YAAY;GAAE,MAAM;GAAU,OAAO;EAAc;CACrD;CACA,WACE;AACJ,CAAC"}
@@ -2,17 +2,17 @@
2
2
  import { defineComponent } from "../../core/dist/define-component.js";
3
3
  import { defineContentType } from "../../core/dist/define-content-type.js";
4
4
  import "../../core/dist/index.js";
5
+ import { signInTarget } from "../../utils/safe-href.js";
6
+ import { useStorefrontRoute } from "../../sdk/navigation/use-storefront-route.js";
5
7
  import { useSession } from "../session/session.js";
6
- import { resolveSignInHref } from "../../utils/safe-href.js";
7
8
  import { NavigationLink } from "../../particles/navigation-link/navigation-link.js";
8
9
  import { Icon } from "../../particles/icon/icon.js";
9
10
  import { useEffect, useState } from "react";
10
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
11
- import { usePathname } from "next/navigation";
11
+ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
12
12
  //#region src/matter/account-entry-point/account-entry-point.tsx
13
- /** The account's root. A fixed convention, never an authored value: an authored destination could
14
- * misroute the entry into the account. */
15
- const ACCOUNT_ROUTE = "/pvt/account";
13
+ /** The account's root page. Never an authored value: an authored destination could misroute the entry
14
+ * into the account. */
15
+ const ACCOUNT_ROUTE = { standard: "account" };
16
16
  const AccountEntryPointContent = defineContentType({
17
17
  id: "account-entry-point",
18
18
  title: "Account Entry Point",
@@ -72,11 +72,11 @@ const AccountEntryPointDefinition = defineComponent({
72
72
  label: "Loading Announcement"
73
73
  }
74
74
  },
75
- guideline: "Session-aware header control rendering one link: the signed-out label toward /login for anonymous and identified shoppers, the signed-in label toward the account route for logged-in ones, and a politely announced placeholder while the session resolves. Both destinations are fixed conventions, not props, so no authored value can misroute the auth flow. Must be inside a SessionRoot, normally the one hosted by the shared layout; a page-hosted provider also works, since the server-side session fetch forwards the shopper cookie. Author the label for a state or that state renders nothing; the labels are optional in the type only because a CMS entry may supply them, and an entry overrides all four fields at runtime. Style it through data-fs-account-entry-point and switch on data-fs-account-entry-point-state."
75
+ guideline: "Session-aware header control rendering one link: the signed-out label toward the sign-in page for anonymous and identified shoppers, the signed-in label toward the account page for logged-in ones, and a politely announced placeholder while the session resolves. Both destinations are fixed conventions, not props, so no authored value can misroute the auth flow. Must be inside a SessionRoot, normally the one hosted by the shared layout; a page-hosted provider also works, since the server-side session fetch forwards the shopper cookie. Author the label for a state or that state renders nothing; the labels are optional in the type only because a CMS entry may supply them, and an entry overrides all four fields at runtime. Style it through data-fs-account-entry-point and switch on data-fs-account-entry-point-state."
76
76
  });
77
77
  function AccountEntryPoint({ signedOutLabel, signedInLabel, icon, loadingLabel, $content, className, ref, ...props }) {
78
78
  const { state, loading } = useSession();
79
- const pathname = usePathname();
79
+ const { path } = useStorefrontRoute();
80
80
  const entrySignedOutLabel = $content?.signedOutLabel?.trim() ? $content.signedOutLabel : signedOutLabel;
81
81
  const entrySignedInLabel = $content?.signedInLabel?.trim() ? $content.signedInLabel : signedInLabel;
82
82
  const entryIcon = $content?.icon?.trim() ? $content.icon : icon;
@@ -86,17 +86,17 @@ function AccountEntryPoint({ signedOutLabel, signedInLabel, icon, loadingLabel,
86
86
  useEffect(() => {
87
87
  setAnnouncement(resolvingLabel ?? "");
88
88
  }, [resolvingLabel]);
89
- if (loading) return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(AccountEntryPointLoading, {
89
+ if (loading) return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(AccountEntryPointLoading, {
90
90
  ...props,
91
91
  className
92
92
  }), /* @__PURE__ */ jsx(AccountEntryPointAnnouncement, { children: announcement })] });
93
93
  const signedIn = state === "loggedIn";
94
94
  const label = signedIn ? entrySignedInLabel : entrySignedOutLabel;
95
95
  if (!label?.trim()) return null;
96
- return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs(NavigationLink, {
96
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs(NavigationLink, {
97
97
  ...props,
98
98
  ref,
99
- href: signedIn ? ACCOUNT_ROUTE : resolveSignInHref(pathname),
99
+ href: signedIn ? ACCOUNT_ROUTE : signInTarget(path),
100
100
  prefetch: signedIn ? void 0 : false,
101
101
  className,
102
102
  "data-fs-account-entry-point": "",