@vtex/faststore 0.0.6 → 0.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (488) hide show
  1. package/CHANGELOG.md +99 -0
  2. package/dist/actions.json +152 -1
  3. package/dist/catalog.json +2541 -1278
  4. package/dist/cli/UnreachableCaseError-Crd168Vu.js +10 -0
  5. package/dist/cli/UnreachableCaseError-Crd168Vu.js.map +1 -0
  6. package/dist/cli/cacheControl-CEojH_TM.js +158 -0
  7. package/dist/cli/cacheControl-CEojH_TM.js.map +1 -0
  8. package/dist/cli/cachePolicy-m2vASMRW.js +26 -0
  9. package/dist/cli/cachePolicy-m2vASMRW.js.map +1 -0
  10. package/dist/cli/computeCoreSchemaHash-DPJZj-qJ.js +10 -0
  11. package/dist/cli/computeCoreSchemaHash-DPJZj-qJ.js.map +1 -0
  12. package/dist/cli/default-BCQHcwbL.js +253 -0
  13. package/dist/cli/default-BCQHcwbL.js.map +1 -0
  14. package/dist/cli/disableSuggestions-yO9UqiWn.js +21 -0
  15. package/dist/cli/disableSuggestions-yO9UqiWn.js.map +1 -0
  16. package/dist/cli/dist-C1JhdHfo.js +2001 -0
  17. package/dist/cli/dist-C1JhdHfo.js.map +1 -0
  18. package/dist/cli/graphql-DG9thCDG.js +14589 -0
  19. package/dist/cli/graphql-DG9thCDG.js.map +1 -0
  20. package/dist/cli/index.d.ts +799 -0
  21. package/dist/cli/index.js +36459 -0
  22. package/dist/cli/index.js.map +1 -0
  23. package/dist/cli/index.min-BsIHDfFK.js +613 -0
  24. package/dist/cli/index.min-BsIHDfFK.js.map +1 -0
  25. package/dist/cli/inlineTrace-uLgOJ3TH.js +52 -0
  26. package/dist/cli/inlineTrace-uLgOJ3TH.js.map +1 -0
  27. package/dist/cli/internalPlugin-DnuwN4_4.js +11 -0
  28. package/dist/cli/internalPlugin-DnuwN4_4.js.map +1 -0
  29. package/dist/cli/packageVersion-DQAnIEil.js +6 -0
  30. package/dist/cli/packageVersion-DQAnIEil.js.map +1 -0
  31. package/dist/cli/rolldown-runtime-BMI-E3GI.js +44 -0
  32. package/dist/cli/schemaIsSubgraph-DoGh3OYj.js +17 -0
  33. package/dist/cli/schemaIsSubgraph-DoGh3OYj.js.map +1 -0
  34. package/dist/cli/schemaReporting-K-me-3-v.js +199 -0
  35. package/dist/cli/schemaReporting-K-me-3-v.js.map +1 -0
  36. package/dist/cli/server-runtime.js +49879 -0
  37. package/dist/cli/server-runtime.js.map +1 -0
  38. package/dist/cli/traceTreeBuilder-BIcV2U7b.js +9118 -0
  39. package/dist/cli/traceTreeBuilder-BIcV2U7b.js.map +1 -0
  40. package/dist/cli/usageReporting-Bpl8vSZX.js +10201 -0
  41. package/dist/cli/usageReporting-Bpl8vSZX.js.map +1 -0
  42. package/dist/cli/v4-CBhFvC49.js +42 -0
  43. package/dist/cli/v4-CBhFvC49.js.map +1 -0
  44. package/dist/client.d.ts +5 -1
  45. package/dist/client.js +5 -1
  46. package/dist/components.d.ts +38 -9
  47. package/dist/components.js +42 -13
  48. package/dist/content-types.json +616 -0
  49. package/dist/core/dist/define-component.d.ts +43 -1
  50. package/dist/core/dist/index.d.ts +2 -2
  51. package/dist/docs/account-access-gate.md +4 -4
  52. package/dist/docs/account-address-book.md +519 -0
  53. package/dist/docs/account-entry-point.md +1 -1
  54. package/dist/docs/account-menu-identity.md +160 -0
  55. package/dist/docs/account-menu.md +107 -24
  56. package/dist/docs/alert-dialog.md +2 -2
  57. package/dist/docs/avatar.md +103 -0
  58. package/dist/docs/billing-address.md +17 -9
  59. package/dist/docs/card-entry.md +37 -6
  60. package/dist/docs/cardholder-document.md +16 -14
  61. package/dist/docs/cart-item.md +1 -1
  62. package/dist/docs/cart.md +8 -8
  63. package/dist/docs/client-profile-fieldset.md +7 -5
  64. package/dist/docs/copy-text.md +84 -0
  65. package/dist/docs/document-field.md +8 -8
  66. package/dist/docs/footer-link-group.md +2 -2
  67. package/dist/docs/header-root.md +1 -1
  68. package/dist/docs/incentives.md +2 -2
  69. package/dist/docs/logo.md +5 -5
  70. package/dist/docs/my-account-profile.md +5 -5
  71. package/dist/docs/navigation-link-list.md +2 -2
  72. package/dist/docs/navigation-link.md +3 -3
  73. package/dist/docs/order-cancel.md +52 -0
  74. package/dist/docs/order-delivery-address.md +63 -0
  75. package/dist/docs/order-delivery-group.md +83 -0
  76. package/dist/docs/order-details-back.md +41 -0
  77. package/dist/docs/order-details-header.md +48 -0
  78. package/dist/docs/order-list-row.md +46 -0
  79. package/dist/docs/order-list-search.md +101 -0
  80. package/dist/docs/order-list-views.md +97 -0
  81. package/dist/docs/order-list.md +94 -0
  82. package/dist/docs/order-payment.md +94 -0
  83. package/dist/docs/order-placed-date.md +49 -0
  84. package/dist/docs/order-placed-payment-summary.md +13 -15
  85. package/dist/docs/order-placed.md +225 -0
  86. package/dist/docs/order-progress.md +88 -0
  87. package/dist/docs/order-status-badge.md +91 -0
  88. package/dist/docs/order-summary.md +53 -0
  89. package/dist/docs/payment-method-badges.md +14 -3
  90. package/dist/docs/place-order.md +13 -9
  91. package/dist/docs/product-shelf.md +20 -13
  92. package/dist/docs/saved-cards.md +2 -2
  93. package/dist/docs/select.md +19 -6
  94. package/dist/docs/session.md +1 -1
  95. package/dist/docs/shipping-address.md +1 -1
  96. package/dist/docs/sign-in-redirect.md +6 -6
  97. package/dist/docs/toast.md +7 -3
  98. package/dist/index.d.ts +7 -3
  99. package/dist/index.js +2 -1
  100. package/dist/internal/client.d.ts +6 -1
  101. package/dist/internal/client.js +8 -3
  102. package/dist/internal/content.d.ts +2 -2
  103. package/dist/internal/server.d.ts +8 -1
  104. package/dist/internal/server.js +8 -1
  105. package/dist/matter/account-access-gate/account-access-gate.d.ts +2 -1
  106. package/dist/matter/account-access-gate/account-access-gate.js +19 -16
  107. package/dist/matter/account-access-gate/account-access-gate.js.map +1 -1
  108. package/dist/matter/account-address-book/account-address-book-delete.d.ts +60 -0
  109. package/dist/matter/account-address-book/account-address-book-delete.js +184 -0
  110. package/dist/matter/account-address-book/account-address-book-delete.js.map +1 -0
  111. package/dist/matter/account-address-book/account-address-book-deliverability.d.ts +19 -0
  112. package/dist/matter/account-address-book/account-address-book-deliverability.js +50 -0
  113. package/dist/matter/account-address-book/account-address-book-deliverability.js.map +1 -0
  114. package/dist/matter/account-address-book/account-address-book-form-parts.d.ts +42 -0
  115. package/dist/matter/account-address-book/account-address-book-form-parts.js +146 -0
  116. package/dist/matter/account-address-book/account-address-book-form-parts.js.map +1 -0
  117. package/dist/matter/account-address-book/account-address-book-profile-notice.d.ts +25 -0
  118. package/dist/matter/account-address-book/account-address-book-profile-notice.js +72 -0
  119. package/dist/matter/account-address-book/account-address-book-profile-notice.js.map +1 -0
  120. package/dist/matter/account-address-book/account-address-book.d.ts +120 -0
  121. package/dist/matter/account-address-book/account-address-book.js +469 -0
  122. package/dist/matter/account-address-book/account-address-book.js.map +1 -0
  123. package/dist/matter/account-address-book/account-address-country-switch.js +59 -0
  124. package/dist/matter/account-address-book/account-address-country-switch.js.map +1 -0
  125. package/dist/matter/account-address-book/account-address-country.d.ts +36 -0
  126. package/dist/matter/account-address-book/account-address-country.js +151 -0
  127. package/dist/matter/account-address-book/account-address-country.js.map +1 -0
  128. package/dist/matter/account-address-book/account-address-first-line.js +11 -0
  129. package/dist/matter/account-address-book/account-address-first-line.js.map +1 -0
  130. package/dist/matter/account-address-book/account-address-form-context.d.ts +55 -0
  131. package/dist/matter/account-address-book/account-address-form-context.js +14 -0
  132. package/dist/matter/account-address-book/account-address-form-context.js.map +1 -0
  133. package/dist/matter/account-address-book/account-address-form.d.ts +85 -0
  134. package/dist/matter/account-address-book/account-address-form.js +946 -0
  135. package/dist/matter/account-address-book/account-address-form.js.map +1 -0
  136. package/dist/matter/account-address-book/account-address-postal-autofill.js +189 -0
  137. package/dist/matter/account-address-book/account-address-postal-autofill.js.map +1 -0
  138. package/dist/matter/account-address-book/account-address-record.d.ts +26 -0
  139. package/dist/matter/account-address-book/account-address-record.js +138 -0
  140. package/dist/matter/account-address-book/account-address-record.js.map +1 -0
  141. package/dist/matter/account-entry-point/account-entry-point.js +11 -11
  142. package/dist/matter/account-entry-point/account-entry-point.js.map +1 -1
  143. package/dist/matter/account-menu/account-menu.d.ts +77 -3
  144. package/dist/matter/account-menu/account-menu.js +252 -19
  145. package/dist/matter/account-menu/account-menu.js.map +1 -1
  146. package/dist/matter/account-menu/sign-out-failure.js +50 -0
  147. package/dist/matter/account-menu/sign-out-failure.js.map +1 -0
  148. package/dist/matter/account-menu-identity/account-menu-identity.d.ts +21 -0
  149. package/dist/matter/account-menu-identity/account-menu-identity.js +88 -0
  150. package/dist/matter/account-menu-identity/account-menu-identity.js.map +1 -0
  151. package/dist/matter/billing-address/billing-address.d.ts +30 -17
  152. package/dist/matter/billing-address/billing-address.js +128 -33
  153. package/dist/matter/billing-address/billing-address.js.map +1 -1
  154. package/dist/matter/breadcrumb/breadcrumb.js +2 -2
  155. package/dist/matter/breadcrumb/breadcrumb.js.map +1 -1
  156. package/dist/matter/card-entry/card-capture.js +4 -3
  157. package/dist/matter/card-entry/card-capture.js.map +1 -1
  158. package/dist/matter/card-entry/card-entry.d.ts +5 -3
  159. package/dist/matter/card-entry/card-entry.js +78 -27
  160. package/dist/matter/card-entry/card-entry.js.map +1 -1
  161. package/dist/matter/cardholder-document/cardholder-document.d.ts +10 -9
  162. package/dist/matter/cardholder-document/cardholder-document.js +36 -16
  163. package/dist/matter/cardholder-document/cardholder-document.js.map +1 -1
  164. package/dist/matter/cart/cart.d.ts +7 -2
  165. package/dist/matter/cart/cart.js +29 -26
  166. package/dist/matter/cart/cart.js.map +1 -1
  167. package/dist/matter/cart-item/cart-item.js +2 -2
  168. package/dist/matter/cart-item/cart-item.js.map +1 -1
  169. package/dist/matter/client-preferences/client-preferences-fieldset.js +2 -2
  170. package/dist/matter/client-profile-form/client-profile-fieldset.js +9 -6
  171. package/dist/matter/client-profile-form/client-profile-fieldset.js.map +1 -1
  172. package/dist/matter/identity-edit/identity-edit.js +3 -3
  173. package/dist/matter/identity-edit/identity-edit.js.map +1 -1
  174. package/dist/matter/identity-summary/identity-summary.js +4 -3
  175. package/dist/matter/identity-summary/identity-summary.js.map +1 -1
  176. package/dist/matter/my-account-profile/my-account-profile.d.ts +6 -3
  177. package/dist/matter/my-account-profile/my-account-profile.js +6 -5
  178. package/dist/matter/my-account-profile/my-account-profile.js.map +1 -1
  179. package/dist/matter/order-cancel/order-cancel.d.ts +110 -0
  180. package/dist/matter/order-cancel/order-cancel.js +344 -0
  181. package/dist/matter/order-cancel/order-cancel.js.map +1 -0
  182. package/dist/matter/order-delivery-address/order-delivery-address.d.ts +73 -0
  183. package/dist/matter/order-delivery-address/order-delivery-address.js +172 -0
  184. package/dist/matter/order-delivery-address/order-delivery-address.js.map +1 -0
  185. package/dist/matter/order-delivery-group/order-delivery-group.d.ts +128 -0
  186. package/dist/matter/order-delivery-group/order-delivery-group.js +408 -0
  187. package/dist/matter/order-delivery-group/order-delivery-group.js.map +1 -0
  188. package/dist/matter/order-details-header/order-details-header.d.ts +104 -0
  189. package/dist/matter/order-details-header/order-details-header.js +190 -0
  190. package/dist/matter/order-details-header/order-details-header.js.map +1 -0
  191. package/dist/matter/order-list/customer-orders-filter.d.ts +12 -0
  192. package/dist/matter/order-list/customer-orders-filter.js +30 -0
  193. package/dist/matter/order-list/customer-orders-filter.js.map +1 -0
  194. package/dist/matter/order-list/order-list.d.ts +121 -0
  195. package/dist/matter/order-list/order-list.js +395 -0
  196. package/dist/matter/order-list/order-list.js.map +1 -0
  197. package/dist/matter/order-list-row/order-list-row.d.ts +44 -0
  198. package/dist/matter/order-list-row/order-list-row.js +127 -0
  199. package/dist/matter/order-list-row/order-list-row.js.map +1 -0
  200. package/dist/matter/order-list-search/order-list-search.d.ts +72 -0
  201. package/dist/matter/order-list-search/order-list-search.js +296 -0
  202. package/dist/matter/order-list-search/order-list-search.js.map +1 -0
  203. package/dist/matter/order-list-views/order-list-views.d.ts +65 -0
  204. package/dist/matter/order-list-views/order-list-views.js +154 -0
  205. package/dist/matter/order-list-views/order-list-views.js.map +1 -0
  206. package/dist/matter/order-payment/order-payment.d.ts +83 -0
  207. package/dist/matter/order-payment/order-payment.js +258 -0
  208. package/dist/matter/order-payment/order-payment.js.map +1 -0
  209. package/dist/matter/order-placed/order-placed-deliveries.d.ts +145 -0
  210. package/dist/matter/order-placed/order-placed-deliveries.js +380 -0
  211. package/dist/matter/order-placed/order-placed-deliveries.js.map +1 -0
  212. package/dist/matter/order-placed/order-placed.d.ts +122 -0
  213. package/dist/matter/order-placed/order-placed.js +452 -0
  214. package/dist/matter/order-placed/order-placed.js.map +1 -0
  215. package/dist/matter/order-placed-date/order-placed-date.d.ts +45 -0
  216. package/dist/matter/order-placed-date/order-placed-date.js +92 -0
  217. package/dist/matter/order-placed-date/order-placed-date.js.map +1 -0
  218. package/dist/matter/order-placed-payment-summary/order-placed-payment-summary.d.ts +5 -8
  219. package/dist/matter/order-placed-payment-summary/order-placed-payment-summary.js +29 -81
  220. package/dist/matter/order-placed-payment-summary/order-placed-payment-summary.js.map +1 -1
  221. package/dist/matter/order-progress/order-progress.d.ts +85 -0
  222. package/dist/matter/order-progress/order-progress.js +203 -0
  223. package/dist/matter/order-progress/order-progress.js.map +1 -0
  224. package/dist/matter/order-summary/order-summary.d.ts +81 -0
  225. package/dist/matter/order-summary/order-summary.js +192 -0
  226. package/dist/matter/order-summary/order-summary.js.map +1 -0
  227. package/dist/matter/payment/cardholder-document-rule.d.ts +35 -0
  228. package/dist/matter/payment/cardholder-document-rule.js +35 -0
  229. package/dist/matter/payment/cardholder-document-rule.js.map +1 -0
  230. package/dist/matter/payment/payment-card-capture.js +38 -23
  231. package/dist/matter/payment/payment-card-capture.js.map +1 -1
  232. package/dist/matter/payment/payment-controller.js +12 -0
  233. package/dist/matter/payment/payment-controller.js.map +1 -1
  234. package/dist/matter/payment/payment-method-badges.js +4 -2
  235. package/dist/matter/payment/payment-method-badges.js.map +1 -1
  236. package/dist/matter/payment/payment.js +12 -0
  237. package/dist/matter/payment/payment.js.map +1 -1
  238. package/dist/matter/payment/use-payment-method-selection.d.ts +39 -0
  239. package/dist/matter/payment/use-payment-method-selection.js +30 -2
  240. package/dist/matter/payment/use-payment-method-selection.js.map +1 -1
  241. package/dist/matter/payment/use-payment-submit-gate.d.ts +16 -2
  242. package/dist/matter/payment/use-payment-submit-gate.js +42 -14
  243. package/dist/matter/payment/use-payment-submit-gate.js.map +1 -1
  244. package/dist/matter/place-order/place-order.d.ts +12 -7
  245. package/dist/matter/place-order/place-order.js +126 -103
  246. package/dist/matter/place-order/place-order.js.map +1 -1
  247. package/dist/matter/pricing/pricing.js +5 -5
  248. package/dist/matter/pricing/pricing.js.map +1 -1
  249. package/dist/matter/product-shelf/product-shelf.d.ts +61 -31
  250. package/dist/matter/product-shelf/product-shelf.js +157 -57
  251. package/dist/matter/product-shelf/product-shelf.js.map +1 -1
  252. package/dist/matter/region/region.js +1 -1
  253. package/dist/matter/saved-cards/saved-cards.js +27 -15
  254. package/dist/matter/saved-cards/saved-cards.js.map +1 -1
  255. package/dist/matter/session/session.js +2 -2
  256. package/dist/matter/session/session.js.map +1 -1
  257. package/dist/matter/shipping-address/country-descriptors.d.ts +1 -0
  258. package/dist/matter/shipping-address/country-descriptors.js +23 -1
  259. package/dist/matter/shipping-address/country-descriptors.js.map +1 -1
  260. package/dist/matter/shipping-address/shipping-address.js +63 -15
  261. package/dist/matter/shipping-address/shipping-address.js.map +1 -1
  262. package/dist/matter/shipping-simulator/shipping-simulator.d.ts +1 -1
  263. package/dist/matter/shipping-simulator/shipping-simulator.js.map +1 -1
  264. package/dist/matter/sign-in-redirect/sign-in-redirect.js +48 -10
  265. package/dist/matter/sign-in-redirect/sign-in-redirect.js.map +1 -1
  266. package/dist/matter/variant-selector/variant-selector.js +2 -2
  267. package/dist/matter/variant-selector/variant-selector.js.map +1 -1
  268. package/dist/particles/address-summary/address-summary.js +2 -2
  269. package/dist/particles/address-summary/address-summary.js.map +1 -1
  270. package/dist/particles/alert-dialog/alert-dialog.d.ts +5 -1
  271. package/dist/particles/alert-dialog/alert-dialog.js +5 -2
  272. package/dist/particles/alert-dialog/alert-dialog.js.map +1 -1
  273. package/dist/particles/avatar/avatar.d.ts +17 -0
  274. package/dist/particles/avatar/avatar.js +65 -0
  275. package/dist/particles/avatar/avatar.js.map +1 -0
  276. package/dist/particles/copy-text/copy-text.d.ts +28 -0
  277. package/dist/particles/copy-text/copy-text.js +140 -0
  278. package/dist/particles/copy-text/copy-text.js.map +1 -0
  279. package/dist/particles/document-field/document-field.d.ts +34 -5
  280. package/dist/particles/document-field/document-field.js +115 -19
  281. package/dist/particles/document-field/document-field.js.map +1 -1
  282. package/dist/particles/field/field.js +1 -1
  283. package/dist/particles/field/field.js.map +1 -1
  284. package/dist/particles/footer-link-group/footer-link-group.d.ts +6 -2
  285. package/dist/particles/footer-link-group/footer-link-group.js +18 -7
  286. package/dist/particles/footer-link-group/footer-link-group.js.map +1 -1
  287. package/dist/particles/incentives/incentives.d.ts +6 -2
  288. package/dist/particles/incentives/incentives.js +7 -2
  289. package/dist/particles/incentives/incentives.js.map +1 -1
  290. package/dist/particles/logo/logo.d.ts +3 -2
  291. package/dist/particles/logo/logo.js +20 -8
  292. package/dist/particles/logo/logo.js.map +1 -1
  293. package/dist/particles/navigation-link/navigation-link.d.ts +2 -3
  294. package/dist/particles/navigation-link/navigation-link.js +4 -4
  295. package/dist/particles/navigation-link/navigation-link.js.map +1 -1
  296. package/dist/particles/navigation-link-list/navigation-link-list.d.ts +6 -2
  297. package/dist/particles/navigation-link-list/navigation-link-list.js +18 -7
  298. package/dist/particles/navigation-link-list/navigation-link-list.js.map +1 -1
  299. package/dist/particles/order-details-back/order-details-back.d.ts +28 -0
  300. package/dist/particles/order-details-back/order-details-back.js +52 -0
  301. package/dist/particles/order-details-back/order-details-back.js.map +1 -0
  302. package/dist/particles/order-status-badge/order-status-badge.d.ts +19 -0
  303. package/dist/particles/order-status-badge/order-status-badge.js +50 -0
  304. package/dist/particles/order-status-badge/order-status-badge.js.map +1 -0
  305. package/dist/particles/phone-field/phone-field.js +2 -2
  306. package/dist/particles/phone-field/phone-field.js.map +1 -1
  307. package/dist/particles/select/select.js +6 -6
  308. package/dist/particles/select/select.js.map +1 -1
  309. package/dist/particles/toast/toast.d.ts +1 -1
  310. package/dist/particles/toast/toast.js +32 -6
  311. package/dist/particles/toast/toast.js.map +1 -1
  312. package/dist/schema.graphql +1079 -54
  313. package/dist/sdk/actions/address-action-provider.d.ts +16 -0
  314. package/dist/sdk/actions/address-action-provider.js +20 -0
  315. package/dist/sdk/actions/address-action-provider.js.map +1 -0
  316. package/dist/sdk/actions/analytics-action-provider.js +1 -1
  317. package/dist/sdk/actions/index.d.ts +3 -1
  318. package/dist/sdk/actions/index.js +3 -1
  319. package/dist/sdk/actions/order-action-provider.d.ts +12 -0
  320. package/dist/sdk/actions/order-action-provider.js +16 -0
  321. package/dist/sdk/actions/order-action-provider.js.map +1 -0
  322. package/dist/sdk/actions/types.d.ts +6 -2
  323. package/dist/sdk/address/address-fields.js +38 -0
  324. package/dist/sdk/address/address-fields.js.map +1 -0
  325. package/dist/sdk/address/checkout-readiness.js +17 -0
  326. package/dist/sdk/address/checkout-readiness.js.map +1 -0
  327. package/dist/sdk/address/constants.js +60 -0
  328. package/dist/sdk/address/constants.js.map +1 -0
  329. package/dist/sdk/address/country-display.js +19 -0
  330. package/dist/sdk/address/country-display.js.map +1 -0
  331. package/dist/sdk/address/country-rules.js +30 -0
  332. package/dist/sdk/address/country-rules.js.map +1 -0
  333. package/dist/sdk/address/format-address.js +18 -0
  334. package/dist/sdk/address/format-address.js.map +1 -0
  335. package/dist/sdk/address/iso-countries.js +262 -0
  336. package/dist/sdk/address/iso-countries.js.map +1 -0
  337. package/dist/sdk/address/layouts.js +56 -0
  338. package/dist/sdk/address/layouts.js.map +1 -0
  339. package/dist/sdk/address/messages.js +97 -0
  340. package/dist/sdk/address/messages.js.map +1 -0
  341. package/dist/sdk/address/operations.d.ts +54 -0
  342. package/dist/sdk/address/operations.js +83 -0
  343. package/dist/sdk/address/operations.js.map +1 -0
  344. package/dist/sdk/address/postal-code-lookup-operations.js +23 -0
  345. package/dist/sdk/address/postal-code-lookup-operations.js.map +1 -0
  346. package/dist/sdk/address/postal-code.js +11 -0
  347. package/dist/sdk/address/postal-code.js.map +1 -0
  348. package/dist/sdk/address/schema.js +14 -0
  349. package/dist/sdk/address/schema.js.map +1 -0
  350. package/dist/sdk/address/server-fields.js +25 -0
  351. package/dist/sdk/address/server-fields.js.map +1 -0
  352. package/dist/sdk/address/switch-country.js +57 -0
  353. package/dist/sdk/address/switch-country.js.map +1 -0
  354. package/dist/sdk/address/types.d.ts +26 -0
  355. package/dist/sdk/address/use-address-actions.d.ts +29 -0
  356. package/dist/sdk/address/use-address-actions.js +247 -0
  357. package/dist/sdk/address/use-address-actions.js.map +1 -0
  358. package/dist/sdk/address/use-address-by-postal-code.js +57 -0
  359. package/dist/sdk/address/use-address-by-postal-code.js.map +1 -0
  360. package/dist/sdk/address/validate-address.js +62 -0
  361. package/dist/sdk/address/validate-address.js.map +1 -0
  362. package/dist/sdk/analytics/use-analytics-actions.js +2 -1
  363. package/dist/sdk/analytics/use-analytics-actions.js.map +1 -1
  364. package/dist/sdk/cache/storefront-cache.js +29 -4
  365. package/dist/sdk/cache/storefront-cache.js.map +1 -1
  366. package/dist/sdk/cart/use-cart-actions.js +9 -8
  367. package/dist/sdk/cart/use-cart-actions.js.map +1 -1
  368. package/dist/sdk/cart/use-cart-validate-on-open.js +2 -1
  369. package/dist/sdk/cart/use-cart-validate-on-open.js.map +1 -1
  370. package/dist/sdk/client/fetch-page-data.d.ts +11 -0
  371. package/dist/sdk/client/fetch-page-data.js +12 -1
  372. package/dist/sdk/client/fetch-page-data.js.map +1 -1
  373. package/dist/sdk/content/create-content-runtime.d.ts +22 -1
  374. package/dist/sdk/content/create-content-runtime.js +90 -9
  375. package/dist/sdk/content/create-content-runtime.js.map +1 -1
  376. package/dist/sdk/data/empty-content-value.js +16 -0
  377. package/dist/sdk/data/empty-content-value.js.map +1 -0
  378. package/dist/sdk/data/failed-fields.js +23 -0
  379. package/dist/sdk/data/failed-fields.js.map +1 -0
  380. package/dist/sdk/data/hot-data-provider.js +2 -1
  381. package/dist/sdk/data/hot-data-provider.js.map +1 -1
  382. package/dist/sdk/data/index.js +1 -1
  383. package/dist/sdk/data/page-reactive-data-root.d.ts +45 -7
  384. package/dist/sdk/data/page-reactive-data-root.js +88 -12
  385. package/dist/sdk/data/page-reactive-data-root.js.map +1 -1
  386. package/dist/sdk/data/variables-from-content.d.ts +43 -0
  387. package/dist/sdk/data/variables-from-content.js +57 -0
  388. package/dist/sdk/data/variables-from-content.js.map +1 -0
  389. package/dist/sdk/generated/fragment-types.js +2 -0
  390. package/dist/sdk/generated/fragment-types.js.map +1 -1
  391. package/dist/sdk/generated/gql.js +4 -1
  392. package/dist/sdk/generated/gql.js.map +1 -1
  393. package/dist/sdk/generated/graphql.d.ts +8 -0
  394. package/dist/sdk/generated/graphql.js +296 -1
  395. package/dist/sdk/generated/graphql.js.map +1 -1
  396. package/dist/sdk/i18n/messages/en-US.js +138 -1
  397. package/dist/sdk/i18n/messages/en-US.json +138 -1
  398. package/dist/sdk/i18n/messages/en-US.json.d.ts +137 -0
  399. package/dist/sdk/i18n/messages/es-ES.js +138 -1
  400. package/dist/sdk/i18n/messages/es-ES.json +138 -1
  401. package/dist/sdk/i18n/messages/pt-BR.js +138 -1
  402. package/dist/sdk/i18n/messages/pt-BR.json +138 -1
  403. package/dist/sdk/identity/use-identity-actions.js +5 -4
  404. package/dist/sdk/identity/use-identity-actions.js.map +1 -1
  405. package/dist/sdk/navigation/current-page.js +30 -0
  406. package/dist/sdk/navigation/current-page.js.map +1 -0
  407. package/dist/sdk/navigation/not-found-log.d.ts +28 -0
  408. package/dist/sdk/navigation/not-found-log.js +133 -0
  409. package/dist/sdk/navigation/not-found-log.js.map +1 -0
  410. package/dist/sdk/navigation/path.js +25 -0
  411. package/dist/sdk/navigation/path.js.map +1 -0
  412. package/dist/sdk/navigation/redirect.d.ts +11 -0
  413. package/dist/sdk/navigation/redirect.js +22 -0
  414. package/dist/sdk/navigation/redirect.js.map +1 -0
  415. package/dist/sdk/navigation/report.js +70 -0
  416. package/dist/sdk/navigation/report.js.map +1 -0
  417. package/dist/sdk/navigation/resolve-storefront-href.d.ts +12 -0
  418. package/dist/sdk/navigation/resolve-storefront-href.js +214 -0
  419. package/dist/sdk/navigation/resolve-storefront-href.js.map +1 -0
  420. package/dist/sdk/navigation/route-identity-provider.d.ts +11 -0
  421. package/dist/sdk/navigation/route-identity-provider.js +20 -0
  422. package/dist/sdk/navigation/route-identity-provider.js.map +1 -0
  423. package/dist/sdk/navigation/route-map-provider.d.ts +19 -0
  424. package/dist/sdk/navigation/route-map-provider.js +29 -0
  425. package/dist/sdk/navigation/route-map-provider.js.map +1 -0
  426. package/dist/sdk/navigation/storefront-link.d.ts +16 -0
  427. package/dist/sdk/navigation/storefront-link.js +66 -0
  428. package/dist/sdk/navigation/storefront-link.js.map +1 -0
  429. package/dist/sdk/navigation/types.d.ts +45 -0
  430. package/dist/sdk/navigation/use-storefront-navigation.d.ts +26 -0
  431. package/dist/sdk/navigation/use-storefront-navigation.js +73 -0
  432. package/dist/sdk/navigation/use-storefront-navigation.js.map +1 -0
  433. package/dist/sdk/navigation/use-storefront-route.d.ts +26 -0
  434. package/dist/sdk/navigation/use-storefront-route.js +87 -0
  435. package/dist/sdk/navigation/use-storefront-route.js.map +1 -0
  436. package/dist/sdk/navigation/use-storefront-search-params.d.ts +11 -0
  437. package/dist/sdk/navigation/use-storefront-search-params.js +16 -0
  438. package/dist/sdk/navigation/use-storefront-search-params.js.map +1 -0
  439. package/dist/sdk/orders/completion-badge.d.ts +8 -0
  440. package/dist/sdk/orders/completion-badge.js +47 -0
  441. package/dist/sdk/orders/completion-badge.js.map +1 -0
  442. package/dist/sdk/orders/order-operations.d.ts +19 -0
  443. package/dist/sdk/orders/order-operations.js +21 -0
  444. package/dist/sdk/orders/order-operations.js.map +1 -0
  445. package/dist/sdk/orders/use-order-actions.d.ts +23 -0
  446. package/dist/sdk/orders/use-order-actions.js +62 -0
  447. package/dist/sdk/orders/use-order-actions.js.map +1 -0
  448. package/dist/sdk/payment/gateway-origin.js +26 -13
  449. package/dist/sdk/payment/gateway-origin.js.map +1 -1
  450. package/dist/sdk/payment/gateway.d.ts +14 -2
  451. package/dist/sdk/payment/gateway.js +32 -14
  452. package/dist/sdk/payment/gateway.js.map +1 -1
  453. package/dist/sdk/payment/operations.js +11 -0
  454. package/dist/sdk/payment/operations.js.map +1 -1
  455. package/dist/sdk/payment/submission-registry.d.ts +2 -1
  456. package/dist/sdk/payment/submission-registry.js +12 -8
  457. package/dist/sdk/payment/submission-registry.js.map +1 -1
  458. package/dist/sdk/payment/use-payment-actions.d.ts +5 -3
  459. package/dist/sdk/payment/use-payment-actions.js +6 -3
  460. package/dist/sdk/payment/use-payment-actions.js.map +1 -1
  461. package/dist/sdk/payment/use-place-order.d.ts +6 -3
  462. package/dist/sdk/payment/use-place-order.js +334 -144
  463. package/dist/sdk/payment/use-place-order.js.map +1 -1
  464. package/dist/sdk/region/use-region-actions.js +2 -1
  465. package/dist/sdk/region/use-region-actions.js.map +1 -1
  466. package/dist/sdk/seo/page-alternates.d.ts +55 -0
  467. package/dist/sdk/seo/page-alternates.js +132 -0
  468. package/dist/sdk/seo/page-alternates.js.map +1 -0
  469. package/dist/sdk/session/read-server-session.d.ts +21 -0
  470. package/dist/sdk/session/read-server-session.js +61 -0
  471. package/dist/sdk/session/read-server-session.js.map +1 -0
  472. package/dist/sdk/session/use-session-actions.js +5 -4
  473. package/dist/sdk/session/use-session-actions.js.map +1 -1
  474. package/dist/sdk/session/use-session-revalidation.js +2 -1
  475. package/dist/sdk/session/use-session-revalidation.js.map +1 -1
  476. package/dist/sdk/shipping/use-shipping-actions.js +3 -2
  477. package/dist/sdk/shipping/use-shipping-actions.js.map +1 -1
  478. package/dist/utils/own-value.js +19 -0
  479. package/dist/utils/own-value.js.map +1 -0
  480. package/dist/utils/safe-href.d.ts +11 -0
  481. package/dist/utils/safe-href.js +31 -22
  482. package/dist/utils/safe-href.js.map +1 -1
  483. package/package.json +17 -2
  484. package/skills/storefront-asset/SKILL.md +111 -0
  485. package/skills/storefront-asset/references/api-side.md +153 -0
  486. package/skills/storefront-asset/references/findings.md +40 -0
  487. package/skills/storefront-asset/references/ui-side.md +94 -0
  488. package/src/styles/tailwind.css +27 -0
