@shoutem/ui 8.3.0-rc.2 → 9.0.0-rc.0

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,80 +1,60 @@
1
- import React, { PureComponent } from 'react';
1
+ import React, { useContext, useEffect, useRef } from 'react';
2
2
  import { Animated } from 'react-native';
3
- import autoBindReact from 'auto-bind/react';
3
+ import { useFocusEffect } from '@react-navigation/native';
4
4
  import _ from 'lodash';
5
5
  import PropTypes from 'prop-types';
6
- import { ScrollDriver } from '@shoutem/animation';
6
+ import { AnimationDriverContext, ScrollDriver } from '@shoutem/animation';
7
7
  import { connectStyle } from '@shoutem/theme';
8
- import {
9
- ScrollDriverContext,
10
- ScrollDriverProvider,
11
- } from './ScrollDriverProvider.js';
12
8
 
13
- class ScrollView extends PureComponent {
14
- static DriverProvider = ScrollDriverProvider;
15
-
16
- static DriverContext = ScrollDriverContext;
17
-
18
- constructor(props, context) {
19
- super(props, context);
20
-
21
- autoBindReact(this);
22
-
23
- this.animationDriver =
24
- props.driver ||
9
+ const ScrollView = ({ driver, onScroll, primary, style, ...otherProps }) => {
10
+ const animationDriver = useRef(
11
+ driver ||
25
12
  new ScrollDriver(
26
13
  { useNativeDriver: true, nativeScrollEventThrottle: 20 },
27
- props.onScroll,
28
- );
29
- }
30
-
31
- componentDidMount() {
32
- const { driverProvider } = this.context;
33
- const { primary } = this.props;
34
-
35
- if (driverProvider) {
36
- driverProvider.setAnimationDriver(this.animationDriver, primary);
14
+ onScroll,
15
+ ),
16
+ );
17
+ const animationDriverContext = useContext(AnimationDriverContext);
18
+
19
+ // When transition to and back from the screen containing the scrollview,
20
+ // we want to switch to appropriate animation driver. We use the following hook
21
+ // to derive the new driver and cascading styles before the actual navigation transition is done
22
+ // to avoid rerendering when the actual nav transition completes
23
+ useFocusEffect(() => {
24
+ const {
25
+ animationDriver: prevAnimationDriver,
26
+ setAnimationDriver,
27
+ } = animationDriverContext;
28
+
29
+ if (setAnimationDriver) {
30
+ setAnimationDriver(animationDriver.current, primary);
37
31
  }
38
- }
39
32
 
40
- componentDidUpdate() {
41
- const { driver } = this.props;
33
+ return () => {
34
+ if (prevAnimationDriver) {
35
+ setAnimationDriver(prevAnimationDriver);
36
+ }
37
+ };
38
+ });
42
39
 
43
- if (driver && this.animationDriver !== driver) {
44
- this.animationDriver = driver;
40
+ useEffect(() => {
41
+ if (driver && animationDriver.current !== driver) {
42
+ animationDriver.current = driver;
45
43
  }
46
- }
47
-
48
- setWrappedInstance(component) {
49
- this.wrappedInstance = component;
50
- }
51
-
52
- render() {
53
- const { style, ...otherProps } = this.props;
54
- const { driverProvider } = this.context;
55
- const { scrollViewProps } = this.animationDriver;
56
- const { contentContainerStyle, ...otherStyle } = style;
57
-
58
- return (
59
- <ScrollDriverContext.Provider
60
- value={{
61
- driverProvider,
62
- animationDriver: this.animationDriver,
63
- }}
64
- >
65
- <Animated.ScrollView
66
- ref={this.setWrappedInstance}
67
- contentContainerStyle={contentContainerStyle}
68
- {...scrollViewProps}
69
- {..._.omit(otherProps, 'onScroll')}
70
- style={otherStyle}
71
- />
72
- </ScrollDriverContext.Provider>
73
- );
74
- }
75
- }
76
-
77
- ScrollView.contextType = ScrollDriverContext;
44
+ }, [driver]);
45
+
46
+ const { scrollViewProps } = animationDriver?.current;
47
+ const { contentContainerStyle, ...otherStyle } = style;
48
+
49
+ return (
50
+ <Animated.ScrollView
51
+ contentContainerStyle={contentContainerStyle}
52
+ {...scrollViewProps}
53
+ {..._.omit(otherProps, 'onScroll')}
54
+ style={otherStyle}
55
+ />
56
+ );
57
+ };
78
58
 
79
59
  ScrollView.propTypes = {
80
60
  ...Animated.ScrollView.propTypes,
@@ -87,27 +67,4 @@ ScrollView.defaultProps = {
87
67
 
88
68
  const StyledScrollView = connectStyle('shoutem.ui.ScrollView')(ScrollView);
89
69
 
90
- function getRNScrollViewComponent(context) {
91
- // wrappedInstance.wrappedInstance._component:
92
- // 1st wrappedInstance -> StyledScrollView
93
- // 2nd wrappedInstance -> ScrollView (Shoutem UI)
94
- // _component -> Animated.ScrollView
95
- // more info about _component: https://stackoverflow.com/questions/42051368/scrollto-is-undefined-on-animated-scrollview
96
- return _.get(context, 'wrappedInstance.wrappedInstance._component');
97
- }
98
-
99
- StyledScrollView.prototype.scrollTo = function scrollTo(coordinates) {
100
- const scrollView = getRNScrollViewComponent(this);
101
- if (scrollView) {
102
- scrollView.scrollTo(coordinates);
103
- }
104
- };
105
-
106
- StyledScrollView.prototype.scrollToEnd = function scrollToEnd(animation) {
107
- const scrollView = getRNScrollViewComponent(this);
108
- if (scrollView) {
109
- scrollView.scrollToEnd(animation);
110
- }
111
- };
112
-
113
70
  export { StyledScrollView as ScrollView };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shoutem/ui",
3
- "version": "8.3.0-rc.2",
3
+ "version": "9.0.0-rc.0",
4
4
  "description": "Styleable set of components for React Native applications",
5
5
  "scripts": {
6
6
  "lint": "eslint .",
@@ -51,7 +51,8 @@
51
51
  "react": ">=19.0.0",
52
52
  "react-native": ">=0.78.0",
53
53
  "react-native-gesture-handler": "*",
54
- "react-native-safe-area-context": "*"
54
+ "react-native-safe-area-context": "*",
55
+ "@react-navigation/native": "*"
55
56
  },
56
57
  "devDependencies": {
57
58
  "@babel/core": "^7.25.2",
@@ -1,92 +0,0 @@
1
- import React, { Children, createContext, PureComponent } from 'react';
2
- import _ from 'lodash';
3
- import PropTypes from 'prop-types';
4
- import { DriverShape, ScrollDriver } from '@shoutem/animation';
5
-
6
- export const ScrollDriverContext = createContext({});
7
-
8
- /**
9
- * Use this component if you want to share animation driver between unreachable siblings.
10
- * Just wrap their parent component with it. We use it to share an instance of ScrollDriver
11
- * between Screen and NavigationBar automatically. ScrollView from @shoutem/ui uses it to
12
- * register its driver.
13
- */
14
- export class ScrollDriverProvider extends PureComponent {
15
- constructor(props, context) {
16
- super(props, context);
17
-
18
- this.setupAnimationDriver(props, context);
19
- }
20
-
21
- setupAnimationDriver(props, context) {
22
- const { onAnimationDriverChange } = this.props;
23
-
24
- if (props.driver) {
25
- this.animationDriver = props.driver;
26
- } else if (context.driverProvider) {
27
- this.animationDriver = context.animationDriver;
28
- } else if (!this.animationDriver) {
29
- this.animationDriver = new ScrollDriver(
30
- { useNativeDriver: true, nativeScrollEventThrottle: 20 },
31
- props.onScroll,
32
- );
33
- }
34
-
35
- if (onAnimationDriverChange) {
36
- onAnimationDriverChange(this.animationDriver);
37
- }
38
- }
39
-
40
- setAnimationDriver(driver, primaryScrollView) {
41
- if (driver || !this.animationDriver || primaryScrollView) {
42
- const { onAnimationDriverChange } = this.props;
43
- const { driverProvider } = this.context;
44
-
45
- _.assign(this.animationDriver, driver);
46
- if (onAnimationDriverChange) {
47
- onAnimationDriverChange(driver);
48
- }
49
-
50
- if (driverProvider) {
51
- driverProvider.setAnimationDriver(driver, primaryScrollView);
52
- }
53
- }
54
- }
55
-
56
- render() {
57
- const { children } = this.props;
58
-
59
- return (
60
- <ScrollDriverContext.Provider
61
- value={{
62
- driverProvider: this,
63
- animationDriver: this.animationDriver,
64
- }}
65
- >
66
- {children && Children.only(children)}
67
- </ScrollDriverContext.Provider>
68
- );
69
- }
70
- }
71
-
72
- ScrollDriverProvider.contextType = ScrollDriverContext;
73
-
74
- // We disable this eslint rule because the props are being utilized indirectly
75
- // through componentDidUpdate's usage of setupAnimationDriver
76
- /* eslint-disable react/no-unused-prop-types */
77
- ScrollDriverProvider.propTypes = {
78
- children: PropTypes.node,
79
- driver: DriverShape,
80
- // Used to propagate animation driver changes to components that aren't
81
- // children of ScrollDriver, recieves driver as argument.
82
- // TODO: Rewrite for new context API.
83
- onAnimationDriverChange: PropTypes.func,
84
- onScroll: PropTypes.func,
85
- };
86
-
87
- ScrollDriverProvider.defaultProps = {
88
- children: undefined,
89
- driver: undefined,
90
- onAnimationDriverChange: undefined,
91
- onScroll: undefined,
92
- };