@fountain-ui/lab 1.15.2 → 1.16.1
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/CHANGELOG.md +32 -0
- package/build/commonjs/hooks/useUnstableCollapsibleAppBar.js +22 -10
- package/build/commonjs/hooks/useUnstableCollapsibleAppBar.js.map +1 -1
- package/build/module/hooks/useUnstableCollapsibleAppBar.js +21 -9
- package/build/module/hooks/useUnstableCollapsibleAppBar.js.map +1 -1
- package/build/typescript/hooks/useUnstableCollapsibleAppBar.d.ts +2 -1
- package/package.json +4 -4
- package/src/hooks/useUnstableCollapsibleAppBar.ts +25 -8
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,38 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [1.16.1](https://github.com/tappytoon/tappytoon/compare/@fountain-ui/lab@1.13.0...@fountain-ui/lab@1.16.1) (2022-01-07)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @fountain-ui/lab
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# [1.16.0](https://github.com/tappytoon/tappytoon/compare/@fountain-ui/lab@1.13.0...@fountain-ui/lab@1.16.0) (2021-12-27)
|
|
15
|
+
|
|
16
|
+
**Note:** Version bump only for package @fountain-ui/lab
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
## [1.15.4](https://github.com/tappytoon/tappytoon/compare/@fountain-ui/lab@1.13.0...@fountain-ui/lab@1.15.4) (2021-11-18)
|
|
23
|
+
|
|
24
|
+
**Note:** Version bump only for package @fountain-ui/lab
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
## [1.15.3](https://github.com/tappytoon/tappytoon/compare/@fountain-ui/lab@1.13.0...@fountain-ui/lab@1.15.3) (2021-11-17)
|
|
31
|
+
|
|
32
|
+
**Note:** Version bump only for package @fountain-ui/lab
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
6
38
|
## [1.15.2](https://github.com/tappytoon/tappytoon/compare/@fountain-ui/lab@1.13.0...@fountain-ui/lab@1.15.2) (2021-11-15)
|
|
7
39
|
|
|
8
40
|
**Note:** Version bump only for package @fountain-ui/lab
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.default =
|
|
6
|
+
exports.default = useUnstableCollapsibleAppBar;
|
|
7
7
|
|
|
8
8
|
var _react = _interopRequireWildcard(require("react"));
|
|
9
9
|
|
|
@@ -26,27 +26,30 @@ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "functio
|
|
|
26
26
|
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
27
27
|
|
|
28
28
|
const defaultOptions = {
|
|
29
|
-
translucent: false
|
|
29
|
+
translucent: false,
|
|
30
|
+
shouldTranslateYReset: false
|
|
30
31
|
};
|
|
31
32
|
const ANIMATION_DURATION_MILLIS = 100;
|
|
32
33
|
const SUPPORTS_DRAG_DETECTION = _reactNative.Platform.OS !== 'web';
|
|
33
34
|
|
|
34
|
-
function
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
function useLargerValueOfLastTwoValues(value) {
|
|
36
|
+
const refLatestTwoValues = (0, _react.useRef)([0, 0]);
|
|
37
|
+
refLatestTwoValues.current.shift();
|
|
38
|
+
refLatestTwoValues.current.push(value);
|
|
39
|
+
return Math.max(...refLatestTwoValues.current);
|
|
38
40
|
}
|
|
39
41
|
|
|
40
|
-
function
|
|
42
|
+
function useUnstableCollapsibleAppBar(userOptions = defaultOptions) {
|
|
41
43
|
const {
|
|
42
|
-
translucent
|
|
44
|
+
translucent,
|
|
45
|
+
shouldTranslateYReset
|
|
43
46
|
} = { ...defaultOptions,
|
|
44
47
|
...userOptions
|
|
45
48
|
};
|
|
46
49
|
const styles = (0, _useAppbarStyles.default)();
|
|
47
50
|
const safeAreaInsets = (0, _reactNativeSafeAreaContext.useSafeAreaInsets)();
|
|
48
51
|
const [appBarHeight, onAppBarLayout] = (0, _useHeight.default)();
|
|
49
|
-
const appBarMaxHeight =
|
|
52
|
+
const appBarMaxHeight = useLargerValueOfLastTwoValues(appBarHeight);
|
|
50
53
|
const [collapsibleToolbarHeight, onCollapsibleToolbarLayout] = (0, _useHeight.default)();
|
|
51
54
|
|
|
52
55
|
const maxTranslateY = _reactNativeReanimated.default.useDerivedValue(() => -collapsibleToolbarHeight);
|
|
@@ -93,6 +96,15 @@ function useCollapsibleAppBar(userOptions = defaultOptions) {
|
|
|
93
96
|
const prevIndex = indexRef.current;
|
|
94
97
|
|
|
95
98
|
if (prevIndex === nextIndex) {
|
|
99
|
+
if (shouldTranslateYReset) {
|
|
100
|
+
translateY.value = _reactNativeReanimated.default.withTiming(0, {
|
|
101
|
+
duration: ANIMATION_DURATION_MILLIS
|
|
102
|
+
});
|
|
103
|
+
vectorY.value = 0;
|
|
104
|
+
offsetsRef.current = [];
|
|
105
|
+
overlapped.value = false;
|
|
106
|
+
}
|
|
107
|
+
|
|
96
108
|
return;
|
|
97
109
|
}
|
|
98
110
|
|
|
@@ -123,7 +135,7 @@ function useCollapsibleAppBar(userOptions = defaultOptions) {
|
|
|
123
135
|
const ty = translateY.value;
|
|
124
136
|
const maxTy = maxTranslateY.value;
|
|
125
137
|
const deltaY = offsetY - prevOffsetY.value;
|
|
126
|
-
vectorY.value = vectorY.value * deltaY >= 0 && offsetY
|
|
138
|
+
vectorY.value = vectorY.value * deltaY >= 0 && offsetY > 0 ? vectorY.value + deltaY : deltaY;
|
|
127
139
|
prevOffsetY.value = offsetY;
|
|
128
140
|
|
|
129
141
|
if (SUPPORTS_DRAG_DETECTION) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["useUnstableCollapsibleAppBar.ts"],"names":["defaultOptions","translucent","ANIMATION_DURATION_MILLIS","SUPPORTS_DRAG_DETECTION","Platform","OS","useMaxNumber","value","refMaxValue","current","Math","max","useCollapsibleAppBar","userOptions","styles","safeAreaInsets","appBarHeight","onAppBarLayout","appBarMaxHeight","collapsibleToolbarHeight","onCollapsibleToolbarLayout","maxTranslateY","Animated","useDerivedValue","translateY","useSharedValue","lastTranslateY","lastOffsetY","prevOffsetY","overlapped","vectorY","elevationStyle","animatedStyle","useAnimatedStyle","transform","boxShadow","elevation","shadowColor","shadowOffset","shadowRadius","shadowOpacity","indexRef","React","useRef","offsetsRef","onScrollViewChanged","nextIndex","prevIndex","savedOffsetY","withTiming","duration","scrollHandler","useAnimatedScrollHandler","onBeginDrag","onMomentumBegin","onScroll","event","offsetY","contentOffset","y","ty","maxTy","deltaY","dy","min","onEndDrag","onMomentumEnd","threshold","nextTranslateY","hasCollapsible","appBarStyle","paddingTop","top","undefined","floating","scrollContentInsets"],"mappings":"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","sourcesContent":["import React, { useRef } from 'react';\nimport { Falsy, Platform, RegisteredStyle, ScrollViewProps, ViewProps, ViewStyle } from 'react-native';\nimport Animated from 'react-native-reanimated';\nimport { useSafeAreaInsets } from 'react-native-safe-area-context';\nimport useAppbarStyles from './useAppbarStyles';\nimport useElevationStyle from './useElevationStyle';\nimport useHeight from './useHeight';\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 translucent?: boolean;\n}\n\nexport interface CollapsibleAppBar {\n appBarStyle: ViewStyleProp;\n vectorY: Animated.SharedValue<number>;\n onAppBarLayout: OnLayoutCallback;\n onCollapsibleToolbarLayout: OnLayoutCallback;\n onScroll: OnScroll;\n onScrollViewChanged: (index: number) => void;\n scrollContentInsets: ContentInsets;\n}\n\nconst defaultOptions: Required<Options> = {\n translucent: false,\n};\n\nconst ANIMATION_DURATION_MILLIS = 100;\n\nconst SUPPORTS_DRAG_DETECTION = Platform.OS !== 'web';\n\nfunction useMaxNumber(value: number) {\n const refMaxValue = useRef(value);\n\n refMaxValue.current = Math.max(value, refMaxValue.current);\n\n return refMaxValue.current;\n}\n\n\nexport default function useCollapsibleAppBar(userOptions: Options = defaultOptions): CollapsibleAppBar {\n const { translucent }: 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 appBarMaxHeight = useMaxNumber(appBarHeight);\n const [collapsibleToolbarHeight, onCollapsibleToolbarLayout] = useHeight();\n\n const maxTranslateY = Animated.useDerivedValue(() => -collapsibleToolbarHeight);\n\n const translateY = Animated.useSharedValue<number>(0);\n const lastTranslateY = Animated.useSharedValue<number>(0);\n const lastOffsetY = Animated.useSharedValue<number>(0);\n const prevOffsetY = Animated.useSharedValue<number>(0);\n const overlapped = Animated.useSharedValue<boolean>(false);\n const vectorY = Animated.useSharedValue<number>(0);\n\n const elevationStyle = useElevationStyle(4);\n const animatedStyle = Animated.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 = Animated.withTiming(0, {\n duration: ANIMATION_DURATION_MILLIS,\n });\n\n vectorY.value = 0;\n }\n };\n\n const scrollHandler = Animated.useAnimatedScrollHandler({\n onBeginDrag: () => {\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 const deltaY = offsetY - prevOffsetY.value;\n vectorY.value = vectorY.value * deltaY >= 0 && offsetY !== 0 ? vectorY.value + deltaY : deltaY;\n prevOffsetY.value = offsetY;\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 = Animated.withTiming(Math.min(Math.max(-offsetY, maxTy), 0), {\n duration: ANIMATION_DURATION_MILLIS,\n });\n }\n } else {\n if (ty === maxTy) {\n translateY.value = Animated.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 = Animated.withTiming(nextTranslateY, {\n duration: ANIMATION_DURATION_MILLIS,\n });\n },\n });\n\n const hasCollapsible = collapsibleToolbarHeight > 0;\n\n const appBarStyle = [\n animatedStyle,\n translucent ? { paddingTop: safeAreaInsets.top } : undefined,\n hasCollapsible ? styles.floating : undefined,\n ];\n\n return {\n appBarStyle,\n vectorY,\n onAppBarLayout,\n onCollapsibleToolbarLayout,\n onScroll: scrollHandler,\n onScrollViewChanged,\n scrollContentInsets: { top: hasCollapsible ? appBarMaxHeight : 0 },\n };\n};\n"]}
|
|
1
|
+
{"version":3,"sources":["useUnstableCollapsibleAppBar.ts"],"names":["defaultOptions","translucent","shouldTranslateYReset","ANIMATION_DURATION_MILLIS","SUPPORTS_DRAG_DETECTION","Platform","OS","useLargerValueOfLastTwoValues","value","refLatestTwoValues","current","shift","push","Math","max","useUnstableCollapsibleAppBar","userOptions","styles","safeAreaInsets","appBarHeight","onAppBarLayout","appBarMaxHeight","collapsibleToolbarHeight","onCollapsibleToolbarLayout","maxTranslateY","Animated","useDerivedValue","translateY","useSharedValue","lastTranslateY","lastOffsetY","prevOffsetY","overlapped","vectorY","elevationStyle","animatedStyle","useAnimatedStyle","transform","boxShadow","elevation","shadowColor","shadowOffset","shadowRadius","shadowOpacity","indexRef","React","useRef","offsetsRef","onScrollViewChanged","nextIndex","prevIndex","withTiming","duration","savedOffsetY","scrollHandler","useAnimatedScrollHandler","onBeginDrag","onMomentumBegin","onScroll","event","offsetY","contentOffset","y","ty","maxTy","deltaY","dy","min","onEndDrag","onMomentumEnd","threshold","nextTranslateY","hasCollapsible","appBarStyle","paddingTop","top","undefined","floating","scrollContentInsets"],"mappings":"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","sourcesContent":["import React, { useRef } from 'react';\nimport { Falsy, Platform, RegisteredStyle, ScrollViewProps, ViewProps, ViewStyle } from 'react-native';\nimport Animated from 'react-native-reanimated';\nimport { useSafeAreaInsets } from 'react-native-safe-area-context';\nimport useAppbarStyles from './useAppbarStyles';\nimport useElevationStyle from './useElevationStyle';\nimport useHeight from './useHeight';\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 translucent?: boolean;\n shouldTranslateYReset?: boolean;\n}\n\nexport interface CollapsibleAppBar {\n appBarStyle: ViewStyleProp;\n vectorY: Animated.SharedValue<number>;\n onAppBarLayout: OnLayoutCallback;\n onCollapsibleToolbarLayout: OnLayoutCallback;\n onScroll: OnScroll;\n onScrollViewChanged: (index: number) => void;\n scrollContentInsets: ContentInsets;\n}\n\nconst defaultOptions: Required<Options> = {\n translucent: false,\n shouldTranslateYReset: false,\n};\n\nconst ANIMATION_DURATION_MILLIS = 100;\n\nconst SUPPORTS_DRAG_DETECTION = Platform.OS !== 'web';\n\n\nfunction useLargerValueOfLastTwoValues(value: number) {\n const refLatestTwoValues = useRef([0, 0]);\n\n refLatestTwoValues.current.shift();\n refLatestTwoValues.current.push(value);\n\n return Math.max(...refLatestTwoValues.current);\n}\n\n\nexport default function useUnstableCollapsibleAppBar(userOptions: Options = defaultOptions): CollapsibleAppBar {\n const {\n translucent,\n shouldTranslateYReset,\n }: 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 appBarMaxHeight = useLargerValueOfLastTwoValues(appBarHeight);\n const [collapsibleToolbarHeight, onCollapsibleToolbarLayout] = useHeight();\n\n const maxTranslateY = Animated.useDerivedValue(() => -collapsibleToolbarHeight);\n\n const translateY = Animated.useSharedValue<number>(0);\n const lastTranslateY = Animated.useSharedValue<number>(0);\n const lastOffsetY = Animated.useSharedValue<number>(0);\n const prevOffsetY = Animated.useSharedValue<number>(0);\n const overlapped = Animated.useSharedValue<boolean>(false);\n const vectorY = Animated.useSharedValue<number>(0);\n\n const elevationStyle = useElevationStyle(4);\n const animatedStyle = Animated.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 if (shouldTranslateYReset) {\n translateY.value = Animated.withTiming(0, {\n duration: ANIMATION_DURATION_MILLIS,\n });\n\n vectorY.value = 0;\n offsetsRef.current = [];\n overlapped.value = false;\n }\n\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 = Animated.withTiming(0, {\n duration: ANIMATION_DURATION_MILLIS,\n });\n\n vectorY.value = 0;\n }\n };\n\n const scrollHandler = Animated.useAnimatedScrollHandler({\n onBeginDrag: () => {\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 const deltaY = offsetY - prevOffsetY.value;\n vectorY.value = (vectorY.value * deltaY >= 0 && offsetY > 0) ? vectorY.value + deltaY : deltaY;\n prevOffsetY.value = offsetY;\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 = Animated.withTiming(Math.min(Math.max(-offsetY, maxTy), 0), {\n duration: ANIMATION_DURATION_MILLIS,\n });\n }\n } else {\n if (ty === maxTy) {\n translateY.value = Animated.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 = Animated.withTiming(nextTranslateY, {\n duration: ANIMATION_DURATION_MILLIS,\n });\n },\n });\n\n const hasCollapsible = collapsibleToolbarHeight > 0;\n\n const appBarStyle = [\n animatedStyle,\n translucent ? { paddingTop: safeAreaInsets.top } : undefined,\n hasCollapsible ? styles.floating : undefined,\n ];\n\n return {\n appBarStyle,\n vectorY,\n onAppBarLayout,\n onCollapsibleToolbarLayout,\n onScroll: scrollHandler,\n onScrollViewChanged,\n scrollContentInsets: { top: hasCollapsible ? appBarMaxHeight : 0 },\n };\n};\n"]}
|
|
@@ -6,27 +6,30 @@ import useAppbarStyles from './useAppbarStyles';
|
|
|
6
6
|
import useElevationStyle from './useElevationStyle';
|
|
7
7
|
import useHeight from './useHeight';
|
|
8
8
|
const defaultOptions = {
|
|
9
|
-
translucent: false
|
|
9
|
+
translucent: false,
|
|
10
|
+
shouldTranslateYReset: false
|
|
10
11
|
};
|
|
11
12
|
const ANIMATION_DURATION_MILLIS = 100;
|
|
12
13
|
const SUPPORTS_DRAG_DETECTION = Platform.OS !== 'web';
|
|
13
14
|
|
|
14
|
-
function
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
function useLargerValueOfLastTwoValues(value) {
|
|
16
|
+
const refLatestTwoValues = useRef([0, 0]);
|
|
17
|
+
refLatestTwoValues.current.shift();
|
|
18
|
+
refLatestTwoValues.current.push(value);
|
|
19
|
+
return Math.max(...refLatestTwoValues.current);
|
|
18
20
|
}
|
|
19
21
|
|
|
20
|
-
export default function
|
|
22
|
+
export default function useUnstableCollapsibleAppBar(userOptions = defaultOptions) {
|
|
21
23
|
const {
|
|
22
|
-
translucent
|
|
24
|
+
translucent,
|
|
25
|
+
shouldTranslateYReset
|
|
23
26
|
} = { ...defaultOptions,
|
|
24
27
|
...userOptions
|
|
25
28
|
};
|
|
26
29
|
const styles = useAppbarStyles();
|
|
27
30
|
const safeAreaInsets = useSafeAreaInsets();
|
|
28
31
|
const [appBarHeight, onAppBarLayout] = useHeight();
|
|
29
|
-
const appBarMaxHeight =
|
|
32
|
+
const appBarMaxHeight = useLargerValueOfLastTwoValues(appBarHeight);
|
|
30
33
|
const [collapsibleToolbarHeight, onCollapsibleToolbarLayout] = useHeight();
|
|
31
34
|
const maxTranslateY = Animated.useDerivedValue(() => -collapsibleToolbarHeight);
|
|
32
35
|
const translateY = Animated.useSharedValue(0);
|
|
@@ -62,6 +65,15 @@ export default function useCollapsibleAppBar(userOptions = defaultOptions) {
|
|
|
62
65
|
const prevIndex = indexRef.current;
|
|
63
66
|
|
|
64
67
|
if (prevIndex === nextIndex) {
|
|
68
|
+
if (shouldTranslateYReset) {
|
|
69
|
+
translateY.value = Animated.withTiming(0, {
|
|
70
|
+
duration: ANIMATION_DURATION_MILLIS
|
|
71
|
+
});
|
|
72
|
+
vectorY.value = 0;
|
|
73
|
+
offsetsRef.current = [];
|
|
74
|
+
overlapped.value = false;
|
|
75
|
+
}
|
|
76
|
+
|
|
65
77
|
return;
|
|
66
78
|
}
|
|
67
79
|
|
|
@@ -92,7 +104,7 @@ export default function useCollapsibleAppBar(userOptions = defaultOptions) {
|
|
|
92
104
|
const ty = translateY.value;
|
|
93
105
|
const maxTy = maxTranslateY.value;
|
|
94
106
|
const deltaY = offsetY - prevOffsetY.value;
|
|
95
|
-
vectorY.value = vectorY.value * deltaY >= 0 && offsetY
|
|
107
|
+
vectorY.value = vectorY.value * deltaY >= 0 && offsetY > 0 ? vectorY.value + deltaY : deltaY;
|
|
96
108
|
prevOffsetY.value = offsetY;
|
|
97
109
|
|
|
98
110
|
if (SUPPORTS_DRAG_DETECTION) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["useUnstableCollapsibleAppBar.ts"],"names":["React","useRef","Platform","Animated","useSafeAreaInsets","useAppbarStyles","useElevationStyle","useHeight","defaultOptions","translucent","ANIMATION_DURATION_MILLIS","SUPPORTS_DRAG_DETECTION","OS","useMaxNumber","value","refMaxValue","current","Math","max","useCollapsibleAppBar","userOptions","styles","safeAreaInsets","appBarHeight","onAppBarLayout","appBarMaxHeight","collapsibleToolbarHeight","onCollapsibleToolbarLayout","maxTranslateY","useDerivedValue","translateY","useSharedValue","lastTranslateY","lastOffsetY","prevOffsetY","overlapped","vectorY","elevationStyle","animatedStyle","useAnimatedStyle","transform","boxShadow","elevation","shadowColor","shadowOffset","shadowRadius","shadowOpacity","indexRef","offsetsRef","onScrollViewChanged","nextIndex","prevIndex","savedOffsetY","withTiming","duration","scrollHandler","useAnimatedScrollHandler","onBeginDrag","onMomentumBegin","onScroll","event","offsetY","contentOffset","y","ty","maxTy","deltaY","dy","min","onEndDrag","onMomentumEnd","threshold","nextTranslateY","hasCollapsible","appBarStyle","paddingTop","top","undefined","floating","scrollContentInsets"],"mappings":"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","sourcesContent":["import React, { useRef } from 'react';\nimport { Falsy, Platform, RegisteredStyle, ScrollViewProps, ViewProps, ViewStyle } from 'react-native';\nimport Animated from 'react-native-reanimated';\nimport { useSafeAreaInsets } from 'react-native-safe-area-context';\nimport useAppbarStyles from './useAppbarStyles';\nimport useElevationStyle from './useElevationStyle';\nimport useHeight from './useHeight';\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 translucent?: boolean;\n}\n\nexport interface CollapsibleAppBar {\n appBarStyle: ViewStyleProp;\n vectorY: Animated.SharedValue<number>;\n onAppBarLayout: OnLayoutCallback;\n onCollapsibleToolbarLayout: OnLayoutCallback;\n onScroll: OnScroll;\n onScrollViewChanged: (index: number) => void;\n scrollContentInsets: ContentInsets;\n}\n\nconst defaultOptions: Required<Options> = {\n translucent: false,\n};\n\nconst ANIMATION_DURATION_MILLIS = 100;\n\nconst SUPPORTS_DRAG_DETECTION = Platform.OS !== 'web';\n\nfunction useMaxNumber(value: number) {\n const refMaxValue = useRef(value);\n\n refMaxValue.current = Math.max(value, refMaxValue.current);\n\n return refMaxValue.current;\n}\n\n\nexport default function useCollapsibleAppBar(userOptions: Options = defaultOptions): CollapsibleAppBar {\n const { translucent }: 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 appBarMaxHeight = useMaxNumber(appBarHeight);\n const [collapsibleToolbarHeight, onCollapsibleToolbarLayout] = useHeight();\n\n const maxTranslateY = Animated.useDerivedValue(() => -collapsibleToolbarHeight);\n\n const translateY = Animated.useSharedValue<number>(0);\n const lastTranslateY = Animated.useSharedValue<number>(0);\n const lastOffsetY = Animated.useSharedValue<number>(0);\n const prevOffsetY = Animated.useSharedValue<number>(0);\n const overlapped = Animated.useSharedValue<boolean>(false);\n const vectorY = Animated.useSharedValue<number>(0);\n\n const elevationStyle = useElevationStyle(4);\n const animatedStyle = Animated.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 = Animated.withTiming(0, {\n duration: ANIMATION_DURATION_MILLIS,\n });\n\n vectorY.value = 0;\n }\n };\n\n const scrollHandler = Animated.useAnimatedScrollHandler({\n onBeginDrag: () => {\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 const deltaY = offsetY - prevOffsetY.value;\n vectorY.value = vectorY.value * deltaY >= 0 && offsetY !== 0 ? vectorY.value + deltaY : deltaY;\n prevOffsetY.value = offsetY;\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 = Animated.withTiming(Math.min(Math.max(-offsetY, maxTy), 0), {\n duration: ANIMATION_DURATION_MILLIS,\n });\n }\n } else {\n if (ty === maxTy) {\n translateY.value = Animated.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 = Animated.withTiming(nextTranslateY, {\n duration: ANIMATION_DURATION_MILLIS,\n });\n },\n });\n\n const hasCollapsible = collapsibleToolbarHeight > 0;\n\n const appBarStyle = [\n animatedStyle,\n translucent ? { paddingTop: safeAreaInsets.top } : undefined,\n hasCollapsible ? styles.floating : undefined,\n ];\n\n return {\n appBarStyle,\n vectorY,\n onAppBarLayout,\n onCollapsibleToolbarLayout,\n onScroll: scrollHandler,\n onScrollViewChanged,\n scrollContentInsets: { top: hasCollapsible ? appBarMaxHeight : 0 },\n };\n};\n"]}
|
|
1
|
+
{"version":3,"sources":["useUnstableCollapsibleAppBar.ts"],"names":["React","useRef","Platform","Animated","useSafeAreaInsets","useAppbarStyles","useElevationStyle","useHeight","defaultOptions","translucent","shouldTranslateYReset","ANIMATION_DURATION_MILLIS","SUPPORTS_DRAG_DETECTION","OS","useLargerValueOfLastTwoValues","value","refLatestTwoValues","current","shift","push","Math","max","useUnstableCollapsibleAppBar","userOptions","styles","safeAreaInsets","appBarHeight","onAppBarLayout","appBarMaxHeight","collapsibleToolbarHeight","onCollapsibleToolbarLayout","maxTranslateY","useDerivedValue","translateY","useSharedValue","lastTranslateY","lastOffsetY","prevOffsetY","overlapped","vectorY","elevationStyle","animatedStyle","useAnimatedStyle","transform","boxShadow","elevation","shadowColor","shadowOffset","shadowRadius","shadowOpacity","indexRef","offsetsRef","onScrollViewChanged","nextIndex","prevIndex","withTiming","duration","savedOffsetY","scrollHandler","useAnimatedScrollHandler","onBeginDrag","onMomentumBegin","onScroll","event","offsetY","contentOffset","y","ty","maxTy","deltaY","dy","min","onEndDrag","onMomentumEnd","threshold","nextTranslateY","hasCollapsible","appBarStyle","paddingTop","top","undefined","floating","scrollContentInsets"],"mappings":"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","sourcesContent":["import React, { useRef } from 'react';\nimport { Falsy, Platform, RegisteredStyle, ScrollViewProps, ViewProps, ViewStyle } from 'react-native';\nimport Animated from 'react-native-reanimated';\nimport { useSafeAreaInsets } from 'react-native-safe-area-context';\nimport useAppbarStyles from './useAppbarStyles';\nimport useElevationStyle from './useElevationStyle';\nimport useHeight from './useHeight';\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 translucent?: boolean;\n shouldTranslateYReset?: boolean;\n}\n\nexport interface CollapsibleAppBar {\n appBarStyle: ViewStyleProp;\n vectorY: Animated.SharedValue<number>;\n onAppBarLayout: OnLayoutCallback;\n onCollapsibleToolbarLayout: OnLayoutCallback;\n onScroll: OnScroll;\n onScrollViewChanged: (index: number) => void;\n scrollContentInsets: ContentInsets;\n}\n\nconst defaultOptions: Required<Options> = {\n translucent: false,\n shouldTranslateYReset: false,\n};\n\nconst ANIMATION_DURATION_MILLIS = 100;\n\nconst SUPPORTS_DRAG_DETECTION = Platform.OS !== 'web';\n\n\nfunction useLargerValueOfLastTwoValues(value: number) {\n const refLatestTwoValues = useRef([0, 0]);\n\n refLatestTwoValues.current.shift();\n refLatestTwoValues.current.push(value);\n\n return Math.max(...refLatestTwoValues.current);\n}\n\n\nexport default function useUnstableCollapsibleAppBar(userOptions: Options = defaultOptions): CollapsibleAppBar {\n const {\n translucent,\n shouldTranslateYReset,\n }: 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 appBarMaxHeight = useLargerValueOfLastTwoValues(appBarHeight);\n const [collapsibleToolbarHeight, onCollapsibleToolbarLayout] = useHeight();\n\n const maxTranslateY = Animated.useDerivedValue(() => -collapsibleToolbarHeight);\n\n const translateY = Animated.useSharedValue<number>(0);\n const lastTranslateY = Animated.useSharedValue<number>(0);\n const lastOffsetY = Animated.useSharedValue<number>(0);\n const prevOffsetY = Animated.useSharedValue<number>(0);\n const overlapped = Animated.useSharedValue<boolean>(false);\n const vectorY = Animated.useSharedValue<number>(0);\n\n const elevationStyle = useElevationStyle(4);\n const animatedStyle = Animated.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 if (shouldTranslateYReset) {\n translateY.value = Animated.withTiming(0, {\n duration: ANIMATION_DURATION_MILLIS,\n });\n\n vectorY.value = 0;\n offsetsRef.current = [];\n overlapped.value = false;\n }\n\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 = Animated.withTiming(0, {\n duration: ANIMATION_DURATION_MILLIS,\n });\n\n vectorY.value = 0;\n }\n };\n\n const scrollHandler = Animated.useAnimatedScrollHandler({\n onBeginDrag: () => {\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 const deltaY = offsetY - prevOffsetY.value;\n vectorY.value = (vectorY.value * deltaY >= 0 && offsetY > 0) ? vectorY.value + deltaY : deltaY;\n prevOffsetY.value = offsetY;\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 = Animated.withTiming(Math.min(Math.max(-offsetY, maxTy), 0), {\n duration: ANIMATION_DURATION_MILLIS,\n });\n }\n } else {\n if (ty === maxTy) {\n translateY.value = Animated.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 = Animated.withTiming(nextTranslateY, {\n duration: ANIMATION_DURATION_MILLIS,\n });\n },\n });\n\n const hasCollapsible = collapsibleToolbarHeight > 0;\n\n const appBarStyle = [\n animatedStyle,\n translucent ? { paddingTop: safeAreaInsets.top } : undefined,\n hasCollapsible ? styles.floating : undefined,\n ];\n\n return {\n appBarStyle,\n vectorY,\n onAppBarLayout,\n onCollapsibleToolbarLayout,\n onScroll: scrollHandler,\n onScrollViewChanged,\n scrollContentInsets: { top: hasCollapsible ? appBarMaxHeight : 0 },\n };\n};\n"]}
|
|
@@ -14,6 +14,7 @@ export interface ContentInsets {
|
|
|
14
14
|
}
|
|
15
15
|
export interface Options {
|
|
16
16
|
translucent?: boolean;
|
|
17
|
+
shouldTranslateYReset?: boolean;
|
|
17
18
|
}
|
|
18
19
|
export interface CollapsibleAppBar {
|
|
19
20
|
appBarStyle: ViewStyleProp;
|
|
@@ -24,5 +25,5 @@ export interface CollapsibleAppBar {
|
|
|
24
25
|
onScrollViewChanged: (index: number) => void;
|
|
25
26
|
scrollContentInsets: ContentInsets;
|
|
26
27
|
}
|
|
27
|
-
export default function
|
|
28
|
+
export default function useUnstableCollapsibleAppBar(userOptions?: Options): CollapsibleAppBar;
|
|
28
29
|
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fountain-ui/lab",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.16.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"author": "Fountain-UI Team",
|
|
6
6
|
"description": "Incubator for Fountain-UI React components.",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"dependencies": {
|
|
18
18
|
"@emotion/react": "^11.4.1",
|
|
19
19
|
"@emotion/styled": "^11.0.0",
|
|
20
|
-
"@fountain-ui/icons": "^1.
|
|
20
|
+
"@fountain-ui/icons": "^1.15.1",
|
|
21
21
|
"@fountain-ui/utils": "^1.1.0",
|
|
22
22
|
"react-native-calendars": "1.1267.0"
|
|
23
23
|
},
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
}
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
|
-
"@fountain-ui/core": "^1.
|
|
56
|
+
"@fountain-ui/core": "^1.14.1",
|
|
57
57
|
"@gorhom/bottom-sheet": "4.1.3",
|
|
58
58
|
"@react-native-community/viewpager": "^4.2.2",
|
|
59
59
|
"@types/react-native-snap-carousel": "^3.8.4",
|
|
@@ -85,5 +85,5 @@
|
|
|
85
85
|
"publishConfig": {
|
|
86
86
|
"access": "public"
|
|
87
87
|
},
|
|
88
|
-
"gitHead": "
|
|
88
|
+
"gitHead": "db43f98577b3009518570d7b9b3df42f4fe16a51"
|
|
89
89
|
}
|
|
@@ -23,6 +23,7 @@ export interface ContentInsets {
|
|
|
23
23
|
|
|
24
24
|
export interface Options {
|
|
25
25
|
translucent?: boolean;
|
|
26
|
+
shouldTranslateYReset?: boolean;
|
|
26
27
|
}
|
|
27
28
|
|
|
28
29
|
export interface CollapsibleAppBar {
|
|
@@ -37,23 +38,29 @@ export interface CollapsibleAppBar {
|
|
|
37
38
|
|
|
38
39
|
const defaultOptions: Required<Options> = {
|
|
39
40
|
translucent: false,
|
|
41
|
+
shouldTranslateYReset: false,
|
|
40
42
|
};
|
|
41
43
|
|
|
42
44
|
const ANIMATION_DURATION_MILLIS = 100;
|
|
43
45
|
|
|
44
46
|
const SUPPORTS_DRAG_DETECTION = Platform.OS !== 'web';
|
|
45
47
|
|
|
46
|
-
function useMaxNumber(value: number) {
|
|
47
|
-
const refMaxValue = useRef(value);
|
|
48
48
|
|
|
49
|
-
|
|
49
|
+
function useLargerValueOfLastTwoValues(value: number) {
|
|
50
|
+
const refLatestTwoValues = useRef([0, 0]);
|
|
50
51
|
|
|
51
|
-
|
|
52
|
+
refLatestTwoValues.current.shift();
|
|
53
|
+
refLatestTwoValues.current.push(value);
|
|
54
|
+
|
|
55
|
+
return Math.max(...refLatestTwoValues.current);
|
|
52
56
|
}
|
|
53
57
|
|
|
54
58
|
|
|
55
|
-
export default function
|
|
56
|
-
const {
|
|
59
|
+
export default function useUnstableCollapsibleAppBar(userOptions: Options = defaultOptions): CollapsibleAppBar {
|
|
60
|
+
const {
|
|
61
|
+
translucent,
|
|
62
|
+
shouldTranslateYReset,
|
|
63
|
+
}: Required<Options> = {
|
|
57
64
|
...defaultOptions,
|
|
58
65
|
...userOptions,
|
|
59
66
|
};
|
|
@@ -63,7 +70,7 @@ export default function useCollapsibleAppBar(userOptions: Options = defaultOptio
|
|
|
63
70
|
const safeAreaInsets = useSafeAreaInsets();
|
|
64
71
|
|
|
65
72
|
const [appBarHeight, onAppBarLayout] = useHeight();
|
|
66
|
-
const appBarMaxHeight =
|
|
73
|
+
const appBarMaxHeight = useLargerValueOfLastTwoValues(appBarHeight);
|
|
67
74
|
const [collapsibleToolbarHeight, onCollapsibleToolbarLayout] = useHeight();
|
|
68
75
|
|
|
69
76
|
const maxTranslateY = Animated.useDerivedValue(() => -collapsibleToolbarHeight);
|
|
@@ -96,6 +103,16 @@ export default function useCollapsibleAppBar(userOptions: Options = defaultOptio
|
|
|
96
103
|
const onScrollViewChanged = (nextIndex: number) => {
|
|
97
104
|
const prevIndex = indexRef.current;
|
|
98
105
|
if (prevIndex === nextIndex) {
|
|
106
|
+
if (shouldTranslateYReset) {
|
|
107
|
+
translateY.value = Animated.withTiming(0, {
|
|
108
|
+
duration: ANIMATION_DURATION_MILLIS,
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
vectorY.value = 0;
|
|
112
|
+
offsetsRef.current = [];
|
|
113
|
+
overlapped.value = false;
|
|
114
|
+
}
|
|
115
|
+
|
|
99
116
|
return;
|
|
100
117
|
}
|
|
101
118
|
|
|
@@ -133,7 +150,7 @@ export default function useCollapsibleAppBar(userOptions: Options = defaultOptio
|
|
|
133
150
|
const maxTy = maxTranslateY.value;
|
|
134
151
|
|
|
135
152
|
const deltaY = offsetY - prevOffsetY.value;
|
|
136
|
-
vectorY.value = vectorY.value * deltaY >= 0 && offsetY
|
|
153
|
+
vectorY.value = (vectorY.value * deltaY >= 0 && offsetY > 0) ? vectorY.value + deltaY : deltaY;
|
|
137
154
|
prevOffsetY.value = offsetY;
|
|
138
155
|
|
|
139
156
|
if (SUPPORTS_DRAG_DETECTION) {
|