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.
Files changed (365) hide show
  1. package/CHANGELOG.md +64 -0
  2. package/COMPONENT-GOTCHAS.md +50 -22
  3. package/DESIGN-GUIDE.md +19 -2
  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/DatePickerProps.d.ts +1 -1
  35. package/dist/Components/DatePicker/PickerPortal.d.ts +11 -0
  36. package/dist/Components/DatePicker/PickerPortal.js +26 -0
  37. package/dist/Components/DatePicker/RangeDatePicker.d.ts +1 -1
  38. package/dist/Components/DatePicker/RangeDatePicker.js +67 -32
  39. package/dist/Components/DatePicker/SingleDatePicker.js +49 -13
  40. package/dist/Components/DatePicker/TimeOnlyPicker.js +39 -4
  41. package/dist/Components/DetailSections/DetailSections.d.ts +4 -0
  42. package/dist/Components/DetailSections/DetailSections.js +112 -0
  43. package/dist/Components/DetailSections/DetailSectionsProps.d.ts +58 -0
  44. package/dist/Components/DetailSections/DetailSectionsProps.js +2 -0
  45. package/dist/Components/Input/PhoneNumberInputProps.d.ts +1 -1
  46. package/dist/Components/MediaGallery/MediaFrame.d.ts +31 -0
  47. package/dist/Components/MediaGallery/MediaFrame.js +55 -0
  48. package/dist/Components/MediaGallery/MediaGallery.d.ts +4 -0
  49. package/dist/Components/MediaGallery/MediaGallery.js +206 -0
  50. package/dist/Components/MediaGallery/MediaGalleryProps.d.ts +76 -0
  51. package/dist/Components/MediaGallery/MediaGalleryProps.js +20 -0
  52. package/dist/Components/MediaGallery/MediaLightbox.d.ts +4 -0
  53. package/dist/Components/MediaGallery/MediaLightbox.js +116 -0
  54. package/dist/Components/MediaGallery/MediaLightboxProps.d.ts +40 -0
  55. package/dist/Components/MediaGallery/MediaLightboxProps.js +15 -0
  56. package/dist/Components/MediaGallery/MediaThumb.d.ts +18 -0
  57. package/dist/Components/MediaGallery/MediaThumb.js +25 -0
  58. package/dist/Components/MediaGallery/glass.d.ts +31 -0
  59. package/dist/Components/MediaGallery/glass.js +47 -0
  60. package/dist/Components/MediaGallery/mediaGalleryModel.d.ts +22 -0
  61. package/dist/Components/MediaGallery/mediaGalleryModel.js +83 -0
  62. package/dist/Components/MediaGallery/motion.d.ts +5 -0
  63. package/dist/Components/MediaGallery/motion.js +12 -0
  64. package/dist/Components/MediaGallery/useMatchMedia.d.ts +2 -0
  65. package/dist/Components/MediaGallery/useMatchMedia.js +20 -0
  66. package/dist/Components/MultiSelect/MultiSelectProps.d.ts +1 -1
  67. package/dist/Components/OffersList/OffersList.d.ts +4 -0
  68. package/dist/Components/OffersList/OffersList.js +83 -0
  69. package/dist/Components/OffersList/OffersListProps.d.ts +34 -0
  70. package/dist/Components/OffersList/OffersListProps.js +2 -0
  71. package/dist/Components/OptionChip/OptionChip.d.ts +4 -0
  72. package/dist/Components/OptionChip/OptionChip.js +97 -0
  73. package/dist/Components/OptionChip/OptionChipProps.d.ts +33 -0
  74. package/dist/Components/OptionChip/OptionChipProps.js +2 -0
  75. package/dist/Components/OptionChip/optionInk.d.ts +12 -0
  76. package/dist/Components/OptionChip/optionInk.js +25 -0
  77. package/dist/Components/OrderStatusTimeline/OrderStatusTimeline.d.ts +4 -0
  78. package/dist/Components/OrderStatusTimeline/OrderStatusTimeline.js +57 -0
  79. package/dist/Components/OrderStatusTimeline/OrderStatusTimelineProps.d.ts +29 -0
  80. package/dist/Components/OrderStatusTimeline/OrderStatusTimelineProps.js +2 -0
  81. package/dist/Components/OrderSummary/OrderSummary.d.ts +4 -0
  82. package/dist/Components/OrderSummary/OrderSummary.js +63 -0
  83. package/dist/Components/OrderSummary/OrderSummaryProps.d.ts +53 -0
  84. package/dist/Components/OrderSummary/OrderSummaryProps.js +2 -0
  85. package/dist/Components/PaymentOption/PaymentOption.d.ts +4 -0
  86. package/dist/Components/PaymentOption/PaymentOption.js +24 -0
  87. package/dist/Components/PaymentOption/PaymentOptionGroup.d.ts +4 -0
  88. package/dist/Components/PaymentOption/PaymentOptionGroup.js +7 -0
  89. package/dist/Components/PaymentOption/PaymentOptionProps.d.ts +32 -0
  90. package/dist/Components/PaymentOption/PaymentOptionProps.js +2 -0
  91. package/dist/Components/PinInput/PinInputProps.d.ts +1 -1
  92. package/dist/Components/PincodeChecker/PincodeChecker.d.ts +4 -0
  93. package/dist/Components/PincodeChecker/PincodeChecker.js +175 -0
  94. package/dist/Components/PincodeChecker/PincodeCheckerProps.d.ts +57 -0
  95. package/dist/Components/PincodeChecker/PincodeCheckerProps.js +2 -0
  96. package/dist/Components/PriceBlock/PriceBlock.d.ts +4 -0
  97. package/dist/Components/PriceBlock/PriceBlock.js +41 -0
  98. package/dist/Components/PriceBlock/PriceBlockProps.d.ts +39 -0
  99. package/dist/Components/PriceBlock/PriceBlockProps.js +2 -0
  100. package/dist/Components/ProductBadges/ProductBadges.d.ts +4 -0
  101. package/dist/Components/ProductBadges/ProductBadges.js +61 -0
  102. package/dist/Components/ProductBadges/ProductBadgesProps.d.ts +18 -0
  103. package/dist/Components/ProductBadges/ProductBadgesProps.js +2 -0
  104. package/dist/Components/ProductCard/ProductCard.d.ts +3 -2
  105. package/dist/Components/ProductCard/ProductCard.js +103 -52
  106. package/dist/Components/ProductCard/ProductCardAction.d.ts +17 -0
  107. package/dist/Components/ProductCard/ProductCardAction.js +65 -0
  108. package/dist/Components/ProductCard/ProductCardGrid.d.ts +4 -0
  109. package/dist/Components/ProductCard/ProductCardGrid.js +20 -0
  110. package/dist/Components/ProductCard/ProductCardMedia.d.ts +18 -0
  111. package/dist/Components/ProductCard/ProductCardMedia.js +35 -0
  112. package/dist/Components/ProductCard/ProductCardProps.d.ts +138 -56
  113. package/dist/Components/ProductCard/ProductCardSkeleton.d.ts +4 -0
  114. package/dist/Components/ProductCard/ProductCardSkeleton.js +17 -0
  115. package/dist/Components/ProductCard/ProductCardSwatches.d.ts +15 -0
  116. package/dist/Components/ProductCard/ProductCardSwatches.js +37 -0
  117. package/dist/Components/ProductCard/QuickAddSheet.d.ts +4 -0
  118. package/dist/Components/ProductCard/QuickAddSheet.js +109 -0
  119. package/dist/Components/ProductCard/QuickAddSheetProps.d.ts +38 -0
  120. package/dist/Components/ProductCard/QuickAddSheetProps.js +2 -0
  121. package/dist/Components/ProductCard/cardLabels.d.ts +2 -0
  122. package/dist/Components/ProductCard/cardLabels.js +16 -0
  123. package/dist/Components/ProductCard/cardMetrics.d.ts +27 -0
  124. package/dist/Components/ProductCard/cardMetrics.js +55 -0
  125. package/dist/Components/ProductCard/productCardFixtures.d.ts +7 -0
  126. package/dist/Components/ProductCard/productCardFixtures.js +61 -0
  127. package/dist/Components/ProductCard/productCardModel.d.ts +22 -0
  128. package/dist/Components/ProductCard/productCardModel.js +79 -0
  129. package/dist/Components/ProductCard/useMinWidth.d.ts +2 -0
  130. package/dist/Components/ProductCard/useMinWidth.js +20 -0
  131. package/dist/Components/ProductDetails/ProductDetails.d.ts +3 -2
  132. package/dist/Components/ProductDetails/ProductDetails.js +209 -33
  133. package/dist/Components/ProductDetails/ProductDetailsProps.d.ts +143 -41
  134. package/dist/Components/ProductDetails/productDetailsModel.d.ts +14 -0
  135. package/dist/Components/ProductDetails/productDetailsModel.js +45 -0
  136. package/dist/Components/ProductDetails/useInViewport.d.ts +3 -0
  137. package/dist/Components/ProductDetails/useInViewport.js +18 -0
  138. package/dist/Components/QuantityStepper/QuantityStepper.d.ts +4 -0
  139. package/dist/Components/QuantityStepper/QuantityStepper.js +59 -0
  140. package/dist/Components/QuantityStepper/QuantityStepperProps.d.ts +24 -0
  141. package/dist/Components/QuantityStepper/QuantityStepperProps.js +2 -0
  142. package/dist/Components/Rating/Rating.d.ts +4 -0
  143. package/dist/Components/Rating/Rating.js +81 -0
  144. package/dist/Components/Rating/RatingProps.d.ts +27 -0
  145. package/dist/Components/Rating/RatingProps.js +2 -0
  146. package/dist/Components/ReviewList/ReviewList.d.ts +4 -0
  147. package/dist/Components/ReviewList/ReviewList.js +94 -0
  148. package/dist/Components/ReviewList/ReviewListProps.d.ts +68 -0
  149. package/dist/Components/ReviewList/ReviewListProps.js +2 -0
  150. package/dist/Components/ReviewSummary/ReviewSummary.d.ts +4 -0
  151. package/dist/Components/ReviewSummary/ReviewSummary.js +47 -0
  152. package/dist/Components/ReviewSummary/ReviewSummaryProps.d.ts +31 -0
  153. package/dist/Components/ReviewSummary/ReviewSummaryProps.js +2 -0
  154. package/dist/Components/Search/SearchProps.d.ts +1 -1
  155. package/dist/Components/SearchSelect/SearchSelectProps.d.ts +1 -1
  156. package/dist/Components/SegmentedControl/SegmentedControl.d.ts +1 -1
  157. package/dist/Components/SegmentedControl/SegmentedControl.js +17 -5
  158. package/dist/Components/SegmentedControl/SegmentedControlProps.d.ts +6 -0
  159. package/dist/Components/SegmentedControl/segmentedInk.d.ts +2 -0
  160. package/dist/Components/SegmentedControl/segmentedInk.js +4 -1
  161. package/dist/Components/SegmentedControl/useSlidingPill.d.ts +2 -0
  162. package/dist/Components/SegmentedControl/useSlidingPill.js +6 -1
  163. package/dist/Components/Select/SelectProps.d.ts +1 -1
  164. package/dist/Components/SelectSearch/SelectSearchProps.d.ts +1 -1
  165. package/dist/Components/SelectV2/SelectV2Props.d.ts +1 -1
  166. package/dist/Components/SideBar/SecondaryBar.js +13 -8
  167. package/dist/Components/SideBar/SideBarProps.d.ts +3 -1
  168. package/dist/Components/SideBar/components/MenuItemBox.js +47 -10
  169. package/dist/Components/SideBar/components/MenuPopoverContent.js +4 -3
  170. package/dist/Components/SpecTable/SpecTable.d.ts +4 -0
  171. package/dist/Components/SpecTable/SpecTable.js +39 -0
  172. package/dist/Components/SpecTable/SpecTableProps.d.ts +25 -0
  173. package/dist/Components/SpecTable/SpecTableProps.js +2 -0
  174. package/dist/Components/Spinner/Spinner.d.ts +1 -1
  175. package/dist/Components/Spinner/Spinner.js +2 -2
  176. package/dist/Components/Spinner/SpinnerProps.d.ts +2 -0
  177. package/dist/Components/StageProgress/StepperStage.js +2 -1
  178. package/dist/Components/StatCard/StatCard.d.ts +1 -1
  179. package/dist/Components/StatCard/StatCard.js +2 -2
  180. package/dist/Components/StatCard/StatCardProps.d.ts +4 -0
  181. package/dist/Components/StickyBuyBar/StickyBuyBar.d.ts +3 -0
  182. package/dist/Components/StickyBuyBar/StickyBuyBar.js +85 -0
  183. package/dist/Components/StickyBuyBar/StickyBuyBarProps.d.ts +54 -0
  184. package/dist/Components/StickyBuyBar/StickyBuyBarProps.js +2 -0
  185. package/dist/Components/StockStatus/StockStatus.d.ts +4 -0
  186. package/dist/Components/StockStatus/StockStatus.js +31 -0
  187. package/dist/Components/StockStatus/StockStatusProps.d.ts +14 -0
  188. package/dist/Components/StockStatus/StockStatusProps.js +2 -0
  189. package/dist/Components/Table/Table.js +2 -1
  190. package/dist/Components/Table/TableProps.d.ts +5 -2
  191. package/dist/Components/Table/columnLabel.d.ts +6 -0
  192. package/dist/Components/Table/columnLabel.js +27 -0
  193. package/dist/Components/Table/components/TableBody.js +5 -1
  194. package/dist/Components/Table/components/TableHeader.js +3 -2
  195. package/dist/Components/Table/filters/ActiveFilters.js +2 -1
  196. package/dist/Components/Table/filters/TableFilters.js +2 -1
  197. package/dist/Components/Table/hooks/useTable.js +3 -2
  198. package/dist/Components/Table/settings/ManageColumns.js +4 -3
  199. package/dist/Components/Table/settings/TableSettings.js +2 -1
  200. package/dist/Components/TrustBadges/TrustBadges.d.ts +4 -0
  201. package/dist/Components/TrustBadges/TrustBadges.js +24 -0
  202. package/dist/Components/TrustBadges/TrustBadgesProps.d.ts +20 -0
  203. package/dist/Components/TrustBadges/TrustBadgesProps.js +2 -0
  204. package/dist/Components/VariantSelector/VariantSelector.d.ts +4 -0
  205. package/dist/Components/VariantSelector/VariantSelector.js +123 -0
  206. package/dist/Components/VariantSelector/VariantSelectorProps.d.ts +27 -0
  207. package/dist/Components/VariantSelector/VariantSelectorProps.js +2 -0
  208. package/dist/Components/VariantSelector/variantSelection.d.ts +6 -0
  209. package/dist/Components/VariantSelector/variantSelection.js +25 -0
  210. package/dist/Components/WishlistToggle/WishlistToggle.d.ts +4 -0
  211. package/dist/Components/WishlistToggle/WishlistToggle.js +65 -0
  212. package/dist/Components/WishlistToggle/WishlistToggleProps.d.ts +19 -0
  213. package/dist/Components/WishlistToggle/WishlistToggleProps.js +2 -0
  214. package/dist/Theme/assertPalette.d.ts +1 -1
  215. package/dist/Theme/assertPalette.js +1 -1
  216. package/dist/Theme/tokens/brands/index.js +2 -0
  217. package/dist/Theme/tokens/brands/zinc/palette.dark.d.ts +1 -0
  218. package/dist/Theme/tokens/builders/buildDarkPalette.js +2 -0
  219. package/dist/Theme/tokens/builders/index.d.ts +1 -0
  220. package/dist/Theme/tokens/builders/index.js +1 -0
  221. package/dist/Theme/tokens/builders/rechartsTheme.d.ts +56 -0
  222. package/dist/Theme/tokens/builders/rechartsTheme.js +43 -0
  223. package/dist/Theme/tokens/builders/star.d.ts +3 -0
  224. package/dist/Theme/tokens/builders/star.js +8 -0
  225. package/dist/Theme/tokens/primitives/controlSizes.js +1 -1
  226. package/dist/Theme/tokens/types.d.ts +3 -1
  227. package/dist/Theme/useChartTheme.d.ts +4 -0
  228. package/dist/Theme/useChartTheme.js +12 -0
  229. package/dist/Utils/price.d.ts +16 -0
  230. package/dist/Utils/price.js +34 -0
  231. package/dist/esm/Components/AddressCard/AddressCard.js +20 -0
  232. package/dist/esm/Components/AddressCard/AddressCardGroup.js +5 -0
  233. package/dist/esm/Components/AddressCard/AddressCardProps.js +1 -0
  234. package/dist/esm/Components/BagBar/BagBar.js +27 -0
  235. package/dist/esm/Components/BagBar/BagBarProps.js +1 -0
  236. package/dist/esm/Components/CartItem/CartItem.js +55 -0
  237. package/dist/esm/Components/CartItem/CartItemProps.js +1 -0
  238. package/dist/esm/Components/CartItem/cartItemOptions.js +9 -0
  239. package/dist/esm/Components/CheckoutKit/selectable.js +112 -0
  240. package/dist/esm/Components/Commerce/commerceTypes.js +1 -0
  241. package/dist/esm/Components/Commerce/commerceVariants.js +41 -0
  242. package/dist/esm/Components/Commerce/index.js +2 -0
  243. package/dist/esm/Components/Commerce/useContainerWidth.js +21 -0
  244. package/dist/esm/Components/CouponField/CouponField.js +67 -0
  245. package/dist/esm/Components/CouponField/CouponFieldProps.js +1 -0
  246. package/dist/esm/Components/DatePicker/PickerPortal.js +21 -0
  247. package/dist/esm/Components/DatePicker/RangeDatePicker.js +34 -32
  248. package/dist/esm/Components/DatePicker/SingleDatePicker.js +16 -13
  249. package/dist/esm/Components/DatePicker/TimeOnlyPicker.js +6 -4
  250. package/dist/esm/Components/DetailSections/DetailSections.js +107 -0
  251. package/dist/esm/Components/DetailSections/DetailSectionsProps.js +1 -0
  252. package/dist/esm/Components/MediaGallery/MediaFrame.js +48 -0
  253. package/dist/esm/Components/MediaGallery/MediaGallery.js +201 -0
  254. package/dist/esm/Components/MediaGallery/MediaGalleryProps.js +17 -0
  255. package/dist/esm/Components/MediaGallery/MediaLightbox.js +78 -0
  256. package/dist/esm/Components/MediaGallery/MediaLightboxProps.js +12 -0
  257. package/dist/esm/Components/MediaGallery/MediaThumb.js +23 -0
  258. package/dist/esm/Components/MediaGallery/glass.js +42 -0
  259. package/dist/esm/Components/MediaGallery/mediaGalleryModel.js +71 -0
  260. package/dist/esm/Components/MediaGallery/motion.js +8 -0
  261. package/dist/esm/Components/MediaGallery/useMatchMedia.js +16 -0
  262. package/dist/esm/Components/OffersList/OffersList.js +81 -0
  263. package/dist/esm/Components/OffersList/OffersListProps.js +1 -0
  264. package/dist/esm/Components/OptionChip/OptionChip.js +95 -0
  265. package/dist/esm/Components/OptionChip/OptionChipProps.js +1 -0
  266. package/dist/esm/Components/OptionChip/optionInk.js +21 -0
  267. package/dist/esm/Components/OrderStatusTimeline/OrderStatusTimeline.js +55 -0
  268. package/dist/esm/Components/OrderStatusTimeline/OrderStatusTimelineProps.js +1 -0
  269. package/dist/esm/Components/OrderSummary/OrderSummary.js +58 -0
  270. package/dist/esm/Components/OrderSummary/OrderSummaryProps.js +1 -0
  271. package/dist/esm/Components/PaymentOption/PaymentOption.js +19 -0
  272. package/dist/esm/Components/PaymentOption/PaymentOptionGroup.js +5 -0
  273. package/dist/esm/Components/PaymentOption/PaymentOptionProps.js +1 -0
  274. package/dist/esm/Components/PincodeChecker/PincodeChecker.js +170 -0
  275. package/dist/esm/Components/PincodeChecker/PincodeCheckerProps.js +1 -0
  276. package/dist/esm/Components/PriceBlock/PriceBlock.js +39 -0
  277. package/dist/esm/Components/PriceBlock/PriceBlockProps.js +1 -0
  278. package/dist/esm/Components/ProductBadges/ProductBadges.js +59 -0
  279. package/dist/esm/Components/ProductBadges/ProductBadgesProps.js +1 -0
  280. package/dist/esm/Components/ProductCard/ProductCard.js +105 -54
  281. package/dist/esm/Components/ProductCard/ProductCardAction.js +60 -0
  282. package/dist/esm/Components/ProductCard/ProductCardGrid.js +18 -0
  283. package/dist/esm/Components/ProductCard/ProductCardMedia.js +33 -0
  284. package/dist/esm/Components/ProductCard/ProductCardSkeleton.js +12 -0
  285. package/dist/esm/Components/ProductCard/ProductCardSwatches.js +35 -0
  286. package/dist/esm/Components/ProductCard/QuickAddSheet.js +71 -0
  287. package/dist/esm/Components/ProductCard/QuickAddSheetProps.js +1 -0
  288. package/dist/esm/Components/ProductCard/cardLabels.js +13 -0
  289. package/dist/esm/Components/ProductCard/cardMetrics.js +52 -0
  290. package/dist/esm/Components/ProductCard/productCardFixtures.js +58 -0
  291. package/dist/esm/Components/ProductCard/productCardModel.js +65 -0
  292. package/dist/esm/Components/ProductCard/useMinWidth.js +16 -0
  293. package/dist/esm/Components/ProductDetails/ProductDetails.js +210 -34
  294. package/dist/esm/Components/ProductDetails/productDetailsModel.js +35 -0
  295. package/dist/esm/Components/ProductDetails/useInViewport.js +14 -0
  296. package/dist/esm/Components/QuantityStepper/QuantityStepper.js +57 -0
  297. package/dist/esm/Components/QuantityStepper/QuantityStepperProps.js +1 -0
  298. package/dist/esm/Components/Rating/Rating.js +79 -0
  299. package/dist/esm/Components/Rating/RatingProps.js +1 -0
  300. package/dist/esm/Components/ReviewList/ReviewList.js +89 -0
  301. package/dist/esm/Components/ReviewList/ReviewListProps.js +1 -0
  302. package/dist/esm/Components/ReviewSummary/ReviewSummary.js +42 -0
  303. package/dist/esm/Components/ReviewSummary/ReviewSummaryProps.js +1 -0
  304. package/dist/esm/Components/SegmentedControl/SegmentedControl.js +19 -7
  305. package/dist/esm/Components/SegmentedControl/segmentedInk.js +2 -0
  306. package/dist/esm/Components/SegmentedControl/useSlidingPill.js +6 -1
  307. package/dist/esm/Components/SideBar/SecondaryBar.js +14 -9
  308. package/dist/esm/Components/SideBar/components/MenuItemBox.js +14 -10
  309. package/dist/esm/Components/SideBar/components/MenuPopoverContent.js +4 -3
  310. package/dist/esm/Components/SpecTable/SpecTable.js +34 -0
  311. package/dist/esm/Components/SpecTable/SpecTableProps.js +1 -0
  312. package/dist/esm/Components/Spinner/Spinner.js +2 -2
  313. package/dist/esm/Components/StageProgress/StepperStage.js +2 -1
  314. package/dist/esm/Components/StatCard/StatCard.js +2 -2
  315. package/dist/esm/Components/StickyBuyBar/StickyBuyBar.js +80 -0
  316. package/dist/esm/Components/StickyBuyBar/StickyBuyBarProps.js +1 -0
  317. package/dist/esm/Components/StockStatus/StockStatus.js +29 -0
  318. package/dist/esm/Components/StockStatus/StockStatusProps.js +1 -0
  319. package/dist/esm/Components/Table/Table.js +2 -1
  320. package/dist/esm/Components/Table/columnLabel.js +21 -0
  321. package/dist/esm/Components/Table/components/TableBody.js +5 -1
  322. package/dist/esm/Components/Table/components/TableHeader.js +3 -2
  323. package/dist/esm/Components/Table/filters/ActiveFilters.js +2 -1
  324. package/dist/esm/Components/Table/filters/TableFilters.js +2 -1
  325. package/dist/esm/Components/Table/hooks/useTable.js +3 -2
  326. package/dist/esm/Components/Table/settings/ManageColumns.js +4 -3
  327. package/dist/esm/Components/Table/settings/TableSettings.js +2 -1
  328. package/dist/esm/Components/TrustBadges/TrustBadges.js +22 -0
  329. package/dist/esm/Components/TrustBadges/TrustBadgesProps.js +1 -0
  330. package/dist/esm/Components/VariantSelector/VariantSelector.js +118 -0
  331. package/dist/esm/Components/VariantSelector/VariantSelectorProps.js +1 -0
  332. package/dist/esm/Components/VariantSelector/variantSelection.js +19 -0
  333. package/dist/esm/Components/WishlistToggle/WishlistToggle.js +63 -0
  334. package/dist/esm/Components/WishlistToggle/WishlistToggleProps.js +1 -0
  335. package/dist/esm/Theme/assertPalette.js +1 -1
  336. package/dist/esm/Theme/tokens/brands/index.js +2 -0
  337. package/dist/esm/Theme/tokens/builders/buildDarkPalette.js +2 -0
  338. package/dist/esm/Theme/tokens/builders/index.js +1 -0
  339. package/dist/esm/Theme/tokens/builders/rechartsTheme.js +37 -0
  340. package/dist/esm/Theme/tokens/builders/star.js +4 -0
  341. package/dist/esm/Theme/tokens/primitives/controlSizes.js +1 -1
  342. package/dist/esm/Theme/useChartTheme.js +8 -0
  343. package/dist/esm/Utils/price.js +27 -0
  344. package/dist/esm/index.js +36 -0
  345. package/dist/index.d.ts +66 -0
  346. package/dist/index.js +86 -4
  347. package/package.json +1 -1
  348. package/dist/Components/ProductCard/ProductLabel.d.ts +0 -7
  349. package/dist/Components/ProductCard/ProductLabel.js +0 -20
  350. package/dist/Components/ProductCard/ProductPrice.d.ts +0 -10
  351. package/dist/Components/ProductCard/ProductPrice.js +0 -126
  352. package/dist/Components/ProductCard/ProductReview.d.ts +0 -8
  353. package/dist/Components/ProductCard/ProductReview.js +0 -30
  354. package/dist/Components/ProductCard/ProductTags.d.ts +0 -8
  355. package/dist/Components/ProductCard/ProductTags.js +0 -53
  356. package/dist/Components/ProductDetails/ProductDtlPrice.d.ts +0 -7
  357. package/dist/Components/ProductDetails/ProductDtlPrice.js +0 -24
  358. package/dist/Components/ProductDetails/ProductImageSlider.d.ts +0 -13
  359. package/dist/Components/ProductDetails/ProductImageSlider.js +0 -240
  360. package/dist/esm/Components/ProductCard/ProductLabel.js +0 -18
  361. package/dist/esm/Components/ProductCard/ProductPrice.js +0 -121
  362. package/dist/esm/Components/ProductCard/ProductReview.js +0 -28
  363. package/dist/esm/Components/ProductCard/ProductTags.js +0 -48
  364. package/dist/esm/Components/ProductDetails/ProductDtlPrice.js +0 -22
  365. package/dist/esm/Components/ProductDetails/ProductImageSlider.js +0 -204
