@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.
- package/html/components/SimpleHtml.js +110 -103
- package/package.json +3 -3
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import 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
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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
|
-
|
|
28
|
-
|
|
44
|
+
const maxWidth = useMemo(() => {
|
|
45
|
+
return resolveMaxWidth(style);
|
|
46
|
+
}, [style]);
|
|
29
47
|
|
|
30
|
-
|
|
31
|
-
|
|
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
|
-
|
|
63
|
+
return `${cssStyle}${tableCssStyle}`;
|
|
64
|
+
}, [style]);
|
|
67
65
|
|
|
68
|
-
|
|
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
|
-
|
|
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:
|
|
93
|
-
systemFonts
|
|
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
|
-
|
|
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
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
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
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
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
|
+
"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.
|
|
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": "
|
|
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",
|