@shopify/hydrogen 2026.4.4 → 2026.10.0-preview.1
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/README.md +73 -13
- package/bin/hydrogen.mjs +7 -0
- package/dist/cli/index.mjs +330 -0
- package/dist/client/client.d.mts +34 -0
- package/dist/client/client.mjs +193 -0
- package/dist/client/client.mjs.map +1 -0
- package/dist/client/errors.d.mts +48 -0
- package/dist/client/errors.mjs +52 -0
- package/dist/client/errors.mjs.map +1 -0
- package/dist/client/index.d.mts +4 -0
- package/dist/client/types.d.mts +147 -0
- package/dist/core/analytics/cart-tracker.d.mts +8 -0
- package/dist/core/analytics/cart-tracker.mjs +144 -0
- package/dist/core/analytics/cart-tracker.mjs.map +1 -0
- package/dist/core/analytics/events.d.mts +15 -0
- package/dist/core/analytics/events.mjs +15 -0
- package/dist/core/analytics/events.mjs.map +1 -0
- package/dist/core/analytics/index.d.mts +3 -0
- package/dist/core/analytics/types.d.mts +143 -0
- package/dist/core/analytics/utils/flatten-connection.d.mts +19 -0
- package/dist/core/analytics/utils/flatten-connection.mjs +25 -0
- package/dist/core/analytics/utils/flatten-connection.mjs.map +1 -0
- package/dist/core/cache/cache-status.mjs +17 -0
- package/dist/core/cache/cache-status.mjs.map +1 -0
- package/dist/core/cache/fetch-with-cache.d.mts +43 -0
- package/dist/core/cache/fetch-with-cache.mjs +188 -0
- package/dist/core/cache/fetch-with-cache.mjs.map +1 -0
- package/dist/core/cache/key.d.mts +6 -0
- package/dist/core/cache/key.mjs +27 -0
- package/dist/core/cache/key.mjs.map +1 -0
- package/dist/core/cache/run-with-cache.d.mts +36 -0
- package/dist/core/cache/run-with-cache.mjs +114 -0
- package/dist/core/cache/run-with-cache.mjs.map +1 -0
- package/dist/core/cache/store.d.mts +19 -0
- package/dist/core/cache/store.mjs +62 -0
- package/dist/core/cache/store.mjs.map +1 -0
- package/dist/core/cache/strategies.d.mts +39 -0
- package/dist/core/cache/strategies.mjs +70 -0
- package/dist/core/cache/strategies.mjs.map +1 -0
- package/dist/core/cart/actions.d.mts +50 -0
- package/dist/core/cart/actions.mjs +240 -0
- package/dist/core/cart/actions.mjs.map +1 -0
- package/dist/core/cart/attach-quantity-input.d.mts +5 -0
- package/dist/core/cart/attach-quantity-input.mjs +17 -0
- package/dist/core/cart/attach-quantity-input.mjs.map +1 -0
- package/dist/core/cart/buyer-identity-sync.d.mts +23 -0
- package/dist/core/cart/buyer-identity-sync.mjs +9 -0
- package/dist/core/cart/buyer-identity-sync.mjs.map +1 -0
- package/dist/core/cart/cart.d.mts +32 -0
- package/dist/core/cart/cart.mjs +1687 -0
- package/dist/core/cart/cart.mjs.map +1 -0
- package/dist/core/cart/cookie.d.mts +5 -0
- package/dist/core/cart/cookie.mjs +28 -0
- package/dist/core/cart/cookie.mjs.map +1 -0
- package/dist/core/cart/form.d.mts +130 -0
- package/dist/core/cart/form.mjs +75 -0
- package/dist/core/cart/form.mjs.map +1 -0
- package/dist/core/cart/get-cart.d.mts +25 -0
- package/dist/core/cart/get-cart.mjs +32 -0
- package/dist/core/cart/get-cart.mjs.map +1 -0
- package/dist/core/cart/index.d.mts +10 -0
- package/dist/core/cart/quantity.d.mts +10 -0
- package/dist/core/cart/quantity.mjs +14 -0
- package/dist/core/cart/quantity.mjs.map +1 -0
- package/dist/core/cart/queries.d.mts +4296 -0
- package/dist/core/cart/queries.mjs +70 -0
- package/dist/core/cart/queries.mjs.map +1 -0
- package/dist/core/cart/server-handlers.d.mts +82 -0
- package/dist/core/cart/server-handlers.mjs +322 -0
- package/dist/core/cart/server-handlers.mjs.map +1 -0
- package/dist/core/cart/state.d.mts +137 -0
- package/dist/core/cart/state.mjs +76 -0
- package/dist/core/cart/state.mjs.map +1 -0
- package/dist/core/cart/sync-quantity-inputs.mjs +16 -0
- package/dist/core/cart/sync-quantity-inputs.mjs.map +1 -0
- package/dist/core/collection/collection.d.mts +134 -0
- package/dist/core/collection/collection.mjs +170 -0
- package/dist/core/collection/collection.mjs.map +1 -0
- package/dist/core/collection/index.d.mts +6 -0
- package/dist/core/collection/reconciler.d.mts +32 -0
- package/dist/core/collection/reconciler.mjs +89 -0
- package/dist/core/collection/reconciler.mjs.map +1 -0
- package/dist/core/collection/state.d.mts +66 -0
- package/dist/core/collection/state.mjs +20 -0
- package/dist/core/collection/state.mjs.map +1 -0
- package/dist/core/collection/url.d.mts +70 -0
- package/dist/core/collection/url.mjs +367 -0
- package/dist/core/collection/url.mjs.map +1 -0
- package/dist/core/constants.d.mts +5 -0
- package/dist/core/constants.mjs +8 -0
- package/dist/core/constants.mjs.map +1 -0
- package/dist/core/headers.mjs +44 -0
- package/dist/core/headers.mjs.map +1 -0
- package/dist/core/index.d.mts +55 -0
- package/dist/core/index.mjs +44 -0
- package/dist/core/logging/logging.d.mts +21 -0
- package/dist/core/logging/logging.mjs +99 -0
- package/dist/core/logging/logging.mjs.map +1 -0
- package/dist/core/logging/types.d.mts +40 -0
- package/dist/core/logging/types.mjs +18 -0
- package/dist/core/logging/types.mjs.map +1 -0
- package/dist/core/money/cache.mjs +25 -0
- package/dist/core/money/cache.mjs.map +1 -0
- package/dist/core/money/format.d.mts +15 -0
- package/dist/core/money/format.mjs +243 -0
- package/dist/core/money/format.mjs.map +1 -0
- package/dist/core/money/types.d.mts +47 -0
- package/dist/core/observable.mjs +46 -0
- package/dist/core/observable.mjs.map +1 -0
- package/dist/core/predictive-search/constants.d.mts +5 -0
- package/dist/core/predictive-search/constants.mjs +6 -0
- package/dist/core/predictive-search/constants.mjs.map +1 -0
- package/dist/core/predictive-search/form.d.mts +31 -0
- package/dist/core/predictive-search/form.mjs +31 -0
- package/dist/core/predictive-search/form.mjs.map +1 -0
- package/dist/core/predictive-search/index.d.mts +6 -0
- package/dist/core/predictive-search/queries.d.mts +118 -0
- package/dist/core/predictive-search/queries.mjs +81 -0
- package/dist/core/predictive-search/queries.mjs.map +1 -0
- package/dist/core/predictive-search/search.d.mts +32 -0
- package/dist/core/predictive-search/search.mjs +74 -0
- package/dist/core/predictive-search/search.mjs.map +1 -0
- package/dist/core/predictive-search/server-handlers.d.mts +36 -0
- package/dist/core/predictive-search/server-handlers.mjs +113 -0
- package/dist/core/predictive-search/server-handlers.mjs.map +1 -0
- package/dist/core/predictive-search/store.d.mts +44 -0
- package/dist/core/predictive-search/store.mjs +224 -0
- package/dist/core/predictive-search/store.mjs.map +1 -0
- package/dist/core/predictive-search/url.d.mts +41 -0
- package/dist/core/predictive-search/url.mjs +71 -0
- package/dist/core/predictive-search/url.mjs.map +1 -0
- package/dist/core/product/form.d.mts +63 -0
- package/dist/core/product/form.mjs +44 -0
- package/dist/core/product/form.mjs.map +1 -0
- package/dist/core/product/index.d.mts +4 -0
- package/dist/core/product/options.d.mts +40 -0
- package/dist/core/product/options.mjs +291 -0
- package/dist/core/product/options.mjs.map +1 -0
- package/dist/core/product/product-form.d.mts +72 -0
- package/dist/core/product/product-form.mjs +158 -0
- package/dist/core/product/product-form.mjs.map +1 -0
- package/dist/core/product/state.d.mts +68 -0
- package/dist/core/request-context.d.mts +70 -0
- package/dist/core/request-context.mjs +120 -0
- package/dist/core/request-context.mjs.map +1 -0
- package/dist/core/request-routing/handle-shopify-redirects.d.mts +17 -0
- package/dist/core/request-routing/handle-shopify-redirects.mjs +31 -0
- package/dist/core/request-routing/handle-shopify-redirects.mjs.map +1 -0
- package/dist/core/request-routing/handle-shopify-routes.d.mts +14 -0
- package/dist/core/request-routing/handle-shopify-routes.mjs +42 -0
- package/dist/core/request-routing/handle-shopify-routes.mjs.map +1 -0
- package/dist/core/request-routing/interceptors/admin-redirect.mjs +12 -0
- package/dist/core/request-routing/interceptors/admin-redirect.mjs.map +1 -0
- package/dist/core/request-routing/interceptors/agent-proxy.mjs +19 -0
- package/dist/core/request-routing/interceptors/agent-proxy.mjs.map +1 -0
- package/dist/core/request-routing/interceptors/ajax-api.mjs +16 -0
- package/dist/core/request-routing/interceptors/ajax-api.mjs.map +1 -0
- package/dist/core/request-routing/interceptors/api-proxy.mjs +20 -0
- package/dist/core/request-routing/interceptors/api-proxy.mjs.map +1 -0
- package/dist/core/request-routing/interceptors/checkout.mjs +58 -0
- package/dist/core/request-routing/interceptors/checkout.mjs.map +1 -0
- package/dist/core/request-routing/interceptors/mcp-proxy.mjs +23 -0
- package/dist/core/request-routing/interceptors/mcp-proxy.mjs.map +1 -0
- package/dist/core/request-routing/interceptors/proxy.mjs +68 -0
- package/dist/core/request-routing/interceptors/proxy.mjs.map +1 -0
- package/dist/core/request-routing/interceptors/query-param-redirect.mjs +22 -0
- package/dist/core/request-routing/interceptors/query-param-redirect.mjs.map +1 -0
- package/dist/core/request-routing/interceptors/sfapi-proxy.mjs +27 -0
- package/dist/core/request-routing/interceptors/sfapi-proxy.mjs.map +1 -0
- package/dist/core/request-routing/interceptors/standard-routes.mjs +19 -0
- package/dist/core/request-routing/interceptors/standard-routes.mjs.map +1 -0
- package/dist/core/request-routing/interceptors/url-redirects.mjs +27 -0
- package/dist/core/request-routing/interceptors/url-redirects.mjs.map +1 -0
- package/dist/core/request-routing/interceptors/well-known.mjs +19 -0
- package/dist/core/request-routing/interceptors/well-known.mjs.map +1 -0
- package/dist/core/request-routing/registered-routes.d.mts +7 -0
- package/dist/core/request-routing/registered-routes.mjs +59 -0
- package/dist/core/request-routing/registered-routes.mjs.map +1 -0
- package/dist/core/request-routing/route-types.d.mts +51 -0
- package/dist/core/request-routing/safe-apply-response-headers.mjs +16 -0
- package/dist/core/request-routing/safe-apply-response-headers.mjs.map +1 -0
- package/dist/core/shop-pay/shop-pay.d.mts +102 -0
- package/dist/core/shop-pay/shop-pay.mjs +289 -0
- package/dist/core/shop-pay/shop-pay.mjs.map +1 -0
- package/dist/core/shopify-scripts/analytics.mjs +26 -0
- package/dist/core/shopify-scripts/analytics.mjs.map +1 -0
- package/dist/core/shopify-scripts/consent.mjs +17 -0
- package/dist/core/shopify-scripts/consent.mjs.map +1 -0
- package/dist/core/shopify-scripts/constants.mjs +19 -0
- package/dist/core/shopify-scripts/constants.mjs.map +1 -0
- package/dist/core/shopify-scripts/deprecated-cookies.mjs +97 -0
- package/dist/core/shopify-scripts/deprecated-cookies.mjs.map +1 -0
- package/dist/core/shopify-scripts/global.d.mts +1 -0
- package/dist/core/shopify-scripts/global.mjs +86 -0
- package/dist/core/shopify-scripts/global.mjs.map +1 -0
- package/dist/core/shopify-scripts/index.d.mts +27 -0
- package/dist/core/shopify-scripts/index.mjs +135 -0
- package/dist/core/shopify-scripts/index.mjs.map +1 -0
- package/dist/core/shopify-scripts/initialize.d.mts +18 -0
- package/dist/core/shopify-scripts/initialize.mjs +27 -0
- package/dist/core/shopify-scripts/initialize.mjs.map +1 -0
- package/dist/core/shopify-scripts/page-view.mjs +49 -0
- package/dist/core/shopify-scripts/page-view.mjs.map +1 -0
- package/dist/core/shopify-scripts/perfkit.mjs +33 -0
- package/dist/core/shopify-scripts/perfkit.mjs.map +1 -0
- package/dist/core/shopify-scripts/render.d.mts +1 -0
- package/dist/core/shopify-scripts/render.mjs +23 -0
- package/dist/core/shopify-scripts/render.mjs.map +1 -0
- package/dist/core/shopify-scripts/types.d.mts +76 -0
- package/dist/core/shopify-scripts/utils/cookie-domain.mjs +43 -0
- package/dist/core/shopify-scripts/utils/cookie-domain.mjs.map +1 -0
- package/dist/core/shopify-scripts/utils/inline-script.mjs +8 -0
- package/dist/core/shopify-scripts/utils/inline-script.mjs.map +1 -0
- package/dist/core/shopify-scripts/utils/navigation.mjs +46 -0
- package/dist/core/shopify-scripts/utils/navigation.mjs.map +1 -0
- package/dist/core/shopify-scripts/utils/tracking-values.mjs +65 -0
- package/dist/core/shopify-scripts/utils/tracking-values.mjs.map +1 -0
- package/dist/core/shopify-scripts/utils/uuid.mjs +17 -0
- package/dist/core/shopify-scripts/utils/uuid.mjs.map +1 -0
- package/dist/core/shopify-scripts/webmcp.mjs +22 -0
- package/dist/core/shopify-scripts/webmcp.mjs.map +1 -0
- package/dist/core/standard-routes/build.d.mts +34 -0
- package/dist/core/standard-routes/build.mjs +54 -0
- package/dist/core/standard-routes/build.mjs.map +1 -0
- package/dist/core/standard-routes/defaults.mjs +31 -0
- package/dist/core/standard-routes/defaults.mjs.map +1 -0
- package/dist/core/standard-routes/match.mjs +108 -0
- package/dist/core/standard-routes/match.mjs.map +1 -0
- package/dist/core/standard-routes/path.mjs +58 -0
- package/dist/core/standard-routes/path.mjs.map +1 -0
- package/dist/core/standard-routes/redirects.mjs +51 -0
- package/dist/core/standard-routes/redirects.mjs.map +1 -0
- package/dist/core/standard-routes/types.d.mts +95 -0
- package/dist/core/url.mjs +35 -0
- package/dist/core/url.mjs.map +1 -0
- package/dist/core/utils/load-script.mjs +34 -0
- package/dist/core/utils/load-script.mjs.map +1 -0
- package/dist/core/utils/parse-gid.mjs +33 -0
- package/dist/core/utils/parse-gid.mjs.map +1 -0
- package/dist/core/utils/record.mjs +8 -0
- package/dist/core/utils/record.mjs.map +1 -0
- package/dist/customer-account/client.d.mts +50 -0
- package/dist/customer-account/client.mjs +239 -0
- package/dist/customer-account/client.mjs.map +1 -0
- package/dist/customer-account/errors.d.mts +28 -0
- package/dist/customer-account/errors.mjs +39 -0
- package/dist/customer-account/errors.mjs.map +1 -0
- package/dist/customer-account/graphql.d.mts +29 -0
- package/dist/customer-account/graphql.mjs +39 -0
- package/dist/customer-account/graphql.mjs.map +1 -0
- package/dist/customer-account/index.d.mts +7 -0
- package/dist/customer-account/index.mjs +7 -0
- package/dist/customer-account/session.d.mts +117 -0
- package/dist/customer-account/session.mjs +733 -0
- package/dist/customer-account/session.mjs.map +1 -0
- package/dist/customer-account/type-resolver.d.mts +11 -0
- package/dist/customer-account-api-types.d.ts +3269 -3270
- package/dist/customer-account.schema.json +50753 -1
- package/dist/development/_virtual/_@oxc-project_runtime@0.127.0/helpers/taggedTemplateLiteral.mjs +7 -0
- package/dist/development/client/client.d.mts +34 -0
- package/dist/development/client/client.mjs +193 -0
- package/dist/development/client/client.mjs.map +1 -0
- package/dist/development/client/errors.d.mts +48 -0
- package/dist/development/client/errors.mjs +57 -0
- package/dist/development/client/errors.mjs.map +1 -0
- package/dist/development/client/index.d.mts +4 -0
- package/dist/development/client/types.d.mts +147 -0
- package/dist/development/core/analytics/cart-tracker.d.mts +8 -0
- package/dist/development/core/analytics/cart-tracker.mjs +144 -0
- package/dist/development/core/analytics/cart-tracker.mjs.map +1 -0
- package/dist/development/core/analytics/events.d.mts +15 -0
- package/dist/development/core/analytics/events.mjs +15 -0
- package/dist/development/core/analytics/events.mjs.map +1 -0
- package/dist/development/core/analytics/index.d.mts +3 -0
- package/dist/development/core/analytics/types.d.mts +143 -0
- package/dist/development/core/analytics/utils/flatten-connection.d.mts +19 -0
- package/dist/development/core/analytics/utils/flatten-connection.mjs +25 -0
- package/dist/development/core/analytics/utils/flatten-connection.mjs.map +1 -0
- package/dist/development/core/cache/cache-status.mjs +17 -0
- package/dist/development/core/cache/cache-status.mjs.map +1 -0
- package/dist/development/core/cache/fetch-with-cache.d.mts +43 -0
- package/dist/development/core/cache/fetch-with-cache.mjs +188 -0
- package/dist/development/core/cache/fetch-with-cache.mjs.map +1 -0
- package/dist/development/core/cache/key.d.mts +6 -0
- package/dist/development/core/cache/key.mjs +27 -0
- package/dist/development/core/cache/key.mjs.map +1 -0
- package/dist/development/core/cache/run-with-cache.d.mts +36 -0
- package/dist/development/core/cache/run-with-cache.mjs +114 -0
- package/dist/development/core/cache/run-with-cache.mjs.map +1 -0
- package/dist/development/core/cache/store.d.mts +19 -0
- package/dist/development/core/cache/store.mjs +62 -0
- package/dist/development/core/cache/store.mjs.map +1 -0
- package/dist/development/core/cache/strategies.d.mts +39 -0
- package/dist/development/core/cache/strategies.mjs +70 -0
- package/dist/development/core/cache/strategies.mjs.map +1 -0
- package/dist/development/core/cart/actions.d.mts +50 -0
- package/dist/development/core/cart/actions.mjs +240 -0
- package/dist/development/core/cart/actions.mjs.map +1 -0
- package/dist/development/core/cart/attach-quantity-input.d.mts +5 -0
- package/dist/development/core/cart/attach-quantity-input.mjs +17 -0
- package/dist/development/core/cart/attach-quantity-input.mjs.map +1 -0
- package/dist/development/core/cart/buyer-identity-sync.d.mts +19 -0
- package/dist/development/core/cart/buyer-identity-sync.mjs +6 -0
- package/dist/development/core/cart/buyer-identity-sync.mjs.map +1 -0
- package/dist/development/core/cart/cart.d.mts +32 -0
- package/dist/development/core/cart/cart.mjs +1687 -0
- package/dist/development/core/cart/cart.mjs.map +1 -0
- package/dist/development/core/cart/cookie.d.mts +5 -0
- package/dist/development/core/cart/cookie.mjs +28 -0
- package/dist/development/core/cart/cookie.mjs.map +1 -0
- package/dist/development/core/cart/form.d.mts +130 -0
- package/dist/development/core/cart/form.mjs +75 -0
- package/dist/development/core/cart/form.mjs.map +1 -0
- package/dist/development/core/cart/get-cart.d.mts +25 -0
- package/dist/development/core/cart/get-cart.mjs +32 -0
- package/dist/development/core/cart/get-cart.mjs.map +1 -0
- package/dist/development/core/cart/index.d.mts +10 -0
- package/dist/development/core/cart/quantity.d.mts +10 -0
- package/dist/development/core/cart/quantity.mjs +14 -0
- package/dist/development/core/cart/quantity.mjs.map +1 -0
- package/dist/development/core/cart/queries.d.mts +4296 -0
- package/dist/development/core/cart/queries.mjs +70 -0
- package/dist/development/core/cart/queries.mjs.map +1 -0
- package/dist/development/core/cart/server-handlers.d.mts +82 -0
- package/dist/development/core/cart/server-handlers.mjs +322 -0
- package/dist/development/core/cart/server-handlers.mjs.map +1 -0
- package/dist/development/core/cart/state.d.mts +137 -0
- package/dist/development/core/cart/state.mjs +76 -0
- package/dist/development/core/cart/state.mjs.map +1 -0
- package/dist/development/core/cart/sync-quantity-inputs.mjs +16 -0
- package/dist/development/core/cart/sync-quantity-inputs.mjs.map +1 -0
- package/dist/development/core/collection/collection.d.mts +134 -0
- package/dist/development/core/collection/collection.mjs +170 -0
- package/dist/development/core/collection/collection.mjs.map +1 -0
- package/dist/development/core/collection/index.d.mts +6 -0
- package/dist/development/core/collection/reconciler.d.mts +32 -0
- package/dist/development/core/collection/reconciler.mjs +89 -0
- package/dist/development/core/collection/reconciler.mjs.map +1 -0
- package/dist/development/core/collection/state.d.mts +66 -0
- package/dist/development/core/collection/state.mjs +20 -0
- package/dist/development/core/collection/state.mjs.map +1 -0
- package/dist/development/core/collection/url.d.mts +70 -0
- package/dist/development/core/collection/url.mjs +367 -0
- package/dist/development/core/collection/url.mjs.map +1 -0
- package/dist/development/core/constants.mjs +7 -0
- package/dist/development/core/constants.mjs.map +1 -0
- package/dist/development/core/development.d.mts +55 -0
- package/dist/development/core/development.mjs +44 -0
- package/dist/development/core/headers.mjs +44 -0
- package/dist/development/core/headers.mjs.map +1 -0
- package/dist/development/core/index.d.mts +53 -0
- package/dist/development/core/logging/logging.d.mts +21 -0
- package/dist/development/core/logging/logging.mjs +99 -0
- package/dist/development/core/logging/logging.mjs.map +1 -0
- package/dist/development/core/logging/types.d.mts +40 -0
- package/dist/development/core/logging/types.mjs +18 -0
- package/dist/development/core/logging/types.mjs.map +1 -0
- package/dist/development/core/money/cache.mjs +25 -0
- package/dist/development/core/money/cache.mjs.map +1 -0
- package/dist/development/core/money/format.d.mts +15 -0
- package/dist/development/core/money/format.mjs +243 -0
- package/dist/development/core/money/format.mjs.map +1 -0
- package/dist/development/core/money/types.d.mts +47 -0
- package/dist/development/core/observable.mjs +46 -0
- package/dist/development/core/observable.mjs.map +1 -0
- package/dist/development/core/predictive-search/constants.d.mts +5 -0
- package/dist/development/core/predictive-search/constants.mjs +6 -0
- package/dist/development/core/predictive-search/constants.mjs.map +1 -0
- package/dist/development/core/predictive-search/form.d.mts +31 -0
- package/dist/development/core/predictive-search/form.mjs +31 -0
- package/dist/development/core/predictive-search/form.mjs.map +1 -0
- package/dist/development/core/predictive-search/index.d.mts +6 -0
- package/dist/development/core/predictive-search/queries.d.mts +118 -0
- package/dist/development/core/predictive-search/queries.mjs +81 -0
- package/dist/development/core/predictive-search/queries.mjs.map +1 -0
- package/dist/development/core/predictive-search/search.d.mts +32 -0
- package/dist/development/core/predictive-search/search.mjs +74 -0
- package/dist/development/core/predictive-search/search.mjs.map +1 -0
- package/dist/development/core/predictive-search/server-handlers.d.mts +36 -0
- package/dist/development/core/predictive-search/server-handlers.mjs +113 -0
- package/dist/development/core/predictive-search/server-handlers.mjs.map +1 -0
- package/dist/development/core/predictive-search/store.d.mts +44 -0
- package/dist/development/core/predictive-search/store.mjs +224 -0
- package/dist/development/core/predictive-search/store.mjs.map +1 -0
- package/dist/development/core/predictive-search/url.d.mts +41 -0
- package/dist/development/core/predictive-search/url.mjs +71 -0
- package/dist/development/core/predictive-search/url.mjs.map +1 -0
- package/dist/development/core/product/form.d.mts +63 -0
- package/dist/development/core/product/form.mjs +44 -0
- package/dist/development/core/product/form.mjs.map +1 -0
- package/dist/development/core/product/index.d.mts +4 -0
- package/dist/development/core/product/options.d.mts +40 -0
- package/dist/development/core/product/options.mjs +291 -0
- package/dist/development/core/product/options.mjs.map +1 -0
- package/dist/development/core/product/product-form.d.mts +72 -0
- package/dist/development/core/product/product-form.mjs +158 -0
- package/dist/development/core/product/product-form.mjs.map +1 -0
- package/dist/development/core/product/state.d.mts +68 -0
- package/dist/development/core/request-context.d.mts +70 -0
- package/dist/development/core/request-context.mjs +120 -0
- package/dist/development/core/request-context.mjs.map +1 -0
- package/dist/development/core/request-routing/handle-shopify-redirects.d.mts +17 -0
- package/dist/development/core/request-routing/handle-shopify-redirects.mjs +31 -0
- package/dist/development/core/request-routing/handle-shopify-redirects.mjs.map +1 -0
- package/dist/development/core/request-routing/handle-shopify-routes.d.mts +1 -0
- package/dist/development/core/request-routing/handle-shopify-routes.development.d.mts +11 -0
- package/dist/development/core/request-routing/handle-shopify-routes.development.mjs +16 -0
- package/dist/development/core/request-routing/handle-shopify-routes.development.mjs.map +1 -0
- package/dist/development/core/request-routing/handle-shopify-routes.mjs +42 -0
- package/dist/development/core/request-routing/handle-shopify-routes.mjs.map +1 -0
- package/dist/development/core/request-routing/interceptors/admin-redirect.mjs +12 -0
- package/dist/development/core/request-routing/interceptors/admin-redirect.mjs.map +1 -0
- package/dist/development/core/request-routing/interceptors/agent-proxy.mjs +19 -0
- package/dist/development/core/request-routing/interceptors/agent-proxy.mjs.map +1 -0
- package/dist/development/core/request-routing/interceptors/ajax-api.mjs +16 -0
- package/dist/development/core/request-routing/interceptors/ajax-api.mjs.map +1 -0
- package/dist/development/core/request-routing/interceptors/api-proxy.mjs +20 -0
- package/dist/development/core/request-routing/interceptors/api-proxy.mjs.map +1 -0
- package/dist/development/core/request-routing/interceptors/checkout.mjs +58 -0
- package/dist/development/core/request-routing/interceptors/checkout.mjs.map +1 -0
- package/dist/development/core/request-routing/interceptors/graphiql.mjs +46 -0
- package/dist/development/core/request-routing/interceptors/graphiql.mjs.map +1 -0
- package/dist/development/core/request-routing/interceptors/mcp-proxy.mjs +23 -0
- package/dist/development/core/request-routing/interceptors/mcp-proxy.mjs.map +1 -0
- package/dist/development/core/request-routing/interceptors/proxy.mjs +68 -0
- package/dist/development/core/request-routing/interceptors/proxy.mjs.map +1 -0
- package/dist/development/core/request-routing/interceptors/query-param-redirect.mjs +22 -0
- package/dist/development/core/request-routing/interceptors/query-param-redirect.mjs.map +1 -0
- package/dist/development/core/request-routing/interceptors/sfapi-proxy.mjs +27 -0
- package/dist/development/core/request-routing/interceptors/sfapi-proxy.mjs.map +1 -0
- package/dist/development/core/request-routing/interceptors/standard-routes.mjs +19 -0
- package/dist/development/core/request-routing/interceptors/standard-routes.mjs.map +1 -0
- package/dist/development/core/request-routing/interceptors/url-redirects.mjs +27 -0
- package/dist/development/core/request-routing/interceptors/url-redirects.mjs.map +1 -0
- package/dist/development/core/request-routing/interceptors/well-known.mjs +19 -0
- package/dist/development/core/request-routing/interceptors/well-known.mjs.map +1 -0
- package/dist/development/core/request-routing/registered-routes.d.mts +7 -0
- package/dist/development/core/request-routing/registered-routes.mjs +59 -0
- package/dist/development/core/request-routing/registered-routes.mjs.map +1 -0
- package/dist/development/core/request-routing/route-types.d.mts +51 -0
- package/dist/development/core/request-routing/safe-apply-response-headers.mjs +16 -0
- package/dist/development/core/request-routing/safe-apply-response-headers.mjs.map +1 -0
- package/dist/development/core/shop-pay/shop-pay.d.mts +102 -0
- package/dist/development/core/shop-pay/shop-pay.mjs +289 -0
- package/dist/development/core/shop-pay/shop-pay.mjs.map +1 -0
- package/dist/development/core/shopify-scripts/analytics.mjs +26 -0
- package/dist/development/core/shopify-scripts/analytics.mjs.map +1 -0
- package/dist/development/core/shopify-scripts/consent.mjs +17 -0
- package/dist/development/core/shopify-scripts/consent.mjs.map +1 -0
- package/dist/development/core/shopify-scripts/constants.mjs +19 -0
- package/dist/development/core/shopify-scripts/constants.mjs.map +1 -0
- package/dist/development/core/shopify-scripts/deprecated-cookies.mjs +97 -0
- package/dist/development/core/shopify-scripts/deprecated-cookies.mjs.map +1 -0
- package/dist/development/core/shopify-scripts/global.d.mts +1 -0
- package/dist/development/core/shopify-scripts/global.mjs +86 -0
- package/dist/development/core/shopify-scripts/global.mjs.map +1 -0
- package/dist/development/core/shopify-scripts/index.d.mts +27 -0
- package/dist/development/core/shopify-scripts/index.mjs +145 -0
- package/dist/development/core/shopify-scripts/index.mjs.map +1 -0
- package/dist/development/core/shopify-scripts/initialize.d.mts +18 -0
- package/dist/development/core/shopify-scripts/initialize.mjs +27 -0
- package/dist/development/core/shopify-scripts/initialize.mjs.map +1 -0
- package/dist/development/core/shopify-scripts/page-view.mjs +49 -0
- package/dist/development/core/shopify-scripts/page-view.mjs.map +1 -0
- package/dist/development/core/shopify-scripts/perfkit.mjs +33 -0
- package/dist/development/core/shopify-scripts/perfkit.mjs.map +1 -0
- package/dist/development/core/shopify-scripts/render.d.mts +1 -0
- package/dist/development/core/shopify-scripts/render.mjs +23 -0
- package/dist/development/core/shopify-scripts/render.mjs.map +1 -0
- package/dist/development/core/shopify-scripts/types.d.mts +76 -0
- package/dist/development/core/shopify-scripts/utils/cookie-domain.mjs +43 -0
- package/dist/development/core/shopify-scripts/utils/cookie-domain.mjs.map +1 -0
- package/dist/development/core/shopify-scripts/utils/inline-script.mjs +8 -0
- package/dist/development/core/shopify-scripts/utils/inline-script.mjs.map +1 -0
- package/dist/development/core/shopify-scripts/utils/navigation.mjs +46 -0
- package/dist/development/core/shopify-scripts/utils/navigation.mjs.map +1 -0
- package/dist/development/core/shopify-scripts/utils/tracking-values.mjs +65 -0
- package/dist/development/core/shopify-scripts/utils/tracking-values.mjs.map +1 -0
- package/dist/development/core/shopify-scripts/utils/uuid.mjs +17 -0
- package/dist/development/core/shopify-scripts/utils/uuid.mjs.map +1 -0
- package/dist/development/core/shopify-scripts/webmcp.mjs +22 -0
- package/dist/development/core/shopify-scripts/webmcp.mjs.map +1 -0
- package/dist/development/core/standard-routes/build.d.mts +34 -0
- package/dist/development/core/standard-routes/build.mjs +54 -0
- package/dist/development/core/standard-routes/build.mjs.map +1 -0
- package/dist/development/core/standard-routes/defaults.mjs +31 -0
- package/dist/development/core/standard-routes/defaults.mjs.map +1 -0
- package/dist/development/core/standard-routes/match.mjs +108 -0
- package/dist/development/core/standard-routes/match.mjs.map +1 -0
- package/dist/development/core/standard-routes/path.mjs +58 -0
- package/dist/development/core/standard-routes/path.mjs.map +1 -0
- package/dist/development/core/standard-routes/redirects.mjs +51 -0
- package/dist/development/core/standard-routes/redirects.mjs.map +1 -0
- package/dist/development/core/standard-routes/types.d.mts +95 -0
- package/dist/development/core/types.d.mts +11 -0
- package/dist/development/core/url.mjs +35 -0
- package/dist/development/core/url.mjs.map +1 -0
- package/dist/development/core/utils/load-script.mjs +34 -0
- package/dist/development/core/utils/load-script.mjs.map +1 -0
- package/dist/development/core/utils/parse-gid.mjs +33 -0
- package/dist/development/core/utils/parse-gid.mjs.map +1 -0
- package/dist/development/customer-account/session.d.mts +46 -0
- package/dist/development/customer-account/session.mjs +21 -0
- package/dist/development/customer-account/session.mjs.map +1 -0
- package/dist/development/globals.d.mts +64 -0
- package/dist/development/graphql/generated/customer-account-api-types.d.mts +13 -0
- package/dist/development/graphql/generated/graphql-env.d.mts +19280 -0
- package/dist/development/graphql/generated/storefront-api-types.d.mts +47 -0
- package/dist/development/graphql/graphql.d.mts +40 -0
- package/dist/development/graphql/graphql.mjs +16 -0
- package/dist/development/graphql/graphql.mjs.map +1 -0
- package/dist/development/graphql/index.d.mts +2 -0
- package/dist/development/graphql/scalars.d.mts +15 -0
- package/dist/development/graphql/type-resolver.d.mts +229 -0
- package/dist/development/react/cart.d.mts +40 -0
- package/dist/development/react/cart.mjs +150 -0
- package/dist/development/react/cart.mjs.map +1 -0
- package/dist/development/react/collection.d.mts +91 -0
- package/dist/development/react/collection.mjs +129 -0
- package/dist/development/react/collection.mjs.map +1 -0
- package/dist/development/react/index.d.mts +13 -0
- package/dist/development/react/index.mjs +10 -0
- package/dist/development/react/predictive-search.d.mts +49 -0
- package/dist/development/react/predictive-search.mjs +133 -0
- package/dist/development/react/predictive-search.mjs.map +1 -0
- package/dist/development/react/product.d.mts +72 -0
- package/dist/development/react/product.mjs +127 -0
- package/dist/development/react/product.mjs.map +1 -0
- package/dist/development/react/shop-pay.d.mts +9 -0
- package/dist/development/react/shop-pay.mjs +16 -0
- package/dist/development/react/shop-pay.mjs.map +1 -0
- package/dist/development/react/shopify-scripts.d.mts +20 -0
- package/dist/development/react/shopify-scripts.mjs +39 -0
- package/dist/development/react/shopify-scripts.mjs.map +1 -0
- package/dist/development/vendor/standard-actions.d.mts +134 -0
- package/dist/development/vendor/standard-events.d.mts +1107 -0
- package/dist/development/vue/cart.d.mts +42 -0
- package/dist/development/vue/cart.mjs +118 -0
- package/dist/development/vue/cart.mjs.map +1 -0
- package/dist/development/vue/collection.d.mts +46 -0
- package/dist/development/vue/collection.mjs +108 -0
- package/dist/development/vue/collection.mjs.map +1 -0
- package/dist/development/vue/index.d.mts +11 -0
- package/dist/development/vue/index.mjs +8 -0
- package/dist/development/vue/predictive-search.d.mts +124 -0
- package/dist/development/vue/predictive-search.mjs +171 -0
- package/dist/development/vue/predictive-search.mjs.map +1 -0
- package/dist/development/vue/product.d.mts +57 -0
- package/dist/development/vue/product.mjs +167 -0
- package/dist/development/vue/product.mjs.map +1 -0
- package/dist/development/vue/shop-pay.d.mts +25 -0
- package/dist/development/vue/shop-pay.mjs +35 -0
- package/dist/development/vue/shop-pay.mjs.map +1 -0
- package/dist/development/vue/shopify-scripts.d.mts +127 -0
- package/dist/development/vue/shopify-scripts.mjs +79 -0
- package/dist/development/vue/shopify-scripts.mjs.map +1 -0
- package/dist/globals.d.mts +64 -0
- package/dist/graphql/generated/customer-account-api-types.d.mts +13 -0
- package/dist/graphql/generated/customer-account-graphql-env.d.mts +22170 -0
- package/dist/graphql/generated/graphql-env.d.mts +19280 -0
- package/dist/graphql/generated/storefront-api-types.d.mts +47 -0
- package/dist/graphql/graphql.d.mts +40 -0
- package/dist/graphql/graphql.mjs +16 -0
- package/dist/graphql/graphql.mjs.map +1 -0
- package/dist/graphql/index.d.mts +2 -0
- package/dist/graphql/scalars.d.mts +26 -0
- package/dist/graphql/type-resolver.d.mts +229 -0
- package/dist/react/cart.d.mts +40 -0
- package/dist/react/cart.mjs +150 -0
- package/dist/react/cart.mjs.map +1 -0
- package/dist/react/collection.d.mts +91 -0
- package/dist/react/collection.mjs +129 -0
- package/dist/react/collection.mjs.map +1 -0
- package/dist/react/index.d.mts +13 -0
- package/dist/react/index.mjs +10 -0
- package/dist/react/predictive-search.d.mts +49 -0
- package/dist/react/predictive-search.mjs +133 -0
- package/dist/react/predictive-search.mjs.map +1 -0
- package/dist/react/product.d.mts +72 -0
- package/dist/react/product.mjs +127 -0
- package/dist/react/product.mjs.map +1 -0
- package/dist/react/shop-pay.d.mts +9 -0
- package/dist/react/shop-pay.mjs +16 -0
- package/dist/react/shop-pay.mjs.map +1 -0
- package/dist/react/shopify-scripts.d.mts +20 -0
- package/dist/react/shopify-scripts.mjs +39 -0
- package/dist/react/shopify-scripts.mjs.map +1 -0
- package/dist/storefront-api-types.d.ts +2351 -2390
- package/dist/storefront.schema.json +41534 -1
- package/dist/ts-plugin/index.cjs +68 -0
- package/dist/ts-plugin/index.cjs.map +1 -0
- package/dist/ts-plugin/index.d.cts +4 -0
- package/dist/vendor/standard-actions.d.mts +134 -0
- package/dist/vendor/standard-events.d.mts +1107 -0
- package/dist/vite/index.d.mts +2 -0
- package/dist/vite/index.mjs +3 -0
- package/dist/vite/local-https.d.mts +35 -0
- package/dist/vite/local-https.mjs +202 -0
- package/dist/vite/local-https.mjs.map +1 -0
- package/dist/vue/cart.d.mts +42 -0
- package/dist/vue/cart.mjs +118 -0
- package/dist/vue/cart.mjs.map +1 -0
- package/dist/vue/collection.d.mts +46 -0
- package/dist/vue/collection.mjs +108 -0
- package/dist/vue/collection.mjs.map +1 -0
- package/dist/vue/index.d.mts +11 -0
- package/dist/vue/index.mjs +8 -0
- package/dist/vue/predictive-search.d.mts +124 -0
- package/dist/vue/predictive-search.mjs +171 -0
- package/dist/vue/predictive-search.mjs.map +1 -0
- package/dist/vue/product.d.mts +57 -0
- package/dist/vue/product.mjs +167 -0
- package/dist/vue/product.mjs.map +1 -0
- package/dist/vue/shop-pay.d.mts +25 -0
- package/dist/vue/shop-pay.mjs +35 -0
- package/dist/vue/shop-pay.mjs.map +1 -0
- package/dist/vue/shopify-scripts.d.mts +127 -0
- package/dist/vue/shopify-scripts.mjs +79 -0
- package/dist/vue/shopify-scripts.mjs.map +1 -0
- package/package.json +116 -86
- package/skills/hydrogen-analytics/SKILL.md +80 -0
- package/skills/hydrogen-analytics/references/react.md +160 -0
- package/skills/hydrogen-analytics/references/vue.md +80 -0
- package/skills/hydrogen-cart-drawer/SKILL.md +248 -0
- package/skills/hydrogen-cart-drawer/references/accessibility.md +109 -0
- package/skills/hydrogen-cart-drawer/references/css.md +67 -0
- package/skills/hydrogen-cart-ui/SKILL.md +218 -0
- package/skills/hydrogen-cart-ui/references/nextjs.md +89 -0
- package/skills/hydrogen-cart-ui/references/react.md +263 -0
- package/skills/hydrogen-cart-ui/references/vue.md +204 -0
- package/skills/hydrogen-collection-browser/SKILL.md +80 -0
- package/skills/hydrogen-collection-browser/references/nextjs.md +118 -0
- package/skills/hydrogen-collection-browser/references/nuxt.md +108 -0
- package/skills/hydrogen-collection-browser/references/react.md +237 -0
- package/skills/hydrogen-customer-account/SKILL.md +107 -0
- package/skills/hydrogen-image/SKILL.md +65 -0
- package/skills/hydrogen-local-https/SKILL.md +144 -0
- package/skills/hydrogen-markets/SKILL.md +221 -0
- package/skills/hydrogen-markets/references/nextjs.md +157 -0
- package/skills/hydrogen-money/SKILL.md +67 -0
- package/skills/hydrogen-oxygen/SKILL.md +245 -0
- package/skills/hydrogen-oxygen/references/react-router.md +230 -0
- package/skills/hydrogen-predictive-search/SKILL.md +130 -0
- package/skills/hydrogen-predictive-search/references/react.md +32 -0
- package/skills/hydrogen-predictive-search/references/vue.md +40 -0
- package/skills/hydrogen-request-handlers/SKILL.md +90 -0
- package/skills/hydrogen-request-handlers/references/frameworks.md +174 -0
- package/skills/hydrogen-request-handlers/references/nextjs.md +136 -0
- package/skills/hydrogen-request-handlers/references/nuxt.md +214 -0
- package/skills/hydrogen-routing/SKILL.md +154 -0
- package/skills/hydrogen-setup/SKILL.md +50 -0
- package/skills/hydrogen-setup/references/analytics.md +624 -0
- package/skills/hydrogen-setup/steps/1-inspect-app.md +62 -0
- package/skills/hydrogen-setup/steps/10-analytics.md +10 -0
- package/skills/hydrogen-setup/steps/11-verify.md +31 -0
- package/skills/hydrogen-setup/steps/2-scaffold.md +86 -0
- package/skills/hydrogen-setup/steps/3-build-home-page.md +37 -0
- package/skills/hydrogen-setup/steps/4-collection-and-search.md +13 -0
- package/skills/hydrogen-setup/steps/5-cart.md +10 -0
- package/skills/hydrogen-setup/steps/6-product-detail-page.md +390 -0
- package/skills/hydrogen-setup/steps/7-shopify-runtime-scripts.md +69 -0
- package/skills/hydrogen-setup/steps/8-cart-drawer-and-navbar.md +35 -0
- package/skills/hydrogen-setup/steps/9-account-page.md +54 -0
- package/skills/hydrogen-shop-pay/SKILL.md +79 -0
- package/skills/hydrogen-shop-pay/references/core.md +66 -0
- package/skills/hydrogen-shop-pay/references/react.md +50 -0
- package/skills/hydrogen-shop-pay/references/vue.md +39 -0
- package/skills/hydrogen-smoke-test/SKILL.md +203 -0
- package/skills/hydrogen-storefront-client/SKILL.md +322 -0
- package/skills/hydrogen-storefront-client/references/astro.md +125 -0
- package/skills/hydrogen-storefront-client/references/caching.md +25 -0
- package/skills/hydrogen-storefront-client/references/nextjs.md +121 -0
- package/skills/hydrogen-storefront-client/references/nuxt.md +121 -0
- package/skills/hydrogen-storefront-client/references/query-validation.md +95 -0
- package/skills/hydrogen-storefront-client/references/react-router.md +81 -0
- package/skills/hydrogen-storefront-client/references/solidstart.md +131 -0
- package/skills/hydrogen-storefront-client/references/sveltekit.md +169 -0
- package/skills/hydrogen-variant-form/SKILL.md +250 -0
- package/skills/hydrogen-variant-form/references/nextjs.md +203 -0
- package/skills/hydrogen-variant-form/references/nuxt.md +95 -0
- package/skills/hydrogen-variant-form/references/react.md +71 -0
- package/dist/dev/get-virtual-routes-H72465VB.js +0 -74
- package/dist/dev/hydrogen-routes.d.ts +0 -5
- package/dist/dev/hydrogen-routes.js +0 -25
- package/dist/development/get-virtual-routes-ACFZHU42.js +0 -71
- package/dist/development/get-virtual-routes-ACFZHU42.js.map +0 -1
- package/dist/development/index.cjs +0 -6948
- package/dist/development/index.cjs.map +0 -1
- package/dist/development/index.js +0 -6601
- package/dist/development/index.js.map +0 -1
- package/dist/development/log-seo-tags-IG37ONQ2.js +0 -74
- package/dist/development/log-seo-tags-IG37ONQ2.js.map +0 -1
- package/dist/development/react-router-preset.d.ts +0 -45
- package/dist/development/react-router-preset.js +0 -49
- package/dist/development/react-router-preset.js.map +0 -1
- package/dist/index.cjs +0 -1
- package/dist/oxygen/index.d.ts +0 -197
- package/dist/oxygen/index.js +0 -107
- package/dist/production/get-virtual-routes-ZZEGQQDV.js +0 -3
- package/dist/production/get-virtual-routes-ZZEGQQDV.js.map +0 -1
- package/dist/production/index.cjs +0 -1019
- package/dist/production/index.cjs.map +0 -1
- package/dist/production/index.d.cts +0 -3260
- package/dist/production/index.d.ts +0 -3260
- package/dist/production/index.js +0 -1019
- package/dist/production/index.js.map +0 -1
- package/dist/production/log-seo-tags-TY72EQWZ.js +0 -2
- package/dist/production/log-seo-tags-TY72EQWZ.js.map +0 -1
- package/dist/production/react-router-preset.d.ts +0 -45
- package/dist/production/react-router-preset.js +0 -11
- package/dist/react-router.d.ts +0 -75
- package/dist/vite/chunk-4O5OI3OO.js +0 -127
- package/dist/vite/chunk-FAQ7TVHC.js +0 -9
- package/dist/vite/chunk-QXBQVDMY.js +0 -68
- package/dist/vite/compat-date.d.ts +0 -3
- package/dist/vite/compat-date.js +0 -6
- package/dist/vite/get-virtual-routes.d.ts +0 -21
- package/dist/vite/get-virtual-routes.js +0 -74
- package/dist/vite/hydrogen-middleware.d.ts +0 -9
- package/dist/vite/hydrogen-middleware.js +0 -7
- package/dist/vite/plugin.d.ts +0 -22
- package/dist/vite/plugin.js +0 -171
- package/dist/vite/request-events.d.ts +0 -144
- package/dist/vite/request-events.js +0 -10
- package/dist/vite/types.d.ts +0 -5
- package/dist/vite/types.js +0 -0
- package/dist/vite/virtual-routes/assets/debug-network.css +0 -609
- package/dist/vite/virtual-routes/assets/favicon-dark.svg +0 -20
- package/dist/vite/virtual-routes/assets/favicon.svg +0 -28
- package/dist/vite/virtual-routes/assets/inter-variable-font.woff2 +0 -0
- package/dist/vite/virtual-routes/assets/jetbrainsmono-variable-font.woff2 +0 -0
- package/dist/vite/virtual-routes/assets/styles.css +0 -249
- package/dist/vite/virtual-routes/components/FlameChartWrapper.jsx +0 -123
- package/dist/vite/virtual-routes/components/HydrogenLogoBaseBW.jsx +0 -32
- package/dist/vite/virtual-routes/components/HydrogenLogoBaseColor.jsx +0 -47
- package/dist/vite/virtual-routes/components/IconBanner.jsx +0 -292
- package/dist/vite/virtual-routes/components/IconClose.jsx +0 -38
- package/dist/vite/virtual-routes/components/IconDiscard.jsx +0 -44
- package/dist/vite/virtual-routes/components/IconError.jsx +0 -61
- package/dist/vite/virtual-routes/components/IconGithub.jsx +0 -23
- package/dist/vite/virtual-routes/components/IconTwitter.jsx +0 -21
- package/dist/vite/virtual-routes/components/Layout.jsx +0 -7
- package/dist/vite/virtual-routes/components/RequestDetails.jsx +0 -171
- package/dist/vite/virtual-routes/components/RequestTable.jsx +0 -91
- package/dist/vite/virtual-routes/components/RequestWaterfall.jsx +0 -151
- package/dist/vite/virtual-routes/layout.jsx +0 -33
- package/dist/vite/virtual-routes/lib/useDebugNetworkServer.jsx +0 -178
- package/dist/vite/virtual-routes/routes/[.]well-known.appspecific.com[.]chrome[.]devtools[.]json.jsx +0 -37
- package/dist/vite/virtual-routes/routes/[.]well-known.appspecific.com[.]chrome[.]devtools[.]json.tsx +0 -79
- package/dist/vite/virtual-routes/routes/graphiql.jsx +0 -5
- package/dist/vite/virtual-routes/routes/index.jsx +0 -265
- package/dist/vite/virtual-routes/routes/subrequest-profiler.jsx +0 -243
- package/dist/vite/virtual-routes/virtual-root-with-layout.jsx +0 -63
- package/dist/vite/virtual-routes/virtual-root.jsx +0 -67
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# React Frameworks
|
|
2
|
+
|
|
3
|
+
Use ShopifyScripts in the root layout/head, then publish events from client-side tracker components.
|
|
4
|
+
|
|
5
|
+
## Root Tracker
|
|
6
|
+
|
|
7
|
+
Server root/layout resolves safe `shop` and `i18n` data and passes it to ShopifyScripts.
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
<ShopifyScripts
|
|
11
|
+
shop={{
|
|
12
|
+
shopId: env.SHOP_ID,
|
|
13
|
+
storefrontId: env.PUBLIC_STOREFRONT_ID ?? "0",
|
|
14
|
+
myshopifyDomain: env.PUBLIC_STORE_DOMAIN,
|
|
15
|
+
}}
|
|
16
|
+
i18n={{ country: market.country, language: market.language, currency: market.currencyCode }}
|
|
17
|
+
consent={{ mode: "default-banner" }}
|
|
18
|
+
/>
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Do not query `localization.language` just to echo the language already passed to `@inContext`. If the app only knows country/language and does not have a market currency code, add `currencyCode` to the app's market config or query `localization { country { currency { isoCode } } }` as a fallback.
|
|
22
|
+
|
|
23
|
+
```tsx
|
|
24
|
+
import { useEffect } from "react";
|
|
25
|
+
import { AnalyticsEvent, getAnalytics } from "../lib/analytics";
|
|
26
|
+
|
|
27
|
+
export function AnalyticsTracker() {
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
const analytics = getAnalytics();
|
|
30
|
+
if (!analytics) return;
|
|
31
|
+
analytics.publish(AnalyticsEvent.PAGE_VIEWED);
|
|
32
|
+
}, []);
|
|
33
|
+
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Add `"use client"` only when this component lives in a Next.js App Router client component file.
|
|
39
|
+
|
|
40
|
+
For real route tracking, include the framework location in the effect dependency. In React Router, read `useLocation()` and key the effect by `location.pathname + location.search`. In Next App Router, read `usePathname()` and `useSearchParams()` in a client component wrapped in `Suspense`, then key the effect by both values. View events infer `url` from `window.location.href`; pass `url` only for an explicit override.
|
|
41
|
+
|
|
42
|
+
Cart analytics should publish from the confirmed cart state. If a component reads cart state directly, wait while `cart.revalidating === true || cart.pending.cost === true || cart.pending.note` is true so optimistic or revalidating cart changes do not publish as settled analytics.
|
|
43
|
+
|
|
44
|
+
```tsx
|
|
45
|
+
// app/layout.tsx
|
|
46
|
+
import { Suspense } from "react";
|
|
47
|
+
import { AnalyticsTracker } from "./components/AnalyticsTracker";
|
|
48
|
+
|
|
49
|
+
export default async function RootLayout({ children }: { children: React.ReactNode }) {
|
|
50
|
+
return (
|
|
51
|
+
<html lang="en">
|
|
52
|
+
<body>
|
|
53
|
+
<Suspense fallback={null}>
|
|
54
|
+
<AnalyticsTracker />
|
|
55
|
+
</Suspense>
|
|
56
|
+
{children}
|
|
57
|
+
</body>
|
|
58
|
+
</html>
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
```tsx
|
|
64
|
+
// app/components/AnalyticsTracker.tsx
|
|
65
|
+
"use client";
|
|
66
|
+
|
|
67
|
+
import { usePathname, useSearchParams } from "next/navigation";
|
|
68
|
+
import { useEffect } from "react";
|
|
69
|
+
import { AnalyticsEvent, getAnalytics } from "../lib/analytics";
|
|
70
|
+
|
|
71
|
+
export function AnalyticsTracker() {
|
|
72
|
+
const pathname = usePathname();
|
|
73
|
+
const searchParams = useSearchParams();
|
|
74
|
+
const pageKey = `${pathname}?${searchParams?.toString() ?? ""}`;
|
|
75
|
+
|
|
76
|
+
useEffect(() => {
|
|
77
|
+
const analytics = getAnalytics();
|
|
78
|
+
if (!analytics) return;
|
|
79
|
+
analytics.publish(AnalyticsEvent.PAGE_VIEWED);
|
|
80
|
+
}, [pageKey]);
|
|
81
|
+
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Product Viewed
|
|
87
|
+
|
|
88
|
+
Publish after product route data is available:
|
|
89
|
+
|
|
90
|
+
```tsx
|
|
91
|
+
function ProductViewedTracker({ product, selectedVariant }: Props) {
|
|
92
|
+
useEffect(() => {
|
|
93
|
+
const analytics = getAnalytics();
|
|
94
|
+
if (!analytics) return;
|
|
95
|
+
|
|
96
|
+
analytics.publish(AnalyticsEvent.PRODUCT_VIEWED, {
|
|
97
|
+
products: [
|
|
98
|
+
{
|
|
99
|
+
id: product.id,
|
|
100
|
+
title: product.title,
|
|
101
|
+
price:
|
|
102
|
+
selectedVariant?.price.amount ??
|
|
103
|
+
product.selectedOrFirstAvailableVariant?.price.amount ??
|
|
104
|
+
product.priceRange.minVariantPrice.amount,
|
|
105
|
+
vendor: product.vendor,
|
|
106
|
+
variantId:
|
|
107
|
+
selectedVariant?.id ??
|
|
108
|
+
product.selectedOrFirstAvailableVariant?.id ??
|
|
109
|
+
product.id,
|
|
110
|
+
variantTitle:
|
|
111
|
+
selectedVariant?.title ??
|
|
112
|
+
product.selectedOrFirstAvailableVariant?.title ??
|
|
113
|
+
product.title,
|
|
114
|
+
quantity: 1,
|
|
115
|
+
sku: selectedVariant?.sku,
|
|
116
|
+
},
|
|
117
|
+
],
|
|
118
|
+
});
|
|
119
|
+
}, [product.handle]);
|
|
120
|
+
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Prefer ProductVariant GID for `variantId`. Falling back to product ID should be treated as incomplete data.
|
|
126
|
+
|
|
127
|
+
## Collection And Search Viewed
|
|
128
|
+
|
|
129
|
+
Publish collection view when collection identity changes:
|
|
130
|
+
|
|
131
|
+
```tsx
|
|
132
|
+
analytics.publish(AnalyticsEvent.COLLECTION_VIEWED, {
|
|
133
|
+
collection: { id: collection.id, handle: collection.handle },
|
|
134
|
+
});
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Publish search view only for non-empty terms:
|
|
138
|
+
|
|
139
|
+
```tsx
|
|
140
|
+
if (term) {
|
|
141
|
+
analytics.publish(AnalyticsEvent.SEARCH_VIEWED, {
|
|
142
|
+
searchTerm: term,
|
|
143
|
+
searchResults: { totalCount },
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## Cart Updates
|
|
149
|
+
|
|
150
|
+
Use the `useCartAnalytics()` hook from the React binding — rendered inside `CartProvider`, it calls `trackCartAnalytics(store)` in an effect and cleans up on unmount. Outside the binding, call `trackCartAnalytics(store)` once with the cart store from a client-only effect (`useEffect`) — never at cart-store creation time, since it throws when `window.Shopify.analytics` is missing during SSR. It subscribes itself, skips pending/revalidating/note updates, derives cart delta events from confirmed cart changes, returns an unsubscribe function, and uses the global analytics bus created by ShopifyScripts. Do not manually publish `product_added_to_cart`.
|
|
151
|
+
|
|
152
|
+
Publish `CART_VIEWED` when the cart page or drawer is viewed. The cart payload is `AnalyticsCart | null`: when a compatible cart is available, include `id`, `updatedAt`, and connection-shaped `lines`; otherwise pass `cart: null` instead of a partial cart.
|
|
153
|
+
|
|
154
|
+
```tsx
|
|
155
|
+
analytics.publish(AnalyticsEvent.CART_VIEWED, {
|
|
156
|
+
cart: analyticsCart ?? null,
|
|
157
|
+
});
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
If the app uses Hydrogen's cart store type directly, convert it at the app boundary before publishing analytics. Only pass settled cart lines that include product IDs, vendor, and variant price fields.
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# Vue And Nuxt
|
|
2
|
+
|
|
3
|
+
Use `ShopifyScripts` in the app root/head, then read the shared bus from the Shopify global.
|
|
4
|
+
|
|
5
|
+
## Singleton
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
import {
|
|
9
|
+
AnalyticsEvent,
|
|
10
|
+
type StorefrontAnalytics,
|
|
11
|
+
} from "@shopify/hydrogen";
|
|
12
|
+
|
|
13
|
+
export { AnalyticsEvent };
|
|
14
|
+
|
|
15
|
+
let analytics: StorefrontAnalytics | null = null;
|
|
16
|
+
|
|
17
|
+
export function getAnalytics() {
|
|
18
|
+
if (!import.meta.client) return null;
|
|
19
|
+
analytics ??= window.Shopify?.analytics ?? null;
|
|
20
|
+
return analytics;
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Nuxt Client Plugin
|
|
25
|
+
|
|
26
|
+
Render `ShopifyScripts` with top-level `shop` and `i18n` in the app root/head. A client plugin can then read the global bus directly:
|
|
27
|
+
|
|
28
|
+
```ts
|
|
29
|
+
export default defineNuxtPlugin(() => {
|
|
30
|
+
const analytics = getAnalytics();
|
|
31
|
+
analytics?.addDestination({
|
|
32
|
+
name: "example-console-logger",
|
|
33
|
+
setup({ subscribe }) {
|
|
34
|
+
return subscribe(AnalyticsEvent.PAGE_VIEWED, (payload) => {
|
|
35
|
+
console.log("[analytics] page_viewed", payload);
|
|
36
|
+
});
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Do not expose private tokens through runtime public config.
|
|
43
|
+
|
|
44
|
+
## Page Views
|
|
45
|
+
|
|
46
|
+
Use a client plugin or root component watcher. View events infer `url` from `window.location.href`; pass `url` only for an explicit override:
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
export default defineNuxtPlugin(() => {
|
|
50
|
+
const router = useRouter();
|
|
51
|
+
router.afterEach(() => {
|
|
52
|
+
const analytics = getAnalytics();
|
|
53
|
+
if (!analytics) return;
|
|
54
|
+
analytics.publish(AnalyticsEvent.PAGE_VIEWED);
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Product, Collection, Search
|
|
60
|
+
|
|
61
|
+
Use `onMounted` or `watch` keyed on resolved route data:
|
|
62
|
+
|
|
63
|
+
```ts
|
|
64
|
+
onMounted(() => {
|
|
65
|
+
const analytics = getAnalytics();
|
|
66
|
+
if (!analytics) return;
|
|
67
|
+
analytics.publish(AnalyticsEvent.SEARCH_VIEWED, {
|
|
68
|
+
searchTerm: term.value,
|
|
69
|
+
searchResults: { totalCount: totalCount.value },
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Avoid publishing view events before server data is available.
|
|
75
|
+
|
|
76
|
+
## Cart Updates
|
|
77
|
+
|
|
78
|
+
Call the `useCartAnalytics()` composable from `@shopify/hydrogen/vue` in a component rendered inside the `CartProvider` returned by `createCartComponents()` (the Vue entry exports no standalone `CartProvider`). It subscribes the provider's cart store on mount, skips pending/revalidating/note updates, publishes derived cart delta events through the global analytics bus on confirmed cart changes, and unsubscribes when the component is disposed. If the app owns its cart store directly (`createCartStore` from `@shopify/hydrogen`), call `trackCartAnalytics(store)` once instead, from a client-only effect (`onMounted`) — never at cart-store creation time, since it throws when `window.Shopify.analytics` is missing during SSR. It returns an unsubscribe function.
|
|
79
|
+
|
|
80
|
+
If a component reads cart state directly, wait while `cart.revalidating === true || cart.pending.cost === true || cart.pending.note` is true so optimistic or revalidating cart changes do not publish as settled analytics.
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: hydrogen-cart-drawer
|
|
3
|
+
description: >
|
|
4
|
+
Guide for building an accessible cart drawer using @shopify/hydrogen. Use when
|
|
5
|
+
creating or reviewing a cart drawer, mini cart, or slide-out cart, including
|
|
6
|
+
native dialog element (showModal), closedby light dismiss, body scroll lock, exit
|
|
7
|
+
animations, and wiring window.Shopify.actions.openCart().
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Cart Drawer
|
|
11
|
+
|
|
12
|
+
Build an accessible cart drawer that opens from the edge of the viewport and integrates with Standard Actions so any code can open it via `window.Shopify.actions.openCart()`.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## 1. Prerequisites
|
|
17
|
+
|
|
18
|
+
Before building the cart drawer, these must be in place:
|
|
19
|
+
|
|
20
|
+
- **Shopify runtime scripts** — render `ShopifyScripts` once in the root document, or use `getShopifyScriptTags()` / `renderShopifyScriptTags()` from core in framework-agnostic heads plus `initializeShopifyScripts({ routes: routeTemplates })` during browser hydration. Use the local `hydrogen-routing` skill for the required routing options. The drawer uses `window.Shopify.actions.openCart()` from that runtime.
|
|
21
|
+
- **`/cart` route** — the full cart page, used as the fallback route when the drawer is unavailable. For strict no-JS live cart HTML, the cart route must receive resolved cart `initialData`.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## 2. Drawer structure
|
|
26
|
+
|
|
27
|
+
The drawer has three layout zones (header / body / footer):
|
|
28
|
+
|
|
29
|
+
1. **Header** — title, close button, and error banner (if any cart errors exist). Always visible, never scrolls.
|
|
30
|
+
2. **Body** — line items only. This is the only zone that scrolls when content overflows.
|
|
31
|
+
3. **Footer** — discount codes, order note and/or cart attribute editors, totals, and checkout button. Always visible (pinned to bottom), never scrolls.
|
|
32
|
+
|
|
33
|
+
**Empty state**: When the cart has no items, the body shows an empty message ("Your cart is empty") and the footer is hidden entirely — no totals, no discounts, no notes, no checkout button.
|
|
34
|
+
|
|
35
|
+
The drawer is a `<dialog>` (or primitive library equivalent) rendered once in the root layout. The storefront must also have a `/cart` route that renders a full cart page — this is the fallback route when the drawer is unavailable. The drawer is the progressively-enhanced experience that layers on top after hydration.
|
|
36
|
+
|
|
37
|
+
The full `/cart` page shares the same content components (line items, discounts, note, attributes, totals, checkout) but uses a page layout instead of the fixed header/body/footer zones.
|
|
38
|
+
|
|
39
|
+
The drawer's line item forms must use the same Hydrogen line-item form contract as the `/cart` page — see `hydrogen-cart-ui` ("Form structure"). The layout may differ by framework and design system; the form contract must not.
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## 3. Accessibility
|
|
44
|
+
|
|
45
|
+
See `references/accessibility.md` for the full dialog accessibility spec grounded in the WHATWG HTML specification.
|
|
46
|
+
|
|
47
|
+
### Must implement (not provided by `<dialog>`)
|
|
48
|
+
|
|
49
|
+
At-a-glance index — full treatment lives where each concern is implemented:
|
|
50
|
+
|
|
51
|
+
1. **Body scroll lock** — pure CSS, no JS class toggling (see §6)
|
|
52
|
+
2. **Backdrop click dismissal** — native light dismiss via `<dialog closedby="any">` (see §5)
|
|
53
|
+
3. **Exit animation** — `@starting-style` / discrete transitions (see §6)
|
|
54
|
+
|
|
55
|
+
### Provided by `<dialog>` + `showModal()`
|
|
56
|
+
|
|
57
|
+
These are free — **do not reimplement them**: focus containment (background `inert`), focus restoration to the trigger on `close()`, Escape dismissal, `::backdrop` overlay, and implicit `aria-modal="true"`. See `references/accessibility.md` for the full table and how each works.
|
|
58
|
+
|
|
59
|
+
### Required markup
|
|
60
|
+
|
|
61
|
+
```html
|
|
62
|
+
<dialog aria-labelledby="cart-drawer-title">
|
|
63
|
+
<h2 id="cart-drawer-title">Cart</h2>
|
|
64
|
+
<!-- drawer content -->
|
|
65
|
+
</dialog>
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
All interactive elements inside the drawer must be `<button>` or `<input>` elements — not `<div>` or `<span>` with click handlers.
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## 4. Dialog primitive recommendation
|
|
73
|
+
|
|
74
|
+
**Default**: use native `<dialog>` with `showModal()`. It gives you most accessibility behaviors for free and avoids adding a dependency.
|
|
75
|
+
|
|
76
|
+
Use a primitive library only when the app already depends on one for dialog-like UI and wants that library's controlled-state or animation model. The accessibility requirements in `references/accessibility.md` are identical regardless of approach.
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## 5. Open/close behavior
|
|
81
|
+
|
|
82
|
+
### Opening the drawer
|
|
83
|
+
|
|
84
|
+
The cart trigger renders in SSR as `<a href="/cart">Cart</a>` so it works before hydration and without JavaScript (the anchor navigates to the full `/cart` page). After hydration, an `onClick` calls `e.preventDefault()` then `openCartDrawer()` (which calls `showModal()`), so the click opens the drawer instead of navigating; no `hasHydrated` swap is needed — the anchor is the no-JS baseline and the `onClick` is the enhancement.
|
|
85
|
+
|
|
86
|
+
Keep the drawer as hydrated progressive enhancement. Do not make the drawer itself the fallback route; the `/cart` page is that full-page fallback.
|
|
87
|
+
|
|
88
|
+
```tsx
|
|
89
|
+
export const CART_DRAWER_ID = "cart-drawer";
|
|
90
|
+
const STANDARD_ACTIONS_READY_EVENT = "DOMContentLoaded";
|
|
91
|
+
|
|
92
|
+
let openCartActionConfigured = false;
|
|
93
|
+
let openCartActionRetryQueued = false;
|
|
94
|
+
|
|
95
|
+
function getCartDrawer() {
|
|
96
|
+
if (typeof document === "undefined") return null;
|
|
97
|
+
|
|
98
|
+
const drawer = document.getElementById(CART_DRAWER_ID);
|
|
99
|
+
return drawer instanceof HTMLDialogElement ? drawer : null;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export function openCartDrawer() {
|
|
103
|
+
const drawer = getCartDrawer();
|
|
104
|
+
if (!drawer || drawer.open) return;
|
|
105
|
+
drawer.showModal();
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export function closeCartDrawer() {
|
|
109
|
+
getCartDrawer()?.close();
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function configureOpenCartActionNow() {
|
|
113
|
+
const openCart = typeof window !== "undefined" ? window.Shopify?.actions?.openCart : undefined;
|
|
114
|
+
if (!openCart) return false;
|
|
115
|
+
|
|
116
|
+
openCart.configure({
|
|
117
|
+
handler: async () => openCartDrawer(),
|
|
118
|
+
});
|
|
119
|
+
openCartActionConfigured = true;
|
|
120
|
+
return true;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export function configureOpenCartAction() {
|
|
124
|
+
if (typeof document === "undefined" || openCartActionConfigured) return;
|
|
125
|
+
if (configureOpenCartActionNow()) return;
|
|
126
|
+
if (openCartActionRetryQueued || document.readyState !== "loading") return;
|
|
127
|
+
|
|
128
|
+
openCartActionRetryQueued = true;
|
|
129
|
+
document.addEventListener(
|
|
130
|
+
STANDARD_ACTIONS_READY_EVENT,
|
|
131
|
+
() => {
|
|
132
|
+
openCartActionRetryQueued = false;
|
|
133
|
+
configureOpenCartAction();
|
|
134
|
+
},
|
|
135
|
+
{ once: true },
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
configureOpenCartAction();
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
The module-scope `configureOpenCartAction()` call is intentional. It no-ops during SSR, configures immediately when Standard Actions is already available, and retries once on `DOMContentLoaded` when the runtime loads after this module.
|
|
143
|
+
|
|
144
|
+
Render the drawer once in the root layout. Use explicit JavaScript open/close helpers for app-owned controls.
|
|
145
|
+
|
|
146
|
+
```tsx
|
|
147
|
+
import { CART_DRAWER_ID, closeCartDrawer } from "~/lib/cart-drawer";
|
|
148
|
+
|
|
149
|
+
function CartDrawer() {
|
|
150
|
+
return (
|
|
151
|
+
<dialog id={CART_DRAWER_ID} aria-labelledby="cart-drawer-title" closedby="any">
|
|
152
|
+
<h2 id="cart-drawer-title">Cart</h2>
|
|
153
|
+
<button
|
|
154
|
+
type="button"
|
|
155
|
+
aria-label="Close cart"
|
|
156
|
+
onClick={closeCartDrawer}
|
|
157
|
+
>
|
|
158
|
+
Close
|
|
159
|
+
</button>
|
|
160
|
+
{/* cart content */}
|
|
161
|
+
</dialog>
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
The drawer opens from three surfaces. The cart trigger is the canonical one; the other two reuse the same helper.
|
|
167
|
+
|
|
168
|
+
**1. The cart trigger.** A `/cart` anchor with an `onClick` that opens the drawer after hydration. It carries the accessibility attributes `aria-controls` and `aria-haspopup="dialog"`:
|
|
169
|
+
|
|
170
|
+
```tsx
|
|
171
|
+
return (
|
|
172
|
+
<a href="/cart" onClick={(e) => { e.preventDefault(); openCartDrawer(); }} aria-controls={CART_DRAWER_ID} aria-haspopup="dialog">
|
|
173
|
+
Cart
|
|
174
|
+
</a>
|
|
175
|
+
);
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
**2. `window.Shopify.actions.openCart()`** — the Standard Action for programmatic opening, so external code (Standard Actions tools, agents, third-party components) can open the drawer. Register the same stable DOM helper as the `openCart` handler (see §8 for the handler-permanence caveat).
|
|
179
|
+
|
|
180
|
+
```js
|
|
181
|
+
window.Shopify.actions.openCart();
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
**3. From add-to-cart** — when the canonical cart trigger is an anchor, open the drawer immediately with optimistic state so pending cart contents remain inspectable. Opening only after success is compatible with the storefront contract only when the page also provides a visible button that opens the drawer while the mutation is pending.
|
|
185
|
+
|
|
186
|
+
```tsx
|
|
187
|
+
<form {...formProps({ beforeSubmit: openCartDrawer })}>
|
|
188
|
+
{/* add-to-cart controls */}
|
|
189
|
+
</form>
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Validate before calling the drawer helper — for example, call `event.preventDefault()` and return if the quantity is invalid. Do not push this policy into core cart mutations; some storefronts want a toast, a cart page navigation, or no automatic UI change.
|
|
193
|
+
|
|
194
|
+
### Closing the drawer
|
|
195
|
+
|
|
196
|
+
Native: Escape and the back gesture (fires `cancel` then `close`). App-provided: the explicit close `<button>` in the header (`aria-label="Close cart"`). Backdrop (light dismiss) requires `<dialog closedby="any">`.
|
|
197
|
+
|
|
198
|
+
`closedby="any"` is the least compatible part of this pattern. Browsers without `closedby` support will ignore the attribute, so the drawer will still close from Escape and the explicit close button, but backdrop click will not close it. Do not provide a polyfill for `closedby` unless the app explicitly requires backdrop click support in those browsers.
|
|
199
|
+
|
|
200
|
+
If an app does require that polyfill, use a pointerdown-plus-click guard on the `<dialog>` itself: record whether `pointerdown` started on the dialog backdrop, then close only when the following `click` also targets the dialog. Do not close on a plain `click.self` alone, because a drag that starts inside the drawer and ends on the backdrop can produce an accidental close.
|
|
201
|
+
|
|
202
|
+
### State management
|
|
203
|
+
|
|
204
|
+
Open/close is DOM state owned by the `<dialog>` element. Prefer `dialog.showModal()` and `dialog.close()` over duplicating open state in framework state unless a primitive library requires controlled state.
|
|
205
|
+
|
|
206
|
+
For custom logic, listen to native dialog events instead of duplicating state. Use `toggle` to react after the drawer opens or closes. Use `beforetoggle` with `event.preventDefault()` when the app needs to intercept opening, run custom work such as an animation, and then call `showModal()` manually later.
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## 6. CSS and animation
|
|
211
|
+
|
|
212
|
+
See `references/css.md` for the reference drawer shell, entry/exit animation, backdrop, and scroll-lock CSS. In Tailwind apps, keep the dialog shell, `::backdrop`, `@starting-style`, and scroll-lock rules in global CSS or a project `@layer`; use utilities for the drawer's internal content layout.
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## 7. Verify
|
|
217
|
+
|
|
218
|
+
After building the cart drawer, test:
|
|
219
|
+
|
|
220
|
+
- [ ] Cart trigger is a `/cart` anchor pre-hydration; after hydration its `onClick` opens the drawer via `showModal()`
|
|
221
|
+
- [ ] If a no-JS fallback is required, it navigates to `/cart` without JavaScript
|
|
222
|
+
- [ ] `window.Shopify.actions.openCart()` opens drawer (test from browser console)
|
|
223
|
+
- [ ] Drawer closes via Escape, backdrop click (with `closedby="any"`), and the close button
|
|
224
|
+
- [ ] Focus returns to the cart icon after close
|
|
225
|
+
- [ ] Tab cycles only through elements inside the drawer while open
|
|
226
|
+
- [ ] Screen reader announces "Cart" (or equivalent title) on drawer open
|
|
227
|
+
- [ ] While cart data loads, the title and close button remain available and the loading status is announced
|
|
228
|
+
- [ ] Drawer line item forms use the same `hydrogen-cart-ui` progressive form contract as the `/cart` page
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
## 8. Common gotchas
|
|
233
|
+
|
|
234
|
+
- **`openCart` handler is permanent** — `openCart.configure({ handler })` has no corresponding `unconfigure()`. Once registered, the handler persists for the page lifetime. This is fine when the drawer lives in the root layout. Avoid handlers that close over component refs that can go stale during HMR; prefer a small stable helper that looks up `dialog#cart-drawer` and calls `showModal()`.
|
|
235
|
+
|
|
236
|
+
- **Astro view transitions** — if the drawer is vanilla JS (like the base example), it must be re-initialized after view transition navigations. Listen for `astro:after-swap`.
|
|
237
|
+
|
|
238
|
+
- **Cart selectors must be stable** — don't derive arrays or objects inside a cart selector unless the binding accepts an equality function. Select store references such as `state.errors` or `state.data.lines.nodes` and derive banner messages outside the selector with the framework's memoization primitive.
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
## 9. Anti-patterns
|
|
243
|
+
|
|
244
|
+
- **Drawer as a route instead of overlay** — the drawer is overlay UI in the root layout and must be available on every page; the `/cart` route is the full cart page, not the drawer (see §2).
|
|
245
|
+
|
|
246
|
+
- **`dialog.show()` instead of `showModal()`** — `show()` does not get top-layer rendering, focus containment, `inert` on background, or `::backdrop`. Always use `showModal()`.
|
|
247
|
+
|
|
248
|
+
- **Text-only drawer quantities** — rendering line quantities as text with only plus/minus controls breaks the progressive set-quantity path; use the same editable quantity input contract as the `/cart` page (see `hydrogen-cart-ui`).
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# Dialog/Drawer Accessibility Requirements
|
|
2
|
+
|
|
3
|
+
Framework-agnostic specification for building an accessible modal drawer. Grounded in the WHATWG HTML specification for the `<dialog>` element and WAI-ARIA Authoring Practices.
|
|
4
|
+
|
|
5
|
+
## The `<dialog>` element with `showModal()`
|
|
6
|
+
|
|
7
|
+
The native `<dialog>` element with `showModal()` is the recommended foundation. It provides six accessibility behaviors for free, leaving only three concerns for the implementation to handle.
|
|
8
|
+
|
|
9
|
+
### What `showModal()` provides
|
|
10
|
+
|
|
11
|
+
| Behavior | How it works |
|
|
12
|
+
|----------|-------------|
|
|
13
|
+
| **Top-layer rendering** | The dialog is promoted above all other content, regardless of `z-index` stacking. No z-index wars. |
|
|
14
|
+
| **`::backdrop` pseudo-element** | A full-viewport overlay rendered behind the dialog in the top layer. Styleable with CSS. |
|
|
15
|
+
| **Escape key dismissal** | Pressing Escape fires a `cancel` event (cancelable), then closes the dialog and fires a `close` event. |
|
|
16
|
+
| **Focus containment** | All content outside the dialog becomes `inert` — unreachable by Tab, click, or assistive technology. Tab and Shift+Tab cycle only through focusable elements inside the dialog. |
|
|
17
|
+
| **Focus restoration** | The browser stores the previously-focused element when `showModal()` is called and restores focus to it when the dialog closes via `close()`. Per the WHATWG spec, this is automatic. |
|
|
18
|
+
| **Implicit `aria-modal="true"`** | Screen readers recognize the dialog as modal without an explicit attribute. |
|
|
19
|
+
|
|
20
|
+
### What must be implemented manually
|
|
21
|
+
|
|
22
|
+
These three behaviors are NOT provided by `<dialog>` and must be handled by the implementation or a primitive library:
|
|
23
|
+
|
|
24
|
+
#### 1. Body scroll lock
|
|
25
|
+
|
|
26
|
+
`showModal()` does not prevent the background from scrolling. Use the CSS `:has()` selector to apply `overflow: hidden` on `<body>` when the dialog is open — no JS class toggling or cleanup needed:
|
|
27
|
+
|
|
28
|
+
```css
|
|
29
|
+
body:has(dialog#cart-drawer[open]) {
|
|
30
|
+
overflow: hidden;
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Watch for the scrollbar-gutter shift: when the scrollbar disappears, body width increases by the scrollbar's width. Primitive libraries typically handle this with `padding-right` compensation or `scrollbar-gutter: stable`.
|
|
35
|
+
|
|
36
|
+
#### 2. Backdrop click dismissal
|
|
37
|
+
|
|
38
|
+
The default `<dialog>` behavior does not close on backdrop click. The standard pattern detects clicks on the dialog element itself (as opposed to its children):
|
|
39
|
+
|
|
40
|
+
```js
|
|
41
|
+
dialog.addEventListener('click', (event) => {
|
|
42
|
+
if (event.target === dialog) dialog.close();
|
|
43
|
+
});
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Click events on child elements bubble to the dialog, but `event.target` remains the child — only direct clicks on the dialog element (i.e., the backdrop area) satisfy the condition.
|
|
47
|
+
|
|
48
|
+
**Preferred:** The `closedby` attribute provides native light dismiss. Setting `closedby="any"` enables both Escape and backdrop click dismissal natively. Browsers that do not support it ignore the attribute; keep an explicit close button as the always-available close mechanism.
|
|
49
|
+
|
|
50
|
+
#### 3. Exit animations
|
|
51
|
+
|
|
52
|
+
The hard problem: `close()` removes the dialog from the top layer immediately, making exit animations impossible with the standard approach.
|
|
53
|
+
|
|
54
|
+
Two strategies:
|
|
55
|
+
|
|
56
|
+
**CSS `@starting-style` + `allow-discrete` (modern browsers)**
|
|
57
|
+
```css
|
|
58
|
+
dialog[open] {
|
|
59
|
+
transform: translateX(0);
|
|
60
|
+
transition: transform 250ms, overlay 250ms allow-discrete, display 250ms allow-discrete;
|
|
61
|
+
}
|
|
62
|
+
@starting-style {
|
|
63
|
+
dialog[open] { transform: translateX(100%); }
|
|
64
|
+
}
|
|
65
|
+
dialog:not([open]) {
|
|
66
|
+
transform: translateX(100%);
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
**JavaScript-deferred close (broadest compatibility)**
|
|
71
|
+
Run the exit animation first, then call `dialog.close()` after the animation completes. This requires intercepting the native close flow (cancel the `cancel` event, run the animation, then close programmatically).
|
|
72
|
+
|
|
73
|
+
## Labeling
|
|
74
|
+
|
|
75
|
+
The drawer must have an accessible name. Use `aria-labelledby` pointing to the visible heading element:
|
|
76
|
+
|
|
77
|
+
```html
|
|
78
|
+
<dialog aria-labelledby="cart-drawer-title">
|
|
79
|
+
<h2 id="cart-drawer-title">Cart</h2>
|
|
80
|
+
...
|
|
81
|
+
</dialog>
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
If additional context is useful for screen readers (e.g., item count), use `aria-describedby` pointing to a summary element.
|
|
85
|
+
|
|
86
|
+
## Keyboard interaction
|
|
87
|
+
|
|
88
|
+
With `<dialog>` + `showModal()` and semantic HTML, all keyboard interactions are native:
|
|
89
|
+
|
|
90
|
+
| Key | Behavior | Source |
|
|
91
|
+
|-----|----------|--------|
|
|
92
|
+
| Escape | Closes the dialog | Native (`cancel` → `close` events) |
|
|
93
|
+
| Tab | Moves focus to next focusable element inside dialog | Native (background is `inert`) |
|
|
94
|
+
| Shift+Tab | Moves focus to previous focusable element inside dialog | Native |
|
|
95
|
+
| Enter / Space | Activates the focused button or link | Native for `<button>`, `<a>`, `<input>` |
|
|
96
|
+
|
|
97
|
+
No additional keyboard handlers are needed if all interactive elements use semantic HTML (`<button>`, `<a>`, `<input>`). Custom elements that are not natively focusable require `tabindex="0"` and `role` attributes — prefer native elements instead.
|
|
98
|
+
|
|
99
|
+
## How primitive libraries handle these concerns
|
|
100
|
+
|
|
101
|
+
Primitive libraries (Radix UI, Base UI, Melt UI, Kobalte, Headless UI, etc.) implement the same accessibility contract described above. They abstract the manual work:
|
|
102
|
+
|
|
103
|
+
- **Focus containment**: Some libraries build their own focus trap from `<div>` + portal rather than using `<dialog>`. The result is equivalent — Tab cycles within the dialog, background is inert.
|
|
104
|
+
- **Scroll lock**: Libraries typically add `overflow: hidden` with scrollbar-gutter compensation automatically.
|
|
105
|
+
- **Backdrop click**: Handled via an overlay component with an `onClick` handler, or via the `closedby` attribute where supported.
|
|
106
|
+
- **Exit animations**: Libraries integrate with their framework's animation system (React transition groups, Svelte transitions, CSS animation hooks) to defer unmounting until the animation completes.
|
|
107
|
+
- **Focus restoration**: Most libraries implement their own, even though `<dialog>` handles it natively. This is because some libraries render from `<div>` + portal, not `<dialog>`.
|
|
108
|
+
|
|
109
|
+
The accessibility requirements are identical regardless of whether you use a library or native `<dialog>`. Libraries reduce implementation effort but don't change what must be true for the drawer to be accessible.
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Cart Drawer CSS
|
|
2
|
+
|
|
3
|
+
Reference drawer shell, entry/exit animation, backdrop, and scroll-lock CSS for the cart drawer.
|
|
4
|
+
|
|
5
|
+
```css
|
|
6
|
+
dialog#cart-drawer {
|
|
7
|
+
position: fixed;
|
|
8
|
+
inset-block: 0;
|
|
9
|
+
right: 0;
|
|
10
|
+
left: auto;
|
|
11
|
+
margin: 0;
|
|
12
|
+
width: 100%;
|
|
13
|
+
max-width: 28rem;
|
|
14
|
+
height: 100dvh;
|
|
15
|
+
max-height: none;
|
|
16
|
+
border: 0;
|
|
17
|
+
padding: 0;
|
|
18
|
+
}
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
**Entry and exit animation**: slide in from the edge and let the dialog remain transitionable while closing.
|
|
22
|
+
```css
|
|
23
|
+
dialog#cart-drawer {
|
|
24
|
+
transform: translateX(100%);
|
|
25
|
+
transition:
|
|
26
|
+
transform 250ms cubic-bezier(0.22, 1, 0.36, 1),
|
|
27
|
+
overlay 250ms allow-discrete,
|
|
28
|
+
display 250ms allow-discrete;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
dialog#cart-drawer[open] {
|
|
32
|
+
transform: translateX(0);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
@starting-style {
|
|
36
|
+
dialog#cart-drawer[open] {
|
|
37
|
+
transform: translateX(100%);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
**Backdrop**: fade in.
|
|
43
|
+
```css
|
|
44
|
+
dialog#cart-drawer::backdrop {
|
|
45
|
+
background: rgb(0 0 0 / 0);
|
|
46
|
+
transition:
|
|
47
|
+
background-color 250ms ease-out,
|
|
48
|
+
overlay 250ms allow-discrete,
|
|
49
|
+
display 250ms allow-discrete;
|
|
50
|
+
}
|
|
51
|
+
dialog#cart-drawer[open]::backdrop {
|
|
52
|
+
background: rgb(0 0 0 / 0.3);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
@starting-style {
|
|
56
|
+
dialog#cart-drawer[open]::backdrop {
|
|
57
|
+
background: rgb(0 0 0 / 0);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
**Scroll lock**:
|
|
63
|
+
```css
|
|
64
|
+
body:has(dialog#cart-drawer[open]) { overflow: hidden; }
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Exact measurements and colors are not prescribed — the above matches the base example for reference. Adapt to the project's design system.
|