data-grid
Data grid with movable columns
Data grid with movable columns
Загрузка превью…
src/data-grid/c-data-grid-12.vue
<script setup lang="ts">
import { h, ref } from "vue"
import { Badge } from "@/components/reui/badge"
import { DataGrid, DataGridColumnHeader, DataGridContainer, DataGridPagination, DataGridScrollArea, DataGridTable } from "@/components/reui/data-grid"
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
import { getCoreRowModel, getFilteredRowModel, getPaginationRowModel, getSortedRowModel, useVueTable } from "@tanstack/vue-table"
import type { ColumnDef, PaginationState, SortingState } from "@tanstack/vue-table"
interface IData {
id: string
name: string
availability: "online" | "away" | "busy" | "offline"
avatar: string
status: "active" | "inactive"
flag: string
email: string
company: string
role: string
joined: string
location: string
balance: number
}
const demoData: IData[] = [
{
id: "1",
name: "Alex Johnson",
availability: "online",
avatar: "https://images.unsplash.com/photo-1535713875002-d1d0cf377fde?w=96&h=96&dpr=2&q=80",
status: "active",
flag: "us",
email: "alex@apple.com",
company: "Apple",
role: "CEO",
joined: "Jan, 2024",
location: "United States",
balance: 5143.03,
},
{
id: "2",
name: "Sarah Chen",
availability: "away",
avatar: "https://images.unsplash.com/photo-1519699047748-de8e457a634e?w=96&h=96&dpr=2&q=80",
status: "inactive",
flag: "gb",
email: "sarah@openai.com",
company: "OpenAI",
role: "CTO",
joined: "Mar, 2023",
location: "United Kingdom",
balance: 4321.87,
},
{
id: "3",
name: "Michael Rodriguez",
availability: "busy",
avatar: "https://images.unsplash.com/photo-1584308972272-9e4e7685e80f?w=96&h=96&dpr=2&q=80",
status: "active",
flag: "ca",
email: "michael@meta.com",
company: "Meta",
role: "Designer",
joined: "Jun, 2022",
location: "Canada",
balance: 7654.98,
},
{
id: "4",
name: "Emma Wilson",
availability: "offline",
avatar: "https://images.unsplash.com/photo-1485893086445-ed75865251e0?w=96&h=96&dpr=2&q=80",
status: "inactive",
flag: "au",
email: "emma@tesla.com",
company: "Tesla",
role: "Developer",
joined: "Sep, 2024",
location: "Australia",
balance: 3456.45,
},
{
id: "5",
name: "David Kim",
availability: "online",
avatar: "https://images.unsplash.com/photo-1607990281513-2c110a25bd8c?w=96&h=96&dpr=2&q=80",
status: "active",
flag: "de",
email: "david@sap.com",
company: "SAP",
role: "Lawyer",
joined: "Nov, 2023",
location: "Germany",
balance: 9876.54,
},
{
id: "6",
name: "Aron Thompson",
availability: "away",
avatar: "https://images.unsplash.com/photo-1527980965255-d3b416303d12?w=96&h=96&dpr=2&q=80",
status: "active",
flag: "my",
email: "aron@keenthemes.com",
company: "Keenthemes",
role: "Director",
joined: "Feb, 2022",
location: "Malaysia",
balance: 6214.22,
},
{
id: "7",
name: "James Brown",
availability: "busy",
avatar: "https://images.unsplash.com/photo-1543299750-19d1d6297053?w=96&h=96&dpr=2&q=80",
status: "inactive",
flag: "es",
email: "james@bbva.es",
company: "BBVA",
role: "Product Manager",
joined: "Aug, 2024",
location: "Spain",
balance: 5321.77,
},
]
const pagination = ref<PaginationState>({ pageIndex: 0, pageSize: 5 })
const sorting = ref<SortingState>([{ id: "name", desc: true }])
const columns: ColumnDef<IData>[] = [
{
accessorKey: "name",
id: "name",
header: (ctx) => h(DataGridColumnHeader, { column: ctx.column as never, title: "Staff" }),
cell: (info) =>
h("div", { class: "flex items-center gap-3" }, [
h(Avatar, { class: "size-8" }, () => [
h(AvatarImage, { src: info.row.original.avatar, alt: info.row.original.name }),
h(AvatarFallback, () => info.row.original.name.split(" ").map((n: string) => n[0]).join("")),
]),
h("div", { class: "space-y-px" }, [
h("div", { class: "text-foreground font-medium" }, info.row.original.name),
h("div", { class: "text-muted-foreground" }, info.row.original.email),
]),
]),
size: 200,
enableSorting: true,
enableHiding: false,
},
{
accessorKey: "company",
id: "company",
header: (ctx) => h(DataGridColumnHeader, { column: ctx.column as never, title: "Company" }),
cell: (info) => h("span", info.getValue() as string),
size: 125,
enableSorting: true,
enableHiding: false,
},
{
accessorKey: "role",
id: "role",
header: (ctx) => h(DataGridColumnHeader, { column: ctx.column as never, title: "Occupation" }),
cell: (info) => h("span", info.getValue() as string),
size: 150,
enableSorting: true,
enableHiding: false,
},
{
accessorKey: "status",
id: "status",
header: "Status",
cell: (info) =>
info.row.original.status === "active"
? h(Badge, { variant: "success-light" }, () => "Approved")
: h(Badge, { variant: "warning-light" }, () => "Pending"),
size: 100,
},
]
const columnOrder = ref<string[]>(columns.map((column) => column.id as string))
const table = useVueTable({
get data() {
return demoData
},
columns,
get pageCount() {
return Math.ceil(demoData.length / pagination.value.pageSize)
},
getRowId: (row: IData) => row.id,
state: {
get pagination() {
return pagination.value
},
get sorting() {
return sorting.value
},
get columnOrder() {
return columnOrder.value
},
},
onColumnOrderChange: (updater) => {
columnOrder.value = typeof updater === "function" ? updater(columnOrder.value) : updater
},
onPaginationChange: (updater) => {
pagination.value = typeof updater === "function" ? updater(pagination.value) : updater
},
onSortingChange: (updater) => {
sorting.value = typeof updater === "function" ? updater(sorting.value) : updater
},
getCoreRowModel: getCoreRowModel(),
getFilteredRowModel: getFilteredRowModel(),
getPaginationRowModel: getPaginationRowModel(),
getSortedRowModel: getSortedRowModel(),
})
</script>
<template>
<DataGrid :table="table" :record-count="demoData?.length || 0" :table-layout="{ columnsMovable: true }">
<div class="w-full space-y-2.5">
<DataGridContainer>
<DataGridScrollArea>
<DataGridTable />
</DataGridScrollArea>
</DataGridContainer>
<DataGridPagination />
</div>
</DataGrid>
</template>