From a116102b9110c78fdaeb72c90f692233abb1dbe1 Mon Sep 17 00:00:00 2001 From: unix Date: Sat, 12 Feb 2022 20:25:49 +0800 Subject: [PATCH 1/2] fix(scale): add dunamic functions to export all props related to scale --- components/use-scale/__tests__/scale.test.tsx | 26 ++++++ components/use-scale/scale-context.ts | 36 +++++++++ components/use-scale/utils.ts | 81 +++++++++---------- components/use-scale/with-scale.tsx | 25 ++---- 4 files changed, 104 insertions(+), 64 deletions(-) diff --git a/components/use-scale/__tests__/scale.test.tsx b/components/use-scale/__tests__/scale.test.tsx index a78be1bcf..256da73a1 100644 --- a/components/use-scale/__tests__/scale.test.tsx +++ b/components/use-scale/__tests__/scale.test.tsx @@ -167,4 +167,30 @@ describe('UseScale', () => { inner = wrapper.find('#inner').getDOMNode() expect(inner.hasAttribute('scale')).not.toBe(true) }) + + it('should be update all native scale props', () => { + const wrapper: React.FC = ({ children, ...props }) => ( + {children} + ) + const { result, rerender } = renderHook(() => useScale(), { + wrapper, + initialProps: {}, + }) + let { SCALES, getAllScaleProps } = result.current + expect(typeof SCALES).toEqual('object') + expect(typeof getAllScaleProps).toEqual('function') + expect(typeof getAllScaleProps()).toEqual('object') + + rerender({ width: '1em', height: '2em' }) + getAllScaleProps = result.current.getAllScaleProps + expect(getAllScaleProps().width).toEqual('1em') + expect(getAllScaleProps().height).toEqual('2em') + expect(typeof getAllScaleProps().font).toEqual('undefined') + + rerender({ px: '10px', mx: '20px' }) + getAllScaleProps = result.current.getAllScaleProps + expect(getAllScaleProps().px).toEqual('10px') + expect(getAllScaleProps().mx).toEqual('20px') + expect(typeof getAllScaleProps().paddingTop).toEqual('undefined') + }) }) diff --git a/components/use-scale/scale-context.ts b/components/use-scale/scale-context.ts index 477309c0d..78f5bff52 100644 --- a/components/use-scale/scale-context.ts +++ b/components/use-scale/scale-context.ts @@ -1,5 +1,37 @@ import React from 'react' +export const ScalePropKeys = [ + 'width', + 'height', + 'padding', + 'margin', + 'w', + 'h', + 'paddingLeft', + 'paddingRight', + 'paddingTop', + 'paddingBottom', + 'pl', + 'pr', + 'pt', + 'pb', + 'marginLeft', + 'marginRight', + 'marginTop', + 'marginBottom', + 'ml', + 'mr', + 'mt', + 'mb', + 'px', + 'py', + 'mx', + 'my', + 'font', + 'unit', + 'scale', +] + export type ScaleProps = { width?: string | number height?: string | number @@ -62,9 +94,12 @@ export type GetScalePropsFunction = ( key: keyof ScaleProps | Array, ) => ScaleProps[keyof ScaleProps] +export type GetAllScalePropsFunction = () => ScaleProps + export interface ScaleConfig { SCALES: DynamicScales getScaleProps: GetScalePropsFunction + getAllScaleProps: GetAllScalePropsFunction unit: string } @@ -74,6 +109,7 @@ const defaultDynamicLayoutPipe: DynamicLayoutPipe = scale1x => { const defaultContext: ScaleConfig = { getScaleProps: () => undefined, + getAllScaleProps: () => ({}), SCALES: { pl: defaultDynamicLayoutPipe, pr: defaultDynamicLayoutPipe, diff --git a/components/use-scale/utils.ts b/components/use-scale/utils.ts index 2b0636ebd..ef5f8ba55 100644 --- a/components/use-scale/utils.ts +++ b/components/use-scale/utils.ts @@ -1,46 +1,39 @@ -import { ScaleProps } from './scale-context' +import { + GetAllScalePropsFunction, + GetScalePropsFunction, + ScaleProps, + ScalePropKeys, +} from './scale-context' -export type ScalePropsAndInvalid = keyof ScaleProps | 'size' +export const generateGetScaleProps =

( + props: P & ScaleProps, +): GetScalePropsFunction => { + const getScaleProps: GetScalePropsFunction = keyOrKeys => { + if (!Array.isArray(keyOrKeys)) return props[keyOrKeys as keyof ScaleProps] + let value = undefined + for (const key of keyOrKeys) { + const currentValue = props[key] + if (typeof currentValue !== 'undefined') { + value = currentValue + } + } + return value + } + return getScaleProps +} -export const ScalePropKeys: Array = [ - 'paddingLeft', - 'pl', - 'paddingRight', - 'pr', - 'paddingTop', - 'pt', - 'paddingBottom', - 'pb', - 'marginTop', - 'mt', - 'marginRight', - 'mr', - 'marginBottom', - 'mb', - 'marginLeft', - 'ml', - 'px', - 'py', - 'mx', - 'my', - 'width', - 'height', - 'font', - 'unit', - 'scale', - 'size', -] - -// export const withPureProps = >( -// props: T, -// ): Omit => { -// if (!props) return {} as Omit -// const keys = Object.keys(props).filter(key => key !== '') -// const nextProps: any = {} -// for (const key of keys) { -// if (!(ScalePropKeys as string[]).includes(key)) { -// nextProps[key] = props[key] -// } -// } -// return nextProps -// } +export const generateGetAllScaleProps =

( + props: P & ScaleProps, +): GetAllScalePropsFunction => { + const getAllScaleProps: GetAllScalePropsFunction = () => { + let scaleProps: ScaleProps = {} + for (const key of ScalePropKeys) { + const value = props[key as keyof ScaleProps] + if (typeof value !== 'undefined') { + scaleProps[key as keyof ScaleProps] = value as any + } + } + return scaleProps + } + return getAllScaleProps +} diff --git a/components/use-scale/with-scale.tsx b/components/use-scale/with-scale.tsx index fc4ad44d5..0d7ad21d2 100644 --- a/components/use-scale/with-scale.tsx +++ b/components/use-scale/with-scale.tsx @@ -1,13 +1,8 @@ import React, { forwardRef } from 'react' -import { - DynamicLayoutPipe, - GetScalePropsFunction, - ScaleConfig, - ScaleContext, - ScaleProps, -} from './scale-context' +import { DynamicLayoutPipe, ScaleConfig, ScaleContext, ScaleProps } from './scale-context' import useTheme from '../use-theme' import { isCSSNumberValue } from '../utils/collections' +import { generateGetAllScaleProps, generateGetScaleProps } from './utils' const reduceScaleCoefficient = (scale: number) => { if (scale === 1) return scale @@ -70,20 +65,9 @@ const withScale = ( const customFactor = factor * Number(attrValue) return `calc(${customFactor} * ${unit})` } - const getScaleProps: GetScalePropsFunction = keyOrKeys => { - if (!Array.isArray(keyOrKeys)) return props[keyOrKeys as keyof ScaleProps] - let value = undefined - for (const key of keyOrKeys) { - const currentValue = props[key] - if (typeof currentValue !== 'undefined') { - value = currentValue - } - } - return value - } const value: ScaleConfig = { - unit, + unit: unit, SCALES: { pt: makeScaleHandler(paddingTop ?? pt ?? py ?? padding), pr: makeScaleHandler(paddingRight ?? pr ?? px ?? padding), @@ -101,7 +85,8 @@ const withScale = ( height: makeScaleHandler(height ?? h), font: makeScaleHandler(font), }, - getScaleProps, + getScaleProps: generateGetScaleProps(props), + getAllScaleProps: generateGetAllScaleProps(props), } return ( From ab5c1b8d73e0f160884917981b4f0af8b31c2ab5 Mon Sep 17 00:00:00 2001 From: unix Date: Sat, 12 Feb 2022 20:27:19 +0800 Subject: [PATCH 2/2] fix(password): pass all scale props for internally wrapped components --- components/index.ts | 2 +- components/input/__tests__/password.test.tsx | 11 ++++++++++- components/input/password.tsx | 5 +++-- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/components/index.ts b/components/index.ts index 9df6d1f9e..71452012f 100644 --- a/components/index.ts +++ b/components/index.ts @@ -200,8 +200,8 @@ export { default as useClasses } from './use-classes' export { default as useScale } from './use-scale' export { withScale, ScalePropKeys, ScaleContext } from './use-scale' export type { - ScalePropsAndInvalid, ScaleProps, ScaleConfig, GetScalePropsFunction, + GetAllScalePropsFunction, } from './use-scale' diff --git a/components/input/__tests__/password.test.tsx b/components/input/__tests__/password.test.tsx index 896d1ba66..c5cf15336 100644 --- a/components/input/__tests__/password.test.tsx +++ b/components/input/__tests__/password.test.tsx @@ -1,5 +1,5 @@ import React from 'react' -import { mount } from 'enzyme' +import { mount, shallow } from 'enzyme' import { Input } from 'components' import { nativeEvent } from 'tests/utils' @@ -23,4 +23,13 @@ describe('InputPassword', () => { const wrapper = mount() expect(wrapper.find('.input-icon').length).toBe(0) }) + + it('should be pass all native scale props', () => { + const width = 'calc(100% - 10px)' + const height = Math.random().toString(16).slice(-8) + const wrapper = shallow() + const html = wrapper.html() + expect(html).toContain(width) + expect(html).toContain(height) + }) }) diff --git a/components/input/password.tsx b/components/input/password.tsx index 7044d4801..381bd0a54 100644 --- a/components/input/password.tsx +++ b/components/input/password.tsx @@ -2,7 +2,7 @@ import React, { useImperativeHandle, useMemo, useRef, useState } from 'react' import { Props, defaultProps } from './input-props' import PasswordIcon from './password-icon' import Input from './input' -import { withScale } from '../use-scale' +import { useScale, withScale } from '../use-scale' interface PasswordProps extends Props { hideToggle?: boolean @@ -28,6 +28,7 @@ const InputPasswordComponent = React.forwardRef< }: React.PropsWithChildren & typeof defaultProps, ref: React.Ref, ) => { + const { getAllScaleProps } = useScale() const inputRef = useRef(null) const [visible, setVisible] = useState(false) useImperativeHandle(ref, () => inputRef.current) @@ -56,7 +57,7 @@ const InputPasswordComponent = React.forwardRef< }, [hideToggle, visible]) return ( - + {children} )