From 66acf09d37f7a1df90c556605e7138171b43bda1 Mon Sep 17 00:00:00 2001 From: hiyuki <674883329@qq.com> Date: Thu, 17 Oct 2024 15:16:32 +0800 Subject: [PATCH 1/4] RN: support calc() && fix transform percent --- .../lib/platform/style/wx/index.js | 5 - .../lib/runtime/components/react/mpx-text.tsx | 27 +++- .../lib/runtime/components/react/mpx-view.tsx | 31 +++-- .../lib/runtime/components/react/utils.ts | 120 ++++++++++-------- 4 files changed, 111 insertions(+), 72 deletions(-) diff --git a/packages/webpack-plugin/lib/platform/style/wx/index.js b/packages/webpack-plugin/lib/platform/style/wx/index.js index 6cac0cf304..83e8ea6789 100644 --- a/packages/webpack-plugin/lib/platform/style/wx/index.js +++ b/packages/webpack-plugin/lib/platform/style/wx/index.js @@ -233,11 +233,6 @@ module.exports = function getSpec ({ warn, error }) { suffix = ['Top', 'Right', 'Bottom', 'Left'] break } - if (values.length === 1 && (calcExp.test(value) || cssVariableExp.test(value))) { - // calc() or var() 则分开输出 - suffix = ['Vertical', 'Horizontal'] - values.push(values[0]) - } return values.map((value, index) => { const newProp = `${prop}${suffix[index] || ''}` // validate diff --git a/packages/webpack-plugin/lib/runtime/components/react/mpx-text.tsx b/packages/webpack-plugin/lib/runtime/components/react/mpx-text.tsx index fd554b2e48..dba63dc21f 100644 --- a/packages/webpack-plugin/lib/runtime/components/react/mpx-text.tsx +++ b/packages/webpack-plugin/lib/runtime/components/react/mpx-text.tsx @@ -15,11 +15,12 @@ interface _TextProps extends TextProps { style?: TextStyle children?: ReactNode selectable?: boolean + 'user-select'?: boolean 'enable-var'?: boolean 'external-var-context'?: Record - 'user-select'?: boolean - userSelect?: boolean - 'disable-default-style'?: boolean + 'parent-font-size'?: number + 'parent-width'?: number + 'parent-height'?: number } interface WrapChildrenConfig { @@ -41,7 +42,10 @@ const _Text = forwardRef, _TextProps>((props, ref): selectable, 'enable-var': enableVar, 'external-var-context': externalVarContext, - 'user-select': userSelect + 'user-select': userSelect, + 'parent-font-size': parentFontSize, + 'parent-width': parentWidth, + 'parent-height': parentHeight } = props const layoutRef = useRef({}) @@ -50,7 +54,13 @@ const _Text = forwardRef, _TextProps>((props, ref): normalStyle, hasVarDec, varContextRef - } = useTransformStyle(style, { enableVar, externalVarContext }) + } = useTransformStyle(style, { + enableVar, + externalVarContext, + parentFontSize, + parentWidth, + parentHeight + }) const { nodeRef } = useNodesRef(props, ref) @@ -61,8 +71,11 @@ const _Text = forwardRef, _TextProps>((props, ref): 'children', 'selectable', 'user-select', - 'useInherit', - 'enable-offset' + 'enable-var', + 'external-var-context', + 'parent-font-size', + 'parent-width', + 'parent-height' ], { layoutRef }) diff --git a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx index c17f20bfb0..353bd7eec7 100644 --- a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx +++ b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx @@ -21,6 +21,9 @@ export interface _ViewProps extends ViewProps { 'enable-background'?: boolean 'enable-var'?: boolean 'external-var-context'?: Record + 'parent-font-size'?: number + 'parent-width'?: number + 'parent-height'?: number bindtouchstart?: (event: NativeSyntheticEvent | unknown) => void bindtouchmove?: (event: NativeSyntheticEvent | unknown) => void bindtouchend?: (event: NativeSyntheticEvent | unknown) => void @@ -426,7 +429,10 @@ const _View = forwardRef, _ViewProps>((props, ref): 'enable-offset': enableOffset, 'enable-var': enableVar, 'external-var-context': externalVarContext, - 'enable-background': enableBackground + 'enable-background': enableBackground, + 'parent-font-size': parentFontSize, + 'parent-width': parentWidth, + 'parent-height': parentHeight } = props const [isHover, setIsHover] = useState(false) @@ -451,12 +457,18 @@ const _View = forwardRef, _ViewProps>((props, ref): const { normalStyle, - hasPercent, + hasSelfPercent, hasVarDec, varContextRef, - setContainerWidth, - setContainerHeight - } = useTransformStyle(styleObj, { enableVar, externalVarContext }) + setWidth, + setHeight + } = useTransformStyle(styleObj, { + enableVar, + externalVarContext, + parentFontSize, + parentWidth, + parentHeight + }) const { textStyle, backgroundStyle, innerStyle } = splitStyle(normalStyle) @@ -510,10 +522,11 @@ const _View = forwardRef, _ViewProps>((props, ref): } const onLayout = (res: LayoutChangeEvent) => { - if (hasPercent) { + props.onLayout && props.onLayout(res) + if (hasSelfPercent) { const { width, height } = res?.nativeEvent?.layout || {} - setContainerWidth(width || 0) - setContainerHeight(height || 0) + setWidth(width || 0) + setHeight(height || 0) } if (enableOffset) { nodeRef.current?.measure((x: number, y: number, width: number, height: number, offsetLeft: number, offsetTop: number) => { @@ -522,7 +535,7 @@ const _View = forwardRef, _ViewProps>((props, ref): } } - const needLayout = enableOffset || hasPercent + const needLayout = enableOffset || hasSelfPercent const innerProps = useInnerProps(props, { ref: nodeRef, diff --git a/packages/webpack-plugin/lib/runtime/components/react/utils.ts b/packages/webpack-plugin/lib/runtime/components/react/utils.ts index c3403b27b0..b7e49845df 100644 --- a/packages/webpack-plugin/lib/runtime/components/react/utils.ts +++ b/packages/webpack-plugin/lib/runtime/components/react/utils.ts @@ -132,7 +132,7 @@ export function splitStyle (styleObj: Object) { }) } -const percentRule: Record = { +const selfPercentRule: Record = { translateX: 'width', translateY: 'height', borderTopLeftRadius: 'width', @@ -142,16 +142,10 @@ const percentRule: Record = { borderRadius: 'width' } -const heightPercentRule: Record = { - translateY: true, +const parentHeightPercentRule: Record = { + height: true, top: true, - bottom: true, - marginTop: true, - marginBottom: true, - marginVertical: true, - paddingTop: true, - paddingBottom: true, - paddingVertical: true + bottom: true } // todo calc时处理角度和时间等单位 @@ -167,18 +161,47 @@ function formatValue (value: string) { return value } -function transformPercent (styleObj: Record, percentKeyPaths: Array>, { width, height }: { width?: number, height?: number }) { +interface PercentConfig { + fontSize?: number | string + width?: number + height?: number + parentFontSize?: number + parentWidth?: number + parentHeight?: number +} + +function resolvePercent (value: string | number | undefined, key: string, percentConfig: PercentConfig): string | number | undefined { + if (!(typeof value === 'string' && PERCENT_REGEX.test(value))) return value + let base + let reason + if (key === 'fontSize') { + base = percentConfig.parentFontSize + reason = 'parent-font-size' + } else if (key === 'lineHeight') { + base = resolvePercent(percentConfig.fontSize, 'fontSize', percentConfig) + reason = 'font-size' + } else if (selfPercentRule[key]) { + base = percentConfig[selfPercentRule[key]] + reason = selfPercentRule[key] + } else if (parentHeightPercentRule[key]) { + base = percentConfig.parentHeight + reason = 'parent-height' + } else { + base = percentConfig.parentWidth + reason = 'parent-width' + } + if (typeof base !== 'number') { + error(`[${key}] can not contain % unit unless you set [${reason}] with a number for the percent calculation.`) + return value + } else { + return parseFloat(value) / 100 * base + } +} + +function transformPercent (styleObj: Record, percentKeyPaths: Array>, percentConfig: PercentConfig) { percentKeyPaths.forEach((percentKeyPath) => { setStyle(styleObj, percentKeyPath, ({ target, key, value }) => { - const percentage = parseFloat(value) / 100 - const type = percentRule[key] - if (type === 'height' && height) { - target[key] = percentage * height - } else if (type === 'width' && width) { - target[key] = percentage * width - } else { - target[key] = 0 - } + target[key] = resolvePercent(value, key, percentConfig) }) }) } @@ -246,22 +269,22 @@ function transformLineHeight (styleObj: Record) { interface TransformStyleConfig { enableVar?: boolean externalVarContext?: Record + parentFontSize?: number + parentWidth?: number + parentHeight?: number } -export function useTransformStyle (styleObj: Record = {}, { enableVar, externalVarContext }: TransformStyleConfig) { +export function useTransformStyle (styleObj: Record = {}, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight }: TransformStyleConfig) { const varStyle: Record = {} const normalStyle: Record = {} let hasVarDec = false let hasVarUse = false - let hasPercent = false - let hasCalcUse = false + let hasSelfPercent = false const varKeyPaths: Array> = [] const percentKeyPaths: Array> = [] const calcKeyPaths: Array> = [] const [width, setWidth] = useState(0) const [height, setHeight] = useState(0) - const setContainerWidth = setWidth - const setContainerHeight = setHeight function varVisitor ({ key, value, keyPath }: VisitorArg) { if (keyPath.length === 1) { @@ -301,14 +324,15 @@ export function useTransformStyle (styleObj: Record = {}, { enableV function calcVisitor ({ value, keyPath }: VisitorArg) { if (calcUseRegExp.test(value)) { - hasCalcUse = true calcKeyPaths.push(keyPath.slice()) } } function percentVisitor ({ key, value, keyPath }: VisitorArg) { - if (hasOwn(percentRule, key) && PERCENT_REGEX.test(value)) { - hasPercent = true + if (hasOwn(selfPercentRule, key) && PERCENT_REGEX.test(value)) { + hasSelfPercent = true + percentKeyPaths.push(keyPath.slice()) + } else if (key === 'fontSize' || key === 'lineHeight') { percentKeyPaths.push(keyPath.slice()) } } @@ -316,21 +340,22 @@ export function useTransformStyle (styleObj: Record = {}, { enableV // traverse calc & percent traverseStyle(normalStyle, [percentVisitor, calcVisitor]) - // apply percent - if (hasPercent) { - transformPercent(normalStyle, percentKeyPaths, { width, height }) + const percentConfig = { + width, + height, + fontSize: normalStyle.fontSize, + parentWidth, + parentHeight, + parentFontSize } - function calcFormatter (value: string, key: string) { + // apply percent + transformPercent(normalStyle, percentKeyPaths, percentConfig) + // apply calc + transformCalc(normalStyle, calcKeyPaths, (value: string, key: string) => { if (PERCENT_REGEX.test(value)) { - if (key === 'width' || key === 'height') { - error(`calc() can not use % in ${key}.`) - return 0 - } - hasPercent = true - const percentage = parseFloat(value) / 100 - const isHeight = heightPercentRule[key] - return percentage * (isHeight ? height : width) + const resolved = resolvePercent(value, key, percentConfig) + return typeof resolved === 'number' ? resolved : 0 } else { const formatted = formatValue(value) if (typeof formatted === 'number') { @@ -340,23 +365,16 @@ export function useTransformStyle (styleObj: Record = {}, { enableV return 0 } } - } - // apply calc - if (hasCalcUse) { - transformCalc(normalStyle, calcKeyPaths, calcFormatter) - } - // transform lineHeight - transformLineHeight(normalStyle) + }) return { normalStyle, - hasPercent, + hasSelfPercent, hasVarDec, - hasVarUse, enableVarRef, varContextRef, - setContainerWidth, - setContainerHeight + setWidth, + setHeight } } From 78a651480c2af7f65274ef437bbc364f6f3640e4 Mon Sep 17 00:00:00 2001 From: hiyuki <674883329@qq.com> Date: Thu, 17 Oct 2024 15:39:09 +0800 Subject: [PATCH 2/4] rm private props --- .../lib/runtime/components/react/mpx-view.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx index 353bd7eec7..1d7a7eab54 100644 --- a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx +++ b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx @@ -552,7 +552,12 @@ const _View = forwardRef, _ViewProps>((props, ref): 'hover-style', 'hover-class', 'enable-offset', - 'enable-background-image' + 'enable-background-image', + 'enable-var', + 'external-var-context', + 'parent-font-size', + 'parent-width', + 'parent-height' ], { layoutRef }) From 7966a2b5c99c13d18136855b5f147889f34de368 Mon Sep 17 00:00:00 2001 From: hiyuki <674883329@qq.com> Date: Thu, 17 Oct 2024 17:54:45 +0800 Subject: [PATCH 3/4] rm useless func --- .../lib/runtime/components/react/utils.ts | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/packages/webpack-plugin/lib/runtime/components/react/utils.ts b/packages/webpack-plugin/lib/runtime/components/react/utils.ts index b7e49845df..98b7fe5d1b 100644 --- a/packages/webpack-plugin/lib/runtime/components/react/utils.ts +++ b/packages/webpack-plugin/lib/runtime/components/react/utils.ts @@ -253,19 +253,6 @@ function transformCalc (styleObj: Record, calcKeyPaths: Array) { - let { lineHeight } = styleObj - if (typeof lineHeight === 'string' && PERCENT_REGEX.test(lineHeight)) { - const hasFontSize = hasOwn(styleObj, 'fontSize') - if (!hasFontSize) { - warn('The fontSize property could not be read correctly, so the default fontSize of 16 will be used as the basis for calculating the lineHeight!') - } - const fontSize = hasFontSize ? styleObj.fontSize : DEFAULT_FONT_SIZE - lineHeight = (parseFloat(lineHeight) / 100) * fontSize - styleObj.lineHeight = lineHeight - } -} - interface TransformStyleConfig { enableVar?: boolean externalVarContext?: Record From c117f280e20ba7bdad5bea97439e33b8a11e043b Mon Sep 17 00:00:00 2001 From: hiyuki <674883329@qq.com> Date: Thu, 17 Oct 2024 20:40:23 +0800 Subject: [PATCH 4/4] little adjust --- .../webpack-plugin/lib/runtime/components/react/mpx-view.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx index 1d7a7eab54..ef68ed2917 100644 --- a/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx +++ b/packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx @@ -383,7 +383,7 @@ function wrapImage (imageStyle?: ExtendedViewStyle) { } } - return + return {show && } }