@@ -1,8 +1,51 @@
1
+ import { ContentValue } 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 { ProductListItem } from "../product-list/product-list.js";
4
5
  import { ComponentPropsWithRef } from "react";
5
6
  //#region src/matter/product-shelf/product-shelf.d.ts
7
+ export declare const ProductShelfContent: {
8
+ readonly id: "product-shelf";
9
+ readonly title: "Product Shelf";
10
+ readonly description: "Which products a shelf shows: how many, in which order, and from which facet.";
11
+ readonly schema: {
12
+ readonly type: "object";
13
+ readonly additionalProperties: false;
14
+ readonly properties: {
15
+ readonly first: {
16
+ readonly type: "integer";
17
+ readonly title: "Number of products";
18
+ readonly minimum: 1;
19
+ readonly maximum: 100;
20
+ };
21
+ readonly sort: {
22
+ readonly type: "string";
23
+ readonly enum: readonly ["relevance", "price_asc", "price_desc", "name_asc", "name_desc", "release", "orders", "discount"];
24
+ readonly title: "Sort";
25
+ };
26
+ readonly categoryId: {
27
+ readonly type: "string";
28
+ readonly title: "Category ID";
29
+ };
30
+ readonly brandId: {
31
+ readonly type: "string";
32
+ readonly title: "Brand ID";
33
+ };
34
+ readonly collectionId: {
35
+ readonly type: "string";
36
+ readonly title: "Collection ID";
37
+ };
38
+ readonly searchTerm: {
39
+ readonly type: "string";
40
+ readonly title: "Search term";
41
+ };
42
+ readonly availableOnly: {
43
+ readonly type: "boolean";
44
+ readonly title: "Available only";
45
+ };
46
+ };
47
+ };
48
+ };
6
49
  type RawMoney = {
7
50
  amount: number;
8
51
  currencyCode: string;
@@ -54,62 +97,49 @@ export type ProductShelfItem = ProductListItem;
54
97
  export type ProductShelfSort = 'relevance' | 'price_asc' | 'price_desc' | 'name_asc' | 'name_desc' | 'release' | 'orders' | 'discount';
55
98
  export type ProductSortField = 'TITLE' | 'PRICE' | 'RELEASE_DATE' | 'RELEVANCE' | 'BEST_SELLING';
56
99
  export type SortDirection = 'ASC' | 'DESC';
57
- export type ProductsFilterInput = {
58
- searchTerm?: string;
59
- categoryIds?: string[];
60
- brandIds?: string[];
61
- collectionId?: string;
62
- specifications?: Array<{
63
- name: string;
64
- values: string[];
65
- }>;
66
- availableOnly?: boolean;
67
- };
68
- export type ProductShelfVariables = {
69
- first: number;
70
- orderBy?: {
71
- field: ProductSortField;
72
- direction: SortDirection;
73
- };
74
- filter: ProductsFilterInput;
75
- };
100
+ /**
101
+ * The query configuration the shelf resolved for this element: the content slice when the
102
+ * merchant filled a field, else the prop. The query has already applied these values; the
103
+ * context republishes them for parts that describe the shelf (a "sorted by" label, a facet link).
104
+ */
76
105
  export type ProductShelfConfig = {
77
- first?: number;
78
- itemsPerPage?: number;
79
- sort?: ProductShelfSort;
106
+ first: number;
107
+ sort: ProductShelfSort;
80
108
  searchTerm?: string;
81
109
  categoryId?: string;
82
110
  brandId?: string;
83
111
  collectionId?: string;
84
- specifications?: Array<{
85
- name: string;
86
- values: string[];
87
- }>;
88
- availableOnly?: boolean;
112
+ availableOnly: boolean;
89
113
  };
90
114
  export type ProductShelfContextValue = {
91
115
  itemsPerPage: number;
92
- variables: ProductShelfVariables;
116
+ config: ProductShelfConfig;
93
117
  count: number;
94
118
  };
95
- export type ProductShelfRootProps = ComponentPropsWithRef<'section'> & ProductShelfConfig & {
119
+ export type ProductShelfRootProps = ComponentPropsWithRef<'section'> & Partial<ProductShelfConfig> & {
120
+ itemsPerPage?: number;
96
121
  /** When true, card prices render tax-inclusive (from each item's tax data). Default false. */
97
122
  usePriceWithTaxes?: boolean;
98
123
  /** Text for the tax label part when tax display is on. Default `'Tax included'`. */
99
124
  taxesLabel?: string;
100
125
  products?: ProductShelfItem[];
126
+ /** Injected by the compiler, sliced from the page's or layout's composite content entry. */
127
+ $content?: ContentValue<typeof ProductShelfContent>;
101
128
  $data?: ProductShelfData | null;
102
129
  };
103
130
  export type ProductShelfItemsProps = ComponentPropsWithRef<'div'>;
104
131
  export type ProductShelfHeadingProps = ComponentPropsWithRef<'h2'>;
105
132
  export declare function useProductShelf(): ProductShelfContextValue;
106
133
  export declare function useProductShelfItem(): ProductShelfItem;
107
- export declare function buildProductShelfVariables(config: ProductShelfConfig): ProductShelfVariables;
134
+ export declare const PRODUCT_SHELF_SORT_MAP: Record<ProductShelfSort, {
135
+ field: ProductSortField;
136
+ direction: SortDirection;
137
+ }>;
108
138
  export declare function transformProducts(data: ProductShelfData): ProductShelfItem[];
109
139
  export declare const ProductShelfRootDefinition: ComponentDefinition<ProductShelfRootProps>;
110
140
  export declare const ProductShelfItemsDefinition: ComponentDefinition<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>>;
111
141
  export declare const ProductShelfHeadingDefinition: ComponentDefinition<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLHeadingElement>, HTMLHeadingElement>>;
112
- export declare function ProductShelfRoot({ first, itemsPerPage, sort, searchTerm, categoryId, brandId, collectionId, specifications, availableOnly, usePriceWithTaxes, taxesLabel, products, $data: $dataProp, className, children, ...props }: ProductShelfRootProps): import("react/jsx-runtime").JSX.Element | null;
142
+ export declare function ProductShelfRoot({ first, itemsPerPage, sort, searchTerm, categoryId, brandId, collectionId, availableOnly, usePriceWithTaxes, taxesLabel, products, $content, $data: $dataProp, className, children, ...props }: ProductShelfRootProps): import("react/jsx-runtime").JSX.Element | null;
113
143
  export declare namespace ProductShelfRoot {
114
144
  var Skeleton: typeof ProductShelfSkeleton;
115
145
  }
@@ -1,16 +1,79 @@
1
1
  "use client";
2
2
  import { defineComponent } from "../../core/dist/define-component.js";
3
+ import { defineContentType } from "../../core/dist/define-content-type.js";
3
4
  import "../../core/dist/index.js";
4
5
  import { useDataOverride } from "../../sdk/data/data-override-context.js";
5
6
  import { Text } from "../../particles/text/text.js";
6
7
  import { ProductListConfigContext, ProductListItemContext } from "../product-list/product-list.js";
7
8
  import { CarouselTrack } from "../../particles/carousel/carousel.js";
9
+ import { isEmptyContentValue } from "../../sdk/data/empty-content-value.js";
8
10
  import { createContext, useCallback, useContext, useEffect, useId, useMemo, useState } from "react";
9
11
  import { jsx, jsxs } from "react/jsx-runtime";
10
12
  //#region src/matter/product-shelf/product-shelf.tsx
13
+ const ProductShelfContent = defineContentType({
14
+ id: "product-shelf",
15
+ title: "Product Shelf",
16
+ description: "Which products a shelf shows: how many, in which order, and from which facet.",
17
+ schema: {
18
+ type: "object",
19
+ additionalProperties: false,
20
+ properties: {
21
+ first: {
22
+ type: "integer",
23
+ title: "Number of products",
24
+ minimum: 1,
25
+ maximum: 100
26
+ },
27
+ sort: {
28
+ type: "string",
29
+ enum: [
30
+ "relevance",
31
+ "price_asc",
32
+ "price_desc",
33
+ "name_asc",
34
+ "name_desc",
35
+ "release",
36
+ "orders",
37
+ "discount"
38
+ ],
39
+ title: "Sort"
40
+ },
41
+ categoryId: {
42
+ type: "string",
43
+ title: "Category ID"
44
+ },
45
+ brandId: {
46
+ type: "string",
47
+ title: "Brand ID"
48
+ },
49
+ collectionId: {
50
+ type: "string",
51
+ title: "Collection ID"
52
+ },
53
+ searchTerm: {
54
+ type: "string",
55
+ title: "Search term"
56
+ },
57
+ availableOnly: {
58
+ type: "boolean",
59
+ title: "Available only"
60
+ }
61
+ }
62
+ }
63
+ });
11
64
  const fragment = `
12
65
  fragment ProductShelfData on Query {
13
- products(first: 12, orderBy: { field: RELEVANCE, direction: DESC }) {
66
+ products(
67
+ first: $first
68
+ orderBy: $orderBy
69
+ filter: {
70
+ categoryIds: $categoryId
71
+ brandIds: $brandId
72
+ collectionId: $collectionId
73
+ searchTerm: $searchTerm
74
+ availableOnly: $availableOnly
75
+ }
76
+ ) {
14
77
  edges {
15
78
  node {
16
79
  id
@@ -88,7 +151,7 @@ function useProductShelfItem() {
88
151
  if (!item) throw new Error("Product card components must be used inside ProductShelfItems.");
89
152
  return item;
90
153
  }
91
- const SORT_MAP = {
154
+ const PRODUCT_SHELF_SORT_MAP = {
92
155
  relevance: {
93
156
  field: "RELEVANCE",
94
157
  direction: "DESC"
@@ -122,21 +185,6 @@ const SORT_MAP = {
122
185
  direction: "DESC"
123
186
  }
124
187
  };
125
- function buildProductShelfVariables(config) {
126
- const { first = 5, sort = "relevance", searchTerm, categoryId, brandId, collectionId, specifications, availableOnly } = config;
127
- const filter = {};
128
- if (searchTerm) filter.searchTerm = searchTerm;
129
- if (categoryId) filter.categoryIds = [categoryId];
130
- if (brandId) filter.brandIds = [brandId];
131
- if (collectionId) filter.collectionId = collectionId;
132
- if (specifications && specifications.length > 0) filter.specifications = specifications;
133
- if (availableOnly) filter.availableOnly = true;
134
- return {
135
- first,
136
- orderBy: SORT_MAP[sort],
137
- filter
138
- };
139
- }
140
188
  function transformProducts(data) {
141
189
  return data.edges.map(({ node }) => {
142
190
  const image = node.images.edges[0]?.node;
@@ -175,21 +223,69 @@ const ProductShelfRootDefinition = defineComponent({
175
223
  fragment,
176
224
  fetchStrategy: "lazy",
177
225
  skeleton: ProductShelfSkeleton,
226
+ content: ProductShelfContent,
227
+ variables: { orderBy: {
228
+ from: "sort",
229
+ values: {
230
+ relevance: {
231
+ field: "RELEVANCE",
232
+ direction: "DESC"
233
+ },
234
+ price_asc: {
235
+ field: "PRICE",
236
+ direction: "ASC"
237
+ },
238
+ price_desc: {
239
+ field: "PRICE",
240
+ direction: "DESC"
241
+ },
242
+ name_asc: {
243
+ field: "TITLE",
244
+ direction: "ASC"
245
+ },
246
+ name_desc: {
247
+ field: "TITLE",
248
+ direction: "DESC"
249
+ },
250
+ release: {
251
+ field: "RELEASE_DATE",
252
+ direction: "DESC"
253
+ },
254
+ orders: {
255
+ field: "BEST_SELLING",
256
+ direction: "DESC"
257
+ },
258
+ discount: {
259
+ field: "RELEVANCE",
260
+ direction: "DESC"
261
+ }
262
+ }
263
+ } },
178
264
  editor: {
179
265
  label: "Product Shelf Root",
180
266
  category: "commerce"
181
267
  },
182
268
  providesContext: "product-shelf",
183
269
  schema: {
184
- first: {
270
+ itemsPerPage: {
185
271
  type: "number",
186
272
  default: 5,
187
- label: "Number of Products"
273
+ label: "Items Per Page"
188
274
  },
189
- itemsPerPage: {
275
+ usePriceWithTaxes: {
276
+ type: "boolean",
277
+ default: false,
278
+ label: "Use Price With Taxes"
279
+ },
280
+ taxesLabel: {
281
+ type: "string",
282
+ default: "Tax included",
283
+ label: "Taxes Label"
284
+ },
285
+ first: {
190
286
  type: "number",
191
287
  default: 5,
192
- label: "Items Per Page"
288
+ label: "Number of Products"
193
289
  },
194
290
  sort: {
195
291
  type: [
@@ -221,27 +317,13 @@ const ProductShelfRootDefinition = defineComponent({
221
317
  type: "string",
222
318
  label: "Collection ID"
223
319
  },
224
- specifications: {
225
- type: "array",
226
- label: "Specification Filters"
227
- },
228
320
  availableOnly: {
229
321
  type: "boolean",
230
322
  default: false,
231
323
  label: "Available Only"
232
- },
233
- usePriceWithTaxes: {
234
- type: "boolean",
235
- default: false,
236
- label: "Use Price With Taxes"
237
- },
238
- taxesLabel: {
239
- type: "string",
240
- default: "Tax included",
241
- label: "Taxes Label"
242
324
  }
243
325
  },
244
- guideline: "Data-owning root of a facet-sourced product shelf. Owns a products(filter:) fragment and receives $data lazily. Compose as: ProductShelfRoot > (ProductShelfHeading + CarouselRoot > (ProductShelfItems + CarouselPrevious + CarouselNext + CarouselBullets)). Compose ProductShelfHeading with the title as its children to render a heading; set the source with categoryId / brandId / collectionId / searchTerm / specifications and tune first, sort, availableOnly. Renders a skeleton while loading and nothing when the result is empty. Bind itemsPerPage to the CarouselRoot so paging matches the shelf config. See product-shelf.md."
326
+ guideline: "Data-owning root of a facet-sourced product shelf. Owns a products(first:, orderBy:, filter:) fragment whose variables bind to this element: the merchant fills them in the CMS (content model product-shelf) and the props of the same name are the defaults. Receives $data lazily. Compose as: ProductShelfRoot > (ProductShelfHeading + CarouselRoot > (ProductShelfItems + CarouselPrevious + CarouselNext + CarouselBullets)). Compose ProductShelfHeading with the title as its children to render a heading; set the source with categoryId / brandId / collectionId / searchTerm and tune first, sort, availableOnly. Renders a skeleton while loading and nothing when the result is empty. Bind itemsPerPage to the CarouselRoot so paging matches the shelf config. See product-shelf.md."
245
327
  });
246
328
  const ProductShelfItemsDefinition = defineComponent({
247
329
  name: "ProductShelfItems",
@@ -267,8 +349,31 @@ const ProductShelfHeadingDefinition = defineComponent({
267
349
  schema: {},
268
350
  guideline: "Renders its children as the shelf title (an <h2>) and provides the section's accessible label. Author the title text as its children (props.children). Place it inside ProductShelfRoot where the title should sit — usually above CarouselRoot. Renders nothing when it has no children."
269
351
  });
270
- function ProductShelfRoot({ first = 5, itemsPerPage = 5, sort = "relevance", searchTerm, categoryId, brandId, collectionId, specifications, availableOnly = false, usePriceWithTaxes = false, taxesLabel = "Tax included", products, $data: $dataProp, className, children, ...props }) {
352
+ /** The content value when the merchant filled the field, else the prop (the shared emptiness rule). */
353
+ function contentOrProp(content, prop) {
354
+ if (content === void 0 || isEmptyContentValue(content)) return prop;
355
+ return content;
356
+ }
357
+ function ProductShelfRoot({ first = 5, itemsPerPage = 5, sort = "relevance", searchTerm, categoryId, brandId, collectionId, availableOnly = false, usePriceWithTaxes = false, taxesLabel = "Tax included", products, $content, $data: $dataProp, className, children, ...props }) {
271
358
  const $data = useDataOverride($dataProp);
359
+ const shelfConfig = useMemo(() => ({
360
+ first: contentOrProp($content?.first, first),
361
+ sort: contentOrProp($content?.sort, sort),
362
+ searchTerm: contentOrProp($content?.searchTerm, searchTerm),
363
+ categoryId: contentOrProp($content?.categoryId, categoryId),
364
+ brandId: contentOrProp($content?.brandId, brandId),
365
+ collectionId: contentOrProp($content?.collectionId, collectionId),
366
+ availableOnly: contentOrProp($content?.availableOnly, availableOnly)
367
+ }), [
368
+ $content,
369
+ first,
370
+ sort,
371
+ searchTerm,
372
+ categoryId,
373
+ brandId,
374
+ collectionId,
375
+ availableOnly
376
+ ]);
272
377
  const headingId = useId();
273
378
  const [headingCount, setHeadingCount] = useState(0);
274
379
  const registerHeading = useCallback(() => {
@@ -283,27 +388,22 @@ function ProductShelfRoot({ first = 5, itemsPerPage = 5, sort = "relevance", sea
283
388
  usePriceWithTaxes,
284
389
  taxesLabel
285
390
  }), [usePriceWithTaxes, taxesLabel]);
286
- const hasHeading = headingCount > 0;
287
- let items;
288
- if (products !== void 0) items = products;
289
- else if ($data === void 0) return /* @__PURE__ */ jsx(ProductShelfSkeleton, { className });
290
- else items = $data ? transformProducts($data) : [];
291
- items = items.slice(0, first);
292
- if (items.length === 0) return null;
293
- const shelf = {
391
+ const items = useMemo(() => {
392
+ if (products !== void 0) return products;
393
+ return $data ? transformProducts($data) : [];
394
+ }, [products, $data]);
395
+ const shelf = useMemo(() => ({
294
396
  itemsPerPage,
295
- variables: buildProductShelfVariables({
296
- first,
297
- sort,
298
- searchTerm,
299
- categoryId,
300
- brandId,
301
- collectionId,
302
- specifications,
303
- availableOnly
304
- }),
397
+ config: shelfConfig,
305
398
  count: items.length
306
- };
399
+ }), [
400
+ itemsPerPage,
401
+ shelfConfig,
402
+ items.length
403
+ ]);
404
+ const hasHeading = headingCount > 0;
405
+ if (products === void 0 && $data === void 0) return /* @__PURE__ */ jsx(ProductShelfSkeleton, { className });
406
+ if (items.length === 0) return null;
307
407
  return /* @__PURE__ */ jsx(ProductListConfigContext, {
308
408
  value: config,
309
409
  children: /* @__PURE__ */ jsx(ProductShelfProductsContext, {
@@ -373,6 +473,6 @@ const ProductShelf = {
373
473
  Skeleton: ProductShelfSkeleton
374
474
  };
375
475
  //#endregion
376
- export { ProductShelf, ProductShelfHeading, ProductShelfHeadingDefinition, ProductShelfItems, ProductShelfItemsDefinition, ProductShelfRoot, ProductShelfRootDefinition, ProductShelfSkeleton, buildProductShelfVariables, transformProducts, useProductShelf, useProductShelfItem };
476
+ export { PRODUCT_SHELF_SORT_MAP, ProductShelf, ProductShelfContent, ProductShelfHeading, ProductShelfHeadingDefinition, ProductShelfItems, ProductShelfItemsDefinition, ProductShelfRoot, ProductShelfRootDefinition, ProductShelfSkeleton, transformProducts, useProductShelf, useProductShelfItem };
377
477
 
378
478
  //# sourceMappingURL=product-shelf.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"product-shelf.js","names":[],"sources":["../../../src/matter/product-shelf/product-shelf.tsx"],"sourcesContent":["'use client';\n\nimport { defineComponent } from '@vtex/fs-core';\nimport {\n type ComponentPropsWithRef,\n createContext,\n useCallback,\n useContext,\n useEffect,\n useId,\n useMemo,\n useState,\n} from 'react';\nimport { CarouselTrack } from '../../particles/carousel/carousel.js';\nimport { Text } from '../../particles/text/text.js';\nimport { useDataOverride } from '../../sdk/data/data-override-context.js';\nimport {\n ProductListConfigContext,\n type ProductListItem,\n ProductListItemContext,\n} from '../product-list/product-list.js';\n\n// ---------------------------------------------------------------------------\n// GraphQL Fragment — product connection from the catalog module. The query\n// arguments are fixed literals rather than variables: the compiler resolves\n// fragment variables only from route params, search params, or reactive vars\n// (there is no per-element config-variable source), so a config-sourced\n// $first/$orderBy/$filter cannot be hoisted. Until that binding exists\n// (Decision 4), the shelf fetches a fixed top-relevance slice; the config\n// props still drive the client-side context (itemsPerPage, locale, currency).\n// ---------------------------------------------------------------------------\n\nconst fragment = /* GraphQL */ `\n fragment ProductShelfData on Query {\n products(first: 12, orderBy: { field: RELEVANCE, direction: DESC }) {\n edges {\n node {\n id\n title\n slug\n routeSlug\n images(first: 1) {\n edges {\n node {\n url\n altText\n }\n }\n }\n variants(first: 1) {\n edges {\n node {\n availableForSale\n quantityAvailable\n price {\n amount\n currencyCode\n }\n compareAtPrice {\n amount\n currencyCode\n }\n sellers {\n isDefault\n offer {\n price {\n amount\n currencyCode\n }\n listPrice {\n amount\n currencyCode\n }\n spotPrice {\n amount\n currencyCode\n }\n tax {\n amount\n currencyCode\n }\n taxPercentage\n availableQuantity\n }\n }\n }\n }\n }\n }\n }\n totalCount\n }\n }\n`;\n\n// ---------------------------------------------------------------------------\n// Raw data types (shape of the fragment result)\n// ---------------------------------------------------------------------------\n\ntype RawMoney = { amount: number; currencyCode: string };\n\ntype RawOffer = {\n price: RawMoney;\n listPrice: RawMoney;\n spotPrice: RawMoney;\n tax: RawMoney;\n taxPercentage: number | null;\n availableQuantity: number;\n};\n\ntype RawVariantNode = {\n availableForSale: boolean;\n quantityAvailable: number | null;\n price: RawMoney;\n compareAtPrice: RawMoney | null;\n sellers: Array<{ isDefault: boolean; offer: RawOffer | null }>;\n};\n\ntype RawProductNode = {\n id: string;\n title: string;\n slug: string;\n routeSlug: string;\n images: { edges: Array<{ node: { url: string; altText: string | null } }> };\n variants: { edges: Array<{ node: RawVariantNode }> };\n};\n\n// The `$data` the shelf receives is the unwrapped top-level fragment field:\n// HotDataProvider forwards `data['products']` (the connection value), not the\n// `{ products: ... }` wrapper — same contract as PricingRoot's productBySlug.\nexport type ProductShelfData = {\n edges: Array<{ node: RawProductNode }>;\n totalCount: number;\n};\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n// The per-item value object the card parts (T3–T7) read. It is the widened\n// ProductListItem, so the existing ProductList.Card* leaves render unchanged.\nexport type ProductShelfItem = ProductListItem;\n\nexport type ProductShelfSort =\n | 'relevance'\n | 'price_asc'\n | 'price_desc'\n | 'name_asc'\n | 'name_desc'\n | 'release'\n | 'orders'\n | 'discount';\n\nexport type ProductSortField = 'TITLE' | 'PRICE' | 'RELEASE_DATE' | 'RELEVANCE' | 'BEST_SELLING';\n\nexport type SortDirection = 'ASC' | 'DESC';\n\nexport type ProductsFilterInput = {\n searchTerm?: string;\n categoryIds?: string[];\n brandIds?: string[];\n collectionId?: string;\n specifications?: Array<{ name: string; values: string[] }>;\n availableOnly?: boolean;\n};\n\nexport type ProductShelfVariables = {\n first: number;\n orderBy?: { field: ProductSortField; direction: SortDirection };\n filter: ProductsFilterInput;\n};\n\nexport type ProductShelfConfig = {\n first?: number;\n itemsPerPage?: number;\n sort?: ProductShelfSort;\n searchTerm?: string;\n categoryId?: string;\n brandId?: string;\n collectionId?: string;\n specifications?: Array<{ name: string; values: string[] }>;\n availableOnly?: boolean;\n};\n\nexport type ProductShelfContextValue = {\n itemsPerPage: number;\n variables: ProductShelfVariables;\n count: number;\n};\n\nexport type ProductShelfRootProps = ComponentPropsWithRef<'section'> &\n ProductShelfConfig & {\n /** When true, card prices render tax-inclusive (from each item's tax data). Default false. */\n usePriceWithTaxes?: boolean;\n /** Text for the tax label part when tax display is on. Default `'Tax included'`. */\n taxesLabel?: string;\n products?: ProductShelfItem[];\n $data?: ProductShelfData | null;\n };\n\nexport type ProductShelfItemsProps = ComponentPropsWithRef<'div'>;\n\nexport type ProductShelfHeadingProps = ComponentPropsWithRef<'h2'>;\n\n// ---------------------------------------------------------------------------\n// Context\n// ---------------------------------------------------------------------------\n\nconst ProductShelfProductsContext = createContext<ProductShelfItem[]>([]);\n\nconst ProductShelfContext = createContext<ProductShelfContextValue | null>(null);\n\n// Wires the section ⇄ heading `aria-labelledby` link without the root having to\n// know its descendants: `headingId` is the shared id, and a composed\n// ProductShelfHeading registers its presence so the section points at it only\n// when it exists (never a dangling idref). `registerHeading` is ref-counted and\n// returns its unregister, so the heading can be placed anywhere.\ntype ProductShelfHeadingContextValue = { headingId: string; registerHeading: () => () => void };\n\nconst ProductShelfHeadingContext = createContext<ProductShelfHeadingContextValue | null>(null);\n\nexport function useProductShelf(): ProductShelfContextValue {\n const ctx = useContext(ProductShelfContext);\n if (!ctx) {\n throw new Error('useProductShelf must be used inside ProductShelfRoot.');\n }\n return ctx;\n}\n\nfunction useProductShelfHeading(): ProductShelfHeadingContextValue {\n const ctx = useContext(ProductShelfHeadingContext);\n if (!ctx) {\n throw new Error('ProductShelfHeading must be used inside ProductShelfRoot.');\n }\n return ctx;\n}\n\nexport function useProductShelfItem(): ProductShelfItem {\n const item = useContext(ProductListItemContext);\n if (!item) {\n throw new Error('Product card components must be used inside ProductShelfItems.');\n }\n return item;\n}\n\n// ---------------------------------------------------------------------------\n// Config → GraphQL variables (the read-side of the shelf's serializable props)\n// ---------------------------------------------------------------------------\n\nconst SORT_MAP: Record<ProductShelfSort, { field: ProductSortField; direction: SortDirection }> = {\n relevance: { field: 'RELEVANCE', direction: 'DESC' },\n price_asc: { field: 'PRICE', direction: 'ASC' },\n price_desc: { field: 'PRICE', direction: 'DESC' },\n name_asc: { field: 'TITLE', direction: 'ASC' },\n name_desc: { field: 'TITLE', direction: 'DESC' },\n release: { field: 'RELEASE_DATE', direction: 'DESC' },\n orders: { field: 'BEST_SELLING', direction: 'DESC' },\n // No direct ProductSortField for legacy \"discount\"; fall back to relevance.\n discount: { field: 'RELEVANCE', direction: 'DESC' },\n};\n\nexport function buildProductShelfVariables(config: ProductShelfConfig): ProductShelfVariables {\n const {\n first = 5,\n sort = 'relevance',\n searchTerm,\n categoryId,\n brandId,\n collectionId,\n specifications,\n availableOnly,\n } = config;\n\n const filter: ProductsFilterInput = {};\n if (searchTerm) filter.searchTerm = searchTerm;\n if (categoryId) filter.categoryIds = [categoryId];\n if (brandId) filter.brandIds = [brandId];\n if (collectionId) filter.collectionId = collectionId;\n if (specifications && specifications.length > 0) filter.specifications = specifications;\n if (availableOnly) filter.availableOnly = true;\n\n return { first, orderBy: SORT_MAP[sort], filter };\n}\n\n// ---------------------------------------------------------------------------\n// Transform — raw fragment slice → per-item value objects\n// ---------------------------------------------------------------------------\n\nexport function transformProducts(data: ProductShelfData): ProductShelfItem[] {\n return data.edges.map(({ node }): ProductShelfItem => {\n const image = node.images.edges[0]?.node;\n const variant = node.variants.edges[0]?.node;\n const seller = variant?.sellers.find((s) => s.isDefault) ?? variant?.sellers[0];\n const offer = seller?.offer ?? null;\n\n const price = offer?.price.amount ?? variant?.price.amount ?? 0;\n const listPrice = offer?.listPrice.amount ?? variant?.compareAtPrice?.amount;\n const spotPrice = offer?.spotPrice.amount;\n const currency = offer?.price.currencyCode ?? variant?.price.currencyCode;\n\n return {\n id: node.id,\n name: node.title,\n slug: node.slug,\n routeSlug: node.routeSlug,\n image: { src: image?.url ?? '', alt: image?.altText ?? node.title },\n price,\n ...(listPrice !== undefined ? { listPrice } : {}),\n ...(spotPrice !== undefined ? { spotPrice } : {}),\n ...(offer ? { tax: offer.tax.amount, taxPercentage: offer.taxPercentage } : {}),\n ...(variant ? { availableForSale: variant.availableForSale } : {}),\n ...(variant?.quantityAvailable != null ? { availableQuantity: variant.quantityAvailable } : {}),\n ...(currency ? { currency } : {}),\n };\n });\n}\n\n// ---------------------------------------------------------------------------\n// Definitions\n// ---------------------------------------------------------------------------\n\nexport const ProductShelfRootDefinition = defineComponent<ProductShelfRootProps>({\n name: 'ProductShelfRoot',\n importPath: '@vtex/faststore/components',\n component: ProductShelfRoot,\n fragment,\n fetchStrategy: 'lazy',\n skeleton: ProductShelfSkeleton,\n editor: { label: 'Product Shelf Root', category: 'commerce' },\n providesContext: 'product-shelf',\n schema: {\n first: { type: 'number', default: 5, label: 'Number of Products' },\n itemsPerPage: { type: 'number', default: 5, label: 'Items Per Page' },\n sort: {\n type: ['relevance', 'price_asc', 'price_desc', 'name_asc', 'name_desc', 'release', 'orders', 'discount'] as const,\n default: 'relevance',\n label: 'Sort',\n },\n searchTerm: { type: 'string', label: 'Search Term' },\n categoryId: { type: 'string', label: 'Category ID' },\n brandId: { type: 'string', label: 'Brand ID' },\n collectionId: { type: 'string', label: 'Collection ID' },\n specifications: { type: 'array', label: 'Specification Filters' },\n availableOnly: { type: 'boolean', default: false, label: 'Available Only' },\n usePriceWithTaxes: { type: 'boolean', default: false, label: 'Use Price With Taxes' },\n taxesLabel: { type: 'string', default: 'Tax included', label: 'Taxes Label' },\n },\n guideline:\n 'Data-owning root of a facet-sourced product shelf. Owns a products(filter:) fragment and receives $data lazily. Compose as: ProductShelfRoot > (ProductShelfHeading + CarouselRoot > (ProductShelfItems + CarouselPrevious + CarouselNext + CarouselBullets)). Compose ProductShelfHeading with the title as its children to render a heading; set the source with categoryId / brandId / collectionId / searchTerm / specifications and tune first, sort, availableOnly. Renders a skeleton while loading and nothing when the result is empty. Bind itemsPerPage to the CarouselRoot so paging matches the shelf config. See product-shelf.md.',\n});\n\nexport const ProductShelfItemsDefinition = defineComponent<ProductShelfItemsProps>({\n name: 'ProductShelfItems',\n importPath: '@vtex/faststore/components',\n component: ProductShelfItems,\n editor: { label: 'Product Shelf Items', category: 'commerce' },\n requiresContext: 'product-shelf',\n schema: {},\n guideline:\n 'Repeats the shelf products into the carousel track, publishing one product per slide through the per-item context the ProductCard* parts read. Place directly inside CarouselRoot (it renders the CarouselTrack). Put the card template (ProductCardImage, ProductCardName, ProductCardPrice, …) as its children.',\n});\n\nexport const ProductShelfHeadingDefinition = defineComponent<ProductShelfHeadingProps>({\n name: 'ProductShelfHeading',\n importPath: '@vtex/faststore/components',\n component: ProductShelfHeading,\n editor: { label: 'Product Shelf Heading', category: 'commerce' },\n requiresContext: 'product-shelf',\n schema: {},\n guideline:\n \"Renders its children as the shelf title (an <h2>) and provides the section's accessible label. Author the title text as its children (props.children). Place it inside ProductShelfRoot where the title should sit — usually above CarouselRoot. Renders nothing when it has no children.\",\n});\n\n// ---------------------------------------------------------------------------\n// Implementations\n// ---------------------------------------------------------------------------\n\nexport function ProductShelfRoot({\n first = 5,\n itemsPerPage = 5,\n sort = 'relevance',\n searchTerm,\n categoryId,\n brandId,\n collectionId,\n specifications,\n availableOnly = false,\n usePriceWithTaxes = false,\n taxesLabel = 'Tax included',\n products,\n $data: $dataProp,\n className,\n children,\n ...props\n}: ProductShelfRootProps) {\n const $data = useDataOverride<ProductShelfData | null | undefined>($dataProp);\n const headingId = useId();\n // Ref-counted so a composed ProductShelfHeading flips `hasHeading` wherever it is placed; the\n // section then labels itself only while a heading is mounted, never via a dangling idref.\n const [headingCount, setHeadingCount] = useState(0);\n const registerHeading = useCallback(() => {\n setHeadingCount((count) => count + 1);\n return () => setHeadingCount((count) => count - 1);\n }, []);\n const headingContext = useMemo(() => ({ headingId, registerHeading }), [headingId, registerHeading]);\n const config = useMemo(() => ({ usePriceWithTaxes, taxesLabel }), [usePriceWithTaxes, taxesLabel]);\n const hasHeading = headingCount > 0;\n\n let items: ProductShelfItem[];\n if (products !== undefined) {\n items = products;\n } else if ($data === undefined) {\n // Lazy source not resolved yet — show the skeleton (the runtime also renders it).\n return <ProductShelfSkeleton className={className} />;\n } else {\n items = $data ? transformProducts($data) : [];\n }\n\n items = items.slice(0, first);\n\n // Empty result renders nothing (legacy parity) rather than an empty carousel.\n if (items.length === 0) {\n return null;\n }\n\n const variables = buildProductShelfVariables({\n first,\n sort,\n searchTerm,\n categoryId,\n brandId,\n collectionId,\n specifications,\n availableOnly,\n });\n\n const shelf: ProductShelfContextValue = { itemsPerPage, variables, count: items.length };\n\n return (\n <ProductListConfigContext value={config}>\n <ProductShelfProductsContext value={items}>\n <ProductShelfContext value={shelf}>\n <ProductShelfHeadingContext value={headingContext}>\n <section\n {...props}\n className={className}\n data-fs-product-shelf=\"\"\n aria-labelledby={hasHeading ? headingId : undefined}\n >\n {children}\n </section>\n </ProductShelfHeadingContext>\n </ProductShelfContext>\n </ProductShelfProductsContext>\n </ProductListConfigContext>\n );\n}\n\nexport function ProductShelfHeading({ className, children, ...props }: ProductShelfHeadingProps) {\n const { headingId, registerHeading } = useProductShelfHeading();\n const hasContent = children != null && children !== '';\n\n // Announce presence to the root so its section wires `aria-labelledby` to this heading; the\n // registration (and its unregister) is scoped to when the heading actually renders content.\n useEffect(() => {\n if (!hasContent) {\n return;\n }\n return registerHeading();\n }, [hasContent, registerHeading]);\n\n if (!hasContent) {\n return null;\n }\n\n return (\n <Text {...props} as=\"h2\" id={headingId} className={className} data-fs-product-shelf-heading=\"\">\n {children}\n </Text>\n );\n}\n\nexport function ProductShelfItems({ children, ...props }: ProductShelfItemsProps) {\n const items = useContext(ProductShelfProductsContext);\n\n return (\n <CarouselTrack {...props} data-fs-product-shelf-items=\"\">\n {items.map((item) => (\n <ProductListItemContext key={item.id} value={item}>\n {children}\n </ProductListItemContext>\n ))}\n </CarouselTrack>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Skeleton\n// ---------------------------------------------------------------------------\n\nexport function ProductShelfSkeleton({ className, ...props }: ComponentPropsWithRef<'div'>) {\n return (\n <div {...props} className={className} data-fs-product-shelf-skeleton=\"\" aria-hidden=\"true\">\n <span data-fs-product-shelf-skeleton-item=\"\" />\n <span data-fs-product-shelf-skeleton-item=\"\" />\n <span data-fs-product-shelf-skeleton-item=\"\" />\n </div>\n );\n}\n\nProductShelfRoot.Skeleton = ProductShelfSkeleton;\n\n// ---------------------------------------------------------------------------\n// Namespace export\n// ---------------------------------------------------------------------------\n\nexport const ProductShelf = {\n Root: ProductShelfRoot,\n Heading: ProductShelfHeading,\n Items: ProductShelfItems,\n Skeleton: ProductShelfSkeleton,\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"product-shelf.js","names":[],"sources":["../../../src/matter/product-shelf/product-shelf.tsx"],"sourcesContent":["'use client';\n\nimport { type ContentValue, defineComponent, defineContentType } from '@vtex/fs-core';\nimport {\n type ComponentPropsWithRef,\n createContext,\n useCallback,\n useContext,\n useEffect,\n useId,\n useMemo,\n useState,\n} from 'react';\nimport { CarouselTrack } from '../../particles/carousel/carousel.js';\nimport { Text } from '../../particles/text/text.js';\nimport { useDataOverride } from '../../sdk/data/data-override-context.js';\nimport { isEmptyContentValue } from '../../sdk/data/empty-content-value.js';\nimport {\n ProductListConfigContext,\n type ProductListItem,\n ProductListItemContext,\n} from '../product-list/product-list.js';\n\n// ---------------------------------------------------------------------------\n// Content model — the merchant-facing fields that drive the query. Each one is\n// also a schema prop of the same name on the root: the CMS value wins per\n// field, and the prop is the developer default (the only source in a store\n// with no CMS binding). No field is required, so an empty value relaxes the\n// filter or takes the prop instead of omitting the shelf.\n// ---------------------------------------------------------------------------\n\nexport const ProductShelfContent = defineContentType({\n id: 'product-shelf',\n title: 'Product Shelf',\n description: 'Which products a shelf shows: how many, in which order, and from which facet.',\n schema: {\n type: 'object',\n additionalProperties: false,\n properties: {\n first: { type: 'integer', title: 'Number of products', minimum: 1, maximum: 100 },\n sort: {\n type: 'string',\n enum: ['relevance', 'price_asc', 'price_desc', 'name_asc', 'name_desc', 'release', 'orders', 'discount'],\n title: 'Sort',\n },\n categoryId: { type: 'string', title: 'Category ID' },\n brandId: { type: 'string', title: 'Brand ID' },\n collectionId: { type: 'string', title: 'Collection ID' },\n searchTerm: { type: 'string', title: 'Search term' },\n availableOnly: { type: 'boolean', title: 'Available only' },\n },\n },\n});\n\n// ---------------------------------------------------------------------------\n// GraphQL Fragment — product connection from the catalog module. Every\n// argument is a variable the compiler binds from the element's configuration\n// (its content slice at request time, else its prop at compile time), one\n// fragment instance per element. A variable left unbound inside `filter`\n// omits that key, so an unset facet relaxes the filter rather than sending\n// null; `$orderBy` reads `sort` through the `values` table in the definition.\n// ---------------------------------------------------------------------------\n\nconst fragment = /* GraphQL */ `\n fragment ProductShelfData on Query {\n products(\n first: $first\n orderBy: $orderBy\n filter: {\n categoryIds: $categoryId\n brandIds: $brandId\n collectionId: $collectionId\n searchTerm: $searchTerm\n availableOnly: $availableOnly\n }\n ) {\n edges {\n node {\n id\n title\n slug\n routeSlug\n images(first: 1) {\n edges {\n node {\n url\n altText\n }\n }\n }\n variants(first: 1) {\n edges {\n node {\n availableForSale\n quantityAvailable\n price {\n amount\n currencyCode\n }\n compareAtPrice {\n amount\n currencyCode\n }\n sellers {\n isDefault\n offer {\n price {\n amount\n currencyCode\n }\n listPrice {\n amount\n currencyCode\n }\n spotPrice {\n amount\n currencyCode\n }\n tax {\n amount\n currencyCode\n }\n taxPercentage\n availableQuantity\n }\n }\n }\n }\n }\n }\n }\n totalCount\n }\n }\n`;\n\n// ---------------------------------------------------------------------------\n// Raw data types (shape of the fragment result)\n// ---------------------------------------------------------------------------\n\ntype RawMoney = { amount: number; currencyCode: string };\n\ntype RawOffer = {\n price: RawMoney;\n listPrice: RawMoney;\n spotPrice: RawMoney;\n tax: RawMoney;\n taxPercentage: number | null;\n availableQuantity: number;\n};\n\ntype RawVariantNode = {\n availableForSale: boolean;\n quantityAvailable: number | null;\n price: RawMoney;\n compareAtPrice: RawMoney | null;\n sellers: Array<{ isDefault: boolean; offer: RawOffer | null }>;\n};\n\ntype RawProductNode = {\n id: string;\n title: string;\n slug: string;\n routeSlug: string;\n images: { edges: Array<{ node: { url: string; altText: string | null } }> };\n variants: { edges: Array<{ node: RawVariantNode }> };\n};\n\n// The `$data` the shelf receives is the unwrapped top-level fragment field:\n// HotDataProvider forwards `data['products']` (the connection value), not the\n// `{ products: ... }` wrapper — same contract as PricingRoot's productBySlug.\nexport type ProductShelfData = {\n edges: Array<{ node: RawProductNode }>;\n totalCount: number;\n};\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n// The per-item value object the card parts (T3–T7) read. It is the widened\n// ProductListItem, so the existing ProductList.Card* leaves render unchanged.\nexport type ProductShelfItem = ProductListItem;\n\nexport type ProductShelfSort =\n | 'relevance'\n | 'price_asc'\n | 'price_desc'\n | 'name_asc'\n | 'name_desc'\n | 'release'\n | 'orders'\n | 'discount';\n\nexport type ProductSortField = 'TITLE' | 'PRICE' | 'RELEASE_DATE' | 'RELEVANCE' | 'BEST_SELLING';\n\nexport type SortDirection = 'ASC' | 'DESC';\n\n/**\n * The query configuration the shelf resolved for this element: the content slice when the\n * merchant filled a field, else the prop. The query has already applied these values; the\n * context republishes them for parts that describe the shelf (a \"sorted by\" label, a facet link).\n */\nexport type ProductShelfConfig = {\n first: number;\n sort: ProductShelfSort;\n searchTerm?: string;\n categoryId?: string;\n brandId?: string;\n collectionId?: string;\n availableOnly: boolean;\n};\n\nexport type ProductShelfContextValue = {\n itemsPerPage: number;\n config: ProductShelfConfig;\n count: number;\n};\n\nexport type ProductShelfRootProps = ComponentPropsWithRef<'section'> &\n Partial<ProductShelfConfig> & {\n itemsPerPage?: number;\n /** When true, card prices render tax-inclusive (from each item's tax data). Default false. */\n usePriceWithTaxes?: boolean;\n /** Text for the tax label part when tax display is on. Default `'Tax included'`. */\n taxesLabel?: string;\n products?: ProductShelfItem[];\n /** Injected by the compiler, sliced from the page's or layout's composite content entry. */\n $content?: ContentValue<typeof ProductShelfContent>;\n $data?: ProductShelfData | null;\n };\n\nexport type ProductShelfItemsProps = ComponentPropsWithRef<'div'>;\n\nexport type ProductShelfHeadingProps = ComponentPropsWithRef<'h2'>;\n\n// ---------------------------------------------------------------------------\n// Context\n// ---------------------------------------------------------------------------\n\nconst ProductShelfProductsContext = createContext<ProductShelfItem[]>([]);\n\nconst ProductShelfContext = createContext<ProductShelfContextValue | null>(null);\n\n// Wires the section ⇄ heading `aria-labelledby` link without the root having to\n// know its descendants: `headingId` is the shared id, and a composed\n// ProductShelfHeading registers its presence so the section points at it only\n// when it exists (never a dangling idref). `registerHeading` is ref-counted and\n// returns its unregister, so the heading can be placed anywhere.\ntype ProductShelfHeadingContextValue = { headingId: string; registerHeading: () => () => void };\n\nconst ProductShelfHeadingContext = createContext<ProductShelfHeadingContextValue | null>(null);\n\nexport function useProductShelf(): ProductShelfContextValue {\n const ctx = useContext(ProductShelfContext);\n if (!ctx) {\n throw new Error('useProductShelf must be used inside ProductShelfRoot.');\n }\n return ctx;\n}\n\nfunction useProductShelfHeading(): ProductShelfHeadingContextValue {\n const ctx = useContext(ProductShelfHeadingContext);\n if (!ctx) {\n throw new Error('ProductShelfHeading must be used inside ProductShelfRoot.');\n }\n return ctx;\n}\n\nexport function useProductShelfItem(): ProductShelfItem {\n const item = useContext(ProductListItemContext);\n if (!item) {\n throw new Error('Product card components must be used inside ProductShelfItems.');\n }\n return item;\n}\n\n// ---------------------------------------------------------------------------\n// `sort` → `$orderBy` (ProductSortingInput). The same table is the `values`\n// block of the definition, so the compiler and the SDK helper apply it; the\n// contract test pins the two to each other.\n// ---------------------------------------------------------------------------\n\nexport const PRODUCT_SHELF_SORT_MAP: Record<ProductShelfSort, { field: ProductSortField; direction: SortDirection }> = {\n relevance: { field: 'RELEVANCE', direction: 'DESC' },\n price_asc: { field: 'PRICE', direction: 'ASC' },\n price_desc: { field: 'PRICE', direction: 'DESC' },\n name_asc: { field: 'TITLE', direction: 'ASC' },\n name_desc: { field: 'TITLE', direction: 'DESC' },\n release: { field: 'RELEASE_DATE', direction: 'DESC' },\n orders: { field: 'BEST_SELLING', direction: 'DESC' },\n // No direct ProductSortField for legacy \"discount\"; fall back to relevance.\n discount: { field: 'RELEVANCE', direction: 'DESC' },\n};\n\n// ---------------------------------------------------------------------------\n// Transform — raw fragment slice → per-item value objects\n// ---------------------------------------------------------------------------\n\nexport function transformProducts(data: ProductShelfData): ProductShelfItem[] {\n return data.edges.map(({ node }): ProductShelfItem => {\n const image = node.images.edges[0]?.node;\n const variant = node.variants.edges[0]?.node;\n const seller = variant?.sellers.find((s) => s.isDefault) ?? variant?.sellers[0];\n const offer = seller?.offer ?? null;\n\n const price = offer?.price.amount ?? variant?.price.amount ?? 0;\n const listPrice = offer?.listPrice.amount ?? variant?.compareAtPrice?.amount;\n const spotPrice = offer?.spotPrice.amount;\n const currency = offer?.price.currencyCode ?? variant?.price.currencyCode;\n\n return {\n id: node.id,\n name: node.title,\n slug: node.slug,\n routeSlug: node.routeSlug,\n image: { src: image?.url ?? '', alt: image?.altText ?? node.title },\n price,\n ...(listPrice !== undefined ? { listPrice } : {}),\n ...(spotPrice !== undefined ? { spotPrice } : {}),\n ...(offer ? { tax: offer.tax.amount, taxPercentage: offer.taxPercentage } : {}),\n ...(variant ? { availableForSale: variant.availableForSale } : {}),\n ...(variant?.quantityAvailable != null ? { availableQuantity: variant.quantityAvailable } : {}),\n ...(currency ? { currency } : {}),\n };\n });\n}\n\n// ---------------------------------------------------------------------------\n// Definitions\n// ---------------------------------------------------------------------------\n\nexport const ProductShelfRootDefinition = defineComponent<ProductShelfRootProps>({\n name: 'ProductShelfRoot',\n importPath: '@vtex/faststore/components',\n component: ProductShelfRoot,\n fragment,\n fetchStrategy: 'lazy',\n skeleton: ProductShelfSkeleton,\n content: ProductShelfContent,\n // The `values` table is authored as a literal: the Catalog Build serializes the block as JSON and\n // rejects identifiers. `PRODUCT_SHELF_SORT_MAP` is pinned equal to it by the contract test.\n variables: {\n orderBy: {\n from: 'sort',\n values: {\n relevance: { field: 'RELEVANCE', direction: 'DESC' },\n price_asc: { field: 'PRICE', direction: 'ASC' },\n price_desc: { field: 'PRICE', direction: 'DESC' },\n name_asc: { field: 'TITLE', direction: 'ASC' },\n name_desc: { field: 'TITLE', direction: 'DESC' },\n release: { field: 'RELEASE_DATE', direction: 'DESC' },\n orders: { field: 'BEST_SELLING', direction: 'DESC' },\n discount: { field: 'RELEVANCE', direction: 'DESC' },\n },\n },\n },\n editor: { label: 'Product Shelf Root', category: 'commerce' },\n providesContext: 'product-shelf',\n schema: {\n itemsPerPage: { type: 'number', default: 5, label: 'Items Per Page' },\n usePriceWithTaxes: { type: 'boolean', default: false, label: 'Use Price With Taxes' },\n taxesLabel: { type: 'string', default: 'Tax included', label: 'Taxes Label' },\n // The content fields again, as props: the developer's defaults, and the only source in a\n // store with no CMS binding (example stores, Storybook, tests).\n first: { type: 'number', default: 5, label: 'Number of Products' },\n sort: {\n type: ['relevance', 'price_asc', 'price_desc', 'name_asc', 'name_desc', 'release', 'orders', 'discount'] as const,\n default: 'relevance',\n label: 'Sort',\n },\n searchTerm: { type: 'string', label: 'Search Term' },\n categoryId: { type: 'string', label: 'Category ID' },\n brandId: { type: 'string', label: 'Brand ID' },\n collectionId: { type: 'string', label: 'Collection ID' },\n availableOnly: { type: 'boolean', default: false, label: 'Available Only' },\n },\n guideline:\n 'Data-owning root of a facet-sourced product shelf. Owns a products(first:, orderBy:, filter:) fragment whose variables bind to this element: the merchant fills them in the CMS (content model product-shelf) and the props of the same name are the defaults. Receives $data lazily. Compose as: ProductShelfRoot > (ProductShelfHeading + CarouselRoot > (ProductShelfItems + CarouselPrevious + CarouselNext + CarouselBullets)). Compose ProductShelfHeading with the title as its children to render a heading; set the source with categoryId / brandId / collectionId / searchTerm and tune first, sort, availableOnly. Renders a skeleton while loading and nothing when the result is empty. Bind itemsPerPage to the CarouselRoot so paging matches the shelf config. See product-shelf.md.',\n});\n\nexport const ProductShelfItemsDefinition = defineComponent<ProductShelfItemsProps>({\n name: 'ProductShelfItems',\n importPath: '@vtex/faststore/components',\n component: ProductShelfItems,\n editor: { label: 'Product Shelf Items', category: 'commerce' },\n requiresContext: 'product-shelf',\n schema: {},\n guideline:\n 'Repeats the shelf products into the carousel track, publishing one product per slide through the per-item context the ProductCard* parts read. Place directly inside CarouselRoot (it renders the CarouselTrack). Put the card template (ProductCardImage, ProductCardName, ProductCardPrice, …) as its children.',\n});\n\nexport const ProductShelfHeadingDefinition = defineComponent<ProductShelfHeadingProps>({\n name: 'ProductShelfHeading',\n importPath: '@vtex/faststore/components',\n component: ProductShelfHeading,\n editor: { label: 'Product Shelf Heading', category: 'commerce' },\n requiresContext: 'product-shelf',\n schema: {},\n guideline:\n \"Renders its children as the shelf title (an <h2>) and provides the section's accessible label. Author the title text as its children (props.children). Place it inside ProductShelfRoot where the title should sit — usually above CarouselRoot. Renders nothing when it has no children.\",\n});\n\n// ---------------------------------------------------------------------------\n// Implementations\n// ---------------------------------------------------------------------------\n\n/** The content value when the merchant filled the field, else the prop (the shared emptiness rule). */\nfunction contentOrProp<T>(content: T | undefined, prop: T): T {\n if (content === undefined || isEmptyContentValue(content)) return prop;\n return content;\n}\n\nexport function ProductShelfRoot({\n first = 5,\n itemsPerPage = 5,\n sort = 'relevance',\n searchTerm,\n categoryId,\n brandId,\n collectionId,\n availableOnly = false,\n usePriceWithTaxes = false,\n taxesLabel = 'Tax included',\n products,\n $content,\n $data: $dataProp,\n className,\n children,\n ...props\n}: ProductShelfRootProps) {\n const $data = useDataOverride<ProductShelfData | null | undefined>($dataProp);\n // The query already applied these values (the compiler binds the same slice and props to the\n // fragment variables); the context only republishes what this element resolved to.\n const shelfConfig = useMemo<ProductShelfConfig>(\n () => ({\n first: contentOrProp($content?.first, first),\n sort: contentOrProp($content?.sort, sort),\n searchTerm: contentOrProp($content?.searchTerm, searchTerm),\n categoryId: contentOrProp($content?.categoryId, categoryId),\n brandId: contentOrProp($content?.brandId, brandId),\n collectionId: contentOrProp($content?.collectionId, collectionId),\n availableOnly: contentOrProp($content?.availableOnly, availableOnly),\n }),\n [$content, first, sort, searchTerm, categoryId, brandId, collectionId, availableOnly],\n );\n const headingId = useId();\n // Ref-counted so a composed ProductShelfHeading flips `hasHeading` wherever it is placed; the\n // section then labels itself only while a heading is mounted, never via a dangling idref.\n const [headingCount, setHeadingCount] = useState(0);\n const registerHeading = useCallback(() => {\n setHeadingCount((count) => count + 1);\n return () => setHeadingCount((count) => count - 1);\n }, []);\n const headingContext = useMemo(() => ({ headingId, registerHeading }), [headingId, registerHeading]);\n const config = useMemo(() => ({ usePriceWithTaxes, taxesLabel }), [usePriceWithTaxes, taxesLabel]);\n const items = useMemo<ProductShelfItem[]>(() => {\n if (products !== undefined) return products;\n return $data ? transformProducts($data) : [];\n }, [products, $data]);\n const shelf = useMemo<ProductShelfContextValue>(\n () => ({ itemsPerPage, config: shelfConfig, count: items.length }),\n [itemsPerPage, shelfConfig, items.length],\n );\n const hasHeading = headingCount > 0;\n\n if (products === undefined && $data === undefined) {\n // Lazy source not resolved yet — show the skeleton (the runtime also renders it).\n return <ProductShelfSkeleton className={className} />;\n }\n\n // Empty result renders nothing (legacy parity) rather than an empty carousel.\n if (items.length === 0) {\n return null;\n }\n\n return (\n <ProductListConfigContext value={config}>\n <ProductShelfProductsContext value={items}>\n <ProductShelfContext value={shelf}>\n <ProductShelfHeadingContext value={headingContext}>\n <section\n {...props}\n className={className}\n data-fs-product-shelf=\"\"\n aria-labelledby={hasHeading ? headingId : undefined}\n >\n {children}\n </section>\n </ProductShelfHeadingContext>\n </ProductShelfContext>\n </ProductShelfProductsContext>\n </ProductListConfigContext>\n );\n}\n\nexport function ProductShelfHeading({ className, children, ...props }: ProductShelfHeadingProps) {\n const { headingId, registerHeading } = useProductShelfHeading();\n const hasContent = children != null && children !== '';\n\n // Announce presence to the root so its section wires `aria-labelledby` to this heading; the\n // registration (and its unregister) is scoped to when the heading actually renders content.\n useEffect(() => {\n if (!hasContent) {\n return;\n }\n return registerHeading();\n }, [hasContent, registerHeading]);\n\n if (!hasContent) {\n return null;\n }\n\n return (\n <Text {...props} as=\"h2\" id={headingId} className={className} data-fs-product-shelf-heading=\"\">\n {children}\n </Text>\n );\n}\n\nexport function ProductShelfItems({ children, ...props }: ProductShelfItemsProps) {\n const items = useContext(ProductShelfProductsContext);\n\n return (\n <CarouselTrack {...props} data-fs-product-shelf-items=\"\">\n {items.map((item) => (\n <ProductListItemContext key={item.id} value={item}>\n {children}\n </ProductListItemContext>\n ))}\n </CarouselTrack>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Skeleton\n// ---------------------------------------------------------------------------\n\nexport function ProductShelfSkeleton({ className, ...props }: ComponentPropsWithRef<'div'>) {\n return (\n <div {...props} className={className} data-fs-product-shelf-skeleton=\"\" aria-hidden=\"true\">\n <span data-fs-product-shelf-skeleton-item=\"\" />\n <span data-fs-product-shelf-skeleton-item=\"\" />\n <span data-fs-product-shelf-skeleton-item=\"\" />\n </div>\n );\n}\n\nProductShelfRoot.Skeleton = ProductShelfSkeleton;\n\n// ---------------------------------------------------------------------------\n// Namespace export\n// ---------------------------------------------------------------------------\n\nexport const ProductShelf = {\n Root: ProductShelfRoot,\n Heading: ProductShelfHeading,\n Items: ProductShelfItems,\n Skeleton: ProductShelfSkeleton,\n};\n"],"mappings":"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"}
@@ -2,11 +2,11 @@
2
2
  import { defineComponent } from "../../core/dist/define-component.js";
3
3
  import { defineContentType } from "../../core/dist/define-content-type.js";
4
4
  import "../../core/dist/index.js";
5
+ import { resolveSafeHref } from "../../utils/safe-href.js";
5
6
  import { useIntl } from "../../sdk/i18n/client.js";
6
7
  import { graphql } from "../../sdk/generated/gql.js";
7
8
  import { useActionsOverride } from "../../sdk/actions/actions-override-context.js";
8
9
  import { useDataOverride } from "../../sdk/data/data-override-context.js";
9
- import { resolveSafeHref } from "../../utils/safe-href.js";
10
10
  import { ReactiveRootContext } from "../../sdk/data/page-reactive-data-root.js";
11
11
  import { PostalCodeField } from "../../particles/postal-code-field/postal-code-field.js";
12
12
  import { cloneElement, createContext, isValidElement, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";