Skip to content

Commit

Permalink
add editable feature
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexBHdez committed Jan 20, 2025
1 parent b17e2a2 commit 164bb66
Show file tree
Hide file tree
Showing 5 changed files with 354 additions and 44 deletions.
62 changes: 62 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -146,9 +146,11 @@
"@rollup/rollup-linux-x64-gnu": "^4.30"
},
"dependencies": {
"@tanstack/react-table": "^8.20.6",
"@tanstack/react-virtual": "^3.11.2",
"embla-carousel-autoplay": "^8.5.2",
"embla-carousel-react": "^8.5.1",
"embla-carousel-wheel-gestures": "^8.0.1",
"vaul": "^1.1.2"
}
}
}
126 changes: 126 additions & 0 deletions src/playground/Collections/Table/features/selection.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import {
OnChangeFn,
RowData,
TableFeature,
Table as TanstackTable,
makeStateUpdater,
} from "@tanstack/react-table"

export type SelectionState = {
selectedCells: Set<string>
}

export interface SelectionTableState {
selection: SelectionState
}

export interface SelectionOptions {
enableSelection?: boolean
onSelectionChange?: OnChangeFn<SelectionState>
}

export interface SelectionInstance {
toggleCellSelection: (rowIndex: number, columnId: string) => void
toggleColumnSelection: (columnId: string) => void
getIsCellSelected: (rowIndex: number, columnId: string) => boolean
getIsColumnSelected: (columnId: string) => boolean
}

declare module "@tanstack/react-table" {
interface TableState {
selection: SelectionState
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
interface TableOptionsResolved<TData extends RowData> {
enableSelection?: boolean
onSelectionChange?: OnChangeFn<SelectionState>
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
interface Table<TData extends RowData> {
toggleCellSelection: (rowIndex: number, columnId: string) => void
toggleColumnSelection: (columnId: string) => void
getIsCellSelected: (rowIndex: number, columnId: string) => boolean
getIsColumnSelected: (columnId: string) => boolean
}
}

export const SelectionFeature: TableFeature = {
getInitialState: (state): SelectionTableState => {
return {
selection: {
selectedCells: new Set<string>(),
},
...state,
}
},

getDefaultOptions: <TData extends RowData>(
table: TanstackTable<TData>
): SelectionOptions => {
return {
enableSelection: true,
onSelectionChange: makeStateUpdater("selection", table),
}
},

createTable: <TData extends RowData>(table: TanstackTable<TData>): void => {
table.toggleCellSelection = (rowIndex: number, columnId: string) => {
if (table.options.enableSelection === false) return

table.options.onSelectionChange?.((old: SelectionState) => {
const newSelection = { ...old }
const cellId = `${rowIndex}-${columnId}`

if (newSelection.selectedCells.has(cellId)) {
newSelection.selectedCells.delete(cellId)
} else {
newSelection.selectedCells.add(cellId)
}

return newSelection
})
}

table.toggleColumnSelection = (columnId: string) => {
if (table.options.enableSelection === false) return

table.options.onSelectionChange?.((old: SelectionState) => {
const newSelection = { ...old }
const isColumnFullySelected = table
.getCoreRowModel()
.rows.every((row) =>
newSelection.selectedCells.has(`${row.index}-${columnId}`)
)

if (isColumnFullySelected) {
table.getCoreRowModel().rows.forEach((row) => {
newSelection.selectedCells.delete(`${row.index}-${columnId}`)
})
} else {
table.getCoreRowModel().rows.forEach((row) => {
newSelection.selectedCells.add(`${row.index}-${columnId}`)
})
}

return newSelection
})
}

table.getIsCellSelected = (rowIndex: number, columnId: string) => {
const cellId = `${rowIndex}-${columnId}`
return table.getState().selection.selectedCells.has(cellId)
}

table.getIsColumnSelected = (columnId: string) => {
return table
.getCoreRowModel()
.rows.every((row) =>
table
.getState()
.selection.selectedCells.has(`${row.index}-${columnId}`)
)
}
},
}
24 changes: 15 additions & 9 deletions src/playground/Collections/Table/index.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { Meta, StoryObj } from "@storybook/react"

import { Badge } from "@/factorial-one"
import { PersonAvatar } from "@/experimental/exports"
import { Column, Table } from "."

type RowData = {
Expand Down Expand Up @@ -52,14 +52,10 @@ const generateRowData = (count = 4000): RowData[] => {
employeeGroupId: randomNumber(1, 3),
managerId: randomNumber(1, 1),
employee: () => (
<Badge
avatar={{
alt: `${firstName[0]}${lastName[0]}`,
src: "https://github.com/dani-moreno.png",
}}
text={`${firstName} ${lastName}`}
variant="name"
/>
<>
<PersonAvatar firstName={firstName} lastName={lastName} />
<span className="text-base">{`${firstName} ${lastName}`}</span>
</>
),
}
})
Expand All @@ -69,6 +65,9 @@ const columns: Column<RowData>[] = [
{
accessorKey: "employee",
header: "Employee",
meta: {
hideCheckbox: true,
},
},
{
accessorKey: "firstName",
Expand Down Expand Up @@ -115,6 +114,13 @@ const meta: Meta = {
columns,
data: generateRowData(),
},
decorators: [
(Story) => (
<div style={{ height: "100vh" }}>
<Story />
</div>
),
],
}

export default meta
Expand Down
Loading

0 comments on commit 164bb66

Please sign in to comment.