@gradio/dataframe 0.22.0 → 0.23.1

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 (128) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/Dataframe.test.ts +777 -31
  3. package/Index.svelte +107 -106
  4. package/dist/Index.svelte +107 -106
  5. package/dist/Index.svelte.d.ts +0 -1
  6. package/dist/shared/BooleanCell.svelte +12 -6
  7. package/dist/shared/BooleanCell.svelte.d.ts +4 -18
  8. package/dist/shared/CellMenu.svelte +74 -49
  9. package/dist/shared/CellMenu.svelte.d.ts +5 -19
  10. package/dist/shared/CellMenuButton.svelte +3 -3
  11. package/dist/shared/CellMenuButton.svelte.d.ts +4 -18
  12. package/dist/shared/CellMenuIcons.svelte +1 -1
  13. package/dist/shared/CellMenuIcons.svelte.d.ts +4 -18
  14. package/dist/shared/DataCell.svelte +189 -0
  15. package/dist/shared/DataCell.svelte.d.ts +44 -0
  16. package/dist/shared/EditableCell.svelte +88 -64
  17. package/dist/shared/EditableCell.svelte.d.ts +8 -26
  18. package/dist/shared/EmptyRowButton.svelte +2 -2
  19. package/dist/shared/EmptyRowButton.svelte.d.ts +4 -18
  20. package/dist/shared/FilterMenu.svelte +26 -18
  21. package/dist/shared/FilterMenu.svelte.d.ts +5 -21
  22. package/dist/shared/HeaderCell.svelte +218 -0
  23. package/dist/shared/HeaderCell.svelte.d.ts +30 -0
  24. package/dist/shared/RowNumber.svelte +4 -2
  25. package/dist/shared/RowNumber.svelte.d.ts +4 -18
  26. package/dist/shared/Table.svelte +1037 -949
  27. package/dist/shared/Table.svelte.d.ts +12 -30
  28. package/dist/shared/Toolbar.svelte +32 -22
  29. package/dist/shared/Toolbar.svelte.d.ts +6 -21
  30. package/dist/shared/column_measurement.svelte.d.ts +20 -0
  31. package/dist/shared/column_measurement.svelte.js +79 -0
  32. package/dist/shared/icons/FilterIcon.svelte +14 -6
  33. package/dist/shared/icons/FilterIcon.svelte.d.ts +14 -6
  34. package/dist/shared/icons/Padlock.svelte +6 -2
  35. package/dist/shared/icons/Padlock.svelte.d.ts +4 -25
  36. package/dist/shared/icons/SelectionButtons.svelte +23 -8
  37. package/dist/shared/icons/SelectionButtons.svelte.d.ts +4 -18
  38. package/dist/shared/icons/SortButtonDown.svelte +15 -4
  39. package/dist/shared/icons/SortButtonDown.svelte.d.ts +4 -25
  40. package/dist/shared/icons/SortButtonUp.svelte +15 -5
  41. package/dist/shared/icons/SortButtonUp.svelte.d.ts +4 -25
  42. package/dist/shared/icons/SortIcon.svelte +13 -7
  43. package/dist/shared/icons/SortIcon.svelte.d.ts +7 -21
  44. package/dist/shared/tanstack/index.d.ts +3 -0
  45. package/dist/shared/tanstack/index.js +3 -0
  46. package/dist/shared/tanstack/table.svelte.d.ts +26 -0
  47. package/dist/shared/tanstack/table.svelte.js +102 -0
  48. package/dist/shared/tanstack/virtual.svelte.d.ts +14 -0
  49. package/dist/shared/tanstack/virtual.svelte.js +76 -0
  50. package/dist/shared/types.d.ts +2 -0
  51. package/dist/shared/utils/filter.d.ts +5 -0
  52. package/dist/shared/utils/filter.js +62 -0
  53. package/dist/shared/utils/selection_utils.js +1 -1
  54. package/dist/shared/utils/table_utils.d.ts +1 -14
  55. package/dist/shared/utils/table_utils.js +0 -61
  56. package/dist/standalone/Index.svelte +71 -46
  57. package/dist/standalone/Index.svelte.d.ts +4 -23
  58. package/dist/types.d.ts +32 -0
  59. package/dist/types.js +1 -0
  60. package/package.json +12 -11
  61. package/shared/BooleanCell.svelte +12 -6
  62. package/shared/CellMenu.svelte +74 -49
  63. package/shared/CellMenuButton.svelte +3 -3
  64. package/shared/CellMenuIcons.svelte +1 -1
  65. package/shared/DataCell.svelte +189 -0
  66. package/shared/EditableCell.svelte +88 -64
  67. package/shared/EmptyRowButton.svelte +2 -2
  68. package/shared/FilterMenu.svelte +26 -18
  69. package/shared/HeaderCell.svelte +218 -0
  70. package/shared/RowNumber.svelte +4 -2
  71. package/shared/Table.svelte +1037 -949
  72. package/shared/Toolbar.svelte +32 -22
  73. package/shared/column_measurement.svelte.ts +103 -0
  74. package/shared/icons/FilterIcon.svelte +14 -6
  75. package/shared/icons/Padlock.svelte +6 -2
  76. package/shared/icons/SelectionButtons.svelte +23 -8
  77. package/shared/icons/SortButtonDown.svelte +15 -4
  78. package/shared/icons/SortButtonUp.svelte +15 -5
  79. package/shared/icons/SortIcon.svelte +13 -7
  80. package/shared/tanstack/index.ts +23 -0
  81. package/shared/tanstack/table.svelte.ts +117 -0
  82. package/shared/tanstack/virtual.svelte.ts +105 -0
  83. package/shared/types.ts +3 -0
  84. package/shared/utils/filter.ts +66 -0
  85. package/shared/utils/selection_utils.ts +1 -1
  86. package/shared/utils/table_utils.ts +1 -100
  87. package/standalone/Index.svelte +71 -46
  88. package/test/filter.test.ts +350 -0
  89. package/test/selection_utils.test.ts +416 -0
  90. package/test/table_utils.test.ts +45 -112
  91. package/types.ts +34 -0
  92. package/dist/shared/TableCell.svelte +0 -330
  93. package/dist/shared/TableCell.svelte.d.ts +0 -66
  94. package/dist/shared/TableHeader.svelte +0 -344
  95. package/dist/shared/TableHeader.svelte.d.ts +0 -61
  96. package/dist/shared/VirtualTable.svelte +0 -379
  97. package/dist/shared/VirtualTable.svelte.d.ts +0 -42
  98. package/dist/shared/context/dataframe_context.d.ts +0 -180
  99. package/dist/shared/context/dataframe_context.js +0 -412
  100. package/dist/shared/icons/SortArrowDown.svelte +0 -25
  101. package/dist/shared/icons/SortArrowDown.svelte.d.ts +0 -20
  102. package/dist/shared/icons/SortArrowUp.svelte +0 -25
  103. package/dist/shared/icons/SortArrowUp.svelte.d.ts +0 -20
  104. package/dist/shared/utils/data_processing.d.ts +0 -14
  105. package/dist/shared/utils/data_processing.js +0 -47
  106. package/dist/shared/utils/drag_utils.d.ts +0 -15
  107. package/dist/shared/utils/drag_utils.js +0 -67
  108. package/dist/shared/utils/filter_utils.d.ts +0 -29
  109. package/dist/shared/utils/filter_utils.js +0 -123
  110. package/dist/shared/utils/keyboard_utils.d.ts +0 -3
  111. package/dist/shared/utils/keyboard_utils.js +0 -236
  112. package/dist/shared/utils/menu_utils.d.ts +0 -42
  113. package/dist/shared/utils/menu_utils.js +0 -58
  114. package/dist/shared/utils/sort_utils.d.ts +0 -26
  115. package/dist/shared/utils/sort_utils.js +0 -59
  116. package/shared/TableCell.svelte +0 -330
  117. package/shared/TableHeader.svelte +0 -344
  118. package/shared/VirtualTable.svelte +0 -379
  119. package/shared/context/dataframe_context.ts +0 -701
  120. package/shared/icons/SortArrowDown.svelte +0 -25
  121. package/shared/icons/SortArrowUp.svelte +0 -25
  122. package/shared/utils/data_processing.ts +0 -77
  123. package/shared/utils/drag_utils.ts +0 -105
  124. package/shared/utils/filter_utils.ts +0 -208
  125. package/shared/utils/keyboard_utils.ts +0 -309
  126. package/shared/utils/menu_utils.ts +0 -115
  127. package/shared/utils/sort_utils.ts +0 -91
  128. package/test/sort_utils.test.ts +0 -323
