@mpxjs/webpack-plugin 2.9.56 → 2.9.58

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.
Files changed (38) hide show
  1. package/lib/platform/style/wx/index.js +29 -9
  2. package/lib/platform/template/wx/component-config/web-view.js +8 -0
  3. package/lib/react/index.js +0 -1
  4. package/lib/react/processStyles.js +14 -3
  5. package/lib/react/style-helper.js +6 -10
  6. package/lib/runtime/base.styl +27 -0
  7. package/lib/runtime/components/react/dist/event.config.js +27 -0
  8. package/lib/runtime/components/react/dist/getInnerListeners.js +230 -0
  9. package/lib/runtime/components/react/dist/mpx-button.jsx +270 -0
  10. package/lib/runtime/components/react/dist/mpx-image/index.jsx +229 -0
  11. package/lib/runtime/components/react/dist/mpx-image/svg.jsx +6 -0
  12. package/lib/runtime/components/react/dist/mpx-input.jsx +203 -0
  13. package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +294 -0
  14. package/lib/runtime/components/react/dist/mpx-swiper/carouse.jsx +353 -0
  15. package/lib/runtime/components/react/dist/mpx-swiper/index.jsx +57 -0
  16. package/lib/runtime/components/react/dist/mpx-swiper/type.js +1 -0
  17. package/lib/runtime/components/react/dist/mpx-swiper-item.jsx +25 -0
  18. package/lib/runtime/components/react/dist/mpx-text.jsx +67 -0
  19. package/lib/runtime/components/react/dist/mpx-textarea.jsx +27 -0
  20. package/lib/runtime/components/react/dist/mpx-view.jsx +307 -0
  21. package/lib/runtime/components/react/dist/mpx-web-view.jsx +115 -0
  22. package/lib/runtime/components/react/dist/types/getInnerListeners.js +1 -0
  23. package/lib/runtime/components/react/dist/useNodesRef.js +25 -0
  24. package/lib/runtime/components/react/dist/utils.js +80 -0
  25. package/lib/runtime/components/react/getInnerListeners.ts +1 -1
  26. package/lib/runtime/components/react/mpx-button.tsx +1 -2
  27. package/lib/runtime/components/react/mpx-image/svg.tsx +0 -1
  28. package/lib/runtime/components/react/mpx-web-view.tsx +171 -0
  29. package/lib/runtime/components/react/{getInnerListeners.type.ts → types/getInnerListeners.ts} +2 -2
  30. package/lib/runtime/components/react/types/global.d.ts +15 -0
  31. package/lib/runtime/components/react/utils.ts +1 -1
  32. package/lib/runtime/optionProcessor.js +27 -1
  33. package/lib/runtime/transRpxStyle.js +1 -1
  34. package/lib/style-compiler/plugins/rpx.js +2 -2
  35. package/lib/style-compiler/plugins/vw.js +2 -2
  36. package/lib/template-compiler/compiler.js +104 -42
  37. package/lib/web/processTemplate.js +1 -1
  38. package/package.json +8 -4
