@vtex/faststore 0.0.5 → 0.0.7

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 (326) hide show
  1. package/CHANGELOG.md +101 -0
  2. package/dist/actions.json +181 -0
  3. package/dist/catalog.json +1673 -484
  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 +350 -0
  21. package/dist/cli/index.js +35047 -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 +49859 -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 +2 -1
  45. package/dist/client.js +2 -1
  46. package/dist/components.d.ts +32 -9
  47. package/dist/components.js +35 -14
  48. package/dist/content-types.json +93 -0
  49. package/dist/core/dist/define-component.d.ts +37 -0
  50. package/dist/core/dist/index.d.ts +2 -2
  51. package/dist/docs/access-code-sign-in.md +1 -1
  52. package/dist/docs/account-entry-point.md +1 -1
  53. package/dist/docs/account-menu-identity.md +160 -0
  54. package/dist/docs/account-menu.md +106 -23
  55. package/dist/docs/address-summary.md +24 -3
  56. package/dist/docs/alert-dialog.md +204 -0
  57. package/dist/docs/avatar.md +103 -0
  58. package/dist/docs/billing-address.md +284 -0
  59. package/dist/docs/card-entry.md +250 -0
  60. package/dist/docs/cardholder-document.md +142 -0
  61. package/dist/docs/client-preferences-fieldset.md +148 -0
  62. package/dist/docs/client-preferences.md +2 -1
  63. package/dist/docs/client-profile-fieldset.md +184 -0
  64. package/dist/docs/client-profile.md +1 -1
  65. package/dist/docs/document-field.md +58 -4
  66. package/dist/docs/field.md +317 -0
  67. package/dist/docs/form.md +307 -0
  68. package/dist/docs/identity-edit.md +6 -6
  69. package/dist/docs/identity-summary.md +5 -5
  70. package/dist/docs/installments.md +248 -0
  71. package/dist/docs/my-account-profile.md +2 -1
  72. package/dist/docs/order-placed-payment-summary.md +138 -0
  73. package/dist/docs/payment-method-badges.md +232 -0
  74. package/dist/docs/payment-methods.md +1 -0
  75. package/dist/docs/payment.md +218 -0
  76. package/dist/docs/phone-field.md +58 -4
  77. package/dist/docs/place-order.md +157 -0
  78. package/dist/docs/product-shelf.md +20 -13
  79. package/dist/docs/save-card.md +186 -0
  80. package/dist/docs/saved-cards.md +218 -0
  81. package/dist/docs/select.md +465 -0
  82. package/dist/docs/shipping-address.md +110 -258
  83. package/dist/index.d.ts +5 -2
  84. package/dist/internal/client.d.ts +3 -1
  85. package/dist/internal/client.js +4 -2
  86. package/dist/internal/content.d.ts +2 -2
  87. package/dist/internal/server.d.ts +4 -1
  88. package/dist/internal/server.js +4 -1
  89. package/dist/matter/access-code-sign-in/access-code-sign-in.js +9 -8
  90. package/dist/matter/access-code-sign-in/access-code-sign-in.js.map +1 -1
  91. package/dist/matter/account-access-gate/account-access-gate.js.map +1 -1
  92. package/dist/matter/account-entry-point/account-entry-point.js +1 -1
  93. package/dist/matter/account-entry-point/account-entry-point.js.map +1 -1
  94. package/dist/matter/account-menu/account-menu.d.ts +70 -0
  95. package/dist/matter/account-menu/account-menu.js +201 -9
  96. package/dist/matter/account-menu/account-menu.js.map +1 -1
  97. package/dist/matter/account-menu/sign-out-failure.js +50 -0
  98. package/dist/matter/account-menu/sign-out-failure.js.map +1 -0
  99. package/dist/matter/account-menu-identity/account-menu-identity.d.ts +21 -0
  100. package/dist/matter/account-menu-identity/account-menu-identity.js +88 -0
  101. package/dist/matter/account-menu-identity/account-menu-identity.js.map +1 -0
  102. package/dist/matter/billing-address/billing-address.d.ts +165 -0
  103. package/dist/matter/billing-address/billing-address.js +408 -0
  104. package/dist/matter/billing-address/billing-address.js.map +1 -0
  105. package/dist/matter/card-entry/card-capture.d.ts +25 -0
  106. package/dist/matter/card-entry/card-capture.js +25 -0
  107. package/dist/matter/card-entry/card-capture.js.map +1 -0
  108. package/dist/matter/card-entry/card-entry.d.ts +120 -0
  109. package/dist/matter/card-entry/card-entry.js +833 -0
  110. package/dist/matter/card-entry/card-entry.js.map +1 -0
  111. package/dist/matter/cardholder-document/cardholder-document.d.ts +45 -0
  112. package/dist/matter/cardholder-document/cardholder-document.js +70 -0
  113. package/dist/matter/cardholder-document/cardholder-document.js.map +1 -0
  114. package/dist/matter/cart/cart.js +1 -1
  115. package/dist/matter/client-preferences/client-preferences-fieldset.d.ts +77 -0
  116. package/dist/matter/client-preferences/client-preferences-fieldset.js +299 -0
  117. package/dist/matter/client-preferences/client-preferences-fieldset.js.map +1 -0
  118. package/dist/matter/client-preferences/client-preferences.d.ts +3 -5
  119. package/dist/matter/client-preferences/client-preferences.js +6 -6
  120. package/dist/matter/client-preferences/client-preferences.js.map +1 -1
  121. package/dist/matter/client-profile/client-profile.d.ts +4 -6
  122. package/dist/matter/client-profile/client-profile.js +9 -6
  123. package/dist/matter/client-profile/client-profile.js.map +1 -1
  124. package/dist/matter/client-profile-form/client-profile-fieldset.d.ts +119 -0
  125. package/dist/matter/client-profile-form/client-profile-fieldset.js +488 -0
  126. package/dist/matter/client-profile-form/client-profile-fieldset.js.map +1 -0
  127. package/dist/matter/identity-edit/identity-edit.js +2 -2
  128. package/dist/matter/identity-edit/identity-edit.js.map +1 -1
  129. package/dist/matter/identity-summary/identity-summary.js +3 -2
  130. package/dist/matter/identity-summary/identity-summary.js.map +1 -1
  131. package/dist/matter/installments/installments-select.d.ts +42 -0
  132. package/dist/matter/installments/installments-select.js +167 -0
  133. package/dist/matter/installments/installments-select.js.map +1 -0
  134. package/dist/matter/installments/installments.d.ts +58 -0
  135. package/dist/matter/installments/installments.js +176 -0
  136. package/dist/matter/installments/installments.js.map +1 -0
  137. package/dist/matter/installments/use-installments-selection.d.ts +29 -0
  138. package/dist/matter/installments/use-installments-selection.js +95 -0
  139. package/dist/matter/installments/use-installments-selection.js.map +1 -0
  140. package/dist/matter/my-account-profile/my-account-profile.d.ts +3 -0
  141. package/dist/matter/my-account-profile/my-account-profile.js +6 -5
  142. package/dist/matter/my-account-profile/my-account-profile.js.map +1 -1
  143. package/dist/matter/order-placed-payment-summary/order-placed-payment-summary.d.ts +63 -0
  144. package/dist/matter/order-placed-payment-summary/order-placed-payment-summary.js +305 -0
  145. package/dist/matter/order-placed-payment-summary/order-placed-payment-summary.js.map +1 -0
  146. package/dist/matter/payment/payment-card-capture.d.ts +19 -0
  147. package/dist/matter/payment/payment-card-capture.js +129 -0
  148. package/dist/matter/payment/payment-card-capture.js.map +1 -0
  149. package/dist/matter/payment/payment-controller.d.ts +24 -0
  150. package/dist/matter/payment/payment-controller.js +108 -0
  151. package/dist/matter/payment/payment-controller.js.map +1 -0
  152. package/dist/matter/payment/payment-method-badges.d.ts +57 -0
  153. package/dist/matter/payment/payment-method-badges.js +192 -0
  154. package/dist/matter/payment/payment-method-badges.js.map +1 -0
  155. package/dist/matter/payment/payment.d.ts +89 -0
  156. package/dist/matter/payment/payment.js +264 -0
  157. package/dist/matter/payment/payment.js.map +1 -0
  158. package/dist/matter/payment/use-payment-method-selection.d.ts +302 -0
  159. package/dist/matter/payment/use-payment-method-selection.js +458 -0
  160. package/dist/matter/payment/use-payment-method-selection.js.map +1 -0
  161. package/dist/matter/payment/use-payment-submit-gate.d.ts +111 -0
  162. package/dist/matter/payment/use-payment-submit-gate.js +144 -0
  163. package/dist/matter/payment/use-payment-submit-gate.js.map +1 -0
  164. package/dist/matter/place-order/place-order.d.ts +74 -0
  165. package/dist/matter/place-order/place-order.js +379 -0
  166. package/dist/matter/place-order/place-order.js.map +1 -0
  167. package/dist/matter/product-list/product-list.d.ts +1 -0
  168. package/dist/matter/product-list/product-list.js.map +1 -1
  169. package/dist/matter/product-shelf/product-shelf.d.ts +62 -31
  170. package/dist/matter/product-shelf/product-shelf.js +159 -57
  171. package/dist/matter/product-shelf/product-shelf.js.map +1 -1
  172. package/dist/matter/region/region.js +1 -1
  173. package/dist/matter/region/region.js.map +1 -1
  174. package/dist/matter/save-card/save-card.d.ts +49 -0
  175. package/dist/matter/save-card/save-card.js +188 -0
  176. package/dist/matter/save-card/save-card.js.map +1 -0
  177. package/dist/matter/saved-cards/saved-cards.d.ts +79 -0
  178. package/dist/matter/saved-cards/saved-cards.js +388 -0
  179. package/dist/matter/saved-cards/saved-cards.js.map +1 -0
  180. package/dist/matter/shipping-address/country-descriptors.js +20 -10
  181. package/dist/matter/shipping-address/country-descriptors.js.map +1 -1
  182. package/dist/matter/shipping-address/shipping-address.d.ts +113 -174
  183. package/dist/matter/shipping-address/shipping-address.js +480 -791
  184. package/dist/matter/shipping-address/shipping-address.js.map +1 -1
  185. package/dist/matter/variant-selector/variant-selector.js +1 -1
  186. package/dist/particles/address-summary/address-summary.d.ts +24 -0
  187. package/dist/particles/address-summary/address-summary.js +83 -2
  188. package/dist/particles/address-summary/address-summary.js.map +1 -1
  189. package/dist/particles/alert-dialog/alert-dialog.d.ts +68 -0
  190. package/dist/particles/alert-dialog/alert-dialog.js +187 -0
  191. package/dist/particles/alert-dialog/alert-dialog.js.map +1 -0
  192. package/dist/particles/avatar/avatar.d.ts +17 -0
  193. package/dist/particles/avatar/avatar.js +65 -0
  194. package/dist/particles/avatar/avatar.js.map +1 -0
  195. package/dist/particles/checkbox/checkbox.d.ts +7 -3
  196. package/dist/particles/checkbox/checkbox.js +4 -1
  197. package/dist/particles/checkbox/checkbox.js.map +1 -1
  198. package/dist/particles/document-field/document-field.d.ts +48 -5
  199. package/dist/particles/document-field/document-field.js +189 -32
  200. package/dist/particles/document-field/document-field.js.map +1 -1
  201. package/dist/particles/field/bound-field-registry.js +52 -0
  202. package/dist/particles/field/bound-field-registry.js.map +1 -0
  203. package/dist/particles/field/field.d.ts +116 -0
  204. package/dist/particles/field/field.js +497 -6
  205. package/dist/particles/field/field.js.map +1 -1
  206. package/dist/particles/fieldset/fieldset.js +2 -2
  207. package/dist/particles/fieldset/fieldset.js.map +1 -1
  208. package/dist/particles/form/form.d.ts +104 -0
  209. package/dist/particles/form/form.js +485 -0
  210. package/dist/particles/form/form.js.map +1 -0
  211. package/dist/particles/phone-field/phone-field.d.ts +38 -10
  212. package/dist/particles/phone-field/phone-field.js +183 -39
  213. package/dist/particles/phone-field/phone-field.js.map +1 -1
  214. package/dist/particles/postal-code-field/postal-code-field.js +2 -2
  215. package/dist/particles/postal-code-field/postal-code-field.js.map +1 -1
  216. package/dist/particles/select/field-select.d.ts +43 -0
  217. package/dist/particles/select/field-select.js +150 -0
  218. package/dist/particles/select/field-select.js.map +1 -0
  219. package/dist/particles/select/select.d.ts +2 -0
  220. package/dist/particles/select/select.js.map +1 -1
  221. package/dist/particles/shared/compose-refs.js +21 -0
  222. package/dist/particles/shared/compose-refs.js.map +1 -0
  223. package/dist/schema.graphql +766 -28
  224. package/dist/sdk/actions/analytics-action-provider.d.ts +15 -0
  225. package/dist/sdk/actions/analytics-action-provider.js +19 -0
  226. package/dist/sdk/actions/analytics-action-provider.js.map +1 -0
  227. package/dist/sdk/actions/index.d.ts +3 -1
  228. package/dist/sdk/actions/index.js +3 -1
  229. package/dist/sdk/actions/payment-action-provider.d.ts +22 -0
  230. package/dist/sdk/actions/payment-action-provider.js +26 -0
  231. package/dist/sdk/actions/payment-action-provider.js.map +1 -0
  232. package/dist/sdk/actions/types.d.ts +6 -2
  233. package/dist/sdk/analytics/analytics-destination.d.ts +43 -0
  234. package/dist/sdk/analytics/analytics-destination.js +90 -0
  235. package/dist/sdk/analytics/analytics-destination.js.map +1 -0
  236. package/dist/sdk/analytics/use-analytics-actions.d.ts +57 -0
  237. package/dist/sdk/analytics/use-analytics-actions.js +109 -0
  238. package/dist/sdk/analytics/use-analytics-actions.js.map +1 -0
  239. package/dist/sdk/cart/use-cart-actions.js +10 -9
  240. package/dist/sdk/cart/use-cart-actions.js.map +1 -1
  241. package/dist/sdk/cart/use-cart-validate-on-open.js +2 -1
  242. package/dist/sdk/cart/use-cart-validate-on-open.js.map +1 -1
  243. package/dist/sdk/content/create-content-runtime.d.ts +22 -1
  244. package/dist/sdk/content/create-content-runtime.js +89 -1
  245. package/dist/sdk/content/create-content-runtime.js.map +1 -1
  246. package/dist/sdk/data/empty-content-value.js +16 -0
  247. package/dist/sdk/data/empty-content-value.js.map +1 -0
  248. package/dist/sdk/data/entity-resolution-context.js +31 -0
  249. package/dist/sdk/data/entity-resolution-context.js.map +1 -0
  250. package/dist/sdk/data/entity-subscriber.js +18 -8
  251. package/dist/sdk/data/entity-subscriber.js.map +1 -1
  252. package/dist/sdk/data/hot-data-provider.js +2 -1
  253. package/dist/sdk/data/hot-data-provider.js.map +1 -1
  254. package/dist/sdk/data/index.js +2 -1
  255. package/dist/sdk/data/page-reactive-data-root.d.ts +36 -0
  256. package/dist/sdk/data/page-reactive-data-root.js +4 -2
  257. package/dist/sdk/data/page-reactive-data-root.js.map +1 -1
  258. package/dist/sdk/data/reactive-data-provider.js +7 -3
  259. package/dist/sdk/data/reactive-data-provider.js.map +1 -1
  260. package/dist/sdk/data/reactive-list-item-data-provider.js +12 -4
  261. package/dist/sdk/data/reactive-list-item-data-provider.js.map +1 -1
  262. package/dist/sdk/data/use-reactive-data-settled.js +39 -0
  263. package/dist/sdk/data/use-reactive-data-settled.js.map +1 -0
  264. package/dist/sdk/data/use-reactive-entity.js +5 -1
  265. package/dist/sdk/data/use-reactive-entity.js.map +1 -1
  266. package/dist/sdk/data/variables-from-content.d.ts +43 -0
  267. package/dist/sdk/data/variables-from-content.js +57 -0
  268. package/dist/sdk/data/variables-from-content.js.map +1 -0
  269. package/dist/sdk/generated/fragment-types.js +2 -0
  270. package/dist/sdk/generated/fragment-types.js.map +1 -1
  271. package/dist/sdk/generated/gql.js +2 -1
  272. package/dist/sdk/generated/gql.js.map +1 -1
  273. package/dist/sdk/generated/graphql.js +85 -1
  274. package/dist/sdk/generated/graphql.js.map +1 -1
  275. package/dist/sdk/i18n/messages/en-US.js +3 -0
  276. package/dist/sdk/i18n/messages/en-US.json +3 -0
  277. package/dist/sdk/i18n/messages/en-US.json.d.ts +3 -0
  278. package/dist/sdk/i18n/messages/es-ES.js +3 -0
  279. package/dist/sdk/i18n/messages/es-ES.json +3 -0
  280. package/dist/sdk/i18n/messages/pt-BR.js +3 -0
  281. package/dist/sdk/i18n/messages/pt-BR.json +3 -0
  282. package/dist/sdk/identity/use-identity-actions.js +8 -6
  283. package/dist/sdk/identity/use-identity-actions.js.map +1 -1
  284. package/dist/sdk/payment/gateway-origin.js +35 -0
  285. package/dist/sdk/payment/gateway-origin.js.map +1 -0
  286. package/dist/sdk/payment/gateway.d.ts +85 -0
  287. package/dist/sdk/payment/gateway.js +183 -0
  288. package/dist/sdk/payment/gateway.js.map +1 -0
  289. package/dist/sdk/payment/operations.d.ts +52 -0
  290. package/dist/sdk/payment/operations.js +223 -0
  291. package/dist/sdk/payment/operations.js.map +1 -0
  292. package/dist/sdk/payment/security-code-mask.js +71 -0
  293. package/dist/sdk/payment/security-code-mask.js.map +1 -0
  294. package/dist/sdk/payment/submission-registry.d.ts +33 -0
  295. package/dist/sdk/payment/submission-registry.js +58 -0
  296. package/dist/sdk/payment/submission-registry.js.map +1 -0
  297. package/dist/sdk/payment/use-payment-actions.d.ts +78 -0
  298. package/dist/sdk/payment/use-payment-actions.js +276 -0
  299. package/dist/sdk/payment/use-payment-actions.js.map +1 -0
  300. package/dist/sdk/payment/use-place-order.d.ts +65 -0
  301. package/dist/sdk/payment/use-place-order.js +640 -0
  302. package/dist/sdk/payment/use-place-order.js.map +1 -0
  303. package/dist/sdk/region/use-region-actions.js +2 -1
  304. package/dist/sdk/region/use-region-actions.js.map +1 -1
  305. package/dist/sdk/session/read-server-session.d.ts +21 -0
  306. package/dist/sdk/session/read-server-session.js +61 -0
  307. package/dist/sdk/session/read-server-session.js.map +1 -0
  308. package/dist/sdk/session/use-session-actions.js +5 -4
  309. package/dist/sdk/session/use-session-actions.js.map +1 -1
  310. package/dist/sdk/session/use-session-revalidation.js +2 -1
  311. package/dist/sdk/session/use-session-revalidation.js.map +1 -1
  312. package/dist/sdk/shipping/use-shipping-actions.js +4 -3
  313. package/dist/sdk/shipping/use-shipping-actions.js.map +1 -1
  314. package/dist/utils/loggable-error-name.js +49 -0
  315. package/dist/utils/loggable-error-name.js.map +1 -0
  316. package/dist/utils/resolve-authored-copy.js +18 -0
  317. package/dist/utils/resolve-authored-copy.js.map +1 -0
  318. package/dist/utils/safe-href.d.ts +11 -0
  319. package/dist/utils/substitute-template.js +33 -0
  320. package/dist/utils/substitute-template.js.map +1 -0
  321. package/package.json +14 -2
  322. package/src/styles/tailwind.css +34 -0
  323. package/dist/docs/client-profile-form.md +0 -192
  324. package/dist/matter/client-profile-form/client-profile-form.d.ts +0 -126
  325. package/dist/matter/client-profile-form/client-profile-form.js +0 -662
  326. package/dist/matter/client-profile-form/client-profile-form.js.map +0 -1
