@godaddy/gd-commerce-storefront 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -84,9 +84,9 @@ A connection failure leaves the surrounding application and its state mounted. C
84
84
 
85
85
  The stylesheet includes all required utilities and scopes them to the package's surfaces. The build removes CSS layer wrappers in their declared order, so the exported CSS can pass through a host Tailwind v3 PostCSS pipeline without `@tailwind` directives. Import it directly; consumers do not need to copy or rewrite the CSS. It does not add a global reset or require dependency scanning by a host Tailwind build. The `theme` prop reaches the drawer even though it is portalled into `document.body`.
86
86
 
87
- By default, `.commerce-storefront` wrappers do not paint a background and inherit the host's text color. Set page and section backgrounds on the host application's layout elements. `--commerce-surface` colors controls and the opaque cart drawer, and supplies the base for muted colors; it does not color component wrappers. Set `--commerce-surface` and `--commerce-text` together to adapt controls and the drawer to a dark theme. Avoid setting wrapper backgrounds through CSS or the `theme` prop's `background`, `backgroundColor`, or `backgroundImage` properties, which can still override the transparent default. Descendants inherit the surface text and body font instead of global heading styles. Keep text, controls and focus indicators accessible when changing colors. Utility class names and internal markup are not a customization API.
87
+ By default, `.commerce-storefront` wrappers do not paint a background and inherit the host's text color. Set page and section backgrounds on the host application's layout elements. `--commerce-surface` colors controls and the opaque cart drawer, and supplies the base for muted colors; it does not color component wrappers. Set `--commerce-surface` and `--commerce-text` together to adapt controls and the drawer to a dark theme. Avoid setting wrapper backgrounds through CSS or the `theme` prop's `background`, `backgroundColor`, or `backgroundImage` properties, which can still override the transparent default. Descendants inherit the surface text and body font instead of global heading styles. Keep text, controls and focus indicators accessible when changing colors. Internal utility class names and markup are not a customization API; use the [product parts](#custom-product-layouts) to change a product page's layout.
88
88
 
89
- The first release uses English UI text and `en-US` currency formatting. Catalog title and description are configurable. Full localization and arbitrary component slots are outside this initial API.
89
+ The first release uses English UI text and `en-US` currency formatting. Catalog title and description are configurable. Full localization is outside this initial API.
90
90
 
91
91
  ## Compatibility
92
92
 
@@ -100,8 +100,10 @@ The repository example uses React Router 7. Follow each router version's own Rea
100
100
  | --- | --- |
101
101
  | `CommerceStorefront` | Recommended integration: provider and one drawer |
102
102
  | `Catalog` | Six products per cursor page, with `title`, `description`, and `showHeader` props |
