@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.
- package/dist/cli/index.mjs +23 -12
- package/dist/client/client.d.mts +18 -15
- package/dist/client/client.mjs +8 -3
- package/dist/client/client.mjs.map +1 -1
- package/dist/client/errors.d.mts +35 -13
- package/dist/client/errors.mjs +23 -13
- package/dist/client/errors.mjs.map +1 -1
- package/dist/client/types.d.mts +140 -90
- package/dist/core/analytics/cart-tracker.d.mts +19 -10
- package/dist/core/analytics/cart-tracker.mjs +18 -10
- package/dist/core/analytics/cart-tracker.mjs.map +1 -1
- package/dist/core/analytics/events.d.mts +17 -11
- package/dist/core/analytics/events.mjs +13 -4
- package/dist/core/analytics/events.mjs.map +1 -1
- package/dist/core/analytics/types.d.mts +207 -118
- package/dist/core/analytics/utils/flatten-connection.d.mts +11 -9
- package/dist/core/analytics/utils/flatten-connection.mjs +7 -6
- package/dist/core/analytics/utils/flatten-connection.mjs.map +1 -1
- package/dist/core/cache/fetch-with-cache.d.mts +24 -4
- package/dist/core/cache/fetch-with-cache.mjs +17 -2
- package/dist/core/cache/fetch-with-cache.mjs.map +1 -1
- package/dist/core/cache/key.d.mts +2 -0
- package/dist/core/cache/key.mjs.map +1 -1
- package/dist/core/cache/run-with-cache.d.mts +56 -8
- package/dist/core/cache/run-with-cache.mjs +17 -6
- package/dist/core/cache/run-with-cache.mjs.map +1 -1
- package/dist/core/cache/store.d.mts +8 -6
- package/dist/core/cache/store.mjs.map +1 -1
- package/dist/core/cache/strategies.d.mts +27 -2
- package/dist/core/cache/strategies.mjs +6 -0
- package/dist/core/cache/strategies.mjs.map +1 -1
- package/dist/core/cart/actions.d.mts +37 -30
- package/dist/core/cart/actions.mjs +21 -9
- package/dist/core/cart/actions.mjs.map +1 -1
- package/dist/core/cart/attach-quantity-input.d.mts +8 -7
- package/dist/core/cart/attach-quantity-input.mjs +8 -7
- package/dist/core/cart/attach-quantity-input.mjs.map +1 -1
- package/dist/core/cart/buyer-identity-sync.d.mts +7 -6
- package/dist/core/cart/buyer-identity-sync.mjs.map +1 -1
- package/dist/core/cart/cart.d.mts +59 -46
- package/dist/core/cart/cart.mjs +46 -29
- package/dist/core/cart/cart.mjs.map +1 -1
- package/dist/core/cart/cookie.d.mts +8 -4
- package/dist/core/cart/cookie.mjs +8 -4
- package/dist/core/cart/cookie.mjs.map +1 -1
- package/dist/core/cart/form.d.mts +34 -20
- package/dist/core/cart/form.mjs +6 -4
- package/dist/core/cart/form.mjs.map +1 -1
- package/dist/core/cart/get-cart.d.mts +27 -15
- package/dist/core/cart/get-cart.mjs +13 -8
- package/dist/core/cart/get-cart.mjs.map +1 -1
- package/dist/core/cart/quantity.d.mts +16 -5
- package/dist/core/cart/quantity.mjs +16 -5
- package/dist/core/cart/quantity.mjs.map +1 -1
- package/dist/core/cart/queries.d.mts +25 -19
- package/dist/core/cart/queries.mjs +15 -1
- package/dist/core/cart/queries.mjs.map +1 -1
- package/dist/core/cart/server-handlers.d.mts +82 -45
- package/dist/core/cart/server-handlers.mjs +4 -0
- package/dist/core/cart/server-handlers.mjs.map +1 -1
- package/dist/core/cart/state.d.mts +110 -64
- package/dist/core/cart/state.mjs +24 -6
- package/dist/core/cart/state.mjs.map +1 -1
- package/dist/core/collection/collection.d.mts +52 -53
- package/dist/core/collection/collection.mjs +5 -3
- package/dist/core/collection/collection.mjs.map +1 -1
- package/dist/core/collection/reconciler.d.mts +23 -16
- package/dist/core/collection/reconciler.mjs +8 -4
- package/dist/core/collection/reconciler.mjs.map +1 -1
- package/dist/core/collection/state.d.mts +31 -26
- package/dist/core/collection/state.mjs +4 -3
- package/dist/core/collection/state.mjs.map +1 -1
- package/dist/core/collection/url.d.mts +70 -29
- package/dist/core/collection/url.mjs +63 -25
- package/dist/core/collection/url.mjs.map +1 -1
- package/dist/core/constants.d.mts +1 -0
- package/dist/core/constants.mjs +1 -0
- package/dist/core/constants.mjs.map +1 -1
- package/dist/core/logging/logging.d.mts +14 -8
- package/dist/core/logging/logging.mjs +15 -10
- package/dist/core/logging/logging.mjs.map +1 -1
- package/dist/core/logging/types.d.mts +28 -11
- package/dist/core/logging/types.mjs.map +1 -1
- package/dist/core/money/format.d.mts +6 -4
- package/dist/core/money/format.mjs +19 -9
- package/dist/core/money/format.mjs.map +1 -1
- package/dist/core/money/types.d.mts +41 -25
- package/dist/core/predictive-search/form.d.mts +37 -7
- package/dist/core/predictive-search/form.mjs +21 -3
- package/dist/core/predictive-search/form.mjs.map +1 -1
- package/dist/core/predictive-search/queries.d.mts +18 -30
- package/dist/core/predictive-search/queries.mjs +7 -3
- package/dist/core/predictive-search/queries.mjs.map +1 -1
- package/dist/core/predictive-search/search.d.mts +25 -27
- package/dist/core/predictive-search/search.mjs +20 -19
- package/dist/core/predictive-search/search.mjs.map +1 -1
- package/dist/core/predictive-search/server-handlers.d.mts +25 -26
- package/dist/core/predictive-search/server-handlers.mjs +4 -0
- package/dist/core/predictive-search/server-handlers.mjs.map +1 -1
- package/dist/core/predictive-search/store.d.mts +65 -24
- package/dist/core/predictive-search/store.mjs +12 -1
- package/dist/core/predictive-search/store.mjs.map +1 -1
- package/dist/core/predictive-search/url.d.mts +36 -37
- package/dist/core/predictive-search/url.mjs +14 -6
- package/dist/core/predictive-search/url.mjs.map +1 -1
- package/dist/core/product/form.d.mts +63 -16
- package/dist/core/product/form.mjs +8 -2
- package/dist/core/product/form.mjs.map +1 -1
- package/dist/core/product/options.d.mts +8 -10
- package/dist/core/product/options.mjs +8 -10
- package/dist/core/product/options.mjs.map +1 -1
- package/dist/core/product/product-form.d.mts +77 -29
- package/dist/core/product/product-form.mjs +32 -10
- package/dist/core/product/product-form.mjs.map +1 -1
- package/dist/core/product/state.d.mts +55 -32
- package/dist/core/product/url.d.mts +19 -13
- package/dist/core/product/url.mjs +10 -10
- package/dist/core/product/url.mjs.map +1 -1
- package/dist/core/request-context.d.mts +77 -19
- package/dist/core/request-context.mjs +5 -1
- package/dist/core/request-context.mjs.map +1 -1
- package/dist/core/request-routing/handle-shopify-redirects.d.mts +12 -4
- package/dist/core/request-routing/handle-shopify-redirects.mjs +9 -2
- package/dist/core/request-routing/handle-shopify-redirects.mjs.map +1 -1
- package/dist/core/request-routing/handle-shopify-routes.d.mts +5 -5
- package/dist/core/request-routing/handle-shopify-routes.mjs +7 -5
- package/dist/core/request-routing/handle-shopify-routes.mjs.map +1 -1
- package/dist/core/request-routing/interceptors/proxy.mjs +79 -43
- package/dist/core/request-routing/interceptors/proxy.mjs.map +1 -1
- package/dist/core/request-routing/interceptors/ucp-profile-proxy.mjs +69 -0
- package/dist/core/request-routing/interceptors/ucp-profile-proxy.mjs.map +1 -0
- package/dist/core/request-routing/interceptors/url-redirects.mjs +6 -1
- package/dist/core/request-routing/interceptors/url-redirects.mjs.map +1 -1
- package/dist/core/request-routing/interceptors/well-known.mjs +1 -1
- package/dist/core/request-routing/interceptors/well-known.mjs.map +1 -1
- package/dist/core/request-routing/registered-routes.d.mts +12 -0
- package/dist/core/request-routing/registered-routes.mjs +12 -0
- package/dist/core/request-routing/registered-routes.mjs.map +1 -1
- package/dist/core/request-routing/route-types.d.mts +43 -18
- package/dist/core/shop-pay/shop-pay.d.mts +71 -35
- package/dist/core/shop-pay/shop-pay.mjs +36 -10
- package/dist/core/shop-pay/shop-pay.mjs.map +1 -1
- package/dist/core/shopify-scripts/index.d.mts +15 -5
- package/dist/core/shopify-scripts/index.mjs +15 -5
- package/dist/core/shopify-scripts/index.mjs.map +1 -1
- package/dist/core/shopify-scripts/initialize.d.mts +12 -4
- package/dist/core/shopify-scripts/initialize.mjs +12 -4
- package/dist/core/shopify-scripts/initialize.mjs.map +1 -1
- package/dist/core/shopify-scripts/types.d.mts +58 -25
- package/dist/core/standard-routes/build.d.mts +11 -12
- package/dist/core/standard-routes/build.mjs +11 -12
- package/dist/core/standard-routes/build.mjs.map +1 -1
- package/dist/core/standard-routes/types.d.mts +30 -24
- package/dist/core/url.mjs +2 -1
- package/dist/core/url.mjs.map +1 -1
- package/dist/customer-account/client.d.mts +36 -69
- package/dist/customer-account/client.mjs +7 -8
- package/dist/customer-account/client.mjs.map +1 -1
- package/dist/customer-account/errors.d.mts +45 -36
- package/dist/customer-account/errors.mjs +21 -36
- package/dist/customer-account/errors.mjs.map +1 -1
- package/dist/customer-account/graphql.d.mts +11 -23
- package/dist/customer-account/graphql.mjs +3 -9
- package/dist/customer-account/graphql.mjs.map +1 -1
- package/dist/customer-account/session.d.mts +130 -100
- package/dist/customer-account/session.mjs +32 -10
- package/dist/customer-account/session.mjs.map +1 -1
- package/dist/customer-account/type-resolver.d.mts +7 -8
- package/dist/development/client/client.d.mts +18 -15
- package/dist/development/client/client.mjs +8 -3
- package/dist/development/client/client.mjs.map +1 -1
- package/dist/development/client/errors.d.mts +35 -13
- package/dist/development/client/errors.mjs +23 -13
- package/dist/development/client/errors.mjs.map +1 -1
- package/dist/development/client/types.d.mts +140 -90
- package/dist/development/core/analytics/cart-tracker.d.mts +19 -10
- package/dist/development/core/analytics/cart-tracker.mjs +18 -10
- package/dist/development/core/analytics/cart-tracker.mjs.map +1 -1
- package/dist/development/core/analytics/events.d.mts +17 -11
- package/dist/development/core/analytics/events.mjs +13 -4
- package/dist/development/core/analytics/events.mjs.map +1 -1
- package/dist/development/core/analytics/types.d.mts +207 -118
- package/dist/development/core/analytics/utils/flatten-connection.d.mts +11 -9
- package/dist/development/core/analytics/utils/flatten-connection.mjs +7 -6
- package/dist/development/core/analytics/utils/flatten-connection.mjs.map +1 -1
- package/dist/development/core/cache/fetch-with-cache.d.mts +24 -4
- package/dist/development/core/cache/fetch-with-cache.mjs +17 -2
- package/dist/development/core/cache/fetch-with-cache.mjs.map +1 -1
- package/dist/development/core/cache/key.d.mts +2 -0
- package/dist/development/core/cache/key.mjs.map +1 -1
- package/dist/development/core/cache/run-with-cache.d.mts +56 -8
- package/dist/development/core/cache/run-with-cache.mjs +17 -6
- package/dist/development/core/cache/run-with-cache.mjs.map +1 -1
- package/dist/development/core/cache/store.d.mts +8 -6
- package/dist/development/core/cache/store.mjs.map +1 -1
- package/dist/development/core/cache/strategies.d.mts +27 -2
- package/dist/development/core/cache/strategies.mjs +6 -0
- package/dist/development/core/cache/strategies.mjs.map +1 -1
- package/dist/development/core/cart/actions.d.mts +37 -30
- package/dist/development/core/cart/actions.mjs +21 -9
- package/dist/development/core/cart/actions.mjs.map +1 -1
- package/dist/development/core/cart/attach-quantity-input.d.mts +8 -7
- package/dist/development/core/cart/attach-quantity-input.mjs +8 -7
- package/dist/development/core/cart/attach-quantity-input.mjs.map +1 -1
- package/dist/development/core/cart/buyer-identity-sync.d.mts +6 -5
- package/dist/development/core/cart/buyer-identity-sync.mjs.map +1 -1
- package/dist/development/core/cart/cart.d.mts +59 -46
- package/dist/development/core/cart/cart.mjs +46 -29
- package/dist/development/core/cart/cart.mjs.map +1 -1
- package/dist/development/core/cart/cookie.d.mts +8 -4
- package/dist/development/core/cart/cookie.mjs +8 -4
- package/dist/development/core/cart/cookie.mjs.map +1 -1
- package/dist/development/core/cart/form.d.mts +34 -20
- package/dist/development/core/cart/form.mjs +6 -4
- package/dist/development/core/cart/form.mjs.map +1 -1
- package/dist/development/core/cart/get-cart.d.mts +27 -15
- package/dist/development/core/cart/get-cart.mjs +13 -8
- package/dist/development/core/cart/get-cart.mjs.map +1 -1
- package/dist/development/core/cart/quantity.d.mts +16 -5
- package/dist/development/core/cart/quantity.mjs +16 -5
- package/dist/development/core/cart/quantity.mjs.map +1 -1
- package/dist/development/core/cart/queries.d.mts +25 -19
- package/dist/development/core/cart/queries.mjs +15 -1
- package/dist/development/core/cart/queries.mjs.map +1 -1
- package/dist/development/core/cart/server-handlers.d.mts +82 -45
- package/dist/development/core/cart/server-handlers.mjs +4 -0
- package/dist/development/core/cart/server-handlers.mjs.map +1 -1
- package/dist/development/core/cart/state.d.mts +110 -64
- package/dist/development/core/cart/state.mjs +24 -6
- package/dist/development/core/cart/state.mjs.map +1 -1
- package/dist/development/core/collection/collection.d.mts +52 -53
- package/dist/development/core/collection/collection.mjs +5 -3
- package/dist/development/core/collection/collection.mjs.map +1 -1
- package/dist/development/core/collection/reconciler.d.mts +23 -16
- package/dist/development/core/collection/reconciler.mjs +8 -4
- package/dist/development/core/collection/reconciler.mjs.map +1 -1
- package/dist/development/core/collection/state.d.mts +31 -26
- package/dist/development/core/collection/state.mjs +4 -3
- package/dist/development/core/collection/state.mjs.map +1 -1
- package/dist/development/core/collection/url.d.mts +70 -29
- package/dist/development/core/collection/url.mjs +63 -25
- package/dist/development/core/collection/url.mjs.map +1 -1
- package/dist/development/core/constants.mjs.map +1 -1
- package/dist/development/core/logging/logging.d.mts +14 -8
- package/dist/development/core/logging/logging.mjs +15 -10
- package/dist/development/core/logging/logging.mjs.map +1 -1
- package/dist/development/core/logging/types.d.mts +28 -11
- package/dist/development/core/logging/types.mjs.map +1 -1
- package/dist/development/core/money/format.d.mts +6 -4
- package/dist/development/core/money/format.mjs +19 -9
- package/dist/development/core/money/format.mjs.map +1 -1
- package/dist/development/core/money/types.d.mts +41 -25
- package/dist/development/core/predictive-search/form.d.mts +37 -7
- package/dist/development/core/predictive-search/form.mjs +21 -3
- package/dist/development/core/predictive-search/form.mjs.map +1 -1
- package/dist/development/core/predictive-search/queries.d.mts +18 -30
- package/dist/development/core/predictive-search/queries.mjs +7 -3
- package/dist/development/core/predictive-search/queries.mjs.map +1 -1
- package/dist/development/core/predictive-search/search.d.mts +25 -27
- package/dist/development/core/predictive-search/search.mjs +20 -19
- package/dist/development/core/predictive-search/search.mjs.map +1 -1
- package/dist/development/core/predictive-search/server-handlers.d.mts +25 -26
- package/dist/development/core/predictive-search/server-handlers.mjs +4 -0
- package/dist/development/core/predictive-search/server-handlers.mjs.map +1 -1
- package/dist/development/core/predictive-search/store.d.mts +65 -24
- package/dist/development/core/predictive-search/store.mjs +12 -1
- package/dist/development/core/predictive-search/store.mjs.map +1 -1
- package/dist/development/core/predictive-search/url.d.mts +36 -37
- package/dist/development/core/predictive-search/url.mjs +14 -6
- package/dist/development/core/predictive-search/url.mjs.map +1 -1
- package/dist/development/core/product/form.d.mts +63 -16
- package/dist/development/core/product/form.mjs +8 -2
- package/dist/development/core/product/form.mjs.map +1 -1
- package/dist/development/core/product/options.d.mts +8 -10
- package/dist/development/core/product/options.mjs +8 -10
- package/dist/development/core/product/options.mjs.map +1 -1
- package/dist/development/core/product/product-form.d.mts +77 -29
- package/dist/development/core/product/product-form.mjs +32 -10
- package/dist/development/core/product/product-form.mjs.map +1 -1
- package/dist/development/core/product/state.d.mts +55 -32
- package/dist/development/core/product/url.d.mts +19 -13
- package/dist/development/core/product/url.mjs +10 -10
- package/dist/development/core/product/url.mjs.map +1 -1
- package/dist/development/core/request-context.d.mts +77 -19
- package/dist/development/core/request-context.mjs +5 -1
- package/dist/development/core/request-context.mjs.map +1 -1
- package/dist/development/core/request-routing/handle-shopify-redirects.d.mts +12 -4
- package/dist/development/core/request-routing/handle-shopify-redirects.mjs +9 -2
- package/dist/development/core/request-routing/handle-shopify-redirects.mjs.map +1 -1
- package/dist/development/core/request-routing/handle-shopify-routes.development.d.mts +9 -1
- package/dist/development/core/request-routing/handle-shopify-routes.development.mjs +7 -0
- package/dist/development/core/request-routing/handle-shopify-routes.development.mjs.map +1 -1
- package/dist/development/core/request-routing/handle-shopify-routes.mjs +7 -5
- package/dist/development/core/request-routing/handle-shopify-routes.mjs.map +1 -1
- package/dist/development/core/request-routing/interceptors/proxy.mjs +79 -43
- package/dist/development/core/request-routing/interceptors/proxy.mjs.map +1 -1
- package/dist/development/core/request-routing/interceptors/ucp-profile-proxy.mjs +69 -0
- package/dist/development/core/request-routing/interceptors/ucp-profile-proxy.mjs.map +1 -0
- package/dist/development/core/request-routing/interceptors/url-redirects.mjs +6 -1
- package/dist/development/core/request-routing/interceptors/url-redirects.mjs.map +1 -1
- package/dist/development/core/request-routing/interceptors/well-known.mjs +1 -1
- package/dist/development/core/request-routing/interceptors/well-known.mjs.map +1 -1
- package/dist/development/core/request-routing/registered-routes.d.mts +12 -0
- package/dist/development/core/request-routing/registered-routes.mjs +12 -0
- package/dist/development/core/request-routing/registered-routes.mjs.map +1 -1
- package/dist/development/core/request-routing/route-types.d.mts +43 -18
- package/dist/development/core/shop-pay/shop-pay.d.mts +71 -35
- package/dist/development/core/shop-pay/shop-pay.mjs +36 -10
- package/dist/development/core/shop-pay/shop-pay.mjs.map +1 -1
- package/dist/development/core/shopify-scripts/index.d.mts +15 -5
- package/dist/development/core/shopify-scripts/index.mjs +15 -5
- package/dist/development/core/shopify-scripts/index.mjs.map +1 -1
- package/dist/development/core/shopify-scripts/initialize.d.mts +12 -4
- package/dist/development/core/shopify-scripts/initialize.mjs +12 -4
- package/dist/development/core/shopify-scripts/initialize.mjs.map +1 -1
- package/dist/development/core/shopify-scripts/types.d.mts +58 -25
- package/dist/development/core/standard-routes/build.d.mts +11 -12
- package/dist/development/core/standard-routes/build.mjs +11 -12
- package/dist/development/core/standard-routes/build.mjs.map +1 -1
- package/dist/development/core/standard-routes/types.d.mts +30 -24
- package/dist/development/core/url.mjs +2 -1
- package/dist/development/core/url.mjs.map +1 -1
- package/dist/development/customer-account/session.d.mts +45 -54
- package/dist/development/customer-account/session.mjs +20 -4
- package/dist/development/customer-account/session.mjs.map +1 -1
- package/dist/development/globals.d.mts +20 -11
- package/dist/development/graphql/generated/storefront-api-types.d.mts +127 -1
- package/dist/development/graphql/graphql.d.mts +17 -16
- package/dist/development/graphql/graphql.mjs +7 -8
- package/dist/development/graphql/graphql.mjs.map +1 -1
- package/dist/development/graphql/type-resolver.d.mts +15 -8
- package/dist/development/react/cart.d.mts +78 -32
- package/dist/development/react/cart.mjs +56 -29
- package/dist/development/react/cart.mjs.map +1 -1
- package/dist/development/react/collection.d.mts +40 -22
- package/dist/development/react/collection.mjs +27 -7
- package/dist/development/react/collection.mjs.map +1 -1
- package/dist/development/react/predictive-search.d.mts +65 -50
- package/dist/development/react/predictive-search.mjs +23 -21
- package/dist/development/react/predictive-search.mjs.map +1 -1
- package/dist/development/react/product.d.mts +45 -16
- package/dist/development/react/product.mjs +13 -11
- package/dist/development/react/product.mjs.map +1 -1
- package/dist/development/react/shop-pay.d.mts +15 -0
- package/dist/development/react/shop-pay.mjs +9 -0
- package/dist/development/react/shop-pay.mjs.map +1 -1
- package/dist/development/react/shopify-scripts.d.mts +23 -2
- package/dist/development/react/shopify-scripts.mjs +9 -0
- package/dist/development/react/shopify-scripts.mjs.map +1 -1
- package/dist/development/vue/cart.d.mts +28 -23
- package/dist/development/vue/cart.mjs +42 -25
- package/dist/development/vue/cart.mjs.map +1 -1
- package/dist/development/vue/collection.d.mts +20 -12
- package/dist/development/vue/collection.mjs +15 -7
- package/dist/development/vue/collection.mjs.map +1 -1
- package/dist/development/vue/index.d.mts +2 -2
- package/dist/development/vue/index.mjs +2 -2
- package/dist/development/vue/predictive-search.d.mts +31 -36
- package/dist/development/vue/predictive-search.mjs +16 -22
- package/dist/development/vue/predictive-search.mjs.map +1 -1
- package/dist/development/vue/product.d.mts +16 -15
- package/dist/development/vue/product.mjs +11 -11
- package/dist/development/vue/product.mjs.map +1 -1
- package/dist/development/vue/shop-pay.d.mts +14 -17
- package/dist/development/vue/shop-pay.mjs +8 -0
- package/dist/development/vue/shop-pay.mjs.map +1 -1
- package/dist/development/vue/shopify-scripts.d.mts +11 -0
- package/dist/development/vue/shopify-scripts.mjs +6 -0
- package/dist/development/vue/shopify-scripts.mjs.map +1 -1
- package/dist/globals.d.mts +20 -11
- package/dist/graphql/generated/storefront-api-types.d.mts +127 -1
- package/dist/graphql/graphql.d.mts +17 -16
- package/dist/graphql/graphql.mjs +7 -8
- package/dist/graphql/graphql.mjs.map +1 -1
- package/dist/graphql/type-resolver.d.mts +15 -8
- package/dist/react/cart.d.mts +78 -32
- package/dist/react/cart.mjs +56 -29
- package/dist/react/cart.mjs.map +1 -1
- package/dist/react/collection.d.mts +40 -22
- package/dist/react/collection.mjs +27 -7
- package/dist/react/collection.mjs.map +1 -1
- package/dist/react/predictive-search.d.mts +65 -50
- package/dist/react/predictive-search.mjs +23 -21
- package/dist/react/predictive-search.mjs.map +1 -1
- package/dist/react/product.d.mts +45 -16
- package/dist/react/product.mjs +13 -11
- package/dist/react/product.mjs.map +1 -1
- package/dist/react/shop-pay.d.mts +15 -0
- package/dist/react/shop-pay.mjs +9 -0
- package/dist/react/shop-pay.mjs.map +1 -1
- package/dist/react/shopify-scripts.d.mts +23 -2
- package/dist/react/shopify-scripts.mjs +9 -0
- package/dist/react/shopify-scripts.mjs.map +1 -1
- package/dist/ts-plugin/index.cjs +6 -0
- package/dist/ts-plugin/index.cjs.map +1 -1
- package/dist/ts-plugin/index.d.cts +6 -0
- package/dist/vite/local-https.d.mts +51 -17
- package/dist/vite/local-https.mjs +26 -5
- package/dist/vite/local-https.mjs.map +1 -1
- package/dist/vue/cart.d.mts +28 -23
- package/dist/vue/cart.mjs +42 -25
- package/dist/vue/cart.mjs.map +1 -1
- package/dist/vue/collection.d.mts +20 -12
- package/dist/vue/collection.mjs +15 -7
- package/dist/vue/collection.mjs.map +1 -1
- package/dist/vue/index.d.mts +2 -2
- package/dist/vue/index.mjs +2 -2
- package/dist/vue/predictive-search.d.mts +31 -36
- package/dist/vue/predictive-search.mjs +16 -22
- package/dist/vue/predictive-search.mjs.map +1 -1
- package/dist/vue/product.d.mts +16 -15
- package/dist/vue/product.mjs +11 -11
- package/dist/vue/product.mjs.map +1 -1
- package/dist/vue/shop-pay.d.mts +14 -17
- package/dist/vue/shop-pay.mjs +8 -0
- package/dist/vue/shop-pay.mjs.map +1 -1
- package/dist/vue/shopify-scripts.d.mts +11 -0
- package/dist/vue/shopify-scripts.mjs +6 -0
- package/dist/vue/shopify-scripts.mjs.map +1 -1
- package/package.json +3 -1
- package/skills/hydrogen-analytics/SKILL.md +1 -1
- package/skills/hydrogen-cart-ui/SKILL.md +28 -2
- package/skills/hydrogen-collection-browser/SKILL.md +9 -1
- package/skills/hydrogen-collection-browser/references/nextjs.md +1 -1
- package/skills/hydrogen-collection-browser/references/nuxt.md +1 -1
- package/skills/hydrogen-collection-browser/references/react.md +151 -32
- package/skills/hydrogen-customer-account/SKILL.md +2 -0
- package/skills/hydrogen-request-handlers/SKILL.md +21 -11
- package/skills/hydrogen-setup/references/analytics.md +14 -8
- package/skills/hydrogen-setup/steps/1-inspect-app.md +2 -2
- package/skills/hydrogen-setup/steps/6-product-detail-page.md +21 -11
- package/skills/hydrogen-storefront-client/SKILL.md +1 -1
- package/skills/hydrogen-storefront-client/references/caching.md +2 -0
- package/skills/hydrogen-variant-form/SKILL.md +25 -7
- package/skills/hydrogen-variant-form/references/nextjs.md +39 -4
- package/skills/hydrogen-variant-form/references/nuxt.md +83 -42
- 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
|
-
*
|
|
29
|
+
* Creates a cart store and shares the store with the cart composables below the provider.
|
|
30
30
|
*
|
|
31
|
-
*
|
|
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
|
|
64
|
+
* Returns the cart action that syncs the cart after a mutation outside cart forms.
|
|
66
65
|
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
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
|
-
*
|
|
87
|
+
* Publishes cart analytics events when the cart changes.
|
|
87
88
|
*
|
|
88
|
-
* Call once near the root of your app.
|
|
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
|
-
*
|
|
108
|
-
*
|
|
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
|
|
126
|
-
* for building cart forms in Vue.
|
|
140
|
+
* Returns form props, a register function, and pending state for cart forms.
|
|
127
141
|
*
|
|
128
|
-
*
|
|
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
|
-
*
|
|
133
|
-
*
|
|
134
|
-
*
|
|
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
|
-
*
|
|
181
|
-
* server
|
|
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
|
|
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,
|
|
233
|
+
export { createCartComponents, getCartEndpoint, useCartAnalytics, useCartStore };
|
|
217
234
|
//# sourceMappingURL=cart.mjs.map
|
package/dist/vue/cart.mjs.map
CHANGED
|
@@ -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
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
82
|
-
*
|
|
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.
|
|
95
|
-
*
|
|
96
|
-
*
|
|
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
|
|
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?: {
|
package/dist/vue/collection.mjs
CHANGED
|
@@ -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
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
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.
|
|
114
|
-
*
|
|
115
|
-
*
|
|
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
|
|
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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"}
|
package/dist/vue/index.d.mts
CHANGED
|
@@ -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,
|
|
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,
|
|
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 };
|
package/dist/vue/index.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { createCartComponents,
|
|
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,
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
|
18
|
+
/** Options for the query input attributes that the register function returns. */
|
|
15
19
|
type PredictiveSearchQueryInputPropsOptions = {
|
|
16
|
-
/**
|
|
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
|
-
/**
|
|
23
|
+
/** Functions that build a predictive search form that works without JavaScript. */
|
|
20
24
|
type PredictiveSearchFormResult = {
|
|
21
|
-
/**
|
|
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
|
|
26
|
-
*
|
|
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
|
-
*
|
|
29
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
|
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
|
|
146
|
+
* Returns methods that search and clear results in the provider's current store.
|
|
143
147
|
*
|
|
144
|
-
*
|
|
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
|
-
*
|
|
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
|
|
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
|
-
*
|
|
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
|
|
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
|
|
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
|
-
*
|
|
13
|
-
*
|
|
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
|
|
135
|
+
* Returns methods that search and clear results in the provider's current store.
|
|
133
136
|
*
|
|
134
|
-
*
|
|
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
|
-
*
|
|
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
|
|
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
|
-
*
|
|
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
|
|
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");
|