@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.
- package/evolve-ui.entries.json +556 -0
- package/fileUpload/testUtils/mockFilesAndImages.d.cts +3 -3
- package/fileUpload/testUtils/mockFilesAndImages.d.cts.map +1 -1
- package/fileUpload/testUtils/mockFilesAndImages.d.mts +3 -3
- package/fileUpload/testUtils/mockFilesAndImages.d.mts.map +1 -1
- package/fileUpload/testUtils/testUtils.d.cts +1 -1
- package/fileUpload/testUtils/testUtils.d.cts.map +1 -1
- package/fileUpload/testUtils/testUtils.d.mts +1 -1
- package/fileUpload/testUtils/testUtils.d.mts.map +1 -1
- package/package.json +2 -2
- package/src/Accordion/Accordion.tsx +233 -0
- package/src/AddressDisplay/AddressDisplay.tsx +43 -0
- package/src/AddressDisplay/components/addressComponents.tsx +111 -0
- package/src/AddressDisplay/components/addressField.tsx +25 -0
- package/src/AddressDisplay/components/addressSection.tsx +8 -0
- package/src/AddressDisplay/components/getCountryValue.tsx +31 -0
- package/src/AddressDisplay/types.ts +26 -0
- package/src/AutomatedCarousel/AutomatedCarousel.tsx +163 -0
- package/src/AutomatedCarousel/automatedCarousel.types.ts +7 -0
- package/src/AutomatedCarousel/components/CarouselProgressBar/CarouselProgressBar.tsx +139 -0
- package/src/AutomatedCarousel/components/CarouselProgressBar/components/CarouselProgressBarUnit/CarouselProgressBarUnit.tsx +165 -0
- package/src/Badge/Badge.tsx +104 -0
- package/src/Badge/Badge.types.ts +58 -0
- package/src/Badge/ItemBadge.tsx +97 -0
- package/src/Badge/LiveStatusBadge.tsx +93 -0
- package/src/BannerNotification/BannerNotification.tsx +157 -0
- package/src/BannerNotification/components/BannerNotificationSkeleton.tsx +39 -0
- package/src/BannerNotification/components/CalloutIcon/BannerIcon.tsx +48 -0
- package/src/BannerNotification/utils/getRandomTooltipId.ts +3 -0
- package/src/BottomSheet/BottomSheet.tsx +476 -0
- package/src/BottomSheet/components/BottomSheetBackdrop/BottomSheetBackdrop.tsx +47 -0
- package/src/BottomSheet/components/BottomSheetContentArea/BottomSheetContentArea.tsx +92 -0
- package/src/BottomSheet/components/BottomSheetOverlay/BottomSheetOverlayTranslate3d.tsx +196 -0
- package/src/BottomSheet/components/SheetDescription/SheetDescription.tsx +22 -0
- package/src/BottomSheet/components/SheetTitle/SheetTitle.tsx +21 -0
- package/src/BottomSheet/components/index.tsx +5 -0
- package/src/BottomSheet/hooks/index.tsx +13 -0
- package/src/BottomSheet/hooks/useAriaHider.tsx +91 -0
- package/src/BottomSheet/hooks/useBottomSheetServices.tsx +224 -0
- package/src/BottomSheet/hooks/useDragHandler.tsx +282 -0
- package/src/BottomSheet/hooks/useFocusTrap.tsx +113 -0
- package/src/BottomSheet/hooks/useLayoutEffect.tsx +4 -0
- package/src/BottomSheet/hooks/useOptimizedResizeObserver.tsx +94 -0
- package/src/BottomSheet/hooks/useOptimizedScrollState.tsx +87 -0
- package/src/BottomSheet/hooks/useReady.tsx +34 -0
- package/src/BottomSheet/hooks/useReducedMotion.tsx +22 -0
- package/src/BottomSheet/hooks/useScrollLock.tsx +143 -0
- package/src/BottomSheet/hooks/useSnapPoints.tsx +355 -0
- package/src/BottomSheet/hooks/useSpring.tsx +47 -0
- package/src/BottomSheet/hooks/useSpringInterpolationsTranslate3d.tsx +101 -0
- package/src/BottomSheet/index.tsx +237 -0
- package/src/BottomSheet/state/atoms.ts +147 -0
- package/src/BottomSheet/state/useBottomSheetStateMachine.ts +246 -0
- package/src/BottomSheet/types.ts +172 -0
- package/src/BottomSheet/utils.ts +65 -0
- package/src/Breadcrumbs/Breadcrumbs.tsx +126 -0
- package/src/Button/Button.tsx +164 -0
- package/src/Button/Button.types.ts +80 -0
- package/src/Button/buttonColorClasses.ts +53 -0
- package/src/Callout/Callout.tsx +136 -0
- package/src/Callout/Callout.types.ts +29 -0
- package/src/Callout/components/CalloutIcon/CalloutIcon.tsx +56 -0
- package/src/Card/CardGrid.tsx +263 -0
- package/src/Card/SingleCard.tsx +22 -0
- package/src/Card/cardFactory.tsx +176 -0
- package/src/Card/components/createBadge.tsx +34 -0
- package/src/Card/components/createFavoriteButton.tsx +40 -0
- package/src/Card/components/createImage.tsx +64 -0
- package/src/Card/components/createInfo.tsx +84 -0
- package/src/Card/components/createName.tsx +63 -0
- package/src/Card/components/createPriceStatus.tsx +100 -0
- package/src/Card/components/types.ts +4 -0
- package/src/Card/hooks/useCardVisibilityTracking.ts +82 -0
- package/src/Card/sharedProps.ts +12 -0
- package/src/Card/types.ts +62 -0
- package/src/Carousel/Carousel.tsx +513 -0
- package/src/Carousel/Carousel.types.ts +43 -0
- package/src/Carousel/Carousel.utils.ts +63 -0
- package/src/Carousel/components/DotButton/DotButton.tsx +42 -0
- package/src/Carousel/components/NavigationButtons/NavigationButtons.tsx +77 -0
- package/src/Carousel/components/TitleSection/TitleSection.tsx +61 -0
- package/src/Carousel/components/TitleSection/components/SubHeaderLeft/SubHeaderLeft.tsx +53 -0
- package/src/Carousel/components/TitleSection/components/Title/Title.tsx +46 -0
- package/src/Carousel/index.ts +2 -0
- package/src/Carousel/testUtils.ts +10 -0
- package/src/Chips/Chip.tsx +153 -0
- package/src/Chips/ChipGroup.tsx +173 -0
- package/src/Chips/SuggestionChip.tsx +15 -0
- package/src/Chips/chipTypes.ts +113 -0
- package/src/Chips/index.ts +4 -0
- package/src/ChoiceListItem/Checkbox.tsx +69 -0
- package/src/ChoiceListItem/Radio.tsx +61 -0
- package/src/ChoiceListItem/choiceListItem.tsx +99 -0
- package/src/ChoiceListItem/common.tsx +148 -0
- package/src/ChoiceListItem/index.ts +3 -0
- package/src/Collapsible/Collapsible.tsx +58 -0
- package/src/Confetti/Confetti.tsx +270 -0
- package/src/Confetti/index.ts +2 -0
- package/src/ContentPager/ContentPager.tsx +189 -0
- package/src/ContentPager/components/Page.tsx +24 -0
- package/src/CookieConsent/components/CookieCategoryRow/CookieCategoryRow.tsx +30 -0
- package/src/CookieConsent/components/CookieConsent/CookieConsent.tsx +74 -0
- package/src/CookieConsent/components/CookieConsentBanner/CookieConsentBanner.tsx +51 -0
- package/src/CookieConsent/components/CookieConsentModal/CookieConsentModal.tsx +64 -0
- package/src/CookieConsent/hooks/useCookieConsent.ts +170 -0
- package/src/CookieConsent/hooks/useCookieConsentState.ts +142 -0
- package/src/CookieConsent/index.ts +16 -0
- package/src/CookieConsent/types/cookieConsent.types.ts +79 -0
- package/src/CookieConsent/types/index.ts +7 -0
- package/src/Countdown/Countdown.tsx +161 -0
- package/src/Countdown/Countdown.types.ts +4 -0
- package/src/Countdown/hooks/useGetCountdown.ts +103 -0
- package/src/DateTimeInput/dateInput/DateInput.tsx +199 -0
- package/src/DateTimeInput/datePicker/DatePicker.tsx +138 -0
- package/src/DateTimeInput/datePicker/components/calendar/Calendar.tsx +72 -0
- package/src/DateTimeInput/datePicker/index.ts +2 -0
- package/src/DateTimeInput/timeInput/TimeInput.tsx +128 -0
- package/src/DateTimeInput/timePicker/TimePicker.tsx +118 -0
- package/src/DateTimeInput/timePicker/components/TimePopover/AmPmSwitch.tsx +103 -0
- package/src/DateTimeInput/timePicker/components/TimePopover/TimeFieldInput.tsx +26 -0
- package/src/DateTimeInput/timePicker/components/TimePopover/TimePopover.tsx +84 -0
- package/src/DateTimeInput/timePicker/components/TimePopover/TimePopover.utils.ts +67 -0
- package/src/DateTimeInput/timePicker/components/TimePopover/TimePopoverActions.tsx +26 -0
- package/src/DateTimeInput/timePicker/index.ts +2 -0
- package/src/DateTimeInput/utils/getDisplayDate.ts +15 -0
- package/src/DateTimeInput/utils/getDisplayTime.ts +15 -0
- package/src/DateTimeInput/utils/index.ts +2 -0
- package/src/DateTimeInput/utils/parseTimeValue.ts +54 -0
- package/src/Drawer/Drawer.tsx +446 -0
- package/src/Drawer/atoms.ts +4 -0
- package/src/Drawer/components/DialogActions/DialogActions.tsx +33 -0
- package/src/Drawer/components/DialogContent/DialogContent.tsx +80 -0
- package/src/Drawer/components/DialogHeader/DialogHeader.tsx +68 -0
- package/src/EducationalPopover/EducationalPopover.tsx +174 -0
- package/src/FavoriteButton/FavoriteButton.tsx +64 -0
- package/src/FavoriteButton/components/IconOnlyFavoriteButton/IconOnlyFavoriteButton.tsx +80 -0
- package/src/FavoriteButton/components/LabeledAnimatedFavoriteButton/LabeledAnimatedFavoriteButton.tsx +179 -0
- package/src/FavoriteButton/components/LabeledFavoriteButton/LabeledFavoriteButton.tsx +71 -0
- package/src/FavoriteButton/components/SmallHeartStraightIcon/SmallHeartStraightIcon.tsx +14 -0
- package/src/FavoriteButton/hooks/useFavoriteButtonState.ts +30 -0
- package/src/FavoriteButton/index.ts +2 -0
- package/src/FavoriteButton/types/favoriteButton.ts +87 -0
- package/src/FeatureFlags/devTools/FeatureFlagDevToolsUI.tsx +226 -0
- package/src/FeatureFlags/devTools/getFeatureFlagCookieOverrides.ts +30 -0
- package/src/FeatureFlags/devTools/utils/cookies.ts +169 -0
- package/src/FeatureFlags/hooks/index.ts +2 -0
- package/src/FeatureFlags/hooks/useFeatureFlag.tsx +19 -0
- package/src/FeatureFlags/hooks/useFeatureFlags.tsx +15 -0
- package/src/FileUpload/components/FileCard/FileCard.tsx +50 -0
- package/src/FileUpload/components/FileDropzone/FileDropzone.tsx +221 -0
- package/src/FileUpload/components/FileDropzone/components/DropzoneContent/DropzoneContent.tsx +28 -0
- package/src/FileUpload/components/FileDropzone/components/DropzoneContent/DropzoneText.tsx +81 -0
- package/src/FileUpload/components/FileDropzone/components/FileDropzoneDebugger/FileDropzoneDebugger.tsx +40 -0
- package/src/FileUpload/components/FileDropzone/components/FileDropzoneDebugger/FileRejectionsDisplay.tsx +110 -0
- package/src/FileUpload/components/FileDropzoneOverlay/FileDropzoneOverlay.tsx +183 -0
- package/src/FileUpload/components/FileDropzoneOverlay/components/OverlayDropzoneContent.tsx +146 -0
- package/src/FileUpload/components/FileDropzoneOverlay/components/OverlayDropzoneDragText.tsx +42 -0
- package/src/FileUpload/components/FileDropzoneOverlay/styles.ts +79 -0
- package/src/FileUpload/components/FilePreviewList/FilePreviewList.tsx +251 -0
- package/src/FileUpload/components/FilePreviewList/virtualizerComponents/FilePreviewVirtualizedList/FilePreviewVirtualizedList.tsx +88 -0
- package/src/FileUpload/components/FileUpload/FileUpload.tsx +63 -0
- package/src/FileUpload/components/FileUploadCanvas/FileUploadCanvas.tsx +125 -0
- package/src/FileUpload/components/GridFileCard/GridFileCard.tsx +364 -0
- package/src/FileUpload/components/GridFileCard/utils/sortable.ts +48 -0
- package/src/FileUpload/components/ListFileCard/ListFileCard.tsx +259 -0
- package/src/FileUpload/components/types.ts +78 -0
- package/src/FileUpload/hooks/filePreview/useImageFilePreviewUrl.ts +62 -0
- package/src/FileUpload/hooks/index.ts +11 -0
- package/src/FileUpload/hooks/upload/useHandleDragEnter/useHandleDragEnter.ts +154 -0
- package/src/FileUpload/hooks/upload/useHandleDrop/createFileRejectionHelpers.ts +273 -0
- package/src/FileUpload/hooks/upload/useHandleDrop/useHandleDrop.ts +153 -0
- package/src/FileUpload/hooks/upload/useUploadAvailability/useUploadAvailability.ts +44 -0
- package/src/FileUpload/hooks/validation/createDropzoneValidator.ts +41 -0
- package/src/FileUpload/hooks/validation/useFileValidation.ts +25 -0
- package/src/FileUpload/hooks/validation/useFileValidationLogic.ts +107 -0
- package/src/FileUpload/hooks/validation/useValidationMessages.ts +92 -0
- package/src/FileUpload/hooks/validation/useValidationState.ts +171 -0
- package/src/FileUpload/index.ts +57 -0
- package/src/FileUpload/providers/FileUploadProvider.tsx +219 -0
- package/src/FileUpload/providers/UploadValidationProvider.tsx +159 -0
- package/src/FileUpload/testUtils/mockFilesAndImages.ts +64 -0
- package/src/FileUpload/testUtils/testUtils.ts +111 -0
- package/src/FileUpload/types/commonTypes.ts +267 -0
- package/src/FileUpload/types/index.ts +31 -0
- package/src/FileUpload/types/sharedTypes.ts +159 -0
- package/src/FileUpload/utils/constants.ts +79 -0
- package/src/FileUpload/utils/createMessageContext.ts +180 -0
- package/src/FileUpload/utils/getFileExtensionsFromAcceptedTypes.ts +73 -0
- package/src/FileUpload/utils/getFilePluralizationText.ts +68 -0
- package/src/FileUpload/utils/getMimeTypes.ts +26 -0
- package/src/FileUpload/utils/messageUtils.ts +41 -0
- package/src/FileUpload/utils/styles.ts +68 -0
- package/src/FormLabel/FormLabel.tsx +212 -0
- package/src/IconButton/IconButton.tsx +154 -0
- package/src/Icons/CreditCardIcon/CreditCardIcon.tsx +73 -0
- package/src/Icons/CreditCardIcon/cardIcons.tsx +270 -0
- package/src/Icons/IconBase.tsx +133 -0
- package/src/Icons/anyIcon.ts +3 -0
- package/src/Icons/generatedIcons/Archive.tsx +48 -0
- package/src/Icons/generatedIcons/ArrowClockwise.tsx +48 -0
- package/src/Icons/generatedIcons/ArrowDown.tsx +48 -0
- package/src/Icons/generatedIcons/ArrowLeft.tsx +48 -0
- package/src/Icons/generatedIcons/ArrowRight.tsx +48 -0
- package/src/Icons/generatedIcons/ArrowSquareOut.tsx +51 -0
- package/src/Icons/generatedIcons/ArrowSquareRight.tsx +51 -0
- package/src/Icons/generatedIcons/ArrowUp.tsx +48 -0
- package/src/Icons/generatedIcons/ArrowsCounterClockwise.tsx +48 -0
- package/src/Icons/generatedIcons/ArrowsLeftRight.tsx +48 -0
- package/src/Icons/generatedIcons/ArrowsOutCardinal.tsx +48 -0
- package/src/Icons/generatedIcons/Bank.tsx +48 -0
- package/src/Icons/generatedIcons/Bell.tsx +51 -0
- package/src/Icons/generatedIcons/BookBookmark.tsx +51 -0
- package/src/Icons/generatedIcons/BookmarksSimple.tsx +51 -0
- package/src/Icons/generatedIcons/Broadcast.tsx +48 -0
- package/src/Icons/generatedIcons/CalendarBlank.tsx +48 -0
- package/src/Icons/generatedIcons/CalendarStar.tsx +51 -0
- package/src/Icons/generatedIcons/Camera.tsx +51 -0
- package/src/Icons/generatedIcons/CaretDown.tsx +48 -0
- package/src/Icons/generatedIcons/CaretLeft.tsx +48 -0
- package/src/Icons/generatedIcons/CaretRight.tsx +48 -0
- package/src/Icons/generatedIcons/CaretUp.tsx +48 -0
- package/src/Icons/generatedIcons/Certificate.tsx +51 -0
- package/src/Icons/generatedIcons/ChartBar.tsx +48 -0
- package/src/Icons/generatedIcons/Check.tsx +51 -0
- package/src/Icons/generatedIcons/CheckCircle.tsx +48 -0
- package/src/Icons/generatedIcons/CirclesFour.tsx +51 -0
- package/src/Icons/generatedIcons/Clock.tsx +48 -0
- package/src/Icons/generatedIcons/ClockCountdown.tsx +48 -0
- package/src/Icons/generatedIcons/Close.tsx +51 -0
- package/src/Icons/generatedIcons/CloudArrowUp.tsx +51 -0
- package/src/Icons/generatedIcons/CloudWarning.tsx +51 -0
- package/src/Icons/generatedIcons/Code.tsx +48 -0
- package/src/Icons/generatedIcons/Compass.tsx +51 -0
- package/src/Icons/generatedIcons/Confetti.tsx +51 -0
- package/src/Icons/generatedIcons/Copy.tsx +48 -0
- package/src/Icons/generatedIcons/CornersOut.tsx +48 -0
- package/src/Icons/generatedIcons/CreditCard.tsx +48 -0
- package/src/Icons/generatedIcons/Crown.tsx +51 -0
- package/src/Icons/generatedIcons/CrownSimple.tsx +51 -0
- package/src/Icons/generatedIcons/CurrencyCircleDollar.tsx +48 -0
- package/src/Icons/generatedIcons/CurrencyDollarSimple.tsx +51 -0
- package/src/Icons/generatedIcons/Desktop.tsx +51 -0
- package/src/Icons/generatedIcons/Detective.tsx +51 -0
- package/src/Icons/generatedIcons/DotOutline.tsx +46 -0
- package/src/Icons/generatedIcons/DotsSixVertical.tsx +51 -0
- package/src/Icons/generatedIcons/DotsThreeOutline.tsx +51 -0
- package/src/Icons/generatedIcons/DotsThreeOutlineVertical.tsx +51 -0
- package/src/Icons/generatedIcons/DownloadSimple.tsx +51 -0
- package/src/Icons/generatedIcons/EnvelopeSimple.tsx +48 -0
- package/src/Icons/generatedIcons/Eraser.tsx +51 -0
- package/src/Icons/generatedIcons/Eye.tsx +51 -0
- package/src/Icons/generatedIcons/EyeSlash.tsx +51 -0
- package/src/Icons/generatedIcons/FacebookLogo.tsx +48 -0
- package/src/Icons/generatedIcons/FileArchive.tsx +48 -0
- package/src/Icons/generatedIcons/FileArrowDown.tsx +48 -0
- package/src/Icons/generatedIcons/FileCsv.tsx +48 -0
- package/src/Icons/generatedIcons/FilePdf.tsx +48 -0
- package/src/Icons/generatedIcons/FileText.tsx +48 -0
- package/src/Icons/generatedIcons/Files.tsx +51 -0
- package/src/Icons/generatedIcons/Fire.tsx +51 -0
- package/src/Icons/generatedIcons/Flag.tsx +51 -0
- package/src/Icons/generatedIcons/FlagBannerFold.tsx +48 -0
- package/src/Icons/generatedIcons/FloppyDisk.tsx +51 -0
- package/src/Icons/generatedIcons/Gauge.tsx +51 -0
- package/src/Icons/generatedIcons/Gavel.tsx +51 -0
- package/src/Icons/generatedIcons/Gear.tsx +51 -0
- package/src/Icons/generatedIcons/GlobeHemisphereWest.tsx +51 -0
- package/src/Icons/generatedIcons/GoogleLogo.tsx +48 -0
- package/src/Icons/generatedIcons/GridNine.tsx +51 -0
- package/src/Icons/generatedIcons/HandCoins.tsx +51 -0
- package/src/Icons/generatedIcons/HandbagSimple.tsx +51 -0
- package/src/Icons/generatedIcons/Headset.tsx +51 -0
- package/src/Icons/generatedIcons/HeartStraight.tsx +51 -0
- package/src/Icons/generatedIcons/HourglassLow.tsx +48 -0
- package/src/Icons/generatedIcons/House.tsx +51 -0
- package/src/Icons/generatedIcons/Image.tsx +51 -0
- package/src/Icons/generatedIcons/ImageSquare.tsx +51 -0
- package/src/Icons/generatedIcons/ImagesSquare.tsx +51 -0
- package/src/Icons/generatedIcons/Info.tsx +48 -0
- package/src/Icons/generatedIcons/InstagramLogo.tsx +51 -0
- package/src/Icons/generatedIcons/Lightning.tsx +48 -0
- package/src/Icons/generatedIcons/Link.tsx +51 -0
- package/src/Icons/generatedIcons/LinkedinLogo.tsx +51 -0
- package/src/Icons/generatedIcons/List.tsx +48 -0
- package/src/Icons/generatedIcons/Lock.tsx +51 -0
- package/src/Icons/generatedIcons/LockOpen.tsx +51 -0
- package/src/Icons/generatedIcons/MagnifyingGlass.tsx +48 -0
- package/src/Icons/generatedIcons/MapPin.tsx +51 -0
- package/src/Icons/generatedIcons/MapPinSimpleArea.tsx +48 -0
- package/src/Icons/generatedIcons/Medal.tsx +48 -0
- package/src/Icons/generatedIcons/Megaphone.tsx +48 -0
- package/src/Icons/generatedIcons/Minus.tsx +45 -0
- package/src/Icons/generatedIcons/Money.tsx +51 -0
- package/src/Icons/generatedIcons/Notches.tsx +48 -0
- package/src/Icons/generatedIcons/NotePencil.tsx +48 -0
- package/src/Icons/generatedIcons/Package.tsx +51 -0
- package/src/Icons/generatedIcons/PaintBrush.tsx +51 -0
- package/src/Icons/generatedIcons/PaperPlaneTilt.tsx +51 -0
- package/src/Icons/generatedIcons/Paperclip.tsx +51 -0
- package/src/Icons/generatedIcons/Pause.tsx +51 -0
- package/src/Icons/generatedIcons/PencilLine.tsx +51 -0
- package/src/Icons/generatedIcons/PencilRuler.tsx +51 -0
- package/src/Icons/generatedIcons/PencilSimple.tsx +51 -0
- package/src/Icons/generatedIcons/Phone.tsx +51 -0
- package/src/Icons/generatedIcons/PinterestLogo.tsx +51 -0
- package/src/Icons/generatedIcons/Play.tsx +51 -0
- package/src/Icons/generatedIcons/Plus.tsx +51 -0
- package/src/Icons/generatedIcons/PlusCircle.tsx +48 -0
- package/src/Icons/generatedIcons/Printer.tsx +51 -0
- package/src/Icons/generatedIcons/Question.tsx +48 -0
- package/src/Icons/generatedIcons/Receipt.tsx +51 -0
- package/src/Icons/generatedIcons/Rows.tsx +51 -0
- package/src/Icons/generatedIcons/SealCheck.tsx +51 -0
- package/src/Icons/generatedIcons/SelectionSlash.tsx +48 -0
- package/src/Icons/generatedIcons/ShareNetwork.tsx +51 -0
- package/src/Icons/generatedIcons/ShieldCheck.tsx +51 -0
- package/src/Icons/generatedIcons/ShieldStar.tsx +51 -0
- package/src/Icons/generatedIcons/ShoppingCart.tsx +48 -0
- package/src/Icons/generatedIcons/ShuffleAngular.tsx +48 -0
- package/src/Icons/generatedIcons/SidebarSimple.tsx +48 -0
- package/src/Icons/generatedIcons/SlidersHorizontal.tsx +51 -0
- package/src/Icons/generatedIcons/Smiley.tsx +48 -0
- package/src/Icons/generatedIcons/Sparkle.tsx +51 -0
- package/src/Icons/generatedIcons/SpinnerGap.tsx +48 -0
- package/src/Icons/generatedIcons/StackPlus.tsx +48 -0
- package/src/Icons/generatedIcons/Star.tsx +51 -0
- package/src/Icons/generatedIcons/Storefront.tsx +51 -0
- package/src/Icons/generatedIcons/Swap.tsx +51 -0
- package/src/Icons/generatedIcons/Tag.tsx +51 -0
- package/src/Icons/generatedIcons/ThumbsDown.tsx +48 -0
- package/src/Icons/generatedIcons/ThumbsUp.tsx +48 -0
- package/src/Icons/generatedIcons/Toolbox.tsx +48 -0
- package/src/Icons/generatedIcons/Trash.tsx +48 -0
- package/src/Icons/generatedIcons/TrendUp.tsx +48 -0
- package/src/Icons/generatedIcons/Trophy.tsx +51 -0
- package/src/Icons/generatedIcons/Truck.tsx +51 -0
- package/src/Icons/generatedIcons/UploadSimple.tsx +51 -0
- package/src/Icons/generatedIcons/User.tsx +48 -0
- package/src/Icons/generatedIcons/Users.tsx +48 -0
- package/src/Icons/generatedIcons/UsersThree.tsx +51 -0
- package/src/Icons/generatedIcons/VideoCamera.tsx +51 -0
- package/src/Icons/generatedIcons/Warning.tsx +51 -0
- package/src/Icons/generatedIcons/WarningCircle.tsx +48 -0
- package/src/Icons/generatedIcons/WifiHigh.tsx +51 -0
- package/src/Icons/generatedIcons/XCircle.tsx +48 -0
- package/src/Icons/generatedIcons/XLogo.tsx +48 -0
- package/src/Icons/generatedIcons/YoutubeLogo.tsx +51 -0
- package/src/Icons/importedIcons.ts +152 -0
- package/src/Icons/index.ts +149 -0
- package/src/Icons/socialIcons/appleSocialIcon.tsx +50 -0
- package/src/Icons/socialIcons/facebookSocialIcon.tsx +41 -0
- package/src/Icons/socialIcons/googleSocialIcon.tsx +134 -0
- package/src/ImageCluster/ImageCluster.tsx +125 -0
- package/src/ImageSlider/ImageSlider.tsx +582 -0
- package/src/ImageSlider/ImageSlider.types.ts +90 -0
- package/src/ImageSlider/components/IndexIndicator/IndexIndicator.tsx +21 -0
- package/src/ImageSlider/components/NavigationButtons/NavigationButtons.tsx +113 -0
- package/src/ImageSlider/components/ResponsiveImage/ResponsiveImage.tsx +114 -0
- package/src/ImageSlider/components/ResponsiveImage/index.ts +1 -0
- package/src/ImageSlider/components/Thumbnails/Thumbnails.tsx +184 -0
- package/src/ImageSlider/constants.ts +59 -0
- package/src/ImageSlider/hooks/index.ts +3 -0
- package/src/ImageSlider/hooks/useImageSlider.ts +57 -0
- package/src/ImageSlider/hooks/useImageSliderNavigation.ts +133 -0
- package/src/ImageSlider/hooks/useImageSliderScrollHandler.ts +171 -0
- package/src/ImageSlider/index.ts +3 -0
- package/src/ImageSlider/utils/imageOptimization.ts +97 -0
- package/src/ImageSlider/utils/index.ts +1 -0
- package/src/InlineNotification/InlineNotification.tsx +95 -0
- package/src/JumpMenu/JumpMenu.tsx +395 -0
- package/src/JumpMenu/components/JumpMenuItem/JumpMenuItem.tsx +62 -0
- package/src/JumpMenu/hooks/useContainerTracking.ts +171 -0
- package/src/JumpMenu/hooks/useIntersectionObserver.ts +77 -0
- package/src/JumpMenu/hooks/useKeyboardNavigation.ts +102 -0
- package/src/JumpMenu/hooks/useResizeObserver.ts +53 -0
- package/src/JumpMenu/hooks/useSectionObserver.ts +102 -0
- package/src/JumpMenu/index.ts +2 -0
- package/src/JumpMenu/types/index.ts +19 -0
- package/src/Loading/Loading.tsx +39 -0
- package/src/Loading/components/LoadingDot/LoadingDot.tsx +16 -0
- package/src/LoadingSpinner/LoadingSpinner.tsx +20 -0
- package/src/Menu/Menu.tsx +372 -0
- package/src/Menu/components/MenuDivider/MenuDivider.tsx +5 -0
- package/src/Menu/components/MenuItem/MenuItem.tsx +298 -0
- package/src/Menu/context/menuContext.tsx +20 -0
- package/src/Menu/hooks/useMenu.tsx +18 -0
- package/src/Menu/index.ts +3 -0
- package/src/Modal/ComposableModal.tsx +313 -0
- package/src/Modal/Modal.tsx +231 -0
- package/src/Modal/components/BackButton/BackButton.tsx +43 -0
- package/src/Modal/components/Backdrop/Backdrop.tsx +62 -0
- package/src/Modal/components/CloseButton/CloseButton.tsx +55 -0
- package/src/Modal/components/ModalActions/ModalActions.tsx +135 -0
- package/src/Modal/components/ModalContent/ModalContent.tsx +163 -0
- package/src/Modal/components/ModalHeader/ModalHeader.tsx +84 -0
- package/src/Modal/components/ModalHeader/hooks/useHeaderAnimation.tsx +49 -0
- package/src/Modal/components/ModalProgressSteps/ModalProgressSteps.tsx +26 -0
- package/src/Modal/components/ModalSubTitle/ModalSubTitle.tsx +29 -0
- package/src/Modal/components/ModalTitle/ModalTitle.tsx +22 -0
- package/src/Modal/components/PreventModalScroll/PreventModalScroll.tsx +106 -0
- package/src/Modal/components/index.ts +12 -0
- package/src/Modal/context.ts +33 -0
- package/src/Modal/hooks/useCloseModal.ts +133 -0
- package/src/NotificationBadge/NotificationBadge.tsx +34 -0
- package/src/Pagination/AdvancedPagination.tsx +48 -0
- package/src/Pagination/Pagination.tsx +216 -0
- package/src/Pagination/components/AdvancedPaginator/AdvancedPaginator.tsx +52 -0
- package/src/Pagination/components/AdvancedPaginator/components/PageSelect/PageSelect.tsx +43 -0
- package/src/Pagination/components/ItemCountDisplay/ItemCountDisplay.tsx +32 -0
- package/src/Pagination/components/ItemCountSelect/ItemCountSelect.tsx +33 -0
- package/src/Pagination/index.tsx +3 -0
- package/src/Pagination/paginationProvider.tsx +234 -0
- package/src/Pagination/utils.tsx +36 -0
- package/src/PhoneInput/PhoneInput.tsx +509 -0
- package/src/PhoneInput/useDropdownLogic.tsx +163 -0
- package/src/ProgressCircle/ProgressCircle.tsx +246 -0
- package/src/ProgressCircle/hooks/useProgressStatusTransitions.ts +49 -0
- package/src/ProgressCircle/utils/progressCircle.constants.ts +27 -0
- package/src/ProgressSteps/ProgressSteps.tsx +160 -0
- package/src/SaveConfetti/SaveConfetti.tsx +277 -0
- package/src/SaveConfetti/index.ts +2 -0
- package/src/SearchInput/SearchInput.tsx +236 -0
- package/src/SegmentedControl/SegmentedControl.tsx +111 -0
- package/src/SegmentedControl/SegmentedControlGroup.tsx +94 -0
- package/src/SegmentedControl/index.ts +4 -0
- package/src/Select/Select.tsx +154 -0
- package/src/Select/SelectAsync.tsx +13 -0
- package/src/Select/SelectAsyncCreatable.tsx +14 -0
- package/src/Select/SelectCreatable.tsx +12 -0
- package/src/Select/reexportedComponents.tsx +5 -0
- package/src/Select/selectComponents.tsx +306 -0
- package/src/Skeleton/Skeleton.tsx +13 -0
- package/src/SplitButton/SplitButton.tsx +298 -0
- package/src/SplitButton/SplitButtonTrigger.tsx +55 -0
- package/src/StarRating/StarRating.tsx +165 -0
- package/src/StarRating/components/StarComponent/StarComponent.tsx +44 -0
- package/src/Table/Table.tsx +474 -0
- package/src/Table/components/TableHeader/TableHeader.tsx +166 -0
- package/src/Table/components/TablePagination/TablePagination.tsx +18 -0
- package/src/Table/components/TablePagination/components/ItemCountDisplay/ItemCountDisplay.tsx +17 -0
- package/src/Table/components/TablePagination/components/ItemCountSelect/ItemCountSelect.tsx +31 -0
- package/src/Table/components/TablePagination/components/TablePaginator/TablePaginator.tsx +37 -0
- package/src/Table/components/TablePagination/components/TablePaginator/components/PageSelect/PageSelect.tsx +32 -0
- package/src/Table/components/TableRow/TableRows.tsx +147 -0
- package/src/Table/components/TableRow/components/TableRowCell/TableRowCell.tsx +49 -0
- package/src/Table/components/TableShadow/TableShadow.tsx +46 -0
- package/src/Table/index.ts +2 -0
- package/src/Table/sharedState.ts +30 -0
- package/src/Table/sharedStyles.ts +1 -0
- package/src/Table/types.ts +55 -0
- package/src/Tabs/Tabs.tsx +358 -0
- package/src/TextArea/TextArea.tsx +157 -0
- package/src/TextInput/TextInput.tsx +173 -0
- package/src/Toast/Toast.tsx +64 -0
- package/src/Toast/components/ToastContainer/ToastContainer.tsx +48 -0
- package/src/Toast/index.ts +2 -0
- package/src/Toast/types/role.ts +1 -0
- package/src/Toast/utils/getIcon.tsx +41 -0
- package/src/ToggleSwitch/ToggleSwitch.tsx +188 -0
- package/src/Tooltip/InfoIconTooltip.tsx +47 -0
- package/src/Tooltip/Tooltip.tsx +41 -0
- package/src/Typography/InlineButton/InlineButton.tsx +166 -0
- package/src/Typography/Links/Links.tsx +113 -0
- package/src/Typography/Text/Text.tsx +239 -0
- package/src/ViewMore/ViewMore.tsx +226 -0
- package/src/WebRTCPlayer/WebRTCPlayer.tsx +325 -0
- package/src/WebRTCPlayer/adaptor/NativeWebRTCAdaptor.ts +588 -0
- package/src/WebRTCPlayer/hooks/useWebRTCStream.ts +571 -0
- package/src/WebRTCPlayer/index.ts +22 -0
- package/src/WebRTCPlayer/types.ts +95 -0
- package/src/breakpoints/index.tsx +1 -0
- package/src/breakpoints/utils.tsx +50 -0
- package/src/declarations.d.ts +7 -0
- package/src/grid/gridHighlighter.tsx +83 -0
- package/src/grid/index.ts +3 -0
- package/src/grid/pageGrid.tsx +37 -0
- package/src/grid/useSubGridCSS.tsx +214 -0
- package/src/hooks/useHorizontalScrollFade.ts +44 -0
- package/src/hooks/usePrevious.ts +14 -0
- package/src/index.ts +351 -0
- package/src/intl/index.ts +4 -0
- package/src/intl/utils.ts +67 -0
- package/src/mixins/horizontalScrollFadeMixin.ts +56 -0
- package/src/mixins/index.ts +18 -0
- package/src/mixins/propMixins.ts +389 -0
- package/src/providers/createContextProvider.ts +22 -0
- package/src/providers/designSystemProvider.tsx +218 -0
- package/src/providers/errorBoundaryProvider.tsx +179 -0
- package/src/providers/featureFlagProvider.tsx +18 -0
- package/src/providers/gridSizeProvider.tsx +23 -0
- package/src/providers/index.ts +12 -0
- package/src/providers/linkProvider.tsx +32 -0
- package/src/providers/normalize.tsx +93 -0
- package/src/providers/targets/DatePickerTarget.tsx +10 -0
- package/src/providers/targets/ModalTarget.tsx +14 -0
- package/src/providers/targets/TimePickerTarget.tsx +10 -0
- package/src/providers/themeContext.tsx +24 -0
- package/src/providers/windowSizeProvider.tsx +125 -0
- package/src/spacing/index.ts +1 -0
- package/src/spacing/spacing.ts +11 -0
- package/src/utils/countriesWithISOCodes.ts +1419 -0
- package/src/utils/dateTimeFormat.ts +257 -0
- package/src/utils/effectEventListener.ts +11 -0
- package/src/utils/formatFileSize.ts +18 -0
- package/src/utils/isClientSide.ts +1 -0
- package/src/utils/keepTransition.ts +15 -0
- package/src/utils/nodeEnv.ts +9 -0
- package/src/utils/smoothScrollTo.ts +47 -0
- package/src/utils/utilityTypes.ts +13 -0
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
import { rubberbandIfOutOfBounds } from '@use-gesture/react';
|
|
2
|
+
import { RefObject, useCallback, useEffect, useRef } from 'react';
|
|
3
|
+
|
|
4
|
+
import type { BottomSheetEvent, SnapPayload } from '../state/atoms';
|
|
5
|
+
import type { Spring, SpringAPI } from './useSpring';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* The subset of use-gesture's drag state the handler reads.
|
|
9
|
+
* Structurally compatible with `FullGestureState<'drag'>`, so the handler can be
|
|
10
|
+
* passed straight to `useDrag` without widening any parameter to `any`.
|
|
11
|
+
*/
|
|
12
|
+
export type DragState = {
|
|
13
|
+
args?: { closeOnTap?: boolean }[];
|
|
14
|
+
cancel: () => void;
|
|
15
|
+
direction?: [number, number];
|
|
16
|
+
down?: boolean;
|
|
17
|
+
first?: boolean;
|
|
18
|
+
last?: boolean;
|
|
19
|
+
memo?: number;
|
|
20
|
+
movement?: [number, number];
|
|
21
|
+
tap?: boolean;
|
|
22
|
+
velocity?: [number, number];
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Props for the drag handler hook
|
|
27
|
+
*/
|
|
28
|
+
type UseDragHandlerProps = {
|
|
29
|
+
/** Spring API object for controlling animations */
|
|
30
|
+
api: SpringAPI;
|
|
31
|
+
/** Reference to track if dragging is allowed */
|
|
32
|
+
canDragRef: RefObject<boolean>;
|
|
33
|
+
/** Reference to the current max height value */
|
|
34
|
+
maxHeightRef: RefObject<number>;
|
|
35
|
+
/** Reference to the current max snap value */
|
|
36
|
+
maxSnapRef: RefObject<number>;
|
|
37
|
+
/** Reference to the current min snap value */
|
|
38
|
+
minSnapRef: RefObject<number>;
|
|
39
|
+
/** Dismiss handler function */
|
|
40
|
+
onDismiss?: () => void;
|
|
41
|
+
/** Reference to track if scrolling should be prevented */
|
|
42
|
+
preventScrollingRef: RefObject<boolean>;
|
|
43
|
+
/** Function to send events to the state machine */
|
|
44
|
+
send: (event: BottomSheetEvent['type'], payload?: SnapPayload) => void;
|
|
45
|
+
/** Spring object with current values */
|
|
46
|
+
spring: Spring;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Custom hook to handle drag interactions for the bottom sheet
|
|
51
|
+
*/
|
|
52
|
+
export const useDragHandler = ({
|
|
53
|
+
api,
|
|
54
|
+
canDragRef,
|
|
55
|
+
maxHeightRef,
|
|
56
|
+
maxSnapRef,
|
|
57
|
+
minSnapRef,
|
|
58
|
+
onDismiss,
|
|
59
|
+
preventScrollingRef,
|
|
60
|
+
send,
|
|
61
|
+
spring,
|
|
62
|
+
}: UseDragHandlerProps) => {
|
|
63
|
+
// Create stable refs for the functions to avoid recreating the drag handler
|
|
64
|
+
const sendRef = useRef(send);
|
|
65
|
+
const apiRef = useRef(api);
|
|
66
|
+
const onDismissRef = useRef(onDismiss);
|
|
67
|
+
const springRef = useRef(spring);
|
|
68
|
+
|
|
69
|
+
// Performance optimization: Throttle drag updates using RAF
|
|
70
|
+
const rafRef = useRef<number>(0);
|
|
71
|
+
const lastUpdateRef = useRef<number>(0);
|
|
72
|
+
|
|
73
|
+
// DEBUGGING: Track active timers and RAF calls
|
|
74
|
+
const activeTimersRef = useRef<Set<ReturnType<typeof setTimeout>>>(new Set());
|
|
75
|
+
const activeRAFsRef = useRef<Set<number>>(new Set());
|
|
76
|
+
|
|
77
|
+
// Cleanup function to clear all pending timers and RAF calls
|
|
78
|
+
const cleanupPendingCalls = useCallback(() => {
|
|
79
|
+
// Clear all pending RAF calls
|
|
80
|
+
activeRAFsRef.current.forEach((id) => {
|
|
81
|
+
cancelAnimationFrame(id);
|
|
82
|
+
});
|
|
83
|
+
activeRAFsRef.current.clear();
|
|
84
|
+
|
|
85
|
+
// Clear all pending timers
|
|
86
|
+
activeTimersRef.current.forEach((id) => {
|
|
87
|
+
clearTimeout(id);
|
|
88
|
+
});
|
|
89
|
+
activeTimersRef.current.clear();
|
|
90
|
+
|
|
91
|
+
// Clear the main RAF ref
|
|
92
|
+
if (rafRef.current) {
|
|
93
|
+
cancelAnimationFrame(rafRef.current);
|
|
94
|
+
rafRef.current = 0;
|
|
95
|
+
}
|
|
96
|
+
}, []);
|
|
97
|
+
|
|
98
|
+
// Cleanup on unmount - force cleanup of all pending operations
|
|
99
|
+
useEffect(() => {
|
|
100
|
+
return () => {
|
|
101
|
+
cleanupPendingCalls();
|
|
102
|
+
};
|
|
103
|
+
}, [cleanupPendingCalls]);
|
|
104
|
+
|
|
105
|
+
// Update refs when functions change
|
|
106
|
+
sendRef.current = send;
|
|
107
|
+
apiRef.current = api;
|
|
108
|
+
onDismissRef.current = onDismiss;
|
|
109
|
+
springRef.current = spring;
|
|
110
|
+
|
|
111
|
+
const handleDrag = useCallback(
|
|
112
|
+
(state: DragState) => {
|
|
113
|
+
// Clean up any pending timers/RAF at the start of each drag operation
|
|
114
|
+
if (state?.first) {
|
|
115
|
+
cleanupPendingCalls();
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Optimize: Avoid destructuring and use direct property access to reduce object creation
|
|
119
|
+
const args = state?.args || [];
|
|
120
|
+
const cancel = state?.cancel;
|
|
121
|
+
const direction = state?.direction?.[1] || 0; // Only need Y direction
|
|
122
|
+
const down = state?.down;
|
|
123
|
+
const first = state?.first;
|
|
124
|
+
const last = state?.last;
|
|
125
|
+
const memo = state?.memo ?? (springRef.current.y.get() as number);
|
|
126
|
+
const movement = state?.movement || [0, 0];
|
|
127
|
+
const tap = state?.tap;
|
|
128
|
+
const velocity = state?.velocity || [0, 0];
|
|
129
|
+
|
|
130
|
+
// Extract closeOnTap from args if available, default to false
|
|
131
|
+
const closeOnTap = args[0]?.closeOnTap || false;
|
|
132
|
+
const _my = movement[1];
|
|
133
|
+
const velocityY = velocity[1]; // Extract y-component of velocity
|
|
134
|
+
const my = _my * -1;
|
|
135
|
+
|
|
136
|
+
// Cancel the drag operation if the canDrag state changed
|
|
137
|
+
if (!canDragRef.current) {
|
|
138
|
+
cancel();
|
|
139
|
+
return memo;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if (onDismissRef.current && closeOnTap && tap) {
|
|
143
|
+
cancel();
|
|
144
|
+
// Runs onDismiss in a timeout to avoid tap events on the backdrop from triggering click events on elements underneath
|
|
145
|
+
const timerId = setTimeout(() => {
|
|
146
|
+
activeTimersRef.current.delete(timerId);
|
|
147
|
+
onDismissRef.current?.();
|
|
148
|
+
}, 0);
|
|
149
|
+
activeTimersRef.current.add(timerId);
|
|
150
|
+
return memo;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Filter out taps
|
|
154
|
+
if (tap) {
|
|
155
|
+
return memo;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Note: Content dragging has been removed - only header/handle area can drag the sheet
|
|
159
|
+
|
|
160
|
+
const rawY = memo + my;
|
|
161
|
+
// More natural velocity prediction with proper deceleration
|
|
162
|
+
// Use a smaller multiplier and consider the velocity direction more carefully
|
|
163
|
+
const velocityFactor = Math.min(Math.abs(velocityY), 2); // Cap velocity influence
|
|
164
|
+
const predictedDistance = my * velocityFactor * 0.3; // Much gentler prediction
|
|
165
|
+
// Allow going below minSnap for close detection, but clamp for normal snapping
|
|
166
|
+
const unclamped = rawY + predictedDistance;
|
|
167
|
+
const predictedY = onDismissRef.current
|
|
168
|
+
? Math.min(maxSnapRef.current, unclamped) // Allow below minSnap if dismissible
|
|
169
|
+
: Math.max(minSnapRef.current, Math.min(maxSnapRef.current, unclamped)); // Normal clamping
|
|
170
|
+
|
|
171
|
+
if (!down && onDismissRef.current && direction > 0 && rawY + predictedDistance < minSnapRef.current / 2) {
|
|
172
|
+
cancel();
|
|
173
|
+
onDismissRef.current();
|
|
174
|
+
return memo;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const newY = down
|
|
178
|
+
? // Handle rubberband when min and max snap points are equal (single snap point)
|
|
179
|
+
!onDismissRef.current && minSnapRef.current === maxSnapRef.current
|
|
180
|
+
? // For single snap point, create symmetric rubberband effect
|
|
181
|
+
rubberbandIfOutOfBounds(
|
|
182
|
+
rawY,
|
|
183
|
+
minSnapRef.current * 0.5, // Allow some downward stretch
|
|
184
|
+
minSnapRef.current * 1.5, // Allow some upward stretch
|
|
185
|
+
0.55
|
|
186
|
+
)
|
|
187
|
+
: rubberbandIfOutOfBounds(
|
|
188
|
+
rawY,
|
|
189
|
+
onDismissRef.current ? 0 : minSnapRef.current,
|
|
190
|
+
maxSnapRef.current,
|
|
191
|
+
0.55
|
|
192
|
+
)
|
|
193
|
+
: predictedY;
|
|
194
|
+
|
|
195
|
+
// Since content dragging is disabled, we don't need to prevent scrolling
|
|
196
|
+
preventScrollingRef.current = false;
|
|
197
|
+
|
|
198
|
+
if (first) {
|
|
199
|
+
sendRef.current('DRAG');
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (last) {
|
|
203
|
+
// Add small delay to prevent rapid state changes
|
|
204
|
+
const timerId1 = setTimeout(() => {
|
|
205
|
+
activeTimersRef.current.delete(timerId1);
|
|
206
|
+
// Check if should close instead of snap
|
|
207
|
+
// Use unclamped position for close detection
|
|
208
|
+
const closePosition = rawY + my * velocityFactor * 0.3;
|
|
209
|
+
const shouldClose =
|
|
210
|
+
onDismissRef.current &&
|
|
211
|
+
// Close if dragged significantly below minSnap
|
|
212
|
+
(closePosition < minSnapRef.current * 0.75 ||
|
|
213
|
+
// Close if moving downward with significant velocity
|
|
214
|
+
(velocityY < -0.5 && closePosition < minSnapRef.current));
|
|
215
|
+
|
|
216
|
+
if (shouldClose) {
|
|
217
|
+
// Call onDismiss directly like the backdrop click does
|
|
218
|
+
// This triggers the same close animation as clicking the backdrop
|
|
219
|
+
cancel();
|
|
220
|
+
const timerId2 = setTimeout(() => {
|
|
221
|
+
activeTimersRef.current.delete(timerId2);
|
|
222
|
+
onDismissRef.current?.();
|
|
223
|
+
}, 0);
|
|
224
|
+
activeTimersRef.current.add(timerId2);
|
|
225
|
+
} else {
|
|
226
|
+
sendRef.current('SNAP', {
|
|
227
|
+
source: 'dragging',
|
|
228
|
+
velocity: Math.abs(velocityY) > 0.01 ? Math.abs(velocityY) : 0.5,
|
|
229
|
+
y: newY,
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
}, 0);
|
|
233
|
+
activeTimersRef.current.add(timerId1);
|
|
234
|
+
|
|
235
|
+
return memo;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// Performance optimization: Throttle spring updates to ~60fps during dragging
|
|
239
|
+
const now = performance.now();
|
|
240
|
+
if (now - lastUpdateRef.current < 16) {
|
|
241
|
+
// ~60fps throttling
|
|
242
|
+
// Cancel any pending RAF and schedule new one
|
|
243
|
+
if (rafRef.current) {
|
|
244
|
+
activeRAFsRef.current.delete(rafRef.current);
|
|
245
|
+
cancelAnimationFrame(rafRef.current);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
rafRef.current = requestAnimationFrame(() => {
|
|
249
|
+
activeRAFsRef.current.delete(rafRef.current);
|
|
250
|
+
apiRef.current.start({
|
|
251
|
+
config: { velocity: velocityY },
|
|
252
|
+
immediate: true,
|
|
253
|
+
maxHeight: maxHeightRef.current,
|
|
254
|
+
maxSnap: maxSnapRef.current,
|
|
255
|
+
minSnap: minSnapRef.current,
|
|
256
|
+
y: newY,
|
|
257
|
+
});
|
|
258
|
+
lastUpdateRef.current = performance.now();
|
|
259
|
+
rafRef.current = 0;
|
|
260
|
+
});
|
|
261
|
+
activeRAFsRef.current.add(rafRef.current);
|
|
262
|
+
} else {
|
|
263
|
+
// Update immediately if enough time has passed
|
|
264
|
+
apiRef.current.start({
|
|
265
|
+
config: { velocity: velocityY },
|
|
266
|
+
immediate: true,
|
|
267
|
+
maxHeight: maxHeightRef.current,
|
|
268
|
+
maxSnap: maxSnapRef.current,
|
|
269
|
+
minSnap: minSnapRef.current,
|
|
270
|
+
y: newY,
|
|
271
|
+
});
|
|
272
|
+
lastUpdateRef.current = now;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
return memo;
|
|
276
|
+
},
|
|
277
|
+
[canDragRef, preventScrollingRef, minSnapRef, maxSnapRef, maxHeightRef, cleanupPendingCalls]
|
|
278
|
+
// Removed spring.y from deps since we access it via spring.y.get() inside the callback
|
|
279
|
+
);
|
|
280
|
+
|
|
281
|
+
return { handleDrag };
|
|
282
|
+
};
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { RefObject, useDebugValue, useEffect, useRef } from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Lightweight focus trap implementation without external dependencies
|
|
5
|
+
* Provides basic focus management for modal/sheet components
|
|
6
|
+
*/
|
|
7
|
+
export const useFocusTrap = ({
|
|
8
|
+
enabled,
|
|
9
|
+
fallbackRef,
|
|
10
|
+
initialFocusRef,
|
|
11
|
+
targetRef,
|
|
12
|
+
}: {
|
|
13
|
+
enabled: boolean;
|
|
14
|
+
fallbackRef: RefObject<HTMLElement>;
|
|
15
|
+
initialFocusRef?: RefObject<HTMLElement>;
|
|
16
|
+
targetRef: RefObject<HTMLElement>;
|
|
17
|
+
}) => {
|
|
18
|
+
// eslint-disable-next-line func-call-spacing
|
|
19
|
+
const ref = useRef<{ activate: () => void; deactivate: () => void }>({
|
|
20
|
+
activate: () => {
|
|
21
|
+
throw new TypeError('Tried to activate focus trap too early');
|
|
22
|
+
},
|
|
23
|
+
deactivate: () => {},
|
|
24
|
+
});
|
|
25
|
+
const previousActiveElement = useRef<Element | null>(null);
|
|
26
|
+
|
|
27
|
+
useDebugValue(enabled ? 'Enabled' : 'Disabled');
|
|
28
|
+
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
if (!enabled) {
|
|
31
|
+
ref.current.deactivate();
|
|
32
|
+
ref.current = { activate: () => {}, deactivate: () => {} };
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const target = targetRef.current;
|
|
37
|
+
let active = false;
|
|
38
|
+
|
|
39
|
+
const getFocusableElements = (container: HTMLElement): HTMLElement[] => {
|
|
40
|
+
const focusableSelectors = [
|
|
41
|
+
'button:not([disabled])',
|
|
42
|
+
'input:not([disabled])',
|
|
43
|
+
'textarea:not([disabled])',
|
|
44
|
+
'select:not([disabled])',
|
|
45
|
+
'a[href]',
|
|
46
|
+
'[tabindex]:not([tabindex="-1"])',
|
|
47
|
+
].join(', ');
|
|
48
|
+
|
|
49
|
+
return Array.from(container.querySelectorAll(focusableSelectors)) as HTMLElement[];
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const handleKeyDown = (e: KeyboardEvent) => {
|
|
53
|
+
// eslint-disable-next-line @typescript-eslint/prefer-optional-chain, @typescript-eslint/no-unnecessary-condition
|
|
54
|
+
if (!active || !target || e.key !== 'Tab') {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const focusableElements = getFocusableElements(target);
|
|
59
|
+
if (focusableElements.length === 0) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const firstElement = focusableElements[0];
|
|
64
|
+
const lastElement = focusableElements[focusableElements.length - 1];
|
|
65
|
+
|
|
66
|
+
if (e.shiftKey) {
|
|
67
|
+
if (document.activeElement === firstElement) {
|
|
68
|
+
e.preventDefault();
|
|
69
|
+
lastElement.focus();
|
|
70
|
+
}
|
|
71
|
+
} else if (document.activeElement === lastElement) {
|
|
72
|
+
e.preventDefault();
|
|
73
|
+
firstElement.focus();
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
ref.current = {
|
|
78
|
+
activate: () => {
|
|
79
|
+
// eslint-disable-next-line @typescript-eslint/prefer-optional-chain, @typescript-eslint/no-unnecessary-condition
|
|
80
|
+
if (active || !target) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
active = true;
|
|
84
|
+
|
|
85
|
+
// Store the previously focused element
|
|
86
|
+
previousActiveElement.current = document.activeElement;
|
|
87
|
+
|
|
88
|
+
// Add event listener for tab trapping
|
|
89
|
+
document.addEventListener('keydown', handleKeyDown);
|
|
90
|
+
},
|
|
91
|
+
deactivate: () => {
|
|
92
|
+
if (!active) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
active = false;
|
|
96
|
+
|
|
97
|
+
// Remove event listener
|
|
98
|
+
document.removeEventListener('keydown', handleKeyDown);
|
|
99
|
+
|
|
100
|
+
// Restore focus to previously focused element
|
|
101
|
+
if (
|
|
102
|
+
previousActiveElement.current &&
|
|
103
|
+
typeof (previousActiveElement.current as HTMLElement).focus === 'function'
|
|
104
|
+
) {
|
|
105
|
+
(previousActiveElement.current as HTMLElement).focus();
|
|
106
|
+
}
|
|
107
|
+
previousActiveElement.current = null;
|
|
108
|
+
},
|
|
109
|
+
};
|
|
110
|
+
}, [enabled, fallbackRef, initialFocusRef, targetRef]);
|
|
111
|
+
|
|
112
|
+
return ref;
|
|
113
|
+
};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { useEffect, useLayoutEffect as useLayoutEffectSafely } from 'react';
|
|
2
|
+
|
|
3
|
+
// Ensure the name used in components is useLayoutEffect so the eslint react hooks plugin works
|
|
4
|
+
export const useLayoutEffect = typeof window !== 'undefined' ? useLayoutEffectSafely : useEffect;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { ResizeObserver, ResizeObserverEntry } from '@juggle/resize-observer';
|
|
2
|
+
import { ResizeObserverOptions } from '@juggle/resize-observer/lib/ResizeObserverOptions';
|
|
3
|
+
import { RefObject, useCallback, useEffect, useRef } from 'react';
|
|
4
|
+
|
|
5
|
+
import type { ResizeSource } from '../types';
|
|
6
|
+
|
|
7
|
+
const observerOptions: ResizeObserverOptions = {
|
|
8
|
+
box: 'border-box',
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Performance-optimized hook that combines multiple resize observers into a single observer
|
|
13
|
+
* with throttled updates using requestAnimationFrame
|
|
14
|
+
*/
|
|
15
|
+
export const useOptimizedResizeObserver = (
|
|
16
|
+
targets: Array<{
|
|
17
|
+
enabled: boolean;
|
|
18
|
+
label: string;
|
|
19
|
+
onResize: (size: number) => void;
|
|
20
|
+
ref: RefObject<Element>;
|
|
21
|
+
}>,
|
|
22
|
+
resizeSourceRef: RefObject<ResizeSource>
|
|
23
|
+
) => {
|
|
24
|
+
const rafRef = useRef<number>(0);
|
|
25
|
+
const pendingUpdatesRef = useRef<Map<string, number>>(new Map());
|
|
26
|
+
|
|
27
|
+
const handleResize = useCallback(
|
|
28
|
+
(entries: ResizeObserverEntry[]) => {
|
|
29
|
+
// Cancel any pending RAF to throttle updates
|
|
30
|
+
if (rafRef.current) {
|
|
31
|
+
cancelAnimationFrame(rafRef.current);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Collect all size updates
|
|
35
|
+
entries.forEach((entry) => {
|
|
36
|
+
const element = entry.target;
|
|
37
|
+
const size = entry.borderBoxSize[0].blockSize;
|
|
38
|
+
|
|
39
|
+
// Find the corresponding target by element reference
|
|
40
|
+
const target = targets.find((t) => t.ref.current === element);
|
|
41
|
+
if (target?.enabled) {
|
|
42
|
+
pendingUpdatesRef.current.set(target.label, size);
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
// Process all updates in a single RAF
|
|
47
|
+
rafRef.current = requestAnimationFrame(() => {
|
|
48
|
+
const updates = pendingUpdatesRef.current;
|
|
49
|
+
|
|
50
|
+
// Apply all size updates
|
|
51
|
+
targets.forEach((target) => {
|
|
52
|
+
if (target.enabled && updates.has(target.label)) {
|
|
53
|
+
const size = updates.get(target.label)!;
|
|
54
|
+
target.onResize(size);
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
// Set resize source after all updates
|
|
59
|
+
if (updates.size > 0) {
|
|
60
|
+
resizeSourceRef.current = 'element';
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Clear pending updates
|
|
64
|
+
updates.clear();
|
|
65
|
+
rafRef.current = 0;
|
|
66
|
+
});
|
|
67
|
+
},
|
|
68
|
+
[targets, resizeSourceRef]
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
useEffect(() => {
|
|
72
|
+
const elementsToObserve = targets
|
|
73
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
74
|
+
.filter((target) => target.ref.current && target.enabled)
|
|
75
|
+
.map((target) => target.ref.current!);
|
|
76
|
+
|
|
77
|
+
if (elementsToObserve.length === 0) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const resizeObserver = new ResizeObserver(handleResize);
|
|
82
|
+
|
|
83
|
+
elementsToObserve.forEach((element) => {
|
|
84
|
+
resizeObserver.observe(element, observerOptions);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
return () => {
|
|
88
|
+
resizeObserver.disconnect();
|
|
89
|
+
if (rafRef.current) {
|
|
90
|
+
cancelAnimationFrame(rafRef.current);
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
}, [handleResize, targets]);
|
|
94
|
+
};
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { RefObject, useCallback, useEffect, useRef, useState } from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Custom hook for optimized scroll state management
|
|
5
|
+
* Reduces re-renders and improves performance for scroll tracking
|
|
6
|
+
*/
|
|
7
|
+
export const useOptimizedScrollState = (scrollRef: RefObject<HTMLDivElement | null>, ready: boolean) => {
|
|
8
|
+
const [isScrollable, setIsScrollable] = useState(false);
|
|
9
|
+
const [isScrolledToBottom, setIsScrolledToBottom] = useState(false);
|
|
10
|
+
|
|
11
|
+
// Function to check if content is scrollable and if we're at the bottom
|
|
12
|
+
// Memoized with throttling for better performance
|
|
13
|
+
const checkScrollState = useCallback(() => {
|
|
14
|
+
const elem = scrollRef.current;
|
|
15
|
+
if (!elem) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const { clientHeight, scrollHeight, scrollTop } = elem;
|
|
20
|
+
const scrollable = scrollHeight > clientHeight;
|
|
21
|
+
const atBottom = Math.abs(scrollHeight - clientHeight - scrollTop) < 1;
|
|
22
|
+
|
|
23
|
+
// Only update state if values actually changed to prevent unnecessary re-renders
|
|
24
|
+
setIsScrollable((prev) => (prev !== scrollable ? scrollable : prev));
|
|
25
|
+
setIsScrolledToBottom((prev) => (prev !== atBottom ? atBottom : prev));
|
|
26
|
+
}, [scrollRef]);
|
|
27
|
+
|
|
28
|
+
const checkScrollStateRef = useRef(checkScrollState);
|
|
29
|
+
checkScrollStateRef.current = checkScrollState;
|
|
30
|
+
|
|
31
|
+
// Set up scroll listener and initial check with optimized throttling
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
const elem = scrollRef.current;
|
|
34
|
+
if (!elem || !ready) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
checkScrollState();
|
|
39
|
+
|
|
40
|
+
// Use requestAnimationFrame for scroll throttling instead of setTimeout
|
|
41
|
+
let scrollRaf: number | null = null;
|
|
42
|
+
let resizeRaf: number | null = null;
|
|
43
|
+
|
|
44
|
+
const throttledScrollCheck = () => {
|
|
45
|
+
if (scrollRaf !== null) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
scrollRaf = requestAnimationFrame(() => {
|
|
49
|
+
checkScrollStateRef.current();
|
|
50
|
+
scrollRaf = null;
|
|
51
|
+
});
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const throttledResizeCheck = () => {
|
|
55
|
+
if (resizeRaf !== null) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
resizeRaf = requestAnimationFrame(() => {
|
|
59
|
+
checkScrollStateRef.current();
|
|
60
|
+
resizeRaf = null;
|
|
61
|
+
});
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
// Use passive listeners for better scroll performance
|
|
65
|
+
elem.addEventListener('scroll', throttledScrollCheck, { passive: true });
|
|
66
|
+
|
|
67
|
+
const resizeObserver = new ResizeObserver(throttledResizeCheck);
|
|
68
|
+
resizeObserver.observe(elem);
|
|
69
|
+
|
|
70
|
+
return () => {
|
|
71
|
+
elem.removeEventListener('scroll', throttledScrollCheck);
|
|
72
|
+
if (scrollRaf !== null) {
|
|
73
|
+
cancelAnimationFrame(scrollRaf);
|
|
74
|
+
}
|
|
75
|
+
if (resizeRaf !== null) {
|
|
76
|
+
cancelAnimationFrame(resizeRaf);
|
|
77
|
+
}
|
|
78
|
+
resizeObserver.disconnect();
|
|
79
|
+
};
|
|
80
|
+
}, [ready, scrollRef, checkScrollState]);
|
|
81
|
+
|
|
82
|
+
return {
|
|
83
|
+
checkScrollState,
|
|
84
|
+
isScrollable,
|
|
85
|
+
isScrolledToBottom,
|
|
86
|
+
};
|
|
87
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/* eslint-disable no-console */
|
|
2
|
+
// Keeps track of wether everything is good to go or not, in the most efficient way possible
|
|
3
|
+
|
|
4
|
+
import { useCallback, useEffect, useState } from 'react';
|
|
5
|
+
|
|
6
|
+
export const useReady = () => {
|
|
7
|
+
const [ready, setReady] = useState(false);
|
|
8
|
+
const [readyMap, updateReadyMap] = useState<{ [key: string]: boolean }>({});
|
|
9
|
+
|
|
10
|
+
const registerReady = useCallback((key: string) => {
|
|
11
|
+
// Register the check we're gonna wait for until it's ready
|
|
12
|
+
updateReadyMap((ready) => ({ ...ready, [key]: false }));
|
|
13
|
+
|
|
14
|
+
return () => {
|
|
15
|
+
// Set it to ready
|
|
16
|
+
updateReadyMap((ready) => ({ ...ready, [key]: true }));
|
|
17
|
+
};
|
|
18
|
+
}, []);
|
|
19
|
+
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
const states = Object.values(readyMap);
|
|
22
|
+
|
|
23
|
+
if (states.length === 0) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const isReady = states.every(Boolean);
|
|
28
|
+
if (isReady) {
|
|
29
|
+
setReady(true);
|
|
30
|
+
}
|
|
31
|
+
}, [readyMap]);
|
|
32
|
+
|
|
33
|
+
return { ready, registerReady };
|
|
34
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { useDebugValue, useEffect, useMemo, useRef } from 'react';
|
|
2
|
+
|
|
3
|
+
export const useReducedMotion = () => {
|
|
4
|
+
const mql = useMemo(
|
|
5
|
+
() => (typeof window !== 'undefined' ? window.matchMedia('(prefers-reduced-motion: reduce)') : null),
|
|
6
|
+
[]
|
|
7
|
+
);
|
|
8
|
+
const ref = useRef(mql?.matches);
|
|
9
|
+
|
|
10
|
+
useDebugValue(ref.current ? 'reduce' : 'no-preference');
|
|
11
|
+
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
const handler = (event: MediaQueryListEvent) => {
|
|
14
|
+
ref.current = event.matches;
|
|
15
|
+
};
|
|
16
|
+
mql?.addEventListener('change', handler);
|
|
17
|
+
|
|
18
|
+
return () => mql?.removeEventListener('change', handler);
|
|
19
|
+
}, [mql]);
|
|
20
|
+
|
|
21
|
+
return ref;
|
|
22
|
+
};
|