Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
471 changes: 261 additions & 210 deletions package-lock.json

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions packages/hydrogen-react/src/ExternalVideo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ import type {ExternalVideo as ExternalVideoType} from './storefront-api-types.js
import type {Entries, PartialDeep} from 'type-fest';
import {forwardRef, IframeHTMLAttributes} from 'react';

/**
* The `ExternalVideo` component renders an embedded video for the Storefront API's [ExternalVideo object](https://shopify.dev/api/storefront/reference/products/externalvideo).
* @publicDocs
*/
export interface ExternalVideoBaseProps {
/**
* An object with fields that correspond to the Storefront API's [ExternalVideo object](https://shopify.dev/api/storefront/reference/products/externalvideo).
Expand All @@ -23,6 +27,7 @@ export type ExternalVideoProps = Omit<
/**
* The `ExternalVideo` component renders an embedded video for the Storefront
* API's [ExternalVideo object](https://shopify.dev/api/storefront/reference/products/externalvideo).
* @publicDocs
*/
export const ExternalVideo = forwardRef<HTMLIFrameElement, ExternalVideoProps>(
(props, ref): JSX.Element => {
Expand Down
1 change: 1 addition & 0 deletions packages/hydrogen-react/src/Image.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ export const IMAGE_FRAGMENT = `#graphql
* ```
*
* {@link https://shopify.dev/docs/api/hydrogen-react/components/image}
* @publicDocs
*/
export const Image = React.forwardRef<HTMLImageElement, HydrogenImageProps>(
(
Expand Down
6 changes: 6 additions & 0 deletions packages/hydrogen-react/src/MediaFile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ import type {ModelViewerElement} from '@google/model-viewer/lib/model-viewer.js'
type BaseProps = React.HTMLAttributes<
HTMLImageElement | HTMLVideoElement | HTMLIFrameElement | ModelViewerElement
>;
/**
* MediaFile renders an `Image`, `Video`, `ExternalVideo`, or `ModelViewer` component. Use the `mediaOptions` prop to customize the props sent to each of these components.
* @publicDocs
*/
export interface MediaFileProps extends BaseProps {
/** An object with fields that correspond to the Storefront API's [Media object](https://shopify.dev/api/storefront/reference/products/media). */
data: PartialDeep<MediaEdgeType['node'], {recurseIntoArrays: true}>;
Expand All @@ -34,6 +38,8 @@ type MediaOptions = {
* The `MediaFile` component renders the media for the Storefront API's
* [Media object](https://shopify.dev/api/storefront/reference/products/media). It renders an `Image`, a
* `Video`, an `ExternalVideo`, or a `ModelViewer` depending on the `__typename` of the `data` prop.
* Use the `mediaOptions` prop to customize the props sent to each of these components.
* @publicDocs
*/
export function MediaFile({
data,
Expand Down
7 changes: 6 additions & 1 deletion packages/hydrogen-react/src/ModelViewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@ type ModelViewerProps = Omit<
> &
ModelViewerBaseProps;

type ModelViewerBaseProps = {
/**
* The `ModelViewer` component renders a 3D model (with the `model-viewer` custom element) for the Storefront API's [Model3d object](https://shopify.dev/api/storefront/reference/products/model3d). The `model-viewer` custom element is lazily downloaded through a dynamically-injected `<script type='module'>` tag when the `<ModelViewer />` component is rendered. ModelViewer is using version `1.21.1` of the `@google/model-viewer` library.
* @publicDocs
*/
export type ModelViewerBaseProps = {
/** An object with fields that correspond to the Storefront API's [Model3D object](https://shopify.dev/api/storefront/2025-07/objects/model3d). */
data: PartialDeep<Model3d, {recurseIntoArrays: true}>;
/** The callback to invoke when the 'error' event is triggered. Refer to [error in the <model-viewer> documentation](https://modelviewer.dev/docs/index.html#entrydocs-loading-events-error). */
Expand Down Expand Up @@ -60,6 +64,7 @@ type ModelViewerBaseProps = {
* The `model-viewer` custom element is lazily downloaded through a dynamically-injected `<script type="module">` tag when the `<ModelViewer />` component is rendered
*
* ModelViewer is using version `1.21.1` of the `@google/model-viewer` library.
* @publicDocs
*/
export function ModelViewer(props: ModelViewerProps): JSX.Element | null {
const [modelViewer, setModelViewer] = useState<undefined | HTMLElement>(
Expand Down
2 changes: 1 addition & 1 deletion packages/hydrogen-react/src/Money.doc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const data: ReferenceEntityTemplateSchema = {
},
],
description:
"The `Money` component renders a string of the Storefront API's[MoneyV2 object](https://shopify.dev/api/storefront/reference/common-objects/moneyv2) according to the `locale` in the [`ShopifyProvider` component](/api/hydrogen/components/global/shopifyprovider).\nThe component outputs a `<div>`. You can [customize this component](https://api/hydrogen/components#customizing-hydrogen-components) using passthrough props.",
"The `Money` component renders a string of the Storefront API's [MoneyV2 object](https://shopify.dev/api/storefront/reference/common-objects/moneyv2) according to the `locale` in the [`ShopifyProvider` component](/api/hydrogen/components/global/shopifyprovider).\nThe component outputs a `<div>`. You can [customize this component](https://api/hydrogen/components#customizing-hydrogen-components) using passthrough props.",
type: 'component',
defaultExample: {
description: 'I am the default example',
Expand Down
5 changes: 5 additions & 0 deletions packages/hydrogen-react/src/Money.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ import type {PartialDeep} from 'type-fest';
*/
type MoneyV2 = StorefrontApiMoneyV2 | CustomerAccountApiMoneyV2;

/**
* The `Money` component renders a string of the Storefront API's [MoneyV2 object](https://shopify.dev/api/storefront/reference/common-objects/moneyv2) according to the `locale` in the `ShopifyProvider` component.
* @publicDocs
*/
export interface MoneyPropsBase<ComponentGeneric extends React.ElementType> {
/** An HTML tag or React Component to be rendered as the base element wrapper. The default is `div`. */
as?: ComponentGeneric;
Expand Down Expand Up @@ -71,6 +75,7 @@ export type MoneyProps<ComponentGeneric extends React.ElementType> =
* measurementSeparator=" per "
* />
* ```
* @publicDocs
*/
export function Money<ComponentGeneric extends React.ElementType = 'div'>({
data,
Expand Down
4 changes: 4 additions & 0 deletions packages/hydrogen-react/src/RichText.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -209,5 +209,9 @@ function richTextToString(
}

// This is only for documentation purposes, and it is not used in the code.
/**
* The `RichText` component renders a metafield of type `rich_text_field`. By default the rendered output uses semantic HTML tags. Customize how nodes are rendered with the `components` prop.
* @publicDocs
*/
export type RichTextPropsForDocs<AsType extends React.ElementType = 'div'> =
RichTextPropsBase<AsType>;
7 changes: 6 additions & 1 deletion packages/hydrogen-react/src/ShopPayButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@ import {useLoadScript} from './load-script.js';
import {parseGid} from './analytics-utils.js';

// By using 'never' in the "or" cases below, it makes these props "exclusive" and means that you cannot pass both of them; you must pass either one OR the other.
type ShopPayButtonProps = ShopPayButtonStyleProps &
/**
* The `ShopPayButton` component renders a button that redirects to the Shop Pay checkout. It renders a [`<shop-pay-button>`](https://shopify.dev/custom-storefronts/tools/web-components) custom element, for which it will lazy-load the source code automatically.
* @publicDocs
*/
export type ShopPayButtonProps = ShopPayButtonStyleProps &
ShopPayDomainProps &
ShopPayChannelAttribution &
(ShopPayVariantIds | ShopPayVariantAndQuantities);
Expand Down Expand Up @@ -68,6 +72,7 @@ function isChannel(
* The `ShopPayButton` component renders a button that redirects to the Shop Pay checkout.
* It renders a [`<shop-pay-button>`](https://shopify.dev/custom-storefronts/tools/web-components) custom element, for which it will lazy-load the source code automatically.
* It relies on the `<ShopProvider>` context provider.
* @publicDocs
*/
export function ShopPayButton({
channel,
Expand Down
5 changes: 5 additions & 0 deletions packages/hydrogen-react/src/Video.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ import {shopifyLoader} from './Image.js';
import type {Video as VideoType} from './storefront-api-types.js';
import type {PartialDeep} from 'type-fest';

/**
* The `Video` component renders a video for the Storefront API's [Video object](https://shopify.dev/api/storefront/reference/products/video). The component outputs a `video` element.
* @publicDocs
*/
export interface VideoProps {
/** An object with fields that correspond to the Storefront API's [Video object](https://shopify.dev/api/storefront/2025-07/objects/video). */
data: PartialDeep<VideoType, {recurseIntoArrays: true}>;
Expand All @@ -16,6 +20,7 @@ export interface VideoProps {

/**
* The `Video` component renders a `video` for the Storefront API's [Video object](https://shopify.dev/api/storefront/reference/products/video).
* @publicDocs
*/
export const Video = forwardRef<
HTMLVideoElement,
Expand Down
1 change: 1 addition & 0 deletions packages/hydrogen-react/src/analytics-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@ export type ShopifyAnalyticsPayloadWithPrivacyFields =

export type ShopifyAnalytics = ShopifyPageView | ShopifyAddToCart;

/** @publicDocs */
export type ShopifyCookies = {
/** Shopify unique user token: Value of `_shopify_y` cookie. */
[SHOPIFY_Y]: string;
Expand Down
1 change: 1 addition & 0 deletions packages/hydrogen-react/src/analytics-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export function schemaWrapper(
* * const {id, resource} = parseGid('gid://shopify/Cart/abc123')
* // => id = "abc123", resource = 'Cart'
* ```
* @publicDocs
**/
export function parseGid(gid: string | undefined): ShopifyGid {
const defaultReturn: ShopifyGid = {
Expand Down
5 changes: 5 additions & 0 deletions packages/hydrogen-react/src/analytics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {getTrackingValues} from './tracking-utils.js';
* @param event - The analytics event.
* @param shopDomain - The Online Store domain to sent Shopify analytics under the same
* top level domain.
* @publicDocs
*/
export function sendShopifyAnalytics(
event: ShopifyAnalytics,
Expand Down Expand Up @@ -135,6 +136,10 @@ function sendToShopify(
}
}

/**
* Gathers client browser values commonly used for analytics.
* @publicDocs
*/
export function getClientBrowserParameters(): ClientBrowserParameters {
if (errorIfServer('getClientBrowserParameters')) {
return {
Expand Down
1 change: 1 addition & 0 deletions packages/hydrogen-react/src/cookies-utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ export function hexTime(): string {
/**
* Gets the values of _shopify_y and _shopify_s cookies from the provided cookie string.
* @deprecated Use getTrackingValues instead.
* @publicDocs
*/
export function getShopifyCookies(cookies: string): ShopifyCookies {
// @ts-expect-error - Undeclared argument type
Expand Down
6 changes: 6 additions & 0 deletions packages/hydrogen-react/src/flatten-connection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type {PartialDeep} from 'type-fest';
* The utility works with either `nodes` or `edges.node`.
*
* If `connection` is null or undefined, will return an empty array instead in production. In development, an error will be thrown.
* @publicDocs
*/
export function flattenConnection<
ConnectionGeneric extends
Expand Down Expand Up @@ -86,7 +87,12 @@ type ConnectionNodes = {
};

// This is only for documentation purposes, and it is not used in the code.
/**
* The `flattenConnection` utility transforms a connection object from the Storefront API (for example, [Product-related connections](https://shopify.dev/api/storefront/reference/products/product)) into a flat array of nodes. The utility works with either `nodes` or `edges.node`. If `connection` is null or undefined, will return an empty array instead in production. In development, an error will be thrown.
* @publicDocs
*/
export interface ConnectionGenericForDoc {
connection?: ConnectionEdges | ConnectionNodes;
}
/** @publicDocs */
export type FlattenConnectionReturnForDoc = unknown[];
7 changes: 6 additions & 1 deletion packages/hydrogen-react/src/load-script.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,15 @@ export function loadScript(
return promise;
}

type LoadScriptParams = Parameters<typeof loadScript>;
/**
* The `useLoadScript` hook loads an external script tag in the browser. It allows React components to lazy-load third-party dependencies.
* @publicDocs
*/
export type LoadScriptParams = Parameters<typeof loadScript>;

/**
* The `useLoadScript` hook loads an external script tag in the browser. It allows React components to lazy-load large third-party dependencies.
* @publicDocs
*/
export function useLoadScript(
url: LoadScriptParams[0],
Expand Down
3 changes: 3 additions & 0 deletions packages/hydrogen-react/src/optionValueDecoder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const V1_CONTROL_CHARS = {
RANGE: '-',
};

/** @publicDocs */
export type IsOptionValueCombinationInEncodedVariant = (
targetOptionValueCombination: number[],
encodedVariantField: string,
Expand All @@ -31,6 +32,7 @@ export type IsOptionValueCombinationInEncodedVariant = (
* @param targetOptionValueCombination - Indices of option values to look up in the encoded option value string. A partial set of indices may be passed to determine whether a node or any children is present. For example, if a product has 3 options, passing [0] will return true if any option value combination for the first option's option value is present in the encoded string.
* @param encodedVariantField - Encoded option value string from the Storefront API, e.g. [product.encodedVariantExistence](/docs/api/storefront/2025-07/objects/Product#field-encodedvariantexistence) or [product.encodedVariantAvailability](/docs/api/storefront/2025-07/objects/Product#field-encodedvariantavailability)
* @returns - True if a full or partial targetOptionValueIndices is present in the encoded option value string, false otherwise.
* @publicDocs
*/
export const isOptionValueCombinationInEncodedVariant: IsOptionValueCombinationInEncodedVariant =
((): IsOptionValueCombinationInEncodedVariant => {
Expand Down Expand Up @@ -80,6 +82,7 @@ type DecodedOptionValues = number[][];
* For an encoded option value string, decode into option value combinations. Entries represent a valid combination formatted as an array of option value positions.
* @param encodedVariantField - Encoded option value string from the Storefront API, e.g. [product.encodedVariantExistence](/docs/api/storefront/2025-07/objects/Product#field-encodedvariantexistence) or [product.encodedVariantAvailability](/docs/api/storefront/2025-07/objects/Product#field-encodedvariantavailability)
* @returns Decoded option value combinations
* @publicDocs
*/
export function decodeEncodedVariant(
encodedVariantField: EncodedVariantField,
Expand Down
1 change: 1 addition & 0 deletions packages/hydrogen-react/src/parse-metafield.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {RootASTNode as RichTextRootASTNode} from './RichText.types.js';
* ```
* parseMetafield<ParsedMetafields['boolean']>({type: 'boolean', value: 'false'}
* ```
* @publicDocs
*/
export function parseMetafield<ReturnGeneric>(
metafield: PartialDeep<MetafieldBaseType, {recurseIntoArrays: true}>,
Expand Down
1 change: 1 addition & 0 deletions packages/hydrogen-react/src/tracking-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export const cachedTrackingValues: {
/**
* Retrieves user session tracking values for analytics
* and marketing from the browser environment.
* @publicDocs
*/
export function getTrackingValues(): TrackingValues {
// Overall behavior: Tracking values are returned in Server-Timing headers from
Expand Down
1 change: 1 addition & 0 deletions packages/hydrogen-react/src/useMoney.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ export type UseMoneyValue = {
* ```ts
* money.withoutTrailingZerosAndCurrency
* ```
* @publicDocs
*/
export function useMoney(money: MoneyV2): UseMoneyValue {
const {countryIsoCode, languageIsoCode} = useShop();
Expand Down
1 change: 1 addition & 0 deletions packages/hydrogen-react/src/useShopifyCookies.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ type UseShopifyCookiesOptions = CoreShopifyCookiesOptions & {
* Useful when you only want to use the newer tracking values and not rely on the deprecated ones.
*
* @returns `true` when cookies are set and ready.
* @publicDocs
*/
export function useShopifyCookies(options?: UseShopifyCookiesOptions): boolean {
const {
Expand Down
9 changes: 9 additions & 0 deletions packages/hydrogen-react/tsdoc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json",
"tagDefinitions": [
{
"tagName": "@publicDocs",
"syntaxKind": "modifier"
}
]
}
12 changes: 6 additions & 6 deletions packages/hydrogen/docs/build-docs.sh
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
COMPILE_DOCS="npx tsc --project docs/tsconfig.docs.json --types react --moduleResolution node --target esNext && generate-docs --overridePath ./docs/typeOverride.json --input ./src --output ./docs/generated && rm -rf src/**/**/*.doc.js src/**/*.doc.js src/*.doc.js"
COMPILE_STATIC_PAGES="npx tsc docs/staticPages/*.doc.ts --types react --moduleResolution node --target esNext && generate-docs --isLandingPage --input ./docs/staticPages --output ./docs/generated && rm -rf docs/staticPages/*.doc.js"
COMPILE_DOCS="generate-docs --overridePath ./docs/typeOverride.json --input ./src ../hydrogen-react/src --output ./docs/generated"

if [ "$1" = "isTest" ];
then
COMPILE_DOCS="npx tsc --project docs/tsconfig.docs.json --types react --moduleResolution node --target esNext && generate-docs --overridePath ./docs/typeOverride.json --input ./src --output ./docs/temp && rm -rf src/**/*.doc.js src/*.doc.js"
COMPILE_STATIC_PAGES="npx tsc docs/staticPages/*.doc.ts --types react --moduleResolution node --target esNext && generate-docs --isLandingPage --input ./docs/staticPages --output ./docs/temp && rm -rf docs/staticPages/*.doc.js"
COMPILE_DOCS="generate-docs --overridePath ./docs/typeOverride.json --input ./src ../hydrogen-react/src --output ./docs/temp"
fi

eval $COMPILE_DOCS
eval $COMPILE_STATIC_PAGES

node ./docs/copy-hydrogen-react-docs.cjs
if [ "$1" != "isTest" ];
then
node ./docs/copy-docs-to-shopify-dev.mjs
fi
53 changes: 53 additions & 0 deletions packages/hydrogen/docs/copy-docs-to-shopify-dev.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import {promises as fs} from 'fs';
import path from 'path';
import {fileURLToPath} from 'url';

const __dirname = path.dirname(fileURLToPath(import.meta.url));

const SHOPIFY_DEV_DB_SUBPATH =
'areas/platforms/shopify-dev/db/data/docs/templated_apis';

const HYDROGEN_VERSION = '2025-07';

async function copyGeneratedToShopifyDev() {
const generatedDocsPath = path.resolve(
__dirname,
'./generated/generated_docs_data_v2.json',
);

// Find the shopify-dev repo: try world first, then relative fallback
const rootPath = path.resolve(__dirname, '../../..');
const worldPath = path.join(process.env.HOME, 'world/trees/root/src');

let shopifyDevPath;
try {
await fs.access(worldPath);
shopifyDevPath = worldPath;
} catch {
shopifyDevPath = path.join(rootPath, '../../../shopify-dev');
}

const shopifyDevDBPath = path.join(shopifyDevPath, SHOPIFY_DEV_DB_SUBPATH);

try {
await fs.access(shopifyDevDBPath);
} catch {
console.warn(
`[h2:docs] shopify-dev not found at ${shopifyDevDBPath}. Skipping copy.`,
);
return;
}

const destDir = path.join(shopifyDevDBPath, 'hydrogen', HYDROGEN_VERSION);
const destFile = path.join(destDir, 'generated_docs_data_v2.json');

await fs.mkdir(destDir, {recursive: true});
await fs.copyFile(generatedDocsPath, destFile);

console.log(`[h2:docs] Copied generated_docs_data_v2.json → ${destFile}`);
}

copyGeneratedToShopifyDev().catch((err) => {
console.error(err);
process.exit(1);
});
Loading
Loading