@gradio/dataframe 0.24.5 → 0.24.7
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 +26 -0
- package/Dataframe.test.ts +641 -115
- package/Index.svelte +1 -0
- package/dist/Index.svelte +1 -0
- package/dist/shared/Table.svelte +155 -29
- package/dist/shared/Table.svelte.d.ts +1 -0
- package/dist/shared/types.d.ts +0 -4
- package/dist/shared/types.js +0 -1
- package/dist/shared/utils/table_utils.d.ts +5 -4
- package/dist/shared/utils/table_utils.js +37 -35
- package/dist/shared/utils/utils.d.ts +0 -4
- package/dist/standalone/default_i18n.js +7 -0
- package/dist/types.d.ts +1 -0
- package/package.json +9 -9
- package/shared/Table.svelte +155 -29
- package/shared/types.ts +0 -6
- package/shared/utils/table_utils.ts +38 -44
- package/shared/utils/utils.ts +0 -1
- package/standalone/default_i18n.ts +12 -0
- package/test/table_utils.test.ts +92 -28
- package/types.ts +1 -0
package/Index.svelte
CHANGED
package/dist/Index.svelte
CHANGED
package/dist/shared/Table.svelte
CHANGED
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
is_cell_selected,
|
|
36
36
|
handle_click_outside as handle_click_outside_util
|
|
37
37
|
} from "./utils/selection_utils";
|
|
38
|
-
import { copy_table_data,
|
|
38
|
+
import { copy_table_data, parse_table_file } from "./utils/table_utils";
|
|
39
39
|
import { gradio_filter_fn } from "./utils/filter";
|
|
40
40
|
import { create_column_measurement } from "./column_measurement.svelte.js";
|
|
41
41
|
|
|
@@ -73,7 +73,8 @@
|
|
|
73
73
|
onselect,
|
|
74
74
|
onedit,
|
|
75
75
|
onsearch,
|
|
76
|
-
onfullscreen
|
|
76
|
+
onfullscreen,
|
|
77
|
+
onerror
|
|
77
78
|
}: {
|
|
78
79
|
datatype: Datatype | Datatype[];
|
|
79
80
|
label?: string | null;
|
|
@@ -109,6 +110,7 @@
|
|
|
109
110
|
onedit?: (detail: EditData) => void;
|
|
110
111
|
onsearch?: (detail: string | null) => void;
|
|
111
112
|
onfullscreen?: () => void;
|
|
113
|
+
onerror?: (message: string) => void;
|
|
112
114
|
} = $props();
|
|
113
115
|
|
|
114
116
|
type GradioRow = Record<string, CellValue> & { _index: number };
|
|
@@ -277,7 +279,11 @@
|
|
|
277
279
|
let copy_flash = $state(false);
|
|
278
280
|
let is_dragging = $state(false);
|
|
279
281
|
let show_scroll_button = $state(false);
|
|
280
|
-
let
|
|
282
|
+
let file_dragging = $state(false);
|
|
283
|
+
let discard_pending_edit = false;
|
|
284
|
+
// document-unique so several dataframes on a page do not describe each
|
|
285
|
+
// other's grids
|
|
286
|
+
const drop_hint_id = $props.id();
|
|
281
287
|
|
|
282
288
|
let parent: HTMLDivElement;
|
|
283
289
|
|
|
@@ -603,12 +609,21 @@
|
|
|
603
609
|
blur_event: FocusEvent;
|
|
604
610
|
coords: [number, number];
|
|
605
611
|
}): void {
|
|
612
|
+
// an import replaces the table under an open editor, and EditableCell
|
|
613
|
+
// commits when it leaves edit mode either way. that half-typed value
|
|
614
|
+
// belongs to the table that just went away
|
|
615
|
+
if (discard_pending_edit) return;
|
|
616
|
+
|
|
606
617
|
const { coords } = detail;
|
|
607
618
|
const input_el = detail.blur_event.target as HTMLTextAreaElement;
|
|
608
619
|
if (!input_el || input_el.value === undefined) return;
|
|
609
620
|
|
|
610
621
|
const [row, col] = coords;
|
|
611
|
-
|
|
622
|
+
// and deleting a row leaves the editor's row behind. a column short of
|
|
623
|
+
// the header is not the same thing: a value can arrive ragged, and the
|
|
624
|
+
// cell past the end of its own row still renders and still takes an edit
|
|
625
|
+
if (!values?.[row]) return;
|
|
626
|
+
const old_value = values[row][col];
|
|
612
627
|
const new_value = input_el.value;
|
|
613
628
|
|
|
614
629
|
if (String(old_value) !== String(new_value)) {
|
|
@@ -858,16 +873,22 @@
|
|
|
858
873
|
return true;
|
|
859
874
|
}
|
|
860
875
|
|
|
876
|
+
// every one of these holds a row or column index, so they have to go
|
|
877
|
+
// whenever the table stops being the one they were recorded against
|
|
878
|
+
function reset_interaction_state(): void {
|
|
879
|
+
selected_cells = [];
|
|
880
|
+
selected = false;
|
|
881
|
+
range_anchor = false;
|
|
882
|
+
editing = false;
|
|
883
|
+
header_edit = false;
|
|
884
|
+
selected_header = false;
|
|
885
|
+
active_cell_menu = null;
|
|
886
|
+
active_header_menu = null;
|
|
887
|
+
}
|
|
888
|
+
|
|
861
889
|
function handle_click_outside(event: Event): void {
|
|
862
890
|
if (handle_click_outside_util(event, parent)) {
|
|
863
|
-
|
|
864
|
-
selected = false;
|
|
865
|
-
range_anchor = false;
|
|
866
|
-
editing = false;
|
|
867
|
-
header_edit = false;
|
|
868
|
-
selected_header = false;
|
|
869
|
-
active_cell_menu = null;
|
|
870
|
-
active_header_menu = null;
|
|
891
|
+
reset_interaction_state();
|
|
871
892
|
}
|
|
872
893
|
}
|
|
873
894
|
|
|
@@ -1113,21 +1134,87 @@
|
|
|
1113
1134
|
}
|
|
1114
1135
|
}
|
|
1115
1136
|
|
|
1116
|
-
function
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1137
|
+
function interpolate(
|
|
1138
|
+
message: string,
|
|
1139
|
+
values: Record<string, string | number>
|
|
1140
|
+
): string {
|
|
1141
|
+
return message.replace(/\{(\w+)\}/g, (_, key) => String(values[key]));
|
|
1142
|
+
}
|
|
1143
|
+
|
|
1144
|
+
function apply_imported_table(
|
|
1145
|
+
new_headers: (string | null)[],
|
|
1146
|
+
new_values: CellValue[][]
|
|
1147
|
+
): void {
|
|
1148
|
+
if (!new_headers.length) {
|
|
1149
|
+
throw new Error(i18n("dataframe.import_empty_file"));
|
|
1150
|
+
}
|
|
1151
|
+
// a file of separators alone parses into a header of blank names, and
|
|
1152
|
+
// importing it would replace the table with unnamed columns
|
|
1153
|
+
if (new_headers.every((h) => !h?.trim())) {
|
|
1154
|
+
throw new Error(i18n("dataframe.import_no_column_names"));
|
|
1155
|
+
}
|
|
1156
|
+
// a row the header cannot account for would reach the backend as a ragged
|
|
1157
|
+
// value, and the column checks below only see the header
|
|
1158
|
+
const ragged = new_values.findIndex(
|
|
1159
|
+
(row) => row.length !== new_headers.length
|
|
1130
1160
|
);
|
|
1161
|
+
if (ragged !== -1) {
|
|
1162
|
+
throw new Error(
|
|
1163
|
+
interpolate(i18n("dataframe.import_ragged_row"), {
|
|
1164
|
+
line: ragged + 2,
|
|
1165
|
+
fields: new_values[ragged].length,
|
|
1166
|
+
columns: new_headers.length
|
|
1167
|
+
})
|
|
1168
|
+
);
|
|
1169
|
+
}
|
|
1170
|
+
// the menu paths already refuse to change a fixed shape or write to a
|
|
1171
|
+
// read-only column, so an import must not be the way around them
|
|
1172
|
+
if (static_columns.length > 0) {
|
|
1173
|
+
throw new Error(i18n("dataframe.import_static_columns"));
|
|
1174
|
+
}
|
|
1175
|
+
if (col_count[1] === "fixed" && new_headers.length !== col_count[0]) {
|
|
1176
|
+
throw new Error(
|
|
1177
|
+
interpolate(i18n("dataframe.import_fixed_columns"), {
|
|
1178
|
+
expected: col_count[0],
|
|
1179
|
+
actual: new_headers.length
|
|
1180
|
+
})
|
|
1181
|
+
);
|
|
1182
|
+
}
|
|
1183
|
+
if (row_count[1] === "fixed" && new_values.length !== row_count[0]) {
|
|
1184
|
+
throw new Error(
|
|
1185
|
+
interpolate(i18n("dataframe.import_fixed_rows"), {
|
|
1186
|
+
expected: row_count[0],
|
|
1187
|
+
actual: new_values.length
|
|
1188
|
+
})
|
|
1189
|
+
);
|
|
1190
|
+
}
|
|
1191
|
+
|
|
1192
|
+
discard_pending_edit = true;
|
|
1193
|
+
headers = new_headers;
|
|
1194
|
+
values = new_values;
|
|
1195
|
+
reset_interaction_state();
|
|
1196
|
+
// tanstack keys these by positional col_N, so they would land on whichever
|
|
1197
|
+
// column now sits at that index. a search is worse than misplaced: it hides
|
|
1198
|
+
// imported rows, and commit_filter then drops the hidden ones from the value
|
|
1199
|
+
sorting = [];
|
|
1200
|
+
column_filters = [];
|
|
1201
|
+
global_filter = "";
|
|
1202
|
+
push_change(new_values, headers as string[]);
|
|
1203
|
+
tick().then(() => (discard_pending_edit = false));
|
|
1204
|
+
}
|
|
1205
|
+
|
|
1206
|
+
// undefined when every dropped file was filtered out by `filetype`
|
|
1207
|
+
function on_file_upload(file: File | undefined): void {
|
|
1208
|
+
if (!editable || !file) return;
|
|
1209
|
+
parse_table_file(file)
|
|
1210
|
+
.then(({ headers: new_headers, values: new_values }) =>
|
|
1211
|
+
apply_imported_table(new_headers, new_values)
|
|
1212
|
+
)
|
|
1213
|
+
.catch((e) => {
|
|
1214
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
1215
|
+
if (onerror) onerror(message);
|
|
1216
|
+
else console.error(message);
|
|
1217
|
+
});
|
|
1131
1218
|
}
|
|
1132
1219
|
|
|
1133
1220
|
onMount(() => {
|
|
@@ -1225,6 +1312,7 @@
|
|
|
1225
1312
|
bind:this={parent}
|
|
1226
1313
|
class="table-wrap"
|
|
1227
1314
|
class:dragging={is_dragging}
|
|
1315
|
+
class:file-dragging={file_dragging && editable}
|
|
1228
1316
|
class:menu-open={active_cell_menu || active_header_menu}
|
|
1229
1317
|
onkeydown={handle_keydown}
|
|
1230
1318
|
role="grid"
|
|
@@ -1232,6 +1320,7 @@
|
|
|
1232
1320
|
aria-rowcount={rows.length + 1}
|
|
1233
1321
|
aria-colcount={resolved_headers.length + Number(show_row_numbers)}
|
|
1234
1322
|
aria-readonly={!editable}
|
|
1323
|
+
aria-describedby={editable ? drop_hint_id : undefined}
|
|
1235
1324
|
tabindex={rows.length === 0 ? 0 : -1}
|
|
1236
1325
|
style="--df-max-col-width: {viewport_width}px;"
|
|
1237
1326
|
>
|
|
@@ -1242,10 +1331,12 @@
|
|
|
1242
1331
|
center={false}
|
|
1243
1332
|
boundedheight={false}
|
|
1244
1333
|
disable_click={true}
|
|
1334
|
+
format="blob"
|
|
1335
|
+
filetype={[".csv", ".tsv"]}
|
|
1245
1336
|
{root}
|
|
1246
1337
|
onload={on_file_upload}
|
|
1247
|
-
|
|
1248
|
-
|
|
1338
|
+
onerror={editable ? onerror : undefined}
|
|
1339
|
+
bind:dragging={file_dragging}
|
|
1249
1340
|
tab_index={-1}
|
|
1250
1341
|
container_element="div"
|
|
1251
1342
|
>
|
|
@@ -1470,6 +1561,15 @@
|
|
|
1470
1561
|
{/if}
|
|
1471
1562
|
</div>
|
|
1472
1563
|
|
|
1564
|
+
<!-- outside the grid: #13729 took the label off a span like this one and put it
|
|
1565
|
+
on the grid as an attribute, and a test pins that there is no sr-only text
|
|
1566
|
+
inside. a description has no equally well supported attribute form -->
|
|
1567
|
+
{#if editable}
|
|
1568
|
+
<span id={drop_hint_id} class="drop-hint"
|
|
1569
|
+
>{i18n("dataframe.drop_to_upload")}</span
|
|
1570
|
+
>
|
|
1571
|
+
{/if}
|
|
1572
|
+
|
|
1473
1573
|
{#if values.length === 0 && editable && row_count[1] === "dynamic"}
|
|
1474
1574
|
<EmptyRowButton on_click={() => add_row()} />
|
|
1475
1575
|
{/if}
|
|
@@ -1585,8 +1685,13 @@
|
|
|
1585
1685
|
|
|
1586
1686
|
.table-wrap {
|
|
1587
1687
|
position: relative;
|
|
1588
|
-
transition: 150ms;
|
|
1589
1688
|
width: 100%;
|
|
1689
|
+
/* the duration used to stand alone, which means every property. that
|
|
1690
|
+
swept the drag outline in from `currentcolor`, near-white in dark
|
|
1691
|
+
mode, before it reached the accent. the list is what the fullscreen
|
|
1692
|
+
rules above actually change */
|
|
1693
|
+
transition-property: flex-grow, flex-shrink, flex-basis, min-height;
|
|
1694
|
+
transition-duration: 150ms;
|
|
1590
1695
|
}
|
|
1591
1696
|
|
|
1592
1697
|
/* Constrain Upload component wrapper */
|
|
@@ -1602,6 +1707,27 @@
|
|
|
1602
1707
|
outline: none;
|
|
1603
1708
|
}
|
|
1604
1709
|
|
|
1710
|
+
/* after :focus-within, which is equally specific and would otherwise
|
|
1711
|
+
clear the outline whenever a cell is focused. drawn inside the box so
|
|
1712
|
+
hovering a file over the table shifts nothing */
|
|
1713
|
+
.table-wrap.file-dragging {
|
|
1714
|
+
outline: 2px solid var(--color-accent);
|
|
1715
|
+
outline-offset: -2px;
|
|
1716
|
+
/* matches the .upload-container border the outline covers */
|
|
1717
|
+
border-radius: var(--table-radius);
|
|
1718
|
+
}
|
|
1719
|
+
|
|
1720
|
+
/* an aria-describedby target, so it has to stay in the accessibility tree
|
|
1721
|
+
rather than be hidden with display: none */
|
|
1722
|
+
.drop-hint {
|
|
1723
|
+
position: absolute;
|
|
1724
|
+
clip-path: inset(50%);
|
|
1725
|
+
width: 1px;
|
|
1726
|
+
height: 1px;
|
|
1727
|
+
overflow: hidden;
|
|
1728
|
+
white-space: nowrap;
|
|
1729
|
+
}
|
|
1730
|
+
|
|
1605
1731
|
.table-wrap.dragging {
|
|
1606
1732
|
cursor: crosshair !important;
|
|
1607
1733
|
user-select: none;
|
|
@@ -42,6 +42,7 @@ type $$ComponentProps = {
|
|
|
42
42
|
onedit?: (detail: EditData) => void;
|
|
43
43
|
onsearch?: (detail: string | null) => void;
|
|
44
44
|
onfullscreen?: () => void;
|
|
45
|
+
onerror?: (message: string) => void;
|
|
45
46
|
};
|
|
46
47
|
declare const Table: import("svelte").Component<$$ComponentProps, {}, "headers" | "values" | "value_is_output">;
|
|
47
48
|
type Table = ReturnType<typeof Table>;
|
package/dist/shared/types.d.ts
CHANGED
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
export type CellCoordinate = [number, number];
|
|
2
2
|
export type EditingState = CellCoordinate | false;
|
|
3
3
|
export type Headers = (string | null)[];
|
|
4
|
-
export interface HeadersWithIDs {
|
|
5
|
-
id: string;
|
|
6
|
-
value: string;
|
|
7
|
-
}
|
|
8
4
|
export type CellValue = string | number | boolean;
|
|
9
5
|
export interface TableCell {
|
|
10
6
|
id: string;
|
package/dist/shared/types.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import type { CellValue, Headers,
|
|
1
|
+
import type { CellValue, Headers, TableData } from "../types";
|
|
2
2
|
export declare function make_cell_id(row: number, col: number): string;
|
|
3
3
|
export declare function make_header_id(col: number): string;
|
|
4
4
|
export declare function copy_table_data(data: TableData, selected_cells: [number, number][]): Promise<void>;
|
|
5
|
-
export declare function
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
export declare function parse_table_file(file: File): Promise<{
|
|
6
|
+
headers: Headers;
|
|
7
|
+
values: CellValue[][];
|
|
8
|
+
}>;
|
|
@@ -36,41 +36,43 @@ export async function copy_table_data(data, selected_cells) {
|
|
|
36
36
|
throw new Error("Failed to copy to clipboard: " + err.message);
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
|
-
export function
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
39
|
+
export async function parse_table_file(file) {
|
|
40
|
+
const text = await file.text();
|
|
41
|
+
if (!text.trim())
|
|
42
|
+
return { headers: [], values: [] };
|
|
43
|
+
// the drop zone only accepts .csv and .tsv, so the extension goes first and
|
|
44
|
+
// wins any tie, but a mislabeled file is still read by its content: a
|
|
45
|
+
// separator only takes the file if it splits every line the same way, which
|
|
46
|
+
// is what tells a real separator from one that sits in a header name. the
|
|
47
|
+
// split is d3's rather than a raw count, so a separator inside a quoted
|
|
48
|
+
// field does not throw the detection off.
|
|
49
|
+
const by_extension = file.name.toLowerCase().endsWith(".tsv") ? "\t" : ",";
|
|
50
|
+
const candidates = by_extension === "\t" ? ["\t", ","] : [",", "\t"];
|
|
51
|
+
let consistent;
|
|
52
|
+
let ragged;
|
|
53
|
+
let unsplit;
|
|
54
|
+
for (const delimiter of candidates) {
|
|
55
|
+
// a blank line parses to a single empty field, which both the width
|
|
56
|
+
// checks below and the caller's ragged check would read as a short row
|
|
57
|
+
const parsed = dsvFormat(delimiter)
|
|
58
|
+
.parseRows(text)
|
|
59
|
+
.filter((row) => row.length > 1 || row[0] !== "");
|
|
60
|
+
const width = parsed[0]?.length ?? 0;
|
|
61
|
+
// the extension is first in `candidates`, so this keeps its parse for the
|
|
62
|
+
// single-column case rather than running it again at the end
|
|
63
|
+
unsplit ??= parsed;
|
|
64
|
+
if (width < 2)
|
|
65
|
+
continue;
|
|
66
|
+
if (parsed.every((row) => row.length === width)) {
|
|
67
|
+
consistent = parsed;
|
|
68
|
+
break;
|
|
51
69
|
}
|
|
70
|
+
// a separator that splits the header but leaves the rows uneven is
|
|
71
|
+
// usually the one that just happens to appear in a header name. keep it
|
|
72
|
+
// only in case the other does not split at all, where a ragged table is
|
|
73
|
+
// still better to report on than an unsplit one
|
|
74
|
+
ragged ??= parsed;
|
|
52
75
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
const byte_str = atob(data_uri.split(",")[1]);
|
|
56
|
-
const mime_str = data_uri.split(",")[0].split(":")[1].split(";")[0];
|
|
57
|
-
const ab = new ArrayBuffer(byte_str.length);
|
|
58
|
-
const ia = new Uint8Array(ab);
|
|
59
|
-
for (let i = 0; i < byte_str.length; i++) {
|
|
60
|
-
ia[i] = byte_str.charCodeAt(i);
|
|
61
|
-
}
|
|
62
|
-
return new Blob([ab], { type: mime_str });
|
|
63
|
-
}
|
|
64
|
-
export function handle_file_upload(data_uri, update_headers, update_values) {
|
|
65
|
-
const blob = data_uri_to_blob(data_uri);
|
|
66
|
-
const reader = new FileReader();
|
|
67
|
-
reader.addEventListener("loadend", (e) => {
|
|
68
|
-
if (!e?.target?.result || typeof e.target.result !== "string")
|
|
69
|
-
return;
|
|
70
|
-
const [delimiter] = guess_delimiter(e.target.result, [",", "\t"]);
|
|
71
|
-
const [head, ...rest] = dsvFormat(delimiter).parseRows(e.target.result);
|
|
72
|
-
update_headers(head);
|
|
73
|
-
update_values(rest);
|
|
74
|
-
});
|
|
75
|
-
reader.readAsText(blob);
|
|
76
|
+
const [head = [], ...rest] = consistent ?? ragged ?? unsplit ?? [];
|
|
77
|
+
return { headers: head.map((h) => h ?? ""), values: rest };
|
|
76
78
|
}
|
|
@@ -5,10 +5,6 @@ export type Datatype = "str" | "number" | "bool" | "date" | "markdown" | "html"
|
|
|
5
5
|
export type Metadata = {
|
|
6
6
|
[key: string]: string[][] | null;
|
|
7
7
|
} | null;
|
|
8
|
-
export type HeadersWithIDs = {
|
|
9
|
-
value: string;
|
|
10
|
-
id: string;
|
|
11
|
-
}[];
|
|
12
8
|
export type DataframeValue = {
|
|
13
9
|
data: Data;
|
|
14
10
|
headers: Headers;
|
|
@@ -5,6 +5,13 @@ export const default_i18n = {
|
|
|
5
5
|
"dataframe.add_column_left": "Add column left",
|
|
6
6
|
"dataframe.add_column_right": "Add column right",
|
|
7
7
|
"dataframe.delete_column": "Delete column",
|
|
8
|
+
"dataframe.drop_to_upload": "Drop CSV or TSV files here to import data into dataframe",
|
|
9
|
+
"dataframe.import_empty_file": "The dropped file is empty.",
|
|
10
|
+
"dataframe.import_no_column_names": "The dropped file has no column names.",
|
|
11
|
+
"dataframe.import_ragged_row": "Line {line} of the file has {fields} fields, the header has {columns}.",
|
|
12
|
+
"dataframe.import_static_columns": "Cannot import into a table with read-only columns.",
|
|
13
|
+
"dataframe.import_fixed_columns": "This table takes exactly {expected} columns, the file has {actual}.",
|
|
14
|
+
"dataframe.import_fixed_rows": "This table takes exactly {expected} rows, the file has {actual}.",
|
|
8
15
|
"dataframe.sort_asc": "Sort ascending",
|
|
9
16
|
"dataframe.sort_desc": "Sort descending",
|
|
10
17
|
"dataframe.sort_ascending": "Sort ascending",
|
package/dist/types.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gradio/dataframe",
|
|
3
|
-
"version": "0.24.
|
|
3
|
+
"version": "0.24.7",
|
|
4
4
|
"description": "Gradio UI packages",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "",
|
|
@@ -15,15 +15,15 @@
|
|
|
15
15
|
"dequal": "^2.0.3",
|
|
16
16
|
"@tanstack/table-core": "^8.21.3",
|
|
17
17
|
"@tanstack/virtual-core": "^3.13.6",
|
|
18
|
-
"@gradio/atoms": "^0.26.
|
|
19
|
-
"@gradio/checkbox": "^0.8.
|
|
20
|
-
"@gradio/
|
|
21
|
-
"@gradio/
|
|
22
|
-
"@gradio/
|
|
18
|
+
"@gradio/atoms": "^0.26.3",
|
|
19
|
+
"@gradio/checkbox": "^0.8.4",
|
|
20
|
+
"@gradio/client": "^2.7.2",
|
|
21
|
+
"@gradio/markdown-code": "^0.10.3",
|
|
22
|
+
"@gradio/button": "^0.8.4",
|
|
23
|
+
"@gradio/statustracker": "^0.16.0",
|
|
24
|
+
"@gradio/utils": "^0.15.0",
|
|
23
25
|
"@gradio/icons": "^0.16.0",
|
|
24
|
-
"@gradio/upload": "^0.
|
|
25
|
-
"@gradio/statustracker": "^0.15.3",
|
|
26
|
-
"@gradio/utils": "^0.14.2"
|
|
26
|
+
"@gradio/upload": "^0.19.1"
|
|
27
27
|
},
|
|
28
28
|
"exports": {
|
|
29
29
|
".": {
|