Skip to content

Commit

Permalink
Merge pull request #215 from sima-land/213-enhance-reducers
Browse files Browse the repository at this point in the history
Шаг 2 #213 ProductCard: добавить возможность определять фильтры содержимого
  • Loading branch information
krutoo authored Jan 10, 2024
2 parents 18ca727 + d710ae8 commit 8e2a5aa
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { ProductInfo, Parts } from '@sima-land/moleculas/common/components/produ
import { Badge, BadgeProps } from '@sima-land/moleculas/common/components/badge';
import { Stepper } from '@sima-land/ui-nucleons/stepper';
import FavSVG from '@sima-land/ui-quarks/icons/24x24/Stroked/Favorite';
import ComparisonAddSVG from '@sima-land/ui-quarks/icons/24x24/Stroked/ComparisonAdd';
import cupSrc from './cup.jpg';

export default {
Expand All @@ -28,7 +29,14 @@ export function Primary() {

return (
<div style={{ width: '200px', margin: '32px' }}>
<ProductCard reduceBaseInfo={elem => reduceBaseInfo(elem, { hideImageButtons: false })}>
<ProductCard
// Определение контента который будет выведен без наведения (по умолчанию фильтруется)
reduceBaseInfo={elem =>
reduceBaseInfo(elem, {
hideImageButtons: btn => (btn as any)?.props?.icon === FavSVG,
})
}
>
<ProductInfo>
{/* Изображение */}
<Parts.Image src={cupSrc} href='https://www.sima-land.ru'>
Expand All @@ -38,6 +46,12 @@ export function Primary() {
hint='Добавить в избранное'
hintDirection='right'
/>
<Parts.ImageButton
icon={ComparisonAddSVG}
position={{ x: 'right', y: 'top' }}
hint='Добавить в сравнение'
hintDirection='left'
/>
</Parts.Image>

{/* Шильдики */}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Children } from 'react';
import { Children, isValidElement } from 'react';
import { fireEvent, render } from '@testing-library/react';
import { ProductCard, reduceBaseInfo, reduceHoverInfo } from '../product-card';
import { ProductInfo, Parts } from '../../../../common/components/product-info';
Expand Down Expand Up @@ -128,6 +128,27 @@ describe('reduceBaseInfo', () => {

expect(Children.toArray(result.props.children)).toEqual([]);
});

it('should handle function as "hideImageButtons" option', () => {
const jsx = (
<ProductInfo>
<Parts.Image>
some string
<span>excluded</span>
<article>survivor</article>
</Parts.Image>
</ProductInfo>
);

const result = reduceBaseInfo(jsx, {
hideImageButtons: value => isValidElement(value) && value.type === 'article',
});

const { container } = render(result);

expect(container.querySelectorAll('article')).toHaveLength(1);
expect(container.textContent).toBe('survivor');
});
});

describe('reduceHoverInfo', () => {
Expand Down
19 changes: 9 additions & 10 deletions src/desktop/components/product-card/product-card.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Children, forwardRef, isValidElement, cloneElement, useState } from 'react';
import { ProductCardChildren, ProductCardProps } from './types';
import { ProductCardChildren, ProductCardProps, ReduceBaseInfoOptions } from './types';
import { Parts } from '../../../common/components/product-info';
import { Plate, PlateProps } from '@sima-land/ui-nucleons/plate';
import { useLayer } from '@sima-land/ui-nucleons/helpers/layer';
Expand Down Expand Up @@ -62,23 +62,22 @@ export const HoverCard = forwardRef<HTMLDivElement | null, PlateProps>((props, r
*/
export function reduceBaseInfo(
element: ProductCardChildren,
{
hideImageButtons = true,
hideFooter = true,
}: {
hideImageButtons?: boolean;
hideFooter?: boolean;
} = {},
{ hideImageButtons = true, hideFooter = true }: ReduceBaseInfoOptions = {},
) {
return cloneElement(element, {
children: Children.map(element.props.children, child => {
let result;

if (isValidElement(child)) {
switch (true) {
// игнорируем кнопки-иконки на изображении
// игнорируем или фильтруем кнопки-иконки на изображении
case Boolean(child.type === Parts.Image && hideImageButtons):
result = cloneElement<any>(child, { children: undefined });
result = cloneElement<any>(child, {
children:
typeof hideImageButtons === 'function'
? Children.toArray(child.props.children).filter(hideImageButtons)
: undefined,
});
break;

// игнорируем футер
Expand Down
9 changes: 9 additions & 0 deletions src/desktop/components/product-card/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,12 @@ export interface ProductCardProps extends HTMLAttributes<HTMLDivElement> {
/** Получив содержимое должен вернуть то что будет выведено во всплывающей карточке. */
reduceHoverInfo?: (children: ProductCardChildren) => ReactNode;
}

/** Опции фильтрации содержимого карточки без наведения. */
export interface ReduceBaseInfoOptions {
/** Надо ли скрыть кнопки на картинке. При передаче функции она будет применена для каждого дочернего элемента внутри картинки как фильтр. */
hideImageButtons?: boolean | ((element: ReactNode) => boolean);

/** Надо ли скрыть футер. */
hideFooter?: boolean;
}

0 comments on commit 8e2a5aa

Please sign in to comment.