@mpxjs/webpack-plugin 2.10.24 → 2.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.js +4 -1
- package/lib/platform/style/wx/index.js +417 -120
- package/lib/platform/template/wx/component-config/picker.js +0 -6
- package/lib/react/style-helper.js +6 -6
- package/lib/resolver/AddEnvPlugin.js +1 -1
- package/lib/resolver/AddModePlugin.js +1 -1
- package/lib/resolver/ExtendComponentsPlugin.js +68 -0
- package/lib/runtime/components/extends/section-list.mpx +14 -0
- package/lib/runtime/components/react/animationHooks/index.ts +7 -3
- package/lib/runtime/components/react/dist/animationHooks/index.d.ts +0 -2
- package/lib/runtime/components/react/dist/animationHooks/index.js +6 -1
- package/lib/runtime/components/react/dist/event.config.d.ts +2 -6
- package/lib/runtime/components/react/dist/event.config.js +28 -24
- package/lib/runtime/components/react/dist/getInnerListeners.d.ts +1 -1
- package/lib/runtime/components/react/dist/getInnerListeners.js +74 -56
- package/lib/runtime/components/react/dist/mpx-button.d.ts +1 -2
- package/lib/runtime/components/react/dist/mpx-button.jsx +16 -9
- package/lib/runtime/components/react/dist/mpx-camera.d.ts +0 -2
- package/lib/runtime/components/react/dist/mpx-camera.jsx +36 -5
- package/lib/runtime/components/react/dist/mpx-canvas/index.d.ts +0 -2
- package/lib/runtime/components/react/dist/mpx-canvas/index.jsx +1 -3
- package/lib/runtime/components/react/dist/mpx-canvas/utils.d.ts +1 -1
- package/lib/runtime/components/react/dist/mpx-checkbox-group.d.ts +0 -2
- package/lib/runtime/components/react/dist/mpx-checkbox-group.jsx +3 -4
- package/lib/runtime/components/react/dist/mpx-checkbox.d.ts +1 -2
- package/lib/runtime/components/react/dist/mpx-checkbox.jsx +8 -9
- package/lib/runtime/components/react/dist/mpx-form.d.ts +1 -2
- package/lib/runtime/components/react/dist/mpx-form.jsx +5 -5
- package/lib/runtime/components/react/dist/mpx-icon/index.d.ts +0 -2
- package/lib/runtime/components/react/dist/mpx-icon/index.jsx +2 -2
- package/lib/runtime/components/react/dist/mpx-image.d.ts +0 -2
- package/lib/runtime/components/react/dist/mpx-image.jsx +59 -43
- package/lib/runtime/components/react/dist/mpx-inline-text.jsx +13 -4
- package/lib/runtime/components/react/dist/mpx-input.d.ts +0 -2
- package/lib/runtime/components/react/dist/mpx-input.jsx +16 -8
- package/lib/runtime/components/react/dist/mpx-label.d.ts +1 -2
- package/lib/runtime/components/react/dist/mpx-label.jsx +5 -6
- package/lib/runtime/components/react/dist/mpx-movable-area.d.ts +0 -2
- package/lib/runtime/components/react/dist/mpx-movable-area.jsx +3 -3
- package/lib/runtime/components/react/dist/mpx-movable-view.d.ts +1 -2
- package/lib/runtime/components/react/dist/mpx-movable-view.jsx +6 -6
- package/lib/runtime/components/react/dist/mpx-nav.jsx +1 -1
- package/lib/runtime/components/react/dist/mpx-picker/index.jsx +72 -23
- package/lib/runtime/components/react/dist/mpx-picker/multiSelector.jsx +2 -2
- package/lib/runtime/components/react/dist/mpx-picker/type.d.ts +4 -0
- package/lib/runtime/components/react/dist/mpx-picker-view/index.d.ts +1 -1
- package/lib/runtime/components/react/dist/mpx-picker-view/index.jsx +10 -14
- package/lib/runtime/components/react/dist/mpx-picker-view/pickerVIewContext.d.ts +0 -2
- package/lib/runtime/components/react/dist/mpx-picker-view/pickerVIewContext.js +0 -5
- package/lib/runtime/components/react/dist/mpx-picker-view-column/index.d.ts +1 -1
- package/lib/runtime/components/react/dist/mpx-picker-view-column/index.jsx +34 -14
- package/lib/runtime/components/react/dist/mpx-picker-view-column/pickerViewColumnItem.d.ts +0 -2
- package/lib/runtime/components/react/dist/mpx-picker-view-column/pickerViewColumnItem.jsx +4 -5
- package/lib/runtime/components/react/dist/mpx-picker-view-column/pickerViewColumnItemLite.d.ts +0 -2
- package/lib/runtime/components/react/dist/mpx-picker-view-column/pickerViewColumnItemLite.jsx +3 -5
- package/lib/runtime/components/react/dist/mpx-popup/index.d.ts +5 -4
- package/lib/runtime/components/react/dist/mpx-popup/index.jsx +2 -2
- package/lib/runtime/components/react/dist/mpx-popup/popupBase.jsx +3 -2
- package/lib/runtime/components/react/dist/mpx-progress.d.ts +0 -2
- package/lib/runtime/components/react/dist/mpx-progress.jsx +1 -3
- package/lib/runtime/components/react/dist/mpx-radio-group.d.ts +0 -2
- package/lib/runtime/components/react/dist/mpx-radio-group.jsx +3 -4
- package/lib/runtime/components/react/dist/mpx-radio.d.ts +1 -2
- package/lib/runtime/components/react/dist/mpx-radio.jsx +8 -9
- package/lib/runtime/components/react/dist/mpx-rich-text/index.d.ts +0 -2
- package/lib/runtime/components/react/dist/mpx-rich-text/index.jsx +1 -3
- package/lib/runtime/components/react/dist/mpx-scroll-view.d.ts +1 -2
- package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +6 -6
- package/lib/runtime/components/react/dist/mpx-section-list.d.ts +51 -0
- package/lib/runtime/components/react/dist/mpx-section-list.jsx +376 -0
- package/lib/runtime/components/react/dist/mpx-simple-text.jsx +37 -19
- package/lib/runtime/components/react/dist/mpx-simple-view.d.ts +4 -1
- package/lib/runtime/components/react/dist/mpx-simple-view.jsx +11 -4
- package/lib/runtime/components/react/dist/mpx-slider.d.ts +0 -2
- package/lib/runtime/components/react/dist/mpx-slider.jsx +6 -7
- package/lib/runtime/components/react/dist/mpx-sticky-header.d.ts +1 -2
- package/lib/runtime/components/react/dist/mpx-sticky-header.jsx +5 -5
- package/lib/runtime/components/react/dist/mpx-sticky-section.d.ts +1 -2
- package/lib/runtime/components/react/dist/mpx-sticky-section.jsx +6 -6
- package/lib/runtime/components/react/dist/mpx-swiper-item.d.ts +1 -2
- package/lib/runtime/components/react/dist/mpx-swiper-item.jsx +5 -5
- package/lib/runtime/components/react/dist/mpx-swiper.d.ts +1 -2
- package/lib/runtime/components/react/dist/mpx-swiper.jsx +4 -8
- package/lib/runtime/components/react/dist/mpx-switch.d.ts +0 -2
- package/lib/runtime/components/react/dist/mpx-switch.jsx +1 -3
- package/lib/runtime/components/react/dist/mpx-text.d.ts +0 -2
- package/lib/runtime/components/react/dist/mpx-text.jsx +43 -25
- package/lib/runtime/components/react/dist/mpx-video.d.ts +0 -2
- package/lib/runtime/components/react/dist/mpx-video.jsx +4 -5
- package/lib/runtime/components/react/dist/mpx-view.d.ts +2 -2
- package/lib/runtime/components/react/dist/mpx-view.jsx +214 -114
- package/lib/runtime/components/react/dist/mpx-web-view.d.ts +2 -1
- package/lib/runtime/components/react/dist/mpx-web-view.jsx +5 -1
- package/lib/runtime/components/react/dist/namedColorSet.d.ts +2 -0
- package/lib/runtime/components/react/dist/namedColorSet.js +149 -0
- package/lib/runtime/components/react/dist/utils.d.ts +71 -70
- package/lib/runtime/components/react/dist/utils.jsx +1295 -456
- package/lib/runtime/components/react/event.config.ts +32 -25
- package/lib/runtime/components/react/getInnerListeners.ts +84 -60
- package/lib/runtime/components/react/mpx-button.tsx +18 -18
- package/lib/runtime/components/react/mpx-camera.tsx +40 -8
- package/lib/runtime/components/react/mpx-canvas/index.tsx +5 -7
- package/lib/runtime/components/react/mpx-canvas/utils.tsx +3 -1
- package/lib/runtime/components/react/mpx-checkbox-group.tsx +2 -8
- package/lib/runtime/components/react/mpx-checkbox.tsx +9 -13
- package/lib/runtime/components/react/mpx-form.tsx +6 -8
- package/lib/runtime/components/react/mpx-icon/index.tsx +1 -5
- package/lib/runtime/components/react/mpx-image.tsx +66 -58
- package/lib/runtime/components/react/mpx-inline-text.tsx +13 -4
- package/lib/runtime/components/react/mpx-input.tsx +19 -12
- package/lib/runtime/components/react/mpx-label.tsx +6 -10
- package/lib/runtime/components/react/mpx-movable-area.tsx +3 -5
- package/lib/runtime/components/react/mpx-movable-view.tsx +7 -9
- package/lib/runtime/components/react/mpx-nav.tsx +1 -1
- package/lib/runtime/components/react/mpx-picker/index.tsx +100 -29
- package/lib/runtime/components/react/mpx-picker/multiSelector.tsx +3 -3
- package/lib/runtime/components/react/mpx-picker/selector.tsx +1 -1
- package/lib/runtime/components/react/mpx-picker/type.ts +4 -0
- package/lib/runtime/components/react/mpx-picker-view/index.tsx +17 -24
- package/lib/runtime/components/react/mpx-picker-view/pickerVIewContext.ts +0 -9
- package/lib/runtime/components/react/mpx-picker-view-column/index.tsx +44 -23
- package/lib/runtime/components/react/mpx-picker-view-column/pickerViewColumnItem.tsx +1 -9
- package/lib/runtime/components/react/mpx-picker-view-column/pickerViewColumnItemLite.tsx +0 -9
- package/lib/runtime/components/react/mpx-popup/index.tsx +7 -3
- package/lib/runtime/components/react/mpx-popup/popupBase.tsx +3 -2
- package/lib/runtime/components/react/mpx-progress.tsx +0 -6
- package/lib/runtime/components/react/mpx-radio-group.tsx +2 -8
- package/lib/runtime/components/react/mpx-radio.tsx +9 -13
- package/lib/runtime/components/react/mpx-rich-text/index.tsx +0 -6
- package/lib/runtime/components/react/mpx-scroll-view.tsx +7 -9
- package/lib/runtime/components/react/mpx-section-list.tsx +557 -0
- package/lib/runtime/components/react/mpx-simple-text.tsx +36 -25
- package/lib/runtime/components/react/mpx-simple-view.tsx +17 -5
- package/lib/runtime/components/react/mpx-slider.tsx +15 -13
- package/lib/runtime/components/react/mpx-sticky-header.tsx +6 -8
- package/lib/runtime/components/react/mpx-sticky-section.tsx +7 -9
- package/lib/runtime/components/react/mpx-swiper-item.tsx +6 -7
- package/lib/runtime/components/react/mpx-swiper.tsx +5 -11
- package/lib/runtime/components/react/mpx-switch.tsx +0 -6
- package/lib/runtime/components/react/mpx-text.tsx +45 -36
- package/lib/runtime/components/react/mpx-video.tsx +3 -8
- package/lib/runtime/components/react/mpx-view.tsx +235 -129
- package/lib/runtime/components/react/mpx-web-view.tsx +12 -6
- package/lib/runtime/components/react/namedColorSet.ts +150 -0
- package/lib/runtime/components/react/types/getInnerListeners.d.ts +21 -1
- package/lib/runtime/components/react/types/global.d.ts +1 -0
- package/lib/runtime/components/react/utils.tsx +1352 -550
- package/lib/runtime/i18n.wxs +15 -9
- package/lib/style-compiler/strip-conditional.js +19 -4
- package/lib/template-compiler/compiler.js +6 -0
- package/package.json +6 -6
|
@@ -10,7 +10,7 @@ import useNodesRef from './useNodesRef';
|
|
|
10
10
|
import { useLayout, useTransformStyle, wrapChildren, extendObject } from './utils';
|
|
11
11
|
import Portal from './mpx-portal';
|
|
12
12
|
const radioGroup = forwardRef((props, ref) => {
|
|
13
|
-
const { style = {}, 'enable-var': enableVar, '
|
|
13
|
+
const { style = {}, 'enable-var': enableVar, 'parent-width': parentWidth, 'parent-height': parentHeight } = props;
|
|
14
14
|
const propsRef = useRef({});
|
|
15
15
|
propsRef.current = props;
|
|
16
16
|
const formContext = useContext(FormContext);
|
|
@@ -23,8 +23,7 @@ const radioGroup = forwardRef((props, ref) => {
|
|
|
23
23
|
flexDirection: 'row',
|
|
24
24
|
flexWrap: 'wrap'
|
|
25
25
|
};
|
|
26
|
-
const
|
|
27
|
-
const { hasPositionFixed, hasSelfPercent, normalStyle, hasVarDec, varContextRef, setWidth, setHeight } = useTransformStyle(styleObj, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
|
|
26
|
+
const { hasPositionFixed, hasSelfPercent, normalStyle, hasVarDec, varContextRef, setWidth, setHeight } = useTransformStyle(style, { enableVar, parentWidth, parentHeight, defaultStyle });
|
|
28
27
|
const nodeRef = useRef(null);
|
|
29
28
|
useNodesRef(props, ref, nodeRef, { style: normalStyle });
|
|
30
29
|
const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef });
|
|
@@ -83,7 +82,7 @@ const radioGroup = forwardRef((props, ref) => {
|
|
|
83
82
|
});
|
|
84
83
|
const finalComponent = createElement(View, innerProps, createElement(RadioGroupContext.Provider, {
|
|
85
84
|
value: contextValue
|
|
86
|
-
}, wrapChildren(props, {
|
|
85
|
+
}, wrapChildren(props.children, {
|
|
87
86
|
hasVarDec,
|
|
88
87
|
varContext: varContextRef.current
|
|
89
88
|
})));
|
|
@@ -15,8 +15,7 @@ export interface RadioProps {
|
|
|
15
15
|
style?: ViewStyle & Record<string, any>;
|
|
16
16
|
'enable-offset'?: boolean;
|
|
17
17
|
'enable-var'?: boolean;
|
|
18
|
-
'
|
|
19
|
-
'parent-font-size'?: number;
|
|
18
|
+
'enable-text-pass-through'?: boolean;
|
|
20
19
|
'parent-width'?: number;
|
|
21
20
|
'parent-height'?: number;
|
|
22
21
|
children: ReactNode;
|
|
@@ -10,7 +10,7 @@ import { warn } from '@mpxjs/utils';
|
|
|
10
10
|
import { LabelContext, RadioGroupContext } from './context';
|
|
11
11
|
import useInnerProps, { getCustomEvent } from './getInnerListeners';
|
|
12
12
|
import useNodesRef from './useNodesRef';
|
|
13
|
-
import { splitProps, splitStyle, useLayout, useTransformStyle, wrapChildren, extendObject,
|
|
13
|
+
import { splitProps, splitStyle, useLayout, useTransformStyle, wrapChildren, extendObject, useTextPassThrough } from './utils';
|
|
14
14
|
import Icon from './mpx-icon';
|
|
15
15
|
import Portal from './mpx-portal';
|
|
16
16
|
const styles = StyleSheet.create({
|
|
@@ -48,14 +48,13 @@ const styles = StyleSheet.create({
|
|
|
48
48
|
});
|
|
49
49
|
const Radio = forwardRef((radioProps, ref) => {
|
|
50
50
|
const { textProps, innerProps: props = {} } = splitProps(radioProps);
|
|
51
|
-
const { value = '', disabled = false, checked = false, color = '#09BB07', style = [], 'enable-var': enableVar, '
|
|
51
|
+
const { value = '', disabled = false, checked = false, color = '#09BB07', style = [], 'enable-var': enableVar, 'enable-text-pass-through': enableTextPassThrough, 'parent-width': parentWidth, 'parent-height': parentHeight, bindtap } = props;
|
|
52
52
|
const [isChecked, setIsChecked] = useState(!!checked);
|
|
53
53
|
const groupContext = useContext(RadioGroupContext);
|
|
54
54
|
let groupValue;
|
|
55
55
|
let notifyChange;
|
|
56
56
|
const labelContext = useContext(LabelContext);
|
|
57
|
-
const
|
|
58
|
-
const styleObj = extendObject({}, styles.container, style);
|
|
57
|
+
const wrapperStyle = extendObject({}, styles.wrapper, isChecked ? styles.wrapperChecked : {}, disabled ? styles.wrapperDisabled : {});
|
|
59
58
|
const onChange = (evt) => {
|
|
60
59
|
if (disabled || isChecked)
|
|
61
60
|
return;
|
|
@@ -74,15 +73,15 @@ const Radio = forwardRef((radioProps, ref) => {
|
|
|
74
73
|
bindtap && bindtap(getCustomEvent('tap', evt, { layoutRef }, props));
|
|
75
74
|
onChange(evt);
|
|
76
75
|
};
|
|
77
|
-
const { hasPositionFixed, hasSelfPercent, normalStyle, hasVarDec, varContextRef, setWidth, setHeight } = useTransformStyle(
|
|
76
|
+
const { hasPositionFixed, hasSelfPercent, normalStyle, hasVarDec, varContextRef, setWidth, setHeight } = useTransformStyle(style, { enableVar, parentWidth, parentHeight, defaultStyle: styles.container });
|
|
78
77
|
const { textStyle, backgroundStyle, innerStyle = {} } = splitStyle(normalStyle);
|
|
79
|
-
const textPassThrough =
|
|
78
|
+
const textPassThrough = useTextPassThrough(textStyle, textProps, { enableTextPassThrough });
|
|
80
79
|
if (backgroundStyle) {
|
|
81
80
|
warn('Radio does not support background image-related styles!');
|
|
82
81
|
}
|
|
83
82
|
const nodeRef = useRef(null);
|
|
84
83
|
useNodesRef(props, ref, nodeRef, {
|
|
85
|
-
style:
|
|
84
|
+
style: normalStyle,
|
|
86
85
|
change: onChange
|
|
87
86
|
});
|
|
88
87
|
const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef });
|
|
@@ -126,12 +125,12 @@ const Radio = forwardRef((radioProps, ref) => {
|
|
|
126
125
|
}
|
|
127
126
|
}
|
|
128
127
|
}, [checked]);
|
|
129
|
-
const finalComponent = createElement(View, innerProps, createElement(View, { style:
|
|
128
|
+
const finalComponent = createElement(View, innerProps, createElement(View, { style: wrapperStyle }, createElement(Icon, {
|
|
130
129
|
type: 'success',
|
|
131
130
|
size: 24,
|
|
132
131
|
color: disabled ? '#E1E1E1' : color,
|
|
133
132
|
style: extendObject({}, styles.icon, isChecked && styles.iconChecked, disabled && styles.iconDisabled)
|
|
134
|
-
})), wrapChildren(props, {
|
|
133
|
+
})), wrapChildren(props.children, {
|
|
135
134
|
hasVarDec,
|
|
136
135
|
varContext: varContextRef.current,
|
|
137
136
|
textPassThrough
|
|
@@ -15,8 +15,6 @@ interface _RichTextProps extends ViewProps {
|
|
|
15
15
|
style?: ViewStyle;
|
|
16
16
|
nodes: string | Array<Node>;
|
|
17
17
|
'enable-var'?: boolean;
|
|
18
|
-
'external-var-context'?: Record<string, any>;
|
|
19
|
-
'parent-font-size'?: number;
|
|
20
18
|
'parent-width'?: number;
|
|
21
19
|
'parent-height'?: number;
|
|
22
20
|
}
|
|
@@ -28,7 +28,7 @@ function jsonToHtmlStr(elements) {
|
|
|
28
28
|
return htmlStr;
|
|
29
29
|
}
|
|
30
30
|
const _RichText = forwardRef((props, ref) => {
|
|
31
|
-
const { style = {}, nodes, 'enable-var': enableVar, '
|
|
31
|
+
const { style = {}, nodes, 'enable-var': enableVar, 'parent-width': parentWidth, 'parent-height': parentHeight } = props;
|
|
32
32
|
const nodeRef = useRef(null);
|
|
33
33
|
const [webViewHeight, setWebViewHeight] = useState(0);
|
|
34
34
|
const { normalStyle, hasSelfPercent, setWidth, setHeight, hasPositionFixed } = useTransformStyle(Object.assign({
|
|
@@ -36,8 +36,6 @@ const _RichText = forwardRef((props, ref) => {
|
|
|
36
36
|
height: webViewHeight
|
|
37
37
|
}, style), {
|
|
38
38
|
enableVar,
|
|
39
|
-
externalVarContext,
|
|
40
|
-
parentFontSize,
|
|
41
39
|
parentWidth,
|
|
42
40
|
parentHeight
|
|
43
41
|
});
|
|
@@ -26,8 +26,7 @@ interface ScrollViewProps {
|
|
|
26
26
|
'scroll-into-view'?: string;
|
|
27
27
|
'enable-trigger-intersection-observer'?: boolean;
|
|
28
28
|
'enable-var'?: boolean;
|
|
29
|
-
'
|
|
30
|
-
'parent-font-size'?: number;
|
|
29
|
+
'enable-text-pass-through'?: boolean;
|
|
31
30
|
'parent-width'?: number;
|
|
32
31
|
'parent-height'?: number;
|
|
33
32
|
'enable-sticky'?: boolean;
|
|
@@ -38,7 +38,7 @@ import Animated, { useSharedValue, withTiming, useAnimatedStyle, runOnJS } from
|
|
|
38
38
|
import { warn, hasOwn } from '@mpxjs/utils';
|
|
39
39
|
import useInnerProps, { getCustomEvent } from './getInnerListeners';
|
|
40
40
|
import useNodesRef from './useNodesRef';
|
|
41
|
-
import { splitProps, splitStyle, useTransformStyle, useLayout, wrapChildren, extendObject, flatGesture,
|
|
41
|
+
import { splitProps, splitStyle, useTransformStyle, useLayout, wrapChildren, extendObject, flatGesture, hiddenStyle, useRunOnJSCallback, useTextPassThrough } from './utils';
|
|
42
42
|
import { IntersectionObserverContext, ScrollViewContext } from './context';
|
|
43
43
|
import Portal from './mpx-portal';
|
|
44
44
|
const AnimatedScrollView = RNAnimated.createAnimatedComponent(ScrollView);
|
|
@@ -48,7 +48,7 @@ const REFRESH_COLOR = {
|
|
|
48
48
|
};
|
|
49
49
|
const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
|
|
50
50
|
const { textProps, innerProps: props = {} } = splitProps(scrollViewProps);
|
|
51
|
-
const { enhanced = false, bounces = true, style = {}, binddragstart, binddragging, binddragend, bindtouchmove, 'scroll-x': scrollX = false, 'scroll-y': scrollY = false, 'enable-back-to-top': enableBackToTop = false, 'enable-trigger-intersection-observer': enableTriggerIntersectionObserver = false, 'paging-enabled': pagingEnabled = false, 'upper-threshold': upperThreshold = 50, 'lower-threshold': lowerThreshold = 50, 'scroll-with-animation': scrollWithAnimation = false, 'refresher-enabled': refresherEnabled, 'refresher-default-style': refresherDefaultStyle, 'refresher-background': refresherBackground, 'refresher-threshold': refresherThreshold = 45, 'show-scrollbar': showScrollbar = true, 'scroll-into-view': scrollIntoView = '', 'scroll-top': scrollTop = 0, 'scroll-left': scrollLeft = 0, 'refresher-triggered': refresherTriggered, 'enable-var': enableVar, '
|
|
51
|
+
const { enhanced = false, bounces = true, style = {}, binddragstart, binddragging, binddragend, bindtouchmove, 'scroll-x': scrollX = false, 'scroll-y': scrollY = false, 'enable-back-to-top': enableBackToTop = false, 'enable-trigger-intersection-observer': enableTriggerIntersectionObserver = false, 'paging-enabled': pagingEnabled = false, 'upper-threshold': upperThreshold = 50, 'lower-threshold': lowerThreshold = 50, 'scroll-with-animation': scrollWithAnimation = false, 'refresher-enabled': refresherEnabled, 'refresher-default-style': refresherDefaultStyle, 'refresher-background': refresherBackground, 'refresher-threshold': refresherThreshold = 45, 'show-scrollbar': showScrollbar = true, 'scroll-into-view': scrollIntoView = '', 'scroll-top': scrollTop = 0, 'scroll-left': scrollLeft = 0, 'refresher-triggered': refresherTriggered, 'enable-var': enableVar, 'enable-text-pass-through': enableTextPassThrough, 'parent-width': parentWidth, 'parent-height': parentHeight, 'simultaneous-handlers': originSimultaneousHandlers, 'wait-for': waitFor, 'enable-sticky': enableSticky, 'scroll-event-throttle': scrollEventThrottle = 0, 'scroll-into-view-offset': scrollIntoViewOffset = 0, __selectRef } = props;
|
|
52
52
|
const scrollOffset = useRef(new RNAnimated.Value(0)).current;
|
|
53
53
|
const simultaneousHandlers = flatGesture(originSimultaneousHandlers);
|
|
54
54
|
const waitForHandlers = flatGesture(waitFor);
|
|
@@ -75,9 +75,9 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
|
|
|
75
75
|
const intersectionObservers = useContext(IntersectionObserverContext);
|
|
76
76
|
const firstScrollIntoViewChange = useRef(true);
|
|
77
77
|
const isContentSizeChange = useRef(false);
|
|
78
|
-
const { normalStyle, hasVarDec, varContextRef, hasSelfPercent, hasPositionFixed, setWidth, setHeight } = useTransformStyle(style, { enableVar,
|
|
78
|
+
const { normalStyle, hasVarDec, varContextRef, hasSelfPercent, hasPositionFixed, setWidth, setHeight } = useTransformStyle(style, { enableVar, parentWidth, parentHeight });
|
|
79
79
|
const { textStyle, innerStyle = {} } = splitStyle(normalStyle);
|
|
80
|
-
const textPassThrough =
|
|
80
|
+
const textPassThrough = useTextPassThrough(textStyle, textProps, { enableTextPassThrough });
|
|
81
81
|
const scrollViewRef = useRef(null);
|
|
82
82
|
const propsRef = useRef(props);
|
|
83
83
|
const refresherStateRef = useRef({
|
|
@@ -120,7 +120,7 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
|
|
|
120
120
|
}, []);
|
|
121
121
|
const hasRefresherLayoutRef = useRef(false);
|
|
122
122
|
// layout 完成前先隐藏,避免安卓闪烁问题
|
|
123
|
-
const refresherLayoutStyle = useMemo(() => { return !hasRefresherLayoutRef.current ?
|
|
123
|
+
const refresherLayoutStyle = useMemo(() => { return !hasRefresherLayoutRef.current ? hiddenStyle : {}; }, [hasRefresherLayoutRef.current]);
|
|
124
124
|
const lastOffset = useRef(0);
|
|
125
125
|
if (scrollX && scrollY) {
|
|
126
126
|
warn('scroll-x and scroll-y cannot be set to true at the same time, Mpx will use the value of scroll-y as the criterion');
|
|
@@ -667,7 +667,7 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
|
|
|
667
667
|
], { layoutRef });
|
|
668
668
|
const ScrollViewComponent = enableSticky ? AnimatedScrollView : ScrollView;
|
|
669
669
|
const createScrollViewContent = () => {
|
|
670
|
-
const wrappedChildren = wrapChildren(hasRefresher ?
|
|
670
|
+
const wrappedChildren = wrapChildren(hasRefresher ? otherContent : props.children, {
|
|
671
671
|
hasVarDec,
|
|
672
672
|
varContext: varContextRef.current,
|
|
673
673
|
textPassThrough
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import { GestureHandler } from './utils';
|
|
3
|
+
interface ListItem {
|
|
4
|
+
isSectionHeader?: boolean;
|
|
5
|
+
isSectionFooter?: boolean;
|
|
6
|
+
[key: string]: any;
|
|
7
|
+
}
|
|
8
|
+
interface ItemHeightType {
|
|
9
|
+
value?: number;
|
|
10
|
+
getter?: (item: any, index: number) => number;
|
|
11
|
+
}
|
|
12
|
+
interface MpxSectionListProps {
|
|
13
|
+
enhanced?: boolean;
|
|
14
|
+
bounces?: boolean;
|
|
15
|
+
height?: number | string;
|
|
16
|
+
width?: number | string;
|
|
17
|
+
generichash?: string;
|
|
18
|
+
style?: Record<string, any>;
|
|
19
|
+
'scroll-event-throttle'?: number;
|
|
20
|
+
'list-data'?: ListItem[];
|
|
21
|
+
'item-height'?: ItemHeightType;
|
|
22
|
+
'section-header-height'?: ItemHeightType;
|
|
23
|
+
'section-footer-height'?: ItemHeightType;
|
|
24
|
+
'list-header-data'?: any;
|
|
25
|
+
'list-header-height'?: number;
|
|
26
|
+
'use-list-header'?: boolean;
|
|
27
|
+
'list-footer-data'?: any;
|
|
28
|
+
'use-list-footer'?: boolean;
|
|
29
|
+
'genericrecycle-item'?: string;
|
|
30
|
+
'genericsection-header'?: string;
|
|
31
|
+
'genericsection-footer'?: string;
|
|
32
|
+
'genericlist-header'?: string;
|
|
33
|
+
'genericlist-footer'?: string;
|
|
34
|
+
'enable-var'?: boolean;
|
|
35
|
+
'parent-width'?: number;
|
|
36
|
+
'parent-height'?: number;
|
|
37
|
+
'enable-sticky'?: boolean;
|
|
38
|
+
'enable-back-to-top'?: boolean;
|
|
39
|
+
'end-reached-threshold'?: number;
|
|
40
|
+
'refresher-enabled'?: boolean;
|
|
41
|
+
'show-scrollbar'?: boolean;
|
|
42
|
+
'refresher-triggered'?: boolean;
|
|
43
|
+
'wait-for'?: Array<GestureHandler>;
|
|
44
|
+
'simultaneous-handlers'?: Array<GestureHandler>;
|
|
45
|
+
bindrefresherrefresh?: (event: any) => void;
|
|
46
|
+
bindscrolltolower?: (event: any) => void;
|
|
47
|
+
bindscroll?: (event: any) => void;
|
|
48
|
+
[key: string]: any;
|
|
49
|
+
}
|
|
50
|
+
declare const _SectionList: import("react").ForwardRefExoticComponent<Omit<MpxSectionListProps, "ref"> & import("react").RefAttributes<any>>;
|
|
51
|
+
export default _SectionList;
|
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
import { forwardRef, useRef, useMemo, createElement, useImperativeHandle } from 'react';
|
|
2
|
+
import { SectionList, RefreshControl } from 'react-native';
|
|
3
|
+
import { Gesture, GestureDetector } from 'react-native-gesture-handler';
|
|
4
|
+
import { hasOwn } from '@mpxjs/utils';
|
|
5
|
+
import useInnerProps, { getCustomEvent } from './getInnerListeners';
|
|
6
|
+
import { extendObject, useLayout, useTransformStyle, flatGesture, wrapChildren, splitStyle, useTextPassThrough, splitProps } from './utils';
|
|
7
|
+
import Portal from './mpx-portal';
|
|
8
|
+
const TypedSectionList = SectionList;
|
|
9
|
+
const getGeneric = (generichash, generickey) => {
|
|
10
|
+
if (!generichash || !generickey)
|
|
11
|
+
return null;
|
|
12
|
+
return global.__mpxGenericsMap?.[generichash]?.[generickey]?.() || null;
|
|
13
|
+
};
|
|
14
|
+
const _SectionList = forwardRef((sectionListProps = {}, ref) => {
|
|
15
|
+
const { textProps, innerProps: props = {} } = splitProps(sectionListProps);
|
|
16
|
+
const { enhanced = false, bounces = true, height, width, generichash, style = {}, 'list-data': listData, 'scroll-event-throttle': scrollEventThrottle = 0, 'item-height': itemHeight = {}, 'section-header-height': sectionHeaderHeight = {}, 'section-footer-height': sectionFooterHeight = {}, 'list-header-height': listHeaderHeight = 0, 'list-header-data': listHeaderData = null, 'use-list-header': useListHeader = false, 'list-footer-data': listFooterData = null, 'use-list-footer': useListFooter = false, 'genericrecycle-item': genericrecycleItem, 'genericsection-header': genericsectionHeader, 'genericsection-footer': genericsectionFooter, 'genericlist-header': genericListHeader, 'genericlist-footer': genericListFooter, 'enable-var': enableVar, 'enable-text-pass-through': enableTextPassThrough, 'parent-width': parentWidth, 'parent-height': parentHeight, 'enable-sticky': enableSticky = false, 'enable-back-to-top': enableBackToTop = false, 'end-reached-threshold': onEndReachedThreshold = 0.1, 'refresher-enabled': refresherEnabled, 'show-scrollbar': showScrollbar = true, 'refresher-triggered': refresherTriggered, 'simultaneous-handlers': originSimultaneousHandlers, 'wait-for': waitFor } = props;
|
|
17
|
+
const refreshing = !!refresherTriggered;
|
|
18
|
+
const scrollViewRef = useRef(null);
|
|
19
|
+
const sectionListGestureRef = useRef();
|
|
20
|
+
const indexMap = useRef({});
|
|
21
|
+
const reverseIndexMap = useRef({});
|
|
22
|
+
const { normalStyle, hasVarDec, varContextRef, hasSelfPercent, hasPositionFixed, setWidth, setHeight } = useTransformStyle(style, { enableVar, parentWidth, parentHeight });
|
|
23
|
+
const { textStyle, innerStyle = {} } = splitStyle(normalStyle);
|
|
24
|
+
const textPassThrough = useTextPassThrough(textStyle, textProps, { enableTextPassThrough });
|
|
25
|
+
const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef: scrollViewRef });
|
|
26
|
+
const onRefresh = () => {
|
|
27
|
+
const { bindrefresherrefresh } = props;
|
|
28
|
+
bindrefresherrefresh &&
|
|
29
|
+
bindrefresherrefresh(getCustomEvent('refresherrefresh', {}, { layoutRef }, props));
|
|
30
|
+
};
|
|
31
|
+
const onEndReached = () => {
|
|
32
|
+
const { bindscrolltolower } = props;
|
|
33
|
+
bindscrolltolower &&
|
|
34
|
+
bindscrolltolower(getCustomEvent('scrolltolower', {}, { layoutRef }, props));
|
|
35
|
+
};
|
|
36
|
+
const onScroll = (event) => {
|
|
37
|
+
const { bindscroll } = props;
|
|
38
|
+
if (bindscroll) {
|
|
39
|
+
const { nativeEvent } = event;
|
|
40
|
+
bindscroll(getCustomEvent('scroll', event, {
|
|
41
|
+
detail: {
|
|
42
|
+
scrollTop: nativeEvent.contentOffset.y
|
|
43
|
+
},
|
|
44
|
+
layoutRef
|
|
45
|
+
}, props));
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
// 通过sectionIndex和rowIndex获取原始索引
|
|
49
|
+
const getOriginalIndex = (sectionIndex, rowIndex) => {
|
|
50
|
+
const key = `${sectionIndex}_${rowIndex}`;
|
|
51
|
+
return reverseIndexMap.current[key] ?? -1; // 如果找不到,返回-1
|
|
52
|
+
};
|
|
53
|
+
const scrollToIndex = ({ index, animated, viewOffset = 0, viewPosition = 0 }) => {
|
|
54
|
+
if (!scrollViewRef.current)
|
|
55
|
+
return;
|
|
56
|
+
// 通过索引映射表快速定位位置
|
|
57
|
+
const position = indexMap.current[index];
|
|
58
|
+
if (!position)
|
|
59
|
+
return;
|
|
60
|
+
const [sectionIndex, itemIndex] = position.split('_');
|
|
61
|
+
const targetSectionIndex = Number(sectionIndex) || 0;
|
|
62
|
+
const targetItemIndex = itemIndex === 'header'
|
|
63
|
+
? 0
|
|
64
|
+
: itemIndex === 'footer'
|
|
65
|
+
? convertedListData[targetSectionIndex].data.length + 1
|
|
66
|
+
: Number(itemIndex) + 1;
|
|
67
|
+
scrollViewRef.current.scrollToLocation?.({
|
|
68
|
+
itemIndex: targetItemIndex,
|
|
69
|
+
sectionIndex: targetSectionIndex,
|
|
70
|
+
animated,
|
|
71
|
+
viewOffset,
|
|
72
|
+
viewPosition
|
|
73
|
+
});
|
|
74
|
+
};
|
|
75
|
+
const getItemHeight = ({ sectionIndex, rowIndex }) => {
|
|
76
|
+
if (!itemHeight) {
|
|
77
|
+
return 0;
|
|
78
|
+
}
|
|
79
|
+
if (itemHeight.getter) {
|
|
80
|
+
const item = convertedListData[sectionIndex].data[rowIndex];
|
|
81
|
+
// 使用getOriginalIndex获取原始索引
|
|
82
|
+
const originalIndex = getOriginalIndex(sectionIndex, rowIndex);
|
|
83
|
+
return itemHeight.getter?.(item, originalIndex) || 0;
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
return itemHeight.value || 0;
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
const getSectionExtraHeight = ({ sectionIndex, type }) => {
|
|
90
|
+
const item = convertedListData[sectionIndex];
|
|
91
|
+
const isHeader = type === 'header';
|
|
92
|
+
if (!(isHeader ? item.hasSectionHeader : item.hasSectionFooter))
|
|
93
|
+
return 0;
|
|
94
|
+
const sectionExtraHeight = (isHeader ? sectionHeaderHeight : sectionFooterHeight);
|
|
95
|
+
if (sectionExtraHeight.getter) {
|
|
96
|
+
const sectionExtraData = isHeader ? item.headerData : item.footerData;
|
|
97
|
+
return sectionExtraHeight.getter?.(sectionExtraData, getOriginalIndex(sectionIndex, type)) || 0;
|
|
98
|
+
}
|
|
99
|
+
return sectionExtraHeight.value || 0;
|
|
100
|
+
};
|
|
101
|
+
const convertedListData = useMemo(() => {
|
|
102
|
+
const sections = [];
|
|
103
|
+
let currentSection = null;
|
|
104
|
+
// 清空之前的索引映射
|
|
105
|
+
indexMap.current = {};
|
|
106
|
+
// 清空反向索引映射
|
|
107
|
+
reverseIndexMap.current = {};
|
|
108
|
+
// 处理 listData 为空的情况
|
|
109
|
+
if (!listData || !listData.length) {
|
|
110
|
+
return sections;
|
|
111
|
+
}
|
|
112
|
+
listData.forEach((item, index) => {
|
|
113
|
+
if (item.isSectionHeader) {
|
|
114
|
+
// 如果已经存在一个 section,先把它添加到 sections 中
|
|
115
|
+
if (currentSection) {
|
|
116
|
+
sections.push(currentSection);
|
|
117
|
+
}
|
|
118
|
+
// 创建新的 section
|
|
119
|
+
currentSection = {
|
|
120
|
+
headerData: item,
|
|
121
|
+
footerData: null,
|
|
122
|
+
data: [],
|
|
123
|
+
hasSectionHeader: true,
|
|
124
|
+
hasSectionFooter: false
|
|
125
|
+
};
|
|
126
|
+
// 为 section header 添加索引映射
|
|
127
|
+
const sectionIndex = sections.length;
|
|
128
|
+
indexMap.current[index] = `${sectionIndex}_header`;
|
|
129
|
+
// 添加反向索引映射
|
|
130
|
+
reverseIndexMap.current[`${sectionIndex}_header`] = index;
|
|
131
|
+
}
|
|
132
|
+
else if (item.isSectionFooter) {
|
|
133
|
+
// 如果没有当前 section,创建一个默认的
|
|
134
|
+
if (!currentSection) {
|
|
135
|
+
// 创建默认section (无header的section)
|
|
136
|
+
currentSection = {
|
|
137
|
+
headerData: null,
|
|
138
|
+
footerData: null,
|
|
139
|
+
data: [],
|
|
140
|
+
hasSectionHeader: false,
|
|
141
|
+
hasSectionFooter: false
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
const sectionIndex = sections.length;
|
|
145
|
+
currentSection.footerData = item;
|
|
146
|
+
currentSection.hasSectionFooter = true;
|
|
147
|
+
indexMap.current[index] = `${sectionIndex}_footer`;
|
|
148
|
+
// 添加反向索引映射
|
|
149
|
+
reverseIndexMap.current[`${sectionIndex}_footer`] = index;
|
|
150
|
+
sections.push(currentSection);
|
|
151
|
+
currentSection = null;
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
// 如果没有当前 section,创建一个默认的
|
|
155
|
+
if (!currentSection) {
|
|
156
|
+
// 创建默认section (无header的section)
|
|
157
|
+
currentSection = {
|
|
158
|
+
headerData: null,
|
|
159
|
+
footerData: null,
|
|
160
|
+
data: [],
|
|
161
|
+
hasSectionHeader: false,
|
|
162
|
+
hasSectionFooter: false
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
// 将 item 添加到当前 section 的 data 中
|
|
166
|
+
const itemIndex = currentSection.data.length;
|
|
167
|
+
currentSection.data.push(item);
|
|
168
|
+
let sectionIndex;
|
|
169
|
+
// 为 item 添加索引映射 - 存储格式为: "sectionIndex_itemIndex"
|
|
170
|
+
if (!currentSection.hasSectionHeader && sections.length === 0) {
|
|
171
|
+
// 在默认section中(第一个且无header)
|
|
172
|
+
sectionIndex = 0;
|
|
173
|
+
indexMap.current[index] = `${sectionIndex}_${itemIndex}`;
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
// 在普通section中
|
|
177
|
+
sectionIndex = sections.length;
|
|
178
|
+
indexMap.current[index] = `${sectionIndex}_${itemIndex}`;
|
|
179
|
+
}
|
|
180
|
+
// 添加反向索引映射
|
|
181
|
+
reverseIndexMap.current[`${sectionIndex}_${itemIndex}`] = index;
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
// 添加最后一个 section
|
|
185
|
+
if (currentSection) {
|
|
186
|
+
sections.push(currentSection);
|
|
187
|
+
}
|
|
188
|
+
return sections;
|
|
189
|
+
}, [listData, listData?.length]);
|
|
190
|
+
const { getItemLayout } = useMemo(() => {
|
|
191
|
+
const layouts = [];
|
|
192
|
+
let offset = 0;
|
|
193
|
+
if (useListHeader) {
|
|
194
|
+
// 计算列表头部的高度
|
|
195
|
+
offset += listHeaderHeight;
|
|
196
|
+
}
|
|
197
|
+
// 遍历所有 sections
|
|
198
|
+
convertedListData.forEach((section, sectionIndex) => {
|
|
199
|
+
// 添加 section header 的位置信息
|
|
200
|
+
const headerHeight = getSectionExtraHeight({ sectionIndex, type: 'header' });
|
|
201
|
+
layouts.push({
|
|
202
|
+
length: headerHeight,
|
|
203
|
+
offset,
|
|
204
|
+
index: layouts.length
|
|
205
|
+
});
|
|
206
|
+
offset += headerHeight;
|
|
207
|
+
// 添加该 section 中所有 items 的位置信息
|
|
208
|
+
section.data.forEach((item, itemIndex) => {
|
|
209
|
+
const contentHeight = getItemHeight({ sectionIndex, rowIndex: itemIndex });
|
|
210
|
+
layouts.push({
|
|
211
|
+
length: contentHeight,
|
|
212
|
+
offset,
|
|
213
|
+
index: layouts.length
|
|
214
|
+
});
|
|
215
|
+
offset += contentHeight;
|
|
216
|
+
});
|
|
217
|
+
// 添加该 section 尾部位置信息
|
|
218
|
+
// 因为即使 sectionList 没传 renderSectionFooter,getItemLayout 中的 index 的计算也会包含尾部节点
|
|
219
|
+
const footerHeight = getSectionExtraHeight({ sectionIndex, type: 'footer' });
|
|
220
|
+
layouts.push({
|
|
221
|
+
length: footerHeight,
|
|
222
|
+
offset,
|
|
223
|
+
index: layouts.length
|
|
224
|
+
});
|
|
225
|
+
offset += footerHeight;
|
|
226
|
+
});
|
|
227
|
+
return {
|
|
228
|
+
itemLayouts: layouts,
|
|
229
|
+
getItemLayout: (data, index) => layouts[index]
|
|
230
|
+
};
|
|
231
|
+
}, [convertedListData, useListHeader, itemHeight.value, itemHeight.getter, sectionHeaderHeight.value, sectionHeaderHeight.getter, sectionFooterHeight.value, sectionFooterHeight.getter, listHeaderHeight]);
|
|
232
|
+
const scrollAdditionalProps = extendObject({
|
|
233
|
+
style: [
|
|
234
|
+
hasOwn(innerStyle, 'flex') || hasOwn(innerStyle, 'flexGrow') ? null : { flexGrow: 0 },
|
|
235
|
+
{ height, width },
|
|
236
|
+
innerStyle,
|
|
237
|
+
layoutStyle
|
|
238
|
+
],
|
|
239
|
+
alwaysBounceVertical: false,
|
|
240
|
+
alwaysBounceHorizontal: false,
|
|
241
|
+
scrollEventThrottle: scrollEventThrottle,
|
|
242
|
+
scrollsToTop: enableBackToTop,
|
|
243
|
+
showsVerticalScrollIndicator: showScrollbar,
|
|
244
|
+
onEndReachedThreshold,
|
|
245
|
+
ref: scrollViewRef,
|
|
246
|
+
bounces: enhanced ? bounces : false,
|
|
247
|
+
stickySectionHeadersEnabled: enableSticky,
|
|
248
|
+
onScroll: onScroll,
|
|
249
|
+
onEndReached: onEndReached
|
|
250
|
+
}, refresherEnabled ? { refreshing } : null, layoutProps);
|
|
251
|
+
const nativeGesture = useMemo(() => {
|
|
252
|
+
const simultaneousHandlers = flatGesture(originSimultaneousHandlers);
|
|
253
|
+
const waitForHandlers = flatGesture(waitFor);
|
|
254
|
+
const gesture = Gesture.Native().withRef(sectionListGestureRef);
|
|
255
|
+
if (simultaneousHandlers && simultaneousHandlers.length) {
|
|
256
|
+
gesture.simultaneousWithExternalGesture(...simultaneousHandlers);
|
|
257
|
+
}
|
|
258
|
+
if (waitForHandlers && waitForHandlers.length) {
|
|
259
|
+
gesture.requireExternalGestureToFail(...waitForHandlers);
|
|
260
|
+
}
|
|
261
|
+
return gesture;
|
|
262
|
+
}, [originSimultaneousHandlers, waitFor]);
|
|
263
|
+
useImperativeHandle(ref, () => {
|
|
264
|
+
return {
|
|
265
|
+
gestureRef: sectionListGestureRef,
|
|
266
|
+
scrollToIndex
|
|
267
|
+
};
|
|
268
|
+
});
|
|
269
|
+
const innerProps = useInnerProps(extendObject({}, props, scrollAdditionalProps), [
|
|
270
|
+
'id',
|
|
271
|
+
'enhanced',
|
|
272
|
+
'height',
|
|
273
|
+
'width',
|
|
274
|
+
'list-data',
|
|
275
|
+
'item-height',
|
|
276
|
+
'section-header-height',
|
|
277
|
+
'section-footer-height',
|
|
278
|
+
'list-header-height',
|
|
279
|
+
'list-header-data',
|
|
280
|
+
'use-list-header',
|
|
281
|
+
'list-footer-data',
|
|
282
|
+
'use-list-footer',
|
|
283
|
+
'genericrecycle-item',
|
|
284
|
+
'genericsection-header',
|
|
285
|
+
'genericsection-footer',
|
|
286
|
+
'genericlist-header',
|
|
287
|
+
'genericlist-footer',
|
|
288
|
+
'enable-text-pass-through',
|
|
289
|
+
'show-scrollbar',
|
|
290
|
+
'lower-threshold',
|
|
291
|
+
'scroll-event-throttle',
|
|
292
|
+
'enable-sticky',
|
|
293
|
+
'enable-back-to-top',
|
|
294
|
+
'end-reached-threshold',
|
|
295
|
+
'refresher-triggered',
|
|
296
|
+
'refresher-enabled',
|
|
297
|
+
'bindrefresherrefresh',
|
|
298
|
+
'bindscrolltolower',
|
|
299
|
+
'bindscroll',
|
|
300
|
+
'simultaneous-handlers',
|
|
301
|
+
'wait-for'
|
|
302
|
+
], { layoutRef });
|
|
303
|
+
// 使用 useMemo 获取 GenericComponent 并创建渲染函数,避免每次组件更新都重新创建函数引用导致不必要的重新渲染
|
|
304
|
+
const renderItem = useMemo(() => {
|
|
305
|
+
const ItemComponent = getGeneric(generichash, genericrecycleItem);
|
|
306
|
+
if (!ItemComponent)
|
|
307
|
+
return undefined;
|
|
308
|
+
return ({ item }) => createElement(ItemComponent, { itemData: item });
|
|
309
|
+
}, [generichash, genericrecycleItem]);
|
|
310
|
+
const renderSectionHeader = useMemo(() => {
|
|
311
|
+
const SectionHeaderComponent = getGeneric(generichash, genericsectionHeader);
|
|
312
|
+
if (!SectionHeaderComponent)
|
|
313
|
+
return undefined;
|
|
314
|
+
return (sectionData) => {
|
|
315
|
+
if (!sectionData.section.hasSectionHeader)
|
|
316
|
+
return null;
|
|
317
|
+
return createElement(SectionHeaderComponent, { itemData: sectionData.section.headerData });
|
|
318
|
+
};
|
|
319
|
+
}, [generichash, genericsectionHeader]);
|
|
320
|
+
const renderSectionFooter = useMemo(() => {
|
|
321
|
+
const SectionFooterComponent = getGeneric(generichash, genericsectionFooter);
|
|
322
|
+
if (!SectionFooterComponent)
|
|
323
|
+
return undefined;
|
|
324
|
+
return (sectionData) => {
|
|
325
|
+
if (!sectionData.section.hasSectionFooter)
|
|
326
|
+
return null;
|
|
327
|
+
return createElement(SectionFooterComponent, { itemData: sectionData.section.footerData });
|
|
328
|
+
};
|
|
329
|
+
}, [generichash, genericsectionFooter]);
|
|
330
|
+
const ListHeaderGenericComponent = useMemo(() => {
|
|
331
|
+
if (!useListHeader)
|
|
332
|
+
return null;
|
|
333
|
+
return getGeneric(generichash, genericListHeader);
|
|
334
|
+
}, [useListHeader, generichash, genericListHeader]);
|
|
335
|
+
const ListFooterGenericComponent = useMemo(() => {
|
|
336
|
+
if (!useListFooter)
|
|
337
|
+
return null;
|
|
338
|
+
return getGeneric(generichash, genericListFooter);
|
|
339
|
+
}, [useListFooter, generichash, genericListFooter]);
|
|
340
|
+
const ListHeaderComponent = useMemo(() => {
|
|
341
|
+
if (!ListHeaderGenericComponent)
|
|
342
|
+
return null;
|
|
343
|
+
return createElement(ListHeaderGenericComponent, { listHeaderData });
|
|
344
|
+
}, [ListHeaderGenericComponent, listHeaderData]);
|
|
345
|
+
const ListFooterComponent = useMemo(() => {
|
|
346
|
+
if (!ListFooterGenericComponent)
|
|
347
|
+
return null;
|
|
348
|
+
return createElement(ListFooterGenericComponent, { listFooterData });
|
|
349
|
+
}, [ListFooterGenericComponent, listFooterData]);
|
|
350
|
+
const rnSectionListProps = extendObject({
|
|
351
|
+
sections: convertedListData,
|
|
352
|
+
renderItem: renderItem,
|
|
353
|
+
getItemLayout: getItemLayout,
|
|
354
|
+
ListHeaderComponent: useListHeader ? ListHeaderComponent : null,
|
|
355
|
+
ListFooterComponent: useListFooter ? ListFooterComponent : null,
|
|
356
|
+
renderSectionHeader: renderSectionHeader,
|
|
357
|
+
renderSectionFooter: renderSectionFooter,
|
|
358
|
+
refreshControl: refresherEnabled
|
|
359
|
+
? createElement(RefreshControl, {
|
|
360
|
+
onRefresh: onRefresh,
|
|
361
|
+
refreshing: refreshing
|
|
362
|
+
})
|
|
363
|
+
: undefined
|
|
364
|
+
}, innerProps);
|
|
365
|
+
let sectionListComponent = wrapChildren(createElement(GestureDetector, { gesture: nativeGesture }, createElement(TypedSectionList, rnSectionListProps)), {
|
|
366
|
+
hasVarDec,
|
|
367
|
+
varContext: varContextRef.current,
|
|
368
|
+
textPassThrough
|
|
369
|
+
});
|
|
370
|
+
if (hasPositionFixed) {
|
|
371
|
+
sectionListComponent = createElement(Portal, null, sectionListComponent);
|
|
372
|
+
}
|
|
373
|
+
return sectionListComponent;
|
|
374
|
+
});
|
|
375
|
+
_SectionList.displayName = 'MpxSectionList';
|
|
376
|
+
export default _SectionList;
|