@evolve.ui/core-components 1.0.1 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (509) hide show
  1. package/evolve-ui.entries.json +556 -0
  2. package/fileUpload/testUtils/mockFilesAndImages.d.cts +3 -3
  3. package/fileUpload/testUtils/mockFilesAndImages.d.cts.map +1 -1
  4. package/fileUpload/testUtils/mockFilesAndImages.d.mts +3 -3
  5. package/fileUpload/testUtils/mockFilesAndImages.d.mts.map +1 -1
  6. package/fileUpload/testUtils/testUtils.d.cts +1 -1
  7. package/fileUpload/testUtils/testUtils.d.cts.map +1 -1
  8. package/fileUpload/testUtils/testUtils.d.mts +1 -1
  9. package/fileUpload/testUtils/testUtils.d.mts.map +1 -1
  10. package/package.json +2 -2
  11. package/src/Accordion/Accordion.tsx +233 -0
  12. package/src/AddressDisplay/AddressDisplay.tsx +43 -0
  13. package/src/AddressDisplay/components/addressComponents.tsx +111 -0
  14. package/src/AddressDisplay/components/addressField.tsx +25 -0
  15. package/src/AddressDisplay/components/addressSection.tsx +8 -0
  16. package/src/AddressDisplay/components/getCountryValue.tsx +31 -0
  17. package/src/AddressDisplay/types.ts +26 -0
  18. package/src/AutomatedCarousel/AutomatedCarousel.tsx +163 -0
  19. package/src/AutomatedCarousel/automatedCarousel.types.ts +7 -0
  20. package/src/AutomatedCarousel/components/CarouselProgressBar/CarouselProgressBar.tsx +139 -0
  21. package/src/AutomatedCarousel/components/CarouselProgressBar/components/CarouselProgressBarUnit/CarouselProgressBarUnit.tsx +165 -0
  22. package/src/Badge/Badge.tsx +104 -0
  23. package/src/Badge/Badge.types.ts +58 -0
  24. package/src/Badge/ItemBadge.tsx +97 -0
  25. package/src/Badge/LiveStatusBadge.tsx +93 -0
  26. package/src/BannerNotification/BannerNotification.tsx +157 -0
  27. package/src/BannerNotification/components/BannerNotificationSkeleton.tsx +39 -0
  28. package/src/BannerNotification/components/CalloutIcon/BannerIcon.tsx +48 -0
  29. package/src/BannerNotification/utils/getRandomTooltipId.ts +3 -0
  30. package/src/BottomSheet/BottomSheet.tsx +476 -0
  31. package/src/BottomSheet/components/BottomSheetBackdrop/BottomSheetBackdrop.tsx +47 -0
  32. package/src/BottomSheet/components/BottomSheetContentArea/BottomSheetContentArea.tsx +92 -0
  33. package/src/BottomSheet/components/BottomSheetOverlay/BottomSheetOverlayTranslate3d.tsx +196 -0
  34. package/src/BottomSheet/components/SheetDescription/SheetDescription.tsx +22 -0
  35. package/src/BottomSheet/components/SheetTitle/SheetTitle.tsx +21 -0
  36. package/src/BottomSheet/components/index.tsx +5 -0
  37. package/src/BottomSheet/hooks/index.tsx +13 -0
  38. package/src/BottomSheet/hooks/useAriaHider.tsx +91 -0
  39. package/src/BottomSheet/hooks/useBottomSheetServices.tsx +224 -0
  40. package/src/BottomSheet/hooks/useDragHandler.tsx +282 -0
  41. package/src/BottomSheet/hooks/useFocusTrap.tsx +113 -0
  42. package/src/BottomSheet/hooks/useLayoutEffect.tsx +4 -0
  43. package/src/BottomSheet/hooks/useOptimizedResizeObserver.tsx +94 -0
  44. package/src/BottomSheet/hooks/useOptimizedScrollState.tsx +87 -0
  45. package/src/BottomSheet/hooks/useReady.tsx +34 -0
  46. package/src/BottomSheet/hooks/useReducedMotion.tsx +22 -0
  47. package/src/BottomSheet/hooks/useScrollLock.tsx +143 -0
  48. package/src/BottomSheet/hooks/useSnapPoints.tsx +355 -0
  49. package/src/BottomSheet/hooks/useSpring.tsx +47 -0
  50. package/src/BottomSheet/hooks/useSpringInterpolationsTranslate3d.tsx +101 -0
  51. package/src/BottomSheet/index.tsx +237 -0
  52. package/src/BottomSheet/state/atoms.ts +147 -0
  53. package/src/BottomSheet/state/useBottomSheetStateMachine.ts +246 -0
  54. package/src/BottomSheet/types.ts +172 -0
  55. package/src/BottomSheet/utils.ts +65 -0
  56. package/src/Breadcrumbs/Breadcrumbs.tsx +126 -0
  57. package/src/Button/Button.tsx +164 -0
  58. package/src/Button/Button.types.ts +80 -0
  59. package/src/Button/buttonColorClasses.ts +53 -0
  60. package/src/Callout/Callout.tsx +136 -0
  61. package/src/Callout/Callout.types.ts +29 -0
  62. package/src/Callout/components/CalloutIcon/CalloutIcon.tsx +56 -0
  63. package/src/Card/CardGrid.tsx +263 -0
  64. package/src/Card/SingleCard.tsx +22 -0
  65. package/src/Card/cardFactory.tsx +176 -0
  66. package/src/Card/components/createBadge.tsx +34 -0
  67. package/src/Card/components/createFavoriteButton.tsx +40 -0
  68. package/src/Card/components/createImage.tsx +64 -0
  69. package/src/Card/components/createInfo.tsx +84 -0
  70. package/src/Card/components/createName.tsx +63 -0
  71. package/src/Card/components/createPriceStatus.tsx +100 -0
  72. package/src/Card/components/types.ts +4 -0
  73. package/src/Card/hooks/useCardVisibilityTracking.ts +82 -0
  74. package/src/Card/sharedProps.ts +12 -0
  75. package/src/Card/types.ts +62 -0
  76. package/src/Carousel/Carousel.tsx +513 -0
  77. package/src/Carousel/Carousel.types.ts +43 -0
  78. package/src/Carousel/Carousel.utils.ts +63 -0
  79. package/src/Carousel/components/DotButton/DotButton.tsx +42 -0
  80. package/src/Carousel/components/NavigationButtons/NavigationButtons.tsx +77 -0
  81. package/src/Carousel/components/TitleSection/TitleSection.tsx +61 -0
  82. package/src/Carousel/components/TitleSection/components/SubHeaderLeft/SubHeaderLeft.tsx +53 -0
  83. package/src/Carousel/components/TitleSection/components/Title/Title.tsx +46 -0
  84. package/src/Carousel/index.ts +2 -0
  85. package/src/Carousel/testUtils.ts +10 -0
  86. package/src/Chips/Chip.tsx +153 -0
  87. package/src/Chips/ChipGroup.tsx +173 -0
  88. package/src/Chips/SuggestionChip.tsx +15 -0
  89. package/src/Chips/chipTypes.ts +113 -0
  90. package/src/Chips/index.ts +4 -0
  91. package/src/ChoiceListItem/Checkbox.tsx +69 -0
  92. package/src/ChoiceListItem/Radio.tsx +61 -0
  93. package/src/ChoiceListItem/choiceListItem.tsx +99 -0
  94. package/src/ChoiceListItem/common.tsx +148 -0
  95. package/src/ChoiceListItem/index.ts +3 -0
  96. package/src/Collapsible/Collapsible.tsx +58 -0
  97. package/src/Confetti/Confetti.tsx +270 -0
  98. package/src/Confetti/index.ts +2 -0
  99. package/src/ContentPager/ContentPager.tsx +189 -0
  100. package/src/ContentPager/components/Page.tsx +24 -0
  101. package/src/CookieConsent/components/CookieCategoryRow/CookieCategoryRow.tsx +30 -0
  102. package/src/CookieConsent/components/CookieConsent/CookieConsent.tsx +74 -0
  103. package/src/CookieConsent/components/CookieConsentBanner/CookieConsentBanner.tsx +51 -0
  104. package/src/CookieConsent/components/CookieConsentModal/CookieConsentModal.tsx +64 -0
  105. package/src/CookieConsent/hooks/useCookieConsent.ts +170 -0
  106. package/src/CookieConsent/hooks/useCookieConsentState.ts +142 -0
  107. package/src/CookieConsent/index.ts +16 -0
  108. package/src/CookieConsent/types/cookieConsent.types.ts +79 -0
  109. package/src/CookieConsent/types/index.ts +7 -0
  110. package/src/Countdown/Countdown.tsx +161 -0
  111. package/src/Countdown/Countdown.types.ts +4 -0
  112. package/src/Countdown/hooks/useGetCountdown.ts +103 -0
  113. package/src/DateTimeInput/dateInput/DateInput.tsx +199 -0
  114. package/src/DateTimeInput/datePicker/DatePicker.tsx +138 -0
  115. package/src/DateTimeInput/datePicker/components/calendar/Calendar.tsx +72 -0
  116. package/src/DateTimeInput/datePicker/index.ts +2 -0
  117. package/src/DateTimeInput/timeInput/TimeInput.tsx +128 -0
  118. package/src/DateTimeInput/timePicker/TimePicker.tsx +118 -0
  119. package/src/DateTimeInput/timePicker/components/TimePopover/AmPmSwitch.tsx +103 -0
  120. package/src/DateTimeInput/timePicker/components/TimePopover/TimeFieldInput.tsx +26 -0
  121. package/src/DateTimeInput/timePicker/components/TimePopover/TimePopover.tsx +84 -0
  122. package/src/DateTimeInput/timePicker/components/TimePopover/TimePopover.utils.ts +67 -0
  123. package/src/DateTimeInput/timePicker/components/TimePopover/TimePopoverActions.tsx +26 -0
  124. package/src/DateTimeInput/timePicker/index.ts +2 -0
  125. package/src/DateTimeInput/utils/getDisplayDate.ts +15 -0
  126. package/src/DateTimeInput/utils/getDisplayTime.ts +15 -0
  127. package/src/DateTimeInput/utils/index.ts +2 -0
  128. package/src/DateTimeInput/utils/parseTimeValue.ts +54 -0
  129. package/src/Drawer/Drawer.tsx +446 -0
  130. package/src/Drawer/atoms.ts +4 -0
  131. package/src/Drawer/components/DialogActions/DialogActions.tsx +33 -0
  132. package/src/Drawer/components/DialogContent/DialogContent.tsx +80 -0
  133. package/src/Drawer/components/DialogHeader/DialogHeader.tsx +68 -0
  134. package/src/EducationalPopover/EducationalPopover.tsx +174 -0
  135. package/src/FavoriteButton/FavoriteButton.tsx +64 -0
  136. package/src/FavoriteButton/components/IconOnlyFavoriteButton/IconOnlyFavoriteButton.tsx +80 -0
  137. package/src/FavoriteButton/components/LabeledAnimatedFavoriteButton/LabeledAnimatedFavoriteButton.tsx +179 -0
  138. package/src/FavoriteButton/components/LabeledFavoriteButton/LabeledFavoriteButton.tsx +71 -0
  139. package/src/FavoriteButton/components/SmallHeartStraightIcon/SmallHeartStraightIcon.tsx +14 -0
  140. package/src/FavoriteButton/hooks/useFavoriteButtonState.ts +30 -0
  141. package/src/FavoriteButton/index.ts +2 -0
  142. package/src/FavoriteButton/types/favoriteButton.ts +87 -0
  143. package/src/FeatureFlags/devTools/FeatureFlagDevToolsUI.tsx +226 -0
  144. package/src/FeatureFlags/devTools/getFeatureFlagCookieOverrides.ts +30 -0
  145. package/src/FeatureFlags/devTools/utils/cookies.ts +169 -0
  146. package/src/FeatureFlags/hooks/index.ts +2 -0
  147. package/src/FeatureFlags/hooks/useFeatureFlag.tsx +19 -0
  148. package/src/FeatureFlags/hooks/useFeatureFlags.tsx +15 -0
  149. package/src/FileUpload/components/FileCard/FileCard.tsx +50 -0
  150. package/src/FileUpload/components/FileDropzone/FileDropzone.tsx +221 -0
  151. package/src/FileUpload/components/FileDropzone/components/DropzoneContent/DropzoneContent.tsx +28 -0
  152. package/src/FileUpload/components/FileDropzone/components/DropzoneContent/DropzoneText.tsx +81 -0
  153. package/src/FileUpload/components/FileDropzone/components/FileDropzoneDebugger/FileDropzoneDebugger.tsx +40 -0
  154. package/src/FileUpload/components/FileDropzone/components/FileDropzoneDebugger/FileRejectionsDisplay.tsx +110 -0
  155. package/src/FileUpload/components/FileDropzoneOverlay/FileDropzoneOverlay.tsx +183 -0
  156. package/src/FileUpload/components/FileDropzoneOverlay/components/OverlayDropzoneContent.tsx +146 -0
  157. package/src/FileUpload/components/FileDropzoneOverlay/components/OverlayDropzoneDragText.tsx +42 -0
  158. package/src/FileUpload/components/FileDropzoneOverlay/styles.ts +79 -0
  159. package/src/FileUpload/components/FilePreviewList/FilePreviewList.tsx +251 -0
  160. package/src/FileUpload/components/FilePreviewList/virtualizerComponents/FilePreviewVirtualizedList/FilePreviewVirtualizedList.tsx +88 -0
  161. package/src/FileUpload/components/FileUpload/FileUpload.tsx +63 -0
  162. package/src/FileUpload/components/FileUploadCanvas/FileUploadCanvas.tsx +125 -0
  163. package/src/FileUpload/components/GridFileCard/GridFileCard.tsx +364 -0
  164. package/src/FileUpload/components/GridFileCard/utils/sortable.ts +48 -0
  165. package/src/FileUpload/components/ListFileCard/ListFileCard.tsx +259 -0
  166. package/src/FileUpload/components/types.ts +78 -0
  167. package/src/FileUpload/hooks/filePreview/useImageFilePreviewUrl.ts +62 -0
  168. package/src/FileUpload/hooks/index.ts +11 -0
  169. package/src/FileUpload/hooks/upload/useHandleDragEnter/useHandleDragEnter.ts +154 -0
  170. package/src/FileUpload/hooks/upload/useHandleDrop/createFileRejectionHelpers.ts +273 -0
  171. package/src/FileUpload/hooks/upload/useHandleDrop/useHandleDrop.ts +153 -0
  172. package/src/FileUpload/hooks/upload/useUploadAvailability/useUploadAvailability.ts +44 -0
  173. package/src/FileUpload/hooks/validation/createDropzoneValidator.ts +41 -0
  174. package/src/FileUpload/hooks/validation/useFileValidation.ts +25 -0
  175. package/src/FileUpload/hooks/validation/useFileValidationLogic.ts +107 -0
  176. package/src/FileUpload/hooks/validation/useValidationMessages.ts +92 -0
  177. package/src/FileUpload/hooks/validation/useValidationState.ts +171 -0
  178. package/src/FileUpload/index.ts +57 -0
  179. package/src/FileUpload/providers/FileUploadProvider.tsx +219 -0
  180. package/src/FileUpload/providers/UploadValidationProvider.tsx +159 -0
  181. package/src/FileUpload/testUtils/mockFilesAndImages.ts +64 -0
  182. package/src/FileUpload/testUtils/testUtils.ts +111 -0
  183. package/src/FileUpload/types/commonTypes.ts +267 -0
  184. package/src/FileUpload/types/index.ts +31 -0
  185. package/src/FileUpload/types/sharedTypes.ts +159 -0
  186. package/src/FileUpload/utils/constants.ts +79 -0
  187. package/src/FileUpload/utils/createMessageContext.ts +180 -0
  188. package/src/FileUpload/utils/getFileExtensionsFromAcceptedTypes.ts +73 -0
  189. package/src/FileUpload/utils/getFilePluralizationText.ts +68 -0
  190. package/src/FileUpload/utils/getMimeTypes.ts +26 -0
  191. package/src/FileUpload/utils/messageUtils.ts +41 -0
  192. package/src/FileUpload/utils/styles.ts +68 -0
  193. package/src/FormLabel/FormLabel.tsx +212 -0
  194. package/src/IconButton/IconButton.tsx +154 -0
  195. package/src/Icons/CreditCardIcon/CreditCardIcon.tsx +73 -0
  196. package/src/Icons/CreditCardIcon/cardIcons.tsx +270 -0
  197. package/src/Icons/IconBase.tsx +133 -0
  198. package/src/Icons/anyIcon.ts +3 -0
  199. package/src/Icons/generatedIcons/Archive.tsx +48 -0
  200. package/src/Icons/generatedIcons/ArrowClockwise.tsx +48 -0
  201. package/src/Icons/generatedIcons/ArrowDown.tsx +48 -0
  202. package/src/Icons/generatedIcons/ArrowLeft.tsx +48 -0
  203. package/src/Icons/generatedIcons/ArrowRight.tsx +48 -0
  204. package/src/Icons/generatedIcons/ArrowSquareOut.tsx +51 -0
  205. package/src/Icons/generatedIcons/ArrowSquareRight.tsx +51 -0
  206. package/src/Icons/generatedIcons/ArrowUp.tsx +48 -0
  207. package/src/Icons/generatedIcons/ArrowsCounterClockwise.tsx +48 -0
  208. package/src/Icons/generatedIcons/ArrowsLeftRight.tsx +48 -0
  209. package/src/Icons/generatedIcons/ArrowsOutCardinal.tsx +48 -0
  210. package/src/Icons/generatedIcons/Bank.tsx +48 -0
  211. package/src/Icons/generatedIcons/Bell.tsx +51 -0
  212. package/src/Icons/generatedIcons/BookBookmark.tsx +51 -0
  213. package/src/Icons/generatedIcons/BookmarksSimple.tsx +51 -0
  214. package/src/Icons/generatedIcons/Broadcast.tsx +48 -0
  215. package/src/Icons/generatedIcons/CalendarBlank.tsx +48 -0
  216. package/src/Icons/generatedIcons/CalendarStar.tsx +51 -0
  217. package/src/Icons/generatedIcons/Camera.tsx +51 -0
  218. package/src/Icons/generatedIcons/CaretDown.tsx +48 -0
  219. package/src/Icons/generatedIcons/CaretLeft.tsx +48 -0
  220. package/src/Icons/generatedIcons/CaretRight.tsx +48 -0
  221. package/src/Icons/generatedIcons/CaretUp.tsx +48 -0
  222. package/src/Icons/generatedIcons/Certificate.tsx +51 -0
  223. package/src/Icons/generatedIcons/ChartBar.tsx +48 -0
  224. package/src/Icons/generatedIcons/Check.tsx +51 -0
  225. package/src/Icons/generatedIcons/CheckCircle.tsx +48 -0
  226. package/src/Icons/generatedIcons/CirclesFour.tsx +51 -0
  227. package/src/Icons/generatedIcons/Clock.tsx +48 -0
  228. package/src/Icons/generatedIcons/ClockCountdown.tsx +48 -0
  229. package/src/Icons/generatedIcons/Close.tsx +51 -0
  230. package/src/Icons/generatedIcons/CloudArrowUp.tsx +51 -0
  231. package/src/Icons/generatedIcons/CloudWarning.tsx +51 -0
  232. package/src/Icons/generatedIcons/Code.tsx +48 -0
  233. package/src/Icons/generatedIcons/Compass.tsx +51 -0
  234. package/src/Icons/generatedIcons/Confetti.tsx +51 -0
  235. package/src/Icons/generatedIcons/Copy.tsx +48 -0
  236. package/src/Icons/generatedIcons/CornersOut.tsx +48 -0
  237. package/src/Icons/generatedIcons/CreditCard.tsx +48 -0
  238. package/src/Icons/generatedIcons/Crown.tsx +51 -0
  239. package/src/Icons/generatedIcons/CrownSimple.tsx +51 -0
  240. package/src/Icons/generatedIcons/CurrencyCircleDollar.tsx +48 -0
  241. package/src/Icons/generatedIcons/CurrencyDollarSimple.tsx +51 -0
  242. package/src/Icons/generatedIcons/Desktop.tsx +51 -0
  243. package/src/Icons/generatedIcons/Detective.tsx +51 -0
  244. package/src/Icons/generatedIcons/DotOutline.tsx +46 -0
  245. package/src/Icons/generatedIcons/DotsSixVertical.tsx +51 -0
  246. package/src/Icons/generatedIcons/DotsThreeOutline.tsx +51 -0
  247. package/src/Icons/generatedIcons/DotsThreeOutlineVertical.tsx +51 -0
  248. package/src/Icons/generatedIcons/DownloadSimple.tsx +51 -0
  249. package/src/Icons/generatedIcons/EnvelopeSimple.tsx +48 -0
  250. package/src/Icons/generatedIcons/Eraser.tsx +51 -0
  251. package/src/Icons/generatedIcons/Eye.tsx +51 -0
  252. package/src/Icons/generatedIcons/EyeSlash.tsx +51 -0
  253. package/src/Icons/generatedIcons/FacebookLogo.tsx +48 -0
  254. package/src/Icons/generatedIcons/FileArchive.tsx +48 -0
  255. package/src/Icons/generatedIcons/FileArrowDown.tsx +48 -0
  256. package/src/Icons/generatedIcons/FileCsv.tsx +48 -0
  257. package/src/Icons/generatedIcons/FilePdf.tsx +48 -0
  258. package/src/Icons/generatedIcons/FileText.tsx +48 -0
  259. package/src/Icons/generatedIcons/Files.tsx +51 -0
  260. package/src/Icons/generatedIcons/Fire.tsx +51 -0
  261. package/src/Icons/generatedIcons/Flag.tsx +51 -0
  262. package/src/Icons/generatedIcons/FlagBannerFold.tsx +48 -0
  263. package/src/Icons/generatedIcons/FloppyDisk.tsx +51 -0
  264. package/src/Icons/generatedIcons/Gauge.tsx +51 -0
  265. package/src/Icons/generatedIcons/Gavel.tsx +51 -0
  266. package/src/Icons/generatedIcons/Gear.tsx +51 -0
  267. package/src/Icons/generatedIcons/GlobeHemisphereWest.tsx +51 -0
  268. package/src/Icons/generatedIcons/GoogleLogo.tsx +48 -0
  269. package/src/Icons/generatedIcons/GridNine.tsx +51 -0
  270. package/src/Icons/generatedIcons/HandCoins.tsx +51 -0
  271. package/src/Icons/generatedIcons/HandbagSimple.tsx +51 -0
  272. package/src/Icons/generatedIcons/Headset.tsx +51 -0
  273. package/src/Icons/generatedIcons/HeartStraight.tsx +51 -0
  274. package/src/Icons/generatedIcons/HourglassLow.tsx +48 -0
  275. package/src/Icons/generatedIcons/House.tsx +51 -0
  276. package/src/Icons/generatedIcons/Image.tsx +51 -0
  277. package/src/Icons/generatedIcons/ImageSquare.tsx +51 -0
  278. package/src/Icons/generatedIcons/ImagesSquare.tsx +51 -0
  279. package/src/Icons/generatedIcons/Info.tsx +48 -0
  280. package/src/Icons/generatedIcons/InstagramLogo.tsx +51 -0
  281. package/src/Icons/generatedIcons/Lightning.tsx +48 -0
  282. package/src/Icons/generatedIcons/Link.tsx +51 -0
  283. package/src/Icons/generatedIcons/LinkedinLogo.tsx +51 -0
  284. package/src/Icons/generatedIcons/List.tsx +48 -0
  285. package/src/Icons/generatedIcons/Lock.tsx +51 -0
  286. package/src/Icons/generatedIcons/LockOpen.tsx +51 -0
  287. package/src/Icons/generatedIcons/MagnifyingGlass.tsx +48 -0
  288. package/src/Icons/generatedIcons/MapPin.tsx +51 -0
  289. package/src/Icons/generatedIcons/MapPinSimpleArea.tsx +48 -0
  290. package/src/Icons/generatedIcons/Medal.tsx +48 -0
  291. package/src/Icons/generatedIcons/Megaphone.tsx +48 -0
  292. package/src/Icons/generatedIcons/Minus.tsx +45 -0
  293. package/src/Icons/generatedIcons/Money.tsx +51 -0
  294. package/src/Icons/generatedIcons/Notches.tsx +48 -0
  295. package/src/Icons/generatedIcons/NotePencil.tsx +48 -0
  296. package/src/Icons/generatedIcons/Package.tsx +51 -0
  297. package/src/Icons/generatedIcons/PaintBrush.tsx +51 -0
  298. package/src/Icons/generatedIcons/PaperPlaneTilt.tsx +51 -0
  299. package/src/Icons/generatedIcons/Paperclip.tsx +51 -0
  300. package/src/Icons/generatedIcons/Pause.tsx +51 -0
  301. package/src/Icons/generatedIcons/PencilLine.tsx +51 -0
  302. package/src/Icons/generatedIcons/PencilRuler.tsx +51 -0
  303. package/src/Icons/generatedIcons/PencilSimple.tsx +51 -0
  304. package/src/Icons/generatedIcons/Phone.tsx +51 -0
  305. package/src/Icons/generatedIcons/PinterestLogo.tsx +51 -0
  306. package/src/Icons/generatedIcons/Play.tsx +51 -0
  307. package/src/Icons/generatedIcons/Plus.tsx +51 -0
  308. package/src/Icons/generatedIcons/PlusCircle.tsx +48 -0
  309. package/src/Icons/generatedIcons/Printer.tsx +51 -0
  310. package/src/Icons/generatedIcons/Question.tsx +48 -0
  311. package/src/Icons/generatedIcons/Receipt.tsx +51 -0
  312. package/src/Icons/generatedIcons/Rows.tsx +51 -0
  313. package/src/Icons/generatedIcons/SealCheck.tsx +51 -0
  314. package/src/Icons/generatedIcons/SelectionSlash.tsx +48 -0
  315. package/src/Icons/generatedIcons/ShareNetwork.tsx +51 -0
  316. package/src/Icons/generatedIcons/ShieldCheck.tsx +51 -0
  317. package/src/Icons/generatedIcons/ShieldStar.tsx +51 -0
  318. package/src/Icons/generatedIcons/ShoppingCart.tsx +48 -0
  319. package/src/Icons/generatedIcons/ShuffleAngular.tsx +48 -0
  320. package/src/Icons/generatedIcons/SidebarSimple.tsx +48 -0
  321. package/src/Icons/generatedIcons/SlidersHorizontal.tsx +51 -0
  322. package/src/Icons/generatedIcons/Smiley.tsx +48 -0
  323. package/src/Icons/generatedIcons/Sparkle.tsx +51 -0
  324. package/src/Icons/generatedIcons/SpinnerGap.tsx +48 -0
  325. package/src/Icons/generatedIcons/StackPlus.tsx +48 -0
  326. package/src/Icons/generatedIcons/Star.tsx +51 -0
  327. package/src/Icons/generatedIcons/Storefront.tsx +51 -0
  328. package/src/Icons/generatedIcons/Swap.tsx +51 -0
  329. package/src/Icons/generatedIcons/Tag.tsx +51 -0
  330. package/src/Icons/generatedIcons/ThumbsDown.tsx +48 -0
  331. package/src/Icons/generatedIcons/ThumbsUp.tsx +48 -0
  332. package/src/Icons/generatedIcons/Toolbox.tsx +48 -0
  333. package/src/Icons/generatedIcons/Trash.tsx +48 -0
  334. package/src/Icons/generatedIcons/TrendUp.tsx +48 -0
  335. package/src/Icons/generatedIcons/Trophy.tsx +51 -0
  336. package/src/Icons/generatedIcons/Truck.tsx +51 -0
  337. package/src/Icons/generatedIcons/UploadSimple.tsx +51 -0
  338. package/src/Icons/generatedIcons/User.tsx +48 -0
  339. package/src/Icons/generatedIcons/Users.tsx +48 -0
  340. package/src/Icons/generatedIcons/UsersThree.tsx +51 -0
  341. package/src/Icons/generatedIcons/VideoCamera.tsx +51 -0
  342. package/src/Icons/generatedIcons/Warning.tsx +51 -0
  343. package/src/Icons/generatedIcons/WarningCircle.tsx +48 -0
  344. package/src/Icons/generatedIcons/WifiHigh.tsx +51 -0
  345. package/src/Icons/generatedIcons/XCircle.tsx +48 -0
  346. package/src/Icons/generatedIcons/XLogo.tsx +48 -0
  347. package/src/Icons/generatedIcons/YoutubeLogo.tsx +51 -0
  348. package/src/Icons/importedIcons.ts +152 -0
  349. package/src/Icons/index.ts +149 -0
  350. package/src/Icons/socialIcons/appleSocialIcon.tsx +50 -0
  351. package/src/Icons/socialIcons/facebookSocialIcon.tsx +41 -0
  352. package/src/Icons/socialIcons/googleSocialIcon.tsx +134 -0
  353. package/src/ImageCluster/ImageCluster.tsx +125 -0
  354. package/src/ImageSlider/ImageSlider.tsx +582 -0
  355. package/src/ImageSlider/ImageSlider.types.ts +90 -0
  356. package/src/ImageSlider/components/IndexIndicator/IndexIndicator.tsx +21 -0
  357. package/src/ImageSlider/components/NavigationButtons/NavigationButtons.tsx +113 -0
  358. package/src/ImageSlider/components/ResponsiveImage/ResponsiveImage.tsx +114 -0
  359. package/src/ImageSlider/components/ResponsiveImage/index.ts +1 -0
  360. package/src/ImageSlider/components/Thumbnails/Thumbnails.tsx +184 -0
  361. package/src/ImageSlider/constants.ts +59 -0
  362. package/src/ImageSlider/hooks/index.ts +3 -0
  363. package/src/ImageSlider/hooks/useImageSlider.ts +57 -0
  364. package/src/ImageSlider/hooks/useImageSliderNavigation.ts +133 -0
  365. package/src/ImageSlider/hooks/useImageSliderScrollHandler.ts +171 -0
  366. package/src/ImageSlider/index.ts +3 -0
  367. package/src/ImageSlider/utils/imageOptimization.ts +97 -0
  368. package/src/ImageSlider/utils/index.ts +1 -0
  369. package/src/InlineNotification/InlineNotification.tsx +95 -0
  370. package/src/JumpMenu/JumpMenu.tsx +395 -0
  371. package/src/JumpMenu/components/JumpMenuItem/JumpMenuItem.tsx +62 -0
  372. package/src/JumpMenu/hooks/useContainerTracking.ts +171 -0
  373. package/src/JumpMenu/hooks/useIntersectionObserver.ts +77 -0
  374. package/src/JumpMenu/hooks/useKeyboardNavigation.ts +102 -0
  375. package/src/JumpMenu/hooks/useResizeObserver.ts +53 -0
  376. package/src/JumpMenu/hooks/useSectionObserver.ts +102 -0
  377. package/src/JumpMenu/index.ts +2 -0
  378. package/src/JumpMenu/types/index.ts +19 -0
  379. package/src/Loading/Loading.tsx +39 -0
  380. package/src/Loading/components/LoadingDot/LoadingDot.tsx +16 -0
  381. package/src/LoadingSpinner/LoadingSpinner.tsx +20 -0
  382. package/src/Menu/Menu.tsx +372 -0
  383. package/src/Menu/components/MenuDivider/MenuDivider.tsx +5 -0
  384. package/src/Menu/components/MenuItem/MenuItem.tsx +298 -0
  385. package/src/Menu/context/menuContext.tsx +20 -0
  386. package/src/Menu/hooks/useMenu.tsx +18 -0
  387. package/src/Menu/index.ts +3 -0
  388. package/src/Modal/ComposableModal.tsx +313 -0
  389. package/src/Modal/Modal.tsx +231 -0
  390. package/src/Modal/components/BackButton/BackButton.tsx +43 -0
  391. package/src/Modal/components/Backdrop/Backdrop.tsx +62 -0
  392. package/src/Modal/components/CloseButton/CloseButton.tsx +55 -0
  393. package/src/Modal/components/ModalActions/ModalActions.tsx +135 -0
  394. package/src/Modal/components/ModalContent/ModalContent.tsx +163 -0
  395. package/src/Modal/components/ModalHeader/ModalHeader.tsx +84 -0
  396. package/src/Modal/components/ModalHeader/hooks/useHeaderAnimation.tsx +49 -0
  397. package/src/Modal/components/ModalProgressSteps/ModalProgressSteps.tsx +26 -0
  398. package/src/Modal/components/ModalSubTitle/ModalSubTitle.tsx +29 -0
  399. package/src/Modal/components/ModalTitle/ModalTitle.tsx +22 -0
  400. package/src/Modal/components/PreventModalScroll/PreventModalScroll.tsx +106 -0
  401. package/src/Modal/components/index.ts +12 -0
  402. package/src/Modal/context.ts +33 -0
  403. package/src/Modal/hooks/useCloseModal.ts +133 -0
  404. package/src/NotificationBadge/NotificationBadge.tsx +34 -0
  405. package/src/Pagination/AdvancedPagination.tsx +48 -0
  406. package/src/Pagination/Pagination.tsx +216 -0
  407. package/src/Pagination/components/AdvancedPaginator/AdvancedPaginator.tsx +52 -0
  408. package/src/Pagination/components/AdvancedPaginator/components/PageSelect/PageSelect.tsx +43 -0
  409. package/src/Pagination/components/ItemCountDisplay/ItemCountDisplay.tsx +32 -0
  410. package/src/Pagination/components/ItemCountSelect/ItemCountSelect.tsx +33 -0
  411. package/src/Pagination/index.tsx +3 -0
  412. package/src/Pagination/paginationProvider.tsx +234 -0
  413. package/src/Pagination/utils.tsx +36 -0
  414. package/src/PhoneInput/PhoneInput.tsx +509 -0
  415. package/src/PhoneInput/useDropdownLogic.tsx +163 -0
  416. package/src/ProgressCircle/ProgressCircle.tsx +246 -0
  417. package/src/ProgressCircle/hooks/useProgressStatusTransitions.ts +49 -0
  418. package/src/ProgressCircle/utils/progressCircle.constants.ts +27 -0
  419. package/src/ProgressSteps/ProgressSteps.tsx +160 -0
  420. package/src/SaveConfetti/SaveConfetti.tsx +277 -0
  421. package/src/SaveConfetti/index.ts +2 -0
  422. package/src/SearchInput/SearchInput.tsx +236 -0
  423. package/src/SegmentedControl/SegmentedControl.tsx +111 -0
  424. package/src/SegmentedControl/SegmentedControlGroup.tsx +94 -0
  425. package/src/SegmentedControl/index.ts +4 -0
  426. package/src/Select/Select.tsx +154 -0
  427. package/src/Select/SelectAsync.tsx +13 -0
  428. package/src/Select/SelectAsyncCreatable.tsx +14 -0
  429. package/src/Select/SelectCreatable.tsx +12 -0
  430. package/src/Select/reexportedComponents.tsx +5 -0
  431. package/src/Select/selectComponents.tsx +306 -0
  432. package/src/Skeleton/Skeleton.tsx +13 -0
  433. package/src/SplitButton/SplitButton.tsx +298 -0
  434. package/src/SplitButton/SplitButtonTrigger.tsx +55 -0
  435. package/src/StarRating/StarRating.tsx +165 -0
  436. package/src/StarRating/components/StarComponent/StarComponent.tsx +44 -0
  437. package/src/Table/Table.tsx +474 -0
  438. package/src/Table/components/TableHeader/TableHeader.tsx +166 -0
  439. package/src/Table/components/TablePagination/TablePagination.tsx +18 -0
  440. package/src/Table/components/TablePagination/components/ItemCountDisplay/ItemCountDisplay.tsx +17 -0
  441. package/src/Table/components/TablePagination/components/ItemCountSelect/ItemCountSelect.tsx +31 -0
  442. package/src/Table/components/TablePagination/components/TablePaginator/TablePaginator.tsx +37 -0
  443. package/src/Table/components/TablePagination/components/TablePaginator/components/PageSelect/PageSelect.tsx +32 -0
  444. package/src/Table/components/TableRow/TableRows.tsx +147 -0
  445. package/src/Table/components/TableRow/components/TableRowCell/TableRowCell.tsx +49 -0
  446. package/src/Table/components/TableShadow/TableShadow.tsx +46 -0
  447. package/src/Table/index.ts +2 -0
  448. package/src/Table/sharedState.ts +30 -0
  449. package/src/Table/sharedStyles.ts +1 -0
  450. package/src/Table/types.ts +55 -0
  451. package/src/Tabs/Tabs.tsx +358 -0
  452. package/src/TextArea/TextArea.tsx +157 -0
  453. package/src/TextInput/TextInput.tsx +173 -0
  454. package/src/Toast/Toast.tsx +64 -0
  455. package/src/Toast/components/ToastContainer/ToastContainer.tsx +48 -0
  456. package/src/Toast/index.ts +2 -0
  457. package/src/Toast/types/role.ts +1 -0
  458. package/src/Toast/utils/getIcon.tsx +41 -0
  459. package/src/ToggleSwitch/ToggleSwitch.tsx +188 -0
  460. package/src/Tooltip/InfoIconTooltip.tsx +47 -0
  461. package/src/Tooltip/Tooltip.tsx +41 -0
  462. package/src/Typography/InlineButton/InlineButton.tsx +166 -0
  463. package/src/Typography/Links/Links.tsx +113 -0
  464. package/src/Typography/Text/Text.tsx +239 -0
  465. package/src/ViewMore/ViewMore.tsx +226 -0
  466. package/src/WebRTCPlayer/WebRTCPlayer.tsx +325 -0
  467. package/src/WebRTCPlayer/adaptor/NativeWebRTCAdaptor.ts +588 -0
  468. package/src/WebRTCPlayer/hooks/useWebRTCStream.ts +571 -0
  469. package/src/WebRTCPlayer/index.ts +22 -0
  470. package/src/WebRTCPlayer/types.ts +95 -0
  471. package/src/breakpoints/index.tsx +1 -0
  472. package/src/breakpoints/utils.tsx +50 -0
  473. package/src/declarations.d.ts +7 -0
  474. package/src/grid/gridHighlighter.tsx +83 -0
  475. package/src/grid/index.ts +3 -0
  476. package/src/grid/pageGrid.tsx +37 -0
  477. package/src/grid/useSubGridCSS.tsx +214 -0
  478. package/src/hooks/useHorizontalScrollFade.ts +44 -0
  479. package/src/hooks/usePrevious.ts +14 -0
  480. package/src/index.ts +351 -0
  481. package/src/intl/index.ts +4 -0
  482. package/src/intl/utils.ts +67 -0
  483. package/src/mixins/horizontalScrollFadeMixin.ts +56 -0
  484. package/src/mixins/index.ts +18 -0
  485. package/src/mixins/propMixins.ts +389 -0
  486. package/src/providers/createContextProvider.ts +22 -0
  487. package/src/providers/designSystemProvider.tsx +218 -0
  488. package/src/providers/errorBoundaryProvider.tsx +179 -0
  489. package/src/providers/featureFlagProvider.tsx +18 -0
  490. package/src/providers/gridSizeProvider.tsx +23 -0
  491. package/src/providers/index.ts +12 -0
  492. package/src/providers/linkProvider.tsx +32 -0
  493. package/src/providers/normalize.tsx +93 -0
  494. package/src/providers/targets/DatePickerTarget.tsx +10 -0
  495. package/src/providers/targets/ModalTarget.tsx +14 -0
  496. package/src/providers/targets/TimePickerTarget.tsx +10 -0
  497. package/src/providers/themeContext.tsx +24 -0
  498. package/src/providers/windowSizeProvider.tsx +125 -0
  499. package/src/spacing/index.ts +1 -0
  500. package/src/spacing/spacing.ts +11 -0
  501. package/src/utils/countriesWithISOCodes.ts +1419 -0
  502. package/src/utils/dateTimeFormat.ts +257 -0
  503. package/src/utils/effectEventListener.ts +11 -0
  504. package/src/utils/formatFileSize.ts +18 -0
  505. package/src/utils/isClientSide.ts +1 -0
  506. package/src/utils/keepTransition.ts +15 -0
  507. package/src/utils/nodeEnv.ts +9 -0
  508. package/src/utils/smoothScrollTo.ts +47 -0
  509. package/src/utils/utilityTypes.ts +13 -0
