@vtex/faststore 0.0.10 → 0.0.12

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 (509) hide show
  1. package/CHANGELOG.md +55 -0
  2. package/README.md +0 -1
  3. package/dist/_virtual/_rolldown/runtime.js +4 -0
  4. package/dist/actions.json +6 -1
  5. package/dist/catalog.json +789 -1701
  6. package/dist/cli/index.d.ts +66 -28
  7. package/dist/cli/index.js +7371 -512
  8. package/dist/cli/index.js.map +1 -1
  9. package/dist/cli/server-runtime.js +41 -60
  10. package/dist/cli/server-runtime.js.map +1 -1
  11. package/dist/client.d.ts +3 -3
  12. package/dist/client.js +2 -2
  13. package/dist/components.d.ts +63 -57
  14. package/dist/components.js +60 -54
  15. package/dist/content-types.json +5785 -754
  16. package/dist/core/dist/define-component.d.ts +1 -1
  17. package/dist/core/dist/define-content-type.d.ts +50 -2
  18. package/dist/core/dist/define-content-type.js +107 -3
  19. package/dist/core/dist/define-content-type.js.map +1 -1
  20. package/dist/core/dist/index.d.ts +2 -2
  21. package/dist/docs/access-code-field.md +1 -1
  22. package/dist/docs/access-code-sign-in.md +126 -77
  23. package/dist/docs/account-address-book.md +210 -95
  24. package/dist/docs/account-menu.md +14 -15
  25. package/dist/docs/account-saved-cards.md +44 -39
  26. package/dist/docs/alert-dialog.md +3 -1
  27. package/dist/docs/avatar.md +4 -2
  28. package/dist/docs/billing-address.md +99 -30
  29. package/dist/docs/binding-switcher.md +5 -2
  30. package/dist/docs/buy-button.md +7 -8
  31. package/dist/docs/card-entry.md +39 -26
  32. package/dist/docs/card-summary.md +18 -8
  33. package/dist/docs/cardholder-document.md +5 -3
  34. package/dist/docs/carousel.md +5 -4
  35. package/dist/docs/cart-destination.md +39 -26
  36. package/dist/docs/cart-item.md +29 -14
  37. package/dist/docs/cart-totalizer.md +7 -5
  38. package/dist/docs/cart.md +135 -41
  39. package/dist/docs/challenge-return.md +135 -0
  40. package/dist/docs/client-preferences-fieldset.md +10 -5
  41. package/dist/docs/client-preferences.md +31 -8
  42. package/dist/docs/client-profile-fieldset.md +20 -6
  43. package/dist/docs/client-profile.md +12 -3
  44. package/dist/docs/copy-text.md +9 -7
  45. package/dist/docs/document-field.md +1 -1
  46. package/dist/docs/email-field.md +2 -1
  47. package/dist/docs/email-identification.md +12 -2
  48. package/dist/docs/footer-copyright.md +4 -2
  49. package/dist/docs/form.md +54 -18
  50. package/dist/docs/free-shipping-progress.md +6 -5
  51. package/dist/docs/identity-edit.md +8 -2
  52. package/dist/docs/identity-summary.md +18 -5
  53. package/dist/docs/installments.md +46 -32
  54. package/dist/docs/my-account-profile.md +16 -11
  55. package/dist/docs/navigation-link.md +5 -3
  56. package/dist/docs/order-cancel.md +3 -1
  57. package/dist/docs/order-delivery-address.md +7 -5
  58. package/dist/docs/order-delivery-group.md +1 -3
  59. package/dist/docs/order-details-back.md +1 -1
  60. package/dist/docs/order-details-header.md +1 -4
  61. package/dist/docs/order-invoice-download.md +60 -0
  62. package/dist/docs/order-list-row.md +1 -1
  63. package/dist/docs/order-list-search.md +13 -20
  64. package/dist/docs/order-list-views.md +11 -17
  65. package/dist/docs/order-list.md +12 -5
  66. package/dist/docs/order-payment.md +9 -7
  67. package/dist/docs/order-placed-date.md +1 -1
  68. package/dist/docs/order-placed-payment-summary.md +28 -15
  69. package/dist/docs/order-placed.md +49 -14
  70. package/dist/docs/order-progress.md +1 -1
  71. package/dist/docs/order-status-badge.md +20 -9
  72. package/dist/docs/order-summary.md +2 -2
  73. package/dist/docs/order-tracking-link.md +58 -0
  74. package/dist/docs/payment-method-badges.md +30 -4
  75. package/dist/docs/payment-methods.md +1 -1
  76. package/dist/docs/payment.md +36 -17
  77. package/dist/docs/phone-field.md +4 -4
  78. package/dist/docs/place-order.md +84 -36
  79. package/dist/docs/postal-code-field.md +3 -1
  80. package/dist/docs/pricing.md +21 -23
  81. package/dist/docs/product-gallery.md +19 -20
  82. package/dist/docs/product-information.md +13 -9
  83. package/dist/docs/product-list.md +7 -6
  84. package/dist/docs/product-shelf.md +0 -1
  85. package/dist/docs/promotion.md +4 -2
  86. package/dist/docs/region.md +23 -15
  87. package/dist/docs/save-card.md +7 -6
  88. package/dist/docs/saved-cards.md +65 -36
  89. package/dist/docs/shipping-address.md +57 -21
  90. package/dist/docs/shipping-simulator.md +53 -15
  91. package/dist/docs/sign-in-disclosure.md +176 -0
  92. package/dist/docs/sign-in-form.md +78 -47
  93. package/dist/docs/sign-in-redirect.md +4 -2
  94. package/dist/docs/sign-in.md +173 -0
  95. package/dist/docs/toast.md +15 -4
  96. package/dist/docs/variant-selector.md +15 -11
  97. package/dist/domain-logic/dist/checkout/rules.js +33 -0
  98. package/dist/domain-logic/dist/checkout/rules.js.map +1 -0
  99. package/dist/graphql/types.d.ts +4 -14
  100. package/dist/index.d.ts +2 -2
  101. package/dist/internal/client.d.ts +1 -3
  102. package/dist/internal/client.js +1 -1
  103. package/dist/internal/server.d.ts +7 -4
  104. package/dist/internal/server.js +7 -4
  105. package/dist/matter/access-code-sign-in/access-code-sign-in.d.ts +250 -66
  106. package/dist/matter/access-code-sign-in/access-code-sign-in.js +459 -188
  107. package/dist/matter/access-code-sign-in/access-code-sign-in.js.map +1 -1
  108. package/dist/matter/account-address-book/account-address-book-delete.d.ts +78 -40
  109. package/dist/matter/account-address-book/account-address-book-delete.js +86 -50
  110. package/dist/matter/account-address-book/account-address-book-delete.js.map +1 -1
  111. package/dist/matter/account-address-book/account-address-book-deliverability.d.ts +21 -4
  112. package/dist/matter/account-address-book/account-address-book-deliverability.js +45 -17
  113. package/dist/matter/account-address-book/account-address-book-deliverability.js.map +1 -1
  114. package/dist/matter/account-address-book/account-address-book-form-parts.d.ts +74 -19
  115. package/dist/matter/account-address-book/account-address-book-form-parts.js +77 -26
  116. package/dist/matter/account-address-book/account-address-book-form-parts.js.map +1 -1
  117. package/dist/matter/account-address-book/account-address-book-profile-notice.d.ts +27 -6
  118. package/dist/matter/account-address-book/account-address-book-profile-notice.js +55 -28
  119. package/dist/matter/account-address-book/account-address-book-profile-notice.js.map +1 -1
  120. package/dist/matter/account-address-book/account-address-book.d.ts +67 -14
  121. package/dist/matter/account-address-book/account-address-book.js +74 -33
  122. package/dist/matter/account-address-book/account-address-book.js.map +1 -1
  123. package/dist/matter/account-address-book/account-address-country-switch.js +3 -3
  124. package/dist/matter/account-address-book/account-address-country-switch.js.map +1 -1
  125. package/dist/matter/account-address-book/account-address-country.d.ts +66 -20
  126. package/dist/matter/account-address-book/account-address-country.js +83 -49
  127. package/dist/matter/account-address-book/account-address-country.js.map +1 -1
  128. package/dist/matter/account-address-book/account-address-form-context.d.ts +8 -4
  129. package/dist/matter/account-address-book/account-address-form-context.js.map +1 -1
  130. package/dist/matter/account-address-book/account-address-form.d.ts +468 -45
  131. package/dist/matter/account-address-book/account-address-form.js +518 -155
  132. package/dist/matter/account-address-book/account-address-form.js.map +1 -1
  133. package/dist/matter/account-address-book/account-address-record.d.ts +27 -6
  134. package/dist/matter/account-address-book/account-address-record.js +32 -17
  135. package/dist/matter/account-address-book/account-address-record.js.map +1 -1
  136. package/dist/matter/account-menu/account-menu.d.ts +34 -17
  137. package/dist/matter/account-menu/account-menu.js +46 -54
  138. package/dist/matter/account-menu/account-menu.js.map +1 -1
  139. package/dist/matter/account-menu-identity/account-menu-identity.js +1 -1
  140. package/dist/matter/account-saved-cards/account-saved-cards.d.ts +108 -28
  141. package/dist/matter/account-saved-cards/account-saved-cards.js +177 -122
  142. package/dist/matter/account-saved-cards/account-saved-cards.js.map +1 -1
  143. package/dist/matter/billing-address/billing-address.d.ts +156 -74
  144. package/dist/matter/billing-address/billing-address.js +227 -156
  145. package/dist/matter/billing-address/billing-address.js.map +1 -1
  146. package/dist/matter/breadcrumb/breadcrumb.d.ts +21 -3
  147. package/dist/matter/breadcrumb/breadcrumb.js +24 -9
  148. package/dist/matter/breadcrumb/breadcrumb.js.map +1 -1
  149. package/dist/matter/buy-button/buy-button.d.ts +8 -11
  150. package/dist/matter/buy-button/buy-button.js +10 -19
  151. package/dist/matter/buy-button/buy-button.js.map +1 -1
  152. package/dist/matter/card-entry/card-capture.js +12 -4
  153. package/dist/matter/card-entry/card-capture.js.map +1 -1
  154. package/dist/matter/card-entry/card-entry.d.ts +123 -32
  155. package/dist/matter/card-entry/card-entry.js +348 -221
  156. package/dist/matter/card-entry/card-entry.js.map +1 -1
  157. package/dist/matter/cart/cart-namespace.d.ts +7 -1
  158. package/dist/matter/cart/cart-namespace.js +7 -1
  159. package/dist/matter/cart/cart-namespace.js.map +1 -1
  160. package/dist/matter/cart/cart.d.ts +402 -61
  161. package/dist/matter/cart/cart.js +624 -153
  162. package/dist/matter/cart/cart.js.map +1 -1
  163. package/dist/matter/cart-destination/cart-destination.d.ts +30 -19
  164. package/dist/matter/cart-destination/cart-destination.js +160 -70
  165. package/dist/matter/cart-destination/cart-destination.js.map +1 -1
  166. package/dist/matter/cart-item/cart-item.d.ts +144 -17
  167. package/dist/matter/cart-item/cart-item.js +166 -49
  168. package/dist/matter/cart-item/cart-item.js.map +1 -1
  169. package/dist/matter/cart-item-compositions/cart-item-compositions.js +1 -1
  170. package/dist/matter/cart-item-compositions/cart-item-compositions.js.map +1 -1
  171. package/dist/matter/cart-item-customizations/cart-item-customizations.js +1 -1
  172. package/dist/matter/cart-item-customizations/cart-item-customizations.js.map +1 -1
  173. package/dist/matter/cart-item-discounts/cart-item-discounts.js +1 -1
  174. package/dist/matter/cart-item-discounts/cart-item-discounts.js.map +1 -1
  175. package/dist/matter/cart-item-seller-info/cart-item-seller-info.js +1 -1
  176. package/dist/matter/cart-item-seller-info/cart-item-seller-info.js.map +1 -1
  177. package/dist/matter/cart-item-variations/cart-item-variations.js +1 -1
  178. package/dist/matter/cart-item-variations/cart-item-variations.js.map +1 -1
  179. package/dist/matter/cart-totalizer/cart-totalizer.d.ts +43 -9
  180. package/dist/matter/cart-totalizer/cart-totalizer.js +46 -17
  181. package/dist/matter/cart-totalizer/cart-totalizer.js.map +1 -1
  182. package/dist/matter/challenge-return/challenge-return.d.ts +62 -0
  183. package/dist/matter/challenge-return/challenge-return.js +241 -0
  184. package/dist/matter/challenge-return/challenge-return.js.map +1 -0
  185. package/dist/matter/client-preferences/client-preferences-fieldset.d.ts +86 -17
  186. package/dist/matter/client-preferences/client-preferences-fieldset.js +126 -54
  187. package/dist/matter/client-preferences/client-preferences-fieldset.js.map +1 -1
  188. package/dist/matter/client-preferences/client-preferences.d.ts +50 -7
  189. package/dist/matter/client-preferences/client-preferences.js +84 -15
  190. package/dist/matter/client-preferences/client-preferences.js.map +1 -1
  191. package/dist/matter/client-profile/client-profile.d.ts +44 -9
  192. package/dist/matter/client-profile/client-profile.js +64 -24
  193. package/dist/matter/client-profile/client-profile.js.map +1 -1
  194. package/dist/matter/client-profile-form/client-profile-fieldset.d.ts +119 -22
  195. package/dist/matter/client-profile-form/client-profile-fieldset.js +161 -73
  196. package/dist/matter/client-profile-form/client-profile-fieldset.js.map +1 -1
  197. package/dist/matter/delivery-options/delivery-options-accordion.d.ts +49 -4
  198. package/dist/matter/delivery-options/delivery-options-accordion.js +67 -14
  199. package/dist/matter/delivery-options/delivery-options-accordion.js.map +1 -1
  200. package/dist/matter/delivery-options/delivery-options-controller.d.ts +69 -9
  201. package/dist/matter/delivery-options/delivery-options-controller.js +80 -14
  202. package/dist/matter/delivery-options/delivery-options-controller.js.map +1 -1
  203. package/dist/matter/delivery-options/delivery-options.d.ts +37 -2
  204. package/dist/matter/delivery-options/delivery-options.js +75 -12
  205. package/dist/matter/delivery-options/delivery-options.js.map +1 -1
  206. package/dist/matter/delivery-options/use-delivery-option-selection.d.ts +1 -0
  207. package/dist/matter/delivery-options/use-delivery-option-selection.js +1 -1
  208. package/dist/matter/delivery-options/use-delivery-option-selection.js.map +1 -1
  209. package/dist/matter/email-identification/email-identification.d.ts +25 -3
  210. package/dist/matter/email-identification/email-identification.js +49 -12
  211. package/dist/matter/email-identification/email-identification.js.map +1 -1
  212. package/dist/matter/free-shipping-progress/free-shipping-progress.d.ts +79 -7
  213. package/dist/matter/free-shipping-progress/free-shipping-progress.js +77 -20
  214. package/dist/matter/free-shipping-progress/free-shipping-progress.js.map +1 -1
  215. package/dist/matter/identity-edit/identity-edit.d.ts +52 -10
  216. package/dist/matter/identity-edit/identity-edit.js +47 -19
  217. package/dist/matter/identity-edit/identity-edit.js.map +1 -1
  218. package/dist/matter/identity-summary/identity-summary.d.ts +76 -22
  219. package/dist/matter/identity-summary/identity-summary.js +95 -45
  220. package/dist/matter/identity-summary/identity-summary.js.map +1 -1
  221. package/dist/matter/installments/installments-select.d.ts +98 -16
  222. package/dist/matter/installments/installments-select.js +156 -48
  223. package/dist/matter/installments/installments-select.js.map +1 -1
  224. package/dist/matter/installments/installments.d.ts +96 -16
  225. package/dist/matter/installments/installments.js +115 -40
  226. package/dist/matter/installments/installments.js.map +1 -1
  227. package/dist/matter/installments/use-installments-selection.d.ts +1 -0
  228. package/dist/matter/installments/use-installments-selection.js +8 -3
  229. package/dist/matter/installments/use-installments-selection.js.map +1 -1
  230. package/dist/matter/my-account-profile/my-account-profile.d.ts +358 -103
  231. package/dist/matter/my-account-profile/my-account-profile.js +370 -174
  232. package/dist/matter/my-account-profile/my-account-profile.js.map +1 -1
  233. package/dist/matter/order-cancel/order-cancel.d.ts +65 -19
  234. package/dist/matter/order-cancel/order-cancel.js +118 -51
  235. package/dist/matter/order-cancel/order-cancel.js.map +1 -1
  236. package/dist/matter/order-delivery-address/order-delivery-address.d.ts +8 -18
  237. package/dist/matter/order-delivery-address/order-delivery-address.js +14 -23
  238. package/dist/matter/order-delivery-address/order-delivery-address.js.map +1 -1
  239. package/dist/matter/order-delivery-group/order-delivery-group.d.ts +40 -24
  240. package/dist/matter/order-delivery-group/order-delivery-group.js +64 -74
  241. package/dist/matter/order-delivery-group/order-delivery-group.js.map +1 -1
  242. package/dist/matter/order-details-header/order-details-header.d.ts +32 -15
  243. package/dist/matter/order-details-header/order-details-header.js +66 -58
  244. package/dist/matter/order-details-header/order-details-header.js.map +1 -1
  245. package/dist/matter/order-invoice-download/order-invoice-download.d.ts +78 -0
  246. package/dist/matter/order-invoice-download/order-invoice-download.js +173 -0
  247. package/dist/matter/order-invoice-download/order-invoice-download.js.map +1 -0
  248. package/dist/matter/order-list/order-list.d.ts +164 -19
  249. package/dist/matter/order-list/order-list.js +229 -87
  250. package/dist/matter/order-list/order-list.js.map +1 -1
  251. package/dist/matter/order-list-row/order-list-row.d.ts +6 -1
  252. package/dist/matter/order-list-row/order-list-row.js +3 -2
  253. package/dist/matter/order-list-row/order-list-row.js.map +1 -1
  254. package/dist/matter/order-list-search/order-list-search.d.ts +18 -26
  255. package/dist/matter/order-list-search/order-list-search.js +30 -69
  256. package/dist/matter/order-list-search/order-list-search.js.map +1 -1
  257. package/dist/matter/order-list-views/order-list-views.d.ts +15 -22
  258. package/dist/matter/order-list-views/order-list-views.js +22 -68
  259. package/dist/matter/order-list-views/order-list-views.js.map +1 -1
  260. package/dist/matter/order-payment/order-payment.d.ts +33 -10
  261. package/dist/matter/order-payment/order-payment.js +44 -39
  262. package/dist/matter/order-payment/order-payment.js.map +1 -1
  263. package/dist/matter/order-placed/order-placed-deliveries.d.ts +144 -12
  264. package/dist/matter/order-placed/order-placed-deliveries.js +115 -40
  265. package/dist/matter/order-placed/order-placed-deliveries.js.map +1 -1
  266. package/dist/matter/order-placed/order-placed.d.ts +198 -31
  267. package/dist/matter/order-placed/order-placed.js +230 -139
  268. package/dist/matter/order-placed/order-placed.js.map +1 -1
  269. package/dist/matter/order-placed-date/order-placed-date.d.ts +5 -8
  270. package/dist/matter/order-placed-date/order-placed-date.js +7 -8
  271. package/dist/matter/order-placed-date/order-placed-date.js.map +1 -1
  272. package/dist/matter/order-placed-payment-summary/order-placed-payment-summary.d.ts +90 -17
  273. package/dist/matter/order-placed-payment-summary/order-placed-payment-summary.js +93 -117
  274. package/dist/matter/order-placed-payment-summary/order-placed-payment-summary.js.map +1 -1
  275. package/dist/matter/order-progress/order-progress.d.ts +19 -8
  276. package/dist/matter/order-progress/order-progress.js +37 -45
  277. package/dist/matter/order-progress/order-progress.js.map +1 -1
  278. package/dist/matter/order-summary/order-summary.d.ts +19 -9
  279. package/dist/matter/order-summary/order-summary.js +38 -44
  280. package/dist/matter/order-summary/order-summary.js.map +1 -1
  281. package/dist/matter/order-tracking-link/order-tracking-link.d.ts +43 -0
  282. package/dist/matter/order-tracking-link/order-tracking-link.js +107 -0
  283. package/dist/matter/order-tracking-link/order-tracking-link.js.map +1 -0
  284. package/dist/matter/payment/payment-card-capture.js +17 -10
  285. package/dist/matter/payment/payment-card-capture.js.map +1 -1
  286. package/dist/matter/payment/payment-controller.d.ts +4 -2
  287. package/dist/matter/payment/payment-controller.js +30 -9
  288. package/dist/matter/payment/payment-controller.js.map +1 -1
  289. package/dist/matter/payment/payment-method-badges.js +1 -1
  290. package/dist/matter/payment/payment.d.ts +69 -19
  291. package/dist/matter/payment/payment.js +101 -35
  292. package/dist/matter/payment/payment.js.map +1 -1
  293. package/dist/matter/payment/use-payment-method-selection.d.ts +25 -4
  294. package/dist/matter/payment/use-payment-method-selection.js +94 -32
  295. package/dist/matter/payment/use-payment-method-selection.js.map +1 -1
  296. package/dist/matter/payment/use-payment-submit-gate.d.ts +14 -3
  297. package/dist/matter/payment/use-payment-submit-gate.js +47 -8
  298. package/dist/matter/payment/use-payment-submit-gate.js.map +1 -1
  299. package/dist/matter/place-order/place-order.d.ts +171 -57
  300. package/dist/matter/place-order/place-order.js +376 -185
  301. package/dist/matter/place-order/place-order.js.map +1 -1
  302. package/dist/matter/pricing/pricing.d.ts +152 -13
  303. package/dist/matter/pricing/pricing.js +153 -52
  304. package/dist/matter/pricing/pricing.js.map +1 -1
  305. package/dist/matter/product-information/product-information.d.ts +27 -4
  306. package/dist/matter/product-information/product-information.js +32 -15
  307. package/dist/matter/product-information/product-information.js.map +1 -1
  308. package/dist/matter/product-list/product-list.d.ts +24 -6
  309. package/dist/matter/product-list/product-list.js +32 -26
  310. package/dist/matter/product-list/product-list.js.map +1 -1
  311. package/dist/matter/product-shelf/product-shelf.d.ts +1 -3
  312. package/dist/matter/product-shelf/product-shelf.js +2 -15
  313. package/dist/matter/product-shelf/product-shelf.js.map +1 -1
  314. package/dist/matter/region/region.d.ts +33 -16
  315. package/dist/matter/region/region.js +59 -52
  316. package/dist/matter/region/region.js.map +1 -1
  317. package/dist/matter/save-card/save-card.d.ts +43 -8
  318. package/dist/matter/save-card/save-card.js +61 -23
  319. package/dist/matter/save-card/save-card.js.map +1 -1
  320. package/dist/matter/saved-cards/saved-cards.d.ts +113 -21
  321. package/dist/matter/saved-cards/saved-cards.js +349 -77
  322. package/dist/matter/saved-cards/saved-cards.js.map +1 -1
  323. package/dist/matter/shipping-address/address-payload.js +25 -0
  324. package/dist/matter/shipping-address/address-payload.js.map +1 -0
  325. package/dist/matter/shipping-address/country-descriptors.js +71 -71
  326. package/dist/matter/shipping-address/country-descriptors.js.map +1 -1
  327. package/dist/matter/shipping-address/library-country-descriptors.js +136 -0
  328. package/dist/matter/shipping-address/library-country-descriptors.js.map +1 -0
  329. package/dist/matter/shipping-address/shipping-address.d.ts +312 -45
  330. package/dist/matter/shipping-address/shipping-address.js +443 -188
  331. package/dist/matter/shipping-address/shipping-address.js.map +1 -1
  332. package/dist/matter/shipping-simulator/shipping-simulator.d.ts +250 -24
  333. package/dist/matter/shipping-simulator/shipping-simulator.js +257 -51
  334. package/dist/matter/shipping-simulator/shipping-simulator.js.map +1 -1
  335. package/dist/matter/sign-in/sign-in.d.ts +108 -0
  336. package/dist/matter/sign-in/sign-in.js +285 -0
  337. package/dist/matter/sign-in/sign-in.js.map +1 -0
  338. package/dist/matter/sign-in-disclosure/sign-in-disclosure.d.ts +81 -0
  339. package/dist/matter/sign-in-disclosure/sign-in-disclosure.js +232 -0
  340. package/dist/matter/sign-in-disclosure/sign-in-disclosure.js.map +1 -0
  341. package/dist/matter/sign-in-form/sign-in-form.d.ts +93 -62
  342. package/dist/matter/sign-in-form/sign-in-form.js +134 -144
  343. package/dist/matter/sign-in-form/sign-in-form.js.map +1 -1
  344. package/dist/particles/binding-switcher/binding-switcher.d.ts +29 -8
  345. package/dist/particles/binding-switcher/binding-switcher.js +37 -26
  346. package/dist/particles/binding-switcher/binding-switcher.js.map +1 -1
  347. package/dist/particles/card-summary/card-summary.d.ts +38 -8
  348. package/dist/particles/card-summary/card-summary.js +55 -22
  349. package/dist/particles/card-summary/card-summary.js.map +1 -1
  350. package/dist/particles/carousel/carousel.d.ts +99 -11
  351. package/dist/particles/carousel/carousel.js +103 -35
  352. package/dist/particles/carousel/carousel.js.map +1 -1
  353. package/dist/particles/copy-text/copy-text.js +5 -15
  354. package/dist/particles/copy-text/copy-text.js.map +1 -1
  355. package/dist/particles/dialog/dialog.d.ts +14 -6
  356. package/dist/particles/dialog/dialog.js +6 -3
  357. package/dist/particles/dialog/dialog.js.map +1 -1
  358. package/dist/particles/drawer/drawer.js +1 -1
  359. package/dist/particles/drawer/drawer.js.map +1 -1
  360. package/dist/particles/email-field/email-field.d.ts +2 -1
  361. package/dist/particles/email-field/email-field.js +2 -1
  362. package/dist/particles/email-field/email-field.js.map +1 -1
  363. package/dist/particles/footer-link-group/footer-link-group.js +1 -0
  364. package/dist/particles/footer-link-group/footer-link-group.js.map +1 -1
  365. package/dist/particles/form/form.d.ts +85 -13
  366. package/dist/particles/form/form.js +91 -42
  367. package/dist/particles/form/form.js.map +1 -1
  368. package/dist/particles/gallery/gallery.d.ts +129 -12
  369. package/dist/particles/gallery/gallery.js +121 -34
  370. package/dist/particles/gallery/gallery.js.map +1 -1
  371. package/dist/particles/order-details-back/order-details-back.d.ts +5 -3
  372. package/dist/particles/order-details-back/order-details-back.js +8 -10
  373. package/dist/particles/order-details-back/order-details-back.js.map +1 -1
  374. package/dist/particles/order-status-badge/order-status-badge.d.ts +3 -3
  375. package/dist/particles/order-status-badge/order-status-badge.js +4 -20
  376. package/dist/particles/order-status-badge/order-status-badge.js.map +1 -1
  377. package/dist/particles/password-field/password-field.d.ts +1 -1
  378. package/dist/particles/password-field/password-field.js +2 -4
  379. package/dist/particles/password-field/password-field.js.map +1 -1
  380. package/dist/particles/phone-field/phone-field.d.ts +4 -4
  381. package/dist/particles/phone-field/phone-field.js +8 -11
  382. package/dist/particles/phone-field/phone-field.js.map +1 -1
  383. package/dist/particles/spinner/spinner.d.ts +24 -4
  384. package/dist/particles/spinner/spinner.js +25 -9
  385. package/dist/particles/spinner/spinner.js.map +1 -1
  386. package/dist/particles/switch/switch.d.ts +4 -1
  387. package/dist/particles/switch/switch.js +3 -1
  388. package/dist/particles/switch/switch.js.map +1 -1
  389. package/dist/particles/toast/toast.d.ts +29 -3
  390. package/dist/particles/toast/toast.js +34 -10
  391. package/dist/particles/toast/toast.js.map +1 -1
  392. package/dist/schema.graphql +164 -56
  393. package/dist/sdk/address/address-fields.js +4 -4
  394. package/dist/sdk/address/address-fields.js.map +1 -1
  395. package/dist/sdk/address/constants.js +1 -6
  396. package/dist/sdk/address/constants.js.map +1 -1
  397. package/dist/sdk/address/messages.js +44 -44
  398. package/dist/sdk/address/messages.js.map +1 -1
  399. package/dist/sdk/address/postal-code.js +15 -2
  400. package/dist/sdk/address/postal-code.js.map +1 -1
  401. package/dist/sdk/address/types.d.ts +5 -3
  402. package/dist/sdk/address/validate-address.js +3 -3
  403. package/dist/sdk/address/validate-address.js.map +1 -1
  404. package/dist/sdk/analytics/use-analytics-actions.d.ts +1 -1
  405. package/dist/sdk/analytics/use-analytics-actions.js.map +1 -1
  406. package/dist/sdk/cart/use-cart-actions.js.map +1 -1
  407. package/dist/sdk/data/index.js +2 -2
  408. package/dist/sdk/data/reactive-list-item-data-provider.js +2 -2
  409. package/dist/sdk/generated/gql.js +1 -1
  410. package/dist/sdk/generated/gql.js.map +1 -1
  411. package/dist/sdk/generated/graphql.d.ts +20 -5
  412. package/dist/sdk/generated/graphql.js +6 -0
  413. package/dist/sdk/generated/graphql.js.map +1 -1
  414. package/dist/sdk/i18n/format-error-code.js +23 -0
  415. package/dist/sdk/i18n/format-error-code.js.map +1 -0
  416. package/dist/sdk/i18n/message-formatter.d.ts +22 -0
  417. package/dist/sdk/i18n/message-formatter.js +140 -0
  418. package/dist/sdk/i18n/message-formatter.js.map +1 -0
  419. package/dist/sdk/i18n/use-message-formatter.d.ts +8 -0
  420. package/dist/sdk/i18n/use-message-formatter.js +18 -0
  421. package/dist/sdk/i18n/use-message-formatter.js.map +1 -0
  422. package/dist/sdk/identity/use-identity-actions.js.map +1 -1
  423. package/dist/sdk/navigation/redirect.d.ts +2 -0
  424. package/dist/sdk/navigation/redirect.js +19 -1
  425. package/dist/sdk/navigation/redirect.js.map +1 -1
  426. package/dist/sdk/navigation/types.d.ts +13 -0
  427. package/dist/sdk/payment/bin-format.js +21 -0
  428. package/dist/sdk/payment/bin-format.js.map +1 -0
  429. package/dist/sdk/payment/challenge-return.js +37 -0
  430. package/dist/sdk/payment/challenge-return.js.map +1 -0
  431. package/dist/sdk/payment/confirmation-last-four.js +39 -0
  432. package/dist/sdk/payment/confirmation-last-four.js.map +1 -0
  433. package/dist/sdk/payment/gateway.d.ts +1 -1
  434. package/dist/sdk/payment/gateway.js +8 -2
  435. package/dist/sdk/payment/gateway.js.map +1 -1
  436. package/dist/sdk/payment/operations.d.ts +1 -0
  437. package/dist/sdk/payment/operations.js +28 -6
  438. package/dist/sdk/payment/operations.js.map +1 -1
  439. package/dist/sdk/payment/resumed-purchase.d.ts +1 -0
  440. package/dist/sdk/payment/resumed-purchase.js +119 -0
  441. package/dist/sdk/payment/resumed-purchase.js.map +1 -0
  442. package/dist/sdk/payment/security-code-mask.js +16 -23
  443. package/dist/sdk/payment/security-code-mask.js.map +1 -1
  444. package/dist/sdk/payment/submission-registry.js +6 -2
  445. package/dist/sdk/payment/submission-registry.js.map +1 -1
  446. package/dist/sdk/payment/use-payment-actions.d.ts +18 -3
  447. package/dist/sdk/payment/use-payment-actions.js +23 -4
  448. package/dist/sdk/payment/use-payment-actions.js.map +1 -1
  449. package/dist/sdk/payment/use-place-order.d.ts +10 -2
  450. package/dist/sdk/payment/use-place-order.js +138 -76
  451. package/dist/sdk/payment/use-place-order.js.map +1 -1
  452. package/dist/sdk/provider/storefront-provider.d.ts +1 -7
  453. package/dist/sdk/provider/storefront-provider.js +4 -11
  454. package/dist/sdk/provider/storefront-provider.js.map +1 -1
  455. package/dist/sdk/seo/entity-landing.d.ts +24 -0
  456. package/dist/sdk/seo/entity-landing.js +30 -0
  457. package/dist/sdk/seo/entity-landing.js.map +1 -0
  458. package/dist/sdk/seo/page-alternates.d.ts +3 -2
  459. package/dist/sdk/seo/page-alternates.js +4 -2
  460. package/dist/sdk/seo/page-alternates.js.map +1 -1
  461. package/dist/sdk/seo/search-landing.d.ts +42 -0
  462. package/dist/sdk/seo/search-landing.js +85 -0
  463. package/dist/sdk/seo/search-landing.js.map +1 -0
  464. package/dist/sdk/session/mock-session.d.ts +9 -0
  465. package/dist/sdk/session/mock-session.js +31 -0
  466. package/dist/sdk/session/mock-session.js.map +1 -0
  467. package/dist/sdk/session/read-server-session.d.ts +3 -0
  468. package/dist/sdk/session/read-server-session.js +5 -0
  469. package/dist/sdk/session/read-server-session.js.map +1 -1
  470. package/dist/sdk/session/return-path-segment.d.ts +10 -0
  471. package/dist/sdk/session/return-path-segment.js +15 -0
  472. package/dist/sdk/session/return-path-segment.js.map +1 -0
  473. package/dist/sdk/session/use-session-actions.js.map +1 -1
  474. package/dist/sdk/shipping/use-cart-shipping-simulation.js.map +1 -1
  475. package/dist/sdk/shipping/use-shipping-actions.js.map +1 -1
  476. package/dist/sdk/shipping/use-shipping-simulation.js.map +1 -1
  477. package/dist/utils/safe-href.d.ts +2 -0
  478. package/package.json +4 -3
  479. package/skills/storefront-asset/SKILL.md +2 -2
  480. package/skills/storefront-asset/references/api-side.md +27 -14
  481. package/skills/storefront-asset/references/findings.md +5 -2
  482. package/src/styles/tailwind.css +8 -0
  483. package/dist/matter/shipping-address/country-descriptors.d.ts +0 -1
  484. package/dist/message-locales.json +0 -7
  485. package/dist/sdk/i18n/client.d.ts +0 -4
  486. package/dist/sdk/i18n/client.js +0 -4
  487. package/dist/sdk/i18n/locales.d.ts +0 -8
  488. package/dist/sdk/i18n/locales.js +0 -57
  489. package/dist/sdk/i18n/locales.js.map +0 -1
  490. package/dist/sdk/i18n/messages/en-US.js +0 -183
  491. package/dist/sdk/i18n/messages/en-US.js.map +0 -1
  492. package/dist/sdk/i18n/messages/en-US.json +0 -178
  493. package/dist/sdk/i18n/messages/en-US.json.d.ts +0 -182
  494. package/dist/sdk/i18n/messages/es-ES.js +0 -183
  495. package/dist/sdk/i18n/messages/es-ES.js.map +0 -1
  496. package/dist/sdk/i18n/messages/es-ES.json +0 -178
  497. package/dist/sdk/i18n/messages/pt-BR.js +0 -183
  498. package/dist/sdk/i18n/messages/pt-BR.js.map +0 -1
  499. package/dist/sdk/i18n/messages/pt-BR.json +0 -178
  500. package/dist/sdk/i18n/provider.d.ts +0 -1
  501. package/dist/sdk/i18n/provider.js +0 -30
  502. package/dist/sdk/i18n/provider.js.map +0 -1
  503. package/dist/sdk/i18n/server.d.ts +0 -28
  504. package/dist/sdk/i18n/server.js +0 -59
  505. package/dist/sdk/i18n/server.js.map +0 -1
  506. package/dist/utils/resolve-authored-copy.js +0 -18
  507. package/dist/utils/resolve-authored-copy.js.map +0 -1
  508. package/dist/utils/substitute-template.js +0 -33
  509. package/dist/utils/substitute-template.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"order-details-back.js","names":[],"sources":["../../../src/particles/order-details-back/order-details-back.tsx"],"sourcesContent":["'use client';\n\nimport { type ContentValue, defineComponent, defineContentType } from '@vtex/fs-core';\nimport type { ComponentPropsWithRef } from 'react';\nimport { useIntl } from '../../sdk/i18n/client.js';\n\nconst LIST_HREF = '/pvt/orders';\n\nexport const OrderDetailsBackContent = defineContentType({\n id: 'order-details-back',\n title: 'Order Details Back',\n description: 'The link back to the order list.',\n schema: {\n type: 'object',\n additionalProperties: false,\n properties: {\n label: { type: 'string', title: 'Label' },\n },\n },\n});\n\nexport type OrderDetailsBackContentValue = ContentValue<typeof OrderDetailsBackContent>;\n\nexport type OrderDetailsBackProps = ComponentPropsWithRef<'a'> & {\n $content?: OrderDetailsBackContentValue;\n};\n\nexport const OrderDetailsBackDefinition = defineComponent<OrderDetailsBackProps>({\n name: 'OrderDetailsBack',\n importPath: '@vtex/faststore/components',\n component: OrderDetailsBack,\n content: OrderDetailsBackContent,\n editor: { label: 'Order Details Back', category: 'action' },\n schema: {},\n guideline:\n 'The return from one order to the order list. Place it first on the order page when the layout has no account breadcrumb. The label is content; a blank field keeps the catalogue.',\n});\n\nfunction authored(value: string | undefined, fallback: string): string {\n const trimmed = value?.trim();\n return trimmed || fallback;\n}\n\nexport function OrderDetailsBack({ className, ref, $content, ...props }: OrderDetailsBackProps) {\n const intl = useIntl();\n const label = authored($content?.label, intl.formatMessage({ id: 'fs/order.back-to-orders' }));\n\n return (\n <a {...props} ref={ref} href={LIST_HREF} className={className} data-fs-order-details-back=\"\">\n {label}\n </a>\n );\n}\n"],"mappings":";;;;;;;AAMA,MAAM,YAAY;AAElB,MAAa,0BAA0B,kBAAkB;CACvD,IAAI;CACJ,OAAO;CACP,aAAa;CACb,QAAQ;EACN,MAAM;EACN,sBAAsB;EACtB,YAAY,EACV,OAAO;GAAE,MAAM;GAAU,OAAO;EAAQ,EAC1C;CACF;AACF,CAAC;AAQD,MAAa,6BAA6B,gBAAuC;CAC/E,MAAM;CACN,YAAY;CACZ,WAAW;CACX,SAAS;CACT,QAAQ;EAAE,OAAO;EAAsB,UAAU;CAAS;CAC1D,QAAQ,CAAC;CACT,WACE;AACJ,CAAC;AAED,SAAS,SAAS,OAA2B,UAA0B;CAErE,OADgB,OAAO,KAAK,KACV;AACpB;AAEA,SAAgB,iBAAiB,EAAE,WAAW,KAAK,UAAU,GAAG,SAAgC;CAC9F,MAAM,OAAO,QAAQ;CACrB,MAAM,QAAQ,SAAS,UAAU,OAAO,KAAK,cAAc,EAAE,IAAI,0BAA0B,CAAC,CAAC;CAE7F,OACE,oBAAC,KAAD;EAAG,GAAI;EAAY;EAAK,MAAM;EAAsB;EAAW,8BAA2B;EACvF,UAAA;CACA,CAAA;AAEP"}
