@mpxjs/webpack-plugin 2.9.69 → 2.9.70-alpha.0

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 (138) hide show
  1. package/README.md +1 -1
  2. package/lib/config.js +14 -0
  3. package/lib/dependencies/AddEntryDependency.js +24 -0
  4. package/lib/dependencies/ResolveDependency.js +5 -0
  5. package/lib/index.js +38 -7
  6. package/lib/json-compiler/helper.js +3 -3
  7. package/lib/loader.js +53 -0
  8. package/lib/platform/template/wx/component-config/button.js +14 -2
  9. package/lib/platform/template/wx/component-config/image.js +4 -0
  10. package/lib/platform/template/wx/component-config/input.js +5 -1
  11. package/lib/platform/template/wx/component-config/rich-text.js +4 -0
  12. package/lib/platform/template/wx/component-config/scroll-view.js +4 -0
  13. package/lib/platform/template/wx/component-config/swiper.js +1 -1
  14. package/lib/platform/template/wx/component-config/switch.js +4 -0
  15. package/lib/platform/template/wx/component-config/text.js +4 -0
  16. package/lib/platform/template/wx/component-config/textarea.js +6 -1
  17. package/lib/platform/template/wx/component-config/view.js +4 -0
  18. package/lib/platform/template/wx/index.js +127 -1
  19. package/lib/react/processTemplate.js +3 -0
  20. package/lib/resolve-loader.js +4 -1
  21. package/lib/runtime/components/react/context.ts +4 -0
  22. package/lib/runtime/components/react/dist/context.js +1 -0
  23. package/lib/runtime/components/react/dist/event.config.js +24 -24
  24. package/lib/runtime/components/react/dist/getInnerListeners.js +183 -165
  25. package/lib/runtime/components/react/dist/mpx-button.jsx +35 -42
  26. package/lib/runtime/components/react/dist/mpx-canvas/index.jsx +30 -12
  27. package/lib/runtime/components/react/dist/mpx-checkbox-group.jsx +13 -19
  28. package/lib/runtime/components/react/dist/mpx-checkbox.jsx +29 -38
  29. package/lib/runtime/components/react/dist/mpx-form.jsx +16 -19
  30. package/lib/runtime/components/react/dist/mpx-icon.jsx +8 -16
  31. package/lib/runtime/components/react/dist/mpx-image.jsx +291 -0
  32. package/lib/runtime/components/react/dist/mpx-input.jsx +54 -27
  33. package/lib/runtime/components/react/dist/mpx-label.jsx +15 -22
  34. package/lib/runtime/components/react/dist/mpx-movable-area.jsx +13 -16
  35. package/lib/runtime/components/react/dist/mpx-movable-view.jsx +13 -13
  36. package/lib/runtime/components/react/dist/mpx-navigator.jsx +2 -4
  37. package/lib/runtime/components/react/dist/mpx-picker/date.jsx +6 -2
  38. package/lib/runtime/components/react/dist/mpx-picker/index.jsx +5 -3
  39. package/lib/runtime/components/react/dist/mpx-picker/multiSelector.jsx +6 -2
  40. package/lib/runtime/components/react/dist/mpx-picker/region.jsx +6 -2
  41. package/lib/runtime/components/react/dist/mpx-picker/selector.jsx +6 -2
  42. package/lib/runtime/components/react/dist/mpx-picker/time.jsx +10 -15
  43. package/lib/runtime/components/react/dist/mpx-picker-view-column-item.jsx +39 -0
  44. package/lib/runtime/components/react/dist/mpx-picker-view-column.jsx +110 -97
  45. package/lib/runtime/components/react/dist/mpx-picker-view.jsx +32 -29
  46. package/lib/runtime/components/react/dist/mpx-radio-group.jsx +11 -19
  47. package/lib/runtime/components/react/dist/mpx-radio.jsx +27 -42
  48. package/lib/runtime/components/react/dist/mpx-rich-text/html.js +39 -0
  49. package/lib/runtime/components/react/dist/mpx-rich-text/index.jsx +63 -0
  50. package/lib/runtime/components/react/dist/mpx-root-portal.jsx +6 -4
  51. package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +47 -41
  52. package/lib/runtime/components/react/dist/mpx-simple-text.jsx +11 -0
  53. package/lib/runtime/components/react/dist/mpx-swiper-item.jsx +4 -2
  54. package/lib/runtime/components/react/dist/mpx-swiper.jsx +606 -0
  55. package/lib/runtime/components/react/dist/mpx-switch.jsx +20 -10
  56. package/lib/runtime/components/react/dist/mpx-text.jsx +11 -10
  57. package/lib/runtime/components/react/dist/mpx-textarea.jsx +8 -3
  58. package/lib/runtime/components/react/dist/mpx-view.jsx +29 -44
  59. package/lib/runtime/components/react/dist/mpx-web-view.jsx +105 -42
  60. package/lib/runtime/components/react/dist/pickerFaces.js +12 -6
  61. package/lib/runtime/components/react/dist/pickerVIewContext.js +9 -0
  62. package/lib/runtime/components/react/dist/pickerViewMask.jsx +18 -0
  63. package/lib/runtime/components/react/dist/{pickerOverlay.jsx → pickerViewOverlay.jsx} +5 -3
  64. package/lib/runtime/components/react/dist/useAnimationHooks.js +35 -9
  65. package/lib/runtime/components/react/dist/utils.jsx +20 -24
  66. package/lib/runtime/components/react/getInnerListeners.ts +35 -28
  67. package/lib/runtime/components/react/mpx-button.tsx +55 -36
  68. package/lib/runtime/components/react/mpx-canvas/index.tsx +2 -2
  69. package/lib/runtime/components/react/mpx-checkbox-group.tsx +13 -12
  70. package/lib/runtime/components/react/mpx-checkbox.tsx +28 -28
  71. package/lib/runtime/components/react/mpx-form.tsx +10 -8
  72. package/lib/runtime/components/react/mpx-icon.tsx +10 -15
  73. package/lib/runtime/components/react/mpx-image.tsx +396 -0
  74. package/lib/runtime/components/react/mpx-input.tsx +61 -33
  75. package/lib/runtime/components/react/mpx-label.tsx +14 -13
  76. package/lib/runtime/components/react/mpx-movable-area.tsx +8 -7
  77. package/lib/runtime/components/react/mpx-movable-view.tsx +1 -1
  78. package/lib/runtime/components/react/mpx-picker/date.tsx +5 -2
  79. package/lib/runtime/components/react/mpx-picker/index.tsx +3 -2
  80. package/lib/runtime/components/react/mpx-picker/multiSelector.tsx +5 -2
  81. package/lib/runtime/components/react/mpx-picker/region.tsx +5 -2
  82. package/lib/runtime/components/react/mpx-picker/selector.tsx +5 -2
  83. package/lib/runtime/components/react/mpx-picker/time.tsx +10 -15
  84. package/lib/runtime/components/react/mpx-picker/type.ts +48 -43
  85. package/lib/runtime/components/react/mpx-picker-view-column.tsx +4 -1
  86. package/lib/runtime/components/react/mpx-picker-view.tsx +7 -1
  87. package/lib/runtime/components/react/mpx-radio-group.tsx +11 -12
  88. package/lib/runtime/components/react/mpx-radio.tsx +26 -29
  89. package/lib/runtime/components/react/mpx-scroll-view.tsx +32 -30
  90. package/lib/runtime/components/react/mpx-simple-text.tsx +18 -0
  91. package/lib/runtime/components/react/mpx-swiper/carouse.tsx +4 -2
  92. package/lib/runtime/components/react/mpx-swiper-item.tsx +3 -2
  93. package/lib/runtime/components/react/mpx-switch.tsx +10 -8
  94. package/lib/runtime/components/react/mpx-text.tsx +6 -2
  95. package/lib/runtime/components/react/mpx-view.tsx +37 -45
  96. package/lib/runtime/components/react/mpx-web-view.tsx +25 -15
  97. package/lib/runtime/components/react/types/global.d.ts +1 -16
  98. package/lib/runtime/components/react/utils.tsx +24 -24
  99. package/lib/runtime/components/tenon/getInnerListeners.js +334 -0
  100. package/lib/runtime/components/tenon/tenon-button.vue +309 -0
  101. package/lib/runtime/components/tenon/tenon-image.vue +66 -0
  102. package/lib/runtime/components/tenon/tenon-input.vue +171 -0
  103. package/lib/runtime/components/tenon/tenon-rich-text.vue +26 -0
  104. package/lib/runtime/components/tenon/tenon-scroll-view.vue +127 -0
  105. package/lib/runtime/components/tenon/tenon-switch.vue +96 -0
  106. package/lib/runtime/components/tenon/tenon-text.vue +70 -0
  107. package/lib/runtime/components/tenon/tenon-textarea.vue +86 -0
  108. package/lib/runtime/components/tenon/tenon-view.vue +93 -0
  109. package/lib/runtime/components/web/getInnerListeners.js +6 -6
  110. package/lib/runtime/components/web/mpx-movable-view.vue +334 -344
  111. package/lib/runtime/components/web/mpx-picker-view-column.vue +75 -75
  112. package/lib/runtime/components/web/mpx-picker.vue +382 -385
  113. package/lib/runtime/components/web/mpx-web-view.vue +162 -162
  114. package/lib/runtime/optionProcessor.js +7 -16
  115. package/lib/runtime/optionProcessor.tenon.js +84 -0
  116. package/lib/runtime/utils.js +2 -0
  117. package/lib/style-compiler/index.js +1 -1
  118. package/lib/style-compiler/plugins/hm.js +20 -0
  119. package/lib/template-compiler/bind-this.js +7 -2
  120. package/lib/template-compiler/compiler.js +67 -40
  121. package/lib/template-compiler/gen-node-react.js +2 -2
  122. package/lib/tenon/index.js +117 -0
  123. package/lib/tenon/processJSON.js +352 -0
  124. package/lib/tenon/processScript.js +203 -0
  125. package/lib/tenon/processStyles.js +21 -0
  126. package/lib/tenon/processTemplate.js +126 -0
  127. package/lib/tenon/script-helper.js +223 -0
  128. package/lib/utils/env.js +6 -1
  129. package/lib/utils/get-relative-path.js +25 -0
  130. package/package.json +7 -3
  131. package/LICENSE +0 -433
  132. package/lib/runtime/components/react/dist/mpx-image/index.jsx +0 -226
  133. package/lib/runtime/components/react/dist/mpx-image/svg.jsx +0 -7
  134. package/lib/runtime/components/react/dist/mpx-swiper/carouse.jsx +0 -478
  135. package/lib/runtime/components/react/dist/mpx-swiper/index.jsx +0 -68
  136. package/lib/runtime/components/react/dist/mpx-swiper/type.js +0 -1
  137. package/lib/runtime/components/react/mpx-image/index.tsx +0 -345
  138. package/lib/runtime/components/react/mpx-image/svg.tsx +0 -22
