@fountain-ui/lab 1.21.1 → 2.0.0-beta.11
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/AnimatedY/AnimatedY.js +10 -14
- package/build/commonjs/AnimatedY/AnimatedY.js.map +1 -1
- package/build/commonjs/AnimatedY/AnimatedYProps.js.map +1 -1
- package/build/commonjs/AnimatedY/index.js.map +1 -1
- package/build/commonjs/BottomSheet/BottomSheetNative.js +8 -2
- package/build/commonjs/BottomSheet/BottomSheetNative.js.map +1 -1
- package/build/commonjs/BottomSheet/BottomSheetProps.js.map +1 -1
- package/build/commonjs/BottomSheet/BottomSheetWeb.js +2 -6
- package/build/commonjs/BottomSheet/BottomSheetWeb.js.map +1 -1
- package/build/commonjs/BottomSheet/TransparentBackdrop.js +1 -1
- package/build/commonjs/BottomSheet/TransparentBackdrop.js.map +1 -1
- package/build/commonjs/BottomSheet/index.js.map +1 -1
- package/build/commonjs/BottomSheet/index.native.js.map +1 -1
- package/build/commonjs/Carousel/CarouselNative.js.map +1 -1
- package/build/commonjs/Carousel/CarouselProps.js.map +1 -1
- package/build/commonjs/Carousel/CarouselWeb.js +1 -1
- package/build/commonjs/Carousel/CarouselWeb.js.map +1 -1
- package/build/commonjs/Carousel/index.js.map +1 -1
- package/build/commonjs/Carousel/index.native.js.map +1 -1
- package/build/commonjs/Carousel/utils.js +1 -1
- package/build/commonjs/Carousel/utils.js.map +1 -1
- package/build/commonjs/ComicViewer/ComicViewer.js +168 -0
- package/build/commonjs/ComicViewer/ComicViewer.js.map +1 -0
- package/build/commonjs/ComicViewer/ComicViewerItemProps.js +6 -0
- package/build/commonjs/ComicViewer/ComicViewerItemProps.js.map +1 -0
- package/build/commonjs/ComicViewer/ComicViewerProps.js +2 -0
- package/build/commonjs/ComicViewer/ComicViewerProps.js.map +1 -0
- package/build/commonjs/ComicViewer/ViewerItem.js +88 -0
- package/build/commonjs/ComicViewer/ViewerItem.js.map +1 -0
- package/build/commonjs/ComicViewer/index.js +16 -0
- package/build/commonjs/ComicViewer/index.js.map +1 -0
- package/build/commonjs/DateTimePicker/DateTimePicker.js +7 -1
- package/build/commonjs/DateTimePicker/DateTimePicker.js.map +1 -1
- package/build/commonjs/DateTimePicker/DateTimePickerProps.js.map +1 -1
- package/build/commonjs/DateTimePicker/DateTimePickerProvider.js.map +1 -1
- package/build/commonjs/DateTimePicker/YearPicker.js +22 -17
- package/build/commonjs/DateTimePicker/YearPicker.js.map +1 -1
- package/build/commonjs/DateTimePicker/index.js +4 -4
- package/build/commonjs/DateTimePicker/index.js.map +1 -1
- package/build/commonjs/DateTimePicker/utils.js +2 -1
- package/build/commonjs/DateTimePicker/utils.js.map +1 -1
- package/build/commonjs/FlipCard/FlipCard.js +7 -13
- package/build/commonjs/FlipCard/FlipCard.js.map +1 -1
- package/build/commonjs/FlipCard/FlipCardProps.js.map +1 -1
- package/build/commonjs/FlipCard/index.js.map +1 -1
- package/build/commonjs/StatusBarProvider/Provider.js +1 -1
- package/build/commonjs/StatusBarProvider/Provider.js.map +1 -1
- package/build/commonjs/StatusBarProvider/StatusBarProvider.js.map +1 -1
- package/build/commonjs/StatusBarProvider/StatusBarProviderProps.js.map +1 -1
- package/build/commonjs/StatusBarProvider/index.js.map +1 -1
- package/build/commonjs/ViewPager/ChildrenMemoizedPage.js +90 -22
- package/build/commonjs/ViewPager/ChildrenMemoizedPage.js.map +1 -1
- package/build/commonjs/ViewPager/ViewPagerNative.js +46 -36
- package/build/commonjs/ViewPager/ViewPagerNative.js.map +1 -1
- package/build/commonjs/ViewPager/ViewPagerProps.js.map +1 -1
- package/build/commonjs/ViewPager/ViewPagerWeb.js +32 -25
- package/build/commonjs/ViewPager/ViewPagerWeb.js.map +1 -1
- package/build/commonjs/ViewPager/index.js.map +1 -1
- package/build/commonjs/ViewPager/index.native.js.map +1 -1
- package/build/commonjs/ViewPager/utils.js +3 -39
- package/build/commonjs/ViewPager/utils.js.map +1 -1
- package/build/commonjs/hooks/index.js.map +1 -1
- package/build/commonjs/hooks/useAppbarStyles.js.map +1 -1
- package/build/commonjs/hooks/useElevationStyle.js.map +1 -1
- package/build/commonjs/hooks/useHeight.js +5 -4
- package/build/commonjs/hooks/useHeight.js.map +1 -1
- package/build/commonjs/hooks/useUnstableCollapsibleAppBar.js +56 -57
- package/build/commonjs/hooks/useUnstableCollapsibleAppBar.js.map +1 -1
- package/build/commonjs/hooks/useUnstableToggleDisplayStyle.js +9 -11
- package/build/commonjs/hooks/useUnstableToggleDisplayStyle.js.map +1 -1
- package/build/commonjs/index.js +25 -4
- package/build/commonjs/index.js.map +1 -1
- package/build/module/AnimatedY/AnimatedY.js +11 -10
- package/build/module/AnimatedY/AnimatedY.js.map +1 -1
- package/build/module/AnimatedY/AnimatedYProps.js.map +1 -1
- package/build/module/AnimatedY/index.js.map +1 -1
- package/build/module/BottomSheet/BottomSheetNative.js +8 -2
- package/build/module/BottomSheet/BottomSheetNative.js.map +1 -1
- package/build/module/BottomSheet/BottomSheetProps.js.map +1 -1
- package/build/module/BottomSheet/BottomSheetWeb.js +2 -6
- package/build/module/BottomSheet/BottomSheetWeb.js.map +1 -1
- package/build/module/BottomSheet/TransparentBackdrop.js +1 -1
- package/build/module/BottomSheet/TransparentBackdrop.js.map +1 -1
- package/build/module/BottomSheet/index.js.map +1 -1
- package/build/module/BottomSheet/index.native.js.map +1 -1
- package/build/module/Carousel/CarouselNative.js.map +1 -1
- package/build/module/Carousel/CarouselProps.js.map +1 -1
- package/build/module/Carousel/CarouselWeb.js +1 -1
- package/build/module/Carousel/CarouselWeb.js.map +1 -1
- package/build/module/Carousel/index.js.map +1 -1
- package/build/module/Carousel/index.native.js.map +1 -1
- package/build/module/Carousel/utils.js.map +1 -1
- package/build/module/ComicViewer/ComicViewer.js +151 -0
- package/build/module/ComicViewer/ComicViewer.js.map +1 -0
- package/build/module/ComicViewer/ComicViewerItemProps.js +2 -0
- package/build/module/ComicViewer/ComicViewerItemProps.js.map +1 -0
- package/build/module/ComicViewer/ComicViewerProps.js +2 -0
- package/build/module/ComicViewer/ComicViewerProps.js.map +1 -0
- package/build/module/ComicViewer/ViewerItem.js +72 -0
- package/build/module/ComicViewer/ViewerItem.js.map +1 -0
- package/build/module/ComicViewer/index.js +2 -0
- package/build/module/ComicViewer/index.js.map +1 -0
- package/build/module/DateTimePicker/DateTimePicker.js +7 -1
- package/build/module/DateTimePicker/DateTimePicker.js.map +1 -1
- package/build/module/DateTimePicker/DateTimePickerProps.js.map +1 -1
- package/build/module/DateTimePicker/DateTimePickerProvider.js.map +1 -1
- package/build/module/DateTimePicker/YearPicker.js +22 -17
- package/build/module/DateTimePicker/YearPicker.js.map +1 -1
- package/build/module/DateTimePicker/index.js.map +1 -1
- package/build/module/DateTimePicker/utils.js +2 -1
- package/build/module/DateTimePicker/utils.js.map +1 -1
- package/build/module/FlipCard/FlipCard.js +7 -7
- package/build/module/FlipCard/FlipCard.js.map +1 -1
- package/build/module/FlipCard/FlipCardProps.js.map +1 -1
- package/build/module/FlipCard/index.js.map +1 -1
- package/build/module/StatusBarProvider/Provider.js.map +1 -1
- package/build/module/StatusBarProvider/StatusBarProvider.js.map +1 -1
- package/build/module/StatusBarProvider/StatusBarProviderProps.js.map +1 -1
- package/build/module/StatusBarProvider/index.js.map +1 -1
- package/build/module/ViewPager/ChildrenMemoizedPage.js +85 -23
- package/build/module/ViewPager/ChildrenMemoizedPage.js.map +1 -1
- package/build/module/ViewPager/ViewPagerNative.js +43 -32
- package/build/module/ViewPager/ViewPagerNative.js.map +1 -1
- package/build/module/ViewPager/ViewPagerProps.js.map +1 -1
- package/build/module/ViewPager/ViewPagerWeb.js +26 -23
- package/build/module/ViewPager/ViewPagerWeb.js.map +1 -1
- package/build/module/ViewPager/index.js.map +1 -1
- package/build/module/ViewPager/index.native.js.map +1 -1
- package/build/module/ViewPager/utils.js +1 -31
- package/build/module/ViewPager/utils.js.map +1 -1
- package/build/module/hooks/index.js.map +1 -1
- package/build/module/hooks/useAppbarStyles.js.map +1 -1
- package/build/module/hooks/useElevationStyle.js.map +1 -1
- package/build/module/hooks/useHeight.js +4 -3
- package/build/module/hooks/useHeight.js.map +1 -1
- package/build/module/hooks/useUnstableCollapsibleAppBar.js +58 -43
- package/build/module/hooks/useUnstableCollapsibleAppBar.js.map +1 -1
- package/build/module/hooks/useUnstableToggleDisplayStyle.js +9 -7
- package/build/module/hooks/useUnstableToggleDisplayStyle.js.map +1 -1
- package/build/module/index.js +2 -0
- package/build/module/index.js.map +1 -1
- package/build/typescript/AnimatedY/AnimatedY.d.ts +0 -1
- package/build/typescript/BottomSheet/BottomSheetNative.d.ts +0 -1
- package/build/typescript/BottomSheet/BottomSheetWeb.d.ts +0 -1
- package/build/typescript/BottomSheet/TransparentBackdrop.d.ts +0 -1
- package/build/typescript/Carousel/CarouselNative.d.ts +0 -1
- package/build/typescript/ComicViewer/ComicViewer.d.ts +2 -0
- package/build/typescript/ComicViewer/ComicViewerItemProps.d.ts +12 -0
- package/build/typescript/ComicViewer/ComicViewerProps.d.ts +76 -0
- package/build/typescript/ComicViewer/ViewerItem.d.ts +7 -0
- package/build/typescript/ComicViewer/index.d.ts +3 -0
- package/build/typescript/DateTimePicker/DateTimePicker.d.ts +0 -1
- package/build/typescript/DateTimePicker/YearPicker.d.ts +0 -1
- package/build/typescript/FlipCard/FlipCard.d.ts +0 -1
- package/build/typescript/StatusBarProvider/StatusBarProvider.d.ts +0 -1
- package/build/typescript/ViewPager/ChildrenMemoizedPage.d.ts +2 -1
- package/build/typescript/ViewPager/ViewPagerNative.d.ts +4 -2
- package/build/typescript/ViewPager/ViewPagerProps.d.ts +20 -19
- package/build/typescript/ViewPager/ViewPagerWeb.d.ts +4 -2
- package/build/typescript/ViewPager/index.d.ts +1 -1
- package/build/typescript/ViewPager/utils.d.ts +2 -19
- package/build/typescript/hooks/useUnstableCollapsibleAppBar.d.ts +2 -3
- package/build/typescript/hooks/useUnstableToggleDisplayStyle.d.ts +2 -2
- package/build/typescript/index.d.ts +2 -0
- package/package.json +13 -13
- package/src/AnimatedY/AnimatedY.tsx +13 -10
- package/src/BottomSheet/BottomSheetNative.tsx +6 -0
- package/src/ComicViewer/ComicViewer.tsx +162 -0
- package/src/ComicViewer/ComicViewerItemProps.ts +15 -0
- package/src/ComicViewer/ComicViewerProps.ts +90 -0
- package/src/ComicViewer/ViewerItem.tsx +76 -0
- package/src/ComicViewer/index.ts +3 -0
- package/src/DateTimePicker/DateTimePicker.tsx +6 -0
- package/src/DateTimePicker/YearPicker.tsx +2 -1
- package/src/FlipCard/FlipCard.tsx +8 -8
- package/src/ViewPager/ChildrenMemoizedPage.tsx +91 -22
- package/src/ViewPager/ViewPagerNative.tsx +47 -35
- package/src/ViewPager/ViewPagerProps.ts +20 -19
- package/src/ViewPager/ViewPagerWeb.tsx +34 -29
- package/src/ViewPager/index.ts +1 -1
- package/src/ViewPager/utils.tsx +2 -55
- package/src/hooks/useHeight.ts +2 -2
- package/src/hooks/useUnstableCollapsibleAppBar.ts +59 -42
- package/src/hooks/useUnstableToggleDisplayStyle.ts +8 -6
- package/src/index.ts +3 -0
- package/build/commonjs/hooks/useWidth.js +0 -29
- package/build/commonjs/hooks/useWidth.js.map +0 -1
- package/build/module/hooks/useWidth.js +0 -15
- package/build/module/hooks/useWidth.js.map +0 -1
- package/build/typescript/hooks/useWidth.d.ts +0 -2
- package/src/hooks/useWidth.ts +0 -17
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fountain-ui/lab",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0-beta.11",
|
|
4
4
|
"private": false,
|
|
5
5
|
"author": "Fountain-UI Team",
|
|
6
6
|
"description": "Incubator for Fountain-UI React components.",
|
|
@@ -15,20 +15,21 @@
|
|
|
15
15
|
"prepare": "bob build"
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@emotion/react": "^11.
|
|
19
|
-
"@emotion/styled": "^11.
|
|
20
|
-
"@fountain-ui/icons": "^
|
|
21
|
-
"@fountain-ui/utils": "^
|
|
18
|
+
"@emotion/react": "^11.10.0",
|
|
19
|
+
"@emotion/styled": "^11.10.0",
|
|
20
|
+
"@fountain-ui/icons": "^2.0.0-beta.6",
|
|
21
|
+
"@fountain-ui/utils": "^2.0.0-beta.3",
|
|
22
22
|
"react-native-calendars": "1.1267.0"
|
|
23
23
|
},
|
|
24
24
|
"peerDependencies": {
|
|
25
|
-
"@fountain-ui/core": "^
|
|
25
|
+
"@fountain-ui/core": "^2.0.0-beta.3",
|
|
26
26
|
"@gorhom/bottom-sheet": "^4.1.3",
|
|
27
|
-
"@react-native-community/viewpager": "> 4.2.x",
|
|
28
27
|
"date-fns": "^2.0.0",
|
|
29
28
|
"react": "^16.8.0 || ^17.0.0",
|
|
30
29
|
"react-dom": "^16.8.0 || ^17.0.0",
|
|
31
30
|
"react-native": "^0.63.0",
|
|
31
|
+
"react-native-gesture-handler": "^2.0.0",
|
|
32
|
+
"react-native-pager-view": "^4.0.0",
|
|
32
33
|
"react-native-snap-carousel": "^3.9.0",
|
|
33
34
|
"react-slick": "^0.25.0"
|
|
34
35
|
},
|
|
@@ -36,9 +37,6 @@
|
|
|
36
37
|
"@gorhom/bottom-sheet": {
|
|
37
38
|
"optional": true
|
|
38
39
|
},
|
|
39
|
-
"@react-native-community/viewpager": {
|
|
40
|
-
"optional": true
|
|
41
|
-
},
|
|
42
40
|
"react-dom": {
|
|
43
41
|
"optional": true
|
|
44
42
|
},
|
|
@@ -48,17 +46,19 @@
|
|
|
48
46
|
"react-slick": {
|
|
49
47
|
"optional": true
|
|
50
48
|
},
|
|
49
|
+
"react-native-pager-view": {
|
|
50
|
+
"optional": true
|
|
51
|
+
},
|
|
51
52
|
"react-native-snap-carousel": {
|
|
52
53
|
"optional": true
|
|
53
54
|
}
|
|
54
55
|
},
|
|
55
56
|
"devDependencies": {
|
|
56
|
-
"@fountain-ui/core": "^1.19.1",
|
|
57
57
|
"@gorhom/bottom-sheet": "4.1.3",
|
|
58
|
-
"@react-native-community/viewpager": "^4.2.2",
|
|
59
58
|
"@types/react-native-snap-carousel": "^3.8.4",
|
|
60
59
|
"@types/react-slick": "^0.23.5",
|
|
61
60
|
"date-fns": "^2.23.0",
|
|
61
|
+
"react-native-pager-view": "^4.2.4",
|
|
62
62
|
"react-native-safe-area-context": "^3.3.2",
|
|
63
63
|
"react-native-snap-carousel": "^3.9.1",
|
|
64
64
|
"react-slick": "^0.28.1"
|
|
@@ -85,5 +85,5 @@
|
|
|
85
85
|
"publishConfig": {
|
|
86
86
|
"access": "public"
|
|
87
87
|
},
|
|
88
|
-
"gitHead": "
|
|
88
|
+
"gitHead": "80988af3fdfd671fcb655d4b36a017ce13baf29e"
|
|
89
89
|
}
|
|
@@ -1,7 +1,13 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import
|
|
1
|
+
import React, { useEffect } from 'react';
|
|
2
|
+
import type { WithTimingConfig } from 'react-native-reanimated';
|
|
3
|
+
import Animated, { Easing, useAnimatedStyle, useSharedValue, withTiming } from 'react-native-reanimated';
|
|
3
4
|
import type AnimatedYProps from './AnimatedYProps';
|
|
4
5
|
|
|
6
|
+
const ANIMATION_CONFIG: Readonly<WithTimingConfig> = {
|
|
7
|
+
duration: 150,
|
|
8
|
+
easing: Easing.out(Easing.exp),
|
|
9
|
+
};
|
|
10
|
+
|
|
5
11
|
export default function AnimatedY(props: AnimatedYProps) {
|
|
6
12
|
const {
|
|
7
13
|
children,
|
|
@@ -9,17 +15,14 @@ export default function AnimatedY(props: AnimatedYProps) {
|
|
|
9
15
|
style,
|
|
10
16
|
} = props;
|
|
11
17
|
|
|
12
|
-
const animatedY =
|
|
13
|
-
const animatedStyle =
|
|
18
|
+
const animatedY = useSharedValue(translateY);
|
|
19
|
+
const animatedStyle = useAnimatedStyle(() => ({
|
|
14
20
|
transform: [{ translateY: animatedY.value }],
|
|
15
|
-
}));
|
|
21
|
+
}), []);
|
|
16
22
|
|
|
17
|
-
|
|
23
|
+
useEffect(() => {
|
|
18
24
|
if (translateY >= 0) {
|
|
19
|
-
animatedY.value =
|
|
20
|
-
duration: 150,
|
|
21
|
-
easing: Easing.out(Easing.exp),
|
|
22
|
-
});
|
|
25
|
+
animatedY.value = withTiming(translateY, ANIMATION_CONFIG);
|
|
23
26
|
}
|
|
24
27
|
}, [translateY]);
|
|
25
28
|
|
|
@@ -46,6 +46,7 @@ export default function BottomSheet(props: BottomSheetProps) {
|
|
|
46
46
|
} else if (indexRef.current >= 0 && index < 0) {
|
|
47
47
|
bottomSheetRef.current?.dismiss();
|
|
48
48
|
} else {
|
|
49
|
+
// @ts-ignore
|
|
49
50
|
bottomSheetRef.current?.snapToIndex(index);
|
|
50
51
|
}
|
|
51
52
|
}, [index]);
|
|
@@ -60,6 +61,9 @@ export default function BottomSheet(props: BottomSheetProps) {
|
|
|
60
61
|
web: shadow?.boxShadow,
|
|
61
62
|
}),
|
|
62
63
|
};
|
|
64
|
+
const backgroundStyle = {
|
|
65
|
+
backgroundColor: theme.palette.paper.default,
|
|
66
|
+
};
|
|
63
67
|
|
|
64
68
|
const isBackdropTransparent = backdropOpacity <= 0;
|
|
65
69
|
|
|
@@ -76,6 +80,8 @@ export default function BottomSheet(props: BottomSheetProps) {
|
|
|
76
80
|
<BottomSheetModalProvider>
|
|
77
81
|
<BottomSheetModal
|
|
78
82
|
backdropComponent={isBackdropTransparent ? TransparentBackdrop : OpacityAwareBackdrop}
|
|
83
|
+
// @ts-ignore
|
|
84
|
+
backgroundStyle={backgroundStyle}
|
|
79
85
|
index={index}
|
|
80
86
|
handleComponent={NoHandle}
|
|
81
87
|
onChange={handleChange}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
2
|
+
import { FlatList, ListRenderItem, ViewToken } from 'react-native';
|
|
3
|
+
import * as R from 'ramda';
|
|
4
|
+
import { ComicViewerItemData, default as ComicViewerProps, ErrorInfo } from './ComicViewerProps';
|
|
5
|
+
import type ComicViewerItemProps from './ComicViewerItemProps';
|
|
6
|
+
import ViewerItem from './ViewerItem';
|
|
7
|
+
|
|
8
|
+
const getItemHeights = <T, >(items: ComicViewerItemProps<T>[]): number[] => R.map((content: ComicViewerItemProps<T>) => content.height)(items);
|
|
9
|
+
const appender = (left: number, right: number): [number, number] => [left + right, left + right];
|
|
10
|
+
const getHeightAccum = (itemHeights: number[]): [number, number[]] => R.mapAccum(appender, 0, itemHeights);
|
|
11
|
+
|
|
12
|
+
const keyExtractor = <T, >(item: ComicViewerItemProps<T>) => item.id;
|
|
13
|
+
|
|
14
|
+
export default function ComicViewer<T>(props: ComicViewerProps<T>) {
|
|
15
|
+
const {
|
|
16
|
+
data,
|
|
17
|
+
errorDebounceMillis = 500,
|
|
18
|
+
errorRetryCount = 3,
|
|
19
|
+
initialNumToRender = 1,
|
|
20
|
+
initialScrollPercentage = 0,
|
|
21
|
+
itemVisiblePercentThreshold = 0,
|
|
22
|
+
onError,
|
|
23
|
+
viewerWidth,
|
|
24
|
+
windowSize = 3,
|
|
25
|
+
...otherProps
|
|
26
|
+
} = props;
|
|
27
|
+
|
|
28
|
+
const flatListRef = useRef<FlatList>(null);
|
|
29
|
+
|
|
30
|
+
const errors = useRef<Map<string, number>>(new Map());
|
|
31
|
+
const debounceTimeOut = useRef<NodeJS.Timeout | null>(null);
|
|
32
|
+
|
|
33
|
+
const resourceString = R.toString(R.map((itemData: ComicViewerItemData) => itemData.sourceUrl)(data));
|
|
34
|
+
|
|
35
|
+
const initialItems = R.map((itemData: ComicViewerItemData<T>) => ({
|
|
36
|
+
...itemData,
|
|
37
|
+
isViewable: false,
|
|
38
|
+
width: viewerWidth,
|
|
39
|
+
height: (itemData.height * viewerWidth) / itemData.width,
|
|
40
|
+
}))(data);
|
|
41
|
+
|
|
42
|
+
const [items, setItems] = useState<ComicViewerItemProps<T>[]>(initialItems);
|
|
43
|
+
|
|
44
|
+
const itemHeights = getItemHeights(items);
|
|
45
|
+
const itemHeightAccum = getHeightAccum(itemHeights);
|
|
46
|
+
|
|
47
|
+
const viewabilityConfig = useMemo(() => ({
|
|
48
|
+
itemVisiblePercentThreshold,
|
|
49
|
+
}), [itemVisiblePercentThreshold]);
|
|
50
|
+
|
|
51
|
+
const getItemLayout = useCallback((data: any, index: number) => {
|
|
52
|
+
const offsets = R.prepend(0, itemHeightAccum[1]);
|
|
53
|
+
|
|
54
|
+
return {
|
|
55
|
+
length: itemHeights[index],
|
|
56
|
+
offset: offsets[index],
|
|
57
|
+
index,
|
|
58
|
+
};
|
|
59
|
+
}, [itemHeights]);
|
|
60
|
+
|
|
61
|
+
const onViewableItemsChanged = useRef(({ viewableItems }: {
|
|
62
|
+
viewableItems: Array<ViewToken>,
|
|
63
|
+
}) => {
|
|
64
|
+
setItems((prev: ComicViewerItemProps<T>[]) => {
|
|
65
|
+
const viewableItemIds = R.map((viewableItem: ViewToken) => viewableItem.item.id)(viewableItems);
|
|
66
|
+
|
|
67
|
+
return R.map((prevItem: ComicViewerItemProps<T>) => ({
|
|
68
|
+
...prevItem,
|
|
69
|
+
isViewable: R.includes(prevItem.id, viewableItemIds),
|
|
70
|
+
}))([...prev]);
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
const onErrorHandler = (errors: ErrorInfo[]) => {
|
|
75
|
+
const isRetryLimited = R.any((error: ErrorInfo) => error.count >= errorRetryCount)(errors);
|
|
76
|
+
|
|
77
|
+
if (isRetryLimited) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
onError && onError(errors);
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const itemErrorHandler = useCallback((errorInfo: ErrorInfo) => {
|
|
85
|
+
errors.current.set(errorInfo.id, errorInfo.count);
|
|
86
|
+
|
|
87
|
+
if (debounceTimeOut.current) {
|
|
88
|
+
clearTimeout(debounceTimeOut.current);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
debounceTimeOut.current = setTimeout(function () {
|
|
92
|
+
const errorsArray = Array.from(errors.current.entries());
|
|
93
|
+
const errorsInfo = R.map(([key, value]: [string, number]) => ({
|
|
94
|
+
id: key,
|
|
95
|
+
count: value,
|
|
96
|
+
}))(errorsArray);
|
|
97
|
+
|
|
98
|
+
onErrorHandler([...errorsInfo]);
|
|
99
|
+
errors.current.clear();
|
|
100
|
+
}, errorDebounceMillis);
|
|
101
|
+
}, [errorDebounceMillis, errors.current]);
|
|
102
|
+
|
|
103
|
+
const renderItem: ListRenderItem<ComicViewerItemProps<T>> = useCallback(({ item }) => {
|
|
104
|
+
const props = {
|
|
105
|
+
...item,
|
|
106
|
+
onError: itemErrorHandler,
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
return <ViewerItem props={props}/>;
|
|
110
|
+
}, []);
|
|
111
|
+
|
|
112
|
+
useEffect(() => {
|
|
113
|
+
setItems((prev: ComicViewerItemProps<T>[]) => {
|
|
114
|
+
return R.map((prevItem: ComicViewerItemProps<T>) => {
|
|
115
|
+
const currentData = R.find((currentItemData: ComicViewerItemData<T>) => prevItem.id === currentItemData.id)(data);
|
|
116
|
+
|
|
117
|
+
if (currentData && (currentData.sourceUrl !== prevItem.sourceUrl)) {
|
|
118
|
+
return {
|
|
119
|
+
...prevItem,
|
|
120
|
+
sourceUrl: currentData.sourceUrl,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return prevItem;
|
|
125
|
+
})([...prev]);
|
|
126
|
+
});
|
|
127
|
+
}, [resourceString]);
|
|
128
|
+
|
|
129
|
+
useEffect(() => {
|
|
130
|
+
const newItems = R.map((item: ComicViewerItemProps<T>) => ({
|
|
131
|
+
...item,
|
|
132
|
+
width: viewerWidth,
|
|
133
|
+
height: (item.height * viewerWidth) / item.width,
|
|
134
|
+
}))(items);
|
|
135
|
+
|
|
136
|
+
setItems(newItems);
|
|
137
|
+
}, [viewerWidth]);
|
|
138
|
+
|
|
139
|
+
useEffect(() => {
|
|
140
|
+
const totalHeight = itemHeightAccum[0];
|
|
141
|
+
const offset = Math.floor((initialScrollPercentage / 100) * totalHeight);
|
|
142
|
+
|
|
143
|
+
if (flatListRef.current) {
|
|
144
|
+
flatListRef.current.scrollToOffset({ offset, animated: false });
|
|
145
|
+
}
|
|
146
|
+
}, [flatListRef.current]);
|
|
147
|
+
|
|
148
|
+
return (
|
|
149
|
+
<FlatList
|
|
150
|
+
data={items}
|
|
151
|
+
getItemLayout={getItemLayout}
|
|
152
|
+
initialNumToRender={initialNumToRender}
|
|
153
|
+
keyExtractor={keyExtractor}
|
|
154
|
+
onViewableItemsChanged={onViewableItemsChanged.current}
|
|
155
|
+
ref={flatListRef}
|
|
156
|
+
renderItem={renderItem}
|
|
157
|
+
viewabilityConfig={viewabilityConfig}
|
|
158
|
+
windowSize={windowSize}
|
|
159
|
+
{...otherProps}
|
|
160
|
+
/>
|
|
161
|
+
);
|
|
162
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { ComicViewerItemData, ErrorInfo } from './ComicViewerProps';
|
|
2
|
+
|
|
3
|
+
type ComicViewerItemProps<T> = ComicViewerItemData<T> & {
|
|
4
|
+
/**
|
|
5
|
+
* FlatListItem is viewable in screen.
|
|
6
|
+
*/
|
|
7
|
+
isViewable: boolean;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Error handler
|
|
11
|
+
*/
|
|
12
|
+
onError?: (errorInfo: ErrorInfo) => void;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export default ComicViewerItemProps;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { ComponentProps } from '@fountain-ui/core';
|
|
2
|
+
|
|
3
|
+
export interface ErrorInfo {
|
|
4
|
+
/**
|
|
5
|
+
* ComicViewerItemData.id.
|
|
6
|
+
*/
|
|
7
|
+
id: string;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Number of times an error occurred.
|
|
11
|
+
*/
|
|
12
|
+
count: number;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export type ComicViewerItemData<T = {}> = T & {
|
|
16
|
+
/**
|
|
17
|
+
* Image height.
|
|
18
|
+
*/
|
|
19
|
+
height: number;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Unique value for identifying.
|
|
23
|
+
*/
|
|
24
|
+
id: string;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Image sourceUrl for displaying.
|
|
28
|
+
*/
|
|
29
|
+
sourceUrl: string;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Image width.
|
|
33
|
+
*/
|
|
34
|
+
width: number;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export default interface ComicViewerProps<T> extends ComponentProps <{
|
|
38
|
+
/**
|
|
39
|
+
* Data for render.
|
|
40
|
+
*/
|
|
41
|
+
data: ComicViewerItemData<T>[];
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Delay Time to call the error handler.
|
|
45
|
+
* @default 500
|
|
46
|
+
*/
|
|
47
|
+
errorDebounceMillis?: number;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* How many times retry onError when same item error occur
|
|
51
|
+
* @default 3
|
|
52
|
+
*/
|
|
53
|
+
errorRetryCount?: number;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* How many items to render in the initial batch.
|
|
57
|
+
* @default 1
|
|
58
|
+
*/
|
|
59
|
+
initialNumToRender?: number;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Start at initialScrollPercentage.
|
|
63
|
+
* If over 100, scroll to end.
|
|
64
|
+
* @default 0
|
|
65
|
+
*/
|
|
66
|
+
initialScrollPercentage?: number;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* The value for FlatList viewabilityConfig.itemVisiblePercentThreshold.
|
|
70
|
+
* @default 0
|
|
71
|
+
*/
|
|
72
|
+
itemVisiblePercentThreshold?: number;
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Handling all viewerItem errors at once.
|
|
76
|
+
* @param errors Array of ViewerItems errorInfo.
|
|
77
|
+
*/
|
|
78
|
+
onError?: (errors: ErrorInfo[]) => void;
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Comic viewer width.
|
|
82
|
+
*/
|
|
83
|
+
viewerWidth: number;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* The value for FlatList windowSize.
|
|
87
|
+
* @default 3
|
|
88
|
+
*/
|
|
89
|
+
windowSize?: number;
|
|
90
|
+
}> {}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import React, { useCallback, useRef, useState } from 'react';
|
|
2
|
+
import { View } from 'react-native';
|
|
3
|
+
import { Image, StyleSheet } from '@fountain-ui/core';
|
|
4
|
+
import ComicViewerItemProps from './ComicViewerItemProps';
|
|
5
|
+
|
|
6
|
+
const styles = StyleSheet.create({
|
|
7
|
+
placeholder: {
|
|
8
|
+
backgroundColor: '#abcabc',
|
|
9
|
+
},
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
function ViewerItem<T>({ props }: { props: ComicViewerItemProps<T> }) {
|
|
13
|
+
const {
|
|
14
|
+
height,
|
|
15
|
+
id,
|
|
16
|
+
isViewable,
|
|
17
|
+
onError,
|
|
18
|
+
sourceUrl,
|
|
19
|
+
width,
|
|
20
|
+
} = props;
|
|
21
|
+
|
|
22
|
+
const [isLoaded, setIsLoaded] = useState(false);
|
|
23
|
+
|
|
24
|
+
const errorCount = useRef<number>(0);
|
|
25
|
+
|
|
26
|
+
const onLoad = useCallback(() => {
|
|
27
|
+
errorCount.current = 0;
|
|
28
|
+
setIsLoaded(true);
|
|
29
|
+
}, []);
|
|
30
|
+
|
|
31
|
+
const handleError = useCallback(() => {
|
|
32
|
+
errorCount.current = errorCount.current + 1;
|
|
33
|
+
|
|
34
|
+
onError && onError({
|
|
35
|
+
id,
|
|
36
|
+
count: errorCount.current
|
|
37
|
+
});
|
|
38
|
+
}, [id]);
|
|
39
|
+
|
|
40
|
+
const viewStyle = { width, height };
|
|
41
|
+
|
|
42
|
+
const Placeholder = () => (
|
|
43
|
+
<View style={[
|
|
44
|
+
viewStyle,
|
|
45
|
+
styles.placeholder,
|
|
46
|
+
]}/>
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
if (!isViewable && !isLoaded) {
|
|
50
|
+
return <Placeholder/>;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
<Image
|
|
55
|
+
disableOutline={true}
|
|
56
|
+
key={sourceUrl}
|
|
57
|
+
onLoad={onLoad}
|
|
58
|
+
onError={handleError}
|
|
59
|
+
source={{ uri: sourceUrl }}
|
|
60
|
+
style={viewStyle}
|
|
61
|
+
square={true}
|
|
62
|
+
/>
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export default React.memo(ViewerItem, (prevProps, nextProps) => {
|
|
67
|
+
if (prevProps.props.isViewable !== nextProps.props.isViewable) {
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (prevProps.props.sourceUrl !== nextProps.props.sourceUrl) {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return true;
|
|
76
|
+
});
|
|
@@ -81,6 +81,12 @@ export default function DateTimePicker(props: DateTimePickerProps) {
|
|
|
81
81
|
onPress={() => setYearPickerVisible(true)}
|
|
82
82
|
/>
|
|
83
83
|
)}
|
|
84
|
+
theme={{
|
|
85
|
+
backgroundColor: theme.palette.paper.default,
|
|
86
|
+
calendarBackground: theme.palette.paper.default,
|
|
87
|
+
dayTextColor: theme.palette.text.primary,
|
|
88
|
+
textDisabledColor: theme.palette.text.hint,
|
|
89
|
+
}}
|
|
84
90
|
/>
|
|
85
91
|
);
|
|
86
92
|
};
|
|
@@ -61,6 +61,7 @@ const YearPicker = ({
|
|
|
61
61
|
<Column>
|
|
62
62
|
<Typography
|
|
63
63
|
children={formatDate(date, locale)}
|
|
64
|
+
color={'textPrimary'}
|
|
64
65
|
variant={'subtitle2'}
|
|
65
66
|
/>
|
|
66
67
|
<FlatList
|
|
@@ -84,4 +85,4 @@ const YearPicker = ({
|
|
|
84
85
|
);
|
|
85
86
|
};
|
|
86
87
|
|
|
87
|
-
export default YearPicker;
|
|
88
|
+
export default YearPicker;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { useEffect } from 'react';
|
|
2
2
|
import { StyleSheet, View } from 'react-native';
|
|
3
|
-
import Animated from 'react-native-reanimated';
|
|
3
|
+
import Animated, { useAnimatedStyle, useSharedValue, withTiming } from 'react-native-reanimated';
|
|
4
4
|
import type FlipCardProps from './FlipCardProps';
|
|
5
5
|
|
|
6
6
|
const styles = StyleSheet.create({
|
|
@@ -27,9 +27,9 @@ export default function FlipCard(props: FlipCardProps) {
|
|
|
27
27
|
style,
|
|
28
28
|
} = props;
|
|
29
29
|
|
|
30
|
-
const sharedAngle =
|
|
30
|
+
const sharedAngle = useSharedValue(0);
|
|
31
31
|
|
|
32
|
-
const animatedFrontCardStyle =
|
|
32
|
+
const animatedFrontCardStyle = useAnimatedStyle(() => {
|
|
33
33
|
return {
|
|
34
34
|
zIndex: sharedAngle.value < Z_INDEX_CHANGE_ANGLE ? 2 : 1,
|
|
35
35
|
transform: [
|
|
@@ -37,9 +37,9 @@ export default function FlipCard(props: FlipCardProps) {
|
|
|
37
37
|
{ rotateX: `${sharedAngle.value}deg` },
|
|
38
38
|
],
|
|
39
39
|
};
|
|
40
|
-
});
|
|
40
|
+
}, []);
|
|
41
41
|
|
|
42
|
-
const animatedBackCardStyle =
|
|
42
|
+
const animatedBackCardStyle = useAnimatedStyle(() => {
|
|
43
43
|
return {
|
|
44
44
|
zIndex: sharedAngle.value <= Z_INDEX_CHANGE_ANGLE ? 1 : 2,
|
|
45
45
|
transform: [
|
|
@@ -47,11 +47,11 @@ export default function FlipCard(props: FlipCardProps) {
|
|
|
47
47
|
{ rotateX: `${(sharedAngle.value + 180)}deg` },
|
|
48
48
|
],
|
|
49
49
|
};
|
|
50
|
-
});
|
|
50
|
+
}, []);
|
|
51
51
|
|
|
52
52
|
useEffect(() => {
|
|
53
53
|
sharedAngle.value = 0;
|
|
54
|
-
sharedAngle.value =
|
|
54
|
+
sharedAngle.value = withTiming(180, { duration: 500 });
|
|
55
55
|
}, [reanimationKey]);
|
|
56
56
|
|
|
57
57
|
return (
|
|
@@ -65,4 +65,4 @@ export default function FlipCard(props: FlipCardProps) {
|
|
|
65
65
|
</Animated.View>
|
|
66
66
|
</View>
|
|
67
67
|
);
|
|
68
|
-
};
|
|
68
|
+
};
|
|
@@ -1,36 +1,105 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { View } from 'react-native';
|
|
1
|
+
import React, { memo, useState } from 'react';
|
|
2
|
+
import { Platform, View } from 'react-native';
|
|
3
|
+
import { runOnJS, useAnimatedReaction } from 'react-native-reanimated';
|
|
4
|
+
import { StyleSheet } from '@fountain-ui/core';
|
|
3
5
|
import type { PageProps } from './ViewPagerProps';
|
|
4
6
|
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
+
const OFFSCREEN_RERENDER_LIMIT = 1;
|
|
8
|
+
|
|
9
|
+
const styles = StyleSheet.create({
|
|
10
|
+
none: { display: 'none' },
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
interface PageState {
|
|
14
|
+
active: boolean;
|
|
15
|
+
visited: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function Page(props: PageProps) {
|
|
19
|
+
const {
|
|
20
|
+
index,
|
|
21
|
+
children,
|
|
22
|
+
loading,
|
|
23
|
+
sharedIndex,
|
|
24
|
+
} = props;
|
|
25
|
+
|
|
26
|
+
const assumeInitialPageState = (): PageState => {
|
|
27
|
+
const activeIndex = sharedIndex.value;
|
|
28
|
+
|
|
29
|
+
const active = index === activeIndex;
|
|
30
|
+
|
|
31
|
+
if (Platform.OS === 'web') {
|
|
32
|
+
return { active, visited: active };
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (loading === 'eager') {
|
|
36
|
+
return { active, visited: true };
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const visited = index >= activeIndex - OFFSCREEN_RERENDER_LIMIT
|
|
40
|
+
&& index <= activeIndex + OFFSCREEN_RERENDER_LIMIT;
|
|
41
|
+
|
|
42
|
+
return { active, visited };
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const [pageState, setPageState] = useState<PageState>(assumeInitialPageState);
|
|
46
|
+
|
|
47
|
+
const content = pageState.visited ? children : null;
|
|
48
|
+
|
|
49
|
+
const updatePageState = (active: boolean, neighbor: boolean) => {
|
|
50
|
+
setPageState(prevState => {
|
|
51
|
+
if (prevState.active !== active) {
|
|
52
|
+
return { active, visited: active || prevState.visited };
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (neighbor && !prevState.visited) {
|
|
56
|
+
return { ...prevState, visited: true };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return prevState;
|
|
60
|
+
});
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
useAnimatedReaction(
|
|
64
|
+
() => {
|
|
65
|
+
const activeIndex = sharedIndex.value;
|
|
66
|
+
|
|
67
|
+
const willVisible = index >= activeIndex - OFFSCREEN_RERENDER_LIMIT
|
|
68
|
+
&& index <= activeIndex + OFFSCREEN_RERENDER_LIMIT;
|
|
69
|
+
|
|
70
|
+
const willActive = index === activeIndex;
|
|
71
|
+
const willNeighbor = Platform.OS === 'web' ? false : (willVisible && !willActive);
|
|
72
|
+
|
|
73
|
+
return { willActive, willNeighbor };
|
|
74
|
+
},
|
|
75
|
+
(nextState, prevState) => {
|
|
76
|
+
const activeStateChanged = nextState.willActive !== prevState?.willActive;
|
|
77
|
+
const willNewNeighbor = nextState.willNeighbor && !prevState?.willNeighbor;
|
|
78
|
+
|
|
79
|
+
if (activeStateChanged || willNewNeighbor) {
|
|
80
|
+
runOnJS(updatePageState)(nextState.willActive, nextState.willNeighbor);
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
[index],
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
const style = Platform.OS === 'web'
|
|
87
|
+
? (pageState.active ? StyleSheet.absoluteFill : styles.none)
|
|
88
|
+
: undefined;
|
|
7
89
|
|
|
8
90
|
return (
|
|
9
91
|
<View
|
|
92
|
+
children={content}
|
|
10
93
|
collapsable={false}
|
|
11
|
-
{
|
|
94
|
+
style={style}
|
|
12
95
|
/>
|
|
13
96
|
);
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export default React.memo(Page, (prevProps, nextProps) => {
|
|
17
|
-
if (prevProps.children === null && nextProps.children === null) {
|
|
18
|
-
return true;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
// isVisible is an important condition for determining memos on the web.
|
|
22
|
-
// Reference ViewPagerWeb's return.
|
|
23
|
-
if (prevProps.isVisible !== nextProps.isVisible) {
|
|
24
|
-
return false;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
if (nextProps.isVisible || nextProps.isNeighbor) {
|
|
28
|
-
return false;
|
|
29
|
-
}
|
|
97
|
+
}
|
|
30
98
|
|
|
99
|
+
export default memo(Page, (prevProps, nextProps) => {
|
|
31
100
|
if (prevProps.rerenderKey !== nextProps.rerenderKey) {
|
|
32
101
|
return false;
|
|
33
102
|
}
|
|
34
103
|
|
|
35
|
-
return prevProps.
|
|
104
|
+
return prevProps.index !== nextProps.index;
|
|
36
105
|
});
|