@mpxjs/webpack-plugin 2.10.4-beta.2 → 2.10.4-beta.20

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 (88) hide show
  1. package/lib/parser.js +1 -1
  2. package/lib/platform/json/wx/index.js +0 -1
  3. package/lib/platform/style/wx/index.js +22 -21
  4. package/lib/platform/template/wx/component-config/button.js +1 -1
  5. package/lib/platform/template/wx/component-config/index.js +5 -1
  6. package/lib/platform/template/wx/component-config/input.js +1 -1
  7. package/lib/platform/template/wx/component-config/sticky-header.js +23 -0
  8. package/lib/platform/template/wx/component-config/sticky-section.js +23 -0
  9. package/lib/react/processJSON.js +7 -6
  10. package/lib/runtime/components/react/context.ts +12 -3
  11. package/lib/runtime/components/react/dist/context.js +4 -1
  12. package/lib/runtime/components/react/dist/event.config.js +0 -2
  13. package/lib/runtime/components/react/dist/getInnerListeners.js +127 -153
  14. package/lib/runtime/components/react/dist/mpx-button.jsx +4 -5
  15. package/lib/runtime/components/react/dist/mpx-canvas/index.jsx +3 -4
  16. package/lib/runtime/components/react/dist/mpx-checkbox-group.jsx +2 -2
  17. package/lib/runtime/components/react/dist/mpx-checkbox.jsx +2 -3
  18. package/lib/runtime/components/react/dist/mpx-form.jsx +2 -2
  19. package/lib/runtime/components/react/dist/mpx-icon/index.jsx +2 -2
  20. package/lib/runtime/components/react/dist/mpx-image.jsx +2 -2
  21. package/lib/runtime/components/react/dist/mpx-input.jsx +8 -5
  22. package/lib/runtime/components/react/dist/mpx-keyboard-avoiding-view.jsx +23 -30
  23. package/lib/runtime/components/react/dist/mpx-label.jsx +2 -3
  24. package/lib/runtime/components/react/dist/mpx-movable-area.jsx +2 -2
  25. package/lib/runtime/components/react/dist/mpx-movable-view.jsx +1 -1
  26. package/lib/runtime/components/react/dist/mpx-navigator.jsx +11 -3
  27. package/lib/runtime/components/react/dist/mpx-picker/index.jsx +2 -2
  28. package/lib/runtime/components/react/dist/mpx-picker-view/index.jsx +2 -3
  29. package/lib/runtime/components/react/dist/mpx-picker-view-column/index.jsx +3 -3
  30. package/lib/runtime/components/react/dist/mpx-radio-group.jsx +2 -2
  31. package/lib/runtime/components/react/dist/mpx-radio.jsx +2 -3
  32. package/lib/runtime/components/react/dist/mpx-rich-text/index.jsx +2 -2
  33. package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +32 -16
  34. package/lib/runtime/components/react/dist/mpx-simple-text.jsx +3 -2
  35. package/lib/runtime/components/react/dist/mpx-simple-view.jsx +3 -3
  36. package/lib/runtime/components/react/dist/mpx-sticky-header.jsx +115 -0
  37. package/lib/runtime/components/react/dist/mpx-sticky-section.jsx +45 -0
  38. package/lib/runtime/components/react/dist/mpx-swiper-item.jsx +5 -6
  39. package/lib/runtime/components/react/dist/mpx-swiper.jsx +99 -37
  40. package/lib/runtime/components/react/dist/mpx-switch.jsx +3 -5
  41. package/lib/runtime/components/react/dist/mpx-text.jsx +4 -7
  42. package/lib/runtime/components/react/dist/mpx-video.jsx +2 -2
  43. package/lib/runtime/components/react/dist/mpx-view.jsx +23 -9
  44. package/lib/runtime/components/react/dist/mpx-web-view.jsx +13 -13
  45. package/lib/runtime/components/react/dist/useAnimationHooks.js +26 -4
  46. package/lib/runtime/components/react/dist/utils.jsx +12 -1
  47. package/lib/runtime/components/react/event.config.ts +1 -8
  48. package/lib/runtime/components/react/getInnerListeners.ts +146 -192
  49. package/lib/runtime/components/react/mpx-button.tsx +7 -7
  50. package/lib/runtime/components/react/mpx-canvas/index.tsx +23 -15
  51. package/lib/runtime/components/react/mpx-checkbox-group.tsx +4 -3
  52. package/lib/runtime/components/react/mpx-checkbox.tsx +8 -9
  53. package/lib/runtime/components/react/mpx-form.tsx +25 -19
  54. package/lib/runtime/components/react/mpx-icon/index.tsx +4 -3
  55. package/lib/runtime/components/react/mpx-image.tsx +4 -3
  56. package/lib/runtime/components/react/mpx-input.tsx +14 -9
  57. package/lib/runtime/components/react/mpx-keyboard-avoiding-view.tsx +31 -42
  58. package/lib/runtime/components/react/mpx-label.tsx +4 -5
  59. package/lib/runtime/components/react/mpx-movable-area.tsx +22 -13
  60. package/lib/runtime/components/react/mpx-movable-view.tsx +47 -40
  61. package/lib/runtime/components/react/mpx-navigator.tsx +4 -6
  62. package/lib/runtime/components/react/mpx-picker/index.tsx +7 -4
  63. package/lib/runtime/components/react/mpx-picker-view/index.tsx +17 -14
  64. package/lib/runtime/components/react/mpx-picker-view-column/index.tsx +3 -3
  65. package/lib/runtime/components/react/mpx-radio-group.tsx +4 -3
  66. package/lib/runtime/components/react/mpx-radio.tsx +8 -9
  67. package/lib/runtime/components/react/mpx-rich-text/index.tsx +15 -6
  68. package/lib/runtime/components/react/mpx-scroll-view.tsx +97 -66
  69. package/lib/runtime/components/react/mpx-simple-text.tsx +10 -3
  70. package/lib/runtime/components/react/mpx-simple-view.tsx +10 -4
  71. package/lib/runtime/components/react/mpx-sticky-header.tsx +179 -0
  72. package/lib/runtime/components/react/mpx-sticky-section.tsx +96 -0
  73. package/lib/runtime/components/react/mpx-swiper-item.tsx +32 -25
  74. package/lib/runtime/components/react/mpx-swiper.tsx +166 -88
  75. package/lib/runtime/components/react/mpx-switch.tsx +19 -14
  76. package/lib/runtime/components/react/mpx-text.tsx +16 -13
  77. package/lib/runtime/components/react/mpx-video.tsx +34 -33
  78. package/lib/runtime/components/react/mpx-view.tsx +41 -17
  79. package/lib/runtime/components/react/mpx-web-view.tsx +12 -12
  80. package/lib/runtime/components/react/types/getInnerListeners.d.ts +65 -35
  81. package/lib/runtime/components/react/useAnimationHooks.ts +29 -9
  82. package/lib/runtime/components/react/utils.tsx +12 -1
  83. package/lib/runtime/components/web/mpx-scroll-view.vue +21 -4
  84. package/lib/runtime/components/web/mpx-sticky-header.vue +91 -0
  85. package/lib/runtime/components/web/mpx-sticky-section.vue +15 -0
  86. package/lib/script-setup-compiler/index.js +27 -5
  87. package/lib/template-compiler/compiler.js +3 -2
  88. package/package.json +1 -1
