@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.
Files changed (87) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/Dataframe.stories.svelte +202 -9
  3. package/Index.svelte +7 -13
  4. package/dist/Index.svelte +5 -9
  5. package/dist/Index.svelte.d.ts +9 -2
  6. package/dist/shared/CellMenu.svelte +91 -10
  7. package/dist/shared/CellMenu.svelte.d.ts +6 -0
  8. package/dist/shared/CellMenuButton.svelte +45 -0
  9. package/dist/shared/CellMenuButton.svelte.d.ts +16 -0
  10. package/dist/shared/CellMenuIcons.svelte +79 -0
  11. package/dist/shared/EditableCell.svelte +83 -14
  12. package/dist/shared/EditableCell.svelte.d.ts +12 -3
  13. package/dist/shared/EmptyRowButton.svelte +28 -0
  14. package/dist/shared/EmptyRowButton.svelte.d.ts +16 -0
  15. package/dist/shared/RowNumber.svelte +40 -0
  16. package/dist/shared/RowNumber.svelte.d.ts +17 -0
  17. package/dist/shared/Table.svelte +564 -1121
  18. package/dist/shared/Table.svelte.d.ts +4 -0
  19. package/dist/shared/TableCell.svelte +291 -0
  20. package/dist/shared/TableCell.svelte.d.ts +57 -0
  21. package/dist/shared/TableHeader.svelte +239 -0
  22. package/dist/shared/TableHeader.svelte.d.ts +45 -0
  23. package/dist/shared/Toolbar.svelte +18 -8
  24. package/dist/shared/VirtualTable.svelte +66 -19
  25. package/dist/shared/VirtualTable.svelte.d.ts +4 -0
  26. package/dist/shared/context/keyboard_context.d.ts +37 -0
  27. package/dist/shared/context/keyboard_context.js +12 -0
  28. package/dist/shared/context/selection_context.d.ts +32 -0
  29. package/dist/shared/context/selection_context.js +107 -0
  30. package/dist/shared/context/table_context.d.ts +141 -0
  31. package/dist/shared/context/table_context.js +375 -0
  32. package/dist/shared/icons/Padlock.svelte +24 -0
  33. package/dist/shared/icons/Padlock.svelte.d.ts +23 -0
  34. package/dist/shared/icons/SelectionButtons.svelte +85 -0
  35. package/dist/shared/icons/SelectionButtons.svelte.d.ts +18 -0
  36. package/dist/shared/icons/SortArrowDown.svelte +24 -0
  37. package/dist/shared/icons/SortArrowDown.svelte.d.ts +16 -0
  38. package/dist/shared/icons/SortArrowUp.svelte +24 -0
  39. package/dist/shared/icons/SortArrowUp.svelte.d.ts +16 -0
  40. package/dist/shared/icons/SortButtonDown.svelte +14 -0
  41. package/dist/shared/icons/SortButtonDown.svelte.d.ts +23 -0
  42. package/dist/shared/icons/SortButtonUp.svelte +15 -0
  43. package/dist/shared/icons/SortButtonUp.svelte.d.ts +23 -0
  44. package/dist/shared/icons/SortIcon.svelte +46 -68
  45. package/dist/shared/icons/SortIcon.svelte.d.ts +3 -2
  46. package/dist/shared/selection_utils.d.ts +2 -1
  47. package/dist/shared/selection_utils.js +39 -10
  48. package/dist/shared/utils/data_processing.d.ts +13 -0
  49. package/dist/shared/utils/data_processing.js +45 -0
  50. package/dist/shared/utils/drag_utils.d.ts +15 -0
  51. package/dist/shared/utils/drag_utils.js +57 -0
  52. package/dist/shared/utils/keyboard_utils.d.ts +2 -0
  53. package/dist/shared/utils/keyboard_utils.js +186 -0
  54. package/dist/shared/utils/sort_utils.d.ts +22 -3
  55. package/dist/shared/utils/sort_utils.js +44 -24
  56. package/dist/shared/utils/table_utils.d.ts +6 -5
  57. package/dist/shared/utils/table_utils.js +13 -56
  58. package/package.json +7 -7
  59. package/shared/CellMenu.svelte +90 -10
  60. package/shared/CellMenuButton.svelte +46 -0
  61. package/shared/CellMenuIcons.svelte +79 -0
  62. package/shared/EditableCell.svelte +97 -18
  63. package/shared/EmptyRowButton.svelte +29 -0
  64. package/shared/RowNumber.svelte +41 -0
  65. package/shared/Table.svelte +604 -1235
  66. package/shared/TableCell.svelte +324 -0
  67. package/shared/TableHeader.svelte +256 -0
  68. package/shared/Toolbar.svelte +19 -8
  69. package/shared/VirtualTable.svelte +72 -19
  70. package/shared/context/keyboard_context.ts +65 -0
  71. package/shared/context/selection_context.ts +168 -0
  72. package/shared/context/table_context.ts +625 -0
  73. package/shared/icons/Padlock.svelte +24 -0
  74. package/shared/icons/SelectionButtons.svelte +93 -0
  75. package/shared/icons/SortArrowDown.svelte +25 -0
  76. package/shared/icons/SortArrowUp.svelte +25 -0
  77. package/shared/icons/SortButtonDown.svelte +14 -0
  78. package/shared/icons/SortButtonUp.svelte +15 -0
  79. package/shared/icons/SortIcon.svelte +47 -70
  80. package/shared/selection_utils.ts +39 -13
  81. package/shared/utils/data_processing.ts +72 -0
  82. package/shared/utils/drag_utils.ts +92 -0
  83. package/shared/utils/keyboard_utils.ts +238 -0
  84. package/shared/utils/sort_utils.test.ts +262 -14
  85. package/shared/utils/sort_utils.ts +67 -31
  86. package/shared/utils/table_utils.test.ts +66 -45
  87. package/shared/utils/table_utils.ts +16 -86
