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,206 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
7
|
+
const react_1 = require("react");
|
|
8
|
+
const react_2 = require("@chakra-ui/react");
|
|
9
|
+
const lucide_react_1 = require("lucide-react");
|
|
10
|
+
const useCustomTheme_1 = require("../../Theme/useCustomTheme");
|
|
11
|
+
const motion_1 = require("../../Theme/tokens/primitives/motion");
|
|
12
|
+
const scrollbar_1 = require("../../Theme/tokens/builders/scrollbar");
|
|
13
|
+
const motion_2 = require("../../Theme/chakra/motion");
|
|
14
|
+
const focusRing_styles_1 = require("../../Theme/chakra/focusRing.styles");
|
|
15
|
+
const Skeletons_1 = __importDefault(require("../Skeletons/Skeletons"));
|
|
16
|
+
const MediaFrame_1 = __importDefault(require("./MediaFrame"));
|
|
17
|
+
const MediaThumb_1 = __importDefault(require("./MediaThumb"));
|
|
18
|
+
const MediaLightbox_1 = __importDefault(require("./MediaLightbox"));
|
|
19
|
+
const glass_1 = require("./glass");
|
|
20
|
+
const motion_3 = require("./motion");
|
|
21
|
+
const useContainerWidth_1 = require("../Commerce/useContainerWidth");
|
|
22
|
+
const useMatchMedia_1 = require("./useMatchMedia");
|
|
23
|
+
const mediaGalleryModel_1 = require("./mediaGalleryModel");
|
|
24
|
+
const MediaGalleryProps_1 = require("./MediaGalleryProps");
|
|
25
|
+
const WIDE_QUERY = "(min-width: 768px)";
|
|
26
|
+
const WIDE_MIN_WIDTH = 560;
|
|
27
|
+
const FINE_POINTER_QUERY = "(hover: hover) and (pointer: fine)";
|
|
28
|
+
const MAX_DOTS = 8;
|
|
29
|
+
const INNER_ZOOM = 2;
|
|
30
|
+
const SETTLE_MS = 700;
|
|
31
|
+
const HIDDEN_SCROLLBAR = { scrollbarWidth: "none", "&::-webkit-scrollbar": { display: "none" } };
|
|
32
|
+
const revealWithin = (container, child, axis) => {
|
|
33
|
+
const [start, size, view] = axis === "x"
|
|
34
|
+
? [child.offsetLeft, child.offsetWidth, container.clientWidth]
|
|
35
|
+
: [child.offsetTop, child.offsetHeight, container.clientHeight];
|
|
36
|
+
const key = axis === "x" ? "scrollLeft" : "scrollTop";
|
|
37
|
+
const at = container[key];
|
|
38
|
+
if (start < at)
|
|
39
|
+
container[key] = start;
|
|
40
|
+
else if (start + size > at + view)
|
|
41
|
+
container[key] = start + size - view;
|
|
42
|
+
};
|
|
43
|
+
const GallerySkeleton = ({ arrangement, aspectRatio, rounded, label }) => {
|
|
44
|
+
const rail = arrangement !== "swipe";
|
|
45
|
+
const vertical = arrangement === "thumbs-left";
|
|
46
|
+
return ((0, jsx_runtime_1.jsxs)(react_2.Flex, { role: "status", "aria-label": label, direction: vertical ? "row" : "column", gap: 4, w: "100%", "data-testid": "media-gallery-skeleton", children: [rail && vertical && ((0, jsx_runtime_1.jsx)(react_2.Flex, { direction: "column", gap: 3, w: "72px", flexShrink: 0, children: [0, 1, 2, 3].map((n) => ((0, jsx_runtime_1.jsx)(Skeletons_1.default, { type: "skeleton", height: "90px", width: "72px", borderRadius: "xl" }, n))) })), (0, jsx_runtime_1.jsx)(react_2.Box, { flex: 1, minW: 0, sx: { aspectRatio }, borderRadius: rounded ? "2xl" : 0, overflow: "hidden", children: (0, jsx_runtime_1.jsx)(Skeletons_1.default, { type: "skeleton", height: "100%", width: "100%", borderRadius: "0" }) }), rail && !vertical && ((0, jsx_runtime_1.jsx)(react_2.Flex, { gap: 3, children: [0, 1, 2, 3].map((n) => ((0, jsx_runtime_1.jsx)(Skeletons_1.default, { type: "skeleton", height: "80px", width: "64px", borderRadius: "xl" }, n))) }))] }));
|
|
47
|
+
};
|
|
48
|
+
/** Product media carousel: scroll-snap track, thumbnail rail or dots, lightbox, colour-linked frame sets. */
|
|
49
|
+
const MediaGallery = ({ media, layout = "auto", aspectRatio = "4/5", zoom = "lightbox", index, defaultIndex = 0, onIndexChange, activeMediaIds, badges, actions, sticky = false, stickyTop = 24, rounded, isLoading = false, labels: labelOverrides, lightboxLabels, "aria-label": ariaLabel, "data-testid": testId, }) => {
|
|
50
|
+
const { colors } = (0, useCustomTheme_1.useCustomTheme)();
|
|
51
|
+
const reduced = (0, motion_2.usePrefersReducedMotion)();
|
|
52
|
+
const rootRef = (0, react_1.useRef)(null);
|
|
53
|
+
const containerWidth = (0, useContainerWidth_1.useContainerWidth)(rootRef);
|
|
54
|
+
const windowWide = (0, useMatchMedia_1.useMatchMedia)(WIDE_QUERY, false);
|
|
55
|
+
const wide = containerWidth === undefined ? windowWide : containerWidth >= WIDE_MIN_WIDTH;
|
|
56
|
+
const finePointer = (0, useMatchMedia_1.useMatchMedia)(FINE_POINTER_QUERY, false);
|
|
57
|
+
const labels = { ...MediaGalleryProps_1.defaultMediaGalleryLabels, ...labelOverrides };
|
|
58
|
+
const arrangement = layout === "auto" ? (wide ? "thumbs-left" : "swipe") : layout;
|
|
59
|
+
const isSwipe = arrangement === "swipe";
|
|
60
|
+
const squared = rounded === undefined ? isSwipe : !rounded;
|
|
61
|
+
const activeKey = JSON.stringify(activeMediaIds !== null && activeMediaIds !== void 0 ? activeMediaIds : null);
|
|
62
|
+
const frames = (0, react_1.useMemo)(() => { var _a; return (0, mediaGalleryModel_1.resolveFrames)(media, (_a = JSON.parse(activeKey)) !== null && _a !== void 0 ? _a : undefined); }, [media, activeKey]);
|
|
63
|
+
const signature = (0, mediaGalleryModel_1.frameSignature)(frames);
|
|
64
|
+
const count = frames.length;
|
|
65
|
+
const isControlled = index !== undefined;
|
|
66
|
+
const [ownIndex, setOwnIndex] = (0, react_1.useState)(defaultIndex);
|
|
67
|
+
const current = (0, mediaGalleryModel_1.clampIndex)(isControlled ? index : ownIndex, count);
|
|
68
|
+
const latest = (0, react_1.useRef)(current);
|
|
69
|
+
latest.current = current;
|
|
70
|
+
const onChangeRef = (0, react_1.useRef)(onIndexChange);
|
|
71
|
+
onChangeRef.current = onIndexChange;
|
|
72
|
+
const commit = (next) => {
|
|
73
|
+
var _a;
|
|
74
|
+
const target = (0, mediaGalleryModel_1.clampIndex)(next, count);
|
|
75
|
+
if (target === latest.current)
|
|
76
|
+
return;
|
|
77
|
+
latest.current = target;
|
|
78
|
+
if (!isControlled)
|
|
79
|
+
setOwnIndex(target);
|
|
80
|
+
(_a = onChangeRef.current) === null || _a === void 0 ? void 0 : _a.call(onChangeRef, target);
|
|
81
|
+
};
|
|
82
|
+
const commitRef = (0, react_1.useRef)(commit);
|
|
83
|
+
commitRef.current = commit;
|
|
84
|
+
const trackRef = (0, react_1.useRef)(null);
|
|
85
|
+
const railRef = (0, react_1.useRef)(null);
|
|
86
|
+
const settling = (0, react_1.useRef)(null);
|
|
87
|
+
const settleTimer = (0, react_1.useRef)();
|
|
88
|
+
const alignedTrack = (0, react_1.useRef)(null);
|
|
89
|
+
const lightboxReturn = (0, react_1.useRef)(null);
|
|
90
|
+
const [lightboxOpen, setLightboxOpen] = (0, react_1.useState)(false);
|
|
91
|
+
const [inner, setInner] = (0, react_1.useState)({ on: false, x: 50, y: 50 });
|
|
92
|
+
const [fadeKey, setFadeKey] = (0, react_1.useState)(0);
|
|
93
|
+
const seenSignature = (0, react_1.useRef)(signature);
|
|
94
|
+
(0, react_1.useEffect)(() => {
|
|
95
|
+
if (seenSignature.current === signature)
|
|
96
|
+
return;
|
|
97
|
+
seenSignature.current = signature;
|
|
98
|
+
setFadeKey((key) => key + 1);
|
|
99
|
+
commitRef.current(0);
|
|
100
|
+
}, [signature]);
|
|
101
|
+
(0, react_1.useEffect)(() => setInner((state) => (state.on ? { ...state, on: false } : state)), [current, signature]);
|
|
102
|
+
(0, react_1.useEffect)(() => () => window.clearTimeout(settleTimer.current), []);
|
|
103
|
+
(0, react_1.useLayoutEffect)(() => {
|
|
104
|
+
var _a;
|
|
105
|
+
const track = trackRef.current;
|
|
106
|
+
const width = (_a = track === null || track === void 0 ? void 0 : track.clientWidth) !== null && _a !== void 0 ? _a : 0;
|
|
107
|
+
if (!track || !width)
|
|
108
|
+
return;
|
|
109
|
+
const firstPass = alignedTrack.current !== track;
|
|
110
|
+
alignedTrack.current = track;
|
|
111
|
+
const left = current * width;
|
|
112
|
+
if (Math.abs(track.scrollLeft - left) < 2)
|
|
113
|
+
return;
|
|
114
|
+
settling.current = current;
|
|
115
|
+
window.clearTimeout(settleTimer.current);
|
|
116
|
+
settleTimer.current = window.setTimeout(() => {
|
|
117
|
+
settling.current = null;
|
|
118
|
+
}, SETTLE_MS);
|
|
119
|
+
if (firstPass || reduced || typeof track.scrollTo !== "function")
|
|
120
|
+
track.scrollLeft = left;
|
|
121
|
+
else
|
|
122
|
+
track.scrollTo({ left, behavior: "smooth" });
|
|
123
|
+
}, [current, fadeKey, arrangement, reduced]);
|
|
124
|
+
(0, react_1.useEffect)(() => {
|
|
125
|
+
const rail = railRef.current;
|
|
126
|
+
const selected = rail === null || rail === void 0 ? void 0 : rail.querySelector('[aria-current="true"]');
|
|
127
|
+
if (rail && selected)
|
|
128
|
+
revealWithin(rail, selected, arrangement === "thumbs-left" ? "y" : "x");
|
|
129
|
+
}, [current, fadeKey, arrangement]);
|
|
130
|
+
const onScroll = () => {
|
|
131
|
+
const track = trackRef.current;
|
|
132
|
+
if (!track || !track.clientWidth)
|
|
133
|
+
return;
|
|
134
|
+
const at = (0, mediaGalleryModel_1.clampIndex)(Math.round(track.scrollLeft / track.clientWidth), count);
|
|
135
|
+
if (settling.current !== null) {
|
|
136
|
+
if (at === settling.current)
|
|
137
|
+
settling.current = null;
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
commit(at);
|
|
141
|
+
};
|
|
142
|
+
const onKeyDown = (event) => {
|
|
143
|
+
if (event.ctrlKey || event.metaKey || event.altKey || (0, mediaGalleryModel_1.keyBelongsToTarget)(event.target))
|
|
144
|
+
return;
|
|
145
|
+
const next = (0, mediaGalleryModel_1.indexForKey)(event.key, latest.current, count);
|
|
146
|
+
if (next === undefined)
|
|
147
|
+
return;
|
|
148
|
+
event.preventDefault();
|
|
149
|
+
commit(next);
|
|
150
|
+
};
|
|
151
|
+
const openLightbox = (event) => {
|
|
152
|
+
lightboxReturn.current = event.currentTarget;
|
|
153
|
+
setLightboxOpen(true);
|
|
154
|
+
};
|
|
155
|
+
const toggleInner = (event) => {
|
|
156
|
+
const box = event.currentTarget.getBoundingClientRect();
|
|
157
|
+
const x = box.width ? ((event.clientX - box.left) / box.width) * 100 : 50;
|
|
158
|
+
const y = box.height ? ((event.clientY - box.top) / box.height) * 100 : 50;
|
|
159
|
+
setInner((state) => ({ on: !state.on, x, y }));
|
|
160
|
+
};
|
|
161
|
+
const panInner = (event) => {
|
|
162
|
+
if (!inner.on || event.pointerType !== "mouse")
|
|
163
|
+
return;
|
|
164
|
+
const box = event.currentTarget.getBoundingClientRect();
|
|
165
|
+
if (!box.width || !box.height)
|
|
166
|
+
return;
|
|
167
|
+
setInner({ on: true, x: ((event.clientX - box.left) / box.width) * 100, y: ((event.clientY - box.top) / box.height) * 100 });
|
|
168
|
+
};
|
|
169
|
+
const ratio = aspectRatio.replace("/", " / ");
|
|
170
|
+
const radius = squared ? 0 : "2xl";
|
|
171
|
+
const showArrows = count > 1 && (finePointer || !isSwipe);
|
|
172
|
+
const showRail = count > 1 && !isSwipe;
|
|
173
|
+
const arrowSize = isSwipe ? 36 : 44;
|
|
174
|
+
const arrowInset = isSwipe ? 12 : 16;
|
|
175
|
+
const currentFrame = frames[current];
|
|
176
|
+
const zoomable = zoom !== "none" && currentFrame !== undefined && (0, mediaGalleryModel_1.frameKind)(currentFrame) === "image";
|
|
177
|
+
if (isLoading)
|
|
178
|
+
return (0, jsx_runtime_1.jsx)(GallerySkeleton, { arrangement: arrangement, aspectRatio: ratio, rounded: !squared, label: labels.loading });
|
|
179
|
+
const thumbRing = { gap: colors.background[50], ink: colors.header[900] };
|
|
180
|
+
const thumbs = (width, height) => frames.map((frame, position) => ((0, jsx_runtime_1.jsx)(MediaThumb_1.default, { media: frame, label: labels.frame(position + 1, count, frame.alt), selected: position === current, onSelect: () => commit(position), width: width, height: height, ring: thumbRing }, frame.id)));
|
|
181
|
+
const glassDots = (0, glass_1.glassStyles)(colors);
|
|
182
|
+
const focusInset = { outline: "2px solid transparent", boxShadow: `inset 0 0 0 2px ${colors.focusRing.halo}, inset 0 0 0 4px ${colors.focusRing.ring}` };
|
|
183
|
+
const well = ((0, jsx_runtime_1.jsxs)(react_2.Box, { position: "relative", flex: 1, minW: 0, overflow: "hidden", isolation: "isolate", borderRadius: radius, bg: colors.background[100], sx: { aspectRatio: ratio }, "data-testid": "media-gallery-well", children: [(0, jsx_runtime_1.jsxs)(react_2.Flex, { ref: trackRef, position: "absolute", inset: 0, tabIndex: 0, role: "group", "aria-label": labels.region, overflowX: "auto", overflowY: "hidden", animation: fadeKey > 0 ? (0, motion_3.fadeIn)(motion_3.CROSSFADE_MS) : undefined, onScroll: onScroll, onPointerDown: () => {
|
|
184
|
+
settling.current = null;
|
|
185
|
+
}, outline: "none", _focusVisible: focusInset, sx: {
|
|
186
|
+
scrollSnapType: "x mandatory",
|
|
187
|
+
overscrollBehaviorX: "contain",
|
|
188
|
+
...HIDDEN_SCROLLBAR,
|
|
189
|
+
...(0, motion_2.reducedMotionSx)(),
|
|
190
|
+
}, "data-testid": "media-gallery-track", children: [frames.map((frame, position) => {
|
|
191
|
+
var _a;
|
|
192
|
+
const isCurrent = position === current;
|
|
193
|
+
const kind = (0, mediaGalleryModel_1.frameKind)(frame);
|
|
194
|
+
const alt = (_a = frame.alt) !== null && _a !== void 0 ? _a : labels.image(position + 1, count);
|
|
195
|
+
const view = ((0, jsx_runtime_1.jsx)(MediaFrame_1.default, { media: frame, alt: alt, active: isCurrent, eager: Math.abs(position - current) <= 1, zoom: zoom === "inner" && isCurrent && inner.on ? { scale: INNER_ZOOM, x: inner.x, y: inner.y } : undefined, playLabel: labels.playVideo, unavailableLabel: labels.imageUnavailable }));
|
|
196
|
+
const interactive = zoom !== "none" && kind === "image";
|
|
197
|
+
return ((0, jsx_runtime_1.jsx)(react_2.Box, { role: "group", "aria-roledescription": "slide", "aria-label": labels.slide(position + 1, count), "aria-hidden": isCurrent ? undefined : true, flex: "0 0 100%", h: "100%", position: "relative", opacity: reduced && !isCurrent ? 0 : 1, transition: reduced ? (0, motion_1.transitionFor)(["opacity"], "fast") : undefined, sx: { scrollSnapAlign: "start", scrollSnapStop: "always" }, children: interactive ? ((0, jsx_runtime_1.jsx)(react_2.Box, { as: "button", type: "button", w: "100%", h: "100%", p: 0, border: "0", bg: "transparent", display: "block", overflow: "hidden", cursor: "zoom-in", tabIndex: isCurrent ? 0 : -1, "aria-label": zoom === "lightbox" ? labels.openLightbox(position + 1, count) : labels.zoomImage(position + 1, count), "aria-haspopup": zoom === "lightbox" ? "dialog" : undefined, "aria-pressed": zoom === "inner" ? isCurrent && inner.on : undefined, onClick: zoom === "lightbox" ? openLightbox : toggleInner, onPointerMove: zoom === "inner" ? panInner : undefined, outline: "none", _focusVisible: focusInset, sx: { cursor: zoom === "inner" && inner.on ? "zoom-out" : "zoom-in" }, children: view })) : (view) }, frame.id));
|
|
198
|
+
}), count === 0 && (0, jsx_runtime_1.jsx)(react_2.Box, { flex: "0 0 100%", bg: colors.background[100] })] }, fadeKey), badges && ((0, jsx_runtime_1.jsx)(react_2.Box, { position: "absolute", top: 3, left: 3, zIndex: 2, pointerEvents: "none", "data-testid": "media-gallery-badges", children: badges })), actions && ((0, jsx_runtime_1.jsx)(react_2.Box, { position: "absolute", top: 3, right: 3, zIndex: 3, "data-testid": "media-gallery-actions", children: actions })), showArrows && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(glass_1.GlassIconButton, { label: labels.previous, icon: (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronLeft, { size: arrowSize / 2, "aria-hidden": true }), onClick: () => commit(current - 1), isDisabled: current === 0, size: arrowSize, left: `${arrowInset}px`, top: `calc(50% - ${arrowSize / 2}px)`, zIndex: 2 }), (0, jsx_runtime_1.jsx)(glass_1.GlassIconButton, { label: labels.next, icon: (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronRight, { size: arrowSize / 2, "aria-hidden": true }), onClick: () => commit(current + 1), isDisabled: current === count - 1, size: arrowSize, right: `${arrowInset}px`, top: `calc(50% - ${arrowSize / 2}px)`, zIndex: 2 })] })), count > 1 && isSwipe && count <= MAX_DOTS && ((0, jsx_runtime_1.jsx)(react_2.Flex, { role: "group", "aria-label": labels.dots, position: "absolute", left: "50%", bottom: 4, transform: "translateX(-50%)", zIndex: 2, h: "28px", px: 1.5, align: "center", borderRadius: "full", ...glassDots, "data-testid": "media-gallery-dots", children: frames.map((frame, position) => {
|
|
199
|
+
const selected = position === current;
|
|
200
|
+
return ((0, jsx_runtime_1.jsx)(react_2.Box, { as: "button", type: "button", onClick: () => commit(position), "aria-label": labels.image(position + 1, count), "aria-current": selected ? "true" : undefined, display: "inline-flex", alignItems: "center", justifyContent: "center", h: "28px", w: selected ? "30px" : "20px", p: 0, border: "0", bg: "transparent", cursor: "pointer", transition: (0, motion_1.transitionFor)(["width"]), borderRadius: "full", sx: { ...(0, focusRing_styles_1.focusVisibleStyles)(colors), ...(0, motion_2.reducedMotionSx)() }, children: (0, jsx_runtime_1.jsx)(react_2.Box, { as: "span", boxSize: "6px", borderRadius: "full", bg: "currentColor", opacity: selected ? 0.92 : 0.3, transform: selected ? "scaleX(2.4)" : "scaleX(1)", transition: (0, motion_1.transitionFor)(["transform", "opacity"]) }) }, frame.id));
|
|
201
|
+
}) })), count > 1 && ((0, jsx_runtime_1.jsx)(glass_1.GlassPill, { ...(isSwipe ? { right: 4, bottom: "19px", height: 22 } : { left: 4, bottom: 4, height: 32 }), zIndex: 2, children: (0, jsx_runtime_1.jsx)("span", { "aria-live": "polite", "data-testid": "media-gallery-counter", children: labels.counter(current + 1, count) }) })), !isSwipe && finePointer && zoomable && zoom === "lightbox" && ((0, jsx_runtime_1.jsxs)(glass_1.GlassPill, { right: 4, bottom: 4, height: 32, zIndex: 2, children: [(0, jsx_runtime_1.jsx)(lucide_react_1.ZoomIn, { size: 14, "aria-hidden": true }), (0, jsx_runtime_1.jsx)(react_2.Text, { as: "span", children: labels.zoomHint })] }))] }));
|
|
202
|
+
const rail = showRail &&
|
|
203
|
+
(arrangement === "thumbs-left" ? ((0, jsx_runtime_1.jsx)(react_2.Box, { position: "relative", w: "72px", flexShrink: 0, alignSelf: "stretch", "data-testid": "media-gallery-rail", children: (0, jsx_runtime_1.jsx)(react_2.Flex, { ref: railRef, role: "group", "aria-label": labels.thumbnails, position: "absolute", inset: "-4px", p: "4px", direction: "column", gap: 3, overflowY: "auto", overflowX: "hidden", animation: fadeKey > 0 ? (0, motion_3.fadeIn)(motion_3.CROSSFADE_MS) : undefined, sx: { ...(0, scrollbar_1.scrollbarStyles)(colors, "hover"), ...(0, motion_2.reducedMotionSx)() }, children: thumbs(72, 90) }, fadeKey) })) : ((0, jsx_runtime_1.jsx)(react_2.Flex, { ref: railRef, role: "group", "aria-label": labels.thumbnails, gap: 3, m: "-4px", p: "4px", overflowX: "auto", animation: fadeKey > 0 ? (0, motion_3.fadeIn)(motion_3.CROSSFADE_MS) : undefined, sx: { ...(0, scrollbar_1.scrollbarStyles)(colors, "hover"), ...(0, motion_2.reducedMotionSx)() }, "data-testid": "media-gallery-rail", children: thumbs(64, 80) }, fadeKey)));
|
|
204
|
+
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(react_2.Box, { ref: rootRef, role: "region", "aria-roledescription": "carousel", "aria-label": ariaLabel !== null && ariaLabel !== void 0 ? ariaLabel : labels.region, onKeyDown: onKeyDown, w: "100%", position: sticky ? "sticky" : "relative", top: sticky ? `${stickyTop}px` : undefined, alignSelf: sticky ? "flex-start" : undefined, "data-testid": testId, children: (0, jsx_runtime_1.jsxs)(react_2.Flex, { direction: arrangement === "thumbs-left" ? "row" : "column", gap: 4, align: arrangement === "thumbs-left" ? "stretch" : undefined, children: [arrangement === "thumbs-left" && rail, well, arrangement === "thumbs-below" && rail] }) }), (0, jsx_runtime_1.jsx)(MediaLightbox_1.default, { isOpen: lightboxOpen, onClose: () => setLightboxOpen(false), items: frames, index: current, onIndexChange: commit, finalFocusRef: lightboxReturn, labels: lightboxLabels })] }));
|
|
205
|
+
};
|
|
206
|
+
exports.default = MediaGallery;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import type { ProductMedia } from "../Commerce/commerceTypes";
|
|
3
|
+
import type { MediaLightboxLabels } from "./MediaLightboxProps";
|
|
4
|
+
/** `auto` picks `thumbs-left` from 768px up and `swipe` below it. */
|
|
5
|
+
export type MediaGalleryLayout = "auto" | "thumbs-left" | "thumbs-below" | "swipe";
|
|
6
|
+
/** `lightbox` opens the full-screen viewer, `inner` zooms in place, `none` is inert. */
|
|
7
|
+
export type MediaGalleryZoom = "lightbox" | "inner" | "none";
|
|
8
|
+
/** Width / height of the media well; every frame is cropped to it, never stretched. */
|
|
9
|
+
export type MediaAspectRatio = "4/5" | "1/1" | "3/4" | "16/9" | `${number}/${number}`;
|
|
10
|
+
/** Every string the gallery renders or announces, merged over `defaultMediaGalleryLabels`. */
|
|
11
|
+
export interface MediaGalleryLabels {
|
|
12
|
+
/** Accessible name of the carousel region. */
|
|
13
|
+
region: string;
|
|
14
|
+
/** Slide label, "2 of 5". */
|
|
15
|
+
slide: (position: number, total: number) => string;
|
|
16
|
+
/** Alt text for a frame that has no `alt` of its own. */
|
|
17
|
+
image: (position: number, total: number) => string;
|
|
18
|
+
/** Accessible name of a thumbnail or dot; `alt` is the frame's own description when it has one. */
|
|
19
|
+
frame: (position: number, total: number, alt?: string) => string;
|
|
20
|
+
previous: string;
|
|
21
|
+
next: string;
|
|
22
|
+
/** Accessible name of the dots group. */
|
|
23
|
+
dots: string;
|
|
24
|
+
/** Accessible name of the thumbnail list. */
|
|
25
|
+
thumbnails: string;
|
|
26
|
+
/** Visible and live-announced counter, "1 / 5". */
|
|
27
|
+
counter: (position: number, total: number) => string;
|
|
28
|
+
/** Pill shown on desktop while `zoom` is not `none`. */
|
|
29
|
+
zoomHint: string;
|
|
30
|
+
/** Name of the button that opens the lightbox on an image. */
|
|
31
|
+
openLightbox: (position: number, total: number) => string;
|
|
32
|
+
/** Name of the button that toggles in-place zoom on an image. */
|
|
33
|
+
zoomImage: (position: number, total: number) => string;
|
|
34
|
+
playVideo: string;
|
|
35
|
+
imageUnavailable: string;
|
|
36
|
+
loading: string;
|
|
37
|
+
}
|
|
38
|
+
export declare const defaultMediaGalleryLabels: MediaGalleryLabels;
|
|
39
|
+
/** Product media carousel: thumbnail rail or swipe track, lightbox, colour-linked frames. */
|
|
40
|
+
export interface MediaGalleryProps {
|
|
41
|
+
/** Every frame the product has; images are cropped to `aspectRatio`, videos play on demand. */
|
|
42
|
+
media: ProductMedia[];
|
|
43
|
+
/** Arrangement of well and thumbnails; `auto` shows the thumbnail rail from 560px of the gallery's own width. */
|
|
44
|
+
layout?: MediaGalleryLayout;
|
|
45
|
+
/** Shape of the well. */
|
|
46
|
+
aspectRatio?: MediaAspectRatio;
|
|
47
|
+
/** What a click on an image does. */
|
|
48
|
+
zoom?: MediaGalleryZoom;
|
|
49
|
+
/** Controlled frame position, within the visible frames; pair with `onIndexChange`. */
|
|
50
|
+
index?: number;
|
|
51
|
+
/** Starting frame when uncontrolled. */
|
|
52
|
+
defaultIndex?: number;
|
|
53
|
+
/** Fires on every navigation (swipe, key, arrow, thumbnail, dot) with the new position. */
|
|
54
|
+
onIndexChange?: (index: number) => void;
|
|
55
|
+
/** Restricts and orders the visible frames by media id, e.g. the selected colour's `mediaIds`; position resets to 0. */
|
|
56
|
+
activeMediaIds?: string[];
|
|
57
|
+
/** Overlaid top-left on the well, e.g. product badges. */
|
|
58
|
+
badges?: ReactNode;
|
|
59
|
+
/** Overlaid top-right on the well, e.g. a wishlist toggle. */
|
|
60
|
+
actions?: ReactNode;
|
|
61
|
+
/** Pins the gallery while the rest of the page scrolls past. */
|
|
62
|
+
sticky?: boolean;
|
|
63
|
+
/** Offset from the top of the viewport when `sticky`, in px. */
|
|
64
|
+
stickyTop?: number;
|
|
65
|
+
/** Square the corners for an edge-to-edge well; defaults to rounded except in the swipe layout. */
|
|
66
|
+
rounded?: boolean;
|
|
67
|
+
/** Renders a skeleton of the same shape in place of the frames. */
|
|
68
|
+
isLoading?: boolean;
|
|
69
|
+
/** Overrides for any of `defaultMediaGalleryLabels`. */
|
|
70
|
+
labels?: Partial<MediaGalleryLabels>;
|
|
71
|
+
/** Overrides for the lightbox copy. */
|
|
72
|
+
lightboxLabels?: Partial<MediaLightboxLabels>;
|
|
73
|
+
/** Replaces `labels.region` as the carousel's accessible name, e.g. the product title. */
|
|
74
|
+
"aria-label"?: string;
|
|
75
|
+
"data-testid"?: string;
|
|
76
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.defaultMediaGalleryLabels = void 0;
|
|
4
|
+
exports.defaultMediaGalleryLabels = {
|
|
5
|
+
region: "Product images",
|
|
6
|
+
slide: (position, total) => `${position} of ${total}`,
|
|
7
|
+
image: (position, total) => `Image ${position} of ${total}`,
|
|
8
|
+
frame: (position, total, alt) => `Image ${position} of ${total}${alt ? `: ${alt}` : ""}`,
|
|
9
|
+
previous: "Previous image",
|
|
10
|
+
next: "Next image",
|
|
11
|
+
dots: "Choose an image",
|
|
12
|
+
thumbnails: "Image thumbnails",
|
|
13
|
+
counter: (position, total) => `${position} / ${total}`,
|
|
14
|
+
zoomHint: "Click to zoom",
|
|
15
|
+
openLightbox: (position, total) => `View image ${position} of ${total} full screen`,
|
|
16
|
+
zoomImage: (position, total) => `Zoom image ${position} of ${total}`,
|
|
17
|
+
playVideo: "Play video",
|
|
18
|
+
imageUnavailable: "Image unavailable",
|
|
19
|
+
loading: "Loading product images",
|
|
20
|
+
};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { MediaLightboxProps } from "./MediaLightboxProps";
|
|
2
|
+
/** Full-screen product media viewer: counter and close on top, arrows, thumbnail row, Esc and arrow keys. */
|
|
3
|
+
declare const MediaLightbox: ({ isOpen, onClose, items, index, defaultIndex, onIndexChange, finalFocusRef, labels: labelOverrides, }: MediaLightboxProps) => import("react/jsx-runtime").JSX.Element | null;
|
|
4
|
+
export default MediaLightbox;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
40
|
+
const react_1 = require("react");
|
|
41
|
+
const react_2 = require("@chakra-ui/react");
|
|
42
|
+
const lucide_react_1 = require("lucide-react");
|
|
43
|
+
const Modal_1 = __importStar(require("../Modal/Modal"));
|
|
44
|
+
const ViewerIconButton_1 = __importDefault(require("../MediaViewer/components/ViewerIconButton"));
|
|
45
|
+
const useViewerChrome_1 = require("../MediaViewer/useViewerChrome");
|
|
46
|
+
const useCustomTheme_1 = require("../../Theme/useCustomTheme");
|
|
47
|
+
const scrim_1 = require("../../Theme/tokens/builders/scrim");
|
|
48
|
+
const viewportHeight_1 = require("../../Theme/tokens/builders/viewportHeight");
|
|
49
|
+
const motion_1 = require("../../Theme/chakra/motion");
|
|
50
|
+
const MediaFrame_1 = __importDefault(require("./MediaFrame"));
|
|
51
|
+
const MediaThumb_1 = __importDefault(require("./MediaThumb"));
|
|
52
|
+
const motion_2 = require("./motion");
|
|
53
|
+
const mediaGalleryModel_1 = require("./mediaGalleryModel");
|
|
54
|
+
const MediaLightboxProps_1 = require("./MediaLightboxProps");
|
|
55
|
+
const SWIPE_MIN_PX = 50;
|
|
56
|
+
/** Full-screen product media viewer: counter and close on top, arrows, thumbnail row, Esc and arrow keys. */
|
|
57
|
+
const MediaLightbox = ({ isOpen, onClose, items, index, defaultIndex = 0, onIndexChange, finalFocusRef, labels: labelOverrides, }) => {
|
|
58
|
+
var _a;
|
|
59
|
+
const { colors } = (0, useCustomTheme_1.useCustomTheme)();
|
|
60
|
+
const chrome = (0, useViewerChrome_1.useViewerChrome)();
|
|
61
|
+
const reduced = (0, motion_1.usePrefersReducedMotion)();
|
|
62
|
+
const labels = { ...MediaLightboxProps_1.defaultMediaLightboxLabels, ...labelOverrides };
|
|
63
|
+
const isControlled = index !== undefined;
|
|
64
|
+
const [own, setOwn] = (0, react_1.useState)(defaultIndex);
|
|
65
|
+
const total = items.length;
|
|
66
|
+
const current = (0, mediaGalleryModel_1.clampIndex)(isControlled ? index : own, total);
|
|
67
|
+
const latest = (0, react_1.useRef)(current);
|
|
68
|
+
latest.current = current;
|
|
69
|
+
const stageRef = (0, react_1.useRef)(null);
|
|
70
|
+
const stripRef = (0, react_1.useRef)(null);
|
|
71
|
+
const touchStartX = (0, react_1.useRef)(null);
|
|
72
|
+
const go = (next) => {
|
|
73
|
+
const target = (0, mediaGalleryModel_1.clampIndex)(next, total);
|
|
74
|
+
if (target === latest.current)
|
|
75
|
+
return;
|
|
76
|
+
latest.current = target;
|
|
77
|
+
if (!isControlled)
|
|
78
|
+
setOwn(target);
|
|
79
|
+
onIndexChange === null || onIndexChange === void 0 ? void 0 : onIndexChange(target);
|
|
80
|
+
};
|
|
81
|
+
(0, react_1.useEffect)(() => {
|
|
82
|
+
const strip = stripRef.current;
|
|
83
|
+
const selected = strip === null || strip === void 0 ? void 0 : strip.querySelector('[aria-current="true"]');
|
|
84
|
+
if (!strip || !selected)
|
|
85
|
+
return;
|
|
86
|
+
const left = selected.offsetLeft - strip.clientWidth / 2 + selected.offsetWidth / 2;
|
|
87
|
+
strip.scrollLeft = Math.max(0, left);
|
|
88
|
+
}, [current, isOpen]);
|
|
89
|
+
const onKeyDown = (event) => {
|
|
90
|
+
if (event.ctrlKey || event.metaKey || event.altKey || (0, mediaGalleryModel_1.keyBelongsToTarget)(event.target))
|
|
91
|
+
return;
|
|
92
|
+
const next = (0, mediaGalleryModel_1.indexForKey)(event.key, latest.current, total);
|
|
93
|
+
if (next === undefined)
|
|
94
|
+
return;
|
|
95
|
+
event.preventDefault();
|
|
96
|
+
go(next);
|
|
97
|
+
};
|
|
98
|
+
const onTouchEnd = (event) => {
|
|
99
|
+
const start = touchStartX.current;
|
|
100
|
+
touchStartX.current = null;
|
|
101
|
+
if (start === null)
|
|
102
|
+
return;
|
|
103
|
+
const dx = event.changedTouches[0].clientX - start;
|
|
104
|
+
if (Math.abs(dx) > SWIPE_MIN_PX)
|
|
105
|
+
go(latest.current + (dx < 0 ? 1 : -1));
|
|
106
|
+
};
|
|
107
|
+
const item = items[current];
|
|
108
|
+
if (!item)
|
|
109
|
+
return null;
|
|
110
|
+
const alt = (_a = item.alt) !== null && _a !== void 0 ? _a : labels.image(current + 1, total);
|
|
111
|
+
const bar = { bg: (0, scrim_1.overlayScrim)(colors), color: chrome.ink };
|
|
112
|
+
return ((0, jsx_runtime_1.jsx)(Modal_1.default, { isOpen: isOpen, onClose: onClose, size: "full", hideCloseButton: true, motionPreset: reduced ? "none" : "scale", initialFocusRef: stageRef, finalFocusRef: finalFocusRef, overlaybg: (0, scrim_1.overlayScrim)(colors), contentProps: { bg: chrome.stage, m: 0, borderRadius: 0, "aria-label": labels.dialog }, children: (0, jsx_runtime_1.jsxs)(Modal_1.ModalBody, { p: 0, display: "flex", flexDirection: "column", sx: viewportHeight_1.fullViewportHeight, children: [(0, jsx_runtime_1.jsxs)(react_2.Flex, { align: "center", justify: "space-between", gap: 2, px: 4, py: 2, ...bar, "data-testid": "media-lightbox-bar", children: [(0, jsx_runtime_1.jsx)(react_2.Text, { as: "span", fontSize: "sm", fontWeight: 600, "aria-live": "polite", sx: { fontVariantNumeric: "tabular-nums" }, children: labels.counter(current + 1, total) }), (0, jsx_runtime_1.jsx)(ViewerIconButton_1.default, { label: labels.close, icon: (0, jsx_runtime_1.jsx)(lucide_react_1.X, { size: 20, "aria-hidden": true }), onClick: onClose, testId: "media-lightbox-close" })] }), (0, jsx_runtime_1.jsxs)(react_2.Box, { ref: stageRef, tabIndex: -1, flex: 1, minH: 0, position: "relative", outline: "none", onKeyDown: onKeyDown, onTouchStart: (event) => {
|
|
113
|
+
touchStartX.current = event.touches.length === 1 ? event.touches[0].clientX : null;
|
|
114
|
+
}, onTouchEnd: onTouchEnd, "data-testid": "media-lightbox-stage", children: [(0, jsx_runtime_1.jsx)(react_2.Box, { position: "absolute", inset: { base: 0, md: 6 }, animation: (0, motion_2.fadeIn)(), sx: (0, motion_1.reducedMotionSx)(), children: (0, jsx_runtime_1.jsx)(MediaFrame_1.default, { media: item, alt: alt, fit: "contain", autoPlay: true, surface: "transparent", playLabel: labels.playVideo, unavailableLabel: labels.imageUnavailable }) }, item.id), total > 1 && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(react_2.Box, { position: "absolute", left: { base: 2, md: 4 }, top: "calc(50% - 20px)", zIndex: 2, children: (0, jsx_runtime_1.jsx)(ViewerIconButton_1.default, { label: labels.previous, icon: (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronLeft, { size: 24, "aria-hidden": true }), onClick: () => go(current - 1), isDisabled: current === 0, round: true, testId: "media-lightbox-prev" }) }), (0, jsx_runtime_1.jsx)(react_2.Box, { position: "absolute", right: { base: 2, md: 4 }, top: "calc(50% - 20px)", zIndex: 2, children: (0, jsx_runtime_1.jsx)(ViewerIconButton_1.default, { label: labels.next, icon: (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronRight, { size: 24, "aria-hidden": true }), onClick: () => go(current + 1), isDisabled: current === total - 1, round: true, testId: "media-lightbox-next" }) })] }))] }), total > 1 && ((0, jsx_runtime_1.jsx)(react_2.Flex, { as: "nav", "aria-label": labels.thumbnails, ...bar, py: 3, px: 4, justify: "center", children: (0, jsx_runtime_1.jsx)(react_2.Flex, { ref: stripRef, gap: 3, p: "4px", maxW: "100%", overflowX: "auto", onKeyDown: onKeyDown, "data-testid": "media-lightbox-thumbs", children: items.map((frame, position) => ((0, jsx_runtime_1.jsx)(MediaThumb_1.default, { media: frame, label: labels.frame(position + 1, total, frame.alt), selected: position === current, onSelect: () => go(position), width: 56, height: 70, ring: { gap: chrome.stage, ink: chrome.ink }, surface: chrome.raised }, frame.id))) }) }))] }) }));
|
|
115
|
+
};
|
|
116
|
+
exports.default = MediaLightbox;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { RefObject } from "react";
|
|
2
|
+
import type { ProductMedia } from "../Commerce/commerceTypes";
|
|
3
|
+
/** Every string the lightbox renders or announces, merged over `defaultMediaLightboxLabels`. */
|
|
4
|
+
export interface MediaLightboxLabels {
|
|
5
|
+
/** Accessible name of the dialog. */
|
|
6
|
+
dialog: string;
|
|
7
|
+
close: string;
|
|
8
|
+
previous: string;
|
|
9
|
+
next: string;
|
|
10
|
+
/** Visible and live-announced counter, "2 / 5". */
|
|
11
|
+
counter: (position: number, total: number) => string;
|
|
12
|
+
/** Accessible name of the thumbnail row. */
|
|
13
|
+
thumbnails: string;
|
|
14
|
+
/** Accessible name of one thumbnail. */
|
|
15
|
+
frame: (position: number, total: number, alt?: string) => string;
|
|
16
|
+
/** Alt text for a frame that has no `alt` of its own. */
|
|
17
|
+
image: (position: number, total: number) => string;
|
|
18
|
+
playVideo: string;
|
|
19
|
+
imageUnavailable: string;
|
|
20
|
+
}
|
|
21
|
+
export declare const defaultMediaLightboxLabels: MediaLightboxLabels;
|
|
22
|
+
/** Full-screen viewer for product media on an opaque dark surface. */
|
|
23
|
+
export interface MediaLightboxProps {
|
|
24
|
+
/** Mounts and shows the viewer. */
|
|
25
|
+
isOpen: boolean;
|
|
26
|
+
/** Fires from the close button, Esc and a click on the backdrop. */
|
|
27
|
+
onClose: () => void;
|
|
28
|
+
/** Frames in order; navigation stops at both ends. */
|
|
29
|
+
items: ProductMedia[];
|
|
30
|
+
/** Controlled position; pair with `onIndexChange`. */
|
|
31
|
+
index?: number;
|
|
32
|
+
/** Starting position when uncontrolled. */
|
|
33
|
+
defaultIndex?: number;
|
|
34
|
+
/** Fires on every navigation with the new position. */
|
|
35
|
+
onIndexChange?: (index: number) => void;
|
|
36
|
+
/** Element that regains focus on close; defaults to whatever held focus before opening. */
|
|
37
|
+
finalFocusRef?: RefObject<HTMLElement>;
|
|
38
|
+
/** Overrides for any of `defaultMediaLightboxLabels`. */
|
|
39
|
+
labels?: Partial<MediaLightboxLabels>;
|
|
40
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.defaultMediaLightboxLabels = void 0;
|
|
4
|
+
exports.defaultMediaLightboxLabels = {
|
|
5
|
+
dialog: "Product images",
|
|
6
|
+
close: "Close",
|
|
7
|
+
previous: "Previous image",
|
|
8
|
+
next: "Next image",
|
|
9
|
+
counter: (position, total) => `${position} / ${total}`,
|
|
10
|
+
thumbnails: "Image thumbnails",
|
|
11
|
+
frame: (position, total, alt) => `Image ${position} of ${total}${alt ? `: ${alt}` : ""}`,
|
|
12
|
+
image: (position, total) => `Image ${position} of ${total}`,
|
|
13
|
+
playVideo: "Play video",
|
|
14
|
+
imageUnavailable: "Image unavailable",
|
|
15
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { ProductMedia } from "../Commerce/commerceTypes";
|
|
2
|
+
type MediaThumbProps = {
|
|
3
|
+
media: ProductMedia;
|
|
4
|
+
label: string;
|
|
5
|
+
selected: boolean;
|
|
6
|
+
onSelect: () => void;
|
|
7
|
+
width: number;
|
|
8
|
+
height: number;
|
|
9
|
+
/** Ring colours: `gap` separates the ring from the photo, `ink` is the selection mark. */
|
|
10
|
+
ring: {
|
|
11
|
+
gap: string;
|
|
12
|
+
ink: string;
|
|
13
|
+
};
|
|
14
|
+
surface?: string;
|
|
15
|
+
};
|
|
16
|
+
/** Selectable thumbnail: ring and full opacity when current, `aria-current` for assistive tech. */
|
|
17
|
+
declare const MediaThumb: ({ media, label, selected, onSelect, width, height, ring, surface }: MediaThumbProps) => import("react/jsx-runtime").JSX.Element;
|
|
18
|
+
export default MediaThumb;
|
|
@@ -0,0 +1,25 @@
|
|
|
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 scrim_1 = require("../../Theme/tokens/builders/scrim");
|
|
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 mediaGalleryModel_1 = require("./mediaGalleryModel");
|
|
13
|
+
/** Selectable thumbnail: ring and full opacity when current, `aria-current` for assistive tech. */
|
|
14
|
+
const MediaThumb = ({ media, label, selected, onSelect, width, height, ring, surface }) => {
|
|
15
|
+
const { colors } = (0, useCustomTheme_1.useCustomTheme)();
|
|
16
|
+
const [loaded, setLoaded] = (0, react_1.useState)(false);
|
|
17
|
+
const [failed, setFailed] = (0, react_1.useState)(false);
|
|
18
|
+
const src = (0, mediaGalleryModel_1.frameThumb)(media);
|
|
19
|
+
const settle = (0, react_1.useCallback)((node) => {
|
|
20
|
+
if (node && node.complete && node.naturalWidth > 0)
|
|
21
|
+
setLoaded(true);
|
|
22
|
+
}, []);
|
|
23
|
+
return ((0, jsx_runtime_1.jsxs)(react_2.Box, { as: "button", type: "button", onClick: onSelect, "aria-label": label, "aria-current": selected ? "true" : undefined, position: "relative", flexShrink: 0, w: `${width}px`, h: `${height}px`, p: 0, border: "0", borderRadius: "xl", overflow: "hidden", cursor: "pointer", bg: surface !== null && surface !== void 0 ? surface : colors.background[100], opacity: selected ? 1 : 0.72, boxShadow: selected ? `0 0 0 2px ${ring.gap}, 0 0 0 4px ${ring.ink}` : "none", transition: (0, motion_1.transitionFor)(["box-shadow", "opacity", "transform"]), _hover: { opacity: 1, transform: "translateY(-1px)" }, sx: { ...(0, focusRing_styles_1.focusVisibleStyles)(colors), ...(0, motion_2.reducedMotionSx)({ transform: "none" }) }, children: [src && !failed ? ((0, jsx_runtime_1.jsx)(react_2.Box, { as: "img", ref: settle, src: src, alt: "", loading: "lazy", decoding: "async", draggable: false, onLoad: () => setLoaded(true), onError: () => setFailed(true), position: "absolute", inset: 0, w: "100%", h: "100%", objectFit: "cover", opacity: loaded ? 1 : 0, transition: (0, motion_1.transitionFor)(["opacity"], "base") })) : ((0, jsx_runtime_1.jsx)(react_2.Flex, { position: "absolute", inset: 0, align: "center", justify: "center", color: colors.textMuted, "aria-hidden": true, children: (0, jsx_runtime_1.jsx)(lucide_react_1.Video, { size: 20 }) })), media.type === "video" && ((0, jsx_runtime_1.jsx)(react_2.Flex, { position: "absolute", inset: 0, align: "center", justify: "center", color: colors.white, "aria-hidden": true, children: (0, jsx_runtime_1.jsx)(react_2.Flex, { boxSize: 6, align: "center", justify: "center", borderRadius: "full", bg: (0, scrim_1.overlayScrim)(colors), children: (0, jsx_runtime_1.jsx)(lucide_react_1.Play, { size: 12, fill: "currentColor" }) }) }))] }));
|
|
24
|
+
};
|
|
25
|
+
exports.default = MediaThumb;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { ReactElement, ReactNode } from "react";
|
|
2
|
+
import type { BoxProps } from "@chakra-ui/react";
|
|
3
|
+
import type { PaletteProps } from "../../Theme/tokens/types";
|
|
4
|
+
/** Translucent surface over a photo: the page canvas at 72%, blurred, opaque where blur is unsupported. */
|
|
5
|
+
export declare const glassStyles: (colors: PaletteProps, hover?: boolean) => {
|
|
6
|
+
bg: string;
|
|
7
|
+
color: string;
|
|
8
|
+
backdropFilter: string;
|
|
9
|
+
sx: {
|
|
10
|
+
WebkitBackdropFilter: string;
|
|
11
|
+
"@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)))": {
|
|
12
|
+
backgroundColor: string;
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
/** 36 or 44 px glass circle with a 44 px hit area; fades out instead of unmounting when disabled. */
|
|
17
|
+
export declare const GlassIconButton: import("react").ForwardRefExoticComponent<{
|
|
18
|
+
label: string;
|
|
19
|
+
icon: ReactElement;
|
|
20
|
+
onClick: () => void;
|
|
21
|
+
size?: number;
|
|
22
|
+
isDisabled?: boolean;
|
|
23
|
+
tabIndex?: number;
|
|
24
|
+
} & Pick<BoxProps, "bottom" | "left" | "right" | "top" | "zIndex"> & import("react").RefAttributes<HTMLButtonElement>>;
|
|
25
|
+
type GlassPillProps = {
|
|
26
|
+
children: ReactNode;
|
|
27
|
+
height?: number;
|
|
28
|
+
} & Pick<BoxProps, "left" | "right" | "top" | "bottom" | "zIndex" | "px">;
|
|
29
|
+
/** Non-interactive glass capsule for the counter and zoom hint. */
|
|
30
|
+
export declare const GlassPill: ({ children, height, ...placement }: GlassPillProps) => import("react/jsx-runtime").JSX.Element;
|
|
31
|
+
export {};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GlassPill = exports.GlassIconButton = exports.glassStyles = void 0;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const react_1 = require("react");
|
|
6
|
+
const react_2 = require("@chakra-ui/react");
|
|
7
|
+
const useCustomTheme_1 = require("../../Theme/useCustomTheme");
|
|
8
|
+
const color_1 = require("../../Theme/tokens/builders/color");
|
|
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 GLASS_ALPHA = 0.72;
|
|
13
|
+
const GLASS_ALPHA_HOVER = 0.9;
|
|
14
|
+
const BLUR = "blur(20px) saturate(180%)";
|
|
15
|
+
const NO_BLUR_SUPPORT = "@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)))";
|
|
16
|
+
const tint = (colors, alpha) => {
|
|
17
|
+
const { r, g, b } = (0, color_1.hexToRgb)(colors.background[50]);
|
|
18
|
+
return `rgba(${r}, ${g}, ${b}, ${alpha})`;
|
|
19
|
+
};
|
|
20
|
+
/** Translucent surface over a photo: the page canvas at 72%, blurred, opaque where blur is unsupported. */
|
|
21
|
+
const glassStyles = (colors, hover = false) => ({
|
|
22
|
+
bg: tint(colors, hover ? GLASS_ALPHA_HOVER : GLASS_ALPHA),
|
|
23
|
+
color: colors.header[900],
|
|
24
|
+
backdropFilter: BLUR,
|
|
25
|
+
sx: { WebkitBackdropFilter: BLUR, [NO_BLUR_SUPPORT]: { backgroundColor: colors.background[50] } },
|
|
26
|
+
});
|
|
27
|
+
exports.glassStyles = glassStyles;
|
|
28
|
+
/** 36 or 44 px glass circle with a 44 px hit area; fades out instead of unmounting when disabled. */
|
|
29
|
+
exports.GlassIconButton = (0, react_1.forwardRef)(({ label, icon, onClick, size = 36, isDisabled = false, tabIndex, ...placement }, ref) => {
|
|
30
|
+
const { colors } = (0, useCustomTheme_1.useCustomTheme)();
|
|
31
|
+
const glass = (0, exports.glassStyles)(colors);
|
|
32
|
+
const reach = Math.max(0, (44 - size) / 2);
|
|
33
|
+
return ((0, jsx_runtime_1.jsx)(react_2.Box, { as: "button", ref: ref, type: "button", "aria-label": label, onClick: onClick, disabled: isDisabled, tabIndex: tabIndex, display: "inline-flex", alignItems: "center", justifyContent: "center", w: `${size}px`, h: `${size}px`, borderRadius: "full", position: "absolute", flexShrink: 0, cursor: "pointer", opacity: isDisabled ? 0 : 1, pointerEvents: isDisabled ? "none" : "auto", transition: (0, motion_1.transitionFor)(["opacity", "background-color"]), _hover: { bg: tint(colors, GLASS_ALPHA_HOVER) }, ...glass, sx: {
|
|
34
|
+
...glass.sx,
|
|
35
|
+
...(0, focusRing_styles_1.focusVisibleStyles)(colors),
|
|
36
|
+
"&::after": { content: '""', position: "absolute", inset: `-${reach}px` },
|
|
37
|
+
...(0, motion_2.reducedMotionSx)(),
|
|
38
|
+
}, ...placement, children: icon }));
|
|
39
|
+
});
|
|
40
|
+
exports.GlassIconButton.displayName = "GlassIconButton";
|
|
41
|
+
/** Non-interactive glass capsule for the counter and zoom hint. */
|
|
42
|
+
const GlassPill = ({ children, height = 28, ...placement }) => {
|
|
43
|
+
const { colors } = (0, useCustomTheme_1.useCustomTheme)();
|
|
44
|
+
const glass = (0, exports.glassStyles)(colors);
|
|
45
|
+
return ((0, jsx_runtime_1.jsx)(react_2.Flex, { align: "center", gap: 1.5, h: `${height}px`, px: 3, borderRadius: "full", position: "absolute", fontSize: "xs", fontWeight: 600, pointerEvents: "none", whiteSpace: "nowrap", ...glass, sx: { ...glass.sx, fontVariantNumeric: "tabular-nums" }, ...placement, children: children }));
|
|
46
|
+
};
|
|
47
|
+
exports.GlassPill = GlassPill;
|