@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.
- package/lib/config.js +3 -1
- package/lib/file-loader.js +5 -0
- package/lib/parser.js +1 -1
- package/lib/platform/json/wx/index.js +21 -8
- package/lib/platform/style/wx/index.js +51 -54
- package/lib/platform/template/wx/component-config/fix-component-name.js +15 -12
- package/lib/platform/template/wx/component-config/index.js +1 -1
- package/lib/platform/template/wx/component-config/movable-view.js +8 -1
- package/lib/platform/template/wx/component-config/picker-view.js +1 -5
- package/lib/platform/template/wx/component-config/rich-text.js +8 -0
- package/lib/platform/template/wx/component-config/scroll-view.js +1 -1
- package/lib/platform/template/wx/component-config/unsupported.js +1 -1
- package/lib/platform/template/wx/index.js +3 -5
- package/lib/react/processScript.js +6 -3
- package/lib/react/script-helper.js +5 -1
- package/lib/runtime/components/react/context.ts +8 -0
- package/lib/runtime/components/react/dist/context.js +0 -2
- package/lib/runtime/components/react/dist/getInnerListeners.js +34 -31
- package/lib/runtime/components/react/dist/mpx-button.jsx +11 -11
- package/lib/runtime/components/react/dist/mpx-canvas/html.js +2 -4
- package/lib/runtime/components/react/dist/mpx-canvas/index.jsx +5 -1
- package/lib/runtime/components/react/dist/mpx-icon/icons/cancel.png +0 -0
- package/lib/runtime/components/react/dist/mpx-icon/icons/clear.png +0 -0
- package/lib/runtime/components/react/dist/mpx-icon/icons/download.png +0 -0
- package/lib/runtime/components/react/dist/mpx-icon/icons/info.png +0 -0
- package/lib/runtime/components/react/dist/mpx-icon/icons/search.png +0 -0
- package/lib/runtime/components/react/dist/mpx-icon/icons/success.png +0 -0
- package/lib/runtime/components/react/dist/mpx-icon/icons/success_no_circle.png +0 -0
- package/lib/runtime/components/react/dist/mpx-icon/icons/waiting.png +0 -0
- package/lib/runtime/components/react/dist/mpx-icon/icons/warn.png +0 -0
- package/lib/runtime/components/react/dist/mpx-icon/index.jsx +50 -0
- package/lib/runtime/components/react/dist/mpx-image.jsx +12 -15
- package/lib/runtime/components/react/dist/mpx-input.jsx +10 -8
- package/lib/runtime/components/react/dist/mpx-movable-view.jsx +92 -57
- package/lib/runtime/components/react/dist/mpx-navigator.jsx +1 -1
- package/lib/runtime/components/react/dist/mpx-picker/time.jsx +1 -2
- package/lib/runtime/components/react/dist/mpx-picker-view-column-item.jsx +10 -14
- package/lib/runtime/components/react/dist/mpx-picker-view-column.jsx +79 -67
- package/lib/runtime/components/react/dist/mpx-picker-view.jsx +19 -16
- package/lib/runtime/components/react/dist/mpx-root-portal.jsx +1 -1
- package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +2 -0
- package/lib/runtime/components/react/dist/mpx-swiper-item.jsx +13 -7
- package/lib/runtime/components/react/dist/mpx-swiper.jsx +382 -325
- package/lib/runtime/components/react/dist/mpx-view.jsx +15 -13
- package/lib/runtime/components/react/dist/mpx-web-view.jsx +22 -118
- package/lib/runtime/components/react/dist/pickerFaces.js +1 -6
- package/lib/runtime/components/react/dist/pickerVIewContext.js +5 -0
- package/lib/runtime/components/react/dist/{pickerViewOverlay.jsx → pickerViewIndicator.jsx} +6 -6
- package/lib/runtime/components/react/dist/pickerViewMask.jsx +2 -2
- package/lib/runtime/components/react/dist/useAnimationHooks.js +15 -10
- package/lib/runtime/components/react/dist/utils.jsx +117 -84
- package/lib/runtime/components/react/event.config.ts +25 -26
- package/lib/runtime/components/react/getInnerListeners.ts +236 -182
- package/lib/runtime/components/react/mpx-button.tsx +27 -69
- package/lib/runtime/components/react/mpx-canvas/html.ts +2 -4
- package/lib/runtime/components/react/mpx-canvas/index.tsx +44 -46
- package/lib/runtime/components/react/mpx-checkbox-group.tsx +15 -13
- package/lib/runtime/components/react/mpx-checkbox.tsx +20 -21
- package/lib/runtime/components/react/mpx-form.tsx +15 -20
- package/lib/runtime/components/react/mpx-icon/icons/cancel.png +0 -0
- package/lib/runtime/components/react/mpx-icon/icons/clear.png +0 -0
- package/lib/runtime/components/react/mpx-icon/icons/download.png +0 -0
- package/lib/runtime/components/react/mpx-icon/icons/info.png +0 -0
- package/lib/runtime/components/react/mpx-icon/icons/search.png +0 -0
- package/lib/runtime/components/react/mpx-icon/icons/success.png +0 -0
- package/lib/runtime/components/react/mpx-icon/icons/success_no_circle.png +0 -0
- package/lib/runtime/components/react/mpx-icon/icons/waiting.png +0 -0
- package/lib/runtime/components/react/mpx-icon/icons/warn.png +0 -0
- package/lib/runtime/components/react/mpx-icon/index.tsx +111 -0
- package/lib/runtime/components/react/mpx-image.tsx +99 -47
- package/lib/runtime/components/react/mpx-input.tsx +33 -39
- package/lib/runtime/components/react/mpx-label.tsx +12 -14
- package/lib/runtime/components/react/mpx-movable-area.tsx +10 -16
- package/lib/runtime/components/react/mpx-movable-view.tsx +133 -92
- package/lib/runtime/components/react/mpx-navigator.tsx +3 -9
- package/lib/runtime/components/react/mpx-picker-view-column-item.tsx +76 -0
- package/lib/runtime/components/react/mpx-picker-view-column.tsx +206 -183
- package/lib/runtime/components/react/mpx-picker-view.tsx +49 -48
- package/lib/runtime/components/react/mpx-radio-group.tsx +13 -15
- package/lib/runtime/components/react/mpx-radio.tsx +19 -25
- package/lib/runtime/components/react/mpx-rich-text/html.ts +40 -0
- package/lib/runtime/components/react/mpx-rich-text/index.tsx +115 -0
- package/lib/runtime/components/react/mpx-root-portal.tsx +3 -5
- package/lib/runtime/components/react/mpx-scroll-view.tsx +62 -49
- package/lib/runtime/components/react/mpx-swiper-item.tsx +45 -11
- package/lib/runtime/components/react/mpx-swiper.tsx +742 -0
- package/lib/runtime/components/react/mpx-switch.tsx +19 -15
- package/lib/runtime/components/react/mpx-text.tsx +8 -16
- package/lib/runtime/components/react/mpx-textarea.tsx +11 -10
- package/lib/runtime/components/react/mpx-view.tsx +28 -77
- package/lib/runtime/components/react/mpx-web-view.tsx +94 -59
- package/lib/runtime/components/react/pickerFaces.ts +10 -7
- package/lib/runtime/components/react/pickerVIewContext.ts +27 -0
- package/lib/runtime/components/react/pickerViewIndicator.tsx +34 -0
- package/lib/runtime/components/react/pickerViewMask.tsx +30 -0
- package/lib/runtime/components/react/types/{getInnerListeners.ts → getInnerListeners.d.ts} +4 -5
- package/lib/runtime/components/react/types/global.d.ts +14 -1
- package/lib/runtime/components/react/useAnimationHooks.ts +60 -15
- package/lib/runtime/components/react/utils.tsx +175 -71
- package/lib/runtime/components/web/mpx-checkbox.vue +1 -1
- package/lib/runtime/components/web/mpx-picker-view-column.vue +9 -4
- package/lib/runtime/components/web/mpx-web-view.vue +34 -20
- package/lib/runtime/optionProcessor.js +0 -22
- package/lib/style-compiler/plugins/scope-id.js +30 -2
- package/lib/template-compiler/compiler.js +96 -29
- package/lib/utils/pre-process-json.js +9 -5
- package/lib/wxss/loader.js +15 -2
- package/package.json +4 -3
- package/lib/runtime/components/react/dist/locale-provider.jsx +0 -15
- package/lib/runtime/components/react/dist/mpx-icon.jsx +0 -41
- package/lib/runtime/components/react/dist/mpx-portal/portal-consumer.jsx +0 -23
- package/lib/runtime/components/react/dist/mpx-portal/portal-host.jsx +0 -124
- package/lib/runtime/components/react/dist/mpx-portal/portal-manager.jsx +0 -40
- package/lib/runtime/components/react/dist/mpx-portal.jsx +0 -12
- package/lib/runtime/components/react/dist/mpx-provider.jsx +0 -31
- package/lib/runtime/components/react/dist/types/common.js +0 -1
- package/lib/runtime/components/react/dist/types/getInnerListeners.js +0 -1
- package/lib/runtime/components/react/mpx-icon.tsx +0 -102
- package/lib/runtime/components/react/mpx-swiper/carouse.tsx +0 -527
- package/lib/runtime/components/react/mpx-swiper/index.tsx +0 -80
- package/lib/runtime/components/react/mpx-swiper/type.ts +0 -87
- package/lib/runtime/components/react/pickerOverlay.tsx +0 -32
- package/lib/runtime/components/web/event.js +0 -105
- /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
|
|
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
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
400
|
-
const
|
|
401
|
-
const
|
|
402
|
-
{
|
|
403
|
-
{
|
|
404
|
-
{
|
|
423
|
+
const rewriteCatchEvent = () => {
|
|
424
|
+
const handlers = {};
|
|
425
|
+
const events = [
|
|
426
|
+
{ type: 'touchstart' },
|
|
427
|
+
{ type: 'touchmove', alias: ['vtouchmove', 'htouchmove'] },
|
|
428
|
+
{ type: 'touchend' }
|
|
405
429
|
];
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
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
|
|
436
|
+
return handlers;
|
|
416
437
|
};
|
|
417
|
-
const catchEventHandlers = injectCatchEvent(props);
|
|
418
438
|
const layoutStyle = !hasLayoutRef.current && hasSelfPercent ? HIDDEN_STYLE : {};
|
|
419
|
-
|
|
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
|
-
},
|
|
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 '
|
|
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 {
|
|
3
|
+
import { extendObject } from './utils';
|
|
4
4
|
import { createFaces } from './pickerFaces';
|
|
5
|
-
import { usePickerViewColumnAnimationContext } from './pickerVIewContext';
|
|
6
|
-
const
|
|
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%' },
|
|
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
|
-
{
|
|
31
|
-
hasVarDec,
|
|
32
|
-
varContext,
|
|
33
|
-
textStyle,
|
|
34
|
-
textProps
|
|
35
|
-
})}
|
|
31
|
+
{realItem}
|
|
36
32
|
</Reanimated.View>);
|
|
37
33
|
};
|
|
38
|
-
|
|
39
|
-
export default
|
|
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 {
|
|
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
|
|
4
|
+
import { useTransformStyle, splitStyle, splitProps, useLayout, usePrevious, isAndroid, isIOS } from './utils';
|
|
5
5
|
import useNodesRef from './useNodesRef';
|
|
6
|
-
import
|
|
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,
|
|
13
|
-
const { normalStyle,
|
|
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(() =>
|
|
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
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
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
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
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
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
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
|
-
|
|
77
|
+
clearTimerScrollTo();
|
|
78
|
+
timerScrollTo.current = setTimeout(() => {
|
|
80
79
|
scrollViewRef.current?.scrollTo({
|
|
81
80
|
x: 0,
|
|
82
|
-
y:
|
|
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 =
|
|
86
|
+
}, [itemRawH, maxIndex, initialIndex]);
|
|
87
|
+
const onContentSizeChange = useCallback((_w, h) => {
|
|
88
|
+
const y = initialIndex * itemRawH;
|
|
90
89
|
if (y <= h) {
|
|
91
|
-
|
|
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
|
|
104
|
-
|
|
105
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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:
|
|
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}
|
|
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
|
|
181
|
+
const renderIndicator = () => (<PickerIndicator itemHeight={itemHeight} indicatorItemStyle={pickerIndicatorStyle}/>);
|
|
170
182
|
const renderMask = () => (<PickerMask itemHeight={itemHeight} maskContainerStyle={pickerMaskStyle}/>);
|
|
171
|
-
return (<
|
|
183
|
+
return (<View style={[styles.wrapper, normalStyle]}>
|
|
172
184
|
{renderScollView()}
|
|
173
185
|
{renderMask()}
|
|
174
|
-
{
|
|
175
|
-
</
|
|
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,
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
}), [
|
|
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
|
-
|
|
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 (<
|
|
118
|
-
<View
|
|
119
|
-
|
|
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 '
|
|
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;
|