package/CHANGELOG.md CHANGED
@@ -1,5 +1,39 @@
1
1
  # @gradio/dataframe
2
2
 
3
+ ## 0.17.1
4
+
5
+ ### Fixes
6
+
7
+ - [#10819](https://github.com/gradio-app/gradio/pull/10819) [`ac075ad`](https://github.com/gradio-app/gradio/commit/ac075ad6aaea855bfd4839cef7140719a584498e) - Fix cell menu not showing in non-editable dataframes. Thanks @hannahblair!
8
+
9
+ ## 0.17.0
10
+
11
+ ### Features
12
+
13
+ - [#10784](https://github.com/gradio-app/gradio/pull/10784) [`6812544`](https://github.com/gradio-app/gradio/commit/681254453a15dadde068feaec176bb984710292b) - On Windows OS, hide `gr.Dataframe` scrollbars while keeping scrolling functionality. Thanks @abidlabs!
14
+ - [#10802](https://github.com/gradio-app/gradio/pull/10802) [`9ec8898`](https://github.com/gradio-app/gradio/commit/9ec8898c0f5753fb548a89f9804b71b69797d00c) - Fix excess scroll bug in dataframe. Thanks @hannahblair!
15
+ - [#10805](https://github.com/gradio-app/gradio/pull/10805) [`8d03368`](https://github.com/gradio-app/gradio/commit/8d03368243b6365d279563cf38a18b67a0efaf69) - Fix max characters in non-editable dataframes. Thanks @hannahblair!
16
+ - [#10787](https://github.com/gradio-app/gradio/pull/10787) [`b3e8c26`](https://github.com/gradio-app/gradio/commit/b3e8c263be51f9553e9f19939be0f880092b44c9) - Implement cell selection via drag in dataframe. Thanks @hannahblair!
17
+ - [#10734](https://github.com/gradio-app/gradio/pull/10734) [`c44b8f4`](https://github.com/gradio-app/gradio/commit/c44b8f47b927258552af61c3af06f2e30449f571) - Add `static_columns` param for interactive dataframes. Thanks @hannahblair!
18
+ - [#10778](https://github.com/gradio-app/gradio/pull/10778) [`373007b`](https://github.com/gradio-app/gradio/commit/373007b3e9d019ee41589d1dbb09a7511a024a51) - Allow sorting by multiple columns in dataframe. Thanks @hannahblair!
19
+ - [#10804](https://github.com/gradio-app/gradio/pull/10804) [`39c30be`](https://github.com/gradio-app/gradio/commit/39c30be1628028a86400c1e4b993db51e91b2580) - Add parent focus for drag selection. Thanks @hannahblair!
20
+ - [#10777](https://github.com/gradio-app/gradio/pull/10777) [`3b48367`](https://github.com/gradio-app/gradio/commit/3b483672f4778f5b19d2f529328c1f71b3742f45) - Allow navigating down from header cells, as well as support cmd/ctrl + arrow keys. Thanks @abidlabs!
21
+ - [#10776](https://github.com/gradio-app/gradio/pull/10776) [`85f6132`](https://github.com/gradio-app/gradio/commit/85f6132f1f9f653329edfa22f627e342e8b42731) - Fix cell selection when using shift + arrow keys. Thanks @abidlabs!
22
+
23
+ ### Fixes
24
+
25
+ - [#10757](https://github.com/gradio-app/gradio/pull/10757) [`b4342d2`](https://github.com/gradio-app/gradio/commit/b4342d24a88acaa4ed4028c8fdd44eea0d1b8b57) - Fix dataframe search and filter functionality. Thanks @hannahblair!
26
+ - [#10786](https://github.com/gradio-app/gradio/pull/10786) [`88941b6`](https://github.com/gradio-app/gradio/commit/88941b655e708ab14611341ed3fe57452fbbfc58) - Remove fixed layouts from dataframe. Thanks @hannahblair!
27
+ - [#10631](https://github.com/gradio-app/gradio/pull/10631) [`b5ca1dc`](https://github.com/gradio-app/gradio/commit/b5ca1dcfdf496292eade31347ae1974d3a0976c4) - Refactor `gr.Dataframe`. Thanks @hannahblair!
28
+
29
+ ### Dependency updates
30
+
31
+ - @gradio/upload@0.15.5
32
+ - @gradio/statustracker@0.10.5
33
+ - @gradio/button@0.4.10
34
+ - @gradio/atoms@0.14.0
35
+ - @gradio/markdown-code@0.4.1
36
+
3
37
  ## 0.16.5
4
38
 
5
39
  ### Dependency updates
@@ -6,6 +6,7 @@
6
6
  import { userEvent } from "@storybook/test";
7
7
  import { get } from "svelte/store";
8
8
  import { format } from "svelte-i18n";
9
+ import Image from "@gradio/image";
9
10
  </script>
10
11
 
11
12
  <Meta
@@ -219,6 +220,18 @@
219
220
  }}
220
221
  />
221
222
 
223
+ <Story
224
+ name="Interactive dataframe with zero row count"
225
+ args={{
226
+ values: [],
227
+ headers: ["Narrow", "Wide", "Half"],
228
+ label: "Test scores",
229
+ col_count: [0, "dynamic"],
230
+ row_count: [0, "dynamic"],
231
+ editable: true
232
+ }}
233
+ />
234
+
222
235
  <Story
223
236
  name="Dataframe with link"
224
237
  args={{
@@ -249,9 +262,8 @@
249
262
  const cell_400 = canvas.getAllByRole("cell")[5];
250
263
  await userEvent.click(cell_400);
251
264
 
252
- const open_dialog_btn = await within(cell_400).findByRole("button", {
253
- name: ""
254
- });
265
+ const open_dialog_btn =
266
+ await within(cell_400).findByLabelText("Open cell menu");
255
267
  await userEvent.click(open_dialog_btn);
256
268
 
257
269
  const add_row_btn = canvas.getByText("Add row above");
@@ -417,6 +429,31 @@
417
429
  }}
418
430
  />
419
431
 
432
+ <Story
433
+ name="Dataframe with custom components"
434
+ args={{
435
+ values: [
436
+ [
437
+ "Absol G",
438
+ 70,
439
+ "https://images.pokemontcg.io/pl3/1_hires.png",
440
+ "pl3-1",
441
+ "Supreme Victors"
442
+ ]
443
+ ],
444
+ datatype: ["str", "number", "image", "str", "str"],
445
+ headers: ["Pokemon", "HP", "Image", "ID", "Set"],
446
+ label: "Pokemon Cards",
447
+ col_count: [5, "fixed"],
448
+ row_count: [1, "dynamic"],
449
+ interactive: true,
450
+ editable: true,
451
+ components: {
452
+ image: Image
453
+ }
454
+ }}
455
+ />
456
+
420
457
  <Story
421
458
  name="Dataframe with row and column selection"
422
459
  args={{
@@ -441,16 +478,16 @@
441
478
  const cells = canvas.getAllByRole("cell");
442
479
  await user.click(cells[5]); // Click cell with value 6
443
480
 
444
- const row_button = await canvas.findByRole("button", {
481
+ const row_button = await canvas.findAllByRole("button", {
445
482
  name: "Select row"
446
- });
483
+ })[0];
447
484
  await user.click(row_button);
448
485
 
449
486
  await user.click(cells[6]);
450
487
 
451
- const col_button = await canvas.findByRole("button", {
488
+ const col_button = await canvas.findAllByRole("button", {
452
489
  name: "Select column"
453
- });
490
+ })[0];
454
491
  await user.click(col_button);
455
492
 
456
493
  await user.keyboard("{Delete}");
@@ -513,7 +550,7 @@
513
550
  const canvas = within(canvasElement);
514
551
  const user = userEvent.setup();
515
552
 
516
- const search_input = canvas.getByPlaceholderText("Search...");
553
+ const search_input = canvas.getByPlaceholderText("Filter...");
517
554
  await user.type(search_input, "Pet");
518
555
 
519
556
  await new Promise((resolve) => setTimeout(resolve, 100));
@@ -528,7 +565,7 @@
528
565
  />
529
566
 
530
567
  <Story
531
- name="Dataframe with frozen columns"
568
+ name="Dataframe with pinned columns"
532
569
  args={{
533
570
  values: [
534
571
  ["ID", "Name", "Age", "City", "Country", "Score"],
@@ -547,3 +584,159 @@
547
584
  editable: false
548
585
  }}
549
586
  />
587
+
588
+ <Story
589
+ name="Dataframe with pixel and percentage column widths set"
590
+ args={{
591
+ values: [
592
+ [1, 2, 3, 4, 5],
593
+ [6, 7, 8, 9, 10]
594
+ ],
595
+ headers: ["10%", "50%", "40%", "100px", "100px"],
596
+ col_count: [5, "dynamic"],
597
+ row_count: [2, "dynamic"],
598
+ column_widths: ["10%", "50%", "40%", "100px", "100px"]
599
+ }}
600
+ />
601
+
602
+ <Story
603
+ name="Dataframe with drag selection"
604
+ args={{
605
+ values: [
606
+ [1, 2, 3, 4, 5],
607
+ [6, 7, 8, 9, 10],
608
+ [11, 12, 13, 14, 15],
609
+ [16, 17, 18, 19, 20],
610
+ [21, 22, 23, 24, 25]
611
+ ],
612
+ headers: ["A", "B", "C", "D", "E"],
613
+ label: "Drag Selection Demo",
614
+ col_count: [5, "dynamic"],
615
+ row_count: [5, "dynamic"],
616
+ editable: true
617
+ }}
618
+ play={async ({ canvasElement }) => {
619
+ const canvas = within(canvasElement);
620
+ const user = userEvent.setup();
621
+
622
+ await new Promise((resolve) => setTimeout(resolve, 300));
623
+
624
+ const table = canvas.getByRole("grid");
625
+ const cells = canvas.getAllByRole("cell");
626
+ const startCell = cells[6];
627
+ const startRect = startCell.getBoundingClientRect();
628
+ const startX = startRect.left + startRect.width / 2;
629
+ const startY = startRect.top + startRect.height / 2;
630
+
631
+ const endCell = cells[18];
632
+ const endRect = endCell.getBoundingClientRect();
633
+ const endX = endRect.left + endRect.width / 2;
634
+ const endY = endRect.top + endRect.height / 2;
635
+
636
+ await user.pointer({
637
+ keys: "[MouseLeft>]",
638
+ target: startCell,
639
+ coords: { clientX: startX, clientY: startY }
640
+ });
641
+
642
+ await new Promise((resolve) => setTimeout(resolve, 50));
643
+
644
+ const midX1 = startX + (endX - startX) / 3;
645
+ const midY1 = startY + (endY - startY) / 3;
646
+ await user.pointer({
647
+ target: table,
648
+ coords: { clientX: midX1, clientY: midY1 }
649
+ });
650
+
651
+ await new Promise((resolve) => setTimeout(resolve, 50));
652
+
653
+ const midX2 = startX + ((endX - startX) * 2) / 3;
654
+ const midY2 = startY + ((endY - startY) * 2) / 3;
655
+ await user.pointer({
656
+ target: table,
657
+ coords: { clientX: midX2, clientY: midY2 }
658
+ });
659
+
660
+ await new Promise((resolve) => setTimeout(resolve, 50));
661
+
662
+ await user.pointer({
663
+ target: endCell,
664
+ coords: { clientX: endX, clientY: endY }
665
+ });
666
+
667
+ await new Promise((resolve) => setTimeout(resolve, 50));
668
+
669
+ await user.pointer({
670
+ keys: "[/MouseLeft]"
671
+ });
672
+
673
+ await new Promise((resolve) => setTimeout(resolve, 500));
674
+ }}
675
+ />
676
+
677
+ <Story
678
+ name="Non-interactive dataframe with sorting by multiple columns"
679
+ args={{
680
+ values: [
681
+ [1, 2, 3],
682
+ [4, 5, 6],
683
+ [7, 8, 9]
684
+ ],
685
+ headers: ["A", "B", "C"],
686
+ col_count: [3, "dynamic"],
687
+ row_count: [3, "dynamic"],
688
+ editable: false,
689
+ sort_columns: [
690
+ { col: 0, direction: "asc" },
691
+ { col: 1, direction: "desc" }
692
+ ],
693
+ sort_state: {
694
+ sort_columns: [
695
+ { col: 0, direction: "asc" },
696
+ { col: 1, direction: "desc" }
697
+ ],
698
+ row_order: [0, 1, 2]
699
+ }
700
+ }}
701
+ play={async ({ canvasElement }) => {
702
+ const canvas = within(canvasElement);
703
+ const user = userEvent.setup();
704
+
705
+ const header_1 = canvas.getAllByText("A")[1];
706
+ await userEvent.click(header_1);
707
+
708
+ const cell_menu_button = canvas.getAllByLabelText("Open cell menu")[0];
709
+ await userEvent.click(cell_menu_button);
710
+
711
+ const sort_ascending_button = canvas.getByRole("menuitem", {
712
+ name: "Sort ascending"
713
+ });
714
+ await userEvent.click(sort_ascending_button);
715
+
716
+ const header_2 = canvas.getAllByText("B")[1];
717
+ await userEvent.click(header_2);
718
+
719
+ const cell_menu_button_2 = canvas.getAllByLabelText("Open cell menu")[1];
720
+ await userEvent.click(cell_menu_button_2);
721
+
722
+ const sort_descending_button = canvas.getByRole("menuitem", {
723
+ name: "Sort descending"
724
+ });
725
+ await userEvent.click(sort_descending_button);
726
+
727
+ const header_3 = canvas.getAllByText("C")[1];
728
+ await userEvent.click(header_3);
729
+
730
+ const cell_menu_button_3 = canvas.getAllByLabelText("Open cell menu")[2];
731
+ await userEvent.click(cell_menu_button_3);
732
+
733
+ const sort_ascending_button_3 = canvas.getByRole("menuitem", {
734
+ name: "Sort ascending"
735
+ });
736
+ await userEvent.click(sort_ascending_button_3);
737
+
738
+ await userEvent.click(header_3);
739
+ await userEvent.click(cell_menu_button_3);
740
+ await userEvent.click(canvas.getByText("Clear sort"));
741
+ }}
742
+ />
package/Index.svelte CHANGED
@@ -12,6 +12,8 @@
12
12
  import { StatusTracker } from "@gradio/statustracker";
13
13
  import type { LoadingStatus } from "@gradio/statustracker";
14
14
  import type { Headers, Datatype, DataframeValue } from "./shared/utils";
15
+ import Image from "@gradio/image";
16
+
15
17
  export let headers: Headers = [];
16
18
  export let elem_id = "";
17
19
  export let elem_classes: string[] = [];
@@ -39,6 +41,7 @@
39
41
  select: SelectData;
40
42
  input: never;
41
43
  clear_status: LoadingStatus;
44
+ search: string | null;
42
45
  }>;
43
46
  export let latex_delimiters: {
44
47
  left: string;
@@ -53,18 +56,8 @@
53
56
  export let show_copy_button = false;
54
57
  export let show_row_numbers = false;
55
58
  export let show_search: "none" | "search" | "filter" = "none";
56
-
57
- let search_query: string | null = null;
58
- $: filtered_cell_values = search_query
59
- ? value.data?.filter((row) =>
60
- row.some(
61
- (cell) =>
62
- search_query &&
63
- String(cell).toLowerCase().includes(search_query.toLowerCase())
64
- )
65
- )
66
- : null;
67
59
  export let pinned_columns = 0;
60
+ export let static_columns: (string | number)[] = [];
68
61
 
69
62
  $: _headers = [...(value.headers || headers)];
70
63
  $: display_value = value?.metadata?.display_value
@@ -98,7 +91,7 @@
98
91
  {show_label}
99
92
  {row_count}
100
93
  {col_count}
101
- values={filtered_cell_values || value.data}
94
+ values={value.data}
102
95
  {display_value}
103
96
  {styling}
104
97
  headers={_headers}
@@ -109,7 +102,6 @@
109
102
  }}
110
103
  on:input={(e) => gradio.dispatch("input")}
111
104
  on:select={(e) => gradio.dispatch("select", e.detail)}
112
- on:search={(e) => (search_query = e.detail)}
113
105
  {wrap}
114
106
  {datatype}
115
107
  {latex_delimiters}
@@ -127,5 +119,7 @@
127
119
  {show_row_numbers}
128
120
  {show_search}
129
121
  {pinned_columns}
122
+ components={{ image: Image }}
123
+ {static_columns}
130
124
  />
131
125
  </Block>
package/dist/Index.svelte CHANGED
@@ -7,6 +7,7 @@ export { default as BaseExample } from "./Example.svelte";
7
7
  <script>import { Block } from "@gradio/atoms";
8
8
  import Table from "./shared/Table.svelte";
9
9
  import { StatusTracker } from "@gradio/statustracker";
10
+ import Image from "@gradio/image";
10
11
  export let headers = [];
11
12
  export let elem_id = "";
12
13
  export let elem_classes = [];
@@ -38,14 +39,8 @@ export let max_chars = void 0;
38
39
  export let show_copy_button = false;
39
40
  export let show_row_numbers = false;
40
41
  export let show_search = "none";
41
- let search_query = null;
42
- $:
43
- filtered_cell_values = search_query ? value.data?.filter(
44
- (row) => row.some(
45
- (cell) => search_query && String(cell).toLowerCase().includes(search_query.toLowerCase())
46
- )
47
- ) : null;
48
42
  export let pinned_columns = 0;
43
+ export let static_columns = [];
49
44
  $:
50
45
  _headers = [...value.headers || headers];
51
46
  $:
@@ -76,7 +71,7 @@ $:
76
71
  {show_label}
77
72
  {row_count}
78
73
  {col_count}
79
- values={filtered_cell_values || value.data}
74
+ values={value.data}
80
75
  {display_value}
81
76
  {styling}
82
77
  headers={_headers}
@@ -87,7 +82,6 @@ $:
87
82
  }}
88
83
  on:input={(e) => gradio.dispatch("input")}
89
84
  on:select={(e) => gradio.dispatch("select", e.detail)}
90
- on:search={(e) => (search_query = e.detail)}
91
85
  {wrap}
92
86
  {datatype}
93
87
  {latex_delimiters}
@@ -105,5 +99,7 @@ $:
105
99
  {show_row_numbers}
106
100
  {show_search}
107
101
  {pinned_columns}
102
+ components={{ image: Image }}
103
+ {static_columns}
108
104
  />
109
105
  </Block>
@@ -28,6 +28,7 @@ declare const __propDef: {
28
28
  select: SelectData;
29
29
  input: never;
30
30
  clear_status: LoadingStatus;
31
+ search: string | null;
31
32
  }>;
32
33
  latex_delimiters: {
33
34
  left: string;
@@ -43,6 +44,7 @@ declare const __propDef: {
43
44
  show_row_numbers?: boolean | undefined;
44
45
  show_search?: ("none" | "search" | "filter") | undefined;
45
46
  pinned_columns?: number | undefined;
47
+ static_columns?: (string | number)[] | undefined;
46
48
  };
47
49
  events: {
48
50
  [evt: string]: CustomEvent<any>;
@@ -109,6 +111,7 @@ export default class Index extends SvelteComponent<IndexProps, IndexEvents, Inde
109
111
  select: SelectData;
110
112
  input: never;
111
113
  clear_status: LoadingStatus;
114
+ search: string | null;
112
115
  }>;
113
116
  /**accessor*/
114
117
  set gradio(_: Gradio<{
@@ -116,6 +119,7 @@ export default class Index extends SvelteComponent<IndexProps, IndexEvents, Inde
116
119
  select: SelectData;
117
120
  input: never;
118
121
  clear_status: LoadingStatus;
122
+ search: string | null;
119
123
  }>);
120
124
  get latex_delimiters(): {
121
125
  left: string;
@@ -149,10 +153,13 @@ export default class Index extends SvelteComponent<IndexProps, IndexEvents, Inde
149
153
  get show_row_numbers(): boolean | undefined;
150
154
  /**accessor*/
151
155
  set show_row_numbers(_: boolean | undefined);
152
- get show_search(): "filter" | "none" | "search" | undefined;
156
+ get show_search(): "none" | "filter" | "search" | undefined;
153
157
  /**accessor*/
154
- set show_search(_: "filter" | "none" | "search" | undefined);
158
+ set show_search(_: "none" | "filter" | "search" | undefined);
155
159
  get pinned_columns(): number | undefined;
156
160
  /**accessor*/
157
161
  set pinned_columns(_: number | undefined);
162
+ get static_columns(): (string | number)[] | undefined;
163
+ /**accessor*/
164
+ set static_columns(_: (string | number)[] | undefined);
158
165
  }
@@ -13,14 +13,21 @@ export let on_delete_row;
13
13
  export let on_delete_col;
14
14
  export let can_delete_rows;
15
15
  export let can_delete_cols;
16
+ export let on_sort = () => {
17
+ };
18
+ export let on_clear_sort = () => {
19
+ };
20
+ export let sort_direction = null;
21
+ export let sort_priority = null;
22
+ export let editable = true;
16
23
  export let i18n;
17
24
  let menu_element;
18
25
  $:
19
26
  is_header = row === -1;
20
27
  $:
21
- can_add_rows = row_count[1] === "dynamic";
28
+ can_add_rows = editable && row_count[1] === "dynamic";
22
29
  $:
23
- can_add_columns = col_count[1] === "dynamic";
30
+ can_add_columns = editable && col_count[1] === "dynamic";
24
31
  onMount(() => {
25
32
  position_menu();
26
33
  });
@@ -43,34 +50,89 @@ function position_menu() {
43
50
  }
44
51
  </script>
45
52
 
46
- <div bind:this={menu_element} class="cell-menu">
53
+ <div bind:this={menu_element} class="cell-menu" role="menu">
54
+ {#if is_header}
55
+ <button
56
+ role="menuitem"
57
+ on:click={() => on_sort("asc")}
58
+ class:active={sort_direction === "asc"}
59
+ >
60
+ <CellMenuIcons icon="sort-asc" />
61
+ {i18n("dataframe.sort_ascending")}
62
+ {#if sort_direction === "asc" && sort_priority !== null}
63
+ <span class="priority">{sort_priority}</span>
64
+ {/if}
65
+ </button>
66
+ <button
67
+ role="menuitem"
68
+ on:click={() => on_sort("desc")}
69
+ class:active={sort_direction === "desc"}
70
+ >
71
+ <CellMenuIcons icon="sort-desc" />
72
+ {i18n("dataframe.sort_descending")}
73
+ {#if sort_direction === "desc" && sort_priority !== null}
74
+ <span class="priority">{sort_priority}</span>
75
+ {/if}
76
+ </button>
77
+ <button role="menuitem" on:click={on_clear_sort}>
78
+ <CellMenuIcons icon="clear-sort" />
79
+ {i18n("dataframe.clear_sort")}
80
+ </button>
81
+ {/if}
82
+
47
83
  {#if !is_header && can_add_rows}
48
- <button on:click={() => on_add_row_above()}>
84
+ <button
85
+ role="menuitem"
86
+ on:click={() => on_add_row_above()}
87
+ aria-label="Add row above"
88
+ >
49
89
  <CellMenuIcons icon="add-row-above" />
50
90
  {i18n("dataframe.add_row_above")}
51
91
  </button>
52
- <button on:click={() => on_add_row_below()}>
92
+ <button
93
+ role="menuitem"
94
+ on:click={() => on_add_row_below()}
95
+ aria-label="Add row below"
96
+ >
53
97
  <CellMenuIcons icon="add-row-below" />
54
98
  {i18n("dataframe.add_row_below")}
55
99
  </button>
56
100
  {#if can_delete_rows}
57
- <button on:click={on_delete_row} class="delete">
101
+ <button
102
+ role="menuitem"
103
+ on:click={on_delete_row}
104
+ class="delete"
105
+ aria-label="Delete row"
106
+ >
58
107
  <CellMenuIcons icon="delete-row" />
59
108
  {i18n("dataframe.delete_row")}
60
109
  </button>
61
110
  {/if}
62
111
  {/if}
63
112
  {#if can_add_columns}
64
- <button on:click={() => on_add_column_left()}>
113
+ <button
114
+ role="menuitem"
115
+ on:click={() => on_add_column_left()}
116
+ aria-label="Add column to the left"
117
+ >
65
118
  <CellMenuIcons icon="add-column-left" />
66
119
  {i18n("dataframe.add_column_left")}
67
120
  </button>
68
- <button on:click={() => on_add_column_right()}>
121
+ <button
122
+ role="menuitem"
123
+ on:click={() => on_add_column_right()}
124
+ aria-label="Add column to the right"
125
+ >
69
126
  <CellMenuIcons icon="add-column-right" />
70
127
  {i18n("dataframe.add_column_right")}
71
128
  </button>
72
129
  {#if can_delete_cols}
73
- <button on:click={on_delete_col} class="delete">
130
+ <button
131
+ role="menuitem"
132
+ on:click={on_delete_col}
133
+ class="delete"
134
+ aria-label="Delete column"
135
+ >
74
136
  <CellMenuIcons icon="delete-column" />
75
137
  {i18n("dataframe.delete_column")}
76
138
  </button>
@@ -81,7 +143,7 @@ function position_menu() {
81
143
  <style>
82
144
  .cell-menu {
83
145
  position: fixed;
84
- z-index: var(--layer-4);
146
+ z-index: 9;
85
147
  background: var(--background-fill-primary);
86
148
  border: 1px solid var(--border-color-primary);
87
149
  border-radius: var(--radius-sm);
@@ -91,6 +153,7 @@ function position_menu() {
91
153
  gap: var(--size-1);
92
154
  box-shadow: var(--shadow-drop-lg);
93
155
  min-width: 150px;
156
+ z-index: var(--layer-1);
94
157
  }
95
158
 
96
159
  .cell-menu button {
@@ -108,6 +171,11 @@ function position_menu() {
108
171
  display: flex;
109
172
  align-items: center;
110
173
  gap: var(--size-2);
174
+ position: relative;
175
+ }
176
+
177
+ .cell-menu button.active {
178
+ background-color: var(--background-fill-secondary);
111
179
  }
112
180
 
113
181
  .cell-menu button:hover {
@@ -118,4 +186,17 @@ function position_menu() {
118
186
  fill: currentColor;
119
187
  transition: fill 0.2s;
120
188
  }
189
+
190
+ .priority {
191
+ display: flex;
192
+ align-items: center;
193
+ justify-content: center;
194
+ margin-left: auto;
195
+ font-size: var(--size-2);
196
+ background-color: var(--button-secondary-background-fill);
197
+ color: var(--body-text-color);
198
+ border-radius: var(--radius-sm);
199
+ width: var(--size-2-5);
200
+ height: var(--size-2-5);
201
+ }
121
202
  </style>
@@ -1,5 +1,6 @@
1
1
  import { SvelteComponent } from "svelte";
2
2
  import type { I18nFormatter } from "js/utils/src";
3
+ import type { SortDirection } from "./context/table_context";
3
4
  declare const __propDef: {
4
5
  props: {
5
6
  x: number;
@@ -15,6 +16,11 @@ declare const __propDef: {
15
16
  on_delete_col: () => void;
16
17
  can_delete_rows: boolean;
17
18
  can_delete_cols: boolean;
19
+ on_sort?: ((direction: SortDirection) => void) | undefined;
20
+ on_clear_sort?: (() => void) | undefined;
21
+ sort_direction?: (SortDirection | null) | undefined;
22
+ sort_priority?: (number | null) | undefined;
23
+ editable?: boolean | undefined;
18
24
  i18n: I18nFormatter;
19
25
  };
20
26
  events: {
@@ -0,0 +1,45 @@
1
+ <script>export let on_click;
2
+ </script>
3
+
4
+ <button
5
+ aria-label="Open cell menu"
6
+ class="cell-menu-button"
7
+ aria-haspopup="menu"
8
+ on:click={on_click}
9
+ on:touchstart={(event) => {
10
+ event.preventDefault();
11
+ const touch = event.touches[0];
12
+ const mouseEvent = new MouseEvent("click", {
13
+ clientX: touch.clientX,
14
+ clientY: touch.clientY,
15
+ bubbles: true,
16
+ cancelable: true,
17
+ view: window
18
+ });
19
+ on_click(mouseEvent);
20
+ }}
21
+ >
22
+ &#8942;
23
+ </button>
24
+
25
+ <style>
26
+ .cell-menu-button {
27
+ flex-shrink: 0;
28
+ display: none;
29
+ align-items: center;
30
+ justify-content: center;
31
+ background-color: var(--block-background-fill);
32
+ border: 1px solid var(--border-color-primary);
33
+ border-radius: var(--block-radius);
34
+ width: var(--size-5);
35
+ height: var(--size-5);
36
+ min-width: var(--size-5);
37
+ padding: 0;
38
+ margin-right: var(--spacing-sm);
39
+ z-index: 2;
40
+ position: absolute;
41
+ right: var(--size-1);
42
+ top: 50%;
43
+ transform: translateY(-50%);
44
+ }
45
+ </style>