@@ -77,7 +77,7 @@ function getColumnIndexByValue(range = [], column, value = []) {
77
77
  return changeIndex;
78
78
  }
79
79
  const _MultiSelectorPicker = forwardRef((props, ref) => {
80
- const { range, value, disabled, bindchange, bindcancel, children, bindcolumnchange } = props;
80
+ const { range, value, disabled, bindchange, bindcancel, children, bindcolumnchange, style } = props;
81
81
  const formatRange = formatRangeFun(range, props['range-key']);
82
82
  const initValue = getInnerValueByIndex(formatRange, value);
83
83
  // 选中的索引值
@@ -87,7 +87,10 @@ const _MultiSelectorPicker = forwardRef((props, ref) => {
87
87
  // 存储layout布局信息
88
88
  const layoutRef = useRef({});
89
89
  const viewRef = useRef(null);
90
- useNodesRef(props, ref, viewRef, {});
90
+ const nodeRef = useRef(null);
91
+ useNodesRef(props, ref, nodeRef, {
92
+ style
93
+ });
91
94
  useEffect(() => {
92
95
  if (range) {
93
96
  const newFormatRange = formatRangeFun(range, props['range-key']);
@@ -117,6 +120,7 @@ const _MultiSelectorPicker = forwardRef((props, ref) => {
117
120
  });
118
121
  };
119
122
  const antPickerProps = {
123
+ ref: nodeRef,
120
124
  data,
121
125
  value: selected,
122
126
  cols: range.length,
@@ -35,13 +35,16 @@ function formateRegionData(clObj = [], customItem, depth = 2) {
35
35
  return obj;
36
36
  }
37
37
  const _RegionPicker = forwardRef((props, ref) => {
38
- const { children, value, bindchange, bindcancel, disabled } = props;
38
+ const { children, value, bindchange, bindcancel, disabled, style } = props;
39
39
  const formatRegionData = formateRegionData(regionData, props['custom-item']);
40
40
  const [regionvalue, setRegionValue] = useState(value);
41
41
  // 存储layout布局信息
42
42
  const layoutRef = useRef({});
43
43
  const viewRef = useRef(null);
44
- useNodesRef(props, ref, viewRef, {});
44
+ const nodeRef = useRef(null);
45
+ useNodesRef(props, ref, nodeRef, {
46
+ style
47
+ });
45
48
  const onChange = (value) => {
46
49
  // 通过 value 查找 code
47
50
  let tmp = regionData;
@@ -75,6 +78,7 @@ const _RegionPicker = forwardRef((props, ref) => {
75
78
  bindcancel && bindcancel();
76
79
  };
77
80
  const regionProps = {
81
+ ref: nodeRef,
78
82
  data: formatRegionData,
79
83
  value: regionvalue,
80
84
  onChange,
@@ -18,7 +18,7 @@ const formatRangeFun = (range, rangeKey = '') => {
18
18
  return newRange;
19
19
  };
20
20
  const _SelectorPicker = forwardRef((props, ref) => {
21
- const { range, children, value, disabled, bindchange, bindcancel } = props;
21
+ const { range, children, value, disabled, bindchange, bindcancel, style } = props;
22
22
  // 格式化数据为Array<*>
23
23
  const formatRange = formatRangeFun(range, props['range-key']);
24
24
  // 选中的索引值
@@ -28,7 +28,10 @@ const _SelectorPicker = forwardRef((props, ref) => {
28
28
  // 存储layout布局信息
29
29
  const layoutRef = useRef({});
30
30
  const viewRef = useRef(null);
31
- useNodesRef(props, ref, viewRef, {});
31
+ const nodeRef = useRef(null);
32
+ useNodesRef(props, ref, nodeRef, {
33
+ style
34
+ });
32
35
  useEffect(() => {
33
36
  if (range) {
34
37
  const newFormatRange = formatRangeFun(range, props['range-key']);
@@ -53,6 +56,7 @@ const _SelectorPicker = forwardRef((props, ref) => {
53
56
  });
54
57
  };
55
58
  const antPickerProps = {
59
+ ref: nodeRef,
56
60
  data,
57
61
  value: [selected],
58
62
  cols: 1,
@@ -1,5 +1,5 @@
1
1
  import { View, Text, Modal, TouchableWithoutFeedback } from 'react-native';
2
- import { PickerView } from '@ant-design/react-native';
2
+ import { PickerView, Portal } from '@ant-design/react-native';
3
3
  import React, { forwardRef, useState, useRef, useEffect } from 'react';
4
4
  import useNodesRef from '../useNodesRef'; // 引入辅助函数
5
5
  // 可见应用窗口的大小。
@@ -11,8 +11,8 @@ const styles = {
11
11
  showModal: {
12
12
  backgroundColor: 'black',
13
13
  opacity: 0.5,
14
- position: 'absolute',
15
- width: '100%'
14
+ width: '100%',
15
+ height: '100%'
16
16
  },
17
17
  hideModal: {
18
18
  opacity: 1,
@@ -117,7 +117,7 @@ function checkSelectedIsValid(strStart, strEnd, selected) {
117
117
  */
118
118
  // start="02:10" end = 23:01
119
119
  const _TimePicker = forwardRef((props, ref) => {
120
- const { children, start, end, value, bindchange, bindcancel, disabled } = props;
120
+ const { children, start, end, value, bindchange, bindcancel, style } = props;
121
121
  const defaultProps = {
122
122
  start: '00:10',
123
123
  end: '23:59'
@@ -127,11 +127,11 @@ const _TimePicker = forwardRef((props, ref) => {
127
127
  // 存储layout布局信息
128
128
  const layoutRef = useRef({});
129
129
  const viewRef = useRef(null);
130
- useNodesRef(props, ref, viewRef, {});
130
+ const nodeRef = useRef(null);
131
+ useNodesRef(props, ref, nodeRef, { style });
131
132
  // 存储modal的布局信息
132
133
  const modalLayoutRef = useRef({});
133
134
  const modalRef = useRef(null);
134
- useNodesRef(props, ref, modalRef, {});
135
135
  const [visible, setVisible] = useState(false);
136
136
  const columnData = generateColumns();
137
137
  const [data, setData] = useState(columnData);
@@ -175,12 +175,6 @@ const _TimePicker = forwardRef((props, ref) => {
175
175
  else {
176
176
  // [9, 13]
177
177
  setTimeValue(date);
178
- const strDate = formatStr(date);
179
- bindchange && bindchange({
180
- detail: {
181
- value: strDate
182
- }
183
- });
184
178
  }
185
179
  };
186
180
  const onElementLayout = () => {
@@ -197,6 +191,7 @@ const _TimePicker = forwardRef((props, ref) => {
197
191
  };
198
192
  const renderModalChildren = () => {
199
193
  const pickerProps = {
194
+ ref: nodeRef,
200
195
  data,
201
196
  value: timevalue,
202
197
  defaultValue: timevalue,
@@ -230,15 +225,15 @@ const _TimePicker = forwardRef((props, ref) => {
230
225
  </TouchableWithoutFeedback>
231
226
  </View>;
232
227
  };
233
- const strStyle = visible ? styles.showModal : styles.hideModal;
234
- const mheight = Math.floor(offsetTop);
235
228
  // Animated.View
236
229
  return (<>
237
- <View style={{ ...strStyle, height: visible ? mheight : 0, bottom: 0 }}>
230
+ <Portal>
231
+ <View style={visible ? styles.showModal : styles.hideModal}>
238
232
  <Modal animationType="slide" transparent={true} visible={visible}>
239
233
  {renderModalChildren()}
240
234
  </Modal>
241
235
  </View>
236
+ </Portal>
242
237
  {renderChildren()}
243
238
  </>);
244
239
  });
@@ -0,0 +1,39 @@
1
+ import React, { useEffect } from 'react';
2
+ import Reanimated, { Extrapolation, interpolate, useAnimatedStyle, useSharedValue } from 'react-native-reanimated';
3
+ import { wrapChildren, extendObject } from './utils';
4
+ import { createFaces } from './pickerFaces';
5
+ import { usePickerViewColumnAnimationContext } from './pickerVIewContext';
6
+ const _PickerViewColumnItem = ({ item, index, itemHeight, itemWidth, textStyleFromParent, textStyle, hasVarDec, varContext, textProps, visibleCount, onItemLayout }) => {
7
+ const offsetYShared = usePickerViewColumnAnimationContext();
8
+ const facesShared = useSharedValue(createFaces(itemHeight, visibleCount));
9
+ useEffect(() => {
10
+ facesShared.value = createFaces(itemHeight, visibleCount);
11
+ }, [itemHeight]);
12
+ const animatedStyles = useAnimatedStyle(() => {
13
+ const inputRange = facesShared.value.map((f) => itemHeight * (index + f.index));
14
+ return {
15
+ opacity: interpolate(offsetYShared.value, inputRange, facesShared.value.map((x) => x.opacity), Extrapolation.CLAMP),
16
+ transform: [
17
+ { rotateX: interpolate(offsetYShared.value, inputRange, facesShared.value.map((x) => x.deg), Extrapolation.CLAMP) + 'deg' },
18
+ { translateY: interpolate(offsetYShared.value, inputRange, facesShared.value.map((x) => x.offsetY), Extrapolation.EXTEND) },
19
+ { scale: interpolate(offsetYShared.value, inputRange, facesShared.value.map((x) => x.scale), Extrapolation.EXTEND) }
20
+ ]
21
+ };
22
+ });
23
+ const strKey = `picker-column-item-${index}`;
24
+ const restProps = index === 0 ? { onLayout: onItemLayout } : {};
25
+ const itemProps = extendObject({
26
+ style: extendObject({ height: itemHeight, width: '100%' }, textStyleFromParent, textStyle, item.props.style)
27
+ }, restProps);
28
+ const realItem = React.cloneElement(item, itemProps);
29
+ return (<Reanimated.View key={strKey} style={[{ height: itemHeight, width: itemWidth }, animatedStyles]}>
30
+ {wrapChildren({ children: realItem }, {
31
+ hasVarDec,
32
+ varContext,
33
+ textStyle,
34
+ textProps
35
+ })}
36
+ </Reanimated.View>);
37
+ };
38
+ _PickerViewColumnItem.displayName = 'MpxPickerViewColumnItem';
39
+ export default _PickerViewColumnItem;
@@ -1,40 +1,58 @@
1
- import { Animated, SafeAreaView } from 'react-native';
2
- import React, { forwardRef, useRef, useState, useMemo, useCallback, useEffect } from 'react';
3
- import { useTransformStyle, splitStyle, splitProps, wrapChildren, useLayout, usePrevious } from './utils';
1
+ import React, { forwardRef, useRef, useState, useMemo, useEffect, useCallback } from 'react';
2
+ import { Platform, SafeAreaView, StyleSheet } from 'react-native';
3
+ import Reanimated, { useAnimatedRef, useScrollViewOffset } from 'react-native-reanimated';
4
+ import { vibrateShort } from '@mpxjs/api-proxy';
5
+ import { useTransformStyle, splitStyle, splitProps, useLayout, usePrevious } from './utils';
4
6
  import useNodesRef from './useNodesRef';
5
- import { createFaces } from './pickerFaces';
6
- import PickerOverlay from './pickerOverlay';
7
- // 默认的单个选项高度
8
- const DefaultPickerItemH = 36;
9
- // 默认一屏可见选项个数
7
+ import PickerOverlay from './pickerViewOverlay';
8
+ import PickerMask from './pickerViewMask';
9
+ import MpxPickerVIewColumnItem from './mpx-picker-view-column-item';
10
+ import { PickerViewColumnAnimationContext } from './pickerVIewContext';
10
11
  const visibleCount = 5;
11
12
  const _PickerViewColumn = forwardRef((props, ref) => {
12
- const { columnData, columnIndex, initialIndex, onSelectChange, onColumnItemRawHChange, getInnerLayout, style, wrapperStyle, pickerOverlayStyle, 'enable-var': enableVar, 'external-var-context': externalVarContext } = props;
13
+ const { columnData, columnIndex, columnStyle, initialIndex, onSelectChange, style, wrapperStyle, pickerMaskStyle, pickerOverlayStyle, 'enable-var': enableVar, 'external-var-context': externalVarContext } = props;
13
14
  const { normalStyle, hasVarDec, varContextRef, hasSelfPercent, setWidth, setHeight } = useTransformStyle(style, { enableVar, externalVarContext });
14
- const { textStyle } = splitStyle(normalStyle);
15
+ const { textStyle: textStyleFromParent = {} } = splitStyle(columnStyle);
16
+ const { textStyle = {} } = splitStyle(normalStyle);
15
17
  const { textProps } = splitProps(props);
16
- const scrollViewRef = useRef(null);
17
- useNodesRef(props, ref, scrollViewRef, {});
18
- const { height: pickerH, itemHeight = DefaultPickerItemH } = wrapperStyle;
19
- const [itemRawH, setItemRawH] = useState(0); // 单个选项真实渲染高度
18
+ const scrollViewRef = useAnimatedRef();
19
+ const offsetYShared = useScrollViewOffset(scrollViewRef);
20
+ useNodesRef(props, ref, scrollViewRef, {
21
+ style: normalStyle
22
+ });
23
+ const { height: pickerH, itemHeight } = wrapperStyle;
24
+ const [scrollViewWidth, setScrollViewWidth] = useState('100%');
25
+ const [itemRawW, setItemRawW] = useState('100%');
26
+ const [itemRawH, setItemRawH] = useState(itemHeight);
20
27
  const maxIndex = useMemo(() => columnData.length - 1, [columnData]);
28
+ const maxScrollViewWidth = useRef(-1);
29
+ const prevScrollingInfo = useRef({ index: initialIndex, y: 0 });
21
30
  const touching = useRef(false);
22
31
  const scrolling = useRef(false);
23
32
  const activeIndex = useRef(initialIndex);
24
33
  const prevIndex = usePrevious(initialIndex);
25
34
  const prevMaxIndex = usePrevious(maxIndex);
26
- const initialOffset = useMemo(() => ({
27
- x: 0,
28
- y: itemRawH * initialIndex
29
- }), [itemRawH]);
35
+ const { layoutProps } = useLayout({
36
+ props,
37
+ hasSelfPercent,
38
+ setWidth,
39
+ setHeight,
40
+ nodeRef: scrollViewRef
41
+ });
42
+ // console.log('[mpx-picker-view-column], render ---> columnIndex=', columnIndex, 'initialIndex=', initialIndex, 'columnData=', columnData.length)
43
+ // const initialOffset = useMemo(() => ({
44
+ // x: 0,
45
+ // y: itemRawH * initialIndex
46
+ // }), [itemRawH])
30
47
  const snapToOffsets = useMemo(() => columnData.map((_, i) => i * itemRawH), [columnData, itemRawH]);
48
+ const paddingHeight = useMemo(() => Math.round((pickerH - itemRawH) / 2), [pickerH, itemRawH]);
31
49
  const contentContainerStyle = useMemo(() => {
32
- return [
33
- {
34
- paddingVertical: Math.round(pickerH - itemRawH) / 2
35
- }
36
- ];
37
- }, [pickerH, itemRawH]);
50
+ return [{ paddingVertical: paddingHeight }];
51
+ }, [paddingHeight]);
52
+ const getIndex = useCallback((y) => {
53
+ const calc = Math.round(y / itemRawH);
54
+ return Math.max(0, Math.min(calc, maxIndex));
55
+ }, [itemRawH, maxIndex]);
38
56
  useEffect(() => {
39
57
  if (!scrollViewRef.current ||
40
58
  !itemRawH ||
@@ -46,40 +64,55 @@ const _PickerViewColumn = forwardRef((props, ref) => {
46
64
  maxIndex !== prevMaxIndex) {
47
65
  return;
48
66
  }
67
+ // console.log('[mpx-picker-view-column], useEffect ---> columnIndex=', columnIndex, 'initialIndex=', initialIndex, 'y=', itemRawH * initialIndex, `${scrollViewRef.current?.scrollTo}`)
68
+ setTimeout(() => {
69
+ scrollViewRef.current?.scrollTo({
70
+ x: 0,
71
+ y: itemRawH * initialIndex,
72
+ animated: false
73
+ });
74
+ }, 0);
49
75
  activeIndex.current = initialIndex;
50
- scrollViewRef.current.scrollTo({
51
- x: 0,
52
- y: itemRawH * initialIndex,
53
- animated: false
54
- });
55
76
  }, [itemRawH, initialIndex]);
56
- const onScrollViewLayout = () => {
57
- getInnerLayout && getInnerLayout(layoutRef);
77
+ const onContentSizeChange = (_w, h) => {
78
+ const y = itemRawH * initialIndex;
79
+ // console.log('[mpx-picker-view-column], onContentSizeChange --->', 'columnIndex=', columnIndex, '_w=', _w, 'h=', h, 'y=', y)
80
+ if (y <= h) {
81
+ setTimeout(() => {
82
+ scrollViewRef.current?.scrollTo({ x: 0, y, animated: false });
83
+ }, 0);
84
+ }
58
85
  };
59
- const { layoutRef, layoutProps } = useLayout({
60
- props,
61
- hasSelfPercent,
62
- setWidth,
63
- setHeight,
64
- nodeRef: scrollViewRef,
65
- onLayout: onScrollViewLayout
66
- });
67
- const onContentSizeChange = (w, h) => {
68
- scrollViewRef.current?.scrollTo({
69
- x: 0,
70
- y: itemRawH * initialIndex,
71
- animated: false
72
- });
86
+ const onScrollViewLayout = (e) => {
87
+ const { width } = e.nativeEvent.layout;
88
+ const widthInt = Math.ceil(width);
89
+ // console.log('[mpx-picker-view-column], onScrollViewLayout --->', 'columnIndex=', columnIndex, 'widthInt=', widthInt, 'scrollViewWidth=', scrollViewWidth)
90
+ if (widthInt !== scrollViewWidth) {
91
+ const maxW = maxScrollViewWidth.current;
92
+ if (maxW !== -1 && widthInt > maxW) {
93
+ return;
94
+ }
95
+ if (maxW === -1) {
96
+ maxScrollViewWidth.current = Math.ceil(widthInt * 1.5);
97
+ }
98
+ setScrollViewWidth(widthInt);
99
+ }
100
+ if (itemRawW === '100%') {
101
+ setItemRawW(widthInt);
102
+ }
73
103
  };
74
104
  const onItemLayout = (e) => {
75
105
  const { height: rawH } = e.nativeEvent.layout;
76
106
  if (rawH && itemRawH !== rawH) {
77
107
  setItemRawH(rawH);
78
- onColumnItemRawHChange(rawH);
79
108
  }
80
109
  };
81
110
  const onTouchStart = () => {
82
111
  touching.current = true;
112
+ prevScrollingInfo.current = {
113
+ index: activeIndex.current,
114
+ y: activeIndex.current * itemRawH
115
+ };
83
116
  };
84
117
  const onTouchEnd = () => {
85
118
  touching.current = false;
@@ -103,65 +136,45 @@ const _PickerViewColumn = forwardRef((props, ref) => {
103
136
  onSelectChange(calcIndex);
104
137
  }
105
138
  };
106
- const offsetY = useRef(new Animated.Value(0)).current;
107
- const onScroll = useMemo(() => Animated.event([{ nativeEvent: { contentOffset: { y: offsetY } } }], {
108
- useNativeDriver: true
109
- }), [offsetY]);
110
- const faces = useMemo(() => createFaces(itemRawH, visibleCount), [itemRawH]);
111
- const getTransform = useCallback((index) => {
112
- const inputRange = faces.map((f) => itemRawH * (index + f.index));
113
- return {
114
- opacity: offsetY.interpolate({
115
- inputRange: inputRange,
116
- outputRange: faces.map((x) => x.opacity),
117
- extrapolate: 'clamp'
118
- }),
119
- rotateX: offsetY.interpolate({
120
- inputRange: inputRange,
121
- outputRange: faces.map((x) => `${x.deg}deg`),
122
- extrapolate: 'extend'
123
- }),
124
- translateY: offsetY.interpolate({
125
- inputRange: inputRange,
126
- outputRange: faces.map((x) => x.offsetY),
127
- extrapolate: 'extend'
128
- })
129
- };
130
- }, [offsetY, faces, itemRawH]);
131
- const renderInnerchild = () => columnData.map((item, index) => {
132
- const InnerProps = index === 0 ? { onLayout: onItemLayout } : {};
133
- const strKey = `picker-column-${columnIndex}-${index}`;
134
- const { opacity, rotateX, translateY } = getTransform(index);
135
- return (<Animated.View key={strKey} {...InnerProps} style={[
136
- {
137
- height: itemHeight || DefaultPickerItemH,
138
- width: '100%',
139
- opacity,
140
- transform: [
141
- { translateY },
142
- { rotateX },
143
- { perspective: 1000 } // 适配 Android
144
- ]
139
+ const onScroll = (e) => {
140
+ if (Platform.OS === 'android') {
141
+ return;
142
+ }
143
+ const { y } = e.nativeEvent.contentOffset;
144
+ const { index: prevIndex, y: _y } = prevScrollingInfo.current;
145
+ if (touching.current || scrolling.current) {
146
+ if (Math.abs(y - _y) >= itemRawH) {
147
+ const currentId = getIndex(y);
148
+ if (currentId !== prevIndex) {
149
+ prevScrollingInfo.current = {
150
+ index: currentId,
151
+ y: currentId * itemRawH
152
+ };
153
+ vibrateShort({ type: 'selection' });
145
154
  }
146
- ]}>
147
- {wrapChildren({ children: item }, {
148
- hasVarDec,
149
- varContext: varContextRef.current,
150
- textStyle,
151
- textProps
152
- })}
153
- </Animated.View>);
155
+ }
156
+ }
157
+ };
158
+ const renderInnerchild = () => columnData.map((item, index) => {
159
+ return (<MpxPickerVIewColumnItem key={index} item={item} index={index} itemHeight={itemHeight} itemWidth={itemRawW} textStyleFromParent={textStyleFromParent} textStyle={textStyle} hasVarDec={hasVarDec} varContext={varContextRef.current} textProps={textProps} visibleCount={visibleCount} onItemLayout={onItemLayout}/>);
154
160
  });
155
161
  const renderScollView = () => {
156
- return (<Animated.ScrollView ref={scrollViewRef} bounces={true} horizontal={false} pagingEnabled={false} nestedScrollEnabled={true} removeClippedSubviews={true} showsVerticalScrollIndicator={false} showsHorizontalScrollIndicator={false} {...layoutProps} scrollEventThrottle={16} contentContainerStyle={contentContainerStyle} contentOffset={initialOffset} snapToOffsets={snapToOffsets} onContentSizeChange={onContentSizeChange} onScroll={onScroll} onTouchStart={onTouchStart} onTouchEnd={onTouchEnd} onTouchCancel={onTouchCancel} onMomentumScrollBegin={onMomentumScrollBegin} onMomentumScrollEnd={onMomentumScrollEnd}>
157
- {renderInnerchild()}
158
- </Animated.ScrollView>);
162
+ return (<PickerViewColumnAnimationContext.Provider value={offsetYShared}>
163
+ <Reanimated.ScrollView ref={scrollViewRef} bounces={true} horizontal={false} nestedScrollEnabled={true} removeClippedSubviews={false} showsVerticalScrollIndicator={false} showsHorizontalScrollIndicator={false} scrollEventThrottle={16} {...layoutProps} style={[{ width: scrollViewWidth }]} decelerationRate="fast" snapToOffsets={snapToOffsets} onScroll={onScroll} onLayout={onScrollViewLayout} onTouchStart={onTouchStart} onTouchEnd={onTouchEnd} onTouchCancel={onTouchCancel} onMomentumScrollBegin={onMomentumScrollBegin} onMomentumScrollEnd={onMomentumScrollEnd} onContentSizeChange={onContentSizeChange} contentContainerStyle={contentContainerStyle}>
164
+ {renderInnerchild()}
165
+ </Reanimated.ScrollView>
166
+ </PickerViewColumnAnimationContext.Provider>);
159
167
  };
160
168
  const renderOverlay = () => (<PickerOverlay itemHeight={itemHeight} overlayItemStyle={pickerOverlayStyle}/>);
161
- return (<SafeAreaView style={[{ display: 'flex', flex: 1 }]}>
169
+ const renderMask = () => (<PickerMask itemHeight={itemHeight} maskContainerStyle={pickerMaskStyle}/>);
170
+ return (<SafeAreaView style={[styles.wrapper, normalStyle]}>
162
171
  {renderScollView()}
172
+ {renderMask()}
163
173
  {renderOverlay()}
164
174
  </SafeAreaView>);
165
175
  });
176
+ const styles = StyleSheet.create({
177
+ wrapper: { display: 'flex', flex: 1 }
178
+ });
166
179
  _PickerViewColumn.displayName = 'MpxPickerViewColumn';
167
180
  export default _PickerViewColumn;
@@ -1,8 +1,8 @@
1
1
  import { View } from 'react-native';
2
- import React, { forwardRef, useState, useRef } from 'react';
2
+ import React, { forwardRef, useRef } from 'react';
3
3
  import useInnerProps, { getCustomEvent } from './getInnerListeners';
4
4
  import useNodesRef from './useNodesRef';
5
- import { useLayout, splitProps, splitStyle, wrapChildren, parseInlineStyle, useTransformStyle, useDebounceCallback, useStableCallback, extendObject } from './utils';
5
+ import { useLayout, splitProps, splitStyle, wrapChildren, parseInlineStyle, useTransformStyle, extendObject } from './utils';
6
6
  const styles = {
7
7
  wrapper: {
8
8
  display: 'flex',
@@ -13,66 +13,69 @@ const styles = {
13
13
  alignItems: 'center'
14
14
  }
15
15
  };
16
+ const DefaultPickerItemH = 36;
16
17
  const _PickerView = forwardRef((props, ref) => {
17
18
  const { children, value = [], bindchange, style, 'enable-var': enableVar, 'external-var-context': externalVarContext } = props;
18
- // indicatorStyle 需要转换为rn的style
19
- // 微信设置到pick-view上上设置的normalStyle如border等需要转换成RN的style然后进行透传
20
19
  const indicatorStyle = parseInlineStyle(props['indicator-style']);
20
+ const pickerMaskStyle = parseInlineStyle(props['mask-style']);
21
21
  const { height: indicatorH, ...pickerOverlayStyle } = indicatorStyle;
22
- const [pickMaxH, setPickMaxH] = useState(0);
23
22
  const nodeRef = useRef(null);
24
23
  const cloneRef = useRef(null);
25
24
  const activeValueRef = useRef(value);
26
25
  activeValueRef.current = value.slice();
26
+ const snapActiveValueRef = useRef(null);
27
+ console.log('[mpx-picker-view] value=', value, Date.now());
27
28
  const { normalStyle, hasVarDec, varContextRef, hasSelfPercent, setWidth, setHeight } = useTransformStyle(style, { enableVar, externalVarContext });
28
- useNodesRef(props, ref, nodeRef, {});
29
- const {
30
- // 存储layout布局信息
31
- layoutRef, layoutProps, layoutStyle } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef: nodeRef });
29
+ useNodesRef(props, ref, nodeRef, {
30
+ style: normalStyle
31
+ });
32
+ const { layoutRef, layoutProps, layoutStyle } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef: nodeRef });
32
33
  const { textProps } = splitProps(props);
33
34
  const { textStyle } = splitStyle(normalStyle);
34
- const onColumnItemRawHChange = (height) => {
35
- if (height > pickMaxH) {
36
- setPickMaxH(height);
37
- }
38
- };
39
- const bindchangeDebounce = useDebounceCallback(useStableCallback(bindchange), 300);
40
35
  const onSelectChange = (columnIndex, selectedIndex) => {
41
- bindchangeDebounce.clear();
42
36
  const activeValue = activeValueRef.current;
43
37
  activeValue[columnIndex] = selectedIndex;
38
+ console.log('[mpx-picker-view], onSelectChange ---> columnIndex=', columnIndex, 'selectedIndex=', selectedIndex, 'activeValue=', activeValue);
44
39
  const eventData = getCustomEvent('change', {}, { detail: { value: activeValue, source: 'change' }, layoutRef });
45
- bindchangeDebounce(eventData);
40
+ bindchange?.(eventData);
41
+ snapActiveValueRef.current = activeValueRef.current;
46
42
  };
47
- const onInitialChange = (value) => {
48
- const eventData = getCustomEvent('change', {}, { detail: { value, source: 'change' }, layoutRef });
49
- bindchange?.(eventData); // immediate
43
+ const hasDiff = (a = [], b) => {
44
+ return a.some((v, i) => v !== b[i]);
45
+ };
46
+ const onInitialChange = (isInvalid, value) => {
47
+ if (isInvalid || !snapActiveValueRef.current || hasDiff(snapActiveValueRef.current, value)) {
48
+ console.log('[mpx-picker-view], onInitialChange-1 ===> value=', value);
49
+ const eventData = getCustomEvent('change', {}, { detail: { value, source: 'change' }, layoutRef });
50
+ bindchange?.(eventData);
51
+ snapActiveValueRef.current = value.slice();
52
+ }
50
53
  };
51
54
  const innerProps = useInnerProps(props, extendObject({
52
55
  ref: nodeRef,
53
- style: extendObject(normalStyle, layoutStyle, {
56
+ style: extendObject({}, normalStyle, layoutStyle, {
54
57
  position: 'relative',
55
58
  overflow: 'hidden'
56
59
  }),
57
60
  layoutProps
58
61
  }), ['enable-offset'], { layoutRef });
59
62
  const renderColumn = (child, index, columnData, initialIndex) => {
60
- const extraProps = {};
61
63
  const childProps = child?.props || {};
62
- const wrappedProps = extendObject(childProps, {
64
+ const wrappedProps = extendObject({}, childProps, {
63
65
  columnData,
64
66
  ref: cloneRef,
65
67
  columnIndex: index,
66
68
  key: `pick-view-${index}`,
67
69
  wrapperStyle: {
68
- height: normalStyle?.height || 0,
69
- itemHeight: indicatorH || 0
70
+ height: normalStyle?.height || DefaultPickerItemH,
71
+ itemHeight: indicatorH || DefaultPickerItemH
70
72
  },
71
- onColumnItemRawHChange,
73
+ columnStyle: normalStyle,
72
74
  onSelectChange: onSelectChange.bind(null, index),
73
75
  initialIndex,
74
- pickerOverlayStyle
75
- }, extraProps);
76
+ pickerOverlayStyle,
77
+ pickerMaskStyle
78
+ });
76
79
  const realElement = React.cloneElement(child, wrappedProps);
77
80
  return wrapChildren({
78
81
  children: realElement
@@ -108,7 +111,7 @@ const _PickerView = forwardRef((props, ref) => {
108
111
  validValue.push(validIndex);
109
112
  renderColumns.push(renderColumn(item, index, columnData, validIndex));
110
113
  });
111
- isInvalid && onInitialChange(validValue);
114
+ onInitialChange(isInvalid, validValue);
112
115
  return renderColumns;
113
116
  };
114
117
  return (<View {...innerProps}>
@@ -1,13 +1,13 @@
1
1
  /**
2
2
  * ✔ bindchange
3
3
  */
4
- import { useRef, forwardRef, useContext, useMemo, useEffect } from 'react';
4
+ import { useRef, forwardRef, useContext, useMemo, useEffect, createElement } from 'react';
5
5
  import { View } from 'react-native';
6
6
  import { warn } from '@mpxjs/utils';
7
7
  import { FormContext, RadioGroupContext } from './context';
8
8
  import useInnerProps, { getCustomEvent } from './getInnerListeners';
9
9
  import useNodesRef from './useNodesRef';
10
- import { useLayout, useTransformStyle, wrapChildren } from './utils';
10
+ import { useLayout, useTransformStyle, wrapChildren, extendObject } from './utils';
11
11
  const radioGroup = forwardRef((props, ref) => {
12
12
  const { style = {}, 'enable-var': enableVar, 'external-var-context': externalVarContext, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight } = props;
13
13
  const propsRef = useRef({});
@@ -22,13 +22,10 @@ const radioGroup = forwardRef((props, ref) => {
22
22
  flexDirection: 'row',
23
23
  flexWrap: 'wrap'
24
24
  };
25
- const styleObj = {
26
- ...defaultStyle,
27
- ...style
28
- };
25
+ const styleObj = extendObject({}, defaultStyle, style);
29
26
  const { hasSelfPercent, normalStyle, hasVarDec, varContextRef, setWidth, setHeight } = useTransformStyle(styleObj, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
30
27
  const nodeRef = useRef(null);
31
- useNodesRef(props, ref, nodeRef, { defaultStyle });
28
+ useNodesRef(props, ref, nodeRef, { style: normalStyle });
32
29
  const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef });
33
30
  const getValue = () => {
34
31
  for (const key in groupValue) {
@@ -74,21 +71,16 @@ const radioGroup = forwardRef((props, ref) => {
74
71
  notifyChange
75
72
  };
76
73
  }, []);
77
- const innerProps = useInnerProps(props, {
74
+ const innerProps = useInnerProps(props, extendObject({
78
75
  ref: nodeRef,
79
- style: { ...normalStyle, ...layoutStyle },
80
- ...layoutProps
81
- }, [], {
76
+ style: extendObject({}, normalStyle, layoutStyle)
77
+ }, layoutProps), ['name'], {
82
78
  layoutRef
83
79
  });
84
- return (<View {...innerProps}>
85
- <RadioGroupContext.Provider value={contextValue}>
86
- {wrapChildren(props, {
87
- hasVarDec,
88
- varContext: varContextRef.current
89
- })}
90
- </RadioGroupContext.Provider>
91
- </View>);
80
+ return createElement(View, innerProps, createElement(RadioGroupContext.Provider, { value: contextValue }, wrapChildren(props, {
81
+ hasVarDec,
82
+ varContext: varContextRef.current
83
+ })));
92
84
  });
93
85
  radioGroup.displayName = 'MpxRadioGroup';
94
86
  export default radioGroup;