@unif/react-native-design 0.8.2 → 0.10.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/README.md +1 -2
- package/lib/module/components/business/AvatarWithRing/AvatarWithRing.js +6 -4
- package/lib/module/components/business/AvatarWithRing/AvatarWithRing.js.map +1 -1
- package/lib/module/components/business/AvatarWithRing/styles.js +15 -3
- package/lib/module/components/business/AvatarWithRing/styles.js.map +1 -1
- package/lib/module/components/business/Decorations/GradientWash.js +50 -36
- package/lib/module/components/business/Decorations/GradientWash.js.map +1 -1
- package/lib/module/components/business/Decorations/RadialHalo.js +10 -4
- package/lib/module/components/business/Decorations/RadialHalo.js.map +1 -1
- package/lib/module/components/business/Decorations/ScreenBackdrop.js +22 -14
- package/lib/module/components/business/Decorations/ScreenBackdrop.js.map +1 -1
- package/lib/module/components/business/Decorations/index.js +3 -0
- package/lib/module/components/business/Decorations/index.js.map +1 -1
- package/lib/module/components/business/GlassStats/GlassStats.js +7 -4
- package/lib/module/components/business/GlassStats/GlassStats.js.map +1 -1
- package/lib/module/components/business/GlassStats/types.js +2 -0
- package/lib/module/components/business/VersionPill/VersionPill.js +23 -5
- package/lib/module/components/business/VersionPill/VersionPill.js.map +1 -1
- package/lib/module/components/business/VersionPill/styles.js +1 -1
- package/lib/module/components/business/index.js.map +1 -1
- package/lib/module/components/business/useSvgId.js +20 -0
- package/lib/module/components/business/useSvgId.js.map +1 -0
- package/lib/module/components/ui/Avatar/Avatar.js +13 -8
- package/lib/module/components/ui/Avatar/Avatar.js.map +1 -1
- package/lib/module/components/ui/Avatar/styles.js +7 -7
- package/lib/module/components/ui/Avatar/styles.js.map +1 -1
- package/lib/module/components/ui/BlurLayer/BlurLayer.js +5 -1
- package/lib/module/components/ui/BlurLayer/BlurLayer.js.map +1 -1
- package/lib/module/components/ui/BlurLayer/BlurLayer.web.js +7 -1
- package/lib/module/components/ui/BlurLayer/BlurLayer.web.js.map +1 -1
- package/lib/module/components/ui/Button/Button.js +2 -1
- package/lib/module/components/ui/Button/Button.js.map +1 -1
- package/lib/module/components/ui/Button/ButtonBase.js +36 -2
- package/lib/module/components/ui/Button/ButtonBase.js.map +1 -1
- package/lib/module/components/ui/Button/styles.js +27 -25
- package/lib/module/components/ui/Button/styles.js.map +1 -1
- package/lib/module/components/ui/Card/Card.js +17 -8
- package/lib/module/components/ui/Card/Card.js.map +1 -1
- package/lib/module/components/ui/Card/styles.js +6 -1
- package/lib/module/components/ui/Card/styles.js.map +1 -1
- package/lib/module/components/ui/Carousel/Carousel.js +36 -6
- package/lib/module/components/ui/Carousel/Carousel.js.map +1 -1
- package/lib/module/components/ui/Cell/Cell.js +23 -5
- package/lib/module/components/ui/Cell/Cell.js.map +1 -1
- package/lib/module/components/ui/Cell/Leading.js +2 -2
- package/lib/module/components/ui/Cell/Leading.js.map +1 -1
- package/lib/module/components/ui/Cell/List.js +10 -5
- package/lib/module/components/ui/Cell/List.js.map +1 -1
- package/lib/module/components/ui/Cell/styles.js +7 -6
- package/lib/module/components/ui/Cell/styles.js.map +1 -1
- package/lib/module/components/ui/Checkbox/Checkbox.js +10 -8
- package/lib/module/components/ui/Checkbox/Checkbox.js.map +1 -1
- package/lib/module/components/ui/Checkbox/styles.js +9 -1
- package/lib/module/components/ui/Checkbox/styles.js.map +1 -1
- package/lib/module/components/ui/Chip/Chip.js +19 -5
- package/lib/module/components/ui/Chip/Chip.js.map +1 -1
- package/lib/module/components/ui/Confirm/ConfirmHost.js +28 -11
- package/lib/module/components/ui/Confirm/ConfirmHost.js.map +1 -1
- package/lib/module/components/ui/Confirm/confirm.js +6 -0
- package/lib/module/components/ui/Confirm/confirm.js.map +1 -1
- package/lib/module/components/ui/DrawerHeader/DrawerHeader.js +14 -9
- package/lib/module/components/ui/DrawerHeader/DrawerHeader.js.map +1 -1
- package/lib/module/components/ui/DrawerHeader/styles.js +10 -6
- package/lib/module/components/ui/DrawerHeader/styles.js.map +1 -1
- package/lib/module/components/ui/Empty/Empty.js +5 -4
- package/lib/module/components/ui/Empty/Empty.js.map +1 -1
- package/lib/module/components/ui/EntryCard/EntryCard.js +5 -3
- package/lib/module/components/ui/EntryCard/EntryCard.js.map +1 -1
- package/lib/module/components/ui/EntryCard/styles.js +4 -4
- package/lib/module/components/ui/EntryCard/styles.js.map +1 -1
- package/lib/module/components/ui/Form/FormRow.js +1 -0
- package/lib/module/components/ui/Form/FormRow.js.map +1 -1
- package/lib/module/components/ui/Form/styles.js +3 -1
- package/lib/module/components/ui/Form/styles.js.map +1 -1
- package/lib/module/components/ui/Grid/Grid.js +39 -24
- package/lib/module/components/ui/Grid/Grid.js.map +1 -1
- package/lib/module/components/ui/Grid/styles.js +35 -46
- package/lib/module/components/ui/Grid/styles.js.map +1 -1
- package/lib/module/components/ui/Icon/Icon.js +46 -29
- package/lib/module/components/ui/Icon/Icon.js.map +1 -1
- package/lib/module/components/ui/IconButton/IconButton.js +2 -0
- package/lib/module/components/ui/IconButton/IconButton.js.map +1 -1
- package/lib/module/components/ui/Logo/Logo.js +2 -1
- package/lib/module/components/ui/Logo/Logo.js.map +1 -1
- package/lib/module/components/ui/NavBar/NavBar.js +15 -3
- package/lib/module/components/ui/NavBar/NavBar.js.map +1 -1
- package/lib/module/components/ui/PasswordInput/PasswordInput.js +43 -14
- package/lib/module/components/ui/PasswordInput/PasswordInput.js.map +1 -1
- package/lib/module/components/ui/PasswordInput/styles.js +1 -1
- package/lib/module/components/ui/Pulse/Pulse.js +2 -1
- package/lib/module/components/ui/Pulse/Pulse.js.map +1 -1
- package/lib/module/components/ui/Pulse/PulseDot.js +8 -10
- package/lib/module/components/ui/Pulse/PulseDot.js.map +1 -1
- package/lib/module/components/ui/Pulse/types.js +2 -0
- package/lib/module/components/ui/Pulse/usePulse.web.js +51 -30
- package/lib/module/components/ui/Pulse/usePulse.web.js.map +1 -1
- package/lib/module/components/ui/Radio/Radio.js +19 -5
- package/lib/module/components/ui/Radio/Radio.js.map +1 -1
- package/lib/module/components/ui/Radio/RadioGroup.js +10 -6
- package/lib/module/components/ui/Radio/RadioGroup.js.map +1 -1
- package/lib/module/components/ui/Radio/styles.js +10 -3
- package/lib/module/components/ui/Radio/styles.js.map +1 -1
- package/lib/module/components/ui/Reveal/Reveal.web.js +18 -3
- package/lib/module/components/ui/Reveal/Reveal.web.js.map +1 -1
- package/lib/module/components/ui/Search/Search.js +26 -10
- package/lib/module/components/ui/Search/Search.js.map +1 -1
- package/lib/module/components/ui/Segmented/Segmented.js +40 -30
- package/lib/module/components/ui/Segmented/Segmented.js.map +1 -1
- package/lib/module/components/ui/Segmented/styles.js +4 -2
- package/lib/module/components/ui/Segmented/styles.js.map +1 -1
- package/lib/module/components/ui/Skeleton/Skeleton.js +9 -8
- package/lib/module/components/ui/Skeleton/Skeleton.js.map +1 -1
- package/lib/module/components/ui/Spinner/Spinner.js +15 -16
- package/lib/module/components/ui/Spinner/Spinner.js.map +1 -1
- package/lib/module/components/ui/Spinner/Spinner.web.js +10 -14
- package/lib/module/components/ui/Spinner/Spinner.web.js.map +1 -1
- package/lib/module/components/ui/Spinner/shared.js +31 -0
- package/lib/module/components/ui/Spinner/shared.js.map +1 -0
- package/lib/module/components/ui/StatusDot/StatusDot.js +21 -4
- package/lib/module/components/ui/StatusDot/StatusDot.js.map +1 -1
- package/lib/module/components/ui/StatusDot/styles.js +1 -1
- package/lib/module/components/ui/StatusDot/types.js +2 -0
- package/lib/module/components/ui/Stepper/Stepper.js +46 -10
- package/lib/module/components/ui/Stepper/Stepper.js.map +1 -1
- package/lib/module/components/ui/Switch/Switch.js +6 -11
- package/lib/module/components/ui/Switch/Switch.js.map +1 -1
- package/lib/module/components/ui/Switch/Switch.web.js +2 -8
- package/lib/module/components/ui/Switch/Switch.web.js.map +1 -1
- package/lib/module/components/ui/Switch/styles.js +12 -3
- package/lib/module/components/ui/Switch/styles.js.map +1 -1
- package/lib/module/components/ui/TabBar/TabBar.js +10 -6
- package/lib/module/components/ui/TabBar/TabBar.js.map +1 -1
- package/lib/module/components/ui/TabBar/styles.js +28 -39
- package/lib/module/components/ui/TabBar/styles.js.map +1 -1
- package/lib/module/components/ui/Tabs/Tabs.js +19 -5
- package/lib/module/components/ui/Tabs/Tabs.js.map +1 -1
- package/lib/module/components/ui/Tabs/styles.js +6 -2
- package/lib/module/components/ui/Tabs/styles.js.map +1 -1
- package/lib/module/components/ui/Tabs/types.js +2 -0
- package/lib/module/components/ui/Tag/styles.js +15 -14
- package/lib/module/components/ui/Tag/styles.js.map +1 -1
- package/lib/module/components/ui/TextField/TextFieldBase.js +24 -6
- package/lib/module/components/ui/TextField/TextFieldBase.js.map +1 -1
- package/lib/module/components/ui/Thumbnail/Thumbnail.js +11 -3
- package/lib/module/components/ui/Thumbnail/Thumbnail.js.map +1 -1
- package/lib/module/components/ui/Thumbnail/styles.js +6 -2
- package/lib/module/components/ui/Thumbnail/styles.js.map +1 -1
- package/lib/module/components/ui/Toast/ToastHost.js +16 -5
- package/lib/module/components/ui/Toast/ToastHost.js.map +1 -1
- package/lib/module/components/ui/Toast/ToastHost.web.js +21 -4
- package/lib/module/components/ui/Toast/ToastHost.web.js.map +1 -1
- package/lib/module/components/ui/Toast/styles.js +2 -0
- package/lib/module/components/ui/Toast/styles.js.map +1 -1
- package/lib/module/components/ui/Toast/toast.js +23 -3
- package/lib/module/components/ui/Toast/toast.js.map +1 -1
- package/lib/module/components/ui/shared/badgeStyles.js +31 -0
- package/lib/module/components/ui/shared/badgeStyles.js.map +1 -0
- package/lib/module/icons/data.js +45 -19
- package/lib/module/icons/data.js.map +1 -1
- package/lib/module/theme/colors.js +28 -10
- package/lib/module/theme/colors.js.map +1 -1
- package/lib/module/theme/index.js +6 -2
- package/lib/module/theme/index.js.map +1 -1
- package/lib/module/theme/scale.js +9 -1
- package/lib/module/theme/scale.js.map +1 -1
- package/lib/module/theme/shadow.js +24 -41
- package/lib/module/theme/shadow.js.map +1 -1
- package/lib/module/theme/tokens.js +10 -5
- package/lib/module/theme/tokens.js.map +1 -1
- package/lib/module/theme/usePrefersReducedMotion.js +12 -0
- package/lib/module/theme/usePrefersReducedMotion.js.map +1 -0
- package/lib/module/theme/usePrefersReducedMotion.web.js +25 -0
- package/lib/module/theme/usePrefersReducedMotion.web.js.map +1 -0
- package/lib/module/theme/useTheme.js +13 -0
- package/lib/module/theme/useTheme.js.map +1 -1
- package/lib/module/utils/logger/logger.js +5 -1
- package/lib/module/utils/logger/logger.js.map +1 -1
- package/lib/module/utils/testID/testID.js +6 -3
- package/lib/module/utils/testID/testID.js.map +1 -1
- package/lib/typescript/src/components/business/AvatarWithRing/AvatarWithRing.d.ts +1 -1
- package/lib/typescript/src/components/business/AvatarWithRing/AvatarWithRing.d.ts.map +1 -1
- package/lib/typescript/src/components/business/AvatarWithRing/styles.d.ts +5 -5
- package/lib/typescript/src/components/business/AvatarWithRing/styles.d.ts.map +1 -1
- package/lib/typescript/src/components/business/AvatarWithRing/types.d.ts +3 -1
- package/lib/typescript/src/components/business/AvatarWithRing/types.d.ts.map +1 -1
- package/lib/typescript/src/components/business/Decorations/GradientWash.d.ts +25 -0
- package/lib/typescript/src/components/business/Decorations/GradientWash.d.ts.map +1 -1
- package/lib/typescript/src/components/business/Decorations/RadialHalo.d.ts.map +1 -1
- package/lib/typescript/src/components/business/Decorations/ScreenBackdrop.d.ts +1 -1
- package/lib/typescript/src/components/business/Decorations/ScreenBackdrop.d.ts.map +1 -1
- package/lib/typescript/src/components/business/Decorations/index.d.ts +1 -1
- package/lib/typescript/src/components/business/Decorations/index.d.ts.map +1 -1
- package/lib/typescript/src/components/business/Decorations/types.d.ts +2 -0
- package/lib/typescript/src/components/business/Decorations/types.d.ts.map +1 -1
- package/lib/typescript/src/components/business/GlassStats/GlassStats.d.ts +1 -1
- package/lib/typescript/src/components/business/GlassStats/GlassStats.d.ts.map +1 -1
- package/lib/typescript/src/components/business/GlassStats/styles.d.ts +2 -2
- package/lib/typescript/src/components/business/GlassStats/types.d.ts +5 -0
- package/lib/typescript/src/components/business/GlassStats/types.d.ts.map +1 -1
- package/lib/typescript/src/components/business/VersionPill/VersionPill.d.ts +1 -1
- package/lib/typescript/src/components/business/VersionPill/VersionPill.d.ts.map +1 -1
- package/lib/typescript/src/components/business/VersionPill/styles.d.ts +1 -1
- package/lib/typescript/src/components/business/VersionPill/styles.d.ts.map +1 -1
- package/lib/typescript/src/components/business/VersionPill/types.d.ts +13 -1
- package/lib/typescript/src/components/business/VersionPill/types.d.ts.map +1 -1
- package/lib/typescript/src/components/business/index.d.ts +1 -1
- package/lib/typescript/src/components/business/index.d.ts.map +1 -1
- package/lib/typescript/src/components/business/useSvgId.d.ts +12 -0
- package/lib/typescript/src/components/business/useSvgId.d.ts.map +1 -0
- package/lib/typescript/src/components/ui/Avatar/Avatar.d.ts +1 -1
- package/lib/typescript/src/components/ui/Avatar/Avatar.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Avatar/styles.d.ts +1 -1
- package/lib/typescript/src/components/ui/Avatar/styles.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Avatar/types.d.ts +3 -1
- package/lib/typescript/src/components/ui/Avatar/types.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/BlurLayer/BlurLayer.d.ts +1 -1
- package/lib/typescript/src/components/ui/BlurLayer/BlurLayer.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/BlurLayer/BlurLayer.web.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Button/Button.d.ts +1 -1
- package/lib/typescript/src/components/ui/Button/Button.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Button/ButtonBase.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Button/styles.d.ts +2 -1
- package/lib/typescript/src/components/ui/Button/styles.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Button/types.d.ts +1 -1
- package/lib/typescript/src/components/ui/Button/types.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Card/Card.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Card/styles.d.ts +2 -0
- package/lib/typescript/src/components/ui/Card/styles.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Card/types.d.ts +4 -4
- package/lib/typescript/src/components/ui/Card/types.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Carousel/Carousel.d.ts +4 -11
- package/lib/typescript/src/components/ui/Carousel/Carousel.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Carousel/index.d.ts +1 -1
- package/lib/typescript/src/components/ui/Carousel/index.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Carousel/types.d.ts +4 -0
- package/lib/typescript/src/components/ui/Carousel/types.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Cell/Cell.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Cell/List.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Cell/styles.d.ts +1 -1
- package/lib/typescript/src/components/ui/Cell/styles.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Cell/types.d.ts +5 -2
- package/lib/typescript/src/components/ui/Cell/types.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Checkbox/Checkbox.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Checkbox/styles.d.ts +6 -0
- package/lib/typescript/src/components/ui/Checkbox/styles.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Chip/Chip.d.ts +4 -3
- package/lib/typescript/src/components/ui/Chip/Chip.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Chip/types.d.ts +2 -0
- package/lib/typescript/src/components/ui/Chip/types.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Confirm/ConfirmHost.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Confirm/confirm.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Confirm/types.d.ts +4 -2
- package/lib/typescript/src/components/ui/Confirm/types.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/DrawerHeader/DrawerHeader.d.ts +1 -1
- package/lib/typescript/src/components/ui/DrawerHeader/DrawerHeader.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/DrawerHeader/styles.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/DrawerHeader/types.d.ts +3 -1
- package/lib/typescript/src/components/ui/DrawerHeader/types.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Empty/Empty.d.ts +2 -2
- package/lib/typescript/src/components/ui/Empty/Empty.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Empty/types.d.ts +3 -0
- package/lib/typescript/src/components/ui/Empty/types.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/EntryCard/EntryCard.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/EntryCard/styles.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/EntryCard/types.d.ts +2 -2
- package/lib/typescript/src/components/ui/EntryCard/types.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Form/FormRow.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Form/styles.d.ts +1 -0
- package/lib/typescript/src/components/ui/Form/styles.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Form/types.d.ts +7 -2
- package/lib/typescript/src/components/ui/Form/types.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Grid/Grid.d.ts +1 -1
- package/lib/typescript/src/components/ui/Grid/Grid.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Grid/styles.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Grid/types.d.ts +4 -1
- package/lib/typescript/src/components/ui/Grid/types.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Icon/Icon.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/IconButton/IconButton.d.ts +1 -1
- package/lib/typescript/src/components/ui/IconButton/IconButton.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/IconButton/types.d.ts +7 -2
- package/lib/typescript/src/components/ui/IconButton/types.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Input/Input.d.ts +16 -16
- package/lib/typescript/src/components/ui/Input/types.d.ts +3 -2
- package/lib/typescript/src/components/ui/Input/types.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Logo/Logo.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/NavBar/NavBar.d.ts +8 -1
- package/lib/typescript/src/components/ui/NavBar/NavBar.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/NavBar/types.d.ts +5 -1
- package/lib/typescript/src/components/ui/NavBar/types.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/PasswordInput/PasswordInput.d.ts +13 -5
- package/lib/typescript/src/components/ui/PasswordInput/PasswordInput.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/PasswordInput/styles.d.ts +1 -1
- package/lib/typescript/src/components/ui/PasswordInput/styles.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/PasswordInput/types.d.ts +7 -2
- package/lib/typescript/src/components/ui/PasswordInput/types.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Pulse/Pulse.d.ts +1 -1
- package/lib/typescript/src/components/ui/Pulse/Pulse.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Pulse/PulseDot.d.ts +1 -1
- package/lib/typescript/src/components/ui/Pulse/PulseDot.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Pulse/types.d.ts +5 -0
- package/lib/typescript/src/components/ui/Pulse/types.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Pulse/usePulse.web.d.ts +12 -8
- package/lib/typescript/src/components/ui/Pulse/usePulse.web.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Radio/Radio.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Radio/RadioGroup.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Radio/styles.d.ts +4 -2
- package/lib/typescript/src/components/ui/Radio/styles.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Reveal/Reveal.web.d.ts +9 -0
- package/lib/typescript/src/components/ui/Reveal/Reveal.web.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Search/Search.d.ts +16 -15
- package/lib/typescript/src/components/ui/Search/Search.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Search/types.d.ts +3 -1
- package/lib/typescript/src/components/ui/Search/types.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Segmented/Segmented.d.ts +1 -1
- package/lib/typescript/src/components/ui/Segmented/Segmented.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Segmented/styles.d.ts +1 -1
- package/lib/typescript/src/components/ui/Segmented/styles.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Segmented/types.d.ts +2 -0
- package/lib/typescript/src/components/ui/Segmented/types.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Skeleton/Skeleton.d.ts +3 -2
- package/lib/typescript/src/components/ui/Skeleton/Skeleton.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Spinner/Spinner.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Spinner/Spinner.web.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Spinner/shared.d.ts +5 -0
- package/lib/typescript/src/components/ui/Spinner/shared.d.ts.map +1 -0
- package/lib/typescript/src/components/ui/StatusDot/StatusDot.d.ts +1 -5
- package/lib/typescript/src/components/ui/StatusDot/StatusDot.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/StatusDot/styles.d.ts +1 -1
- package/lib/typescript/src/components/ui/StatusDot/types.d.ts +13 -1
- package/lib/typescript/src/components/ui/StatusDot/types.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Stepper/Stepper.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Switch/Switch.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Switch/Switch.web.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Switch/styles.d.ts +7 -1
- package/lib/typescript/src/components/ui/Switch/styles.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/TabBar/TabBar.d.ts +2 -2
- package/lib/typescript/src/components/ui/TabBar/TabBar.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/TabBar/styles.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/TabBar/types.d.ts +3 -0
- package/lib/typescript/src/components/ui/TabBar/types.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Tabs/Tabs.d.ts +1 -1
- package/lib/typescript/src/components/ui/Tabs/Tabs.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Tabs/styles.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Tabs/types.d.ts +9 -1
- package/lib/typescript/src/components/ui/Tabs/types.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Tag/styles.d.ts +2 -1
- package/lib/typescript/src/components/ui/Tag/styles.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Tag/types.d.ts +6 -2
- package/lib/typescript/src/components/ui/Tag/types.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/TextField/TextFieldBase.d.ts +16 -16
- package/lib/typescript/src/components/ui/TextField/TextFieldBase.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Textarea/Textarea.d.ts +16 -16
- package/lib/typescript/src/components/ui/Textarea/types.d.ts +2 -1
- package/lib/typescript/src/components/ui/Textarea/types.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Thumbnail/Thumbnail.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Thumbnail/styles.d.ts +3 -0
- package/lib/typescript/src/components/ui/Thumbnail/styles.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Toast/ToastHost.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Toast/ToastHost.web.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Toast/styles.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Toast/toast.d.ts +0 -5
- package/lib/typescript/src/components/ui/Toast/toast.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Toast/types.d.ts +1 -1
- package/lib/typescript/src/components/ui/Toast/types.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/shared/badgeStyles.d.ts +27 -0
- package/lib/typescript/src/components/ui/shared/badgeStyles.d.ts.map +1 -0
- package/lib/typescript/src/icons/data.d.ts +1 -1
- package/lib/typescript/src/icons/data.d.ts.map +1 -1
- package/lib/typescript/src/icons/types.d.ts +18 -12
- package/lib/typescript/src/icons/types.d.ts.map +1 -1
- package/lib/typescript/src/theme/colors.d.ts +9 -3
- package/lib/typescript/src/theme/colors.d.ts.map +1 -1
- package/lib/typescript/src/theme/index.d.ts +3 -2
- package/lib/typescript/src/theme/index.d.ts.map +1 -1
- package/lib/typescript/src/theme/scale.d.ts.map +1 -1
- package/lib/typescript/src/theme/shadow.d.ts +8 -8
- package/lib/typescript/src/theme/shadow.d.ts.map +1 -1
- package/lib/typescript/src/theme/tokens.d.ts +7 -3
- package/lib/typescript/src/theme/tokens.d.ts.map +1 -1
- package/lib/typescript/src/theme/usePrefersReducedMotion.d.ts +8 -0
- package/lib/typescript/src/theme/usePrefersReducedMotion.d.ts.map +1 -0
- package/lib/typescript/src/theme/usePrefersReducedMotion.web.d.ts +6 -0
- package/lib/typescript/src/theme/usePrefersReducedMotion.web.d.ts.map +1 -0
- package/lib/typescript/src/theme/useTheme.d.ts.map +1 -1
- package/lib/typescript/src/utils/logger/logger.d.ts.map +1 -1
- package/lib/typescript/src/utils/testID/testID.d.ts +6 -3
- package/lib/typescript/src/utils/testID/testID.d.ts.map +1 -1
- package/package.json +2 -1
- package/src/components/business/AvatarWithRing/AvatarWithRing.tsx +5 -4
- package/src/components/business/AvatarWithRing/styles.ts +21 -3
- package/src/components/business/AvatarWithRing/types.ts +3 -1
- package/src/components/business/Decorations/GradientWash.tsx +46 -22
- package/src/components/business/Decorations/RadialHalo.tsx +8 -4
- package/src/components/business/Decorations/ScreenBackdrop.tsx +23 -5
- package/src/components/business/Decorations/index.ts +4 -0
- package/src/components/business/Decorations/types.ts +2 -0
- package/src/components/business/GlassStats/GlassStats.tsx +8 -4
- package/src/components/business/GlassStats/types.ts +6 -0
- package/src/components/business/VersionPill/VersionPill.tsx +46 -6
- package/src/components/business/VersionPill/styles.ts +1 -1
- package/src/components/business/VersionPill/types.ts +13 -1
- package/src/components/business/index.ts +1 -0
- package/src/components/business/useSvgId.ts +17 -0
- package/src/components/ui/Avatar/Avatar.tsx +17 -10
- package/src/components/ui/Avatar/styles.ts +7 -7
- package/src/components/ui/Avatar/types.ts +3 -1
- package/src/components/ui/BlurLayer/BlurLayer.tsx +4 -1
- package/src/components/ui/BlurLayer/BlurLayer.web.tsx +7 -1
- package/src/components/ui/Button/Button.tsx +2 -1
- package/src/components/ui/Button/ButtonBase.tsx +26 -2
- package/src/components/ui/Button/styles.ts +27 -25
- package/src/components/ui/Button/types.ts +1 -1
- package/src/components/ui/Card/Card.tsx +17 -7
- package/src/components/ui/Card/styles.ts +5 -0
- package/src/components/ui/Card/types.ts +4 -4
- package/src/components/ui/Carousel/Carousel.tsx +44 -15
- package/src/components/ui/Carousel/index.ts +1 -1
- package/src/components/ui/Carousel/types.ts +5 -0
- package/src/components/ui/Cell/Cell.tsx +28 -6
- package/src/components/ui/Cell/Leading.tsx +2 -2
- package/src/components/ui/Cell/List.tsx +14 -8
- package/src/components/ui/Cell/styles.ts +8 -5
- package/src/components/ui/Cell/types.ts +5 -2
- package/src/components/ui/Checkbox/Checkbox.tsx +18 -5
- package/src/components/ui/Checkbox/styles.ts +8 -0
- package/src/components/ui/Chip/Chip.tsx +20 -5
- package/src/components/ui/Chip/types.ts +2 -0
- package/src/components/ui/Confirm/ConfirmHost.tsx +26 -10
- package/src/components/ui/Confirm/confirm.ts +8 -0
- package/src/components/ui/Confirm/types.ts +4 -2
- package/src/components/ui/DrawerHeader/DrawerHeader.tsx +18 -12
- package/src/components/ui/DrawerHeader/styles.ts +10 -6
- package/src/components/ui/DrawerHeader/types.ts +3 -1
- package/src/components/ui/Empty/Empty.tsx +5 -4
- package/src/components/ui/Empty/types.ts +3 -0
- package/src/components/ui/EntryCard/EntryCard.tsx +5 -3
- package/src/components/ui/EntryCard/styles.ts +13 -4
- package/src/components/ui/EntryCard/types.ts +2 -2
- package/src/components/ui/Form/FormRow.tsx +7 -1
- package/src/components/ui/Form/styles.ts +2 -0
- package/src/components/ui/Form/types.ts +7 -2
- package/src/components/ui/Grid/Grid.tsx +42 -25
- package/src/components/ui/Grid/styles.ts +8 -20
- package/src/components/ui/Grid/types.ts +4 -1
- package/src/components/ui/Icon/Icon.tsx +42 -27
- package/src/components/ui/IconButton/IconButton.tsx +2 -0
- package/src/components/ui/IconButton/types.ts +8 -2
- package/src/components/ui/Input/types.ts +3 -2
- package/src/components/ui/Logo/Logo.tsx +2 -1
- package/src/components/ui/NavBar/NavBar.tsx +16 -2
- package/src/components/ui/NavBar/types.ts +5 -1
- package/src/components/ui/PasswordInput/PasswordInput.tsx +77 -43
- package/src/components/ui/PasswordInput/styles.ts +1 -1
- package/src/components/ui/PasswordInput/types.ts +7 -2
- package/src/components/ui/Pulse/Pulse.tsx +2 -1
- package/src/components/ui/Pulse/PulseDot.tsx +7 -6
- package/src/components/ui/Pulse/types.ts +6 -0
- package/src/components/ui/Pulse/usePulse.web.ts +50 -33
- package/src/components/ui/Radio/Radio.tsx +29 -6
- package/src/components/ui/Radio/RadioGroup.tsx +10 -3
- package/src/components/ui/Radio/styles.ts +9 -2
- package/src/components/ui/Reveal/Reveal.web.tsx +18 -3
- package/src/components/ui/Search/Search.tsx +22 -9
- package/src/components/ui/Search/types.ts +7 -1
- package/src/components/ui/Segmented/Segmented.tsx +8 -3
- package/src/components/ui/Segmented/styles.ts +4 -2
- package/src/components/ui/Segmented/types.ts +2 -0
- package/src/components/ui/Skeleton/Skeleton.tsx +9 -8
- package/src/components/ui/Spinner/Spinner.tsx +17 -17
- package/src/components/ui/Spinner/Spinner.web.tsx +7 -15
- package/src/components/ui/Spinner/shared.ts +37 -0
- package/src/components/ui/StatusDot/StatusDot.tsx +21 -3
- package/src/components/ui/StatusDot/styles.ts +1 -1
- package/src/components/ui/StatusDot/types.ts +14 -1
- package/src/components/ui/Stepper/Stepper.tsx +45 -10
- package/src/components/ui/Switch/Switch.tsx +4 -10
- package/src/components/ui/Switch/Switch.web.tsx +2 -8
- package/src/components/ui/Switch/styles.ts +10 -1
- package/src/components/ui/TabBar/TabBar.tsx +14 -6
- package/src/components/ui/TabBar/styles.ts +9 -21
- package/src/components/ui/TabBar/types.ts +3 -0
- package/src/components/ui/Tabs/Tabs.tsx +24 -5
- package/src/components/ui/Tabs/styles.ts +6 -2
- package/src/components/ui/Tabs/types.ts +10 -1
- package/src/components/ui/Tag/styles.ts +18 -10
- package/src/components/ui/Tag/types.ts +6 -2
- package/src/components/ui/TextField/TextFieldBase.tsx +31 -6
- package/src/components/ui/Textarea/types.ts +2 -1
- package/src/components/ui/Thumbnail/Thumbnail.tsx +14 -3
- package/src/components/ui/Thumbnail/styles.ts +6 -2
- package/src/components/ui/Toast/ToastHost.tsx +16 -8
- package/src/components/ui/Toast/ToastHost.web.tsx +26 -4
- package/src/components/ui/Toast/styles.ts +2 -0
- package/src/components/ui/Toast/toast.ts +35 -2
- package/src/components/ui/Toast/types.ts +1 -1
- package/src/components/ui/shared/badgeStyles.ts +36 -0
- package/src/icons/data.ts +30 -0
- package/src/icons/types.ts +25 -10
- package/src/theme/colors.ts +29 -10
- package/src/theme/index.ts +10 -1
- package/src/theme/scale.ts +5 -1
- package/src/theme/shadow.ts +33 -24
- package/src/theme/tokens.ts +10 -5
- package/src/theme/usePrefersReducedMotion.ts +9 -0
- package/src/theme/usePrefersReducedMotion.web.ts +27 -0
- package/src/theme/useTheme.ts +15 -0
- package/src/utils/logger/logger.ts +5 -1
- package/src/utils/testID/testID.ts +6 -3
- package/lib/module/components/index.js +0 -5
- package/lib/module/components/index.js.map +0 -1
- package/lib/typescript/src/components/index.d.ts +0 -3
- package/lib/typescript/src/components/index.d.ts.map +0 -1
- package/src/components/index.ts +0 -2
|
@@ -1,57 +1,74 @@
|
|
|
1
1
|
import { useEffect, useState } from 'react';
|
|
2
|
+
import { usePrefersReducedMotion } from '../../../theme';
|
|
2
3
|
import type { PulseOptions } from './types';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Web 端 usePulse —— RN-Web 上 reanimated 4 + worklets 0.9.x 的 useAnimatedStyle
|
|
6
7
|
* 链路会抛 `Object.keys(undefined)` TypeError(animation frame 每帧打印),pulse 卡死
|
|
7
|
-
*
|
|
8
|
-
* 返回 RN style({ opacity }),保持 native API 兼容。
|
|
8
|
+
* 在初始值。
|
|
9
9
|
*
|
|
10
10
|
* native 端走 usePulse.ts(reanimated worklet) 不动。
|
|
11
11
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
12
|
+
* [M-19] 实现方案 —— CSS transition 降级(零 rAF JS 帧):
|
|
13
|
+
* rnw 0.21 的 animationKeyframes 字段类型侧尚未稳定暴露;
|
|
14
|
+
* 且 <style> 注入在 Spinner.web.tsx 已有安全注释(不拼外部输入)——为保持
|
|
15
|
+
* 一致性,Pulse 侧不再注入第二处 <style> 标签,故采用 CSS transition 降级:
|
|
16
|
+
*
|
|
17
|
+
* - 返回 { opacity, transition } 作为 RN style(RN-Web 把 transition 透传 DOM)
|
|
18
|
+
* - setInterval 每隔 `duration` ms 在 from/to 两档切换 opacity ——
|
|
19
|
+
* setState 频率从原来的 ~60fps 降到 1 次/duration ms(参 ToastHost.web.tsx)
|
|
20
|
+
* - CSS transition 负责两档之间的视觉补间,JS 侧零插值
|
|
21
|
+
* - reduce-motion:静止于 `to`(完全显示),骨架/圆点静态呈现
|
|
15
22
|
*/
|
|
16
23
|
export function usePulse({
|
|
17
24
|
from = 0.6,
|
|
18
25
|
to = 1,
|
|
19
26
|
duration = 700,
|
|
20
27
|
delay = 0,
|
|
21
|
-
}: PulseOptions = {})
|
|
28
|
+
}: PulseOptions = {}) {
|
|
29
|
+
const reduced = usePrefersReducedMotion();
|
|
22
30
|
const [opacity, setOpacity] = useState(from);
|
|
23
31
|
|
|
24
32
|
useEffect(() => {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
if (elapsed + 16 >= duration) {
|
|
43
|
-
direction = direction === 'up' ? 'down' : 'up';
|
|
44
|
-
start = now;
|
|
45
|
-
}
|
|
46
|
-
raf = requestAnimationFrame(tick);
|
|
33
|
+
// reduce-motion:不脉冲,直接停在完全显示(to),骨架/圆点静态呈现。
|
|
34
|
+
if (reduced) {
|
|
35
|
+
setOpacity(to);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// CSS transition 模式:setInterval 只负责在 from/to 两档翻转(1 次/duration ms),
|
|
40
|
+
// 浏览器 CSS transition 负责补间 —— 与原方案 rAF 每帧 setState 相比
|
|
41
|
+
// setState 频率从 ~60fps 降到 1/(duration/1000) fps,无 JS 插值开销。
|
|
42
|
+
let timer: ReturnType<typeof setInterval> | null = null;
|
|
43
|
+
let current = from;
|
|
44
|
+
|
|
45
|
+
const start = () => {
|
|
46
|
+
timer = setInterval(() => {
|
|
47
|
+
current = current === from ? to : from;
|
|
48
|
+
setOpacity(current);
|
|
49
|
+
}, duration);
|
|
47
50
|
};
|
|
48
|
-
raf = requestAnimationFrame(tick);
|
|
49
51
|
|
|
52
|
+
if (delay > 0) {
|
|
53
|
+
const delayTimer = setTimeout(start, delay);
|
|
54
|
+
return () => {
|
|
55
|
+
clearTimeout(delayTimer);
|
|
56
|
+
if (timer != null) clearInterval(timer);
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
start();
|
|
50
60
|
return () => {
|
|
51
|
-
|
|
52
|
-
if (raf != null) cancelAnimationFrame(raf);
|
|
61
|
+
if (timer != null) clearInterval(timer);
|
|
53
62
|
};
|
|
54
|
-
}, [from, to, duration, delay]);
|
|
63
|
+
}, [from, to, duration, delay, reduced]);
|
|
64
|
+
|
|
65
|
+
if (reduced) {
|
|
66
|
+
return { opacity: to } as any;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// RN-Web 把 transition 字段透传到 DOM style,实现 CSS 级平滑过渡。
|
|
70
|
+
// RN style typedef 无 transition 字段,cast any 绕过 TS strict
|
|
71
|
+
// (实际只在 web bundle 命中,DOM div 原样接受该字段)。
|
|
55
72
|
|
|
56
|
-
return { opacity };
|
|
73
|
+
return { opacity, transition: `opacity ${duration}ms ease-in-out` } as any;
|
|
57
74
|
}
|
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
import React, { useContext } from 'react';
|
|
2
2
|
import { Text, View } from 'react-native';
|
|
3
3
|
import { Pressable } from 'react-native-gesture-handler';
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
fixed,
|
|
6
|
+
pressedOpacity,
|
|
7
|
+
r,
|
|
8
|
+
space,
|
|
9
|
+
useColors,
|
|
10
|
+
useThemedStyles,
|
|
11
|
+
} from '../../../theme';
|
|
5
12
|
import { createLogger } from '../../../utils/logger';
|
|
13
|
+
import { childTestID } from '../../../utils/testID';
|
|
6
14
|
import { RadioContext } from './RadioContext';
|
|
7
15
|
import { RadioGroup } from './RadioGroup';
|
|
8
16
|
import { makeStyles } from './styles';
|
|
@@ -10,6 +18,9 @@ import type { RadioProps } from './types';
|
|
|
10
18
|
|
|
11
19
|
const log = createLogger('Radio');
|
|
12
20
|
|
|
21
|
+
// [L-30] 模块级 Set 去重 —— "must be inside Group" 只告警一次,避免 FlatList 滚动时刷屏
|
|
22
|
+
const _warnedCtx = new Set<string>();
|
|
23
|
+
|
|
13
24
|
/**
|
|
14
25
|
* 单个 radio 选项。必须放在 `<Radio.Group>` 里使用。
|
|
15
26
|
*/
|
|
@@ -23,25 +34,37 @@ export function Radio({
|
|
|
23
34
|
const styles = useThemedStyles(makeStyles);
|
|
24
35
|
const ctx = useContext(RadioContext);
|
|
25
36
|
if (!ctx) {
|
|
26
|
-
|
|
37
|
+
// [L-30] 去重:同一 value 的 warn 只打一次,避免渲染阶段反复刷屏
|
|
38
|
+
const warnKey = `no-ctx:${String(value)}`;
|
|
39
|
+
if (!_warnedCtx.has(warnKey)) {
|
|
40
|
+
_warnedCtx.add(warnKey);
|
|
41
|
+
log.warn('<Radio> must be used inside <Radio.Group>');
|
|
42
|
+
}
|
|
27
43
|
return <View />;
|
|
28
44
|
}
|
|
29
45
|
const checked = ctx.value === value;
|
|
30
|
-
|
|
31
|
-
|
|
46
|
+
// [L-92] 改用 childTestID:收口 parent+id 拼接逻辑,保持空串 override 回落拼接语义
|
|
47
|
+
const resolvedTestID = childTestID(ctx.groupTestID, value, testID);
|
|
48
|
+
|
|
49
|
+
// [M-7] row 含 paddingVertical space[2](上下各 ~6pt) → 行高 ≈ r(20) + 2×space[2] ≈ 32pt
|
|
50
|
+
// 补足到 fixed.hitTarget:slop = (44 - 32) / 2 = 6
|
|
51
|
+
const hitSlopV = Math.max(
|
|
52
|
+
0,
|
|
53
|
+
Math.round((fixed.hitTarget - (r(20) + 2 * space[2])) / 2)
|
|
54
|
+
);
|
|
32
55
|
|
|
33
56
|
return (
|
|
34
57
|
<Pressable
|
|
35
58
|
onPress={() => !disabled && ctx.onChange(value)}
|
|
36
59
|
disabled={disabled}
|
|
37
|
-
hitSlop={
|
|
60
|
+
hitSlop={hitSlopV}
|
|
38
61
|
accessibilityRole="radio"
|
|
39
62
|
accessibilityState={{ checked, disabled: !!disabled }}
|
|
40
63
|
accessibilityLabel={label}
|
|
41
64
|
testID={resolvedTestID}
|
|
42
65
|
style={({ pressed }) => [
|
|
43
66
|
styles.row,
|
|
44
|
-
{ opacity: disabled ? 0.5 : pressed ?
|
|
67
|
+
{ opacity: disabled ? 0.5 : pressed ? pressedOpacity : 1 },
|
|
45
68
|
]}
|
|
46
69
|
>
|
|
47
70
|
<View style={[styles.circle, checked && { borderColor: c.primary }]}>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { useMemo } from 'react';
|
|
2
2
|
import { View } from 'react-native';
|
|
3
3
|
import { useThemedStyles } from '../../../theme';
|
|
4
4
|
import { RadioContext } from './RadioContext';
|
|
@@ -20,9 +20,16 @@ export function RadioGroup({
|
|
|
20
20
|
testID,
|
|
21
21
|
}: GroupProps): React.JSX.Element {
|
|
22
22
|
const styles = useThemedStyles(makeStyles);
|
|
23
|
+
// [L-80b] useMemo 稳定 context value —— 避免每次渲染都产生新对象引用,
|
|
24
|
+
// 防止所有 Radio 子项因 context 变化而不必要 re-render。
|
|
25
|
+
const ctx = useMemo(
|
|
26
|
+
() => ({ value, onChange, groupTestID: testID }),
|
|
27
|
+
[value, onChange, testID]
|
|
28
|
+
);
|
|
23
29
|
return (
|
|
24
|
-
<RadioContext.Provider value={
|
|
25
|
-
|
|
30
|
+
<RadioContext.Provider value={ctx}>
|
|
31
|
+
{/* [L-34] accessibilityRole="radiogroup" —— SR 宣读"单选按钮组" */}
|
|
32
|
+
<View style={styles.group} testID={testID} accessibilityRole="radiogroup">
|
|
26
33
|
{children}
|
|
27
34
|
</View>
|
|
28
35
|
</RadioContext.Provider>
|
|
@@ -6,17 +6,21 @@ export const makeStyles = (c: ColorTokens) =>
|
|
|
6
6
|
StyleSheet.create({
|
|
7
7
|
group: {
|
|
8
8
|
gap: space[1],
|
|
9
|
+
// [L-34] radiogroup 角色由 RadioGroup.tsx 容器 View 上设置
|
|
9
10
|
},
|
|
10
11
|
row: {
|
|
11
12
|
flexDirection: 'row',
|
|
12
13
|
alignItems: 'center',
|
|
14
|
+
// [L-37] alignSelf:'flex-start' 防止父容器拉伸(与 Chip [M-8] 同口径)
|
|
15
|
+
alignSelf: 'flex-start' as const,
|
|
13
16
|
gap: space[4],
|
|
14
17
|
paddingVertical: space[2],
|
|
15
18
|
},
|
|
16
19
|
circle: {
|
|
17
20
|
width: r(20),
|
|
18
21
|
height: r(20),
|
|
19
|
-
|
|
22
|
+
// [L-79] radius.pill —— sentinel 999 确保任何尺寸下都是真圆
|
|
23
|
+
borderRadius: radius.pill,
|
|
20
24
|
borderWidth: r(1.5),
|
|
21
25
|
borderColor: c.outline,
|
|
22
26
|
alignItems: 'center',
|
|
@@ -25,12 +29,15 @@ export const makeStyles = (c: ColorTokens) =>
|
|
|
25
29
|
dot: {
|
|
26
30
|
width: r(8),
|
|
27
31
|
height: r(8),
|
|
28
|
-
|
|
32
|
+
// [L-79] radius.pill —— 内圆点同理
|
|
33
|
+
borderRadius: radius.pill,
|
|
29
34
|
backgroundColor: c.primary,
|
|
30
35
|
},
|
|
31
36
|
label: {
|
|
32
37
|
fontSize: t.sm,
|
|
33
38
|
color: c.foreground,
|
|
34
39
|
fontWeight: fw.regular,
|
|
40
|
+
// flexShrink:长 label 在 row 内换行/截断,不溢出也不把同行控件挤没([M-10])
|
|
41
|
+
flexShrink: 1,
|
|
35
42
|
},
|
|
36
43
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { useEffect, useRef, useState } from 'react';
|
|
2
2
|
import { View } from 'react-native';
|
|
3
|
-
import { motion } from '../../../theme';
|
|
3
|
+
import { motion, usePrefersReducedMotion } from '../../../theme';
|
|
4
4
|
import type { RevealProps } from './types';
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -8,6 +8,15 @@ import type { RevealProps } from './types';
|
|
|
8
8
|
* _updatePropsJS 里 Object.keys 抛 TypeError(layoutReanimation/web,渲染即每帧崩),
|
|
9
9
|
* 改用 React state + CSS transition 复刻入场淡入。退场在 web 省略(消费者卸载即移除);
|
|
10
10
|
* native 走 Reveal.tsx 的 reanimated 实现。
|
|
11
|
+
*
|
|
12
|
+
* **结构分叉说明(三层容器)**:
|
|
13
|
+
* - 外层 `<View style={style}>` —— 承接 RN StyleSheet 样式(flex/margin/padding 等),
|
|
14
|
+
* 与 native Reveal 保持相同的容器语义;
|
|
15
|
+
* - 中间 `<div style={animatedWebStyle}>` —— CSS opacity transition 动画层;
|
|
16
|
+
* 必须是真正的 DOM 元素才能触发 CSS transition(react-native-web 的 <View> 会先
|
|
17
|
+
* inline 合并 style 再设 opacity,时序不稳定);
|
|
18
|
+
* - 因此这里刻意不用 animationKeyframes(需要 @keyframes 注入 document),
|
|
19
|
+
* 而用 CSS transition + state 切换 opacity。
|
|
11
20
|
*/
|
|
12
21
|
export function Reveal({
|
|
13
22
|
children,
|
|
@@ -15,10 +24,16 @@ export function Reveal({
|
|
|
15
24
|
duration = motion.base,
|
|
16
25
|
testID,
|
|
17
26
|
}: RevealProps): React.JSX.Element {
|
|
27
|
+
const reduced = usePrefersReducedMotion();
|
|
18
28
|
const [visible, setVisible] = useState(false);
|
|
19
29
|
const rafRef = useRef<number | null>(null);
|
|
20
30
|
|
|
21
31
|
useEffect(() => {
|
|
32
|
+
// reduce-motion:跳过淡入,内容即时呈现(与 native FadeIn 在 ReduceMotion.System 下一致)。
|
|
33
|
+
if (reduced) {
|
|
34
|
+
setVisible(true);
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
22
37
|
let cancelled = false;
|
|
23
38
|
// 双 RAF 过一帧 commit/paint,确保 CSS transition 有 opacity:0 起点(仿 ToastHost.web)。
|
|
24
39
|
rafRef.current = requestAnimationFrame(() => {
|
|
@@ -31,11 +46,11 @@ export function Reveal({
|
|
|
31
46
|
cancelled = true;
|
|
32
47
|
if (rafRef.current != null) cancelAnimationFrame(rafRef.current);
|
|
33
48
|
};
|
|
34
|
-
}, []);
|
|
49
|
+
}, [reduced]);
|
|
35
50
|
|
|
36
51
|
const animatedWebStyle: React.CSSProperties = {
|
|
37
52
|
opacity: visible ? 1 : 0,
|
|
38
|
-
transition: `opacity ${duration}ms ease-out`,
|
|
53
|
+
transition: reduced ? undefined : `opacity ${duration}ms ease-out`,
|
|
39
54
|
};
|
|
40
55
|
|
|
41
56
|
return (
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import React, { forwardRef } from 'react';
|
|
2
2
|
import { Pressable } from 'react-native-gesture-handler';
|
|
3
3
|
|
|
4
|
-
import { useColors } from '../../../theme';
|
|
4
|
+
import { control, fixed, r, useColors } from '../../../theme';
|
|
5
|
+
import { childTestID } from '../../../utils/testID';
|
|
5
6
|
import { Icon } from '../Icon';
|
|
6
7
|
import { Input } from '../Input';
|
|
7
8
|
import type { TextInputRef } from '../TextField/TextFieldBase';
|
|
@@ -9,12 +10,12 @@ import type { SearchProps } from './types';
|
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* 搜索输入框 —— `<Input>` 的预设:前置搜索图标、清除按钮、
|
|
12
|
-
* 高
|
|
13
|
+
* 高 control.md、键盘 return 键为「搜索」。
|
|
13
14
|
*
|
|
14
15
|
* Ref 透传到 Input 内部 TextInput,业务可调 `searchRef.current?.focus()`。
|
|
15
16
|
*/
|
|
16
17
|
export const Search = forwardRef<TextInputRef, SearchProps>(function Search(
|
|
17
|
-
{ onSubmit, placeholder = '搜索…', value, onChangeText, ...rest },
|
|
18
|
+
{ onSubmit, placeholder = '搜索…', value, onChangeText, testID, ...rest },
|
|
18
19
|
ref
|
|
19
20
|
): React.JSX.Element {
|
|
20
21
|
const c = useColors();
|
|
@@ -26,22 +27,34 @@ export const Search = forwardRef<TextInputRef, SearchProps>(function Search(
|
|
|
26
27
|
value={value}
|
|
27
28
|
onChangeText={onChangeText}
|
|
28
29
|
placeholder={placeholder}
|
|
29
|
-
|
|
30
|
+
// [L-81] 高度裸 36 → control.md(r(36),随设备缩放)
|
|
31
|
+
height={control.md}
|
|
30
32
|
returnKeyType="search"
|
|
31
33
|
accessibilityRole="search"
|
|
32
|
-
|
|
33
|
-
|
|
34
|
+
testID={testID}
|
|
35
|
+
onSubmitEditing={(e) => {
|
|
36
|
+
// [M-9] 改读 e.nativeEvent.text —— 不再依赖受控 value,非受控场景也能触发
|
|
37
|
+
const text = e.nativeEvent.text;
|
|
38
|
+
onSubmit?.(text);
|
|
34
39
|
}}
|
|
35
|
-
leading={<Icon name="search" size={18} color={c.foregroundSubtle} />}
|
|
40
|
+
leading={<Icon name="search" size={r(18)} color={c.foregroundSubtle} />}
|
|
36
41
|
trailing={
|
|
37
42
|
filled ? (
|
|
38
43
|
<Pressable
|
|
39
44
|
onPress={() => onChangeText?.('')}
|
|
40
|
-
|
|
45
|
+
// [M-7] 清除按钮 icon r(14)≈14pt;Input 高 control.md≈36pt 限制垂直扩展
|
|
46
|
+
// horizontal 走 (44-14)/2=15;vertical 走 (44-control.md)/2≈4
|
|
47
|
+
hitSlop={{
|
|
48
|
+
top: Math.round((fixed.hitTarget - control.md) / 2),
|
|
49
|
+
bottom: Math.round((fixed.hitTarget - control.md) / 2),
|
|
50
|
+
left: Math.round((fixed.hitTarget - r(14)) / 2),
|
|
51
|
+
right: Math.round((fixed.hitTarget - r(14)) / 2),
|
|
52
|
+
}}
|
|
41
53
|
accessibilityRole="button"
|
|
42
54
|
accessibilityLabel="清除"
|
|
55
|
+
testID={childTestID(testID, 'clear')}
|
|
43
56
|
>
|
|
44
|
-
<Icon name="close" size={14} color={c.foregroundSubtle} />
|
|
57
|
+
<Icon name="close" size={r(14)} color={c.foregroundSubtle} />
|
|
45
58
|
</Pressable>
|
|
46
59
|
) : null
|
|
47
60
|
}
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import type { TextInputProps } from 'react-native';
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
// [L-36] Omit 扩 'multiline'/'numberOfLines' —— 搜索框固定单行,这两属性无意义
|
|
4
|
+
export type SearchProps = Omit<
|
|
5
|
+
TextInputProps,
|
|
6
|
+
'style' | 'multiline' | 'numberOfLines'
|
|
7
|
+
> & {
|
|
4
8
|
/** 提交回调(按下 return 键时触发) */
|
|
5
9
|
onSubmit?: (value: string) => void;
|
|
6
10
|
/** 覆盖 placeholder(默认:搜索…) */
|
|
7
11
|
placeholder?: string;
|
|
12
|
+
/** E2E / 测试定位 */
|
|
13
|
+
testID?: string;
|
|
8
14
|
};
|
|
@@ -16,6 +16,7 @@ export function Segmented({
|
|
|
16
16
|
value,
|
|
17
17
|
onChange,
|
|
18
18
|
items,
|
|
19
|
+
disabled = false,
|
|
19
20
|
testID,
|
|
20
21
|
}: SegmentedProps): React.JSX.Element {
|
|
21
22
|
const { colors: c, scheme, shadow } = useTheme();
|
|
@@ -24,16 +25,20 @@ export function Segmented({
|
|
|
24
25
|
const activeShadow = scheme === 'dark' ? null : shadow.subtle;
|
|
25
26
|
|
|
26
27
|
return (
|
|
27
|
-
|
|
28
|
+
// [L-34] accessibilityRole="tablist" —— SR 宣读"标签列表"
|
|
29
|
+
<View style={styles.seg} testID={testID} accessibilityRole="tablist">
|
|
28
30
|
{items.map((it) => {
|
|
29
31
|
const on = it.id === value;
|
|
30
32
|
const itemTestID = childTestID(testID, it.id, it.testID);
|
|
33
|
+
// [L-82] item 禁用 = 整体 disabled OR 单项 it.disabled
|
|
34
|
+
const itemDisabled = disabled || !!it.disabled;
|
|
31
35
|
return (
|
|
32
36
|
<Pressable
|
|
33
37
|
key={it.id}
|
|
34
|
-
onPress={() => onChange(it.id)}
|
|
38
|
+
onPress={() => !itemDisabled && onChange(it.id)}
|
|
39
|
+
disabled={itemDisabled}
|
|
35
40
|
accessibilityRole="tab"
|
|
36
|
-
accessibilityState={{ selected: on }}
|
|
41
|
+
accessibilityState={{ selected: on, disabled: itemDisabled }}
|
|
37
42
|
accessibilityLabel={it.label}
|
|
38
43
|
testID={itemTestID}
|
|
39
44
|
style={({ pressed }) => [
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { StyleSheet } from 'react-native';
|
|
2
2
|
import type { ColorTokens } from '../../../theme';
|
|
3
|
-
import {
|
|
3
|
+
import { fixed, r, radius, space, type as t } from '../../../theme';
|
|
4
4
|
|
|
5
5
|
export const makeStyles = (c: ColorTokens) =>
|
|
6
6
|
StyleSheet.create({
|
|
@@ -12,7 +12,9 @@ export const makeStyles = (c: ColorTokens) =>
|
|
|
12
12
|
alignSelf: 'flex-start',
|
|
13
13
|
},
|
|
14
14
|
segItem: {
|
|
15
|
-
|
|
15
|
+
// [M-7] Segmented item 高原为 control.sm≈28pt < 44pt;
|
|
16
|
+
// hitSlop 不越父 seg 容器边界 → 改用 minHeight 直接对齐 fixed.hitTarget(44pt)
|
|
17
|
+
minHeight: fixed.hitTarget,
|
|
16
18
|
paddingHorizontal: space[7],
|
|
17
19
|
alignItems: 'center',
|
|
18
20
|
justifyContent: 'center',
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import Animated from 'react-native-reanimated';
|
|
3
3
|
import { usePulse } from '../Pulse';
|
|
4
|
-
import { useColors } from '../../../theme';
|
|
4
|
+
import { r, useColors } from '../../../theme';
|
|
5
5
|
import type { SkeletonProps } from './types';
|
|
6
6
|
|
|
7
7
|
/**
|
|
@@ -13,13 +13,14 @@ import type { SkeletonProps } from './types';
|
|
|
13
13
|
* <Skeleton shape="circle" size={40} /> // 头像占位
|
|
14
14
|
* ```
|
|
15
15
|
*
|
|
16
|
-
* `usePulse({ from: 0.5 })`
|
|
17
|
-
*
|
|
16
|
+
* `usePulse({ from: 0.5 })` 每实例独立脉冲 —— native 端走 Reanimated 4 worklet,
|
|
17
|
+
* web 端走 CSS transition + setInterval(零 rAF JS 帧),opacity 在 0.5~1 循环。
|
|
18
|
+
* 区别于沿 X 横扫高光的流式 shimmer。 */
|
|
18
19
|
export function Skeleton({
|
|
19
20
|
shape = 'rect',
|
|
20
21
|
width,
|
|
21
22
|
height,
|
|
22
|
-
size = 40,
|
|
23
|
+
size = r(40),
|
|
23
24
|
radius,
|
|
24
25
|
style,
|
|
25
26
|
testID,
|
|
@@ -35,14 +36,14 @@ export function Skeleton({
|
|
|
35
36
|
if (shape === 'line') {
|
|
36
37
|
return {
|
|
37
38
|
width: width ?? '100%',
|
|
38
|
-
height: height ?? 11,
|
|
39
|
-
borderRadius: radius ?? 3,
|
|
39
|
+
height: height ?? r(11),
|
|
40
|
+
borderRadius: radius ?? r(3),
|
|
40
41
|
};
|
|
41
42
|
}
|
|
42
43
|
return {
|
|
43
44
|
width: width ?? '100%',
|
|
44
|
-
height: height ?? 80,
|
|
45
|
-
borderRadius: radius ?? 8,
|
|
45
|
+
height: height ?? r(80),
|
|
46
|
+
borderRadius: radius ?? r(8),
|
|
46
47
|
};
|
|
47
48
|
})();
|
|
48
49
|
|
|
@@ -2,42 +2,42 @@ import { useEffect } from 'react';
|
|
|
2
2
|
import Animated, {
|
|
3
3
|
cancelAnimation,
|
|
4
4
|
Easing,
|
|
5
|
+
ReduceMotion,
|
|
5
6
|
useAnimatedStyle,
|
|
6
7
|
useSharedValue,
|
|
7
8
|
withRepeat,
|
|
8
9
|
withTiming,
|
|
9
10
|
} from 'react-native-reanimated';
|
|
10
|
-
import { useColors } from '../../../theme';
|
|
11
|
-
import {
|
|
11
|
+
import { r, useColors } from '../../../theme';
|
|
12
|
+
import { sanitizeSpinnerProps } from './shared';
|
|
12
13
|
import type { SpinnerProps } from './types';
|
|
13
14
|
|
|
14
|
-
const log = createLogger('Spinner');
|
|
15
|
-
|
|
16
15
|
export function Spinner({
|
|
17
|
-
size = 18,
|
|
16
|
+
size = r(18),
|
|
18
17
|
color,
|
|
19
|
-
thickness = 2,
|
|
18
|
+
thickness = r(2),
|
|
20
19
|
style,
|
|
21
20
|
testID,
|
|
22
21
|
}: SpinnerProps) {
|
|
23
22
|
const c = useColors();
|
|
24
23
|
const angle = useSharedValue(0);
|
|
25
24
|
const stroke = color ?? c.primary;
|
|
26
|
-
|
|
27
|
-
log.warn(`size 应为 ≥8 的有限数,传入 ${size},已钳到 8`);
|
|
28
|
-
}
|
|
29
|
-
if (Number.isFinite(thickness) && (thickness as number) <= 0) {
|
|
30
|
-
log.warn(`thickness 应为正数,传入 ${thickness},已 fallback 为 2`);
|
|
31
|
-
}
|
|
32
|
-
const safeSize = Number.isFinite(size) && size > 8 ? size : 8;
|
|
33
|
-
const safeThickness =
|
|
34
|
-
Number.isFinite(thickness) && thickness > 0 ? thickness : 2;
|
|
25
|
+
const { safeSize, safeThickness } = sanitizeSpinnerProps(size, thickness);
|
|
35
26
|
|
|
36
27
|
useEffect(() => {
|
|
28
|
+
// 加载指示属 essential motion(W3C):系统「减弱动态效果」下仍应旋转,否则会冻结成
|
|
29
|
+
// 与空闲/完成不可区分的静止圆环(形似卡死)。显式 ReduceMotion.Never 覆盖 reanimated
|
|
30
|
+
// 默认的 System —— 后者在 reduce-motion 下让 withTiming 跳端值、withRepeat 一轮即停。
|
|
37
31
|
angle.value = withRepeat(
|
|
38
|
-
withTiming(360, {
|
|
32
|
+
withTiming(360, {
|
|
33
|
+
duration: 900,
|
|
34
|
+
easing: Easing.linear,
|
|
35
|
+
reduceMotion: ReduceMotion.Never,
|
|
36
|
+
}),
|
|
39
37
|
-1,
|
|
40
|
-
false
|
|
38
|
+
false,
|
|
39
|
+
undefined,
|
|
40
|
+
ReduceMotion.Never
|
|
41
41
|
);
|
|
42
42
|
return () => cancelAnimation(angle);
|
|
43
43
|
}, [angle]);
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import React, { useEffect, useRef } from 'react';
|
|
2
2
|
import { View } from 'react-native';
|
|
3
|
-
import { useColors } from '../../../theme';
|
|
4
|
-
import {
|
|
3
|
+
import { r, useColors } from '../../../theme';
|
|
4
|
+
import { sanitizeSpinnerProps } from './shared';
|
|
5
5
|
import type { SpinnerProps } from './types';
|
|
6
6
|
|
|
7
|
-
const log = createLogger('Spinner');
|
|
8
|
-
|
|
9
7
|
// React-Native-Web 上 reanimated 4 + worklets 0.9.x 的 useAnimatedStyle 链路在
|
|
10
8
|
// web bundle 里跑会触发 `_updatePropsJS` 里 `Object.keys(updates)` 的 worklet
|
|
11
9
|
// 回值打包 edge case(animation frame 每帧抛 TypeError),旋转停滞。
|
|
@@ -33,9 +31,9 @@ function ensureKeyframes() {
|
|
|
33
31
|
}
|
|
34
32
|
|
|
35
33
|
export function Spinner({
|
|
36
|
-
size = 18,
|
|
34
|
+
size = r(18),
|
|
37
35
|
color,
|
|
38
|
-
thickness = 2,
|
|
36
|
+
thickness = r(2),
|
|
39
37
|
style,
|
|
40
38
|
testID,
|
|
41
39
|
}: SpinnerProps): React.JSX.Element {
|
|
@@ -45,15 +43,7 @@ export function Spinner({
|
|
|
45
43
|
|
|
46
44
|
const ref = useRef<any>(null);
|
|
47
45
|
const stroke = color ?? c.primary;
|
|
48
|
-
|
|
49
|
-
log.warn(`size 应为 ≥8 的有限数,传入 ${size},已钳到 8`);
|
|
50
|
-
}
|
|
51
|
-
if (Number.isFinite(thickness) && (thickness as number) <= 0) {
|
|
52
|
-
log.warn(`thickness 应为正数,传入 ${thickness},已 fallback 为 2`);
|
|
53
|
-
}
|
|
54
|
-
const safeSize = Number.isFinite(size) && size > 8 ? size : 8;
|
|
55
|
-
const safeThickness =
|
|
56
|
-
Number.isFinite(thickness) && thickness > 0 ? thickness : 2;
|
|
46
|
+
const { safeSize, safeThickness } = sanitizeSpinnerProps(size, thickness);
|
|
57
47
|
|
|
58
48
|
// RN-Web 把 View 渲染成 div,我们用 ref 拿到底层 DOM 节点直接挂 CSS animation
|
|
59
49
|
// (RN style 不支持 animation 字段;只能事后注入)。
|
|
@@ -61,6 +51,8 @@ export function Spinner({
|
|
|
61
51
|
ensureKeyframes();
|
|
62
52
|
const node = ref.current;
|
|
63
53
|
if (node && node.style) {
|
|
54
|
+
// essential motion:加载指示在 prefers-reduced-motion 下仍应旋转(与 native 的
|
|
55
|
+
// ReduceMotion.Never 对齐),故意不加 @media (prefers-reduced-motion) 停转。
|
|
64
56
|
node.style.animation = 'unif-spinner-spin 900ms linear infinite';
|
|
65
57
|
}
|
|
66
58
|
}, []);
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { createLogger } from '../../../utils/logger';
|
|
2
|
+
|
|
3
|
+
const log = createLogger('Spinner');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* [M-24][L-11] 入参防御逻辑抽到单一模块,native/web 两端 import 同一份:
|
|
7
|
+
* - 去重 warn:同一异常值只告警一次(模块级 Set 记录),避免渲染路径每帧刷日志。
|
|
8
|
+
* - size / thickness 两字段均覆盖非有限值告警(thickness 原缺失 isFinite 守卫)。
|
|
9
|
+
* - 返回已钳制的安全值,调用方直接使用。
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const warnedKeys = new Set<string>();
|
|
13
|
+
|
|
14
|
+
function warnOnce(key: string, msg: string) {
|
|
15
|
+
if (warnedKeys.has(key)) return;
|
|
16
|
+
warnedKeys.add(key);
|
|
17
|
+
log.warn(msg);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function sanitizeSpinnerProps(
|
|
21
|
+
size: number,
|
|
22
|
+
thickness: number
|
|
23
|
+
): { safeSize: number; safeThickness: number } {
|
|
24
|
+
if (!Number.isFinite(size) || size < 8) {
|
|
25
|
+
warnOnce(`size:${size}`, `size 应为 ≥8 的有限数,传入 ${size},已钳到 8`);
|
|
26
|
+
}
|
|
27
|
+
if (!Number.isFinite(thickness) || thickness <= 0) {
|
|
28
|
+
warnOnce(
|
|
29
|
+
`thickness:${thickness}`,
|
|
30
|
+
`thickness 应为正有限数,传入 ${thickness},已 fallback 为 2`
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
return {
|
|
34
|
+
safeSize: Number.isFinite(size) && size > 8 ? size : 8,
|
|
35
|
+
safeThickness: Number.isFinite(thickness) && thickness > 0 ? thickness : 2,
|
|
36
|
+
};
|
|
37
|
+
}
|