import { h } from 'vue'; import { Badge } from '@/Components/ui/badge'; import { Button } from '@/Components/ui/button'; import { Checkbox } from '@/Components/ui/checkbox'; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, } from '@/Components/ui/dropdown-menu'; import { MoreHorizontal, ArrowUpDown } from 'lucide-vue-next'; /** * Example columns definition following shadcn-vue DataTable patterns * * Usage: * import { columns } from './columns' * * * This is a TypeScript-like example for JavaScript. * The columns follow TanStack Table's ColumnDef format. */ /** * Simple format - automatically converted to ColumnDef * Use this for basic tables */ export const simpleColumns = [ { key: 'id', label: 'ID', sortable: true }, { key: 'name', label: 'Name', sortable: true }, { key: 'email', label: 'Email', sortable: true }, { key: 'status', label: 'Status', sortable: false }, ]; /** * Advanced format - full TanStack Table ColumnDef * Use this for custom rendering, formatting, etc. */ export const advancedColumns = [ // Selection column (added automatically if enableRowSelection prop is true) // { // id: 'select', // header: ({ table }) => { // return h(Checkbox, { // modelValue: table.getIsAllPageRowsSelected(), // indeterminate: table.getIsSomePageRowsSelected(), // 'onUpdate:modelValue': (value) => table.toggleAllPageRowsSelected(!!value), // 'aria-label': 'Select all', // }); // }, // cell: ({ row }) => { // return h(Checkbox, { // modelValue: row.getIsSelected(), // 'onUpdate:modelValue': (value) => row.toggleSelected(!!value), // 'aria-label': 'Select row', // }); // }, // enableSorting: false, // enableHiding: false, // }, // ID column { accessorKey: 'id', header: ({ column }) => { return h( Button, { variant: 'ghost', onClick: () => column.toggleSorting(column.getIsSorted() === 'asc'), }, () => ['ID', h(ArrowUpDown, { class: 'ml-2 h-4 w-4' })] ); }, cell: ({ row }) => { return h('div', { class: 'w-20 font-medium' }, row.getValue('id')); }, }, // Name column { accessorKey: 'name', header: 'Name', cell: ({ row }) => { return h('div', { class: 'font-medium' }, row.getValue('name')); }, }, // Email column with custom rendering { accessorKey: 'email', header: ({ column }) => { return h( Button, { variant: 'ghost', onClick: () => column.toggleSorting(column.getIsSorted() === 'asc'), }, () => ['Email', h(ArrowUpDown, { class: 'ml-2 h-4 w-4' })] ); }, cell: ({ row }) => { return h('div', { class: 'lowercase' }, row.getValue('email')); }, }, // Amount column with formatting { accessorKey: 'amount', header: () => h('div', { class: 'text-right' }, 'Amount'), cell: ({ row }) => { const amount = parseFloat(row.getValue('amount')); const formatted = new Intl.NumberFormat('sl-SI', { style: 'currency', currency: 'EUR', }).format(amount); return h('div', { class: 'text-right font-medium' }, formatted); }, }, // Status column with badge { accessorKey: 'status', header: 'Status', cell: ({ row }) => { const status = row.getValue('status'); const variants = { success: 'default', pending: 'secondary', failed: 'destructive', }; return h( Badge, { variant: variants[status] || 'outline', }, () => status ); }, }, // Actions column { id: 'actions', enableHiding: false, cell: ({ row }) => { const item = row.original; return h( 'div', { class: 'text-right' }, h( DropdownMenu, {}, { default: () => [ h( DropdownMenuTrigger, { asChild: true }, { default: () => h( Button, { variant: 'ghost', class: 'h-8 w-8 p-0', }, { default: () => [ h('span', { class: 'sr-only' }, 'Open menu'), h(MoreHorizontal, { class: 'h-4 w-4' }), ], } ), } ), h( DropdownMenuContent, { align: 'end' }, { default: () => [ h(DropdownMenuLabel, {}, () => 'Actions'), h( DropdownMenuItem, { onClick: () => navigator.clipboard.writeText(item.id), }, () => 'Copy ID' ), h(DropdownMenuSeparator), h(DropdownMenuItem, {}, () => 'View details'), h(DropdownMenuItem, {}, () => 'Edit'), ], } ), ], } ) ); }, }, ]; /** * Payments example from shadcn-vue docs */ export const paymentColumns = [ { accessorKey: 'status', header: 'Status', cell: ({ row }) => { const status = row.getValue('status'); return h('div', { class: 'capitalize' }, status); }, }, { accessorKey: 'email', header: ({ column }) => { return h( Button, { variant: 'ghost', onClick: () => column.toggleSorting(column.getIsSorted() === 'asc'), }, () => ['Email', h(ArrowUpDown, { class: 'ml-2 h-4 w-4' })] ); }, cell: ({ row }) => h('div', { class: 'lowercase' }, row.getValue('email')), }, { accessorKey: 'amount', header: () => h('div', { class: 'text-right' }, 'Amount'), cell: ({ row }) => { const amount = parseFloat(row.getValue('amount')); const formatted = new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD', }).format(amount); return h('div', { class: 'text-right font-medium' }, formatted); }, }, ]; /** * Example with custom cell slots * Use template slots in your component: * * * * */ export const columnsWithSlots = [ { key: 'id', label: 'ID', sortable: true }, { key: 'name', label: 'Name', sortable: true }, { key: 'status', label: 'Status', sortable: false }, // Will use #cell-status slot { key: 'email', label: 'Email', sortable: true }, ]; export default advancedColumns;