@mpxjs/webpack-plugin 2.10.1 → 2.10.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/lib/dependencies/RecordPageConfigsMapDependency.js +45 -0
  2. package/lib/index.js +23 -1
  3. package/lib/platform/style/wx/index.js +6 -4
  4. package/lib/platform/template/wx/component-config/input.js +1 -1
  5. package/lib/platform/template/wx/component-config/textarea.js +1 -1
  6. package/lib/platform/template/wx/component-config/view.js +12 -2
  7. package/lib/react/index.js +0 -1
  8. package/lib/react/processJSON.js +13 -2
  9. package/lib/react/processScript.js +7 -4
  10. package/lib/react/processTemplate.js +18 -3
  11. package/lib/react/script-helper.js +18 -4
  12. package/lib/runtime/components/react/context.ts +3 -4
  13. package/lib/runtime/components/react/dist/mpx-image.jsx +2 -2
  14. package/lib/runtime/components/react/dist/mpx-input.jsx +54 -54
  15. package/lib/runtime/components/react/dist/{KeyboardAvoidingView.jsx → mpx-keyboard-avoiding-view.jsx} +23 -12
  16. package/lib/runtime/components/react/dist/mpx-portal/portal-manager.jsx +1 -2
  17. package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +16 -8
  18. package/lib/runtime/components/react/dist/mpx-simple-view.jsx +22 -0
  19. package/lib/runtime/components/react/dist/mpx-textarea.jsx +6 -6
  20. package/lib/runtime/components/react/dist/mpx-view.jsx +10 -5
  21. package/lib/runtime/components/react/dist/mpx-web-view.jsx +6 -5
  22. package/lib/runtime/components/react/dist/useAnimationHooks.js +46 -48
  23. package/lib/runtime/components/react/dist/utils.jsx +17 -21
  24. package/lib/runtime/components/react/mpx-image.tsx +2 -2
  25. package/lib/runtime/components/react/mpx-input.tsx +66 -72
  26. package/lib/runtime/components/react/{KeyboardAvoidingView.tsx → mpx-keyboard-avoiding-view.tsx} +32 -18
  27. package/lib/runtime/components/react/mpx-portal/portal-manager.tsx +1 -2
  28. package/lib/runtime/components/react/mpx-scroll-view.tsx +21 -8
  29. package/lib/runtime/components/react/mpx-simple-view.tsx +32 -0
  30. package/lib/runtime/components/react/mpx-textarea.tsx +10 -6
  31. package/lib/runtime/components/react/mpx-view.tsx +17 -10
  32. package/lib/runtime/components/react/mpx-web-view.tsx +12 -10
  33. package/lib/runtime/components/react/types/getInnerListeners.d.ts +1 -1
  34. package/lib/runtime/components/react/useAnimationHooks.ts +46 -48
  35. package/lib/runtime/components/react/utils.tsx +21 -24
  36. package/lib/runtime/optionProcessor.js +3 -2
  37. package/lib/style-compiler/index.js +8 -6
  38. package/lib/template-compiler/compiler.js +22 -14
  39. package/lib/utils/match-condition.js +14 -8
  40. package/lib/web/processJSON.js +1 -3
  41. package/package.json +4 -4
@@ -4,7 +4,7 @@
4
4
  * ✔ password
5
5
  * ✔ placeholder
6
6
  * - placeholder-style: Only support color.
7
- * placeholder-class
7
+ * - placeholder-class: Only support color.
8
8
  * ✔ disabled
9
9
  * ✔ maxlength
10
10
  * ✔ cursor-spacing
@@ -54,7 +54,7 @@ import {
54
54
  TextInputSubmitEditingEventData
55
55
  } from 'react-native'
56
56
  import { warn } from '@mpxjs/utils'
57
- import { parseInlineStyle, useUpdateEffect, useTransformStyle, useLayout, extendObject } from './utils'
57
+ import { useUpdateEffect, useTransformStyle, useLayout, extendObject } from './utils'
58
58
  import useInnerProps, { getCustomEvent } from './getInnerListeners'
59
59
  import useNodesRef, { HandlerRef } from './useNodesRef'
60
60
  import { FormContext, FormFieldValue, KeyboardAvoidContext } from './context'
