import React, { ReactElement, useState, FormEvent, CSSProperties } from "react"; import classnames from "classnames"; import { Box } from "../Box"; import { CheckboxProps } from "../Checkbox"; import { FilterDropdown } from "./FilterDropdown"; import TableContext, { SORT_DIRECTION } from "./TableContext"; import { bem } from "../../utilities/bem"; import { Icon, ICON_TYPE } from "../Icon"; import isUndefined from "../../utilities/isUndefined"; const cn = "TableHeaderCell"; // Typescript can't actually enforce children having certain props, // so this interface doesn't work. TODO: Handle this some other way interface FilterProps extends CheckboxProps { label: string; } export interface TableHeaderCellProps extends React.HTMLProps { /** * This will set the width for the entire column. Any valid CSS value for the `width` * property is acceptable (e.g. "100px", "20%", etc.) */ columnWidth?: string; /** * This will set a minWidth for the entire column. Any valid CSS value for the `min-width` * property is acceptable (e.g. "100px", "20%", etc.) */ minColumnWidth?: string; /** * If true, this changes the filter icon green to indicate a filter within is applied */ filterApplied?: boolean; /** * Hides the search input and "Select All"/"Clear links in the filter dropdown" */ hideFilterSearch?: boolean; /** * Required with the `sortable` prop to enable sorting */ id?: string; /** * Callback when the "Clear" link is clicked in the filter dropdown */ onClearFilters?: () => void; /** * Callback when input in the filter dropdown is changed */ onSearchInputChange?: (value: string) => void; /** * Callback when the "Select All" link is clicked in the filter dropdown */ onSelectAllFilters?: () => void; /** * Removes top and bottom padding within the HeaderCell */ removeVerticalPadding?: boolean; /** * Value provided to the input in the filter dropdown */ searchInputValue?: string; /** * Shrinks column to minimum width without breaking words. */ shrinkToContent?: boolean; /** * Enables sorting on the column. Must also include an `id` prop to work properly. */ sortable?: boolean; /** * Enables column filtering */ filterOptions?: ReactElement[]; /** * Specify a custom filter control, e.g. DatePicker */ filterControl?: ReactElement; } const TableHeaderCell = ({ children, className, id, shrinkToContent = false, sortable = true, filterOptions: filterOptionsProp, onSelectAllFilters, onClearFilters, hideFilterSearch = false, filterApplied = false, searchInputValue = "", onSearchInputChange, columnWidth, minColumnWidth, removeVerticalPadding = false, filterControl, style, ...rest }: TableHeaderCellProps) => { const [filterDropDownOpen, setFilterDropdownOpen] = useState(false); const filterOptions = filterOptionsProp; return ( {({ handleSort, sortColumnId, sortDirection, renderInModal }) => { const classes = classnames( bem(cn), shrinkToContent && bem(cn, { m: "shrinkToContent" }), removeVerticalPadding && bem(cn, { m: "removeVerticalPadding" }), className, ); const handleSortClick = () => { if (sortable && id && handleSort) { handleSort(id); } }; const handleFilterInputChange = (e: FormEvent) => { const { value } = e.target as HTMLInputElement; if (!isUndefined(onSearchInputChange)) { onSearchInputChange(value); } }; const handleFilterSelectAll = () => { if (!isUndefined(onSelectAllFilters)) { onSelectAllFilters(); } }; const handleFilterClear = () => { if (!isUndefined(onClearFilters)) { onClearFilters(); } }; let sortIcon = ICON_TYPE.SORT; let sortActive = false; if (sortable && id && sortColumnId === id) { sortActive = true; sortIcon = sortDirection === SORT_DIRECTION.ASC ? ICON_TYPE.SORT_UP : ICON_TYPE.SORT_DOWN; } const computedStyle: CSSProperties = { ...style }; if (columnWidth) { computedStyle.width = columnWidth; } if (minColumnWidth) { computedStyle.minWidth = minColumnWidth; } return ( {children} {(filterOptions || filterControl || sortable) && ( {(filterOptions || filterControl) && ( )} {sortable && ( )} )} ); }} ); }; export default TableHeaderCell;