mirror of
https://github.com/jeffvli/feishin.git
synced 2026-05-10 04:30:25 +02:00
add more table configuration
- alternate row colors - row hover highlight - vertical borders - horizontal borders
This commit is contained in:
+21
-3
@@ -41,12 +41,30 @@
|
|||||||
padding: var(--theme-spacing-xs);
|
padding: var(--theme-spacing-xs);
|
||||||
}
|
}
|
||||||
|
|
||||||
.container.with-row-border {
|
.container.with-horizontal-border {
|
||||||
border-bottom: 1px solid var(--theme-colors-border);
|
border-bottom: 1px solid var(--theme-colors-border);
|
||||||
}
|
}
|
||||||
|
|
||||||
.container.data-row.row-hover-enabled:hover::before,
|
.container.with-vertical-border {
|
||||||
.container.data-row.row-hover-enabled.row-hovered::before {
|
border-right: 1px solid var(--theme-colors-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.container.alternate-row-even {
|
||||||
|
background-color: initial;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container.alternate-row-odd {
|
||||||
|
@mixin dark {
|
||||||
|
background-color: darken(var(--theme-colors-background), 30%);
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin light {
|
||||||
|
background-color: darken(var(--theme-colors-background), 2%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.container.data-row.row-hover-highlight-enabled:hover::before,
|
||||||
|
.container.data-row.row-hover-highlight-enabled.row-hovered::before {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
|
|||||||
@@ -154,7 +154,7 @@ export const TableColumnTextContainer = (
|
|||||||
const dataIndex = isDataRow ? props.rowIndex - 1 : props.rowIndex;
|
const dataIndex = isDataRow ? props.rowIndex - 1 : props.rowIndex;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isDataRow || !containerRef.current || !props.enableRowHover) return;
|
if (!isDataRow || !containerRef.current) return;
|
||||||
|
|
||||||
const container = containerRef.current;
|
const container = containerRef.current;
|
||||||
const rowIndex = props.rowIndex;
|
const rowIndex = props.rowIndex;
|
||||||
@@ -178,19 +178,24 @@ export const TableColumnTextContainer = (
|
|||||||
container.removeEventListener('mouseenter', handleMouseEnter);
|
container.removeEventListener('mouseenter', handleMouseEnter);
|
||||||
container.removeEventListener('mouseleave', handleMouseLeave);
|
container.removeEventListener('mouseleave', handleMouseLeave);
|
||||||
};
|
};
|
||||||
}, [isDataRow, props.rowIndex, props.enableRowHover]);
|
}, [isDataRow, props.rowIndex, props.enableRowHoverHighlight]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={clsx(styles.container, props.containerClassName, {
|
className={clsx(styles.container, props.containerClassName, {
|
||||||
|
[styles.alternateRowEven]:
|
||||||
|
props.enableAlternateRowColors && isDataRow && dataIndex % 2 === 0,
|
||||||
|
[styles.alternateRowOdd]:
|
||||||
|
props.enableAlternateRowColors && isDataRow && dataIndex % 2 === 1,
|
||||||
[styles.center]: props.columns[props.columnIndex].align === 'center',
|
[styles.center]: props.columns[props.columnIndex].align === 'center',
|
||||||
[styles.compact]: props.size === 'compact',
|
[styles.compact]: props.size === 'compact',
|
||||||
[styles.dataRow]: isDataRow,
|
[styles.dataRow]: isDataRow,
|
||||||
[styles.left]: props.columns[props.columnIndex].align === 'start',
|
[styles.left]: props.columns[props.columnIndex].align === 'start',
|
||||||
[styles.right]: props.columns[props.columnIndex].align === 'end',
|
[styles.right]: props.columns[props.columnIndex].align === 'end',
|
||||||
[styles.rowHoverEnabled]: isDataRow && props.enableRowHover,
|
[styles.rowHoverHighlightEnabled]: isDataRow && props.enableRowHoverHighlight,
|
||||||
[styles.withRowBorder]:
|
[styles.withHorizontalBorder]:
|
||||||
props.enableRowBorders && props.enableHeader && props.rowIndex > 0,
|
props.enableHorizontalBorders && props.enableHeader && props.rowIndex > 0,
|
||||||
|
[styles.withVerticalBorder]: props.enableVerticalBorders,
|
||||||
})}
|
})}
|
||||||
data-row-index={isDataRow ? props.rowIndex : undefined}
|
data-row-index={isDataRow ? props.rowIndex : undefined}
|
||||||
ref={containerRef}
|
ref={containerRef}
|
||||||
@@ -223,7 +228,7 @@ export const TableColumnContainer = (
|
|||||||
const dataIndex = isDataRow ? props.rowIndex - 1 : props.rowIndex;
|
const dataIndex = isDataRow ? props.rowIndex - 1 : props.rowIndex;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isDataRow || !containerRef.current || !props.enableRowHover) return;
|
if (!isDataRow || !containerRef.current) return;
|
||||||
|
|
||||||
const container = containerRef.current;
|
const container = containerRef.current;
|
||||||
const rowIndex = props.rowIndex;
|
const rowIndex = props.rowIndex;
|
||||||
@@ -247,19 +252,24 @@ export const TableColumnContainer = (
|
|||||||
container.removeEventListener('mouseenter', handleMouseEnter);
|
container.removeEventListener('mouseenter', handleMouseEnter);
|
||||||
container.removeEventListener('mouseleave', handleMouseLeave);
|
container.removeEventListener('mouseleave', handleMouseLeave);
|
||||||
};
|
};
|
||||||
}, [isDataRow, props.rowIndex, props.enableRowHover]);
|
}, [isDataRow, props.rowIndex, props.enableRowHoverHighlight]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={clsx(styles.container, props.className, {
|
className={clsx(styles.container, props.className, {
|
||||||
|
[styles.alternateRowEven]:
|
||||||
|
props.enableAlternateRowColors && isDataRow && dataIndex % 2 === 0,
|
||||||
|
[styles.alternateRowOdd]:
|
||||||
|
props.enableAlternateRowColors && isDataRow && dataIndex % 2 === 1,
|
||||||
[styles.center]: props.columns[props.columnIndex].align === 'center',
|
[styles.center]: props.columns[props.columnIndex].align === 'center',
|
||||||
[styles.compact]: props.size === 'compact',
|
[styles.compact]: props.size === 'compact',
|
||||||
[styles.dataRow]: isDataRow,
|
[styles.dataRow]: isDataRow,
|
||||||
[styles.left]: props.columns[props.columnIndex].align === 'start',
|
[styles.left]: props.columns[props.columnIndex].align === 'start',
|
||||||
[styles.right]: props.columns[props.columnIndex].align === 'end',
|
[styles.right]: props.columns[props.columnIndex].align === 'end',
|
||||||
[styles.rowHoverEnabled]: isDataRow && props.enableRowHover,
|
[styles.rowHoverHighlightEnabled]: isDataRow && props.enableRowHoverHighlight,
|
||||||
[styles.withRowBorder]:
|
[styles.withHorizontalBorder]:
|
||||||
props.enableRowBorders && props.enableHeader && props.rowIndex > 0,
|
props.enableHorizontalBorders && props.enableHeader && props.rowIndex > 0,
|
||||||
|
[styles.withVerticalBorder]: props.enableVerticalBorders,
|
||||||
})}
|
})}
|
||||||
data-row-index={isDataRow ? props.rowIndex : undefined}
|
data-row-index={isDataRow ? props.rowIndex : undefined}
|
||||||
ref={containerRef}
|
ref={containerRef}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import { useMergedRef } from '@mantine/hooks';
|
import { useMergedRef } from '@mantine/hooks';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import { AnimatePresence, motion } from 'motion/react';
|
import { AnimatePresence } from 'motion/react';
|
||||||
import { useOverlayScrollbars } from 'overlayscrollbars-react';
|
import { useOverlayScrollbars } from 'overlayscrollbars-react';
|
||||||
import {
|
import {
|
||||||
type JSXElementConstructor,
|
type JSXElementConstructor,
|
||||||
@@ -24,18 +24,21 @@ import {
|
|||||||
ItemListStateActions,
|
ItemListStateActions,
|
||||||
useItemListState,
|
useItemListState,
|
||||||
} from '/@/renderer/components/item-list/helpers/item-list-state';
|
} from '/@/renderer/components/item-list/helpers/item-list-state';
|
||||||
import { sortTableColumns } from '/@/renderer/components/item-list/helpers/sort-table-columns';
|
import { parseTableColumns } from '/@/renderer/components/item-list/helpers/parse-table-columns';
|
||||||
import { ItemListHandle, ItemTableListColumnConfig } from '/@/renderer/components/item-list/types';
|
import { ItemListHandle, ItemTableListColumnConfig } from '/@/renderer/components/item-list/types';
|
||||||
import { LibraryItem } from '/@/shared/types/domain-types';
|
import { LibraryItem } from '/@/shared/types/domain-types';
|
||||||
|
|
||||||
export interface TableItemProps {
|
export interface TableItemProps {
|
||||||
columns: ItemTableListColumnConfig[];
|
columns: ItemTableListColumnConfig[];
|
||||||
data: unknown[];
|
data: unknown[];
|
||||||
|
enableAlternateRowColors?: boolean;
|
||||||
enableExpansion?: boolean;
|
enableExpansion?: boolean;
|
||||||
enableHeader?: boolean;
|
enableHeader?: boolean;
|
||||||
enableRowBorders?: boolean;
|
enableHorizontalBorders?: boolean;
|
||||||
enableRowHover?: boolean;
|
enableRowHoverHighlight?: boolean;
|
||||||
enableSelection?: boolean;
|
enableSelection?: boolean;
|
||||||
|
enableVerticalBorders?: boolean;
|
||||||
|
getRowHeight: (index: number, cellProps: TableItemProps) => number;
|
||||||
internalState: ItemListStateActions;
|
internalState: ItemListStateActions;
|
||||||
itemType: LibraryItem;
|
itemType: LibraryItem;
|
||||||
size?: 'compact' | 'default';
|
size?: 'compact' | 'default';
|
||||||
@@ -45,11 +48,13 @@ interface ItemTableListProps {
|
|||||||
CellComponent: JSXElementConstructor<CellComponentProps<TableItemProps>>;
|
CellComponent: JSXElementConstructor<CellComponentProps<TableItemProps>>;
|
||||||
columns: ItemTableListColumnConfig[];
|
columns: ItemTableListColumnConfig[];
|
||||||
data: unknown[];
|
data: unknown[];
|
||||||
|
enableAlternateRowColors?: boolean;
|
||||||
enableExpansion?: boolean;
|
enableExpansion?: boolean;
|
||||||
enableHeader?: boolean;
|
enableHeader?: boolean;
|
||||||
enableRowBorders?: boolean;
|
enableHorizontalBorders?: boolean;
|
||||||
enableRowHover?: boolean;
|
enableRowHoverHighlight?: boolean;
|
||||||
enableSelection?: boolean;
|
enableSelection?: boolean;
|
||||||
|
enableVerticalBorders?: boolean;
|
||||||
headerHeight?: number;
|
headerHeight?: number;
|
||||||
initialTop?: {
|
initialTop?: {
|
||||||
behavior?: 'auto' | 'smooth';
|
behavior?: 'auto' | 'smooth';
|
||||||
@@ -74,11 +79,13 @@ export const ItemTableList = ({
|
|||||||
CellComponent,
|
CellComponent,
|
||||||
columns,
|
columns,
|
||||||
data,
|
data,
|
||||||
enableExpansion = false,
|
enableAlternateRowColors = false,
|
||||||
|
enableExpansion = true,
|
||||||
enableHeader = true,
|
enableHeader = true,
|
||||||
enableRowBorders = false,
|
enableHorizontalBorders = false,
|
||||||
enableRowHover = false,
|
enableRowHoverHighlight = true,
|
||||||
enableSelection = false,
|
enableSelection = true,
|
||||||
|
enableVerticalBorders = false,
|
||||||
headerHeight = 40,
|
headerHeight = 40,
|
||||||
initialTop,
|
initialTop,
|
||||||
itemType,
|
itemType,
|
||||||
@@ -92,7 +99,7 @@ export const ItemTableList = ({
|
|||||||
size = 'default',
|
size = 'default',
|
||||||
}: ItemTableListProps) => {
|
}: ItemTableListProps) => {
|
||||||
const totalItemCount = data.length;
|
const totalItemCount = data.length;
|
||||||
const sortedColumns = useMemo(() => sortTableColumns(columns), [columns]);
|
const sortedColumns = useMemo(() => parseTableColumns(columns), [columns]);
|
||||||
const columnCount = sortedColumns.length;
|
const columnCount = sortedColumns.length;
|
||||||
|
|
||||||
const [centerContainerWidth, setCenterContainerWidth] = useState(0);
|
const [centerContainerWidth, setCenterContainerWidth] = useState(0);
|
||||||
@@ -130,7 +137,7 @@ export const ItemTableList = ({
|
|||||||
sortedColumns.forEach((col, idx) => {
|
sortedColumns.forEach((col, idx) => {
|
||||||
if (col.pinned === null) {
|
if (col.pinned === null) {
|
||||||
unpinnedIndices.push(idx);
|
unpinnedIndices.push(idx);
|
||||||
if (col.autoWidth) {
|
if (col.autoSize) {
|
||||||
autoUnpinnedIndices.push(idx);
|
autoUnpinnedIndices.push(idx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -238,7 +245,6 @@ export const ItemTableList = ({
|
|||||||
autoHideDelay: 500,
|
autoHideDelay: 500,
|
||||||
pointers: ['mouse', 'pen', 'touch'],
|
pointers: ['mouse', 'pen', 'touch'],
|
||||||
theme: 'feishin-os-scrollbar',
|
theme: 'feishin-os-scrollbar',
|
||||||
visibility: 'visible',
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -521,7 +527,7 @@ export const ItemTableList = ({
|
|||||||
|
|
||||||
const getRowHeight = useCallback(
|
const getRowHeight = useCallback(
|
||||||
(index: number, cellProps: TableItemProps) => {
|
(index: number, cellProps: TableItemProps) => {
|
||||||
const height = size === 'compact' ? 40 : 68;
|
const height = size === 'compact' ? 40 : 64;
|
||||||
|
|
||||||
const baseHeight =
|
const baseHeight =
|
||||||
typeof rowHeight === 'number' ? rowHeight : rowHeight?.(index, cellProps) || height;
|
typeof rowHeight === 'number' ? rowHeight : rowHeight?.(index, cellProps) || height;
|
||||||
@@ -653,11 +659,14 @@ export const ItemTableList = ({
|
|||||||
const itemProps: TableItemProps = {
|
const itemProps: TableItemProps = {
|
||||||
columns: sortedColumns,
|
columns: sortedColumns,
|
||||||
data,
|
data,
|
||||||
|
enableAlternateRowColors,
|
||||||
enableExpansion,
|
enableExpansion,
|
||||||
enableHeader,
|
enableHeader,
|
||||||
enableRowBorders,
|
enableHorizontalBorders,
|
||||||
enableRowHover,
|
enableRowHoverHighlight,
|
||||||
enableSelection,
|
enableSelection,
|
||||||
|
enableVerticalBorders,
|
||||||
|
getRowHeight,
|
||||||
internalState,
|
internalState,
|
||||||
itemType,
|
itemType,
|
||||||
size,
|
size,
|
||||||
@@ -704,18 +713,7 @@ export const ItemTableList = ({
|
|||||||
}, [imperativeHandle]);
|
}, [imperativeHandle]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<motion.div
|
<div className={styles.itemTableListContainer}>
|
||||||
animate={{
|
|
||||||
height: '100%',
|
|
||||||
opacity: 1,
|
|
||||||
transition: {
|
|
||||||
duration: 1,
|
|
||||||
ease: 'backInOut',
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
className={styles.itemTableListContainer}
|
|
||||||
initial={{ opacity: 0 }}
|
|
||||||
>
|
|
||||||
<div className={styles.itemTableContainer}>
|
<div className={styles.itemTableContainer}>
|
||||||
<div
|
<div
|
||||||
className={styles.itemTablePinnedColumnsGridContainer}
|
className={styles.itemTablePinnedColumnsGridContainer}
|
||||||
@@ -903,6 +901,6 @@ export const ItemTableList = ({
|
|||||||
</ExpandedListContainer>
|
</ExpandedListContainer>
|
||||||
)}
|
)}
|
||||||
</AnimatePresence>
|
</AnimatePresence>
|
||||||
</motion.div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user