mirror of
https://github.com/woodchen-ink/clash-and-dashboard.git
synced 2025-07-18 14:01:56 +08:00
Improve: connections ux
This commit is contained in:
parent
ce2ee24c0e
commit
cd53cb8c54
@ -1,7 +1,5 @@
|
|||||||
import React, { useEffect, useState, useMemo, useCallback, useRef, useLayoutEffect } from 'react'
|
import React, { useEffect, useMemo } from 'react'
|
||||||
import { useBlockLayout, useResizeColumns, useTable } from 'react-table'
|
import { useBlockLayout, useResizeColumns, useTable } from 'react-table'
|
||||||
import { VariableSizeGrid as Grid, GridOnScrollProps, GridChildComponentProps } from 'react-window'
|
|
||||||
import AutoSizer from 'react-virtualized-auto-sizer'
|
|
||||||
import classnames from 'classnames'
|
import classnames from 'classnames'
|
||||||
import { Header, Card, Checkbox, Modal, useModal, Icon } from '@components'
|
import { Header, Card, Checkbox, Modal, useModal, Icon } from '@components'
|
||||||
import { containers } from '@stores'
|
import { containers } from '@stores'
|
||||||
@ -174,48 +172,33 @@ export default function Connections () {
|
|||||||
getTableBodyProps,
|
getTableBodyProps,
|
||||||
headerGroups,
|
headerGroups,
|
||||||
rows,
|
rows,
|
||||||
prepareRow,
|
prepareRow
|
||||||
columns: realColumns,
|
|
||||||
totalColumnsWidth
|
|
||||||
} = useTable(
|
} = useTable(
|
||||||
{ columns, data },
|
{ columns, data },
|
||||||
useBlockLayout,
|
useBlockLayout,
|
||||||
useResizeColumns
|
useResizeColumns
|
||||||
)
|
)
|
||||||
const headerGroup = useMemo(() => headerGroups[0], [headerGroups])
|
const headerGroup = useMemo(() => headerGroups[0], [headerGroups])
|
||||||
const renderItem = useCallback(
|
const renderItem = useMemo(() => rows.map((row, index) => {
|
||||||
({ columnIndex, rowIndex, style }: GridChildComponentProps) => {
|
|
||||||
const row = rows[rowIndex]
|
|
||||||
prepareRow(row)
|
prepareRow(row)
|
||||||
const cell = row.cells[columnIndex]
|
return (
|
||||||
|
<div {...row.getRowProps()} className="connections-item">
|
||||||
|
{
|
||||||
|
row.cells.map((cell) => {
|
||||||
const classname = classnames(
|
const classname = classnames(
|
||||||
'connections-block',
|
'connections-block',
|
||||||
{ center: shouldCenter.has(cell.column.id), completed: !!(row.original as any).completed }
|
{ center: shouldCenter.has(cell.column.id), completed: !!(row.original as any).completed }
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div {...row.getRowProps({ style })} className="connections-item">
|
|
||||||
<div {...cell.getCellProps()} className={classname}>
|
<div {...cell.getCellProps()} className={classname}>
|
||||||
{ cell.render('Cell') }
|
{ cell.render('Cell') }
|
||||||
</div>
|
</div>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
},
|
}), [prepareRow, rows])
|
||||||
[prepareRow, rows]
|
|
||||||
)
|
|
||||||
|
|
||||||
// handle consistency of react-window and react-table
|
|
||||||
const [girdLeft, setGirdLeft] = useState(0)
|
|
||||||
const handleScroll = useCallback(({ scrollLeft }: GridOnScrollProps) => setGirdLeft(scrollLeft), [setGirdLeft])
|
|
||||||
const handleColumnWidth = useCallback(index => realColumns[index].width, [realColumns])
|
|
||||||
const gridRef = useRef<Grid>()
|
|
||||||
useLayoutEffect(() => {
|
|
||||||
gridRef.current && gridRef.current.resetAfterIndices({
|
|
||||||
columnIndex: 0,
|
|
||||||
rowIndex: 0,
|
|
||||||
shouldForceUpdate: false
|
|
||||||
})
|
|
||||||
}, [totalColumnsWidth])
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="page">
|
<div className="page">
|
||||||
@ -228,7 +211,7 @@ export default function Connections () {
|
|||||||
</Header>
|
</Header>
|
||||||
<Card className="connections-card">
|
<Card className="connections-card">
|
||||||
<div {...getTableProps()} className="connections">
|
<div {...getTableProps()} className="connections">
|
||||||
<div {...headerGroup.getHeaderGroupProps()} className="connections-tr" style={{ transform: `translateX(-${girdLeft}px)` }}>
|
<div {...headerGroup.getHeaderGroupProps()} className="connections-header">
|
||||||
{
|
{
|
||||||
headerGroup.headers.map((column, idx) => {
|
headerGroup.headers.map((column, idx) => {
|
||||||
const id = column.id
|
const id = column.id
|
||||||
@ -249,25 +232,7 @@ export default function Connections () {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div {...getTableBodyProps()} className="connections-body">
|
<div {...getTableBodyProps()} className="connections-body">
|
||||||
<AutoSizer>
|
|
||||||
{
|
|
||||||
({ height, width }) => (
|
|
||||||
<Grid
|
|
||||||
ref={gridRef}
|
|
||||||
onScroll={handleScroll}
|
|
||||||
itemData={data}
|
|
||||||
itemKey={({ rowIndex, columnIndex, data }) => `${data[rowIndex].id}/${columnIndex}`}
|
|
||||||
height={height}
|
|
||||||
width={width}
|
|
||||||
columnCount={columns.length}
|
|
||||||
columnWidth={handleColumnWidth}
|
|
||||||
rowCount={rows.length}
|
|
||||||
rowHeight={() => 36}>
|
|
||||||
{ renderItem }
|
{ renderItem }
|
||||||
</Grid>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
</AutoSizer>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
|
@ -6,13 +6,20 @@
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
.connections {
|
.connections {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
flex: 1 0 auto;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
overflow: hidden;
|
flex-grow: 1;
|
||||||
|
flex-basis: 0;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.connections-header {
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.connections-body {
|
.connections-body {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user