import { Button } from '@cloud-ru/ds-button'; import { InfoOutlineSVG } from '@cloud-ru/ds-icons/interface/product'; import { CollapseVerticalSVG, ExpandVerticalSVG, StarFilledSVG, StarSVG } from '@cloud-ru/ds-icons/interface/system'; import { Tooltip, TooltipProps, TRIGGER } from '@cloud-ru/ds-tooltip'; import { preventEventDefault, preventEventDefaultAndPropagation } from '@cloud-ru/ds-utils'; import cn from 'classnames'; import { MouseEvent, ReactElement, RefObject, useCallback, useRef, useState } from 'react'; import { TOOLTIP_HOVER_DELAY_OPEN_MS, VISIBILITY_STRATEGY } from '../../constants'; import { cardPredefinedLocale } from '../../locale'; import { FavoriteProps, VisibilityStrategy } from '../../types'; import styles from './styles.module.scss'; type TooltipType = 'info' | 'favorite' | 'expandable'; export type CardActionsSurfaceProps = { /** * Формат отображения действий: всегда или при наведении и фокусе * @default 'hover' */ actionsVisibility?: VisibilityStrategy; /** Кнопка info с тултипом */ tooltip?: Omit & { buttonRef?: RefObject; 'data-test-id'?: string; }; /** Кнопка «Избранное» */ favorite?: FavoriteProps & { buttonRef?: RefObject; 'data-test-id'?: string; }; /** Кнопка раскрытия */ expandable?: { value: boolean; onClick(): void; buttonRef?: RefObject; }; /** CSS-класс корневого элемента */ className?: string; /** Callback, вызываемый при открытии тултипа */ onTooltipOpenChange?(isOpen: boolean): void; }; export function CardActionsSurface({ actionsVisibility = VISIBILITY_STRATEGY.hover, tooltip, favorite, expandable, className, onTooltipOpenChange, }: CardActionsSurfaceProps): ReactElement | null { const { t } = cardPredefinedLocale.useTranslations(); const [visibleTooltip, setVisibleTooltip] = useState(undefined); const rootRef = useRef(null); const tooltipTrigger = tooltip?.trigger ?? (actionsVisibility === VISIBILITY_STRATEGY.always ? TRIGGER.Click : TRIGGER.HoverAndFocusVisible); const getHandleTooltipOpenChange = useCallback( (tooltipType: TooltipType) => (isOpen: boolean) => { // Отложенное открытие floating-ui срабатывает и после ухода курсора с панели — его пропускаем. if (isOpen && tooltipTrigger !== TRIGGER.Click && !rootRef.current?.matches(':hover, :focus-within')) { return; } setVisibleTooltip(isOpen ? tooltipType : undefined); onTooltipOpenChange?.(isOpen); }, [onTooltipOpenChange, tooltipTrigger], ); if (!tooltip && !favorite && !expandable) { return null; } const handleExpandButtonClick = (e: MouseEvent) => { preventEventDefaultAndPropagation(e); expandable?.onClick(); }; const handleFavoriteClick = (e: MouseEvent) => { preventEventDefaultAndPropagation(e); favorite?.onChange?.(!favorite.checked); }; // safePolygon держит подсказку открытой и над соседней карточкой — закрываем при уходе с панели. const handleMouseLeave = () => { if (!visibleTooltip || tooltipTrigger === TRIGGER.Click) { return; } setVisibleTooltip(undefined); onTooltipOpenChange?.(false); }; const { buttonRef: tooltipButtonRef, 'data-test-id': tooltipTestId, ...tooltipProps } = tooltip ?? {}; return ( // eslint-disable-next-line jsx-a11y/no-static-element-interactions
{tooltip && ( {/* Кнопки действий — `as='span'` внутри интерактивной карточки (вложенный `
); }