@mpxjs/webpack-plugin 2.9.70-alpha.1 → 2.9.70-alpha.2

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 (124) hide show
  1. package/lib/config.js +3 -1
  2. package/lib/file-loader.js +5 -0
  3. package/lib/parser.js +1 -1
  4. package/lib/platform/json/wx/index.js +21 -8
  5. package/lib/platform/style/wx/index.js +51 -54
  6. package/lib/platform/template/wx/component-config/fix-component-name.js +15 -12
  7. package/lib/platform/template/wx/component-config/index.js +1 -1
  8. package/lib/platform/template/wx/component-config/movable-view.js +8 -1
  9. package/lib/platform/template/wx/component-config/picker-view.js +1 -5
  10. package/lib/platform/template/wx/component-config/rich-text.js +8 -0
  11. package/lib/platform/template/wx/component-config/scroll-view.js +1 -1
  12. package/lib/platform/template/wx/component-config/unsupported.js +1 -1
  13. package/lib/platform/template/wx/index.js +3 -5
  14. package/lib/react/processScript.js +6 -3
  15. package/lib/react/script-helper.js +5 -1
  16. package/lib/runtime/components/react/context.ts +8 -0
  17. package/lib/runtime/components/react/dist/context.js +0 -2
  18. package/lib/runtime/components/react/dist/getInnerListeners.js +34 -31
  19. package/lib/runtime/components/react/dist/mpx-button.jsx +11 -11
  20. package/lib/runtime/components/react/dist/mpx-canvas/html.js +2 -4
  21. package/lib/runtime/components/react/dist/mpx-canvas/index.jsx +5 -1
  22. package/lib/runtime/components/react/dist/mpx-icon/icons/cancel.png +0 -0
  23. package/lib/runtime/components/react/dist/mpx-icon/icons/clear.png +0 -0
  24. package/lib/runtime/components/react/dist/mpx-icon/icons/download.png +0 -0
  25. package/lib/runtime/components/react/dist/mpx-icon/icons/info.png +0 -0
  26. package/lib/runtime/components/react/dist/mpx-icon/icons/search.png +0 -0
  27. package/lib/runtime/components/react/dist/mpx-icon/icons/success.png +0 -0
  28. package/lib/runtime/components/react/dist/mpx-icon/icons/success_no_circle.png +0 -0
  29. package/lib/runtime/components/react/dist/mpx-icon/icons/waiting.png +0 -0
  30. package/lib/runtime/components/react/dist/mpx-icon/icons/warn.png +0 -0
  31. package/lib/runtime/components/react/dist/mpx-icon/index.jsx +50 -0
  32. package/lib/runtime/components/react/dist/mpx-image.jsx +12 -15
  33. package/lib/runtime/components/react/dist/mpx-input.jsx +10 -8
  34. package/lib/runtime/components/react/dist/mpx-movable-view.jsx +92 -57
  35. package/lib/runtime/components/react/dist/mpx-navigator.jsx +1 -1
  36. package/lib/runtime/components/react/dist/mpx-picker/time.jsx +1 -2
  37. package/lib/runtime/components/react/dist/mpx-picker-view-column-item.jsx +10 -14
  38. package/lib/runtime/components/react/dist/mpx-picker-view-column.jsx +79 -67
  39. package/lib/runtime/components/react/dist/mpx-picker-view.jsx +19 -16
  40. package/lib/runtime/components/react/dist/mpx-root-portal.jsx +1 -1
  41. package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +2 -0
  42. package/lib/runtime/components/react/dist/mpx-swiper-item.jsx +13 -7
  43. package/lib/runtime/components/react/dist/mpx-swiper.jsx +382 -325
  44. package/lib/runtime/components/react/dist/mpx-view.jsx +15 -13
  45. package/lib/runtime/components/react/dist/mpx-web-view.jsx +22 -118
  46. package/lib/runtime/components/react/dist/pickerFaces.js +1 -6
  47. package/lib/runtime/components/react/dist/pickerVIewContext.js +5 -0
  48. package/lib/runtime/components/react/dist/{pickerViewOverlay.jsx → pickerViewIndicator.jsx} +6 -6
  49. package/lib/runtime/components/react/dist/pickerViewMask.jsx +2 -2
  50. package/lib/runtime/components/react/dist/useAnimationHooks.js +15 -10
  51. package/lib/runtime/components/react/dist/utils.jsx +117 -84
  52. package/lib/runtime/components/react/event.config.ts +25 -26
  53. package/lib/runtime/components/react/getInnerListeners.ts +236 -182
  54. package/lib/runtime/components/react/mpx-button.tsx +27 -69
  55. package/lib/runtime/components/react/mpx-canvas/html.ts +2 -4
  56. package/lib/runtime/components/react/mpx-canvas/index.tsx +44 -46
  57. package/lib/runtime/components/react/mpx-checkbox-group.tsx +15 -13
  58. package/lib/runtime/components/react/mpx-checkbox.tsx +20 -21
  59. package/lib/runtime/components/react/mpx-form.tsx +15 -20
  60. package/lib/runtime/components/react/mpx-icon/icons/cancel.png +0 -0
  61. package/lib/runtime/components/react/mpx-icon/icons/clear.png +0 -0
  62. package/lib/runtime/components/react/mpx-icon/icons/download.png +0 -0
  63. package/lib/runtime/components/react/mpx-icon/icons/info.png +0 -0
  64. package/lib/runtime/components/react/mpx-icon/icons/search.png +0 -0
  65. package/lib/runtime/components/react/mpx-icon/icons/success.png +0 -0
  66. package/lib/runtime/components/react/mpx-icon/icons/success_no_circle.png +0 -0
  67. package/lib/runtime/components/react/mpx-icon/icons/waiting.png +0 -0
  68. package/lib/runtime/components/react/mpx-icon/icons/warn.png +0 -0
  69. package/lib/runtime/components/react/mpx-icon/index.tsx +111 -0
  70. package/lib/runtime/components/react/mpx-image.tsx +99 -47
  71. package/lib/runtime/components/react/mpx-input.tsx +33 -39
  72. package/lib/runtime/components/react/mpx-label.tsx +12 -14
  73. package/lib/runtime/components/react/mpx-movable-area.tsx +10 -16
  74. package/lib/runtime/components/react/mpx-movable-view.tsx +133 -92
  75. package/lib/runtime/components/react/mpx-navigator.tsx +3 -9
  76. package/lib/runtime/components/react/mpx-picker-view-column-item.tsx +76 -0
  77. package/lib/runtime/components/react/mpx-picker-view-column.tsx +206 -183
  78. package/lib/runtime/components/react/mpx-picker-view.tsx +49 -48
  79. package/lib/runtime/components/react/mpx-radio-group.tsx +13 -15
  80. package/lib/runtime/components/react/mpx-radio.tsx +19 -25
  81. package/lib/runtime/components/react/mpx-rich-text/html.ts +40 -0
  82. package/lib/runtime/components/react/mpx-rich-text/index.tsx +115 -0
  83. package/lib/runtime/components/react/mpx-root-portal.tsx +3 -5
  84. package/lib/runtime/components/react/mpx-scroll-view.tsx +62 -49
  85. package/lib/runtime/components/react/mpx-swiper-item.tsx +45 -11
  86. package/lib/runtime/components/react/mpx-swiper.tsx +742 -0
  87. package/lib/runtime/components/react/mpx-switch.tsx +19 -15
  88. package/lib/runtime/components/react/mpx-text.tsx +8 -16
  89. package/lib/runtime/components/react/mpx-textarea.tsx +11 -10
  90. package/lib/runtime/components/react/mpx-view.tsx +28 -77
  91. package/lib/runtime/components/react/mpx-web-view.tsx +94 -59
  92. package/lib/runtime/components/react/pickerFaces.ts +10 -7
  93. package/lib/runtime/components/react/pickerVIewContext.ts +27 -0
  94. package/lib/runtime/components/react/pickerViewIndicator.tsx +34 -0
  95. package/lib/runtime/components/react/pickerViewMask.tsx +30 -0
  96. package/lib/runtime/components/react/types/{getInnerListeners.ts → getInnerListeners.d.ts} +4 -5
  97. package/lib/runtime/components/react/types/global.d.ts +14 -1
  98. package/lib/runtime/components/react/useAnimationHooks.ts +60 -15
  99. package/lib/runtime/components/react/utils.tsx +175 -71
  100. package/lib/runtime/components/web/mpx-checkbox.vue +1 -1
  101. package/lib/runtime/components/web/mpx-picker-view-column.vue +9 -4
  102. package/lib/runtime/components/web/mpx-web-view.vue +34 -20
  103. package/lib/runtime/optionProcessor.js +0 -22
  104. package/lib/style-compiler/plugins/scope-id.js +30 -2
  105. package/lib/template-compiler/compiler.js +96 -29
  106. package/lib/utils/pre-process-json.js +9 -5
  107. package/lib/wxss/loader.js +15 -2
  108. package/package.json +4 -3
  109. package/lib/runtime/components/react/dist/locale-provider.jsx +0 -15
  110. package/lib/runtime/components/react/dist/mpx-icon.jsx +0 -41
  111. package/lib/runtime/components/react/dist/mpx-portal/portal-consumer.jsx +0 -23
  112. package/lib/runtime/components/react/dist/mpx-portal/portal-host.jsx +0 -124
  113. package/lib/runtime/components/react/dist/mpx-portal/portal-manager.jsx +0 -40
  114. package/lib/runtime/components/react/dist/mpx-portal.jsx +0 -12
  115. package/lib/runtime/components/react/dist/mpx-provider.jsx +0 -31
  116. package/lib/runtime/components/react/dist/types/common.js +0 -1
  117. package/lib/runtime/components/react/dist/types/getInnerListeners.js +0 -1
  118. package/lib/runtime/components/react/mpx-icon.tsx +0 -102
  119. package/lib/runtime/components/react/mpx-swiper/carouse.tsx +0 -527
  120. package/lib/runtime/components/react/mpx-swiper/index.tsx +0 -80
  121. package/lib/runtime/components/react/mpx-swiper/type.ts +0 -87
  122. package/lib/runtime/components/react/pickerOverlay.tsx +0 -32
  123. package/lib/runtime/components/web/event.js +0 -105
  124. /package/lib/runtime/components/react/types/{common.ts → common.d.ts} +0 -0
