@evolve.ui/core-components 1.0.1 → 1.2.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/{BottomSheet-ZV_eq3xt.mjs → BottomSheet-CNVLnEoD.mjs} +3 -3
- package/BottomSheet-CNVLnEoD.mjs.map +1 -0
- package/{BottomSheet-emWP9Fct.cjs → BottomSheet-D5w0WZDl.cjs} +3 -3
- package/BottomSheet-D5w0WZDl.cjs.map +1 -0
- package/Button.cjs +1 -1
- package/Button.mjs +1 -1
- package/{CookieConsent-CIwm0bTz.mjs → CookieConsent-B9dg9WdC.mjs} +2 -2
- package/{CookieConsent-CIwm0bTz.mjs.map → CookieConsent-B9dg9WdC.mjs.map} +1 -1
- package/{CookieConsent-PIglB_bb.cjs → CookieConsent-BSXJHMwX.cjs} +2 -2
- package/{CookieConsent-PIglB_bb.cjs.map → CookieConsent-BSXJHMwX.cjs.map} +1 -1
- package/{Drawer-9HFG45OA.cjs → Drawer-3rA9dGCl.cjs} +2 -2
- package/{Drawer-9HFG45OA.cjs.map → Drawer-3rA9dGCl.cjs.map} +1 -1
- package/Drawer-CFZbwg0R.d.cts.map +1 -1
- package/Drawer-CFZbwg0R.d.mts.map +1 -1
- package/{Drawer-BkCPfK6P.mjs → Drawer-DzKEmewj.mjs} +2 -2
- package/{Drawer-BkCPfK6P.mjs.map → Drawer-DzKEmewj.mjs.map} +1 -1
- package/{FavoriteButton-CC3qL0lR.mjs → FavoriteButton-7nK77lQP.mjs} +6 -6
- package/FavoriteButton-7nK77lQP.mjs.map +1 -0
- package/{FavoriteButton-BGF-3dze.d.cts → FavoriteButton-B8r_qtlj.d.cts} +2 -2
- package/{FavoriteButton-BGF-3dze.d.cts.map → FavoriteButton-B8r_qtlj.d.cts.map} +1 -1
- package/{FavoriteButton-DliYzkfu.cjs → FavoriteButton-BkIaWfgD.cjs} +6 -6
- package/FavoriteButton-BkIaWfgD.cjs.map +1 -0
- package/{FavoriteButton-BZEGWrRo.d.mts → FavoriteButton-hIkGjcKH.d.mts} +2 -2
- package/{FavoriteButton-BZEGWrRo.d.mts.map → FavoriteButton-hIkGjcKH.d.mts.map} +1 -1
- package/{FileUpload-p_pl9NXr.mjs → FileUpload-BfZOMsLs.mjs} +6 -6
- package/FileUpload-BfZOMsLs.mjs.map +1 -0
- package/{FileUpload--e_UJ_ek.cjs → FileUpload-gjRbkgrL.cjs} +6 -6
- package/FileUpload-gjRbkgrL.cjs.map +1 -0
- package/IconButton.cjs +1 -1
- package/IconButton.mjs +1 -1
- package/{ImageSlider-BidXfnLj.cjs → ImageSlider-CAgxQffP.cjs} +3 -3
- package/ImageSlider-CAgxQffP.cjs.map +1 -0
- package/{ImageSlider-CDrg_TbL.mjs → ImageSlider-fdrJ6lIJ.mjs} +3 -3
- package/ImageSlider-fdrJ6lIJ.mjs.map +1 -0
- package/InfoIconTooltip.cjs +1 -1
- package/InfoIconTooltip.cjs.map +1 -1
- package/InfoIconTooltip.mjs +1 -1
- package/InfoIconTooltip.mjs.map +1 -1
- package/InlineButton-CRLbNJZ3.d.mts.map +1 -1
- package/InlineButton-DoXGLiSE.d.cts.map +1 -1
- package/Input.cjs +1 -1
- package/Input.cjs.map +1 -1
- package/Input.mjs +1 -1
- package/Input.mjs.map +1 -1
- package/JumpMenu-BXYZnPIH.cjs.map +1 -1
- package/JumpMenu-DcZjAiej.mjs.map +1 -1
- package/{Menu-Cxu8CaX1.mjs → Menu-Bn4smlEe.mjs} +2 -2
- package/Menu-Bn4smlEe.mjs.map +1 -0
- package/{Menu-ClUogmwE.cjs → Menu-DuDhtoNP.cjs} +2 -2
- package/Menu-DuDhtoNP.cjs.map +1 -0
- package/Modal-DM0aXJZ5.d.cts.map +1 -1
- package/Modal-DM0aXJZ5.d.mts.map +1 -1
- package/{Modal-C6gatdtT.mjs → Modal-DtxWd7Le.mjs} +3 -2
- package/{Modal-C6gatdtT.mjs.map → Modal-DtxWd7Le.mjs.map} +1 -1
- package/{Modal-CiBqXyiK.cjs → Modal-q4HhBAQU.cjs} +3 -2
- package/Modal-q4HhBAQU.cjs.map +1 -0
- package/{Pagination-bAtbN478.cjs → Pagination-Denb9_zB.cjs} +2 -2
- package/{Pagination-bAtbN478.cjs.map → Pagination-Denb9_zB.cjs.map} +1 -1
- package/{Pagination-DIpGKMLz.mjs → Pagination-Dyfeys4B.mjs} +2 -2
- package/{Pagination-DIpGKMLz.mjs.map → Pagination-Dyfeys4B.mjs.map} +1 -1
- package/PhoneInput-B5pkpkdt.mjs.map +1 -1
- package/PhoneInput-BXnkBME4.d.mts.map +1 -1
- package/PhoneInput-Bkrbrins.d.cts.map +1 -1
- package/PhoneInput-CUMPOSxJ.cjs.map +1 -1
- package/{ProgressCircle-BC81D9sU.cjs → ProgressCircle-B6R4dxoV.cjs} +2 -2
- package/{ProgressCircle-BC81D9sU.cjs.map → ProgressCircle-B6R4dxoV.cjs.map} +1 -1
- package/{ProgressCircle-ae8cvZhe.mjs → ProgressCircle-zSai1HTT.mjs} +2 -2
- package/{ProgressCircle-ae8cvZhe.mjs.map → ProgressCircle-zSai1HTT.mjs.map} +1 -1
- package/SearchInput-DYIPC8Cd.d.cts.map +1 -1
- package/SearchInput-IfEWePDQ.d.mts.map +1 -1
- package/{Select-BkZu8OLs.mjs → Select-CH_ZN88G.mjs} +2 -2
- package/Select-CH_ZN88G.mjs.map +1 -0
- package/{Select-BXDjzyDs.cjs → Select-DCCcyLT4.cjs} +2 -2
- package/Select-DCCcyLT4.cjs.map +1 -0
- package/{SplitButton-DcmmLW8j.cjs → SplitButton-B_Y253RU.cjs} +2 -2
- package/{SplitButton-DcmmLW8j.cjs.map → SplitButton-B_Y253RU.cjs.map} +1 -1
- package/{SplitButton-WE5ymwCQ.mjs → SplitButton-_poP9Ykq.mjs} +2 -2
- package/{SplitButton-WE5ymwCQ.mjs.map → SplitButton-_poP9Ykq.mjs.map} +1 -1
- package/{Table-M-rANdMt.mjs → Table-CQGtDpvH.mjs} +3 -3
- package/{Table-M-rANdMt.mjs.map → Table-CQGtDpvH.mjs.map} +1 -1
- package/{Table-CLlDragJ.cjs → Table-D4UYosb1.cjs} +3 -3
- package/{Table-CLlDragJ.cjs.map → Table-D4UYosb1.cjs.map} +1 -1
- package/Typography/InlineButton.cjs +1 -1
- package/Typography/InlineButton.cjs.map +1 -1
- package/Typography/InlineButton.mjs +1 -1
- package/Typography/InlineButton.mjs.map +1 -1
- package/{ViewMore-BBoUvo7p.cjs → ViewMore-BcoSRZSl.cjs} +14 -1
- package/ViewMore-BcoSRZSl.cjs.map +1 -0
- package/{ViewMore-BrZPuE4E.mjs → ViewMore-Be0TQZ_2.mjs} +14 -1
- package/ViewMore-Be0TQZ_2.mjs.map +1 -0
- package/bottomSheet.cjs +1 -1
- package/bottomSheet.mjs +1 -1
- package/{buttonColorClasses-C3hg1at8.cjs → buttonColorClasses-CQQmLYfk.cjs} +4 -4
- package/buttonColorClasses-CQQmLYfk.cjs.map +1 -0
- package/{buttonColorClasses-B7OU4aQA.mjs → buttonColorClasses-CQnqAJXl.mjs} +4 -4
- package/buttonColorClasses-CQnqAJXl.mjs.map +1 -0
- package/card/components/createFavoriteButton.cjs +1 -1
- package/card/components/createFavoriteButton.mjs +1 -1
- package/cookieConsent.cjs +1 -1
- package/cookieConsent.mjs +1 -1
- package/drawer.cjs +1 -1
- package/drawer.mjs +1 -1
- package/evolve-ui.entries.json +556 -0
- package/favoriteButton.cjs +1 -1
- package/favoriteButton.d.cts +1 -1
- package/favoriteButton.d.mts +1 -1
- package/favoriteButton.mjs +1 -1
- package/featureFlags/hooks.d.cts +1 -1
- package/featureFlags/hooks.d.mts +1 -1
- package/fileUpload.cjs +1 -1
- package/fileUpload.mjs +1 -1
- package/imageSlider.cjs +1 -1
- package/imageSlider.mjs +1 -1
- package/index.cjs +14 -14
- package/index.d.cts +1 -1
- package/index.d.mts +1 -1
- package/index.mjs +14 -14
- package/menu.cjs +1 -1
- package/menu.mjs +1 -1
- package/modal/useCloseModal.cjs +2 -1
- package/modal/useCloseModal.cjs.map +1 -1
- package/modal/useCloseModal.mjs +2 -1
- package/modal/useCloseModal.mjs.map +1 -1
- package/modal.cjs +1 -1
- package/modal.mjs +1 -1
- package/package.json +2 -4
- package/pagination.cjs +1 -1
- package/pagination.mjs +1 -1
- package/progressCircle.cjs +1 -1
- package/progressCircle.mjs +1 -1
- package/searchInput.cjs +4 -4
- package/searchInput.cjs.map +1 -1
- package/searchInput.mjs +4 -4
- package/searchInput.mjs.map +1 -1
- package/select.cjs +1 -1
- package/select.mjs +1 -1
- package/selectAsync.cjs +1 -1
- package/selectAsync.mjs +1 -1
- package/selectAsyncCreatable.cjs +1 -1
- package/selectAsyncCreatable.mjs +1 -1
- package/selectCreatable.cjs +1 -1
- package/selectCreatable.mjs +1 -1
- package/splitButton.cjs +1 -1
- package/splitButton.mjs +1 -1
- 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 +93 -0
- package/src/BottomSheet/components/BottomSheetOverlay/BottomSheetOverlayTranslate3d.tsx +199 -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 +58 -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 +443 -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 +83 -0
- package/src/FavoriteButton/components/LabeledAnimatedFavoriteButton/LabeledAnimatedFavoriteButton.tsx +186 -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 +584 -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 +65 -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 +321 -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 +140 -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 +515 -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 +237 -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 +305 -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 +159 -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 +167 -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 +65 -0
- package/src/utils/utilityTypes.ts +13 -0
- package/table.cjs +1 -1
- package/table.mjs +1 -1
- package/tabs.cjs +1 -1
- package/tabs.cjs.map +1 -1
- package/tabs.mjs +1 -1
- package/tabs.mjs.map +1 -1
- package/textArea.cjs.map +1 -1
- package/textArea.mjs.map +1 -1
- package/viewMore.cjs +1 -1
- package/viewMore.mjs +1 -1
- package/BottomSheet-ZV_eq3xt.mjs.map +0 -1
- package/BottomSheet-emWP9Fct.cjs.map +0 -1
- package/FavoriteButton-CC3qL0lR.mjs.map +0 -1
- package/FavoriteButton-DliYzkfu.cjs.map +0 -1
- package/FileUpload--e_UJ_ek.cjs.map +0 -1
- package/FileUpload-p_pl9NXr.mjs.map +0 -1
- package/ImageSlider-BidXfnLj.cjs.map +0 -1
- package/ImageSlider-CDrg_TbL.mjs.map +0 -1
- package/Menu-ClUogmwE.cjs.map +0 -1
- package/Menu-Cxu8CaX1.mjs.map +0 -1
- package/Modal-CiBqXyiK.cjs.map +0 -1
- package/Select-BXDjzyDs.cjs.map +0 -1
- package/Select-BkZu8OLs.mjs.map +0 -1
- package/ViewMore-BBoUvo7p.cjs.map +0 -1
- package/ViewMore-BrZPuE4E.mjs.map +0 -1
- package/buttonColorClasses-B7OU4aQA.mjs.map +0 -1
- package/buttonColorClasses-C3hg1at8.cjs.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ImageSlider-CDrg_TbL.mjs","names":["placeholderImage","useHighQuality"],"sources":["../src/ImageSlider/components/IndexIndicator/IndexIndicator.tsx","../src/ImageSlider/components/NavigationButtons/NavigationButtons.tsx","../src/ImageSlider/assets/placeholder.svg","../src/ImageSlider/constants.ts","../src/ImageSlider/utils/imageOptimization.ts","../src/ImageSlider/components/ResponsiveImage/ResponsiveImage.tsx","../src/ImageSlider/components/Thumbnails/Thumbnails.tsx","../src/ImageSlider/hooks/useImageSlider.ts","../src/ImageSlider/ImageSlider.types.ts","../src/ImageSlider/hooks/useImageSliderNavigation.ts","../src/ImageSlider/hooks/useImageSliderScrollHandler.ts","../src/ImageSlider/ImageSlider.tsx"],"sourcesContent":["type Props = {\n /** Currently active page number (1-based) */\n currentPage: number;\n /** Total number of pages/images */\n numberOfPages: number;\n};\n\n/**\n * Displays a numeric index indicator (e.g., \"1 of 11\") for image gallery position.\n * Used when thumbnailDisplay is 'index' instead of image thumbnails.\n */\nexport const IndexIndicator = ({ currentPage, numberOfPages }: Props) => (\n <div\n aria-label={`Image ${currentPage} of ${numberOfPages}`}\n aria-live=\"polite\"\n className=\"hui-text-caption flex justify-center text-text-secondary\"\n role=\"status\"\n >\n {currentPage} of {numberOfPages}\n </div>\n);\n","import { cn } from '@evolve.ui/theme-system';\n\nimport { IconButton } from '../../../IconButton/IconButton';\nimport { ArrowLeft, ArrowRight, CaretLeft, CaretRight } from '../../../Icons';\n\ntype Props = {\n goToNextPage: () => void;\n goToPreviousPage: () => void;\n /** Shape of the navigation icons */\n iconShape?: 'circle' | 'square';\n /** Size of the navigation icons - sm=34px, md=42px, lg=54px */\n iconSize?: 'sm' | 'md' | 'lg';\n /** Type of icons to use for navigation */\n iconType?: 'caret' | 'arrow';\n /** Variant of the navigation icons */\n iconVariant?: 'outlined' | 'transparent';\n /** Whether the next button should be disabled */\n isNextPageDisabled?: boolean;\n /** Whether the previous button should be disabled */\n isPreviousPageDisabled?: boolean;\n /** For grid layout - which position this button should render (left or right) */\n position?: 'left' | 'right';\n showNextPageButton: boolean;\n showPreviousPageButton: boolean;\n};\n\nexport const NavigationButtons = ({\n goToNextPage,\n goToPreviousPage,\n iconShape = 'circle',\n iconSize = 'sm',\n iconType = 'caret',\n iconVariant = 'outlined',\n isNextPageDisabled = false,\n isPreviousPageDisabled = false,\n position,\n showNextPageButton,\n showPreviousPageButton,\n}: Props) => {\n // Choose the correct icons based on iconType prop\n const LeftIcon = iconType === 'arrow' ? ArrowLeft : CaretLeft;\n const RightIcon = iconType === 'arrow' ? ArrowRight : CaretRight;\n\n // For grid layout with outside positioning, render individual buttons\n if (position) {\n if (position === 'left') {\n return showPreviousPageButton ? (\n <IconButton\n aria-label=\"Previous Page\"\n className=\"xsMax:hidden\"\n disabled={isPreviousPageDisabled}\n hideTooltip\n icon={LeftIcon}\n onClick={goToPreviousPage}\n shape={iconShape}\n size={iconSize}\n variant={iconVariant}\n />\n ) : null;\n }\n\n // position === 'right'\n return showNextPageButton ? (\n <IconButton\n aria-label=\"Next Page\"\n className=\"xsMax:hidden\"\n disabled={isNextPageDisabled}\n hideTooltip\n icon={RightIcon}\n onClick={goToNextPage}\n shape={iconShape}\n size={iconSize}\n variant={iconVariant}\n />\n ) : null;\n }\n\n // Original layout for inside positioning or non-grid layouts\n // For inside positioning: calculate from the top to put the button halfway down its parent relative to its own center.\n // this will break if the size of the IconButton is ever changed,\n const positionStyles = cn('absolute top-[calc(50%-21px)] w-full');\n\n return (\n <div className=\"z-10\">\n {showPreviousPageButton && (\n <IconButton\n aria-label=\"Previous Page\"\n className={cn(positionStyles, 'left-sm', 'xsMax:hidden')}\n disabled={isPreviousPageDisabled}\n hideTooltip\n icon={LeftIcon}\n onClick={goToPreviousPage}\n shape={iconShape}\n size={iconSize}\n variant={iconVariant}\n />\n )}\n {showNextPageButton && (\n <IconButton\n aria-label=\"Next Page\"\n className={cn(positionStyles, 'right-sm', 'xsMax:hidden')}\n disabled={isNextPageDisabled}\n hideTooltip\n icon={RightIcon}\n onClick={goToNextPage}\n shape={iconShape}\n size={iconSize}\n variant={iconVariant}\n />\n )}\n </div>\n );\n};\n","\"data:image/svg+xml,<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" viewBox=\\\"0 0 400 400\\\" role=\\\"img\\\" aria-label=\\\"Image unavailable\\\">%0A <rect width=\\\"400\\\" height=\\\"400\\\" fill=\\\"%23ececec\\\"/>%0A <rect x=\\\"10\\\" y=\\\"10\\\" width=\\\"380\\\" height=\\\"380\\\" fill=\\\"none\\\" stroke=\\\"%23c4c4c4\\\" stroke-width=\\\"4\\\"/>%0A <circle cx=\\\"148\\\" cy=\\\"148\\\" r=\\\"32\\\" fill=\\\"%23c4c4c4\\\"/>%0A <path d=\\\"M56 322 L162 204 L232 280 L282 228 L344 322 Z\\\" fill=\\\"%23c4c4c4\\\"/>%0A</svg>%0A\"","import { spacing } from '@evolve.ui/theme-system/themes/common';\n\nimport placeholderImage from './assets/placeholder.svg';\nimport { ImageSliderCard } from './ImageSlider.types';\n\n/**\n * Constants used throughout the ImageSlider component\n */\n\n// Breakpoints\nexport const MOBILE_BREAKPOINT = 768;\nexport const MOBILE_BREAKPOINT_QUERY = `(max-width: ${MOBILE_BREAKPOINT}px)`;\n\n// Spacing values (use design tokens)\nexport const SPACING = {\n GAP_2XS: spacing.xxsValue, // gap-2xs (4px)\n GAP_MD: spacing.mdValue, // gap-md (24px)\n MARGIN_SM: spacing.smValue, // ml-sm, mr-sm (16px)\n} as const;\n\n// Thumbnail dimensions\nexport const THUMBNAIL = {\n QUALITY: 50, // Thumbnail quality setting\n SIZE: 111, // Fixed thumbnail size\n WIDTH_PARAM: 107, // URL width parameter for thumbnails\n} as const;\n\n// Mobile card dimensions\nexport const MOBILE_CARD = {\n MAX_WIDTH: 651, // Max card width\n WIDTH_REDUCTION: 64, // calc(100% - 64px) to match container extension for optimal bleed effect\n} as const;\n\n// Animation timings\nexport const ANIMATION = {\n DEBOUNCE_DELAY: 100, // Scroll handler debounce delay\n SCROLL_TIMEOUT: 300, // Smooth scroll animation duration\n} as const;\n\n// Navigation button positioning\nexport const NAVIGATION = {\n INSIDE_TOP_OFFSET: 21, // top-[calc(50%-21px)]\n OUTSIDE_TOP_OFFSET: 17, // top-[calc(50%-17px)]\n} as const;\n\n// Bundled brand-neutral fallback (inlined as a data URI at build time) — the image-error\n// fallback must never depend on an external CDN.\nexport const PLACEHOLDER_IMAGE_URL = placeholderImage;\n\nexport const PLACEHOLDER_EMPTY_CARDS: ImageSliderCard[] = [\n {\n imageData: {\n alt: 'Placeholder empty card',\n baseUrl: PLACEHOLDER_IMAGE_URL,\n title: 'Placeholder empty card',\n },\n key: 'placeholder-empty-card-1',\n },\n];\n","import { THUMBNAIL } from '../constants';\nimport { ResponsiveImageConfig } from '../ImageSlider.types';\n\n/**\n * Generates a srcSet string for main images with responsive breakpoints\n * @param baseUrl - The base URL of the image\n * @param config - Responsive image configuration\n * @param useHighQuality - Whether to use high quality mode (no width constraints)\n * @returns The srcSet string for the image\n */\nexport const generateMainImageSrcSet = (\n baseUrl: string,\n config: ResponsiveImageConfig,\n useHighQuality: boolean = false\n): string => {\n // If high quality mode is enabled (after hover), return empty string\n // This forces the browser to use only the src attribute (full quality)\n // avoiding intermediate 651px requests\n if (useHighQuality) {\n return '';\n }\n\n const { desktopSize, mobileSize } = config;\n const widths = [mobileSize, desktopSize];\n\n return widths\n .map((width) => {\n return `${baseUrl}&width=${width} ${width}w`;\n })\n .join(', ');\n};\n\n/**\n * Generates a srcSet string for thumbnail images\n * @param baseUrl - The base URL of the image\n * @returns The srcSet string for the thumbnail\n */\nexport const generateThumbnailSrcSet = (baseUrl: string): string => {\n return `${baseUrl}&width=${THUMBNAIL.WIDTH_PARAM} ${THUMBNAIL.WIDTH_PARAM}w`;\n};\n\n/**\n * Generates the sizes attribute for responsive images\n * @param config - Responsive image configuration\n * @param useHighQuality - Whether to use high quality mode\n * @returns The sizes attribute string\n */\nexport const generateSizesAttribute = (config: ResponsiveImageConfig, useHighQuality: boolean = false): string => {\n // If high quality mode is enabled (after hover), sizes attribute is not needed\n // since we're using empty srcSet and relying only on src attribute\n if (useHighQuality) {\n return '';\n }\n\n const { breakpoint, desktopSize, mobileSize } = config;\n // Use a much smaller size on mobile to force selection of 366w image even on high-DPR devices\n const adjustedMobileSize = Math.floor(mobileSize / 3); // ~122px, ensuring 366w is selected even at DPR 3.0\n return `(max-width: ${breakpoint}px) ${adjustedMobileSize}px, ${desktopSize}px`;\n};\n\n// Memoized thumbnail sizes attribute (static value)\nconst THUMBNAIL_SIZES_ATTRIBUTE = `${THUMBNAIL.WIDTH_PARAM}px`;\n\n/**\n * Generates the sizes attribute for thumbnail images\n * @returns The sizes attribute string for thumbnails\n */\nexport const generateThumbnailSizesAttribute = (): string => {\n return THUMBNAIL_SIZES_ATTRIBUTE;\n};\n\n/**\n * Gets the appropriate image source URL based on quality mode\n * @param baseUrl - The base URL of the image\n * @param config - Responsive image configuration\n * @param useHighQuality - Whether to use high quality mode\n * @returns The appropriate source URL\n */\nexport const getImageSrc = (\n baseUrl: string,\n config: ResponsiveImageConfig,\n useHighQuality: boolean = false\n): string => {\n if (useHighQuality) {\n return baseUrl;\n }\n return `${baseUrl}&width=${config.mobileSize}`;\n};\n\n/**\n * Gets the thumbnail image source URL\n * @param baseUrl - The base URL of the image\n * @returns The thumbnail source URL\n */\nexport const getThumbnailSrc = (baseUrl: string): string => {\n return `${baseUrl}&width=${THUMBNAIL.WIDTH_PARAM}`;\n};\n","import { PLACEHOLDER_IMAGE_URL } from '../../constants';\nimport { ResponsiveImageConfig, ResponsiveImageData } from '../../ImageSlider.types';\nimport {\n generateMainImageSrcSet,\n generateSizesAttribute,\n generateThumbnailSizesAttribute,\n generateThumbnailSrcSet,\n getImageSrc,\n getThumbnailSrc,\n} from '../../utils/imageOptimization';\n\n/**\n * Props for the ResponsiveImage component\n */\ntype Props = {\n /** Additional CSS classes */\n className?: string;\n /** Whether the gallery has been hovered (for quality optimization) */\n hasHoveredGallery?: boolean;\n /** Image data containing alt, baseUrl, and title */\n imageData: ResponsiveImageData;\n /** Whether this image is currently active/visible */\n isActiveImage?: boolean;\n /** Whether this is a main image (not a thumbnail) */\n isMainImage?: boolean;\n /** Responsive image configuration */\n responsiveImageConfig?: ResponsiveImageConfig;\n};\n\n/**\n * Renders a responsive image with optimized loading priorities and srcSet\n */\nexport const ResponsiveImage = ({\n className,\n hasHoveredGallery = false,\n imageData,\n isActiveImage = false,\n isMainImage = true,\n responsiveImageConfig,\n}: Props) => {\n const { alt, baseUrl, title } = imageData;\n\n if (!responsiveImageConfig) {\n // Fallback to simple image if no config provided\n return (\n <img\n alt={alt}\n className={className}\n onError={(e) => {\n const target = e.target as HTMLImageElement;\n if (target.src !== PLACEHOLDER_IMAGE_URL) {\n target.src = PLACEHOLDER_IMAGE_URL;\n }\n }}\n src={baseUrl}\n title={title}\n />\n );\n }\n\n if (isMainImage) {\n // Use high quality mode for all images once gallery has been hovered\n const useHighQuality = hasHoveredGallery;\n\n // Only use high quality URLs/srcSet after gallery has been hovered\n // Active images get high priority/eager loading but still use responsive srcSet initially\n const shouldLoadHighQuality = useHighQuality;\n\n return (\n <img\n alt={alt}\n className=\"h-full w-full bg-background-primary object-contain\"\n fetchPriority={isActiveImage || shouldLoadHighQuality ? 'high' : 'low'}\n // Force React to create a new img element when switching to high quality\n // This prevents the browser from loading both constrained and unconstrained versions\n key={shouldLoadHighQuality && !isActiveImage ? 'high-quality' : 'standard-quality'}\n loading={isActiveImage || shouldLoadHighQuality ? 'eager' : 'lazy'}\n onError={(e) => {\n const target = e.target as HTMLImageElement;\n if (target.src !== PLACEHOLDER_IMAGE_URL) {\n target.src = PLACEHOLDER_IMAGE_URL;\n // Clear srcSet to prevent fallback to other sizes that might also fail\n target.srcset = '';\n }\n }}\n sizes={generateSizesAttribute(responsiveImageConfig, shouldLoadHighQuality)}\n src={getImageSrc(baseUrl, responsiveImageConfig, shouldLoadHighQuality)}\n srcSet={generateMainImageSrcSet(baseUrl, responsiveImageConfig, shouldLoadHighQuality)}\n title={title}\n />\n );\n }\n\n // Thumbnail image - responsive sizes\n return (\n <img\n alt={alt}\n className=\"h-full max-h-[111px] w-full max-w-[111px] object-cover\"\n loading=\"lazy\"\n onError={(e) => {\n const target = e.target as HTMLImageElement;\n if (target.src !== PLACEHOLDER_IMAGE_URL) {\n target.src = PLACEHOLDER_IMAGE_URL;\n // Clear srcSet to prevent fallback to other sizes that might also fail\n target.srcset = '';\n }\n }}\n sizes={generateThumbnailSizesAttribute()}\n src={getThumbnailSrc(baseUrl)}\n srcSet={generateThumbnailSrcSet(baseUrl)}\n title={title}\n />\n );\n};\n","import { cn } from '@evolve.ui/theme-system';\nimport { useCallback, useEffect, useMemo, useRef } from 'react';\n\nimport { PLACEHOLDER_IMAGE_URL, THUMBNAIL } from '../../constants';\nimport { ImageSliderCard, ResponsiveImageData } from '../../ImageSlider.types';\n\n/**\n * Props for the Thumbnails component\n */\ntype Props = {\n /** Array of image cards to display as thumbnails */\n cards: ImageSliderCard[];\n /** Currently active page number (1-based) */\n currentPage: number;\n /** Function to generate responsive thumbnail sizes attribute */\n generateThumbnailSizesAttribute: () => string;\n /** Function to generate responsive thumbnail srcSet */\n generateThumbnailSrcSet: (baseUrl: string) => string;\n /** Callback fired when a thumbnail is clicked */\n onThumbnailClick: (pageNumber: number) => void;\n /** Orientation of the thumbnail previews */\n orientation: 'vertical' | 'horizontal';\n};\n\n/**\n * Thumbnails component displays clickable thumbnail previews for image navigation.\n * Supports both vertical and horizontal orientations with consistent 111px sizing across all viewports.\n */\nexport const Thumbnails = ({\n cards,\n currentPage,\n generateThumbnailSizesAttribute,\n generateThumbnailSrcSet,\n onThumbnailClick,\n orientation,\n}: Props) => {\n const containerRef = useRef<HTMLDivElement>(null);\n const thumbnailRefs = useRef<(HTMLButtonElement | null)[]>([]);\n const previousPageRef = useRef<number>(currentPage);\n\n // Initialize refs array to match cards length - more efficient approach\n useEffect(() => {\n // Only resize if length changed, don't create new array unnecessarily\n if (thumbnailRefs.current.length !== cards.length) {\n thumbnailRefs.current.length = cards.length;\n }\n }, [cards.length]);\n\n // Helper function to modify baseUrl query parameters for quality and sharpening\n // Memoized to avoid repeated URL object creation\n const enhanceBaseUrl = useCallback((baseUrl: string) => {\n // Use string manipulation instead of URL constructor for better performance\n const hasParams = baseUrl.includes('?');\n const separator = hasParams ? '&' : '?';\n return `${baseUrl}${separator}quality=${THUMBNAIL.QUALITY}&sharpen=false`;\n }, []);\n\n // Helper function to render thumbnail images with low fetch priority\n const renderThumbnailImage = useCallback(\n (imageData: ResponsiveImageData, index: number, thumbnailSize: number) => {\n const { alt, baseUrl, title } = imageData;\n const enhancedBaseUrl = enhanceBaseUrl(baseUrl);\n return (\n <img\n alt={alt}\n className={`h-full max-h-[${thumbnailSize}px] w-full max-w-[${thumbnailSize}px] bg-background-primary object-contain`}\n fetchPriority={index <= 5 ? 'high' : 'low'}\n loading={index <= 5 ? 'eager' : 'lazy'}\n onError={(e) => {\n const target = e.target as HTMLImageElement;\n if (target.src !== PLACEHOLDER_IMAGE_URL) {\n target.src = PLACEHOLDER_IMAGE_URL;\n // Clear srcSet to prevent fallback to other sizes that might also fail\n target.srcset = '';\n }\n }}\n sizes={generateThumbnailSizesAttribute()}\n src={`${enhancedBaseUrl}&width=${thumbnailSize}`} // Fallback for browsers without srcSet support\n srcSet={generateThumbnailSrcSet(enhancedBaseUrl)}\n title={title}\n />\n );\n },\n [generateThumbnailSrcSet, generateThumbnailSizesAttribute, enhanceBaseUrl]\n );\n\n // Auto-scroll the active thumbnail into view when currentPage changes\n // Only scroll if the page actually changed (not on mount or remount from mobile → desktop)\n useEffect(() => {\n const pageChanged = previousPageRef.current !== currentPage;\n\n // Update the ref for next comparison\n previousPageRef.current = currentPage;\n\n // Only scroll if the page actually changed\n if (!pageChanged) {\n return;\n }\n\n const activeIndex = currentPage - 1;\n const activeThumbnail = thumbnailRefs.current[activeIndex];\n\n if (activeThumbnail && containerRef.current) {\n activeThumbnail.scrollIntoView({\n behavior: 'smooth',\n block: 'nearest',\n inline: 'center',\n });\n }\n }, [currentPage, orientation]);\n\n /**\n * Creates thumbnail preview images that can be clicked to navigate to specific images.\n * Supports both horizontal and vertical orientations with configurable size and dimming.\n * Supports both custom ReactNode cards and responsive imageData.\n */\n const thumbnailPreviews = useMemo(() => {\n const isHorizontal = orientation === 'horizontal';\n const thumbnailSize = isHorizontal ? 48 : THUMBNAIL.SIZE;\n\n return cards.map(({ card, imageData, key }, index) => {\n const pageNumber = index + 1;\n const isActive = currentPage === pageNumber;\n\n return (\n <button\n aria-current={isActive ? 'true' : 'false'}\n aria-label={`Go to image ${pageNumber}${imageData?.alt ? `: ${imageData.alt}` : ''}`}\n aria-selected={isActive}\n className={cn(\n 'box-border flex-shrink-0 cursor-pointer overflow-hidden rounded-md transition-all duration-100',\n 'hui-focus-visible-outline hover:opacity-80 focus:-outline-offset-4',\n `aspect-square h-[${thumbnailSize}px] w-[${thumbnailSize}px] max-h-[${thumbnailSize}px] max-w-[${thumbnailSize}px]`,\n // Use outline instead of border to avoid affecting box dimensions\n isActive\n ? 'opacity-100 outline outline-2 -outline-offset-2 outline-border-selected'\n : 'opacity-50 outline outline-1 -outline-offset-1 outline-border-secondary'\n )}\n data-active={isActive}\n data-page={pageNumber}\n key={key}\n onClick={() => onThumbnailClick(pageNumber)}\n ref={(el) => {\n thumbnailRefs.current[index] = el;\n }}\n role=\"tab\"\n style={{\n height: `${thumbnailSize}px`,\n maxHeight: `${thumbnailSize}px`,\n maxWidth: `${thumbnailSize}px`,\n width: `${thumbnailSize}px`,\n }}\n type=\"button\"\n >\n <div className=\"h-full w-full bg-background-primary\">\n {/* Render responsive image if imageData is provided, otherwise use custom card */}\n {imageData ? renderThumbnailImage(imageData, index, thumbnailSize) : card}\n </div>\n </button>\n );\n });\n }, [cards, currentPage, onThumbnailClick, renderThumbnailImage, orientation]);\n\n const isHorizontal = orientation === 'horizontal';\n\n return (\n <div\n aria-label=\"Image thumbnails\"\n className={cn(\n 'flex xsMax:hidden',\n isHorizontal\n ? 'w-full flex-row justify-center overflow-x-auto overflow-y-hidden pb-2xs'\n : 'h-full w-[136px] flex-col overflow-y-auto overflow-x-hidden pr-2xs mdMax:w-[128px]'\n )}\n ref={containerRef}\n role=\"tablist\"\n style={{\n scrollbarWidth: 'thin',\n }}\n >\n <div className={cn('flex gap-xs', isHorizontal ? 'flex-row' : 'flex-col')}>{thumbnailPreviews}</div>\n </div>\n );\n};\n","import { useRef, useState } from 'react';\n\nimport { useWindowIsMobile } from '../../providers';\nimport { ResponsiveImageConfig } from '../ImageSlider.types';\n\n/**\n * Props for the useImageSlider hook\n */\ntype UseImageSliderProps = {\n /** Number of cards/images in the slider */\n numberOfPages: number;\n /** Responsive image configuration */\n responsiveImageConfig: ResponsiveImageConfig;\n};\n\n/**\n * Main hook for ImageSlider component that provides basic state and refs\n * Navigation and scroll handling are managed separately to avoid circular dependencies\n * @param props - ImageSlider configuration\n * @returns Basic state and handlers needed for the ImageSlider component\n */\nexport const useImageSlider = ({ numberOfPages, responsiveImageConfig }: UseImageSliderProps) => {\n const containerRef = useRef<HTMLDivElement | null>(null);\n const contentRef = useRef<HTMLDivElement | null>(null);\n\n const [hasHoveredGallery, setHasHoveredGallery] = useState(false);\n const isMobile = useWindowIsMobile();\n\n const handleMouseOver = () => {\n if (!isMobile && !hasHoveredGallery) {\n setHasHoveredGallery(true);\n }\n };\n\n const handleMobileInteraction = () => {\n if (isMobile && !hasHoveredGallery) {\n setHasHoveredGallery(true);\n }\n };\n\n return {\n // Refs\n containerRef,\n contentRef,\n\n // Event handlers\n handleMobileInteraction,\n handleMouseOver,\n\n // State\n hasHoveredGallery,\n isMobile,\n numberOfPages,\n responsiveImageConfig,\n setHasHoveredGallery,\n };\n};\n","import { ReactNode } from 'react';\n\n/**\n * Display mode for thumbnail navigation\n */\nexport enum ThumbnailDisplay {\n Index = 'index',\n Thumbnails = 'thumbnails',\n}\n\n/**\n * Analytics event data for ImageSlider interactions\n */\nexport type ImageSliderAnalyticsEvent = {\n /** Current image position (1-based index) */\n imagePosition: number;\n /** Type of interaction that triggered the event */\n interactionType: 'Thumbnail Click' | 'Next' | 'Prev' | 'Open Lightbox';\n /** Total number of images in the slider */\n totalImages: number;\n};\n\n/**\n * Responsive image data for optimized loading\n */\nexport type ResponsiveImageData = {\n /**\n * Alt text for the image\n */\n alt: string;\n /**\n * Base URL for the image (without width parameters)\n */\n baseUrl: string;\n /**\n * Optional title for the image\n */\n title?: string;\n};\n\n/**\n * Configuration for responsive image sizes and breakpoints\n */\nexport type ResponsiveImageConfig = {\n /**\n * Breakpoint width in pixels where mobile switches to desktop\n * @default 768\n */\n breakpoint: number;\n /**\n * Desktop image width in pixels\n * @default 651\n */\n desktopSize: number;\n /**\n * Mobile image width in pixels\n * @default 366\n */\n mobileSize: number;\n};\n\n/**\n * Card for the ImageSlider - supports both custom ReactNode and responsive images\n */\nexport type ImageSliderCard = {\n /**\n * The rendered content of the card or image.\n * Optional when using imageData.\n */\n card?: ReactNode;\n /**\n * Responsive image data for automatic srcset/sizes optimization.\n * When provided, `card` will be ignored and an optimized <img> will be rendered.\n * Optional when using custom card content.\n */\n imageData?: ResponsiveImageData;\n /**\n * The unique identifier for the card\n */\n key: string;\n};\n\nexport type ImageSliderPageInfo = {\n breakpoints: number[];\n cardsPerPage: number;\n numberOfPages: number;\n};\n\n// this is the px size of the MD gap (kept for potential future use)\nexport const CAROUSEL_CARD_GAP_NUM = 24;\n","import { RefObject, useCallback, useEffect, useState } from 'react';\n\nimport { ImageSliderCard, ThumbnailDisplay } from '../ImageSlider.types';\n\n/**\n * Props for the useImageSliderNavigation hook\n */\ntype UseImageSliderNavigationProps = {\n /** The cards in the slider */\n cards: ImageSliderCard[];\n /** Optional key to identify when content has changed (e.g., an item id) */\n contentKey?: string | number;\n /** Ref to the content container */\n contentRef: RefObject<HTMLDivElement | null>;\n /** Whether the slider is currently scrolling */\n isScrolling: boolean;\n /** Total number of pages/slides */\n numberOfPages: number;\n /** Function to reset the gallery hover state when content changes (new URL/different images) */\n setHasHoveredGallery: (hasHovered: boolean) => void;\n /** Display mode for navigation controls; 'index' uses same button visibility as horizontal */\n thumbnailDisplay?: ThumbnailDisplay;\n /** Orientation of the thumbnail previews */\n thumbnailOrientation?: 'vertical' | 'horizontal';\n};\n\n/**\n * Hook for managing navigation state and handlers in the ImageSlider.\n * Implements wraparound navigation where clicking previous on the first image\n * jumps to the last image, and clicking next on the last image jumps to the first.\n * @param props - Navigation configuration\n * @returns Navigation state and handlers\n */\nexport const useImageSliderNavigation = ({\n contentKey,\n contentRef,\n isScrolling,\n numberOfPages,\n setHasHoveredGallery,\n thumbnailDisplay = ThumbnailDisplay.Thumbnails,\n thumbnailOrientation = 'vertical',\n}: UseImageSliderNavigationProps) => {\n const [currentPage, setCurrentPage] = useState(1);\n\n // For horizontal thumbnails or index display, always show buttons even with single image\n // For vertical thumbnails, hide buttons when there's only one image\n const showNavButtonsWithSingleImage =\n thumbnailOrientation === 'horizontal' || thumbnailDisplay === ThumbnailDisplay.Index;\n const showPreviousPageButton = showNavButtonsWithSingleImage ? true : numberOfPages > 1;\n const showNextPageButton = showNavButtonsWithSingleImage ? true : numberOfPages > 1;\n\n // For horizontal/index with single image, disable buttons\n // For vertical or multiple images, use wraparound navigation (never disabled)\n const isPreviousPageDisabled = showNavButtonsWithSingleImage && numberOfPages <= 1;\n const isNextPageDisabled = showNavButtonsWithSingleImage && numberOfPages <= 1;\n\n const goToPreviousPage = useCallback(() => {\n if (!isScrolling) {\n // Trigger hover state to load all images when navigation is used\n setHasHoveredGallery(true);\n if (currentPage > 1) {\n setCurrentPage(currentPage - 1);\n } else {\n // Wrap to last page when on first page\n setCurrentPage(numberOfPages);\n }\n }\n }, [currentPage, numberOfPages, isScrolling, setCurrentPage, setHasHoveredGallery]);\n\n const goToNextPage = useCallback(() => {\n if (!isScrolling) {\n // Trigger hover state to load all images when navigation is used\n setHasHoveredGallery(true);\n if (currentPage < numberOfPages) {\n setCurrentPage(currentPage + 1);\n } else {\n // Wrap to first page when on last page\n setCurrentPage(1);\n }\n }\n }, [currentPage, numberOfPages, isScrolling, setCurrentPage, setHasHoveredGallery]);\n\n const handleThumbnailClick = useCallback(\n (pageNumber: number) => {\n if (!isScrolling) {\n // Trigger hover state to load all images when thumbnail navigation is used\n setHasHoveredGallery(true);\n setCurrentPage(pageNumber);\n }\n },\n [isScrolling, setCurrentPage, setHasHoveredGallery]\n );\n\n /**\n * Handles keyboard navigation for the slider.\n * Allows using Left and Right arrow keys to navigate between images.\n */\n const onKeyNavigation = useCallback(\n (event: React.KeyboardEvent) => {\n if (event.key === 'ArrowRight') {\n goToNextPage();\n } else if (event.key === 'ArrowLeft') {\n goToPreviousPage();\n }\n },\n [goToNextPage, goToPreviousPage]\n );\n\n useEffect(() => {\n setCurrentPage(1);\n // Reset hover state when content changes (new content key/different images)\n setHasHoveredGallery(false);\n if (contentRef.current && typeof contentRef.current.scrollTo === 'function') {\n contentRef.current.scrollTo({\n behavior: 'instant',\n left: 0,\n });\n }\n }, [contentKey, contentRef, setHasHoveredGallery]);\n\n return {\n currentPage,\n goToNextPage,\n goToPreviousPage,\n handleThumbnailClick,\n isNextPageDisabled,\n isPreviousPageDisabled,\n onKeyNavigation,\n setCurrentPage,\n showNextPageButton,\n showPreviousPageButton,\n };\n};\n","import { debounce } from 'es-toolkit';\nimport { RefObject, useCallback, useEffect, useMemo, useRef, useState } from 'react';\n\nimport { useWindowIsMobile } from '../../providers';\nimport { ANIMATION, MOBILE_CARD, SPACING } from '../constants';\n\n/**\n * Props for the useImageSliderScrollHandler hook\n */\ntype UseImageSliderScrollHandlerProps = {\n /** Ref to the content container */\n contentRef: RefObject<HTMLDivElement | null>;\n /** Current page number */\n currentPage: number;\n /**\n * Max width in px of each carousel card on mobile (matches `responsiveImageConfig.desktopSize` on the slider).\n * @default MOBILE_CARD.MAX_WIDTH\n */\n maxMobileCardWidth?: number;\n /** Total number of pages */\n numberOfPages: number;\n /** Function to update the current page */\n setCurrentPage: (page: number) => void;\n /** Function to update the scrolling state */\n setIsScrolling?: (isScrolling: boolean) => void;\n};\n\n/**\n * Hook for managing scroll behavior and page tracking in the ImageSlider\n * @param props - Scroll handler configuration\n * @returns Scroll handlers and scrolling state\n */\nexport const useImageSliderScrollHandler = ({\n contentRef,\n currentPage,\n maxMobileCardWidth = MOBILE_CARD.MAX_WIDTH,\n numberOfPages,\n setCurrentPage,\n setIsScrolling,\n}: UseImageSliderScrollHandlerProps) => {\n const [internalIsScrolling, setInternalIsScrolling] = useState(false);\n const isScrollingState = setIsScrolling ? internalIsScrolling : false;\n const isMobile = useWindowIsMobile();\n const previousPageRef = useRef<number>(currentPage);\n\n // Handle programmatic scrolling on page changes (desktop only)\n useEffect(() => {\n if (contentRef.current) {\n // Skip programmatic scrolling on mobile - let natural snap scrolling handle it\n if (isMobile) {\n return;\n }\n\n const pageChanged = previousPageRef.current !== currentPage;\n\n // Set scrolling state to prevent rapid navigation\n if (setIsScrolling) {\n setIsScrolling(true);\n } else {\n setInternalIsScrolling(true);\n }\n\n // Calculate scroll position including gap for desktop\n const containerWidth = contentRef.current.offsetWidth;\n const gap = SPACING.GAP_MD; // md gap in pixels for desktop\n const scrollPosition = (currentPage - 1) * (containerWidth + gap);\n\n // Use 'auto' (instant) instead of 'smooth' if page hasn't changed\n // This prevents page scrolling on resize/mount while keeping smooth scrolling for navigation\n contentRef.current.scrollTo({\n behavior: pageChanged ? 'smooth' : 'auto',\n left: scrollPosition,\n });\n\n // Reset scrolling state after animation completes\n // Smooth scroll animation typically takes ~300-400ms\n const scrollTimeout = setTimeout(() => {\n if (setIsScrolling) {\n setIsScrolling(false);\n } else {\n setInternalIsScrolling(false);\n }\n }, ANIMATION.SCROLL_TIMEOUT);\n\n // Update previous page reference\n previousPageRef.current = currentPage;\n\n return () => {\n clearTimeout(scrollTimeout);\n };\n }\n return undefined;\n }, [currentPage, contentRef, setIsScrolling, isMobile]);\n\n /**\n * Memoized debounced scroll handler for desktop scroll tracking.\n * Updates the current page when user scrolls to reflect active thumbnail.\n */\n const debouncedDesktopScrollHandler = useMemo(\n () =>\n debounce(() => {\n if (contentRef.current && !isMobile) {\n const scrollLeft = contentRef.current.scrollLeft;\n const containerWidth = contentRef.current.offsetWidth;\n const gap = SPACING.GAP_MD; // md gap in pixels for desktop\n const newPage = Math.round(scrollLeft / (containerWidth + gap)) + 1;\n\n if (newPage !== currentPage && newPage >= 1 && newPage <= numberOfPages) {\n setCurrentPage(newPage);\n }\n }\n }, ANIMATION.DEBOUNCE_DELAY),\n [currentPage, numberOfPages, contentRef, setCurrentPage, isMobile]\n );\n\n /**\n * Memoized debounced scroll handler for mobile scroll tracking.\n * Updates the current page based on mobile card layout with gaps and margins.\n */\n const debouncedMobileScrollHandler = useMemo(\n () =>\n debounce(() => {\n if (contentRef.current && isMobile) {\n const { clientWidth, scrollLeft, scrollWidth } = contentRef.current;\n const maxScroll = scrollWidth - clientWidth;\n\n // Prevent scrolling beyond bounds\n if (scrollLeft < 0) {\n contentRef.current.scrollLeft = 0;\n } else if (scrollLeft > maxScroll) {\n contentRef.current.scrollLeft = maxScroll;\n }\n\n // Calculate current page based on scroll position\n // Mobile cards: min(calc(100% - 64px), maxMobileCardWidth) with 4px gaps\n // First card has 16px left margin, last card has 16px right margin\n const gap = SPACING.GAP_2XS;\n const margin = SPACING.MARGIN_SM;\n const cardWidth = Math.min(clientWidth - MOBILE_CARD.WIDTH_REDUCTION, maxMobileCardWidth);\n const cardWithGap = cardWidth + gap;\n\n // Calculate which card is most visible based on scroll position\n // Account for the initial margin offset\n const adjustedScrollLeft = scrollLeft + margin;\n const newPage = Math.round(adjustedScrollLeft / cardWithGap) + 1;\n\n if (newPage !== currentPage && newPage >= 1 && newPage <= numberOfPages) {\n setCurrentPage(newPage);\n }\n }\n }, ANIMATION.DEBOUNCE_DELAY),\n [currentPage, maxMobileCardWidth, numberOfPages, contentRef, setCurrentPage, isMobile]\n );\n\n /**\n * Handles scroll events within the slider content area.\n * Uses debounced handlers for both mobile and desktop to improve performance.\n */\n const onScrollCards = useCallback(() => {\n if (isMobile) {\n debouncedMobileScrollHandler();\n } else {\n debouncedDesktopScrollHandler();\n }\n }, [isMobile, debouncedMobileScrollHandler, debouncedDesktopScrollHandler]);\n\n return {\n isScrolling: isScrollingState,\n onScrollCards,\n };\n};\n","import { cn } from '@evolve.ui/theme-system';\nimport { useCallback, useMemo, useState, type CSSProperties } from 'react';\n\nimport { IndexIndicator } from './components/IndexIndicator/IndexIndicator';\nimport { NavigationButtons } from './components/NavigationButtons/NavigationButtons';\nimport { ResponsiveImage } from './components/ResponsiveImage';\nimport { Thumbnails } from './components/Thumbnails/Thumbnails';\nimport { PLACEHOLDER_EMPTY_CARDS } from './constants';\nimport { useImageSlider } from './hooks/useImageSlider';\nimport { useImageSliderNavigation } from './hooks/useImageSliderNavigation';\nimport { useImageSliderScrollHandler } from './hooks/useImageSliderScrollHandler';\nimport {\n ImageSliderAnalyticsEvent,\n ImageSliderCard,\n ResponsiveImageConfig,\n ThumbnailDisplay,\n} from './ImageSlider.types';\nimport { generateThumbnailSizesAttribute, generateThumbnailSrcSet } from './utils/imageOptimization';\n\ntype Props = {\n /**\n * The scrollable content of the image slider.\n * Should be individual images.\n *\n * @property {ReactNode} card - The rendered image content\n * @property {string} key - A unique identifier for the image\n */\n cards: ImageSliderCard[];\n /**\n * Class name for the image gallery container.\n */\n className?: string;\n /**\n * Optional key to identify when content has changed (e.g., an item id).\n * When this key changes, the slider will reset to the first image.\n * If not provided, will reset whenever the cards array reference changes.\n */\n contentKey?: string | number;\n /**\n * Shape of the navigation icons.\n * 'circle' creates round buttons, 'square' creates square buttons.\n *\n * @default 'circle'\n */\n iconShape?: 'circle' | 'square';\n /**\n * Size of the navigation icons - sm=34px, md=42px, lg=54px.\n * For horizontal thumbnails, 'lg' (54px) is recommended.\n *\n * @default 'sm'\n */\n iconSize?: 'sm' | 'md' | 'lg';\n /**\n * Type of icons to use for navigation.\n * 'caret' uses CaretLeft/CaretRight, 'arrow' uses ArrowLeft/ArrowRight.\n *\n * @default 'caret'\n */\n iconType?: 'caret' | 'arrow';\n /**\n * Variant of the navigation icons.\n * 'outlined' shows buttons with borders, 'transparent' shows borderless buttons.\n *\n * @default 'outlined'\n */\n iconVariant?: 'outlined' | 'transparent';\n /**\n * When thumbnailDisplay is 'index', position of the numeric indicator relative to the main image.\n *\n * @default 'bottom'\n */\n indexPosition?: 'top' | 'bottom';\n /**\n * Callback fired when an analytics event occurs in the image slider.\n * Receives interaction type, current image position (1-based), and total image count.\n * Does not fire for mobile swipe navigation, only for button/thumbnail clicks and lightbox opens.\n */\n onAnalyticsEventTriggered?: (event: ImageSliderAnalyticsEvent) => void;\n /**\n * Callback fired when an image is clicked (mouse) or activated via keyboard (Enter/Space).\n * Receives the index of the image and the mouse or keyboard event.\n */\n onImageClick?: (\n imageIndex: number,\n event: React.MouseEvent<HTMLElement> | React.KeyboardEvent<HTMLElement>\n ) => void;\n /**\n * Callback fired when an image is hovered (mouse) or focused (keyboard/screen reader).\n * Receives the index of the image and the mouse or focus event.\n */\n onImageMouseOver?: (\n imageIndex: number,\n event: React.MouseEvent<HTMLElement> | React.FocusEvent<HTMLElement>\n ) => void;\n /**\n * Configuration for responsive image loading when using imageData in cards.\n * Defines mobile/desktop sizes and breakpoint for optimal image loading.\n */\n responsiveImageConfig?: ResponsiveImageConfig;\n /**\n * Displays thumbnail previews on the left side of the slider.\n * Clicking a thumbnail will navigate to the corresponding image.\n * The current image thumbnail will have a border highlight.\n *\n * @default true\n */\n showThumbnails?: boolean;\n /**\n * Display mode for image navigation controls.\n * 'thumbnails' shows image previews (vertical or horizontal per thumbnailOrientation).\n * 'index' shows a numeric indicator (e.g., \"1 of 11\") above or below the main image per indexPosition.\n *\n * @default ThumbnailDisplay.Thumbnails\n */\n thumbnailDisplay?: ThumbnailDisplay;\n /**\n * Orientation of the thumbnail previews when showThumbnails is true.\n * 'vertical' displays thumbnails on the left side, 'horizontal' displays them below the image.\n *\n * @default 'vertical'\n */\n thumbnailOrientation?: 'vertical' | 'horizontal';\n};\n\n/**\n * Displays a single image at a time with navigation controls.\n * Allows navigation via buttons, dots (pagination), or touch gestures (on mobile).\n */\n// Default responsive image configuration\nconst DEFAULT_RESPONSIVE_CONFIG: ResponsiveImageConfig = {\n breakpoint: 768,\n desktopSize: 651,\n mobileSize: 366,\n};\n\nexport const ImageSlider = ({\n cards: initialCards,\n className,\n contentKey,\n iconShape = 'circle',\n iconSize = 'sm',\n iconType = 'caret',\n iconVariant = 'outlined',\n indexPosition = 'bottom',\n onAnalyticsEventTriggered,\n onImageClick,\n onImageMouseOver,\n responsiveImageConfig = DEFAULT_RESPONSIVE_CONFIG,\n showThumbnails = true,\n thumbnailDisplay = ThumbnailDisplay.Thumbnails,\n thumbnailOrientation = 'vertical',\n}: Props) => {\n // When an item doesn't have images, the cards array will be empty.\n // We need to show a placeholder empty card in this case.\n const cards = useMemo(() => {\n if (initialCards.length === 0) {\n return PLACEHOLDER_EMPTY_CARDS;\n }\n return initialCards;\n }, [initialCards]);\n\n const numberOfPages = cards.length;\n\n // Initialize base slider state and refs\n const {\n containerRef,\n contentRef,\n handleMobileInteraction,\n handleMouseOver,\n hasHoveredGallery,\n isMobile,\n setHasHoveredGallery,\n } = useImageSlider({\n numberOfPages,\n responsiveImageConfig,\n });\n\n // Manage scrolling state locally to avoid circular dependency\n const [isScrolling, setIsScrolling] = useState(false);\n\n // Initialize navigation state and handlers\n const navigation = useImageSliderNavigation({\n cards,\n contentKey,\n contentRef,\n isScrolling,\n numberOfPages,\n setHasHoveredGallery,\n thumbnailDisplay,\n thumbnailOrientation,\n });\n\n // Initialize scroll handling with navigation state and local setIsScrolling\n const { onScrollCards } = useImageSliderScrollHandler({\n contentRef,\n currentPage: navigation.currentPage,\n maxMobileCardWidth: responsiveImageConfig.desktopSize,\n numberOfPages,\n setCurrentPage: navigation.setCurrentPage,\n setIsScrolling,\n });\n\n // Extract all the values we need\n const {\n currentPage,\n goToNextPage,\n goToPreviousPage,\n handleThumbnailClick,\n isNextPageDisabled,\n isPreviousPageDisabled,\n onKeyNavigation,\n showNextPageButton,\n showPreviousPageButton,\n } = navigation;\n\n // Wrap navigation handlers to trigger analytics\n const goToNextPageWithAnalytics = useCallback(() => {\n goToNextPage();\n onAnalyticsEventTriggered?.({\n imagePosition: currentPage < numberOfPages ? currentPage + 1 : 1,\n interactionType: 'Next',\n totalImages: numberOfPages,\n });\n }, [goToNextPage, onAnalyticsEventTriggered, currentPage, numberOfPages]);\n\n const goToPreviousPageWithAnalytics = useCallback(() => {\n goToPreviousPage();\n onAnalyticsEventTriggered?.({\n imagePosition: currentPage > 1 ? currentPage - 1 : numberOfPages,\n interactionType: 'Prev',\n totalImages: numberOfPages,\n });\n }, [goToPreviousPage, onAnalyticsEventTriggered, currentPage, numberOfPages]);\n\n const handleThumbnailClickWithAnalytics = useCallback(\n (pageNumber: number) => {\n // Only trigger analytics if navigating to a different image\n if (pageNumber !== currentPage && onAnalyticsEventTriggered) {\n onAnalyticsEventTriggered({\n imagePosition: pageNumber,\n interactionType: 'Thumbnail Click',\n totalImages: numberOfPages,\n });\n }\n handleThumbnailClick(pageNumber);\n },\n [currentPage, handleThumbnailClick, onAnalyticsEventTriggered, numberOfPages]\n );\n\n /**\n * These images are wrapped in a div and displayed one at a time with proper snap behavior.\n * When showImageOverflow is enabled on mobile, images take partial width to show overflow.\n * Supports both custom ReactNode cards and responsive imageData.\n * Images are re-rendered when currentPage changes to ensure active image gets full quality.\n *\n * On desktop before hover: Only render first image to avoid loading second image unnecessarily.\n * On mobile: Always render all images for swipe functionality.\n * After hover on desktop: Render all images for navigation.\n */\n const carouselCards = useMemo(() => {\n // On desktop before hover, only render the first image to prevent unnecessary loading\n // On mobile or after hover, render all images\n const cardsToRender = !isMobile && !hasHoveredGallery ? cards.slice(0, 1) : cards;\n\n return cardsToRender.map(({ card, imageData, key }, index) => {\n // For the sliced scenario, we need to get the actual index from the original cards array\n const actualIndex = !isMobile && !hasHoveredGallery ? 0 : index;\n const isActive = actualIndex + 1 === currentPage;\n\n return (\n <div\n aria-current={isActive ? 'true' : 'false'}\n aria-label={`Image ${actualIndex + 1} of ${cards.length}${imageData?.alt ? `: ${imageData.alt}` : ''}`}\n className={cn(\n 'flex w-full flex-none snap-center items-center justify-center bg-background-primary',\n onImageClick ? 'cursor-zoom-in' : 'cursor-default',\n // Desktop: full height\n 'smMin:h-full',\n // Mobile-specific styling (xsMax) — max dimensions follow responsiveImageConfig.desktopSize via --slider-size\n 'xsMax:aspect-square xsMax:max-h-[var(--slider-size)] xsMax:max-w-[var(--slider-size)] xsMax:overflow-hidden xsMax:rounded-lg xsMax:border xsMax:border-border-secondary',\n // Apply width reduction only when there are multiple cards for bleed effect\n numberOfPages > 1\n ? 'xsMax:w-[calc(100%-64px)] xsMax:max-w-[var(--slider-size)]'\n : 'xsMax:w-full xsMax:max-w-[var(--slider-size)]',\n {\n 'ml-sm': actualIndex === 0,\n 'mr-sm': actualIndex === cards.length - 1,\n }\n )}\n key={key} // Use stable key to avoid unnecessary DOM recreations\n onClick={(event) => {\n // Trigger mobile interaction for high-quality loading\n handleMobileInteraction();\n // Trigger analytics for lightbox open\n if (onAnalyticsEventTriggered) {\n onAnalyticsEventTriggered({\n imagePosition: actualIndex + 1,\n interactionType: 'Open Lightbox',\n totalImages: numberOfPages,\n });\n }\n // Call optional user-provided handler\n onImageClick?.(actualIndex, event);\n }}\n onFocus={(event) => {\n // Trigger mobile interaction for high-quality loading\n handleMobileInteraction();\n // Call optional user-provided handler\n onImageMouseOver?.(actualIndex, event);\n }}\n onKeyUp={\n onImageClick\n ? (event) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n // Trigger analytics for lightbox open via keyboard\n if (onAnalyticsEventTriggered) {\n onAnalyticsEventTriggered({\n imagePosition: actualIndex + 1,\n interactionType: 'Open Lightbox',\n totalImages: numberOfPages,\n });\n }\n if (event.key === 'Enter') {\n onImageClick(actualIndex, event);\n }\n }\n }\n : undefined\n }\n onMouseOver={(event) => {\n // Always trigger gallery hover state for high-quality loading\n handleMouseOver();\n // Call optional user-provided handler\n if (onImageMouseOver) {\n onImageMouseOver(actualIndex, event);\n }\n }}\n onTouchStart={() => {\n // Trigger mobile interaction for high-quality loading on touch/drag\n handleMobileInteraction();\n }}\n role={onImageClick ? 'button' : undefined}\n tabIndex={onImageClick ? 0 : undefined}\n >\n {/* Render responsive image if imageData is provided, otherwise use custom card */}\n {imageData ? (\n <ResponsiveImage\n hasHoveredGallery={hasHoveredGallery}\n imageData={imageData}\n isActiveImage={isActive}\n isMainImage\n responsiveImageConfig={responsiveImageConfig}\n />\n ) : (\n card || null\n )}\n </div>\n );\n });\n }, [\n cards,\n currentPage,\n handleMobileInteraction,\n handleMouseOver,\n hasHoveredGallery,\n isMobile,\n numberOfPages,\n onAnalyticsEventTriggered,\n onImageClick,\n onImageMouseOver,\n responsiveImageConfig,\n ]);\n\n const isIndexDisplay = thumbnailDisplay === ThumbnailDisplay.Index;\n const isHorizontalThumbnailsDisplay =\n thumbnailDisplay === ThumbnailDisplay.Thumbnails && thumbnailOrientation === 'horizontal';\n\n return (\n // eslint-disable-next-line jsx-a11y/no-static-element-interactions, jsx-a11y/mouse-events-have-key-events, jsx-a11y/no-noninteractive-element-interactions, jsx-a11y/tabindex-no-positive\n <section\n aria-label=\"Image gallery\"\n aria-roledescription=\"carousel\"\n className={cn(\n 'relative mx-auto w-full pr-lg outline-none smMax:pr-0',\n // Only extend beyond viewport for bleed effect when there are multiple cards\n { 'xsMax:-ml-sm xsMax:w-[calc(100%+32px)]': numberOfPages > 1 },\n className\n )}\n onClick={() => containerRef.current?.focus()}\n onKeyUp={onKeyNavigation}\n onMouseOver={handleMouseOver}\n ref={containerRef}\n role=\"application\"\n style={\n {\n '--slider-size': `${responsiveImageConfig.desktopSize}px`,\n } as CSSProperties\n }\n // eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex\n tabIndex={0}\n >\n <div\n className={cn(\n 'flex flex-col',\n // Dynamic gap that scales smoothly from ~58px down to smaller sizes\n 'gap-[58px] mdMax:gap-xl smMax:gap-[38px] xsMax:gap-[28px]'\n )}\n >\n {/* Image Gallery Container */}\n <div\n className={cn(\n 'flex w-full',\n thumbnailDisplay === ThumbnailDisplay.Index\n ? 'flex-col items-center justify-center gap-2xs'\n : thumbnailOrientation === 'horizontal'\n ? 'flex-col items-center justify-center gap-xs'\n : 'relative items-center justify-center gap-[28px]'\n )}\n >\n {/* Index indicator - above main image when thumbnailDisplay is 'index' and indexPosition is 'top' */}\n {thumbnailDisplay === ThumbnailDisplay.Index && indexPosition === 'top' && (\n <IndexIndicator\n currentPage={currentPage}\n numberOfPages={numberOfPages}\n />\n )}\n\n {/* Vertical Thumbnails Container - Absolutely positioned */}\n {showThumbnails &&\n thumbnailDisplay === ThumbnailDisplay.Thumbnails &&\n thumbnailOrientation === 'vertical' && (\n <div className=\"absolute bottom-0 left-0 top-0 z-10 xsMax:hidden\">\n <Thumbnails\n cards={cards}\n currentPage={currentPage}\n generateThumbnailSizesAttribute={generateThumbnailSizesAttribute}\n generateThumbnailSrcSet={generateThumbnailSrcSet}\n onThumbnailClick={handleThumbnailClickWithAnalytics}\n orientation=\"vertical\"\n />\n </div>\n )}\n\n {/* Main Image Area */}\n <div\n className={cn(\n 'flex items-center',\n isIndexDisplay\n ? 'relative w-full justify-center gap-md smMin:max-w-[780px] xsMax:w-full'\n : isHorizontalThumbnailsDisplay\n ? 'max-w-[606px] gap-md xsMax:w-full'\n : cn(\n 'w-full justify-between gap-sm',\n showThumbnails ? 'pl-[146px] mdMax:pl-[139px] xsMax:pl-0' : ''\n )\n )}\n data-testid=\"image-slider-hero-controls\"\n >\n {/* Desktop navigation buttons (left) - hidden on mobile */}\n <div className=\"hidden smMin:block\">\n <NavigationButtons\n goToNextPage={goToNextPageWithAnalytics}\n goToPreviousPage={goToPreviousPageWithAnalytics}\n iconShape={iconShape}\n iconSize={iconSize}\n iconType={iconType}\n iconVariant={iconVariant}\n isNextPageDisabled={isNextPageDisabled}\n isPreviousPageDisabled={isPreviousPageDisabled}\n position=\"left\"\n showNextPageButton={showNextPageButton}\n showPreviousPageButton={showPreviousPageButton}\n />\n </div>\n\n {/* Main image container - responsive layout */}\n <div\n className={cn(\n // Shared: relative container with consistent max dimensions\n 'relative',\n isIndexDisplay\n ? 'max-h-[var(--slider-size)] smMin:flex smMin:aspect-square smMin:max-w-[var(--slider-size)] smMin:flex-1 smMin:justify-center smMin:overflow-hidden xsMax:w-full'\n : isHorizontalThumbnailsDisplay\n ? 'max-h-[400px] smMin:flex smMin:aspect-square smMin:max-w-[400px] smMin:flex-1 smMin:justify-center smMin:overflow-hidden xsMax:w-full'\n : 'max-h-[var(--slider-size)] smMin:flex smMin:aspect-square smMin:max-w-[var(--slider-size)] smMin:flex-1 smMin:justify-center smMin:overflow-hidden xsMax:w-full'\n )}\n data-testid=\"image-slider-media-frame\"\n >\n {/* Mobile navigation buttons - hidden on desktop */}\n <div className=\"smMin:hidden\">\n <NavigationButtons\n goToNextPage={goToNextPageWithAnalytics}\n goToPreviousPage={goToPreviousPageWithAnalytics}\n iconShape={iconShape}\n iconSize={iconSize}\n iconType={iconType}\n iconVariant={iconVariant}\n isNextPageDisabled={isNextPageDisabled}\n isPreviousPageDisabled={isPreviousPageDisabled}\n showNextPageButton={showNextPageButton}\n showPreviousPageButton={showPreviousPageButton}\n />\n </div>\n\n {/* Responsive scroll container wrapper */}\n <div\n className={cn(\n // Shared: primary background and full width\n 'w-full bg-background-primary',\n // Desktop: full height and hidden overflow\n 'smMin:h-full smMin:overflow-hidden'\n )}\n >\n <div\n aria-atomic=\"false\"\n aria-live=\"polite\"\n className={cn(\n 'flex w-full snap-x snap-mandatory overflow-y-hidden overflow-x-scroll',\n // Desktop: full height and 24px gap\n 'smMin:h-full smMin:gap-md',\n // Mobile: 2xs gap, let aspect-square control height\n 'xsMax:gap-2xs'\n )}\n onScroll={onScrollCards}\n ref={contentRef}\n role=\"region\"\n style={{\n scrollbarWidth: 'none',\n }}\n >\n {carouselCards}\n </div>\n </div>\n </div>\n\n {/* Desktop navigation buttons (right) - hidden on mobile */}\n <div className=\"hidden smMin:block\">\n <NavigationButtons\n goToNextPage={goToNextPageWithAnalytics}\n goToPreviousPage={goToPreviousPageWithAnalytics}\n iconShape={iconShape}\n iconSize={iconSize}\n iconType={iconType}\n iconVariant={iconVariant}\n isNextPageDisabled={isNextPageDisabled}\n isPreviousPageDisabled={isPreviousPageDisabled}\n position=\"right\"\n showNextPageButton={showNextPageButton}\n showPreviousPageButton={showPreviousPageButton}\n />\n </div>\n </div>\n\n {/* Horizontal Thumbnails Container - Below image */}\n {showThumbnails &&\n thumbnailDisplay === ThumbnailDisplay.Thumbnails &&\n thumbnailOrientation === 'horizontal' && (\n <div className=\"w-full xsMax:hidden\">\n <Thumbnails\n cards={cards}\n currentPage={currentPage}\n generateThumbnailSizesAttribute={generateThumbnailSizesAttribute}\n generateThumbnailSrcSet={generateThumbnailSrcSet}\n onThumbnailClick={handleThumbnailClickWithAnalytics}\n orientation=\"horizontal\"\n />\n </div>\n )}\n\n {/* Index indicator - below main image when thumbnailDisplay is 'index' and indexPosition is 'bottom' */}\n {thumbnailDisplay === ThumbnailDisplay.Index && indexPosition === 'bottom' && (\n <IndexIndicator\n currentPage={currentPage}\n numberOfPages={numberOfPages}\n />\n )}\n </div>\n </div>\n </section>\n );\n};\n"],"mappings":"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"}
|
package/Menu-ClUogmwE.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Menu-ClUogmwE.cjs","names":["MenuContext","ToggleSwitch","Checkbox","RadioOption","H5","BodyPrimary","Caption","useMenuContext","autoUpdate","FloatingNode","MenuContext","FloatingList","FloatingPortal","FloatingFocusManager","FloatingArrow","FloatingTree"],"sources":["../src/Menu/components/MenuItem/MenuItem.tsx","../src/Menu/components/MenuDivider/MenuDivider.tsx","../src/Menu/Menu.tsx"],"sourcesContent":["import { cn } from '@evolve.ui/theme-system';\nimport { useFloatingTree, useListItem, useMergeRefs } from '@floating-ui/react';\nimport { forwardRef, HTMLAttributes, KeyboardEvent, useContext, useEffect, useMemo, useState } from 'react';\n\nimport { Checkbox, RadioOption } from '../../../ChoiceListItem';\nimport { AnyIcon } from '../../../Icons/anyIcon';\nimport { ToggleSwitch } from '../../../ToggleSwitch/ToggleSwitch';\nimport { BodyPrimary, Caption, H5 } from '../../../Typography/Text/Text';\nimport { MenuContext } from '../../context/menuContext';\n\nexport type MenuItemProps = {\n /** additional CSS class name for the menu item*/\n className?: string;\n /** close menu after action is performed */\n closeOnAction?: boolean;\n /** color of menu item */\n color?: 'disabled' | 'inherit' | 'critical' | 'info' | 'inverse' | 'success' | 'secondary' | 'primary' | 'warning';\n /** second row description, optional */\n description?: string;\n /** disable menu item */\n disabled?: boolean;\n /** id required for all event handlers: click, checkbox,\n * radio or toggle\n */\n id?: string | number;\n /** flag if using as header, alters style and hover state */\n isHeader?: boolean;\n /** Icon to use on Left side of menu item, requires numberOfColumns of 3 */\n leftIcon?: AnyIcon;\n /** primary menu label string, required */\n primaryLabel: string;\n /** Icon to use on Right side of menu, requires numberOfColumns of 2 or 3 */\n rightIcon?: AnyIcon;\n /** secondary label to be used to right of primary label, cannot be used with rightIcon, requires numberOfColumns of 2 or 3 */\n secondaryLabel?: string;\n} & (\n | {\n checked?: never;\n id?: never;\n onCheckboxChange?: never;\n onClick?: never;\n onFocus?: never;\n onRadioChange?: never;\n onToggleChange?: never;\n }\n | {\n /** current state of control */\n checked?: boolean;\n /** id required for all event handlers: click, checkbox,\n * radio or toggle\n */\n className?: string;\n id?: string | number;\n /** if present, will show checkbox on in LeftIcon space, requires numberOfColumns of 3 */\n onCheckboxChange?: (id: string | number, checked: boolean) => void;\n /** if present, will show checkbox on in LeftIcon space */\n onClick?: (id: string | number) => void;\n /** if present, trigger when MenuItem is focused */\n onFocus?: (id: string | number) => void;\n /** if present, will show checkbox on in LeftIcon space, requires numberOfColumns of 3 */\n onRadioChange?: (id: string | number, checked: boolean) => void;\n /** if present, will show checkbox on in RightIcon space, requires numberOfColumns of 2 or 3 */\n onToggleChange?: (id: string | number, checked: boolean) => void;\n }\n);\n\nexport const MenuItem = forwardRef<HTMLDivElement, MenuItemProps & HTMLAttributes<HTMLDivElement>>(\n (\n {\n checked = false,\n className,\n closeOnAction = false,\n color = 'inherit',\n description,\n disabled,\n id = '',\n isHeader,\n leftIcon: LeftIcon,\n onCheckboxChange,\n onClick,\n onFocus,\n onRadioChange,\n onToggleChange,\n primaryLabel,\n rightIcon: RightIcon,\n secondaryLabel,\n ...rest\n }: MenuItemProps & HTMLAttributes<HTMLDivElement>,\n forwardedRef\n ) => {\n const [isChecked, setIsChecked] = useState(checked);\n const { getItemProps, numberOfColumns } = useContext(MenuContext);\n const { ref: itemRef } = useListItem();\n\n const renderColor = disabled ? 'disabled' : color;\n\n useEffect(() => {\n setIsChecked(checked);\n }, [checked]);\n\n const tree = useFloatingTree();\n\n const rightSection = useMemo(() => {\n if (RightIcon) {\n return (\n <RightIcon\n className=\"self-center justify-self-center grid-area-[right]\"\n color={renderColor}\n size=\"sm\"\n />\n );\n }\n if (onToggleChange) {\n // Note, event handled by component level onClick\n return (\n <ToggleSwitch\n className=\"grid-area-[right]\"\n data-testid={`menu-toggle-${id}`}\n dense\n isToggled={isChecked}\n tabIndex={-1}\n />\n );\n }\n return null;\n }, [id, RightIcon, onToggleChange, isChecked, renderColor]);\n\n const handleKeyDown = (e: KeyboardEvent<HTMLDivElement>) => {\n if (disabled) {\n return;\n }\n if (e.code === 'Space' || e.code === 'Enter') {\n if (onClick) {\n onClick(id);\n tree?.events.emit('click');\n } else if (onCheckboxChange) {\n const newChecked = !isChecked;\n setIsChecked(newChecked);\n onCheckboxChange(id, newChecked);\n if (closeOnAction) {\n tree?.events.emit('click');\n }\n } else if (onRadioChange) {\n const newChecked = !isChecked;\n setIsChecked(newChecked);\n onRadioChange(id, newChecked);\n if (closeOnAction) {\n tree?.events.emit('click');\n }\n } else if (onToggleChange) {\n const newChecked = !isChecked;\n setIsChecked(newChecked);\n onToggleChange(id, newChecked);\n if (closeOnAction) {\n tree?.events.emit('click');\n }\n }\n }\n };\n\n const handleItemClick = (event: React.MouseEvent<HTMLElement>) => {\n event.stopPropagation();\n if (disabled) {\n return;\n }\n // this is to prevent UI elements like SVGs from triggering an additional click\n if (\n event.target instanceof HTMLButtonElement ||\n event.target instanceof HTMLInputElement ||\n event.target instanceof HTMLSpanElement ||\n event.target instanceof HTMLDivElement\n ) {\n if (onClick) {\n onClick(id);\n tree?.events.emit('click');\n } else if (onCheckboxChange) {\n const newChecked = !isChecked;\n setIsChecked(newChecked);\n onCheckboxChange(id, newChecked);\n if (closeOnAction) {\n tree?.events.emit('click');\n }\n } else if (onRadioChange) {\n const newChecked = !isChecked;\n setIsChecked(newChecked);\n onRadioChange(id, newChecked);\n if (closeOnAction) {\n tree?.events.emit('click');\n }\n } else if (onToggleChange) {\n const newChecked = !isChecked;\n setIsChecked(newChecked);\n onToggleChange(id, newChecked);\n if (closeOnAction) {\n tree?.events.emit('click');\n }\n }\n }\n };\n\n const handleFocus = () => {\n if (disabled) {\n return;\n }\n onFocus?.(id);\n };\n\n return (\n <div\n {...rest}\n {...getItemProps({})}\n aria-describedby={description ? `menu-item-description-${id}` : undefined}\n aria-disabled={disabled}\n aria-label={primaryLabel}\n className={cn(\n {\n 'active:bg-background-hover': !isHeader,\n 'focus:bg-background-hover': !isHeader,\n 'hover:bg-background-hover': !isHeader,\n },\n 'MenuItem relative grid w-full cursor-pointer items-center justify-start gap-x-xs border-none px-sm py-3 outline-0',\n className\n )}\n data-testid={`menu-item-${id}`}\n onClick={handleItemClick}\n onFocus={handleFocus}\n onKeyDown={handleKeyDown}\n ref={useMergeRefs([itemRef, forwardedRef])}\n role=\"menuitem\"\n style={{\n gridTemplateAreas:\n numberOfColumns === 2\n ? \"'title right' 'description right'\"\n : numberOfColumns === 1\n ? \"'title' 'description'\"\n : // 3 column default\n \"'icon title right' 'icon description right'\",\n gridTemplateColumns:\n numberOfColumns === 2\n ? '1fr min-content'\n : numberOfColumns === 1\n ? '1fr'\n : // 3 column default\n '24px 1fr min-content',\n gridTemplateRows: 'min-content min-content',\n }}\n tabIndex={isHeader ? -1 : 0}\n >\n {/* LEFT */}\n {LeftIcon && (\n <LeftIcon\n className=\"self-center justify-self-center grid-area-[icon]\"\n color={renderColor}\n size=\"sm\"\n />\n )}\n {onCheckboxChange && (\n <Checkbox.Option\n checked={isChecked}\n className=\"grid-area-[icon]\"\n data-testid={`menu-checkbox-${id}`}\n readOnly // no onChange event is provided, handled by MenuItem propagation\n tabIndex={-1}\n />\n )}\n {onRadioChange && (\n <RadioOption\n checked={isChecked}\n className=\"grid-area-[icon]\"\n data-testid={`menu-radio-${id}`}\n readOnly // no onChange event is provided, handled by MenuItem propagation\n tabIndex={-1}\n />\n )}\n\n {/* MAIN */}\n {isHeader ? (\n <H5 className={cn('grid-area-[title]', `text-text-${renderColor}`)}>{primaryLabel}</H5>\n ) : (\n <div className=\"flex items-center justify-between gap-x-xs grid-area-[title]\">\n <BodyPrimary className={`text-text-${renderColor}`}>{primaryLabel}</BodyPrimary>\n {secondaryLabel && <BodyPrimary className=\"text-text-secondary\">{secondaryLabel}</BodyPrimary>}\n </div>\n )}\n {Boolean(description?.trim()) && (\n <Caption className={cn('grid-area-[description]', `text-text-${renderColor}`)}>\n {description}\n </Caption>\n )}\n\n {/* RIGHT */}\n {rightSection}\n </div>\n );\n }\n);\n\nMenuItem.displayName = 'MenuItem';\n","import { cn } from '@evolve.ui/theme-system';\n\nexport const MenuDivider = ({ className }: { className?: string }) => {\n return <div className={cn('border-t border-border-secondary', className)} />;\n};\n","import { cn } from '@evolve.ui/theme-system';\nimport {\n arrow,\n autoUpdate,\n flip,\n FloatingArrow,\n FloatingFocusManager,\n FloatingList,\n FloatingNode,\n FloatingPortal,\n FloatingTree,\n offset,\n Placement,\n safePolygon,\n shift,\n useClick,\n useDismiss,\n useFloating,\n useFloatingNodeId,\n useFloatingParentNodeId,\n useFloatingTree,\n useHover,\n useInteractions,\n useListItem,\n useListNavigation,\n useMergeRefs,\n useRole,\n useTypeahead,\n} from '@floating-ui/react';\nimport {\n cloneElement,\n FocusEvent,\n forwardRef,\n HTMLProps,\n isValidElement,\n MouseEvent,\n ReactElement,\n ReactNode,\n useEffect,\n useRef,\n useState,\n} from 'react';\n\nimport { MenuContext, useMenuContext } from './context/menuContext';\n\n/**\n * Hook to detect if component has mounted (client-side only)\n * Useful for preventing SSR hydration mismatches\n */\nconst useHasMounted = () => {\n const [hasMounted, setHasMounted] = useState(false);\n useEffect(() => {\n setHasMounted(true);\n }, []);\n return hasMounted;\n};\n\nexport type MenuProps = {\n /** MenuItem children */\n children?: ReactNode;\n /** additional CSS class name for the menu container*/\n className?: string;\n /** when true, menu will open on first render */\n defaultOpen?: boolean;\n /** when true, menu borders are rounded */\n hasRoundedBorders?: boolean;\n /**\n * Optional stable ID for SSR scenarios. If not provided, a unique ID will be generated.\n * This helps prevent hydration mismatches when using SSR.\n */\n id?: string;\n /** Enable menu custom content vs MenuItem children */\n isCustomContent?: boolean;\n /** initial menu placement */\n menuPlacement?: Placement;\n /** custom menu width */\n menuSize?: 'sm' | 'md' | 'lg' | 'xl';\n /** number of grid columns required for children */\n numberOfColumns: 1 | 2 | 3;\n /** callback that triggers when the menu is closed */\n onMenuClose?: () => void;\n /** callback that triggers when the menu is opened */\n onMenuOpen?: () => void;\n /** when true, menu will open on hover */\n openOnHover?: boolean;\n /** trigger component to open menu */\n trigger: ReactNode;\n /** additional CSS class name for the trigger */\n triggerClassName?: string;\n};\n\nconst MenuComponent = forwardRef<HTMLSpanElement, MenuProps & HTMLProps<HTMLSpanElement>>(\n (\n {\n children,\n className,\n defaultOpen,\n hasRoundedBorders = false,\n id,\n isCustomContent,\n menuPlacement,\n menuSize = 'lg',\n numberOfColumns,\n onMenuClose,\n onMenuOpen,\n openOnHover = false,\n trigger,\n triggerClassName,\n ...props\n },\n forwardedRef\n ) => {\n const [isOpen, setIsOpen] = useState(defaultOpen ?? false);\n const [activeIndex, setActiveIndex] = useState<number | null>(null);\n const elementsRef = useRef<Array<HTMLSpanElement | null>>([]);\n const labelsRef = useRef<Array<string | null>>([]);\n const parent = useMenuContext();\n const hasMounted = useHasMounted();\n\n const tree = useFloatingTree();\n const nodeId = useFloatingNodeId(id);\n const parentId = useFloatingParentNodeId();\n const item = useListItem();\n\n const isNested = parentId !== null;\n\n const arrowRef = useRef(null);\n\n const { context, floatingStyles, refs } = useFloating<HTMLButtonElement>({\n middleware: [\n offset({ alignmentAxis: -2, mainAxis: isNested ? 2 : 8 }),\n flip(),\n shift({ padding: !isNested ? 2 : 0 }),\n arrow({ element: arrowRef, padding: 5 }),\n ],\n nodeId,\n onOpenChange: (open) => {\n setIsOpen(open);\n if (!open) {\n onMenuClose?.();\n } else {\n onMenuOpen?.();\n }\n },\n open: isOpen,\n placement: isNested ? 'right-start' : (menuPlacement ?? 'bottom'),\n whileElementsMounted: autoUpdate,\n });\n const hover = useHover(context, {\n delay: { open: 75 },\n enabled: isNested || openOnHover,\n handleClose: safePolygon({ blockPointerEvents: true }),\n });\n const click = useClick(context, {\n enabled: !context.dataRef.current.openEvent?.defaultPrevented && !openOnHover,\n event: 'click',\n ignoreMouse: isNested,\n toggle: !isNested,\n });\n\n const role = useRole(context, { role: 'menu' });\n const dismiss = useDismiss(context, { bubbles: true });\n const listNavigation = useListNavigation(context, {\n activeIndex,\n focusItemOnOpen: false,\n listRef: elementsRef,\n nested: isNested,\n onNavigate: setActiveIndex,\n });\n const typeahead = useTypeahead(context, {\n activeIndex,\n enabled: !isCustomContent,\n listRef: labelsRef,\n onMatch: isOpen ? setActiveIndex : undefined,\n });\n\n const { getFloatingProps, getItemProps, getReferenceProps } = useInteractions([\n hover,\n click,\n role,\n dismiss,\n listNavigation,\n typeahead,\n ]);\n\n // Event emitter allows you to communicate across tree components.\n // This effect closes all menus when an item gets clicked anywhere\n // in the tree.\n useEffect(() => {\n if (!tree) {\n return;\n }\n\n function handleTreeClick() {\n setIsOpen(false);\n onMenuClose?.();\n }\n\n function onSubMenuOpen(event: { nodeId: string; parentId: string }) {\n if (event.nodeId !== nodeId && event.parentId === parentId) {\n setIsOpen(false);\n onMenuClose?.();\n }\n }\n\n tree.events.on('click', handleTreeClick);\n tree.events.on('menuopen', onSubMenuOpen);\n\n return () => {\n tree.events.off('click', handleTreeClick);\n tree.events.off('menuopen', onSubMenuOpen);\n };\n }, [tree, nodeId, parentId, onMenuClose]);\n\n useEffect(() => {\n if (isOpen && tree) {\n tree.events.emit('menuopen', { nodeId, parentId });\n }\n }, [tree, isOpen, nodeId, parentId]);\n\n // Strip the three ARIA attrs from the floating-ui reference props so the wrapper span keeps\n // every behavior it had before (refs, click/keyboard handlers, positioning), but no longer\n // carries ARIA that its implicit `generic` role disallows (the axe `aria-allowed-attr`\n // violation). The three ARIA attrs are reapplied to the trigger child via `cloneElement`,\n // landing on a node whose role natively permits them (button / link / menuitem).\n const {\n 'aria-controls': ariaControls,\n 'aria-expanded': ariaExpanded,\n 'aria-haspopup': ariaHasPopup,\n ...referencePropsWithoutAria\n } = getReferenceProps(\n parent.getItemProps({\n ...props,\n onClick(event: MouseEvent<HTMLButtonElement>) {\n event.stopPropagation();\n props.onClick?.(event);\n },\n onFocus(event: FocusEvent<HTMLButtonElement>) {\n props.onFocus?.(event);\n },\n })\n ) as Record<string, unknown>;\n\n const triggerIsElement = isValidElement(trigger);\n const triggerElement = trigger as ReactElement;\n const ariaPropsForTrigger: Record<string, unknown> = {};\n if (ariaHasPopup !== undefined) {\n ariaPropsForTrigger['aria-haspopup'] = ariaHasPopup;\n }\n if (ariaExpanded !== undefined) {\n ariaPropsForTrigger['aria-expanded'] = ariaExpanded;\n }\n if (ariaControls !== undefined) {\n ariaPropsForTrigger['aria-controls'] = ariaControls;\n }\n\n // For element triggers, clone the ARIA onto the child (preferred — lands on a node whose role\n // natively permits these attrs). Note: this intentionally overrides any same-named ARIA the\n // caller already set on the trigger; menu disclosure semantics (`aria-haspopup=\"menu\"`) must\n // win for the popup to be announced correctly.\n const clonedTrigger = triggerIsElement ? cloneElement(triggerElement, ariaPropsForTrigger) : trigger;\n\n // For non-element triggers (string / number / null), we cannot clone ARIA anywhere meaningful,\n // so the wrapper span itself becomes the disclosure control. Adding `role=\"button\"` +\n // `tabIndex={0}` makes the ARIA attrs valid (no `aria-allowed-attr` violation) and preserves\n // the screen-reader disclosure pattern. Safe because non-element triggers don't contain a\n // nested interactive element (no `nested-interactive` violation).\n const wrapperFallbackProps = !triggerIsElement ? { ...ariaPropsForTrigger, role: 'button' as const } : {};\n\n return (\n <FloatingNode id={nodeId}>\n <span\n className={cn(\n {\n 'w-full': isNested,\n },\n 'm-0 inline-flex cursor-pointer appearance-none items-center border-none bg-none p-0 text-left no-underline outline-0 hover:no-underline',\n triggerClassName\n )}\n data-testid=\"menu-trigger-wrapper\"\n ref={useMergeRefs([refs.setReference, item.ref, forwardedRef])}\n tabIndex={\n !triggerIsElement ? 0 : !isNested ? undefined : parent.activeIndex === item.index ? 0 : -1\n }\n {...wrapperFallbackProps}\n {...referencePropsWithoutAria}\n >\n {clonedTrigger}\n </span>\n <MenuContext.Provider\n value={{\n activeIndex,\n getItemProps,\n isOpen,\n numberOfColumns,\n setActiveIndex,\n }}\n >\n <FloatingList\n elementsRef={elementsRef}\n labelsRef={labelsRef}\n >\n {isOpen && hasMounted && Boolean(refs.domReference) && (\n <FloatingPortal root={refs.domReference}>\n <FloatingFocusManager\n context={context}\n initialFocus={-1}\n modal={false}\n returnFocus={!isNested}\n >\n <div\n className={cn(\n 'Menu relative z-50 w-min cursor-default bg-background-primary py-2 shadow-03 outline-0',\n {\n 'min-w-[200px]': menuSize === 'sm',\n 'min-w-[250px]': menuSize === 'md',\n 'min-w-[300px]': menuSize === 'lg',\n 'min-w-[350px]': menuSize === 'xl',\n 'rounded-md': hasRoundedBorders,\n },\n className\n )}\n data-testid=\"menu-wrapper\"\n ref={refs.setFloating}\n style={floatingStyles}\n {...getFloatingProps()}\n >\n {!isNested && (\n <FloatingArrow\n className=\"fill-background-primary\"\n context={context}\n ref={arrowRef}\n tipRadius={hasRoundedBorders ? 2 : 0}\n />\n )}\n {children}\n </div>\n </FloatingFocusManager>\n </FloatingPortal>\n )}\n </FloatingList>\n </MenuContext.Provider>\n </FloatingNode>\n );\n }\n);\n\nMenuComponent.displayName = 'MenuComponent';\n\nexport const Menu = forwardRef<HTMLSpanElement, MenuProps & HTMLProps<HTMLSpanElement>>((props, ref) => {\n const parentId = useFloatingParentNodeId();\n\n if (parentId === null) {\n return (\n <FloatingTree>\n <MenuComponent\n {...props}\n ref={ref}\n />\n </FloatingTree>\n );\n }\n\n return (\n <MenuComponent\n {...props}\n ref={ref}\n />\n );\n});\n\nMenu.displayName = 'Menu';\n"],"mappings":"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"}
|
package/Menu-Cxu8CaX1.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Menu-Cxu8CaX1.mjs","names":[],"sources":["../src/Menu/components/MenuItem/MenuItem.tsx","../src/Menu/components/MenuDivider/MenuDivider.tsx","../src/Menu/Menu.tsx"],"sourcesContent":["import { cn } from '@evolve.ui/theme-system';\nimport { useFloatingTree, useListItem, useMergeRefs } from '@floating-ui/react';\nimport { forwardRef, HTMLAttributes, KeyboardEvent, useContext, useEffect, useMemo, useState } from 'react';\n\nimport { Checkbox, RadioOption } from '../../../ChoiceListItem';\nimport { AnyIcon } from '../../../Icons/anyIcon';\nimport { ToggleSwitch } from '../../../ToggleSwitch/ToggleSwitch';\nimport { BodyPrimary, Caption, H5 } from '../../../Typography/Text/Text';\nimport { MenuContext } from '../../context/menuContext';\n\nexport type MenuItemProps = {\n /** additional CSS class name for the menu item*/\n className?: string;\n /** close menu after action is performed */\n closeOnAction?: boolean;\n /** color of menu item */\n color?: 'disabled' | 'inherit' | 'critical' | 'info' | 'inverse' | 'success' | 'secondary' | 'primary' | 'warning';\n /** second row description, optional */\n description?: string;\n /** disable menu item */\n disabled?: boolean;\n /** id required for all event handlers: click, checkbox,\n * radio or toggle\n */\n id?: string | number;\n /** flag if using as header, alters style and hover state */\n isHeader?: boolean;\n /** Icon to use on Left side of menu item, requires numberOfColumns of 3 */\n leftIcon?: AnyIcon;\n /** primary menu label string, required */\n primaryLabel: string;\n /** Icon to use on Right side of menu, requires numberOfColumns of 2 or 3 */\n rightIcon?: AnyIcon;\n /** secondary label to be used to right of primary label, cannot be used with rightIcon, requires numberOfColumns of 2 or 3 */\n secondaryLabel?: string;\n} & (\n | {\n checked?: never;\n id?: never;\n onCheckboxChange?: never;\n onClick?: never;\n onFocus?: never;\n onRadioChange?: never;\n onToggleChange?: never;\n }\n | {\n /** current state of control */\n checked?: boolean;\n /** id required for all event handlers: click, checkbox,\n * radio or toggle\n */\n className?: string;\n id?: string | number;\n /** if present, will show checkbox on in LeftIcon space, requires numberOfColumns of 3 */\n onCheckboxChange?: (id: string | number, checked: boolean) => void;\n /** if present, will show checkbox on in LeftIcon space */\n onClick?: (id: string | number) => void;\n /** if present, trigger when MenuItem is focused */\n onFocus?: (id: string | number) => void;\n /** if present, will show checkbox on in LeftIcon space, requires numberOfColumns of 3 */\n onRadioChange?: (id: string | number, checked: boolean) => void;\n /** if present, will show checkbox on in RightIcon space, requires numberOfColumns of 2 or 3 */\n onToggleChange?: (id: string | number, checked: boolean) => void;\n }\n);\n\nexport const MenuItem = forwardRef<HTMLDivElement, MenuItemProps & HTMLAttributes<HTMLDivElement>>(\n (\n {\n checked = false,\n className,\n closeOnAction = false,\n color = 'inherit',\n description,\n disabled,\n id = '',\n isHeader,\n leftIcon: LeftIcon,\n onCheckboxChange,\n onClick,\n onFocus,\n onRadioChange,\n onToggleChange,\n primaryLabel,\n rightIcon: RightIcon,\n secondaryLabel,\n ...rest\n }: MenuItemProps & HTMLAttributes<HTMLDivElement>,\n forwardedRef\n ) => {\n const [isChecked, setIsChecked] = useState(checked);\n const { getItemProps, numberOfColumns } = useContext(MenuContext);\n const { ref: itemRef } = useListItem();\n\n const renderColor = disabled ? 'disabled' : color;\n\n useEffect(() => {\n setIsChecked(checked);\n }, [checked]);\n\n const tree = useFloatingTree();\n\n const rightSection = useMemo(() => {\n if (RightIcon) {\n return (\n <RightIcon\n className=\"self-center justify-self-center grid-area-[right]\"\n color={renderColor}\n size=\"sm\"\n />\n );\n }\n if (onToggleChange) {\n // Note, event handled by component level onClick\n return (\n <ToggleSwitch\n className=\"grid-area-[right]\"\n data-testid={`menu-toggle-${id}`}\n dense\n isToggled={isChecked}\n tabIndex={-1}\n />\n );\n }\n return null;\n }, [id, RightIcon, onToggleChange, isChecked, renderColor]);\n\n const handleKeyDown = (e: KeyboardEvent<HTMLDivElement>) => {\n if (disabled) {\n return;\n }\n if (e.code === 'Space' || e.code === 'Enter') {\n if (onClick) {\n onClick(id);\n tree?.events.emit('click');\n } else if (onCheckboxChange) {\n const newChecked = !isChecked;\n setIsChecked(newChecked);\n onCheckboxChange(id, newChecked);\n if (closeOnAction) {\n tree?.events.emit('click');\n }\n } else if (onRadioChange) {\n const newChecked = !isChecked;\n setIsChecked(newChecked);\n onRadioChange(id, newChecked);\n if (closeOnAction) {\n tree?.events.emit('click');\n }\n } else if (onToggleChange) {\n const newChecked = !isChecked;\n setIsChecked(newChecked);\n onToggleChange(id, newChecked);\n if (closeOnAction) {\n tree?.events.emit('click');\n }\n }\n }\n };\n\n const handleItemClick = (event: React.MouseEvent<HTMLElement>) => {\n event.stopPropagation();\n if (disabled) {\n return;\n }\n // this is to prevent UI elements like SVGs from triggering an additional click\n if (\n event.target instanceof HTMLButtonElement ||\n event.target instanceof HTMLInputElement ||\n event.target instanceof HTMLSpanElement ||\n event.target instanceof HTMLDivElement\n ) {\n if (onClick) {\n onClick(id);\n tree?.events.emit('click');\n } else if (onCheckboxChange) {\n const newChecked = !isChecked;\n setIsChecked(newChecked);\n onCheckboxChange(id, newChecked);\n if (closeOnAction) {\n tree?.events.emit('click');\n }\n } else if (onRadioChange) {\n const newChecked = !isChecked;\n setIsChecked(newChecked);\n onRadioChange(id, newChecked);\n if (closeOnAction) {\n tree?.events.emit('click');\n }\n } else if (onToggleChange) {\n const newChecked = !isChecked;\n setIsChecked(newChecked);\n onToggleChange(id, newChecked);\n if (closeOnAction) {\n tree?.events.emit('click');\n }\n }\n }\n };\n\n const handleFocus = () => {\n if (disabled) {\n return;\n }\n onFocus?.(id);\n };\n\n return (\n <div\n {...rest}\n {...getItemProps({})}\n aria-describedby={description ? `menu-item-description-${id}` : undefined}\n aria-disabled={disabled}\n aria-label={primaryLabel}\n className={cn(\n {\n 'active:bg-background-hover': !isHeader,\n 'focus:bg-background-hover': !isHeader,\n 'hover:bg-background-hover': !isHeader,\n },\n 'MenuItem relative grid w-full cursor-pointer items-center justify-start gap-x-xs border-none px-sm py-3 outline-0',\n className\n )}\n data-testid={`menu-item-${id}`}\n onClick={handleItemClick}\n onFocus={handleFocus}\n onKeyDown={handleKeyDown}\n ref={useMergeRefs([itemRef, forwardedRef])}\n role=\"menuitem\"\n style={{\n gridTemplateAreas:\n numberOfColumns === 2\n ? \"'title right' 'description right'\"\n : numberOfColumns === 1\n ? \"'title' 'description'\"\n : // 3 column default\n \"'icon title right' 'icon description right'\",\n gridTemplateColumns:\n numberOfColumns === 2\n ? '1fr min-content'\n : numberOfColumns === 1\n ? '1fr'\n : // 3 column default\n '24px 1fr min-content',\n gridTemplateRows: 'min-content min-content',\n }}\n tabIndex={isHeader ? -1 : 0}\n >\n {/* LEFT */}\n {LeftIcon && (\n <LeftIcon\n className=\"self-center justify-self-center grid-area-[icon]\"\n color={renderColor}\n size=\"sm\"\n />\n )}\n {onCheckboxChange && (\n <Checkbox.Option\n checked={isChecked}\n className=\"grid-area-[icon]\"\n data-testid={`menu-checkbox-${id}`}\n readOnly // no onChange event is provided, handled by MenuItem propagation\n tabIndex={-1}\n />\n )}\n {onRadioChange && (\n <RadioOption\n checked={isChecked}\n className=\"grid-area-[icon]\"\n data-testid={`menu-radio-${id}`}\n readOnly // no onChange event is provided, handled by MenuItem propagation\n tabIndex={-1}\n />\n )}\n\n {/* MAIN */}\n {isHeader ? (\n <H5 className={cn('grid-area-[title]', `text-text-${renderColor}`)}>{primaryLabel}</H5>\n ) : (\n <div className=\"flex items-center justify-between gap-x-xs grid-area-[title]\">\n <BodyPrimary className={`text-text-${renderColor}`}>{primaryLabel}</BodyPrimary>\n {secondaryLabel && <BodyPrimary className=\"text-text-secondary\">{secondaryLabel}</BodyPrimary>}\n </div>\n )}\n {Boolean(description?.trim()) && (\n <Caption className={cn('grid-area-[description]', `text-text-${renderColor}`)}>\n {description}\n </Caption>\n )}\n\n {/* RIGHT */}\n {rightSection}\n </div>\n );\n }\n);\n\nMenuItem.displayName = 'MenuItem';\n","import { cn } from '@evolve.ui/theme-system';\n\nexport const MenuDivider = ({ className }: { className?: string }) => {\n return <div className={cn('border-t border-border-secondary', className)} />;\n};\n","import { cn } from '@evolve.ui/theme-system';\nimport {\n arrow,\n autoUpdate,\n flip,\n FloatingArrow,\n FloatingFocusManager,\n FloatingList,\n FloatingNode,\n FloatingPortal,\n FloatingTree,\n offset,\n Placement,\n safePolygon,\n shift,\n useClick,\n useDismiss,\n useFloating,\n useFloatingNodeId,\n useFloatingParentNodeId,\n useFloatingTree,\n useHover,\n useInteractions,\n useListItem,\n useListNavigation,\n useMergeRefs,\n useRole,\n useTypeahead,\n} from '@floating-ui/react';\nimport {\n cloneElement,\n FocusEvent,\n forwardRef,\n HTMLProps,\n isValidElement,\n MouseEvent,\n ReactElement,\n ReactNode,\n useEffect,\n useRef,\n useState,\n} from 'react';\n\nimport { MenuContext, useMenuContext } from './context/menuContext';\n\n/**\n * Hook to detect if component has mounted (client-side only)\n * Useful for preventing SSR hydration mismatches\n */\nconst useHasMounted = () => {\n const [hasMounted, setHasMounted] = useState(false);\n useEffect(() => {\n setHasMounted(true);\n }, []);\n return hasMounted;\n};\n\nexport type MenuProps = {\n /** MenuItem children */\n children?: ReactNode;\n /** additional CSS class name for the menu container*/\n className?: string;\n /** when true, menu will open on first render */\n defaultOpen?: boolean;\n /** when true, menu borders are rounded */\n hasRoundedBorders?: boolean;\n /**\n * Optional stable ID for SSR scenarios. If not provided, a unique ID will be generated.\n * This helps prevent hydration mismatches when using SSR.\n */\n id?: string;\n /** Enable menu custom content vs MenuItem children */\n isCustomContent?: boolean;\n /** initial menu placement */\n menuPlacement?: Placement;\n /** custom menu width */\n menuSize?: 'sm' | 'md' | 'lg' | 'xl';\n /** number of grid columns required for children */\n numberOfColumns: 1 | 2 | 3;\n /** callback that triggers when the menu is closed */\n onMenuClose?: () => void;\n /** callback that triggers when the menu is opened */\n onMenuOpen?: () => void;\n /** when true, menu will open on hover */\n openOnHover?: boolean;\n /** trigger component to open menu */\n trigger: ReactNode;\n /** additional CSS class name for the trigger */\n triggerClassName?: string;\n};\n\nconst MenuComponent = forwardRef<HTMLSpanElement, MenuProps & HTMLProps<HTMLSpanElement>>(\n (\n {\n children,\n className,\n defaultOpen,\n hasRoundedBorders = false,\n id,\n isCustomContent,\n menuPlacement,\n menuSize = 'lg',\n numberOfColumns,\n onMenuClose,\n onMenuOpen,\n openOnHover = false,\n trigger,\n triggerClassName,\n ...props\n },\n forwardedRef\n ) => {\n const [isOpen, setIsOpen] = useState(defaultOpen ?? false);\n const [activeIndex, setActiveIndex] = useState<number | null>(null);\n const elementsRef = useRef<Array<HTMLSpanElement | null>>([]);\n const labelsRef = useRef<Array<string | null>>([]);\n const parent = useMenuContext();\n const hasMounted = useHasMounted();\n\n const tree = useFloatingTree();\n const nodeId = useFloatingNodeId(id);\n const parentId = useFloatingParentNodeId();\n const item = useListItem();\n\n const isNested = parentId !== null;\n\n const arrowRef = useRef(null);\n\n const { context, floatingStyles, refs } = useFloating<HTMLButtonElement>({\n middleware: [\n offset({ alignmentAxis: -2, mainAxis: isNested ? 2 : 8 }),\n flip(),\n shift({ padding: !isNested ? 2 : 0 }),\n arrow({ element: arrowRef, padding: 5 }),\n ],\n nodeId,\n onOpenChange: (open) => {\n setIsOpen(open);\n if (!open) {\n onMenuClose?.();\n } else {\n onMenuOpen?.();\n }\n },\n open: isOpen,\n placement: isNested ? 'right-start' : (menuPlacement ?? 'bottom'),\n whileElementsMounted: autoUpdate,\n });\n const hover = useHover(context, {\n delay: { open: 75 },\n enabled: isNested || openOnHover,\n handleClose: safePolygon({ blockPointerEvents: true }),\n });\n const click = useClick(context, {\n enabled: !context.dataRef.current.openEvent?.defaultPrevented && !openOnHover,\n event: 'click',\n ignoreMouse: isNested,\n toggle: !isNested,\n });\n\n const role = useRole(context, { role: 'menu' });\n const dismiss = useDismiss(context, { bubbles: true });\n const listNavigation = useListNavigation(context, {\n activeIndex,\n focusItemOnOpen: false,\n listRef: elementsRef,\n nested: isNested,\n onNavigate: setActiveIndex,\n });\n const typeahead = useTypeahead(context, {\n activeIndex,\n enabled: !isCustomContent,\n listRef: labelsRef,\n onMatch: isOpen ? setActiveIndex : undefined,\n });\n\n const { getFloatingProps, getItemProps, getReferenceProps } = useInteractions([\n hover,\n click,\n role,\n dismiss,\n listNavigation,\n typeahead,\n ]);\n\n // Event emitter allows you to communicate across tree components.\n // This effect closes all menus when an item gets clicked anywhere\n // in the tree.\n useEffect(() => {\n if (!tree) {\n return;\n }\n\n function handleTreeClick() {\n setIsOpen(false);\n onMenuClose?.();\n }\n\n function onSubMenuOpen(event: { nodeId: string; parentId: string }) {\n if (event.nodeId !== nodeId && event.parentId === parentId) {\n setIsOpen(false);\n onMenuClose?.();\n }\n }\n\n tree.events.on('click', handleTreeClick);\n tree.events.on('menuopen', onSubMenuOpen);\n\n return () => {\n tree.events.off('click', handleTreeClick);\n tree.events.off('menuopen', onSubMenuOpen);\n };\n }, [tree, nodeId, parentId, onMenuClose]);\n\n useEffect(() => {\n if (isOpen && tree) {\n tree.events.emit('menuopen', { nodeId, parentId });\n }\n }, [tree, isOpen, nodeId, parentId]);\n\n // Strip the three ARIA attrs from the floating-ui reference props so the wrapper span keeps\n // every behavior it had before (refs, click/keyboard handlers, positioning), but no longer\n // carries ARIA that its implicit `generic` role disallows (the axe `aria-allowed-attr`\n // violation). The three ARIA attrs are reapplied to the trigger child via `cloneElement`,\n // landing on a node whose role natively permits them (button / link / menuitem).\n const {\n 'aria-controls': ariaControls,\n 'aria-expanded': ariaExpanded,\n 'aria-haspopup': ariaHasPopup,\n ...referencePropsWithoutAria\n } = getReferenceProps(\n parent.getItemProps({\n ...props,\n onClick(event: MouseEvent<HTMLButtonElement>) {\n event.stopPropagation();\n props.onClick?.(event);\n },\n onFocus(event: FocusEvent<HTMLButtonElement>) {\n props.onFocus?.(event);\n },\n })\n ) as Record<string, unknown>;\n\n const triggerIsElement = isValidElement(trigger);\n const triggerElement = trigger as ReactElement;\n const ariaPropsForTrigger: Record<string, unknown> = {};\n if (ariaHasPopup !== undefined) {\n ariaPropsForTrigger['aria-haspopup'] = ariaHasPopup;\n }\n if (ariaExpanded !== undefined) {\n ariaPropsForTrigger['aria-expanded'] = ariaExpanded;\n }\n if (ariaControls !== undefined) {\n ariaPropsForTrigger['aria-controls'] = ariaControls;\n }\n\n // For element triggers, clone the ARIA onto the child (preferred — lands on a node whose role\n // natively permits these attrs). Note: this intentionally overrides any same-named ARIA the\n // caller already set on the trigger; menu disclosure semantics (`aria-haspopup=\"menu\"`) must\n // win for the popup to be announced correctly.\n const clonedTrigger = triggerIsElement ? cloneElement(triggerElement, ariaPropsForTrigger) : trigger;\n\n // For non-element triggers (string / number / null), we cannot clone ARIA anywhere meaningful,\n // so the wrapper span itself becomes the disclosure control. Adding `role=\"button\"` +\n // `tabIndex={0}` makes the ARIA attrs valid (no `aria-allowed-attr` violation) and preserves\n // the screen-reader disclosure pattern. Safe because non-element triggers don't contain a\n // nested interactive element (no `nested-interactive` violation).\n const wrapperFallbackProps = !triggerIsElement ? { ...ariaPropsForTrigger, role: 'button' as const } : {};\n\n return (\n <FloatingNode id={nodeId}>\n <span\n className={cn(\n {\n 'w-full': isNested,\n },\n 'm-0 inline-flex cursor-pointer appearance-none items-center border-none bg-none p-0 text-left no-underline outline-0 hover:no-underline',\n triggerClassName\n )}\n data-testid=\"menu-trigger-wrapper\"\n ref={useMergeRefs([refs.setReference, item.ref, forwardedRef])}\n tabIndex={\n !triggerIsElement ? 0 : !isNested ? undefined : parent.activeIndex === item.index ? 0 : -1\n }\n {...wrapperFallbackProps}\n {...referencePropsWithoutAria}\n >\n {clonedTrigger}\n </span>\n <MenuContext.Provider\n value={{\n activeIndex,\n getItemProps,\n isOpen,\n numberOfColumns,\n setActiveIndex,\n }}\n >\n <FloatingList\n elementsRef={elementsRef}\n labelsRef={labelsRef}\n >\n {isOpen && hasMounted && Boolean(refs.domReference) && (\n <FloatingPortal root={refs.domReference}>\n <FloatingFocusManager\n context={context}\n initialFocus={-1}\n modal={false}\n returnFocus={!isNested}\n >\n <div\n className={cn(\n 'Menu relative z-50 w-min cursor-default bg-background-primary py-2 shadow-03 outline-0',\n {\n 'min-w-[200px]': menuSize === 'sm',\n 'min-w-[250px]': menuSize === 'md',\n 'min-w-[300px]': menuSize === 'lg',\n 'min-w-[350px]': menuSize === 'xl',\n 'rounded-md': hasRoundedBorders,\n },\n className\n )}\n data-testid=\"menu-wrapper\"\n ref={refs.setFloating}\n style={floatingStyles}\n {...getFloatingProps()}\n >\n {!isNested && (\n <FloatingArrow\n className=\"fill-background-primary\"\n context={context}\n ref={arrowRef}\n tipRadius={hasRoundedBorders ? 2 : 0}\n />\n )}\n {children}\n </div>\n </FloatingFocusManager>\n </FloatingPortal>\n )}\n </FloatingList>\n </MenuContext.Provider>\n </FloatingNode>\n );\n }\n);\n\nMenuComponent.displayName = 'MenuComponent';\n\nexport const Menu = forwardRef<HTMLSpanElement, MenuProps & HTMLProps<HTMLSpanElement>>((props, ref) => {\n const parentId = useFloatingParentNodeId();\n\n if (parentId === null) {\n return (\n <FloatingTree>\n <MenuComponent\n {...props}\n ref={ref}\n />\n </FloatingTree>\n );\n }\n\n return (\n <MenuComponent\n {...props}\n ref={ref}\n />\n );\n});\n\nMenu.displayName = 'Menu';\n"],"mappings":"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"}
|
package/Modal-CiBqXyiK.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Modal-CiBqXyiK.cjs","names":["useCloseModal","ModalContext","effectEventListener","useWindowIsMobile","ModalContext","usePrevious","useCloseModal","BackButton","CloseButton","ModalHeader","ModalTitle","ModalContent","ModalSubTitle","ModalActions"],"sources":["../src/Modal/components/Backdrop/Backdrop.tsx","../src/Modal/components/PreventModalScroll/PreventModalScroll.tsx","../src/Modal/ComposableModal.tsx","../src/Modal/Modal.tsx"],"sourcesContent":["import { cn } from '@evolve.ui/theme-system';\nimport { useAtom } from 'jotai';\nimport { ReactNode, useContext, useEffect, useRef } from 'react';\n\nimport { effectEventListener } from '../../../utils/effectEventListener';\nimport { ModalContext } from '../../context';\nimport { useCloseModal } from '../../hooks/useCloseModal';\n\ntype Props = {\n children?: ReactNode;\n closeModalOnBackdropClick?: boolean;\n show: boolean;\n};\n\nexport const Backdrop = ({ children, closeModalOnBackdropClick, show }: Props) => {\n const closeModal = useCloseModal('backdrop');\n const { modalAnimationAtom } = useContext(ModalContext);\n const backdropRef = useRef<HTMLDivElement>(null);\n const [modalAnimation, setModalAnimation] = useAtom(modalAnimationAtom);\n\n // NEEDS A DELAY TO ALLOW THE MODAL TO ANIMATE IN\n useEffect(() => {\n if (show && modalAnimation === '') {\n setModalAnimation('opening');\n }\n }, [modalAnimation, setModalAnimation, show]);\n\n useEffect(() => {\n if (!closeModalOnBackdropClick) {\n return;\n }\n\n return effectEventListener(window, 'mousedown', (event: Event) => {\n if (event.target === backdropRef.current) {\n closeModal();\n }\n });\n }, [closeModal, closeModalOnBackdropClick]);\n\n return (\n <div\n className={cn(\n // GENERAL CLOSED\n 'hui-modal-backdrop opacity-0',\n // OPEN\n {\n 'fixed bottom-0 left-0 right-0 top-0 z-[1001] flex items-center justify-center bg-background-overlay':\n show,\n },\n // GENERAL ANIMATION\n 'transition-opacity duration-200 ease-in',\n // OPEN ANIMATION\n { 'opacity-100': modalAnimation === 'opening' },\n // CLOSE ANIMATION\n { 'opacity-0': modalAnimation === 'closing' }\n )}\n ref={backdropRef}\n >\n {children}\n </div>\n );\n};\n","import { useEffect } from 'react';\n\n// Open modals share a single body scroll-lock. Module-scoped and ref-counted\n// (local deviation from hammer — mirrors Drawer's lock): hammer's per-instance\n// save/restore leaves the body locked forever when two instances overlap\n// (docs pages embedding multiple open modals, auto-reopening stories), because\n// the later instance saves the earlier one's `overflow: hidden` as \"original\".\n// The first instance to mount captures the body's real styles + scroll\n// position; the last to unmount restores them.\nlet openLockCount = 0;\nlet previousBodyStyles: {\n overflow: string;\n paddingRight: string;\n position: string;\n top: string;\n width: string;\n} | null = null;\nlet savedScrollPosition = 0;\nlet iosTouchCleanup: (() => void) | undefined;\n\n/**\n * Prevents scrolling of the page while the modal is open.\n * Uses a unified approach with additional touch event handling for iOS Safari.\n *\n * Can be disabled with `preventScrollWhileOpen={false}` on the `Modal`.\n */\nexport const PreventModalScroll = () => {\n useEffect(() => {\n const body = document.body;\n\n if (openLockCount === 0) {\n const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent);\n\n // Store current scroll position and original styles\n savedScrollPosition = window.pageYOffset || document.documentElement.scrollTop;\n previousBodyStyles = {\n overflow: body.style.overflow,\n paddingRight: body.style.paddingRight,\n position: body.style.position,\n top: body.style.top,\n width: body.style.width,\n };\n\n // Calculate scrollbar width and add padding to prevent content shift\n const scrollBarWidth = window.innerWidth - document.documentElement.clientWidth;\n if (scrollBarWidth > 0) {\n body.style.paddingRight = `${scrollBarWidth}px`;\n }\n\n // Apply scroll prevention\n body.style.overflow = 'hidden';\n body.style.position = 'fixed';\n body.style.top = `-${savedScrollPosition}px`;\n body.style.width = '100%';\n\n // iOS-specific touch event handling\n if (isIOS) {\n const preventDefault = (e: TouchEvent) => {\n // Allow touch events on modal content but prevent on backdrop\n const target = e.target as Element;\n const isModalContent =\n target.closest('[data-testid=\"modal-content\"]') || target.closest('.hui-modal-container');\n\n if (!isModalContent) {\n e.preventDefault();\n }\n };\n\n // Add touch event listeners for iOS\n document.addEventListener('touchstart', preventDefault, { passive: false });\n document.addEventListener('touchmove', preventDefault, { passive: false });\n\n iosTouchCleanup = () => {\n document.removeEventListener('touchstart', preventDefault);\n document.removeEventListener('touchmove', preventDefault);\n };\n }\n }\n\n openLockCount += 1;\n\n // Cleanup function\n return () => {\n openLockCount -= 1;\n\n if (openLockCount === 0) {\n // Remove iOS touch event listeners if they exist\n iosTouchCleanup?.();\n iosTouchCleanup = undefined;\n\n // Restore original styles\n body.style.overflow = previousBodyStyles?.overflow ?? '';\n body.style.position = previousBodyStyles?.position ?? '';\n body.style.top = previousBodyStyles?.top ?? '';\n body.style.width = previousBodyStyles?.width ?? '';\n body.style.paddingRight = previousBodyStyles?.paddingRight ?? '';\n previousBodyStyles = null;\n\n // Restore scroll position\n window.scrollTo(0, savedScrollPosition);\n }\n };\n }, []);\n\n return null;\n};\n","import { cn } from '@evolve.ui/theme-system';\nimport { useAtom, useAtomValue } from 'jotai';\nimport { atomWithReset } from 'jotai/utils';\nimport { ReactNode, useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\n\nimport { usePrevious } from '../hooks/usePrevious';\nimport { useWindowIsMobile } from '../providers';\nimport { Backdrop } from './components/Backdrop/Backdrop';\nimport { PreventModalScroll } from './components/PreventModalScroll/PreventModalScroll';\nimport { ModalContext } from './context';\nimport { useCloseModal } from './hooks/useCloseModal';\n\ntype Props = {\n /**\n * Content of the modal.\n *\n * Generally, the structure for a modal is:\n * ```tsx\n * <Modal>\n * <ModalHeader>\n * <BackButton />\n * <CloseButton />\n * <ModalTitle>Modal Title</ModalTitle>\n * </ModalHeader>\n * <ModalContent>\n * <ModalSubTitle>Modal Subtitle</ModalSubTitle>\n * Content, whatever the main body of the modal is.\n * </ModalContent>\n * <ModalActions>Actions (usually buttons) go here</ModalActions>\n * </Modal>\n * ```\n */\n children: ReactNode;\n className?: string;\n /**\n * If true, the modal will close when the backdrop is clicked.\n */\n closeModalOnBackdropClick?: boolean;\n /**\n * Optional data-testid for the dialog element\n */\n 'data-testid'?: string;\n /**\n * This is a callback that is called when the modal is trying to close itself.\n *\n * It should look something like\n * ```tsx\n * handleClose={() => setShow(false)}\n * ```\n *\n * It optionally recieves a data object that is passed to the `useCloseModal` function.\n * For the close button, this is by default `\"closed\"`.\n * For the backdrop, this is by default `\"backdrop\"`\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- hammer-parity: handleCloseData is an arbitrary consumer-defined payload forwarded verbatim\n handleClose: (handleCloseData?: any) => void;\n /**\n * If true, the modal will have a content pager.\n * This is needed to prevent the modal from scaling upon opening.\n */\n hasContentPager?: boolean;\n /**\n * Needed for the progress steps to be shown with the correct animation.\n */\n hasProgressSteps?: boolean;\n /**\n * If true, the modal will be full screen on mobile.\n */\n mobileFullScreen?: boolean;\n /**\n * This is a callback that is called when the modal close animation ends.\n */\n onModalCloseAnimationEnd?: () => void;\n /**\n * This is the position of the modal.\n * It can be either `'center'` or `'top'`.\n */\n position?: 'center' | 'top';\n /**\n * Prevents scrolling of the page while the modal is open.\n *\n * @default true\n */\n preventScrollWhileOpen?: boolean;\n /**\n * The `show` prop is used to control the visibility of the modal. Should be set to false by `handleClose`.\n */\n show: boolean;\n};\n\n/**\n * The actual modal logic. This is the \"composable\" version of the modal.\n */\nexport const ComposableModal = ({\n children,\n className,\n closeModalOnBackdropClick = true,\n 'data-testid': dataTestId,\n handleClose: handleCloseProp,\n hasContentPager = false,\n hasProgressSteps = false,\n mobileFullScreen = false,\n onModalCloseAnimationEnd,\n position = 'center',\n preventScrollWhileOpen = true,\n show: showProp,\n}: Props) => {\n const [modalTarget, setModalTarget] = useState<HTMLElement | null>(null);\n const [show, setShow] = useState(showProp);\n const isMobile = useWindowIsMobile();\n\n const modalAtoms = useMemo(\n () => ({\n closeModalOnBackdropClickAtom: atomWithReset(true),\n isMobileKeyboardOpen: atomWithReset<boolean>(false),\n modalAnimationAtom: atomWithReset<'opening' | 'closing' | ''>(''),\n modalFullScreenAtom: atomWithReset<boolean>(mobileFullScreen),\n modalHasFooterAtom: atomWithReset<boolean>(false),\n modalHasProgressStepsAtom: atomWithReset<boolean>(hasProgressSteps),\n modalRefAtom: atomWithReset<{ current: HTMLDialogElement | null }>({ current: null }),\n scrollTopAtom: atomWithReset(0),\n showBottomScrollHintAtom: atomWithReset<boolean>(false),\n showTopScrollHintAtom: atomWithReset<boolean>(false),\n }),\n [hasProgressSteps, mobileFullScreen]\n );\n\n const modalAnimation = useAtomValue(modalAtoms.modalAnimationAtom);\n const [isMobileKeyboardOpen, setIsMobileKeyboardOpen] = useAtom(modalAtoms.isMobileKeyboardOpen);\n\n const handleClose = useCallback(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- hammer-parity: handleCloseData is an arbitrary consumer-defined payload forwarded verbatim\n (handleCloseData?: any) => {\n setShow(false); // Must be triggered before the handleCloseProp\n\n handleCloseProp(handleCloseData);\n },\n [handleCloseProp]\n );\n\n useEffect(() => {\n const target = document.querySelector('.hui-modal-target');\n\n if (!target) {\n throw new Error('Modal target not found, add one in the DOM tree.');\n }\n\n setModalTarget(target as HTMLElement);\n }, []);\n\n const ref = useRef<HTMLDialogElement | null>(null);\n\n const [viewportHeight, setViewportHeight] = useState({ current: 0, initial: 0 });\n\n const updateViewport = useCallback(() => {\n if (typeof window === 'undefined' || typeof window.visualViewport === 'undefined') {\n return;\n }\n\n const currentViewportHeight = window.visualViewport?.height ?? 0;\n\n // Get initial viewport height\n if (viewportHeight.initial === 0) {\n setViewportHeight({\n current: currentViewportHeight,\n initial: window.visualViewport?.height ?? 0,\n });\n } else {\n // Get the difference between the current viewport height and the initial viewport height\n // This is to check if mobile keyboard is open\n const isLessThanInitial = Boolean(currentViewportHeight < viewportHeight.initial);\n setIsMobileKeyboardOpen(isLessThanInitial);\n setViewportHeight((prev) => ({\n current: currentViewportHeight,\n initial: prev.initial,\n }));\n }\n }, [setIsMobileKeyboardOpen, viewportHeight.initial]);\n\n useEffect(() => {\n if (typeof window !== 'undefined' && typeof window.visualViewport !== 'undefined' && isMobile) {\n updateViewport();\n\n window.visualViewport?.addEventListener('resize', updateViewport);\n\n return () => window.visualViewport?.removeEventListener('resize', updateViewport);\n }\n\n return undefined;\n }, [isMobile, updateViewport]);\n\n if (!modalTarget || !show) {\n return (\n <ModalContext.Provider value={{ handleClose, onModalCloseAnimationEnd, ...modalAtoms }}>\n <HandleShowProp\n setShow={setShow}\n show={show}\n showProp={showProp}\n />\n </ModalContext.Provider>\n );\n }\n\n const modal = createPortal(\n <Backdrop\n closeModalOnBackdropClick={closeModalOnBackdropClick}\n show={show}\n >\n <dialog\n aria-label=\"Modal\"\n className={cn(\n // GENERAL CLOSED\n 'hui-modal-container group relative flex',\n // OPEN\n 'max-h-[calc(100vh-64px)] w-[588px] flex-col overflow-hidden rounded-md border-none bg-background-primary p-0',\n // MOBILE\n 'xsMax:w-[375px]',\n // SMALL MOBILE\n 'mobileSmall:!w-full',\n // POSITION\n { 'absolute top-lg': position === 'top' },\n // GENERAL ANIMATION\n 'transition-opacity duration-100 ease-in',\n // OPEN ANIMATION\n {\n 'animate-fadeIn': modalAnimation === 'opening' && hasContentPager,\n 'animate-fadeInScaled': modalAnimation === 'opening' && !hasContentPager,\n },\n // CLOSE ANIMATION\n { 'animate-fadeOut': modalAnimation === 'closing' },\n // FULL SCREEN\n {\n 'group/fullscreen mobile:top-0 mobile:flex mobile:h-full mobile:max-h-full mobile:w-screen mobile:min-w-[100vw] mobile:rounded-none':\n mobileFullScreen,\n },\n className\n )}\n data-hui-id=\"Modal\"\n data-testid={dataTestId}\n onAnimationEnd={() => {\n if (modalAnimation === 'closing') {\n onModalCloseAnimationEnd?.();\n }\n }}\n open={show}\n ref={ref}\n >\n {preventScrollWhileOpen && <PreventModalScroll />}\n {children}\n <div\n className={cn('relative', {\n // Use CSS :has() selector to immediately apply min-height when footer exists\n // Apply 148px on desktop, 74px on mobile fullscreen\n 'mobile:group-only/fullscreen:has-[#modal-footer.flex]:min-h-[74px] smMin:has-[#modal-footer.flex]:min-h-[148px]':\n hasContentPager,\n // Hide the actions portal when the mobile keyboard is open\n 'mobile:group-only/fullscreen:hidden': isMobileKeyboardOpen && hasContentPager,\n })}\n id=\"modal-actions-portal\"\n />\n </dialog>\n </Backdrop>,\n modalTarget\n );\n\n return (\n <ModalContext.Provider value={{ handleClose, onModalCloseAnimationEnd, ...modalAtoms }}>\n <HandleShowProp\n setShow={setShow}\n show={show}\n showProp={showProp}\n />\n {modal}\n </ModalContext.Provider>\n );\n};\n\nconst HandleShowProp = ({\n setShow,\n show,\n showProp,\n}: {\n setShow: (value: boolean) => void;\n show: boolean;\n showProp: boolean;\n}) => {\n const previousShowProp = usePrevious(showProp);\n const closeModal = useCloseModal('setShow set to false');\n\n useEffect(() => {\n if (previousShowProp === undefined) {\n return;\n }\n\n const propChanged = showProp !== previousShowProp;\n if (!propChanged) {\n return;\n }\n\n const showMustChange = show !== showProp;\n if (!showMustChange) {\n return;\n }\n if (showProp) {\n setShow(true);\n } else {\n closeModal();\n }\n }, [show, previousShowProp, showProp, closeModal, setShow]);\n\n return null;\n};\n","import { ComponentProps, ReactNode } from 'react';\n\nimport {\n BackButton,\n CloseButton,\n ModalActions,\n ModalContent,\n ModalHeader,\n ModalSubTitle,\n ModalTitle,\n} from './components';\nimport { ComposableModal } from './ComposableModal';\n\ntype TemplatedModalProps = {\n /**\n * This is the actions of the modal. Usually buttons.\n * It is rendered at the bottom of the modal.\n *\n * `ModalActions` is not rendered if this is not passed.\n */\n actions?: ReactNode;\n /**\n * This is the main content of the modal.\n */\n body?: ReactNode;\n /**\n * If you want to pass children, set `type=\"composable\"`.\n */\n children?: never;\n /**\n * If true, the close button will not be shown.\n */\n hideClose?: boolean;\n /**\n * This is a callback that is called when the back button is clicked.\n *\n * When passed, the back button will be shown.\n */\n onBackClicked?: () => void;\n /**\n * If passed, this will be shown as a subtitle in the modal.\n */\n subtitle?: ReactNode;\n /**\n * If passed, this will be shown as a title in the modal.\n *\n * `ModalHeader` is not rendered if this is not passed.\n */\n title?: ReactNode;\n /**\n * Marks the type of modal as templated / simple.\n */\n type?: 'templated';\n};\n\ntype ComposableModalProps = {\n /**\n * Content of the modal.\n *\n * Generally, the structure for a modal is:\n * ```tsx\n * <Modal>\n * <ModalHeader>\n * <BackButton />\n * <CloseButton />\n * <ModalTitle>Modal Title</ModalTitle>\n * </ModalHeader>\n * <ModalContent>\n * <ModalSubTitle>Modal Subtitle</ModalSubTitle>\n * Content, whatever the main body of the modal is.\n * </ModalContent>\n * <ModalActions>Actions (usually buttons) go here</ModalActions>\n * </Modal>\n * ```\n */\n children: ReactNode;\n /**\n * Marks the type of modal as composable.\n */\n type: 'composable';\n};\n\ntype Props = {\n className?: string;\n /**\n * If true, the modal will close when the backdrop is clicked.\n */\n closeModalOnBackdropClick?: ComponentProps<typeof ComposableModal>['closeModalOnBackdropClick'];\n /**\n * Optional data-testid for the dialog element\n */\n 'data-testid'?: string;\n /**\n * This is a callback that is called when the modal is trying to close itself.\n *\n * It should look something like\n * ```tsx\n * handleClose={() => setShow(false)}\n * ```\n *\n * It optionally recieves a data object that is passed to the `useCloseModal` function.\n * For the close button, this is by default `\"closed\"`.\n * For the backdrop, this is by default `\"backdrop\"`\n */\n handleClose: ComponentProps<typeof ComposableModal>['handleClose'];\n /**\n * If true, the modal will have a content pager.\n * This is needed to prevent the modal from scaling upon opening.\n */\n hasContentPager?: boolean;\n /**\n * Needed for the progress steps to be shown with the correct animation.\n */\n hasProgressSteps?: boolean;\n /**\n * If true, the modal will be full screen on mobile.\n */\n mobileFullScreen?: boolean;\n /**\n * This is a callback that is called when the modal close animation ends.\n */\n onModalCloseAnimationEnd?: ComponentProps<typeof ComposableModal>['onModalCloseAnimationEnd'];\n /**\n * This is the position of the modal.\n * It can be either `'center'` or `'top'`.\n */\n position?: ComponentProps<typeof ComposableModal>['position'];\n /**\n * Prevents scrolling of the page while the modal is open.\n *\n * @default true\n */\n preventScrollWhileOpen?: ComponentProps<typeof ComposableModal>['preventScrollWhileOpen'];\n /**\n * The `show` prop is used to control the visibility of the modal. Should be set to false by `handleClose`.\n */\n show: ComponentProps<typeof ComposableModal>['show'];\n} & (TemplatedModalProps | ComposableModalProps);\n\n/**\n * Primary component for creating modals.\n * When rendered, it automatically opens the modal and backdrop.\n *\n * These preprovided components give you the styles of the modal.\n *\n * By default, you get a particular preset of the `Modal` component that is used for simple modals.\n * It has (optionally) a title, subtitle, body, and actions.\n *\n * If you need to get a little bit more custom, be sure to read the docs and add `type=\"composable\"` to the this component.\n *\n * Generally, the structure for a modal is:\n * ```tsx\n * <Modal>\n * <ModalHeader>\n * <BackButton />\n * <CloseButton />\n * <ModalTitle>Modal Title</ModalTitle>\n * </ModalHeader>\n * <ModalContent>\n * <ModalSubTitle>Modal Subtitle</ModalSubTitle>\n * Content, whatever the main body of the modal is.\n * </ModalContent>\n * <ModalActions>Actions (usually buttons) go here</ModalActions>\n * </Modal>\n * ```\n */\nexport const Modal = ({\n className,\n closeModalOnBackdropClick,\n 'data-testid': dataTestId,\n handleClose,\n hasContentPager,\n hasProgressSteps,\n mobileFullScreen,\n onModalCloseAnimationEnd,\n position,\n preventScrollWhileOpen,\n show,\n ...rest\n}: Props) => {\n if (rest.type === 'composable') {\n return (\n <ComposableModal\n className={className}\n closeModalOnBackdropClick={closeModalOnBackdropClick}\n data-testid={dataTestId}\n handleClose={handleClose}\n hasContentPager={hasContentPager}\n hasProgressSteps={hasProgressSteps}\n mobileFullScreen={mobileFullScreen}\n onModalCloseAnimationEnd={onModalCloseAnimationEnd}\n position={position}\n preventScrollWhileOpen={preventScrollWhileOpen}\n show={show}\n >\n {rest.children}\n </ComposableModal>\n );\n }\n\n const { actions, body, hideClose, onBackClicked, subtitle, title } = rest;\n\n return (\n <ComposableModal\n className={className}\n closeModalOnBackdropClick={closeModalOnBackdropClick}\n data-testid={dataTestId}\n handleClose={handleClose}\n hasContentPager={hasContentPager}\n hasProgressSteps={hasProgressSteps}\n mobileFullScreen={mobileFullScreen}\n onModalCloseAnimationEnd={onModalCloseAnimationEnd}\n position={position}\n preventScrollWhileOpen={preventScrollWhileOpen}\n show={show}\n >\n {onBackClicked && <BackButton onClick={onBackClicked} />}\n {!hideClose && <CloseButton />}\n {Boolean(title) && (\n <ModalHeader>\n <ModalTitle>{title}</ModalTitle>\n </ModalHeader>\n )}\n <ModalContent>\n {Boolean(subtitle) && <ModalSubTitle>{subtitle}</ModalSubTitle>}\n {Boolean(body) && body}\n </ModalContent>\n {Boolean(actions) && <ModalActions>{actions}</ModalActions>}\n </ComposableModal>\n );\n};\n"],"mappings":"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"}
|
package/Select-BXDjzyDs.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Select-BXDjzyDs.cjs","names":["selectBuiltins","BodyPrimary","CaretDown","Check","ReactSelect","extractFormLabelProps","FormLabel"],"sources":["../src/Select/selectComponents.tsx","../src/Select/Select.tsx"],"sourcesContent":["import { cn } from '@evolve.ui/theme-system';\nimport { ComponentProps, ReactNode } from 'react';\nimport { components as selectBuiltins } from 'react-select';\n\nimport { CaretDown, Check } from '../Icons';\nimport { BodyPrimary } from '../Typography/Text/Text';\n\nexport const InsideLabelControl = ({\n children,\n ...props\n}: ComponentProps<typeof selectBuiltins.Control> & {\n selectProps: {\n hasError?: boolean;\n isInsideLabel?: boolean;\n labelText?: ReactNode;\n small?: boolean;\n };\n}) => {\n const { hasError, isInsideLabel, labelText, small } = props.selectProps;\n return (\n <selectBuiltins.Control\n {...props}\n className={cn(\n // GENERAL\n '!m-0 !min-h-[42px] !flex-nowrap !rounded-input !border !border-solid !border-border-secondary !bg-background-primary !p-0 ![box-shadow:none]',\n // HOVER\n {\n 'hover:!border-border-hover': !props.menuIsOpen,\n 'hover:!border-border-selected': props.menuIsOpen,\n },\n {\n '!border-border-critical': props.selectProps['aria-invalid'] === 'true',\n '!border-border-selected': props.menuIsOpen || props.isFocused,\n '!min-h-[34px]': small,\n },\n // ERROR\n {\n '!border-border-critical': hasError && !props.menuIsOpen && !props.isDisabled,\n }\n )}\n >\n {isInsideLabel && Boolean(labelText) && (\n <BodyPrimary\n className=\"ml-xs mr--2xs\"\n color=\"secondary\"\n >\n {labelText}\n </BodyPrimary>\n )}\n {children}\n </selectBuiltins.Control>\n );\n};\n\n/**\n * Add custom icon for dropdown indicator\n * @see https://react-select.com/components#components\n */\nexport const DropdownIndicator = (props: ComponentProps<typeof selectBuiltins.DropdownIndicator>) => {\n return (\n <selectBuiltins.DropdownIndicator\n {...props}\n className=\"flex h-full w-full items-center justify-center !py-0 px-xs\"\n >\n <CaretDown\n aria-label={props.selectProps.menuIsOpen ? 'Caret Up' : 'Caret Down'}\n className={cn({\n 'rotate-180': props.selectProps.menuIsOpen,\n })}\n color={props.selectProps.isDisabled ? 'disabled' : 'primary'}\n size=\"sm\"\n />\n </selectBuiltins.DropdownIndicator>\n );\n};\n\n/**\n * Add data-testid prop to the select component container\n * @see https://react-select.com/components#components\n */\nexport const SelectContainer = ({ className, ...props }: ComponentProps<typeof selectBuiltins.SelectContainer>) => (\n <selectBuiltins.SelectContainer\n {...props}\n className={cn(className, 'hui-text-body-primary !rounded-input text-text-primary ![box-shadow:none]')}\n innerProps={{\n ...props.innerProps,\n // @ts-expect-error all attributes are passed and we have the custom \"data-testid\", so this is ok.\n ...(Boolean(props.selectProps['data-testid']) && {\n // @ts-expect-error all attributes are passed and we have the custom \"data-testid\", so this is ok.\n 'data-testid': props.selectProps['data-testid'],\n }),\n }}\n />\n);\n\nexport const NoOptionsMessage = (props: ComponentProps<typeof selectBuiltins.NoOptionsMessage>) => (\n <selectBuiltins.NoOptionsMessage\n {...props}\n className=\"p-0\"\n >\n <BodyPrimary\n className=\"normal-case\"\n color=\"secondary\"\n >\n No results\n </BodyPrimary>\n </selectBuiltins.NoOptionsMessage>\n);\n\nexport const Input = (props: ComponentProps<typeof selectBuiltins.Input>) => (\n <selectBuiltins.Input\n {...props}\n aria-activedescendant={props['aria-activedescendant'] || undefined}\n // @ts-expect-error prop type does exist on parent, just not here.\n autoComplete={props.selectProps.autoComplete}\n className=\"!m-0 !p-0\"\n />\n);\n\nexport const Option = ({\n children,\n isDisabled,\n isFocused,\n isSelected,\n ...rest\n}: ComponentProps<typeof selectBuiltins.Option>) => {\n const isSelectedAndDisabled = isSelected && isDisabled;\n\n return (\n <selectBuiltins.Option\n {...rest}\n className={cn(\n // BASE\n 'hui-text-body-primary !px-[8px] !py-[4px] text-[16px] text-text-primary',\n // HOVER\n 'hover:cursor-pointer hover:bg-background-hover',\n // SELECTED\n {\n '!bg-background-hover': !isDisabled && isFocused,\n '!bg-background-inverse !text-text-inverse hover:!bg-background-inverse': !isDisabled && isSelected,\n '!bg-background-primary': isDisabled && isFocused && !isSelected,\n // Selected AND disabled - show as selected but with disabled text color\n '!cursor-not-allowed !bg-background-inverse !text-text-disabled hover:!bg-background-inverse':\n isSelectedAndDisabled,\n '!cursor-not-allowed !text-text-disabled hover:!bg-background-primary focus:!bg-background-primary':\n isDisabled && !isSelected,\n }\n )}\n innerProps={{\n ...rest.innerProps,\n // @ts-expect-error all attributes are passed and we have the custom \"data-testid\", so this is ok.\n ...(Boolean(rest.selectProps['data-testid']) && {\n // @ts-expect-error all attributes are passed and we have the custom \"data-testid\", so this is ok.\n 'data-testid': rest.selectProps['data-testid'],\n }),\n }}\n isDisabled={Boolean(isDisabled)}\n isFocused={isFocused}\n isSelected={isSelected}\n >\n <div\n // adds data-testid attribute to dropdown option\n {...(rest.data && typeof rest.data === 'object' && 'data-testid' in rest.data\n ? { 'data-testid': rest.data['data-testid'] }\n : {})}\n className={cn('flex h-full w-full items-center', {\n 'bg-background-inverse text-text-disabled': isSelectedAndDisabled,\n 'bg-background-inverse text-text-inverse': isSelected && !isDisabled,\n 'pl-sm': !isSelected,\n })}\n >\n {isSelected && (\n <Check\n className=\"mr-[2px]\"\n color={isDisabled ? 'disabled' : 'inverse'}\n size=\"xs\"\n />\n )}\n {children}\n </div>\n </selectBuiltins.Option>\n );\n};\n\nexport const ClearIndicator = (props: ComponentProps<typeof selectBuiltins.ClearIndicator>) => (\n <selectBuiltins.ClearIndicator\n {...props}\n className=\"!py-0\"\n >\n {props.children}\n </selectBuiltins.ClearIndicator>\n);\n\n/**\n * Reads the scroll offset that `PreventModalScroll` parks on `document.body.style.top`.\n *\n * When a modal is open, `PreventModalScroll` sets `body.style.top = \"-${scrollPosition}px\"`\n * and `body.style.position = \"fixed\"`. React-select uses `window.pageYOffset` for the\n * portal offset, but that returns 0 when the body is fixed, so we read the stored scroll\n * position directly from `body.style.top` to compensate. Zoom-agnostic because it's a\n * stored value, not a layout measurement.\n */\nconst getBodyScrollOffset = () => {\n const bodyTop = typeof document !== 'undefined' ? document.body.style.top : '';\n return bodyTop ? Math.abs(parseFloat(bodyTop)) : 0;\n};\n\n/**\n * Adds the stored body-scroll offset to react-select's computed `top` style.\n *\n * react-select only sets `top` when placement === 'bottom'. When it flips to 'top'\n * it sets `bottom` instead and leaves `top` undefined, so we must guard before adding\n * the scroll offset — otherwise `Number(undefined)` NaN-stomps the style and breaks\n * the flipped portal menu.\n *\n * @internal exported for unit testing only.\n */\nexport const applyBodyScrollOffsetToTop = <T extends Record<string, unknown>>(\n baseStyles: T,\n scrollOffset: number\n): T => ({\n ...baseStyles,\n ...(typeof baseStyles.top === 'number' ? { top: baseStyles.top + scrollOffset } : {}),\n});\n\nexport const Menu = ({ getStyles, ...props }: ComponentProps<typeof selectBuiltins.Menu>) => {\n if (props.selectProps.menuPortalTarget) {\n const customGetStyles: typeof getStyles = (name, styleProps) =>\n applyBodyScrollOffsetToTop(getStyles(name, styleProps), getBodyScrollOffset());\n\n return (\n <selectBuiltins.Menu\n {...props}\n getStyles={customGetStyles}\n className={cn(\n props.className,\n '!z-[11111] !mt-2xs !rounded-input !border !border-border-secondary !bg-background-primary'\n )}\n >\n {props.children}\n </selectBuiltins.Menu>\n );\n }\n\n return (\n <selectBuiltins.Menu\n {...props}\n getStyles={getStyles}\n className={cn(\n props.className,\n '!z-[11111] !mt-2xs !rounded-input !border !border-border-secondary !bg-background-primary'\n )}\n >\n {props.children}\n </selectBuiltins.Menu>\n );\n};\n\nexport const MenuList = (props: ComponentProps<typeof selectBuiltins.MenuList>) => (\n <selectBuiltins.MenuList\n {...props}\n className=\"!px-0 !py-xs\"\n >\n {props.children}\n </selectBuiltins.MenuList>\n);\n\nexport const MenuPortal = (props: ComponentProps<typeof selectBuiltins.MenuPortal>) => (\n <selectBuiltins.MenuPortal\n {...props}\n className=\"!z-[11111]\"\n >\n {props.children}\n </selectBuiltins.MenuPortal>\n);\n\nexport const Placeholder = (props: ComponentProps<typeof selectBuiltins.Placeholder>) => (\n <selectBuiltins.Placeholder\n {...props}\n className=\"!hui-text-body-primary overflow-hidden text-nowrap\"\n >\n {props.children}\n </selectBuiltins.Placeholder>\n);\n\nexport const SingleValue = ({ isDisabled, ...rest }: ComponentProps<typeof selectBuiltins.SingleValue>) => (\n <selectBuiltins.SingleValue\n {...rest}\n className={cn('!hui-text-body-primary m-0', {\n '!cursor-not-allowed !text-text-disabled': isDisabled,\n '!text-text-primary': !isDisabled,\n })}\n isDisabled={isDisabled}\n >\n {rest.children}\n </selectBuiltins.SingleValue>\n);\n\nexport const ValueContainer = (props: ComponentProps<typeof selectBuiltins.ValueContainer>) => (\n <selectBuiltins.ValueContainer\n {...props}\n className=\"!m-0 flex h-full items-center !py-0\"\n >\n {props.children}\n </selectBuiltins.ValueContainer>\n);\n","import type ReactSelectAsync from 'react-select/async';\nimport type ReactSelectAsyncCreatable from 'react-select/async-creatable';\nimport type ReactSelectCreatable from 'react-select/creatable';\n\nimport {\n type ForwardRefExoticComponent,\n type RefAttributes,\n ComponentProps,\n forwardRef,\n useCallback,\n useId,\n} from 'react';\nimport ReactSelect, { ActionMeta, components as selectBuiltins } from 'react-select';\n\nimport { extractFormLabelProps, FormLabel, FormLabelProps } from '../FormLabel/FormLabel';\nimport {\n ClearIndicator,\n DropdownIndicator,\n Input,\n InsideLabelControl,\n Menu,\n MenuList,\n MenuPortal,\n NoOptionsMessage,\n Option,\n Placeholder,\n SelectContainer,\n SingleValue,\n ValueContainer,\n} from './selectComponents';\n\n// Props are unwieldy, so, put them at the bottom.\n\n/**\n * A customized + styled react-select\n *\n * @see https://react-select.com\n */\nexport const Select = forwardRef(\n <SelectType extends AllSelects>(unfilteredProps: Props<SelectType>, ref: ComponentProps<SelectType>['ref']) => {\n const defaultInstanceId = useId();\n const [\n formLabelProps,\n {\n components,\n disabled,\n isInsideLabel,\n menuPlacement = 'auto',\n menuPosition,\n name,\n onChange: propOnChange,\n selectType: SelectComponent = ReactSelect,\n small = false,\n usePortalMenu,\n ...selectProps\n },\n ] = extractFormLabelProps(unfilteredProps);\n\n const onChange = useCallback<SelectOnChange>(\n (event, action) => {\n if (event) {\n event.name = name;\n propOnChange?.(event, action);\n }\n },\n [name, propOnChange]\n );\n\n return (\n <FormLabel\n {...formLabelProps}\n labelText={isInsideLabel ? undefined : formLabelProps.labelText}\n >\n <SelectComponent\n data-hui-id=\"Select\"\n instanceId={defaultInstanceId}\n placeholder=\"Select\"\n {...selectProps}\n components={{\n ClearIndicator,\n Control: InsideLabelControl,\n DropdownIndicator,\n IndicatorSeparator: null,\n Input,\n Menu,\n MenuList,\n MenuPortal,\n NoOptionsMessage,\n Option,\n Placeholder,\n SelectContainer,\n SingleValue,\n ValueContainer,\n ...components,\n }}\n hasError={formLabelProps.hasError}\n isDisabled={disabled}\n isInsideLabel={isInsideLabel}\n labelText={formLabelProps.labelText}\n menuPlacement={menuPlacement}\n menuPosition={menuPosition ?? (usePortalMenu ? 'fixed' : 'absolute')}\n menuPortalTarget={\n usePortalMenu && typeof document !== 'undefined'\n ? document.getElementById('hui-modal-target')\n : undefined\n }\n name={name}\n // This typing should be correct, but react-select is a bit of a mess\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n onChange={onChange as any}\n ref={ref}\n small={small}\n />\n </FormLabel>\n );\n }\n) as ForwardRefExoticComponent<Props<typeof ReactSelect> & RefAttributes<unknown>>;\n\nSelect.displayName = 'Select';\n\n/**\n * Re-export react-select built-ins\n * @see https://react-select.com/components\n */\nexport { selectBuiltins as reactSelectBuiltins };\n\ntype ExtendedProps = {\n /** Adds autocomplete attribute to the dom element, used for accessibility and password managers. */\n autoComplete?: string;\n /** If true, the label will be inside the select. */\n isInsideLabel?: boolean;\n /** Set the size of the select to small (`34px` height, small=false is `42px`) */\n small?: boolean;\n /** Position the select dropdown menu absolutely, relative to <body />. Useful in places like modals where the menu may get cut off */\n usePortalMenu?: boolean;\n} & FormLabelProps;\n\ntype AllSelects =\n | typeof ReactSelect\n | typeof ReactSelectAsync\n | typeof ReactSelectAsyncCreatable\n | typeof ReactSelectCreatable;\n\ntype OverridenOnChangeProps<SelectType extends AllSelects> = Omit<ComponentProps<SelectType>, 'onChange'> & {\n onChange?: SelectOnChange;\n};\n\ntype Props<SelectType extends AllSelects> = { selectType?: SelectType } & ExtendedProps &\n OverridenOnChangeProps<SelectType>;\n\n// Hammer-parity public type — `value: any` is the published contract consumers rely on.\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type OptionType = { label: string; name?: string; value: any };\nexport type SelectOnChange = (event?: OptionType, action?: ActionMeta<OptionType>) => void;\n"],"mappings":"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"}
|
package/Select-BkZu8OLs.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Select-BkZu8OLs.mjs","names":["selectBuiltins"],"sources":["../src/Select/selectComponents.tsx","../src/Select/Select.tsx"],"sourcesContent":["import { cn } from '@evolve.ui/theme-system';\nimport { ComponentProps, ReactNode } from 'react';\nimport { components as selectBuiltins } from 'react-select';\n\nimport { CaretDown, Check } from '../Icons';\nimport { BodyPrimary } from '../Typography/Text/Text';\n\nexport const InsideLabelControl = ({\n children,\n ...props\n}: ComponentProps<typeof selectBuiltins.Control> & {\n selectProps: {\n hasError?: boolean;\n isInsideLabel?: boolean;\n labelText?: ReactNode;\n small?: boolean;\n };\n}) => {\n const { hasError, isInsideLabel, labelText, small } = props.selectProps;\n return (\n <selectBuiltins.Control\n {...props}\n className={cn(\n // GENERAL\n '!m-0 !min-h-[42px] !flex-nowrap !rounded-input !border !border-solid !border-border-secondary !bg-background-primary !p-0 ![box-shadow:none]',\n // HOVER\n {\n 'hover:!border-border-hover': !props.menuIsOpen,\n 'hover:!border-border-selected': props.menuIsOpen,\n },\n {\n '!border-border-critical': props.selectProps['aria-invalid'] === 'true',\n '!border-border-selected': props.menuIsOpen || props.isFocused,\n '!min-h-[34px]': small,\n },\n // ERROR\n {\n '!border-border-critical': hasError && !props.menuIsOpen && !props.isDisabled,\n }\n )}\n >\n {isInsideLabel && Boolean(labelText) && (\n <BodyPrimary\n className=\"ml-xs mr--2xs\"\n color=\"secondary\"\n >\n {labelText}\n </BodyPrimary>\n )}\n {children}\n </selectBuiltins.Control>\n );\n};\n\n/**\n * Add custom icon for dropdown indicator\n * @see https://react-select.com/components#components\n */\nexport const DropdownIndicator = (props: ComponentProps<typeof selectBuiltins.DropdownIndicator>) => {\n return (\n <selectBuiltins.DropdownIndicator\n {...props}\n className=\"flex h-full w-full items-center justify-center !py-0 px-xs\"\n >\n <CaretDown\n aria-label={props.selectProps.menuIsOpen ? 'Caret Up' : 'Caret Down'}\n className={cn({\n 'rotate-180': props.selectProps.menuIsOpen,\n })}\n color={props.selectProps.isDisabled ? 'disabled' : 'primary'}\n size=\"sm\"\n />\n </selectBuiltins.DropdownIndicator>\n );\n};\n\n/**\n * Add data-testid prop to the select component container\n * @see https://react-select.com/components#components\n */\nexport const SelectContainer = ({ className, ...props }: ComponentProps<typeof selectBuiltins.SelectContainer>) => (\n <selectBuiltins.SelectContainer\n {...props}\n className={cn(className, 'hui-text-body-primary !rounded-input text-text-primary ![box-shadow:none]')}\n innerProps={{\n ...props.innerProps,\n // @ts-expect-error all attributes are passed and we have the custom \"data-testid\", so this is ok.\n ...(Boolean(props.selectProps['data-testid']) && {\n // @ts-expect-error all attributes are passed and we have the custom \"data-testid\", so this is ok.\n 'data-testid': props.selectProps['data-testid'],\n }),\n }}\n />\n);\n\nexport const NoOptionsMessage = (props: ComponentProps<typeof selectBuiltins.NoOptionsMessage>) => (\n <selectBuiltins.NoOptionsMessage\n {...props}\n className=\"p-0\"\n >\n <BodyPrimary\n className=\"normal-case\"\n color=\"secondary\"\n >\n No results\n </BodyPrimary>\n </selectBuiltins.NoOptionsMessage>\n);\n\nexport const Input = (props: ComponentProps<typeof selectBuiltins.Input>) => (\n <selectBuiltins.Input\n {...props}\n aria-activedescendant={props['aria-activedescendant'] || undefined}\n // @ts-expect-error prop type does exist on parent, just not here.\n autoComplete={props.selectProps.autoComplete}\n className=\"!m-0 !p-0\"\n />\n);\n\nexport const Option = ({\n children,\n isDisabled,\n isFocused,\n isSelected,\n ...rest\n}: ComponentProps<typeof selectBuiltins.Option>) => {\n const isSelectedAndDisabled = isSelected && isDisabled;\n\n return (\n <selectBuiltins.Option\n {...rest}\n className={cn(\n // BASE\n 'hui-text-body-primary !px-[8px] !py-[4px] text-[16px] text-text-primary',\n // HOVER\n 'hover:cursor-pointer hover:bg-background-hover',\n // SELECTED\n {\n '!bg-background-hover': !isDisabled && isFocused,\n '!bg-background-inverse !text-text-inverse hover:!bg-background-inverse': !isDisabled && isSelected,\n '!bg-background-primary': isDisabled && isFocused && !isSelected,\n // Selected AND disabled - show as selected but with disabled text color\n '!cursor-not-allowed !bg-background-inverse !text-text-disabled hover:!bg-background-inverse':\n isSelectedAndDisabled,\n '!cursor-not-allowed !text-text-disabled hover:!bg-background-primary focus:!bg-background-primary':\n isDisabled && !isSelected,\n }\n )}\n innerProps={{\n ...rest.innerProps,\n // @ts-expect-error all attributes are passed and we have the custom \"data-testid\", so this is ok.\n ...(Boolean(rest.selectProps['data-testid']) && {\n // @ts-expect-error all attributes are passed and we have the custom \"data-testid\", so this is ok.\n 'data-testid': rest.selectProps['data-testid'],\n }),\n }}\n isDisabled={Boolean(isDisabled)}\n isFocused={isFocused}\n isSelected={isSelected}\n >\n <div\n // adds data-testid attribute to dropdown option\n {...(rest.data && typeof rest.data === 'object' && 'data-testid' in rest.data\n ? { 'data-testid': rest.data['data-testid'] }\n : {})}\n className={cn('flex h-full w-full items-center', {\n 'bg-background-inverse text-text-disabled': isSelectedAndDisabled,\n 'bg-background-inverse text-text-inverse': isSelected && !isDisabled,\n 'pl-sm': !isSelected,\n })}\n >\n {isSelected && (\n <Check\n className=\"mr-[2px]\"\n color={isDisabled ? 'disabled' : 'inverse'}\n size=\"xs\"\n />\n )}\n {children}\n </div>\n </selectBuiltins.Option>\n );\n};\n\nexport const ClearIndicator = (props: ComponentProps<typeof selectBuiltins.ClearIndicator>) => (\n <selectBuiltins.ClearIndicator\n {...props}\n className=\"!py-0\"\n >\n {props.children}\n </selectBuiltins.ClearIndicator>\n);\n\n/**\n * Reads the scroll offset that `PreventModalScroll` parks on `document.body.style.top`.\n *\n * When a modal is open, `PreventModalScroll` sets `body.style.top = \"-${scrollPosition}px\"`\n * and `body.style.position = \"fixed\"`. React-select uses `window.pageYOffset` for the\n * portal offset, but that returns 0 when the body is fixed, so we read the stored scroll\n * position directly from `body.style.top` to compensate. Zoom-agnostic because it's a\n * stored value, not a layout measurement.\n */\nconst getBodyScrollOffset = () => {\n const bodyTop = typeof document !== 'undefined' ? document.body.style.top : '';\n return bodyTop ? Math.abs(parseFloat(bodyTop)) : 0;\n};\n\n/**\n * Adds the stored body-scroll offset to react-select's computed `top` style.\n *\n * react-select only sets `top` when placement === 'bottom'. When it flips to 'top'\n * it sets `bottom` instead and leaves `top` undefined, so we must guard before adding\n * the scroll offset — otherwise `Number(undefined)` NaN-stomps the style and breaks\n * the flipped portal menu.\n *\n * @internal exported for unit testing only.\n */\nexport const applyBodyScrollOffsetToTop = <T extends Record<string, unknown>>(\n baseStyles: T,\n scrollOffset: number\n): T => ({\n ...baseStyles,\n ...(typeof baseStyles.top === 'number' ? { top: baseStyles.top + scrollOffset } : {}),\n});\n\nexport const Menu = ({ getStyles, ...props }: ComponentProps<typeof selectBuiltins.Menu>) => {\n if (props.selectProps.menuPortalTarget) {\n const customGetStyles: typeof getStyles = (name, styleProps) =>\n applyBodyScrollOffsetToTop(getStyles(name, styleProps), getBodyScrollOffset());\n\n return (\n <selectBuiltins.Menu\n {...props}\n getStyles={customGetStyles}\n className={cn(\n props.className,\n '!z-[11111] !mt-2xs !rounded-input !border !border-border-secondary !bg-background-primary'\n )}\n >\n {props.children}\n </selectBuiltins.Menu>\n );\n }\n\n return (\n <selectBuiltins.Menu\n {...props}\n getStyles={getStyles}\n className={cn(\n props.className,\n '!z-[11111] !mt-2xs !rounded-input !border !border-border-secondary !bg-background-primary'\n )}\n >\n {props.children}\n </selectBuiltins.Menu>\n );\n};\n\nexport const MenuList = (props: ComponentProps<typeof selectBuiltins.MenuList>) => (\n <selectBuiltins.MenuList\n {...props}\n className=\"!px-0 !py-xs\"\n >\n {props.children}\n </selectBuiltins.MenuList>\n);\n\nexport const MenuPortal = (props: ComponentProps<typeof selectBuiltins.MenuPortal>) => (\n <selectBuiltins.MenuPortal\n {...props}\n className=\"!z-[11111]\"\n >\n {props.children}\n </selectBuiltins.MenuPortal>\n);\n\nexport const Placeholder = (props: ComponentProps<typeof selectBuiltins.Placeholder>) => (\n <selectBuiltins.Placeholder\n {...props}\n className=\"!hui-text-body-primary overflow-hidden text-nowrap\"\n >\n {props.children}\n </selectBuiltins.Placeholder>\n);\n\nexport const SingleValue = ({ isDisabled, ...rest }: ComponentProps<typeof selectBuiltins.SingleValue>) => (\n <selectBuiltins.SingleValue\n {...rest}\n className={cn('!hui-text-body-primary m-0', {\n '!cursor-not-allowed !text-text-disabled': isDisabled,\n '!text-text-primary': !isDisabled,\n })}\n isDisabled={isDisabled}\n >\n {rest.children}\n </selectBuiltins.SingleValue>\n);\n\nexport const ValueContainer = (props: ComponentProps<typeof selectBuiltins.ValueContainer>) => (\n <selectBuiltins.ValueContainer\n {...props}\n className=\"!m-0 flex h-full items-center !py-0\"\n >\n {props.children}\n </selectBuiltins.ValueContainer>\n);\n","import type ReactSelectAsync from 'react-select/async';\nimport type ReactSelectAsyncCreatable from 'react-select/async-creatable';\nimport type ReactSelectCreatable from 'react-select/creatable';\n\nimport {\n type ForwardRefExoticComponent,\n type RefAttributes,\n ComponentProps,\n forwardRef,\n useCallback,\n useId,\n} from 'react';\nimport ReactSelect, { ActionMeta, components as selectBuiltins } from 'react-select';\n\nimport { extractFormLabelProps, FormLabel, FormLabelProps } from '../FormLabel/FormLabel';\nimport {\n ClearIndicator,\n DropdownIndicator,\n Input,\n InsideLabelControl,\n Menu,\n MenuList,\n MenuPortal,\n NoOptionsMessage,\n Option,\n Placeholder,\n SelectContainer,\n SingleValue,\n ValueContainer,\n} from './selectComponents';\n\n// Props are unwieldy, so, put them at the bottom.\n\n/**\n * A customized + styled react-select\n *\n * @see https://react-select.com\n */\nexport const Select = forwardRef(\n <SelectType extends AllSelects>(unfilteredProps: Props<SelectType>, ref: ComponentProps<SelectType>['ref']) => {\n const defaultInstanceId = useId();\n const [\n formLabelProps,\n {\n components,\n disabled,\n isInsideLabel,\n menuPlacement = 'auto',\n menuPosition,\n name,\n onChange: propOnChange,\n selectType: SelectComponent = ReactSelect,\n small = false,\n usePortalMenu,\n ...selectProps\n },\n ] = extractFormLabelProps(unfilteredProps);\n\n const onChange = useCallback<SelectOnChange>(\n (event, action) => {\n if (event) {\n event.name = name;\n propOnChange?.(event, action);\n }\n },\n [name, propOnChange]\n );\n\n return (\n <FormLabel\n {...formLabelProps}\n labelText={isInsideLabel ? undefined : formLabelProps.labelText}\n >\n <SelectComponent\n data-hui-id=\"Select\"\n instanceId={defaultInstanceId}\n placeholder=\"Select\"\n {...selectProps}\n components={{\n ClearIndicator,\n Control: InsideLabelControl,\n DropdownIndicator,\n IndicatorSeparator: null,\n Input,\n Menu,\n MenuList,\n MenuPortal,\n NoOptionsMessage,\n Option,\n Placeholder,\n SelectContainer,\n SingleValue,\n ValueContainer,\n ...components,\n }}\n hasError={formLabelProps.hasError}\n isDisabled={disabled}\n isInsideLabel={isInsideLabel}\n labelText={formLabelProps.labelText}\n menuPlacement={menuPlacement}\n menuPosition={menuPosition ?? (usePortalMenu ? 'fixed' : 'absolute')}\n menuPortalTarget={\n usePortalMenu && typeof document !== 'undefined'\n ? document.getElementById('hui-modal-target')\n : undefined\n }\n name={name}\n // This typing should be correct, but react-select is a bit of a mess\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n onChange={onChange as any}\n ref={ref}\n small={small}\n />\n </FormLabel>\n );\n }\n) as ForwardRefExoticComponent<Props<typeof ReactSelect> & RefAttributes<unknown>>;\n\nSelect.displayName = 'Select';\n\n/**\n * Re-export react-select built-ins\n * @see https://react-select.com/components\n */\nexport { selectBuiltins as reactSelectBuiltins };\n\ntype ExtendedProps = {\n /** Adds autocomplete attribute to the dom element, used for accessibility and password managers. */\n autoComplete?: string;\n /** If true, the label will be inside the select. */\n isInsideLabel?: boolean;\n /** Set the size of the select to small (`34px` height, small=false is `42px`) */\n small?: boolean;\n /** Position the select dropdown menu absolutely, relative to <body />. Useful in places like modals where the menu may get cut off */\n usePortalMenu?: boolean;\n} & FormLabelProps;\n\ntype AllSelects =\n | typeof ReactSelect\n | typeof ReactSelectAsync\n | typeof ReactSelectAsyncCreatable\n | typeof ReactSelectCreatable;\n\ntype OverridenOnChangeProps<SelectType extends AllSelects> = Omit<ComponentProps<SelectType>, 'onChange'> & {\n onChange?: SelectOnChange;\n};\n\ntype Props<SelectType extends AllSelects> = { selectType?: SelectType } & ExtendedProps &\n OverridenOnChangeProps<SelectType>;\n\n// Hammer-parity public type — `value: any` is the published contract consumers rely on.\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type OptionType = { label: string; name?: string; value: any };\nexport type SelectOnChange = (event?: OptionType, action?: ActionMeta<OptionType>) => void;\n"],"mappings":"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"}
|