@gradio/dataframe 0.12.6 → 0.13.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 +31 -0
- package/Dataframe.stories.svelte +26 -0
- package/Dataframe.test.ts +37 -0
- package/Index.svelte +21 -71
- package/dist/Index.svelte +20 -45
- package/dist/Index.svelte.d.ts +90 -6
- package/dist/shared/EditableCell.svelte +11 -6
- package/dist/shared/EditableCell.svelte.d.ts +3 -1
- package/dist/shared/Table.svelte +176 -78
- package/dist/shared/Table.svelte.d.ts +6 -6
- package/dist/shared/Toolbar.svelte +49 -0
- package/dist/shared/Toolbar.svelte.d.ts +19 -0
- package/dist/shared/utils.d.ts +5 -0
- package/package.json +8 -7
- package/shared/EditableCell.svelte +11 -6
- package/shared/Table.svelte +194 -92
- package/shared/Toolbar.svelte +51 -0
- package/shared/utils.ts +5 -0
package/shared/Table.svelte
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import { createEventDispatcher, tick, onMount } from "svelte";
|
|
2
|
+
import { afterUpdate, createEventDispatcher, tick, onMount } from "svelte";
|
|
3
3
|
import { dsvFormat } from "d3-dsv";
|
|
4
4
|
import { dequal } from "dequal/lite";
|
|
5
|
-
import { copy } from "@gradio/utils";
|
|
6
5
|
import { Upload } from "@gradio/upload";
|
|
7
6
|
|
|
8
7
|
import EditableCell from "./EditableCell.svelte";
|
|
@@ -10,8 +9,14 @@
|
|
|
10
9
|
import type { I18nFormatter } from "js/core/src/gradio_helper";
|
|
11
10
|
import { type Client } from "@gradio/client";
|
|
12
11
|
import VirtualTable from "./VirtualTable.svelte";
|
|
13
|
-
import type {
|
|
12
|
+
import type {
|
|
13
|
+
Headers,
|
|
14
|
+
HeadersWithIDs,
|
|
15
|
+
DataframeValue,
|
|
16
|
+
Datatype
|
|
17
|
+
} from "./utils";
|
|
14
18
|
import CellMenu from "./CellMenu.svelte";
|
|
19
|
+
import Toolbar from "./Toolbar.svelte";
|
|
15
20
|
|
|
16
21
|
export let datatype: Datatype | Datatype[];
|
|
17
22
|
export let label: string | null = null;
|
|
@@ -34,20 +39,21 @@
|
|
|
34
39
|
export let max_height = 500;
|
|
35
40
|
export let line_breaks = true;
|
|
36
41
|
export let column_widths: string[] = [];
|
|
42
|
+
export let show_row_numbers = false;
|
|
37
43
|
export let upload: Client["upload"];
|
|
38
44
|
export let stream_handler: Client["stream"];
|
|
45
|
+
export let show_fullscreen_button = false;
|
|
46
|
+
export let value_is_output = false;
|
|
39
47
|
|
|
40
48
|
let selected: false | [number, number] = false;
|
|
49
|
+
let clicked_cell: { row: number; col: number } | undefined = undefined;
|
|
41
50
|
export let display_value: string[][] | null = null;
|
|
42
51
|
export let styling: string[][] | null = null;
|
|
43
52
|
let t_rect: DOMRectReadOnly;
|
|
44
53
|
|
|
45
54
|
const dispatch = createEventDispatcher<{
|
|
46
|
-
change:
|
|
47
|
-
|
|
48
|
-
headers: string[];
|
|
49
|
-
metadata: Metadata;
|
|
50
|
-
};
|
|
55
|
+
change: DataframeValue;
|
|
56
|
+
input: undefined;
|
|
51
57
|
select: SelectData;
|
|
52
58
|
}>();
|
|
53
59
|
|
|
@@ -142,38 +148,49 @@
|
|
|
142
148
|
}
|
|
143
149
|
|
|
144
150
|
let _headers = make_headers(headers);
|
|
145
|
-
let old_headers: string[]
|
|
151
|
+
let old_headers: string[] = headers;
|
|
146
152
|
|
|
147
153
|
$: {
|
|
148
154
|
if (!dequal(headers, old_headers)) {
|
|
149
|
-
|
|
155
|
+
_headers = make_headers(headers);
|
|
156
|
+
old_headers = JSON.parse(JSON.stringify(headers));
|
|
150
157
|
}
|
|
151
158
|
}
|
|
152
159
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
old_headers = headers.slice();
|
|
157
|
-
trigger_change();
|
|
158
|
-
}
|
|
160
|
+
let data: { id: string; value: string | number }[][] = [[]];
|
|
161
|
+
let old_val: undefined | (string | number)[][] = undefined;
|
|
159
162
|
|
|
160
163
|
$: if (!dequal(values, old_val)) {
|
|
161
164
|
data = process_data(values as (string | number)[][]);
|
|
162
|
-
old_val = values as (string | number)[][];
|
|
165
|
+
old_val = JSON.parse(JSON.stringify(values)) as (string | number)[][];
|
|
163
166
|
}
|
|
164
167
|
|
|
165
|
-
let
|
|
166
|
-
|
|
167
|
-
let old_val: undefined | (string | number)[][] = undefined;
|
|
168
|
+
let previous_headers = _headers.map((h) => h.value);
|
|
169
|
+
let previous_data = data.map((row) => row.map((cell) => String(cell.value)));
|
|
168
170
|
|
|
169
171
|
async function trigger_change(): Promise<void> {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
172
|
+
const current_headers = _headers.map((h) => h.value);
|
|
173
|
+
const current_data = data.map((row) =>
|
|
174
|
+
row.map((cell) => String(cell.value))
|
|
175
|
+
);
|
|
176
|
+
|
|
177
|
+
if (
|
|
178
|
+
!dequal(current_data, previous_data) ||
|
|
179
|
+
!dequal(current_headers, previous_headers)
|
|
180
|
+
) {
|
|
181
|
+
// We dispatch the value as part of the change event to ensure that the value is updated
|
|
182
|
+
// in the parent component and the updated value is passed into the user's function
|
|
183
|
+
dispatch("change", {
|
|
184
|
+
data: data.map((row) => row.map((cell) => cell.value)),
|
|
185
|
+
headers: _headers.map((h) => h.value),
|
|
186
|
+
metadata: null
|
|
187
|
+
});
|
|
188
|
+
if (!value_is_output) {
|
|
189
|
+
dispatch("input");
|
|
190
|
+
}
|
|
191
|
+
previous_data = current_data;
|
|
192
|
+
previous_headers = current_headers;
|
|
193
|
+
}
|
|
177
194
|
}
|
|
178
195
|
|
|
179
196
|
function get_sort_status(
|
|
@@ -204,12 +221,6 @@
|
|
|
204
221
|
);
|
|
205
222
|
}
|
|
206
223
|
|
|
207
|
-
async function start_edit(i: number, j: number): Promise<void> {
|
|
208
|
-
if (!editable || dequal(editing, [i, j])) return;
|
|
209
|
-
|
|
210
|
-
editing = [i, j];
|
|
211
|
-
}
|
|
212
|
-
|
|
213
224
|
function move_cursor(
|
|
214
225
|
key: "ArrowRight" | "ArrowLeft" | "ArrowDown" | "ArrowUp",
|
|
215
226
|
current_coords: [number, number]
|
|
@@ -349,25 +360,6 @@
|
|
|
349
360
|
}
|
|
350
361
|
}
|
|
351
362
|
|
|
352
|
-
let active_cell: { row: number; col: number } | null = null;
|
|
353
|
-
|
|
354
|
-
async function handle_cell_click(i: number, j: number): Promise<void> {
|
|
355
|
-
if (active_cell && active_cell.row === i && active_cell.col === j) {
|
|
356
|
-
active_cell = null;
|
|
357
|
-
} else {
|
|
358
|
-
active_cell = { row: i, col: j };
|
|
359
|
-
}
|
|
360
|
-
if (dequal(editing, [i, j])) return;
|
|
361
|
-
header_edit = false;
|
|
362
|
-
selected_header = false;
|
|
363
|
-
editing = false;
|
|
364
|
-
if (!dequal(selected, [i, j])) {
|
|
365
|
-
selected = [i, j];
|
|
366
|
-
await tick();
|
|
367
|
-
parent.focus();
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
|
|
371
363
|
type SortDirection = "asc" | "des";
|
|
372
364
|
let sort_direction: SortDirection | undefined;
|
|
373
365
|
let sort_by: number | undefined;
|
|
@@ -440,7 +432,7 @@
|
|
|
440
432
|
selected = [index !== undefined ? index : data.length - 1, 0];
|
|
441
433
|
}
|
|
442
434
|
|
|
443
|
-
$: (data ||
|
|
435
|
+
$: (data || _headers) && trigger_change();
|
|
444
436
|
|
|
445
437
|
async function add_col(index?: number): Promise<void> {
|
|
446
438
|
parent.focus();
|
|
@@ -479,17 +471,16 @@
|
|
|
479
471
|
active_header_menu = null;
|
|
480
472
|
}
|
|
481
473
|
|
|
482
|
-
event.stopImmediatePropagation();
|
|
483
474
|
const [trigger] = event.composedPath() as HTMLElement[];
|
|
484
475
|
if (parent.contains(trigger)) {
|
|
485
476
|
return;
|
|
486
477
|
}
|
|
487
478
|
|
|
479
|
+
clicked_cell = undefined;
|
|
488
480
|
editing = false;
|
|
481
|
+
selected = false;
|
|
489
482
|
header_edit = false;
|
|
490
483
|
selected_header = false;
|
|
491
|
-
reset_selection();
|
|
492
|
-
active_cell = null;
|
|
493
484
|
active_cell_menu = null;
|
|
494
485
|
active_header_menu = null;
|
|
495
486
|
}
|
|
@@ -560,6 +551,7 @@
|
|
|
560
551
|
function get_max(
|
|
561
552
|
_d: { value: any; id: string }[][]
|
|
562
553
|
): { value: any; id: string }[] {
|
|
554
|
+
if (!_d || _d.length === 0 || !_d[0]) return [];
|
|
563
555
|
let max = _d[0].slice();
|
|
564
556
|
for (let i = 0; i < _d.length; i++) {
|
|
565
557
|
for (let j = 0; j < _d[i].length; j++) {
|
|
@@ -665,8 +657,18 @@
|
|
|
665
657
|
|
|
666
658
|
observer.observe(parent);
|
|
667
659
|
|
|
660
|
+
document.addEventListener("click", handle_click_outside);
|
|
661
|
+
window.addEventListener("resize", handle_resize);
|
|
662
|
+
document.addEventListener("fullscreenchange", handle_fullscreen_change);
|
|
663
|
+
|
|
668
664
|
return () => {
|
|
669
665
|
observer.disconnect();
|
|
666
|
+
document.removeEventListener("click", handle_click_outside);
|
|
667
|
+
window.removeEventListener("resize", handle_resize);
|
|
668
|
+
document.removeEventListener(
|
|
669
|
+
"fullscreenchange",
|
|
670
|
+
handle_fullscreen_change
|
|
671
|
+
);
|
|
670
672
|
};
|
|
671
673
|
});
|
|
672
674
|
|
|
@@ -721,15 +723,6 @@
|
|
|
721
723
|
set_cell_widths();
|
|
722
724
|
}
|
|
723
725
|
|
|
724
|
-
onMount(() => {
|
|
725
|
-
document.addEventListener("click", handle_click_outside);
|
|
726
|
-
window.addEventListener("resize", handle_resize);
|
|
727
|
-
return () => {
|
|
728
|
-
document.removeEventListener("click", handle_click_outside);
|
|
729
|
-
window.removeEventListener("resize", handle_resize);
|
|
730
|
-
};
|
|
731
|
-
});
|
|
732
|
-
|
|
733
726
|
let active_button: {
|
|
734
727
|
type: "header" | "cell";
|
|
735
728
|
row?: number;
|
|
@@ -762,6 +755,22 @@
|
|
|
762
755
|
y: number;
|
|
763
756
|
} | null = null;
|
|
764
757
|
|
|
758
|
+
let is_fullscreen = false;
|
|
759
|
+
|
|
760
|
+
function toggle_fullscreen(): void {
|
|
761
|
+
if (!document.fullscreenElement) {
|
|
762
|
+
parent.requestFullscreen();
|
|
763
|
+
is_fullscreen = true;
|
|
764
|
+
} else {
|
|
765
|
+
document.exitFullscreen();
|
|
766
|
+
is_fullscreen = false;
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
function handle_fullscreen_change(): void {
|
|
771
|
+
is_fullscreen = !!document.fullscreenElement;
|
|
772
|
+
}
|
|
773
|
+
|
|
765
774
|
function toggle_header_menu(event: MouseEvent, col: number): void {
|
|
766
775
|
event.stopPropagation();
|
|
767
776
|
if (active_header_menu && active_header_menu.col === col) {
|
|
@@ -779,24 +788,26 @@
|
|
|
779
788
|
}
|
|
780
789
|
}
|
|
781
790
|
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
}
|
|
791
|
+
afterUpdate(() => {
|
|
792
|
+
value_is_output = false;
|
|
793
|
+
});
|
|
786
794
|
</script>
|
|
787
795
|
|
|
788
|
-
<svelte:window
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
<
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
796
|
+
<svelte:window on:resize={() => set_cell_widths()} />
|
|
797
|
+
|
|
798
|
+
<div class="table-container">
|
|
799
|
+
<div class="header-row">
|
|
800
|
+
{#if label && label.length !== 0 && show_label}
|
|
801
|
+
<div class="label">
|
|
802
|
+
<p>{label}</p>
|
|
803
|
+
</div>
|
|
804
|
+
{/if}
|
|
805
|
+
<Toolbar
|
|
806
|
+
{show_fullscreen_button}
|
|
807
|
+
{is_fullscreen}
|
|
808
|
+
on:click={toggle_fullscreen}
|
|
809
|
+
/>
|
|
810
|
+
</div>
|
|
800
811
|
<div
|
|
801
812
|
bind:this={parent}
|
|
802
813
|
class="table-wrap"
|
|
@@ -817,6 +828,9 @@
|
|
|
817
828
|
{/if}
|
|
818
829
|
<thead>
|
|
819
830
|
<tr>
|
|
831
|
+
{#if show_row_numbers}
|
|
832
|
+
<th class="row-number-header"></th>
|
|
833
|
+
{/if}
|
|
820
834
|
{#each _headers as { value, id }, i (id)}
|
|
821
835
|
<th
|
|
822
836
|
class:editing={header_edit === i}
|
|
@@ -896,6 +910,9 @@
|
|
|
896
910
|
<caption class="sr-only">{label}</caption>
|
|
897
911
|
{/if}
|
|
898
912
|
<tr slot="thead">
|
|
913
|
+
{#if show_row_numbers}
|
|
914
|
+
<th class="row-number-header"></th>
|
|
915
|
+
{/if}
|
|
899
916
|
{#each _headers as { value, id }, i (id)}
|
|
900
917
|
<th
|
|
901
918
|
class:focus={header_edit === i || selected_header === i}
|
|
@@ -915,17 +932,14 @@
|
|
|
915
932
|
edit={header_edit === i}
|
|
916
933
|
on:keydown={end_header_edit}
|
|
917
934
|
on:dblclick={() => edit_header(i)}
|
|
918
|
-
{select_on_focus}
|
|
919
935
|
header
|
|
920
936
|
{root}
|
|
921
937
|
/>
|
|
922
|
-
|
|
923
|
-
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
|
924
|
-
<!-- svelte-ignore a11y-no-static-element-interactions-->
|
|
925
|
-
<div
|
|
938
|
+
<button
|
|
926
939
|
class:sorted={sort_by === i}
|
|
927
940
|
class:des={sort_by === i && sort_direction === "des"}
|
|
928
941
|
class="sort-button {sort_direction}"
|
|
942
|
+
tabindex="0"
|
|
929
943
|
on:click={(event) => {
|
|
930
944
|
event.stopPropagation();
|
|
931
945
|
handle_sort(i);
|
|
@@ -940,7 +954,7 @@
|
|
|
940
954
|
>
|
|
941
955
|
<path d="M4.49999 0L8.3971 6.75H0.602875L4.49999 0Z" />
|
|
942
956
|
</svg>
|
|
943
|
-
</
|
|
957
|
+
</button>
|
|
944
958
|
</div>
|
|
945
959
|
|
|
946
960
|
{#if editable}
|
|
@@ -957,15 +971,44 @@
|
|
|
957
971
|
</tr>
|
|
958
972
|
|
|
959
973
|
<tr slot="tbody" let:item let:index class:row_odd={index % 2 === 0}>
|
|
974
|
+
{#if show_row_numbers}
|
|
975
|
+
<td class="row-number" title={`Row ${index + 1}`}>{index + 1}</td>
|
|
976
|
+
{/if}
|
|
960
977
|
{#each item as { value, id }, j (id)}
|
|
961
978
|
<td
|
|
962
979
|
tabindex="0"
|
|
963
|
-
on:touchstart={() =>
|
|
964
|
-
|
|
965
|
-
|
|
980
|
+
on:touchstart={(event) => {
|
|
981
|
+
event.preventDefault();
|
|
982
|
+
event.stopPropagation();
|
|
983
|
+
clear_on_focus = false;
|
|
984
|
+
clicked_cell = { row: index, col: j };
|
|
985
|
+
selected = [index, j];
|
|
986
|
+
selected_header = false;
|
|
987
|
+
header_edit = false;
|
|
988
|
+
if (editable) {
|
|
989
|
+
editing = [index, j];
|
|
990
|
+
}
|
|
991
|
+
toggle_cell_button(index, j);
|
|
992
|
+
}}
|
|
993
|
+
on:mousedown={(event) => {
|
|
994
|
+
event.preventDefault();
|
|
995
|
+
event.stopPropagation();
|
|
996
|
+
}}
|
|
997
|
+
on:click={(event) => {
|
|
998
|
+
event.preventDefault();
|
|
999
|
+
event.stopPropagation();
|
|
1000
|
+
clear_on_focus = false;
|
|
1001
|
+
active_cell_menu = null;
|
|
1002
|
+
active_header_menu = null;
|
|
1003
|
+
clicked_cell = { row: index, col: j };
|
|
1004
|
+
selected = [index, j];
|
|
1005
|
+
selected_header = false;
|
|
1006
|
+
header_edit = false;
|
|
1007
|
+
if (editable) {
|
|
1008
|
+
editing = [index, j];
|
|
1009
|
+
}
|
|
966
1010
|
toggle_cell_button(index, j);
|
|
967
1011
|
}}
|
|
968
|
-
on:dblclick={() => start_edit(index, j)}
|
|
969
1012
|
style:width="var(--cell-width-{j})"
|
|
970
1013
|
style={styling?.[index]?.[j] || ""}
|
|
971
1014
|
class:focus={dequal(selected, [index, j])}
|
|
@@ -983,7 +1026,10 @@
|
|
|
983
1026
|
{editable}
|
|
984
1027
|
edit={dequal(editing, [index, j])}
|
|
985
1028
|
datatype={Array.isArray(datatype) ? datatype[j] : datatype}
|
|
986
|
-
on:blur={() =>
|
|
1029
|
+
on:blur={() => {
|
|
1030
|
+
clear_on_focus = false;
|
|
1031
|
+
parent.focus();
|
|
1032
|
+
}}
|
|
987
1033
|
{clear_on_focus}
|
|
988
1034
|
{root}
|
|
989
1035
|
/>
|
|
@@ -1250,4 +1296,60 @@
|
|
|
1250
1296
|
overflow-wrap: break-word;
|
|
1251
1297
|
word-break: break-word;
|
|
1252
1298
|
}
|
|
1299
|
+
|
|
1300
|
+
.table-container {
|
|
1301
|
+
display: flex;
|
|
1302
|
+
flex-direction: column;
|
|
1303
|
+
gap: var(--size-2);
|
|
1304
|
+
}
|
|
1305
|
+
|
|
1306
|
+
.row-number,
|
|
1307
|
+
.row-number-header {
|
|
1308
|
+
width: var(--size-7);
|
|
1309
|
+
min-width: var(--size-7);
|
|
1310
|
+
text-align: center;
|
|
1311
|
+
background: var(--table-even-background-fill);
|
|
1312
|
+
position: sticky;
|
|
1313
|
+
left: 0;
|
|
1314
|
+
font-size: var(--input-text-size);
|
|
1315
|
+
color: var(--body-text-color);
|
|
1316
|
+
padding: var(--size-1) var(--size-2);
|
|
1317
|
+
overflow: hidden;
|
|
1318
|
+
text-overflow: ellipsis;
|
|
1319
|
+
white-space: nowrap;
|
|
1320
|
+
font-weight: var(--weight-semibold);
|
|
1321
|
+
}
|
|
1322
|
+
|
|
1323
|
+
.row-number-header {
|
|
1324
|
+
z-index: var(--layer-2);
|
|
1325
|
+
}
|
|
1326
|
+
|
|
1327
|
+
.row-number {
|
|
1328
|
+
z-index: var(--layer-1);
|
|
1329
|
+
}
|
|
1330
|
+
|
|
1331
|
+
:global(tbody > tr:nth-child(odd)) .row-number {
|
|
1332
|
+
background: var(--table-odd-background-fill);
|
|
1333
|
+
}
|
|
1334
|
+
|
|
1335
|
+
.header-row {
|
|
1336
|
+
display: flex;
|
|
1337
|
+
justify-content: space-between;
|
|
1338
|
+
align-items: center;
|
|
1339
|
+
gap: var(--size-2);
|
|
1340
|
+
height: var(--size-6);
|
|
1341
|
+
min-height: var(--size-6);
|
|
1342
|
+
}
|
|
1343
|
+
|
|
1344
|
+
.label {
|
|
1345
|
+
flex: 1;
|
|
1346
|
+
}
|
|
1347
|
+
|
|
1348
|
+
.label p {
|
|
1349
|
+
position: relative;
|
|
1350
|
+
z-index: var(--layer-4);
|
|
1351
|
+
margin: 0;
|
|
1352
|
+
color: var(--block-label-text-color);
|
|
1353
|
+
font-size: var(--block-label-text-size);
|
|
1354
|
+
}
|
|
1253
1355
|
</style>
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Maximize, Minimize } from "@gradio/icons";
|
|
3
|
+
|
|
4
|
+
export let show_fullscreen_button = false;
|
|
5
|
+
export let is_fullscreen = false;
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
{#if show_fullscreen_button}
|
|
9
|
+
<div class="toolbar">
|
|
10
|
+
<button class="toolbar-button" on:click>
|
|
11
|
+
{#if is_fullscreen}
|
|
12
|
+
<Minimize />
|
|
13
|
+
{:else}
|
|
14
|
+
<Maximize />
|
|
15
|
+
{/if}
|
|
16
|
+
</button>
|
|
17
|
+
</div>
|
|
18
|
+
{/if}
|
|
19
|
+
|
|
20
|
+
<style>
|
|
21
|
+
.toolbar {
|
|
22
|
+
display: flex;
|
|
23
|
+
justify-content: flex-end;
|
|
24
|
+
gap: var(--size-1);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.toolbar-button {
|
|
28
|
+
display: flex;
|
|
29
|
+
align-items: center;
|
|
30
|
+
justify-content: center;
|
|
31
|
+
width: var(--size-6);
|
|
32
|
+
height: var(--size-6);
|
|
33
|
+
padding: var(--size-1);
|
|
34
|
+
border: none;
|
|
35
|
+
border-radius: var(--radius-sm);
|
|
36
|
+
background: transparent;
|
|
37
|
+
color: var(--body-text-color-subdued);
|
|
38
|
+
cursor: pointer;
|
|
39
|
+
transition: all 0.2s;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.toolbar-button:hover {
|
|
43
|
+
background: var(--background-fill-secondary);
|
|
44
|
+
color: var(--body-text-color);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.toolbar-button :global(svg) {
|
|
48
|
+
width: var(--size-4);
|
|
49
|
+
height: var(--size-4);
|
|
50
|
+
}
|
|
51
|
+
</style>
|