@mpxjs/webpack-plugin 2.10.17-beta.6 → 2.10.17-beta.8

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 (35) hide show
  1. package/lib/index.js +1 -0
  2. package/lib/json-compiler/index.js +18 -1
  3. package/lib/platform/style/wx/index.js +1 -17
  4. package/lib/react/processJSON.js +20 -1
  5. package/lib/react/processScript.js +1 -0
  6. package/lib/react/script-helper.js +0 -1
  7. package/lib/runtime/components/ali/mpx-recycle-view.mpx +518 -0
  8. package/lib/runtime/components/ali/mpx-sticky-header.mpx +212 -0
  9. package/lib/runtime/components/ali/mpx-sticky-section.mpx +17 -0
  10. package/lib/runtime/components/react/animationHooks/useTransitionHooks.ts +34 -30
  11. package/lib/runtime/components/react/animationHooks/utils.ts +3 -2
  12. package/lib/runtime/components/react/dist/animationHooks/useTransitionHooks.js +38 -33
  13. package/lib/runtime/components/react/dist/animationHooks/utils.js +3 -2
  14. package/lib/runtime/components/react/dist/mpx-image.jsx +2 -2
  15. package/lib/runtime/components/react/dist/mpx-recycle-view.d.ts +45 -0
  16. package/lib/runtime/components/react/dist/mpx-recycle-view.jsx +272 -0
  17. package/lib/runtime/components/react/dist/mpx-swiper.jsx +6 -5
  18. package/lib/runtime/components/react/dist/utils.d.ts +2 -1
  19. package/lib/runtime/components/react/dist/utils.jsx +15 -21
  20. package/lib/runtime/components/react/mpx-image.tsx +2 -2
  21. package/lib/runtime/components/react/mpx-recycle-view.tsx +398 -0
  22. package/lib/runtime/components/react/mpx-scroll-view.tsx +1 -0
  23. package/lib/runtime/components/react/mpx-sticky-section.tsx +1 -1
  24. package/lib/runtime/components/react/mpx-swiper.tsx +6 -5
  25. package/lib/runtime/components/react/utils.tsx +18 -23
  26. package/lib/runtime/components/web/mpx-recycle-view.vue +508 -0
  27. package/lib/runtime/components/wx/mpx-list-header-default.mpx +21 -0
  28. package/lib/runtime/components/wx/mpx-recycle-item-default.mpx +21 -0
  29. package/lib/runtime/components/wx/mpx-recycle-view.mpx +193 -0
  30. package/lib/runtime/components/wx/mpx-section-header-default.mpx +21 -0
  31. package/lib/template-compiler/compiler.js +8 -3
  32. package/lib/utils/const.js +17 -0
  33. package/lib/utils/process-extend-components.js +43 -0
  34. package/lib/web/processJSON.js +20 -2
  35. package/package.json +1 -1
