Implement column resizing functionality in Channels Table, Streams Table and CustomTableHeader

This commit is contained in:
SergeantPanda 2025-09-12 09:22:02 -05:00
parent ab36b28b51
commit 22f0a4078b
4 changed files with 91 additions and 0 deletions

View file

@ -306,6 +306,9 @@ const ChannelsTable = ({}) => {
const [isBulkDelete, setIsBulkDelete] = useState(false);
const [channelToDelete, setChannelToDelete] = useState(null);
// Column sizing state for resizable columns
const [columnSizing, setColumnSizing] = useLocalStorage('channels-table-column-sizing', {});
// M3U and EPG URL configuration state
const [m3uParams, setM3uParams] = useState({
cachedlogos: true,
@ -697,14 +700,17 @@ const ChannelsTable = ({}) => {
{
id: 'expand',
size: 20,
enableResizing: false,
},
{
id: 'select',
size: 30,
enableResizing: false,
},
{
id: 'enabled',
size: 45,
enableResizing: false,
cell: ({ row, table }) => {
return (
<ChannelEnabledSwitch
@ -719,6 +725,8 @@ const ChannelsTable = ({}) => {
id: 'channel_number',
accessorKey: 'channel_number',
size: 40,
minSize: 30,
maxSize: 100,
cell: ({ getValue }) => {
const value = getValue();
// Format as integer if no decimal component
@ -739,6 +747,7 @@ const ChannelsTable = ({}) => {
{
id: 'name',
accessorKey: 'name',
minSize: 100,
cell: ({ getValue }) => (
<Box
style={{
@ -794,6 +803,8 @@ const ChannelsTable = ({}) => {
);
},
size: 120,
minSize: 80,
maxSize: 200,
},
{
id: 'channel_group',
@ -813,6 +824,8 @@ const ChannelsTable = ({}) => {
</Box>
),
size: 175,
minSize: 100,
maxSize: 300,
},
{
id: 'logo',
@ -821,6 +834,9 @@ const ChannelsTable = ({}) => {
return row.logo_id;
},
size: 75,
minSize: 50,
maxSize: 120,
enableResizing: false,
header: '',
cell: ({ getValue }) => {
const logoId = getValue();
@ -839,6 +855,7 @@ const ChannelsTable = ({}) => {
{
id: 'actions',
size: tableSize == 'compact' ? 75 : 100,
enableResizing: false,
header: '',
cell: ({ row }) => (
<ChannelRowActions
@ -953,6 +970,10 @@ const ChannelsTable = ({}) => {
manualFiltering: true,
enableRowSelection: true,
onRowSelectionChange: onRowSelectionChange,
state: {
columnSizing,
},
onColumnSizingChange: setColumnSizing,
getExpandedRowHeight: (row) => {
return 20 + 28 * row.original.streams.length;
},

View file

@ -67,6 +67,7 @@ const CustomTableHeader = ({
? header.getSize()
: undefined,
minWidth: 0,
position: 'relative',
// ...(tableCellProps && tableCellProps({ cell: header })),
}}
>
@ -80,6 +81,40 @@ const CustomTableHeader = ({
>
{renderHeaderCell(header)}
</Flex>
{header.column.getCanResize() && (
<Box
onMouseDown={header.getResizeHandler()}
onTouchStart={header.getResizeHandler()}
className={`resizer ${
header.column.getIsResizing() ? 'isResizing' : ''
}`}
style={{
position: 'absolute',
right: 0,
top: 0,
height: '100%',
width: '5px',
cursor: 'col-resize',
userSelect: 'none',
touchAction: 'none',
backgroundColor: header.column.getIsResizing()
? '#3b82f6'
: 'transparent',
opacity: header.column.getIsResizing() ? 1 : 0.5,
transition: 'opacity 0.2s',
}}
onMouseEnter={(e) => {
e.target.style.opacity = '1';
e.target.style.backgroundColor = '#6b7280';
}}
onMouseLeave={(e) => {
if (!header.column.getIsResizing()) {
e.target.style.opacity = '0.5';
e.target.style.backgroundColor = 'transparent';
}
}}
/>
)}
</Box>
);
})}

View file

@ -92,8 +92,11 @@ const useTable = ({
state: {
data: options.data,
selectedTableIds,
columnSizing: options.state?.columnSizing || {},
},
getCoreRowModel: options.getCoreRowModel ?? getCoreRowModel(),
enableColumnResizing: true,
columnResizeMode: 'onChange',
});
const selectedTableIdsSet = useMemo(

View file

@ -180,3 +180,35 @@ html {
-ms-user-select: text !important;
cursor: text !important;
}
/* Column resize handle styles */
.resizer {
position: absolute;
right: 0;
top: 0;
height: 100%;
width: 5px;
cursor: col-resize;
user-select: none;
touch-action: none;
background-color: transparent;
opacity: 0;
transition: all 0.2s ease;
}
.resizer:hover {
opacity: 1 !important;
background-color: #6b7280 !important;
}
.resizer.isResizing {
opacity: 1 !important;
background-color: #3b82f6 !important;
width: 3px;
}
/* Show resize handle on header hover */
.th:hover .resizer {
opacity: 0.5;
background-color: #6b7280;
}