Untitled

mail@pastecode.io avatar
unknown
plain_text
a year ago
4.3 kB
2
Indexable
'use client'
import * as React from 'react'
import { cva, type VariantProps } from 'class-variance-authority'
import { cn } from '@/libs/utils'

const TableWrapper = (props: React.HTMLAttributes<HTMLTableElement>) => {
  return <table className="border border-input bg-background shadow-sm rounded-md">{props.children}</table>
}

export type TTableFieldType = 'image' | undefined
type data = { data?: any; rowType?: TTableFieldType }
export type TTableCell = React.HTMLAttributes<HTMLTableCellElement> & data
export type TTableHeaderFooter = TTableCell[]
export type TTableRow = React.HTMLAttributes<HTMLTableRowElement> & TTableCell[]
export type TTableBody = TTableRow[]

const convertToRowData = (data?: any, rowType?: TTableFieldType) => {
  if (rowType === 'image') {
    return <img src={data} alt={''} width={80} height={80} />
  }
  return data === undefined || data === null ? '' : typeof data === 'string' ? data : data.toString()
}

const TableHeader = (props: { headers?: TTableHeaderFooter }) => {
  const { headers } = props
  return (
    <thead>
      <tr>
        {headers?.map((cell, id) => (
          <th
            key={`table-head-cell-${id}`}
            // {...cell}
            className={cn('border border-input bg-background shadow-sm text-center p-5', cell.className)}>
            {convertToRowData(cell.data, cell.rowType)}
            {cell.children}
          </th>
        ))}
      </tr>
    </thead>
  )
}

const TableBody = (props: { body?: TTableBody }) => {
  const { body: rows } = props
  const defaultClassName = 'border text-center p-5'
  return (
    <tbody className="">
      {rows?.map((row, id) => (
        <tr key={`table-body-row-${id}`} className={cn(defaultClassName, row.className)}>
          {row?.map((cell, id) => (
            <td
              key={`table-body-row-cell-${id}`}
              // {...cell}
              className={cn(defaultClassName, cell.className)}>
              {convertToRowData(cell.data, cell.rowType)}
              {cell.children}
            </td>
          ))}
        </tr>
      ))}
    </tbody>
  )
}

const TableFooter = (props: { footer?: TTableHeaderFooter }) => {
  const { footer } = props
  return (
    <tfoot>
      <tr>
        {footer?.map((cell, id) => (
          <td
            key={`table-head-cell-${id}`}
            // {...cell}
            className={cn('border border-input bg-background shadow-sm text-center p-5', cell.className)}>
            {convertToRowData(cell.data, cell.rowType)}
            {cell.children}
          </td>
        ))}
      </tr>
    </tfoot>
  )
}

const tableVariants = cva('inline-flex items-center justify-center rounded-md text-sm font-medium', {
  variants: {
    variant: {
      default: 'bg-primary text-primary-foreground shadow hover:bg-primary/90',
      destructive: 'bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90',
      outline: 'border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground',
      secondary: 'bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80',
      ghost: 'hover:bg-accent hover:text-accent-foreground',
      link: 'text-primary underline-offset-4 hover:underline',
    },
    size: {
      default: 'h-9 px-4 py-2',
      sm: 'h-8 rounded-md px-3 text-xs',
      lg: 'h-10 rounded-md px-8',
      icon: 'h-9 w-9',
    },
  },
  defaultVariants: {
    variant: 'default',
    size: 'default',
  },
})

export type TTableData = {
  headers?: TTableHeaderFooter
  body?: TTableBody
  footer?: TTableHeaderFooter
}

export interface TableProps extends React.TableHTMLAttributes<HTMLTableElement>, VariantProps<typeof tableVariants> {
  asChild?: boolean
  tableData?: TTableData
}

const Table = React.forwardRef<HTMLTableElement, TableProps>(
  ({ tableData, className, variant, size, asChild = false, ...props }, ref) => {
    const { headers, body, footer } = tableData || {}
    return (
      <TableWrapper>
        <TableHeader headers={headers} />
        <TableBody body={body} />
        <TableFooter footer={footer} />
        {/* <div className={cn(tableVariants({ variant, size, className }))} ref={ref} {...props} > */}
      </TableWrapper>
    )
  }
)
Table.displayName = 'Table'

export { Table, tableVariants }