@gradio/dataframe 0.15.0 → 0.16.0
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 +29 -0
- package/Dataframe.stories.svelte +168 -2
- package/Index.svelte +20 -3
- package/dist/Index.svelte +16 -4
- package/dist/Index.svelte.d.ts +12 -0
- package/dist/shared/EditableCell.svelte +1 -4
- package/dist/shared/Table.svelte +423 -181
- package/dist/shared/Table.svelte.d.ts +3 -0
- package/dist/shared/Toolbar.svelte +122 -30
- package/dist/shared/Toolbar.svelte.d.ts +4 -0
- package/dist/shared/VirtualTable.svelte +70 -26
- package/dist/shared/VirtualTable.svelte.d.ts +1 -0
- package/dist/shared/icons/FilterIcon.svelte +11 -0
- package/dist/shared/icons/FilterIcon.svelte.d.ts +16 -0
- package/dist/shared/icons/SortIcon.svelte +90 -0
- package/dist/shared/icons/SortIcon.svelte.d.ts +20 -0
- package/dist/shared/selection_utils.d.ts +12 -2
- package/dist/shared/selection_utils.js +33 -5
- package/dist/shared/types.d.ts +16 -0
- package/dist/shared/types.js +1 -0
- package/dist/shared/utils/menu_utils.d.ts +42 -0
- package/dist/shared/utils/menu_utils.js +58 -0
- package/dist/shared/utils/sort_utils.d.ts +7 -0
- package/dist/shared/utils/sort_utils.js +39 -0
- package/dist/shared/utils/table_utils.d.ts +12 -0
- package/dist/shared/utils/table_utils.js +148 -0
- package/package.json +8 -8
- package/shared/EditableCell.svelte +1 -4
- package/shared/Table.svelte +453 -182
- package/shared/Toolbar.svelte +125 -30
- package/shared/VirtualTable.svelte +73 -26
- package/shared/icons/FilterIcon.svelte +12 -0
- package/shared/icons/SortIcon.svelte +95 -0
- package/shared/selection_utils.ts +51 -9
- package/shared/types.ts +27 -0
- package/shared/utils/menu_utils.ts +115 -0
- package/shared/utils/sort_utils.test.ts +71 -0
- package/shared/utils/sort_utils.ts +55 -0
- package/shared/utils/table_utils.test.ts +114 -0
- package/shared/utils/table_utils.ts +206 -0
- package/dist/shared/table_utils.d.ts +0 -12
- package/dist/shared/table_utils.js +0 -113
- package/shared/table_utils.ts +0 -148
package/dist/shared/Table.svelte
CHANGED
|
@@ -6,6 +6,7 @@ import {} from "@gradio/client";
|
|
|
6
6
|
import VirtualTable from "./VirtualTable.svelte";
|
|
7
7
|
import CellMenu from "./CellMenu.svelte";
|
|
8
8
|
import Toolbar from "./Toolbar.svelte";
|
|
9
|
+
import SortIcon from "./icons/SortIcon.svelte";
|
|
9
10
|
import {
|
|
10
11
|
is_cell_selected,
|
|
11
12
|
handle_selection,
|
|
@@ -15,9 +16,17 @@ import {
|
|
|
15
16
|
get_range_selection,
|
|
16
17
|
move_cursor,
|
|
17
18
|
get_current_indices,
|
|
18
|
-
handle_click_outside as handle_click_outside_util
|
|
19
|
+
handle_click_outside as handle_click_outside_util,
|
|
20
|
+
select_column,
|
|
21
|
+
select_row,
|
|
22
|
+
calculate_selection_positions
|
|
19
23
|
} from "./selection_utils";
|
|
20
|
-
import {
|
|
24
|
+
import {
|
|
25
|
+
copy_table_data,
|
|
26
|
+
get_max,
|
|
27
|
+
handle_file_upload,
|
|
28
|
+
sort_table_data
|
|
29
|
+
} from "./utils/table_utils";
|
|
21
30
|
export let datatype;
|
|
22
31
|
export let label = null;
|
|
23
32
|
export let show_label = true;
|
|
@@ -40,6 +49,11 @@ export let show_fullscreen_button = false;
|
|
|
40
49
|
export let show_copy_button = false;
|
|
41
50
|
export let value_is_output = false;
|
|
42
51
|
export let max_chars = void 0;
|
|
52
|
+
export let show_search = "none";
|
|
53
|
+
export let pinned_columns = 0;
|
|
54
|
+
let actual_pinned_columns = 0;
|
|
55
|
+
$:
|
|
56
|
+
actual_pinned_columns = pinned_columns && data?.[0]?.length ? Math.min(pinned_columns, data[0].length) : 0;
|
|
43
57
|
let selected_cells = [];
|
|
44
58
|
$:
|
|
45
59
|
selected_cells = [...selected_cells];
|
|
@@ -60,33 +74,43 @@ let active_cell_menu = null;
|
|
|
60
74
|
let active_header_menu = null;
|
|
61
75
|
let is_fullscreen = false;
|
|
62
76
|
let dragging = false;
|
|
77
|
+
let copy_flash = false;
|
|
78
|
+
let color_accent_copied;
|
|
79
|
+
onMount(() => {
|
|
80
|
+
const color = getComputedStyle(document.documentElement).getPropertyValue("--color-accent").trim();
|
|
81
|
+
color_accent_copied = color + "40";
|
|
82
|
+
document.documentElement.style.setProperty(
|
|
83
|
+
"--color-accent-copied",
|
|
84
|
+
color_accent_copied
|
|
85
|
+
);
|
|
86
|
+
});
|
|
63
87
|
const get_data_at = (row, col) => data?.[row]?.[col]?.value;
|
|
64
88
|
function make_id() {
|
|
65
89
|
return Math.random().toString(36).substring(2, 15);
|
|
66
90
|
}
|
|
67
|
-
function make_headers(_head) {
|
|
91
|
+
function make_headers(_head, col_count2, els2) {
|
|
68
92
|
let _h = _head || [];
|
|
69
|
-
if (
|
|
70
|
-
const fill = Array(
|
|
93
|
+
if (col_count2[1] === "fixed" && _h.length < col_count2[0]) {
|
|
94
|
+
const fill = Array(col_count2[0] - _h.length).fill("").map((_, i) => `${i + _h.length}`);
|
|
71
95
|
_h = _h.concat(fill);
|
|
72
96
|
}
|
|
73
97
|
if (!_h || _h.length === 0) {
|
|
74
|
-
return Array(
|
|
98
|
+
return Array(col_count2[0]).fill(0).map((_, i) => {
|
|
75
99
|
const _id = make_id();
|
|
76
|
-
|
|
100
|
+
els2[_id] = { cell: null, input: null };
|
|
77
101
|
return { id: _id, value: JSON.stringify(i + 1) };
|
|
78
102
|
});
|
|
79
103
|
}
|
|
80
104
|
return _h.map((h, i) => {
|
|
81
105
|
const _id = make_id();
|
|
82
|
-
|
|
106
|
+
els2[_id] = { cell: null, input: null };
|
|
83
107
|
return { id: _id, value: h ?? "" };
|
|
84
108
|
});
|
|
85
109
|
}
|
|
86
110
|
function process_data(_values) {
|
|
87
111
|
const data_row_length = _values.length;
|
|
88
|
-
return Array(row_count[1] === "fixed" ? row_count[0] : data_row_length).fill(0).map(
|
|
89
|
-
|
|
112
|
+
return Array(row_count[1] === "fixed" ? row_count[0] : data_row_length).fill(0).map((_, i) => {
|
|
113
|
+
return Array(
|
|
90
114
|
col_count[1] === "fixed" ? col_count[0] : data_row_length > 0 ? _values[0].length : headers.length
|
|
91
115
|
).fill(0).map((_2, j) => {
|
|
92
116
|
const id = make_id();
|
|
@@ -94,14 +118,14 @@ function process_data(_values) {
|
|
|
94
118
|
const obj = { value: _values?.[i]?.[j] ?? "", id };
|
|
95
119
|
data_binding[id] = obj;
|
|
96
120
|
return obj;
|
|
97
|
-
})
|
|
98
|
-
);
|
|
121
|
+
});
|
|
122
|
+
});
|
|
99
123
|
}
|
|
100
|
-
let _headers = make_headers(headers);
|
|
124
|
+
let _headers = make_headers(headers, col_count, els);
|
|
101
125
|
let old_headers = headers;
|
|
102
126
|
$: {
|
|
103
127
|
if (!dequal(headers, old_headers)) {
|
|
104
|
-
_headers = make_headers(headers);
|
|
128
|
+
_headers = make_headers(headers, col_count, els);
|
|
105
129
|
old_headers = JSON.parse(JSON.stringify(headers));
|
|
106
130
|
}
|
|
107
131
|
}
|
|
@@ -115,6 +139,8 @@ $:
|
|
|
115
139
|
let previous_headers = _headers.map((h) => h.value);
|
|
116
140
|
let previous_data = data.map((row) => row.map((cell) => String(cell.value)));
|
|
117
141
|
async function trigger_change() {
|
|
142
|
+
if (current_search_query)
|
|
143
|
+
return;
|
|
118
144
|
const current_headers = _headers.map((h) => h.value);
|
|
119
145
|
const current_data = data.map(
|
|
120
146
|
(row) => row.map((cell) => String(cell.value))
|
|
@@ -224,8 +250,10 @@ async function handle_keydown(event) {
|
|
|
224
250
|
editing = false;
|
|
225
251
|
} else {
|
|
226
252
|
selected_cells = [next_coords];
|
|
227
|
-
|
|
228
|
-
|
|
253
|
+
if (editable) {
|
|
254
|
+
editing = next_coords;
|
|
255
|
+
clear_on_focus = false;
|
|
256
|
+
}
|
|
229
257
|
}
|
|
230
258
|
selected = next_coords;
|
|
231
259
|
} else if (next_coords === false && event.key === "ArrowUp" && i === 0) {
|
|
@@ -241,26 +269,26 @@ async function handle_keydown(event) {
|
|
|
241
269
|
editing = false;
|
|
242
270
|
break;
|
|
243
271
|
case "Enter":
|
|
244
|
-
if (!editable)
|
|
245
|
-
break;
|
|
246
272
|
event.preventDefault();
|
|
247
|
-
if (
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
selected = [i + 1, j];
|
|
251
|
-
} else {
|
|
252
|
-
if (dequal(editing, [i, j])) {
|
|
253
|
-
const cell_id = data[i][j].id;
|
|
254
|
-
const input_el = els[cell_id].input;
|
|
255
|
-
if (input_el) {
|
|
256
|
-
data[i][j].value = input_el.value;
|
|
257
|
-
}
|
|
258
|
-
editing = false;
|
|
273
|
+
if (editable) {
|
|
274
|
+
if (event.shiftKey) {
|
|
275
|
+
add_row(i);
|
|
259
276
|
await tick();
|
|
260
|
-
selected = [i, j];
|
|
277
|
+
selected = [i + 1, j];
|
|
261
278
|
} else {
|
|
262
|
-
editing
|
|
263
|
-
|
|
279
|
+
if (dequal(editing, [i, j])) {
|
|
280
|
+
const cell_id = data[i][j].id;
|
|
281
|
+
const input_el = els[cell_id].input;
|
|
282
|
+
if (input_el) {
|
|
283
|
+
data[i][j].value = input_el.value;
|
|
284
|
+
}
|
|
285
|
+
editing = false;
|
|
286
|
+
await tick();
|
|
287
|
+
selected = [i, j];
|
|
288
|
+
} else {
|
|
289
|
+
editing = [i, j];
|
|
290
|
+
clear_on_focus = false;
|
|
291
|
+
}
|
|
264
292
|
}
|
|
265
293
|
}
|
|
266
294
|
break;
|
|
@@ -292,15 +320,16 @@ async function handle_keydown(event) {
|
|
|
292
320
|
}
|
|
293
321
|
let sort_direction;
|
|
294
322
|
let sort_by;
|
|
295
|
-
function handle_sort(col) {
|
|
323
|
+
function handle_sort(col, direction) {
|
|
296
324
|
if (typeof sort_by !== "number" || sort_by !== col) {
|
|
297
|
-
sort_direction =
|
|
325
|
+
sort_direction = direction;
|
|
298
326
|
sort_by = col;
|
|
299
|
-
} else {
|
|
300
|
-
if (sort_direction ===
|
|
301
|
-
sort_direction =
|
|
302
|
-
|
|
303
|
-
|
|
327
|
+
} else if (sort_by === col) {
|
|
328
|
+
if (sort_direction === direction) {
|
|
329
|
+
sort_direction = void 0;
|
|
330
|
+
sort_by = void 0;
|
|
331
|
+
} else {
|
|
332
|
+
sort_direction = direction;
|
|
304
333
|
}
|
|
305
334
|
}
|
|
306
335
|
}
|
|
@@ -388,50 +417,36 @@ let cells = [];
|
|
|
388
417
|
let parent;
|
|
389
418
|
let table;
|
|
390
419
|
function set_cell_widths() {
|
|
391
|
-
const widths = cells.map((el
|
|
392
|
-
return el?.clientWidth || 0;
|
|
393
|
-
});
|
|
420
|
+
const widths = cells.map((el) => el?.clientWidth || 0);
|
|
394
421
|
if (widths.length === 0)
|
|
395
422
|
return;
|
|
396
|
-
|
|
397
|
-
parent.style.setProperty(
|
|
398
|
-
`--cell-width-${i}`,
|
|
399
|
-
`${widths[i] - scrollbar_width / widths.length}px`
|
|
400
|
-
);
|
|
423
|
+
if (show_row_numbers) {
|
|
424
|
+
parent.style.setProperty(`--cell-width-row-number`, `${widths[0]}px`);
|
|
401
425
|
}
|
|
426
|
+
const data_cells = show_row_numbers ? widths.slice(1) : widths;
|
|
427
|
+
data_cells.forEach((width, i) => {
|
|
428
|
+
if (!column_widths[i]) {
|
|
429
|
+
parent.style.setProperty(
|
|
430
|
+
`--cell-width-${i}`,
|
|
431
|
+
`${width - scrollbar_width / data_cells.length}px`
|
|
432
|
+
);
|
|
433
|
+
}
|
|
434
|
+
});
|
|
435
|
+
}
|
|
436
|
+
function get_cell_width(index) {
|
|
437
|
+
return column_widths[index] || `var(--cell-width-${index})`;
|
|
402
438
|
}
|
|
403
439
|
let table_height = values.slice(0, max_height / values.length * 37).length * 37 + 37;
|
|
404
440
|
let scrollbar_width = 0;
|
|
405
441
|
function sort_data(_data, _display_value, _styling, col, dir) {
|
|
406
442
|
let id = null;
|
|
407
|
-
if (selected && selected[0] in
|
|
408
|
-
id =
|
|
443
|
+
if (selected && selected[0] in _data && selected[1] in _data[selected[0]]) {
|
|
444
|
+
id = _data[selected[0]][selected[1]].id;
|
|
409
445
|
}
|
|
410
446
|
if (typeof col !== "number" || !dir) {
|
|
411
447
|
return;
|
|
412
448
|
}
|
|
413
|
-
|
|
414
|
-
if (dir === "asc") {
|
|
415
|
-
indices.sort(
|
|
416
|
-
(i, j) => _data[i][col].value < _data[j][col].value ? -1 : 1
|
|
417
|
-
);
|
|
418
|
-
} else if (dir === "des") {
|
|
419
|
-
indices.sort(
|
|
420
|
-
(i, j) => _data[i][col].value > _data[j][col].value ? -1 : 1
|
|
421
|
-
);
|
|
422
|
-
} else {
|
|
423
|
-
return;
|
|
424
|
-
}
|
|
425
|
-
const temp_data = [..._data];
|
|
426
|
-
const temp_display_value = _display_value ? [..._display_value] : null;
|
|
427
|
-
const temp_styling = _styling ? [..._styling] : null;
|
|
428
|
-
indices.forEach((originalIndex, sortedIndex) => {
|
|
429
|
-
_data[sortedIndex] = temp_data[originalIndex];
|
|
430
|
-
if (_display_value && temp_display_value)
|
|
431
|
-
_display_value[sortedIndex] = temp_display_value[originalIndex];
|
|
432
|
-
if (_styling && temp_styling)
|
|
433
|
-
_styling[sortedIndex] = temp_styling[originalIndex];
|
|
434
|
-
});
|
|
449
|
+
sort_table_data(_data, _display_value, _styling, col, dir);
|
|
435
450
|
data = data;
|
|
436
451
|
if (id) {
|
|
437
452
|
const [i, j] = get_current_indices(id, data);
|
|
@@ -468,25 +483,33 @@ onMount(() => {
|
|
|
468
483
|
};
|
|
469
484
|
});
|
|
470
485
|
function handle_cell_click(event, row, col) {
|
|
486
|
+
if (event.target instanceof HTMLAnchorElement) {
|
|
487
|
+
return;
|
|
488
|
+
}
|
|
471
489
|
event.preventDefault();
|
|
472
490
|
event.stopPropagation();
|
|
491
|
+
if (show_row_numbers && col === -1)
|
|
492
|
+
return;
|
|
473
493
|
clear_on_focus = false;
|
|
474
494
|
active_cell_menu = null;
|
|
475
495
|
active_header_menu = null;
|
|
476
496
|
selected_header = false;
|
|
477
497
|
header_edit = false;
|
|
478
498
|
selected_cells = handle_selection([row, col], selected_cells, event);
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
input_el.
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
499
|
+
parent.focus();
|
|
500
|
+
if (editable) {
|
|
501
|
+
if (selected_cells.length === 1) {
|
|
502
|
+
editing = [row, col];
|
|
503
|
+
tick().then(() => {
|
|
504
|
+
const input_el = els[data[row][col].id].input;
|
|
505
|
+
if (input_el) {
|
|
506
|
+
input_el.focus();
|
|
507
|
+
input_el.selectionStart = input_el.selectionEnd = input_el.value.length;
|
|
508
|
+
}
|
|
509
|
+
});
|
|
510
|
+
} else {
|
|
511
|
+
editing = false;
|
|
512
|
+
}
|
|
490
513
|
}
|
|
491
514
|
toggle_cell_button(row, col);
|
|
492
515
|
dispatch("select", {
|
|
@@ -522,6 +545,9 @@ function add_col_at(index, position) {
|
|
|
522
545
|
function handle_resize() {
|
|
523
546
|
active_cell_menu = null;
|
|
524
547
|
active_header_menu = null;
|
|
548
|
+
selected_cells = [];
|
|
549
|
+
selected = false;
|
|
550
|
+
editing = false;
|
|
525
551
|
set_cell_widths();
|
|
526
552
|
}
|
|
527
553
|
let active_button = null;
|
|
@@ -544,7 +570,11 @@ function handle_fullscreen_change() {
|
|
|
544
570
|
is_fullscreen = !!document.fullscreenElement;
|
|
545
571
|
}
|
|
546
572
|
async function handle_copy() {
|
|
547
|
-
await copy_table_data(data,
|
|
573
|
+
await copy_table_data(data, selected_cells);
|
|
574
|
+
copy_flash = true;
|
|
575
|
+
setTimeout(() => {
|
|
576
|
+
copy_flash = false;
|
|
577
|
+
}, 800);
|
|
548
578
|
}
|
|
549
579
|
function toggle_header_menu(event, col) {
|
|
550
580
|
event.stopPropagation();
|
|
@@ -595,6 +625,78 @@ function delete_col_at(index) {
|
|
|
595
625
|
active_cell_menu = null;
|
|
596
626
|
active_header_menu = null;
|
|
597
627
|
}
|
|
628
|
+
let row_order = [];
|
|
629
|
+
$: {
|
|
630
|
+
if (typeof sort_by === "number" && sort_direction && sort_by >= 0 && sort_by < data[0].length) {
|
|
631
|
+
const indices = [...Array(data.length)].map((_, i) => i);
|
|
632
|
+
const sort_index = sort_by;
|
|
633
|
+
indices.sort((a, b) => {
|
|
634
|
+
const row_a = data[a];
|
|
635
|
+
const row_b = data[b];
|
|
636
|
+
if (!row_a || !row_b || sort_index >= row_a.length || sort_index >= row_b.length)
|
|
637
|
+
return 0;
|
|
638
|
+
const val_a = row_a[sort_index].value;
|
|
639
|
+
const val_b = row_b[sort_index].value;
|
|
640
|
+
const comp = val_a < val_b ? -1 : val_a > val_b ? 1 : 0;
|
|
641
|
+
return sort_direction === "asc" ? comp : -comp;
|
|
642
|
+
});
|
|
643
|
+
row_order = indices;
|
|
644
|
+
} else {
|
|
645
|
+
row_order = [...Array(data.length)].map((_, i) => i);
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
function handle_select_column(col) {
|
|
649
|
+
selected_cells = select_column(data, col);
|
|
650
|
+
selected = selected_cells[0];
|
|
651
|
+
editing = false;
|
|
652
|
+
}
|
|
653
|
+
function handle_select_row(row) {
|
|
654
|
+
selected_cells = select_row(data, row);
|
|
655
|
+
selected = selected_cells[0];
|
|
656
|
+
editing = false;
|
|
657
|
+
}
|
|
658
|
+
let coords;
|
|
659
|
+
$:
|
|
660
|
+
if (selected !== false)
|
|
661
|
+
coords = selected;
|
|
662
|
+
$:
|
|
663
|
+
if (selected !== false) {
|
|
664
|
+
const positions = calculate_selection_positions(
|
|
665
|
+
selected,
|
|
666
|
+
data,
|
|
667
|
+
els,
|
|
668
|
+
parent,
|
|
669
|
+
table
|
|
670
|
+
);
|
|
671
|
+
document.documentElement.style.setProperty(
|
|
672
|
+
"--selected-col-pos",
|
|
673
|
+
positions.col_pos
|
|
674
|
+
);
|
|
675
|
+
if (positions.row_pos) {
|
|
676
|
+
document.documentElement.style.setProperty(
|
|
677
|
+
"--selected-row-pos",
|
|
678
|
+
positions.row_pos
|
|
679
|
+
);
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
let current_search_query = null;
|
|
683
|
+
function handle_search(search_query) {
|
|
684
|
+
current_search_query = search_query;
|
|
685
|
+
dispatch("search", search_query);
|
|
686
|
+
}
|
|
687
|
+
function commit_filter() {
|
|
688
|
+
if (current_search_query && show_search === "filter") {
|
|
689
|
+
dispatch("change", {
|
|
690
|
+
data: data.map((row) => row.map((cell) => cell.value)),
|
|
691
|
+
headers: _headers.map((h) => h.value),
|
|
692
|
+
metadata: null
|
|
693
|
+
});
|
|
694
|
+
if (!value_is_output) {
|
|
695
|
+
dispatch("input");
|
|
696
|
+
}
|
|
697
|
+
current_search_query = null;
|
|
698
|
+
}
|
|
699
|
+
}
|
|
598
700
|
</script>
|
|
599
701
|
|
|
600
702
|
<svelte:window on:resize={() => set_cell_widths()} />
|
|
@@ -612,6 +714,10 @@ function delete_col_at(index) {
|
|
|
612
714
|
on:click={toggle_fullscreen}
|
|
613
715
|
on_copy={handle_copy}
|
|
614
716
|
{show_copy_button}
|
|
717
|
+
{show_search}
|
|
718
|
+
on:search={(e) => handle_search(e.detail)}
|
|
719
|
+
on_commit_filter={commit_filter}
|
|
720
|
+
{current_search_query}
|
|
615
721
|
/>
|
|
616
722
|
</div>
|
|
617
723
|
<div
|
|
@@ -619,11 +725,28 @@ function delete_col_at(index) {
|
|
|
619
725
|
class="table-wrap"
|
|
620
726
|
class:dragging
|
|
621
727
|
class:no-wrap={!wrap}
|
|
622
|
-
style="height:{table_height}px"
|
|
728
|
+
style="height:{table_height}px;"
|
|
729
|
+
class:menu-open={active_cell_menu || active_header_menu}
|
|
623
730
|
on:keydown={(e) => handle_keydown(e)}
|
|
624
731
|
role="grid"
|
|
625
732
|
tabindex="0"
|
|
626
733
|
>
|
|
734
|
+
{#if selected !== false && selected_cells.length === 1}
|
|
735
|
+
<button
|
|
736
|
+
class="selection-button selection-button-column"
|
|
737
|
+
on:click|stopPropagation={() => handle_select_column(coords[1])}
|
|
738
|
+
aria-label="Select column"
|
|
739
|
+
>
|
|
740
|
+
⋮
|
|
741
|
+
</button>
|
|
742
|
+
<button
|
|
743
|
+
class="selection-button selection-button-row"
|
|
744
|
+
on:click|stopPropagation={() => handle_select_row(coords[0])}
|
|
745
|
+
aria-label="Select row"
|
|
746
|
+
>
|
|
747
|
+
⋮
|
|
748
|
+
</button>
|
|
749
|
+
{/if}
|
|
627
750
|
<table
|
|
628
751
|
bind:contentRect={t_rect}
|
|
629
752
|
bind:this={table}
|
|
@@ -635,40 +758,59 @@ function delete_col_at(index) {
|
|
|
635
758
|
<thead>
|
|
636
759
|
<tr>
|
|
637
760
|
{#if show_row_numbers}
|
|
638
|
-
<th
|
|
761
|
+
<th
|
|
762
|
+
class="row-number-header frozen-column always-frozen"
|
|
763
|
+
style="left: 0;"
|
|
764
|
+
>
|
|
765
|
+
<div class="cell-wrap">
|
|
766
|
+
<div class="header-content">
|
|
767
|
+
<div class="header-text"></div>
|
|
768
|
+
</div>
|
|
769
|
+
</div>
|
|
770
|
+
</th>
|
|
639
771
|
{/if}
|
|
640
772
|
{#each _headers as { value, id }, i (id)}
|
|
641
773
|
<th
|
|
774
|
+
class:frozen-column={i < actual_pinned_columns}
|
|
775
|
+
class:last-frozen={show_row_numbers
|
|
776
|
+
? i === actual_pinned_columns - 1
|
|
777
|
+
: i === actual_pinned_columns - 1}
|
|
642
778
|
class:editing={header_edit === i}
|
|
643
779
|
aria-sort={get_sort_status(value, sort_by, sort_direction)}
|
|
644
|
-
style:
|
|
780
|
+
style="width: {column_widths.length
|
|
781
|
+
? column_widths[i]
|
|
782
|
+
: undefined}; left: {i < actual_pinned_columns
|
|
783
|
+
? i === 0
|
|
784
|
+
? show_row_numbers
|
|
785
|
+
? 'var(--cell-width-row-number)'
|
|
786
|
+
: '0'
|
|
787
|
+
: `calc(${show_row_numbers ? 'var(--cell-width-row-number) + ' : ''}${Array(
|
|
788
|
+
i
|
|
789
|
+
)
|
|
790
|
+
.fill(0)
|
|
791
|
+
.map((_, idx) => `var(--cell-width-${idx})`)
|
|
792
|
+
.join(' + ')})`
|
|
793
|
+
: 'auto'};"
|
|
645
794
|
>
|
|
646
795
|
<div class="cell-wrap">
|
|
647
|
-
<
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
height="1em"
|
|
666
|
-
viewBox="0 0 9 7"
|
|
667
|
-
fill="none"
|
|
668
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
669
|
-
>
|
|
670
|
-
<path d="M4.49999 0L8.3971 6.75H0.602875L4.49999 0Z" />
|
|
671
|
-
</svg>
|
|
796
|
+
<div class="header-content">
|
|
797
|
+
<EditableCell
|
|
798
|
+
{value}
|
|
799
|
+
{latex_delimiters}
|
|
800
|
+
{line_breaks}
|
|
801
|
+
header
|
|
802
|
+
edit={false}
|
|
803
|
+
el={null}
|
|
804
|
+
{root}
|
|
805
|
+
{editable}
|
|
806
|
+
/>
|
|
807
|
+
<div class="sort-buttons">
|
|
808
|
+
<SortIcon
|
|
809
|
+
direction={sort_by === i ? sort_direction : null}
|
|
810
|
+
on:sort={({ detail }) => handle_sort(i, detail)}
|
|
811
|
+
{i18n}
|
|
812
|
+
/>
|
|
813
|
+
</div>
|
|
672
814
|
</div>
|
|
673
815
|
</div>
|
|
674
816
|
</th>
|
|
@@ -707,9 +849,12 @@ function delete_col_at(index) {
|
|
|
707
849
|
on:load={({ detail }) =>
|
|
708
850
|
handle_file_upload(
|
|
709
851
|
detail.data,
|
|
710
|
-
col_count,
|
|
711
852
|
(head) => {
|
|
712
|
-
_headers = make_headers(
|
|
853
|
+
_headers = make_headers(
|
|
854
|
+
head.map((h) => h ?? ""),
|
|
855
|
+
col_count,
|
|
856
|
+
els
|
|
857
|
+
);
|
|
713
858
|
return _headers;
|
|
714
859
|
},
|
|
715
860
|
(vals) => {
|
|
@@ -725,19 +870,44 @@ function delete_col_at(index) {
|
|
|
725
870
|
bind:actual_height={table_height}
|
|
726
871
|
bind:table_scrollbar_width={scrollbar_width}
|
|
727
872
|
selected={selected_index}
|
|
873
|
+
disable_scroll={active_cell_menu !== null ||
|
|
874
|
+
active_header_menu !== null}
|
|
728
875
|
>
|
|
729
876
|
{#if label && label.length !== 0}
|
|
730
877
|
<caption class="sr-only">{label}</caption>
|
|
731
878
|
{/if}
|
|
732
879
|
<tr slot="thead">
|
|
733
880
|
{#if show_row_numbers}
|
|
734
|
-
<th
|
|
881
|
+
<th
|
|
882
|
+
class="row-number-header frozen-column always-frozen"
|
|
883
|
+
style="left: 0;"
|
|
884
|
+
>
|
|
885
|
+
<div class="cell-wrap">
|
|
886
|
+
<div class="header-content">
|
|
887
|
+
<div class="header-text"></div>
|
|
888
|
+
</div>
|
|
889
|
+
</div>
|
|
890
|
+
</th>
|
|
735
891
|
{/if}
|
|
736
892
|
{#each _headers as { value, id }, i (id)}
|
|
737
893
|
<th
|
|
894
|
+
class:frozen-column={i < actual_pinned_columns}
|
|
895
|
+
class:last-frozen={i === actual_pinned_columns - 1}
|
|
738
896
|
class:focus={header_edit === i || selected_header === i}
|
|
739
897
|
aria-sort={get_sort_status(value, sort_by, sort_direction)}
|
|
740
|
-
style="width:
|
|
898
|
+
style="width: {get_cell_width(i)}; left: {i <
|
|
899
|
+
actual_pinned_columns
|
|
900
|
+
? i === 0
|
|
901
|
+
? show_row_numbers
|
|
902
|
+
? 'var(--cell-width-row-number)'
|
|
903
|
+
: '0'
|
|
904
|
+
: `calc(${show_row_numbers ? 'var(--cell-width-row-number) + ' : ''}${Array(
|
|
905
|
+
i
|
|
906
|
+
)
|
|
907
|
+
.fill(0)
|
|
908
|
+
.map((_, idx) => `var(--cell-width-${idx})`)
|
|
909
|
+
.join(' + ')})`
|
|
910
|
+
: 'auto'};"
|
|
741
911
|
on:click={() => {
|
|
742
912
|
toggle_header_button(i);
|
|
743
913
|
}}
|
|
@@ -757,28 +927,14 @@ function delete_col_at(index) {
|
|
|
757
927
|
{root}
|
|
758
928
|
{editable}
|
|
759
929
|
/>
|
|
760
|
-
<
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
handle_sort(i);
|
|
768
|
-
}}
|
|
769
|
-
>
|
|
770
|
-
<svg
|
|
771
|
-
width="1em"
|
|
772
|
-
height="1em"
|
|
773
|
-
viewBox="0 0 9 7"
|
|
774
|
-
fill="none"
|
|
775
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
776
|
-
>
|
|
777
|
-
<path d="M4.49999 0L8.3971 6.75H0.602875L4.49999 0Z" />
|
|
778
|
-
</svg>
|
|
779
|
-
</button>
|
|
930
|
+
<div class="sort-buttons">
|
|
931
|
+
<SortIcon
|
|
932
|
+
direction={sort_by === i ? sort_direction : null}
|
|
933
|
+
on:sort={({ detail }) => handle_sort(i, detail)}
|
|
934
|
+
{i18n}
|
|
935
|
+
/>
|
|
936
|
+
</div>
|
|
780
937
|
</div>
|
|
781
|
-
|
|
782
938
|
{#if editable}
|
|
783
939
|
<button
|
|
784
940
|
class="cell-menu-button"
|
|
@@ -791,14 +947,22 @@ function delete_col_at(index) {
|
|
|
791
947
|
</th>
|
|
792
948
|
{/each}
|
|
793
949
|
</tr>
|
|
794
|
-
|
|
795
950
|
<tr slot="tbody" let:item let:index class:row_odd={index % 2 === 0}>
|
|
796
951
|
{#if show_row_numbers}
|
|
797
|
-
<td
|
|
952
|
+
<td
|
|
953
|
+
class="row-number frozen-column always-frozen"
|
|
954
|
+
style="left: 0;"
|
|
955
|
+
tabindex="-1"
|
|
956
|
+
>
|
|
957
|
+
{index + 1}
|
|
958
|
+
</td>
|
|
798
959
|
{/if}
|
|
799
960
|
{#each item as { value, id }, j (id)}
|
|
800
961
|
<td
|
|
801
|
-
|
|
962
|
+
class:frozen-column={j < actual_pinned_columns}
|
|
963
|
+
class:last-frozen={j === actual_pinned_columns - 1}
|
|
964
|
+
tabindex={show_row_numbers && j === 0 ? -1 : 0}
|
|
965
|
+
bind:this={els[id].cell}
|
|
802
966
|
on:touchstart={(event) => {
|
|
803
967
|
const touch = event.touches[0];
|
|
804
968
|
const mouseEvent = new MouseEvent("click", {
|
|
@@ -815,8 +979,21 @@ function delete_col_at(index) {
|
|
|
815
979
|
event.stopPropagation();
|
|
816
980
|
}}
|
|
817
981
|
on:click={(event) => handle_cell_click(event, index, j)}
|
|
818
|
-
style
|
|
819
|
-
|
|
982
|
+
style="width: {get_cell_width(j)}; left: {j <
|
|
983
|
+
actual_pinned_columns
|
|
984
|
+
? j === 0
|
|
985
|
+
? show_row_numbers
|
|
986
|
+
? 'var(--cell-width-row-number)'
|
|
987
|
+
: '0'
|
|
988
|
+
: `calc(${show_row_numbers ? 'var(--cell-width-row-number) + ' : ''}${Array(
|
|
989
|
+
j
|
|
990
|
+
)
|
|
991
|
+
.fill(0)
|
|
992
|
+
.map((_, idx) => `var(--cell-width-${idx})`)
|
|
993
|
+
.join(' + ')})`
|
|
994
|
+
: 'auto'}; {styling?.[index]?.[j] || ''}"
|
|
995
|
+
class:flash={copy_flash &&
|
|
996
|
+
is_cell_selected([index, j], selected_cells)}
|
|
820
997
|
class={is_cell_selected([index, j], selected_cells)}
|
|
821
998
|
class:menu-active={active_cell_menu &&
|
|
822
999
|
active_cell_menu.row === index &&
|
|
@@ -906,6 +1083,14 @@ function delete_col_at(index) {
|
|
|
906
1083
|
{/if}
|
|
907
1084
|
|
|
908
1085
|
<style>
|
|
1086
|
+
.label p {
|
|
1087
|
+
position: relative;
|
|
1088
|
+
z-index: var(--layer-4);
|
|
1089
|
+
margin-bottom: var(--size-2);
|
|
1090
|
+
color: var(--block-label-text-color);
|
|
1091
|
+
font-size: var(--block-label-text-size);
|
|
1092
|
+
}
|
|
1093
|
+
|
|
909
1094
|
.table-container {
|
|
910
1095
|
display: flex;
|
|
911
1096
|
flex-direction: column;
|
|
@@ -917,6 +1102,9 @@ function delete_col_at(index) {
|
|
|
917
1102
|
transition: 150ms;
|
|
918
1103
|
border: 1px solid var(--border-color-primary);
|
|
919
1104
|
border-radius: var(--table-radius);
|
|
1105
|
+
}
|
|
1106
|
+
|
|
1107
|
+
.table-wrap.menu-open {
|
|
920
1108
|
overflow: hidden;
|
|
921
1109
|
}
|
|
922
1110
|
|
|
@@ -961,8 +1149,7 @@ function delete_col_at(index) {
|
|
|
961
1149
|
thead {
|
|
962
1150
|
position: sticky;
|
|
963
1151
|
top: 0;
|
|
964
|
-
|
|
965
|
-
z-index: var(--layer-1);
|
|
1152
|
+
z-index: var(--layer-2);
|
|
966
1153
|
box-shadow: var(--shadow-drop);
|
|
967
1154
|
}
|
|
968
1155
|
|
|
@@ -1018,32 +1205,10 @@ function delete_col_at(index) {
|
|
|
1018
1205
|
background: var(--table-even-background-fill);
|
|
1019
1206
|
}
|
|
1020
1207
|
|
|
1021
|
-
|
|
1022
|
-
fill: currentColor;
|
|
1023
|
-
font-size: 10px;
|
|
1024
|
-
}
|
|
1025
|
-
|
|
1026
|
-
.sort-button {
|
|
1208
|
+
.sort-buttons {
|
|
1027
1209
|
display: flex;
|
|
1028
|
-
flex: none;
|
|
1029
|
-
justify-content: center;
|
|
1030
1210
|
align-items: center;
|
|
1031
|
-
|
|
1032
|
-
cursor: pointer;
|
|
1033
|
-
padding: var(--size-2);
|
|
1034
|
-
color: var(--body-text-color-subdued);
|
|
1035
|
-
}
|
|
1036
|
-
|
|
1037
|
-
.sort-button:hover {
|
|
1038
|
-
color: var(--body-text-color);
|
|
1039
|
-
}
|
|
1040
|
-
|
|
1041
|
-
.des {
|
|
1042
|
-
transform: scaleY(-1);
|
|
1043
|
-
}
|
|
1044
|
-
|
|
1045
|
-
.sort-button.sorted {
|
|
1046
|
-
color: var(--color-accent);
|
|
1211
|
+
flex-shrink: 0;
|
|
1047
1212
|
}
|
|
1048
1213
|
|
|
1049
1214
|
.editing {
|
|
@@ -1062,12 +1227,16 @@ function delete_col_at(index) {
|
|
|
1062
1227
|
.header-content {
|
|
1063
1228
|
display: flex;
|
|
1064
1229
|
align-items: center;
|
|
1230
|
+
justify-content: space-between;
|
|
1065
1231
|
overflow: hidden;
|
|
1066
1232
|
flex-grow: 1;
|
|
1067
1233
|
min-width: 0;
|
|
1068
1234
|
white-space: normal;
|
|
1069
1235
|
overflow-wrap: break-word;
|
|
1070
|
-
word-break:
|
|
1236
|
+
word-break: normal;
|
|
1237
|
+
height: 100%;
|
|
1238
|
+
padding: var(--size-1);
|
|
1239
|
+
gap: var(--size-1);
|
|
1071
1240
|
}
|
|
1072
1241
|
|
|
1073
1242
|
.row_odd {
|
|
@@ -1104,46 +1273,55 @@ function delete_col_at(index) {
|
|
|
1104
1273
|
|
|
1105
1274
|
.header-row {
|
|
1106
1275
|
display: flex;
|
|
1107
|
-
justify-content:
|
|
1276
|
+
justify-content: flex-end;
|
|
1108
1277
|
align-items: center;
|
|
1109
1278
|
gap: var(--size-2);
|
|
1110
|
-
height: var(--size-6);
|
|
1111
1279
|
min-height: var(--size-6);
|
|
1280
|
+
flex-wrap: nowrap;
|
|
1281
|
+
width: 100%;
|
|
1112
1282
|
}
|
|
1113
1283
|
|
|
1114
1284
|
.label {
|
|
1115
|
-
flex: 1;
|
|
1285
|
+
flex: 1 1 auto;
|
|
1286
|
+
margin-right: auto;
|
|
1116
1287
|
}
|
|
1117
1288
|
|
|
1118
1289
|
.label p {
|
|
1119
1290
|
margin: 0;
|
|
1120
1291
|
color: var(--block-label-text-color);
|
|
1121
1292
|
font-size: var(--block-label-text-size);
|
|
1293
|
+
line-height: var(--line-sm);
|
|
1294
|
+
}
|
|
1295
|
+
|
|
1296
|
+
.toolbar {
|
|
1297
|
+
flex: 0 0 auto;
|
|
1122
1298
|
}
|
|
1123
1299
|
|
|
1124
1300
|
.row-number,
|
|
1125
1301
|
.row-number-header {
|
|
1126
|
-
width: var(--size-7);
|
|
1127
|
-
min-width: var(--size-7);
|
|
1128
1302
|
text-align: center;
|
|
1129
1303
|
background: var(--table-even-background-fill);
|
|
1130
|
-
position: sticky;
|
|
1131
|
-
left: 0;
|
|
1132
1304
|
font-size: var(--input-text-size);
|
|
1133
1305
|
color: var(--body-text-color);
|
|
1134
|
-
padding: var(--size-1)
|
|
1306
|
+
padding: var(--size-1);
|
|
1307
|
+
min-width: var(--size-12);
|
|
1308
|
+
width: var(--size-12);
|
|
1135
1309
|
overflow: hidden;
|
|
1136
1310
|
text-overflow: ellipsis;
|
|
1137
1311
|
white-space: nowrap;
|
|
1138
1312
|
font-weight: var(--weight-semibold);
|
|
1139
1313
|
}
|
|
1140
1314
|
|
|
1141
|
-
.row-number-header {
|
|
1142
|
-
|
|
1315
|
+
.row-number-header .header-content {
|
|
1316
|
+
justify-content: space-between;
|
|
1317
|
+
padding: var(--size-1);
|
|
1318
|
+
height: var(--size-9);
|
|
1319
|
+
display: flex;
|
|
1320
|
+
align-items: center;
|
|
1143
1321
|
}
|
|
1144
1322
|
|
|
1145
|
-
.row-number {
|
|
1146
|
-
|
|
1323
|
+
.row-number-header :global(.sort-icons) {
|
|
1324
|
+
margin-right: 0;
|
|
1147
1325
|
}
|
|
1148
1326
|
|
|
1149
1327
|
:global(tbody > tr:nth-child(odd)) .row-number {
|
|
@@ -1240,4 +1418,68 @@ function delete_col_at(index) {
|
|
|
1240
1418
|
.cell-selected.no-top.no-bottom.no-left.no-right {
|
|
1241
1419
|
box-shadow: none;
|
|
1242
1420
|
}
|
|
1421
|
+
|
|
1422
|
+
.selection-button {
|
|
1423
|
+
position: absolute;
|
|
1424
|
+
display: flex;
|
|
1425
|
+
align-items: center;
|
|
1426
|
+
justify-content: center;
|
|
1427
|
+
background: var(--color-accent);
|
|
1428
|
+
color: white;
|
|
1429
|
+
border-radius: var(--radius-sm);
|
|
1430
|
+
z-index: var(--layer-4);
|
|
1431
|
+
}
|
|
1432
|
+
|
|
1433
|
+
.selection-button-column {
|
|
1434
|
+
width: var(--size-3);
|
|
1435
|
+
height: var(--size-5);
|
|
1436
|
+
top: -10px;
|
|
1437
|
+
left: var(--selected-col-pos);
|
|
1438
|
+
transform: rotate(90deg);
|
|
1439
|
+
}
|
|
1440
|
+
|
|
1441
|
+
.selection-button-row {
|
|
1442
|
+
width: var(--size-3);
|
|
1443
|
+
height: var(--size-5);
|
|
1444
|
+
left: -7px;
|
|
1445
|
+
top: calc(var(--selected-row-pos) - var(--size-5) / 2);
|
|
1446
|
+
}
|
|
1447
|
+
|
|
1448
|
+
.table-wrap:not(:focus-within) .selection-button {
|
|
1449
|
+
opacity: 0;
|
|
1450
|
+
pointer-events: none;
|
|
1451
|
+
}
|
|
1452
|
+
|
|
1453
|
+
.flash.cell-selected {
|
|
1454
|
+
animation: flash-color 700ms ease-out;
|
|
1455
|
+
}
|
|
1456
|
+
|
|
1457
|
+
@keyframes flash-color {
|
|
1458
|
+
0%,
|
|
1459
|
+
30% {
|
|
1460
|
+
background: var(--color-accent-copied);
|
|
1461
|
+
}
|
|
1462
|
+
|
|
1463
|
+
100% {
|
|
1464
|
+
background: transparent;
|
|
1465
|
+
}
|
|
1466
|
+
}
|
|
1467
|
+
|
|
1468
|
+
.frozen-column {
|
|
1469
|
+
position: sticky;
|
|
1470
|
+
z-index: var(--layer-2);
|
|
1471
|
+
border-right: 1px solid var(--border-color-primary);
|
|
1472
|
+
}
|
|
1473
|
+
|
|
1474
|
+
tr:nth-child(odd) .frozen-column {
|
|
1475
|
+
background: var(--table-odd-background-fill);
|
|
1476
|
+
}
|
|
1477
|
+
|
|
1478
|
+
tr:nth-child(even) .frozen-column {
|
|
1479
|
+
background: var(--table-even-background-fill);
|
|
1480
|
+
}
|
|
1481
|
+
|
|
1482
|
+
.always-frozen {
|
|
1483
|
+
z-index: var(--layer-3);
|
|
1484
|
+
}
|
|
1243
1485
|
</style>
|