@gradio/dataframe 0.15.0 → 0.16.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 +29 -0
- package/Dataframe.stories.svelte +168 -2
- package/Index.svelte +20 -3
- package/dist/Index.svelte +16 -4
- package/dist/Index.svelte.d.ts +12 -0
- package/dist/shared/EditableCell.svelte +1 -4
- package/dist/shared/Table.svelte +423 -181
- package/dist/shared/Table.svelte.d.ts +3 -0
- package/dist/shared/Toolbar.svelte +122 -30
- package/dist/shared/Toolbar.svelte.d.ts +4 -0
- package/dist/shared/VirtualTable.svelte +70 -26
- package/dist/shared/VirtualTable.svelte.d.ts +1 -0
- package/dist/shared/icons/FilterIcon.svelte +11 -0
- package/dist/shared/icons/FilterIcon.svelte.d.ts +16 -0
- package/dist/shared/icons/SortIcon.svelte +90 -0
- package/dist/shared/icons/SortIcon.svelte.d.ts +20 -0
- package/dist/shared/selection_utils.d.ts +12 -2
- package/dist/shared/selection_utils.js +33 -5
- package/dist/shared/types.d.ts +16 -0
- package/dist/shared/types.js +1 -0
- package/dist/shared/utils/menu_utils.d.ts +42 -0
- package/dist/shared/utils/menu_utils.js +58 -0
- package/dist/shared/utils/sort_utils.d.ts +7 -0
- package/dist/shared/utils/sort_utils.js +39 -0
- package/dist/shared/utils/table_utils.d.ts +12 -0
- package/dist/shared/utils/table_utils.js +148 -0
- package/package.json +8 -8
- package/shared/EditableCell.svelte +1 -4
- package/shared/Table.svelte +453 -182
- package/shared/Toolbar.svelte +125 -30
- package/shared/VirtualTable.svelte +73 -26
- package/shared/icons/FilterIcon.svelte +12 -0
- package/shared/icons/SortIcon.svelte +95 -0
- package/shared/selection_utils.ts +51 -9
- package/shared/types.ts +27 -0
- package/shared/utils/menu_utils.ts +115 -0
- package/shared/utils/sort_utils.test.ts +71 -0
- package/shared/utils/sort_utils.ts +55 -0
- package/shared/utils/table_utils.test.ts +114 -0
- package/shared/utils/table_utils.ts +206 -0
- package/dist/shared/table_utils.d.ts +0 -12
- package/dist/shared/table_utils.js +0 -113
- package/shared/table_utils.ts +0 -148
|
@@ -31,6 +31,8 @@ declare const __propDef: {
|
|
|
31
31
|
show_copy_button?: boolean | undefined;
|
|
32
32
|
value_is_output?: boolean | undefined;
|
|
33
33
|
max_chars?: number | undefined;
|
|
34
|
+
show_search?: ("none" | "search" | "filter") | undefined;
|
|
35
|
+
pinned_columns?: number | undefined;
|
|
34
36
|
display_value?: (string[][] | null) | undefined;
|
|
35
37
|
styling?: (string[][] | null) | undefined;
|
|
36
38
|
};
|
|
@@ -38,6 +40,7 @@ declare const __propDef: {
|
|
|
38
40
|
change: CustomEvent<DataframeValue>;
|
|
39
41
|
input: CustomEvent<undefined>;
|
|
40
42
|
select: CustomEvent<SelectData>;
|
|
43
|
+
search: CustomEvent<string | null>;
|
|
41
44
|
} & {
|
|
42
45
|
[evt: string]: CustomEvent<any>;
|
|
43
46
|
};
|
|
@@ -1,11 +1,19 @@
|
|
|
1
|
-
<script>import { Maximize, Minimize, Copy
|
|
1
|
+
<script>import { Maximize, Minimize, Copy } from "@gradio/icons";
|
|
2
2
|
import { onDestroy } from "svelte";
|
|
3
|
+
import { createEventDispatcher } from "svelte";
|
|
4
|
+
import FilterIcon from "./icons/FilterIcon.svelte";
|
|
3
5
|
export let show_fullscreen_button = false;
|
|
4
6
|
export let show_copy_button = false;
|
|
7
|
+
export let show_search = "none";
|
|
5
8
|
export let is_fullscreen = false;
|
|
6
9
|
export let on_copy;
|
|
10
|
+
export let on_commit_filter;
|
|
11
|
+
const dispatch = createEventDispatcher();
|
|
7
12
|
let copied = false;
|
|
8
13
|
let timer;
|
|
14
|
+
export let current_search_query = null;
|
|
15
|
+
$:
|
|
16
|
+
dispatch("search", current_search_query);
|
|
9
17
|
function copy_feedback() {
|
|
10
18
|
copied = true;
|
|
11
19
|
if (timer)
|
|
@@ -25,41 +33,70 @@ onDestroy(() => {
|
|
|
25
33
|
</script>
|
|
26
34
|
|
|
27
35
|
<div class="toolbar" role="toolbar" aria-label="Table actions">
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
class="
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
36
|
+
<div class="toolbar-buttons">
|
|
37
|
+
{#if show_search !== "none"}
|
|
38
|
+
<div class="search-container">
|
|
39
|
+
<input
|
|
40
|
+
type="text"
|
|
41
|
+
bind:value={current_search_query}
|
|
42
|
+
placeholder="Search..."
|
|
43
|
+
class="search-input"
|
|
44
|
+
/>
|
|
45
|
+
{#if current_search_query && show_search === "filter"}
|
|
46
|
+
<button
|
|
47
|
+
class="toolbar-button check-button"
|
|
48
|
+
on:click={on_commit_filter}
|
|
49
|
+
aria-label="Apply filter and update dataframe values"
|
|
50
|
+
title="Apply filter and update dataframe values"
|
|
51
|
+
>
|
|
52
|
+
<FilterIcon />
|
|
53
|
+
</button>
|
|
54
|
+
{/if}
|
|
55
|
+
</div>
|
|
56
|
+
{/if}
|
|
57
|
+
{#if show_copy_button}
|
|
58
|
+
<button
|
|
59
|
+
class="toolbar-button"
|
|
60
|
+
on:click={handle_copy}
|
|
61
|
+
aria-label={copied ? "Copied to clipboard" : "Copy table data"}
|
|
62
|
+
title={copied ? "Copied to clipboard" : "Copy table data"}
|
|
63
|
+
>
|
|
64
|
+
{#if copied}
|
|
65
|
+
<FilterIcon />
|
|
66
|
+
{:else}
|
|
67
|
+
<Copy />
|
|
68
|
+
{/if}
|
|
69
|
+
</button>
|
|
70
|
+
{/if}
|
|
71
|
+
{#if show_fullscreen_button}
|
|
72
|
+
<button
|
|
73
|
+
class="toolbar-button"
|
|
74
|
+
on:click
|
|
75
|
+
aria-label={is_fullscreen ? "Exit fullscreen" : "Enter fullscreen"}
|
|
76
|
+
title={is_fullscreen ? "Exit fullscreen" : "Enter fullscreen"}
|
|
77
|
+
>
|
|
78
|
+
{#if is_fullscreen}
|
|
79
|
+
<Minimize />
|
|
80
|
+
{:else}
|
|
81
|
+
<Maximize />
|
|
82
|
+
{/if}
|
|
83
|
+
</button>
|
|
84
|
+
{/if}
|
|
85
|
+
</div>
|
|
56
86
|
</div>
|
|
57
87
|
|
|
58
88
|
<style>
|
|
59
89
|
.toolbar {
|
|
60
90
|
display: flex;
|
|
61
|
-
|
|
91
|
+
align-items: center;
|
|
92
|
+
gap: var(--size-2);
|
|
93
|
+
flex: 0 0 auto;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.toolbar-buttons {
|
|
97
|
+
display: flex;
|
|
62
98
|
gap: var(--size-1);
|
|
99
|
+
flex-wrap: nowrap;
|
|
63
100
|
}
|
|
64
101
|
|
|
65
102
|
.toolbar-button {
|
|
@@ -86,4 +123,59 @@ onDestroy(() => {
|
|
|
86
123
|
width: var(--size-4);
|
|
87
124
|
height: var(--size-4);
|
|
88
125
|
}
|
|
126
|
+
|
|
127
|
+
.search-container {
|
|
128
|
+
position: relative;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.search-input {
|
|
132
|
+
width: var(--size-full);
|
|
133
|
+
height: var(--size-6);
|
|
134
|
+
padding: var(--size-2);
|
|
135
|
+
padding-right: var(--size-8);
|
|
136
|
+
border: 1px solid var(--border-color-primary);
|
|
137
|
+
border-radius: var(--table-radius);
|
|
138
|
+
font-size: var(--text-sm);
|
|
139
|
+
color: var(--body-text-color);
|
|
140
|
+
background: var(--background-fill-secondary);
|
|
141
|
+
transition: all 0.2s ease;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
.search-input:hover {
|
|
145
|
+
border-color: var(--border-color-secondary);
|
|
146
|
+
background: var(--background-fill-primary);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.search-input:focus {
|
|
150
|
+
outline: none;
|
|
151
|
+
border-color: var(--color-accent);
|
|
152
|
+
background: var(--background-fill-primary);
|
|
153
|
+
box-shadow: 0 0 0 1px var(--color-accent);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
.check-button {
|
|
157
|
+
position: absolute;
|
|
158
|
+
right: var(--size-1);
|
|
159
|
+
top: 50%;
|
|
160
|
+
transform: translateY(-50%);
|
|
161
|
+
background: var(--color-accent);
|
|
162
|
+
color: white;
|
|
163
|
+
border: none;
|
|
164
|
+
width: var(--size-4);
|
|
165
|
+
height: var(--size-4);
|
|
166
|
+
border-radius: var(--radius-sm);
|
|
167
|
+
display: flex;
|
|
168
|
+
align-items: center;
|
|
169
|
+
justify-content: center;
|
|
170
|
+
padding: var(--size-1);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
.check-button :global(svg) {
|
|
174
|
+
width: var(--size-3);
|
|
175
|
+
height: var(--size-3);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
.check-button:hover {
|
|
179
|
+
background: var(--color-accent-soft);
|
|
180
|
+
}
|
|
89
181
|
</style>
|
|
@@ -3,11 +3,15 @@ declare const __propDef: {
|
|
|
3
3
|
props: {
|
|
4
4
|
show_fullscreen_button?: boolean | undefined;
|
|
5
5
|
show_copy_button?: boolean | undefined;
|
|
6
|
+
show_search?: ("none" | "search" | "filter") | undefined;
|
|
6
7
|
is_fullscreen?: boolean | undefined;
|
|
7
8
|
on_copy: () => Promise<void>;
|
|
9
|
+
on_commit_filter: () => void;
|
|
10
|
+
current_search_query?: (string | null) | undefined;
|
|
8
11
|
};
|
|
9
12
|
events: {
|
|
10
13
|
click: MouseEvent;
|
|
14
|
+
search: CustomEvent<string | null>;
|
|
11
15
|
} & {
|
|
12
16
|
[evt: string]: CustomEvent<any>;
|
|
13
17
|
};
|
|
@@ -7,6 +7,7 @@ export let table_scrollbar_width;
|
|
|
7
7
|
export let start = 0;
|
|
8
8
|
export let end = 20;
|
|
9
9
|
export let selected;
|
|
10
|
+
export let disable_scroll = false;
|
|
10
11
|
let height = "100%";
|
|
11
12
|
let average_height = 30;
|
|
12
13
|
let bottom = 0;
|
|
@@ -32,6 +33,8 @@ async function refresh_height_map(_items) {
|
|
|
32
33
|
if (viewport_height === 0) {
|
|
33
34
|
return;
|
|
34
35
|
}
|
|
36
|
+
head_height = viewport.querySelector(".thead")?.getBoundingClientRect().height || 0;
|
|
37
|
+
await tick();
|
|
35
38
|
const { scrollTop } = viewport;
|
|
36
39
|
table_scrollbar_width = viewport.offsetWidth - viewport.clientWidth;
|
|
37
40
|
content_height = top - (scrollTop - head_height);
|
|
@@ -202,29 +205,32 @@ onMount(() => {
|
|
|
202
205
|
</script>
|
|
203
206
|
|
|
204
207
|
<svelte-virtual-table-viewport>
|
|
205
|
-
<
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
208
|
+
<div>
|
|
209
|
+
<table
|
|
210
|
+
class="table"
|
|
211
|
+
class:disable-scroll={disable_scroll}
|
|
212
|
+
bind:this={viewport}
|
|
213
|
+
bind:contentRect={viewport_box}
|
|
214
|
+
on:scroll={handle_scroll}
|
|
215
|
+
style="height: {height}; --bw-svt-p-top: {top}px; --bw-svt-p-bottom: {bottom}px; --bw-svt-head-height: {head_height}px; --bw-svt-foot-height: {foot_height}px; --bw-svt-avg-row-height: {average_height}px; --max-height: {max_height}px"
|
|
216
|
+
>
|
|
217
|
+
<thead class="thead" bind:offsetHeight={head_height}>
|
|
218
|
+
<slot name="thead" />
|
|
219
|
+
</thead>
|
|
220
|
+
<tbody bind:this={contents} class="tbody">
|
|
221
|
+
{#if visible.length && visible[0].data.length}
|
|
222
|
+
{#each visible as item (item.data[0].id)}
|
|
223
|
+
<slot name="tbody" item={item.data} index={item.index}>
|
|
224
|
+
Missing Table Row
|
|
225
|
+
</slot>
|
|
226
|
+
{/each}
|
|
227
|
+
{/if}
|
|
228
|
+
</tbody>
|
|
229
|
+
<tfoot class="tfoot" bind:offsetHeight={foot_height}>
|
|
230
|
+
<slot name="tfoot" />
|
|
231
|
+
</tfoot>
|
|
232
|
+
</table>
|
|
233
|
+
</div>
|
|
228
234
|
</svelte-virtual-table-viewport>
|
|
229
235
|
|
|
230
236
|
<style>
|
|
@@ -233,7 +239,7 @@ onMount(() => {
|
|
|
233
239
|
overflow-y: scroll;
|
|
234
240
|
overflow-x: scroll;
|
|
235
241
|
-webkit-overflow-scrolling: touch;
|
|
236
|
-
max-height:
|
|
242
|
+
max-height: var(--max-height);
|
|
237
243
|
box-sizing: border-box;
|
|
238
244
|
display: block;
|
|
239
245
|
padding: 0;
|
|
@@ -281,11 +287,49 @@ onMount(() => {
|
|
|
281
287
|
background: var(--table-even-background-fill);
|
|
282
288
|
}
|
|
283
289
|
|
|
290
|
+
tbody :global(td.frozen-column) {
|
|
291
|
+
position: sticky;
|
|
292
|
+
z-index: var(--layer-2);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
tbody :global(tr:nth-child(odd)) :global(td.frozen-column) {
|
|
296
|
+
background: var(--table-odd-background-fill);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
tbody :global(tr:nth-child(even)) :global(td.frozen-column) {
|
|
300
|
+
background: var(--table-even-background-fill);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
tbody :global(td.always-frozen) {
|
|
304
|
+
z-index: var(--layer-3);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
tbody :global(td.last-frozen) {
|
|
308
|
+
border-right: 2px solid var(--border-color-primary);
|
|
309
|
+
}
|
|
310
|
+
|
|
284
311
|
thead {
|
|
285
312
|
position: sticky;
|
|
286
313
|
top: 0;
|
|
287
314
|
left: 0;
|
|
288
|
-
z-index: var(--layer-
|
|
289
|
-
|
|
315
|
+
z-index: var(--layer-3);
|
|
316
|
+
background: var(--background-fill-primary);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
thead :global(th) {
|
|
320
|
+
background: var(--table-even-background-fill) !important;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
thead :global(th.frozen-column) {
|
|
324
|
+
position: sticky;
|
|
325
|
+
z-index: var(--layer-4);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
thead :global(th.always-frozen) {
|
|
329
|
+
z-index: var(--layer-5);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
.table.disable-scroll {
|
|
333
|
+
overflow: hidden !important;
|
|
290
334
|
}
|
|
291
335
|
</style>
|
|
@@ -8,6 +8,7 @@ declare const __propDef: {
|
|
|
8
8
|
start?: number | undefined;
|
|
9
9
|
end?: number | undefined;
|
|
10
10
|
selected: number | false;
|
|
11
|
+
disable_scroll?: boolean | undefined;
|
|
11
12
|
scroll_to_index?: ((index: number, opts: ScrollToOptions, align_end?: boolean) => Promise<void>) | undefined;
|
|
12
13
|
};
|
|
13
14
|
events: {
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<script></script>
|
|
2
|
+
|
|
3
|
+
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
4
|
+
<path
|
|
5
|
+
d="M4 4h16v2.67l-6.67 6.67v8L9.33 19v-5.66L2.67 6.67V4h1.33z"
|
|
6
|
+
stroke="currentColor"
|
|
7
|
+
stroke-width="2"
|
|
8
|
+
stroke-linecap="round"
|
|
9
|
+
stroke-linejoin="round"
|
|
10
|
+
/>
|
|
11
|
+
</svg>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { SvelteComponent } from "svelte";
|
|
2
|
+
declare const __propDef: {
|
|
3
|
+
props: {
|
|
4
|
+
[x: string]: never;
|
|
5
|
+
};
|
|
6
|
+
events: {
|
|
7
|
+
[evt: string]: CustomEvent<any>;
|
|
8
|
+
};
|
|
9
|
+
slots: {};
|
|
10
|
+
};
|
|
11
|
+
export type FilterIconProps = typeof __propDef.props;
|
|
12
|
+
export type FilterIconEvents = typeof __propDef.events;
|
|
13
|
+
export type FilterIconSlots = typeof __propDef.slots;
|
|
14
|
+
export default class FilterIcon extends SvelteComponent<FilterIconProps, FilterIconEvents, FilterIconSlots> {
|
|
15
|
+
}
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
<script>import { createEventDispatcher } from "svelte";
|
|
2
|
+
export let direction = null;
|
|
3
|
+
export let i18n;
|
|
4
|
+
const dispatch = createEventDispatcher();
|
|
5
|
+
</script>
|
|
6
|
+
|
|
7
|
+
<div class="sort-icons" role="group" aria-label={i18n("dataframe.sort_column")}>
|
|
8
|
+
<button
|
|
9
|
+
class="sort-button up"
|
|
10
|
+
class:active={direction === "asc"}
|
|
11
|
+
on:click={() => dispatch("sort", "asc")}
|
|
12
|
+
aria-label={i18n("dataframe.sort_ascending")}
|
|
13
|
+
aria-pressed={direction === "asc"}
|
|
14
|
+
>
|
|
15
|
+
<svg
|
|
16
|
+
viewBox="0 0 24 24"
|
|
17
|
+
fill="none"
|
|
18
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
19
|
+
aria-hidden="true"
|
|
20
|
+
focusable="false"
|
|
21
|
+
>
|
|
22
|
+
<path
|
|
23
|
+
d="M7 14l5-5 5 5"
|
|
24
|
+
stroke="currentColor"
|
|
25
|
+
stroke-width="2"
|
|
26
|
+
stroke-linecap="round"
|
|
27
|
+
stroke-linejoin="round"
|
|
28
|
+
/>
|
|
29
|
+
</svg>
|
|
30
|
+
</button>
|
|
31
|
+
<button
|
|
32
|
+
class="sort-button down"
|
|
33
|
+
class:active={direction === "des"}
|
|
34
|
+
on:click={() => dispatch("sort", "des")}
|
|
35
|
+
aria-label={i18n("dataframe.sort_descending")}
|
|
36
|
+
aria-pressed={direction === "des"}
|
|
37
|
+
>
|
|
38
|
+
<svg
|
|
39
|
+
viewBox="0 0 24 24"
|
|
40
|
+
fill="none"
|
|
41
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
42
|
+
aria-hidden="true"
|
|
43
|
+
focusable="false"
|
|
44
|
+
>
|
|
45
|
+
<path
|
|
46
|
+
d="M7 10l5 5 5-5"
|
|
47
|
+
stroke="currentColor"
|
|
48
|
+
stroke-width="2"
|
|
49
|
+
stroke-linecap="round"
|
|
50
|
+
stroke-linejoin="round"
|
|
51
|
+
/>
|
|
52
|
+
</svg>
|
|
53
|
+
</button>
|
|
54
|
+
</div>
|
|
55
|
+
|
|
56
|
+
<style>
|
|
57
|
+
.sort-icons {
|
|
58
|
+
display: flex;
|
|
59
|
+
flex-direction: column;
|
|
60
|
+
gap: 0;
|
|
61
|
+
margin-right: var(--spacing-md);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.sort-button {
|
|
65
|
+
display: flex;
|
|
66
|
+
align-items: center;
|
|
67
|
+
justify-content: center;
|
|
68
|
+
padding: 0;
|
|
69
|
+
background: none;
|
|
70
|
+
border: none;
|
|
71
|
+
cursor: pointer;
|
|
72
|
+
opacity: 0.5;
|
|
73
|
+
transition: opacity 150ms;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.sort-button:hover {
|
|
77
|
+
opacity: 0.8;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.sort-button.active {
|
|
81
|
+
opacity: 1;
|
|
82
|
+
color: var(--color-accent);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
svg {
|
|
86
|
+
width: var(--size-3);
|
|
87
|
+
height: var(--size-3);
|
|
88
|
+
display: block;
|
|
89
|
+
}
|
|
90
|
+
</style>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { SvelteComponent } from "svelte";
|
|
2
|
+
import type { I18nFormatter } from "@gradio/utils";
|
|
3
|
+
declare const __propDef: {
|
|
4
|
+
props: {
|
|
5
|
+
direction?: (("asc" | "des") | null) | undefined;
|
|
6
|
+
i18n: I18nFormatter;
|
|
7
|
+
};
|
|
8
|
+
events: {
|
|
9
|
+
sort: CustomEvent<"asc" | "des">;
|
|
10
|
+
} & {
|
|
11
|
+
[evt: string]: CustomEvent<any>;
|
|
12
|
+
};
|
|
13
|
+
slots: {};
|
|
14
|
+
};
|
|
15
|
+
export type SortIconProps = typeof __propDef.props;
|
|
16
|
+
export type SortIconEvents = typeof __propDef.events;
|
|
17
|
+
export type SortIconSlots = typeof __propDef.slots;
|
|
18
|
+
export default class SortIcon extends SvelteComponent<SortIconProps, SortIconEvents, SortIconSlots> {
|
|
19
|
+
}
|
|
20
|
+
export {};
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
import type { CellCoordinate, EditingState } from "./types";
|
|
2
2
|
export type CellData = {
|
|
3
3
|
id: string;
|
|
4
4
|
value: string | number;
|
|
5
5
|
};
|
|
6
|
-
export type EditingState = false | CellCoordinate;
|
|
7
6
|
export declare function is_cell_selected(cell: CellCoordinate, selected_cells: CellCoordinate[]): string;
|
|
8
7
|
export declare function get_range_selection(start: CellCoordinate, end: CellCoordinate): CellCoordinate[];
|
|
9
8
|
export declare function handle_selection(current: CellCoordinate, selected_cells: CellCoordinate[], event: {
|
|
@@ -18,3 +17,14 @@ export declare function get_next_cell_coordinates(current: CellCoordinate, data:
|
|
|
18
17
|
export declare function move_cursor(key: "ArrowRight" | "ArrowLeft" | "ArrowDown" | "ArrowUp", current_coords: CellCoordinate, data: CellData[][]): CellCoordinate | false;
|
|
19
18
|
export declare function get_current_indices(id: string, data: CellData[][]): [number, number];
|
|
20
19
|
export declare function handle_click_outside(event: Event, parent: HTMLElement): boolean;
|
|
20
|
+
export declare function select_column(data: any[][], col: number): CellCoordinate[];
|
|
21
|
+
export declare function select_row(data: any[][], row: number): CellCoordinate[];
|
|
22
|
+
export declare function calculate_selection_positions(selected: CellCoordinate, data: {
|
|
23
|
+
id: string;
|
|
24
|
+
value: string | number;
|
|
25
|
+
}[][], els: Record<string, {
|
|
26
|
+
cell: HTMLTableCellElement | null;
|
|
27
|
+
}>, parent: HTMLElement, table: HTMLElement): {
|
|
28
|
+
col_pos: string;
|
|
29
|
+
row_pos: string | undefined;
|
|
30
|
+
};
|
|
@@ -28,11 +28,11 @@ export function handle_selection(current, selected_cells, event) {
|
|
|
28
28
|
return get_range_selection(selected_cells[selected_cells.length - 1], current);
|
|
29
29
|
}
|
|
30
30
|
if (event.metaKey || event.ctrlKey) {
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
31
|
+
const is_cell_match = ([r, c]) => r === current[0] && c === current[1];
|
|
32
|
+
const index = selected_cells.findIndex(is_cell_match);
|
|
33
|
+
return index === -1
|
|
34
|
+
? [...selected_cells, current]
|
|
35
|
+
: selected_cells.filter((_, i) => i !== index);
|
|
36
36
|
}
|
|
37
37
|
return [current];
|
|
38
38
|
}
|
|
@@ -109,3 +109,31 @@ export function handle_click_outside(event, parent) {
|
|
|
109
109
|
const [trigger] = event.composedPath();
|
|
110
110
|
return !parent.contains(trigger);
|
|
111
111
|
}
|
|
112
|
+
export function select_column(data, col) {
|
|
113
|
+
return Array.from({ length: data.length }, (_, i) => [i, col]);
|
|
114
|
+
}
|
|
115
|
+
export function select_row(data, row) {
|
|
116
|
+
return Array.from({ length: data[0].length }, (_, i) => [row, i]);
|
|
117
|
+
}
|
|
118
|
+
export function calculate_selection_positions(selected, data, els, parent, table) {
|
|
119
|
+
const [row, col] = selected;
|
|
120
|
+
if (!data[row]?.[col]) {
|
|
121
|
+
return { col_pos: "0px", row_pos: undefined };
|
|
122
|
+
}
|
|
123
|
+
let offset = 0;
|
|
124
|
+
for (let i = 0; i < col; i++) {
|
|
125
|
+
offset += parseFloat(getComputedStyle(parent).getPropertyValue(`--cell-width-${i}`));
|
|
126
|
+
}
|
|
127
|
+
const cell_id = data[row][col].id;
|
|
128
|
+
const cell_el = els[cell_id]?.cell;
|
|
129
|
+
if (!cell_el) {
|
|
130
|
+
// if we cant get the row position, just return the column position which is static
|
|
131
|
+
return { col_pos: "0px", row_pos: undefined };
|
|
132
|
+
}
|
|
133
|
+
const cell_rect = cell_el.getBoundingClientRect();
|
|
134
|
+
const table_rect = table.getBoundingClientRect();
|
|
135
|
+
const col_pos = `${cell_rect.left - table_rect.left + cell_rect.width / 2}px`;
|
|
136
|
+
const relative_top = cell_rect.top - table_rect.top;
|
|
137
|
+
const row_pos = `${relative_top + cell_rect.height / 2}px`;
|
|
138
|
+
return { col_pos, row_pos };
|
|
139
|
+
}
|
package/dist/shared/types.d.ts
CHANGED
|
@@ -1,2 +1,18 @@
|
|
|
1
1
|
export type CellCoordinate = [number, number];
|
|
2
2
|
export type EditingState = CellCoordinate | false;
|
|
3
|
+
export type Headers = (string | null)[];
|
|
4
|
+
export interface HeadersWithIDs {
|
|
5
|
+
id: string;
|
|
6
|
+
value: string;
|
|
7
|
+
}
|
|
8
|
+
export interface TableCell {
|
|
9
|
+
id: string;
|
|
10
|
+
value: string | number;
|
|
11
|
+
}
|
|
12
|
+
export type TableData = TableCell[][];
|
|
13
|
+
export type CountConfig = [number, "fixed" | "dynamic"];
|
|
14
|
+
export type ElementRefs = Record<string, {
|
|
15
|
+
cell: null | HTMLTableCellElement;
|
|
16
|
+
input: null | HTMLInputElement;
|
|
17
|
+
}>;
|
|
18
|
+
export type DataBinding = Record<string, TableCell>;
|
package/dist/shared/types.js
CHANGED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export declare function toggle_header_menu(event: MouseEvent, col: number, active_header_menu: {
|
|
2
|
+
col: number;
|
|
3
|
+
x: number;
|
|
4
|
+
y: number;
|
|
5
|
+
} | null, set_active_header_menu: (menu: {
|
|
6
|
+
col: number;
|
|
7
|
+
x: number;
|
|
8
|
+
y: number;
|
|
9
|
+
} | null) => void): void;
|
|
10
|
+
export declare function toggle_cell_menu(event: MouseEvent, row: number, col: number, active_cell_menu: {
|
|
11
|
+
row: number;
|
|
12
|
+
col: number;
|
|
13
|
+
x: number;
|
|
14
|
+
y: number;
|
|
15
|
+
} | null, set_active_cell_menu: (menu: {
|
|
16
|
+
row: number;
|
|
17
|
+
col: number;
|
|
18
|
+
x: number;
|
|
19
|
+
y: number;
|
|
20
|
+
} | null) => void): void;
|
|
21
|
+
export declare function add_row_at(index: number, position: "above" | "below", add_row: (index?: number) => void, clear_menus: () => void): void;
|
|
22
|
+
export declare function add_col_at(index: number, position: "left" | "right", add_col: (index?: number) => void, clear_menus: () => void): void;
|
|
23
|
+
export declare function delete_row_at(index: number, delete_row: (index: number) => void, clear_menus: () => void): void;
|
|
24
|
+
export declare function delete_col_at(index: number, delete_col: (index: number) => void, clear_menus: () => void): void;
|
|
25
|
+
export declare function toggle_header_button(col: number, active_button: {
|
|
26
|
+
type: "header" | "cell";
|
|
27
|
+
row?: number;
|
|
28
|
+
col: number;
|
|
29
|
+
} | null, set_active_button: (button: {
|
|
30
|
+
type: "header" | "cell";
|
|
31
|
+
row?: number;
|
|
32
|
+
col: number;
|
|
33
|
+
} | null) => void): void;
|
|
34
|
+
export declare function toggle_cell_button(row: number, col: number, active_button: {
|
|
35
|
+
type: "header" | "cell";
|
|
36
|
+
row?: number;
|
|
37
|
+
col: number;
|
|
38
|
+
} | null, set_active_button: (button: {
|
|
39
|
+
type: "header" | "cell";
|
|
40
|
+
row?: number;
|
|
41
|
+
col: number;
|
|
42
|
+
} | null) => void): void;
|