@fountain-ui/core 2.0.0-beta.10 → 2.0.0-beta.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/build/commonjs/Accordion/Accordion.js +3 -3
  2. package/build/commonjs/Accordion/Accordion.js.map +1 -1
  3. package/build/commonjs/ButtonBase/ButtonBase.js +56 -52
  4. package/build/commonjs/ButtonBase/ButtonBase.js.map +1 -1
  5. package/build/commonjs/CircularProgress/CircularProgress.js +19 -24
  6. package/build/commonjs/CircularProgress/CircularProgress.js.map +1 -1
  7. package/build/commonjs/ImageCore/ImageCoreNative.js +24 -26
  8. package/build/commonjs/ImageCore/ImageCoreNative.js.map +1 -1
  9. package/build/commonjs/Slide/Slide.js +12 -13
  10. package/build/commonjs/Slide/Slide.js.map +1 -1
  11. package/build/commonjs/Tabs/TabIndicator.js +2 -6
  12. package/build/commonjs/Tabs/TabIndicator.js.map +1 -1
  13. package/build/commonjs/Tabs/Tabs.js +46 -48
  14. package/build/commonjs/Tabs/Tabs.js.map +1 -1
  15. package/build/commonjs/Tabs/useTabCoordinates.js +44 -0
  16. package/build/commonjs/Tabs/useTabCoordinates.js.map +1 -0
  17. package/build/commonjs/Tabs/useTabsWidth.js +26 -0
  18. package/build/commonjs/Tabs/useTabsWidth.js.map +1 -0
  19. package/build/commonjs/Tooltip/Tooltip.js +18 -22
  20. package/build/commonjs/Tooltip/Tooltip.js.map +1 -1
  21. package/build/commonjs/animated/AnimatedPressable.js +2 -3
  22. package/build/commonjs/animated/AnimatedPressable.js.map +1 -1
  23. package/build/commonjs/hooks/useCollapsibleAppBar.js +46 -36
  24. package/build/commonjs/hooks/useCollapsibleAppBar.js.map +1 -1
  25. package/build/commonjs/hooks/useFadeInAppBar.js +35 -18
  26. package/build/commonjs/hooks/useFadeInAppBar.js.map +1 -1
  27. package/build/commonjs/hooks/useThrottle.js +3 -7
  28. package/build/commonjs/hooks/useThrottle.js.map +1 -1
  29. package/build/commonjs/internal/hooks/index.js +0 -8
  30. package/build/commonjs/internal/hooks/index.js.map +1 -1
  31. package/build/commonjs/internal/hooks/useHeight.js +2 -6
  32. package/build/commonjs/internal/hooks/useHeight.js.map +1 -1
  33. package/build/module/Accordion/Accordion.js +3 -3
  34. package/build/module/Accordion/Accordion.js.map +1 -1
  35. package/build/module/ButtonBase/ButtonBase.js +54 -48
  36. package/build/module/ButtonBase/ButtonBase.js.map +1 -1
  37. package/build/module/CircularProgress/CircularProgress.js +20 -21
  38. package/build/module/CircularProgress/CircularProgress.js.map +1 -1
  39. package/build/module/ImageCore/ImageCoreNative.js +20 -23
  40. package/build/module/ImageCore/ImageCoreNative.js.map +1 -1
  41. package/build/module/Slide/Slide.js +14 -10
  42. package/build/module/Slide/Slide.js.map +1 -1
  43. package/build/module/Tabs/TabIndicator.js +3 -7
  44. package/build/module/Tabs/TabIndicator.js.map +1 -1
  45. package/build/module/Tabs/Tabs.js +39 -39
  46. package/build/module/Tabs/Tabs.js.map +1 -1
  47. package/build/module/Tabs/useTabCoordinates.js +30 -0
  48. package/build/module/Tabs/useTabCoordinates.js.map +1 -0
  49. package/build/module/Tabs/useTabsWidth.js +18 -0
  50. package/build/module/Tabs/useTabsWidth.js.map +1 -0
  51. package/build/module/Tooltip/Tooltip.js +15 -15
  52. package/build/module/Tooltip/Tooltip.js.map +1 -1
  53. package/build/module/animated/AnimatedPressable.js +2 -3
  54. package/build/module/animated/AnimatedPressable.js.map +1 -1
  55. package/build/module/hooks/useCollapsibleAppBar.js +46 -34
  56. package/build/module/hooks/useCollapsibleAppBar.js.map +1 -1
  57. package/build/module/hooks/useFadeInAppBar.js +35 -14
  58. package/build/module/hooks/useFadeInAppBar.js.map +1 -1
  59. package/build/module/hooks/useThrottle.js +3 -3
  60. package/build/module/hooks/useThrottle.js.map +1 -1
  61. package/build/module/internal/hooks/index.js +0 -1
  62. package/build/module/internal/hooks/index.js.map +1 -1
  63. package/build/module/internal/hooks/useHeight.js +2 -2
  64. package/build/module/internal/hooks/useHeight.js.map +1 -1
  65. package/build/typescript/Tabs/useTabCoordinates.d.ts +7 -0
  66. package/build/typescript/Tabs/useTabsWidth.d.ts +2 -0
  67. package/build/typescript/animated/AnimatedPressable.d.ts +2 -2
  68. package/build/typescript/internal/hooks/index.d.ts +0 -1
  69. package/package.json +2 -2
  70. package/src/Accordion/Accordion.tsx +5 -3
  71. package/src/ButtonBase/ButtonBase.tsx +65 -43
  72. package/src/CircularProgress/CircularProgress.tsx +24 -30
  73. package/src/ImageCore/ImageCoreNative.tsx +17 -19
  74. package/src/Slide/Slide.tsx +17 -15
  75. package/src/Tabs/TabIndicator.tsx +4 -8
  76. package/src/Tabs/Tabs.tsx +37 -39
  77. package/src/Tabs/useTabCoordinates.ts +36 -0
  78. package/src/Tabs/useTabsWidth.ts +20 -0
  79. package/src/Tooltip/Tooltip.tsx +16 -16
  80. package/src/animated/AnimatedPressable.tsx +1 -2
  81. package/src/hooks/useCollapsibleAppBar.ts +41 -31
  82. package/src/hooks/useFadeInAppBar.ts +31 -15
  83. package/src/hooks/useThrottle.ts +3 -3
  84. package/src/internal/hooks/index.ts +0 -1
  85. package/src/internal/hooks/useHeight.ts +2 -2
  86. package/build/commonjs/ButtonBase/ButtonBase.ios.js +0 -101
  87. package/build/commonjs/ButtonBase/ButtonBase.ios.js.map +0 -1
  88. package/build/commonjs/ButtonBase/useDisabledReaction/index.js +0 -21
  89. package/build/commonjs/ButtonBase/useDisabledReaction/index.js.map +0 -1
  90. package/build/commonjs/ButtonBase/useDisabledReaction/index.native.js +0 -9
  91. package/build/commonjs/ButtonBase/useDisabledReaction/index.native.js.map +0 -1
  92. package/build/commonjs/ImageCore/ImageCoreNative.ios.js +0 -60
  93. package/build/commonjs/ImageCore/ImageCoreNative.ios.js.map +0 -1
  94. package/build/commonjs/internal/hooks/useWidth.js +0 -29
  95. package/build/commonjs/internal/hooks/useWidth.js.map +0 -1
  96. package/build/module/ButtonBase/ButtonBase.ios.js +0 -82
  97. package/build/module/ButtonBase/ButtonBase.ios.js.map +0 -1
  98. package/build/module/ButtonBase/useDisabledReaction/index.js +0 -12
  99. package/build/module/ButtonBase/useDisabledReaction/index.js.map +0 -1
  100. package/build/module/ButtonBase/useDisabledReaction/index.native.js +0 -2
  101. package/build/module/ButtonBase/useDisabledReaction/index.native.js.map +0 -1
  102. package/build/module/ImageCore/ImageCoreNative.ios.js +0 -45
  103. package/build/module/ImageCore/ImageCoreNative.ios.js.map +0 -1
  104. package/build/module/internal/hooks/useWidth.js +0 -15
  105. package/build/module/internal/hooks/useWidth.js.map +0 -1
  106. package/build/typescript/ButtonBase/ButtonBase.ios.d.ts +0 -2
  107. package/build/typescript/ButtonBase/useDisabledReaction/index.d.ts +0 -2
  108. package/build/typescript/ButtonBase/useDisabledReaction/index.native.d.ts +0 -2
  109. package/build/typescript/ImageCore/ImageCoreNative.ios.d.ts +0 -2
  110. package/build/typescript/internal/hooks/useWidth.d.ts +0 -2
  111. package/src/ButtonBase/ButtonBase.ios.tsx +0 -95
  112. package/src/ButtonBase/useDisabledReaction/index.native.ts +0 -4
  113. package/src/ButtonBase/useDisabledReaction/index.ts +0 -16
  114. package/src/ImageCore/ImageCoreNative.ios.tsx +0 -46
  115. package/src/internal/hooks/useWidth.ts +0 -17
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import { useRef } from 'react';
2
2
  import { Keyboard, Platform } from 'react-native';
3
3
  import { runOnJS, useAnimatedScrollHandler, useAnimatedStyle, useDerivedValue, useSharedValue, withTiming } from 'react-native-reanimated';
4
4
  import { useSafeAreaInsets } from 'react-native-safe-area-context';
