@shopify/hydrogen 2026.10.0-preview.4 → 2026.10.0

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 (437) hide show
  1. package/dist/cli/index.mjs +23 -12
  2. package/dist/client/client.d.mts +18 -15
  3. package/dist/client/client.mjs +8 -3
  4. package/dist/client/client.mjs.map +1 -1
  5. package/dist/client/errors.d.mts +35 -13
  6. package/dist/client/errors.mjs +23 -13
  7. package/dist/client/errors.mjs.map +1 -1
  8. package/dist/client/types.d.mts +140 -90
  9. package/dist/core/analytics/cart-tracker.d.mts +19 -10
  10. package/dist/core/analytics/cart-tracker.mjs +18 -10
  11. package/dist/core/analytics/cart-tracker.mjs.map +1 -1
  12. package/dist/core/analytics/events.d.mts +17 -11
  13. package/dist/core/analytics/events.mjs +13 -4
  14. package/dist/core/analytics/events.mjs.map +1 -1
  15. package/dist/core/analytics/types.d.mts +207 -118
  16. package/dist/core/analytics/utils/flatten-connection.d.mts +11 -9
  17. package/dist/core/analytics/utils/flatten-connection.mjs +7 -6
  18. package/dist/core/analytics/utils/flatten-connection.mjs.map +1 -1
  19. package/dist/core/cache/fetch-with-cache.d.mts +24 -4
  20. package/dist/core/cache/fetch-with-cache.mjs +17 -2
  21. package/dist/core/cache/fetch-with-cache.mjs.map +1 -1
  22. package/dist/core/cache/key.d.mts +2 -0
  23. package/dist/core/cache/key.mjs.map +1 -1
  24. package/dist/core/cache/run-with-cache.d.mts +56 -8
  25. package/dist/core/cache/run-with-cache.mjs +17 -6
  26. package/dist/core/cache/run-with-cache.mjs.map +1 -1
  27. package/dist/core/cache/store.d.mts +8 -6
  28. package/dist/core/cache/store.mjs.map +1 -1
  29. package/dist/core/cache/strategies.d.mts +27 -2
  30. package/dist/core/cache/strategies.mjs +6 -0
  31. package/dist/core/cache/strategies.mjs.map +1 -1
  32. package/dist/core/cart/actions.d.mts +37 -30
  33. package/dist/core/cart/actions.mjs +21 -9
  34. package/dist/core/cart/actions.mjs.map +1 -1
  35. package/dist/core/cart/attach-quantity-input.d.mts +8 -7
  36. package/dist/core/cart/attach-quantity-input.mjs +8 -7
  37. package/dist/core/cart/attach-quantity-input.mjs.map +1 -1
  38. package/dist/core/cart/buyer-identity-sync.d.mts +7 -6
  39. package/dist/core/cart/buyer-identity-sync.mjs.map +1 -1
  40. package/dist/core/cart/cart.d.mts +59 -46
  41. package/dist/core/cart/cart.mjs +46 -29
  42. package/dist/core/cart/cart.mjs.map +1 -1
  43. package/dist/core/cart/cookie.d.mts +8 -4
  44. package/dist/core/cart/cookie.mjs +8 -4
  45. package/dist/core/cart/cookie.mjs.map +1 -1
  46. package/dist/core/cart/form.d.mts +34 -20
  47. package/dist/core/cart/form.mjs +6 -4
  48. package/dist/core/cart/form.mjs.map +1 -1
  49. package/dist/core/cart/get-cart.d.mts +27 -15
  50. package/dist/core/cart/get-cart.mjs +13 -8
  51. package/dist/core/cart/get-cart.mjs.map +1 -1
  52. package/dist/core/cart/quantity.d.mts +16 -5
  53. package/dist/core/cart/quantity.mjs +16 -5
  54. package/dist/core/cart/quantity.mjs.map +1 -1
  55. package/dist/core/cart/queries.d.mts +25 -19
  56. package/dist/core/cart/queries.mjs +15 -1
  57. package/dist/core/cart/queries.mjs.map +1 -1
  58. package/dist/core/cart/server-handlers.d.mts +82 -45
  59. package/dist/core/cart/server-handlers.mjs +4 -0
  60. package/dist/core/cart/server-handlers.mjs.map +1 -1
  61. package/dist/core/cart/state.d.mts +110 -64
  62. package/dist/core/cart/state.mjs +24 -6
  63. package/dist/core/cart/state.mjs.map +1 -1
  64. package/dist/core/collection/collection.d.mts +52 -53
  65. package/dist/core/collection/collection.mjs +5 -3
  66. package/dist/core/collection/collection.mjs.map +1 -1
  67. package/dist/core/collection/reconciler.d.mts +23 -16
  68. package/dist/core/collection/reconciler.mjs +8 -4
  69. package/dist/core/collection/reconciler.mjs.map +1 -1
  70. package/dist/core/collection/state.d.mts +31 -26
  71. package/dist/core/collection/state.mjs +4 -3
  72. package/dist/core/collection/state.mjs.map +1 -1
  73. package/dist/core/collection/url.d.mts +70 -29
  74. package/dist/core/collection/url.mjs +63 -25
  75. package/dist/core/collection/url.mjs.map +1 -1
  76. package/dist/core/constants.d.mts +1 -0
  77. package/dist/core/constants.mjs +1 -0
  78. package/dist/core/constants.mjs.map +1 -1
  79. package/dist/core/logging/logging.d.mts +14 -8
  80. package/dist/core/logging/logging.mjs +15 -10
  81. package/dist/core/logging/logging.mjs.map +1 -1
  82. package/dist/core/logging/types.d.mts +28 -11
  83. package/dist/core/logging/types.mjs.map +1 -1
  84. package/dist/core/money/format.d.mts +6 -4
  85. package/dist/core/money/format.mjs +19 -9
  86. package/dist/core/money/format.mjs.map +1 -1
  87. package/dist/core/money/types.d.mts +41 -25
  88. package/dist/core/predictive-search/form.d.mts +37 -7
  89. package/dist/core/predictive-search/form.mjs +21 -3
  90. package/dist/core/predictive-search/form.mjs.map +1 -1
  91. package/dist/core/predictive-search/queries.d.mts +18 -30
  92. package/dist/core/predictive-search/queries.mjs +7 -3
  93. package/dist/core/predictive-search/queries.mjs.map +1 -1
  94. package/dist/core/predictive-search/search.d.mts +25 -27
  95. package/dist/core/predictive-search/search.mjs +20 -19
  96. package/dist/core/predictive-search/search.mjs.map +1 -1
  97. package/dist/core/predictive-search/server-handlers.d.mts +25 -26
  98. package/dist/core/predictive-search/server-handlers.mjs +4 -0
  99. package/dist/core/predictive-search/server-handlers.mjs.map +1 -1
  100. package/dist/core/predictive-search/store.d.mts +65 -24
  101. package/dist/core/predictive-search/store.mjs +12 -1
  102. package/dist/core/predictive-search/store.mjs.map +1 -1
  103. package/dist/core/predictive-search/url.d.mts +36 -37
  104. package/dist/core/predictive-search/url.mjs +14 -6
  105. package/dist/core/predictive-search/url.mjs.map +1 -1
  106. package/dist/core/product/form.d.mts +63 -16
  107. package/dist/core/product/form.mjs +8 -2
  108. package/dist/core/product/form.mjs.map +1 -1
  109. package/dist/core/product/options.d.mts +8 -10
  110. package/dist/core/product/options.mjs +8 -10
  111. package/dist/core/product/options.mjs.map +1 -1
  112. package/dist/core/product/product-form.d.mts +77 -29
  113. package/dist/core/product/product-form.mjs +32 -10
  114. package/dist/core/product/product-form.mjs.map +1 -1
  115. package/dist/core/product/state.d.mts +55 -32
  116. package/dist/core/product/url.d.mts +19 -13
  117. package/dist/core/product/url.mjs +10 -10
  118. package/dist/core/product/url.mjs.map +1 -1
  119. package/dist/core/request-context.d.mts +77 -19
  120. package/dist/core/request-context.mjs +5 -1
  121. package/dist/core/request-context.mjs.map +1 -1
  122. package/dist/core/request-routing/handle-shopify-redirects.d.mts +12 -4
  123. package/dist/core/request-routing/handle-shopify-redirects.mjs +9 -2
  124. package/dist/core/request-routing/handle-shopify-redirects.mjs.map +1 -1
  125. package/dist/core/request-routing/handle-shopify-routes.d.mts +5 -5
  126. package/dist/core/request-routing/handle-shopify-routes.mjs +7 -5
  127. package/dist/core/request-routing/handle-shopify-routes.mjs.map +1 -1
  128. package/dist/core/request-routing/interceptors/proxy.mjs +79 -43
  129. package/dist/core/request-routing/interceptors/proxy.mjs.map +1 -1
  130. package/dist/core/request-routing/interceptors/ucp-profile-proxy.mjs +69 -0
  131. package/dist/core/request-routing/interceptors/ucp-profile-proxy.mjs.map +1 -0
  132. package/dist/core/request-routing/interceptors/url-redirects.mjs +6 -1
  133. package/dist/core/request-routing/interceptors/url-redirects.mjs.map +1 -1
  134. package/dist/core/request-routing/interceptors/well-known.mjs +1 -1
  135. package/dist/core/request-routing/interceptors/well-known.mjs.map +1 -1
  136. package/dist/core/request-routing/registered-routes.d.mts +12 -0
  137. package/dist/core/request-routing/registered-routes.mjs +12 -0
  138. package/dist/core/request-routing/registered-routes.mjs.map +1 -1
  139. package/dist/core/request-routing/route-types.d.mts +43 -18
  140. package/dist/core/shop-pay/shop-pay.d.mts +71 -35
  141. package/dist/core/shop-pay/shop-pay.mjs +36 -10
  142. package/dist/core/shop-pay/shop-pay.mjs.map +1 -1
  143. package/dist/core/shopify-scripts/index.d.mts +15 -5
  144. package/dist/core/shopify-scripts/index.mjs +15 -5
  145. package/dist/core/shopify-scripts/index.mjs.map +1 -1
  146. package/dist/core/shopify-scripts/initialize.d.mts +12 -4
  147. package/dist/core/shopify-scripts/initialize.mjs +12 -4
  148. package/dist/core/shopify-scripts/initialize.mjs.map +1 -1
  149. package/dist/core/shopify-scripts/types.d.mts +58 -25
  150. package/dist/core/standard-routes/build.d.mts +11 -12
  151. package/dist/core/standard-routes/build.mjs +11 -12
  152. package/dist/core/standard-routes/build.mjs.map +1 -1
  153. package/dist/core/standard-routes/types.d.mts +30 -24
  154. package/dist/core/url.mjs +2 -1
  155. package/dist/core/url.mjs.map +1 -1
  156. package/dist/customer-account/client.d.mts +36 -69
  157. package/dist/customer-account/client.mjs +7 -8
  158. package/dist/customer-account/client.mjs.map +1 -1
  159. package/dist/customer-account/errors.d.mts +45 -36
  160. package/dist/customer-account/errors.mjs +21 -36
  161. package/dist/customer-account/errors.mjs.map +1 -1
  162. package/dist/customer-account/graphql.d.mts +11 -23
  163. package/dist/customer-account/graphql.mjs +3 -9
  164. package/dist/customer-account/graphql.mjs.map +1 -1
  165. package/dist/customer-account/session.d.mts +130 -100
  166. package/dist/customer-account/session.mjs +32 -10
  167. package/dist/customer-account/session.mjs.map +1 -1
  168. package/dist/customer-account/type-resolver.d.mts +7 -8
  169. package/dist/development/client/client.d.mts +18 -15
  170. package/dist/development/client/client.mjs +8 -3
  171. package/dist/development/client/client.mjs.map +1 -1
  172. package/dist/development/client/errors.d.mts +35 -13
  173. package/dist/development/client/errors.mjs +23 -13
  174. package/dist/development/client/errors.mjs.map +1 -1
  175. package/dist/development/client/types.d.mts +140 -90
  176. package/dist/development/core/analytics/cart-tracker.d.mts +19 -10
  177. package/dist/development/core/analytics/cart-tracker.mjs +18 -10
  178. package/dist/development/core/analytics/cart-tracker.mjs.map +1 -1
  179. package/dist/development/core/analytics/events.d.mts +17 -11
  180. package/dist/development/core/analytics/events.mjs +13 -4
  181. package/dist/development/core/analytics/events.mjs.map +1 -1
  182. package/dist/development/core/analytics/types.d.mts +207 -118
  183. package/dist/development/core/analytics/utils/flatten-connection.d.mts +11 -9
  184. package/dist/development/core/analytics/utils/flatten-connection.mjs +7 -6
  185. package/dist/development/core/analytics/utils/flatten-connection.mjs.map +1 -1
  186. package/dist/development/core/cache/fetch-with-cache.d.mts +24 -4
  187. package/dist/development/core/cache/fetch-with-cache.mjs +17 -2
  188. package/dist/development/core/cache/fetch-with-cache.mjs.map +1 -1
  189. package/dist/development/core/cache/key.d.mts +2 -0
  190. package/dist/development/core/cache/key.mjs.map +1 -1
  191. package/dist/development/core/cache/run-with-cache.d.mts +56 -8
  192. package/dist/development/core/cache/run-with-cache.mjs +17 -6
  193. package/dist/development/core/cache/run-with-cache.mjs.map +1 -1
  194. package/dist/development/core/cache/store.d.mts +8 -6
  195. package/dist/development/core/cache/store.mjs.map +1 -1
  196. package/dist/development/core/cache/strategies.d.mts +27 -2
  197. package/dist/development/core/cache/strategies.mjs +6 -0
  198. package/dist/development/core/cache/strategies.mjs.map +1 -1
  199. package/dist/development/core/cart/actions.d.mts +37 -30
  200. package/dist/development/core/cart/actions.mjs +21 -9
  201. package/dist/development/core/cart/actions.mjs.map +1 -1
  202. package/dist/development/core/cart/attach-quantity-input.d.mts +8 -7
  203. package/dist/development/core/cart/attach-quantity-input.mjs +8 -7
  204. package/dist/development/core/cart/attach-quantity-input.mjs.map +1 -1
  205. package/dist/development/core/cart/buyer-identity-sync.d.mts +6 -5
  206. package/dist/development/core/cart/buyer-identity-sync.mjs.map +1 -1
  207. package/dist/development/core/cart/cart.d.mts +59 -46
  208. package/dist/development/core/cart/cart.mjs +46 -29
  209. package/dist/development/core/cart/cart.mjs.map +1 -1
  210. package/dist/development/core/cart/cookie.d.mts +8 -4
  211. package/dist/development/core/cart/cookie.mjs +8 -4
  212. package/dist/development/core/cart/cookie.mjs.map +1 -1
  213. package/dist/development/core/cart/form.d.mts +34 -20
  214. package/dist/development/core/cart/form.mjs +6 -4
  215. package/dist/development/core/cart/form.mjs.map +1 -1
  216. package/dist/development/core/cart/get-cart.d.mts +27 -15
  217. package/dist/development/core/cart/get-cart.mjs +13 -8
  218. package/dist/development/core/cart/get-cart.mjs.map +1 -1
  219. package/dist/development/core/cart/quantity.d.mts +16 -5
  220. package/dist/development/core/cart/quantity.mjs +16 -5
  221. package/dist/development/core/cart/quantity.mjs.map +1 -1
  222. package/dist/development/core/cart/queries.d.mts +25 -19
  223. package/dist/development/core/cart/queries.mjs +15 -1
  224. package/dist/development/core/cart/queries.mjs.map +1 -1
  225. package/dist/development/core/cart/server-handlers.d.mts +82 -45
  226. package/dist/development/core/cart/server-handlers.mjs +4 -0
  227. package/dist/development/core/cart/server-handlers.mjs.map +1 -1
  228. package/dist/development/core/cart/state.d.mts +110 -64
  229. package/dist/development/core/cart/state.mjs +24 -6
  230. package/dist/development/core/cart/state.mjs.map +1 -1
  231. package/dist/development/core/collection/collection.d.mts +52 -53
  232. package/dist/development/core/collection/collection.mjs +5 -3
  233. package/dist/development/core/collection/collection.mjs.map +1 -1
  234. package/dist/development/core/collection/reconciler.d.mts +23 -16
  235. package/dist/development/core/collection/reconciler.mjs +8 -4
  236. package/dist/development/core/collection/reconciler.mjs.map +1 -1
  237. package/dist/development/core/collection/state.d.mts +31 -26
  238. package/dist/development/core/collection/state.mjs +4 -3
  239. package/dist/development/core/collection/state.mjs.map +1 -1
  240. package/dist/development/core/collection/url.d.mts +70 -29
  241. package/dist/development/core/collection/url.mjs +63 -25
  242. package/dist/development/core/collection/url.mjs.map +1 -1
  243. package/dist/development/core/constants.mjs.map +1 -1
  244. package/dist/development/core/logging/logging.d.mts +14 -8
  245. package/dist/development/core/logging/logging.mjs +15 -10
  246. package/dist/development/core/logging/logging.mjs.map +1 -1
  247. package/dist/development/core/logging/types.d.mts +28 -11
  248. package/dist/development/core/logging/types.mjs.map +1 -1
  249. package/dist/development/core/money/format.d.mts +6 -4
  250. package/dist/development/core/money/format.mjs +19 -9
  251. package/dist/development/core/money/format.mjs.map +1 -1
  252. package/dist/development/core/money/types.d.mts +41 -25
  253. package/dist/development/core/predictive-search/form.d.mts +37 -7
  254. package/dist/development/core/predictive-search/form.mjs +21 -3
  255. package/dist/development/core/predictive-search/form.mjs.map +1 -1
  256. package/dist/development/core/predictive-search/queries.d.mts +18 -30
  257. package/dist/development/core/predictive-search/queries.mjs +7 -3
  258. package/dist/development/core/predictive-search/queries.mjs.map +1 -1
  259. package/dist/development/core/predictive-search/search.d.mts +25 -27
  260. package/dist/development/core/predictive-search/search.mjs +20 -19
  261. package/dist/development/core/predictive-search/search.mjs.map +1 -1
  262. package/dist/development/core/predictive-search/server-handlers.d.mts +25 -26
  263. package/dist/development/core/predictive-search/server-handlers.mjs +4 -0
  264. package/dist/development/core/predictive-search/server-handlers.mjs.map +1 -1
  265. package/dist/development/core/predictive-search/store.d.mts +65 -24
  266. package/dist/development/core/predictive-search/store.mjs +12 -1
  267. package/dist/development/core/predictive-search/store.mjs.map +1 -1
  268. package/dist/development/core/predictive-search/url.d.mts +36 -37
  269. package/dist/development/core/predictive-search/url.mjs +14 -6
  270. package/dist/development/core/predictive-search/url.mjs.map +1 -1
  271. package/dist/development/core/product/form.d.mts +63 -16
  272. package/dist/development/core/product/form.mjs +8 -2
  273. package/dist/development/core/product/form.mjs.map +1 -1
  274. package/dist/development/core/product/options.d.mts +8 -10
  275. package/dist/development/core/product/options.mjs +8 -10
  276. package/dist/development/core/product/options.mjs.map +1 -1
  277. package/dist/development/core/product/product-form.d.mts +77 -29
  278. package/dist/development/core/product/product-form.mjs +32 -10
  279. package/dist/development/core/product/product-form.mjs.map +1 -1
  280. package/dist/development/core/product/state.d.mts +55 -32
  281. package/dist/development/core/product/url.d.mts +19 -13
  282. package/dist/development/core/product/url.mjs +10 -10
  283. package/dist/development/core/product/url.mjs.map +1 -1
  284. package/dist/development/core/request-context.d.mts +77 -19
  285. package/dist/development/core/request-context.mjs +5 -1
  286. package/dist/development/core/request-context.mjs.map +1 -1
  287. package/dist/development/core/request-routing/handle-shopify-redirects.d.mts +12 -4
  288. package/dist/development/core/request-routing/handle-shopify-redirects.mjs +9 -2
  289. package/dist/development/core/request-routing/handle-shopify-redirects.mjs.map +1 -1
  290. package/dist/development/core/request-routing/handle-shopify-routes.development.d.mts +9 -1
  291. package/dist/development/core/request-routing/handle-shopify-routes.development.mjs +7 -0
  292. package/dist/development/core/request-routing/handle-shopify-routes.development.mjs.map +1 -1
  293. package/dist/development/core/request-routing/handle-shopify-routes.mjs +7 -5
  294. package/dist/development/core/request-routing/handle-shopify-routes.mjs.map +1 -1
  295. package/dist/development/core/request-routing/interceptors/proxy.mjs +79 -43
  296. package/dist/development/core/request-routing/interceptors/proxy.mjs.map +1 -1
  297. package/dist/development/core/request-routing/interceptors/ucp-profile-proxy.mjs +69 -0
  298. package/dist/development/core/request-routing/interceptors/ucp-profile-proxy.mjs.map +1 -0
  299. package/dist/development/core/request-routing/interceptors/url-redirects.mjs +6 -1
  300. package/dist/development/core/request-routing/interceptors/url-redirects.mjs.map +1 -1
  301. package/dist/development/core/request-routing/interceptors/well-known.mjs +1 -1
  302. package/dist/development/core/request-routing/interceptors/well-known.mjs.map +1 -1
  303. package/dist/development/core/request-routing/registered-routes.d.mts +12 -0
  304. package/dist/development/core/request-routing/registered-routes.mjs +12 -0
  305. package/dist/development/core/request-routing/registered-routes.mjs.map +1 -1
  306. package/dist/development/core/request-routing/route-types.d.mts +43 -18
  307. package/dist/development/core/shop-pay/shop-pay.d.mts +71 -35
  308. package/dist/development/core/shop-pay/shop-pay.mjs +36 -10
  309. package/dist/development/core/shop-pay/shop-pay.mjs.map +1 -1
  310. package/dist/development/core/shopify-scripts/index.d.mts +15 -5
  311. package/dist/development/core/shopify-scripts/index.mjs +15 -5
  312. package/dist/development/core/shopify-scripts/index.mjs.map +1 -1
  313. package/dist/development/core/shopify-scripts/initialize.d.mts +12 -4
  314. package/dist/development/core/shopify-scripts/initialize.mjs +12 -4
  315. package/dist/development/core/shopify-scripts/initialize.mjs.map +1 -1
  316. package/dist/development/core/shopify-scripts/types.d.mts +58 -25
  317. package/dist/development/core/standard-routes/build.d.mts +11 -12
  318. package/dist/development/core/standard-routes/build.mjs +11 -12
  319. package/dist/development/core/standard-routes/build.mjs.map +1 -1
  320. package/dist/development/core/standard-routes/types.d.mts +30 -24
  321. package/dist/development/core/url.mjs +2 -1
  322. package/dist/development/core/url.mjs.map +1 -1
  323. package/dist/development/customer-account/session.d.mts +45 -54
  324. package/dist/development/customer-account/session.mjs +20 -4
  325. package/dist/development/customer-account/session.mjs.map +1 -1
  326. package/dist/development/globals.d.mts +20 -11
  327. package/dist/development/graphql/generated/storefront-api-types.d.mts +127 -1
  328. package/dist/development/graphql/graphql.d.mts +17 -16
  329. package/dist/development/graphql/graphql.mjs +7 -8
  330. package/dist/development/graphql/graphql.mjs.map +1 -1
  331. package/dist/development/graphql/type-resolver.d.mts +15 -8
  332. package/dist/development/react/cart.d.mts +78 -32
  333. package/dist/development/react/cart.mjs +56 -29
  334. package/dist/development/react/cart.mjs.map +1 -1
  335. package/dist/development/react/collection.d.mts +40 -22
  336. package/dist/development/react/collection.mjs +27 -7
  337. package/dist/development/react/collection.mjs.map +1 -1
  338. package/dist/development/react/predictive-search.d.mts +65 -50
  339. package/dist/development/react/predictive-search.mjs +23 -21
  340. package/dist/development/react/predictive-search.mjs.map +1 -1
  341. package/dist/development/react/product.d.mts +45 -16
  342. package/dist/development/react/product.mjs +13 -11
  343. package/dist/development/react/product.mjs.map +1 -1
  344. package/dist/development/react/shop-pay.d.mts +15 -0
  345. package/dist/development/react/shop-pay.mjs +9 -0
  346. package/dist/development/react/shop-pay.mjs.map +1 -1
  347. package/dist/development/react/shopify-scripts.d.mts +23 -2
  348. package/dist/development/react/shopify-scripts.mjs +9 -0
  349. package/dist/development/react/shopify-scripts.mjs.map +1 -1
  350. package/dist/development/vue/cart.d.mts +28 -23
  351. package/dist/development/vue/cart.mjs +42 -25
  352. package/dist/development/vue/cart.mjs.map +1 -1
  353. package/dist/development/vue/collection.d.mts +20 -12
  354. package/dist/development/vue/collection.mjs +15 -7
  355. package/dist/development/vue/collection.mjs.map +1 -1
  356. package/dist/development/vue/index.d.mts +2 -2
  357. package/dist/development/vue/index.mjs +2 -2
  358. package/dist/development/vue/predictive-search.d.mts +31 -36
  359. package/dist/development/vue/predictive-search.mjs +16 -22
  360. package/dist/development/vue/predictive-search.mjs.map +1 -1
  361. package/dist/development/vue/product.d.mts +16 -15
  362. package/dist/development/vue/product.mjs +11 -11
  363. package/dist/development/vue/product.mjs.map +1 -1
  364. package/dist/development/vue/shop-pay.d.mts +14 -17
  365. package/dist/development/vue/shop-pay.mjs +8 -0
  366. package/dist/development/vue/shop-pay.mjs.map +1 -1
  367. package/dist/development/vue/shopify-scripts.d.mts +11 -0
  368. package/dist/development/vue/shopify-scripts.mjs +6 -0
  369. package/dist/development/vue/shopify-scripts.mjs.map +1 -1
  370. package/dist/globals.d.mts +20 -11
  371. package/dist/graphql/generated/storefront-api-types.d.mts +127 -1
  372. package/dist/graphql/graphql.d.mts +17 -16
  373. package/dist/graphql/graphql.mjs +7 -8
  374. package/dist/graphql/graphql.mjs.map +1 -1
  375. package/dist/graphql/type-resolver.d.mts +15 -8
  376. package/dist/react/cart.d.mts +78 -32
  377. package/dist/react/cart.mjs +56 -29
  378. package/dist/react/cart.mjs.map +1 -1
  379. package/dist/react/collection.d.mts +40 -22
  380. package/dist/react/collection.mjs +27 -7
  381. package/dist/react/collection.mjs.map +1 -1
  382. package/dist/react/predictive-search.d.mts +65 -50
  383. package/dist/react/predictive-search.mjs +23 -21
  384. package/dist/react/predictive-search.mjs.map +1 -1
  385. package/dist/react/product.d.mts +45 -16
  386. package/dist/react/product.mjs +13 -11
  387. package/dist/react/product.mjs.map +1 -1
  388. package/dist/react/shop-pay.d.mts +15 -0
  389. package/dist/react/shop-pay.mjs +9 -0
  390. package/dist/react/shop-pay.mjs.map +1 -1
  391. package/dist/react/shopify-scripts.d.mts +23 -2
  392. package/dist/react/shopify-scripts.mjs +9 -0
  393. package/dist/react/shopify-scripts.mjs.map +1 -1
  394. package/dist/ts-plugin/index.cjs +6 -0
  395. package/dist/ts-plugin/index.cjs.map +1 -1
  396. package/dist/ts-plugin/index.d.cts +6 -0
  397. package/dist/vite/local-https.d.mts +51 -17
  398. package/dist/vite/local-https.mjs +26 -5
  399. package/dist/vite/local-https.mjs.map +1 -1
  400. package/dist/vue/cart.d.mts +28 -23
  401. package/dist/vue/cart.mjs +42 -25
  402. package/dist/vue/cart.mjs.map +1 -1
  403. package/dist/vue/collection.d.mts +20 -12
  404. package/dist/vue/collection.mjs +15 -7
  405. package/dist/vue/collection.mjs.map +1 -1
  406. package/dist/vue/index.d.mts +2 -2
  407. package/dist/vue/index.mjs +2 -2
  408. package/dist/vue/predictive-search.d.mts +31 -36
  409. package/dist/vue/predictive-search.mjs +16 -22
  410. package/dist/vue/predictive-search.mjs.map +1 -1
  411. package/dist/vue/product.d.mts +16 -15
  412. package/dist/vue/product.mjs +11 -11
  413. package/dist/vue/product.mjs.map +1 -1
  414. package/dist/vue/shop-pay.d.mts +14 -17
  415. package/dist/vue/shop-pay.mjs +8 -0
  416. package/dist/vue/shop-pay.mjs.map +1 -1
  417. package/dist/vue/shopify-scripts.d.mts +11 -0
  418. package/dist/vue/shopify-scripts.mjs +6 -0
  419. package/dist/vue/shopify-scripts.mjs.map +1 -1
  420. package/package.json +3 -1
  421. package/skills/hydrogen-analytics/SKILL.md +1 -1
  422. package/skills/hydrogen-cart-ui/SKILL.md +28 -2
  423. package/skills/hydrogen-collection-browser/SKILL.md +9 -1
  424. package/skills/hydrogen-collection-browser/references/nextjs.md +1 -1
  425. package/skills/hydrogen-collection-browser/references/nuxt.md +1 -1
  426. package/skills/hydrogen-collection-browser/references/react.md +151 -32
  427. package/skills/hydrogen-customer-account/SKILL.md +2 -0
  428. package/skills/hydrogen-request-handlers/SKILL.md +21 -11
  429. package/skills/hydrogen-setup/references/analytics.md +14 -8
  430. package/skills/hydrogen-setup/steps/1-inspect-app.md +2 -2
  431. package/skills/hydrogen-setup/steps/6-product-detail-page.md +21 -11
  432. package/skills/hydrogen-storefront-client/SKILL.md +1 -1
  433. package/skills/hydrogen-storefront-client/references/caching.md +2 -0
  434. package/skills/hydrogen-variant-form/SKILL.md +25 -7
  435. package/skills/hydrogen-variant-form/references/nextjs.md +39 -4
  436. package/skills/hydrogen-variant-form/references/nuxt.md +83 -42
  437. package/skills/hydrogen-variant-form/references/react.md +45 -9
