Skip to content

Commit

Permalink
feat: update data-table sortable]
Browse files Browse the repository at this point in the history
  • Loading branch information
sadmann7 committed May 11, 2024
1 parent 6c420b9 commit adf0941
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 123 deletions.
193 changes: 96 additions & 97 deletions src/app/_components/hook-form-demo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,106 +53,105 @@ export function HookFormDemo() {
})

return (
<Form {...form}>
<form
onSubmit={form.handleSubmit(onSubmit)}
className="flex w-full max-w-4xl flex-col gap-4 rounded-md border p-6"
>
<div className="space-y-1">
<h4>Flip tricks</h4>
<p className="text-[0.8rem] text-muted-foreground">
Add your favorite flip tricks
</p>
</div>
<Sortable
value={fields}
onValueChange={(value) => form.setValue("flipTricks", value)}
overlay={
<div className="grid grid-cols-[0.5fr,1fr,auto,auto] items-center gap-2">
<Skeleton className="h-8 w-full rounded-sm" />
<Skeleton className="h-8 w-full rounded-sm" />
<Skeleton className="size-8 shrink-0 rounded-sm" />
<Skeleton className="size-8 shrink-0 rounded-sm" />
</div>
}
<div className="rounded-lg border p-6">
<Form {...form}>
<form
onSubmit={form.handleSubmit(onSubmit)}
className="flex w-full max-w-4xl flex-col gap-4"
>
<div className="w-full space-y-1.5">
{fields.map((field, index) => (
<SortableItem
key={field.id}
value={field.id}
className="py-0.5"
asChild
>
<div className="space-y-1">
<h4>Flip tricks</h4>
<p className="text-[0.8rem] text-muted-foreground">
Add your favorite flip tricks
</p>
</div>
<div className="space-y-2">
<Sortable
value={fields}
onValueChange={(value) => form.setValue("flipTricks", value)}
overlay={
<div className="grid grid-cols-[0.5fr,1fr,auto,auto] items-center gap-2">
<FormField
control={form.control}
name={`flipTricks.${index}.name`}
render={({ field }) => (
<FormItem>
<FormControl>
<Input className="h-8" {...field} />
</FormControl>
</FormItem>
)}
/>
<FormField
control={form.control}
name={`flipTricks.${index}.spin`}
render={({ field }) => (
<FormItem>
<FormControl>
<Input className="h-8" {...field} />
</FormControl>
</FormItem>
)}
/>
<SortableDragHandle
variant="outline"
size="icon"
className="size-8 shrink-0"
>
<DragHandleDots2Icon
className="size-4"
aria-hidden="true"
/>
</SortableDragHandle>
<Button
type="button"
variant="outline"
size="icon"
className="size-8 shrink-0"
onClick={() => remove(index)}
>
<TrashIcon
className="size-4 text-destructive"
aria-hidden="true"
/>
<span className="sr-only">Remove</span>
</Button>
<Skeleton className="h-8 w-full rounded-sm" />
<Skeleton className="h-8 w-full rounded-sm" />
<Skeleton className="size-8 shrink-0 rounded-sm" />
<Skeleton className="size-8 shrink-0 rounded-sm" />
</div>
</SortableItem>
))}
}
>
<div className="w-full space-y-2">
{fields.map((field, index) => (
<SortableItem key={field.id} value={field.id} asChild>
<div className="grid grid-cols-[0.5fr,1fr,auto,auto] items-center gap-2">
<FormField
control={form.control}
name={`flipTricks.${index}.name`}
render={({ field }) => (
<FormItem>
<FormControl>
<Input className="h-8" {...field} />
</FormControl>
</FormItem>
)}
/>
<FormField
control={form.control}
name={`flipTricks.${index}.spin`}
render={({ field }) => (
<FormItem>
<FormControl>
<Input className="h-8" {...field} />
</FormControl>
</FormItem>
)}
/>
<SortableDragHandle
variant="outline"
size="icon"
className="size-8 shrink-0"
>
<DragHandleDots2Icon
className="size-4"
aria-hidden="true"
/>
</SortableDragHandle>
<Button
type="button"
variant="outline"
size="icon"
className="size-8 shrink-0"
onClick={() => remove(index)}
>
<TrashIcon
className="size-4 text-destructive"
aria-hidden="true"
/>
<span className="sr-only">Remove</span>
</Button>
</div>
</SortableItem>
))}
</div>
</Sortable>
<Button
type="button"
variant="outline"
size="sm"
className="w-fit"
onClick={() =>
append({
name: "",
spin: "",
})
}
>
Add trick
</Button>
</div>
</Sortable>
<Button
type="button"
variant="outline"
size="sm"
className="w-fit"
onClick={() =>
append({
name: "",
spin: "",
})
}
>
Add trick
</Button>
<Button type="submit" className="w-fit">
Submit
</Button>
</form>
</Form>
<Button type="submit" className="w-fit">
Submit
</Button>
</form>
</Form>
</div>
)
}
58 changes: 35 additions & 23 deletions src/app/data-table/_components/data-table-demo.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
"use client"

