@mpxjs/webpack-plugin 2.8.25-alpha.21 → 2.8.25-alpha.22

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 (72) hide show
  1. package/lib/runtime/components/react/dist/KeyboardAvoidingView.jsx +89 -0
  2. package/lib/runtime/components/react/dist/context.js +14 -0
  3. package/lib/runtime/components/react/dist/event.config.js +27 -0
  4. package/lib/runtime/components/react/dist/getInnerListeners.js +262 -0
  5. package/lib/runtime/components/react/dist/mpx-button.jsx +271 -0
  6. package/lib/runtime/components/react/dist/mpx-canvas/Bus.js +60 -0
  7. package/lib/runtime/components/react/dist/mpx-canvas/CanvasGradient.js +15 -0
  8. package/lib/runtime/components/react/dist/mpx-canvas/CanvasRenderingContext2D.js +84 -0
  9. package/lib/runtime/components/react/dist/mpx-canvas/Image.js +87 -0
  10. package/lib/runtime/components/react/dist/mpx-canvas/ImageData.js +15 -0
  11. package/lib/runtime/components/react/dist/mpx-canvas/constructorsRegistry.js +28 -0
  12. package/lib/runtime/components/react/dist/mpx-canvas/html.js +341 -0
  13. package/lib/runtime/components/react/dist/mpx-canvas/index.jsx +236 -0
  14. package/lib/runtime/components/react/dist/mpx-canvas/utils.jsx +89 -0
  15. package/lib/runtime/components/react/dist/mpx-checkbox-group.jsx +90 -0
  16. package/lib/runtime/components/react/dist/mpx-checkbox.jsx +131 -0
  17. package/lib/runtime/components/react/dist/mpx-form.jsx +68 -0
  18. package/lib/runtime/components/react/dist/mpx-icon/icons/cancel.png +0 -0
  19. package/lib/runtime/components/react/dist/mpx-icon/icons/clear.png +0 -0
  20. package/lib/runtime/components/react/dist/mpx-icon/icons/download.png +0 -0
  21. package/lib/runtime/components/react/dist/mpx-icon/icons/info.png +0 -0
  22. package/lib/runtime/components/react/dist/mpx-icon/icons/search.png +0 -0
  23. package/lib/runtime/components/react/dist/mpx-icon/icons/success.png +0 -0
  24. package/lib/runtime/components/react/dist/mpx-icon/icons/success_no_circle.png +0 -0
  25. package/lib/runtime/components/react/dist/mpx-icon/icons/waiting.png +0 -0
  26. package/lib/runtime/components/react/dist/mpx-icon/icons/warn.png +0 -0
  27. package/lib/runtime/components/react/dist/mpx-icon/index.jsx +50 -0
  28. package/lib/runtime/components/react/dist/mpx-image.jsx +292 -0
  29. package/lib/runtime/components/react/dist/mpx-input.jsx +292 -0
  30. package/lib/runtime/components/react/dist/mpx-label.jsx +52 -0
  31. package/lib/runtime/components/react/dist/mpx-movable-area.jsx +32 -0
  32. package/lib/runtime/components/react/dist/mpx-movable-view.jsx +468 -0
  33. package/lib/runtime/components/react/dist/mpx-navigator.jsx +33 -0
  34. package/lib/runtime/components/react/dist/mpx-picker/date.jsx +74 -0
  35. package/lib/runtime/components/react/dist/mpx-picker/index.jsx +141 -0
  36. package/lib/runtime/components/react/dist/mpx-picker/multiSelector.jsx +147 -0
  37. package/lib/runtime/components/react/dist/mpx-picker/region.jsx +99 -0
  38. package/lib/runtime/components/react/dist/mpx-picker/regionData.js +6099 -0
  39. package/lib/runtime/components/react/dist/mpx-picker/selector.jsx +81 -0
  40. package/lib/runtime/components/react/dist/mpx-picker/time.jsx +242 -0
  41. package/lib/runtime/components/react/dist/mpx-picker/type.js +1 -0
  42. package/lib/runtime/components/react/dist/mpx-picker-view-column-item.jsx +35 -0
  43. package/lib/runtime/components/react/dist/mpx-picker-view-column.jsx +193 -0
  44. package/lib/runtime/components/react/dist/mpx-picker-view.jsx +125 -0
  45. package/lib/runtime/components/react/dist/mpx-portal/index.jsx +30 -0
  46. package/lib/runtime/components/react/dist/mpx-portal/portal-host.jsx +112 -0
  47. package/lib/runtime/components/react/dist/mpx-portal/portal-manager.jsx +41 -0
  48. package/lib/runtime/components/react/dist/mpx-radio-group.jsx +86 -0
  49. package/lib/runtime/components/react/dist/mpx-radio.jsx +140 -0
  50. package/lib/runtime/components/react/dist/mpx-rich-text/html.js +39 -0
  51. package/lib/runtime/components/react/dist/mpx-rich-text/index.jsx +62 -0
  52. package/lib/runtime/components/react/dist/mpx-root-portal.jsx +17 -0
  53. package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +372 -0
  54. package/lib/runtime/components/react/dist/mpx-simple-text.jsx +11 -0
  55. package/lib/runtime/components/react/dist/mpx-swiper-item.jsx +59 -0
  56. package/lib/runtime/components/react/dist/mpx-swiper.jsx +671 -0
  57. package/lib/runtime/components/react/dist/mpx-switch.jsx +97 -0
  58. package/lib/runtime/components/react/dist/mpx-text.jsx +41 -0
  59. package/lib/runtime/components/react/dist/mpx-textarea.jsx +40 -0
  60. package/lib/runtime/components/react/dist/mpx-video.jsx +248 -0
  61. package/lib/runtime/components/react/dist/mpx-view.jsx +611 -0
  62. package/lib/runtime/components/react/dist/mpx-web-view.jsx +289 -0
  63. package/lib/runtime/components/react/dist/parser.js +218 -0
  64. package/lib/runtime/components/react/dist/pickerFaces.js +76 -0
  65. package/lib/runtime/components/react/dist/pickerVIewContext.js +14 -0
  66. package/lib/runtime/components/react/dist/pickerViewIndicator.jsx +23 -0
  67. package/lib/runtime/components/react/dist/pickerViewMask.jsx +18 -0
  68. package/lib/runtime/components/react/dist/useAnimationHooks.js +346 -0
  69. package/lib/runtime/components/react/dist/useNodesRef.js +16 -0
  70. package/lib/runtime/components/react/dist/utils.jsx +599 -0
  71. package/package.json +6 -3
  72. package/LICENSE +0 -433