@@ -0,0 +1,277 @@
1
+ import { forwardRef, useEffect, useImperativeHandle, useRef, useState } from 'react';
2
+ import { createPortal } from 'react-dom';
3
+
4
+ // Physics constants authored at 60 fps; frameScale normalizes to any refresh rate.
5
+ const TARGET_FRAME_MS = 1000 / 60;
6
+ const PARTICLE_COUNT = 16;
7
+ const TRAVEL_MIN = 50;
8
+ const TRAVEL_MAX = 90;
9
+ // Downward gravity bias added on top of radial travel (px)
10
+ const GRAVITY_DROP = 18;
11
+ const DURATION_MIN = 650;
12
+ const DURATION_MAX = 950;
13
+ // ±radians of angle jitter per particle
14
+ const ANGLE_JITTER = 0.2;
15
+ // Roughly 40% of hearts are outlined
16
+ const OUTLINED_HEART_RATIO = 0.4;
17
+
18
+ // CSS custom property names from the theme system (space-separated RGB, Tailwind format).
19
+ // Resolved at mount time via getComputedStyle so the canvas always uses the active theme values.
20
+ const COLOR_TOKENS = [
21
+ '--color-critical-500',
22
+ '--color-critical-300',
23
+ '--color-critical-200',
24
+ '--color-tertiary-400',
25
+ '--color-tertiary-200',
26
+ ] as const;
27
+
28
+ // Per-token fallbacks so particles remain visually distinct if CSS variables fail to resolve.
29
+ const FALLBACK_COLORS = ['#CB3A2C', '#E24B4A', '#F09595', '#D4537E', '#EF9F27'] as const;
30
+
31
+ const resolveColors = (): readonly string[] => {
32
+ const computed = getComputedStyle(document.documentElement);
33
+ return COLOR_TOKENS.map((token, i) => {
34
+ const raw = computed.getPropertyValue(token).trim();
35
+ if (!raw) {
36
+ return FALLBACK_COLORS[i];
37
+ }
38
+ // CSS vars use space-separated RGB ("204 47 40"). Normalise to rgb(r, g, b) with
39
+ // commas so canvas fillStyle recognises it in all browsers (CSS1/2/3 compat;
40
+ // CSS4 space-separated syntax is silently ignored by some canvas implementations).
41
+ const parts = raw.split(/\s+/);
42
+ return parts.length === 3 ? `rgb(${parts.join(', ')})` : FALLBACK_COLORS[i];
43
+ });
44
+ };
45
+
46
+ type ParticleShape = 'circle' | 'heart-filled' | 'heart-outlined';
47
+
48
+ type Particle = {
49
+ angle: number;
50
+ color: string;
51
+ duration: number;
52
+ opacity: number;
53
+ /** Normalized elapsed time [0, 1] within the particle's own duration */
54
+ progress: number;
55
+ shape: ParticleShape;
56
+ /** px — circle radius or heart bounding half-size */
57
+ size: number;
58
+ startX: number;
59
+ startY: number;
60
+ travel: number;
61
+ };
62
+
63
+ export type SaveConfettiHandle = {
64
+ /** Trigger a mini confetti burst originating from the center of `anchor`. */
65
+ fire: (anchor: HTMLElement) => void;
66
+ };
67
+
68
+ /** Draw a heart path centered at (0, 0) with the given half-size. */
69
+ const drawHeartPath = (ctx: CanvasRenderingContext2D, halfSize: number) => {
70
+ const s = halfSize;
71
+ ctx.beginPath();
72
+ ctx.moveTo(0, s * 0.4);
73
+ ctx.bezierCurveTo(-s * 0.1, s * 0.1, -s, -s * 0.3, -s, -s * 0.6);
74
+ ctx.bezierCurveTo(-s, -s * 1.1, 0, -s * 0.9, 0, -s * 0.5);
75
+ ctx.bezierCurveTo(0, -s * 0.9, s, -s * 1.1, s, -s * 0.6);
76
+ ctx.bezierCurveTo(s, -s * 0.3, s * 0.1, s * 0.1, 0, s * 0.4);
77
+ ctx.closePath();
78
+ };
79
+
80
+ const randomBetween = (min: number, max: number) => Math.random() * (max - min) + min;
81
+
82
+ const createParticle = (anchorRect: DOMRect, angleIndex: number, colors: readonly string[]): Particle => {
83
+ const baseAngle = (angleIndex / PARTICLE_COUNT) * Math.PI * 2;
84
+ const angle = baseAngle + randomBetween(-ANGLE_JITTER, ANGLE_JITTER);
85
+
86
+ const heartRoll = Math.random();
87
+ let shape: ParticleShape;
88
+ if (heartRoll < OUTLINED_HEART_RATIO) {
89
+ shape = 'heart-outlined';
90
+ } else if (heartRoll < 0.7) {
91
+ shape = 'heart-filled';
92
+ } else {
93
+ shape = 'circle';
94
+ }
95
+
96
+ const size = shape === 'circle' ? randomBetween(2.5, 5.5) : randomBetween(11, 16) / 2;
97
+
98
+ return {
99
+ angle,
100
+ color: colors[Math.floor(Math.random() * colors.length)],
101
+ duration: randomBetween(DURATION_MIN, DURATION_MAX),
102
+ opacity: 1,
103
+ progress: 0,
104
+ shape,
105
+ size,
106
+ startX: anchorRect.left + anchorRect.width / 2,
107
+ startY: anchorRect.top + anchorRect.height / 2,
108
+ travel: randomBetween(TRAVEL_MIN, TRAVEL_MAX),
109
+ };
110
+ };
111
+
112
+ /**
113
+ * Canvas-based mini confetti burst for the Save / FavoriteButton animated variant.
114
+ *
115
+ * Renders a fixed, pointer-events-none overlay canvas. Trigger a burst by calling
116
+ * `ref.current.fire(buttonElement)`. The animation runs entirely outside React's
117
+ * render cycle via requestAnimationFrame (tickRef pattern).
118
+ *
119
+ * Architecture mirrors `@evolve.ui/core-components/confetti` — canvas + rAF,
120
+ * tickRef loop, frameScale normalization, createPortal, DPR scaling.
121
+ * Physics differ: 16 heart/circle particles radiate outward from button center.
122
+ *
123
+ * @example
124
+ * ```tsx
125
+ * const confettiRef = useRef<SaveConfettiHandle>(null);
126
+ * confettiRef.current?.fire(buttonElement);
127
+ * return <SaveConfetti ref={confettiRef} />;
128
+ * ```
129
+ */
130
+ export const SaveConfetti = forwardRef<SaveConfettiHandle>((_, ref) => {
131
+ const canvasRef = useRef<HTMLCanvasElement>(null);
132
+ const canvasContextRef = useRef<CanvasRenderingContext2D | null>(null);
133
+ const particlesRef = useRef<Particle[]>([]);
134
+ const animationFrameRef = useRef<number | null>(null);
135
+ const lastTimestampRef = useRef<number>(0);
136
+ // Colors resolved once at first canvas setup (guarantees DOM + stylesheets are ready)
137
+ const colorsRef = useRef<readonly string[]>([]);
138
+
139
+ // SSR guard: returns null until client has mounted (canvas APIs unavailable server-side)
140
+ const [mounted, setMounted] = useState(false);
141
+
142
+ // tickRef holds the rAF loop so it can recurse without closure staleness.
143
+ // Assigning on every render means the loop always sees the latest refs — intentional.
144
+ const tickRef = useRef<(timestamp: number) => void>(() => {});
145
+ tickRef.current = (timestamp: number) => {
146
+ const ctx = canvasContextRef.current;
147
+ if (!ctx) {
148
+ return;
149
+ }
150
+
151
+ // Normalize physics to 60fps. Cap at 2× so a tab-switch pause doesn't teleport particles.
152
+ const frameScale =
153
+ lastTimestampRef.current === 0 ? 1 : Math.min((timestamp - lastTimestampRef.current) / TARGET_FRAME_MS, 2);
154
+ lastTimestampRef.current = timestamp;
155
+
156
+ ctx.clearRect(0, 0, window.innerWidth, window.innerHeight);
157
+
158
+ particlesRef.current = particlesRef.current.filter((p) => p.progress < 1);
159
+
160
+ for (const particle of particlesRef.current) {
161
+ const progressDelta = (frameScale * TARGET_FRAME_MS) / particle.duration;
162
+ particle.progress = Math.min(particle.progress + progressDelta, 1);
163
+ const t = particle.progress;
164
+
165
+ // Ease-out cubic approximation of cubic-bezier(0.16, 1, 0.3, 1)
166
+ const eased = 1 - Math.pow(1 - t, 3);
167
+
168
+ // Radial position + downward gravity component
169
+ const x = particle.startX + Math.cos(particle.angle) * particle.travel * eased;
170
+ const y = particle.startY + Math.sin(particle.angle) * particle.travel * eased + GRAVITY_DROP * eased;
171
+
172
+ // Scale curve: 0.2 → 1 (first half) → 0.55 (second half)
173
+ const scale = t < 0.5 ? 0.2 + (1 - 0.2) * (t / 0.5) : 1 - (1 - 0.55) * ((t - 0.5) / 0.5);
174
+
175
+ // Opacity: holds at 1 for first 70%, fades over last 30%
176
+ const opacity = t < 0.7 ? 1 : 1 - (t - 0.7) / 0.3;
177
+
178
+ ctx.save();
179
+ ctx.translate(x, y);
180
+ ctx.globalAlpha = Math.max(0, opacity);
181
+ ctx.fillStyle = particle.color;
182
+ ctx.strokeStyle = particle.color;
183
+ ctx.lineWidth = 1.5;
184
+
185
+ if (particle.shape === 'circle') {
186
+ ctx.beginPath();
187
+ ctx.arc(0, 0, particle.size * scale, 0, Math.PI * 2);
188
+ ctx.fill();
189
+ } else {
190
+ ctx.scale(scale, scale);
191
+ drawHeartPath(ctx, particle.size);
192
+ if (particle.shape === 'heart-outlined') {
193
+ ctx.stroke();
194
+ } else {
195
+ ctx.fill();
196
+ }
197
+ }
198
+
199
+ ctx.restore();
200
+ }
201
+
202
+ if (particlesRef.current.length > 0) {
203
+ animationFrameRef.current = requestAnimationFrame(tickRef.current);
204
+ } else {
205
+ animationFrameRef.current = null;
206
+ lastTimestampRef.current = 0;
207
+ }
208
+ };
209
+
210
+ useImperativeHandle(ref, () => ({
211
+ fire(anchor: HTMLElement) {
212
+ if (!canvasRef.current) {
213
+ return;
214
+ }
215
+ // Resolve colors on first fire (guarantees document styles are fully loaded)
216
+ if (colorsRef.current.length === 0) {
217
+ colorsRef.current = resolveColors();
218
+ }
219
+ const rect = anchor.getBoundingClientRect();
220
+ for (let i = 0; i < PARTICLE_COUNT; i++) {
221
+ particlesRef.current.push(createParticle(rect, i, colorsRef.current));
222
+ }
223
+ if (animationFrameRef.current === null) {
224
+ lastTimestampRef.current = 0;
225
+ animationFrameRef.current = requestAnimationFrame(tickRef.current);
226
+ }
227
+ },
228
+ }));
229
+
230
+ useEffect(() => {
231
+ setMounted(true);
232
+
233
+ const canvas = canvasRef.current;
234
+ if (!canvas) {
235
+ return;
236
+ }
237
+
238
+ const setupCanvas = () => {
239
+ if (!canvasRef.current) {
240
+ return;
241
+ }
242
+ const dpr = window.devicePixelRatio ?? 1;
243
+ canvasRef.current.width = window.innerWidth * dpr;
244
+ canvasRef.current.height = window.innerHeight * dpr;
245
+ const ctx = canvasRef.current.getContext('2d');
246
+ ctx?.scale(dpr, dpr);
247
+ canvasContextRef.current = ctx;
248
+ };
249
+
250
+ setupCanvas();
251
+
252
+ window.addEventListener('resize', setupCanvas);
253
+ return () => {
254
+ window.removeEventListener('resize', setupCanvas);
255
+ if (animationFrameRef.current !== null) {
256
+ cancelAnimationFrame(animationFrameRef.current);
257
+ }
258
+ };
259
+ }, [mounted]);
260
+
261
+ if (!mounted) {
262
+ return null;
263
+ }
264
+
265
+ return createPortal(
266
+ <canvas
267
+ aria-hidden="true"
268
+ className="pointer-events-none fixed inset-0 z-[9999] h-screen w-screen"
269
+ data-hui-id="SaveConfetti"
270
+ data-testid="save-confetti-canvas"
271
+ ref={canvasRef}
272
+ />,
273
+ document.body
274
+ );
275
+ });
276
+
277
+ SaveConfetti.displayName = 'SaveConfetti';
@@ -0,0 +1,2 @@
1
+ export { SaveConfetti } from './SaveConfetti';
2
+ export type { SaveConfettiHandle } from './SaveConfetti';
@@ -0,0 +1,236 @@
1
+ import { cn } from '@evolve.ui/theme-system';
2
+ import { FormEventHandler, ReactNode, RefObject, useCallback, useEffect, useState } from 'react';
3
+
4
+ import { IconButton } from '../IconButton/IconButton';
5
+ import { MagnifyingGlass } from '../Icons';
6
+ import { IconWeight } from '../Icons/IconBase';
7
+ import { TextInput } from '../TextInput/TextInput';
8
+
9
+ type Props = {
10
+ /**
11
+ * Changes the aria label for the `<button>` element
12
+ *
13
+ * @default 'Search button'
14
+ */
15
+ 'button-aria-label'?: string;
16
+ className?: string;
17
+ /**
18
+ * Allows you to add a data-testid to the component
19
+ */
20
+ ['data-testid']?: string;
21
+ /**
22
+ * If true, the search input will be disabled
23
+ */
24
+ disabled?: boolean;
25
+ /**
26
+ * Input emphasis. Currently supports subtle and bold. Defaults to subtle.
27
+ */
28
+ emphasis?: 'subtle' | 'bold';
29
+ /**
30
+ * Custom content rendered inside the input on the right, before the search button
31
+ * (e.g. an extra action icon).
32
+ */
33
+ endAdornment?: ReactNode;
34
+ /**
35
+ * Style variant for the icon. Can be either 'regular' (default), 'bold', 'fill', or 'duotone'.
36
+ */
37
+ iconStyle?: IconWeight;
38
+ /**
39
+ * Allows you to edit the input id
40
+ *
41
+ * @default 'search-input'
42
+ */
43
+ id?: string;
44
+ /**
45
+ * Set an initial value to pass through
46
+ *
47
+ * @default ''
48
+ */
49
+ initialValue?: string;
50
+ /**
51
+ * Changes the aria label for the `<input>` element
52
+ *
53
+ * @default 'Search input'
54
+ */
55
+ 'input-aria-label'?: string;
56
+ /**
57
+ * Ref for the input element
58
+ */
59
+ inputRef?: RefObject<HTMLInputElement>;
60
+ /**
61
+ * Maximum number of characters allowed in the input.
62
+ * Uses the native HTML maxLength attribute.
63
+ */
64
+ maxLength?: number;
65
+ /**
66
+ * Callback that triggers when the input loses focus
67
+ */
68
+ onBlur?: () => void;
69
+ /**
70
+ * Callback that triggers when you press the clear button
71
+ */
72
+ onClear?: () => void;
73
+ /**
74
+ * Callback that triggers when the input gains focus
75
+ */
76
+ onFocus?: () => void;
77
+ /**
78
+ * Callback that triggers when you submit (press enter or button)
79
+ */
80
+ onSubmit?: (searchString: string) => void;
81
+ /**
82
+ * Callback that triggers when you type
83
+ */
84
+ onTextChange?: (searchString: string) => void;
85
+ /**
86
+ * Allows you to edit the placeholder text
87
+ *
88
+ * @default 'Search'
89
+ */
90
+ placeholder?: string;
91
+ /**
92
+ * Show in the small size vs the medium one
93
+ */
94
+ small?: boolean;
95
+ /**
96
+ * Style variant for the input. Can be either 'neutral' (default) or 'inverse' for dark backgrounds.
97
+ */
98
+ style?: 'neutral' | 'inverse';
99
+
100
+ /**
101
+ * Controlled value for the input
102
+ * If provided, initialValue will be ignored
103
+ */
104
+ value?: string;
105
+ };
106
+
107
+ export const SearchInput = ({
108
+ 'button-aria-label': buttonAriaLabel = 'Search',
109
+ className,
110
+ 'data-testid': testId = 'search-input',
111
+ disabled = false,
112
+ emphasis,
113
+ endAdornment,
114
+ iconStyle,
115
+ id = 'search-input',
116
+ initialValue = '',
117
+ 'input-aria-label': inputAriaLabel = 'Search input',
118
+ inputRef,
119
+ maxLength,
120
+ onBlur,
121
+ onClear: onClearProp,
122
+ onFocus,
123
+ onSubmit: onSubmitProp,
124
+ onTextChange,
125
+ placeholder = 'Search',
126
+ small = false,
127
+ style,
128
+ value,
129
+ }: Props) => {
130
+ const [search, setSearch] = useState(value ?? initialValue);
131
+
132
+ // Add effect to sync with controlled value when it changes
133
+ useEffect(() => {
134
+ if (value !== undefined) {
135
+ setSearch(value);
136
+ }
137
+ }, [value]);
138
+
139
+ const setSearchText = useCallback(
140
+ (s: string) => {
141
+ onTextChange?.(s);
142
+ setSearch(s);
143
+ },
144
+ [onTextChange]
145
+ );
146
+
147
+ const onChange = useCallback<FormEventHandler<HTMLInputElement>>(
148
+ (e) => {
149
+ setSearchText(e.currentTarget.value);
150
+ },
151
+ [setSearchText]
152
+ );
153
+
154
+ const onClear = useCallback(() => {
155
+ onClearProp?.();
156
+ setSearchText('');
157
+ }, [setSearchText, onClearProp]);
158
+
159
+ const onSubmit = useCallback<FormEventHandler<HTMLFormElement>>(
160
+ (e) => {
161
+ onSubmitProp?.(search);
162
+ e.preventDefault();
163
+ },
164
+ [onSubmitProp, search]
165
+ );
166
+
167
+ return (
168
+ <div className={cn('rounded-search-input bg-background-primary', className)}>
169
+ <form
170
+ className={cn(
171
+ 'overflow-none box-content flex items-center gap-2xs rounded-search-input border border-border-secondary bg-background-primary outline-1 outline-background-critical-dark hover:border-border-hover has-[:focus]:border-border-selected',
172
+ {
173
+ 'border-0': emphasis === 'bold',
174
+ 'h-[32px]': small, // Smaller due to box-content to prevent clipping
175
+ 'h-[40px]': !small, // Smaller due to box-content to prevent clipping
176
+ 'outline outline-1 outline-border-black': emphasis === 'bold' && style === 'neutral',
177
+ },
178
+ // Hover Styles
179
+ {
180
+ 'hover:border-border-secondary hover:bg-background-hover hover:outline hover:outline-2 hover:outline-border-black':
181
+ emphasis === 'bold',
182
+ 'hover:outline-border-black': style === 'neutral' && emphasis === 'bold',
183
+ 'hover:outline-focus-inverse': style === 'inverse',
184
+ },
185
+ // Focus Styles
186
+ {
187
+ 'has-[:focus]:border-border-secondary has-[:focus]:bg-background-primary has-[:focus]:outline has-[:focus]:outline-focus-inverse':
188
+ emphasis === 'bold',
189
+ 'has-[:focus]:outline-2 has-[:focus]:outline-border-black':
190
+ style === 'neutral' && emphasis === 'bold',
191
+ 'has-[:focus]:outline-4 has-[:focus]:outline-focus-inverse': style === 'inverse',
192
+ }
193
+ )}
194
+ data-hui-id="SearchInput"
195
+ data-testid={testId}
196
+ onSubmit={onSubmit}
197
+ >
198
+ <TextInput
199
+ aria-label={inputAriaLabel}
200
+ autoComplete="off"
201
+ className={cn('w-full [&>div]:!border-transparent [&>div]:!bg-transparent')}
202
+ clearAriaLabel="Clear search text"
203
+ disabled={disabled}
204
+ emphasis={emphasis}
205
+ id={id}
206
+ maxLength={maxLength}
207
+ onBlur={onBlur}
208
+ onChange={onChange}
209
+ onClear={onClear}
210
+ onFocus={onFocus}
211
+ placeholder={placeholder}
212
+ ref={inputRef}
213
+ value={search}
214
+ />
215
+ {endAdornment}
216
+ {search !== '' && emphasis === 'bold' && (
217
+ <div className={cn('-ml-2xs h-[24px] border-l border-border-secondary', { 'h-[20px]': small })} />
218
+ )}
219
+ <IconButton
220
+ aria-label={buttonAriaLabel}
221
+ className={cn('mr-2xs self-center justify-self-end !rounded-button', {
222
+ 'mr-[-1px]': small,
223
+ })}
224
+ disabled={disabled}
225
+ hideTooltip
226
+ icon={MagnifyingGlass}
227
+ iconStyle={iconStyle}
228
+ size="sm"
229
+ style={search === '' || emphasis === 'bold' ? 'neutral' : 'primary'}
230
+ type="submit"
231
+ variant={search === '' || emphasis === 'bold' ? 'transparent' : 'filled'}
232
+ />
233
+ </form>
234
+ </div>
235
+ );
236
+ };
@@ -0,0 +1,111 @@
1
+ import { cn } from '@evolve.ui/theme-system';
2
+ import { ReactNode } from 'react';
3
+
4
+ import { IconComponent } from '../Icons/IconBase';
5
+ import { LabelMiniStrong } from '../Typography/Text/Text';
6
+
7
+ export type SegmentedControlProps<ControlItemOptionId extends string> = {
8
+ /** The content to be displayed inside the control */
9
+ children?: ReactNode;
10
+ /** Additional CSS class name for the control */
11
+ className?: string;
12
+ /** Whether the control is disabled */
13
+ disabled?: boolean;
14
+ /** Icon component to be displayed on the left side of the control */
15
+ iconLeft?: IconComponent;
16
+ /** Icon component to be displayed on the right side of the control */
17
+ iconRight?: IconComponent;
18
+ /** Unique identifier for the control */
19
+ id: ControlItemOptionId;
20
+ /** Callback function triggered when the control is clicked */
21
+ onClick: (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => void;
22
+ /** Callback function triggered when a key is pressed while the control is focused */
23
+ onKeyDown: (event: React.KeyboardEvent<HTMLDivElement>) => void;
24
+ /** Whether the control is currently selected */
25
+ selected?: boolean;
26
+ };
27
+
28
+ export const SegmentedControl = <ControlItemOptionId extends string>({
29
+ children,
30
+ className,
31
+ disabled = false,
32
+ iconLeft: IconLeft,
33
+ iconRight: IconRight,
34
+ id,
35
+ onClick,
36
+ onKeyDown,
37
+ selected = false,
38
+ ...props
39
+ }: SegmentedControlProps<ControlItemOptionId>) => {
40
+ const baseClasses = cn(
41
+ 'rounded-md px-4 py-2',
42
+ 'transition-colors duration-200 ease-in-out',
43
+ 'cursor-pointer select-none',
44
+ 'flex items-center justify-center',
45
+ 'h-[26px]',
46
+ 'hui-focus-visible-outline',
47
+ {
48
+ 'bg-background-primary text-text-inverse shadow-02 drop-shadow-xl': selected && !disabled,
49
+ 'bg-background-subdued hover:bg-background-hover active:bg-background-pressed': !selected && !disabled,
50
+ 'pointer-events-none bg-background-subdued text-text-disabled': disabled,
51
+ 'px-2': !children,
52
+ },
53
+ className
54
+ );
55
+
56
+ return (
57
+ <div
58
+ className={baseClasses}
59
+ data-hui-id="SegmentedControl"
60
+ data-testid={id}
61
+ id={id}
62
+ {...props}
63
+ role="radio"
64
+ tabIndex={disabled ? -1 : 0}
65
+ {...(!disabled && {
66
+ onClick: (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
67
+ onClick(event);
68
+ },
69
+ onKeyDown: (event: React.KeyboardEvent<HTMLDivElement>) => {
70
+ onKeyDown(event);
71
+ if (event.key === 'Enter' || event.key === ' ') {
72
+ event.preventDefault();
73
+ onClick(event as unknown as React.MouseEvent<HTMLDivElement, MouseEvent>);
74
+ }
75
+ },
76
+ })}
77
+ aria-checked={selected}
78
+ aria-disabled={disabled}
79
+ aria-label={typeof children === 'string' ? children : id}
80
+ >
81
+ {IconLeft && (
82
+ <IconLeft
83
+ aria-hidden="true"
84
+ className={cn({ 'mr-1': Boolean(children) })}
85
+ color={disabled ? 'disabled' : 'primary'}
86
+ size="xs"
87
+ style="bold"
88
+ />
89
+ )}
90
+ {children && (
91
+ <LabelMiniStrong
92
+ aria-hidden="true"
93
+ color={disabled ? 'disabled' : 'primary'}
94
+ >
95
+ {children}
96
+ </LabelMiniStrong>
97
+ )}
98
+ {IconRight && (
99
+ <IconRight
100
+ aria-hidden="true"
101
+ className={cn({ 'ml-1': Boolean(children) })}
102
+ color={disabled ? 'disabled' : 'primary'}
103
+ size="xs"
104
+ style="bold"
105
+ />
106
+ )}
107
+ </div>
108
+ );
109
+ };
110
+
111
+ SegmentedControl.displayName = 'SegmentedControl';