@ticatec/topside-elements 1.0.1 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/dist/data_table/DataTable.svelte +4 -3
- package/dist/data_table/README.md +159 -1
- package/dist/data_table/README_CN.md +159 -1
- package/dist/data_table/index.d.ts +4 -4
- package/dist/data_table/lib/CellAction.d.ts +7 -0
- package/dist/data_table/lib/DataColumn.d.ts +21 -2
- package/dist/data_table/lib/TableUtils.d.ts +9 -0
- package/dist/data_table/lib/TableUtils.js +10 -2
- package/dist/data_table/parts/ActionCell.svelte +1 -1
- package/dist/data_table/parts/ContentPanel.svelte +1 -1
- package/dist/data_table/parts/ContentPanel.svelte.d.ts +1 -1
- package/dist/data_table/parts/DataCell.svelte +9 -2
- package/dist/data_table/parts/FixedColumnsPanel.svelte +1 -1
- package/dist/data_table/parts/FixedColumnsPanel.svelte.d.ts +1 -1
- package/dist/data_table/parts/FixedHeaderPanel.svelte +4 -3
- package/dist/data_table/parts/FixedHeaderPanel.svelte.d.ts +1 -1
- package/dist/data_table/parts/TableHeaderPanel.svelte +4 -3
- package/dist/data_table/parts/TableHeaderPanel.svelte.d.ts +1 -1
- package/dist/general/split/README.md +42 -57
- package/dist/general/split/README_CN.md +42 -57
- package/dist/general/split/Split.svelte +100 -15
- package/dist/general/split/Split.svelte.d.ts +15 -0
- package/dist/topside-elements.css +2 -0
- package/docs/components/README.md +3 -3
- package/docs/components/concise-data-table/README.md +52 -2
- package/docs/components/data-table/README.md +54 -8
- package/docs/components/split/README.md +10 -5
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.0.3
|
|
4
|
+
|
|
5
|
+
### 变更
|
|
6
|
+
- **Split 分割线外观**:线条默认 1px(`width`,原 2px);新增 `hitSize`(不占布局的感应区,默认 8px,靠近即可悬停 / 拖动)、`color`、`gripColor`、`gripSize`、`gripLength`;悬停 / 拖动 / 键盘聚焦时中间淡入深色稍粗的把手,取代原来整条加深。新令牌 `--topside-divider-grip-color`(亮 `#94A3B8` / 暗 `#8a8a8a`)。
|
|
7
|
+
|
|
8
|
+
### 文档
|
|
9
|
+
- 重新生成 `docs/components`(Split、DataTable / ConciseDataTable 合计行相关属性)。
|
|
10
|
+
|
|
3
11
|
## 1.0.0 — 首个公开版本
|
|
4
12
|
|
|
5
13
|
### 新增
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
import type { GetRowFontStyle } from "../types";
|
|
14
14
|
import { computeVirtualWindow } from "./lib/virtualWindow";
|
|
15
15
|
import { buildTableSummary } from "./lib/summary";
|
|
16
|
+
import { isSameColumn } from "./lib/TableUtils";
|
|
16
17
|
import i18nRes from "../i18nRes";
|
|
17
18
|
|
|
18
19
|
interface Props {
|
|
@@ -170,7 +171,7 @@
|
|
|
170
171
|
|
|
171
172
|
const onCellClick = (col: DataColumn) => {
|
|
172
173
|
if (col.compareFunction != null) {
|
|
173
|
-
if (col
|
|
174
|
+
if (isSameColumn(col, orderColumn)) {
|
|
174
175
|
orderDirection = orderDirection == OrderDirection.Ascending
|
|
175
176
|
? OrderDirection.Descending
|
|
176
177
|
: OrderDirection.Ascending;
|
|
@@ -200,7 +201,7 @@
|
|
|
200
201
|
{onRowExpand}
|
|
201
202
|
bind:selectedRows
|
|
202
203
|
{orderDirection}
|
|
203
|
-
|
|
204
|
+
{orderColumn}
|
|
204
205
|
{onCellClick}
|
|
205
206
|
{indicatorColumn}
|
|
206
207
|
bind:expandRow
|
|
@@ -220,7 +221,7 @@
|
|
|
220
221
|
<ContentPanel
|
|
221
222
|
columns={dataColumns}
|
|
222
223
|
{orderDirection}
|
|
223
|
-
|
|
224
|
+
{orderColumn}
|
|
224
225
|
{onWidthChange}
|
|
225
226
|
{onCellClick}
|
|
226
227
|
{tabWidth}
|
|
@@ -73,7 +73,7 @@ interface DataColumn {
|
|
|
73
73
|
escapeHTML?: boolean; // Whether to escape HTML in content
|
|
74
74
|
href?: HrefBuilder; // Link builder function
|
|
75
75
|
hint?: CellHint; // Tooltip/hint function
|
|
76
|
-
render?:
|
|
76
|
+
render?: ColumnRender; // Custom Svelte component renderer (component or { component, props })
|
|
77
77
|
visible?: boolean; // Column visibility
|
|
78
78
|
resizable?: boolean; // Whether column is resizable
|
|
79
79
|
compareFunction?: CompareFunction; // Sorting comparison function
|
|
@@ -82,6 +82,41 @@ interface DataColumn {
|
|
|
82
82
|
}
|
|
83
83
|
```
|
|
84
84
|
|
|
85
|
+
### ColumnRender
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
type ColumnRender<Props extends Record<string, any> = Record<string, any>> =
|
|
89
|
+
| Component<any>
|
|
90
|
+
| ColumnRenderObject<Props>;
|
|
91
|
+
|
|
92
|
+
interface ColumnRenderObject<Props extends Record<string, any> = Record<string, any>> {
|
|
93
|
+
component: Component<any>; // Svelte 5 component
|
|
94
|
+
props?: Props; // Extra props passed to component (component also receives row `data`)
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### ActionCell and CellAction
|
|
99
|
+
|
|
100
|
+
`ActionCell` is a built-in single button action cell component that can be placed in any column (unlike `actionsColumn`, which is docked at the end of the table):
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
interface CellAction<T = any> {
|
|
104
|
+
label: string; // Button text
|
|
105
|
+
type?: ButtonType; // Semantic style ('primary', 'secondary', etc.)
|
|
106
|
+
icon?: string; // Optional icon
|
|
107
|
+
tooltip?: string; // Hover tooltip
|
|
108
|
+
disabled?: boolean; // Disabled state
|
|
109
|
+
handler: (data: T) => void | Promise<void>; // Click handler
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
type GetCellAction<T = any> = (data: T) => CellAction<T> | undefined;
|
|
113
|
+
|
|
114
|
+
interface ActionCellProps<T = any> {
|
|
115
|
+
data?: T; // Injected automatically by DataTable
|
|
116
|
+
getAction: GetCellAction<T>; // Returns action definition; returning undefined hides the button
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
85
120
|
### ActionsColumn
|
|
86
121
|
|
|
87
122
|
```typescript
|
|
@@ -320,6 +355,129 @@ interface RowAction {
|
|
|
320
355
|
<DataTable {columns} list={userData} rowHeight={50} />
|
|
321
356
|
```
|
|
322
357
|
|
|
358
|
+
### Custom Cell Rendering with render (Custom Components & ActionCell)
|
|
359
|
+
|
|
360
|
+
`DataColumn.render` supports two ways to render custom cell content:
|
|
361
|
+
1. **Pass a Svelte component directly**: The component automatically receives the current row data `{ data }`.
|
|
362
|
+
2. **Pass a `{ component, props }` configuration object**: The component receives all specified `props` along with `{ data }`.
|
|
363
|
+
|
|
364
|
+
#### 1. Creating and Using Custom Components
|
|
365
|
+
|
|
366
|
+
For example, a status badge component `StatusBadge.svelte`:
|
|
367
|
+
|
|
368
|
+
```svelte
|
|
369
|
+
<!-- StatusBadge.svelte -->
|
|
370
|
+
<script lang="ts">
|
|
371
|
+
interface Props {
|
|
372
|
+
data: any; // Row data injected automatically by DataTable
|
|
373
|
+
theme?: string; // Custom prop passed from column definition
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
let { data, theme = "info" }: Props = $props();
|
|
377
|
+
</script>
|
|
378
|
+
|
|
379
|
+
<span class="status-badge {theme}">
|
|
380
|
+
{data.statusName ?? data.status}
|
|
381
|
+
</span>
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
Using the custom component in column definitions:
|
|
385
|
+
|
|
386
|
+
```svelte
|
|
387
|
+
<script>
|
|
388
|
+
import DataTable from "@ticatec/topside-elements/data_table";
|
|
389
|
+
import UserAvatar from "./UserAvatar.svelte";
|
|
390
|
+
import StatusBadge from "./StatusBadge.svelte";
|
|
391
|
+
|
|
392
|
+
const columns = [
|
|
393
|
+
// Method 1: Component directly
|
|
394
|
+
{
|
|
395
|
+
title: "Avatar",
|
|
396
|
+
width: 70,
|
|
397
|
+
render: UserAvatar
|
|
398
|
+
},
|
|
399
|
+
// Method 2: Configuration object with extra props
|
|
400
|
+
{
|
|
401
|
+
title: "Status",
|
|
402
|
+
width: 120,
|
|
403
|
+
render: {
|
|
404
|
+
component: StatusBadge,
|
|
405
|
+
props: { theme: "success" }
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
];
|
|
409
|
+
</script>
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
#### 2. Using Built-in ActionCell for Action Columns
|
|
413
|
+
|
|
414
|
+
`ActionCell` allows rendering single button actions in any column position with full dynamic control over label, style, and visibility based on row data:
|
|
415
|
+
|
|
416
|
+
```svelte
|
|
417
|
+
<script>
|
|
418
|
+
import DataTable, { ActionCell } from "@ticatec/topside-elements/data_table";
|
|
419
|
+
|
|
420
|
+
const columns = [
|
|
421
|
+
{
|
|
422
|
+
title: "Service Code",
|
|
423
|
+
field: "code",
|
|
424
|
+
width: 150
|
|
425
|
+
},
|
|
426
|
+
{
|
|
427
|
+
title: "Service Name",
|
|
428
|
+
field: "name",
|
|
429
|
+
width: 200
|
|
430
|
+
},
|
|
431
|
+
{
|
|
432
|
+
title: "Modules",
|
|
433
|
+
width: 100,
|
|
434
|
+
render: {
|
|
435
|
+
component: ActionCell,
|
|
436
|
+
props: {
|
|
437
|
+
getAction: (row) => ({
|
|
438
|
+
label: "Manage",
|
|
439
|
+
handler: (data) => openModules(data)
|
|
440
|
+
})
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
},
|
|
444
|
+
{
|
|
445
|
+
title: "Status Action",
|
|
446
|
+
width: 100,
|
|
447
|
+
render: {
|
|
448
|
+
component: ActionCell,
|
|
449
|
+
props: {
|
|
450
|
+
getAction: (row) => {
|
|
451
|
+
// Return undefined to hide the action button
|
|
452
|
+
if (row.locked) return undefined;
|
|
453
|
+
return {
|
|
454
|
+
label: row.enabled ? "Disable" : "Enable",
|
|
455
|
+
type: row.enabled ? "danger" : "primary",
|
|
456
|
+
handler: (data) => toggleService(data)
|
|
457
|
+
};
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
];
|
|
463
|
+
|
|
464
|
+
const list = [
|
|
465
|
+
{ code: "AUTH", name: "Auth Service", enabled: true, locked: false },
|
|
466
|
+
{ code: "SYS", name: "Core Kernel", enabled: true, locked: true }
|
|
467
|
+
];
|
|
468
|
+
|
|
469
|
+
function openModules(item) {
|
|
470
|
+
console.log("Manage modules:", item.code);
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
function toggleService(item) {
|
|
474
|
+
console.log("Toggle status:", item.code);
|
|
475
|
+
}
|
|
476
|
+
</script>
|
|
477
|
+
|
|
478
|
+
<DataTable {columns} {list} />
|
|
479
|
+
```
|
|
480
|
+
|
|
323
481
|
### Table with Inline Row Expansion
|
|
324
482
|
|
|
325
483
|
```svelte
|
|
@@ -73,7 +73,7 @@ interface DataColumn {
|
|
|
73
73
|
escapeHTML?: boolean; // 是否转义 HTML 内容
|
|
74
74
|
href?: HrefBuilder; // 链接生成函数
|
|
75
75
|
hint?: CellHint; // 工具提示/提示函数
|
|
76
|
-
render?:
|
|
76
|
+
render?: ColumnRender; // 自定义 Svelte 组件渲染器(可为组件或 { component, props } 配置对象)
|
|
77
77
|
visible?: boolean; // 列可见性
|
|
78
78
|
resizable?: boolean; // 列是否可调整大小
|
|
79
79
|
compareFunction?: CompareFunction; // 排序比较函数
|
|
@@ -82,6 +82,41 @@ interface DataColumn {
|
|
|
82
82
|
}
|
|
83
83
|
```
|
|
84
84
|
|
|
85
|
+
### ColumnRender
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
type ColumnRender<Props extends Record<string, any> = Record<string, any>> =
|
|
89
|
+
| Component<any>
|
|
90
|
+
| ColumnRenderObject<Props>;
|
|
91
|
+
|
|
92
|
+
interface ColumnRenderObject<Props extends Record<string, any> = Record<string, any>> {
|
|
93
|
+
component: Component<any>; // Svelte 5 组件
|
|
94
|
+
props?: Props; // 传递给组件的额外属性(组件会自动接收当前行数据 `data`)
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### ActionCell 与 CellAction
|
|
99
|
+
|
|
100
|
+
`ActionCell` 是预置的单元格操作按钮组件,可在任意列中使用(不受 `actionsColumn` 只能固定在最右侧的限制):
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
interface CellAction<T = any> {
|
|
104
|
+
label: string; // 按钮显示文本
|
|
105
|
+
type?: ButtonType; // 语义样式(如 'primary' | 'secondary' 等)
|
|
106
|
+
icon?: string; // 前缀图标
|
|
107
|
+
tooltip?: string; // 悬停提示
|
|
108
|
+
disabled?: boolean; // 是否禁用
|
|
109
|
+
handler: (data: T) => void | Promise<void>; // 点击回调函数
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
type GetCellAction<T = any> = (data: T) => CellAction<T> | undefined;
|
|
113
|
+
|
|
114
|
+
interface ActionCellProps<T = any> {
|
|
115
|
+
data?: T; // 自动由 DataTable 注入当前行数据
|
|
116
|
+
getAction: GetCellAction<T>; // 返回该单元格操作,返回 undefined 则不显示按钮
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
85
120
|
### ActionsColumn
|
|
86
121
|
|
|
87
122
|
```typescript
|
|
@@ -320,6 +355,129 @@ interface RowAction {
|
|
|
320
355
|
<DataTable {columns} list={userData} rowHeight={50} />
|
|
321
356
|
```
|
|
322
357
|
|
|
358
|
+
### 使用 render 自定义单元格(自定义组件与 ActionCell)
|
|
359
|
+
|
|
360
|
+
`DataColumn.render` 支持两种方式自定义单元格内容:
|
|
361
|
+
1. **直接传入自定义 Svelte 组件**:组件将自动接收当前行的数据 `{ data }`。
|
|
362
|
+
2. **传入 `{ component, props }` 配置对象**:组件接收 `props` 中的所有自定义属性,同时自动注入 `{ data }`。
|
|
363
|
+
|
|
364
|
+
#### 1. 编写与使用自定义组件
|
|
365
|
+
|
|
366
|
+
例如定义一个状态徽标组件 `StatusBadge.svelte`:
|
|
367
|
+
|
|
368
|
+
```svelte
|
|
369
|
+
<!-- StatusBadge.svelte -->
|
|
370
|
+
<script lang="ts">
|
|
371
|
+
interface Props {
|
|
372
|
+
data: any; // DataTable 自动注入的当前行数据
|
|
373
|
+
theme?: string; // 通过 props 传入的自定义属性
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
let { data, theme = "info" }: Props = $props();
|
|
377
|
+
</script>
|
|
378
|
+
|
|
379
|
+
<span class="status-badge {theme}">
|
|
380
|
+
{data.statusName ?? data.status}
|
|
381
|
+
</span>
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
在表格列中使用自定义组件:
|
|
385
|
+
|
|
386
|
+
```svelte
|
|
387
|
+
<script>
|
|
388
|
+
import DataTable from "@ticatec/topside-elements/data_table";
|
|
389
|
+
import UserAvatar from "./UserAvatar.svelte";
|
|
390
|
+
import StatusBadge from "./StatusBadge.svelte";
|
|
391
|
+
|
|
392
|
+
const columns = [
|
|
393
|
+
// 方式一:直接传入组件
|
|
394
|
+
{
|
|
395
|
+
title: "头像",
|
|
396
|
+
width: 70,
|
|
397
|
+
render: UserAvatar
|
|
398
|
+
},
|
|
399
|
+
// 方式二:传入配置对象(可附带额外 props)
|
|
400
|
+
{
|
|
401
|
+
title: "状态",
|
|
402
|
+
width: 120,
|
|
403
|
+
render: {
|
|
404
|
+
component: StatusBadge,
|
|
405
|
+
props: { theme: "success" }
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
];
|
|
409
|
+
</script>
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
#### 2. 使用内置 ActionCell 渲染操作列
|
|
413
|
+
|
|
414
|
+
`ActionCell` 是预置的操作按钮组件,可在任意列中渲染单按钮操作,支持基于行数据动态设置按钮文本、类型,或通过返回 `undefined` 条件隐藏按钮:
|
|
415
|
+
|
|
416
|
+
```svelte
|
|
417
|
+
<script>
|
|
418
|
+
import DataTable, { ActionCell } from "@ticatec/topside-elements/data_table";
|
|
419
|
+
|
|
420
|
+
const columns = [
|
|
421
|
+
{
|
|
422
|
+
title: "服务编码",
|
|
423
|
+
field: "code",
|
|
424
|
+
width: 150
|
|
425
|
+
},
|
|
426
|
+
{
|
|
427
|
+
title: "服务名称",
|
|
428
|
+
field: "name",
|
|
429
|
+
width: 200
|
|
430
|
+
},
|
|
431
|
+
{
|
|
432
|
+
title: "模块管理",
|
|
433
|
+
width: 100,
|
|
434
|
+
render: {
|
|
435
|
+
component: ActionCell,
|
|
436
|
+
props: {
|
|
437
|
+
getAction: (row) => ({
|
|
438
|
+
label: "管理",
|
|
439
|
+
handler: (data) => openModules(data)
|
|
440
|
+
})
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
},
|
|
444
|
+
{
|
|
445
|
+
title: "状态操作",
|
|
446
|
+
width: 100,
|
|
447
|
+
render: {
|
|
448
|
+
component: ActionCell,
|
|
449
|
+
props: {
|
|
450
|
+
getAction: (row) => {
|
|
451
|
+
// 返回 undefined 时不渲染按钮
|
|
452
|
+
if (row.locked) return undefined;
|
|
453
|
+
return {
|
|
454
|
+
label: row.enabled ? "禁用" : "启用",
|
|
455
|
+
type: row.enabled ? "danger" : "primary",
|
|
456
|
+
handler: (data) => toggleStatus(data)
|
|
457
|
+
};
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
];
|
|
463
|
+
|
|
464
|
+
const list = [
|
|
465
|
+
{ code: "AUTH", name: "认证服务", enabled: true, locked: false },
|
|
466
|
+
{ code: "SYS", name: "系统内核", enabled: true, locked: true }
|
|
467
|
+
];
|
|
468
|
+
|
|
469
|
+
function openModules(item) {
|
|
470
|
+
console.log("管理服务模块:", item.code);
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
function toggleStatus(item) {
|
|
474
|
+
console.log("切换服务状态:", item.code);
|
|
475
|
+
}
|
|
476
|
+
</script>
|
|
477
|
+
|
|
478
|
+
<DataTable {columns} {list} />
|
|
479
|
+
```
|
|
480
|
+
|
|
323
481
|
### 带有内联行扩展的表格
|
|
324
482
|
|
|
325
483
|
```svelte
|
|
@@ -5,11 +5,11 @@ import type IndicatorColumn from "./lib/IndicatorColumn";
|
|
|
5
5
|
import type RowAction from "./lib/RowAction";
|
|
6
6
|
import type { GetRowActions, ActionHandler } from "./lib/RowAction";
|
|
7
7
|
import type DataColumn from "./lib/DataColumn";
|
|
8
|
-
import type { SummaryKind, SummaryFn } from "./lib/DataColumn";
|
|
9
|
-
import type { CellAction } from "./lib/CellAction";
|
|
8
|
+
import type { SummaryKind, SummaryFn, ColumnRender, ColumnRenderObject } from "./lib/DataColumn";
|
|
9
|
+
import type { CellAction, GetCellAction, ActionCellProps } from "./lib/CellAction";
|
|
10
10
|
import ActionCell from "./parts/ActionCell.svelte";
|
|
11
11
|
export default DataTable;
|
|
12
12
|
export { ActionCell };
|
|
13
|
-
export type { ActionsColumn, IndicatorColumn, FormatCellFn, CellHint, DataColumn };
|
|
14
|
-
export type { RowAction, GetRowActions, ActionHandler, CellAction };
|
|
13
|
+
export type { ActionsColumn, IndicatorColumn, FormatCellFn, CellHint, DataColumn, ColumnRender, ColumnRenderObject };
|
|
14
|
+
export type { RowAction, GetRowActions, ActionHandler, CellAction, GetCellAction, ActionCellProps };
|
|
15
15
|
export type { SummaryKind, SummaryFn };
|
|
@@ -7,3 +7,10 @@ export type CellAction<T = any> = RowAction<T>;
|
|
|
7
7
|
* 获取单元格动作;返回 undefined 表示该单元格没有动作
|
|
8
8
|
*/
|
|
9
9
|
export type GetCellAction<T = any> = (data: T) => CellAction<T> | undefined;
|
|
10
|
+
/**
|
|
11
|
+
* ActionCell 组件的属性类型
|
|
12
|
+
*/
|
|
13
|
+
export interface ActionCellProps<T = any> {
|
|
14
|
+
data?: T;
|
|
15
|
+
getAction: GetCellAction<T>;
|
|
16
|
+
}
|
|
@@ -2,10 +2,29 @@ import type { CellHint, FormatCellFn } from "./FormatCellFn";
|
|
|
2
2
|
import type { HrefBuilder } from "./HrefLink";
|
|
3
3
|
import type { CompareFn } from "./CompareFn";
|
|
4
4
|
import type { GetCellStyle } from "../../types";
|
|
5
|
+
import type { Component } from "svelte";
|
|
5
6
|
/** 内置聚合方式;'label' 表示该列在合计行里显示合计标签("合计") */
|
|
6
7
|
export type SummaryKind = 'sum' | 'avg' | 'count' | 'min' | 'max';
|
|
7
8
|
/** 自定义聚合:values 为本列各行的字段值,rows 为当前全部行数据 */
|
|
8
9
|
export type SummaryFn = (values: Array<any>, rows: Array<any>) => any;
|
|
10
|
+
/**
|
|
11
|
+
* 自定义单元格渲染器对象配置
|
|
12
|
+
*/
|
|
13
|
+
export interface ColumnRenderObject<Props extends Record<string, any> = Record<string, any>> {
|
|
14
|
+
/**
|
|
15
|
+
* 自定义 Svelte 单元格组件。
|
|
16
|
+
* 组件会接收 `props` 中传入的属性,并自动接收当前行的数据 `data`。
|
|
17
|
+
*/
|
|
18
|
+
component: Component<any>;
|
|
19
|
+
/**
|
|
20
|
+
* 传递给自定义组件的额外属性
|
|
21
|
+
*/
|
|
22
|
+
props?: Props;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* 自定义单元格渲染器:支持直接传入 Svelte 组件,或传入包含 { component, props } 的配置对象
|
|
26
|
+
*/
|
|
27
|
+
export type ColumnRender<Props extends Record<string, any> = Record<string, any>> = Component<any> | ColumnRenderObject<Props>;
|
|
9
28
|
export default interface DataColumn {
|
|
10
29
|
/**
|
|
11
30
|
* 列头文字(与 ConciseListTable 的 Column.title 统一)
|
|
@@ -50,9 +69,9 @@ export default interface DataColumn {
|
|
|
50
69
|
*/
|
|
51
70
|
hint?: CellHint;
|
|
52
71
|
/**
|
|
53
|
-
*
|
|
72
|
+
* 自定义单元格渲染器(可为 Svelte 组件或 `{ component, props }` 配置对象)
|
|
54
73
|
*/
|
|
55
|
-
render?:
|
|
74
|
+
render?: ColumnRender;
|
|
56
75
|
/**
|
|
57
76
|
*
|
|
58
77
|
*/
|
|
@@ -1,4 +1,13 @@
|
|
|
1
|
+
import type DataColumn from "./DataColumn";
|
|
2
|
+
/**
|
|
3
|
+
* 根据字段名获取对于的值,支持"."嵌套获取
|
|
4
|
+
* @param data
|
|
5
|
+
* @param field
|
|
6
|
+
*/
|
|
7
|
+
export declare const extractFieldValue: (data: any, field?: string) => any;
|
|
8
|
+
export declare const isSameColumn: (a?: DataColumn | null, b?: DataColumn | null) => boolean;
|
|
1
9
|
declare const _default: {
|
|
2
10
|
extractFieldValue: (data: any, field?: string) => any;
|
|
11
|
+
isSameColumn: (a?: DataColumn | null, b?: DataColumn | null) => boolean;
|
|
3
12
|
};
|
|
4
13
|
export default _default;
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* @param data
|
|
4
4
|
* @param field
|
|
5
5
|
*/
|
|
6
|
-
const extractFieldValue = (data, field) => {
|
|
6
|
+
export const extractFieldValue = (data, field) => {
|
|
7
7
|
let v = data;
|
|
8
8
|
if (field != null) {
|
|
9
9
|
let attrs = field.split(".");
|
|
@@ -13,6 +13,14 @@ const extractFieldValue = (data, field) => {
|
|
|
13
13
|
}
|
|
14
14
|
return v;
|
|
15
15
|
};
|
|
16
|
+
export const isSameColumn = (a, b) => {
|
|
17
|
+
if (!a || !b)
|
|
18
|
+
return false;
|
|
19
|
+
if (a === b)
|
|
20
|
+
return true;
|
|
21
|
+
return a.field != null && b.field != null && a.field === b.field;
|
|
22
|
+
};
|
|
16
23
|
export default {
|
|
17
|
-
extractFieldValue
|
|
24
|
+
extractFieldValue,
|
|
25
|
+
isSameColumn
|
|
18
26
|
};
|
|
@@ -7,7 +7,7 @@ import type { VirtualWindow } from "../lib/virtualWindow";
|
|
|
7
7
|
interface Props {
|
|
8
8
|
columns: Array<DataColumn>;
|
|
9
9
|
rows: Array<TableRow>;
|
|
10
|
-
orderColumn
|
|
10
|
+
orderColumn?: DataColumn | null;
|
|
11
11
|
orderDirection: OrderDirection;
|
|
12
12
|
getRowFontStyle?: GetRowFontStyle;
|
|
13
13
|
emptyText?: string | null;
|
|
@@ -22,8 +22,15 @@
|
|
|
22
22
|
<div class="data-cell {colClass}" {style} bind:this={cell}>
|
|
23
23
|
<div class="vertical-center">
|
|
24
24
|
{#if column.render}
|
|
25
|
-
{@const Render = column.render.component
|
|
26
|
-
|
|
25
|
+
{@const Render = typeof column.render === 'object' && column.render !== null && 'component' in column.render
|
|
26
|
+
? column.render.component
|
|
27
|
+
: column.render}
|
|
28
|
+
{@const renderProps = typeof column.render === 'object' && column.render !== null && 'props' in column.render
|
|
29
|
+
? column.render.props
|
|
30
|
+
: undefined}
|
|
31
|
+
{#if Render}
|
|
32
|
+
<Render {...renderProps} {data} />
|
|
33
|
+
{/if}
|
|
27
34
|
{:else if column.href}
|
|
28
35
|
<HrefCell {data} href={column.href} />
|
|
29
36
|
{:else}
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
onWidthChange?: OnWidthChange;
|
|
23
23
|
onRowExpand?: OnRowExpand;
|
|
24
24
|
onCellClick?: (col: DataColumn) => any;
|
|
25
|
-
orderColumn?: DataColumn;
|
|
25
|
+
orderColumn?: DataColumn | null;
|
|
26
26
|
orderDirection?: OrderDirection;
|
|
27
27
|
selectedRows?: Array<any>;
|
|
28
28
|
expandRow?: TableRow | null;
|
|
@@ -14,7 +14,7 @@ interface Props {
|
|
|
14
14
|
onWidthChange?: OnWidthChange;
|
|
15
15
|
onRowExpand?: OnRowExpand;
|
|
16
16
|
onCellClick?: (col: DataColumn) => any;
|
|
17
|
-
orderColumn?: DataColumn;
|
|
17
|
+
orderColumn?: DataColumn | null;
|
|
18
18
|
orderDirection?: OrderDirection;
|
|
19
19
|
selectedRows?: Array<any>;
|
|
20
20
|
expandRow?: TableRow | null;
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import type { IndicatorColumn } from "..";
|
|
4
4
|
import { type OnSelectAll, SelectionMode, type OnWidthChange } from "../UniDataTable";
|
|
5
5
|
import { OrderDirection } from "../lib/OrderDirection";
|
|
6
|
+
import { isSameColumn } from "../lib/TableUtils";
|
|
6
7
|
import i18nRes from "../../i18nRes";
|
|
7
8
|
|
|
8
9
|
interface Props {
|
|
@@ -12,7 +13,7 @@
|
|
|
12
13
|
rowHeight?: number;
|
|
13
14
|
headerHeight?: number;
|
|
14
15
|
onCellClick?: (col: DataColumn) => any;
|
|
15
|
-
orderColumn?: DataColumn;
|
|
16
|
+
orderColumn?: DataColumn | null;
|
|
16
17
|
orderDirection?: OrderDirection;
|
|
17
18
|
selectionMode?: SelectionMode;
|
|
18
19
|
onToggleSelectAll?: OnSelectAll;
|
|
@@ -124,13 +125,13 @@
|
|
|
124
125
|
onkeydown={handleHeaderKeyDown(column)}
|
|
125
126
|
role={column.compareFunction != null ? 'button' : undefined}
|
|
126
127
|
tabindex={column.compareFunction != null ? 0 : undefined}
|
|
127
|
-
aria-sort={column
|
|
128
|
+
aria-sort={isSameColumn(column, orderColumn)
|
|
128
129
|
? (orderDirection === OrderDirection.Ascending ? 'ascending' : 'descending')
|
|
129
130
|
: undefined}
|
|
130
131
|
class="vertical-center"
|
|
131
132
|
>
|
|
132
133
|
<span>{column.title}</span>
|
|
133
|
-
{#if column
|
|
134
|
+
{#if isSameColumn(column, orderColumn)}
|
|
134
135
|
<i
|
|
135
136
|
style="margin-left: 2px; font-size: 12px; position: absolute; top: 0; right: 4px"
|
|
136
137
|
class={orderDirection === OrderDirection.Ascending
|
|
@@ -9,7 +9,7 @@ interface Props {
|
|
|
9
9
|
rowHeight?: number;
|
|
10
10
|
headerHeight?: number;
|
|
11
11
|
onCellClick?: (col: DataColumn) => any;
|
|
12
|
-
orderColumn?: DataColumn;
|
|
12
|
+
orderColumn?: DataColumn | null;
|
|
13
13
|
orderDirection?: OrderDirection;
|
|
14
14
|
selectionMode?: SelectionMode;
|
|
15
15
|
onToggleSelectAll?: OnSelectAll;
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { OrderDirection } from "../lib/OrderDirection";
|
|
3
3
|
import { type OnWidthChange } from "../UniDataTable";
|
|
4
4
|
import type DataColumn from "../lib/DataColumn";
|
|
5
|
+
import { isSameColumn } from "../lib/TableUtils";
|
|
5
6
|
|
|
6
7
|
interface Props {
|
|
7
8
|
scrollLeft?: number;
|
|
@@ -10,7 +11,7 @@
|
|
|
10
11
|
width?: number;
|
|
11
12
|
whitespace?: boolean;
|
|
12
13
|
onCellClick?: (col: DataColumn) => any;
|
|
13
|
-
orderColumn?: DataColumn;
|
|
14
|
+
orderColumn?: DataColumn | null;
|
|
14
15
|
orderDirection?: OrderDirection;
|
|
15
16
|
headerHeight?: number;
|
|
16
17
|
}
|
|
@@ -82,13 +83,13 @@
|
|
|
82
83
|
onkeydown={handleHeaderKeyDown(col)}
|
|
83
84
|
role={col.compareFunction != null ? 'button' : undefined}
|
|
84
85
|
tabindex={col.compareFunction != null ? 0 : undefined}
|
|
85
|
-
aria-sort={col
|
|
86
|
+
aria-sort={isSameColumn(col, orderColumn)
|
|
86
87
|
? (orderDirection === OrderDirection.Ascending ? 'ascending' : 'descending')
|
|
87
88
|
: undefined}
|
|
88
89
|
class="vertical-center"
|
|
89
90
|
>
|
|
90
91
|
<span>{col.title}</span>
|
|
91
|
-
{#if col
|
|
92
|
+
{#if isSameColumn(col, orderColumn)}
|
|
92
93
|
<i
|
|
93
94
|
style="margin-left: 2px; font-size: 12px; position: absolute; top: 0; right: 4px"
|
|
94
95
|
class={orderDirection === OrderDirection.Ascending
|