@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
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import EditableCell from "./EditableCell.svelte";
|
|
3
|
+
import CellMenuButton from "./CellMenuButton.svelte";
|
|
4
|
+
import type { I18nFormatter } from "js/core/src/gradio_helper";
|
|
5
|
+
import type { Datatype } from "./utils";
|
|
6
|
+
import { is_cell_in_selection } from "./selection_utils";
|
|
7
|
+
|
|
8
|
+
export let value: string | number;
|
|
9
|
+
export let index: number;
|
|
10
|
+
export let j: number;
|
|
11
|
+
export let actual_pinned_columns: number;
|
|
12
|
+
export let get_cell_width: (index: number) => string;
|
|
13
|
+
export let handle_cell_click: (
|
|
14
|
+
event: MouseEvent,
|
|
15
|
+
row: number,
|
|
16
|
+
col: number
|
|
17
|
+
) => void;
|
|
18
|
+
export let toggle_cell_menu: (
|
|
19
|
+
event: MouseEvent,
|
|
20
|
+
row: number,
|
|
21
|
+
col: number
|
|
22
|
+
) => void;
|
|
23
|
+
export let is_cell_selected: (
|
|
24
|
+
coords: [number, number],
|
|
25
|
+
selected_cells: [number, number][]
|
|
26
|
+
) => string;
|
|
27
|
+
export let should_show_cell_menu: (
|
|
28
|
+
coords: [number, number],
|
|
29
|
+
selected_cells: [number, number][],
|
|
30
|
+
editable: boolean
|
|
31
|
+
) => boolean;
|
|
32
|
+
export let selected_cells: [number, number][];
|
|
33
|
+
export let copy_flash: boolean;
|
|
34
|
+
export let active_cell_menu: {
|
|
35
|
+
row: number;
|
|
36
|
+
col: number;
|
|
37
|
+
x: number;
|
|
38
|
+
y: number;
|
|
39
|
+
} | null;
|
|
40
|
+
export let styling: string | undefined;
|
|
41
|
+
export let latex_delimiters: {
|
|
42
|
+
left: string;
|
|
43
|
+
right: string;
|
|
44
|
+
display: boolean;
|
|
45
|
+
}[];
|
|
46
|
+
export let line_breaks: boolean;
|
|
47
|
+
export let datatype: Datatype;
|
|
48
|
+
export let editing: [number, number] | false;
|
|
49
|
+
export let clear_on_focus: boolean;
|
|
50
|
+
export let max_chars: number | undefined;
|
|
51
|
+
export let root: string;
|
|
52
|
+
export let editable: boolean;
|
|
53
|
+
export let is_static = false;
|
|
54
|
+
export let i18n: I18nFormatter;
|
|
55
|
+
export let components: Record<string, any> = {};
|
|
56
|
+
export let el: {
|
|
57
|
+
cell: HTMLTableCellElement | null;
|
|
58
|
+
input: HTMLInputElement | null;
|
|
59
|
+
};
|
|
60
|
+
export let handle_select_column: (col: number) => void;
|
|
61
|
+
export let handle_select_row: (row: number) => void;
|
|
62
|
+
export let is_dragging: boolean;
|
|
63
|
+
|
|
64
|
+
function get_cell_position(col_index: number): string {
|
|
65
|
+
if (col_index >= actual_pinned_columns) {
|
|
66
|
+
return "auto";
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (col_index === 0) {
|
|
70
|
+
return "0";
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const previous_widths = Array(col_index)
|
|
74
|
+
.fill(0)
|
|
75
|
+
.map((_, idx) => {
|
|
76
|
+
return get_cell_width(idx);
|
|
77
|
+
})
|
|
78
|
+
.join(" + ");
|
|
79
|
+
|
|
80
|
+
return `calc(${previous_widths})`;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
$: cell_classes = is_cell_selected([index, j], selected_cells || []);
|
|
84
|
+
$: is_in_selection = is_cell_in_selection([index, j], selected_cells);
|
|
85
|
+
$: has_no_top = cell_classes.includes("no-top");
|
|
86
|
+
$: has_no_bottom = cell_classes.includes("no-bottom");
|
|
87
|
+
$: has_no_left = cell_classes.includes("no-left");
|
|
88
|
+
$: has_no_right = cell_classes.includes("no-right");
|
|
89
|
+
</script>
|
|
90
|
+
|
|
91
|
+
<td
|
|
92
|
+
class:pinned-column={j < actual_pinned_columns}
|
|
93
|
+
class:last-pinned={j === actual_pinned_columns - 1}
|
|
94
|
+
tabindex={j < actual_pinned_columns ? -1 : 0}
|
|
95
|
+
bind:this={el.cell}
|
|
96
|
+
data-row={index}
|
|
97
|
+
data-col={j}
|
|
98
|
+
data-testid={`cell-${index}-${j}`}
|
|
99
|
+
on:mousedown={(e) => handle_cell_click(e, index, j)}
|
|
100
|
+
on:contextmenu|preventDefault={(e) => toggle_cell_menu(e, index, j)}
|
|
101
|
+
style="width: {get_cell_width(j)}; left: {get_cell_position(j)}; {styling ||
|
|
102
|
+
''}"
|
|
103
|
+
class:flash={copy_flash && is_in_selection}
|
|
104
|
+
class:cell-selected={is_in_selection}
|
|
105
|
+
class:no-top={has_no_top}
|
|
106
|
+
class:no-bottom={has_no_bottom}
|
|
107
|
+
class:no-left={has_no_left}
|
|
108
|
+
class:no-right={has_no_right}
|
|
109
|
+
class:menu-active={active_cell_menu &&
|
|
110
|
+
active_cell_menu.row === index &&
|
|
111
|
+
active_cell_menu.col === j}
|
|
112
|
+
class:dragging={is_dragging}
|
|
113
|
+
>
|
|
114
|
+
<div class="cell-wrap">
|
|
115
|
+
<EditableCell
|
|
116
|
+
bind:value
|
|
117
|
+
bind:el={el.input}
|
|
118
|
+
display_value={String(value)}
|
|
119
|
+
{latex_delimiters}
|
|
120
|
+
{line_breaks}
|
|
121
|
+
{editable}
|
|
122
|
+
{is_static}
|
|
123
|
+
edit={editing && editing[0] === index && editing[1] === j}
|
|
124
|
+
{datatype}
|
|
125
|
+
on:blur={() => {
|
|
126
|
+
clear_on_focus = false;
|
|
127
|
+
}}
|
|
128
|
+
on:focus={() => {
|
|
129
|
+
const row = index;
|
|
130
|
+
const col = j;
|
|
131
|
+
if (!selected_cells.some(([r, c]) => r === row && c === col)) {
|
|
132
|
+
selected_cells = [[row, col]];
|
|
133
|
+
}
|
|
134
|
+
}}
|
|
135
|
+
{clear_on_focus}
|
|
136
|
+
{root}
|
|
137
|
+
{max_chars}
|
|
138
|
+
{i18n}
|
|
139
|
+
{components}
|
|
140
|
+
show_selection_buttons={selected_cells.length === 1 &&
|
|
141
|
+
selected_cells[0][0] === index &&
|
|
142
|
+
selected_cells[0][1] === j}
|
|
143
|
+
coords={[index, j]}
|
|
144
|
+
on_select_column={handle_select_column}
|
|
145
|
+
on_select_row={handle_select_row}
|
|
146
|
+
{is_dragging}
|
|
147
|
+
/>
|
|
148
|
+
{#if editable && should_show_cell_menu([index, j], selected_cells, editable)}
|
|
149
|
+
<CellMenuButton on_click={(event) => toggle_cell_menu(event, index, j)} />
|
|
150
|
+
{/if}
|
|
151
|
+
</div>
|
|
152
|
+
</td>
|
|
153
|
+
|
|
154
|
+
<style>
|
|
155
|
+
td {
|
|
156
|
+
--ring-color: transparent;
|
|
157
|
+
position: relative;
|
|
158
|
+
outline: none;
|
|
159
|
+
box-shadow: inset 0 0 0 1px var(--ring-color);
|
|
160
|
+
padding: 0;
|
|
161
|
+
border-right-width: 0px;
|
|
162
|
+
border-left-width: 1px;
|
|
163
|
+
border-style: solid;
|
|
164
|
+
border-color: var(--border-color-primary);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
.cell-wrap {
|
|
168
|
+
display: flex;
|
|
169
|
+
align-items: center;
|
|
170
|
+
justify-content: flex-start;
|
|
171
|
+
outline: none;
|
|
172
|
+
min-height: var(--size-9);
|
|
173
|
+
position: relative;
|
|
174
|
+
height: 100%;
|
|
175
|
+
padding: var(--size-2);
|
|
176
|
+
box-sizing: border-box;
|
|
177
|
+
margin: 0;
|
|
178
|
+
gap: var(--size-1);
|
|
179
|
+
overflow: visible;
|
|
180
|
+
min-width: 0;
|
|
181
|
+
border-radius: var(--table-radius);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
.cell-selected {
|
|
185
|
+
--ring-color: var(--color-accent);
|
|
186
|
+
box-shadow: inset 0 0 0 2px var(--ring-color);
|
|
187
|
+
z-index: 2;
|
|
188
|
+
position: relative;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
.cell-selected :global(.cell-menu-button) {
|
|
192
|
+
display: flex;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
.flash.cell-selected {
|
|
196
|
+
animation: flash-color 700ms ease-out;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
@keyframes flash-color {
|
|
200
|
+
0%,
|
|
201
|
+
30% {
|
|
202
|
+
background: var(--color-accent-copied);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
100% {
|
|
206
|
+
background: transparent;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
.pinned-column {
|
|
211
|
+
position: sticky;
|
|
212
|
+
z-index: 3;
|
|
213
|
+
border-right: none;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
.pinned-column:nth-child(odd) {
|
|
217
|
+
background: var(--table-odd-background-fill);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
.pinned-column:nth-child(even) {
|
|
221
|
+
background: var(--table-even-background-fill);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
td:first-child {
|
|
225
|
+
border-left-width: 0px;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
:global(tr:last-child) td:first-child {
|
|
229
|
+
border-bottom-left-radius: var(--table-radius);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
:global(tr:last-child) td:last-child {
|
|
233
|
+
border-bottom-right-radius: var(--table-radius);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
.dragging {
|
|
237
|
+
cursor: crosshair;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/* Add back the cell selection border styles */
|
|
241
|
+
.cell-selected.no-top {
|
|
242
|
+
box-shadow:
|
|
243
|
+
inset 2px 0 0 var(--ring-color),
|
|
244
|
+
inset -2px 0 0 var(--ring-color),
|
|
245
|
+
inset 0 -2px 0 var(--ring-color);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
.cell-selected.no-bottom {
|
|
249
|
+
box-shadow:
|
|
250
|
+
inset 2px 0 0 var(--ring-color),
|
|
251
|
+
inset -2px 0 0 var(--ring-color),
|
|
252
|
+
inset 0 2px 0 var(--ring-color);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
.cell-selected.no-left {
|
|
256
|
+
box-shadow:
|
|
257
|
+
inset 0 2px 0 var(--ring-color),
|
|
258
|
+
inset -2px 0 0 var(--ring-color),
|
|
259
|
+
inset 0 -2px 0 var(--ring-color);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
.cell-selected.no-right {
|
|
263
|
+
box-shadow:
|
|
264
|
+
inset 0 2px 0 var(--ring-color),
|
|
265
|
+
inset 2px 0 0 var(--ring-color),
|
|
266
|
+
inset 0 -2px 0 var(--ring-color);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
.cell-selected.no-top.no-left {
|
|
270
|
+
box-shadow:
|
|
271
|
+
inset -2px 0 0 var(--ring-color),
|
|
272
|
+
inset 0 -2px 0 var(--ring-color);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
.cell-selected.no-top.no-right {
|
|
276
|
+
box-shadow:
|
|
277
|
+
inset 2px 0 0 var(--ring-color),
|
|
278
|
+
inset 0 -2px 0 var(--ring-color);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
.cell-selected.no-bottom.no-left {
|
|
282
|
+
box-shadow:
|
|
283
|
+
inset -2px 0 0 var(--ring-color),
|
|
284
|
+
inset 0 2px 0 var(--ring-color);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
.cell-selected.no-bottom.no-right {
|
|
288
|
+
box-shadow:
|
|
289
|
+
inset 2px 0 0 var(--ring-color),
|
|
290
|
+
inset 0 2px 0 var(--ring-color);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
.cell-selected.no-top.no-bottom {
|
|
294
|
+
box-shadow:
|
|
295
|
+
inset 2px 0 0 var(--ring-color),
|
|
296
|
+
inset -2px 0 0 var(--ring-color);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
.cell-selected.no-left.no-right {
|
|
300
|
+
box-shadow:
|
|
301
|
+
inset 0 2px 0 var(--ring-color),
|
|
302
|
+
inset 0 -2px 0 var(--ring-color);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
.cell-selected.no-top.no-left.no-right {
|
|
306
|
+
box-shadow: inset 0 -2px 0 var(--ring-color);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
.cell-selected.no-bottom.no-left.no-right {
|
|
310
|
+
box-shadow: inset 0 2px 0 var(--ring-color);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
.cell-selected.no-left.no-top.no-bottom {
|
|
314
|
+
box-shadow: inset -2px 0 0 var(--ring-color);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
.cell-selected.no-right.no-top.no-bottom {
|
|
318
|
+
box-shadow: inset 2px 0 0 var(--ring-color);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
.cell-selected.no-top.no-bottom.no-left.no-right {
|
|
322
|
+
box-shadow: none;
|
|
323
|
+
}
|
|
324
|
+
</style>
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import EditableCell from "./EditableCell.svelte";
|
|
3
|
+
import CellMenuButton from "./CellMenuButton.svelte";
|
|
4
|
+
import type { I18nFormatter } from "js/core/src/gradio_helper";
|
|
5
|
+
import type { SortDirection } from "./context/table_context";
|
|
6
|
+
import Padlock from "./icons/Padlock.svelte";
|
|
7
|
+
import SortArrowUp from "./icons/SortArrowUp.svelte";
|
|
8
|
+
import SortArrowDown from "./icons/SortArrowDown.svelte";
|
|
9
|
+
|
|
10
|
+
export let value: string;
|
|
11
|
+
export let i: number;
|
|
12
|
+
export let actual_pinned_columns: number;
|
|
13
|
+
export let header_edit: number | false;
|
|
14
|
+
export let selected_header: number | false;
|
|
15
|
+
export let get_sort_status: (
|
|
16
|
+
value: string,
|
|
17
|
+
headers: string[]
|
|
18
|
+
) => "none" | "asc" | "desc";
|
|
19
|
+
export let headers: string[];
|
|
20
|
+
export let get_cell_width: (index: number) => string;
|
|
21
|
+
export let handle_header_click: (event: MouseEvent, col: number) => void;
|
|
22
|
+
export let toggle_header_menu: (event: MouseEvent, col: number) => void;
|
|
23
|
+
export let end_header_edit: (event: CustomEvent<KeyboardEvent>) => void;
|
|
24
|
+
export let sort_columns: { col: number; direction: SortDirection }[] = [];
|
|
25
|
+
|
|
26
|
+
export let latex_delimiters: {
|
|
27
|
+
left: string;
|
|
28
|
+
right: string;
|
|
29
|
+
display: boolean;
|
|
30
|
+
}[];
|
|
31
|
+
export let line_breaks: boolean;
|
|
32
|
+
export let max_chars: number | undefined;
|
|
33
|
+
export let root: string;
|
|
34
|
+
export let editable: boolean;
|
|
35
|
+
export let i18n: I18nFormatter;
|
|
36
|
+
export let el: HTMLInputElement | null;
|
|
37
|
+
export let is_static: boolean;
|
|
38
|
+
export let col_count: [number, "fixed" | "dynamic"];
|
|
39
|
+
|
|
40
|
+
$: can_add_columns = col_count && col_count[1] === "dynamic";
|
|
41
|
+
$: sort_index = sort_columns.findIndex((item) => item.col === i);
|
|
42
|
+
$: sort_priority = sort_index !== -1 ? sort_index + 1 : null;
|
|
43
|
+
$: current_direction =
|
|
44
|
+
sort_index !== -1 ? sort_columns[sort_index].direction : null;
|
|
45
|
+
|
|
46
|
+
function get_header_position(col_index: number): string {
|
|
47
|
+
if (col_index >= actual_pinned_columns) {
|
|
48
|
+
return "auto";
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (col_index === 0) {
|
|
52
|
+
return "0";
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const previous_widths = Array(col_index)
|
|
56
|
+
.fill(0)
|
|
57
|
+
.map((_, idx) => {
|
|
58
|
+
return get_cell_width(idx);
|
|
59
|
+
})
|
|
60
|
+
.join(" + ");
|
|
61
|
+
|
|
62
|
+
return `calc(${previous_widths})`;
|
|
63
|
+
}
|
|
64
|
+
</script>
|
|
65
|
+
|
|
66
|
+
<th
|
|
67
|
+
class:pinned-column={i < actual_pinned_columns}
|
|
68
|
+
class:last-pinned={i === actual_pinned_columns - 1}
|
|
69
|
+
class:focus={header_edit === i || selected_header === i}
|
|
70
|
+
class:sorted={sort_index !== -1}
|
|
71
|
+
aria-sort={get_sort_status(value, headers) === "none"
|
|
72
|
+
? "none"
|
|
73
|
+
: get_sort_status(value, headers) === "asc"
|
|
74
|
+
? "ascending"
|
|
75
|
+
: "descending"}
|
|
76
|
+
style="width: {get_cell_width(i)}; left: {get_header_position(i)};"
|
|
77
|
+
on:click={(event) => handle_header_click(event, i)}
|
|
78
|
+
on:mousedown={(event) => {
|
|
79
|
+
event.preventDefault();
|
|
80
|
+
event.stopPropagation();
|
|
81
|
+
}}
|
|
82
|
+
title={value}
|
|
83
|
+
>
|
|
84
|
+
<div class="cell-wrap">
|
|
85
|
+
<div class="header-content">
|
|
86
|
+
<button
|
|
87
|
+
class="header-button"
|
|
88
|
+
on:click={(event) => handle_header_click(event, i)}
|
|
89
|
+
on:mousedown={(event) => {
|
|
90
|
+
event.preventDefault();
|
|
91
|
+
event.stopPropagation();
|
|
92
|
+
}}
|
|
93
|
+
title={value}
|
|
94
|
+
>
|
|
95
|
+
<EditableCell
|
|
96
|
+
{max_chars}
|
|
97
|
+
bind:value
|
|
98
|
+
bind:el
|
|
99
|
+
{latex_delimiters}
|
|
100
|
+
{line_breaks}
|
|
101
|
+
edit={header_edit === i}
|
|
102
|
+
on:keydown={(event) => {
|
|
103
|
+
if (
|
|
104
|
+
event.detail.key === "Enter" ||
|
|
105
|
+
event.detail.key === "Escape" ||
|
|
106
|
+
event.detail.key === "Tab"
|
|
107
|
+
) {
|
|
108
|
+
end_header_edit(event);
|
|
109
|
+
}
|
|
110
|
+
}}
|
|
111
|
+
header
|
|
112
|
+
{root}
|
|
113
|
+
{editable}
|
|
114
|
+
{is_static}
|
|
115
|
+
{i18n}
|
|
116
|
+
/>
|
|
117
|
+
{#if sort_index !== -1}
|
|
118
|
+
<div class="sort-indicators">
|
|
119
|
+
<span class="sort-arrow">
|
|
120
|
+
{#if current_direction === "asc"}
|
|
121
|
+
<SortArrowUp size={12} />
|
|
122
|
+
{:else}
|
|
123
|
+
<SortArrowDown size={12} />
|
|
124
|
+
{/if}
|
|
125
|
+
</span>
|
|
126
|
+
{#if sort_columns.length > 1}
|
|
127
|
+
<span class="sort-priority">
|
|
128
|
+
{sort_priority}
|
|
129
|
+
</span>
|
|
130
|
+
{/if}
|
|
131
|
+
</div>
|
|
132
|
+
{/if}
|
|
133
|
+
</button>
|
|
134
|
+
{#if is_static}
|
|
135
|
+
<Padlock />
|
|
136
|
+
{/if}
|
|
137
|
+
</div>
|
|
138
|
+
{#if can_add_columns}
|
|
139
|
+
<CellMenuButton on_click={(event) => toggle_header_menu(event, i)} />
|
|
140
|
+
{/if}
|
|
141
|
+
</div>
|
|
142
|
+
</th>
|
|
143
|
+
|
|
144
|
+
<style>
|
|
145
|
+
th {
|
|
146
|
+
--ring-color: transparent;
|
|
147
|
+
position: relative;
|
|
148
|
+
outline: none;
|
|
149
|
+
box-shadow: inset 0 0 0 1px var(--ring-color);
|
|
150
|
+
padding: 0;
|
|
151
|
+
background: var(--table-even-background-fill);
|
|
152
|
+
border-right-width: 0px;
|
|
153
|
+
border-left-width: 1px;
|
|
154
|
+
border-style: solid;
|
|
155
|
+
border-color: var(--border-color-primary);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
th:first-child {
|
|
159
|
+
border-top-left-radius: var(--table-radius);
|
|
160
|
+
border-bottom-left-radius: var(--table-radius);
|
|
161
|
+
border-left-width: 0px;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
th:last-child {
|
|
165
|
+
border-top-right-radius: var(--table-radius);
|
|
166
|
+
border-bottom-right-radius: var(--table-radius);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
th.focus {
|
|
170
|
+
--ring-color: var(--color-accent);
|
|
171
|
+
box-shadow: inset 0 0 0 2px var(--ring-color);
|
|
172
|
+
z-index: 4;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
th.focus :global(.cell-menu-button) {
|
|
176
|
+
display: flex;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
th:hover :global(.cell-menu-button) {
|
|
180
|
+
display: flex;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
.cell-wrap {
|
|
184
|
+
display: flex;
|
|
185
|
+
align-items: center;
|
|
186
|
+
justify-content: flex-start;
|
|
187
|
+
outline: none;
|
|
188
|
+
min-height: var(--size-9);
|
|
189
|
+
position: relative;
|
|
190
|
+
height: 100%;
|
|
191
|
+
padding: var(--size-2);
|
|
192
|
+
box-sizing: border-box;
|
|
193
|
+
margin: 0;
|
|
194
|
+
gap: var(--size-1);
|
|
195
|
+
overflow: visible;
|
|
196
|
+
min-width: 0;
|
|
197
|
+
border-radius: var(--table-radius);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
.header-content {
|
|
201
|
+
display: flex;
|
|
202
|
+
align-items: center;
|
|
203
|
+
overflow: hidden;
|
|
204
|
+
flex-grow: 1;
|
|
205
|
+
min-width: 0;
|
|
206
|
+
white-space: normal;
|
|
207
|
+
overflow-wrap: break-word;
|
|
208
|
+
word-break: normal;
|
|
209
|
+
height: 100%;
|
|
210
|
+
gap: var(--size-1);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
.header-button {
|
|
214
|
+
display: flex;
|
|
215
|
+
text-align: left;
|
|
216
|
+
width: 100%;
|
|
217
|
+
overflow: hidden;
|
|
218
|
+
text-overflow: ellipsis;
|
|
219
|
+
display: flex;
|
|
220
|
+
align-items: center;
|
|
221
|
+
position: relative;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
.sort-indicators {
|
|
225
|
+
display: flex;
|
|
226
|
+
align-items: center;
|
|
227
|
+
margin-left: var(--size-1);
|
|
228
|
+
gap: var(--size-1);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
.sort-arrow {
|
|
232
|
+
display: flex;
|
|
233
|
+
align-items: center;
|
|
234
|
+
justify-content: center;
|
|
235
|
+
color: var(--body-text-color);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
.sort-priority {
|
|
239
|
+
display: flex;
|
|
240
|
+
align-items: center;
|
|
241
|
+
justify-content: center;
|
|
242
|
+
font-size: var(--size-2);
|
|
243
|
+
background-color: var(--button-secondary-background-fill);
|
|
244
|
+
color: var(--body-text-color);
|
|
245
|
+
border-radius: var(--radius-sm);
|
|
246
|
+
width: var(--size-2-5);
|
|
247
|
+
height: var(--size-2-5);
|
|
248
|
+
padding: var(--size-1-5);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
.pinned-column {
|
|
252
|
+
position: sticky;
|
|
253
|
+
z-index: 5;
|
|
254
|
+
border-right: none;
|
|
255
|
+
}
|
|
256
|
+
</style>
|
package/shared/Toolbar.svelte
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import { Maximize, Minimize, Copy } from "@gradio/icons";
|
|
2
|
+
import { Maximize, Minimize, Copy, Check } from "@gradio/icons";
|
|
3
3
|
import { onDestroy } from "svelte";
|
|
4
4
|
import { createEventDispatcher } from "svelte";
|
|
5
|
-
import FilterIcon from "./icons/FilterIcon.svelte";
|
|
6
5
|
|
|
7
6
|
export let show_fullscreen_button = false;
|
|
8
7
|
export let show_copy_button = false;
|
|
@@ -18,8 +17,17 @@
|
|
|
18
17
|
let copied = false;
|
|
19
18
|
let timer: ReturnType<typeof setTimeout>;
|
|
20
19
|
export let current_search_query: string | null = null;
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
let input_value = "";
|
|
21
|
+
|
|
22
|
+
function handle_search_input(e: Event): void {
|
|
23
|
+
const target = e.target as HTMLInputElement;
|
|
24
|
+
input_value = target.value;
|
|
25
|
+
const new_query = input_value || null;
|
|
26
|
+
if (current_search_query !== new_query) {
|
|
27
|
+
current_search_query = new_query;
|
|
28
|
+
dispatch("search", current_search_query);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
23
31
|
|
|
24
32
|
function copy_feedback(): void {
|
|
25
33
|
copied = true;
|
|
@@ -45,9 +53,12 @@
|
|
|
45
53
|
<div class="search-container">
|
|
46
54
|
<input
|
|
47
55
|
type="text"
|
|
48
|
-
|
|
49
|
-
|
|
56
|
+
value={current_search_query || ""}
|
|
57
|
+
on:input={handle_search_input}
|
|
58
|
+
placeholder={show_search === "filter" ? "Filter..." : "Search..."}
|
|
50
59
|
class="search-input"
|
|
60
|
+
class:filter-mode={show_search === "filter"}
|
|
61
|
+
title={`Enter text to ${show_search} the table`}
|
|
51
62
|
/>
|
|
52
63
|
{#if current_search_query && show_search === "filter"}
|
|
53
64
|
<button
|
|
@@ -56,7 +67,7 @@
|
|
|
56
67
|
aria-label="Apply filter and update dataframe values"
|
|
57
68
|
title="Apply filter and update dataframe values"
|
|
58
69
|
>
|
|
59
|
-
<
|
|
70
|
+
<Check />
|
|
60
71
|
</button>
|
|
61
72
|
{/if}
|
|
62
73
|
</div>
|
|
@@ -69,7 +80,7 @@
|
|
|
69
80
|
title={copied ? "Copied to clipboard" : "Copy table data"}
|
|
70
81
|
>
|
|
71
82
|
{#if copied}
|
|
72
|
-
<
|
|
83
|
+
<Check />
|
|
73
84
|
{:else}
|
|
74
85
|
<Copy />
|
|
75
86
|
{/if}
|