@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,571 @@
1
+ import { useCallback, useEffect, useRef, useState } from 'react';
2
+
3
+ import { NativeWebRTCAdaptor } from '../adaptor/NativeWebRTCAdaptor';
4
+ import {
5
+ DEFAULT_PATH,
6
+ DEFAULT_WS_PORT,
7
+ DEFAULT_WSS_PORT,
8
+ FETCH_STREAM_ID_TIMEOUT,
9
+ PING_INTERVAL,
10
+ RECONNECT_INTERVAL,
11
+ WebRTCConfig,
12
+ WebRTCConnectionState,
13
+ WebRTCErrorToken,
14
+ WebRTCPlayerState,
15
+ } from '../types';
16
+
17
+ /**
18
+ * Races a value/promise against a timeout, resolving to `undefined` if the
19
+ * timeout wins. Used to prevent a hung host-supplied fetchStreamId() from
20
+ * permanently blocking the reconnect loop.
21
+ */
22
+ const withTimeout = async <T>(value: Promise<T> | T, ms: number): Promise<T | undefined> => {
23
+ let timer: ReturnType<typeof setTimeout> | undefined;
24
+ const valuePromise = Promise.resolve(value);
25
+ // If the timeout wins the race, the value promise is left dangling. Attach a
26
+ // no-op catch so a late rejection doesn't surface as an unhandledRejection.
27
+ // (An early rejection still propagates through Promise.race to the caller.)
28
+ valuePromise.catch(() => undefined);
29
+ try {
30
+ return await Promise.race([
31
+ valuePromise,
32
+ new Promise<undefined>((resolve) => {
33
+ timer = setTimeout(() => {
34
+ resolve(undefined);
35
+ }, ms);
36
+ }),
37
+ ]);
38
+ } finally {
39
+ if (timer) {
40
+ clearTimeout(timer);
41
+ }
42
+ }
43
+ };
44
+
45
+ /**
46
+ * Maps adaptor error tokens to user-facing copy so raw identifiers like
47
+ * `IceConnectionFailed` never reach the error overlay. Keyed off the shared
48
+ * WebRTCErrorToken constants so this map can't drift from what the adaptor emits.
49
+ */
50
+ const FRIENDLY_ERROR_MESSAGES = new Map<string, string>([
51
+ [WebRTCErrorToken.failedToCreateAnswer, 'Connection lost'],
52
+ [WebRTCErrorToken.failedToSetLocalDescription, 'Connection lost'],
53
+ [WebRTCErrorToken.failedToSetRemoteDescription, 'Connection lost'],
54
+ [WebRTCErrorToken.iceConnectionFailed, 'Connection lost'],
55
+ [WebRTCErrorToken.peerConnectionFailed, 'Connection lost'],
56
+ [WebRTCErrorToken.webSocketError, 'Connection lost'],
57
+ [WebRTCErrorToken.webSocketNotConnected, 'Connection lost'],
58
+ [WebRTCErrorToken.webSocketNotSupported, 'Your browser does not support live streaming'],
59
+ ]);
60
+
61
+ const toFriendlyError = (raw: string): string => FRIENDLY_ERROR_MESSAGES.get(raw) ?? raw;
62
+
63
+ /**
64
+ * Custom hook for managing WebRTC stream connections to Ant Media Server
65
+ *
66
+ * This hook handles the complete lifecycle of a WebRTC stream connection including:
67
+ * - WebSocket connection management
68
+ * - RTCPeerConnection setup and negotiation
69
+ * - Stream state management (loading, playing, error, reconnecting)
70
+ * - Automatic reconnection on connection failure
71
+ * - Proper cleanup on unmount
72
+ *
73
+ * @param config - Configuration object for the WebRTC connection
74
+ * @returns WebRTC player state including video ref, loading state, playing state, error, and mute controls
75
+ *
76
+ * @example
77
+ * ```tsx
78
+ * const { videoRef, loading, playing, error } = useWebRTCStream({
79
+ * streamId: 'my-stream-id',
80
+ * hostname: 'media.example.com'
81
+ * });
82
+ *
83
+ * return (
84
+ * <video ref={videoRef} autoPlay playsInline />
85
+ * );
86
+ * ```
87
+ */
88
+ export const useWebRTCStream = ({
89
+ debug = false,
90
+ fetchStreamId,
91
+ hostname,
92
+ streamId,
93
+ wsPort = DEFAULT_WS_PORT,
94
+ wssPort = DEFAULT_WSS_PORT,
95
+ }: WebRTCConfig): WebRTCPlayerState => {
96
+ const videoRef = useRef<HTMLVideoElement>(null);
97
+ const [loading, setLoading] = useState(true);
98
+ const [error, setError] = useState<string | null>(null);
99
+ const [connectionState, setConnectionState] = useState<WebRTCConnectionState>('idle');
100
+
101
+ const webRTCAdaptorRef = useRef<NativeWebRTCAdaptor | null>(null);
102
+ const reconnectIntervalRef = useRef<ReturnType<typeof setInterval> | null>(null);
103
+ const pingIntervalRef = useRef<ReturnType<typeof setInterval> | null>(null);
104
+ const isReconnectingRef = useRef(false);
105
+ // True while the component is mounted; lets async init bail after an await if
106
+ // the component has since unmounted (avoids setState/adaptor build post-teardown).
107
+ const isMountedRef = useRef(true);
108
+ // Monotonic token identifying the current connection attempt. Each
109
+ // initializeWebRTC() call claims a fresh token; if a newer attempt starts
110
+ // (reconnect tick, streamId prop change), the older one becomes stale and
111
+ // bails at the next checkpoint instead of building an adaptor or mutating
112
+ // shared state — preventing overlapping adaptors and stale-id connects.
113
+ const initTokenRef = useRef(0);
114
+ // Holds the latest initializeWebRTC so the reconnect loop never calls a stale
115
+ // closure (and so handleError/handleCallback don't need to depend on it).
116
+ /* istanbul ignore next -- @preserve: the default initializer is never invoked; an effect overwrites this ref on first commit, and no reconnect (the only caller) can fire before the mount effect creates an adaptor. */
117
+ const initializeWebRTCRef = useRef<() => void | Promise<void>>(() => undefined);
118
+ // The stream ID the adaptor is currently using. Defaults to the streamId prop
119
+ // and is refreshed by fetchStreamId() before each reconnect attempt.
120
+ const activeStreamIdRef = useRef(streamId);
121
+ // Latest fetchStreamId, held in a ref so the reconnect path always calls the
122
+ // current one without needing it in any dependency array.
123
+ const fetchStreamIdRef = useRef(fetchStreamId);
124
+ fetchStreamIdRef.current = fetchStreamId;
125
+
126
+ /**
127
+ * Generates the WebSocket URL based on the current page protocol
128
+ */
129
+ const getWebSocketUrl = useCallback(() => {
130
+ const isSecure = window.location.protocol === 'https:';
131
+ const protocol = isSecure ? 'wss' : 'ws';
132
+ const port = isSecure ? wssPort : wsPort;
133
+ const url = `${protocol}://${hostname}:${port}${DEFAULT_PATH}`;
134
+
135
+ if (debug) {
136
+ // eslint-disable-next-line no-console
137
+ console.log('[WebRTC] Generated WebSocket URL:', {
138
+ hostname,
139
+ isSecure,
140
+ location: window.location.protocol,
141
+ port,
142
+ protocol,
143
+ url,
144
+ });
145
+ }
146
+
147
+ return url;
148
+ }, [hostname, wsPort, wssPort, debug]);
149
+
150
+ /**
151
+ * Clears reconnection interval
152
+ */
153
+ const stopReconnecting = useCallback(() => {
154
+ if (reconnectIntervalRef.current) {
155
+ clearInterval(reconnectIntervalRef.current);
156
+ reconnectIntervalRef.current = null;
157
+ }
158
+ isReconnectingRef.current = false;
159
+ }, []);
160
+
161
+ /**
162
+ * Starts the reconnection loop if one is not already running.
163
+ *
164
+ * Any failure signal (WebSocket error, WebSocket close, or the stream
165
+ * finishing) funnels through here so that a dropped connection always
166
+ * triggers recovery. The loop is idempotent — guarded by isReconnectingRef —
167
+ * and is cleared by stopReconnecting() once the stream re-initializes or
168
+ * starts playing again.
169
+ *
170
+ * The loop retries indefinitely (no max-attempt cap) by design: a live stream
171
+ * can resume minutes after dropping, so we keep attempting every
172
+ * RECONNECT_INTERVAL until it returns or the component unmounts.
173
+ */
174
+ const startReconnecting = useCallback(() => {
175
+ if (isReconnectingRef.current) {
176
+ return;
177
+ }
178
+
179
+ if (debug) {
180
+ // eslint-disable-next-line no-console
181
+ console.log(`[WebRTC] Starting reconnection attempts (every ${RECONNECT_INTERVAL}ms)`);
182
+ }
183
+
184
+ isReconnectingRef.current = true;
185
+ reconnectIntervalRef.current = setInterval(() => {
186
+ if (debug) {
187
+ // eslint-disable-next-line no-console
188
+ console.log('[WebRTC] 🔄 Attempting to reconnect...');
189
+ }
190
+ // initializeWebRTC sets the 'reconnecting' state while isReconnectingRef is true.
191
+ void initializeWebRTCRef.current();
192
+ }, RECONNECT_INTERVAL);
193
+ }, [debug]);
194
+
195
+ /**
196
+ * Starts ping interval to keep connection alive
197
+ */
198
+ const startPinging = useCallback(() => {
199
+ if (pingIntervalRef.current) {
200
+ clearInterval(pingIntervalRef.current);
201
+ }
202
+
203
+ pingIntervalRef.current = setInterval(() => {
204
+ const activeStreamId = activeStreamIdRef.current;
205
+ if (webRTCAdaptorRef.current && activeStreamId) {
206
+ try {
207
+ webRTCAdaptorRef.current.ping(activeStreamId);
208
+ } catch (err) {
209
+ if (debug) {
210
+ // eslint-disable-next-line no-console
211
+ console.error('Error sending ping:', err);
212
+ }
213
+ }
214
+ }
215
+ }, PING_INTERVAL);
216
+ }, [debug]);
217
+
218
+ /**
219
+ * Stops ping interval
220
+ */
221
+ const stopPinging = useCallback(() => {
222
+ if (pingIntervalRef.current) {
223
+ clearInterval(pingIntervalRef.current);
224
+ pingIntervalRef.current = null;
225
+ }
226
+ }, []);
227
+
228
+ /**
229
+ * Handles WebRTC adaptor callbacks
230
+ */
231
+ const handleCallback = useCallback(
232
+ (info: string, obj?: unknown) => {
233
+ // A late callback can arrive after unmount (e.g. closeWebSocket() during
234
+ // cleanup triggers onclose). Ignore it so we don't setState or re-arm the
235
+ // reconnect interval on a torn-down component.
236
+ if (!isMountedRef.current) {
237
+ return;
238
+ }
239
+
240
+ if (debug) {
241
+ // eslint-disable-next-line no-console
242
+ console.log(`[WebRTC] Callback: ${info}`, obj);
243
+ }
244
+
245
+ switch (info) {
246
+ case 'initialized':
247
+ if (debug) {
248
+ // eslint-disable-next-line no-console
249
+ console.log('[WebRTC] ✅ Initialized - WebSocket connected, starting playback');
250
+ }
251
+ setConnectionState('connected');
252
+ setLoading(true);
253
+ stopReconnecting();
254
+ startPinging();
255
+ // Start playing the stream using the ID the adaptor connected with
256
+ if (webRTCAdaptorRef.current && activeStreamIdRef.current) {
257
+ if (debug) {
258
+ // eslint-disable-next-line no-console
259
+ console.log(`[WebRTC] Calling play() for streamId: ${activeStreamIdRef.current}`);
260
+ }
261
+ webRTCAdaptorRef.current.play(activeStreamIdRef.current);
262
+ }
263
+ break;
264
+
265
+ case 'play_started':
266
+ if (debug) {
267
+ // eslint-disable-next-line no-console
268
+ console.log('[WebRTC] ✅ Play started - Stream is now playing');
269
+ }
270
+ setConnectionState('playing');
271
+ setLoading(false);
272
+ // setPlaying(true);
273
+ setError(null);
274
+ stopReconnecting();
275
+ break;
276
+
277
+ case 'play_finished':
278
+ if (debug) {
279
+ // eslint-disable-next-line no-console
280
+ console.log('[WebRTC] ⚠️ Play finished - Stream ended');
281
+ }
282
+ setConnectionState('error');
283
+ setError('Stream ended');
284
+ // A finished stream is treated as a recoverable failure: the
285
+ // stream may simply have restarted on the server. Attempt to
286
+ // reconnect rather than leaving the player dead.
287
+ startReconnecting();
288
+ break;
289
+
290
+ case 'closed':
291
+ if (debug) {
292
+ // eslint-disable-next-line no-console
293
+ console.log('[WebRTC] ❌ Connection closed');
294
+ }
295
+ setConnectionState('error');
296
+ setError('Connection closed');
297
+ // A dropped WebSocket is reported via callback('closed'), NOT
298
+ // callbackError, so the reconnect loop must be started here too
299
+ // — otherwise a network failure leaves the player stuck.
300
+ startReconnecting();
301
+ break;
302
+
303
+ case 'publish_started':
304
+ case 'publish_finished':
305
+ case 'ice_connection_state_changed':
306
+ case 'updated_stats':
307
+ case 'data_received':
308
+ default:
309
+ if (debug) {
310
+ // eslint-disable-next-line no-console
311
+ console.log(`[WebRTC] Unhandled callback: ${info}`, obj);
312
+ }
313
+ }
314
+ },
315
+ [debug, startPinging, stopReconnecting, startReconnecting]
316
+ );
317
+
318
+ /**
319
+ * Handles WebRTC adaptor errors
320
+ */
321
+ const handleError = useCallback(
322
+ (errorMessage: string, errorObject?: unknown) => {
323
+ // Ignore late errors from an adaptor that outlived the component.
324
+ if (!isMountedRef.current) {
325
+ return;
326
+ }
327
+
328
+ // eslint-disable-next-line no-console
329
+ console.error('[WebRTC] ❌ Error:', errorMessage, errorObject);
330
+ setConnectionState('error');
331
+ setLoading(false);
332
+ setError(toFriendlyError(errorMessage));
333
+
334
+ // Start reconnection attempts if not already reconnecting
335
+ startReconnecting();
336
+ },
337
+ [startReconnecting]
338
+ );
339
+
340
+ /**
341
+ * Initializes the WebRTC adaptor
342
+ */
343
+ const initializeWebRTC = useCallback(async () => {
344
+ if (!activeStreamIdRef.current) {
345
+ // eslint-disable-next-line no-console
346
+ console.error('[WebRTC] ❌ No stream ID provided');
347
+ setError('No stream ID provided');
348
+ return;
349
+ }
350
+
351
+ // Claim this attempt. Any later attempt bumps the token, marking this one
352
+ // stale. `isCurrent()` is checked after every await so a superseded or
353
+ // unmounted attempt bails before mutating shared state / building an adaptor.
354
+ const token = ++initTokenRef.current;
355
+ const isCurrent = () => token === initTokenRef.current && isMountedRef.current;
356
+
357
+ // Clean up existing adaptor (using the ID it was created with, before we
358
+ // potentially swap in a freshly fetched one below).
359
+ if (webRTCAdaptorRef.current) {
360
+ if (debug) {
361
+ // eslint-disable-next-line no-console
362
+ console.log('[WebRTC] Cleaning up existing adaptor');
363
+ }
364
+ try {
365
+ stopPinging();
366
+ webRTCAdaptorRef.current.stop(activeStreamIdRef.current);
367
+ webRTCAdaptorRef.current.closeWebSocket();
368
+ } catch (err) {
369
+ // eslint-disable-next-line no-console
370
+ console.error('[WebRTC] Error cleaning up previous adaptor:', err);
371
+ }
372
+ webRTCAdaptorRef.current = null;
373
+ }
374
+
375
+ // Preserve the 'reconnecting' state across the rebuild so the UI can
376
+ // surface it; a first-time connect uses 'connecting'.
377
+ const reconnecting = isReconnectingRef.current;
378
+ setConnectionState(reconnecting ? 'reconnecting' : 'connecting');
379
+ // On a reconnect tick keep `loading` false: the error overlay (and its
380
+ // "Attempting to reconnect…" caption) is gated behind `!loading`, and the
381
+ // failure handler that started the loop has already set `error`, so leaving
382
+ // loading false is what makes the reconnecting UI visible. Only a first-time
383
+ // connect shows the loading spinner.
384
+ setLoading(!reconnecting);
385
+
386
+ // On reconnect, give the host a chance to supply a fresh stream ID — a
387
+ // restarted stream is usually issued a new ID, so reusing the old one
388
+ // would just reconnect to a dead stream. Bounded by a timeout so a hung
389
+ // callback can't wedge the reconnect loop.
390
+ if (isReconnectingRef.current && fetchStreamIdRef.current) {
391
+ try {
392
+ const freshStreamId = await withTimeout(fetchStreamIdRef.current(), FETCH_STREAM_ID_TIMEOUT);
393
+ // A newer attempt (e.g. a streamId prop change) may have superseded
394
+ // us during the await. Don't clobber its ID or continue this build.
395
+ if (!isCurrent()) {
396
+ return;
397
+ }
398
+ if (freshStreamId) {
399
+ if (debug && freshStreamId !== activeStreamIdRef.current) {
400
+ // eslint-disable-next-line no-console
401
+ console.log(`[WebRTC] Refreshed stream ID: ${activeStreamIdRef.current} -> ${freshStreamId}`);
402
+ }
403
+ activeStreamIdRef.current = freshStreamId;
404
+ }
405
+ } catch (err) {
406
+ // eslint-disable-next-line no-console
407
+ console.error('[WebRTC] fetchStreamId failed, reusing current stream ID:', err);
408
+ if (!isCurrent()) {
409
+ return;
410
+ }
411
+ }
412
+ }
413
+
414
+ // Final checkpoint before building: bail if unmounted or superseded.
415
+ if (!isCurrent()) {
416
+ if (debug) {
417
+ // eslint-disable-next-line no-console
418
+ console.log('[WebRTC] Initialization superseded or unmounted, aborting');
419
+ }
420
+ return;
421
+ }
422
+
423
+ const activeStreamId = activeStreamIdRef.current;
424
+
425
+ if (debug) {
426
+ // eslint-disable-next-line no-console
427
+ console.log(`[WebRTC] 🚀 Initializing WebRTC for streamId: ${activeStreamId}`);
428
+ }
429
+
430
+ try {
431
+ const websocketUrl = getWebSocketUrl();
432
+
433
+ // Ensure video element has an ID before creating adaptor
434
+ if (videoRef.current && !videoRef.current.id) {
435
+ videoRef.current.id = 'webrtc-video-' + activeStreamId;
436
+ }
437
+ const videoId = videoRef.current?.id || 'webrtc-video';
438
+
439
+ if (debug) {
440
+ // eslint-disable-next-line no-console
441
+ console.log('[WebRTC] Creating WebRTCAdaptor with config:', {
442
+ isPlayMode: true,
443
+ remoteVideoId: videoId,
444
+ streamId: activeStreamId,
445
+ websocket_url: websocketUrl,
446
+ });
447
+ }
448
+
449
+ webRTCAdaptorRef.current = new NativeWebRTCAdaptor({
450
+ callback: handleCallback,
451
+ callbackError: handleError,
452
+ debug,
453
+ peerconnection_config: {
454
+ iceServers: [{ urls: 'stun:stun.l.google.com:19302' }],
455
+ },
456
+ remoteVideoId: videoId,
457
+ sdp_constraints: {
458
+ offerToReceiveAudio: true,
459
+ offerToReceiveVideo: true,
460
+ },
461
+ websocket_url: websocketUrl,
462
+ });
463
+
464
+ if (debug) {
465
+ // eslint-disable-next-line no-console
466
+ console.log('[WebRTC] ✅ WebRTCAdaptor created, waiting for connection...');
467
+ }
468
+ } catch (err) {
469
+ // eslint-disable-next-line no-console
470
+ console.error('[WebRTC] ❌ Failed to initialize WebRTC:', err);
471
+ handleError('Failed to initialize WebRTC', err);
472
+ }
473
+ }, [debug, getWebSocketUrl, handleCallback, handleError, stopPinging]);
474
+
475
+ /**
476
+ * Track mount status so async init can bail after an await once the component
477
+ * has unmounted. Kept separate from the streamId-scoped cleanup effect below
478
+ * so a prop change never flips this to unmounted.
479
+ */
480
+ useEffect(() => {
481
+ isMountedRef.current = true;
482
+ return () => {
483
+ isMountedRef.current = false;
484
+ };
485
+ }, []);
486
+
487
+ /**
488
+ * Keep the ref pointed at the latest initializeWebRTC so the reconnect loop
489
+ * always reconnects with the current streamId/config rather than a closure
490
+ * captured when the loop first started.
491
+ */
492
+ useEffect(() => {
493
+ initializeWebRTCRef.current = initializeWebRTC;
494
+ }, [initializeWebRTC]);
495
+
496
+ /**
497
+ * Initialize WebRTC connection on mount or when streamId changes
498
+ */
499
+ useEffect(() => {
500
+ if (streamId) {
501
+ if (debug) {
502
+ // eslint-disable-next-line no-console
503
+ console.log('[WebRTC] StreamId changed or component mounted, scheduling initialization');
504
+ }
505
+ // A streamId prop change is authoritative and supersedes any ID
506
+ // previously fetched during reconnection.
507
+ activeStreamIdRef.current = streamId;
508
+ // Small delay to ensure video element is mounted
509
+ const timeoutId = setTimeout(() => {
510
+ void initializeWebRTC();
511
+ }, 100);
512
+
513
+ return () => {
514
+ clearTimeout(timeoutId);
515
+ };
516
+ }
517
+ return undefined;
518
+ }, [streamId, initializeWebRTC, debug]);
519
+
520
+ /**
521
+ * Cleanup on unmount
522
+ */
523
+ useEffect(() => {
524
+ return () => {
525
+ if (debug) {
526
+ // eslint-disable-next-line no-console
527
+ console.log('[WebRTC] 🧹 Cleaning up on unmount');
528
+ }
529
+ stopReconnecting();
530
+ stopPinging();
531
+
532
+ if (webRTCAdaptorRef.current && activeStreamIdRef.current) {
533
+ try {
534
+ webRTCAdaptorRef.current.stop(activeStreamIdRef.current);
535
+ webRTCAdaptorRef.current.closeWebSocket();
536
+ if (debug) {
537
+ // eslint-disable-next-line no-console
538
+ console.log('[WebRTC] ✅ Cleanup complete');
539
+ }
540
+ } catch (err) {
541
+ // eslint-disable-next-line no-console
542
+ console.error('[WebRTC] Error during cleanup:', err);
543
+ }
544
+ }
545
+
546
+ webRTCAdaptorRef.current = null;
547
+ };
548
+ }, [streamId, debug, stopReconnecting, stopPinging]);
549
+
550
+ /**
551
+ * Assign the stream to the video element when it's available
552
+ */
553
+ useEffect(() => {
554
+ if (videoRef.current && webRTCAdaptorRef.current) {
555
+ const remoteVideo = videoRef.current;
556
+
557
+ // The Ant Media adaptor will set the srcObject automatically
558
+ // We just need to ensure the video element has the correct ID
559
+ if (!remoteVideo.id) {
560
+ remoteVideo.id = 'webrtc-video-' + streamId;
561
+ }
562
+ }
563
+ }, [streamId]);
564
+
565
+ return {
566
+ connectionState,
567
+ error,
568
+ loading,
569
+ videoRef: videoRef as React.RefObject<HTMLVideoElement>,
570
+ };
571
+ };
@@ -0,0 +1,22 @@
1
+ /**
2
+ * WebRTC video player for streaming from Ant Media Server
3
+ *
4
+ * @module
5
+ * Components:
6
+ * - WebRTCPlayer: Complete WebRTC video player with connection management and UI
7
+ *
8
+ * Hooks:
9
+ * - useWebRTCStream: Custom hook for managing WebRTC stream connections
10
+ *
11
+ * Types:
12
+ * - WebRTCPlayerProps: Props for the WebRTCPlayer component
13
+ * - WebRTCConfig: Configuration for WebRTC connections
14
+ * - WebRTCPlayerState: State returned by useWebRTCStream hook
15
+ * - WebRTCConnectionState: Connection state enum
16
+ */
17
+
18
+ export { WebRTCPlayer } from './WebRTCPlayer';
19
+ export type { WebRTCPlayerProps } from './WebRTCPlayer';
20
+ export { useWebRTCStream } from './hooks/useWebRTCStream';
21
+ export type { WebRTCConfig, WebRTCPlayerState, WebRTCConnectionState } from './types';
22
+ export { DEFAULT_WS_PORT, DEFAULT_WSS_PORT, DEFAULT_PATH, RECONNECT_INTERVAL, PING_INTERVAL } from './types';
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Configuration constants for WebRTC player
3
+ */
4
+ export const DEFAULT_WS_PORT = 5080;
5
+ export const DEFAULT_WSS_PORT = 5443;
6
+ export const DEFAULT_PATH = '/WebRTCAppEE/websocket';
7
+ // Interval between reconnect attempts. The reconnect loop retries indefinitely
8
+ // (no max-attempt cap) by design: a live stream can resume minutes after
9
+ // dropping, so the player keeps attempting until the stream returns or the
10
+ // component unmounts.
11
+ export const RECONNECT_INTERVAL = 5000; // 5 seconds
12
+ export const PING_INTERVAL = 30000; // 30 seconds
13
+ // Cap on how long to wait for a host-supplied fetchStreamId() before falling back
14
+ // to the current ID, so a hung callback can't permanently block reconnection.
15
+ // INVARIANT: must stay strictly below RECONNECT_INTERVAL. The reconnect loop
16
+ // awaits fetchStreamId() on each tick, so a timeout >= the interval would let the
17
+ // next tick start while the previous one is still awaiting, producing overlapping
18
+ // reconnect attempts.
19
+ export const FETCH_STREAM_ID_TIMEOUT = 3000; // 3 seconds
20
+
21
+ /**
22
+ * WebRTC connection state
23
+ */
24
+ export type WebRTCConnectionState = 'idle' | 'connecting' | 'connected' | 'playing' | 'error' | 'reconnecting';
25
+
26
+ /**
27
+ * Error tokens emitted by NativeWebRTCAdaptor via its callbackError channel.
28
+ * Exported so the adaptor (producer) and the hook's friendly-message map
29
+ * (consumer) reference the same literals and can't silently drift apart — a
30
+ * rename here is a compile error on both sides rather than a silent fallthrough.
31
+ */
32
+ export const WebRTCErrorToken = {
33
+ failedToCreateAnswer: 'Failed to create answer',
34
+ failedToSetLocalDescription: 'Failed to set local description',
35
+ failedToSetRemoteDescription: 'Failed to set remote description',
36
+ iceConnectionFailed: 'IceConnectionFailed',
37
+ peerConnectionFailed: 'PeerConnectionFailed',
38
+ webSocketError: 'WebSocket error',
39
+ webSocketNotConnected: 'WebSocketNotConnected',
40
+ webSocketNotSupported: 'WebSocketNotSupported',
41
+ } as const;
42
+
43
+ export type WebRTCErrorToken = (typeof WebRTCErrorToken)[keyof typeof WebRTCErrorToken];
44
+
45
+ /**
46
+ * WebRTC adaptor callback information types
47
+ */
48
+ export type WebRTCCallbackInfo =
49
+ | 'initialized'
50
+ | 'play_started'
51
+ | 'play_finished'
52
+ | 'publish_started'
53
+ | 'publish_finished'
54
+ | 'closed'
55
+ | 'ice_connection_state_changed'
56
+ | 'updated_stats'
57
+ | 'data_received';
58
+
59
+ /**
60
+ * Configuration for WebRTC player
61
+ */
62
+ export type WebRTCConfig = {
63
+ /** Whether to enable debug logging */
64
+ debug?: boolean;
65
+ /**
66
+ * Optional callback invoked before each reconnect attempt to obtain a fresh
67
+ * stream ID. A stream that restarts on the server is often issued a new ID,
68
+ * so reconnecting with the original `streamId` would target a dead stream.
69
+ * Return the latest ID (sync or async); return a falsy value to keep the
70
+ * current one. Errors are swallowed and the current ID is reused.
71
+ */
72
+ fetchStreamId?: () => string | Promise<string>;
73
+ /** WebRTC server hostname */
74
+ hostname: string;
75
+ /** Stream ID from Ant Media Server */
76
+ streamId: string;
77
+ /** WebSocket port for non-SSL connections */
78
+ wsPort?: number;
79
+ /** WebSocket port for SSL connections */
80
+ wssPort?: number;
81
+ };
82
+
83
+ /**
84
+ * WebRTC player state returned by the hook
85
+ */
86
+ export type WebRTCPlayerState = {
87
+ /** Current connection state */
88
+ connectionState: WebRTCConnectionState;
89
+ /** Error message if connection failed */
90
+ error: string | null;
91
+ /** Whether the stream is currently loading/connecting */
92
+ loading: boolean;
93
+ /** Reference to attach to video element */
94
+ videoRef: React.RefObject<HTMLVideoElement>;
95
+ };
@@ -0,0 +1 @@
1
+ export * from './utils';