@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":"form.js","names":[],"sources":["../../../src/particles/form/form.tsx"],"sourcesContent":["'use client';\nimport { defineComponent } from '@vtex/fs-core';\nimport type { ComponentPropsWithRef, Context, FormEvent, KeyboardEvent, ReactNode } from 'react';\nimport { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';\nimport { FormProvider, useForm, useFormContext, useFormState } from 'react-hook-form';\nimport { useIntl } from '../../sdk/i18n/client.js';\nimport { Button } from '../button/button.js';\nimport { clearBoundField } from '../field/bound-field-registry.js';\n\n// ---------------------------------------------------------------------------\n// Data models\n// ---------------------------------------------------------------------------\n\n/**\n * The structural minimum every SDK user-error type satisfies. `code` is optional so that every\n * shipped shape is assignable, including `RegionUserError`, the one that declares it optional;\n * `ShippingAddressUpdateErrorEntity`, `ClientProfileUserError`, `CartUserError` and\n * `SessionUserError` all declare `Readonly<{ code: string; message: string }>`. There is no shared\n * user-error type in the SDK to reuse.\n */\nexport type FormUserError = Readonly<{ code?: string; message: string }>;\n\n/** What one fieldset hands the form. The form learns nothing else about it. */\nexport type FieldsetRegistration = Readonly<{\n /** Matches the field-name prefix every one of this fieldset's controls registers under. */\n namespace: string;\n /** Every full, namespaced field name this fieldset currently has mounted. */\n getFieldNames: () => readonly string[];\n /**\n * Closes over the fieldset's own injected `$actions`. Rejecting is allowed; the form catches it.\n * Must settle: the form gives up on a dispatch still pending after `FORM_DISPATCH_TIMEOUT_MS` and\n * reports it as a failed write. Must also be idempotent: giving up on a dispatch does not cancel it,\n * so a timed-out write may already be landing on the server, and the same payload is re-dispatched on\n * the shopper's next submit while the field stays dirty.\n */\n dispatch: (payload: Record<string, unknown>) => Promise<readonly FormUserError[]>;\n /** Shapes react-hook-form's raw values into the mutation's payload, including type coercion. */\n toPayload: (values: Record<string, unknown>) => Record<string, unknown>;\n /**\n * Machine identifier for this fieldset's write. `FormError` renders it as the\n * `data-fs-form-error-item` attribute value and uses it in two React keys; it is never displayed,\n * because the visible text is each `userError`'s own `message` or `FormError`'s `fallbackMessage`.\n * Its value is the kebab-case ASCII rendering of this registration's own `namespace`\n * (`shippingAddress` → `shipping-address`), so a stylesheet selecting\n * `[data-fs-form-error-item=\"…\"]` needs one predictable shape and no diacritics.\n */\n label: string;\n}>;\n\n/**\n * One fieldset's write that did not land. An empty `userErrors` means the dispatch rejected or never\n * settled within `FORM_DISPATCH_TIMEOUT_MS`; either way `FormError` renders `fallbackMessage`.\n */\nexport type FormWriteFailure = Readonly<{\n label: string;\n userErrors: readonly FormUserError[];\n}>;\n\nexport type FormRegistry = Readonly<{\n /** Stable for the life of the FormRoot. Returns the unregister function. */\n registerFieldset: (registration: FieldsetRegistration) => () => void;\n /** The last submit's failures, in dispatch order. */\n failures: readonly FormWriteFailure[];\n}>;\n\n// ---------------------------------------------------------------------------\n// Registry context\n// ---------------------------------------------------------------------------\n\nexport const FormRegistryContext: Context<FormRegistry | null> = createContext<FormRegistry | null>(null);\n\n/** Throws when no FormRoot is above the caller. */\nexport function useFormRegistry(): FormRegistry {\n const registry = useContext(FormRegistryContext);\n if (!registry) throw new Error('Form parts must be used inside FormRoot.');\n return registry;\n}\n\n/**\n * Internal-only seam between the six parts in this file. `FormClear` and `FormReset` iterate every\n * registered fieldset's field names (Invariant 11 — the form reaches a field name only through a\n * registration's `getFieldNames()`), which the public `FormRegistry` contract does not expose to a\n * fieldset — it only ever calls `registerFieldset` and reads `failures`. Not exported from this\n * module or the barrel.\n */\nconst FieldsetSnapshotContext = createContext<(() => readonly FieldsetRegistration[]) | null>(null);\n\nfunction useFieldsetSnapshot(): () => readonly FieldsetRegistration[] {\n const snapshot = useContext(FieldsetSnapshotContext);\n if (!snapshot) throw new Error('Form parts must be used inside FormRoot.');\n return snapshot;\n}\n\n/** Adds one token for as long as the caller is mounted; the returned cleanup removes that token. */\ntype AllowImplicitSubmission = (token: symbol) => () => void;\n\n/**\n * A second, internal-only seam beside `FieldsetSnapshotContext`, for the same reason: `FormEnterSubmit`\n * takes a form-wide keyboard allowance the public `FormRegistry` must not expose to a fieldset. Not\n * exported from this module or the barrel.\n */\nconst ImplicitSubmissionContext: Context<AllowImplicitSubmission | null> =\n createContext<AllowImplicitSubmission | null>(null);\n\n/**\n * Takes an allowance token for the life of the calling component, so `handleKeyDown` allows implicit\n * submission on this FormRoot's own text-entry inputs while at least one caller holds a token. Throws\n * the same error as every other part when there is no FormRoot above it.\n */\nfunction useAllowImplicitSubmission(): void {\n const allow = useContext(ImplicitSubmissionContext);\n // useState's lazy initialiser, not a ref written during render: it runs Symbol() exactly once, on\n // this component instance's first render, and every re-render reads back the same value.\n const [token] = useState(() => Symbol());\n\n useEffect(() => {\n if (!allow) return;\n return allow(token);\n }, [allow, token]);\n\n // All hooks above run unconditionally on every render; only this line is conditional, so throwing\n // here (rather than before the hooks) is not a rules-of-hooks violation.\n if (!allow) throw new Error('Form parts must be used inside FormRoot.');\n}\n\n/**\n * Two namespaces are in conflict when one equals, prefixes or is a descendant of the other —\n * `profile` collides with itself and with `profile.address` alike, because a fieldset under either\n * arrangement would dispatch on the other's edits and marshal its values into the wrong payload.\n */\nfunction namespacesCollide(a: string, b: string): boolean {\n if (a === b) return true;\n return a.startsWith(`${b}.`) || b.startsWith(`${a}.`);\n}\n\n/**\n * Is any of `names` dirty? React Hook Form nests `dirtyFields` by dot-path segment, so each full\n * field name is walked segment by segment rather than read as a flat key.\n *\n * Callers pass the names a fieldset's mounted controls currently hold, not its whole namespace. With\n * `shouldUnregister` unset, a control that has left the screen keeps its value and its dirty flag,\n * and nothing resets it — reconciliation, `FormReset` and `FormClear` all act on mounted names only.\n * Asking about the namespace would keep that flag reporting the fieldset dirty, so every later\n * submit would dispatch again for a field the shopper can no longer see, and the same holds for a\n * fieldset that has not mounted its controls yet.\n */\nfunction isAnyFieldDirty(dirtyFields: Record<string, unknown>, names: readonly string[]): boolean {\n return names.some((name) => {\n let node: unknown = dirtyFields;\n for (const segment of name.split('.')) {\n if (typeof node !== 'object' || node === null) return false;\n node = (node as Record<string, unknown>)[segment];\n }\n return Boolean(node);\n });\n}\n\n/**\n * Shallow-unsafe but adequate: field values are the primitives and plain records a bound Control\n * produces (strings, booleans, small objects), never functions or circular structures, so a\n * `JSON.stringify` comparison is a safe stand-in for a real deep-equal. Used only to tell whether a\n * shopper's keystroke landed while a dispatch was in flight (Decision 6) — a false \"changed\" verdict\n * merely means the field is resubmitted needlessly, never data loss.\n */\nfunction valuesEqual(a: unknown, b: unknown): boolean {\n return a === b || JSON.stringify(a) === JSON.stringify(b);\n}\n\n/**\n * Ceiling on one fieldset's `dispatch`. A dispatch that neither resolves nor rejects — a fetch to a\n * server that accepts the connection and never answers, for which browsers apply no default timeout —\n * would otherwise leave `onValid` awaiting forever, so the submit boundary's `finally` never runs and\n * the re-entrancy guard stays armed for the life of the page. This is not cancellation: the request\n * keeps running and may still reach the server, and the form stops waiting for it.\n *\n * The ceiling is per fieldset, not per submit: `onValid` visits dirty fieldsets one at a time, in\n * registration order, so a submit over *n* hung fieldsets takes up to *n* times this long to release.\n * That is measured and accepted, not overlooked (Decision 3) — the wait stays bounded and\n * self-releasing, since the submit boundary's `finally` always runs once the last ceiling fires.\n */\nexport const FORM_DISPATCH_TIMEOUT_MS = 30_000;\n\n/**\n * Resolves with the dispatch's own result, or rejects once `FORM_DISPATCH_TIMEOUT_MS` has elapsed,\n * whichever happens first. The no-op handler on `dispatch` is what stops a late rejection surfacing as\n * an unhandled rejection after the race has already been lost; the timer is cleared either way, so a\n * dispatch that settles normally leaves nothing pending.\n */\nfunction withDispatchTimeout(dispatch: Promise<readonly FormUserError[]>): Promise<readonly FormUserError[]> {\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n reject(new Error(`Dispatch exceeded FORM_DISPATCH_TIMEOUT_MS (${FORM_DISPATCH_TIMEOUT_MS}ms).`));\n }, FORM_DISPATCH_TIMEOUT_MS);\n\n dispatch.then(\n (userErrors) => {\n clearTimeout(timer);\n resolve(userErrors);\n },\n (error) => {\n clearTimeout(timer);\n reject(error);\n },\n );\n });\n}\n\n/**\n * The HTML spec's text-entry `<input>` types — the ones that block implicit submission for anything\n * other than the field a shopper is typing in. An `<input>` with no `type` attribute reports\n * `type === 'text'`, so it is covered without a separate case.\n */\nconst TEXT_ENTRY_INPUT_TYPES = new Set([\n 'text',\n 'search',\n 'url',\n 'tel',\n 'email',\n 'password',\n 'number',\n 'date',\n 'month',\n 'week',\n 'time',\n 'datetime-local',\n]);\n\n// ---------------------------------------------------------------------------\n// Prop types\n// ---------------------------------------------------------------------------\n\nexport type FormRootProps = Omit<\n ComponentPropsWithRef<'form'>,\n 'onSubmit' | 'action' | 'method' | 'target' | 'encType' | 'dangerouslySetInnerHTML'\n>;\nexport type FormSubmitProps = { className?: string; label?: string; children?: ReactNode };\nexport type FormClearProps = { className?: string; label?: string; children?: ReactNode };\nexport type FormResetProps = { className?: string; label?: string; children?: ReactNode };\nexport type FormErrorProps = { className?: string; fallbackMessage?: string };\n\n// ---------------------------------------------------------------------------\n// Definitions\n// ---------------------------------------------------------------------------\n\nexport const FormRootDefinition = defineComponent<FormRootProps>({\n name: 'FormRoot',\n importPath: '@vtex/faststore/components',\n component: FormRoot,\n providesContext: 'form',\n editor: { label: 'Form', category: 'action' },\n schema: {},\n guideline:\n \"The only <form> its own fieldset registry dispatches from — a composed CartCouponForm, ShippingSimulatorForm or RegionForm renders its own, and a submit-origin check keeps theirs out of this one. Calls react-hook-form's useForm() once and holds the registry a submit dispatches in registration order. Compose FormSubmit/FormEnterSubmit/FormError/FormClear/FormReset anywhere inside it, and a fieldset as a descendant to give the submit something to persist — FormRoot itself declares no actions.\",\n});\n\nexport const FormSubmitDefinition = defineComponent<FormSubmitProps>({\n name: 'FormSubmit',\n importPath: '@vtex/faststore/components',\n component: FormSubmit,\n requiresContext: 'form',\n editor: { label: 'Form Submit', category: 'action' },\n schema: {\n label: { type: 'string', label: 'Label' },\n },\n guideline:\n 'Submits every registered fieldset the shopper changed, in registration order, and disables itself while a write is in flight. Renders children, then label, then the message catalog (fs/form.submit) — never a hard-coded English default. A fieldset with nothing changed contributes no request; an invalid field blocks every dispatch and moves focus to it instead of submitting. Enter in a text input does not submit — see FormEnterSubmit for a form where it does.',\n});\n\nexport const FormEnterSubmitDefinition = defineComponent<FormSubmitProps>({\n name: 'FormEnterSubmit',\n importPath: '@vtex/faststore/components',\n component: FormEnterSubmit,\n requiresContext: 'form',\n editor: { label: 'Form Enter Submit', category: 'action' },\n schema: {\n label: { type: 'string', label: 'Label' },\n },\n guideline:\n 'Renders the same button as FormSubmit, sharing its children/label/fs/form.submit resolution, and additionally allows Enter to submit this form from any text-entry input while mounted. The allowance is form-scoped: placed inside one fieldset of a multi-fieldset FormRoot, it allows Enter for every text input in the enclosing form, not only that fieldset. Enter that commits an IME candidate never submits.',\n});\n\nexport const FormErrorDefinition = defineComponent<FormErrorProps>({\n name: 'FormError',\n importPath: '@vtex/faststore/components',\n component: FormError,\n requiresContext: 'form',\n editor: { label: 'Form Error', category: 'content' },\n schema: {\n fallbackMessage: { type: 'string', label: 'Fallback message' },\n },\n guideline:\n \"Renders the last submit's write failures grouped by fieldset, or nothing when there were none. Set fallbackMessage for a fieldset whose write rejected rather than resolving with userErrors.\",\n});\n\nexport const FormClearDefinition = defineComponent<FormClearProps>({\n name: 'FormClear',\n importPath: '@vtex/faststore/components',\n component: FormClear,\n requiresContext: 'form',\n editor: { label: 'Form Clear', category: 'action' },\n schema: {\n label: { type: 'string', label: 'Label' },\n },\n guideline:\n 'Empties every field registered by every fieldset inside the enclosing FormRoot, not only the nearest one, but marks dirty only the fields whose value actually changed — a field already empty stays clean. Renders children, then label, then the message catalog (fs/form.clear). The following submit dispatches a write for every fieldset that had something to clear, and nothing for one where clearing was a no-op. There is no way to scope it to a single fieldset; place it only where clearing the whole form is the intended action, not by analogy with a per-field clear.',\n});\n\nexport const FormResetDefinition = defineComponent<FormResetProps>({\n name: 'FormReset',\n importPath: '@vtex/faststore/components',\n component: FormReset,\n requiresContext: 'form',\n editor: { label: 'Form Reset', category: 'action' },\n schema: {\n label: { type: 'string', label: 'Label' },\n },\n guideline:\n \"Returns every registered field to react-hook-form's baseline for that name and clears its dirty/touched state. Renders children, then label, then the message catalog (fs/form.reset). Before a fieldset's first successful write, that baseline is whatever the field's own seed resolves to — not empty — so Reset reverts to the original value rather than clearing it; only after a successful submit does the baseline become what was last written.\",\n});\n\n// ---------------------------------------------------------------------------\n// Parts\n// ---------------------------------------------------------------------------\n\nexport function FormRoot({ className, children, onKeyDown, ...props }: FormRootProps): ReactNode {\n const form = useForm();\n const {\n handleSubmit,\n // `dirtyFields` is destructured here, in render, on purpose. React Hook Form keeps `dirtyFields`\n // current whether or not anything reads it — the proxy on `formState` decides only whether a\n // change here re-renders the subscriber, not whether the underlying store is kept. What the\n // render-time read buys is freshness: the submit handler below closes over the copy from the\n // render that defined it, and subscribing here is what keeps that copy current by the time a\n // later submit reads it. (The per-fieldset check further down walks each mounted field's\n // dot-path through this object rather than indexing it by a single key — see `isAnyFieldDirty`.)\n formState: { dirtyFields, isSubmitting },\n getValues,\n resetField,\n } = form;\n\n const fieldsets = useRef(new Map<string, FieldsetRegistration>());\n /**\n * Insertion order of every namespace ever registered, independent of `fieldsets`' own Map order.\n * A namespace's slot here is created once and never moved — re-registering it (the cleanup-then-\n * effect cycle a changed dep triggers) deletes and re-adds the `fieldsets` entry, which would push\n * a plain `Map` iteration to the tail; reading dispatch order through this array instead keeps a\n * namespace in its original position across any number of re-registrations.\n */\n const order = useRef<string[]>([]);\n const submitting = useRef(false);\n const [failures, setFailures] = useState<readonly FormWriteFailure[]>([]);\n /**\n * One token per mounted part that allows implicit submission (Decision 1). A `Set`, not a boolean or\n * a count: two mounted allowing parts must compose, unmounting one must leave the allowance held by\n * the other in place, and a token's cleanup — including a double-invoked one under StrictMode — must\n * be a no-op once already removed. `handleKeyDown` only ever reads `.size`; nothing renders from it.\n */\n const allowance = useRef(new Set<symbol>());\n\n const registerFieldset = useCallback((registration: FieldsetRegistration) => {\n const { namespace } = registration;\n\n for (const existing of fieldsets.current.values()) {\n if (namespacesCollide(namespace, existing.namespace)) {\n throw new Error(\n `FormRoot already has a fieldset registered under namespace \"${existing.namespace}\", which collides with \"${namespace}\". Two different fieldsets cannot share a namespace or nest one inside the other — re-registering the same namespace is only valid once its previous registration has been unregistered.`,\n );\n }\n }\n\n if (!order.current.includes(namespace)) {\n order.current.push(namespace);\n }\n fieldsets.current.set(namespace, registration);\n\n return () => {\n if (fieldsets.current.get(namespace) === registration) {\n fieldsets.current.delete(namespace);\n }\n };\n }, []);\n\n const getFieldsetSnapshot = useCallback(\n () => order.current.flatMap((namespace) => fieldsets.current.get(namespace) ?? []),\n [],\n );\n\n const registerAllowance = useCallback((token: symbol) => {\n allowance.current.add(token);\n return () => {\n allowance.current.delete(token);\n };\n }, []);\n\n const onValid = useCallback(async () => {\n setFailures([]);\n const collected: FormWriteFailure[] = [];\n const snapshot = getFieldsetSnapshot();\n\n for (const fieldset of snapshot) {\n let preDispatchValues: ReadonlyArray<readonly [string, unknown]>;\n let userErrors: readonly FormUserError[];\n try {\n const fieldNames = fieldset.getFieldNames();\n if (!isAnyFieldDirty(dirtyFields, fieldNames)) continue;\n preDispatchValues = fieldNames.map((name) => [name, getValues(name)] as const);\n const payload = fieldset.toPayload(getValues(fieldset.namespace) ?? {});\n userErrors = await withDispatchTimeout(fieldset.dispatch(payload));\n } catch {\n // Threw, timed out, or could not build its payload — collected as a failure either way, and\n // the queue moves on: the next fieldset's dispatch never depends on this one's code being\n // sound.\n collected.push({ label: fieldset.label, userErrors: [] });\n continue;\n }\n\n if (userErrors.length > 0) {\n collected.push({ label: fieldset.label, userErrors });\n continue;\n }\n\n // Reconcile against the values captured before the await, not the live ones (Decision 6).\n // A name whose live value still matches what was captured is safe to reconcile: the write\n // targeted exactly that value, so moving the baseline there is invisible. A name whose live\n // value has since diverged means a keystroke landed mid-write — it is left untouched, so it\n // stays dirty and is picked up, unsent, by the next submit.\n //\n // Deliberately outside the try above: the write already succeeded (no userErrors), so a\n // `resetField` that throws here is a reconciliation fault, not a write fault, and must not be\n // reported to the shopper as one.\n for (const [name, capturedValue] of preDispatchValues) {\n if (valuesEqual(getValues(name), capturedValue)) {\n resetField(name, { defaultValue: capturedValue });\n }\n }\n }\n\n setFailures(collected);\n }, [dirtyFields, getValues, resetField, getFieldsetSnapshot]);\n\n const onInvalid = useCallback(() => {\n setFailures([]);\n }, []);\n\n /**\n * Ignores a submit event whose origin isn't this FormRoot's own <form>. Submit events bubble, so a\n * nested <form>'s own submission — the shape CartCouponForm, ShippingSimulatorForm and RegionForm\n * each render when composed inside a checkout FormRoot — reaches this handler too; without this\n * check, that bubbled event would run react-hook-form's handleSubmit and commit an entity write the\n * shopper never asked this FormRoot to make. Mirrors handleKeyDown's own origin check (there scoped\n * by `target.form`), for the same reason: a nested form is never this one.\n *\n * Two properties of where this check sits are load-bearing. First, it reads `event.currentTarget`\n * before any `await`: React nulls `currentTarget` once the synchronous part of a handler returns,\n * so the same comparison placed after an await degrades to `event.target !== null` — always true —\n * and rejects every submit, a permanently dead submit button with no error raised. It needs no test\n * of its own: inserting an await above this check fails most of the tests in form.test.tsx, and\n * moving it below the awaited `handleSubmit(...)` below fails the nested-form test in *Implicit\n * submission*. Second, it runs before the re-entrancy check immediately below: while this form's own\n * write is in flight, `submitting.current` is `true`, so a bubbled nested submit that reached the\n * re-entrancy check first would call `event.preventDefault()` and cancel a nested form's own\n * submission that this FormRoot never rendered. The last test in *Re-entrancy* pins that second\n * property; nothing caught it before that test existed.\n */\n const handleFormSubmit = useCallback(\n async (event: FormEvent<HTMLFormElement>) => {\n if (event.target !== event.currentTarget) return;\n\n if (submitting.current) {\n event.preventDefault();\n return;\n }\n\n submitting.current = true;\n try {\n await handleSubmit(onValid, onInvalid)(event);\n } finally {\n // Released after the awaited handler, not inside onValid: react-hook-form flips\n // formState.isSubmitting to false in the statement immediately before its returned promise\n // settles, so releasing here keeps the guard armed for a superset of the window in which\n // isSubmitting is true. Releasing earlier — inside onValid's own finally, where this guard\n // used to live — would open a sliver in which a third submit is accepted while isSubmitting\n // is still true, reintroducing the defect this guard exists to close.\n submitting.current = false;\n }\n },\n [handleSubmit, onValid, onInvalid],\n );\n\n /**\n * Cancels HTML implicit submission by default. A text input inside a form with a default button\n * submits that form on Enter, which for an entity form means committing a write from a keystroke a\n * shopper means as \"look this up\" or \"next field\" — before they have finished editing the rest of\n * the sendable unit. That default is form-scoped and opt-in to override: mounting `FormEnterSubmit`\n * anywhere inside this FormRoot allows Enter to submit from any of this form's own text-entry\n * inputs, not only the fieldset the allowing part happens to sit in; a form composing only\n * `FormSubmit` keeps today's cancelling behaviour. Enter that commits an IME candidate is cancelled\n * either way, allowance or not, so choosing a word never submits a half-finished form. Submitting\n * stays fully keyboard-operable either way, through a focusable native `FormSubmit`/`FormEnterSubmit`\n * button, so no capability is removed (WCAG 2.1 SC 2.1.1). Scoped to text-entry inputs by target, so\n * Enter on a button, a link, a `<textarea>`, a `contentEditable` region or a Base UI select trigger is\n * untouched, and scoped to Enter, so typing is untouched. Also scoped to this form's own inputs by\n * `target.form`: a keydown from a nested `<form>`'s own control bubbles up here too, and without that\n * check this guard would cancel implicit submission for a form it never rendered. Composes rather\n * than replaces an author-supplied `onKeyDown`: theirs runs first, unconditionally, before any of\n * this guard's own checks — it can cancel Enter on an allowing form, but it cannot force Enter on a\n * cancelling one, because this guard's own `preventDefault()` runs after it.\n */\n const handleKeyDown = useCallback(\n (event: KeyboardEvent<HTMLFormElement>) => {\n onKeyDown?.(event);\n if (event.key !== 'Enter' || event.defaultPrevented) return;\n\n const { target } = event;\n if (!(target instanceof HTMLInputElement) || !TEXT_ENTRY_INPUT_TYPES.has(target.type)) return;\n if (target.form !== event.currentTarget) return;\n if (allowance.current.size > 0 && !event.nativeEvent.isComposing) return;\n\n event.preventDefault();\n },\n [onKeyDown],\n );\n\n const registry = useMemo<FormRegistry>(() => ({ registerFieldset, failures }), [registerFieldset, failures]);\n\n return (\n <form\n {...props}\n noValidate\n onSubmit={handleFormSubmit}\n onKeyDown={handleKeyDown}\n className={className}\n data-fs-form=\"\"\n data-fs-form-pending={isSubmitting ? '' : undefined}\n >\n <FormProvider {...form}>\n <FormRegistryContext.Provider value={registry}>\n <FieldsetSnapshotContext.Provider value={getFieldsetSnapshot}>\n <ImplicitSubmissionContext.Provider value={registerAllowance}>\n {children}\n </ImplicitSubmissionContext.Provider>\n </FieldsetSnapshotContext.Provider>\n </FormRegistryContext.Provider>\n </FormProvider>\n </form>\n );\n}\n\n/**\n * The shared render for both submit parts: same button, same hooks, same data-fs-form-submit hook.\n * Text resolves `children ?? label ?? formatMessage(...)` (RFC sketch) — never a hard-coded English\n * default — so an unauthored FormEnterSubmit reads correctly in every shipped locale, not only\n * en-US. One id, `fs/form.submit`, covers both parts: they render the same button, so a second id\n * for the Enter variant would only be a second translation of the same word.\n */\nfunction SubmitButton({ className, label, children }: FormSubmitProps): ReactNode {\n const { isSubmitting } = useFormState();\n const intl = useIntl();\n\n return (\n <Button\n type=\"submit\"\n disabled={isSubmitting}\n className={className}\n data-fs-form-submit=\"\"\n data-fs-form-submit-pending={isSubmitting ? '' : undefined}\n >\n {children ?? label ?? intl.formatMessage({ id: 'fs/form.submit' })}\n </Button>\n );\n}\n\nexport function FormSubmit(props: FormSubmitProps): ReactNode {\n useFormRegistry();\n return <SubmitButton {...props} />;\n}\n\n/**\n * Renders the same button as `FormSubmit` and additionally allows Enter to submit this FormRoot's own\n * text-entry inputs while mounted — see `handleKeyDown`'s own doc for the form-scoped allowance and\n * the IME carve-out.\n */\nexport function FormEnterSubmit(props: FormSubmitProps): ReactNode {\n useFormRegistry();\n useAllowImplicitSubmission();\n return <SubmitButton {...props} />;\n}\n\nexport function FormError({\n className,\n fallbackMessage = 'Something went wrong. Please try again.',\n}: FormErrorProps): ReactNode {\n const { failures } = useFormRegistry();\n\n if (failures.length === 0) return null;\n\n return (\n <div role=\"alert\" className={className} data-fs-form-error=\"\">\n {failures.map((failure, failureIndex) => (\n <ul key={`${failure.label}-${failureIndex}`} data-fs-form-error-item={failure.label}>\n {failure.userErrors.length > 0 ? (\n failure.userErrors.map((error, errorIndex) => (\n <li key={`${failure.label}-${failureIndex}-${errorIndex}`}>{error.message}</li>\n ))\n ) : (\n <li>{fallbackMessage}</li>\n )}\n </ul>\n ))}\n </div>\n );\n}\n\nexport function FormClear({ className, label, children }: FormClearProps): ReactNode {\n const getFieldsets = useFieldsetSnapshot();\n const { control } = useFormContext();\n const intl = useIntl();\n\n // Empties every field registered by every fieldset — not `FormRoot` recognising a field's type\n // (Invariant: it holds no field value and infers no field type). Each bound part registered its own\n // clearer, keyed by its own name, when `useBoundField` mounted it (`particles/field/field.tsx`); a\n // name with none registered — no bound part currently mounted for it — is left untouched.\n function handleClear() {\n for (const fieldset of getFieldsets()) {\n for (const name of fieldset.getFieldNames()) {\n clearBoundField(control, name);\n }\n }\n }\n\n return (\n <Button type=\"button\" onClick={handleClear} className={className} data-fs-form-clear=\"\">\n {children ?? label ?? intl.formatMessage({ id: 'fs/form.clear' })}\n </Button>\n );\n}\n\nexport function FormReset({ className, label, children }: FormResetProps): ReactNode {\n const getFieldsets = useFieldsetSnapshot();\n const { resetField } = useFormContext();\n const intl = useIntl();\n\n function handleReset() {\n for (const fieldset of getFieldsets()) {\n for (const name of fieldset.getFieldNames()) {\n resetField(name);\n }\n }\n }\n\n return (\n <Button type=\"button\" onClick={handleReset} className={className} data-fs-form-reset=\"\">\n {children ?? label ?? intl.formatMessage({ id: 'fs/form.reset' })}\n </Button>\n );\n}\n\nexport const Form = {\n Root: FormRoot,\n Submit: FormSubmit,\n EnterSubmit: FormEnterSubmit,\n Error: FormError,\n Clear: FormClear,\n Reset: FormReset,\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"form.js","names":[],"sources":["../../../src/particles/form/form.tsx"],"sourcesContent":["'use client';\nimport { type ContentValue, defineComponent, defineContentType, type MessageLocaleProp } from '@vtex/fs-core';\nimport type { ComponentPropsWithRef, Context, FormEvent, KeyboardEvent, ReactNode } from 'react';\nimport { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';\nimport { FormProvider, useForm, useFormContext, useFormState } from 'react-hook-form';\nimport { useMessageFormatter } from '../../sdk/i18n/use-message-formatter.js';\nimport { Button } from '../button/button.js';\nimport { clearBoundField } from '../field/bound-field-registry.js';\n\n// ---------------------------------------------------------------------------\n// Data models\n// ---------------------------------------------------------------------------\n\n/**\n * The structural minimum every SDK user-error type satisfies. `code` is optional so that every\n * shipped shape is assignable, including `RegionUserError`, the one that declares it optional;\n * `ShippingAddressUpdateErrorEntity`, `ClientProfileUserError`, `CartUserError` and\n * `SessionUserError` all declare `Readonly<{ code: string; message: string }>`. There is no shared\n * user-error type in the SDK to reuse.\n */\nexport type FormUserError = Readonly<{ code?: string; message: string }>;\n\n/** What one fieldset hands the form. The form learns nothing else about it. */\nexport type FieldsetRegistration = Readonly<{\n /** Matches the field-name prefix every one of this fieldset's controls registers under. */\n namespace: string;\n /** Every full, namespaced field name this fieldset currently has mounted. */\n getFieldNames: () => readonly string[];\n /**\n * Closes over the fieldset's own injected `$actions`. Rejecting is allowed; the form catches it.\n * Must settle: the form gives up on a dispatch still pending after `FORM_DISPATCH_TIMEOUT_MS` and\n * reports it as a failed write. Must also be idempotent: giving up on a dispatch does not cancel it,\n * so a timed-out write may already be landing on the server, and the same payload is re-dispatched on\n * the shopper's next submit while the field stays dirty. Each resolved error's `message` is already\n * worded from the fieldset's own `$content`, keyed on its `code`: `FormError` renders it as is.\n */\n dispatch: (payload: Record<string, unknown>) => Promise<readonly FormUserError[]>;\n /** Shapes react-hook-form's raw values into the mutation's payload, including type coercion. */\n toPayload: (values: Record<string, unknown>) => Record<string, unknown>;\n /**\n * Machine identifier for this fieldset's write. `FormError` renders it as the\n * `data-fs-form-error-item` attribute value and uses it in two React keys; it is never displayed,\n * because the visible text is each `userError`'s `message` (the fieldset's own copy) or `FormError`'s\n * `fallbackMessage`.\n * Its value is the kebab-case ASCII rendering of this registration's own `namespace`\n * (`shippingAddress` → `shipping-address`), so a stylesheet selecting\n * `[data-fs-form-error-item=\"…\"]` needs one predictable shape and no diacritics.\n */\n label: string;\n}>;\n\n/**\n * One fieldset's write that did not land. An empty `userErrors` means the dispatch rejected or never\n * settled within `FORM_DISPATCH_TIMEOUT_MS`; either way `FormError` renders `fallbackMessage`.\n */\nexport type FormWriteFailure = Readonly<{\n label: string;\n userErrors: readonly FormUserError[];\n}>;\n\nexport type FormRegistry = Readonly<{\n /** Stable for the life of the FormRoot. Returns the unregister function. */\n registerFieldset: (registration: FieldsetRegistration) => () => void;\n /** The last submit's failures, in dispatch order. */\n failures: readonly FormWriteFailure[];\n}>;\n\n// ---------------------------------------------------------------------------\n// Registry context\n// ---------------------------------------------------------------------------\n\nexport const FormRegistryContext: Context<FormRegistry | null> = createContext<FormRegistry | null>(null);\n\n/** Throws when no FormRoot is above the caller. */\nexport function useFormRegistry(): FormRegistry {\n const registry = useContext(FormRegistryContext);\n if (!registry) throw new Error('Form parts must be used inside FormRoot.');\n return registry;\n}\n\n/**\n * Internal-only seam between the six parts in this file. `FormClear` and `FormReset` iterate every\n * registered fieldset's field names (Invariant 11 — the form reaches a field name only through a\n * registration's `getFieldNames()`), which the public `FormRegistry` contract does not expose to a\n * fieldset — it only ever calls `registerFieldset` and reads `failures`. Not exported from this\n * module or the barrel.\n */\nconst FieldsetSnapshotContext = createContext<(() => readonly FieldsetRegistration[]) | null>(null);\n\nfunction useFieldsetSnapshot(): () => readonly FieldsetRegistration[] {\n const snapshot = useContext(FieldsetSnapshotContext);\n if (!snapshot) throw new Error('Form parts must be used inside FormRoot.');\n return snapshot;\n}\n\n/** Adds one token for as long as the caller is mounted; the returned cleanup removes that token. */\ntype AllowImplicitSubmission = (token: symbol) => () => void;\n\n/**\n * A second, internal-only seam beside `FieldsetSnapshotContext`, for the same reason: `FormEnterSubmit`\n * takes a form-wide keyboard allowance the public `FormRegistry` must not expose to a fieldset. Not\n * exported from this module or the barrel.\n */\nconst ImplicitSubmissionContext: Context<AllowImplicitSubmission | null> =\n createContext<AllowImplicitSubmission | null>(null);\n\n/**\n * Takes an allowance token for the life of the calling component, so `handleKeyDown` allows implicit\n * submission on this FormRoot's own text-entry inputs while at least one caller holds a token. Throws\n * the same error as every other part when there is no FormRoot above it.\n */\nfunction useAllowImplicitSubmission(): void {\n const allow = useContext(ImplicitSubmissionContext);\n // useState's lazy initialiser, not a ref written during render: it runs Symbol() exactly once, on\n // this component instance's first render, and every re-render reads back the same value.\n const [token] = useState(() => Symbol());\n\n useEffect(() => {\n if (!allow) return;\n return allow(token);\n }, [allow, token]);\n\n // All hooks above run unconditionally on every render; only this line is conditional, so throwing\n // here (rather than before the hooks) is not a rules-of-hooks violation.\n if (!allow) throw new Error('Form parts must be used inside FormRoot.');\n}\n\n/**\n * Two namespaces are in conflict when one equals, prefixes or is a descendant of the other —\n * `profile` collides with itself and with `profile.address` alike, because a fieldset under either\n * arrangement would dispatch on the other's edits and marshal its values into the wrong payload.\n */\nfunction namespacesCollide(a: string, b: string): boolean {\n if (a === b) return true;\n return a.startsWith(`${b}.`) || b.startsWith(`${a}.`);\n}\n\n/**\n * Is any of `names` dirty? React Hook Form nests `dirtyFields` by dot-path segment, so each full\n * field name is walked segment by segment rather than read as a flat key.\n *\n * Callers pass the names a fieldset's mounted controls currently hold, not its whole namespace. With\n * `shouldUnregister` unset, a control that has left the screen keeps its value and its dirty flag,\n * and nothing resets it — reconciliation, `FormReset` and `FormClear` all act on mounted names only.\n * Asking about the namespace would keep that flag reporting the fieldset dirty, so every later\n * submit would dispatch again for a field the shopper can no longer see, and the same holds for a\n * fieldset that has not mounted its controls yet.\n */\nfunction isAnyFieldDirty(dirtyFields: Record<string, unknown>, names: readonly string[]): boolean {\n return names.some((name) => {\n let node: unknown = dirtyFields;\n for (const segment of name.split('.')) {\n if (typeof node !== 'object' || node === null) return false;\n node = (node as Record<string, unknown>)[segment];\n }\n return Boolean(node);\n });\n}\n\n/**\n * Shallow-unsafe but adequate: field values are the primitives and plain records a bound Control\n * produces (strings, booleans, small objects), never functions or circular structures, so a\n * `JSON.stringify` comparison is a safe stand-in for a real deep-equal. Used only to tell whether a\n * shopper's keystroke landed while a dispatch was in flight (Decision 6) — a false \"changed\" verdict\n * merely means the field is resubmitted needlessly, never data loss.\n */\nfunction valuesEqual(a: unknown, b: unknown): boolean {\n return a === b || JSON.stringify(a) === JSON.stringify(b);\n}\n\n/**\n * Ceiling on one fieldset's `dispatch`. A dispatch that neither resolves nor rejects — a fetch to a\n * server that accepts the connection and never answers, for which browsers apply no default timeout —\n * would otherwise leave `onValid` awaiting forever, so the submit boundary's `finally` never runs and\n * the re-entrancy guard stays armed for the life of the page. This is not cancellation: the request\n * keeps running and may still reach the server, and the form stops waiting for it.\n *\n * The ceiling is per fieldset, not per submit: `onValid` visits dirty fieldsets one at a time, in\n * registration order, so a submit over *n* hung fieldsets takes up to *n* times this long to release.\n * That is measured and accepted, not overlooked (Decision 3) — the wait stays bounded and\n * self-releasing, since the submit boundary's `finally` always runs once the last ceiling fires.\n */\nexport const FORM_DISPATCH_TIMEOUT_MS = 30_000;\n\n/**\n * Resolves with the dispatch's own result, or rejects once `FORM_DISPATCH_TIMEOUT_MS` has elapsed,\n * whichever happens first. The no-op handler on `dispatch` is what stops a late rejection surfacing as\n * an unhandled rejection after the race has already been lost; the timer is cleared either way, so a\n * dispatch that settles normally leaves nothing pending.\n */\nfunction withDispatchTimeout(dispatch: Promise<readonly FormUserError[]>): Promise<readonly FormUserError[]> {\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n reject(new Error(`Dispatch exceeded FORM_DISPATCH_TIMEOUT_MS (${FORM_DISPATCH_TIMEOUT_MS}ms).`));\n }, FORM_DISPATCH_TIMEOUT_MS);\n\n dispatch.then(\n (userErrors) => {\n clearTimeout(timer);\n resolve(userErrors);\n },\n (error) => {\n clearTimeout(timer);\n reject(error);\n },\n );\n });\n}\n\n/**\n * The HTML spec's text-entry `<input>` types — the ones that block implicit submission for anything\n * other than the field a shopper is typing in. An `<input>` with no `type` attribute reports\n * `type === 'text'`, so it is covered without a separate case.\n */\nconst TEXT_ENTRY_INPUT_TYPES = new Set([\n 'text',\n 'search',\n 'url',\n 'tel',\n 'email',\n 'password',\n 'number',\n 'date',\n 'month',\n 'week',\n 'time',\n 'datetime-local',\n]);\n\n// ---------------------------------------------------------------------------\n// Prop types\n// ---------------------------------------------------------------------------\n\nexport type FormRootProps = Omit<\n ComponentPropsWithRef<'form'>,\n 'onSubmit' | 'action' | 'method' | 'target' | 'encType' | 'dangerouslySetInnerHTML'\n>;\nexport type FormSubmitProps = MessageLocaleProp & {\n $content?: ContentValue<typeof FormSubmitContent>;\n className?: string;\n children?: ReactNode;\n};\nexport type FormClearProps = MessageLocaleProp & {\n $content?: ContentValue<typeof FormClearContent>;\n className?: string;\n children?: ReactNode;\n};\nexport type FormResetProps = MessageLocaleProp & {\n $content?: ContentValue<typeof FormResetContent>;\n className?: string;\n children?: ReactNode;\n};\nexport type FormErrorProps = MessageLocaleProp & {\n /** The message shown for a fieldset whose write rejected rather than resolving with userErrors. */\n $content?: ContentValue<typeof FormErrorContent>;\n className?: string;\n};\n\n// ---------------------------------------------------------------------------\n// Definitions\n// ---------------------------------------------------------------------------\n\nexport const FormRootDefinition = defineComponent<FormRootProps>({\n name: 'FormRoot',\n importPath: '@vtex/faststore/components',\n component: FormRoot,\n providesContext: 'form',\n editor: { label: 'Form', category: 'action' },\n schema: {},\n guideline:\n \"The only <form> its own fieldset registry dispatches from — a composed CartCouponForm, ShippingSimulatorForm or RegionForm renders its own, and a submit-origin check keeps theirs out of this one. Calls react-hook-form's useForm() once and holds the registry a submit dispatches in registration order. Compose FormSubmit/FormEnterSubmit/FormError/FormClear/FormReset anywhere inside it, and a fieldset as a descendant to give the submit something to persist — FormRoot itself declares no actions.\",\n});\n\nexport const FormSubmitContent = defineContentType({\n id: 'form-submit',\n title: 'Form Submit',\n description: 'Label of the button that submits the form.',\n schema: {\n type: 'object',\n additionalProperties: false,\n properties: {\n label: { type: 'string', title: 'Label', format: 'icu-message', messageSource: 'Continue' },\n },\n },\n});\n\nexport const FormSubmitDefinition = defineComponent<FormSubmitProps>({\n name: 'FormSubmit',\n importPath: '@vtex/faststore/components',\n component: FormSubmit,\n content: FormSubmitContent,\n requiresContext: 'form',\n editor: { label: 'Form Submit', category: 'action' },\n schema: {},\n guideline:\n 'Submits every registered fieldset the shopper changed, in registration order, and disables itself while a write is in flight. Renders children, else its label message. A fieldset with nothing changed contributes no request; an invalid field blocks every dispatch and moves focus to it instead of submitting. Enter in a text input does not submit — see FormEnterSubmit for a form where it does.',\n});\n\nexport const FormEnterSubmitDefinition = defineComponent<FormSubmitProps>({\n name: 'FormEnterSubmit',\n importPath: '@vtex/faststore/components',\n component: FormEnterSubmit,\n content: FormSubmitContent,\n requiresContext: 'form',\n editor: { label: 'Form Enter Submit', category: 'action' },\n schema: {},\n guideline:\n 'Renders the same button as FormSubmit, sharing its content type (form-submit) and children, and additionally allows Enter to submit this form from any text-entry input while mounted. The allowance is form-scoped: placed inside one fieldset of a multi-fieldset FormRoot, it allows Enter for every text input in the enclosing form, not only that fieldset. Enter that commits an IME candidate never submits.',\n});\n\nexport const FormErrorContent = defineContentType({\n id: 'form-error',\n title: 'Form Error',\n description: 'Message shown for a fieldset whose write failed without saying why.',\n schema: {\n type: 'object',\n additionalProperties: false,\n properties: {\n fallbackMessage: {\n type: 'string',\n title: 'Fallback message',\n format: 'icu-message',\n messageSource: 'Something went wrong. Please try again.',\n },\n },\n },\n});\n\nexport const FormErrorDefinition = defineComponent<FormErrorProps>({\n name: 'FormError',\n importPath: '@vtex/faststore/components',\n component: FormError,\n content: FormErrorContent,\n requiresContext: 'form',\n editor: { label: 'Form Error', category: 'content' },\n schema: {},\n guideline:\n \"Renders the last submit's write failures grouped by fieldset, or nothing when there were none. The messages are the fieldsets' own copy: each fieldset words its refusals from its own $content, keyed on the error code. A fieldset whose write rejected rather than resolving with userErrors shows the fallbackMessage message.\",\n});\n\nexport const FormClearContent = defineContentType({\n id: 'form-clear',\n title: 'Form Clear',\n description: \"Label of the button that empties the form's fields.\",\n schema: {\n type: 'object',\n additionalProperties: false,\n properties: {\n label: { type: 'string', title: 'Label', format: 'icu-message', messageSource: 'Clear' },\n },\n },\n});\n\nexport const FormClearDefinition = defineComponent<FormClearProps>({\n name: 'FormClear',\n importPath: '@vtex/faststore/components',\n component: FormClear,\n content: FormClearContent,\n requiresContext: 'form',\n editor: { label: 'Form Clear', category: 'action' },\n schema: {},\n guideline:\n 'Empties every field registered by every fieldset inside the enclosing FormRoot, not only the nearest one, but marks dirty only the fields whose value actually changed — a field already empty stays clean. Renders children, else its label message. The following submit dispatches a write for every fieldset that had something to clear, and nothing for one where clearing was a no-op. There is no way to scope it to a single fieldset; place it only where clearing the whole form is the intended action, not by analogy with a per-field clear.',\n});\n\nexport const FormResetContent = defineContentType({\n id: 'form-reset',\n title: 'Form Reset',\n description: \"Label of the button that returns the form's fields to their baseline.\",\n schema: {\n type: 'object',\n additionalProperties: false,\n properties: {\n label: { type: 'string', title: 'Label', format: 'icu-message', messageSource: 'Reset' },\n },\n },\n});\n\nexport const FormResetDefinition = defineComponent<FormResetProps>({\n name: 'FormReset',\n importPath: '@vtex/faststore/components',\n component: FormReset,\n content: FormResetContent,\n requiresContext: 'form',\n editor: { label: 'Form Reset', category: 'action' },\n schema: {},\n guideline:\n \"Returns every registered field to react-hook-form's baseline for that name and clears its dirty/touched state. Renders children, else its label message. Before a fieldset's first successful write, that baseline is whatever the field's own seed resolves to — not empty — so Reset reverts to the original value rather than clearing it; only after a successful submit does the baseline become what was last written.\",\n});\n\n// ---------------------------------------------------------------------------\n// Parts\n// ---------------------------------------------------------------------------\n\nexport function FormRoot({ className, children, onKeyDown, ...props }: FormRootProps): ReactNode {\n const form = useForm();\n const {\n handleSubmit,\n // `dirtyFields` is destructured here, in render, on purpose. React Hook Form keeps `dirtyFields`\n // current whether or not anything reads it — the proxy on `formState` decides only whether a\n // change here re-renders the subscriber, not whether the underlying store is kept. What the\n // render-time read buys is freshness: the submit handler below closes over the copy from the\n // render that defined it, and subscribing here is what keeps that copy current by the time a\n // later submit reads it. (The per-fieldset check further down walks each mounted field's\n // dot-path through this object rather than indexing it by a single key — see `isAnyFieldDirty`.)\n formState: { dirtyFields, isSubmitting },\n getValues,\n resetField,\n } = form;\n\n const fieldsets = useRef(new Map<string, FieldsetRegistration>());\n /**\n * Insertion order of every namespace ever registered, independent of `fieldsets`' own Map order.\n * A namespace's slot here is created once and never moved — re-registering it (the cleanup-then-\n * effect cycle a changed dep triggers) deletes and re-adds the `fieldsets` entry, which would push\n * a plain `Map` iteration to the tail; reading dispatch order through this array instead keeps a\n * namespace in its original position across any number of re-registrations.\n */\n const order = useRef<string[]>([]);\n const submitting = useRef(false);\n const [failures, setFailures] = useState<readonly FormWriteFailure[]>([]);\n /**\n * One token per mounted part that allows implicit submission (Decision 1). A `Set`, not a boolean or\n * a count: two mounted allowing parts must compose, unmounting one must leave the allowance held by\n * the other in place, and a token's cleanup — including a double-invoked one under StrictMode — must\n * be a no-op once already removed. `handleKeyDown` only ever reads `.size`; nothing renders from it.\n */\n const allowance = useRef(new Set<symbol>());\n\n const registerFieldset = useCallback((registration: FieldsetRegistration) => {\n const { namespace } = registration;\n\n for (const existing of fieldsets.current.values()) {\n if (namespacesCollide(namespace, existing.namespace)) {\n throw new Error(\n `FormRoot already has a fieldset registered under namespace \"${existing.namespace}\", which collides with \"${namespace}\". Two different fieldsets cannot share a namespace or nest one inside the other — re-registering the same namespace is only valid once its previous registration has been unregistered.`,\n );\n }\n }\n\n if (!order.current.includes(namespace)) {\n order.current.push(namespace);\n }\n fieldsets.current.set(namespace, registration);\n\n return () => {\n if (fieldsets.current.get(namespace) === registration) {\n fieldsets.current.delete(namespace);\n }\n };\n }, []);\n\n const getFieldsetSnapshot = useCallback(\n () => order.current.flatMap((namespace) => fieldsets.current.get(namespace) ?? []),\n [],\n );\n\n const registerAllowance = useCallback((token: symbol) => {\n allowance.current.add(token);\n return () => {\n allowance.current.delete(token);\n };\n }, []);\n\n const onValid = useCallback(async () => {\n setFailures([]);\n const collected: FormWriteFailure[] = [];\n const snapshot = getFieldsetSnapshot();\n\n for (const fieldset of snapshot) {\n let preDispatchValues: ReadonlyArray<readonly [string, unknown]>;\n let userErrors: readonly FormUserError[];\n try {\n const fieldNames = fieldset.getFieldNames();\n if (!isAnyFieldDirty(dirtyFields, fieldNames)) continue;\n preDispatchValues = fieldNames.map((name) => [name, getValues(name)] as const);\n const payload = fieldset.toPayload(getValues(fieldset.namespace) ?? {});\n userErrors = await withDispatchTimeout(fieldset.dispatch(payload));\n } catch {\n // Threw, timed out, or could not build its payload — collected as a failure either way, and\n // the queue moves on: the next fieldset's dispatch never depends on this one's code being\n // sound.\n collected.push({ label: fieldset.label, userErrors: [] });\n continue;\n }\n\n if (userErrors.length > 0) {\n collected.push({ label: fieldset.label, userErrors });\n continue;\n }\n\n // Reconcile against the values captured before the await, not the live ones (Decision 6).\n // A name whose live value still matches what was captured is safe to reconcile: the write\n // targeted exactly that value, so moving the baseline there is invisible. A name whose live\n // value has since diverged means a keystroke landed mid-write — it is left untouched, so it\n // stays dirty and is picked up, unsent, by the next submit.\n //\n // Deliberately outside the try above: the write already succeeded (no userErrors), so a\n // `resetField` that throws here is a reconciliation fault, not a write fault, and must not be\n // reported to the shopper as one.\n for (const [name, capturedValue] of preDispatchValues) {\n if (valuesEqual(getValues(name), capturedValue)) {\n resetField(name, { defaultValue: capturedValue });\n }\n }\n }\n\n setFailures(collected);\n }, [dirtyFields, getValues, resetField, getFieldsetSnapshot]);\n\n const onInvalid = useCallback(() => {\n setFailures([]);\n }, []);\n\n /**\n * Ignores a submit event whose origin isn't this FormRoot's own <form>. Submit events bubble, so a\n * nested <form>'s own submission — the shape CartCouponForm, ShippingSimulatorForm and RegionForm\n * each render when composed inside a checkout FormRoot — reaches this handler too; without this\n * check, that bubbled event would run react-hook-form's handleSubmit and commit an entity write the\n * shopper never asked this FormRoot to make. Mirrors handleKeyDown's own origin check (there scoped\n * by `target.form`), for the same reason: a nested form is never this one.\n *\n * Two properties of where this check sits are load-bearing. First, it reads `event.currentTarget`\n * before any `await`: React nulls `currentTarget` once the synchronous part of a handler returns,\n * so the same comparison placed after an await degrades to `event.target !== null` — always true —\n * and rejects every submit, a permanently dead submit button with no error raised. It needs no test\n * of its own: inserting an await above this check fails most of the tests in form.test.tsx, and\n * moving it below the awaited `handleSubmit(...)` below fails the nested-form test in *Implicit\n * submission*. Second, it runs before the re-entrancy check immediately below: while this form's own\n * write is in flight, `submitting.current` is `true`, so a bubbled nested submit that reached the\n * re-entrancy check first would call `event.preventDefault()` and cancel a nested form's own\n * submission that this FormRoot never rendered. The last test in *Re-entrancy* pins that second\n * property; nothing caught it before that test existed.\n */\n const handleFormSubmit = useCallback(\n async (event: FormEvent<HTMLFormElement>) => {\n if (event.target !== event.currentTarget) return;\n\n if (submitting.current) {\n event.preventDefault();\n return;\n }\n\n submitting.current = true;\n try {\n await handleSubmit(onValid, onInvalid)(event);\n } finally {\n // Released after the awaited handler, not inside onValid: react-hook-form flips\n // formState.isSubmitting to false in the statement immediately before its returned promise\n // settles, so releasing here keeps the guard armed for a superset of the window in which\n // isSubmitting is true. Releasing earlier — inside onValid's own finally, where this guard\n // used to live — would open a sliver in which a third submit is accepted while isSubmitting\n // is still true, reintroducing the defect this guard exists to close.\n submitting.current = false;\n }\n },\n [handleSubmit, onValid, onInvalid],\n );\n\n /**\n * Cancels HTML implicit submission by default. A text input inside a form with a default button\n * submits that form on Enter, which for an entity form means committing a write from a keystroke a\n * shopper means as \"look this up\" or \"next field\" — before they have finished editing the rest of\n * the sendable unit. That default is form-scoped and opt-in to override: mounting `FormEnterSubmit`\n * anywhere inside this FormRoot allows Enter to submit from any of this form's own text-entry\n * inputs, not only the fieldset the allowing part happens to sit in; a form composing only\n * `FormSubmit` keeps today's cancelling behaviour. Enter that commits an IME candidate is cancelled\n * either way, allowance or not, so choosing a word never submits a half-finished form. Submitting\n * stays fully keyboard-operable either way, through a focusable native `FormSubmit`/`FormEnterSubmit`\n * button, so no capability is removed (WCAG 2.1 SC 2.1.1). Scoped to text-entry inputs by target, so\n * Enter on a button, a link, a `<textarea>`, a `contentEditable` region or a Base UI select trigger is\n * untouched, and scoped to Enter, so typing is untouched. Also scoped to this form's own inputs by\n * `target.form`: a keydown from a nested `<form>`'s own control bubbles up here too, and without that\n * check this guard would cancel implicit submission for a form it never rendered. Composes rather\n * than replaces an author-supplied `onKeyDown`: theirs runs first, unconditionally, before any of\n * this guard's own checks — it can cancel Enter on an allowing form, but it cannot force Enter on a\n * cancelling one, because this guard's own `preventDefault()` runs after it.\n */\n const handleKeyDown = useCallback(\n (event: KeyboardEvent<HTMLFormElement>) => {\n onKeyDown?.(event);\n if (event.key !== 'Enter' || event.defaultPrevented) return;\n\n const { target } = event;\n if (!(target instanceof HTMLInputElement) || !TEXT_ENTRY_INPUT_TYPES.has(target.type)) return;\n if (target.form !== event.currentTarget) return;\n if (allowance.current.size > 0 && !event.nativeEvent.isComposing) return;\n\n event.preventDefault();\n },\n [onKeyDown],\n );\n\n const registry = useMemo<FormRegistry>(() => ({ registerFieldset, failures }), [registerFieldset, failures]);\n\n return (\n <form\n {...props}\n noValidate\n onSubmit={handleFormSubmit}\n onKeyDown={handleKeyDown}\n className={className}\n data-fs-form=\"\"\n data-fs-form-pending={isSubmitting ? '' : undefined}\n >\n <FormProvider {...form}>\n <FormRegistryContext.Provider value={registry}>\n <FieldsetSnapshotContext.Provider value={getFieldsetSnapshot}>\n <ImplicitSubmissionContext.Provider value={registerAllowance}>\n {children}\n </ImplicitSubmissionContext.Provider>\n </FieldsetSnapshotContext.Provider>\n </FormRegistryContext.Provider>\n </FormProvider>\n </form>\n );\n}\n\n/**\n * The shared render for both submit parts: same button, same hooks, same data-fs-form-submit hook.\n * Both read the `form-submit` content type: they render the same button.\n */\nfunction SubmitButton({ $content, className, children }: Readonly<FormSubmitProps>): ReactNode {\n const { isSubmitting } = useFormState();\n const { format } = useMessageFormatter(FormSubmitContent, $content);\n\n return (\n <Button\n type=\"submit\"\n disabled={isSubmitting}\n className={className}\n data-fs-form-submit=\"\"\n data-fs-form-submit-pending={isSubmitting ? '' : undefined}\n >\n {children ?? format('label')}\n </Button>\n );\n}\n\nexport function FormSubmit(props: FormSubmitProps): ReactNode {\n useFormRegistry();\n return <SubmitButton {...props} />;\n}\n\n/**\n * Renders the same button as `FormSubmit` and additionally allows Enter to submit this FormRoot's own\n * text-entry inputs while mounted — see `handleKeyDown`'s own doc for the form-scoped allowance and\n * the IME carve-out.\n */\nexport function FormEnterSubmit(props: FormSubmitProps): ReactNode {\n useFormRegistry();\n useAllowImplicitSubmission();\n return <SubmitButton {...props} />;\n}\n\nexport function FormError({ $content, className }: FormErrorProps): ReactNode {\n const { failures } = useFormRegistry();\n const { format } = useMessageFormatter(FormErrorContent, $content);\n\n if (failures.length === 0) return null;\n\n return (\n <div role=\"alert\" className={className} data-fs-form-error=\"\">\n {failures.map((failure, failureIndex) => (\n <ul key={`${failure.label}-${failureIndex}`} data-fs-form-error-item={failure.label}>\n {failure.userErrors.length > 0 ? (\n failure.userErrors.map((error, errorIndex) => (\n <li key={`${failure.label}-${failureIndex}-${errorIndex}`}>{error.message}</li>\n ))\n ) : (\n <li>{format('fallbackMessage')}</li>\n )}\n </ul>\n ))}\n </div>\n );\n}\n\nexport function FormClear({ $content, className, children }: Readonly<FormClearProps>): ReactNode {\n const getFieldsets = useFieldsetSnapshot();\n const { control } = useFormContext();\n const { format } = useMessageFormatter(FormClearContent, $content);\n\n // Empties every field registered by every fieldset — not `FormRoot` recognising a field's type\n // (Invariant: it holds no field value and infers no field type). Each bound part registered its own\n // clearer, keyed by its own name, when `useBoundField` mounted it (`particles/field/field.tsx`); a\n // name with none registered — no bound part currently mounted for it — is left untouched.\n function handleClear() {\n for (const fieldset of getFieldsets()) {\n for (const name of fieldset.getFieldNames()) {\n clearBoundField(control, name);\n }\n }\n }\n\n return (\n <Button type=\"button\" onClick={handleClear} className={className} data-fs-form-clear=\"\">\n {children ?? format('label')}\n </Button>\n );\n}\n\nexport function FormReset({ $content, className, children }: Readonly<FormResetProps>): ReactNode {\n const getFieldsets = useFieldsetSnapshot();\n const { resetField } = useFormContext();\n const { format } = useMessageFormatter(FormResetContent, $content);\n\n function handleReset() {\n for (const fieldset of getFieldsets()) {\n for (const name of fieldset.getFieldNames()) {\n resetField(name);\n }\n }\n }\n\n return (\n <Button type=\"button\" onClick={handleReset} className={className} data-fs-form-reset=\"\">\n {children ?? format('label')}\n </Button>\n );\n}\n\nexport const Form = {\n Root: FormRoot,\n Submit: FormSubmit,\n EnterSubmit: FormEnterSubmit,\n Error: FormError,\n Clear: FormClear,\n Reset: FormReset,\n};\n"],"mappings":"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"}
@@ -1,7 +1,122 @@
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, ReactNode } from "react";
4
5
  //#region src/particles/gallery/gallery.d.ts
