+
{header &&
{header}
}
{loading ? (
-
Loading...
+
Loading...
) : (
renderItems()
)}
@@ -171,4 +182,6 @@ const List = React.forwardRef
((props, ref) => {
});
List.displayName = 'List';
-export default List;
+export default List as (
+ props: ListProps & React.RefAttributes
+) => React.ReactElement | null;
diff --git a/packages/react/src/list/style/_index.scss b/packages/react/src/list/style/_index.scss
index e5f2a990..af0985a1 100644
--- a/packages/react/src/list/style/_index.scss
+++ b/packages/react/src/list/style/_index.scss
@@ -49,6 +49,13 @@
}
}
+ &__items,
+ &__grid {
+ list-style: none;
+ margin: 0;
+ padding: 0;
+ }
+
&__empty {
padding: 24px;
text-align: center;
diff --git a/packages/react/src/list/types.ts b/packages/react/src/list/types.ts
index d76e7ac0..66e9a373 100644
--- a/packages/react/src/list/types.ts
+++ b/packages/react/src/list/types.ts
@@ -36,13 +36,15 @@ export interface ListPaginationProps extends Pick {
+ React.PropsWithoutRef {
extra?: React.ReactNode;
actions?: React.ReactNode[];
children?: React.ReactNode;
}
-export interface ListItemMetaProps extends BaseProps {
+export interface ListItemMetaProps
+ extends BaseProps,
+ Omit, 'title'> {
avatar?: React.ReactNode;
title?: React.ReactNode;
description?: React.ReactNode;
diff --git a/packages/react/src/loader/__tests__/__snapshots__/loader.test.tsx.snap b/packages/react/src/loader/__tests__/__snapshots__/loader.test.tsx.snap
index 685f4382..87ab9793 100644
--- a/packages/react/src/loader/__tests__/__snapshots__/loader.test.tsx.snap
+++ b/packages/react/src/loader/__tests__/__snapshots__/loader.test.tsx.snap
@@ -12,20 +12,7 @@ exports[` should match the snapshot 1`] = `
>
-
-
-
-
-
+ />
diff --git a/packages/react/src/loader/indicator.tsx b/packages/react/src/loader/indicator.tsx
index 6c9b6339..b34eb177 100644
--- a/packages/react/src/loader/indicator.tsx
+++ b/packages/react/src/loader/indicator.tsx
@@ -8,14 +8,7 @@ type Props = {
const Indicator = (props: Props): React.ReactElement => {
const { size, className } = props;
- return (
-
-
-
-
-
-
- );
+ return
;
};
export default Indicator;
diff --git a/packages/react/src/loader/style/_index.scss b/packages/react/src/loader/style/_index.scss
index 87cda31a..b9a6ab96 100755
--- a/packages/react/src/loader/style/_index.scss
+++ b/packages/react/src/loader/style/_index.scss
@@ -9,44 +9,44 @@
&__indicator {
position: relative;
display: inline-block;
- font-size: 20px;
- width: 1em;
- height: 1em;
+ aspect-ratio: 1;
+ border-radius: 50%;
+ border: var(--ty-loader-border-width) solid transparent;
+ border-right-color: currentcolor;
margin: 5px;
- animation: ty-rotate 1s linear infinite;
- }
+ animation: ty-loader-spin 1s infinite linear;
- &__indicator-dot {
- position: absolute;
- display: block;
- transform: scale(0.75);
- background-color: currentcolor;
- border-radius: 50%;
- transform-origin: 50% 50%;
- opacity: 0.5;
- animation: dot-opacity 2s linear infinite;
+ &::before,
+ &::after {
+ content: '';
+ position: absolute;
+ inset: calc(var(--ty-loader-border-width) * -1);
+ border-radius: 50%;
+ border: inherit;
+ animation: inherit;
+ animation-duration: 2s;
+ }
- &:nth-child(1) {
- top: 0;
- left: 0;
+ &::after {
+ animation-duration: 4s;
}
- &:nth-child(2) {
- top: 0;
- right: 0;
- animation-delay: .4s;
+ &_sm {
+ --ty-loader-border-width: 2px;
+
+ width: 16px;
}
- &:nth-child(3) {
- right: 0;
- bottom: 0;
- animation-delay: .8s;
+ &_md {
+ --ty-loader-border-width: 3px;
+
+ width: 24px;
}
- &:nth-child(4) {
- bottom: 0;
- left: 0;
- animation-delay: 1.2s;
+ &_lg {
+ --ty-loader-border-width: 4px;
+
+ width: 36px;
}
}
@@ -57,45 +57,6 @@
font-size: 16px;
}
- &_md {
- .#{$prefix}-loader{
- &__indicator{
- font-size: 20px;
- }
-
- &__indicator-dot {
- width: 9px;
- height: 9px;
- }
- }
- }
-
- &_lg {
- .#{$prefix}-loader{
- &__indicator{
- font-size: 32px;
- }
-
- &__indicator-dot {
- width: 14px;
- height: 14px;
- }
- }
- }
-
- &_sm {
- .#{$prefix}-loader{
- &__indicator{
- font-size: 14px;
- }
-
- &__indicator-dot {
- width: 6px;
- height: 6px;
- }
- }
- }
-
&__loader-container {
width: 100%;
height: 100%;
@@ -127,16 +88,8 @@
}
}
-@keyframes dot-opacity {
- 0% {
- opacity: 0.2;
- }
-
- 50% {
- opacity: 0.9;
- }
-
+@keyframes ty-loader-spin {
100% {
- opacity: 0.2;
+ transform: rotate(1turn);
}
}
diff --git a/packages/react/src/table/index.md b/packages/react/src/table/index.md
index 1c7aef5d..9a11bf63 100644
--- a/packages/react/src/table/index.md
+++ b/packages/react/src/table/index.md
@@ -120,6 +120,8 @@ Render large tables efficiently with virtual scrolling. The header stays fixed w
| onChange | sort/pagination change callback | (pagination, sorter) => void | |
| emptyText | empty state text | ReactNode | No Data |
| showHeader | show table header | boolean | true |
+| rowClassName | custom row class name | string | (record, index) => string | |
+| onRow | row event handler | (record, index) => HTMLAttributes | |
### ColumnType
@@ -132,7 +134,9 @@ Render large tables efficiently with virtual scrolling. The header stays fixed w
| align | text alignment | `left` | `center` | `right` | left |
| sorter | enable sorting | boolean | (a, b) => number | |
| render | custom cell renderer | (value, record, index) => ReactNode | |
+| defaultSortOrder | default sort order | `ascend` | `descend` | |
| ellipsis | truncate long content | boolean | false |
+| className | custom column class name | string | |
### RowSelection
diff --git a/packages/react/src/table/index.zh_CN.md b/packages/react/src/table/index.zh_CN.md
index cf1454af..b8869859 100644
--- a/packages/react/src/table/index.zh_CN.md
+++ b/packages/react/src/table/index.zh_CN.md
@@ -120,6 +120,8 @@ import { Table } from 'tiny-design';
| onChange | 排序/分页变化回调 | (pagination, sorter) => void | |
| emptyText | 空状态文本 | ReactNode | 暂无数据 |
| showHeader | 显示表头 | boolean | true |
+| rowClassName | 自定义行类名 | string | (record, index) => string | |
+| onRow | 行事件处理 | (record, index) => HTMLAttributes | |
### ColumnType
@@ -132,7 +134,9 @@ import { Table } from 'tiny-design';
| align | 对齐方式 | `left` | `center` | `right` | left |
| sorter | 排序功能 | boolean | (a, b) => number | |
| render | 自定义渲染 | (value, record, index) => ReactNode | |
+| defaultSortOrder | 默认排序方向 | `ascend` | `descend` | |
| ellipsis | 文本溢出省略 | boolean | false |
+| className | 自定义列类名 | string | |
### RowSelection
diff --git a/packages/react/src/table/table.tsx b/packages/react/src/table/table.tsx
index 299173e4..0375ba62 100644
--- a/packages/react/src/table/table.tsx
+++ b/packages/react/src/table/table.tsx
@@ -4,6 +4,8 @@ import { ConfigContext } from '../config-provider/config-context';
import { getPrefixCls } from '../_utils/general';
import { useVirtualScroll } from '../_utils/use-virtual-scroll';
import Pagination from '../pagination';
+import Checkbox from '../checkbox';
+import Radio from '../radio';
import { TableProps, ColumnType, SortOrder } from './types';
const ROW_HEIGHT_MAP = { sm: 40, md: 48, lg: 56 } as const;
@@ -81,7 +83,7 @@ const Table = React.forwardRef
((props, ref) => {
break;
}
}
- }, []);
+ }, [columns]);
const sortedData = useMemo(() => {
if (!sortField || !sortOrder) return [...dataSource];
@@ -143,13 +145,14 @@ const Table = React.forwardRef((props, ref) => {
const handlePageChange = (page: number) => {
setCurrentPage(page);
- pagination && pagination.onChange?.(page, pageSize);
+ paginationConfig?.onChange?.(page, pageSize);
onChange?.({ current: page, pageSize }, { field: sortField, order: sortOrder });
};
const handleSelectAll = () => {
if (!rowSelection) return;
- const allKeys = paginatedData.map((record, i) => getRowKey(record, rowKey, i));
+ const offset = (!isVirtual && pagination !== false) ? (activePage - 1) * pageSize : 0;
+ const allKeys = paginatedData.map((record, i) => getRowKey(record, rowKey, offset + i));
const allSelected = allKeys.every((k) => selectedKeys.includes(k));
const newKeys = allSelected ? [] : allKeys;
if (!rowSelection.selectedRowKeys) {
@@ -173,7 +176,7 @@ const Table = React.forwardRef((props, ref) => {
if (!rowSelection.selectedRowKeys) {
setSelectedKeys(newKeys);
}
- const newRows = dataSource.filter((r, i) => newKeys.includes(getRowKey(r, rowKey, i)));
+ const newRows = sortedData.filter((r, i) => newKeys.includes(getRowKey(r, rowKey, i)));
rowSelection.onChange?.(newKeys, newRows);
};
@@ -195,7 +198,8 @@ const Table = React.forwardRef((props, ref) => {
wrapperStyle.overflowY = 'auto';
}
- const allPageKeys = paginatedData.map((r, i) => getRowKey(r, rowKey, i));
+ const pageOffset = (!isVirtual && pagination !== false) ? (activePage - 1) * pageSize : 0;
+ const allPageKeys = paginatedData.map((r, i) => getRowKey(r, rowKey, pageOffset + i));
const allSelected = allPageKeys.length > 0 && allPageKeys.every((k) => selectedKeys.includes(k));
const someSelected = allPageKeys.some((k) => selectedKeys.includes(k));
@@ -212,12 +216,19 @@ const Table = React.forwardRef((props, ref) => {
{rowSelection && (
|
- handleSelectRow(record, key)}
- aria-label={`Select row ${rowIndex + 1}`}
- />
+ {rowSelection.type === 'radio' ? (
+ handleSelectRow(record, key)}
+ aria-label={`Select row ${rowIndex + 1}`}
+ />
+ ) : (
+ handleSelectRow(record, key)}
+ aria-label={`Select row ${rowIndex + 1}`}
+ />
+ )}
|
)}
{columns.map((col, colIndex) => {
@@ -294,7 +305,7 @@ const Table = React.forwardRef((props, ref) => {
);
}
- return paginatedData.map((record, rowIndex) => renderRow(record, rowIndex));
+ return paginatedData.map((record, i) => renderRow(record, pageOffset + i));
};
const theadCls = classNames(`${prefixCls}__thead`, {
@@ -317,10 +328,9 @@ const Table = React.forwardRef((props, ref) => {
{rowSelection && (
{rowSelection.type !== 'radio' && (
- { if (el) el.indeterminate = someSelected && !allSelected; }}
+ indeterminate={someSelected && !allSelected}
onChange={handleSelectAll}
aria-label="Select all"
/>
diff --git a/packages/react/src/table/types.ts b/packages/react/src/table/types.ts
index fa28caa2..3ebc209e 100644
--- a/packages/react/src/table/types.ts
+++ b/packages/react/src/table/types.ts
@@ -7,11 +7,10 @@ export type ColumnAlign = 'left' | 'center' | 'right';
export interface ColumnType {
title: React.ReactNode;
- dataIndex?: string;
+ dataIndex?: keyof T & string;
key?: string;
width?: number | string;
align?: ColumnAlign;
- fixed?: 'left' | 'right';
sorter?: boolean | ((a: T, b: T) => number);
defaultSortOrder?: SortOrder;
render?: (value: any, record: T, index: number) => React.ReactNode;
@@ -19,11 +18,11 @@ export interface ColumnType {
className?: string;
}
-export type RowSelection = {
+export interface RowSelection {
selectedRowKeys?: React.Key[];
onChange?: (selectedRowKeys: React.Key[], selectedRows: T[]) => void;
type?: 'checkbox' | 'radio';
-};
+}
export interface TablePaginationConfig extends Pick {
current?: number;
|