@@ -0,0 +1,22 @@
1
+ import type { OptionAxis, ProductMedia, ProductVariant, VariantSelection } from "../Commerce/commerceTypes";
2
+ import type { ProductCardAction } from "./ProductCardProps";
3
+ export declare const DEFAULT_SWATCH_LIMIT = 3;
4
+ export declare const hasChoice: (axes: OptionAxis[]) => boolean;
5
+ /** The first colour-like axis whose values all carry a swatch; the card draws dots only for this one. */
6
+ export declare const swatchAxisOf: (axes: OptionAxis[]) => OptionAxis | undefined;
7
+ /** The one variant a product without a real choice resolves to, when there is one. */
8
+ export declare const soleVariantOf: (axes: OptionAxis[], variants: ProductVariant[]) => ProductVariant | undefined;
9
+ export declare const isSoldOut: (outOfStock: boolean | undefined, stock: number | undefined, variants: ProductVariant[]) => boolean;
10
+ /** Units left, only when a real count says the product is low; undefined otherwise. */
11
+ export declare const lowStockCount: (stock: number | undefined, sole: ProductVariant | undefined) => number | undefined;
12
+ export declare const deriveAction: (override: ProductCardAction | undefined, soldOut: boolean, axes: OptionAxis[]) => ProductCardAction;
13
+ /** Frames for the active swatch value: its mapped media, else the whole pool. */
14
+ export declare const framesFor: (media: ProductMedia[], mediaIdsByOption: Record<string, string[]> | undefined, axisId: string | undefined, valueId: string | undefined) => ProductMedia[];
15
+ /** Variants that share the picked colour, so the price range follows the dot. */
16
+ export declare const variantsFor: (variants: ProductVariant[], axisId: string | undefined, valueId: string | undefined) => ProductVariant[];
17
+ export declare const rangeOf: (variants: ProductVariant[]) => {
18
+ min: number;
19
+ max: number;
20
+ } | undefined;
21
+ export declare const valueSoldOut: (variants: ProductVariant[], axisId: string, valueId: string) => boolean;
22
+ export declare const firstMissingAxis: (axes: OptionAxis[], selection: VariantSelection) => OptionAxis | undefined;
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.firstMissingAxis = exports.valueSoldOut = exports.rangeOf = exports.variantsFor = exports.framesFor = exports.deriveAction = exports.lowStockCount = exports.isSoldOut = exports.soleVariantOf = exports.swatchAxisOf = exports.hasChoice = exports.DEFAULT_SWATCH_LIMIT = void 0;
4
+ const commerceVariants_1 = require("../Commerce/commerceVariants");
5
+ exports.DEFAULT_SWATCH_LIMIT = 3;
6
+ const hasChoice = (axes) => axes.some((axis) => axis.values.length > 1);
7
+ exports.hasChoice = hasChoice;
8
+ /** The first colour-like axis whose values all carry a swatch; the card draws dots only for this one. */
9
+ const swatchAxisOf = (axes) => axes.find((axis) => (axis.type === "swatch" || axis.type === "image-tile") &&
10
+ axis.values.length > 1 &&
11
+ axis.values.every((value) => value.swatch));
12
+ exports.swatchAxisOf = swatchAxisOf;
13
+ /** The one variant a product without a real choice resolves to, when there is one. */
14
+ const soleVariantOf = (axes, variants) => {
15
+ var _a;
16
+ if ((0, exports.hasChoice)(axes))
17
+ return undefined;
18
+ const selection = {};
19
+ axes.forEach((axis) => {
20
+ if (axis.values[0])
21
+ selection[axis.id] = axis.values[0].id;
22
+ });
23
+ return (_a = (0, commerceVariants_1.findVariant)(axes, variants, selection)) !== null && _a !== void 0 ? _a : (axes.length === 0 ? variants[0] : undefined);
24
+ };
25
+ exports.soleVariantOf = soleVariantOf;
26
+ const isSoldOut = (outOfStock, stock, variants) => {
27
+ if (outOfStock !== undefined)
28
+ return outOfStock;
29
+ if (stock !== undefined)
30
+ return stock <= 0;
31
+ return variants.length > 0 && variants.every((variant) => (0, commerceVariants_1.stockState)(variant) === "out-of-stock");
32
+ };
33
+ exports.isSoldOut = isSoldOut;
34
+ /** Units left, only when a real count says the product is low; undefined otherwise. */
35
+ const lowStockCount = (stock, sole) => {
36
+ const count = stock !== null && stock !== void 0 ? stock : sole === null || sole === void 0 ? void 0 : sole.stock;
37
+ if (count === undefined)
38
+ return undefined;
39
+ const state = (0, commerceVariants_1.stockState)({ stock: count, backorder: sole === null || sole === void 0 ? void 0 : sole.backorder });
40
+ return state === "low-stock" ? count : undefined;
41
+ };
42
+ exports.lowStockCount = lowStockCount;
43
+ const deriveAction = (override, soldOut, axes) => {
44
+ if (override)
45
+ return override;
46
+ if (soldOut)
47
+ return "notify";
48
+ return (0, exports.hasChoice)(axes) ? "options" : "add";
49
+ };
50
+ exports.deriveAction = deriveAction;
51
+ const optionKey = (axisId, valueId) => `${axisId}:${valueId}`;
52
+ /** Frames for the active swatch value: its mapped media, else the whole pool. */
53
+ const framesFor = (media, mediaIdsByOption, axisId, valueId) => {
54
+ if (!axisId || !valueId || !mediaIdsByOption)
55
+ return media;
56
+ const ids = mediaIdsByOption[optionKey(axisId, valueId)];
57
+ if (!ids)
58
+ return media;
59
+ const frames = ids.map((id) => media.find((item) => item.id === id)).filter((item) => !!item);
60
+ return frames.length > 0 ? frames : media;
61
+ };
62
+ exports.framesFor = framesFor;
63
+ /** Variants that share the picked colour, so the price range follows the dot. */
64
+ const variantsFor = (variants, axisId, valueId) => {
65
+ if (!axisId || !valueId)
66
+ return variants;
67
+ const scoped = variants.filter((variant) => variant.options[axisId] === valueId);
68
+ return scoped.length > 0 ? scoped : variants;
69
+ };
70
+ exports.variantsFor = variantsFor;
71
+ const rangeOf = (variants) => {
72
+ const range = (0, commerceVariants_1.priceRange)(variants);
73
+ return range && range.min !== range.max ? range : undefined;
74
+ };
75
+ exports.rangeOf = rangeOf;
76
+ const valueSoldOut = (variants, axisId, valueId) => variants.length > 0 && !(0, commerceVariants_1.isOptionAvailable)(variants, {}, axisId, valueId);
77
+ exports.valueSoldOut = valueSoldOut;
78
+ const firstMissingAxis = (axes, selection) => axes.find((axis) => selection[axis.id] === undefined);
79
+ exports.firstMissingAxis = firstMissingAxis;
@@ -0,0 +1,2 @@
1
+ /** `matches` for a media query; false where matchMedia does not exist (SSR, jsdom). */
2
+ export declare const useMinWidth: (query: string) => boolean;
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useMinWidth = void 0;
4
+ const react_1 = require("react");
5
+ const supported = () => typeof window !== "undefined" && typeof window.matchMedia === "function";
6
+ /** `matches` for a media query; false where matchMedia does not exist (SSR, jsdom). */
7
+ const useMinWidth = (query) => {
8
+ const [matches, setMatches] = (0, react_1.useState)(() => (supported() ? window.matchMedia(query).matches : false));
9
+ (0, react_1.useEffect)(() => {
10
+ if (!supported())
11
+ return undefined;
12
+ const list = window.matchMedia(query);
13
+ const onChange = () => setMatches(list.matches);
14
+ onChange();
15
+ list.addEventListener("change", onChange);
16
+ return () => list.removeEventListener("change", onChange);
17
+ }, [query]);
18
+ return matches;
19
+ };
20
+ exports.useMinWidth = useMinWidth;
@@ -1,3 +1,4 @@
1
- import { ProductDetailsProps } from "./ProductDetailsProps";
2
- declare const ProductDetails: ({ id, price, label, shortdesc, tags, images, batch, onAddToCart, onNotifyMe, onOptionChange, addToCart, goToCart, OnGoToCart, rating, reviews, notifyMe, isQtyEditable, displayRating, }: ProductDetailsProps) => import("react/jsx-runtime").JSX.Element;
1
+ import type { ProductDetailsProps } from "./ProductDetailsProps";
2
+ /** Product page that wires one selection to price, stock, gallery frames and the primary action; every region has a slot. */
3
+ declare const ProductDetails: ({ product, selection: selectionProp, defaultSelection, onSelectionChange, quantity: quantityProp, defaultQuantity, onQuantityChange, maxQuantity, onAddToBag, onBuyNow, onNotify, onGoToBag, addedDuration, wishlisted, defaultWishlisted, onWishlistChange, onShare, offers, offersProps, trustItems, pincode, sizeGuide, onGuideClick, reviews, ratingBreakdown, reviewsProps, onWriteReview, detailSectionsProps, care, breadcrumbs, layout, mediaSlot, metaSlot, infoSlot, belowFold, relatedSlot, isLoading, labels: labelOverrides, currency, locale, "data-testid": testId, }: ProductDetailsProps) => import("react/jsx-runtime").JSX.Element;
3
4
  export default ProductDetails;
@@ -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;