@gradio/dataframe 0.16.0 → 0.16.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 +7 -0
- package/Dataframe.stories.svelte +15 -0
- package/Example.svelte +7 -0
- package/dist/Example.svelte +7 -0
- package/dist/shared/CellMenu.svelte +1 -1
- package/dist/shared/EditableCell.svelte +1 -3
- package/dist/shared/Table.svelte +264 -205
- package/package.json +4 -4
- package/shared/CellMenu.svelte +1 -1
- package/shared/EditableCell.svelte +1 -3
- package/shared/Table.svelte +263 -207
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# @gradio/dataframe
|
|
2
2
|
|
|
3
|
+
## 0.16.1
|
|
4
|
+
|
|
5
|
+
### Fixes
|
|
6
|
+
|
|
7
|
+
- [#10607](https://github.com/gradio-app/gradio/pull/10607) [`c354f5f`](https://github.com/gradio-app/gradio/commit/c354f5ff16c787d722f4e53d5a97f729abba955e) - Add empty dataframe functionality. Thanks @hannahblair!
|
|
8
|
+
- [#10596](https://github.com/gradio-app/gradio/pull/10596) [`a8bde76`](https://github.com/gradio-app/gradio/commit/a8bde76e2b0f65b3565019beb03ac8b1fd152963) - Fix margin above `gr.Dataframe` when no header is provided. Thanks @abidlabs!
|
|
9
|
+
|
|
3
10
|
## 0.16.0
|
|
4
11
|
|
|
5
12
|
### Features
|
package/Dataframe.stories.svelte
CHANGED
|
@@ -152,6 +152,21 @@
|
|
|
152
152
|
}}
|
|
153
153
|
/>
|
|
154
154
|
|
|
155
|
+
<Story
|
|
156
|
+
name="Dataframe without a label"
|
|
157
|
+
args={{
|
|
158
|
+
values: [
|
|
159
|
+
[800, 100, 800],
|
|
160
|
+
[200, 800, 700]
|
|
161
|
+
],
|
|
162
|
+
headers: ["Math", "Reading", "Writing"],
|
|
163
|
+
show_label: false,
|
|
164
|
+
col_count: [3, "dynamic"],
|
|
165
|
+
row_count: [2, "dynamic"],
|
|
166
|
+
editable: false
|
|
167
|
+
}}
|
|
168
|
+
/>
|
|
169
|
+
|
|
155
170
|
<Story
|
|
156
171
|
name="Dataframe with different colors"
|
|
157
172
|
args={{
|
package/Example.svelte
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
let hovered = false;
|
|
8
8
|
let loaded = Array.isArray(value);
|
|
9
|
+
let is_empty = loaded && (value.length === 0 || value[0].length === 0);
|
|
9
10
|
</script>
|
|
10
11
|
|
|
11
12
|
{#if loaded}
|
|
@@ -20,6 +21,12 @@
|
|
|
20
21
|
>
|
|
21
22
|
{#if typeof value === "string"}
|
|
22
23
|
{value}
|
|
24
|
+
{:else if is_empty}
|
|
25
|
+
<table class="">
|
|
26
|
+
<tr>
|
|
27
|
+
<td>Empty</td>
|
|
28
|
+
</tr>
|
|
29
|
+
</table>
|
|
23
30
|
{:else}
|
|
24
31
|
<table class="">
|
|
25
32
|
{#each value.slice(0, 3) as row, i}
|
package/dist/Example.svelte
CHANGED
|
@@ -4,6 +4,7 @@ export let selected = false;
|
|
|
4
4
|
export let index;
|
|
5
5
|
let hovered = false;
|
|
6
6
|
let loaded = Array.isArray(value);
|
|
7
|
+
let is_empty = loaded && (value.length === 0 || value[0].length === 0);
|
|
7
8
|
</script>
|
|
8
9
|
|
|
9
10
|
{#if loaded}
|
|
@@ -18,6 +19,12 @@ let loaded = Array.isArray(value);
|
|
|
18
19
|
>
|
|
19
20
|
{#if typeof value === "string"}
|
|
20
21
|
{value}
|
|
22
|
+
{:else if is_empty}
|
|
23
|
+
<table class="">
|
|
24
|
+
<tr>
|
|
25
|
+
<td>Empty</td>
|
|
26
|
+
</tr>
|
|
27
|
+
</table>
|
|
21
28
|
{:else}
|
|
22
29
|
<table class="">
|
|
23
30
|
{#each value.slice(0, 3) as row, i}
|
|
@@ -81,7 +81,7 @@ function position_menu() {
|
|
|
81
81
|
<style>
|
|
82
82
|
.cell-menu {
|
|
83
83
|
position: fixed;
|
|
84
|
-
z-index: var(--layer-
|
|
84
|
+
z-index: var(--layer-4);
|
|
85
85
|
background: var(--background-fill-primary);
|
|
86
86
|
border: 1px solid var(--border-color-primary);
|
|
87
87
|
border-radius: var(--radius-sm);
|
|
@@ -84,7 +84,6 @@ function handle_click() {
|
|
|
84
84
|
class:multiline={header}
|
|
85
85
|
on:focus|preventDefault
|
|
86
86
|
style={styling}
|
|
87
|
-
class="table-cell-text"
|
|
88
87
|
data-editable={editable}
|
|
89
88
|
placeholder=" "
|
|
90
89
|
>
|
|
@@ -123,8 +122,6 @@ function handle_click() {
|
|
|
123
122
|
position: relative;
|
|
124
123
|
display: inline-block;
|
|
125
124
|
outline: none;
|
|
126
|
-
padding: var(--size-2);
|
|
127
|
-
padding-right: 0;
|
|
128
125
|
-webkit-user-select: text;
|
|
129
126
|
-moz-user-select: text;
|
|
130
127
|
-ms-user-select: text;
|
|
@@ -151,6 +148,7 @@ function handle_click() {
|
|
|
151
148
|
font-weight: var(--weight-bold);
|
|
152
149
|
white-space: normal;
|
|
153
150
|
word-break: break-word;
|
|
151
|
+
margin-left: var(--size-1);
|
|
154
152
|
}
|
|
155
153
|
|
|
156
154
|
.edit {
|
package/dist/shared/Table.svelte
CHANGED
|
@@ -109,9 +109,11 @@ function make_headers(_head, col_count2, els2) {
|
|
|
109
109
|
}
|
|
110
110
|
function process_data(_values) {
|
|
111
111
|
const data_row_length = _values.length;
|
|
112
|
+
if (data_row_length === 0)
|
|
113
|
+
return [];
|
|
112
114
|
return Array(row_count[1] === "fixed" ? row_count[0] : data_row_length).fill(0).map((_, i) => {
|
|
113
115
|
return Array(
|
|
114
|
-
col_count[1] === "fixed" ? col_count[0] :
|
|
116
|
+
col_count[1] === "fixed" ? col_count[0] : _values[0].length || headers.length
|
|
115
117
|
).fill(0).map((_2, j) => {
|
|
116
118
|
const id = make_id();
|
|
117
119
|
els[id] = els[id] || { input: null, cell: null };
|
|
@@ -360,16 +362,14 @@ async function add_row(index) {
|
|
|
360
362
|
parent.focus();
|
|
361
363
|
if (row_count[1] !== "dynamic")
|
|
362
364
|
return;
|
|
363
|
-
|
|
364
|
-
values = [Array(headers.length).fill("")];
|
|
365
|
-
return;
|
|
366
|
-
}
|
|
367
|
-
const new_row = Array(data[0].length).fill(0).map((_, i) => {
|
|
365
|
+
const new_row = Array(data[0]?.length || headers.length).fill(0).map((_, i) => {
|
|
368
366
|
const _id = make_id();
|
|
369
367
|
els[_id] = { cell: null, input: null };
|
|
370
368
|
return { id: _id, value: "" };
|
|
371
369
|
});
|
|
372
|
-
if (
|
|
370
|
+
if (data.length === 0) {
|
|
371
|
+
data = [new_row];
|
|
372
|
+
} else if (index !== void 0 && index >= 0 && index <= data.length) {
|
|
373
373
|
data.splice(index, 0, new_row);
|
|
374
374
|
} else {
|
|
375
375
|
data.push(new_row);
|
|
@@ -605,14 +605,16 @@ async function delete_col(index) {
|
|
|
605
605
|
parent.focus();
|
|
606
606
|
if (col_count[1] !== "dynamic")
|
|
607
607
|
return;
|
|
608
|
-
if (
|
|
608
|
+
if (_headers.length <= 1)
|
|
609
609
|
return;
|
|
610
610
|
_headers.splice(index, 1);
|
|
611
611
|
_headers = _headers;
|
|
612
|
-
data.
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
612
|
+
if (data.length > 0) {
|
|
613
|
+
data.forEach((row) => {
|
|
614
|
+
row.splice(index, 1);
|
|
615
|
+
});
|
|
616
|
+
data = data;
|
|
617
|
+
}
|
|
616
618
|
selected = false;
|
|
617
619
|
}
|
|
618
620
|
function delete_row_at(index) {
|
|
@@ -702,24 +704,26 @@ function commit_filter() {
|
|
|
702
704
|
<svelte:window on:resize={() => set_cell_widths()} />
|
|
703
705
|
|
|
704
706
|
<div class="table-container">
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
<
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
707
|
+
{#if (label && label.length !== 0 && show_label) || show_fullscreen_button || show_copy_button || show_search !== "none"}
|
|
708
|
+
<div class="header-row">
|
|
709
|
+
{#if label && label.length !== 0 && show_label}
|
|
710
|
+
<div class="label">
|
|
711
|
+
<p>{label}</p>
|
|
712
|
+
</div>
|
|
713
|
+
{/if}
|
|
714
|
+
<Toolbar
|
|
715
|
+
{show_fullscreen_button}
|
|
716
|
+
{is_fullscreen}
|
|
717
|
+
on:click={toggle_fullscreen}
|
|
718
|
+
on_copy={handle_copy}
|
|
719
|
+
{show_copy_button}
|
|
720
|
+
{show_search}
|
|
721
|
+
on:search={(e) => handle_search(e.detail)}
|
|
722
|
+
on_commit_filter={commit_filter}
|
|
723
|
+
{current_search_query}
|
|
724
|
+
/>
|
|
725
|
+
</div>
|
|
726
|
+
{/if}
|
|
723
727
|
<div
|
|
724
728
|
bind:this={parent}
|
|
725
729
|
class="table-wrap"
|
|
@@ -864,184 +868,205 @@ function commit_filter() {
|
|
|
864
868
|
bind:dragging
|
|
865
869
|
aria_label={i18n("dataframe.drop_to_upload")}
|
|
866
870
|
>
|
|
867
|
-
<
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
<tr slot="thead">
|
|
880
|
-
{#if show_row_numbers}
|
|
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>
|
|
871
|
+
<div class="table-wrap">
|
|
872
|
+
<VirtualTable
|
|
873
|
+
bind:items={data}
|
|
874
|
+
{max_height}
|
|
875
|
+
bind:actual_height={table_height}
|
|
876
|
+
bind:table_scrollbar_width={scrollbar_width}
|
|
877
|
+
selected={selected_index}
|
|
878
|
+
disable_scroll={active_cell_menu !== null ||
|
|
879
|
+
active_header_menu !== null}
|
|
880
|
+
>
|
|
881
|
+
{#if label && label.length !== 0}
|
|
882
|
+
<caption class="sr-only">{label}</caption>
|
|
891
883
|
{/if}
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
884
|
+
<tr slot="thead">
|
|
885
|
+
{#if show_row_numbers}
|
|
886
|
+
<th
|
|
887
|
+
class="row-number-header frozen-column always-frozen"
|
|
888
|
+
style="left: 0;"
|
|
889
|
+
>
|
|
890
|
+
<div class="cell-wrap">
|
|
891
|
+
<div class="header-content">
|
|
892
|
+
<div class="header-text"></div>
|
|
893
|
+
</div>
|
|
894
|
+
</div>
|
|
895
|
+
</th>
|
|
896
|
+
{/if}
|
|
897
|
+
{#each _headers as { value, id }, i (id)}
|
|
898
|
+
<th
|
|
899
|
+
class:frozen-column={i < actual_pinned_columns}
|
|
900
|
+
class:last-frozen={i === actual_pinned_columns - 1}
|
|
901
|
+
class:focus={header_edit === i || selected_header === i}
|
|
902
|
+
aria-sort={get_sort_status(value, sort_by, sort_direction)}
|
|
903
|
+
style="width: {get_cell_width(i)}; left: {i <
|
|
904
|
+
actual_pinned_columns
|
|
905
|
+
? i === 0
|
|
906
|
+
? show_row_numbers
|
|
907
|
+
? 'var(--cell-width-row-number)'
|
|
908
|
+
: '0'
|
|
909
|
+
: `calc(${show_row_numbers ? 'var(--cell-width-row-number) + ' : ''}${Array(
|
|
910
|
+
i
|
|
911
|
+
)
|
|
912
|
+
.fill(0)
|
|
913
|
+
.map((_, idx) => `var(--cell-width-${idx})`)
|
|
914
|
+
.join(' + ')})`
|
|
915
|
+
: 'auto'};"
|
|
916
|
+
on:click={() => {
|
|
917
|
+
toggle_header_button(i);
|
|
918
|
+
}}
|
|
919
|
+
>
|
|
920
|
+
<div class="cell-wrap">
|
|
921
|
+
<div class="header-content">
|
|
922
|
+
<EditableCell
|
|
923
|
+
{max_chars}
|
|
924
|
+
bind:value={_headers[i].value}
|
|
925
|
+
bind:el={els[id].input}
|
|
926
|
+
{latex_delimiters}
|
|
927
|
+
{line_breaks}
|
|
928
|
+
edit={header_edit === i}
|
|
929
|
+
on:keydown={end_header_edit}
|
|
930
|
+
on:dblclick={() => edit_header(i)}
|
|
931
|
+
header
|
|
932
|
+
{root}
|
|
933
|
+
{editable}
|
|
934
|
+
/>
|
|
935
|
+
<div class="sort-buttons">
|
|
936
|
+
<SortIcon
|
|
937
|
+
direction={sort_by === i ? sort_direction : null}
|
|
938
|
+
on:sort={({ detail }) => handle_sort(i, detail)}
|
|
939
|
+
{i18n}
|
|
940
|
+
/>
|
|
941
|
+
</div>
|
|
942
|
+
</div>
|
|
943
|
+
{#if editable}
|
|
944
|
+
<button
|
|
945
|
+
class="cell-menu-button"
|
|
946
|
+
on:click={(event) => toggle_header_menu(event, i)}
|
|
947
|
+
on:touchstart={(event) => {
|
|
948
|
+
event.preventDefault();
|
|
949
|
+
const touch = event.touches[0];
|
|
950
|
+
const mouseEvent = new MouseEvent("click", {
|
|
951
|
+
clientX: touch.clientX,
|
|
952
|
+
clientY: touch.clientY,
|
|
953
|
+
bubbles: true,
|
|
954
|
+
cancelable: true,
|
|
955
|
+
view: window
|
|
956
|
+
});
|
|
957
|
+
toggle_header_menu(mouseEvent, i);
|
|
958
|
+
}}
|
|
959
|
+
>
|
|
960
|
+
⋮
|
|
961
|
+
</button>
|
|
962
|
+
{/if}
|
|
963
|
+
</div>
|
|
964
|
+
</th>
|
|
965
|
+
{/each}
|
|
966
|
+
</tr>
|
|
967
|
+
<tr slot="tbody" let:item let:index class:row_odd={index % 2 === 0}>
|
|
968
|
+
{#if show_row_numbers}
|
|
969
|
+
<td
|
|
970
|
+
class="row-number frozen-column always-frozen"
|
|
971
|
+
style="left: 0;"
|
|
972
|
+
tabindex="-1"
|
|
973
|
+
>
|
|
974
|
+
{index + 1}
|
|
975
|
+
</td>
|
|
976
|
+
{/if}
|
|
977
|
+
{#each item as { value, id }, j (id)}
|
|
978
|
+
<td
|
|
979
|
+
class:frozen-column={j < actual_pinned_columns}
|
|
980
|
+
class:last-frozen={j === actual_pinned_columns - 1}
|
|
981
|
+
tabindex={show_row_numbers && j === 0 ? -1 : 0}
|
|
982
|
+
bind:this={els[id].cell}
|
|
983
|
+
on:touchstart={(event) => {
|
|
984
|
+
const touch = event.touches[0];
|
|
985
|
+
const mouseEvent = new MouseEvent("click", {
|
|
986
|
+
clientX: touch.clientX,
|
|
987
|
+
clientY: touch.clientY,
|
|
988
|
+
bubbles: true,
|
|
989
|
+
cancelable: true,
|
|
990
|
+
view: window
|
|
991
|
+
});
|
|
992
|
+
handle_cell_click(mouseEvent, index, j);
|
|
993
|
+
}}
|
|
994
|
+
on:mousedown={(event) => {
|
|
995
|
+
event.preventDefault();
|
|
996
|
+
event.stopPropagation();
|
|
997
|
+
}}
|
|
998
|
+
on:click={(event) => handle_cell_click(event, index, j)}
|
|
999
|
+
style="width: {get_cell_width(j)}; left: {j <
|
|
1000
|
+
actual_pinned_columns
|
|
1001
|
+
? j === 0
|
|
1002
|
+
? show_row_numbers
|
|
1003
|
+
? 'var(--cell-width-row-number)'
|
|
1004
|
+
: '0'
|
|
1005
|
+
: `calc(${show_row_numbers ? 'var(--cell-width-row-number) + ' : ''}${Array(
|
|
1006
|
+
j
|
|
1007
|
+
)
|
|
1008
|
+
.fill(0)
|
|
1009
|
+
.map((_, idx) => `var(--cell-width-${idx})`)
|
|
1010
|
+
.join(' + ')})`
|
|
1011
|
+
: 'auto'}; {styling?.[index]?.[j] || ''}"
|
|
1012
|
+
class:flash={copy_flash &&
|
|
1013
|
+
is_cell_selected([index, j], selected_cells)}
|
|
1014
|
+
class={is_cell_selected([index, j], selected_cells)}
|
|
1015
|
+
class:menu-active={active_cell_menu &&
|
|
1016
|
+
active_cell_menu.row === index &&
|
|
1017
|
+
active_cell_menu.col === j}
|
|
1018
|
+
>
|
|
1019
|
+
<div class="cell-wrap">
|
|
917
1020
|
<EditableCell
|
|
918
|
-
{
|
|
919
|
-
bind:value={_headers[i].value}
|
|
1021
|
+
bind:value={data[index][j].value}
|
|
920
1022
|
bind:el={els[id].input}
|
|
1023
|
+
display_value={display_value?.[index]?.[j]}
|
|
921
1024
|
{latex_delimiters}
|
|
922
1025
|
{line_breaks}
|
|
923
|
-
edit={header_edit === i}
|
|
924
|
-
on:keydown={end_header_edit}
|
|
925
|
-
on:dblclick={() => edit_header(i)}
|
|
926
|
-
header
|
|
927
|
-
{root}
|
|
928
1026
|
{editable}
|
|
1027
|
+
edit={dequal(editing, [index, j])}
|
|
1028
|
+
datatype={Array.isArray(datatype) ? datatype[j] : datatype}
|
|
1029
|
+
on:blur={() => {
|
|
1030
|
+
clear_on_focus = false;
|
|
1031
|
+
parent.focus();
|
|
1032
|
+
}}
|
|
1033
|
+
on:focus={() => {
|
|
1034
|
+
const row = index;
|
|
1035
|
+
const col = j;
|
|
1036
|
+
if (
|
|
1037
|
+
!selected_cells.some(([r, c]) => r === row && c === col)
|
|
1038
|
+
) {
|
|
1039
|
+
selected_cells = [[row, col]];
|
|
1040
|
+
}
|
|
1041
|
+
}}
|
|
1042
|
+
{clear_on_focus}
|
|
1043
|
+
{root}
|
|
1044
|
+
{max_chars}
|
|
929
1045
|
/>
|
|
930
|
-
|
|
931
|
-
<
|
|
932
|
-
|
|
933
|
-
on:
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
1046
|
+
{#if editable && should_show_cell_menu([index, j], selected_cells, editable)}
|
|
1047
|
+
<button
|
|
1048
|
+
class="cell-menu-button"
|
|
1049
|
+
on:click={(event) => toggle_cell_menu(event, index, j)}
|
|
1050
|
+
>
|
|
1051
|
+
⋮
|
|
1052
|
+
</button>
|
|
1053
|
+
{/if}
|
|
937
1054
|
</div>
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
⋮
|
|
944
|
-
</button>
|
|
945
|
-
{/if}
|
|
946
|
-
</div>
|
|
947
|
-
</th>
|
|
948
|
-
{/each}
|
|
949
|
-
</tr>
|
|
950
|
-
<tr slot="tbody" let:item let:index class:row_odd={index % 2 === 0}>
|
|
951
|
-
{#if show_row_numbers}
|
|
952
|
-
<td
|
|
953
|
-
class="row-number frozen-column always-frozen"
|
|
954
|
-
style="left: 0;"
|
|
955
|
-
tabindex="-1"
|
|
956
|
-
>
|
|
957
|
-
{index + 1}
|
|
958
|
-
</td>
|
|
959
|
-
{/if}
|
|
960
|
-
{#each item as { value, id }, j (id)}
|
|
961
|
-
<td
|
|
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}
|
|
966
|
-
on:touchstart={(event) => {
|
|
967
|
-
const touch = event.touches[0];
|
|
968
|
-
const mouseEvent = new MouseEvent("click", {
|
|
969
|
-
clientX: touch.clientX,
|
|
970
|
-
clientY: touch.clientY,
|
|
971
|
-
bubbles: true,
|
|
972
|
-
cancelable: true,
|
|
973
|
-
view: window
|
|
974
|
-
});
|
|
975
|
-
handle_cell_click(mouseEvent, index, j);
|
|
976
|
-
}}
|
|
977
|
-
on:mousedown={(event) => {
|
|
978
|
-
event.preventDefault();
|
|
979
|
-
event.stopPropagation();
|
|
980
|
-
}}
|
|
981
|
-
on:click={(event) => handle_cell_click(event, index, j)}
|
|
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)}
|
|
997
|
-
class={is_cell_selected([index, j], selected_cells)}
|
|
998
|
-
class:menu-active={active_cell_menu &&
|
|
999
|
-
active_cell_menu.row === index &&
|
|
1000
|
-
active_cell_menu.col === j}
|
|
1001
|
-
>
|
|
1002
|
-
<div class="cell-wrap">
|
|
1003
|
-
<EditableCell
|
|
1004
|
-
bind:value={data[index][j].value}
|
|
1005
|
-
bind:el={els[id].input}
|
|
1006
|
-
display_value={display_value?.[index]?.[j]}
|
|
1007
|
-
{latex_delimiters}
|
|
1008
|
-
{line_breaks}
|
|
1009
|
-
{editable}
|
|
1010
|
-
edit={dequal(editing, [index, j])}
|
|
1011
|
-
datatype={Array.isArray(datatype) ? datatype[j] : datatype}
|
|
1012
|
-
on:blur={() => {
|
|
1013
|
-
clear_on_focus = false;
|
|
1014
|
-
parent.focus();
|
|
1015
|
-
}}
|
|
1016
|
-
on:focus={() => {
|
|
1017
|
-
const row = index;
|
|
1018
|
-
const col = j;
|
|
1019
|
-
if (
|
|
1020
|
-
!selected_cells.some(([r, c]) => r === row && c === col)
|
|
1021
|
-
) {
|
|
1022
|
-
selected_cells = [[row, col]];
|
|
1023
|
-
}
|
|
1024
|
-
}}
|
|
1025
|
-
{clear_on_focus}
|
|
1026
|
-
{root}
|
|
1027
|
-
{max_chars}
|
|
1028
|
-
/>
|
|
1029
|
-
{#if editable && should_show_cell_menu([index, j], selected_cells, editable)}
|
|
1030
|
-
<button
|
|
1031
|
-
class="cell-menu-button"
|
|
1032
|
-
on:click={(event) => toggle_cell_menu(event, index, j)}
|
|
1033
|
-
>
|
|
1034
|
-
⋮
|
|
1035
|
-
</button>
|
|
1036
|
-
{/if}
|
|
1037
|
-
</div>
|
|
1038
|
-
</td>
|
|
1039
|
-
{/each}
|
|
1040
|
-
</tr>
|
|
1041
|
-
</VirtualTable>
|
|
1055
|
+
</td>
|
|
1056
|
+
{/each}
|
|
1057
|
+
</tr>
|
|
1058
|
+
</VirtualTable>
|
|
1059
|
+
</div>
|
|
1042
1060
|
</Upload>
|
|
1043
1061
|
</div>
|
|
1044
1062
|
</div>
|
|
1063
|
+
{#if data.length === 0 && editable && row_count[1] === "dynamic"}
|
|
1064
|
+
<div class="add-row-container">
|
|
1065
|
+
<button class="add-row-button" on:click={() => add_row()}>
|
|
1066
|
+
<span>+</span>
|
|
1067
|
+
</button>
|
|
1068
|
+
</div>
|
|
1069
|
+
{/if}
|
|
1045
1070
|
|
|
1046
1071
|
{#if active_cell_menu}
|
|
1047
1072
|
<CellMenu
|
|
@@ -1078,7 +1103,7 @@ function commit_filter() {
|
|
|
1078
1103
|
on_delete_row={() => delete_row_at(active_cell_menu?.row ?? -1)}
|
|
1079
1104
|
on_delete_col={() => delete_col_at(active_header_menu?.col ?? -1)}
|
|
1080
1105
|
can_delete_rows={false}
|
|
1081
|
-
can_delete_cols={
|
|
1106
|
+
can_delete_cols={_headers.length > 1}
|
|
1082
1107
|
/>
|
|
1083
1108
|
{/if}
|
|
1084
1109
|
|
|
@@ -1100,8 +1125,6 @@ function commit_filter() {
|
|
|
1100
1125
|
.table-wrap {
|
|
1101
1126
|
position: relative;
|
|
1102
1127
|
transition: 150ms;
|
|
1103
|
-
border: 1px solid var(--border-color-primary);
|
|
1104
|
-
border-radius: var(--table-radius);
|
|
1105
1128
|
}
|
|
1106
1129
|
|
|
1107
1130
|
.table-wrap.menu-open {
|
|
@@ -1134,6 +1157,12 @@ function commit_filter() {
|
|
|
1134
1157
|
border-collapse: separate;
|
|
1135
1158
|
}
|
|
1136
1159
|
|
|
1160
|
+
.table-wrap > :global(button) {
|
|
1161
|
+
border: 1px solid var(--border-color-primary);
|
|
1162
|
+
border-radius: var(--table-radius);
|
|
1163
|
+
overflow: hidden;
|
|
1164
|
+
}
|
|
1165
|
+
|
|
1137
1166
|
div:not(.no-wrap) td {
|
|
1138
1167
|
overflow-wrap: anywhere;
|
|
1139
1168
|
}
|
|
@@ -1176,10 +1205,12 @@ function commit_filter() {
|
|
|
1176
1205
|
|
|
1177
1206
|
th:first-child {
|
|
1178
1207
|
border-top-left-radius: var(--table-radius);
|
|
1208
|
+
border-bottom-left-radius: var(--table-radius);
|
|
1179
1209
|
}
|
|
1180
1210
|
|
|
1181
1211
|
th:last-child {
|
|
1182
1212
|
border-top-right-radius: var(--table-radius);
|
|
1213
|
+
border-bottom-right-radius: var(--table-radius);
|
|
1183
1214
|
}
|
|
1184
1215
|
|
|
1185
1216
|
th.focus,
|
|
@@ -1209,6 +1240,7 @@ function commit_filter() {
|
|
|
1209
1240
|
display: flex;
|
|
1210
1241
|
align-items: center;
|
|
1211
1242
|
flex-shrink: 0;
|
|
1243
|
+
order: -1;
|
|
1212
1244
|
}
|
|
1213
1245
|
|
|
1214
1246
|
.editing {
|
|
@@ -1217,17 +1249,24 @@ function commit_filter() {
|
|
|
1217
1249
|
|
|
1218
1250
|
.cell-wrap {
|
|
1219
1251
|
display: flex;
|
|
1220
|
-
align-items:
|
|
1252
|
+
align-items: center;
|
|
1253
|
+
justify-content: flex-start;
|
|
1221
1254
|
outline: none;
|
|
1222
1255
|
min-height: var(--size-9);
|
|
1223
1256
|
position: relative;
|
|
1224
|
-
height:
|
|
1257
|
+
height: 100%;
|
|
1258
|
+
padding: var(--size-2);
|
|
1259
|
+
box-sizing: border-box;
|
|
1260
|
+
margin: 0;
|
|
1261
|
+
gap: var(--size-1);
|
|
1262
|
+
overflow: visible;
|
|
1263
|
+
min-width: 0;
|
|
1264
|
+
border-radius: var(--table-radius);
|
|
1225
1265
|
}
|
|
1226
1266
|
|
|
1227
1267
|
.header-content {
|
|
1228
1268
|
display: flex;
|
|
1229
1269
|
align-items: center;
|
|
1230
|
-
justify-content: space-between;
|
|
1231
1270
|
overflow: hidden;
|
|
1232
1271
|
flex-grow: 1;
|
|
1233
1272
|
min-width: 0;
|
|
@@ -1235,7 +1274,6 @@ function commit_filter() {
|
|
|
1235
1274
|
overflow-wrap: break-word;
|
|
1236
1275
|
word-break: normal;
|
|
1237
1276
|
height: 100%;
|
|
1238
|
-
padding: var(--size-1);
|
|
1239
1277
|
gap: var(--size-1);
|
|
1240
1278
|
}
|
|
1241
1279
|
|
|
@@ -1265,7 +1303,8 @@ function commit_filter() {
|
|
|
1265
1303
|
transform: translateY(-50%);
|
|
1266
1304
|
}
|
|
1267
1305
|
|
|
1268
|
-
.cell-selected .cell-menu-button
|
|
1306
|
+
.cell-selected .cell-menu-button,
|
|
1307
|
+
th:hover .cell-menu-button {
|
|
1269
1308
|
display: flex;
|
|
1270
1309
|
align-items: center;
|
|
1271
1310
|
justify-content: center;
|
|
@@ -1482,4 +1521,24 @@ function commit_filter() {
|
|
|
1482
1521
|
.always-frozen {
|
|
1483
1522
|
z-index: var(--layer-3);
|
|
1484
1523
|
}
|
|
1524
|
+
|
|
1525
|
+
.add-row-container {
|
|
1526
|
+
margin-top: var(--size-2);
|
|
1527
|
+
}
|
|
1528
|
+
|
|
1529
|
+
.add-row-button {
|
|
1530
|
+
width: 100%;
|
|
1531
|
+
padding: var(--size-1);
|
|
1532
|
+
background: transparent;
|
|
1533
|
+
border: 1px dashed var(--border-color-primary);
|
|
1534
|
+
border-radius: var(--radius-sm);
|
|
1535
|
+
color: var(--body-text-color);
|
|
1536
|
+
cursor: pointer;
|
|
1537
|
+
transition: all 150ms;
|
|
1538
|
+
}
|
|
1539
|
+
|
|
1540
|
+
.add-row-button:hover {
|
|
1541
|
+
background: var(--background-fill-secondary);
|
|
1542
|
+
border-style: solid;
|
|
1543
|
+
}
|
|
1485
1544
|
</style>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gradio/dataframe",
|
|
3
|
-
"version": "0.16.
|
|
3
|
+
"version": "0.16.1",
|
|
4
4
|
"description": "Gradio UI packages",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "",
|
|
@@ -18,12 +18,12 @@
|
|
|
18
18
|
"katex": "^0.16.7",
|
|
19
19
|
"marked": "^12.0.0",
|
|
20
20
|
"@gradio/atoms": "^0.13.2",
|
|
21
|
-
"@gradio/button": "^0.4.6",
|
|
22
|
-
"@gradio/markdown-code": "^0.4.0",
|
|
23
21
|
"@gradio/client": "^1.12.0",
|
|
24
|
-
"@gradio/statustracker": "^0.10.3",
|
|
25
22
|
"@gradio/icons": "^0.10.0",
|
|
23
|
+
"@gradio/button": "^0.4.6",
|
|
24
|
+
"@gradio/markdown-code": "^0.4.0",
|
|
26
25
|
"@gradio/upload": "^0.15.1",
|
|
26
|
+
"@gradio/statustracker": "^0.10.3",
|
|
27
27
|
"@gradio/utils": "^0.10.1"
|
|
28
28
|
},
|
|
29
29
|
"exports": {
|
package/shared/CellMenu.svelte
CHANGED
|
@@ -110,7 +110,6 @@
|
|
|
110
110
|
class:multiline={header}
|
|
111
111
|
on:focus|preventDefault
|
|
112
112
|
style={styling}
|
|
113
|
-
class="table-cell-text"
|
|
114
113
|
data-editable={editable}
|
|
115
114
|
placeholder=" "
|
|
116
115
|
>
|
|
@@ -149,8 +148,6 @@
|
|
|
149
148
|
position: relative;
|
|
150
149
|
display: inline-block;
|
|
151
150
|
outline: none;
|
|
152
|
-
padding: var(--size-2);
|
|
153
|
-
padding-right: 0;
|
|
154
151
|
-webkit-user-select: text;
|
|
155
152
|
-moz-user-select: text;
|
|
156
153
|
-ms-user-select: text;
|
|
@@ -177,6 +174,7 @@
|
|
|
177
174
|
font-weight: var(--weight-bold);
|
|
178
175
|
white-space: normal;
|
|
179
176
|
word-break: break-word;
|
|
177
|
+
margin-left: var(--size-1);
|
|
180
178
|
}
|
|
181
179
|
|
|
182
180
|
.edit {
|
package/shared/Table.svelte
CHANGED
|
@@ -176,15 +176,14 @@
|
|
|
176
176
|
id: string;
|
|
177
177
|
}[][] {
|
|
178
178
|
const data_row_length = _values.length;
|
|
179
|
+
if (data_row_length === 0) return [];
|
|
179
180
|
return Array(row_count[1] === "fixed" ? row_count[0] : data_row_length)
|
|
180
181
|
.fill(0)
|
|
181
182
|
.map((_, i) => {
|
|
182
183
|
return Array(
|
|
183
184
|
col_count[1] === "fixed"
|
|
184
185
|
? col_count[0]
|
|
185
|
-
:
|
|
186
|
-
? _values[0].length
|
|
187
|
-
: headers.length
|
|
186
|
+
: _values[0].length || headers.length
|
|
188
187
|
)
|
|
189
188
|
.fill(0)
|
|
190
189
|
.map((_, j) => {
|
|
@@ -473,12 +472,8 @@
|
|
|
473
472
|
parent.focus();
|
|
474
473
|
|
|
475
474
|
if (row_count[1] !== "dynamic") return;
|
|
476
|
-
if (data.length === 0) {
|
|
477
|
-
values = [Array(headers.length).fill("")];
|
|
478
|
-
return;
|
|
479
|
-
}
|
|
480
475
|
|
|
481
|
-
const new_row = Array(data[0].length)
|
|
476
|
+
const new_row = Array(data[0]?.length || headers.length)
|
|
482
477
|
.fill(0)
|
|
483
478
|
.map((_, i) => {
|
|
484
479
|
const _id = make_id();
|
|
@@ -486,7 +481,9 @@
|
|
|
486
481
|
return { id: _id, value: "" };
|
|
487
482
|
});
|
|
488
483
|
|
|
489
|
-
if (
|
|
484
|
+
if (data.length === 0) {
|
|
485
|
+
data = [new_row];
|
|
486
|
+
} else if (index !== undefined && index >= 0 && index <= data.length) {
|
|
490
487
|
data.splice(index, 0, new_row);
|
|
491
488
|
} else {
|
|
492
489
|
data.push(new_row);
|
|
@@ -786,15 +783,17 @@
|
|
|
786
783
|
async function delete_col(index: number): Promise<void> {
|
|
787
784
|
parent.focus();
|
|
788
785
|
if (col_count[1] !== "dynamic") return;
|
|
789
|
-
if (
|
|
786
|
+
if (_headers.length <= 1) return;
|
|
790
787
|
|
|
791
788
|
_headers.splice(index, 1);
|
|
792
789
|
_headers = _headers;
|
|
793
790
|
|
|
794
|
-
data.
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
791
|
+
if (data.length > 0) {
|
|
792
|
+
data.forEach((row) => {
|
|
793
|
+
row.splice(index, 1);
|
|
794
|
+
});
|
|
795
|
+
data = data;
|
|
796
|
+
}
|
|
798
797
|
selected = false;
|
|
799
798
|
}
|
|
800
799
|
|
|
@@ -902,24 +901,26 @@
|
|
|
902
901
|
<svelte:window on:resize={() => set_cell_widths()} />
|
|
903
902
|
|
|
904
903
|
<div class="table-container">
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
<
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
904
|
+
{#if (label && label.length !== 0 && show_label) || show_fullscreen_button || show_copy_button || show_search !== "none"}
|
|
905
|
+
<div class="header-row">
|
|
906
|
+
{#if label && label.length !== 0 && show_label}
|
|
907
|
+
<div class="label">
|
|
908
|
+
<p>{label}</p>
|
|
909
|
+
</div>
|
|
910
|
+
{/if}
|
|
911
|
+
<Toolbar
|
|
912
|
+
{show_fullscreen_button}
|
|
913
|
+
{is_fullscreen}
|
|
914
|
+
on:click={toggle_fullscreen}
|
|
915
|
+
on_copy={handle_copy}
|
|
916
|
+
{show_copy_button}
|
|
917
|
+
{show_search}
|
|
918
|
+
on:search={(e) => handle_search(e.detail)}
|
|
919
|
+
on_commit_filter={commit_filter}
|
|
920
|
+
{current_search_query}
|
|
921
|
+
/>
|
|
922
|
+
</div>
|
|
923
|
+
{/if}
|
|
923
924
|
<div
|
|
924
925
|
bind:this={parent}
|
|
925
926
|
class="table-wrap"
|
|
@@ -1064,184 +1065,205 @@
|
|
|
1064
1065
|
bind:dragging
|
|
1065
1066
|
aria_label={i18n("dataframe.drop_to_upload")}
|
|
1066
1067
|
>
|
|
1067
|
-
<
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
<tr slot="thead">
|
|
1080
|
-
{#if show_row_numbers}
|
|
1081
|
-
<th
|
|
1082
|
-
class="row-number-header frozen-column always-frozen"
|
|
1083
|
-
style="left: 0;"
|
|
1084
|
-
>
|
|
1085
|
-
<div class="cell-wrap">
|
|
1086
|
-
<div class="header-content">
|
|
1087
|
-
<div class="header-text"></div>
|
|
1088
|
-
</div>
|
|
1089
|
-
</div>
|
|
1090
|
-
</th>
|
|
1068
|
+
<div class="table-wrap">
|
|
1069
|
+
<VirtualTable
|
|
1070
|
+
bind:items={data}
|
|
1071
|
+
{max_height}
|
|
1072
|
+
bind:actual_height={table_height}
|
|
1073
|
+
bind:table_scrollbar_width={scrollbar_width}
|
|
1074
|
+
selected={selected_index}
|
|
1075
|
+
disable_scroll={active_cell_menu !== null ||
|
|
1076
|
+
active_header_menu !== null}
|
|
1077
|
+
>
|
|
1078
|
+
{#if label && label.length !== 0}
|
|
1079
|
+
<caption class="sr-only">{label}</caption>
|
|
1091
1080
|
{/if}
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1081
|
+
<tr slot="thead">
|
|
1082
|
+
{#if show_row_numbers}
|
|
1083
|
+
<th
|
|
1084
|
+
class="row-number-header frozen-column always-frozen"
|
|
1085
|
+
style="left: 0;"
|
|
1086
|
+
>
|
|
1087
|
+
<div class="cell-wrap">
|
|
1088
|
+
<div class="header-content">
|
|
1089
|
+
<div class="header-text"></div>
|
|
1090
|
+
</div>
|
|
1091
|
+
</div>
|
|
1092
|
+
</th>
|
|
1093
|
+
{/if}
|
|
1094
|
+
{#each _headers as { value, id }, i (id)}
|
|
1095
|
+
<th
|
|
1096
|
+
class:frozen-column={i < actual_pinned_columns}
|
|
1097
|
+
class:last-frozen={i === actual_pinned_columns - 1}
|
|
1098
|
+
class:focus={header_edit === i || selected_header === i}
|
|
1099
|
+
aria-sort={get_sort_status(value, sort_by, sort_direction)}
|
|
1100
|
+
style="width: {get_cell_width(i)}; left: {i <
|
|
1101
|
+
actual_pinned_columns
|
|
1102
|
+
? i === 0
|
|
1103
|
+
? show_row_numbers
|
|
1104
|
+
? 'var(--cell-width-row-number)'
|
|
1105
|
+
: '0'
|
|
1106
|
+
: `calc(${show_row_numbers ? 'var(--cell-width-row-number) + ' : ''}${Array(
|
|
1107
|
+
i
|
|
1108
|
+
)
|
|
1109
|
+
.fill(0)
|
|
1110
|
+
.map((_, idx) => `var(--cell-width-${idx})`)
|
|
1111
|
+
.join(' + ')})`
|
|
1112
|
+
: 'auto'};"
|
|
1113
|
+
on:click={() => {
|
|
1114
|
+
toggle_header_button(i);
|
|
1115
|
+
}}
|
|
1116
|
+
>
|
|
1117
|
+
<div class="cell-wrap">
|
|
1118
|
+
<div class="header-content">
|
|
1119
|
+
<EditableCell
|
|
1120
|
+
{max_chars}
|
|
1121
|
+
bind:value={_headers[i].value}
|
|
1122
|
+
bind:el={els[id].input}
|
|
1123
|
+
{latex_delimiters}
|
|
1124
|
+
{line_breaks}
|
|
1125
|
+
edit={header_edit === i}
|
|
1126
|
+
on:keydown={end_header_edit}
|
|
1127
|
+
on:dblclick={() => edit_header(i)}
|
|
1128
|
+
header
|
|
1129
|
+
{root}
|
|
1130
|
+
{editable}
|
|
1131
|
+
/>
|
|
1132
|
+
<div class="sort-buttons">
|
|
1133
|
+
<SortIcon
|
|
1134
|
+
direction={sort_by === i ? sort_direction : null}
|
|
1135
|
+
on:sort={({ detail }) => handle_sort(i, detail)}
|
|
1136
|
+
{i18n}
|
|
1137
|
+
/>
|
|
1138
|
+
</div>
|
|
1139
|
+
</div>
|
|
1140
|
+
{#if editable}
|
|
1141
|
+
<button
|
|
1142
|
+
class="cell-menu-button"
|
|
1143
|
+
on:click={(event) => toggle_header_menu(event, i)}
|
|
1144
|
+
on:touchstart={(event) => {
|
|
1145
|
+
event.preventDefault();
|
|
1146
|
+
const touch = event.touches[0];
|
|
1147
|
+
const mouseEvent = new MouseEvent("click", {
|
|
1148
|
+
clientX: touch.clientX,
|
|
1149
|
+
clientY: touch.clientY,
|
|
1150
|
+
bubbles: true,
|
|
1151
|
+
cancelable: true,
|
|
1152
|
+
view: window
|
|
1153
|
+
});
|
|
1154
|
+
toggle_header_menu(mouseEvent, i);
|
|
1155
|
+
}}
|
|
1156
|
+
>
|
|
1157
|
+
⋮
|
|
1158
|
+
</button>
|
|
1159
|
+
{/if}
|
|
1160
|
+
</div>
|
|
1161
|
+
</th>
|
|
1162
|
+
{/each}
|
|
1163
|
+
</tr>
|
|
1164
|
+
<tr slot="tbody" let:item let:index class:row_odd={index % 2 === 0}>
|
|
1165
|
+
{#if show_row_numbers}
|
|
1166
|
+
<td
|
|
1167
|
+
class="row-number frozen-column always-frozen"
|
|
1168
|
+
style="left: 0;"
|
|
1169
|
+
tabindex="-1"
|
|
1170
|
+
>
|
|
1171
|
+
{index + 1}
|
|
1172
|
+
</td>
|
|
1173
|
+
{/if}
|
|
1174
|
+
{#each item as { value, id }, j (id)}
|
|
1175
|
+
<td
|
|
1176
|
+
class:frozen-column={j < actual_pinned_columns}
|
|
1177
|
+
class:last-frozen={j === actual_pinned_columns - 1}
|
|
1178
|
+
tabindex={show_row_numbers && j === 0 ? -1 : 0}
|
|
1179
|
+
bind:this={els[id].cell}
|
|
1180
|
+
on:touchstart={(event) => {
|
|
1181
|
+
const touch = event.touches[0];
|
|
1182
|
+
const mouseEvent = new MouseEvent("click", {
|
|
1183
|
+
clientX: touch.clientX,
|
|
1184
|
+
clientY: touch.clientY,
|
|
1185
|
+
bubbles: true,
|
|
1186
|
+
cancelable: true,
|
|
1187
|
+
view: window
|
|
1188
|
+
});
|
|
1189
|
+
handle_cell_click(mouseEvent, index, j);
|
|
1190
|
+
}}
|
|
1191
|
+
on:mousedown={(event) => {
|
|
1192
|
+
event.preventDefault();
|
|
1193
|
+
event.stopPropagation();
|
|
1194
|
+
}}
|
|
1195
|
+
on:click={(event) => handle_cell_click(event, index, j)}
|
|
1196
|
+
style="width: {get_cell_width(j)}; left: {j <
|
|
1197
|
+
actual_pinned_columns
|
|
1198
|
+
? j === 0
|
|
1199
|
+
? show_row_numbers
|
|
1200
|
+
? 'var(--cell-width-row-number)'
|
|
1201
|
+
: '0'
|
|
1202
|
+
: `calc(${show_row_numbers ? 'var(--cell-width-row-number) + ' : ''}${Array(
|
|
1203
|
+
j
|
|
1204
|
+
)
|
|
1205
|
+
.fill(0)
|
|
1206
|
+
.map((_, idx) => `var(--cell-width-${idx})`)
|
|
1207
|
+
.join(' + ')})`
|
|
1208
|
+
: 'auto'}; {styling?.[index]?.[j] || ''}"
|
|
1209
|
+
class:flash={copy_flash &&
|
|
1210
|
+
is_cell_selected([index, j], selected_cells)}
|
|
1211
|
+
class={is_cell_selected([index, j], selected_cells)}
|
|
1212
|
+
class:menu-active={active_cell_menu &&
|
|
1213
|
+
active_cell_menu.row === index &&
|
|
1214
|
+
active_cell_menu.col === j}
|
|
1215
|
+
>
|
|
1216
|
+
<div class="cell-wrap">
|
|
1117
1217
|
<EditableCell
|
|
1118
|
-
{
|
|
1119
|
-
bind:value={_headers[i].value}
|
|
1218
|
+
bind:value={data[index][j].value}
|
|
1120
1219
|
bind:el={els[id].input}
|
|
1220
|
+
display_value={display_value?.[index]?.[j]}
|
|
1121
1221
|
{latex_delimiters}
|
|
1122
1222
|
{line_breaks}
|
|
1123
|
-
edit={header_edit === i}
|
|
1124
|
-
on:keydown={end_header_edit}
|
|
1125
|
-
on:dblclick={() => edit_header(i)}
|
|
1126
|
-
header
|
|
1127
|
-
{root}
|
|
1128
1223
|
{editable}
|
|
1224
|
+
edit={dequal(editing, [index, j])}
|
|
1225
|
+
datatype={Array.isArray(datatype) ? datatype[j] : datatype}
|
|
1226
|
+
on:blur={() => {
|
|
1227
|
+
clear_on_focus = false;
|
|
1228
|
+
parent.focus();
|
|
1229
|
+
}}
|
|
1230
|
+
on:focus={() => {
|
|
1231
|
+
const row = index;
|
|
1232
|
+
const col = j;
|
|
1233
|
+
if (
|
|
1234
|
+
!selected_cells.some(([r, c]) => r === row && c === col)
|
|
1235
|
+
) {
|
|
1236
|
+
selected_cells = [[row, col]];
|
|
1237
|
+
}
|
|
1238
|
+
}}
|
|
1239
|
+
{clear_on_focus}
|
|
1240
|
+
{root}
|
|
1241
|
+
{max_chars}
|
|
1129
1242
|
/>
|
|
1130
|
-
|
|
1131
|
-
<
|
|
1132
|
-
|
|
1133
|
-
on:
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1243
|
+
{#if editable && should_show_cell_menu([index, j], selected_cells, editable)}
|
|
1244
|
+
<button
|
|
1245
|
+
class="cell-menu-button"
|
|
1246
|
+
on:click={(event) => toggle_cell_menu(event, index, j)}
|
|
1247
|
+
>
|
|
1248
|
+
⋮
|
|
1249
|
+
</button>
|
|
1250
|
+
{/if}
|
|
1137
1251
|
</div>
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
⋮
|
|
1144
|
-
</button>
|
|
1145
|
-
{/if}
|
|
1146
|
-
</div>
|
|
1147
|
-
</th>
|
|
1148
|
-
{/each}
|
|
1149
|
-
</tr>
|
|
1150
|
-
<tr slot="tbody" let:item let:index class:row_odd={index % 2 === 0}>
|
|
1151
|
-
{#if show_row_numbers}
|
|
1152
|
-
<td
|
|
1153
|
-
class="row-number frozen-column always-frozen"
|
|
1154
|
-
style="left: 0;"
|
|
1155
|
-
tabindex="-1"
|
|
1156
|
-
>
|
|
1157
|
-
{index + 1}
|
|
1158
|
-
</td>
|
|
1159
|
-
{/if}
|
|
1160
|
-
{#each item as { value, id }, j (id)}
|
|
1161
|
-
<td
|
|
1162
|
-
class:frozen-column={j < actual_pinned_columns}
|
|
1163
|
-
class:last-frozen={j === actual_pinned_columns - 1}
|
|
1164
|
-
tabindex={show_row_numbers && j === 0 ? -1 : 0}
|
|
1165
|
-
bind:this={els[id].cell}
|
|
1166
|
-
on:touchstart={(event) => {
|
|
1167
|
-
const touch = event.touches[0];
|
|
1168
|
-
const mouseEvent = new MouseEvent("click", {
|
|
1169
|
-
clientX: touch.clientX,
|
|
1170
|
-
clientY: touch.clientY,
|
|
1171
|
-
bubbles: true,
|
|
1172
|
-
cancelable: true,
|
|
1173
|
-
view: window
|
|
1174
|
-
});
|
|
1175
|
-
handle_cell_click(mouseEvent, index, j);
|
|
1176
|
-
}}
|
|
1177
|
-
on:mousedown={(event) => {
|
|
1178
|
-
event.preventDefault();
|
|
1179
|
-
event.stopPropagation();
|
|
1180
|
-
}}
|
|
1181
|
-
on:click={(event) => handle_cell_click(event, index, j)}
|
|
1182
|
-
style="width: {get_cell_width(j)}; left: {j <
|
|
1183
|
-
actual_pinned_columns
|
|
1184
|
-
? j === 0
|
|
1185
|
-
? show_row_numbers
|
|
1186
|
-
? 'var(--cell-width-row-number)'
|
|
1187
|
-
: '0'
|
|
1188
|
-
: `calc(${show_row_numbers ? 'var(--cell-width-row-number) + ' : ''}${Array(
|
|
1189
|
-
j
|
|
1190
|
-
)
|
|
1191
|
-
.fill(0)
|
|
1192
|
-
.map((_, idx) => `var(--cell-width-${idx})`)
|
|
1193
|
-
.join(' + ')})`
|
|
1194
|
-
: 'auto'}; {styling?.[index]?.[j] || ''}"
|
|
1195
|
-
class:flash={copy_flash &&
|
|
1196
|
-
is_cell_selected([index, j], selected_cells)}
|
|
1197
|
-
class={is_cell_selected([index, j], selected_cells)}
|
|
1198
|
-
class:menu-active={active_cell_menu &&
|
|
1199
|
-
active_cell_menu.row === index &&
|
|
1200
|
-
active_cell_menu.col === j}
|
|
1201
|
-
>
|
|
1202
|
-
<div class="cell-wrap">
|
|
1203
|
-
<EditableCell
|
|
1204
|
-
bind:value={data[index][j].value}
|
|
1205
|
-
bind:el={els[id].input}
|
|
1206
|
-
display_value={display_value?.[index]?.[j]}
|
|
1207
|
-
{latex_delimiters}
|
|
1208
|
-
{line_breaks}
|
|
1209
|
-
{editable}
|
|
1210
|
-
edit={dequal(editing, [index, j])}
|
|
1211
|
-
datatype={Array.isArray(datatype) ? datatype[j] : datatype}
|
|
1212
|
-
on:blur={() => {
|
|
1213
|
-
clear_on_focus = false;
|
|
1214
|
-
parent.focus();
|
|
1215
|
-
}}
|
|
1216
|
-
on:focus={() => {
|
|
1217
|
-
const row = index;
|
|
1218
|
-
const col = j;
|
|
1219
|
-
if (
|
|
1220
|
-
!selected_cells.some(([r, c]) => r === row && c === col)
|
|
1221
|
-
) {
|
|
1222
|
-
selected_cells = [[row, col]];
|
|
1223
|
-
}
|
|
1224
|
-
}}
|
|
1225
|
-
{clear_on_focus}
|
|
1226
|
-
{root}
|
|
1227
|
-
{max_chars}
|
|
1228
|
-
/>
|
|
1229
|
-
{#if editable && should_show_cell_menu([index, j], selected_cells, editable)}
|
|
1230
|
-
<button
|
|
1231
|
-
class="cell-menu-button"
|
|
1232
|
-
on:click={(event) => toggle_cell_menu(event, index, j)}
|
|
1233
|
-
>
|
|
1234
|
-
⋮
|
|
1235
|
-
</button>
|
|
1236
|
-
{/if}
|
|
1237
|
-
</div>
|
|
1238
|
-
</td>
|
|
1239
|
-
{/each}
|
|
1240
|
-
</tr>
|
|
1241
|
-
</VirtualTable>
|
|
1252
|
+
</td>
|
|
1253
|
+
{/each}
|
|
1254
|
+
</tr>
|
|
1255
|
+
</VirtualTable>
|
|
1256
|
+
</div>
|
|
1242
1257
|
</Upload>
|
|
1243
1258
|
</div>
|
|
1244
1259
|
</div>
|
|
1260
|
+
{#if data.length === 0 && editable && row_count[1] === "dynamic"}
|
|
1261
|
+
<div class="add-row-container">
|
|
1262
|
+
<button class="add-row-button" on:click={() => add_row()}>
|
|
1263
|
+
<span>+</span>
|
|
1264
|
+
</button>
|
|
1265
|
+
</div>
|
|
1266
|
+
{/if}
|
|
1245
1267
|
|
|
1246
1268
|
{#if active_cell_menu}
|
|
1247
1269
|
<CellMenu
|
|
@@ -1278,7 +1300,7 @@
|
|
|
1278
1300
|
on_delete_row={() => delete_row_at(active_cell_menu?.row ?? -1)}
|
|
1279
1301
|
on_delete_col={() => delete_col_at(active_header_menu?.col ?? -1)}
|
|
1280
1302
|
can_delete_rows={false}
|
|
1281
|
-
can_delete_cols={
|
|
1303
|
+
can_delete_cols={_headers.length > 1}
|
|
1282
1304
|
/>
|
|
1283
1305
|
{/if}
|
|
1284
1306
|
|
|
@@ -1300,8 +1322,6 @@
|
|
|
1300
1322
|
.table-wrap {
|
|
1301
1323
|
position: relative;
|
|
1302
1324
|
transition: 150ms;
|
|
1303
|
-
border: 1px solid var(--border-color-primary);
|
|
1304
|
-
border-radius: var(--table-radius);
|
|
1305
1325
|
}
|
|
1306
1326
|
|
|
1307
1327
|
.table-wrap.menu-open {
|
|
@@ -1334,6 +1354,12 @@
|
|
|
1334
1354
|
border-collapse: separate;
|
|
1335
1355
|
}
|
|
1336
1356
|
|
|
1357
|
+
.table-wrap > :global(button) {
|
|
1358
|
+
border: 1px solid var(--border-color-primary);
|
|
1359
|
+
border-radius: var(--table-radius);
|
|
1360
|
+
overflow: hidden;
|
|
1361
|
+
}
|
|
1362
|
+
|
|
1337
1363
|
div:not(.no-wrap) td {
|
|
1338
1364
|
overflow-wrap: anywhere;
|
|
1339
1365
|
}
|
|
@@ -1376,10 +1402,12 @@
|
|
|
1376
1402
|
|
|
1377
1403
|
th:first-child {
|
|
1378
1404
|
border-top-left-radius: var(--table-radius);
|
|
1405
|
+
border-bottom-left-radius: var(--table-radius);
|
|
1379
1406
|
}
|
|
1380
1407
|
|
|
1381
1408
|
th:last-child {
|
|
1382
1409
|
border-top-right-radius: var(--table-radius);
|
|
1410
|
+
border-bottom-right-radius: var(--table-radius);
|
|
1383
1411
|
}
|
|
1384
1412
|
|
|
1385
1413
|
th.focus,
|
|
@@ -1409,6 +1437,7 @@
|
|
|
1409
1437
|
display: flex;
|
|
1410
1438
|
align-items: center;
|
|
1411
1439
|
flex-shrink: 0;
|
|
1440
|
+
order: -1;
|
|
1412
1441
|
}
|
|
1413
1442
|
|
|
1414
1443
|
.editing {
|
|
@@ -1417,17 +1446,24 @@
|
|
|
1417
1446
|
|
|
1418
1447
|
.cell-wrap {
|
|
1419
1448
|
display: flex;
|
|
1420
|
-
align-items:
|
|
1449
|
+
align-items: center;
|
|
1450
|
+
justify-content: flex-start;
|
|
1421
1451
|
outline: none;
|
|
1422
1452
|
min-height: var(--size-9);
|
|
1423
1453
|
position: relative;
|
|
1424
|
-
height:
|
|
1454
|
+
height: 100%;
|
|
1455
|
+
padding: var(--size-2);
|
|
1456
|
+
box-sizing: border-box;
|
|
1457
|
+
margin: 0;
|
|
1458
|
+
gap: var(--size-1);
|
|
1459
|
+
overflow: visible;
|
|
1460
|
+
min-width: 0;
|
|
1461
|
+
border-radius: var(--table-radius);
|
|
1425
1462
|
}
|
|
1426
1463
|
|
|
1427
1464
|
.header-content {
|
|
1428
1465
|
display: flex;
|
|
1429
1466
|
align-items: center;
|
|
1430
|
-
justify-content: space-between;
|
|
1431
1467
|
overflow: hidden;
|
|
1432
1468
|
flex-grow: 1;
|
|
1433
1469
|
min-width: 0;
|
|
@@ -1435,7 +1471,6 @@
|
|
|
1435
1471
|
overflow-wrap: break-word;
|
|
1436
1472
|
word-break: normal;
|
|
1437
1473
|
height: 100%;
|
|
1438
|
-
padding: var(--size-1);
|
|
1439
1474
|
gap: var(--size-1);
|
|
1440
1475
|
}
|
|
1441
1476
|
|
|
@@ -1465,7 +1500,8 @@
|
|
|
1465
1500
|
transform: translateY(-50%);
|
|
1466
1501
|
}
|
|
1467
1502
|
|
|
1468
|
-
.cell-selected .cell-menu-button
|
|
1503
|
+
.cell-selected .cell-menu-button,
|
|
1504
|
+
th:hover .cell-menu-button {
|
|
1469
1505
|
display: flex;
|
|
1470
1506
|
align-items: center;
|
|
1471
1507
|
justify-content: center;
|
|
@@ -1682,4 +1718,24 @@
|
|
|
1682
1718
|
.always-frozen {
|
|
1683
1719
|
z-index: var(--layer-3);
|
|
1684
1720
|
}
|
|
1721
|
+
|
|
1722
|
+
.add-row-container {
|
|
1723
|
+
margin-top: var(--size-2);
|
|
1724
|
+
}
|
|
1725
|
+
|
|
1726
|
+
.add-row-button {
|
|
1727
|
+
width: 100%;
|
|
1728
|
+
padding: var(--size-1);
|
|
1729
|
+
background: transparent;
|
|
1730
|
+
border: 1px dashed var(--border-color-primary);
|
|
1731
|
+
border-radius: var(--radius-sm);
|
|
1732
|
+
color: var(--body-text-color);
|
|
1733
|
+
cursor: pointer;
|
|
1734
|
+
transition: all 150ms;
|
|
1735
|
+
}
|
|
1736
|
+
|
|
1737
|
+
.add-row-button:hover {
|
|
1738
|
+
background: var(--background-fill-secondary);
|
|
1739
|
+
border-style: solid;
|
|
1740
|
+
}
|
|
1685
1741
|
</style>
|