@shoutem/ui 9.0.0-rc.4 → 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,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.4",
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.3",
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",