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
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { findVariant, isOptionAvailable, priceRange, stockState } from "../Commerce/commerceVariants.js";
|
|
2
|
+
export const DEFAULT_SWATCH_LIMIT = 3;
|
|
3
|
+
export const hasChoice = (axes) => axes.some((axis) => axis.values.length > 1);
|
|
4
|
+
/** The first colour-like axis whose values all carry a swatch; the card draws dots only for this one. */
|
|
5
|
+
export const swatchAxisOf = (axes) => axes.find((axis) => (axis.type === "swatch" || axis.type === "image-tile") &&
|
|
6
|
+
axis.values.length > 1 &&
|
|
7
|
+
axis.values.every((value) => value.swatch));
|
|
8
|
+
/** The one variant a product without a real choice resolves to, when there is one. */
|
|
9
|
+
export const soleVariantOf = (axes, variants) => {
|
|
10
|
+
var _a;
|
|
11
|
+
if (hasChoice(axes))
|
|
12
|
+
return undefined;
|
|
13
|
+
const selection = {};
|
|
14
|
+
axes.forEach((axis) => {
|
|
15
|
+
if (axis.values[0])
|
|
16
|
+
selection[axis.id] = axis.values[0].id;
|
|
17
|
+
});
|
|
18
|
+
return (_a = findVariant(axes, variants, selection)) !== null && _a !== void 0 ? _a : (axes.length === 0 ? variants[0] : undefined);
|
|
19
|
+
};
|
|
20
|
+
export const isSoldOut = (outOfStock, stock, variants) => {
|
|
21
|
+
if (outOfStock !== undefined)
|
|
22
|
+
return outOfStock;
|
|
23
|
+
if (stock !== undefined)
|
|
24
|
+
return stock <= 0;
|
|
25
|
+
return variants.length > 0 && variants.every((variant) => stockState(variant) === "out-of-stock");
|
|
26
|
+
};
|
|
27
|
+
/** Units left, only when a real count says the product is low; undefined otherwise. */
|
|
28
|
+
export const lowStockCount = (stock, sole) => {
|
|
29
|
+
const count = stock !== null && stock !== void 0 ? stock : sole === null || sole === void 0 ? void 0 : sole.stock;
|
|
30
|
+
if (count === undefined)
|
|
31
|
+
return undefined;
|
|
32
|
+
const state = stockState({ stock: count, backorder: sole === null || sole === void 0 ? void 0 : sole.backorder });
|
|
33
|
+
return state === "low-stock" ? count : undefined;
|
|
34
|
+
};
|
|
35
|
+
export const deriveAction = (override, soldOut, axes) => {
|
|
36
|
+
if (override)
|
|
37
|
+
return override;
|
|
38
|
+
if (soldOut)
|
|
39
|
+
return "notify";
|
|
40
|
+
return hasChoice(axes) ? "options" : "add";
|
|
41
|
+
};
|
|
42
|
+
const optionKey = (axisId, valueId) => `${axisId}:${valueId}`;
|
|
43
|
+
/** Frames for the active swatch value: its mapped media, else the whole pool. */
|
|
44
|
+
export const framesFor = (media, mediaIdsByOption, axisId, valueId) => {
|
|
45
|
+
if (!axisId || !valueId || !mediaIdsByOption)
|
|
46
|
+
return media;
|
|
47
|
+
const ids = mediaIdsByOption[optionKey(axisId, valueId)];
|
|
48
|
+
if (!ids)
|
|
49
|
+
return media;
|
|
50
|
+
const frames = ids.map((id) => media.find((item) => item.id === id)).filter((item) => !!item);
|
|
51
|
+
return frames.length > 0 ? frames : media;
|
|
52
|
+
};
|
|
53
|
+
/** Variants that share the picked colour, so the price range follows the dot. */
|
|
54
|
+
export const variantsFor = (variants, axisId, valueId) => {
|
|
55
|
+
if (!axisId || !valueId)
|
|
56
|
+
return variants;
|
|
57
|
+
const scoped = variants.filter((variant) => variant.options[axisId] === valueId);
|
|
58
|
+
return scoped.length > 0 ? scoped : variants;
|
|
59
|
+
};
|
|
60
|
+
export const rangeOf = (variants) => {
|
|
61
|
+
const range = priceRange(variants);
|
|
62
|
+
return range && range.min !== range.max ? range : undefined;
|
|
63
|
+
};
|
|
64
|
+
export const valueSoldOut = (variants, axisId, valueId) => variants.length > 0 && !isOptionAvailable(variants, {}, axisId, valueId);
|
|
65
|
+
export const firstMissingAxis = (axes, selection) => axes.find((axis) => selection[axis.id] === undefined);
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
|
+
const supported = () => typeof window !== "undefined" && typeof window.matchMedia === "function";
|
|
3
|
+
/** `matches` for a media query; false where matchMedia does not exist (SSR, jsdom). */
|
|
4
|
+
export const useMinWidth = (query) => {
|
|
5
|
+
const [matches, setMatches] = useState(() => (supported() ? window.matchMedia(query).matches : false));
|
|
6
|
+
useEffect(() => {
|
|
7
|
+
if (!supported())
|
|
8
|
+
return undefined;
|
|
9
|
+
const list = window.matchMedia(query);
|
|
10
|
+
const onChange = () => setMatches(list.matches);
|
|
11
|
+
onChange();
|
|
12
|
+
list.addEventListener("change", onChange);
|
|
13
|
+
return () => list.removeEventListener("change", onChange);
|
|
14
|
+
}, [query]);
|
|
15
|
+
return matches;
|
|
16
|
+
};
|
|
@@ -1,42 +1,218 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import
|
|
3
|
-
import { Box, Flex, Text,
|
|
2
|
+
import { useCallback, useEffect, useId, useMemo, useRef, useState } from "react";
|
|
3
|
+
import { Box, Flex, Text, VisuallyHidden } from "@chakra-ui/react";
|
|
4
|
+
import { BellRing, Check, CircleAlert, Share2 } from "lucide-react";
|
|
4
5
|
import { useCustomTheme } from "../../Theme/useCustomTheme.js";
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import
|
|
6
|
+
import { transitionFor } from "../../Theme/tokens/primitives/motion.js";
|
|
7
|
+
import { reducedMotionSx, usePrefersReducedMotion } from "../../Theme/chakra/motion.js";
|
|
8
|
+
import { focusVisibleStyles } from "../../Theme/chakra/focusRing.styles.js";
|
|
9
|
+
import { formatPrice } from "../../Utils/price.js";
|
|
9
10
|
import Button from "../Button/Button.js";
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
-
import
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
import Skeletons from "../Skeletons/Skeletons.js";
|
|
12
|
+
import MediaGallery from "../MediaGallery/MediaGallery.js";
|
|
13
|
+
import { useContainerWidth } from "../Commerce/useContainerWidth.js";
|
|
14
|
+
import { useMatchMedia } from "../MediaGallery/useMatchMedia.js";
|
|
15
|
+
import ProductBadges from "../ProductBadges/ProductBadges.js";
|
|
16
|
+
import Rating from "../Rating/Rating.js";
|
|
17
|
+
import PriceBlock from "../PriceBlock/PriceBlock.js";
|
|
18
|
+
import StockStatus from "../StockStatus/StockStatus.js";
|
|
19
|
+
import WishlistToggle from "../WishlistToggle/WishlistToggle.js";
|
|
20
|
+
import VariantSelector from "../VariantSelector/VariantSelector.js";
|
|
21
|
+
import QuantityStepper from "../QuantityStepper/QuantityStepper.js";
|
|
22
|
+
import OffersList from "../OffersList/OffersList.js";
|
|
23
|
+
import PincodeChecker from "../PincodeChecker/PincodeChecker.js";
|
|
24
|
+
import TrustBadges from "../TrustBadges/TrustBadges.js";
|
|
25
|
+
import StickyBuyBar from "../StickyBuyBar/StickyBuyBar.js";
|
|
26
|
+
import DetailSections from "../DetailSections/DetailSections.js";
|
|
27
|
+
import ReviewSummary from "../ReviewSummary/ReviewSummary.js";
|
|
28
|
+
import ReviewList from "../ReviewList/ReviewList.js";
|
|
29
|
+
import { findVariant, priceRange, selectionComplete, stockState } from "../Commerce/commerceVariants.js";
|
|
30
|
+
import { DEFAULT_MAX_QUANTITY, activeMediaIds, clampQuantity, firstUnpickedAxis, packUnitPrice, quantityCeiling, resolveVariants, soldOutEverywhere, } from "./productDetailsModel.js";
|
|
31
|
+
import { useInViewport } from "./useInViewport.js";
|
|
32
|
+
const DESKTOP_QUERY = "(min-width: 1024px)";
|
|
33
|
+
const DESKTOP_MIN_WIDTH = 960;
|
|
34
|
+
const DEFAULT_ADDED_MS = 1600;
|
|
35
|
+
const DEFAULT_LABELS = {
|
|
36
|
+
addToBag: "Add to bag",
|
|
37
|
+
buyNow: "Buy now",
|
|
38
|
+
notifyMe: "Notify me",
|
|
39
|
+
goToBag: "Go to bag",
|
|
40
|
+
added: "Added",
|
|
41
|
+
addedAnnouncement: "Added to bag",
|
|
42
|
+
addFailed: "Couldn't add this to your bag. Try again.",
|
|
43
|
+
selectPrompt: (axisLabel) => `Select a ${axisLabel}`,
|
|
44
|
+
taxNote: "Inclusive of all taxes",
|
|
45
|
+
jumpToReviews: (ratingText) => `${ratingText}. Go to reviews`,
|
|
46
|
+
share: "Share",
|
|
47
|
+
wishlistSave: "Save for later",
|
|
48
|
+
};
|
|
49
|
+
const withGuide = (axes, guide) => {
|
|
50
|
+
var _a;
|
|
51
|
+
if (!guide)
|
|
52
|
+
return axes;
|
|
53
|
+
const axisId = (_a = guide.axisId) !== null && _a !== void 0 ? _a : "size";
|
|
54
|
+
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; });
|
|
55
|
+
};
|
|
56
|
+
const scrollToNode = (node, reduced) => {
|
|
57
|
+
if (node && typeof node.scrollIntoView === "function") {
|
|
58
|
+
node.scrollIntoView({ behavior: reduced ? "auto" : "smooth", block: "center" });
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
/** Product page that wires one selection to price, stock, gallery frames and the primary action; every region has a slot. */
|
|
62
|
+
const ProductDetails = ({ product, selection: selectionProp, defaultSelection, onSelectionChange, quantity: quantityProp, defaultQuantity = 1, onQuantityChange, maxQuantity = 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, }) => {
|
|
63
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
15
64
|
const { colors } = useCustomTheme();
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
65
|
+
const reduced = usePrefersReducedMotion();
|
|
66
|
+
const uid = useId();
|
|
67
|
+
const labels = { ...DEFAULT_LABELS, ...labelOverrides };
|
|
68
|
+
const fmt = useMemo(() => ({ currency, locale }), [currency, locale]);
|
|
69
|
+
const rootRef = useRef(null);
|
|
70
|
+
const containerWidth = useContainerWidth(rootRef);
|
|
71
|
+
const wide = useMatchMedia(DESKTOP_QUERY, false);
|
|
72
|
+
const desktop = layout === "auto" ? (containerWidth === undefined ? wide : containerWidth >= DESKTOP_MIN_WIDTH) : layout === "desktop";
|
|
73
|
+
const variants = useMemo(() => resolveVariants(product), [product]);
|
|
74
|
+
const axes = useMemo(() => withGuide(product.axes, sizeGuide), [product.axes, sizeGuide]);
|
|
75
|
+
const [innerSelection, setInnerSelection] = useState(defaultSelection !== null && defaultSelection !== void 0 ? defaultSelection : {});
|
|
76
|
+
const selection = selectionProp !== null && selectionProp !== void 0 ? selectionProp : innerSelection;
|
|
77
|
+
const complete = selectionComplete(product.axes, selection);
|
|
78
|
+
const variant = findVariant(product.axes, variants, selection);
|
|
79
|
+
const unpicked = firstUnpickedAxis(product.axes, selection);
|
|
80
|
+
const selectPrompt = unpicked ? labels.selectPrompt(unpicked.label.toLowerCase()) : "";
|
|
81
|
+
const state = variant ? stockState(variant) : soldOutEverywhere(variants) ? "out-of-stock" : undefined;
|
|
82
|
+
const notifyMode = state === "out-of-stock";
|
|
83
|
+
const ceiling = quantityCeiling(variant, maxQuantity);
|
|
84
|
+
const [innerQuantity, setInnerQuantity] = useState(defaultQuantity);
|
|
85
|
+
const quantity = clampQuantity(quantityProp !== null && quantityProp !== void 0 ? quantityProp : innerQuantity, ceiling);
|
|
86
|
+
const [bag, setBag] = useState("idle");
|
|
87
|
+
const [addFailed, setAddFailed] = useState(false);
|
|
88
|
+
const [showSelectError, setShowSelectError] = useState(false);
|
|
89
|
+
const [promptTick, setPromptTick] = useState(0);
|
|
90
|
+
const [announcement, setAnnouncement] = useState("");
|
|
91
|
+
const timer = useRef();
|
|
92
|
+
const mounted = useRef(true);
|
|
93
|
+
const selectorRef = useRef(null);
|
|
94
|
+
const ctaRef = useRef(null);
|
|
95
|
+
const reviewsRef = useRef(null);
|
|
96
|
+
const ctaInView = useInViewport(ctaRef, !desktop && !isLoading);
|
|
97
|
+
useEffect(() => {
|
|
98
|
+
mounted.current = true;
|
|
99
|
+
return () => {
|
|
100
|
+
mounted.current = false;
|
|
101
|
+
clearTimeout(timer.current);
|
|
102
|
+
};
|
|
103
|
+
}, []);
|
|
104
|
+
const variantId = variant === null || variant === void 0 ? void 0 : variant.id;
|
|
105
|
+
useEffect(() => {
|
|
106
|
+
clearTimeout(timer.current);
|
|
107
|
+
setBag("idle");
|
|
108
|
+
setAddFailed(false);
|
|
109
|
+
}, [variantId, quantity]);
|
|
110
|
+
useEffect(() => {
|
|
111
|
+
var _a, _b;
|
|
112
|
+
if (promptTick === 0)
|
|
113
|
+
return;
|
|
114
|
+
const group = (_a = selectorRef.current) === null || _a === void 0 ? void 0 : _a.querySelector('[role="radiogroup"][aria-invalid="true"]');
|
|
115
|
+
scrollToNode(group !== null && group !== void 0 ? group : selectorRef.current, reduced);
|
|
116
|
+
(_b = group === null || group === void 0 ? void 0 : group.querySelector('[role="radio"][tabindex="0"]')) === null || _b === void 0 ? void 0 : _b.focus({ preventScroll: true });
|
|
117
|
+
}, [promptTick, reduced]);
|
|
118
|
+
const handleSelection = useCallback((next, matched) => {
|
|
119
|
+
if (selectionProp === undefined)
|
|
120
|
+
setInnerSelection(next);
|
|
121
|
+
if (selectionComplete(product.axes, next))
|
|
122
|
+
setShowSelectError(false);
|
|
123
|
+
onSelectionChange === null || onSelectionChange === void 0 ? void 0 : onSelectionChange(next, matched);
|
|
124
|
+
}, [selectionProp, product.axes, onSelectionChange]);
|
|
125
|
+
const handleQuantity = (next) => {
|
|
126
|
+
if (quantityProp === undefined)
|
|
127
|
+
setInnerQuantity(next);
|
|
128
|
+
onQuantityChange === null || onQuantityChange === void 0 ? void 0 : onQuantityChange(next);
|
|
129
|
+
};
|
|
130
|
+
const promptSelection = () => {
|
|
131
|
+
setShowSelectError(true);
|
|
132
|
+
setPromptTick((tick) => tick + 1);
|
|
133
|
+
};
|
|
134
|
+
const handleAdd = async () => {
|
|
135
|
+
if (!complete || !variant) {
|
|
136
|
+
promptSelection();
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
if (bag === "in-bag") {
|
|
140
|
+
onGoToBag === null || onGoToBag === void 0 ? void 0 : onGoToBag();
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
if (bag !== "idle")
|
|
144
|
+
return;
|
|
145
|
+
setAddFailed(false);
|
|
146
|
+
try {
|
|
147
|
+
const pending = onAddToBag === null || onAddToBag === void 0 ? void 0 : onAddToBag(variant.id, quantity);
|
|
148
|
+
if (pending && typeof pending.then === "function") {
|
|
149
|
+
setBag("adding");
|
|
150
|
+
await pending;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
catch {
|
|
154
|
+
if (mounted.current) {
|
|
155
|
+
setBag("idle");
|
|
156
|
+
setAddFailed(true);
|
|
157
|
+
}
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
if (!mounted.current)
|
|
161
|
+
return;
|
|
162
|
+
setBag("added");
|
|
163
|
+
setAnnouncement(labels.addedAnnouncement);
|
|
164
|
+
timer.current = setTimeout(() => {
|
|
165
|
+
setBag(onGoToBag ? "in-bag" : "idle");
|
|
166
|
+
setAnnouncement("");
|
|
167
|
+
}, addedDuration);
|
|
30
168
|
};
|
|
31
|
-
const
|
|
32
|
-
|
|
169
|
+
const handleBuyNow = () => {
|
|
170
|
+
if (!complete || !variant) {
|
|
171
|
+
promptSelection();
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
onBuyNow === null || onBuyNow === void 0 ? void 0 : onBuyNow(variant.id, quantity);
|
|
33
175
|
};
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
176
|
+
const handleNotify = () => onNotify === null || onNotify === void 0 ? void 0 : onNotify(variant === null || variant === void 0 ? void 0 : variant.id);
|
|
177
|
+
const jumpToReviews = () => scrollToNode(reviewsRef.current, reduced);
|
|
178
|
+
const range = !variant && !complete ? priceRange(variants) : null;
|
|
179
|
+
const price = (_a = variant === null || variant === void 0 ? void 0 : variant.price) !== null && _a !== void 0 ? _a : product.price;
|
|
180
|
+
const mrp = variant ? variant.mrp : product.mrp;
|
|
181
|
+
const showRange = range !== null && range.min !== range.max;
|
|
182
|
+
const activeIds = activeMediaIds(product, selection, variant);
|
|
183
|
+
const primaryLabel = bag === "added" ? labels.added : bag === "in-bag" ? labels.goToBag : notifyMode ? labels.notifyMe : labels.addToBag;
|
|
184
|
+
const barMode = notifyMode
|
|
185
|
+
? "notify"
|
|
186
|
+
: !complete
|
|
187
|
+
? "select-option"
|
|
188
|
+
: bag === "added"
|
|
189
|
+
? "added"
|
|
190
|
+
: bag === "in-bag"
|
|
191
|
+
? "go-to-bag"
|
|
192
|
+
: "add";
|
|
193
|
+
const showStepper = !notifyMode && ceiling > 0;
|
|
194
|
+
const showBuyNow = !!onBuyNow && !notifyMode && bag === "idle";
|
|
195
|
+
const ratingText = product.rating === undefined
|
|
196
|
+
? ""
|
|
197
|
+
: `Rated ${product.rating.toFixed(1)} out of 5${product.ratingCount ? ` from ${product.ratingCount.toLocaleString(locale !== null && locale !== void 0 ? locale : "en-IN")} ratings` : ""}`;
|
|
198
|
+
const mrpForLegal = variant ? ((_b = variant.mrp) !== null && _b !== void 0 ? _b : variant.price) : ((_c = product.mrp) !== null && _c !== void 0 ? _c : product.price);
|
|
199
|
+
const hasLegal = !!(product.netQuantity || product.manufacturer || product.originCountry);
|
|
200
|
+
const reviewsHeadingId = `${uid}-reviews`;
|
|
201
|
+
const showReviews = reviews !== undefined || product.ratingCount !== undefined;
|
|
202
|
+
const sectionGap = desktop ? 18 : 10;
|
|
203
|
+
const gutter = desktop ? 6 : 4;
|
|
204
|
+
const wishlist = (_jsx(WishlistToggle, { selected: wishlisted, defaultSelected: defaultWishlisted, onSelectedChange: onWishlistChange, size: desktop ? "lg" : "md", variant: desktop ? "soft" : "glass", label: labels.wishlistSave }));
|
|
205
|
+
const badgeSlot = product.badges && product.badges.length > 0 ? _jsx(ProductBadges, { badges: product.badges, max: 2, variant: "glass", size: "md" }) : undefined;
|
|
206
|
+
const gallery = mediaSlot !== null && mediaSlot !== void 0 ? mediaSlot : (_jsx(MediaGallery, { 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 }));
|
|
207
|
+
const primaryButton = (_jsx(Button, { size: desktop ? "md" : "lg", width: "100%", variant: notifyMode ? "outline" : "solid", label: primaryLabel, leftIcon: bag === "added" ? _jsx(Check, { size: 18, "aria-hidden": true }) : notifyMode ? _jsx(BellRing, { size: 18, "aria-hidden": true }) : undefined, isLoading: bag === "adding", onClick: notifyMode ? handleNotify : handleAdd, fontWeight: 600 }));
|
|
208
|
+
const buyPanel = isLoading ? (_jsxs(Flex, { direction: "column", gap: 4, "aria-busy": "true", children: [_jsx(Skeletons, { type: "skeleton", height: "1rem", width: "30%" }), _jsx(Skeletons, { type: "skeleton", height: "2rem", width: "90%" }), _jsx(Skeletons, { type: "skeleton", height: "2.5rem", width: "45%" }), _jsx(Skeletons, { type: "skeleton", height: "3rem", width: "100%" }), _jsx(Skeletons, { type: "skeleton", height: "3rem", width: "100%" })] })) : (_jsxs(Flex, { direction: "column", gap: 6, children: [_jsxs(Flex, { direction: "column", gap: 2, children: [_jsxs(Flex, { align: "center", justify: "space-between", gap: 3, minH: product.brand || onShare ? "2.75rem" : undefined, children: [product.brand ? (_jsx(Text, { as: "span", fontSize: "sm", fontWeight: 600, color: colors.textMuted, children: product.brand })) : (_jsx("span", {})), onShare ? (_jsx(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: transitionFor(["background-color"]), _hover: { bg: colors.background[100] }, sx: { ...focusVisibleStyles(colors), ...reducedMotionSx() }, children: _jsx(Share2, { size: 20, "aria-hidden": true }) })) : null] }), _jsx(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 ? (_jsx(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: { ...focusVisibleStyles(colors) }, children: _jsx(Rating, { value: product.rating, count: product.ratingCount, size: "sm", "aria-label": ratingText, locale: locale }) })) : product.rating !== undefined ? (_jsx(Rating, { value: product.rating, count: product.ratingCount, size: "sm", locale: locale })) : null] }), _jsxs(Flex, { direction: "column", gap: 2, children: [_jsx(PriceBlock, { size: "lg", price: price, mrp: mrp, priceRange: showRange ? range : undefined, showSavings: true, taxNote: labels.taxNote, unitPrice: packUnitPrice(product, selection, price), ...fmt }), state ? _jsx(StockStatus, { status: state, count: variant === null || variant === void 0 ? void 0 : variant.stock }) : null, metaSlot] }), offers && offers.length > 0 ? _jsx(OffersList, { offers: offers, ...offersProps }) : null, axes.length > 0 ? (_jsx(Box, { ref: selectorRef, children: _jsx(VariantSelector, { axes: axes, variants: variants, value: selection, onValueChange: handleSelection, error: showSelectError && !complete ? selectPrompt : undefined, showSelectedLabel: true, showLowStock: true, onGuideClick: onGuideClick }) })) : null, _jsxs(Flex, { direction: "column", gap: 3, ref: ctaRef, children: [_jsxs(Flex, { align: "center", gap: 3, children: [showStepper ? (_jsx(QuantityStepper, { size: desktop ? "md" : "lg", value: quantity, onValueChange: handleQuantity, min: 1, max: ceiling, itemLabel: product.title })) : null, _jsx(Box, { flex: 1, minW: 0, children: primaryButton }), desktop ? wishlist : null] }), showBuyNow ? _jsx(Button, { size: desktop ? "md" : "lg", width: "100%", variant: "outline", label: labels.buyNow, onClick: handleBuyNow }) : null, addFailed ? (_jsxs(Flex, { role: "alert", align: "center", gap: 1.5, color: colors.semanticText.error, fontSize: "sm", fontWeight: 600, children: [_jsx(CircleAlert, { size: 14, "aria-hidden": true }), _jsx(Text, { as: "span", children: labels.addFailed })] })) : null] }), pincode ? _jsx(PincodeChecker, { ...pincode }) : null, trustItems && trustItems.length > 0 ? _jsx(TrustBadges, { items: trustItems, layout: desktop ? "grid" : "row" }) : null, infoSlot] }));
|
|
209
|
+
return (_jsxs(Box, { ref: rootRef, "data-testid": testId, "data-layout": desktop ? "desktop" : "mobile", w: "100%", maxW: "82rem", mx: "auto", px: desktop ? 6 : 0, children: [_jsx(VisuallyHidden, { role: "status", "aria-live": "polite", "aria-atomic": "true", children: announcement }), breadcrumbs ? _jsx(Box, { px: desktop ? 0 : gutter, py: 3, children: breadcrumbs }) : null, _jsxs(Flex, { direction: desktop ? "row" : "column", align: desktop ? "flex-start" : "stretch", gap: desktop ? 12 : 5, children: [_jsx(Box, { flex: desktop ? "1.63 1 0" : undefined, minW: 0, w: desktop ? undefined : "100%", children: gallery }), _jsx(Box, { flex: desktop ? "1 1 0" : undefined, minW: 0, px: desktop ? 0 : gutter, children: buyPanel })] }), !isLoading ? (_jsxs(Flex, { direction: "column", gap: sectionGap, mt: sectionGap, px: desktop ? 0 : gutter, children: [_jsx(DetailSections, { description: product.description, highlights: product.highlights, specs: product.specs, care: care, shipping: product.returnsNote, legal: hasLegal
|
|
210
|
+
? {
|
|
211
|
+
netQuantity: product.netQuantity,
|
|
212
|
+
manufacturer: product.manufacturer,
|
|
213
|
+
originCountry: product.originCountry,
|
|
214
|
+
mrpNote: `${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"}`,
|
|
215
|
+
}
|
|
216
|
+
: undefined, defaultOpenIds: desktop ? ["description", "highlights", "specs"] : undefined, ...detailSectionsProps }), showReviews ? (_jsx(Box, { ref: reviewsRef, children: _jsxs(Flex, { direction: "column", gap: 6, children: [_jsx(ReviewSummary, { 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)) ? (_jsx(ReviewList, { reviews: reviews, locale: locale, ...reviewsProps })) : null] }) })) : null, belowFold, relatedSlot] })) : null, !desktop && !isLoading ? (_jsx(StickyBuyBar, { 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] }));
|
|
41
217
|
};
|
|
42
218
|
export default ProductDetails;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { stockState } from "../Commerce/commerceVariants.js";
|
|
2
|
+
import { unitPrice } from "../../Utils/price.js";
|
|
3
|
+
export const DEFAULT_MAX_QUANTITY = 10;
|
|
4
|
+
/** A product without variants sells as one variant at its own price. */
|
|
5
|
+
export const resolveVariants = (product) => product.variants.length > 0
|
|
6
|
+
? product.variants
|
|
7
|
+
: [{ id: "default", options: {}, price: product.price, mrp: product.mrp }];
|
|
8
|
+
/** A variant's own frames win; otherwise the frames of each picked option, in axis order. */
|
|
9
|
+
export const activeMediaIds = (product, selection, variant) => {
|
|
10
|
+
if ((variant === null || variant === void 0 ? void 0 : variant.mediaIds) && variant.mediaIds.length > 0)
|
|
11
|
+
return variant.mediaIds;
|
|
12
|
+
const byOption = product.mediaIdsByOption;
|
|
13
|
+
if (!byOption)
|
|
14
|
+
return undefined;
|
|
15
|
+
const ids = product.axes.flatMap((axis) => { var _a; return (_a = byOption[`${axis.id}:${selection[axis.id]}`]) !== null && _a !== void 0 ? _a : []; });
|
|
16
|
+
return ids.length > 0 ? [...new Set(ids)] : undefined;
|
|
17
|
+
};
|
|
18
|
+
export const packUnitPrice = (product, selection, price) => {
|
|
19
|
+
if (!product.unit)
|
|
20
|
+
return null;
|
|
21
|
+
const axis = product.axes.find((candidate) => candidate.type === "pack");
|
|
22
|
+
const picked = axis === null || axis === void 0 ? void 0 : axis.values.find((value) => value.id === selection[axis.id]);
|
|
23
|
+
if (!(picked === null || picked === void 0 ? void 0 : picked.quantity))
|
|
24
|
+
return null;
|
|
25
|
+
return unitPrice(price, picked.quantity, product.unit.unit, product.unit.per);
|
|
26
|
+
};
|
|
27
|
+
export const firstUnpickedAxis = (axes, selection) => axes.find((axis) => selection[axis.id] === undefined);
|
|
28
|
+
export const soldOutEverywhere = (variants) => variants.length > 0 && variants.every((variant) => stockState(variant) === "out-of-stock");
|
|
29
|
+
/** Real remaining stock caps the order; backorder and untracked stock fall back to the per-order ceiling. */
|
|
30
|
+
export const quantityCeiling = (variant, maxQuantity) => {
|
|
31
|
+
if ((variant === null || variant === void 0 ? void 0 : variant.stock) === undefined || variant.backorder)
|
|
32
|
+
return maxQuantity;
|
|
33
|
+
return Math.max(0, Math.min(variant.stock, maxQuantity));
|
|
34
|
+
};
|
|
35
|
+
export const clampQuantity = (value, ceiling) => Math.max(1, Math.min(value, Math.max(1, ceiling)));
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
|
+
/** Whether the element is on screen; true until an observer reports otherwise, and always true where IntersectionObserver is missing. */
|
|
3
|
+
export const useInViewport = (ref, enabled = true) => {
|
|
4
|
+
const [inView, setInView] = useState(true);
|
|
5
|
+
useEffect(() => {
|
|
6
|
+
const node = ref.current;
|
|
7
|
+
if (!enabled || !node || typeof IntersectionObserver === "undefined")
|
|
8
|
+
return undefined;
|
|
9
|
+
const observer = new IntersectionObserver(([entry]) => setInView(entry.isIntersecting));
|
|
10
|
+
observer.observe(node);
|
|
11
|
+
return () => observer.disconnect();
|
|
12
|
+
}, [ref, enabled]);
|
|
13
|
+
return inView;
|
|
14
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from "react";
|
|
3
|
+
import { Box, Flex, Text } from "@chakra-ui/react";
|
|
4
|
+
import { Minus, Plus, Trash2 } from "lucide-react";
|
|
5
|
+
import { useCustomTheme } from "../../Theme/useCustomTheme.js";
|
|
6
|
+
import { BUTTON_SIZES } from "../../Theme/tokens/primitives/controlSizes.js";
|
|
7
|
+
import { transitionFor } from "../../Theme/tokens/primitives/motion.js";
|
|
8
|
+
import { reducedMotionSx } from "../../Theme/chakra/motion.js";
|
|
9
|
+
import { focusVisibleStyles } from "../../Theme/chakra/focusRing.styles.js";
|
|
10
|
+
const MIN_HIT = "2.75rem";
|
|
11
|
+
const LIMIT_OPACITY = 0.4;
|
|
12
|
+
const clamp = (n, min, max) => Math.max(min, max === undefined ? n : Math.min(max, n));
|
|
13
|
+
/** Pill stepper for quantities: soft or outline, trash at the floor on cart lines, limits announced via aria-disabled. */
|
|
14
|
+
const QuantityStepper = ({ value, defaultValue, onValueChange, min = 1, max, step = 1, size = "md", variant = "soft", removable = false, onRemove, disabled = false, itemLabel, "data-testid": testId, }) => {
|
|
15
|
+
const { colors } = useCustomTheme();
|
|
16
|
+
const spec = BUTTON_SIZES[size];
|
|
17
|
+
const [inner, setInner] = useState(defaultValue !== null && defaultValue !== void 0 ? defaultValue : min);
|
|
18
|
+
const current = value !== null && value !== void 0 ? value : inner;
|
|
19
|
+
const atMin = current <= min;
|
|
20
|
+
const atMax = max !== undefined && current >= max;
|
|
21
|
+
const trash = removable && atMin;
|
|
22
|
+
const subject = itemLabel ? ` of ${itemLabel}` : "";
|
|
23
|
+
const change = (direction) => {
|
|
24
|
+
const next = clamp(current + direction * step, min, max);
|
|
25
|
+
if (next === current)
|
|
26
|
+
return;
|
|
27
|
+
if (value === undefined)
|
|
28
|
+
setInner(next);
|
|
29
|
+
onValueChange === null || onValueChange === void 0 ? void 0 : onValueChange(next);
|
|
30
|
+
};
|
|
31
|
+
const surface = variant === "outline"
|
|
32
|
+
? { bg: "transparent", boxShadow: `inset 0 0 0 1px ${colors.boxborder[500]}` }
|
|
33
|
+
: { bg: colors.background[100], boxShadow: "none" };
|
|
34
|
+
const button = (kind) => {
|
|
35
|
+
const limited = kind === "dec" ? atMin && !trash : atMax;
|
|
36
|
+
const Icon = kind === "inc" ? Plus : trash ? Trash2 : Minus;
|
|
37
|
+
const label = kind === "inc" ? `Increase quantity${subject}` : trash ? `Remove${itemLabel ? ` ${itemLabel}` : ""}` : `Decrease quantity${subject}`;
|
|
38
|
+
return (_jsx(Box, { as: "button", type: "button", "aria-label": label, "aria-disabled": limited || undefined, disabled: disabled, "data-testid": testId ? `${testId}-${kind}` : undefined, onClick: () => {
|
|
39
|
+
if (limited)
|
|
40
|
+
return;
|
|
41
|
+
if (kind === "dec" && trash)
|
|
42
|
+
onRemove === null || onRemove === void 0 ? void 0 : onRemove();
|
|
43
|
+
else
|
|
44
|
+
change(kind === "inc" ? 1 : -1);
|
|
45
|
+
}, 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: transitionFor(["background-color", "transform", "opacity"]), _hover: limited || disabled ? undefined : { bg: colors.background[200] }, _active: limited || disabled ? undefined : { transform: "scale(0.96)" }, sx: {
|
|
46
|
+
...focusVisibleStyles(colors),
|
|
47
|
+
...reducedMotionSx({ "&:active": { transform: "none" } }),
|
|
48
|
+
"&::before": {
|
|
49
|
+
content: '""',
|
|
50
|
+
position: "absolute",
|
|
51
|
+
inset: `max(0px, calc((${MIN_HIT} - ${spec.height}) / -2))`,
|
|
52
|
+
},
|
|
53
|
+
}, children: _jsx(Icon, { size: spec.iconSize, "aria-hidden": true }) }));
|
|
54
|
+
};
|
|
55
|
+
return (_jsxs(Flex, { role: "group", "aria-label": `Quantity${subject}`, display: "inline-flex", align: "center", h: spec.height, borderRadius: "full", ...surface, "data-testid": testId, children: [button("dec"), _jsx(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")] }));
|
|
56
|
+
};
|
|
57
|
+
export default QuantityStepper;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useRef, useState } from "react";
|
|
3
|
+
import { Box, Flex, Text } from "@chakra-ui/react";
|
|
4
|
+
import { Star } from "lucide-react";
|
|
5
|
+
import { useCustomTheme } from "../../Theme/useCustomTheme.js";
|
|
6
|
+
import { transitionFor } from "../../Theme/tokens/primitives/motion.js";
|
|
7
|
+
import { reducedMotionSx, usePrefersReducedMotion } from "../../Theme/chakra/motion.js";
|
|
8
|
+
import { focusVisibleStyles } from "../../Theme/chakra/focusRing.styles.js";
|
|
9
|
+
import { DEFAULT_LOCALE } from "../../Utils/price.js";
|
|
10
|
+
const STAR_PX = { xs: 12, sm: 14, md: 18, lg: 24 };
|
|
11
|
+
const HIT_PX = { xs: 24, sm: 28, md: 44, lg: 44 };
|
|
12
|
+
const TEXT_SIZE = { xs: "xs", sm: "xs", md: "sm", lg: "md" };
|
|
13
|
+
const GAP_PX = { xs: 1, sm: 1, md: 2, lg: 2 };
|
|
14
|
+
const clamp = (n, lo, hi) => Math.min(hi, Math.max(lo, n));
|
|
15
|
+
const tenth = (n) => Math.round(n * 10) / 10;
|
|
16
|
+
const StarGlyph = ({ px, fillPercent, filled, empty }) => (_jsxs(Box, { as: "span", "aria-hidden": true, position: "relative", display: "inline-flex", boxSize: `${px}px`, flexShrink: 0, color: empty, children: [_jsx(Star, { size: px, fill: "currentColor", strokeWidth: 1.5 }), fillPercent > 0 && (_jsx(Box, { as: "span", "data-fill": fillPercent, position: "absolute", inset: 0, color: filled, sx: {
|
|
17
|
+
clipPath: `inset(0 ${100 - fillPercent}% 0 0)`,
|
|
18
|
+
"[dir=rtl] &": { clipPath: `inset(0 0 0 ${100 - fillPercent}%)` },
|
|
19
|
+
}, children: _jsx(Star, { size: px, fill: "currentColor", strokeWidth: 1.5 }) }))] }));
|
|
20
|
+
const fillOf = (index, value) => clamp(value - index, 0, 1) * 100;
|
|
21
|
+
/** Star rating with fractional fill; becomes a radio group for "write a review" when `onValueChange` is set. */
|
|
22
|
+
const Rating = ({ value, defaultValue = 0, max = 5, size = "sm", showValue = true, count, compactCount = false, locale = DEFAULT_LOCALE, onValueChange, isDisabled = false, "aria-label": ariaLabel, "data-testid": testId, }) => {
|
|
23
|
+
const { colors } = useCustomTheme();
|
|
24
|
+
const [inner, setInner] = useState(defaultValue);
|
|
25
|
+
const [hover, setHover] = useState(null);
|
|
26
|
+
const reduced = usePrefersReducedMotion();
|
|
27
|
+
const refs = useRef([]);
|
|
28
|
+
const interactive = !!onValueChange;
|
|
29
|
+
const current = tenth(clamp(value !== null && value !== void 0 ? value : (interactive ? inner : 0), 0, max));
|
|
30
|
+
const px = STAR_PX[size];
|
|
31
|
+
const nf = new Intl.NumberFormat(locale);
|
|
32
|
+
const valueText = new Intl.NumberFormat(locale, { minimumFractionDigits: 1, maximumFractionDigits: 1 }).format(current);
|
|
33
|
+
const countText = count === undefined
|
|
34
|
+
? null
|
|
35
|
+
: compactCount
|
|
36
|
+
? new Intl.NumberFormat(locale, { notation: "compact", maximumFractionDigits: 1 }).format(count)
|
|
37
|
+
: nf.format(count);
|
|
38
|
+
const summary = (_jsxs(_Fragment, { children: [showValue && current > 0 && (_jsx(Text, { as: "span", fontSize: TEXT_SIZE[size], fontWeight: 600, color: colors.header[900], sx: { fontVariantNumeric: "tabular-nums" }, children: valueText })), countText !== null && (_jsxs(Text, { as: "span", fontSize: TEXT_SIZE[size], color: colors.textMuted, sx: { fontVariantNumeric: "tabular-nums" }, children: ["(", countText, ")"] }))] }));
|
|
39
|
+
if (!interactive) {
|
|
40
|
+
const label = ariaLabel !== null && ariaLabel !== void 0 ? ariaLabel : (current === 0 && !count
|
|
41
|
+
? "Not rated yet"
|
|
42
|
+
: `Rated ${valueText} out of ${nf.format(max)}${count ? ` from ${nf.format(count)} ${count === 1 ? "rating" : "ratings"}` : ""}`);
|
|
43
|
+
return (_jsxs(Flex, { as: "span", role: "img", "aria-label": label, "data-testid": testId, display: "inline-flex", align: "center", gap: 1.5, verticalAlign: "middle", children: [_jsx(Flex, { as: "span", "aria-hidden": true, gap: `${GAP_PX[size]}px`, children: Array.from({ length: max }, (_, i) => (_jsx(StarGlyph, { px: px, fillPercent: fillOf(i, current), filled: colors.star, empty: colors.boxborder[300] }, i))) }), summary] }));
|
|
44
|
+
}
|
|
45
|
+
const select = (next) => {
|
|
46
|
+
if (isDisabled)
|
|
47
|
+
return;
|
|
48
|
+
if (value === undefined)
|
|
49
|
+
setInner(next);
|
|
50
|
+
onValueChange(next);
|
|
51
|
+
};
|
|
52
|
+
const chosen = Math.round(current);
|
|
53
|
+
const focusStop = chosen > 0 ? chosen : 1;
|
|
54
|
+
const shown = hover !== null && hover !== void 0 ? hover : chosen;
|
|
55
|
+
const onKeyDown = (e) => {
|
|
56
|
+
var _a;
|
|
57
|
+
const move = {
|
|
58
|
+
ArrowRight: chosen + 1,
|
|
59
|
+
ArrowUp: chosen + 1,
|
|
60
|
+
ArrowLeft: chosen - 1,
|
|
61
|
+
ArrowDown: chosen - 1,
|
|
62
|
+
Home: 1,
|
|
63
|
+
End: max,
|
|
64
|
+
};
|
|
65
|
+
if (!(e.key in move))
|
|
66
|
+
return;
|
|
67
|
+
e.preventDefault();
|
|
68
|
+
const next = clamp(move[e.key], 1, max);
|
|
69
|
+
select(next);
|
|
70
|
+
(_a = refs.current[next - 1]) === null || _a === void 0 ? void 0 : _a.focus();
|
|
71
|
+
};
|
|
72
|
+
return (_jsxs(Flex, { as: "span", display: "inline-flex", align: "center", gap: 1.5, "data-testid": testId, children: [_jsx(Flex, { as: "span", role: "radiogroup", "aria-label": ariaLabel !== null && ariaLabel !== void 0 ? ariaLabel : "Rating", "aria-disabled": isDisabled || undefined, gap: `${GAP_PX[size]}px`, onMouseLeave: () => setHover(null), children: Array.from({ length: max }, (_, i) => {
|
|
73
|
+
const n = i + 1;
|
|
74
|
+
return (_jsx(Box, { as: "button", type: "button", role: "radio", ref: (el) => {
|
|
75
|
+
refs.current[i] = el;
|
|
76
|
+
}, "aria-checked": n === chosen, "aria-label": `${n} ${n === 1 ? "star" : "stars"}`, tabIndex: n === focusStop && !isDisabled ? 0 : -1, disabled: isDisabled, onClick: () => select(n), onKeyDown: onKeyDown, onMouseEnter: () => !isDisabled && setHover(n), display: "inline-flex", alignItems: "center", justifyContent: "center", boxSize: `${HIT_PX[size]}px`, mx: `-${(HIT_PX[size] - px) / 2 - 1}px`, borderRadius: "full", cursor: isDisabled ? "not-allowed" : "pointer", opacity: isDisabled ? 0.5 : 1, transition: transitionFor(["transform"]), _active: isDisabled || reduced ? undefined : { transform: "scale(0.88)" }, sx: { ...focusVisibleStyles(colors), ...reducedMotionSx() }, children: _jsx(StarGlyph, { px: px, fillPercent: fillOf(i, shown), filled: colors.star, empty: colors.boxborder[300] }) }, n));
|
|
77
|
+
}) }), summary] }));
|
|
78
|
+
};
|
|
79
|
+
export default Rating;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|