pixelize-design-library 2.4.2-beta.55 → 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 +64 -0
- package/COMPONENT-GOTCHAS.md +50 -22
- package/DESIGN-GUIDE.md +19 -2
- 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/DatePickerProps.d.ts +1 -1
- 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/Input/PhoneNumberInputProps.d.ts +1 -1
- 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/MultiSelect/MultiSelectProps.d.ts +1 -1
- 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/PinInput/PinInputProps.d.ts +1 -1
- 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/Search/SearchProps.d.ts +1 -1
- package/dist/Components/SearchSelect/SearchSelectProps.d.ts +1 -1
- 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/Select/SelectProps.d.ts +1 -1
- package/dist/Components/SelectSearch/SelectSearchProps.d.ts +1 -1
- package/dist/Components/SelectV2/SelectV2Props.d.ts +1 -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/primitives/controlSizes.js +1 -1
- 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/tokens/primitives/controlSizes.js +1 -1
- 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,63 @@
|
|
|
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 tone_1 = require("../../Theme/tokens/builders/tone");
|
|
12
|
+
const price_1 = require("../../Utils/price");
|
|
13
|
+
const ProgressBar_1 = __importDefault(require("../ProgressBar/ProgressBar"));
|
|
14
|
+
const Skeletons_1 = __importDefault(require("../Skeletons/Skeletons"));
|
|
15
|
+
const DEFAULT_LABELS = {
|
|
16
|
+
title: "Price details",
|
|
17
|
+
total: "Total",
|
|
18
|
+
free: "FREE",
|
|
19
|
+
savings: (amount) => `You save ${amount} on this order`,
|
|
20
|
+
addMore: (amount) => `Add ${amount} more for free delivery`,
|
|
21
|
+
unlocked: "You've unlocked free delivery",
|
|
22
|
+
progressLabel: "Progress to free delivery",
|
|
23
|
+
};
|
|
24
|
+
const MINUS = "−";
|
|
25
|
+
const tabular = { fontVariantNumeric: "tabular-nums" };
|
|
26
|
+
const SummarySkeleton = () => ((0, jsx_runtime_1.jsxs)(react_2.Flex, { direction: "column", gap: 4, p: 5, borderRadius: "1.5rem", "aria-busy": "true", "data-testid": "order-summary-skeleton", children: [(0, jsx_runtime_1.jsx)(Skeletons_1.default, { type: "skeleton", height: 4, width: "40%" }), [0, 1, 2].map((row) => ((0, jsx_runtime_1.jsxs)(react_2.Flex, { justify: "space-between", children: [(0, jsx_runtime_1.jsx)(Skeletons_1.default, { type: "skeleton", height: 3, width: "30%" }), (0, jsx_runtime_1.jsx)(Skeletons_1.default, { type: "skeleton", height: 3, width: "20%" })] }, row))), (0, jsx_runtime_1.jsxs)(react_2.Flex, { justify: "space-between", pt: 2, children: [(0, jsx_runtime_1.jsx)(Skeletons_1.default, { type: "skeleton", height: 5, width: "25%" }), (0, jsx_runtime_1.jsx)(Skeletons_1.default, { type: "skeleton", height: 5, width: "30%" })] })] }));
|
|
27
|
+
/** Tonal price panel: label/amount rows, a large tabular total, a calm savings banner and free-delivery progress. */
|
|
28
|
+
const OrderSummary = ({ lines, total, savings, taxNote, freeShippingProgress, hideTitle = false, isLoading = false, currency, locale, labels, "data-testid": testId, }) => {
|
|
29
|
+
const { colors } = (0, useCustomTheme_1.useCustomTheme)();
|
|
30
|
+
const headingId = (0, react_1.useId)();
|
|
31
|
+
const copy = { ...DEFAULT_LABELS, ...labels };
|
|
32
|
+
const fmt = { currency, locale };
|
|
33
|
+
const panel = colors.background[100];
|
|
34
|
+
if (isLoading)
|
|
35
|
+
return (0, jsx_runtime_1.jsx)(SummarySkeleton, {});
|
|
36
|
+
const inkFor = (line, isFree, isDeduction) => {
|
|
37
|
+
if (isFree || isDeduction || line.tone === "success")
|
|
38
|
+
return colors.semanticText.success;
|
|
39
|
+
return line.tone === "muted" ? colors.textMuted : colors.header[900];
|
|
40
|
+
};
|
|
41
|
+
const amountText = (line) => {
|
|
42
|
+
if (typeof line.amount === "string")
|
|
43
|
+
return { text: line.amount, isFree: false, isDeduction: false };
|
|
44
|
+
if (line.amount === 0 && line.freeWhenZero)
|
|
45
|
+
return { text: copy.free, isFree: true, isDeduction: false };
|
|
46
|
+
if (line.amount < 0)
|
|
47
|
+
return { text: `${MINUS}${(0, price_1.formatPrice)(Math.abs(line.amount), fmt)}`, isFree: false, isDeduction: true };
|
|
48
|
+
return { text: (0, price_1.formatPrice)(line.amount, fmt), isFree: false, isDeduction: false };
|
|
49
|
+
};
|
|
50
|
+
const success = (0, tone_1.resolveSoftTone)(colors, (0, tone_1.toneScale)(colors, "success"), panel);
|
|
51
|
+
const progress = freeShippingProgress;
|
|
52
|
+
const remaining = progress ? Math.max(0, progress.threshold - progress.current) : 0;
|
|
53
|
+
const unlocked = !!progress && remaining === 0;
|
|
54
|
+
const percent = progress && progress.threshold > 0 ? Math.min(100, Math.round((progress.current / progress.threshold) * 100)) : 0;
|
|
55
|
+
const progressText = unlocked ? copy.unlocked : copy.addMore((0, price_1.formatPrice)(remaining, fmt));
|
|
56
|
+
return ((0, jsx_runtime_1.jsxs)(react_2.Flex, { direction: "column", gap: 3, "data-testid": testId, children: [progress && ((0, jsx_runtime_1.jsxs)(react_2.Flex, { direction: "column", gap: 2, px: 1, "data-testid": "order-summary-progress", children: [(0, jsx_runtime_1.jsx)(react_2.Text, { as: "p", fontSize: "sm", fontWeight: 600, lineHeight: 1.4, color: unlocked ? colors.semanticText.success : colors.header[900], sx: tabular, children: progressText }), (0, jsx_runtime_1.jsx)(ProgressBar_1.default, { size: "xs", value: percent, colorScheme: unlocked ? "green" : "primary", borderRadius: "full", "aria-label": copy.progressLabel, "aria-valuetext": progressText })] })), (0, jsx_runtime_1.jsxs)(react_2.Box, { as: "section", "aria-labelledby": hideTitle ? undefined : headingId, "aria-label": hideTitle ? copy.title : undefined, bg: panel, borderRadius: "1.5rem", p: 5, children: [!hideTitle && ((0, jsx_runtime_1.jsx)(react_2.Text, { as: "h2", id: headingId, fontSize: "md", fontWeight: 700, lineHeight: 1.4, color: colors.header[900], mb: 4, children: copy.title })), (0, jsx_runtime_1.jsx)(react_2.Flex, { as: "dl", direction: "column", gap: 3, m: 0, children: lines.map((line) => {
|
|
57
|
+
var _a;
|
|
58
|
+
const { text, isFree, isDeduction } = amountText(line);
|
|
59
|
+
const ink = inkFor(line, isFree, isDeduction);
|
|
60
|
+
return ((0, jsx_runtime_1.jsxs)(react_2.Flex, { justify: "space-between", align: "flex-start", gap: 4, children: [(0, jsx_runtime_1.jsxs)(react_2.Box, { as: "dt", minW: 0, children: [(0, jsx_runtime_1.jsx)(react_2.Text, { as: "span", fontSize: "sm", lineHeight: 1.45, color: line.tone === "muted" ? colors.textMuted : colors.text[800], children: line.label }), line.hint && ((0, jsx_runtime_1.jsx)(react_2.Text, { as: "span", display: "block", fontSize: "xs", lineHeight: 1.4, color: colors.textMuted, children: line.hint }))] }), (0, jsx_runtime_1.jsx)(react_2.Box, { as: "dd", m: 0, flexShrink: 0, textAlign: "right", fontSize: "sm", fontWeight: isFree || isDeduction ? 600 : 500, lineHeight: 1.45, color: ink, sx: tabular, children: text })] }, (_a = line.id) !== null && _a !== void 0 ? _a : line.label));
|
|
61
|
+
}) }), (0, jsx_runtime_1.jsxs)(react_2.Flex, { justify: "space-between", align: "baseline", gap: 4, mt: 6, children: [(0, jsx_runtime_1.jsx)(react_2.Text, { as: "span", fontSize: "md", fontWeight: 700, color: colors.header[900], children: copy.total }), (0, jsx_runtime_1.jsxs)(react_2.Box, { textAlign: "right", children: [(0, jsx_runtime_1.jsx)(react_2.Text, { as: "span", display: "block", fontSize: "1.5rem", fontWeight: 700, lineHeight: 1.2, letterSpacing: "-0.02em", color: colors.header[900], sx: tabular, "data-testid": "order-summary-total", children: (0, price_1.formatPrice)(total, fmt) }), taxNote && ((0, jsx_runtime_1.jsx)(react_2.Text, { as: "span", display: "block", fontSize: "xs", lineHeight: 1.4, color: colors.textMuted, children: taxNote }))] })] }), savings !== undefined && savings > 0 && ((0, jsx_runtime_1.jsxs)(react_2.Flex, { align: "center", gap: 2, mt: 4, px: 3, py: 2.5, borderRadius: "0.75rem", bg: success.bg, color: success.fg, "data-testid": "order-summary-savings", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.PartyPopper, { size: 16, "aria-hidden": true }), (0, jsx_runtime_1.jsx)(react_2.Text, { as: "span", fontSize: "sm", fontWeight: 600, lineHeight: 1.4, sx: tabular, children: copy.savings((0, price_1.formatPrice)(savings, fmt)) })] }))] })] }));
|
|
62
|
+
};
|
|
63
|
+
exports.default = OrderSummary;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { PriceFormat } from "../Commerce/commerceTypes";
|
|
2
|
+
/** How a line is inked: default is body ink, success for discounts, muted for secondary lines. */
|
|
3
|
+
export type OrderSummaryTone = "default" | "success" | "muted";
|
|
4
|
+
/** One row of the breakdown. Negative numbers render as a deduction ("−₹500") in the success tone. */
|
|
5
|
+
export interface OrderSummaryLine {
|
|
6
|
+
/** Stable key; falls back to the label. */
|
|
7
|
+
id?: string;
|
|
8
|
+
label: string;
|
|
9
|
+
/** A number is formatted as a price; a string is shown as is, e.g. "Calculated at checkout". */
|
|
10
|
+
amount: number | string;
|
|
11
|
+
tone?: OrderSummaryTone;
|
|
12
|
+
/** Muted line under the label, e.g. "Applied: WELCOME10". */
|
|
13
|
+
hint?: string;
|
|
14
|
+
/** Shows "FREE" in the success tone when `amount` is 0. */
|
|
15
|
+
freeWhenZero?: boolean;
|
|
16
|
+
}
|
|
17
|
+
/** Progress toward a free-delivery threshold, in the same currency as the lines. */
|
|
18
|
+
export interface FreeShippingProgress {
|
|
19
|
+
threshold: number;
|
|
20
|
+
/** Eligible subtotal so far; at or above `threshold` the line reads as unlocked. */
|
|
21
|
+
current: number;
|
|
22
|
+
}
|
|
23
|
+
/** Visible copy; override every string for another language. */
|
|
24
|
+
export interface OrderSummaryLabels {
|
|
25
|
+
title: string;
|
|
26
|
+
total: string;
|
|
27
|
+
/** Shown instead of a number when `amount` is 0 on a `freeWhenZero` line. */
|
|
28
|
+
free: string;
|
|
29
|
+
/** Banner text, given the formatted saving. */
|
|
30
|
+
savings: (amount: string) => string;
|
|
31
|
+
/** Progress text while below the threshold, given the formatted shortfall. */
|
|
32
|
+
addMore: (amount: string) => string;
|
|
33
|
+
/** Progress text once the threshold is met. */
|
|
34
|
+
unlocked: string;
|
|
35
|
+
/** Accessible name of the progress bar. */
|
|
36
|
+
progressLabel: string;
|
|
37
|
+
}
|
|
38
|
+
/** Price breakdown for the bag and checkout: lines, a large tabular total, optional savings banner and free-delivery progress. Flows in the page, so it is sticky-friendly. */
|
|
39
|
+
export interface OrderSummaryProps extends PriceFormat {
|
|
40
|
+
lines: OrderSummaryLine[];
|
|
41
|
+
total: number;
|
|
42
|
+
/** Total saved on the order; the banner is hidden at 0 or when omitted. */
|
|
43
|
+
savings?: number;
|
|
44
|
+
/** Muted line under the total, e.g. "Inclusive of all taxes". */
|
|
45
|
+
taxNote?: string;
|
|
46
|
+
freeShippingProgress?: FreeShippingProgress;
|
|
47
|
+
/** Hides the "Price details" heading when the page already has one. */
|
|
48
|
+
hideTitle?: boolean;
|
|
49
|
+
/** Skeleton of the same shape; the total and lines are not rendered. */
|
|
50
|
+
isLoading?: boolean;
|
|
51
|
+
labels?: Partial<OrderSummaryLabels>;
|
|
52
|
+
"data-testid"?: string;
|
|
53
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { PaymentOptionProps } from "./PaymentOptionProps";
|
|
2
|
+
/** Tonal payment-method row: icon well, title, subtitle, offer tag, and an area that opens when it is chosen. */
|
|
3
|
+
declare const PaymentOption: ({ value, title, subtitle, icon, offer, selected, onSelect, disabled, children, "data-testid": testId, }: PaymentOptionProps) => import("react/jsx-runtime").JSX.Element;
|
|
4
|
+
export default PaymentOption;
|
|
@@ -0,0 +1,24 @@
|
|
|
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 useCustomTheme_1 = require("../../Theme/useCustomTheme");
|
|
10
|
+
const selectable_1 = require("../CheckoutKit/selectable");
|
|
11
|
+
const Tag_1 = __importDefault(require("../Tag/Tag"));
|
|
12
|
+
/** Tonal payment-method row: icon well, title, subtitle, offer tag, and an area that opens when it is chosen. */
|
|
13
|
+
const PaymentOption = ({ value, title, subtitle, icon, offer, selected, onSelect, disabled = false, children, "data-testid": testId, }) => {
|
|
14
|
+
const { colors } = (0, useCustomTheme_1.useCustomTheme)();
|
|
15
|
+
const uid = (0, react_1.useId)();
|
|
16
|
+
const titleId = `${uid}-title`;
|
|
17
|
+
const subtitleId = `${uid}-subtitle`;
|
|
18
|
+
const regionId = `${uid}-region`;
|
|
19
|
+
const { isSelected, interactive, inGroup, ringed, props } = (0, selectable_1.useSelectable)({ value, selected, disabled, onSelect });
|
|
20
|
+
const selectable = inGroup || !!onSelect;
|
|
21
|
+
const expanded = isSelected && !!children;
|
|
22
|
+
return ((0, jsx_runtime_1.jsxs)(react_2.Flex, { direction: "column", "data-testid": testId, "data-selected": isSelected || undefined, ...(0, selectable_1.selectableSurface)(colors, { selected: isSelected && selectable, disabled, interactive, ringed }), children: [(0, jsx_runtime_1.jsxs)(react_2.Flex, { ...props, "data-radio": true, "aria-disabled": selectable && disabled ? true : undefined, "aria-labelledby": props.role ? titleId : undefined, "aria-describedby": props.role && subtitle ? subtitleId : undefined, "aria-controls": expanded && props.role === "radio" ? regionId : undefined, align: "center", gap: 3, p: 4, borderRadius: "1rem", cursor: interactive ? "pointer" : "default", outline: "none", children: [selectable && (0, jsx_runtime_1.jsx)(selectable_1.RadioIndicator, { selected: isSelected }), icon && ((0, jsx_runtime_1.jsx)(react_2.Flex, { as: "span", "aria-hidden": true, align: "center", justify: "center", boxSize: 10, flexShrink: 0, borderRadius: "0.75rem", bg: colors.background[50], color: colors.header[900], children: icon })), (0, jsx_runtime_1.jsxs)(react_2.Box, { flex: 1, minW: 0, children: [(0, jsx_runtime_1.jsx)(react_2.Text, { as: "span", id: titleId, display: "block", fontSize: "sm", fontWeight: 600, lineHeight: 1.4, color: colors.header[900], children: title }), subtitle && ((0, jsx_runtime_1.jsx)(react_2.Text, { as: "span", id: subtitleId, display: "block", fontSize: "xs", lineHeight: 1.4, color: colors.textMuted, children: subtitle }))] }), offer && (0, jsx_runtime_1.jsx)(Tag_1.default, { label: offer, size: "xs", tone: "success" })] }), expanded && ((0, jsx_runtime_1.jsx)(react_2.Box, { id: regionId, role: "group", "aria-labelledby": titleId, px: 4, pb: 4, pl: selectable ? "3.25rem" : 4, children: children }))] }));
|
|
23
|
+
};
|
|
24
|
+
exports.default = PaymentOption;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
4
|
+
const selectable_1 = require("../CheckoutKit/selectable");
|
|
5
|
+
/** Radiogroup wrapper for `PaymentOption`s. */
|
|
6
|
+
const PaymentOptionGroup = (props) => (0, jsx_runtime_1.jsx)(selectable_1.SelectableGroup, { ...props });
|
|
7
|
+
exports.default = PaymentOptionGroup;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
/** A payment-method row. Inside a `PaymentOptionGroup` it is a radio keyed by `value`; alone, `onSelect` makes it a toggle button. */
|
|
3
|
+
export interface PaymentOptionProps {
|
|
4
|
+
/** Identifies the option inside a `PaymentOptionGroup`; required there. */
|
|
5
|
+
value?: string;
|
|
6
|
+
title: string;
|
|
7
|
+
/** Muted line under the title, e.g. "Pay on delivery · ₹50 handling fee". */
|
|
8
|
+
subtitle?: string;
|
|
9
|
+
/** Slot for a method icon or logo, shown in a 40px well. */
|
|
10
|
+
icon?: ReactNode;
|
|
11
|
+
/** Short offer tag, e.g. "5% cashback". */
|
|
12
|
+
offer?: string;
|
|
13
|
+
/** Standalone selection state; ignored inside a group, where the group's value decides. */
|
|
14
|
+
selected?: boolean;
|
|
15
|
+
onSelect?: () => void;
|
|
16
|
+
/** Dims the row and drops it from the tab order, e.g. COD above the order limit; say why in `subtitle`. */
|
|
17
|
+
disabled?: boolean;
|
|
18
|
+
/** Revealed under the row only while it is selected, e.g. a UPI id input. Interactive content here sits outside the radio. */
|
|
19
|
+
children?: ReactNode;
|
|
20
|
+
"data-testid"?: string;
|
|
21
|
+
}
|
|
22
|
+
/** Radiogroup of `PaymentOption`s with a roving tab stop; arrow keys move focus and selection together. */
|
|
23
|
+
export interface PaymentOptionGroupProps {
|
|
24
|
+
value?: string;
|
|
25
|
+
defaultValue?: string;
|
|
26
|
+
onValueChange?: (value: string) => void;
|
|
27
|
+
/** Direct `PaymentOption` children; wrapping them in another component hides their `value` from the roving tab stop. */
|
|
28
|
+
children: ReactNode;
|
|
29
|
+
"aria-label"?: string;
|
|
30
|
+
"aria-labelledby"?: string;
|
|
31
|
+
"data-testid"?: string;
|
|
32
|
+
}
|
|
@@ -2,7 +2,7 @@ import { PinInputProps } from "@chakra-ui/react";
|
|
|
2
2
|
/** The only pin/OTP component exported from the package. */
|
|
3
3
|
export type ChakraPinInputProps = Pick<PinInputProps, "otp" | "mask" | "defaultValue" | "placeholder" | "manageFocus" | "errorBorderColor" | "focusBorderColor" | "onChange" | "onComplete"> & {
|
|
4
4
|
type?: "alphanumeric" | "number";
|
|
5
|
-
/** Square cell size, aligned to CONTROL_SIZES heights (xs
|
|
5
|
+
/** Square cell size, aligned to CONTROL_SIZES heights (xs 32 · sm 38 · md 40 · lg 48). Defaults to "sm". */
|
|
6
6
|
size?: "xs" | "sm" | "md" | "lg";
|
|
7
7
|
variant?: "flushed" | "outline" | "filled" | "unstyled";
|
|
8
8
|
color?: "gray" | "red" | "orange" | "yellow" | "green" | "teal" | "blue" | "cyan" | "purple" | "pink" | "whiteAlpha" | "blackAlpha" | "primary";
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { PincodeCheckerProps } from "./PincodeCheckerProps";
|
|
2
|
+
/** Pincode field that answers with a delivery date, COD availability and a shipping note, held in place so the panel never jumps. */
|
|
3
|
+
declare const PincodeChecker: ({ value, defaultValue, onValueChange, status: statusProp, result: resultProp, onCheck, autoCheck, checkOnMount, labels, "data-testid": testId, }: PincodeCheckerProps) => import("react/jsx-runtime").JSX.Element;
|
|
4
|
+
export default PincodeChecker;
|
|
@@ -0,0 +1,175 @@
|
|
|
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 react_3 = require("@emotion/react");
|
|
10
|
+
const lucide_react_1 = require("lucide-react");
|
|
11
|
+
const Button_1 = __importDefault(require("../Button/Button"));
|
|
12
|
+
const useCustomTheme_1 = require("../../Theme/useCustomTheme");
|
|
13
|
+
const focusRing_styles_1 = require("../../Theme/chakra/focusRing.styles");
|
|
14
|
+
const fieldStyles_1 = require("../Common/fieldStyles");
|
|
15
|
+
const placeholderInk_1 = require("../../Theme/tokens/builders/placeholderInk");
|
|
16
|
+
const motion_1 = require("../../Theme/tokens/primitives/motion");
|
|
17
|
+
const motion_2 = require("../../Theme/chakra/motion");
|
|
18
|
+
const DEFAULT_LABELS = {
|
|
19
|
+
heading: "Check delivery",
|
|
20
|
+
inputLabel: "Pincode",
|
|
21
|
+
placeholder: "Enter pincode",
|
|
22
|
+
check: "Check",
|
|
23
|
+
change: "Change",
|
|
24
|
+
hint: "Delivery date, COD and returns for your area",
|
|
25
|
+
invalid: "Enter a 6-digit pincode",
|
|
26
|
+
unserviceable: "We don't deliver here yet",
|
|
27
|
+
checking: "Checking delivery",
|
|
28
|
+
deliveryBy: "Delivery by",
|
|
29
|
+
codAvailable: "Cash on Delivery available",
|
|
30
|
+
codUnavailable: "Cash on Delivery not available",
|
|
31
|
+
deliverTo: "Deliver to",
|
|
32
|
+
unserviceableHint: "Try another pincode",
|
|
33
|
+
};
|
|
34
|
+
const PIN_LENGTH = 6;
|
|
35
|
+
const FIELD_HEIGHT = "3rem";
|
|
36
|
+
const ERROR_RING = "1.5px";
|
|
37
|
+
const tabular = { fontVariantNumeric: "tabular-nums" };
|
|
38
|
+
const pulse = (0, react_3.keyframes) `0%, 100% { opacity: 1; } 50% { opacity: 0.5; }`;
|
|
39
|
+
const digitsOnly = (raw) => raw.replace(/\D/g, "").slice(0, PIN_LENGTH);
|
|
40
|
+
const isPin = (pin) => pin.length === PIN_LENGTH;
|
|
41
|
+
const isThenable = (value) => typeof value === "object" && value !== null && typeof value.then === "function";
|
|
42
|
+
const SkeletonBlock = ({ w, h }) => {
|
|
43
|
+
const { colors } = (0, useCustomTheme_1.useCustomTheme)();
|
|
44
|
+
return ((0, jsx_runtime_1.jsx)(react_2.Box, { "aria-hidden": true, w: w, h: h, borderRadius: "md", bg: colors.background[200], animation: `${pulse} 1.2s ease-in-out infinite`, sx: (0, motion_2.reducedMotionSx)() }));
|
|
45
|
+
};
|
|
46
|
+
/** Pincode field that answers with a delivery date, COD availability and a shipping note, held in place so the panel never jumps. */
|
|
47
|
+
const PincodeChecker = ({ value, defaultValue = "", onValueChange, status: statusProp, result: resultProp, onCheck, autoCheck = true, checkOnMount = false, labels, "data-testid": testId, }) => {
|
|
48
|
+
const { colors } = (0, useCustomTheme_1.useCustomTheme)();
|
|
49
|
+
const copy = { ...DEFAULT_LABELS, ...labels };
|
|
50
|
+
const baseId = (0, react_1.useId)();
|
|
51
|
+
const inputId = `${baseId}-pin`;
|
|
52
|
+
const hintId = `${baseId}-hint`;
|
|
53
|
+
const errorId = `${baseId}-error`;
|
|
54
|
+
const [innerPin, setInnerPin] = (0, react_1.useState)(digitsOnly(defaultValue));
|
|
55
|
+
const [innerStatus, setInnerStatus] = (0, react_1.useState)("idle");
|
|
56
|
+
const [innerResult, setInnerResult] = (0, react_1.useState)();
|
|
57
|
+
const [editing, setEditing] = (0, react_1.useState)(false);
|
|
58
|
+
const [localInvalid, setLocalInvalid] = (0, react_1.useState)(false);
|
|
59
|
+
const inputRef = (0, react_1.useRef)(null);
|
|
60
|
+
const changeRef = (0, react_1.useRef)(null);
|
|
61
|
+
const latest = (0, react_1.useRef)(0);
|
|
62
|
+
const mounted = (0, react_1.useRef)(true);
|
|
63
|
+
const focusInput = (0, react_1.useRef)(false);
|
|
64
|
+
const focusChange = (0, react_1.useRef)(false);
|
|
65
|
+
const pin = value === undefined ? innerPin : digitsOnly(value);
|
|
66
|
+
const status = statusProp !== null && statusProp !== void 0 ? statusProp : innerStatus;
|
|
67
|
+
const result = resultProp !== null && resultProp !== void 0 ? resultProp : innerResult;
|
|
68
|
+
const invalid = localInvalid || status === "invalid";
|
|
69
|
+
const outcome = status === "serviceable" || status === "unserviceable"
|
|
70
|
+
? status
|
|
71
|
+
: status === "idle" || status === "invalid"
|
|
72
|
+
? null
|
|
73
|
+
: result
|
|
74
|
+
? result.ok
|
|
75
|
+
? "serviceable"
|
|
76
|
+
: "unserviceable"
|
|
77
|
+
: null;
|
|
78
|
+
const checking = status === "checking";
|
|
79
|
+
const showField = editing || status === "idle" || invalid;
|
|
80
|
+
(0, react_1.useEffect)(() => {
|
|
81
|
+
mounted.current = true;
|
|
82
|
+
return () => {
|
|
83
|
+
mounted.current = false;
|
|
84
|
+
};
|
|
85
|
+
}, []);
|
|
86
|
+
(0, react_1.useEffect)(() => {
|
|
87
|
+
if (status === "serviceable" || status === "unserviceable")
|
|
88
|
+
setEditing(false);
|
|
89
|
+
}, [status]);
|
|
90
|
+
(0, react_1.useEffect)(() => {
|
|
91
|
+
var _a, _b;
|
|
92
|
+
if (showField && focusInput.current) {
|
|
93
|
+
focusInput.current = false;
|
|
94
|
+
(_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.focus();
|
|
95
|
+
}
|
|
96
|
+
if (!showField && focusChange.current) {
|
|
97
|
+
focusChange.current = false;
|
|
98
|
+
(_b = changeRef.current) === null || _b === void 0 ? void 0 : _b.focus();
|
|
99
|
+
}
|
|
100
|
+
}, [showField]);
|
|
101
|
+
const settle = (0, react_1.useCallback)((answer) => {
|
|
102
|
+
if (document.activeElement === inputRef.current)
|
|
103
|
+
focusChange.current = true;
|
|
104
|
+
setInnerResult(answer);
|
|
105
|
+
setInnerStatus(answer.ok ? "serviceable" : "unserviceable");
|
|
106
|
+
setEditing(false);
|
|
107
|
+
}, []);
|
|
108
|
+
const run = (0, react_1.useCallback)((code) => {
|
|
109
|
+
if (!isPin(code)) {
|
|
110
|
+
setLocalInvalid(true);
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
setLocalInvalid(false);
|
|
114
|
+
setEditing(showField);
|
|
115
|
+
const ticket = ++latest.current;
|
|
116
|
+
const answer = onCheck === null || onCheck === void 0 ? void 0 : onCheck(code);
|
|
117
|
+
if (answer === undefined)
|
|
118
|
+
return;
|
|
119
|
+
if (!isThenable(answer)) {
|
|
120
|
+
settle(answer);
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
setInnerStatus("checking");
|
|
124
|
+
answer.then((resolved) => {
|
|
125
|
+
if (mounted.current && ticket === latest.current)
|
|
126
|
+
settle(resolved);
|
|
127
|
+
}, () => {
|
|
128
|
+
if (mounted.current && ticket === latest.current)
|
|
129
|
+
settle({ ok: false });
|
|
130
|
+
});
|
|
131
|
+
}, [onCheck, settle, showField]);
|
|
132
|
+
(0, react_1.useEffect)(() => {
|
|
133
|
+
if (checkOnMount && isPin(pin))
|
|
134
|
+
run(pin);
|
|
135
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
136
|
+
}, []);
|
|
137
|
+
const onChange = (event) => {
|
|
138
|
+
const next = digitsOnly(event.target.value);
|
|
139
|
+
if (value === undefined)
|
|
140
|
+
setInnerPin(next);
|
|
141
|
+
onValueChange === null || onValueChange === void 0 ? void 0 : onValueChange(next);
|
|
142
|
+
setEditing(true);
|
|
143
|
+
setLocalInvalid(false);
|
|
144
|
+
if (autoCheck && isPin(next))
|
|
145
|
+
run(next);
|
|
146
|
+
};
|
|
147
|
+
const onSubmit = (event) => {
|
|
148
|
+
var _a;
|
|
149
|
+
event.preventDefault();
|
|
150
|
+
if (!isPin(pin))
|
|
151
|
+
(_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.focus();
|
|
152
|
+
run(pin);
|
|
153
|
+
};
|
|
154
|
+
const reopen = () => {
|
|
155
|
+
focusInput.current = true;
|
|
156
|
+
setEditing(true);
|
|
157
|
+
};
|
|
158
|
+
const fieldRing = invalid
|
|
159
|
+
? `inset 0 0 0 ${ERROR_RING} ${colors.semanticText.error}`
|
|
160
|
+
: "none";
|
|
161
|
+
const field = ((0, jsx_runtime_1.jsxs)(react_2.Box, { as: "form", noValidate: true, onSubmit: onSubmit, children: [(0, jsx_runtime_1.jsxs)(react_2.Flex, { gap: 2, align: "stretch", children: [(0, jsx_runtime_1.jsx)(react_2.Box, { as: "input", ref: inputRef, id: inputId, type: "text", inputMode: "numeric", autoComplete: "postal-code", maxLength: PIN_LENGTH, value: pin, placeholder: copy.placeholder, onChange: onChange, onBlur: () => {
|
|
162
|
+
if (pin.length > 0 && !isPin(pin))
|
|
163
|
+
setLocalInvalid(true);
|
|
164
|
+
}, "aria-invalid": invalid || undefined, "aria-describedby": invalid ? errorId : hintId, flex: 1, minW: 0, h: FIELD_HEIGHT, px: 4, fontSize: "md", bg: colors.background[50], borderWidth: "1px", borderStyle: "solid", borderColor: "transparent", borderRadius: fieldStyles_1.FIELD_RADIUS, boxShadow: fieldRing, transition: fieldStyles_1.FIELD_TRANSITION, _placeholder: { color: (0, placeholderInk_1.placeholderInk)(colors), opacity: 1 }, _hover: invalid ? undefined : { borderColor: (0, fieldStyles_1.fieldHoverBorder)(colors) }, _focusVisible: {
|
|
165
|
+
borderColor: invalid ? "transparent" : colors.primary[500],
|
|
166
|
+
...(0, focusRing_styles_1.fieldFocusVisible)(colors),
|
|
167
|
+
boxShadow: invalid ? `${fieldRing}, ${(0, focusRing_styles_1.fieldFocusVisible)(colors).boxShadow}` : (0, focusRing_styles_1.fieldFocusVisible)(colors).boxShadow,
|
|
168
|
+
}, sx: { ...(0, fieldStyles_1.fieldTextStyles)(colors), ...tabular, letterSpacing: "0.08em", ...(0, motion_2.reducedMotionSx)() } }), (0, jsx_runtime_1.jsx)(Button_1.default, { type: "submit", size: "lg", label: copy.check })] }), invalid ? ((0, jsx_runtime_1.jsxs)(react_2.Flex, { id: errorId, mt: 2, gap: 1.5, align: "center", fontSize: "sm", fontWeight: 500, color: colors.semanticText.error, children: [(0, jsx_runtime_1.jsx)(lucide_react_1.CircleAlert, { size: 16, "aria-hidden": true, style: { flexShrink: 0 } }), (0, jsx_runtime_1.jsx)(react_2.Text, { as: "span", children: (status === "invalid" && (result === null || result === void 0 ? void 0 : result.message)) || copy.invalid })] })) : ((0, jsx_runtime_1.jsx)(react_2.Text, { id: hintId, mt: 2, fontSize: "xs", color: colors.textMuted, children: copy.hint }))] }));
|
|
169
|
+
const changeButton = ((0, jsx_runtime_1.jsx)(Button_1.default, { ref: changeRef, variant: "link", size: "sm", h: "2.75rem", flexShrink: 0, onClick: reopen, label: copy.change }));
|
|
170
|
+
const savedLine = !showField && outcome === "serviceable" ? ((0, jsx_runtime_1.jsxs)(react_2.Flex, { align: "center", justify: "space-between", gap: 3, children: [(0, jsx_runtime_1.jsxs)(react_2.Text, { fontSize: "sm", color: colors.textMuted, sx: tabular, children: [copy.deliverTo, " ", (0, jsx_runtime_1.jsxs)(react_2.Text, { as: "span", fontWeight: 600, color: colors.header[900], children: [pin, (result === null || result === void 0 ? void 0 : result.city) ? ` · ${result.city}` : ""] })] }), changeButton] })) : null;
|
|
171
|
+
const details = outcome === "serviceable" && result ? ((0, jsx_runtime_1.jsxs)(react_2.Flex, { direction: "column", gap: 2, children: [result.deliveryBy && ((0, jsx_runtime_1.jsxs)(react_2.Text, { fontSize: "lg", lineHeight: 1.3, sx: tabular, children: [(0, jsx_runtime_1.jsxs)(react_2.Text, { as: "span", fontSize: "sm", color: colors.textMuted, children: [copy.deliveryBy, " "] }), (0, jsx_runtime_1.jsx)(react_2.Text, { as: "span", fontWeight: 700, color: colors.header[900], children: result.deliveryBy })] })), result.cod !== undefined && ((0, jsx_runtime_1.jsxs)(react_2.Flex, { align: "center", gap: 2, fontSize: "sm", fontWeight: 500, color: colors.header[900], children: [result.cod ? ((0, jsx_runtime_1.jsx)(react_2.Box, { as: "span", color: colors.semanticText.success, display: "inline-flex", children: (0, jsx_runtime_1.jsx)(lucide_react_1.Check, { size: 16, "aria-hidden": true }) })) : ((0, jsx_runtime_1.jsx)(react_2.Box, { as: "span", color: colors.semanticText.warning, display: "inline-flex", children: (0, jsx_runtime_1.jsx)(lucide_react_1.Info, { size: 16, "aria-hidden": true }) })), (0, jsx_runtime_1.jsx)(react_2.Text, { as: "span", children: result.cod ? copy.codAvailable : copy.codUnavailable })] })), result.shippingNote && ((0, jsx_runtime_1.jsx)(react_2.Text, { fontSize: "xs", color: colors.textMuted, children: result.shippingNote }))] })) : outcome === "unserviceable" ? ((0, jsx_runtime_1.jsxs)(react_2.Flex, { align: "flex-start", justify: "space-between", gap: 3, children: [(0, jsx_runtime_1.jsxs)(react_2.Box, { children: [(0, jsx_runtime_1.jsx)(react_2.Text, { fontSize: "md", fontWeight: 600, color: colors.header[900], children: (result === null || result === void 0 ? void 0 : result.message) || copy.unserviceable }), (0, jsx_runtime_1.jsx)(react_2.Text, { fontSize: "sm", color: colors.textMuted, children: copy.unserviceableHint })] }), !showField && changeButton] })) : null;
|
|
172
|
+
const skeleton = checking && !outcome && ((0, jsx_runtime_1.jsxs)(react_2.Flex, { direction: "column", gap: 3, "aria-hidden": true, children: [(0, jsx_runtime_1.jsx)(SkeletonBlock, { w: "55%", h: "0.875rem" }), (0, jsx_runtime_1.jsx)(SkeletonBlock, { w: "40%", h: "1.5rem" }), (0, jsx_runtime_1.jsx)(SkeletonBlock, { w: "70%", h: "0.875rem" })] }));
|
|
173
|
+
return ((0, jsx_runtime_1.jsxs)(react_2.Box, { "aria-busy": checking || undefined, bg: colors.background[100], borderRadius: "xl", p: 4, "data-testid": testId, children: [(0, jsx_runtime_1.jsx)(react_2.Text, { as: "h2", fontSize: "md", fontWeight: 600, color: colors.header[900], mb: 3, children: copy.heading }), showField && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(react_2.VisuallyHidden, { as: "label", htmlFor: inputId, children: copy.inputLabel }), field] })), (0, jsx_runtime_1.jsxs)(react_2.Flex, { direction: "column", gap: 3, mt: showField && (outcome || skeleton) ? 4 : 0, "aria-live": "polite", opacity: checking && outcome ? 0.6 : 1, transition: (0, motion_1.transitionFor)(["opacity"]), sx: (0, motion_2.reducedMotionSx)(), children: [checking && (0, jsx_runtime_1.jsx)(react_2.VisuallyHidden, { children: copy.checking }), savedLine, details, skeleton] })] }));
|
|
174
|
+
};
|
|
175
|
+
exports.default = PincodeChecker;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/** Where the check is: nothing entered, request in flight, a serviceable or unserviceable answer, or a malformed pincode. */
|
|
2
|
+
export type PincodeStatus = "idle" | "checking" | "serviceable" | "unserviceable" | "invalid";
|
|
3
|
+
/** The answer for one pincode; structurally the same as the demo fixtures' `PincodeResult`. */
|
|
4
|
+
export interface PincodeResult {
|
|
5
|
+
/** False means the pincode is not serviceable. */
|
|
6
|
+
ok: boolean;
|
|
7
|
+
city?: string;
|
|
8
|
+
/** Ready-to-print delivery date such as "Thu, 8 Oct"; never a range of days. */
|
|
9
|
+
deliveryBy?: string;
|
|
10
|
+
/** Cash on delivery available at this pincode. */
|
|
11
|
+
cod?: boolean;
|
|
12
|
+
/** Fee rules, e.g. "Free above ₹999 · ₹49 handling with COD". */
|
|
13
|
+
shippingNote?: string;
|
|
14
|
+
/** Replaces the default wording for an unserviceable or invalid pincode. */
|
|
15
|
+
message?: string;
|
|
16
|
+
}
|
|
17
|
+
/** Every string the checker renders; override all of them for another language. */
|
|
18
|
+
export interface PincodeCheckerLabels {
|
|
19
|
+
heading: string;
|
|
20
|
+
inputLabel: string;
|
|
21
|
+
placeholder: string;
|
|
22
|
+
check: string;
|
|
23
|
+
change: string;
|
|
24
|
+
/** Visible helper under the idle field. */
|
|
25
|
+
hint: string;
|
|
26
|
+
invalid: string;
|
|
27
|
+
unserviceable: string;
|
|
28
|
+
checking: string;
|
|
29
|
+
/** Prefix before the date, e.g. "Delivery by". */
|
|
30
|
+
deliveryBy: string;
|
|
31
|
+
codAvailable: string;
|
|
32
|
+
codUnavailable: string;
|
|
33
|
+
/** Prefix in the saved line, e.g. "Deliver to". */
|
|
34
|
+
deliverTo: string;
|
|
35
|
+
/** Helper under the unserviceable message. */
|
|
36
|
+
unserviceableHint: string;
|
|
37
|
+
}
|
|
38
|
+
/** Six-digit pincode field that answers with a delivery date, COD availability and a shipping note. */
|
|
39
|
+
export interface PincodeCheckerProps {
|
|
40
|
+
/** Controlled pincode digits; pair with `onValueChange`. */
|
|
41
|
+
value?: string;
|
|
42
|
+
/** Starting pincode when uncontrolled, e.g. the shopper's last one. */
|
|
43
|
+
defaultValue?: string;
|
|
44
|
+
onValueChange?: (pincode: string) => void;
|
|
45
|
+
/** Controlled status; omit it and the checker derives the status from what `onCheck` resolves. */
|
|
46
|
+
status?: PincodeStatus;
|
|
47
|
+
/** Controlled result matching `status`; omit it and the checker keeps the last `onCheck` result. */
|
|
48
|
+
result?: PincodeResult;
|
|
49
|
+
/** Runs when a valid pincode is submitted (Check, Enter, or the sixth digit with `autoCheck`). */
|
|
50
|
+
onCheck?: (pincode: string) => Promise<PincodeResult> | PincodeResult | void;
|
|
51
|
+
/** Checks as soon as the sixth digit is typed; the Check button always works. */
|
|
52
|
+
autoCheck?: boolean;
|
|
53
|
+
/** Runs `onCheck` once on mount when the initial pincode is valid, for a saved pincode. */
|
|
54
|
+
checkOnMount?: boolean;
|
|
55
|
+
labels?: Partial<PincodeCheckerLabels>;
|
|
56
|
+
"data-testid"?: string;
|
|
57
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { PriceBlockProps } from "./PriceBlockProps";
|
|
2
|
+
/** Selling price, struck MRP, discount, savings, tax note and unit price in one tabular, screen-reader-friendly block. */
|
|
3
|
+
declare const PriceBlock: ({ price, mrp, priceRange, size, align, showSavings, taxNote, unitPrice, currency, locale, labels, "data-testid": testId, }: PriceBlockProps) => import("react/jsx-runtime").JSX.Element;
|
|
4
|
+
export default PriceBlock;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
4
|
+
const react_1 = require("@chakra-ui/react");
|
|
5
|
+
const useCustomTheme_1 = require("../../Theme/useCustomTheme");
|
|
6
|
+
const price_1 = require("../../Utils/price");
|
|
7
|
+
const SCALE = {
|
|
8
|
+
sm: { price: "0.9375rem", priceLine: 1.33, secondary: "0.75rem", secondaryLine: 1.33, note: "0.75rem" },
|
|
9
|
+
md: { price: "1.125rem", priceLine: 1.22, secondary: "0.8125rem", secondaryLine: 1.38, note: "0.75rem" },
|
|
10
|
+
lg: { price: "1.75rem", priceLine: 1.21, secondary: "0.9375rem", secondaryLine: 1.47, note: "0.8125rem" },
|
|
11
|
+
};
|
|
12
|
+
const ALIGN = {
|
|
13
|
+
start: { items: "flex-start", justify: "flex-start", text: "left" },
|
|
14
|
+
center: { items: "center", justify: "center", text: "center" },
|
|
15
|
+
end: { items: "flex-end", justify: "flex-end", text: "right" },
|
|
16
|
+
};
|
|
17
|
+
const DEFAULT_LABELS = {
|
|
18
|
+
price: "Price",
|
|
19
|
+
originalPrice: "Original price",
|
|
20
|
+
off: (percent) => `${percent}% off`,
|
|
21
|
+
save: (amount) => `You save ${amount}`,
|
|
22
|
+
};
|
|
23
|
+
const unitText = (unit, fmt) => typeof unit === "string" ? unit : `${(0, price_1.formatPrice)(unit.value, fmt)} / ${unit.per === 1 ? "" : `${unit.per} `}${unit.unit}`;
|
|
24
|
+
const tabular = { fontVariantNumeric: "tabular-nums" };
|
|
25
|
+
/** Selling price, struck MRP, discount, savings, tax note and unit price in one tabular, screen-reader-friendly block. */
|
|
26
|
+
const PriceBlock = ({ price, mrp, priceRange, size = "md", align = "start", showSavings = false, taxNote, unitPrice, currency, locale, labels, "data-testid": testId, }) => {
|
|
27
|
+
const { colors } = (0, useCustomTheme_1.useCustomTheme)();
|
|
28
|
+
const fmt = { currency, locale };
|
|
29
|
+
const copy = { ...DEFAULT_LABELS, ...labels };
|
|
30
|
+
const scale = SCALE[size];
|
|
31
|
+
const a = ALIGN[align];
|
|
32
|
+
const isRange = !!priceRange && priceRange.min !== priceRange.max;
|
|
33
|
+
const selling = priceRange ? priceRange.min : price;
|
|
34
|
+
const priceText = isRange ? `${(0, price_1.formatPrice)(priceRange.min, fmt)} – ${(0, price_1.formatPrice)(priceRange.max, fmt)}` : selling === undefined ? null : (0, price_1.formatPrice)(selling, fmt);
|
|
35
|
+
const percent = !priceRange && selling !== undefined ? (0, price_1.discountPercent)(selling, mrp) : 0;
|
|
36
|
+
const saved = !priceRange && selling !== undefined ? (0, price_1.discountAmount)(selling, mrp) : 0;
|
|
37
|
+
const hasDiscount = percent > 0;
|
|
38
|
+
const muted = { fontSize: scale.note, lineHeight: 1.4, color: colors.textMuted, sx: tabular };
|
|
39
|
+
return ((0, jsx_runtime_1.jsxs)(react_1.Flex, { direction: "column", align: a.items, gap: 0.5, textAlign: a.text, "data-testid": testId, children: [(0, jsx_runtime_1.jsxs)(react_1.Flex, { align: "baseline", justify: a.justify, columnGap: 2, rowGap: 0, wrap: "wrap", children: [priceText !== null && ((0, jsx_runtime_1.jsxs)(react_1.Text, { as: "span", fontSize: scale.price, lineHeight: scale.priceLine, fontWeight: 700, letterSpacing: "-0.02em", color: colors.header[900], sx: tabular, children: [(0, jsx_runtime_1.jsxs)(react_1.VisuallyHidden, { children: [copy.price, " "] }), priceText] })), hasDiscount && mrp !== undefined && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)(react_1.Box, { as: "del", fontSize: scale.secondary, lineHeight: scale.secondaryLine, color: colors.textMuted, textDecoration: "line-through", sx: tabular, children: [(0, jsx_runtime_1.jsxs)(react_1.VisuallyHidden, { children: [copy.originalPrice, " "] }), (0, price_1.formatPrice)(mrp, fmt)] }), (0, jsx_runtime_1.jsx)(react_1.Text, { as: "span", fontSize: scale.secondary, lineHeight: scale.secondaryLine, fontWeight: 600, color: colors.semanticText.success, sx: tabular, children: copy.off(percent) })] }))] }), showSavings && hasDiscount && ((0, jsx_runtime_1.jsx)(react_1.Text, { as: "span", fontSize: scale.note, lineHeight: 1.4, fontWeight: 600, color: colors.semanticText.success, sx: tabular, children: copy.save((0, price_1.formatPrice)(saved, fmt)) })), taxNote && ((0, jsx_runtime_1.jsx)(react_1.Text, { as: "span", ...muted, children: taxNote })), unitPrice != null && ((0, jsx_runtime_1.jsx)(react_1.Text, { as: "span", ...muted, children: unitText(unitPrice, fmt) }))] }));
|
|
40
|
+
};
|
|
41
|
+
exports.default = PriceBlock;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { PriceFormat } from "../Commerce/commerceTypes";
|
|
2
|
+
import type { UnitPrice } from "../../Utils/price";
|
|
3
|
+
/** Price typography scale: sm for cards, md for rows and sticky bars, lg for the product page. */
|
|
4
|
+
export type PriceBlockSize = "sm" | "md" | "lg";
|
|
5
|
+
/** Cross-axis alignment of the price lines inside the block. */
|
|
6
|
+
export type PriceBlockAlign = "start" | "center" | "end";
|
|
7
|
+
/** Visually-hidden and visible copy; override every string for another language. */
|
|
8
|
+
export interface PriceBlockLabels {
|
|
9
|
+
/** Screen-reader prefix before the selling price. */
|
|
10
|
+
price: string;
|
|
11
|
+
/** Screen-reader prefix inside the struck MRP. */
|
|
12
|
+
originalPrice: string;
|
|
13
|
+
/** Visible discount text, given the whole-number percentage. */
|
|
14
|
+
off: (percent: number) => string;
|
|
15
|
+
/** Visible savings text, given the already-formatted amount. */
|
|
16
|
+
save: (amount: string) => string;
|
|
17
|
+
}
|
|
18
|
+
/** Selling price with struck MRP, discount, tax note and unit price; every figure comes from `Utils/price` helpers. */
|
|
19
|
+
export interface PriceBlockProps extends PriceFormat {
|
|
20
|
+
/** Selling price; ignored when `priceRange` is set. */
|
|
21
|
+
price?: number;
|
|
22
|
+
/** Original list price; the strike and discount only render when it is above `price`. */
|
|
23
|
+
mrp?: number;
|
|
24
|
+
/** Shows "min – max" instead of a single price, e.g. for a product whose variants differ; hides the MRP and discount. */
|
|
25
|
+
priceRange?: {
|
|
26
|
+
min: number;
|
|
27
|
+
max: number;
|
|
28
|
+
};
|
|
29
|
+
size?: PriceBlockSize;
|
|
30
|
+
align?: PriceBlockAlign;
|
|
31
|
+
/** Adds a "You save ₹1,500" line under the price; needs `mrp`. */
|
|
32
|
+
showSavings?: boolean;
|
|
33
|
+
/** Muted line under the price, e.g. "Inclusive of all taxes". */
|
|
34
|
+
taxNote?: string;
|
|
35
|
+
/** A `unitPrice()` result (null renders nothing), or a ready-made string; rendered as "₹169.80 / 100 g". */
|
|
36
|
+
unitPrice?: UnitPrice | string | null;
|
|
37
|
+
labels?: Partial<PriceBlockLabels>;
|
|
38
|
+
"data-testid"?: string;
|
|
39
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ProductBadgesProps } from "./ProductBadgesProps";
|
|
2
|
+
/** Stack of corner badges (sale, new, low stock…) built from `ProductBadge[]`; filled chips resolve ink per brand and mode. */
|
|
3
|
+
declare const ProductBadges: ({ badges, max, size, variant, orientation, "data-testid": testId, }: ProductBadgesProps) => import("react/jsx-runtime").JSX.Element | null;
|
|
4
|
+
export default ProductBadges;
|