@mpxjs/webpack-plugin 2.9.69-beta.0 → 2.9.69-beta.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/index.js +17 -1
- package/lib/platform/style/wx/index.js +18 -18
- package/lib/platform/template/wx/component-config/movable-view.js +8 -1
- package/lib/platform/template/wx/component-config/scroll-view.js +1 -1
- package/lib/resolver/AddEnvPlugin.js +1 -0
- package/lib/resolver/AddModePlugin.js +1 -0
- package/lib/runtime/components/react/context.ts +8 -0
- package/lib/runtime/components/react/dist/context.js +2 -0
- package/lib/runtime/components/react/dist/getInnerListeners.js +3 -4
- package/lib/runtime/components/react/dist/mpx-input.jsx +1 -1
- package/lib/runtime/components/react/dist/mpx-movable-view.jsx +1 -1
- package/lib/runtime/components/react/dist/mpx-picker-view-column-item.jsx +1 -1
- package/lib/runtime/components/react/dist/mpx-picker-view-column.jsx +54 -52
- package/lib/runtime/components/react/dist/mpx-picker-view.jsx +1 -1
- package/lib/runtime/components/react/dist/mpx-rich-text/index.jsx +10 -11
- package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +21 -6
- package/lib/runtime/components/react/dist/mpx-swiper-item.jsx +25 -8
- package/lib/runtime/components/react/dist/mpx-swiper.jsx +150 -148
- package/lib/runtime/components/react/dist/mpx-view.jsx +9 -40
- package/lib/runtime/components/react/dist/mpx-web-view.jsx +50 -12
- package/lib/runtime/components/react/dist/pickerFaces.js +1 -1
- package/lib/runtime/components/react/dist/useAnimationHooks.js +1 -1
- package/lib/runtime/components/react/dist/utils.jsx +63 -4
- package/lib/runtime/components/react/getInnerListeners.ts +3 -5
- package/lib/runtime/components/react/mpx-input.tsx +1 -1
- package/lib/runtime/components/react/mpx-movable-view.tsx +1 -1
- package/lib/runtime/components/react/mpx-picker-view-column-item.tsx +88 -0
- package/lib/runtime/components/react/mpx-picker-view-column.tsx +177 -159
- package/lib/runtime/components/react/mpx-picker-view.tsx +35 -37
- package/lib/runtime/components/react/mpx-rich-text/index.tsx +12 -18
- package/lib/runtime/components/react/mpx-scroll-view.tsx +30 -13
- package/lib/runtime/components/react/mpx-swiper-item.tsx +38 -10
- package/lib/runtime/components/react/mpx-swiper.tsx +690 -0
- package/lib/runtime/components/react/mpx-view.tsx +11 -51
- package/lib/runtime/components/react/mpx-web-view.tsx +57 -13
- package/lib/runtime/components/react/pickerFaces.ts +15 -7
- package/lib/runtime/components/react/pickerVIewContext.ts +18 -0
- package/lib/runtime/components/react/pickerViewMask.tsx +30 -0
- package/lib/runtime/components/react/{pickerOverlay.tsx → pickerViewOverlay.tsx} +5 -3
- package/lib/runtime/components/react/types/global.d.ts +3 -1
- package/lib/runtime/components/react/useAnimationHooks.ts +1 -1
- package/lib/runtime/components/react/utils.tsx +75 -5
- package/lib/style-compiler/index.js +3 -4
- package/lib/style-compiler/strip-conditional-loader.js +118 -0
- package/lib/template-compiler/compiler.js +9 -14
- package/lib/utils/pre-process-json.js +5 -9
- package/package.json +1 -1
- 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/index.js
CHANGED
|
@@ -54,11 +54,13 @@ const wxssLoaderPath = normalize.lib('wxss/index')
|
|
|
54
54
|
const wxmlLoaderPath = normalize.lib('wxml/loader')
|
|
55
55
|
const wxsLoaderPath = normalize.lib('wxs/loader')
|
|
56
56
|
const styleCompilerPath = normalize.lib('style-compiler/index')
|
|
57
|
+
const styleStripConditaionalPath = normalize.lib('style-compiler/strip-conditional-loader')
|
|
57
58
|
const templateCompilerPath = normalize.lib('template-compiler/index')
|
|
58
59
|
const jsonCompilerPath = normalize.lib('json-compiler/index')
|
|
59
60
|
const jsonThemeCompilerPath = normalize.lib('json-compiler/theme')
|
|
60
61
|
const jsonPluginCompilerPath = normalize.lib('json-compiler/plugin')
|
|
61
62
|
const extractorPath = normalize.lib('extractor')
|
|
63
|
+
const selectorPath = normalize.lib('selector')
|
|
62
64
|
const async = require('async')
|
|
63
65
|
const { parseQuery } = require('loader-utils')
|
|
64
66
|
const stringifyLoadersAndResource = require('./utils/stringify-loaders-resource')
|
|
@@ -1775,7 +1777,7 @@ try {
|
|
|
1775
1777
|
})
|
|
1776
1778
|
|
|
1777
1779
|
const typeLoaderProcessInfo = {
|
|
1778
|
-
styles: ['node_modules/css-loader', wxssLoaderPath, styleCompilerPath],
|
|
1780
|
+
styles: ['node_modules/css-loader', wxssLoaderPath, styleCompilerPath, styleStripConditaionalPath],
|
|
1779
1781
|
template: ['node_modules/html-loader', wxmlLoaderPath, templateCompilerPath]
|
|
1780
1782
|
}
|
|
1781
1783
|
|
|
@@ -1833,6 +1835,20 @@ try {
|
|
|
1833
1835
|
loader: extractorPath
|
|
1834
1836
|
})
|
|
1835
1837
|
}
|
|
1838
|
+
if (type === 'styles') {
|
|
1839
|
+
// 判断最后一个loader是否是 selectorPath, 如果是,则在sectorPath之前插入strip-conditional
|
|
1840
|
+
const lastLoader = loaders[loaders.length - 1]
|
|
1841
|
+
if (lastLoader.loader.includes(selectorPath)) {
|
|
1842
|
+
loaders.splice(loaders.length - 1, 0, {
|
|
1843
|
+
loader: styleStripConditaionalPath
|
|
1844
|
+
})
|
|
1845
|
+
} else {
|
|
1846
|
+
// 在最后一个插入strip-conditional
|
|
1847
|
+
loaders.push({
|
|
1848
|
+
loader: styleStripConditaionalPath
|
|
1849
|
+
})
|
|
1850
|
+
}
|
|
1851
|
+
}
|
|
1836
1852
|
createData.resource = addQuery(createData.resource, { mpx: MPX_PROCESSED_FLAG }, true)
|
|
1837
1853
|
}
|
|
1838
1854
|
// mpxStyleOptions 为 mpx style 文件的标识,避免 Vue 文件插入 styleCompiler 后导致 vue scoped 样式隔离失效
|
|
@@ -374,11 +374,11 @@ module.exports = function getSpec ({ warn, error }) {
|
|
|
374
374
|
// transform 转换
|
|
375
375
|
const formatTransform = ({ prop, value, selector }, { mode }) => {
|
|
376
376
|
// css var & 数组直接返回
|
|
377
|
-
if (Array.isArray(value) ||
|
|
377
|
+
if (Array.isArray(value) || cssVariableExp.test(value)) return { prop, value }
|
|
378
378
|
const values = parseValues(value)
|
|
379
379
|
const transform = []
|
|
380
380
|
values.forEach(item => {
|
|
381
|
-
const match = item.match(/([/\w]+)\((
|
|
381
|
+
const match = item.match(/([/\w]+)\((.+)\)/)
|
|
382
382
|
if (match && match.length >= 3) {
|
|
383
383
|
let key = match[1]
|
|
384
384
|
const val = match[2]
|
|
@@ -407,23 +407,23 @@ module.exports = function getSpec ({ warn, error }) {
|
|
|
407
407
|
case 'rotate3d': // x y z angle
|
|
408
408
|
case 'translate3d': // x y 支持 z不支持
|
|
409
409
|
case 'scale3d': // x y 支持 z不支持
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
}
|
|
418
|
-
const xyz = ['X', 'Y', 'Z']
|
|
419
|
-
transform.push(...vals.map((v, index) => {
|
|
420
|
-
if (key !== 'rotate' && index > 1) {
|
|
421
|
-
unsupportedPropError({ prop: `${key}Z`, value, selector }, { mode })
|
|
422
|
-
}
|
|
423
|
-
return { [`${key}${xyz[index] || ''}`]: v.trim() }
|
|
424
|
-
}))
|
|
425
|
-
break
|
|
410
|
+
{
|
|
411
|
+
// 2 个以上的值处理
|
|
412
|
+
key = key.replace('3d', '')
|
|
413
|
+
const vals = parseValues(val, ',').splice(0, key === 'rotate' ? 4 : 3)
|
|
414
|
+
// scale(.5) === scaleX(.5) scaleY(.5)
|
|
415
|
+
if (vals.length === 1 && key === 'scale') {
|
|
416
|
+
vals.push(vals[0])
|
|
426
417
|
}
|
|
418
|
+
const xyz = ['X', 'Y', 'Z']
|
|
419
|
+
transform.push(...vals.map((v, index) => {
|
|
420
|
+
if (key !== 'rotate' && index > 1) {
|
|
421
|
+
unsupportedPropError({ prop: `${key}Z`, value, selector }, { mode })
|
|
422
|
+
}
|
|
423
|
+
return { [`${key}${xyz[index] || ''}`]: v.trim() }
|
|
424
|
+
}))
|
|
425
|
+
break
|
|
426
|
+
}
|
|
427
427
|
case 'translateZ':
|
|
428
428
|
case 'scaleZ':
|
|
429
429
|
default:
|
|
@@ -2,6 +2,8 @@ const TAG_NAME = 'movable-view'
|
|
|
2
2
|
|
|
3
3
|
module.exports = function ({ print }) {
|
|
4
4
|
const aliEventLog = print({ platform: 'ali', tag: TAG_NAME, isError: false, type: 'event' })
|
|
5
|
+
const androidEventLog = print({ platform: 'android', tag: TAG_NAME, isError: false, type: 'event' })
|
|
6
|
+
const iosEventLog = print({ platform: 'ios', tag: TAG_NAME, isError: false, type: 'event' })
|
|
5
7
|
const qaPropLog = print({ platform: 'qa', tag: TAG_NAME, isError: false })
|
|
6
8
|
const androidPropLog = print({ platform: 'android', tag: TAG_NAME, isError: false })
|
|
7
9
|
const iosPropLog = print({ platform: 'ios', tag: TAG_NAME, isError: false })
|
|
@@ -27,7 +29,7 @@ module.exports = function ({ print }) {
|
|
|
27
29
|
android: androidPropLog
|
|
28
30
|
},
|
|
29
31
|
{
|
|
30
|
-
test: /^(
|
|
32
|
+
test: /^(damping|friction|scale|scale-min|scale-max|scale-value)$/,
|
|
31
33
|
ios: iosPropLog,
|
|
32
34
|
android: androidPropLog
|
|
33
35
|
}
|
|
@@ -36,6 +38,11 @@ module.exports = function ({ print }) {
|
|
|
36
38
|
{
|
|
37
39
|
test: /^(htouchmove|vtouchmove)$/,
|
|
38
40
|
ali: aliEventLog
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
test: /^(bindscale)$/,
|
|
44
|
+
ios: iosEventLog,
|
|
45
|
+
android: androidEventLog
|
|
39
46
|
}
|
|
40
47
|
]
|
|
41
48
|
}
|
|
@@ -53,7 +53,7 @@ module.exports = function ({ print }) {
|
|
|
53
53
|
qa: qaPropLog
|
|
54
54
|
},
|
|
55
55
|
{
|
|
56
|
-
test: /^(
|
|
56
|
+
test: /^(refresher-threshold|enable-passive|scroll-anchoring|using-sticky|fast-deceleration|enable-flex)$/,
|
|
57
57
|
android: androidPropLog,
|
|
58
58
|
ios: iosPropLog
|
|
59
59
|
},
|
|
@@ -34,6 +34,7 @@ module.exports = class AddEnvPlugin {
|
|
|
34
34
|
if (!extname || !matchCondition(resourcePath, this.fileConditionRules)) return callback()
|
|
35
35
|
const queryObj = parseQuery(request.query || '?')
|
|
36
36
|
queryObj.infix = `${queryObj.infix || ''}.${env}`
|
|
37
|
+
// css | stylus | less | sass 中 import file 过滤query,避免在对应的 loader 中无法读取到文件
|
|
37
38
|
obj.query = stringifyQuery(queryObj)
|
|
38
39
|
obj.path = addInfix(resourcePath, env, extname)
|
|
39
40
|
obj.relativePath = request.relativePath && addInfix(request.relativePath, env, extname)
|
|
@@ -43,6 +43,7 @@ module.exports = class AddModePlugin {
|
|
|
43
43
|
resolver.doResolve(target, Object.assign({}, request, obj), 'add mode: ' + mode, resolveContext, (err, result) => {
|
|
44
44
|
if (defaultMode && !result) {
|
|
45
45
|
queryObj.infix = `${queryInfix || ''}.${defaultMode}`
|
|
46
|
+
// css | stylus | less | sass 中 import file 过滤query,避免在对应的 loader 中无法读取到文件
|
|
46
47
|
obj.query = stringifyQuery(queryObj)
|
|
47
48
|
obj.path = addInfix(resourcePath, defaultMode, extname)
|
|
48
49
|
resolver.doResolve(target, Object.assign({}, request, obj), 'add mode: ' + defaultMode, resolveContext, (err, result) => {
|
|
@@ -33,6 +33,10 @@ export interface IntersectionObserver {
|
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
export interface ScrollViewContextValue {
|
|
37
|
+
gestureRef: React.RefObject<any> | null
|
|
38
|
+
}
|
|
39
|
+
|
|
36
40
|
export const MovableAreaContext = createContext({ width: 0, height: 0 })
|
|
37
41
|
|
|
38
42
|
export const FormContext = createContext<FormContextValue | null>(null)
|
|
@@ -51,4 +55,8 @@ export const IntersectionObserverContext = createContext<IntersectionObserver |
|
|
|
51
55
|
|
|
52
56
|
export const RouteContext = createContext<number | null>(null)
|
|
53
57
|
|
|
58
|
+
export const SwiperContext = createContext({})
|
|
59
|
+
|
|
54
60
|
export const KeyboardAvoidContext = createContext<KeyboardAvoidContextValue | null>(null)
|
|
61
|
+
|
|
62
|
+
export const ScrollViewContext = createContext<ScrollViewContextValue>({ gestureRef: null })
|
|
@@ -8,4 +8,6 @@ export const PickerContext = createContext(null);
|
|
|
8
8
|
export const VarContext = createContext({});
|
|
9
9
|
export const IntersectionObserverContext = createContext(null);
|
|
10
10
|
export const RouteContext = createContext(null);
|
|
11
|
+
export const SwiperContext = createContext({});
|
|
11
12
|
export const KeyboardAvoidContext = createContext(null);
|
|
13
|
+
export const ScrollViewContext = createContext({ gestureRef: null });
|
|
@@ -213,7 +213,6 @@ const useInnerProps = (props = {}, additionalProps = {}, userRemoveProps = [], r
|
|
|
213
213
|
const eventConfig = {};
|
|
214
214
|
const config = rawConfig || {
|
|
215
215
|
layoutRef: { current: {} },
|
|
216
|
-
disableTouch: false,
|
|
217
216
|
disableTap: false
|
|
218
217
|
};
|
|
219
218
|
const removeProps = [
|
|
@@ -237,10 +236,10 @@ const useInnerProps = (props = {}, additionalProps = {}, userRemoveProps = [], r
|
|
|
237
236
|
rawEventKeys.push(key);
|
|
238
237
|
}
|
|
239
238
|
}
|
|
240
|
-
if (!rawEventKeys.length || config.disableTouch) {
|
|
241
|
-
return omit(propsRef.current, removeProps);
|
|
242
|
-
}
|
|
243
239
|
const events = useMemo(() => {
|
|
240
|
+
if (!rawEventKeys.length) {
|
|
241
|
+
return {};
|
|
242
|
+
}
|
|
244
243
|
const transformedEventKeys = rawEventKeys.reduce((acc, key) => {
|
|
245
244
|
if (propsRef.current[key]) {
|
|
246
245
|
return acc.concat(eventConfig[key]);
|
|
@@ -54,7 +54,7 @@ const keyboardTypeMap = {
|
|
|
54
54
|
}) || ''
|
|
55
55
|
};
|
|
56
56
|
const Input = forwardRef((props, ref) => {
|
|
57
|
-
const { style = {}, allowFontScaling = false, type = 'text', value, password, 'placeholder-style': placeholderStyle, disabled, maxlength = 140, 'auto-focus': autoFocus, focus, 'confirm-type': confirmType = 'done', 'confirm-hold': confirmHold = false, cursor, 'cursor-color': cursorColor, 'selection-start': selectionStart = -1, 'selection-end': selectionEnd = -1, 'enable-var': enableVar, 'external-var-context': externalVarContext, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight, 'adjust-position': adjustPosition =
|
|
57
|
+
const { style = {}, allowFontScaling = false, type = 'text', value, password, 'placeholder-style': placeholderStyle, disabled, maxlength = 140, 'auto-focus': autoFocus, focus, 'confirm-type': confirmType = 'done', 'confirm-hold': confirmHold = false, cursor, 'cursor-color': cursorColor, 'selection-start': selectionStart = -1, 'selection-end': selectionEnd = -1, 'enable-var': enableVar, 'external-var-context': externalVarContext, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight, 'adjust-position': adjustPosition = false, bindinput, bindfocus, bindblur, bindconfirm, bindselectionchange,
|
|
58
58
|
// private
|
|
59
59
|
multiline, 'auto-height': autoHeight, bindlinechange } = props;
|
|
60
60
|
const formContext = useContext(FormContext);
|
|
@@ -3,7 +3,7 @@ import Reanimated, { Extrapolation, interpolate, useAnimatedStyle, useSharedValu
|
|
|
3
3
|
import { wrapChildren, extendObject } from './utils';
|
|
4
4
|
import { createFaces } from './pickerFaces';
|
|
5
5
|
import { usePickerViewColumnAnimationContext } from './pickerVIewContext';
|
|
6
|
-
const _PickerViewColumnItem = ({ item, index, itemHeight, itemWidth, textStyleFromParent, textStyle, hasVarDec, varContext, textProps, visibleCount, onItemLayout }) => {
|
|
6
|
+
const _PickerViewColumnItem = ({ item, index, itemHeight, itemWidth = '100%', textStyleFromParent, textStyle, hasVarDec, varContext, textProps, visibleCount, onItemLayout }) => {
|
|
7
7
|
const offsetYShared = usePickerViewColumnAnimationContext();
|
|
8
8
|
const facesShared = useSharedValue(createFaces(itemHeight, visibleCount));
|
|
9
9
|
useEffect(() => {
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import React, { forwardRef, useRef, useState, useMemo, useEffect, useCallback } from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { SafeAreaView, StyleSheet } from 'react-native';
|
|
3
3
|
import Reanimated, { useAnimatedRef, useScrollViewOffset } from 'react-native-reanimated';
|
|
4
|
-
import {
|
|
5
|
-
import { useTransformStyle, splitStyle, splitProps, useLayout, usePrevious } from './utils';
|
|
4
|
+
import { useTransformStyle, splitStyle, splitProps, useLayout, usePrevious, isAndroid, useDebounceCallback, useStableCallback, isIOS } from './utils';
|
|
6
5
|
import useNodesRef from './useNodesRef';
|
|
7
6
|
import PickerOverlay from './pickerViewOverlay';
|
|
8
7
|
import PickerMask from './pickerViewMask';
|
|
@@ -21,11 +20,8 @@ const _PickerViewColumn = forwardRef((props, ref) => {
|
|
|
21
20
|
style: normalStyle
|
|
22
21
|
});
|
|
23
22
|
const { height: pickerH, itemHeight } = wrapperStyle;
|
|
24
|
-
const [scrollViewWidth, setScrollViewWidth] = useState('100%');
|
|
25
|
-
const [itemRawW, setItemRawW] = useState('100%');
|
|
26
23
|
const [itemRawH, setItemRawH] = useState(itemHeight);
|
|
27
24
|
const maxIndex = useMemo(() => columnData.length - 1, [columnData]);
|
|
28
|
-
const maxScrollViewWidth = useRef(-1);
|
|
29
25
|
const prevScrollingInfo = useRef({ index: initialIndex, y: 0 });
|
|
30
26
|
const touching = useRef(false);
|
|
31
27
|
const scrolling = useRef(false);
|
|
@@ -39,13 +35,9 @@ const _PickerViewColumn = forwardRef((props, ref) => {
|
|
|
39
35
|
setHeight,
|
|
40
36
|
nodeRef: scrollViewRef
|
|
41
37
|
});
|
|
42
|
-
// console.log('[mpx-picker-view-column], render ---> columnIndex=', columnIndex, 'initialIndex=', initialIndex, 'columnData=', columnData.length)
|
|
43
|
-
|
|
44
|
-
// x: 0,
|
|
45
|
-
// y: itemRawH * initialIndex
|
|
46
|
-
// }), [itemRawH])
|
|
38
|
+
// console.log('[mpx-picker-view-column], render ---> columnIndex=', columnIndex, 'initialIndex=', initialIndex, 'columnData=', columnData.length, 'pickerH=', pickerH, 'itemRawH=', itemRawH, 'itemHeight=', itemHeight)
|
|
39
|
+
const paddingHeight = useMemo(() => Math.round((pickerH - itemHeight) / 2), [pickerH, itemHeight]);
|
|
47
40
|
const snapToOffsets = useMemo(() => columnData.map((_, i) => i * itemRawH), [columnData, itemRawH]);
|
|
48
|
-
const paddingHeight = useMemo(() => Math.round((pickerH - itemRawH) / 2), [pickerH, itemRawH]);
|
|
49
41
|
const contentContainerStyle = useMemo(() => {
|
|
50
42
|
return [{ paddingVertical: paddingHeight }];
|
|
51
43
|
}, [paddingHeight]);
|
|
@@ -53,6 +45,26 @@ const _PickerViewColumn = forwardRef((props, ref) => {
|
|
|
53
45
|
const calc = Math.round(y / itemRawH);
|
|
54
46
|
return Math.max(0, Math.min(calc, maxIndex));
|
|
55
47
|
}, [itemRawH, maxIndex]);
|
|
48
|
+
const getYofIndex = useCallback((index) => {
|
|
49
|
+
return index * itemRawH;
|
|
50
|
+
}, [itemRawH]);
|
|
51
|
+
const stableResetScrollPosition = useStableCallback((y) => {
|
|
52
|
+
console.log('[mpx-picker-view-column], reset --->', 'columnIndex=', columnIndex, 'y=', y, touching.current, scrolling.current);
|
|
53
|
+
if (touching.current || scrolling.current) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
// needReset.current = true
|
|
57
|
+
if (y % itemRawH !== 0) {
|
|
58
|
+
scrolling.current = true;
|
|
59
|
+
const targetIndex = getIndex(y);
|
|
60
|
+
const targetY = getYofIndex(targetIndex);
|
|
61
|
+
scrollViewRef.current?.scrollTo({ x: 0, y: targetY, animated: false });
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
onMomentumScrollEnd({ nativeEvent: { contentOffset: { y } } });
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
const debounceResetScrollPosition = useDebounceCallback(stableResetScrollPosition, 10);
|
|
56
68
|
useEffect(() => {
|
|
57
69
|
if (!scrollViewRef.current ||
|
|
58
70
|
!itemRawH ||
|
|
@@ -64,83 +76,72 @@ const _PickerViewColumn = forwardRef((props, ref) => {
|
|
|
64
76
|
maxIndex !== prevMaxIndex) {
|
|
65
77
|
return;
|
|
66
78
|
}
|
|
67
|
-
// console.log('[mpx-picker-view-column], useEffect ---> columnIndex=', columnIndex, 'initialIndex=', initialIndex, 'y=', itemRawH * initialIndex, `${scrollViewRef.current?.scrollTo}`)
|
|
68
79
|
setTimeout(() => {
|
|
69
80
|
scrollViewRef.current?.scrollTo({
|
|
70
81
|
x: 0,
|
|
71
|
-
y:
|
|
82
|
+
y: getYofIndex(initialIndex),
|
|
72
83
|
animated: false
|
|
73
84
|
});
|
|
74
|
-
}, 0);
|
|
85
|
+
}, isAndroid ? 200 : 0);
|
|
75
86
|
activeIndex.current = initialIndex;
|
|
76
87
|
}, [itemRawH, initialIndex]);
|
|
77
88
|
const onContentSizeChange = (_w, h) => {
|
|
78
|
-
const y =
|
|
79
|
-
// console.log('[mpx-picker-view-column], onContentSizeChange --->', 'columnIndex=', columnIndex, '_w=', _w, 'h=', h, 'y=', y)
|
|
89
|
+
const y = getYofIndex(initialIndex);
|
|
80
90
|
if (y <= h) {
|
|
81
91
|
setTimeout(() => {
|
|
82
92
|
scrollViewRef.current?.scrollTo({ x: 0, y, animated: false });
|
|
83
93
|
}, 0);
|
|
84
94
|
}
|
|
85
95
|
};
|
|
86
|
-
const onScrollViewLayout = (e) => {
|
|
87
|
-
const { width } = e.nativeEvent.layout;
|
|
88
|
-
const widthInt = Math.ceil(width);
|
|
89
|
-
// console.log('[mpx-picker-view-column], onScrollViewLayout --->', 'columnIndex=', columnIndex, 'widthInt=', widthInt, 'scrollViewWidth=', scrollViewWidth)
|
|
90
|
-
if (widthInt !== scrollViewWidth) {
|
|
91
|
-
const maxW = maxScrollViewWidth.current;
|
|
92
|
-
if (maxW !== -1 && widthInt > maxW) {
|
|
93
|
-
return;
|
|
94
|
-
}
|
|
95
|
-
if (maxW === -1) {
|
|
96
|
-
maxScrollViewWidth.current = Math.ceil(widthInt * 1.5);
|
|
97
|
-
}
|
|
98
|
-
setScrollViewWidth(widthInt);
|
|
99
|
-
}
|
|
100
|
-
if (itemRawW === '100%') {
|
|
101
|
-
setItemRawW(widthInt);
|
|
102
|
-
}
|
|
103
|
-
};
|
|
104
96
|
const onItemLayout = (e) => {
|
|
105
97
|
const { height: rawH } = e.nativeEvent.layout;
|
|
106
98
|
if (rawH && itemRawH !== rawH) {
|
|
107
99
|
setItemRawH(rawH);
|
|
108
100
|
}
|
|
109
101
|
};
|
|
110
|
-
const
|
|
102
|
+
const onScrollBeginDrag = () => {
|
|
103
|
+
isIOS && debounceResetScrollPosition.clear();
|
|
111
104
|
touching.current = true;
|
|
112
105
|
prevScrollingInfo.current = {
|
|
113
106
|
index: activeIndex.current,
|
|
114
|
-
y: activeIndex.current
|
|
107
|
+
y: getYofIndex(activeIndex.current)
|
|
115
108
|
};
|
|
116
109
|
};
|
|
117
|
-
const
|
|
118
|
-
touching.current = false;
|
|
119
|
-
};
|
|
120
|
-
const onTouchCancel = () => {
|
|
110
|
+
const onScrollEndDrag = (e) => {
|
|
121
111
|
touching.current = false;
|
|
112
|
+
const { y } = e.nativeEvent.contentOffset;
|
|
113
|
+
if (isIOS) {
|
|
114
|
+
if (y > 0 && y < snapToOffsets[maxIndex]) {
|
|
115
|
+
debounceResetScrollPosition(y);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
122
118
|
};
|
|
123
119
|
const onMomentumScrollBegin = () => {
|
|
120
|
+
isIOS && debounceResetScrollPosition.clear();
|
|
124
121
|
scrolling.current = true;
|
|
125
122
|
};
|
|
126
123
|
const onMomentumScrollEnd = (e) => {
|
|
127
124
|
scrolling.current = false;
|
|
128
|
-
if (!itemRawH) {
|
|
129
|
-
return;
|
|
130
|
-
}
|
|
131
125
|
const { y: scrollY } = e.nativeEvent.contentOffset;
|
|
132
|
-
|
|
126
|
+
if (isIOS && scrollY % itemRawH !== 0) {
|
|
127
|
+
return debounceResetScrollPosition(scrollY);
|
|
128
|
+
}
|
|
129
|
+
const calcIndex = getIndex(scrollY);
|
|
133
130
|
activeIndex.current = calcIndex;
|
|
134
131
|
if (calcIndex !== initialIndex) {
|
|
135
|
-
calcIndex = Math.max(0, Math.min(calcIndex, maxIndex)) || 0;
|
|
136
132
|
onSelectChange(calcIndex);
|
|
137
133
|
}
|
|
138
134
|
};
|
|
139
135
|
const onScroll = (e) => {
|
|
140
|
-
|
|
136
|
+
const { y } = e.nativeEvent.contentOffset;
|
|
137
|
+
if (isAndroid) {
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
// 全局注册的震动触感 hook
|
|
141
|
+
const pickerVibrate = global.__mpx.config.rnConfig.pickerVibrate;
|
|
142
|
+
if (typeof pickerVibrate !== 'function') {
|
|
141
143
|
return;
|
|
142
144
|
}
|
|
143
|
-
const { y } = e.nativeEvent.contentOffset;
|
|
144
145
|
const { index: prevIndex, y: _y } = prevScrollingInfo.current;
|
|
145
146
|
if (touching.current || scrolling.current) {
|
|
146
147
|
if (Math.abs(y - _y) >= itemRawH) {
|
|
@@ -148,19 +149,20 @@ const _PickerViewColumn = forwardRef((props, ref) => {
|
|
|
148
149
|
if (currentId !== prevIndex) {
|
|
149
150
|
prevScrollingInfo.current = {
|
|
150
151
|
index: currentId,
|
|
151
|
-
y: currentId
|
|
152
|
+
y: getYofIndex(currentId)
|
|
152
153
|
};
|
|
153
|
-
vibrateShort({ type: 'selection' })
|
|
154
|
+
// vibrateShort({ type: 'selection' })
|
|
155
|
+
pickerVibrate();
|
|
154
156
|
}
|
|
155
157
|
}
|
|
156
158
|
}
|
|
157
159
|
};
|
|
158
160
|
const renderInnerchild = () => columnData.map((item, index) => {
|
|
159
|
-
return (<MpxPickerVIewColumnItem key={index} item={item} index={index} itemHeight={itemHeight}
|
|
161
|
+
return (<MpxPickerVIewColumnItem key={index} item={item} index={index} itemHeight={itemHeight} textStyleFromParent={textStyleFromParent} textStyle={textStyle} hasVarDec={hasVarDec} varContext={varContextRef.current} textProps={textProps} visibleCount={visibleCount} onItemLayout={onItemLayout}/>);
|
|
160
162
|
});
|
|
161
163
|
const renderScollView = () => {
|
|
162
164
|
return (<PickerViewColumnAnimationContext.Provider value={offsetYShared}>
|
|
163
|
-
<Reanimated.ScrollView ref={scrollViewRef} bounces={true} horizontal={false} nestedScrollEnabled={true} removeClippedSubviews={false} showsVerticalScrollIndicator={false} showsHorizontalScrollIndicator={false} scrollEventThrottle={16} {...layoutProps} style={[{ width:
|
|
165
|
+
<Reanimated.ScrollView ref={scrollViewRef} bounces={true} horizontal={false} nestedScrollEnabled={true} removeClippedSubviews={false} showsVerticalScrollIndicator={false} showsHorizontalScrollIndicator={false} scrollEventThrottle={16} {...layoutProps} style={[{ width: '100%' }]} decelerationRate="fast" snapToOffsets={snapToOffsets} onScroll={onScroll} onScrollBeginDrag={onScrollBeginDrag} onScrollEndDrag={onScrollEndDrag} onMomentumScrollBegin={onMomentumScrollBegin} onMomentumScrollEnd={onMomentumScrollEnd} onContentSizeChange={onContentSizeChange} contentContainerStyle={contentContainerStyle}>
|
|
164
166
|
{renderInnerchild()}
|
|
165
167
|
</Reanimated.ScrollView>
|
|
166
168
|
</PickerViewColumnAnimationContext.Provider>);
|
|
@@ -45,7 +45,7 @@ const _PickerView = forwardRef((props, ref) => {
|
|
|
45
45
|
};
|
|
46
46
|
const onInitialChange = (isInvalid, value) => {
|
|
47
47
|
if (isInvalid || !snapActiveValueRef.current || hasDiff(snapActiveValueRef.current, value)) {
|
|
48
|
-
console.log('[mpx-picker-view], onInitialChange
|
|
48
|
+
console.log('[mpx-picker-view], onInitialChange ===> value=', value);
|
|
49
49
|
const eventData = getCustomEvent('change', {}, { detail: { value, source: 'change' }, layoutRef });
|
|
50
50
|
bindchange?.(eventData);
|
|
51
51
|
snapActiveValueRef.current = value.slice();
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
* ✔ nodes
|
|
3
3
|
*/
|
|
4
4
|
import { View } from 'react-native';
|
|
5
|
-
import { useRef, forwardRef, useState } from 'react';
|
|
5
|
+
import { useRef, forwardRef, useState, createElement } from 'react';
|
|
6
6
|
import useInnerProps from '../getInnerListeners';
|
|
7
7
|
import useNodesRef from '../useNodesRef'; // 引入辅助函数
|
|
8
|
-
import { useTransformStyle, useLayout } from '../utils';
|
|
8
|
+
import { useTransformStyle, useLayout, extendObject } from '../utils';
|
|
9
9
|
import { WebView } from 'react-native-webview';
|
|
10
10
|
import { generateHTML } from './html';
|
|
11
11
|
function jsonToHtmlStr(elements) {
|
|
@@ -44,20 +44,19 @@ const _RichText = forwardRef((props, ref) => {
|
|
|
44
44
|
useNodesRef(props, ref, nodeRef, {
|
|
45
45
|
layoutRef
|
|
46
46
|
});
|
|
47
|
-
const innerProps = useInnerProps(props, {
|
|
47
|
+
const innerProps = useInnerProps(props, extendObject({
|
|
48
48
|
ref: nodeRef,
|
|
49
|
-
style:
|
|
50
|
-
|
|
51
|
-
}, [], {
|
|
49
|
+
style: extendObject(normalStyle, layoutStyle)
|
|
50
|
+
}, layoutProps), [], {
|
|
52
51
|
layoutRef
|
|
53
52
|
});
|
|
54
53
|
const html = typeof nodes === 'string' ? nodes : jsonToHtmlStr(nodes);
|
|
55
|
-
return (
|
|
56
|
-
|
|
54
|
+
return createElement(View, innerProps, createElement(WebView, {
|
|
55
|
+
source: { html: generateHTML(html) },
|
|
56
|
+
onMessage: (event) => {
|
|
57
57
|
setWebViewHeight(+event.nativeEvent.data);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
</View>);
|
|
58
|
+
}
|
|
59
|
+
}));
|
|
61
60
|
});
|
|
62
61
|
_RichText.displayName = 'mpx-rich-text';
|
|
63
62
|
export default _RichText;
|
|
@@ -32,14 +32,14 @@
|
|
|
32
32
|
* ✔ bindscroll
|
|
33
33
|
*/
|
|
34
34
|
import { ScrollView } from 'react-native-gesture-handler';
|
|
35
|
-
import { RefreshControl } from 'react-native';
|
|
36
|
-
import { useRef, useState, useEffect, forwardRef, useContext, createElement } from 'react';
|
|
35
|
+
import { RefreshControl, Platform } from 'react-native';
|
|
36
|
+
import { useRef, useState, useEffect, forwardRef, useContext, createElement, useMemo } from 'react';
|
|
37
37
|
import { useAnimatedRef } from 'react-native-reanimated';
|
|
38
38
|
import { warn } from '@mpxjs/utils';
|
|
39
39
|
import useInnerProps, { getCustomEvent } from './getInnerListeners';
|
|
40
40
|
import useNodesRef from './useNodesRef';
|
|
41
41
|
import { splitProps, splitStyle, useTransformStyle, useLayout, wrapChildren, extendObject, flatGesture } from './utils';
|
|
42
|
-
import { IntersectionObserverContext } from './context';
|
|
42
|
+
import { IntersectionObserverContext, ScrollViewContext } from './context';
|
|
43
43
|
const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
|
|
44
44
|
const { textProps, innerProps: props = {} } = splitProps(scrollViewProps);
|
|
45
45
|
const { enhanced = false, bounces = true, style = {}, binddragstart, binddragging, binddragend, bindtouchstart, bindtouchmove, bindtouchend, '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, 'refresher-enabled': refresherEnabled, 'refresher-default-style': refresherDefaultStyle, 'refresher-background': refresherBackground, 'show-scrollbar': showScrollbar = true, 'scroll-into-view': scrollIntoView = '', 'scroll-top': scrollTop = 0, 'scroll-left': scrollLeft = 0, 'refresher-triggered': refresherTriggered, 'enable-var': enableVar, 'external-var-context': externalVarContext, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight, 'simultaneous-handlers': originSimultaneousHandlers, 'wait-for': waitFor, __selectRef } = props;
|
|
@@ -78,6 +78,11 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
|
|
|
78
78
|
},
|
|
79
79
|
gestureRef: scrollViewRef
|
|
80
80
|
});
|
|
81
|
+
const contextValue = useMemo(() => {
|
|
82
|
+
return {
|
|
83
|
+
gestureRef: scrollViewRef
|
|
84
|
+
};
|
|
85
|
+
}, []);
|
|
81
86
|
const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef: scrollViewRef, onLayout });
|
|
82
87
|
if (scrollX && scrollY) {
|
|
83
88
|
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');
|
|
@@ -179,6 +184,7 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
|
|
|
179
184
|
visibleLength
|
|
180
185
|
});
|
|
181
186
|
}
|
|
187
|
+
const observerTimers = {};
|
|
182
188
|
function onScroll(e) {
|
|
183
189
|
const { bindscroll } = props;
|
|
184
190
|
const { x: scrollLeft, y: scrollTop } = e.nativeEvent.contentOffset;
|
|
@@ -198,7 +204,16 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
|
|
|
198
204
|
updateScrollOptions(e, { scrollLeft, scrollTop });
|
|
199
205
|
if (enableTriggerIntersectionObserver && intersectionObservers) {
|
|
200
206
|
for (const key in intersectionObservers) {
|
|
201
|
-
|
|
207
|
+
if (Platform.OS === 'android') {
|
|
208
|
+
intersectionObservers[key].throttleMeasure();
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
// TODO: 由于iOS在onScroll滚动的过程中view的计算measureInWindow计算的值不发生变化,所以暂时在ios上加一个延时计算
|
|
212
|
+
observerTimers[key] && clearTimeout(observerTimers[key]);
|
|
213
|
+
observerTimers[key] = setTimeout(() => {
|
|
214
|
+
intersectionObservers[key].throttleMeasure();
|
|
215
|
+
}, 300);
|
|
216
|
+
}
|
|
202
217
|
}
|
|
203
218
|
}
|
|
204
219
|
}
|
|
@@ -342,12 +357,12 @@ const _ScrollView = forwardRef((scrollViewProps = {}, ref) => {
|
|
|
342
357
|
onRefresh: onRefresh
|
|
343
358
|
}, (refresherDefaultStyle && refresherDefaultStyle !== 'none' ? { colors: refreshColor[refresherDefaultStyle] } : null)))
|
|
344
359
|
: undefined
|
|
345
|
-
}), wrapChildren(props, {
|
|
360
|
+
}), createElement(ScrollViewContext.Provider, { value: contextValue }, wrapChildren(props, {
|
|
346
361
|
hasVarDec,
|
|
347
362
|
varContext: varContextRef.current,
|
|
348
363
|
textStyle,
|
|
349
364
|
textProps
|
|
350
|
-
}));
|
|
365
|
+
})));
|
|
351
366
|
});
|
|
352
367
|
_ScrollView.displayName = 'MpxScrollView';
|
|
353
368
|
export default _ScrollView;
|
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { forwardRef, useRef } from 'react';
|
|
1
|
+
import Animated, { useAnimatedStyle, interpolate } from 'react-native-reanimated';
|
|
2
|
+
import { forwardRef, useRef, useContext } from 'react';
|
|
3
3
|
import useInnerProps from './getInnerListeners';
|
|
4
4
|
import useNodesRef from './useNodesRef'; // 引入辅助函数
|
|
5
5
|
import { useTransformStyle, splitStyle, splitProps, wrapChildren, useLayout } from './utils';
|
|
6
|
+
import { SwiperContext } from './context';
|
|
6
7
|
const _SwiperItem = forwardRef((props, ref) => {
|
|
7
|
-
const { 'enable-var': enableVar, 'external-var-context': externalVarContext, style } = props;
|
|
8
|
+
const { 'enable-var': enableVar, 'external-var-context': externalVarContext, style, customStyle, itemIndex } = props;
|
|
9
|
+
const contextValue = useContext(SwiperContext);
|
|
10
|
+
const offset = contextValue.offset || 0;
|
|
11
|
+
const step = contextValue.step || 0;
|
|
12
|
+
const scale = contextValue.scale || false;
|
|
8
13
|
const { textProps } = splitProps(props);
|
|
9
14
|
const nodeRef = useRef(null);
|
|
10
15
|
const { normalStyle, hasVarDec, varContextRef, hasSelfPercent, setWidth, setHeight } = useTransformStyle(style, { enableVar, externalVarContext });
|
|
@@ -16,21 +21,33 @@ const _SwiperItem = forwardRef((props, ref) => {
|
|
|
16
21
|
// 存储layout布局信息
|
|
17
22
|
layoutRef, layoutProps, layoutStyle } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef: nodeRef });
|
|
18
23
|
const innerProps = useInnerProps(props, {
|
|
19
|
-
style: { ...innerStyle, ...layoutStyle },
|
|
20
24
|
ref: nodeRef,
|
|
21
25
|
...layoutProps
|
|
22
26
|
}, [
|
|
23
27
|
'children',
|
|
24
|
-
'enable-offset'
|
|
28
|
+
'enable-offset',
|
|
29
|
+
'style'
|
|
25
30
|
], { layoutRef });
|
|
26
|
-
|
|
27
|
-
|
|
31
|
+
const itemAnimatedStyle = useAnimatedStyle(() => {
|
|
32
|
+
if (!step.value)
|
|
33
|
+
return {};
|
|
34
|
+
const inputRange = [step.value, 0];
|
|
35
|
+
const outputRange = [0.7, 1];
|
|
36
|
+
return {
|
|
37
|
+
transform: [{
|
|
38
|
+
scale: interpolate(Math.abs(Math.abs(offset.value) - itemIndex * step.value), inputRange, outputRange)
|
|
39
|
+
}]
|
|
40
|
+
};
|
|
41
|
+
});
|
|
42
|
+
const mergeStyle = [innerStyle, layoutStyle, { width: '100%', height: '100%' }, scale ? itemAnimatedStyle : {}].concat(customStyle);
|
|
43
|
+
return (<Animated.View {...innerProps} style={mergeStyle} data-itemId={props['item-id']}>
|
|
44
|
+
{wrapChildren(props, {
|
|
28
45
|
hasVarDec,
|
|
29
46
|
varContext: varContextRef.current,
|
|
30
47
|
textStyle,
|
|
31
48
|
textProps
|
|
32
49
|
})}
|
|
33
|
-
</View>);
|
|
50
|
+
</Animated.View>);
|
|
34
51
|
});
|
|
35
52
|
_SwiperItem.displayName = 'MpxSwiperItem';
|
|
36
53
|
export default _SwiperItem;
|