import React, { CSSProperties, ThHTMLAttributes, HTMLAttributes, TableHTMLAttributes, TdHTMLAttributes, FC, createContext, useMemo, useContext, ReactNode, } from 'react'; import classnames from 'classnames'; import { Icon } from './Icon'; /** * */ const TableRowContext = createContext<{ header?: boolean; hasActions?: boolean; actionsPosition?: number; sortable?: boolean; }>({}); const TableContext = createContext<{ sortable?: boolean }>({}); /** * */ export type TableHeaderProps = { hasActions?: boolean; actionsPosition?: number; sortable?: boolean; children?: ReactNode; }; /** * */ export const TableHeader: FC = (props) => { const { hasActions, actionsPosition, sortable: sortable_, children } = props; const { sortable: tableSortable } = useContext(TableContext); const sortable = typeof sortable_ !== 'undefined' ? sortable_ : tableSortable; const ctx = useMemo( () => ({ header: true, hasActions, actionsPosition, sortable }), [hasActions, actionsPosition, sortable] ); return ( {children} ); }; /** * */ export const TableBody: FC<{ children?: ReactNode }> = ({ children }) => { const ctx = useMemo(() => ({}), []); return ( {React.Children.map(children, (child) => ( {child} ))} ); }; /** * */ export type TableRowProps = { selected?: boolean; style?: object; } & HTMLAttributes; /** * */ export const TableRow: FC = (props) => { const { className, selected, style: style_, children, ...rprops } = props; const { header, hasActions, actionsPosition = 0, } = useContext(TableRowContext); let newChildren = React.Children.toArray(children); if (header && hasActions) { newChildren = [ ...newChildren.slice(0, actionsPosition), , ...newChildren.slice(actionsPosition), ]; } const rowClassName = classnames( className, header ? 'slds-line-height_reset' : 'slds-hint-parent' ); const style = selected ? { ...style_, backgroundColor: '#F8FCF5', borderLeft: '2px solid #7db450', } : style_; return ( {newChildren} ); }; /** * */ export type TableHeaderColumnProps = { className?: string; width?: string | number; sortable?: boolean; resizable?: boolean; sortDir?: string; sorted?: boolean; align?: 'left' | 'center' | 'right'; onSort?: () => void; } & ThHTMLAttributes; /** * */ export const TableHeaderColumn: FC = (props) => { const { sortable: sortable_, resizable, children, className, width, sortDir, onSort, sorted, align, ...pprops } = props; const { sortable: rowSortable } = useContext(TableRowContext); const sortable = typeof sortable_ === 'undefined' ? rowSortable : sortable_; const oClassNames = classnames( className, { 'slds-is-sortable': sortable, 'slds-is-resizable': resizable, 'slds-is-sorted': sorted, }, align ? `slds-text-align_${align}` : undefined ); const style = { minWidth: width || 'auto' }; const icon = sortDir === 'DESC' ? 'arrowdown' : 'arrowup'; const content = typeof children === 'string' ? children : undefined; const cellContent = (
{children}
); return ( {sortable ? ( { e.preventDefault(); if (onSort) { onSort(); } }} className='slds-th__action slds-text-link_reset' > Sort {cellContent} ) : ( cellContent )} ); }; /** * */ export type TableRowColumnProps = { width?: string | number; truncate?: boolean; } & TdHTMLAttributes; /** * */ export const TableRowColumn: FC = (props) => { const { truncate = true, className: oClassNames, width, children, ...pprops } = props; const style: CSSProperties = {}; if (width !== undefined) style.width = width; if (!truncate) style.position = 'static'; const content = typeof children === 'string' ? children : undefined; const cellContent = truncate ? (
{children}
) : ( children ); return ( {cellContent} ); }; /** * */ export const TableRowColumnActions: FC<{ children?: ReactNode }> = (props) => ( {props.children} ); /** * */ export type TableProps = { bordered?: boolean; verticalBorders?: boolean; noRowHover?: boolean; striped?: boolean; fixedLayout?: boolean; sortable?: boolean; autoWidth?: boolean; } & TableHTMLAttributes; /** * */ export const Table: FC = (props) => { const { className, bordered, verticalBorders, noRowHover, striped, fixedLayout, autoWidth, sortable, children, style: style_, ...rprops } = props; const tableClassNames = classnames(className, 'slds-table', { 'slds-table_bordered': bordered, 'slds-no-row-hover': noRowHover, 'slds-table_striped': striped, 'slds-table_fixed-layout': fixedLayout, 'slds-table_resizable-cols': sortable, 'slds-table_cell-buffer': !sortable, 'slds-table_col-bordered': verticalBorders, }); const style: CSSProperties = { ...style_ }; if (autoWidth) { style.width = 'auto'; } const ctx = useMemo(() => ({ sortable }), [sortable]); return ( {children}
); };