import { createColumnHelper } from '@tanstack/react-table' import { useAtom, useAtomValue, useSetAtom } from 'jotai' import { useMemo } from 'react' import { currentItemSelectionAtom, itemSelectionSetActionAtom, mouseDragSelectionStateAtom, } from '@/state/atoms' import { StatsColumns } from '../columns' import { ItemWithSelection } from './defs' const ch = createColumnHelper() const columns = { icon: ch.display({ id: 'icon', header: function Component(_col) { return
}, cell: function Component({ row }) { const setItemSelection = useSetAtom(itemSelectionSetActionAtom) const c = useAtomValue(currentItemSelectionAtom) const [dragState, setDragState] = useAtom(mouseDragSelectionStateAtom) const selected = useMemo(() => { return c[0].has(row.original.item.id) }, [c]) const handleMouseDown = (e: React.MouseEvent) => { e.preventDefault() const newSelected = !selected setItemSelection({ [row.original.item.id]: newSelected ? row.original.item.item_count : undefined, }) setDragState({ isDragging: true, lastAction: newSelected ? 'select' : 'deselect', lastItemId: row.original.item.id, }) } const handleMouseEnter = () => { if (dragState.isDragging && dragState.lastItemId !== row.original.item.id) { if (dragState.lastAction === 'select' && !selected) { setItemSelection({ [row.original.item.id]: row.original.item.item_count, }) } else if (dragState.lastAction === 'deselect' && selected) { setItemSelection({ [row.original.item.id]: undefined, }) } } } return ( ) }, }), count: ch.display({ id: 'count', header: function Component(_col) { return
#
}, cell: function Component({ row }) { const c = useAtomValue(currentItemSelectionAtom) const setItemSelection = useSetAtom(itemSelectionSetActionAtom) const dragState = useAtomValue(mouseDragSelectionStateAtom) const currentValue = useMemo(() => { const got = c[0].get(row.original.item.id) if (got !== undefined) { return got.toString() } return '' }, [c]) const itemCount = row.original.item.item_count const selected = useMemo(() => { return c[0].has(row.original.item.id) }, [c]) const handleMouseEnter = () => { if (dragState.isDragging && dragState.lastItemId !== row.original.item.id) { if (dragState.lastAction === 'select' && !selected) { setItemSelection({ [row.original.item.id]: row.original.item.item_count, }) } else if (dragState.lastAction === 'deselect' && selected) { setItemSelection({ [row.original.item.id]: undefined, }) } } } return ( // biome-ignore lint/a11y/useSemanticElements: Using div for layout with input child // biome-ignore lint/a11y/noStaticElementInteractions: Mouse interaction needed for drag select
{ if (e.target.value === '') { setItemSelection({ [row.original.item.id]: undefined }) return } if (e.target.value === '-') { setItemSelection({ [row.original.item.id]: itemCount, }) } let parsedInt = parseInt(e.target.value) if (Number.isNaN(parsedInt)) { return } if (parsedInt > itemCount) { parsedInt = itemCount } setItemSelection({ [row.original.item.id]: parsedInt, }) }} placeholder={itemCount.toString()} />
) }, }), name: ch.display({ id: 'name', header: _col => { return
name
}, cell: function Component({ row }) { const c = useAtomValue(currentItemSelectionAtom) const setItemSelection = useSetAtom(itemSelectionSetActionAtom) const [dragState, setDragState] = useAtom(mouseDragSelectionStateAtom) const selected = useMemo(() => { return c[0].has(row.original.item.id) }, [c]) const handleMouseEnter = () => { if (dragState.isDragging && dragState.lastItemId !== row.original.item.id) { if (dragState.lastAction === 'select' && !selected) { setItemSelection({ [row.original.item.id]: row.original.item.item_count, }) } else if (dragState.lastAction === 'deselect' && selected) { setItemSelection({ [row.original.item.id]: undefined, }) } } } const handleMouseDown = (e: React.MouseEvent) => { e.preventDefault() const newSelected = !selected setItemSelection({ [row.original.item.id]: newSelected ? row.original.item.item_count : undefined, }) setDragState({ isDragging: true, lastAction: newSelected ? 'select' : 'deselect', lastItemId: row.original.item.id, }) } return ( // biome-ignore lint/a11y/useSemanticElements: Using div for text content // biome-ignore lint/a11y/noStaticElementInteractions: Mouse interaction needed for drag select
{row.original.item.item_name}
) }, }), slots: ch.display({ id: 'slots', header: _col => { return
slots
}, cell: function Component({ row }) { return (
{row.original.item.item_slots}
) }, }), stats: ch.group({ id: 'stats', header: _col => { return
stats
}, columns: [ ...StatsColumns.map(c => { return ch.display({ id: `stats.${c}`, header: _col => { return
{c}
}, cell: function Component({ row }) { const stats = row.original.item.stats const stat = stats ? stats[c] : '' return (
{stat}
) }, }) }), ], }), } as const export const InventoryColumns = columns