package/dist/vue/cart.mjs CHANGED
@@ -26,11 +26,9 @@ function useOptionalCartStore() {
26
26
  return inject(CartStoreKey, null);
27
27
  }
28
28
  /**
29
- * Vue component that creates and manages a {@link CartStore} instance.
29
+ * Creates a cart store and shares the store with the cart composables below the provider.
30
30
  *
31
- * Calls {@link CartStore.connect} on mount and {@link CartStore.destroy} on unmount.
32
- * All cart composables (`useCart`, `useCartForm`, `useCartActions`) must be
33
- * descendants of this component.
31
+ * The provider connects the store on mount and destroys the store on unmount. Render every cart composable inside the provider. The provider creates its store once from the first initial data and ignores later changes.
34
32
  *
35
33
  * @example
36
34
  * ```vue
@@ -38,6 +36,7 @@ function useOptionalCartStore() {
38
36
  * <App />
39
37
  * </CartProvider>
40
38
  * ```
39
+ * @publicDocs
41
40
  */
42
41
  const CartProvider = defineComponent({
43
42
  name: "CartProvider",
@@ -62,10 +61,11 @@ function useCart(selector, isEqual) {
62
61
  return useCartSelector(useCartStore("useCart"), selector ?? ((state) => state), isEqual);
63
62
  }
64
63
  /**
65
- * Returns cart actions for reconciling state after out-of-band mutations.
64
+ * Returns the cart action that syncs the cart after a mutation outside cart forms.
66
65
  *
67
- * Currently exposes {@link CartStore.refresh} — call it after server-side cart
68
- * mutations that bypass the form system.
66
+ * Call `refresh` after a server-side cart mutation that bypasses cart forms, such as a server action that creates the cart.
67
+ *
68
+ * @returns The `refresh` action.
69
69
  *
70
70
  * @example
71
71
  * ```vue
@@ -78,15 +78,15 @@ function useCart(selector, isEqual) {
78
78
  * }
79
79
  * <\/script>
80
80
  * ```
81
+ * @publicDocs
81
82
  */
82
83
  function useCartActions() {
83
84
  return { refresh: useCartStore("useCartActions").refresh };
84
85
  }
85
86
  /**
86
- * Subscribes the {@link CartStore} to the analytics event dispatcher.
87
+ * Publishes cart analytics events when the cart changes.
87
88
  *
88
- * Call once near the root of your app. Starts tracking on mount via `onMounted`
89
- * and cleans up via `onScopeDispose`.
89
+ * Call the composable once near the root of your app. The composable starts tracking on mount and stops when the component's scope ends. The composable throws when you call it outside the cart provider.
90
90
  *
91
91
  * @example
92
92
  * ```vue
@@ -94,6 +94,7 @@ function useCartActions() {
94
94
  * useCartAnalytics();
95
95
  * <\/script>
96
96
  * ```
97
+ * @publicDocs
97
98
  */
98
99
  function useCartAnalytics() {
99
100
  const store = useCartStore("useCartAnalytics");
@@ -104,8 +105,22 @@ function useCartAnalytics() {
104
105
  onScopeDispose(() => stopTracking?.());
105
106
  }
106
107
  /**
107
- * Like `useCart`, but returns `undefined` when rendered outside a `<CartProvider>`.
108
- * @internal
108
+ * Returns the slice of cart state that the selector picks as a read-only shallow ref. Outside the cart provider, the ref holds `undefined`.
109
+ *
110
+ * Use the composable in a component that also renders above the provider, such as a header cart badge on an error page.
111
+ * Wherever the provider always exists, use the cart composable that throws. A missing provider then fails with an error.
112
+ *
113
+ * @example
114
+ * ```vue
115
+ * <script setup>
116
+ * const count = useOptionalCart((state) => state.data.totalQuantity);
117
+ * <\/script>
118
+ *
119
+ * <template>
120
+ * <span v-if="count !== undefined">Cart ({{ count }})</span>
121
+ * </template>
122
+ * ```
123
+ * @publicDocs
109
124
  */
110
125
  function useOptionalCart(selector, isEqual) {
111
126
  const store = useOptionalCartStore();
@@ -122,16 +137,15 @@ function useCartSelector(store, selector, isEqual) {
122
137
  return selected;
123
138
  }
124
139
  /**
125
- * Returns form props, a field register function, and reactive pending state
126
- * for building cart forms in Vue.
140
+ * Returns form props, a register function, and pending state for cart forms.
127
141
  *
128
- * Unlike the React hook, the Vue variant includes `isPending` — a reactive
129
- * object with `initial` (`ComputedRef<boolean>`) for the initial cart load
130
- * and `lines(lineId?)` for checking per-line or any-line pending state.
142
+ * The form props post to the cart endpoint and send each submission through the cart store. A `beforeSubmit` callback that prevents the event's default skips the cart submission.
131
143
  *
132
- * Note: `interactive: true` returns numeric input attributes but does **not**
133
- * auto-submit on change — that behavior requires `attachQuantityInput`, which
134
- * is only wired by the React adapter.
144
+ * The pending state holds a computed ref that's `true` during a full cart load, and a function that checks whether one line or any line has a mutation in flight.
145
+ *
146
+ * Registering the quantity field with `interactive: true` returns numeric input attributes without auto-submit. Call attachQuantityInput on the input to submit the form when the quantity changes.
147
+ *
148
+ * @returns The form props function, the register function, and the pending state.
135
149
  *
136
150
  * @example
137
151
  * ```vue
@@ -150,6 +164,7 @@ function useCartSelector(store, selector, isEqual) {
150
164
  * </form>
151
165
  * </template>
152
166
  * ```
167
+ * @publicDocs
153
168
  */
154
169
  function useCartForm() {
155
170
  const store = useCartStore("useCartForm");
@@ -177,11 +192,12 @@ function useCartForm() {
177
192
  };
178
193
  }
179
194
  /**
180
- * Factory that returns typed cart components and composables matched to your
181
- * server handler's cart query shape.
195
+ * Returns a cart provider and composables typed to the cart query in your cart server handlers.
196
+ * Pass the type of your cart server handlers as the `THandlers` type argument. Every composable's cart state then includes your custom cart fields.
197
+ *
198
+ * On mount, the provider points cart requests at `/api/cart` and connects the store. Every composable except the optional cart composable throws when you call it outside the provider.
182
199
  *
183
- * The generic `THandlers` parameter is inferred from your `createCartServerHandlers`
184
- * call, so every composable's {@link CartState} carries your custom cart fields.
200
+ * @returns The typed cart provider, the cart state composables, and the cart actions and form composables.
185
201
  *
186
202
  * @example
187
203
  * ```ts
@@ -195,6 +211,7 @@ function useCartForm() {
195
211
  * useCartForm,
196
212
  * } = createCartComponents<typeof cartServerHandlers>();
197
213
  * ```
214
+ * @publicDocs
198
215
  */
199
216
  function createCartComponents() {
200
217
  const TypedCartProvider = createTypedCartProvider();
@@ -213,5 +230,5 @@ function createCartComponents() {
213
230
  }
214
231
 
215
232
  //#endregion
216
- export { createCartComponents, getCartEndpoint, useCartActions, useCartAnalytics, useCartStore };
233
+ export { createCartComponents, getCartEndpoint, useCartAnalytics, useCartStore };
217
234
  //# sourceMappingURL=cart.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"cart.mjs","names":[],"sources":["../../src/vue/cart.ts"],"sourcesContent":["import {\n computed,\n defineComponent,\n h,\n inject,\n onMounted,\n onScopeDispose,\n onUnmounted,\n provide,\n shallowRef,\n type ComputedRef,\n type InjectionKey,\n type PropType,\n type ShallowRef,\n} from \"vue\";\n\nimport { trackCartAnalytics } from \"../core/analytics/cart-tracker\";\nimport {\n configureCartEndpoint as configureCoreCartEndpoint,\n createCartStore,\n type CreateCartStoreOptions,\n type CartActions,\n type CartStore,\n} from \"../core/cart/cart\";\nimport { createCartFormRegister, type CartFormRegister } from \"../core/cart/form\";\nimport type { CartDataFromHandlers } from \"../core/cart/server-handlers\";\nimport type { CartData, CartState } from \"../core/cart/state\";\n\nconst DEFAULT_CART_ENDPOINT = \"/api/cart\";\n\nlet cartEndpoint = DEFAULT_CART_ENDPOINT;\n\nconst CartStoreKey: InjectionKey<CartStore> = Symbol(\"CartStore\");\n\nexport function configureCartEndpoint(endpoint: string): void {\n cartEndpoint = endpoint;\n configureCoreCartEndpoint(endpoint);\n}\n\nexport function getCartEndpoint(): string {\n return cartEndpoint;\n}\n\ntype TypedUseCart<TData extends CartData> = {\n (): Readonly<ShallowRef<CartState<TData>>>;\n <S>(\n selector: (state: CartState<TData>) => S,\n isEqual?: (a: S, b: S) => boolean,\n ): Readonly<ShallowRef<S>>;\n};\n\ntype TypedUseOptionalCart<TData extends CartData> = <S>(\n selector: (state: CartState<TData>) => S,\n isEqual?: (a: S, b: S) => boolean,\n) => Readonly<ShallowRef<S | undefined>>;\n\ntype CartInitialData<TData extends CartData = CartData> =\n CreateCartStoreOptions<TData>[\"initialData\"];\n\ntype TypedCartProvider<TData extends CartData> = {\n new (): { $props: { initialData?: CartInitialData<TData> } };\n};\n\nexport type { CartActions };\n\ntype TypedCartComponents<TData extends CartData> = {\n CartProvider: TypedCartProvider<TData>;\n useCart: TypedUseCart<TData>;\n useOptionalCart: TypedUseOptionalCart<TData>;\n useCartActions: typeof useCartActions;\n useCartForm: typeof useCartForm;\n};\n\nfunction createTypedCartProvider<TData extends CartData>(): TypedCartProvider<TData> {\n const TypedCartProvider = defineComponent(\n (props: { initialData?: CartInitialData<TData> }, { slots }) => {\n return () =>\n h(\n CartProvider,\n { initialData: props.initialData as CartInitialData | undefined },\n slots.default,\n );\n },\n { name: \"CartProvider\", props: [\"initialData\"] },\n );\n\n return TypedCartProvider as unknown as TypedCartProvider<TData>;\n}\n\nexport function useCartStore(composableName = \"useCartStore\"): CartStore {\n const store = inject(CartStoreKey, null);\n if (!store) {\n throw new Error(`${composableName} must be used inside a <CartProvider>.`);\n }\n return store;\n}\n\nfunction useOptionalCartStore(): CartStore | null {\n return inject(CartStoreKey, null);\n}\n\n/**\n * Vue component that creates and manages a {@link CartStore} instance.\n *\n * Calls {@link CartStore.connect} on mount and {@link CartStore.destroy} on unmount.\n * All cart composables (`useCart`, `useCartForm`, `useCartActions`) must be\n * descendants of this component.\n *\n * @example\n * ```vue\n * <CartProvider :initialData=\"{ cart: loaderData.cart }\">\n * <App />\n * </CartProvider>\n * ```\n */\nexport const CartProvider = defineComponent({\n name: \"CartProvider\",\n props: {\n initialData: {\n type: Object as PropType<CartInitialData>,\n default: undefined,\n },\n },\n setup(props, { slots }) {\n const store = createCartStore({ initialData: props.initialData });\n provide(CartStoreKey, store);\n\n onMounted(() => {\n configureCoreCartEndpoint(cartEndpoint);\n store.connect();\n });\n\n onUnmounted(() => {\n store.destroy();\n });\n\n return () => slots.default?.();\n },\n});\n\n/**\n * Subscribes to {@link CartState} as a Vue `ShallowRef`.\n *\n * Without a selector, returns the full `CartState`. With a selector, returns\n * a `ShallowRef` of the selected slice — the ref updates only when the\n * selected value changes (by reference, or by custom `isEqual`).\n *\n * @example\n * ```vue\n * <script setup>\n * // Full state\n * const state = useCart();\n *\n * // Selected slice — re-renders only when lines change\n * const lines = useCart((s) => s.data.lines.nodes);\n *\n * // Check if a specific line is pending\n * const isPending = useCart((s) => s.pending.lines.has(lineId));\n * </script>\n * ```\n */\nexport function useCart(): Readonly<ShallowRef<CartState>>;\nexport function useCart<TData extends CartData = CartData, S = unknown>(\n selector: (state: CartState<TData>) => S,\n isEqual?: (a: S, b: S) => boolean,\n): Readonly<ShallowRef<S>>;\nexport function useCart<TData extends CartData = CartData, S = unknown>(\n selector?: (state: CartState<TData>) => S,\n isEqual?: (a: S, b: S) => boolean,\n): Readonly<ShallowRef<S | CartState>> {\n const store = useCartStore(\"useCart\");\n const resolve = selector ?? ((state: CartState<TData>) => state as unknown as S);\n return useCartSelector(store, resolve, isEqual) as Readonly<ShallowRef<S>>;\n}\n\n/**\n * Returns cart actions for reconciling state after out-of-band mutations.\n *\n * Currently exposes {@link CartStore.refresh} — call it after server-side cart\n * mutations that bypass the form system.\n *\n * @example\n * ```vue\n * <script setup>\n * const { refresh } = useCartActions();\n *\n * async function handleServerAction() {\n * await createCartOnServer();\n * refresh();\n * }\n * </script>\n * ```\n */\nexport function useCartActions(): CartActions {\n const store = useCartStore(\"useCartActions\");\n return { refresh: store.refresh };\n}\n\n/**\n * Subscribes the {@link CartStore} to the analytics event dispatcher.\n *\n * Call once near the root of your app. Starts tracking on mount via `onMounted`\n * and cleans up via `onScopeDispose`.\n *\n * @example\n * ```vue\n * <script setup>\n * useCartAnalytics();\n * </script>\n * ```\n */\nexport function useCartAnalytics(): void {\n const store = useCartStore(\"useCartAnalytics\");\n let stopTracking: (() => void) | undefined;\n\n onMounted(() => {\n stopTracking = trackCartAnalytics(store);\n });\n\n onScopeDispose(() => stopTracking?.());\n}\n\n/**\n * Like `useCart`, but returns `undefined` when rendered outside a `<CartProvider>`.\n * @internal\n */\nexport function useOptionalCart<TData extends CartData = CartData, S = unknown>(\n selector: (state: CartState<TData>) => S,\n isEqual?: (a: S, b: S) => boolean,\n): Readonly<ShallowRef<S | undefined>> {\n const store = useOptionalCartStore();\n if (!store) return shallowRef<S | undefined>(undefined);\n return useCartSelector(store, selector, isEqual);\n}\n\nfunction useCartSelector<TData extends CartData = CartData, S = unknown>(\n store: CartStore,\n selector: (state: CartState<TData>) => S,\n isEqual?: (a: S, b: S) => boolean,\n): Readonly<ShallowRef<S>> {\n const selected = shallowRef<S>(selector(store.getState() as CartState<TData>));\n\n const unsubscribe = store.subscribe(() => {\n const next = selector(store.getState() as CartState<TData>);\n if (isEqual?.(selected.value, next)) return;\n selected.value = next;\n });\n\n onScopeDispose(unsubscribe);\n\n return selected as Readonly<ShallowRef<S>>;\n}\n\n/**\n * Returns form props, a field register function, and reactive pending state\n * for building cart forms in Vue.\n *\n * Unlike the React hook, the Vue variant includes `isPending` — a reactive\n * object with `initial` (`ComputedRef<boolean>`) for the initial cart load\n * and `lines(lineId?)` for checking per-line or any-line pending state.\n *\n * Note: `interactive: true` returns numeric input attributes but does **not**\n * auto-submit on change — that behavior requires `attachQuantityInput`, which\n * is only wired by the React adapter.\n *\n * @example\n * ```vue\n * <script setup>\n * const { formProps, register, isPending } = useCartForm();\n * </script>\n *\n * <template>\n * <form v-bind=\"formProps()\">\n * <input v-bind=\"register('lineId', { value: line.id })\" />\n * <input v-bind=\"register('quantity', { value: line.quantity })\" />\n * <button v-bind=\"register('set')\" />\n * <button v-bind=\"register('increase')\">+</button>\n * <button v-bind=\"register('decrease')\">−</button>\n * <span v-if=\"isPending.lines(line.id)\">Updating…</span>\n * </form>\n * </template>\n * ```\n */\nexport function useCartForm(): {\n formProps: (opts?: {\n beforeSubmit?: (e: SubmitEvent) => void;\n afterSubmit?: (e: SubmitEvent) => void;\n }) => Record<string, unknown>;\n register: CartFormRegister;\n isPending: {\n initial: ComputedRef<boolean>;\n lines: (lineId?: string) => boolean;\n };\n} {\n const store = useCartStore(\"useCartForm\");\n const loading = useCart((s) => s.loading);\n const pendingLines = useCart((s) => s.pending.lines);\n const register = createCartFormRegister();\n\n const formProps = (opts?: {\n beforeSubmit?: (e: SubmitEvent) => void;\n afterSubmit?: (e: SubmitEvent) => void;\n }): Record<string, unknown> => ({\n onSubmit: (e: SubmitEvent) => {\n opts?.beforeSubmit?.(e);\n if (e.defaultPrevented) return;\n e.preventDefault();\n store.handleFormSubmit(e).catch(() => {});\n opts?.afterSubmit?.(e);\n },\n method: \"post\",\n action: cartEndpoint,\n });\n\n const isPending = {\n initial: computed(() => loading.value),\n lines: (lineId?: string): boolean =>\n lineId ? pendingLines.value.has(lineId) : pendingLines.value.size > 0,\n };\n\n return { formProps, register, isPending };\n}\n\n/**\n * Factory that returns typed cart components and composables matched to your\n * server handler's cart query shape.\n *\n * The generic `THandlers` parameter is inferred from your `createCartServerHandlers`\n * call, so every composable's {@link CartState} carries your custom cart fields.\n *\n * @example\n * ```ts\n * import type { cartServerHandlers } from \"./server/cart.server\";\n *\n * const {\n * CartProvider,\n * useCart,\n * useOptionalCart,\n * useCartActions,\n * useCartForm,\n * } = createCartComponents<typeof cartServerHandlers>();\n * ```\n */\nexport function createCartComponents<THandlers>(): TypedCartComponents<\n CartDataFromHandlers<THandlers>\n> {\n type TData = CartDataFromHandlers<THandlers>;\n const TypedCartProvider = createTypedCartProvider<TData>();\n\n const useTypedCart = ((\n selector?: (state: CartState<TData>) => unknown,\n isEqual?: (a: unknown, b: unknown) => boolean,\n ) => {\n if (!selector) return useCart() as Readonly<ShallowRef<CartState<TData>>>;\n return useCart<TData, unknown>(selector, isEqual);\n }) as TypedUseCart<TData>;\n\n const useTypedOptionalCart = (<S>(\n selector: (state: CartState<TData>) => S,\n isEqual?: (a: S, b: S) => boolean,\n ) => useOptionalCart<TData, S>(selector, isEqual)) as TypedUseOptionalCart<TData>;\n\n return {\n CartProvider: TypedCartProvider,\n useCart: useTypedCart,\n useOptionalCart: useTypedOptionalCart,\n useCartActions,\n useCartForm,\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"cart.mjs","names":[],"sources":["../../src/vue/cart.ts"],"sourcesContent":["import {\n computed,\n defineComponent,\n h,\n inject,\n onMounted,\n onScopeDispose,\n onUnmounted,\n provide,\n shallowRef,\n type ComputedRef,\n type InjectionKey,\n type PropType,\n type ShallowRef,\n} from \"vue\";\n\nimport { trackCartAnalytics } from \"../core/analytics/cart-tracker\";\nimport {\n configureCartEndpoint as configureCoreCartEndpoint,\n createCartStore,\n type CreateCartStoreOptions,\n type CartActions,\n type CartStore,\n} from \"../core/cart/cart\";\nimport { createCartFormRegister, type CartFormRegister } from \"../core/cart/form\";\nimport type { CartDataFromHandlers } from \"../core/cart/server-handlers\";\nimport type { CartData, CartState } from \"../core/cart/state\";\n\nconst DEFAULT_CART_ENDPOINT = \"/api/cart\";\n\nlet cartEndpoint = DEFAULT_CART_ENDPOINT;\n\nconst CartStoreKey: InjectionKey<CartStore> = Symbol(\"CartStore\");\n\nexport function configureCartEndpoint(endpoint: string): void {\n cartEndpoint = endpoint;\n configureCoreCartEndpoint(endpoint);\n}\n\nexport function getCartEndpoint(): string {\n return cartEndpoint;\n}\n\ntype TypedUseCart<TData extends CartData> = {\n (): Readonly<ShallowRef<CartState<TData>>>;\n <S>(\n selector: (state: CartState<TData>) => S,\n isEqual?: (a: S, b: S) => boolean,\n ): Readonly<ShallowRef<S>>;\n};\n\ntype TypedUseOptionalCart<TData extends CartData> = <S>(\n selector: (state: CartState<TData>) => S,\n isEqual?: (a: S, b: S) => boolean,\n) => Readonly<ShallowRef<S | undefined>>;\n\ntype CartInitialData<TData extends CartData = CartData> =\n CreateCartStoreOptions<TData>[\"initialData\"];\n\ntype TypedCartProvider<TData extends CartData> = {\n new (): { $props: { initialData?: CartInitialData<TData> } };\n};\n\nexport type { CartActions };\n\n/** Cart provider and composables whose cart state carries the custom fields from your cart server handlers. */\ntype TypedCartComponents<TData extends CartData> = {\n /** The provider that creates the cart store. The provider connects the store on mount and destroys the store on unmount. */\n CartProvider: TypedCartProvider<TData>;\n /** Returns cart state as a read-only shallow ref. The selector is optional. Without a selector, the ref holds the full cart state. */\n useCart: TypedUseCart<TData>;\n /** Returns the slice of cart state that the selector picks as a read-only shallow ref. Outside the provider, the ref holds `undefined`. */\n useOptionalCart: TypedUseOptionalCart<TData>;\n /** Returns the `refresh` action. Call `refresh` after a server-side cart mutation that bypasses cart forms. */\n useCartActions: typeof useCartActions;\n /** Returns form props, a register function, and pending state for cart forms. */\n useCartForm: typeof useCartForm;\n};\n\nfunction createTypedCartProvider<TData extends CartData>(): TypedCartProvider<TData> {\n const TypedCartProvider = defineComponent(\n (props: { initialData?: CartInitialData<TData> }, { slots }) => {\n return () =>\n h(\n CartProvider,\n { initialData: props.initialData as CartInitialData | undefined },\n slots.default,\n );\n },\n { name: \"CartProvider\", props: [\"initialData\"] },\n );\n\n return TypedCartProvider as unknown as TypedCartProvider<TData>;\n}\n\nexport function useCartStore(composableName = \"useCartStore\"): CartStore {\n const store = inject(CartStoreKey, null);\n if (!store) {\n throw new Error(`${composableName} must be used inside a <CartProvider>.`);\n }\n return store;\n}\n\nfunction useOptionalCartStore(): CartStore | null {\n return inject(CartStoreKey, null);\n}\n\n/**\n * Creates a cart store and shares the store with the cart composables below the provider.\n *\n * The provider connects the store on mount and destroys the store on unmount. Render every cart composable inside the provider. The provider creates its store once from the first initial data and ignores later changes.\n *\n * @example\n * ```vue\n * <CartProvider :initialData=\"{ cart: loaderData.cart }\">\n * <App />\n * </CartProvider>\n * ```\n * @publicDocs\n */\nexport const CartProvider = defineComponent({\n name: \"CartProvider\",\n props: {\n initialData: {\n type: Object as PropType<CartInitialData>,\n default: undefined,\n },\n },\n setup(props, { slots }) {\n const store = createCartStore({ initialData: props.initialData });\n provide(CartStoreKey, store);\n\n onMounted(() => {\n configureCoreCartEndpoint(cartEndpoint);\n store.connect();\n });\n\n onUnmounted(() => {\n store.destroy();\n });\n\n return () => slots.default?.();\n },\n});\n\n/**\n * Returns cart state as a read-only shallow ref.\n *\n * Without a selector, the ref holds the full cart state. With a selector, the ref holds the selected value. The ref updates when the selected value changes by reference, or when your `isEqual` function reports a change.\n *\n * @example\n * ```vue\n * <script setup>\n * // Full state\n * const state = useCart();\n *\n * // Selected slice — re-renders only when lines change\n * const lines = useCart((s) => s.data.lines.nodes);\n *\n * // Check if a specific line is pending\n * const isPending = useCart((s) => s.pending.lines.has(lineId));\n * </script>\n * ```\n * @publicDocs\n */\nexport function useCart(): Readonly<ShallowRef<CartState>>;\nexport function useCart<TData extends CartData = CartData, S = unknown>(\n selector: (state: CartState<TData>) => S,\n isEqual?: (a: S, b: S) => boolean,\n): Readonly<ShallowRef<S>>;\nexport function useCart<TData extends CartData = CartData, S = unknown>(\n selector?: (state: CartState<TData>) => S,\n isEqual?: (a: S, b: S) => boolean,\n): Readonly<ShallowRef<S | CartState>> {\n const store = useCartStore(\"useCart\");\n const resolve = selector ?? ((state: CartState<TData>) => state as unknown as S);\n return useCartSelector(store, resolve, isEqual) as Readonly<ShallowRef<S>>;\n}\n\n/**\n * Returns the cart action that syncs the cart after a mutation outside cart forms.\n *\n * Call `refresh` after a server-side cart mutation that bypasses cart forms, such as a server action that creates the cart.\n *\n * @returns The `refresh` action.\n *\n * @example\n * ```vue\n * <script setup>\n * const { refresh } = useCartActions();\n *\n * async function handleServerAction() {\n * await createCartOnServer();\n * refresh();\n * }\n * </script>\n * ```\n * @publicDocs\n */\nexport function useCartActions(): CartActions {\n const store = useCartStore(\"useCartActions\");\n return { refresh: store.refresh };\n}\n\n/**\n * Publishes cart analytics events when the cart changes.\n *\n * Call the composable once near the root of your app. The composable starts tracking on mount and stops when the component's scope ends. The composable throws when you call it outside the cart provider.\n *\n * @example\n * ```vue\n * <script setup>\n * useCartAnalytics();\n * </script>\n * ```\n * @publicDocs\n */\nexport function useCartAnalytics(): void {\n const store = useCartStore(\"useCartAnalytics\");\n let stopTracking: (() => void) | undefined;\n\n onMounted(() => {\n stopTracking = trackCartAnalytics(store);\n });\n\n onScopeDispose(() => stopTracking?.());\n}\n\n/**\n * Returns the slice of cart state that the selector picks as a read-only shallow ref. Outside the cart provider, the ref holds `undefined`.\n *\n * Use the composable in a component that also renders above the provider, such as a header cart badge on an error page.\n * Wherever the provider always exists, use the cart composable that throws. A missing provider then fails with an error.\n *\n * @example\n * ```vue\n * <script setup>\n * const count = useOptionalCart((state) => state.data.totalQuantity);\n * </script>\n *\n * <template>\n * <span v-if=\"count !== undefined\">Cart ({{ count }})</span>\n * </template>\n * ```\n * @publicDocs\n */\nexport function useOptionalCart<TData extends CartData = CartData, S = unknown>(\n selector: (state: CartState<TData>) => S,\n isEqual?: (a: S, b: S) => boolean,\n): Readonly<ShallowRef<S | undefined>> {\n const store = useOptionalCartStore();\n if (!store) return shallowRef<S | undefined>(undefined);\n return useCartSelector(store, selector, isEqual);\n}\n\nfunction useCartSelector<TData extends CartData = CartData, S = unknown>(\n store: CartStore,\n selector: (state: CartState<TData>) => S,\n isEqual?: (a: S, b: S) => boolean,\n): Readonly<ShallowRef<S>> {\n const selected = shallowRef<S>(selector(store.getState() as CartState<TData>));\n\n const unsubscribe = store.subscribe(() => {\n const next = selector(store.getState() as CartState<TData>);\n if (isEqual?.(selected.value, next)) return;\n selected.value = next;\n });\n\n onScopeDispose(unsubscribe);\n\n return selected as Readonly<ShallowRef<S>>;\n}\n\n/**\n * Returns form props, a register function, and pending state for cart forms.\n *\n * The form props post to the cart endpoint and send each submission through the cart store. A `beforeSubmit` callback that prevents the event's default skips the cart submission.\n *\n * The pending state holds a computed ref that's `true` during a full cart load, and a function that checks whether one line or any line has a mutation in flight.\n *\n * Registering the quantity field with `interactive: true` returns numeric input attributes without auto-submit. Call attachQuantityInput on the input to submit the form when the quantity changes.\n *\n * @returns The form props function, the register function, and the pending state.\n *\n * @example\n * ```vue\n * <script setup>\n * const { formProps, register, isPending } = useCartForm();\n * </script>\n *\n * <template>\n * <form v-bind=\"formProps()\">\n * <input v-bind=\"register('lineId', { value: line.id })\" />\n * <input v-bind=\"register('quantity', { value: line.quantity })\" />\n * <button v-bind=\"register('set')\" />\n * <button v-bind=\"register('increase')\">+</button>\n * <button v-bind=\"register('decrease')\">−</button>\n * <span v-if=\"isPending.lines(line.id)\">Updating…</span>\n * </form>\n * </template>\n * ```\n * @publicDocs\n */\nexport function useCartForm(): {\n formProps: (opts?: {\n beforeSubmit?: (e: SubmitEvent) => void;\n afterSubmit?: (e: SubmitEvent) => void;\n }) => Record<string, unknown>;\n register: CartFormRegister;\n isPending: {\n initial: ComputedRef<boolean>;\n lines: (lineId?: string) => boolean;\n };\n} {\n const store = useCartStore(\"useCartForm\");\n const loading = useCart((s) => s.loading);\n const pendingLines = useCart((s) => s.pending.lines);\n const register = createCartFormRegister();\n\n const formProps = (opts?: {\n beforeSubmit?: (e: SubmitEvent) => void;\n afterSubmit?: (e: SubmitEvent) => void;\n }): Record<string, unknown> => ({\n onSubmit: (e: SubmitEvent) => {\n opts?.beforeSubmit?.(e);\n if (e.defaultPrevented) return;\n e.preventDefault();\n store.handleFormSubmit(e).catch(() => {});\n opts?.afterSubmit?.(e);\n },\n method: \"post\",\n action: cartEndpoint,\n });\n\n const isPending = {\n initial: computed(() => loading.value),\n lines: (lineId?: string): boolean =>\n lineId ? pendingLines.value.has(lineId) : pendingLines.value.size > 0,\n };\n\n return { formProps, register, isPending };\n}\n\n/**\n * Returns a cart provider and composables typed to the cart query in your cart server handlers.\n * Pass the type of your cart server handlers as the `THandlers` type argument. Every composable's cart state then includes your custom cart fields.\n *\n * On mount, the provider points cart requests at `/api/cart` and connects the store. Every composable except the optional cart composable throws when you call it outside the provider.\n *\n * @returns The typed cart provider, the cart state composables, and the cart actions and form composables.\n *\n * @example\n * ```ts\n * import type { cartServerHandlers } from \"./server/cart.server\";\n *\n * const {\n * CartProvider,\n * useCart,\n * useOptionalCart,\n * useCartActions,\n * useCartForm,\n * } = createCartComponents<typeof cartServerHandlers>();\n * ```\n * @publicDocs\n */\nexport function createCartComponents<THandlers>(): TypedCartComponents<\n CartDataFromHandlers<THandlers>\n> {\n type TData = CartDataFromHandlers<THandlers>;\n const TypedCartProvider = createTypedCartProvider<TData>();\n\n const useTypedCart = ((\n selector?: (state: CartState<TData>) => unknown,\n isEqual?: (a: unknown, b: unknown) => boolean,\n ) => {\n if (!selector) return useCart() as Readonly<ShallowRef<CartState<TData>>>;\n return useCart<TData, unknown>(selector, isEqual);\n }) as TypedUseCart<TData>;\n\n const useTypedOptionalCart = (<S>(\n selector: (state: CartState<TData>) => S,\n isEqual?: (a: S, b: S) => boolean,\n ) => useOptionalCart<TData, S>(selector, isEqual)) as TypedUseOptionalCart<TData>;\n\n return {\n CartProvider: TypedCartProvider,\n useCart: useTypedCart,\n useOptionalCart: useTypedOptionalCart,\n useCartActions,\n useCartForm,\n };\n}\n"],"mappings":"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"}
@@ -5,9 +5,10 @@ import { PropType, ShallowRef } from "vue";
5
5
 
6
6
  //#region src/vue/collection.d.ts
7
7
  /**
8
- * Manages the lifecycle of a {@link CollectionStore}: creates on mount and syncs
9
- * with URL changes. Recreates the store when `data.handle` changes
10
- * (navigating to a different collection).
8
+ * Creates a collection store and keeps its filters and sort in sync with the URL.
9
+ * The provider creates a new store when the collection handle changes, such as on navigation to a different collection.
10
+ *
11
+ * The provider takes `data` and `url-search` props, emits a `change` event with the search string to navigate to, and renders its default slot.
11
12
  *
12
13
  * @example
13
14
  * ```vue
@@ -33,6 +34,7 @@ import { PropType, ShallowRef } from "vue";
33
34
  * </CollectionProvider>
34
35
  * </template>
35
36
  * ```
37
+ * @publicDocs
36
38
  */
37
39
  declare const CollectionProvider: _$vue.DefineComponent<_$vue.ExtractPropTypes<{
38
40
  data: {
@@ -62,8 +64,7 @@ declare const CollectionProvider: _$vue.DefineComponent<_$vue.ExtractPropTypes<{
62
64
  urlSearch: string;
63
65
  }, {}, {}, {}, string, _$vue.ComponentProvideOptions, true, {}, any>;
64
66
  /**
65
- * Subscribes to the collection store and returns a reactive ref of the full
66
- * state snapshot.
67
+ * Returns a read-only shallow ref of the collection state. The ref follows the new store when the provider replaces the store.
67
68
  *
68
69
  * @example
69
70
  * ```vue
@@ -75,12 +76,12 @@ declare const CollectionProvider: _$vue.DefineComponent<_$vue.ExtractPropTypes<{
75
76
  * <p>{{ state.status }}</p>
76
77
  * </template>
77
78
  * ```
79
+ * @publicDocs
78
80
  */
79
81
  declare function useCollection(): Readonly<ShallowRef<CollectionState>>;
80
82
  /**
81
- * Subscribes to the collection store and returns a reactive ref of a derived
82
- * value via `selector`. Optionally accepts an `isEqual` comparator to skip
83
- * updates when the derived value is structurally unchanged.
83
+ * With a selector, the composable returns a ref of the selector's value.
84
+ * Pass an `isEqual` comparator to skip updates for equal values. The composable throws outside the collection provider.
84
85
  *
85
86
  * @example
86
87
  * ```vue
@@ -88,16 +89,22 @@ declare function useCollection(): Readonly<ShallowRef<CollectionState>>;
88
89
  * const status = useCollection(s => s.status);
89
90
  * </script>
90
91
  * ```
92
+ * @publicDocs
91
93
  */
92
94
  declare function useCollection<S>(selector: (state: CollectionState) => S, isEqual?: (a: S, b: S) => boolean): Readonly<ShallowRef<S>>;
93
95
  /**
94
- * Returns methods that change filters and sort. The store's `onBrowseChange`
95
- * callback (set by {@link CollectionProvider}) handles emitting `change` with a
96
- * serialized search string.
96
+ * Returns methods that change filters and sort. After each change, the collection provider emits a `change` event with the new search string.
97
+ *
98
+ * The composable throws outside the collection provider.
99
+ *
100
+ * @publicDocs
97
101
  */
98
102
  declare function useCollectionActions(): CollectionActions;
99
103
  /**
100
- * Returns form props for progressive-enhancement of collection filter forms.
104
+ * Returns form props that progressively enhance collection filter forms.
105
+ *
106
+ * Bind the result of `formProps()` on the form. Its submit handler cancels the native submission and applies the form's filter and sort fields to the store.
107
+ * The `beforeSubmit` and `afterSubmit` callbacks receive the native submit event. The composable throws outside the collection provider.
101
108
  *
102
109
  * @example
103
110
  * ```vue
@@ -112,6 +119,7 @@ declare function useCollectionActions(): CollectionActions;
112
119
  * </form>
113
120
  * </template>
114
121
  * ```
122
+ * @publicDocs
115
123
  */
116
124
  declare function useCollectionForm(): {
117
125
  formProps: (opts?: {
@@ -5,9 +5,10 @@ import { defineComponent, inject, onUnmounted, provide, shallowRef, toValue, wat
5
5
  //#region src/vue/collection.ts
6
6
  const CollectionStoreKey = Symbol("CollectionStore");
7
7
  /**
8
- * Manages the lifecycle of a {@link CollectionStore}: creates on mount and syncs
9
- * with URL changes. Recreates the store when `data.handle` changes
10
- * (navigating to a different collection).
8
+ * Creates a collection store and keeps its filters and sort in sync with the URL.
9
+ * The provider creates a new store when the collection handle changes, such as on navigation to a different collection.
10
+ *
11
+ * The provider takes `data` and `url-search` props, emits a `change` event with the search string to navigate to, and renders its default slot.
11
12
  *
12
13
  * @example
13
14
  * ```vue
@@ -33,6 +34,7 @@ const CollectionStoreKey = Symbol("CollectionStore");
33
34
  * </CollectionProvider>
34
35
  * </template>
35
36
  * ```
37
+ * @publicDocs
36
38
  */
37
39
  const CollectionProvider = defineComponent({
38
40
  name: "CollectionProvider",
@@ -110,9 +112,11 @@ function useCollection(selector, isEqual) {
110
112
  return selected;
111
113
  }
112
114
  /**
113
- * Returns methods that change filters and sort. The store's `onBrowseChange`
114
- * callback (set by {@link CollectionProvider}) handles emitting `change` with a
115
- * serialized search string.
115
+ * Returns methods that change filters and sort. After each change, the collection provider emits a `change` event with the new search string.
116
+ *
117
+ * The composable throws outside the collection provider.
118
+ *
119
+ * @publicDocs
116
120
  */
117
121
  function useCollectionActions() {
118
122
  const storeRef = useRequiredStoreRef("useCollectionActions");
@@ -127,7 +131,10 @@ function useCollectionActions() {
127
131
  };
128
132
  }
129
133
  /**
130
- * Returns form props for progressive-enhancement of collection filter forms.
134
+ * Returns form props that progressively enhance collection filter forms.
135
+ *
136
+ * Bind the result of `formProps()` on the form. Its submit handler cancels the native submission and applies the form's filter and sort fields to the store.
137
+ * The `beforeSubmit` and `afterSubmit` callbacks receive the native submit event. The composable throws outside the collection provider.
131
138
  *
132
139
  * @example
133
140
  * ```vue
@@ -142,6 +149,7 @@ function useCollectionActions() {
142
149
  * </form>
143
150
  * </template>
144
151
  * ```
152
+ * @publicDocs
145
153
  */
146
154
  function useCollectionForm() {
147
155
  const actions = useCollectionActions();
@@ -1 +1 @@
1
- {"version":3,"file":"collection.mjs","names":[],"sources":["../../src/vue/collection.ts"],"sourcesContent":["import {\n defineComponent,\n inject,\n onUnmounted,\n provide,\n shallowRef,\n toValue,\n watch,\n type InjectionKey,\n type PropType,\n type ShallowRef,\n} from \"vue\";\n\nimport {\n createCollectionStore,\n createCollectionReconciler,\n type CollectionActions,\n type CollectionData,\n type CollectionReconciler,\n type CollectionStore,\n} from \"../core/collection\";\nimport type { CollectionState } from \"../core/collection\";\n\nexport type { CollectionActions, CollectionData };\n\nconst CollectionStoreKey: InjectionKey<ShallowRef<CollectionStore>> = Symbol(\"CollectionStore\");\n\n/**\n * Manages the lifecycle of a {@link CollectionStore}: creates on mount and syncs\n * with URL changes. Recreates the store when `data.handle` changes\n * (navigating to a different collection).\n *\n * @example\n * ```vue\n * <script setup lang=\"ts\">\n * import { CollectionProvider, type CollectionData } from '@shopify/hydrogen/vue';\n * import { useRoute, useRouter } from 'vue-router';\n *\n * const props = defineProps<{ data: CollectionData; urlSearch: string }>();\n * const route = useRoute();\n * const router = useRouter();\n *\n * // `search` includes the leading `?`, so append it to the path as-is.\n * const onChange = (search: string) => router.replace(`${route.path}${search}`);\n * </script>\n *\n * <template>\n * <CollectionProvider\n * :data=\"props.data\"\n * :url-search=\"props.urlSearch\"\n * @change=\"onChange\"\n * >\n * <slot />\n * </CollectionProvider>\n * </template>\n * ```\n */\nexport const CollectionProvider = defineComponent({\n name: \"CollectionProvider\",\n props: {\n data: {\n type: Object as PropType<CollectionData>,\n required: true,\n },\n urlSearch: {\n type: String,\n default: \"\",\n },\n },\n emits: {\n change: (searchString: string) => typeof searchString === \"string\",\n },\n setup(props, { slots, emit }) {\n const readUrlSearch = () => toValue(props.urlSearch);\n\n const initialStore = createCollectionStore({\n data: props.data,\n urlSearch: readUrlSearch(),\n });\n const storeRef = shallowRef<CollectionStore>(initialStore);\n provide(CollectionStoreKey, storeRef);\n\n let reconciler: CollectionReconciler = createCollectionReconciler(\n {\n getStore: () => storeRef.value,\n readUrlSearch,\n emitChange: (s) => emit(\"change\", s),\n },\n readUrlSearch(),\n );\n initialStore.setOnBrowseChange(() => reconciler.handleBrowseChange());\n\n function resetStore() {\n storeRef.value.setOnBrowseChange(null);\n const store = createCollectionStore({\n data: props.data,\n urlSearch: readUrlSearch(),\n });\n storeRef.value = store;\n reconciler.reset(readUrlSearch());\n store.setOnBrowseChange(() => reconciler.handleBrowseChange());\n }\n\n watch(\n () => props.data.handle,\n (newHandle, oldHandle) => {\n if (newHandle === oldHandle) return;\n resetStore();\n },\n );\n\n watch(\n () => [readUrlSearch(), props.data] as const,\n () => {\n reconciler.reconcile(readUrlSearch(), props.data.dataSearch);\n },\n { flush: \"sync\", immediate: true, deep: true },\n );\n\n onUnmounted(() => {\n storeRef.value.setOnBrowseChange(null);\n });\n\n return () => slots.default?.();\n },\n});\n\nfunction useRequiredStoreRef(composableName: string): ShallowRef<CollectionStore> {\n const storeRef = inject(CollectionStoreKey, null);\n if (!storeRef) {\n throw new Error(`${composableName} must be used inside a <CollectionProvider>.`);\n }\n return storeRef;\n}\n\n/**\n * Subscribes to the collection store and returns a reactive ref of the full\n * state snapshot.\n *\n * @example\n * ```vue\n * <script setup lang=\"ts\">\n * const state = useCollection();\n * </script>\n *\n * <template>\n * <p>{{ state.status }}</p>\n * </template>\n * ```\n */\nexport function useCollection(): Readonly<ShallowRef<CollectionState>>;\n/**\n * Subscribes to the collection store and returns a reactive ref of a derived\n * value via `selector`. Optionally accepts an `isEqual` comparator to skip\n * updates when the derived value is structurally unchanged.\n *\n * @example\n * ```vue\n * <script setup lang=\"ts\">\n * const status = useCollection(s => s.status);\n * </script>\n * ```\n */\nexport function useCollection<S>(\n selector: (state: CollectionState) => S,\n isEqual?: (a: S, b: S) => boolean,\n): Readonly<ShallowRef<S>>;\nexport function useCollection<S>(\n selector?: (state: CollectionState) => S,\n isEqual?: (a: S, b: S) => boolean,\n): Readonly<ShallowRef<CollectionState | S>> {\n const storeRef = useRequiredStoreRef(\"useCollection\");\n const resolve = selector ?? ((state: CollectionState) => state as unknown as S);\n const selected = shallowRef<CollectionState | S>(resolve(storeRef.value.getState()));\n\n watch(\n () => storeRef.value,\n (store, _, onCleanup) => {\n selected.value = resolve(store.getState());\n\n const unsubscribe = store.subscribe(() => {\n const next = resolve(store.getState());\n if (isEqual && selector) {\n if (isEqual(selected.value as S, next)) return;\n }\n selected.value = next;\n });\n\n onCleanup(unsubscribe);\n },\n { immediate: true },\n );\n\n return selected as Readonly<ShallowRef<CollectionState | S>>;\n}\n\n/**\n * Returns methods that change filters and sort. The store's `onBrowseChange`\n * callback (set by {@link CollectionProvider}) handles emitting `change` with a\n * serialized search string.\n */\nexport function useCollectionActions(): CollectionActions {\n const storeRef = useRequiredStoreRef(\"useCollectionActions\");\n\n return {\n setFilters: (...args) => storeRef.value.setFilters(...args),\n toggleFilter: (...args) => storeRef.value.toggleFilter(...args),\n toggleFilterInput: (...args) => storeRef.value.toggleFilterInput(...args),\n setSortKey: (...args) => storeRef.value.setSortKey(...args),\n setSortByValue: (...args) => storeRef.value.setSortByValue(...args),\n reset: (...args) => storeRef.value.reset(...args),\n handleFormSubmit: (...args) => storeRef.value.handleFormSubmit(...args),\n };\n}\n\n/**\n * Returns form props for progressive-enhancement of collection filter forms.\n *\n * @example\n * ```vue\n * <script setup lang=\"ts\">\n * const { formProps } = useCollectionForm();\n * </script>\n *\n * <template>\n * <form v-bind=\"formProps()\" action=\"/collections/shoes\">\n * <input type=\"checkbox\" name=\"filter.p.tag\" value=\"sale\" />\n * <button type=\"submit\">Apply</button>\n * </form>\n * </template>\n * ```\n */\nexport function useCollectionForm(): {\n formProps: (opts?: {\n beforeSubmit?: (e: SubmitEvent) => void;\n afterSubmit?: (e: SubmitEvent) => void;\n }) => Record<string, unknown>;\n} {\n const actions = useCollectionActions();\n\n const formProps = (opts?: {\n beforeSubmit?: (e: SubmitEvent) => void;\n afterSubmit?: (e: SubmitEvent) => void;\n }): Record<string, unknown> => ({\n onSubmit: (e: SubmitEvent) => {\n opts?.beforeSubmit?.(e);\n if (e.defaultPrevented) return;\n e.preventDefault();\n actions.handleFormSubmit(e);\n opts?.afterSubmit?.(e);\n },\n });\n\n return { formProps };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"collection.mjs","names":[],"sources":["../../src/vue/collection.ts"],"sourcesContent":["import {\n defineComponent,\n inject,\n onUnmounted,\n provide,\n shallowRef,\n toValue,\n watch,\n type InjectionKey,\n type PropType,\n type ShallowRef,\n} from \"vue\";\n\nimport {\n createCollectionStore,\n createCollectionReconciler,\n type CollectionActions,\n type CollectionData,\n type CollectionReconciler,\n type CollectionStore,\n} from \"../core/collection\";\nimport type { CollectionState } from \"../core/collection\";\n\nexport type { CollectionActions, CollectionData };\n\nconst CollectionStoreKey: InjectionKey<ShallowRef<CollectionStore>> = Symbol(\"CollectionStore\");\n\n/**\n * Creates a collection store and keeps its filters and sort in sync with the URL.\n * The provider creates a new store when the collection handle changes, such as on navigation to a different collection.\n *\n * The provider takes `data` and `url-search` props, emits a `change` event with the search string to navigate to, and renders its default slot.\n *\n * @example\n * ```vue\n * <script setup lang=\"ts\">\n * import { CollectionProvider, type CollectionData } from '@shopify/hydrogen/vue';\n * import { useRoute, useRouter } from 'vue-router';\n *\n * const props = defineProps<{ data: CollectionData; urlSearch: string }>();\n * const route = useRoute();\n * const router = useRouter();\n *\n * // `search` includes the leading `?`, so append it to the path as-is.\n * const onChange = (search: string) => router.replace(`${route.path}${search}`);\n * </script>\n *\n * <template>\n * <CollectionProvider\n * :data=\"props.data\"\n * :url-search=\"props.urlSearch\"\n * @change=\"onChange\"\n * >\n * <slot />\n * </CollectionProvider>\n * </template>\n * ```\n * @publicDocs\n */\nexport const CollectionProvider = defineComponent({\n name: \"CollectionProvider\",\n props: {\n data: {\n type: Object as PropType<CollectionData>,\n required: true,\n },\n urlSearch: {\n type: String,\n default: \"\",\n },\n },\n emits: {\n change: (searchString: string) => typeof searchString === \"string\",\n },\n setup(props, { slots, emit }) {\n const readUrlSearch = () => toValue(props.urlSearch);\n\n const initialStore = createCollectionStore({\n data: props.data,\n urlSearch: readUrlSearch(),\n });\n const storeRef = shallowRef<CollectionStore>(initialStore);\n provide(CollectionStoreKey, storeRef);\n\n let reconciler: CollectionReconciler = createCollectionReconciler(\n {\n getStore: () => storeRef.value,\n readUrlSearch,\n emitChange: (s) => emit(\"change\", s),\n },\n readUrlSearch(),\n );\n initialStore.setOnBrowseChange(() => reconciler.handleBrowseChange());\n\n function resetStore() {\n storeRef.value.setOnBrowseChange(null);\n const store = createCollectionStore({\n data: props.data,\n urlSearch: readUrlSearch(),\n });\n storeRef.value = store;\n reconciler.reset(readUrlSearch());\n store.setOnBrowseChange(() => reconciler.handleBrowseChange());\n }\n\n watch(\n () => props.data.handle,\n (newHandle, oldHandle) => {\n if (newHandle === oldHandle) return;\n resetStore();\n },\n );\n\n watch(\n () => [readUrlSearch(), props.data] as const,\n () => {\n reconciler.reconcile(readUrlSearch(), props.data.dataSearch);\n },\n { flush: \"sync\", immediate: true, deep: true },\n );\n\n onUnmounted(() => {\n storeRef.value.setOnBrowseChange(null);\n });\n\n return () => slots.default?.();\n },\n});\n\nfunction useRequiredStoreRef(composableName: string): ShallowRef<CollectionStore> {\n const storeRef = inject(CollectionStoreKey, null);\n if (!storeRef) {\n throw new Error(`${composableName} must be used inside a <CollectionProvider>.`);\n }\n return storeRef;\n}\n\n/**\n * Returns a read-only shallow ref of the collection state. The ref follows the new store when the provider replaces the store.\n *\n * @example\n * ```vue\n * <script setup lang=\"ts\">\n * const state = useCollection();\n * </script>\n *\n * <template>\n * <p>{{ state.status }}</p>\n * </template>\n * ```\n * @publicDocs\n */\nexport function useCollection(): Readonly<ShallowRef<CollectionState>>;\n/**\n * With a selector, the composable returns a ref of the selector's value.\n * Pass an `isEqual` comparator to skip updates for equal values. The composable throws outside the collection provider.\n *\n * @example\n * ```vue\n * <script setup lang=\"ts\">\n * const status = useCollection(s => s.status);\n * </script>\n * ```\n * @publicDocs\n */\nexport function useCollection<S>(\n selector: (state: CollectionState) => S,\n isEqual?: (a: S, b: S) => boolean,\n): Readonly<ShallowRef<S>>;\nexport function useCollection<S>(\n selector?: (state: CollectionState) => S,\n isEqual?: (a: S, b: S) => boolean,\n): Readonly<ShallowRef<CollectionState | S>> {\n const storeRef = useRequiredStoreRef(\"useCollection\");\n const resolve = selector ?? ((state: CollectionState) => state as unknown as S);\n const selected = shallowRef<CollectionState | S>(resolve(storeRef.value.getState()));\n\n watch(\n () => storeRef.value,\n (store, _, onCleanup) => {\n selected.value = resolve(store.getState());\n\n const unsubscribe = store.subscribe(() => {\n const next = resolve(store.getState());\n if (isEqual && selector) {\n if (isEqual(selected.value as S, next)) return;\n }\n selected.value = next;\n });\n\n onCleanup(unsubscribe);\n },\n { immediate: true },\n );\n\n return selected as Readonly<ShallowRef<CollectionState | S>>;\n}\n\n/**\n * Returns methods that change filters and sort. After each change, the collection provider emits a `change` event with the new search string.\n *\n * The composable throws outside the collection provider.\n *\n * @publicDocs\n */\nexport function useCollectionActions(): CollectionActions {\n const storeRef = useRequiredStoreRef(\"useCollectionActions\");\n\n return {\n setFilters: (...args) => storeRef.value.setFilters(...args),\n toggleFilter: (...args) => storeRef.value.toggleFilter(...args),\n toggleFilterInput: (...args) => storeRef.value.toggleFilterInput(...args),\n setSortKey: (...args) => storeRef.value.setSortKey(...args),\n setSortByValue: (...args) => storeRef.value.setSortByValue(...args),\n reset: (...args) => storeRef.value.reset(...args),\n handleFormSubmit: (...args) => storeRef.value.handleFormSubmit(...args),\n };\n}\n\n/**\n * Returns form props that progressively enhance collection filter forms.\n *\n * Bind the result of `formProps()` on the form. Its submit handler cancels the native submission and applies the form's filter and sort fields to the store.\n * The `beforeSubmit` and `afterSubmit` callbacks receive the native submit event. The composable throws outside the collection provider.\n *\n * @example\n * ```vue\n * <script setup lang=\"ts\">\n * const { formProps } = useCollectionForm();\n * </script>\n *\n * <template>\n * <form v-bind=\"formProps()\" action=\"/collections/shoes\">\n * <input type=\"checkbox\" name=\"filter.p.tag\" value=\"sale\" />\n * <button type=\"submit\">Apply</button>\n * </form>\n * </template>\n * ```\n * @publicDocs\n */\nexport function useCollectionForm(): {\n formProps: (opts?: {\n beforeSubmit?: (e: SubmitEvent) => void;\n afterSubmit?: (e: SubmitEvent) => void;\n }) => Record<string, unknown>;\n} {\n const actions = useCollectionActions();\n\n const formProps = (opts?: {\n beforeSubmit?: (e: SubmitEvent) => void;\n afterSubmit?: (e: SubmitEvent) => void;\n }): Record<string, unknown> => ({\n onSubmit: (e: SubmitEvent) => {\n opts?.beforeSubmit?.(e);\n if (e.defaultPrevented) return;\n e.preventDefault();\n actions.handleFormSubmit(e);\n opts?.afterSubmit?.(e);\n },\n });\n\n return { formProps };\n}\n"],"mappings":"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"}
@@ -4,10 +4,10 @@ import { CollectionActions, CollectionData } from "../core/collection/collection
4
4
  import { ValidProductSelectionResult } from "../core/product/product-form.mjs";
5
5
  import { ProductAddToCartProps, ProductFormRegister, ProductMerchandiseIdProps, ProductOptionValueProps, ProductQuantityDefaultProps, ProductQuantityProps } from "../core/product/form.mjs";
6
6
  import { PredictiveSearchActions } from "../core/predictive-search/store.mjs";
7
- import { createCartComponents, useCartActions, useCartAnalytics } from "./cart.mjs";
7
+ import { createCartComponents, useCartAnalytics } from "./cart.mjs";
8
8
  import { CollectionProvider, useCollection, useCollectionActions, useCollectionForm } from "./collection.mjs";
9
9
  import { PredictiveSearchFormPropsOptions, PredictiveSearchFormResult, PredictiveSearchProvider, PredictiveSearchQueryInputPropsOptions, usePredictiveSearch, usePredictiveSearchActions, usePredictiveSearchForm } from "./predictive-search.mjs";
10
10
  import { UseProductFormOptions, UseProductFormResult, UseProductResult, createProductComponents, useProductForm } from "./product.mjs";
11
11
  import { ShopPayButton, ShopPayButtonProps } from "./shop-pay.mjs";
12
12
  import { ShopifyScripts, ShopifyScriptsProps } from "./shopify-scripts.mjs";
13
- export { type CartActions, type CollectionActions, type CollectionData, CollectionProvider, type PredictiveSearchActions, type PredictiveSearchFormPropsOptions, type PredictiveSearchFormResult, PredictiveSearchProvider, type PredictiveSearchQueryInputPropsOptions, type ProductAddToCartProps, type ProductFormRegister, type ProductMerchandiseIdProps, type ProductOptionValueProps, type ProductQuantityDefaultProps, type ProductQuantityProps, ShopPayButton, type ShopPayButtonProps, type ShopifyGlobal, ShopifyScripts, type ShopifyScriptsProps, type UseProductFormOptions, type UseProductFormResult, type UseProductResult, type ValidProductSelectionResult, createCartComponents, createProductComponents, useCartActions, useCartAnalytics, useCollection, useCollectionActions, useCollectionForm, usePredictiveSearch, usePredictiveSearchActions, usePredictiveSearchForm, useProductForm };
13
+ export { type CartActions, type CollectionActions, type CollectionData, CollectionProvider, type PredictiveSearchActions, type PredictiveSearchFormPropsOptions, type PredictiveSearchFormResult, PredictiveSearchProvider, type PredictiveSearchQueryInputPropsOptions, type ProductAddToCartProps, type ProductFormRegister, type ProductMerchandiseIdProps, type ProductOptionValueProps, type ProductQuantityDefaultProps, type ProductQuantityProps, ShopPayButton, type ShopPayButtonProps, type ShopifyGlobal, ShopifyScripts, type ShopifyScriptsProps, type UseProductFormOptions, type UseProductFormResult, type UseProductResult, type ValidProductSelectionResult, createCartComponents, createProductComponents, useCartAnalytics, useCollection, useCollectionActions, useCollectionForm, usePredictiveSearch, usePredictiveSearchActions, usePredictiveSearchForm, useProductForm };
@@ -1,8 +1,8 @@
1
- import { createCartComponents, useCartActions, useCartAnalytics } from "./cart.mjs";
1
+ import { createCartComponents, useCartAnalytics } from "./cart.mjs";
2
2
  import { CollectionProvider, useCollection, useCollectionActions, useCollectionForm } from "./collection.mjs";
3
3
  import { PredictiveSearchProvider, usePredictiveSearch, usePredictiveSearchActions, usePredictiveSearchForm } from "./predictive-search.mjs";
4
4
  import { createProductComponents, useProductForm } from "./product.mjs";
5
5
  import { ShopPayButton } from "./shop-pay.mjs";
6
6
  import { ShopifyScripts } from "./shopify-scripts.mjs";
7
7
 
8
- export { CollectionProvider, PredictiveSearchProvider, ShopPayButton, ShopifyScripts, createCartComponents, createProductComponents, useCartActions, useCartAnalytics, useCollection, useCollectionActions, useCollectionForm, usePredictiveSearch, usePredictiveSearchActions, usePredictiveSearchForm, useProductForm };
8
+ export { CollectionProvider, PredictiveSearchProvider, ShopPayButton, ShopifyScripts, createCartComponents, createProductComponents, useCartAnalytics, useCollection, useCollectionActions, useCollectionForm, usePredictiveSearch, usePredictiveSearchActions, usePredictiveSearchForm, useProductForm };
@@ -5,28 +5,35 @@ import * as _$vue from "vue";
5
5
  import { PropType, ShallowRef } from "vue";
6
6
 
7
7
  //#region src/vue/predictive-search.d.ts
8
- /** Options for the form props builder returned by {@link usePredictiveSearchForm}. */
8
+ /**
9
+ * Options for the form props function of the predictive search form composable.
10
+ *
11
+ * Accepts any form attribute. Attributes that you pass override the default action, method, and role.
12
+ */
9
13
  type PredictiveSearchFormPropsOptions = {
10
- /** When `true`, prevents the native form submission and triggers a client-side search instead. */preventDefault?: boolean; /** Called on submit with the submit event and the extracted search term. Calling `event.preventDefault()` cancels both the native submission and Hydrogen's client-side search. */
14
+ /** Set to `true` to cancel the native submission and run a client-side search with the submitted term. */preventDefault?: boolean; /** Runs on submit with the submit event and the search term. Calling preventDefault on the event cancels the native submission and the client-side search. */
11
15
  onSubmit?: (event: SubmitEvent, term: string) => void;
12
16
  [key: string]: unknown;
13
17
  };
14
- /** Options for the query input props builder returned by {@link usePredictiveSearchForm}'s `register` method. */
18
+ /** Options for the query input attributes that the register function returns. */
15
19
  type PredictiveSearchQueryInputPropsOptions = {
16
- /** Called on input with the input event and the current input value. Call `event.preventDefault()` to skip the automatic search trigger. */onInput?: (event: Event, term: string) => void;
20
+ /** Runs on input with the input event and the input value. Calling preventDefault on the event skips the automatic search. */onInput?: (event: Event, term: string) => void;
17
21
  [key: string]: unknown;
18
22
  };
19
- /** Return type of {@link usePredictiveSearchForm}, providing methods to build a progressively-enhanced search form. */
23
+ /** Functions that build a predictive search form that works without JavaScript. */
20
24
  type PredictiveSearchFormResult = {
21
- /** Generates form element attributes including the search action and submit handler. */formProps(options?: PredictiveSearchFormPropsOptions): Record<string, unknown>; /** Generates input element attributes for a named form field and wires up the search trigger. */
25
+ /** Returns the form attributes, including the search action and a submit handler. */formProps(options?: PredictiveSearchFormPropsOptions): Record<string, unknown>; /** Returns the query input attributes, including an input handler that searches on every input event. The function accepts only the `query` field and throws for any other field name. */
22
26
  register: (field: "query", options?: PredictiveSearchQueryInputPropsOptions) => Record<string, unknown>;
23
27
  };
24
28
  /**
25
- * Creates and manages a predictive search store, providing it to descendant
26
- * composables via Vue's provide/inject.
29
+ * Creates a predictive search store and shares the store with the predictive search composables in the default slot.
30
+ *
31
+ * The provider connects the store on mount and destroys the store on unmount. A change to a store option prop replaces the store with a new one. The provider compares the types and searchable fields arrays by their values.
27
32
  *
28
- * Recreates the store when configuration props change. Connects the store
29
- * on mount and destroys it on unmount.
33
+ * The provider throws when neither the fetch prop nor a global fetch function exists.
34
+ *
35
+ * @throws {Error} When neither the fetch prop nor a global fetch function exists.
36
+ * @publicDocs
30
37
  */
31
38
  declare const PredictiveSearchProvider: _$vue.DefineComponent<_$vue.ExtractPropTypes<{
32
39
  predictiveSearchEndpoint: {
@@ -125,45 +132,33 @@ declare const PredictiveSearchProvider: _$vue.DefineComponent<_$vue.ExtractPropT
125
132
  unavailableProducts: SearchUnavailableProductsType;
126
133
  }, {}, {}, {}, string, _$vue.ComponentProvideOptions, true, {}, any>;
127
134
  /**
128
- * Subscribes to the predictive search store's state as a reactive ref.
129
- *
130
- * Without arguments, returns a `ShallowRef` of the full
131
- * {@link PredictiveSearchState}. With a `selector`, returns a ref of the
132
- * derived value that only updates when the selected value changes
133
- * (reference equality by default, or a custom `isEqual`).
135
+ * Returns the predictive search state as a read-only shallow ref that updates when the state changes.
134
136
  *
135
- * Must be used inside a {@link PredictiveSearchProvider}.
137
+ * With a selector, the ref holds the selected value and updates only when that value changes.
138
+ * The composable compares values by reference unless you pass an equality function.
136
139
  *
137
- * @throws {Error} When called outside a PredictiveSearchProvider.
140
+ * @throws {Error} When you call it outside a PredictiveSearchProvider.
141
+ * @publicDocs
138
142
  */
139
143
  declare function usePredictiveSearch<TData extends PredictiveSearchData = PredictiveSearchData>(): Readonly<ShallowRef<PredictiveSearchState<TData>>>;
140
144
  declare function usePredictiveSearch<TData extends PredictiveSearchData = PredictiveSearchData, S = PredictiveSearchState<TData>>(selector: (state: PredictiveSearchState<TData>) => S, isEqual?: (a: S, b: S) => boolean): Readonly<ShallowRef<S>>;
141
145
  /**
142
- * Returns `search` and `clear` methods that delegate to the current store.
146
+ * Returns methods that search and clear results in the provider's current store.
143
147
  *
144
- * These are thin wrappers that read from the reactive store ref on each call,
145
- * so they always target the active store even after a provider prop change
146
- * triggers store recreation.
148
+ * After a store option prop change replaces the store, the methods act on the new store.
147
149
  *
148
- * Must be used inside a {@link PredictiveSearchProvider}.
149
- *
150
- * @throws {Error} When called outside a PredictiveSearchProvider.
150
+ * @throws {Error} When you call it outside a PredictiveSearchProvider.
151
+ * @publicDocs
151
152
  */
152
153
  declare function usePredictiveSearchActions(): PredictiveSearchActions;
153
154
  /**
154
- * Returns `formProps` and `register` for building a progressively-enhanced
155
- * search form.
156
- *
157
- * `formProps()` generates form element attributes including the search
158
- * action URL. `register("query")` generates input attributes and calls the
159
- * store's search action on every `input` event. The store debounces requests
160
- * and resets state for terms shorter than `minTermLength`.
161
- * Both support an optional callback that receives the event and extracted
162
- * term, and respect `event.preventDefault()` to cancel the automatic behavior.
155
+ * Returns functions that build a predictive search form that works without JavaScript.
163
156
  *
164
- * Must be used inside a {@link PredictiveSearchProvider}.
157
+ * The form props function returns the form attributes. The register function returns the query input attributes and searches on every input event.
158
+ * Both functions accept a callback that receives the event and the search term. Calling preventDefault on the event cancels the automatic behavior.
165
159
  *
166
- * @throws {Error} When called outside a PredictiveSearchProvider.
160
+ * @throws {Error} When you call it outside a PredictiveSearchProvider.
161
+ * @publicDocs
167
162
  */
168
163
  declare function usePredictiveSearchForm(): PredictiveSearchFormResult;
169
164
  //#endregion
@@ -6,11 +6,14 @@ import { defineComponent, inject, onMounted, onUnmounted, provide, shallowRef, w
6
6
  const CONFIG_ARRAY_SEPARATOR = "\0";
7
7
  const PredictiveSearchKey = Symbol("PredictiveSearch");
8
8
  /**
9
- * Creates and manages a predictive search store, providing it to descendant
10
- * composables via Vue's provide/inject.
9
+ * Creates a predictive search store and shares the store with the predictive search composables in the default slot.
11
10
  *
12
- * Recreates the store when configuration props change. Connects the store
13
- * on mount and destroys it on unmount.
11
+ * The provider connects the store on mount and destroys the store on unmount. A change to a store option prop replaces the store with a new one. The provider compares the types and searchable fields arrays by their values.
12
+ *
13
+ * The provider throws when neither the fetch prop nor a global fetch function exists.
14
+ *
15
+ * @throws {Error} When neither the fetch prop nor a global fetch function exists.
16
+ * @publicDocs
14
17
  */
15
18
  const PredictiveSearchProvider = defineComponent({
16
19
  name: "PredictiveSearchProvider",
@@ -129,15 +132,12 @@ function usePredictiveSearch(selector, isEqual) {
129
132
  return selected;
130
133
  }
131
134
  /**
132
- * Returns `search` and `clear` methods that delegate to the current store.
135
+ * Returns methods that search and clear results in the provider's current store.
133
136
  *
134
- * These are thin wrappers that read from the reactive store ref on each call,
135
- * so they always target the active store even after a provider prop change
136
- * triggers store recreation.
137
+ * After a store option prop change replaces the store, the methods act on the new store.
137
138
  *
138
- * Must be used inside a {@link PredictiveSearchProvider}.
139
- *
140
- * @throws {Error} When called outside a PredictiveSearchProvider.
139
+ * @throws {Error} When you call it outside a PredictiveSearchProvider.
140
+ * @publicDocs
141
141
  */
142
142
  function usePredictiveSearchActions() {
143
143
  const { storeRef } = useRequiredContext("usePredictiveSearchActions");
@@ -147,19 +147,13 @@ function usePredictiveSearchActions() {
147
147
  };
148
148
  }
149
149
  /**
150
- * Returns `formProps` and `register` for building a progressively-enhanced
151
- * search form.
152
- *
153
- * `formProps()` generates form element attributes including the search
154
- * action URL. `register("query")` generates input attributes and calls the
155
- * store's search action on every `input` event. The store debounces requests
156
- * and resets state for terms shorter than `minTermLength`.
157
- * Both support an optional callback that receives the event and extracted
158
- * term, and respect `event.preventDefault()` to cancel the automatic behavior.
150
+ * Returns functions that build a predictive search form that works without JavaScript.
159
151
  *
160
- * Must be used inside a {@link PredictiveSearchProvider}.
152
+ * The form props function returns the form attributes. The register function returns the query input attributes and searches on every input event.
153
+ * Both functions accept a callback that receives the event and the search term. Calling preventDefault on the event cancels the automatic behavior.
161
154
  *
162
- * @throws {Error} When called outside a PredictiveSearchProvider.
155
+ * @throws {Error} When you call it outside a PredictiveSearchProvider.
156
+ * @publicDocs
163
157
  */
164
158
  function usePredictiveSearchForm() {
165
159
  const { storeRef, searchActionRef } = useRequiredContext("usePredictiveSearchForm");