@@ -19,12 +19,13 @@
19
19
  */
20
20
  import { useEffect, forwardRef, useContext, useCallback, useRef, useMemo, createElement } from 'react';
21
21
  import { StyleSheet } from 'react-native';
22
- import { getCustomEvent } from './getInnerListeners';
22
+ import useInnerProps, { getCustomEvent } from './getInnerListeners';
23
23
  import useNodesRef from './useNodesRef';
24
24
  import { MovableAreaContext } from './context';
25
- import { useTransformStyle, splitProps, splitStyle, HIDDEN_STYLE, wrapChildren, flatGesture, extendObject } from './utils';
25
+ import { useTransformStyle, splitProps, splitStyle, HIDDEN_STYLE, wrapChildren, flatGesture, extendObject, omit } from './utils';
26
26
  import { GestureDetector, Gesture } from 'react-native-gesture-handler';
27
27
  import Animated, { useSharedValue, useAnimatedStyle, withDecay, runOnJS, runOnUI, useAnimatedReaction, withSpring } from 'react-native-reanimated';
28
+ import { collectDataset, noop } from '@mpxjs/utils';
28
29
  const styles = StyleSheet.create({
29
30
  container: {
30
31
  position: 'absolute',
@@ -233,8 +234,7 @@ const _MovableView = forwardRef((movableViewProps, ref) => {
233
234
  });
234
235
  props.onLayout && props.onLayout(e);
235
236
  };
236
- const extendEvent = useCallback((e) => {
237
- 'worklet';
237
+ const extendEvent = useCallback((e, obj) => {
238
238
  const touchArr = [e.changedTouches, e.allTouches];
239
239
  touchArr.forEach(touches => {
240
240
  touches && touches.forEach((item) => {
@@ -242,45 +242,65 @@ const _MovableView = forwardRef((movableViewProps, ref) => {
242
242
  item.pageY = item.absoluteY;
243
243
  });
244
244
  });
245
- e.touches = e.allTouches;
245
+ Object.assign(e, {
246
+ touches: e.allTouches,
247
+ detail: {
248
+ x: e.changedTouches[0].absoluteX,
249
+ y: e.changedTouches[0].absoluteY
250
+ },
251
+ currentTarget: {
252
+ id: props.id || '',
253
+ dataset: collectDataset(props),
254
+ offsetLeft: 0,
255
+ offsetTop: 0
256
+ }
257
+ }, obj);
246
258
  }, []);
259
+ const triggerStartOnJS = ({ e }) => {
260
+ extendEvent(e);
261
+ bindtouchstart && bindtouchstart(e);
262
+ catchtouchstart && catchtouchstart(e);
263
+ };
264
+ const triggerMoveOnJS = ({ e, hasTouchmove, hasCatchTouchmove, touchEvent }) => {
265
+ extendEvent(e);
266
+ if (hasTouchmove) {
267
+ if (touchEvent === 'htouchmove') {
268
+ bindhtouchmove && bindhtouchmove(e);
269
+ }
270
+ else if (touchEvent === 'vtouchmove') {
271
+ bindvtouchmove && bindvtouchmove(e);
272
+ }
273
+ bindtouchmove && bindtouchmove(e);
274
+ }
275
+ if (hasCatchTouchmove) {
276
+ if (touchEvent === 'htouchmove') {
277
+ catchhtouchmove && catchhtouchmove(e);
278
+ }
279
+ else if (touchEvent === 'vtouchmove') {
280
+ catchvtouchmove && catchvtouchmove(e);
281
+ }
282
+ catchtouchmove && catchtouchmove(e);
283
+ }
284
+ };
285
+ const triggerEndOnJS = ({ e }) => {
286
+ extendEvent(e);
287
+ bindtouchend && bindtouchend(e);
288
+ catchtouchend && catchtouchend(e);
289
+ };
247
290
  const gesture = useMemo(() => {
248
- const handleTriggerStart = (e) => {
249
- 'worklet';
250
- extendEvent(e);
251
- bindtouchstart && runOnJS(bindtouchstart)(e);
252
- catchtouchstart && runOnJS(catchtouchstart)(e);
253
- };
254
291
  const handleTriggerMove = (e) => {
255
292
  'worklet';
256
- extendEvent(e);
257
293
  const hasTouchmove = !!bindhtouchmove || !!bindvtouchmove || !!bindtouchmove;
258
294
  const hasCatchTouchmove = !!catchhtouchmove || !!catchvtouchmove || !!catchtouchmove;
259
- if (hasTouchmove) {
260
- if (touchEvent.value === 'htouchmove') {
261
- bindhtouchmove && runOnJS(bindhtouchmove)(e);
262
- }
263
- else if (touchEvent.value === 'vtouchmove') {
264
- bindvtouchmove && runOnJS(bindvtouchmove)(e);
265
- }
266
- bindtouchmove && runOnJS(bindtouchmove)(e);
267
- }
268
- if (hasCatchTouchmove) {
269
- if (touchEvent.value === 'htouchmove') {
270
- catchhtouchmove && runOnJS(catchhtouchmove)(e);
271
- }
272
- else if (touchEvent.value === 'vtouchmove') {
273
- catchvtouchmove && runOnJS(catchvtouchmove)(e);
274
- }
275
- catchtouchmove && runOnJS(catchtouchmove)(e);
295
+ if (hasTouchmove || hasCatchTouchmove) {
296
+ runOnJS(triggerMoveOnJS)({
297
+ e,
298
+ touchEvent: touchEvent.value,
299
+ hasTouchmove,
300
+ hasCatchTouchmove
301
+ });
276
302
  }
277
303
  };
278
- const handleTriggerEnd = (e) => {
279
- 'worklet';
280
- extendEvent(e);
281
- bindtouchend && runOnJS(bindtouchend)(e);
282
- catchtouchend && runOnJS(catchtouchend)(e);
283
- };
284
304
  const gesturePan = Gesture.Pan()
285
305
  .onTouchesDown((e) => {
286
306
  'worklet';
@@ -290,12 +310,14 @@ const _MovableView = forwardRef((movableViewProps, ref) => {
290
310
  x: changedTouches.x,
291
311
  y: changedTouches.y
292
312
  };
293
- handleTriggerStart(e);
313
+ if (bindtouchstart || catchtouchstart) {
314
+ runOnJS(triggerStartOnJS)({ e });
315
+ }
294
316
  })
295
317
  .onTouchesMove((e) => {
296
318
  'worklet';
297
- isMoving.value = true;
298
319
  const changedTouches = e.changedTouches[0] || { x: 0, y: 0 };
320
+ isMoving.value = true;
299
321
  if (isFirstTouch.value) {
300
322
  touchEvent.value = Math.abs(changedTouches.x - startPosition.value.x) > Math.abs(changedTouches.y - startPosition.value.y) ? 'htouchmove' : 'vtouchmove';
301
323
  isFirstTouch.value = false;
@@ -330,7 +352,9 @@ const _MovableView = forwardRef((movableViewProps, ref) => {
330
352
  'worklet';
331
353
  isFirstTouch.value = true;
332
354
  isMoving.value = false;
333
- handleTriggerEnd(e);
355
+ if (bindtouchend || catchtouchend) {
356
+ runOnJS(triggerEndOnJS)({ e });
357
+ }
334
358
  if (disabled)
335
359
  return;
336
360
  if (!inertia) {
@@ -355,9 +379,9 @@ const _MovableView = forwardRef((movableViewProps, ref) => {
355
379
  })
356
380
  .onFinalize((e) => {
357
381
  'worklet';
382
+ isMoving.value = false;
358
383
  if (!inertia || disabled || !animation)
359
384
  return;
360
- isMoving.value = false;
361
385
  if (direction === 'horizontal' || direction === 'all') {
362
386
  xInertialMotion.value = true;
363
387
  offsetX.value = withDecay({
@@ -396,31 +420,42 @@ const _MovableView = forwardRef((movableViewProps, ref) => {
396
420
  ]
397
421
  };
398
422
  });
399
- const injectCatchEvent = (props) => {
400
- const eventHandlers = {};
401
- const catchEventList = [
402
- { name: 'onTouchStart', value: ['catchtouchstart'] },
403
- { name: 'onTouchMove', value: ['catchtouchmove', 'catchvtouchmove', 'catchhtouchmove'] },
404
- { name: 'onTouchEnd', value: ['catchtouchend'] }
423
+ const rewriteCatchEvent = () => {
424
+ const handlers = {};
425
+ const events = [
426
+ { type: 'touchstart' },
427
+ { type: 'touchmove', alias: ['vtouchmove', 'htouchmove'] },
428
+ { type: 'touchend' }
405
429
  ];
406
- catchEventList.forEach(event => {
407
- event.value.forEach(name => {
408
- if (props[name] && !eventHandlers[event.name]) {
409
- eventHandlers[event.name] = (e) => {
410
- e.stopPropagation();
411
- };
412
- }
413
- });
430
+ events.forEach(({ type, alias = [] }) => {
431
+ const hasCatchEvent = props[`catch${type}`] ||
432
+ alias.some(name => props[`catch${name}`]);
433
+ if (hasCatchEvent)
434
+ handlers[`catch${type}`] = noop;
414
435
  });
415
- return eventHandlers;
436
+ return handlers;
416
437
  };
417
- const catchEventHandlers = injectCatchEvent(props);
418
438
  const layoutStyle = !hasLayoutRef.current && hasSelfPercent ? HIDDEN_STYLE : {};
419
- return createElement(GestureDetector, { gesture: gesture }, createElement(Animated.View, extendObject({
439
+ // bind 相关 touch 事件直接由 gesture 触发,无须重复挂载
440
+ // catch 相关 touch 事件需要重写并通过 useInnerProps 注入阻止冒泡逻辑
441
+ const filterProps = omit(props, [
442
+ 'bindtouchstart',
443
+ 'bindtouchmove',
444
+ 'bindvtouchmove',
445
+ 'bindhtouchmove',
446
+ 'bindtouchend',
447
+ 'catchtouchstart',
448
+ 'catchtouchmove',
449
+ 'catchvtouchmove',
450
+ 'catchhtouchmove',
451
+ 'catchtouchend'
452
+ ]);
453
+ const innerProps = useInnerProps(filterProps, extendObject({
420
454
  ref: nodeRef,
421
455
  onLayout: onLayout,
422
456
  style: [innerStyle, animatedStyles, layoutStyle]
423
- }, catchEventHandlers), wrapChildren(props, {
457
+ }, rewriteCatchEvent()));
458
+ return createElement(GestureDetector, { gesture: gesture }, createElement(Animated.View, innerProps, wrapChildren(props, {
424
459
  hasVarDec,
425
460
  varContext: varContextRef.current,
426
461
  textStyle,
@@ -3,7 +3,7 @@ import useInnerProps from './getInnerListeners';
3
3
  import { redirectTo, navigateTo, navigateBack, reLaunch, switchTab } from '@mpxjs/api-proxy';
4
4
  import MpxView from './mpx-view';
5
5
  const _Navigator = forwardRef((props, ref) => {
6
- const { children, 'open-type': openType, url, delta } = props;
6
+ const { children, 'open-type': openType, url = '', delta } = props;
7
7
  const handleClick = useCallback(() => {
8
8
  switch (openType) {
9
9
  case 'navigateBack':
@@ -1,6 +1,5 @@
1
1
  import { View, Text, Modal, TouchableWithoutFeedback } from 'react-native';
2
- import Portal from '../mpx-portal';
3
- import { PickerView } from '@ant-design/react-native';
2
+ import { PickerView, Portal } from '@ant-design/react-native';
4
3
  import React, { forwardRef, useState, useRef, useEffect } from 'react';
5
4
  import useNodesRef from '../useNodesRef'; // 引入辅助函数
6
5
  // 可见应用窗口的大小。
@@ -1,9 +1,10 @@
1
1
  import React, { useEffect } from 'react';
2
2
  import Reanimated, { Extrapolation, interpolate, useAnimatedStyle, useSharedValue } from 'react-native-reanimated';
3
- import { wrapChildren, extendObject } from './utils';
3
+ import { extendObject } from './utils';
4
4
  import { createFaces } from './pickerFaces';
5
- import { usePickerViewColumnAnimationContext } from './pickerVIewContext';
6
- const _PickerViewColumnItem = ({ item, index, itemHeight, itemWidth = '100%', textStyleFromParent, textStyle, hasVarDec, varContext, textProps, visibleCount, onItemLayout }) => {
5
+ import { usePickerViewColumnAnimationContext, usePickerViewStyleContext } from './pickerVIewContext';
6
+ const PickerViewColumnItem = ({ item, index, itemHeight, itemWidth = '100%', textStyle, textProps, visibleCount, onItemLayout }) => {
7
+ const textStyleFromAncestor = usePickerViewStyleContext();
7
8
  const offsetYShared = usePickerViewColumnAnimationContext();
8
9
  const facesShared = useSharedValue(createFaces(itemHeight, visibleCount));
9
10
  useEffect(() => {
@@ -14,8 +15,8 @@ const _PickerViewColumnItem = ({ item, index, itemHeight, itemWidth = '100%', te
14
15
  return {
15
16
  opacity: interpolate(offsetYShared.value, inputRange, facesShared.value.map((x) => x.opacity), Extrapolation.CLAMP),
16
17
  transform: [
17
- { rotateX: interpolate(offsetYShared.value, inputRange, facesShared.value.map((x) => x.deg), Extrapolation.CLAMP) + 'deg' },
18
18
  { translateY: interpolate(offsetYShared.value, inputRange, facesShared.value.map((x) => x.offsetY), Extrapolation.EXTEND) },
19
+ { rotateX: interpolate(offsetYShared.value, inputRange, facesShared.value.map((x) => x.deg), Extrapolation.CLAMP) + 'deg' },
19
20
  { scale: interpolate(offsetYShared.value, inputRange, facesShared.value.map((x) => x.scale), Extrapolation.EXTEND) }
20
21
  ]
21
22
  };
@@ -23,17 +24,12 @@ const _PickerViewColumnItem = ({ item, index, itemHeight, itemWidth = '100%', te
23
24
  const strKey = `picker-column-item-${index}`;
24
25
  const restProps = index === 0 ? { onLayout: onItemLayout } : {};
25
26
  const itemProps = extendObject({
26
- style: extendObject({ height: itemHeight, width: '100%' }, textStyleFromParent, textStyle, item.props.style)
27
- }, restProps);
27
+ style: extendObject({ height: itemHeight, width: '100%' }, textStyleFromAncestor, textStyle, item.props.style)
28
+ }, textProps, restProps);
28
29
  const realItem = React.cloneElement(item, itemProps);
29
30
  return (<Reanimated.View key={strKey} style={[{ height: itemHeight, width: itemWidth }, animatedStyles]}>
30
- {wrapChildren({ children: realItem }, {
31
- hasVarDec,
32
- varContext,
33
- textStyle,
34
- textProps
35
- })}
31
+ {realItem}
36
32
  </Reanimated.View>);
37
33
  };
38
- _PickerViewColumnItem.displayName = 'MpxPickerViewColumnItem';
39
- export default _PickerViewColumnItem;
34
+ PickerViewColumnItem.displayName = 'MpxPickerViewColumnItem';
35
+ export default PickerViewColumnItem;
@@ -1,19 +1,18 @@
1
1
  import React, { forwardRef, useRef, useState, useMemo, useEffect, useCallback } from 'react';
2
- import { SafeAreaView, StyleSheet } from 'react-native';
2
+ import { StyleSheet, View } from 'react-native';
3
3
  import Reanimated, { useAnimatedRef, useScrollViewOffset } from 'react-native-reanimated';
4
- import { useTransformStyle, splitStyle, splitProps, useLayout, usePrevious, isAndroid, isIOS, useDebounceCallback, useStableCallback } from './utils';
4
+ import { useTransformStyle, splitStyle, splitProps, useLayout, usePrevious, isAndroid, isIOS } from './utils';
5
5
  import useNodesRef from './useNodesRef';
6
- import PickerOverlay from './pickerViewOverlay';
6
+ import PickerIndicator from './pickerViewIndicator';
7
7
  import PickerMask from './pickerViewMask';
8
8
  import MpxPickerVIewColumnItem from './mpx-picker-view-column-item';
9
9
  import { PickerViewColumnAnimationContext } from './pickerVIewContext';
10
10
  const visibleCount = 5;
11
11
  const _PickerViewColumn = forwardRef((props, ref) => {
12
- const { columnData, columnIndex, columnStyle, initialIndex, onSelectChange, style, wrapperStyle, pickerMaskStyle, pickerOverlayStyle, 'enable-var': enableVar, 'external-var-context': externalVarContext } = props;
13
- const { normalStyle, hasVarDec, varContextRef, hasSelfPercent, setWidth, setHeight } = useTransformStyle(style, { enableVar, externalVarContext });
14
- const { textStyle: textStyleFromParent = {} } = splitStyle(columnStyle);
12
+ const { columnData, columnIndex, initialIndex, onSelectChange, style, wrapperStyle, pickerMaskStyle, pickerIndicatorStyle, 'enable-var': enableVar, 'external-var-context': externalVarContext } = props;
13
+ const { normalStyle, hasSelfPercent, setWidth, setHeight } = useTransformStyle(style, { enableVar, externalVarContext });
15
14
  const { textStyle = {} } = splitStyle(normalStyle);
16
- const { textProps } = splitProps(props);
15
+ const { textProps = {} } = splitProps(props);
17
16
  const scrollViewRef = useAnimatedRef();
18
17
  const offsetYShared = useScrollViewOffset(scrollViewRef);
19
18
  useNodesRef(props, ref, scrollViewRef, {
@@ -25,6 +24,8 @@ const _PickerViewColumn = forwardRef((props, ref) => {
25
24
  const prevScrollingInfo = useRef({ index: initialIndex, y: 0 });
26
25
  const touching = useRef(false);
27
26
  const scrolling = useRef(false);
27
+ const timerResetPosition = useRef(null);
28
+ const timerScrollTo = useRef(null);
28
29
  const activeIndex = useRef(initialIndex);
29
30
  const prevIndex = usePrevious(initialIndex);
30
31
  const prevMaxIndex = usePrevious(maxIndex);
@@ -35,9 +36,8 @@ const _PickerViewColumn = forwardRef((props, ref) => {
35
36
  setHeight,
36
37
  nodeRef: scrollViewRef
37
38
  });
38
- // console.log('[mpx-picker-view-column], render ---> columnIndex=', columnIndex, 'initialIndex=', initialIndex, 'columnData=', columnData.length, 'pickerH=', pickerH, 'itemRawH=', itemRawH, 'itemHeight=', itemHeight)
39
39
  const paddingHeight = useMemo(() => Math.round((pickerH - itemHeight) / 2), [pickerH, itemHeight]);
40
- const snapToOffsets = useMemo(() => columnData.map((_, i) => i * itemRawH), [columnData, itemRawH]);
40
+ const snapToOffsets = useMemo(() => Array.from({ length: maxIndex + 1 }, (_, i) => i * itemRawH), [maxIndex, itemRawH]);
41
41
  const contentContainerStyle = useMemo(() => {
42
42
  return [{ paddingVertical: paddingHeight }];
43
43
  }, [paddingHeight]);
@@ -45,26 +45,24 @@ const _PickerViewColumn = forwardRef((props, ref) => {
45
45
  const calc = Math.round(y / itemRawH);
46
46
  return Math.max(0, Math.min(calc, maxIndex));
47
47
  }, [itemRawH, maxIndex]);
48
- const getYofIndex = useCallback((index) => {
49
- return index * itemRawH;
50
- }, [itemRawH]);
51
- const stableResetScrollPosition = useStableCallback((y) => {
52
- // console.log('[mpx-picker-view-column], reset --->', 'columnIndex=', columnIndex, 'y=', y, touching.current, scrolling.current, itemRawH, 'snapToOffsets=', snapToOffsets)
53
- if (touching.current || scrolling.current) {
54
- return;
48
+ const clearTimerResetPosition = useCallback(() => {
49
+ if (timerResetPosition.current) {
50
+ clearTimeout(timerResetPosition.current);
51
+ timerResetPosition.current = null;
55
52
  }
56
- // needReset.current = true
57
- if (y % itemRawH !== 0) {
58
- scrolling.current = true;
59
- const targetIndex = getIndex(y);
60
- const targetY = getYofIndex(targetIndex);
61
- scrollViewRef.current?.scrollTo({ x: 0, y: targetY, animated: false });
53
+ }, []);
54
+ const clearTimerScrollTo = useCallback(() => {
55
+ if (timerScrollTo.current) {
56
+ clearTimeout(timerScrollTo.current);
57
+ timerScrollTo.current = null;
62
58
  }
63
- else {
64
- onMomentumScrollEnd({ nativeEvent: { contentOffset: { y } } });
65
- }
66
- });
67
- const debounceResetScrollPosition = useDebounceCallback(stableResetScrollPosition, 10);
59
+ }, []);
60
+ useEffect(() => {
61
+ return () => {
62
+ clearTimerResetPosition();
63
+ clearTimerScrollTo();
64
+ };
65
+ }, []);
68
66
  useEffect(() => {
69
67
  if (!scrollViewRef.current ||
70
68
  !itemRawH ||
@@ -76,65 +74,79 @@ const _PickerViewColumn = forwardRef((props, ref) => {
76
74
  maxIndex !== prevMaxIndex) {
77
75
  return;
78
76
  }
79
- setTimeout(() => {
77
+ clearTimerScrollTo();
78
+ timerScrollTo.current = setTimeout(() => {
80
79
  scrollViewRef.current?.scrollTo({
81
80
  x: 0,
82
- y: getYofIndex(initialIndex),
81
+ y: initialIndex * itemRawH,
83
82
  animated: false
84
83
  });
85
84
  }, isAndroid ? 200 : 0);
86
85
  activeIndex.current = initialIndex;
87
- }, [itemRawH, initialIndex]);
88
- const onContentSizeChange = (_w, h) => {
89
- const y = getYofIndex(initialIndex);
86
+ }, [itemRawH, maxIndex, initialIndex]);
87
+ const onContentSizeChange = useCallback((_w, h) => {
88
+ const y = initialIndex * itemRawH;
90
89
  if (y <= h) {
91
- setTimeout(() => {
90
+ clearTimerScrollTo();
91
+ timerScrollTo.current = setTimeout(() => {
92
92
  scrollViewRef.current?.scrollTo({ x: 0, y, animated: false });
93
93
  }, 0);
94
94
  }
95
- };
96
- const onItemLayout = (e) => {
95
+ }, [itemRawH, initialIndex]);
96
+ const onItemLayout = useCallback((e) => {
97
97
  const { height: rawH } = e.nativeEvent.layout;
98
98
  const roundedH = Math.round(rawH);
99
99
  if (roundedH && roundedH !== itemRawH) {
100
100
  setItemRawH(roundedH);
101
101
  }
102
- };
103
- const onScrollBeginDrag = () => {
104
- isIOS && debounceResetScrollPosition.clear();
105
- touching.current = true;
106
- prevScrollingInfo.current = {
107
- index: activeIndex.current,
108
- y: getYofIndex(activeIndex.current)
109
- };
110
- };
111
- const onScrollEndDrag = (e) => {
112
- touching.current = false;
113
- const { y } = e.nativeEvent.contentOffset;
114
- if (isIOS) {
115
- if (y >= 0 && y <= snapToOffsets[maxIndex]) {
116
- debounceResetScrollPosition(y);
117
- }
102
+ }, [itemRawH]);
103
+ const resetScrollPosition = useCallback((y) => {
104
+ if (touching.current || scrolling.current) {
105
+ return;
118
106
  }
119
- };
120
- const onMomentumScrollBegin = () => {
121
- isIOS && debounceResetScrollPosition.clear();
122
107
  scrolling.current = true;
123
- };
124
- const onMomentumScrollEnd = (e) => {
108
+ const targetIndex = getIndex(y);
109
+ scrollViewRef.current?.scrollTo({ x: 0, y: targetIndex * itemRawH, animated: false });
110
+ }, [itemRawH, getIndex]);
111
+ const onMomentumScrollBegin = useCallback(() => {
112
+ isIOS && clearTimerResetPosition();
113
+ scrolling.current = true;
114
+ }, []);
115
+ const onMomentumScrollEnd = useCallback((e) => {
125
116
  scrolling.current = false;
126
117
  const { y: scrollY } = e.nativeEvent.contentOffset;
127
- // console.log('[mpx-picker-view-column], onMomentumScrollEnd --->', 'columnIndex=', columnIndex, scrollY, itemRawH)
128
118
  if (isIOS && scrollY % itemRawH !== 0) {
129
- return debounceResetScrollPosition(scrollY);
119
+ return resetScrollPosition(scrollY);
130
120
  }
131
121
  const calcIndex = getIndex(scrollY);
132
122
  if (calcIndex !== activeIndex.current) {
133
123
  activeIndex.current = calcIndex;
134
124
  onSelectChange(calcIndex);
135
125
  }
136
- };
137
- const onScroll = (e) => {
126
+ }, [itemRawH, getIndex, onSelectChange, resetScrollPosition]);
127
+ const onScrollBeginDrag = useCallback(() => {
128
+ isIOS && clearTimerResetPosition();
129
+ touching.current = true;
130
+ prevScrollingInfo.current = {
131
+ index: activeIndex.current,
132
+ y: activeIndex.current * itemRawH
133
+ };
134
+ }, [itemRawH]);
135
+ const onScrollEndDrag = useCallback((e) => {
136
+ touching.current = false;
137
+ if (isIOS) {
138
+ const { y } = e.nativeEvent.contentOffset;
139
+ if (y % itemRawH === 0) {
140
+ onMomentumScrollEnd({ nativeEvent: { contentOffset: { y } } });
141
+ }
142
+ else if (y > 0 && y < snapToOffsets[maxIndex]) {
143
+ timerResetPosition.current = setTimeout(() => {
144
+ resetScrollPosition(y);
145
+ }, 10);
146
+ }
147
+ }
148
+ }, [itemRawH, maxIndex, snapToOffsets, onMomentumScrollEnd, resetScrollPosition]);
149
+ const onScroll = useCallback((e) => {
138
150
  // 全局注册的振动触感 hook
139
151
  const pickerVibrate = global.__mpx?.config?.rnConfig?.pickerVibrate;
140
152
  if (typeof pickerVibrate !== 'function') {
@@ -148,16 +160,16 @@ const _PickerViewColumn = forwardRef((props, ref) => {
148
160
  if (currentId !== prevIndex) {
149
161
  prevScrollingInfo.current = {
150
162
  index: currentId,
151
- y: getYofIndex(currentId)
163
+ y: currentId * itemRawH
152
164
  };
153
165
  // vibrateShort({ type: 'selection' })
154
166
  pickerVibrate();
155
167
  }
156
168
  }
157
169
  }
158
- };
170
+ }, [itemRawH, getIndex]);
159
171
  const renderInnerchild = () => columnData.map((item, index) => {
160
- return (<MpxPickerVIewColumnItem key={index} item={item} index={index} itemHeight={itemHeight} textStyleFromParent={textStyleFromParent} textStyle={textStyle} hasVarDec={hasVarDec} varContext={varContextRef.current} textProps={textProps} visibleCount={visibleCount} onItemLayout={onItemLayout}/>);
172
+ return (<MpxPickerVIewColumnItem key={index} item={item} index={index} itemHeight={itemHeight} textStyle={textStyle} textProps={textProps} visibleCount={visibleCount} onItemLayout={onItemLayout}/>);
161
173
  });
162
174
  const renderScollView = () => {
163
175
  return (<PickerViewColumnAnimationContext.Provider value={offsetYShared}>
@@ -166,13 +178,13 @@ const _PickerViewColumn = forwardRef((props, ref) => {
166
178
  </Reanimated.ScrollView>
167
179
  </PickerViewColumnAnimationContext.Provider>);
168
180
  };
169
- const renderOverlay = () => (<PickerOverlay itemHeight={itemHeight} overlayItemStyle={pickerOverlayStyle}/>);
181
+ const renderIndicator = () => (<PickerIndicator itemHeight={itemHeight} indicatorItemStyle={pickerIndicatorStyle}/>);
170
182
  const renderMask = () => (<PickerMask itemHeight={itemHeight} maskContainerStyle={pickerMaskStyle}/>);
171
- return (<SafeAreaView style={[styles.wrapper, normalStyle]}>
183
+ return (<View style={[styles.wrapper, normalStyle]}>
172
184
  {renderScollView()}
173
185
  {renderMask()}
174
- {renderOverlay()}
175
- </SafeAreaView>);
186
+ {renderIndicator()}
187
+ </View>);
176
188
  });
177
189
  const styles = StyleSheet.create({
178
190
  wrapper: { display: 'flex', flex: 1 }
@@ -2,7 +2,8 @@ import { View } from 'react-native';
2
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, extendObject } from './utils';
5
+ import { useLayout, splitProps, splitStyle, wrapChildren, useTransformStyle, extendObject } from './utils';
6
+ import { PickerViewStyleContext } from './pickerVIewContext';
6
7
  const styles = {
7
8
  wrapper: {
8
9
  display: 'flex',
@@ -15,16 +16,13 @@ const styles = {
15
16
  };
16
17
  const DefaultPickerItemH = 36;
17
18
  const _PickerView = forwardRef((props, ref) => {
18
- const { children, value = [], bindchange, style, 'enable-var': enableVar, 'external-var-context': externalVarContext } = props;
19
- const indicatorStyle = parseInlineStyle(props['indicator-style']);
20
- const pickerMaskStyle = parseInlineStyle(props['mask-style']);
21
- const { height: indicatorH, ...pickerOverlayStyle } = indicatorStyle;
19
+ const { children, value = [], bindchange, style, 'indicator-style': indicatorStyle = {}, 'mask-style': pickerMaskStyle = {}, 'enable-var': enableVar, 'external-var-context': externalVarContext } = props;
20
+ const { height: indicatorH, ...pickerIndicatorStyle } = indicatorStyle;
22
21
  const nodeRef = useRef(null);
23
22
  const cloneRef = useRef(null);
24
23
  const activeValueRef = useRef(value);
25
24
  activeValueRef.current = value.slice();
26
25
  const snapActiveValueRef = useRef(null);
27
- console.log('[mpx-picker-view] value=', value, Date.now());
28
26
  const { normalStyle, hasVarDec, varContextRef, hasSelfPercent, setWidth, setHeight } = useTransformStyle(style, { enableVar, externalVarContext });
29
27
  useNodesRef(props, ref, nodeRef, {
30
28
  style: normalStyle
@@ -35,8 +33,7 @@ const _PickerView = forwardRef((props, ref) => {
35
33
  const onSelectChange = (columnIndex, selectedIndex) => {
36
34
  const activeValue = activeValueRef.current;
37
35
  activeValue[columnIndex] = selectedIndex;
38
- console.log('[mpx-picker-view], onSelectChange ---> columnIndex=', columnIndex, 'selectedIndex=', selectedIndex, 'activeValue=', activeValue);
39
- const eventData = getCustomEvent('change', {}, { detail: { value: activeValue, source: 'change' }, layoutRef });
36
+ const eventData = getCustomEvent('change', {}, { detail: { value: activeValue.slice(), source: 'change' }, layoutRef });
40
37
  bindchange?.(eventData);
41
38
  snapActiveValueRef.current = activeValueRef.current;
42
39
  };
@@ -45,8 +42,7 @@ const _PickerView = forwardRef((props, ref) => {
45
42
  };
46
43
  const onInitialChange = (isInvalid, value) => {
47
44
  if (isInvalid || !snapActiveValueRef.current || hasDiff(snapActiveValueRef.current, value)) {
48
- console.log('[mpx-picker-view], onInitialChange ===> value=', value);
49
- const eventData = getCustomEvent('change', {}, { detail: { value, source: 'change' }, layoutRef });
45
+ const eventData = getCustomEvent('change', {}, { detail: { value: value.slice(), source: 'change' }, layoutRef });
50
46
  bindchange?.(eventData);
51
47
  snapActiveValueRef.current = value.slice();
52
48
  }
@@ -58,7 +54,13 @@ const _PickerView = forwardRef((props, ref) => {
58
54
  overflow: 'hidden'
59
55
  }),
60
56
  layoutProps
61
- }), ['enable-offset'], { layoutRef });
57
+ }), [
58
+ 'enable-offset',
59
+ 'indicator-style',
60
+ 'indicator-class',
61
+ 'mask-style',
62
+ 'mask-class'
63
+ ], { layoutRef });
62
64
  const renderColumn = (child, index, columnData, initialIndex) => {
63
65
  const childProps = child?.props || {};
64
66
  const wrappedProps = extendObject({}, childProps, {
@@ -70,10 +72,9 @@ const _PickerView = forwardRef((props, ref) => {
70
72
  height: normalStyle?.height || DefaultPickerItemH,
71
73
  itemHeight: indicatorH || DefaultPickerItemH
72
74
  },
73
- columnStyle: normalStyle,
74
75
  onSelectChange: onSelectChange.bind(null, index),
75
76
  initialIndex,
76
- pickerOverlayStyle,
77
+ pickerIndicatorStyle,
77
78
  pickerMaskStyle
78
79
  });
79
80
  const realElement = React.cloneElement(child, wrappedProps);
@@ -114,9 +115,11 @@ const _PickerView = forwardRef((props, ref) => {
114
115
  onInitialChange(isInvalid, validValue);
115
116
  return renderColumns;
116
117
  };
117
- return (<View {...innerProps}>
118
- <View style={[styles.wrapper]}>{renderPickerColumns()}</View>
119
- </View>);
118
+ return (<PickerViewStyleContext.Provider value={textStyle}>
119
+ <View {...innerProps}>
120
+ <View style={[styles.wrapper]}>{renderPickerColumns()}</View>
121
+ </View>
122
+ </PickerViewStyleContext.Provider>);
120
123
  });
121
124
  _PickerView.displayName = 'MpxPickerView';
122
125
  export default _PickerView;
@@ -2,7 +2,7 @@
2
2
  * ✔ enable
3
3
  */
4
4
  import { createElement, Fragment } from 'react';
5
- import Portal from './mpx-portal';
5
+ import { Portal } from '@ant-design/react-native';
6
6
  import { warn } from '@mpxjs/utils';
7
7
  const _RootPortal = (props) => {
8
8
  const { children, enable = true } = props;
@@ -201,6 +201,8 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
201
201
  layoutRef
202
202
  }, props));
203
203
  updateScrollOptions(e, { scrollLeft, scrollTop });
204
+ onStartReached(e);
205
+ onEndReached(e);
204
206
  }
205
207
  function onScrollEnd(e) {
206
208
  const { bindscrollend } = props;