@@ -73,6 +73,8 @@ type InputStyle = Omit<
73
73
 
74
74
  type Type = 'text' | 'number' | 'idcard' | 'digit'
75
75
 
76
+ type ConfirmType = 'done' | 'send' | 'search' | 'next' | 'go' | 'return'
77
+
76
78
  export interface InputProps {
77
79
  name?: string
78
80
  style?: InputStyle & Record<string, any>
@@ -85,13 +87,13 @@ export interface InputProps {
85
87
  maxlength?: number
86
88
  'auto-focus'?: boolean
87
89
  focus?: boolean
88
- 'confirm-type'?: 'done' | 'send' | 'search' | 'next' | 'go'
90
+ 'confirm-type'?: ConfirmType
89
91
  'confirm-hold'?: boolean
90
92
  cursor?: number
91
93
  'cursor-color'?: string
92
94
  'selection-start'?: number
93
95
  'selection-end'?: number
94
- 'placeholder-style'?: string
96
+ 'placeholder-style'?: { color?: string }
95
97
  'enable-offset'?: boolean,
96
98
  'enable-var'?: boolean
97
99
  'external-var-context'?: Record<string, any>
@@ -133,7 +135,7 @@ const Input = forwardRef<HandlerRef<TextInput, FinalInputProps>, FinalInputProps
133
135
  type = 'text',
134
136
  value,
135
137
  password,
136
- 'placeholder-style': placeholderStyle,
138
+ 'placeholder-style': placeholderStyle = {},
137
139
  disabled,
138
140
  maxlength = 140,
139
141
  'cursor-spacing': cursorSpacing = 0,
@@ -185,10 +187,9 @@ const Input = forwardRef<HandlerRef<TextInput, FinalInputProps>, FinalInputProps
185
187
 
186
188
  const keyboardType = keyboardTypeMap[type]
187
189
  const defaultValue = parseValue(value)
188
- const placeholderTextColor = parseInlineStyle(placeholderStyle)?.color
189
190
  const textAlignVertical = multiline ? 'top' : 'auto'
190
191
 
191
- const tmpValue = useRef<string | undefined>(defaultValue)
192
+ const tmpValue = useRef<string>(defaultValue)
192
193
  const cursorIndex = useRef<number>(0)
193
194
  const lineCount = useRef<number>(0)
194
195
 
@@ -200,7 +201,7 @@ const Input = forwardRef<HandlerRef<TextInput, FinalInputProps>, FinalInputProps
200
201
  { padding: 0, backgroundColor: '#fff' },
201
202
  style,
202
203
  multiline && autoHeight
203
- ? { minHeight: Math.max((style as any)?.minHeight || 35, contentHeight) }
204
+ ? { height: 'auto', minHeight: Math.max((style as any)?.minHeight || 35, contentHeight) }
204
205
  : {}
205
206
  )
206
207
 
@@ -232,55 +233,64 @@ const Input = forwardRef<HandlerRef<TextInput, FinalInputProps>, FinalInputProps
232
233
  }
233
234
  }, [cursor, selectionStart, selectionEnd])
234
235
 
