@gradio/dataframe 0.19.3 → 0.20.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 +16 -0
- package/Index.svelte +2 -0
- package/dist/Index.svelte +1 -0
- package/dist/Index.svelte.d.ts +3 -0
- package/dist/shared/BooleanCell.svelte +1 -2
- package/dist/shared/BooleanCell.svelte.d.ts +1 -1
- package/dist/shared/EditableCell.svelte +7 -18
- package/dist/shared/EditableCell.svelte.d.ts +2 -1
- package/dist/shared/Table.svelte +5 -13
- package/dist/shared/Table.svelte.d.ts +4 -2
- package/dist/shared/TableCell.svelte.d.ts +2 -1
- package/dist/shared/context/dataframe_context.d.ts +9 -8
- package/dist/shared/context/dataframe_context.js +9 -1
- package/dist/shared/types.d.ts +2 -1
- package/dist/shared/utils/data_processing.d.ts +5 -4
- package/dist/shared/utils/data_processing.js +4 -2
- package/dist/shared/utils/filter_utils.d.ts +5 -4
- package/dist/shared/utils/keyboard_utils.js +1 -1
- package/dist/shared/utils/selection_utils.d.ts +3 -3
- package/dist/shared/utils/sort_utils.d.ts +4 -4
- package/dist/shared/utils/table_utils.d.ts +2 -2
- package/dist/shared/utils/utils.d.ts +8 -2
- package/dist/standalone/Index.svelte +2 -2
- package/dist/standalone/Index.svelte.d.ts +1 -1
- package/package.json +5 -5
- package/shared/BooleanCell.svelte +2 -5
- package/shared/EditableCell.svelte +12 -20
- package/shared/Table.svelte +24 -27
- package/shared/TableCell.svelte +2 -1
- package/shared/context/dataframe_context.ts +20 -13
- package/shared/types.ts +3 -1
- package/shared/utils/data_processing.ts +10 -5
- package/shared/utils/filter_utils.ts +5 -4
- package/shared/utils/keyboard_utils.ts +1 -6
- package/shared/utils/selection_utils.ts +3 -3
- package/shared/utils/sort_utils.ts +4 -4
- package/shared/utils/table_utils.ts +8 -2
- package/shared/utils/utils.ts +10 -5
- package/standalone/Index.svelte +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# @gradio/dataframe
|
|
2
2
|
|
|
3
|
+
## 0.20.0
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
|
|
7
|
+
- [#11959](https://github.com/gradio-app/gradio/pull/11959) [`cb16ca5`](https://github.com/gradio-app/gradio/commit/cb16ca5123030beebcb24ddc287fcf958bd3fbe2) - Ensure interactivity works as expected in standalone dataframe. Thanks @hannahblair!
|
|
8
|
+
|
|
9
|
+
## 0.19.4
|
|
10
|
+
|
|
11
|
+
### Fixes
|
|
12
|
+
|
|
13
|
+
- [#11648](https://github.com/gradio-app/gradio/pull/11648) [`57d8d65`](https://github.com/gradio-app/gradio/commit/57d8d6598645e438337c78c1c8e0759f876fb193) - Dataframe Edit Event. Thanks @deckar01!
|
|
14
|
+
|
|
15
|
+
### Dependency updates
|
|
16
|
+
|
|
17
|
+
- @gradio/markdown-code@0.5.2
|
|
18
|
+
|
|
3
19
|
## 0.19.3
|
|
4
20
|
|
|
5
21
|
### Features
|
package/Index.svelte
CHANGED
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
input: never;
|
|
42
42
|
clear_status: LoadingStatus;
|
|
43
43
|
search: string | null;
|
|
44
|
+
edit: SelectData;
|
|
44
45
|
}>;
|
|
45
46
|
export let latex_delimiters: {
|
|
46
47
|
left: string;
|
|
@@ -95,6 +96,7 @@
|
|
|
95
96
|
}}
|
|
96
97
|
on:input={(e) => gradio.dispatch("input")}
|
|
97
98
|
on:select={(e) => gradio.dispatch("select", e.detail)}
|
|
99
|
+
on:edit={(e) => gradio.dispatch("edit", e.detail)}
|
|
98
100
|
on:fullscreen={({ detail }) => {
|
|
99
101
|
fullscreen = detail;
|
|
100
102
|
}}
|
package/dist/Index.svelte
CHANGED
package/dist/Index.svelte.d.ts
CHANGED
|
@@ -28,6 +28,7 @@ declare const __propDef: {
|
|
|
28
28
|
input: never;
|
|
29
29
|
clear_status: LoadingStatus;
|
|
30
30
|
search: string | null;
|
|
31
|
+
edit: SelectData;
|
|
31
32
|
}>;
|
|
32
33
|
latex_delimiters: {
|
|
33
34
|
left: string;
|
|
@@ -111,6 +112,7 @@ export default class Index extends SvelteComponent<IndexProps, IndexEvents, Inde
|
|
|
111
112
|
input: never;
|
|
112
113
|
clear_status: LoadingStatus;
|
|
113
114
|
search: string | null;
|
|
115
|
+
edit: SelectData;
|
|
114
116
|
}>;
|
|
115
117
|
/**accessor*/
|
|
116
118
|
set gradio(_: Gradio<{
|
|
@@ -119,6 +121,7 @@ export default class Index extends SvelteComponent<IndexProps, IndexEvents, Inde
|
|
|
119
121
|
input: never;
|
|
120
122
|
clear_status: LoadingStatus;
|
|
121
123
|
search: string | null;
|
|
124
|
+
edit: SelectData;
|
|
122
125
|
}>);
|
|
123
126
|
get latex_delimiters(): {
|
|
124
127
|
left: string;
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
export let value = false;
|
|
3
3
|
export let editable = true;
|
|
4
4
|
export let on_change;
|
|
5
|
-
$: bool_value = typeof value === "string" ? value.toLowerCase() === "true" : !!value;
|
|
6
5
|
function handle_change(event) {
|
|
7
6
|
if (editable) {
|
|
8
7
|
on_change(event.detail);
|
|
@@ -12,7 +11,7 @@ function handle_change(event) {
|
|
|
12
11
|
|
|
13
12
|
<div class="bool-cell" role="button" tabindex="-1">
|
|
14
13
|
<BaseCheckbox
|
|
15
|
-
bind:value
|
|
14
|
+
bind:value
|
|
16
15
|
label=""
|
|
17
16
|
interactive={editable}
|
|
18
17
|
on:change={handle_change}
|
|
@@ -48,18 +48,11 @@ function handle_blur(event) {
|
|
|
48
48
|
function handle_keydown(event) {
|
|
49
49
|
dispatch("keydown", event);
|
|
50
50
|
}
|
|
51
|
-
function
|
|
52
|
-
value
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
type: "checkbox",
|
|
57
|
-
checked: new_value,
|
|
58
|
-
value: new_value.toString()
|
|
59
|
-
}
|
|
60
|
-
},
|
|
61
|
-
coords
|
|
62
|
-
});
|
|
51
|
+
function commit_change(checked) {
|
|
52
|
+
handle_blur({ target: { value } });
|
|
53
|
+
}
|
|
54
|
+
$: if (!edit) {
|
|
55
|
+
handle_blur({ target: { value } });
|
|
63
56
|
}
|
|
64
57
|
</script>
|
|
65
58
|
|
|
@@ -80,12 +73,8 @@ function handle_bool_change(new_value) {
|
|
|
80
73
|
/>
|
|
81
74
|
{/if}
|
|
82
75
|
|
|
83
|
-
{#if datatype === "bool"}
|
|
84
|
-
<BooleanCell
|
|
85
|
-
value={String(display_content)}
|
|
86
|
-
{editable}
|
|
87
|
-
on_change={handle_bool_change}
|
|
88
|
-
/>
|
|
76
|
+
{#if datatype === "bool" && typeof value === "boolean"}
|
|
77
|
+
<BooleanCell bind:value {editable} on_change={commit_change} />
|
|
89
78
|
{:else}
|
|
90
79
|
<span
|
|
91
80
|
class:dragging={is_dragging}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { SvelteComponent } from "svelte";
|
|
2
2
|
import type { I18nFormatter } from "@gradio/utils";
|
|
3
|
+
import type { CellValue } from "./types";
|
|
3
4
|
declare const __propDef: {
|
|
4
5
|
props: {
|
|
5
6
|
edit: boolean;
|
|
6
|
-
value?:
|
|
7
|
+
value?: CellValue;
|
|
7
8
|
display_value?: string | null;
|
|
8
9
|
styling?: string;
|
|
9
10
|
header?: boolean;
|
package/dist/shared/Table.svelte
CHANGED
|
@@ -28,7 +28,6 @@ import {
|
|
|
28
28
|
handle_file_upload
|
|
29
29
|
} from "./utils/table_utils";
|
|
30
30
|
import { make_headers, process_data } from "./utils/data_processing";
|
|
31
|
-
import { cast_value_to_type } from "./utils/utils";
|
|
32
31
|
import { handle_keydown, handle_cell_blur } from "./utils/keyboard_utils";
|
|
33
32
|
import {
|
|
34
33
|
create_drag_handlers
|
|
@@ -180,7 +179,8 @@ $: if (!dequal(values, old_val)) {
|
|
|
180
179
|
els,
|
|
181
180
|
data_binding,
|
|
182
181
|
make_id,
|
|
183
|
-
display_value
|
|
182
|
+
display_value,
|
|
183
|
+
datatype
|
|
184
184
|
);
|
|
185
185
|
old_val = JSON.parse(JSON.stringify(values));
|
|
186
186
|
if (is_reset || is_different_structure) {
|
|
@@ -235,26 +235,18 @@ $: if ($df_state.current_search_query !== void 0) {
|
|
|
235
235
|
filtered_to_original_map = [];
|
|
236
236
|
}
|
|
237
237
|
let previous_headers = _headers.map((h) => h.value);
|
|
238
|
-
let previous_data = data.map((row) => row.map((cell) =>
|
|
238
|
+
let previous_data = data.map((row) => row.map((cell) => cell.value));
|
|
239
239
|
$: {
|
|
240
240
|
if (data || _headers) {
|
|
241
241
|
df_actions.trigger_change(
|
|
242
|
-
data
|
|
243
|
-
(row, rowIdx) => row.map((cell, colIdx) => {
|
|
244
|
-
const dtype = Array.isArray(datatype) ? datatype[colIdx] : datatype;
|
|
245
|
-
return {
|
|
246
|
-
...cell,
|
|
247
|
-
value: cast_value_to_type(cell.value, dtype)
|
|
248
|
-
};
|
|
249
|
-
})
|
|
250
|
-
),
|
|
242
|
+
data,
|
|
251
243
|
_headers,
|
|
252
244
|
previous_data,
|
|
253
245
|
previous_headers,
|
|
254
246
|
value_is_output,
|
|
255
247
|
dispatch
|
|
256
248
|
);
|
|
257
|
-
previous_data = data.map((row) => row.map((cell) =>
|
|
249
|
+
previous_data = data.map((row) => row.map((cell) => cell.value));
|
|
258
250
|
previous_headers = _headers.map((h) => h.value);
|
|
259
251
|
}
|
|
260
252
|
}
|
|
@@ -2,14 +2,15 @@ import { SvelteComponent } from "svelte";
|
|
|
2
2
|
import type { SelectData } from "@gradio/utils";
|
|
3
3
|
import type { I18nFormatter } from "js/core/src/gradio_helper";
|
|
4
4
|
import { type Client } from "@gradio/client";
|
|
5
|
-
import type { Headers, DataframeValue, Datatype } from "./utils/utils";
|
|
5
|
+
import type { Headers, DataframeValue, Datatype, EditData } from "./utils/utils";
|
|
6
|
+
import type { CellValue } from "./types";
|
|
6
7
|
declare const __propDef: {
|
|
7
8
|
props: {
|
|
8
9
|
datatype: Datatype | Datatype[];
|
|
9
10
|
label?: string | null;
|
|
10
11
|
show_label?: boolean;
|
|
11
12
|
headers?: Headers;
|
|
12
|
-
values?:
|
|
13
|
+
values?: CellValue[][];
|
|
13
14
|
col_count: [number, "fixed" | "dynamic"];
|
|
14
15
|
row_count: [number, "fixed" | "dynamic"];
|
|
15
16
|
latex_delimiters: {
|
|
@@ -46,6 +47,7 @@ declare const __propDef: {
|
|
|
46
47
|
input: CustomEvent<undefined>;
|
|
47
48
|
select: CustomEvent<SelectData>;
|
|
48
49
|
search: CustomEvent<string | null>;
|
|
50
|
+
edit: CustomEvent<EditData>;
|
|
49
51
|
} & {
|
|
50
52
|
[evt: string]: CustomEvent<any>;
|
|
51
53
|
};
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { SvelteComponent } from "svelte";
|
|
2
2
|
import type { I18nFormatter } from "js/core/src/gradio_helper";
|
|
3
3
|
import type { Datatype } from "./utils/utils";
|
|
4
|
+
import type { CellValue } from "./types";
|
|
4
5
|
declare const __propDef: {
|
|
5
6
|
props: {
|
|
6
|
-
value:
|
|
7
|
+
value: CellValue;
|
|
7
8
|
index: number;
|
|
8
9
|
j: number;
|
|
9
10
|
actual_pinned_columns: number;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { writable } from "svelte/store";
|
|
2
|
+
import type { CellValue } from "../types";
|
|
2
3
|
import { get_next_cell_coordinates, get_range_selection, move_cursor } from "../utils/selection_utils";
|
|
3
4
|
export declare const DATAFRAME_KEY: unique symbol;
|
|
4
5
|
export type SortDirection = "asc" | "desc";
|
|
@@ -18,7 +19,7 @@ interface DataFrameState {
|
|
|
18
19
|
max_height: number;
|
|
19
20
|
column_widths: string[];
|
|
20
21
|
max_chars?: number;
|
|
21
|
-
static_columns?:
|
|
22
|
+
static_columns?: CellValue[];
|
|
22
23
|
};
|
|
23
24
|
current_search_query: string | null;
|
|
24
25
|
sort_state: {
|
|
@@ -30,7 +31,7 @@ interface DataFrameState {
|
|
|
30
31
|
initial_data: {
|
|
31
32
|
data: {
|
|
32
33
|
id: string;
|
|
33
|
-
value:
|
|
34
|
+
value: CellValue;
|
|
34
35
|
}[][];
|
|
35
36
|
display_value: string[][] | null;
|
|
36
37
|
styling: string[][] | null;
|
|
@@ -46,7 +47,7 @@ interface DataFrameState {
|
|
|
46
47
|
initial_data: {
|
|
47
48
|
data: {
|
|
48
49
|
id: string;
|
|
49
|
-
value:
|
|
50
|
+
value: CellValue;
|
|
50
51
|
}[][];
|
|
51
52
|
display_value: string[][] | null;
|
|
52
53
|
styling: string[][] | null;
|
|
@@ -105,7 +106,7 @@ interface DataFrameActions {
|
|
|
105
106
|
data: any[][];
|
|
106
107
|
headers: string[];
|
|
107
108
|
};
|
|
108
|
-
trigger_change: (data: any[][], headers: any[], previous_data:
|
|
109
|
+
trigger_change: (data: any[][], headers: any[], previous_data: any[][], previous_headers: string[], value_is_output: boolean, dispatch: (e: "change" | "input" | "edit", detail?: any) => void) => Promise<void>;
|
|
109
110
|
reset_sort_state: () => void;
|
|
110
111
|
reset_filter_state: () => void;
|
|
111
112
|
set_active_cell_menu: (menu: {
|
|
@@ -169,10 +170,10 @@ export interface DataFrameContext {
|
|
|
169
170
|
input: HTMLTextAreaElement | null;
|
|
170
171
|
}>;
|
|
171
172
|
parent_element?: HTMLElement;
|
|
172
|
-
get_data_at?: (row: number, col: number) =>
|
|
173
|
-
get_column?: (col: number) =>
|
|
174
|
-
get_row?: (row: number) =>
|
|
175
|
-
dispatch?: (e: "change" | "select" | "search", detail?: any) => void;
|
|
173
|
+
get_data_at?: (row: number, col: number) => CellValue;
|
|
174
|
+
get_column?: (col: number) => CellValue[];
|
|
175
|
+
get_row?: (row: number) => CellValue[];
|
|
176
|
+
dispatch?: (e: "change" | "select" | "search" | "edit", detail?: any) => void;
|
|
176
177
|
}
|
|
177
178
|
export declare function create_dataframe_context(config: DataFrameState["config"]): DataFrameContext;
|
|
178
179
|
export declare function get_dataframe_context(): DataFrameContext;
|
|
@@ -152,7 +152,7 @@ function create_actions(state, context) {
|
|
|
152
152
|
if (s.current_search_query)
|
|
153
153
|
return;
|
|
154
154
|
const current_headers = headers.map((h) => h.value);
|
|
155
|
-
const current_data = data.map((row) => row.map((cell) =>
|
|
155
|
+
const current_data = data.map((row) => row.map((cell) => cell.value));
|
|
156
156
|
if (!dequal(current_data, previous_data) ||
|
|
157
157
|
!dequal(current_headers, previous_headers)) {
|
|
158
158
|
if (!dequal(current_headers, previous_headers)) {
|
|
@@ -166,6 +166,14 @@ function create_actions(state, context) {
|
|
|
166
166
|
headers: current_headers,
|
|
167
167
|
metadata: null
|
|
168
168
|
});
|
|
169
|
+
const index = s.ui_state.selected;
|
|
170
|
+
if (index) {
|
|
171
|
+
dispatch("edit", {
|
|
172
|
+
index,
|
|
173
|
+
value: data[index[0]][index[1]].value,
|
|
174
|
+
previous_value: previous_data[index[0]][index[1]]
|
|
175
|
+
});
|
|
176
|
+
}
|
|
169
177
|
if (!value_is_output)
|
|
170
178
|
dispatch("input");
|
|
171
179
|
}
|
package/dist/shared/types.d.ts
CHANGED
|
@@ -5,9 +5,10 @@ export interface HeadersWithIDs {
|
|
|
5
5
|
id: string;
|
|
6
6
|
value: string;
|
|
7
7
|
}
|
|
8
|
+
export type CellValue = string | number | boolean;
|
|
8
9
|
export interface TableCell {
|
|
9
10
|
id: string;
|
|
10
|
-
value:
|
|
11
|
+
value: CellValue;
|
|
11
12
|
}
|
|
12
13
|
export type TableData = TableCell[][];
|
|
13
14
|
export type CountConfig = [number, "fixed" | "dynamic"];
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import type { Headers, HeadersWithIDs } from "./utils";
|
|
1
|
+
import type { Datatype, Headers, HeadersWithIDs } from "./utils";
|
|
2
|
+
import type { CellValue } from "../types";
|
|
2
3
|
export declare function make_headers(_head: Headers, col_count: [number, "fixed" | "dynamic"], els: Record<string, {
|
|
3
4
|
cell: null | HTMLTableCellElement;
|
|
4
5
|
input: null | HTMLTextAreaElement;
|
|
5
6
|
}>, make_id: () => string): HeadersWithIDs;
|
|
6
|
-
export declare function process_data(values:
|
|
7
|
+
export declare function process_data(values: CellValue[][], els: Record<string, {
|
|
7
8
|
cell: null | HTMLTableCellElement;
|
|
8
9
|
input: null | HTMLTextAreaElement;
|
|
9
|
-
}>, data_binding: Record<string, any>, make_id: () => string, display_value
|
|
10
|
+
}>, data_binding: Record<string, any>, make_id: () => string, display_value: (string[][] | null) | undefined, datatype: Datatype | Datatype[]): {
|
|
10
11
|
id: string;
|
|
11
|
-
value:
|
|
12
|
+
value: CellValue;
|
|
12
13
|
display_value?: string;
|
|
13
14
|
}[][];
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { cast_value_to_type } from "./utils";
|
|
1
2
|
export function make_headers(_head, col_count, els, make_id) {
|
|
2
3
|
let _h = _head || [];
|
|
3
4
|
if (col_count[1] === "fixed" && _h.length < col_count[0]) {
|
|
@@ -21,7 +22,7 @@ export function make_headers(_head, col_count, els, make_id) {
|
|
|
21
22
|
return { id: _id, value: h ?? "" };
|
|
22
23
|
});
|
|
23
24
|
}
|
|
24
|
-
export function process_data(values, els, data_binding, make_id, display_value = null) {
|
|
25
|
+
export function process_data(values, els, data_binding, make_id, display_value = null, datatype) {
|
|
25
26
|
if (!values || values.length === 0) {
|
|
26
27
|
return [];
|
|
27
28
|
}
|
|
@@ -34,9 +35,10 @@ export function process_data(values, els, data_binding, make_id, display_value =
|
|
|
34
35
|
if (display === undefined) {
|
|
35
36
|
display = String(value);
|
|
36
37
|
}
|
|
38
|
+
const dtype = Array.isArray(datatype) ? datatype[j] : datatype;
|
|
37
39
|
return {
|
|
38
40
|
id: _id,
|
|
39
|
-
value,
|
|
41
|
+
value: cast_value_to_type(value, dtype),
|
|
40
42
|
display_value: display
|
|
41
43
|
};
|
|
42
44
|
});
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import type { CellValue } from "../types";
|
|
1
2
|
export type FilterDatatype = "string" | "number";
|
|
2
3
|
export declare function filter_data(data: {
|
|
3
4
|
id: string;
|
|
4
|
-
value:
|
|
5
|
+
value: CellValue;
|
|
5
6
|
}[][], filter_columns: {
|
|
6
7
|
col: number;
|
|
7
8
|
datatype: FilterDatatype;
|
|
@@ -10,7 +11,7 @@ export declare function filter_data(data: {
|
|
|
10
11
|
}[]): number[];
|
|
11
12
|
export declare function filter_data_and_preserve_selection(data: {
|
|
12
13
|
id: string;
|
|
13
|
-
value:
|
|
14
|
+
value: CellValue;
|
|
14
15
|
}[][], display_value: string[][] | null, styling: string[][] | null, filter_columns: {
|
|
15
16
|
col: number;
|
|
16
17
|
datatype: FilterDatatype;
|
|
@@ -18,10 +19,10 @@ export declare function filter_data_and_preserve_selection(data: {
|
|
|
18
19
|
value: string;
|
|
19
20
|
}[], selected: [number, number] | false, get_current_indices: (id: string, data: {
|
|
20
21
|
id: string;
|
|
21
|
-
value:
|
|
22
|
+
value: CellValue;
|
|
22
23
|
}[][]) => [number, number], original_data?: {
|
|
23
24
|
id: string;
|
|
24
|
-
value:
|
|
25
|
+
value: CellValue;
|
|
25
26
|
}[][], original_display_value?: string[][] | null, original_styling?: string[][] | null): {
|
|
26
27
|
data: typeof data;
|
|
27
28
|
selected: [number, number] | false;
|
|
@@ -26,7 +26,7 @@ export async function handle_cell_blur(event, ctx, coords) {
|
|
|
26
26
|
const input_el = event.target;
|
|
27
27
|
if (!input_el || input_el.value === undefined)
|
|
28
28
|
return;
|
|
29
|
-
await save_cell_value(input_el.
|
|
29
|
+
await save_cell_value(input_el.value, ctx, coords[0], coords[1]);
|
|
30
30
|
}
|
|
31
31
|
function handle_header_navigation(event, ctx) {
|
|
32
32
|
const state = get(ctx.state);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { CellCoordinate } from "./../types";
|
|
1
|
+
import type { CellCoordinate, CellValue } from "./../types";
|
|
2
2
|
export type CellData = {
|
|
3
3
|
id: string;
|
|
4
|
-
value:
|
|
4
|
+
value: CellValue;
|
|
5
5
|
};
|
|
6
6
|
export declare function is_cell_in_selection(coords: [number, number], selected_cells: [number, number][]): boolean;
|
|
7
7
|
export declare function is_cell_selected(cell: CellCoordinate, selected_cells: CellCoordinate[]): string;
|
|
@@ -21,7 +21,7 @@ export declare function select_column(data: any[][], col: number): CellCoordinat
|
|
|
21
21
|
export declare function select_row(data: any[][], row: number): CellCoordinate[];
|
|
22
22
|
export declare function calculate_selection_positions(selected: CellCoordinate, data: {
|
|
23
23
|
id: string;
|
|
24
|
-
value:
|
|
24
|
+
value: CellValue;
|
|
25
25
|
}[][], els: Record<string, {
|
|
26
26
|
cell: HTMLTableCellElement | null;
|
|
27
27
|
}>, parent: HTMLElement, table: HTMLElement): {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Headers } from "../types";
|
|
1
|
+
import type { Headers, CellValue } from "../types";
|
|
2
2
|
export type SortDirection = "asc" | "desc";
|
|
3
3
|
export declare function get_sort_status(name: string, sort_columns: {
|
|
4
4
|
col: number;
|
|
@@ -6,20 +6,20 @@ export declare function get_sort_status(name: string, sort_columns: {
|
|
|
6
6
|
}[], headers: Headers): "none" | "asc" | "desc";
|
|
7
7
|
export declare function sort_data(data: {
|
|
8
8
|
id: string;
|
|
9
|
-
value:
|
|
9
|
+
value: CellValue;
|
|
10
10
|
}[][], sort_columns: {
|
|
11
11
|
col: number;
|
|
12
12
|
direction: SortDirection;
|
|
13
13
|
}[]): number[];
|
|
14
14
|
export declare function sort_data_and_preserve_selection(data: {
|
|
15
15
|
id: string;
|
|
16
|
-
value:
|
|
16
|
+
value: CellValue;
|
|
17
17
|
}[][], display_value: string[][] | null, styling: string[][] | null, sort_columns: {
|
|
18
18
|
col: number;
|
|
19
19
|
direction: SortDirection;
|
|
20
20
|
}[], selected: [number, number] | false, get_current_indices: (id: string, data: {
|
|
21
21
|
id: string;
|
|
22
|
-
value:
|
|
22
|
+
value: CellValue;
|
|
23
23
|
}[][]) => [number, number]): {
|
|
24
24
|
data: typeof data;
|
|
25
25
|
selected: [number, number] | false;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Headers, HeadersWithIDs, TableCell, TableData } from "../types";
|
|
1
|
+
import type { CellValue, Headers, HeadersWithIDs, TableCell, TableData } from "../types";
|
|
2
2
|
import type { SortDirection } from "./sort_utils";
|
|
3
3
|
import type { FilterDatatype } from "./filter_utils";
|
|
4
4
|
export declare function make_cell_id(row: number, col: number): string;
|
|
@@ -17,4 +17,4 @@ export declare function filter_table_data(data: TableData, display_value: string
|
|
|
17
17
|
export declare function copy_table_data(data: TableData, selected_cells: [number, number][] | null): Promise<void>;
|
|
18
18
|
export declare function guess_delimiter(text: string, possibleDelimiters: string[]): string[];
|
|
19
19
|
export declare function data_uri_to_blob(data_uri: string): Blob;
|
|
20
|
-
export declare function handle_file_upload(data_uri: string, update_headers: (headers: Headers) => HeadersWithIDs[], update_values: (values:
|
|
20
|
+
export declare function handle_file_upload(data_uri: string, update_headers: (headers: Headers) => HeadersWithIDs[], update_values: (values: CellValue[][]) => void): void;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import type { CellValue } from "../types";
|
|
1
2
|
export type Headers = string[];
|
|
2
|
-
export type Data =
|
|
3
|
+
export type Data = CellValue[][];
|
|
3
4
|
export type Datatype = "str" | "number" | "bool" | "date" | "markdown" | "html" | "image";
|
|
4
5
|
export type Metadata = {
|
|
5
6
|
[key: string]: string[][] | null;
|
|
@@ -19,4 +20,9 @@ export type DataframeValue = {
|
|
|
19
20
|
* @param t - The type to coerce to.
|
|
20
21
|
* @returns The coerced value.
|
|
21
22
|
*/
|
|
22
|
-
export declare function cast_value_to_type(v: any, t: Datatype):
|
|
23
|
+
export declare function cast_value_to_type(v: any, t: Datatype): CellValue;
|
|
24
|
+
export interface EditData {
|
|
25
|
+
index: number | [number, number];
|
|
26
|
+
value: string;
|
|
27
|
+
previous_value: string;
|
|
28
|
+
}
|
|
@@ -15,7 +15,7 @@ export let value = {
|
|
|
15
15
|
metadata: null
|
|
16
16
|
};
|
|
17
17
|
export let datatype = "str";
|
|
18
|
-
export let
|
|
18
|
+
export let interactive = true;
|
|
19
19
|
export let show_row_numbers = false;
|
|
20
20
|
export let max_height = 500;
|
|
21
21
|
export let show_search = "none";
|
|
@@ -68,7 +68,7 @@ onMount(() => {
|
|
|
68
68
|
display_value={value?.metadata?.display_value}
|
|
69
69
|
styling={value?.metadata?.styling}
|
|
70
70
|
{datatype}
|
|
71
|
-
{
|
|
71
|
+
editable={interactive}
|
|
72
72
|
{show_row_numbers}
|
|
73
73
|
{max_height}
|
|
74
74
|
{show_search}
|
|
@@ -6,7 +6,7 @@ declare const __propDef: {
|
|
|
6
6
|
i18n?: I18nFormatter | undefined;
|
|
7
7
|
value?: DataframeValue;
|
|
8
8
|
datatype?: Datatype | Datatype[];
|
|
9
|
-
|
|
9
|
+
interactive?: boolean;
|
|
10
10
|
show_row_numbers?: boolean;
|
|
11
11
|
max_height?: number;
|
|
12
12
|
show_search?: "none" | "search" | "filter";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gradio/dataframe",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.20.0",
|
|
4
4
|
"description": "Gradio UI packages",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "",
|
|
@@ -16,12 +16,12 @@
|
|
|
16
16
|
"@gradio/atoms": "^0.18.0",
|
|
17
17
|
"@gradio/button": "^0.5.13",
|
|
18
18
|
"@gradio/icons": "^0.14.0",
|
|
19
|
-
"@gradio/
|
|
19
|
+
"@gradio/markdown-code": "^0.5.2",
|
|
20
20
|
"@gradio/checkbox": "^0.4.30",
|
|
21
|
-
"@gradio/
|
|
21
|
+
"@gradio/statustracker": "^0.11.1",
|
|
22
22
|
"@gradio/upload": "^0.17.0",
|
|
23
|
-
"@gradio/
|
|
24
|
-
"@gradio/
|
|
23
|
+
"@gradio/utils": "^0.10.2",
|
|
24
|
+
"@gradio/client": "^1.19.0"
|
|
25
25
|
},
|
|
26
26
|
"exports": {
|
|
27
27
|
".": {
|
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { BaseCheckbox } from "@gradio/checkbox";
|
|
3
3
|
|
|
4
|
-
export let value
|
|
4
|
+
export let value = false;
|
|
5
5
|
export let editable = true;
|
|
6
6
|
export let on_change: (value: boolean) => void;
|
|
7
7
|
|
|
8
|
-
$: bool_value =
|
|
9
|
-
typeof value === "string" ? value.toLowerCase() === "true" : !!value;
|
|
10
|
-
|
|
11
8
|
function handle_change(event: CustomEvent<boolean>): void {
|
|
12
9
|
if (editable) {
|
|
13
10
|
on_change(event.detail);
|
|
@@ -17,7 +14,7 @@
|
|
|
17
14
|
|
|
18
15
|
<div class="bool-cell" role="button" tabindex="-1">
|
|
19
16
|
<BaseCheckbox
|
|
20
|
-
bind:value
|
|
17
|
+
bind:value
|
|
21
18
|
label=""
|
|
22
19
|
interactive={editable}
|
|
23
20
|
on:change={handle_change}
|
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
import { createEventDispatcher } from "svelte";
|
|
3
3
|
import { MarkdownCode } from "@gradio/markdown-code";
|
|
4
4
|
import type { I18nFormatter } from "@gradio/utils";
|
|
5
|
+
import type { CellValue } from "./types";
|
|
5
6
|
import SelectionButtons from "./icons/SelectionButtons.svelte";
|
|
6
7
|
import BooleanCell from "./BooleanCell.svelte";
|
|
7
8
|
|
|
8
9
|
export let edit: boolean;
|
|
9
|
-
export let value:
|
|
10
|
+
export let value: CellValue = "";
|
|
10
11
|
export let display_value: string | null = null;
|
|
11
12
|
export let styling = "";
|
|
12
13
|
export let header = false;
|
|
@@ -44,7 +45,7 @@
|
|
|
44
45
|
}>();
|
|
45
46
|
|
|
46
47
|
function truncate_text(
|
|
47
|
-
text:
|
|
48
|
+
text: CellValue,
|
|
48
49
|
max_length: number | null = null,
|
|
49
50
|
is_image = false
|
|
50
51
|
): string {
|
|
@@ -86,18 +87,13 @@
|
|
|
86
87
|
dispatch("keydown", event);
|
|
87
88
|
}
|
|
88
89
|
|
|
89
|
-
function
|
|
90
|
-
value
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
value: new_value.toString()
|
|
97
|
-
}
|
|
98
|
-
} as unknown as FocusEvent,
|
|
99
|
-
coords: coords
|
|
100
|
-
});
|
|
90
|
+
function commit_change(checked: boolean): void {
|
|
91
|
+
handle_blur({ target: { value } } as unknown as FocusEvent);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
$: if (!edit) {
|
|
95
|
+
// Shim blur on removal for Safari and Firefox
|
|
96
|
+
handle_blur({ target: { value } } as unknown as FocusEvent);
|
|
101
97
|
}
|
|
102
98
|
</script>
|
|
103
99
|
|
|
@@ -118,12 +114,8 @@
|
|
|
118
114
|
/>
|
|
119
115
|
{/if}
|
|
120
116
|
|
|
121
|
-
{#if datatype === "bool"}
|
|
122
|
-
<BooleanCell
|
|
123
|
-
value={String(display_content)}
|
|
124
|
-
{editable}
|
|
125
|
-
on_change={handle_bool_change}
|
|
126
|
-
/>
|
|
117
|
+
{#if datatype === "bool" && typeof value === "boolean"}
|
|
118
|
+
<BooleanCell bind:value {editable} on_change={commit_change} />
|
|
127
119
|
{:else}
|
|
128
120
|
<span
|
|
129
121
|
class:dragging={is_dragging}
|
package/shared/Table.svelte
CHANGED
|
@@ -20,10 +20,15 @@
|
|
|
20
20
|
import type { I18nFormatter } from "js/core/src/gradio_helper";
|
|
21
21
|
import { type Client } from "@gradio/client";
|
|
22
22
|
import VirtualTable from "./VirtualTable.svelte";
|
|
23
|
-
import type {
|
|
23
|
+
import type {
|
|
24
|
+
Headers,
|
|
25
|
+
DataframeValue,
|
|
26
|
+
Datatype,
|
|
27
|
+
EditData
|
|
28
|
+
} from "./utils/utils";
|
|
24
29
|
import CellMenu from "./CellMenu.svelte";
|
|
25
30
|
import Toolbar from "./Toolbar.svelte";
|
|
26
|
-
import type { CellCoordinate } from "./types";
|
|
31
|
+
import type { CellCoordinate, CellValue } from "./types";
|
|
27
32
|
import {
|
|
28
33
|
is_cell_selected,
|
|
29
34
|
should_show_cell_menu,
|
|
@@ -37,7 +42,6 @@
|
|
|
37
42
|
handle_file_upload
|
|
38
43
|
} from "./utils/table_utils";
|
|
39
44
|
import { make_headers, process_data } from "./utils/data_processing";
|
|
40
|
-
import { cast_value_to_type } from "./utils/utils";
|
|
41
45
|
import { handle_keydown, handle_cell_blur } from "./utils/keyboard_utils";
|
|
42
46
|
import {
|
|
43
47
|
create_drag_handlers,
|
|
@@ -51,7 +55,7 @@
|
|
|
51
55
|
export let label: string | null = null;
|
|
52
56
|
export let show_label = true;
|
|
53
57
|
export let headers: Headers = [];
|
|
54
|
-
export let values:
|
|
58
|
+
export let values: CellValue[][] = [];
|
|
55
59
|
export let col_count: [number, "fixed" | "dynamic"];
|
|
56
60
|
export let row_count: [number, "fixed" | "dynamic"];
|
|
57
61
|
export let latex_delimiters: {
|
|
@@ -163,6 +167,7 @@
|
|
|
163
167
|
input: undefined;
|
|
164
168
|
select: SelectData;
|
|
165
169
|
search: string | null;
|
|
170
|
+
edit: EditData;
|
|
166
171
|
}>();
|
|
167
172
|
|
|
168
173
|
let els: Record<
|
|
@@ -172,12 +177,11 @@
|
|
|
172
177
|
let data_binding: Record<string, (typeof data)[0][0]> = {};
|
|
173
178
|
let _headers = make_headers(headers, col_count, els, make_id);
|
|
174
179
|
let old_headers: string[] = headers;
|
|
175
|
-
let data: { id: string; value:
|
|
176
|
-
|
|
177
|
-
let old_val: undefined | (string | number)[][] = undefined;
|
|
180
|
+
let data: { id: string; value: CellValue; display_value?: string }[][] = [[]];
|
|
181
|
+
let old_val: undefined | CellValue[][] = undefined;
|
|
178
182
|
let search_results: {
|
|
179
183
|
id: string;
|
|
180
|
-
value:
|
|
184
|
+
value: CellValue;
|
|
181
185
|
display_value?: string;
|
|
182
186
|
styling?: string;
|
|
183
187
|
}[][] = [[]];
|
|
@@ -196,13 +200,13 @@
|
|
|
196
200
|
);
|
|
197
201
|
});
|
|
198
202
|
|
|
199
|
-
const get_data_at = (row: number, col: number):
|
|
203
|
+
const get_data_at = (row: number, col: number): CellValue =>
|
|
200
204
|
data?.[row]?.[col]?.value;
|
|
201
205
|
|
|
202
|
-
const get_column = (col: number):
|
|
206
|
+
const get_column = (col: number): CellValue[] =>
|
|
203
207
|
data?.map((row) => row[col]?.value) ?? [];
|
|
204
208
|
|
|
205
|
-
const get_row = (row: number):
|
|
209
|
+
const get_row = (row: number): CellValue[] =>
|
|
206
210
|
data?.[row]?.map((cell) => cell.value) ?? [];
|
|
207
211
|
|
|
208
212
|
$: {
|
|
@@ -248,13 +252,14 @@
|
|
|
248
252
|
(values[0] && old_val[0] && values[0].length !== old_val[0].length));
|
|
249
253
|
|
|
250
254
|
data = process_data(
|
|
251
|
-
values as
|
|
255
|
+
values as CellValue[][],
|
|
252
256
|
els,
|
|
253
257
|
data_binding,
|
|
254
258
|
make_id,
|
|
255
|
-
display_value
|
|
259
|
+
display_value,
|
|
260
|
+
datatype
|
|
256
261
|
);
|
|
257
|
-
old_val = JSON.parse(JSON.stringify(values)) as
|
|
262
|
+
old_val = JSON.parse(JSON.stringify(values)) as CellValue[][];
|
|
258
263
|
|
|
259
264
|
if (is_reset || is_different_structure) {
|
|
260
265
|
df_actions.reset_sort_state();
|
|
@@ -326,27 +331,19 @@
|
|
|
326
331
|
}
|
|
327
332
|
|
|
328
333
|
let previous_headers = _headers.map((h) => h.value);
|
|
329
|
-
let previous_data = data.map((row) => row.map((cell) =>
|
|
334
|
+
let previous_data = data.map((row) => row.map((cell) => cell.value));
|
|
330
335
|
|
|
331
336
|
$: {
|
|
332
337
|
if (data || _headers) {
|
|
333
338
|
df_actions.trigger_change(
|
|
334
|
-
data
|
|
335
|
-
row.map((cell, colIdx) => {
|
|
336
|
-
const dtype = Array.isArray(datatype) ? datatype[colIdx] : datatype;
|
|
337
|
-
return {
|
|
338
|
-
...cell,
|
|
339
|
-
value: cast_value_to_type(cell.value, dtype)
|
|
340
|
-
};
|
|
341
|
-
})
|
|
342
|
-
),
|
|
339
|
+
data,
|
|
343
340
|
_headers,
|
|
344
341
|
previous_data,
|
|
345
342
|
previous_headers,
|
|
346
343
|
value_is_output,
|
|
347
344
|
dispatch
|
|
348
345
|
);
|
|
349
|
-
previous_data = data.map((row) => row.map((cell) =>
|
|
346
|
+
previous_data = data.map((row) => row.map((cell) => cell.value));
|
|
350
347
|
previous_headers = _headers.map((h) => h.value);
|
|
351
348
|
}
|
|
352
349
|
}
|
|
@@ -675,12 +672,12 @@
|
|
|
675
672
|
|
|
676
673
|
function commit_filter(): void {
|
|
677
674
|
if ($df_state.current_search_query && show_search === "filter") {
|
|
678
|
-
const filtered_data:
|
|
675
|
+
const filtered_data: CellValue[][] = [];
|
|
679
676
|
const filtered_display_values: string[][] = [];
|
|
680
677
|
const filtered_styling: string[][] = [];
|
|
681
678
|
|
|
682
679
|
search_results.forEach((row) => {
|
|
683
|
-
const data_row:
|
|
680
|
+
const data_row: CellValue[] = [];
|
|
684
681
|
const display_row: string[] = [];
|
|
685
682
|
const styling_row: string[] = [];
|
|
686
683
|
|
package/shared/TableCell.svelte
CHANGED
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
import CellMenuButton from "./CellMenuButton.svelte";
|
|
4
4
|
import type { I18nFormatter } from "js/core/src/gradio_helper";
|
|
5
5
|
import type { Datatype } from "./utils/utils";
|
|
6
|
+
import type { CellValue } from "./types";
|
|
6
7
|
import { is_cell_in_selection } from "./utils/selection_utils";
|
|
7
8
|
|
|
8
|
-
export let value:
|
|
9
|
+
export let value: CellValue;
|
|
9
10
|
export let index: number;
|
|
10
11
|
export let j: number;
|
|
11
12
|
export let actual_pinned_columns: number;
|
|
@@ -2,6 +2,7 @@ import { getContext, setContext } from "svelte";
|
|
|
2
2
|
import { dequal } from "dequal";
|
|
3
3
|
import { writable, get } from "svelte/store";
|
|
4
4
|
import { sort_table_data } from "../utils/table_utils";
|
|
5
|
+
import type { CellValue } from "../types";
|
|
5
6
|
import { tick } from "svelte";
|
|
6
7
|
import {
|
|
7
8
|
handle_selection,
|
|
@@ -30,14 +31,14 @@ interface DataFrameState {
|
|
|
30
31
|
max_height: number;
|
|
31
32
|
column_widths: string[];
|
|
32
33
|
max_chars?: number;
|
|
33
|
-
static_columns?:
|
|
34
|
+
static_columns?: CellValue[];
|
|
34
35
|
};
|
|
35
36
|
current_search_query: string | null;
|
|
36
37
|
sort_state: {
|
|
37
38
|
sort_columns: { col: number; direction: SortDirection }[];
|
|
38
39
|
row_order: number[];
|
|
39
40
|
initial_data: {
|
|
40
|
-
data: { id: string; value:
|
|
41
|
+
data: { id: string; value: CellValue }[][];
|
|
41
42
|
display_value: string[][] | null;
|
|
42
43
|
styling: string[][] | null;
|
|
43
44
|
} | null;
|
|
@@ -50,7 +51,7 @@ interface DataFrameState {
|
|
|
50
51
|
value: string;
|
|
51
52
|
}[];
|
|
52
53
|
initial_data: {
|
|
53
|
-
data: { id: string; value:
|
|
54
|
+
data: { id: string; value: CellValue }[][];
|
|
54
55
|
display_value: string[][] | null;
|
|
55
56
|
styling: string[][] | null;
|
|
56
57
|
} | null;
|
|
@@ -124,10 +125,10 @@ interface DataFrameActions {
|
|
|
124
125
|
trigger_change: (
|
|
125
126
|
data: any[][],
|
|
126
127
|
headers: any[],
|
|
127
|
-
previous_data:
|
|
128
|
+
previous_data: any[][],
|
|
128
129
|
previous_headers: string[],
|
|
129
130
|
value_is_output: boolean,
|
|
130
|
-
dispatch: (e: "change" | "input", detail?: any) => void
|
|
131
|
+
dispatch: (e: "change" | "input" | "edit", detail?: any) => void
|
|
131
132
|
) => Promise<void>;
|
|
132
133
|
reset_sort_state: () => void;
|
|
133
134
|
reset_filter_state: () => void;
|
|
@@ -183,10 +184,10 @@ export interface DataFrameContext {
|
|
|
183
184
|
{ cell: HTMLTableCellElement | null; input: HTMLTextAreaElement | null }
|
|
184
185
|
>;
|
|
185
186
|
parent_element?: HTMLElement;
|
|
186
|
-
get_data_at?: (row: number, col: number) =>
|
|
187
|
-
get_column?: (col: number) =>
|
|
188
|
-
get_row?: (row: number) =>
|
|
189
|
-
dispatch?: (e: "change" | "select" | "search", detail?: any) => void;
|
|
187
|
+
get_data_at?: (row: number, col: number) => CellValue;
|
|
188
|
+
get_column?: (col: number) => CellValue[];
|
|
189
|
+
get_row?: (row: number) => CellValue[];
|
|
190
|
+
dispatch?: (e: "change" | "select" | "search" | "edit", detail?: any) => void;
|
|
190
191
|
}
|
|
191
192
|
|
|
192
193
|
function create_actions(
|
|
@@ -230,7 +231,7 @@ function create_actions(
|
|
|
230
231
|
};
|
|
231
232
|
|
|
232
233
|
const update_array = (
|
|
233
|
-
source: { id: string; value:
|
|
234
|
+
source: { id: string; value: CellValue }[][] | string[][] | null,
|
|
234
235
|
target: any[] | null | undefined
|
|
235
236
|
): void => {
|
|
236
237
|
if (source && target) {
|
|
@@ -397,9 +398,7 @@ function create_actions(
|
|
|
397
398
|
if (s.current_search_query) return;
|
|
398
399
|
|
|
399
400
|
const current_headers = headers.map((h) => h.value);
|
|
400
|
-
const current_data = data.map((row) =>
|
|
401
|
-
row.map((cell) => String(cell.value))
|
|
402
|
-
);
|
|
401
|
+
const current_data = data.map((row) => row.map((cell) => cell.value));
|
|
403
402
|
|
|
404
403
|
if (
|
|
405
404
|
!dequal(current_data, previous_data) ||
|
|
@@ -416,6 +415,14 @@ function create_actions(
|
|
|
416
415
|
headers: current_headers,
|
|
417
416
|
metadata: null
|
|
418
417
|
});
|
|
418
|
+
const index = s.ui_state.selected;
|
|
419
|
+
if (index) {
|
|
420
|
+
dispatch("edit", {
|
|
421
|
+
index,
|
|
422
|
+
value: data[index[0]][index[1]].value,
|
|
423
|
+
previous_value: previous_data[index[0]][index[1]]
|
|
424
|
+
});
|
|
425
|
+
}
|
|
419
426
|
if (!value_is_output) dispatch("input");
|
|
420
427
|
}
|
|
421
428
|
},
|
package/shared/types.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import type { Headers, HeadersWithIDs } from "./utils";
|
|
1
|
+
import type { Datatype, Headers, HeadersWithIDs } from "./utils";
|
|
2
|
+
import type { CellValue } from "../types";
|
|
3
|
+
import { cast_value_to_type } from "./utils";
|
|
2
4
|
|
|
3
5
|
export function make_headers(
|
|
4
6
|
_head: Headers,
|
|
@@ -35,15 +37,16 @@ export function make_headers(
|
|
|
35
37
|
}
|
|
36
38
|
|
|
37
39
|
export function process_data(
|
|
38
|
-
values:
|
|
40
|
+
values: CellValue[][],
|
|
39
41
|
els: Record<
|
|
40
42
|
string,
|
|
41
43
|
{ cell: null | HTMLTableCellElement; input: null | HTMLTextAreaElement }
|
|
42
44
|
>,
|
|
43
45
|
data_binding: Record<string, any>,
|
|
44
46
|
make_id: () => string,
|
|
45
|
-
display_value: string[][] | null = null
|
|
46
|
-
|
|
47
|
+
display_value: string[][] | null = null,
|
|
48
|
+
datatype: Datatype | Datatype[]
|
|
49
|
+
): { id: string; value: CellValue; display_value?: string }[][] {
|
|
47
50
|
if (!values || values.length === 0) {
|
|
48
51
|
return [];
|
|
49
52
|
}
|
|
@@ -60,9 +63,11 @@ export function process_data(
|
|
|
60
63
|
display = String(value);
|
|
61
64
|
}
|
|
62
65
|
|
|
66
|
+
const dtype = Array.isArray(datatype) ? datatype[j] : datatype;
|
|
67
|
+
|
|
63
68
|
return {
|
|
64
69
|
id: _id,
|
|
65
|
-
value,
|
|
70
|
+
value: cast_value_to_type(value, dtype),
|
|
66
71
|
display_value: display
|
|
67
72
|
};
|
|
68
73
|
});
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { filter_table_data } from "./table_utils";
|
|
2
|
+
import type { CellValue } from "../types";
|
|
2
3
|
|
|
3
4
|
export type FilterDatatype = "string" | "number";
|
|
4
5
|
|
|
5
6
|
export function filter_data(
|
|
6
|
-
data: { id: string; value:
|
|
7
|
+
data: { id: string; value: CellValue }[][],
|
|
7
8
|
filter_columns: {
|
|
8
9
|
col: number;
|
|
9
10
|
datatype: FilterDatatype;
|
|
@@ -164,7 +165,7 @@ export function filter_data(
|
|
|
164
165
|
}
|
|
165
166
|
|
|
166
167
|
export function filter_data_and_preserve_selection(
|
|
167
|
-
data: { id: string; value:
|
|
168
|
+
data: { id: string; value: CellValue }[][],
|
|
168
169
|
display_value: string[][] | null,
|
|
169
170
|
styling: string[][] | null,
|
|
170
171
|
filter_columns: {
|
|
@@ -176,9 +177,9 @@ export function filter_data_and_preserve_selection(
|
|
|
176
177
|
selected: [number, number] | false,
|
|
177
178
|
get_current_indices: (
|
|
178
179
|
id: string,
|
|
179
|
-
data: { id: string; value:
|
|
180
|
+
data: { id: string; value: CellValue }[][]
|
|
180
181
|
) => [number, number],
|
|
181
|
-
original_data?: { id: string; value:
|
|
182
|
+
original_data?: { id: string; value: CellValue }[][],
|
|
182
183
|
original_display_value?: string[][] | null,
|
|
183
184
|
original_styling?: string[][] | null
|
|
184
185
|
): { data: typeof data; selected: [number, number] | false } {
|
|
@@ -40,12 +40,7 @@ export async function handle_cell_blur(
|
|
|
40
40
|
const input_el = event.target as HTMLInputElement;
|
|
41
41
|
if (!input_el || input_el.value === undefined) return;
|
|
42
42
|
|
|
43
|
-
await save_cell_value(
|
|
44
|
-
input_el.type === "checkbox" ? String(input_el.checked) : input_el.value,
|
|
45
|
-
ctx,
|
|
46
|
-
coords[0],
|
|
47
|
-
coords[1]
|
|
48
|
-
);
|
|
43
|
+
await save_cell_value(input_el.value, ctx, coords[0], coords[1]);
|
|
49
44
|
}
|
|
50
45
|
|
|
51
46
|
function handle_header_navigation(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { CellCoordinate } from "./../types";
|
|
1
|
+
import type { CellCoordinate, CellValue } from "./../types";
|
|
2
2
|
|
|
3
|
-
export type CellData = { id: string; value:
|
|
3
|
+
export type CellData = { id: string; value: CellValue };
|
|
4
4
|
|
|
5
5
|
export function is_cell_in_selection(
|
|
6
6
|
coords: [number, number],
|
|
@@ -208,7 +208,7 @@ export function select_row(data: any[][], row: number): CellCoordinate[] {
|
|
|
208
208
|
|
|
209
209
|
export function calculate_selection_positions(
|
|
210
210
|
selected: CellCoordinate,
|
|
211
|
-
data: { id: string; value:
|
|
211
|
+
data: { id: string; value: CellValue }[][],
|
|
212
212
|
els: Record<string, { cell: HTMLTableCellElement | null }>,
|
|
213
213
|
parent: HTMLElement,
|
|
214
214
|
table: HTMLElement
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Headers } from "../types";
|
|
1
|
+
import type { Headers, CellValue } from "../types";
|
|
2
2
|
import { sort_table_data } from "./table_utils";
|
|
3
3
|
|
|
4
4
|
export type SortDirection = "asc" | "desc";
|
|
@@ -21,7 +21,7 @@ export function get_sort_status(
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
export function sort_data(
|
|
24
|
-
data: { id: string; value:
|
|
24
|
+
data: { id: string; value: CellValue }[][],
|
|
25
25
|
sort_columns: { col: number; direction: SortDirection }[]
|
|
26
26
|
): number[] {
|
|
27
27
|
if (!data || !data.length || !data[0]) {
|
|
@@ -64,14 +64,14 @@ export function sort_data(
|
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
export function sort_data_and_preserve_selection(
|
|
67
|
-
data: { id: string; value:
|
|
67
|
+
data: { id: string; value: CellValue }[][],
|
|
68
68
|
display_value: string[][] | null,
|
|
69
69
|
styling: string[][] | null,
|
|
70
70
|
sort_columns: { col: number; direction: SortDirection }[],
|
|
71
71
|
selected: [number, number] | false,
|
|
72
72
|
get_current_indices: (
|
|
73
73
|
id: string,
|
|
74
|
-
data: { id: string; value:
|
|
74
|
+
data: { id: string; value: CellValue }[][]
|
|
75
75
|
) => [number, number]
|
|
76
76
|
): { data: typeof data; selected: [number, number] | false } {
|
|
77
77
|
let id = null;
|
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
CellValue,
|
|
3
|
+
Headers,
|
|
4
|
+
HeadersWithIDs,
|
|
5
|
+
TableCell,
|
|
6
|
+
TableData
|
|
7
|
+
} from "../types";
|
|
2
8
|
import { sort_data } from "./sort_utils";
|
|
3
9
|
import { filter_data } from "./filter_utils";
|
|
4
10
|
import type { SortDirection } from "./sort_utils";
|
|
@@ -173,7 +179,7 @@ export function data_uri_to_blob(data_uri: string): Blob {
|
|
|
173
179
|
export function handle_file_upload(
|
|
174
180
|
data_uri: string,
|
|
175
181
|
update_headers: (headers: Headers) => HeadersWithIDs[],
|
|
176
|
-
update_values: (values:
|
|
182
|
+
update_values: (values: CellValue[][]) => void
|
|
177
183
|
): void {
|
|
178
184
|
const blob = data_uri_to_blob(data_uri);
|
|
179
185
|
const reader = new FileReader();
|
package/shared/utils/utils.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import type { CellValue } from "../types";
|
|
2
|
+
|
|
1
3
|
export type Headers = string[];
|
|
2
|
-
export type Data =
|
|
4
|
+
export type Data = CellValue[][];
|
|
3
5
|
|
|
4
6
|
export type Datatype =
|
|
5
7
|
| "str"
|
|
@@ -26,10 +28,7 @@ export type DataframeValue = {
|
|
|
26
28
|
* @param t - The type to coerce to.
|
|
27
29
|
* @returns The coerced value.
|
|
28
30
|
*/
|
|
29
|
-
export function cast_value_to_type(
|
|
30
|
-
v: any,
|
|
31
|
-
t: Datatype
|
|
32
|
-
): string | number | boolean {
|
|
31
|
+
export function cast_value_to_type(v: any, t: Datatype): CellValue {
|
|
33
32
|
if (t === "number") {
|
|
34
33
|
const n = Number(v);
|
|
35
34
|
return isNaN(n) ? v : n;
|
|
@@ -48,3 +47,9 @@ export function cast_value_to_type(
|
|
|
48
47
|
}
|
|
49
48
|
return v;
|
|
50
49
|
}
|
|
50
|
+
|
|
51
|
+
export interface EditData {
|
|
52
|
+
index: number | [number, number];
|
|
53
|
+
value: string;
|
|
54
|
+
previous_value: string;
|
|
55
|
+
}
|
package/standalone/Index.svelte
CHANGED
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
metadata: null
|
|
21
21
|
};
|
|
22
22
|
export let datatype: Datatype | Datatype[] = "str";
|
|
23
|
-
export let
|
|
23
|
+
export let interactive = true;
|
|
24
24
|
export let show_row_numbers = false;
|
|
25
25
|
export let max_height = 500;
|
|
26
26
|
export let show_search: "none" | "search" | "filter" = "none";
|
|
@@ -96,7 +96,7 @@
|
|
|
96
96
|
display_value={value?.metadata?.display_value}
|
|
97
97
|
styling={value?.metadata?.styling}
|
|
98
98
|
{datatype}
|
|
99
|
-
{
|
|
99
|
+
editable={interactive}
|
|
100
100
|
{show_row_numbers}
|
|
101
101
|
{max_height}
|
|
102
102
|
{show_search}
|