@@ -0,0 +1,270 @@
1
+ /**
2
+ * ✔ size
3
+ * ✔ type
4
+ * ✔ plain
5
+ * ✔ disabled
6
+ * ✔ loading
7
+ * ✘ form-type
8
+ * - open-type: Partially. Only support `share`、`getUserInfo`
9
+ * ✔ hover-class: Convert hoverClass to hoverStyle.
10
+ * ✔ hover-style
11
+ * ✘ hover-stop-propagation
12
+ * ✔ hover-start-time
13
+ * ✔ hover-stay-time
14
+ * ✘ lang
15
+ * ✘ session-from
16
+ * ✘ send-message-title
17
+ * ✘ send-message-path
18
+ * ✘ send-message-img
19
+ * ✘ app-parameter
20
+ * ✘ show-message-card
21
+ * ✘ phone-number-no-quota-toast
22
+ * ✘ bindgetuserinfo
23
+ * ✘ bindcontact
24
+ * ✘ createliveactivity
25
+ * ✘ bindgetphonenumber
26
+ * ✘ bindgetphonenumber
27
+ * ✘ bindgetrealtimephonenumber
28
+ * ✘ binderror
29
+ * ✘ bindopensetting
30
+ * ✘ bindlaunchapp
31
+ * ✘ bindlaunchapp
32
+ * ✘ bindchooseavatar
33
+ * ✘ bindchooseavatar
34
+ * ✘ bindagreeprivacyauthorization
35
+ * ✔ bindtap
36
+ */
37
+ import React, { useEffect, useRef, useState, forwardRef, } from 'react';
38
+ import { View, Text, StyleSheet, Animated, Easing, } from 'react-native';
39
+ import { extractTextStyle, isText, every } from './utils';
40
+ import useInnerProps, { getCustomEvent } from './getInnerListeners';
41
+ import useNodesRef from './useNodesRef';
42
+ const LOADING_IMAGE_URI = 'data:image/png;base64,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';
43
+ const TypeColorMap = {
44
+ default: ['#F8F8F8', '#DEDEDE', '35,35,35', '#F7F7F7'],
45
+ primary: ['#1AAD19', '#179B16', '26,173,25', '#9ED99D'],
46
+ warn: ['#E64340', '#CE3C39', '230,67,64', '#EC8B89'],
47
+ };
48
+ const OpenTypeEventsMap = new Map([
49
+ ['share', 'onShareAppMessage'],
50
+ ['getUserInfo', 'onUserInfo'],
51
+ ]);
52
+ const styles = StyleSheet.create({
53
+ button: {
54
+ width: '100%',
55
+ flexDirection: 'row',
56
+ justifyContent: 'center',
57
+ alignItems: 'center',
58
+ height: 46,
59
+ borderRadius: 5,
60
+ backgroundColor: '#F8F8F8',
61
+ marginHorizontal: 'auto' // 按钮默认居中
62
+ },
63
+ buttonMini: {
64
+ height: 30,
65
+ },
66
+ text: {
67
+ fontSize: 18,
68
+ color: '#000000',
69
+ },
70
+ textMini: {
71
+ fontSize: 13,
72
+ },
73
+ loading: {
74
+ width: 20,
75
+ height: 20,
76
+ },
77
+ });
78
+ const getOpenTypeEvent = (openType) => {
79
+ // @ts-ignore
80
+ if (!global?.__mpx?.config?.rnConfig) {
81
+ console.warn('Environment not supported');
82
+ return;
83
+ }
84
+ const eventName = OpenTypeEventsMap.get(openType);
85
+ if (!eventName) {
86
+ console.warn(`open-type not support ${openType}`);
87
+ return;
88
+ }
89
+ // @ts-ignore
90
+ const event = global.__mpx.config.rnConfig?.openTypeHandler?.[eventName];
91
+ if (!event) {
92
+ console.warn(`Unregistered ${eventName} event`);
93
+ return;
94
+ }
95
+ return event;
96
+ };
97
+ const Loading = ({ alone = false }) => {
98
+ const image = useRef(new Animated.Value(0)).current;
99
+ const rotate = image.interpolate({
100
+ inputRange: [0, 1],
101
+ outputRange: ['0deg', '360deg'],
102
+ });
103
+ useEffect(() => {
104
+ const animation = Animated.loop(Animated.timing(image, {
105
+ toValue: 1,
106
+ duration: 1000,
107
+ easing: Easing.linear,
108
+ useNativeDriver: true,
109
+ isInteraction: false,
110
+ }));
111
+ animation.start();
112
+ return () => {
113
+ animation.stop();
114
+ };
115
+ // eslint-disable-next-line react-hooks/exhaustive-deps
116
+ }, []);
117
+ const loadingStyle = {
118
+ ...styles.loading,
119
+ transform: [{ rotate }],
120
+ marginRight: alone ? 0 : 5,
121
+ };
122
+ return <Animated.Image testID="loading" style={loadingStyle} source={{ uri: LOADING_IMAGE_URI }}/>;
123
+ };
124
+ const Button = forwardRef((props, ref) => {
125
+ const { size = 'default', type = 'default', plain = false, disabled = false, loading = false, 'hover-class': hoverClass, 'hover-style': hoverStyle = [], 'hover-start-time': hoverStartTime = 20, 'hover-stay-time': hoverStayTime = 70, 'open-type': openType, 'enable-offset': enableOffset, style = [], children, bindgetuserinfo, bindtap, catchtap, bindtouchstart, bindtouchend, } = props;
126
+ const refs = useRef({
127
+ hoverStartTimer: undefined,
128
+ hoverStayTimer: undefined,
129
+ });
130
+ const layoutRef = useRef({});
131
+ const [isHover, setIsHover] = useState(false);
132
+ const isMiniSize = size === 'mini';
133
+ const applyHoverEffect = isHover && hoverClass !== 'none';
134
+ const inheritTextStyle = extractTextStyle(style);
135
+ const textHoverStyle = extractTextStyle(hoverStyle);
136
+ const [color, hoverColor, plainColor, disabledColor] = TypeColorMap[type];
137
+ const normalBackgroundColor = disabled ? disabledColor : applyHoverEffect || loading ? hoverColor : color;
138
+ const plainBorderColor = disabled
139
+ ? 'rgba(0, 0, 0, .2)'
140
+ : applyHoverEffect
141
+ ? `rgba(${plainColor},.6)`
142
+ : `rgb(${plainColor})`;
143
+ const normalBorderColor = type === 'default' ? 'rgba(0, 0, 0, .2)' : normalBackgroundColor;
144
+ const plainTextColor = disabled
145
+ ? 'rgba(0, 0, 0, .2)'
146
+ : applyHoverEffect
147
+ ? `rgba(${plainColor}, .6)`
148
+ : `rgb(${plainColor})`;
149
+ const normalTextColor = type === 'default'
150
+ ? `rgba(0, 0, 0, ${disabled ? 0.3 : applyHoverEffect || loading ? 0.6 : 1})`
151
+ : `rgba(255 ,255 ,255 , ${disabled || applyHoverEffect || loading ? 0.6 : 1})`;
152
+ const viewStyle = {
153
+ borderWidth: 1,
154
+ borderStyle: 'solid',
155
+ borderColor: plain ? plainBorderColor : normalBorderColor,
156
+ backgroundColor: plain ? 'transparent' : normalBackgroundColor,
157
+ };
158
+ const textStyle = {
159
+ color: plain ? plainTextColor : normalTextColor,
160
+ ...inheritTextStyle
161
+ };
162
+ const defaultViewStyle = [
163
+ styles.button,
164
+ isMiniSize && styles.buttonMini || {},
165
+ viewStyle,
166
+ ];
167
+ const defaultTextStyle = [
168
+ styles.text, isMiniSize && styles.textMini, textStyle
169
+ ];
170
+ const handleOpenTypeEvent = (evt) => {
171
+ if (!openType)
172
+ return;
173
+ const handleEvent = getOpenTypeEvent(openType);
174
+ if (openType === 'share') {
175
+ handleEvent && handleEvent({
176
+ from: 'button',
177
+ target: getCustomEvent('tap', evt, { layoutRef }, props).target,
178
+ });
179
+ }
180
+ if (openType === 'getUserInfo') {
181
+ const userInfo = handleEvent && handleEvent();
182
+ if (typeof userInfo === 'object') {
183
+ bindgetuserinfo && bindgetuserinfo(userInfo);
184
+ }
185
+ }
186
+ };
187
+ const setStayTimer = () => {
188
+ clearTimeout(refs.current.hoverStayTimer);
189
+ refs.current.hoverStayTimer = setTimeout(() => {
190
+ setIsHover(false);
191
+ clearTimeout(refs.current.hoverStayTimer);
192
+ }, hoverStayTime);
193
+ };
194
+ const setStartTimer = () => {
195
+ clearTimeout(refs.current.hoverStartTimer);
196
+ refs.current.hoverStartTimer = setTimeout(() => {
197
+ setIsHover(true);
198
+ clearTimeout(refs.current.hoverStartTimer);
199
+ }, hoverStartTime);
200
+ };
201
+ const onTouchStart = (evt) => {
202
+ bindtouchstart && bindtouchstart(evt);
203
+ if (disabled)
204
+ return;
205
+ setStartTimer();
206
+ };
207
+ const onTouchEnd = (evt) => {
208
+ bindtouchend && bindtouchend(evt);
209
+ if (disabled)
210
+ return;
211
+ setStayTimer();
212
+ };
213
+ const onTap = (evt) => {
214
+ if (disabled)
215
+ return;
216
+ bindtap && bindtap(getCustomEvent('tap', evt, { layoutRef }, props));
217
+ handleOpenTypeEvent(evt);
218
+ };
219
+ const catchTap = (evt) => {
220
+ if (disabled)
221
+ return;
222
+ catchtap && catchtap(getCustomEvent('tap', evt, { layoutRef }, props));
223
+ };
224
+ function wrapChildren(children, textStyle) {
225
+ if (every(children, (child) => isText(child))) {
226
+ children = [<Text key='buttonTextWrap' style={textStyle}>{children}</Text>];
227
+ }
228
+ else {
229
+ if (textStyle)
230
+ console.warn('Text style will be ignored unless every child of the Button is Text node!');
231
+ }
232
+ return children;
233
+ }
234
+ const { nodeRef } = useNodesRef(props, ref, {
235
+ defaultStyle: StyleSheet.flatten([
236
+ ...defaultViewStyle,
237
+ ...defaultTextStyle,
238
+ ])
239
+ });
240
+ const onLayout = () => {
241
+ nodeRef.current?.measure((x, y, width, height, offsetLeft, offsetTop) => {
242
+ layoutRef.current = { x, y, width, height, offsetLeft, offsetTop };
243
+ });
244
+ };
245
+ const innerProps = useInnerProps(props, {
246
+ ref: nodeRef,
247
+ bindtouchstart: onTouchStart,
248
+ bindtouchend: onTouchEnd,
249
+ bindtap: onTap,
250
+ catchtap: catchTap,
251
+ ...(enableOffset ? { onLayout } : {}),
252
+ }, [
253
+ 'enable-offset'
254
+ ], {
255
+ layoutRef
256
+ });
257
+ return (<View {...innerProps} style={[
258
+ ...defaultViewStyle,
259
+ style,
260
+ applyHoverEffect && hoverStyle,
261
+ ]}>
262
+ {loading && <Loading alone={!children}/>}
263
+ {wrapChildren(children, [
264
+ ...defaultTextStyle,
265
+ applyHoverEffect && textHoverStyle,
266
+ ])}
267
+ </View>);
268
+ });
269
+ Button.displayName = 'mpx-button';
270
+ export default Button;
@@ -0,0 +1,229 @@
1
+ /**
2
+ * ✔ src
3
+ * - mode: Partially, Only SVG format do not support
4
+ * ✘ show-menu-by-longpress
5
+ * ✔ binderror
6
+ * ✔ bindload
7
+ * ✘ fade-in
8
+ * ✔ webp
9
+ * ✘ lazy-load
10
+ * ✔ bindtap
11
+ * ✔ DEFAULT_SIZE
12
+ */
13
+ import React, { useEffect, useMemo, useState, forwardRef, useRef, } from 'react';
14
+ import { Image as RNImage, View, StyleSheet, } from 'react-native';
15
+ import useInnerProps, { getCustomEvent } from '../getInnerListeners';
16
+ import useNodesRef from '../useNodesRef';
17
+ const DEFAULT_IMAGE_WIDTH = 320;
18
+ const DEFAULT_IMAGE_HEIGHT = 240;
19
+ // const REMOTE_SVG_REGEXP = /https?:\/\/.*\.(?:svg)/i
20
+ // const styls = StyleSheet.create({
21
+ // suspense: {
22
+ // display: 'flex',
23
+ // justifyContent: 'center',
24
+ // alignItems: 'center',
25
+ // width: '100%',
26
+ // height: '100%',
27
+ // },
28
+ // })
29
+ const cropMode = [
30
+ 'top',
31
+ 'bottom',
32
+ 'center',
33
+ 'right',
34
+ 'left',
35
+ 'top left',
36
+ 'top right',
37
+ 'bottom left',
38
+ 'bottom right',
39
+ ];
40
+ const ModeMap = new Map([
41
+ ['scaleToFill', 'stretch'],
42
+ ['aspectFit', 'contain'],
43
+ ['aspectFill', 'cover'],
44
+ ['widthFix', 'stretch'],
45
+ ['heightFix', 'stretch'],
46
+ ...cropMode.map(mode => [mode, 'stretch']),
47
+ ]);
48
+ const isNumber = (value) => typeof value === 'number';
49
+ const relativeCenteredSize = (viewSize, imageSize) => (viewSize - imageSize) / 2;
50
+ // const Svg = lazy(() => import('./svg'))
51
+ // const Fallback = (
52
+ // <View style={styls.suspense}>
53
+ // <Text>loading ...</Text>
54
+ // </View>
55
+ // )
56
+ const Image = forwardRef((props, ref) => {
57
+ const { src = '', mode = 'scaleToFill',
58
+ // svg = false,
59
+ style = [], 'enable-offset': enableOffset, bindload, binderror } = props;
60
+ const { width = DEFAULT_IMAGE_WIDTH, height = DEFAULT_IMAGE_HEIGHT } = StyleSheet.flatten(style);
61
+ const { nodeRef } = useNodesRef(props, ref, {
62
+ defaultStyle: {
63
+ width: DEFAULT_IMAGE_WIDTH,
64
+ height: DEFAULT_IMAGE_HEIGHT
65
+ }
66
+ });
67
+ const layoutRef = useRef({});
68
+ const preSrc = useRef();
69
+ const resizeMode = ModeMap.get(mode) || 'stretch';
70
+ const isWidthFixMode = mode === 'widthFix';
71
+ const isHeightFixMode = mode === 'heightFix';
72
+ const isCropMode = cropMode.includes(mode);
73
+ const source = typeof src === 'string' ? { uri: src } : src;
74
+ const [viewWidth, setViewWidth] = useState(isNumber(width) ? width : 0);
75
+ const [viewHeight, setViewHeight] = useState(isNumber(height) ? height : 0);
76
+ const [imageWidth, setImageWidth] = useState(0);
77
+ const [imageHeight, setImageHeight] = useState(0);
78
+ const [ratio, setRatio] = useState(0);
79
+ const [loaded, setLoaded] = useState(false);
80
+ const fixedHeight = useMemo(() => {
81
+ const fixed = viewWidth * ratio;
82
+ return !fixed ? viewHeight : fixed;
83
+ }, [ratio, viewWidth, viewHeight]);
84
+ const fixedWidth = useMemo(() => {
85
+ if (!ratio)
86
+ return viewWidth;
87
+ const fixed = viewHeight / ratio;
88
+ return !fixed ? viewWidth : fixed;
89
+ }, [ratio, viewWidth, viewHeight]);
90
+ const cropModeStyle = useMemo(() => {
91
+ switch (mode) {
92
+ case 'top':
93
+ return { top: 0, left: relativeCenteredSize(viewWidth, imageWidth) };
94
+ case 'bottom':
95
+ return { top: 'auto', bottom: 0, left: relativeCenteredSize(viewWidth, imageWidth) };
96
+ case 'center':
97
+ return { top: relativeCenteredSize(viewHeight, imageHeight), left: relativeCenteredSize(viewWidth, imageWidth) };
98
+ case 'left':
99
+ return { top: relativeCenteredSize(viewHeight, imageHeight), left: 0 };
100
+ case 'right':
101
+ return { top: relativeCenteredSize(viewHeight, imageHeight), left: 'auto', right: 0 };
102
+ case 'top left':
103
+ return { top: 0, left: 0 };
104
+ case 'top right':
105
+ return { top: 0, left: 'auto', right: 0 };
106
+ case 'bottom left':
107
+ return { top: 'auto', bottom: 0, left: 0 };
108
+ case 'bottom right':
109
+ return { top: 'auto', bottom: 0, left: 'auto', right: 0 };
110
+ default:
111
+ return {};
112
+ }
113
+ }, [mode, viewWidth, viewHeight, imageWidth, imageHeight]);
114
+ const onImageLoad = (evt) => {
115
+ if (!bindload)
116
+ return;
117
+ if (typeof src === 'string') {
118
+ RNImage.getSize(src, (width, height) => {
119
+ bindload(getCustomEvent('load', evt, {
120
+ detail: { width, height },
121
+ layoutRef
122
+ }, props));
123
+ });
124
+ }
125
+ else {
126
+ const { width = 0, height = 0 } = RNImage.resolveAssetSource(src) || {};
127
+ bindload(getCustomEvent('load', evt, {
128
+ detail: { width, height },
129
+ layoutRef
130
+ }, props));
131
+ }
132
+ };
133
+ const onImageError = (evt) => {
134
+ binderror &&
135
+ binderror(getCustomEvent('error', evt, {
136
+ detail: { errMsg: evt.nativeEvent.error },
137
+ layoutRef
138
+ }, props));
139
+ };
140
+ const onViewLayout = ({ nativeEvent: { layout: { width, height }, }, }) => {
141
+ setViewWidth(width);
142
+ setViewHeight(height);
143
+ };
144
+ const onImageLayout = () => {
145
+ nodeRef.current?.measure((x, y, width, height, offsetLeft, offsetTop) => {
146
+ layoutRef.current = { x, y, width, height, offsetLeft, offsetTop };
147
+ });
148
+ };
149
+ useEffect(() => {
150
+ if (!isWidthFixMode && !isHeightFixMode && !isCropMode) {
151
+ setLoaded(true);
152
+ return;
153
+ }
154
+ const changed = preSrc.current !== src;
155
+ preSrc.current = src;
156
+ changed && setLoaded(false);
157
+ if (typeof src === 'string') {
158
+ RNImage.getSize(src, (width, height) => {
159
+ if (isWidthFixMode || isHeightFixMode) {
160
+ setRatio(width === 0 ? 0 : height / width);
161
+ }
162
+ if (isCropMode) {
163
+ setImageWidth(width);
164
+ setImageHeight(height);
165
+ }
166
+ changed && setLoaded(true);
167
+ });
168
+ }
169
+ else {
170
+ const { width = 0, height = 0 } = RNImage.resolveAssetSource(src) || {};
171
+ if (isWidthFixMode || isHeightFixMode) {
172
+ setRatio(width === 0 ? 0 : height / width);
173
+ }
174
+ if (isCropMode) {
175
+ setImageWidth(width);
176
+ setImageHeight(height);
177
+ }
178
+ changed && setLoaded(true);
179
+ }
180
+ }, [isWidthFixMode, isHeightFixMode, isCropMode, src]);
181
+ const innerProps = useInnerProps(props, {
182
+ ref: nodeRef,
183
+ ...(enableOffset ? { onLayout: onImageLayout } : {})
184
+ }, [
185
+ 'enable-offset'
186
+ ], {
187
+ layoutRef
188
+ });
189
+ // if (typeof src === 'string' && REMOTE_SVG_REGEXP.test(src)) {
190
+ // return (
191
+ // <Suspense fallback={Fallback} {...innerProps}>
192
+ // <View {...innerProps}>
193
+ // <Svg src={src} style={style} width={width as SvgNumberProp} height={height as SvgNumberProp} />
194
+ // </View>
195
+ // </Suspense>
196
+ // )
197
+ // }
198
+ // if (svg) {
199
+ // return (
200
+ // <Suspense fallback={Fallback}>
201
+ // <View {...innerProps}>
202
+ // <Svg local src={src} style={style} width={width as SvgNumberProp} height={height as SvgNumberProp} />
203
+ // </View>
204
+ // </Suspense>
205
+ // )
206
+ // }
207
+ return (<View style={[
208
+ { width, height },
209
+ style,
210
+ {
211
+ ...(isHeightFixMode && { width: fixedWidth }),
212
+ ...(isWidthFixMode && { height: fixedHeight }),
213
+ },
214
+ { overflow: 'hidden' },
215
+ ]} onLayout={onViewLayout}>
216
+ {loaded && <RNImage {...innerProps} source={source} resizeMode={resizeMode} onLoad={onImageLoad} onError={onImageError} style={[
217
+ StyleSheet.absoluteFill,
218
+ {
219
+ width: !isCropMode ? '100%' : imageWidth,
220
+ height: !isCropMode ? '100%' : imageHeight,
221
+ },
222
+ {
223
+ ...(isCropMode && cropModeStyle),
224
+ },
225
+ ]}/>}
226
+ </View>);
227
+ });
228
+ Image.displayName = 'mpx-image';
229
+ export default Image;
@@ -0,0 +1,6 @@
1
+ import React from 'react';
2
+ import { SvgCssUri, WithLocalSvg } from 'react-native-svg/css';
3
+ const Svg = ({ local = false, src, style, width, height }) => {
4
+ return local ? (<WithLocalSvg style={style} asset={src} width={width} height={height}/>) : (<SvgCssUri style={style} uri={src} width={width} height={height}/>);
5
+ };
6
+ export default Svg;