Untitled

 avatar
unknown
plain_text
a month ago
5.0 kB
3
Indexable
import {
  Table as ShadTable,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from '@components/shadcn/ui/table'
import SortArrow from '@public/icons/sort-arrow.svg'
import { Table as ReactTable, flexRender } from '@tanstack/react-table'
import { classnames, classnames as cn } from '@tools/common'
import Text from './typography/Text'

interface TableProps<T> {
  table: ReactTable<T>
  rowRef?: React.Ref<HTMLTableRowElement>
  onClickRow?: (row: T) => void
}

const Table = <T extends object>({
  table,
  rowRef,
  onClickRow,
}: TableProps<T>) => {
  const headers = table.getFlatHeaders()
  const rows = table.getRowModel().rows

  return (
    <ShadTable>
      <TableHeader className="sticky top-0 z-10 bg-main-300">
        <TableRow>
          {headers.map((header, index) => {
            const isSorted = header.column.getIsSorted()
            const noSorting = header.column.columnDef.enableSorting === false

            const sortDirection = noSorting ? (
              ''
            ) : isSorted === 'desc' ? (
              <SortArrow className="w-6 h-6 fill-primary transition-transform" />
            ) : isSorted === 'asc' ? (
              <SortArrow className="w-6 h-6 rotate-180 fill-primary transition-transform" />
            ) : (
              <SortArrow className="w-6 h-6 fill-main-500 group-hover:fill-main-700 transition-transform" />
            )

            return (
              <TableHead
                key={header.id + index}
                className={cn(
                  'relative group bg-main-300 md:hover:bg-main-500 transition-colors border-r border-white',
                  {
                    'sticky z-10':
                      typeof header.column.getIsPinned() === 'string',
                    'left-0': header.column.getIsPinned() === 'left',
                    'right-0': header.column.getIsPinned() === 'right',
                  },
                )}
                style={{
                  minWidth: header.getSize(),
                  width: header.getSize(),
                }}
              >
                <div
                  onClick={() =>
                    !noSorting &&
                    header.column.toggleSorting(
                      header.column.getIsSorted() === 'asc',
                    )
                  }
                  className="h-full items-center w-full cursor-pointer flex justify-between select-none"
                >
                  {header.isPlaceholder ? null : (
                    <>
                      <Text
                        size="caption-default"
                        as="span"
                        className="uppercase"
                      >
                        {flexRender(
                          header.column.columnDef.header,
                          header.getContext(),
                        )}
                      </Text>
                      <span className="duration-300">{sortDirection}</span>
                    </>
                  )}
                </div>
                {header.column.getCanResize() && (
                  <div
                    onMouseDown={header.getResizeHandler()}
                    onTouchStart={header.getResizeHandler()}
                    className={classnames(
                      `absolute opacity-0 top-0 right-0 h-full w-[5px] bg-primary cursor-col-resize select-none touch-none rounded-[6px] group-hover:opacity-100`,
                      {
                        'bg-main-500': header.column.getIsResizing(),
                      },
                    )}
                  />
                )}
              </TableHead>
            )
          })}
        </TableRow>
      </TableHeader>

      <TableBody>
        {rows.map((row, index) => (
          <TableRow
            key={row.id + index}
            ref={rowRef}
            className={classnames(
              'hover bg-white group/row transition-colors',
              {
                'cursor-pointer': onClickRow,
              },
            )}
            onClick={() => {
              if (onClickRow) {
                onClickRow(row.original)
              }
            }}
          >
            {row.getVisibleCells().map((cell, index) => {
              const CellComponent = index === 0 ? TableHead : TableCell
              return (
                <CellComponent
                  key={cell.id + index}
                  className={cn({
                    'sticky z-10':
                      typeof cell.column.getIsPinned() === 'string',
                    'left-0': cell.column.getIsPinned() === 'left',
                    'right-0': cell.column.getIsPinned() === 'right',
                  })}
                  style={{ width: cell.column.getSize() }}
                >
                  {flexRender(cell.column.columnDef.cell, cell.getContext())}
                </CellComponent>
              )
            })}
          </TableRow>
        ))}
      </TableBody>
    </ShadTable>
  )
}

export default Table
Leave a Comment