1
+ {"version":3,"file":"order-details-back.js","names":[],"sources":["../../../src/particles/order-details-back/order-details-back.tsx"],"sourcesContent":["'use client';\n\nimport { type ContentValue, defineComponent, defineContentType, type MessageLocaleProp } from '@vtex/fs-core';\nimport type { ComponentPropsWithRef } from 'react';\nimport { useMessageFormatter } from '../../sdk/i18n/use-message-formatter.js';\n\nconst LIST_HREF = '/pvt/orders';\n\nexport const OrderDetailsBackContent = defineContentType({\n id: 'order-details-back',\n title: 'Order Details Back',\n description: 'The link back to the order list.',\n schema: {\n type: 'object',\n additionalProperties: false,\n properties: {\n label: { type: 'string', title: 'Label', format: 'icu-message', messageSource: 'Back to orders' },\n },\n },\n});\n\nexport type OrderDetailsBackContentValue = ContentValue<typeof OrderDetailsBackContent>;\n\nexport type OrderDetailsBackProps = ComponentPropsWithRef<'a'> &\n MessageLocaleProp & {\n $content?: OrderDetailsBackContentValue;\n };\n\nexport const OrderDetailsBackDefinition = defineComponent<OrderDetailsBackProps>({\n name: 'OrderDetailsBack',\n importPath: '@vtex/faststore/components',\n component: OrderDetailsBack,\n content: OrderDetailsBackContent,\n editor: { label: 'Order Details Back', category: 'action' },\n schema: {},\n guideline:\n 'The return from one order to the order list. Place it first on the order page when the layout has no account breadcrumb. The label is content.',\n});\n\nexport function OrderDetailsBack({ className, ref, $content, $locale, ...props }: OrderDetailsBackProps) {\n const { format } = useMessageFormatter(OrderDetailsBackContent, $content);\n\n return (\n <a {...props} ref={ref} href={LIST_HREF} className={className} data-fs-order-details-back=\"\">\n {format('label')}\n </a>\n );\n}\n"],"mappings":";;;;;;;AAMA,MAAM,YAAY;AAElB,MAAa,0BAA0B,kBAAkB;CACvD,IAAI;CACJ,OAAO;CACP,aAAa;CACb,QAAQ;EACN,MAAM;EACN,sBAAsB;EACtB,YAAY,EACV,OAAO;GAAE,MAAM;GAAU,OAAO;GAAS,QAAQ;GAAe,eAAe;EAAiB,EAClG;CACF;AACF,CAAC;AASD,MAAa,6BAA6B,gBAAuC;CAC/E,MAAM;CACN,YAAY;CACZ,WAAW;CACX,SAAS;CACT,QAAQ;EAAE,OAAO;EAAsB,UAAU;CAAS;CAC1D,QAAQ,CAAC;CACT,WACE;AACJ,CAAC;AAED,SAAgB,iBAAiB,EAAE,WAAW,KAAK,UAAU,SAAS,GAAG,SAAgC;CACvG,MAAM,EAAE,WAAW,oBAAoB,yBAAyB,QAAQ;CAExE,OACE,oBAAC,KAAD;EAAG,GAAI;EAAY;EAAK,MAAM;EAAsB;EAAW,8BAA2B;EACvF,UAAA,OAAO,OAAO;CACd,CAAA;AAEP"}
@@ -5,13 +5,13 @@ import { ComponentPropsWithRef } from "react";
5
5
  export type OrderStatusState = 'ongoing' | 'completed' | 'cancelled';
