@evolve.ui/core-components 1.0.1 → 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 (509) hide show
  1. package/evolve-ui.entries.json +556 -0
  2. package/fileUpload/testUtils/mockFilesAndImages.d.cts +3 -3
  3. package/fileUpload/testUtils/mockFilesAndImages.d.cts.map +1 -1
  4. package/fileUpload/testUtils/mockFilesAndImages.d.mts +3 -3
  5. package/fileUpload/testUtils/mockFilesAndImages.d.mts.map +1 -1
  6. package/fileUpload/testUtils/testUtils.d.cts +1 -1
  7. package/fileUpload/testUtils/testUtils.d.cts.map +1 -1
  8. package/fileUpload/testUtils/testUtils.d.mts +1 -1
  9. package/fileUpload/testUtils/testUtils.d.mts.map +1 -1
  10. package/package.json +2 -2
  11. package/src/Accordion/Accordion.tsx +233 -0
  12. package/src/AddressDisplay/AddressDisplay.tsx +43 -0
  13. package/src/AddressDisplay/components/addressComponents.tsx +111 -0
  14. package/src/AddressDisplay/components/addressField.tsx +25 -0
  15. package/src/AddressDisplay/components/addressSection.tsx +8 -0
  16. package/src/AddressDisplay/components/getCountryValue.tsx +31 -0
  17. package/src/AddressDisplay/types.ts +26 -0
  18. package/src/AutomatedCarousel/AutomatedCarousel.tsx +163 -0
  19. package/src/AutomatedCarousel/automatedCarousel.types.ts +7 -0
  20. package/src/AutomatedCarousel/components/CarouselProgressBar/CarouselProgressBar.tsx +139 -0
  21. package/src/AutomatedCarousel/components/CarouselProgressBar/components/CarouselProgressBarUnit/CarouselProgressBarUnit.tsx +165 -0
  22. package/src/Badge/Badge.tsx +104 -0
  23. package/src/Badge/Badge.types.ts +58 -0
  24. package/src/Badge/ItemBadge.tsx +97 -0
  25. package/src/Badge/LiveStatusBadge.tsx +93 -0
  26. package/src/BannerNotification/BannerNotification.tsx +157 -0
  27. package/src/BannerNotification/components/BannerNotificationSkeleton.tsx +39 -0
  28. package/src/BannerNotification/components/CalloutIcon/BannerIcon.tsx +48 -0
  29. package/src/BannerNotification/utils/getRandomTooltipId.ts +3 -0
  30. package/src/BottomSheet/BottomSheet.tsx +476 -0
  31. package/src/BottomSheet/components/BottomSheetBackdrop/BottomSheetBackdrop.tsx +47 -0
  32. package/src/BottomSheet/components/BottomSheetContentArea/BottomSheetContentArea.tsx +92 -0
  33. package/src/BottomSheet/components/BottomSheetOverlay/BottomSheetOverlayTranslate3d.tsx +196 -0
  34. package/src/BottomSheet/components/SheetDescription/SheetDescription.tsx +22 -0
  35. package/src/BottomSheet/components/SheetTitle/SheetTitle.tsx +21 -0
  36. package/src/BottomSheet/components/index.tsx +5 -0
  37. package/src/BottomSheet/hooks/index.tsx +13 -0
  38. package/src/BottomSheet/hooks/useAriaHider.tsx +91 -0
  39. package/src/BottomSheet/hooks/useBottomSheetServices.tsx +224 -0
  40. package/src/BottomSheet/hooks/useDragHandler.tsx +282 -0
  41. package/src/BottomSheet/hooks/useFocusTrap.tsx +113 -0
  42. package/src/BottomSheet/hooks/useLayoutEffect.tsx +4 -0
  43. package/src/BottomSheet/hooks/useOptimizedResizeObserver.tsx +94 -0
  44. package/src/BottomSheet/hooks/useOptimizedScrollState.tsx +87 -0
  45. package/src/BottomSheet/hooks/useReady.tsx +34 -0
  46. package/src/BottomSheet/hooks/useReducedMotion.tsx +22 -0
  47. package/src/BottomSheet/hooks/useScrollLock.tsx +143 -0
  48. package/src/BottomSheet/hooks/useSnapPoints.tsx +355 -0
  49. package/src/BottomSheet/hooks/useSpring.tsx +47 -0
  50. package/src/BottomSheet/hooks/useSpringInterpolationsTranslate3d.tsx +101 -0
  51. package/src/BottomSheet/index.tsx +237 -0
  52. package/src/BottomSheet/state/atoms.ts +147 -0
  53. package/src/BottomSheet/state/useBottomSheetStateMachine.ts +246 -0
  54. package/src/BottomSheet/types.ts +172 -0
  55. package/src/BottomSheet/utils.ts +65 -0
  56. package/src/Breadcrumbs/Breadcrumbs.tsx +126 -0
  57. package/src/Button/Button.tsx +164 -0
  58. package/src/Button/Button.types.ts +80 -0
  59. package/src/Button/buttonColorClasses.ts +53 -0
  60. package/src/Callout/Callout.tsx +136 -0
  61. package/src/Callout/Callout.types.ts +29 -0
  62. package/src/Callout/components/CalloutIcon/CalloutIcon.tsx +56 -0
  63. package/src/Card/CardGrid.tsx +263 -0
  64. package/src/Card/SingleCard.tsx +22 -0
  65. package/src/Card/cardFactory.tsx +176 -0
  66. package/src/Card/components/createBadge.tsx +34 -0
  67. package/src/Card/components/createFavoriteButton.tsx +40 -0
  68. package/src/Card/components/createImage.tsx +64 -0
  69. package/src/Card/components/createInfo.tsx +84 -0
  70. package/src/Card/components/createName.tsx +63 -0
  71. package/src/Card/components/createPriceStatus.tsx +100 -0
  72. package/src/Card/components/types.ts +4 -0
  73. package/src/Card/hooks/useCardVisibilityTracking.ts +82 -0
  74. package/src/Card/sharedProps.ts +12 -0
  75. package/src/Card/types.ts +62 -0
  76. package/src/Carousel/Carousel.tsx +513 -0
  77. package/src/Carousel/Carousel.types.ts +43 -0
  78. package/src/Carousel/Carousel.utils.ts +63 -0
  79. package/src/Carousel/components/DotButton/DotButton.tsx +42 -0
  80. package/src/Carousel/components/NavigationButtons/NavigationButtons.tsx +77 -0
  81. package/src/Carousel/components/TitleSection/TitleSection.tsx +61 -0
  82. package/src/Carousel/components/TitleSection/components/SubHeaderLeft/SubHeaderLeft.tsx +53 -0
  83. package/src/Carousel/components/TitleSection/components/Title/Title.tsx +46 -0
  84. package/src/Carousel/index.ts +2 -0
  85. package/src/Carousel/testUtils.ts +10 -0
  86. package/src/Chips/Chip.tsx +153 -0
  87. package/src/Chips/ChipGroup.tsx +173 -0
  88. package/src/Chips/SuggestionChip.tsx +15 -0
  89. package/src/Chips/chipTypes.ts +113 -0
  90. package/src/Chips/index.ts +4 -0
  91. package/src/ChoiceListItem/Checkbox.tsx +69 -0
  92. package/src/ChoiceListItem/Radio.tsx +61 -0
  93. package/src/ChoiceListItem/choiceListItem.tsx +99 -0
  94. package/src/ChoiceListItem/common.tsx +148 -0
  95. package/src/ChoiceListItem/index.ts +3 -0
  96. package/src/Collapsible/Collapsible.tsx +58 -0
  97. package/src/Confetti/Confetti.tsx +270 -0
  98. package/src/Confetti/index.ts +2 -0
  99. package/src/ContentPager/ContentPager.tsx +189 -0
  100. package/src/ContentPager/components/Page.tsx +24 -0
  101. package/src/CookieConsent/components/CookieCategoryRow/CookieCategoryRow.tsx +30 -0
  102. package/src/CookieConsent/components/CookieConsent/CookieConsent.tsx +74 -0
  103. package/src/CookieConsent/components/CookieConsentBanner/CookieConsentBanner.tsx +51 -0
  104. package/src/CookieConsent/components/CookieConsentModal/CookieConsentModal.tsx +64 -0
  105. package/src/CookieConsent/hooks/useCookieConsent.ts +170 -0
  106. package/src/CookieConsent/hooks/useCookieConsentState.ts +142 -0
  107. package/src/CookieConsent/index.ts +16 -0
  108. package/src/CookieConsent/types/cookieConsent.types.ts +79 -0
  109. package/src/CookieConsent/types/index.ts +7 -0
  110. package/src/Countdown/Countdown.tsx +161 -0
  111. package/src/Countdown/Countdown.types.ts +4 -0
  112. package/src/Countdown/hooks/useGetCountdown.ts +103 -0
  113. package/src/DateTimeInput/dateInput/DateInput.tsx +199 -0
  114. package/src/DateTimeInput/datePicker/DatePicker.tsx +138 -0
  115. package/src/DateTimeInput/datePicker/components/calendar/Calendar.tsx +72 -0
  116. package/src/DateTimeInput/datePicker/index.ts +2 -0
  117. package/src/DateTimeInput/timeInput/TimeInput.tsx +128 -0
  118. package/src/DateTimeInput/timePicker/TimePicker.tsx +118 -0
  119. package/src/DateTimeInput/timePicker/components/TimePopover/AmPmSwitch.tsx +103 -0
  120. package/src/DateTimeInput/timePicker/components/TimePopover/TimeFieldInput.tsx +26 -0
  121. package/src/DateTimeInput/timePicker/components/TimePopover/TimePopover.tsx +84 -0
  122. package/src/DateTimeInput/timePicker/components/TimePopover/TimePopover.utils.ts +67 -0
  123. package/src/DateTimeInput/timePicker/components/TimePopover/TimePopoverActions.tsx +26 -0
  124. package/src/DateTimeInput/timePicker/index.ts +2 -0
  125. package/src/DateTimeInput/utils/getDisplayDate.ts +15 -0
  126. package/src/DateTimeInput/utils/getDisplayTime.ts +15 -0
  127. package/src/DateTimeInput/utils/index.ts +2 -0
  128. package/src/DateTimeInput/utils/parseTimeValue.ts +54 -0
  129. package/src/Drawer/Drawer.tsx +446 -0
  130. package/src/Drawer/atoms.ts +4 -0
  131. package/src/Drawer/components/DialogActions/DialogActions.tsx +33 -0
  132. package/src/Drawer/components/DialogContent/DialogContent.tsx +80 -0
  133. package/src/Drawer/components/DialogHeader/DialogHeader.tsx +68 -0
  134. package/src/EducationalPopover/EducationalPopover.tsx +174 -0
  135. package/src/FavoriteButton/FavoriteButton.tsx +64 -0
  136. package/src/FavoriteButton/components/IconOnlyFavoriteButton/IconOnlyFavoriteButton.tsx +80 -0
  137. package/src/FavoriteButton/components/LabeledAnimatedFavoriteButton/LabeledAnimatedFavoriteButton.tsx +179 -0
  138. package/src/FavoriteButton/components/LabeledFavoriteButton/LabeledFavoriteButton.tsx +71 -0
  139. package/src/FavoriteButton/components/SmallHeartStraightIcon/SmallHeartStraightIcon.tsx +14 -0
  140. package/src/FavoriteButton/hooks/useFavoriteButtonState.ts +30 -0
  141. package/src/FavoriteButton/index.ts +2 -0
  142. package/src/FavoriteButton/types/favoriteButton.ts +87 -0
  143. package/src/FeatureFlags/devTools/FeatureFlagDevToolsUI.tsx +226 -0
  144. package/src/FeatureFlags/devTools/getFeatureFlagCookieOverrides.ts +30 -0
  145. package/src/FeatureFlags/devTools/utils/cookies.ts +169 -0
  146. package/src/FeatureFlags/hooks/index.ts +2 -0
  147. package/src/FeatureFlags/hooks/useFeatureFlag.tsx +19 -0
  148. package/src/FeatureFlags/hooks/useFeatureFlags.tsx +15 -0
  149. package/src/FileUpload/components/FileCard/FileCard.tsx +50 -0
  150. package/src/FileUpload/components/FileDropzone/FileDropzone.tsx +221 -0
  151. package/src/FileUpload/components/FileDropzone/components/DropzoneContent/DropzoneContent.tsx +28 -0
  152. package/src/FileUpload/components/FileDropzone/components/DropzoneContent/DropzoneText.tsx +81 -0
  153. package/src/FileUpload/components/FileDropzone/components/FileDropzoneDebugger/FileDropzoneDebugger.tsx +40 -0
  154. package/src/FileUpload/components/FileDropzone/components/FileDropzoneDebugger/FileRejectionsDisplay.tsx +110 -0
  155. package/src/FileUpload/components/FileDropzoneOverlay/FileDropzoneOverlay.tsx +183 -0
  156. package/src/FileUpload/components/FileDropzoneOverlay/components/OverlayDropzoneContent.tsx +146 -0
  157. package/src/FileUpload/components/FileDropzoneOverlay/components/OverlayDropzoneDragText.tsx +42 -0
  158. package/src/FileUpload/components/FileDropzoneOverlay/styles.ts +79 -0
  159. package/src/FileUpload/components/FilePreviewList/FilePreviewList.tsx +251 -0
  160. package/src/FileUpload/components/FilePreviewList/virtualizerComponents/FilePreviewVirtualizedList/FilePreviewVirtualizedList.tsx +88 -0
  161. package/src/FileUpload/components/FileUpload/FileUpload.tsx +63 -0
  162. package/src/FileUpload/components/FileUploadCanvas/FileUploadCanvas.tsx +125 -0
  163. package/src/FileUpload/components/GridFileCard/GridFileCard.tsx +364 -0
  164. package/src/FileUpload/components/GridFileCard/utils/sortable.ts +48 -0
  165. package/src/FileUpload/components/ListFileCard/ListFileCard.tsx +259 -0
  166. package/src/FileUpload/components/types.ts +78 -0
  167. package/src/FileUpload/hooks/filePreview/useImageFilePreviewUrl.ts +62 -0
  168. package/src/FileUpload/hooks/index.ts +11 -0
  169. package/src/FileUpload/hooks/upload/useHandleDragEnter/useHandleDragEnter.ts +154 -0
  170. package/src/FileUpload/hooks/upload/useHandleDrop/createFileRejectionHelpers.ts +273 -0
  171. package/src/FileUpload/hooks/upload/useHandleDrop/useHandleDrop.ts +153 -0
  172. package/src/FileUpload/hooks/upload/useUploadAvailability/useUploadAvailability.ts +44 -0
  173. package/src/FileUpload/hooks/validation/createDropzoneValidator.ts +41 -0
  174. package/src/FileUpload/hooks/validation/useFileValidation.ts +25 -0
  175. package/src/FileUpload/hooks/validation/useFileValidationLogic.ts +107 -0
  176. package/src/FileUpload/hooks/validation/useValidationMessages.ts +92 -0
  177. package/src/FileUpload/hooks/validation/useValidationState.ts +171 -0
  178. package/src/FileUpload/index.ts +57 -0
  179. package/src/FileUpload/providers/FileUploadProvider.tsx +219 -0
  180. package/src/FileUpload/providers/UploadValidationProvider.tsx +159 -0
  181. package/src/FileUpload/testUtils/mockFilesAndImages.ts +64 -0
  182. package/src/FileUpload/testUtils/testUtils.ts +111 -0
  183. package/src/FileUpload/types/commonTypes.ts +267 -0
  184. package/src/FileUpload/types/index.ts +31 -0
  185. package/src/FileUpload/types/sharedTypes.ts +159 -0
  186. package/src/FileUpload/utils/constants.ts +79 -0
  187. package/src/FileUpload/utils/createMessageContext.ts +180 -0
  188. package/src/FileUpload/utils/getFileExtensionsFromAcceptedTypes.ts +73 -0
  189. package/src/FileUpload/utils/getFilePluralizationText.ts +68 -0
  190. package/src/FileUpload/utils/getMimeTypes.ts +26 -0
  191. package/src/FileUpload/utils/messageUtils.ts +41 -0
  192. package/src/FileUpload/utils/styles.ts +68 -0
  193. package/src/FormLabel/FormLabel.tsx +212 -0
  194. package/src/IconButton/IconButton.tsx +154 -0
  195. package/src/Icons/CreditCardIcon/CreditCardIcon.tsx +73 -0
  196. package/src/Icons/CreditCardIcon/cardIcons.tsx +270 -0
  197. package/src/Icons/IconBase.tsx +133 -0
  198. package/src/Icons/anyIcon.ts +3 -0
  199. package/src/Icons/generatedIcons/Archive.tsx +48 -0
  200. package/src/Icons/generatedIcons/ArrowClockwise.tsx +48 -0
  201. package/src/Icons/generatedIcons/ArrowDown.tsx +48 -0
  202. package/src/Icons/generatedIcons/ArrowLeft.tsx +48 -0
  203. package/src/Icons/generatedIcons/ArrowRight.tsx +48 -0
  204. package/src/Icons/generatedIcons/ArrowSquareOut.tsx +51 -0
  205. package/src/Icons/generatedIcons/ArrowSquareRight.tsx +51 -0
  206. package/src/Icons/generatedIcons/ArrowUp.tsx +48 -0
  207. package/src/Icons/generatedIcons/ArrowsCounterClockwise.tsx +48 -0
  208. package/src/Icons/generatedIcons/ArrowsLeftRight.tsx +48 -0
  209. package/src/Icons/generatedIcons/ArrowsOutCardinal.tsx +48 -0
  210. package/src/Icons/generatedIcons/Bank.tsx +48 -0
  211. package/src/Icons/generatedIcons/Bell.tsx +51 -0
  212. package/src/Icons/generatedIcons/BookBookmark.tsx +51 -0
  213. package/src/Icons/generatedIcons/BookmarksSimple.tsx +51 -0
  214. package/src/Icons/generatedIcons/Broadcast.tsx +48 -0
  215. package/src/Icons/generatedIcons/CalendarBlank.tsx +48 -0
  216. package/src/Icons/generatedIcons/CalendarStar.tsx +51 -0
  217. package/src/Icons/generatedIcons/Camera.tsx +51 -0
  218. package/src/Icons/generatedIcons/CaretDown.tsx +48 -0
  219. package/src/Icons/generatedIcons/CaretLeft.tsx +48 -0
  220. package/src/Icons/generatedIcons/CaretRight.tsx +48 -0
  221. package/src/Icons/generatedIcons/CaretUp.tsx +48 -0
  222. package/src/Icons/generatedIcons/Certificate.tsx +51 -0
  223. package/src/Icons/generatedIcons/ChartBar.tsx +48 -0
  224. package/src/Icons/generatedIcons/Check.tsx +51 -0
  225. package/src/Icons/generatedIcons/CheckCircle.tsx +48 -0
  226. package/src/Icons/generatedIcons/CirclesFour.tsx +51 -0
  227. package/src/Icons/generatedIcons/Clock.tsx +48 -0
  228. package/src/Icons/generatedIcons/ClockCountdown.tsx +48 -0
  229. package/src/Icons/generatedIcons/Close.tsx +51 -0
  230. package/src/Icons/generatedIcons/CloudArrowUp.tsx +51 -0
  231. package/src/Icons/generatedIcons/CloudWarning.tsx +51 -0
  232. package/src/Icons/generatedIcons/Code.tsx +48 -0
  233. package/src/Icons/generatedIcons/Compass.tsx +51 -0
  234. package/src/Icons/generatedIcons/Confetti.tsx +51 -0
  235. package/src/Icons/generatedIcons/Copy.tsx +48 -0
  236. package/src/Icons/generatedIcons/CornersOut.tsx +48 -0
  237. package/src/Icons/generatedIcons/CreditCard.tsx +48 -0
  238. package/src/Icons/generatedIcons/Crown.tsx +51 -0
  239. package/src/Icons/generatedIcons/CrownSimple.tsx +51 -0
  240. package/src/Icons/generatedIcons/CurrencyCircleDollar.tsx +48 -0
  241. package/src/Icons/generatedIcons/CurrencyDollarSimple.tsx +51 -0
  242. package/src/Icons/generatedIcons/Desktop.tsx +51 -0
  243. package/src/Icons/generatedIcons/Detective.tsx +51 -0
  244. package/src/Icons/generatedIcons/DotOutline.tsx +46 -0
  245. package/src/Icons/generatedIcons/DotsSixVertical.tsx +51 -0
  246. package/src/Icons/generatedIcons/DotsThreeOutline.tsx +51 -0
  247. package/src/Icons/generatedIcons/DotsThreeOutlineVertical.tsx +51 -0
  248. package/src/Icons/generatedIcons/DownloadSimple.tsx +51 -0
  249. package/src/Icons/generatedIcons/EnvelopeSimple.tsx +48 -0
  250. package/src/Icons/generatedIcons/Eraser.tsx +51 -0
  251. package/src/Icons/generatedIcons/Eye.tsx +51 -0
  252. package/src/Icons/generatedIcons/EyeSlash.tsx +51 -0
  253. package/src/Icons/generatedIcons/FacebookLogo.tsx +48 -0
  254. package/src/Icons/generatedIcons/FileArchive.tsx +48 -0
  255. package/src/Icons/generatedIcons/FileArrowDown.tsx +48 -0
  256. package/src/Icons/generatedIcons/FileCsv.tsx +48 -0
  257. package/src/Icons/generatedIcons/FilePdf.tsx +48 -0
  258. package/src/Icons/generatedIcons/FileText.tsx +48 -0
  259. package/src/Icons/generatedIcons/Files.tsx +51 -0
  260. package/src/Icons/generatedIcons/Fire.tsx +51 -0
  261. package/src/Icons/generatedIcons/Flag.tsx +51 -0
  262. package/src/Icons/generatedIcons/FlagBannerFold.tsx +48 -0
  263. package/src/Icons/generatedIcons/FloppyDisk.tsx +51 -0
  264. package/src/Icons/generatedIcons/Gauge.tsx +51 -0
  265. package/src/Icons/generatedIcons/Gavel.tsx +51 -0
  266. package/src/Icons/generatedIcons/Gear.tsx +51 -0
  267. package/src/Icons/generatedIcons/GlobeHemisphereWest.tsx +51 -0
  268. package/src/Icons/generatedIcons/GoogleLogo.tsx +48 -0
  269. package/src/Icons/generatedIcons/GridNine.tsx +51 -0
  270. package/src/Icons/generatedIcons/HandCoins.tsx +51 -0
  271. package/src/Icons/generatedIcons/HandbagSimple.tsx +51 -0
  272. package/src/Icons/generatedIcons/Headset.tsx +51 -0
  273. package/src/Icons/generatedIcons/HeartStraight.tsx +51 -0
  274. package/src/Icons/generatedIcons/HourglassLow.tsx +48 -0
  275. package/src/Icons/generatedIcons/House.tsx +51 -0
  276. package/src/Icons/generatedIcons/Image.tsx +51 -0
  277. package/src/Icons/generatedIcons/ImageSquare.tsx +51 -0
  278. package/src/Icons/generatedIcons/ImagesSquare.tsx +51 -0
  279. package/src/Icons/generatedIcons/Info.tsx +48 -0
  280. package/src/Icons/generatedIcons/InstagramLogo.tsx +51 -0
  281. package/src/Icons/generatedIcons/Lightning.tsx +48 -0
  282. package/src/Icons/generatedIcons/Link.tsx +51 -0
  283. package/src/Icons/generatedIcons/LinkedinLogo.tsx +51 -0
  284. package/src/Icons/generatedIcons/List.tsx +48 -0
  285. package/src/Icons/generatedIcons/Lock.tsx +51 -0
  286. package/src/Icons/generatedIcons/LockOpen.tsx +51 -0
  287. package/src/Icons/generatedIcons/MagnifyingGlass.tsx +48 -0
  288. package/src/Icons/generatedIcons/MapPin.tsx +51 -0
  289. package/src/Icons/generatedIcons/MapPinSimpleArea.tsx +48 -0
  290. package/src/Icons/generatedIcons/Medal.tsx +48 -0
  291. package/src/Icons/generatedIcons/Megaphone.tsx +48 -0
  292. package/src/Icons/generatedIcons/Minus.tsx +45 -0
  293. package/src/Icons/generatedIcons/Money.tsx +51 -0
  294. package/src/Icons/generatedIcons/Notches.tsx +48 -0
  295. package/src/Icons/generatedIcons/NotePencil.tsx +48 -0
  296. package/src/Icons/generatedIcons/Package.tsx +51 -0
  297. package/src/Icons/generatedIcons/PaintBrush.tsx +51 -0
  298. package/src/Icons/generatedIcons/PaperPlaneTilt.tsx +51 -0
  299. package/src/Icons/generatedIcons/Paperclip.tsx +51 -0
  300. package/src/Icons/generatedIcons/Pause.tsx +51 -0
  301. package/src/Icons/generatedIcons/PencilLine.tsx +51 -0
  302. package/src/Icons/generatedIcons/PencilRuler.tsx +51 -0
  303. package/src/Icons/generatedIcons/PencilSimple.tsx +51 -0
  304. package/src/Icons/generatedIcons/Phone.tsx +51 -0
  305. package/src/Icons/generatedIcons/PinterestLogo.tsx +51 -0
  306. package/src/Icons/generatedIcons/Play.tsx +51 -0
  307. package/src/Icons/generatedIcons/Plus.tsx +51 -0
  308. package/src/Icons/generatedIcons/PlusCircle.tsx +48 -0
  309. package/src/Icons/generatedIcons/Printer.tsx +51 -0
  310. package/src/Icons/generatedIcons/Question.tsx +48 -0
  311. package/src/Icons/generatedIcons/Receipt.tsx +51 -0
  312. package/src/Icons/generatedIcons/Rows.tsx +51 -0
  313. package/src/Icons/generatedIcons/SealCheck.tsx +51 -0
  314. package/src/Icons/generatedIcons/SelectionSlash.tsx +48 -0
  315. package/src/Icons/generatedIcons/ShareNetwork.tsx +51 -0
  316. package/src/Icons/generatedIcons/ShieldCheck.tsx +51 -0
  317. package/src/Icons/generatedIcons/ShieldStar.tsx +51 -0
  318. package/src/Icons/generatedIcons/ShoppingCart.tsx +48 -0
  319. package/src/Icons/generatedIcons/ShuffleAngular.tsx +48 -0
  320. package/src/Icons/generatedIcons/SidebarSimple.tsx +48 -0
  321. package/src/Icons/generatedIcons/SlidersHorizontal.tsx +51 -0
  322. package/src/Icons/generatedIcons/Smiley.tsx +48 -0
  323. package/src/Icons/generatedIcons/Sparkle.tsx +51 -0
  324. package/src/Icons/generatedIcons/SpinnerGap.tsx +48 -0
  325. package/src/Icons/generatedIcons/StackPlus.tsx +48 -0
  326. package/src/Icons/generatedIcons/Star.tsx +51 -0
  327. package/src/Icons/generatedIcons/Storefront.tsx +51 -0
  328. package/src/Icons/generatedIcons/Swap.tsx +51 -0
  329. package/src/Icons/generatedIcons/Tag.tsx +51 -0
  330. package/src/Icons/generatedIcons/ThumbsDown.tsx +48 -0
  331. package/src/Icons/generatedIcons/ThumbsUp.tsx +48 -0
  332. package/src/Icons/generatedIcons/Toolbox.tsx +48 -0
  333. package/src/Icons/generatedIcons/Trash.tsx +48 -0
  334. package/src/Icons/generatedIcons/TrendUp.tsx +48 -0
  335. package/src/Icons/generatedIcons/Trophy.tsx +51 -0
  336. package/src/Icons/generatedIcons/Truck.tsx +51 -0
  337. package/src/Icons/generatedIcons/UploadSimple.tsx +51 -0
  338. package/src/Icons/generatedIcons/User.tsx +48 -0
  339. package/src/Icons/generatedIcons/Users.tsx +48 -0
  340. package/src/Icons/generatedIcons/UsersThree.tsx +51 -0
  341. package/src/Icons/generatedIcons/VideoCamera.tsx +51 -0
  342. package/src/Icons/generatedIcons/Warning.tsx +51 -0
  343. package/src/Icons/generatedIcons/WarningCircle.tsx +48 -0
  344. package/src/Icons/generatedIcons/WifiHigh.tsx +51 -0
  345. package/src/Icons/generatedIcons/XCircle.tsx +48 -0
  346. package/src/Icons/generatedIcons/XLogo.tsx +48 -0
  347. package/src/Icons/generatedIcons/YoutubeLogo.tsx +51 -0
  348. package/src/Icons/importedIcons.ts +152 -0
  349. package/src/Icons/index.ts +149 -0
  350. package/src/Icons/socialIcons/appleSocialIcon.tsx +50 -0
  351. package/src/Icons/socialIcons/facebookSocialIcon.tsx +41 -0
  352. package/src/Icons/socialIcons/googleSocialIcon.tsx +134 -0
  353. package/src/ImageCluster/ImageCluster.tsx +125 -0
  354. package/src/ImageSlider/ImageSlider.tsx +582 -0
  355. package/src/ImageSlider/ImageSlider.types.ts +90 -0
  356. package/src/ImageSlider/components/IndexIndicator/IndexIndicator.tsx +21 -0
  357. package/src/ImageSlider/components/NavigationButtons/NavigationButtons.tsx +113 -0
  358. package/src/ImageSlider/components/ResponsiveImage/ResponsiveImage.tsx +114 -0
  359. package/src/ImageSlider/components/ResponsiveImage/index.ts +1 -0
  360. package/src/ImageSlider/components/Thumbnails/Thumbnails.tsx +184 -0
  361. package/src/ImageSlider/constants.ts +59 -0
  362. package/src/ImageSlider/hooks/index.ts +3 -0
  363. package/src/ImageSlider/hooks/useImageSlider.ts +57 -0
  364. package/src/ImageSlider/hooks/useImageSliderNavigation.ts +133 -0
  365. package/src/ImageSlider/hooks/useImageSliderScrollHandler.ts +171 -0
  366. package/src/ImageSlider/index.ts +3 -0
  367. package/src/ImageSlider/utils/imageOptimization.ts +97 -0
  368. package/src/ImageSlider/utils/index.ts +1 -0
  369. package/src/InlineNotification/InlineNotification.tsx +95 -0
  370. package/src/JumpMenu/JumpMenu.tsx +395 -0
  371. package/src/JumpMenu/components/JumpMenuItem/JumpMenuItem.tsx +62 -0
  372. package/src/JumpMenu/hooks/useContainerTracking.ts +171 -0
  373. package/src/JumpMenu/hooks/useIntersectionObserver.ts +77 -0
  374. package/src/JumpMenu/hooks/useKeyboardNavigation.ts +102 -0
  375. package/src/JumpMenu/hooks/useResizeObserver.ts +53 -0
  376. package/src/JumpMenu/hooks/useSectionObserver.ts +102 -0
  377. package/src/JumpMenu/index.ts +2 -0
  378. package/src/JumpMenu/types/index.ts +19 -0
  379. package/src/Loading/Loading.tsx +39 -0
  380. package/src/Loading/components/LoadingDot/LoadingDot.tsx +16 -0
  381. package/src/LoadingSpinner/LoadingSpinner.tsx +20 -0
  382. package/src/Menu/Menu.tsx +372 -0
  383. package/src/Menu/components/MenuDivider/MenuDivider.tsx +5 -0
  384. package/src/Menu/components/MenuItem/MenuItem.tsx +298 -0
  385. package/src/Menu/context/menuContext.tsx +20 -0
  386. package/src/Menu/hooks/useMenu.tsx +18 -0
  387. package/src/Menu/index.ts +3 -0
  388. package/src/Modal/ComposableModal.tsx +313 -0
  389. package/src/Modal/Modal.tsx +231 -0
  390. package/src/Modal/components/BackButton/BackButton.tsx +43 -0
  391. package/src/Modal/components/Backdrop/Backdrop.tsx +62 -0
  392. package/src/Modal/components/CloseButton/CloseButton.tsx +55 -0
  393. package/src/Modal/components/ModalActions/ModalActions.tsx +135 -0
  394. package/src/Modal/components/ModalContent/ModalContent.tsx +163 -0
  395. package/src/Modal/components/ModalHeader/ModalHeader.tsx +84 -0
  396. package/src/Modal/components/ModalHeader/hooks/useHeaderAnimation.tsx +49 -0
  397. package/src/Modal/components/ModalProgressSteps/ModalProgressSteps.tsx +26 -0
  398. package/src/Modal/components/ModalSubTitle/ModalSubTitle.tsx +29 -0
  399. package/src/Modal/components/ModalTitle/ModalTitle.tsx +22 -0
  400. package/src/Modal/components/PreventModalScroll/PreventModalScroll.tsx +106 -0
  401. package/src/Modal/components/index.ts +12 -0
  402. package/src/Modal/context.ts +33 -0
  403. package/src/Modal/hooks/useCloseModal.ts +133 -0
  404. package/src/NotificationBadge/NotificationBadge.tsx +34 -0
  405. package/src/Pagination/AdvancedPagination.tsx +48 -0
  406. package/src/Pagination/Pagination.tsx +216 -0
  407. package/src/Pagination/components/AdvancedPaginator/AdvancedPaginator.tsx +52 -0
  408. package/src/Pagination/components/AdvancedPaginator/components/PageSelect/PageSelect.tsx +43 -0
  409. package/src/Pagination/components/ItemCountDisplay/ItemCountDisplay.tsx +32 -0
  410. package/src/Pagination/components/ItemCountSelect/ItemCountSelect.tsx +33 -0
  411. package/src/Pagination/index.tsx +3 -0
  412. package/src/Pagination/paginationProvider.tsx +234 -0
  413. package/src/Pagination/utils.tsx +36 -0
  414. package/src/PhoneInput/PhoneInput.tsx +509 -0
  415. package/src/PhoneInput/useDropdownLogic.tsx +163 -0
  416. package/src/ProgressCircle/ProgressCircle.tsx +246 -0
  417. package/src/ProgressCircle/hooks/useProgressStatusTransitions.ts +49 -0
  418. package/src/ProgressCircle/utils/progressCircle.constants.ts +27 -0
  419. package/src/ProgressSteps/ProgressSteps.tsx +160 -0
  420. package/src/SaveConfetti/SaveConfetti.tsx +277 -0
  421. package/src/SaveConfetti/index.ts +2 -0
  422. package/src/SearchInput/SearchInput.tsx +236 -0
  423. package/src/SegmentedControl/SegmentedControl.tsx +111 -0
  424. package/src/SegmentedControl/SegmentedControlGroup.tsx +94 -0
  425. package/src/SegmentedControl/index.ts +4 -0
  426. package/src/Select/Select.tsx +154 -0
  427. package/src/Select/SelectAsync.tsx +13 -0
  428. package/src/Select/SelectAsyncCreatable.tsx +14 -0
  429. package/src/Select/SelectCreatable.tsx +12 -0
  430. package/src/Select/reexportedComponents.tsx +5 -0
  431. package/src/Select/selectComponents.tsx +306 -0
  432. package/src/Skeleton/Skeleton.tsx +13 -0
  433. package/src/SplitButton/SplitButton.tsx +298 -0
  434. package/src/SplitButton/SplitButtonTrigger.tsx +55 -0
  435. package/src/StarRating/StarRating.tsx +165 -0
  436. package/src/StarRating/components/StarComponent/StarComponent.tsx +44 -0
  437. package/src/Table/Table.tsx +474 -0
  438. package/src/Table/components/TableHeader/TableHeader.tsx +166 -0
  439. package/src/Table/components/TablePagination/TablePagination.tsx +18 -0
  440. package/src/Table/components/TablePagination/components/ItemCountDisplay/ItemCountDisplay.tsx +17 -0
  441. package/src/Table/components/TablePagination/components/ItemCountSelect/ItemCountSelect.tsx +31 -0
  442. package/src/Table/components/TablePagination/components/TablePaginator/TablePaginator.tsx +37 -0
  443. package/src/Table/components/TablePagination/components/TablePaginator/components/PageSelect/PageSelect.tsx +32 -0
  444. package/src/Table/components/TableRow/TableRows.tsx +147 -0
  445. package/src/Table/components/TableRow/components/TableRowCell/TableRowCell.tsx +49 -0
  446. package/src/Table/components/TableShadow/TableShadow.tsx +46 -0
  447. package/src/Table/index.ts +2 -0
  448. package/src/Table/sharedState.ts +30 -0
  449. package/src/Table/sharedStyles.ts +1 -0
  450. package/src/Table/types.ts +55 -0
  451. package/src/Tabs/Tabs.tsx +358 -0
  452. package/src/TextArea/TextArea.tsx +157 -0
  453. package/src/TextInput/TextInput.tsx +173 -0
  454. package/src/Toast/Toast.tsx +64 -0
  455. package/src/Toast/components/ToastContainer/ToastContainer.tsx +48 -0
  456. package/src/Toast/index.ts +2 -0
  457. package/src/Toast/types/role.ts +1 -0
  458. package/src/Toast/utils/getIcon.tsx +41 -0
  459. package/src/ToggleSwitch/ToggleSwitch.tsx +188 -0
  460. package/src/Tooltip/InfoIconTooltip.tsx +47 -0
  461. package/src/Tooltip/Tooltip.tsx +41 -0
  462. package/src/Typography/InlineButton/InlineButton.tsx +166 -0
  463. package/src/Typography/Links/Links.tsx +113 -0
  464. package/src/Typography/Text/Text.tsx +239 -0
  465. package/src/ViewMore/ViewMore.tsx +226 -0
  466. package/src/WebRTCPlayer/WebRTCPlayer.tsx +325 -0
  467. package/src/WebRTCPlayer/adaptor/NativeWebRTCAdaptor.ts +588 -0
  468. package/src/WebRTCPlayer/hooks/useWebRTCStream.ts +571 -0
  469. package/src/WebRTCPlayer/index.ts +22 -0
  470. package/src/WebRTCPlayer/types.ts +95 -0
  471. package/src/breakpoints/index.tsx +1 -0
  472. package/src/breakpoints/utils.tsx +50 -0
  473. package/src/declarations.d.ts +7 -0
  474. package/src/grid/gridHighlighter.tsx +83 -0
  475. package/src/grid/index.ts +3 -0
  476. package/src/grid/pageGrid.tsx +37 -0
  477. package/src/grid/useSubGridCSS.tsx +214 -0
  478. package/src/hooks/useHorizontalScrollFade.ts +44 -0
  479. package/src/hooks/usePrevious.ts +14 -0
  480. package/src/index.ts +351 -0
  481. package/src/intl/index.ts +4 -0
  482. package/src/intl/utils.ts +67 -0
  483. package/src/mixins/horizontalScrollFadeMixin.ts +56 -0
  484. package/src/mixins/index.ts +18 -0
  485. package/src/mixins/propMixins.ts +389 -0
  486. package/src/providers/createContextProvider.ts +22 -0
  487. package/src/providers/designSystemProvider.tsx +218 -0
  488. package/src/providers/errorBoundaryProvider.tsx +179 -0
  489. package/src/providers/featureFlagProvider.tsx +18 -0
  490. package/src/providers/gridSizeProvider.tsx +23 -0
  491. package/src/providers/index.ts +12 -0
  492. package/src/providers/linkProvider.tsx +32 -0
  493. package/src/providers/normalize.tsx +93 -0
  494. package/src/providers/targets/DatePickerTarget.tsx +10 -0
  495. package/src/providers/targets/ModalTarget.tsx +14 -0
  496. package/src/providers/targets/TimePickerTarget.tsx +10 -0
  497. package/src/providers/themeContext.tsx +24 -0
  498. package/src/providers/windowSizeProvider.tsx +125 -0
  499. package/src/spacing/index.ts +1 -0
  500. package/src/spacing/spacing.ts +11 -0
  501. package/src/utils/countriesWithISOCodes.ts +1419 -0
  502. package/src/utils/dateTimeFormat.ts +257 -0
  503. package/src/utils/effectEventListener.ts +11 -0
  504. package/src/utils/formatFileSize.ts +18 -0
  505. package/src/utils/isClientSide.ts +1 -0
  506. package/src/utils/keepTransition.ts +15 -0
  507. package/src/utils/nodeEnv.ts +9 -0
  508. package/src/utils/smoothScrollTo.ts +47 -0
  509. package/src/utils/utilityTypes.ts +13 -0
