@gradio/dataframe 0.16.5 → 0.17.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.
- package/CHANGELOG.md +34 -0
- package/Dataframe.stories.svelte +202 -9
- package/Index.svelte +7 -13
- package/dist/Index.svelte +5 -9
- package/dist/Index.svelte.d.ts +9 -2
- package/dist/shared/CellMenu.svelte +91 -10
- package/dist/shared/CellMenu.svelte.d.ts +6 -0
- package/dist/shared/CellMenuButton.svelte +45 -0
- package/dist/shared/CellMenuButton.svelte.d.ts +16 -0
- package/dist/shared/CellMenuIcons.svelte +79 -0
- package/dist/shared/EditableCell.svelte +83 -14
- package/dist/shared/EditableCell.svelte.d.ts +12 -3
- package/dist/shared/EmptyRowButton.svelte +28 -0
- package/dist/shared/EmptyRowButton.svelte.d.ts +16 -0
- package/dist/shared/RowNumber.svelte +40 -0
- package/dist/shared/RowNumber.svelte.d.ts +17 -0
- package/dist/shared/Table.svelte +564 -1121
- package/dist/shared/Table.svelte.d.ts +4 -0
- package/dist/shared/TableCell.svelte +291 -0
- package/dist/shared/TableCell.svelte.d.ts +57 -0
- package/dist/shared/TableHeader.svelte +239 -0
- package/dist/shared/TableHeader.svelte.d.ts +45 -0
- package/dist/shared/Toolbar.svelte +18 -8
- package/dist/shared/VirtualTable.svelte +66 -19
- package/dist/shared/VirtualTable.svelte.d.ts +4 -0
- package/dist/shared/context/keyboard_context.d.ts +37 -0
- package/dist/shared/context/keyboard_context.js +12 -0
- package/dist/shared/context/selection_context.d.ts +32 -0
- package/dist/shared/context/selection_context.js +107 -0
- package/dist/shared/context/table_context.d.ts +141 -0
- package/dist/shared/context/table_context.js +375 -0
- package/dist/shared/icons/Padlock.svelte +24 -0
- package/dist/shared/icons/Padlock.svelte.d.ts +23 -0
- package/dist/shared/icons/SelectionButtons.svelte +85 -0
- package/dist/shared/icons/SelectionButtons.svelte.d.ts +18 -0
- package/dist/shared/icons/SortArrowDown.svelte +24 -0
- package/dist/shared/icons/SortArrowDown.svelte.d.ts +16 -0
- package/dist/shared/icons/SortArrowUp.svelte +24 -0
- package/dist/shared/icons/SortArrowUp.svelte.d.ts +16 -0
- package/dist/shared/icons/SortButtonDown.svelte +14 -0
- package/dist/shared/icons/SortButtonDown.svelte.d.ts +23 -0
- package/dist/shared/icons/SortButtonUp.svelte +15 -0
- package/dist/shared/icons/SortButtonUp.svelte.d.ts +23 -0
- package/dist/shared/icons/SortIcon.svelte +46 -68
- package/dist/shared/icons/SortIcon.svelte.d.ts +3 -2
- package/dist/shared/selection_utils.d.ts +2 -1
- package/dist/shared/selection_utils.js +39 -10
- package/dist/shared/utils/data_processing.d.ts +13 -0
- package/dist/shared/utils/data_processing.js +45 -0
- package/dist/shared/utils/drag_utils.d.ts +15 -0
- package/dist/shared/utils/drag_utils.js +57 -0
- package/dist/shared/utils/keyboard_utils.d.ts +2 -0
- package/dist/shared/utils/keyboard_utils.js +186 -0
- package/dist/shared/utils/sort_utils.d.ts +22 -3
- package/dist/shared/utils/sort_utils.js +44 -24
- package/dist/shared/utils/table_utils.d.ts +6 -5
- package/dist/shared/utils/table_utils.js +13 -56
- package/package.json +7 -7
- package/shared/CellMenu.svelte +90 -10
- package/shared/CellMenuButton.svelte +46 -0
- package/shared/CellMenuIcons.svelte +79 -0
- package/shared/EditableCell.svelte +97 -18
- package/shared/EmptyRowButton.svelte +29 -0
- package/shared/RowNumber.svelte +41 -0
- package/shared/Table.svelte +604 -1235
- package/shared/TableCell.svelte +324 -0
- package/shared/TableHeader.svelte +256 -0
- package/shared/Toolbar.svelte +19 -8
- package/shared/VirtualTable.svelte +72 -19
- package/shared/context/keyboard_context.ts +65 -0
- package/shared/context/selection_context.ts +168 -0
- package/shared/context/table_context.ts +625 -0
- package/shared/icons/Padlock.svelte +24 -0
- package/shared/icons/SelectionButtons.svelte +93 -0
- package/shared/icons/SortArrowDown.svelte +25 -0
- package/shared/icons/SortArrowUp.svelte +25 -0
- package/shared/icons/SortButtonDown.svelte +14 -0
- package/shared/icons/SortButtonUp.svelte +15 -0
- package/shared/icons/SortIcon.svelte +47 -70
- package/shared/selection_utils.ts +39 -13
- package/shared/utils/data_processing.ts +72 -0
- package/shared/utils/drag_utils.ts +92 -0
- package/shared/utils/keyboard_utils.ts +238 -0
- package/shared/utils/sort_utils.test.ts +262 -14
- package/shared/utils/sort_utils.ts +67 -31
- package/shared/utils/table_utils.test.ts +66 -45
- package/shared/utils/table_utils.ts +16 -86
package/shared/Table.svelte
CHANGED
|
@@ -1,43 +1,53 @@
|
|
|
1
|
+
<script lang="ts" context="module">
|
|
2
|
+
import {
|
|
3
|
+
type SortDirection,
|
|
4
|
+
create_dataframe_context
|
|
5
|
+
} from "./context/table_context";
|
|
6
|
+
import { create_keyboard_context } from "./context/keyboard_context";
|
|
7
|
+
import { create_selection_context } from "./context/selection_context";
|
|
8
|
+
</script>
|
|
9
|
+
|
|
1
10
|
<script lang="ts">
|
|
2
11
|
import { afterUpdate, createEventDispatcher, tick, onMount } from "svelte";
|
|
3
12
|
import { dequal } from "dequal/lite";
|
|
4
13
|
import { Upload } from "@gradio/upload";
|
|
5
14
|
|
|
6
15
|
import EditableCell from "./EditableCell.svelte";
|
|
16
|
+
import RowNumber from "./RowNumber.svelte";
|
|
17
|
+
import TableHeader from "./TableHeader.svelte";
|
|
18
|
+
import TableCell from "./TableCell.svelte";
|
|
19
|
+
import EmptyRowButton from "./EmptyRowButton.svelte";
|
|
7
20
|
import type { SelectData } from "@gradio/utils";
|
|
8
21
|
import type { I18nFormatter } from "js/core/src/gradio_helper";
|
|
9
22
|
import { type Client } from "@gradio/client";
|
|
10
23
|
import VirtualTable from "./VirtualTable.svelte";
|
|
11
|
-
import type {
|
|
12
|
-
Headers,
|
|
13
|
-
HeadersWithIDs,
|
|
14
|
-
DataframeValue,
|
|
15
|
-
Datatype
|
|
16
|
-
} from "./utils";
|
|
24
|
+
import type { Headers, DataframeValue, Datatype } from "./utils";
|
|
17
25
|
import CellMenu from "./CellMenu.svelte";
|
|
18
26
|
import Toolbar from "./Toolbar.svelte";
|
|
19
|
-
import
|
|
20
|
-
import type { CellCoordinate, EditingState } from "./types";
|
|
27
|
+
import type { CellCoordinate } from "./types";
|
|
21
28
|
import {
|
|
22
29
|
is_cell_selected,
|
|
23
|
-
handle_selection,
|
|
24
|
-
handle_delete_key,
|
|
25
30
|
should_show_cell_menu,
|
|
26
31
|
get_next_cell_coordinates,
|
|
27
32
|
get_range_selection,
|
|
28
33
|
move_cursor,
|
|
29
34
|
get_current_indices,
|
|
30
35
|
handle_click_outside as handle_click_outside_util,
|
|
31
|
-
select_column,
|
|
32
|
-
select_row,
|
|
33
36
|
calculate_selection_positions
|
|
34
37
|
} from "./selection_utils";
|
|
35
38
|
import {
|
|
36
39
|
copy_table_data,
|
|
37
40
|
get_max,
|
|
38
|
-
handle_file_upload
|
|
39
|
-
sort_table_data
|
|
41
|
+
handle_file_upload
|
|
40
42
|
} from "./utils/table_utils";
|
|
43
|
+
import { make_headers, process_data } from "./utils/data_processing";
|
|
44
|
+
import { handle_keydown } from "./utils/keyboard_utils";
|
|
45
|
+
import {
|
|
46
|
+
create_drag_handlers,
|
|
47
|
+
type DragState,
|
|
48
|
+
type DragHandlers
|
|
49
|
+
} from "./utils/drag_utils";
|
|
50
|
+
import { sort_data_and_preserve_selection } from "./utils/sort_utils";
|
|
41
51
|
|
|
42
52
|
export let datatype: Datatype | Datatype[];
|
|
43
53
|
export let label: string | null = null;
|
|
@@ -51,6 +61,7 @@
|
|
|
51
61
|
right: string;
|
|
52
62
|
display: boolean;
|
|
53
63
|
}[];
|
|
64
|
+
export let components: Record<string, any> = {};
|
|
54
65
|
|
|
55
66
|
export let editable = true;
|
|
56
67
|
export let wrap = false;
|
|
@@ -69,24 +80,40 @@
|
|
|
69
80
|
export let max_chars: number | undefined = undefined;
|
|
70
81
|
export let show_search: "none" | "search" | "filter" = "none";
|
|
71
82
|
export let pinned_columns = 0;
|
|
83
|
+
export let static_columns: (string | number)[] = [];
|
|
72
84
|
|
|
73
|
-
let actual_pinned_columns = 0;
|
|
74
85
|
$: actual_pinned_columns =
|
|
75
86
|
pinned_columns && data?.[0]?.length
|
|
76
87
|
? Math.min(pinned_columns, data[0].length)
|
|
77
88
|
: 0;
|
|
78
89
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
90
|
+
const { state: df_state, actions: df_actions } = create_dataframe_context({
|
|
91
|
+
show_fullscreen_button,
|
|
92
|
+
show_copy_button,
|
|
93
|
+
show_search,
|
|
94
|
+
show_row_numbers,
|
|
95
|
+
editable,
|
|
96
|
+
pinned_columns,
|
|
97
|
+
show_label,
|
|
98
|
+
line_breaks,
|
|
99
|
+
wrap,
|
|
100
|
+
max_height,
|
|
101
|
+
column_widths,
|
|
102
|
+
max_chars
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
$: selected_cells = $df_state.ui_state.selected_cells; // $: {
|
|
106
|
+
let previous_selected_cells: [number, number][] = [];
|
|
107
|
+
$: {
|
|
108
|
+
if (copy_flash && !dequal(selected_cells, previous_selected_cells)) {
|
|
109
|
+
keyboard_ctx?.set_copy_flash(false);
|
|
110
|
+
}
|
|
111
|
+
previous_selected_cells = selected_cells;
|
|
112
|
+
}
|
|
113
|
+
$: selected = $df_state.ui_state.selected;
|
|
86
114
|
|
|
87
115
|
export let display_value: string[][] | null = null;
|
|
88
116
|
export let styling: string[][] | null = null;
|
|
89
|
-
let t_rect: DOMRectReadOnly;
|
|
90
117
|
let els: Record<
|
|
91
118
|
string,
|
|
92
119
|
{ cell: null | HTMLTableCellElement; input: null | HTMLInputElement }
|
|
@@ -100,21 +127,12 @@
|
|
|
100
127
|
search: string | null;
|
|
101
128
|
}>();
|
|
102
129
|
|
|
103
|
-
|
|
130
|
+
$: editing = $df_state.ui_state.editing;
|
|
104
131
|
let clear_on_focus = false;
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
col: number;
|
|
110
|
-
x: number;
|
|
111
|
-
y: number;
|
|
112
|
-
} | null = null;
|
|
113
|
-
let active_header_menu: {
|
|
114
|
-
col: number;
|
|
115
|
-
x: number;
|
|
116
|
-
y: number;
|
|
117
|
-
} | null = null;
|
|
132
|
+
$: header_edit = $df_state.ui_state.header_edit;
|
|
133
|
+
$: selected_header = $df_state.ui_state.selected_header;
|
|
134
|
+
$: active_cell_menu = $df_state.ui_state.active_cell_menu;
|
|
135
|
+
$: active_header_menu = $df_state.ui_state.active_header_menu;
|
|
118
136
|
let is_fullscreen = false;
|
|
119
137
|
let dragging = false;
|
|
120
138
|
let copy_flash = false;
|
|
@@ -138,336 +156,166 @@
|
|
|
138
156
|
return Math.random().toString(36).substring(2, 15);
|
|
139
157
|
}
|
|
140
158
|
|
|
141
|
-
|
|
142
|
-
_head: Headers,
|
|
143
|
-
col_count: [number, "fixed" | "dynamic"],
|
|
144
|
-
els: Record<
|
|
145
|
-
string,
|
|
146
|
-
{ cell: null | HTMLTableCellElement; input: null | HTMLInputElement }
|
|
147
|
-
>
|
|
148
|
-
): HeadersWithIDs {
|
|
149
|
-
let _h = _head || [];
|
|
150
|
-
if (col_count[1] === "fixed" && _h.length < col_count[0]) {
|
|
151
|
-
const fill = Array(col_count[0] - _h.length)
|
|
152
|
-
.fill("")
|
|
153
|
-
.map((_, i) => `${i + _h.length}`);
|
|
154
|
-
_h = _h.concat(fill);
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
if (!_h || _h.length === 0) {
|
|
158
|
-
return Array(col_count[0])
|
|
159
|
-
.fill(0)
|
|
160
|
-
.map((_, i) => {
|
|
161
|
-
const _id = make_id();
|
|
162
|
-
els[_id] = { cell: null, input: null };
|
|
163
|
-
return { id: _id, value: JSON.stringify(i + 1) };
|
|
164
|
-
});
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
return _h.map((h, i) => {
|
|
168
|
-
const _id = make_id();
|
|
169
|
-
els[_id] = { cell: null, input: null };
|
|
170
|
-
return { id: _id, value: h ?? "" };
|
|
171
|
-
});
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
function process_data(_values: (string | number)[][]): {
|
|
175
|
-
value: string | number;
|
|
176
|
-
id: string;
|
|
177
|
-
}[][] {
|
|
178
|
-
const data_row_length = _values.length;
|
|
179
|
-
if (data_row_length === 0) return [];
|
|
180
|
-
return Array(row_count[1] === "fixed" ? row_count[0] : data_row_length)
|
|
181
|
-
.fill(0)
|
|
182
|
-
.map((_, i) => {
|
|
183
|
-
return Array(
|
|
184
|
-
col_count[1] === "fixed"
|
|
185
|
-
? col_count[0]
|
|
186
|
-
: _values[0].length || headers.length
|
|
187
|
-
)
|
|
188
|
-
.fill(0)
|
|
189
|
-
.map((_, j) => {
|
|
190
|
-
const id = make_id();
|
|
191
|
-
els[id] = els[id] || { input: null, cell: null };
|
|
192
|
-
const obj = { value: _values?.[i]?.[j] ?? "", id };
|
|
193
|
-
data_binding[id] = obj;
|
|
194
|
-
return obj;
|
|
195
|
-
});
|
|
196
|
-
});
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
let _headers = make_headers(headers, col_count, els);
|
|
159
|
+
let _headers = make_headers(headers, col_count, els, make_id);
|
|
200
160
|
let old_headers: string[] = headers;
|
|
201
161
|
|
|
202
162
|
$: {
|
|
203
163
|
if (!dequal(headers, old_headers)) {
|
|
204
|
-
_headers = make_headers(headers, col_count, els);
|
|
164
|
+
_headers = make_headers(headers, col_count, els, make_id);
|
|
205
165
|
old_headers = JSON.parse(JSON.stringify(headers));
|
|
206
166
|
}
|
|
207
167
|
}
|
|
208
168
|
|
|
209
169
|
let data: { id: string; value: string | number }[][] = [[]];
|
|
210
170
|
let old_val: undefined | (string | number)[][] = undefined;
|
|
171
|
+
let search_results: {
|
|
172
|
+
id: string;
|
|
173
|
+
value: string | number;
|
|
174
|
+
display_value?: string;
|
|
175
|
+
styling?: string;
|
|
176
|
+
}[][] = [[]];
|
|
211
177
|
|
|
212
178
|
$: if (!dequal(values, old_val)) {
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
179
|
+
if (parent) {
|
|
180
|
+
// only clear column widths when the data structure changes
|
|
181
|
+
const is_reset =
|
|
182
|
+
values.length === 0 || (values.length === 1 && values[0].length === 0);
|
|
183
|
+
const is_different_structure =
|
|
184
|
+
old_val !== undefined &&
|
|
185
|
+
(values.length !== old_val.length ||
|
|
186
|
+
(values[0] && old_val[0] && values[0].length !== old_val[0].length));
|
|
187
|
+
|
|
188
|
+
if (is_reset || is_different_structure) {
|
|
189
|
+
for (let i = 0; i < 50; i++) {
|
|
190
|
+
parent.style.removeProperty(`--cell-width-${i}`);
|
|
191
|
+
}
|
|
192
|
+
last_width_data_length = 0;
|
|
193
|
+
last_width_column_count = 0;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
216
196
|
|
|
217
|
-
|
|
218
|
-
|
|
197
|
+
// only reset sort state when values are changed
|
|
198
|
+
const is_reset =
|
|
199
|
+
values.length === 0 || (values.length === 1 && values[0].length === 0);
|
|
200
|
+
const is_different_structure =
|
|
201
|
+
old_val !== undefined &&
|
|
202
|
+
(values.length !== old_val.length ||
|
|
203
|
+
(values[0] && old_val[0] && values[0].length !== old_val[0].length));
|
|
219
204
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
205
|
+
data = process_data(
|
|
206
|
+
values as (string | number)[][],
|
|
207
|
+
els,
|
|
208
|
+
data_binding,
|
|
209
|
+
make_id,
|
|
210
|
+
display_value
|
|
226
211
|
);
|
|
212
|
+
old_val = JSON.parse(JSON.stringify(values)) as (string | number)[][];
|
|
227
213
|
|
|
228
|
-
if (
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
// We dispatch the value as part of the change event to ensure that the value is updated
|
|
233
|
-
// in the parent component and the updated value is passed into the user's function
|
|
234
|
-
dispatch("change", {
|
|
235
|
-
data: data.map((row) => row.map((cell) => cell.value)),
|
|
236
|
-
headers: _headers.map((h) => h.value),
|
|
237
|
-
metadata: null // the metadata (display value, styling) cannot be changed by the user so we don't need to pass it up
|
|
238
|
-
});
|
|
239
|
-
if (!value_is_output) {
|
|
240
|
-
dispatch("input");
|
|
241
|
-
}
|
|
242
|
-
previous_data = current_data;
|
|
243
|
-
previous_headers = current_headers;
|
|
214
|
+
if (is_reset || is_different_structure) {
|
|
215
|
+
df_actions.reset_sort_state();
|
|
216
|
+
} else if ($df_state.sort_state.sort_columns.length > 0) {
|
|
217
|
+
sort_data(data, display_value, styling);
|
|
244
218
|
}
|
|
245
|
-
}
|
|
246
219
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
_sort?: number,
|
|
250
|
-
direction?: SortDirection
|
|
251
|
-
): "none" | "ascending" | "descending" {
|
|
252
|
-
if (!_sort) return "none";
|
|
253
|
-
if (headers[_sort] === name) {
|
|
254
|
-
if (direction === "asc") return "ascending";
|
|
255
|
-
if (direction === "des") return "descending";
|
|
220
|
+
if ($df_state.current_search_query) {
|
|
221
|
+
df_actions.handle_search(null);
|
|
256
222
|
}
|
|
257
|
-
return "none";
|
|
258
|
-
}
|
|
259
223
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
if (selected_header !== false && header_edit === false) {
|
|
263
|
-
switch (event.key) {
|
|
264
|
-
case "ArrowDown":
|
|
265
|
-
selected = [0, selected_header];
|
|
266
|
-
selected_cells = [[0, selected_header]];
|
|
267
|
-
selected_header = false;
|
|
268
|
-
return;
|
|
269
|
-
case "ArrowLeft":
|
|
270
|
-
selected_header =
|
|
271
|
-
selected_header > 0 ? selected_header - 1 : selected_header;
|
|
272
|
-
return;
|
|
273
|
-
case "ArrowRight":
|
|
274
|
-
selected_header =
|
|
275
|
-
selected_header < _headers.length - 1
|
|
276
|
-
? selected_header + 1
|
|
277
|
-
: selected_header;
|
|
278
|
-
return;
|
|
279
|
-
case "Escape":
|
|
280
|
-
event.preventDefault();
|
|
281
|
-
selected_header = false;
|
|
282
|
-
break;
|
|
283
|
-
case "Enter":
|
|
284
|
-
event.preventDefault();
|
|
285
|
-
if (editable) {
|
|
286
|
-
header_edit = selected_header;
|
|
287
|
-
}
|
|
288
|
-
break;
|
|
289
|
-
}
|
|
224
|
+
if (parent && cells.length > 0) {
|
|
225
|
+
set_cell_widths();
|
|
290
226
|
}
|
|
227
|
+
}
|
|
291
228
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
if (editing) {
|
|
296
|
-
const [row, col] = editing;
|
|
297
|
-
const input_el = els[data[row][col].id].input;
|
|
298
|
-
if (input_el && input_el.selectionStart !== input_el.selectionEnd) {
|
|
299
|
-
return;
|
|
300
|
-
}
|
|
301
|
-
if (
|
|
302
|
-
event.key === "Delete" &&
|
|
303
|
-
input_el?.selectionStart !== input_el?.value.length
|
|
304
|
-
) {
|
|
305
|
-
return;
|
|
306
|
-
}
|
|
307
|
-
if (event.key === "Backspace" && input_el?.selectionStart !== 0) {
|
|
308
|
-
return;
|
|
309
|
-
}
|
|
310
|
-
}
|
|
229
|
+
$: if ($df_state.current_search_query !== undefined) {
|
|
230
|
+
const cell_map = new Map();
|
|
311
231
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
headers: _headers.map((h) => h.value),
|
|
318
|
-
metadata: null
|
|
232
|
+
data.forEach((row, row_idx) => {
|
|
233
|
+
row.forEach((cell, col_idx) => {
|
|
234
|
+
cell_map.set(cell.id, {
|
|
235
|
+
value: cell.value,
|
|
236
|
+
styling: styling?.[row_idx]?.[col_idx] || ""
|
|
319
237
|
});
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
return;
|
|
325
|
-
}
|
|
238
|
+
});
|
|
239
|
+
});
|
|
326
240
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
241
|
+
const filtered = df_actions.filter_data(data);
|
|
242
|
+
|
|
243
|
+
search_results = filtered.map((row) =>
|
|
244
|
+
row.map((cell) => {
|
|
245
|
+
const original = cell_map.get(cell.id);
|
|
246
|
+
return {
|
|
247
|
+
...cell,
|
|
248
|
+
display_value: original?.display_value || String(cell.value),
|
|
249
|
+
styling: original?.styling || ""
|
|
250
|
+
};
|
|
251
|
+
})
|
|
252
|
+
);
|
|
253
|
+
}
|
|
334
254
|
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
}
|
|
255
|
+
let previous_headers = _headers.map((h) => h.value);
|
|
256
|
+
let previous_data = data.map((row) => row.map((cell) => String(cell.value)));
|
|
338
257
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
selected_cells = get_range_selection(
|
|
352
|
-
selected_cells.length > 0 ? selected_cells[0] : [i, j],
|
|
353
|
-
next_coords
|
|
354
|
-
);
|
|
355
|
-
editing = false;
|
|
356
|
-
} else {
|
|
357
|
-
selected_cells = [next_coords];
|
|
358
|
-
editing = false;
|
|
359
|
-
}
|
|
360
|
-
selected = next_coords;
|
|
361
|
-
} else if (
|
|
362
|
-
next_coords === false &&
|
|
363
|
-
event.key === "ArrowUp" &&
|
|
364
|
-
i === 0
|
|
365
|
-
) {
|
|
366
|
-
selected_header = j;
|
|
367
|
-
selected = false;
|
|
368
|
-
selected_cells = [];
|
|
369
|
-
editing = false;
|
|
370
|
-
}
|
|
371
|
-
break;
|
|
372
|
-
|
|
373
|
-
case "Escape":
|
|
374
|
-
if (!editable) break;
|
|
375
|
-
event.preventDefault();
|
|
376
|
-
editing = false;
|
|
377
|
-
break;
|
|
378
|
-
case "Enter":
|
|
379
|
-
event.preventDefault();
|
|
380
|
-
if (editable) {
|
|
381
|
-
if (event.shiftKey) {
|
|
382
|
-
add_row(i);
|
|
383
|
-
await tick();
|
|
384
|
-
selected = [i + 1, j];
|
|
385
|
-
} else {
|
|
386
|
-
if (dequal(editing, [i, j])) {
|
|
387
|
-
const cell_id = data[i][j].id;
|
|
388
|
-
const input_el = els[cell_id].input;
|
|
389
|
-
if (input_el) {
|
|
390
|
-
data[i][j].value = input_el.value;
|
|
391
|
-
}
|
|
392
|
-
editing = false;
|
|
393
|
-
await tick();
|
|
394
|
-
selected = [i, j];
|
|
395
|
-
} else {
|
|
396
|
-
editing = [i, j];
|
|
397
|
-
clear_on_focus = false;
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
break;
|
|
402
|
-
case "Tab":
|
|
403
|
-
event.preventDefault();
|
|
404
|
-
editing = false;
|
|
405
|
-
const next_cell = get_next_cell_coordinates(
|
|
406
|
-
[i, j],
|
|
407
|
-
data,
|
|
408
|
-
event.shiftKey
|
|
409
|
-
);
|
|
410
|
-
if (next_cell) {
|
|
411
|
-
selected_cells = [next_cell];
|
|
412
|
-
selected = next_cell;
|
|
413
|
-
if (editable) {
|
|
414
|
-
editing = next_cell;
|
|
415
|
-
clear_on_focus = false;
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
break;
|
|
419
|
-
default:
|
|
420
|
-
if (!editable) break;
|
|
421
|
-
if (
|
|
422
|
-
(!editing || (editing && dequal(editing, [i, j]))) &&
|
|
423
|
-
event.key.length === 1
|
|
424
|
-
) {
|
|
425
|
-
clear_on_focus = true;
|
|
426
|
-
editing = [i, j];
|
|
427
|
-
}
|
|
258
|
+
$: {
|
|
259
|
+
if (data || _headers) {
|
|
260
|
+
df_actions.trigger_change(
|
|
261
|
+
data,
|
|
262
|
+
_headers,
|
|
263
|
+
previous_data,
|
|
264
|
+
previous_headers,
|
|
265
|
+
value_is_output,
|
|
266
|
+
dispatch
|
|
267
|
+
);
|
|
268
|
+
previous_data = data.map((row) => row.map((cell) => String(cell.value)));
|
|
269
|
+
previous_headers = _headers.map((h) => h.value);
|
|
428
270
|
}
|
|
429
271
|
}
|
|
430
272
|
|
|
431
|
-
type SortDirection = "asc" | "des";
|
|
432
|
-
let sort_direction: SortDirection | undefined;
|
|
433
|
-
let sort_by: number | undefined;
|
|
434
|
-
|
|
435
273
|
function handle_sort(col: number, direction: SortDirection): void {
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
274
|
+
df_actions.handle_sort(col, direction);
|
|
275
|
+
sort_data(data, display_value, styling);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
function clear_sort(): void {
|
|
279
|
+
df_actions.reset_sort_state();
|
|
280
|
+
sort_data(data, display_value, styling);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
$: {
|
|
284
|
+
df_actions.sort_data(data, display_value, styling);
|
|
285
|
+
df_actions.update_row_order(data);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
$: {
|
|
289
|
+
if ($df_state.sort_state.sort_columns) {
|
|
290
|
+
if ($df_state.sort_state.sort_columns.length > 0) {
|
|
291
|
+
sort_data(data, display_value, styling);
|
|
445
292
|
}
|
|
446
293
|
}
|
|
447
294
|
}
|
|
448
295
|
|
|
449
296
|
async function edit_header(i: number, _select = false): Promise<void> {
|
|
450
297
|
if (!editable || header_edit === i) return;
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
selected_header = i;
|
|
454
|
-
header_edit = i;
|
|
298
|
+
if (!editable || col_count[1] !== "dynamic" || header_edit === i) return;
|
|
299
|
+
df_actions.set_header_edit(i);
|
|
455
300
|
}
|
|
456
301
|
|
|
457
|
-
function
|
|
302
|
+
function handle_header_click(event: MouseEvent, col: number): void {
|
|
303
|
+
if (event.target instanceof HTMLAnchorElement) {
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
event.preventDefault();
|
|
307
|
+
event.stopPropagation();
|
|
458
308
|
if (!editable) return;
|
|
309
|
+
clear_on_focus = false;
|
|
310
|
+
df_actions.set_editing(false);
|
|
311
|
+
df_actions.handle_header_click(col, editable);
|
|
312
|
+
parent.focus();
|
|
313
|
+
}
|
|
459
314
|
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
event.preventDefault();
|
|
465
|
-
selected = false;
|
|
466
|
-
selected_header = header_edit;
|
|
467
|
-
header_edit = false;
|
|
468
|
-
parent.focus();
|
|
469
|
-
break;
|
|
470
|
-
}
|
|
315
|
+
function end_header_edit(event: CustomEvent<KeyboardEvent>): void {
|
|
316
|
+
if (!editable) return;
|
|
317
|
+
df_actions.end_header_edit(event.detail.key);
|
|
318
|
+
parent.focus();
|
|
471
319
|
}
|
|
472
320
|
|
|
473
321
|
async function add_row(index?: number): Promise<void> {
|
|
@@ -495,29 +343,27 @@
|
|
|
495
343
|
selected = [index !== undefined ? index : data.length - 1, 0];
|
|
496
344
|
}
|
|
497
345
|
|
|
498
|
-
$: (data || _headers) && trigger_change();
|
|
499
|
-
|
|
500
346
|
async function add_col(index?: number): Promise<void> {
|
|
501
347
|
parent.focus();
|
|
502
348
|
if (col_count[1] !== "dynamic") return;
|
|
503
349
|
|
|
504
|
-
const
|
|
505
|
-
|
|
506
|
-
for (let i = 0; i < data.length; i++) {
|
|
507
|
-
const _id = make_id();
|
|
508
|
-
els[_id] = { cell: null, input: null };
|
|
509
|
-
data[i].splice(insert_index, 0, { id: _id, value: "" });
|
|
510
|
-
}
|
|
350
|
+
const result = df_actions.add_col(data, headers, make_id, index);
|
|
511
351
|
|
|
512
|
-
|
|
352
|
+
result.data.forEach((row) => {
|
|
353
|
+
row.forEach((cell) => {
|
|
354
|
+
if (!els[cell.id]) {
|
|
355
|
+
els[cell.id] = { cell: null, input: null };
|
|
356
|
+
}
|
|
357
|
+
});
|
|
358
|
+
});
|
|
513
359
|
|
|
514
|
-
data = data;
|
|
515
|
-
headers = headers;
|
|
360
|
+
data = result.data;
|
|
361
|
+
headers = result.headers;
|
|
516
362
|
|
|
517
363
|
await tick();
|
|
518
364
|
|
|
519
365
|
requestAnimationFrame(() => {
|
|
520
|
-
edit_header(
|
|
366
|
+
edit_header(index !== undefined ? index : data[0].length - 1, true);
|
|
521
367
|
const new_w = parent.querySelectorAll("tbody")[1].offsetWidth;
|
|
522
368
|
parent.querySelectorAll("table")[1].scrollTo({ left: new_w });
|
|
523
369
|
});
|
|
@@ -525,42 +371,65 @@
|
|
|
525
371
|
|
|
526
372
|
function handle_click_outside(event: Event): void {
|
|
527
373
|
if (handle_click_outside_util(event, parent)) {
|
|
528
|
-
|
|
529
|
-
selected_cells = [];
|
|
374
|
+
df_actions.clear_ui_state();
|
|
530
375
|
header_edit = false;
|
|
531
376
|
selected_header = false;
|
|
532
|
-
active_cell_menu = null;
|
|
533
|
-
active_header_menu = null;
|
|
534
377
|
}
|
|
535
378
|
}
|
|
536
379
|
|
|
537
380
|
$: max = get_max(data);
|
|
538
381
|
|
|
539
|
-
|
|
382
|
+
// Modify how we trigger cell width calculations
|
|
383
|
+
// Only recalculate when cells actually change, not during sort
|
|
384
|
+
$: cells[0] && cells[0]?.clientWidth && set_cell_widths();
|
|
540
385
|
let cells: HTMLTableCellElement[] = [];
|
|
541
386
|
let parent: HTMLDivElement;
|
|
542
387
|
let table: HTMLTableElement;
|
|
388
|
+
let last_width_data_length = 0;
|
|
389
|
+
let last_width_column_count = 0;
|
|
543
390
|
|
|
544
391
|
function set_cell_widths(): void {
|
|
392
|
+
const column_count = data[0]?.length || 0;
|
|
393
|
+
if (
|
|
394
|
+
last_width_data_length === data.length &&
|
|
395
|
+
last_width_column_count === column_count &&
|
|
396
|
+
$df_state.sort_state.sort_columns.length > 0
|
|
397
|
+
) {
|
|
398
|
+
return;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
last_width_data_length = data.length;
|
|
402
|
+
last_width_column_count = column_count;
|
|
403
|
+
|
|
545
404
|
const widths = cells.map((el) => el?.clientWidth || 0);
|
|
546
405
|
if (widths.length === 0) return;
|
|
547
406
|
|
|
548
407
|
if (show_row_numbers) {
|
|
549
408
|
parent.style.setProperty(`--cell-width-row-number`, `${widths[0]}px`);
|
|
550
409
|
}
|
|
551
|
-
|
|
552
|
-
|
|
410
|
+
|
|
411
|
+
for (let i = 0; i < 50; i++) {
|
|
553
412
|
if (!column_widths[i]) {
|
|
554
|
-
parent.style.
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
);
|
|
413
|
+
parent.style.removeProperty(`--cell-width-${i}`);
|
|
414
|
+
} else if (column_widths[i].endsWith("%")) {
|
|
415
|
+
const percentage = parseFloat(column_widths[i]);
|
|
416
|
+
const pixel_width = Math.floor((percentage / 100) * parent.clientWidth);
|
|
417
|
+
parent.style.setProperty(`--cell-width-${i}`, `${pixel_width}px`);
|
|
418
|
+
} else {
|
|
419
|
+
parent.style.setProperty(`--cell-width-${i}`, column_widths[i]);
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
widths.forEach((width, i) => {
|
|
424
|
+
if (!column_widths[i]) {
|
|
425
|
+
const calculated_width = `${Math.max(width, 45)}px`;
|
|
426
|
+
parent.style.setProperty(`--cell-width-${i}`, calculated_width);
|
|
558
427
|
}
|
|
559
428
|
});
|
|
560
429
|
}
|
|
561
430
|
|
|
562
431
|
function get_cell_width(index: number): string {
|
|
563
|
-
return
|
|
432
|
+
return `var(--cell-width-${index})`;
|
|
564
433
|
}
|
|
565
434
|
|
|
566
435
|
let table_height: number =
|
|
@@ -570,28 +439,22 @@
|
|
|
570
439
|
function sort_data(
|
|
571
440
|
_data: typeof data,
|
|
572
441
|
_display_value: string[][] | null,
|
|
573
|
-
_styling: string[][] | null
|
|
574
|
-
col?: number,
|
|
575
|
-
dir?: SortDirection
|
|
442
|
+
_styling: string[][] | null
|
|
576
443
|
): void {
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
sort_table_data(_data, _display_value, _styling, col, dir);
|
|
586
|
-
data = data;
|
|
444
|
+
const result = sort_data_and_preserve_selection(
|
|
445
|
+
_data,
|
|
446
|
+
_display_value,
|
|
447
|
+
_styling,
|
|
448
|
+
$df_state.sort_state.sort_columns,
|
|
449
|
+
selected,
|
|
450
|
+
get_current_indices
|
|
451
|
+
);
|
|
587
452
|
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
selected = [i, j];
|
|
591
|
-
}
|
|
453
|
+
data = result.data;
|
|
454
|
+
selected = result.selected;
|
|
592
455
|
}
|
|
593
456
|
|
|
594
|
-
$: sort_data(data, display_value, styling
|
|
457
|
+
$: sort_data(data, display_value, styling);
|
|
595
458
|
|
|
596
459
|
$: selected_index = !!selected && selected[0];
|
|
597
460
|
|
|
@@ -624,114 +487,65 @@
|
|
|
624
487
|
};
|
|
625
488
|
});
|
|
626
489
|
|
|
490
|
+
$: keyboard_ctx = create_keyboard_context({
|
|
491
|
+
selected_header,
|
|
492
|
+
header_edit,
|
|
493
|
+
editing,
|
|
494
|
+
selected,
|
|
495
|
+
selected_cells,
|
|
496
|
+
editable,
|
|
497
|
+
data,
|
|
498
|
+
headers: _headers,
|
|
499
|
+
els,
|
|
500
|
+
df_actions,
|
|
501
|
+
dispatch,
|
|
502
|
+
add_row,
|
|
503
|
+
get_next_cell_coordinates,
|
|
504
|
+
get_range_selection,
|
|
505
|
+
move_cursor,
|
|
506
|
+
copy_flash,
|
|
507
|
+
parent_element: parent,
|
|
508
|
+
set_copy_flash: (value: boolean) => {
|
|
509
|
+
copy_flash = value;
|
|
510
|
+
if (value) {
|
|
511
|
+
setTimeout(() => {
|
|
512
|
+
copy_flash = false;
|
|
513
|
+
}, 800);
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
});
|
|
517
|
+
|
|
518
|
+
$: selection_ctx = create_selection_context({
|
|
519
|
+
df_actions,
|
|
520
|
+
dispatch,
|
|
521
|
+
data,
|
|
522
|
+
els,
|
|
523
|
+
editable,
|
|
524
|
+
show_row_numbers,
|
|
525
|
+
get_data_at,
|
|
526
|
+
clear_on_focus,
|
|
527
|
+
selected_cells,
|
|
528
|
+
parent_element: parent
|
|
529
|
+
});
|
|
530
|
+
|
|
627
531
|
function handle_cell_click(
|
|
628
532
|
event: MouseEvent,
|
|
629
533
|
row: number,
|
|
630
534
|
col: number
|
|
631
535
|
): void {
|
|
632
|
-
|
|
633
|
-
return;
|
|
634
|
-
}
|
|
635
|
-
|
|
636
|
-
event.preventDefault();
|
|
637
|
-
event.stopPropagation();
|
|
638
|
-
|
|
639
|
-
if (show_row_numbers && col === -1) return;
|
|
640
|
-
|
|
641
|
-
clear_on_focus = false;
|
|
642
|
-
active_cell_menu = null;
|
|
643
|
-
active_header_menu = null;
|
|
644
|
-
selected_header = false;
|
|
645
|
-
header_edit = false;
|
|
646
|
-
|
|
647
|
-
selected_cells = handle_selection([row, col], selected_cells, event);
|
|
648
|
-
parent.focus();
|
|
649
|
-
|
|
650
|
-
if (editable) {
|
|
651
|
-
if (selected_cells.length === 1) {
|
|
652
|
-
editing = [row, col];
|
|
653
|
-
tick().then(() => {
|
|
654
|
-
const input_el = els[data[row][col].id].input;
|
|
655
|
-
if (input_el) {
|
|
656
|
-
input_el.focus();
|
|
657
|
-
input_el.selectionStart = input_el.selectionEnd =
|
|
658
|
-
input_el.value.length;
|
|
659
|
-
}
|
|
660
|
-
});
|
|
661
|
-
} else {
|
|
662
|
-
editing = false;
|
|
663
|
-
}
|
|
664
|
-
}
|
|
665
|
-
|
|
666
|
-
toggle_cell_button(row, col);
|
|
667
|
-
|
|
668
|
-
dispatch("select", {
|
|
669
|
-
index: [row, col],
|
|
670
|
-
value: get_data_at(row, col),
|
|
671
|
-
row_value: data[row].map((d) => d.value)
|
|
672
|
-
});
|
|
536
|
+
selection_ctx.actions.handle_cell_click(event, row, col);
|
|
673
537
|
}
|
|
674
538
|
|
|
675
539
|
function toggle_cell_menu(event: MouseEvent, row: number, col: number): void {
|
|
676
|
-
|
|
677
|
-
if (
|
|
678
|
-
active_cell_menu &&
|
|
679
|
-
active_cell_menu.row === row &&
|
|
680
|
-
active_cell_menu.col === col
|
|
681
|
-
) {
|
|
682
|
-
active_cell_menu = null;
|
|
683
|
-
} else {
|
|
684
|
-
const cell = (event.target as HTMLElement).closest("td");
|
|
685
|
-
if (cell) {
|
|
686
|
-
const rect = cell.getBoundingClientRect();
|
|
687
|
-
active_cell_menu = { row, col, x: rect.right, y: rect.bottom };
|
|
688
|
-
}
|
|
689
|
-
}
|
|
690
|
-
}
|
|
691
|
-
|
|
692
|
-
function add_row_at(index: number, position: "above" | "below"): void {
|
|
693
|
-
const row_index = position === "above" ? index : index + 1;
|
|
694
|
-
add_row(row_index);
|
|
695
|
-
active_cell_menu = null;
|
|
696
|
-
active_header_menu = null;
|
|
697
|
-
}
|
|
698
|
-
|
|
699
|
-
function add_col_at(index: number, position: "left" | "right"): void {
|
|
700
|
-
const col_index = position === "left" ? index : index + 1;
|
|
701
|
-
add_col(col_index);
|
|
702
|
-
active_cell_menu = null;
|
|
703
|
-
active_header_menu = null;
|
|
540
|
+
selection_ctx.actions.toggle_cell_menu(event, row, col);
|
|
704
541
|
}
|
|
705
542
|
|
|
706
|
-
function
|
|
707
|
-
|
|
708
|
-
active_header_menu = null;
|
|
709
|
-
selected_cells = [];
|
|
710
|
-
selected = false;
|
|
711
|
-
editing = false;
|
|
712
|
-
set_cell_widths();
|
|
713
|
-
}
|
|
714
|
-
|
|
715
|
-
let active_button: {
|
|
716
|
-
type: "header" | "cell";
|
|
717
|
-
row?: number;
|
|
718
|
-
col: number;
|
|
719
|
-
} | null = null;
|
|
720
|
-
|
|
721
|
-
function toggle_header_button(col: number): void {
|
|
722
|
-
active_button =
|
|
723
|
-
active_button?.type === "header" && active_button.col === col
|
|
724
|
-
? null
|
|
725
|
-
: { type: "header", col };
|
|
543
|
+
function handle_select_column(col: number): void {
|
|
544
|
+
selection_ctx.actions.handle_select_column(col);
|
|
726
545
|
}
|
|
727
546
|
|
|
728
|
-
function
|
|
729
|
-
|
|
730
|
-
active_button?.type === "cell" &&
|
|
731
|
-
active_button.row === row &&
|
|
732
|
-
active_button.col === col
|
|
733
|
-
? null
|
|
734
|
-
: { type: "cell", row, col };
|
|
547
|
+
function handle_select_row(row: number): void {
|
|
548
|
+
selection_ctx.actions.handle_select_row(row);
|
|
735
549
|
}
|
|
736
550
|
|
|
737
551
|
function toggle_fullscreen(): void {
|
|
@@ -748,23 +562,19 @@
|
|
|
748
562
|
is_fullscreen = !!document.fullscreenElement;
|
|
749
563
|
}
|
|
750
564
|
|
|
751
|
-
async function handle_copy(): Promise<void> {
|
|
752
|
-
await copy_table_data(data, selected_cells);
|
|
753
|
-
copy_flash = true;
|
|
754
|
-
setTimeout(() => {
|
|
755
|
-
copy_flash = false;
|
|
756
|
-
}, 800);
|
|
757
|
-
}
|
|
758
|
-
|
|
759
565
|
function toggle_header_menu(event: MouseEvent, col: number): void {
|
|
760
566
|
event.stopPropagation();
|
|
761
567
|
if (active_header_menu && active_header_menu.col === col) {
|
|
762
|
-
|
|
568
|
+
df_actions.set_active_header_menu(null);
|
|
763
569
|
} else {
|
|
764
570
|
const header = (event.target as HTMLElement).closest("th");
|
|
765
571
|
if (header) {
|
|
766
572
|
const rect = header.getBoundingClientRect();
|
|
767
|
-
|
|
573
|
+
df_actions.set_active_header_menu({
|
|
574
|
+
col,
|
|
575
|
+
x: rect.right,
|
|
576
|
+
y: rect.bottom
|
|
577
|
+
});
|
|
768
578
|
}
|
|
769
579
|
}
|
|
770
580
|
}
|
|
@@ -773,86 +583,25 @@
|
|
|
773
583
|
value_is_output = false;
|
|
774
584
|
});
|
|
775
585
|
|
|
776
|
-
|
|
777
|
-
parent.focus();
|
|
778
|
-
if (row_count[1] !== "dynamic") return;
|
|
779
|
-
if (data.length <= 1) return;
|
|
780
|
-
data.splice(index, 1);
|
|
781
|
-
data = data;
|
|
782
|
-
selected = false;
|
|
783
|
-
}
|
|
784
|
-
|
|
785
|
-
async function delete_col(index: number): Promise<void> {
|
|
786
|
-
parent.focus();
|
|
586
|
+
function delete_col_at(index: number): void {
|
|
787
587
|
if (col_count[1] !== "dynamic") return;
|
|
788
|
-
if (
|
|
588
|
+
if (data[0].length <= 1) return;
|
|
789
589
|
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
selected = false;
|
|
590
|
+
const result = df_actions.delete_col_at(data, headers, index);
|
|
591
|
+
data = result.data;
|
|
592
|
+
headers = result.headers;
|
|
593
|
+
_headers = make_headers(headers, col_count, els, make_id);
|
|
594
|
+
df_actions.set_active_cell_menu(null);
|
|
595
|
+
df_actions.set_active_header_menu(null);
|
|
596
|
+
df_actions.set_selected(false);
|
|
597
|
+
df_actions.set_selected_cells([]);
|
|
598
|
+
df_actions.set_editing(false);
|
|
800
599
|
}
|
|
801
600
|
|
|
802
601
|
function delete_row_at(index: number): void {
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
}
|
|
807
|
-
|
|
808
|
-
function delete_col_at(index: number): void {
|
|
809
|
-
delete_col(index);
|
|
810
|
-
active_cell_menu = null;
|
|
811
|
-
active_header_menu = null;
|
|
812
|
-
}
|
|
813
|
-
|
|
814
|
-
let row_order: number[] = [];
|
|
815
|
-
|
|
816
|
-
$: {
|
|
817
|
-
if (
|
|
818
|
-
typeof sort_by === "number" &&
|
|
819
|
-
sort_direction &&
|
|
820
|
-
sort_by >= 0 &&
|
|
821
|
-
sort_by < data[0].length
|
|
822
|
-
) {
|
|
823
|
-
const indices = [...Array(data.length)].map((_, i) => i);
|
|
824
|
-
const sort_index = sort_by as number;
|
|
825
|
-
indices.sort((a, b) => {
|
|
826
|
-
const row_a = data[a];
|
|
827
|
-
const row_b = data[b];
|
|
828
|
-
if (
|
|
829
|
-
!row_a ||
|
|
830
|
-
!row_b ||
|
|
831
|
-
sort_index >= row_a.length ||
|
|
832
|
-
sort_index >= row_b.length
|
|
833
|
-
)
|
|
834
|
-
return 0;
|
|
835
|
-
const val_a = row_a[sort_index].value;
|
|
836
|
-
const val_b = row_b[sort_index].value;
|
|
837
|
-
const comp = val_a < val_b ? -1 : val_a > val_b ? 1 : 0;
|
|
838
|
-
return sort_direction === "asc" ? comp : -comp;
|
|
839
|
-
});
|
|
840
|
-
row_order = indices;
|
|
841
|
-
} else {
|
|
842
|
-
row_order = [...Array(data.length)].map((_, i) => i);
|
|
843
|
-
}
|
|
844
|
-
}
|
|
845
|
-
|
|
846
|
-
function handle_select_column(col: number): void {
|
|
847
|
-
selected_cells = select_column(data, col);
|
|
848
|
-
selected = selected_cells[0];
|
|
849
|
-
editing = false;
|
|
850
|
-
}
|
|
851
|
-
|
|
852
|
-
function handle_select_row(row: number): void {
|
|
853
|
-
selected_cells = select_row(data, row);
|
|
854
|
-
selected = selected_cells[0];
|
|
855
|
-
editing = false;
|
|
602
|
+
data = df_actions.delete_row_at(data, index);
|
|
603
|
+
df_actions.set_active_cell_menu(null);
|
|
604
|
+
df_actions.set_active_header_menu(null);
|
|
856
605
|
}
|
|
857
606
|
|
|
858
607
|
let coords: CellCoordinate;
|
|
@@ -870,55 +619,125 @@
|
|
|
870
619
|
"--selected-col-pos",
|
|
871
620
|
positions.col_pos
|
|
872
621
|
);
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
);
|
|
878
|
-
}
|
|
622
|
+
document.documentElement.style.setProperty(
|
|
623
|
+
"--selected-row-pos",
|
|
624
|
+
positions.row_pos || "0px"
|
|
625
|
+
);
|
|
879
626
|
}
|
|
880
627
|
|
|
881
|
-
|
|
628
|
+
function commit_filter(): void {
|
|
629
|
+
if ($df_state.current_search_query && show_search === "filter") {
|
|
630
|
+
const filtered_data: (string | number)[][] = [];
|
|
631
|
+
const filtered_display_values: string[][] = [];
|
|
632
|
+
const filtered_styling: string[][] = [];
|
|
633
|
+
|
|
634
|
+
search_results.forEach((row) => {
|
|
635
|
+
const data_row: (string | number)[] = [];
|
|
636
|
+
const display_row: string[] = [];
|
|
637
|
+
const styling_row: string[] = [];
|
|
638
|
+
|
|
639
|
+
row.forEach((cell) => {
|
|
640
|
+
data_row.push(cell.value);
|
|
641
|
+
display_row.push(cell.display_value || String(cell.value));
|
|
642
|
+
styling_row.push(cell.styling || "");
|
|
643
|
+
});
|
|
882
644
|
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
645
|
+
filtered_data.push(data_row);
|
|
646
|
+
filtered_display_values.push(display_row);
|
|
647
|
+
filtered_styling.push(styling_row);
|
|
648
|
+
});
|
|
887
649
|
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
dispatch("change", {
|
|
891
|
-
data: data.map((row) => row.map((cell) => cell.value)),
|
|
650
|
+
const change_payload = {
|
|
651
|
+
data: filtered_data,
|
|
892
652
|
headers: _headers.map((h) => h.value),
|
|
893
|
-
metadata:
|
|
894
|
-
|
|
653
|
+
metadata: {
|
|
654
|
+
display_value: filtered_display_values,
|
|
655
|
+
styling: filtered_styling
|
|
656
|
+
}
|
|
657
|
+
};
|
|
658
|
+
|
|
659
|
+
dispatch("change", change_payload);
|
|
660
|
+
|
|
895
661
|
if (!value_is_output) {
|
|
896
662
|
dispatch("input");
|
|
897
663
|
}
|
|
898
|
-
|
|
664
|
+
|
|
665
|
+
df_actions.handle_search(null);
|
|
899
666
|
}
|
|
900
667
|
}
|
|
901
668
|
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
return;
|
|
905
|
-
}
|
|
669
|
+
let viewport: HTMLTableElement;
|
|
670
|
+
let show_scroll_button = false;
|
|
906
671
|
|
|
907
|
-
|
|
908
|
-
|
|
672
|
+
function scroll_to_top(): void {
|
|
673
|
+
viewport.scrollTo({
|
|
674
|
+
top: 0
|
|
675
|
+
});
|
|
676
|
+
}
|
|
909
677
|
|
|
910
|
-
|
|
678
|
+
function handle_resize(): void {
|
|
679
|
+
df_actions.set_active_cell_menu(null);
|
|
680
|
+
df_actions.set_active_header_menu(null);
|
|
681
|
+
selected_cells = [];
|
|
682
|
+
selected = false;
|
|
683
|
+
editing = false;
|
|
684
|
+
set_cell_widths();
|
|
685
|
+
}
|
|
911
686
|
|
|
912
|
-
|
|
687
|
+
function add_row_at(index: number, position: "above" | "below"): void {
|
|
688
|
+
const row_index = position === "above" ? index : index + 1;
|
|
689
|
+
add_row(row_index);
|
|
913
690
|
active_cell_menu = null;
|
|
914
691
|
active_header_menu = null;
|
|
915
|
-
|
|
916
|
-
selected_cells = [];
|
|
917
|
-
selected_header = col;
|
|
918
|
-
header_edit = col;
|
|
692
|
+
}
|
|
919
693
|
|
|
920
|
-
|
|
694
|
+
function add_col_at(index: number, position: "left" | "right"): void {
|
|
695
|
+
const col_index = position === "left" ? index : index + 1;
|
|
696
|
+
add_col(col_index);
|
|
697
|
+
active_cell_menu = null;
|
|
698
|
+
active_header_menu = null;
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
export function reset_sort_state(): void {
|
|
702
|
+
df_actions.reset_sort_state();
|
|
921
703
|
}
|
|
704
|
+
|
|
705
|
+
let is_dragging = false;
|
|
706
|
+
let drag_start: [number, number] | null = null;
|
|
707
|
+
let mouse_down_pos: { x: number; y: number } | null = null;
|
|
708
|
+
|
|
709
|
+
const drag_state: DragState = {
|
|
710
|
+
is_dragging,
|
|
711
|
+
drag_start,
|
|
712
|
+
mouse_down_pos
|
|
713
|
+
};
|
|
714
|
+
|
|
715
|
+
$: {
|
|
716
|
+
is_dragging = drag_state.is_dragging;
|
|
717
|
+
drag_start = drag_state.drag_start;
|
|
718
|
+
mouse_down_pos = drag_state.mouse_down_pos;
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
let drag_handlers: DragHandlers;
|
|
722
|
+
|
|
723
|
+
function init_drag_handlers(): void {
|
|
724
|
+
drag_handlers = create_drag_handlers(
|
|
725
|
+
drag_state,
|
|
726
|
+
(value) => (is_dragging = value),
|
|
727
|
+
(cells) => df_actions.set_selected_cells(cells),
|
|
728
|
+
(cell) => df_actions.set_selected(cell),
|
|
729
|
+
(event, row, col) =>
|
|
730
|
+
selection_ctx.actions.handle_cell_click(event, row, col),
|
|
731
|
+
show_row_numbers,
|
|
732
|
+
parent
|
|
733
|
+
);
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
$: if (parent) init_drag_handlers();
|
|
737
|
+
|
|
738
|
+
$: handle_mouse_down = drag_handlers?.handle_mouse_down || (() => {});
|
|
739
|
+
$: handle_mouse_move = drag_handlers?.handle_mouse_move || (() => {});
|
|
740
|
+
$: handle_mouse_up = drag_handlers?.handle_mouse_up || (() => {});
|
|
922
741
|
</script>
|
|
923
742
|
|
|
924
743
|
<svelte:window on:resize={() => set_cell_widths()} />
|
|
@@ -935,140 +754,70 @@
|
|
|
935
754
|
{show_fullscreen_button}
|
|
936
755
|
{is_fullscreen}
|
|
937
756
|
on:click={toggle_fullscreen}
|
|
938
|
-
on_copy={
|
|
757
|
+
on_copy={async () => await copy_table_data(data, null)}
|
|
939
758
|
{show_copy_button}
|
|
940
759
|
{show_search}
|
|
941
|
-
on:search={(e) => handle_search(e.detail)}
|
|
760
|
+
on:search={(e) => df_actions.handle_search(e.detail)}
|
|
942
761
|
on_commit_filter={commit_filter}
|
|
943
|
-
{current_search_query}
|
|
762
|
+
current_search_query={$df_state.current_search_query}
|
|
944
763
|
/>
|
|
945
764
|
</div>
|
|
946
765
|
{/if}
|
|
947
766
|
<div
|
|
948
767
|
bind:this={parent}
|
|
949
768
|
class="table-wrap"
|
|
950
|
-
class:dragging
|
|
769
|
+
class:dragging={is_dragging}
|
|
951
770
|
class:no-wrap={!wrap}
|
|
952
771
|
style="height:{table_height}px;"
|
|
953
772
|
class:menu-open={active_cell_menu || active_header_menu}
|
|
954
|
-
on:keydown={(e) => handle_keydown(e)}
|
|
773
|
+
on:keydown={(e) => handle_keydown(e, keyboard_ctx)}
|
|
774
|
+
on:mousemove={handle_mouse_move}
|
|
775
|
+
on:mouseup={handle_mouse_up}
|
|
776
|
+
on:mouseleave={handle_mouse_up}
|
|
955
777
|
role="grid"
|
|
956
778
|
tabindex="0"
|
|
957
779
|
>
|
|
958
|
-
{
|
|
959
|
-
<button
|
|
960
|
-
class="selection-button selection-button-column"
|
|
961
|
-
on:click|stopPropagation={() => handle_select_column(coords[1])}
|
|
962
|
-
aria-label="Select column"
|
|
963
|
-
>
|
|
964
|
-
⋮
|
|
965
|
-
</button>
|
|
966
|
-
<button
|
|
967
|
-
class="selection-button selection-button-row"
|
|
968
|
-
on:click|stopPropagation={() => handle_select_row(coords[0])}
|
|
969
|
-
aria-label="Select row"
|
|
970
|
-
>
|
|
971
|
-
⋮
|
|
972
|
-
</button>
|
|
973
|
-
{/if}
|
|
974
|
-
<table
|
|
975
|
-
bind:contentRect={t_rect}
|
|
976
|
-
bind:this={table}
|
|
977
|
-
class:fixed-layout={column_widths.length != 0}
|
|
978
|
-
>
|
|
780
|
+
<table bind:this={table}>
|
|
979
781
|
{#if label && label.length !== 0}
|
|
980
782
|
<caption class="sr-only">{label}</caption>
|
|
981
783
|
{/if}
|
|
982
784
|
<thead>
|
|
983
785
|
<tr>
|
|
984
786
|
{#if show_row_numbers}
|
|
985
|
-
<
|
|
986
|
-
class="row-number-header frozen-column always-frozen"
|
|
987
|
-
style="left: 0;"
|
|
988
|
-
>
|
|
989
|
-
<div class="cell-wrap">
|
|
990
|
-
<div class="header-content">
|
|
991
|
-
<div class="header-text"></div>
|
|
992
|
-
</div>
|
|
993
|
-
</div>
|
|
994
|
-
</th>
|
|
787
|
+
<RowNumber is_header={true} />
|
|
995
788
|
{/if}
|
|
996
789
|
{#each _headers as { value, id }, i (id)}
|
|
997
|
-
<
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
>
|
|
1021
|
-
<div class="cell-wrap">
|
|
1022
|
-
<div class="header-content">
|
|
1023
|
-
<EditableCell
|
|
1024
|
-
{max_chars}
|
|
1025
|
-
bind:value={_headers[i].value}
|
|
1026
|
-
bind:el={els[id].input}
|
|
1027
|
-
{latex_delimiters}
|
|
1028
|
-
{line_breaks}
|
|
1029
|
-
edit={header_edit === i}
|
|
1030
|
-
on:keydown={end_header_edit}
|
|
1031
|
-
header
|
|
1032
|
-
{root}
|
|
1033
|
-
{editable}
|
|
1034
|
-
/>
|
|
1035
|
-
{#if header_edit !== i}
|
|
1036
|
-
<div class="sort-buttons">
|
|
1037
|
-
<SortIcon
|
|
1038
|
-
direction={sort_by === i ? sort_direction : null}
|
|
1039
|
-
on:sort={({ detail }) => handle_sort(i, detail)}
|
|
1040
|
-
{i18n}
|
|
1041
|
-
/>
|
|
1042
|
-
</div>
|
|
1043
|
-
{/if}
|
|
1044
|
-
</div>
|
|
1045
|
-
{#if editable}
|
|
1046
|
-
<button
|
|
1047
|
-
class="cell-menu-button"
|
|
1048
|
-
on:click={(event) => toggle_header_menu(event, i)}
|
|
1049
|
-
on:touchstart={(event) => {
|
|
1050
|
-
event.preventDefault();
|
|
1051
|
-
const touch = event.touches[0];
|
|
1052
|
-
const mouseEvent = new MouseEvent("click", {
|
|
1053
|
-
clientX: touch.clientX,
|
|
1054
|
-
clientY: touch.clientY,
|
|
1055
|
-
bubbles: true,
|
|
1056
|
-
cancelable: true,
|
|
1057
|
-
view: window
|
|
1058
|
-
});
|
|
1059
|
-
toggle_header_menu(mouseEvent, i);
|
|
1060
|
-
}}
|
|
1061
|
-
>
|
|
1062
|
-
⋮
|
|
1063
|
-
</button>
|
|
1064
|
-
{/if}
|
|
1065
|
-
</div>
|
|
1066
|
-
</th>
|
|
790
|
+
<TableHeader
|
|
791
|
+
bind:value={_headers[i].value}
|
|
792
|
+
{i}
|
|
793
|
+
{actual_pinned_columns}
|
|
794
|
+
{header_edit}
|
|
795
|
+
{selected_header}
|
|
796
|
+
get_sort_status={df_actions.get_sort_status}
|
|
797
|
+
{headers}
|
|
798
|
+
{get_cell_width}
|
|
799
|
+
{handle_header_click}
|
|
800
|
+
{toggle_header_menu}
|
|
801
|
+
{end_header_edit}
|
|
802
|
+
sort_columns={$df_state.sort_state.sort_columns}
|
|
803
|
+
{latex_delimiters}
|
|
804
|
+
{line_breaks}
|
|
805
|
+
{max_chars}
|
|
806
|
+
{root}
|
|
807
|
+
{editable}
|
|
808
|
+
is_static={static_columns.includes(i)}
|
|
809
|
+
{i18n}
|
|
810
|
+
bind:el={els[id].input}
|
|
811
|
+
{col_count}
|
|
812
|
+
/>
|
|
1067
813
|
{/each}
|
|
1068
814
|
</tr>
|
|
1069
815
|
</thead>
|
|
1070
816
|
<tbody>
|
|
1071
817
|
<tr>
|
|
818
|
+
{#if show_row_numbers}
|
|
819
|
+
<RowNumber index={0} />
|
|
820
|
+
{/if}
|
|
1072
821
|
{#each max as { value, id }, j (id)}
|
|
1073
822
|
<td tabindex="-1" bind:this={cells[j]}>
|
|
1074
823
|
<div class="cell-wrap">
|
|
@@ -1081,6 +830,14 @@
|
|
|
1081
830
|
el={null}
|
|
1082
831
|
{root}
|
|
1083
832
|
{editable}
|
|
833
|
+
{i18n}
|
|
834
|
+
show_selection_buttons={selected_cells.length === 1 &&
|
|
835
|
+
selected_cells[0][0] === 0 &&
|
|
836
|
+
selected_cells[0][1] === j}
|
|
837
|
+
coords={[0, j]}
|
|
838
|
+
on_select_column={handle_select_column}
|
|
839
|
+
on_select_row={handle_select_row}
|
|
840
|
+
{is_dragging}
|
|
1084
841
|
/>
|
|
1085
842
|
</div>
|
|
1086
843
|
</td>
|
|
@@ -1103,7 +860,8 @@
|
|
|
1103
860
|
_headers = make_headers(
|
|
1104
861
|
head.map((h) => h ?? ""),
|
|
1105
862
|
col_count,
|
|
1106
|
-
els
|
|
863
|
+
els,
|
|
864
|
+
make_id
|
|
1107
865
|
);
|
|
1108
866
|
return _headers;
|
|
1109
867
|
},
|
|
@@ -1116,258 +874,160 @@
|
|
|
1116
874
|
>
|
|
1117
875
|
<div class="table-wrap">
|
|
1118
876
|
<VirtualTable
|
|
1119
|
-
bind:items={
|
|
877
|
+
bind:items={search_results}
|
|
1120
878
|
{max_height}
|
|
1121
879
|
bind:actual_height={table_height}
|
|
1122
880
|
bind:table_scrollbar_width={scrollbar_width}
|
|
1123
881
|
selected={selected_index}
|
|
1124
882
|
disable_scroll={active_cell_menu !== null ||
|
|
1125
883
|
active_header_menu !== null}
|
|
884
|
+
bind:viewport
|
|
885
|
+
bind:show_scroll_button
|
|
886
|
+
on:scroll_top={(_) => {}}
|
|
1126
887
|
>
|
|
1127
888
|
{#if label && label.length !== 0}
|
|
1128
889
|
<caption class="sr-only">{label}</caption>
|
|
1129
890
|
{/if}
|
|
1130
891
|
<tr slot="thead">
|
|
1131
892
|
{#if show_row_numbers}
|
|
1132
|
-
<
|
|
1133
|
-
class="row-number-header frozen-column always-frozen"
|
|
1134
|
-
style="left: 0;"
|
|
1135
|
-
>
|
|
1136
|
-
<div class="cell-wrap">
|
|
1137
|
-
<div class="header-content">
|
|
1138
|
-
<div class="header-text"></div>
|
|
1139
|
-
</div>
|
|
1140
|
-
</div>
|
|
1141
|
-
</th>
|
|
893
|
+
<RowNumber is_header={true} />
|
|
1142
894
|
{/if}
|
|
1143
895
|
{#each _headers as { value, id }, i (id)}
|
|
1144
|
-
<
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
>
|
|
1168
|
-
<div class="cell-wrap">
|
|
1169
|
-
<div class="header-content">
|
|
1170
|
-
<EditableCell
|
|
1171
|
-
{max_chars}
|
|
1172
|
-
bind:value={_headers[i].value}
|
|
1173
|
-
bind:el={els[id].input}
|
|
1174
|
-
{latex_delimiters}
|
|
1175
|
-
{line_breaks}
|
|
1176
|
-
edit={header_edit === i}
|
|
1177
|
-
header
|
|
1178
|
-
{root}
|
|
1179
|
-
{editable}
|
|
1180
|
-
/>
|
|
1181
|
-
{#if header_edit !== i}
|
|
1182
|
-
<div class="sort-buttons">
|
|
1183
|
-
<SortIcon
|
|
1184
|
-
direction={sort_by === i ? sort_direction : null}
|
|
1185
|
-
on:sort={({ detail }) => handle_sort(i, detail)}
|
|
1186
|
-
{i18n}
|
|
1187
|
-
/>
|
|
1188
|
-
</div>
|
|
1189
|
-
{/if}
|
|
1190
|
-
</div>
|
|
1191
|
-
{#if editable}
|
|
1192
|
-
<button
|
|
1193
|
-
class="cell-menu-button"
|
|
1194
|
-
on:click={(event) => toggle_header_menu(event, i)}
|
|
1195
|
-
on:touchstart={(event) => {
|
|
1196
|
-
event.preventDefault();
|
|
1197
|
-
const touch = event.touches[0];
|
|
1198
|
-
const mouseEvent = new MouseEvent("click", {
|
|
1199
|
-
clientX: touch.clientX,
|
|
1200
|
-
clientY: touch.clientY,
|
|
1201
|
-
bubbles: true,
|
|
1202
|
-
cancelable: true,
|
|
1203
|
-
view: window
|
|
1204
|
-
});
|
|
1205
|
-
toggle_header_menu(mouseEvent, i);
|
|
1206
|
-
}}
|
|
1207
|
-
>
|
|
1208
|
-
⋮
|
|
1209
|
-
</button>
|
|
1210
|
-
{/if}
|
|
1211
|
-
</div>
|
|
1212
|
-
</th>
|
|
896
|
+
<TableHeader
|
|
897
|
+
bind:value={_headers[i].value}
|
|
898
|
+
{i}
|
|
899
|
+
{actual_pinned_columns}
|
|
900
|
+
{header_edit}
|
|
901
|
+
{selected_header}
|
|
902
|
+
get_sort_status={df_actions.get_sort_status}
|
|
903
|
+
{headers}
|
|
904
|
+
{get_cell_width}
|
|
905
|
+
{handle_header_click}
|
|
906
|
+
{toggle_header_menu}
|
|
907
|
+
{end_header_edit}
|
|
908
|
+
sort_columns={$df_state.sort_state.sort_columns}
|
|
909
|
+
{latex_delimiters}
|
|
910
|
+
{line_breaks}
|
|
911
|
+
{max_chars}
|
|
912
|
+
{root}
|
|
913
|
+
{editable}
|
|
914
|
+
is_static={static_columns.includes(i)}
|
|
915
|
+
{i18n}
|
|
916
|
+
bind:el={els[id].input}
|
|
917
|
+
{col_count}
|
|
918
|
+
/>
|
|
1213
919
|
{/each}
|
|
1214
920
|
</tr>
|
|
1215
|
-
<tr slot="tbody" let:item let:index class:
|
|
921
|
+
<tr slot="tbody" let:item let:index class:row-odd={index % 2 === 0}>
|
|
1216
922
|
{#if show_row_numbers}
|
|
1217
|
-
<
|
|
1218
|
-
class="row-number frozen-column always-frozen"
|
|
1219
|
-
style="left: 0;"
|
|
1220
|
-
tabindex="-1"
|
|
1221
|
-
>
|
|
1222
|
-
{index + 1}
|
|
1223
|
-
</td>
|
|
923
|
+
<RowNumber {index} />
|
|
1224
924
|
{/if}
|
|
1225
925
|
{#each item as { value, id }, j (id)}
|
|
1226
|
-
<
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
}
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
}
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
.fill(0)
|
|
1257
|
-
.map((_, idx) => `var(--cell-width-${idx})`)
|
|
1258
|
-
.join(' + ')})`
|
|
1259
|
-
: 'auto'}; {styling?.[index]?.[j] || ''}"
|
|
1260
|
-
class:flash={copy_flash &&
|
|
1261
|
-
is_cell_selected([index, j], selected_cells)}
|
|
1262
|
-
class={is_cell_selected([index, j], selected_cells)}
|
|
1263
|
-
class:menu-active={active_cell_menu &&
|
|
1264
|
-
active_cell_menu.row === index &&
|
|
1265
|
-
active_cell_menu.col === j}
|
|
1266
|
-
>
|
|
1267
|
-
<div class="cell-wrap">
|
|
1268
|
-
<EditableCell
|
|
1269
|
-
bind:value={data[index][j].value}
|
|
1270
|
-
bind:el={els[id].input}
|
|
1271
|
-
display_value={display_value?.[index]?.[j]}
|
|
1272
|
-
{latex_delimiters}
|
|
1273
|
-
{line_breaks}
|
|
1274
|
-
{editable}
|
|
1275
|
-
edit={dequal(editing, [index, j])}
|
|
1276
|
-
datatype={Array.isArray(datatype) ? datatype[j] : datatype}
|
|
1277
|
-
on:blur={() => {
|
|
1278
|
-
clear_on_focus = false;
|
|
1279
|
-
parent.focus();
|
|
1280
|
-
}}
|
|
1281
|
-
on:focus={() => {
|
|
1282
|
-
const row = index;
|
|
1283
|
-
const col = j;
|
|
1284
|
-
if (
|
|
1285
|
-
!selected_cells.some(([r, c]) => r === row && c === col)
|
|
1286
|
-
) {
|
|
1287
|
-
selected_cells = [[row, col]];
|
|
1288
|
-
}
|
|
1289
|
-
}}
|
|
1290
|
-
{clear_on_focus}
|
|
1291
|
-
{root}
|
|
1292
|
-
{max_chars}
|
|
1293
|
-
/>
|
|
1294
|
-
{#if editable && should_show_cell_menu([index, j], selected_cells, editable)}
|
|
1295
|
-
<button
|
|
1296
|
-
class="cell-menu-button"
|
|
1297
|
-
on:click={(event) => toggle_cell_menu(event, index, j)}
|
|
1298
|
-
>
|
|
1299
|
-
⋮
|
|
1300
|
-
</button>
|
|
1301
|
-
{/if}
|
|
1302
|
-
</div>
|
|
1303
|
-
</td>
|
|
926
|
+
<TableCell
|
|
927
|
+
bind:value={search_results[index][j].value}
|
|
928
|
+
{index}
|
|
929
|
+
{j}
|
|
930
|
+
{actual_pinned_columns}
|
|
931
|
+
{get_cell_width}
|
|
932
|
+
handle_cell_click={(e, r, c) => handle_mouse_down(e, r, c)}
|
|
933
|
+
{toggle_cell_menu}
|
|
934
|
+
{is_cell_selected}
|
|
935
|
+
{should_show_cell_menu}
|
|
936
|
+
{selected_cells}
|
|
937
|
+
{copy_flash}
|
|
938
|
+
{active_cell_menu}
|
|
939
|
+
styling={search_results[index][j].styling}
|
|
940
|
+
{latex_delimiters}
|
|
941
|
+
{line_breaks}
|
|
942
|
+
datatype={Array.isArray(datatype) ? datatype[j] : datatype}
|
|
943
|
+
{editing}
|
|
944
|
+
{clear_on_focus}
|
|
945
|
+
{max_chars}
|
|
946
|
+
{root}
|
|
947
|
+
{editable}
|
|
948
|
+
is_static={static_columns.includes(j)}
|
|
949
|
+
{i18n}
|
|
950
|
+
{components}
|
|
951
|
+
{handle_select_column}
|
|
952
|
+
{handle_select_row}
|
|
953
|
+
bind:el={els[id]}
|
|
954
|
+
{is_dragging}
|
|
955
|
+
/>
|
|
1304
956
|
{/each}
|
|
1305
957
|
</tr>
|
|
1306
958
|
</VirtualTable>
|
|
1307
959
|
</div>
|
|
1308
960
|
</Upload>
|
|
961
|
+
{#if show_scroll_button}
|
|
962
|
+
<button class="scroll-top-button" on:click={scroll_to_top}>
|
|
963
|
+
↑
|
|
964
|
+
</button>
|
|
965
|
+
{/if}
|
|
1309
966
|
</div>
|
|
1310
967
|
</div>
|
|
1311
968
|
{#if data.length === 0 && editable && row_count[1] === "dynamic"}
|
|
1312
|
-
<
|
|
1313
|
-
<button class="add-row-button" on:click={() => add_row()}>
|
|
1314
|
-
<span>+</span>
|
|
1315
|
-
</button>
|
|
1316
|
-
</div>
|
|
969
|
+
<EmptyRowButton on_click={() => add_row()} />
|
|
1317
970
|
{/if}
|
|
1318
971
|
|
|
1319
|
-
{#if active_cell_menu}
|
|
972
|
+
{#if active_cell_menu || active_header_menu}
|
|
1320
973
|
<CellMenu
|
|
1321
|
-
x={active_cell_menu
|
|
1322
|
-
y={active_cell_menu
|
|
1323
|
-
row={active_cell_menu
|
|
1324
|
-
{col_count}
|
|
1325
|
-
{row_count}
|
|
1326
|
-
on_add_row_above={() => add_row_at(active_cell_menu?.row || 0, "above")}
|
|
1327
|
-
on_add_row_below={() => add_row_at(active_cell_menu?.row || 0, "below")}
|
|
1328
|
-
on_add_column_left={() => add_col_at(active_cell_menu?.col || 0, "left")}
|
|
1329
|
-
on_add_column_right={() => add_col_at(active_cell_menu?.col || 0, "right")}
|
|
1330
|
-
on_delete_row={() => delete_row_at(active_cell_menu?.row || 0)}
|
|
1331
|
-
on_delete_col={() => delete_col_at(active_cell_menu?.col || 0)}
|
|
1332
|
-
can_delete_rows={data.length > 1}
|
|
1333
|
-
can_delete_cols={data[0].length > 1}
|
|
1334
|
-
{i18n}
|
|
1335
|
-
/>
|
|
1336
|
-
{/if}
|
|
1337
|
-
|
|
1338
|
-
{#if active_header_menu !== null}
|
|
1339
|
-
<CellMenu
|
|
1340
|
-
{i18n}
|
|
1341
|
-
x={active_header_menu.x}
|
|
1342
|
-
y={active_header_menu.y}
|
|
1343
|
-
row={-1}
|
|
974
|
+
x={active_cell_menu?.x ?? active_header_menu?.x ?? 0}
|
|
975
|
+
y={active_cell_menu?.y ?? active_header_menu?.y ?? 0}
|
|
976
|
+
row={active_header_menu ? -1 : active_cell_menu?.row ?? 0}
|
|
1344
977
|
{col_count}
|
|
1345
978
|
{row_count}
|
|
1346
979
|
on_add_row_above={() => add_row_at(active_cell_menu?.row ?? -1, "above")}
|
|
1347
980
|
on_add_row_below={() => add_row_at(active_cell_menu?.row ?? -1, "below")}
|
|
1348
|
-
on_add_column_left={() =>
|
|
981
|
+
on_add_column_left={() =>
|
|
982
|
+
add_col_at(
|
|
983
|
+
active_cell_menu?.col ?? active_header_menu?.col ?? -1,
|
|
984
|
+
"left"
|
|
985
|
+
)}
|
|
1349
986
|
on_add_column_right={() =>
|
|
1350
|
-
add_col_at(
|
|
987
|
+
add_col_at(
|
|
988
|
+
active_cell_menu?.col ?? active_header_menu?.col ?? -1,
|
|
989
|
+
"right"
|
|
990
|
+
)}
|
|
1351
991
|
on_delete_row={() => delete_row_at(active_cell_menu?.row ?? -1)}
|
|
1352
|
-
on_delete_col={() =>
|
|
1353
|
-
|
|
1354
|
-
|
|
992
|
+
on_delete_col={() =>
|
|
993
|
+
delete_col_at(active_cell_menu?.col ?? active_header_menu?.col ?? -1)}
|
|
994
|
+
{editable}
|
|
995
|
+
can_delete_rows={!active_header_menu && data.length > 1 && editable}
|
|
996
|
+
can_delete_cols={data.length > 0 && data[0]?.length > 1 && editable}
|
|
997
|
+
{i18n}
|
|
998
|
+
on_sort={active_header_menu
|
|
999
|
+
? (direction) => {
|
|
1000
|
+
if (active_header_menu) {
|
|
1001
|
+
handle_sort(active_header_menu.col, direction);
|
|
1002
|
+
df_actions.set_active_header_menu(null);
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
1005
|
+
: undefined}
|
|
1006
|
+
on_clear_sort={active_header_menu
|
|
1007
|
+
? () => {
|
|
1008
|
+
clear_sort();
|
|
1009
|
+
df_actions.set_active_header_menu(null);
|
|
1010
|
+
}
|
|
1011
|
+
: undefined}
|
|
1012
|
+
sort_direction={active_header_menu
|
|
1013
|
+
? $df_state.sort_state.sort_columns.find(
|
|
1014
|
+
(item) => item.col === (active_header_menu?.col ?? -1)
|
|
1015
|
+
)?.direction ?? null
|
|
1016
|
+
: null}
|
|
1017
|
+
sort_priority={active_header_menu
|
|
1018
|
+
? $df_state.sort_state.sort_columns.findIndex(
|
|
1019
|
+
(item) => item.col === (active_header_menu?.col ?? -1)
|
|
1020
|
+
) + 1 || null
|
|
1021
|
+
: null}
|
|
1355
1022
|
/>
|
|
1356
1023
|
{/if}
|
|
1357
1024
|
|
|
1358
1025
|
<style>
|
|
1359
|
-
.label p {
|
|
1360
|
-
position: relative;
|
|
1361
|
-
z-index: var(--layer-4);
|
|
1362
|
-
margin-bottom: var(--size-2);
|
|
1363
|
-
color: var(--block-label-text-color);
|
|
1364
|
-
font-size: var(--block-label-text-size);
|
|
1365
|
-
}
|
|
1366
|
-
|
|
1367
1026
|
.table-container {
|
|
1368
1027
|
display: flex;
|
|
1369
1028
|
flex-direction: column;
|
|
1370
1029
|
gap: var(--size-2);
|
|
1030
|
+
position: relative;
|
|
1371
1031
|
}
|
|
1372
1032
|
|
|
1373
1033
|
.table-wrap {
|
|
@@ -1383,17 +1043,26 @@
|
|
|
1383
1043
|
outline: none;
|
|
1384
1044
|
}
|
|
1385
1045
|
|
|
1386
|
-
.dragging {
|
|
1387
|
-
|
|
1046
|
+
.table-wrap.dragging {
|
|
1047
|
+
cursor: crosshair !important;
|
|
1048
|
+
user-select: none;
|
|
1388
1049
|
}
|
|
1389
1050
|
|
|
1390
|
-
.
|
|
1391
|
-
|
|
1051
|
+
.table-wrap.dragging * {
|
|
1052
|
+
cursor: crosshair !important;
|
|
1053
|
+
user-select: none;
|
|
1054
|
+
}
|
|
1055
|
+
|
|
1056
|
+
.table-wrap > :global(button) {
|
|
1057
|
+
border: 1px solid var(--border-color-primary);
|
|
1058
|
+
border-radius: var(--table-radius);
|
|
1059
|
+
overflow: hidden;
|
|
1392
1060
|
}
|
|
1393
1061
|
|
|
1394
1062
|
table {
|
|
1395
1063
|
position: absolute;
|
|
1396
1064
|
opacity: 0;
|
|
1065
|
+
z-index: -1;
|
|
1397
1066
|
transition: 150ms;
|
|
1398
1067
|
width: var(--size-full);
|
|
1399
1068
|
table-layout: auto;
|
|
@@ -1405,159 +1074,39 @@
|
|
|
1405
1074
|
border-collapse: separate;
|
|
1406
1075
|
}
|
|
1407
1076
|
|
|
1408
|
-
.table-wrap > :global(button) {
|
|
1409
|
-
border: 1px solid var(--border-color-primary);
|
|
1410
|
-
border-radius: var(--table-radius);
|
|
1411
|
-
overflow: hidden;
|
|
1412
|
-
}
|
|
1413
|
-
|
|
1414
|
-
div:not(.no-wrap) td {
|
|
1415
|
-
overflow-wrap: anywhere;
|
|
1416
|
-
}
|
|
1417
|
-
|
|
1418
|
-
div.no-wrap td {
|
|
1419
|
-
overflow-x: hidden;
|
|
1420
|
-
}
|
|
1421
|
-
|
|
1422
|
-
table.fixed-layout {
|
|
1423
|
-
table-layout: fixed;
|
|
1424
|
-
}
|
|
1425
|
-
|
|
1426
1077
|
thead {
|
|
1427
1078
|
position: sticky;
|
|
1428
1079
|
top: 0;
|
|
1429
|
-
z-index:
|
|
1080
|
+
z-index: 5;
|
|
1430
1081
|
box-shadow: var(--shadow-drop);
|
|
1431
1082
|
}
|
|
1432
1083
|
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
tr > * + * {
|
|
1439
|
-
border-right-width: 0px;
|
|
1440
|
-
border-left-width: 1px;
|
|
1441
|
-
border-style: solid;
|
|
1442
|
-
border-color: var(--border-color-primary);
|
|
1443
|
-
}
|
|
1444
|
-
|
|
1445
|
-
th,
|
|
1446
|
-
td {
|
|
1447
|
-
--ring-color: transparent;
|
|
1448
|
-
position: relative;
|
|
1449
|
-
outline: none;
|
|
1450
|
-
box-shadow: inset 0 0 0 1px var(--ring-color);
|
|
1451
|
-
padding: 0;
|
|
1452
|
-
}
|
|
1453
|
-
|
|
1454
|
-
th:first-child {
|
|
1455
|
-
border-top-left-radius: var(--table-radius);
|
|
1456
|
-
border-bottom-left-radius: var(--table-radius);
|
|
1457
|
-
}
|
|
1458
|
-
|
|
1459
|
-
th:last-child {
|
|
1460
|
-
border-top-right-radius: var(--table-radius);
|
|
1461
|
-
border-bottom-right-radius: var(--table-radius);
|
|
1462
|
-
}
|
|
1463
|
-
|
|
1464
|
-
th.focus,
|
|
1465
|
-
td.focus {
|
|
1466
|
-
--ring-color: var(--color-accent);
|
|
1467
|
-
box-shadow: inset 0 0 0 2px var(--ring-color);
|
|
1468
|
-
z-index: var(--layer-1);
|
|
1469
|
-
}
|
|
1470
|
-
|
|
1471
|
-
th.focus {
|
|
1472
|
-
z-index: var(--layer-2);
|
|
1473
|
-
}
|
|
1474
|
-
|
|
1475
|
-
tr:last-child td:first-child {
|
|
1476
|
-
border-bottom-left-radius: var(--table-radius);
|
|
1477
|
-
}
|
|
1478
|
-
|
|
1479
|
-
tr:last-child td:last-child {
|
|
1480
|
-
border-bottom-right-radius: var(--table-radius);
|
|
1481
|
-
}
|
|
1482
|
-
|
|
1483
|
-
tr th {
|
|
1484
|
-
background: var(--table-even-background-fill);
|
|
1084
|
+
thead :global(th.pinned-column) {
|
|
1085
|
+
position: sticky;
|
|
1086
|
+
z-index: 6;
|
|
1087
|
+
background: var(--table-even-background-fill) !important;
|
|
1485
1088
|
}
|
|
1486
1089
|
|
|
1487
|
-
.
|
|
1488
|
-
|
|
1489
|
-
align-items: center;
|
|
1490
|
-
flex-shrink: 0;
|
|
1491
|
-
order: -1;
|
|
1090
|
+
.dragging {
|
|
1091
|
+
border-color: var(--color-accent);
|
|
1492
1092
|
}
|
|
1493
1093
|
|
|
1494
|
-
.
|
|
1495
|
-
|
|
1094
|
+
.no-wrap {
|
|
1095
|
+
white-space: nowrap;
|
|
1496
1096
|
}
|
|
1497
1097
|
|
|
1498
|
-
.
|
|
1499
|
-
|
|
1500
|
-
align-items: center;
|
|
1501
|
-
justify-content: flex-start;
|
|
1502
|
-
outline: none;
|
|
1503
|
-
min-height: var(--size-9);
|
|
1504
|
-
position: relative;
|
|
1505
|
-
height: 100%;
|
|
1506
|
-
padding: var(--size-2);
|
|
1507
|
-
box-sizing: border-box;
|
|
1508
|
-
margin: 0;
|
|
1509
|
-
gap: var(--size-1);
|
|
1510
|
-
overflow: visible;
|
|
1511
|
-
min-width: 0;
|
|
1512
|
-
border-radius: var(--table-radius);
|
|
1098
|
+
div:not(.no-wrap) td {
|
|
1099
|
+
overflow-wrap: anywhere;
|
|
1513
1100
|
}
|
|
1514
1101
|
|
|
1515
|
-
.
|
|
1516
|
-
|
|
1517
|
-
align-items: center;
|
|
1518
|
-
overflow: hidden;
|
|
1519
|
-
flex-grow: 1;
|
|
1520
|
-
min-width: 0;
|
|
1521
|
-
white-space: normal;
|
|
1522
|
-
overflow-wrap: break-word;
|
|
1523
|
-
word-break: normal;
|
|
1524
|
-
height: 100%;
|
|
1525
|
-
gap: var(--size-1);
|
|
1102
|
+
div.no-wrap td {
|
|
1103
|
+
overflow-x: hidden;
|
|
1526
1104
|
}
|
|
1527
1105
|
|
|
1528
|
-
.
|
|
1106
|
+
.row-odd {
|
|
1529
1107
|
background: var(--table-odd-background-fill);
|
|
1530
1108
|
}
|
|
1531
1109
|
|
|
1532
|
-
.row_odd.focus {
|
|
1533
|
-
background: var(--background-fill-primary);
|
|
1534
|
-
}
|
|
1535
|
-
|
|
1536
|
-
.cell-menu-button {
|
|
1537
|
-
flex-shrink: 0;
|
|
1538
|
-
display: none;
|
|
1539
|
-
background-color: var(--block-background-fill);
|
|
1540
|
-
border: 1px solid var(--border-color-primary);
|
|
1541
|
-
border-radius: var(--block-radius);
|
|
1542
|
-
width: var(--size-5);
|
|
1543
|
-
height: var(--size-5);
|
|
1544
|
-
min-width: var(--size-5);
|
|
1545
|
-
padding: 0;
|
|
1546
|
-
margin-right: var(--spacing-sm);
|
|
1547
|
-
z-index: var(--layer-1);
|
|
1548
|
-
position: absolute;
|
|
1549
|
-
right: var(--size-1);
|
|
1550
|
-
top: 50%;
|
|
1551
|
-
transform: translateY(-50%);
|
|
1552
|
-
}
|
|
1553
|
-
|
|
1554
|
-
.cell-selected .cell-menu-button,
|
|
1555
|
-
th:hover .cell-menu-button {
|
|
1556
|
-
display: flex;
|
|
1557
|
-
align-items: center;
|
|
1558
|
-
justify-content: center;
|
|
1559
|
-
}
|
|
1560
|
-
|
|
1561
1110
|
.header-row {
|
|
1562
1111
|
display: flex;
|
|
1563
1112
|
justify-content: flex-end;
|
|
@@ -1568,225 +1117,45 @@
|
|
|
1568
1117
|
width: 100%;
|
|
1569
1118
|
}
|
|
1570
1119
|
|
|
1571
|
-
.label {
|
|
1120
|
+
.header-row .label {
|
|
1572
1121
|
flex: 1 1 auto;
|
|
1573
1122
|
margin-right: auto;
|
|
1574
1123
|
}
|
|
1575
1124
|
|
|
1576
|
-
.label p {
|
|
1125
|
+
.header-row .label p {
|
|
1577
1126
|
margin: 0;
|
|
1578
1127
|
color: var(--block-label-text-color);
|
|
1579
1128
|
font-size: var(--block-label-text-size);
|
|
1580
1129
|
line-height: var(--line-sm);
|
|
1581
|
-
}
|
|
1582
|
-
|
|
1583
|
-
.toolbar {
|
|
1584
|
-
flex: 0 0 auto;
|
|
1585
|
-
}
|
|
1586
|
-
|
|
1587
|
-
.row-number,
|
|
1588
|
-
.row-number-header {
|
|
1589
|
-
text-align: center;
|
|
1590
|
-
background: var(--table-even-background-fill);
|
|
1591
|
-
font-size: var(--input-text-size);
|
|
1592
|
-
color: var(--body-text-color);
|
|
1593
|
-
padding: var(--size-1);
|
|
1594
|
-
min-width: var(--size-12);
|
|
1595
|
-
width: var(--size-12);
|
|
1596
|
-
overflow: hidden;
|
|
1597
|
-
text-overflow: ellipsis;
|
|
1598
|
-
white-space: nowrap;
|
|
1599
|
-
font-weight: var(--weight-semibold);
|
|
1600
|
-
}
|
|
1601
|
-
|
|
1602
|
-
.row-number-header .header-content {
|
|
1603
|
-
justify-content: space-between;
|
|
1604
|
-
padding: var(--size-1);
|
|
1605
|
-
height: var(--size-9);
|
|
1606
|
-
display: flex;
|
|
1607
|
-
align-items: center;
|
|
1608
|
-
}
|
|
1609
|
-
|
|
1610
|
-
.row-number-header :global(.sort-icons) {
|
|
1611
|
-
margin-right: 0;
|
|
1612
|
-
}
|
|
1613
|
-
|
|
1614
|
-
:global(tbody > tr:nth-child(odd)) .row-number {
|
|
1615
|
-
background: var(--table-odd-background-fill);
|
|
1616
|
-
}
|
|
1617
|
-
|
|
1618
|
-
.cell-selected {
|
|
1619
|
-
--ring-color: var(--color-accent);
|
|
1620
|
-
box-shadow: inset 0 0 0 2px var(--ring-color);
|
|
1621
|
-
z-index: var(--layer-1);
|
|
1622
1130
|
position: relative;
|
|
1131
|
+
z-index: 4;
|
|
1623
1132
|
}
|
|
1624
1133
|
|
|
1625
|
-
.
|
|
1626
|
-
box-shadow:
|
|
1627
|
-
inset 2px 0 0 var(--ring-color),
|
|
1628
|
-
inset -2px 0 0 var(--ring-color),
|
|
1629
|
-
inset 0 -2px 0 var(--ring-color);
|
|
1630
|
-
}
|
|
1631
|
-
|
|
1632
|
-
.cell-selected.no-bottom {
|
|
1633
|
-
box-shadow:
|
|
1634
|
-
inset 2px 0 0 var(--ring-color),
|
|
1635
|
-
inset -2px 0 0 var(--ring-color),
|
|
1636
|
-
inset 0 2px 0 var(--ring-color);
|
|
1637
|
-
}
|
|
1638
|
-
|
|
1639
|
-
.cell-selected.no-left {
|
|
1640
|
-
box-shadow:
|
|
1641
|
-
inset 0 2px 0 var(--ring-color),
|
|
1642
|
-
inset -2px 0 0 var(--ring-color),
|
|
1643
|
-
inset 0 -2px 0 var(--ring-color);
|
|
1644
|
-
}
|
|
1645
|
-
|
|
1646
|
-
.cell-selected.no-right {
|
|
1647
|
-
box-shadow:
|
|
1648
|
-
inset 0 2px 0 var(--ring-color),
|
|
1649
|
-
inset 2px 0 0 var(--ring-color),
|
|
1650
|
-
inset 0 -2px 0 var(--ring-color);
|
|
1651
|
-
}
|
|
1652
|
-
|
|
1653
|
-
.cell-selected.no-top.no-left {
|
|
1654
|
-
box-shadow:
|
|
1655
|
-
inset -2px 0 0 var(--ring-color),
|
|
1656
|
-
inset 0 -2px 0 var(--ring-color);
|
|
1657
|
-
}
|
|
1658
|
-
|
|
1659
|
-
.cell-selected.no-top.no-right {
|
|
1660
|
-
box-shadow:
|
|
1661
|
-
inset 2px 0 0 var(--ring-color),
|
|
1662
|
-
inset 0 -2px 0 var(--ring-color);
|
|
1663
|
-
}
|
|
1664
|
-
|
|
1665
|
-
.cell-selected.no-bottom.no-left {
|
|
1666
|
-
box-shadow:
|
|
1667
|
-
inset -2px 0 0 var(--ring-color),
|
|
1668
|
-
inset 0 2px 0 var(--ring-color);
|
|
1669
|
-
}
|
|
1670
|
-
|
|
1671
|
-
.cell-selected.no-bottom.no-right {
|
|
1672
|
-
box-shadow:
|
|
1673
|
-
inset 2px 0 0 var(--ring-color),
|
|
1674
|
-
inset 0 2px 0 var(--ring-color);
|
|
1675
|
-
}
|
|
1676
|
-
|
|
1677
|
-
.cell-selected.no-top.no-bottom {
|
|
1678
|
-
box-shadow:
|
|
1679
|
-
inset 2px 0 0 var(--ring-color),
|
|
1680
|
-
inset -2px 0 0 var(--ring-color);
|
|
1681
|
-
}
|
|
1682
|
-
|
|
1683
|
-
.cell-selected.no-left.no-right {
|
|
1684
|
-
box-shadow:
|
|
1685
|
-
inset 0 2px 0 var(--ring-color),
|
|
1686
|
-
inset 0 -2px 0 var(--ring-color);
|
|
1687
|
-
}
|
|
1688
|
-
|
|
1689
|
-
.cell-selected.no-top.no-left.no-right {
|
|
1690
|
-
box-shadow: inset 0 -2px 0 var(--ring-color);
|
|
1691
|
-
}
|
|
1692
|
-
|
|
1693
|
-
.cell-selected.no-bottom.no-left.no-right {
|
|
1694
|
-
box-shadow: inset 0 2px 0 var(--ring-color);
|
|
1695
|
-
}
|
|
1696
|
-
|
|
1697
|
-
.cell-selected.no-left.no-top.no-bottom {
|
|
1698
|
-
box-shadow: inset -2px 0 0 var(--ring-color);
|
|
1699
|
-
}
|
|
1700
|
-
|
|
1701
|
-
.cell-selected.no-right.no-top.no-bottom {
|
|
1702
|
-
box-shadow: inset 2px 0 0 var(--ring-color);
|
|
1703
|
-
}
|
|
1704
|
-
|
|
1705
|
-
.cell-selected.no-top.no-bottom.no-left.no-right {
|
|
1706
|
-
box-shadow: none;
|
|
1707
|
-
}
|
|
1708
|
-
|
|
1709
|
-
.selection-button {
|
|
1134
|
+
.scroll-top-button {
|
|
1710
1135
|
position: absolute;
|
|
1136
|
+
right: var(--size-4);
|
|
1137
|
+
bottom: var(--size-4);
|
|
1138
|
+
width: var(--size-8);
|
|
1139
|
+
height: var(--size-8);
|
|
1140
|
+
border-radius: var(--table-radius);
|
|
1141
|
+
background: var(--color-accent);
|
|
1142
|
+
color: white;
|
|
1143
|
+
border: none;
|
|
1144
|
+
cursor: pointer;
|
|
1711
1145
|
display: flex;
|
|
1712
1146
|
align-items: center;
|
|
1713
1147
|
justify-content: center;
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
z-index: var(--layer-4);
|
|
1718
|
-
}
|
|
1719
|
-
|
|
1720
|
-
.selection-button-column {
|
|
1721
|
-
width: var(--size-3);
|
|
1722
|
-
height: var(--size-5);
|
|
1723
|
-
top: -10px;
|
|
1724
|
-
left: var(--selected-col-pos);
|
|
1725
|
-
transform: rotate(90deg);
|
|
1148
|
+
font-size: var(--text-lg);
|
|
1149
|
+
z-index: 9;
|
|
1150
|
+
opacity: 0.5;
|
|
1726
1151
|
}
|
|
1727
1152
|
|
|
1728
|
-
.
|
|
1729
|
-
|
|
1730
|
-
height: var(--size-5);
|
|
1731
|
-
left: -7px;
|
|
1732
|
-
top: calc(var(--selected-row-pos) - var(--size-5) / 2);
|
|
1153
|
+
.scroll-top-button:hover {
|
|
1154
|
+
opacity: 1;
|
|
1733
1155
|
}
|
|
1734
1156
|
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
}
|
|
1739
|
-
|
|
1740
|
-
.flash.cell-selected {
|
|
1741
|
-
animation: flash-color 700ms ease-out;
|
|
1742
|
-
}
|
|
1743
|
-
|
|
1744
|
-
@keyframes flash-color {
|
|
1745
|
-
0%,
|
|
1746
|
-
30% {
|
|
1747
|
-
background: var(--color-accent-copied);
|
|
1748
|
-
}
|
|
1749
|
-
|
|
1750
|
-
100% {
|
|
1751
|
-
background: transparent;
|
|
1752
|
-
}
|
|
1753
|
-
}
|
|
1754
|
-
|
|
1755
|
-
.frozen-column {
|
|
1756
|
-
position: sticky;
|
|
1757
|
-
z-index: var(--layer-2);
|
|
1758
|
-
border-right: 1px solid var(--border-color-primary);
|
|
1759
|
-
}
|
|
1760
|
-
|
|
1761
|
-
tr:nth-child(odd) .frozen-column {
|
|
1762
|
-
background: var(--table-odd-background-fill);
|
|
1763
|
-
}
|
|
1764
|
-
|
|
1765
|
-
tr:nth-child(even) .frozen-column {
|
|
1766
|
-
background: var(--table-even-background-fill);
|
|
1767
|
-
}
|
|
1768
|
-
|
|
1769
|
-
.always-frozen {
|
|
1770
|
-
z-index: var(--layer-3);
|
|
1771
|
-
}
|
|
1772
|
-
|
|
1773
|
-
.add-row-container {
|
|
1774
|
-
margin-top: var(--size-2);
|
|
1775
|
-
}
|
|
1776
|
-
|
|
1777
|
-
.add-row-button {
|
|
1778
|
-
width: 100%;
|
|
1779
|
-
padding: var(--size-1);
|
|
1780
|
-
background: transparent;
|
|
1781
|
-
border: 1px dashed var(--border-color-primary);
|
|
1782
|
-
border-radius: var(--radius-sm);
|
|
1783
|
-
color: var(--body-text-color);
|
|
1784
|
-
cursor: pointer;
|
|
1785
|
-
transition: all 150ms;
|
|
1786
|
-
}
|
|
1787
|
-
|
|
1788
|
-
.add-row-button:hover {
|
|
1789
|
-
background: var(--background-fill-secondary);
|
|
1790
|
-
border-style: solid;
|
|
1157
|
+
tr {
|
|
1158
|
+
border-bottom: 1px solid var(--border-color-primary);
|
|
1159
|
+
text-align: left;
|
|
1791
1160
|
}
|
|
1792
1161
|
</style>
|