mirror of
https://github.com/ArthurDanjou/ui.git
synced 2026-01-14 20:19:34 +01:00
feat(Table): conditionally apply classes to tr and td (#3866)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
<script lang="ts">
|
||||
import type { Ref } from 'vue'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import type { RowData } from '@tanstack/table-core'
|
||||
import type { Cell, Header, RowData, TableMeta } from '@tanstack/table-core'
|
||||
import type {
|
||||
CellContext,
|
||||
ColumnDef,
|
||||
@@ -39,13 +39,20 @@ import theme from '#build/ui/table'
|
||||
import type { ComponentConfig } from '../types/utils'
|
||||
|
||||
declare module '@tanstack/table-core' {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
|
||||
interface ColumnMeta<TData extends RowData, TValue> {
|
||||
class?: {
|
||||
th?: string
|
||||
td?: string
|
||||
th?: string | ((cell: Header<TData, TValue>) => string)
|
||||
td?: string | ((cell: Cell<TData, TValue>) => string)
|
||||
}
|
||||
}
|
||||
|
||||
interface TableMeta<TData> {
|
||||
class?: {
|
||||
tr?: string | ((row: Row<TData>) => string)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
type Table = ComponentConfig<typeof theme, AppConfig, 'table'>
|
||||
@@ -69,6 +76,7 @@ export interface TableProps<T extends TableData> extends TableOptions<T> {
|
||||
data?: T[]
|
||||
columns?: TableColumn<T>[]
|
||||
caption?: string
|
||||
meta?: TableMeta<T>
|
||||
/**
|
||||
* The text to display when the table is empty.
|
||||
* @defaultValue t('table.noData')
|
||||
@@ -184,6 +192,7 @@ const appConfig = useAppConfig() as Table['AppConfig']
|
||||
|
||||
const data = computed(() => props.data ?? [])
|
||||
const columns = computed<TableColumn<T>[]>(() => props.columns ?? Object.keys(data.value[0] ?? {}).map((accessorKey: string) => ({ accessorKey, header: upperFirst(accessorKey) })))
|
||||
const meta = computed(() => props.meta ?? {})
|
||||
|
||||
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.table || {}) })({
|
||||
sticky: props.sticky,
|
||||
@@ -212,6 +221,7 @@ const tableApi = useVueTable({
|
||||
...reactiveOmit(props, 'as', 'data', 'columns', 'caption', 'sticky', 'loading', 'loadingColor', 'loadingAnimation', 'class', 'ui'),
|
||||
data,
|
||||
columns: columns.value,
|
||||
meta: meta.value,
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
...(props.globalFilterOptions || {}),
|
||||
onGlobalFilterChange: updaterOrValue => valueUpdater(updaterOrValue, globalFilterState),
|
||||
@@ -326,7 +336,13 @@ defineExpose({
|
||||
:key="header.id"
|
||||
:data-pinned="header.column.getIsPinned()"
|
||||
:colspan="header.colSpan > 1 ? header.colSpan : undefined"
|
||||
:class="ui.th({ class: [props.ui?.th, header.column.columnDef.meta?.class?.th], pinned: !!header.column.getIsPinned() })"
|
||||
:class="ui.th({
|
||||
class: [
|
||||
props.ui?.th,
|
||||
typeof header.column.columnDef.meta?.class?.th === 'function' ? header.column.columnDef.meta.class.th(header) : header.column.columnDef.meta?.class?.th
|
||||
],
|
||||
pinned: !!header.column.getIsPinned()
|
||||
})"
|
||||
>
|
||||
<slot :name="`${header.id}-header`" v-bind="header.getContext()">
|
||||
<FlexRender v-if="!header.isPlaceholder" :render="header.column.columnDef.header" :props="header.getContext()" />
|
||||
@@ -344,14 +360,25 @@ defineExpose({
|
||||
:data-expanded="row.getIsExpanded()"
|
||||
:role="props.onSelect ? 'button' : undefined"
|
||||
:tabindex="props.onSelect ? 0 : undefined"
|
||||
:class="ui.tr({ class: [props.ui?.tr] })"
|
||||
:class="ui.tr({
|
||||
class: [
|
||||
props.ui?.tr,
|
||||
typeof tableApi.options.meta?.class?.tr === 'function' ? tableApi.options.meta.class.tr(row) : tableApi.options.meta?.class?.tr
|
||||
]
|
||||
})"
|
||||
@click="handleRowSelect(row, $event)"
|
||||
>
|
||||
<td
|
||||
v-for="cell in row.getVisibleCells()"
|
||||
:key="cell.id"
|
||||
:data-pinned="cell.column.getIsPinned()"
|
||||
:class="ui.td({ class: [props.ui?.td, cell.column.columnDef.meta?.class?.td], pinned: !!cell.column.getIsPinned() })"
|
||||
:class="ui.td({
|
||||
class: [
|
||||
props.ui?.td,
|
||||
typeof cell.column.columnDef.meta?.class?.td === 'function' ? cell.column.columnDef.meta.class.td(cell) : cell.column.columnDef.meta?.class?.td
|
||||
],
|
||||
pinned: !!cell.column.getIsPinned()
|
||||
})"
|
||||
>
|
||||
<slot :name="`${cell.column.id}-cell`" v-bind="cell.getContext()">
|
||||
<FlexRender :render="cell.column.columnDef.cell" :props="cell.getContext()" />
|
||||
|
||||
Reference in New Issue
Block a user