@gradio/dataframe 0.17.3 → 0.17.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/Dataframe.stories.svelte +29 -0
  3. package/dist/shared/CellMenu.svelte.d.ts +1 -1
  4. package/dist/shared/EditableCell.svelte +8 -17
  5. package/dist/shared/EditableCell.svelte.d.ts +5 -3
  6. package/dist/shared/Table.svelte +111 -138
  7. package/dist/shared/TableCell.svelte +4 -6
  8. package/dist/shared/TableCell.svelte.d.ts +5 -1
  9. package/dist/shared/TableHeader.svelte +4 -3
  10. package/dist/shared/TableHeader.svelte.d.ts +1 -2
  11. package/dist/shared/context/dataframe_context.d.ts +147 -0
  12. package/dist/shared/context/dataframe_context.js +335 -0
  13. package/dist/shared/selection_utils.d.ts +1 -2
  14. package/dist/shared/selection_utils.js +0 -13
  15. package/dist/shared/utils/drag_utils.js +1 -0
  16. package/dist/shared/utils/keyboard_utils.d.ts +3 -2
  17. package/dist/shared/utils/keyboard_utils.js +107 -68
  18. package/package.json +7 -7
  19. package/shared/CellMenu.svelte +1 -1
  20. package/shared/EditableCell.svelte +9 -20
  21. package/shared/Table.svelte +147 -165
  22. package/shared/TableCell.svelte +9 -6
  23. package/shared/TableHeader.svelte +5 -8
  24. package/shared/context/dataframe_context.ts +576 -0
  25. package/shared/selection_utils.ts +1 -23
  26. package/shared/utils/drag_utils.ts +1 -0
  27. package/shared/utils/keyboard_utils.ts +142 -80
  28. package/{shared/utils → test}/sort_utils.test.ts +5 -1
  29. package/{shared/utils → test}/table_utils.test.ts +2 -2
  30. package/dist/shared/context/keyboard_context.d.ts +0 -37
  31. package/dist/shared/context/keyboard_context.js +0 -12
  32. package/dist/shared/context/selection_context.d.ts +0 -32
  33. package/dist/shared/context/selection_context.js +0 -107
  34. package/dist/shared/context/table_context.d.ts +0 -141
  35. package/dist/shared/context/table_context.js +0 -375
  36. package/shared/context/keyboard_context.ts +0 -65
  37. package/shared/context/selection_context.ts +0 -168
  38. package/shared/context/table_context.ts +0 -625
@@ -1,40 +1,82 @@
1
1
  import { dequal } from "dequal/lite";
2
2
  import { handle_delete_key } from "../selection_utils";
3
- import type { KeyboardContext } from "../context/keyboard_context";
3
+ import type { DataFrameContext } from "../context/dataframe_context";
4
4
  import { tick } from "svelte";
5
+ import { get } from "svelte/store";
5
6
  import { copy_table_data } from "./table_utils";
6
7
 
