From 4ad610ea796de99ce8afc432a5de1ecddc914e48 Mon Sep 17 00:00:00 2001 From: EldarMuhamethanov <61377022+EldarMuhamethanov@users.noreply.github.com> Date: Fri, 19 Jul 2024 19:43:35 +0300 Subject: [PATCH] feat(ImageBase): add prop keepAspectRatio to ImageBase (#7187) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Добавил флаг keepAspectRatio, который задает необходимый класснейм для картинки --- .../components/ImageBase/ImageBase.module.css | 5 +++ .../components/ImageBase/ImageBase.test.tsx | 6 +++ .../src/components/ImageBase/ImageBase.tsx | 44 ++++++++++++++++--- 3 files changed, 49 insertions(+), 6 deletions(-) diff --git a/packages/vkui/src/components/ImageBase/ImageBase.module.css b/packages/vkui/src/components/ImageBase/ImageBase.module.css index e3f80ece2b..fa7095cb7d 100644 --- a/packages/vkui/src/components/ImageBase/ImageBase.module.css +++ b/packages/vkui/src/components/ImageBase/ImageBase.module.css @@ -43,6 +43,11 @@ visibility: hidden; } +.ImageBase__img--keepRatio { + inline-size: auto; + block-size: auto; +} + .ImageBase__img--objectFit-contain { object-fit: contain; } diff --git a/packages/vkui/src/components/ImageBase/ImageBase.test.tsx b/packages/vkui/src/components/ImageBase/ImageBase.test.tsx index e27c647e25..965d22af28 100644 --- a/packages/vkui/src/components/ImageBase/ImageBase.test.tsx +++ b/packages/vkui/src/components/ImageBase/ImageBase.test.tsx @@ -156,6 +156,12 @@ describe(ImageBase, () => { // make sure we ignore img.onLoad that is fired for some reason after we manually handled the complete state. expect(onLoadMock).toHaveBeenCalledTimes(1); }); + + it('should have className with keepRatio', () => { + render(); + + expect(getImageBaseImgEl()).toHaveClass(styles['ImageBase__img--keepRatio']); + }); }); describe(ImageBase.Badge, () => { diff --git a/packages/vkui/src/components/ImageBase/ImageBase.tsx b/packages/vkui/src/components/ImageBase/ImageBase.tsx index 1f81e45a60..3cabeb4d72 100644 --- a/packages/vkui/src/components/ImageBase/ImageBase.tsx +++ b/packages/vkui/src/components/ImageBase/ImageBase.tsx @@ -49,11 +49,11 @@ export interface ImageBaseProps /** * Ширина изображения */ - widthSize?: number; + widthSize?: number | string; /** * Высота изображения */ - heightSize?: number; + heightSize?: number | string; /** * Отключает обводку. */ @@ -82,6 +82,11 @@ export interface ImageBaseProps * Подробнее можно почитать в [документации](https://developer.mozilla.org/ru/docs/Web/CSS/object-fit) */ objectFit?: React.CSSProperties['objectFit']; + /** + * Флаг для сохранения пропорций картинки. + * Для корректной работы необходимо задать размеры хотя бы одной стороны картинки + */ + keepAspectRatio?: boolean; } const getObjectFitClassName = (objectFit: React.CSSProperties['objectFit']) => { @@ -98,6 +103,20 @@ const getObjectFitClassName = (objectFit: React.CSSProperties['objectFit']) => { return undefined; }; +const parsePx = (value: string): number | undefined => { + if (value.endsWith('px')) { + return parseInt(value); + } + return undefined; +}; + +const sizeToNumber = (size: number | string | undefined): number | undefined => { + if (typeof size === 'string') { + return parsePx(size); + } + return size; +}; + /** * @see https://vkcom.github.io/VKUI/#/ImageBase */ @@ -129,12 +148,13 @@ export const ImageBase: React.FC & { onError, withTransparentBackground, objectFit = 'cover', + keepAspectRatio = false, ...restProps }: ImageBaseProps) => { - const size = sizeProp ?? minOr([widthSize, heightSize], defaultSize); + const size = sizeProp ?? minOr([sizeToNumber(widthSize), sizeToNumber(heightSize)], defaultSize); - const width = widthSize ?? size; - const height = heightSize ?? size; + const width = widthSize ?? (keepAspectRatio ? undefined : size); + const height = heightSize ?? (keepAspectRatio ? undefined : size); const [loaded, setLoaded] = React.useState(false); const [failed, setFailed] = React.useState(false); @@ -199,11 +219,23 @@ export const ImageBase: React.FC & {