@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,55 @@
1
+ import { cn } from '@evolve.ui/theme-system';
2
+
3
+ import { IconButton } from '../../../IconButton/IconButton';
4
+ import { Close } from '../../../Icons';
5
+ import { useWindowIsMobile } from '../../../providers';
6
+ import { nodeEnv } from '../../../utils/nodeEnv';
7
+ import { useCloseModal, useForceCloseModal } from '../../hooks/useCloseModal';
8
+
9
+ type Props = {
10
+ /**
11
+ * @default 'Close'
12
+ */
13
+ 'aria-label'?: string;
14
+ /**
15
+ * Optional class name for the component.
16
+ */
17
+ className?: string;
18
+ };
19
+
20
+ let useCloseModalHook = useCloseModal;
21
+
22
+ if (nodeEnv === 'test') {
23
+ useCloseModalHook = useForceCloseModal as typeof useCloseModal;
24
+ }
25
+
26
+ /**
27
+ * Component used in modal windows to close them.
28
+ *
29
+ * You can access this same functionality (no need for the component to be a child of `Modal`)
30
+ * with `useCloseModal` (subpath `modal/useCloseModal`).
31
+ *
32
+ * If you need to add a callback, you likely want to modify `handleClose` on the `Modal` component.
33
+ */
34
+ export const CloseButton = ({ 'aria-label': ariaLabel = 'Close', className }: Props) => {
35
+ const closeModal = useCloseModalHook('close');
36
+ const isMobile = useWindowIsMobile();
37
+
38
+ return (
39
+ <IconButton
40
+ aria-label={ariaLabel}
41
+ className={cn(
42
+ // GENERAL
43
+ 'absolute right-sm top-sm z-[2] cursor-pointer',
44
+ // MOBILE
45
+ 'xsMax:right-[12px] xsMax:top-[13px]',
46
+ className
47
+ )}
48
+ hideTooltip
49
+ icon={Close}
50
+ onClick={closeModal}
51
+ size={isMobile ? 'sm' : 'md'}
52
+ type="button"
53
+ />
54
+ );
55
+ };
@@ -0,0 +1,135 @@
1
+ import { cn } from '@evolve.ui/theme-system';
2
+ import { useAtomValue, useSetAtom } from 'jotai';
3
+ import { Children, ReactNode, useContext, useEffect, useId, useMemo, useRef, useState } from 'react';
4
+ import { createPortal } from 'react-dom';
5
+
6
+ import { currentPageAtom } from '../../../ContentPager/ContentPager';
7
+ import { ModalContext } from '../../context';
8
+
9
+ type Props = {
10
+ children: ReactNode;
11
+ className?: string;
12
+ usePortalActions?: boolean;
13
+ };
14
+
15
+ /**
16
+ * A styled container for buttons or other actions.
17
+ *
18
+ * Automatically adds scroll hint above when `ModalContent` is scrollable.
19
+ * During page transitions, only the first set of portal actions are shown.
20
+ */
21
+ export const ModalActions = ({ children, className, usePortalActions }: Props) => {
22
+ const { modalHasFooterAtom, showBottomScrollHintAtom } = useContext(ModalContext);
23
+ const showBottomScrollHint = useAtomValue(showBottomScrollHintAtom);
24
+ const setModalHasFooter = useSetAtom(modalHasFooterAtom);
25
+ const modalActionsRef = useRef<HTMLDivElement | null>(null);
26
+
27
+ const modalPortalKey = useId();
28
+ const amountOfChildren = useMemo(() => Children.toArray(children).length, [children]);
29
+ const currentPage = useAtomValue(currentPageAtom);
30
+
31
+ // Track which page this ModalActions belongs to
32
+ const [modalActionsPageName, setModalActionsPageName] = useState<string | null>(null);
33
+
34
+ // Find the page name by checking the DOM when the ref is available
35
+ useEffect(() => {
36
+ if (modalActionsRef.current && modalActionsPageName === null) {
37
+ // For non-portal actions, traverse up the DOM to find the page
38
+ if (!usePortalActions) {
39
+ const pageElement = modalActionsRef.current.closest('[data-page-name]');
40
+ if (pageElement) {
41
+ const pageName = pageElement.getAttribute('data-page-name');
42
+ if (pageName) {
43
+ setModalActionsPageName(pageName);
44
+ return;
45
+ }
46
+ }
47
+ }
48
+
49
+ // For portal actions, find which page is currently active in the DOM
50
+ // Since portal actions are rendered outside the page structure, we check
51
+ // which page element exists and use the last one (most recently rendered)
52
+ const pageElements = document.querySelectorAll('[data-page-name]');
53
+ if (pageElements.length > 0) {
54
+ const lastPageElement = pageElements[pageElements.length - 1];
55
+ const pageName = lastPageElement.getAttribute('data-page-name');
56
+ if (pageName) {
57
+ setModalActionsPageName(pageName);
58
+ }
59
+ }
60
+ }
61
+ }, [modalActionsPageName, usePortalActions]);
62
+
63
+ const isModalActionsInCurrentPage = useMemo(() => {
64
+ return modalActionsPageName === currentPage;
65
+ }, [modalActionsPageName, currentPage]);
66
+
67
+ // Update modalHasFooter based on visibility
68
+ useEffect(() => {
69
+ if (modalActionsPageName !== null) {
70
+ // If this ModalActions is visible, set modalHasFooter to true
71
+ if (isModalActionsInCurrentPage) {
72
+ setModalHasFooter(true);
73
+ } else {
74
+ // If this ModalActions is hidden, only set modalHasFooter to false
75
+ // if there are no other visible ModalActions (i.e., we're on a page without actions)
76
+ const hasVisibleModalActions = document.querySelector('[data-testid="modal-footer"]:not(.hidden)');
77
+ if (!hasVisibleModalActions) {
78
+ setModalHasFooter(false);
79
+ }
80
+ }
81
+ }
82
+ }, [isModalActionsInCurrentPage, modalActionsPageName, setModalHasFooter]);
83
+
84
+ const modalActionsContent = (
85
+ <div
86
+ className={cn(
87
+ // GENERAL
88
+ 'relative z-[1] flex items-center justify-center gap-sm p-[32px_64px_64px_64px] [&>button]:min-w-[158px]',
89
+ // ANIMATION
90
+ 'transition-all duration-200 ease-in [animation-play-state:paused] [scrollbar-gutter:stable-both-edges]',
91
+ // SHADOW
92
+ { 'shadow-04': showBottomScrollHint },
93
+ // If there are 2 buttons, make them take up the full width
94
+ { '[&>button]:flex-1': amountOfChildren === 2 },
95
+ // PORTAL ACTIONS - absolute on desktop and mobile fullscreen, relative on tablet
96
+ {
97
+ 'mobile:group-only/fullscreen:absolute mobile:group-only/fullscreen:bottom-0 mobile:group-only/fullscreen:h-[74px] mobile:group-only/fullscreen:w-full':
98
+ usePortalActions,
99
+ 'smMin:absolute smMin:bottom-0 smMin:h-[138px] smMin:w-full': usePortalActions,
100
+ },
101
+ // MOBILE
102
+ 'xsMax:p-[24px_32px_32px_32px] xsMax:[&>button]:min-w-fit xsMax:[&>button]:flex-1',
103
+ // MOBILE FULLSCREEN
104
+ 'mobile:group-only/fullscreen:gap-sm mobile:group-only/fullscreen:p-sm',
105
+ // HIDE MODAL ACTIONS: Hide if this ModalActions belongs to a page that's NOT the current page
106
+ {
107
+ 'hidden duration-0':
108
+ usePortalActions && !isModalActionsInCurrentPage && modalActionsPageName !== null,
109
+ },
110
+ className
111
+ )}
112
+ data-testid="modal-footer"
113
+ id="modal-footer"
114
+ ref={(ref) => {
115
+ // Only set modalHasFooter based on ref existence, not visibility
116
+ // Visibility is handled by the useEffect above
117
+ modalActionsRef.current = ref;
118
+ }}
119
+ >
120
+ {children}
121
+ </div>
122
+ );
123
+
124
+ if (usePortalActions && typeof window !== 'undefined') {
125
+ const portalTarget = document.getElementById('modal-actions-portal');
126
+
127
+ if (!portalTarget) {
128
+ return modalActionsContent;
129
+ }
130
+
131
+ return createPortal(modalActionsContent, portalTarget, modalPortalKey.toString());
132
+ }
133
+
134
+ return modalActionsContent;
135
+ };
@@ -0,0 +1,163 @@
1
+ import { cn } from '@evolve.ui/theme-system';
2
+ import { useAtomValue, useSetAtom } from 'jotai';
3
+ import { ReactNode, useCallback, useContext, useEffect, useRef, useState } from 'react';
4
+
5
+ import { currentPageAtom } from '../../../ContentPager/ContentPager';
6
+ import { effectEventListener } from '../../../utils/effectEventListener';
7
+ import { ModalContext } from '../../context';
8
+
9
+ type Props = {
10
+ children: ReactNode;
11
+ className?: string;
12
+ };
13
+
14
+ /**
15
+ * The main content area of the modal.
16
+ *
17
+ * It automatically adds scroll hints to `ModalHeader` (above) and `ModalActions` (below).
18
+ * It automatically moves the `ModalTitle` farther into the header if scrolled.
19
+ */
20
+ export const ModalContent = ({ children, className }: Props) => {
21
+ const { scrollTopAtom, showBottomScrollHintAtom, showTopScrollHintAtom } = useContext(ModalContext);
22
+ const contentRef = useRef<HTMLDivElement>(null);
23
+ const currentPage = useAtomValue(currentPageAtom);
24
+
25
+ const setScrollTop = useSetAtom(scrollTopAtom);
26
+ const setShowBottomScrollHint = useSetAtom(showBottomScrollHintAtom);
27
+ const setShowTopScrollHint = useSetAtom(showTopScrollHintAtom);
28
+ const [hasModalSubTitle, setHasModalSubTitle] = useState(
29
+ Boolean(contentRef.current?.querySelector('#modal-sub-title'))
30
+ );
31
+
32
+ /* istanbul ignore next */
33
+ const handleScroll = useCallback(
34
+ (contentRef: HTMLDivElement) => () => {
35
+ if (contentRef.scrollHeight > contentRef.clientHeight + 32) {
36
+ const atTheBottom =
37
+ Math.round(contentRef.scrollHeight - contentRef.scrollTop) - 5 < contentRef.clientHeight;
38
+ const atTheTop = contentRef.scrollTop < 10;
39
+
40
+ setShowBottomScrollHint(!atTheBottom);
41
+ setShowTopScrollHint(!atTheTop);
42
+ setScrollTop(contentRef.scrollTop);
43
+ } else if (contentRef.scrollTop === 0) {
44
+ setShowBottomScrollHint(false);
45
+ setShowTopScrollHint(false);
46
+ setScrollTop(0);
47
+ }
48
+ },
49
+ [setShowBottomScrollHint, setShowTopScrollHint, setScrollTop]
50
+ );
51
+
52
+ const onScrollRef = useRef<ReturnType<typeof handleScroll>>(null);
53
+
54
+ // Trigger handleScroll on window resize
55
+ useEffect(() => {
56
+ return effectEventListener(window, 'resize', () => onScrollRef.current?.());
57
+ }, [handleScroll]);
58
+
59
+ /**
60
+ * Effect to detect presence of modal subtitle and adjust padding accordingly.
61
+ * Uses MutationObserver to handle dynamic content changes, particularly when
62
+ * content is loaded through a ContentPager component.
63
+ * Also triggers scroll hint updates when content changes.
64
+ */
65
+ useEffect(() => {
66
+ if (!contentRef.current) {
67
+ return;
68
+ }
69
+
70
+ // Initial check for subtitle in the current content
71
+ const subTitle = contentRef.current.querySelector('#modal-sub-title');
72
+
73
+ setHasModalSubTitle(Boolean(subTitle));
74
+
75
+ // Set up MutationObserver to watch for changes in the modal content
76
+ const observer = new MutationObserver(() => {
77
+ // Get all content pager pages
78
+ const allPages = contentRef.current?.querySelectorAll('[data-page-name]');
79
+
80
+ // During transition, check the second page (incoming page)
81
+ // Otherwise check the first/only page
82
+ const targetPage = allPages && allPages.length > 1 ? allPages[1] : allPages?.[0];
83
+ const modalSubtitle = targetPage?.querySelector('#modal-sub-title');
84
+
85
+ setHasModalSubTitle(Boolean(modalSubtitle));
86
+
87
+ // Trigger scroll check when content changes (e.g., page navigation)
88
+ // This ensures scroll hints update immediately when switching to a page with different scroll state
89
+ onScrollRef.current?.();
90
+ });
91
+
92
+ // Observe changes to the modal content structure
93
+ observer.observe(contentRef.current, {
94
+ childList: true,
95
+ subtree: true,
96
+ });
97
+
98
+ return () => observer.disconnect();
99
+ }, []);
100
+
101
+ // Reset scroll position when page changes in ContentPager
102
+ useEffect(() => {
103
+ if (Boolean(currentPage) && contentRef.current && contentRef.current.scrollTop !== 0) {
104
+ contentRef.current.scrollTo({ behavior: 'smooth', top: 0 });
105
+ }
106
+ }, [currentPage]);
107
+
108
+ return (
109
+ <div
110
+ className={cn(
111
+ // GENERAL
112
+ 'relative mb-2xl flex justify-center overflow-y-auto px-xl py-sm pt-md [scrollbar-gutter:stable-both-edges]',
113
+
114
+ // GROUP CLASSES FOR CONDITIONAL MARGIN BASED OFF FOOTER
115
+ 'group-has-[#modal-footer.flex]:mb-0',
116
+ // ANIMATION
117
+ 'transition-all duration-200 ease-in',
118
+ // MOBILE
119
+ 'xsMax:px-sm xsMax:pb-xs',
120
+ // WITH SUBTITLE
121
+ { '!pt-0': hasModalSubTitle },
122
+ // FULLSCREEN
123
+ 'mobile:group-only/fullscreen:h-full',
124
+ // MOBILE FULLSCREEN
125
+ 'mobile:group-only/fullscreen:mb-0 mobile:group-only/fullscreen:px-sm',
126
+ className
127
+ )}
128
+ data-testid="modal-content"
129
+ id="modal-content"
130
+ onTransitionEnd={() => {
131
+ // Check scroll hints after transitions complete (accordion animations, etc.)
132
+ onScrollRef.current?.();
133
+ }}
134
+ ref={(ref) => {
135
+ if (!ref) {
136
+ return;
137
+ }
138
+ contentRef.current = ref;
139
+
140
+ const onScroll = handleScroll(ref);
141
+ onScrollRef.current = onScroll;
142
+
143
+ ref.addEventListener('scroll', onScroll);
144
+
145
+ // Initial scroll hint check
146
+ requestAnimationFrame(() => {
147
+ onScroll();
148
+ });
149
+ }}
150
+ style={{ scrollbarGutter: 'stable both-edges' }}
151
+ >
152
+ <div
153
+ className={cn(
154
+ 'w-[460px] xsMax:w-[311px]',
155
+ // MOBILE FULLSCREEN
156
+ 'mobile:group-only/fullscreen:w-full'
157
+ )}
158
+ >
159
+ {children}
160
+ </div>
161
+ </div>
162
+ );
163
+ };
@@ -0,0 +1,84 @@
1
+ import { cn } from '@evolve.ui/theme-system';
2
+ import { useAtomValue } from 'jotai';
3
+ import { ReactNode, useContext, useEffect, useMemo } from 'react';
4
+
5
+ import { useWindowIsMobile } from '../../../providers';
6
+ import { effectEventListener } from '../../../utils/effectEventListener';
7
+ import { ModalContext } from '../../context';
8
+ import { useCloseModal } from '../../hooks/useCloseModal';
9
+ import { useHeaderAnimation } from './hooks/useHeaderAnimation';
10
+
11
+ type Props = {
12
+ children: ReactNode;
13
+ className?: string;
14
+ };
15
+
16
+ /**
17
+ * A styled container for the header of the modal.
18
+ *
19
+ * Automatically moves the `ModalTitle` farther into the header if scrolled.
20
+ * Automatically adds scroll hint below when `ModalContent` is scrollable.
21
+ */
22
+ export const ModalHeader = ({ children, className }: Props) => {
23
+ const { scrollTopAtom, showTopScrollHintAtom } = useContext(ModalContext);
24
+ const scrollTop = useAtomValue(scrollTopAtom);
25
+ const showTopScrollHint = useAtomValue(showTopScrollHintAtom);
26
+ const { headerAnimations, setAnimationPercentage, storedAnimation } = useHeaderAnimation();
27
+
28
+ const isMobile = useWindowIsMobile();
29
+ const closeModal = useCloseModal('escape');
30
+
31
+ useMemo(() => {
32
+ if (Boolean(isMobile)) {
33
+ setAnimationPercentage(Math.max(1 - (Math.max(scrollTop, 32) - scrollTop) / 32, 0));
34
+ } else {
35
+ setAnimationPercentage(Math.max(1 - (Math.max(scrollTop, 48) - scrollTop) / 48, 0));
36
+ }
37
+ }, [isMobile, scrollTop, setAnimationPercentage]);
38
+
39
+ useEffect(() => {
40
+ const handleEsc = (event: Event) => {
41
+ if ((event as KeyboardEvent).key === 'Escape') {
42
+ closeModal();
43
+ }
44
+ };
45
+
46
+ return effectEventListener(window, 'keydown', handleEsc);
47
+ }, [closeModal]);
48
+
49
+ return (
50
+ <div
51
+ className={cn(
52
+ // GENERAL
53
+ 'relative z-[1] mb-xs flex flex-col items-center justify-center px-2xl',
54
+ // ANIMATION
55
+ 'transition-all duration-200 ease-in [animation-play-state:paused] [scrollbar-gutter:stable-both-edges]',
56
+ // SHADOW
57
+ { 'shadow-01': showTopScrollHint },
58
+ // MOBILE
59
+ 'xsMax:px-xs',
60
+ // MOBILE FULLSCREEN
61
+ 'mobile:group-only/fullscreen:px-sm',
62
+ className
63
+ )}
64
+ ref={(ref) => {
65
+ if (!ref) {
66
+ return;
67
+ }
68
+
69
+ // Needed for tests to pass
70
+ if (ref.getAnimations?.().length === 0) {
71
+ const animation = ref.animate(headerAnimations, {
72
+ duration: 1000,
73
+ fill: 'both',
74
+ iterations: Infinity,
75
+ });
76
+ animation.pause();
77
+ storedAnimation.current = animation;
78
+ }
79
+ }}
80
+ >
81
+ {children}
82
+ </div>
83
+ );
84
+ };
@@ -0,0 +1,49 @@
1
+ import { useAtomValue } from 'jotai';
2
+ import { useContext, useRef } from 'react';
3
+
4
+ import { useWindowIsMobile } from '../../../../providers';
5
+ import { useTheme } from '../../../../providers/themeContext';
6
+ import { ModalContext } from '../../../context';
7
+
8
+ export const useHeaderAnimation = () => {
9
+ const storedAnimation = useRef<Animation | undefined>(undefined);
10
+ const theme = useTheme();
11
+ const isMobile = useWindowIsMobile();
12
+ const { modalHasProgressStepsAtom } = useContext(ModalContext);
13
+ const modalHasProgressSteps = useAtomValue(modalHasProgressStepsAtom);
14
+
15
+ const headerAnimations = [
16
+ {
17
+ color: theme.color.text.standard,
18
+ fontFamily: theme.typography.heading['200'].family,
19
+ fontSize: theme.typography.heading['200'].size,
20
+ fontStyle: theme.typography.heading['200'].style,
21
+ fontWeight: theme.typography.heading['200'].weight,
22
+ letterSpacing: theme.typography.heading['200'].spacing,
23
+ lineHeight: theme.typography.heading['200'].height,
24
+ marginTop: isMobile ? '38px' : '48px',
25
+ paddingBottom: '0px',
26
+ },
27
+ {
28
+ color: theme.color.text.standard,
29
+ fontFamily: theme.typography.heading['300'].family,
30
+ fontSize: theme.typography.heading['300'].size,
31
+ fontStyle: theme.typography.heading['300'].style,
32
+ fontWeight: theme.typography.heading['300'].weight,
33
+ letterSpacing: theme.typography.heading['300'].spacing,
34
+ lineHeight: theme.typography.heading['300'].height,
35
+ marginTop: isMobile ? '14px' : '22px',
36
+ paddingBottom: modalHasProgressSteps ? '8px' : isMobile ? '14px' : '22px',
37
+ },
38
+ ];
39
+
40
+ const setAnimationPercentage = (percentage: number) => {
41
+ if (!storedAnimation.current) {
42
+ return;
43
+ }
44
+
45
+ storedAnimation.current.currentTime = percentage * 999;
46
+ };
47
+
48
+ return { headerAnimations, setAnimationPercentage, storedAnimation };
49
+ };
@@ -0,0 +1,26 @@
1
+ import { cn } from '@evolve.ui/theme-system';
2
+ import { useSetAtom } from 'jotai';
3
+ import { ComponentProps, useContext, useEffect } from 'react';
4
+
5
+ import { ProgressSteps } from '../../../ProgressSteps/ProgressSteps';
6
+ import { ModalContext } from '../../context';
7
+
8
+ type Props = {
9
+ className?: string;
10
+ } & ComponentProps<typeof ProgressSteps>;
11
+
12
+ export const ModalProgressSteps = ({ className, ...props }: Props) => {
13
+ const { modalHasProgressStepsAtom } = useContext(ModalContext);
14
+ const setModalHasProgressSteps = useSetAtom(modalHasProgressStepsAtom);
15
+
16
+ useEffect(() => {
17
+ setModalHasProgressSteps(true);
18
+ }, [setModalHasProgressSteps]);
19
+
20
+ return (
21
+ <ProgressSteps
22
+ className={cn('pb-0 pt-xs', className)}
23
+ {...props}
24
+ />
25
+ );
26
+ };
@@ -0,0 +1,29 @@
1
+ import { cn } from '@evolve.ui/theme-system';
2
+
3
+ import { BodyPrimary } from '../../../Typography/Text/Text';
4
+
5
+ type Props = {
6
+ children: React.ReactNode;
7
+ className?: string;
8
+ ['data-testid']?: string;
9
+ };
10
+
11
+ /**
12
+ * Styled subtitle for modal.
13
+ */
14
+ export const ModalSubTitle = ({ children, className, 'data-testid': dataTestId = 'modalSubTitle' }: Props) => {
15
+ return (
16
+ <div className={cn('-pt-sm mb-lg block w-full text-center', className)}>
17
+ <BodyPrimary
18
+ className={className}
19
+ color="secondary"
20
+ data-testid={dataTestId}
21
+ // `id` used in ModalContent
22
+ id="modal-sub-title"
23
+ >
24
+ {children}
25
+ </BodyPrimary>
26
+ </div>
27
+ );
28
+ };
29
+ ModalSubTitle.displayName = 'ModalSubTitle';
@@ -0,0 +1,22 @@
1
+ import { ReactNode } from 'react';
2
+
3
+ /**
4
+ * Styled title for modal.
5
+ *
6
+ * Automatically moves the `ModalTitle` farther into the header if `ModalContent` scrolled.
7
+ */
8
+
9
+ export const ModalTitle = ({
10
+ children,
11
+ 'data-testid': dataTestId = 'modalTitle',
12
+ }: {
13
+ children: ReactNode;
14
+ 'data-testid'?: string;
15
+ }) => (
16
+ <span
17
+ className="px-md text-center xsMax:pt-[1px]"
18
+ data-testid={dataTestId}
19
+ >
20
+ {children}
21
+ </span>
22
+ );
@@ -0,0 +1,106 @@
1
+ import { useEffect } from 'react';
2
+
3
+ // Open modals share a single body scroll-lock. Module-scoped and ref-counted
4
+ // (local deviation from hammer — mirrors Drawer's lock): hammer's per-instance
5
+ // save/restore leaves the body locked forever when two instances overlap
6
+ // (docs pages embedding multiple open modals, auto-reopening stories), because
7
+ // the later instance saves the earlier one's `overflow: hidden` as "original".
8
+ // The first instance to mount captures the body's real styles + scroll
9
+ // position; the last to unmount restores them.
10
+ let openLockCount = 0;
11
+ let previousBodyStyles: {
12
+ overflow: string;
13
+ paddingRight: string;
14
+ position: string;
15
+ top: string;
16
+ width: string;
17
+ } | null = null;
18
+ let savedScrollPosition = 0;
19
+ let iosTouchCleanup: (() => void) | undefined;
20
+
21
+ /**
22
+ * Prevents scrolling of the page while the modal is open.
23
+ * Uses a unified approach with additional touch event handling for iOS Safari.
24
+ *
25
+ * Can be disabled with `preventScrollWhileOpen={false}` on the `Modal`.
26
+ */
27
+ export const PreventModalScroll = () => {
28
+ useEffect(() => {
29
+ const body = document.body;
30
+
31
+ if (openLockCount === 0) {
32
+ const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent);
33
+
34
+ // Store current scroll position and original styles
35
+ savedScrollPosition = window.pageYOffset || document.documentElement.scrollTop;
36
+ previousBodyStyles = {
37
+ overflow: body.style.overflow,
38
+ paddingRight: body.style.paddingRight,
39
+ position: body.style.position,
40
+ top: body.style.top,
41
+ width: body.style.width,
42
+ };
43
+
44
+ // Calculate scrollbar width and add padding to prevent content shift
45
+ const scrollBarWidth = window.innerWidth - document.documentElement.clientWidth;
46
+ if (scrollBarWidth > 0) {
47
+ body.style.paddingRight = `${scrollBarWidth}px`;
48
+ }
49
+
50
+ // Apply scroll prevention
51
+ body.style.overflow = 'hidden';
52
+ body.style.position = 'fixed';
53
+ body.style.top = `-${savedScrollPosition}px`;
54
+ body.style.width = '100%';
55
+
56
+ // iOS-specific touch event handling
57
+ if (isIOS) {
58
+ const preventDefault = (e: TouchEvent) => {
59
+ // Allow touch events on modal content but prevent on backdrop
60
+ const target = e.target as Element;
61
+ const isModalContent =
62
+ target.closest('[data-testid="modal-content"]') || target.closest('.hui-modal-container');
63
+
64
+ if (!isModalContent) {
65
+ e.preventDefault();
66
+ }
67
+ };
68
+
69
+ // Add touch event listeners for iOS
70
+ document.addEventListener('touchstart', preventDefault, { passive: false });
71
+ document.addEventListener('touchmove', preventDefault, { passive: false });
72
+
73
+ iosTouchCleanup = () => {
74
+ document.removeEventListener('touchstart', preventDefault);
75
+ document.removeEventListener('touchmove', preventDefault);
76
+ };
77
+ }
78
+ }
79
+
80
+ openLockCount += 1;
81
+
82
+ // Cleanup function
83
+ return () => {
84
+ openLockCount -= 1;
85
+
86
+ if (openLockCount === 0) {
87
+ // Remove iOS touch event listeners if they exist
88
+ iosTouchCleanup?.();
89
+ iosTouchCleanup = undefined;
90
+
91
+ // Restore original styles
92
+ body.style.overflow = previousBodyStyles?.overflow ?? '';
93
+ body.style.position = previousBodyStyles?.position ?? '';
94
+ body.style.top = previousBodyStyles?.top ?? '';
95
+ body.style.width = previousBodyStyles?.width ?? '';
96
+ body.style.paddingRight = previousBodyStyles?.paddingRight ?? '';
97
+ previousBodyStyles = null;
98
+
99
+ // Restore scroll position
100
+ window.scrollTo(0, savedScrollPosition);
101
+ }
102
+ };
103
+ }, []);
104
+
105
+ return null;
106
+ };