@coreui/vue-pro
Version:
UI Components Library for Vue.js
282 lines (264 loc) • 10.1 kB
text/typescript
import { computed, defineComponent, h, PropType, ref, watch } from 'vue'
import { CFormInput } from '../form/'
import { CTableFoot, CTableHead, CTableHeaderCell, CTableRow } from '../table/'
import {
getColumnKey,
getColumnLabel,
getColumnGroups,
getColumns,
getColumnSorterState,
getColumnValues,
getTableHeaderCellProps,
getTableHeaderCellStyles,
} from './utils'
import type { Column, ColumnFilter, ColumnFilterValue, Item, Sorter, SorterValue } from './types'
const CSmartTableHead = defineComponent({
name: 'CSmartTableHead',
props: {
as: {
type: String,
default: 'head',
},
columnFilter: [Boolean, Object] as PropType<boolean | ColumnFilter>,
columnFilterValue: Object as PropType<ColumnFilterValue>,
columnSorter: [Boolean, Object] as PropType<boolean | Sorter>,
columns: {
type: Array as PropType<(Column | string)[]>,
default: () => [],
},
items: {
type: Array as PropType<Item[]>,
default: () => [],
},
selectable: Boolean,
selectAll: [Boolean, Object] as PropType<boolean | { external?: boolean }>,
selectedAll: [Boolean, String],
showGroups: {
type: Boolean,
default: true,
},
sorterState: {
type: Array as PropType<SorterValue[]>,
default: () => [],
}
},
emits: ['customFilterChange', 'filterInput', 'filterChange', 'selectAllChecked', 'sortClick'],
setup(props, { slots, emit }) {
const selectedAll = ref()
const seleactAllCheckboxRef = ref<HTMLInputElement>()
const columns = computed(() => getColumns(props.columns))
const groups = computed(() => getColumnGroups(props.columns))
watch(
() => props.selectedAll,
() => {
selectedAll.value = props.selectedAll
},
{
immediate: true,
},
)
watch([selectedAll, seleactAllCheckboxRef], () => {
if (seleactAllCheckboxRef.value && props.selectedAll === true) {
seleactAllCheckboxRef.value.indeterminate = false
seleactAllCheckboxRef.value.checked = true
return
}
if (seleactAllCheckboxRef.value && props.selectedAll === 'indeterminate') {
seleactAllCheckboxRef.value.checked = false
seleactAllCheckboxRef.value.indeterminate = true
return
}
if (seleactAllCheckboxRef.value) {
seleactAllCheckboxRef.value.indeterminate = false
seleactAllCheckboxRef.value.checked = false
}
})
const columnSorterIcon = (column: Column | string) => {
if (getColumnSorterState(getColumnKey(column), props.sorterState) === 0) {
return h(
'span',
{ class: 'opacity-25 float-end me-1' },
slots.sortingIcon && slots.sortingIcon(),
)
}
if (getColumnSorterState(getColumnKey(column), props.sorterState) === 'asc') {
return h(
'span',
{ class: 'float-end me-1' },
slots.sortingIconAscending && slots.sortingIconAscending(),
)
}
if (getColumnSorterState(getColumnKey(column), props.sorterState) === 'desc') {
return h(
'span',
{ class: 'float-end me-1' },
slots.sortingIconDescending && slots.sortingIconDescending(),
)
}
return
}
return () =>
h(
props.as === 'head' ? CTableHead : CTableFoot,
{},
{
default: () => [
props.showGroups &&
groups.value &&
groups.value.length > 0 &&
groups.value.map((row) => [
h(CTableRow, {}, () => [
props.selectable && h(CTableHeaderCell),
row.map((cell) =>
h(
CTableHeaderCell,
{
colspan: cell.colspan,
...getTableHeaderCellProps(cell),
},
() => cell.label,
),
),
]),
]),
h(
CTableRow,
{},
{
default: () => [
props.selectable &&
h(CTableHeaderCell, {}, () =>
h('input', {
class: 'form-check-input',
type: 'checkbox',
ref: seleactAllCheckboxRef,
onClick: () => {
if (selectedAll.value !== 'reset') {
selectedAll.value = 'reset'
} else {
selectedAll.value = ''
}
emit('selectAllChecked')
},
}),
),
columns.value.map((column, index: number) => {
const isSortable =
props.columnSorter &&
(typeof column === 'object'
? column.sorter === undefined
? true
: column.sorter
: true)
return h(
CTableHeaderCell,
{
...getTableHeaderCellProps(column),
style: getTableHeaderCellStyles(column, props.columnSorter),
...(isSortable && {
tabindex: 0,
onClick: () => emit('sortClick', getColumnKey(column), index),
onKeydown: (event: KeyboardEvent) => {
if (event.key === 'Enter') {
emit('sortClick', getColumnKey(column), index)
}
if (event.key === 'ArrowUp') {
event.preventDefault()
emit('sortClick', getColumnKey(column), index, 'asc')
}
if (event.key === 'ArrowDown') {
event.preventDefault()
emit('sortClick', getColumnKey(column), index, 'desc')
}
},
}),
},
{
default: () => [
h(
'div',
{
class: 'd-inline',
},
getColumnLabel(column),
),
props.columnSorter &&
(typeof column === 'object'
? typeof column.sorter === 'undefined'
? true
: column.sorter
: true) &&
columnSorterIcon(column),
],
},
)
}),
],
},
),
props.columnFilter &&
h(
CTableRow,
{},
{
default: () => [
props.selectable && h(CTableHeaderCell),
columns.value.map((column: Column | string) => {
return h(
CTableHeaderCell,
{
...getTableHeaderCellProps(column),
},
{
default: () =>
(
typeof column === 'object'
? column.filter === undefined
? true
: column.filter
: true
)
? typeof column !== 'string' && typeof column.filter === 'function'
? column.filter(
getColumnValues(props.items, getColumnKey(column)),
(value: any) => {
emit('customFilterChange', getColumnKey(column), value)
},
)
: h(CFormInput, {
size: 'sm',
onInput: (event: Event) => {
emit(
'filterInput',
getColumnKey(column),
(event.target as HTMLInputElement).value,
)
},
onChange: (event: Event) => {
emit(
'filterChange',
getColumnKey(column),
(event.target as HTMLInputElement).value,
)
},
'aria-label': `column name: '${getColumnLabel(
column,
)}' filter input`,
...(props.columnFilterValue &&
props.columnFilterValue[getColumnKey(column)] && {
value: props.columnFilterValue[getColumnKey(column)],
}),
})
: '',
},
)
}),
],
},
),
],
},
)
},
})
export { CSmartTableHead }