8
+ async function save_cell_value(
9
+ input_value: string,
10
+ ctx: DataFrameContext,
11
+ row: number,
12
+ col: number
13
+ ): Promise<void> {
14
+ if (!ctx.data || !ctx.data[row] || !ctx.data[row][col]) return;
15
+
16
+ const old_value = ctx.data[row][col].value;
17
+ ctx.data[row][col].value = input_value;
18
+
19
+ if (old_value !== input_value && ctx.dispatch) {
20
+ ctx.dispatch("change", {
21
+ data: ctx.data.map((row) => row.map((cell) => cell.value)),
22
+ headers: ctx.headers?.map((h) => h.value) || [],
23
+ metadata: null
24
+ });
25
+ }
26
+
27
+ ctx.actions.set_selected([row, col]);
28
+ }
29
+
30
+ export async function handle_cell_blur(
31
+ event: FocusEvent,
32
+ ctx: DataFrameContext,
33
+ coords: [number, number]
34
+ ): Promise<void> {
35
+ if (!ctx.data || !ctx.headers || !ctx.els) return;
36
+
37
+ const input_el = event.target as HTMLInputElement;
38
+ if (!input_el || input_el.value === undefined) return;
39
+
40
+ await save_cell_value(input_el.value, ctx, coords[0], coords[1]);
41
+ }
42
+
7
43
  function handle_header_navigation(
8
44
  event: KeyboardEvent,
9
- ctx: KeyboardContext
45
+ ctx: DataFrameContext
10
46
  ): boolean {
11
- if (ctx.selected_header === false || ctx.header_edit !== false) return false;
47
+ const state = get(ctx.state);
48
+ const selected_header = state.ui_state.selected_header;
49
+ const header_edit = state.ui_state.header_edit;
50
+ const headers = ctx.headers || [];
51
+
52
+ if (selected_header === false || header_edit !== false) return false;
53
+
12
54
  switch (event.key) {
13
55
  case "ArrowDown":
14
- ctx.df_actions.set_selected_header(false);
15
- ctx.df_actions.set_selected([0, ctx.selected_header]);
16
- ctx.df_actions.set_selected_cells([[0, ctx.selected_header]]);
56
+ ctx.actions.set_selected_header(false);
57
+ ctx.actions.set_selected([0, selected_header as number]);
58
+ ctx.actions.set_selected_cells([[0, selected_header as number]]);
17
59
  return true;
18
60
  case "ArrowLeft":
19
- ctx.df_actions.set_selected_header(
20
- ctx.selected_header > 0 ? ctx.selected_header - 1 : ctx.selected_header
61
+ ctx.actions.set_selected_header(
62
+ selected_header > 0 ? selected_header - 1 : selected_header
21
63
  );
22
64
  return true;
23
65
  case "ArrowRight":
24
- ctx.df_actions.set_selected_header(
25
- ctx.selected_header < ctx.headers.length - 1
26
- ? ctx.selected_header + 1
27
- : ctx.selected_header
66
+ ctx.actions.set_selected_header(
67
+ selected_header < headers.length - 1
68
+ ? selected_header + 1
69
+ : selected_header
28
70
  );
29
71
  return true;
30
72
  case "Escape":
31
73
  event.preventDefault();
32
- ctx.df_actions.set_selected_header(false);
74
+ ctx.actions.set_selected_header(false);
33
75
  return true;
34
76
  case "Enter":
35
77
  event.preventDefault();
36
- if (ctx.editable) {
37
- ctx.df_actions.set_header_edit(ctx.selected_header);
78
+ if (state.config.editable) {
79
+ ctx.actions.set_header_edit(selected_header);
38
80
  }
39
81
  return true;
40
82
  }
@@ -43,14 +85,20 @@ function handle_header_navigation(
43
85
 
44
86
  function handle_delete_operation(
45
87
  event: KeyboardEvent,
46
- ctx: KeyboardContext
88
+ ctx: DataFrameContext
47
89
  ): boolean {
48
- if (!ctx.editable) return false;
90
+ if (!ctx.data || !ctx.headers || !ctx.els || !ctx.dispatch) return false;
91
+
92
+ const state = get(ctx.state);
93
+ if (!state.config.editable) return false;
49
94
  if (event.key !== "Delete" && event.key !== "Backspace") return false;
50
95
 
51
- if (ctx.editing) {
52
- const [row, col] = ctx.editing;
53
- const input_el = ctx.els[ctx.data[row][col].id].input;
96
+ const editing = state.ui_state.editing;
97
+ const selected_cells = state.ui_state.selected_cells;
98
+
99
+ if (editing) {
100
+ const [row, col] = editing;
101
+ const input_el = ctx.els[ctx.data[row][col].id]?.input;
54
102
  if (input_el && input_el.selectionStart !== input_el.selectionEnd) {
55
103
  return false;
56
104
  }
@@ -66,103 +114,105 @@ function handle_delete_operation(
66
114
  }
67
115
 
68
116
  event.preventDefault();
69
- if (ctx.selected_cells.length > 0) {
70
- const new_data = handle_delete_key(ctx.data, ctx.selected_cells);
117
+ if (selected_cells.length > 0) {
118
+ const new_data = handle_delete_key(ctx.data, selected_cells);
71
119
  ctx.dispatch("change", {
72
120
  data: new_data.map((row) => row.map((cell) => cell.value)),
73
121
  headers: ctx.headers.map((h) => h.value),
74
122
  metadata: null
75
123
  });
76
- ctx.dispatch("input");
77
124
  }
78
125
  return true;
79
126
  }
80
127
 
81
128
  function handle_arrow_keys(
82
129
  event: KeyboardEvent,
83
- ctx: KeyboardContext,
130
+ ctx: DataFrameContext,
84
131
  i: number,
85
132
  j: number
86
133
  ): boolean {
87
- if (ctx.editing) return false;
134
+ const state = get(ctx.state);
135
+ const editing = state.ui_state.editing;
136
+ const selected_cells = state.ui_state.selected_cells;
137
+
138
+ if (editing) return false;
139
+ if (!ctx.data) return false;
140
+
88
141
  event.preventDefault();
89
142
 
90
- const next_coords = ctx.move_cursor(event, [i, j], ctx.data);
143
+ const next_coords = ctx.actions.move_cursor(event, [i, j], ctx.data);
91
144
  if (next_coords) {
92
145
  if (event.shiftKey) {
93
- ctx.df_actions.set_selected_cells(
94
- ctx.get_range_selection(
95
- ctx.selected_cells.length > 0 ? ctx.selected_cells[0] : [i, j],
146
+ ctx.actions.set_selected_cells(
147
+ ctx.actions.get_range_selection(
148
+ selected_cells.length > 0 ? selected_cells[0] : [i, j],
96
149
  next_coords
97
150
  )
98
151
  );
99
- ctx.df_actions.set_editing(false);
152
+ ctx.actions.set_editing(false);
100
153
  } else {
101
- ctx.df_actions.set_selected_cells([next_coords]);
102
- ctx.df_actions.set_editing(false);
154
+ ctx.actions.set_selected_cells([next_coords]);
155
+ ctx.actions.set_editing(false);
103
156
  }
104
- ctx.df_actions.set_selected(next_coords);
157
+ ctx.actions.set_selected(next_coords);
105
158
  } else if (next_coords === false && event.key === "ArrowUp" && i === 0) {
106
- ctx.df_actions.set_selected_header(j);
107
- ctx.df_actions.set_selected(false);
108
- ctx.df_actions.set_selected_cells([]);
109
- ctx.df_actions.set_editing(false);
159
+ ctx.actions.set_selected_header(j);
160
+ ctx.actions.set_selected(false);
161
+ ctx.actions.set_selected_cells([]);
162
+ ctx.actions.set_editing(false);
110
163
  }
111
164
  return true;
112
165
  }
113
166
 
114
167
  async function handle_enter_key(
115
168
  event: KeyboardEvent,
116
- ctx: KeyboardContext,
169
+ ctx: DataFrameContext,
117
170
  i: number,
118
171
  j: number
119
172
  ): Promise<boolean> {
173
+ if (!ctx.data || !ctx.els) return false;
174
+
175
+ const state = get(ctx.state);
176
+ if (!state.config.editable) return false;
177
+
120
178
  event.preventDefault();
121
- if (!ctx.editable) return false;
122
179
 
123
- if (event.shiftKey) {
124
- await ctx.add_row(i);
125
- await tick();
126
- ctx.df_actions.set_selected([i + 1, j]);
127
- } else {
128
- if (dequal(ctx.editing, [i, j])) {
129
- const cell_id = ctx.data[i][j].id;
130
- const input_el = ctx.els[cell_id].input;
131
- if (input_el) {
132
- const old_value = ctx.data[i][j].value;
133
- ctx.data[i][j].value = input_el.value;
134
- if (old_value !== input_el.value) {
135
- ctx.dispatch("input");
136
- }
137
- }
138
- ctx.df_actions.set_editing(false);
139
- await tick();
140
- ctx.df_actions.set_selected([i, j]);
141
- } else {
142
- ctx.df_actions.set_editing([i, j]);
180
+ const editing = state.ui_state.editing;
181
+
182
+ if (editing && dequal(editing, [i, j])) {
183
+ const cell_id = ctx.data[i][j].id;
184
+ const input_el = ctx.els[cell_id]?.input;
185
+ if (input_el) {
186
+ await save_cell_value(input_el.value, ctx, i, j);
143
187
  }
188
+ ctx.actions.set_editing(false);
189
+ } else {
190
+ ctx.actions.set_editing([i, j]);
144
191
  }
192
+
145
193
  return true;
146
194
  }
147
195
 
148
196
  function handle_tab_key(
149
197
  event: KeyboardEvent,
150
- ctx: KeyboardContext,
198
+ ctx: DataFrameContext,
151
199
  i: number,
152
200
  j: number
153
201
  ): boolean {
202
+ if (!ctx.data) return false;
203
+
154
204
  event.preventDefault();
155
- ctx.df_actions.set_editing(false);
156
- const next_cell = ctx.get_next_cell_coordinates(
205
+ ctx.actions.set_editing(false);
206
+ const next_cell = ctx.actions.get_next_cell_coordinates(
157
207
  [i, j],
158
208
  ctx.data,
159
209
  event.shiftKey
160
210
  );
161
211
  if (next_cell) {
162
- ctx.df_actions.set_selected_cells([next_cell]);
163
- ctx.df_actions.set_selected(next_cell);
164
- if (ctx.editable) {
165
- ctx.df_actions.set_editing(next_cell);
212
+ ctx.actions.set_selected_cells([next_cell]);
213
+ ctx.actions.set_selected(next_cell);
214
+ if (get(ctx.state).config.editable) {
215
+ ctx.actions.set_editing(next_cell);
166
216
  }
167
217
  }
168
218
  return true;
@@ -170,16 +220,20 @@ function handle_tab_key(
170
220
 
171
221
  function handle_default_key(
172
222
  event: KeyboardEvent,
173
- ctx: KeyboardContext,
223
+ ctx: DataFrameContext,
174
224
  i: number,
175
225
  j: number
176
226
  ): boolean {
177
- if (!ctx.editable) return false;
227
+ const state = get(ctx.state);
228
+ if (!state.config.editable) return false;
229
+
230
+ const editing = state.ui_state.editing;
231
+
178
232
  if (
179
- (!ctx.editing || (ctx.editing && dequal(ctx.editing, [i, j]))) &&
233
+ (!editing || (editing && dequal(editing, [i, j]))) &&
180
234
  event.key.length === 1
181
235
  ) {
182
- ctx.df_actions.set_editing([i, j]);
236
+ ctx.actions.set_editing([i, j]);
183
237
  return true;
184
238
  }
185
239
  return false;
@@ -187,20 +241,25 @@ function handle_default_key(
187
241
 
188
242
  async function handle_cell_navigation(
189
243
  event: KeyboardEvent,
190
- ctx: KeyboardContext
244
+ ctx: DataFrameContext
191
245
  ): Promise<boolean> {
192
- if (!ctx.selected) return false;
246
+ if (!ctx.data) return false;
247
+
248
+ const state = get(ctx.state);
249
+ const selected = state.ui_state.selected;
250
+ const selected_cells = state.ui_state.selected_cells;
251
+
252
+ if (!selected) return false;
193
253
  if (event.key === "c" && (event.metaKey || event.ctrlKey)) {
194
254
  event.preventDefault();
195
- if (ctx.selected_cells.length > 0) {
196
- await copy_table_data(ctx.data, ctx.selected_cells);
255
+ if (selected_cells.length > 0) {
256
+ await copy_table_data(ctx.data, selected_cells);
197
257
  }
198
- ctx.set_copy_flash(true);
199
-
258
+ ctx.actions.set_copy_flash(true);
200
259
  return true;
201
260
  }
202
261
 
203
- const [i, j] = ctx.selected;
262
+ const [i, j] = selected;
204
263
 
205
264
  switch (event.key) {
206
265
  case "ArrowRight":
@@ -209,9 +268,9 @@ async function handle_cell_navigation(
209
268
  case "ArrowUp":
210
269
  return handle_arrow_keys(event, ctx, i, j);
211
270
  case "Escape":
212
- if (!ctx.editable) return false;
271
+ if (!state.config.editable) return false;
213
272
  event.preventDefault();
214
- ctx.df_actions.set_editing(false);
273
+ ctx.actions.set_editing(false);
215
274
  tick().then(() => {
216
275
  if (ctx.parent_element) {
217
276
  ctx.parent_element.focus();
@@ -223,6 +282,9 @@ async function handle_cell_navigation(
223
282
  return await handle_enter_key(event, ctx, i, j);
224
283
  case "Tab":
225
284
  return handle_tab_key(event, ctx, i, j);
285
+ case "Delete":
286
+ case "Backspace":
287
+ return handle_delete_operation(event, ctx);
226
288
  default:
227
289
  return handle_default_key(event, ctx, i, j);
228
290
  }
@@ -230,7 +292,7 @@ async function handle_cell_navigation(
230
292
 
231
293
  export async function handle_keydown(
232
294
  event: KeyboardEvent,
233
- context: KeyboardContext
295
+ context: DataFrameContext
234
296
  ): Promise<void> {
235
297
  if (handle_header_navigation(event, context)) return;
236
298
  if (handle_delete_operation(event, context)) return;
@@ -1,5 +1,9 @@
1
1
  import { describe, test, expect } from "vitest";
2
- import { get_sort_status, sort_data, SortDirection } from "./sort_utils";
2
+ import {
3
+ get_sort_status,
4
+ sort_data,
5
+ SortDirection
6
+ } from "../shared/utils/sort_utils";
3
7
 
4
8
  describe("sort_utils", () => {
5
9
  describe("get_sort_status", () => {
@@ -1,6 +1,6 @@
1
1
  import { describe, test, expect } from "vitest";
2
- import { make_cell_id, make_header_id } from "./table_utils";
3
- import { process_data, make_headers } from "./data_processing";
2
+ import { make_cell_id, make_header_id } from "../shared/utils/table_utils";
3
+ import { process_data, make_headers } from "../shared/utils/data_processing";
4
4
 
5
5
  function make_id(): string {
6
6
  return Math.random().toString(36).substring(2, 15);
@@ -1,37 +0,0 @@
1
- import type { DataFrameContext } from "./table_context";
2
- import type { CellData } from "../selection_utils";
3
- import type { DataframeValue } from "../utils";
4
- import type { CellCoordinate } from "../types";
5
- export type KeyboardContext = {
6
- selected_header: number | false;
7
- header_edit: number | false;
8
- editing: [number, number] | false;
9
- selected: [number, number] | false;
10
- selected_cells: [number, number][];
11
- editable: boolean;
12
- data: CellData[][];
13
- headers: {
14
- id: string;
15
- value: string;
16
- }[];
17
- els: Record<string, {
18
- cell: null | HTMLTableCellElement;
19
- input: null | HTMLInputElement;
20
- }>;
21
- df_actions: DataFrameContext["actions"];
22
- dispatch: {
23
- (e: "change", detail: DataframeValue): void;
24
- (e: "input", detail?: undefined): void;
25
- (e: "select", detail: any): void;
26
- (e: "search", detail: string | null): void;
27
- };
28
- add_row: (index?: number) => Promise<void>;
29
- get_next_cell_coordinates: (current: CellCoordinate, data: CellData[][], shift_key: boolean) => false | CellCoordinate;
30
- get_range_selection: (start: CellCoordinate, end: CellCoordinate) => CellCoordinate[];
31
- move_cursor: (event: KeyboardEvent, current_coords: CellCoordinate, data: CellData[][]) => false | CellCoordinate;
32
- copy_flash: boolean;
33
- set_copy_flash: (value: boolean) => void;
34
- parent_element?: HTMLDivElement;
35
- };
36
- export declare function create_keyboard_context(context: KeyboardContext): KeyboardContext;
37
- export declare function get_keyboard_context(): KeyboardContext | undefined;
@@ -1,12 +0,0 @@
1
- import { getContext, setContext } from "svelte";
2
- const KEYBOARD_KEY = Symbol("keyboard");
3
- export function create_keyboard_context(context) {
4
- const instance_id = Symbol(`keyboard_${Math.random().toString(36).substring(2)}`);
5
- setContext(instance_id, context);
6
- setContext(KEYBOARD_KEY, { instance_id, context });
7
- return context;
8
- }
9
- export function get_keyboard_context() {
10
- const ctx = getContext(KEYBOARD_KEY);
11
- return ctx ? ctx.context : getContext(KEYBOARD_KEY);
12
- }
@@ -1,32 +0,0 @@
1
- import type { DataFrameContext } from "./table_context";
2
- import type { CellData } from "../selection_utils";
3
- import type { DataframeValue } from "../utils";
4
- export type SelectionContext = {
5
- df_actions: DataFrameContext["actions"];
6
- dispatch: {
7
- (e: "change", detail: DataframeValue): void;
8
- (e: "input", detail?: undefined): void;
9
- (e: "select", detail: any): void;
10
- (e: "search", detail: string | null): void;
11
- };
12
- data: CellData[][];
13
- els: Record<string, {
14
- cell: null | HTMLTableCellElement;
15
- input: null | HTMLInputElement;
16
- }>;
17
- editable: boolean;
18
- show_row_numbers: boolean;
19
- get_data_at: (row: number, col: number) => string | number;
20
- clear_on_focus: boolean;
21
- selected_cells: [number, number][];
22
- parent_element: HTMLElement;
23
- actions: {
24
- handle_cell_click: (event: MouseEvent, row: number, col: number) => void;
25
- toggle_cell_menu: (event: MouseEvent, row: number, col: number) => void;
26
- toggle_cell_button: (row: number, col: number) => void;
27
- handle_select_column: (col: number) => void;
28
- handle_select_row: (row: number) => void;
29
- };
30
- };
31
- export declare function create_selection_context(context: Omit<SelectionContext, "actions">): SelectionContext;
32
- export declare function get_selection_context(): SelectionContext;
@@ -1,107 +0,0 @@
1
- import { getContext, setContext } from "svelte";
2
- import { tick } from "svelte";
3
- import { handle_selection } from "../selection_utils";
4
- const SELECTION_KEY = Symbol("selection");
5
- export function create_selection_context(context) {
6
- const instance_id = Symbol(`selection_${Math.random().toString(36).substring(2)}`);
7
- const actions = {
8
- handle_cell_click: (event, row, col) => {
9
- if (event.target instanceof HTMLAnchorElement)
10
- return;
11
- event.preventDefault();
12
- event.stopPropagation();
13
- if (context.show_row_numbers && col === -1)
14
- return;
15
- context.clear_on_focus = false;
16
- context.df_actions.set_active_cell_menu(null);
17
- context.df_actions.set_active_header_menu(null);
18
- context.df_actions.set_selected_header(false);
19
- context.df_actions.set_header_edit(false);
20
- const new_selected_cells = handle_selection([row, col], context.selected_cells || [], event);
21
- context.df_actions.set_selected_cells(new_selected_cells);
22
- context.df_actions.set_selected(new_selected_cells[0]);
23
- if (context.editable) {
24
- if (new_selected_cells.length === 1) {
25
- context.df_actions.set_editing([row, col]);
26
- tick().then(() => {
27
- const input_el = context.els[context.data[row][col].id].input;
28
- if (input_el) {
29
- input_el.focus();
30
- input_el.selectionStart = input_el.selectionEnd =
31
- input_el.value.length;
32
- }
33
- });
34
- }
35
- else {
36
- context.df_actions.set_editing(false);
37
- context.parent_element.focus();
38
- }
39
- }
40
- else {
41
- context.parent_element.focus();
42
- }
43
- actions.toggle_cell_button(row, col);
44
- context.dispatch("select", {
45
- index: [row, col],
46
- value: context.get_data_at(row, col),
47
- row_value: context.data[row].map((d) => d.value)
48
- });
49
- },
50
- toggle_cell_menu: (event, row, col) => {
51
- event.stopPropagation();
52
- const current_menu = context.df_actions.get_active_cell_menu();
53
- if (current_menu &&
54
- current_menu.row === row &&
55
- current_menu.col === col) {
56
- context.df_actions.set_active_cell_menu(null);
57
- }
58
- else {
59
- const cell = event.target.closest("td");
60
- if (cell) {
61
- const rect = cell.getBoundingClientRect();
62
- context.df_actions.set_active_cell_menu({
63
- row,
64
- col,
65
- x: rect.right,
66
- y: rect.bottom
67
- });
68
- }
69
- }
70
- },
71
- toggle_cell_button: (row, col) => {
72
- const current_button = context.df_actions.get_active_button();
73
- const new_button = current_button?.type === "cell" &&
74
- current_button.row === row &&
75
- current_button.col === col
76
- ? null
77
- : { type: "cell", row, col };
78
- context.df_actions.set_active_button(new_button);
79
- },
80
- handle_select_column: (col) => {
81
- const selected_cells = context.data.map((_, row) => [row, col]);
82
- context.df_actions.set_selected_cells(selected_cells);
83
- context.df_actions.set_selected(selected_cells[0]);
84
- context.df_actions.set_editing(false);
85
- setTimeout(() => {
86
- context.parent_element.focus();
87
- }, 0);
88
- },
89
- handle_select_row: (row) => {
90
- const selected_cells = context.data[0].map((_, col) => [row, col]);
91
- context.df_actions.set_selected_cells(selected_cells);
92
- context.df_actions.set_selected(selected_cells[0]);
93
- context.df_actions.set_editing(false);
94
- setTimeout(() => {
95
- context.parent_element.focus();
96
- }, 0);
97
- }
98
- };
99
- const selection_context = { ...context, actions };
100
- setContext(instance_id, selection_context);
101
- setContext(SELECTION_KEY, { instance_id, context: selection_context });
102
- return selection_context;
103
- }
104
- export function get_selection_context() {
105
- const ctx = getContext(SELECTION_KEY);
106
- return ctx ? ctx.context : getContext(SELECTION_KEY);
107
- }