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