@godaddy/gd-commerce-storefront 0.5.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -13,7 +13,8 @@ declare class ApiError extends Error {
13
13
  readonly status: number;
14
14
  constructor(message: string, status: number, options?: ErrorOptions);
15
15
  }
16
- declare function money(value: number, currency: string): string;
16
+ /** Formats minor units, such as cents, as currency. Inside the provider, prefer `useMoney`, which follows its `locale`. */
17
+ declare function money(value: number, currency: string, locale?: string): string;
17
18
  //#endregion
18
19
  //#region src/cart-model.d.ts
19
20
  interface Money {
@@ -303,18 +304,60 @@ declare function getPrimaryImageUrl(item: MediaObjectContainer | null | undefine
303
304
  declare function getProductAttributes(skuGroup: SKUGroup | null | undefined): StorefrontProductAttribute[];
304
305
  /** The product's display name: its label, then its name. */
305
306
  declare function getProductName(skuGroup: SKUGroup): string;
307
+ /** Lowercases a label for use mid-sentence, leaving acronyms alone: "Size" becomes "size", "US Size" stays. */
308
+ declare const inSentence: (label: string) => string;
309
+ /** Whether `compareAt` is above `price`, so the price is a sale price. */
310
+ declare function isOnSale(price: number | null | undefined, compareAt: number | null | undefined): boolean;
311
+ /**
312
+ * Whether some SKU's compare-at price is above that SKU's own price. Without every SKU's price, only a product whose
313
+ * lowest compare-at price is above its highest price is certainly on sale, so other products show no badge.
314
+ */
315
+ declare function isProductOnSale(product: SKUGroup | null | undefined): boolean;
316
+ /**
317
+ * The compare-at price that belongs with the product's starting price, so a struck-through price never pairs one
318
+ * SKU's price with another SKU's compare-at price. With every SKU and its price loaded, the cheapest SKUs must share
319
+ * one compare-at price above their price. Otherwise the product needs a single price and a single compare-at price.
320
+ */
321
+ declare function getStartingCompareAt(product: SKUGroup | null | undefined): number | null;
322
+ /** The SKU's attribute value names, or `null` when the response does not include them. */
323
+ declare function getSkuAttributeValueNames(sku: SKU | null | undefined): string[] | null;
324
+ //#endregion
325
+ //#region src/part.d.ts
326
+ /** Replacement content for a part's text: content, or a function of the part's state. */
327
+ type PartLabel<State> = ReactNode | ((state: State) => ReactNode);
306
328
  //#endregion
307
329
  //#region src/cart.d.ts
308
- declare function CartButton(): ReactElement;
309
- declare function AddToCartButton({
310
- sku,
311
- name,
312
- quantity
313
- }: {
330
+ interface CartButtonProps {
331
+ /**
332
+ * Replaces the bag icon and count badge with a visible label. A function receives the item count. Keep the count in
333
+ * the label.
334
+ */
335
+ children?: PartLabel<{
336
+ itemCount: number;
337
+ }>;
338
+ }
339
+ /**
340
+ * Opens the cart drawer: a bag icon with a count badge that pops when the count changes. Its accessible name is
341
+ * "Cart, 2 items". With `children`, a labeled button instead.
342
+ */
343
+ declare function CartButton({
344
+ children
345
+ }?: CartButtonProps): ReactElement;
346
+ /** What an add-to-cart label can depend on. */
347
+ interface AddToCartLabelState {
348
+ /** The add is running. */
349
+ readonly busy: boolean;
350
+ /** Tracked stock is used up, so the button stays disabled. */
351
+ readonly soldOut: boolean;
352
+ }
353
+ interface AddToCartButtonProps {
314
354
  sku: SKU;
315
355
  name: string;
316
356
  quantity?: number;
317
- }): ReactElement;
357
+ /** Replaces the label. A function receives `busy` and `soldOut`; the button keeps its rules either way. */
358
+ children?: PartLabel<AddToCartLabelState>;
359
+ }
360
+ declare function AddToCartButton(props: AddToCartButtonProps): ReactElement;
318
361
  //#endregion
319
362
  //#region src/cart-state.d.ts
320
363
  /** One cart line, for custom cart parts. */
@@ -351,6 +394,20 @@ declare function useCart(): CartState;
351
394
  interface CartPartProps {
352
395
  className?: string;
353
396
  }
397
+ /** Props for a cart part whose text the host can replace, with or without the sample wording. */
398
+ interface CartTextPartProps extends CartPartProps {
399
+ /** Replaces the text. A function receives whether the cart is the sample cart. */
400
+ children?: PartLabel<{
401
+ isSample: boolean;
402
+ }>;
403
+ }
404
+ /** Props for a cart button whose label the host can replace. The button keeps its behavior and state. */
405
+ interface CartActionPartProps extends CartPartProps {
406
+ /** Replaces the button label. A function receives whether the action is running. */
407
+ children?: PartLabel<{
408
+ busy: boolean;
409
+ }>;
410
+ }
354
411
  interface CartRootProps {
355
412
  children: ReactNode;
356
413
  /** Added to the root `<section>`. */
@@ -378,14 +435,19 @@ declare function CartDrawerRoot({
378
435
  children,
379
436
  className
380
437
  }: CartDrawerRootProps): ReactElement;
381
- /** "Your cart", or "Sample cart" before a store is connected, as an H2. In the drawer it names the dialog. */
438
+ /**
439
+ * "Your cart", or "Sample cart" before a store is connected, as an H2, with the item count once there are items.
440
+ * In the drawer it names the dialog.
441
+ */
382
442
  declare function CartTitle({
383
- className
384
- }: CartPartProps): ReactElement;
443
+ className,
444
+ children
445
+ }: CartTextPartProps): ReactElement;
385
446
  /** One line about the cart. In the drawer it describes the dialog. */
386
447
  declare function CartDescription({
387
- className
388
- }: CartPartProps): ReactElement;
448
+ className,
449
+ children
450
+ }: CartTextPartProps): ReactElement;
389
451
  /** The drawer's close button. Renders nothing outside the drawer. */
