@gradio/dataframe 0.9.2 → 0.10.1-beta.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.9.2",
3
+ "version": "0.10.1-beta.1",
4
4
  "description": "Gradio UI packages",
5
5
  "type": "module",
6
6
  "author": "",
@@ -17,20 +17,36 @@
17
17
  "dompurify": "^3.0.3",
18
18
  "katex": "^0.16.7",
19
19
  "marked": "^12.0.0",
20
- "@gradio/button": "^0.2.49",
21
- "@gradio/atoms": "^0.7.9",
22
- "@gradio/client": "^1.5.0",
23
- "@gradio/statustracker": "^0.7.4",
24
- "@gradio/markdown": "^0.9.2",
25
- "@gradio/upload": "^0.12.2",
26
- "@gradio/utils": "^0.5.2"
20
+ "@gradio/atoms": "^0.8.1-beta.1",
21
+ "@gradio/client": "^1.6.0-beta.1",
22
+ "@gradio/markdown": "^0.9.4-beta.1",
23
+ "@gradio/statustracker": "^0.8.0-beta.1",
24
+ "@gradio/upload": "^0.12.4-beta.1",
25
+ "@gradio/button": "^0.3.0-beta.1",
26
+ "@gradio/utils": "^0.7.0-beta.1"
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.10.2"
45
+ "@gradio/preview": "^0.11.1-beta.0"
46
+ },
47
+ "repository": {
48
+ "type": "git",
49
+ "url": "git+https://github.com/gradio-app/gradio.git",
50
+ "directory": "js/dataframe"
35
51
  }
36
52
  }
@@ -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}
@@ -7,7 +7,7 @@
7
7
  import { BaseButton } from "@gradio/button";
8
8
  import EditableCell from "./EditableCell.svelte";
9
9
  import type { SelectData } from "@gradio/utils";
10
- import type { I18nFormatter } from "js/app/src/gradio_helper";
10
+ import type { I18nFormatter } from "js/core/src/gradio_helper";
11
11
  import { type Client } from "@gradio/client";
12
12
  import VirtualTable from "./VirtualTable.svelte";
13
13
  import type {
@@ -65,7 +65,11 @@
65
65
  if (selected !== false) {
66
66
  const [row, col] = selected;
67
67
  if (!isNaN(row) && !isNaN(col)) {
68
- dispatch("select", { index: [row, col], value: get_data_at(row, col) });
68
+ dispatch("select", {
69
+ index: [row, col],
70
+ value: get_data_at(row, col),
71
+ row_value: data[row].map((d) => d.value)
72
+ });
69
73
  }
70
74
  }
71
75
  }
@@ -559,7 +563,8 @@
559
563
  }
560
564
  }
561
565
 
562
- let table_height: number = height;
566
+ let table_height: number =
567
+ values.slice(0, (height / values.length) * 37).length * 37 + 37;
563
568
  let scrollbar_width = 0;
564
569
 
565
570
  function sort_data(
@@ -683,6 +688,7 @@
683
688
  header
684
689
  edit={false}
685
690
  el={null}
691
+ {root}
686
692
  />
687
693
 
688
694
  <div
@@ -717,6 +723,7 @@
717
723
  datatype={Array.isArray(datatype) ? datatype[j] : datatype}
718
724
  edit={false}
719
725
  el={null}
726
+ {root}
720
727
  />
721
728
  </div>
722
729
  </td>
@@ -763,6 +770,7 @@
763
770
  on:dblclick={() => edit_header(i)}
764
771
  {select_on_focus}
765
772
  header
773
+ {root}
766
774
  />
767
775
 
768
776
  <!-- TODO: fix -->
@@ -812,6 +820,7 @@
812
820
  datatype={Array.isArray(datatype) ? datatype[j] : datatype}
813
821
  on:blur={() => ((clear_on_focus = false), parent.focus())}
814
822
  {clear_on_focus}
823
+ {root}
815
824
  />
816
825
  </div>
817
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;