UNPKG

saagie-ui

Version:

Saagie UI from Saagie Design System

226 lines (208 loc) 5.87 kB
import React, { useState } from 'react'; import PropTypes from 'prop-types'; import classnames from 'classnames'; import { getColumnClasses } from './helpers'; import { modifierCSS } from '../../../helpers'; const propTypes = { children: PropTypes.oneOfType([ PropTypes.element, PropTypes.arrayOf(PropTypes.element), ]), className: PropTypes.string, defaultClassName: PropTypes.oneOfType([PropTypes.string, PropTypes.arrayOf(PropTypes.string)]), headerLabels: PropTypes.arrayOf(PropTypes.node), preHeader: PropTypes.arrayOf( PropTypes.shape({ label: PropTypes.string, size: PropTypes.number }) ), isBordered: PropTypes.bool, innerBorder: PropTypes.bool, isHover: PropTypes.bool, isLight: PropTypes.bool, levelBreakpoint: PropTypes.oneOf(['none', 'xxs', 'xs', 'sm', 'md', 'lg', 'xl', 'xxl']), sortIndexes: PropTypes.arrayOf(PropTypes.number), onSort: PropTypes.func, /** * The component used for the root node. * Either a string to use a DOM element or a component. */ tag: PropTypes.elementType, }; const defaultProps = { children: null, className: '', defaultClassName: 'sui-o-datalist', headerLabels: null, preHeader: [], isBordered: false, innerBorder: false, isHover: true, isLight: false, levelBreakpoint: 'md', sortIndexes: null, onSort: () => {}, tag: 'div', }; export const Datalist = (props) => { const { children, className, defaultClassName, headerLabels, preHeader, isBordered, innerBorder, isHover, isLight, levelBreakpoint, sortIndexes, onSort, tag: Tag, ...attributes } = props; const [activeSortByIndex, setActiveSortByIndex] = useState({}); const classes = classnames( defaultClassName, className, modifierCSS(levelBreakpoint, 'level-breakpoint'), { 'as--sorted': sortIndexes, 'as--inner-border': innerBorder, 'as--bordered': isBordered, 'as--light': isLight, 'as--hover': isHover, }, ); const rows = (React.Children.toArray(children) || []) .map((row) => React.Children.toArray(row.props.children)); const firstRow = rows[0]; const headerClasses = firstRow ? firstRow.map((col) => getColumnClasses(col.props)) : ''; const handleSort = (type, index) => { setActiveSortByIndex({ [index]: type, }); onSort(type, index); }; const renderHeader = () => { if (!headerLabels) { return ''; } const preHeaders = () => { if (preHeader.length === 0) { return null; } if (rows.length === 0) { return null; } let sizeIndex = 0; return preHeader.map((elem, i) => { sizeIndex += elem.size || 1; return ( // eslint-disable-next-line react/no-array-index-key <div key={i} style={{ flexGrow: elem.size && elem.size.toString(), borderBottom: headerLabels[sizeIndex - 1] === '' ? 'none' : '0.0625rem solid #d9dbe3' }} className={`${headerClasses[i]} sui-o-datalist__col`}> {elem.label} </div> ); } ); }; const headers = () => { if (rows.length === 0) { return headerLabels.map((x, i) => ( // eslint-disable-next-line react/no-array-index-key <div key={i} className="sui-o-datalist__col"> {x} </div> )); } return firstRow.map((x, i) => { const canSort = sortIndexes && sortIndexes.indexOf(i) > -1; return ( <div // eslint-disable-next-line react/no-array-index-key key={i} className={classnames( headerClasses[i], { 'sui-o-datalist__col--sortable': canSort, }, )} > {headerLabels[i]} {canSort && ( <div className="sui-o-datalist__col__sort"> <button type="button" aria-label="Sort ASC" className={classnames( 'sui-o-datalist__col__sort-up', { 'as--active': activeSortByIndex[i] === 'ASC', }, )} onClick={() => handleSort('ASC', i)} /> <button type="button" aria-label="Sort DESC" className={classnames( 'sui-o-datalist__col__sort-down', { 'as--active': activeSortByIndex[i] === 'DESC', }, )} onClick={() => handleSort('DESC', i)} /> </div> )} </div> ); }); }; return ( <div> {preHeader.length ? ( <div className="sui-o-datalist__preheader"> {preHeaders()} </div> ) : ''} <div className="sui-o-datalist__header"> {headers()} </div> </div> ); }; const renderRows = () => { if (!headerLabels) { return children; } return React.Children.map(children, (row) => { if (!row.props || !row.props.children) { return ''; } const columns = React.Children .map(row.props.children, (col, index = 1) => ({ ...col, props: { ...col.props, label: col.props.label === null ? headerLabels[index] : col.props.label, }, })); return { ...row, props: { ...row.props, children: columns, }, }; }); }; return ( <Tag {...attributes} className={classes}> {renderHeader()} {renderRows()} </Tag> ); }; Datalist.propTypes = propTypes; Datalist.defaultProps = defaultProps;