235
- const onTextInput = ({ nativeEvent }: NativeSyntheticEvent<TextInputTextInputEventData>) => {
236
- if (!bindinput && !bindblur) return
237
- const {
238
- range: { start, end },
239
- text
240
- } = nativeEvent
241
- cursorIndex.current = start < end ? start : start + text.length
236
+ // have not selection on the Android platformg
237
+ const getCursorIndex = (
238
+ changedSelection: TextInputSelectionChangeEventData['selection'] | undefined,
239
+ prevValue: string,
240
+ curValue: string
241
+ ) => {
242
+ if (changedSelection) return changedSelection.end
243
+ if (!prevValue || !curValue || prevValue.length === curValue.length) return curValue.length
244
+ const prevStr = prevValue.substring(cursorIndex.current)
245
+ const curStr = curValue.substring(cursorIndex.current)
246
+ return cursorIndex.current + curStr.length - prevStr.length
242
247
  }
243
248
 
244
- const onChange = (evt: NativeSyntheticEvent<TextInputChangeEventData>) => {
245
- tmpValue.current = evt.nativeEvent.text
246
- if (!bindinput) return
247
- const result = bindinput(
248
- getCustomEvent(
249
- 'input',
250
- evt,
251
- {
252
- detail: {
253
- value: evt.nativeEvent.text,
254
- cursor: cursorIndex.current
249
+ const onChange = (evt: NativeSyntheticEvent<TextInputChangeEventData & TextInputSelectionChangeEventData>) => {
250
+ const { text, selection } = evt.nativeEvent
251
+ // will trigger twice on the Android platformg, prevent the second trigger
252
+ if (tmpValue.current === text) return
253
+ const index = getCursorIndex(selection, tmpValue.current, text)
254
+ tmpValue.current = text
255
+ cursorIndex.current = index
256
+ if (bindinput) {
257
+ const result = bindinput(
258
+ getCustomEvent(
259
+ 'input',
260
+ evt,
261
+ {
262
+ detail: {
263
+ value: tmpValue.current,
264
+ cursor: cursorIndex.current
265
+ },
266
+ layoutRef
255
267
  },
256
- layoutRef
257
- },
258
- props
268
+ props
269
+ )
259
270
  )
260
- )
261
- if (typeof result === 'string') {
262
- tmpValue.current = result
263
- setInputValue(result)
271
+ if (typeof result === 'string') {
272
+ tmpValue.current = result
273
+ setInputValue(result)
274
+ } else {
275
+ setInputValue(tmpValue.current)
276
+ }
264
277
  } else {
265
278
  setInputValue(tmpValue.current)
266
279
  }
267
280
  }
268
281
 
269
282
  const setKeyboardAvoidContext = () => {
270
- if (adjustPosition && keyboardAvoid?.current) {
271
- extendObject(keyboardAvoid.current, {
272
- cursorSpacing,
273
- ref: nodeRef
274
- })
283
+ if (adjustPosition && keyboardAvoid) {
284
+ keyboardAvoid.current = { cursorSpacing, ref: nodeRef }
275
285
  }
276
286
  }
277
287
 
278
- const onInputTouchStart = () => {
288
+ const onTouchStart = () => {
279
289
  // sometimes the focus event occurs later than the keyboardWillShow event
280
290
  setKeyboardAvoidContext()
281
291
  }
282
292
 
283
- const onInputFocus = (evt: NativeSyntheticEvent<TextInputFocusEventData>) => {
293
+ const onFocus = (evt: NativeSyntheticEvent<TextInputFocusEventData>) => {
284
294
  setKeyboardAvoidContext()
285
295
  bindfocus && bindfocus(
286
296
  getCustomEvent(
@@ -297,7 +307,7 @@ const Input = forwardRef<HandlerRef<TextInput, FinalInputProps>, FinalInputProps
297
307
  )
298
308
  }
299
309
 
300
- const onInputBlur = (evt: NativeSyntheticEvent<TextInputFocusEventData>) => {
310
+ const onBlur = (evt: NativeSyntheticEvent<TextInputFocusEventData>) => {
301
311
  bindblur && bindblur(
302
312
  getCustomEvent(
303
313
  'blur',
@@ -314,23 +324,6 @@ const Input = forwardRef<HandlerRef<TextInput, FinalInputProps>, FinalInputProps
314
324
  )
315
325
  }
316
326
 
317
- const onKeyPress = (evt: NativeSyntheticEvent<TextInputKeyPressEventData>) => {
318
- evt.nativeEvent.key === 'Enter' &&
319
- bindconfirm!(
320
- getCustomEvent(
321
- 'confirm',
322
- evt,
323
- {
324
- detail: {
325
- value: tmpValue.current || ''
326
- },
327
- layoutRef
328
- },
329
- props
330
- )
331
- )
332
- }
333
-
334
327
  const onSubmitEditing = (evt: NativeSyntheticEvent<TextInputSubmitEditingEventData>) => {
335
328
  bindconfirm!(
336
329
  getCustomEvent(
@@ -348,15 +341,18 @@ const Input = forwardRef<HandlerRef<TextInput, FinalInputProps>, FinalInputProps
348
341
  }
349
342
 
350
343
  const onSelectionChange = (evt: NativeSyntheticEvent<TextInputSelectionChangeEventData>) => {
351
- setSelection(evt.nativeEvent.selection)
344
+ const { selection } = evt.nativeEvent
345
+ const { start, end } = selection
346
+ cursorIndex.current = start
347
+ setSelection(selection)
352
348
  bindselectionchange && bindselectionchange(
353
349
  getCustomEvent(
354
350
  'selectionchange',
355
351
  evt,
356
352
  {
357
353
  detail: {
358
- selectionStart: evt.nativeEvent.selection.start,
359
- selectionEnd: evt.nativeEvent.selection.end
354
+ selectionStart: start,
355
+ selectionEnd: end
360
356
  },
361
357
  layoutRef
362
358
  },
@@ -444,26 +440,24 @@ const Input = forwardRef<HandlerRef<TextInput, FinalInputProps>, FinalInputProps
444
440
  maxLength: maxlength === -1 ? undefined : maxlength,
445
441
  editable: !disabled,
446
442
  autoFocus: !!autoFocus || !!focus,
447
- returnKeyType: confirmType,
448
443
  selection: selection,
449
444
  selectionColor: cursorColor,
450
445
  blurOnSubmit: !multiline && !confirmHold,
451
446
  underlineColorAndroid: 'rgba(0,0,0,0)',
452
447
  textAlignVertical: textAlignVertical,
453
- placeholderTextColor: placeholderTextColor,
448
+ placeholderTextColor: placeholderStyle?.color,
454
449
  multiline: !!multiline
455
450
  },
451
+ !!multiline && confirmType === 'return' ? {} : { enterKeyHint: confirmType },
456
452
  layoutProps,
457
453
  {
458
- onTouchStart: onInputTouchStart,
459
- onFocus: onInputFocus,
460
- onBlur: onInputBlur,
461
- onKeyPress: bindconfirm && onKeyPress,
462
- onSubmitEditing: bindconfirm && multiline && onSubmitEditing,
463
- onSelectionChange: onSelectionChange,
464
- onTextInput: onTextInput,
465
- onChange: onChange,
466
- onContentSizeChange: onContentSizeChange
454
+ onTouchStart,
455
+ onFocus,
456
+ onBlur,
457
+ onChange,
458
+ onSelectionChange,
459
+ onContentSizeChange,
460
+ onSubmitEditing: bindconfirm && !multiline && onSubmitEditing
467
461
  }
468
462
  ),
469
463
  [
@@ -1,8 +1,8 @@
1
- import React, { ReactNode, useContext, useEffect } from 'react'
1
+ import React, { ReactNode, useContext, useEffect, useMemo } from 'react'
2
2
  import { DimensionValue, EmitterSubscription, Keyboard, Platform, View, ViewStyle } from 'react-native'
3
- import Animated, { useSharedValue, useAnimatedStyle, withTiming, Easing } from 'react-native-reanimated'
3
+ import Animated, { useSharedValue, useAnimatedStyle, withTiming, Easing, runOnJS } from 'react-native-reanimated'
4
+ import { GestureDetector, Gesture } from 'react-native-gesture-handler'
4
5
  import { KeyboardAvoidContext } from './context'
5
- import { extendObject } from './utils'
6
6
 
7
7
  type KeyboardAvoidViewProps = {
8
8
  children?: ReactNode
@@ -19,6 +19,17 @@ const KeyboardAvoidingView = ({ children, style, contentContainerStyle }: Keyboa
19
19
  const basic = useSharedValue('auto')
20
20
  const keyboardAvoid = useContext(KeyboardAvoidContext)
21
21
 
22
+ const dismiss = () => {
23
+ Keyboard.isVisible() && Keyboard.dismiss()
24
+ }
25
+
26
+ const gesture = useMemo(() => {
27
+ return Gesture.Tap()
28
+ .onEnd(() => {
29
+ dismiss()
30
+ }).runOnJS(true)
31
+ }, [])
32
+
22
33
  const animatedStyle = useAnimatedStyle(() => {
23
34
  return Object.assign(
24
35
  {
@@ -29,10 +40,9 @@ const KeyboardAvoidingView = ({ children, style, contentContainerStyle }: Keyboa
29
40
  })
30
41
 
31
42
  const resetKeyboard = () => {
32
- keyboardAvoid?.current && extendObject(keyboardAvoid.current, {
33
- cursorSpacing: 0,
34
- ref: null
35
- })
43
+ if (keyboardAvoid?.current) {
44
+ keyboardAvoid.current = null
45
+ }
36
46
  offset.value = withTiming(0, { duration, easing })
37
47
  basic.value = 'auto'
38
48
  }
@@ -48,7 +58,7 @@ const KeyboardAvoidingView = ({ children, style, contentContainerStyle }: Keyboa
48
58
  const { ref, cursorSpacing = 0 } = keyboardAvoid.current
49
59
  setTimeout(() => {
50
60
  ref?.current?.measure((x: number, y: number, width: number, height: number, pageX: number, pageY: number) => {
51
- const aboveOffset = offset.value + pageY + height - endCoordinates.screenY
61
+ const aboveOffset = pageY + height - endCoordinates.screenY
52
62
  const aboveValue = -aboveOffset >= cursorSpacing ? 0 : aboveOffset + cursorSpacing
53
63
  const belowValue = Math.min(endCoordinates.height, aboveOffset + cursorSpacing)
54
64
  const value = aboveOffset > 0 ? belowValue : aboveValue
@@ -92,17 +102,21 @@ const KeyboardAvoidingView = ({ children, style, contentContainerStyle }: Keyboa
92
102
  }, [keyboardAvoid])
93
103
 
94
104
  return (
95
- <View style={style}>
96
- <Animated.View
97
- style={[
98
- contentContainerStyle,
99
- animatedStyle
100
- ]}
101
- >
102
- {children}
103
- </Animated.View>
104
- </View>
105
+ <GestureDetector gesture={gesture}>
106
+ <View style={style}>
107
+ <Animated.View
108
+ style={[
109
+ contentContainerStyle,
110
+ animatedStyle
111
+ ]}
112
+ >
113
+ {children}
114
+ </Animated.View>
115
+ </View>
116
+ </GestureDetector>
105
117
  )
106
118
  }
107
119
 
120
+ KeyboardAvoidingView.displayName = 'MpxKeyboardAvoidingView'
121
+
108
122
  export default KeyboardAvoidingView
@@ -1,6 +1,5 @@
1
1
  import { useState, useCallback, forwardRef, ForwardedRef, useImperativeHandle, ReactNode, ReactElement } from 'react'
2
2
  import { View, StyleSheet } from 'react-native'
3
- import { extendObject } from '../utils'
4
3
 
5
4
  export type State = {
6
5
  portals: Array<{
@@ -27,7 +26,7 @@ const _PortalManager = forwardRef((props: PortalManagerProps, ref:ForwardedRef<u
27
26
  setState((prevState) => ({
28
27
  portals: prevState.portals.map((item) => {
29
28
  if (item.key === key) {
30
- return extendObject({}, item, { children })
29
+ return Object.assign({}, item, { children })
31
30
  }
32
31
  return item
33
32
  })
@@ -70,6 +70,7 @@ interface ScrollViewProps {
70
70
  'parent-height'?: number;
71
71
  'wait-for'?: Array<GestureHandler>;
72
72
  'simultaneous-handlers'?: Array<GestureHandler>;
73
+ 'scroll-event-throttle'?:number;
73
74
  bindscrolltoupper?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;
74
75
  bindscrolltolower?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;
75
76
  bindscroll?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;
@@ -124,7 +125,7 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
124
125
  'paging-enabled': pagingEnabled = false,
125
126
  'upper-threshold': upperThreshold = 50,
126
127
  'lower-threshold': lowerThreshold = 50,
127
- 'scroll-with-animation': scrollWithAnimation,
128
+ 'scroll-with-animation': scrollWithAnimation = false,
128
129
  'refresher-enabled': refresherEnabled,
129
130
  'refresher-default-style': refresherDefaultStyle,
130
131
  'refresher-background': refresherBackground,
@@ -140,6 +141,7 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
140
141
  'parent-height': parentHeight,
141
142
  'simultaneous-handlers': originSimultaneousHandlers,
142
143
  'wait-for': waitFor,
144
+ 'scroll-event-throttle': scrollEventThrottle = 0,
143
145
  __selectRef
144
146
  } = props
145
147
 
@@ -159,7 +161,6 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
159
161
  visibleLength: 0
160
162
  })
161
163
 
162
- const scrollEventThrottle = 50
163
164
  const hasCallScrollToUpper = useRef(true)
164
165
  const hasCallScrollToLower = useRef(false)
165
166
  const initialTimeout = useRef<ReturnType<typeof setTimeout> | null>(null)
@@ -189,7 +190,7 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
189
190
  pagingEnabled,
190
191
  fastDeceleration: false,
191
192
  decelerationDisabled: false,
192
- scrollTo: scrollToOffset
193
+ scrollTo
193
194
  },
194
195
  gestureRef: scrollViewRef
195
196
  })
@@ -202,6 +203,8 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
202
203
 
203
204
  const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef: scrollViewRef, onLayout })
204
205
 
206
+ const lastOffset = useRef(0)
207
+
205
208
  if (scrollX && scrollY) {
206
209
  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')
207
210
  }
@@ -236,6 +239,10 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
236
239
  firstScrollIntoViewChange.current = true
237
240
  }, [scrollIntoView])
238
241
 
242
+ function scrollTo ({ top = 0, left = 0, animated = false } : { top?: number; left?: number; animated?: boolean }) {
243
+ scrollToOffset(left, top, animated)
244
+ }
245
+
239
246
  function handleScrollIntoView () {
240
247
  const refs = __selectRef!(`#${scrollIntoView}`, 'node')
241
248
  if (!refs) return
@@ -259,7 +266,8 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
259
266
  function onStartReached (e: NativeSyntheticEvent<NativeScrollEvent>) {
260
267
  const { bindscrolltoupper } = props
261
268
  const { offset } = scrollOptions.current
262
- if (bindscrolltoupper && (offset <= upperThreshold)) {
269
+ const isScrollingBackward = offset < lastOffset.current
270
+ if (bindscrolltoupper && (offset <= upperThreshold) && isScrollingBackward) {
263
271
  if (!hasCallScrollToUpper.current) {
264
272
  bindscrolltoupper(
265
273
  getCustomEvent('scrolltoupper', e, {
@@ -280,13 +288,15 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
280
288
  const { bindscrolltolower } = props
281
289
  const { contentLength, visibleLength, offset } = scrollOptions.current
282
290
  const distanceFromEnd = contentLength - visibleLength - offset
283
- if (bindscrolltolower && (distanceFromEnd < lowerThreshold)) {
291
+ const isScrollingForward = offset > lastOffset.current
292
+
293
+ if (bindscrolltolower && (distanceFromEnd < lowerThreshold) && isScrollingForward) {
284
294
  if (!hasCallScrollToLower.current) {
285
295
  hasCallScrollToLower.current = true
286
296
  bindscrolltolower(
287
297
  getCustomEvent('scrolltolower', e, {
288
298
  detail: {
289
- direction: scrollX ? 'right' : 'botttom'
299
+ direction: scrollX ? 'right' : 'bottom'
290
300
  },
291
301
  layoutRef
292
302
  }, props)
@@ -341,6 +351,8 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
341
351
  onStartReached(e)
342
352
  onEndReached(e)
343
353
  updateIntersection()
354
+ // 在 onStartReached、onEndReached 执行完后更新 lastOffset
355
+ lastOffset.current = scrollOptions.current.offset
344
356
  }
345
357
 
346
358
  function onScrollEnd (e: NativeSyntheticEvent<NativeScrollEvent>) {
@@ -363,6 +375,7 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
363
375
  onStartReached(e)
364
376
  onEndReached(e)
365
377
  updateIntersection()
378
+ lastOffset.current = scrollOptions.current.offset
366
379
  }
367
380
  function updateIntersection () {
368
381
  if (enableTriggerIntersectionObserver && intersectionObservers) {
@@ -371,9 +384,9 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
371
384
  }
372
385
  }
373
386
  }
374
- function scrollToOffset (x = 0, y = 0) {
387
+ function scrollToOffset (x = 0, y = 0, animated = scrollWithAnimation) {
375
388
  if (scrollViewRef.current) {
376
- scrollViewRef.current.scrollTo({ x, y, animated: !!scrollWithAnimation })
389
+ scrollViewRef.current.scrollTo({ x, y, animated })
377
390
  scrollOptions.current.scrollLeft = x
378
391
  scrollOptions.current.scrollTop = y
379
392
  snapScrollLeft.current = x
@@ -0,0 +1,32 @@
1
+ import { View, ViewProps, TextStyle } from 'react-native'
2
+ import { createElement, forwardRef, useRef } from 'react'
3
+ import useNodesRef, { HandlerRef } from './useNodesRef'
4
+ import { extendObject, splitProps, splitStyle, wrapChildren } from './utils'
5
+
6
+ const _View2 = forwardRef<HandlerRef<View, ViewProps>, ViewProps>((simpleViewProps: ViewProps, ref) => {
7
+ const nodeRef = useRef(null)
8
+
9
+ const { textProps, innerProps: props = {} } = splitProps(simpleViewProps)
10
+
11
+ const { textStyle, innerStyle = {} } = splitStyle(props.style || {})
12
+
13
+ useNodesRef(props, ref, nodeRef, {
14
+ style: innerStyle || {}
15
+ })
16
+
17
+ return createElement(View, extendObject({}, props, {
18
+ style: innerStyle,
19
+ ref: nodeRef
20
+ }), wrapChildren(
21
+ props,
22
+ {
23
+ hasVarDec: false,
24
+ textStyle: textStyle as TextStyle,
25
+ textProps
26
+ }
27
+ ))
28
+ })
29
+
30
+ _View2.displayName = 'MpxSimpleView'
31
+
32
+ export default _View2
@@ -3,14 +3,14 @@
3
3
  * Subtraction:
4
4
  * type, password, confirm-hold
5
5
  * Addition:
6
- * - confirm-type: Not support `return`
6
+ * confirm-type
7
7
  * ✔ auto-height
8
8
  * ✘ fixed
9
9
  * ✘ show-confirm-bar
10
10
  * ✔ bindlinechange: No `heightRpx` info.
11
11
  */
12
12
  import { JSX, forwardRef, createElement } from 'react'
13
- import { Keyboard, TextInput } from 'react-native'
13
+ import { TextInput } from 'react-native'
14
14
  import Input, { InputProps, PrivateInputProps } from './mpx-input'
15
15
  import { omit, extendObject } from './utils'
16
16
  import { HandlerRef } from './useNodesRef'
@@ -25,7 +25,10 @@ const DEFAULT_TEXTAREA_HEIGHT = 150
25
25
 
26
26
  const Textarea = forwardRef<HandlerRef<TextInput, TextareProps>, TextareProps>(
27
27
  (props, ref): JSX.Element => {
28
- const { style = {} } = props
28
+ const {
29
+ style = {},
30
+ 'confirm-type': confirmType = 'return'
31
+ } = props
29
32
 
30
33
  const restProps = omit(props, [
31
34
  'ref',
@@ -33,16 +36,17 @@ const Textarea = forwardRef<HandlerRef<TextInput, TextareProps>, TextareProps>(
33
36
  'style',
34
37
  'password',
35
38
  'multiline',
39
+ 'confirm-type',
36
40
  'confirm-hold'
37
41
  ])
38
42
 
39
43
  return createElement(
40
44
  Input,
41
45
  extendObject(restProps, {
42
- ref: ref,
46
+ ref,
47
+ confirmType,
43
48
  multiline: true,
44
- confirmType: 'next',
45
- bindblur: () => Keyboard.dismiss(),
49
+ 'confirm-type': confirmType,
46
50
  style: extendObject({
47
51
  width: DEFAULT_TEXTAREA_WIDTH,
48
52
  height: DEFAULT_TEXTAREA_HEIGHT
@@ -16,6 +16,7 @@ import { parseUrl, PERCENT_REGEX, splitStyle, splitProps, useTransformStyle, wra
16
16
  import { error } from '@mpxjs/utils'
17
17
  import LinearGradient from 'react-native-linear-gradient'
18
18
  import { GestureDetector, PanGesture } from 'react-native-gesture-handler'
19
+ import Portal from './mpx-portal'
19
20
 
20
21
  export interface _ViewProps extends ViewProps {
21
22
  style?: ExtendedViewStyle
@@ -79,7 +80,7 @@ type PreImageInfo = {
79
80
  type ImageProps = {
80
81
  style: ImageStyle,
81
82
  src?: string,
82
- source?: {uri: string },
83
+ source?: { uri: string },
83
84
  colors: Array<string>,
84
85
  locations?: Array<number>
85
86
  angle?: number
@@ -483,8 +484,8 @@ function parseLinearGradient (text: string): LinearInfo | undefined {
483
484
  }
484
485
 
485
486
  function parseBgImage (text: string): {
486
- linearInfo?: LinearInfo;
487
- direction?: string;
487
+ linearInfo?: LinearInfo
488
+ direction?: string
488
489
  type?: 'image' | 'linear'
489
490
  src?: string
490
491
  } {
@@ -578,7 +579,7 @@ function useWrapImage (imageStyle?: ExtendedViewStyle, innerStyle?: Record<strin
578
579
  if (!src) {
579
580
  setShow(false)
580
581
  return
581
- // 一开始未出现,数据改变时出现
582
+ // 一开始未出现,数据改变时出现
582
583
  } else if (!(needLayout || needImageSize)) {
583
584
  setShow(true)
584
585
  return
@@ -602,7 +603,7 @@ function useWrapImage (imageStyle?: ExtendedViewStyle, innerStyle?: Record<strin
602
603
  }
603
604
  })
604
605
  }
605
- // type 添加type 处理无渐变 有渐变的场景
606
+ // type 添加type 处理无渐变 有渐变的场景
606
607
  }, [src, type])
607
608
 
608
609
  if (!type) return null
@@ -636,7 +637,7 @@ function useWrapImage (imageStyle?: ExtendedViewStyle, innerStyle?: Record<strin
636
637
  }
637
638
 
638
639
  return <View key='backgroundImage' {...needLayout ? { onLayout } : null} style={{ ...inheritStyle(innerStyle), ...StyleSheet.absoluteFillObject, overflow: 'hidden' }}>
639
- {show && type === 'linear' && <LinearGradient useAngle={true} {...imageStyleToProps(preImageInfo, sizeInfo.current as Size, layoutInfo.current as Size)} /> }
640
+ {show && type === 'linear' && <LinearGradient useAngle={true} {...imageStyleToProps(preImageInfo, sizeInfo.current as Size, layoutInfo.current as Size)} />}
640
641
  {show && type === 'image' && (renderImage(imageStyleToProps(preImageInfo, sizeInfo.current as Size, layoutInfo.current as Size), enableFastImage))}
641
642
  </View>
642
643
  }
@@ -703,6 +704,7 @@ const _View = forwardRef<HandlerRef<View, _ViewProps>, _ViewProps>((viewProps, r
703
704
  const {
704
705
  normalStyle,
705
706
  hasSelfPercent,
707
+ hasPositionFixed,
706
708
  hasVarDec,
707
709
  varContextRef,
708
710
  setWidth,
@@ -769,13 +771,18 @@ const _View = forwardRef<HandlerRef<View, _ViewProps>, _ViewProps>((viewProps, r
769
771
  enableFastImage
770
772
  })
771
773
 
772
- const BaseComponent = enableStyleAnimation
774
+ let finalComponent: JSX.Element = enableStyleAnimation
773
775
  ? createElement(Animated.View, innerProps, childNode)
774
776
  : createElement(View, innerProps, childNode)
775
777
 
776
- return enableHover
777
- ? createElement(GestureDetector, { gesture: gesture as PanGesture }, BaseComponent)
778
- : BaseComponent
778
+ if (enableHover) {
779
+ finalComponent = createElement(GestureDetector, { gesture: gesture as PanGesture }, finalComponent)
780
+ }
781
+
782
+ if (hasPositionFixed) {
783
+ finalComponent = createElement(Portal, null, finalComponent)
784
+ }
785
+ return finalComponent
779
786
  })
780
787
 
781
788
  _View.displayName = 'MpxView'