feat(web): 支持渠道列表手动调整列宽 (#5948)
* 支持渠道表格列宽拖拽 * fix(web): address column resize review feedback * feat(web): auto-fit resized table columns * fix(web): reduce column resize persistence work --------- Signed-off-by: zuiho <2324465096@qq.com>
This commit is contained in:
@@ -34,9 +34,12 @@ export function DataTableColgroup<TData>({
|
||||
return (
|
||||
<colgroup>
|
||||
{columns.map((column) => {
|
||||
const width = isContentSizedColumn(column.id)
|
||||
? undefined
|
||||
: getColumnWidth(column.getSize(), totalSize)
|
||||
const width = getColumnWidth(
|
||||
table,
|
||||
column.id,
|
||||
column.getSize(),
|
||||
totalSize
|
||||
)
|
||||
|
||||
return <col key={column.id} style={{ width }} />
|
||||
})}
|
||||
@@ -44,7 +47,20 @@ export function DataTableColgroup<TData>({
|
||||
)
|
||||
}
|
||||
|
||||
function getColumnWidth(columnSize: number, totalSize: number) {
|
||||
function getColumnWidth<TData>(
|
||||
table: TanstackTable<TData>,
|
||||
columnId: string,
|
||||
columnSize: number,
|
||||
totalSize: number
|
||||
) {
|
||||
if (isContentSizedColumn(columnId)) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
if (table.options.enableColumnResizing === true) {
|
||||
return `${columnSize}px`
|
||||
}
|
||||
|
||||
if (totalSize <= 0) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
@@ -21,8 +21,11 @@ import {
|
||||
type Header,
|
||||
type Table as TanstackTable,
|
||||
} from '@tanstack/react-table'
|
||||
import type { KeyboardEvent, MouseEvent } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
import { TableHead, TableHeader, TableRow } from '@/components/ui/table'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
import { DataTableColumnHeader } from './column-header'
|
||||
import { isContentSizedColumn } from './content-sized-columns'
|
||||
@@ -43,6 +46,8 @@ export function DataTableHeader<TData>({
|
||||
rowClassName,
|
||||
getColumnClassName,
|
||||
}: DataTableHeaderProps<TData>) {
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<TableHeader className={className}>
|
||||
{table.getHeaderGroups().map((headerGroup) => (
|
||||
@@ -51,10 +56,36 @@ export function DataTableHeader<TData>({
|
||||
<TableHead
|
||||
key={header.id}
|
||||
colSpan={header.colSpan}
|
||||
className={getColumnClassName?.(header.column.id, 'header')}
|
||||
data-column-id={header.column.id}
|
||||
className={cn(
|
||||
'relative',
|
||||
getColumnClassName?.(header.column.id, 'header')
|
||||
)}
|
||||
style={getHeaderSizeStyle(header, applyHeaderSize)}
|
||||
>
|
||||
{renderHeaderContent(header)}
|
||||
{shouldRenderColumnResizer(table, header) && (
|
||||
<div
|
||||
role='separator'
|
||||
aria-orientation='vertical'
|
||||
aria-label={t('Resize column')}
|
||||
data-column-resizer
|
||||
tabIndex={0}
|
||||
onDoubleClick={(event) =>
|
||||
handleColumnAutoSize(event, table, header)
|
||||
}
|
||||
onMouseDown={header.getResizeHandler()}
|
||||
onTouchStart={header.getResizeHandler()}
|
||||
onKeyDown={(event) =>
|
||||
handleColumnResizeKeyDown(event, table, header)
|
||||
}
|
||||
className={cn(
|
||||
'absolute top-0 right-0 h-full w-2 cursor-col-resize touch-none select-none',
|
||||
'after:bg-border hover:after:bg-primary after:absolute after:top-2 after:right-0 after:h-[calc(100%-1rem)] after:w-px after:transition-colors',
|
||||
header.column.getIsResizing() && 'after:bg-primary'
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
</TableHead>
|
||||
))}
|
||||
</TableRow>
|
||||
@@ -63,6 +94,161 @@ export function DataTableHeader<TData>({
|
||||
)
|
||||
}
|
||||
|
||||
function handleColumnResizeKeyDown<TData>(
|
||||
event: KeyboardEvent<HTMLDivElement>,
|
||||
table: TanstackTable<TData>,
|
||||
header: Header<TData, unknown>
|
||||
) {
|
||||
const step = event.shiftKey ? 50 : 10
|
||||
|
||||
if (event.key === 'ArrowLeft') {
|
||||
event.preventDefault()
|
||||
resizeColumnByKeyboard(table, header, -step)
|
||||
return
|
||||
}
|
||||
|
||||
if (event.key === 'ArrowRight') {
|
||||
event.preventDefault()
|
||||
resizeColumnByKeyboard(table, header, step)
|
||||
return
|
||||
}
|
||||
|
||||
if (event.key === 'Enter' || event.key === ' ') {
|
||||
event.preventDefault()
|
||||
autoSizeColumn(event.currentTarget, table, header)
|
||||
}
|
||||
}
|
||||
|
||||
function resizeColumnByKeyboard<TData>(
|
||||
table: TanstackTable<TData>,
|
||||
header: Header<TData, unknown>,
|
||||
delta: number
|
||||
) {
|
||||
table.setColumnSizing((previous) => ({
|
||||
...previous,
|
||||
[header.column.id]: getClampedColumnSize(
|
||||
header,
|
||||
header.column.getSize() + delta
|
||||
),
|
||||
}))
|
||||
}
|
||||
|
||||
function handleColumnAutoSize<TData>(
|
||||
event: MouseEvent<HTMLDivElement>,
|
||||
table: TanstackTable<TData>,
|
||||
header: Header<TData, unknown>
|
||||
) {
|
||||
event.preventDefault()
|
||||
autoSizeColumn(event.currentTarget, table, header)
|
||||
}
|
||||
|
||||
function autoSizeColumn<TData>(
|
||||
resizerElement: HTMLElement,
|
||||
table: TanstackTable<TData>,
|
||||
header: Header<TData, unknown>
|
||||
) {
|
||||
const measuredSize = measureColumnContentWidth(
|
||||
resizerElement,
|
||||
header.column.id
|
||||
)
|
||||
|
||||
if (measuredSize === undefined) {
|
||||
return
|
||||
}
|
||||
|
||||
table.setColumnSizing((previous) => ({
|
||||
...previous,
|
||||
[header.column.id]: getClampedColumnSize(header, measuredSize),
|
||||
}))
|
||||
}
|
||||
|
||||
function getClampedColumnSize<TData>(
|
||||
header: Header<TData, unknown>,
|
||||
nextSize: number
|
||||
) {
|
||||
const { minSize, maxSize } = header.column.columnDef
|
||||
|
||||
if (typeof minSize === 'number' && nextSize < minSize) {
|
||||
return minSize
|
||||
}
|
||||
|
||||
if (typeof maxSize === 'number' && nextSize > maxSize) {
|
||||
return maxSize
|
||||
}
|
||||
|
||||
return nextSize
|
||||
}
|
||||
|
||||
function measureColumnContentWidth(
|
||||
resizerElement: HTMLElement,
|
||||
columnId: string
|
||||
) {
|
||||
const tableElement = resizerElement.closest('table')
|
||||
if (!tableElement) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
const cells = tableElement.querySelectorAll<HTMLElement>(
|
||||
getColumnElementSelector(columnId)
|
||||
)
|
||||
if (cells.length === 0) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
const measuredWidth = [...cells].reduce(
|
||||
(maxWidth, cell) => Math.max(maxWidth, measureElementWidth(cell)),
|
||||
0
|
||||
)
|
||||
|
||||
return measuredWidth > 0 ? Math.ceil(measuredWidth) : undefined
|
||||
}
|
||||
|
||||
function measureElementWidth(element: HTMLElement) {
|
||||
const clone = element.cloneNode(true) as HTMLElement
|
||||
|
||||
clone.querySelectorAll('[data-column-resizer]').forEach((resizer) => {
|
||||
resizer.remove()
|
||||
})
|
||||
|
||||
clone.style.position = 'absolute'
|
||||
clone.style.visibility = 'hidden'
|
||||
clone.style.pointerEvents = 'none'
|
||||
clone.style.left = '-10000px'
|
||||
clone.style.top = '0'
|
||||
clone.style.width = 'max-content'
|
||||
clone.style.minWidth = '0'
|
||||
clone.style.maxWidth = 'none'
|
||||
clone.style.height = 'auto'
|
||||
clone.style.whiteSpace = 'nowrap'
|
||||
|
||||
document.body.append(clone)
|
||||
const width = clone.scrollWidth
|
||||
clone.remove()
|
||||
|
||||
return width
|
||||
}
|
||||
|
||||
function getColumnElementSelector(columnId: string) {
|
||||
const escapedColumnId =
|
||||
typeof CSS !== 'undefined' && typeof CSS.escape === 'function'
|
||||
? CSS.escape(columnId)
|
||||
: columnId.replaceAll('\\', '\\\\').replaceAll('"', '\\"')
|
||||
|
||||
return `[data-column-id="${escapedColumnId}"]`
|
||||
}
|
||||
|
||||
function shouldRenderColumnResizer<TData>(
|
||||
table: TanstackTable<TData>,
|
||||
header: Header<TData, unknown>
|
||||
) {
|
||||
return (
|
||||
table.options.enableColumnResizing === true &&
|
||||
!header.isPlaceholder &&
|
||||
header.column.getCanResize() &&
|
||||
!isContentSizedColumn(header.column.id)
|
||||
)
|
||||
}
|
||||
|
||||
function getHeaderSizeStyle<TData>(
|
||||
header: Header<TData, unknown>,
|
||||
applyHeaderSize: boolean | undefined
|
||||
|
||||
@@ -65,6 +65,7 @@ function DataTableRowInner<TData>({
|
||||
return (
|
||||
<TableCell
|
||||
key={cell.id}
|
||||
data-column-id={cell.column.id}
|
||||
className={cn(
|
||||
'max-w-full min-w-0',
|
||||
renderedCell.isPrimitive && 'overflow-hidden',
|
||||
|
||||
@@ -19,6 +19,7 @@ For commercial licensing, please contact support@quantumnous.com
|
||||
import {
|
||||
type ColumnDef,
|
||||
type ColumnFiltersState,
|
||||
type ColumnSizingState,
|
||||
type ExpandedState,
|
||||
type OnChangeFn,
|
||||
type PaginationState,
|
||||
@@ -48,6 +49,7 @@ type DataTableFeatureOptions<TData> = Pick<
|
||||
| 'manualFiltering'
|
||||
| 'manualPagination'
|
||||
| 'manualSorting'
|
||||
| 'enableColumnResizing'
|
||||
>
|
||||
|
||||
type DataTableStateOptions = {
|
||||
@@ -58,6 +60,10 @@ type DataTableStateOptions = {
|
||||
columnVisibilityStorageKey?: string | false
|
||||
columnVisibility?: VisibilityState
|
||||
onColumnVisibilityChange?: OnChangeFn<VisibilityState>
|
||||
initialColumnSizing?: ColumnSizingState
|
||||
columnSizingStorageKey?: string | false
|
||||
columnSizing?: ColumnSizingState
|
||||
onColumnSizingChange?: OnChangeFn<ColumnSizingState>
|
||||
initialRowSelection?: RowSelectionState
|
||||
rowSelection?: RowSelectionState
|
||||
onRowSelectionChange?: OnChangeFn<RowSelectionState>
|
||||
@@ -91,6 +97,21 @@ type UseDataTableOptions<TData> = DataTableFeatureOptions<TData> &
|
||||
ensurePageInRange?: (pageCount: number) => void
|
||||
}
|
||||
|
||||
type ColumnSizingBounds = Record<
|
||||
string,
|
||||
{
|
||||
minSize?: number
|
||||
maxSize?: number
|
||||
}
|
||||
>
|
||||
|
||||
type ColumnWithSizing<TData> = ColumnDef<TData, unknown> & {
|
||||
accessorKey?: string | number
|
||||
columns?: ColumnDef<TData, unknown>[]
|
||||
}
|
||||
|
||||
const COLUMN_SIZING_PERSIST_DELAY_MS = 250
|
||||
|
||||
function resolveUpdater<TValue>(
|
||||
updater: Updater<TValue>,
|
||||
previous: TValue
|
||||
@@ -149,6 +170,110 @@ function readColumnVisibility(storageKey: string | undefined): VisibilityState {
|
||||
}
|
||||
}
|
||||
|
||||
function getColumnId<TData>(column: ColumnDef<TData, unknown>) {
|
||||
const columnWithSizing = column as ColumnWithSizing<TData>
|
||||
|
||||
if (typeof columnWithSizing.id === 'string') {
|
||||
return columnWithSizing.id
|
||||
}
|
||||
|
||||
if (typeof columnWithSizing.accessorKey === 'string') {
|
||||
return columnWithSizing.accessorKey.replaceAll('.', '_')
|
||||
}
|
||||
|
||||
if (typeof columnWithSizing.accessorKey === 'number') {
|
||||
return String(columnWithSizing.accessorKey)
|
||||
}
|
||||
|
||||
return undefined
|
||||
}
|
||||
|
||||
function buildColumnSizingBounds<TData>(
|
||||
columns: ColumnDef<TData, unknown>[]
|
||||
): ColumnSizingBounds {
|
||||
return columns.reduce<ColumnSizingBounds>((bounds, column) => {
|
||||
const columnWithSizing = column as ColumnWithSizing<TData>
|
||||
const columnId = getColumnId(column)
|
||||
|
||||
if (columnId) {
|
||||
const minSize =
|
||||
typeof columnWithSizing.minSize === 'number' &&
|
||||
Number.isFinite(columnWithSizing.minSize)
|
||||
? columnWithSizing.minSize
|
||||
: undefined
|
||||
const maxSize =
|
||||
typeof columnWithSizing.maxSize === 'number' &&
|
||||
Number.isFinite(columnWithSizing.maxSize)
|
||||
? columnWithSizing.maxSize
|
||||
: undefined
|
||||
|
||||
if (minSize !== undefined || maxSize !== undefined) {
|
||||
bounds[columnId] = { minSize, maxSize }
|
||||
}
|
||||
}
|
||||
|
||||
if (Array.isArray(columnWithSizing.columns)) {
|
||||
Object.assign(bounds, buildColumnSizingBounds(columnWithSizing.columns))
|
||||
}
|
||||
|
||||
return bounds
|
||||
}, {})
|
||||
}
|
||||
|
||||
function getBoundedColumnSize(
|
||||
columnId: string,
|
||||
value: unknown,
|
||||
bounds: ColumnSizingBounds
|
||||
) {
|
||||
if (typeof value !== 'number' || !Number.isFinite(value) || value <= 0) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
const columnBounds = bounds[columnId]
|
||||
let size = value
|
||||
|
||||
if (columnBounds?.minSize !== undefined && size < columnBounds.minSize) {
|
||||
size = columnBounds.minSize
|
||||
}
|
||||
|
||||
if (columnBounds?.maxSize !== undefined && size > columnBounds.maxSize) {
|
||||
size = columnBounds.maxSize
|
||||
}
|
||||
|
||||
return size > 0 ? size : undefined
|
||||
}
|
||||
|
||||
function readColumnSizing(
|
||||
storageKey: string | undefined,
|
||||
bounds: ColumnSizingBounds
|
||||
): ColumnSizingState {
|
||||
if (!storageKey || typeof window === 'undefined') return {}
|
||||
|
||||
try {
|
||||
const raw = window.localStorage.getItem(storageKey)
|
||||
if (!raw) return {}
|
||||
|
||||
const parsed = JSON.parse(raw) as unknown
|
||||
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
||||
return {}
|
||||
}
|
||||
|
||||
return Object.entries(parsed).reduce<ColumnSizingState>(
|
||||
(sizing, [key, value]) => {
|
||||
const boundedSize = getBoundedColumnSize(key, value, bounds)
|
||||
|
||||
if (boundedSize !== undefined) {
|
||||
sizing[key] = boundedSize
|
||||
}
|
||||
return sizing
|
||||
},
|
||||
{}
|
||||
)
|
||||
} catch {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
|
||||
export function useDataTable<TData>(options: UseDataTableOptions<TData>) {
|
||||
const {
|
||||
data,
|
||||
@@ -161,6 +286,7 @@ export function useDataTable<TData>(options: UseDataTableOptions<TData>) {
|
||||
manualSorting,
|
||||
initialSorting = [],
|
||||
initialColumnVisibility = {},
|
||||
initialColumnSizing = {},
|
||||
initialRowSelection = {},
|
||||
initialExpanded = {},
|
||||
initialPagination = { pageIndex: 0, pageSize: 20 },
|
||||
@@ -175,6 +301,10 @@ export function useDataTable<TData>(options: UseDataTableOptions<TData>) {
|
||||
typeof options.columnVisibilityStorageKey === 'string'
|
||||
? options.columnVisibilityStorageKey
|
||||
: undefined
|
||||
const columnSizingStorageKey =
|
||||
typeof options.columnSizingStorageKey === 'string'
|
||||
? options.columnSizingStorageKey
|
||||
: undefined
|
||||
const resolvedInitialColumnVisibility = React.useMemo(
|
||||
() => ({
|
||||
...initialColumnVisibility,
|
||||
@@ -182,6 +312,17 @@ export function useDataTable<TData>(options: UseDataTableOptions<TData>) {
|
||||
}),
|
||||
[columnVisibilityStorageKey, initialColumnVisibility]
|
||||
)
|
||||
const columnSizingBounds = React.useMemo(
|
||||
() => buildColumnSizingBounds(columns),
|
||||
[columns]
|
||||
)
|
||||
const resolvedInitialColumnSizing = React.useMemo(
|
||||
() => ({
|
||||
...initialColumnSizing,
|
||||
...readColumnSizing(columnSizingStorageKey, columnSizingBounds),
|
||||
}),
|
||||
[columnSizingBounds, columnSizingStorageKey, initialColumnSizing]
|
||||
)
|
||||
|
||||
const [sorting, onSortingChange] = useControllableTableState(
|
||||
options.sorting,
|
||||
@@ -194,10 +335,20 @@ export function useDataTable<TData>(options: UseDataTableOptions<TData>) {
|
||||
resolvedInitialColumnVisibility,
|
||||
options.onColumnVisibilityChange
|
||||
)
|
||||
const [columnSizing, onColumnSizingChange] = useControllableTableState(
|
||||
options.columnSizing,
|
||||
resolvedInitialColumnSizing,
|
||||
options.onColumnSizingChange
|
||||
)
|
||||
const hydratedColumnVisibilityStorageKeyRef = React.useRef(
|
||||
columnVisibilityStorageKey
|
||||
)
|
||||
const hydratedColumnSizingStorageKeyRef = React.useRef(columnSizingStorageKey)
|
||||
const skipNextColumnVisibilityPersistRef = React.useRef(false)
|
||||
const skipNextColumnSizingPersistRef = React.useRef(false)
|
||||
const columnSizingPersistTimerRef = React.useRef<number | undefined>(
|
||||
undefined
|
||||
)
|
||||
const [rowSelection, onRowSelectionChange] = useControllableTableState(
|
||||
options.rowSelection,
|
||||
initialRowSelection,
|
||||
@@ -228,6 +379,7 @@ export function useDataTable<TData>(options: UseDataTableOptions<TData>) {
|
||||
state: {
|
||||
sorting,
|
||||
columnVisibility,
|
||||
columnSizing,
|
||||
rowSelection,
|
||||
expanded,
|
||||
columnFilters: options.columnFilters,
|
||||
@@ -242,8 +394,11 @@ export function useDataTable<TData>(options: UseDataTableOptions<TData>) {
|
||||
manualFiltering,
|
||||
manualPagination,
|
||||
manualSorting,
|
||||
enableColumnResizing: options.enableColumnResizing,
|
||||
columnResizeMode: 'onChange',
|
||||
onSortingChange,
|
||||
onColumnVisibilityChange,
|
||||
onColumnSizingChange,
|
||||
onRowSelectionChange,
|
||||
onExpandedChange,
|
||||
onColumnFiltersChange: options.onColumnFiltersChange,
|
||||
@@ -290,6 +445,24 @@ export function useDataTable<TData>(options: UseDataTableOptions<TData>) {
|
||||
resolvedInitialColumnVisibility,
|
||||
])
|
||||
|
||||
React.useEffect(() => {
|
||||
if (
|
||||
options.columnSizing !== undefined ||
|
||||
columnSizingStorageKey === hydratedColumnSizingStorageKeyRef.current
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
hydratedColumnSizingStorageKeyRef.current = columnSizingStorageKey
|
||||
skipNextColumnSizingPersistRef.current = true
|
||||
onColumnSizingChange(() => resolvedInitialColumnSizing)
|
||||
}, [
|
||||
columnSizingStorageKey,
|
||||
onColumnSizingChange,
|
||||
options.columnSizing,
|
||||
resolvedInitialColumnSizing,
|
||||
])
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!columnVisibilityStorageKey || typeof window === 'undefined') return
|
||||
|
||||
@@ -308,6 +481,39 @@ export function useDataTable<TData>(options: UseDataTableOptions<TData>) {
|
||||
}
|
||||
}, [columnVisibility, columnVisibilityStorageKey])
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!columnSizingStorageKey || typeof window === 'undefined') return
|
||||
|
||||
if (skipNextColumnSizingPersistRef.current) {
|
||||
skipNextColumnSizingPersistRef.current = false
|
||||
return
|
||||
}
|
||||
|
||||
if (columnSizingPersistTimerRef.current !== undefined) {
|
||||
window.clearTimeout(columnSizingPersistTimerRef.current)
|
||||
}
|
||||
|
||||
columnSizingPersistTimerRef.current = window.setTimeout(() => {
|
||||
try {
|
||||
window.localStorage.setItem(
|
||||
columnSizingStorageKey,
|
||||
JSON.stringify(columnSizing)
|
||||
)
|
||||
} catch {
|
||||
// Storage can be unavailable in private mode; table controls still work.
|
||||
} finally {
|
||||
columnSizingPersistTimerRef.current = undefined
|
||||
}
|
||||
}, COLUMN_SIZING_PERSIST_DELAY_MS)
|
||||
|
||||
return () => {
|
||||
if (columnSizingPersistTimerRef.current !== undefined) {
|
||||
window.clearTimeout(columnSizingPersistTimerRef.current)
|
||||
columnSizingPersistTimerRef.current = undefined
|
||||
}
|
||||
}
|
||||
}, [columnSizing, columnSizingStorageKey])
|
||||
|
||||
return {
|
||||
table,
|
||||
}
|
||||
|
||||
@@ -560,6 +560,7 @@ export function useChannelsColumns(
|
||||
},
|
||||
enableSorting: false,
|
||||
enableHiding: false,
|
||||
enableResizing: false,
|
||||
size: 40,
|
||||
} satisfies ColumnDef<Channel>,
|
||||
]
|
||||
@@ -624,13 +625,13 @@ export function useChannelsColumns(
|
||||
const hasParamOverride = Boolean(channel.param_override?.trim())
|
||||
|
||||
return (
|
||||
<div className='flex items-center gap-2'>
|
||||
<div className='flex flex-col gap-1'>
|
||||
<div className='flex items-center gap-1.5'>
|
||||
<div className='flex max-w-full min-w-0 items-center gap-2'>
|
||||
<div className='flex max-w-full min-w-0 flex-col gap-1'>
|
||||
<div className='flex max-w-full min-w-0 items-center gap-1.5'>
|
||||
<TruncatedText
|
||||
text={sensitiveVisible ? name : SENSITIVE_MASK}
|
||||
className='font-medium'
|
||||
maxWidth='max-w-[180px]'
|
||||
maxWidth='max-w-full'
|
||||
/>
|
||||
{isPassThrough && (
|
||||
<TooltipProvider delay={100}>
|
||||
@@ -684,6 +685,7 @@ export function useChannelsColumns(
|
||||
</div>
|
||||
)
|
||||
},
|
||||
size: 260,
|
||||
minSize: 200,
|
||||
},
|
||||
|
||||
|
||||
@@ -67,6 +67,7 @@ import { DataTableBulkActions } from './data-table-bulk-actions'
|
||||
|
||||
const route = getRouteApi('/_authenticated/channels/')
|
||||
const CHANNELS_COLUMN_VISIBILITY_STORAGE_KEY = 'channels:column-visibility'
|
||||
const CHANNELS_COLUMN_SIZING_STORAGE_KEY = 'channels:column-sizing'
|
||||
const CHANNELS_VIEW_MODE_STORAGE_KEY = 'channels:view-mode'
|
||||
const CHANNELS_STATUS_FILTER_STORAGE_KEY = 'channel-status-filter'
|
||||
|
||||
@@ -316,6 +317,9 @@ export function ChannelsTable() {
|
||||
tag: false,
|
||||
},
|
||||
columnVisibilityStorageKey: CHANNELS_COLUMN_VISIBILITY_STORAGE_KEY,
|
||||
columnSizingStorageKey: isMobile
|
||||
? false
|
||||
: CHANNELS_COLUMN_SIZING_STORAGE_KEY,
|
||||
columnFilters,
|
||||
pagination,
|
||||
globalFilter,
|
||||
@@ -331,6 +335,7 @@ export function ChannelsTable() {
|
||||
manualSorting: true,
|
||||
manualFiltering: true,
|
||||
withExpandedRowModel: true,
|
||||
enableColumnResizing: !isMobile,
|
||||
ensurePageInRange,
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user