6
6
  export type OrderStatusTone = 'neutral' | 'progress' | 'success' | 'danger';
7
7
  export type OrderStatusMessageKey = 'cancelled' | 'cancellation-requested' | 'in-progress' | 'delivered' | 'shipped' | 'ready-for-pickup' | 'collected' | 'placeholder';
8
- /** Per-label sentences. A blank value keeps the catalogue sentence for that label. */
9
- export type OrderStatusMessages = Partial<Record<OrderStatusMessageKey, string>>;
8
+ /** The formatted sentence for each status label, supplied by the component that owns the copy. */
9
+ export type OrderStatusMessages = Record<OrderStatusMessageKey, string>;
10
10
  export type OrderStatusBadgeProps = Omit<ComponentPropsWithRef<'span'>, 'children'> & {
11
11
  state: OrderStatusState;
12
12
  tone: OrderStatusTone;
13
13
  label: string;
14
- messages?: OrderStatusMessages;
14
+ messages: OrderStatusMessages;
15
15
  };
16
16
  export declare const OrderStatusBadgeDefinition: ComponentDefinition<OrderStatusBadgeProps>;
17
17
  export declare function OrderStatusBadge({ state, tone, label, messages, className, ...props }: OrderStatusBadgeProps): import("react/jsx-runtime").JSX.Element;
@@ -1,23 +1,9 @@
1
1
  "use client";
2
2
  import { defineComponent } from "../../core/dist/define-component.js";
3
3
  import "../../core/dist/index.js";
4
- import { useIntl } from "../../sdk/i18n/client.js";
5
4
  import { Badge } from "../badge/badge.js";
6
5
  import { jsx } from "react/jsx-runtime";
7
6
  //#region src/particles/order-status-badge/order-status-badge.tsx