@@ -1,309 +0,0 @@
1
- import { dequal } from "dequal/lite";
2
- import { handle_delete_key } from "../utils/selection_utils";
3
- import type { DataFrameContext } from "../context/dataframe_context";
4
- import { tick } from "svelte";
5
- import { get } from "svelte/store";
6
- import { copy_table_data } from "./table_utils";
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
- if (ctx.data[row][col].display_value !== undefined) {
19
- ctx.data[row][col].display_value = input_value;
20
- }
21
-
22
- if (old_value !== input_value && ctx.dispatch) {
23
- ctx.dispatch("change", {
24
- data: ctx.data.map((row) => row.map((cell) => cell.value)),
25
- headers: ctx.headers?.map((h) => h.value) || [],
26
- metadata: null
27
- });
28
- }
29
-
30
- ctx.actions.set_selected([row, col]);
31
- }
32
-
33
- export async function handle_cell_blur(
34
- event: FocusEvent,
35
- ctx: DataFrameContext,
36
- coords: [number, number]
37
- ): Promise<void> {
38
- if (!ctx.data || !ctx.headers || !ctx.els) return;
39
-
40
- const input_el = event.target as HTMLInputElement;
41
- if (!input_el || input_el.value === undefined) return;
42
-
43
- await save_cell_value(input_el.value, ctx, coords[0], coords[1]);
44
- }
45
-
46
- function handle_header_navigation(
47
- event: KeyboardEvent,
48
- ctx: DataFrameContext
49
- ): boolean {
50
- const state = get(ctx.state);
51
- const selected_header = state.ui_state.selected_header;
52
- const header_edit = state.ui_state.header_edit;
53
- const headers = ctx.headers || [];
54
-
55
- if (selected_header === false || header_edit !== false) return false;
56
-
57
- switch (event.key) {
58
- case "ArrowDown":
59
- ctx.actions.set_selected_header(false);
60
- ctx.actions.set_selected([0, selected_header as number]);
61
- ctx.actions.set_selected_cells([[0, selected_header as number]]);
62
- return true;
63
- case "ArrowLeft":
64
- ctx.actions.set_selected_header(
65
- selected_header > 0 ? selected_header - 1 : selected_header
66
- );
67
- return true;
68
- case "ArrowRight":
69
- ctx.actions.set_selected_header(
70
- selected_header < headers.length - 1
71
- ? selected_header + 1
72
- : selected_header
73
- );
74
- return true;
75
- case "Escape":
76
- event.preventDefault();
77
- ctx.actions.set_selected_header(false);
78
- return true;
79
- case "Enter":
80
- event.preventDefault();
81
- if (state.config.editable) {
82
- ctx.actions.set_header_edit(selected_header);
83
- }
84
- return true;
85
- }
86
- return false;
87
- }
88
-
89
- // eslint-disable-next-line complexity
90
- function handle_delete_operation(
91
- event: KeyboardEvent,
92
- ctx: DataFrameContext
93
- ): boolean {
94
- if (!ctx.data || !ctx.headers || !ctx.els || !ctx.dispatch) return false;
95
-
96
- const state = get(ctx.state);
97
- if (!state.config.editable) return false;
98
- if (event.key !== "Delete" && event.key !== "Backspace") return false;
99
-
100
- const editing = state.ui_state.editing;
101
- const selected_cells = state.ui_state.selected_cells;
102
-
103
- const static_columns = state.config.static_columns || [];
104
- if (selected_cells.some(([_, col]) => static_columns.includes(col))) {
105
- return false;
106
- }
107
-
108
- if (editing) {
109
- const [row, col] = editing;
110
- const input_el = ctx.els[ctx.data[row][col].id]?.input;
111
- if (input_el && input_el.selectionStart !== input_el.selectionEnd) {
112
- return false;
113
- }
114
- if (
115
- event.key === "Delete" &&
116
- input_el?.selectionStart !== input_el?.value.length
117
- ) {
118
- return false;
119
- }
120
- if (event.key === "Backspace" && input_el?.selectionStart !== 0) {
121
- return false;
122
- }
123
- }
124
-
125
- event.preventDefault();
126
- if (selected_cells.length > 0) {
127
- const new_data = handle_delete_key(ctx.data, selected_cells);
128
- ctx.dispatch("change", {
129
- data: new_data.map((row) => row.map((cell) => cell.value)),
130
- headers: ctx.headers.map((h) => h.value),
131
- metadata: null
132
- });
133
- }
134
- return true;
135
- }
136
-
137
- function handle_arrow_keys(
138
- event: KeyboardEvent,
139
- ctx: DataFrameContext,
140
- i: number,
141
- j: number
142
- ): boolean {
143
- const state = get(ctx.state);
144
- const editing = state.ui_state.editing;
145
- const selected_cells = state.ui_state.selected_cells;
146
-
147
- if (editing) return false;
148
- if (!ctx.data) return false;
149
-
150
- event.preventDefault();
151
-
152
- const next_coords = ctx.actions.move_cursor(event, [i, j], ctx.data);
153
- if (next_coords) {
154
- if (event.shiftKey) {
155
- ctx.actions.set_selected_cells(
156
- ctx.actions.get_range_selection(
157
- selected_cells.length > 0 ? selected_cells[0] : [i, j],
158
- next_coords
159
- )
160
- );
161
- ctx.actions.set_editing(false);
162
- } else {
163
- ctx.actions.set_selected_cells([next_coords]);
164
- ctx.actions.set_editing(false);
165
- }
166
- ctx.actions.set_selected(next_coords);
167
- } else if (next_coords === false && event.key === "ArrowUp" && i === 0) {
168
- ctx.actions.set_selected_header(j);
169
- ctx.actions.set_selected(false);
170
- ctx.actions.set_selected_cells([]);
171
- ctx.actions.set_editing(false);
172
- }
173
- return true;
174
- }
175
-
176
- async function handle_enter_key(
177
- event: KeyboardEvent,
178
- ctx: DataFrameContext,
179
- i: number,
180
- j: number
181
- ): Promise<boolean> {
182
- if (!ctx.data || !ctx.els) return false;
183
-
184
- const state = get(ctx.state);
185
- if (!state.config.editable) return false;
186
-
187
- const editing = state.ui_state.editing;
188
- if (editing && event.shiftKey) return false;
189
-
190
- event.preventDefault();
191
-
192
- if (editing && dequal(editing, [i, j])) {
193
- const cell_id = ctx.data[i][j].id;
194
- const input_el = ctx.els[cell_id]?.input;
195
- if (input_el) {
196
- await save_cell_value(input_el.value, ctx, i, j);
197
- }
198
- ctx.actions.set_editing(false);
199
- await tick();
200
- ctx.parent_element?.focus();
201
- } else {
202
- ctx.actions.set_editing([i, j]);
203
- }
204
-
205
- return true;
206
- }
207
-
208
- function handle_tab_key(
209
- event: KeyboardEvent,
210
- ctx: DataFrameContext,
211
- i: number,
212
- j: number
213
- ): boolean {
214
- if (!ctx.data) return false;
215
-
216
- event.preventDefault();
217
- ctx.actions.set_editing(false);
218
- const next_cell = ctx.actions.get_next_cell_coordinates(
219
- [i, j],
220
- ctx.data,
221
- event.shiftKey
222
- );
223
- if (next_cell) {
224
- ctx.actions.set_selected_cells([next_cell]);
225
- ctx.actions.set_selected(next_cell);
226
- if (get(ctx.state).config.editable) {
227
- ctx.actions.set_editing(next_cell);
228
- }
229
- }
230
- return true;
231
- }
232
-
233
- function handle_default_key(
234
- event: KeyboardEvent,
235
- ctx: DataFrameContext,
236
- i: number,
237
- j: number
238
- ): boolean {
239
- const state = get(ctx.state);
240
- if (!state.config.editable) return false;
241
-
242
- const editing = state.ui_state.editing;
243
-
244
- if (event.key.length === 1 && (!editing || !dequal(editing, [i, j]))) {
245
- ctx.actions.set_editing([i, j]);
246
- return true;
247
- }
248
- return false;
249
- }
250
-
251
- async function handle_cell_navigation(
252
- event: KeyboardEvent,
253
- ctx: DataFrameContext
254
- ): Promise<boolean> {
255
- if (!ctx.data) return false;
256
-
257
- const state = get(ctx.state);
258
- const selected = state.ui_state.selected;
259
- const selected_cells = state.ui_state.selected_cells;
260
-
261
- if (!selected) return false;
262
- if (event.key === "c" && (event.metaKey || event.ctrlKey)) {
263
- event.preventDefault();
264
- if (selected_cells.length > 0) {
265
- await copy_table_data(ctx.data, selected_cells);
266
- }
267
- ctx.actions.set_copy_flash(true);
268
- return true;
269
- }
270
-
271
- const [i, j] = selected;
272
-
273
- switch (event.key) {
274
- case "ArrowRight":
275
- case "ArrowLeft":
276
- case "ArrowDown":
277
- case "ArrowUp":
278
- return handle_arrow_keys(event, ctx, i, j);
279
- case "Escape":
280
- if (!state.config.editable) return false;
281
- event.preventDefault();
282
- ctx.actions.set_editing(false);
283
- tick().then(() => {
284
- if (ctx.parent_element) {
285
- ctx.parent_element.focus();
286
- }
287
- });
288
-
289
- return true;
290
- case "Enter":
291
- return await handle_enter_key(event, ctx, i, j);
292
- case "Tab":
293
- return handle_tab_key(event, ctx, i, j);
294
- case "Delete":
295
- case "Backspace":
296
- return handle_delete_operation(event, ctx);
297
- default:
298
- return handle_default_key(event, ctx, i, j);
299
- }
300
- }
301
-
302
- export async function handle_keydown(
303
- event: KeyboardEvent,
304
- context: DataFrameContext
305
- ): Promise<void> {
306
- if (handle_header_navigation(event, context)) return;
307
- if (handle_delete_operation(event, context)) return;
308
- await handle_cell_navigation(event, context);
309
- }
@@ -1,115 +0,0 @@
1
- export function toggle_header_menu(
2
- event: MouseEvent,
3
- col: number,
4
- active_header_menu: { col: number; x: number; y: number } | null,
5
- set_active_header_menu: (
6
- menu: { col: number; x: number; y: number } | null
7
- ) => void
8
- ): void {
9
- event.stopPropagation();
10
- if (active_header_menu && active_header_menu.col === col) {
11
- set_active_header_menu(null);
12
- } else {
13
- const header = (event.target as HTMLElement).closest("th");
14
- if (header) {
15
- const rect = header.getBoundingClientRect();
16
- set_active_header_menu({ col, x: rect.right, y: rect.bottom });
17
- }
18
- }
19
- }
20
-
21
- export function toggle_cell_menu(
22
- event: MouseEvent,
23
- row: number,
24
- col: number,
25
- active_cell_menu: { row: number; col: number; x: number; y: number } | null,
26
- set_active_cell_menu: (
27
- menu: { row: number; col: number; x: number; y: number } | null
28
- ) => void
29
- ): void {
30
- event.stopPropagation();
31
- if (
32
- active_cell_menu &&
33
- active_cell_menu.row === row &&
34
- active_cell_menu.col === col
35
- ) {
36
- set_active_cell_menu(null);
37
- } else {
38
- const cell = (event.target as HTMLElement).closest("td");
39
- if (cell) {
40
- const rect = cell.getBoundingClientRect();
41
- set_active_cell_menu({ row, col, x: rect.right, y: rect.bottom });
42
- }
43
- }
44
- }
45
-
46
- export function add_row_at(
47
- index: number,
48
- position: "above" | "below",
49
- add_row: (index?: number) => void,
50
- clear_menus: () => void
51
- ): void {
52
- const row_index = position === "above" ? index : index + 1;
53
- add_row(row_index);
54
- clear_menus();
55
- }
56
-
57
- export function add_col_at(
58
- index: number,
59
- position: "left" | "right",
60
- add_col: (index?: number) => void,
61
- clear_menus: () => void
62
- ): void {
63
- const col_index = position === "left" ? index : index + 1;
64
- add_col(col_index);
65
- clear_menus();
66
- }
67
-
68
- export function delete_row_at(
69
- index: number,
70
- delete_row: (index: number) => void,
71
- clear_menus: () => void
72
- ): void {
73
- delete_row(index);
74
- clear_menus();
75
- }
76
-
77
- export function delete_col_at(
78
- index: number,
79
- delete_col: (index: number) => void,
80
- clear_menus: () => void
81
- ): void {
82
- delete_col(index);
83
- clear_menus();
84
- }
85
-
86
- export function toggle_header_button(
87
- col: number,
88
- active_button: { type: "header" | "cell"; row?: number; col: number } | null,
89
- set_active_button: (
90
- button: { type: "header" | "cell"; row?: number; col: number } | null
91
- ) => void
92
- ): void {
93
- set_active_button(
94
- active_button?.type === "header" && active_button.col === col
95
- ? null
96
- : { type: "header", col }
97
- );
98
- }
99
-
100
- export function toggle_cell_button(
101
- row: number,
102
- col: number,
103
- active_button: { type: "header" | "cell"; row?: number; col: number } | null,
104
- set_active_button: (
105
- button: { type: "header" | "cell"; row?: number; col: number } | null
106
- ) => void
107
- ): void {
108
- set_active_button(
109
- active_button?.type === "cell" &&
110
- active_button.row === row &&
111
- active_button.col === col
112
- ? null
113
- : { type: "cell", row, col }
114
- );
115
- }
@@ -1,91 +0,0 @@
1
- import type { Headers, CellValue } from "../types";
2
- import { sort_table_data } from "./table_utils";
3
-
4
- export type SortDirection = "asc" | "desc";
5
-
6
- export function get_sort_status(
7
- name: string,
8
- sort_columns: { col: number; direction: SortDirection }[],
9
- headers: Headers
10
- ): "none" | "asc" | "desc" {
11
- if (!sort_columns.length) return "none";
12
-
13
- const sort_item = sort_columns.find((item) => {
14
- const col = item.col;
15
- if (col < 0 || col >= headers.length) return false;
16
- return headers[col] === name;
17
- });
18
-
19
- if (!sort_item) return "none";
20
- return sort_item.direction;
21
- }
22
-
23
- export function sort_data(
24
- data: { id: string; value: CellValue }[][],
25
- sort_columns: { col: number; direction: SortDirection }[]
26
- ): number[] {
27
- if (!data || !data.length || !data[0]) {
28
- return [];
29
- }
30
-
31
- if (sort_columns.length > 0) {
32
- const row_indices = [...Array(data.length)].map((_, i) => i);
33
- row_indices.sort((row_a_idx, row_b_idx) => {
34
- const row_a = data[row_a_idx];
35
- const row_b = data[row_b_idx];
36
-
37
- for (const { col: sort_by, direction } of sort_columns) {
38
- if (
39
- !row_a ||
40
- !row_b ||
41
- sort_by < 0 ||
42
- sort_by >= row_a.length ||
43
- sort_by >= row_b.length ||
44
- !row_a[sort_by] ||
45
- !row_b[sort_by]
46
- ) {
47
- continue;
48
- }
49
-
50
- const val_a = row_a[sort_by].value;
51
- const val_b = row_b[sort_by].value;
52
- const comparison = val_a < val_b ? -1 : val_a > val_b ? 1 : 0;
53
-
54
- if (comparison !== 0) {
55
- return direction === "asc" ? comparison : -comparison;
56
- }
57
- }
58
-
59
- return 0;
60
- });
61
- return row_indices;
62
- }
63
- return [...Array(data.length)].map((_, i) => i);
64
- }
65
-
66
- export function sort_data_and_preserve_selection(
67
- data: { id: string; value: CellValue }[][],
68
- display_value: string[][] | null,
69
- styling: string[][] | null,
70
- sort_columns: { col: number; direction: SortDirection }[],
71
- selected: [number, number] | false,
72
- get_current_indices: (
73
- id: string,
74
- data: { id: string; value: CellValue }[][]
75
- ) => [number, number]
76
- ): { data: typeof data; selected: [number, number] | false } {
77
- let id = null;
78
- if (selected && selected[0] in data && selected[1] in data[selected[0]]) {
79
- id = data[selected[0]][selected[1]].id;
80
- }
81
-
82
- sort_table_data(data, display_value, styling, sort_columns);
83
-
84
- let new_selected = selected;
85
- if (id) {
86
- const [i, j] = get_current_indices(id, data);
87
- new_selected = [i, j];
88
- }
89
-
90
- return { data, selected: new_selected };
91
- }