@@ -8,7 +8,9 @@ import useAppbarStyles from './useAppbarStyles';
8
8
  const defaultOptions = {
9
9
  keyboardDismissMode: 'none'
10
10
  };
11
- const ANIMATION_DURATION_MILLIS = 100;
11
+ const ANIMATION_CONFIG = {
12
+ duration: 100
13
+ };
12
14
  const SUPPORTS_DRAG_DETECTION = Platform.OS !== 'web';
13
15
  export default function useCollapsibleAppBar() {
14
16
  let userOptions = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : defaultOptions;
@@ -21,31 +23,49 @@ export default function useCollapsibleAppBar() {
21
23
  const safeAreaInsets = useSafeAreaInsets();
22
24
  const [appBarHeight, onAppBarLayout] = useHeight();
23
25
  const [collapsibleToolbarHeight, onCollapsibleToolbarLayout] = useHeight();
24
- const maxTranslateY = useDerivedValue(() => -collapsibleToolbarHeight);
26
+ const maxTranslateY = useDerivedValue(() => -collapsibleToolbarHeight, [collapsibleToolbarHeight]);
25
27
  const translateY = useSharedValue(0);
26
28
  const lastTranslateY = useSharedValue(0);
27
29
  const lastOffsetY = useSharedValue(0);
28
30
  const overlapped = useSharedValue(false);
29
31
  const elevationStyle = useElevationStyle(4);
30
32
  const animatedStyle = useAnimatedStyle(() => {
31
- return Platform.OS === 'web' ? {
32
- transform: [{
33
- translateY: translateY.value
34
- }],
35
- boxShadow: overlapped.value ? elevationStyle === null || elevationStyle === void 0 ? void 0 : elevationStyle.boxShadow : 0
36
- } : {
37
- transform: [{
38
- translateY: translateY.value
39
- }],
40
- elevation: overlapped.value ? elevationStyle === null || elevationStyle === void 0 ? void 0 : elevationStyle.elevation : 0,
41
- shadowColor: elevationStyle === null || elevationStyle === void 0 ? void 0 : elevationStyle.shadowColor,
42
- shadowOffset: elevationStyle === null || elevationStyle === void 0 ? void 0 : elevationStyle.shadowOffset,
43
- shadowRadius: elevationStyle === null || elevationStyle === void 0 ? void 0 : elevationStyle.shadowRadius,
44
- shadowOpacity: overlapped.value ? elevationStyle === null || elevationStyle === void 0 ? void 0 : elevationStyle.shadowOpacity : 0
45
- };
46
- });
47
- const indexRef = React.useRef(0);
48
- const offsetsRef = React.useRef([]);
33
+ const transform = [{
34
+ translateY: translateY.value
35
+ }];
36
+
37
+ if (Platform.OS === 'web') {
38
+ return {
39
+ transform,
40
+ boxShadow: overlapped.value ? elevationStyle === null || elevationStyle === void 0 ? void 0 : elevationStyle.boxShadow : 0
41
+ };
42
+ }
43
+
44
+ if (Platform.OS === 'android') {
45
+ return {
46
+ transform,
47
+ elevation: overlapped.value ? elevationStyle === null || elevationStyle === void 0 ? void 0 : elevationStyle.elevation : 0
48
+ };
49
+ }
50
+
51
+ if (Platform.OS === 'ios') {
52
+ return {
53
+ transform,
54
+ shadowColor: elevationStyle === null || elevationStyle === void 0 ? void 0 : elevationStyle.shadowColor,
55
+ shadowOffset: elevationStyle === null || elevationStyle === void 0 ? void 0 : elevationStyle.shadowOffset,
56
+ shadowRadius: elevationStyle === null || elevationStyle === void 0 ? void 0 : elevationStyle.shadowRadius,
57
+ shadowOpacity: overlapped.value ? elevationStyle === null || elevationStyle === void 0 ? void 0 : elevationStyle.shadowOpacity : 0
58
+ };
59
+ }
60
+
61
+ return {};
62
+ }, [
63
+ /**
64
+ * FIXME: Consider add `elevationStyle` to dependencies.
65
+ */
66
+ ]);
67
+ const indexRef = useRef(0);
68
+ const offsetsRef = useRef([]);
49
69
 
50
70
  const onScrollViewChanged = nextIndex => {
51
71
  const prevIndex = indexRef.current;
@@ -62,9 +82,7 @@ export default function useCollapsibleAppBar() {
62
82
  overlapped.value = savedOffsetY > 0; // If next ScrollView's offset is too short, expand app bar.
63
83
 
64
84
  if (translateY.value < 0 && savedOffsetY < appBarHeight) {
65
- translateY.value = withTiming(0, {
66
- duration: ANIMATION_DURATION_MILLIS
67
- });
85
+ translateY.value = withTiming(0, ANIMATION_CONFIG);
68
86
  }
69
87
  };
70
88
 
@@ -91,15 +109,11 @@ export default function useCollapsibleAppBar() {
91
109
  } else {
92
110
  if (offsetY > -maxTy) {
93
111
  if (ty === 0) {
94
- translateY.value = withTiming(Math.min(Math.max(-offsetY, maxTy), 0), {
95
- duration: ANIMATION_DURATION_MILLIS
96
- });
112
+ translateY.value = withTiming(Math.min(Math.max(-offsetY, maxTy), 0), ANIMATION_CONFIG);
97
113
  }
98
114
  } else {
99
115
  if (ty === maxTy) {
100
- translateY.value = withTiming(0, {
101
- duration: ANIMATION_DURATION_MILLIS
102
- });
116
+ translateY.value = withTiming(0, ANIMATION_CONFIG);
103
117
  }
104
118
  }
105
119
 
@@ -123,11 +137,9 @@ export default function useCollapsibleAppBar() {
123
137
  const threshold = maxTy * 0.5;
124
138
  const nextTranslateY = ty > threshold || offsetY < appBarHeight ? 0 : maxTy;
125
139
  overlapped.value = offsetY + nextTranslateY > 0;
126
- translateY.value = withTiming(nextTranslateY, {
127
- duration: ANIMATION_DURATION_MILLIS
128
- });
140
+ translateY.value = withTiming(nextTranslateY, ANIMATION_CONFIG);
129
141
  }
130
- });
142
+ }, [keyboardDismissMode]);
131
143
  const hasCollapsible = collapsibleToolbarHeight > 0;
