@fountain-ui/lab 2.0.0-beta.45 → 2.0.0-beta.46
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/ComicViewer/ComicViewer.js +28 -3
- package/build/commonjs/ComicViewer/ComicViewer.js.map +1 -1
- package/build/commonjs/ComicViewer/ComicViewerProps.js.map +1 -1
- package/build/commonjs/ComicViewer/FastScroll.js +162 -0
- package/build/commonjs/ComicViewer/FastScroll.js.map +1 -0
- package/build/commonjs/ComicViewer/FastScrollProps.js +6 -0
- package/build/commonjs/ComicViewer/FastScrollProps.js.map +1 -0
- package/build/commonjs/ComicViewer/index.js.map +1 -1
- package/build/commonjs/ComicViewer/util.js +27 -0
- package/build/commonjs/ComicViewer/util.js.map +1 -0
- package/build/module/ComicViewer/ComicViewer.js +27 -3
- package/build/module/ComicViewer/ComicViewer.js.map +1 -1
- package/build/module/ComicViewer/ComicViewerProps.js.map +1 -1
- package/build/module/ComicViewer/FastScroll.js +141 -0
- package/build/module/ComicViewer/FastScroll.js.map +1 -0
- package/build/module/ComicViewer/FastScrollProps.js +2 -0
- package/build/module/ComicViewer/FastScrollProps.js.map +1 -0
- package/build/module/ComicViewer/index.js.map +1 -1
- package/build/module/ComicViewer/util.js +15 -0
- package/build/module/ComicViewer/util.js.map +1 -0
- package/build/typescript/AnimatedY/AnimatedY.d.ts +1 -0
- package/build/typescript/BottomSheet/BottomSheetNative.d.ts +1 -0
- package/build/typescript/BottomSheet/BottomSheetWeb.d.ts +1 -0
- package/build/typescript/BottomSheet/TransparentBackdrop.d.ts +1 -0
- package/build/typescript/ComicViewer/ComicViewer.d.ts +1 -0
- package/build/typescript/ComicViewer/ComicViewerProps.d.ts +5 -0
- package/build/typescript/ComicViewer/FastScroll.d.ts +4 -0
- package/build/typescript/ComicViewer/FastScrollProps.d.ts +70 -0
- package/build/typescript/ComicViewer/ReloadButton.d.ts +1 -0
- package/build/typescript/ComicViewer/ViewerItem.d.ts +1 -0
- package/build/typescript/ComicViewer/index.d.ts +1 -0
- package/build/typescript/ComicViewer/util.d.ts +2 -0
- package/build/typescript/DateTimePicker/DateTimePicker.d.ts +1 -0
- package/build/typescript/DateTimePicker/YearPicker.d.ts +1 -0
- package/build/typescript/FlipCard/FlipCard.d.ts +1 -0
- package/build/typescript/StatusBarProvider/StatusBarProvider.d.ts +1 -0
- package/build/typescript/ViewabilityTrackerView/ViewabilityTrackerView.d.ts +1 -0
- package/package.json +3 -3
- package/src/ComicViewer/ComicViewer.tsx +40 -13
- package/src/ComicViewer/ComicViewerProps.ts +6 -0
- package/src/ComicViewer/FastScroll.tsx +158 -0
- package/src/ComicViewer/FastScrollProps.ts +83 -0
- package/src/ComicViewer/index.ts +6 -0
- package/src/ComicViewer/util.ts +15 -0
- package/yarn-error.log +103 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["ComicViewerProps.ts"],"sourcesContent":["import React from 'react';\nimport { ComponentProps } from '@fountain-ui/core';\nimport { NativeScrollEvent, NativeSyntheticEvent } from 'react-native';\n\nexport interface Dimension {\n width: number;\n height: number;\n}\n\nexport default interface ComicViewerProps extends ComponentProps <{\n /**\n * Delay Time to call the error handler.\n * @default 100\n */\n debounceMillis?: number;\n\n /**\n * How many times handle onError directly when item error occur\n * @default 3\n */\n autoHandleErrorCount?: number;\n\n /**\n * How many items to render in the initial batch.\n * @default 1\n */\n initialNumToRender?: number;\n\n /**\n * Start at initialScrollPercentage.\n * If over 100, scroll to end.\n * @default 0\n */\n initialScrollPercentage?: number;\n\n /**\n * The value for FlatList viewabilityConfig.itemVisiblePercentThreshold.\n * @default 0\n */\n itemVisiblePercentThreshold?: number;\n\n /**\n * Dimensions of each Image considering viewport.\n */\n intrinsicDimensions: Array<Dimension>;\n\n /**\n * Need invisible paddingTop viewer vertically expanded.\n * @default 0\n */\n invisiblePaddingTop?: number;\n\n /**\n * Max value of contents image width size.\n * @default 720\n */\n maxContentWidth?: number;\n\n /**\n * Width of viewport.\n */\n viewportWidth: number;\n\n /**\n * The value for FlatList windowSize.\n * @default 3\n */\n windowSize?: number;\n\n /**\n * Get contents urls by indexes.\n */\n getUrlByIndex: (indexes: Array<number>) => Promise<Map<number, string> | undefined> ;\n\n /**\n * Handle scroll event.\n * @param event Scroll event.\n */\n onScroll?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;\n\n /**\n * Handle item press event.\n */\n onItemPress?: () => void;\n\n /**\n * Component for comic viewer footer.\n */\n ListFooterComponent?: React.ReactElement;\n}> {}\n"],"mappings":""}
|
|
1
|
+
{"version":3,"names":[],"sources":["ComicViewerProps.ts"],"sourcesContent":["import React from 'react';\nimport { ComponentProps } from '@fountain-ui/core';\nimport { NativeScrollEvent, NativeSyntheticEvent } from 'react-native';\nimport { FastScrollOptions } from './FastScrollProps';\n\nexport interface Dimension {\n width: number;\n height: number;\n}\n\nexport default interface ComicViewerProps extends ComponentProps <{\n /**\n * Delay Time to call the error handler.\n * @default 100\n */\n debounceMillis?: number;\n\n /**\n * How many times handle onError directly when item error occur\n * @default 3\n */\n autoHandleErrorCount?: number;\n\n /**\n * How many items to render in the initial batch.\n * @default 1\n */\n initialNumToRender?: number;\n\n /**\n * Start at initialScrollPercentage.\n * If over 100, scroll to end.\n * @default 0\n */\n initialScrollPercentage?: number;\n\n /**\n * The value for FlatList viewabilityConfig.itemVisiblePercentThreshold.\n * @default 0\n */\n itemVisiblePercentThreshold?: number;\n\n /**\n * Dimensions of each Image considering viewport.\n */\n intrinsicDimensions: Array<Dimension>;\n\n /**\n * Need invisible paddingTop viewer vertically expanded.\n * @default 0\n */\n invisiblePaddingTop?: number;\n\n /**\n * Max value of contents image width size.\n * @default 720\n */\n maxContentWidth?: number;\n\n /**\n * Width of viewport.\n */\n viewportWidth: number;\n\n /**\n * The value for FlatList windowSize.\n * @default 3\n */\n windowSize?: number;\n\n /**\n * Options for fastscroll component.\n */\n fastScrollOptions: FastScrollOptions;\n\n /**\n * Get contents urls by indexes.\n */\n getUrlByIndex: (indexes: Array<number>) => Promise<Map<number, string> | undefined> ;\n\n /**\n * Handle scroll event.\n * @param event Scroll event.\n */\n onScroll?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;\n\n /**\n * Handle item press event.\n */\n onItemPress?: () => void;\n\n /**\n * Component for comic viewer footer.\n */\n ListFooterComponent?: React.ReactElement;\n}> {}\n"],"mappings":""}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import React, { useEffect, useImperativeHandle, useRef, useState } from 'react';
|
|
2
|
+
import { View } from 'react-native';
|
|
3
|
+
import { Gesture, GestureDetector } from 'react-native-gesture-handler';
|
|
4
|
+
import Animated, { runOnJS, useAnimatedStyle, useSharedValue, withDelay, withTiming } from 'react-native-reanimated';
|
|
5
|
+
import { ChevronDown, ChevronUp } from '@fountain-ui/icons';
|
|
6
|
+
import { StyleSheet } from '@fountain-ui/core';
|
|
7
|
+
import { offsetToPercentage, percentageToOffset } from './util';
|
|
8
|
+
const styles = StyleSheet.create({
|
|
9
|
+
indicator: {
|
|
10
|
+
width: 24,
|
|
11
|
+
height: 40,
|
|
12
|
+
backgroundColor: '#767676',
|
|
13
|
+
flexDirection: 'column',
|
|
14
|
+
alignItems: 'center',
|
|
15
|
+
borderRadius: 4
|
|
16
|
+
},
|
|
17
|
+
view: {
|
|
18
|
+
position: 'absolute'
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
const FastScroll = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
22
|
+
const {
|
|
23
|
+
absolutePosition,
|
|
24
|
+
additionalLength = 0,
|
|
25
|
+
contentLength,
|
|
26
|
+
movementRange,
|
|
27
|
+
scrollContentToOffset,
|
|
28
|
+
visibleDurations = {
|
|
29
|
+
hideMillis: 200,
|
|
30
|
+
showMillis: 350
|
|
31
|
+
}
|
|
32
|
+
} = props;
|
|
33
|
+
const lastIndicatorOffset = useSharedValue(0);
|
|
34
|
+
const indicatorOffset = useSharedValue(lastIndicatorOffset.value);
|
|
35
|
+
const isIndicatorDragging = useRef(false);
|
|
36
|
+
const indicatorOpacity = useSharedValue(1);
|
|
37
|
+
const [visible, setVisible] = useState(true);
|
|
38
|
+
const animatedStyle = useAnimatedStyle(() => ({
|
|
39
|
+
transform: [{
|
|
40
|
+
translateY: indicatorOffset.value
|
|
41
|
+
}],
|
|
42
|
+
opacity: indicatorOpacity.value
|
|
43
|
+
}));
|
|
44
|
+
const totalContentLength = contentLength + additionalLength;
|
|
45
|
+
|
|
46
|
+
const onContentScroll = event => {
|
|
47
|
+
if (isIndicatorDragging.current === false) {
|
|
48
|
+
const contentPercentage = offsetToPercentage(event.nativeEvent.contentOffset.y, totalContentLength);
|
|
49
|
+
const offset = percentageToOffset(contentPercentage, movementRange);
|
|
50
|
+
|
|
51
|
+
if (offset < 0 || indicatorOffset.value < 0) {
|
|
52
|
+
lastIndicatorOffset.value = 0;
|
|
53
|
+
indicatorOffset.value = 0;
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (offset > movementRange || indicatorOffset.value > movementRange) {
|
|
58
|
+
lastIndicatorOffset.value = movementRange;
|
|
59
|
+
indicatorOffset.value = movementRange;
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
lastIndicatorOffset.value = offset;
|
|
64
|
+
} else {
|
|
65
|
+
setVisible(true);
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const getIsIndicatorDragging = () => isIndicatorDragging.current;
|
|
70
|
+
|
|
71
|
+
useImperativeHandle(ref, () => ({
|
|
72
|
+
getIsIndicatorDragging,
|
|
73
|
+
onContentScroll,
|
|
74
|
+
setVisible
|
|
75
|
+
}), []);
|
|
76
|
+
|
|
77
|
+
const handleUpdate = () => {
|
|
78
|
+
const contentPercentage = offsetToPercentage(indicatorOffset.value, movementRange);
|
|
79
|
+
const offset = percentageToOffset(contentPercentage, totalContentLength);
|
|
80
|
+
scrollContentToOffset(offset);
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
const setIsIndicatorDragging = value => isIndicatorDragging.current = value;
|
|
84
|
+
|
|
85
|
+
const pan = Gesture.Pan().onBegin(e => {
|
|
86
|
+
indicatorOffset.value = lastIndicatorOffset.value;
|
|
87
|
+
runOnJS(setIsIndicatorDragging)(true);
|
|
88
|
+
}).onUpdate(e => {
|
|
89
|
+
if (indicatorOffset.value <= 0 && e.translationY < 0) {
|
|
90
|
+
indicatorOffset.value = 0;
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (indicatorOffset.value >= movementRange && e.translationY > 0) {
|
|
95
|
+
indicatorOffset.value = movementRange;
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
indicatorOffset.value = lastIndicatorOffset.value + e.translationY;
|
|
100
|
+
runOnJS(handleUpdate)();
|
|
101
|
+
}).onFinalize(e => {
|
|
102
|
+
lastIndicatorOffset.value = indicatorOffset.value;
|
|
103
|
+
runOnJS(setIsIndicatorDragging)(false);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
const hide = () => indicatorOpacity.value = withDelay(0, withTiming(0, {
|
|
107
|
+
duration: visibleDurations.hideMillis
|
|
108
|
+
}));
|
|
109
|
+
|
|
110
|
+
const show = () => indicatorOpacity.value = withDelay(0, withTiming(1, {
|
|
111
|
+
duration: visibleDurations.showMillis
|
|
112
|
+
}));
|
|
113
|
+
|
|
114
|
+
useEffect(() => {
|
|
115
|
+
if (visible) {
|
|
116
|
+
indicatorOffset.value = lastIndicatorOffset.value;
|
|
117
|
+
show();
|
|
118
|
+
} else {
|
|
119
|
+
hide();
|
|
120
|
+
}
|
|
121
|
+
}, [visible]);
|
|
122
|
+
return /*#__PURE__*/React.createElement(View, {
|
|
123
|
+
style: [{
|
|
124
|
+
height: movementRange
|
|
125
|
+
}, styles.view, absolutePosition]
|
|
126
|
+
}, /*#__PURE__*/React.createElement(GestureDetector, {
|
|
127
|
+
gesture: pan
|
|
128
|
+
}, /*#__PURE__*/React.createElement(Animated.View, {
|
|
129
|
+
style: [animatedStyle, styles.indicator]
|
|
130
|
+
}, /*#__PURE__*/React.createElement(ChevronUp, {
|
|
131
|
+
fill: '#ededed',
|
|
132
|
+
height: 20,
|
|
133
|
+
width: 20
|
|
134
|
+
}), /*#__PURE__*/React.createElement(ChevronDown, {
|
|
135
|
+
fill: '#ededed',
|
|
136
|
+
height: 20,
|
|
137
|
+
width: 20
|
|
138
|
+
}))));
|
|
139
|
+
});
|
|
140
|
+
export default FastScroll;
|
|
141
|
+
//# sourceMappingURL=FastScroll.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["React","useEffect","useImperativeHandle","useRef","useState","View","Gesture","GestureDetector","Animated","runOnJS","useAnimatedStyle","useSharedValue","withDelay","withTiming","ChevronDown","ChevronUp","StyleSheet","offsetToPercentage","percentageToOffset","styles","create","indicator","width","height","backgroundColor","flexDirection","alignItems","borderRadius","view","position","FastScroll","forwardRef","props","ref","absolutePosition","additionalLength","contentLength","movementRange","scrollContentToOffset","visibleDurations","hideMillis","showMillis","lastIndicatorOffset","indicatorOffset","value","isIndicatorDragging","indicatorOpacity","visible","setVisible","animatedStyle","transform","translateY","opacity","totalContentLength","onContentScroll","event","current","contentPercentage","nativeEvent","contentOffset","y","offset","getIsIndicatorDragging","handleUpdate","setIsIndicatorDragging","pan","Pan","onBegin","e","onUpdate","translationY","onFinalize","hide","duration","show"],"sources":["FastScroll.tsx"],"sourcesContent":["import React, { useEffect, useImperativeHandle, useRef, useState } from 'react';\nimport { NativeScrollEvent, NativeSyntheticEvent, View } from 'react-native';\nimport { Gesture, GestureDetector } from 'react-native-gesture-handler';\nimport Animated, { runOnJS, useAnimatedStyle, useSharedValue, withDelay, withTiming } from 'react-native-reanimated';\nimport { ChevronDown, ChevronUp } from '@fountain-ui/icons';\nimport { StyleSheet } from '@fountain-ui/core';\nimport FastScrollProps from './FastScrollProps';\nimport { offsetToPercentage, percentageToOffset } from './util';\n\nconst styles = StyleSheet.create({\n indicator: {\n width: 24,\n height: 40,\n backgroundColor: '#767676',\n flexDirection: 'column',\n alignItems: 'center',\n borderRadius: 4,\n },\n view: { position: 'absolute' },\n});\n\nconst FastScroll = React.forwardRef((props: FastScrollProps, ref) => {\n const {\n absolutePosition,\n additionalLength = 0,\n contentLength,\n movementRange,\n scrollContentToOffset,\n visibleDurations = { hideMillis: 200, showMillis: 350 },\n } = props;\n\n const lastIndicatorOffset = useSharedValue(0);\n const indicatorOffset = useSharedValue(lastIndicatorOffset.value);\n\n const isIndicatorDragging = useRef(false);\n\n const indicatorOpacity = useSharedValue(1);\n const [visible, setVisible] = useState(true);\n\n const animatedStyle = useAnimatedStyle(() => ({\n transform: [{ translateY: indicatorOffset.value }],\n opacity: indicatorOpacity.value,\n }));\n\n const totalContentLength = contentLength + additionalLength;\n\n const onContentScroll = (event: NativeSyntheticEvent<NativeScrollEvent>) => {\n if (isIndicatorDragging.current === false) {\n const contentPercentage = offsetToPercentage(event.nativeEvent.contentOffset.y, totalContentLength);\n const offset = percentageToOffset(contentPercentage, movementRange);\n\n if (offset < 0 || indicatorOffset.value < 0) {\n lastIndicatorOffset.value = 0;\n indicatorOffset.value = 0;\n return;\n }\n\n if (offset > movementRange || indicatorOffset.value > movementRange) {\n lastIndicatorOffset.value = movementRange;\n indicatorOffset.value = movementRange;\n return;\n }\n\n lastIndicatorOffset.value = offset;\n } else {\n setVisible(true);\n }\n };\n\n const getIsIndicatorDragging = () => isIndicatorDragging.current;\n\n useImperativeHandle(\n ref,\n () => ({\n getIsIndicatorDragging,\n onContentScroll,\n setVisible,\n }),\n [],\n );\n\n const handleUpdate = () => {\n const contentPercentage = offsetToPercentage(indicatorOffset.value, movementRange);\n const offset = percentageToOffset(contentPercentage, totalContentLength);\n\n scrollContentToOffset(offset);\n };\n\n const setIsIndicatorDragging = (value: boolean) => isIndicatorDragging.current = value;\n\n const pan = Gesture.Pan()\n .onBegin((e) => {\n indicatorOffset.value = lastIndicatorOffset.value;\n runOnJS(setIsIndicatorDragging)(true);\n })\n .onUpdate((e) => {\n if (indicatorOffset.value <= 0 && e.translationY < 0) {\n indicatorOffset.value = 0;\n return;\n }\n\n if (indicatorOffset.value >= movementRange && e.translationY > 0) {\n indicatorOffset.value = movementRange;\n return;\n }\n\n indicatorOffset.value = lastIndicatorOffset.value + e.translationY;\n\n runOnJS(handleUpdate)();\n })\n .onFinalize((e) => {\n lastIndicatorOffset.value = indicatorOffset.value;\n runOnJS(setIsIndicatorDragging)(false);\n });\n\n const hide = () => indicatorOpacity.value = withDelay(0, withTiming(0, { duration: visibleDurations.hideMillis }));\n\n const show = () => indicatorOpacity.value = withDelay(0, withTiming(1, { duration: visibleDurations.showMillis }));\n\n useEffect(() => {\n if (visible) {\n indicatorOffset.value = lastIndicatorOffset.value;\n show();\n } else {\n hide();\n }\n }, [visible]);\n\n return (\n <View\n style={[\n { height: movementRange },\n styles.view,\n absolutePosition,\n ]}\n >\n <GestureDetector gesture={pan}>\n <Animated.View style={[\n animatedStyle,\n styles.indicator,\n ]}>\n <ChevronUp\n fill={'#ededed'}\n height={20}\n width={20}\n />\n <ChevronDown\n fill={'#ededed'}\n height={20}\n width={20}\n />\n </Animated.View>\n </GestureDetector>\n </View>\n );\n});\n\nexport default FastScroll;"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":[],"sources":["FastScrollProps.ts"],"sourcesContent":["import React from 'react';\nimport { NativeScrollEvent, NativeSyntheticEvent } from 'react-native';\nimport type { RefObject } from 'react';\n\n/**\n * Position infos with display: 'position'.\n */\nexport type AbsolutePosition = {\n top: number;\n bottom: number;\n right: number;\n left: number;\n};\n\n/**\n * Durations(millis) for show, hide animation.\n */\nexport type VisibleDurations = {\n hideMillis: number;\n showMillis: number;\n}\n\nexport interface FastScrollInstance {\n /**\n * Handle content scroll event, not using fast scroll indicator.\n * @param event Function onScroll event params.\n */\n onContentScroll: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;\n\n /**\n * Set indicator visible state.\n */\n setVisible: React.Dispatch<React.SetStateAction<boolean>>;\n\n /**\n * Return true, if pan gesture state is begin to finalize.\n */\n getIsIndicatorDragging: () => boolean,\n}\n\nexport interface FastScrollOptions {\n /**\n * Ref for React.forwardRef.\n */\n ref: RefObject<FastScrollInstance>;\n\n /**\n * Range within which the indicator can move.\n */\n movementRange: number;\n\n /**\n * Scrollbar positions for 'display: position'.\n */\n absolutePosition?: Partial<AbsolutePosition>;\n\n /**\n * Durations(millis) for show, hide animation.\n * @default { hide: 200, show: 350 }\n */\n visibleDurations?: VisibleDurations;\n\n /**\n * Additional height except contentLength.\n * @default 0\n */\n additionalLength?: number;\n}\n\ninterface FastScrollProps extends FastScrollOptions {\n /**\n * Total length of scrollable content.\n */\n contentLength: number;\n\n /**\n * Scroll content to offset appropriate for the indicator location.\n * @param offset Content offset.\n */\n scrollContentToOffset: (offset: number) => void;\n}\n\nexport default FastScrollProps;\n"],"mappings":""}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["default"],"sources":["index.ts"],"sourcesContent":["export { default } from './ComicViewer';\nexport type { Dimension, default as ComicViewerProps } from './ComicViewerProps';\nexport type { ViewerItemProps } from './ViewerItem';\n"],"mappings":"AAAA,SAASA,OAAT,QAAwB,eAAxB"}
|
|
1
|
+
{"version":3,"names":["default"],"sources":["index.ts"],"sourcesContent":["export { default } from './ComicViewer';\nexport type { Dimension, default as ComicViewerProps } from './ComicViewerProps';\nexport type { ViewerItemProps } from './ViewerItem';\nexport type {\n AbsolutePosition,\n FastScrollInstance,\n FastScrollOptions,\n VisibleDurations,\n} from './FastScrollProps';\n"],"mappings":"AAAA,SAASA,OAAT,QAAwB,eAAxB"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export const offsetToPercentage = (offset, total) => {
|
|
2
|
+
if (offset === 0 || total === 0) {
|
|
3
|
+
return 0;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
return offset / total * 100;
|
|
7
|
+
};
|
|
8
|
+
export const percentageToOffset = (percentage, total) => {
|
|
9
|
+
if (percentage === 0 || total === 0) {
|
|
10
|
+
return 0;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
return percentage / 100 * total;
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=util.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["offsetToPercentage","offset","total","percentageToOffset","percentage"],"sources":["util.ts"],"sourcesContent":["export const offsetToPercentage = (offset: number, total: number) => {\n if (offset === 0 || total === 0) {\n return 0;\n }\n\n return offset / total * 100;\n};\n\nexport const percentageToOffset = (percentage: number, total: number) => {\n if (percentage === 0 || total === 0) {\n return 0;\n }\n\n return percentage / 100 * total;\n};\n"],"mappings":"AAAA,OAAO,MAAMA,kBAAkB,GAAG,CAACC,MAAD,EAAiBC,KAAjB,KAAmC;EACjE,IAAID,MAAM,KAAK,CAAX,IAAgBC,KAAK,KAAK,CAA9B,EAAiC;IAC7B,OAAO,CAAP;EACH;;EAED,OAAOD,MAAM,GAAGC,KAAT,GAAiB,GAAxB;AACH,CANM;AAQP,OAAO,MAAMC,kBAAkB,GAAG,CAACC,UAAD,EAAqBF,KAArB,KAAuC;EACrE,IAAIE,UAAU,KAAK,CAAf,IAAoBF,KAAK,KAAK,CAAlC,EAAqC;IACjC,OAAO,CAAP;EACH;;EAED,OAAOE,UAAU,GAAG,GAAb,GAAmBF,KAA1B;AACH,CANM"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { ComponentProps } from '@fountain-ui/core';
|
|
3
3
|
import { NativeScrollEvent, NativeSyntheticEvent } from 'react-native';
|
|
4
|
+
import { FastScrollOptions } from './FastScrollProps';
|
|
4
5
|
export interface Dimension {
|
|
5
6
|
width: number;
|
|
6
7
|
height: number;
|
|
@@ -55,6 +56,10 @@ export default interface ComicViewerProps extends ComponentProps<{
|
|
|
55
56
|
* @default 3
|
|
56
57
|
*/
|
|
57
58
|
windowSize?: number;
|
|
59
|
+
/**
|
|
60
|
+
* Options for fastscroll component.
|
|
61
|
+
*/
|
|
62
|
+
fastScrollOptions: FastScrollOptions;
|
|
58
63
|
/**
|
|
59
64
|
* Get contents urls by indexes.
|
|
60
65
|
*/
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import FastScrollProps from './FastScrollProps';
|
|
3
|
+
declare const FastScroll: React.ForwardRefExoticComponent<Pick<FastScrollProps, "contentLength" | "scrollContentToOffset" | "movementRange" | "absolutePosition" | "visibleDurations" | "additionalLength"> & React.RefAttributes<unknown>>;
|
|
4
|
+
export default FastScroll;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { NativeScrollEvent, NativeSyntheticEvent } from 'react-native';
|
|
3
|
+
import type { RefObject } from 'react';
|
|
4
|
+
/**
|
|
5
|
+
* Position infos with display: 'position'.
|
|
6
|
+
*/
|
|
7
|
+
export declare type AbsolutePosition = {
|
|
8
|
+
top: number;
|
|
9
|
+
bottom: number;
|
|
10
|
+
right: number;
|
|
11
|
+
left: number;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Durations(millis) for show, hide animation.
|
|
15
|
+
*/
|
|
16
|
+
export declare type VisibleDurations = {
|
|
17
|
+
hideMillis: number;
|
|
18
|
+
showMillis: number;
|
|
19
|
+
};
|
|
20
|
+
export interface FastScrollInstance {
|
|
21
|
+
/**
|
|
22
|
+
* Handle content scroll event, not using fast scroll indicator.
|
|
23
|
+
* @param event Function onScroll event params.
|
|
24
|
+
*/
|
|
25
|
+
onContentScroll: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;
|
|
26
|
+
/**
|
|
27
|
+
* Set indicator visible state.
|
|
28
|
+
*/
|
|
29
|
+
setVisible: React.Dispatch<React.SetStateAction<boolean>>;
|
|
30
|
+
/**
|
|
31
|
+
* Return true, if pan gesture state is begin to finalize.
|
|
32
|
+
*/
|
|
33
|
+
getIsIndicatorDragging: () => boolean;
|
|
34
|
+
}
|
|
35
|
+
export interface FastScrollOptions {
|
|
36
|
+
/**
|
|
37
|
+
* Ref for React.forwardRef.
|
|
38
|
+
*/
|
|
39
|
+
ref: RefObject<FastScrollInstance>;
|
|
40
|
+
/**
|
|
41
|
+
* Range within which the indicator can move.
|
|
42
|
+
*/
|
|
43
|
+
movementRange: number;
|
|
44
|
+
/**
|
|
45
|
+
* Scrollbar positions for 'display: position'.
|
|
46
|
+
*/
|
|
47
|
+
absolutePosition?: Partial<AbsolutePosition>;
|
|
48
|
+
/**
|
|
49
|
+
* Durations(millis) for show, hide animation.
|
|
50
|
+
* @default { hide: 200, show: 350 }
|
|
51
|
+
*/
|
|
52
|
+
visibleDurations?: VisibleDurations;
|
|
53
|
+
/**
|
|
54
|
+
* Additional height except contentLength.
|
|
55
|
+
* @default 0
|
|
56
|
+
*/
|
|
57
|
+
additionalLength?: number;
|
|
58
|
+
}
|
|
59
|
+
interface FastScrollProps extends FastScrollOptions {
|
|
60
|
+
/**
|
|
61
|
+
* Total length of scrollable content.
|
|
62
|
+
*/
|
|
63
|
+
contentLength: number;
|
|
64
|
+
/**
|
|
65
|
+
* Scroll content to offset appropriate for the indicator location.
|
|
66
|
+
* @param offset Content offset.
|
|
67
|
+
*/
|
|
68
|
+
scrollContentToOffset: (offset: number) => void;
|
|
69
|
+
}
|
|
70
|
+
export default FastScrollProps;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
export { default } from './ComicViewer';
|
|
2
2
|
export type { Dimension, default as ComicViewerProps } from './ComicViewerProps';
|
|
3
3
|
export type { ViewerItemProps } from './ViewerItem';
|
|
4
|
+
export type { AbsolutePosition, FastScrollInstance, FastScrollOptions, VisibleDurations, } from './FastScrollProps';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fountain-ui/lab",
|
|
3
|
-
"version": "2.0.0-beta.
|
|
3
|
+
"version": "2.0.0-beta.46",
|
|
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.10.0",
|
|
19
19
|
"@emotion/styled": "^11.10.0",
|
|
20
|
-
"@fountain-ui/icons": "^2.0.0-beta.
|
|
20
|
+
"@fountain-ui/icons": "^2.0.0-beta.10",
|
|
21
21
|
"@fountain-ui/utils": "^2.0.0-beta.4",
|
|
22
22
|
"react-native-calendars": "1.1267.0"
|
|
23
23
|
},
|
|
@@ -70,5 +70,5 @@
|
|
|
70
70
|
"publishConfig": {
|
|
71
71
|
"access": "public"
|
|
72
72
|
},
|
|
73
|
-
"gitHead": "
|
|
73
|
+
"gitHead": "b0d9e43744035ca199189733ba172320955879c9"
|
|
74
74
|
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
2
|
-
import { FlatList, ListRenderItem, ViewToken } from 'react-native';
|
|
2
|
+
import { FlatList, ListRenderItem, NativeScrollEvent, NativeSyntheticEvent, ViewToken } from 'react-native';
|
|
3
3
|
import * as R from 'ramda';
|
|
4
4
|
import { useDebounce } from '@fountain-ui/core';
|
|
5
5
|
import { default as ComicViewerProps, Dimension } from './ComicViewerProps';
|
|
6
6
|
import ViewerItem from './ViewerItem';
|
|
7
|
+
import FastScroll from './FastScroll';
|
|
7
8
|
|
|
8
9
|
const appender = (left: number, right: number): [number, number] => [left + right, left + right];
|
|
9
10
|
const getHeightAccum = (heights: number[]): [number, number[]] => R.mapAccum(appender, 0, heights);
|
|
@@ -56,6 +57,7 @@ export default function ComicViewer(props: ComicViewerProps) {
|
|
|
56
57
|
const {
|
|
57
58
|
debounceMillis = 100,
|
|
58
59
|
autoHandleErrorCount = 3,
|
|
60
|
+
fastScrollOptions,
|
|
59
61
|
getUrlByIndex,
|
|
60
62
|
initialNumToRender = 1,
|
|
61
63
|
initialScrollPercentage = 0,
|
|
@@ -63,12 +65,15 @@ export default function ComicViewer(props: ComicViewerProps) {
|
|
|
63
65
|
intrinsicDimensions,
|
|
64
66
|
maxContentWidth = MAXIMUM_WIDTH,
|
|
65
67
|
onItemPress,
|
|
68
|
+
onScroll,
|
|
66
69
|
viewportWidth,
|
|
67
70
|
invisiblePaddingTop = 0,
|
|
68
71
|
windowSize = 3,
|
|
69
72
|
...otherProps
|
|
70
73
|
} = props;
|
|
71
74
|
|
|
75
|
+
const fastScrollRef = fastScrollOptions?.ref;
|
|
76
|
+
|
|
72
77
|
const flatListRef = useRef<FlatList>(null);
|
|
73
78
|
|
|
74
79
|
const maybeLoadableItemsIndexRange = useRef<[number, number]>([-1, 0]);
|
|
@@ -210,6 +215,19 @@ export default function ComicViewer(props: ComicViewerProps) {
|
|
|
210
215
|
loadItemsDebounce();
|
|
211
216
|
});
|
|
212
217
|
|
|
218
|
+
const handleScroll = useCallback((event: NativeSyntheticEvent<NativeScrollEvent>) => {
|
|
219
|
+
fastScrollRef?.current?.onContentScroll(event);
|
|
220
|
+
|
|
221
|
+
onScroll?.(event);
|
|
222
|
+
}, [onScroll]);
|
|
223
|
+
|
|
224
|
+
const scrollContentToOffset = (offset: number) => {
|
|
225
|
+
flatListRef.current?.scrollToOffset({
|
|
226
|
+
offset,
|
|
227
|
+
animated: false,
|
|
228
|
+
});
|
|
229
|
+
};
|
|
230
|
+
|
|
213
231
|
const renderItem: ListRenderItem<ItemState> = useCallback(({ item, index }) => {
|
|
214
232
|
const onError = () => {
|
|
215
233
|
updateImageState((imageState, i) => {
|
|
@@ -288,17 +306,26 @@ export default function ComicViewer(props: ComicViewerProps) {
|
|
|
288
306
|
}, []);
|
|
289
307
|
|
|
290
308
|
return (
|
|
291
|
-
<
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
309
|
+
<React.Fragment>
|
|
310
|
+
<FlatList
|
|
311
|
+
data={itemStates}
|
|
312
|
+
getItemLayout={getItemLayout}
|
|
313
|
+
initialNumToRender={initialNumToRender}
|
|
314
|
+
keyExtractor={keyExtractor}
|
|
315
|
+
onViewableItemsChanged={onViewableItemsChanged.current}
|
|
316
|
+
ref={flatListRef}
|
|
317
|
+
renderItem={renderItem}
|
|
318
|
+
viewabilityConfig={viewabilityConfig}
|
|
319
|
+
windowSize={windowSize}
|
|
320
|
+
onScroll={handleScroll}
|
|
321
|
+
{...otherProps}
|
|
322
|
+
/>
|
|
323
|
+
|
|
324
|
+
<FastScroll
|
|
325
|
+
{...fastScrollOptions}
|
|
326
|
+
contentLength={totalHeight}
|
|
327
|
+
scrollContentToOffset={scrollContentToOffset}
|
|
328
|
+
/>
|
|
329
|
+
</React.Fragment>
|
|
303
330
|
);
|
|
304
331
|
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { ComponentProps } from '@fountain-ui/core';
|
|
3
3
|
import { NativeScrollEvent, NativeSyntheticEvent } from 'react-native';
|
|
4
|
+
import { FastScrollOptions } from './FastScrollProps';
|
|
4
5
|
|
|
5
6
|
export interface Dimension {
|
|
6
7
|
width: number;
|
|
@@ -67,6 +68,11 @@ export default interface ComicViewerProps extends ComponentProps <{
|
|
|
67
68
|
*/
|
|
68
69
|
windowSize?: number;
|
|
69
70
|
|
|
71
|
+
/**
|
|
72
|
+
* Options for fastscroll component.
|
|
73
|
+
*/
|
|
74
|
+
fastScrollOptions: FastScrollOptions;
|
|
75
|
+
|
|
70
76
|
/**
|
|
71
77
|
* Get contents urls by indexes.
|
|
72
78
|
*/
|