103
+ | `CatalogRoot` and catalog parts | Build a [custom catalog or card layout](#custom-catalog-layouts) with the same rules as `Catalog` |
103
104
  | `ProductDetails` | Reads `:productId`; validates URL option selections against catalog results |
104
- | `ProductCard` | Renders one `SKUGroup` with direct add or a product-details link |
105
+ | `ProductDetailsRoot` and product parts | Build a [custom product layout](#custom-product-layouts) with the same rules as `ProductDetails` |
106
+ | `ProductCard` | Renders one `SKUGroup` with direct add or a product-details link; `ProductCardRoot` and card parts customize it |
105
107
  | `CartButton` | Opens the shared drawer and displays item count |
106
108
  | `AddToCartButton` | Adds a verified `sku`, `name`, and optional integer `quantity` |
107
109
  | `CommerceStatus` | Connection progress/error/retry for custom layouts |
@@ -112,6 +114,119 @@ The package exports TypeScript catalog/cart response types and selection/summary
112
114
 
113
115
  `Catalog` renders its `title` as an H1 by default. When the host page owns its semantic heading, render that page H1 and pass `showHeader={false}` so the document still has exactly one H1.
114
116
 
117
+ ## Custom product layouts
118
+
119
+ `ProductDetails` is the recommended product page. When its layout does not fit, compose the same parts inside `ProductDetailsRoot`. The root loads the route's `:productId` and shows the connection, loading, error and not-found states itself, so parts render only once the product exists. This is the packaged layout, written out:
120
+
121
+ ```tsx
122
+ import {
123
+ ProductDetailsBackLink, ProductDetailsDescription, ProductDetailsGallery, ProductDetailsPrice,
124
+ ProductDetailsPurchase, ProductDetailsRoot, ProductDetailsTitle,
125
+ } from '@godaddy/gd-commerce-storefront';
126
+
127
+ <ProductDetailsRoot>
128
+ <ProductDetailsBackLink className='mb-8 sm:mb-10' />
129
+ <div className='grid items-start gap-8 lg:grid-cols-12 lg:gap-12'>
130
+ <ProductDetailsGallery className='min-w-0 lg:col-span-7' />
131
+ <div className='min-w-0 lg:col-span-5 lg:py-4'>
132
+ <ProductDetailsTitle />
133
+ <ProductDetailsPrice className='mt-6' />
134
+ <ProductDetailsDescription className='my-8' />
135
+ <ProductDetailsPurchase className='border-t border-neutral-200 pt-8' />
136
+ </div>
137
+ </div>
138
+ </ProductDetailsRoot>
139
+ ```
140
+
141
+ The grid, spacing and border classes come from your own stylesheet in a custom layout. Without them, the parts stack in one column with no space between them.
142
+
143
+ Add your own elements between parts, reorder them, or leave out display parts. `ProductDetailsPurchase` renders the purchase parts below in order. Replace it with individual parts to place options apart from the add button:
144
+
145
+ | Part | Renders |
146
+ | --- | --- |
147
+ | `ProductDetailsOptions` | A select for every attribute, or the SKU list for products without attributes |
148
+ | `ProductDetailsOption` | A select for one attribute, by `attribute` name; nothing when the product lacks it |
149
+ | `ProductDetailsPurchaseStatus` | The one message explaining why the selection is not purchasable yet; nothing when ready |
150
+ | `ProductDetailsAvailability`, `ProductDetailsQuantity` | Stock and quantity for the verified SKU; nothing before verification |
151
+ | `ProductDetailsAddToCart` | Adds the verified SKU and quantity; before a SKU is verified, its accessible description gives the reason |
152
+
153
+ Every part is named `ProductDetails*` because it works only inside `ProductDetailsRoot`. `AddToCartButton` is the standalone button for a SKU you already have.
154
+
155
+ Parts read state from the root and take no product, SKU, price or quantity props. Whatever the layout, only a server-verified SKU can be added, and changing a selection resets the quantity and image. Every part throws if it is rendered outside `ProductDetailsRoot`. In development builds, if no control is rendered for an attribute the product requires, a console warning names the missing ones. A control that mounts later, such as one in a closed accordion, can trigger it; the product becomes purchasable once the control renders. Products without attributes but with several SKUs need `ProductDetailsOptions` or `ProductDetailsPurchase`. Parts can be rendered more than once, such as in a sticky mobile purchase bar; each copy gets its own element IDs.
156
+
157
+ Every part accepts `className`, which is added to the part's outer element, a wrapper the package's CSS reset leaves alone. Host classes there control margin, padding, border, color, width, display, gap and grid placement, including layered utilities such as Tailwind v4's. In `ProductDetailsOptions` and `ProductDetailsPurchase`, each control keeps a 24px bottom margin, even in a host grid. The exception is a class name the package also uses, such as `grid-cols-1` or `p-6`: the package's rule wins, even over the host's responsive variants on the same element, such as `md:grid-cols-4`. The packaged layout sets its spacing and grid placement this way. Elements inside the part, such as the title's `<h1>`, keep the package's own styles: a host font size on `ProductDetailsTitle` does not change the heading's size, but a host color does reach it, because the heading inherits its color.
158
+
159
+ Two hooks support custom parts inside the root:
160
+
161
+ - `useProductDetails()` returns read-only `product`, `name`, `selectedSku`, `quantity`, `availableQuantity`, `images` and `status` (`incomplete`, `checking`, `variant-error`, `unavailable`, `not-purchasable` or `ready`). `selectedSku` is set only when `status` is `ready`.
162
+ - `useProductDetailsOption(attribute)` returns `{ name, label, selected, values, select }` for building swatches or buttons, or `null` when the product has no such attribute. `select(value)` accepts only that attribute's value names, or `null` to clear. Other values are ignored. A hook-based control counts toward the layout check.
163
+
164
+ ```tsx
165
+ function ColorSwatches() {
166
+ const color = useProductDetailsOption('color');
167
+ if (!color) return null;
168
+ return (
169
+ <div role='group' aria-label={color.label}>
170
+ {color.values.map((value) => (
171
+ <button key={value.name} type='button' aria-pressed={value.selected} onClick={() => color.select(value.name)}>
172
+ {value.label}
173
+ </button>
174
+ ))}
175
+ </div>
176
+ );
177
+ }
178
+ ```
179
+
180
+ Parts are flat named exports, not properties such as `ProductDetails.Title`, so each one is an ordinary module export.
181
+
182
+ ## Custom catalog layouts
183
+
184
+ `Catalog` is the recommended catalog. When its layout or its cards do not fit, compose the same parts inside `CatalogRoot`. The root loads one cursor page of six products, or the built-in samples when `sampleProducts` is set and no store is connected, and shows the connection state itself. This is `<Catalog sampleProducts />` written out with its packaged card:
185
+
186
+ ```tsx
187
+ import {
188
+ CatalogHeader, CatalogPagination, CatalogProducts, CatalogRoot, CatalogSummary, ProductCardAction,
189
+ ProductCardDescription, ProductCardImage, ProductCardPrice, ProductCardRoot, ProductCardTitle,
190
+ } from '@godaddy/gd-commerce-storefront';
191
+
192
+ <CatalogRoot sampleProducts>
193
+ <CatalogHeader className='border-b border-neutral-200 pb-10 pt-4 sm:pb-14 sm:pt-8' />
194
+ <CatalogSummary className='border-b border-neutral-200 py-6 sm:py-8' />
195
+ <CatalogProducts className='grid grid-cols-1 gap-6 py-8 sm:grid-cols-2 lg:grid-cols-3 lg:gap-8 lg:py-10'>
196
+ <ProductCardRoot className='flex min-w-0 flex-col overflow-hidden rounded-lg border border-neutral-200'>
197
+ <ProductCardImage />
198
+ <div className='flex flex-1 flex-col p-6'>
199
+ <ProductCardTitle />
200
+ <ProductCardDescription className='mt-3' />
201
+ <div className='mt-auto pt-6'>
202
+ <div className='flex flex-wrap items-end justify-between gap-4 border-t border-neutral-200 pt-5'>
203
+ <ProductCardPrice className='min-w-0 flex-1' />
204
+ <ProductCardAction className='max-w-full' />
205
+ </div>
206
+ </div>
207
+ </div>
208
+ </ProductCardRoot>
209
+ </CatalogProducts>
210
+ <CatalogPagination className='border-t border-neutral-200 pt-6' />
211
+ </CatalogRoot>
212
+ ```
213
+
214
+ As with product layouts, the grid, spacing and border classes come from your own stylesheet in a custom layout. Without them, the cards stack in one column.
215
+
216
+ | Part | Renders |
217
+ | --- | --- |
218
+ | `CatalogHeader` | The `title` as the page's H1 and a `description`; leave it out when the host page owns the H1 |
219
+ | `CatalogSummary` | The loading, failure or product-count status line |
220
+ | `CatalogProducts` | One card per product. Its children are the card, rendered once for each product; without children, the packaged card |
221
+ | `CatalogPagination` | First-page and next-page buttons; nothing for samples |
222
+ | `ProductCardImage`, `ProductCardTitle` | The first image and the name as an H2, each linked to the product page. With a title in the card, keyboard and screen reader users get only the title link; without one, the image link takes its place once the page is interactive |
223
+ | `ProductCardDescription`, `ProductCardPrice` | Up to three lines of description (nothing without one), and the price or price range |
224
+ | `ProductCardAction` | Adds the product directly only when it has one SKU and no options; otherwise links to the product page to choose |
225
+
226
+ `className` on `CatalogProducts` goes on the element whose direct children are the cards, so a host grid places them, and `className` on `ProductCardRoot` goes on each card, so classes such as `col-span-2` work. The loading placeholder (three cards, one to three columns), the error with its retry button, and the empty message render just before that element, whatever the layout. Card parts take no product, SKU or price props. Inside `CatalogProducts`, `ProductCardRoot` takes no `product` prop either and throws if it gets one, so a card always shows the product it is rendered for. Samples use the same card: they show a placeholder image, no description and no links, and add only to the sample cart. Card and catalog parts throw if they are rendered outside their root. Packaged cards fill their grid row, with the price and action at the bottom of each card.
227
+
228
+ For a product the host already has, such as a featured product, use `ProductCard` or `ProductCardRoot` with a `product` prop outside the catalog. `useProductCard()` returns read-only `product` (`null` for samples), `name`, `href` (`null` for samples) and `isSample` for building custom card parts. Every part accepts `className` on an outer wrapper that the package's CSS reset leaves alone, with the same limits as [product parts](#custom-product-layouts).
229
+
115
230
  ## How it works
116
231
 
117
232
  Products are SKU groups. The package purchases only an unambiguous SKU, verifies all selected attributes through the server, uses SKU prices/images, and distinguishes untracked inventory from sold-out inventory. Server-side inventory and pricing checks remain mandatory.
package/dist/index.d.ts CHANGED
@@ -301,6 +301,8 @@ declare function getAvailableInventoryQuantity(item: InventoryCountContainer | n
301
301
  declare function getImageUrls(item: MediaObjectContainer | null | undefined): string[];
302
302
  declare function getPrimaryImageUrl(item: MediaObjectContainer | null | undefined): string | null;
303
303
  declare function getProductAttributes(skuGroup: SKUGroup | null | undefined): StorefrontProductAttribute[];
304
+ /** The product's display name: its label, then its name. */
305
+ declare function getProductName(skuGroup: SKUGroup): string;
304
306
  //#endregion
305
307
  //#region src/cart.d.ts
306
308
  declare function CartButton(): ReactElement;
@@ -316,11 +318,53 @@ declare function AddToCartButton({
316
318
  declare function CartDrawer(): ReactElement;
317
319
  //#endregion
318
320
  //#region src/catalog.d.ts
319
- declare function ProductCard({
320
- product
321
- }: {
322
- product: SKUGroup;
323
- }): ReactElement;
321
+ /** Props shared by every catalog part. `className` is added to the part's outer element. */
322
+ interface CatalogPartProps {
323
+ className?: string;
324
+ }
325
+ interface CatalogRootProps {
326
+ children: ReactNode;
327
+ /** Added to the root `<section>`. */
328
+ className?: string;
329
+ /** Permit built-in examples only while the host confirms this site is unbound. */
330
+ sampleProducts?: boolean;
331
+ }
332
+ /** Loads one cursor page of products, or the built-in samples, and provides them to catalog parts. */
333
+ declare function CatalogRoot({
334
+ children,
335
+ className,
336
+ sampleProducts
337
+ }: CatalogRootProps): ReactElement;
338
+ interface CatalogHeaderProps extends CatalogPartProps {
339
+ title?: string;
340
+ description?: string;
341
+ }
342
+ /** The catalog title as the page's H1, with a description. */
343
+ declare function CatalogHeader({
344
+ title,
345
+ description,
346
+ className
347
+ }: CatalogHeaderProps): ReactElement;
348
+ /** Announces loading, failure, or how many products the page shows. */
349
+ declare function CatalogSummary({
350
+ className
351
+ }: CatalogPartProps): ReactElement;
352
+ interface CatalogProductsProps extends CatalogPartProps {
353
+ /** One card, rendered for every product. Defaults to the packaged card. */
354
+ children?: ReactNode;
355
+ }
356
+ /**
357
+ * The product cards. `className` goes on the element that contains the cards, such as a grid. The loading
358
+ * placeholder, the error with its retry, and the empty message render just before that element.
359
+ */
360
+ declare function CatalogProducts({
361
+ className,
362
+ children
363
+ }: CatalogProductsProps): ReactElement;
364
+ /** First-page and next-page buttons. Renders nothing for samples, which have one page. */
365
+ declare function CatalogPagination({
366
+ className
367
+ }: CatalogPartProps): ReactElement | null;
324
368
  interface CatalogProps {
325
369
  title?: string;
326
370
  description?: string;
@@ -328,7 +372,13 @@ interface CatalogProps {
328
372
  /** Permit built-in examples only while the host confirms this site is unbound. */
329
373
  sampleProducts?: boolean;
330
374
  }
331
- declare function Catalog(props: CatalogProps): ReactElement;
375
+ /** The packaged catalog. Compose `CatalogRoot` and the catalog parts for a custom layout. */
376
+ declare function Catalog({
377
+ title,
378
+ description,
379
+ showHeader,
380
+ sampleProducts
381
+ }: CatalogProps): ReactElement;
332
382
  //#endregion
333
383
  //#region src/commerce-provider.d.ts
334
384
  interface CommerceContextValue {
@@ -387,10 +437,178 @@ declare function CommerceStorefront({
387
437
  ...props
388
438
  }: CommerceProviderProps): react_jsx_runtime0.JSX.Element;
389
439
  //#endregion
440
+ //#region src/product-card.d.ts
441
+ /** Read-only card state for custom parts rendered inside `ProductCardRoot`. */
442
+ interface ProductCardState {
443
+ /** `null` for a built-in sample, which is not a catalog product. */
444
+ readonly product: SKUGroup | null;
445
+ readonly name: string;
446
+ /** The product page, or `null` for a sample, which has none. */
447
+ readonly href: string | null;
448
+ readonly isSample: boolean;
449
+ }
450
+ /** Props shared by every card part. `className` is added to the part's outer element. */
451
+ interface ProductCardPartProps {
452
+ className?: string;
453
+ }
454
+ /** Read the card's product, name, and link from inside `ProductCardRoot`. */
455
+ declare function useProductCard(): ProductCardState;
456
+ interface ProductCardRootProps {
457
+ children: ReactNode;
458
+ /** The catalog product to show. Leave it out inside `CatalogProducts`, which supplies each product. */
459
+ product?: SKUGroup;
460
+ /** Added to the root `<article>`. */
461
+ className?: string;
462
+ }
463
+ /** Provides one product to card parts. Inside `CatalogProducts` it renders the current catalog entry. */
464
+ declare function ProductCardRoot({
465
+ children,
466
+ product,
467
+ className
468
+ }: ProductCardRootProps): ReactElement;
469
+ /**
470
+ * The product's first image, linked to its page. Samples show a placeholder. With a `ProductCardTitle` in the card,
471
+ * the title is the one link keyboard and screen reader users get; without one, the image link is.
472
+ */
473
+ declare function ProductCardImage({
474
+ className
475
+ }: ProductCardPartProps): ReactElement;
476
+ /** The product name as an H2, linked to its page. */
477
+ declare function ProductCardTitle({
478
+ className
479
+ }: ProductCardPartProps): ReactElement;
480
+ /** Up to three lines of the product description. Renders nothing without one. */
481
+ declare function ProductCardDescription({
482
+ className
483
+ }: ProductCardPartProps): ReactElement | null;
484
+ /** The product's price, or its price range when variants differ. */
485
+ declare function ProductCardPrice({
486
+ className
487
+ }: ProductCardPartProps): ReactElement;
488
+ /**
489
+ * Adds the product directly when it has exactly one SKU and no options; otherwise links to its page to choose.
490
+ * Samples add to the sample cart.
491
+ */
492
+ declare function ProductCardAction({
493
+ className
494
+ }: ProductCardPartProps): ReactElement;
495
+ interface ProductCardProps {
496
+ product: SKUGroup;
497
+ }
498
+ /** The packaged card for one `SKUGroup`. Compose `ProductCardRoot` and the card parts for a custom card. */
499
+ declare function ProductCard({
500
+ product
501
+ }: ProductCardProps): ReactElement;
502
+ //#endregion
503
+ //#region src/product-details-context.d.ts
504
+ /** Where the shopper is in choosing a purchasable SKU. Only `ready` has a verified `selectedSku`. */
505
+ type ProductDetailsStatus = 'incomplete' | 'checking' | 'variant-error' | 'unavailable' | 'not-purchasable' | 'ready';
506
+ /** Read-only product state for custom parts rendered inside `ProductDetailsRoot`. */
507
+ interface ProductDetailsState {
508
+ readonly product: SKUGroup;
509
+ readonly name: string;
510
+ /** Set only after the server verifies the full selection. */
511
+ readonly selectedSku: SKU | null;
512
+ readonly quantity: number;
513
+ /** `null` means inventory is not tracked; `0` means sold out. */
514
+ readonly availableQuantity: number | null;
515
+ readonly status: ProductDetailsStatus;
516
+ readonly images: readonly string[];
517
+ }
518
+ /** Props shared by every product part. `className` is added to the part's outer element. */
519
+ interface ProductDetailsPartProps {
520
+ className?: string;
521
+ }
522
+ /** Read the current product, verified SKU, and purchase status from inside `ProductDetailsRoot`. */
523
+ declare function useProductDetails(): ProductDetailsState;
524
+ interface ProductDetailsOptionValueState {
525
+ readonly name: string;
526
+ readonly label: string;
527
+ readonly selected: boolean;
528
+ }
529
+ interface ProductDetailsOptionState {
530
+ readonly name: string;
531
+ readonly label: string;
532
+ readonly selected: string | null;
533
+ readonly values: readonly ProductDetailsOptionValueState[];
534
+ /** Accepts only this attribute's own value names, or `null` to clear. Other values are ignored. */
535
+ readonly select: (value: string | null) => void;
536
+ }
537
+ /**
538
+ * Build a custom control for one product attribute. Returns `null` when the product has no such attribute.
539
+ * A selection is never purchasable until the server verifies it.
540
+ */
541
+ declare function useProductDetailsOption(attribute: string): ProductDetailsOptionState | null;
542
+ interface ProductDetailsRootProps {
543
+ children: ReactNode;
544
+ /** Added to the root `<article>`. */
545
+ className?: string;
546
+ }
547
+ /** Loads the product for the route's `:productId` and provides state to product parts. */
548
+ declare function ProductDetailsRoot({
549
+ children,
550
+ className
551
+ }: ProductDetailsRootProps): ReactElement;
552
+ //#endregion
390
553
  //#region src/product-details.d.ts
554
+ /** The packaged product page for `${productPath}/:productId`. Compose the parts for a custom layout. */
391
555
  declare function ProductDetails(): ReactElement;
556
+ declare function ProductDetailsBackLink({
557
+ className
558
+ }: ProductDetailsPartProps): ReactElement;
559
+ /** Main image with thumbnails; the selected SKU's images replace the product's when present. */
560
+ declare function ProductDetailsGallery({
561
+ className
562
+ }: ProductDetailsPartProps): ReactElement;
563
+ /** The product name as the page's H1. */
564
+ declare function ProductDetailsTitle({
565
+ className
566
+ }: ProductDetailsPartProps): ReactElement;
567
+ /** The verified SKU's price and compare-at price, or the product's starting price. */
568
+ declare function ProductDetailsPrice({
569
+ className
570
+ }: ProductDetailsPartProps): ReactElement;
571
+ /** The verified SKU's description, or the product's. */
572
+ declare function ProductDetailsDescription({
573
+ className
574
+ }: ProductDetailsPartProps): ReactElement;
575
+ //#endregion
576
+ //#region src/product-purchase.d.ts
577
+ /** The packaged purchase area: options, status, availability, quantity, and add to cart. */
578
+ declare function ProductDetailsPurchase({
579
+ className
580
+ }: ProductDetailsPartProps): ReactElement;
581
+ /** A select for every product attribute, or the SKU list for products without attributes. */
582
+ declare function ProductDetailsOptions({
583
+ className
584
+ }: ProductDetailsPartProps): ReactElement | null;
585
+ interface ProductDetailsOptionProps extends ProductDetailsPartProps {
586
+ /** The attribute `name`, such as `color`. Renders nothing when the product has no such attribute. */
587
+ attribute: string;
588
+ }
589
+ /** A select for one product attribute. Use `useProductDetailsOption` for swatches or other custom controls. */
590
+ declare function ProductDetailsOption({
591
+ attribute,
592
+ className
593
+ }: ProductDetailsOptionProps): ReactElement | null;
594
+ /** The single message explaining why the selection is not yet purchasable. Renders nothing when ready. */
595
+ declare function ProductDetailsPurchaseStatus({
596
+ className
597
+ }: ProductDetailsPartProps): ReactElement | null;
598
+ /** Stock for the verified SKU. Renders nothing until a SKU is verified. */
599
+ declare function ProductDetailsAvailability({
600
+ className
601
+ }: ProductDetailsPartProps): ReactElement | null;
602
+ /** Quantity for the verified SKU. Renders nothing until a SKU is verified. */
603
+ declare function ProductDetailsQuantity({
604
+ className
605
+ }: ProductDetailsPartProps): ReactElement | null;
606
+ /** Adds the verified SKU and quantity. While disabled, its accessible description says why. */
607
+ declare function ProductDetailsAddToCart({
608
+ className
609
+ }: ProductDetailsPartProps): ReactElement;
392
610
  //#endregion
393
611
  //#region src/storefront-surface.d.ts
394
612
  declare function CommerceStatus(): ReactElement | null;
395
613
  //#endregion
396
- export { AddToCartButton, AddToCartItemInput, ApiError, CartAddress, CartButton, CartDiscount, CartDrawer, CartLineItem, CartLineItemDetails, CartNote, CartOrder, CartSelectedAddon, CartSelectedAddonValue, CartSelectedOption, CartShippingInfo, CartSummaryTotals, CartTax, Catalog, type CatalogProps, type CommerceContextValue, CommerceProvider, type CommerceProviderProps, CommerceStatus, CommerceStorefront, Connection, ConnectionEdge, DraftOrderContext, InventoryCount, LabelFilter, LineItemTotals, MediaObject, Money, OrderTotals, PageInfo, PriceRange, ProductCard, ProductDetails, ProductDetailsVariablesInput, ProductGridVariablesInput, SKU, SKUAttributeValue, SKUGroup, SKUGroupAttribute, SKUGroupAttributeValue, SKUGroupSKU, SKUPrice, SkuGroupResult, SkuGroupVariables, SkuGroupsResult, SkuGroupsVariables, SkuResult, SkuVariables, type StorefrontConfig, StorefrontProductAttribute, StorefrontProductAttributeValue, type StorefrontTheme, StringInFilter, addToCart, getAvailableInventoryQuantity, getCartSummaryTotals, getImageUrls, getLabeledSkuOptions, getPrimaryImageUrl, getProductAttributes, getSingleMatchedSku, getSingleMatchedSkuId, money, useCommerce };
614
+ export { AddToCartButton, AddToCartItemInput, ApiError, CartAddress, CartButton, CartDiscount, CartDrawer, CartLineItem, CartLineItemDetails, CartNote, CartOrder, CartSelectedAddon, CartSelectedAddonValue, CartSelectedOption, CartShippingInfo, CartSummaryTotals, CartTax, Catalog, CatalogHeader, type CatalogHeaderProps, CatalogPagination, type CatalogPartProps, CatalogProducts, type CatalogProductsProps, type CatalogProps, CatalogRoot, type CatalogRootProps, CatalogSummary, type CommerceContextValue, CommerceProvider, type CommerceProviderProps, CommerceStatus, CommerceStorefront, Connection, ConnectionEdge, DraftOrderContext, InventoryCount, LabelFilter, LineItemTotals, MediaObject, Money, OrderTotals, PageInfo, PriceRange, ProductCard, ProductCardAction, ProductCardDescription, ProductCardImage, type ProductCardPartProps, ProductCardPrice, type ProductCardProps, ProductCardRoot, type ProductCardRootProps, type ProductCardState, ProductCardTitle, ProductDetails, ProductDetailsAddToCart, ProductDetailsAvailability, ProductDetailsBackLink, ProductDetailsDescription, ProductDetailsGallery, ProductDetailsOption, type ProductDetailsOptionProps, type ProductDetailsOptionState, type ProductDetailsOptionValueState, ProductDetailsOptions, type ProductDetailsPartProps, ProductDetailsPrice, ProductDetailsPurchase, ProductDetailsPurchaseStatus, ProductDetailsQuantity, ProductDetailsRoot, type ProductDetailsRootProps, type ProductDetailsState, type ProductDetailsStatus, ProductDetailsTitle, ProductDetailsVariablesInput, ProductGridVariablesInput, SKU, SKUAttributeValue, SKUGroup, SKUGroupAttribute, SKUGroupAttributeValue, SKUGroupSKU, SKUPrice, SkuGroupResult, SkuGroupVariables, SkuGroupsResult, SkuGroupsVariables, SkuResult, SkuVariables, type StorefrontConfig, StorefrontProductAttribute, StorefrontProductAttributeValue, type StorefrontTheme, StringInFilter, addToCart, getAvailableInventoryQuantity, getCartSummaryTotals, getImageUrls, getLabeledSkuOptions, getPrimaryImageUrl, getProductAttributes, getProductName, getSingleMatchedSku, getSingleMatchedSkuId, money, useCommerce, useProductCard, useProductDetails, useProductDetailsOption };