@gradio/dataframe 0.10.0 → 0.10.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 +20 -0
- package/Index.svelte +4 -1
- package/dist/Example.svelte +104 -0
- package/dist/Example.svelte.d.ts +19 -0
- package/dist/Index.svelte +117 -0
- package/dist/Index.svelte.d.ts +54 -0
- package/dist/shared/EditableCell.svelte +106 -0
- package/dist/shared/EditableCell.svelte.d.ts +37 -0
- package/dist/shared/Example.svelte +28 -0
- package/dist/shared/Example.svelte.d.ts +16 -0
- package/dist/shared/Table.svelte +915 -0
- package/dist/shared/Table.svelte.d.ts +49 -0
- package/dist/shared/VirtualTable.svelte +294 -0
- package/dist/shared/VirtualTable.svelte.d.ts +31 -0
- package/dist/shared/utils.d.ts +10 -0
- package/dist/shared/utils.js +1 -0
- package/package.json +22 -11
- package/shared/EditableCell.svelte +2 -0
- package/shared/Table.svelte +6 -1
- package/shared/VirtualTable.svelte +23 -10
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { SvelteComponent } from "svelte";
|
|
2
|
+
import type { SelectData } from "@gradio/utils";
|
|
3
|
+
import type { I18nFormatter } from "js/core/src/gradio_helper";
|
|
4
|
+
import { type Client } from "@gradio/client";
|
|
5
|
+
import type { Headers, Metadata, Datatype } from "./utils";
|
|
6
|
+
declare const __propDef: {
|
|
7
|
+
props: {
|
|
8
|
+
datatype: Datatype | Datatype[];
|
|
9
|
+
label?: (string | null) | undefined;
|
|
10
|
+
show_label?: boolean | undefined;
|
|
11
|
+
headers?: Headers | undefined;
|
|
12
|
+
values?: (string | number)[][] | undefined;
|
|
13
|
+
col_count: [number, "fixed" | "dynamic"];
|
|
14
|
+
row_count: [number, "fixed" | "dynamic"];
|
|
15
|
+
latex_delimiters: {
|
|
16
|
+
left: string;
|
|
17
|
+
right: string;
|
|
18
|
+
display: boolean;
|
|
19
|
+
}[];
|
|
20
|
+
editable?: boolean | undefined;
|
|
21
|
+
wrap?: boolean | undefined;
|
|
22
|
+
root: string;
|
|
23
|
+
i18n: I18nFormatter;
|
|
24
|
+
height?: number | undefined;
|
|
25
|
+
line_breaks?: boolean | undefined;
|
|
26
|
+
column_widths?: string[] | undefined;
|
|
27
|
+
upload: Client["upload"];
|
|
28
|
+
stream_handler: Client["stream"];
|
|
29
|
+
display_value?: (string[][] | null) | undefined;
|
|
30
|
+
styling?: (string[][] | null) | undefined;
|
|
31
|
+
};
|
|
32
|
+
events: {
|
|
33
|
+
change: CustomEvent<{
|
|
34
|
+
data: (string | number)[][];
|
|
35
|
+
headers: string[];
|
|
36
|
+
metadata: Metadata;
|
|
37
|
+
}>;
|
|
38
|
+
select: CustomEvent<SelectData>;
|
|
39
|
+
} & {
|
|
40
|
+
[evt: string]: CustomEvent<any>;
|
|
41
|
+
};
|
|
42
|
+
slots: {};
|
|
43
|
+
};
|
|
44
|
+
export type TableProps = typeof __propDef.props;
|
|
45
|
+
export type TableEvents = typeof __propDef.events;
|
|
46
|
+
export type TableSlots = typeof __propDef.slots;
|
|
47
|
+
export default class Table extends SvelteComponent<TableProps, TableEvents, TableSlots> {
|
|
48
|
+
}
|
|
49
|
+
export {};
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
<script>import { onMount, tick } from "svelte";
|
|
2
|
+
import { _ } from "svelte-i18n";
|
|
3
|
+
export let items = [];
|
|
4
|
+
export let max_height;
|
|
5
|
+
export let actual_height;
|
|
6
|
+
export let table_scrollbar_width;
|
|
7
|
+
export let start = 0;
|
|
8
|
+
export let end = 20;
|
|
9
|
+
export let selected;
|
|
10
|
+
let height = "100%";
|
|
11
|
+
let average_height = 30;
|
|
12
|
+
let bottom = 0;
|
|
13
|
+
let contents;
|
|
14
|
+
let head_height = 0;
|
|
15
|
+
let foot_height = 0;
|
|
16
|
+
let height_map = [];
|
|
17
|
+
let mounted;
|
|
18
|
+
let rows;
|
|
19
|
+
let top = 0;
|
|
20
|
+
let viewport;
|
|
21
|
+
let viewport_height = 200;
|
|
22
|
+
let visible = [];
|
|
23
|
+
let viewport_box;
|
|
24
|
+
$:
|
|
25
|
+
viewport_height = viewport_box?.height || 200;
|
|
26
|
+
const is_browser = typeof window !== "undefined";
|
|
27
|
+
const raf = is_browser ? window.requestAnimationFrame : (cb) => cb();
|
|
28
|
+
$:
|
|
29
|
+
mounted && raf(() => refresh_height_map(sortedItems));
|
|
30
|
+
let content_height = 0;
|
|
31
|
+
async function refresh_height_map(_items) {
|
|
32
|
+
if (viewport_height === 0) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
const { scrollTop } = viewport;
|
|
36
|
+
table_scrollbar_width = viewport.offsetWidth - viewport.clientWidth;
|
|
37
|
+
content_height = top - (scrollTop - head_height);
|
|
38
|
+
let i = start;
|
|
39
|
+
while (content_height < max_height && i < _items.length) {
|
|
40
|
+
let row = rows[i - start];
|
|
41
|
+
if (!row) {
|
|
42
|
+
end = i + 1;
|
|
43
|
+
await tick();
|
|
44
|
+
row = rows[i - start];
|
|
45
|
+
}
|
|
46
|
+
let _h = row?.getBoundingClientRect().height;
|
|
47
|
+
if (!_h) {
|
|
48
|
+
_h = average_height;
|
|
49
|
+
}
|
|
50
|
+
const row_height = height_map[i] = _h;
|
|
51
|
+
content_height += row_height;
|
|
52
|
+
i += 1;
|
|
53
|
+
}
|
|
54
|
+
end = i;
|
|
55
|
+
const remaining = _items.length - end;
|
|
56
|
+
const scrollbar_height = viewport.offsetHeight - viewport.clientHeight;
|
|
57
|
+
if (scrollbar_height > 0) {
|
|
58
|
+
content_height += scrollbar_height;
|
|
59
|
+
}
|
|
60
|
+
let filtered_height_map = height_map.filter((v) => typeof v === "number");
|
|
61
|
+
average_height = filtered_height_map.reduce((a, b) => a + b, 0) / filtered_height_map.length;
|
|
62
|
+
bottom = remaining * average_height;
|
|
63
|
+
height_map.length = _items.length;
|
|
64
|
+
await tick();
|
|
65
|
+
if (!max_height) {
|
|
66
|
+
actual_height = content_height + 1;
|
|
67
|
+
} else if (content_height < max_height) {
|
|
68
|
+
actual_height = content_height + 2;
|
|
69
|
+
} else {
|
|
70
|
+
actual_height = max_height;
|
|
71
|
+
}
|
|
72
|
+
await tick();
|
|
73
|
+
}
|
|
74
|
+
$:
|
|
75
|
+
scroll_and_render(selected);
|
|
76
|
+
async function scroll_and_render(n) {
|
|
77
|
+
raf(async () => {
|
|
78
|
+
if (typeof n !== "number")
|
|
79
|
+
return;
|
|
80
|
+
const direction = typeof n !== "number" ? false : is_in_view(n);
|
|
81
|
+
if (direction === true) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
if (direction === "back") {
|
|
85
|
+
await scroll_to_index(n, { behavior: "instant" });
|
|
86
|
+
}
|
|
87
|
+
if (direction === "forwards") {
|
|
88
|
+
await scroll_to_index(n, { behavior: "instant" }, true);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
function is_in_view(n) {
|
|
93
|
+
const current = rows && rows[n - start];
|
|
94
|
+
if (!current && n < start) {
|
|
95
|
+
return "back";
|
|
96
|
+
}
|
|
97
|
+
if (!current && n >= end - 1) {
|
|
98
|
+
return "forwards";
|
|
99
|
+
}
|
|
100
|
+
const { top: viewport_top } = viewport.getBoundingClientRect();
|
|
101
|
+
const { top: top2, bottom: bottom2 } = current.getBoundingClientRect();
|
|
102
|
+
if (top2 - viewport_top < 37) {
|
|
103
|
+
return "back";
|
|
104
|
+
}
|
|
105
|
+
if (bottom2 - viewport_top > viewport_height) {
|
|
106
|
+
return "forwards";
|
|
107
|
+
}
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
function get_computed_px_amount(elem, property) {
|
|
111
|
+
if (!elem) {
|
|
112
|
+
return 0;
|
|
113
|
+
}
|
|
114
|
+
const compStyle = getComputedStyle(elem);
|
|
115
|
+
let x = parseInt(compStyle.getPropertyValue(property));
|
|
116
|
+
return x;
|
|
117
|
+
}
|
|
118
|
+
async function handle_scroll(e) {
|
|
119
|
+
const scroll_top = viewport.scrollTop;
|
|
120
|
+
rows = contents.children;
|
|
121
|
+
const is_start_overflow = sortedItems.length < start;
|
|
122
|
+
const row_top_border = get_computed_px_amount(rows[1], "border-top-width");
|
|
123
|
+
const actual_border_collapsed_width = 0;
|
|
124
|
+
if (is_start_overflow) {
|
|
125
|
+
await scroll_to_index(sortedItems.length - 1, { behavior: "auto" });
|
|
126
|
+
}
|
|
127
|
+
let new_start = 0;
|
|
128
|
+
for (let v = 0; v < rows.length; v += 1) {
|
|
129
|
+
height_map[start + v] = rows[v].getBoundingClientRect().height;
|
|
130
|
+
}
|
|
131
|
+
let i = 0;
|
|
132
|
+
let y = head_height + row_top_border / 2;
|
|
133
|
+
let row_heights = [];
|
|
134
|
+
while (i < sortedItems.length) {
|
|
135
|
+
const row_height = height_map[i] || average_height;
|
|
136
|
+
row_heights[i] = row_height;
|
|
137
|
+
if (y + row_height + actual_border_collapsed_width > scroll_top) {
|
|
138
|
+
new_start = i;
|
|
139
|
+
top = y - (head_height + row_top_border / 2);
|
|
140
|
+
break;
|
|
141
|
+
}
|
|
142
|
+
y += row_height;
|
|
143
|
+
i += 1;
|
|
144
|
+
}
|
|
145
|
+
new_start = Math.max(0, new_start);
|
|
146
|
+
while (i < sortedItems.length) {
|
|
147
|
+
const row_height = height_map[i] || average_height;
|
|
148
|
+
y += row_height;
|
|
149
|
+
i += 1;
|
|
150
|
+
if (y > scroll_top + viewport_height) {
|
|
151
|
+
break;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
start = new_start;
|
|
155
|
+
end = i;
|
|
156
|
+
const remaining = sortedItems.length - end;
|
|
157
|
+
if (end === 0) {
|
|
158
|
+
end = 10;
|
|
159
|
+
}
|
|
160
|
+
average_height = (y - head_height) / end;
|
|
161
|
+
let remaining_height = remaining * average_height;
|
|
162
|
+
while (i < sortedItems.length) {
|
|
163
|
+
i += 1;
|
|
164
|
+
height_map[i] = average_height;
|
|
165
|
+
}
|
|
166
|
+
bottom = remaining_height;
|
|
167
|
+
if (!isFinite(bottom)) {
|
|
168
|
+
bottom = 2e5;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
export async function scroll_to_index(index, opts, align_end = false) {
|
|
172
|
+
await tick();
|
|
173
|
+
const _itemHeight = average_height;
|
|
174
|
+
let distance = index * _itemHeight;
|
|
175
|
+
if (align_end) {
|
|
176
|
+
distance = distance - viewport_height + _itemHeight + head_height;
|
|
177
|
+
}
|
|
178
|
+
const scrollbar_height = viewport.offsetHeight - viewport.clientHeight;
|
|
179
|
+
if (scrollbar_height > 0) {
|
|
180
|
+
distance += scrollbar_height;
|
|
181
|
+
}
|
|
182
|
+
const _opts = {
|
|
183
|
+
top: distance,
|
|
184
|
+
behavior: "smooth",
|
|
185
|
+
...opts
|
|
186
|
+
};
|
|
187
|
+
viewport.scrollTo(_opts);
|
|
188
|
+
}
|
|
189
|
+
$:
|
|
190
|
+
sortedItems = items;
|
|
191
|
+
$:
|
|
192
|
+
visible = is_browser ? sortedItems.slice(start, end).map((data, i) => {
|
|
193
|
+
return { index: i + start, data };
|
|
194
|
+
}) : sortedItems.slice(0, max_height / sortedItems.length * average_height + 1).map((data, i) => {
|
|
195
|
+
return { index: i + start, data };
|
|
196
|
+
});
|
|
197
|
+
$:
|
|
198
|
+
actual_height = visible.length * average_height + 10;
|
|
199
|
+
onMount(() => {
|
|
200
|
+
rows = contents.children;
|
|
201
|
+
mounted = true;
|
|
202
|
+
refresh_height_map(items);
|
|
203
|
+
});
|
|
204
|
+
</script>
|
|
205
|
+
|
|
206
|
+
<svelte-virtual-table-viewport>
|
|
207
|
+
<table
|
|
208
|
+
class="table"
|
|
209
|
+
bind:this={viewport}
|
|
210
|
+
bind:contentRect={viewport_box}
|
|
211
|
+
on:scroll={handle_scroll}
|
|
212
|
+
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"
|
|
213
|
+
>
|
|
214
|
+
<thead class="thead" bind:offsetHeight={head_height}>
|
|
215
|
+
<slot name="thead" />
|
|
216
|
+
</thead>
|
|
217
|
+
<tbody bind:this={contents} class="tbody">
|
|
218
|
+
{#if visible.length && visible[0].data.length}
|
|
219
|
+
{#each visible as item (item.data[0].id)}
|
|
220
|
+
<slot name="tbody" item={item.data} index={item.index}>
|
|
221
|
+
Missing Table Row
|
|
222
|
+
</slot>
|
|
223
|
+
{/each}
|
|
224
|
+
{/if}
|
|
225
|
+
</tbody>
|
|
226
|
+
<tfoot class="tfoot" bind:offsetHeight={foot_height}>
|
|
227
|
+
<slot name="tfoot" />
|
|
228
|
+
</tfoot>
|
|
229
|
+
</table>
|
|
230
|
+
</svelte-virtual-table-viewport>
|
|
231
|
+
|
|
232
|
+
<style>
|
|
233
|
+
table {
|
|
234
|
+
position: relative;
|
|
235
|
+
overflow-y: scroll;
|
|
236
|
+
overflow-x: scroll;
|
|
237
|
+
-webkit-overflow-scrolling: touch;
|
|
238
|
+
max-height: 100vh;
|
|
239
|
+
box-sizing: border-box;
|
|
240
|
+
display: block;
|
|
241
|
+
padding: 0;
|
|
242
|
+
margin: 0;
|
|
243
|
+
color: var(--body-text-color);
|
|
244
|
+
font-size: var(--input-text-size);
|
|
245
|
+
line-height: var(--line-md);
|
|
246
|
+
font-family: var(--font-mono);
|
|
247
|
+
border-spacing: 0;
|
|
248
|
+
width: 100%;
|
|
249
|
+
scroll-snap-type: x proximity;
|
|
250
|
+
border-collapse: separate;
|
|
251
|
+
}
|
|
252
|
+
table :is(thead, tfoot, tbody) {
|
|
253
|
+
display: table;
|
|
254
|
+
table-layout: fixed;
|
|
255
|
+
width: 100%;
|
|
256
|
+
box-sizing: border-box;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
tbody {
|
|
260
|
+
overflow-x: scroll;
|
|
261
|
+
overflow-y: hidden;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
table tbody {
|
|
265
|
+
padding-top: var(--bw-svt-p-top);
|
|
266
|
+
padding-bottom: var(--bw-svt-p-bottom);
|
|
267
|
+
}
|
|
268
|
+
tbody {
|
|
269
|
+
position: relative;
|
|
270
|
+
box-sizing: border-box;
|
|
271
|
+
border: 0px solid currentColor;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
tbody > :global(tr:last-child) {
|
|
275
|
+
border: none;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
table :global(td) {
|
|
279
|
+
scroll-snap-align: start;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
tbody > :global(tr:nth-child(even)) {
|
|
283
|
+
background: var(--table-even-background-fill);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
thead {
|
|
287
|
+
position: sticky;
|
|
288
|
+
top: 0;
|
|
289
|
+
left: 0;
|
|
290
|
+
z-index: var(--layer-1);
|
|
291
|
+
box-shadow: var(--shadow-drop);
|
|
292
|
+
overflow: hidden;
|
|
293
|
+
}
|
|
294
|
+
</style>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { SvelteComponent } from "svelte";
|
|
2
|
+
declare const __propDef: {
|
|
3
|
+
props: {
|
|
4
|
+
items?: any[][] | undefined;
|
|
5
|
+
max_height: number;
|
|
6
|
+
actual_height: number;
|
|
7
|
+
table_scrollbar_width: number;
|
|
8
|
+
start?: number | undefined;
|
|
9
|
+
end?: number | undefined;
|
|
10
|
+
selected: number | false;
|
|
11
|
+
scroll_to_index?: ((index: number, opts: ScrollToOptions, align_end?: boolean) => Promise<void>) | undefined;
|
|
12
|
+
};
|
|
13
|
+
events: {
|
|
14
|
+
[evt: string]: CustomEvent<any>;
|
|
15
|
+
};
|
|
16
|
+
slots: {
|
|
17
|
+
thead: {};
|
|
18
|
+
tbody: {
|
|
19
|
+
item: any[];
|
|
20
|
+
index: number;
|
|
21
|
+
};
|
|
22
|
+
tfoot: {};
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
export type VirtualTableProps = typeof __propDef.props;
|
|
26
|
+
export type VirtualTableEvents = typeof __propDef.events;
|
|
27
|
+
export type VirtualTableSlots = typeof __propDef.slots;
|
|
28
|
+
export default class VirtualTable extends SvelteComponent<VirtualTableProps, VirtualTableEvents, VirtualTableSlots> {
|
|
29
|
+
get scroll_to_index(): (index: number, opts: ScrollToOptions, align_end?: boolean) => Promise<void>;
|
|
30
|
+
}
|
|
31
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type Headers = string[];
|
|
2
|
+
export type Data = (string | number)[][];
|
|
3
|
+
export type Datatype = "str" | "markdown" | "html" | "number" | "bool" | "date";
|
|
4
|
+
export type Metadata = {
|
|
5
|
+
[key: string]: string[][] | null;
|
|
6
|
+
} | null;
|
|
7
|
+
export type HeadersWithIDs = {
|
|
8
|
+
value: string;
|
|
9
|
+
id: string;
|
|
10
|
+
}[];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gradio/dataframe",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.1",
|
|
4
4
|
"description": "Gradio UI packages",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "",
|
|
@@ -17,21 +17,32 @@
|
|
|
17
17
|
"dompurify": "^3.0.3",
|
|
18
18
|
"katex": "^0.16.7",
|
|
19
19
|
"marked": "^12.0.0",
|
|
20
|
-
"@gradio/
|
|
21
|
-
"@gradio/
|
|
22
|
-
"@gradio/client": "^1.5.
|
|
23
|
-
"@gradio/
|
|
24
|
-
"@gradio/
|
|
25
|
-
"@gradio/
|
|
26
|
-
"@gradio/
|
|
20
|
+
"@gradio/atoms": "^0.8.1",
|
|
21
|
+
"@gradio/button": "^0.2.51",
|
|
22
|
+
"@gradio/client": "^1.5.2",
|
|
23
|
+
"@gradio/markdown": "^0.9.4",
|
|
24
|
+
"@gradio/statustracker": "^0.7.6",
|
|
25
|
+
"@gradio/utils": "^0.6.1",
|
|
26
|
+
"@gradio/upload": "^0.12.4"
|
|
27
27
|
},
|
|
28
28
|
"exports": {
|
|
29
|
-
".":
|
|
30
|
-
|
|
29
|
+
".": {
|
|
30
|
+
"gradio": "./Index.svelte",
|
|
31
|
+
"svelte": "./dist/Index.svelte",
|
|
32
|
+
"types": "./dist/Index.svelte.d.ts"
|
|
33
|
+
},
|
|
34
|
+
"./example": {
|
|
35
|
+
"gradio": "./Example.svelte",
|
|
36
|
+
"svelte": "./dist/Example.svelte",
|
|
37
|
+
"types": "./dist/Example.svelte.d.ts"
|
|
38
|
+
},
|
|
31
39
|
"./package.json": "./package.json"
|
|
32
40
|
},
|
|
41
|
+
"peerDependencies": {
|
|
42
|
+
"svelte": "^4.0.0"
|
|
43
|
+
},
|
|
33
44
|
"devDependencies": {
|
|
34
|
-
"@gradio/preview": "^0.11.
|
|
45
|
+
"@gradio/preview": "^0.11.1"
|
|
35
46
|
},
|
|
36
47
|
"repository": {
|
|
37
48
|
"type": "git",
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
export let select_on_focus = false;
|
|
24
24
|
export let line_breaks = true;
|
|
25
25
|
export let editable = true;
|
|
26
|
+
export let root: string;
|
|
26
27
|
|
|
27
28
|
const dispatch = createEventDispatcher();
|
|
28
29
|
|
|
@@ -81,6 +82,7 @@
|
|
|
81
82
|
{latex_delimiters}
|
|
82
83
|
{line_breaks}
|
|
83
84
|
chatbot={false}
|
|
85
|
+
{root}
|
|
84
86
|
/>
|
|
85
87
|
{:else}
|
|
86
88
|
{editable ? value : display_value || value}
|
package/shared/Table.svelte
CHANGED
|
@@ -563,7 +563,8 @@
|
|
|
563
563
|
}
|
|
564
564
|
}
|
|
565
565
|
|
|
566
|
-
let table_height: number =
|
|
566
|
+
let table_height: number =
|
|
567
|
+
values.slice(0, (height / values.length) * 37).length * 37 + 37;
|
|
567
568
|
let scrollbar_width = 0;
|
|
568
569
|
|
|
569
570
|
function sort_data(
|
|
@@ -687,6 +688,7 @@
|
|
|
687
688
|
header
|
|
688
689
|
edit={false}
|
|
689
690
|
el={null}
|
|
691
|
+
{root}
|
|
690
692
|
/>
|
|
691
693
|
|
|
692
694
|
<div
|
|
@@ -721,6 +723,7 @@
|
|
|
721
723
|
datatype={Array.isArray(datatype) ? datatype[j] : datatype}
|
|
722
724
|
edit={false}
|
|
723
725
|
el={null}
|
|
726
|
+
{root}
|
|
724
727
|
/>
|
|
725
728
|
</div>
|
|
726
729
|
</td>
|
|
@@ -767,6 +770,7 @@
|
|
|
767
770
|
on:dblclick={() => edit_header(i)}
|
|
768
771
|
{select_on_focus}
|
|
769
772
|
header
|
|
773
|
+
{root}
|
|
770
774
|
/>
|
|
771
775
|
|
|
772
776
|
<!-- TODO: fix -->
|
|
@@ -816,6 +820,7 @@
|
|
|
816
820
|
datatype={Array.isArray(datatype) ? datatype[j] : datatype}
|
|
817
821
|
on:blur={() => ((clear_on_focus = false), parent.focus())}
|
|
818
822
|
{clear_on_focus}
|
|
823
|
+
{root}
|
|
819
824
|
/>
|
|
820
825
|
</div>
|
|
821
826
|
</td>
|
|
@@ -8,11 +8,11 @@
|
|
|
8
8
|
export let actual_height: number;
|
|
9
9
|
export let table_scrollbar_width: number;
|
|
10
10
|
export let start = 0;
|
|
11
|
-
export let end =
|
|
11
|
+
export let end = 20;
|
|
12
12
|
export let selected: number | false;
|
|
13
13
|
let height = "100%";
|
|
14
14
|
|
|
15
|
-
let average_height
|
|
15
|
+
let average_height = 30;
|
|
16
16
|
let bottom = 0;
|
|
17
17
|
let contents: HTMLTableSectionElement;
|
|
18
18
|
let head_height = 0;
|
|
@@ -22,19 +22,25 @@
|
|
|
22
22
|
let rows: HTMLCollectionOf<HTMLTableRowElement>;
|
|
23
23
|
let top = 0;
|
|
24
24
|
let viewport: HTMLTableElement;
|
|
25
|
-
let viewport_height =
|
|
25
|
+
let viewport_height = 200;
|
|
26
26
|
let visible: { index: number; data: any[] }[] = [];
|
|
27
27
|
let viewport_box: DOMRectReadOnly;
|
|
28
28
|
|
|
29
|
-
$: viewport_height = viewport_box?.height ||
|
|
29
|
+
$: viewport_height = viewport_box?.height || 200;
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
const is_browser = typeof window !== "undefined";
|
|
32
|
+
const raf = is_browser
|
|
33
|
+
? window.requestAnimationFrame
|
|
34
|
+
: (cb: (...args: any[]) => void) => cb();
|
|
35
|
+
|
|
36
|
+
$: mounted && raf(() => refresh_height_map(sortedItems));
|
|
32
37
|
|
|
33
38
|
let content_height = 0;
|
|
34
39
|
async function refresh_height_map(_items: typeof items): Promise<void> {
|
|
35
40
|
if (viewport_height === 0) {
|
|
36
41
|
return;
|
|
37
42
|
}
|
|
43
|
+
|
|
38
44
|
const { scrollTop } = viewport;
|
|
39
45
|
table_scrollbar_width = viewport.offsetWidth - viewport.clientWidth;
|
|
40
46
|
|
|
@@ -87,7 +93,7 @@
|
|
|
87
93
|
$: scroll_and_render(selected);
|
|
88
94
|
|
|
89
95
|
async function scroll_and_render(n: number | false): Promise<void> {
|
|
90
|
-
|
|
96
|
+
raf(async () => {
|
|
91
97
|
if (typeof n !== "number") return;
|
|
92
98
|
const direction = typeof n !== "number" ? false : is_in_view(n);
|
|
93
99
|
if (direction === true) {
|
|
@@ -232,10 +238,17 @@
|
|
|
232
238
|
|
|
233
239
|
$: sortedItems = items;
|
|
234
240
|
|
|
235
|
-
$: visible =
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
241
|
+
$: visible = is_browser
|
|
242
|
+
? sortedItems.slice(start, end).map((data, i) => {
|
|
243
|
+
return { index: i + start, data };
|
|
244
|
+
})
|
|
245
|
+
: sortedItems
|
|
246
|
+
.slice(0, (max_height / sortedItems.length) * average_height + 1)
|
|
247
|
+
.map((data, i) => {
|
|
248
|
+
return { index: i + start, data };
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
$: actual_height = visible.length * average_height + 10;
|
|
239
252
|
onMount(() => {
|
|
240
253
|
rows = contents.children as HTMLCollectionOf<HTMLTableRowElement>;
|
|
241
254
|
mounted = true;
|