UNPKG

optimizely-oui

Version:

Optimizely's Component Library.

145 lines (130 loc) 4.49 kB
import React from "react"; import PropTypes from "prop-types"; import classNames from "classnames"; class Item extends React.Component { constructor(props) { super(props); this._handleOnKeyDown = this._handleOnKeyDown.bind(this); } ref = React.createRef(); componentDidUpdate() { if (this.props.hasFauxFocus) { this.ref.current.scrollIntoView({ behavior: "smooth", block: "center", }); } } _handleOnKeyDown(event) { if (event && event.keyCode === 32 && event.target === this._itemWithOnClick) { // Space key was pressed on the item, not a child of the item. // Run the `onClick` and prevent the page from scrolling. event.preventDefault(); this.props.onClick(); } } render() { let item; const { children, className, gutters, hasFauxFocus, href, hrefTarget, hrefTitle, isDisabled, onClick, onMouseDown, testSection, ...props } = this.props; const commonClasses = classNames({ "oui-block-list__item": true, "oui-block-list__item--has-focus": hasFauxFocus, "hard--sides": gutters === "tight", }); if (isDisabled) { item = ( <div className={`${commonClasses} pointer-events--none background--faint muted`}> {children} </div> ); } else if (onClick) { // The element is rendered as a `div` instead of a `button` because the // user may want to pass in a `button` within `children`. // `tabIndex`, `role`, and `onKeyDown` are provided to make the `div` // behave like a button: https://mzl.la/1mRMvQj item = ( <div className={`${commonClasses} link oui-block-list__link`} onClick={onClick} onKeyDown={this._handleOnKeyDown} tabIndex="0" role="button" ref={el => { this._itemWithOnClick = el; }} > {children} </div> ); } else if (href) { item = ( <a href={href} className={`${commonClasses} oui-block-list__link display--block`} target={hrefTarget} title={hrefTitle} rel={hrefTarget === "_blank" && "noopener noreferrer"} > {children} </a> ); } else { item = ( <div className={commonClasses} onMouseDown={onMouseDown} {...(testSection && { "data-test-section": testSection + "-item" })} > {children} </div> ); } return ( <li ref={this.ref} style={{ wordBreak: "break-word" }} className={className} data-test-section={testSection} {...props}> {item} </li> ); } } Item.propTypes = { /** String or JSX that appears within the component */ children: PropTypes.node.isRequired, /** CSS class names. */ className: PropTypes.string, /** Determines level of padding of item */ gutters: PropTypes.oneOf(["loose", "tight"]), /** Boolean to set faux focus of a list item */ hasFauxFocus: PropTypes.bool, /** URL to navigate to when clicking on the item */ href: PropTypes.string, /** Target that the link, if provided, should open in */ hrefTarget: PropTypes.oneOf(["_self", "_blank"]), /** Sets the `title` attribute on an `href` */ hrefTitle: PropTypes.string, /** Disable the item */ isDisabled: PropTypes.bool, /** Function that is run when clicking on the item */ onClick: PropTypes.func, /** Function that is run when mouse-down event is fired on the item */ onMouseDown: PropTypes.func, /** Hook for automated JavaScript tests */ testSection: PropTypes.string, }; Item.defaultProps = { gutters: "loose", }; Item.displayName = "BlockList.Item"; export default Item;