6
+ export declare const GalleryOverflowCountContent: {
7
+ readonly id: "gallery-overflow-count";
8
+ readonly title: "Gallery Overflow Count";
9
+ readonly description: "Text and accessible name of the overflow indicator that opens the fullscreen gallery.";
10
+ readonly schema: {
11
+ readonly type: "object";
12
+ readonly additionalProperties: false;
13
+ readonly properties: {
14
+ readonly template: {
15
+ readonly type: "string";
16
+ readonly title: "Text";
17
+ readonly description: "The count argument is the number of hidden media items.";
18
+ readonly format: "icu-message";
19
+ readonly messageSource: "+{count}";
20
+ readonly messageArguments: {
21
+ readonly type: "object";
22
+ readonly properties: {
23
+ readonly count: {
24
+ readonly type: "integer";
25
+ };
26
+ };
27
+ };
28
+ readonly messageExample: {
29
+ readonly count: 3;
30
+ };
31
+ };
32
+ readonly ariaLabel: {
33
+ readonly type: "string";
34
+ readonly title: "Accessible label";
35
+ readonly description: "The total argument is the number of media items in the gallery.";
36
+ readonly format: "icu-message";
37
+ readonly messageSource: "View all {total} images";
38
+ readonly messageArguments: {
39
+ readonly type: "object";
40
+ readonly properties: {
41
+ readonly total: {
42
+ readonly type: "integer";
43
+ };
44
+ };
45
+ };
46
+ readonly messageExample: {
47
+ readonly total: 8;
48
+ };
49
+ };
50
+ };
51
+ };
52
+ };
53
+ export declare const GalleryFullscreenContent: {
54
+ readonly id: "gallery-fullscreen";
55
+ readonly title: "Gallery Fullscreen";
56
+ readonly description: "Accessible name of the fullscreen dialog when no GalleryFullscreenTitle is composed.";
57
+ readonly schema: {
58
+ readonly type: "object";
59
+ readonly additionalProperties: false;
60
+ readonly properties: {
61
+ readonly title: {
62
+ readonly type: "string";
63
+ readonly title: "Fallback title";
64
+ readonly format: "icu-message";
65
+ readonly messageSource: "Gallery";
66
+ };
67
+ };
68
+ };
69
+ };
70
+ export declare const GalleryFullscreenTitleContent: {
71
+ readonly id: "gallery-fullscreen-title";
72
+ readonly title: "Gallery Fullscreen Title";
73
+ readonly description: "Title of the fullscreen dialog, used when no children are composed.";
74
+ readonly schema: {
75
+ readonly type: "object";
76
+ readonly additionalProperties: false;
77
+ readonly properties: {
78
+ readonly label: {
79
+ readonly type: "string";
80
+ readonly title: "Title";
81
+ readonly format: "icu-message";
82
+ readonly messageSource: "Gallery";
83
+ };
84
+ };
85
+ };
86
+ };
87
+ export declare const GalleryMediaCountContent: {
88
+ readonly id: "gallery-media-count";
89
+ readonly title: "Gallery Media Count";
90
+ readonly description: "Position of the selected media item in the gallery.";
91
+ readonly schema: {
92
+ readonly type: "object";
93
+ readonly additionalProperties: false;
94
+ readonly properties: {
95
+ readonly template: {
96
+ readonly type: "string";
97
+ readonly title: "Text";
98
+ readonly description: "current is the 1-based position of the selected item; total is the item count.";
99
+ readonly format: "icu-message";
100
+ readonly messageSource: "{current} / {total}";
101
+ readonly messageArguments: {
102
+ readonly type: "object";
103
+ readonly properties: {
104
+ readonly current: {
105
+ readonly type: "integer";
106
+ };
107
+ readonly total: {
108
+ readonly type: "integer";
109
+ };
110
+ };
111
+ };
112
+ readonly messageExample: {
113
+ readonly current: 2;
114
+ readonly total: 8;
115
+ };
116
+ };
117
+ };
118
+ };
119
+ };
5
120
  export type GalleryMediaType = 'image' | 'video';
