@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,64 @@
1
+ import { memo } from 'react';
2
+
3
+ import { Button } from '../../../Button/Button';
4
+ import { CloseButton, ModalActions, ModalContent, ModalHeader } from '../../../Modal/components';
5
+ import { Modal } from '../../../Modal/Modal';
6
+ import { BodySecondary, H2 } from '../../../Typography/Text/Text';
7
+ import { ConsentCategories, CookieCategoryConfig, DEFAULT_COOKIE_CATEGORIES } from '../../types/cookieConsent.types';
8
+ import { CookieCategoryRow } from '../CookieCategoryRow/CookieCategoryRow';
9
+
10
+ type Props = {
11
+ categories?: CookieCategoryConfig[];
12
+ localConsent: ConsentCategories;
13
+ onClose: () => void;
14
+ onSave: () => void;
15
+ onToggle: (key: keyof ConsentCategories) => void;
16
+ show: boolean;
17
+ };
18
+
19
+ export const CookieConsentModal = memo(
20
+ ({ categories = DEFAULT_COOKIE_CATEGORIES, localConsent, onClose, onSave, onToggle, show }: Props) => (
21
+ <Modal
22
+ className="max-w-[588px]"
23
+ handleClose={onClose}
24
+ show={show}
25
+ type="composable"
26
+ >
27
+ <CloseButton />
28
+ <ModalHeader>
29
+ <H2>Cookie Preferences</H2>
30
+ </ModalHeader>
31
+ <ModalContent className="max-w-460px pb-sm">
32
+ <BodySecondary className="mb-sm">
33
+ Our platform uses various types of cookies, each of which has a specific function. Manage your
34
+ preferences below:
35
+ </BodySecondary>
36
+ <div className="border-b border-border-secondary pb-sm"></div>
37
+ <div className="flex flex-col">
38
+ {categories.map((cat) => (
39
+ <CookieCategoryRow
40
+ description={cat.description}
41
+ isToggled={cat.required ? true : localConsent[cat.key as keyof ConsentCategories]}
42
+ key={cat.key}
43
+ label={cat.label}
44
+ onToggleChange={
45
+ cat.required ? undefined : () => onToggle(cat.key as keyof ConsentCategories)
46
+ }
47
+ required={cat.required}
48
+ />
49
+ ))}
50
+ </div>
51
+ </ModalContent>
52
+ <ModalActions>
53
+ <Button
54
+ onClick={onSave}
55
+ size="md"
56
+ style="primary"
57
+ variant="filled"
58
+ >
59
+ SAVE PREFERENCES
60
+ </Button>
61
+ </ModalActions>
62
+ </Modal>
63
+ )
64
+ );
@@ -0,0 +1,170 @@
1
+ import { useCallback, useEffect, useState } from 'react';
2
+
3
+ import type { ConsentCategories, ConsentPayload } from '../types/cookieConsent.types';
4
+
5
+ export const DEFAULT_CONSENT_STORAGE_KEY = 'hui-cookie-consent';
6
+
7
+ const DEFAULT_CONSENT: ConsentCategories = {
8
+ marketing: false,
9
+ preferences: false,
10
+ statistics: false,
11
+ };
12
+
13
+ /**
14
+ * Reads a previously persisted consent payload from localStorage.
15
+ * Returns `undefined` during SSR, when nothing is stored, or when the stored
16
+ * value is corrupt/unparseable (corrupt values are treated as "no response yet"
17
+ * so the banner shows again rather than trusting bad data).
18
+ */
19
+ const readStoredConsent = (storageKey: string): ConsentCategories | undefined => {
20
+ /* istanbul ignore next -- @preserve: SSR guard; a React test renderer always runs with a defined `window`, so this branch is unreachable under jest/jsdom. */
21
+ if (typeof window === 'undefined') {
22
+ return undefined;
23
+ }
24
+
25
+ let raw: string | null = null;
26
+ try {
27
+ raw = window.localStorage.getItem(storageKey);
28
+ } catch {
29
+ // localStorage can throw (e.g. disabled in the browser) — treat as no response.
30
+ return undefined;
31
+ }
32
+
33
+ if (!raw) {
34
+ return undefined;
35
+ }
36
+
37
+ try {
38
+ const parsed: unknown = JSON.parse(raw);
39
+ if (
40
+ typeof parsed === 'object' &&
41
+ parsed !== null &&
42
+ typeof (parsed as ConsentPayload).marketing === 'boolean' &&
43
+ typeof (parsed as ConsentPayload).preferences === 'boolean' &&
44
+ typeof (parsed as ConsentPayload).statistics === 'boolean'
45
+ ) {
46
+ const payload = parsed as ConsentPayload;
47
+ return {
48
+ marketing: payload.marketing,
49
+ preferences: payload.preferences,
50
+ statistics: payload.statistics,
51
+ };
52
+ }
53
+ } catch {
54
+ // Corrupt JSON — fall through to undefined.
55
+ }
56
+
57
+ return undefined;
58
+ };
59
+
60
+ /**
61
+ * Persists a consent payload to localStorage. No-ops during SSR or when
62
+ * localStorage is unavailable.
63
+ */
64
+ const writeStoredConsent = (storageKey: string, categories: ConsentCategories) => {
65
+ /* istanbul ignore next -- @preserve: SSR guard; consent writes are user-triggered client-side actions and a React test renderer always has a defined `window`, so this branch is unreachable under jest/jsdom. */
66
+ if (typeof window === 'undefined') {
67
+ return;
68
+ }
69
+
70
+ const payload: ConsentPayload = { ...categories, necessary: true };
71
+
72
+ try {
73
+ window.localStorage.setItem(storageKey, JSON.stringify(payload));
74
+ } catch {
75
+ // localStorage unavailable — consent still applies for this session via state.
76
+ }
77
+ };
78
+
79
+ /** Params for the useCookieConsent hook. */
80
+ export type UseCookieConsentParams = {
81
+ /**
82
+ * Controlled consent state. When provided, an external consent-management
83
+ * platform (CMP) owns the consent state: internal localStorage persistence
84
+ * is bypassed, the banner is never auto-shown, and consent reads reflect
85
+ * this value. Sync user changes back to the CMP via the component's
86
+ * `onConsentChange` callback.
87
+ */
88
+ consent?: ConsentCategories;
89
+ /** localStorage key used to persist consent in uncontrolled mode. */
90
+ storageKey?: string;
91
+ };
92
+
93
+ /**
94
+ * Low-level consent engine backed by localStorage.
95
+ *
96
+ * Uncontrolled (default) mode: on mount, reads any previously saved consent
97
+ * from localStorage. The banner is visible if and only if no stored consent
98
+ * exists. Action helpers (`acceptAll`, `declineAll`, `submitConsent`) persist
99
+ * the new consent payload and hide the banner.
100
+ *
101
+ * Controlled mode (`consent` param provided): an external CMP owns the state —
102
+ * nothing is read from or written to localStorage and the banner is never
103
+ * auto-shown; the preferences modal remains reachable via
104
+ * `CookieConsentHandle.openModal()`.
105
+ *
106
+ * Exposes `isBannerVisible`, current `consent` state, `hasResponse` (whether
107
+ * the user has already responded), and the action helpers.
108
+ */
109
+ export const useCookieConsent = ({
110
+ consent: controlledConsent,
111
+ storageKey = DEFAULT_CONSENT_STORAGE_KEY,
112
+ }: UseCookieConsentParams = {}) => {
113
+ const isControlled = controlledConsent !== undefined;
114
+
115
+ const [isBannerVisible, setIsBannerVisible] = useState(false);
116
+ const [internalConsent, setInternalConsent] = useState<ConsentCategories>(DEFAULT_CONSENT);
117
+ const [hasStoredResponse, setHasStoredResponse] = useState(false);
118
+
119
+ useEffect(() => {
120
+ if (isControlled) {
121
+ return;
122
+ }
123
+
124
+ const stored = readStoredConsent(storageKey);
125
+ if (stored) {
126
+ setInternalConsent(stored);
127
+ setHasStoredResponse(true);
128
+ setIsBannerVisible(false);
129
+ } else {
130
+ setIsBannerVisible(true);
131
+ }
132
+ }, [isControlled, storageKey]);
133
+
134
+ const applyConsent = useCallback(
135
+ (categories: ConsentCategories) => {
136
+ if (!isControlled) {
137
+ writeStoredConsent(storageKey, categories);
138
+ }
139
+ setInternalConsent(categories);
140
+ setHasStoredResponse(true);
141
+ setIsBannerVisible(false);
142
+ },
143
+ [isControlled, storageKey]
144
+ );
145
+
146
+ const acceptAll = useCallback(() => {
147
+ applyConsent({ marketing: true, preferences: true, statistics: true });
148
+ }, [applyConsent]);
149
+
150
+ const declineAll = useCallback(() => {
151
+ applyConsent(DEFAULT_CONSENT);
152
+ }, [applyConsent]);
153
+
154
+ const submitConsent = useCallback(
155
+ (categories: ConsentCategories) => {
156
+ applyConsent(categories);
157
+ },
158
+ [applyConsent]
159
+ );
160
+
161
+ return {
162
+ acceptAll,
163
+ consent: isControlled ? controlledConsent : internalConsent,
164
+ declineAll,
165
+ /** Whether the user has already responded (controlled mode counts as responded). */
166
+ hasResponse: isControlled || hasStoredResponse,
167
+ isBannerVisible,
168
+ submitConsent,
169
+ };
170
+ };
@@ -0,0 +1,142 @@
1
+ import { AnimationEvent, useCallback, useEffect, useRef, useState } from 'react';
2
+
3
+ import { toast } from '../../Toast';
4
+ import {
5
+ ConsentCategories,
6
+ ConsentPayload,
7
+ ConsentSource,
8
+ UseCookieConsentStateParams,
9
+ } from '../types/cookieConsent.types';
10
+ import { useCookieConsent } from './useCookieConsent';
11
+
12
+ const DEFAULT_LOCAL_CONSENT: ConsentCategories = {
13
+ marketing: true,
14
+ preferences: true,
15
+ statistics: true,
16
+ };
17
+
18
+ const buildConsentPayload = (consent: ConsentCategories): ConsentPayload => ({
19
+ ...consent,
20
+ necessary: true,
21
+ });
22
+
23
+ /**
24
+ * UI state manager for the CookieConsent component.
25
+ *
26
+ * Wraps `useCookieConsent` and owns banner/modal visibility, local consent
27
+ * toggle state, and all user interaction handlers (OK, save, toggle, open/close).
28
+ *
29
+ * Modal toggles default to all-ON (`DEFAULT_LOCAL_CONSENT`). When opening the
30
+ * modal, existing consent is read from the consent engine only if the user has
31
+ * already responded — before a response, consent initializes as all `false`,
32
+ * so we fall back to the all-ON default.
33
+ */
34
+ export const useCookieConsentState = ({
35
+ consent: controlledConsent,
36
+ onConsentChange,
37
+ storageKey,
38
+ toastMessage,
39
+ tracking,
40
+ }: UseCookieConsentStateParams) => {
41
+ const { acceptAll, consent, hasResponse, isBannerVisible, submitConsent } = useCookieConsent({
42
+ consent: controlledConsent,
43
+ storageKey,
44
+ });
45
+ const trackingRef = useRef(tracking);
46
+ trackingRef.current = tracking;
47
+
48
+ const [showBanner, setShowBanner] = useState(false);
49
+ const [bannerExiting, setBannerExiting] = useState(false);
50
+ const [showDialog, setShowDialog] = useState(false);
51
+ const [localConsent, setLocalConsent] = useState(DEFAULT_LOCAL_CONSENT);
52
+
53
+ const readCurrentConsent = useCallback(
54
+ (): ConsentCategories => (hasResponse ? consent : DEFAULT_LOCAL_CONSENT),
55
+ [consent, hasResponse]
56
+ );
57
+
58
+ useEffect(() => {
59
+ if (isBannerVisible) {
60
+ setShowBanner(true);
61
+ setBannerExiting(false);
62
+ trackingRef.current?.onBannerViewed?.();
63
+ }
64
+ }, [isBannerVisible]);
65
+
66
+ const openModal = useCallback(() => {
67
+ setLocalConsent(readCurrentConsent());
68
+ setShowDialog(true);
69
+ }, [readCurrentConsent]);
70
+
71
+ const handleBannerAnimationEnd = useCallback(
72
+ (e: AnimationEvent<HTMLDivElement>) => {
73
+ /* istanbul ignore next -- @preserve: `bannerExiting` is only ever set to false in this hook (faithful hammer parity), so the exit-animation cleanup branch is unreachable. Reported as latent dead code, not modified to preserve parity. */
74
+ if (bannerExiting && e.target === e.currentTarget) {
75
+ setShowBanner(false);
76
+ setBannerExiting(false);
77
+ }
78
+ },
79
+ [bannerExiting]
80
+ );
81
+
82
+ const openDialog = useCallback(() => {
83
+ setLocalConsent(readCurrentConsent());
84
+ setShowDialog(true);
85
+ setShowBanner(false);
86
+ setBannerExiting(false);
87
+ trackingRef.current?.onPreferencesOpened?.(ConsentSource.Banner);
88
+ }, [readCurrentConsent]);
89
+
90
+ const closeDialog = useCallback(() => {
91
+ setShowDialog(false);
92
+ trackingRef.current?.onPreferencesDismissed?.(ConsentSource.Modal);
93
+ if (isBannerVisible) {
94
+ setShowBanner(true);
95
+ setBannerExiting(false);
96
+ }
97
+ }, [isBannerVisible]);
98
+
99
+ const handleOk = useCallback(() => {
100
+ const allConsent: ConsentCategories = { marketing: true, preferences: true, statistics: true };
101
+ acceptAll();
102
+ onConsentChange?.(allConsent);
103
+ setShowBanner(false);
104
+ setBannerExiting(false);
105
+ toast('success', { title: toastMessage });
106
+ trackingRef.current?.onPreferencesSaved?.({
107
+ consent: buildConsentPayload(allConsent),
108
+ source: ConsentSource.Banner,
109
+ });
110
+ }, [acceptAll, onConsentChange, toastMessage]);
111
+
112
+ const handleSavePreferences = useCallback(() => {
113
+ submitConsent(localConsent);
114
+ onConsentChange?.(localConsent);
115
+ setShowDialog(false);
116
+ setShowBanner(false);
117
+ setBannerExiting(false);
118
+ toast('success', { title: toastMessage });
119
+ trackingRef.current?.onPreferencesSaved?.({
120
+ consent: buildConsentPayload(localConsent),
121
+ source: ConsentSource.Modal,
122
+ });
123
+ }, [localConsent, onConsentChange, submitConsent, toastMessage]);
124
+
125
+ const handleToggle = useCallback((key: keyof ConsentCategories) => {
126
+ setLocalConsent((prev) => ({ ...prev, [key]: !prev[key] }));
127
+ }, []);
128
+
129
+ return {
130
+ bannerExiting,
131
+ closeDialog,
132
+ handleBannerAnimationEnd,
133
+ handleOk,
134
+ handleSavePreferences,
135
+ handleToggle,
136
+ localConsent,
137
+ openDialog,
138
+ openModal,
139
+ showBanner,
140
+ showDialog,
141
+ };
142
+ };
@@ -0,0 +1,16 @@
1
+ // Components
2
+ export { CookieConsent } from './components/CookieConsent/CookieConsent';
3
+ export type { CookieConsentHandle } from './components/CookieConsent/CookieConsent';
4
+
5
+ // Hooks
6
+ export { useCookieConsent, DEFAULT_CONSENT_STORAGE_KEY } from './hooks/useCookieConsent';
7
+ export type { UseCookieConsentParams } from './hooks/useCookieConsent';
8
+
9
+ // Types
10
+ export { ConsentSource, DEFAULT_COOKIE_CATEGORIES } from './types/cookieConsent.types';
11
+ export type {
12
+ ConsentCategories,
13
+ CookieCategoryConfig,
14
+ CookieConsentTracking,
15
+ ConsentPayload,
16
+ } from './types/cookieConsent.types';
@@ -0,0 +1,79 @@
1
+ /**
2
+ * The three non-essential consent categories managed by this component.
3
+ * `necessary` is excluded because it's always implicitly granted.
4
+ */
5
+ export type ConsentCategories = {
6
+ marketing: boolean;
7
+ preferences: boolean;
8
+ statistics: boolean;
9
+ };
10
+
11
+ /** Full consent payload including the always-on `necessary` flag. */
12
+ export type ConsentPayload = ConsentCategories & { necessary: true };
13
+
14
+ /** Where the user interaction originated. */
15
+ export enum ConsentSource {
16
+ Banner = 'banner',
17
+ Modal = 'modal',
18
+ }
19
+
20
+ /** Tracking callbacks for cookie consent analytics. */
21
+ export type CookieConsentTracking = {
22
+ onBannerViewed?: () => void;
23
+ onPreferencesDismissed?: (source: ConsentSource) => void;
24
+ onPreferencesOpened?: (source: ConsentSource) => void;
25
+ onPreferencesSaved?: (payload: { consent: ConsentPayload; source: ConsentSource }) => void;
26
+ };
27
+
28
+ /** Params for the useCookieConsentState hook. */
29
+ export type UseCookieConsentStateParams = {
30
+ /**
31
+ * Controlled consent state. When provided, an external consent-management
32
+ * platform owns the consent state and internal localStorage persistence is
33
+ * bypassed — sync changes back through `onConsentChange`.
34
+ */
35
+ consent?: ConsentCategories;
36
+ onConsentChange?: (consent: ConsentCategories) => void;
37
+ /** localStorage key used to persist consent in uncontrolled mode. */
38
+ storageKey?: string;
39
+ toastMessage: string;
40
+ tracking?: CookieConsentTracking;
41
+ };
42
+
43
+ /** Definition for a single row in the preferences modal. */
44
+ export type CookieCategoryConfig = {
45
+ description: string;
46
+ /** Must match a `ConsentCategories` key, or `'necessary'` for the always-on row. */
47
+ key: keyof ConsentCategories | 'necessary';
48
+ label: string;
49
+ /** When `true`, the toggle is locked on and the user cannot opt out. */
50
+ required?: boolean;
51
+ };
52
+
53
+ export const DEFAULT_COOKIE_CATEGORIES: CookieCategoryConfig[] = [
54
+ {
55
+ description:
56
+ 'Necessary cookies help make a website usable by enabling basic functions like page navigation and access to secure areas of the website. The website cannot function properly without these cookies.',
57
+ key: 'necessary',
58
+ label: 'Necessary',
59
+ required: true,
60
+ },
61
+ {
62
+ description:
63
+ 'Preference cookies enable a website to remember information that changes the way the website behaves or looks, like your preferred language or the region that you are in.',
64
+ key: 'preferences',
65
+ label: 'Preferences',
66
+ },
67
+ {
68
+ description:
69
+ 'Statistics cookies help website owners to understand how visitors interact with websites by collecting and reporting information anonymously.',
70
+ key: 'statistics',
71
+ label: 'Statistics',
72
+ },
73
+ {
74
+ description:
75
+ 'Marketing cookies are used to track visitors across websites. The intention is to display ads that are relevant and engaging for the individual user and thereby more valuable for publishers and third party advertisers.',
76
+ key: 'marketing',
77
+ label: 'Marketing',
78
+ },
79
+ ];
@@ -0,0 +1,7 @@
1
+ export type {
2
+ ConsentCategories,
3
+ CookieCategoryConfig,
4
+ CookieConsentTracking,
5
+ ConsentPayload,
6
+ } from './cookieConsent.types';
7
+ export { ConsentSource, DEFAULT_COOKIE_CATEGORIES } from './cookieConsent.types';
@@ -0,0 +1,161 @@
1
+ import { useEffect } from 'react';
2
+
3
+ import { BodySecondary, H3 } from '../Typography/Text/Text';
4
+ import { CountdownFlashpoint } from './Countdown.types';
5
+ import { useGetCountdown } from './hooks/useGetCountdown';
6
+
7
+ /**
8
+ * @property completionTime Timestamp (in ms) for when the countdown will first reach zero
9
+ * @property flashpoint Amount of time left before the countdown turns red (signalling urgency)
10
+ * @property label Additional information for the countdown. *e.g.* 5d 23h **Until the event begins!**
11
+ * @property onComplete Called when the countdown reaches zero.
12
+ * @property preLabel Information shown before the countdown numbers. Will not be shown unless countdown is small
13
+ * @property small If true, all text (the countdown numbers and the label) will be the same size
14
+ * @property startTime Represents the time from which the countdown is counting down from
15
+ * @property timeLabels Used for internationalization, defaults to d/h/m/s, represents days/hours/minutes/seconds
16
+ */
17
+ export type CountdownProps = {
18
+ /* Timestamp (in ms) for when the countdown will first reach zero */
19
+ completionTime: number;
20
+ // Amount of time left before the countdown turns red (signalling urgency)
21
+ flashpoint?: CountdownFlashpoint;
22
+ // If true, the countdown will always display with seconds included
23
+ forceSeconds?: boolean;
24
+ // If true, the countdown will always render in the urgent/critical color regardless of time remaining
25
+ forceUrgent?: boolean;
26
+ // Additional information for the countdown. *e.g.* 5d 23h **Until the event begins!**
27
+ label?: string;
28
+ // Called when the countdown reaches zero.
29
+ onComplete?: () => void;
30
+ // Information shown before the countdown numbers. Will not be shown unless countdown is small
31
+ preLabel?: string;
32
+ // If true, all text (the countdown numbers and the label) will be the same size
33
+ small?: boolean;
34
+ // Represents the time from which the countdown is counting down from
35
+ startTime?: number;
36
+ // Used for internationalization, defaults to d/h/m/s, represents days/hours/minutes/seconds
37
+ timeLabels?: {
38
+ days?: string;
39
+ hours?: string;
40
+ minutes?: string;
41
+ seconds?: string;
42
+ };
43
+ };
44
+
45
+ export const Countdown = ({
46
+ completionTime,
47
+ flashpoint,
48
+ forceSeconds,
49
+ forceUrgent,
50
+ label,
51
+ onComplete,
52
+ preLabel,
53
+ small,
54
+ startTime,
55
+ timeLabels,
56
+ }: CountdownProps) => {
57
+ const {
58
+ daysUntilEnd,
59
+ hoursUntilEnd,
60
+ isUrgent: isUrgentFromFlashpoint,
61
+ minutesUntilEnd,
62
+ secondsUntilEnd,
63
+ } = useGetCountdown({
64
+ completionTime,
65
+ flashpoint,
66
+ forceSeconds,
67
+ startTime,
68
+ });
69
+
70
+ const isUrgent = forceUrgent || isUrgentFromFlashpoint;
71
+
72
+ const dayLabel = timeLabels?.days ?? 'd';
73
+ const hourLabel = timeLabels?.hours ?? 'h';
74
+ const minuteLabel = timeLabels?.minutes ?? 'm';
75
+ const secondLabel = timeLabels?.seconds ?? 's';
76
+
77
+ let primaryDurationValue = `${daysUntilEnd}${dayLabel}`;
78
+ let secondaryDurationValue: string | null = `${hoursUntilEnd}${hourLabel}`;
79
+ let altDurationValue = null;
80
+
81
+ // less than one day from end
82
+ if (daysUntilEnd === 0 && hoursUntilEnd !== 0) {
83
+ primaryDurationValue = `${hoursUntilEnd}${hourLabel}`;
84
+ secondaryDurationValue = `${minutesUntilEnd}${minuteLabel}`;
85
+ if (forceSeconds) {
86
+ altDurationValue = `${secondsUntilEnd}${secondLabel}`;
87
+ }
88
+ } else if (daysUntilEnd === 0 && hoursUntilEnd === 0 && minutesUntilEnd !== 0) {
89
+ primaryDurationValue = `${minutesUntilEnd}${minuteLabel}`;
90
+ secondaryDurationValue = `${secondsUntilEnd}${secondLabel}`;
91
+ } else if (daysUntilEnd === 0 && hoursUntilEnd === 0 && minutesUntilEnd === 0) {
92
+ primaryDurationValue = `${secondsUntilEnd}${secondLabel}`;
93
+ secondaryDurationValue = null;
94
+ }
95
+
96
+ useEffect(() => {
97
+ if (daysUntilEnd === 0 && hoursUntilEnd === 0 && minutesUntilEnd === 0 && secondsUntilEnd === 0) {
98
+ onComplete?.();
99
+ }
100
+ }, [daysUntilEnd, hoursUntilEnd, minutesUntilEnd, onComplete, secondsUntilEnd]);
101
+
102
+ if (small) {
103
+ return (
104
+ <div className="flex items-baseline whitespace-nowrap">
105
+ {Boolean(preLabel) && (
106
+ <>
107
+ <BodySecondary color={isUrgent ? 'critical' : 'primary'}>{preLabel}</BodySecondary>
108
+ &nbsp;
109
+ </>
110
+ )}
111
+ <BodySecondary color={isUrgent ? 'critical' : 'primary'}>{primaryDurationValue}</BodySecondary>
112
+ {secondaryDurationValue && (
113
+ <>
114
+ &nbsp;
115
+ <BodySecondary color={isUrgent ? 'critical' : 'primary'}>
116
+ {secondaryDurationValue}
117
+ </BodySecondary>
118
+ </>
119
+ )}
120
+ &nbsp;
121
+ {altDurationValue && (
122
+ <>
123
+ <BodySecondary color={isUrgent ? 'critical' : 'primary'}>{altDurationValue}</BodySecondary>
124
+ &nbsp;
125
+ </>
126
+ )}
127
+ <BodySecondary color={isUrgent ? 'critical' : 'primary'}>{label}</BodySecondary>
128
+ </div>
129
+ );
130
+ }
131
+
132
+ return (
133
+ <div className="flex items-baseline whitespace-nowrap">
134
+ <span className={`hui-text-h1 text-${isUrgent ? 'text-critical' : 'text-primary'}`}>
135
+ {primaryDurationValue}
136
+ </span>
137
+ {secondaryDurationValue && (
138
+ <>
139
+ &nbsp;
140
+ <span className={`hui-text-h1 text-${isUrgent ? 'text-critical' : 'text-primary'}`}>
141
+ {secondaryDurationValue}
142
+ </span>
143
+ </>
144
+ )}
145
+ {altDurationValue && (
146
+ <>
147
+ &nbsp;
148
+ <span className={`hui-text-h1 text-${isUrgent ? 'text-critical' : 'text-primary'}`}>
149
+ {altDurationValue}
150
+ </span>
151
+ </>
152
+ )}
153
+ <H3
154
+ className="ml-2"
155
+ color="secondary"
156
+ >
157
+ {label}
158
+ </H3>
159
+ </div>
160
+ );
161
+ };
@@ -0,0 +1,4 @@
1
+ export type CountdownFlashpoint = {
2
+ duration: 'd' | 'h' | 'm' | 's';
3
+ value: number;
4
+ };