package/lib/parser.js CHANGED
@@ -14,7 +14,7 @@ module.exports = (content, { filePath, needMap, mode, env }) => {
14
14
  output = compiler.parseComponent(content, {
15
15
  mode,
16
16
  filePath,
17
- // pad: 'line', // stylus编译遇到大量空行时会出现栈溢出,故注释掉
17
+ pad: 'line',
18
18
  env
19
19
  })
20
20
  if (needMap) {
@@ -354,7 +354,6 @@ module.exports = function getSpec ({ warn, error }) {
354
354
  },
355
355
  {
356
356
  test: 'preloadRule',
357
- tt: deletePath(),
358
357
  jd: deletePath()
359
358
  },
360
359
  {
@@ -184,8 +184,9 @@ module.exports = function getSpec ({ warn, error }) {
184
184
  'border-top': ['borderTopWidth', 'borderTopStyle', 'borderTopColor'],
185
185
  // 仅支持 width | style | color 这种排序
186
186
  'border-bottom': ['borderBottomWidth', 'borderBottomStyle', 'borderBottomColor'],
187
+ // 0.76 及以上版本RN支持 box-shadow,实测0.77版本drn红米note12pro Android12 不支持内阴影,其他表现和web一致
187
188
  // 仅支持 offset-x | offset-y | blur-radius | color 排序
188
- 'box-shadow': ['shadowOffset.width', 'shadowOffset.height', 'shadowRadius', 'shadowColor'],
189
+ // 'box-shadow': ['shadowOffset.width', 'shadowOffset.height', 'shadowRadius', 'shadowColor'],
189
190
  // 仅支持 text-decoration-line text-decoration-style text-decoration-color 这种格式
190
191
  'text-decoration': ['textDecorationLine', 'textDecorationStyle', 'textDecorationColor'],
191
192
  // flex-grow | flex-shrink | flex-basis
@@ -525,20 +526,20 @@ module.exports = function getSpec ({ warn, error }) {
525
526
  return { prop, value: values[0].trim() }
526
527
  }
527
528
 
528
- const formatBoxShadow = ({ prop, value, selector }, { mode }) => {
529
- value = value.trim()
530
- if (value === 'none') {
531
- return false
532
- }
533
- const cssMap = formatAbbreviation({ prop, value, selector }, { mode })
534
- if (mode === 'android' || mode === 'harmony') return cssMap
535
- // ios 阴影需要额外设置 shadowOpacity=1
536
- cssMap.push({
537
- prop: 'shadowOpacity',
538
- value: 1
539
- })
540
- return cssMap
541
- }
529
+ // const formatBoxShadow = ({ prop, value, selector }, { mode }) => {
530
+ // value = value.trim()
531
+ // if (value === 'none') {
532
+ // return false
533
+ // }
534
+ // const cssMap = formatAbbreviation({ prop, value, selector }, { mode })
535
+ // if (mode === 'android' || mode === 'harmony') return cssMap
536
+ // // ios 阴影需要额外设置 shadowOpacity=1
537
+ // cssMap.push({
538
+ // prop: 'shadowOpacity',
539
+ // value: 1
540
+ // })
541
+ // return cssMap
542
+ // }
542
543
 
543
544
  return {
544
545
  supportedModes: ['ios', 'android', 'harmony'],
@@ -579,12 +580,12 @@ module.exports = function getSpec ({ warn, error }) {
579
580
  android: formatFontFamily,
580
581
  harmony: formatFontFamily
581
582
  },
582
- {
583
- test: 'box-shadow',
584
- ios: formatBoxShadow,
585
- android: formatBoxShadow,
586
- harmony: formatBoxShadow
587
- },
583
+ // {
584
+ // test: 'box-shadow',
585
+ // ios: formatBoxShadow,
586
+ // android: formatBoxShadow,
587
+ // harmony: formatBoxShadow
588
+ // },
588
589
  // 通用的简写格式匹配
589
590
  {
590
591
  test: new RegExp('^(' + Object.keys(AbbreviationMap).join('|') + ')$'),
@@ -124,7 +124,7 @@ module.exports = function ({ print }) {
124
124
  if (isMustache(value)) {
125
125
  ttValueLog({ name, value })
126
126
  } else {
127
- const supportList = ['share', 'getPhoneNumber', 'contact', 'im', 'openSetting']
127
+ const supportList = ['share', 'getPhoneNumber', 'contact', 'im', 'openSetting', 'addShortcut']
128
128
  if (value && supportList.indexOf(value) === -1) {
129
129
  ttValueLogError({ name, value })
130
130
  }
@@ -42,6 +42,8 @@ const wxs = require('./wxs')
42
42
  const component = require('./component')
43
43
  const fixComponentName = require('./fix-component-name')
44
44
  const rootPortal = require('./root-portal')
45
+ const stickyHeader = require('./sticky-header')
46
+ const stickySection = require('./sticky-section')
45
47
 
46
48
  module.exports = function getComponentConfigs ({ warn, error }) {
47
49
  /**
@@ -125,6 +127,8 @@ module.exports = function getComponentConfigs ({ warn, error }) {
125
127
  hyphenTagName({ print }),
126
128
  label({ print }),
127
129
  component(),
128
- rootPortal({ print })
130
+ rootPortal({ print }),
131
+ stickyHeader({ print }),
132
+ stickySection({ print })
129
133
  ]
130
134
  }
@@ -51,7 +51,7 @@ module.exports = function ({ print }) {
51
51
  swan: baiduPropLog
52
52
  },
53
53
  {
54
- test: /^(placeholder-class|auto-focus|confirm-type|confirm-hold|adjust-position|hold-keyboard)$/,
54
+ test: /^(auto-focus|confirm-type|confirm-hold|adjust-position|hold-keyboard)$/,
55
55
  tt: ttPropLog
56
56
  },
57
57
  {
@@ -0,0 +1,23 @@
1
+ const TAG_NAME = 'sticky-header'
2
+
3
+ module.exports = function ({ print }) {
4
+ return {
5
+ test: TAG_NAME,
6
+ android (tag, { el }) {
7
+ el.isBuiltIn = true
8
+ return 'mpx-sticky-header'
9
+ },
10
+ ios (tag, { el }) {
11
+ el.isBuiltIn = true
12
+ return 'mpx-sticky-header'
13
+ },
14
+ harmony (tag, { el }) {
15
+ el.isBuiltIn = true
16
+ return 'mpx-sticky-header'
17
+ },
18
+ web (tag, { el }) {
19
+ el.isBuiltIn = true
20
+ return 'mpx-sticky-header'
21
+ }
22
+ }
23
+ }
@@ -0,0 +1,23 @@
1
+ const TAG_NAME = 'sticky-section'
2
+
3
+ module.exports = function ({ print }) {
4
+ return {
5
+ test: TAG_NAME,
6
+ android (tag, { el }) {
7
+ el.isBuiltIn = true
8
+ return 'mpx-sticky-section'
9
+ },
10
+ ios (tag, { el }) {
11
+ el.isBuiltIn = true
12
+ return 'mpx-sticky-section'
13
+ },
14
+ harmony (tag, { el }) {
15
+ el.isBuiltIn = true
16
+ return 'mpx-sticky-section'
17
+ },
18
+ web (tag, { el }) {
19
+ el.isBuiltIn = true
20
+ return 'mpx-sticky-section'
21
+ }
22
+ }
23
+ }
@@ -113,13 +113,14 @@ module.exports = function (jsonContent, {
113
113
  }
114
114
 
115
115
  if (ctorType === 'page') {
116
- const keysToExtract = ['navigationStyle']
116
+ // const keysToExtract = ['navigationStyle']
117
117
  const configObj = {}
118
- keysToExtract.forEach(key => {
119
- if (jsonObj[key]) {
120
- configObj[key] = jsonObj[key]
121
- }
122
- })
118
+ // 暂时先不注入数据,后续如需要使用再用
119
+ // keysToExtract.forEach(key => {
120
+ // if (jsonObj[key]) {
121
+ // configObj[key] = jsonObj[key]
122
+ // }
123
+ // })
123
124
  loaderContext._module.addPresentationalDependency(new RecordPageConfigsMapDependency(parseRequest(loaderContext.resource).resourcePath, configObj))
124
125
  }
125
126
 
@@ -1,5 +1,6 @@
1
1
  import { createContext, Dispatch, MutableRefObject, SetStateAction } from 'react'
2
- import { NativeSyntheticEvent } from 'react-native'
2
+ import { NativeSyntheticEvent, Animated } from 'react-native'
3
+ import { noop } from '@mpxjs/utils'
3
4
 
4
5
  export type LabelContextValue = MutableRefObject<{
5
6
  triggerChange: (evt: NativeSyntheticEvent<TouchEvent>) => void
@@ -42,7 +43,8 @@ export interface PortalContextValue {
42
43
  }
43
44
 
44
45
  export interface ScrollViewContextValue {
45
- gestureRef: React.RefObject<any> | null
46
+ gestureRef: React.RefObject<any> | null,
47
+ scrollOffset: Animated.Value
46
48
  }
47
49
 
48
50
  export interface RouteContextValue {
@@ -50,6 +52,11 @@ export interface RouteContextValue {
50
52
  navigation: Record<string, any>
51
53
  }
52
54
 
55
+ export interface StickyContextValue {
56
+ registerStickyHeader: Function,
57
+ unregisterStickyHeader: Function
58
+ }
59
+
53
60
  export const MovableAreaContext = createContext({ width: 0, height: 0 })
54
61
 
55
62
  export const FormContext = createContext<FormContextValue | null>(null)
@@ -72,6 +79,8 @@ export const SwiperContext = createContext({})
72
79
 
73
80
  export const KeyboardAvoidContext = createContext<KeyboardAvoidContextValue | null>(null)
74
81
 
75
- export const ScrollViewContext = createContext<ScrollViewContextValue>({ gestureRef: null })
82
+ export const ScrollViewContext = createContext<ScrollViewContextValue>({ gestureRef: null, scrollOffset: new Animated.Value(0) })
76
83
 
77
84
  export const PortalContext = createContext<PortalContextValue>(null as any)
85
+
86
+ export const StickyContext = createContext<StickyContextValue>({ registerStickyHeader: noop, unregisterStickyHeader: noop })
@@ -1,4 +1,6 @@
1
1
  import { createContext } from 'react';
2
+ import { Animated } from 'react-native';
3
+ import { noop } from '@mpxjs/utils';
2
4
  export const MovableAreaContext = createContext({ width: 0, height: 0 });
3
5
  export const FormContext = createContext(null);
4
6
  export const CheckboxGroupContext = createContext(null);
@@ -10,5 +12,6 @@ export const IntersectionObserverContext = createContext(null);
10
12
  export const RouteContext = createContext(null);
11
13
  export const SwiperContext = createContext({});
12
14
  export const KeyboardAvoidContext = createContext(null);
13
- export const ScrollViewContext = createContext({ gestureRef: null });
15
+ export const ScrollViewContext = createContext({ gestureRef: null, scrollOffset: new Animated.Value(0) });
14
16
  export const PortalContext = createContext(null);
17
+ export const StickyContext = createContext({ registerStickyHeader: noop, unregisterStickyHeader: noop });
@@ -1,5 +1,3 @@
1
- export const TAP_EVENTS = ['bindtap', 'catchtap', 'capture-bindtap', 'capture-catchtap'];
2
- export const LONGPRESS_EVENTS = ['bindlongpress', 'catchlongpress', 'capture-bindlongpress', 'capture-catchlongpress'];
3
1
  const eventConfigMap = {
4
2
  bindtap: { bitFlag: '0', events: ['onTouchStart', 'onTouchMove', 'onTouchEnd'] },
5
3
  bindlongpress: { bitFlag: '1', events: ['onTouchStart', 'onTouchMove', 'onTouchEnd', 'onTouchCancel'] },
@@ -1,21 +1,22 @@
1
1
  import { useRef, useMemo } from 'react';
2
- import { hasOwn, collectDataset } from '@mpxjs/utils';
2
+ import { collectDataset } from '@mpxjs/utils';
3
3
  import { omit, extendObject, useNavigation } from './utils';
4
- import eventConfigMap, { TAP_EVENTS, LONGPRESS_EVENTS } from './event.config';
4
+ import eventConfigMap from './event.config';
5
5
  const globalEventState = {
6
6
  needPress: true
7
7
  };
8
- const getTouchEvent = (type, event, props, config, navigation) => {
8
+ const getTouchEvent = (type, event, config) => {
9
+ const { navigation, propsRef, layoutRef } = config;
10
+ const props = propsRef.current;
9
11
  const { y: navigationY = 0 } = navigation?.layout || {};
10
12
  const nativeEvent = event.nativeEvent;
11
13
  const { timestamp, pageX, pageY, touches, changedTouches } = nativeEvent;
12
14
  const { id } = props;
13
- const { layoutRef } = config;
14
15
  const currentTarget = extendObject({}, event.currentTarget, {
15
16
  id: id || '',
16
17
  dataset: collectDataset(props),
17
- offsetLeft: layoutRef?.current?.offsetLeft || 0,
18
- offsetTop: layoutRef?.current?.offsetTop || 0
18
+ offsetLeft: layoutRef.current?.offsetLeft || 0,
19
+ offsetTop: layoutRef.current?.offsetTop || 0
19
20
  });
20
21
  const pendingProps = event._targetInst?.pendingProps || {};
21
22
  const target = extendObject({}, event.target, {
@@ -70,150 +71,107 @@ export const getCustomEvent = (type = '', oe = {}, { detail = {}, layoutRef }, p
70
71
  preventDefault: oe.preventDefault
71
72
  });
72
73
  };
73
- function handleEmitEvent(events, type, oe, propsRef, config, navigation) {
74
- events.forEach((event) => {
75
- if (propsRef.current[event]) {
76
- const match = /^(catch|capture-catch):?(.*?)(?:\.(.*))?$/.exec(event);
77
- // 检查是否已经被上层的 catch 阻止
78
- if ((type === 'tap' || type === 'longpress') && oe._stoppedEventTypes?.has(type)) {
79
- return;
80
- }
81
- if (match) {
82
- const eventBase = match[2] || '';
83
- if (eventBase === 'tap' || eventBase === 'longpress') {
84
- // 为 tap、longpress 添加标记,影响后续的冒泡
85
- if (!oe._stoppedEventTypes) {
86
- oe._stoppedEventTypes = new Set();
87
- }
88
- oe._stoppedEventTypes.add(eventBase);
89
- }
90
- else {
91
- // 原生 touch 事件使用 stopPropagation
92
- oe.stopPropagation();
93
- }
94
- }
95
- propsRef.current[event](getTouchEvent(type, oe, propsRef.current, config, navigation));
74
+ function handleEmitEvent(name, e, type, eventConfig) {
75
+ const { propsRef } = eventConfig;
76
+ const eventCfg = eventConfig[name];
77
+ if (eventCfg) {
78
+ if (eventCfg.hasCatch && name !== 'tap' && name !== 'longpress') {
79
+ e.stopPropagation();
96
80
  }
97
- });
81
+ eventCfg[type].forEach((event) => {
82
+ propsRef.current[event]?.(getTouchEvent(name, e, eventConfig));
83
+ });
84
+ }
98
85
  }
99
86
  function checkIsNeedPress(e, type, ref) {
100
87
  const tapDetailInfo = ref.current.mpxPressInfo.detail || { x: 0, y: 0 };
101
- const nativeEvent = e.nativeEvent;
102
- const currentPageX = nativeEvent.changedTouches[0].pageX;
103
- const currentPageY = nativeEvent.changedTouches[0].pageY;
88
+ const currentPageX = e.nativeEvent.changedTouches[0].pageX;
89
+ const currentPageY = e.nativeEvent.changedTouches[0].pageY;
104
90
  if (Math.abs(currentPageX - tapDetailInfo.x) > 3 ||
105
91
  Math.abs(currentPageY - tapDetailInfo.y) > 3) {
106
92
  globalEventState.needPress = false;
107
- ref.current.startTimer[type] &&
108
- clearTimeout(ref.current.startTimer[type]);
93
+ ref.current.startTimer[type] && clearTimeout(ref.current.startTimer[type]);
109
94
  ref.current.startTimer[type] = null;
110
95
  }
111
96
  }
112
- function handleTouchstart(e, type, ref, propsRef, config, navigation) {
97
+ function handleTouchstart(e, type, eventConfig) {
98
+ // 阻止事件被释放放回对象池,导致对象复用 _stoppedEventTypes 状态被保留
113
99
  e.persist();
114
- const bubbleTouchEvent = ['catchtouchstart', 'bindtouchstart'];
115
- const bubblePressEvent = ['catchlongpress', 'bindlongpress'];
116
- const captureTouchEvent = [
117
- 'capture-catchtouchstart',
118
- 'capture-bindtouchstart'
119
- ];
120
- const capturePressEvent = [
121
- 'capture-catchlongpress',
122
- 'capture-bindlongpress'
123
- ];
124
- ref.current.startTimer[type] = null;
100
+ const { innerRef } = eventConfig;
125
101
  globalEventState.needPress = true;
126
- const nativeEvent = e.nativeEvent;
127
- ref.current.mpxPressInfo.detail = {
128
- x: nativeEvent.changedTouches[0].pageX,
129
- y: nativeEvent.changedTouches[0].pageY
102
+ innerRef.current.mpxPressInfo.detail = {
103
+ x: e.nativeEvent.changedTouches[0].pageX,
104
+ y: e.nativeEvent.changedTouches[0].pageY
130
105
  };
131
- const currentTouchEvent = type === 'bubble' ? bubbleTouchEvent : captureTouchEvent;
132
- const currentPressEvent = type === 'bubble' ? bubblePressEvent : capturePressEvent;
133
- handleEmitEvent(currentTouchEvent, 'touchstart', e, propsRef, config, navigation);
134
- if (LONGPRESS_EVENTS.some(eventName => propsRef.current[eventName])) {
135
- ref.current.startTimer[type] = setTimeout(() => {
106
+ handleEmitEvent('touchstart', e, type, eventConfig);
107
+ if (eventConfig.longpress) {
108
+ if (e._stoppedEventTypes?.has('longpress')) {
109
+ return;
110
+ }
111
+ if (eventConfig.longpress.hasCatch) {
112
+ e._stoppedEventTypes = e._stoppedEventTypes || new Set();
113
+ e._stoppedEventTypes.add('longpress');
114
+ }
115
+ innerRef.current.startTimer[type] && clearTimeout(innerRef.current.startTimer[type]);
116
+ innerRef.current.startTimer[type] = setTimeout(() => {
136
117
  // 只要触发过longpress, 全局就不再触发tap
137
118
  globalEventState.needPress = false;
138
- handleEmitEvent(currentPressEvent, 'longpress', e, propsRef, config, navigation);
119
+ handleEmitEvent('longpress', e, type, eventConfig);
139
120
  }, 350);
140
121
  }
141
122
  }
142
- function handleTouchmove(e, type, ref, propsRef, config, navigation) {
143
- const bubbleTouchEvent = ['catchtouchmove', 'bindtouchmove'];
144
- const captureTouchEvent = [
145
- 'capture-catchtouchmove',
146
- 'capture-bindtouchmove'
147
- ];
148
- const currentTouchEvent = type === 'bubble' ? bubbleTouchEvent : captureTouchEvent;
149
- handleEmitEvent(currentTouchEvent, 'touchmove', e, propsRef, config, navigation);
150
- if (TAP_EVENTS.some(eventName => propsRef.current[eventName])) {
151
- checkIsNeedPress(e, type, ref);
123
+ function handleTouchmove(e, type, eventConfig) {
124
+ const { innerRef } = eventConfig;
125
+ handleEmitEvent('touchmove', e, type, eventConfig);
126
+ if (eventConfig.tap) {
127
+ checkIsNeedPress(e, type, innerRef);
152
128
  }
153
129
  }
154
- function handleTouchend(e, type, ref, propsRef, config, navigation) {
155
- // move event may not be triggered
156
- if (TAP_EVENTS.some(eventName => propsRef.current[eventName])) {
157
- checkIsNeedPress(e, type, ref);
158
- }
159
- const bubbleTouchEvent = ['catchtouchend', 'bindtouchend'];
160
- const bubbleTapEvent = ['catchtap', 'bindtap'];
161
- const captureTouchEvent = [
162
- 'capture-catchtouchend',
163
- 'capture-bindtouchend'
164
- ];
165
- const captureTapEvent = ['capture-catchtap', 'capture-bindtap'];
166
- const currentTouchEvent = type === 'bubble' ? bubbleTouchEvent : captureTouchEvent;
167
- const currentTapEvent = type === 'bubble' ? bubbleTapEvent : captureTapEvent;
168
- ref.current.startTimer[type] &&
169
- clearTimeout(ref.current.startTimer[type]);
170
- ref.current.startTimer[type] = null;
171
- handleEmitEvent(currentTouchEvent, 'touchend', e, propsRef, config, navigation);
172
- if (globalEventState.needPress) {
173
- if (type === 'bubble' && config.disableTap) {
130
+ function handleTouchend(e, type, eventConfig) {
131
+ const { innerRef, disableTap } = eventConfig;
132
+ handleEmitEvent('touchend', e, type, eventConfig);
133
+ innerRef.current.startTimer[type] && clearTimeout(innerRef.current.startTimer[type]);
134
+ if (eventConfig.tap) {
135
+ checkIsNeedPress(e, type, innerRef);
136
+ if (!globalEventState.needPress || (type === 'bubble' && disableTap) || e._stoppedEventTypes?.has('tap')) {
174
137
  return;
175
138
  }
176
- handleEmitEvent(currentTapEvent, 'tap', e, propsRef, config, navigation);
139
+ if (eventConfig.tap.hasCatch) {
140
+ e._stoppedEventTypes = e._stoppedEventTypes || new Set();
141
+ e._stoppedEventTypes.add('tap');
142
+ }
143
+ handleEmitEvent('tap', e, type, eventConfig);
177
144
  }
178
145
  }
179
- function handleTouchcancel(e, type, ref, propsRef, config, navigation) {
180
- const bubbleTouchEvent = ['catchtouchcancel', 'bindtouchcancel'];
181
- const captureTouchEvent = [
182
- 'capture-catchtouchcancel',
183
- 'capture-bindtouchcancel'
184
- ];
185
- const currentTouchEvent = type === 'bubble' ? bubbleTouchEvent : captureTouchEvent;
186
- ref.current.startTimer[type] &&
187
- clearTimeout(ref.current.startTimer[type]);
188
- ref.current.startTimer[type] = null;
189
- handleEmitEvent(currentTouchEvent, 'touchcancel', e, propsRef, config, navigation);
146
+ function handleTouchcancel(e, type, eventConfig) {
147
+ const { innerRef } = eventConfig;
148
+ handleEmitEvent('touchcancel', e, type, eventConfig);
149
+ innerRef.current.startTimer[type] && clearTimeout(innerRef.current.startTimer[type]);
190
150
  }
191
- function createTouchEventHandler(eventName, type) {
192
- return (e, ref, propsRef, config, navigation) => {
193
- const handlerMap = {
151
+ function createTouchEventHandler(eventName, eventConfig) {
152
+ return (e) => {
153
+ const bubbleHandlerMap = {
194
154
  onTouchStart: handleTouchstart,
195
155
  onTouchMove: handleTouchmove,
196
156
  onTouchEnd: handleTouchend,
197
157
  onTouchCancel: handleTouchcancel
198
158
  };
199
- const handler = handlerMap[eventName];
200
- if (handler) {
201
- handler(e, type, ref, propsRef, config, navigation);
159
+ const captureHandlerMap = {
160
+ onTouchStartCapture: handleTouchstart,
161
+ onTouchMoveCapture: handleTouchmove,
162
+ onTouchEndCapture: handleTouchend,
163
+ onTouchCancelCapture: handleTouchcancel
164
+ };
165
+ if (bubbleHandlerMap[eventName]) {
166
+ bubbleHandlerMap[eventName](e, 'bubble', eventConfig);
167
+ }
168
+ if (captureHandlerMap[eventName]) {
169
+ captureHandlerMap[eventName](e, 'capture', eventConfig);
202
170
  }
203
171
  };
204
172
  }
205
- const touchEventList = [
206
- { eventName: 'onTouchStart', handler: createTouchEventHandler('onTouchStart', 'bubble') },
207
- { eventName: 'onTouchMove', handler: createTouchEventHandler('onTouchMove', 'bubble') },
208
- { eventName: 'onTouchEnd', handler: createTouchEventHandler('onTouchEnd', 'bubble') },
209
- { eventName: 'onTouchCancel', handler: createTouchEventHandler('onTouchCancel', 'bubble') },
210
- { eventName: 'onTouchStartCapture', handler: createTouchEventHandler('onTouchStart', 'capture') },
211
- { eventName: 'onTouchMoveCapture', handler: createTouchEventHandler('onTouchMove', 'capture') },
212
- { eventName: 'onTouchEndCapture', handler: createTouchEventHandler('onTouchEnd', 'capture') },
213
- { eventName: 'onTouchCancelCapture', handler: createTouchEventHandler('onTouchCancel', 'capture') }
214
- ];
215
- const useInnerProps = (props = {}, additionalProps = {}, userRemoveProps = [], rawConfig) => {
216
- const ref = useRef({
173
+ const useInnerProps = (props = {}, userRemoveProps = [], rawConfig) => {
174
+ const innerRef = useRef({
217
175
  startTimer: {
218
176
  bubble: null,
219
177
  capture: null
@@ -226,52 +184,68 @@ const useInnerProps = (props = {}, additionalProps = {}, userRemoveProps = [], r
226
184
  }
227
185
  });
228
186
  const propsRef = useRef({});
229
- const eventConfig = {};
230
- const config = rawConfig || {
231
- layoutRef: { current: {} },
232
- disableTap: false
233
- };
187
+ propsRef.current = props;
234
188
  const navigation = useNavigation();
235
- const removeProps = [
236
- 'children',
237
- 'enable-background',
238
- 'enable-offset',
239
- 'enable-var',
240
- 'external-var-context',
241
- 'parent-font-size',
242
- 'parent-width',
243
- 'parent-height',
244
- ...userRemoveProps
245
- ];
246
- propsRef.current = extendObject({}, props, additionalProps);
189
+ const eventConfig = extendObject({
190
+ layoutRef: {
191
+ current: null
192
+ },
193
+ propsRef,
194
+ innerRef,
195
+ disableTap: false,
196
+ navigation
197
+ }, rawConfig);
247
198
  let hashEventKey = '';
248
199
  const rawEventKeys = [];
249
- for (const key in eventConfigMap) {
250
- if (hasOwn(propsRef.current, key)) {
251
- eventConfig[key] = eventConfigMap[key].events;
252
- hashEventKey = hashEventKey + eventConfigMap[key].bitFlag;
200
+ const transformedEventSet = new Set();
201
+ Object.keys(props).forEach((key) => {
202
+ if (eventConfigMap[key]) {
203
+ hashEventKey += eventConfigMap[key].bitFlag;
253
204
  rawEventKeys.push(key);
205
+ eventConfigMap[key].events.forEach((event) => {
206
+ transformedEventSet.add(event);
207
+ });
208
+ const match = /^(bind|catch|capture-bind|capture-catch)(.*)$/.exec(key);
209
+ const prefix = match[1];
210
+ const eventName = match[2];
211
+ eventConfig[eventName] = eventConfig[eventName] || {
212
+ bubble: [],
213
+ capture: [],
214
+ hasCatch: false
215
+ };
216
+ if (prefix === 'bind' || prefix === 'catch') {
217
+ eventConfig[eventName].bubble.push(key);
218
+ }
219
+ else {
220
+ eventConfig[eventName].capture.push(key);
221
+ }
222
+ if (prefix === 'catch' || prefix === 'capture-catch') {
223
+ eventConfig[eventName].hasCatch = true;
224
+ }
254
225
  }
255
- }
226
+ });
256
227
  const events = useMemo(() => {
257
- if (!rawEventKeys.length) {
228
+ if (!hashEventKey) {
258
229
  return {};
259
230
  }
260
- const transformedEventKeys = rawEventKeys.reduce((acc, key) => {
261
- if (propsRef.current[key]) {
262
- return acc.concat(eventConfig[key]);
263
- }
264
- return acc;
265
- }, []);
266
- const finalEventKeys = [...new Set(transformedEventKeys)];
267
231
  const events = {};
268
- touchEventList.forEach((item) => {
269
- if (finalEventKeys.includes(item.eventName)) {
270
- events[item.eventName] = (e) => item.handler(e, ref, propsRef, config, navigation);
271
- }
272
- });
232
+ for (const eventName of transformedEventSet) {
233
+ events[eventName] = createTouchEventHandler(eventName, eventConfig);
234
+ }
273
235
  return events;
274
236
  }, [hashEventKey]);
275
- return extendObject({}, events, omit(propsRef.current, [...rawEventKeys, ...removeProps]));
237
+ const removeProps = [
238
+ 'children',
239
+ 'enable-background',
240
+ 'enable-offset',
241
+ 'enable-var',
242
+ 'external-var-context',
243
+ 'parent-font-size',
244
+ 'parent-width',
245
+ 'parent-height',
246
+ ...userRemoveProps,
247
+ ...rawEventKeys
248
+ ];
249
+ return extendObject({}, events, omit(props, removeProps));
276
250
  };
277
251
  export default useInnerProps;
@@ -35,7 +35,7 @@
35
35
  * ✔ bindtap
36
36
  */
37
37
  import { createElement, useEffect, useRef, forwardRef, useContext } from 'react';
38
- import { View, StyleSheet, Animated, Easing } from 'react-native';
38
+ import { View, StyleSheet, Animated, Easing, useAnimatedValue } from 'react-native';
39
39
  import { warn } from '@mpxjs/utils';
40
40
  import { GestureDetector } from 'react-native-gesture-handler';
41
41
  import { getCurrentPage, splitProps, splitStyle, useLayout, useTransformStyle, wrapChildren, extendObject, useHover } from './utils';
@@ -103,7 +103,7 @@ const timer = (data, time = 3000) => new Promise((resolve) => {
103
103
  }, time);
104
104
  });
105
105
  const Loading = ({ alone = false }) => {
106
- const image = useRef(new Animated.Value(0)).current;
106
+ const image = useAnimatedValue(0);
107
107
  const rotate = image.interpolate({
108
108
  inputRange: [0, 1],
109
109
  outputRange: ['0deg', '360deg']
@@ -236,10 +236,9 @@ const Button = forwardRef((buttonProps, ref) => {
236
236
  handleOpenTypeEvent(evt);
237
237
  handleFormTypeFn();
238
238
  };
239
- const innerProps = useInnerProps(props, extendObject({
239
+ const innerProps = useInnerProps(extendObject({}, props, layoutProps, {
240
240
  ref: nodeRef,
241
- style: extendObject({}, innerStyle, layoutStyle)
242
- }, layoutProps, {
241
+ style: extendObject({}, innerStyle, layoutStyle),
243
242
  bindtap: !disabled && onTap
244
243
  }), [
245
244
  'disabled',