6
121
  export type GalleryMediaItem = {
7
122
  type: GalleryMediaType;
@@ -86,9 +201,8 @@ export type GalleryThumbnailProps = ComponentPropsWithRef<'button'> & {
86
201
  objectFit?: 'contain' | 'cover' | 'fill' | 'none';
87
202
  aspectRatio?: string;
88
203
  };
89
- export type GalleryOverflowCountProps = ComponentPropsWithRef<'button'> & {
90
- template?: string;
91
- ariaLabel?: string;
204
+ export type GalleryOverflowCountProps = ComponentPropsWithRef<'button'> & MessageLocaleProp & {
205
+ $content?: ContentValue<typeof GalleryOverflowCountContent>;
92
206
  };
93
207
  export type GalleryMediaProps = ComponentPropsWithRef<'div'> & {
94
208
  objectFit?: 'contain' | 'cover' | 'fill' | 'none';
@@ -103,10 +217,13 @@ export type GalleryZoomProps = ComponentPropsWithRef<'div'> & {
103
217
  };
104
218
  export type GalleryZoomLensProps = ComponentPropsWithRef<'div'>;
105
219
  export type GalleryZoomResultProps = ComponentPropsWithRef<'div'>;
106
- export type GalleryFullscreenProps = ComponentPropsWithRef<'div'> & {
220
+ export type GalleryFullscreenProps = ComponentPropsWithRef<'div'> & MessageLocaleProp & {
107
221
  children?: ReactNode;
222
+ $content?: ContentValue<typeof GalleryFullscreenContent>;
223
+ };
224
+ export type GalleryFullscreenTitleProps = ComponentPropsWithRef<'h2'> & MessageLocaleProp & {
225
+ $content?: ContentValue<typeof GalleryFullscreenTitleContent>;
108
226
  };
109
- export type GalleryFullscreenTitleProps = ComponentPropsWithRef<'h2'>;
110
227
  export type GalleryFullscreenCloseProps = ComponentPropsWithRef<'button'> & {
111
228
  children?: ReactNode;
112
229
  };
@@ -118,8 +235,8 @@ export type GalleryNextProps = ComponentPropsWithRef<'button'> & {
118
235
  children?: ReactNode;
119
236
  wrap?: boolean;
120
237
  };
121
- export type GalleryMediaCountProps = ComponentPropsWithRef<'span'> & {
122
- template?: string;
238
+ export type GalleryMediaCountProps = ComponentPropsWithRef<'span'> & MessageLocaleProp & {
239
+ $content?: ContentValue<typeof GalleryMediaCountContent>;
123
240
  };
124
241
  export declare const GalleryItemContext: import("react").Context<GalleryItemContextValue | null>;
125
242
  export declare function useGallery(): GalleryContextValue;
@@ -136,7 +253,7 @@ export declare const GalleryZoomDefinition: ComponentDefinition<GalleryZoomProps
136
253
  export declare const GalleryZoomLensDefinition: ComponentDefinition<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>>;
137
254
  export declare const GalleryZoomResultDefinition: ComponentDefinition<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>>;
138
255
  export declare const GalleryFullscreenDefinition: ComponentDefinition<GalleryFullscreenProps>;
139
- export declare const GalleryFullscreenTitleDefinition: ComponentDefinition<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLHeadingElement>, HTMLHeadingElement>>;
256
+ export declare const GalleryFullscreenTitleDefinition: ComponentDefinition<GalleryFullscreenTitleProps>;
140
257
  export declare const GalleryFullscreenCloseDefinition: ComponentDefinition<GalleryFullscreenCloseProps>;
141
258
  export declare const GalleryPreviousDefinition: ComponentDefinition<GalleryPreviousProps>;
142
259
  export declare const GalleryNextDefinition: ComponentDefinition<GalleryNextProps>;
@@ -145,19 +262,19 @@ export declare function GalleryRoot({ media, defaultIndex, selectOnHover, thumbn
145
262
  export declare function GalleryMainMedia({ objectFit, aspectRatio, videoAutoPlay, videoControls, clickOpensFullscreen, style, ...props }: GalleryMainMediaProps): import("react/jsx-runtime").JSX.Element;
146
263
  export declare function GalleryThumbnails({ hideWhenSingle, ...rest }: GalleryThumbnailsProps): import("react/jsx-runtime").JSX.Element | null;
147
264
  export declare function GalleryThumbnail({ objectFit, aspectRatio, style, ...props }: GalleryThumbnailProps): import("react/jsx-runtime").JSX.Element;
148
- export declare function GalleryOverflowCount({ template, ariaLabel, ...props }: GalleryOverflowCountProps): import("react/jsx-runtime").JSX.Element | null;
265
+ export declare function GalleryOverflowCount({ $locale, $content, ...props }: GalleryOverflowCountProps): import("react/jsx-runtime").JSX.Element | null;
149
266
  export declare function GalleryMedia({ objectFit, aspectRatio, videoAutoPlay, videoControls, clickOpensFullscreen, style, ...props }: GalleryMediaProps): import("react/jsx-runtime").JSX.Element;
150
267
  export declare function GalleryZoom({ magnification, lensSize, children, ...props }: GalleryZoomProps): import("react/jsx-runtime").JSX.Element;
151
268
  export declare function GalleryZoomLens({ style, ...props }: GalleryZoomLensProps): import("react/jsx-runtime").JSX.Element | null;
152
269
  export declare function GalleryZoomResult({ style, ...props }: GalleryZoomResultProps): import("react/jsx-runtime").JSX.Element;
153
- export declare function GalleryFullscreen({ children, ...props }: GalleryFullscreenProps): import("react/jsx-runtime").JSX.Element;
154
- export declare function GalleryFullscreenTitle({ children, ...props }: GalleryFullscreenTitleProps): import("react/jsx-runtime").JSX.Element;
270
+ export declare function GalleryFullscreen({ $locale, $content, children, ...props }: GalleryFullscreenProps): import("react/jsx-runtime").JSX.Element;
271
+ export declare function GalleryFullscreenTitle({ $locale, $content, children, ...props }: GalleryFullscreenTitleProps): import("react/jsx-runtime").JSX.Element;
155
272
  export declare function GalleryFullscreenClose({ children, ...props }: GalleryFullscreenCloseProps): import("react/jsx-runtime").JSX.Element;
156
273
  export declare function GalleryPrevious({ children, wrap, ...props }: GalleryPreviousProps): import("react/jsx-runtime").JSX.Element;
157
274
  export declare function GalleryNext({ children, wrap, ...props }: GalleryNextProps): import("react/jsx-runtime").JSX.Element;
158
275
  export declare function GalleryThumbnailsPrevious({ step, children, ...props }: GalleryThumbnailsPreviousProps): import("react/jsx-runtime").JSX.Element;
159
276
  export declare function GalleryThumbnailsNext({ step, children, ...props }: GalleryThumbnailsNextProps): import("react/jsx-runtime").JSX.Element;
160
- export declare function GalleryMediaCount({ template, ...props }: GalleryMediaCountProps): import("react/jsx-runtime").JSX.Element;
277
+ export declare function GalleryMediaCount({ $locale, $content, ...props }: GalleryMediaCountProps): import("react/jsx-runtime").JSX.Element;
161
278
  export declare const Gallery: {
162
279
  Root: typeof GalleryRoot;
163
280
  MainMedia: typeof GalleryMainMedia;