feat(core): add column pinning and grouping features to Griddy table
- Implement column pinning functionality allowing users to pin columns to the left or right. - Introduce data grouping capabilities for better data organization. - Enhance the theming guide with new styles for pinned columns and loading indicators. - Add infinite scroll support with loading indicators for improved user experience. - Update CSS styles to accommodate new features and improve visual feedback.
This commit is contained in:
@@ -9,9 +9,10 @@ import { EditableCell } from './EditableCell'
|
||||
|
||||
interface TableCellProps<T> {
|
||||
cell: Cell<T, unknown>
|
||||
showGrouping?: boolean
|
||||
}
|
||||
|
||||
export function TableCell<T>({ cell }: TableCellProps<T>) {
|
||||
export function TableCell<T>({ cell, showGrouping }: TableCellProps<T>) {
|
||||
const isSelectionCol = cell.column.id === SELECTION_COLUMN_ID
|
||||
const isEditing = useGriddyStore((s) => s.isEditing)
|
||||
const focusedRowIndex = useGriddyStore((s) => s.focusedRowIndex)
|
||||
@@ -50,13 +51,45 @@ export function TableCell<T>({ cell }: TableCellProps<T>) {
|
||||
}
|
||||
}
|
||||
|
||||
const isPinned = cell.column.getIsPinned()
|
||||
const leftOffset = isPinned === 'left' ? cell.column.getStart('left') : undefined
|
||||
const rightOffset = isPinned === 'right' ? cell.column.getAfter('right') : undefined
|
||||
|
||||
const isGrouped = cell.getIsGrouped()
|
||||
const isAggregated = cell.getIsAggregated()
|
||||
const isPlaceholder = cell.getIsPlaceholder()
|
||||
|
||||
return (
|
||||
<div
|
||||
className={styles[CSS.cell]}
|
||||
className={[
|
||||
styles[CSS.cell],
|
||||
isPinned === 'left' ? styles['griddy-cell--pinned-left'] : '',
|
||||
isPinned === 'right' ? styles['griddy-cell--pinned-right'] : '',
|
||||
].filter(Boolean).join(' ')}
|
||||
onDoubleClick={handleDoubleClick}
|
||||
role="gridcell"
|
||||
style={{ width: cell.column.getSize() }}
|
||||
style={{
|
||||
left: leftOffset !== undefined ? `${leftOffset}px` : undefined,
|
||||
position: isPinned ? 'sticky' : 'relative',
|
||||
right: rightOffset !== undefined ? `${rightOffset}px` : undefined,
|
||||
width: cell.column.getSize(),
|
||||
zIndex: isPinned ? 1 : 0,
|
||||
}}
|
||||
>
|
||||
{showGrouping && isGrouped && (
|
||||
<button
|
||||
onClick={() => cell.row.toggleExpanded()}
|
||||
style={{
|
||||
border: 'none',
|
||||
background: 'none',
|
||||
cursor: 'pointer',
|
||||
marginRight: 4,
|
||||
padding: 0,
|
||||
}}
|
||||
>
|
||||
{cell.row.getIsExpanded() ? '\u25BC' : '\u25B6'}
|
||||
</button>
|
||||
)}
|
||||
{isFocusedCell && isEditable ? (
|
||||
<EditableCell
|
||||
cell={cell}
|
||||
@@ -64,7 +97,13 @@ export function TableCell<T>({ cell }: TableCellProps<T>) {
|
||||
onCancelEdit={handleCancel}
|
||||
onCommitEdit={handleCommit}
|
||||
/>
|
||||
) : (
|
||||
) : isGrouped ? (
|
||||
<>
|
||||
{flexRender(cell.column.columnDef.cell, cell.getContext())} ({cell.row.subRows.length})
|
||||
</>
|
||||
) : isAggregated ? (
|
||||
flexRender(cell.column.columnDef.aggregatedCell ?? cell.column.columnDef.cell, cell.getContext())
|
||||
) : isPlaceholder ? null : (
|
||||
flexRender(cell.column.columnDef.cell, cell.getContext())
|
||||
)}
|
||||
</div>
|
||||
@@ -73,12 +112,25 @@ export function TableCell<T>({ cell }: TableCellProps<T>) {
|
||||
|
||||
function RowCheckbox<T>({ cell }: TableCellProps<T>) {
|
||||
const row = cell.row
|
||||
const isPinned = cell.column.getIsPinned()
|
||||
const leftOffset = isPinned === 'left' ? cell.column.getStart('left') : undefined
|
||||
const rightOffset = isPinned === 'right' ? cell.column.getAfter('right') : undefined
|
||||
|
||||
return (
|
||||
<div
|
||||
className={styles[CSS.cell]}
|
||||
className={[
|
||||
styles[CSS.cell],
|
||||
isPinned === 'left' ? styles['griddy-cell--pinned-left'] : '',
|
||||
isPinned === 'right' ? styles['griddy-cell--pinned-right'] : '',
|
||||
].filter(Boolean).join(' ')}
|
||||
role="gridcell"
|
||||
style={{ width: cell.column.getSize() }}
|
||||
style={{
|
||||
left: leftOffset !== undefined ? `${leftOffset}px` : undefined,
|
||||
position: isPinned ? 'sticky' : 'relative',
|
||||
right: rightOffset !== undefined ? `${rightOffset}px` : undefined,
|
||||
width: cell.column.getSize(),
|
||||
zIndex: isPinned ? 1 : 0,
|
||||
}}
|
||||
>
|
||||
<Checkbox
|
||||
aria-label={`Select row ${row.index + 1}`}
|
||||
|
||||
Reference in New Issue
Block a user