@fountain-ui/lab 2.0.0-beta.29 → 2.0.0-beta.30

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.
@@ -3,6 +3,7 @@ function _extends() { _extends = Object.assign ? Object.assign.bind() : function
3
3
  import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
4
4
  import { FlatList } from 'react-native';
5
5
  import * as R from 'ramda';
6
+ import { STATE } from './ComicViewerProps';
6
7
  import ViewerItem from './ViewerItem';
7
8
 
8
9
  const getItemHeights = items => R.map(content => content.height)(items);
@@ -11,7 +12,7 @@ const appender = (left, right) => [left + right, left + right];
11
12
 
12
13
  const getHeightAccum = itemHeights => R.mapAccum(appender, 0, itemHeights);
13
14
 
14
- const keyExtractor = item => item.id;
15
+ const keyExtractor = item => `${item.sortKey}`;
15
16
 
16
17
  export default function ComicViewer(props) {
17
18
  const {
@@ -22,21 +23,29 @@ export default function ComicViewer(props) {
22
23
  initialScrollPercentage = 0,
23
24
  itemVisiblePercentThreshold = 0,
24
25
  onError,
26
+ onScroll,
27
+ getNextPage,
25
28
  viewerWidth,
26
29
  windowSize = 3,
30
+ pageUnit,
31
+ ListFooterComponent,
27
32
  ...otherProps
28
33
  } = props;
29
34
  const flatListRef = useRef(null);
30
35
  const errors = useRef(new Map());
31
36
  const debounceTimeOut = useRef(null);
32
- const resourceString = R.toString(R.map(itemData => itemData.sourceUrl)(data));
37
+ const resourceString = R.toString(R.map(itemData => itemData.url)(data));
33
38
  const initialItems = R.map(itemData => ({ ...itemData,
34
39
  isViewable: false,
35
40
  width: viewerWidth,
36
41
  height: itemData.height * viewerWidth / itemData.width
37
42
  }))(data);
38
43
  const [items, setItems] = useState(initialItems);
39
- const itemHeights = getItemHeights(items);
44
+ const initialItemState = R.map(() => ({
45
+ state: STATE.UNLOAD
46
+ }))(data);
47
+ const itemStates = useRef(initialItemState);
48
+ const itemHeights = [...getItemHeights(items)];
40
49
  const itemHeightAccum = getHeightAccum(itemHeights);
41
50
  const viewabilityConfig = useMemo(() => ({
42
51
  itemVisiblePercentThreshold
@@ -54,67 +63,84 @@ export default function ComicViewer(props) {
54
63
  viewableItems
55
64
  } = _ref;
56
65
  setItems(prev => {
57
- const viewableItemIds = R.map(viewableItem => viewableItem.item.id)(viewableItems);
58
- return R.map(prevItem => ({ ...prevItem,
59
- isViewable: R.includes(prevItem.id, viewableItemIds)
66
+ const viewableItemSortKeys = R.map(viewableItem => viewableItem.item.sortKey)(viewableItems);
67
+ const newItems = R.map(prevItem => ({ ...prevItem,
68
+ isViewable: R.includes(prevItem.sortKey, viewableItemSortKeys)
60
69
  }))([...prev]);
70
+ return newItems;
61
71
  });
62
72
  });
73
+ const itemLoadedHandler = useCallback(sortKey => {
74
+ const itemState = itemStates.current[sortKey - 1];
75
+ itemState.state = STATE.LOADED;
76
+ itemState.error = undefined;
77
+ }, [itemStates]);
78
+ const itemErrorHandler = useCallback(errorInfo => {
79
+ const {
80
+ sortKey,
81
+ count
82
+ } = errorInfo;
63
83
 
64
- const onErrorHandler = errors => {
65
- const isRetryLimited = R.any(error => error.count >= errorRetryCount)(errors);
66
-
67
- if (isRetryLimited) {
84
+ if (count >= errorRetryCount) {
68
85
  return;
69
86
  }
70
87
 
71
- onError && onError(errors);
72
- };
73
-
74
- const itemErrorHandler = useCallback(errorInfo => {
75
- errors.current.set(errorInfo.id, errorInfo.count);
76
-
77
- if (debounceTimeOut.current) {
78
- clearTimeout(debounceTimeOut.current);
79
- }
88
+ errors.current.set(sortKey, errorInfo);
89
+ const itemState = itemStates.current[sortKey - 1];
90
+ itemState.state = STATE.FAIL;
91
+ itemState.error = errorInfo;
80
92
 
81
- debounceTimeOut.current = setTimeout(function () {
93
+ const handleError = () => {
82
94
  const errorsArray = Array.from(errors.current.entries());
83
95
  const errorsInfo = R.map(_ref2 => {
84
96
  let [key, value] = _ref2;
85
- return {
86
- id: key,
87
- count: value
88
- };
97
+ return value;
89
98
  })(errorsArray);
90
- onErrorHandler([...errorsInfo]);
99
+ onError && onError([...errorsInfo]);
91
100
  errors.current.clear();
92
- }, errorDebounceMillis);
93
- }, [errorDebounceMillis, errors.current]);
101
+ };
102
+
103
+ if (debounceTimeOut.current) {
104
+ clearTimeout(debounceTimeOut.current);
105
+ }
106
+
107
+ if (errors.current.size === pageUnit) {
108
+ handleError();
109
+ } else {
110
+ debounceTimeOut.current = setTimeout(handleError, errorDebounceMillis);
111
+ }
112
+ }, [errors.current, itemStates]);
94
113
  const renderItem = useCallback(_ref3 => {
95
114
  let {
96
115
  item
97
116
  } = _ref3;
117
+ const itemState = itemStates.current[item.sortKey - 1];
98
118
  const props = { ...item,
99
- onError: itemErrorHandler
119
+ itemState,
120
+ errorRetryCount,
121
+ onError: itemErrorHandler,
122
+ onLoaded: itemLoadedHandler,
123
+ getNextPage
100
124
  };
101
125
  return /*#__PURE__*/React.createElement(ViewerItem, {
102
126
  props: props
103
127
  });
104
- }, []);
128
+ }, [resourceString, itemStates, itemErrorHandler, itemLoadedHandler]);
105
129
  useEffect(() => {
106
130
  setItems(prev => {
107
131
  return R.map(prevItem => {
108
- const currentData = R.find(currentItemData => prevItem.id === currentItemData.id)(data);
132
+ const currentData = R.find(currentItemData => prevItem.sortKey === currentItemData.sortKey)(data);
109
133
 
110
- if (currentData && currentData.sourceUrl !== prevItem.sourceUrl) {
134
+ if (currentData && itemStates.current[currentData.sortKey - 1].state !== STATE.LOADED && currentData.url !== prevItem.url) {
111
135
  return { ...prevItem,
112
- sourceUrl: currentData.sourceUrl
136
+ url: currentData.url,
137
+ expiresAt: currentData.expiresAt
113
138
  };
114
139
  }
115
140
 
116
141
  return prevItem;
117
142
  })([...prev]);
143
+ ;
118
144
  });
119
145
  }, [resourceString]);
120
146
  useEffect(() => {
@@ -141,10 +167,12 @@ export default function ComicViewer(props) {
141
167
  initialNumToRender: initialNumToRender,
142
168
  keyExtractor: keyExtractor,
143
169
  onViewableItemsChanged: onViewableItemsChanged.current,
170
+ onScroll: onScroll,
144
171
  ref: flatListRef,
145
172
  renderItem: renderItem,
146
173
  viewabilityConfig: viewabilityConfig,
147
- windowSize: windowSize
174
+ windowSize: windowSize,
175
+ ListFooterComponent: ListFooterComponent
148
176
  }, otherProps));
149
177
  }
150
178
  ;
@@ -1 +1 @@
1
- {"version":3,"names":["React","useCallback","useEffect","useMemo","useRef","useState","FlatList","R","ViewerItem","getItemHeights","items","map","content","height","appender","left","right","getHeightAccum","itemHeights","mapAccum","keyExtractor","item","id","ComicViewer","props","data","errorDebounceMillis","errorRetryCount","initialNumToRender","initialScrollPercentage","itemVisiblePercentThreshold","onError","viewerWidth","windowSize","otherProps","flatListRef","errors","Map","debounceTimeOut","resourceString","toString","itemData","sourceUrl","initialItems","isViewable","width","setItems","itemHeightAccum","viewabilityConfig","getItemLayout","index","offsets","prepend","length","offset","onViewableItemsChanged","viewableItems","prev","viewableItemIds","viewableItem","prevItem","includes","onErrorHandler","isRetryLimited","any","error","count","itemErrorHandler","errorInfo","current","set","clearTimeout","setTimeout","errorsArray","Array","from","entries","errorsInfo","key","value","clear","renderItem","currentData","find","currentItemData","newItems","totalHeight","Math","floor","scrollToOffset","animated"],"sources":["ComicViewer.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { FlatList, ListRenderItem, ViewToken } from 'react-native';\nimport * as R from 'ramda';\nimport { ComicViewerItemData, default as ComicViewerProps, ErrorInfo } from './ComicViewerProps';\nimport type ComicViewerItemProps from './ComicViewerItemProps';\nimport ViewerItem from './ViewerItem';\n\nconst getItemHeights = <T, >(items: ComicViewerItemProps<T>[]): number[] => R.map((content: ComicViewerItemProps<T>) => content.height)(items);\nconst appender = (left: number, right: number): [number, number] => [left + right, left + right];\nconst getHeightAccum = (itemHeights: number[]): [number, number[]] => R.mapAccum(appender, 0, itemHeights);\n\nconst keyExtractor = <T, >(item: ComicViewerItemProps<T>) => item.id;\n\nexport default function ComicViewer<T>(props: ComicViewerProps<T>) {\n const {\n data,\n errorDebounceMillis = 500,\n errorRetryCount = 3,\n initialNumToRender = 1,\n initialScrollPercentage = 0,\n itemVisiblePercentThreshold = 0,\n onError,\n viewerWidth,\n windowSize = 3,\n ...otherProps\n } = props;\n\n const flatListRef = useRef<FlatList>(null);\n\n const errors = useRef<Map<string, number>>(new Map());\n const debounceTimeOut = useRef<NodeJS.Timeout | null>(null);\n\n const resourceString = R.toString(R.map((itemData: ComicViewerItemData) => itemData.sourceUrl)(data));\n\n const initialItems = R.map((itemData: ComicViewerItemData<T>) => ({\n ...itemData,\n isViewable: false,\n width: viewerWidth,\n height: (itemData.height * viewerWidth) / itemData.width,\n }))(data);\n\n const [items, setItems] = useState<ComicViewerItemProps<T>[]>(initialItems);\n\n const itemHeights = getItemHeights(items);\n const itemHeightAccum = getHeightAccum(itemHeights);\n\n const viewabilityConfig = useMemo(() => ({\n itemVisiblePercentThreshold,\n }), [itemVisiblePercentThreshold]);\n\n const getItemLayout = useCallback((data: any, index: number) => {\n const offsets = R.prepend(0, itemHeightAccum[1]);\n\n return {\n length: itemHeights[index],\n offset: offsets[index],\n index,\n };\n }, [itemHeights]);\n\n const onViewableItemsChanged = useRef(({ viewableItems }: {\n viewableItems: Array<ViewToken>,\n }) => {\n setItems((prev: ComicViewerItemProps<T>[]) => {\n const viewableItemIds = R.map((viewableItem: ViewToken) => viewableItem.item.id)(viewableItems);\n\n return R.map((prevItem: ComicViewerItemProps<T>) => ({\n ...prevItem,\n isViewable: R.includes(prevItem.id, viewableItemIds),\n }))([...prev]);\n });\n });\n\n const onErrorHandler = (errors: ErrorInfo[]) => {\n const isRetryLimited = R.any((error: ErrorInfo) => error.count >= errorRetryCount)(errors);\n\n if (isRetryLimited) {\n return;\n }\n\n onError && onError(errors);\n };\n\n const itemErrorHandler = useCallback((errorInfo: ErrorInfo) => {\n errors.current.set(errorInfo.id, errorInfo.count);\n\n if (debounceTimeOut.current) {\n clearTimeout(debounceTimeOut.current);\n }\n\n debounceTimeOut.current = setTimeout(function () {\n const errorsArray = Array.from(errors.current.entries());\n const errorsInfo = R.map(([key, value]: [string, number]) => ({\n id: key,\n count: value,\n }))(errorsArray);\n\n onErrorHandler([...errorsInfo]);\n errors.current.clear();\n }, errorDebounceMillis);\n }, [errorDebounceMillis, errors.current]);\n\n const renderItem: ListRenderItem<ComicViewerItemProps<T>> = useCallback(({ item }) => {\n const props = {\n ...item,\n onError: itemErrorHandler,\n };\n\n return <ViewerItem props={props}/>;\n }, []);\n\n useEffect(() => {\n setItems((prev: ComicViewerItemProps<T>[]) => {\n return R.map((prevItem: ComicViewerItemProps<T>) => {\n const currentData = R.find((currentItemData: ComicViewerItemData<T>) => prevItem.id === currentItemData.id)(data);\n\n if (currentData && (currentData.sourceUrl !== prevItem.sourceUrl)) {\n return {\n ...prevItem,\n sourceUrl: currentData.sourceUrl,\n };\n }\n\n return prevItem;\n })([...prev]);\n });\n }, [resourceString]);\n\n useEffect(() => {\n const newItems = R.map((item: ComicViewerItemProps<T>) => ({\n ...item,\n width: viewerWidth,\n height: (item.height * viewerWidth) / item.width,\n }))(items);\n\n setItems(newItems);\n }, [viewerWidth]);\n\n useEffect(() => {\n const totalHeight = itemHeightAccum[0];\n const offset = Math.floor((initialScrollPercentage / 100) * totalHeight);\n\n if (flatListRef.current) {\n flatListRef.current.scrollToOffset({ offset, animated: false });\n }\n }, [flatListRef.current]);\n\n return (\n <FlatList\n data={items}\n getItemLayout={getItemLayout}\n initialNumToRender={initialNumToRender}\n keyExtractor={keyExtractor}\n onViewableItemsChanged={onViewableItemsChanged.current}\n ref={flatListRef}\n renderItem={renderItem}\n viewabilityConfig={viewabilityConfig}\n windowSize={windowSize}\n {...otherProps}\n />\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"names":["React","useCallback","useEffect","useMemo","useRef","useState","FlatList","R","STATE","ViewerItem","getItemHeights","items","map","content","height","appender","left","right","getHeightAccum","itemHeights","mapAccum","keyExtractor","item","sortKey","ComicViewer","props","data","errorDebounceMillis","errorRetryCount","initialNumToRender","initialScrollPercentage","itemVisiblePercentThreshold","onError","onScroll","getNextPage","viewerWidth","windowSize","pageUnit","ListFooterComponent","otherProps","flatListRef","errors","Map","debounceTimeOut","resourceString","toString","itemData","url","initialItems","isViewable","width","setItems","initialItemState","state","UNLOAD","itemStates","itemHeightAccum","viewabilityConfig","getItemLayout","index","offsets","prepend","length","offset","onViewableItemsChanged","viewableItems","prev","viewableItemSortKeys","viewableItem","newItems","prevItem","includes","itemLoadedHandler","itemState","current","LOADED","error","undefined","itemErrorHandler","errorInfo","count","set","FAIL","handleError","errorsArray","Array","from","entries","errorsInfo","key","value","clear","clearTimeout","size","setTimeout","renderItem","onLoaded","currentData","find","currentItemData","expiresAt","totalHeight","Math","floor","scrollToOffset","animated"],"sources":["ComicViewer.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { FlatList, ListRenderItem, ViewToken } from 'react-native';\nimport * as R from 'ramda';\nimport {\n ComicViewerItemData,\n ComicViewerItemState,\n default as ComicViewerProps,\n ErrorInfo,\n STATE,\n} from './ComicViewerProps';\nimport type ComicViewerItemProps from './ComicViewerItemProps';\nimport ViewerItem from './ViewerItem';\n\nconst getItemHeights = <T, >(items: ComicViewerItemProps<T>[]): number[] => R.map((content: ComicViewerItemProps<T>) => content.height)(items);\nconst appender = (left: number, right: number): [number, number] => [left + right, left + right];\nconst getHeightAccum = (itemHeights: number[]): [number, number[]] => R.mapAccum(appender, 0, itemHeights);\n\nconst keyExtractor = <T, >(item: ComicViewerItemProps<T>) => `${item.sortKey}`;\n\nexport default function ComicViewer<T>(props: ComicViewerProps<T>) {\n const {\n data,\n errorDebounceMillis = 500,\n errorRetryCount = 3,\n initialNumToRender = 1,\n initialScrollPercentage = 0,\n itemVisiblePercentThreshold = 0,\n onError,\n onScroll,\n getNextPage,\n viewerWidth,\n windowSize = 3,\n pageUnit,\n ListFooterComponent,\n ...otherProps\n } = props;\n\n const flatListRef = useRef<FlatList>(null);\n\n const errors = useRef<Map<number, ErrorInfo>>(new Map());\n\n const debounceTimeOut = useRef<NodeJS.Timeout | null>(null);\n\n const resourceString = R.toString(R.map((itemData: ComicViewerItemData) => itemData.url)(data));\n\n const initialItems = R.map((itemData: ComicViewerItemData<T>) => ({\n ...itemData,\n isViewable: false,\n width: viewerWidth,\n height: (itemData.height * viewerWidth) / itemData.width,\n }))(data);\n\n const [items, setItems] = useState<ComicViewerItemProps<T>[]>(initialItems);\n\n const initialItemState: ComicViewerItemState[] = R.map(() => ({\n state: STATE.UNLOAD,\n }))(data);\n\n const itemStates = useRef<Array<ComicViewerItemState>>(initialItemState);\n\n const itemHeights = [...getItemHeights(items)];\n const itemHeightAccum = getHeightAccum(itemHeights);\n\n const viewabilityConfig = useMemo(() => ({\n itemVisiblePercentThreshold,\n }), [itemVisiblePercentThreshold]);\n\n const getItemLayout = useCallback((data: any, index: number) => {\n const offsets = R.prepend(0, itemHeightAccum[1]);\n\n return {\n length: itemHeights[index],\n offset: offsets[index],\n index,\n };\n }, [itemHeights]);\n\n const onViewableItemsChanged = useRef(({ viewableItems }: {\n viewableItems: Array<ViewToken>,\n }) => {\n setItems((prev: ComicViewerItemProps<T>[]) => {\n const viewableItemSortKeys = R.map((viewableItem: ViewToken) => viewableItem.item.sortKey)(viewableItems);\n\n const newItems = R.map((prevItem: ComicViewerItemProps<T>) => ({\n ...prevItem,\n isViewable: R.includes(prevItem.sortKey, viewableItemSortKeys),\n }))([...prev]);\n\n return newItems;\n });\n });\n\n const itemLoadedHandler = useCallback((sortKey: number) => {\n const itemState = itemStates.current[sortKey - 1];\n itemState.state = STATE.LOADED;\n itemState.error = undefined;\n }, [itemStates]);\n\n const itemErrorHandler = useCallback((errorInfo: ErrorInfo) => {\n const { sortKey, count } = errorInfo;\n\n if (count >= errorRetryCount) {\n return;\n }\n\n errors.current.set(sortKey, errorInfo);\n\n const itemState = itemStates.current[sortKey - 1];\n itemState.state = STATE.FAIL;\n itemState.error = errorInfo;\n\n const handleError = () => {\n const errorsArray = Array.from(errors.current.entries());\n const errorsInfo = R.map(([key, value]: [number, ErrorInfo]) => value)(errorsArray);\n\n onError && onError([...errorsInfo]);\n errors.current.clear();\n };\n\n if (debounceTimeOut.current) {\n clearTimeout(debounceTimeOut.current);\n }\n\n if (errors.current.size === pageUnit) {\n handleError();\n } else {\n debounceTimeOut.current = setTimeout(handleError, errorDebounceMillis);\n }\n }, [errors.current, itemStates]);\n\n const renderItem: ListRenderItem<ComicViewerItemProps<T>> = useCallback(({ item }) => {\n const itemState = itemStates.current[item.sortKey - 1];\n\n const props = {\n ...item,\n itemState,\n errorRetryCount,\n onError: itemErrorHandler,\n onLoaded: itemLoadedHandler,\n getNextPage,\n };\n\n return <ViewerItem props={props}/>;\n }, [resourceString, itemStates, itemErrorHandler, itemLoadedHandler]);\n\n useEffect(() => {\n setItems((prev: ComicViewerItemProps<T>[]) => {\n return R.map((prevItem: ComicViewerItemProps<T>) => {\n const currentData = R.find((currentItemData: ComicViewerItemData<T>) => prevItem.sortKey === currentItemData.sortKey)(data);\n\n if (currentData\n && itemStates.current[currentData.sortKey - 1].state !== STATE.LOADED\n && (currentData.url !== prevItem.url)) {\n return {\n ...prevItem,\n url: currentData.url,\n expiresAt: currentData.expiresAt,\n };\n }\n\n return prevItem;\n })([...prev]);\n ;\n });\n }, [resourceString]);\n\n useEffect(() => {\n const newItems = R.map((item: ComicViewerItemProps<T>) => ({\n ...item,\n width: viewerWidth,\n height: (item.height * viewerWidth) / item.width,\n }))(items);\n\n setItems(newItems);\n }, [viewerWidth]);\n\n useEffect(() => {\n const totalHeight = itemHeightAccum[0];\n const offset = Math.floor((initialScrollPercentage / 100) * totalHeight);\n\n if (flatListRef.current) {\n flatListRef.current.scrollToOffset({ offset, animated: false });\n }\n }, [flatListRef.current]);\n\n return (\n <FlatList\n data={items}\n getItemLayout={getItemLayout}\n initialNumToRender={initialNumToRender}\n keyExtractor={keyExtractor}\n onViewableItemsChanged={onViewableItemsChanged.current}\n onScroll={onScroll}\n ref={flatListRef}\n renderItem={renderItem}\n viewabilityConfig={viewabilityConfig}\n windowSize={windowSize}\n ListFooterComponent={ListFooterComponent}\n {...otherProps}\n />\n );\n};\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"names":[],"sources":["ComicViewerItemProps.ts"],"sourcesContent":["import { ComicViewerItemData, ErrorInfo } from './ComicViewerProps';\n\ntype ComicViewerItemProps<T> = ComicViewerItemData<T> & {\n /**\n * FlatListItem is viewable in screen.\n */\n isViewable: boolean;\n\n /**\n * Error handler\n */\n onError?: (errorInfo: ErrorInfo) => void;\n}\n\nexport default ComicViewerItemProps;"],"mappings":""}
1
+ {"version":3,"names":[],"sources":["ComicViewerItemProps.ts"],"sourcesContent":["import { ComicViewerItemData, ErrorInfo, ComicViewerItemState } from './ComicViewerProps';\n\ntype ComicViewerItemProps<T> = ComicViewerItemData<T> & {\n /**\n * FlatListItem is viewable in screen.\n */\n isViewable: boolean;\n\n /**\n * How many times retry onError when same item error occur\n * @default 3\n */\n errorRetryCount?: number;\n\n /**\n * Error handler\n */\n onError?: (errorInfo: ErrorInfo) => void;\n\n /**\n * Load handler\n */\n onLoaded?: (sortKey: number) => void;\n\n getNextPage?: (sortKey: number) => void;\n\n itemState?: ComicViewerItemState;\n}\n\nexport default ComicViewerItemProps;"],"mappings":""}
@@ -1,2 +1,7 @@
1
-
1
+ export const STATE = {
2
+ UNLOAD: 'unload',
3
+ LOADING: 'loading',
4
+ LOADED: 'loaded',
5
+ FAIL: 'fail'
6
+ };
2
7
  //# sourceMappingURL=ComicViewerProps.js.map
@@ -1 +1 @@
1
- {"version":3,"names":[],"sources":["ComicViewerProps.ts"],"sourcesContent":["import { ComponentProps } from '@fountain-ui/core';\n\nexport interface ErrorInfo {\n /**\n * ComicViewerItemData.id.\n */\n id: string;\n\n /**\n * Number of times an error occurred.\n */\n count: number;\n}\n\nexport type ComicViewerItemData<T = {}> = T & {\n /**\n * Image height.\n */\n height: number;\n\n /**\n * Unique value for identifying.\n */\n id: string;\n\n /**\n * Image sourceUrl for displaying.\n */\n sourceUrl: string;\n\n /**\n * Image width.\n */\n width: number;\n}\n\nexport default interface ComicViewerProps<T> extends ComponentProps <{\n /**\n * Data for render.\n */\n data: ComicViewerItemData<T>[];\n\n /**\n * Delay Time to call the error handler.\n * @default 500\n */\n errorDebounceMillis?: number;\n\n /**\n * How many times retry onError when same item error occur\n * @default 3\n */\n errorRetryCount?: 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 * Handling all viewerItem errors at once.\n * @param errors Array of ViewerItems errorInfo.\n */\n onError?: (errors: ErrorInfo[]) => void;\n\n /**\n * Comic viewer width.\n */\n viewerWidth: number;\n\n /**\n * The value for FlatList windowSize.\n * @default 3\n */\n windowSize?: number;\n}> {}"],"mappings":""}
1
+ {"version":3,"names":["STATE","UNLOAD","LOADING","LOADED","FAIL"],"sources":["ComicViewerProps.ts"],"sourcesContent":["import React from 'react';\nimport { ComponentProps } from '@fountain-ui/core';\nimport { NativeScrollEvent, NativeSyntheticEvent } from 'react-native';\n\nexport const STATE = {\n UNLOAD: 'unload',\n LOADING: 'loading',\n LOADED: 'loaded',\n FAIL: 'fail',\n} as const;\n\nexport type LoadingState = typeof STATE[keyof typeof STATE];\n\nexport interface ComicViewerItemState{\n /**\n * Content's loading state.\n */\n state: LoadingState,\n\n /***\n * Content's error Info.\n */\n error?: ErrorInfo,\n}\n\nexport interface ErrorInfo {\n /**\n * ComicViewerItemData.sortKey.\n */\n sortKey: number;\n\n /**\n * Number of times an error occurred.\n */\n count: number;\n\n /**\n * Content is Expired: true\n */\n expired: boolean;\n}\n\nexport type ComicViewerItemData<T = {}> = T & {\n /**\n * Image height.\n */\n height: number;\n\n /**\n * Unique value for identifying.\n */\n id: number | undefined;\n\n /**\n * Image sourceUrl for displaying.\n */\n url: string;\n\n /**\n * Image width.\n */\n width: number;\n\n /**\n * SortKey\n */\n sortKey: number;\n\n /**\n * Image expire date.\n */\n expiresAt: string;\n}\n\nexport default interface ComicViewerProps<T> extends ComponentProps <{\n /**\n * Data for render.\n */\n data: ComicViewerItemData<T>[];\n\n /**\n * Delay Time to call the error handler.\n * @default 500\n */\n errorDebounceMillis?: number;\n\n /**\n * How many times retry onError when same item error occur\n * @default 3\n */\n errorRetryCount?: 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 * Comic viewer width.\n */\n viewerWidth: number;\n\n /**\n * The value for FlatList windowSize.\n * @default 3\n */\n windowSize?: number;\n\n /**\n * How many images in one page.\n */\n pageUnit: number;\n\n /**\n * Method for getting next page contents.\n * @param sortKey\n */\n getNextPage?: (sortKey: number) => void;\n\n /**\n * Handling all viewerItem errors at once.\n * @param errors Array of ViewerItems errorInfo.\n */\n onError?: (errors: ErrorInfo[]) => void;\n\n /**\n * Handle scroll event.\n * @param event Scroll event.\n */\n onScroll?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;\n\n /**\n * Component for comic viewer footer.\n */\n ListFooterComponent?: React.ReactElement;\n}> {}"],"mappings":"AAIA,OAAO,MAAMA,KAAK,GAAG;EACjBC,MAAM,EAAE,QADS;EAEjBC,OAAO,EAAE,SAFQ;EAGjBC,MAAM,EAAE,QAHS;EAIjBC,IAAI,EAAE;AAJW,CAAd"}
@@ -1,60 +1,130 @@
1
- import React, { useCallback, useRef, useState } from 'react';
1
+ import React, { useCallback, useEffect, useRef, useState } from 'react';
2
2
  import { View } from 'react-native';
3
- import { Image, StyleSheet } from '@fountain-ui/core';
4
- const styles = StyleSheet.create({
5
- placeholder: {
6
- backgroundColor: '#abcabc'
7
- }
8
- });
3
+ import * as R from 'ramda';
4
+ import { IconButton, Image, Spacer, useTheme } from '@fountain-ui/core';
5
+ import { Restart } from '@fountain-ui/icons';
6
+
7
+ const useStyles = function () {
8
+ const theme = useTheme();
9
+ return {
10
+ init: {
11
+ backgroundColor: theme.palette.paper.grey
12
+ },
13
+ failed: {
14
+ backgroundColor: theme.palette.paper.grey
15
+ },
16
+ reload: {
17
+ backgroundColor: theme.palette.paper.grey,
18
+ display: 'flex',
19
+ alignItems: 'center'
20
+ }
21
+ };
22
+ };
9
23
 
10
24
  function ViewerItem(_ref) {
25
+ var _itemState$error;
26
+
11
27
  let {
12
28
  props
13
29
  } = _ref;
14
30
  const {
31
+ expiresAt,
32
+ errorRetryCount = 3,
15
33
  height,
16
- id,
34
+ itemState,
17
35
  isViewable,
36
+ sortKey,
37
+ url,
38
+ width,
39
+ getNextPage,
18
40
  onError,
19
- sourceUrl,
20
- width
41
+ onLoaded
21
42
  } = props;
22
43
  const [isLoaded, setIsLoaded] = useState(false);
23
- const errorCount = useRef(0);
44
+ const styles = useStyles();
45
+ const errorCount = useRef(R.defaultTo(0)(itemState === null || itemState === void 0 ? void 0 : (_itemState$error = itemState.error) === null || _itemState$error === void 0 ? void 0 : _itemState$error.count));
24
46
  const onLoad = useCallback(() => {
25
47
  errorCount.current = 0;
26
48
  setIsLoaded(true);
27
- }, []);
49
+ onLoaded && onLoaded(sortKey);
50
+ }, [sortKey]);
28
51
  const handleError = useCallback(() => {
29
52
  errorCount.current = errorCount.current + 1;
53
+ const expired = expiresAt ? new Date(expiresAt) <= new Date() : false;
54
+ onError && onError({
55
+ sortKey,
56
+ count: errorCount.current,
57
+ expired
58
+ });
59
+ }, [errorCount.current]);
60
+ const onReloadPress = useCallback(() => {
61
+ errorCount.current = 1;
30
62
  onError && onError({
31
- id,
32
- count: errorCount.current
63
+ sortKey,
64
+ count: errorCount.current,
65
+ expired: false
33
66
  });
34
- }, [id]);
67
+ }, [sortKey]);
35
68
  const viewStyle = {
36
69
  width,
37
70
  height
38
71
  };
72
+ const Placeholder = useCallback(props => {
73
+ const {
74
+ children,
75
+ failed
76
+ } = props;
39
77
 
40
- const Placeholder = () => /*#__PURE__*/React.createElement(View, {
41
- style: [viewStyle, styles.placeholder]
42
- });
78
+ if (!isViewable && !isLoaded) {
79
+ return /*#__PURE__*/React.createElement(View, {
80
+ style: [viewStyle, styles.init]
81
+ });
82
+ }
43
83
 
44
- if (!isViewable && !isLoaded) {
45
- return /*#__PURE__*/React.createElement(Placeholder, null);
46
- }
84
+ if (errorCount.current >= errorRetryCount) {
85
+ return /*#__PURE__*/React.createElement(View, {
86
+ style: [viewStyle, styles.reload]
87
+ }, /*#__PURE__*/React.createElement(Spacer, {
88
+ size: 20
89
+ }), /*#__PURE__*/React.createElement(IconButton, {
90
+ children: /*#__PURE__*/React.createElement(Restart, {
91
+ fill: '#ffffff'
92
+ }),
93
+ style: {
94
+ width: 48,
95
+ height: 48,
96
+ borderRadius: 24,
97
+ color: '#ffffff',
98
+ backgroundColor: '#767676'
99
+ },
100
+ onPress: onReloadPress
101
+ }));
102
+ }
103
+
104
+ if (failed) {
105
+ return /*#__PURE__*/React.createElement(View, {
106
+ style: [viewStyle, styles.failed]
107
+ });
108
+ }
47
109
 
110
+ return children ? children : null;
111
+ }, [isViewable, isLoaded, errorCount.current, url]);
112
+ useEffect(() => {
113
+ if (url === '') {
114
+ getNextPage === null || getNextPage === void 0 ? void 0 : getNextPage(sortKey);
115
+ }
116
+ }, []);
48
117
  return /*#__PURE__*/React.createElement(Image, {
49
118
  disableOutline: true,
50
- key: sourceUrl,
119
+ key: sortKey,
51
120
  onLoad: onLoad,
52
121
  onError: handleError,
53
122
  source: {
54
- uri: sourceUrl
123
+ uri: url
55
124
  },
56
125
  style: viewStyle,
57
- square: true
126
+ square: true,
127
+ Placeholder: Placeholder
58
128
  });
59
129
  }
60
130
 
@@ -63,7 +133,7 @@ export default /*#__PURE__*/React.memo(ViewerItem, (prevProps, nextProps) => {
63
133
  return false;
64
134
  }
65
135
 
66
- if (prevProps.props.sourceUrl !== nextProps.props.sourceUrl) {
136
+ if (prevProps.props.url !== nextProps.props.url) {
67
137
  return false;
68
138
  }
69
139
 
@@ -1 +1 @@
1
- {"version":3,"names":["React","useCallback","useRef","useState","View","Image","StyleSheet","styles","create","placeholder","backgroundColor","ViewerItem","props","height","id","isViewable","onError","sourceUrl","width","isLoaded","setIsLoaded","errorCount","onLoad","current","handleError","count","viewStyle","Placeholder","uri","memo","prevProps","nextProps"],"sources":["ViewerItem.tsx"],"sourcesContent":["import React, { useCallback, useRef, useState } from 'react';\nimport { View } from 'react-native';\nimport { Image, StyleSheet } from '@fountain-ui/core';\nimport ComicViewerItemProps from './ComicViewerItemProps';\n\nconst styles = StyleSheet.create({\n placeholder: {\n backgroundColor: '#abcabc',\n },\n});\n\nfunction ViewerItem<T>({ props }: { props: ComicViewerItemProps<T> }) {\n const {\n height,\n id,\n isViewable,\n onError,\n sourceUrl,\n width,\n } = props;\n\n const [isLoaded, setIsLoaded] = useState(false);\n\n const errorCount = useRef<number>(0);\n\n const onLoad = useCallback(() => {\n errorCount.current = 0;\n setIsLoaded(true);\n }, []);\n\n const handleError = useCallback(() => {\n errorCount.current = errorCount.current + 1;\n\n onError && onError({\n id,\n count: errorCount.current\n });\n }, [id]);\n\n const viewStyle = { width, height };\n\n const Placeholder = () => (\n <View style={[\n viewStyle,\n styles.placeholder,\n ]}/>\n );\n\n if (!isViewable && !isLoaded) {\n return <Placeholder/>;\n }\n\n return (\n <Image\n disableOutline={true}\n key={sourceUrl}\n onLoad={onLoad}\n onError={handleError}\n source={{ uri: sourceUrl }}\n style={viewStyle}\n square={true}\n />\n );\n}\n\nexport default React.memo(ViewerItem, (prevProps, nextProps) => {\n if (prevProps.props.isViewable !== nextProps.props.isViewable) {\n return false;\n }\n\n if (prevProps.props.sourceUrl !== nextProps.props.sourceUrl) {\n return false;\n }\n\n return true;\n});\n"],"mappings":"AAAA,OAAOA,KAAP,IAAgBC,WAAhB,EAA6BC,MAA7B,EAAqCC,QAArC,QAAqD,OAArD;AACA,SAASC,IAAT,QAAqB,cAArB;AACA,SAASC,KAAT,EAAgBC,UAAhB,QAAkC,mBAAlC;AAGA,MAAMC,MAAM,GAAGD,UAAU,CAACE,MAAX,CAAkB;EAC7BC,WAAW,EAAE;IACTC,eAAe,EAAE;EADR;AADgB,CAAlB,CAAf;;AAMA,SAASC,UAAT,OAAsE;EAAA,IAA/C;IAAEC;EAAF,CAA+C;EAClE,MAAM;IACFC,MADE;IAEFC,EAFE;IAGFC,UAHE;IAIFC,OAJE;IAKFC,SALE;IAMFC;EANE,IAOFN,KAPJ;EASA,MAAM,CAACO,QAAD,EAAWC,WAAX,IAA0BjB,QAAQ,CAAC,KAAD,CAAxC;EAEA,MAAMkB,UAAU,GAAGnB,MAAM,CAAS,CAAT,CAAzB;EAEA,MAAMoB,MAAM,GAAGrB,WAAW,CAAC,MAAM;IAC7BoB,UAAU,CAACE,OAAX,GAAqB,CAArB;IACAH,WAAW,CAAC,IAAD,CAAX;EACH,CAHyB,EAGvB,EAHuB,CAA1B;EAKA,MAAMI,WAAW,GAAGvB,WAAW,CAAC,MAAM;IAClCoB,UAAU,CAACE,OAAX,GAAqBF,UAAU,CAACE,OAAX,GAAqB,CAA1C;IAEAP,OAAO,IAAIA,OAAO,CAAC;MACfF,EADe;MAEfW,KAAK,EAAEJ,UAAU,CAACE;IAFH,CAAD,CAAlB;EAIH,CAP8B,EAO5B,CAACT,EAAD,CAP4B,CAA/B;EASA,MAAMY,SAAS,GAAG;IAAER,KAAF;IAASL;EAAT,CAAlB;;EAEA,MAAMc,WAAW,GAAG,mBAChB,oBAAC,IAAD;IAAM,KAAK,EAAE,CACTD,SADS,EAETnB,MAAM,CAACE,WAFE;EAAb,EADJ;;EAOA,IAAI,CAACM,UAAD,IAAe,CAACI,QAApB,EAA8B;IAC1B,oBAAO,oBAAC,WAAD,OAAP;EACH;;EAED,oBACI,oBAAC,KAAD;IACI,cAAc,EAAE,IADpB;IAEI,GAAG,EAAEF,SAFT;IAGI,MAAM,EAAEK,MAHZ;IAII,OAAO,EAAEE,WAJb;IAKI,MAAM,EAAE;MAAEI,GAAG,EAAEX;IAAP,CALZ;IAMI,KAAK,EAAES,SANX;IAOI,MAAM,EAAE;EAPZ,EADJ;AAWH;;AAED,4BAAe1B,KAAK,CAAC6B,IAAN,CAAWlB,UAAX,EAAuB,CAACmB,SAAD,EAAYC,SAAZ,KAA0B;EAC5D,IAAID,SAAS,CAAClB,KAAV,CAAgBG,UAAhB,KAA+BgB,SAAS,CAACnB,KAAV,CAAgBG,UAAnD,EAA+D;IAC3D,OAAO,KAAP;EACH;;EAED,IAAIe,SAAS,CAAClB,KAAV,CAAgBK,SAAhB,KAA8Bc,SAAS,CAACnB,KAAV,CAAgBK,SAAlD,EAA6D;IACzD,OAAO,KAAP;EACH;;EAED,OAAO,IAAP;AACH,CAVc,CAAf"}
1
+ {"version":3,"names":["React","useCallback","useEffect","useRef","useState","View","R","IconButton","Image","Spacer","useTheme","Restart","useStyles","theme","init","backgroundColor","palette","paper","grey","failed","reload","display","alignItems","ViewerItem","props","expiresAt","errorRetryCount","height","itemState","isViewable","sortKey","url","width","getNextPage","onError","onLoaded","isLoaded","setIsLoaded","styles","errorCount","defaultTo","error","count","onLoad","current","handleError","expired","Date","onReloadPress","viewStyle","Placeholder","children","borderRadius","color","uri","memo","prevProps","nextProps"],"sources":["ViewerItem.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useRef, useState } from 'react';\nimport { View } from 'react-native';\nimport * as R from 'ramda';\nimport type { PlaceholderProps } from '@fountain-ui/core';\nimport { IconButton, Image, Spacer, useTheme } from '@fountain-ui/core';\nimport { NamedStylesStringUnion, UseStyles } from '@fountain-ui/styles';\nimport { Restart } from '@fountain-ui/icons';\nimport ComicViewerItemProps from './ComicViewerItemProps';\n\ntype PlaceholderStyles = NamedStylesStringUnion<'init' | 'failed' | 'reload'>;\n\nconst useStyles: UseStyles<PlaceholderStyles> = function (): PlaceholderStyles {\n const theme = useTheme();\n\n return {\n init: {\n backgroundColor: theme.palette.paper.grey,\n },\n failed: {\n backgroundColor: theme.palette.paper.grey,\n },\n reload: {\n backgroundColor: theme.palette.paper.grey,\n display: 'flex',\n alignItems: 'center',\n },\n };\n};\n\nfunction ViewerItem<T>({ props }: { props: ComicViewerItemProps<T> }) {\n const {\n expiresAt,\n errorRetryCount = 3,\n height,\n itemState,\n isViewable,\n sortKey,\n url,\n width,\n getNextPage,\n onError,\n onLoaded,\n } = props;\n\n const [isLoaded, setIsLoaded] = useState(false);\n\n const styles = useStyles();\n\n const errorCount = useRef<number>(R.defaultTo(0)(itemState?.error?.count));\n\n const onLoad = useCallback(() => {\n errorCount.current = 0;\n\n setIsLoaded(true);\n\n onLoaded && onLoaded(sortKey);\n }, [sortKey]);\n\n const handleError = useCallback(() => {\n errorCount.current = errorCount.current + 1;\n\n const expired = expiresAt ? new Date(expiresAt) <= new Date() : false;\n\n onError && onError({\n sortKey,\n count: errorCount.current,\n expired,\n });\n }, [errorCount.current]);\n\n const onReloadPress = useCallback(() => {\n errorCount.current = 1;\n\n onError && onError({\n sortKey,\n count: errorCount.current,\n expired: false,\n });\n }, [sortKey]);\n\n const viewStyle = { width, height };\n\n const Placeholder = useCallback((props: PlaceholderProps) => {\n const { children, failed } = props;\n\n if (!isViewable && !isLoaded) {\n return <View style={[\n viewStyle,\n styles.init,\n ]}/>;\n }\n\n if (errorCount.current >= errorRetryCount) {\n return <View style={[\n viewStyle,\n styles.reload,\n ]}>\n <Spacer size={20}/>\n\n <IconButton\n children={<Restart fill={'#ffffff'}/>}\n style={{\n width: 48,\n height: 48,\n borderRadius: 24,\n color: '#ffffff',\n backgroundColor: '#767676',\n }}\n onPress={onReloadPress}\n />\n </View>;\n }\n\n if (failed) {\n return (\n <View style={[\n viewStyle,\n styles.failed,\n ]}/>\n );\n }\n\n return children ? children : null;\n }, [isViewable, isLoaded, errorCount.current, url]);\n\n useEffect(() => {\n if (url === '') {\n getNextPage?.(sortKey);\n }\n }, []);\n\n return (\n <Image\n disableOutline={true}\n key={sortKey}\n onLoad={onLoad}\n onError={handleError}\n source={{ uri: url }}\n style={viewStyle}\n square={true}\n Placeholder={Placeholder}\n />\n );\n}\n\nexport default React.memo(ViewerItem, (prevProps, nextProps) => {\n if (prevProps.props.isViewable !== nextProps.props.isViewable) {\n return false;\n }\n\n if (prevProps.props.url !== nextProps.props.url) {\n return false;\n }\n\n return true;\n});\n"],"mappings":"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"}
@@ -1,12 +1,23 @@
1
- import { ComicViewerItemData, ErrorInfo } from './ComicViewerProps';
1
+ import { ComicViewerItemData, ErrorInfo, ComicViewerItemState } from './ComicViewerProps';
2
2
  declare type ComicViewerItemProps<T> = ComicViewerItemData<T> & {
3
3
  /**
4
4
  * FlatListItem is viewable in screen.
5
5
  */
6
6
  isViewable: boolean;
7
+ /**
8
+ * How many times retry onError when same item error occur
9
+ * @default 3
10
+ */
11
+ errorRetryCount?: number;
7
12
  /**
8
13
  * Error handler
9
14
  */
10
15
  onError?: (errorInfo: ErrorInfo) => void;
16
+ /**
17
+ * Load handler
18
+ */
19
+ onLoaded?: (sortKey: number) => void;
20
+ getNextPage?: (sortKey: number) => void;
21
+ itemState?: ComicViewerItemState;
11
22
  };
12
23
  export default ComicViewerItemProps;
@@ -1,13 +1,36 @@
1
+ import React from 'react';
1
2
  import { ComponentProps } from '@fountain-ui/core';
3
+ import { NativeScrollEvent, NativeSyntheticEvent } from 'react-native';
4
+ export declare const STATE: {
5
+ readonly UNLOAD: "unload";
6
+ readonly LOADING: "loading";
7
+ readonly LOADED: "loaded";
8
+ readonly FAIL: "fail";
9
+ };
10
+ export declare type LoadingState = typeof STATE[keyof typeof STATE];
11
+ export interface ComicViewerItemState {
12
+ /**
13
+ * Content's loading state.
14
+ */
15
+ state: LoadingState;
16
+ /***
17
+ * Content's error Info.
18
+ */
19
+ error?: ErrorInfo;
20
+ }
2
21
  export interface ErrorInfo {
3
22
  /**
4
- * ComicViewerItemData.id.
23
+ * ComicViewerItemData.sortKey.
5
24
  */
6
- id: string;
25
+ sortKey: number;
7
26
  /**
8
27
  * Number of times an error occurred.
9
28
  */
10
29
  count: number;
30
+ /**
31
+ * Content is Expired: true
32
+ */
33
+ expired: boolean;
11
34
  }
12
35
  export declare type ComicViewerItemData<T = {}> = T & {
13
36
  /**
@@ -17,15 +40,23 @@ export declare type ComicViewerItemData<T = {}> = T & {
17
40
  /**
18
41
  * Unique value for identifying.
19
42
  */
20
- id: string;
43
+ id: number | undefined;
21
44
  /**
22
45
  * Image sourceUrl for displaying.
23
46
  */
24
- sourceUrl: string;
47
+ url: string;
25
48
  /**
26
49
  * Image width.
27
50
  */
28
51
  width: number;
52
+ /**
53
+ * SortKey
54
+ */
55
+ sortKey: number;
56
+ /**
57
+ * Image expire date.
58
+ */
59
+ expiresAt: string;
29
60
  };
30
61
  export default interface ComicViewerProps<T> extends ComponentProps<{
31
62
  /**
@@ -43,9 +74,9 @@ export default interface ComicViewerProps<T> extends ComponentProps<{
43
74
  */
44
75
  errorRetryCount?: number;
45
76
  /**
46
- * How many items to render in the initial batch.
47
- * @default 1
48
- */
77
+ * How many items to render in the initial batch.
78
+ * @default 1
79
+ */
49
80
  initialNumToRender?: number;
50
81
  /**
51
82
  * Start at initialScrollPercentage.
@@ -58,11 +89,6 @@ export default interface ComicViewerProps<T> extends ComponentProps<{
58
89
  * @default 0
59
90
  */
60
91
  itemVisiblePercentThreshold?: number;
61
- /**
62
- * Handling all viewerItem errors at once.
63
- * @param errors Array of ViewerItems errorInfo.
64
- */
65
- onError?: (errors: ErrorInfo[]) => void;
66
92
  /**
67
93
  * Comic viewer width.
68
94
  */
@@ -72,5 +98,28 @@ export default interface ComicViewerProps<T> extends ComponentProps<{
72
98
  * @default 3
73
99
  */
74
100
  windowSize?: number;
101
+ /**
102
+ * How many images in one page.
103
+ */
104
+ pageUnit: number;
105
+ /**
106
+ * Method for getting next page contents.
107
+ * @param sortKey
108
+ */
109
+ getNextPage?: (sortKey: number) => void;
110
+ /**
111
+ * Handling all viewerItem errors at once.
112
+ * @param errors Array of ViewerItems errorInfo.
113
+ */
114
+ onError?: (errors: ErrorInfo[]) => void;
115
+ /**
116
+ * Handle scroll event.
117
+ * @param event Scroll event.
118
+ */
119
+ onScroll?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;
120
+ /**
121
+ * Component for comic viewer footer.
122
+ */
123
+ ListFooterComponent?: React.ReactElement;
75
124
  }> {
76
125
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fountain-ui/lab",
3
- "version": "2.0.0-beta.29",
3
+ "version": "2.0.0-beta.30",
4
4
  "private": false,
5
5
  "author": "Fountain-UI Team",
6
6
  "description": "Incubator for Fountain-UI React components.",
@@ -70,5 +70,5 @@
70
70
  "publishConfig": {
71
71
  "access": "public"
72
72
  },
73
- "gitHead": "019b85d550c729ccca7f3877d6aebe3fa02bd2ec"
73
+ "gitHead": "0c9f01b22179356577219f06bc6a21f6eb3f554c"
74
74
  }