"use client"; import { type HTMLAttributes, type ReactElement, type Ref } from "react"; import { type ComponentWithRippleProps } from "../interaction/types.js"; import { useElementInteraction } from "../interaction/useElementInteraction.js"; import { useHigherContrastChildren } from "../interaction/useHigherContrastChildren.js"; import { ListItemChildren } from "./ListItemChildren.js"; import { getListItemHeight } from "./getListItemHeight.js"; import { type BaseListItemClassNameOptions, listItem, } from "./listItemStyles.js"; import { type ListItemChildrenProps } from "./types.js"; /** * @since 6.0.0 Renamed `threeLines` to `multiline` since it can * support more than three lines of text. * @since 6.3.1 Extends the BaseListItemClassNameOptions */ export interface ListItemProps extends HTMLAttributes, ListItemChildrenProps, BaseListItemClassNameOptions, ComponentWithRippleProps { ref?: Ref; /** * @defaultValue `"button"` */ role?: HTMLAttributes["role"]; /** * @defaultValue `disabled ? -1 : 0` */ tabIndex?: number; /** * Set this to `false` if the list item should not gain the interaction * states: hover, focus, press, etc. This is kind of like being disabled * without the disabled styles being applied. * * @defaultValue `role === "presentation"` */ presentational?: boolean; } /** * **Client Component** * * The `ListItem` is used to create a clickable/focusable button within a * `List` and removes the normal `
  • ` styles. * * @example Simple Example * ```tsx * import { List } from "@react-md/core/list/List"; * import { ListItem } from "@react-md/core/list/ListItem"; * import type { ReactElement } from "react"; * * function Example(): ReactElement { * return ( * * { * // do something * }} * > * Item 1 * * { * // do something * }} * secondaryText={Some additional content.} * > * Item 2 * * * ); * ); * } * ``` * * @example Applying Addons Example * ```tsx * import { List } from "@react-md/core/list/List"; * import { ListItem } from "@react-md/core/list/ListItem"; * import FavoriteIcon from "@react-md/material-icons/FavoriteIcon"; * import type { ReactElement } from "react"; * * function Example(): ReactElement { * return ( * * }> * Item 1 * * }> * Item 2 * * } * rightAddon={} * rightAddonType="media" * > * Item 3 * * * ); * ); * } * ``` * * @see {@link https://react-md.dev/components/list | List Demos} */ export function ListItem(props: ListItemProps): ReactElement { const { ref, className, textProps, textClassName, secondaryTextClassName, primaryText, secondaryText, secondaryTextProps, disableTextChildren = false, height: propHeight, leftAddon, leftAddonType, leftAddonPosition, leftAddonClassName, leftAddonForceWrap, rightAddon, rightAddonType, rightAddonPosition, rightAddonClassName, rightAddonForceWrap, disableLeftAddonSpacing, disableLeftAddonCenteredMedia, disableRightAddonCenteredMedia, multiline = false, disabled = false, disableRipple, disabledOpacity = false, role = "button", onBlur, onClick, onKeyDown, onKeyUp, onMouseDown, onMouseUp, onMouseLeave, onDragStart, onTouchStart, onTouchEnd, onTouchMove, tabIndex: propTabIndex, children: propChildren, presentational = role === "presentation", ...remaining } = props; let tabIndex = propTabIndex; if (!presentational && tabIndex === undefined) { tabIndex = disabled ? -1 : 0; } const { pressedClassName, ripples, handlers } = useElementInteraction({ mode: disableRipple ? "none" : undefined, onBlur, onClick, onKeyDown, onKeyUp, onMouseDown, onMouseUp, onMouseLeave, onDragStart, onTouchStart, onTouchEnd, onTouchMove, disabled: disabled || presentational, }); const children = useHigherContrastChildren( propChildren, !disableTextChildren ); const height = getListItemHeight({ height: propHeight, leftAddon, leftAddonType, rightAddon, rightAddonType, secondaryText, }); return (
  • {children} {ripples}
  • ); }