@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.
- package/build/commonjs/Accordion/Accordion.js +3 -3
- package/build/commonjs/Accordion/Accordion.js.map +1 -1
- package/build/commonjs/ButtonBase/ButtonBase.js +56 -52
- package/build/commonjs/ButtonBase/ButtonBase.js.map +1 -1
- package/build/commonjs/CircularProgress/CircularProgress.js +19 -24
- package/build/commonjs/CircularProgress/CircularProgress.js.map +1 -1
- package/build/commonjs/ImageCore/ImageCoreNative.js +24 -26
- package/build/commonjs/ImageCore/ImageCoreNative.js.map +1 -1
- package/build/commonjs/Slide/Slide.js +12 -13
- package/build/commonjs/Slide/Slide.js.map +1 -1
- package/build/commonjs/Tabs/TabIndicator.js +2 -6
- package/build/commonjs/Tabs/TabIndicator.js.map +1 -1
- package/build/commonjs/Tabs/Tabs.js +46 -48
- package/build/commonjs/Tabs/Tabs.js.map +1 -1
- package/build/commonjs/Tabs/useTabCoordinates.js +44 -0
- package/build/commonjs/Tabs/useTabCoordinates.js.map +1 -0
- package/build/commonjs/Tabs/useTabsWidth.js +26 -0
- package/build/commonjs/Tabs/useTabsWidth.js.map +1 -0
- package/build/commonjs/Tooltip/Tooltip.js +18 -22
- package/build/commonjs/Tooltip/Tooltip.js.map +1 -1
- package/build/commonjs/animated/AnimatedPressable.js +2 -3
- package/build/commonjs/animated/AnimatedPressable.js.map +1 -1
- package/build/commonjs/hooks/useCollapsibleAppBar.js +46 -36
- package/build/commonjs/hooks/useCollapsibleAppBar.js.map +1 -1
- package/build/commonjs/hooks/useFadeInAppBar.js +35 -18
- package/build/commonjs/hooks/useFadeInAppBar.js.map +1 -1
- package/build/commonjs/hooks/useThrottle.js +3 -7
- package/build/commonjs/hooks/useThrottle.js.map +1 -1
- package/build/commonjs/internal/hooks/index.js +0 -8
- package/build/commonjs/internal/hooks/index.js.map +1 -1
- package/build/commonjs/internal/hooks/useHeight.js +2 -6
- package/build/commonjs/internal/hooks/useHeight.js.map +1 -1
- package/build/module/Accordion/Accordion.js +3 -3
- package/build/module/Accordion/Accordion.js.map +1 -1
- package/build/module/ButtonBase/ButtonBase.js +54 -48
- package/build/module/ButtonBase/ButtonBase.js.map +1 -1
- package/build/module/CircularProgress/CircularProgress.js +20 -21
- package/build/module/CircularProgress/CircularProgress.js.map +1 -1
- package/build/module/ImageCore/ImageCoreNative.js +20 -23
- package/build/module/ImageCore/ImageCoreNative.js.map +1 -1
- package/build/module/Slide/Slide.js +14 -10
- package/build/module/Slide/Slide.js.map +1 -1
- package/build/module/Tabs/TabIndicator.js +3 -7
- package/build/module/Tabs/TabIndicator.js.map +1 -1
- package/build/module/Tabs/Tabs.js +39 -39
- package/build/module/Tabs/Tabs.js.map +1 -1
- package/build/module/Tabs/useTabCoordinates.js +30 -0
- package/build/module/Tabs/useTabCoordinates.js.map +1 -0
- package/build/module/Tabs/useTabsWidth.js +18 -0
- package/build/module/Tabs/useTabsWidth.js.map +1 -0
- package/build/module/Tooltip/Tooltip.js +15 -15
- package/build/module/Tooltip/Tooltip.js.map +1 -1
- package/build/module/animated/AnimatedPressable.js +2 -3
- package/build/module/animated/AnimatedPressable.js.map +1 -1
- package/build/module/hooks/useCollapsibleAppBar.js +46 -34
- package/build/module/hooks/useCollapsibleAppBar.js.map +1 -1
- package/build/module/hooks/useFadeInAppBar.js +35 -14
- package/build/module/hooks/useFadeInAppBar.js.map +1 -1
- package/build/module/hooks/useThrottle.js +3 -3
- package/build/module/hooks/useThrottle.js.map +1 -1
- package/build/module/internal/hooks/index.js +0 -1
- package/build/module/internal/hooks/index.js.map +1 -1
- package/build/module/internal/hooks/useHeight.js +2 -2
- package/build/module/internal/hooks/useHeight.js.map +1 -1
- package/build/typescript/Tabs/useTabCoordinates.d.ts +7 -0
- package/build/typescript/Tabs/useTabsWidth.d.ts +2 -0
- package/build/typescript/animated/AnimatedPressable.d.ts +2 -2
- package/build/typescript/internal/hooks/index.d.ts +0 -1
- package/package.json +2 -2
- package/src/Accordion/Accordion.tsx +5 -3
- package/src/ButtonBase/ButtonBase.tsx +65 -43
- package/src/CircularProgress/CircularProgress.tsx +24 -30
- package/src/ImageCore/ImageCoreNative.tsx +17 -19
- package/src/Slide/Slide.tsx +17 -15
- package/src/Tabs/TabIndicator.tsx +4 -8
- package/src/Tabs/Tabs.tsx +37 -39
- package/src/Tabs/useTabCoordinates.ts +36 -0
- package/src/Tabs/useTabsWidth.ts +20 -0
- package/src/Tooltip/Tooltip.tsx +16 -16
- package/src/animated/AnimatedPressable.tsx +1 -2
- package/src/hooks/useCollapsibleAppBar.ts +41 -31
- package/src/hooks/useFadeInAppBar.ts +31 -15
- package/src/hooks/useThrottle.ts +3 -3
- package/src/internal/hooks/index.ts +0 -1
- package/src/internal/hooks/useHeight.ts +2 -2
- package/build/commonjs/ButtonBase/ButtonBase.ios.js +0 -101
- package/build/commonjs/ButtonBase/ButtonBase.ios.js.map +0 -1
- package/build/commonjs/ButtonBase/useDisabledReaction/index.js +0 -21
- package/build/commonjs/ButtonBase/useDisabledReaction/index.js.map +0 -1
- package/build/commonjs/ButtonBase/useDisabledReaction/index.native.js +0 -9
- package/build/commonjs/ButtonBase/useDisabledReaction/index.native.js.map +0 -1
- package/build/commonjs/ImageCore/ImageCoreNative.ios.js +0 -60
- package/build/commonjs/ImageCore/ImageCoreNative.ios.js.map +0 -1
- package/build/commonjs/internal/hooks/useWidth.js +0 -29
- package/build/commonjs/internal/hooks/useWidth.js.map +0 -1
- package/build/module/ButtonBase/ButtonBase.ios.js +0 -82
- package/build/module/ButtonBase/ButtonBase.ios.js.map +0 -1
- package/build/module/ButtonBase/useDisabledReaction/index.js +0 -12
- package/build/module/ButtonBase/useDisabledReaction/index.js.map +0 -1
- package/build/module/ButtonBase/useDisabledReaction/index.native.js +0 -2
- package/build/module/ButtonBase/useDisabledReaction/index.native.js.map +0 -1
- package/build/module/ImageCore/ImageCoreNative.ios.js +0 -45
- package/build/module/ImageCore/ImageCoreNative.ios.js.map +0 -1
- package/build/module/internal/hooks/useWidth.js +0 -15
- package/build/module/internal/hooks/useWidth.js.map +0 -1
- package/build/typescript/ButtonBase/ButtonBase.ios.d.ts +0 -2
- package/build/typescript/ButtonBase/useDisabledReaction/index.d.ts +0 -2
- package/build/typescript/ButtonBase/useDisabledReaction/index.native.d.ts +0 -2
- package/build/typescript/ImageCore/ImageCoreNative.ios.d.ts +0 -2
- package/build/typescript/internal/hooks/useWidth.d.ts +0 -2
- package/src/ButtonBase/ButtonBase.ios.tsx +0 -95
- package/src/ButtonBase/useDisabledReaction/index.native.ts +0 -4
- package/src/ButtonBase/useDisabledReaction/index.ts +0 -16
- package/src/ImageCore/ImageCoreNative.ios.tsx +0 -46
- package/src/internal/hooks/useWidth.ts +0 -17
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
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
|
|
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
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
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
|
|
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] =
|
|
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
|
|
42
|
-
const
|
|
43
|
-
const animatedAppBarStyle = useAnimatedStyle(() =>
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
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":["
|
|
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
|
|
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 =
|
|
8
|
-
return
|
|
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":["
|
|
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 +1 @@
|
|
|
1
|
-
{"version":3,"names":["default","useHeight"
|
|
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
|
|
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] =
|
|
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":["
|
|
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;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import Animated from 'react-native
|
|
3
|
-
declare const _default:
|
|
2
|
+
import { Animated } from 'react-native';
|
|
3
|
+
declare const _default: Animated.AnimatedComponent<React.ComponentType<import("../Pressable").PressableProps>>;
|
|
4
4
|
export default _default;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fountain-ui/core",
|
|
3
|
-
"version": "2.0.0-beta.
|
|
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": "
|
|
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
|
|
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,
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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 =
|
|
44
|
-
const 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
|
-
|
|
47
|
-
opacity:
|
|
48
|
-
|
|
49
|
-
}));
|
|
56
|
+
useEffect(() => {
|
|
57
|
+
opacity.setValue(disabled ? DISABLED_OPACITY : ORIGINAL_OPACITY);
|
|
58
|
+
}, [disabled]);
|
|
50
59
|
|
|
51
|
-
|
|
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
|
|
54
|
-
if (
|
|
55
|
-
|
|
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
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
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={
|
|
81
|
-
onPressOut={
|
|
102
|
+
onPressIn={handlePressIn}
|
|
103
|
+
onPressOut={handlePressOut}
|
|
82
104
|
style={[
|
|
83
105
|
animatedStyle,
|
|
84
|
-
|
|
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
|
-
|
|
114
|
+
startPressAnimation(hovered, true);
|
|
93
115
|
}
|
|
94
116
|
|
|
95
117
|
return children;
|