@gradio/dataframe 0.11.0-beta.7 → 0.11.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 +36 -0
- package/Dataframe.stories.svelte +30 -1
- package/dist/shared/Arrow.svelte +9 -0
- package/dist/shared/Arrow.svelte.d.ts +16 -0
- package/dist/shared/CellMenu.svelte +101 -0
- package/dist/shared/CellMenu.svelte.d.ts +24 -0
- package/dist/shared/Table.svelte +245 -112
- package/package.json +9 -9
- package/shared/Arrow.svelte +10 -0
- package/shared/CellMenu.svelte +111 -0
- package/shared/Table.svelte +290 -121
package/dist/shared/Table.svelte
CHANGED
|
@@ -3,10 +3,10 @@ import { dsvFormat } from "d3-dsv";
|
|
|
3
3
|
import { dequal } from "dequal/lite";
|
|
4
4
|
import { copy } from "@gradio/utils";
|
|
5
5
|
import { Upload } from "@gradio/upload";
|
|
6
|
-
import { BaseButton } from "@gradio/button";
|
|
7
6
|
import EditableCell from "./EditableCell.svelte";
|
|
8
7
|
import {} from "@gradio/client";
|
|
9
8
|
import VirtualTable from "./VirtualTable.svelte";
|
|
9
|
+
import CellMenu from "./CellMenu.svelte";
|
|
10
10
|
export let datatype;
|
|
11
11
|
export let label = null;
|
|
12
12
|
export let show_label = true;
|
|
@@ -34,7 +34,7 @@ const get_data_at = (row, col) => data?.[row]?.[col]?.value;
|
|
|
34
34
|
$: {
|
|
35
35
|
if (selected !== false) {
|
|
36
36
|
const [row, col] = selected;
|
|
37
|
-
if (!isNaN(row) && !isNaN(col)) {
|
|
37
|
+
if (!isNaN(row) && !isNaN(col) && data[row]) {
|
|
38
38
|
dispatch("select", {
|
|
39
39
|
index: [row, col],
|
|
40
40
|
value: get_data_at(row, col),
|
|
@@ -250,7 +250,13 @@ async function handle_keydown(event) {
|
|
|
250
250
|
}
|
|
251
251
|
}
|
|
252
252
|
}
|
|
253
|
+
let active_cell = null;
|
|
253
254
|
async function handle_cell_click(i, j) {
|
|
255
|
+
if (active_cell && active_cell.row === i && active_cell.col === j) {
|
|
256
|
+
active_cell = null;
|
|
257
|
+
} else {
|
|
258
|
+
active_cell = { row: i, col: j };
|
|
259
|
+
}
|
|
254
260
|
if (dequal(editing, [i, j]))
|
|
255
261
|
return;
|
|
256
262
|
header_edit = false;
|
|
@@ -308,40 +314,46 @@ async function add_row(index) {
|
|
|
308
314
|
values = [Array(headers.length).fill("")];
|
|
309
315
|
return;
|
|
310
316
|
}
|
|
311
|
-
data.
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
317
|
+
const new_row = Array(data[0].length).fill(0).map((_, i) => {
|
|
318
|
+
const _id = make_id();
|
|
319
|
+
els[_id] = { cell: null, input: null };
|
|
320
|
+
return { id: _id, value: "" };
|
|
321
|
+
});
|
|
322
|
+
if (index !== void 0 && index >= 0 && index <= data.length) {
|
|
323
|
+
data.splice(index, 0, new_row);
|
|
324
|
+
} else {
|
|
325
|
+
data.push(new_row);
|
|
326
|
+
}
|
|
320
327
|
data = data;
|
|
321
|
-
selected = [index ? index
|
|
328
|
+
selected = [index !== void 0 ? index : data.length - 1, 0];
|
|
322
329
|
}
|
|
323
330
|
$:
|
|
324
331
|
(data || selected_header) && trigger_change();
|
|
325
|
-
async function add_col() {
|
|
332
|
+
async function add_col(index) {
|
|
326
333
|
parent.focus();
|
|
327
334
|
if (col_count[1] !== "dynamic")
|
|
328
335
|
return;
|
|
336
|
+
const insert_index = index !== void 0 ? index : data[0].length;
|
|
329
337
|
for (let i = 0; i < data.length; i++) {
|
|
330
338
|
const _id = make_id();
|
|
331
339
|
els[_id] = { cell: null, input: null };
|
|
332
|
-
data[i].
|
|
340
|
+
data[i].splice(insert_index, 0, { id: _id, value: "" });
|
|
333
341
|
}
|
|
334
|
-
headers.
|
|
342
|
+
headers.splice(insert_index, 0, `Header ${headers.length + 1}`);
|
|
335
343
|
data = data;
|
|
336
344
|
headers = headers;
|
|
337
345
|
await tick();
|
|
338
346
|
requestAnimationFrame(() => {
|
|
339
|
-
edit_header(
|
|
347
|
+
edit_header(insert_index, true);
|
|
340
348
|
const new_w = parent.querySelectorAll("tbody")[1].offsetWidth;
|
|
341
349
|
parent.querySelectorAll("table")[1].scrollTo({ left: new_w });
|
|
342
350
|
});
|
|
343
351
|
}
|
|
344
352
|
function handle_click_outside(event) {
|
|
353
|
+
if (active_cell_menu && !event.target.closest(".cell-menu") || active_header_menu && !event.target.closest(".cell-menu")) {
|
|
354
|
+
active_cell_menu = null;
|
|
355
|
+
active_header_menu = null;
|
|
356
|
+
}
|
|
345
357
|
event.stopImmediatePropagation();
|
|
346
358
|
const [trigger] = event.composedPath();
|
|
347
359
|
if (parent.contains(trigger)) {
|
|
@@ -351,6 +363,9 @@ function handle_click_outside(event) {
|
|
|
351
363
|
header_edit = false;
|
|
352
364
|
selected_header = false;
|
|
353
365
|
selected = false;
|
|
366
|
+
active_cell = null;
|
|
367
|
+
active_cell_menu = null;
|
|
368
|
+
active_header_menu = null;
|
|
354
369
|
}
|
|
355
370
|
function guess_delimitaor(text, possibleDelimiters) {
|
|
356
371
|
return possibleDelimiters.filter(weedOut);
|
|
@@ -485,6 +500,75 @@ onMount(() => {
|
|
|
485
500
|
observer.disconnect();
|
|
486
501
|
};
|
|
487
502
|
});
|
|
503
|
+
let highlighted_column = null;
|
|
504
|
+
let active_cell_menu = null;
|
|
505
|
+
function toggle_cell_menu(event, row, col) {
|
|
506
|
+
event.stopPropagation();
|
|
507
|
+
if (active_cell_menu && active_cell_menu.row === row && active_cell_menu.col === col) {
|
|
508
|
+
active_cell_menu = null;
|
|
509
|
+
} else {
|
|
510
|
+
const cell = event.target.closest("td");
|
|
511
|
+
if (cell) {
|
|
512
|
+
const rect = cell.getBoundingClientRect();
|
|
513
|
+
active_cell_menu = {
|
|
514
|
+
row,
|
|
515
|
+
col,
|
|
516
|
+
x: rect.right,
|
|
517
|
+
y: rect.bottom
|
|
518
|
+
};
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
function add_row_at(index, position) {
|
|
523
|
+
const row_index = position === "above" ? index : index + 1;
|
|
524
|
+
add_row(row_index);
|
|
525
|
+
active_cell_menu = null;
|
|
526
|
+
active_header_menu = null;
|
|
527
|
+
}
|
|
528
|
+
function add_col_at(index, position) {
|
|
529
|
+
const col_index = position === "left" ? index : index + 1;
|
|
530
|
+
add_col(col_index);
|
|
531
|
+
active_cell_menu = null;
|
|
532
|
+
active_header_menu = null;
|
|
533
|
+
}
|
|
534
|
+
onMount(() => {
|
|
535
|
+
document.addEventListener("click", handle_click_outside);
|
|
536
|
+
return () => {
|
|
537
|
+
document.removeEventListener("click", handle_click_outside);
|
|
538
|
+
};
|
|
539
|
+
});
|
|
540
|
+
let active_button = null;
|
|
541
|
+
function toggle_header_button(col) {
|
|
542
|
+
if (active_button?.type === "header" && active_button.col === col) {
|
|
543
|
+
active_button = null;
|
|
544
|
+
} else {
|
|
545
|
+
active_button = { type: "header", col };
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
function toggle_cell_button(row, col) {
|
|
549
|
+
if (active_button?.type === "cell" && active_button.row === row && active_button.col === col) {
|
|
550
|
+
active_button = null;
|
|
551
|
+
} else {
|
|
552
|
+
active_button = { type: "cell", row, col };
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
let active_header_menu = null;
|
|
556
|
+
function toggle_header_menu(event, col) {
|
|
557
|
+
event.stopPropagation();
|
|
558
|
+
if (active_header_menu && active_header_menu.col === col) {
|
|
559
|
+
active_header_menu = null;
|
|
560
|
+
} else {
|
|
561
|
+
const header = event.target.closest("th");
|
|
562
|
+
if (header) {
|
|
563
|
+
const rect = header.getBoundingClientRect();
|
|
564
|
+
active_header_menu = {
|
|
565
|
+
col,
|
|
566
|
+
x: rect.right,
|
|
567
|
+
y: rect.bottom
|
|
568
|
+
};
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
}
|
|
488
572
|
</script>
|
|
489
573
|
|
|
490
574
|
<svelte:window
|
|
@@ -603,40 +687,58 @@ onMount(() => {
|
|
|
603
687
|
class:focus={header_edit === i || selected_header === i}
|
|
604
688
|
aria-sort={get_sort_status(value, sort_by, sort_direction)}
|
|
605
689
|
style="width: var(--cell-width-{i});"
|
|
690
|
+
on:click={() => {
|
|
691
|
+
toggle_header_button(i);
|
|
692
|
+
}}
|
|
606
693
|
>
|
|
607
694
|
<div class="cell-wrap">
|
|
608
|
-
<
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
height="1em"
|
|
633
|
-
viewBox="0 0 9 7"
|
|
634
|
-
fill="none"
|
|
635
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
695
|
+
<div class="header-content">
|
|
696
|
+
<EditableCell
|
|
697
|
+
bind:value={_headers[i].value}
|
|
698
|
+
bind:el={els[id].input}
|
|
699
|
+
{latex_delimiters}
|
|
700
|
+
{line_breaks}
|
|
701
|
+
edit={header_edit === i}
|
|
702
|
+
on:keydown={end_header_edit}
|
|
703
|
+
on:dblclick={() => edit_header(i)}
|
|
704
|
+
{select_on_focus}
|
|
705
|
+
header
|
|
706
|
+
{root}
|
|
707
|
+
/>
|
|
708
|
+
<!-- TODO: fix -->
|
|
709
|
+
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
|
710
|
+
<!-- svelte-ignore a11y-no-static-element-interactions-->
|
|
711
|
+
<div
|
|
712
|
+
class:sorted={sort_by === i}
|
|
713
|
+
class:des={sort_by === i && sort_direction === "des"}
|
|
714
|
+
class="sort-button {sort_direction}"
|
|
715
|
+
on:click={(event) => {
|
|
716
|
+
event.stopPropagation();
|
|
717
|
+
handle_sort(i);
|
|
718
|
+
}}
|
|
636
719
|
>
|
|
637
|
-
<
|
|
638
|
-
|
|
720
|
+
<svg
|
|
721
|
+
width="1em"
|
|
722
|
+
height="1em"
|
|
723
|
+
viewBox="0 0 9 7"
|
|
724
|
+
fill="none"
|
|
725
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
726
|
+
>
|
|
727
|
+
<path d="M4.49999 0L8.3971 6.75H0.602875L4.49999 0Z" />
|
|
728
|
+
</svg>
|
|
729
|
+
</div>
|
|
639
730
|
</div>
|
|
731
|
+
|
|
732
|
+
{#if editable}
|
|
733
|
+
<button
|
|
734
|
+
class="cell-menu-button"
|
|
735
|
+
class:visible={active_button?.type === "header" &&
|
|
736
|
+
active_button.col === i}
|
|
737
|
+
on:click={(event) => toggle_header_menu(event, i)}
|
|
738
|
+
>
|
|
739
|
+
⋮
|
|
740
|
+
</button>
|
|
741
|
+
{/if}
|
|
640
742
|
</div>
|
|
641
743
|
</th>
|
|
642
744
|
{/each}
|
|
@@ -647,11 +749,17 @@ onMount(() => {
|
|
|
647
749
|
<td
|
|
648
750
|
tabindex="0"
|
|
649
751
|
on:touchstart={() => start_edit(index, j)}
|
|
650
|
-
on:click={() =>
|
|
752
|
+
on:click={() => {
|
|
753
|
+
handle_cell_click(index, j);
|
|
754
|
+
toggle_cell_button(index, j);
|
|
755
|
+
}}
|
|
651
756
|
on:dblclick={() => start_edit(index, j)}
|
|
652
757
|
style:width="var(--cell-width-{j})"
|
|
653
758
|
style={styling?.[index]?.[j] || ""}
|
|
654
759
|
class:focus={dequal(selected, [index, j])}
|
|
760
|
+
class:menu-active={active_cell_menu &&
|
|
761
|
+
active_cell_menu.row === index &&
|
|
762
|
+
active_cell_menu.col === j}
|
|
655
763
|
>
|
|
656
764
|
<div class="cell-wrap">
|
|
657
765
|
<EditableCell
|
|
@@ -667,6 +775,17 @@ onMount(() => {
|
|
|
667
775
|
{clear_on_focus}
|
|
668
776
|
{root}
|
|
669
777
|
/>
|
|
778
|
+
{#if editable}
|
|
779
|
+
<button
|
|
780
|
+
class="cell-menu-button"
|
|
781
|
+
class:visible={active_button?.type === "cell" &&
|
|
782
|
+
active_button.row === index &&
|
|
783
|
+
active_button.col === j}
|
|
784
|
+
on:click={(event) => toggle_cell_menu(event, index, j)}
|
|
785
|
+
>
|
|
786
|
+
⋮
|
|
787
|
+
</button>
|
|
788
|
+
{/if}
|
|
670
789
|
</div>
|
|
671
790
|
</td>
|
|
672
791
|
{/each}
|
|
@@ -674,64 +793,35 @@ onMount(() => {
|
|
|
674
793
|
</VirtualTable>
|
|
675
794
|
</Upload>
|
|
676
795
|
</div>
|
|
677
|
-
{#if editable}
|
|
678
|
-
<div class="controls-wrap">
|
|
679
|
-
{#if row_count[1] === "dynamic"}
|
|
680
|
-
<span class="button-wrap">
|
|
681
|
-
<BaseButton
|
|
682
|
-
variant="secondary"
|
|
683
|
-
size="sm"
|
|
684
|
-
on:click={(e) => (e.stopPropagation(), add_row())}
|
|
685
|
-
>
|
|
686
|
-
<svg
|
|
687
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
688
|
-
xmlns:xlink="http://www.w3.org/1999/xlink"
|
|
689
|
-
aria-hidden="true"
|
|
690
|
-
role="img"
|
|
691
|
-
width="1em"
|
|
692
|
-
height="1em"
|
|
693
|
-
preserveAspectRatio="xMidYMid meet"
|
|
694
|
-
viewBox="0 0 32 32"
|
|
695
|
-
>
|
|
696
|
-
<path
|
|
697
|
-
fill="currentColor"
|
|
698
|
-
d="M24.59 16.59L17 24.17V4h-2v20.17l-7.59-7.58L6 18l10 10l10-10l-1.41-1.41z"
|
|
699
|
-
/>
|
|
700
|
-
</svg>
|
|
701
|
-
{i18n("dataframe.new_row")}
|
|
702
|
-
</BaseButton>
|
|
703
|
-
</span>
|
|
704
|
-
{/if}
|
|
705
|
-
{#if col_count[1] === "dynamic"}
|
|
706
|
-
<span class="button-wrap">
|
|
707
|
-
<BaseButton
|
|
708
|
-
variant="secondary"
|
|
709
|
-
size="sm"
|
|
710
|
-
on:click={(e) => (e.stopPropagation(), add_col())}
|
|
711
|
-
>
|
|
712
|
-
<svg
|
|
713
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
714
|
-
xmlns:xlink="http://www.w3.org/1999/xlink"
|
|
715
|
-
aria-hidden="true"
|
|
716
|
-
role="img"
|
|
717
|
-
width="1em"
|
|
718
|
-
height="1em"
|
|
719
|
-
preserveAspectRatio="xMidYMid meet"
|
|
720
|
-
viewBox="0 0 32 32"
|
|
721
|
-
>
|
|
722
|
-
<path
|
|
723
|
-
fill="currentColor"
|
|
724
|
-
d="m18 6l-1.43 1.393L24.15 15H4v2h20.15l-7.58 7.573L18 26l10-10L18 6z"
|
|
725
|
-
/>
|
|
726
|
-
</svg>
|
|
727
|
-
{i18n("dataframe.new_column")}
|
|
728
|
-
</BaseButton>
|
|
729
|
-
</span>
|
|
730
|
-
{/if}
|
|
731
|
-
</div>
|
|
732
|
-
{/if}
|
|
733
796
|
</div>
|
|
734
797
|
|
|
798
|
+
{#if active_cell_menu !== null}
|
|
799
|
+
<CellMenu
|
|
800
|
+
{i18n}
|
|
801
|
+
x={active_cell_menu.x}
|
|
802
|
+
y={active_cell_menu.y}
|
|
803
|
+
col={active_cell_menu.col}
|
|
804
|
+
row={active_cell_menu?.row ?? -1}
|
|
805
|
+
on_add_row_above={() => add_row_at(active_cell_menu?.row ?? -1, "above")}
|
|
806
|
+
on_add_row_below={() => add_row_at(active_cell_menu?.row ?? -1, "below")}
|
|
807
|
+
on_add_column_left={() => add_col_at(active_cell_menu?.col ?? -1, "left")}
|
|
808
|
+
on_add_column_right={() => add_col_at(active_cell_menu?.col ?? -1, "right")}
|
|
809
|
+
/>
|
|
810
|
+
{/if}
|
|
811
|
+
|
|
812
|
+
{#if active_header_menu !== null}
|
|
813
|
+
<CellMenu
|
|
814
|
+
{i18n}
|
|
815
|
+
x={active_header_menu.x}
|
|
816
|
+
y={active_header_menu.y}
|
|
817
|
+
col={active_header_menu.col}
|
|
818
|
+
row={-1}
|
|
819
|
+
on_add_column_left={() => add_col_at(active_header_menu?.col ?? -1, "left")}
|
|
820
|
+
on_add_column_right={() =>
|
|
821
|
+
add_col_at(active_header_menu?.col ?? -1, "right")}
|
|
822
|
+
/>
|
|
823
|
+
{/if}
|
|
824
|
+
|
|
735
825
|
<style>
|
|
736
826
|
.button-wrap:hover svg {
|
|
737
827
|
color: var(--color-accent);
|
|
@@ -832,8 +922,9 @@ onMount(() => {
|
|
|
832
922
|
}
|
|
833
923
|
|
|
834
924
|
th.focus,
|
|
835
|
-
td.focus
|
|
836
|
-
|
|
925
|
+
td.focus,
|
|
926
|
+
td.menu-active {
|
|
927
|
+
z-index: 1;
|
|
837
928
|
}
|
|
838
929
|
|
|
839
930
|
tr:last-child td:first-child {
|
|
@@ -882,21 +973,22 @@ onMount(() => {
|
|
|
882
973
|
}
|
|
883
974
|
|
|
884
975
|
.cell-wrap {
|
|
976
|
+
position: relative;
|
|
885
977
|
display: flex;
|
|
886
978
|
align-items: center;
|
|
979
|
+
justify-content: space-between;
|
|
887
980
|
outline: none;
|
|
888
981
|
height: var(--size-full);
|
|
889
982
|
min-height: var(--size-9);
|
|
983
|
+
overflow: hidden;
|
|
890
984
|
}
|
|
891
985
|
|
|
892
|
-
.
|
|
986
|
+
.header-content {
|
|
893
987
|
display: flex;
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
.controls-wrap > * + * {
|
|
899
|
-
margin-left: var(--size-1);
|
|
988
|
+
align-items: center;
|
|
989
|
+
overflow: hidden;
|
|
990
|
+
flex-grow: 1;
|
|
991
|
+
min-width: 0;
|
|
900
992
|
}
|
|
901
993
|
|
|
902
994
|
.row_odd {
|
|
@@ -910,4 +1002,45 @@ onMount(() => {
|
|
|
910
1002
|
table {
|
|
911
1003
|
border-collapse: separate;
|
|
912
1004
|
}
|
|
1005
|
+
|
|
1006
|
+
.select-column {
|
|
1007
|
+
width: var(--size-3);
|
|
1008
|
+
text-align: center;
|
|
1009
|
+
padding: var(--size-1);
|
|
1010
|
+
border-right: none;
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
.cell-menu-button {
|
|
1014
|
+
flex-shrink: 0;
|
|
1015
|
+
display: none;
|
|
1016
|
+
background-color: var(--block-background-fill);
|
|
1017
|
+
border: 1px solid var(--border-color-primary);
|
|
1018
|
+
border-radius: var(--block-radius);
|
|
1019
|
+
width: var(--size-5);
|
|
1020
|
+
height: var(--size-5);
|
|
1021
|
+
min-width: var(--size-5);
|
|
1022
|
+
padding: 0;
|
|
1023
|
+
margin-right: var(--spacing-sm);
|
|
1024
|
+
z-index: var(--layer-2);
|
|
1025
|
+
}
|
|
1026
|
+
|
|
1027
|
+
.cell-menu-button:hover {
|
|
1028
|
+
background-color: var(--color-bg-hover);
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
.cell-menu-button.visible {
|
|
1032
|
+
display: flex;
|
|
1033
|
+
align-items: center;
|
|
1034
|
+
justify-content: center;
|
|
1035
|
+
}
|
|
1036
|
+
|
|
1037
|
+
th .cell-wrap {
|
|
1038
|
+
padding-right: var(--spacing-sm);
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
th .header-content {
|
|
1042
|
+
white-space: nowrap;
|
|
1043
|
+
overflow: hidden;
|
|
1044
|
+
text-overflow: ellipsis;
|
|
1045
|
+
}
|
|
913
1046
|
</style>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gradio/dataframe",
|
|
3
|
-
"version": "0.11.0
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"description": "Gradio UI packages",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "",
|
|
@@ -17,13 +17,13 @@
|
|
|
17
17
|
"dompurify": "^3.0.3",
|
|
18
18
|
"katex": "^0.16.7",
|
|
19
19
|
"marked": "^12.0.0",
|
|
20
|
-
"@gradio/atoms": "^0.9.0
|
|
21
|
-
"@gradio/
|
|
22
|
-
"@gradio/
|
|
23
|
-
"@gradio/
|
|
24
|
-
"@gradio/
|
|
25
|
-
"@gradio/
|
|
26
|
-
"@gradio/client": "^1.6.0
|
|
20
|
+
"@gradio/atoms": "^0.9.0",
|
|
21
|
+
"@gradio/markdown": "^0.10.0",
|
|
22
|
+
"@gradio/button": "^0.3.0",
|
|
23
|
+
"@gradio/statustracker": "^0.8.0",
|
|
24
|
+
"@gradio/upload": "^0.13.0",
|
|
25
|
+
"@gradio/utils": "^0.7.0",
|
|
26
|
+
"@gradio/client": "^1.6.0"
|
|
27
27
|
},
|
|
28
28
|
"exports": {
|
|
29
29
|
".": {
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"svelte": "^4.0.0"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
|
-
"@gradio/preview": "^0.
|
|
45
|
+
"@gradio/preview": "^0.12.0"
|
|
46
46
|
},
|
|
47
47
|
"repository": {
|
|
48
48
|
"type": "git",
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { onMount } from "svelte";
|
|
3
|
+
import Arrow from "./Arrow.svelte";
|
|
4
|
+
import type { I18nFormatter } from "js/utils/src";
|
|
5
|
+
|
|
6
|
+
export let x: number;
|
|
7
|
+
export let y: number;
|
|
8
|
+
export let on_add_row_above: () => void;
|
|
9
|
+
export let on_add_row_below: () => void;
|
|
10
|
+
export let on_add_column_left: () => void;
|
|
11
|
+
export let on_add_column_right: () => void;
|
|
12
|
+
export let row: number;
|
|
13
|
+
|
|
14
|
+
export let i18n: I18nFormatter;
|
|
15
|
+
let menu_element: HTMLDivElement;
|
|
16
|
+
|
|
17
|
+
$: is_header = row === -1;
|
|
18
|
+
|
|
19
|
+
onMount(() => {
|
|
20
|
+
position_menu();
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
function position_menu(): void {
|
|
24
|
+
if (!menu_element) return;
|
|
25
|
+
|
|
26
|
+
const viewport_width = window.innerWidth;
|
|
27
|
+
const viewport_height = window.innerHeight;
|
|
28
|
+
const menu_rect = menu_element.getBoundingClientRect();
|
|
29
|
+
|
|
30
|
+
let new_x = x - 30;
|
|
31
|
+
let new_y = y - 20;
|
|
32
|
+
|
|
33
|
+
if (new_x + menu_rect.width > viewport_width) {
|
|
34
|
+
new_x = x - menu_rect.width + 10;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (new_y + menu_rect.height > viewport_height) {
|
|
38
|
+
new_y = y - menu_rect.height + 10;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
menu_element.style.left = `${new_x}px`;
|
|
42
|
+
menu_element.style.top = `${new_y}px`;
|
|
43
|
+
}
|
|
44
|
+
</script>
|
|
45
|
+
|
|
46
|
+
<div bind:this={menu_element} class="cell-menu">
|
|
47
|
+
{#if !is_header}
|
|
48
|
+
<button on:click={() => on_add_row_above()}>
|
|
49
|
+
<Arrow transform="rotate(-90 12 12)" />
|
|
50
|
+
{i18n("dataframe.add_row_above")}
|
|
51
|
+
</button>
|
|
52
|
+
<button on:click={() => on_add_row_below()}>
|
|
53
|
+
<Arrow transform="rotate(90 12 12)" />
|
|
54
|
+
{i18n("dataframe.add_row_below")}
|
|
55
|
+
</button>
|
|
56
|
+
{/if}
|
|
57
|
+
<button on:click={() => on_add_column_left()}>
|
|
58
|
+
<Arrow transform="rotate(180 12 12)" />
|
|
59
|
+
{i18n("dataframe.add_column_left")}
|
|
60
|
+
</button>
|
|
61
|
+
<button on:click={() => on_add_column_right()}>
|
|
62
|
+
<Arrow transform="rotate(0 12 12)" />
|
|
63
|
+
{i18n("dataframe.add_column_right")}
|
|
64
|
+
</button>
|
|
65
|
+
</div>
|
|
66
|
+
|
|
67
|
+
<style>
|
|
68
|
+
.cell-menu {
|
|
69
|
+
position: fixed;
|
|
70
|
+
z-index: var(--layer-2);
|
|
71
|
+
background: var(--background-fill-primary);
|
|
72
|
+
border: 1px solid var(--border-color-primary);
|
|
73
|
+
border-radius: var(--radius-sm);
|
|
74
|
+
padding: var(--size-1);
|
|
75
|
+
display: flex;
|
|
76
|
+
flex-direction: column;
|
|
77
|
+
gap: var(--size-1);
|
|
78
|
+
box-shadow: var(--shadow-drop-lg);
|
|
79
|
+
min-width: 150px;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.cell-menu button {
|
|
83
|
+
background: none;
|
|
84
|
+
border: none;
|
|
85
|
+
cursor: pointer;
|
|
86
|
+
text-align: left;
|
|
87
|
+
padding: var(--size-1) var(--size-2);
|
|
88
|
+
border-radius: var(--radius-sm);
|
|
89
|
+
color: var(--body-text-color);
|
|
90
|
+
font-size: var(--text-sm);
|
|
91
|
+
transition:
|
|
92
|
+
background-color 0.2s,
|
|
93
|
+
color 0.2s;
|
|
94
|
+
display: flex;
|
|
95
|
+
align-items: center;
|
|
96
|
+
gap: var(--size-2);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.cell-menu button:hover {
|
|
100
|
+
background-color: var(--background-fill-secondary);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.cell-menu button :global(svg) {
|
|
104
|
+
fill: currentColor;
|
|
105
|
+
transition: fill 0.2s;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.cell-menu button:hover :global(svg) {
|
|
109
|
+
fill: var(--color-accent);
|
|
110
|
+
}
|
|
111
|
+
</style>
|