@@ -0,0 +1,398 @@
1
+ import React, { forwardRef, useRef, useState, useEffect, useMemo, createElement, useImperativeHandle } from 'react'
2
+ import { SectionList, FlatList, RefreshControl, NativeSyntheticEvent, NativeScrollEvent } from 'react-native'
3
+ import useInnerProps, { getCustomEvent } from './getInnerListeners'
4
+ import { extendObject, useLayout, useTransformStyle } from './utils'
5
+ interface ListItem {
6
+ isSectionHeader?: boolean;
7
+ _originalItemIndex?: number;
8
+ [key: string]: any;
9
+ }
10
+
11
+ interface Section {
12
+ headerData: ListItem | null;
13
+ data: ListItem[];
14
+ hasSectionHeader?: boolean;
15
+ _originalItemIndex?: number;
16
+ }
17
+
18
+ interface ItemHeightType {
19
+ value?: number;
20
+ getter?: (item: any, index: number) => number;
21
+ }
22
+
23
+ interface RecycleViewProps {
24
+ enhanced?: boolean;
25
+ bounces?: boolean;
26
+ scrollEventThrottle?: number;
27
+ height?: number | string;
28
+ width?: number | string;
29
+ listData?: ListItem[];
30
+ generichash?: string;
31
+ style?: Record<string, any>;
32
+ itemHeight?: ItemHeightType;
33
+ sectionHeaderHeight?: ItemHeightType;
34
+ listHeaderData?: any;
35
+ listHeaderHeight?: ItemHeightType;
36
+ useListHeader?: boolean;
37
+ 'genericrecycle-item'?: string;
38
+ 'genericsection-header'?: string;
39
+ 'genericlist-header'?: string;
40
+ 'enable-var'?: boolean;
41
+ 'external-var-context'?: any;
42
+ 'parent-font-size'?: number;
43
+ 'parent-width'?: number;
44
+ 'parent-height'?: number;
45
+ 'enable-sticky'?: boolean;
46
+ 'enable-back-to-top'?: boolean;
47
+ 'end-reached-threshold'?: number;
48
+ 'refresher-enabled'?: boolean;
49
+ 'show-scrollbar'?: boolean;
50
+ 'refresher-triggered'?: boolean;
51
+ bindrefresherrefresh?: (event: any) => void;
52
+ bindscrolltolower?: (event: any) => void;
53
+ bindscroll?: (event: any) => void;
54
+ [key: string]: any;
55
+ }
56
+
57
+ interface ScrollPositionParams {
58
+ index: number;
59
+ animated?: boolean;
60
+ viewOffset?: number;
61
+ viewPosition?: number;
62
+ }
63
+
64
+ const getGeneric = (generichash: string, generickey: string) => {
65
+ if (!generichash || !generickey) return null
66
+ const GenericComponent = global.__mpxGenericsMap?.[generichash]?.[generickey]?.()
67
+ if (!GenericComponent) return null
68
+
69
+ return forwardRef((props: any, ref: any) => {
70
+ return createElement(GenericComponent, extendObject({}, {
71
+ ref: ref
72
+ }, props))
73
+ })
74
+ }
75
+
76
+ const getListHeaderComponent = (generichash: string, generickey: string, data: any) => {
77
+ if (!generichash || !generickey) return undefined
78
+ const ListHeaderComponent = getGeneric(generichash, generickey)
79
+ return ListHeaderComponent ? createElement(ListHeaderComponent, { listHeaderData: data }) : null
80
+ }
81
+
82
+ const getSectionHeaderRenderer = (generichash: string, generickey: string) => {
83
+ if (!generichash || !generickey) return undefined
84
+ return (sectionData: { section: Section }) => {
85
+ if (!sectionData.section.hasSectionHeader) return null
86
+ const SectionHeaderComponent = getGeneric(generichash, generickey)
87
+ return SectionHeaderComponent ? createElement(SectionHeaderComponent, { itemData: sectionData.section.headerData }) : null
88
+ }
89
+ }
90
+
91
+ const getItemRenderer = (generichash: string, generickey: string) => {
92
+ if (!generichash || !generickey) return undefined
93
+ return ({ item }: { item: any }) => {
94
+ const ItemComponent = getGeneric(generichash, generickey)
95
+ return ItemComponent ? createElement(ItemComponent, { itemData: item }) : null
96
+ }
97
+ }
98
+
99
+ const RecycleView = forwardRef<any, RecycleViewProps>((props = {}, ref) => {
100
+ const {
101
+ enhanced = false,
102
+ bounces = true,
103
+ scrollEventThrottle = 0,
104
+ height,
105
+ width,
106
+ listData,
107
+ generichash,
108
+ style = {},
109
+ itemHeight = {},
110
+ sectionHeaderHeight = {},
111
+ listHeaderHeight = {},
112
+ listHeaderData = null,
113
+ useListHeader = false,
114
+ 'genericrecycle-item': genericrecycleItem,
115
+ 'genericsection-header': genericsectionHeader,
116
+ 'genericlist-header': genericListHeader,
117
+ 'enable-var': enableVar,
118
+ 'external-var-context': externalVarContext,
119
+ 'parent-font-size': parentFontSize,
120
+ 'parent-width': parentWidth,
121
+ 'parent-height': parentHeight,
122
+ 'enable-sticky': enableSticky = false,
123
+ 'enable-back-to-top': enableBackToTop = false,
124
+ 'end-reached-threshold': onEndReachedThreshold = 0.1,
125
+ 'refresher-enabled': refresherEnabled,
126
+ 'show-scrollbar': showScrollbar = true,
127
+ 'refresher-triggered': refresherTriggered
128
+ } = props
129
+
130
+ const [refreshing, setRefreshing] = useState(!!refresherTriggered)
131
+
132
+ const scrollViewRef = useRef<any>(null)
133
+
134
+ const indexMap = useRef<{ [key: string]: string | number }>({})
135
+
136
+ const reverseIndexMap = useRef<{ [key: string]: number }>({})
137
+
138
+ const {
139
+ hasSelfPercent,
140
+ setWidth,
141
+ setHeight
142
+ } = useTransformStyle(style, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight })
143
+
144
+ const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef: scrollViewRef })
145
+
146
+ useEffect(() => {
147
+ if (refreshing !== refresherTriggered) {
148
+ setRefreshing(!!refresherTriggered)
149
+ }
150
+ }, [refresherTriggered])
151
+
152
+ const onRefresh = () => {
153
+ const { bindrefresherrefresh } = props
154
+ bindrefresherrefresh &&
155
+ bindrefresherrefresh(
156
+ getCustomEvent('refresherrefresh', {}, { layoutRef }, props)
157
+ )
158
+ }
159
+
160
+ const onEndReached = () => {
161
+ const { bindscrolltolower } = props
162
+ bindscrolltolower &&
163
+ bindscrolltolower(
164
+ getCustomEvent('scrolltolower', {}, { layoutRef }, props)
165
+ )
166
+ }
167
+
168
+ const onScroll = (event: NativeSyntheticEvent<NativeScrollEvent>) => {
169
+ const { bindscroll } = props
170
+ bindscroll &&
171
+ bindscroll(
172
+ getCustomEvent('scroll', event.nativeEvent, { layoutRef }, props)
173
+ )
174
+ }
175
+
176
+ // 通过sectionIndex和rowIndex获取原始索引
177
+ const getOriginalIndex = (sectionIndex: number, rowIndex: number | 'header'): number => {
178
+ const key = `${sectionIndex}_${rowIndex}`
179
+ return reverseIndexMap.current[key] ?? -1 // 如果找不到,返回-1
180
+ }
181
+
182
+ const scrollToIndex = ({ index, animated, viewOffset = 0, viewPosition = 0 }: ScrollPositionParams) => {
183
+ if (scrollViewRef.current) {
184
+ // 通过索引映射表快速定位位置
185
+ const position = indexMap.current[index]
186
+ const [sectionIndex, itemIndex] = (position as string).split('_')
187
+ scrollViewRef.current.scrollToLocation?.({
188
+ itemIndex: itemIndex === 'header' ? 0 : Number(itemIndex) + 1,
189
+ sectionIndex: Number(sectionIndex) || 0,
190
+ animated,
191
+ viewOffset,
192
+ viewPosition
193
+ })
194
+ }
195
+ }
196
+
197
+ const getItemHeight = ({ sectionIndex, rowIndex }: { sectionIndex: number, rowIndex: number }) => {
198
+ if (!itemHeight) {
199
+ return 0
200
+ }
201
+ if ((itemHeight as ItemHeightType).getter) {
202
+ const item = convertedListData[sectionIndex].data[rowIndex]
203
+ // 使用getOriginalIndex获取原始索引
204
+ const originalIndex = getOriginalIndex(sectionIndex, rowIndex)
205
+ return (itemHeight as ItemHeightType).getter?.(item, originalIndex) || 0
206
+ } else {
207
+ return (itemHeight as ItemHeightType).value || 0
208
+ }
209
+ }
210
+
211
+ const getSectionHeaderHeight = ({ sectionIndex }: { sectionIndex: number }) => {
212
+ const item = convertedListData[sectionIndex]
213
+ const { hasSectionHeader } = item
214
+ // 使用getOriginalIndex获取原始索引
215
+ const originalIndex = getOriginalIndex(sectionIndex, 'header')
216
+ if (!hasSectionHeader) return 0
217
+ if ((sectionHeaderHeight as ItemHeightType).getter) {
218
+ return (sectionHeaderHeight as ItemHeightType).getter?.(item, originalIndex) || 0
219
+ } else {
220
+ return (sectionHeaderHeight as ItemHeightType).value || 0
221
+ }
222
+ }
223
+
224
+ const convertedListData = useMemo(() => {
225
+ const sections: Section[] = []
226
+ let currentSection: Section | null = null
227
+ // 清空之前的索引映射
228
+ indexMap.current = {}
229
+ // 清空反向索引映射
230
+ reverseIndexMap.current = {}
231
+ listData.forEach((item: ListItem, index: number) => {
232
+ if (item.isSectionHeader) {
233
+ // 如果已经存在一个 section,先把它添加到 sections 中
234
+ if (currentSection) {
235
+ sections.push(currentSection)
236
+ }
237
+ // 创建新的 section
238
+ currentSection = {
239
+ headerData: item,
240
+ data: [],
241
+ hasSectionHeader: true,
242
+ _originalItemIndex: index
243
+ }
244
+ // 为 section header 添加索引映射
245
+ const sectionIndex = sections.length
246
+ indexMap.current[index] = `${sectionIndex}_header`
247
+ // 添加反向索引映射
248
+ reverseIndexMap.current[`${sectionIndex}_header`] = index
249
+ } else {
250
+ // 如果没有当前 section,创建一个默认的
251
+ if (!currentSection) {
252
+ // 创建默认section (无header的section)
253
+ currentSection = {
254
+ headerData: null,
255
+ data: [],
256
+ hasSectionHeader: false,
257
+ _originalItemIndex: -1
258
+ }
259
+ }
260
+ // 将 item 添加到当前 section 的 data 中
261
+ const itemIndex = currentSection.data.length
262
+ currentSection.data.push(extendObject({}, item, {
263
+ _originalItemIndex: index
264
+ }))
265
+ let sectionIndex
266
+ // 为 item 添加索引映射 - 存储格式为: "sectionIndex_itemIndex"
267
+ if (!currentSection.hasSectionHeader && sections.length === 0) {
268
+ // 在默认section中(第一个且无header)
269
+ sectionIndex = 0
270
+ indexMap.current[index] = `${sectionIndex}_${itemIndex}`
271
+ } else {
272
+ // 在普通section中
273
+ sectionIndex = sections.length
274
+ indexMap.current[index] = `${sectionIndex}_${itemIndex}`
275
+ }
276
+ // 添加反向索引映射
277
+ reverseIndexMap.current[`${sectionIndex}_${itemIndex}`] = index
278
+ }
279
+ })
280
+ // 添加最后一个 section
281
+ if (currentSection) {
282
+ sections.push(currentSection)
283
+ }
284
+ return sections
285
+ }, [listData])
286
+
287
+ const { getItemLayout } = useMemo(() => {
288
+ const layouts: Array<{ length: number, offset: number, index: number }> = []
289
+ let offset = 0
290
+
291
+ if (useListHeader) {
292
+ // 计算列表头部的高度
293
+ offset += listHeaderHeight.getter?.() || listHeaderHeight.value || 0
294
+ }
295
+
296
+ // 遍历所有 sections
297
+ convertedListData.forEach((section: Section, sectionIndex: number) => {
298
+ // 添加 section header 的位置信息
299
+ const headerHeight = getSectionHeaderHeight({ sectionIndex })
300
+ layouts.push({
301
+ length: headerHeight,
302
+ offset,
303
+ index: layouts.length
304
+ })
305
+ offset += headerHeight
306
+
307
+ // 添加该 section 中所有 items 的位置信息
308
+ section.data.forEach((item: ListItem, itemIndex: number) => {
309
+ const contenteight = getItemHeight({ sectionIndex, rowIndex: itemIndex })
310
+ layouts.push({
311
+ length: contenteight,
312
+ offset,
313
+ index: layouts.length
314
+ })
315
+ offset += contenteight
316
+ })
317
+
318
+ // 添加该 section 尾部位置信息
319
+ // 因为即使 sectionList 没传 renderSectionFooter,getItemLayout 中的 index 的计算也会包含尾部节点
320
+ layouts.push({
321
+ length: 0,
322
+ offset,
323
+ index: layouts.length
324
+ })
325
+ })
326
+ return {
327
+ itemLayouts: layouts,
328
+ getItemLayout: (data: any, index: number) => layouts[index]
329
+ }
330
+ }, [convertedListData, useListHeader])
331
+
332
+ const scrollAdditionalProps = extendObject(
333
+ {
334
+ alwaysBounceVertical: false,
335
+ alwaysBounceHorizontal: false,
336
+ scrollEventThrottle: scrollEventThrottle,
337
+ scrollsToTop: enableBackToTop,
338
+ showsHorizontalScrollIndicator: showScrollbar,
339
+ onEndReachedThreshold,
340
+ ref: scrollViewRef,
341
+ bounces: false,
342
+ stickySectionHeadersEnabled: enableSticky,
343
+ onScroll: onScroll,
344
+ onEndReached: onEndReached
345
+ },
346
+ layoutProps
347
+ )
348
+
349
+ if (enhanced) {
350
+ Object.assign(scrollAdditionalProps, {
351
+ bounces
352
+ })
353
+ }
354
+ if (refresherEnabled) {
355
+ Object.assign(scrollAdditionalProps, {
356
+ refreshing: refreshing
357
+ })
358
+ }
359
+
360
+ useImperativeHandle(ref, () => {
361
+ return {
362
+ ...props,
363
+ scrollToIndex
364
+ }
365
+ })
366
+
367
+ const innerProps = useInnerProps(extendObject({}, props, scrollAdditionalProps), [
368
+ 'id',
369
+ 'show-scrollbar',
370
+ 'lower-threshold',
371
+ 'refresher-triggered',
372
+ 'refresher-enabled',
373
+ 'bindrefresherrefresh'
374
+ ], { layoutRef })
375
+
376
+ return createElement(
377
+ SectionList,
378
+ extendObject(
379
+ {
380
+ style: [{ height, width }, style, layoutStyle],
381
+ sections: convertedListData,
382
+ renderItem: getItemRenderer(generichash, genericrecycleItem),
383
+ getItemLayout: getItemLayout,
384
+ ListHeaderComponent: useListHeader ? getListHeaderComponent(generichash, genericListHeader, listHeaderData) : null,
385
+ renderSectionHeader: getSectionHeaderRenderer(generichash, genericsectionHeader),
386
+ refreshControl: refresherEnabled
387
+ ? React.createElement(RefreshControl, {
388
+ onRefresh: onRefresh,
389
+ refreshing: refreshing
390
+ })
391
+ : undefined
392
+ },
393
+ innerProps
394
+ )
395
+ )
396
+ })
397
+
398
+ export default RecycleView
@@ -259,6 +259,7 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
259
259
 