132
144
  const appBarStyle = [animatedStyle, {
133
145
  paddingTop: safeAreaInsets.top
@@ -1 +1 @@
1
- {"version":3,"names":["React","Keyboard","Platform","runOnJS","useAnimatedScrollHandler","useAnimatedStyle","useDerivedValue","useSharedValue","withTiming","useSafeAreaInsets","useHeight","useElevationStyle","useAppbarStyles","defaultOptions","keyboardDismissMode","ANIMATION_DURATION_MILLIS","SUPPORTS_DRAG_DETECTION","OS","useCollapsibleAppBar","userOptions","styles","safeAreaInsets","appBarHeight","onAppBarLayout","collapsibleToolbarHeight","onCollapsibleToolbarLayout","maxTranslateY","translateY","lastTranslateY","lastOffsetY","overlapped","elevationStyle","animatedStyle","transform","value","boxShadow","elevation","shadowColor","shadowOffset","shadowRadius","shadowOpacity","indexRef","useRef","offsetsRef","onScrollViewChanged","nextIndex","prevIndex","current","savedOffsetY","duration","scrollHandler","onBeginDrag","dismiss","onMomentumBegin","onScroll","event","offsetY","contentOffset","y","ty","maxTy","dy","Math","min","max","onEndDrag","onMomentumEnd","threshold","nextTranslateY","hasCollapsible","appBarStyle","paddingTop","top","floating","undefined","scrollContentInsets"],"sources":["useCollapsibleAppBar.ts"],"sourcesContent":["import React from 'react';\nimport { Falsy, Keyboard, Platform, RegisteredStyle, ScrollViewProps, ViewProps, ViewStyle } from 'react-native';\nimport {\n runOnJS,\n useAnimatedScrollHandler,\n useAnimatedStyle,\n useDerivedValue,\n useSharedValue,\n withTiming,\n} from 'react-native-reanimated';\nimport { useSafeAreaInsets } from 'react-native-safe-area-context';\nimport { useHeight } from '../internal/hooks';\nimport useElevationStyle from './useElevationStyle';\nimport useAppbarStyles from './useAppbarStyles';\n\ntype WebOnlyStyle = { boxShadow: any };\n\ntype ViewStyleProp = Array<ViewStyle | RegisteredStyle<ViewStyle> | WebOnlyStyle | Falsy>;\n\ntype OnScroll = ScrollViewProps['onScroll'];\n\ntype OnLayoutCallback = ViewProps['onLayout'];\n\nexport interface ContentInsets {\n top?: number;\n bottom?: number;\n left?: number;\n right?: number;\n}\n\nexport interface Options {\n keyboardDismissMode?: 'none' | 'on-drag';\n}\n\nexport interface CollapsibleAppBar {\n appBarStyle: ViewStyleProp;\n onAppBarLayout: OnLayoutCallback;\n onCollapsibleToolbarLayout: OnLayoutCallback;\n onScroll: OnScroll;\n onScrollViewChanged: (index: number) => void;\n scrollContentInsets: ContentInsets;\n}\n\nconst defaultOptions: Required<Options> = {\n keyboardDismissMode: 'none',\n};\n\nconst ANIMATION_DURATION_MILLIS = 100;\n\nconst SUPPORTS_DRAG_DETECTION = Platform.OS !== 'web';\n\nexport default function useCollapsibleAppBar(userOptions: Options = defaultOptions): CollapsibleAppBar {\n const { keyboardDismissMode }: Required<Options> = {\n ...defaultOptions,\n ...userOptions,\n };\n\n const styles = useAppbarStyles();\n\n const safeAreaInsets = useSafeAreaInsets();\n\n const [appBarHeight, onAppBarLayout] = useHeight();\n const [collapsibleToolbarHeight, onCollapsibleToolbarLayout] = useHeight();\n\n const maxTranslateY = useDerivedValue(() => -collapsibleToolbarHeight);\n\n const translateY = useSharedValue<number>(0);\n const lastTranslateY = useSharedValue<number>(0);\n const lastOffsetY = useSharedValue<number>(0);\n const overlapped = useSharedValue<boolean>(false);\n\n const elevationStyle = useElevationStyle(4);\n const animatedStyle = useAnimatedStyle(() => {\n return Platform.OS === 'web' ? ({\n transform: [{ translateY: translateY.value }],\n boxShadow: overlapped.value ? elevationStyle?.boxShadow : 0,\n }) : ({\n transform: [{ translateY: translateY.value }],\n elevation: overlapped.value ? elevationStyle?.elevation : 0,\n shadowColor: elevationStyle?.shadowColor,\n shadowOffset: elevationStyle?.shadowOffset,\n shadowRadius: elevationStyle?.shadowRadius,\n shadowOpacity: overlapped.value ? elevationStyle?.shadowOpacity : 0,\n });\n });\n\n const indexRef = React.useRef<number>(0);\n const offsetsRef = React.useRef<Array<number>>([]);\n\n const onScrollViewChanged = (nextIndex: number) => {\n const prevIndex = indexRef.current;\n if (prevIndex === nextIndex) {\n return;\n }\n\n offsetsRef.current[prevIndex] = lastOffsetY.value;\n\n const savedOffsetY = offsetsRef.current[nextIndex] ?? 0;\n lastOffsetY.value = savedOffsetY;\n\n indexRef.current = nextIndex;\n\n // Determine whether to overlap every time index is changed.\n overlapped.value = savedOffsetY > 0;\n\n // If next ScrollView's offset is too short, expand app bar.\n if (translateY.value < 0 && savedOffsetY < appBarHeight) {\n translateY.value = withTiming(0, {\n duration: ANIMATION_DURATION_MILLIS,\n });\n }\n };\n\n const scrollHandler = useAnimatedScrollHandler({\n onBeginDrag: () => {\n if (keyboardDismissMode === 'on-drag') {\n runOnJS(Keyboard.dismiss)();\n }\n lastTranslateY.value = translateY.value;\n },\n onMomentumBegin: () => {\n lastTranslateY.value = translateY.value;\n },\n onScroll: (event) => {\n const offsetY = event.contentOffset.y;\n\n const ty = translateY.value;\n const maxTy = maxTranslateY.value;\n\n if (SUPPORTS_DRAG_DETECTION) {\n const dy = offsetY - lastOffsetY.value;\n\n translateY.value = offsetY <= 0 ? 0 : Math.min(Math.max(lastTranslateY.value - dy, maxTy), 0);\n\n overlapped.value = offsetY + translateY.value > 0;\n } else {\n if (offsetY > -maxTy) {\n if (ty === 0) {\n translateY.value = withTiming(Math.min(Math.max(-offsetY, maxTy), 0), {\n duration: ANIMATION_DURATION_MILLIS,\n });\n }\n } else {\n if (ty === maxTy) {\n translateY.value = withTiming(0, {\n duration: ANIMATION_DURATION_MILLIS,\n });\n }\n }\n\n overlapped.value = offsetY > 0;\n\n lastOffsetY.value = offsetY;\n }\n },\n onEndDrag: (event) => {\n lastOffsetY.value = event.contentOffset.y;\n },\n onMomentumEnd: (event) => {\n const offsetY = event.contentOffset.y;\n\n lastOffsetY.value = offsetY;\n\n const ty = translateY.value;\n const maxTy = maxTranslateY.value;\n\n // If toolbar is already positioned on edge, do nothing.\n if (ty <= maxTy || ty >= 0) {\n return;\n }\n\n const threshold = maxTy * 0.5;\n\n const nextTranslateY = (ty > threshold || offsetY < appBarHeight) ? 0 : maxTy;\n\n overlapped.value = offsetY + nextTranslateY > 0;\n\n translateY.value = withTiming(nextTranslateY, {\n duration: ANIMATION_DURATION_MILLIS,\n });\n },\n });\n\n const hasCollapsible = collapsibleToolbarHeight > 0;\n\n const appBarStyle = [\n animatedStyle,\n { paddingTop: safeAreaInsets.top },\n hasCollapsible ? styles.floating : undefined,\n ];\n\n return {\n appBarStyle,\n onAppBarLayout,\n onCollapsibleToolbarLayout,\n onScroll: scrollHandler,\n onScrollViewChanged,\n scrollContentInsets: { top: hasCollapsible ? appBarHeight : 0 },\n };\n};\n"],"mappings":"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"}
1
+ {"version":3,"names":["useRef","Keyboard","Platform","runOnJS","useAnimatedScrollHandler","useAnimatedStyle","useDerivedValue","useSharedValue","withTiming","useSafeAreaInsets","useHeight","useElevationStyle","useAppbarStyles","defaultOptions","keyboardDismissMode","ANIMATION_CONFIG","duration","SUPPORTS_DRAG_DETECTION","OS","useCollapsibleAppBar","userOptions","styles","safeAreaInsets","appBarHeight","onAppBarLayout","collapsibleToolbarHeight","onCollapsibleToolbarLayout","maxTranslateY","translateY","lastTranslateY","lastOffsetY","overlapped","elevationStyle","animatedStyle","transform","value","boxShadow","elevation","shadowColor","shadowOffset","shadowRadius","shadowOpacity","indexRef","offsetsRef","onScrollViewChanged","nextIndex","prevIndex","current","savedOffsetY","scrollHandler","onBeginDrag","dismiss","onMomentumBegin","onScroll","event","offsetY","contentOffset","y","ty","maxTy","dy","Math","min","max","onEndDrag","onMomentumEnd","threshold","nextTranslateY","hasCollapsible","appBarStyle","paddingTop","top","floating","undefined","scrollContentInsets"],"sources":["useCollapsibleAppBar.ts"],"sourcesContent":["import { useRef } from 'react';\nimport { Falsy, Keyboard, Platform, RegisteredStyle, ScrollViewProps, ViewProps, ViewStyle } from 'react-native';\nimport type { WithTimingConfig } from 'react-native-reanimated';\nimport {\n runOnJS,\n useAnimatedScrollHandler,\n useAnimatedStyle,\n useDerivedValue,\n useSharedValue,\n withTiming,\n} from 'react-native-reanimated';\nimport { useSafeAreaInsets } from 'react-native-safe-area-context';\nimport { useHeight } from '../internal/hooks';\nimport useElevationStyle from './useElevationStyle';\nimport useAppbarStyles from './useAppbarStyles';\n\ntype WebOnlyStyle = { boxShadow: any };\n\ntype ViewStyleProp = Array<ViewStyle | RegisteredStyle<ViewStyle> | WebOnlyStyle | Falsy>;\n\ntype OnScroll = ScrollViewProps['onScroll'];\n\ntype OnLayoutCallback = ViewProps['onLayout'];\n\nexport interface ContentInsets {\n top?: number;\n bottom?: number;\n left?: number;\n right?: number;\n}\n\nexport interface Options {\n keyboardDismissMode?: 'none' | 'on-drag';\n}\n\nexport interface CollapsibleAppBar {\n appBarStyle: ViewStyleProp;\n onAppBarLayout: OnLayoutCallback;\n onCollapsibleToolbarLayout: OnLayoutCallback;\n onScroll: OnScroll;\n onScrollViewChanged: (index: number) => void;\n scrollContentInsets: ContentInsets;\n}\n\nconst defaultOptions: Required<Options> = {\n keyboardDismissMode: 'none',\n};\n\nconst ANIMATION_CONFIG: Readonly<WithTimingConfig> = { duration: 100 };\n\nconst SUPPORTS_DRAG_DETECTION = Platform.OS !== 'web';\n\nexport default function useCollapsibleAppBar(userOptions: Options = defaultOptions): CollapsibleAppBar {\n const { keyboardDismissMode }: Required<Options> = {\n ...defaultOptions,\n ...userOptions,\n };\n\n const styles = useAppbarStyles();\n\n const safeAreaInsets = useSafeAreaInsets();\n\n const [appBarHeight, onAppBarLayout] = useHeight();\n const [collapsibleToolbarHeight, onCollapsibleToolbarLayout] = useHeight();\n\n const maxTranslateY = useDerivedValue(() => -collapsibleToolbarHeight, [collapsibleToolbarHeight]);\n\n const translateY = useSharedValue<number>(0);\n const lastTranslateY = useSharedValue<number>(0);\n const lastOffsetY = useSharedValue<number>(0);\n const overlapped = useSharedValue<boolean>(false);\n\n const elevationStyle = useElevationStyle(4);\n const animatedStyle = useAnimatedStyle(() => {\n const transform = [{ translateY: translateY.value }];\n\n if (Platform.OS === 'web') {\n return {\n transform,\n boxShadow: overlapped.value ? elevationStyle?.boxShadow : 0,\n };\n }\n if (Platform.OS === 'android') {\n return {\n transform,\n elevation: overlapped.value ? elevationStyle?.elevation : 0,\n };\n }\n if (Platform.OS === 'ios') {\n return {\n transform,\n shadowColor: elevationStyle?.shadowColor,\n shadowOffset: elevationStyle?.shadowOffset,\n shadowRadius: elevationStyle?.shadowRadius,\n shadowOpacity: overlapped.value ? elevationStyle?.shadowOpacity : 0,\n };\n }\n return {};\n }, [\n /**\n * FIXME: Consider add `elevationStyle` to dependencies.\n */\n ]);\n\n const indexRef = useRef<number>(0);\n const offsetsRef = useRef<Array<number>>([]);\n\n const onScrollViewChanged = (nextIndex: number) => {\n const prevIndex = indexRef.current;\n if (prevIndex === nextIndex) {\n return;\n }\n\n offsetsRef.current[prevIndex] = lastOffsetY.value;\n\n const savedOffsetY = offsetsRef.current[nextIndex] ?? 0;\n lastOffsetY.value = savedOffsetY;\n\n indexRef.current = nextIndex;\n\n // Determine whether to overlap every time index is changed.\n overlapped.value = savedOffsetY > 0;\n\n // If next ScrollView's offset is too short, expand app bar.\n if (translateY.value < 0 && savedOffsetY < appBarHeight) {\n translateY.value = withTiming(0, ANIMATION_CONFIG);\n }\n };\n\n const scrollHandler = useAnimatedScrollHandler({\n onBeginDrag: () => {\n if (keyboardDismissMode === 'on-drag') {\n runOnJS(Keyboard.dismiss)();\n }\n lastTranslateY.value = translateY.value;\n },\n onMomentumBegin: () => {\n lastTranslateY.value = translateY.value;\n },\n onScroll: (event) => {\n const offsetY = event.contentOffset.y;\n\n const ty = translateY.value;\n const maxTy = maxTranslateY.value;\n\n if (SUPPORTS_DRAG_DETECTION) {\n const dy = offsetY - lastOffsetY.value;\n\n translateY.value = offsetY <= 0 ? 0 : Math.min(Math.max(lastTranslateY.value - dy, maxTy), 0);\n\n overlapped.value = offsetY + translateY.value > 0;\n } else {\n if (offsetY > -maxTy) {\n if (ty === 0) {\n translateY.value = withTiming(Math.min(Math.max(-offsetY, maxTy), 0), ANIMATION_CONFIG);\n }\n } else {\n if (ty === maxTy) {\n translateY.value = withTiming(0, ANIMATION_CONFIG);\n }\n }\n\n overlapped.value = offsetY > 0;\n\n lastOffsetY.value = offsetY;\n }\n },\n onEndDrag: (event) => {\n lastOffsetY.value = event.contentOffset.y;\n },\n onMomentumEnd: (event) => {\n const offsetY = event.contentOffset.y;\n\n lastOffsetY.value = offsetY;\n\n const ty = translateY.value;\n const maxTy = maxTranslateY.value;\n\n // If toolbar is already positioned on edge, do nothing.\n if (ty <= maxTy || ty >= 0) {\n return;\n }\n\n const threshold = maxTy * 0.5;\n\n const nextTranslateY = (ty > threshold || offsetY < appBarHeight) ? 0 : maxTy;\n\n overlapped.value = offsetY + nextTranslateY > 0;\n\n translateY.value = withTiming(nextTranslateY, ANIMATION_CONFIG);\n },\n }, [keyboardDismissMode]);\n\n const hasCollapsible = collapsibleToolbarHeight > 0;\n\n const appBarStyle = [\n animatedStyle,\n { paddingTop: safeAreaInsets.top },\n hasCollapsible ? styles.floating : undefined,\n ];\n\n return {\n appBarStyle,\n onAppBarLayout,\n onCollapsibleToolbarLayout,\n onScroll: scrollHandler,\n onScrollViewChanged,\n scrollContentInsets: { top: hasCollapsible ? appBarHeight : 0 },\n };\n};\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import { useMemo } from 'react';
2
2
  import { Keyboard, Platform } from 'react-native';
3
3
  import { runOnJS, useAnimatedScrollHandler, useAnimatedStyle, useSharedValue } from 'react-native-reanimated';
4
4
  import { useSafeAreaInsets } from 'react-native-safe-area-context';
@@ -30,7 +30,7 @@ export default function useFadeInAppBar() {
30
30
  const styles = useAppbarStyles();
31
31
  const safeAreaInsets = useSafeAreaInsets();
32
32
  const [appBarHeight, onAppBarLayout] = useHeight();
33
- const [fromOffsetY, toOffsetY] = React.useMemo(() => {
33
+ const [fromOffsetY, toOffsetY] = useMemo(() => {
34
34
  const endY = typeof fadeInEndY === 'function' ? fadeInEndY(appBarHeight) : fadeInEndY;
35
35
  const beginY = typeof fadeInBeginY === 'function' ? fadeInBeginY(endY, appBarHeight) : fadeInBeginY;
36
36
  return [beginY, endY];
@@ -38,19 +38,40 @@ export default function useFadeInAppBar() {
38
38
  const dy = useSharedValue(0);
39
39
  const lastOffsetY = useSharedValue(0);
40
40
  const normalized = useSharedValue(0);
41
- const backgroundColor = theme.palette.background.default;
42
- const [r, g, b] = React.useMemo(() => rgb(backgroundColor), [backgroundColor]);
43
- const animatedAppBarStyle = useAnimatedStyle(() => ({
44
- backgroundColor: `rgba(${r}, ${g}, ${b}, ${normalized.value})`,
45
- elevation: normalized.value >= 1 ? 6 : 0,
46
- shadowColor: '#000',
47
- shadowOffset,
48
- shadowRadius: 4.65,
49
- shadowOpacity: normalized.value >= 1 ? 0.25 : 0
50
- }));
41
+ const originalBackgroundColor = theme.palette.background.default;
42
+ const rgbValues = useMemo(() => rgb(originalBackgroundColor), [originalBackgroundColor]);
43
+ const animatedAppBarStyle = useAnimatedStyle(() => {
44
+ const [r, g, b] = rgbValues;
45
+ const backgroundColor = `rgba(${r}, ${g}, ${b}, ${normalized.value})`;
46
+
47
+ if (Platform.OS === 'web') {
48
+ return {
49
+ backgroundColor
50
+ };
51
+ }
52
+
53
+ if (Platform.OS === 'android') {
54
+ return {
55
+ backgroundColor,
56
+ elevation: normalized.value >= 1 ? 6 : 0
57
+ };
58
+ }
59
+
60
+ if (Platform.OS === 'ios') {
61
+ return {
62
+ backgroundColor,
63
+ shadowColor: '#000',
64
+ shadowOffset,
65
+ shadowRadius: 4.65,
66
+ shadowOpacity: normalized.value >= 1 ? 0.25 : 0
67
+ };
68
+ }
69
+
70
+ return {};
71
+ }, [rgbValues]);
51
72
  const animatedTitleStyle = useAnimatedStyle(() => ({
52
73
  opacity: normalized.value
53
- }));
74
+ }), []);
54
75
  const scrollHandler = useAnimatedScrollHandler({
55
76
  onBeginDrag: () => {
56
77
  if (keyboardDismissMode === 'on-drag') {
@@ -70,7 +91,7 @@ export default function useFadeInAppBar() {
70
91
  onMomentumEnd: event => {
71
92
  lastOffsetY.value = event.contentOffset.y;
72
93
  }
73
- });
94
+ }, [keyboardDismissMode]);
74
95
  const appBarStyle = [animatedAppBarStyle, {
75
96
  paddingTop: safeAreaInsets.top
76
97
  }, floating ? styles.floating : undefined];
@@ -1 +1 @@
1
- {"version":3,"names":["React","Keyboard","Platform","runOnJS","useAnimatedScrollHandler","useAnimatedStyle","useSharedValue","useSafeAreaInsets","rgb","useHeight","useTheme","useAppbarStyles","defaultOptions","fadeInBeginY","endY","appBarHeight","fadeInEndY","floating","keyboardDismissMode","shadowOffset","OS","width","height","undefined","useFadeInAppBar","userOptions","theme","styles","safeAreaInsets","onAppBarLayout","fromOffsetY","toOffsetY","useMemo","beginY","dy","lastOffsetY","normalized","backgroundColor","palette","background","default","r","g","b","animatedAppBarStyle","value","elevation","shadowColor","shadowRadius","shadowOpacity","animatedTitleStyle","opacity","scrollHandler","onBeginDrag","dismiss","onScroll","event","offsetY","contentOffset","y","distance","Math","max","localOffsetY","min","onEndDrag","onMomentumEnd","appBarStyle","paddingTop","top","titleStyle"],"sources":["useFadeInAppBar.ts"],"sourcesContent":["import React from 'react';\nimport { Falsy, Keyboard, Platform, RegisteredStyle, ScrollViewProps, ViewProps, ViewStyle } from 'react-native';\nimport type { SharedValue } from 'react-native-reanimated';\nimport { runOnJS, useAnimatedScrollHandler, useAnimatedStyle, useSharedValue } from 'react-native-reanimated';\nimport { useSafeAreaInsets } from 'react-native-safe-area-context';\nimport { rgb } from '@fountain-ui/utils';\nimport { useHeight } from '../internal/hooks';\nimport { useTheme } from '../styles';\nimport useAppbarStyles from './useAppbarStyles';\n\ntype ViewStyleProp = Array<ViewStyle | RegisteredStyle<ViewStyle> | Falsy>;\n\ntype OnScroll = ScrollViewProps['onScroll'];\n\ntype OnLayoutCallback = ViewProps['onLayout'];\n\nexport interface Options {\n fadeInBeginY?: number | ((endY: number, appBarHeight: number) => number);\n fadeInEndY?: number | ((appBarHeight: number) => number);\n floating?: boolean;\n keyboardDismissMode?: 'none' | 'on-drag';\n}\n\nexport interface FadeInAppBar {\n appBarStyle: ViewStyleProp;\n titleStyle: ViewStyleProp;\n onAppBarLayout: OnLayoutCallback;\n onScroll: OnScroll;\n dy: SharedValue<number>;\n normalized: SharedValue<number>;\n}\n\nconst defaultOptions: Required<Options> = {\n fadeInBeginY: (endY, appBarHeight) => endY - appBarHeight,\n fadeInEndY: (appBarHeight) => appBarHeight,\n floating: true,\n keyboardDismissMode: 'none',\n};\n\nconst shadowOffset = Platform.OS === 'ios' ? { width: 0, height: 3 } : undefined;\n\nexport default function useFadeInAppBar(userOptions: Options = defaultOptions): FadeInAppBar {\n const {\n fadeInBeginY,\n fadeInEndY,\n floating,\n keyboardDismissMode,\n }: Required<Options> = {\n ...defaultOptions,\n ...userOptions,\n };\n\n const theme = useTheme();\n\n const styles = useAppbarStyles();\n\n const safeAreaInsets = useSafeAreaInsets();\n\n const [appBarHeight, onAppBarLayout] = useHeight();\n\n const [fromOffsetY, toOffsetY] = React.useMemo(() => {\n const endY = typeof fadeInEndY === 'function'\n ? fadeInEndY(appBarHeight)\n : fadeInEndY;\n\n const beginY = typeof fadeInBeginY === 'function'\n ? fadeInBeginY(endY, appBarHeight)\n : fadeInBeginY;\n\n return [beginY, endY];\n }, [fadeInBeginY, fadeInBeginY, appBarHeight]);\n\n const dy = useSharedValue<number>(0);\n const lastOffsetY = useSharedValue<number>(0);\n const normalized = useSharedValue<number>(0);\n\n const backgroundColor = theme.palette.background.default;\n const [r, g, b] = React.useMemo(() => rgb(backgroundColor), [backgroundColor]);\n\n const animatedAppBarStyle = useAnimatedStyle(() => ({\n backgroundColor: `rgba(${r}, ${g}, ${b}, ${normalized.value})`,\n elevation: normalized.value >= 1 ? 6 : 0,\n shadowColor: '#000',\n shadowOffset,\n shadowRadius: 4.65,\n shadowOpacity: normalized.value >= 1 ? 0.25 : 0,\n }));\n\n const animatedTitleStyle = useAnimatedStyle(() => ({\n opacity: normalized.value,\n }));\n\n const scrollHandler = useAnimatedScrollHandler({\n onBeginDrag: () => {\n if (keyboardDismissMode === 'on-drag') {\n runOnJS(Keyboard.dismiss)();\n }\n },\n onScroll: (event) => {\n const offsetY = event.contentOffset.y;\n\n const distance = Math.max(toOffsetY - fromOffsetY, 1);\n const localOffsetY = offsetY - fromOffsetY;\n\n dy.value = offsetY - lastOffsetY.value;\n\n normalized.value = Math.min(Math.max(localOffsetY / distance, 0), 1);\n },\n onEndDrag: (event) => {\n lastOffsetY.value = event.contentOffset.y;\n },\n onMomentumEnd: (event) => {\n lastOffsetY.value = event.contentOffset.y;\n },\n });\n\n const appBarStyle = [\n animatedAppBarStyle,\n { paddingTop: safeAreaInsets.top },\n floating ? styles.floating : undefined,\n ];\n\n return {\n appBarStyle,\n titleStyle: [animatedTitleStyle],\n onAppBarLayout,\n onScroll: scrollHandler,\n dy,\n normalized,\n };\n};\n"],"mappings":"AAAA,OAAOA,KAAP,MAAkB,OAAlB;AACA,SAAgBC,QAAhB,EAA0BC,QAA1B,QAAkG,cAAlG;AAEA,SAASC,OAAT,EAAkBC,wBAAlB,EAA4CC,gBAA5C,EAA8DC,cAA9D,QAAoF,yBAApF;AACA,SAASC,iBAAT,QAAkC,gCAAlC;AACA,SAASC,GAAT,QAAoB,oBAApB;AACA,SAASC,SAAT,QAA0B,mBAA1B;AACA,SAASC,QAAT,QAAyB,WAAzB;AACA,OAAOC,eAAP,MAA4B,mBAA5B;AAwBA,MAAMC,cAAiC,GAAG;EACtCC,YAAY,EAAE,CAACC,IAAD,EAAOC,YAAP,KAAwBD,IAAI,GAAGC,YADP;EAEtCC,UAAU,EAAGD,YAAD,IAAkBA,YAFQ;EAGtCE,QAAQ,EAAE,IAH4B;EAItCC,mBAAmB,EAAE;AAJiB,CAA1C;AAOA,MAAMC,YAAY,GAAGjB,QAAQ,CAACkB,EAAT,KAAgB,KAAhB,GAAwB;EAAEC,KAAK,EAAE,CAAT;EAAYC,MAAM,EAAE;AAApB,CAAxB,GAAkDC,SAAvE;AAEA,eAAe,SAASC,eAAT,GAA8E;EAAA,IAArDC,WAAqD,uEAA9Bb,cAA8B;EACzF,MAAM;IACFC,YADE;IAEFG,UAFE;IAGFC,QAHE;IAIFC;EAJE,IAKiB,EACnB,GAAGN,cADgB;IAEnB,GAAGa;EAFgB,CALvB;EAUA,MAAMC,KAAK,GAAGhB,QAAQ,EAAtB;EAEA,MAAMiB,MAAM,GAAGhB,eAAe,EAA9B;EAEA,MAAMiB,cAAc,GAAGrB,iBAAiB,EAAxC;EAEA,MAAM,CAACQ,YAAD,EAAec,cAAf,IAAiCpB,SAAS,EAAhD;EAEA,MAAM,CAACqB,WAAD,EAAcC,SAAd,IAA2B/B,KAAK,CAACgC,OAAN,CAAc,MAAM;IACjD,MAAMlB,IAAI,GAAG,OAAOE,UAAP,KAAsB,UAAtB,GACPA,UAAU,CAACD,YAAD,CADH,GAEPC,UAFN;IAIA,MAAMiB,MAAM,GAAG,OAAOpB,YAAP,KAAwB,UAAxB,GACTA,YAAY,CAACC,IAAD,EAAOC,YAAP,CADH,GAETF,YAFN;IAIA,OAAO,CAACoB,MAAD,EAASnB,IAAT,CAAP;EACH,CAVgC,EAU9B,CAACD,YAAD,EAAeA,YAAf,EAA6BE,YAA7B,CAV8B,CAAjC;EAYA,MAAMmB,EAAE,GAAG5B,cAAc,CAAS,CAAT,CAAzB;EACA,MAAM6B,WAAW,GAAG7B,cAAc,CAAS,CAAT,CAAlC;EACA,MAAM8B,UAAU,GAAG9B,cAAc,CAAS,CAAT,CAAjC;EAEA,MAAM+B,eAAe,GAAGX,KAAK,CAACY,OAAN,CAAcC,UAAd,CAAyBC,OAAjD;EACA,MAAM,CAACC,CAAD,EAAIC,CAAJ,EAAOC,CAAP,IAAY3C,KAAK,CAACgC,OAAN,CAAc,MAAMxB,GAAG,CAAC6B,eAAD,CAAvB,EAA0C,CAACA,eAAD,CAA1C,CAAlB;EAEA,MAAMO,mBAAmB,GAAGvC,gBAAgB,CAAC,OAAO;IAChDgC,eAAe,EAAG,QAAOI,CAAE,KAAIC,CAAE,KAAIC,CAAE,KAAIP,UAAU,CAACS,KAAM,GADZ;IAEhDC,SAAS,EAAEV,UAAU,CAACS,KAAX,IAAoB,CAApB,GAAwB,CAAxB,GAA4B,CAFS;IAGhDE,WAAW,EAAE,MAHmC;IAIhD5B,YAJgD;IAKhD6B,YAAY,EAAE,IALkC;IAMhDC,aAAa,EAAEb,UAAU,CAACS,KAAX,IAAoB,CAApB,GAAwB,IAAxB,GAA+B;EANE,CAAP,CAAD,CAA5C;EASA,MAAMK,kBAAkB,GAAG7C,gBAAgB,CAAC,OAAO;IAC/C8C,OAAO,EAAEf,UAAU,CAACS;EAD2B,CAAP,CAAD,CAA3C;EAIA,MAAMO,aAAa,GAAGhD,wBAAwB,CAAC;IAC3CiD,WAAW,EAAE,MAAM;MACf,IAAInC,mBAAmB,KAAK,SAA5B,EAAuC;QACnCf,OAAO,CAACF,QAAQ,CAACqD,OAAV,CAAP;MACH;IACJ,CAL0C;IAM3CC,QAAQ,EAAGC,KAAD,IAAW;MACjB,MAAMC,OAAO,GAAGD,KAAK,CAACE,aAAN,CAAoBC,CAApC;MAEA,MAAMC,QAAQ,GAAGC,IAAI,CAACC,GAAL,CAAS/B,SAAS,GAAGD,WAArB,EAAkC,CAAlC,CAAjB;MACA,MAAMiC,YAAY,GAAGN,OAAO,GAAG3B,WAA/B;MAEAI,EAAE,CAACW,KAAH,GAAWY,OAAO,GAAGtB,WAAW,CAACU,KAAjC;MAEAT,UAAU,CAACS,KAAX,GAAmBgB,IAAI,CAACG,GAAL,CAASH,IAAI,CAACC,GAAL,CAASC,YAAY,GAAGH,QAAxB,EAAkC,CAAlC,CAAT,EAA+C,CAA/C,CAAnB;IACH,CAf0C;IAgB3CK,SAAS,EAAGT,KAAD,IAAW;MAClBrB,WAAW,CAACU,KAAZ,GAAoBW,KAAK,CAACE,aAAN,CAAoBC,CAAxC;IACH,CAlB0C;IAmB3CO,aAAa,EAAGV,KAAD,IAAW;MACtBrB,WAAW,CAACU,KAAZ,GAAoBW,KAAK,CAACE,aAAN,CAAoBC,CAAxC;IACH;EArB0C,CAAD,CAA9C;EAwBA,MAAMQ,WAAW,GAAG,CAChBvB,mBADgB,EAEhB;IAAEwB,UAAU,EAAExC,cAAc,CAACyC;EAA7B,CAFgB,EAGhBpD,QAAQ,GAAGU,MAAM,CAACV,QAAV,GAAqBM,SAHb,CAApB;EAMA,OAAO;IACH4C,WADG;IAEHG,UAAU,EAAE,CAACpB,kBAAD,CAFT;IAGHrB,cAHG;IAIH0B,QAAQ,EAAEH,aAJP;IAKHlB,EALG;IAMHE;EANG,CAAP;AAQH;AAAA"}
1
+ {"version":3,"names":["useMemo","Keyboard","Platform","runOnJS","useAnimatedScrollHandler","useAnimatedStyle","useSharedValue","useSafeAreaInsets","rgb","useHeight","useTheme","useAppbarStyles","defaultOptions","fadeInBeginY","endY","appBarHeight","fadeInEndY","floating","keyboardDismissMode","shadowOffset","OS","width","height","undefined","useFadeInAppBar","userOptions","theme","styles","safeAreaInsets","onAppBarLayout","fromOffsetY","toOffsetY","beginY","dy","lastOffsetY","normalized","originalBackgroundColor","palette","background","default","rgbValues","animatedAppBarStyle","r","g","b","backgroundColor","value","elevation","shadowColor","shadowRadius","shadowOpacity","animatedTitleStyle","opacity","scrollHandler","onBeginDrag","dismiss","onScroll","event","offsetY","contentOffset","y","distance","Math","max","localOffsetY","min","onEndDrag","onMomentumEnd","appBarStyle","paddingTop","top","titleStyle"],"sources":["useFadeInAppBar.ts"],"sourcesContent":["import { useMemo } from 'react';\nimport { Falsy, Keyboard, Platform, RegisteredStyle, ScrollViewProps, ViewProps, ViewStyle } from 'react-native';\nimport type { SharedValue } from 'react-native-reanimated';\nimport { runOnJS, useAnimatedScrollHandler, useAnimatedStyle, useSharedValue } from 'react-native-reanimated';\nimport { useSafeAreaInsets } from 'react-native-safe-area-context';\nimport { rgb } from '@fountain-ui/utils';\nimport { useHeight } from '../internal/hooks';\nimport { useTheme } from '../styles';\nimport useAppbarStyles from './useAppbarStyles';\n\ntype ViewStyleProp = Array<ViewStyle | RegisteredStyle<ViewStyle> | Falsy>;\n\ntype OnScroll = ScrollViewProps['onScroll'];\n\ntype OnLayoutCallback = ViewProps['onLayout'];\n\nexport interface Options {\n fadeInBeginY?: number | ((endY: number, appBarHeight: number) => number);\n fadeInEndY?: number | ((appBarHeight: number) => number);\n floating?: boolean;\n keyboardDismissMode?: 'none' | 'on-drag';\n}\n\nexport interface FadeInAppBar {\n appBarStyle: ViewStyleProp;\n titleStyle: ViewStyleProp;\n onAppBarLayout: OnLayoutCallback;\n onScroll: OnScroll;\n dy: SharedValue<number>;\n normalized: SharedValue<number>;\n}\n\nconst defaultOptions: Required<Options> = {\n fadeInBeginY: (endY, appBarHeight) => endY - appBarHeight,\n fadeInEndY: (appBarHeight) => appBarHeight,\n floating: true,\n keyboardDismissMode: 'none',\n};\n\nconst shadowOffset = Platform.OS === 'ios' ? { width: 0, height: 3 } : undefined;\n\nexport default function useFadeInAppBar(userOptions: Options = defaultOptions): FadeInAppBar {\n const {\n fadeInBeginY,\n fadeInEndY,\n floating,\n keyboardDismissMode,\n }: Required<Options> = {\n ...defaultOptions,\n ...userOptions,\n };\n\n const theme = useTheme();\n\n const styles = useAppbarStyles();\n\n const safeAreaInsets = useSafeAreaInsets();\n\n const [appBarHeight, onAppBarLayout] = useHeight();\n\n const [fromOffsetY, toOffsetY] = useMemo(() => {\n const endY = typeof fadeInEndY === 'function'\n ? fadeInEndY(appBarHeight)\n : fadeInEndY;\n\n const beginY = typeof fadeInBeginY === 'function'\n ? fadeInBeginY(endY, appBarHeight)\n : fadeInBeginY;\n\n return [beginY, endY];\n }, [fadeInBeginY, fadeInBeginY, appBarHeight]);\n\n const dy = useSharedValue<number>(0);\n const lastOffsetY = useSharedValue<number>(0);\n const normalized = useSharedValue<number>(0);\n\n const originalBackgroundColor = theme.palette.background.default;\n const rgbValues = useMemo(() => rgb(originalBackgroundColor), [originalBackgroundColor]);\n\n const animatedAppBarStyle = useAnimatedStyle(() => {\n const [r, g, b] = rgbValues;\n const backgroundColor = `rgba(${r}, ${g}, ${b}, ${normalized.value})`;\n\n if (Platform.OS === 'web') {\n return { backgroundColor };\n }\n if (Platform.OS === 'android') {\n return {\n backgroundColor,\n elevation: normalized.value >= 1 ? 6 : 0,\n };\n }\n if (Platform.OS === 'ios') {\n return {\n backgroundColor,\n shadowColor: '#000',\n shadowOffset,\n shadowRadius: 4.65,\n shadowOpacity: normalized.value >= 1 ? 0.25 : 0,\n };\n }\n return {};\n }, [rgbValues]);\n\n const animatedTitleStyle = useAnimatedStyle(() => ({\n opacity: normalized.value,\n }), []);\n\n const scrollHandler = useAnimatedScrollHandler({\n onBeginDrag: () => {\n if (keyboardDismissMode === 'on-drag') {\n runOnJS(Keyboard.dismiss)();\n }\n },\n onScroll: (event) => {\n const offsetY = event.contentOffset.y;\n\n const distance = Math.max(toOffsetY - fromOffsetY, 1);\n const localOffsetY = offsetY - fromOffsetY;\n\n dy.value = offsetY - lastOffsetY.value;\n\n normalized.value = Math.min(Math.max(localOffsetY / distance, 0), 1);\n },\n onEndDrag: (event) => {\n lastOffsetY.value = event.contentOffset.y;\n },\n onMomentumEnd: (event) => {\n lastOffsetY.value = event.contentOffset.y;\n },\n }, [keyboardDismissMode]);\n\n const appBarStyle = [\n animatedAppBarStyle,\n { paddingTop: safeAreaInsets.top },\n floating ? styles.floating : undefined,\n ];\n\n return {\n appBarStyle,\n titleStyle: [animatedTitleStyle],\n onAppBarLayout,\n onScroll: scrollHandler,\n dy,\n normalized,\n };\n};\n"],"mappings":"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"}
@@ -1,11 +1,11 @@
1
- import React from 'react';
1
+ import { useCallback, useRef } from 'react';
2
2
  export default function useThrottle(options) {
3
3
  const {
4
4
  periodMillis,
5
5
  callback
6
6
  } = options;
7
- const lastExecMillisRef = React.useRef(0);
8
- return React.useCallback(function () {
7
+ const lastExecMillisRef = useRef(0);
8
+ return useCallback(function () {
9
9
  const now = Date.now();
10
10
  const millisAfterExecuted = now - lastExecMillisRef.current;
11
11
  lastExecMillisRef.current = now;
@@ -1 +1 @@
1
- {"version":3,"names":["React","useThrottle","options","periodMillis","callback","lastExecMillisRef","useRef","useCallback","now","Date","millisAfterExecuted","current"],"sources":["useThrottle.ts"],"sourcesContent":["import React from 'react';\n\nexport interface ThrottleOptions {\n periodMillis: number;\n callback?: (args?: any) => void;\n}\n\nexport default function useThrottle(options: ThrottleOptions) {\n const { periodMillis, callback } = options;\n\n const lastExecMillisRef = React.useRef(0);\n\n return React.useCallback((...args: any[]) => {\n const now = Date.now();\n const millisAfterExecuted = now - lastExecMillisRef.current;\n lastExecMillisRef.current = now;\n\n if (millisAfterExecuted > periodMillis || periodMillis <= 0) {\n if (callback) {\n callback(...args);\n }\n }\n }, [callback, periodMillis]);\n}\n"],"mappings":"AAAA,OAAOA,KAAP,MAAkB,OAAlB;AAOA,eAAe,SAASC,WAAT,CAAqBC,OAArB,EAA+C;EAC1D,MAAM;IAAEC,YAAF;IAAgBC;EAAhB,IAA6BF,OAAnC;EAEA,MAAMG,iBAAiB,GAAGL,KAAK,CAACM,MAAN,CAAa,CAAb,CAA1B;EAEA,OAAON,KAAK,CAACO,WAAN,CAAkB,YAAoB;IACzC,MAAMC,GAAG,GAAGC,IAAI,CAACD,GAAL,EAAZ;IACA,MAAME,mBAAmB,GAAGF,GAAG,GAAGH,iBAAiB,CAACM,OAApD;IACAN,iBAAiB,CAACM,OAAlB,GAA4BH,GAA5B;;IAEA,IAAIE,mBAAmB,GAAGP,YAAtB,IAAsCA,YAAY,IAAI,CAA1D,EAA6D;MACzD,IAAIC,QAAJ,EAAc;QACVA,QAAQ,CAAC,YAAD,CAAR;MACH;IACJ;EACJ,CAVM,EAUJ,CAACA,QAAD,EAAWD,YAAX,CAVI,CAAP;AAWH"}
1
+ {"version":3,"names":["useCallback","useRef","useThrottle","options","periodMillis","callback","lastExecMillisRef","now","Date","millisAfterExecuted","current"],"sources":["useThrottle.ts"],"sourcesContent":["import { useCallback, useRef } from 'react';\n\nexport interface ThrottleOptions {\n periodMillis: number;\n callback?: (args?: any) => void;\n}\n\nexport default function useThrottle(options: ThrottleOptions) {\n const { periodMillis, callback } = options;\n\n const lastExecMillisRef = useRef(0);\n\n return useCallback((...args: any[]) => {\n const now = Date.now();\n const millisAfterExecuted = now - lastExecMillisRef.current;\n lastExecMillisRef.current = now;\n\n if (millisAfterExecuted > periodMillis || periodMillis <= 0) {\n if (callback) {\n callback(...args);\n }\n }\n }, [callback, periodMillis]);\n}\n"],"mappings":"AAAA,SAASA,WAAT,EAAsBC,MAAtB,QAAoC,OAApC;AAOA,eAAe,SAASC,WAAT,CAAqBC,OAArB,EAA+C;EAC1D,MAAM;IAAEC,YAAF;IAAgBC;EAAhB,IAA6BF,OAAnC;EAEA,MAAMG,iBAAiB,GAAGL,MAAM,CAAC,CAAD,CAAhC;EAEA,OAAOD,WAAW,CAAC,YAAoB;IACnC,MAAMO,GAAG,GAAGC,IAAI,CAACD,GAAL,EAAZ;IACA,MAAME,mBAAmB,GAAGF,GAAG,GAAGD,iBAAiB,CAACI,OAApD;IACAJ,iBAAiB,CAACI,OAAlB,GAA4BH,GAA5B;;IAEA,IAAIE,mBAAmB,GAAGL,YAAtB,IAAsCA,YAAY,IAAI,CAA1D,EAA6D;MACzD,IAAIC,QAAJ,EAAc;QACVA,QAAQ,CAAC,YAAD,CAAR;MACH;IACJ;EACJ,CAViB,EAUf,CAACA,QAAD,EAAWD,YAAX,CAVe,CAAlB;AAWH"}
@@ -1,3 +1,2 @@
1
1
  export { default as useHeight } from './useHeight';
2
- export { default as useWidth } from './useWidth';
3
2
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["default","useHeight","useWidth"],"sources":["index.ts"],"sourcesContent":["export { default as useHeight } from './useHeight';\nexport { default as useWidth } from './useWidth';\n"],"mappings":"AAAA,SAASA,OAAO,IAAIC,SAApB,QAAqC,aAArC;AACA,SAASD,OAAO,IAAIE,QAApB,QAAoC,YAApC"}
1
+ {"version":3,"names":["default","useHeight"],"sources":["index.ts"],"sourcesContent":["export { default as useHeight } from './useHeight';\n"],"mappings":"AAAA,SAASA,OAAO,IAAIC,SAApB,QAAqC,aAArC"}
@@ -1,8 +1,8 @@
1
- import React from 'react';
1
+ import { useState } from 'react';
2
2
  import { useWorkletCallback } from 'react-native-reanimated';
3
3
  export default function useHeight() {
4
4
  let initialHeight = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
5
- const [height, setHeight] = React.useState(initialHeight);
5
+ const [height, setHeight] = useState(initialHeight);
6
6
  const onLayout = useWorkletCallback(e => {
7
7
  setHeight(e.nativeEvent.layout.height);
8
8
  }, []);
@@ -1 +1 @@
1
- {"version":3,"names":["React","useWorkletCallback","useHeight","initialHeight","height","setHeight","useState","onLayout","e","nativeEvent","layout"],"sources":["useHeight.ts"],"sourcesContent":["import React from 'react';\nimport { ViewProps } from 'react-native';\nimport { useWorkletCallback } from 'react-native-reanimated';\n\ntype OnLayoutCallback = ViewProps['onLayout'];\n\nexport default function useHeight(initialHeight = 0): [number, OnLayoutCallback] {\n const [height, setHeight] = React.useState<number>(initialHeight);\n\n const onLayout = useWorkletCallback((e) => {\n setHeight(e.nativeEvent.layout.height);\n }, []);\n\n return [height, onLayout];\n};\n"],"mappings":"AAAA,OAAOA,KAAP,MAAkB,OAAlB;AAEA,SAASC,kBAAT,QAAmC,yBAAnC;AAIA,eAAe,SAASC,SAAT,GAAkE;EAAA,IAA/CC,aAA+C,uEAA/B,CAA+B;EAC7E,MAAM,CAACC,MAAD,EAASC,SAAT,IAAsBL,KAAK,CAACM,QAAN,CAAuBH,aAAvB,CAA5B;EAEA,MAAMI,QAAQ,GAAGN,kBAAkB,CAAEO,CAAD,IAAO;IACvCH,SAAS,CAACG,CAAC,CAACC,WAAF,CAAcC,MAAd,CAAqBN,MAAtB,CAAT;EACH,CAFkC,EAEhC,EAFgC,CAAnC;EAIA,OAAO,CAACA,MAAD,EAASG,QAAT,CAAP;AACH;AAAA"}
1
+ {"version":3,"names":["useState","useWorkletCallback","useHeight","initialHeight","height","setHeight","onLayout","e","nativeEvent","layout"],"sources":["useHeight.ts"],"sourcesContent":["import { useState } from 'react';\nimport { ViewProps } from 'react-native';\nimport { useWorkletCallback } from 'react-native-reanimated';\n\ntype OnLayoutCallback = ViewProps['onLayout'];\n\nexport default function useHeight(initialHeight = 0): [number, OnLayoutCallback] {\n const [height, setHeight] = useState<number>(initialHeight);\n\n const onLayout = useWorkletCallback((e) => {\n setHeight(e.nativeEvent.layout.height);\n }, []);\n\n return [height, onLayout];\n};\n"],"mappings":"AAAA,SAASA,QAAT,QAAyB,OAAzB;AAEA,SAASC,kBAAT,QAAmC,yBAAnC;AAIA,eAAe,SAASC,SAAT,GAAkE;EAAA,IAA/CC,aAA+C,uEAA/B,CAA+B;EAC7E,MAAM,CAACC,MAAD,EAASC,SAAT,IAAsBL,QAAQ,CAASG,aAAT,CAApC;EAEA,MAAMG,QAAQ,GAAGL,kBAAkB,CAAEM,CAAD,IAAO;IACvCF,SAAS,CAACE,CAAC,CAACC,WAAF,CAAcC,MAAd,CAAqBL,MAAtB,CAAT;EACH,CAFkC,EAEhC,EAFgC,CAAnC;EAIA,OAAO,CAACA,MAAD,EAASE,QAAT,CAAP;AACH;AAAA"}
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ import TabCoordinate from './TabCoordinate';
3
+ export interface UseTabCoordinates {
4
+ coordinates: TabCoordinate[];
5
+ updateCoordinate: (index: number, x: number, width: number) => void;
6
+ }
7
+ export default function useTabCoordinates(tabElements: React.ReactNode): UseTabCoordinates;
@@ -0,0 +1,2 @@
1
+ import { ViewProps } from 'react-native';
2
+ export default function useTabsWidth(): [number, ViewProps['onLayout']];
@@ -1,4 +1,4 @@
1
1
  import React from 'react';
2
- import Animated from 'react-native-reanimated';
3
- declare const _default: React.ComponentClass<Animated.AnimateProps<import("../Pressable").PressableProps>, any>;
2
+ import { Animated } from 'react-native';
3
+ declare const _default: Animated.AnimatedComponent<React.ComponentType<import("../Pressable").PressableProps>>;
4
4
  export default _default;
@@ -1,2 +1 @@
1
1
  export { default as useHeight } from './useHeight';
2
- export { default as useWidth } from './useWidth';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fountain-ui/core",
3
- "version": "2.0.0-beta.10",
3
+ "version": "2.0.0-beta.13",
4
4
  "author": "Fountain-UI Team",
5
5
  "description": "React components that implement Tappytoon's Fountain Design.",
6
6
  "license": "MIT",
@@ -67,5 +67,5 @@
67
67
  "publishConfig": {
68
68
  "access": "public"
69
69
  },
70
- "gitHead": "cd8db00a031d4e0debcdc860908c47c7cf709f6e"
70
+ "gitHead": "0ac49f4ca5f910fc8b5edad2593300d796b2d914"
71
71
  }
@@ -1,4 +1,5 @@
1
1
  import React, { useState } from 'react';
2
+ import type { WithTimingConfig } from 'react-native-reanimated';
2
3
  import Animated, { useAnimatedStyle, useSharedValue, withTiming } from 'react-native-reanimated';
3
4
  import { NamedStylesStringUnion, UseStyles } from '@fountain-ui/styles';
4
5
  import { ChevronDown as ChevronDownIcon } from '../internal/icons';
@@ -13,7 +14,7 @@ import AccordionProps from './AccordionProps';
13
14
 
14
15
  type AccordionStyles = NamedStylesStringUnion<'root'>;
15
16
 
16
- const ANIMATION_OPTION = { duration: 250 };
17
+ const ANIMATION_CONFIG: Readonly<WithTimingConfig> = { duration: 250 };
17
18
 
18
19
  const useStyles: UseStyles<AccordionStyles> = function (): AccordionStyles {
19
20
  const theme = useTheme();
@@ -38,15 +39,16 @@ export default function Accordion(props: AccordionProps) {
38
39
  const styles = useStyles();
39
40
 
40
41
  const [isExpanded, setIsExpanded] = useState(false);
42
+
41
43
  const rotate = useSharedValue(0);
42
44
 
43
45
  const animatedChevronDownStyles = useAnimatedStyle(() => ({
44
46
  transform: [{ rotate: `${rotate.value}deg` }],
45
- }));
47
+ }), []);
46
48
 
47
49
  const onPress = () => {
48
50
  setIsExpanded(prev => !prev);
49
- rotate.value = withTiming(!isExpanded ? 180 : 0, ANIMATION_OPTION);
51
+ rotate.value = withTiming(!isExpanded ? 180 : 0, ANIMATION_CONFIG);
50
52
  };
51
53
 
52
54
  return (
@@ -1,11 +1,12 @@
1
- import React from 'react';
2
- import type { WithTimingConfig } from 'react-native-reanimated';
3
- import { useAnimatedStyle, useSharedValue, withDelay, withTiming } from 'react-native-reanimated';
1
+ import React, { useCallback, useEffect, useRef } from 'react';
2
+ import { Animated } from 'react-native';
4
3
  import { useThrottle } from '../hooks';
5
4
  import { AnimatedPressable } from '../animated';
6
- import { StyleSheet } from '../styles';
7
5
  import type ButtonBaseProps from './ButtonBaseProps';
8
- import useDisabledReaction from './useDisabledReaction';
6
+
7
+ interface StartPressAnimation {
8
+ (pressIn: boolean, isHover: boolean): void;
9
+ }
9
10
 
10
11
  export const ORIGINAL_OPACITY = 1;
11
12
  export const DISABLED_OPACITY = .3;
@@ -14,14 +15,23 @@ const ACTIVE_OPACITY = .65;
14
15
  const ORIGINAL_SCALE = 1;
15
16
  const MINIFIED_SCALE = .96;
16
17
 
17
- const animationTimingConfig: WithTimingConfig = { duration: 150 };
18
+ // at "node_modules/react-native/Libraries/Pressability.js"
19
+ // const DEFAULT_MIN_PRESS_DURATION = 130;
20
+ const PRESS_IN_DELAY = 130;
21
+
22
+ type TimingAnimationValue = Animated.Value | Animated.ValueXY;
23
+ type TimingAnimationToValue = Animated.TimingAnimationConfig['toValue'];
18
24
 
19
- const styles = StyleSheet.create({
20
- disabled: {
21
- opacity: DISABLED_OPACITY,
22
- transform: [{ scale: ORIGINAL_SCALE }],
23
- },
24
- });
25
+ const startTimingAnimationWithDefaults = (
26
+ value: TimingAnimationValue,
27
+ toValue: TimingAnimationToValue,
28
+ ) => {
29
+ Animated.timing(value, {
30
+ toValue,
31
+ duration: 150,
32
+ useNativeDriver: true,
33
+ }).start();
34
+ };
25
35
 
26
36
  export default function ButtonBase(props: ButtonBaseProps) {
27
37
  const {
@@ -30,7 +40,7 @@ export default function ButtonBase(props: ButtonBaseProps) {
30
40
  disableThrottle = false,
31
41
  onPress,
32
42
  pressEffect = 'opacity',
33
- style,
43
+ style: styleProp,
34
44
  throttleMillis = 650,
35
45
  ...otherProps
36
46
  } = props;
@@ -40,56 +50,68 @@ export default function ButtonBase(props: ButtonBaseProps) {
40
50
  callback: onPress,
41
51
  });
42
52
 
43
- const opacity = useSharedValue(ORIGINAL_OPACITY);
44
- const scale = useSharedValue(ORIGINAL_SCALE);
53
+ const opacity = useRef<Animated.Value>(new Animated.Value(ORIGINAL_OPACITY)).current;
54
+ const scale = useRef<Animated.Value>(new Animated.Value(ORIGINAL_SCALE)).current;
45
55
 
46
- const animatedStyle = useAnimatedStyle(() => ({
47
- opacity: opacity.value,
48
- transform: [{ scale: scale.value }],
49
- }));
56
+ useEffect(() => {
57
+ opacity.setValue(disabled ? DISABLED_OPACITY : ORIGINAL_OPACITY);
58
+ }, [disabled]);
50
59
 
51
- useDisabledReaction(disabled, opacity);
60
+ const startScaleAnimation = useCallback<StartPressAnimation>((pressIn, isHover) => {
61
+ if (!isHover) {
62
+ startTimingAnimationWithDefaults(
63
+ scale,
64
+ pressIn ? MINIFIED_SCALE : ORIGINAL_SCALE,
65
+ );
66
+ }
67
+ }, []);
52
68
 
53
- const startAnimation = (pressIn: boolean, isHovered: boolean = false) => {
54
- if (pressEffect === 'none') {
55
- return;
69
+ const startOpacityAnimation = useCallback<StartPressAnimation>((pressIn) => {
70
+ if (pressIn) {
71
+ opacity.setValue(ACTIVE_OPACITY);
72
+ } else {
73
+ startTimingAnimationWithDefaults(opacity, ORIGINAL_OPACITY);
56
74
  }
75
+ }, []);
57
76
 
58
- if (pressEffect === 'opacity') {
59
- if (pressIn) {
60
- opacity.value = ACTIVE_OPACITY;
61
- } else {
62
- opacity.value = withTiming(ORIGINAL_OPACITY, animationTimingConfig);
63
- }
64
- } else if (!isHovered) {
65
- if (pressIn) {
66
- scale.value = withDelay(
67
- 100,
68
- withTiming(MINIFIED_SCALE, animationTimingConfig),
69
- );
70
- } else {
71
- scale.value = withTiming(ORIGINAL_SCALE, animationTimingConfig);
72
- }
77
+ const startPressAnimation = useCallback<StartPressAnimation>((pressIn, isHover = false) => {
78
+ if (pressEffect === 'scale') {
79
+ startScaleAnimation(pressIn, isHover);
80
+ } else if (pressEffect === 'opacity') {
81
+ startOpacityAnimation(pressIn, isHover);
73
82
  }
83
+ }, [pressEffect]);
84
+
85
+ const handlePressIn = useCallback(() => {
86
+ startPressAnimation(true, false);
87
+ }, [startPressAnimation]);
88
+
89
+ const handlePressOut = useCallback(() => {
90
+ startPressAnimation(false, false);
91
+ }, [startPressAnimation]);
92
+
93
+ const animatedStyle = {
94
+ opacity,
95
+ transform: [{ scale }],
74
96
  };
75
97
 
76
98
  return (
77
99
  <AnimatedPressable
78
100
  disabled={disabled}
79
101
  onPress={handlePress}
80
- onPressIn={() => startAnimation(true)}
81
- onPressOut={() => startAnimation(false)}
102
+ onPressIn={handlePressIn}
103
+ onPressOut={handlePressOut}
82
104
  style={[
83
105
  animatedStyle,
84
- disabled ? styles.disabled : undefined,
85
- style,
106
+ styleProp,
86
107
  ]}
108
+ unstable_pressDelay={PRESS_IN_DELAY}
87
109
  {...otherProps}
88
110
  >
89
111
  {typeof children !== 'function' ? (
90
112
  ({ hovered }) => {
91
113
  if (hovered !== undefined && !disabled) {
92
- startAnimation(hovered, true);
114
+ startPressAnimation(hovered, true);
93
115
  }
94
116
 
95
117
  return children;