@gradio/dataframe 0.16.5 → 0.17.1
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 +34 -0
- package/Dataframe.stories.svelte +202 -9
- package/Index.svelte +7 -13
- package/dist/Index.svelte +5 -9
- package/dist/Index.svelte.d.ts +9 -2
- package/dist/shared/CellMenu.svelte +91 -10
- package/dist/shared/CellMenu.svelte.d.ts +6 -0
- package/dist/shared/CellMenuButton.svelte +45 -0
- package/dist/shared/CellMenuButton.svelte.d.ts +16 -0
- package/dist/shared/CellMenuIcons.svelte +79 -0
- package/dist/shared/EditableCell.svelte +83 -14
- package/dist/shared/EditableCell.svelte.d.ts +12 -3
- package/dist/shared/EmptyRowButton.svelte +28 -0
- package/dist/shared/EmptyRowButton.svelte.d.ts +16 -0
- package/dist/shared/RowNumber.svelte +40 -0
- package/dist/shared/RowNumber.svelte.d.ts +17 -0
- package/dist/shared/Table.svelte +564 -1121
- package/dist/shared/Table.svelte.d.ts +4 -0
- package/dist/shared/TableCell.svelte +291 -0
- package/dist/shared/TableCell.svelte.d.ts +57 -0
- package/dist/shared/TableHeader.svelte +239 -0
- package/dist/shared/TableHeader.svelte.d.ts +45 -0
- package/dist/shared/Toolbar.svelte +18 -8
- package/dist/shared/VirtualTable.svelte +66 -19
- package/dist/shared/VirtualTable.svelte.d.ts +4 -0
- package/dist/shared/context/keyboard_context.d.ts +37 -0
- package/dist/shared/context/keyboard_context.js +12 -0
- package/dist/shared/context/selection_context.d.ts +32 -0
- package/dist/shared/context/selection_context.js +107 -0
- package/dist/shared/context/table_context.d.ts +141 -0
- package/dist/shared/context/table_context.js +375 -0
- package/dist/shared/icons/Padlock.svelte +24 -0
- package/dist/shared/icons/Padlock.svelte.d.ts +23 -0
- package/dist/shared/icons/SelectionButtons.svelte +85 -0
- package/dist/shared/icons/SelectionButtons.svelte.d.ts +18 -0
- package/dist/shared/icons/SortArrowDown.svelte +24 -0
- package/dist/shared/icons/SortArrowDown.svelte.d.ts +16 -0
- package/dist/shared/icons/SortArrowUp.svelte +24 -0
- package/dist/shared/icons/SortArrowUp.svelte.d.ts +16 -0
- package/dist/shared/icons/SortButtonDown.svelte +14 -0
- package/dist/shared/icons/SortButtonDown.svelte.d.ts +23 -0
- package/dist/shared/icons/SortButtonUp.svelte +15 -0
- package/dist/shared/icons/SortButtonUp.svelte.d.ts +23 -0
- package/dist/shared/icons/SortIcon.svelte +46 -68
- package/dist/shared/icons/SortIcon.svelte.d.ts +3 -2
- package/dist/shared/selection_utils.d.ts +2 -1
- package/dist/shared/selection_utils.js +39 -10
- package/dist/shared/utils/data_processing.d.ts +13 -0
- package/dist/shared/utils/data_processing.js +45 -0
- package/dist/shared/utils/drag_utils.d.ts +15 -0
- package/dist/shared/utils/drag_utils.js +57 -0
- package/dist/shared/utils/keyboard_utils.d.ts +2 -0
- package/dist/shared/utils/keyboard_utils.js +186 -0
- package/dist/shared/utils/sort_utils.d.ts +22 -3
- package/dist/shared/utils/sort_utils.js +44 -24
- package/dist/shared/utils/table_utils.d.ts +6 -5
- package/dist/shared/utils/table_utils.js +13 -56
- package/package.json +7 -7
- package/shared/CellMenu.svelte +90 -10
- package/shared/CellMenuButton.svelte +46 -0
- package/shared/CellMenuIcons.svelte +79 -0
- package/shared/EditableCell.svelte +97 -18
- package/shared/EmptyRowButton.svelte +29 -0
- package/shared/RowNumber.svelte +41 -0
- package/shared/Table.svelte +604 -1235
- package/shared/TableCell.svelte +324 -0
- package/shared/TableHeader.svelte +256 -0
- package/shared/Toolbar.svelte +19 -8
- package/shared/VirtualTable.svelte +72 -19
- package/shared/context/keyboard_context.ts +65 -0
- package/shared/context/selection_context.ts +168 -0
- package/shared/context/table_context.ts +625 -0
- package/shared/icons/Padlock.svelte +24 -0
- package/shared/icons/SelectionButtons.svelte +93 -0
- package/shared/icons/SortArrowDown.svelte +25 -0
- package/shared/icons/SortArrowUp.svelte +25 -0
- package/shared/icons/SortButtonDown.svelte +14 -0
- package/shared/icons/SortButtonUp.svelte +15 -0
- package/shared/icons/SortIcon.svelte +47 -70
- package/shared/selection_utils.ts +39 -13
- package/shared/utils/data_processing.ts +72 -0
- package/shared/utils/drag_utils.ts +92 -0
- package/shared/utils/keyboard_utils.ts +238 -0
- package/shared/utils/sort_utils.test.ts +262 -14
- package/shared/utils/sort_utils.ts +67 -31
- package/shared/utils/table_utils.test.ts +66 -45
- package/shared/utils/table_utils.ts +16 -86
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { describe, test, expect } from "vitest";
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
}
|
|
2
|
+
import { make_cell_id, make_header_id } from "./table_utils";
|
|
3
|
+
import { process_data, make_headers } from "./data_processing";
|
|
4
|
+
|
|
5
|
+
function make_id(): string {
|
|
6
|
+
return Math.random().toString(36).substring(2, 15);
|
|
7
|
+
}
|
|
8
8
|
|
|
9
9
|
describe("table_utils", () => {
|
|
10
10
|
describe("id generation", () => {
|
|
@@ -20,8 +20,8 @@ describe("table_utils", () => {
|
|
|
20
20
|
|
|
21
21
|
test("generates unique header ids", () => {
|
|
22
22
|
const id_set = new Set();
|
|
23
|
-
for (let
|
|
24
|
-
id_set.add(make_header_id(
|
|
23
|
+
for (let i = 0; i < 10; i++) {
|
|
24
|
+
id_set.add(make_header_id(i));
|
|
25
25
|
}
|
|
26
26
|
expect(id_set.size).toBe(10);
|
|
27
27
|
});
|
|
@@ -38,12 +38,9 @@ describe("table_utils", () => {
|
|
|
38
38
|
["1", "2"],
|
|
39
39
|
["3", "4"]
|
|
40
40
|
],
|
|
41
|
-
[2, "fixed"],
|
|
42
|
-
[2, "fixed"],
|
|
43
|
-
["A", "B"],
|
|
44
|
-
true,
|
|
45
41
|
element_refs,
|
|
46
|
-
data_binding
|
|
42
|
+
data_binding,
|
|
43
|
+
make_id
|
|
47
44
|
);
|
|
48
45
|
|
|
49
46
|
expect(test_result[0].map((item) => item.value)).toEqual(["1", "2"]);
|
|
@@ -56,12 +53,9 @@ describe("table_utils", () => {
|
|
|
56
53
|
["1", "2"],
|
|
57
54
|
["3", "4"]
|
|
58
55
|
],
|
|
59
|
-
[2, "fixed"],
|
|
60
|
-
[2, "fixed"],
|
|
61
|
-
["A", "B"],
|
|
62
|
-
false,
|
|
63
56
|
element_refs,
|
|
64
|
-
data_binding
|
|
57
|
+
data_binding,
|
|
58
|
+
make_id
|
|
65
59
|
);
|
|
66
60
|
|
|
67
61
|
expect(test_result.length).toBe(2);
|
|
@@ -71,44 +65,71 @@ describe("table_utils", () => {
|
|
|
71
65
|
});
|
|
72
66
|
|
|
73
67
|
test("handles empty data", () => {
|
|
74
|
-
const test_result = process_data(
|
|
75
|
-
[],
|
|
76
|
-
[0, "dynamic"],
|
|
77
|
-
[0, "dynamic"],
|
|
78
|
-
[],
|
|
79
|
-
false,
|
|
80
|
-
element_refs,
|
|
81
|
-
data_binding
|
|
82
|
-
);
|
|
68
|
+
const test_result = process_data([], element_refs, data_binding, make_id);
|
|
83
69
|
|
|
84
70
|
expect(test_result.length).toBe(0);
|
|
85
71
|
});
|
|
86
72
|
});
|
|
87
73
|
|
|
88
74
|
describe("make_headers", () => {
|
|
89
|
-
|
|
75
|
+
test("creates headers with ids when headers are provided", () => {
|
|
76
|
+
const els = {};
|
|
77
|
+
const headers = ["Name", "Age", "City"];
|
|
78
|
+
const col_count: [number, "fixed" | "dynamic"] = [3, "fixed"];
|
|
90
79
|
|
|
91
|
-
|
|
92
|
-
const test_result = make_headers(
|
|
93
|
-
["A", "B"],
|
|
94
|
-
true,
|
|
95
|
-
[2, "fixed"],
|
|
96
|
-
element_refs
|
|
97
|
-
);
|
|
80
|
+
const result = make_headers(headers, col_count, els, make_id);
|
|
98
81
|
|
|
99
|
-
expect(
|
|
100
|
-
expect(
|
|
101
|
-
expect(
|
|
102
|
-
expect(
|
|
82
|
+
expect(result.length).toBe(3);
|
|
83
|
+
expect(result[0].value).toBe("Name");
|
|
84
|
+
expect(result[1].value).toBe("Age");
|
|
85
|
+
expect(result[2].value).toBe("City");
|
|
86
|
+
expect(result[0].id).toBeDefined();
|
|
87
|
+
expect(result[1].id).toBeDefined();
|
|
88
|
+
expect(result[2].id).toBeDefined();
|
|
89
|
+
expect(Object.keys(els).length).toBe(3);
|
|
103
90
|
});
|
|
104
91
|
|
|
105
|
-
test("
|
|
106
|
-
const
|
|
92
|
+
test("fills missing headers when col_count is fixed", () => {
|
|
93
|
+
const els = {};
|
|
94
|
+
const headers = ["Name", "Age"];
|
|
95
|
+
const col_count: [number, "fixed" | "dynamic"] = [4, "fixed"];
|
|
96
|
+
|
|
97
|
+
const result = make_headers(headers, col_count, els, make_id);
|
|
98
|
+
|
|
99
|
+
expect(result.length).toBe(4);
|
|
100
|
+
expect(result[0].value).toBe("Name");
|
|
101
|
+
expect(result[1].value).toBe("Age");
|
|
102
|
+
expect(result[2].value).toBe("2");
|
|
103
|
+
expect(result[3].value).toBe("3");
|
|
104
|
+
expect(Object.keys(els).length).toBe(4);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
test("creates default headers when no headers are provided", () => {
|
|
108
|
+
const els = {};
|
|
109
|
+
const headers = [];
|
|
110
|
+
const col_count: [number, "fixed" | "dynamic"] = [3, "fixed"];
|
|
111
|
+
|
|
112
|
+
const result = make_headers(headers, col_count, els, make_id);
|
|
113
|
+
|
|
114
|
+
expect(result.length).toBe(3);
|
|
115
|
+
expect(result[0].value).toBe("0");
|
|
116
|
+
expect(result[1].value).toBe("1");
|
|
117
|
+
expect(result[2].value).toBe("2");
|
|
118
|
+
expect(Object.keys(els).length).toBe(3);
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
test("handles null values in headers", () => {
|
|
122
|
+
const els = {};
|
|
123
|
+
const headers = ["Name", null, "City"] as any;
|
|
124
|
+
const col_count: [number, "fixed" | "dynamic"] = [3, "fixed"];
|
|
125
|
+
|
|
126
|
+
const result = make_headers(headers, col_count, els, make_id);
|
|
107
127
|
|
|
108
|
-
expect(
|
|
109
|
-
expect(
|
|
110
|
-
|
|
111
|
-
).toBe(
|
|
128
|
+
expect(result.length).toBe(3);
|
|
129
|
+
expect(result[0].value).toBe("Name");
|
|
130
|
+
expect(result[1].value).toBe("");
|
|
131
|
+
expect(result[2].value).toBe("City");
|
|
132
|
+
expect(Object.keys(els).length).toBe(3);
|
|
112
133
|
});
|
|
113
134
|
});
|
|
114
135
|
});
|
|
@@ -1,12 +1,4 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
Headers,
|
|
3
|
-
HeadersWithIDs,
|
|
4
|
-
TableCell,
|
|
5
|
-
TableData,
|
|
6
|
-
CountConfig,
|
|
7
|
-
ElementRefs,
|
|
8
|
-
DataBinding
|
|
9
|
-
} from "../types";
|
|
1
|
+
import type { Headers, HeadersWithIDs, TableCell, TableData } from "../types";
|
|
10
2
|
import { sort_data } from "./sort_utils";
|
|
11
3
|
import type { SortDirection } from "./sort_utils";
|
|
12
4
|
import { dsvFormat } from "d3-dsv";
|
|
@@ -19,77 +11,6 @@ export function make_header_id(col: number): string {
|
|
|
19
11
|
return `header-${col}`;
|
|
20
12
|
}
|
|
21
13
|
|
|
22
|
-
export function process_data(
|
|
23
|
-
input_values: (string | number)[][],
|
|
24
|
-
row_count: CountConfig,
|
|
25
|
-
col_count: CountConfig,
|
|
26
|
-
headers: Headers,
|
|
27
|
-
show_row_numbers: boolean,
|
|
28
|
-
element_refs: ElementRefs,
|
|
29
|
-
data_binding: DataBinding
|
|
30
|
-
): TableData {
|
|
31
|
-
const data_row_length = input_values.length;
|
|
32
|
-
return Array(row_count[1] === "fixed" ? row_count[0] : data_row_length)
|
|
33
|
-
.fill(0)
|
|
34
|
-
.map((_, row) => {
|
|
35
|
-
return Array(
|
|
36
|
-
col_count[1] === "fixed"
|
|
37
|
-
? col_count[0]
|
|
38
|
-
: data_row_length > 0
|
|
39
|
-
? input_values[0].length
|
|
40
|
-
: headers.length
|
|
41
|
-
)
|
|
42
|
-
.fill(0)
|
|
43
|
-
.map((_, col) => {
|
|
44
|
-
const cell_id = make_cell_id(row, col);
|
|
45
|
-
element_refs[cell_id] = element_refs[cell_id] || {
|
|
46
|
-
input: null,
|
|
47
|
-
cell: null
|
|
48
|
-
};
|
|
49
|
-
const cell_obj: TableCell = {
|
|
50
|
-
value: input_values?.[row]?.[col] ?? "",
|
|
51
|
-
id: cell_id
|
|
52
|
-
};
|
|
53
|
-
data_binding[cell_id] = cell_obj;
|
|
54
|
-
return cell_obj;
|
|
55
|
-
});
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export function make_headers(
|
|
60
|
-
input_headers: Headers,
|
|
61
|
-
show_row_numbers: boolean,
|
|
62
|
-
col_count: CountConfig,
|
|
63
|
-
element_refs: ElementRefs
|
|
64
|
-
): HeadersWithIDs[] {
|
|
65
|
-
let header_list = input_headers || [];
|
|
66
|
-
if (show_row_numbers) {
|
|
67
|
-
header_list = ["", ...header_list];
|
|
68
|
-
}
|
|
69
|
-
if (col_count[1] === "fixed" && header_list.length < col_count[0]) {
|
|
70
|
-
const fill_headers = Array(col_count[0] - header_list.length)
|
|
71
|
-
.fill("")
|
|
72
|
-
.map((_, i) => `${i + header_list.length}`);
|
|
73
|
-
header_list = header_list.concat(fill_headers);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
if (!header_list || header_list.length === 0) {
|
|
77
|
-
return Array(col_count[0])
|
|
78
|
-
.fill(0)
|
|
79
|
-
.map((_, col) => {
|
|
80
|
-
const header_id = make_header_id(col);
|
|
81
|
-
element_refs[header_id] = { cell: null, input: null };
|
|
82
|
-
return { id: header_id, value: JSON.stringify(col + 1) };
|
|
83
|
-
});
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
return header_list.map((header: string | null, col: number) => {
|
|
87
|
-
const header_id = make_header_id(col);
|
|
88
|
-
element_refs[header_id] = { cell: null, input: null };
|
|
89
|
-
return { id: header_id, value: header ?? "" };
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
|
|
93
14
|
export function get_max(data: TableData): TableCell[] {
|
|
94
15
|
if (!data || !data.length) return [];
|
|
95
16
|
let max = data[0].slice();
|
|
@@ -107,10 +28,12 @@ export function sort_table_data(
|
|
|
107
28
|
data: TableData,
|
|
108
29
|
display_value: string[][] | null,
|
|
109
30
|
styling: string[][] | null,
|
|
110
|
-
col: number
|
|
111
|
-
dir: SortDirection
|
|
31
|
+
sort_columns: { col: number; direction: SortDirection }[]
|
|
112
32
|
): void {
|
|
113
|
-
|
|
33
|
+
if (!sort_columns.length) return;
|
|
34
|
+
if (!data || !data.length) return;
|
|
35
|
+
|
|
36
|
+
const indices = sort_data(data, sort_columns);
|
|
114
37
|
|
|
115
38
|
const new_data = indices.map((i: number) => data[i]);
|
|
116
39
|
data.splice(0, data.length, ...new_data);
|
|
@@ -128,9 +51,15 @@ export function sort_table_data(
|
|
|
128
51
|
|
|
129
52
|
export async function copy_table_data(
|
|
130
53
|
data: TableData,
|
|
131
|
-
selected_cells: [number, number][]
|
|
54
|
+
selected_cells: [number, number][] | null
|
|
132
55
|
): Promise<void> {
|
|
133
|
-
|
|
56
|
+
if (!data || !data.length) return;
|
|
57
|
+
|
|
58
|
+
const cells_to_copy =
|
|
59
|
+
selected_cells ||
|
|
60
|
+
data.flatMap((row, r) => row.map((_, c) => [r, c] as [number, number]));
|
|
61
|
+
|
|
62
|
+
const csv = cells_to_copy.reduce(
|
|
134
63
|
(acc: { [key: string]: { [key: string]: string } }, [row, col]) => {
|
|
135
64
|
acc[row] = acc[row] || {};
|
|
136
65
|
const value = String(data[row][col].value);
|
|
@@ -144,6 +73,8 @@ export async function copy_table_data(
|
|
|
144
73
|
);
|
|
145
74
|
|
|
146
75
|
const rows = Object.keys(csv).sort((a, b) => +a - +b);
|
|
76
|
+
if (!rows.length) return;
|
|
77
|
+
|
|
147
78
|
const cols = Object.keys(csv[rows[0]]).sort((a, b) => +a - +b);
|
|
148
79
|
const text = rows
|
|
149
80
|
.map((r) => cols.map((c) => csv[r][c] || "").join(","))
|
|
@@ -152,7 +83,6 @@ export async function copy_table_data(
|
|
|
152
83
|
try {
|
|
153
84
|
await navigator.clipboard.writeText(text);
|
|
154
85
|
} catch (err) {
|
|
155
|
-
console.error("Copy failed:", err);
|
|
156
86
|
throw new Error("Failed to copy to clipboard: " + (err as Error).message);
|
|
157
87
|
}
|
|
158
88
|
}
|