390
452
  declare function CartClose({
391
453
  className
@@ -426,7 +488,7 @@ declare function CartItemImage({
426
488
  declare function CartItemName({
427
489
  className
428
490
  }: CartPartProps): ReactElement;
429
- /** The selected options, one per line, such as "Color: Blue". Renders nothing without options. */
491
+ /** The selected options on one line, such as "Color: Blue · Size: M". Renders nothing without options. */
430
492
  declare function CartItemOptions({
431
493
  className
432
494
  }: CartPartProps): ReactElement | null;
@@ -440,8 +502,9 @@ declare function CartItemQuantity({
440
502
  }: CartPartProps): ReactElement;
441
503
  /** Removes the line. */
442
504
  declare function CartItemRemove({
443
- className
444
- }: CartPartProps): ReactElement;
505
+ className,
506
+ children
507
+ }: CartActionPartProps): ReactElement;
445
508
  interface CartEmptyProps extends CartPartProps {
446
509
  /** Replaces the default message and link. */
447
510
  children?: ReactNode;
@@ -464,7 +527,7 @@ declare function CartSubtotal({
464
527
  className
465
528
  }: CartPartProps): ReactElement | null;
466
529
  /**
467
- * "Shipping, taxes, and discounts are calculated at checkout." Has the stable
530
+ * A row under the subtotal: "Shipping, taxes & discounts", "Calculated at checkout". Has the stable
468
531
  * `commerce-cart-checkout-adjustments-note` class. Renders nothing for samples or an empty cart.
469
532
  */
470
533
  declare function CartCheckoutNote({
@@ -475,8 +538,17 @@ declare function CartCheckoutNote({
475
538
  * Samples never check out. Renders nothing for an empty cart.
476
539
  */
477
540
  declare function CartCheckout({
478
- className
479
- }: CartPartProps): ReactElement | null;
541
+ className,
542
+ children
543
+ }: CartActionPartProps): ReactElement | null;
544
+ /**
545
+ * "Continue shopping": closes the drawer, or on a cart page links to the catalog. Renders nothing for an empty cart,
546
+ * whose `CartEmpty` links to the catalog.
547
+ */
548
+ declare function CartContinueShopping({
549
+ className,
550
+ children
551
+ }: CartTextPartProps): ReactElement | null;
480
552
  /** The packaged cart drawer. Compose `CartDrawerRoot` and the cart parts for a custom drawer. */
481
553
  declare function CartDrawer(): ReactElement;
482
554
  //#endregion
@@ -491,12 +563,21 @@ interface CatalogRootProps {
491
563
  className?: string;
492
564
  /** Permit built-in examples only while the host confirms this site is unbound. */
493
565
  sampleProducts?: boolean;
566
+ /** Products per page, a whole number of 1 or more. Defaults to 6. Samples are always one page of six. */
567
+ pageSize?: number;
568
+ /**
569
+ * Keep the page cursor in the page URL, as `after`, so a reload or a shared link keeps the page. Defaults to
570
+ * `true`. Set `false` for every other catalog on the same page, so the catalogs do not share one cursor.
571
+ */
572
+ urlState?: boolean;
494
573
  }
495
574
  /** Loads one cursor page of products, or the built-in samples, and provides them to catalog parts. */
496
575
  declare function CatalogRoot({
497
576
  children,
498
577
  className,
499
- sampleProducts
578
+ sampleProducts,
579
+ pageSize,
580
+ urlState
500
581
  }: CatalogRootProps): ReactElement;
501
582
  interface CatalogHeaderProps extends CatalogPartProps {
502
583
  title?: string;
@@ -518,13 +599,27 @@ interface CatalogProductsProps extends CatalogPartProps {
518
599
  }
519
600
  /**
520
601
  * The product cards. `className` goes on the element that contains the cards, such as a grid. While loading, that
521
- * element holds placeholder cards. The error with its retry and the empty message render just before it.
602
+ * element holds placeholder cards. The error with its retry and, without a `CatalogEmpty`, the empty message render just before it.
522
603
  */
523
604
  declare function CatalogProducts({
524
605
  className,
525
606
  children
526
607
  }: CatalogProductsProps): ReactElement;
527
- /** First-page and next-page buttons. Renders nothing for samples, which have one page. */
608
+ interface CatalogEmptyProps extends CatalogPartProps {
609
+ /** Replaces the default message. */
610
+ children?: ReactNode;
611
+ }
612
+ /**
613
+ * Renders only when a connected store's catalog has no products: "No products available.", or its children. While
614
+ * one is mounted, `CatalogProducts` leaves out its own empty message. Samples are never empty.
615
+ */
616
+ declare function CatalogEmpty({
617
+ className,
618
+ children
619
+ }: CatalogEmptyProps): ReactElement | null;
620
+ /**
621
+ * First-page and next-page buttons. Renders nothing when there is only one page, including for samples.
622
+ */
528
623
  declare function CatalogPagination({
529
624
  className
530
625
  }: CatalogPartProps): ReactElement | null;
@@ -537,13 +632,16 @@ interface CatalogProps {
537
632
  showHeader?: boolean;
538
633
  /** Permit built-in examples only while the host confirms this site is unbound. */
539
634
  sampleProducts?: boolean;
635
+ /** Products per page. Defaults to 6. */
636
+ pageSize?: number;
540
637
  }
541
638
  /** The packaged catalog. Compose `CatalogRoot` and the catalog parts for a custom layout. */
542
639
  declare function Catalog({
543
640
  title,
544
641
  description,
545
642
  showHeader,
546
- sampleProducts
643
+ sampleProducts,
644
+ pageSize
547
645
  }: CatalogProps): ReactElement;
548
646
  //#endregion
549
647
  //#region src/commerce-provider.d.ts
@@ -552,7 +650,11 @@ interface CommerceContextValue {
552
650
  connectionError: string | null;
553
651
  retryConnection: () => void;
554
652
  theme: StorefrontTheme;
653
+ /** The host's swatch lookup, or `undefined` when options render as buttons. */
654
+ getSwatch: GetSwatch | undefined;
555
655
  config: StorefrontConfig;
656
+ /** The BCP 47 locale that prices are formatted in, such as `en-US`. */
657
+ locale: string;
556
658
  cart: CartOrder | null;
557
659
  /** Whether the cart drawer is open. Always `false` when no `CartDrawer` or `CartDrawerRoot` is mounted. */
558
660
  open: boolean;
@@ -573,6 +675,11 @@ interface CommerceContextValue {
573
675
  checkout: () => Promise<boolean>;
574
676
  }
575
677
  declare function useCommerce(): CommerceContextValue;
678
+ /**
679
+ * Formats minor units, such as cents, in the provider's `locale`, the way the package's own parts do. Uses the
680
+ * store's currency unless `currency` is given.
681
+ */
682
+ declare function useMoney(): (value: number, currency?: string) => string;
576
683
  type StorefrontTheme = CSSProperties & {
577
684
  '--commerce-accent'?: string;
578
685
  '--commerce-accent-hover'?: string;
@@ -580,21 +687,83 @@ type StorefrontTheme = CSSProperties & {
580
687
  '--commerce-surface'?: string;
581
688
  '--commerce-text'?: string;
582
689
  '--commerce-radius'?: string;
690
+ /** Fills the Sale badge. Defaults to a red that white text reads on. */
691
+ '--commerce-sale'?: string;
692
+ /** Text on the Sale badge. Defaults to white. */
693
+ '--commerce-on-sale'?: string;
583
694
  };
695
+ /** The attribute value a host can give a swatch, such as `{ attribute: 'color', name: 'forest', label: 'Forest' }`. */
696
+ interface SwatchValue {
697
+ readonly attribute: string;
698
+ readonly name: string;
699
+ readonly label: string;
700
+ }
701
+ /**
702
+ * Returns a CSS `background` for a value, such as `'#3f6352'` or `'url(/swatches/linen.png) center / cover'`, or
703
+ * nothing for no swatch. An attribute shows swatches only when every value has one.
704
+ */
705
+ type GetSwatch = (value: SwatchValue) => string | null | undefined;
584
706
  interface CommerceProviderProps {
585
707
  children: ReactNode;
586
708
  catalogPath?: string;
587
709
  productPath?: string;
588
710
  /** Applied to storefront surfaces and the portalled cart drawer. */
589
711
  theme?: StorefrontTheme;
712
+ /**
713
+ * Swatches for attribute values, off by default. Attributes whose values all have a swatch render as swatches on
714
+ * the product page, and cards show them as dots. See `GetSwatch`.
715
+ */
716
+ getSwatch?: GetSwatch;
590
717
  /** Set only when your server has enabled checkout and this return route exists. */
591
718
  checkoutSuccessPath?: string;
719
+ /**
720
+ * The BCP 47 locale for formatting prices, such as `de-DE`. Defaults to `en-US`; an invalid tag falls back to it.
721
+ * It never selects UI text: localized text will be a separate, opt-in prop, so setting `locale` cannot change wording.
722
+ */
723
+ locale?: string;
592
724
  /**
593
725
  * Called after an item is added, live or sample. With a drawer mounted, the drawer also opens. Without one, such as
594
726
  * on a site with a cart page, use it to confirm the add.
595
727
  */
596
728
  onItemAdded?: (item: AddedCartItem) => void;
729
+ /** Called for every cart change and failure, such as for analytics. See `CommerceEvent`. */
730
+ onEvent?: (event: CommerceEvent) => void;
597
731
  }
732
+ /** A cart operation that can fail. */
733
+ type CommerceOperation = 'add' | 'change-quantity' | 'remove' | 'discount' | 'refresh' | 'checkout';
734
+ /**
735
+ * What `onEvent` reports. Live changes are reported once the server returns the updated cart; sample changes have
736
+ * `isSample: true` and never reach the store. New event types may be added, so ignore types you do not handle.
737
+ */
738
+ type CommerceEvent = {
739
+ readonly type: 'item-added';
740
+ /** `null` for a sample product, which is not a SKU. */
741
+ readonly skuId: string | null;
742
+ readonly name: string;
743
+ readonly quantity: number;
744
+ readonly isSample: boolean;
745
+ } | {
746
+ readonly type: 'quantity-changed';
747
+ readonly itemId: string;
748
+ readonly quantity: number;
749
+ readonly isSample: boolean;
750
+ } | {
751
+ readonly type: 'item-removed';
752
+ readonly itemId: string;
753
+ readonly isSample: boolean;
754
+ } | {
755
+ readonly type: 'discount-applied';
756
+ readonly code: string;
757
+ }
758
+ /** Sent just before the browser leaves for checkout. */ | {
759
+ readonly type: 'checkout-started';
760
+ readonly cartId: string;
761
+ }
762
+ /** `message` is the one the cart shows. */ | {
763
+ readonly type: 'error';
764
+ readonly operation: CommerceOperation;
765
+ readonly message: string;
766
+ };
598
767
  /** The item passed to `onItemAdded`. */
599
768
  interface AddedCartItem {
600
769
  readonly name: string;
@@ -608,7 +777,10 @@ declare function CommerceProvider({
608
777
  productPath,
609
778
  checkoutSuccessPath,
610
779
  theme,
611
- onItemAdded
780
+ getSwatch,
781
+ locale,
782
+ onItemAdded,
783
+ onEvent
612
784
  }: CommerceProviderProps): ReactElement;
613
785
  //#endregion
614
786
  //#region src/commerce-storefront.d.ts
@@ -619,6 +791,22 @@ declare function CommerceStorefront({
619
791
  }: CommerceProviderProps): react_jsx_runtime0.JSX.Element;
620
792
  //#endregion
621
793
  //#region src/product-card.d.ts
794
+ interface ProductImageProps {
795
+ url?: string | null;
796
+ /** The alt text. Pass `''` for a decorative image, such as a thumbnail next to the product name. */
797
+ name: string;
798
+ /** Added to the image, or to its placeholder. */
799
+ className?: string;
800
+ }
801
+ /**
802
+ * A product image that fills its container, with a labeled placeholder when there is no URL or it fails to load.
803
+ * Use it in custom parts so they handle missing images like the package's own.
804
+ */
805
+ declare function ProductImage({
806
+ url,
807
+ name,
808
+ className
809
+ }: ProductImageProps): ReactElement;
622
810
  /** Read-only card state for custom parts rendered inside `ProductCardRoot`. */
623
811
  interface ProductCardState {
624
812
  /** `null` for a built-in sample, which is not a catalog product. */
@@ -662,17 +850,41 @@ declare function ProductCardTitle({
662
850
  declare function ProductCardDescription({
663
851
  className
664
852
  }: ProductCardPartProps): ReactElement | null;
665
- /** The product's price, or its price range when variants differ. */
853
+ /**
854
+ * "Sale" when some SKU's compare-at price is above that SKU's price. Without SKU prices, as in the catalog list, only
855
+ * when the lowest compare-at price is above the highest price. Renders nothing otherwise, or for samples.
856
+ */
857
+ declare function ProductCardBadge({
858
+ className
859
+ }: ProductCardPartProps): ReactElement | null;
860
+ /** The product's price, or its price range when variants differ. A single price on sale shows its compare-at price. */
666
861
  declare function ProductCardPrice({
667
862
  className
668
863
  }: ProductCardPartProps): ReactElement;
864
+ /**
865
+ * Dots for the first attribute whose values all have a swatch from the provider's `getSwatch`, such as colors.
866
+ * Renders nothing without `getSwatch`, for samples, or when no attribute has swatches.
867
+ */
868
+ declare function ProductCardSwatches({
869
+ className
870
+ }: ProductCardPartProps): ReactElement | null;
871
+ /** What a card action label can depend on. Only `add` can be busy or sold out. */
872
+ interface ProductCardActionLabelState extends AddToCartLabelState {
873
+ /** `add` adds directly; `choose-options` and `view-product` link to the product page. */
874
+ readonly action: 'add' | 'choose-options' | 'view-product';
875
+ }
876
+ interface ProductCardActionProps extends ProductCardPartProps {
877
+ /** Replaces the button or link label. A function receives the action and its state. */
878
+ children?: PartLabel<ProductCardActionLabelState>;
879
+ }
669
880
  /**
670
881
  * Adds the product directly when it has exactly one SKU and no options; otherwise links to its page to choose.
671
882
  * Samples add to the sample cart.
672
883
  */
673
884
  declare function ProductCardAction({
674
- className
675
- }: ProductCardPartProps): ReactElement;
885
+ className,
886
+ children
887
+ }: ProductCardActionProps): ReactElement;
676
888
  interface ProductCardProps {
677
889
  product: SKUGroup;
678
890
  }
@@ -706,11 +918,20 @@ interface ProductDetailsOptionValueState {
706
918
  readonly name: string;
707
919
  readonly label: string;
708
920
  readonly selected: boolean;
921
+ /**
922
+ * Every SKU with this value and the other selected values has tracked stock used up. `false` when that is not
923
+ * known, such as for a product with more SKUs than the page loads.
924
+ */
925
+ readonly soldOut: boolean;
926
+ /** The CSS background from the provider's `getSwatch`, or `null`. */
927
+ readonly swatch: string | null;
709
928
  }
710
929
  interface ProductDetailsOptionState {
711
930
  readonly name: string;
712
931
  readonly label: string;
713
932
  readonly selected: string | null;
933
+ /** Nothing is selected and the shopper pressed add, so the control should show an error. */
934
+ readonly missing: boolean;
714
935
  readonly values: readonly ProductDetailsOptionValueState[];
715
936
  /** Accepts only this attribute's own value names, or `null` to clear. Other values are ignored. */
716
937
  readonly select: (value: string | null) => void;
@@ -724,28 +945,64 @@ interface ProductDetailsRootProps {
724
945
  children: ReactNode;
725
946
  /** Added to the root `<article>`. */
726
947
  className?: string;
727
- }
728
- /** Loads the product for the route's `:productId` and provides state to product parts. */
948
+ /** The product to show. Defaults to the route's `:productId` parameter. */
949
+ productId?: string;
950
+ /**
951
+ * Keep the selected options and SKU in the page URL, as `option.<attribute>` and `sku`, so a reload or a shared link
952
+ * keeps them. Defaults to `true`. Set `false` for every other root on the same page, such as a quick view, so the
953
+ * roots do not share one selection.
954
+ */
955
+ urlState?: boolean;
956
+ /** Replaces the loading message. */
957
+ loading?: ReactNode;
958
+ /** Replaces the not-found heading and link. */
959
+ notFound?: ReactNode;
960
+ /** Replaces the load failure. A function receives the failure message and a `retry` for the product request. */
961
+ error?: PartLabel<ProductDetailsErrorState>;
962
+ }
963
+ /** What a replacement for the product load failure receives. */
964
+ interface ProductDetailsErrorState {
965
+ readonly message: string;
966
+ readonly retry: () => void;
967
+ }
968
+ /** Loads one product, by default the route's `:productId`, and provides state to product parts. */
729
969
  declare function ProductDetailsRoot({
730
- children,
731
- className
970
+ productId: productIdProp,
971
+ className,
972
+ ...props
732
973
  }: ProductDetailsRootProps): ReactElement;
733
974
  //#endregion
734
975
  //#region src/product-details.d.ts
735
976
  /** The packaged product page for `${productPath}/:productId`. Compose the parts for a custom layout. */
736
977
  declare function ProductDetails(): ReactElement;
978
+ interface ProductDetailsBackLinkProps extends ProductDetailsPartProps {
979
+ /** Replaces the chevron and "Back to shop". */
980
+ children?: ReactNode;
981
+ }
982
+ /** A link to the catalog. */
737
983
  declare function ProductDetailsBackLink({
738
- className
739
- }: ProductDetailsPartProps): ReactElement;
984
+ className,
985
+ children
986
+ }: ProductDetailsBackLinkProps): ReactElement;
740
987
  /** Main image with thumbnails; the selected SKU's images replace the product's when present. */
741
988
  declare function ProductDetailsGallery({
742
989
  className
743
990
  }: ProductDetailsPartProps): ReactElement;
991
+ /**
992
+ * "Sale" when the verified SKU's compare-at price is above its price, or, before then, when some SKU's is. Renders
993
+ * nothing otherwise.
994
+ */
995
+ declare function ProductDetailsBadge({
996
+ className
997
+ }: ProductDetailsPartProps): ReactElement | null;
744
998
  /** The product name as the page's H1. */
745
999
  declare function ProductDetailsTitle({
746
1000
  className
747
1001
  }: ProductDetailsPartProps): ReactElement;
748
- /** The verified SKU's price and compare-at price, or the product's starting price. */
1002
+ /**
1003
+ * The verified SKU's price and compare-at price, or the product's starting price. Before a SKU is verified, the
1004
+ * compare-at price shows only when it belongs to the cheapest SKUs, so it never pairs prices from different SKUs.
1005
+ */
749
1006
  declare function ProductDetailsPrice({
750
1007
  className
751
1008
  }: ProductDetailsPartProps): ReactElement;
@@ -755,11 +1012,11 @@ declare function ProductDetailsDescription({
755
1012
  }: ProductDetailsPartProps): ReactElement;
756
1013
  //#endregion
757
1014
  //#region src/product-purchase.d.ts
758
- /** The packaged purchase area: options, status, availability, quantity, and add to cart. */
1015
+ /** The packaged purchase area: options, status, quantity, add to cart, and availability. */
759
1016
  declare function ProductDetailsPurchase({
760
1017
  className
761
1018
  }: ProductDetailsPartProps): ReactElement;
762
- /** A select for every product attribute, or the SKU list for products without attributes. */
1019
+ /** A control for every product attribute, or the SKU list for products without attributes. */
763
1020
  declare function ProductDetailsOptions({
764
1021
  className
765
1022
  }: ProductDetailsPartProps): ReactElement | null;
@@ -767,12 +1024,18 @@ interface ProductDetailsOptionProps extends ProductDetailsPartProps {
767
1024
  /** The attribute `name`, such as `color`. Renders nothing when the product has no such attribute. */
768
1025
  attribute: string;
769
1026
  }
770
- /** A select for one product attribute. Use `useProductDetailsOption` for swatches or other custom controls. */
1027
+ /**
1028
+ * One product attribute: buttons, swatches when the provider's `getSwatch` gives every value one, or a select for
1029
+ * more than eight values. Use `useProductDetailsOption` for other custom controls.
1030
+ */
771
1031
  declare function ProductDetailsOption({
772
1032
  attribute,
773
1033
  className
774
1034
  }: ProductDetailsOptionProps): ReactElement | null;
775
- /** The single message explaining why the selection is not yet purchasable. Renders nothing when ready. */
1035
+ /**
1036
+ * The single message explaining why the selection is not purchasable. Renders nothing when ready, or before every
1037
+ * option is chosen, when the add button names the next one.
1038
+ */
776
1039
  declare function ProductDetailsPurchaseStatus({
777
1040
  className
778
1041
  }: ProductDetailsPartProps): ReactElement | null;
@@ -780,16 +1043,55 @@ declare function ProductDetailsPurchaseStatus({
780
1043
  declare function ProductDetailsAvailability({
781
1044
  className
782
1045
  }: ProductDetailsPartProps): ReactElement | null;
783
- /** Quantity for the verified SKU, with a message when it cannot be added. Renders nothing until a SKU is verified. */
1046
+ /**
1047
+ * A quantity stepper, capped at the verified SKU's stock, with a message when a typed quantity cannot be added.
1048
+ * Disabled while the verified SKU is sold out.
1049
+ */
784
1050
  declare function ProductDetailsQuantity({
785
1051
  className
786
- }: ProductDetailsPartProps): ReactElement | null;
787
- /** Adds the verified SKU and quantity. While disabled, its accessible description says why. */
788
- declare function ProductDetailsAddToCart({
789
- className
790
1052
  }: ProductDetailsPartProps): ReactElement;
1053
+ interface ProductDetailsAddToCartProps extends ProductDetailsPartProps {
1054
+ /** Replaces the button label. A function receives `busy` and `soldOut`; the button keeps its rules either way. */
1055
+ children?: PartLabel<AddToCartLabelState>;
1056
+ }
1057
+ /**
1058
+ * Adds the verified SKU and quantity, labeled with the total, such as "Add to cart · $64.00". Until every option is
1059
+ * chosen it names the next one, such as "Select size", and pressing it marks the missing options and focuses the
1060
+ * first. While the selection is checked or unavailable it is disabled, and its accessible description says why.
1061
+ */
1062
+ declare function ProductDetailsAddToCart({
1063
+ className,
1064
+ children
1065
+ }: ProductDetailsAddToCartProps): ReactElement;
1066
+ //#endregion
1067
+ //#region src/related-products.d.ts
1068
+ interface RelatedProductsProps {
1069
+ /** The product to leave out. Defaults to the route's `:productId` parameter. */
1070
+ productId?: string;
1071
+ /** The H2. Defaults to "You may also like". */
1072
+ title?: ReactNode;
1073
+ /** The most products to show, a whole number from 1 to 24. Defaults to 4. */
1074
+ limit?: number;
1075
+ /** Added to the root `<section>`. */
1076
+ className?: string;
1077
+ /** One card, rendered for every product. Defaults to the packaged card. */
1078
+ children?: ReactNode;
1079
+ }
1080
+ /**
1081
+ * Other products from the catalog's first page, leaving out the current one. Optional and separate from
1082
+ * `ProductDetails`: place it wherever it fits, such as after the product page. There is no related-products API, so
1083
+ * the products are the catalog's first ones. Renders nothing until they load, when none are left, if the request
1084
+ * fails, or while no store is connected.
1085
+ */
1086
+ declare function RelatedProducts({
1087
+ productId: productIdProp,
1088
+ title,
1089
+ limit,
1090
+ className,
1091
+ children
1092
+ }: RelatedProductsProps): ReactElement | null;
791
1093
  //#endregion
792
1094
  //#region src/storefront-surface.d.ts
793
1095
  declare function CommerceStatus(): ReactElement | null;
794
1096
  //#endregion
795
- export { AddToCartButton, AddToCartItemInput, type AddedCartItem, ApiError, CartAddress, CartButton, CartCheckout, CartCheckoutNote, CartClose, CartDescription, CartDiscount, CartDrawer, CartDrawerRoot, type CartDrawerRootProps, CartEmpty, type CartEmptyProps, CartItemImage, CartItemName, CartItemOptions, CartItemPrice, CartItemQuantity, CartItemRemove, CartItemRoot, type CartItemRootProps, type CartItemState, CartItems, type CartItemsProps, CartLineItem, CartLineItemDetails, CartNote, CartNotices, CartOrder, type CartPartProps, CartRoot, type CartRootProps, CartSelectedAddon, CartSelectedAddonValue, CartSelectedOption, CartShippingInfo, type CartState, CartSubtotal, CartSummary, type CartSummaryProps, CartSummaryTotals, CartTax, CartTitle, 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, useCart, useCartItem, useCommerce, useProductCard, useProductDetails, useProductDetailsOption };
1097
+ export { AddToCartButton, type AddToCartButtonProps, AddToCartItemInput, type AddToCartLabelState, type AddedCartItem, ApiError, type CartActionPartProps, CartAddress, CartButton, type CartButtonProps, CartCheckout, CartCheckoutNote, CartClose, CartContinueShopping, CartDescription, CartDiscount, CartDrawer, CartDrawerRoot, type CartDrawerRootProps, CartEmpty, type CartEmptyProps, CartItemImage, CartItemName, CartItemOptions, CartItemPrice, CartItemQuantity, CartItemRemove, CartItemRoot, type CartItemRootProps, type CartItemState, CartItems, type CartItemsProps, CartLineItem, CartLineItemDetails, CartNote, CartNotices, CartOrder, type CartPartProps, CartRoot, type CartRootProps, CartSelectedAddon, CartSelectedAddonValue, CartSelectedOption, CartShippingInfo, type CartState, CartSubtotal, CartSummary, type CartSummaryProps, CartSummaryTotals, CartTax, type CartTextPartProps, CartTitle, Catalog, CatalogEmpty, type CatalogEmptyProps, CatalogHeader, type CatalogHeaderProps, CatalogPagination, type CatalogPartProps, CatalogProducts, type CatalogProductsProps, type CatalogProps, CatalogRoot, type CatalogRootProps, CatalogSummary, type CommerceContextValue, type CommerceEvent, type CommerceOperation, CommerceProvider, type CommerceProviderProps, CommerceStatus, CommerceStorefront, Connection, ConnectionEdge, DraftOrderContext, type GetSwatch, InventoryCount, LabelFilter, LineItemTotals, MediaObject, Money, OrderTotals, PageInfo, type PartLabel, PriceRange, ProductCard, ProductCardAction, type ProductCardActionLabelState, type ProductCardActionProps, ProductCardBadge, ProductCardDescription, ProductCardImage, type ProductCardPartProps, ProductCardPrice, type ProductCardProps, ProductCardRoot, type ProductCardRootProps, type ProductCardState, ProductCardSwatches, ProductCardTitle, ProductDetails, ProductDetailsAddToCart, type ProductDetailsAddToCartProps, ProductDetailsAvailability, ProductDetailsBackLink, type ProductDetailsBackLinkProps, ProductDetailsBadge, ProductDetailsDescription, type ProductDetailsErrorState, 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, ProductImage, type ProductImageProps, RelatedProducts, type RelatedProductsProps, SKU, SKUAttributeValue, SKUGroup, SKUGroupAttribute, SKUGroupAttributeValue, SKUGroupSKU, SKUPrice, SkuGroupResult, SkuGroupVariables, SkuGroupsResult, SkuGroupsVariables, SkuResult, SkuVariables, type StorefrontConfig, StorefrontProductAttribute, StorefrontProductAttributeValue, type StorefrontTheme, StringInFilter, type SwatchValue, addToCart, getAvailableInventoryQuantity, getCartSummaryTotals, getImageUrls, getLabeledSkuOptions, getPrimaryImageUrl, getProductAttributes, getProductName, getSingleMatchedSku, getSingleMatchedSkuId, getSkuAttributeValueNames, getStartingCompareAt, inSentence, isOnSale, isProductOnSale, money, useCart, useCartItem, useCommerce, useMoney, useProductCard, useProductDetails, useProductDetailsOption };