@orionarm/react-native-collapse-tabs 1.0.3 → 1.0.5

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.
@@ -1 +1 @@
1
- {"version":3,"file":"CollapseTabs.d.ts","sourceRoot":"","sources":["../src/CollapseTabs.tsx"],"names":[],"mappings":"AAAA,OAAO,KAKN,MAAM,OAAO,CAAC;AAkBf,OAAO,EACL,iBAAiB,EAOlB,MAAM,eAAe,CAAC;AAIvB,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAgLpD,CAAC"}
1
+ {"version":3,"file":"CollapseTabs.d.ts","sourceRoot":"","sources":["../src/CollapseTabs.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAiD,MAAM,OAAO,CAAC;AAkBtE,OAAO,EACL,iBAAiB,EAOlB,MAAM,eAAe,CAAC;AAIvB,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAkLpD,CAAC"}
@@ -1,4 +1,4 @@
1
- import React, { useCallback, useMemo, useRef, useState, } from "react";
1
+ import React, { useCallback, useMemo, useRef, useState } from "react";
2
2
  import { StyleSheet, View } from "react-native";
3
3
  import PagerView from "react-native-pager-view";
4
4
  import Animated, { useAnimatedReaction, useAnimatedStyle, useEvent, useHandler, useSharedValue, withTiming, } from "react-native-reanimated";
@@ -25,7 +25,7 @@ export const CollapseTabs = ({ children, initialTabName, headerHeight, tabBarHei
25
25
  const y = scrollY.value[tab] ?? 0;
26
26
  return {
27
27
  tab,
28
- translateY: -Math.min(y, headerScrollDistance),
28
+ translateY: -Math.min(Math.max(y, 0), headerScrollDistance),
29
29
  };
30
30
  }, (next, prev) => {
31
31
  if (prev && prev.tab !== next.tab) {
@@ -103,9 +103,7 @@ export const CollapseTabs = ({ children, initialTabName, headerHeight, tabBarHei
103
103
  {renderHeader?.(headerProps)}
104
104
  </View>
105
105
  <View style={{ height: tabBarHeight }}>
106
- {renderTabBar
107
- ? renderTabBar(headerProps)
108
- : <DefaultTabBar {...headerProps}/>}
106
+ {renderTabBar ? (renderTabBar(headerProps)) : (<DefaultTabBar {...headerProps}/>)}
109
107
  </View>
110
108
  </Animated.View>
111
109
  </View>
package/lib/FlatList.d.ts CHANGED
@@ -3,6 +3,6 @@ import { FlatListProps } from "react-native";
3
3
  type Props<T> = FlatListProps<T> & {
4
4
  name: string;
5
5
  };
6
- export declare function FlatList<T>({ name, contentContainerStyle, ...rest }: Props<T>): React.JSX.Element;
6
+ export declare function FlatList<T>({ name, contentContainerStyle, onScroll: userOnScroll, ...rest }: Props<T>): React.JSX.Element;
7
7
  export {};
8
8
  //# sourceMappingURL=FlatList.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"FlatList.d.ts","sourceRoot":"","sources":["../src/FlatList.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAoB,MAAM,OAAO,CAAC;AACzC,OAAO,EAA0B,aAAa,EAAE,MAAM,cAAc,CAAC;AAOrE,KAAK,KAAK,CAAC,CAAC,IAAI,aAAa,CAAC,CAAC,CAAC,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpD,wBAAgB,QAAQ,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,qBAAqB,EAAE,GAAG,IAAI,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC,qBAoC7E"}
1
+ {"version":3,"file":"FlatList.d.ts","sourceRoot":"","sources":["../src/FlatList.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAoB,MAAM,OAAO,CAAC;AACzC,OAAO,EAA0B,aAAa,EAAE,MAAM,cAAc,CAAC;AAQrE,KAAK,KAAK,CAAC,CAAC,IAAI,aAAa,CAAC,CAAC,CAAC,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpD,wBAAgB,QAAQ,CAAC,CAAC,EAAE,EAC1B,IAAI,EACJ,qBAAqB,EACrB,QAAQ,EAAE,YAAY,EACtB,GAAG,IAAI,EACR,EAAE,KAAK,CAAC,CAAC,CAAC,qBA+CV"}
package/lib/FlatList.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import React, { useEffect } from "react";
2
- import Animated, { useAnimatedRef, useAnimatedScrollHandler, } from "react-native-reanimated";
2
+ import Animated, { runOnJS, useAnimatedRef, useAnimatedScrollHandler, } from "react-native-reanimated";
3
3
  import { useTabsContext } from "./hooks";
4
- export function FlatList({ name, contentContainerStyle, ...rest }) {
4
+ export function FlatList({ name, contentContainerStyle, onScroll: userOnScroll, ...rest }) {
5
5
  const { headerHeight, tabBarHeight, scrollY, focusedTab, setRef, } = useTabsContext();
6
6
  const ref = useAnimatedRef();
7
7
  useEffect(() => {
@@ -9,13 +9,21 @@ export function FlatList({ name, contentContainerStyle, ...rest }) {
9
9
  }, [name, ref, setRef]);
10
10
  const handler = useAnimatedScrollHandler({
11
11
  onScroll: (event) => {
12
- if (focusedTab.value !== name)
13
- return;
14
- const map = { ...scrollY.value };
15
- map[name] = event.contentOffset.y;
16
- scrollY.value = map;
12
+ if (focusedTab.value === name) {
13
+ const map = { ...scrollY.value };
14
+ map[name] = event.contentOffset.y;
15
+ scrollY.value = map;
16
+ }
17
+ if (userOnScroll) {
18
+ if (userOnScroll.worklet === true) {
19
+ userOnScroll(event);
20
+ }
21
+ else {
22
+ runOnJS(userOnScroll)(event);
23
+ }
24
+ }
17
25
  },
18
- });
26
+ }, [name, userOnScroll]);
19
27
  return (<Animated.FlatList {...rest} ref={ref} onScroll={handler} scrollEventThrottle={16} contentContainerStyle={[
20
28
  { paddingTop: headerHeight + tabBarHeight },
21
29
  contentContainerStyle,
@@ -4,6 +4,6 @@ type Props = ScrollViewProps & {
4
4
  name: string;
5
5
  children?: React.ReactNode;
6
6
  };
7
- export declare function ScrollView({ name, contentContainerStyle, children, ...rest }: Props): React.JSX.Element;
7
+ export declare function ScrollView({ name, contentContainerStyle, children, onScroll: userOnScroll, ...rest }: Props): React.JSX.Element;
8
8
  export {};
9
9
  //# sourceMappingURL=ScrollView.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ScrollView.d.ts","sourceRoot":"","sources":["../src/ScrollView.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAoB,MAAM,OAAO,CAAC;AACzC,OAAO,EAAE,eAAe,EAA8B,MAAM,cAAc,CAAC;AAO3E,KAAK,KAAK,GAAG,eAAe,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CAAE,CAAC;AAE5E,wBAAgB,UAAU,CAAC,EACzB,IAAI,EACJ,qBAAqB,EACrB,QAAQ,EACR,GAAG,IAAI,EACR,EAAE,KAAK,qBAsCP"}
1
+ {"version":3,"file":"ScrollView.d.ts","sourceRoot":"","sources":["../src/ScrollView.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAoB,MAAM,OAAO,CAAC;AACzC,OAAO,EAAE,eAAe,EAA8B,MAAM,cAAc,CAAC;AAQ3E,KAAK,KAAK,GAAG,eAAe,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CAAE,CAAC;AAE5E,wBAAgB,UAAU,CAAC,EACzB,IAAI,EACJ,qBAAqB,EACrB,QAAQ,EACR,QAAQ,EAAE,YAAY,EACtB,GAAG,IAAI,EACR,EAAE,KAAK,qBAiDP"}
package/lib/ScrollView.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import React, { useEffect } from "react";
2
- import Animated, { useAnimatedRef, useAnimatedScrollHandler, } from "react-native-reanimated";
2
+ import Animated, { runOnJS, useAnimatedRef, useAnimatedScrollHandler, } from "react-native-reanimated";
3
3
  import { useTabsContext } from "./hooks";
4
- export function ScrollView({ name, contentContainerStyle, children, ...rest }) {
4
+ export function ScrollView({ name, contentContainerStyle, children, onScroll: userOnScroll, ...rest }) {
5
5
  const { headerHeight, tabBarHeight, scrollY, focusedTab, setRef, } = useTabsContext();
6
6
  const ref = useAnimatedRef();
7
7
  useEffect(() => {
@@ -9,13 +9,21 @@ export function ScrollView({ name, contentContainerStyle, children, ...rest }) {
9
9
  }, [name, ref, setRef]);
10
10
  const handler = useAnimatedScrollHandler({
11
11
  onScroll: (event) => {
12
- if (focusedTab.value !== name)
13
- return;
14
- const map = { ...scrollY.value };
15
- map[name] = event.contentOffset.y;
16
- scrollY.value = map;
12
+ if (focusedTab.value === name) {
13
+ const map = { ...scrollY.value };
14
+ map[name] = event.contentOffset.y;
15
+ scrollY.value = map;
16
+ }
17
+ if (userOnScroll) {
18
+ if (userOnScroll.worklet === true) {
19
+ userOnScroll(event);
20
+ }
21
+ else {
22
+ runOnJS(userOnScroll)(event);
23
+ }
24
+ }
17
25
  },
18
- });
26
+ }, [name, userOnScroll]);
19
27
  return (<Animated.ScrollView {...rest} ref={ref} onScroll={handler} scrollEventThrottle={16} contentContainerStyle={[
20
28
  { paddingTop: headerHeight + tabBarHeight },
21
29
  contentContainerStyle,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orionarm/react-native-collapse-tabs",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "description": "A React Native collapsible tabs component",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -27,6 +27,14 @@
27
27
  ],
28
28
  "author": "yanan_orionarm",
29
29
  "license": "ISC",
30
+ "repository": {
31
+ "type": "git",
32
+ "url": "git+https://github.com/orion-arm-ai/react-native-collapse-tabs.git"
33
+ },
34
+ "bugs": {
35
+ "url": "https://github.com/orion-arm-ai/react-native-collapse-tabs/issues"
36
+ },
37
+ "homepage": "https://github.com/orion-arm-ai/react-native-collapse-tabs#readme",
30
38
  "peerDependencies": {
31
39
  "react": ">=16.8.0",
32
40
  "react-native": ">=0.60.0",
@@ -1,9 +1,4 @@
1
- import React, {
2
- useCallback,
3
- useMemo,
4
- useRef,
5
- useState,
6
- } from "react";
1
+ import React, { useCallback, useMemo, useRef, useState } from "react";
7
2
  import { StyleSheet, View } from "react-native";
8
3
  import PagerView, {
9
4
  PagerViewOnPageScrollEventData,
@@ -48,20 +43,20 @@ export const CollapseTabs: React.FC<CollapseTabsProps> = ({
48
43
  }) => {
49
44
  const tabs = useMemo(
50
45
  () =>
51
- React.Children.toArray(children).filter(
52
- (c): c is TabReactElement => React.isValidElement(c)
46
+ React.Children.toArray(children).filter((c): c is TabReactElement =>
47
+ React.isValidElement(c),
53
48
  ),
54
- [children]
49
+ [children],
55
50
  );
56
51
 
57
52
  const tabNames = useMemo(
58
53
  () => tabs.map((t) => (t.props as TabProps).name),
59
- [tabs]
54
+ [tabs],
60
55
  );
61
56
 
62
57
  const initialIndex = Math.max(
63
58
  0,
64
- initialTabName ? tabNames.indexOf(initialTabName) : 0
59
+ initialTabName ? tabNames.indexOf(initialTabName) : 0,
65
60
  );
66
61
 
67
62
  const headerScrollDistance = headerHeight - minHeaderHeight;
@@ -85,7 +80,7 @@ export const CollapseTabs: React.FC<CollapseTabsProps> = ({
85
80
  const y = scrollY.value[tab] ?? 0;
86
81
  return {
87
82
  tab,
88
- translateY: -Math.min(y, headerScrollDistance),
83
+ translateY: -Math.min(Math.max(y, 0), headerScrollDistance),
89
84
  };
90
85
  },
91
86
  (next, prev) => {
@@ -95,7 +90,7 @@ export const CollapseTabs: React.FC<CollapseTabsProps> = ({
95
90
  headerTranslateY.value = next.translateY;
96
91
  }
97
92
  },
98
- [headerScrollDistance]
93
+ [headerScrollDistance],
99
94
  );
100
95
 
101
96
  const refMap = useRef<Record<TabName, AnimatedRef<RefComponent>>>({}).current;
@@ -105,16 +100,19 @@ export const CollapseTabs: React.FC<CollapseTabsProps> = ({
105
100
  refMap[key] = ref as unknown as AnimatedRef<RefComponent>;
106
101
  return ref;
107
102
  },
108
- [refMap]
103
+ [refMap],
109
104
  );
110
105
 
111
106
  const containerRef = useRef<ContainerRef>(null);
112
107
 
113
- const onTabPress = useCallback((name: TabName) => {
114
- const i = tabNames.indexOf(name);
115
- if (i < 0) return;
116
- containerRef.current?.setPage(i);
117
- }, [tabNames]);
108
+ const onTabPress = useCallback(
109
+ (name: TabName) => {
110
+ const i = tabNames.indexOf(name);
111
+ if (i < 0) return;
112
+ containerRef.current?.setPage(i);
113
+ },
114
+ [tabNames],
115
+ );
118
116
 
119
117
  const [renderIndex, setRenderIndex] = useState(initialIndex);
120
118
 
@@ -125,7 +123,7 @@ export const CollapseTabs: React.FC<CollapseTabsProps> = ({
125
123
  indexDecimal.value = e.position + e.offset;
126
124
  },
127
125
  ["onPageScroll"],
128
- doDependenciesDiffer
126
+ doDependenciesDiffer,
129
127
  );
130
128
 
131
129
  const onPageSelected = useCallback(
@@ -136,7 +134,7 @@ export const CollapseTabs: React.FC<CollapseTabsProps> = ({
136
134
  setRenderIndex(i);
137
135
  onIndexChange?.(i);
138
136
  },
139
- [tabNames, index, focusedTab, onIndexChange]
137
+ [tabNames, index, focusedTab, onIndexChange],
140
138
  );
141
139
 
142
140
  const headerAnimStyle = useAnimatedStyle(() => ({
@@ -194,16 +192,15 @@ export const CollapseTabs: React.FC<CollapseTabsProps> = ({
194
192
  headerAnimStyle,
195
193
  ]}
196
194
  >
197
- <View
198
- pointerEvents="box-none"
199
- style={{ height: headerHeight }}
200
- >
195
+ <View pointerEvents="box-none" style={{ height: headerHeight }}>
201
196
  {renderHeader?.(headerProps)}
202
197
  </View>
203
198
  <View style={{ height: tabBarHeight }}>
204
- {renderTabBar
205
- ? renderTabBar(headerProps)
206
- : <DefaultTabBar {...headerProps} />}
199
+ {renderTabBar ? (
200
+ renderTabBar(headerProps)
201
+ ) : (
202
+ <DefaultTabBar {...headerProps} />
203
+ )}
207
204
  </View>
208
205
  </Animated.View>
209
206
  </View>
package/src/FlatList.tsx CHANGED
@@ -1,6 +1,7 @@
1
1
  import React, { useEffect } from "react";
2
2
  import { FlatList as RNFlatList, FlatListProps } from "react-native";
3
3
  import Animated, {
4
+ runOnJS,
4
5
  useAnimatedRef,
5
6
  useAnimatedScrollHandler,
6
7
  } from "react-native-reanimated";
@@ -8,7 +9,12 @@ import { useTabsContext } from "./hooks";
8
9
 
9
10
  type Props<T> = FlatListProps<T> & { name: string };
10
11
 
11
- export function FlatList<T>({ name, contentContainerStyle, ...rest }: Props<T>) {
12
+ export function FlatList<T>({
13
+ name,
14
+ contentContainerStyle,
15
+ onScroll: userOnScroll,
16
+ ...rest
17
+ }: Props<T>) {
12
18
  const {
13
19
  headerHeight,
14
20
  tabBarHeight,
@@ -23,14 +29,25 @@ export function FlatList<T>({ name, contentContainerStyle, ...rest }: Props<T>)
23
29
  setRef(name, ref);
24
30
  }, [name, ref, setRef]);
25
31
 
26
- const handler = useAnimatedScrollHandler({
27
- onScroll: (event) => {
28
- if (focusedTab.value !== name) return;
29
- const map = { ...scrollY.value };
30
- map[name] = event.contentOffset.y;
31
- scrollY.value = map;
32
+ const handler = useAnimatedScrollHandler(
33
+ {
34
+ onScroll: (event) => {
35
+ if (focusedTab.value === name) {
36
+ const map = { ...scrollY.value };
37
+ map[name] = event.contentOffset.y;
38
+ scrollY.value = map;
39
+ }
40
+ if (userOnScroll) {
41
+ if ((userOnScroll as any).worklet === true) {
42
+ (userOnScroll as any)(event);
43
+ } else {
44
+ runOnJS(userOnScroll as any)(event);
45
+ }
46
+ }
47
+ },
32
48
  },
33
- });
49
+ [name, userOnScroll],
50
+ );
34
51
 
35
52
  return (
36
53
  <Animated.FlatList
@@ -1,6 +1,7 @@
1
1
  import React, { useEffect } from "react";
2
2
  import { ScrollViewProps, ScrollView as RNScrollView } from "react-native";
3
3
  import Animated, {
4
+ runOnJS,
4
5
  useAnimatedRef,
5
6
  useAnimatedScrollHandler,
6
7
  } from "react-native-reanimated";
@@ -12,6 +13,7 @@ export function ScrollView({
12
13
  name,
13
14
  contentContainerStyle,
14
15
  children,
16
+ onScroll: userOnScroll,
15
17
  ...rest
16
18
  }: Props) {
17
19
  const {
@@ -28,14 +30,25 @@ export function ScrollView({
28
30
  setRef(name, ref);
29
31
  }, [name, ref, setRef]);
30
32
 
31
- const handler = useAnimatedScrollHandler({
32
- onScroll: (event) => {
33
- if (focusedTab.value !== name) return;
34
- const map = { ...scrollY.value };
35
- map[name] = event.contentOffset.y;
36
- scrollY.value = map;
33
+ const handler = useAnimatedScrollHandler(
34
+ {
35
+ onScroll: (event) => {
36
+ if (focusedTab.value === name) {
37
+ const map = { ...scrollY.value };
38
+ map[name] = event.contentOffset.y;
39
+ scrollY.value = map;
40
+ }
41
+ if (userOnScroll) {
42
+ if ((userOnScroll as any).worklet === true) {
43
+ (userOnScroll as any)(event);
44
+ } else {
45
+ runOnJS(userOnScroll as any)(event);
46
+ }
47
+ }
48
+ },
37
49
  },
38
- });
50
+ [name, userOnScroll],
51
+ );
39
52
 
40
53
  return (
41
54
  <Animated.ScrollView