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 & {