@shoutem/ui 9.0.0-rc.3 → 9.0.0-rc.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,8 +1,7 @@
1
1
  import React, { useEffect, useRef, useState } from 'react';
2
- import { Animated } from 'react-native';
2
+ import { Animated, ScrollView } from 'react-native';
3
3
  import PropTypes from 'prop-types';
4
4
  import { connectStyle } from '@shoutem/theme';
5
- import { ScrollView } from './ScrollView';
6
5
  import { Text } from './Text';
7
6
 
8
7
  const DEFAULT_CONFIG = {
@@ -10,7 +9,7 @@ const DEFAULT_CONFIG = {
10
9
  waitDuration: 2000,
11
10
  };
12
11
 
13
- const AnimatedScrollingText = ({ text, config, style }) => {
12
+ const AnimatedScrollingText = ({ text, config = DEFAULT_CONFIG, style }) => {
14
13
  const translateX = useRef(new Animated.Value(0)).current;
15
14
 
16
15
  const [containerWidth, setContainerWidth] = useState();
@@ -84,12 +83,12 @@ const AnimatedScrollingText = ({ text, config, style }) => {
84
83
 
85
84
  AnimatedScrollingText.propTypes = {
86
85
  text: PropTypes.string.isRequired,
86
+ // eslint-disable-next-line react/require-default-props
87
87
  config: PropTypes.object,
88
88
  style: PropTypes.object,
89
89
  };
90
90
 
91
91
  AnimatedScrollingText.defaultProps = {
92
- config: DEFAULT_CONFIG,
93
92
  style: {},
94
93
  };
95
94
 
@@ -6,6 +6,11 @@ import PropTypes from 'prop-types';
6
6
  import { AnimationDriverContext, ScrollDriver } from '@shoutem/animation';
7
7
  import { connectStyle } from '@shoutem/theme';
8
8
 
9
+ // ScrollView component envisioned to be used as a container component inside
10
+ // the Shoutem screens. It will correctly set the current animation driver
11
+ // when it is mounted inside the parent screen. In case you don't want the scroll
12
+ // that is aware of the animation driver context, but want the shoutem themed styling,
13
+ // you should use the plain RN ScrollView and connect it to the 'shoutem.ui.ScrollView' stylename
9
14
  const ScrollView = ({ driver, onScroll, primary, style, ...otherProps }) => {
10
15
  const animationDriver = useRef(
11
16
  driver ||
@@ -1,4 +1,4 @@
1
- import React, { PureComponent } from 'react';
1
+ import React, { useCallback, useMemo } from 'react';
2
2
  import { Linking } from 'react-native';
3
3
  import Html, { defaultSystemFonts } from 'react-native-render-html';
4
4
  import WebView from 'react-native-webview';
@@ -8,9 +8,7 @@ import table, {
8
8
  defaultTableStylesSpecs,
9
9
  tableModel,
10
10
  } from '@native-html/table-plugin';
11
- import autoBindReact from 'auto-bind/react';
12
11
  import _ from 'lodash';
13
- import PropTypes from 'prop-types';
14
12
  import { connectStyle } from '@shoutem/theme';
15
13
  import VideoRenderer from '@shoutem/ui/html/components/VideoRenderer';
16
14
  import { videoModel } from '@shoutem/ui/html/services/HTMLElementModels';
@@ -20,52 +18,53 @@ import { onElement } from '../services/DomVisitors';
20
18
  import AttachmentRenderer from './AttachmentRenderer';
21
19
  import IframeRenderer from './IframeRenderer';
22
20
 
23
- class SimpleHtml extends PureComponent {
24
- constructor(props) {
25
- super(props);
21
+ const SimpleHtml = ({
22
+ style,
23
+ body,
24
+ unsupportedVideoFormatMessage,
25
+ attachments,
26
+ customDomVisitors = {},
27
+ customCustomRenderers = {},
28
+ customTagStyles = {},
29
+ customHtmlElementModels = {},
30
+ customIgnoredStyles = [],
31
+ customRendererProps = {},
32
+ customHandleLinkPress,
33
+ ...otherProps
34
+ }) => {
35
+ const onLinkPress = useCallback(
36
+ (_evt, href) => {
37
+ return customHandleLinkPress
38
+ ? customHandleLinkPress(href)
39
+ : Linking.openURL(href);
40
+ },
41
+ [customHandleLinkPress],
42
+ );
26
43
 
27
- autoBindReact(this);
28
- }
44
+ const maxWidth = useMemo(() => {
45
+ return resolveMaxWidth(style);
46
+ }, [style]);
29
47
 
30
- onLinkPress(_evt, href) {
31
- const { customHandleLinkPress } = this.props;
32
-
33
- return customHandleLinkPress
34
- ? customHandleLinkPress(href)
35
- : Linking.openURL(href);
36
- }
37
-
38
- render() {
39
- const {
40
- style,
41
- body,
42
- unsupportedVideoFormatMessage,
43
- attachments,
44
- customDomVisitors,
45
- customCustomRenderers,
46
- customTagStyles,
47
- customHtmlElementModels,
48
- customIgnoredStyles,
49
- customRendererProps,
50
- ...otherProps
51
- } = this.props;
52
-
53
- const maxWidth = resolveMaxWidth(style);
54
-
55
- const tagStyles = {
48
+ const tagStyles = useMemo(
49
+ () => ({
56
50
  ...style.tags,
57
51
  ...customTagStyles,
58
- };
52
+ }),
53
+ [style.tags, customTagStyles],
54
+ );
59
55
 
56
+ const cssRules = useMemo(() => {
60
57
  const tableStyle = _.get(style, 'table', {});
61
58
  const tableCssStyle = _.get(style, 'tableCss', '');
62
59
  const cssStyle = cssRulesFromSpecs({
63
60
  ...defaultTableStylesSpecs,
64
61
  ...tableStyle,
65
62
  });
66
- const cssRules = `${cssStyle}${tableCssStyle}`;
63
+ return `${cssStyle}${tableCssStyle}`;
64
+ }, [style]);
67
65
 
68
- const customRenderers = {
66
+ const customRenderers = useMemo(
67
+ () => ({
69
68
  iframe: props => (
70
69
  <IframeRenderer
71
70
  {...props}
@@ -83,79 +82,87 @@ class SimpleHtml extends PureComponent {
83
82
  ),
84
83
  video: VideoRenderer,
85
84
  ...customCustomRenderers,
86
- };
85
+ }),
86
+ [style, unsupportedVideoFormatMessage, attachments, customCustomRenderers],
87
+ );
88
+
89
+ const systemFonts = useMemo(
90
+ () => [...defaultSystemFonts, style.baseFont.fontFamily],
91
+ [style.baseFont.fontFamily],
92
+ );
93
+
94
+ const ignoredStyles = useMemo(
95
+ () => ['fontFamily', 'letterSpacing', 'transform', ...customIgnoredStyles],
96
+ [customIgnoredStyles],
97
+ );
98
+
99
+ const renderersProps = useMemo(
100
+ () => ({
101
+ table: {
102
+ cssRules,
103
+ },
104
+ a: { onPress: onLinkPress },
105
+ iframe: {
106
+ webViewProps: {
107
+ renderToHardwareTextureAndroid: true,
108
+ },
109
+ },
110
+ ...customRendererProps,
111
+ }),
112
+ [cssRules, onLinkPress, customRendererProps],
113
+ );
87
114
 
88
- const htmlProps = {
115
+ const customHTMLElementModels = useMemo(
116
+ () => ({
117
+ table: tableModel,
118
+ iframe: iframeModel,
119
+ video: videoModel,
120
+ ...customHtmlElementModels,
121
+ }),
122
+ [customHtmlElementModels],
123
+ );
124
+
125
+ const domVisitors = useMemo(
126
+ () => ({
127
+ onElement,
128
+ ...customDomVisitors,
129
+ }),
130
+ [customDomVisitors],
131
+ );
132
+
133
+ const filteredTagStyles = useMemo(
134
+ () => _.omitBy(tagStyles, tagStyle => !tagStyle),
135
+ [tagStyles],
136
+ );
137
+
138
+ // We have to be really careful with props passed to SimpleHtml, as they'll cause unnecessary re-renders.
139
+ // Component is meant to be static (in almost all scenarios) - it should only render with initially given props.
140
+ // Notice that props below are memoized to only be calculated on mount, because lots of these props non-primitive
141
+ // (reference types), and they'll cause re-renders.
142
+ const htmlProps = useMemo(
143
+ () => ({
89
144
  source: { html: body },
90
145
  computeEmbeddedMaxWidth: () => maxWidth,
91
146
  contentWidth: maxWidth,
92
- tagsStyles: _.omitBy(tagStyles, tagStyle => !tagStyle),
93
- systemFonts: [...defaultSystemFonts, style.baseFont.fontFamily],
147
+ tagsStyles: filteredTagStyles,
148
+ systemFonts,
94
149
  baseStyle: style.baseFont,
95
- ignoredStyles: [
96
- 'fontFamily',
97
- 'letterSpacing',
98
- 'transform',
99
- ...customIgnoredStyles,
100
- ],
150
+ ignoredStyles,
101
151
  renderers: customRenderers,
102
- renderersProps: {
103
- table: {
104
- cssRules,
105
- },
106
- a: { onPress: this.onLinkPress },
107
- iframe: {
108
- webViewProps: {
109
- renderToHardwareTextureAndroid: true,
110
- },
111
- },
112
- ...customRendererProps,
113
- },
114
- customHTMLElementModels: {
115
- table: tableModel,
116
- iframe: iframeModel,
117
- video: videoModel,
118
- ...customHtmlElementModels,
119
- },
152
+ renderersProps,
153
+ customHTMLElementModels,
120
154
  WebView,
121
- domVisitors: { onElement, ...customDomVisitors },
122
- };
123
-
124
- return (
125
- <View style={style.container}>
126
- <Html {...htmlProps} {...otherProps} />
127
- </View>
128
- );
129
- }
130
- }
131
-
132
- SimpleHtml.propTypes = {
133
- style: PropTypes.object.isRequired,
134
- attachments: PropTypes.array,
135
- body: PropTypes.string,
136
- customCustomRenderers: PropTypes.object,
137
- customDomVisitors: PropTypes.object,
138
- customHandleLinkPress: PropTypes.func,
139
- customHtmlElementModels: PropTypes.object,
140
- customIgnoredStyles: PropTypes.arrayOf(PropTypes.string),
141
- customRendererProps: PropTypes.object,
142
- customTagStyles: PropTypes.object,
143
- domVisitors: PropTypes.object,
144
- unsupportedVideoFormatMessage: PropTypes.string,
145
- };
155
+ domVisitors,
156
+ }),
157
+ // eslint-disable-next-line react-hooks/exhaustive-deps
158
+ [],
159
+ );
146
160
 
147
- SimpleHtml.defaultProps = {
148
- attachments: undefined,
149
- body: undefined,
150
- customHandleLinkPress: undefined,
151
- customTagStyles: {},
152
- unsupportedVideoFormatMessage: undefined,
153
- domVisitors: { onElement },
154
- customDomVisitors: {},
155
- customCustomRenderers: {},
156
- customHtmlElementModels: {},
157
- customIgnoredStyles: [],
158
- customRendererProps: {},
161
+ return (
162
+ <View style={style.container}>
163
+ <Html {...htmlProps} {...otherProps} />
164
+ </View>
165
+ );
159
166
  };
160
167
 
161
- export default connectStyle('shoutem.ui.SimpleHtml')(SimpleHtml);
168
+ export default React.memo(connectStyle('shoutem.ui.SimpleHtml')(SimpleHtml));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shoutem/ui",
3
- "version": "9.0.0-rc.3",
3
+ "version": "9.0.0-rc.5",
4
4
  "description": "Styleable set of components for React Native applications",
5
5
  "scripts": {
6
6
  "lint": "eslint .",
@@ -17,7 +17,7 @@
17
17
  "@react-native-community/datetimepicker": "6.2.0",
18
18
  "@shoutem/animation": "1.0.0-rc.1",
19
19
  "@shoutem/eslint-config-react": "~1.0.6",
20
- "@shoutem/theme": "1.0.0-rc.2",
20
+ "@shoutem/theme": "1.0.0-rc.4",
21
21
  "auto-bind": "4.0.0",
22
22
  "babel-plugin-transform-decorators-legacy": "1.3.5",
23
23
  "buffer": "5.6.0",
@@ -41,7 +41,7 @@
41
41
  "react-native-toast-message": "2.1.5",
42
42
  "react-native-vimeo-iframe": "^1.2.1",
43
43
  "react-native-web-refresh-control": "1.1.2",
44
- "react-native-webview": "11.23.0",
44
+ "react-native-webview": "13.16.0",
45
45
  "react-native-youtube-iframe": "2.2.2",
46
46
  "react-native-actions-sheet": "0.9.3",
47
47
  "stream": "0.0.2",