@evolve.ui/core-components 1.0.0 → 1.1.0

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 (559) hide show
  1. package/Checkbox.d.cts +1 -1
  2. package/Checkbox.d.mts +1 -1
  3. package/{DateInput-B8XQZPTx.d.cts → DateInput-CFxTZu3m.d.mts} +2 -2
  4. package/{DateInput-B8XQZPTx.d.cts.map → DateInput-CFxTZu3m.d.mts.map} +1 -1
  5. package/{DateInput-CfNmywqQ.d.mts → DateInput-DstMICTl.d.cts} +2 -2
  6. package/{DateInput-CfNmywqQ.d.mts.map → DateInput-DstMICTl.d.cts.map} +1 -1
  7. package/{FavoriteButton-CowOPoqo.d.cts → FavoriteButton-BGF-3dze.d.cts} +2 -2
  8. package/{FavoriteButton-BRY8FVpV.d.mts.map → FavoriteButton-BGF-3dze.d.cts.map} +1 -1
  9. package/{FavoriteButton-BRY8FVpV.d.mts → FavoriteButton-BZEGWrRo.d.mts} +2 -2
  10. package/{FavoriteButton-CowOPoqo.d.cts.map → FavoriteButton-BZEGWrRo.d.mts.map} +1 -1
  11. package/Input.d.cts +1 -1
  12. package/Input.d.mts +1 -1
  13. package/Radio.d.cts +1 -1
  14. package/Radio.d.mts +1 -1
  15. package/{TextInput-BhkeQZh4.d.cts → TextInput-B7lqQ1gh.d.cts} +3 -3
  16. package/{TextInput-BhkeQZh4.d.cts.map → TextInput-B7lqQ1gh.d.cts.map} +1 -1
  17. package/{TextInput-CWCeR18b.d.mts → TextInput-CxoT3np_.d.mts} +3 -3
  18. package/{TextInput-CWCeR18b.d.mts.map → TextInput-CxoT3np_.d.mts.map} +1 -1
  19. package/dateInput.d.cts +1 -1
  20. package/dateInput.d.mts +1 -1
  21. package/datePicker.d.cts +1 -1
  22. package/datePicker.d.mts +1 -1
  23. package/evolve-ui.entries.json +556 -0
  24. package/favoriteButton.d.cts +1 -1
  25. package/favoriteButton.d.mts +1 -1
  26. package/featureFlags/hooks.d.cts +1 -1
  27. package/featureFlags/hooks.d.mts +1 -1
  28. package/fileUpload/testUtils/mockFilesAndImages.d.cts +3 -3
  29. package/fileUpload/testUtils/mockFilesAndImages.d.cts.map +1 -1
  30. package/fileUpload/testUtils/mockFilesAndImages.d.mts +3 -3
  31. package/fileUpload/testUtils/mockFilesAndImages.d.mts.map +1 -1
  32. package/fileUpload/testUtils/testUtils.d.cts +1 -1
  33. package/fileUpload/testUtils/testUtils.d.cts.map +1 -1
  34. package/fileUpload/testUtils/testUtils.d.mts +1 -1
  35. package/fileUpload/testUtils/testUtils.d.mts.map +1 -1
  36. package/{index-BVb-FJDo.d.mts → index-BYPklw8m.d.mts} +2 -2
  37. package/{index-BVb-FJDo.d.mts.map → index-BYPklw8m.d.mts.map} +1 -1
  38. package/{index-3V0Y3AU3.d.mts → index-Bvn6svaT.d.cts} +2 -2
  39. package/{index-3V0Y3AU3.d.mts.map → index-Bvn6svaT.d.cts.map} +1 -1
  40. package/{index-Bu7c6X7O.d.mts → index-C2zPeUs9.d.mts} +5 -5
  41. package/{index-Bu7c6X7O.d.mts.map → index-C2zPeUs9.d.mts.map} +1 -1
  42. package/{index-BXz3rMMk.d.cts → index-Cmz2OD6x.d.cts} +2 -2
  43. package/{index-BXz3rMMk.d.cts.map → index-Cmz2OD6x.d.cts.map} +1 -1
  44. package/{index-kchg551L.d.cts → index-DsZAxqnF.d.mts} +2 -2
  45. package/{index-kchg551L.d.cts.map → index-DsZAxqnF.d.mts.map} +1 -1
  46. package/{index-BzN9RaXe.d.cts → index-QtMvgJcp.d.cts} +5 -5
  47. package/{index-BzN9RaXe.d.cts.map → index-QtMvgJcp.d.cts.map} +1 -1
  48. package/{index-dpfLYhgI.d.mts → index-hrztez-b.d.mts} +2 -2
  49. package/{index-DBYqF9Sr.d.cts.map → index-hrztez-b.d.mts.map} +1 -1
  50. package/{index-DBYqF9Sr.d.cts → index-o9dwzLLE.d.cts} +2 -2
  51. package/{index-dpfLYhgI.d.mts.map → index-o9dwzLLE.d.cts.map} +1 -1
  52. package/index.d.cts +7 -7
  53. package/index.d.mts +7 -7
  54. package/package.json +2 -2
  55. package/providers.d.cts +1 -1
  56. package/providers.d.mts +1 -1
  57. package/src/Accordion/Accordion.tsx +233 -0
  58. package/src/AddressDisplay/AddressDisplay.tsx +43 -0
  59. package/src/AddressDisplay/components/addressComponents.tsx +111 -0
  60. package/src/AddressDisplay/components/addressField.tsx +25 -0
  61. package/src/AddressDisplay/components/addressSection.tsx +8 -0
  62. package/src/AddressDisplay/components/getCountryValue.tsx +31 -0
  63. package/src/AddressDisplay/types.ts +26 -0
  64. package/src/AutomatedCarousel/AutomatedCarousel.tsx +163 -0
  65. package/src/AutomatedCarousel/automatedCarousel.types.ts +7 -0
  66. package/src/AutomatedCarousel/components/CarouselProgressBar/CarouselProgressBar.tsx +139 -0
  67. package/src/AutomatedCarousel/components/CarouselProgressBar/components/CarouselProgressBarUnit/CarouselProgressBarUnit.tsx +165 -0
  68. package/src/Badge/Badge.tsx +104 -0
  69. package/src/Badge/Badge.types.ts +58 -0
  70. package/src/Badge/ItemBadge.tsx +97 -0
  71. package/src/Badge/LiveStatusBadge.tsx +93 -0
  72. package/src/BannerNotification/BannerNotification.tsx +157 -0
  73. package/src/BannerNotification/components/BannerNotificationSkeleton.tsx +39 -0
  74. package/src/BannerNotification/components/CalloutIcon/BannerIcon.tsx +48 -0
  75. package/src/BannerNotification/utils/getRandomTooltipId.ts +3 -0
  76. package/src/BottomSheet/BottomSheet.tsx +476 -0
  77. package/src/BottomSheet/components/BottomSheetBackdrop/BottomSheetBackdrop.tsx +47 -0
  78. package/src/BottomSheet/components/BottomSheetContentArea/BottomSheetContentArea.tsx +92 -0
  79. package/src/BottomSheet/components/BottomSheetOverlay/BottomSheetOverlayTranslate3d.tsx +196 -0
  80. package/src/BottomSheet/components/SheetDescription/SheetDescription.tsx +22 -0
  81. package/src/BottomSheet/components/SheetTitle/SheetTitle.tsx +21 -0
  82. package/src/BottomSheet/components/index.tsx +5 -0
  83. package/src/BottomSheet/hooks/index.tsx +13 -0
  84. package/src/BottomSheet/hooks/useAriaHider.tsx +91 -0
  85. package/src/BottomSheet/hooks/useBottomSheetServices.tsx +224 -0
  86. package/src/BottomSheet/hooks/useDragHandler.tsx +282 -0
  87. package/src/BottomSheet/hooks/useFocusTrap.tsx +113 -0
  88. package/src/BottomSheet/hooks/useLayoutEffect.tsx +4 -0
  89. package/src/BottomSheet/hooks/useOptimizedResizeObserver.tsx +94 -0
  90. package/src/BottomSheet/hooks/useOptimizedScrollState.tsx +87 -0
  91. package/src/BottomSheet/hooks/useReady.tsx +34 -0
  92. package/src/BottomSheet/hooks/useReducedMotion.tsx +22 -0
  93. package/src/BottomSheet/hooks/useScrollLock.tsx +143 -0
  94. package/src/BottomSheet/hooks/useSnapPoints.tsx +355 -0
  95. package/src/BottomSheet/hooks/useSpring.tsx +47 -0
  96. package/src/BottomSheet/hooks/useSpringInterpolationsTranslate3d.tsx +101 -0
  97. package/src/BottomSheet/index.tsx +237 -0
  98. package/src/BottomSheet/state/atoms.ts +147 -0
  99. package/src/BottomSheet/state/useBottomSheetStateMachine.ts +246 -0
  100. package/src/BottomSheet/types.ts +172 -0
  101. package/src/BottomSheet/utils.ts +65 -0
  102. package/src/Breadcrumbs/Breadcrumbs.tsx +126 -0
  103. package/src/Button/Button.tsx +164 -0
  104. package/src/Button/Button.types.ts +80 -0
  105. package/src/Button/buttonColorClasses.ts +53 -0
  106. package/src/Callout/Callout.tsx +136 -0
  107. package/src/Callout/Callout.types.ts +29 -0
  108. package/src/Callout/components/CalloutIcon/CalloutIcon.tsx +56 -0
  109. package/src/Card/CardGrid.tsx +263 -0
  110. package/src/Card/SingleCard.tsx +22 -0
  111. package/src/Card/cardFactory.tsx +176 -0
  112. package/src/Card/components/createBadge.tsx +34 -0
  113. package/src/Card/components/createFavoriteButton.tsx +40 -0
  114. package/src/Card/components/createImage.tsx +64 -0
  115. package/src/Card/components/createInfo.tsx +84 -0
  116. package/src/Card/components/createName.tsx +63 -0
  117. package/src/Card/components/createPriceStatus.tsx +100 -0
  118. package/src/Card/components/types.ts +4 -0
  119. package/src/Card/hooks/useCardVisibilityTracking.ts +82 -0
  120. package/src/Card/sharedProps.ts +12 -0
  121. package/src/Card/types.ts +62 -0
  122. package/src/Carousel/Carousel.tsx +513 -0
  123. package/src/Carousel/Carousel.types.ts +43 -0
  124. package/src/Carousel/Carousel.utils.ts +63 -0
  125. package/src/Carousel/components/DotButton/DotButton.tsx +42 -0
  126. package/src/Carousel/components/NavigationButtons/NavigationButtons.tsx +77 -0
  127. package/src/Carousel/components/TitleSection/TitleSection.tsx +61 -0
  128. package/src/Carousel/components/TitleSection/components/SubHeaderLeft/SubHeaderLeft.tsx +53 -0
  129. package/src/Carousel/components/TitleSection/components/Title/Title.tsx +46 -0
  130. package/src/Carousel/index.ts +2 -0
  131. package/src/Carousel/testUtils.ts +10 -0
  132. package/src/Chips/Chip.tsx +153 -0
  133. package/src/Chips/ChipGroup.tsx +173 -0
  134. package/src/Chips/SuggestionChip.tsx +15 -0
  135. package/src/Chips/chipTypes.ts +113 -0
  136. package/src/Chips/index.ts +4 -0
  137. package/src/ChoiceListItem/Checkbox.tsx +69 -0
  138. package/src/ChoiceListItem/Radio.tsx +61 -0
  139. package/src/ChoiceListItem/choiceListItem.tsx +99 -0
  140. package/src/ChoiceListItem/common.tsx +148 -0
  141. package/src/ChoiceListItem/index.ts +3 -0
  142. package/src/Collapsible/Collapsible.tsx +58 -0
  143. package/src/Confetti/Confetti.tsx +270 -0
  144. package/src/Confetti/index.ts +2 -0
  145. package/src/ContentPager/ContentPager.tsx +189 -0
  146. package/src/ContentPager/components/Page.tsx +24 -0
  147. package/src/CookieConsent/components/CookieCategoryRow/CookieCategoryRow.tsx +30 -0
  148. package/src/CookieConsent/components/CookieConsent/CookieConsent.tsx +74 -0
  149. package/src/CookieConsent/components/CookieConsentBanner/CookieConsentBanner.tsx +51 -0
  150. package/src/CookieConsent/components/CookieConsentModal/CookieConsentModal.tsx +64 -0
  151. package/src/CookieConsent/hooks/useCookieConsent.ts +170 -0
  152. package/src/CookieConsent/hooks/useCookieConsentState.ts +142 -0
  153. package/src/CookieConsent/index.ts +16 -0
  154. package/src/CookieConsent/types/cookieConsent.types.ts +79 -0
  155. package/src/CookieConsent/types/index.ts +7 -0
  156. package/src/Countdown/Countdown.tsx +161 -0
  157. package/src/Countdown/Countdown.types.ts +4 -0
  158. package/src/Countdown/hooks/useGetCountdown.ts +103 -0
  159. package/src/DateTimeInput/dateInput/DateInput.tsx +199 -0
  160. package/src/DateTimeInput/datePicker/DatePicker.tsx +138 -0
  161. package/src/DateTimeInput/datePicker/components/calendar/Calendar.tsx +72 -0
  162. package/src/DateTimeInput/datePicker/index.ts +2 -0
  163. package/src/DateTimeInput/timeInput/TimeInput.tsx +128 -0
  164. package/src/DateTimeInput/timePicker/TimePicker.tsx +118 -0
  165. package/src/DateTimeInput/timePicker/components/TimePopover/AmPmSwitch.tsx +103 -0
  166. package/src/DateTimeInput/timePicker/components/TimePopover/TimeFieldInput.tsx +26 -0
  167. package/src/DateTimeInput/timePicker/components/TimePopover/TimePopover.tsx +84 -0
  168. package/src/DateTimeInput/timePicker/components/TimePopover/TimePopover.utils.ts +67 -0
  169. package/src/DateTimeInput/timePicker/components/TimePopover/TimePopoverActions.tsx +26 -0
  170. package/src/DateTimeInput/timePicker/index.ts +2 -0
  171. package/src/DateTimeInput/utils/getDisplayDate.ts +15 -0
  172. package/src/DateTimeInput/utils/getDisplayTime.ts +15 -0
  173. package/src/DateTimeInput/utils/index.ts +2 -0
  174. package/src/DateTimeInput/utils/parseTimeValue.ts +54 -0
  175. package/src/Drawer/Drawer.tsx +446 -0
  176. package/src/Drawer/atoms.ts +4 -0
  177. package/src/Drawer/components/DialogActions/DialogActions.tsx +33 -0
  178. package/src/Drawer/components/DialogContent/DialogContent.tsx +80 -0
  179. package/src/Drawer/components/DialogHeader/DialogHeader.tsx +68 -0
  180. package/src/EducationalPopover/EducationalPopover.tsx +174 -0
  181. package/src/FavoriteButton/FavoriteButton.tsx +64 -0
  182. package/src/FavoriteButton/components/IconOnlyFavoriteButton/IconOnlyFavoriteButton.tsx +80 -0
  183. package/src/FavoriteButton/components/LabeledAnimatedFavoriteButton/LabeledAnimatedFavoriteButton.tsx +179 -0
  184. package/src/FavoriteButton/components/LabeledFavoriteButton/LabeledFavoriteButton.tsx +71 -0
  185. package/src/FavoriteButton/components/SmallHeartStraightIcon/SmallHeartStraightIcon.tsx +14 -0
  186. package/src/FavoriteButton/hooks/useFavoriteButtonState.ts +30 -0
  187. package/src/FavoriteButton/index.ts +2 -0
  188. package/src/FavoriteButton/types/favoriteButton.ts +87 -0
  189. package/src/FeatureFlags/devTools/FeatureFlagDevToolsUI.tsx +226 -0
  190. package/src/FeatureFlags/devTools/getFeatureFlagCookieOverrides.ts +30 -0
  191. package/src/FeatureFlags/devTools/utils/cookies.ts +169 -0
  192. package/src/FeatureFlags/hooks/index.ts +2 -0
  193. package/src/FeatureFlags/hooks/useFeatureFlag.tsx +19 -0
  194. package/src/FeatureFlags/hooks/useFeatureFlags.tsx +15 -0
  195. package/src/FileUpload/components/FileCard/FileCard.tsx +50 -0
  196. package/src/FileUpload/components/FileDropzone/FileDropzone.tsx +221 -0
  197. package/src/FileUpload/components/FileDropzone/components/DropzoneContent/DropzoneContent.tsx +28 -0
  198. package/src/FileUpload/components/FileDropzone/components/DropzoneContent/DropzoneText.tsx +81 -0
  199. package/src/FileUpload/components/FileDropzone/components/FileDropzoneDebugger/FileDropzoneDebugger.tsx +40 -0
  200. package/src/FileUpload/components/FileDropzone/components/FileDropzoneDebugger/FileRejectionsDisplay.tsx +110 -0
  201. package/src/FileUpload/components/FileDropzoneOverlay/FileDropzoneOverlay.tsx +183 -0
  202. package/src/FileUpload/components/FileDropzoneOverlay/components/OverlayDropzoneContent.tsx +146 -0
  203. package/src/FileUpload/components/FileDropzoneOverlay/components/OverlayDropzoneDragText.tsx +42 -0
  204. package/src/FileUpload/components/FileDropzoneOverlay/styles.ts +79 -0
  205. package/src/FileUpload/components/FilePreviewList/FilePreviewList.tsx +251 -0
  206. package/src/FileUpload/components/FilePreviewList/virtualizerComponents/FilePreviewVirtualizedList/FilePreviewVirtualizedList.tsx +88 -0
  207. package/src/FileUpload/components/FileUpload/FileUpload.tsx +63 -0
  208. package/src/FileUpload/components/FileUploadCanvas/FileUploadCanvas.tsx +125 -0
  209. package/src/FileUpload/components/GridFileCard/GridFileCard.tsx +364 -0
  210. package/src/FileUpload/components/GridFileCard/utils/sortable.ts +48 -0
  211. package/src/FileUpload/components/ListFileCard/ListFileCard.tsx +259 -0
  212. package/src/FileUpload/components/types.ts +78 -0
  213. package/src/FileUpload/hooks/filePreview/useImageFilePreviewUrl.ts +62 -0
  214. package/src/FileUpload/hooks/index.ts +11 -0
  215. package/src/FileUpload/hooks/upload/useHandleDragEnter/useHandleDragEnter.ts +154 -0
  216. package/src/FileUpload/hooks/upload/useHandleDrop/createFileRejectionHelpers.ts +273 -0
  217. package/src/FileUpload/hooks/upload/useHandleDrop/useHandleDrop.ts +153 -0
  218. package/src/FileUpload/hooks/upload/useUploadAvailability/useUploadAvailability.ts +44 -0
  219. package/src/FileUpload/hooks/validation/createDropzoneValidator.ts +41 -0
  220. package/src/FileUpload/hooks/validation/useFileValidation.ts +25 -0
  221. package/src/FileUpload/hooks/validation/useFileValidationLogic.ts +107 -0
  222. package/src/FileUpload/hooks/validation/useValidationMessages.ts +92 -0
  223. package/src/FileUpload/hooks/validation/useValidationState.ts +171 -0
  224. package/src/FileUpload/index.ts +57 -0
  225. package/src/FileUpload/providers/FileUploadProvider.tsx +219 -0
  226. package/src/FileUpload/providers/UploadValidationProvider.tsx +159 -0
  227. package/src/FileUpload/testUtils/mockFilesAndImages.ts +64 -0
  228. package/src/FileUpload/testUtils/testUtils.ts +111 -0
  229. package/src/FileUpload/types/commonTypes.ts +267 -0
  230. package/src/FileUpload/types/index.ts +31 -0
  231. package/src/FileUpload/types/sharedTypes.ts +159 -0
  232. package/src/FileUpload/utils/constants.ts +79 -0
  233. package/src/FileUpload/utils/createMessageContext.ts +180 -0
  234. package/src/FileUpload/utils/getFileExtensionsFromAcceptedTypes.ts +73 -0
  235. package/src/FileUpload/utils/getFilePluralizationText.ts +68 -0
  236. package/src/FileUpload/utils/getMimeTypes.ts +26 -0
  237. package/src/FileUpload/utils/messageUtils.ts +41 -0
  238. package/src/FileUpload/utils/styles.ts +68 -0
  239. package/src/FormLabel/FormLabel.tsx +212 -0
  240. package/src/IconButton/IconButton.tsx +154 -0
  241. package/src/Icons/CreditCardIcon/CreditCardIcon.tsx +73 -0
  242. package/src/Icons/CreditCardIcon/cardIcons.tsx +270 -0
  243. package/src/Icons/IconBase.tsx +133 -0
  244. package/src/Icons/anyIcon.ts +3 -0
  245. package/src/Icons/generatedIcons/Archive.tsx +48 -0
  246. package/src/Icons/generatedIcons/ArrowClockwise.tsx +48 -0
  247. package/src/Icons/generatedIcons/ArrowDown.tsx +48 -0
  248. package/src/Icons/generatedIcons/ArrowLeft.tsx +48 -0
  249. package/src/Icons/generatedIcons/ArrowRight.tsx +48 -0
  250. package/src/Icons/generatedIcons/ArrowSquareOut.tsx +51 -0
  251. package/src/Icons/generatedIcons/ArrowSquareRight.tsx +51 -0
  252. package/src/Icons/generatedIcons/ArrowUp.tsx +48 -0
  253. package/src/Icons/generatedIcons/ArrowsCounterClockwise.tsx +48 -0
  254. package/src/Icons/generatedIcons/ArrowsLeftRight.tsx +48 -0
  255. package/src/Icons/generatedIcons/ArrowsOutCardinal.tsx +48 -0
  256. package/src/Icons/generatedIcons/Bank.tsx +48 -0
  257. package/src/Icons/generatedIcons/Bell.tsx +51 -0
  258. package/src/Icons/generatedIcons/BookBookmark.tsx +51 -0
  259. package/src/Icons/generatedIcons/BookmarksSimple.tsx +51 -0
  260. package/src/Icons/generatedIcons/Broadcast.tsx +48 -0
  261. package/src/Icons/generatedIcons/CalendarBlank.tsx +48 -0
  262. package/src/Icons/generatedIcons/CalendarStar.tsx +51 -0
  263. package/src/Icons/generatedIcons/Camera.tsx +51 -0
  264. package/src/Icons/generatedIcons/CaretDown.tsx +48 -0
  265. package/src/Icons/generatedIcons/CaretLeft.tsx +48 -0
  266. package/src/Icons/generatedIcons/CaretRight.tsx +48 -0
  267. package/src/Icons/generatedIcons/CaretUp.tsx +48 -0
  268. package/src/Icons/generatedIcons/Certificate.tsx +51 -0
  269. package/src/Icons/generatedIcons/ChartBar.tsx +48 -0
  270. package/src/Icons/generatedIcons/Check.tsx +51 -0
  271. package/src/Icons/generatedIcons/CheckCircle.tsx +48 -0
  272. package/src/Icons/generatedIcons/CirclesFour.tsx +51 -0
  273. package/src/Icons/generatedIcons/Clock.tsx +48 -0
  274. package/src/Icons/generatedIcons/ClockCountdown.tsx +48 -0
  275. package/src/Icons/generatedIcons/Close.tsx +51 -0
  276. package/src/Icons/generatedIcons/CloudArrowUp.tsx +51 -0
  277. package/src/Icons/generatedIcons/CloudWarning.tsx +51 -0
  278. package/src/Icons/generatedIcons/Code.tsx +48 -0
  279. package/src/Icons/generatedIcons/Compass.tsx +51 -0
  280. package/src/Icons/generatedIcons/Confetti.tsx +51 -0
  281. package/src/Icons/generatedIcons/Copy.tsx +48 -0
  282. package/src/Icons/generatedIcons/CornersOut.tsx +48 -0
  283. package/src/Icons/generatedIcons/CreditCard.tsx +48 -0
  284. package/src/Icons/generatedIcons/Crown.tsx +51 -0
  285. package/src/Icons/generatedIcons/CrownSimple.tsx +51 -0
  286. package/src/Icons/generatedIcons/CurrencyCircleDollar.tsx +48 -0
  287. package/src/Icons/generatedIcons/CurrencyDollarSimple.tsx +51 -0
  288. package/src/Icons/generatedIcons/Desktop.tsx +51 -0
  289. package/src/Icons/generatedIcons/Detective.tsx +51 -0
  290. package/src/Icons/generatedIcons/DotOutline.tsx +46 -0
  291. package/src/Icons/generatedIcons/DotsSixVertical.tsx +51 -0
  292. package/src/Icons/generatedIcons/DotsThreeOutline.tsx +51 -0
  293. package/src/Icons/generatedIcons/DotsThreeOutlineVertical.tsx +51 -0
  294. package/src/Icons/generatedIcons/DownloadSimple.tsx +51 -0
  295. package/src/Icons/generatedIcons/EnvelopeSimple.tsx +48 -0
  296. package/src/Icons/generatedIcons/Eraser.tsx +51 -0
  297. package/src/Icons/generatedIcons/Eye.tsx +51 -0
  298. package/src/Icons/generatedIcons/EyeSlash.tsx +51 -0
  299. package/src/Icons/generatedIcons/FacebookLogo.tsx +48 -0
  300. package/src/Icons/generatedIcons/FileArchive.tsx +48 -0
  301. package/src/Icons/generatedIcons/FileArrowDown.tsx +48 -0
  302. package/src/Icons/generatedIcons/FileCsv.tsx +48 -0
  303. package/src/Icons/generatedIcons/FilePdf.tsx +48 -0
  304. package/src/Icons/generatedIcons/FileText.tsx +48 -0
  305. package/src/Icons/generatedIcons/Files.tsx +51 -0
  306. package/src/Icons/generatedIcons/Fire.tsx +51 -0
  307. package/src/Icons/generatedIcons/Flag.tsx +51 -0
  308. package/src/Icons/generatedIcons/FlagBannerFold.tsx +48 -0
  309. package/src/Icons/generatedIcons/FloppyDisk.tsx +51 -0
  310. package/src/Icons/generatedIcons/Gauge.tsx +51 -0
  311. package/src/Icons/generatedIcons/Gavel.tsx +51 -0
  312. package/src/Icons/generatedIcons/Gear.tsx +51 -0
  313. package/src/Icons/generatedIcons/GlobeHemisphereWest.tsx +51 -0
  314. package/src/Icons/generatedIcons/GoogleLogo.tsx +48 -0
  315. package/src/Icons/generatedIcons/GridNine.tsx +51 -0
  316. package/src/Icons/generatedIcons/HandCoins.tsx +51 -0
  317. package/src/Icons/generatedIcons/HandbagSimple.tsx +51 -0
  318. package/src/Icons/generatedIcons/Headset.tsx +51 -0
  319. package/src/Icons/generatedIcons/HeartStraight.tsx +51 -0
  320. package/src/Icons/generatedIcons/HourglassLow.tsx +48 -0
  321. package/src/Icons/generatedIcons/House.tsx +51 -0
  322. package/src/Icons/generatedIcons/Image.tsx +51 -0
  323. package/src/Icons/generatedIcons/ImageSquare.tsx +51 -0
  324. package/src/Icons/generatedIcons/ImagesSquare.tsx +51 -0
  325. package/src/Icons/generatedIcons/Info.tsx +48 -0
  326. package/src/Icons/generatedIcons/InstagramLogo.tsx +51 -0
  327. package/src/Icons/generatedIcons/Lightning.tsx +48 -0
  328. package/src/Icons/generatedIcons/Link.tsx +51 -0
  329. package/src/Icons/generatedIcons/LinkedinLogo.tsx +51 -0
  330. package/src/Icons/generatedIcons/List.tsx +48 -0
  331. package/src/Icons/generatedIcons/Lock.tsx +51 -0
  332. package/src/Icons/generatedIcons/LockOpen.tsx +51 -0
  333. package/src/Icons/generatedIcons/MagnifyingGlass.tsx +48 -0
  334. package/src/Icons/generatedIcons/MapPin.tsx +51 -0
  335. package/src/Icons/generatedIcons/MapPinSimpleArea.tsx +48 -0
  336. package/src/Icons/generatedIcons/Medal.tsx +48 -0
  337. package/src/Icons/generatedIcons/Megaphone.tsx +48 -0
  338. package/src/Icons/generatedIcons/Minus.tsx +45 -0
  339. package/src/Icons/generatedIcons/Money.tsx +51 -0
  340. package/src/Icons/generatedIcons/Notches.tsx +48 -0
  341. package/src/Icons/generatedIcons/NotePencil.tsx +48 -0
  342. package/src/Icons/generatedIcons/Package.tsx +51 -0
  343. package/src/Icons/generatedIcons/PaintBrush.tsx +51 -0
  344. package/src/Icons/generatedIcons/PaperPlaneTilt.tsx +51 -0
  345. package/src/Icons/generatedIcons/Paperclip.tsx +51 -0
  346. package/src/Icons/generatedIcons/Pause.tsx +51 -0
  347. package/src/Icons/generatedIcons/PencilLine.tsx +51 -0
  348. package/src/Icons/generatedIcons/PencilRuler.tsx +51 -0
  349. package/src/Icons/generatedIcons/PencilSimple.tsx +51 -0
  350. package/src/Icons/generatedIcons/Phone.tsx +51 -0
  351. package/src/Icons/generatedIcons/PinterestLogo.tsx +51 -0
  352. package/src/Icons/generatedIcons/Play.tsx +51 -0
  353. package/src/Icons/generatedIcons/Plus.tsx +51 -0
  354. package/src/Icons/generatedIcons/PlusCircle.tsx +48 -0
  355. package/src/Icons/generatedIcons/Printer.tsx +51 -0
  356. package/src/Icons/generatedIcons/Question.tsx +48 -0
  357. package/src/Icons/generatedIcons/Receipt.tsx +51 -0
  358. package/src/Icons/generatedIcons/Rows.tsx +51 -0
  359. package/src/Icons/generatedIcons/SealCheck.tsx +51 -0
  360. package/src/Icons/generatedIcons/SelectionSlash.tsx +48 -0
  361. package/src/Icons/generatedIcons/ShareNetwork.tsx +51 -0
  362. package/src/Icons/generatedIcons/ShieldCheck.tsx +51 -0
  363. package/src/Icons/generatedIcons/ShieldStar.tsx +51 -0
  364. package/src/Icons/generatedIcons/ShoppingCart.tsx +48 -0
  365. package/src/Icons/generatedIcons/ShuffleAngular.tsx +48 -0
  366. package/src/Icons/generatedIcons/SidebarSimple.tsx +48 -0
  367. package/src/Icons/generatedIcons/SlidersHorizontal.tsx +51 -0
  368. package/src/Icons/generatedIcons/Smiley.tsx +48 -0
  369. package/src/Icons/generatedIcons/Sparkle.tsx +51 -0
  370. package/src/Icons/generatedIcons/SpinnerGap.tsx +48 -0
  371. package/src/Icons/generatedIcons/StackPlus.tsx +48 -0
  372. package/src/Icons/generatedIcons/Star.tsx +51 -0
  373. package/src/Icons/generatedIcons/Storefront.tsx +51 -0
  374. package/src/Icons/generatedIcons/Swap.tsx +51 -0
  375. package/src/Icons/generatedIcons/Tag.tsx +51 -0
  376. package/src/Icons/generatedIcons/ThumbsDown.tsx +48 -0
  377. package/src/Icons/generatedIcons/ThumbsUp.tsx +48 -0
  378. package/src/Icons/generatedIcons/Toolbox.tsx +48 -0
  379. package/src/Icons/generatedIcons/Trash.tsx +48 -0
  380. package/src/Icons/generatedIcons/TrendUp.tsx +48 -0
  381. package/src/Icons/generatedIcons/Trophy.tsx +51 -0
  382. package/src/Icons/generatedIcons/Truck.tsx +51 -0
  383. package/src/Icons/generatedIcons/UploadSimple.tsx +51 -0
  384. package/src/Icons/generatedIcons/User.tsx +48 -0
  385. package/src/Icons/generatedIcons/Users.tsx +48 -0
  386. package/src/Icons/generatedIcons/UsersThree.tsx +51 -0
  387. package/src/Icons/generatedIcons/VideoCamera.tsx +51 -0
  388. package/src/Icons/generatedIcons/Warning.tsx +51 -0
  389. package/src/Icons/generatedIcons/WarningCircle.tsx +48 -0
  390. package/src/Icons/generatedIcons/WifiHigh.tsx +51 -0
  391. package/src/Icons/generatedIcons/XCircle.tsx +48 -0
  392. package/src/Icons/generatedIcons/XLogo.tsx +48 -0
  393. package/src/Icons/generatedIcons/YoutubeLogo.tsx +51 -0
  394. package/src/Icons/importedIcons.ts +152 -0
  395. package/src/Icons/index.ts +149 -0
  396. package/src/Icons/socialIcons/appleSocialIcon.tsx +50 -0
  397. package/src/Icons/socialIcons/facebookSocialIcon.tsx +41 -0
  398. package/src/Icons/socialIcons/googleSocialIcon.tsx +134 -0
  399. package/src/ImageCluster/ImageCluster.tsx +125 -0
  400. package/src/ImageSlider/ImageSlider.tsx +582 -0
  401. package/src/ImageSlider/ImageSlider.types.ts +90 -0
  402. package/src/ImageSlider/components/IndexIndicator/IndexIndicator.tsx +21 -0
  403. package/src/ImageSlider/components/NavigationButtons/NavigationButtons.tsx +113 -0
  404. package/src/ImageSlider/components/ResponsiveImage/ResponsiveImage.tsx +114 -0
  405. package/src/ImageSlider/components/ResponsiveImage/index.ts +1 -0
  406. package/src/ImageSlider/components/Thumbnails/Thumbnails.tsx +184 -0
  407. package/src/ImageSlider/constants.ts +59 -0
  408. package/src/ImageSlider/hooks/index.ts +3 -0
  409. package/src/ImageSlider/hooks/useImageSlider.ts +57 -0
  410. package/src/ImageSlider/hooks/useImageSliderNavigation.ts +133 -0
  411. package/src/ImageSlider/hooks/useImageSliderScrollHandler.ts +171 -0
  412. package/src/ImageSlider/index.ts +3 -0
  413. package/src/ImageSlider/utils/imageOptimization.ts +97 -0
  414. package/src/ImageSlider/utils/index.ts +1 -0
  415. package/src/InlineNotification/InlineNotification.tsx +95 -0
  416. package/src/JumpMenu/JumpMenu.tsx +395 -0
  417. package/src/JumpMenu/components/JumpMenuItem/JumpMenuItem.tsx +62 -0
  418. package/src/JumpMenu/hooks/useContainerTracking.ts +171 -0
  419. package/src/JumpMenu/hooks/useIntersectionObserver.ts +77 -0
  420. package/src/JumpMenu/hooks/useKeyboardNavigation.ts +102 -0
  421. package/src/JumpMenu/hooks/useResizeObserver.ts +53 -0
  422. package/src/JumpMenu/hooks/useSectionObserver.ts +102 -0
  423. package/src/JumpMenu/index.ts +2 -0
  424. package/src/JumpMenu/types/index.ts +19 -0
  425. package/src/Loading/Loading.tsx +39 -0
  426. package/src/Loading/components/LoadingDot/LoadingDot.tsx +16 -0
  427. package/src/LoadingSpinner/LoadingSpinner.tsx +20 -0
  428. package/src/Menu/Menu.tsx +372 -0
  429. package/src/Menu/components/MenuDivider/MenuDivider.tsx +5 -0
  430. package/src/Menu/components/MenuItem/MenuItem.tsx +298 -0
  431. package/src/Menu/context/menuContext.tsx +20 -0
  432. package/src/Menu/hooks/useMenu.tsx +18 -0
  433. package/src/Menu/index.ts +3 -0
  434. package/src/Modal/ComposableModal.tsx +313 -0
  435. package/src/Modal/Modal.tsx +231 -0
  436. package/src/Modal/components/BackButton/BackButton.tsx +43 -0
  437. package/src/Modal/components/Backdrop/Backdrop.tsx +62 -0
  438. package/src/Modal/components/CloseButton/CloseButton.tsx +55 -0
  439. package/src/Modal/components/ModalActions/ModalActions.tsx +135 -0
  440. package/src/Modal/components/ModalContent/ModalContent.tsx +163 -0
  441. package/src/Modal/components/ModalHeader/ModalHeader.tsx +84 -0
  442. package/src/Modal/components/ModalHeader/hooks/useHeaderAnimation.tsx +49 -0
  443. package/src/Modal/components/ModalProgressSteps/ModalProgressSteps.tsx +26 -0
  444. package/src/Modal/components/ModalSubTitle/ModalSubTitle.tsx +29 -0
  445. package/src/Modal/components/ModalTitle/ModalTitle.tsx +22 -0
  446. package/src/Modal/components/PreventModalScroll/PreventModalScroll.tsx +106 -0
  447. package/src/Modal/components/index.ts +12 -0
  448. package/src/Modal/context.ts +33 -0
  449. package/src/Modal/hooks/useCloseModal.ts +133 -0
  450. package/src/NotificationBadge/NotificationBadge.tsx +34 -0
  451. package/src/Pagination/AdvancedPagination.tsx +48 -0
  452. package/src/Pagination/Pagination.tsx +216 -0
  453. package/src/Pagination/components/AdvancedPaginator/AdvancedPaginator.tsx +52 -0
  454. package/src/Pagination/components/AdvancedPaginator/components/PageSelect/PageSelect.tsx +43 -0
  455. package/src/Pagination/components/ItemCountDisplay/ItemCountDisplay.tsx +32 -0
  456. package/src/Pagination/components/ItemCountSelect/ItemCountSelect.tsx +33 -0
  457. package/src/Pagination/index.tsx +3 -0
  458. package/src/Pagination/paginationProvider.tsx +234 -0
  459. package/src/Pagination/utils.tsx +36 -0
  460. package/src/PhoneInput/PhoneInput.tsx +509 -0
  461. package/src/PhoneInput/useDropdownLogic.tsx +163 -0
  462. package/src/ProgressCircle/ProgressCircle.tsx +246 -0
  463. package/src/ProgressCircle/hooks/useProgressStatusTransitions.ts +49 -0
  464. package/src/ProgressCircle/utils/progressCircle.constants.ts +27 -0
  465. package/src/ProgressSteps/ProgressSteps.tsx +160 -0
  466. package/src/SaveConfetti/SaveConfetti.tsx +277 -0
  467. package/src/SaveConfetti/index.ts +2 -0
  468. package/src/SearchInput/SearchInput.tsx +236 -0
  469. package/src/SegmentedControl/SegmentedControl.tsx +111 -0
  470. package/src/SegmentedControl/SegmentedControlGroup.tsx +94 -0
  471. package/src/SegmentedControl/index.ts +4 -0
  472. package/src/Select/Select.tsx +154 -0
  473. package/src/Select/SelectAsync.tsx +13 -0
  474. package/src/Select/SelectAsyncCreatable.tsx +14 -0
  475. package/src/Select/SelectCreatable.tsx +12 -0
  476. package/src/Select/reexportedComponents.tsx +5 -0
  477. package/src/Select/selectComponents.tsx +306 -0
  478. package/src/Skeleton/Skeleton.tsx +13 -0
  479. package/src/SplitButton/SplitButton.tsx +298 -0
  480. package/src/SplitButton/SplitButtonTrigger.tsx +55 -0
  481. package/src/StarRating/StarRating.tsx +165 -0
  482. package/src/StarRating/components/StarComponent/StarComponent.tsx +44 -0
  483. package/src/Table/Table.tsx +474 -0
  484. package/src/Table/components/TableHeader/TableHeader.tsx +166 -0
  485. package/src/Table/components/TablePagination/TablePagination.tsx +18 -0
  486. package/src/Table/components/TablePagination/components/ItemCountDisplay/ItemCountDisplay.tsx +17 -0
  487. package/src/Table/components/TablePagination/components/ItemCountSelect/ItemCountSelect.tsx +31 -0
  488. package/src/Table/components/TablePagination/components/TablePaginator/TablePaginator.tsx +37 -0
  489. package/src/Table/components/TablePagination/components/TablePaginator/components/PageSelect/PageSelect.tsx +32 -0
  490. package/src/Table/components/TableRow/TableRows.tsx +147 -0
  491. package/src/Table/components/TableRow/components/TableRowCell/TableRowCell.tsx +49 -0
  492. package/src/Table/components/TableShadow/TableShadow.tsx +46 -0
  493. package/src/Table/index.ts +2 -0
  494. package/src/Table/sharedState.ts +30 -0
  495. package/src/Table/sharedStyles.ts +1 -0
  496. package/src/Table/types.ts +55 -0
  497. package/src/Tabs/Tabs.tsx +358 -0
  498. package/src/TextArea/TextArea.tsx +157 -0
  499. package/src/TextInput/TextInput.tsx +173 -0
  500. package/src/Toast/Toast.tsx +64 -0
  501. package/src/Toast/components/ToastContainer/ToastContainer.tsx +48 -0
  502. package/src/Toast/index.ts +2 -0
  503. package/src/Toast/types/role.ts +1 -0
  504. package/src/Toast/utils/getIcon.tsx +41 -0
  505. package/src/ToggleSwitch/ToggleSwitch.tsx +188 -0
  506. package/src/Tooltip/InfoIconTooltip.tsx +47 -0
  507. package/src/Tooltip/Tooltip.tsx +41 -0
  508. package/src/Typography/InlineButton/InlineButton.tsx +166 -0
  509. package/src/Typography/Links/Links.tsx +113 -0
  510. package/src/Typography/Text/Text.tsx +239 -0
  511. package/src/ViewMore/ViewMore.tsx +226 -0
  512. package/src/WebRTCPlayer/WebRTCPlayer.tsx +325 -0
  513. package/src/WebRTCPlayer/adaptor/NativeWebRTCAdaptor.ts +588 -0
  514. package/src/WebRTCPlayer/hooks/useWebRTCStream.ts +571 -0
  515. package/src/WebRTCPlayer/index.ts +22 -0
  516. package/src/WebRTCPlayer/types.ts +95 -0
  517. package/src/breakpoints/index.tsx +1 -0
  518. package/src/breakpoints/utils.tsx +50 -0
  519. package/src/declarations.d.ts +7 -0
  520. package/src/grid/gridHighlighter.tsx +83 -0
  521. package/src/grid/index.ts +3 -0
  522. package/src/grid/pageGrid.tsx +37 -0
  523. package/src/grid/useSubGridCSS.tsx +214 -0
  524. package/src/hooks/useHorizontalScrollFade.ts +44 -0
  525. package/src/hooks/usePrevious.ts +14 -0
  526. package/src/index.ts +351 -0
  527. package/src/intl/index.ts +4 -0
  528. package/src/intl/utils.ts +67 -0
  529. package/src/mixins/horizontalScrollFadeMixin.ts +56 -0
  530. package/src/mixins/index.ts +18 -0
  531. package/src/mixins/propMixins.ts +389 -0
  532. package/src/providers/createContextProvider.ts +22 -0
  533. package/src/providers/designSystemProvider.tsx +218 -0
  534. package/src/providers/errorBoundaryProvider.tsx +179 -0
  535. package/src/providers/featureFlagProvider.tsx +18 -0
  536. package/src/providers/gridSizeProvider.tsx +23 -0
  537. package/src/providers/index.ts +12 -0
  538. package/src/providers/linkProvider.tsx +32 -0
  539. package/src/providers/normalize.tsx +93 -0
  540. package/src/providers/targets/DatePickerTarget.tsx +10 -0
  541. package/src/providers/targets/ModalTarget.tsx +14 -0
  542. package/src/providers/targets/TimePickerTarget.tsx +10 -0
  543. package/src/providers/themeContext.tsx +24 -0
  544. package/src/providers/windowSizeProvider.tsx +125 -0
  545. package/src/spacing/index.ts +1 -0
  546. package/src/spacing/spacing.ts +11 -0
  547. package/src/utils/countriesWithISOCodes.ts +1419 -0
  548. package/src/utils/dateTimeFormat.ts +257 -0
  549. package/src/utils/effectEventListener.ts +11 -0
  550. package/src/utils/formatFileSize.ts +18 -0
  551. package/src/utils/isClientSide.ts +1 -0
  552. package/src/utils/keepTransition.ts +15 -0
  553. package/src/utils/nodeEnv.ts +9 -0
  554. package/src/utils/smoothScrollTo.ts +47 -0
  555. package/src/utils/utilityTypes.ts +13 -0
  556. package/textInput.d.cts +1 -1
  557. package/textInput.d.mts +1 -1
  558. package/timePicker.d.cts +1 -1
  559. package/timePicker.d.mts +1 -1
