mirror of
https://github.com/jeffvli/feishin.git
synced 2024-11-20 14:37:06 +01:00
Add stickyHeader prop to table component
This commit is contained in:
parent
92d7560362
commit
9d18384b2d
@ -1,42 +1,54 @@
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { useInView } from 'framer-motion';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { useWindowSettings } from '/@/renderer/store/settings.store';
|
||||
import { Platform } from '/@/renderer/types';
|
||||
|
||||
export const useFixedTableHeader = () => {
|
||||
const intersectRef = useRef<HTMLDivElement | null>(null);
|
||||
export const useFixedTableHeader = ({ enabled }: { enabled: boolean }) => {
|
||||
const tableHeaderRef = useRef<HTMLDivElement | null>(null);
|
||||
const tableContainerRef = useRef<HTMLDivElement | null>(null);
|
||||
const { windowBarStyle } = useWindowSettings();
|
||||
|
||||
const isNotPastTableIntersection = useInView(intersectRef, {
|
||||
margin:
|
||||
windowBarStyle === Platform.WEB || windowBarStyle === Platform.LINUX
|
||||
? '-68px 0px 0px 0px'
|
||||
: '-98px 0px 0px 0px',
|
||||
const topMargin =
|
||||
windowBarStyle === Platform.WINDOWS || windowBarStyle === Platform.MACOS
|
||||
? '-128px'
|
||||
: '-98px';
|
||||
|
||||
const isTableHeaderInView = useInView(tableHeaderRef, {
|
||||
margin: `${topMargin} 0px 0px 0px`,
|
||||
});
|
||||
|
||||
const tableInView = useInView(tableContainerRef, {
|
||||
margin: '-128px 0px 0px 0px',
|
||||
const isTableInView = useInView(tableContainerRef, {
|
||||
margin: `${topMargin} 0px 0px 0px`,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (!enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
const header = document.querySelector('main .ag-header');
|
||||
const root = document.querySelector('main .ag-root');
|
||||
|
||||
if (isNotPastTableIntersection || !tableInView) {
|
||||
if (windowBarStyle === Platform.WINDOWS || windowBarStyle === Platform.MACOS) {
|
||||
header?.classList.remove('window-frame');
|
||||
}
|
||||
header?.classList.remove('ag-header-fixed');
|
||||
root?.classList.remove('ag-header-fixed-margin');
|
||||
} else {
|
||||
if (!isTableHeaderInView && isTableInView) {
|
||||
if (windowBarStyle === Platform.WINDOWS || windowBarStyle === Platform.MACOS) {
|
||||
header?.classList.add('window-frame');
|
||||
}
|
||||
header?.classList.add('ag-header-fixed');
|
||||
root?.classList.add('ag-header-fixed-margin');
|
||||
} else if (!isTableInView) {
|
||||
if (windowBarStyle === Platform.WINDOWS || windowBarStyle === Platform.MACOS) {
|
||||
header?.classList.remove('window-frame');
|
||||
}
|
||||
header?.classList.remove('ag-header-fixed');
|
||||
root?.classList.remove('ag-header-fixed-margin');
|
||||
} else if (isTableHeaderInView) {
|
||||
if (windowBarStyle === Platform.WINDOWS || windowBarStyle === Platform.MACOS) {
|
||||
header?.classList.remove('window-frame');
|
||||
}
|
||||
header?.classList.remove('ag-header-fixed');
|
||||
root?.classList.remove('ag-header-fixed-margin');
|
||||
}
|
||||
}, [isNotPastTableIntersection, tableInView, windowBarStyle]);
|
||||
}, [enabled, isTableHeaderInView, isTableInView, windowBarStyle]);
|
||||
|
||||
return { intersectRef, tableContainerRef };
|
||||
return { tableContainerRef, tableHeaderRef };
|
||||
};
|
||||
|
@ -35,6 +35,7 @@ import { RatingCell } from '/@/renderer/components/virtual-table/cells/rating-ce
|
||||
import { TablePagination } from '/@/renderer/components/virtual-table/table-pagination';
|
||||
import { ActionsCell } from '/@/renderer/components/virtual-table/cells/actions-cell';
|
||||
import { TitleCell } from '/@/renderer/components/virtual-table/cells/title-cell';
|
||||
import { useFixedTableHeader } from '/@/renderer/components/virtual-table/hooks/use-fixed-table-header';
|
||||
|
||||
export * from './table-config-dropdown';
|
||||
export * from './table-pagination';
|
||||
@ -43,12 +44,18 @@ export * from './hooks/use-click-outside-deselect';
|
||||
export * from './utils';
|
||||
|
||||
const TableWrapper = styled.div`
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
`;
|
||||
|
||||
const DummyHeader = styled.div<{ height?: number }>`
|
||||
position: absolute;
|
||||
height: ${({ height }) => height || 36}px};
|
||||
`;
|
||||
|
||||
dayjs.extend(relativeTime);
|
||||
|
||||
const tableColumns: { [key: string]: ColDef } = {
|
||||
@ -371,6 +378,7 @@ export interface VirtualTableProps extends AgGridReactProps {
|
||||
pagination: TablePaginationType;
|
||||
setPagination: any;
|
||||
};
|
||||
stickyHeader?: boolean;
|
||||
transparentHeader?: boolean;
|
||||
}
|
||||
|
||||
@ -380,6 +388,7 @@ export const VirtualTable = forwardRef(
|
||||
autoFitColumns,
|
||||
deselectOnClickOutside,
|
||||
autoHeight,
|
||||
stickyHeader,
|
||||
transparentHeader,
|
||||
onColumnMoved,
|
||||
onNewColumnsLoaded,
|
||||
@ -467,55 +476,60 @@ export const VirtualTable = forwardRef(
|
||||
[autoFitColumns],
|
||||
);
|
||||
|
||||
const { tableHeaderRef, tableContainerRef } = useFixedTableHeader({
|
||||
enabled: stickyHeader || false,
|
||||
});
|
||||
|
||||
const mergedWrapperRef = useMergedRef(deselectRef, tableContainerRef);
|
||||
|
||||
return (
|
||||
<>
|
||||
<TableWrapper
|
||||
ref={deselectRef}
|
||||
className={
|
||||
transparentHeader
|
||||
? 'ag-header-transparent ag-theme-alpine-dark'
|
||||
: 'ag-theme-alpine-dark'
|
||||
}
|
||||
>
|
||||
<AgGridReact
|
||||
ref={mergedRef}
|
||||
animateRows
|
||||
maintainColumnOrder
|
||||
suppressAsyncEvents
|
||||
suppressContextMenu
|
||||
suppressCopyRowsToClipboard
|
||||
suppressMoveWhenRowDragging
|
||||
suppressPaginationPanel
|
||||
suppressScrollOnNewData
|
||||
blockLoadDebounceMillis={200}
|
||||
cacheBlockSize={300}
|
||||
cacheOverflowSize={1}
|
||||
defaultColDef={defaultColumnDefs}
|
||||
enableCellChangeFlash={false}
|
||||
headerHeight={36}
|
||||
rowBuffer={30}
|
||||
rowSelection="multiple"
|
||||
{...rest}
|
||||
onColumnMoved={handleColumnMoved}
|
||||
onGridReady={handleGridReady}
|
||||
onGridSizeChanged={handleGridSizeChanged}
|
||||
onModelUpdated={handleModelUpdated}
|
||||
onNewColumnsLoaded={handleNewColumnsLoaded}
|
||||
/>
|
||||
{paginationProps && (
|
||||
<AnimatePresence
|
||||
presenceAffectsLayout
|
||||
initial={false}
|
||||
mode="wait"
|
||||
>
|
||||
<TablePagination
|
||||
{...paginationProps}
|
||||
tableRef={tableRef}
|
||||
/>
|
||||
</AnimatePresence>
|
||||
)}
|
||||
</TableWrapper>
|
||||
</>
|
||||
<TableWrapper
|
||||
ref={mergedWrapperRef}
|
||||
className={
|
||||
transparentHeader
|
||||
? 'ag-theme-alpine-dark ag-header-transparent'
|
||||
: 'ag-theme-alpine-dark'
|
||||
}
|
||||
>
|
||||
<DummyHeader ref={tableHeaderRef} />
|
||||
<AgGridReact
|
||||
ref={mergedRef}
|
||||
animateRows
|
||||
maintainColumnOrder
|
||||
suppressAsyncEvents
|
||||
suppressContextMenu
|
||||
suppressCopyRowsToClipboard
|
||||
suppressMoveWhenRowDragging
|
||||
suppressPaginationPanel
|
||||
suppressScrollOnNewData
|
||||
blockLoadDebounceMillis={200}
|
||||
cacheBlockSize={300}
|
||||
cacheOverflowSize={1}
|
||||
defaultColDef={defaultColumnDefs}
|
||||
enableCellChangeFlash={false}
|
||||
headerHeight={36}
|
||||
rowBuffer={30}
|
||||
rowSelection="multiple"
|
||||
{...rest}
|
||||
onColumnMoved={handleColumnMoved}
|
||||
onGridReady={handleGridReady}
|
||||
onGridSizeChanged={handleGridSizeChanged}
|
||||
onModelUpdated={handleModelUpdated}
|
||||
onNewColumnsLoaded={handleNewColumnsLoaded}
|
||||
/>
|
||||
{paginationProps && (
|
||||
<AnimatePresence
|
||||
presenceAffectsLayout
|
||||
initial={false}
|
||||
mode="wait"
|
||||
>
|
||||
<TablePagination
|
||||
{...paginationProps}
|
||||
tableRef={tableRef}
|
||||
/>
|
||||
</AnimatePresence>
|
||||
)}
|
||||
</TableWrapper>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user