import * as React from "react"
import { DragEndEvent } from "@dnd-kit/core"
import {
CaretSortIcon,
ChevronDownIcon,
Expand Down Expand Up @@ -150,7 +149,6 @@ export const columns: ColumnDef<Payment>[] = [
},
{
id: "actions",
enableHiding: false,
cell: ({ row }) => {
const payment = row.original

Expand All @@ -176,15 +174,15 @@ export const columns: ColumnDef<Payment>[] = [
</DropdownMenu>
)
},
enableHiding: false,
enableSorting: false,
},
{
id: "sortable",
cell: ({ cell }) => (
<SortableItem value={cell.id} asChild>
<SortableDragHandle variant="ghost" size="icon" className="size-8">
<DragHandleDots2Icon className="size-4" aria-hidden="true" />
</SortableDragHandle>
</SortableItem>
id: "drag",
cell: () => (
<SortableDragHandle variant="ghost" size="icon" className="size-8">
<DragHandleDots2Icon className="size-4" aria-hidden="true" />
</SortableDragHandle>
),
enableSorting: false,
enableHiding: false,
Expand Down Expand Up @@ -279,22 +277,36 @@ export function DataTableDemo() {
))}
</TableHeader>
<TableBody>
<Sortable value={data} onValueChange={setData}>
<Sortable
value={data}
onValueChange={setData}
overlay={
<Table>
<TableBody>
<TableRow>
<Skeleton className="h-12 w-full" />
</TableRow>
</TableBody>
</Table>
}
>
{table.getRowModel().rows?.length ? (
table.getRowModel().rows.map((row) => (
<TableRow
key={row.id}
data-state={row.getIsSelected() && "selected"}
>
{row.getVisibleCells().map((cell) => (
<TableCell key={cell.id}>
{flexRender(
cell.column.columnDef.cell,
cell.getContext()
)}
</TableCell>
))}
</TableRow>
<SortableItem key={row.id} value={row.original.id} asChild>
<TableRow
key={row.id}
data-state={row.getIsSelected() && "selected"}
>
{row.getVisibleCells().map((cell) => (
<TableCell key={cell.id}>
{flexRender(
cell.column.columnDef.cell,
cell.getContext()
)}
</TableCell>
))}
</TableRow>
</SortableItem>
))
) : (
<TableRow>
Expand Down
13 changes: 10 additions & 3 deletions src/components/ui/sortable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,13 @@ interface SortableProps<TData extends { id: UniqueIdentifier }>
*/
onMove?: (event: { activeIndex: number; overIndex: number }) => void

/**
* A collision detection strategy that will be used to determine the closest sortable item.
* @default closestCenter
* @type DndContextProps["collisionDetection"]
*/
collisionDetection?: DndContextProps["collisionDetection"]

/**
* An array of modifiers that will be used to modify the behavior of the sortable component.
* @default [restrictToVerticalAxis, restrictToParentElement]
Expand Down Expand Up @@ -147,7 +154,7 @@ function Sortable<TData extends { id: UniqueIdentifier }>({
)
}

const dropAnimationConfig: DropAnimation = {
const dropAnimationOpts: DropAnimation = {
sideEffects: defaultDropAnimationSideEffects({
styles: {
active: {
Expand All @@ -164,7 +171,7 @@ interface SortableOverlayProps

function SortableOverlay({
activeId,
dropAnimation = dropAnimationConfig,
dropAnimation = dropAnimationOpts,
children,
...props
}: SortableOverlayProps) {
Expand Down Expand Up @@ -266,4 +273,4 @@ const SortableDragHandle = React.forwardRef<
})
SortableDragHandle.displayName = "SortableDragHandle"

export { Sortable, SortableDragHandle, SortableItem }
export { Sortable, SortableDragHandle, SortableItem, SortableOverlay }

0 comments on commit adf0941

Please sign in to comment.