@@ -0,0 +1,270 @@
1
+ import { forwardRef, useEffect, useImperativeHandle, useRef, useState } from 'react';
2
+ import { createPortal } from 'react-dom';
3
+
4
+ // Physics constants are authored at 60 fps; frameScale normalizes them to any refresh rate.
5
+ const TARGET_FRAME_MS = 1000 / 60;
6
+ const DEFAULT_PARTICLE_COUNT = 150;
7
+ const GRAVITY = 0.28; // downward acceleration (CSS px / frame² at 60fps)
8
+ const LAUNCH_SPEED_MIN = 10; // minimum initial upward velocity (CSS px / frame at 60fps)
9
+ const LAUNCH_SPEED_MAX = 22; // maximum initial upward velocity (CSS px / frame at 60fps)
10
+ const LATERAL_SPREAD = 10; // horizontal velocity range (±5 CSS px / frame at 60fps)
11
+ const SIZE_MIN = 6; // minimum particle size in CSS px
12
+ const SIZE_MAX = 12; // maximum particle size in CSS px
13
+ const FADE_DESCENT_THRESHOLD = 0.5; // vy at which opacity begins to drop (px/frame at 60fps)
14
+
15
+ /**
16
+ * Brand color palette drawn from the Default theme's generated token steps.
17
+ * Matches success, warning, surface, primary, and critical token families
18
+ * (`--color-*` step values from `@evolve.ui/theme-system` Default brand).
19
+ */
20
+ const DEFAULT_COLORS = {
21
+ success800: '#0B5125',
22
+ success600: '#12823B',
23
+ warning600: '#AE5F05',
24
+ warning300: '#FAAF57',
25
+ surface50: '#FFFFFF',
26
+ primary200: '#B8C3D8',
27
+ critical200: '#F4BDBD',
28
+ } as const;
29
+
30
+ type DefaultColorPalette = typeof DEFAULT_COLORS;
31
+ type ColorKeys = keyof DefaultColorPalette;
32
+
33
+ export type ConfettiHandle = {
34
+ /** Trigger a confetti burst across the bottom of the viewport. Re-calling while animating adds particles to the existing burst. */
35
+ fire: () => void;
36
+ };
37
+
38
+ /**
39
+ * Props for the Confetti component
40
+ */
41
+ type Props = {
42
+ /** Override the default brand color palette
43
+ Allows passing a partial set of default colors, OR any custom string map.*/
44
+ colors?: Partial<Record<ColorKeys, string>> & Record<string, string>;
45
+ /** Called when the animation loop completes */
46
+ onComplete?: () => void;
47
+ /** Number of particles per burst. Default: 150 */
48
+ particleCount?: number;
49
+ };
50
+
51
+ type Particle = {
52
+ color: string;
53
+ /** Per-particle air resistance coefficient (0.94–0.98) for organic scattering */
54
+ drag: number;
55
+ /** Per-particle opacity reduction rate for varied fadeout timing */
56
+ fadeSpeed: number;
57
+ opacity: number;
58
+ rotation: number;
59
+ rotationSpeed: number;
60
+ /** Oscillation frequency for the 3D tumble effect (radians per ms) */
61
+ tumbleFrequency: number;
62
+ shape: 'circle' | 'rect';
63
+ size: number;
64
+ vx: number;
65
+ vy: number;
66
+ x: number;
67
+ y: number;
68
+ };
69
+
70
+ /**
71
+ * Resizes the canvas buffer to match physical device pixels and returns the
72
+ * scaled context. Setting canvas.width/height resets all transforms, so the
73
+ * Device Pixel Ratio (DPR) scale is safe to reapply immediately after.
74
+ */
75
+ const setupCanvas = (canvas: HTMLCanvasElement): CanvasRenderingContext2D | null => {
76
+ const devicePixelRatio = window.devicePixelRatio ?? 1;
77
+ canvas.width = window.innerWidth * devicePixelRatio;
78
+ canvas.height = window.innerHeight * devicePixelRatio;
79
+ const canvasContext = canvas.getContext('2d');
80
+ canvasContext?.scale(devicePixelRatio, devicePixelRatio);
81
+ return canvasContext;
82
+ };
83
+
84
+ const createParticle = (colors: Record<string, string> = DEFAULT_COLORS): Particle => {
85
+ const palette = Object.values(colors);
86
+ // Fallback to default colors if someone passed an empty object {}
87
+ const activePalette = palette.length > 0 ? palette : Object.values(DEFAULT_COLORS);
88
+ const chosenColor = activePalette[Math.floor(Math.random() * activePalette.length)];
89
+
90
+ return {
91
+ color: chosenColor,
92
+ drag: Math.random() * 0.04 + 0.94,
93
+ fadeSpeed: Math.random() * 0.008 + 0.006,
94
+ opacity: 1,
95
+ rotation: Math.random() * Math.PI,
96
+ rotationSpeed: (Math.random() - 0.5) * 0.15,
97
+ tumbleFrequency: Math.random() * 0.08 + 0.04,
98
+ shape: Math.random() < 0.5 ? 'rect' : 'circle',
99
+ size: Math.random() * (SIZE_MAX - SIZE_MIN) + SIZE_MIN,
100
+ vx: (Math.random() - 0.5) * LATERAL_SPREAD,
101
+ vy: -(Math.random() * (LAUNCH_SPEED_MAX - LAUNCH_SPEED_MIN) + LAUNCH_SPEED_MIN),
102
+ x: Math.random() * window.innerWidth,
103
+ y: window.innerHeight + 10,
104
+ };
105
+ };
106
+
107
+ /**
108
+ * Canvas-based confetti burst component with an imperative `fire()` API.
109
+ *
110
+ * Renders a fixed, pointer-events-none overlay canvas and fires a branded
111
+ * particle burst from across the bottom of the viewport on demand. Re-triggerable
112
+ * while animating (accumulates particles). Cleans up the Request Animation Frame (RAF) loop and resize
113
+ * listener on unmount.
114
+ *
115
+ * @example
116
+ * ```tsx
117
+ * const ref = useRef<ConfettiHandle>(null);
118
+ * ref.current?.fire();
119
+ * return <Confetti ref={ref} />;
120
+ * ```
121
+ */
122
+ export const Confetti = forwardRef<ConfettiHandle, Props>(
123
+ ({ colors = DEFAULT_COLORS, onComplete, particleCount = DEFAULT_PARTICLE_COUNT }, ref) => {
124
+ const canvasRef = useRef<HTMLCanvasElement>(null);
125
+ const canvasContextRef = useRef<CanvasRenderingContext2D | null>(null);
126
+ const particlesRef = useRef<Particle[]>([]);
127
+ const animationFrameRef = useRef<number | null>(null);
128
+ const lastTimestampRef = useRef<number>(0);
129
+
130
+ // Clean SSR Guard: Component returns null on server evaluation, flips safely on client mount.
131
+ const [mounted, setMounted] = useState(false);
132
+
133
+ const onCompleteRef = useRef(onComplete);
134
+ onCompleteRef.current = onComplete;
135
+
136
+ // tickRef holds the animation loop function in a ref so that:
137
+ // 1. The loop can call itself recursively via requestAnimationFrame.
138
+ // 2. If props change mid-animation, the loop automatically uses the
139
+ // latest values on the next frame without needing to restart.
140
+ const tickRef = useRef<(timestamp: number) => void>(() => {});
141
+ tickRef.current = (timestamp: number) => {
142
+ const canvasContext = canvasContextRef.current;
143
+ if (!canvasContext) {
144
+ return;
145
+ }
146
+
147
+ // How many "60fps frames worth" of time has passed since the last tick.
148
+ // At 60Hz this is ~1.0; at 120Hz it's ~0.5 — physics are scaled accordingly
149
+ // so the animation runs at the same real-world speed on any display.
150
+ // Capped at 2.0 so a long tab-switch pause doesn't make particles jump.
151
+ const frameScale =
152
+ lastTimestampRef.current === 0
153
+ ? 1
154
+ : Math.min((timestamp - lastTimestampRef.current) / TARGET_FRAME_MS, 2);
155
+ lastTimestampRef.current = timestamp;
156
+
157
+ canvasContext.clearRect(0, 0, window.innerWidth, window.innerHeight);
158
+
159
+ particlesRef.current = particlesRef.current.filter((p) => p.opacity > 0 && p.y < window.innerHeight + 50);
160
+
161
+ for (const particle of particlesRef.current) {
162
+ // Move the particle: apply drag, gravity, then update position.
163
+ // Math.pow(drag, frameScale) keeps drag rate consistent at any refresh rate.
164
+ const dragFactor = Math.pow(particle.drag, frameScale);
165
+ particle.vx *= dragFactor;
166
+ particle.vy *= dragFactor;
167
+ particle.vy += GRAVITY * frameScale;
168
+ particle.x += particle.vx * frameScale;
169
+ particle.y += particle.vy * frameScale;
170
+ particle.rotation += particle.rotationSpeed * frameScale;
171
+
172
+ // Only start fading once the particle has peaked and is falling.
173
+ if (particle.vy > FADE_DESCENT_THRESHOLD) {
174
+ particle.opacity -= particle.fadeSpeed * frameScale;
175
+ }
176
+
177
+ // Squash the shape along one or both axes using sin/cos of real time.
178
+ // This fakes a 3D tumbling look. Using real time (not frame count)
179
+ // keeps the tumble speed the same on any display refresh rate.
180
+ const tumbleY = Math.sin(timestamp * particle.tumbleFrequency * 0.05);
181
+
182
+ canvasContext.save();
183
+ canvasContext.translate(particle.x, particle.y);
184
+ canvasContext.rotate(particle.rotation);
185
+ canvasContext.globalAlpha = Math.max(0, particle.opacity);
186
+ canvasContext.fillStyle = particle.color;
187
+
188
+ if (particle.shape === 'circle') {
189
+ canvasContext.scale(1, tumbleY); // squash on Y only — looks like a spinning coin
190
+ canvasContext.beginPath();
191
+ canvasContext.arc(0, 0, particle.size / 2, 0, Math.PI * 2);
192
+ canvasContext.fill();
193
+ } else {
194
+ const tumbleX = Math.cos(timestamp * particle.tumbleFrequency * 0.03);
195
+ canvasContext.scale(tumbleX, tumbleY); // squash on both axes — looks like fluttering paper
196
+ canvasContext.fillRect(-particle.size / 2, -particle.size / 2, particle.size, particle.size);
197
+ }
198
+
199
+ canvasContext.restore();
200
+ }
201
+
202
+ if (particlesRef.current.length > 0) {
203
+ animationFrameRef.current = requestAnimationFrame(tickRef.current);
204
+ } else {
205
+ animationFrameRef.current = null;
206
+ lastTimestampRef.current = 0;
207
+ onCompleteRef.current?.();
208
+ }
209
+ };
210
+
211
+ useImperativeHandle(ref, () => ({
212
+ fire() {
213
+ if (!canvasRef.current) {
214
+ return;
215
+ }
216
+
217
+ for (let i = 0; i < particleCount; i++) {
218
+ particlesRef.current.push(createParticle(colors));
219
+ }
220
+
221
+ if (animationFrameRef.current === null) {
222
+ lastTimestampRef.current = 0;
223
+ animationFrameRef.current = requestAnimationFrame(tickRef.current);
224
+ }
225
+ },
226
+ }));
227
+
228
+ useEffect(() => {
229
+ setMounted(true);
230
+
231
+ const canvas = canvasRef.current;
232
+ if (!canvas) {
233
+ return;
234
+ }
235
+
236
+ canvasContextRef.current = setupCanvas(canvas);
237
+
238
+ const handleResize = () => {
239
+ if (canvasRef.current) {
240
+ canvasContextRef.current = setupCanvas(canvasRef.current);
241
+ }
242
+ };
243
+
244
+ window.addEventListener('resize', handleResize);
245
+ return () => {
246
+ window.removeEventListener('resize', handleResize);
247
+ if (animationFrameRef.current !== null) {
248
+ window.cancelAnimationFrame(animationFrameRef.current);
249
+ }
250
+ };
251
+ }, [mounted]); // Depend on mounted initialization so it properly captures the canvas element once attached to the DOM
252
+
253
+ if (!mounted) {
254
+ return null;
255
+ }
256
+
257
+ return createPortal(
258
+ <canvas
259
+ aria-hidden="true"
260
+ className="pointer-events-none fixed inset-0 z-[9999] h-screen w-screen"
261
+ data-hui-id="Confetti"
262
+ data-testid="confetti"
263
+ ref={canvasRef}
264
+ />,
265
+ document.body
266
+ );
267
+ }
268
+ );
269
+
270
+ Confetti.displayName = 'Confetti';
@@ -0,0 +1,2 @@
1
+ export { Confetti } from './Confetti';
2
+ export type { ConfettiHandle } from './Confetti';
@@ -0,0 +1,189 @@
1
+ import { cn } from '@evolve.ui/theme-system';
2
+ import { animated, useSpring, useTransition } from '@react-spring/web';
3
+ import { atom, useSetAtom } from 'jotai';
4
+ import { ComponentProps, FC, HTMLProps, ReactElement, useEffect, useMemo, useRef, useState } from 'react';
5
+ import useMeasure from 'react-use-measure';
6
+
7
+ import { nodeEnv } from '../utils/nodeEnv';
8
+ import { Page } from './components/Page';
9
+
10
+ // react-spring 9.7.5's AnimatedComponent props drop `children` under TypeScript 6;
11
+ // runtime behavior is unchanged — re-widen with a typed alias.
12
+ type AnimatedDivProps = Omit<HTMLProps<HTMLDivElement>, 'style'> & { style?: object };
13
+ const AnimatedDiv = animated.div as unknown as FC<AnimatedDivProps>;
14
+
15
+ export const currentPageAtom = atom<string>('');
16
+
17
+ type PagerProps = {
18
+ /** Page components */
19
+ children: ReactElement<ComponentProps<typeof Page>>[];
20
+ /** Custom styling for the outermost ContentPager containing element */
21
+ className?: string;
22
+ /** The currently visible page */
23
+ currentPage: string;
24
+ /** Adds a data-testid attribute to the dom element, used for end to end testing. */
25
+ 'data-testid'?: string;
26
+ /** A callback to run when animation has completed. Useful for focusing.*/
27
+ onTransitionEnd?: () => void;
28
+ };
29
+
30
+ export const ContentPager = ({
31
+ children,
32
+ className,
33
+ currentPage,
34
+ 'data-testid': testId = 'content-pager',
35
+ onTransitionEnd,
36
+ }: PagerProps) => {
37
+ // Add state for modal content height detection
38
+ const [initialPage, setInitialPage] = useState<string>(currentPage);
39
+ const [modalContentHeight, setModalContentHeight] = useState(0);
40
+ const isTestEnv = nodeEnv === 'test';
41
+ const isInitialRender = useRef(true);
42
+
43
+ const setCurrentPage = useSetAtom(currentPageAtom);
44
+
45
+ const [ref, { height, width }] = useMeasure();
46
+
47
+ const currentPageIndex = useMemo(
48
+ () => children.findIndex((page) => page.props.name === currentPage),
49
+ [children, currentPage]
50
+ );
51
+ const currentPageComponent = useMemo(() => children[currentPageIndex], [children, currentPageIndex]);
52
+
53
+ const [previousPageIndex, setPreviousPageIndex] = useState(currentPageIndex);
54
+
55
+ const containerAnimatedStyles = useSpring({
56
+ config: {
57
+ // Increase friction for less oscillation
58
+ friction: 32,
59
+ // Prevent spring from overshooting its target, eliminating final bounce
60
+ overshootClamping: true,
61
+ // End animation sooner when displacement is below this threshold (increased from 0.01)
62
+ restDisplacementThreshold: 0.1,
63
+ // End animation sooner when speed drops below this threshold (increased from 2)
64
+ restSpeedThreshold: 10,
65
+ // Increase tension slightly for snappier animations
66
+ tension: 280,
67
+ },
68
+ height: isInitialRender.current
69
+ ? modalContentHeight
70
+ : initialPage === currentPage && modalContentHeight !== 0
71
+ ? modalContentHeight
72
+ : height,
73
+ immediate: isTestEnv || isInitialRender.current,
74
+ });
75
+
76
+ const { fromTransform, leaveTransform } = useMemo(() => {
77
+ const rightTransform = `translate(${width}px)`;
78
+ const leftTransform = `translate(-${width}px)`;
79
+ const fromTransform = currentPageIndex > previousPageIndex ? rightTransform : leftTransform;
80
+ const leaveTransform = currentPageIndex > previousPageIndex ? leftTransform : rightTransform;
81
+
82
+ return { fromTransform, leaveTransform };
83
+ }, [currentPageIndex, previousPageIndex, width]);
84
+
85
+ useEffect(() => {
86
+ if (initialPage === '') {
87
+ return;
88
+ }
89
+
90
+ if (initialPage !== currentPage) {
91
+ setInitialPage('');
92
+ setModalContentHeight(0);
93
+ }
94
+ if (isInitialRender.current) {
95
+ window.requestAnimationFrame(() => {
96
+ isInitialRender.current = false;
97
+ });
98
+ }
99
+ }, [currentPage, currentPageIndex, initialPage]);
100
+
101
+ // Ensure that modal content height is detected as it has issues with the transition
102
+ useEffect(() => {
103
+ if (currentPage === initialPage) {
104
+ const modalElement = document.querySelector('[data-hui-id="Modal"]');
105
+ const pageElement = document.querySelector(
106
+ '[data-hui-id="ContentPager"] [data-page-name]'
107
+ ) as HTMLElement | null;
108
+
109
+ if (modalElement && pageElement) {
110
+ setModalContentHeight(pageElement.scrollHeight + 1);
111
+ }
112
+ }
113
+ }, [currentPage, initialPage, height]);
114
+
115
+ // Keep the current page atom in sync immediately, so portal actions can resolve visibility on first render
116
+ useEffect(() => {
117
+ setCurrentPage(currentPage);
118
+ }, [currentPage, setCurrentPage]);
119
+
120
+ const transitions = useTransition(
121
+ [
122
+ {
123
+ currentPage,
124
+ currentPageComponent,
125
+ },
126
+ ],
127
+ {
128
+ enter: {
129
+ opacity: 1,
130
+ transform: 'translate(0px)',
131
+ },
132
+ from: {
133
+ opacity: 0,
134
+ transform: fromTransform,
135
+ },
136
+ immediate: isInitialRender.current,
137
+ initial: {
138
+ opacity: 1,
139
+ transform: 'translate(0px)',
140
+ },
141
+ keys: (page) => page.currentPage,
142
+ leave: {
143
+ opacity: 0,
144
+ transform: leaveTransform,
145
+ },
146
+ onRest: () => {
147
+ setPreviousPageIndex(currentPageIndex);
148
+ if (onTransitionEnd) {
149
+ onTransitionEnd();
150
+ }
151
+ },
152
+ onStart: () => {
153
+ setCurrentPage(currentPage);
154
+ },
155
+ }
156
+ );
157
+
158
+ return (
159
+ <AnimatedDiv
160
+ className={cn('relative w-full overflow-hidden', className)}
161
+ data-hui-id="ContentPager"
162
+ data-testid={testId}
163
+ style={{
164
+ ...containerAnimatedStyles,
165
+ height: containerAnimatedStyles.height,
166
+ }}
167
+ >
168
+ {transitions(({ ...style }, page) => (
169
+ <AnimatedDiv
170
+ className={cn('absolute left-0 right-0 h-full')}
171
+ style={{
172
+ ...style,
173
+ opacity: style.opacity,
174
+ position: 'absolute',
175
+ }}
176
+ >
177
+ <div
178
+ data-page-name={page.currentPage}
179
+ ref={ref}
180
+ >
181
+ {page.currentPageComponent}
182
+ </div>
183
+ </AnimatedDiv>
184
+ ))}
185
+ </AnimatedDiv>
186
+ );
187
+ };
188
+
189
+ export { Page };
@@ -0,0 +1,24 @@
1
+ import * as React from 'react';
2
+
3
+ type PageProps = {
4
+ /** Page content */
5
+ children: React.ReactNode;
6
+ /** className __ALL__ exported components pass through a classname to the outermost component */
7
+ className?: string;
8
+ /** Adds a data-testid attribute to the dom element, used for end to end testing. */
9
+ 'data-testid'?: string;
10
+ /** A unique page name, used by the parent <ContentPager /> for moving between pages */
11
+ name: string;
12
+ };
13
+
14
+ export const Page = ({ children, className, 'data-testid': testId = 'pager-content-page' }: PageProps) => {
15
+ return (
16
+ <div
17
+ className={className}
18
+ data-testid={testId}
19
+ id="content-pager-page"
20
+ >
21
+ {children}
22
+ </div>
23
+ );
24
+ };
@@ -0,0 +1,30 @@
1
+ import { memo } from 'react';
2
+
3
+ import { ToggleSwitch } from '../../../ToggleSwitch/ToggleSwitch';
4
+ import { BodySecondary, Caption, LabelStrong } from '../../../Typography/Text/Text';
5
+
6
+ type Props = {
7
+ description: string;
8
+ isToggled: boolean;
9
+ label: string;
10
+ onToggleChange?: () => void;
11
+ required?: boolean;
12
+ };
13
+
14
+ export const CookieCategoryRow = memo(({ description, isToggled, label, onToggleChange, required }: Props) => (
15
+ <div className="flex flex-col gap-2xs border-b border-border-secondary py-sm">
16
+ <div className="flex h-[22px] items-center justify-between">
17
+ <LabelStrong>{label}</LabelStrong>
18
+ {required ? (
19
+ <BodySecondary className="text-text-primary">Required</BodySecondary>
20
+ ) : (
21
+ <ToggleSwitch
22
+ aria-label={label}
23
+ isToggled={isToggled}
24
+ onToggleChange={onToggleChange}
25
+ />
26
+ )}
27
+ </div>
28
+ <Caption className="text-text-secondary">{description}</Caption>
29
+ </div>
30
+ ));
@@ -0,0 +1,74 @@
1
+ import { forwardRef, useImperativeHandle } from 'react';
2
+
3
+ import type { ConsentCategories, CookieCategoryConfig, CookieConsentTracking } from '../../types/cookieConsent.types';
4
+
5
+ import { useCookieConsentState } from '../../hooks/useCookieConsentState';
6
+ import { CookieConsentBanner } from '../CookieConsentBanner/CookieConsentBanner';
7
+ import { CookieConsentModal } from '../CookieConsentModal/CookieConsentModal';
8
+
9
+ const DEFAULT_TOAST_MESSAGE = 'Your privacy preferences have been saved.';
10
+
11
+ type Props = {
12
+ categories?: CookieCategoryConfig[];
13
+ /**
14
+ * Controlled consent state. When provided, an external consent-management
15
+ * platform (CMP) owns the consent state: internal localStorage persistence
16
+ * is bypassed and the banner is never auto-shown. Sync user changes back to
17
+ * the CMP via `onConsentChange`.
18
+ */
19
+ consent?: ConsentCategories;
20
+ onConsentChange?: (consent: ConsentCategories) => void;
21
+ /** localStorage key used to persist consent in uncontrolled mode (default `'hui-cookie-consent'`). */
22
+ storageKey?: string;
23
+ toastMessage?: string;
24
+ tracking?: CookieConsentTracking;
25
+ };
26
+
27
+ export type CookieConsentHandle = {
28
+ openModal: () => void;
29
+ };
30
+
31
+ /**
32
+ * Custom cookie consent UI (banner + preferences modal).
33
+ *
34
+ * Renders the consent banner and modal. By default consent is persisted to
35
+ * localStorage via `useCookieConsentState`; pass the `consent` prop to let an
36
+ * external consent-management platform own the state instead. Exposes
37
+ * `openModal()` through a ref for programmatic access (e.g. footer
38
+ * "Cookie Preferences" link).
39
+ */
40
+ export const CookieConsent = forwardRef<CookieConsentHandle, Props>(
41
+ (
42
+ { categories, consent, onConsentChange, storageKey, toastMessage = DEFAULT_TOAST_MESSAGE, tracking } = {},
43
+ ref
44
+ ) => {
45
+ const state = useCookieConsentState({ consent, onConsentChange, storageKey, toastMessage, tracking });
46
+
47
+ useImperativeHandle(ref, () => ({ openModal: state.openModal }), [state.openModal]);
48
+
49
+ if (!state.showBanner && !state.showDialog) {
50
+ return null;
51
+ }
52
+
53
+ return (
54
+ <>
55
+ {state.showBanner && (
56
+ <CookieConsentBanner
57
+ isExiting={state.bannerExiting}
58
+ onAnimationEnd={state.handleBannerAnimationEnd}
59
+ onDismiss={state.handleOk}
60
+ onOpenPreferences={state.openDialog}
61
+ />
62
+ )}
63
+ <CookieConsentModal
64
+ categories={categories}
65
+ localConsent={state.localConsent}
66
+ onClose={state.closeDialog}
67
+ onSave={state.handleSavePreferences}
68
+ onToggle={state.handleToggle}
69
+ show={state.showDialog}
70
+ />
71
+ </>
72
+ );
73
+ }
74
+ );
@@ -0,0 +1,51 @@
1
+ import { cn } from '@evolve.ui/theme-system';
2
+ import { AnimationEvent, memo } from 'react';
3
+
4
+ import { Button } from '../../../Button/Button';
5
+ import { InlineButton } from '../../../Typography/InlineButton/InlineButton';
6
+ import { BodySecondary } from '../../../Typography/Text/Text';
7
+
8
+ type Props = {
9
+ isExiting: boolean;
10
+ onAnimationEnd: (e: AnimationEvent<HTMLDivElement>) => void;
11
+ onDismiss: () => void;
12
+ onOpenPreferences: () => void;
13
+ };
14
+
15
+ export const CookieConsentBanner = memo(({ isExiting, onAnimationEnd, onDismiss, onOpenPreferences }: Props) => (
16
+ <div
17
+ aria-label="Cookie consent"
18
+ className={cn(
19
+ 'fixed inset-x-0 bottom-md z-[10300] mx-auto w-[calc(100%-48px)] max-w-[1200px] rounded-md border border-border-secondary bg-background-tertiary shadow-01',
20
+ isExiting ? 'animate-slideDown' : 'animate-slideUp'
21
+ )}
22
+ onAnimationEnd={onAnimationEnd}
23
+ role="region"
24
+ >
25
+ <div className="flex flex-col gap-xs p-sm smMin:flex-row smMin:items-center smMin:gap-md smMin:p-md">
26
+ <div className="min-w-0 flex-1">
27
+ <BodySecondary className="inline">
28
+ We use cookies to improve your experience, to analyze website usage, and for marketing purposes.
29
+ </BodySecondary>
30
+ <InlineButton
31
+ className="ml-2xs inline text-text-primary underline"
32
+ onClick={onOpenPreferences}
33
+ size="sm"
34
+ >
35
+ Cookie preferences
36
+ </InlineButton>
37
+ </div>
38
+ <div className="shrink-0 self-end smMin:self-auto">
39
+ <Button
40
+ className="min-w-[96px]"
41
+ onClick={onDismiss}
42
+ size="sm"
43
+ style="neutral"
44
+ variant="outlined"
45
+ >
46
+ OK
47
+ </Button>
48
+ </div>
49
+ </div>
50
+ </div>
51
+ ));