24 lines
8.4 KiB
JSON
24 lines
8.4 KiB
JSON
{
|
|
"name": "DataTableDemo",
|
|
"type": "registry:example",
|
|
"dependencies": [
|
|
"@tanstack/vue-table"
|
|
],
|
|
"registryDependencies": [
|
|
"utils",
|
|
"button",
|
|
"checkbox",
|
|
"dropdown-menu",
|
|
"input",
|
|
"table"
|
|
],
|
|
"files": [
|
|
{
|
|
"path": "example/DataTableDemo.vue",
|
|
"content": "<script setup lang=\"ts\">\nimport type {\n ColumnDef,\n ColumnFiltersState,\n ExpandedState,\n SortingState,\n VisibilityState,\n} from '@tanstack/vue-table'\nimport { valueUpdater } from '@/lib/utils'\nimport { Button } from '@/registry/new-york/ui/button'\nimport { Checkbox } from '@/registry/new-york/ui/checkbox'\nimport {\n DropdownMenu,\n DropdownMenuCheckboxItem,\n DropdownMenuContent,\n DropdownMenuTrigger,\n} from '@/registry/new-york/ui/dropdown-menu'\n\nimport { Input } from '@/registry/new-york/ui/input'\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from '@/registry/new-york/ui/table'\nimport { CaretSortIcon, ChevronDownIcon } from '@radix-icons/vue'\nimport {\n FlexRender,\n getCoreRowModel,\n getExpandedRowModel,\n getFilteredRowModel,\n getPaginationRowModel,\n getSortedRowModel,\n useVueTable,\n} from '@tanstack/vue-table'\nimport { h, ref } from 'vue'\nimport DropdownAction from './DataTableDemoColumn.vue'\n\nexport interface Payment {\n id: string\n amount: number\n status: 'pending' | 'processing' | 'success' | 'failed'\n email: string\n}\n\nconst data: Payment[] = [\n {\n id: 'm5gr84i9',\n amount: 316,\n status: 'success',\n email: 'ken99@yahoo.com',\n },\n {\n id: '3u1reuv4',\n amount: 242,\n status: 'success',\n email: 'Abe45@gmail.com',\n },\n {\n id: 'derv1ws0',\n amount: 837,\n status: 'processing',\n email: 'Monserrat44@gmail.com',\n },\n {\n id: '5kma53ae',\n amount: 874,\n status: 'success',\n email: 'Silas22@gmail.com',\n },\n {\n id: 'bhqecj4p',\n amount: 721,\n status: 'failed',\n email: 'carmella@hotmail.com',\n },\n]\n\nconst columns: ColumnDef<Payment>[] = [\n {\n id: 'select',\n header: ({ table }) => h(Checkbox, {\n 'modelValue': table.getIsAllPageRowsSelected() || (table.getIsSomePageRowsSelected() && 'indeterminate'),\n 'onUpdate:modelValue': value => table.toggleAllPageRowsSelected(!!value),\n 'ariaLabel': 'Select all',\n }),\n cell: ({ row }) => h(Checkbox, {\n 'modelValue': row.getIsSelected(),\n 'onUpdate:modelValue': value => row.toggleSelected(!!value),\n 'ariaLabel': 'Select row',\n }),\n enableSorting: false,\n enableHiding: false,\n },\n {\n accessorKey: 'status',\n header: 'Status',\n cell: ({ row }) => h('div', { class: 'capitalize' }, row.getValue('status')),\n },\n {\n accessorKey: 'email',\n header: ({ column }) => {\n return h(Button, {\n variant: 'ghost',\n onClick: () => column.toggleSorting(column.getIsSorted() === 'asc'),\n }, () => ['Email', h(CaretSortIcon, { class: 'ml-2 h-4 w-4' })])\n },\n cell: ({ row }) => h('div', { class: 'lowercase' }, row.getValue('email')),\n },\n {\n accessorKey: 'amount',\n header: () => h('div', { class: 'text-right' }, 'Amount'),\n cell: ({ row }) => {\n const amount = Number.parseFloat(row.getValue('amount'))\n\n // Format the amount as a dollar amount\n const formatted = new Intl.NumberFormat('en-US', {\n style: 'currency',\n currency: 'USD',\n }).format(amount)\n\n return h('div', { class: 'text-right font-medium' }, formatted)\n },\n },\n {\n id: 'actions',\n enableHiding: false,\n cell: ({ row }) => {\n const payment = row.original\n\n return h(DropdownAction, {\n payment,\n onExpand: row.toggleExpanded,\n })\n },\n },\n]\n\nconst sorting = ref<SortingState>([])\nconst columnFilters = ref<ColumnFiltersState>([])\nconst columnVisibility = ref<VisibilityState>({})\nconst rowSelection = ref({})\nconst expanded = ref<ExpandedState>({})\n\nconst table = useVueTable({\n data,\n columns,\n getCoreRowModel: getCoreRowModel(),\n getPaginationRowModel: getPaginationRowModel(),\n getSortedRowModel: getSortedRowModel(),\n getFilteredRowModel: getFilteredRowModel(),\n getExpandedRowModel: getExpandedRowModel(),\n onSortingChange: updaterOrValue => valueUpdater(updaterOrValue, sorting),\n onColumnFiltersChange: updaterOrValue => valueUpdater(updaterOrValue, columnFilters),\n onColumnVisibilityChange: updaterOrValue => valueUpdater(updaterOrValue, columnVisibility),\n onRowSelectionChange: updaterOrValue => valueUpdater(updaterOrValue, rowSelection),\n onExpandedChange: updaterOrValue => valueUpdater(updaterOrValue, expanded),\n state: {\n get sorting() { return sorting.value },\n get columnFilters() { return columnFilters.value },\n get columnVisibility() { return columnVisibility.value },\n get rowSelection() { return rowSelection.value },\n get expanded() { return expanded.value },\n },\n})\n</script>\n\n<template>\n <div class=\"w-full\">\n <div class=\"flex items-center py-4\">\n <Input\n class=\"max-w-sm\"\n placeholder=\"Filter emails...\"\n :model-value=\"table.getColumn('email')?.getFilterValue() as string\"\n @update:model-value=\" table.getColumn('email')?.setFilterValue($event)\"\n />\n <DropdownMenu>\n <DropdownMenuTrigger as-child>\n <Button variant=\"outline\" class=\"ml-auto\">\n Columns <ChevronDownIcon class=\"ml-2 h-4 w-4\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n <DropdownMenuCheckboxItem\n v-for=\"column in table.getAllColumns().filter((column) => column.getCanHide())\"\n :key=\"column.id\"\n class=\"capitalize\"\n :model-value=\"column.getIsVisible()\"\n @update:model-value=\"(value) => {\n column.toggleVisibility(!!value)\n }\"\n >\n {{ column.id }}\n </DropdownMenuCheckboxItem>\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n <div class=\"rounded-md border\">\n <Table>\n <TableHeader>\n <TableRow v-for=\"headerGroup in table.getHeaderGroups()\" :key=\"headerGroup.id\">\n <TableHead v-for=\"header in headerGroup.headers\" :key=\"header.id\">\n <FlexRender v-if=\"!header.isPlaceholder\" :render=\"header.column.columnDef.header\" :props=\"header.getContext()\" />\n </TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n <template v-if=\"table.getRowModel().rows?.length\">\n <template v-for=\"row in table.getRowModel().rows\" :key=\"row.id\">\n <TableRow :data-state=\"row.getIsSelected() && 'selected'\">\n <TableCell v-for=\"cell in row.getVisibleCells()\" :key=\"cell.id\">\n <FlexRender :render=\"cell.column.columnDef.cell\" :props=\"cell.getContext()\" />\n </TableCell>\n </TableRow>\n <TableRow v-if=\"row.getIsExpanded()\">\n <TableCell :colspan=\"row.getAllCells().length\">\n {{ JSON.stringify(row.original) }}\n </TableCell>\n </TableRow>\n </template>\n </template>\n\n <TableRow v-else>\n <TableCell\n :colspan=\"columns.length\"\n class=\"h-24 text-center\"\n >\n No results.\n </TableCell>\n </TableRow>\n </TableBody>\n </Table>\n </div>\n\n <div class=\"flex items-center justify-end space-x-2 py-4\">\n <div class=\"flex-1 text-sm text-muted-foreground\">\n {{ table.getFilteredSelectedRowModel().rows.length }} of\n {{ table.getFilteredRowModel().rows.length }} row(s) selected.\n </div>\n <div class=\"space-x-2\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n :disabled=\"!table.getCanPreviousPage()\"\n @click=\"table.previousPage()\"\n >\n Previous\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n :disabled=\"!table.getCanNextPage()\"\n @click=\"table.nextPage()\"\n >\n Next\n </Button>\n </div>\n </div>\n </div>\n</template>\n",
|
|
"type": "registry:example",
|
|
"target": "DataTableDemo.vue"
|
|
}
|
|
]
|
|
}
|