import { camelCase } from "lodash-es"; import cx from "classnames"; import { ComponentDefaultTestId, getTestId } from "../../tests/test-ids-utils"; import { getStyle } from "../../helpers/typesciptCssModulesHelper"; import React, { forwardRef, useCallback, useEffect, useMemo, useRef, useState } from "react"; import { backwardCompatibilityForProperties } from "../../helpers/backwardCompatibilityForProperties"; import Text from "../Text/Text"; import Leg from "./Leg"; import { LabelColor, LabelKind } from "./LabelConstants"; import { VibeComponent, VibeComponentProps, withStaticProps } from "../../types"; import useClickableProps from "../../hooks/useClickableProps/useClickableProps"; import useMergeRef from "../../hooks/useMergeRef"; import styles from "./Label.module.scss"; import LabelCelebrationAnimation from "./LabelCelebrationAnimation"; import { mapSizesToTextSize, Sizes } from "./Label.types"; export interface LabelProps extends VibeComponentProps { /** * @deprecated - use className instead */ wrapperClassName?: string; /** * Class name for an inner text wrapper */ labelClassName?: string; kind?: LabelKind; color?: LabelColor; text?: string; isAnimationDisabled?: boolean; isLegIncluded?: boolean; onClick?: (event: React.MouseEvent) => void; celebrationAnimation?: boolean; size?: Sizes; } const Label: VibeComponent & { colors?: typeof LabelColor; kinds?: typeof LabelKind; } = forwardRef( ( { className, wrapperClassName, labelClassName, kind = LabelKind.FILL, color = LabelColor.PRIMARY, text = "", isAnimationDisabled = false, isLegIncluded = false, id, "data-testid": dataTestId, onClick, celebrationAnimation, size = "medium" }, ref ) => { const labelRef = useRef(null); const mergedRef = useMergeRef(ref, labelRef); const [isCelebrationAnimation, setIsCelebrationAnimation] = useState(celebrationAnimation); const overrideClassName = backwardCompatibilityForProperties([className, wrapperClassName]) as string; const isClickable = Boolean(onClick); const classNames = useMemo( () => cx( styles.label, getStyle(styles, camelCase("kind" + "-" + kind)), getStyle(styles, camelCase("color" + "-" + color)), { // When celebrationAnimation is active it wins over the default animation [styles.withAnimation]: !isAnimationDisabled && !isCelebrationAnimation, [styles.withLeg]: isLegIncluded, [styles.clickable]: isClickable, [styles.small]: size === "small" }, labelClassName ), [kind, color, isAnimationDisabled, isLegIncluded, labelClassName, isCelebrationAnimation, isClickable, size] ); const onClickCallback = useCallback( (event: React.MouseEvent) => { if (onClick) { event.preventDefault(); onClick(event); } }, [onClick] ); const clickableProps = useClickableProps( { onClick: onClickCallback, id, ariaHidden: false, ariaHasPopup: false, ariaExpanded: false }, labelRef ); useEffect(() => { setIsCelebrationAnimation(celebrationAnimation); }, [celebrationAnimation]); const label = useMemo(() => { return ( {text} {isLegIncluded ? : null} ); }, [ isClickable, clickableProps, overrideClassName, dataTestId, id, mergedRef, classNames, isCelebrationAnimation, text, isLegIncluded, size ]); // Celebration animation is applied only for line kind if (isCelebrationAnimation && kind === "line") { return ( setIsCelebrationAnimation(false)}> {label} ); } return label; } ); export default withStaticProps(Label, { colors: LabelColor, kinds: LabelKind });