@gradio/dataframe 0.13.1 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +28 -0
- package/Dataframe.stories.svelte +148 -2
- package/Index.svelte +4 -0
- package/dist/Index.svelte +4 -0
- package/dist/Index.svelte.d.ts +8 -0
- package/dist/shared/CellMenu.svelte +21 -9
- package/dist/shared/CellMenu.svelte.d.ts +4 -0
- package/dist/shared/CellMenuIcons.svelte +112 -0
- package/dist/shared/CellMenuIcons.svelte.d.ts +16 -0
- package/dist/shared/EditableCell.svelte +52 -7
- package/dist/shared/EditableCell.svelte.d.ts +1 -1
- package/dist/shared/Table.svelte +356 -270
- package/dist/shared/Table.svelte.d.ts +2 -0
- package/dist/shared/Toolbar.svelte +46 -6
- package/dist/shared/Toolbar.svelte.d.ts +2 -0
- package/dist/shared/selection_utils.d.ts +20 -0
- package/dist/shared/selection_utils.js +111 -0
- package/dist/shared/table_utils.d.ts +12 -0
- package/dist/shared/table_utils.js +113 -0
- package/dist/shared/types.d.ts +2 -0
- package/dist/shared/types.js +1 -0
- package/package.json +6 -6
- package/shared/CellMenu.svelte +21 -9
- package/shared/CellMenuIcons.svelte +113 -0
- package/shared/EditableCell.svelte +58 -7
- package/shared/Table.svelte +400 -341
- package/shared/Toolbar.svelte +48 -6
- package/shared/selection_utils.ts +188 -0
- package/shared/table_utils.ts +148 -0
- package/shared/types.ts +2 -0
- package/dist/shared/Arrow.svelte +0 -9
- package/dist/shared/Arrow.svelte.d.ts +0 -16
- package/shared/Arrow.svelte +0 -10
package/shared/Table.svelte
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { afterUpdate, createEventDispatcher, tick, onMount } from "svelte";
|
|
3
|
-
import { dsvFormat } from "d3-dsv";
|
|
4
3
|
import { dequal } from "dequal/lite";
|
|
5
4
|
import { Upload } from "@gradio/upload";
|
|
6
5
|
|
|
@@ -17,6 +16,19 @@
|
|
|
17
16
|
} from "./utils";
|
|
18
17
|
import CellMenu from "./CellMenu.svelte";
|
|
19
18
|
import Toolbar from "./Toolbar.svelte";
|
|
19
|
+
import type { CellCoordinate, EditingState } from "./types";
|
|
20
|
+
import {
|
|
21
|
+
is_cell_selected,
|
|
22
|
+
handle_selection,
|
|
23
|
+
handle_delete_key,
|
|
24
|
+
should_show_cell_menu,
|
|
25
|
+
get_next_cell_coordinates,
|
|
26
|
+
get_range_selection,
|
|
27
|
+
move_cursor,
|
|
28
|
+
get_current_indices,
|
|
29
|
+
handle_click_outside as handle_click_outside_util
|
|
30
|
+
} from "./selection_utils";
|
|
31
|
+
import { copy_table_data, get_max, handle_file_upload } from "./table_utils";
|
|
20
32
|
|
|
21
33
|
export let datatype: Datatype | Datatype[];
|
|
22
34
|
export let label: string | null = null;
|
|
@@ -43,13 +55,26 @@
|
|
|
43
55
|
export let upload: Client["upload"];
|
|
44
56
|
export let stream_handler: Client["stream"];
|
|
45
57
|
export let show_fullscreen_button = false;
|
|
58
|
+
export let show_copy_button = false;
|
|
46
59
|
export let value_is_output = false;
|
|
60
|
+
export let max_chars: number | undefined = undefined;
|
|
61
|
+
|
|
62
|
+
let selected_cells: CellCoordinate[] = [];
|
|
63
|
+
$: selected_cells = [...selected_cells];
|
|
64
|
+
let selected: CellCoordinate | false = false;
|
|
65
|
+
$: selected =
|
|
66
|
+
selected_cells.length > 0
|
|
67
|
+
? selected_cells[selected_cells.length - 1]
|
|
68
|
+
: false;
|
|
47
69
|
|
|
48
|
-
let selected: false | [number, number] = false;
|
|
49
|
-
let clicked_cell: { row: number; col: number } | undefined = undefined;
|
|
50
70
|
export let display_value: string[][] | null = null;
|
|
51
71
|
export let styling: string[][] | null = null;
|
|
52
72
|
let t_rect: DOMRectReadOnly;
|
|
73
|
+
let els: Record<
|
|
74
|
+
string,
|
|
75
|
+
{ cell: null | HTMLTableCellElement; input: null | HTMLInputElement }
|
|
76
|
+
> = {};
|
|
77
|
+
let data_binding: Record<string, (typeof data)[0][0]> = {};
|
|
53
78
|
|
|
54
79
|
const dispatch = createEventDispatcher<{
|
|
55
80
|
change: DataframeValue;
|
|
@@ -57,34 +82,27 @@
|
|
|
57
82
|
select: SelectData;
|
|
58
83
|
}>();
|
|
59
84
|
|
|
60
|
-
let editing:
|
|
85
|
+
let editing: EditingState = false;
|
|
86
|
+
let clear_on_focus = false;
|
|
87
|
+
let header_edit: number | false = false;
|
|
88
|
+
let selected_header: number | false = false;
|
|
89
|
+
let active_cell_menu: {
|
|
90
|
+
row: number;
|
|
91
|
+
col: number;
|
|
92
|
+
x: number;
|
|
93
|
+
y: number;
|
|
94
|
+
} | null = null;
|
|
95
|
+
let active_header_menu: {
|
|
96
|
+
col: number;
|
|
97
|
+
x: number;
|
|
98
|
+
y: number;
|
|
99
|
+
} | null = null;
|
|
100
|
+
let is_fullscreen = false;
|
|
101
|
+
let dragging = false;
|
|
61
102
|
|
|
62
103
|
const get_data_at = (row: number, col: number): string | number =>
|
|
63
104
|
data?.[row]?.[col]?.value;
|
|
64
105
|
|
|
65
|
-
let last_selected: [number, number] | null = null;
|
|
66
|
-
|
|
67
|
-
$: {
|
|
68
|
-
if (selected !== false && !dequal(selected, last_selected)) {
|
|
69
|
-
const [row, col] = selected;
|
|
70
|
-
if (!isNaN(row) && !isNaN(col) && data[row]) {
|
|
71
|
-
dispatch("select", {
|
|
72
|
-
index: [row, col],
|
|
73
|
-
value: get_data_at(row, col),
|
|
74
|
-
row_value: data[row].map((d) => d.value)
|
|
75
|
-
});
|
|
76
|
-
last_selected = selected;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
let els: Record<
|
|
82
|
-
string,
|
|
83
|
-
{ cell: null | HTMLTableCellElement; input: null | HTMLInputElement }
|
|
84
|
-
> = {};
|
|
85
|
-
|
|
86
|
-
let data_binding: Record<string, (typeof data)[0][0]> = {};
|
|
87
|
-
|
|
88
106
|
function make_id(): string {
|
|
89
107
|
return Math.random().toString(36).substring(2, 15);
|
|
90
108
|
}
|
|
@@ -120,13 +138,7 @@
|
|
|
120
138
|
id: string;
|
|
121
139
|
}[][] {
|
|
122
140
|
const data_row_length = _values.length;
|
|
123
|
-
return Array(
|
|
124
|
-
row_count[1] === "fixed"
|
|
125
|
-
? row_count[0]
|
|
126
|
-
: data_row_length < row_count[0]
|
|
127
|
-
? row_count[0]
|
|
128
|
-
: data_row_length
|
|
129
|
-
)
|
|
141
|
+
return Array(row_count[1] === "fixed" ? row_count[0] : data_row_length)
|
|
130
142
|
.fill(0)
|
|
131
143
|
.map((_, i) =>
|
|
132
144
|
Array(
|
|
@@ -203,48 +215,9 @@
|
|
|
203
215
|
if (direction === "asc") return "ascending";
|
|
204
216
|
if (direction === "des") return "descending";
|
|
205
217
|
}
|
|
206
|
-
|
|
207
218
|
return "none";
|
|
208
219
|
}
|
|
209
220
|
|
|
210
|
-
function get_current_indices(id: string): [number, number] {
|
|
211
|
-
return data.reduce(
|
|
212
|
-
(acc, arr, i) => {
|
|
213
|
-
const j = arr.reduce(
|
|
214
|
-
(_acc, _data, k) => (id === _data.id ? k : _acc),
|
|
215
|
-
-1
|
|
216
|
-
);
|
|
217
|
-
|
|
218
|
-
return j === -1 ? acc : [i, j];
|
|
219
|
-
},
|
|
220
|
-
[-1, -1]
|
|
221
|
-
);
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
function move_cursor(
|
|
225
|
-
key: "ArrowRight" | "ArrowLeft" | "ArrowDown" | "ArrowUp",
|
|
226
|
-
current_coords: [number, number]
|
|
227
|
-
): void {
|
|
228
|
-
const dir = {
|
|
229
|
-
ArrowRight: [0, 1],
|
|
230
|
-
ArrowLeft: [0, -1],
|
|
231
|
-
ArrowDown: [1, 0],
|
|
232
|
-
ArrowUp: [-1, 0]
|
|
233
|
-
}[key];
|
|
234
|
-
|
|
235
|
-
const i = current_coords[0] + dir[0];
|
|
236
|
-
const j = current_coords[1] + dir[1];
|
|
237
|
-
|
|
238
|
-
if (i < 0 && j <= 0) {
|
|
239
|
-
selected_header = j;
|
|
240
|
-
selected = false;
|
|
241
|
-
} else {
|
|
242
|
-
const is_data = data[i]?.[j];
|
|
243
|
-
selected = is_data ? [i, j] : selected;
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
let clear_on_focus = false;
|
|
248
221
|
// eslint-disable-next-line complexity
|
|
249
222
|
async function handle_keydown(event: KeyboardEvent): Promise<void> {
|
|
250
223
|
if (selected_header !== false && header_edit === false) {
|
|
@@ -272,6 +245,50 @@
|
|
|
272
245
|
break;
|
|
273
246
|
}
|
|
274
247
|
}
|
|
248
|
+
|
|
249
|
+
if (event.key === "Delete" || event.key === "Backspace") {
|
|
250
|
+
if (!editable) return;
|
|
251
|
+
|
|
252
|
+
if (editing) {
|
|
253
|
+
const [row, col] = editing;
|
|
254
|
+
const input_el = els[data[row][col].id].input;
|
|
255
|
+
if (input_el && input_el.selectionStart !== input_el.selectionEnd) {
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
if (
|
|
259
|
+
event.key === "Delete" &&
|
|
260
|
+
input_el?.selectionStart !== input_el?.value.length
|
|
261
|
+
) {
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
if (event.key === "Backspace" && input_el?.selectionStart !== 0) {
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
event.preventDefault();
|
|
270
|
+
if (selected_cells.length > 0) {
|
|
271
|
+
data = handle_delete_key(data, selected_cells);
|
|
272
|
+
dispatch("change", {
|
|
273
|
+
data: data.map((row) => row.map((cell) => cell.value)),
|
|
274
|
+
headers: _headers.map((h) => h.value),
|
|
275
|
+
metadata: null
|
|
276
|
+
});
|
|
277
|
+
if (!value_is_output) {
|
|
278
|
+
dispatch("input");
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
if (event.key === "c" && (event.metaKey || event.ctrlKey)) {
|
|
285
|
+
event.preventDefault();
|
|
286
|
+
if (selected_cells.length > 0) {
|
|
287
|
+
await handle_copy();
|
|
288
|
+
}
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
|
|
275
292
|
if (!selected) {
|
|
276
293
|
return;
|
|
277
294
|
}
|
|
@@ -285,7 +302,29 @@
|
|
|
285
302
|
case "ArrowUp":
|
|
286
303
|
if (editing) break;
|
|
287
304
|
event.preventDefault();
|
|
288
|
-
move_cursor(event.key, [i, j]);
|
|
305
|
+
const next_coords = move_cursor(event.key, [i, j], data);
|
|
306
|
+
if (next_coords) {
|
|
307
|
+
if (event.shiftKey) {
|
|
308
|
+
selected_cells = get_range_selection(
|
|
309
|
+
selected_cells.length > 0 ? selected_cells[0] : [i, j],
|
|
310
|
+
next_coords
|
|
311
|
+
);
|
|
312
|
+
editing = false;
|
|
313
|
+
} else {
|
|
314
|
+
selected_cells = [next_coords];
|
|
315
|
+
editing = next_coords;
|
|
316
|
+
clear_on_focus = false;
|
|
317
|
+
}
|
|
318
|
+
selected = next_coords;
|
|
319
|
+
} else if (
|
|
320
|
+
next_coords === false &&
|
|
321
|
+
event.key === "ArrowUp" &&
|
|
322
|
+
i === 0
|
|
323
|
+
) {
|
|
324
|
+
selected_header = j;
|
|
325
|
+
selected = false;
|
|
326
|
+
editing = false;
|
|
327
|
+
}
|
|
289
328
|
break;
|
|
290
329
|
|
|
291
330
|
case "Escape":
|
|
@@ -314,39 +353,26 @@
|
|
|
314
353
|
selected = [i, j];
|
|
315
354
|
} else {
|
|
316
355
|
editing = [i, j];
|
|
356
|
+
clear_on_focus = false;
|
|
317
357
|
}
|
|
318
358
|
}
|
|
319
|
-
|
|
320
|
-
break;
|
|
321
|
-
case "Backspace":
|
|
322
|
-
if (!editable) break;
|
|
323
|
-
if (!editing) {
|
|
324
|
-
event.preventDefault();
|
|
325
|
-
data[i][j].value = "";
|
|
326
|
-
}
|
|
327
|
-
break;
|
|
328
|
-
case "Delete":
|
|
329
|
-
if (!editable) break;
|
|
330
|
-
if (!editing) {
|
|
331
|
-
event.preventDefault();
|
|
332
|
-
data[i][j].value = "";
|
|
333
|
-
}
|
|
334
359
|
break;
|
|
335
360
|
case "Tab":
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
let is_data_x = data[i][j + direction];
|
|
339
|
-
let is_data_y =
|
|
340
|
-
data?.[i + direction]?.[direction > 0 ? 0 : _headers.length - 1];
|
|
341
|
-
|
|
342
|
-
if (is_data_x || is_data_y) {
|
|
343
|
-
event.preventDefault();
|
|
344
|
-
selected = is_data_x
|
|
345
|
-
? [i, j + direction]
|
|
346
|
-
: [i + direction, direction > 0 ? 0 : _headers.length - 1];
|
|
347
|
-
}
|
|
361
|
+
event.preventDefault();
|
|
348
362
|
editing = false;
|
|
349
|
-
|
|
363
|
+
const next_cell = get_next_cell_coordinates(
|
|
364
|
+
[i, j],
|
|
365
|
+
data,
|
|
366
|
+
event.shiftKey
|
|
367
|
+
);
|
|
368
|
+
if (next_cell) {
|
|
369
|
+
selected_cells = [next_cell];
|
|
370
|
+
selected = next_cell;
|
|
371
|
+
if (editable) {
|
|
372
|
+
editing = next_cell;
|
|
373
|
+
clear_on_focus = false;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
350
376
|
break;
|
|
351
377
|
default:
|
|
352
378
|
if (!editable) break;
|
|
@@ -377,16 +403,12 @@
|
|
|
377
403
|
}
|
|
378
404
|
}
|
|
379
405
|
|
|
380
|
-
let header_edit: number | false;
|
|
381
|
-
|
|
382
|
-
let select_on_focus = false;
|
|
383
|
-
let selected_header: number | false = false;
|
|
384
406
|
async function edit_header(i: number, _select = false): Promise<void> {
|
|
385
407
|
if (!editable || col_count[1] !== "dynamic" || header_edit === i) return;
|
|
386
408
|
selected = false;
|
|
409
|
+
selected_cells = [];
|
|
387
410
|
selected_header = i;
|
|
388
411
|
header_edit = i;
|
|
389
|
-
select_on_focus = _select;
|
|
390
412
|
}
|
|
391
413
|
|
|
392
414
|
function end_header_edit(event: CustomEvent<KeyboardEvent>): void {
|
|
@@ -461,107 +483,14 @@
|
|
|
461
483
|
}
|
|
462
484
|
|
|
463
485
|
function handle_click_outside(event: Event): void {
|
|
464
|
-
if (
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
) {
|
|
486
|
+
if (handle_click_outside_util(event, parent)) {
|
|
487
|
+
editing = false;
|
|
488
|
+
selected_cells = [];
|
|
489
|
+
header_edit = false;
|
|
490
|
+
selected_header = false;
|
|
470
491
|
active_cell_menu = null;
|
|
471
492
|
active_header_menu = null;
|
|
472
493
|
}
|
|
473
|
-
|
|
474
|
-
const [trigger] = event.composedPath() as HTMLElement[];
|
|
475
|
-
if (parent.contains(trigger)) {
|
|
476
|
-
return;
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
clicked_cell = undefined;
|
|
480
|
-
editing = false;
|
|
481
|
-
selected = false;
|
|
482
|
-
header_edit = false;
|
|
483
|
-
selected_header = false;
|
|
484
|
-
active_cell_menu = null;
|
|
485
|
-
active_header_menu = null;
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
function guess_delimitaor(
|
|
489
|
-
text: string,
|
|
490
|
-
possibleDelimiters: string[]
|
|
491
|
-
): string[] {
|
|
492
|
-
return possibleDelimiters.filter(weedOut);
|
|
493
|
-
|
|
494
|
-
function weedOut(delimiter: string): boolean {
|
|
495
|
-
var cache = -1;
|
|
496
|
-
return text.split("\n").every(checkLength);
|
|
497
|
-
|
|
498
|
-
function checkLength(line: string): boolean {
|
|
499
|
-
if (!line) {
|
|
500
|
-
return true;
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
var length = line.split(delimiter).length;
|
|
504
|
-
if (cache < 0) {
|
|
505
|
-
cache = length;
|
|
506
|
-
}
|
|
507
|
-
return cache === length && length > 1;
|
|
508
|
-
}
|
|
509
|
-
}
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
function data_uri_to_blob(data_uri: string): Blob {
|
|
513
|
-
const byte_str = atob(data_uri.split(",")[1]);
|
|
514
|
-
const mime_str = data_uri.split(",")[0].split(":")[1].split(";")[0];
|
|
515
|
-
|
|
516
|
-
const ab = new ArrayBuffer(byte_str.length);
|
|
517
|
-
const ia = new Uint8Array(ab);
|
|
518
|
-
|
|
519
|
-
for (let i = 0; i < byte_str.length; i++) {
|
|
520
|
-
ia[i] = byte_str.charCodeAt(i);
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
return new Blob([ab], { type: mime_str });
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
function blob_to_string(blob: Blob): void {
|
|
527
|
-
const reader = new FileReader();
|
|
528
|
-
|
|
529
|
-
function handle_read(e: ProgressEvent<FileReader>): void {
|
|
530
|
-
if (!e?.target?.result || typeof e.target.result !== "string") return;
|
|
531
|
-
|
|
532
|
-
const [delimiter] = guess_delimitaor(e.target.result, [",", "\t"]);
|
|
533
|
-
|
|
534
|
-
const [head, ...rest] = dsvFormat(delimiter).parseRows(e.target.result);
|
|
535
|
-
|
|
536
|
-
_headers = make_headers(
|
|
537
|
-
col_count[1] === "fixed" ? head.slice(0, col_count[0]) : head
|
|
538
|
-
);
|
|
539
|
-
|
|
540
|
-
values = rest;
|
|
541
|
-
reader.removeEventListener("loadend", handle_read);
|
|
542
|
-
}
|
|
543
|
-
|
|
544
|
-
reader.addEventListener("loadend", handle_read);
|
|
545
|
-
|
|
546
|
-
reader.readAsText(blob);
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
let dragging = false;
|
|
550
|
-
|
|
551
|
-
function get_max(
|
|
552
|
-
_d: { value: any; id: string }[][]
|
|
553
|
-
): { value: any; id: string }[] {
|
|
554
|
-
if (!_d || _d.length === 0 || !_d[0]) return [];
|
|
555
|
-
let max = _d[0].slice();
|
|
556
|
-
for (let i = 0; i < _d.length; i++) {
|
|
557
|
-
for (let j = 0; j < _d[i].length; j++) {
|
|
558
|
-
if (`${max[j].value}`.length < `${_d[i][j].value}`.length) {
|
|
559
|
-
max[j] = _d[i][j];
|
|
560
|
-
}
|
|
561
|
-
}
|
|
562
|
-
}
|
|
563
|
-
|
|
564
|
-
return max;
|
|
565
494
|
}
|
|
566
495
|
|
|
567
496
|
$: max = get_max(data);
|
|
@@ -632,7 +561,7 @@
|
|
|
632
561
|
data = data;
|
|
633
562
|
|
|
634
563
|
if (id) {
|
|
635
|
-
const [i, j] = get_current_indices(id);
|
|
564
|
+
const [i, j] = get_current_indices(id, data);
|
|
636
565
|
selected = [i, j];
|
|
637
566
|
}
|
|
638
567
|
}
|
|
@@ -644,19 +573,17 @@
|
|
|
644
573
|
let is_visible = false;
|
|
645
574
|
|
|
646
575
|
onMount(() => {
|
|
647
|
-
const observer = new IntersectionObserver((entries
|
|
576
|
+
const observer = new IntersectionObserver((entries) => {
|
|
648
577
|
entries.forEach((entry) => {
|
|
649
578
|
if (entry.isIntersecting && !is_visible) {
|
|
650
579
|
set_cell_widths();
|
|
651
580
|
data = data;
|
|
652
581
|
}
|
|
653
|
-
|
|
654
582
|
is_visible = entry.isIntersecting;
|
|
655
583
|
});
|
|
656
584
|
});
|
|
657
585
|
|
|
658
586
|
observer.observe(parent);
|
|
659
|
-
|
|
660
587
|
document.addEventListener("click", handle_click_outside);
|
|
661
588
|
window.addEventListener("resize", handle_resize);
|
|
662
589
|
document.addEventListener("fullscreenchange", handle_fullscreen_change);
|
|
@@ -672,14 +599,43 @@
|
|
|
672
599
|
};
|
|
673
600
|
});
|
|
674
601
|
|
|
675
|
-
|
|
602
|
+
function handle_cell_click(
|
|
603
|
+
event: MouseEvent,
|
|
604
|
+
row: number,
|
|
605
|
+
col: number
|
|
606
|
+
): void {
|
|
607
|
+
event.preventDefault();
|
|
608
|
+
event.stopPropagation();
|
|
609
|
+
clear_on_focus = false;
|
|
610
|
+
active_cell_menu = null;
|
|
611
|
+
active_header_menu = null;
|
|
612
|
+
selected_header = false;
|
|
613
|
+
header_edit = false;
|
|
676
614
|
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
615
|
+
selected_cells = handle_selection([row, col], selected_cells, event);
|
|
616
|
+
|
|
617
|
+
if (selected_cells.length === 1 && editable) {
|
|
618
|
+
editing = [row, col];
|
|
619
|
+
tick().then(() => {
|
|
620
|
+
const input_el = els[data[row][col].id].input;
|
|
621
|
+
if (input_el) {
|
|
622
|
+
input_el.focus();
|
|
623
|
+
input_el.selectionStart = input_el.selectionEnd =
|
|
624
|
+
input_el.value.length;
|
|
625
|
+
}
|
|
626
|
+
});
|
|
627
|
+
} else {
|
|
628
|
+
editing = false;
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
toggle_cell_button(row, col);
|
|
632
|
+
|
|
633
|
+
dispatch("select", {
|
|
634
|
+
index: [row, col],
|
|
635
|
+
value: get_data_at(row, col),
|
|
636
|
+
row_value: data[row].map((d) => d.value)
|
|
637
|
+
});
|
|
638
|
+
}
|
|
683
639
|
|
|
684
640
|
function toggle_cell_menu(event: MouseEvent, row: number, col: number): void {
|
|
685
641
|
event.stopPropagation();
|
|
@@ -693,12 +649,7 @@
|
|
|
693
649
|
const cell = (event.target as HTMLElement).closest("td");
|
|
694
650
|
if (cell) {
|
|
695
651
|
const rect = cell.getBoundingClientRect();
|
|
696
|
-
active_cell_menu = {
|
|
697
|
-
row,
|
|
698
|
-
col,
|
|
699
|
-
x: rect.right,
|
|
700
|
-
y: rect.bottom
|
|
701
|
-
};
|
|
652
|
+
active_cell_menu = { row, col, x: rect.right, y: rect.bottom };
|
|
702
653
|
}
|
|
703
654
|
}
|
|
704
655
|
}
|
|
@@ -730,33 +681,21 @@
|
|
|
730
681
|
} | null = null;
|
|
731
682
|
|
|
732
683
|
function toggle_header_button(col: number): void {
|
|
733
|
-
|
|
734
|
-
active_button
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
}
|
|
684
|
+
active_button =
|
|
685
|
+
active_button?.type === "header" && active_button.col === col
|
|
686
|
+
? null
|
|
687
|
+
: { type: "header", col };
|
|
738
688
|
}
|
|
739
689
|
|
|
740
690
|
function toggle_cell_button(row: number, col: number): void {
|
|
741
|
-
|
|
691
|
+
active_button =
|
|
742
692
|
active_button?.type === "cell" &&
|
|
743
693
|
active_button.row === row &&
|
|
744
694
|
active_button.col === col
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
} else {
|
|
748
|
-
active_button = { type: "cell", row, col };
|
|
749
|
-
}
|
|
695
|
+
? null
|
|
696
|
+
: { type: "cell", row, col };
|
|
750
697
|
}
|
|
751
698
|
|
|
752
|
-
let active_header_menu: {
|
|
753
|
-
col: number;
|
|
754
|
-
x: number;
|
|
755
|
-
y: number;
|
|
756
|
-
} | null = null;
|
|
757
|
-
|
|
758
|
-
let is_fullscreen = false;
|
|
759
|
-
|
|
760
699
|
function toggle_fullscreen(): void {
|
|
761
700
|
if (!document.fullscreenElement) {
|
|
762
701
|
parent.requestFullscreen();
|
|
@@ -771,6 +710,10 @@
|
|
|
771
710
|
is_fullscreen = !!document.fullscreenElement;
|
|
772
711
|
}
|
|
773
712
|
|
|
713
|
+
async function handle_copy(): Promise<void> {
|
|
714
|
+
await copy_table_data(data, _headers, selected_cells);
|
|
715
|
+
}
|
|
716
|
+
|
|
774
717
|
function toggle_header_menu(event: MouseEvent, col: number): void {
|
|
775
718
|
event.stopPropagation();
|
|
776
719
|
if (active_header_menu && active_header_menu.col === col) {
|
|
@@ -779,11 +722,7 @@
|
|
|
779
722
|
const header = (event.target as HTMLElement).closest("th");
|
|
780
723
|
if (header) {
|
|
781
724
|
const rect = header.getBoundingClientRect();
|
|
782
|
-
active_header_menu = {
|
|
783
|
-
col,
|
|
784
|
-
x: rect.right,
|
|
785
|
-
y: rect.bottom
|
|
786
|
-
};
|
|
725
|
+
active_header_menu = { col, x: rect.right, y: rect.bottom };
|
|
787
726
|
}
|
|
788
727
|
}
|
|
789
728
|
}
|
|
@@ -791,6 +730,42 @@
|
|
|
791
730
|
afterUpdate(() => {
|
|
792
731
|
value_is_output = false;
|
|
793
732
|
});
|
|
733
|
+
|
|
734
|
+
async function delete_row(index: number): Promise<void> {
|
|
735
|
+
parent.focus();
|
|
736
|
+
if (row_count[1] !== "dynamic") return;
|
|
737
|
+
if (data.length <= 1) return;
|
|
738
|
+
data.splice(index, 1);
|
|
739
|
+
data = data;
|
|
740
|
+
selected = false;
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
async function delete_col(index: number): Promise<void> {
|
|
744
|
+
parent.focus();
|
|
745
|
+
if (col_count[1] !== "dynamic") return;
|
|
746
|
+
if (data[0].length <= 1) return;
|
|
747
|
+
|
|
748
|
+
_headers.splice(index, 1);
|
|
749
|
+
_headers = _headers;
|
|
750
|
+
|
|
751
|
+
data.forEach((row) => {
|
|
752
|
+
row.splice(index, 1);
|
|
753
|
+
});
|
|
754
|
+
data = data;
|
|
755
|
+
selected = false;
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
function delete_row_at(index: number): void {
|
|
759
|
+
delete_row(index);
|
|
760
|
+
active_cell_menu = null;
|
|
761
|
+
active_header_menu = null;
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
function delete_col_at(index: number): void {
|
|
765
|
+
delete_col(index);
|
|
766
|
+
active_cell_menu = null;
|
|
767
|
+
active_header_menu = null;
|
|
768
|
+
}
|
|
794
769
|
</script>
|
|
795
770
|
|
|
796
771
|
<svelte:window on:resize={() => set_cell_widths()} />
|
|
@@ -806,6 +781,8 @@
|
|
|
806
781
|
{show_fullscreen_button}
|
|
807
782
|
{is_fullscreen}
|
|
808
783
|
on:click={toggle_fullscreen}
|
|
784
|
+
on_copy={handle_copy}
|
|
785
|
+
{show_copy_button}
|
|
809
786
|
/>
|
|
810
787
|
</div>
|
|
811
788
|
<div
|
|
@@ -846,6 +823,7 @@
|
|
|
846
823
|
edit={false}
|
|
847
824
|
el={null}
|
|
848
825
|
{root}
|
|
826
|
+
{editable}
|
|
849
827
|
/>
|
|
850
828
|
|
|
851
829
|
<div
|
|
@@ -881,6 +859,7 @@
|
|
|
881
859
|
edit={false}
|
|
882
860
|
el={null}
|
|
883
861
|
{root}
|
|
862
|
+
{editable}
|
|
884
863
|
/>
|
|
885
864
|
</div>
|
|
886
865
|
</td>
|
|
@@ -896,8 +875,20 @@
|
|
|
896
875
|
boundedheight={false}
|
|
897
876
|
disable_click={true}
|
|
898
877
|
{root}
|
|
899
|
-
on:load={(
|
|
878
|
+
on:load={({ detail }) =>
|
|
879
|
+
handle_file_upload(
|
|
880
|
+
detail.data,
|
|
881
|
+
col_count,
|
|
882
|
+
(head) => {
|
|
883
|
+
_headers = make_headers(head);
|
|
884
|
+
return _headers;
|
|
885
|
+
},
|
|
886
|
+
(vals) => {
|
|
887
|
+
values = vals;
|
|
888
|
+
}
|
|
889
|
+
)}
|
|
900
890
|
bind:dragging
|
|
891
|
+
aria_label={i18n("dataframe.drop_to_upload")}
|
|
901
892
|
>
|
|
902
893
|
<VirtualTable
|
|
903
894
|
bind:items={data}
|
|
@@ -925,6 +916,7 @@
|
|
|
925
916
|
<div class="cell-wrap">
|
|
926
917
|
<div class="header-content">
|
|
927
918
|
<EditableCell
|
|
919
|
+
{max_chars}
|
|
928
920
|
bind:value={_headers[i].value}
|
|
929
921
|
bind:el={els[id].input}
|
|
930
922
|
{latex_delimiters}
|
|
@@ -934,6 +926,7 @@
|
|
|
934
926
|
on:dblclick={() => edit_header(i)}
|
|
935
927
|
header
|
|
936
928
|
{root}
|
|
929
|
+
{editable}
|
|
937
930
|
/>
|
|
938
931
|
<button
|
|
939
932
|
class:sorted={sort_by === i}
|
|
@@ -962,7 +955,7 @@
|
|
|
962
955
|
class="cell-menu-button"
|
|
963
956
|
on:click={(event) => toggle_header_menu(event, i)}
|
|
964
957
|
>
|
|
965
|
-
|
|
958
|
+
⋮
|
|
966
959
|
</button>
|
|
967
960
|
{/if}
|
|
968
961
|
</div>
|
|
@@ -978,40 +971,24 @@
|
|
|
978
971
|
<td
|
|
979
972
|
tabindex="0"
|
|
980
973
|
on:touchstart={(event) => {
|
|
981
|
-
event.
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
}
|
|
991
|
-
toggle_cell_button(index, j);
|
|
974
|
+
const touch = event.touches[0];
|
|
975
|
+
const mouseEvent = new MouseEvent("click", {
|
|
976
|
+
clientX: touch.clientX,
|
|
977
|
+
clientY: touch.clientY,
|
|
978
|
+
bubbles: true,
|
|
979
|
+
cancelable: true,
|
|
980
|
+
view: window
|
|
981
|
+
});
|
|
982
|
+
handle_cell_click(mouseEvent, index, j);
|
|
992
983
|
}}
|
|
993
984
|
on:mousedown={(event) => {
|
|
994
985
|
event.preventDefault();
|
|
995
986
|
event.stopPropagation();
|
|
996
987
|
}}
|
|
997
|
-
on:click={(event) =>
|
|
998
|
-
event.preventDefault();
|
|
999
|
-
event.stopPropagation();
|
|
1000
|
-
clear_on_focus = false;
|
|
1001
|
-
active_cell_menu = null;
|
|
1002
|
-
active_header_menu = null;
|
|
1003
|
-
clicked_cell = { row: index, col: j };
|
|
1004
|
-
selected = [index, j];
|
|
1005
|
-
selected_header = false;
|
|
1006
|
-
header_edit = false;
|
|
1007
|
-
if (editable) {
|
|
1008
|
-
editing = [index, j];
|
|
1009
|
-
}
|
|
1010
|
-
toggle_cell_button(index, j);
|
|
1011
|
-
}}
|
|
988
|
+
on:click={(event) => handle_cell_click(event, index, j)}
|
|
1012
989
|
style:width="var(--cell-width-{j})"
|
|
1013
990
|
style={styling?.[index]?.[j] || ""}
|
|
1014
|
-
class
|
|
991
|
+
class={is_cell_selected([index, j], selected_cells)}
|
|
1015
992
|
class:menu-active={active_cell_menu &&
|
|
1016
993
|
active_cell_menu.row === index &&
|
|
1017
994
|
active_cell_menu.col === j}
|
|
@@ -1030,15 +1007,25 @@
|
|
|
1030
1007
|
clear_on_focus = false;
|
|
1031
1008
|
parent.focus();
|
|
1032
1009
|
}}
|
|
1010
|
+
on:focus={() => {
|
|
1011
|
+
const row = index;
|
|
1012
|
+
const col = j;
|
|
1013
|
+
if (
|
|
1014
|
+
!selected_cells.some(([r, c]) => r === row && c === col)
|
|
1015
|
+
) {
|
|
1016
|
+
selected_cells = [[row, col]];
|
|
1017
|
+
}
|
|
1018
|
+
}}
|
|
1033
1019
|
{clear_on_focus}
|
|
1034
1020
|
{root}
|
|
1021
|
+
{max_chars}
|
|
1035
1022
|
/>
|
|
1036
|
-
{#if editable}
|
|
1023
|
+
{#if editable && should_show_cell_menu([index, j], selected_cells, editable)}
|
|
1037
1024
|
<button
|
|
1038
1025
|
class="cell-menu-button"
|
|
1039
1026
|
on:click={(event) => toggle_cell_menu(event, index, j)}
|
|
1040
1027
|
>
|
|
1041
|
-
|
|
1028
|
+
⋮
|
|
1042
1029
|
</button>
|
|
1043
1030
|
{/if}
|
|
1044
1031
|
</div>
|
|
@@ -1050,18 +1037,22 @@
|
|
|
1050
1037
|
</div>
|
|
1051
1038
|
</div>
|
|
1052
1039
|
|
|
1053
|
-
{#if active_cell_menu
|
|
1040
|
+
{#if active_cell_menu}
|
|
1054
1041
|
<CellMenu
|
|
1055
|
-
{i18n}
|
|
1056
1042
|
x={active_cell_menu.x}
|
|
1057
1043
|
y={active_cell_menu.y}
|
|
1058
|
-
row={active_cell_menu
|
|
1044
|
+
row={active_cell_menu.row}
|
|
1059
1045
|
{col_count}
|
|
1060
1046
|
{row_count}
|
|
1061
|
-
on_add_row_above={() => add_row_at(active_cell_menu?.row
|
|
1062
|
-
on_add_row_below={() => add_row_at(active_cell_menu?.row
|
|
1063
|
-
on_add_column_left={() => add_col_at(active_cell_menu?.col
|
|
1064
|
-
on_add_column_right={() => add_col_at(active_cell_menu?.col
|
|
1047
|
+
on_add_row_above={() => add_row_at(active_cell_menu?.row || 0, "above")}
|
|
1048
|
+
on_add_row_below={() => add_row_at(active_cell_menu?.row || 0, "below")}
|
|
1049
|
+
on_add_column_left={() => add_col_at(active_cell_menu?.col || 0, "left")}
|
|
1050
|
+
on_add_column_right={() => add_col_at(active_cell_menu?.col || 0, "right")}
|
|
1051
|
+
on_delete_row={() => delete_row_at(active_cell_menu?.row || 0)}
|
|
1052
|
+
on_delete_col={() => delete_col_at(active_cell_menu?.col || 0)}
|
|
1053
|
+
can_delete_rows={data.length > 1}
|
|
1054
|
+
can_delete_cols={data[0].length > 1}
|
|
1055
|
+
{i18n}
|
|
1065
1056
|
/>
|
|
1066
1057
|
{/if}
|
|
1067
1058
|
|
|
@@ -1078,25 +1069,18 @@
|
|
|
1078
1069
|
on_add_column_left={() => add_col_at(active_header_menu?.col ?? -1, "left")}
|
|
1079
1070
|
on_add_column_right={() =>
|
|
1080
1071
|
add_col_at(active_header_menu?.col ?? -1, "right")}
|
|
1072
|
+
on_delete_row={() => delete_row_at(active_cell_menu?.row ?? -1)}
|
|
1073
|
+
on_delete_col={() => delete_col_at(active_header_menu?.col ?? -1)}
|
|
1074
|
+
can_delete_rows={false}
|
|
1075
|
+
can_delete_cols={data[0].length > 1}
|
|
1081
1076
|
/>
|
|
1082
1077
|
{/if}
|
|
1083
1078
|
|
|
1084
1079
|
<style>
|
|
1085
|
-
.
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
.button-wrap svg {
|
|
1090
|
-
margin-right: var(--size-1);
|
|
1091
|
-
margin-left: -5px;
|
|
1092
|
-
}
|
|
1093
|
-
|
|
1094
|
-
.label p {
|
|
1095
|
-
position: relative;
|
|
1096
|
-
z-index: var(--layer-4);
|
|
1097
|
-
margin-bottom: var(--size-2);
|
|
1098
|
-
color: var(--block-label-text-color);
|
|
1099
|
-
font-size: var(--block-label-text-size);
|
|
1080
|
+
.table-container {
|
|
1081
|
+
display: flex;
|
|
1082
|
+
flex-direction: column;
|
|
1083
|
+
gap: var(--size-2);
|
|
1100
1084
|
}
|
|
1101
1085
|
|
|
1102
1086
|
.table-wrap {
|
|
@@ -1109,7 +1093,6 @@
|
|
|
1109
1093
|
|
|
1110
1094
|
.table-wrap:focus-within {
|
|
1111
1095
|
outline: none;
|
|
1112
|
-
background-color: none;
|
|
1113
1096
|
}
|
|
1114
1097
|
|
|
1115
1098
|
.dragging {
|
|
@@ -1131,6 +1114,7 @@
|
|
|
1131
1114
|
line-height: var(--line-md);
|
|
1132
1115
|
font-family: var(--font-mono);
|
|
1133
1116
|
border-spacing: 0;
|
|
1117
|
+
border-collapse: separate;
|
|
1134
1118
|
}
|
|
1135
1119
|
|
|
1136
1120
|
div:not(.no-wrap) td {
|
|
@@ -1185,6 +1169,12 @@
|
|
|
1185
1169
|
th.focus,
|
|
1186
1170
|
td.focus {
|
|
1187
1171
|
--ring-color: var(--color-accent);
|
|
1172
|
+
box-shadow: inset 0 0 0 2px var(--ring-color);
|
|
1173
|
+
z-index: var(--layer-1);
|
|
1174
|
+
}
|
|
1175
|
+
|
|
1176
|
+
th.focus {
|
|
1177
|
+
z-index: var(--layer-2);
|
|
1188
1178
|
}
|
|
1189
1179
|
|
|
1190
1180
|
tr:last-child td:first-child {
|
|
@@ -1213,7 +1203,6 @@
|
|
|
1213
1203
|
cursor: pointer;
|
|
1214
1204
|
padding: var(--size-2);
|
|
1215
1205
|
color: var(--body-text-color-subdued);
|
|
1216
|
-
line-height: var(--text-sm);
|
|
1217
1206
|
}
|
|
1218
1207
|
|
|
1219
1208
|
.sort-button:hover {
|
|
@@ -1234,11 +1223,11 @@
|
|
|
1234
1223
|
|
|
1235
1224
|
.cell-wrap {
|
|
1236
1225
|
display: flex;
|
|
1237
|
-
align-items:
|
|
1226
|
+
align-items: flex-start;
|
|
1238
1227
|
outline: none;
|
|
1239
|
-
height: var(--size-full);
|
|
1240
1228
|
min-height: var(--size-9);
|
|
1241
|
-
|
|
1229
|
+
position: relative;
|
|
1230
|
+
height: auto;
|
|
1242
1231
|
}
|
|
1243
1232
|
|
|
1244
1233
|
.header-content {
|
|
@@ -1247,12 +1236,9 @@
|
|
|
1247
1236
|
overflow: hidden;
|
|
1248
1237
|
flex-grow: 1;
|
|
1249
1238
|
min-width: 0;
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
display: flex;
|
|
1254
|
-
justify-content: flex-end;
|
|
1255
|
-
padding-top: var(--size-2);
|
|
1239
|
+
white-space: normal;
|
|
1240
|
+
overflow-wrap: break-word;
|
|
1241
|
+
word-break: break-word;
|
|
1256
1242
|
}
|
|
1257
1243
|
|
|
1258
1244
|
.row_odd {
|
|
@@ -1263,10 +1249,6 @@
|
|
|
1263
1249
|
background: var(--background-fill-primary);
|
|
1264
1250
|
}
|
|
1265
1251
|
|
|
1266
|
-
table {
|
|
1267
|
-
border-collapse: separate;
|
|
1268
|
-
}
|
|
1269
|
-
|
|
1270
1252
|
.cell-menu-button {
|
|
1271
1253
|
flex-shrink: 0;
|
|
1272
1254
|
display: none;
|
|
@@ -1279,28 +1261,35 @@
|
|
|
1279
1261
|
padding: 0;
|
|
1280
1262
|
margin-right: var(--spacing-sm);
|
|
1281
1263
|
z-index: var(--layer-1);
|
|
1264
|
+
position: absolute;
|
|
1265
|
+
right: var(--size-1);
|
|
1266
|
+
top: 50%;
|
|
1267
|
+
transform: translateY(-50%);
|
|
1282
1268
|
}
|
|
1283
1269
|
|
|
1284
|
-
.cell-menu-button
|
|
1285
|
-
|
|
1270
|
+
.cell-selected .cell-menu-button {
|
|
1271
|
+
display: flex;
|
|
1272
|
+
align-items: center;
|
|
1273
|
+
justify-content: center;
|
|
1286
1274
|
}
|
|
1287
1275
|
|
|
1288
|
-
|
|
1276
|
+
.header-row {
|
|
1289
1277
|
display: flex;
|
|
1278
|
+
justify-content: space-between;
|
|
1290
1279
|
align-items: center;
|
|
1291
|
-
|
|
1280
|
+
gap: var(--size-2);
|
|
1281
|
+
height: var(--size-6);
|
|
1282
|
+
min-height: var(--size-6);
|
|
1292
1283
|
}
|
|
1293
1284
|
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
overflow-wrap: break-word;
|
|
1297
|
-
word-break: break-word;
|
|
1285
|
+
.label {
|
|
1286
|
+
flex: 1;
|
|
1298
1287
|
}
|
|
1299
1288
|
|
|
1300
|
-
.
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1289
|
+
.label p {
|
|
1290
|
+
margin: 0;
|
|
1291
|
+
color: var(--block-label-text-color);
|
|
1292
|
+
font-size: var(--block-label-text-size);
|
|
1304
1293
|
}
|
|
1305
1294
|
|
|
1306
1295
|
.row-number,
|
|
@@ -1332,24 +1321,94 @@
|
|
|
1332
1321
|
background: var(--table-odd-background-fill);
|
|
1333
1322
|
}
|
|
1334
1323
|
|
|
1335
|
-
.
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
height: var(--size-6);
|
|
1341
|
-
min-height: var(--size-6);
|
|
1324
|
+
.cell-selected {
|
|
1325
|
+
--ring-color: var(--color-accent);
|
|
1326
|
+
box-shadow: inset 0 0 0 2px var(--ring-color);
|
|
1327
|
+
z-index: var(--layer-1);
|
|
1328
|
+
position: relative;
|
|
1342
1329
|
}
|
|
1343
1330
|
|
|
1344
|
-
.
|
|
1345
|
-
|
|
1331
|
+
.cell-selected.no-top {
|
|
1332
|
+
box-shadow:
|
|
1333
|
+
inset 2px 0 0 var(--ring-color),
|
|
1334
|
+
inset -2px 0 0 var(--ring-color),
|
|
1335
|
+
inset 0 -2px 0 var(--ring-color);
|
|
1346
1336
|
}
|
|
1347
1337
|
|
|
1348
|
-
.
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1338
|
+
.cell-selected.no-bottom {
|
|
1339
|
+
box-shadow:
|
|
1340
|
+
inset 2px 0 0 var(--ring-color),
|
|
1341
|
+
inset -2px 0 0 var(--ring-color),
|
|
1342
|
+
inset 0 2px 0 var(--ring-color);
|
|
1343
|
+
}
|
|
1344
|
+
|
|
1345
|
+
.cell-selected.no-left {
|
|
1346
|
+
box-shadow:
|
|
1347
|
+
inset 0 2px 0 var(--ring-color),
|
|
1348
|
+
inset -2px 0 0 var(--ring-color),
|
|
1349
|
+
inset 0 -2px 0 var(--ring-color);
|
|
1350
|
+
}
|
|
1351
|
+
|
|
1352
|
+
.cell-selected.no-right {
|
|
1353
|
+
box-shadow:
|
|
1354
|
+
inset 0 2px 0 var(--ring-color),
|
|
1355
|
+
inset 2px 0 0 var(--ring-color),
|
|
1356
|
+
inset 0 -2px 0 var(--ring-color);
|
|
1357
|
+
}
|
|
1358
|
+
|
|
1359
|
+
.cell-selected.no-top.no-left {
|
|
1360
|
+
box-shadow:
|
|
1361
|
+
inset -2px 0 0 var(--ring-color),
|
|
1362
|
+
inset 0 -2px 0 var(--ring-color);
|
|
1363
|
+
}
|
|
1364
|
+
|
|
1365
|
+
.cell-selected.no-top.no-right {
|
|
1366
|
+
box-shadow:
|
|
1367
|
+
inset 2px 0 0 var(--ring-color),
|
|
1368
|
+
inset 0 -2px 0 var(--ring-color);
|
|
1369
|
+
}
|
|
1370
|
+
|
|
1371
|
+
.cell-selected.no-bottom.no-left {
|
|
1372
|
+
box-shadow:
|
|
1373
|
+
inset -2px 0 0 var(--ring-color),
|
|
1374
|
+
inset 0 2px 0 var(--ring-color);
|
|
1375
|
+
}
|
|
1376
|
+
|
|
1377
|
+
.cell-selected.no-bottom.no-right {
|
|
1378
|
+
box-shadow:
|
|
1379
|
+
inset 2px 0 0 var(--ring-color),
|
|
1380
|
+
inset 0 2px 0 var(--ring-color);
|
|
1381
|
+
}
|
|
1382
|
+
|
|
1383
|
+
.cell-selected.no-top.no-bottom {
|
|
1384
|
+
box-shadow:
|
|
1385
|
+
inset 2px 0 0 var(--ring-color),
|
|
1386
|
+
inset -2px 0 0 var(--ring-color);
|
|
1387
|
+
}
|
|
1388
|
+
|
|
1389
|
+
.cell-selected.no-left.no-right {
|
|
1390
|
+
box-shadow:
|
|
1391
|
+
inset 0 2px 0 var(--ring-color),
|
|
1392
|
+
inset 0 -2px 0 var(--ring-color);
|
|
1393
|
+
}
|
|
1394
|
+
|
|
1395
|
+
.cell-selected.no-top.no-left.no-right {
|
|
1396
|
+
box-shadow: inset 0 -2px 0 var(--ring-color);
|
|
1397
|
+
}
|
|
1398
|
+
|
|
1399
|
+
.cell-selected.no-bottom.no-left.no-right {
|
|
1400
|
+
box-shadow: inset 0 2px 0 var(--ring-color);
|
|
1401
|
+
}
|
|
1402
|
+
|
|
1403
|
+
.cell-selected.no-left.no-top.no-bottom {
|
|
1404
|
+
box-shadow: inset -2px 0 0 var(--ring-color);
|
|
1405
|
+
}
|
|
1406
|
+
|
|
1407
|
+
.cell-selected.no-right.no-top.no-bottom {
|
|
1408
|
+
box-shadow: inset 2px 0 0 var(--ring-color);
|
|
1409
|
+
}
|
|
1410
|
+
|
|
1411
|
+
.cell-selected.no-top.no-bottom.no-left.no-right {
|
|
1412
|
+
box-shadow: none;
|
|
1354
1413
|
}
|
|
1355
1414
|
</style>
|