@@ -0,0 +1,30 @@
1
+ import { useContext, useEffect, useRef } from 'react';
2
+ import { PortalContext, RouteContext, VarContext } from '../context';
3
+ import PortalHost, { portal } from './portal-host';
4
+ const Portal = ({ children }) => {
5
+ const manager = useContext(PortalContext);
6
+ const keyRef = useRef(null);
7
+ const { pageId } = useContext(RouteContext) || {};
8
+ const varContext = useContext(VarContext);
9
+ if (varContext) {
10
+ children = (<VarContext.Provider value={varContext} key='varContextWrap'>{children}</VarContext.Provider>);
11
+ }
12
+ useEffect(() => {
13
+ manager.update(keyRef.current, children);
14
+ }, [children]);
15
+ useEffect(() => {
16
+ if (!manager) {
17
+ throw new Error('Looks like you forgot to wrap your root component with `PortalHost` component from `@mpxjs/webpack-plugin/lib/runtime/components/react/dist/mpx-portal/index`.\n\n');
18
+ }
19
+ keyRef.current = manager.mount(children, null, pageId);
20
+ return () => {
21
+ manager.unmount(keyRef.current);
22
+ };
23
+ }, []);
24
+ return null;
25
+ };
26
+ Portal.Host = PortalHost;
27
+ Portal.add = portal.add;
28
+ Portal.remove = portal.remove;
29
+ Portal.update = portal.update;
30
+ export default Portal;
@@ -0,0 +1,112 @@
1
+ import { useEffect, useRef, useMemo, useContext } from 'react';
2
+ import { View, DeviceEventEmitter, NativeEventEmitter, StyleSheet } from 'react-native';
3
+ import PortalManager from './portal-manager';
4
+ import { PortalContext, RouteContext } from '../context';
5
+ // events
6
+ const addType = 'MPX_RN_ADD_PORTAL';
7
+ const removeType = 'MPX_RN_REMOVE_PORTAL';
8
+ const updateType = 'MPX_RN_UPDATE_PORTAL';
9
+ // fix react native web does not support DeviceEventEmitter
10
+ const TopViewEventEmitter = DeviceEventEmitter || new NativeEventEmitter();
11
+ const styles = StyleSheet.create({
12
+ container: {
13
+ flex: 1
14
+ }
15
+ });
16
+ class PortalGuard {
17
+ nextKey = 10000;
18
+ add = (e, id) => {
19
+ const key = this.nextKey++;
20
+ TopViewEventEmitter.emit(addType, e, key, id);
21
+ return key;
22
+ };
23
+ remove = (key) => {
24
+ TopViewEventEmitter.emit(removeType, key);
25
+ };
26
+ update = (key, e) => {
27
+ TopViewEventEmitter.emit(updateType, key, e);
28
+ };
29
+ }
30
+ /**
31
+ * portal
32
+ */
33
+ export const portal = new PortalGuard();
34
+ const PortalHost = ({ children }) => {
35
+ const _nextKey = useRef(0);
36
+ const manager = useRef(null);
37
+ const queue = useRef([]);
38
+ const { pageId } = useContext(RouteContext) || {};
39
+ const mount = (children, _key, id) => {
40
+ if (id !== pageId)
41
+ return;
42
+ const key = _key || _nextKey.current++;
43
+ if (manager.current) {
44
+ manager.current.mount(key, children);
45
+ }
46
+ else {
47
+ queue.current.push({ type: 'mount', key, children });
48
+ }
49
+ return key;
50
+ };
51
+ const unmount = (key) => {
52
+ if (manager.current) {
53
+ manager.current.unmount(key);
54
+ }
55
+ else {
56
+ queue.current.push({ type: 'unmount', key, children });
57
+ }
58
+ };
59
+ const update = (key, children) => {
60
+ if (manager.current) {
61
+ manager.current.update(key, children);
62
+ }
63
+ else {
64
+ const operation = { type: 'mount', key, children };
65
+ const index = queue.current.findIndex((q) => q.type === 'mount' && q.key === key);
66
+ if (index > -1) {
67
+ queue.current[index] = operation;
68
+ }
69
+ else {
70
+ queue.current.push(operation);
71
+ }
72
+ }
73
+ };
74
+ const subScriptions = useMemo(() => {
75
+ return [
76
+ TopViewEventEmitter.addListener(addType, mount),
77
+ TopViewEventEmitter.addListener(removeType, unmount),
78
+ TopViewEventEmitter.addListener(updateType, update)
79
+ ];
80
+ }, []);
81
+ useEffect(() => {
82
+ while (queue.current.length && manager.current) {
83
+ const operation = queue.current.shift();
84
+ if (!operation)
85
+ return;
86
+ switch (operation.type) {
87
+ case 'mount':
88
+ manager.current.mount(operation.key, operation.children);
89
+ break;
90
+ case 'unmount':
91
+ manager.current.unmount(operation.key);
92
+ break;
93
+ }
94
+ }
95
+ return () => {
96
+ subScriptions.forEach((subScription) => {
97
+ subScription.remove();
98
+ });
99
+ };
100
+ }, []);
101
+ return (<PortalContext.Provider value={{
102
+ mount,
103
+ update,
104
+ unmount
105
+ }}>
106
+ <View style={styles.container} collapsable={false}>
107
+ {children}
108
+ </View>
109
+ <PortalManager ref={manager}/>
110
+ </PortalContext.Provider>);
111
+ };
112
+ export default PortalHost;
@@ -0,0 +1,41 @@
1
+ import { useState, useCallback, forwardRef, useImperativeHandle } from 'react';
2
+ import { View, StyleSheet } from 'react-native';
3
+ import { extendObject } from '../utils';
4
+ const _PortalManager = forwardRef((props, ref) => {
5
+ const [state, setState] = useState({
6
+ portals: []
7
+ });
8
+ const mount = useCallback((key, children) => {
9
+ setState((prevState) => ({
10
+ portals: [...prevState.portals, { key, children }]
11
+ }));
12
+ }, [state]);
13
+ const update = useCallback((key, children) => {
14
+ setState((prevState) => ({
15
+ portals: prevState.portals.map((item) => {
16
+ if (item.key === key) {
17
+ return extendObject({}, item, { children });
18
+ }
19
+ return item;
20
+ })
21
+ }));
22
+ }, [state]);
23
+ const unmount = useCallback((key) => {
24
+ setState((prevState) => ({
25
+ portals: prevState.portals.filter((item) => item.key !== key)
26
+ }));
27
+ }, []);
28
+ useImperativeHandle(ref, () => ({
29
+ mount,
30
+ update,
31
+ unmount,
32
+ portals: state.portals
33
+ }));
34
+ return (<>
35
+ {state.portals.map(({ key, children }, i) => (<View key={key} collapsable={false} // Need collapsable=false here to clip the elevations
36
+ style={[StyleSheet.absoluteFill, { zIndex: 1000 + i, pointerEvents: 'box-none' }]}>
37
+ {children}
38
+ </View>))}
39
+ </>);
40
+ });
41
+ export default _PortalManager;
@@ -0,0 +1,86 @@
1
+ /**
2
+ * ✔ bindchange
3
+ */
4
+ import { useRef, forwardRef, useContext, useMemo, useEffect, createElement } from 'react';
5
+ import { View } from 'react-native';
6
+ import { warn } from '@mpxjs/utils';
7
+ import { FormContext, RadioGroupContext } from './context';
8
+ import useInnerProps, { getCustomEvent } from './getInnerListeners';
9
+ import useNodesRef from './useNodesRef';
10
+ import { useLayout, useTransformStyle, wrapChildren, extendObject } from './utils';
11
+ const radioGroup = forwardRef((props, ref) => {
12
+ const { style = {}, 'enable-var': enableVar, 'external-var-context': externalVarContext, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight } = props;
13
+ const propsRef = useRef({});
14
+ propsRef.current = props;
15
+ const formContext = useContext(FormContext);
16
+ let formValuesMap;
17
+ if (formContext) {
18
+ formValuesMap = formContext.formValuesMap;
19
+ }
20
+ const groupValue = useRef({}).current;
21
+ const defaultStyle = {
22
+ flexDirection: 'row',
23
+ flexWrap: 'wrap'
24
+ };
25
+ const styleObj = extendObject({}, defaultStyle, style);
26
+ const { hasSelfPercent, normalStyle, hasVarDec, varContextRef, setWidth, setHeight } = useTransformStyle(styleObj, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
27
+ const nodeRef = useRef(null);
28
+ useNodesRef(props, ref, nodeRef, { style: normalStyle });
29
+ const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef });
30
+ const getValue = () => {
31
+ for (const key in groupValue) {
32
+ if (groupValue[key].checked) {
33
+ return key;
34
+ }
35
+ }
36
+ };
37
+ const resetValue = () => {
38
+ Object.keys(groupValue).forEach((key) => {
39
+ groupValue[key].checked = false;
40
+ groupValue[key].setValue(false);
41
+ });
42
+ };
43
+ if (formValuesMap) {
44
+ if (!props.name) {
45
+ warn('If a form component is used, the name attribute is required.');
46
+ }
47
+ else {
48
+ formValuesMap.set(props.name, { getValue, resetValue });
49
+ }
50
+ }
51
+ useEffect(() => {
52
+ return () => {
53
+ if (formValuesMap && props.name) {
54
+ formValuesMap.delete(props.name);
55
+ }
56
+ };
57
+ }, []);
58
+ const contextValue = useMemo(() => {
59
+ const notifyChange = (evt) => {
60
+ const { bindchange } = propsRef.current;
61
+ bindchange &&
62
+ bindchange(getCustomEvent('tap', evt, {
63
+ layoutRef,
64
+ detail: {
65
+ value: getValue()
66
+ }
67
+ }, propsRef.current));
68
+ };
69
+ return {
70
+ groupValue,
71
+ notifyChange
72
+ };
73
+ }, []);
74
+ const innerProps = useInnerProps(props, extendObject({
75
+ ref: nodeRef,
76
+ style: extendObject({}, normalStyle, layoutStyle)
77
+ }, layoutProps), ['name'], {
78
+ layoutRef
79
+ });
80
+ return createElement(View, innerProps, createElement(RadioGroupContext.Provider, { value: contextValue }, wrapChildren(props, {
81
+ hasVarDec,
82
+ varContext: varContextRef.current
83
+ })));
84
+ });
85
+ radioGroup.displayName = 'MpxRadioGroup';
86
+ export default radioGroup;
@@ -0,0 +1,140 @@
1
+ /**
2
+ * ✔ value
3
+ * ✔ disabled
4
+ * ✔ checked
5
+ * ✔ color
6
+ */
7
+ import { useRef, useState, forwardRef, useEffect, useContext, createElement } from 'react';
8
+ import { View, StyleSheet } from 'react-native';
9
+ import { warn } from '@mpxjs/utils';
10
+ import { LabelContext, RadioGroupContext } from './context';
11
+ import useInnerProps, { getCustomEvent } from './getInnerListeners';
12
+ import useNodesRef from './useNodesRef';
13
+ import { splitProps, splitStyle, useLayout, useTransformStyle, wrapChildren, extendObject } from './utils';
14
+ import Icon from './mpx-icon';
15
+ const styles = StyleSheet.create({
16
+ container: {
17
+ flexDirection: 'row',
18
+ alignItems: 'center'
19
+ },
20
+ wrapper: {
21
+ alignItems: 'center',
22
+ justifyContent: 'center',
23
+ width: 24,
24
+ height: 24,
25
+ borderColor: '#D1D1D1',
26
+ borderWidth: 1,
27
+ borderRadius: 12,
28
+ backgroundColor: '#ffffff',
29
+ marginRight: 5,
30
+ overflow: 'hidden'
31
+ },
32
+ wrapperChecked: {
33
+ borderWidth: 0
34
+ },
35
+ wrapperDisabled: {
36
+ backgroundColor: '#E1E1E1'
37
+ },
38
+ icon: {
39
+ opacity: 0
40
+ },
41
+ iconDisabled: {
42
+ backgroundColor: '#ADADAD'
43
+ },
44
+ iconChecked: {
45
+ opacity: 1
46
+ }
47
+ });
48
+ const Radio = forwardRef((radioProps, ref) => {
49
+ const { textProps, innerProps: props = {} } = splitProps(radioProps);
50
+ const { value = '', disabled = false, checked = false, color = '#09BB07', style = [], 'enable-var': enableVar, 'external-var-context': externalVarContext, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight, bindtap } = props;
51
+ const [isChecked, setIsChecked] = useState(!!checked);
52
+ const groupContext = useContext(RadioGroupContext);
53
+ let groupValue;
54
+ let notifyChange;
55
+ const labelContext = useContext(LabelContext);
56
+ const defaultStyle = extendObject({}, styles.wrapper, isChecked ? styles.wrapperChecked : {}, disabled ? styles.wrapperDisabled : {});
57
+ const styleObj = extendObject({}, styles.container, style);
58
+ const onChange = (evt) => {
59
+ if (disabled || isChecked)
60
+ return;
61
+ setIsChecked(!isChecked);
62
+ if (groupValue) {
63
+ for (const [key, radio] of Object.entries(groupValue)) {
64
+ if (!radio)
65
+ continue;
66
+ radio.setValue(key === value);
67
+ radio.checked = key === value;
68
+ }
69
+ }
70
+ notifyChange && notifyChange(evt);
71
+ };
72
+ const onTap = (evt) => {
73
+ bindtap && bindtap(getCustomEvent('tap', evt, { layoutRef }, props));
74
+ onChange(evt);
75
+ };
76
+ const { hasSelfPercent, normalStyle, hasVarDec, varContextRef, setWidth, setHeight } = useTransformStyle(styleObj, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
77
+ const { textStyle, backgroundStyle, innerStyle = {} } = splitStyle(normalStyle);
78
+ if (backgroundStyle) {
79
+ warn('Radio does not support background image-related styles!');
80
+ }
81
+ const nodeRef = useRef(null);
82
+ useNodesRef(props, ref, nodeRef, {
83
+ style: extendObject({}, defaultStyle, normalStyle),
84
+ change: onChange
85
+ });
86
+ const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef });
87
+ if (groupContext) {
88
+ groupValue = groupContext.groupValue;
89
+ notifyChange = groupContext.notifyChange;
90
+ }
91
+ if (labelContext) {
92
+ labelContext.current.triggerChange = onChange;
93
+ }
94
+ const innerProps = useInnerProps(props, extendObject({
95
+ ref: nodeRef,
96
+ style: extendObject({}, innerStyle, layoutStyle)
97
+ }, layoutProps, {
98
+ bindtap: !disabled && onTap
99
+ }), [
100
+ 'value',
101
+ 'disabled',
102
+ 'checked'
103
+ ], {
104
+ layoutRef
105
+ });
106
+ useEffect(() => {
107
+ if (groupValue) {
108
+ groupValue[value] = {
109
+ checked: checked,
110
+ setValue: setIsChecked
111
+ };
112
+ }
113
+ return () => {
114
+ if (groupValue) {
115
+ delete groupValue[value];
116
+ }
117
+ };
118
+ }, []);
119
+ useEffect(() => {
120
+ if (checked !== isChecked) {
121
+ setIsChecked(checked);
122
+ if (groupValue) {
123
+ groupValue[value].checked = checked;
124
+ }
125
+ }
126
+ }, [checked]);
127
+ return createElement(View, innerProps, createElement(View, { style: defaultStyle }, createElement(Icon, {
128
+ type: 'success',
129
+ size: 24,
130
+ color: disabled ? '#E1E1E1' : color,
131
+ style: extendObject({}, styles.icon, isChecked && styles.iconChecked, disabled && styles.iconDisabled)
132
+ })), wrapChildren(props, {
133
+ hasVarDec,
134
+ varContext: varContextRef.current,
135
+ textStyle,
136
+ textProps
137
+ }));
138
+ });
139
+ Radio.displayName = 'MpxRadio';
140
+ export default Radio;
@@ -0,0 +1,39 @@
1
+ export const generateHTML = (html) => {
2
+ return `<html><head>
3
+ <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scaleable=no" name="viewport">
4
+ <style>
5
+ html {
6
+ -ms-content-zooming: none;
7
+ -ms-touch-action: pan-x pan-y;
8
+ }
9
+ body {
10
+ position: fixed;
11
+ top: 0;
12
+ right: 0;
13
+ bottom: 0;
14
+ left: 0;
15
+ overflow: hidden;
16
+ }
17
+ html,body {
18
+ margin: 0;
19
+ padding: 0;
20
+ }
21
+ * {
22
+ user-select: none;
23
+ -ms-user-select: none;
24
+ -moz-user-select: none;
25
+ -webkit-user-select: none;
26
+ }
27
+ </style>
28
+ </head>
29
+ <body><div id="rich-text">${html}</div>
30
+ <script>
31
+ function sendHeight() {
32
+ const dom = document.getElementById('rich-text')
33
+ window.ReactNativeWebView.postMessage(dom.scrollHeight);
34
+ }
35
+ window.onload = sendHeight;
36
+ </script>
37
+ </body
38
+ ></html>`;
39
+ };
@@ -0,0 +1,62 @@
1
+ /**
2
+ * ✔ nodes
3
+ */
4
+ import { View } from 'react-native';
5
+ import { useRef, forwardRef, useState, createElement } from 'react';
6
+ import useInnerProps from '../getInnerListeners';
7
+ import useNodesRef from '../useNodesRef'; // 引入辅助函数
8
+ import { useTransformStyle, useLayout, extendObject } from '../utils';
9
+ import { WebView } from 'react-native-webview';
10
+ import { generateHTML } from './html';
11
+ function jsonToHtmlStr(elements) {
12
+ let htmlStr = '';
13
+ for (const element of elements) {
14
+ if (element.type === 'text') {
15
+ htmlStr += element.text;
16
+ return htmlStr;
17
+ }
18
+ const { name, attrs = {}, children = [] } = element;
19
+ let attrStr = '';
20
+ for (const [key, value] of Object.entries(attrs))
21
+ attrStr += ` ${key}="${value}"`;
22
+ let childrenStr = '';
23
+ for (const child of children)
24
+ childrenStr += jsonToHtmlStr([child]);
25
+ htmlStr += `<${name}${attrStr}>${childrenStr}</${name}>`;
26
+ }
27
+ return htmlStr;
28
+ }
29
+ const _RichText = forwardRef((props, ref) => {
30
+ const { style = {}, nodes, 'enable-var': enableVar, 'external-var-context': externalVarContext, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight } = props;
31
+ const nodeRef = useRef(null);
32
+ const [webViewHeight, setWebViewHeight] = useState(0);
33
+ const { normalStyle, hasSelfPercent, setWidth, setHeight } = useTransformStyle(Object.assign({
34
+ width: '100%',
35
+ height: webViewHeight
36
+ }, style), {
37
+ enableVar,
38
+ externalVarContext,
39
+ parentFontSize,
40
+ parentWidth,
41
+ parentHeight
42
+ });
43
+ const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef });
44
+ useNodesRef(props, ref, nodeRef, {
45
+ layoutRef
46
+ });
47
+ const innerProps = useInnerProps(props, extendObject({
48
+ ref: nodeRef,
49
+ style: extendObject(normalStyle, layoutStyle)
50
+ }, layoutProps), [], {
51
+ layoutRef
52
+ });
53
+ const html = typeof nodes === 'string' ? nodes : jsonToHtmlStr(nodes);
54
+ return createElement(View, innerProps, createElement(WebView, {
55
+ source: { html: generateHTML(html) },
56
+ onMessage: (event) => {
57
+ setWebViewHeight(+event.nativeEvent.data);
58
+ }
59
+ }));
60
+ });
61
+ _RichText.displayName = 'mpx-rich-text';
62
+ export default _RichText;
@@ -0,0 +1,17 @@
1
+ /**
2
+ * ✔ enable
3
+ */
4
+ import { createElement, Fragment } from 'react';
5
+ import Portal from './mpx-portal/index';
6
+ import { warn } from '@mpxjs/utils';
7
+ const _RootPortal = (props) => {
8
+ const { children, enable = true } = props;
9
+ if (props.style) {
10
+ warn('The root-portal component does not support the style prop.');
11
+ }
12
+ return enable
13
+ ? createElement(Portal, null, children)
14
+ : createElement(Fragment, null, children);
15
+ };
16
+ _RootPortal.displayName = 'MpxRootPortal';
17
+ export default _RootPortal;