8
- const ORDER_STATUS_MESSAGES = {
9
- cancelled: "fs/order-status.cancelled",
10
- "cancellation-requested": "fs/order-status.cancellation-requested",
11
- "in-progress": "fs/order-status.in-progress",
12
- delivered: "fs/order-status.delivered",
13
- shipped: "fs/order-status.shipped",
14
- "ready-for-pickup": "fs/order-status.ready-for-pickup",
15
- collected: "fs/order-status.collected"
16
- };
17
- function orderStatusMessageId(label) {
18
- if (!Object.hasOwn(ORDER_STATUS_MESSAGES, label)) return "fs/order-status.placeholder";
19
- return ORDER_STATUS_MESSAGES[label] ?? "fs/order-status.placeholder";
20
- }
21
7
  const OrderStatusBadgeDefinition = defineComponent({
22
8
  name: "OrderStatusBadge",
23
9
  importPath: "@vtex/faststore/components",
@@ -27,21 +13,19 @@ const OrderStatusBadgeDefinition = defineComponent({
27
13
  category: "content"
28
14
  },
29
15
  schema: {},
30
- guideline: "Shopper-facing order status. Pass the completion view, the label id, and a tone. A messages entry replaces the catalogue sentence for that label; a blank entry and an unknown label keep the catalogue."
16
+ guideline: "Shopper-facing order status. Pass the completion view, the label id, a tone and the formatted messages; an unknown label renders the placeholder. The order list row and the order details header render it; do not place it on a page alone."
31
17
  });
32
- function messageKey(label) {
33
- return Object.hasOwn(ORDER_STATUS_MESSAGES, label) ? label : "placeholder";
18
+ function statusMessage(messages, label) {
19
+ return Object.hasOwn(messages, label) ? messages[label] : messages.placeholder;
34
20
  }
35
21
  function OrderStatusBadge({ state, tone, label, messages, className, ...props }) {
36
- const intl = useIntl();
37
- const authored = messages?.[messageKey(label)]?.trim();
38
22
  return /* @__PURE__ */ jsx(Badge, {
39
23
  ...props,
40
24
  className,
41
25
  "data-fs-order-status-badge": "",
42
26
  "data-fs-order-status-badge-state": state,
43
27
  "data-fs-order-status-badge-tone": tone,
44
- children: authored || intl.formatMessage({ id: orderStatusMessageId(label) })
28
+ children: statusMessage(messages, label)
45
29
  });
46
30
  }
47
31
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"order-status-badge.js","names":[],"sources":["../../../src/particles/order-status-badge/order-status-badge.tsx"],"sourcesContent":["'use client';\n\nimport { defineComponent } from '@vtex/fs-core';\nimport type { ComponentPropsWithRef } from 'react';\nimport { useIntl } from '../../sdk/i18n/client.js';\nimport type { MessageId } from '../../sdk/i18n/locales.js';\nimport { Badge } from '../badge/badge.js';\n\nexport type OrderStatusState = 'ongoing' | 'completed' | 'cancelled';\n\nexport type OrderStatusTone = 'neutral' | 'progress' | 'success' | 'danger';\n\nexport type OrderStatusMessageKey =\n | 'cancelled'\n | 'cancellation-requested'\n | 'in-progress'\n | 'delivered'\n | 'shipped'\n | 'ready-for-pickup'\n | 'collected'\n | 'placeholder';\n\n/** Per-label sentences. A blank value keeps the catalogue sentence for that label. */\nexport type OrderStatusMessages = Partial<Record<OrderStatusMessageKey, string>>;\n\nexport type OrderStatusBadgeProps = Omit<ComponentPropsWithRef<'span'>, 'children'> & {\n state: OrderStatusState;\n tone: OrderStatusTone;\n label: string;\n messages?: OrderStatusMessages;\n};\n\nconst ORDER_STATUS_MESSAGES: Record<string, MessageId> = {\n cancelled: 'fs/order-status.cancelled',\n 'cancellation-requested': 'fs/order-status.cancellation-requested',\n 'in-progress': 'fs/order-status.in-progress',\n delivered: 'fs/order-status.delivered',\n shipped: 'fs/order-status.shipped',\n 'ready-for-pickup': 'fs/order-status.ready-for-pickup',\n collected: 'fs/order-status.collected',\n};\n\nfunction orderStatusMessageId(label: string): MessageId {\n // Bracket access walks Object.prototype, so \"constructor\" would skip the placeholder.\n if (!Object.hasOwn(ORDER_STATUS_MESSAGES, label)) {\n return 'fs/order-status.placeholder';\n }\n\n return ORDER_STATUS_MESSAGES[label] ?? 'fs/order-status.placeholder';\n}\n\nexport const OrderStatusBadgeDefinition = defineComponent<OrderStatusBadgeProps>({\n name: 'OrderStatusBadge',\n importPath: '@vtex/faststore/components',\n component: OrderStatusBadge,\n editor: { label: 'Order Status Badge', category: 'content' },\n schema: {},\n guideline:\n 'Shopper-facing order status. Pass the completion view, the label id, and a tone. A messages entry replaces the catalogue sentence for that label; a blank entry and an unknown label keep the catalogue.',\n});\n\nfunction messageKey(label: string): OrderStatusMessageKey {\n return Object.hasOwn(ORDER_STATUS_MESSAGES, label) ? (label as OrderStatusMessageKey) : 'placeholder';\n}\n\nexport function OrderStatusBadge({ state, tone, label, messages, className, ...props }: OrderStatusBadgeProps) {\n const intl = useIntl();\n const authored = messages?.[messageKey(label)]?.trim();\n\n return (\n <Badge\n {...props}\n className={className}\n data-fs-order-status-badge=\"\"\n data-fs-order-status-badge-state={state}\n data-fs-order-status-badge-tone={tone}\n >\n {authored || intl.formatMessage({ id: orderStatusMessageId(label) })}\n </Badge>\n );\n}\n"],"mappings":";;;;;;;AAgCA,MAAM,wBAAmD;CACvD,WAAW;CACX,0BAA0B;CAC1B,eAAe;CACf,WAAW;CACX,SAAS;CACT,oBAAoB;CACpB,WAAW;AACb;AAEA,SAAS,qBAAqB,OAA0B;CAEtD,IAAI,CAAC,OAAO,OAAO,uBAAuB,KAAK,GAC7C,OAAO;CAGT,OAAO,sBAAsB,UAAU;AACzC;AAEA,MAAa,6BAA6B,gBAAuC;CAC/E,MAAM;CACN,YAAY;CACZ,WAAW;CACX,QAAQ;EAAE,OAAO;EAAsB,UAAU;CAAU;CAC3D,QAAQ,CAAC;CACT,WACE;AACJ,CAAC;AAED,SAAS,WAAW,OAAsC;CACxD,OAAO,OAAO,OAAO,uBAAuB,KAAK,IAAK,QAAkC;AAC1F;AAEA,SAAgB,iBAAiB,EAAE,OAAO,MAAM,OAAO,UAAU,WAAW,GAAG,SAAgC;CAC7G,MAAM,OAAO,QAAQ;CACrB,MAAM,WAAW,WAAW,WAAW,KAAK,EAAE,EAAE,KAAK;CAErD,OACE,oBAAC,OAAD;EACE,GAAI;EACO;EACX,8BAA2B;EAC3B,oCAAkC;EAClC,mCAAiC;EAEhC,UAAA,YAAY,KAAK,cAAc,EAAE,IAAI,qBAAqB,KAAK,EAAE,CAAC;CAC9D,CAAA;AAEX"}
1
+ {"version":3,"file":"order-status-badge.js","names":[],"sources":["../../../src/particles/order-status-badge/order-status-badge.tsx"],"sourcesContent":["'use client';\n\nimport { defineComponent } from '@vtex/fs-core';\nimport type { ComponentPropsWithRef } from 'react';\nimport { Badge } from '../badge/badge.js';\n\nexport type OrderStatusState = 'ongoing' | 'completed' | 'cancelled';\n\nexport type OrderStatusTone = 'neutral' | 'progress' | 'success' | 'danger';\n\nexport type OrderStatusMessageKey =\n | 'cancelled'\n | 'cancellation-requested'\n | 'in-progress'\n | 'delivered'\n | 'shipped'\n | 'ready-for-pickup'\n | 'collected'\n | 'placeholder';\n\n/** The formatted sentence for each status label, supplied by the component that owns the copy. */\nexport type OrderStatusMessages = Record<OrderStatusMessageKey, string>;\n\nexport type OrderStatusBadgeProps = Omit<ComponentPropsWithRef<'span'>, 'children'> & {\n state: OrderStatusState;\n tone: OrderStatusTone;\n label: string;\n messages: OrderStatusMessages;\n};\n\nexport const OrderStatusBadgeDefinition = defineComponent<OrderStatusBadgeProps>({\n name: 'OrderStatusBadge',\n importPath: '@vtex/faststore/components',\n component: OrderStatusBadge,\n editor: { label: 'Order Status Badge', category: 'content' },\n schema: {},\n guideline:\n 'Shopper-facing order status. Pass the completion view, the label id, a tone and the formatted messages; an unknown label renders the placeholder. The order list row and the order details header render it; do not place it on a page alone.',\n});\n\nfunction statusMessage(messages: OrderStatusMessages, label: string): string {\n // Bracket access walks Object.prototype, so \"constructor\" would skip the placeholder.\n return Object.hasOwn(messages, label) ? messages[label as OrderStatusMessageKey] : messages.placeholder;\n}\n\nexport function OrderStatusBadge({ state, tone, label, messages, className, ...props }: OrderStatusBadgeProps) {\n return (\n <Badge\n {...props}\n className={className}\n data-fs-order-status-badge=\"\"\n data-fs-order-status-badge-state={state}\n data-fs-order-status-badge-tone={tone}\n >\n {statusMessage(messages, label)}\n </Badge>\n );\n}\n"],"mappings":";;;;;;AA8BA,MAAa,6BAA6B,gBAAuC;CAC/E,MAAM;CACN,YAAY;CACZ,WAAW;CACX,QAAQ;EAAE,OAAO;EAAsB,UAAU;CAAU;CAC3D,QAAQ,CAAC;CACT,WACE;AACJ,CAAC;AAED,SAAS,cAAc,UAA+B,OAAuB;CAE3E,OAAO,OAAO,OAAO,UAAU,KAAK,IAAI,SAAS,SAAkC,SAAS;AAC9F;AAEA,SAAgB,iBAAiB,EAAE,OAAO,MAAM,OAAO,UAAU,WAAW,GAAG,SAAgC;CAC7G,OACE,oBAAC,OAAD;EACE,GAAI;EACO;EACX,8BAA2B;EAC3B,oCAAkC;EAClC,mCAAiC;EAEhC,UAAA,cAAc,UAAU,KAAK;CACzB,CAAA;AAEX"}
@@ -26,6 +26,6 @@ export declare const PasswordFieldDefinition: ComponentDefinition<PasswordFieldP
26
26
  * toggle. Presence-only validation is caller-driven via `invalid`/`errorMessage` — this
27
27
  * particle computes no validity of its own. `revealed` is local, uncontrolled UI state.
28
28
  */
29
- export declare function PasswordField({ value, defaultValue, onValueChange, invalid, errorMessage, label, placeholder, requirement, autoComplete, showPasswordLabel, hidePasswordLabel, disabled, name, id, className }: PasswordFieldProps): import("react/jsx-runtime").JSX.Element;
29
+ export declare function PasswordField({ value, defaultValue, onValueChange, invalid, errorMessage, label, placeholder, requirement, autoComplete, showPasswordLabel, hidePasswordLabel, disabled, name, id, className }: Readonly<PasswordFieldProps>): import("react/jsx-runtime").JSX.Element;
30
30
  //#endregion
31
31
  //# sourceMappingURL=password-field.d.ts.map
@@ -37,12 +37,10 @@ const PasswordFieldDefinition = defineComponent({
37
37
  },
38
38
  showPasswordLabel: {
39
39
  type: "string",
40
- default: "Show password",
41
40
  label: "Show password label"
42
41
  },
43
42
  hidePasswordLabel: {
44
43
  type: "string",
45
- default: "Hide password",
46
44
  label: "Hide password label"
47
45
  },
48
46
  disabled: {
@@ -51,14 +49,14 @@ const PasswordFieldDefinition = defineComponent({
51
49
  label: "Disabled"
52
50
  }
53
51
  },
54
- guideline: "Presentational password input with a show/hide reveal toggle. Set autoComplete=\"new-password\" for recovery/set-password screens (default is \"current-password\" for sign-in). No validation beyond presence — invalid/errorMessage are caller-driven. No data layer: does not call login, does not read session."
52
+ guideline: "Presentational password input with a show/hide reveal toggle. Set autoComplete=\"new-password\" for recovery/set-password screens (default is \"current-password\" for sign-in). The owner passes showPasswordLabel and hidePasswordLabel already formatted; they have no default. No validation beyond presence — invalid/errorMessage are caller-driven. No data layer: does not call login, does not read session."
55
53
  });
56
54
  /**
57
55
  * Composes Field + Input + Toggle + Icon into a password input with a show/hide reveal
58
56
  * toggle. Presence-only validation is caller-driven via `invalid`/`errorMessage` — this
59
57
  * particle computes no validity of its own. `revealed` is local, uncontrolled UI state.
60
58
  */
61
- function PasswordField({ value, defaultValue, onValueChange, invalid = false, errorMessage, label, placeholder, requirement = "mandatory", autoComplete = "current-password", showPasswordLabel = "Show password", hidePasswordLabel = "Hide password", disabled = false, name, id, className }) {
59
+ function PasswordField({ value, defaultValue, onValueChange, invalid = false, errorMessage, label, placeholder, requirement = "mandatory", autoComplete = "current-password", showPasswordLabel, hidePasswordLabel, disabled = false, name, id, className }) {
62
60
  const [revealed, setRevealed] = useState(false);
63
61
  function handleChange(event) {
64
62
  onValueChange?.(event.target.value);
@@ -1 +1 @@
1
- {"version":3,"file":"password-field.js","names":[],"sources":["../../../src/particles/password-field/password-field.tsx"],"sourcesContent":["'use client';\nimport { defineComponent } from '@vtex/fs-core';\nimport { type ChangeEvent, useState } from 'react';\nimport { Field } from '../field/field.js';\nimport { Icon } from '../icon/icon.js';\nimport { Input } from '../input/input.js';\nimport { Toggle } from '../toggle/toggle.js';\n\nexport type PasswordFieldRequirement = 'mandatory' | 'optional';\n\nexport type PasswordFieldAutoComplete = 'current-password' | 'new-password';\n\nexport type PasswordFieldProps = {\n value?: string;\n defaultValue?: string;\n onValueChange?: (value: string) => void;\n invalid?: boolean;\n errorMessage?: string;\n label?: string;\n placeholder?: string;\n requirement?: PasswordFieldRequirement;\n autoComplete?: PasswordFieldAutoComplete;\n showPasswordLabel?: string;\n hidePasswordLabel?: string;\n disabled?: boolean;\n name?: string;\n id?: string;\n className?: string;\n};\n\nexport const PasswordFieldDefinition = defineComponent<PasswordFieldProps>({\n name: 'PasswordField',\n importPath: '@vtex/faststore/components',\n component: PasswordField,\n editor: { label: 'Password Field', category: 'action' },\n schema: {\n label: { type: 'string', label: 'Label' },\n placeholder: { type: 'string', label: 'Placeholder' },\n requirement: { type: ['mandatory', 'optional'] as const, default: 'mandatory', label: 'Requirement' },\n autoComplete: {\n type: ['current-password', 'new-password'] as const,\n default: 'current-password',\n label: 'Autocomplete',\n },\n showPasswordLabel: { type: 'string', default: 'Show password', label: 'Show password label' },\n hidePasswordLabel: { type: 'string', default: 'Hide password', label: 'Hide password label' },\n disabled: { type: 'boolean', default: false, label: 'Disabled' },\n },\n guideline:\n 'Presentational password input with a show/hide reveal toggle. Set autoComplete=\"new-password\" for recovery/set-password screens (default is \"current-password\" for sign-in). No validation beyond presence — invalid/errorMessage are caller-driven. No data layer: does not call login, does not read session.',\n});\n\n/**\n * Composes Field + Input + Toggle + Icon into a password input with a show/hide reveal\n * toggle. Presence-only validation is caller-driven via `invalid`/`errorMessage` — this\n * particle computes no validity of its own. `revealed` is local, uncontrolled UI state.\n */\nexport function PasswordField({\n value,\n defaultValue,\n onValueChange,\n invalid = false,\n errorMessage,\n label,\n placeholder,\n requirement = 'mandatory',\n autoComplete = 'current-password',\n showPasswordLabel = 'Show password',\n hidePasswordLabel = 'Hide password',\n disabled = false,\n name,\n id,\n className,\n}: PasswordFieldProps) {\n const [revealed, setRevealed] = useState(false);\n\n function handleChange(event: ChangeEvent<HTMLInputElement>) {\n onValueChange?.(event.target.value);\n }\n\n return (\n <Field.Root invalid={invalid} disabled={disabled} name={name} className={className} data-fs-password-field=\"\">\n {label ? <Field.Label>{label}</Field.Label> : null}\n <div data-fs-password-field-group=\"\">\n <Input\n id={id}\n type={revealed ? 'text' : 'password'}\n autoComplete={autoComplete}\n // `aria-required`, not native `required`: `Input` is a Base UI `Field.Control`, and native\n // constraint tracking would flip `aria-invalid` on its own — validity here is caller-driven.\n aria-required={requirement === 'mandatory' ? 'true' : undefined}\n spellCheck={false}\n autoCapitalize=\"off\"\n autoCorrect=\"off\"\n placeholder={placeholder}\n disabled={disabled}\n value={value}\n defaultValue={value === undefined ? defaultValue : undefined}\n onChange={handleChange}\n />\n <Toggle\n type=\"button\"\n pressed={revealed}\n onPressedChange={setRevealed}\n disabled={disabled}\n aria-label={revealed ? hidePasswordLabel : showPasswordLabel}\n data-fs-password-field-toggle=\"\"\n >\n <Icon name={revealed ? 'eye-off' : 'eye'} />\n </Toggle>\n </div>\n <Field.Error match={invalid ? true : 'customError'}>{errorMessage}</Field.Error>\n </Field.Root>\n );\n}\n"],"mappings":";;;;;;;;;;AA8BA,MAAa,0BAA0B,gBAAoC;CACzE,MAAM;CACN,YAAY;CACZ,WAAW;CACX,QAAQ;EAAE,OAAO;EAAkB,UAAU;CAAS;CACtD,QAAQ;EACN,OAAO;GAAE,MAAM;GAAU,OAAO;EAAQ;EACxC,aAAa;GAAE,MAAM;GAAU,OAAO;EAAc;EACpD,aAAa;GAAE,MAAM,CAAC,aAAa,UAAU;GAAY,SAAS;GAAa,OAAO;EAAc;EACpG,cAAc;GACZ,MAAM,CAAC,oBAAoB,cAAc;GACzC,SAAS;GACT,OAAO;EACT;EACA,mBAAmB;GAAE,MAAM;GAAU,SAAS;GAAiB,OAAO;EAAsB;EAC5F,mBAAmB;GAAE,MAAM;GAAU,SAAS;GAAiB,OAAO;EAAsB;EAC5F,UAAU;GAAE,MAAM;GAAW,SAAS;GAAO,OAAO;EAAW;CACjE;CACA,WACE;AACJ,CAAC;;;;;;AAOD,SAAgB,cAAc,EAC5B,OACA,cACA,eACA,UAAU,OACV,cACA,OACA,aACA,cAAc,aACd,eAAe,oBACf,oBAAoB,iBACpB,oBAAoB,iBACpB,WAAW,OACX,MACA,IACA,aACqB;CACrB,MAAM,CAAC,UAAU,eAAe,SAAS,KAAK;CAE9C,SAAS,aAAa,OAAsC;EAC1D,gBAAgB,MAAM,OAAO,KAAK;CACpC;CAEA,OACE,qBAAC,MAAM,MAAP;EAAqB;EAAmB;EAAgB;EAAiB;EAAW,0BAAuB;EAA3G,UAAA;GACG,QAAQ,oBAAC,MAAM,OAAP,EAAA,UAAc,MAAmB,CAAA,IAAI;GAC9C,qBAAC,OAAD;IAAK,gCAA6B;IAAlC,UAAA,CACE,oBAAC,OAAD;KACM;KACJ,MAAM,WAAW,SAAS;KACZ;KAGd,iBAAe,gBAAgB,cAAc,SAAS,KAAA;KACtD,YAAY;KACZ,gBAAe;KACf,aAAY;KACC;KACH;KACH;KACP,cAAc,UAAU,KAAA,IAAY,eAAe,KAAA;KACnD,UAAU;IACX,CAAA,GACD,oBAAC,QAAD;KACE,MAAK;KACL,SAAS;KACT,iBAAiB;KACP;KACV,cAAY,WAAW,oBAAoB;KAC3C,iCAA8B;KAE9B,UAAA,oBAAC,MAAD,EAAM,MAAM,WAAW,YAAY,MAAQ,CAAA;IACrC,CAAA,CACL;;GACL,oBAAC,MAAM,OAAP;IAAa,OAAO,UAAU,OAAO;IAAgB,UAAA;GAA0B,CAAA;EACrE;;AAEhB"}
1
+ {"version":3,"file":"password-field.js","names":[],"sources":["../../../src/particles/password-field/password-field.tsx"],"sourcesContent":["'use client';\nimport { defineComponent } from '@vtex/fs-core';\nimport { type ChangeEvent, useState } from 'react';\nimport { Field } from '../field/field.js';\nimport { Icon } from '../icon/icon.js';\nimport { Input } from '../input/input.js';\nimport { Toggle } from '../toggle/toggle.js';\n\nexport type PasswordFieldRequirement = 'mandatory' | 'optional';\n\nexport type PasswordFieldAutoComplete = 'current-password' | 'new-password';\n\nexport type PasswordFieldProps = {\n value?: string;\n defaultValue?: string;\n onValueChange?: (value: string) => void;\n invalid?: boolean;\n errorMessage?: string;\n label?: string;\n placeholder?: string;\n requirement?: PasswordFieldRequirement;\n autoComplete?: PasswordFieldAutoComplete;\n showPasswordLabel?: string;\n hidePasswordLabel?: string;\n disabled?: boolean;\n name?: string;\n id?: string;\n className?: string;\n};\n\nexport const PasswordFieldDefinition = defineComponent<PasswordFieldProps>({\n name: 'PasswordField',\n importPath: '@vtex/faststore/components',\n component: PasswordField,\n editor: { label: 'Password Field', category: 'action' },\n schema: {\n label: { type: 'string', label: 'Label' },\n placeholder: { type: 'string', label: 'Placeholder' },\n requirement: { type: ['mandatory', 'optional'] as const, default: 'mandatory', label: 'Requirement' },\n autoComplete: {\n type: ['current-password', 'new-password'] as const,\n default: 'current-password',\n label: 'Autocomplete',\n },\n showPasswordLabel: { type: 'string', label: 'Show password label' },\n hidePasswordLabel: { type: 'string', label: 'Hide password label' },\n disabled: { type: 'boolean', default: false, label: 'Disabled' },\n },\n guideline:\n 'Presentational password input with a show/hide reveal toggle. Set autoComplete=\"new-password\" for recovery/set-password screens (default is \"current-password\" for sign-in). The owner passes showPasswordLabel and hidePasswordLabel already formatted; they have no default. No validation beyond presence — invalid/errorMessage are caller-driven. No data layer: does not call login, does not read session.',\n});\n\n/**\n * Composes Field + Input + Toggle + Icon into a password input with a show/hide reveal\n * toggle. Presence-only validation is caller-driven via `invalid`/`errorMessage` — this\n * particle computes no validity of its own. `revealed` is local, uncontrolled UI state.\n */\nexport function PasswordField({\n value,\n defaultValue,\n onValueChange,\n invalid = false,\n errorMessage,\n label,\n placeholder,\n requirement = 'mandatory',\n autoComplete = 'current-password',\n showPasswordLabel,\n hidePasswordLabel,\n disabled = false,\n name,\n id,\n className,\n}: Readonly<PasswordFieldProps>) {\n const [revealed, setRevealed] = useState(false);\n\n function handleChange(event: ChangeEvent<HTMLInputElement>) {\n onValueChange?.(event.target.value);\n }\n\n return (\n <Field.Root invalid={invalid} disabled={disabled} name={name} className={className} data-fs-password-field=\"\">\n {label ? <Field.Label>{label}</Field.Label> : null}\n <div data-fs-password-field-group=\"\">\n <Input\n id={id}\n type={revealed ? 'text' : 'password'}\n autoComplete={autoComplete}\n // `aria-required`, not native `required`: `Input` is a Base UI `Field.Control`, and native\n // constraint tracking would flip `aria-invalid` on its own — validity here is caller-driven.\n aria-required={requirement === 'mandatory' ? 'true' : undefined}\n spellCheck={false}\n autoCapitalize=\"off\"\n autoCorrect=\"off\"\n placeholder={placeholder}\n disabled={disabled}\n value={value}\n defaultValue={value === undefined ? defaultValue : undefined}\n onChange={handleChange}\n />\n <Toggle\n type=\"button\"\n pressed={revealed}\n onPressedChange={setRevealed}\n disabled={disabled}\n aria-label={revealed ? hidePasswordLabel : showPasswordLabel}\n data-fs-password-field-toggle=\"\"\n >\n <Icon name={revealed ? 'eye-off' : 'eye'} />\n </Toggle>\n </div>\n <Field.Error match={invalid ? true : 'customError'}>{errorMessage}</Field.Error>\n </Field.Root>\n );\n}\n"],"mappings":";;;;;;;;;;AA8BA,MAAa,0BAA0B,gBAAoC;CACzE,MAAM;CACN,YAAY;CACZ,WAAW;CACX,QAAQ;EAAE,OAAO;EAAkB,UAAU;CAAS;CACtD,QAAQ;EACN,OAAO;GAAE,MAAM;GAAU,OAAO;EAAQ;EACxC,aAAa;GAAE,MAAM;GAAU,OAAO;EAAc;EACpD,aAAa;GAAE,MAAM,CAAC,aAAa,UAAU;GAAY,SAAS;GAAa,OAAO;EAAc;EACpG,cAAc;GACZ,MAAM,CAAC,oBAAoB,cAAc;GACzC,SAAS;GACT,OAAO;EACT;EACA,mBAAmB;GAAE,MAAM;GAAU,OAAO;EAAsB;EAClE,mBAAmB;GAAE,MAAM;GAAU,OAAO;EAAsB;EAClE,UAAU;GAAE,MAAM;GAAW,SAAS;GAAO,OAAO;EAAW;CACjE;CACA,WACE;AACJ,CAAC;;;;;;AAOD,SAAgB,cAAc,EAC5B,OACA,cACA,eACA,UAAU,OACV,cACA,OACA,aACA,cAAc,aACd,eAAe,oBACf,mBACA,mBACA,WAAW,OACX,MACA,IACA,aAC+B;CAC/B,MAAM,CAAC,UAAU,eAAe,SAAS,KAAK;CAE9C,SAAS,aAAa,OAAsC;EAC1D,gBAAgB,MAAM,OAAO,KAAK;CACpC;CAEA,OACE,qBAAC,MAAM,MAAP;EAAqB;EAAmB;EAAgB;EAAiB;EAAW,0BAAuB;EAA3G,UAAA;GACG,QAAQ,oBAAC,MAAM,OAAP,EAAA,UAAc,MAAmB,CAAA,IAAI;GAC9C,qBAAC,OAAD;IAAK,gCAA6B;IAAlC,UAAA,CACE,oBAAC,OAAD;KACM;KACJ,MAAM,WAAW,SAAS;KACZ;KAGd,iBAAe,gBAAgB,cAAc,SAAS,KAAA;KACtD,YAAY;KACZ,gBAAe;KACf,aAAY;KACC;KACH;KACH;KACP,cAAc,UAAU,KAAA,IAAY,eAAe,KAAA;KACnD,UAAU;IACX,CAAA,GACD,oBAAC,QAAD;KACE,MAAK;KACL,SAAS;KACT,iBAAiB;KACP;KACV,cAAY,WAAW,oBAAoB;KAC3C,iCAA8B;KAE9B,UAAA,oBAAC,MAAD,EAAM,MAAM,WAAW,YAAY,MAAQ,CAAA;IACrC,CAAA,CACL;;GACL,oBAAC,MAAM,OAAP;IAAa,OAAO,UAAU,OAAO;IAAgB,UAAA;GAA0B,CAAA;EACrE;;AAEhB"}
@@ -19,8 +19,8 @@ export type PhoneFieldProps = {
19
19
  /** Selects the phone mask and validation rule. */
20
20
  country?: PhoneCountry;
21
21
  /**
22
- * Visible field label. No signature default (Decision 5 of the wrapped-field-particles spec) — an
23
- * omitted label falls back to the field contract's `label` when bound, and to `'Phone'` when not.
22
+ * Visible field label, formatted by the owner. No default: an omitted label falls back to the field
23
+ * contract's `label` when bound, and renders empty when not.
24
24
  */
25
25
  label?: string;
26
26
  /** Disables the field when true. Falls back to the field contract's `disabled` when bound. */
@@ -37,9 +37,9 @@ export type PhoneFieldProps = {
37
37
  * particle's internal error string.
38
38
  */
39
39
  error?: string;
40
- /** Error string shown when the input format is invalid. */
40
+ /** Error string shown when the input format is invalid, formatted by the owner. No default. */
41
41
  errorInvalid?: string;
42
- /** Error string shown when the mandatory field is left empty. */
42
+ /** Error string shown when the mandatory field is left empty, formatted by the owner. No default. */
43
43
  errorRequired?: string;
44
44
  /**
45
45
  * Raises the field to required. It only ever raises: bound to a fieldset whose rule already says
@@ -151,7 +151,6 @@ const PhoneFieldDefinition = defineComponent({
151
151
  },
152
152
  label: {
153
153
  type: "string",
154
- default: "Phone",
155
154
  label: "Label"
156
155
  },
157
156
  requirement: {
@@ -160,16 +159,14 @@ const PhoneFieldDefinition = defineComponent({
160
159
  },
161
160
  errorInvalid: {
162
161
  type: "string",
163
- default: "Invalid phone number",
164
162
  label: "Invalid error message"
165
163
  },
166
164
  errorRequired: {
167
165
  type: "string",
168
- default: "Phone number is required",
169
166
  label: "Required error message"
170
167
  }
171
168
  },
172
- guideline: "Locale-aware, business-agnostic phone number input composed from the field + input particles. Applies country masking, validates on blur, and exposes its value via onValueChange. Bind it to a data source (e.g. ClientProfilePhoneControl for checkout) to persist the value. Recomposable (RFC:503): given children, they replace the default Field.Label + PhoneFieldInput + Field.Error anatomy, in any order."
169
+ guideline: "Locale-aware, business-agnostic phone number input composed from the field + input particles. Applies country masking, validates on blur, and exposes its value via onValueChange. Bind it to a data source (e.g. ClientProfilePhoneControl for checkout) to persist the value; the owner supplies label, errorInvalid and errorRequired, which have no default. Recomposable (RFC:503): given children, they replace the default Field.Label + PhoneFieldInput + Field.Error anatomy, in any order."
173
170
  });
174
171
  /**
175
172
  * Presentational, business-agnostic phone field. Composes the `field` and `input` particles: the
@@ -275,7 +272,7 @@ function PhoneFieldView({ ref, country, className, label, isDisabled, placeholde
275
272
  })
276
273
  });
277
274
  }
278
- function UnboundPhoneField({ value, defaultValue = "", onValueChange, country = "US", label, isDisabled = false, placeholder, invalid, error, errorInvalid = "Invalid phone number", errorRequired = "Phone number is required", requirement, onBlur, className, ref, children }) {
275
+ function UnboundPhoneField({ value, defaultValue = "", onValueChange, country = "US", label, isDisabled = false, placeholder, invalid, error, errorInvalid, errorRequired, requirement, onBlur, className, ref, children }) {
279
276
  const isControlled = value !== void 0;
280
277
  const [internalRaw, setInternalRaw] = useState(defaultValue);
281
278
  const [localInvalid, setLocalInvalid] = useState(false);
@@ -288,7 +285,7 @@ function UnboundPhoneField({ value, defaultValue = "", onValueChange, country =
288
285
  }
289
286
  const rawValue = isControlled ? value : internalRaw;
290
287
  const maskedValue = applyPhoneMask(rawValue, country);
291
- const resolvedLabel = label ?? "Phone";
288
+ const resolvedLabel = label ?? "";
292
289
  const effectiveInvalid = invalid !== void 0 ? invalid : localInvalid;
293
290
  const effectiveError = error !== void 0 ? error : effectiveInvalid ? localError : "";
294
291
  function handleChange(event) {
@@ -303,11 +300,11 @@ function UnboundPhoneField({ value, defaultValue = "", onValueChange, country =
303
300
  let fieldError = "";
304
301
  if (requirement === "mandatory" && !rawValue.trim()) {
305
302
  isFieldInvalid = true;
306
- fieldError = errorRequired;
303
+ fieldError = errorRequired ?? "";
307
304
  } else if (rawValue.trim()) {
308
305
  const valid = validatePhoneNumber(rawValue, country);
309
306
  isFieldInvalid = !valid;
310
- fieldError = valid ? "" : errorInvalid;
307
+ fieldError = valid ? "" : errorInvalid ?? "";
311
308
  }
312
309
  setLocalInvalid(isFieldInvalid);
313
310
  setLocalError(fieldError);
@@ -329,10 +326,10 @@ function UnboundPhoneField({ value, defaultValue = "", onValueChange, country =
329
326
  children
330
327
  });
331
328
  }
332
- function BoundPhoneField({ value: _value, defaultValue: _defaultValue, onValueChange, country = "US", label, isDisabled, placeholder, invalid, error, errorInvalid = "Invalid phone number", errorRequired = "Phone number is required", requirement, onBlur, className, ref: callerRef, contract, children }) {
329
+ function BoundPhoneField({ value: _value, defaultValue: _defaultValue, onValueChange, country = "US", label, isDisabled, placeholder, invalid, error, errorInvalid, errorRequired, requirement, onBlur, className, ref: callerRef, contract, children }) {
333
330
  const rule = useMemo(() => mergeFieldValidator(contract.rule, "phoneFormat", (rawValue) => {
334
331
  const raw = typeof rawValue === "string" ? rawValue : String(rawValue ?? "");
335
- return !raw.trim() || validatePhoneNumber(raw, country) || errorInvalid;
332
+ return !raw.trim() || validatePhoneNumber(raw, country) || (errorInvalid ?? false);
336
333
  }), [
337
334
  contract.rule,
338
335
  errorInvalid,
@@ -346,7 +343,7 @@ function BoundPhoneField({ value: _value, defaultValue: _defaultValue, onValueCh
346
343
  const { invalid: rhfInvalid, error: rhfError } = getFieldState(contract.name, useFormState({ name: contract.name }));
347
344
  const composedRef = useComposedRef(callerRef, field.ref);
348
345
  const maskedValue = applyPhoneMask(typeof field.value === "string" ? field.value : String(field.value ?? ""), country);
349
- const resolvedLabel = label ?? contract.label ?? "Phone";
346
+ const resolvedLabel = label ?? contract.label ?? "";
350
347
  const resolvedPlaceholder = placeholder ?? contract.placeholder;
351
348
  const resolvedIsDisabled = isDisabled ?? contract.disabled ?? false;
352
349
  const effectiveInvalid = invalid !== void 0 ? invalid : rhfInvalid;
@@ -1 +1 @@
1
- {"version":3,"file":"phone-field.js","names":["BaseField"],"sources":["../../../src/particles/phone-field/phone-field.tsx"],"sourcesContent":["'use client';\nimport { Field as BaseField } from '@base-ui/react/field';\nimport { defineComponent } from '@vtex/fs-core';\nimport type { ChangeEvent, FocusEvent, ReactNode, Ref } from 'react';\nimport { createContext, useContext, useMemo, useState } from 'react';\nimport { useFormContext, useFormState } from 'react-hook-form';\nimport {\n FieldBinding,\n type FieldContract,\n type FieldRule,\n mergeFieldValidator,\n TEXT_FIELD_VALUE,\n useBoundField,\n useField,\n} from '../field/field.js';\nimport { Input } from '../input/input.js';\nimport { useComposedRef } from '../shared/compose-refs.js';\n\n// ---------------------------------------------------------------------------\n// Country masks\n// ---------------------------------------------------------------------------\n\n/**\n * Country codes supported by PhoneField.\n * Only US and BR are implemented; every other ISO-2 code falls back to the US\n * format (Gap-06 in the PhoneField spec).\n */\nexport type PhoneCountry = 'US' | 'BR';\n\n/**\n * Returns true when `value` starts with the E.164 or bare country-code prefix\n * for the given country.\n *\n * US country code: 1 → \"+1…\" or \"1…\"\n * BR country code: 55 → \"+55…\" or \"55…\"\n */\nfunction isValidCountryCode(value: string, country: PhoneCountry): boolean {\n switch (country) {\n case 'US':\n return value.startsWith('+1') || value.startsWith('1');\n case 'BR':\n return value.startsWith('+55') || value.startsWith('55');\n default:\n return false;\n }\n}\n\n/**\n * Strips phone mask formatting from `value`.\n *\n * When the raw string carries a valid country-code prefix (e.g. \"+55…\"), the\n * returned value preserves the leading \"+\" so callers can detect E.164 intent.\n * Otherwise only digits are returned.\n *\n * `removePhoneMask(applyPhoneMask(raw, country), country) === raw` for all\n * valid raw values that do NOT carry a country-code prefix.\n */\nexport function removePhoneMask(value: string, country: PhoneCountry): string {\n const onlyDigits = value.replace(/\\D/g, '');\n\n // Only treat as E.164 when the raw string explicitly carries a \"+\" prefix.\n // A bare digit string that starts with the country-code digits (e.g. \"1234567890\"\n // starting with \"1\") is a local number, not a country-code-prefixed one.\n if (value.startsWith('+') && isValidCountryCode(value, country)) {\n return `+${onlyDigits}`;\n }\n\n return onlyDigits;\n}\n\n/**\n * Formats `value` into the mask pattern for `country`, applying as many mask\n * characters as the digit count allows (progressive masking while typing).\n *\n * US: (123) 456-7890 or +1 (123) 456-7890\n * BR: (11) 99999-9999 or +55 (11) 99999-9999\n *\n * Non-US/BR countries fall back to the US mask.\n */\nexport function applyPhoneMask(value: string, country: PhoneCountry): string {\n switch (country) {\n case 'US':\n return applyUSPhoneMask(value);\n case 'BR':\n return applyBRPhoneMask(value);\n default:\n return applyUSPhoneMask(value);\n }\n}\n\nfunction applyUSPhoneMask(value: string): string {\n const onlyDigits = value.replace(/\\D/g, '');\n\n // E.164 with explicit \"+\" prefix and full country code\n if (value.startsWith('+1') && onlyDigits.length >= 11) {\n const local = value.replace('+1', '').replace(/\\D/g, '');\n return `+1 ${formatUSNumber(local)}`;\n }\n\n // Bare country-code prefix (e.g. \"11234567890\")\n if (onlyDigits.startsWith('1') && onlyDigits.length === 11) {\n return `+1 ${formatUSNumber(onlyDigits.substring(1))}`;\n }\n\n return formatUSNumber(onlyDigits);\n}\n\nfunction formatUSNumber(digits: string): string {\n // US local numbers cap at 10 digits — drop the overflow instead of growing the mask unbounded.\n const local = digits.slice(0, 10);\n if (local.length === 0) return '';\n if (local.length <= 3) return `(${local}`;\n if (local.length <= 6) return `(${local.slice(0, 3)}) ${local.slice(3)}`;\n return `(${local.slice(0, 3)}) ${local.slice(3, 6)}-${local.slice(6)}`;\n}\n\nfunction applyBRPhoneMask(value: string): string {\n const onlyDigits = value.replace(/\\D/g, '');\n\n // E.164 with explicit \"+55\" prefix. 12 digits is a landline (+55 + 10 local),\n // 13 is a mobile (+55 + 11 local); both strip the \"55\" country code.\n if (value.startsWith('+55') && onlyDigits.length >= 12) {\n const local = value.replace('+55', '').replace(/\\D/g, '');\n return `+55 ${formatBRNumber(local)}`;\n }\n\n // Bare country-code prefix (e.g. \"5511999998888\" mobile, \"551133334444\" landline)\n if (onlyDigits.startsWith('55') && (onlyDigits.length === 12 || onlyDigits.length === 13)) {\n return `+55 ${formatBRNumber(onlyDigits.substring(2))}`;\n }\n\n return formatBRNumber(onlyDigits);\n}\n\nfunction formatBRNumber(digits: string): string {\n // BR local numbers cap at 11 digits (mobile) — drop the overflow instead of growing the mask unbounded.\n const local = digits.slice(0, 11);\n if (local.length === 0) return '';\n if (local.length <= 2) return `(${local}`;\n if (local.length <= 6) return `(${local.slice(0, 2)}) ${local.slice(2)}`;\n // 7-10 digits: landline format (XX) XXXX-XXXX\n if (local.length <= 10) return `(${local.slice(0, 2)}) ${local.slice(2, 6)}-${local.slice(6)}`;\n // 11 digits: mobile format (XX) XXXXX-XXXX\n return `(${local.slice(0, 2)}) ${local.slice(2, 7)}-${local.slice(7)}`;\n}\n\n// ---------------------------------------------------------------------------\n// Validation\n// ---------------------------------------------------------------------------\n\n/**\n * BR local part: 10 digits is a landline; 11 digits is a mobile, which must carry the mandatory\n * ninth digit \"9\" right after the two-digit DDD (the `phone` library rule the spec's Gap-05\n * reimplements — \"11899998888\" is mobile-shaped but not a real BR number).\n */\nfunction isValidBRLocal(digits: string): boolean {\n if (digits.length === 10) return true;\n return digits.length === 11 && digits[2] === '9';\n}\n\n/**\n * Validates a raw (unmasked) phone number string for the given country.\n *\n * NOTE: The spec (KD-3) calls for using the `phone` npm library for validation.\n * The library is listed in Gap-05 as a new dependency to add when available.\n * Until that dependency is installed, this implements an equivalent\n * digit-count validation that covers all spec key-scenarios for US and BR.\n * Country-code and non-country-code inputs are both handled.\n *\n * US valid forms:\n * - 10 digits (local, e.g. \"1234567890\")\n * - 11 raw digits with country code \"1\" (e.g. \"11234567890\")\n * - E.164 \"+1\" + 10 digits (e.g. \"+11234567890\")\n *\n * BR valid forms:\n * - 10 digits (landline, e.g. \"1133334444\")\n * - 11 digits (mobile, e.g. \"11999998888\"; the ninth digit after the DDD must be \"9\")\n * - E.164 \"+55\" + 10 or 11 digits (e.g. \"+5511999998888\")\n */\nexport function validatePhoneNumber(input: string, country: PhoneCountry): boolean {\n if (!input || !input.trim()) return false;\n\n const digits = input.replace(/\\D/g, '');\n\n if (isValidCountryCode(input, country)) {\n // Country-code branch: validate digit count including the country code digits.\n if (country === 'US') {\n // \"+1\" or \"1\" prefix + exactly 10 local digits = 11 raw digits\n if (digits.length === 11) return true;\n // Fall through: could be a 10-digit local number that starts with \"1\"\n } else {\n // BR: \"+55\" or \"55\" prefix + 10 or 11 local digits = 12 or 13 raw digits\n if (digits.length === 12 || digits.length === 13) return isValidBRLocal(digits.slice(2));\n // Fall through: could be local digits that happen to start with \"55\"\n }\n }\n\n // Local (no country code) validation\n if (country === 'US') {\n return digits.length === 10;\n }\n\n return isValidBRLocal(digits);\n}\n\n/**\n * Normalizes a valid raw phone value to E.164 for persistence (legacy checkout parity): the\n * particle emits local digits (\"2015551234\") or a \"+\"-prefixed string; the profile stores\n * \"+12015551234\". Only call this on values `validatePhoneNumber` has already accepted — shared by\n * every binding that persists a phone value (`ClientProfilePhoneControl`, `ClientProfileFieldset`)\n * so there is exactly one normalization implementation.\n */\nexport function toE164(raw: string, country: PhoneCountry): string {\n const unmasked = removePhoneMask(raw, country);\n if (unmasked.startsWith('+')) return unmasked;\n const code = country === 'BR' ? '55' : '1';\n const localMax = country === 'BR' ? 11 : 10;\n // A bare country-code prefix (\"12015551234\", \"5511999998888\") only needs the \"+\".\n return unmasked.startsWith(code) && unmasked.length > localMax ? `+${unmasked}` : `+${code}${unmasked}`;\n}\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ntype PhoneFieldRequirement = 'mandatory' | 'optional';\n\nexport type PhoneFieldProps = {\n /** Controlled raw (unmasked) phone value. Unused on the bound path — react-hook-form owns the value. */\n value?: string;\n /** Uncontrolled initial raw value. Unused on the bound path — the field contract's `defaultValue` seeds it instead. */\n defaultValue?: string;\n /** Called with the raw (unmasked) value on every change. */\n onValueChange?: (value: string) => void;\n /** Selects the phone mask and validation rule. */\n country?: PhoneCountry;\n /**\n * Visible field label. No signature default (Decision 5 of the wrapped-field-particles spec) — an\n * omitted label falls back to the field contract's `label` when bound, and to `'Phone'` when not.\n */\n label?: string;\n /** Disables the field when true. Falls back to the field contract's `disabled` when bound. */\n isDisabled?: boolean;\n /** Input placeholder text. Falls back to the field contract's `placeholder` when bound. */\n placeholder?: string;\n /**\n * Externally-controlled invalid state. When provided, overrides the\n * particle's internal blur-triggered validation result.\n */\n invalid?: boolean;\n /**\n * Externally-supplied error message. When provided, overrides the\n * particle's internal error string.\n */\n error?: string;\n /** Error string shown when the input format is invalid. */\n errorInvalid?: string;\n /** Error string shown when the mandatory field is left empty. */\n errorRequired?: string;\n /**\n * Raises the field to required. It only ever raises: bound to a fieldset whose rule already says\n * required, `'optional'` does not lower it.\n *\n * - `'mandatory'`: empty input blocks submission.\n * - `'optional'`: empty input is allowed; format is still checked when a\n * value is present.\n * - unset: no opinion, so a phone with no baseline is optional.\n */\n requirement?: PhoneFieldRequirement;\n /** Called after the field loses focus (post-validation). */\n onBlur?: () => void;\n /** Additional class applied to the root element. */\n className?: string;\n /**\n * Lands on the masked `<input type=\"tel\">` the particle renders. Composed with react-hook-form's own\n * ref on the bound path — a caller ref and react-hook-form's ref are both honoured.\n */\n ref?: Ref<HTMLInputElement>;\n /**\n * Given, replaces the default `Field.Label` + `PhoneFieldInput` + `Field.Error` anatomy — any order,\n * any subset. `PhoneFieldInput` is the one part that carries the mask, the composed ref and the\n * particle's own value/handlers; a composed generic `Field.Control` would call `useController` a\n * second time for the same name (RFC's named, accepted double-binder hole).\n */\n children?: ReactNode;\n};\n\n// ---------------------------------------------------------------------------\n// Definition\n// ---------------------------------------------------------------------------\n\nexport const PhoneFieldDefinition = defineComponent<PhoneFieldProps>({\n name: 'PhoneField',\n importPath: '@vtex/faststore/components',\n component: PhoneField,\n providesContext: 'phone-field',\n editor: { label: 'Phone Field', category: 'action' },\n schema: {\n country: { type: 'string', default: 'US', label: 'Country (US or BR)' },\n label: { type: 'string', default: 'Phone', label: 'Label' },\n // No default: an unset requirement is no opinion, not a raise to mandatory.\n requirement: { type: ['mandatory', 'optional'] as const, label: 'Requirement' },\n errorInvalid: { type: 'string', default: 'Invalid phone number', label: 'Invalid error message' },\n errorRequired: { type: 'string', default: 'Phone number is required', label: 'Required error message' },\n },\n guideline:\n 'Locale-aware, business-agnostic phone number input composed from the field + input particles. Applies country masking, validates on blur, and exposes its value via onValueChange. Bind it to a data source (e.g. ClientProfilePhoneControl for checkout) to persist the value. Recomposable (RFC:503): given children, they replace the default Field.Label + PhoneFieldInput + Field.Error anatomy, in any order.',\n});\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\n/**\n * Presentational, business-agnostic phone field. Composes the `field` and `input` particles: the\n * `Field.Root` owns the invalid/disabled state and the `Field.Error match` slot, while the `Input`\n * particle renders the masked `<tel>` control. The particle stays reusable (checkout binding today,\n * MyAccount / extensions later); a binding owns the data source and persistence.\n *\n * US/BR masking, blur validation, and the `data-fs-phone-field*` attributes (plus the country variant\n * attribute) are kept; error strings remain props (a documented i18n divergence — the country tables\n * are internal, the copy is owner-supplied).\n *\n * Reads the field contract through `useField()` and `useFormContext()` and dispatches to a bound or an\n * unbound sub-component — \"bound\" means both are present. Every react-hook-form hook lives in\n * `BoundPhoneField`, so hook order never changes under a mounted component. Both sub-components render\n * the same `PhoneFieldView`, so the two paths cannot drift into different DOM.\n */\nexport function PhoneField({ requirement, ...props }: PhoneFieldProps): ReactNode {\n const contract = useField();\n const formContext = useFormContext();\n\n if (contract && formContext) {\n return <BoundPhoneField {...props} requirement={requirement} contract={contract} />;\n }\n\n return <UnboundPhoneField {...props} requirement={requirement} />;\n}\n\n// ---------------------------------------------------------------------------\n// Input part — catalogued, placeable (Decision 4). Carries the mask, the composed ref, and the\n// particle's own onChange/onBlur; a generic Field.Control cannot be this part, because the mask and\n// the country/requirement validator belong to PhoneField, not to react-hook-form's own registration.\n// ---------------------------------------------------------------------------\n\ntype PhoneFieldInputContextValue = {\n ref?: Ref<HTMLInputElement>;\n value: string;\n placeholder?: string;\n /** Resolved by the binder, threaded here because this part is not the one that binds. */\n required: boolean;\n onChange: (event: ChangeEvent<HTMLInputElement>) => void;\n onBlur: (event: FocusEvent<HTMLInputElement>) => void;\n};\n\nconst PhoneFieldInputContext = createContext<PhoneFieldInputContextValue | null>(null);\n\nfunction usePhoneFieldInputContext(): PhoneFieldInputContextValue {\n const context = useContext(PhoneFieldInputContext);\n if (!context) {\n throw new Error('PhoneFieldInput must be a descendant of PhoneField.');\n }\n return context;\n}\n\nexport type PhoneFieldInputProps = { className?: string };\n\nexport const PhoneFieldInputDefinition = defineComponent<PhoneFieldInputProps>({\n name: 'PhoneFieldInput',\n importPath: '@vtex/faststore/components',\n component: PhoneFieldInput,\n requiresContext: 'phone-field',\n editor: { label: 'Phone Field Input', category: 'action' },\n schema: {},\n guideline:\n \"The masked <input type=\\\"tel\\\"> PhoneField owns. Must sit inside PhoneField, in either the default anatomy or an author's composed children. Carries the country mask, the composed ref, and PhoneField's own onChange/onBlur — a composed Field.Control here instead re-registers the field with react-hook-form and loses the mask (unsupported, RFC's named double-binder hole).\",\n});\n\n/** Renders the masked `<input>`, reading its value/handlers/ref from the enclosing `PhoneField`. */\nexport function PhoneFieldInput({ className }: PhoneFieldInputProps): ReactNode {\n const { ref, value, placeholder, required, onChange, onBlur } = usePhoneFieldInputContext();\n\n return (\n <Input\n ref={ref}\n data-fs-phone-field-input=\"\"\n type=\"tel\"\n inputMode=\"numeric\"\n // `aria-required`, not native `required`, for the reason password-field.tsx:89-91 records:\n // `Input` is a Base UI `Field.Control`, and native constraint tracking would flip\n // `aria-invalid` on its own, ahead of react-hook-form's own validation.\n aria-required={required || undefined}\n value={value}\n onChange={onChange}\n onBlur={onBlur}\n placeholder={placeholder}\n className={className}\n />\n );\n}\n\n// ---------------------------------------------------------------------------\n// Shared view — identical DOM whether bound or unbound\n// ---------------------------------------------------------------------------\n\ntype PhoneFieldViewProps = {\n ref?: Ref<HTMLInputElement>;\n country: PhoneCountry;\n className?: string;\n label: string;\n isDisabled: boolean;\n placeholder?: string;\n required: boolean;\n maskedValue: string;\n effectiveInvalid: boolean;\n effectiveError: string;\n onChange: (event: ChangeEvent<HTMLInputElement>) => void;\n onBlur: (event: FocusEvent<HTMLInputElement>) => void;\n children?: ReactNode;\n};\n\nfunction PhoneFieldView({\n ref,\n country,\n className,\n label,\n isDisabled,\n placeholder,\n required,\n maskedValue,\n effectiveInvalid,\n effectiveError,\n onChange,\n onBlur,\n children,\n}: PhoneFieldViewProps) {\n const inputContext = useMemo<PhoneFieldInputContextValue>(\n () => ({ ref, value: maskedValue, placeholder, required, onChange, onBlur }),\n [ref, maskedValue, placeholder, required, onChange, onBlur],\n );\n\n return (\n // Deliberately the RAW Base UI Field primitives, not this package's own Field.Root/Label/Error\n // wrapper, for the default anatomy: this reproduces exactly what rendered before Decision 3\n // (when FieldContractBoundary shielded this subtree from the ambient contract) — the resolved\n // `label`/`effectiveError` text renders unconditionally, and Field.Root's own dirty/touched\n // fallback tracking stays in charge, rather than react-hook-form's. Composed children, below,\n // use the package's own Field.* parts on purpose — that is what makes a childless Field.Label /\n // Field.Error resolve real text (FR-5).\n <BaseField.Root\n data-fs-phone-field-root=\"\"\n data-fs-phone-field-root-country={country}\n data-fs-field-root=\"\"\n className={className}\n invalid={effectiveInvalid}\n disabled={isDisabled}\n >\n <PhoneFieldInputContext.Provider value={inputContext}>\n {children ?? (\n <>\n <BaseField.Label data-fs-phone-field-label=\"\" data-fs-field-label=\"\">\n {label}\n </BaseField.Label>\n <PhoneFieldInput />\n {effectiveError ? (\n <BaseField.Error match data-fs-phone-field-error=\"\" data-fs-field-error=\"\">\n {effectiveError}\n </BaseField.Error>\n ) : null}\n </>\n )}\n </PhoneFieldInputContext.Provider>\n </BaseField.Root>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Unbound — today's body, moved verbatim\n// ---------------------------------------------------------------------------\n\ntype UnboundPhoneFieldProps = PhoneFieldProps;\n\nfunction UnboundPhoneField({\n value,\n defaultValue = '',\n onValueChange,\n country = 'US',\n label,\n isDisabled = false,\n placeholder,\n invalid,\n error,\n errorInvalid = 'Invalid phone number',\n errorRequired = 'Phone number is required',\n requirement,\n onBlur,\n className,\n ref,\n children,\n}: UnboundPhoneFieldProps) {\n const isControlled = value !== undefined;\n\n const [internalRaw, setInternalRaw] = useState(defaultValue);\n const [localInvalid, setLocalInvalid] = useState(false);\n const [localError, setLocalError] = useState('');\n\n // Clear local validation state when country changes so the next blur re-validates against the new\n // country's rules. The comparison baseline lives in state, not a ref, and the compare-and-set runs\n // during render (before paint), so a render React abandons without committing — a suspended\n // transition, a Suspense retry — never leaves a stale baseline behind the way a ref write would.\n const [prevCountry, setPrevCountry] = useState(country);\n if (prevCountry !== country) {\n setPrevCountry(country);\n setLocalInvalid(false);\n setLocalError('');\n }\n\n const rawValue = isControlled ? (value as string) : internalRaw;\n const maskedValue = applyPhoneMask(rawValue, country);\n const resolvedLabel = label ?? 'Phone';\n\n // External props take precedence over internal validation state.\n // When `invalid` is externally controlled, the error display is also fully\n // controlled: use the explicit `error` prop, or fall back to empty string so\n // no stale local error leaks through when the parent says the field is valid.\n const effectiveInvalid = invalid !== undefined ? invalid : localInvalid;\n const effectiveError = error !== undefined ? error : effectiveInvalid ? localError : '';\n\n function handleChange(event: ChangeEvent<HTMLInputElement>) {\n if (isDisabled) return;\n const raw = removePhoneMask(event.target.value, country);\n if (!isControlled) {\n setInternalRaw(raw);\n }\n onValueChange?.(raw);\n }\n\n function handleBlur(_event: FocusEvent<HTMLInputElement>) {\n if (isDisabled) return;\n\n let isFieldInvalid = false;\n let fieldError = '';\n\n if (requirement === 'mandatory' && !rawValue.trim()) {\n isFieldInvalid = true;\n fieldError = errorRequired;\n } else if (rawValue.trim()) {\n const valid = validatePhoneNumber(rawValue, country);\n isFieldInvalid = !valid;\n fieldError = valid ? '' : errorInvalid;\n }\n // optional + empty → no error, keep isFieldInvalid = false / fieldError = ''\n\n setLocalInvalid(isFieldInvalid);\n setLocalError(fieldError);\n onBlur?.();\n }\n\n return (\n <PhoneFieldView\n ref={ref}\n country={country}\n className={className}\n label={resolvedLabel}\n isDisabled={isDisabled}\n placeholder={placeholder}\n required={requirement === 'mandatory'}\n maskedValue={maskedValue}\n effectiveInvalid={effectiveInvalid}\n effectiveError={effectiveError}\n onChange={handleChange}\n onBlur={handleBlur}\n >\n {children}\n </PhoneFieldView>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Bound — reads the field contract, binds through useController\n// ---------------------------------------------------------------------------\n\ntype BoundPhoneFieldProps = UnboundPhoneFieldProps & { contract: FieldContract };\n\nfunction BoundPhoneField({\n value: _value,\n defaultValue: _defaultValue,\n onValueChange,\n country = 'US',\n label,\n isDisabled,\n placeholder,\n invalid,\n error,\n errorInvalid = 'Invalid phone number',\n errorRequired = 'Phone number is required',\n requirement,\n onBlur,\n className,\n ref: callerRef,\n contract,\n children,\n}: BoundPhoneFieldProps) {\n // Format only. Requiredness is not decided here: `useBoundField` resolves it from the fieldset's\n // baseline and the raise below, and installs the blank check, so the announcement and the\n // validation cannot disagree. The check composes alongside whatever the fieldset validates —\n // before this merge, any contract validator discarded the particle's own validation whole.\n const rule = useMemo<FieldRule>(\n () =>\n mergeFieldValidator(contract.rule, 'phoneFormat', (rawValue) => {\n const raw = typeof rawValue === 'string' ? rawValue : String(rawValue ?? '');\n return !raw.trim() || validatePhoneNumber(raw, country) || errorInvalid;\n }),\n [contract.rule, errorInvalid, country],\n );\n\n const field = useBoundField(contract, TEXT_FIELD_VALUE, rule, {\n required: requirement === 'mandatory',\n message: errorRequired,\n });\n const { getFieldState } = useFormContext();\n const { invalid: rhfInvalid, error: rhfError } = getFieldState(contract.name, useFormState({ name: contract.name }));\n\n const composedRef = useComposedRef<HTMLInputElement>(callerRef, field.ref);\n\n const rawValue = typeof field.value === 'string' ? field.value : String(field.value ?? '');\n const maskedValue = applyPhoneMask(rawValue, country);\n const resolvedLabel = label ?? contract.label ?? 'Phone';\n const resolvedPlaceholder = placeholder ?? contract.placeholder;\n const resolvedIsDisabled = isDisabled ?? contract.disabled ?? false;\n\n const effectiveInvalid = invalid !== undefined ? invalid : rhfInvalid;\n const effectiveError = error !== undefined ? error : effectiveInvalid ? (rhfError?.message ?? '') : '';\n\n function handleChange(event: ChangeEvent<HTMLInputElement>) {\n const raw = removePhoneMask(event.target.value, country);\n field.onChange(raw);\n onValueChange?.(raw);\n }\n\n function handleBlur(_event: FocusEvent<HTMLInputElement>) {\n field.onBlur();\n onBlur?.();\n }\n\n return (\n // Decision 3: replaces the empty-contract FieldContractBoundary with a re-provided contract\n // carrying the RESOLVED name/label/placeholder — the values a composed childless Field.Label /\n // Field.Error actually need, as opposed to the raw (possibly-undefined) ones the ambient\n // contract from the enclosing FieldBinding carries. useBoundField above remains the sole binder\n // for contract.name; this FieldBinding never registers anything itself.\n <FieldBinding\n name={contract.name}\n label={resolvedLabel}\n placeholder={resolvedPlaceholder}\n defaultValue={contract.defaultValue}\n rule={contract.rule}\n options={contract.options}\n disabled={resolvedIsDisabled}\n readOnly={contract.readOnly}\n autoComplete={contract.autoComplete}\n inputMode={contract.inputMode}\n >\n <PhoneFieldView\n ref={composedRef}\n country={country}\n className={className}\n label={resolvedLabel}\n isDisabled={resolvedIsDisabled}\n placeholder={resolvedPlaceholder}\n required={field.required}\n maskedValue={maskedValue}\n effectiveInvalid={effectiveInvalid}\n effectiveError={effectiveError}\n onChange={handleChange}\n onBlur={handleBlur}\n >\n {children}\n </PhoneFieldView>\n </FieldBinding>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"phone-field.js","names":["BaseField"],"sources":["../../../src/particles/phone-field/phone-field.tsx"],"sourcesContent":["'use client';\nimport { Field as BaseField } from '@base-ui/react/field';\nimport { defineComponent } from '@vtex/fs-core';\nimport type { ChangeEvent, FocusEvent, ReactNode, Ref } from 'react';\nimport { createContext, useContext, useMemo, useState } from 'react';\nimport { useFormContext, useFormState } from 'react-hook-form';\nimport {\n FieldBinding,\n type FieldContract,\n type FieldRule,\n mergeFieldValidator,\n TEXT_FIELD_VALUE,\n useBoundField,\n useField,\n} from '../field/field.js';\nimport { Input } from '../input/input.js';\nimport { useComposedRef } from '../shared/compose-refs.js';\n\n// ---------------------------------------------------------------------------\n// Country masks\n// ---------------------------------------------------------------------------\n\n/**\n * Country codes supported by PhoneField.\n * Only US and BR are implemented; every other ISO-2 code falls back to the US\n * format (Gap-06 in the PhoneField spec).\n */\nexport type PhoneCountry = 'US' | 'BR';\n\n/**\n * Returns true when `value` starts with the E.164 or bare country-code prefix\n * for the given country.\n *\n * US country code: 1 → \"+1…\" or \"1…\"\n * BR country code: 55 → \"+55…\" or \"55…\"\n */\nfunction isValidCountryCode(value: string, country: PhoneCountry): boolean {\n switch (country) {\n case 'US':\n return value.startsWith('+1') || value.startsWith('1');\n case 'BR':\n return value.startsWith('+55') || value.startsWith('55');\n default:\n return false;\n }\n}\n\n/**\n * Strips phone mask formatting from `value`.\n *\n * When the raw string carries a valid country-code prefix (e.g. \"+55…\"), the\n * returned value preserves the leading \"+\" so callers can detect E.164 intent.\n * Otherwise only digits are returned.\n *\n * `removePhoneMask(applyPhoneMask(raw, country), country) === raw` for all\n * valid raw values that do NOT carry a country-code prefix.\n */\nexport function removePhoneMask(value: string, country: PhoneCountry): string {\n const onlyDigits = value.replace(/\\D/g, '');\n\n // Only treat as E.164 when the raw string explicitly carries a \"+\" prefix.\n // A bare digit string that starts with the country-code digits (e.g. \"1234567890\"\n // starting with \"1\") is a local number, not a country-code-prefixed one.\n if (value.startsWith('+') && isValidCountryCode(value, country)) {\n return `+${onlyDigits}`;\n }\n\n return onlyDigits;\n}\n\n/**\n * Formats `value` into the mask pattern for `country`, applying as many mask\n * characters as the digit count allows (progressive masking while typing).\n *\n * US: (123) 456-7890 or +1 (123) 456-7890\n * BR: (11) 99999-9999 or +55 (11) 99999-9999\n *\n * Non-US/BR countries fall back to the US mask.\n */\nexport function applyPhoneMask(value: string, country: PhoneCountry): string {\n switch (country) {\n case 'US':\n return applyUSPhoneMask(value);\n case 'BR':\n return applyBRPhoneMask(value);\n default:\n return applyUSPhoneMask(value);\n }\n}\n\nfunction applyUSPhoneMask(value: string): string {\n const onlyDigits = value.replace(/\\D/g, '');\n\n // E.164 with explicit \"+\" prefix and full country code\n if (value.startsWith('+1') && onlyDigits.length >= 11) {\n const local = value.replace('+1', '').replace(/\\D/g, '');\n return `+1 ${formatUSNumber(local)}`;\n }\n\n // Bare country-code prefix (e.g. \"11234567890\")\n if (onlyDigits.startsWith('1') && onlyDigits.length === 11) {\n return `+1 ${formatUSNumber(onlyDigits.substring(1))}`;\n }\n\n return formatUSNumber(onlyDigits);\n}\n\nfunction formatUSNumber(digits: string): string {\n // US local numbers cap at 10 digits — drop the overflow instead of growing the mask unbounded.\n const local = digits.slice(0, 10);\n if (local.length === 0) return '';\n if (local.length <= 3) return `(${local}`;\n if (local.length <= 6) return `(${local.slice(0, 3)}) ${local.slice(3)}`;\n return `(${local.slice(0, 3)}) ${local.slice(3, 6)}-${local.slice(6)}`;\n}\n\nfunction applyBRPhoneMask(value: string): string {\n const onlyDigits = value.replace(/\\D/g, '');\n\n // E.164 with explicit \"+55\" prefix. 12 digits is a landline (+55 + 10 local),\n // 13 is a mobile (+55 + 11 local); both strip the \"55\" country code.\n if (value.startsWith('+55') && onlyDigits.length >= 12) {\n const local = value.replace('+55', '').replace(/\\D/g, '');\n return `+55 ${formatBRNumber(local)}`;\n }\n\n // Bare country-code prefix (e.g. \"5511999998888\" mobile, \"551133334444\" landline)\n if (onlyDigits.startsWith('55') && (onlyDigits.length === 12 || onlyDigits.length === 13)) {\n return `+55 ${formatBRNumber(onlyDigits.substring(2))}`;\n }\n\n return formatBRNumber(onlyDigits);\n}\n\nfunction formatBRNumber(digits: string): string {\n // BR local numbers cap at 11 digits (mobile) — drop the overflow instead of growing the mask unbounded.\n const local = digits.slice(0, 11);\n if (local.length === 0) return '';\n if (local.length <= 2) return `(${local}`;\n if (local.length <= 6) return `(${local.slice(0, 2)}) ${local.slice(2)}`;\n // 7-10 digits: landline format (XX) XXXX-XXXX\n if (local.length <= 10) return `(${local.slice(0, 2)}) ${local.slice(2, 6)}-${local.slice(6)}`;\n // 11 digits: mobile format (XX) XXXXX-XXXX\n return `(${local.slice(0, 2)}) ${local.slice(2, 7)}-${local.slice(7)}`;\n}\n\n// ---------------------------------------------------------------------------\n// Validation\n// ---------------------------------------------------------------------------\n\n/**\n * BR local part: 10 digits is a landline; 11 digits is a mobile, which must carry the mandatory\n * ninth digit \"9\" right after the two-digit DDD (the `phone` library rule the spec's Gap-05\n * reimplements — \"11899998888\" is mobile-shaped but not a real BR number).\n */\nfunction isValidBRLocal(digits: string): boolean {\n if (digits.length === 10) return true;\n return digits.length === 11 && digits[2] === '9';\n}\n\n/**\n * Validates a raw (unmasked) phone number string for the given country.\n *\n * NOTE: The spec (KD-3) calls for using the `phone` npm library for validation.\n * The library is listed in Gap-05 as a new dependency to add when available.\n * Until that dependency is installed, this implements an equivalent\n * digit-count validation that covers all spec key-scenarios for US and BR.\n * Country-code and non-country-code inputs are both handled.\n *\n * US valid forms:\n * - 10 digits (local, e.g. \"1234567890\")\n * - 11 raw digits with country code \"1\" (e.g. \"11234567890\")\n * - E.164 \"+1\" + 10 digits (e.g. \"+11234567890\")\n *\n * BR valid forms:\n * - 10 digits (landline, e.g. \"1133334444\")\n * - 11 digits (mobile, e.g. \"11999998888\"; the ninth digit after the DDD must be \"9\")\n * - E.164 \"+55\" + 10 or 11 digits (e.g. \"+5511999998888\")\n */\nexport function validatePhoneNumber(input: string, country: PhoneCountry): boolean {\n if (!input || !input.trim()) return false;\n\n const digits = input.replace(/\\D/g, '');\n\n if (isValidCountryCode(input, country)) {\n // Country-code branch: validate digit count including the country code digits.\n if (country === 'US') {\n // \"+1\" or \"1\" prefix + exactly 10 local digits = 11 raw digits\n if (digits.length === 11) return true;\n // Fall through: could be a 10-digit local number that starts with \"1\"\n } else {\n // BR: \"+55\" or \"55\" prefix + 10 or 11 local digits = 12 or 13 raw digits\n if (digits.length === 12 || digits.length === 13) return isValidBRLocal(digits.slice(2));\n // Fall through: could be local digits that happen to start with \"55\"\n }\n }\n\n // Local (no country code) validation\n if (country === 'US') {\n return digits.length === 10;\n }\n\n return isValidBRLocal(digits);\n}\n\n/**\n * Normalizes a valid raw phone value to E.164 for persistence (legacy checkout parity): the\n * particle emits local digits (\"2015551234\") or a \"+\"-prefixed string; the profile stores\n * \"+12015551234\". Only call this on values `validatePhoneNumber` has already accepted — shared by\n * every binding that persists a phone value (`ClientProfilePhoneControl`, `ClientProfileFieldset`)\n * so there is exactly one normalization implementation.\n */\nexport function toE164(raw: string, country: PhoneCountry): string {\n const unmasked = removePhoneMask(raw, country);\n if (unmasked.startsWith('+')) return unmasked;\n const code = country === 'BR' ? '55' : '1';\n const localMax = country === 'BR' ? 11 : 10;\n // A bare country-code prefix (\"12015551234\", \"5511999998888\") only needs the \"+\".\n return unmasked.startsWith(code) && unmasked.length > localMax ? `+${unmasked}` : `+${code}${unmasked}`;\n}\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ntype PhoneFieldRequirement = 'mandatory' | 'optional';\n\nexport type PhoneFieldProps = {\n /** Controlled raw (unmasked) phone value. Unused on the bound path — react-hook-form owns the value. */\n value?: string;\n /** Uncontrolled initial raw value. Unused on the bound path — the field contract's `defaultValue` seeds it instead. */\n defaultValue?: string;\n /** Called with the raw (unmasked) value on every change. */\n onValueChange?: (value: string) => void;\n /** Selects the phone mask and validation rule. */\n country?: PhoneCountry;\n /**\n * Visible field label, formatted by the owner. No default: an omitted label falls back to the field\n * contract's `label` when bound, and renders empty when not.\n */\n label?: string;\n /** Disables the field when true. Falls back to the field contract's `disabled` when bound. */\n isDisabled?: boolean;\n /** Input placeholder text. Falls back to the field contract's `placeholder` when bound. */\n placeholder?: string;\n /**\n * Externally-controlled invalid state. When provided, overrides the\n * particle's internal blur-triggered validation result.\n */\n invalid?: boolean;\n /**\n * Externally-supplied error message. When provided, overrides the\n * particle's internal error string.\n */\n error?: string;\n /** Error string shown when the input format is invalid, formatted by the owner. No default. */\n errorInvalid?: string;\n /** Error string shown when the mandatory field is left empty, formatted by the owner. No default. */\n errorRequired?: string;\n /**\n * Raises the field to required. It only ever raises: bound to a fieldset whose rule already says\n * required, `'optional'` does not lower it.\n *\n * - `'mandatory'`: empty input blocks submission.\n * - `'optional'`: empty input is allowed; format is still checked when a\n * value is present.\n * - unset: no opinion, so a phone with no baseline is optional.\n */\n requirement?: PhoneFieldRequirement;\n /** Called after the field loses focus (post-validation). */\n onBlur?: () => void;\n /** Additional class applied to the root element. */\n className?: string;\n /**\n * Lands on the masked `<input type=\"tel\">` the particle renders. Composed with react-hook-form's own\n * ref on the bound path — a caller ref and react-hook-form's ref are both honoured.\n */\n ref?: Ref<HTMLInputElement>;\n /**\n * Given, replaces the default `Field.Label` + `PhoneFieldInput` + `Field.Error` anatomy — any order,\n * any subset. `PhoneFieldInput` is the one part that carries the mask, the composed ref and the\n * particle's own value/handlers; a composed generic `Field.Control` would call `useController` a\n * second time for the same name (RFC's named, accepted double-binder hole).\n */\n children?: ReactNode;\n};\n\n// ---------------------------------------------------------------------------\n// Definition\n// ---------------------------------------------------------------------------\n\nexport const PhoneFieldDefinition = defineComponent<PhoneFieldProps>({\n name: 'PhoneField',\n importPath: '@vtex/faststore/components',\n component: PhoneField,\n providesContext: 'phone-field',\n editor: { label: 'Phone Field', category: 'action' },\n schema: {\n country: { type: 'string', default: 'US', label: 'Country (US or BR)' },\n // Copy props carry no default: the owner formats them from its own message fields.\n label: { type: 'string', label: 'Label' },\n // No default: an unset requirement is no opinion, not a raise to mandatory.\n requirement: { type: ['mandatory', 'optional'] as const, label: 'Requirement' },\n errorInvalid: { type: 'string', label: 'Invalid error message' },\n errorRequired: { type: 'string', label: 'Required error message' },\n },\n guideline:\n 'Locale-aware, business-agnostic phone number input composed from the field + input particles. Applies country masking, validates on blur, and exposes its value via onValueChange. Bind it to a data source (e.g. ClientProfilePhoneControl for checkout) to persist the value; the owner supplies label, errorInvalid and errorRequired, which have no default. Recomposable (RFC:503): given children, they replace the default Field.Label + PhoneFieldInput + Field.Error anatomy, in any order.',\n});\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\n/**\n * Presentational, business-agnostic phone field. Composes the `field` and `input` particles: the\n * `Field.Root` owns the invalid/disabled state and the `Field.Error match` slot, while the `Input`\n * particle renders the masked `<tel>` control. The particle stays reusable (checkout binding today,\n * MyAccount / extensions later); a binding owns the data source and persistence.\n *\n * US/BR masking, blur validation, and the `data-fs-phone-field*` attributes (plus the country variant\n * attribute) are kept; error strings remain props (a documented i18n divergence — the country tables\n * are internal, the copy is owner-supplied).\n *\n * Reads the field contract through `useField()` and `useFormContext()` and dispatches to a bound or an\n * unbound sub-component — \"bound\" means both are present. Every react-hook-form hook lives in\n * `BoundPhoneField`, so hook order never changes under a mounted component. Both sub-components render\n * the same `PhoneFieldView`, so the two paths cannot drift into different DOM.\n */\nexport function PhoneField({ requirement, ...props }: PhoneFieldProps): ReactNode {\n const contract = useField();\n const formContext = useFormContext();\n\n if (contract && formContext) {\n return <BoundPhoneField {...props} requirement={requirement} contract={contract} />;\n }\n\n return <UnboundPhoneField {...props} requirement={requirement} />;\n}\n\n// ---------------------------------------------------------------------------\n// Input part — catalogued, placeable (Decision 4). Carries the mask, the composed ref, and the\n// particle's own onChange/onBlur; a generic Field.Control cannot be this part, because the mask and\n// the country/requirement validator belong to PhoneField, not to react-hook-form's own registration.\n// ---------------------------------------------------------------------------\n\ntype PhoneFieldInputContextValue = {\n ref?: Ref<HTMLInputElement>;\n value: string;\n placeholder?: string;\n /** Resolved by the binder, threaded here because this part is not the one that binds. */\n required: boolean;\n onChange: (event: ChangeEvent<HTMLInputElement>) => void;\n onBlur: (event: FocusEvent<HTMLInputElement>) => void;\n};\n\nconst PhoneFieldInputContext = createContext<PhoneFieldInputContextValue | null>(null);\n\nfunction usePhoneFieldInputContext(): PhoneFieldInputContextValue {\n const context = useContext(PhoneFieldInputContext);\n if (!context) {\n throw new Error('PhoneFieldInput must be a descendant of PhoneField.');\n }\n return context;\n}\n\nexport type PhoneFieldInputProps = { className?: string };\n\nexport const PhoneFieldInputDefinition = defineComponent<PhoneFieldInputProps>({\n name: 'PhoneFieldInput',\n importPath: '@vtex/faststore/components',\n component: PhoneFieldInput,\n requiresContext: 'phone-field',\n editor: { label: 'Phone Field Input', category: 'action' },\n schema: {},\n guideline:\n \"The masked <input type=\\\"tel\\\"> PhoneField owns. Must sit inside PhoneField, in either the default anatomy or an author's composed children. Carries the country mask, the composed ref, and PhoneField's own onChange/onBlur — a composed Field.Control here instead re-registers the field with react-hook-form and loses the mask (unsupported, RFC's named double-binder hole).\",\n});\n\n/** Renders the masked `<input>`, reading its value/handlers/ref from the enclosing `PhoneField`. */\nexport function PhoneFieldInput({ className }: PhoneFieldInputProps): ReactNode {\n const { ref, value, placeholder, required, onChange, onBlur } = usePhoneFieldInputContext();\n\n return (\n <Input\n ref={ref}\n data-fs-phone-field-input=\"\"\n type=\"tel\"\n inputMode=\"numeric\"\n // `aria-required`, not native `required`, for the reason password-field.tsx:89-91 records:\n // `Input` is a Base UI `Field.Control`, and native constraint tracking would flip\n // `aria-invalid` on its own, ahead of react-hook-form's own validation.\n aria-required={required || undefined}\n value={value}\n onChange={onChange}\n onBlur={onBlur}\n placeholder={placeholder}\n className={className}\n />\n );\n}\n\n// ---------------------------------------------------------------------------\n// Shared view — identical DOM whether bound or unbound\n// ---------------------------------------------------------------------------\n\ntype PhoneFieldViewProps = {\n ref?: Ref<HTMLInputElement>;\n country: PhoneCountry;\n className?: string;\n label: string;\n isDisabled: boolean;\n placeholder?: string;\n required: boolean;\n maskedValue: string;\n effectiveInvalid: boolean;\n effectiveError: string;\n onChange: (event: ChangeEvent<HTMLInputElement>) => void;\n onBlur: (event: FocusEvent<HTMLInputElement>) => void;\n children?: ReactNode;\n};\n\nfunction PhoneFieldView({\n ref,\n country,\n className,\n label,\n isDisabled,\n placeholder,\n required,\n maskedValue,\n effectiveInvalid,\n effectiveError,\n onChange,\n onBlur,\n children,\n}: PhoneFieldViewProps) {\n const inputContext = useMemo<PhoneFieldInputContextValue>(\n () => ({ ref, value: maskedValue, placeholder, required, onChange, onBlur }),\n [ref, maskedValue, placeholder, required, onChange, onBlur],\n );\n\n return (\n // Deliberately the RAW Base UI Field primitives, not this package's own Field.Root/Label/Error\n // wrapper, for the default anatomy: this reproduces exactly what rendered before Decision 3\n // (when FieldContractBoundary shielded this subtree from the ambient contract) — the resolved\n // `label`/`effectiveError` text renders unconditionally, and Field.Root's own dirty/touched\n // fallback tracking stays in charge, rather than react-hook-form's. Composed children, below,\n // use the package's own Field.* parts on purpose — that is what makes a childless Field.Label /\n // Field.Error resolve real text (FR-5).\n <BaseField.Root\n data-fs-phone-field-root=\"\"\n data-fs-phone-field-root-country={country}\n data-fs-field-root=\"\"\n className={className}\n invalid={effectiveInvalid}\n disabled={isDisabled}\n >\n <PhoneFieldInputContext.Provider value={inputContext}>\n {children ?? (\n <>\n <BaseField.Label data-fs-phone-field-label=\"\" data-fs-field-label=\"\">\n {label}\n </BaseField.Label>\n <PhoneFieldInput />\n {effectiveError ? (\n <BaseField.Error match data-fs-phone-field-error=\"\" data-fs-field-error=\"\">\n {effectiveError}\n </BaseField.Error>\n ) : null}\n </>\n )}\n </PhoneFieldInputContext.Provider>\n </BaseField.Root>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Unbound — today's body, moved verbatim\n// ---------------------------------------------------------------------------\n\ntype UnboundPhoneFieldProps = PhoneFieldProps;\n\nfunction UnboundPhoneField({\n value,\n defaultValue = '',\n onValueChange,\n country = 'US',\n label,\n isDisabled = false,\n placeholder,\n invalid,\n error,\n errorInvalid,\n errorRequired,\n requirement,\n onBlur,\n className,\n ref,\n children,\n}: Readonly<UnboundPhoneFieldProps>) {\n const isControlled = value !== undefined;\n\n const [internalRaw, setInternalRaw] = useState(defaultValue);\n const [localInvalid, setLocalInvalid] = useState(false);\n const [localError, setLocalError] = useState('');\n\n // Clear local validation state when country changes so the next blur re-validates against the new\n // country's rules. The comparison baseline lives in state, not a ref, and the compare-and-set runs\n // during render (before paint), so a render React abandons without committing — a suspended\n // transition, a Suspense retry — never leaves a stale baseline behind the way a ref write would.\n const [prevCountry, setPrevCountry] = useState(country);\n if (prevCountry !== country) {\n setPrevCountry(country);\n setLocalInvalid(false);\n setLocalError('');\n }\n\n const rawValue = isControlled ? (value as string) : internalRaw;\n const maskedValue = applyPhoneMask(rawValue, country);\n const resolvedLabel = label ?? '';\n\n // External props take precedence over internal validation state.\n // When `invalid` is externally controlled, the error display is also fully\n // controlled: use the explicit `error` prop, or fall back to empty string so\n // no stale local error leaks through when the parent says the field is valid.\n const effectiveInvalid = invalid !== undefined ? invalid : localInvalid;\n const effectiveError = error !== undefined ? error : effectiveInvalid ? localError : '';\n\n function handleChange(event: ChangeEvent<HTMLInputElement>) {\n if (isDisabled) return;\n const raw = removePhoneMask(event.target.value, country);\n if (!isControlled) {\n setInternalRaw(raw);\n }\n onValueChange?.(raw);\n }\n\n function handleBlur(_event: FocusEvent<HTMLInputElement>) {\n if (isDisabled) return;\n\n let isFieldInvalid = false;\n let fieldError = '';\n\n if (requirement === 'mandatory' && !rawValue.trim()) {\n isFieldInvalid = true;\n fieldError = errorRequired ?? '';\n } else if (rawValue.trim()) {\n const valid = validatePhoneNumber(rawValue, country);\n isFieldInvalid = !valid;\n fieldError = valid ? '' : (errorInvalid ?? '');\n }\n // optional + empty → no error, keep isFieldInvalid = false / fieldError = ''\n\n setLocalInvalid(isFieldInvalid);\n setLocalError(fieldError);\n onBlur?.();\n }\n\n return (\n <PhoneFieldView\n ref={ref}\n country={country}\n className={className}\n label={resolvedLabel}\n isDisabled={isDisabled}\n placeholder={placeholder}\n required={requirement === 'mandatory'}\n maskedValue={maskedValue}\n effectiveInvalid={effectiveInvalid}\n effectiveError={effectiveError}\n onChange={handleChange}\n onBlur={handleBlur}\n >\n {children}\n </PhoneFieldView>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Bound — reads the field contract, binds through useController\n// ---------------------------------------------------------------------------\n\ntype BoundPhoneFieldProps = UnboundPhoneFieldProps & { contract: FieldContract };\n\nfunction BoundPhoneField({\n value: _value,\n defaultValue: _defaultValue,\n onValueChange,\n country = 'US',\n label,\n isDisabled,\n placeholder,\n invalid,\n error,\n errorInvalid,\n errorRequired,\n requirement,\n onBlur,\n className,\n ref: callerRef,\n contract,\n children,\n}: BoundPhoneFieldProps) {\n // Format only. Requiredness is not decided here: `useBoundField` resolves it from the fieldset's\n // baseline and the raise below, and installs the blank check, so the announcement and the\n // validation cannot disagree. The check composes alongside whatever the fieldset validates —\n // before this merge, any contract validator discarded the particle's own validation whole.\n const rule = useMemo<FieldRule>(\n () =>\n mergeFieldValidator(contract.rule, 'phoneFormat', (rawValue) => {\n const raw = typeof rawValue === 'string' ? rawValue : String(rawValue ?? '');\n // `false`, never undefined: react-hook-form reads an undefined result as valid.\n return !raw.trim() || validatePhoneNumber(raw, country) || (errorInvalid ?? false);\n }),\n [contract.rule, errorInvalid, country],\n );\n\n const field = useBoundField(contract, TEXT_FIELD_VALUE, rule, {\n required: requirement === 'mandatory',\n message: errorRequired,\n });\n const { getFieldState } = useFormContext();\n const { invalid: rhfInvalid, error: rhfError } = getFieldState(contract.name, useFormState({ name: contract.name }));\n\n const composedRef = useComposedRef<HTMLInputElement>(callerRef, field.ref);\n\n const rawValue = typeof field.value === 'string' ? field.value : String(field.value ?? '');\n const maskedValue = applyPhoneMask(rawValue, country);\n const resolvedLabel = label ?? contract.label ?? '';\n const resolvedPlaceholder = placeholder ?? contract.placeholder;\n const resolvedIsDisabled = isDisabled ?? contract.disabled ?? false;\n\n const effectiveInvalid = invalid !== undefined ? invalid : rhfInvalid;\n const effectiveError = error !== undefined ? error : effectiveInvalid ? (rhfError?.message ?? '') : '';\n\n function handleChange(event: ChangeEvent<HTMLInputElement>) {\n const raw = removePhoneMask(event.target.value, country);\n field.onChange(raw);\n onValueChange?.(raw);\n }\n\n function handleBlur(_event: FocusEvent<HTMLInputElement>) {\n field.onBlur();\n onBlur?.();\n }\n\n return (\n // Decision 3: replaces the empty-contract FieldContractBoundary with a re-provided contract\n // carrying the RESOLVED name/label/placeholder — the values a composed childless Field.Label /\n // Field.Error actually need, as opposed to the raw (possibly-undefined) ones the ambient\n // contract from the enclosing FieldBinding carries. useBoundField above remains the sole binder\n // for contract.name; this FieldBinding never registers anything itself.\n <FieldBinding\n name={contract.name}\n label={resolvedLabel}\n placeholder={resolvedPlaceholder}\n defaultValue={contract.defaultValue}\n rule={contract.rule}\n options={contract.options}\n disabled={resolvedIsDisabled}\n readOnly={contract.readOnly}\n autoComplete={contract.autoComplete}\n inputMode={contract.inputMode}\n >\n <PhoneFieldView\n ref={composedRef}\n country={country}\n className={className}\n label={resolvedLabel}\n isDisabled={resolvedIsDisabled}\n placeholder={resolvedPlaceholder}\n required={field.required}\n maskedValue={maskedValue}\n effectiveInvalid={effectiveInvalid}\n effectiveError={effectiveError}\n onChange={handleChange}\n onBlur={handleBlur}\n >\n {children}\n </PhoneFieldView>\n </FieldBinding>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAoCA,SAAS,mBAAmB,OAAe,SAAgC;CACzE,QAAQ,SAAR;EACE,KAAK,MACH,OAAO,MAAM,WAAW,IAAI,KAAK,MAAM,WAAW,GAAG;EACvD,KAAK,MACH,OAAO,MAAM,WAAW,KAAK,KAAK,MAAM,WAAW,IAAI;EACzD,SACE,OAAO;CACX;AACF;;;;;;;;;;;AAYA,SAAgB,gBAAgB,OAAe,SAA+B;CAC5E,MAAM,aAAa,MAAM,QAAQ,OAAO,EAAE;CAK1C,IAAI,MAAM,WAAW,GAAG,KAAK,mBAAmB,OAAO,OAAO,GAC5D,OAAO,IAAI;CAGb,OAAO;AACT;;;;;;;;;;AAWA,SAAgB,eAAe,OAAe,SAA+B;CAC3E,QAAQ,SAAR;EACE,KAAK,MACH,OAAO,iBAAiB,KAAK;EAC/B,KAAK,MACH,OAAO,iBAAiB,KAAK;EAC/B,SACE,OAAO,iBAAiB,KAAK;CACjC;AACF;AAEA,SAAS,iBAAiB,OAAuB;CAC/C,MAAM,aAAa,MAAM,QAAQ,OAAO,EAAE;CAG1C,IAAI,MAAM,WAAW,IAAI,KAAK,WAAW,UAAU,IAEjD,OAAO,MAAM,eADC,MAAM,QAAQ,MAAM,EAAE,CAAC,CAAC,QAAQ,OAAO,EACrB,CAAC;CAInC,IAAI,WAAW,WAAW,GAAG,KAAK,WAAW,WAAW,IACtD,OAAO,MAAM,eAAe,WAAW,UAAU,CAAC,CAAC;CAGrD,OAAO,eAAe,UAAU;AAClC;AAEA,SAAS,eAAe,QAAwB;CAE9C,MAAM,QAAQ,OAAO,MAAM,GAAG,EAAE;CAChC,IAAI,MAAM,WAAW,GAAG,OAAO;CAC/B,IAAI,MAAM,UAAU,GAAG,OAAO,IAAI;CAClC,IAAI,MAAM,UAAU,GAAG,OAAO,IAAI,MAAM,MAAM,GAAG,CAAC,EAAE,IAAI,MAAM,MAAM,CAAC;CACrE,OAAO,IAAI,MAAM,MAAM,GAAG,CAAC,EAAE,IAAI,MAAM,MAAM,GAAG,CAAC,EAAE,GAAG,MAAM,MAAM,CAAC;AACrE;AAEA,SAAS,iBAAiB,OAAuB;CAC/C,MAAM,aAAa,MAAM,QAAQ,OAAO,EAAE;CAI1C,IAAI,MAAM,WAAW,KAAK,KAAK,WAAW,UAAU,IAElD,OAAO,OAAO,eADA,MAAM,QAAQ,OAAO,EAAE,CAAC,CAAC,QAAQ,OAAO,EACrB,CAAC;CAIpC,IAAI,WAAW,WAAW,IAAI,MAAM,WAAW,WAAW,MAAM,WAAW,WAAW,KACpF,OAAO,OAAO,eAAe,WAAW,UAAU,CAAC,CAAC;CAGtD,OAAO,eAAe,UAAU;AAClC;AAEA,SAAS,eAAe,QAAwB;CAE9C,MAAM,QAAQ,OAAO,MAAM,GAAG,EAAE;CAChC,IAAI,MAAM,WAAW,GAAG,OAAO;CAC/B,IAAI,MAAM,UAAU,GAAG,OAAO,IAAI;CAClC,IAAI,MAAM,UAAU,GAAG,OAAO,IAAI,MAAM,MAAM,GAAG,CAAC,EAAE,IAAI,MAAM,MAAM,CAAC;CAErE,IAAI,MAAM,UAAU,IAAI,OAAO,IAAI,MAAM,MAAM,GAAG,CAAC,EAAE,IAAI,MAAM,MAAM,GAAG,CAAC,EAAE,GAAG,MAAM,MAAM,CAAC;CAE3F,OAAO,IAAI,MAAM,MAAM,GAAG,CAAC,EAAE,IAAI,MAAM,MAAM,GAAG,CAAC,EAAE,GAAG,MAAM,MAAM,CAAC;AACrE;;;;;;AAWA,SAAS,eAAe,QAAyB;CAC/C,IAAI,OAAO,WAAW,IAAI,OAAO;CACjC,OAAO,OAAO,WAAW,MAAM,OAAO,OAAO;AAC/C;;;;;;;;;;;;;;;;;;;;AAqBA,SAAgB,oBAAoB,OAAe,SAAgC;CACjF,IAAI,CAAC,SAAS,CAAC,MAAM,KAAK,GAAG,OAAO;CAEpC,MAAM,SAAS,MAAM,QAAQ,OAAO,EAAE;CAEtC,IAAI,mBAAmB,OAAO,OAAO,GAAG;EAEtC,IAAI,YAAY,MAEV;OAAA,OAAO,WAAW,IAAI,OAAO;EAAA,OAIjC,IAAI,OAAO,WAAW,MAAM,OAAO,WAAW,IAAI,OAAO,eAAe,OAAO,MAAM,CAAC,CAAC;CAG3F;CAGA,IAAI,YAAY,MACd,OAAO,OAAO,WAAW;CAG3B,OAAO,eAAe,MAAM;AAC9B;;;;;;;;AASA,SAAgB,OAAO,KAAa,SAA+B;CACjE,MAAM,WAAW,gBAAgB,KAAK,OAAO;CAC7C,IAAI,SAAS,WAAW,GAAG,GAAG,OAAO;CACrC,MAAM,OAAO,YAAY,OAAO,OAAO;CACvC,MAAM,WAAW,YAAY,OAAO,KAAK;CAEzC,OAAO,SAAS,WAAW,IAAI,KAAK,SAAS,SAAS,WAAW,IAAI,aAAa,IAAI,OAAO;AAC/F;AAwEA,MAAa,uBAAuB,gBAAiC;CACnE,MAAM;CACN,YAAY;CACZ,WAAW;CACX,iBAAiB;CACjB,QAAQ;EAAE,OAAO;EAAe,UAAU;CAAS;CACnD,QAAQ;EACN,SAAS;GAAE,MAAM;GAAU,SAAS;GAAM,OAAO;EAAqB;EAEtE,OAAO;GAAE,MAAM;GAAU,OAAO;EAAQ;EAExC,aAAa;GAAE,MAAM,CAAC,aAAa,UAAU;GAAY,OAAO;EAAc;EAC9E,cAAc;GAAE,MAAM;GAAU,OAAO;EAAwB;EAC/D,eAAe;GAAE,MAAM;GAAU,OAAO;EAAyB;CACnE;CACA,WACE;AACJ,CAAC;;;;;;;;;;;;;;;;AAqBD,SAAgB,WAAW,EAAE,aAAa,GAAG,SAAqC;CAChF,MAAM,WAAW,SAAS;CAC1B,MAAM,cAAc,eAAe;CAEnC,IAAI,YAAY,aACd,OAAO,oBAAC,iBAAD;EAAiB,GAAI;EAAoB;EAAuB;CAAW,CAAA;CAGpF,OAAO,oBAAC,mBAAD;EAAmB,GAAI;EAAoB;CAAc,CAAA;AAClE;AAkBA,MAAM,yBAAyB,cAAkD,IAAI;AAErF,SAAS,4BAAyD;CAChE,MAAM,UAAU,WAAW,sBAAsB;CACjD,IAAI,CAAC,SACH,MAAM,IAAI,MAAM,qDAAqD;CAEvE,OAAO;AACT;AAIA,MAAa,4BAA4B,gBAAsC;CAC7E,MAAM;CACN,YAAY;CACZ,WAAW;CACX,iBAAiB;CACjB,QAAQ;EAAE,OAAO;EAAqB,UAAU;CAAS;CACzD,QAAQ,CAAC;CACT,WACE;AACJ,CAAC;;AAGD,SAAgB,gBAAgB,EAAE,aAA8C;CAC9E,MAAM,EAAE,KAAK,OAAO,aAAa,UAAU,UAAU,WAAW,0BAA0B;CAE1F,OACE,oBAAC,OAAD;EACO;EACL,6BAA0B;EAC1B,MAAK;EACL,WAAU;EAIV,iBAAe,YAAY,KAAA;EACpB;EACG;EACF;EACK;EACF;CACZ,CAAA;AAEL;AAsBA,SAAS,eAAe,EACtB,KACA,SACA,WACA,OACA,YACA,aACA,UACA,aACA,kBACA,gBACA,UACA,QACA,YACsB;CACtB,MAAM,eAAe,eACZ;EAAE;EAAK,OAAO;EAAa;EAAa;EAAU;EAAU;CAAO,IAC1E;EAAC;EAAK;EAAa;EAAa;EAAU;EAAU;CAAM,CAC5D;CAEA,OAQE,oBAACA,MAAU,MAAX;EACE,4BAAyB;EACzB,oCAAkC;EAClC,sBAAmB;EACR;EACX,SAAS;EACT,UAAU;EAEV,UAAA,oBAAC,uBAAuB,UAAxB;GAAiC,OAAO;GACrC,UAAA,YACC,qBAAA,YAAA,EAAA,UAAA;IACE,oBAACA,MAAU,OAAX;KAAiB,6BAA0B;KAAG,uBAAoB;KAC/D,UAAA;IACc,CAAA;IACjB,oBAAC,iBAAD,CAAkB,CAAA;IACjB,iBACC,oBAACA,MAAU,OAAX;KAAiB,OAAA;KAAM,6BAA0B;KAAG,uBAAoB;KACrE,UAAA;IACc,CAAA,IACf;GACJ,EAAA,CAAA;EAE2B,CAAA;CACnB,CAAA;AAEpB;AAQA,SAAS,kBAAkB,EACzB,OACA,eAAe,IACf,eACA,UAAU,MACV,OACA,aAAa,OACb,aACA,SACA,OACA,cACA,eACA,aACA,QACA,WACA,KACA,YACmC;CACnC,MAAM,eAAe,UAAU,KAAA;CAE/B,MAAM,CAAC,aAAa,kBAAkB,SAAS,YAAY;CAC3D,MAAM,CAAC,cAAc,mBAAmB,SAAS,KAAK;CACtD,MAAM,CAAC,YAAY,iBAAiB,SAAS,EAAE;CAM/C,MAAM,CAAC,aAAa,kBAAkB,SAAS,OAAO;CACtD,IAAI,gBAAgB,SAAS;EAC3B,eAAe,OAAO;EACtB,gBAAgB,KAAK;EACrB,cAAc,EAAE;CAClB;CAEA,MAAM,WAAW,eAAgB,QAAmB;CACpD,MAAM,cAAc,eAAe,UAAU,OAAO;CACpD,MAAM,gBAAgB,SAAS;CAM/B,MAAM,mBAAmB,YAAY,KAAA,IAAY,UAAU;CAC3D,MAAM,iBAAiB,UAAU,KAAA,IAAY,QAAQ,mBAAmB,aAAa;CAErF,SAAS,aAAa,OAAsC;EAC1D,IAAI,YAAY;EAChB,MAAM,MAAM,gBAAgB,MAAM,OAAO,OAAO,OAAO;EACvD,IAAI,CAAC,cACH,eAAe,GAAG;EAEpB,gBAAgB,GAAG;CACrB;CAEA,SAAS,WAAW,QAAsC;EACxD,IAAI,YAAY;EAEhB,IAAI,iBAAiB;EACrB,IAAI,aAAa;EAEjB,IAAI,gBAAgB,eAAe,CAAC,SAAS,KAAK,GAAG;GACnD,iBAAiB;GACjB,aAAa,iBAAiB;EAChC,OAAO,IAAI,SAAS,KAAK,GAAG;GAC1B,MAAM,QAAQ,oBAAoB,UAAU,OAAO;GACnD,iBAAiB,CAAC;GAClB,aAAa,QAAQ,KAAM,gBAAgB;EAC7C;EAGA,gBAAgB,cAAc;EAC9B,cAAc,UAAU;EACxB,SAAS;CACX;CAEA,OACE,oBAAC,gBAAD;EACO;EACI;EACE;EACX,OAAO;EACK;EACC;EACb,UAAU,gBAAgB;EACb;EACK;EACF;EAChB,UAAU;EACV,QAAQ;EAEP;CACa,CAAA;AAEpB;AAQA,SAAS,gBAAgB,EACvB,OAAO,QACP,cAAc,eACd,eACA,UAAU,MACV,OACA,YACA,aACA,SACA,OACA,cACA,eACA,aACA,QACA,WACA,KAAK,WACL,UACA,YACuB;CAKvB,MAAM,OAAO,cAET,oBAAoB,SAAS,MAAM,gBAAgB,aAAa;EAC9D,MAAM,MAAM,OAAO,aAAa,WAAW,WAAW,OAAO,YAAY,EAAE;EAE3E,OAAO,CAAC,IAAI,KAAK,KAAK,oBAAoB,KAAK,OAAO,MAAM,gBAAgB;CAC9E,CAAC,GACH;EAAC,SAAS;EAAM;EAAc;CAAO,CACvC;CAEA,MAAM,QAAQ,cAAc,UAAU,kBAAkB,MAAM;EAC5D,UAAU,gBAAgB;EAC1B,SAAS;CACX,CAAC;CACD,MAAM,EAAE,kBAAkB,eAAe;CACzC,MAAM,EAAE,SAAS,YAAY,OAAO,aAAa,cAAc,SAAS,MAAM,aAAa,EAAE,MAAM,SAAS,KAAK,CAAC,CAAC;CAEnH,MAAM,cAAc,eAAiC,WAAW,MAAM,GAAG;CAGzE,MAAM,cAAc,eADH,OAAO,MAAM,UAAU,WAAW,MAAM,QAAQ,OAAO,MAAM,SAAS,EAAE,GAC5C,OAAO;CACpD,MAAM,gBAAgB,SAAS,SAAS,SAAS;CACjD,MAAM,sBAAsB,eAAe,SAAS;CACpD,MAAM,qBAAqB,cAAc,SAAS,YAAY;CAE9D,MAAM,mBAAmB,YAAY,KAAA,IAAY,UAAU;CAC3D,MAAM,iBAAiB,UAAU,KAAA,IAAY,QAAQ,mBAAoB,UAAU,WAAW,KAAM;CAEpG,SAAS,aAAa,OAAsC;EAC1D,MAAM,MAAM,gBAAgB,MAAM,OAAO,OAAO,OAAO;EACvD,MAAM,SAAS,GAAG;EAClB,gBAAgB,GAAG;CACrB;CAEA,SAAS,WAAW,QAAsC;EACxD,MAAM,OAAO;EACb,SAAS;CACX;CAEA,OAME,oBAAC,cAAD;EACE,MAAM,SAAS;EACf,OAAO;EACP,aAAa;EACb,cAAc,SAAS;EACvB,MAAM,SAAS;EACf,SAAS,SAAS;EAClB,UAAU;EACV,UAAU,SAAS;EACnB,cAAc,SAAS;EACvB,WAAW,SAAS;EAEpB,UAAA,oBAAC,gBAAD;GACE,KAAK;GACI;GACE;GACX,OAAO;GACP,YAAY;GACZ,aAAa;GACb,UAAU,MAAM;GACH;GACK;GACF;GAChB,UAAU;GACV,QAAQ;GAEP;EACa,CAAA;CACJ,CAAA;AAElB"}
@@ -1,13 +1,33 @@
1
+ import { ContentValue, MessageLocaleProp } from "../../core/dist/define-content-type.js";
1
2
  import { ComponentDefinition } from "../../core/dist/define-component.js";
2
3
  import "../../core/dist/index.js";
3
4
  import { ComponentPropsWithRef } from "react";
4
5
  //#region src/particles/spinner/spinner.d.ts
6
+ export declare const SpinnerContent: {
7
+ readonly id: "spinner";
8
+ readonly title: "Spinner";
9
+ readonly description: "Accessible name of the loading indicator.";
10
+ readonly schema: {
11
+ readonly type: "object";
12
+ readonly additionalProperties: false;
13
+ readonly properties: {
14
+ readonly label: {
15
+ readonly type: "string";
16
+ readonly title: "Accessible label";
17
+ readonly format: "icu-message";
18
+ readonly messageSource: "Loading";
19
+ readonly messageOptional: true;
20
+ };
21
+ };
22
+ };
23
+ };
24
+ export type SpinnerContentValue = ContentValue<typeof SpinnerContent>;
5
25
  /** Props for {@link Spinner}. Extends all native `<output>` attributes. */
6
- export type SpinnerProps = Omit<ComponentPropsWithRef<'output'>, 'children'> & {
7
- /** Accessible label. Defaults to `'Loading'`. */
8
- label?: string;
26
+ export type SpinnerProps = Omit<ComponentPropsWithRef<'output'>, 'children'> & MessageLocaleProp & {
27
+ /** Accessible label, from the `label` message field. */
28
+ $content?: SpinnerContentValue;
9
29
  };
10
30
  export declare const SpinnerDefinition: ComponentDefinition<SpinnerProps>;
11
- export declare function Spinner({ label, className, ...props }: SpinnerProps): import("react/jsx-runtime").JSX.Element;
31
+ export declare function Spinner({ $locale, $content, className, ...props }: SpinnerProps): import("react/jsx-runtime").JSX.Element;
12
32
  //#endregion
13
33
  //# sourceMappingURL=spinner.d.ts.map
@@ -1,31 +1,47 @@
1
1
  import { defineComponent } from "../../core/dist/define-component.js";
2
+ import { defineContentType } from "../../core/dist/define-content-type.js";
2
3
  import "../../core/dist/index.js";
4
+ import { createMessageFormatter } from "../../sdk/i18n/message-formatter.js";
3
5
  import { jsx } from "react/jsx-runtime";
4
6
  //#region src/particles/spinner/spinner.tsx
7
+ const SpinnerContent = defineContentType({
8
+ id: "spinner",
9
+ title: "Spinner",
10
+ description: "Accessible name of the loading indicator.",
11
+ schema: {
12
+ type: "object",
13
+ additionalProperties: false,
14
+ properties: { label: {
15
+ type: "string",
16
+ title: "Accessible label",
17
+ format: "icu-message",
18
+ messageSource: "Loading",
19
+ messageOptional: true
20
+ } }
21
+ }
22
+ });
5
23
  const SpinnerDefinition = defineComponent({
6
24
  name: "Spinner",
7
25
  importPath: "@vtex/faststore/components",
8
26
  component: Spinner,
27
+ content: SpinnerContent,
9
28
  editor: {
10
29
  label: "Spinner",
11
30
  category: "feedback"
12
31
  },
13
- schema: { label: {
14
- type: "string",
15
- default: "Loading",
16
- label: "Label"
17
- } },
18
- guideline: "Loading indicator — use standalone or composed inside Button for loading states. Purely structural with no built-in animation CSS."
32
+ schema: {},
33
+ guideline: "Loading indicator — use standalone or composed inside Button for loading states. Its accessible name comes from the $content field label: a blank label renders no aria-label, and an explicit aria-label prop applies when the label is blank. Purely structural with no built-in animation CSS."
19
34
  });
20
- function Spinner({ label = "Loading", className, ...props }) {
35
+ function Spinner({ $locale, $content, className, ...props }) {
36
+ const label = createMessageFormatter($locale, SpinnerContent, $content).format("label");
21
37
  return /* @__PURE__ */ jsx("output", {
22
38
  ...props,
23
- "aria-label": label,
39
+ "aria-label": label || props["aria-label"],
24
40
  className,
25
41
  "data-fs-spinner": ""
26
42
  });
27
43
  }
28
44
  //#endregion
29
- export { Spinner, SpinnerDefinition };
45
+ export { Spinner, SpinnerContent, SpinnerDefinition };
30
46
 
31
47
  //# sourceMappingURL=spinner.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"spinner.js","names":[],"sources":["../../../src/particles/spinner/spinner.tsx"],"sourcesContent":["import { defineComponent } from '@vtex/fs-core';\nimport type { ComponentPropsWithRef } from 'react';\n\n/** Props for {@link Spinner}. Extends all native `<output>` attributes. */\nexport type SpinnerProps = Omit<ComponentPropsWithRef<'output'>, 'children'> & {\n /** Accessible label. Defaults to `'Loading'`. */\n label?: string;\n};\n\nexport const SpinnerDefinition = defineComponent<SpinnerProps>({\n name: 'Spinner',\n importPath: '@vtex/faststore/components',\n component: Spinner,\n editor: { label: 'Spinner', category: 'feedback' },\n schema: {\n label: { type: 'string', default: 'Loading', label: 'Label' },\n },\n guideline:\n 'Loading indicator — use standalone or composed inside Button for loading states. Purely structural with no built-in animation CSS.',\n});\n\nexport function Spinner({ label = 'Loading', className, ...props }: SpinnerProps) {\n return <output {...props} aria-label={label} className={className} data-fs-spinner=\"\" />;\n}\n"],"mappings":";;;;AASA,MAAa,oBAAoB,gBAA8B;CAC7D,MAAM;CACN,YAAY;CACZ,WAAW;CACX,QAAQ;EAAE,OAAO;EAAW,UAAU;CAAW;CACjD,QAAQ,EACN,OAAO;EAAE,MAAM;EAAU,SAAS;EAAW,OAAO;CAAQ,EAC9D;CACA,WACE;AACJ,CAAC;AAED,SAAgB,QAAQ,EAAE,QAAQ,WAAW,WAAW,GAAG,SAAuB;CAChF,OAAO,oBAAC,UAAD;EAAQ,GAAI;EAAO,cAAY;EAAkB;EAAW,mBAAgB;CAAI,CAAA;AACzF"}
1
+ {"version":3,"file":"spinner.js","names":[],"sources":["../../../src/particles/spinner/spinner.tsx"],"sourcesContent":["import { type ContentValue, defineComponent, defineContentType, type MessageLocaleProp } from '@vtex/fs-core';\nimport type { ComponentPropsWithRef } from 'react';\nimport { createMessageFormatter } from '../../sdk/i18n/message-formatter.js';\n\nexport const SpinnerContent = defineContentType({\n id: 'spinner',\n title: 'Spinner',\n description: 'Accessible name of the loading indicator.',\n schema: {\n type: 'object',\n additionalProperties: false,\n properties: {\n label: {\n type: 'string',\n title: 'Accessible label',\n format: 'icu-message',\n messageSource: 'Loading',\n messageOptional: true,\n },\n },\n },\n});\n\nexport type SpinnerContentValue = ContentValue<typeof SpinnerContent>;\n\n/** Props for {@link Spinner}. Extends all native `<output>` attributes. */\nexport type SpinnerProps = Omit<ComponentPropsWithRef<'output'>, 'children'> &\n MessageLocaleProp & {\n /** Accessible label, from the `label` message field. */\n $content?: SpinnerContentValue;\n };\n\nexport const SpinnerDefinition = defineComponent<SpinnerProps>({\n name: 'Spinner',\n importPath: '@vtex/faststore/components',\n component: Spinner,\n content: SpinnerContent,\n editor: { label: 'Spinner', category: 'feedback' },\n schema: {},\n guideline:\n 'Loading indicator — use standalone or composed inside Button for loading states. Its accessible name comes from the $content field label: a blank label renders no aria-label, and an explicit aria-label prop applies when the label is blank. Purely structural with no built-in animation CSS.',\n});\n\nexport function Spinner({ $locale, $content, className, ...props }: SpinnerProps) {\n const label = createMessageFormatter($locale, SpinnerContent, $content).format('label');\n return <output {...props} aria-label={label || props['aria-label']} className={className} data-fs-spinner=\"\" />;\n}\n"],"mappings":";;;;;;AAIA,MAAa,iBAAiB,kBAAkB;CAC9C,IAAI;CACJ,OAAO;CACP,aAAa;CACb,QAAQ;EACN,MAAM;EACN,sBAAsB;EACtB,YAAY,EACV,OAAO;GACL,MAAM;GACN,OAAO;GACP,QAAQ;GACR,eAAe;GACf,iBAAiB;EACnB,EACF;CACF;AACF,CAAC;AAWD,MAAa,oBAAoB,gBAA8B;CAC7D,MAAM;CACN,YAAY;CACZ,WAAW;CACX,SAAS;CACT,QAAQ;EAAE,OAAO;EAAW,UAAU;CAAW;CACjD,QAAQ,CAAC;CACT,WACE;AACJ,CAAC;AAED,SAAgB,QAAQ,EAAE,SAAS,UAAU,WAAW,GAAG,SAAuB;CAChF,MAAM,QAAQ,uBAAuB,SAAS,gBAAgB,QAAQ,CAAC,CAAC,OAAO,OAAO;CACtF,OAAO,oBAAC,UAAD;EAAQ,GAAI;EAAO,cAAY,SAAS,MAAM;EAA0B;EAAW,mBAAgB;CAAI,CAAA;AAChH"}
@@ -11,13 +11,16 @@ export type SwitchRootProps = {
11
11
  required?: boolean;
12
12
  name?: string;
13
13
  id?: string;
14
+ /** Accessible name when no visible label is bound to the switch. */
15
+ 'aria-label'?: string;
16
+ 'aria-labelledby'?: string;
14
17
  className?: string;
15
18
  children?: ReactNode;
16
19
  };
17
20
  export type SwitchThumbProps = ComponentPropsWithRef<'span'>;
18
21
  export declare const SwitchRootDefinition: ComponentDefinition<SwitchRootProps>;
19
22
  export declare const SwitchThumbDefinition: ComponentDefinition<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>>;
20
- export declare function SwitchRoot({ checked, defaultChecked, onCheckedChange, disabled, readOnly, required, name, id, className, children }: SwitchRootProps): import("react/jsx-runtime").JSX.Element;
23
+ export declare function SwitchRoot({ checked, defaultChecked, onCheckedChange, disabled, readOnly, required, name, id, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, className, children }: Readonly<SwitchRootProps>): import("react/jsx-runtime").JSX.Element;
21
24
  export declare function SwitchThumb({ className, children, ...props }: SwitchThumbProps): import("react/jsx-runtime").JSX.Element;
22
25
  export declare const Switch: {
23
26
  Root: typeof SwitchRoot;