@mpxjs/webpack-plugin 2.9.59 → 2.9.64

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 (115) hide show
  1. package/lib/index.js +1 -3
  2. package/lib/platform/style/wx/index.js +344 -270
  3. package/lib/platform/template/wx/component-config/checkbox-group.js +8 -0
  4. package/lib/platform/template/wx/component-config/checkbox.js +8 -0
  5. package/lib/platform/template/wx/component-config/cover-image.js +15 -0
  6. package/lib/platform/template/wx/component-config/cover-view.js +9 -0
  7. package/lib/platform/template/wx/component-config/form.js +13 -1
  8. package/lib/platform/template/wx/component-config/icon.js +8 -0
  9. package/lib/platform/template/wx/component-config/index.js +5 -1
  10. package/lib/platform/template/wx/component-config/label.js +15 -0
  11. package/lib/platform/template/wx/component-config/movable-area.js +18 -1
  12. package/lib/platform/template/wx/component-config/movable-view.js +18 -1
  13. package/lib/platform/template/wx/component-config/navigator.js +8 -0
  14. package/lib/platform/template/wx/component-config/picker-view-column.js +8 -0
  15. package/lib/platform/template/wx/component-config/picker-view.js +18 -2
  16. package/lib/platform/template/wx/component-config/picker.js +14 -1
  17. package/lib/platform/template/wx/component-config/radio-group.js +8 -0
  18. package/lib/platform/template/wx/component-config/radio.js +8 -0
  19. package/lib/platform/template/wx/component-config/root-portal.js +15 -0
  20. package/lib/platform/template/wx/component-config/switch.js +8 -0
  21. package/lib/platform/template/wx/component-config/unsupported.js +1 -3
  22. package/lib/react/processScript.js +2 -0
  23. package/lib/react/processStyles.js +1 -0
  24. package/lib/react/processTemplate.js +2 -3
  25. package/lib/react/style-helper.js +12 -7
  26. package/lib/runtime/components/react/context.ts +40 -0
  27. package/lib/runtime/components/react/dist/context.js +8 -0
  28. package/lib/runtime/components/react/dist/getInnerListeners.js +34 -12
  29. package/lib/runtime/components/react/dist/mpx-button.jsx +88 -88
  30. package/lib/runtime/components/react/dist/mpx-checkbox-group.jsx +82 -0
  31. package/lib/runtime/components/react/dist/mpx-checkbox.jsx +139 -0
  32. package/lib/runtime/components/react/dist/mpx-form.jsx +61 -0
  33. package/lib/runtime/components/react/dist/mpx-icon.jsx +48 -0
  34. package/lib/runtime/components/react/dist/mpx-image/index.jsx +39 -43
  35. package/lib/runtime/components/react/dist/mpx-image/svg.jsx +3 -2
  36. package/lib/runtime/components/react/dist/mpx-input.jsx +63 -37
  37. package/lib/runtime/components/react/dist/mpx-label.jsx +55 -0
  38. package/lib/runtime/components/react/dist/mpx-movable-area.jsx +41 -0
  39. package/lib/runtime/components/react/dist/mpx-movable-view.jsx +346 -0
  40. package/lib/runtime/components/react/dist/mpx-navigator.jsx +35 -0
  41. package/lib/runtime/components/react/dist/mpx-picker/date.jsx +69 -0
  42. package/lib/runtime/components/react/dist/mpx-picker/index.jsx +138 -0
  43. package/lib/runtime/components/react/dist/mpx-picker/multiSelector.jsx +142 -0
  44. package/lib/runtime/components/react/dist/mpx-picker/region.jsx +94 -0
  45. package/lib/runtime/components/react/dist/mpx-picker/regionData.js +6099 -0
  46. package/lib/runtime/components/react/dist/mpx-picker/selector.jsx +76 -0
  47. package/lib/runtime/components/react/dist/mpx-picker/time.jsx +244 -0
  48. package/lib/runtime/components/react/dist/mpx-picker/type.js +1 -0
  49. package/lib/runtime/components/react/dist/mpx-picker-view-column.jsx +107 -0
  50. package/lib/runtime/components/react/dist/mpx-picker-view.jsx +162 -0
  51. package/lib/runtime/components/react/dist/mpx-radio-group.jsx +80 -0
  52. package/lib/runtime/components/react/dist/mpx-radio.jsx +154 -0
  53. package/lib/runtime/components/react/dist/mpx-root-portal.jsx +15 -0
  54. package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +93 -70
  55. package/lib/runtime/components/react/dist/mpx-swiper/carouse.jsx +281 -157
  56. package/lib/runtime/components/react/dist/mpx-swiper/index.jsx +21 -11
  57. package/lib/runtime/components/react/dist/mpx-swiper-item.jsx +19 -11
  58. package/lib/runtime/components/react/dist/mpx-switch.jsx +79 -0
  59. package/lib/runtime/components/react/dist/mpx-text.jsx +21 -49
  60. package/lib/runtime/components/react/dist/mpx-textarea.jsx +2 -2
  61. package/lib/runtime/components/react/dist/mpx-view.jsx +451 -146
  62. package/lib/runtime/components/react/dist/mpx-web-view.jsx +17 -20
  63. package/lib/runtime/components/react/dist/parser.js +218 -0
  64. package/lib/runtime/components/react/dist/types/common.js +1 -0
  65. package/lib/runtime/components/react/dist/useNodesRef.js +3 -8
  66. package/lib/runtime/components/react/dist/utils.jsx +433 -0
  67. package/lib/runtime/components/react/getInnerListeners.ts +43 -21
  68. package/lib/runtime/components/react/mpx-button.tsx +129 -119
  69. package/lib/runtime/components/react/mpx-checkbox-group.tsx +152 -0
  70. package/lib/runtime/components/react/mpx-checkbox.tsx +234 -0
  71. package/lib/runtime/components/react/mpx-form.tsx +117 -0
  72. package/lib/runtime/components/react/mpx-icon.tsx +106 -0
  73. package/lib/runtime/components/react/mpx-image/index.tsx +62 -68
  74. package/lib/runtime/components/react/mpx-image/svg.tsx +7 -5
  75. package/lib/runtime/components/react/mpx-input.tsx +90 -42
  76. package/lib/runtime/components/react/mpx-label.tsx +110 -0
  77. package/lib/runtime/components/react/mpx-movable-area.tsx +81 -0
  78. package/lib/runtime/components/react/mpx-movable-view.tsx +424 -0
  79. package/lib/runtime/components/react/mpx-navigator.tsx +67 -0
  80. package/lib/runtime/components/react/mpx-picker/date.tsx +82 -0
  81. package/lib/runtime/components/react/mpx-picker/index.tsx +155 -0
  82. package/lib/runtime/components/react/mpx-picker/multiSelector.tsx +156 -0
  83. package/lib/runtime/components/react/mpx-picker/region.tsx +107 -0
  84. package/lib/runtime/components/react/mpx-picker/regionData.ts +6101 -0
  85. package/lib/runtime/components/react/mpx-picker/selector.tsx +91 -0
  86. package/lib/runtime/components/react/mpx-picker/time.tsx +270 -0
  87. package/lib/runtime/components/react/mpx-picker/type.ts +107 -0
  88. package/lib/runtime/components/react/mpx-picker-view-column.tsx +156 -0
  89. package/lib/runtime/components/react/mpx-picker-view.tsx +220 -0
  90. package/lib/runtime/components/react/mpx-radio-group.tsx +150 -0
  91. package/lib/runtime/components/react/mpx-radio.tsx +230 -0
  92. package/lib/runtime/components/react/mpx-root-portal.tsx +27 -0
  93. package/lib/runtime/components/react/mpx-scroll-view.tsx +184 -130
  94. package/lib/runtime/components/react/mpx-swiper/carouse.tsx +308 -183
  95. package/lib/runtime/components/react/mpx-swiper/index.tsx +27 -19
  96. package/lib/runtime/components/react/mpx-swiper/type.ts +23 -5
  97. package/lib/runtime/components/react/mpx-swiper-item.tsx +49 -14
  98. package/lib/runtime/components/react/mpx-switch.tsx +148 -0
  99. package/lib/runtime/components/react/mpx-text.tsx +53 -77
  100. package/lib/runtime/components/react/mpx-textarea.tsx +3 -3
  101. package/lib/runtime/components/react/mpx-view.tsx +576 -195
  102. package/lib/runtime/components/react/mpx-web-view.tsx +34 -39
  103. package/lib/runtime/components/react/parser.ts +245 -0
  104. package/lib/runtime/components/react/types/common.ts +12 -0
  105. package/lib/runtime/components/react/types/getInnerListeners.ts +2 -1
  106. package/lib/runtime/components/react/types/global.d.ts +17 -1
  107. package/lib/runtime/components/react/useNodesRef.ts +4 -10
  108. package/lib/runtime/components/react/utils.tsx +505 -0
  109. package/lib/runtime/optionProcessor.js +19 -17
  110. package/lib/template-compiler/compiler.js +84 -61
  111. package/lib/template-compiler/gen-node-react.js +7 -9
  112. package/lib/web/processStyles.js +2 -5
  113. package/package.json +8 -3
  114. package/lib/runtime/components/react/dist/utils.js +0 -80
  115. package/lib/runtime/components/react/utils.ts +0 -92
