From 191ca9e6c8daaa1d8a3cda4f52f9245d7f0e1827 Mon Sep 17 00:00:00 2001 From: kenneth Date: Wed, 17 Sep 2025 23:19:37 +0000 Subject: [PATCH] feat: impl file table selection --- packages/web/src/files/file-table.tsx | 45 +++++++++++++++++++-------- packages/web/src/files/state.ts | 3 ++ 2 files changed, 35 insertions(+), 13 deletions(-) diff --git a/packages/web/src/files/file-table.tsx b/packages/web/src/files/file-table.tsx index 8103fdc..7a1ebb6 100644 --- a/packages/web/src/files/file-table.tsx +++ b/packages/web/src/files/file-table.tsx @@ -67,7 +67,7 @@ const columns: ColumnDef[] = [ cell: ({ row }) => ( row.toggleSelected(!!value)} + onCheckedChange={row.getToggleSelectedHandler()} aria-label="Select row" /> ), @@ -129,6 +129,7 @@ export function FileTableContextMenu({ children: React.ReactNode }) { const store = useStore() + const target = useAtomValue(contextMenuTargeItemAtom) const setOptimisticDeletedItems = useSetAtom(optimisticDeletedItemsAtom) const moveToTrashMutation = useContextMutation(api.files.moveToTrash) const { mutate: moveToTrash } = useMutation({ @@ -167,16 +168,18 @@ export function FileTableContextMenu({ return ( {children} - - - - Rename - - - - Move to trash - - + {target && ( + + + + Rename + + + + Move to trash + + + )} ) } @@ -185,12 +188,19 @@ export function FileTableContent({ path }: { path: string }) { const directory = useQuery(api.files.fetchDirectoryContent, { path }) const optimisticDeletedItems = useAtomValue(optimisticDeletedItemsAtom) const setContextMenuTargetItem = useSetAtom(contextMenuTargeItemAtom) + const store = useStore() const handleRowContextMenu = ( row: Row, - event: React.MouseEvent, + _event: React.MouseEvent, ) => { - setContextMenuTargetItem(row.original) + const target = store.get(contextMenuTargeItemAtom) + if (target === row.original) { + setContextMenuTargetItem(null) + } else { + selectRow(row) + setContextMenuTargetItem(row.original) + } } const table = useReactTable({ @@ -202,8 +212,14 @@ export function FileTableContent({ path }: { path: string }) { globalFilterFn: (row, _columnId, _filterValue, _addMeta) => { return !optimisticDeletedItems.has(row.original.doc._id) }, + getRowId: (row) => row.doc._id, }) + const selectRow = (row: Row) => { + table.toggleAllPageRowsSelected(false) + row.toggleSelected(true) + } + if (!directory) { return null } @@ -237,6 +253,9 @@ export function FileTableContent({ path }: { path: string }) { { + selectRow(row) + }} onContextMenu={(e) => { handleRowContextMenu(row, e) }} diff --git a/packages/web/src/files/state.ts b/packages/web/src/files/state.ts index 043d119..632441c 100644 --- a/packages/web/src/files/state.ts +++ b/packages/web/src/files/state.ts @@ -3,6 +3,7 @@ import type { DirectoryItem, DirectoryItemKind, } from "@fileone/convex/model/directories" +import type { RowSelectionState } from "@tanstack/react-table" import { atom } from "jotai" export const contextMenuTargeItemAtom = atom(null) @@ -10,4 +11,6 @@ export const optimisticDeletedItemsAtom = atom( new Set | Id<"directories">>(), ) +export const selectedFileRowsAtom = atom({}) + export const newItemKindAtom = atom(null)