260
260
  // layout 完成前先隐藏,避免安卓闪烁问题
261
261
  const refresherLayoutStyle = useMemo(() => { return !hasRefresherLayoutRef.current ? HIDDEN_STYLE : {} }, [hasRefresherLayoutRef.current])
262
+
262
263
  const lastOffset = useRef(0)
263
264
 
264
265
  if (scrollX && scrollY) {
@@ -1,9 +1,9 @@
1
-
2
1
  import { useRef, forwardRef, createElement, ReactNode, useCallback, useMemo } from 'react'
3
2
  import { View, ViewStyle } from 'react-native'
4
3
  import useNodesRef, { HandlerRef } from './useNodesRef'
5
4
  import { splitProps, splitStyle, useTransformStyle, wrapChildren, useLayout, extendObject } from './utils'
6
5
  import { StickyContext } from './context'
6
+
7
7
  import useInnerProps from './getInnerListeners'
8
8
 
9
9
  interface StickySectionProps {
@@ -232,6 +232,8 @@ const SwiperWrapper = forwardRef<HandlerRef<View, SwiperProps>, SwiperProps>((pr
232
232
  const moveTranstion = useSharedValue(0)
233
233
  const timerId = useRef(0 as number | ReturnType<typeof setTimeout>)
234
234
  const intervalTimer = props.interval || 500
235
+ // 记录是否首次
236
+ const isFirstRef = useRef(true)
235
237
 
236
238
  const simultaneousHandlers = flatGesture(originSimultaneousHandlers)
237
239
  const waitForHandlers = flatGesture(waitFor)
@@ -477,10 +479,8 @@ const SwiperWrapper = forwardRef<HandlerRef<View, SwiperProps>, SwiperProps>((pr
477
479
  }, [])
478
480
 
479
481
  function handleSwiperChange (current: number, pCurrent: number) {
480
- if (pCurrent !== currentIndex.value) {
481
- const eventData = getCustomEvent('change', {}, { detail: { current, source: 'touch' }, layoutRef: layoutRef })
482
- bindchange && bindchange(eventData)
483
- }
482
+ const eventData = getCustomEvent('change', {}, { detail: { current, source: 'touch' }, layoutRef: layoutRef })
483
+ bindchange && bindchange(eventData)
484
484
  }
485
485
 
486
486
  const runOnJSCallbackRef = useRef({
@@ -529,9 +529,10 @@ const SwiperWrapper = forwardRef<HandlerRef<View, SwiperProps>, SwiperProps>((pr
529
529
  // 1. 用户在当前页切换选中项,动画;用户携带选中index打开到swiper页直接选中不走动画
530
530
  useAnimatedReaction(() => currentIndex.value, (newIndex: number, preIndex: number) => {
531
531
  // 这里必须传递函数名, 直接写()=> {}形式会报 访问了未sharedValue信息
532
- if (newIndex !== preIndex && bindchange) {
532
+ if (newIndex !== preIndex && bindchange && !isFirstRef.current) {
533
533
  runOnJS(runOnJSCallback)('handleSwiperChange', newIndex, propCurrent)
534
534
  }
535
+ isFirstRef.current = false
535
536
  })
536
537
 
537
538
  useEffect(() => {
@@ -1,12 +1,11 @@
1
1
  import { useEffect, useCallback, useMemo, useRef, ReactNode, ReactElement, isValidElement, useContext, useState, Dispatch, SetStateAction, Children, cloneElement, createElement, MutableRefObject } from 'react'
2
2
  import { LayoutChangeEvent, TextStyle, ImageProps, Image } from 'react-native'
3
- import { isObject, isFunction, isNumber, hasOwn, diffAndCloneA, error, warn, isEmptyObject } from '@mpxjs/utils'
3
+ import { isObject, isFunction, isNumber, hasOwn, diffAndCloneA, error, warn } from '@mpxjs/utils'
4
4
  import { VarContext, ScrollViewContext, RouteContext } from './context'
5
5
  import { ExpressionParser, parseFunc, ReplaceSource } from './parser'
6
6
  import { initialWindowMetrics } from 'react-native-safe-area-context'
7
7
  import FastImage, { FastImageProps } from '@d11/react-native-fast-image'
8
8
  import type { AnyFunc, ExtendedFunctionComponent } from './types/common'
9
- import { runOnJS } from 'react-native-reanimated'
10
9
  import { Gesture } from 'react-native-gesture-handler'
11
10
 
12
11
  export const TEXT_STYLE_REGEX = /color|font.*|text.*|letterSpacing|lineHeight|includeFontPadding|writingDirection/
@@ -143,16 +142,17 @@ export function splitStyle<T extends Record<string, any>> (styleObj: T): {
143
142
  innerStyle: Partial<T>
144
143
  }
145
144
  }
146
-
147
- const selfPercentRule: Record<string, 'height' | 'width'> = {
148
- translateX: 'width',
149
- translateY: 'height',
145
+ const radiusPercentRule: Record<string, 'height' | 'width'> = {
150
146
  borderTopLeftRadius: 'width',
151
147
  borderBottomLeftRadius: 'width',
152
148
  borderBottomRightRadius: 'width',
153
149
  borderTopRightRadius: 'width',
154
150
  borderRadius: 'width'
155
151
  }
152
+ const selfPercentRule: Record<string, 'height' | 'width'> = Object.assign({
153
+ translateX: 'width',
154
+ translateY: 'height'
155
+ }, radiusPercentRule)
156
156
 
157
157
  const parentHeightPercentRule: Record<string, boolean> = {
158
158
  height: true,
@@ -238,7 +238,7 @@ function transformVar (styleObj: Record<string, any>, varKeyPaths: Array<Array<s
238
238
  const resolved = resolveVar(value, varContext)
239
239
  if (resolved === undefined) {
240
240
  delete target[key]
241
- // error(`Can not resolve css var at ${varKeyPath.join('.')}:${value}.`)
241
+ error(`Can not resolve css var at ${varKeyPath.join('.')}:${value}.`)
242
242
  return
243
243
  }
244
244
  target[key] = resolved
@@ -390,23 +390,16 @@ function transformBoxShadow (styleObj: Record<string, any>) {
390
390
  }, '')
391
391
  }
392
392
 
393
- function transformZIndex (styleObj: Record<string, any>) {
394
- if (!styleObj.zIndex || typeof styleObj.zIndex === 'number') return
395
- if (styleObj.zIndex === 'auto') {
396
- error('Property [z-index] does not supported [auto], please check again!')
397
- styleObj.zIndex = 0
398
- }
399
- }
400
-
401
393
  interface TransformStyleConfig {
402
394
  enableVar?: boolean
403
395
  externalVarContext?: Record<string, any>
404
396
  parentFontSize?: number
405
397
  parentWidth?: number
406
398
  parentHeight?: number
399
+ isTransformBorderRadiusPercent?: boolean
407
400
  }
408
401
 
409
- export function useTransformStyle (styleObj: Record<string, any> = {}, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight }: TransformStyleConfig) {
402
+ export function useTransformStyle (styleObj: Record<string, any> = {}, { enableVar, isTransformBorderRadiusPercent, externalVarContext, parentFontSize, parentWidth, parentHeight }: TransformStyleConfig) {
410
403
  const varStyle: Record<string, any> = {}
411
404
  const unoVarStyle: Record<string, any> = {}
412
405
  const normalStyle: Record<string, any> = {}
@@ -457,7 +450,7 @@ export function useTransformStyle (styleObj: Record<string, any> = {}, { enableV
457
450
  function calcVisitor ({ key, value, keyPath }: VisitorArg) {
458
451
  if (calcUseRegExp.test(value)) {
459
452
  // calc translate & border-radius 的百分比计算
460
- if (hasOwn(selfPercentRule, key) && /%/.test(value)) {
453
+ if (hasOwn(selfPercentRule, key) && /calc\(\d+%/.test(value)) {
461
454
  hasSelfPercent = true
462
455
  percentKeyPaths.push(keyPath.slice())
463
456
  }
@@ -467,7 +460,11 @@ export function useTransformStyle (styleObj: Record<string, any> = {}, { enableV
467
460
 
468
461
  function percentVisitor ({ key, value, keyPath }: VisitorArg) {
469
462
  // fixme 去掉 translate & border-radius 的百分比计算
470
- if ((key === 'fontSize' || key === 'lineHeight') && PERCENT_REGEX.test(value)) {
463
+ // fixme Image 组件 borderRadius 仅支持 number
464
+ if (isTransformBorderRadiusPercent && hasOwn(radiusPercentRule, key) && PERCENT_REGEX.test(value)) {
465
+ hasSelfPercent = true
466
+ percentKeyPaths.push(keyPath.slice())
467
+ } else if ((key === 'fontSize' || key === 'lineHeight') && PERCENT_REGEX.test(value)) {
471
468
  percentKeyPaths.push(keyPath.slice())
472
469
  }
473
470
  }
@@ -477,8 +474,10 @@ export function useTransformStyle (styleObj: Record<string, any> = {}, { enableV
477
474
  [envVisitor, percentVisitor, calcVisitor].forEach(visitor => visitor({ target, key, value, keyPath }))
478
475
  }
479
476
  }
477
+
480
478
  // transform 字符串格式转化数组格式(先转数组再处理css var)
481
479
  transformTransform(styleObj)
480
+
482
481
  // traverse var & generate normalStyle
483
482
  traverseStyle(styleObj, [varVisitor])
484
483
  hasVarDec = hasVarDec || !!externalVarContext
@@ -544,11 +543,7 @@ export function useTransformStyle (styleObj: Record<string, any> = {}, { enableV
544
543
  transformStringify(normalStyle)
545
544
  // transform rpx to px
546
545
  transformBoxShadow(normalStyle)
547
- // transform z-index auto to 0
548
- transformZIndex(normalStyle)
549
- if (Array.isArray(normalStyle.transform)) {
550
- normalStyle.transform = normalStyle.transform.filter(item => !isEmptyObject(item))
551
- }
546
+
552
547
  return {
553
548
  hasVarDec,
554
549
  varContextRef,