pixelize-design-library 2.4.2-beta.56 → 2.4.2-beta.57
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/CHANGELOG.md +60 -0
- package/COMPONENT-GOTCHAS.md +48 -20
- package/DESIGN-GUIDE.md +18 -1
- package/dist/Components/AddressCard/AddressCard.d.ts +4 -0
- package/dist/Components/AddressCard/AddressCard.js +25 -0
- package/dist/Components/AddressCard/AddressCardGroup.d.ts +4 -0
- package/dist/Components/AddressCard/AddressCardGroup.js +7 -0
- package/dist/Components/AddressCard/AddressCardProps.d.ts +43 -0
- package/dist/Components/AddressCard/AddressCardProps.js +2 -0
- package/dist/Components/BagBar/BagBar.d.ts +4 -0
- package/dist/Components/BagBar/BagBar.js +32 -0
- package/dist/Components/BagBar/BagBarProps.d.ts +30 -0
- package/dist/Components/BagBar/BagBarProps.js +2 -0
- package/dist/Components/CartItem/CartItem.d.ts +4 -0
- package/dist/Components/CartItem/CartItem.js +60 -0
- package/dist/Components/CartItem/CartItemProps.d.ts +64 -0
- package/dist/Components/CartItem/CartItemProps.js +2 -0
- package/dist/Components/CartItem/cartItemOptions.d.ts +3 -0
- package/dist/Components/CartItem/cartItemOptions.js +13 -0
- package/dist/Components/CheckoutKit/selectable.d.ts +58 -0
- package/dist/Components/CheckoutKit/selectable.js +120 -0
- package/dist/Components/Commerce/commerceTypes.d.ts +52 -0
- package/dist/Components/Commerce/commerceTypes.js +2 -0
- package/dist/Components/Commerce/commerceVariants.d.ts +13 -0
- package/dist/Components/Commerce/commerceVariants.js +51 -0
- package/dist/Components/Commerce/index.d.ts +2 -0
- package/dist/Components/Commerce/index.js +18 -0
- package/dist/Components/Commerce/useContainerWidth.d.ts +3 -0
- package/dist/Components/Commerce/useContainerWidth.js +25 -0
- package/dist/Components/CouponField/CouponField.d.ts +4 -0
- package/dist/Components/CouponField/CouponField.js +72 -0
- package/dist/Components/CouponField/CouponFieldProps.d.ts +49 -0
- package/dist/Components/CouponField/CouponFieldProps.js +2 -0
- package/dist/Components/DatePicker/PickerPortal.d.ts +11 -0
- package/dist/Components/DatePicker/PickerPortal.js +26 -0
- package/dist/Components/DatePicker/RangeDatePicker.d.ts +1 -1
- package/dist/Components/DatePicker/RangeDatePicker.js +67 -32
- package/dist/Components/DatePicker/SingleDatePicker.js +49 -13
- package/dist/Components/DatePicker/TimeOnlyPicker.js +39 -4
- package/dist/Components/DetailSections/DetailSections.d.ts +4 -0
- package/dist/Components/DetailSections/DetailSections.js +112 -0
- package/dist/Components/DetailSections/DetailSectionsProps.d.ts +58 -0
- package/dist/Components/DetailSections/DetailSectionsProps.js +2 -0
- package/dist/Components/MediaGallery/MediaFrame.d.ts +31 -0
- package/dist/Components/MediaGallery/MediaFrame.js +55 -0
- package/dist/Components/MediaGallery/MediaGallery.d.ts +4 -0
- package/dist/Components/MediaGallery/MediaGallery.js +206 -0
- package/dist/Components/MediaGallery/MediaGalleryProps.d.ts +76 -0
- package/dist/Components/MediaGallery/MediaGalleryProps.js +20 -0
- package/dist/Components/MediaGallery/MediaLightbox.d.ts +4 -0
- package/dist/Components/MediaGallery/MediaLightbox.js +116 -0
- package/dist/Components/MediaGallery/MediaLightboxProps.d.ts +40 -0
- package/dist/Components/MediaGallery/MediaLightboxProps.js +15 -0
- package/dist/Components/MediaGallery/MediaThumb.d.ts +18 -0
- package/dist/Components/MediaGallery/MediaThumb.js +25 -0
- package/dist/Components/MediaGallery/glass.d.ts +31 -0
- package/dist/Components/MediaGallery/glass.js +47 -0
- package/dist/Components/MediaGallery/mediaGalleryModel.d.ts +22 -0
- package/dist/Components/MediaGallery/mediaGalleryModel.js +83 -0
- package/dist/Components/MediaGallery/motion.d.ts +5 -0
- package/dist/Components/MediaGallery/motion.js +12 -0
- package/dist/Components/MediaGallery/useMatchMedia.d.ts +2 -0
- package/dist/Components/MediaGallery/useMatchMedia.js +20 -0
- package/dist/Components/OffersList/OffersList.d.ts +4 -0
- package/dist/Components/OffersList/OffersList.js +83 -0
- package/dist/Components/OffersList/OffersListProps.d.ts +34 -0
- package/dist/Components/OffersList/OffersListProps.js +2 -0
- package/dist/Components/OptionChip/OptionChip.d.ts +4 -0
- package/dist/Components/OptionChip/OptionChip.js +97 -0
- package/dist/Components/OptionChip/OptionChipProps.d.ts +33 -0
- package/dist/Components/OptionChip/OptionChipProps.js +2 -0
- package/dist/Components/OptionChip/optionInk.d.ts +12 -0
- package/dist/Components/OptionChip/optionInk.js +25 -0
- package/dist/Components/OrderStatusTimeline/OrderStatusTimeline.d.ts +4 -0
- package/dist/Components/OrderStatusTimeline/OrderStatusTimeline.js +57 -0
- package/dist/Components/OrderStatusTimeline/OrderStatusTimelineProps.d.ts +29 -0
- package/dist/Components/OrderStatusTimeline/OrderStatusTimelineProps.js +2 -0
- package/dist/Components/OrderSummary/OrderSummary.d.ts +4 -0
- package/dist/Components/OrderSummary/OrderSummary.js +63 -0
- package/dist/Components/OrderSummary/OrderSummaryProps.d.ts +53 -0
- package/dist/Components/OrderSummary/OrderSummaryProps.js +2 -0
- package/dist/Components/PaymentOption/PaymentOption.d.ts +4 -0
- package/dist/Components/PaymentOption/PaymentOption.js +24 -0
- package/dist/Components/PaymentOption/PaymentOptionGroup.d.ts +4 -0
- package/dist/Components/PaymentOption/PaymentOptionGroup.js +7 -0
- package/dist/Components/PaymentOption/PaymentOptionProps.d.ts +32 -0
- package/dist/Components/PaymentOption/PaymentOptionProps.js +2 -0
- package/dist/Components/PincodeChecker/PincodeChecker.d.ts +4 -0
- package/dist/Components/PincodeChecker/PincodeChecker.js +175 -0
- package/dist/Components/PincodeChecker/PincodeCheckerProps.d.ts +57 -0
- package/dist/Components/PincodeChecker/PincodeCheckerProps.js +2 -0
- package/dist/Components/PriceBlock/PriceBlock.d.ts +4 -0
- package/dist/Components/PriceBlock/PriceBlock.js +41 -0
- package/dist/Components/PriceBlock/PriceBlockProps.d.ts +39 -0
- package/dist/Components/PriceBlock/PriceBlockProps.js +2 -0
- package/dist/Components/ProductBadges/ProductBadges.d.ts +4 -0
- package/dist/Components/ProductBadges/ProductBadges.js +61 -0
- package/dist/Components/ProductBadges/ProductBadgesProps.d.ts +18 -0
- package/dist/Components/ProductBadges/ProductBadgesProps.js +2 -0
- package/dist/Components/ProductCard/ProductCard.d.ts +3 -2
- package/dist/Components/ProductCard/ProductCard.js +103 -52
- package/dist/Components/ProductCard/ProductCardAction.d.ts +17 -0
- package/dist/Components/ProductCard/ProductCardAction.js +65 -0
- package/dist/Components/ProductCard/ProductCardGrid.d.ts +4 -0
- package/dist/Components/ProductCard/ProductCardGrid.js +20 -0
- package/dist/Components/ProductCard/ProductCardMedia.d.ts +18 -0
- package/dist/Components/ProductCard/ProductCardMedia.js +35 -0
- package/dist/Components/ProductCard/ProductCardProps.d.ts +138 -56
- package/dist/Components/ProductCard/ProductCardSkeleton.d.ts +4 -0
- package/dist/Components/ProductCard/ProductCardSkeleton.js +17 -0
- package/dist/Components/ProductCard/ProductCardSwatches.d.ts +15 -0
- package/dist/Components/ProductCard/ProductCardSwatches.js +37 -0
- package/dist/Components/ProductCard/QuickAddSheet.d.ts +4 -0
- package/dist/Components/ProductCard/QuickAddSheet.js +109 -0
- package/dist/Components/ProductCard/QuickAddSheetProps.d.ts +38 -0
- package/dist/Components/ProductCard/QuickAddSheetProps.js +2 -0
- package/dist/Components/ProductCard/cardLabels.d.ts +2 -0
- package/dist/Components/ProductCard/cardLabels.js +16 -0
- package/dist/Components/ProductCard/cardMetrics.d.ts +27 -0
- package/dist/Components/ProductCard/cardMetrics.js +55 -0
- package/dist/Components/ProductCard/productCardFixtures.d.ts +7 -0
- package/dist/Components/ProductCard/productCardFixtures.js +61 -0
- package/dist/Components/ProductCard/productCardModel.d.ts +22 -0
- package/dist/Components/ProductCard/productCardModel.js +79 -0
- package/dist/Components/ProductCard/useMinWidth.d.ts +2 -0
- package/dist/Components/ProductCard/useMinWidth.js +20 -0
- package/dist/Components/ProductDetails/ProductDetails.d.ts +3 -2
- package/dist/Components/ProductDetails/ProductDetails.js +209 -33
- package/dist/Components/ProductDetails/ProductDetailsProps.d.ts +143 -41
- package/dist/Components/ProductDetails/productDetailsModel.d.ts +14 -0
- package/dist/Components/ProductDetails/productDetailsModel.js +45 -0
- package/dist/Components/ProductDetails/useInViewport.d.ts +3 -0
- package/dist/Components/ProductDetails/useInViewport.js +18 -0
- package/dist/Components/QuantityStepper/QuantityStepper.d.ts +4 -0
- package/dist/Components/QuantityStepper/QuantityStepper.js +59 -0
- package/dist/Components/QuantityStepper/QuantityStepperProps.d.ts +24 -0
- package/dist/Components/QuantityStepper/QuantityStepperProps.js +2 -0
- package/dist/Components/Rating/Rating.d.ts +4 -0
- package/dist/Components/Rating/Rating.js +81 -0
- package/dist/Components/Rating/RatingProps.d.ts +27 -0
- package/dist/Components/Rating/RatingProps.js +2 -0
- package/dist/Components/ReviewList/ReviewList.d.ts +4 -0
- package/dist/Components/ReviewList/ReviewList.js +94 -0
- package/dist/Components/ReviewList/ReviewListProps.d.ts +68 -0
- package/dist/Components/ReviewList/ReviewListProps.js +2 -0
- package/dist/Components/ReviewSummary/ReviewSummary.d.ts +4 -0
- package/dist/Components/ReviewSummary/ReviewSummary.js +47 -0
- package/dist/Components/ReviewSummary/ReviewSummaryProps.d.ts +31 -0
- package/dist/Components/ReviewSummary/ReviewSummaryProps.js +2 -0
- package/dist/Components/SegmentedControl/SegmentedControl.d.ts +1 -1
- package/dist/Components/SegmentedControl/SegmentedControl.js +17 -5
- package/dist/Components/SegmentedControl/SegmentedControlProps.d.ts +6 -0
- package/dist/Components/SegmentedControl/segmentedInk.d.ts +2 -0
- package/dist/Components/SegmentedControl/segmentedInk.js +4 -1
- package/dist/Components/SegmentedControl/useSlidingPill.d.ts +2 -0
- package/dist/Components/SegmentedControl/useSlidingPill.js +6 -1
- package/dist/Components/SideBar/SecondaryBar.js +13 -8
- package/dist/Components/SideBar/SideBarProps.d.ts +3 -1
- package/dist/Components/SideBar/components/MenuItemBox.js +47 -10
- package/dist/Components/SideBar/components/MenuPopoverContent.js +4 -3
- package/dist/Components/SpecTable/SpecTable.d.ts +4 -0
- package/dist/Components/SpecTable/SpecTable.js +39 -0
- package/dist/Components/SpecTable/SpecTableProps.d.ts +25 -0
- package/dist/Components/SpecTable/SpecTableProps.js +2 -0
- package/dist/Components/Spinner/Spinner.d.ts +1 -1
- package/dist/Components/Spinner/Spinner.js +2 -2
- package/dist/Components/Spinner/SpinnerProps.d.ts +2 -0
- package/dist/Components/StageProgress/StepperStage.js +2 -1
- package/dist/Components/StatCard/StatCard.d.ts +1 -1
- package/dist/Components/StatCard/StatCard.js +2 -2
- package/dist/Components/StatCard/StatCardProps.d.ts +4 -0
- package/dist/Components/StickyBuyBar/StickyBuyBar.d.ts +3 -0
- package/dist/Components/StickyBuyBar/StickyBuyBar.js +85 -0
- package/dist/Components/StickyBuyBar/StickyBuyBarProps.d.ts +54 -0
- package/dist/Components/StickyBuyBar/StickyBuyBarProps.js +2 -0
- package/dist/Components/StockStatus/StockStatus.d.ts +4 -0
- package/dist/Components/StockStatus/StockStatus.js +31 -0
- package/dist/Components/StockStatus/StockStatusProps.d.ts +14 -0
- package/dist/Components/StockStatus/StockStatusProps.js +2 -0
- package/dist/Components/Table/Table.js +2 -1
- package/dist/Components/Table/TableProps.d.ts +5 -2
- package/dist/Components/Table/columnLabel.d.ts +6 -0
- package/dist/Components/Table/columnLabel.js +27 -0
- package/dist/Components/Table/components/TableBody.js +5 -1
- package/dist/Components/Table/components/TableHeader.js +3 -2
- package/dist/Components/Table/filters/ActiveFilters.js +2 -1
- package/dist/Components/Table/filters/TableFilters.js +2 -1
- package/dist/Components/Table/hooks/useTable.js +3 -2
- package/dist/Components/Table/settings/ManageColumns.js +4 -3
- package/dist/Components/Table/settings/TableSettings.js +2 -1
- package/dist/Components/TrustBadges/TrustBadges.d.ts +4 -0
- package/dist/Components/TrustBadges/TrustBadges.js +24 -0
- package/dist/Components/TrustBadges/TrustBadgesProps.d.ts +20 -0
- package/dist/Components/TrustBadges/TrustBadgesProps.js +2 -0
- package/dist/Components/VariantSelector/VariantSelector.d.ts +4 -0
- package/dist/Components/VariantSelector/VariantSelector.js +123 -0
- package/dist/Components/VariantSelector/VariantSelectorProps.d.ts +27 -0
- package/dist/Components/VariantSelector/VariantSelectorProps.js +2 -0
- package/dist/Components/VariantSelector/variantSelection.d.ts +6 -0
- package/dist/Components/VariantSelector/variantSelection.js +25 -0
- package/dist/Components/WishlistToggle/WishlistToggle.d.ts +4 -0
- package/dist/Components/WishlistToggle/WishlistToggle.js +65 -0
- package/dist/Components/WishlistToggle/WishlistToggleProps.d.ts +19 -0
- package/dist/Components/WishlistToggle/WishlistToggleProps.js +2 -0
- package/dist/Theme/assertPalette.d.ts +1 -1
- package/dist/Theme/assertPalette.js +1 -1
- package/dist/Theme/tokens/brands/index.js +2 -0
- package/dist/Theme/tokens/brands/zinc/palette.dark.d.ts +1 -0
- package/dist/Theme/tokens/builders/buildDarkPalette.js +2 -0
- package/dist/Theme/tokens/builders/index.d.ts +1 -0
- package/dist/Theme/tokens/builders/index.js +1 -0
- package/dist/Theme/tokens/builders/rechartsTheme.d.ts +56 -0
- package/dist/Theme/tokens/builders/rechartsTheme.js +43 -0
- package/dist/Theme/tokens/builders/star.d.ts +3 -0
- package/dist/Theme/tokens/builders/star.js +8 -0
- package/dist/Theme/tokens/types.d.ts +3 -1
- package/dist/Theme/useChartTheme.d.ts +4 -0
- package/dist/Theme/useChartTheme.js +12 -0
- package/dist/Utils/price.d.ts +16 -0
- package/dist/Utils/price.js +34 -0
- package/dist/esm/Components/AddressCard/AddressCard.js +20 -0
- package/dist/esm/Components/AddressCard/AddressCardGroup.js +5 -0
- package/dist/esm/Components/AddressCard/AddressCardProps.js +1 -0
- package/dist/esm/Components/BagBar/BagBar.js +27 -0
- package/dist/esm/Components/BagBar/BagBarProps.js +1 -0
- package/dist/esm/Components/CartItem/CartItem.js +55 -0
- package/dist/esm/Components/CartItem/CartItemProps.js +1 -0
- package/dist/esm/Components/CartItem/cartItemOptions.js +9 -0
- package/dist/esm/Components/CheckoutKit/selectable.js +112 -0
- package/dist/esm/Components/Commerce/commerceTypes.js +1 -0
- package/dist/esm/Components/Commerce/commerceVariants.js +41 -0
- package/dist/esm/Components/Commerce/index.js +2 -0
- package/dist/esm/Components/Commerce/useContainerWidth.js +21 -0
- package/dist/esm/Components/CouponField/CouponField.js +67 -0
- package/dist/esm/Components/CouponField/CouponFieldProps.js +1 -0
- package/dist/esm/Components/DatePicker/PickerPortal.js +21 -0
- package/dist/esm/Components/DatePicker/RangeDatePicker.js +34 -32
- package/dist/esm/Components/DatePicker/SingleDatePicker.js +16 -13
- package/dist/esm/Components/DatePicker/TimeOnlyPicker.js +6 -4
- package/dist/esm/Components/DetailSections/DetailSections.js +107 -0
- package/dist/esm/Components/DetailSections/DetailSectionsProps.js +1 -0
- package/dist/esm/Components/MediaGallery/MediaFrame.js +48 -0
- package/dist/esm/Components/MediaGallery/MediaGallery.js +201 -0
- package/dist/esm/Components/MediaGallery/MediaGalleryProps.js +17 -0
- package/dist/esm/Components/MediaGallery/MediaLightbox.js +78 -0
- package/dist/esm/Components/MediaGallery/MediaLightboxProps.js +12 -0
- package/dist/esm/Components/MediaGallery/MediaThumb.js +23 -0
- package/dist/esm/Components/MediaGallery/glass.js +42 -0
- package/dist/esm/Components/MediaGallery/mediaGalleryModel.js +71 -0
- package/dist/esm/Components/MediaGallery/motion.js +8 -0
- package/dist/esm/Components/MediaGallery/useMatchMedia.js +16 -0
- package/dist/esm/Components/OffersList/OffersList.js +81 -0
- package/dist/esm/Components/OffersList/OffersListProps.js +1 -0
- package/dist/esm/Components/OptionChip/OptionChip.js +95 -0
- package/dist/esm/Components/OptionChip/OptionChipProps.js +1 -0
- package/dist/esm/Components/OptionChip/optionInk.js +21 -0
- package/dist/esm/Components/OrderStatusTimeline/OrderStatusTimeline.js +55 -0
- package/dist/esm/Components/OrderStatusTimeline/OrderStatusTimelineProps.js +1 -0
- package/dist/esm/Components/OrderSummary/OrderSummary.js +58 -0
- package/dist/esm/Components/OrderSummary/OrderSummaryProps.js +1 -0
- package/dist/esm/Components/PaymentOption/PaymentOption.js +19 -0
- package/dist/esm/Components/PaymentOption/PaymentOptionGroup.js +5 -0
- package/dist/esm/Components/PaymentOption/PaymentOptionProps.js +1 -0
- package/dist/esm/Components/PincodeChecker/PincodeChecker.js +170 -0
- package/dist/esm/Components/PincodeChecker/PincodeCheckerProps.js +1 -0
- package/dist/esm/Components/PriceBlock/PriceBlock.js +39 -0
- package/dist/esm/Components/PriceBlock/PriceBlockProps.js +1 -0
- package/dist/esm/Components/ProductBadges/ProductBadges.js +59 -0
- package/dist/esm/Components/ProductBadges/ProductBadgesProps.js +1 -0
- package/dist/esm/Components/ProductCard/ProductCard.js +105 -54
- package/dist/esm/Components/ProductCard/ProductCardAction.js +60 -0
- package/dist/esm/Components/ProductCard/ProductCardGrid.js +18 -0
- package/dist/esm/Components/ProductCard/ProductCardMedia.js +33 -0
- package/dist/esm/Components/ProductCard/ProductCardSkeleton.js +12 -0
- package/dist/esm/Components/ProductCard/ProductCardSwatches.js +35 -0
- package/dist/esm/Components/ProductCard/QuickAddSheet.js +71 -0
- package/dist/esm/Components/ProductCard/QuickAddSheetProps.js +1 -0
- package/dist/esm/Components/ProductCard/cardLabels.js +13 -0
- package/dist/esm/Components/ProductCard/cardMetrics.js +52 -0
- package/dist/esm/Components/ProductCard/productCardFixtures.js +58 -0
- package/dist/esm/Components/ProductCard/productCardModel.js +65 -0
- package/dist/esm/Components/ProductCard/useMinWidth.js +16 -0
- package/dist/esm/Components/ProductDetails/ProductDetails.js +210 -34
- package/dist/esm/Components/ProductDetails/productDetailsModel.js +35 -0
- package/dist/esm/Components/ProductDetails/useInViewport.js +14 -0
- package/dist/esm/Components/QuantityStepper/QuantityStepper.js +57 -0
- package/dist/esm/Components/QuantityStepper/QuantityStepperProps.js +1 -0
- package/dist/esm/Components/Rating/Rating.js +79 -0
- package/dist/esm/Components/Rating/RatingProps.js +1 -0
- package/dist/esm/Components/ReviewList/ReviewList.js +89 -0
- package/dist/esm/Components/ReviewList/ReviewListProps.js +1 -0
- package/dist/esm/Components/ReviewSummary/ReviewSummary.js +42 -0
- package/dist/esm/Components/ReviewSummary/ReviewSummaryProps.js +1 -0
- package/dist/esm/Components/SegmentedControl/SegmentedControl.js +19 -7
- package/dist/esm/Components/SegmentedControl/segmentedInk.js +2 -0
- package/dist/esm/Components/SegmentedControl/useSlidingPill.js +6 -1
- package/dist/esm/Components/SideBar/SecondaryBar.js +14 -9
- package/dist/esm/Components/SideBar/components/MenuItemBox.js +14 -10
- package/dist/esm/Components/SideBar/components/MenuPopoverContent.js +4 -3
- package/dist/esm/Components/SpecTable/SpecTable.js +34 -0
- package/dist/esm/Components/SpecTable/SpecTableProps.js +1 -0
- package/dist/esm/Components/Spinner/Spinner.js +2 -2
- package/dist/esm/Components/StageProgress/StepperStage.js +2 -1
- package/dist/esm/Components/StatCard/StatCard.js +2 -2
- package/dist/esm/Components/StickyBuyBar/StickyBuyBar.js +80 -0
- package/dist/esm/Components/StickyBuyBar/StickyBuyBarProps.js +1 -0
- package/dist/esm/Components/StockStatus/StockStatus.js +29 -0
- package/dist/esm/Components/StockStatus/StockStatusProps.js +1 -0
- package/dist/esm/Components/Table/Table.js +2 -1
- package/dist/esm/Components/Table/columnLabel.js +21 -0
- package/dist/esm/Components/Table/components/TableBody.js +5 -1
- package/dist/esm/Components/Table/components/TableHeader.js +3 -2
- package/dist/esm/Components/Table/filters/ActiveFilters.js +2 -1
- package/dist/esm/Components/Table/filters/TableFilters.js +2 -1
- package/dist/esm/Components/Table/hooks/useTable.js +3 -2
- package/dist/esm/Components/Table/settings/ManageColumns.js +4 -3
- package/dist/esm/Components/Table/settings/TableSettings.js +2 -1
- package/dist/esm/Components/TrustBadges/TrustBadges.js +22 -0
- package/dist/esm/Components/TrustBadges/TrustBadgesProps.js +1 -0
- package/dist/esm/Components/VariantSelector/VariantSelector.js +118 -0
- package/dist/esm/Components/VariantSelector/VariantSelectorProps.js +1 -0
- package/dist/esm/Components/VariantSelector/variantSelection.js +19 -0
- package/dist/esm/Components/WishlistToggle/WishlistToggle.js +63 -0
- package/dist/esm/Components/WishlistToggle/WishlistToggleProps.js +1 -0
- package/dist/esm/Theme/assertPalette.js +1 -1
- package/dist/esm/Theme/tokens/brands/index.js +2 -0
- package/dist/esm/Theme/tokens/builders/buildDarkPalette.js +2 -0
- package/dist/esm/Theme/tokens/builders/index.js +1 -0
- package/dist/esm/Theme/tokens/builders/rechartsTheme.js +37 -0
- package/dist/esm/Theme/tokens/builders/star.js +4 -0
- package/dist/esm/Theme/useChartTheme.js +8 -0
- package/dist/esm/Utils/price.js +27 -0
- package/dist/esm/index.js +36 -0
- package/dist/index.d.ts +66 -0
- package/dist/index.js +86 -4
- package/package.json +1 -1
- package/dist/Components/ProductCard/ProductLabel.d.ts +0 -7
- package/dist/Components/ProductCard/ProductLabel.js +0 -20
- package/dist/Components/ProductCard/ProductPrice.d.ts +0 -10
- package/dist/Components/ProductCard/ProductPrice.js +0 -126
- package/dist/Components/ProductCard/ProductReview.d.ts +0 -8
- package/dist/Components/ProductCard/ProductReview.js +0 -30
- package/dist/Components/ProductCard/ProductTags.d.ts +0 -8
- package/dist/Components/ProductCard/ProductTags.js +0 -53
- package/dist/Components/ProductDetails/ProductDtlPrice.d.ts +0 -7
- package/dist/Components/ProductDetails/ProductDtlPrice.js +0 -24
- package/dist/Components/ProductDetails/ProductImageSlider.d.ts +0 -13
- package/dist/Components/ProductDetails/ProductImageSlider.js +0 -240
- package/dist/esm/Components/ProductCard/ProductLabel.js +0 -18
- package/dist/esm/Components/ProductCard/ProductPrice.js +0 -121
- package/dist/esm/Components/ProductCard/ProductReview.js +0 -28
- package/dist/esm/Components/ProductCard/ProductTags.js +0 -48
- package/dist/esm/Components/ProductDetails/ProductDtlPrice.js +0 -22
- package/dist/esm/Components/ProductDetails/ProductImageSlider.js +0 -204
|
@@ -4,44 +4,220 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
7
|
-
const react_1 =
|
|
7
|
+
const react_1 = require("react");
|
|
8
8
|
const react_2 = require("@chakra-ui/react");
|
|
9
|
+
const lucide_react_1 = require("lucide-react");
|
|
9
10
|
const useCustomTheme_1 = require("../../Theme/useCustomTheme");
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
const
|
|
11
|
+
const motion_1 = require("../../Theme/tokens/primitives/motion");
|
|
12
|
+
const motion_2 = require("../../Theme/chakra/motion");
|
|
13
|
+
const focusRing_styles_1 = require("../../Theme/chakra/focusRing.styles");
|
|
14
|
+
const price_1 = require("../../Utils/price");
|
|
14
15
|
const Button_1 = __importDefault(require("../Button/Button"));
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
|
|
16
|
+
const Skeletons_1 = __importDefault(require("../Skeletons/Skeletons"));
|
|
17
|
+
const MediaGallery_1 = __importDefault(require("../MediaGallery/MediaGallery"));
|
|
18
|
+
const useContainerWidth_1 = require("../Commerce/useContainerWidth");
|
|
19
|
+
const useMatchMedia_1 = require("../MediaGallery/useMatchMedia");
|
|
20
|
+
const ProductBadges_1 = __importDefault(require("../ProductBadges/ProductBadges"));
|
|
21
|
+
const Rating_1 = __importDefault(require("../Rating/Rating"));
|
|
22
|
+
const PriceBlock_1 = __importDefault(require("../PriceBlock/PriceBlock"));
|
|
23
|
+
const StockStatus_1 = __importDefault(require("../StockStatus/StockStatus"));
|
|
24
|
+
const WishlistToggle_1 = __importDefault(require("../WishlistToggle/WishlistToggle"));
|
|
25
|
+
const VariantSelector_1 = __importDefault(require("../VariantSelector/VariantSelector"));
|
|
26
|
+
const QuantityStepper_1 = __importDefault(require("../QuantityStepper/QuantityStepper"));
|
|
27
|
+
const OffersList_1 = __importDefault(require("../OffersList/OffersList"));
|
|
28
|
+
const PincodeChecker_1 = __importDefault(require("../PincodeChecker/PincodeChecker"));
|
|
29
|
+
const TrustBadges_1 = __importDefault(require("../TrustBadges/TrustBadges"));
|
|
30
|
+
const StickyBuyBar_1 = __importDefault(require("../StickyBuyBar/StickyBuyBar"));
|
|
31
|
+
const DetailSections_1 = __importDefault(require("../DetailSections/DetailSections"));
|
|
32
|
+
const ReviewSummary_1 = __importDefault(require("../ReviewSummary/ReviewSummary"));
|
|
33
|
+
const ReviewList_1 = __importDefault(require("../ReviewList/ReviewList"));
|
|
34
|
+
const commerceVariants_1 = require("../Commerce/commerceVariants");
|
|
35
|
+
const productDetailsModel_1 = require("./productDetailsModel");
|
|
36
|
+
const useInViewport_1 = require("./useInViewport");
|
|
37
|
+
const DESKTOP_QUERY = "(min-width: 1024px)";
|
|
38
|
+
const DESKTOP_MIN_WIDTH = 960;
|
|
39
|
+
const DEFAULT_ADDED_MS = 1600;
|
|
40
|
+
const DEFAULT_LABELS = {
|
|
41
|
+
addToBag: "Add to bag",
|
|
42
|
+
buyNow: "Buy now",
|
|
43
|
+
notifyMe: "Notify me",
|
|
44
|
+
goToBag: "Go to bag",
|
|
45
|
+
added: "Added",
|
|
46
|
+
addedAnnouncement: "Added to bag",
|
|
47
|
+
addFailed: "Couldn't add this to your bag. Try again.",
|
|
48
|
+
selectPrompt: (axisLabel) => `Select a ${axisLabel}`,
|
|
49
|
+
taxNote: "Inclusive of all taxes",
|
|
50
|
+
jumpToReviews: (ratingText) => `${ratingText}. Go to reviews`,
|
|
51
|
+
share: "Share",
|
|
52
|
+
wishlistSave: "Save for later",
|
|
53
|
+
};
|
|
54
|
+
const withGuide = (axes, guide) => {
|
|
55
|
+
var _a;
|
|
56
|
+
if (!guide)
|
|
57
|
+
return axes;
|
|
58
|
+
const axisId = (_a = guide.axisId) !== null && _a !== void 0 ? _a : "size";
|
|
59
|
+
return axes.map((axis) => { var _a; return axis.id === axisId && !axis.guide ? { ...axis, guide: { label: (_a = guide.label) !== null && _a !== void 0 ? _a : "Size guide", onClick: guide.onClick } } : axis; });
|
|
60
|
+
};
|
|
61
|
+
const scrollToNode = (node, reduced) => {
|
|
62
|
+
if (node && typeof node.scrollIntoView === "function") {
|
|
63
|
+
node.scrollIntoView({ behavior: reduced ? "auto" : "smooth", block: "center" });
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
/** Product page that wires one selection to price, stock, gallery frames and the primary action; every region has a slot. */
|
|
67
|
+
const ProductDetails = ({ product, selection: selectionProp, defaultSelection, onSelectionChange, quantity: quantityProp, defaultQuantity = 1, onQuantityChange, maxQuantity = productDetailsModel_1.DEFAULT_MAX_QUANTITY, onAddToBag, onBuyNow, onNotify, onGoToBag, addedDuration = DEFAULT_ADDED_MS, wishlisted, defaultWishlisted, onWishlistChange, onShare, offers, offersProps, trustItems, pincode, sizeGuide, onGuideClick, reviews, ratingBreakdown, reviewsProps, onWriteReview, detailSectionsProps, care, breadcrumbs, layout = "auto", mediaSlot, metaSlot, infoSlot, belowFold, relatedSlot, isLoading = false, labels: labelOverrides, currency, locale, "data-testid": testId, }) => {
|
|
68
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
20
69
|
const { colors } = (0, useCustomTheme_1.useCustomTheme)();
|
|
21
|
-
const
|
|
22
|
-
const
|
|
23
|
-
const
|
|
24
|
-
react_1.
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
70
|
+
const reduced = (0, motion_2.usePrefersReducedMotion)();
|
|
71
|
+
const uid = (0, react_1.useId)();
|
|
72
|
+
const labels = { ...DEFAULT_LABELS, ...labelOverrides };
|
|
73
|
+
const fmt = (0, react_1.useMemo)(() => ({ currency, locale }), [currency, locale]);
|
|
74
|
+
const rootRef = (0, react_1.useRef)(null);
|
|
75
|
+
const containerWidth = (0, useContainerWidth_1.useContainerWidth)(rootRef);
|
|
76
|
+
const wide = (0, useMatchMedia_1.useMatchMedia)(DESKTOP_QUERY, false);
|
|
77
|
+
const desktop = layout === "auto" ? (containerWidth === undefined ? wide : containerWidth >= DESKTOP_MIN_WIDTH) : layout === "desktop";
|
|
78
|
+
const variants = (0, react_1.useMemo)(() => (0, productDetailsModel_1.resolveVariants)(product), [product]);
|
|
79
|
+
const axes = (0, react_1.useMemo)(() => withGuide(product.axes, sizeGuide), [product.axes, sizeGuide]);
|
|
80
|
+
const [innerSelection, setInnerSelection] = (0, react_1.useState)(defaultSelection !== null && defaultSelection !== void 0 ? defaultSelection : {});
|
|
81
|
+
const selection = selectionProp !== null && selectionProp !== void 0 ? selectionProp : innerSelection;
|
|
82
|
+
const complete = (0, commerceVariants_1.selectionComplete)(product.axes, selection);
|
|
83
|
+
const variant = (0, commerceVariants_1.findVariant)(product.axes, variants, selection);
|
|
84
|
+
const unpicked = (0, productDetailsModel_1.firstUnpickedAxis)(product.axes, selection);
|
|
85
|
+
const selectPrompt = unpicked ? labels.selectPrompt(unpicked.label.toLowerCase()) : "";
|
|
86
|
+
const state = variant ? (0, commerceVariants_1.stockState)(variant) : (0, productDetailsModel_1.soldOutEverywhere)(variants) ? "out-of-stock" : undefined;
|
|
87
|
+
const notifyMode = state === "out-of-stock";
|
|
88
|
+
const ceiling = (0, productDetailsModel_1.quantityCeiling)(variant, maxQuantity);
|
|
89
|
+
const [innerQuantity, setInnerQuantity] = (0, react_1.useState)(defaultQuantity);
|
|
90
|
+
const quantity = (0, productDetailsModel_1.clampQuantity)(quantityProp !== null && quantityProp !== void 0 ? quantityProp : innerQuantity, ceiling);
|
|
91
|
+
const [bag, setBag] = (0, react_1.useState)("idle");
|
|
92
|
+
const [addFailed, setAddFailed] = (0, react_1.useState)(false);
|
|
93
|
+
const [showSelectError, setShowSelectError] = (0, react_1.useState)(false);
|
|
94
|
+
const [promptTick, setPromptTick] = (0, react_1.useState)(0);
|
|
95
|
+
const [announcement, setAnnouncement] = (0, react_1.useState)("");
|
|
96
|
+
const timer = (0, react_1.useRef)();
|
|
97
|
+
const mounted = (0, react_1.useRef)(true);
|
|
98
|
+
const selectorRef = (0, react_1.useRef)(null);
|
|
99
|
+
const ctaRef = (0, react_1.useRef)(null);
|
|
100
|
+
const reviewsRef = (0, react_1.useRef)(null);
|
|
101
|
+
const ctaInView = (0, useInViewport_1.useInViewport)(ctaRef, !desktop && !isLoading);
|
|
102
|
+
(0, react_1.useEffect)(() => {
|
|
103
|
+
mounted.current = true;
|
|
104
|
+
return () => {
|
|
105
|
+
mounted.current = false;
|
|
106
|
+
clearTimeout(timer.current);
|
|
107
|
+
};
|
|
108
|
+
}, []);
|
|
109
|
+
const variantId = variant === null || variant === void 0 ? void 0 : variant.id;
|
|
110
|
+
(0, react_1.useEffect)(() => {
|
|
111
|
+
clearTimeout(timer.current);
|
|
112
|
+
setBag("idle");
|
|
113
|
+
setAddFailed(false);
|
|
114
|
+
}, [variantId, quantity]);
|
|
115
|
+
(0, react_1.useEffect)(() => {
|
|
116
|
+
var _a, _b;
|
|
117
|
+
if (promptTick === 0)
|
|
118
|
+
return;
|
|
119
|
+
const group = (_a = selectorRef.current) === null || _a === void 0 ? void 0 : _a.querySelector('[role="radiogroup"][aria-invalid="true"]');
|
|
120
|
+
scrollToNode(group !== null && group !== void 0 ? group : selectorRef.current, reduced);
|
|
121
|
+
(_b = group === null || group === void 0 ? void 0 : group.querySelector('[role="radio"][tabindex="0"]')) === null || _b === void 0 ? void 0 : _b.focus({ preventScroll: true });
|
|
122
|
+
}, [promptTick, reduced]);
|
|
123
|
+
const handleSelection = (0, react_1.useCallback)((next, matched) => {
|
|
124
|
+
if (selectionProp === undefined)
|
|
125
|
+
setInnerSelection(next);
|
|
126
|
+
if ((0, commerceVariants_1.selectionComplete)(product.axes, next))
|
|
127
|
+
setShowSelectError(false);
|
|
128
|
+
onSelectionChange === null || onSelectionChange === void 0 ? void 0 : onSelectionChange(next, matched);
|
|
129
|
+
}, [selectionProp, product.axes, onSelectionChange]);
|
|
130
|
+
const handleQuantity = (next) => {
|
|
131
|
+
if (quantityProp === undefined)
|
|
132
|
+
setInnerQuantity(next);
|
|
133
|
+
onQuantityChange === null || onQuantityChange === void 0 ? void 0 : onQuantityChange(next);
|
|
134
|
+
};
|
|
135
|
+
const promptSelection = () => {
|
|
136
|
+
setShowSelectError(true);
|
|
137
|
+
setPromptTick((tick) => tick + 1);
|
|
138
|
+
};
|
|
139
|
+
const handleAdd = async () => {
|
|
140
|
+
if (!complete || !variant) {
|
|
141
|
+
promptSelection();
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
if (bag === "in-bag") {
|
|
145
|
+
onGoToBag === null || onGoToBag === void 0 ? void 0 : onGoToBag();
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
if (bag !== "idle")
|
|
149
|
+
return;
|
|
150
|
+
setAddFailed(false);
|
|
151
|
+
try {
|
|
152
|
+
const pending = onAddToBag === null || onAddToBag === void 0 ? void 0 : onAddToBag(variant.id, quantity);
|
|
153
|
+
if (pending && typeof pending.then === "function") {
|
|
154
|
+
setBag("adding");
|
|
155
|
+
await pending;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
catch {
|
|
159
|
+
if (mounted.current) {
|
|
160
|
+
setBag("idle");
|
|
161
|
+
setAddFailed(true);
|
|
162
|
+
}
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
if (!mounted.current)
|
|
166
|
+
return;
|
|
167
|
+
setBag("added");
|
|
168
|
+
setAnnouncement(labels.addedAnnouncement);
|
|
169
|
+
timer.current = setTimeout(() => {
|
|
170
|
+
setBag(onGoToBag ? "in-bag" : "idle");
|
|
171
|
+
setAnnouncement("");
|
|
172
|
+
}, addedDuration);
|
|
35
173
|
};
|
|
36
|
-
const
|
|
37
|
-
|
|
174
|
+
const handleBuyNow = () => {
|
|
175
|
+
if (!complete || !variant) {
|
|
176
|
+
promptSelection();
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
onBuyNow === null || onBuyNow === void 0 ? void 0 : onBuyNow(variant.id, quantity);
|
|
38
180
|
};
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
181
|
+
const handleNotify = () => onNotify === null || onNotify === void 0 ? void 0 : onNotify(variant === null || variant === void 0 ? void 0 : variant.id);
|
|
182
|
+
const jumpToReviews = () => scrollToNode(reviewsRef.current, reduced);
|
|
183
|
+
const range = !variant && !complete ? (0, commerceVariants_1.priceRange)(variants) : null;
|
|
184
|
+
const price = (_a = variant === null || variant === void 0 ? void 0 : variant.price) !== null && _a !== void 0 ? _a : product.price;
|
|
185
|
+
const mrp = variant ? variant.mrp : product.mrp;
|
|
186
|
+
const showRange = range !== null && range.min !== range.max;
|
|
187
|
+
const activeIds = (0, productDetailsModel_1.activeMediaIds)(product, selection, variant);
|
|
188
|
+
const primaryLabel = bag === "added" ? labels.added : bag === "in-bag" ? labels.goToBag : notifyMode ? labels.notifyMe : labels.addToBag;
|
|
189
|
+
const barMode = notifyMode
|
|
190
|
+
? "notify"
|
|
191
|
+
: !complete
|
|
192
|
+
? "select-option"
|
|
193
|
+
: bag === "added"
|
|
194
|
+
? "added"
|
|
195
|
+
: bag === "in-bag"
|
|
196
|
+
? "go-to-bag"
|
|
197
|
+
: "add";
|
|
198
|
+
const showStepper = !notifyMode && ceiling > 0;
|
|
199
|
+
const showBuyNow = !!onBuyNow && !notifyMode && bag === "idle";
|
|
200
|
+
const ratingText = product.rating === undefined
|
|
201
|
+
? ""
|
|
202
|
+
: `Rated ${product.rating.toFixed(1)} out of 5${product.ratingCount ? ` from ${product.ratingCount.toLocaleString(locale !== null && locale !== void 0 ? locale : "en-IN")} ratings` : ""}`;
|
|
203
|
+
const mrpForLegal = variant ? ((_b = variant.mrp) !== null && _b !== void 0 ? _b : variant.price) : ((_c = product.mrp) !== null && _c !== void 0 ? _c : product.price);
|
|
204
|
+
const hasLegal = !!(product.netQuantity || product.manufacturer || product.originCountry);
|
|
205
|
+
const reviewsHeadingId = `${uid}-reviews`;
|
|
206
|
+
const showReviews = reviews !== undefined || product.ratingCount !== undefined;
|
|
207
|
+
const sectionGap = desktop ? 18 : 10;
|
|
208
|
+
const gutter = desktop ? 6 : 4;
|
|
209
|
+
const wishlist = ((0, jsx_runtime_1.jsx)(WishlistToggle_1.default, { selected: wishlisted, defaultSelected: defaultWishlisted, onSelectedChange: onWishlistChange, size: desktop ? "lg" : "md", variant: desktop ? "soft" : "glass", label: labels.wishlistSave }));
|
|
210
|
+
const badgeSlot = product.badges && product.badges.length > 0 ? (0, jsx_runtime_1.jsx)(ProductBadges_1.default, { badges: product.badges, max: 2, variant: "glass", size: "md" }) : undefined;
|
|
211
|
+
const gallery = mediaSlot !== null && mediaSlot !== void 0 ? mediaSlot : ((0, jsx_runtime_1.jsx)(MediaGallery_1.default, { media: product.media, layout: desktop ? "thumbs-left" : "swipe", aspectRatio: "4/5", activeMediaIds: activeIds, sticky: desktop, stickyTop: 24, badges: badgeSlot, actions: desktop ? undefined : wishlist, isLoading: isLoading, "aria-label": product.title }));
|
|
212
|
+
const primaryButton = ((0, jsx_runtime_1.jsx)(Button_1.default, { size: desktop ? "md" : "lg", width: "100%", variant: notifyMode ? "outline" : "solid", label: primaryLabel, leftIcon: bag === "added" ? (0, jsx_runtime_1.jsx)(lucide_react_1.Check, { size: 18, "aria-hidden": true }) : notifyMode ? (0, jsx_runtime_1.jsx)(lucide_react_1.BellRing, { size: 18, "aria-hidden": true }) : undefined, isLoading: bag === "adding", onClick: notifyMode ? handleNotify : handleAdd, fontWeight: 600 }));
|
|
213
|
+
const buyPanel = isLoading ? ((0, jsx_runtime_1.jsxs)(react_2.Flex, { direction: "column", gap: 4, "aria-busy": "true", children: [(0, jsx_runtime_1.jsx)(Skeletons_1.default, { type: "skeleton", height: "1rem", width: "30%" }), (0, jsx_runtime_1.jsx)(Skeletons_1.default, { type: "skeleton", height: "2rem", width: "90%" }), (0, jsx_runtime_1.jsx)(Skeletons_1.default, { type: "skeleton", height: "2.5rem", width: "45%" }), (0, jsx_runtime_1.jsx)(Skeletons_1.default, { type: "skeleton", height: "3rem", width: "100%" }), (0, jsx_runtime_1.jsx)(Skeletons_1.default, { type: "skeleton", height: "3rem", width: "100%" })] })) : ((0, jsx_runtime_1.jsxs)(react_2.Flex, { direction: "column", gap: 6, children: [(0, jsx_runtime_1.jsxs)(react_2.Flex, { direction: "column", gap: 2, children: [(0, jsx_runtime_1.jsxs)(react_2.Flex, { align: "center", justify: "space-between", gap: 3, minH: product.brand || onShare ? "2.75rem" : undefined, children: [product.brand ? ((0, jsx_runtime_1.jsx)(react_2.Text, { as: "span", fontSize: "sm", fontWeight: 600, color: colors.textMuted, children: product.brand })) : ((0, jsx_runtime_1.jsx)("span", {})), onShare ? ((0, jsx_runtime_1.jsx)(react_2.Box, { as: "button", type: "button", "aria-label": labels.share, onClick: onShare, display: "inline-flex", alignItems: "center", justifyContent: "center", boxSize: "2.75rem", mr: "-0.625rem", borderRadius: "full", color: colors.header[900], transition: (0, motion_1.transitionFor)(["background-color"]), _hover: { bg: colors.background[100] }, sx: { ...(0, focusRing_styles_1.focusVisibleStyles)(colors), ...(0, motion_2.reducedMotionSx)() }, children: (0, jsx_runtime_1.jsx)(lucide_react_1.Share2, { size: 20, "aria-hidden": true }) })) : null] }), (0, jsx_runtime_1.jsx)(react_2.Text, { as: "h1", fontSize: desktop ? "1.75rem" : "1.375rem", lineHeight: 1.25, fontWeight: 700, letterSpacing: "-0.02em", color: colors.header[900], children: product.title }), product.rating !== undefined && showReviews ? ((0, jsx_runtime_1.jsx)(react_2.Box, { as: "button", type: "button", onClick: jumpToReviews, "aria-label": labels.jumpToReviews(ratingText), alignSelf: "flex-start", display: "inline-flex", alignItems: "center", minH: "2.75rem", borderRadius: "md", sx: { ...(0, focusRing_styles_1.focusVisibleStyles)(colors) }, children: (0, jsx_runtime_1.jsx)(Rating_1.default, { value: product.rating, count: product.ratingCount, size: "sm", "aria-label": ratingText, locale: locale }) })) : product.rating !== undefined ? ((0, jsx_runtime_1.jsx)(Rating_1.default, { value: product.rating, count: product.ratingCount, size: "sm", locale: locale })) : null] }), (0, jsx_runtime_1.jsxs)(react_2.Flex, { direction: "column", gap: 2, children: [(0, jsx_runtime_1.jsx)(PriceBlock_1.default, { size: "lg", price: price, mrp: mrp, priceRange: showRange ? range : undefined, showSavings: true, taxNote: labels.taxNote, unitPrice: (0, productDetailsModel_1.packUnitPrice)(product, selection, price), ...fmt }), state ? (0, jsx_runtime_1.jsx)(StockStatus_1.default, { status: state, count: variant === null || variant === void 0 ? void 0 : variant.stock }) : null, metaSlot] }), offers && offers.length > 0 ? (0, jsx_runtime_1.jsx)(OffersList_1.default, { offers: offers, ...offersProps }) : null, axes.length > 0 ? ((0, jsx_runtime_1.jsx)(react_2.Box, { ref: selectorRef, children: (0, jsx_runtime_1.jsx)(VariantSelector_1.default, { axes: axes, variants: variants, value: selection, onValueChange: handleSelection, error: showSelectError && !complete ? selectPrompt : undefined, showSelectedLabel: true, showLowStock: true, onGuideClick: onGuideClick }) })) : null, (0, jsx_runtime_1.jsxs)(react_2.Flex, { direction: "column", gap: 3, ref: ctaRef, children: [(0, jsx_runtime_1.jsxs)(react_2.Flex, { align: "center", gap: 3, children: [showStepper ? ((0, jsx_runtime_1.jsx)(QuantityStepper_1.default, { size: desktop ? "md" : "lg", value: quantity, onValueChange: handleQuantity, min: 1, max: ceiling, itemLabel: product.title })) : null, (0, jsx_runtime_1.jsx)(react_2.Box, { flex: 1, minW: 0, children: primaryButton }), desktop ? wishlist : null] }), showBuyNow ? (0, jsx_runtime_1.jsx)(Button_1.default, { size: desktop ? "md" : "lg", width: "100%", variant: "outline", label: labels.buyNow, onClick: handleBuyNow }) : null, addFailed ? ((0, jsx_runtime_1.jsxs)(react_2.Flex, { role: "alert", align: "center", gap: 1.5, color: colors.semanticText.error, fontSize: "sm", fontWeight: 600, children: [(0, jsx_runtime_1.jsx)(lucide_react_1.CircleAlert, { size: 14, "aria-hidden": true }), (0, jsx_runtime_1.jsx)(react_2.Text, { as: "span", children: labels.addFailed })] })) : null] }), pincode ? (0, jsx_runtime_1.jsx)(PincodeChecker_1.default, { ...pincode }) : null, trustItems && trustItems.length > 0 ? (0, jsx_runtime_1.jsx)(TrustBadges_1.default, { items: trustItems, layout: desktop ? "grid" : "row" }) : null, infoSlot] }));
|
|
214
|
+
return ((0, jsx_runtime_1.jsxs)(react_2.Box, { ref: rootRef, "data-testid": testId, "data-layout": desktop ? "desktop" : "mobile", w: "100%", maxW: "82rem", mx: "auto", px: desktop ? 6 : 0, children: [(0, jsx_runtime_1.jsx)(react_2.VisuallyHidden, { role: "status", "aria-live": "polite", "aria-atomic": "true", children: announcement }), breadcrumbs ? (0, jsx_runtime_1.jsx)(react_2.Box, { px: desktop ? 0 : gutter, py: 3, children: breadcrumbs }) : null, (0, jsx_runtime_1.jsxs)(react_2.Flex, { direction: desktop ? "row" : "column", align: desktop ? "flex-start" : "stretch", gap: desktop ? 12 : 5, children: [(0, jsx_runtime_1.jsx)(react_2.Box, { flex: desktop ? "1.63 1 0" : undefined, minW: 0, w: desktop ? undefined : "100%", children: gallery }), (0, jsx_runtime_1.jsx)(react_2.Box, { flex: desktop ? "1 1 0" : undefined, minW: 0, px: desktop ? 0 : gutter, children: buyPanel })] }), !isLoading ? ((0, jsx_runtime_1.jsxs)(react_2.Flex, { direction: "column", gap: sectionGap, mt: sectionGap, px: desktop ? 0 : gutter, children: [(0, jsx_runtime_1.jsx)(DetailSections_1.default, { description: product.description, highlights: product.highlights, specs: product.specs, care: care, shipping: product.returnsNote, legal: hasLegal
|
|
215
|
+
? {
|
|
216
|
+
netQuantity: product.netQuantity,
|
|
217
|
+
manufacturer: product.manufacturer,
|
|
218
|
+
originCountry: product.originCountry,
|
|
219
|
+
mrpNote: `${(0, price_1.formatPrice)(mrpForLegal, fmt)} · ${(_e = (_d = detailSectionsProps === null || detailSectionsProps === void 0 ? void 0 : detailSectionsProps.labels) === null || _d === void 0 ? void 0 : _d.mrpIncludesTaxes) !== null && _e !== void 0 ? _e : "Maximum retail price, inclusive of all taxes"}`,
|
|
220
|
+
}
|
|
221
|
+
: undefined, defaultOpenIds: desktop ? ["description", "highlights", "specs"] : undefined, ...detailSectionsProps }), showReviews ? ((0, jsx_runtime_1.jsx)(react_2.Box, { ref: reviewsRef, children: (0, jsx_runtime_1.jsxs)(react_2.Flex, { direction: "column", gap: 6, children: [(0, jsx_runtime_1.jsx)(ReviewSummary_1.default, { id: reviewsHeadingId, rating: (_f = product.rating) !== null && _f !== void 0 ? _f : 0, count: (_h = (_g = product.ratingCount) !== null && _g !== void 0 ? _g : reviews === null || reviews === void 0 ? void 0 : reviews.length) !== null && _h !== void 0 ? _h : 0, breakdown: ratingBreakdown, onWriteReview: onWriteReview, locale: locale }), reviews && (reviews.length > 0 || (reviewsProps === null || reviewsProps === void 0 ? void 0 : reviewsProps.isLoading)) ? ((0, jsx_runtime_1.jsx)(ReviewList_1.default, { reviews: reviews, locale: locale, ...reviewsProps })) : null] }) })) : null, belowFold, relatedSlot] })) : null, !desktop && !isLoading ? ((0, jsx_runtime_1.jsx)(StickyBuyBar_1.default, { price: price, mrp: mrp, mode: barMode, visible: !ctaInView, isLoading: bag === "adding", itemLabel: product.title, onAddToBag: handleAdd, onSelectOption: promptSelection, onNotify: handleNotify, onGoToBag: () => onGoToBag === null || onGoToBag === void 0 ? void 0 : onGoToBag(), onBuyNow: onBuyNow ? handleBuyNow : undefined, labels: { add: labels.addToBag, selectOption: selectPrompt || labels.addToBag, notify: labels.notifyMe, added: labels.added, goToBag: labels.goToBag, buyNow: labels.buyNow }, ...fmt })) : null] }));
|
|
46
222
|
};
|
|
47
223
|
exports.default = ProductDetails;
|
|
@@ -1,41 +1,143 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import type { OptionAxis, PriceFormat, ProductBadge, ProductMedia, ProductVariant, VariantSelection } from "../Commerce/commerceTypes";
|
|
3
|
+
import type { DetailSectionsProps } from "../DetailSections/DetailSectionsProps";
|
|
4
|
+
import type { Offer, OffersListProps } from "../OffersList/OffersListProps";
|
|
5
|
+
import type { PincodeCheckerProps } from "../PincodeChecker/PincodeCheckerProps";
|
|
6
|
+
import type { RatingBreakdown } from "../ReviewSummary/ReviewSummaryProps";
|
|
7
|
+
import type { ReviewItem, ReviewListProps } from "../ReviewList/ReviewListProps";
|
|
8
|
+
import type { SpecItem } from "../SpecTable/SpecTableProps";
|
|
9
|
+
import type { TrustItem } from "../TrustBadges/TrustBadgesProps";
|
|
10
|
+
/** The catalogue record the page renders; structurally compatible with a store's product so it can be passed straight through. */
|
|
11
|
+
export interface ProductDetailsProduct {
|
|
12
|
+
title: string;
|
|
13
|
+
brand?: string;
|
|
14
|
+
description?: string;
|
|
15
|
+
highlights?: string[];
|
|
16
|
+
specs?: SpecItem[];
|
|
17
|
+
/** Every frame the product has; variants and `mediaIdsByOption` pick which ones show. */
|
|
18
|
+
media: ProductMedia[];
|
|
19
|
+
/** Option axes in display order; an empty list means the product has nothing to choose. */
|
|
20
|
+
axes: OptionAxis[];
|
|
21
|
+
/** Every sellable combination with its own price and stock; empty falls back to one variant at `price`. */
|
|
22
|
+
variants: ProductVariant[];
|
|
23
|
+
/** Price shown until a variant is picked, and the fallback when a variant carries none. */
|
|
24
|
+
price: number;
|
|
25
|
+
mrp?: number;
|
|
26
|
+
/** Average rating, 0 to 5. */
|
|
27
|
+
rating?: number;
|
|
28
|
+
ratingCount?: number;
|
|
29
|
+
/** Corner badges on the gallery, e.g. "Bestseller". */
|
|
30
|
+
badges?: ProductBadge[];
|
|
31
|
+
/** Base unit for the "per 100 g" line; needs a `pack` axis whose values carry `quantity`. */
|
|
32
|
+
unit?: {
|
|
33
|
+
unit: string;
|
|
34
|
+
per: number;
|
|
35
|
+
};
|
|
36
|
+
/** Frame ids per picked option, keyed "axisId:valueId"; a variant's own `mediaIds` wins. */
|
|
37
|
+
mediaIdsByOption?: Record<string, string[]>;
|
|
38
|
+
/** Shipping and returns copy for the details section. */
|
|
39
|
+
returnsNote?: string;
|
|
40
|
+
originCountry?: string;
|
|
41
|
+
manufacturer?: string;
|
|
42
|
+
/** Legal-metrology net quantity such as "500 g". */
|
|
43
|
+
netQuantity?: string;
|
|
44
|
+
}
|
|
45
|
+
/** `auto` follows the viewport: two columns from 1024px up, the single-column phone page with a sticky buy bar below it. */
|
|
46
|
+
export type ProductDetailsLayout = "auto" | "desktop" | "mobile";
|
|
47
|
+
/** Every string the page itself renders; sub-components take their own `labels` through their prop pass-throughs. */
|
|
48
|
+
export interface ProductDetailsLabels {
|
|
49
|
+
addToBag: string;
|
|
50
|
+
buyNow: string;
|
|
51
|
+
notifyMe: string;
|
|
52
|
+
goToBag: string;
|
|
53
|
+
/** Short confirmation in the button right after an add. */
|
|
54
|
+
added: string;
|
|
55
|
+
/** Screen-reader announcement after an add. */
|
|
56
|
+
addedAnnouncement: string;
|
|
57
|
+
/** Shown when `onAddToBag` rejects. */
|
|
58
|
+
addFailed: string;
|
|
59
|
+
/** Prompt for an unpicked axis, given its lower-cased label: "Select a size". */
|
|
60
|
+
selectPrompt: (axisLabel: string) => string;
|
|
61
|
+
taxNote: string;
|
|
62
|
+
/** Accessible name of the rating link that scrolls to the reviews. */
|
|
63
|
+
jumpToReviews: (ratingText: string) => string;
|
|
64
|
+
share: string;
|
|
65
|
+
wishlistSave: string;
|
|
66
|
+
}
|
|
67
|
+
/** The composed product page: gallery, buy panel, details and reviews, wired so the picked variant drives price, stock, frames and the primary action. */
|
|
68
|
+
export interface ProductDetailsProps extends PriceFormat {
|
|
69
|
+
product: ProductDetailsProduct;
|
|
70
|
+
/** Controlled selection, axis id to option value id; nothing is preselected, because a size the shopper never chose is a wrong order. */
|
|
71
|
+
selection?: VariantSelection;
|
|
72
|
+
defaultSelection?: VariantSelection;
|
|
73
|
+
/** Receives the new selection and the matching variant, or undefined while it is incomplete. */
|
|
74
|
+
onSelectionChange?: (selection: VariantSelection, variant: ProductVariant | undefined) => void;
|
|
75
|
+
/** Controlled quantity, clamped to the variant's remaining stock and `maxQuantity`. */
|
|
76
|
+
quantity?: number;
|
|
77
|
+
defaultQuantity?: number;
|
|
78
|
+
onQuantityChange?: (quantity: number) => void;
|
|
79
|
+
/** Per-order ceiling; the variant's remaining stock lowers it further. */
|
|
80
|
+
maxQuantity?: number;
|
|
81
|
+
/** Fires with the variant id and quantity; a returned promise keeps the button busy, and a rejection shows `labels.addFailed`. */
|
|
82
|
+
onAddToBag?: (variantId: string, quantity: number) => void | Promise<unknown>;
|
|
83
|
+
/** Adds a secondary "Buy now" beside the primary; incomplete selections get the same prompt as Add to bag. */
|
|
84
|
+
onBuyNow?: (variantId: string, quantity: number) => void;
|
|
85
|
+
/** Fires from "Notify me" with the variant id, or undefined when every variant is sold out. */
|
|
86
|
+
onNotify?: (variantId: string | undefined) => void;
|
|
87
|
+
/** When set, a successful add morphs the button to "Added" and then to "Go to bag", which calls this. */
|
|
88
|
+
onGoToBag?: () => void;
|
|
89
|
+
/** How long "Added" shows before the button becomes "Go to bag", in ms. */
|
|
90
|
+
addedDuration?: number;
|
|
91
|
+
/** Controlled wishlist state; pair with `onWishlistChange`. */
|
|
92
|
+
wishlisted?: boolean;
|
|
93
|
+
defaultWishlisted?: boolean;
|
|
94
|
+
onWishlistChange?: (wishlisted: boolean) => void;
|
|
95
|
+
/** Shows a share button beside the title. */
|
|
96
|
+
onShare?: () => void;
|
|
97
|
+
/** Shown as one collapsed row under the price. */
|
|
98
|
+
offers?: Offer[];
|
|
99
|
+
/** Pass-through to `OffersList`, e.g. `onCopy`. */
|
|
100
|
+
offersProps?: Partial<OffersListProps>;
|
|
101
|
+
/** Reassurance tiles under the delivery check. */
|
|
102
|
+
trustItems?: TrustItem[];
|
|
103
|
+
/** Shows the delivery checker when given; pass-through to `PincodeChecker`. */
|
|
104
|
+
pincode?: PincodeCheckerProps;
|
|
105
|
+
/** Adds a size-guide link to the axis with `axisId` (default "size") unless that axis already has a `guide`. */
|
|
106
|
+
sizeGuide?: {
|
|
107
|
+
label?: string;
|
|
108
|
+
axisId?: string;
|
|
109
|
+
onClick: () => void;
|
|
110
|
+
};
|
|
111
|
+
/** Also fired when any axis guide link is clicked, with the axis id. */
|
|
112
|
+
onGuideClick?: (axisId: string) => void;
|
|
113
|
+
/** Reviews to list; omit both this and `product.ratingCount` to leave the reviews section out. */
|
|
114
|
+
reviews?: ReviewItem[];
|
|
115
|
+
/** Counts per star for the distribution bars. */
|
|
116
|
+
ratingBreakdown?: RatingBreakdown;
|
|
117
|
+
/** Pass-through to `ReviewList`, e.g. `sortSlot`, `hasMore`, `onLoadMore`, `onHelpful`. */
|
|
118
|
+
reviewsProps?: Partial<ReviewListProps>;
|
|
119
|
+
/** Shows "Write a review" in the summary. */
|
|
120
|
+
onWriteReview?: () => void;
|
|
121
|
+
/** Pass-through to `DetailSections`; `sections` there adds or replaces a section. */
|
|
122
|
+
detailSectionsProps?: Partial<DetailSectionsProps>;
|
|
123
|
+
/** Care instructions for the details section. */
|
|
124
|
+
care?: string | string[];
|
|
125
|
+
/** Rendered above the gallery, e.g. a breadcrumb trail. */
|
|
126
|
+
breadcrumbs?: ReactNode;
|
|
127
|
+
/** `auto` splits into gallery and buy panel from 960px of the component's own width, not the window. */
|
|
128
|
+
layout?: ProductDetailsLayout;
|
|
129
|
+
/** Replaces the gallery; its frames, badges and wishlist toggle go with it. */
|
|
130
|
+
mediaSlot?: ReactNode;
|
|
131
|
+
/** Extra content in the buy panel under the price, e.g. an EMI line. */
|
|
132
|
+
metaSlot?: ReactNode;
|
|
133
|
+
/** Extra content at the end of the buy panel. */
|
|
134
|
+
infoSlot?: ReactNode;
|
|
135
|
+
/** Extra content after the reviews. */
|
|
136
|
+
belowFold?: ReactNode;
|
|
137
|
+
/** Rendered last, e.g. a "You may also like" rail. */
|
|
138
|
+
relatedSlot?: ReactNode;
|
|
139
|
+
/** Skeleton in place of the gallery and buy panel. */
|
|
140
|
+
isLoading?: boolean;
|
|
141
|
+
labels?: Partial<ProductDetailsLabels>;
|
|
142
|
+
"data-testid"?: string;
|
|
143
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { OptionAxis, ProductVariant, VariantSelection } from "../Commerce/commerceTypes";
|
|
2
|
+
import type { UnitPrice } from "../../Utils/price";
|
|
3
|
+
import type { ProductDetailsProduct } from "./ProductDetailsProps";
|
|
4
|
+
export declare const DEFAULT_MAX_QUANTITY = 10;
|
|
5
|
+
/** A product without variants sells as one variant at its own price. */
|
|
6
|
+
export declare const resolveVariants: (product: ProductDetailsProduct) => ProductVariant[];
|
|
7
|
+
/** A variant's own frames win; otherwise the frames of each picked option, in axis order. */
|
|
8
|
+
export declare const activeMediaIds: (product: ProductDetailsProduct, selection: VariantSelection, variant: ProductVariant | undefined) => string[] | undefined;
|
|
9
|
+
export declare const packUnitPrice: (product: ProductDetailsProduct, selection: VariantSelection, price: number) => UnitPrice | null;
|
|
10
|
+
export declare const firstUnpickedAxis: (axes: OptionAxis[], selection: VariantSelection) => OptionAxis | undefined;
|
|
11
|
+
export declare const soldOutEverywhere: (variants: ProductVariant[]) => boolean;
|
|
12
|
+
/** Real remaining stock caps the order; backorder and untracked stock fall back to the per-order ceiling. */
|
|
13
|
+
export declare const quantityCeiling: (variant: ProductVariant | undefined, maxQuantity: number) => number;
|
|
14
|
+
export declare const clampQuantity: (value: number, ceiling: number) => number;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.clampQuantity = exports.quantityCeiling = exports.soldOutEverywhere = exports.firstUnpickedAxis = exports.packUnitPrice = exports.activeMediaIds = exports.resolveVariants = exports.DEFAULT_MAX_QUANTITY = void 0;
|
|
4
|
+
const commerceVariants_1 = require("../Commerce/commerceVariants");
|
|
5
|
+
const price_1 = require("../../Utils/price");
|
|
6
|
+
exports.DEFAULT_MAX_QUANTITY = 10;
|
|
7
|
+
/** A product without variants sells as one variant at its own price. */
|
|
8
|
+
const resolveVariants = (product) => product.variants.length > 0
|
|
9
|
+
? product.variants
|
|
10
|
+
: [{ id: "default", options: {}, price: product.price, mrp: product.mrp }];
|
|
11
|
+
exports.resolveVariants = resolveVariants;
|
|
12
|
+
/** A variant's own frames win; otherwise the frames of each picked option, in axis order. */
|
|
13
|
+
const activeMediaIds = (product, selection, variant) => {
|
|
14
|
+
if ((variant === null || variant === void 0 ? void 0 : variant.mediaIds) && variant.mediaIds.length > 0)
|
|
15
|
+
return variant.mediaIds;
|
|
16
|
+
const byOption = product.mediaIdsByOption;
|
|
17
|
+
if (!byOption)
|
|
18
|
+
return undefined;
|
|
19
|
+
const ids = product.axes.flatMap((axis) => { var _a; return (_a = byOption[`${axis.id}:${selection[axis.id]}`]) !== null && _a !== void 0 ? _a : []; });
|
|
20
|
+
return ids.length > 0 ? [...new Set(ids)] : undefined;
|
|
21
|
+
};
|
|
22
|
+
exports.activeMediaIds = activeMediaIds;
|
|
23
|
+
const packUnitPrice = (product, selection, price) => {
|
|
24
|
+
if (!product.unit)
|
|
25
|
+
return null;
|
|
26
|
+
const axis = product.axes.find((candidate) => candidate.type === "pack");
|
|
27
|
+
const picked = axis === null || axis === void 0 ? void 0 : axis.values.find((value) => value.id === selection[axis.id]);
|
|
28
|
+
if (!(picked === null || picked === void 0 ? void 0 : picked.quantity))
|
|
29
|
+
return null;
|
|
30
|
+
return (0, price_1.unitPrice)(price, picked.quantity, product.unit.unit, product.unit.per);
|
|
31
|
+
};
|
|
32
|
+
exports.packUnitPrice = packUnitPrice;
|
|
33
|
+
const firstUnpickedAxis = (axes, selection) => axes.find((axis) => selection[axis.id] === undefined);
|
|
34
|
+
exports.firstUnpickedAxis = firstUnpickedAxis;
|
|
35
|
+
const soldOutEverywhere = (variants) => variants.length > 0 && variants.every((variant) => (0, commerceVariants_1.stockState)(variant) === "out-of-stock");
|
|
36
|
+
exports.soldOutEverywhere = soldOutEverywhere;
|
|
37
|
+
/** Real remaining stock caps the order; backorder and untracked stock fall back to the per-order ceiling. */
|
|
38
|
+
const quantityCeiling = (variant, maxQuantity) => {
|
|
39
|
+
if ((variant === null || variant === void 0 ? void 0 : variant.stock) === undefined || variant.backorder)
|
|
40
|
+
return maxQuantity;
|
|
41
|
+
return Math.max(0, Math.min(variant.stock, maxQuantity));
|
|
42
|
+
};
|
|
43
|
+
exports.quantityCeiling = quantityCeiling;
|
|
44
|
+
const clampQuantity = (value, ceiling) => Math.max(1, Math.min(value, Math.max(1, ceiling)));
|
|
45
|
+
exports.clampQuantity = clampQuantity;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useInViewport = void 0;
|
|
4
|
+
const react_1 = require("react");
|
|
5
|
+
/** Whether the element is on screen; true until an observer reports otherwise, and always true where IntersectionObserver is missing. */
|
|
6
|
+
const useInViewport = (ref, enabled = true) => {
|
|
7
|
+
const [inView, setInView] = (0, react_1.useState)(true);
|
|
8
|
+
(0, react_1.useEffect)(() => {
|
|
9
|
+
const node = ref.current;
|
|
10
|
+
if (!enabled || !node || typeof IntersectionObserver === "undefined")
|
|
11
|
+
return undefined;
|
|
12
|
+
const observer = new IntersectionObserver(([entry]) => setInView(entry.isIntersecting));
|
|
13
|
+
observer.observe(node);
|
|
14
|
+
return () => observer.disconnect();
|
|
15
|
+
}, [ref, enabled]);
|
|
16
|
+
return inView;
|
|
17
|
+
};
|
|
18
|
+
exports.useInViewport = useInViewport;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { QuantityStepperProps } from "./QuantityStepperProps";
|
|
2
|
+
/** Pill stepper for quantities: soft or outline, trash at the floor on cart lines, limits announced via aria-disabled. */
|
|
3
|
+
declare const QuantityStepper: ({ value, defaultValue, onValueChange, min, max, step, size, variant, removable, onRemove, disabled, itemLabel, "data-testid": testId, }: QuantityStepperProps) => import("react/jsx-runtime").JSX.Element;
|
|
4
|
+
export default QuantityStepper;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
4
|
+
const react_1 = require("react");
|
|
5
|
+
const react_2 = require("@chakra-ui/react");
|
|
6
|
+
const lucide_react_1 = require("lucide-react");
|
|
7
|
+
const useCustomTheme_1 = require("../../Theme/useCustomTheme");
|
|
8
|
+
const controlSizes_1 = require("../../Theme/tokens/primitives/controlSizes");
|
|
9
|
+
const motion_1 = require("../../Theme/tokens/primitives/motion");
|
|
10
|
+
const motion_2 = require("../../Theme/chakra/motion");
|
|
11
|
+
const focusRing_styles_1 = require("../../Theme/chakra/focusRing.styles");
|
|
12
|
+
const MIN_HIT = "2.75rem";
|
|
13
|
+
const LIMIT_OPACITY = 0.4;
|
|
14
|
+
const clamp = (n, min, max) => Math.max(min, max === undefined ? n : Math.min(max, n));
|
|
15
|
+
/** Pill stepper for quantities: soft or outline, trash at the floor on cart lines, limits announced via aria-disabled. */
|
|
16
|
+
const QuantityStepper = ({ value, defaultValue, onValueChange, min = 1, max, step = 1, size = "md", variant = "soft", removable = false, onRemove, disabled = false, itemLabel, "data-testid": testId, }) => {
|
|
17
|
+
const { colors } = (0, useCustomTheme_1.useCustomTheme)();
|
|
18
|
+
const spec = controlSizes_1.BUTTON_SIZES[size];
|
|
19
|
+
const [inner, setInner] = (0, react_1.useState)(defaultValue !== null && defaultValue !== void 0 ? defaultValue : min);
|
|
20
|
+
const current = value !== null && value !== void 0 ? value : inner;
|
|
21
|
+
const atMin = current <= min;
|
|
22
|
+
const atMax = max !== undefined && current >= max;
|
|
23
|
+
const trash = removable && atMin;
|
|
24
|
+
const subject = itemLabel ? ` of ${itemLabel}` : "";
|
|
25
|
+
const change = (direction) => {
|
|
26
|
+
const next = clamp(current + direction * step, min, max);
|
|
27
|
+
if (next === current)
|
|
28
|
+
return;
|
|
29
|
+
if (value === undefined)
|
|
30
|
+
setInner(next);
|
|
31
|
+
onValueChange === null || onValueChange === void 0 ? void 0 : onValueChange(next);
|
|
32
|
+
};
|
|
33
|
+
const surface = variant === "outline"
|
|
34
|
+
? { bg: "transparent", boxShadow: `inset 0 0 0 1px ${colors.boxborder[500]}` }
|
|
35
|
+
: { bg: colors.background[100], boxShadow: "none" };
|
|
36
|
+
const button = (kind) => {
|
|
37
|
+
const limited = kind === "dec" ? atMin && !trash : atMax;
|
|
38
|
+
const Icon = kind === "inc" ? lucide_react_1.Plus : trash ? lucide_react_1.Trash2 : lucide_react_1.Minus;
|
|
39
|
+
const label = kind === "inc" ? `Increase quantity${subject}` : trash ? `Remove${itemLabel ? ` ${itemLabel}` : ""}` : `Decrease quantity${subject}`;
|
|
40
|
+
return ((0, jsx_runtime_1.jsx)(react_2.Box, { as: "button", type: "button", "aria-label": label, "aria-disabled": limited || undefined, disabled: disabled, "data-testid": testId ? `${testId}-${kind}` : undefined, onClick: () => {
|
|
41
|
+
if (limited)
|
|
42
|
+
return;
|
|
43
|
+
if (kind === "dec" && trash)
|
|
44
|
+
onRemove === null || onRemove === void 0 ? void 0 : onRemove();
|
|
45
|
+
else
|
|
46
|
+
change(kind === "inc" ? 1 : -1);
|
|
47
|
+
}, position: "relative", display: "inline-flex", alignItems: "center", justifyContent: "center", flexShrink: 0, boxSize: spec.height, borderRadius: "full", color: colors.header[900], opacity: limited || disabled ? LIMIT_OPACITY : 1, cursor: limited || disabled ? "not-allowed" : "pointer", transition: (0, motion_1.transitionFor)(["background-color", "transform", "opacity"]), _hover: limited || disabled ? undefined : { bg: colors.background[200] }, _active: limited || disabled ? undefined : { transform: "scale(0.96)" }, sx: {
|
|
48
|
+
...(0, focusRing_styles_1.focusVisibleStyles)(colors),
|
|
49
|
+
...(0, motion_2.reducedMotionSx)({ "&:active": { transform: "none" } }),
|
|
50
|
+
"&::before": {
|
|
51
|
+
content: '""',
|
|
52
|
+
position: "absolute",
|
|
53
|
+
inset: `max(0px, calc((${MIN_HIT} - ${spec.height}) / -2))`,
|
|
54
|
+
},
|
|
55
|
+
}, children: (0, jsx_runtime_1.jsx)(Icon, { size: spec.iconSize, "aria-hidden": true }) }));
|
|
56
|
+
};
|
|
57
|
+
return ((0, jsx_runtime_1.jsxs)(react_2.Flex, { role: "group", "aria-label": `Quantity${subject}`, display: "inline-flex", align: "center", h: spec.height, borderRadius: "full", ...surface, "data-testid": testId, children: [button("dec"), (0, jsx_runtime_1.jsx)(react_2.Text, { as: "span", "aria-live": "polite", "aria-atomic": "true", minW: "1.75rem", textAlign: "center", fontSize: spec.fontSize, fontWeight: 600, color: colors.header[900], sx: { fontVariantNumeric: "tabular-nums" }, children: current }), button("inc")] }));
|
|
58
|
+
};
|
|
59
|
+
exports.default = QuantityStepper;
|