@@ -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;
@@ -29,6 +72,7 @@ type RawProductNode = {
29
72
  id: string;
30
73
  title: string;
31
74
  slug: string;
75
+ routeSlug: string;
32
76
  images: {
33
77
  edges: Array<{
34
78
  node: {
@@ -53,62 +97,49 @@ export type ProductShelfItem = ProductListItem;
53
97
  export type ProductShelfSort = 'relevance' | 'price_asc' | 'price_desc' | 'name_asc' | 'name_desc' | 'release' | 'orders' | 'discount';
54
98
  export type ProductSortField = 'TITLE' | 'PRICE' | 'RELEASE_DATE' | 'RELEVANCE' | 'BEST_SELLING';
55
99
  export type SortDirection = 'ASC' | 'DESC';
56
- export type ProductsFilterInput = {
57
- searchTerm?: string;
58
- categoryIds?: string[];
59
- brandIds?: string[];
60
- collectionId?: string;
61
- specifications?: Array<{
62
- name: string;
63
- values: string[];
64
- }>;
65
- availableOnly?: boolean;
66
- };
67
- export type ProductShelfVariables = {
68
- first: number;
69
- orderBy?: {
70
- field: ProductSortField;
71
- direction: SortDirection;
72
- };
73
- filter: ProductsFilterInput;
74
- };
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
+ */
75
105
  export type ProductShelfConfig = {
76
- first?: number;
77
- itemsPerPage?: number;
78
- sort?: ProductShelfSort;
106
+ first: number;
107
+ sort: ProductShelfSort;
79
108
  searchTerm?: string;
80
109
  categoryId?: string;
81
110
  brandId?: string;
82
111
  collectionId?: string;
83
- specifications?: Array<{
84
- name: string;
85
- values: string[];
86
- }>;
87
- availableOnly?: boolean;
112
+ availableOnly: boolean;
88
113
  };
89
114
  export type ProductShelfContextValue = {
90
115
  itemsPerPage: number;
91
- variables: ProductShelfVariables;
116
+ config: ProductShelfConfig;
92
117
  count: number;
93
118
  };
94
- export type ProductShelfRootProps = ComponentPropsWithRef<'section'> & ProductShelfConfig & {
119
+ export type ProductShelfRootProps = ComponentPropsWithRef<'section'> & Partial<ProductShelfConfig> & {
120
+ itemsPerPage?: number;
95
121
  /** When true, card prices render tax-inclusive (from each item's tax data). Default false. */
96
122
  usePriceWithTaxes?: boolean;
97
123
  /** Text for the tax label part when tax display is on. Default `'Tax included'`. */
98
124
  taxesLabel?: string;
99
125
  products?: ProductShelfItem[];
126
+ /** Injected by the compiler, sliced from the page's or layout's composite content entry. */
127
+ $content?: ContentValue<typeof ProductShelfContent>;
100
128
  $data?: ProductShelfData | null;
101
129
  };
102
130
  export type ProductShelfItemsProps = ComponentPropsWithRef<'div'>;
103
131
  export type ProductShelfHeadingProps = ComponentPropsWithRef<'h2'>;
104
132
  export declare function useProductShelf(): ProductShelfContextValue;
105
133
  export declare function useProductShelfItem(): ProductShelfItem;
106
- export declare function buildProductShelfVariables(config: ProductShelfConfig): ProductShelfVariables;
134
+ export declare const PRODUCT_SHELF_SORT_MAP: Record<ProductShelfSort, {
135
+ field: ProductSortField;
136
+ direction: SortDirection;
137
+ }>;
107
138
  export declare function transformProducts(data: ProductShelfData): ProductShelfItem[];
108
139
  export declare const ProductShelfRootDefinition: ComponentDefinition<ProductShelfRootProps>;
109
140
  export declare const ProductShelfItemsDefinition: ComponentDefinition<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>>;
110
141
  export declare const ProductShelfHeadingDefinition: ComponentDefinition<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLHeadingElement>, HTMLHeadingElement>>;
111
- 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;
112
143
  export declare namespace ProductShelfRoot {
113
144
  var Skeleton: typeof ProductShelfSkeleton;
114
145
  }
@@ -1,21 +1,85 @@
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
17
80
  title
18
81
  slug
82
+ routeSlug
19
83
  images(first: 1) {
20
84
  edges {
21
85
  node {
@@ -87,7 +151,7 @@ function useProductShelfItem() {
87
151
  if (!item) throw new Error("Product card components must be used inside ProductShelfItems.");
88
152
  return item;
89
153
  }
90
- const SORT_MAP = {
154
+ const PRODUCT_SHELF_SORT_MAP = {
91
155
  relevance: {
92
156
  field: "RELEVANCE",
93
157
  direction: "DESC"
@@ -121,21 +185,6 @@ const SORT_MAP = {
121
185
  direction: "DESC"
122
186
  }
123
187
  };
124
- function buildProductShelfVariables(config) {
125
- const { first = 5, sort = "relevance", searchTerm, categoryId, brandId, collectionId, specifications, availableOnly } = config;
126
- const filter = {};
127
- if (searchTerm) filter.searchTerm = searchTerm;
128
- if (categoryId) filter.categoryIds = [categoryId];
129
- if (brandId) filter.brandIds = [brandId];
130
- if (collectionId) filter.collectionId = collectionId;
131
- if (specifications && specifications.length > 0) filter.specifications = specifications;
132
- if (availableOnly) filter.availableOnly = true;
133
- return {
134
- first,
135
- orderBy: SORT_MAP[sort],
136
- filter
137
- };
138
- }
139
188
  function transformProducts(data) {
140
189
  return data.edges.map(({ node }) => {
141
190
  const image = node.images.edges[0]?.node;
@@ -149,6 +198,7 @@ function transformProducts(data) {
149
198
  id: node.id,
150
199
  name: node.title,
151
200
  slug: node.slug,
201
+ routeSlug: node.routeSlug,
152
202
  image: {
153
203
  src: image?.url ?? "",
154
204
  alt: image?.altText ?? node.title
@@ -173,21 +223,69 @@ const ProductShelfRootDefinition = defineComponent({
173
223
  fragment,
174
224
  fetchStrategy: "lazy",
175
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
+ } },
176
264
  editor: {
177
265
  label: "Product Shelf Root",
178
266
  category: "commerce"
179
267
  },
180
268
  providesContext: "product-shelf",
181
269
  schema: {
182
- first: {
270
+ itemsPerPage: {
183
271
  type: "number",
184
272
  default: 5,
185
- label: "Number of Products"
273
+ label: "Items Per Page"
186
274
  },
187
- 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: {
188
286
  type: "number",
189
287
  default: 5,
190
- label: "Items Per Page"
288
+ label: "Number of Products"
191
289
  },
192
290
  sort: {
193
291
  type: [
@@ -219,27 +317,13 @@ const ProductShelfRootDefinition = defineComponent({
219
317
  type: "string",
220
318
  label: "Collection ID"
221
319
  },
222
- specifications: {
223
- type: "array",
224
- label: "Specification Filters"
225
- },
226
320
  availableOnly: {
227
321
  type: "boolean",
228
322
  default: false,
229
323
  label: "Available Only"
230
- },
231
- usePriceWithTaxes: {
232
- type: "boolean",
233
- default: false,
234
- label: "Use Price With Taxes"
235
- },
236
- taxesLabel: {
237
- type: "string",
238
- default: "Tax included",
239
- label: "Taxes Label"
240
324
  }
241
325
  },
242
- 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."
243
327
  });
244
328
  const ProductShelfItemsDefinition = defineComponent({
245
329
  name: "ProductShelfItems",
@@ -265,8 +349,31 @@ const ProductShelfHeadingDefinition = defineComponent({
265
349
  schema: {},
266
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."
267
351
  });
268
- 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 }) {
269
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
+ ]);
270
377
  const headingId = useId();
271
378
  const [headingCount, setHeadingCount] = useState(0);
272
379
  const registerHeading = useCallback(() => {
@@ -281,27 +388,22 @@ function ProductShelfRoot({ first = 5, itemsPerPage = 5, sort = "relevance", sea
281
388
  usePriceWithTaxes,
282
389
  taxesLabel
283
390
  }), [usePriceWithTaxes, taxesLabel]);
284
- const hasHeading = headingCount > 0;
285
- let items;
286
- if (products !== void 0) items = products;
287
- else if ($data === void 0) return /* @__PURE__ */ jsx(ProductShelfSkeleton, { className });
288
- else items = $data ? transformProducts($data) : [];
289
- items = items.slice(0, first);
290
- if (items.length === 0) return null;
291
- 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(() => ({
292
396
  itemsPerPage,
293
- variables: buildProductShelfVariables({
294
- first,
295
- sort,
296
- searchTerm,
297
- categoryId,
298
- brandId,
299
- collectionId,
300
- specifications,
301
- availableOnly
302
- }),
397
+ config: shelfConfig,
303
398
  count: items.length
304
- };
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;
305
407
  return /* @__PURE__ */ jsx(ProductListConfigContext, {
306
408
  value: config,
307
409
  children: /* @__PURE__ */ jsx(ProductShelfProductsContext, {
@@ -371,6 +473,6 @@ const ProductShelf = {
371
473
  Skeleton: ProductShelfSkeleton
372
474
  };
373
475
  //#endregion
374
- 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 };
375
477
 
376
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 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 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 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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"}
@@ -476,7 +476,7 @@ function RegionPostalCodeControl({ className, mask, label, placeholder, errorMes
476
476
  * from the top. Waits for `pending` to clear, because focusing a still-disabled input is a no-op:
477
477
  * the errors and the pending flag settle in separate microtasks, so there is a render in between
478
478
  * where the rejection is known and the field is not yet editable. The field is reached through the
479
- * root the way ClientProfileForm reaches its own fields.
479
+ * root via a scoped querySelector, not a ref threaded down through props.
480
480
  */
481
481
  useEffect(() => {
482
482
  if (!refused || pending) return;