@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.
@@ -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.0",
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/button": "^0.2.50",
21
- "@gradio/atoms": "^0.8.0",
22
- "@gradio/client": "^1.5.1",
23
- "@gradio/statustracker": "^0.7.5",
24
- "@gradio/markdown": "^0.9.3",
25
- "@gradio/upload": "^0.12.3",
26
- "@gradio/utils": "^0.6.0"
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
- ".": "./Index.svelte",
30
- "./example": "./Example.svelte",
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.0"
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}
@@ -563,7 +563,8 @@
563
563
  }
564
564
  }
565
565
 
566
- let table_height: number = height;
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 = 0;
11
+ export let end = 20;
12
12
  export let selected: number | false;
13
13
  let height = "100%";
14
14
 
15
- let average_height: number;
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 = 0;
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 || 0;
29
+ $: viewport_height = viewport_box?.height || 200;
30
30
 
31
- $: if (mounted) requestAnimationFrame(() => refresh_height_map(sortedItems));
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
- requestAnimationFrame(async () => {
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 = sortedItems.slice(start, end).map((data, i) => {
236
- return { index: i + start, data };
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;