feat: implement new Tasks BigData example for useVirtualList usage
This commit is contained in:
parent
08d6ea6a53
commit
651e6ae19c
|
|
@ -70,6 +70,13 @@ export default defineConfig({
|
|||
rewrites: {
|
||||
'content/(.*)': '(.*)',
|
||||
},
|
||||
vue: {
|
||||
template: {
|
||||
compilerOptions: {
|
||||
isCustomElement: tag => tag === 'option.icon',
|
||||
},
|
||||
},
|
||||
},
|
||||
vite: {
|
||||
css: {
|
||||
postcss: {
|
||||
|
|
|
|||
|
|
@ -23,6 +23,11 @@ const examples = [
|
|||
href: '/examples/tasks',
|
||||
code: 'https://github.com/radix-vue/shadcn-vue/tree/dev/apps/www/src/examples/tasks',
|
||||
},
|
||||
{
|
||||
name: 'Tasks (Big Data)',
|
||||
href: '/examples/big-data',
|
||||
code: 'https://github.com/radix-vue/shadcn-vue/tree/dev/apps/www/src/examples/big-data',
|
||||
},
|
||||
{
|
||||
name: 'Playground',
|
||||
href: '/examples/playground',
|
||||
|
|
|
|||
5
apps/www/src/content/examples/big-data.md
Normal file
5
apps/www/src/content/examples/big-data.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<script setup>
|
||||
import BigDataExample from "@/examples/big-data/Example.vue"
|
||||
</script>
|
||||
|
||||
<BigDataExample />
|
||||
36
apps/www/src/examples/big-data/Example.vue
Normal file
36
apps/www/src/examples/big-data/Example.vue
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
<script setup lang="ts">
|
||||
import tasks from './data/tasks.json'
|
||||
import DataTable from './components/DataTable.vue'
|
||||
import UserNav from './components/UserNav.vue'
|
||||
import { columns } from './components/columns'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="md:hidden">
|
||||
<VPImage
|
||||
alt="Tasks"
|
||||
width="1280"
|
||||
height="1214" class="block" :image="{
|
||||
dark: '/examples/tasks-dark.png',
|
||||
light: '/examples/tasks-light.png',
|
||||
}"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="hidden h-full flex-1 flex-col space-y-8 p-8 md:flex">
|
||||
<div class="flex items-center justify-between space-y-2">
|
||||
<div>
|
||||
<h2 class="text-2xl font-bold tracking-tight">
|
||||
Welcome back!
|
||||
</h2>
|
||||
<p class="text-muted-foreground">
|
||||
Here's a list of your tasks for this month!
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex items-center space-x-2">
|
||||
<UserNav />
|
||||
</div>
|
||||
</div>
|
||||
<DataTable :data="tasks" :columns="columns" />
|
||||
</div>
|
||||
</template>
|
||||
120
apps/www/src/examples/big-data/components/DataTable.vue
Normal file
120
apps/www/src/examples/big-data/components/DataTable.vue
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
<script setup lang="ts">
|
||||
import type {
|
||||
ColumnDef,
|
||||
ColumnFiltersState,
|
||||
SortingState,
|
||||
VisibilityState,
|
||||
} from '@tanstack/vue-table'
|
||||
import {
|
||||
FlexRender,
|
||||
getCoreRowModel,
|
||||
getFacetedRowModel,
|
||||
getFacetedUniqueValues,
|
||||
getFilteredRowModel,
|
||||
getPaginationRowModel,
|
||||
getSortedRowModel,
|
||||
useVueTable,
|
||||
} from '@tanstack/vue-table'
|
||||
|
||||
import { useVirtualList } from '@vueuse/core'
|
||||
|
||||
import { computed, ref } from 'vue'
|
||||
import { type Task } from '../data/schema'
|
||||
import DataTablePagination from './DataTablePagination.vue'
|
||||
import DataTableToolbar from './DataTableToolbar.vue'
|
||||
import { valueUpdater } from '@/lib/utils'
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from '@/lib/registry/new-york/ui/table'
|
||||
|
||||
interface DataTableProps {
|
||||
columns: ColumnDef<Task, any>[]
|
||||
data: Task[]
|
||||
}
|
||||
const props = defineProps<DataTableProps>()
|
||||
|
||||
const sorting = ref<SortingState>([])
|
||||
const columnFilters = ref<ColumnFiltersState>([])
|
||||
const columnVisibility = ref<VisibilityState>({})
|
||||
const rowSelection = ref({})
|
||||
|
||||
const table = useVueTable({
|
||||
get data() { return props.data },
|
||||
get columns() { return props.columns },
|
||||
state: {
|
||||
get sorting() { return sorting.value },
|
||||
get columnFilters() { return columnFilters.value },
|
||||
get columnVisibility() { return columnVisibility.value },
|
||||
get rowSelection() { return rowSelection.value },
|
||||
},
|
||||
enableRowSelection: true,
|
||||
onSortingChange: updaterOrValue => valueUpdater(updaterOrValue, sorting),
|
||||
onColumnFiltersChange: updaterOrValue => valueUpdater(updaterOrValue, columnFilters),
|
||||
onColumnVisibilityChange: updaterOrValue => valueUpdater(updaterOrValue, columnVisibility),
|
||||
onRowSelectionChange: updaterOrValue => valueUpdater(updaterOrValue, rowSelection),
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
getFilteredRowModel: getFilteredRowModel(),
|
||||
getPaginationRowModel: getPaginationRowModel(),
|
||||
getSortedRowModel: getSortedRowModel(),
|
||||
getFacetedRowModel: getFacetedRowModel(),
|
||||
getFacetedUniqueValues: getFacetedUniqueValues(),
|
||||
initialState: {
|
||||
pagination: {
|
||||
pageSize: 500,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
const tableRows = computed(() => table.getRowModel().rows)
|
||||
|
||||
const { list, containerProps, wrapperProps } = useVirtualList(tableRows, {
|
||||
itemHeight: 49,
|
||||
overscan: 15,
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="space-y-4">
|
||||
<DataTableToolbar :table="table" />
|
||||
<div class="rounded-md border max-h-[75dvh]" v-bind="containerProps">
|
||||
<Table v-bind="wrapperProps">
|
||||
<TableHeader style="height: 49px">
|
||||
<TableRow v-for="headerGroup in table.getHeaderGroups()" :key="headerGroup.id">
|
||||
<TableHead v-for="header in headerGroup.headers" :key="header.id">
|
||||
<FlexRender v-if="!header.isPlaceholder" :render="header.column.columnDef.header" :props="header.getContext()" />
|
||||
</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
<template v-if="tableRows?.length">
|
||||
<TableRow
|
||||
v-for="row in list"
|
||||
:key="row.data.id"
|
||||
:data-state="row.data.getIsSelected() && 'selected'"
|
||||
>
|
||||
<TableCell v-for="cell in row.data.getVisibleCells()" :key="cell.id">
|
||||
<FlexRender :render="cell.column.columnDef.cell" :props="cell.getContext()" />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</template>
|
||||
|
||||
<TableRow v-else>
|
||||
<TableCell
|
||||
:colspan="columns.length"
|
||||
class="h-24 text-center"
|
||||
>
|
||||
No results.
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
|
||||
<DataTablePagination :table="table" />
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
<script setup lang="ts">
|
||||
import type { Column } from '@tanstack/vue-table'
|
||||
import { type Task } from '../data/schema'
|
||||
import ArrowDownIcon from '~icons/radix-icons/arrow-down'
|
||||
import ArrowUpIcon from '~icons/radix-icons/arrow-up'
|
||||
import CaretSortIcon from '~icons/radix-icons/caret-sort'
|
||||
import EyeNoneIcon from '~icons/radix-icons/eye-none'
|
||||
|
||||
import { cn } from '@/lib/utils'
|
||||
import { Button } from '@/lib/registry/new-york/ui/button'
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
} from '@/lib/registry/new-york/ui/dropdown-menu'
|
||||
|
||||
interface DataTableColumnHeaderProps {
|
||||
column: Column<Task, any>
|
||||
title: string
|
||||
}
|
||||
|
||||
defineProps<DataTableColumnHeaderProps>()
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
inheritAttrs: false,
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="column.getCanSort()" :class="cn('flex items-center space-x-2', $attrs.class ?? '')">
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger as-child>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
class="-ml-3 h-8 data-[state=open]:bg-accent"
|
||||
>
|
||||
<span>{{ title }}</span>
|
||||
<ArrowDownIcon v-if="column.getIsSorted() === 'desc'" class="ml-2 h-4 w-4" />
|
||||
<ArrowUpIcon v-else-if=" column.getIsSorted() === 'asc'" class="ml-2 h-4 w-4" />
|
||||
<CaretSortIcon v-else class="ml-2 h-4 w-4" />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="start">
|
||||
<DropdownMenuItem @click="column.toggleSorting(false)">
|
||||
<ArrowUpIcon class="mr-2 h-3.5 w-3.5 text-muted-foreground/70" />
|
||||
Asc
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem @click="column.toggleSorting(true)">
|
||||
<ArrowDownIcon class="mr-2 h-3.5 w-3.5 text-muted-foreground/70" />
|
||||
Desc
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem @click="column.toggleVisibility(false)">
|
||||
<EyeNoneIcon class="mr-2 h-3.5 w-3.5 text-muted-foreground/70" />
|
||||
Hide
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</div>
|
||||
|
||||
<div v-else :class="$attrs.class">
|
||||
{{ title }}
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,135 @@
|
|||
<script setup lang="ts">
|
||||
import type { Column } from '@tanstack/vue-table'
|
||||
import type { Component } from 'vue'
|
||||
import { computed } from 'vue'
|
||||
import { type Task } from '../data/schema'
|
||||
import PlusCircledIcon from '~icons/radix-icons/plus-circled'
|
||||
import CheckIcon from '~icons/radix-icons/check'
|
||||
|
||||
import { Badge } from '@/lib/registry/new-york/ui/badge'
|
||||
import { Button } from '@/lib/registry/new-york/ui/button'
|
||||
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator } from '@/lib/registry/new-york/ui/command'
|
||||
|
||||
import {
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
} from '@/lib/registry/new-york/ui/popover'
|
||||
import { Separator } from '@/lib/registry/new-york/ui/separator'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
interface DataTableFacetedFilter {
|
||||
column?: Column<Task, any>
|
||||
title?: string
|
||||
options: {
|
||||
label: string
|
||||
value: string
|
||||
icon?: Component
|
||||
}[]
|
||||
}
|
||||
|
||||
const props = defineProps<DataTableFacetedFilter>()
|
||||
|
||||
const facets = computed(() => props.column?.getFacetedUniqueValues())
|
||||
const selectedValues = computed(() => new Set(props.column?.getFilterValue() as string[]))
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Popover>
|
||||
<PopoverTrigger as-child>
|
||||
<Button variant="outline" size="sm" class="h-8 border-dashed">
|
||||
<PlusCircledIcon class="mr-2 h-4 w-4" />
|
||||
{{ title }}
|
||||
<template v-if="selectedValues.size > 0">
|
||||
<Separator orientation="vertical" class="mx-2 h-4" />
|
||||
<Badge
|
||||
variant="secondary"
|
||||
class="rounded-sm px-1 font-normal lg:hidden"
|
||||
>
|
||||
{{ selectedValues.size }}
|
||||
</Badge>
|
||||
<div class="hidden space-x-1 lg:flex">
|
||||
<Badge
|
||||
v-if="selectedValues.size > 2"
|
||||
variant="secondary"
|
||||
class="rounded-sm px-1 font-normal"
|
||||
>
|
||||
{{ selectedValues.size }} selected
|
||||
</Badge>
|
||||
|
||||
<template v-else>
|
||||
<Badge
|
||||
v-for="option in options
|
||||
.filter((option) => selectedValues.has(option.value))"
|
||||
:key="option.value"
|
||||
variant="secondary"
|
||||
class="rounded-sm px-1 font-normal"
|
||||
>
|
||||
{{ option.label }}
|
||||
</Badge>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent class="w-[200px] p-0" align="start">
|
||||
<Command
|
||||
:filter-function="(list: DataTableFacetedFilter['options'], term) => list.filter(i => i.label.toLowerCase()?.includes(term)) "
|
||||
>
|
||||
<CommandInput :placeholder="title" />
|
||||
<CommandList>
|
||||
<CommandEmpty>No results found.</CommandEmpty>
|
||||
<CommandGroup>
|
||||
<CommandItem
|
||||
v-for="option in options"
|
||||
:key="option.value"
|
||||
:value="option"
|
||||
@select="() => {
|
||||
const isSelected = selectedValues.has(option.value)
|
||||
if (isSelected) {
|
||||
selectedValues.delete(option.value)
|
||||
}
|
||||
else {
|
||||
selectedValues.add(option.value)
|
||||
}
|
||||
const filterValues = Array.from(selectedValues)
|
||||
column?.setFilterValue(
|
||||
filterValues.length ? filterValues : undefined,
|
||||
)
|
||||
}"
|
||||
>
|
||||
<div
|
||||
:class="cn(
|
||||
'mr-2 flex h-4 w-4 items-center justify-center rounded-sm border border-primary',
|
||||
selectedValues.has(option.value)
|
||||
? 'bg-primary text-primary-foreground'
|
||||
: 'opacity-50 [&_svg]:invisible',
|
||||
)"
|
||||
>
|
||||
<CheckIcon :class="cn('h-4 w-4')" />
|
||||
</div>
|
||||
<option.icon v-if="option.icon" class="mr-2 h-4 w-4 text-muted-foreground" />
|
||||
<span>{{ option.label }}</span>
|
||||
<span v-if="facets?.get(option.value)" class="ml-auto flex h-4 w-4 items-center justify-center font-mono text-xs">
|
||||
{{ facets.get(option.value) }}
|
||||
</span>
|
||||
</CommandItem>
|
||||
</CommandGroup>
|
||||
|
||||
<template v-if="selectedValues.size > 0">
|
||||
<CommandSeparator />
|
||||
<CommandGroup>
|
||||
<CommandItem
|
||||
:value="{ label: 'Clear filters' }"
|
||||
class="justify-center text-center"
|
||||
@select="column?.setFilterValue(undefined)"
|
||||
>
|
||||
Clear filters
|
||||
</CommandItem>
|
||||
</CommandGroup>
|
||||
</template>
|
||||
</CommandList>
|
||||
</Command>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
<script setup lang="ts">
|
||||
import { type Table } from '@tanstack/vue-table'
|
||||
import { type Task } from '../data/schema'
|
||||
import ChevronLeftIcon from '~icons/radix-icons/chevron-left'
|
||||
import ChevronRightIcon from '~icons/radix-icons/chevron-right'
|
||||
import DoubleArrowLeftIcon from '~icons/radix-icons/double-arrow-left'
|
||||
import DoubleArrowRightIcon from '~icons/radix-icons/double-arrow-right'
|
||||
|
||||
import { Button } from '@/lib/registry/new-york/ui/button'
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from '@/lib/registry/new-york/ui/select'
|
||||
|
||||
interface DataTablePaginationProps {
|
||||
table: Table<Task>
|
||||
}
|
||||
defineProps<DataTablePaginationProps>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex items-center justify-between px-2">
|
||||
<div class="flex-1 text-sm text-muted-foreground">
|
||||
{{ table.getFilteredSelectedRowModel().rows.length }} of
|
||||
{{ table.getFilteredRowModel().rows.length }} row(s) selected.
|
||||
</div>
|
||||
<div class="flex items-center space-x-6 lg:space-x-8">
|
||||
<div class="flex items-center space-x-2">
|
||||
<p class="text-sm font-medium">
|
||||
Rows per page
|
||||
</p>
|
||||
<Select
|
||||
:model-value="`${table.getState().pagination.pageSize}`"
|
||||
@update:model-value="table.setPageSize"
|
||||
>
|
||||
<SelectTrigger class="h-8 w-[80px]">
|
||||
<SelectValue :placeholder="`${table.getState().pagination.pageSize}`" />
|
||||
</SelectTrigger>
|
||||
<SelectContent side="top">
|
||||
<SelectItem v-for="pageSize in [500, 1000, 2000]" :key="pageSize" :value="`${pageSize}`">
|
||||
{{ pageSize }}
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<div class="flex w-[100px] items-center justify-center text-sm font-medium">
|
||||
Page {{ table.getState().pagination.pageIndex + 1 }} of
|
||||
{{ table.getPageCount() }}
|
||||
</div>
|
||||
<div class="flex items-center space-x-2">
|
||||
<Button
|
||||
variant="outline"
|
||||
class="hidden h-8 w-8 p-0 lg:flex"
|
||||
:disabled="!table.getCanPreviousPage()"
|
||||
@click="table.setPageIndex(0)"
|
||||
>
|
||||
<span class="sr-only">Go to first page</span>
|
||||
<DoubleArrowLeftIcon class="h-4 w-4" />
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
class="h-8 w-8 p-0"
|
||||
:disabled="!table.getCanPreviousPage()"
|
||||
@click="table.previousPage()"
|
||||
>
|
||||
<span class="sr-only">Go to previous page</span>
|
||||
<ChevronLeftIcon class="h-4 w-4" />
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
class="h-8 w-8 p-0"
|
||||
:disabled="!table.getCanNextPage()"
|
||||
@click="table.nextPage()"
|
||||
>
|
||||
<span class="sr-only">Go to next page</span>
|
||||
<ChevronRightIcon class="h-4 w-4" />
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
class="hidden h-8 w-8 p-0 lg:flex"
|
||||
:disabled="!table.getCanNextPage()"
|
||||
@click="table.setPageIndex(table.getPageCount() - 1)"
|
||||
>
|
||||
<span class="sr-only">Go to last page</span>
|
||||
<DoubleArrowRightIcon class="h-4 w-4" />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
<script setup lang="ts">
|
||||
import type { Row } from '@tanstack/vue-table'
|
||||
import { computed } from 'vue'
|
||||
import { labels } from '../data/data'
|
||||
import { taskSchema } from '../data/schema'
|
||||
import { type Task } from '../data/schema'
|
||||
import DotsHorizontalIcon from '~icons/radix-icons/dots-horizontal'
|
||||
|
||||
import { Button } from '@/lib/registry/new-york/ui/button'
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuRadioGroup,
|
||||
DropdownMenuRadioItem,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuShortcut,
|
||||
DropdownMenuSub,
|
||||
DropdownMenuSubContent,
|
||||
DropdownMenuSubTrigger,
|
||||
DropdownMenuTrigger,
|
||||
} from '@/lib/registry/new-york/ui/dropdown-menu'
|
||||
|
||||
interface DataTableRowActionsProps {
|
||||
row: Row<Task>
|
||||
}
|
||||
const props = defineProps<DataTableRowActionsProps>()
|
||||
|
||||
const task = computed(() => taskSchema.parse(props.row.original))
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger as-child>
|
||||
<Button
|
||||
variant="ghost"
|
||||
class="flex h-8 w-8 p-0 data-[state=open]:bg-muted"
|
||||
>
|
||||
<DotsHorizontalIcon class="h-4 w-4" />
|
||||
<span class="sr-only">Open menu</span>
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end" class="w-[160px]">
|
||||
<DropdownMenuItem>Edit</DropdownMenuItem>
|
||||
<DropdownMenuItem>Make a copy</DropdownMenuItem>
|
||||
<DropdownMenuItem>Favorite</DropdownMenuItem>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuSub>
|
||||
<DropdownMenuSubTrigger>Labels</DropdownMenuSubTrigger>
|
||||
<DropdownMenuSubContent>
|
||||
<DropdownMenuRadioGroup :value="task.label">
|
||||
<DropdownMenuRadioItem v-for="label in labels" :key="label.value" :value="label.value">
|
||||
{{ label.label }}
|
||||
</DropdownMenuRadioItem>
|
||||
</DropdownMenuRadioGroup>
|
||||
</DropdownMenuSubContent>
|
||||
</DropdownMenuSub>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem>
|
||||
Delete
|
||||
<DropdownMenuShortcut>⌘⌫</DropdownMenuShortcut>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
<script setup lang="ts">
|
||||
import { type Table } from '@tanstack/vue-table'
|
||||
import { computed } from 'vue'
|
||||
import { type Task } from '../data/schema'
|
||||
|
||||
import { priorities, statuses } from '../data/data'
|
||||
import DataTableFacetedFilter from './DataTableFacetedFilter.vue'
|
||||
import DataTableViewOptions from './DataTableViewOptions.vue'
|
||||
import Cross2Icon from '~icons/radix-icons/cross-2'
|
||||
import { Button } from '@/lib/registry/new-york/ui/button'
|
||||
import { Input } from '@/lib/registry/new-york/ui/input'
|
||||
|
||||
interface DataTableToolbarProps {
|
||||
table: Table<Task>
|
||||
}
|
||||
|
||||
const props = defineProps<DataTableToolbarProps>()
|
||||
|
||||
const isFiltered = computed(() => props.table.getState().columnFilters.length > 0)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex flex-1 items-center space-x-2">
|
||||
<Input
|
||||
placeholder="Filter tasks..."
|
||||
:model-value="(table.getColumn('title')?.getFilterValue() as string) ?? ''"
|
||||
class="h-8 w-[150px] lg:w-[250px]"
|
||||
@input="table.getColumn('title')?.setFilterValue($event.target.value)"
|
||||
/>
|
||||
<DataTableFacetedFilter
|
||||
v-if="table.getColumn('status')"
|
||||
:column="table.getColumn('status')"
|
||||
title="Status"
|
||||
:options="statuses"
|
||||
/>
|
||||
<DataTableFacetedFilter
|
||||
v-if="table.getColumn('priority')"
|
||||
:column="table.getColumn('priority')"
|
||||
title="Priority"
|
||||
:options="priorities"
|
||||
/>
|
||||
|
||||
<Button
|
||||
v-if="isFiltered"
|
||||
variant="ghost"
|
||||
class="h-8 px-2 lg:px-3"
|
||||
@click="table.resetColumnFilters()"
|
||||
>
|
||||
Reset
|
||||
<Cross2Icon class="ml-2 h-4 w-4" />
|
||||
</Button>
|
||||
</div>
|
||||
<DataTableViewOptions :table="table" />
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
<script setup lang="ts">
|
||||
import type { Table } from '@tanstack/vue-table'
|
||||
import { computed } from 'vue'
|
||||
import { type Task } from '../data/schema'
|
||||
import MixerHorizontalIcon from '~icons/radix-icons/mixer-horizontal'
|
||||
|
||||
import { Button } from '@/lib/registry/new-york/ui/button'
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuCheckboxItem,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
} from '@/lib/registry/new-york/ui/dropdown-menu'
|
||||
|
||||
interface DataTableViewOptionsProps {
|
||||
table: Table<Task>
|
||||
}
|
||||
|
||||
const props = defineProps<DataTableViewOptionsProps>()
|
||||
|
||||
const columns = computed(() => props.table.getAllColumns()
|
||||
.filter(
|
||||
column =>
|
||||
typeof column.accessorFn !== 'undefined' && column.getCanHide(),
|
||||
))
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger as-child>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
class="ml-auto hidden h-8 lg:flex"
|
||||
>
|
||||
<MixerHorizontalIcon class="mr-2 h-4 w-4" />
|
||||
View
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end" class="w-[150px]">
|
||||
<DropdownMenuLabel>Toggle columns</DropdownMenuLabel>
|
||||
<DropdownMenuSeparator />
|
||||
|
||||
<DropdownMenuCheckboxItem
|
||||
v-for="column in columns"
|
||||
:key="column.id"
|
||||
class="capitalize"
|
||||
:checked="column.getIsVisible()"
|
||||
@update:checked="(value) => column.toggleVisibility(!!value)"
|
||||
>
|
||||
{{ column.id }}
|
||||
</DropdownMenuCheckboxItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</template>
|
||||
64
apps/www/src/examples/big-data/components/UserNav.vue
Normal file
64
apps/www/src/examples/big-data/components/UserNav.vue
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
<script setup lang="ts">
|
||||
import {
|
||||
Avatar,
|
||||
AvatarFallback,
|
||||
AvatarImage,
|
||||
} from '@/lib/registry/new-york/ui/avatar'
|
||||
import { Button } from '@/lib/registry/new-york/ui/button'
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuGroup,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuShortcut,
|
||||
DropdownMenuTrigger,
|
||||
} from '@/lib/registry/new-york/ui/dropdown-menu'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger as-child>
|
||||
<Button variant="ghost" class="relative h-8 w-8 rounded-full">
|
||||
<Avatar class="h-9 w-9">
|
||||
<AvatarImage src="/avatars/03.png" alt="@shadcn" />
|
||||
<AvatarFallback>SC</AvatarFallback>
|
||||
</Avatar>
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent class="w-56" align="end">
|
||||
<DropdownMenuLabel class="font-normal flex">
|
||||
<div class="flex flex-col space-y-1">
|
||||
<p class="text-sm font-medium leading-none">
|
||||
shadcn
|
||||
</p>
|
||||
<p class="text-xs leading-none text-muted-foreground">
|
||||
m@example.com
|
||||
</p>
|
||||
</div>
|
||||
</DropdownMenuLabel>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuGroup>
|
||||
<DropdownMenuItem>
|
||||
Profile
|
||||
<DropdownMenuShortcut>⇧⌘P</DropdownMenuShortcut>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem>
|
||||
Billing
|
||||
<DropdownMenuShortcut>⌘B</DropdownMenuShortcut>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem>
|
||||
Settings
|
||||
<DropdownMenuShortcut>⌘S</DropdownMenuShortcut>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem>New Team</DropdownMenuItem>
|
||||
</DropdownMenuGroup>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem>
|
||||
Log out
|
||||
<DropdownMenuShortcut>⇧⌘Q</DropdownMenuShortcut>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</template>
|
||||
86
apps/www/src/examples/big-data/components/columns.ts
Normal file
86
apps/www/src/examples/big-data/components/columns.ts
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
import type { ColumnDef } from '@tanstack/vue-table'
|
||||
import { h } from 'vue'
|
||||
|
||||
import { labels, priorities, statuses } from '../data/data'
|
||||
import type { Task } from '../data/schema'
|
||||
import DataTableColumnHeader from './DataTableColumnHeader.vue'
|
||||
import DataTableRowActions from './DataTableRowActions.vue'
|
||||
import { Checkbox } from '@/lib/registry/new-york/ui/checkbox'
|
||||
import { Badge } from '@/lib/registry/new-york/ui/badge'
|
||||
|
||||
export const columns: ColumnDef<Task>[] = [
|
||||
{
|
||||
id: 'select',
|
||||
header: ({ table }) => h(Checkbox,
|
||||
{ 'checked': table.getIsAllPageRowsSelected(), 'onUpdate:checked': value => table.toggleAllPageRowsSelected(!!value), 'ariaLabel': 'Select all', 'class': 'translate-y-0.5' }),
|
||||
cell: ({ row }) => h(Checkbox,
|
||||
{ 'checked': row.getIsSelected(), 'onUpdate:checked': value => row.toggleSelected(!!value), 'ariaLabel': 'Select row', 'class': 'translate-y-0.5' }),
|
||||
enableSorting: false,
|
||||
enableHiding: false,
|
||||
},
|
||||
{
|
||||
accessorKey: 'id',
|
||||
header: ({ column }) => h(DataTableColumnHeader, { column, title: 'Task' }),
|
||||
cell: ({ row }) => h('div', { class: 'w-20' }, row.getValue('id')),
|
||||
enableSorting: false,
|
||||
enableHiding: false,
|
||||
},
|
||||
{
|
||||
accessorKey: 'title',
|
||||
header: ({ column }) => h(DataTableColumnHeader, { column, title: 'Title' }),
|
||||
|
||||
cell: ({ row }) => {
|
||||
const label = labels.find(label => label.value === row.original.label)
|
||||
|
||||
return h('div', { class: 'flex space-x-2' }, [
|
||||
label && h(Badge, { variant: 'outline' }, label.label),
|
||||
h('span', { class: 'max-w-[500px] truncate font-medium' }, row.getValue('title')),
|
||||
])
|
||||
},
|
||||
},
|
||||
{
|
||||
accessorKey: 'status',
|
||||
header: ({ column }) => h(DataTableColumnHeader, { column, title: 'Status' }),
|
||||
|
||||
cell: ({ row }) => {
|
||||
const status = statuses.find(
|
||||
status => status.value === row.getValue('status'),
|
||||
)
|
||||
|
||||
if (!status)
|
||||
return null
|
||||
|
||||
return h('div', { class: 'flex w-[100px] items-center' }, [
|
||||
status.icon && h(status.icon, { class: 'mr-2 h-4 w-4 text-muted-foreground' }),
|
||||
h('span', status.label),
|
||||
])
|
||||
},
|
||||
filterFn: (row, id, value) => {
|
||||
return value.includes(row.getValue(id))
|
||||
},
|
||||
},
|
||||
{
|
||||
accessorKey: 'priority',
|
||||
header: ({ column }) => h(DataTableColumnHeader, { column, title: 'Priority' }),
|
||||
cell: ({ row }) => {
|
||||
const priority = priorities.find(
|
||||
priority => priority.value === row.getValue('priority'),
|
||||
)
|
||||
|
||||
if (!priority)
|
||||
return null
|
||||
|
||||
return h('div', { class: 'flex items-center' }, [
|
||||
priority.icon && h(priority.icon, { class: 'mr-2 h-4 w-4 text-muted-foreground' }),
|
||||
h('span', priority.label),
|
||||
])
|
||||
},
|
||||
filterFn: (row, id, value) => {
|
||||
return value.includes(row.getValue(id))
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'actions',
|
||||
cell: ({ row }) => h(DataTableRowActions, { row }),
|
||||
},
|
||||
]
|
||||
70
apps/www/src/examples/big-data/data/data.ts
Normal file
70
apps/www/src/examples/big-data/data/data.ts
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
import { h } from 'vue'
|
||||
import ArrowDownIcon from '~icons/radix-icons/arrow-down'
|
||||
import ArrowRightIcon from '~icons/radix-icons/arrow-right'
|
||||
import ArrowUpIcon from '~icons/radix-icons/arrow-up'
|
||||
import CheckCircledIcon from '~icons/radix-icons/check-circled'
|
||||
import CircleIcon from '~icons/radix-icons/circle'
|
||||
import CrossCircledIcon from '~icons/radix-icons/cross-circled'
|
||||
import QuestionMarkCircledIcon from '~icons/radix-icons/question-mark-circled'
|
||||
import StopwatchIcon from '~icons/radix-icons/stopwatch'
|
||||
|
||||
export const labels = [
|
||||
{
|
||||
value: 'bug',
|
||||
label: 'Bug',
|
||||
},
|
||||
{
|
||||
value: 'feature',
|
||||
label: 'Feature',
|
||||
},
|
||||
{
|
||||
value: 'documentation',
|
||||
label: 'Documentation',
|
||||
},
|
||||
]
|
||||
|
||||
export const statuses = [
|
||||
{
|
||||
value: 'backlog',
|
||||
label: 'Backlog',
|
||||
icon: h(QuestionMarkCircledIcon),
|
||||
},
|
||||
{
|
||||
value: 'todo',
|
||||
label: 'Todo',
|
||||
icon: h(CircleIcon),
|
||||
},
|
||||
{
|
||||
value: 'in progress',
|
||||
label: 'In Progress',
|
||||
icon: h(StopwatchIcon),
|
||||
},
|
||||
{
|
||||
value: 'done',
|
||||
label: 'Done',
|
||||
icon: h(CheckCircledIcon),
|
||||
},
|
||||
{
|
||||
value: 'canceled',
|
||||
label: 'Canceled',
|
||||
icon: h(CrossCircledIcon),
|
||||
},
|
||||
]
|
||||
|
||||
export const priorities = [
|
||||
{
|
||||
label: 'Low',
|
||||
value: 'low',
|
||||
icon: h(ArrowDownIcon),
|
||||
},
|
||||
{
|
||||
label: 'Medium',
|
||||
value: 'medium',
|
||||
icon: h(ArrowRightIcon),
|
||||
},
|
||||
{
|
||||
label: 'High',
|
||||
value: 'high',
|
||||
icon: h(ArrowUpIcon),
|
||||
},
|
||||
]
|
||||
13
apps/www/src/examples/big-data/data/schema.ts
Normal file
13
apps/www/src/examples/big-data/data/schema.ts
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
import { z } from 'zod'
|
||||
|
||||
// We're keeping a simple non-relational schema here.
|
||||
// IRL, you will have a schema for your data models.
|
||||
export const taskSchema = z.object({
|
||||
id: z.string(),
|
||||
title: z.string(),
|
||||
status: z.string(),
|
||||
label: z.string(),
|
||||
priority: z.string(),
|
||||
})
|
||||
|
||||
export type Task = z.infer<typeof taskSchema>
|
||||
14002
apps/www/src/examples/big-data/data/tasks.json
Normal file
14002
apps/www/src/examples/big-data/data/tasks.json
Normal file
File diff suppressed because it is too large
Load Diff
|
|
@ -40,7 +40,7 @@ defineProps<DataTablePaginationProps>()
|
|||
<SelectValue :placeholder="`${table.getState().pagination.pageSize}`" />
|
||||
</SelectTrigger>
|
||||
<SelectContent side="top">
|
||||
<SelectItem v-for="pageSize in [10, 20, 30, 40, 50]" :key="pageSize" :value="`${pageSize}`">
|
||||
<SelectItem v-for="pageSize in [10, 20, 30, 40, 50, 100, 1000]" :key="pageSize" :value="`${pageSize}`">
|
||||
{{ pageSize }}
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -8,7 +8,7 @@ const props = defineProps<{
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<div class="relative w-full overflow-auto">
|
||||
<div class="relative w-full">
|
||||
<table :class="cn('w-full caption-bottom text-sm', props.class)">
|
||||
<slot />
|
||||
</table>
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ const props = defineProps<{
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<div class="relative w-full overflow-auto">
|
||||
<div class="relative w-full">
|
||||
<table :class="cn('w-full caption-bottom text-sm', props.class)">
|
||||
<slot />
|
||||
</table>
|
||||
|
|
|
|||
|
|
@ -179,7 +179,7 @@ importers:
|
|||
version: 2.2.1
|
||||
tailwindcss:
|
||||
specifier: ^3.4.1
|
||||
version: 3.4.1(ts-node@10.9.2)
|
||||
version: 3.4.1
|
||||
tsx:
|
||||
specifier: ^4.7.0
|
||||
version: 4.7.0
|
||||
|
|
@ -1123,6 +1123,7 @@ packages:
|
|||
engines: {node: '>=12'}
|
||||
dependencies:
|
||||
'@jridgewell/trace-mapping': 0.3.9
|
||||
dev: true
|
||||
|
||||
/@docsearch/css@3.5.2:
|
||||
resolution: {integrity: sha512-SPiDHaWKQZpwR2siD0KQUwlStvIAnEyK6tAE2h2Wuoq8ue9skzhlyVQ1ddzOxX6khULnAALDiR/isSF3bnuciA==}
|
||||
|
|
@ -2057,6 +2058,7 @@ packages:
|
|||
dependencies:
|
||||
'@jridgewell/resolve-uri': 3.1.1
|
||||
'@jridgewell/sourcemap-codec': 1.4.15
|
||||
dev: true
|
||||
|
||||
/@jsdevtools/ez-spawn@3.0.4:
|
||||
resolution: {integrity: sha512-f5DRIOZf7wxogefH03RjMPMdBF7ADTWUMoOs9kaJo06EfwF+aFhMZMDZxHg/Xe12hptN9xoZjGso2fdjapBRIA==}
|
||||
|
|
@ -3103,6 +3105,20 @@ packages:
|
|||
picomatch: 2.3.1
|
||||
dev: true
|
||||
|
||||
/@rollup/pluginutils@5.1.0:
|
||||
resolution: {integrity: sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
peerDependencies:
|
||||
rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0
|
||||
peerDependenciesMeta:
|
||||
rollup:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@types/estree': 1.0.5
|
||||
estree-walker: 2.0.2
|
||||
picomatch: 2.3.1
|
||||
dev: false
|
||||
|
||||
/@rollup/pluginutils@5.1.0(rollup@3.29.4):
|
||||
resolution: {integrity: sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
|
|
@ -3130,12 +3146,14 @@ packages:
|
|||
estree-walker: 2.0.2
|
||||
picomatch: 2.3.1
|
||||
rollup: 4.9.6
|
||||
dev: true
|
||||
|
||||
/@rollup/rollup-android-arm-eabi@4.9.6:
|
||||
resolution: {integrity: sha512-MVNXSSYN6QXOulbHpLMKYi60ppyO13W9my1qogeiAqtjb2yR4LSmfU2+POvDkLzhjYLXz9Rf9+9a3zFHW1Lecg==}
|
||||
cpu: [arm]
|
||||
os: [android]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@rollup/rollup-android-arm64@4.9.6:
|
||||
|
|
@ -3143,6 +3161,7 @@ packages:
|
|||
cpu: [arm64]
|
||||
os: [android]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@rollup/rollup-darwin-arm64@4.9.6:
|
||||
|
|
@ -3150,6 +3169,7 @@ packages:
|
|||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@rollup/rollup-darwin-x64@4.9.6:
|
||||
|
|
@ -3157,6 +3177,7 @@ packages:
|
|||
cpu: [x64]
|
||||
os: [darwin]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@rollup/rollup-linux-arm-gnueabihf@4.9.6:
|
||||
|
|
@ -3164,6 +3185,7 @@ packages:
|
|||
cpu: [arm]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@rollup/rollup-linux-arm64-gnu@4.9.6:
|
||||
|
|
@ -3171,6 +3193,7 @@ packages:
|
|||
cpu: [arm64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@rollup/rollup-linux-arm64-musl@4.9.6:
|
||||
|
|
@ -3178,6 +3201,7 @@ packages:
|
|||
cpu: [arm64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@rollup/rollup-linux-riscv64-gnu@4.9.6:
|
||||
|
|
@ -3185,6 +3209,7 @@ packages:
|
|||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@rollup/rollup-linux-x64-gnu@4.9.6:
|
||||
|
|
@ -3192,6 +3217,7 @@ packages:
|
|||
cpu: [x64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@rollup/rollup-linux-x64-musl@4.9.6:
|
||||
|
|
@ -3199,6 +3225,7 @@ packages:
|
|||
cpu: [x64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@rollup/rollup-win32-arm64-msvc@4.9.6:
|
||||
|
|
@ -3206,6 +3233,7 @@ packages:
|
|||
cpu: [arm64]
|
||||
os: [win32]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@rollup/rollup-win32-ia32-msvc@4.9.6:
|
||||
|
|
@ -3213,6 +3241,7 @@ packages:
|
|||
cpu: [ia32]
|
||||
os: [win32]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@rollup/rollup-win32-x64-msvc@4.9.6:
|
||||
|
|
@ -3220,6 +3249,7 @@ packages:
|
|||
cpu: [x64]
|
||||
os: [win32]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@rushstack/eslint-patch@1.7.2:
|
||||
|
|
@ -3355,15 +3385,19 @@ packages:
|
|||
|
||||
/@tsconfig/node10@1.0.9:
|
||||
resolution: {integrity: sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==}
|
||||
dev: true
|
||||
|
||||
/@tsconfig/node12@1.0.11:
|
||||
resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==}
|
||||
dev: true
|
||||
|
||||
/@tsconfig/node14@1.0.3:
|
||||
resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==}
|
||||
dev: true
|
||||
|
||||
/@tsconfig/node16@1.0.4:
|
||||
resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==}
|
||||
dev: true
|
||||
|
||||
/@tufjs/canonical-json@2.0.0:
|
||||
resolution: {integrity: sha512-yVtV8zsdo8qFHe+/3kw81dSLyF7D576A5cCFCi4X7B39tWT7SekaEFUnvnWJHz+9qO7qJTah1JbrDjWKqFtdWA==}
|
||||
|
|
@ -3719,6 +3753,7 @@ packages:
|
|||
|
||||
/@types/node@20.5.1:
|
||||
resolution: {integrity: sha512-4tT2UrL5LBqDwoed9wZ6N3umC4Yhz3W3FloMmiiG4JwmUJWpie0c7lcnUNd4gtMKuDEO4wRVS8B6Xa0uMRsMKg==}
|
||||
dev: true
|
||||
|
||||
/@types/normalize-package-data@2.4.4:
|
||||
resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==}
|
||||
|
|
@ -4581,6 +4616,7 @@ packages:
|
|||
/acorn-walk@8.3.2:
|
||||
resolution: {integrity: sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==}
|
||||
engines: {node: '>=0.4.0'}
|
||||
dev: true
|
||||
|
||||
/acorn@8.11.3:
|
||||
resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==}
|
||||
|
|
@ -4790,6 +4826,7 @@ packages:
|
|||
|
||||
/arg@4.1.3:
|
||||
resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==}
|
||||
dev: true
|
||||
|
||||
/arg@5.0.2:
|
||||
resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==}
|
||||
|
|
@ -5690,6 +5727,7 @@ packages:
|
|||
|
||||
/create-require@1.1.1:
|
||||
resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==}
|
||||
dev: true
|
||||
|
||||
/cross-spawn@5.1.0:
|
||||
resolution: {integrity: sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==}
|
||||
|
|
@ -6368,6 +6406,7 @@ packages:
|
|||
/diff@4.0.2:
|
||||
resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==}
|
||||
engines: {node: '>=0.3.1'}
|
||||
dev: true
|
||||
|
||||
/diff@5.1.0:
|
||||
resolution: {integrity: sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==}
|
||||
|
|
@ -8958,6 +8997,7 @@ packages:
|
|||
|
||||
/make-error@1.3.6:
|
||||
resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==}
|
||||
dev: true
|
||||
|
||||
/make-fetch-happen@13.0.0:
|
||||
resolution: {integrity: sha512-7ThobcL8brtGo9CavByQrQi+23aIfgYU++wg4B87AIS8Rb2ZBt/MEaDqzA00Xwv/jUjAjYkLHjVolYuTLKda2A==}
|
||||
|
|
@ -10447,6 +10487,22 @@ packages:
|
|||
camelcase-css: 2.0.1
|
||||
postcss: 8.4.33
|
||||
|
||||
/postcss-load-config@4.0.2(postcss@8.4.33):
|
||||
resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==}
|
||||
engines: {node: '>= 14'}
|
||||
peerDependencies:
|
||||
postcss: '>=8.0.9'
|
||||
ts-node: '>=9.0.0'
|
||||
peerDependenciesMeta:
|
||||
postcss:
|
||||
optional: true
|
||||
ts-node:
|
||||
optional: true
|
||||
dependencies:
|
||||
lilconfig: 3.0.0
|
||||
postcss: 8.4.33
|
||||
yaml: 2.3.4
|
||||
|
||||
/postcss-load-config@4.0.2(postcss@8.4.33)(ts-node@10.9.2):
|
||||
resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==}
|
||||
engines: {node: '>= 14'}
|
||||
|
|
@ -10463,6 +10519,7 @@ packages:
|
|||
postcss: 8.4.33
|
||||
ts-node: 10.9.2(@types/node@20.5.1)(typescript@5.3.3)
|
||||
yaml: 2.3.4
|
||||
dev: true
|
||||
|
||||
/postcss-merge-longhand@6.0.2(postcss@8.4.33):
|
||||
resolution: {integrity: sha512-+yfVB7gEM8SrCo9w2lCApKIEzrTKl5yS1F4yGhV3kSim6JzbfLGJyhR1B6X+6vOT0U33Mgx7iv4X9MVWuaSAfw==}
|
||||
|
|
@ -11227,6 +11284,7 @@ packages:
|
|||
'@rollup/rollup-win32-ia32-msvc': 4.9.6
|
||||
'@rollup/rollup-win32-x64-msvc': 4.9.6
|
||||
fsevents: 2.3.3
|
||||
dev: true
|
||||
|
||||
/run-applescript@7.0.0:
|
||||
resolution: {integrity: sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==}
|
||||
|
|
@ -11879,10 +11937,10 @@ packages:
|
|||
peerDependencies:
|
||||
tailwindcss: '>=3.0.0 || insiders'
|
||||
dependencies:
|
||||
tailwindcss: 3.4.1(ts-node@10.9.2)
|
||||
tailwindcss: 3.4.1
|
||||
dev: false
|
||||
|
||||
/tailwindcss@3.4.1(ts-node@10.9.2):
|
||||
/tailwindcss@3.4.1:
|
||||
resolution: {integrity: sha512-qAYmXRfk3ENzuPBakNK0SRrUDipP8NQnEY6772uDhflcQz5EhRdD7JNZxyrFHVQNCwULPBn6FNPp9brpO7ctcA==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
hasBin: true
|
||||
|
|
@ -11904,7 +11962,7 @@ packages:
|
|||
postcss: 8.4.33
|
||||
postcss-import: 15.1.0(postcss@8.4.33)
|
||||
postcss-js: 4.0.1(postcss@8.4.33)
|
||||
postcss-load-config: 4.0.2(postcss@8.4.33)(ts-node@10.9.2)
|
||||
postcss-load-config: 4.0.2(postcss@8.4.33)
|
||||
postcss-nested: 6.0.1(postcss@8.4.33)
|
||||
postcss-selector-parser: 6.0.15
|
||||
resolve: 1.22.8
|
||||
|
|
@ -12191,6 +12249,7 @@ packages:
|
|||
typescript: 5.3.3
|
||||
v8-compile-cache-lib: 3.0.1
|
||||
yn: 3.1.1
|
||||
dev: true
|
||||
|
||||
/tsconfck@3.0.1(typescript@5.3.3):
|
||||
resolution: {integrity: sha512-7ppiBlF3UEddCLeI1JRx5m2Ryq+xk4JrZuq4EuYXykipebaq1dV0Fhgr1hb7CkmHt32QSgOZlcqVLEtHBG4/mg==}
|
||||
|
|
@ -12452,7 +12511,7 @@ packages:
|
|||
/unimport@3.7.1:
|
||||
resolution: {integrity: sha512-V9HpXYfsZye5bPPYUgs0Otn3ODS1mDUciaBlXljI4C2fTwfFpvFZRywmlOu943puN9sncxROMZhsZCjNXEpzEQ==}
|
||||
dependencies:
|
||||
'@rollup/pluginutils': 5.1.0(rollup@4.9.6)
|
||||
'@rollup/pluginutils': 5.1.0
|
||||
acorn: 8.11.3
|
||||
escape-string-regexp: 5.0.0
|
||||
estree-walker: 3.0.3
|
||||
|
|
@ -12784,6 +12843,7 @@ packages:
|
|||
|
||||
/v8-compile-cache-lib@3.0.1:
|
||||
resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==}
|
||||
dev: true
|
||||
|
||||
/validate-npm-package-license@3.0.4:
|
||||
resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==}
|
||||
|
|
@ -13655,6 +13715,7 @@ packages:
|
|||
/yn@3.1.1:
|
||||
resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==}
|
||||
engines: {node: '>=6'}
|
||||
dev: true
|
||||
|
||||
/yocto-queue@0.1.0:
|
||||
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user