@gradio/dataframe 0.18.0 → 0.18.2
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 +22 -0
- package/dist/shared/EditableCell.svelte +16 -20
- package/dist/shared/EditableCell.svelte.d.ts +1 -2
- package/dist/shared/Table.svelte +2 -1
- package/dist/shared/TableCell.svelte.d.ts +1 -1
- package/dist/shared/TableHeader.svelte.d.ts +1 -1
- package/dist/shared/context/dataframe_context.d.ts +2 -1
- package/dist/shared/types.d.ts +1 -1
- package/dist/shared/utils/data_processing.d.ts +2 -2
- package/dist/shared/utils/keyboard_utils.js +10 -1
- package/package.json +9 -9
- package/shared/EditableCell.svelte +18 -25
- package/shared/Table.svelte +3 -2
- package/shared/TableCell.svelte +1 -1
- package/shared/TableHeader.svelte +1 -1
- package/shared/Toolbar.svelte +1 -1
- package/shared/context/dataframe_context.ts +2 -1
- package/shared/types.ts +1 -1
- package/shared/utils/data_processing.ts +2 -2
- package/shared/utils/keyboard_utils.ts +11 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# @gradio/dataframe
|
|
2
2
|
|
|
3
|
+
## 0.18.2
|
|
4
|
+
|
|
5
|
+
### Fixes
|
|
6
|
+
|
|
7
|
+
- [#11496](https://github.com/gradio-app/gradio/pull/11496) [`ee0da48`](https://github.com/gradio-app/gradio/commit/ee0da481446da5ffd79151a457cd3847db645bfb) - Prevent deletion of values in static columns. Thanks @hannahblair!
|
|
8
|
+
|
|
9
|
+
## 0.18.1
|
|
10
|
+
|
|
11
|
+
### Fixes
|
|
12
|
+
|
|
13
|
+
- [#11436](https://github.com/gradio-app/gradio/pull/11436) [`f49b8da`](https://github.com/gradio-app/gradio/commit/f49b8da1c062dbd81acb8e7fdcdc9a09a272d02f) - Multi-Line DataFrame Editing. Thanks @deckar01!
|
|
14
|
+
|
|
15
|
+
### Dependency updates
|
|
16
|
+
|
|
17
|
+
- @gradio/atoms@0.16.3
|
|
18
|
+
- @gradio/statustracker@0.10.14
|
|
19
|
+
- @gradio/upload@0.16.10
|
|
20
|
+
- @gradio/client@1.15.5
|
|
21
|
+
- @gradio/markdown-code@0.5.0
|
|
22
|
+
- @gradio/button@0.5.6
|
|
23
|
+
- @gradio/checkbox@0.4.25
|
|
24
|
+
|
|
3
25
|
## 0.18.0
|
|
4
26
|
|
|
5
27
|
### Features
|
|
@@ -23,7 +23,6 @@ export let on_select_column = null;
|
|
|
23
23
|
export let on_select_row = null;
|
|
24
24
|
export let el;
|
|
25
25
|
const dispatch = createEventDispatcher();
|
|
26
|
-
let is_expanded = false;
|
|
27
26
|
function truncate_text(text, max_length = null, is_image = false) {
|
|
28
27
|
if (is_image)
|
|
29
28
|
return String(text);
|
|
@@ -35,7 +34,7 @@ function truncate_text(text, max_length = null, is_image = false) {
|
|
|
35
34
|
return str.slice(0, max_length) + "...";
|
|
36
35
|
}
|
|
37
36
|
$:
|
|
38
|
-
should_truncate = !edit &&
|
|
37
|
+
should_truncate = !edit && max_chars !== null && max_chars > 0;
|
|
39
38
|
$:
|
|
40
39
|
display_content = editable ? value : display_value !== null ? display_value : value;
|
|
41
40
|
$:
|
|
@@ -53,18 +52,8 @@ function handle_blur(event) {
|
|
|
53
52
|
});
|
|
54
53
|
}
|
|
55
54
|
function handle_keydown(event) {
|
|
56
|
-
if (event.key === "Enter") {
|
|
57
|
-
if (!header) {
|
|
58
|
-
is_expanded = !is_expanded;
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
55
|
dispatch("keydown", event);
|
|
62
56
|
}
|
|
63
|
-
function handle_click() {
|
|
64
|
-
if (!edit && !header) {
|
|
65
|
-
is_expanded = !is_expanded;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
57
|
function handle_bool_change(new_value) {
|
|
69
58
|
value = new_value.toString();
|
|
70
59
|
dispatch("blur", {
|
|
@@ -81,10 +70,9 @@ function handle_bool_change(new_value) {
|
|
|
81
70
|
</script>
|
|
82
71
|
|
|
83
72
|
{#if edit && datatype !== "bool"}
|
|
84
|
-
<
|
|
73
|
+
<textarea
|
|
85
74
|
readonly={is_static}
|
|
86
75
|
aria-readonly={is_static}
|
|
87
|
-
role="textbox"
|
|
88
76
|
aria-label={is_static ? "Cell is read-only" : "Edit cell"}
|
|
89
77
|
bind:this={el}
|
|
90
78
|
bind:value
|
|
@@ -92,7 +80,6 @@ function handle_bool_change(new_value) {
|
|
|
92
80
|
tabindex="-1"
|
|
93
81
|
on:blur={handle_blur}
|
|
94
82
|
on:mousedown|stopPropagation
|
|
95
|
-
on:mouseup|stopPropagation
|
|
96
83
|
on:click|stopPropagation
|
|
97
84
|
use:use_focus
|
|
98
85
|
on:keydown={handle_keydown}
|
|
@@ -108,18 +95,17 @@ function handle_bool_change(new_value) {
|
|
|
108
95
|
{:else}
|
|
109
96
|
<span
|
|
110
97
|
class:dragging={is_dragging}
|
|
111
|
-
on:click={handle_click}
|
|
112
98
|
on:keydown={handle_keydown}
|
|
113
99
|
tabindex="0"
|
|
114
100
|
role="button"
|
|
115
101
|
class:edit
|
|
116
|
-
class:expanded={
|
|
102
|
+
class:expanded={edit}
|
|
117
103
|
class:multiline={header}
|
|
118
104
|
on:focus|preventDefault
|
|
119
105
|
style={styling}
|
|
120
106
|
data-editable={editable}
|
|
121
107
|
data-max-chars={max_chars}
|
|
122
|
-
data-expanded={
|
|
108
|
+
data-expanded={edit}
|
|
123
109
|
placeholder=" "
|
|
124
110
|
class:text={datatype === "str"}
|
|
125
111
|
class:wrap={wrap_text}
|
|
@@ -167,7 +153,7 @@ function handle_bool_change(new_value) {
|
|
|
167
153
|
cursor: crosshair !important;
|
|
168
154
|
}
|
|
169
155
|
|
|
170
|
-
|
|
156
|
+
textarea {
|
|
171
157
|
position: absolute;
|
|
172
158
|
flex: 1 1 0%;
|
|
173
159
|
transform: translateX(-0.1px);
|
|
@@ -176,6 +162,16 @@ function handle_bool_change(new_value) {
|
|
|
176
162
|
background: transparent;
|
|
177
163
|
cursor: text;
|
|
178
164
|
width: calc(100% - var(--size-2));
|
|
165
|
+
resize: none;
|
|
166
|
+
height: 100%;
|
|
167
|
+
padding-left: 0;
|
|
168
|
+
font-size: inherit;
|
|
169
|
+
font-weight: inherit;
|
|
170
|
+
line-height: var(--line-lg);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
textarea:focus {
|
|
174
|
+
outline: none;
|
|
179
175
|
}
|
|
180
176
|
|
|
181
177
|
span {
|
|
@@ -227,7 +223,7 @@ function handle_bool_change(new_value) {
|
|
|
227
223
|
object-fit: contain;
|
|
228
224
|
}
|
|
229
225
|
|
|
230
|
-
|
|
226
|
+
textarea:read-only {
|
|
231
227
|
cursor: not-allowed;
|
|
232
228
|
}
|
|
233
229
|
|
|
@@ -25,11 +25,10 @@ declare const __propDef: {
|
|
|
25
25
|
coords: [number, number];
|
|
26
26
|
on_select_column?: (((col: number) => void) | null) | undefined;
|
|
27
27
|
on_select_row?: (((row: number) => void) | null) | undefined;
|
|
28
|
-
el:
|
|
28
|
+
el: HTMLTextAreaElement | null;
|
|
29
29
|
};
|
|
30
30
|
events: {
|
|
31
31
|
mousedown: MouseEvent;
|
|
32
|
-
mouseup: MouseEvent;
|
|
33
32
|
click: MouseEvent;
|
|
34
33
|
focus: FocusEvent;
|
|
35
34
|
blur: CustomEvent<{
|
package/dist/shared/Table.svelte
CHANGED
|
@@ -40,7 +40,7 @@ declare const __propDef: {
|
|
|
40
40
|
components?: Record<string, any> | undefined;
|
|
41
41
|
el: {
|
|
42
42
|
cell: HTMLTableCellElement | null;
|
|
43
|
-
input:
|
|
43
|
+
input: HTMLTextAreaElement | null;
|
|
44
44
|
};
|
|
45
45
|
handle_select_column: (col: number) => void;
|
|
46
46
|
handle_select_row: (row: number) => void;
|
|
@@ -18,6 +18,7 @@ interface DataFrameState {
|
|
|
18
18
|
max_height: number;
|
|
19
19
|
column_widths: string[];
|
|
20
20
|
max_chars?: number;
|
|
21
|
+
static_columns?: (string | number)[];
|
|
21
22
|
};
|
|
22
23
|
current_search_query: string | null;
|
|
23
24
|
sort_state: {
|
|
@@ -165,7 +166,7 @@ export interface DataFrameContext {
|
|
|
165
166
|
styling?: string[][] | null;
|
|
166
167
|
els?: Record<string, {
|
|
167
168
|
cell: HTMLTableCellElement | null;
|
|
168
|
-
input:
|
|
169
|
+
input: HTMLTextAreaElement | null;
|
|
169
170
|
}>;
|
|
170
171
|
parent_element?: HTMLElement;
|
|
171
172
|
get_data_at?: (row: number, col: number) => string | number;
|
package/dist/shared/types.d.ts
CHANGED
|
@@ -13,6 +13,6 @@ export type TableData = TableCell[][];
|
|
|
13
13
|
export type CountConfig = [number, "fixed" | "dynamic"];
|
|
14
14
|
export type ElementRefs = Record<string, {
|
|
15
15
|
cell: null | HTMLTableCellElement;
|
|
16
|
-
input: null |
|
|
16
|
+
input: null | HTMLTextAreaElement;
|
|
17
17
|
}>;
|
|
18
18
|
export type DataBinding = Record<string, TableCell>;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import type { Headers, HeadersWithIDs } from "../utils";
|
|
2
2
|
export declare function make_headers(_head: Headers, col_count: [number, "fixed" | "dynamic"], els: Record<string, {
|
|
3
3
|
cell: null | HTMLTableCellElement;
|
|
4
|
-
input: null |
|
|
4
|
+
input: null | HTMLTextAreaElement;
|
|
5
5
|
}>, make_id: () => string): HeadersWithIDs;
|
|
6
6
|
export declare function process_data(values: (string | number)[][], els: Record<string, {
|
|
7
7
|
cell: null | HTMLTableCellElement;
|
|
8
|
-
input: null |
|
|
8
|
+
input: null | HTMLTextAreaElement;
|
|
9
9
|
}>, data_binding: Record<string, any>, make_id: () => string, display_value?: string[][] | null): {
|
|
10
10
|
id: string;
|
|
11
11
|
value: string | number;
|
|
@@ -59,6 +59,7 @@ function handle_header_navigation(event, ctx) {
|
|
|
59
59
|
}
|
|
60
60
|
return false;
|
|
61
61
|
}
|
|
62
|
+
// eslint-disable-next-line complexity
|
|
62
63
|
function handle_delete_operation(event, ctx) {
|
|
63
64
|
if (!ctx.data || !ctx.headers || !ctx.els || !ctx.dispatch)
|
|
64
65
|
return false;
|
|
@@ -69,6 +70,10 @@ function handle_delete_operation(event, ctx) {
|
|
|
69
70
|
return false;
|
|
70
71
|
const editing = state.ui_state.editing;
|
|
71
72
|
const selected_cells = state.ui_state.selected_cells;
|
|
73
|
+
const static_columns = state.config.static_columns || [];
|
|
74
|
+
if (selected_cells.some(([_, col]) => static_columns.includes(col))) {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
72
77
|
if (editing) {
|
|
73
78
|
const [row, col] = editing;
|
|
74
79
|
const input_el = ctx.els[ctx.data[row][col].id]?.input;
|
|
@@ -129,8 +134,10 @@ async function handle_enter_key(event, ctx, i, j) {
|
|
|
129
134
|
const state = get(ctx.state);
|
|
130
135
|
if (!state.config.editable)
|
|
131
136
|
return false;
|
|
132
|
-
event.preventDefault();
|
|
133
137
|
const editing = state.ui_state.editing;
|
|
138
|
+
if (editing && event.shiftKey)
|
|
139
|
+
return false;
|
|
140
|
+
event.preventDefault();
|
|
134
141
|
if (editing && dequal(editing, [i, j])) {
|
|
135
142
|
const cell_id = ctx.data[i][j].id;
|
|
136
143
|
const input_el = ctx.els[cell_id]?.input;
|
|
@@ -138,6 +145,8 @@ async function handle_enter_key(event, ctx, i, j) {
|
|
|
138
145
|
await save_cell_value(input_el.value, ctx, i, j);
|
|
139
146
|
}
|
|
140
147
|
ctx.actions.set_editing(false);
|
|
148
|
+
await tick();
|
|
149
|
+
ctx.parent_element?.focus();
|
|
141
150
|
}
|
|
142
151
|
else {
|
|
143
152
|
ctx.actions.set_editing([i, j]);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gradio/dataframe",
|
|
3
|
-
"version": "0.18.
|
|
3
|
+
"version": "0.18.2",
|
|
4
4
|
"description": "Gradio UI packages",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "",
|
|
@@ -17,15 +17,15 @@
|
|
|
17
17
|
"dompurify": "^3.0.3",
|
|
18
18
|
"katex": "^0.16.7",
|
|
19
19
|
"marked": "^12.0.0",
|
|
20
|
-
"@gradio/atoms": "^0.16.
|
|
21
|
-
"@gradio/checkbox": "^0.4.
|
|
22
|
-
"@gradio/
|
|
23
|
-
"@gradio/
|
|
24
|
-
"@gradio/statustracker": "^0.10.13",
|
|
20
|
+
"@gradio/atoms": "^0.16.3",
|
|
21
|
+
"@gradio/checkbox": "^0.4.25",
|
|
22
|
+
"@gradio/button": "^0.5.6",
|
|
23
|
+
"@gradio/client": "^1.15.5",
|
|
25
24
|
"@gradio/icons": "^0.12.0",
|
|
26
|
-
"@gradio/
|
|
25
|
+
"@gradio/statustracker": "^0.10.14",
|
|
26
|
+
"@gradio/markdown-code": "^0.5.0",
|
|
27
27
|
"@gradio/utils": "^0.10.2",
|
|
28
|
-
"@gradio/
|
|
28
|
+
"@gradio/upload": "^0.16.10"
|
|
29
29
|
},
|
|
30
30
|
"exports": {
|
|
31
31
|
".": {
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"svelte": "^4.0.0"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
|
-
"@gradio/preview": "^0.
|
|
47
|
+
"@gradio/preview": "^0.14.0"
|
|
48
48
|
},
|
|
49
49
|
"repository": {
|
|
50
50
|
"type": "git",
|
|
@@ -36,15 +36,13 @@
|
|
|
36
36
|
export let coords: [number, number];
|
|
37
37
|
export let on_select_column: ((col: number) => void) | null = null;
|
|
38
38
|
export let on_select_row: ((row: number) => void) | null = null;
|
|
39
|
-
export let el:
|
|
39
|
+
export let el: HTMLTextAreaElement | null;
|
|
40
40
|
|
|
41
41
|
const dispatch = createEventDispatcher<{
|
|
42
42
|
blur: { blur_event: FocusEvent; coords: [number, number] };
|
|
43
43
|
keydown: KeyboardEvent;
|
|
44
44
|
}>();
|
|
45
45
|
|
|
46
|
-
let is_expanded = false;
|
|
47
|
-
|
|
48
46
|
function truncate_text(
|
|
49
47
|
text: string | number,
|
|
50
48
|
max_length: number | null = null,
|
|
@@ -57,8 +55,7 @@
|
|
|
57
55
|
return str.slice(0, max_length) + "...";
|
|
58
56
|
}
|
|
59
57
|
|
|
60
|
-
$: should_truncate =
|
|
61
|
-
!edit && !is_expanded && max_chars !== null && max_chars > 0;
|
|
58
|
+
$: should_truncate = !edit && max_chars !== null && max_chars > 0;
|
|
62
59
|
|
|
63
60
|
$: display_content = editable
|
|
64
61
|
? value
|
|
@@ -70,7 +67,7 @@
|
|
|
70
67
|
? truncate_text(display_content, max_chars, datatype === "image")
|
|
71
68
|
: display_content;
|
|
72
69
|
|
|
73
|
-
function use_focus(node:
|
|
70
|
+
function use_focus(node: HTMLTextAreaElement): any {
|
|
74
71
|
requestAnimationFrame(() => {
|
|
75
72
|
node.focus();
|
|
76
73
|
});
|
|
@@ -86,20 +83,9 @@
|
|
|
86
83
|
}
|
|
87
84
|
|
|
88
85
|
function handle_keydown(event: KeyboardEvent): void {
|
|
89
|
-
if (event.key === "Enter") {
|
|
90
|
-
if (!header) {
|
|
91
|
-
is_expanded = !is_expanded;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
86
|
dispatch("keydown", event);
|
|
95
87
|
}
|
|
96
88
|
|
|
97
|
-
function handle_click(): void {
|
|
98
|
-
if (!edit && !header) {
|
|
99
|
-
is_expanded = !is_expanded;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
89
|
function handle_bool_change(new_value: boolean): void {
|
|
104
90
|
value = new_value.toString();
|
|
105
91
|
dispatch("blur", {
|
|
@@ -116,10 +102,9 @@
|
|
|
116
102
|
</script>
|
|
117
103
|
|
|
118
104
|
{#if edit && datatype !== "bool"}
|
|
119
|
-
<
|
|
105
|
+
<textarea
|
|
120
106
|
readonly={is_static}
|
|
121
107
|
aria-readonly={is_static}
|
|
122
|
-
role="textbox"
|
|
123
108
|
aria-label={is_static ? "Cell is read-only" : "Edit cell"}
|
|
124
109
|
bind:this={el}
|
|
125
110
|
bind:value
|
|
@@ -127,7 +112,6 @@
|
|
|
127
112
|
tabindex="-1"
|
|
128
113
|
on:blur={handle_blur}
|
|
129
114
|
on:mousedown|stopPropagation
|
|
130
|
-
on:mouseup|stopPropagation
|
|
131
115
|
on:click|stopPropagation
|
|
132
116
|
use:use_focus
|
|
133
117
|
on:keydown={handle_keydown}
|
|
@@ -143,18 +127,17 @@
|
|
|
143
127
|
{:else}
|
|
144
128
|
<span
|
|
145
129
|
class:dragging={is_dragging}
|
|
146
|
-
on:click={handle_click}
|
|
147
130
|
on:keydown={handle_keydown}
|
|
148
131
|
tabindex="0"
|
|
149
132
|
role="button"
|
|
150
133
|
class:edit
|
|
151
|
-
class:expanded={
|
|
134
|
+
class:expanded={edit}
|
|
152
135
|
class:multiline={header}
|
|
153
136
|
on:focus|preventDefault
|
|
154
137
|
style={styling}
|
|
155
138
|
data-editable={editable}
|
|
156
139
|
data-max-chars={max_chars}
|
|
157
|
-
data-expanded={
|
|
140
|
+
data-expanded={edit}
|
|
158
141
|
placeholder=" "
|
|
159
142
|
class:text={datatype === "str"}
|
|
160
143
|
class:wrap={wrap_text}
|
|
@@ -202,7 +185,7 @@
|
|
|
202
185
|
cursor: crosshair !important;
|
|
203
186
|
}
|
|
204
187
|
|
|
205
|
-
|
|
188
|
+
textarea {
|
|
206
189
|
position: absolute;
|
|
207
190
|
flex: 1 1 0%;
|
|
208
191
|
transform: translateX(-0.1px);
|
|
@@ -211,6 +194,16 @@
|
|
|
211
194
|
background: transparent;
|
|
212
195
|
cursor: text;
|
|
213
196
|
width: calc(100% - var(--size-2));
|
|
197
|
+
resize: none;
|
|
198
|
+
height: 100%;
|
|
199
|
+
padding-left: 0;
|
|
200
|
+
font-size: inherit;
|
|
201
|
+
font-weight: inherit;
|
|
202
|
+
line-height: var(--line-lg);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
textarea:focus {
|
|
206
|
+
outline: none;
|
|
214
207
|
}
|
|
215
208
|
|
|
216
209
|
span {
|
|
@@ -262,7 +255,7 @@
|
|
|
262
255
|
object-fit: contain;
|
|
263
256
|
}
|
|
264
257
|
|
|
265
|
-
|
|
258
|
+
textarea:read-only {
|
|
266
259
|
cursor: not-allowed;
|
|
267
260
|
}
|
|
268
261
|
|
package/shared/Table.svelte
CHANGED
|
@@ -92,7 +92,8 @@
|
|
|
92
92
|
wrap,
|
|
93
93
|
max_height,
|
|
94
94
|
column_widths,
|
|
95
|
-
max_chars
|
|
95
|
+
max_chars,
|
|
96
|
+
static_columns
|
|
96
97
|
});
|
|
97
98
|
|
|
98
99
|
const { state: df_state, actions: df_actions } = df_ctx;
|
|
@@ -165,7 +166,7 @@
|
|
|
165
166
|
|
|
166
167
|
let els: Record<
|
|
167
168
|
string,
|
|
168
|
-
{ cell: null | HTMLTableCellElement; input: null |
|
|
169
|
+
{ cell: null | HTMLTableCellElement; input: null | HTMLTextAreaElement }
|
|
169
170
|
> = {};
|
|
170
171
|
let data_binding: Record<string, (typeof data)[0][0]> = {};
|
|
171
172
|
let _headers = make_headers(headers, col_count, els, make_id);
|
package/shared/TableCell.svelte
CHANGED
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
export let components: Record<string, any> = {};
|
|
60
60
|
export let el: {
|
|
61
61
|
cell: HTMLTableCellElement | null;
|
|
62
|
-
input:
|
|
62
|
+
input: HTMLTextAreaElement | null;
|
|
63
63
|
};
|
|
64
64
|
export let handle_select_column: (col: number) => void;
|
|
65
65
|
export let handle_select_row: (row: number) => void;
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
export let max_chars: number | undefined;
|
|
37
37
|
export let editable: boolean;
|
|
38
38
|
export let i18n: I18nFormatter;
|
|
39
|
-
export let el:
|
|
39
|
+
export let el: HTMLTextAreaElement | null;
|
|
40
40
|
export let is_static: boolean;
|
|
41
41
|
export let col_count: [number, "fixed" | "dynamic"];
|
|
42
42
|
|
package/shared/Toolbar.svelte
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
let input_value = "";
|
|
22
22
|
|
|
23
23
|
function handle_search_input(e: Event): void {
|
|
24
|
-
const target = e.target as
|
|
24
|
+
const target = e.target as HTMLTextAreaElement;
|
|
25
25
|
input_value = target.value;
|
|
26
26
|
const new_query = input_value || null;
|
|
27
27
|
if (current_search_query !== new_query) {
|
|
@@ -30,6 +30,7 @@ interface DataFrameState {
|
|
|
30
30
|
max_height: number;
|
|
31
31
|
column_widths: string[];
|
|
32
32
|
max_chars?: number;
|
|
33
|
+
static_columns?: (string | number)[];
|
|
33
34
|
};
|
|
34
35
|
current_search_query: string | null;
|
|
35
36
|
sort_state: {
|
|
@@ -179,7 +180,7 @@ export interface DataFrameContext {
|
|
|
179
180
|
styling?: string[][] | null;
|
|
180
181
|
els?: Record<
|
|
181
182
|
string,
|
|
182
|
-
{ cell: HTMLTableCellElement | null; input:
|
|
183
|
+
{ cell: HTMLTableCellElement | null; input: HTMLTextAreaElement | null }
|
|
183
184
|
>;
|
|
184
185
|
parent_element?: HTMLElement;
|
|
185
186
|
get_data_at?: (row: number, col: number) => string | number;
|
package/shared/types.ts
CHANGED
|
@@ -5,7 +5,7 @@ export function make_headers(
|
|
|
5
5
|
col_count: [number, "fixed" | "dynamic"],
|
|
6
6
|
els: Record<
|
|
7
7
|
string,
|
|
8
|
-
{ cell: null | HTMLTableCellElement; input: null |
|
|
8
|
+
{ cell: null | HTMLTableCellElement; input: null | HTMLTextAreaElement }
|
|
9
9
|
>,
|
|
10
10
|
make_id: () => string
|
|
11
11
|
): HeadersWithIDs {
|
|
@@ -38,7 +38,7 @@ export function process_data(
|
|
|
38
38
|
values: (string | number)[][],
|
|
39
39
|
els: Record<
|
|
40
40
|
string,
|
|
41
|
-
{ cell: null | HTMLTableCellElement; input: null |
|
|
41
|
+
{ cell: null | HTMLTableCellElement; input: null | HTMLTextAreaElement }
|
|
42
42
|
>,
|
|
43
43
|
data_binding: Record<string, any>,
|
|
44
44
|
make_id: () => string,
|
|
@@ -88,6 +88,7 @@ function handle_header_navigation(
|
|
|
88
88
|
return false;
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
+
// eslint-disable-next-line complexity
|
|
91
92
|
function handle_delete_operation(
|
|
92
93
|
event: KeyboardEvent,
|
|
93
94
|
ctx: DataFrameContext
|
|
@@ -101,6 +102,11 @@ function handle_delete_operation(
|
|
|
101
102
|
const editing = state.ui_state.editing;
|
|
102
103
|
const selected_cells = state.ui_state.selected_cells;
|
|
103
104
|
|
|
105
|
+
const static_columns = state.config.static_columns || [];
|
|
106
|
+
if (selected_cells.some(([_, col]) => static_columns.includes(col))) {
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
|
|
104
110
|
if (editing) {
|
|
105
111
|
const [row, col] = editing;
|
|
106
112
|
const input_el = ctx.els[ctx.data[row][col].id]?.input;
|
|
@@ -180,9 +186,10 @@ async function handle_enter_key(
|
|
|
180
186
|
const state = get(ctx.state);
|
|
181
187
|
if (!state.config.editable) return false;
|
|
182
188
|
|
|
183
|
-
event.preventDefault();
|
|
184
|
-
|
|
185
189
|
const editing = state.ui_state.editing;
|
|
190
|
+
if (editing && event.shiftKey) return false;
|
|
191
|
+
|
|
192
|
+
event.preventDefault();
|
|
186
193
|
|
|
187
194
|
if (editing && dequal(editing, [i, j])) {
|
|
188
195
|
const cell_id = ctx.data[i][j].id;
|
|
@@ -191,6 +198,8 @@ async function handle_enter_key(
|
|
|
191
198
|
await save_cell_value(input_el.value, ctx, i, j);
|
|
192
199
|
}
|
|
193
200
|
ctx.actions.set_editing(false);
|
|
201
|
+
await tick();
|
|
202
|
+
ctx.parent_element?.focus();
|
|
194
203
|
} else {
|
|
195
204
|
ctx.actions.set_editing([i, j]);
|
|
196
205
|
}
|