@@ -0,0 +1,513 @@
1
+ import { cn } from '@evolve.ui/theme-system';
2
+ import { debounce } from 'es-toolkit';
3
+ import {
4
+ KeyboardEventHandler,
5
+ MouseEvent,
6
+ ReactNode,
7
+ UIEventHandler,
8
+ useCallback,
9
+ useEffect,
10
+ useMemo,
11
+ useRef,
12
+ useState,
13
+ } from 'react';
14
+ import useMeasure from 'react-use-measure';
15
+
16
+ import { CaretRight } from '../Icons';
17
+ import { useWindowIsDesktop } from '../providers';
18
+ import { SubtleLink } from '../Typography/Links/Links';
19
+ import {
20
+ CAROUSEL_CARD_GAP_MOBILE_NUM,
21
+ CAROUSEL_CARD_GAP_NUM,
22
+ CarouselCard,
23
+ CarouselGoToPageDirection,
24
+ CarouselGoToPageInfo,
25
+ CarouselPageInfo,
26
+ } from './Carousel.types';
27
+ import { calculatePageBreakpoints } from './Carousel.utils';
28
+ import { DotButton } from './components/DotButton/DotButton';
29
+ import { NavigationButtons } from './components/NavigationButtons/NavigationButtons';
30
+ import { TitleSection } from './components/TitleSection/TitleSection';
31
+
32
+ const SCROLL_DEBOUNCE_TIME = 50;
33
+
34
+ type Props = {
35
+ /**
36
+ * A Link element that a user can interact with.
37
+ * Usually, this will be something like a "View all" that links to a page with all the items that the carousel represents.
38
+ *
39
+ * It will appear on the right side, opposite of the title, if one exists
40
+ *
41
+ * @property {string} path - Where the user will be taken upon clicking the action
42
+ * @property {string} text="View All" - The text to be displayed in the action element
43
+ */
44
+ action?: {
45
+ hideIcon?: boolean;
46
+ onClick?: (event: MouseEvent<HTMLAnchorElement>) => void;
47
+ /**
48
+ * Where the user will be taken upon clicking the action
49
+ */
50
+ path: string;
51
+ /**
52
+ * The text to be displayed in the action element
53
+ *
54
+ * @default "View All"
55
+ */
56
+ text?: string;
57
+ };
58
+ /**
59
+ * If provided, the cards, barring the first card, will be offset so that some of the previous card will be shown on the left.
60
+ * This is best used for mobile carousels so that people can better see that they're in the middle of a carousel.
61
+ * It should be a positive number, representing a pixel amount.
62
+ * Gap size will be added to it, so make sure you aren't including it.
63
+ *
64
+ * @default 0
65
+ */
66
+ cardOffset?: number;
67
+ /**
68
+ * The scrollable content of the carousel.
69
+ * Should be individual elements, likes cards or images.
70
+ *
71
+ * @property {ReactNode} card - The rendered content
72
+ * @property {string} key - A unique identifier for the card
73
+ */
74
+ cards: CarouselCard[];
75
+ /**
76
+ * Are the cards taking up a full page of the carousel?
77
+ * This is used to use card counts to render the page-based sections of the carousel for SSR.
78
+ */
79
+ fullPage?: boolean;
80
+ /**
81
+ * Bring the slider to the selected page. Only one property will be defined, so components using this function should check
82
+ * which one is populated.
83
+ *
84
+ * @property {CarouselGoToPageDirection} buttonDirection - If populated, refers to which button was pressed: Previous or Next
85
+ * @property {number} oneBasedPageNumber - If populated, refers to which page the user is specifically going to
86
+ *
87
+ * @see CarouselGoToPageInfo
88
+ */
89
+ goToPage?: (goToPageInfo: CarouselGoToPageInfo) => void;
90
+ /**
91
+ * Callback triggered when the user scrolls through the carousel manually (either through mouse wheel or dragging)
92
+ */
93
+ onScroll?: (currentScrollPage: number) => void;
94
+ /**
95
+ * @returns The number of pages for the carousel
96
+ */
97
+ providePageCount?: (numberOfPages: number) => void;
98
+ /**
99
+ * The selected page to scroll to directly
100
+ */
101
+ selectedPage?: number;
102
+ /**
103
+ * If the user scrolls, they're automatically brought to a specific page breakpoint.
104
+ * Set this to `false` to avoid further scrolling after the user has stopped scrolling through the carousel.
105
+ *
106
+ * @default true
107
+ */
108
+ shouldGoToPageBreakpointsOnScrolling?: boolean;
109
+ /**
110
+ * Displays dots at the bottom of the carousel that represent a page of content.
111
+ * Clicking a dot will bring the user to the corresponding page.
112
+ * Mobile devices will NEVER show the page selector.
113
+ *
114
+ * @default false
115
+ */
116
+ showPagination?: boolean;
117
+ subHeaderDescription?: string;
118
+ /**
119
+ * Left side content for the carousel subheader - can be either a link or plain text.
120
+ */
121
+ subHeaderLeft?:
122
+ | {
123
+ link: {
124
+ ariaLabel?: string;
125
+ href: string;
126
+ label: string;
127
+ onClick?: (event: MouseEvent<HTMLAnchorElement>) => void;
128
+ variant?: 'default' | 'subtle';
129
+ };
130
+ type: 'link';
131
+ }
132
+ | { text: string; type: 'text' };
133
+ /**
134
+ * The title of the carousel, display above and to the left of the carousel.
135
+ * Even though it's a ReactNode, this is for formatMessage/other intl-based libraries
136
+ * to pass in populated values. You should pass in a value that is string-based, due
137
+ * to the carousel variant formatting the title as an h2 or h5.
138
+ *
139
+ * Optional.
140
+ *
141
+ * @variation primary - If carousel is primary, title is rendered as an H2
142
+ * @variation secondary - If carousel is secondary, title is rendered as an H5
143
+ *
144
+ * @see {variant}
145
+ */
146
+ title?: ReactNode;
147
+ /**
148
+ * Link configuration for the title - when provided, title becomes clickable with hover underline
149
+ */
150
+ titleLink?: {
151
+ /** Accessible label for the title link */
152
+ ariaLabel?: string;
153
+ /** URL for the title link */
154
+ href: string;
155
+ /** Click handler for the title link */
156
+ onClick?: (event: MouseEvent<HTMLAnchorElement>) => void;
157
+ };
158
+ /**
159
+ * If true, the carousel will use overlay controls to navigate to the next and previous pages.
160
+ *
161
+ * @default false
162
+ */
163
+ useOverlayControls?: boolean;
164
+ /**
165
+ * @variation {primary} - A primary carousel displays important content relevant to the page. Should only have one per page.
166
+ * @variation {secondary} - A secondary carousel display content of lesser importance to the user. Can have multiple per page.
167
+ *
168
+ * @default primary
169
+ */
170
+ variant?: 'primary' | 'secondary';
171
+ };
172
+
173
+ /**
174
+ * Displays a scrollable list of cards or elements horizontally.
175
+ * Allows navigation via buttons, dots (pagination), or touch gestures (on mobile).
176
+ */
177
+ export const Carousel = ({
178
+ action,
179
+ cardOffset = 0,
180
+ cards,
181
+ fullPage = false,
182
+ goToPage,
183
+ onScroll,
184
+ providePageCount,
185
+ selectedPage,
186
+ shouldGoToPageBreakpointsOnScrolling = true,
187
+ showPagination = false,
188
+ subHeaderDescription,
189
+ subHeaderLeft,
190
+ title,
191
+ titleLink,
192
+ useOverlayControls,
193
+ variant = 'primary',
194
+ }: Props) => {
195
+ const isDesktop = useWindowIsDesktop();
196
+ const [containerRef, { width }] = useMeasure();
197
+ const contentRef = useRef<HTMLDivElement>(null);
198
+
199
+ const actionElement = useMemo(() => {
200
+ if (action) {
201
+ const { hideIcon = false, onClick, path, text = 'View All' } = action;
202
+
203
+ return (
204
+ <SubtleLink
205
+ className="flex items-center gap-2xs"
206
+ href={path}
207
+ onClick={onClick}
208
+ >
209
+ {text} {!hideIcon && <CaretRight size="sm" />}
210
+ </SubtleLink>
211
+ );
212
+ }
213
+ return undefined;
214
+ }, [action]);
215
+
216
+ const [currentPage, setCurrentPage] = useState(1);
217
+ const [shouldGoToPageBreakpoint, setShouldGoToPageBreakpoint] = useState(false);
218
+ // Prevents onScroll prop from firing during programmatic scrollTo (e.g. AutomatedCarousel autoplay),
219
+ // which would otherwise pause autoplay by triggering the parent's scroll handler.
220
+ const isProgrammaticScroll = useRef(false);
221
+ const cardRefs = useRef<(HTMLDivElement | null)[]>([]);
222
+ const [pageInfo, setPageInfo] = useState<CarouselPageInfo>({
223
+ breakpoints: [0],
224
+ cardsPerPage: 0,
225
+ numberOfPages: 1,
226
+ });
227
+
228
+ /**
229
+ * Ensure the ref array has the correct size when the number of cards changes.
230
+ */
231
+ useEffect(() => {
232
+ cardRefs.current = cardRefs.current.slice(0, cards.length);
233
+ }, [cards.length]);
234
+
235
+ /**
236
+ * These cards are wrapped in a div.
237
+ * The div is guaranteed to have a unique key.
238
+ * The div also has a ref used to control the scrolling animation.
239
+ */
240
+ const carouselCards = useMemo(() => {
241
+ return cards.map(({ card, key }, index) => (
242
+ <div
243
+ className={cn('backface-hidden transform-gpu will-change-transform xsMax:shrink-0', {
244
+ 'xsMax:pl-sm': index === 0,
245
+ 'xsMax:pr-sm': index === cards.length - 1,
246
+ })}
247
+ key={key}
248
+ ref={(el) => {
249
+ // Directly assign the element or null to the ref array at the correct index
250
+ cardRefs.current[index] = el;
251
+ }}
252
+ role="listitem"
253
+ >
254
+ {card}
255
+ </div>
256
+ ));
257
+ }, [cards]);
258
+
259
+ useEffect(() => {
260
+ const allRefsPopulated =
261
+ cardRefs.current.length === cards.length && cardRefs.current.every((ref) => ref !== null);
262
+
263
+ if (cards.length > 0 && contentRef.current && allRefsPopulated) {
264
+ const gap = isDesktop ? CAROUSEL_CARD_GAP_NUM : CAROUSEL_CARD_GAP_MOBILE_NUM;
265
+ let contentTotalWidth = 0;
266
+
267
+ const cumulativeWidths = cards.map((_, index) => {
268
+ const ref = cardRefs.current[index];
269
+ if (!ref) {
270
+ return contentTotalWidth;
271
+ }
272
+ const isLastCard = index === cards.length - 1;
273
+ contentTotalWidth += ref.offsetWidth + (isLastCard ? 0 : gap);
274
+ return contentTotalWidth;
275
+ });
276
+
277
+ const scrollAreaWidth = contentRef.current.offsetWidth;
278
+ const newPageInfo = calculatePageBreakpoints(cumulativeWidths, scrollAreaWidth, contentTotalWidth, gap);
279
+ setPageInfo(newPageInfo);
280
+ providePageCount?.(newPageInfo.numberOfPages);
281
+ } else if (cards.length === 0 || !contentRef.current) {
282
+ setPageInfo({ breakpoints: [0], cardsPerPage: 0, numberOfPages: 1 });
283
+ providePageCount?.(1);
284
+ }
285
+ }, [width, cards, providePageCount, isDesktop]);
286
+
287
+ useEffect(() => {
288
+ if (currentPage > pageInfo.numberOfPages) {
289
+ setCurrentPage(pageInfo.numberOfPages);
290
+ setShowPreviousPageButton(pageInfo.numberOfPages > 1);
291
+ }
292
+ }, [currentPage, pageInfo.numberOfPages]);
293
+
294
+ useEffect(() => {
295
+ if (!shouldGoToPageBreakpoint || !contentRef.current || typeof contentRef.current.scrollTo !== 'function') {
296
+ return;
297
+ }
298
+ const scrollToPoint = pageInfo.breakpoints[currentPage - 1];
299
+ if (scrollToPoint === undefined) {
300
+ return;
301
+ }
302
+ let adjustedPoint = scrollToPoint;
303
+ if (cardOffset) {
304
+ const gapSize = isDesktop ? CAROUSEL_CARD_GAP_NUM : CAROUSEL_CARD_GAP_MOBILE_NUM;
305
+ adjustedPoint -= cardOffset + gapSize;
306
+ }
307
+ requestAnimationFrame(() => {
308
+ contentRef.current?.scrollTo({
309
+ behavior: 'smooth',
310
+ left: adjustedPoint,
311
+ });
312
+ });
313
+ }, [cardOffset, currentPage, isDesktop, pageInfo.breakpoints, shouldGoToPageBreakpoint]);
314
+
315
+ const onClickPageDotButton = useCallback((newPage: number) => {
316
+ setShouldGoToPageBreakpoint(true);
317
+ setCurrentPage(newPage);
318
+ setShowPreviousPageButton(newPage > 1);
319
+ }, []);
320
+
321
+ const pageDots = useMemo(() => {
322
+ if (pageInfo.numberOfPages === 1) {
323
+ return [];
324
+ }
325
+ const buttons = [];
326
+ for (let i = 1; i <= pageInfo.numberOfPages; i++) {
327
+ buttons.push(
328
+ <DotButton
329
+ isActive={currentPage === i}
330
+ key={i}
331
+ onClick={() => {
332
+ onClickPageDotButton(i);
333
+ }}
334
+ pageNumber={i}
335
+ />
336
+ );
337
+ }
338
+ return buttons;
339
+ }, [currentPage, onClickPageDotButton, pageInfo.numberOfPages]);
340
+
341
+ // Manually synced in goToNextPage, goToPreviousPage, onClickPageDotButton,
342
+ // selectedPage effect, and onScrollCards. This duplication is intentional:
343
+ // deriving it purely from currentPage would lose the scroll-position-based
344
+ // "show back button when any manual scroll has happened" behavior, and deriving
345
+ // it purely from the scroll handler would cause button flicker during the 50ms
346
+ // debounce window between setCurrentPage and the resulting scroll event.
347
+ const [showPreviousPageButton, setShowPreviousPageButton] = useState(false);
348
+
349
+ const goToPreviousPage = useCallback(() => {
350
+ if (currentPage > 1) {
351
+ setShouldGoToPageBreakpoint(true);
352
+ setCurrentPage(currentPage - 1);
353
+ goToPage?.({
354
+ buttonDirection: CarouselGoToPageDirection.Previous,
355
+ });
356
+ } else if (contentRef.current) {
357
+ contentRef.current.scrollLeft = 0;
358
+ goToPage?.({ oneBasedPageNumber: 1 });
359
+ }
360
+ setShowPreviousPageButton(currentPage - 1 > 1);
361
+ }, [currentPage, goToPage]);
362
+
363
+ const goToNextPage = useCallback(() => {
364
+ if (currentPage >= pageInfo.numberOfPages) {
365
+ return;
366
+ }
367
+ setShouldGoToPageBreakpoint(true);
368
+ setCurrentPage(currentPage + 1);
369
+ setShowPreviousPageButton(true);
370
+ goToPage?.({
371
+ buttonDirection: CarouselGoToPageDirection.Next,
372
+ });
373
+ }, [currentPage, goToPage, pageInfo.numberOfPages]);
374
+
375
+ useEffect(() => {
376
+ if (selectedPage) {
377
+ isProgrammaticScroll.current = true;
378
+ setShouldGoToPageBreakpoint(true);
379
+ setCurrentPage(selectedPage);
380
+ setShowPreviousPageButton(selectedPage > 1);
381
+ }
382
+ }, [selectedPage]);
383
+
384
+ const clearProgrammaticScrollFlag = useCallback(() => {
385
+ isProgrammaticScroll.current = false;
386
+ }, []);
387
+
388
+ /**
389
+ * Handles keyboard navigation for the carousel.
390
+ * Allows using Left and Right arrow keys to navigate between pages.
391
+ */
392
+ const onKeyNavigation: KeyboardEventHandler = useCallback(
393
+ (event) => {
394
+ if (event.key === 'ArrowRight') {
395
+ goToNextPage();
396
+ } else if (event.key === 'ArrowLeft') {
397
+ goToPreviousPage();
398
+ }
399
+ },
400
+ [goToNextPage, goToPreviousPage]
401
+ );
402
+
403
+ /**
404
+ * Handles scroll events within the carousel content area.
405
+ * Updates the current page and visibility of navigation buttons based on scroll position.
406
+ */
407
+ const onScrollCards: UIEventHandler<HTMLDivElement> = useCallback(() => {
408
+ if (!contentRef.current || isProgrammaticScroll.current) {
409
+ return;
410
+ }
411
+ const { clientWidth, scrollLeft, scrollWidth } = contentRef.current;
412
+ setShowPreviousPageButton(scrollLeft > 0);
413
+ setShouldGoToPageBreakpoint(false);
414
+
415
+ const isShowingAllOfLastPage = scrollWidth - scrollLeft <= clientWidth;
416
+
417
+ let resolvedPage: number;
418
+ if (isShowingAllOfLastPage) {
419
+ resolvedPage = pageInfo.numberOfPages;
420
+ } else {
421
+ // Find the last breakpoint the scroll position has reached or passed.
422
+ // breakpoints are sorted ascending; walk backwards for simplicity.
423
+ let pageIndex = 0;
424
+ for (let i = pageInfo.breakpoints.length - 1; i >= 0; i--) {
425
+ if (pageInfo.breakpoints[i] <= scrollLeft) {
426
+ pageIndex = i;
427
+ break;
428
+ }
429
+ }
430
+ resolvedPage = pageIndex + 1;
431
+ }
432
+
433
+ if (shouldGoToPageBreakpointsOnScrolling) {
434
+ setCurrentPage(resolvedPage);
435
+ goToPage?.({ oneBasedPageNumber: resolvedPage });
436
+ } else {
437
+ onScroll?.(resolvedPage);
438
+ }
439
+ }, [goToPage, onScroll, pageInfo, shouldGoToPageBreakpointsOnScrolling]);
440
+
441
+ const debouncedOnScrollCards = useMemo(() => debounce(onScrollCards, SCROLL_DEBOUNCE_TIME), [onScrollCards]);
442
+
443
+ useEffect(() => {
444
+ return () => debouncedOnScrollCards.cancel();
445
+ }, [debouncedOnScrollCards]);
446
+
447
+ const showNextPageButton =
448
+ currentPage < pageInfo.numberOfPages ||
449
+ // only use fullPage if the pageInfo is not yet populated
450
+ (fullPage && pageInfo.numberOfPages === 1 && cards.length > 1);
451
+
452
+ return (
453
+ <section
454
+ className={cn('relative w-full')}
455
+ ref={containerRef}
456
+ >
457
+ <div className={cn('flex items-end justify-between')}>
458
+ <TitleSection
459
+ subHeaderDescription={subHeaderDescription}
460
+ subHeaderLeft={subHeaderLeft}
461
+ title={title}
462
+ titleLink={titleLink}
463
+ variant={variant}
464
+ />
465
+ <div className="flex h-full items-center gap-xs">
466
+ {actionElement}
467
+ <NavigationButtons
468
+ goToNextPage={goToNextPage}
469
+ goToPreviousPage={goToPreviousPage}
470
+ showNextPageButton={showNextPageButton}
471
+ showPreviousPageButton={showPreviousPageButton}
472
+ useOverlayControls={useOverlayControls}
473
+ variant={variant}
474
+ />
475
+ </div>
476
+ </div>
477
+ {/* IF YOU CHANGE GAP BETWEEN CARDS HERE, YOU MUST ALSO ADJUST THE BREAKPOINT CALCULATION FORMULA TO ACCOUNT FOR THAT GAP */}
478
+ <div className={cn('mt-sm w-full overflow-hidden xsMax:-mx-sm xsMax:w-[calc(100%+32px)]')}>
479
+ {/* onKeyUp is used to arrow key right and left to pages */}
480
+ {/* eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions */}
481
+ <div
482
+ aria-label={`Slide ${currentPage} of ${pageInfo.numberOfPages}`}
483
+ aria-live="polite"
484
+ className={cn(
485
+ 'flex gap-md overflow-y-hidden overflow-x-scroll xsMax:gap-sm',
486
+ 'xsMax:snap-x xsMax:snap-mandatory xsMax:scroll-pl-sm xsMax:scroll-pr-sm',
487
+ 'backface-hidden transform-gpu will-change-scroll contain-layout'
488
+ )}
489
+ onKeyUp={onKeyNavigation}
490
+ onScroll={debouncedOnScrollCards}
491
+ onTouchMoveCapture={clearProgrammaticScrollFlag}
492
+ onWheelCapture={clearProgrammaticScrollFlag}
493
+ ref={contentRef}
494
+ role="list"
495
+ style={{
496
+ scrollbarWidth: 'none',
497
+ }}
498
+ >
499
+ {carouselCards}
500
+ </div>
501
+ </div>
502
+ {showPagination && (
503
+ <div
504
+ aria-label={`${title} carousel page selector`}
505
+ className={cn('mt-sm flex justify-center gap-xs')}
506
+ role="tablist"
507
+ >
508
+ {pageDots}
509
+ </div>
510
+ )}
511
+ </section>
512
+ );
513
+ };
@@ -0,0 +1,43 @@
1
+ import { ReactNode } from 'react';
2
+
3
+ export type CarouselCard = {
4
+ /**
5
+ * The rendered content of the card
6
+ */
7
+ card: ReactNode;
8
+ /**
9
+ * The unique identifier for the card
10
+ */
11
+ key: string;
12
+ };
13
+
14
+ export type CarouselPageInfo = {
15
+ breakpoints: number[];
16
+ cardsPerPage: number;
17
+ numberOfPages: number;
18
+ };
19
+
20
+ // this is the px size of the MD gap
21
+ export const CAROUSEL_CARD_GAP_NUM = 24;
22
+ export const CAROUSEL_CARD_GAP_MOBILE_NUM = 16;
23
+
24
+ export enum CarouselGoToPageDirection {
25
+ Previous = -1,
26
+ Next = 1,
27
+ }
28
+
29
+ /**
30
+ * Page navigation information based on the action the user took.
31
+ *
32
+ * @property {CarouselGoToPageDirection} buttonDirection - Populated if the user clicked the Next or Previous buttons
33
+ * @property {number} oneBasedPageNumber - The user navigated between cards by scrolling/dragging manually
34
+ */
35
+ export type CarouselGoToPageInfo =
36
+ | {
37
+ buttonDirection: CarouselGoToPageDirection;
38
+ oneBasedPageNumber?: never;
39
+ }
40
+ | {
41
+ buttonDirection?: never;
42
+ oneBasedPageNumber: number;
43
+ };
@@ -0,0 +1,63 @@
1
+ import { CarouselPageInfo } from './Carousel.types';
2
+
3
+ /**
4
+ * Pure function that calculates page breakpoints from cumulative card positions.
5
+ *
6
+ * @param cumulativeWidths - Array of cumulative widths (including inter-card gaps) for each card.
7
+ * Each entry is the total width from the start through that card, including a trailing gap
8
+ * for every card except the last.
9
+ * @param scrollAreaWidth - The visible width of the scroll container.
10
+ * @param contentTotalWidth - The total width of all cards and gaps combined.
11
+ * @param gap - The gap size (in px) between cards.
12
+ */
13
+ export const calculatePageBreakpoints = (
14
+ cumulativeWidths: number[],
15
+ scrollAreaWidth: number,
16
+ contentTotalWidth: number,
17
+ gap: number
18
+ ): CarouselPageInfo => {
19
+ if (cumulativeWidths.length === 0 || scrollAreaWidth <= 0) {
20
+ return { breakpoints: [0], cardsPerPage: 0, numberOfPages: 1 };
21
+ }
22
+
23
+ const cardsPerPageCounts: number[] = [];
24
+ // Starts at 1 because the first card (index 0) is already on the current page;
25
+ // the loop below begins at index 1.
26
+ let currentCardsPerPage = 1;
27
+ let numberOfPages = 1;
28
+ const pageBreakpoints = [0];
29
+ let pageStartCumulative = 0;
30
+
31
+ for (let index = 1; index < cumulativeWidths.length; index++) {
32
+ // Subtract the trailing gap so we measure only the visual width of cards + inner gaps on this page.
33
+ // The last card in the input never has a trailing gap, but intermediate cards do.
34
+ const isLastCard = index === cumulativeWidths.length - 1;
35
+ const trailingGap = isLastCard ? 0 : gap;
36
+ const pageWidth = cumulativeWidths[index] - pageStartCumulative - trailingGap;
37
+
38
+ if (pageWidth > scrollAreaWidth) {
39
+ numberOfPages++;
40
+ pageBreakpoints.push(cumulativeWidths[index - 1]);
41
+ cardsPerPageCounts.push(currentCardsPerPage);
42
+ pageStartCumulative = cumulativeWidths[index - 1];
43
+ currentCardsPerPage = 1;
44
+ } else {
45
+ currentCardsPerPage++;
46
+ }
47
+ }
48
+
49
+ // Include the last page's card count in the max calculation
50
+ cardsPerPageCounts.push(currentCardsPerPage);
51
+
52
+ const lastBreakpoint = pageBreakpoints[pageBreakpoints.length - 1] || 0;
53
+ if (contentTotalWidth - lastBreakpoint > scrollAreaWidth) {
54
+ numberOfPages++;
55
+ pageBreakpoints.push(contentTotalWidth - scrollAreaWidth);
56
+ }
57
+
58
+ return {
59
+ breakpoints: pageBreakpoints,
60
+ cardsPerPage: Math.max(...cardsPerPageCounts),
61
+ numberOfPages,
62
+ };
63
+ };
@@ -0,0 +1,42 @@
1
+ import { cn } from '@evolve.ui/theme-system';
2
+
3
+ import { Tooltip } from '../../../Tooltip/Tooltip';
4
+
5
+ type Props = {
6
+ isActive: boolean;
7
+ onClick: () => void;
8
+ pageNumber: number;
9
+ };
10
+
11
+ export const DotButton = ({ isActive, onClick, pageNumber }: Props) => {
12
+ const baseStyles = cn('h-xs w-xs rounded-full border-none hover:cursor-pointer');
13
+ const styles = isActive
14
+ ? cn(baseStyles, 'bg-text-primary hover:bg-text-secondary')
15
+ : cn(baseStyles, 'bg-text-inactive hover:bg-text-secondary');
16
+ // Generate deterministic ID from pageNumber for SSR compatibility
17
+ const tooltipId = `carousel-dot-page-${pageNumber}`;
18
+
19
+ return (
20
+ <>
21
+ {/*
22
+ this uses a regular HTML button because our Button component doesn't get small enough to be completely circular.
23
+ this is solving an edgecase and this pattern should be avoided for any other kind of button
24
+ */}
25
+ <button
26
+ aria-controls="carousel-track"
27
+ aria-label={`Page ${pageNumber}`}
28
+ aria-selected={isActive}
29
+ className={styles}
30
+ data-testid="dot-button"
31
+ data-tooltip-id={tooltipId}
32
+ onClick={onClick}
33
+ role="tab"
34
+ />
35
+ <Tooltip
36
+ content={`Page ${pageNumber}`}
37
+ delayShow={50}
38
+ id={tooltipId}
39
+ />
40
+ </>
41
+ );
42
+ };