@@ -0,0 +1,220 @@
1
+ import { View } from 'react-native'
2
+ import { LinearGradient, LinearGradientProps } from 'react-native-linear-gradient'
3
+ import React, { forwardRef, useState, useRef, ReactElement, JSX } from 'react'
4
+ import useInnerProps, { getCustomEvent } from './getInnerListeners'
5
+ import useNodesRef, { HandlerRef } from './useNodesRef' // 引入辅助函数
6
+ import { parseInlineStyle, useTransformStyle, splitStyle, splitProps, useLayout, wrapChildren } from './utils'
7
+ /**
8
+ * ✔ value
9
+ * ✔ bindchange
10
+ * ✘ bindpickstart
11
+ * ✘ bindpickend
12
+ * ✘ mask-class
13
+ * ✔ indicator-style: 优先级indicator-style.height > pick-view-column中的子元素设置的height
14
+ * ✘ indicator-class
15
+ * ✘ mask-style
16
+ * ✘ immediate-change
17
+ */
18
+
19
+ interface PickerViewProps {
20
+ children: React.ReactNode
21
+ // 初始的defaultValue数组中的数字依次表示 picker-view 内的 picker-view-column 选择的第几项(下标从 0 开始),数字大于 picker-view-column 可选项长度时,选择最后一项。
22
+ value?: Array<number>
23
+ bindchange?: Function
24
+ style: {
25
+ [key: string]: any
26
+ }
27
+ 'indicator-style'?: string
28
+ 'enable-var': boolean
29
+ 'external-var-context'?: Record<string, any>,
30
+ 'enable-offset': boolean
31
+ }
32
+
33
+ interface PickerLayout {
34
+ height: number,
35
+ itemHeight: number
36
+ }
37
+
38
+ interface PosType {
39
+ height?: number,
40
+ top?: number
41
+ }
42
+
43
+ const styles: { [key: string]: Object } = {
44
+ wrapper: {
45
+ display: 'flex',
46
+ flex: 1,
47
+ flexDirection: 'row',
48
+ justifyContent: 'space-around',
49
+ overflow: 'hidden',
50
+ alignItems: 'center'
51
+ },
52
+ maskTop: {
53
+ position: 'absolute',
54
+ width: 1000,
55
+ zIndex: 100
56
+ },
57
+ maskBottom: {
58
+ position: 'absolute',
59
+ width: 1000,
60
+ zIndex: 100
61
+ }
62
+ }
63
+ const _PickerView = forwardRef<HandlerRef<View, PickerViewProps>, PickerViewProps>((props: PickerViewProps, ref) => {
64
+ const { children, value = [], bindchange, style, 'enable-var': enableVar, 'external-var-context': externalVarContext } = props
65
+ // indicatorStyle 需要转换为rn的style
66
+ // 微信设置到pick-view上上设置的normalStyle如border等需要转换成RN的style然后进行透传
67
+ const indicatorStyle = parseInlineStyle(props['indicator-style'])
68
+ const { height: indicatorH, width: indicatorW } = indicatorStyle
69
+ const { nodeRef } = useNodesRef<View, PickerViewProps>(props, ref, {})
70
+ // picker-view 设置的color等textStyle,在小程序上的表现是可以继承到最内层的text样式, 但是RN内部column是slot无法设置, 需要业务自己在column内的元素上设置
71
+ const {
72
+ normalStyle,
73
+ hasVarDec,
74
+ varContextRef,
75
+ hasSelfPercent,
76
+ setWidth,
77
+ setHeight
78
+ } = useTransformStyle(style, { enableVar, externalVarContext })
79
+ const { textStyle } = splitStyle(normalStyle)
80
+ const { textProps } = splitProps(props)
81
+ const {
82
+ // 存储layout布局信息
83
+ layoutRef,
84
+ layoutProps,
85
+ layoutStyle
86
+ } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef: nodeRef })
87
+
88
+ const isSetW = indicatorW !== undefined ? 1 : 0
89
+ const cloneRef = useRef(null)
90
+ const maskPos: PosType = {}
91
+ let [pickH, setPickH] = useState(0)
92
+ const itemH = pickH / 5
93
+ if (normalStyle?.height && pickH && pickH !== normalStyle?.height) {
94
+ maskPos.height = itemH * 2 + Math.ceil((normalStyle.height - pickH) / 2)
95
+ } else {
96
+ maskPos.height = itemH * 2
97
+ }
98
+
99
+ const onColumnLayoutChange = (layoutConfig: PickerLayout) => {
100
+ pickH = layoutConfig.height
101
+ setPickH(layoutConfig.height)
102
+ }
103
+
104
+ const onSelectChange = (columnIndex: number, selIndex: number) => {
105
+ const changeValue = value.slice()
106
+ changeValue[columnIndex] = selIndex
107
+ const eventData = getCustomEvent('change', {}, { detail: { value: changeValue, source: 'change' }, layoutRef })
108
+ bindchange && bindchange(eventData)
109
+ }
110
+
111
+ const innerProps = useInnerProps(props, {
112
+ ref: nodeRef,
113
+ style: {
114
+ ...normalStyle,
115
+ ...layoutStyle,
116
+ position: 'relative',
117
+ overflow: 'hidden'
118
+ },
119
+ ...layoutProps
120
+ }, [
121
+ 'enable-offset'
122
+ ], { layoutRef })
123
+
124
+ const cloneChild = (child: React.ReactNode, index: number) => {
125
+ // const extraProps = index === 0 ? { getInnerLayout: getInnerLayout, innerProps } : {}
126
+ const extraProps = {}
127
+ const childProps = {
128
+ ...(child as ReactElement)?.props,
129
+ ref: cloneRef,
130
+ prefix: index,
131
+ key: 'pick-view' + index,
132
+ wrapperStyle: {
133
+ height: normalStyle?.height || 0,
134
+ itemHeight: indicatorH || 0
135
+ },
136
+ onColumnLayoutChange,
137
+ onSelectChange: onSelectChange.bind(null, index),
138
+ selectedIndex: value?.[index] || 0,
139
+ ...extraProps
140
+ }
141
+ const realElement = React.cloneElement(child as ReactElement, childProps)
142
+ return wrapChildren(
143
+ {
144
+ children: realElement
145
+ },
146
+ {
147
+ hasVarDec,
148
+ varContext: varContextRef.current,
149
+ textStyle,
150
+ textProps
151
+ }
152
+ )
153
+ }
154
+
155
+ const renderTopMask = () => {
156
+ const linearProps: LinearGradientProps = {
157
+ colors: ['rgba(255,255,255,0.8)', 'rgba(255,255,255,0.2)'],
158
+ style: [
159
+ styles.maskTop,
160
+ {
161
+ height: maskPos.height,
162
+ top: 0,
163
+ pointerEvents: 'none'
164
+ }
165
+ ]
166
+ }
167
+ return (<LinearGradient {...linearProps}/>)
168
+ }
169
+
170
+ const renderBottomMask = () => {
171
+ const linearProps: LinearGradientProps = {
172
+ colors: ['rgba(255,255,255,0.2)', 'rgba(255,255,255,0.8)'],
173
+ style: [
174
+ styles.maskBottom,
175
+ {
176
+ height: maskPos.height,
177
+ bottom: 0,
178
+ pointerEvents: 'none'
179
+ }
180
+ ]
181
+ }
182
+ return <LinearGradient {...linearProps}></LinearGradient>
183
+ }
184
+
185
+ const renderLine = () => {
186
+ return <View style={[{
187
+ position: 'absolute',
188
+ top: '50%',
189
+ transform: [{ translateY: -(itemH / 2) }],
190
+ height: itemH,
191
+ borderTopWidth: 1,
192
+ borderBottomWidth: 1,
193
+ borderColor: '#f0f0f0',
194
+ width: '100%',
195
+ zIndex: 101
196
+ }]}></View>
197
+ }
198
+
199
+ const renderSubChild = () => {
200
+ if (Array.isArray(children)) {
201
+ return children.map((item, index) => {
202
+ return cloneChild(item, index)
203
+ })
204
+ } else {
205
+ return cloneChild(children, 0)
206
+ }
207
+ }
208
+ return (<View {...innerProps}>
209
+ {renderTopMask()}
210
+ <View style={[styles.wrapper]}>
211
+ {renderSubChild()}
212
+ </View>
213
+ {renderBottomMask()}
214
+ {!isSetW && renderLine()}
215
+ </View>)
216
+ })
217
+
218
+ _PickerView.displayName = 'mpx-picker-view'
219
+
220
+ export default _PickerView
@@ -0,0 +1,150 @@
1
+ /**
2
+ * ✔ bindchange
3
+ */
4
+ import { JSX, useRef, forwardRef, ReactNode, useContext } from 'react'
5
+ import { View, NativeSyntheticEvent, ViewStyle } from 'react-native'
6
+ import { warn } from '@mpxjs/utils'
7
+ import { FormContext, FormFieldValue, RadioGroupContext, GroupValue } from './context'
8
+ import useInnerProps, { getCustomEvent } from './getInnerListeners'
9
+ import useNodesRef, { HandlerRef } from './useNodesRef'
10
+ import { useLayout, useTransformStyle, wrapChildren } from './utils'
11
+
12
+ export interface RadioGroupProps {
13
+ name: string
14
+ style?: ViewStyle & Record<string, any>
15
+ 'enable-offset'?: boolean
16
+ 'enable-var'?: boolean
17
+ 'external-var-context'?: Record<string, any>
18
+ 'parent-font-size'?: number
19
+ 'parent-width'?: number
20
+ 'parent-height'?: number
21
+ children: ReactNode
22
+ bindchange?: (evt: NativeSyntheticEvent<TouchEvent> | unknown) => void
23
+ }
24
+
25
+ const radioGroup = forwardRef<
26
+ HandlerRef<View, RadioGroupProps>,
27
+ RadioGroupProps
28
+ >((props, ref): JSX.Element => {
29
+ const {
30
+ style = {},
31
+ 'enable-var': enableVar,
32
+ 'external-var-context': externalVarContext,
33
+ 'parent-font-size': parentFontSize,
34
+ 'parent-width': parentWidth,
35
+ 'parent-height': parentHeight,
36
+ bindchange
37
+ } = props
38
+
39
+ const formContext = useContext(FormContext)
40
+
41
+ let formValuesMap: Map<string, FormFieldValue> | undefined
42
+
43
+ if (formContext) {
44
+ formValuesMap = formContext.formValuesMap
45
+ }
46
+
47
+ const groupValue: GroupValue = useRef({}).current
48
+
49
+ const defaultStyle = {
50
+ flexDirection: 'row',
51
+ flexWrap: 'wrap'
52
+ }
53
+
54
+ const styleObj = {
55
+ ...defaultStyle,
56
+ ...style
57
+ }
58
+
59
+ const {
60
+ hasSelfPercent,
61
+ normalStyle,
62
+ hasVarDec,
63
+ varContextRef,
64
+ setWidth,
65
+ setHeight
66
+ } = useTransformStyle(styleObj, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight })
67
+
68
+ const { nodeRef } = useNodesRef(props, ref, { defaultStyle })
69
+
70
+ const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef })
71
+
72
+ const getSelectionValue = (): string | undefined => {
73
+ for (const key in groupValue) {
74
+ if (groupValue[key].checked) {
75
+ return key
76
+ }
77
+ }
78
+ }
79
+
80
+ const getValue = () => {
81
+ return getSelectionValue()
82
+ }
83
+
84
+ const resetValue = () => {
85
+ Object.keys(groupValue).forEach((key) => {
86
+ groupValue[key].checked = false
87
+ groupValue[key].setValue(false)
88
+ })
89
+ }
90
+
91
+ if (formValuesMap) {
92
+ if (!props.name) {
93
+ warn('If a form component is used, the name attribute is required.')
94
+ } else {
95
+ formValuesMap.set(props.name, { getValue, resetValue })
96
+ }
97
+ }
98
+
99
+ const notifyChange = (
100
+ evt: NativeSyntheticEvent<TouchEvent>
101
+ ) => {
102
+ bindchange &&
103
+ bindchange(
104
+ getCustomEvent(
105
+ 'tap',
106
+ evt,
107
+ {
108
+ layoutRef,
109
+ detail: {
110
+ value: getSelectionValue()
111
+ }
112
+ },
113
+ props
114
+ )
115
+ )
116
+ }
117
+
118
+ const innerProps = useInnerProps(
119
+ props,
120
+ {
121
+ ref: nodeRef,
122
+ style: { ...normalStyle, ...layoutStyle },
123
+ ...layoutProps
124
+ },
125
+ [],
126
+ {
127
+ layoutRef
128
+ }
129
+ )
130
+
131
+ return (
132
+ <View {...innerProps}>
133
+ <RadioGroupContext.Provider value={{ groupValue, notifyChange }}>
134
+ {
135
+ wrapChildren(
136
+ props,
137
+ {
138
+ hasVarDec,
139
+ varContext: varContextRef.current
140
+ }
141
+ )
142
+ }
143
+ </RadioGroupContext.Provider>
144
+ </View>
145
+ )
146
+ })
147
+
148
+ radioGroup.displayName = 'mpx-radio-group'
149
+
150
+ export default radioGroup
@@ -0,0 +1,230 @@
1
+ /**
2
+ * ✔ value
3
+ * ✔ disabled
4
+ * ✔ checked
5
+ * ✔ color
6
+ */
7
+ import { JSX, useState, forwardRef, useEffect, ReactNode, useContext, Dispatch, SetStateAction } from 'react'
8
+ import { View, StyleSheet, ViewStyle, NativeSyntheticEvent } from 'react-native'
9
+ import { warn } from '@mpxjs/utils'
10
+ import { LabelContext, RadioGroupContext } from './context'
11
+ import useInnerProps, { getCustomEvent } from './getInnerListeners'
12
+ import useNodesRef, { HandlerRef } from './useNodesRef'
13
+ import { splitProps, splitStyle, useLayout, useTransformStyle, wrapChildren } from './utils'
14
+ import Icon from './mpx-icon'
15
+
16
+ export interface RadioProps {
17
+ value?: string
18
+ checked?: boolean
19
+ disabled?: boolean
20
+ color?: string
21
+ style?: ViewStyle & Record<string, any>
22
+ 'enable-offset'?: boolean
23
+ 'enable-var'?: boolean
24
+ 'external-var-context'?: Record<string, any>
25
+ 'parent-font-size'?: number;
26
+ 'parent-width'?: number;
27
+ 'parent-height'?: number;
28
+ children: ReactNode
29
+ bindtap?: (evt: NativeSyntheticEvent<TouchEvent> | unknown) => void
30
+ catchtap?: (evt: NativeSyntheticEvent<TouchEvent> | unknown) => void
31
+ }
32
+
33
+ const styles = StyleSheet.create({
34
+ container: {
35
+ flexDirection: 'row',
36
+ alignItems: 'center'
37
+ },
38
+ wrapper: {
39
+ alignItems: 'center',
40
+ justifyContent: 'center',
41
+ width: 24,
42
+ height: 24,
43
+ borderColor: '#D1D1D1',
44
+ borderWidth: 1,
45
+ borderRadius: 12,
46
+ backgroundColor: '#ffffff',
47
+ marginRight: 5,
48
+ overflow: 'hidden'
49
+ },
50
+ wrapperChecked: {
51
+ borderWidth: 0
52
+ },
53
+ wrapperDisabled: {
54
+ backgroundColor: '#E1E1E1'
55
+ },
56
+ icon: {
57
+ opacity: 0
58
+ },
59
+ iconDisabled: {
60
+ backgroundColor: '#ADADAD'
61
+ },
62
+ iconChecked: {
63
+ opacity: 1
64
+ }
65
+ })
66
+
67
+ const Radio = forwardRef<HandlerRef<View, RadioProps>, RadioProps>(
68
+ (radioProps, ref): JSX.Element => {
69
+ const { textProps, innerProps: props = {} } = splitProps(radioProps)
70
+
71
+ const {
72
+ value = '',
73
+ disabled = false,
74
+ checked = false,
75
+ color = '#09BB07',
76
+ style = [],
77
+ 'enable-var': enableVar,
78
+ 'external-var-context': externalVarContext,
79
+ 'parent-font-size': parentFontSize,
80
+ 'parent-width': parentWidth,
81
+ 'parent-height': parentHeight,
82
+ bindtap,
83
+ catchtap
84
+ } = props
85
+
86
+ const [isChecked, setIsChecked] = useState<boolean>(!!checked)
87
+
88
+ const groupContext = useContext(RadioGroupContext)
89
+ let groupValue: { [key: string]: { checked: boolean; setValue: Dispatch<SetStateAction<boolean>>; } } | undefined
90
+ let notifyChange: (evt: NativeSyntheticEvent<TouchEvent>) => void | undefined
91
+
92
+ const labelContext = useContext(LabelContext)
93
+
94
+ const defaultStyle = {
95
+ ...styles.wrapper,
96
+ ...(isChecked && styles.wrapperChecked),
97
+ ...(disabled && styles.wrapperDisabled)
98
+ }
99
+
100
+ const styleObj = {
101
+ ...styles.container,
102
+ ...style
103
+ }
104
+
105
+ const onChange = (evt: NativeSyntheticEvent<TouchEvent>) => {
106
+ if (disabled || isChecked) return
107
+ setIsChecked(!isChecked)
108
+ if (groupValue) {
109
+ for (const [key, radio] of Object.entries(groupValue)) {
110
+ if (!radio) continue
111
+ radio.setValue(key === value)
112
+ radio.checked = key === value
113
+ }
114
+ }
115
+ notifyChange && notifyChange(evt)
116
+ }
117
+
118
+ const onTap = (evt: NativeSyntheticEvent<TouchEvent>) => {
119
+ if (disabled) return
120
+ bindtap && bindtap(getCustomEvent('tap', evt, { layoutRef }, props))
121
+ onChange(evt)
122
+ }
123
+
124
+ const catchTap = (evt: NativeSyntheticEvent<TouchEvent>) => {
125
+ if (disabled) return
126
+ catchtap && catchtap(getCustomEvent('tap', evt, { layoutRef }, props))
127
+ }
128
+
129
+ const {
130
+ hasSelfPercent,
131
+ normalStyle,
132
+ hasVarDec,
133
+ varContextRef,
134
+ setWidth,
135
+ setHeight
136
+ } = useTransformStyle(styleObj, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight })
137
+
138
+ const { textStyle, backgroundStyle, innerStyle } = splitStyle(normalStyle)
139
+
140
+ if (backgroundStyle) {
141
+ warn('Radio does not support background image-related styles!')
142
+ }
143
+
144
+ const { nodeRef } = useNodesRef(props, ref, {
145
+ defaultStyle,
146
+ change: onChange
147
+ })
148
+
149
+ const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef })
150
+
151
+ if (groupContext) {
152
+ groupValue = groupContext.groupValue
153
+ notifyChange = groupContext.notifyChange
154
+ }
155
+
156
+ if (labelContext) {
157
+ labelContext.current.triggerChange = onChange
158
+ }
159
+
160
+ const innerProps = useInnerProps(
161
+ props,
162
+ {
163
+ ref: nodeRef,
164
+ style: { ...innerStyle, ...layoutStyle },
165
+ ...layoutProps,
166
+ bindtap: onTap,
167
+ catchtap: catchTap
168
+ },
169
+ [],
170
+ {
171
+ layoutRef
172
+ }
173
+ )
174
+
175
+ useEffect(() => {
176
+ if (groupValue) {
177
+ groupValue[value] = {
178
+ checked: checked,
179
+ setValue: setIsChecked
180
+ }
181
+ }
182
+ return () => {
183
+ if (groupValue) {
184
+ delete groupValue[value]
185
+ }
186
+ }
187
+ }, [])
188
+
189
+ useEffect(() => {
190
+ if (checked !== isChecked) {
191
+ setIsChecked(checked)
192
+ if (groupValue) {
193
+ groupValue[value].checked = checked
194
+ }
195
+ }
196
+ }, [checked])
197
+
198
+ return (
199
+ <View {...innerProps}>
200
+ <View style={defaultStyle}>
201
+ <Icon
202
+ type='success'
203
+ size={24}
204
+ color={disabled ? '#E1E1E1' : color}
205
+ style={{
206
+ ...styles.icon,
207
+ ...(isChecked && styles.iconChecked),
208
+ ...(disabled && styles.iconDisabled)
209
+ }}
210
+ />
211
+ </View>
212
+ {
213
+ wrapChildren(
214
+ props,
215
+ {
216
+ hasVarDec,
217
+ varContext: varContextRef.current,
218
+ textStyle,
219
+ textProps
220
+ }
221
+ )
222
+ }
223
+ </View>
224
+ )
225
+ }
226
+ )
227
+
228
+ Radio.displayName = 'mpx-radio'
229
+
230
+ export default Radio
@@ -0,0 +1,27 @@
1
+ /**
2
+ * ✔ enable
3
+ */
4
+ import { ReactNode } from 'react'
5
+ import { Portal } from '@ant-design/react-native'
6
+ import { warn } from '@mpxjs/utils'
7
+ interface RootPortalProps {
8
+ enable?: boolean
9
+ children: ReactNode
10
+ [x: string]: any
11
+ }
12
+
13
+ const _RootPortal = (props: RootPortalProps) => {
14
+ const { children, enable = true } = props
15
+ if (props.style) {
16
+ warn('The root-portal component does not support the style prop.')
17
+ }
18
+ return enable
19
+ ? <Portal>
20
+ {children}
21
+ </Portal>
22
+ : <>{children}</>
23
+ }
24
+
25
+ _RootPortal.displayName = 'mpx-root-portal'
26
+
27
+ export default _RootPortal