@gradio/dataframe 0.12.7 → 0.13.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 CHANGED
@@ -1,5 +1,26 @@
1
1
  # @gradio/dataframe
2
2
 
3
+ ## 0.13.0
4
+
5
+ ### Features
6
+
7
+ - [#10377](https://github.com/gradio-app/gradio/pull/10377) [`feb1e81`](https://github.com/gradio-app/gradio/commit/feb1e81ecabf34fd3f9ec228dcf3bdaa4b0bd75e) - Add toolbar with fullscreen button to `gr.Dataframe`. Thanks @hannahblair!
8
+ - [#10376](https://github.com/gradio-app/gradio/pull/10376) [`2b7ba48`](https://github.com/gradio-app/gradio/commit/2b7ba4801398b6dd6b72496ea50245a0cd6852d6) - Add `show_row_numbers` param to gr.Dataframe. Thanks @hannahblair!
9
+ - [#10410](https://github.com/gradio-app/gradio/pull/10410) [`48809c7`](https://github.com/gradio-app/gradio/commit/48809c722bcbb3aaed72edfdb6c59de5413fdbc4) - Fix bug where dataframe `value` prop was not updating when an input value was changed manually. Thanks @abidlabs!
10
+
11
+ ### Fixes
12
+
13
+ - [#10365](https://github.com/gradio-app/gradio/pull/10365) [`40e0c48`](https://github.com/gradio-app/gradio/commit/40e0c4832060cef457406896b2ad94639888897a) - Ensure clicking on a cell once enables editing mode. Thanks @hannahblair!
14
+ - [#10348](https://github.com/gradio-app/gradio/pull/10348) [`62cd4ef`](https://github.com/gradio-app/gradio/commit/62cd4ef302cd7529d1f8842b416f9d8fcf6b5750) - Handle `row_count=0` in gr.Dataframe. Thanks @hannahblair!
15
+ - [#10403](https://github.com/gradio-app/gradio/pull/10403) [`3219382`](https://github.com/gradio-app/gradio/commit/3219382eeea0a0047c74e0cdd2bf333e69f8f806) - Fix event triggers and recent regressions related to `gr.DataFrame`. Thanks @abidlabs!
16
+ - [#10360](https://github.com/gradio-app/gradio/pull/10360) [`31cccc3`](https://github.com/gradio-app/gradio/commit/31cccc3e79a3d1b4a840610d9becb235f8829b13) - Fix logic for detecting changes in `gr.Dataframe` table value. Thanks @abidlabs!
17
+
18
+ ### Dependency updates
19
+
20
+ - @gradio/upload@0.14.6
21
+ - @gradio/button@0.4.2
22
+ - @gradio/statustracker@0.10.2
23
+
3
24
  ## 0.12.7
4
25
 
5
26
  ### Dependency updates
@@ -166,6 +166,18 @@
166
166
  }}
167
167
  />
168
168
 
169
+ <Story
170
+ name="Dataframe with zero row count"
171
+ args={{
172
+ values: [],
173
+ headers: ["Narrow", "Wide", "Half"],
174
+ label: "Test scores",
175
+ col_count: [0, "dynamic"],
176
+ row_count: [0, "dynamic"],
177
+ editable: false
178
+ }}
179
+ />
180
+
169
181
  <Story
170
182
  name="Dataframe with dialog interactions"
171
183
  args={{
@@ -194,3 +206,17 @@
194
206
  userEvent.click(new_cell);
195
207
  }}
196
208
  />
209
+
210
+ <Story
211
+ name="Dataframe with fullscreen button"
212
+ args={{
213
+ col_count: [3, "dynamic"],
214
+ row_count: [2, "dynamic"],
215
+ headers: ["Math", "Reading", "Writing"],
216
+ values: [
217
+ [800, 100, 400],
218
+ [200, 800, 700]
219
+ ],
220
+ show_fullscreen_button: true
221
+ }}
222
+ />
@@ -0,0 +1,37 @@
1
+ import { test, describe, assert, afterEach, vi } from "vitest";
2
+ import { cleanup, render } from "@self/tootils";
3
+ import { setupi18n } from "../core/src/i18n";
4
+ import Dataframe from "./Index.svelte";
5
+
6
+ describe("Dataframe", () => {
7
+ beforeEach(setupi18n);
8
+ afterEach(() => {
9
+ cleanup();
10
+ });
11
+
12
+ test("changing value triggers change event", async () => {
13
+ await setupi18n();
14
+ const { component, listen } = await render(Dataframe, {
15
+ headers: ["A", "B", "C"],
16
+ values: [
17
+ ["1", "2", "3"],
18
+ ["4", "5", "6"]
19
+ ],
20
+ col_count: [3, "fixed"],
21
+ row_count: [2, "fixed"],
22
+ editable: true,
23
+ datatype: "str",
24
+ root: ""
25
+ });
26
+ const mock = listen("change");
27
+ component.value = {
28
+ data: [
29
+ ["11", "22", "33"],
30
+ ["44", "55", "66"]
31
+ ],
32
+ headers: ["A", "B", "C"],
33
+ metadata: null
34
+ };
35
+ assert.equal(mock.callCount, 1);
36
+ });
37
+ });
package/Index.svelte CHANGED
@@ -1,26 +1,26 @@
1
+ <svelte:options accessors={true} />
2
+
1
3
  <script context="module" lang="ts">
2
4
  export { default as BaseDataFrame } from "./shared/Table.svelte";
3
5
  export { default as BaseExample } from "./Example.svelte";
4
6
  </script>
5
7
 
6
8
  <script lang="ts">
7
- import { afterUpdate, tick } from "svelte";
8
9
  import type { Gradio, SelectData } from "@gradio/utils";
9
10
  import { Block } from "@gradio/atoms";
10
11
  import Table from "./shared/Table.svelte";
11
12
  import { StatusTracker } from "@gradio/statustracker";
12
13
  import type { LoadingStatus } from "@gradio/statustracker";
13
- import type { Headers, Data, Metadata, Datatype } from "./shared/utils";
14
+ import type { Headers, Datatype, DataframeValue } from "./shared/utils";
14
15
  export let headers: Headers = [];
15
16
  export let elem_id = "";
16
17
  export let elem_classes: string[] = [];
17
18
  export let visible = true;
18
- export let value: { data: Data; headers: Headers; metadata: Metadata } = {
19
+ export let value: DataframeValue = {
19
20
  data: [["", "", ""]],
20
21
  headers: ["1", "2", "3"],
21
22
  metadata: null
22
23
  };
23
- let old_value = "";
24
24
  export let value_is_output = false;
25
25
  export let col_count: [number, "fixed" | "dynamic"];
26
26
  export let row_count: [number, "fixed" | "dynamic"];
@@ -46,75 +46,19 @@
46
46
  display: boolean;
47
47
  }[];
48
48
  export let max_height: number | undefined = undefined;
49
-
50
49
  export let loading_status: LoadingStatus;
51
50
  export let interactive: boolean;
51
+ export let show_fullscreen_button = false;
52
52
 
53
- let _headers: Headers;
54
- let display_value: string[][] | null;
55
- let styling: string[][] | null;
56
- let values: (string | number)[][];
57
- async function handle_change(data?: {
58
- data: Data;
59
- headers: Headers;
60
- metadata: Metadata;
61
- }): Promise<void> {
62
- let _data = data || value;
63
-
64
- _headers = [...(_data.headers || headers)];
65
- values = _data.data ? [..._data.data] : [];
66
- display_value = _data?.metadata?.display_value
67
- ? [..._data?.metadata?.display_value]
53
+ $: _headers = [...(value.headers || headers)];
54
+ $: cell_values = value.data ? [...value.data] : [];
55
+ $: display_value = value?.metadata?.display_value
56
+ ? [...value?.metadata?.display_value]
57
+ : null;
58
+ $: styling =
59
+ !interactive && value?.metadata?.styling
60
+ ? [...value?.metadata?.styling]
68
61
  : null;
69
- styling =
70
- !interactive && _data?.metadata?.styling
71
- ? [..._data?.metadata?.styling]
72
- : null;
73
- await tick();
74
-
75
- gradio.dispatch("change");
76
- if (!value_is_output) {
77
- gradio.dispatch("input");
78
- }
79
- }
80
-
81
- handle_change();
82
-
83
- afterUpdate(() => {
84
- value_is_output = false;
85
- });
86
-
87
- $: {
88
- if (old_value && JSON.stringify(value) !== old_value) {
89
- old_value = JSON.stringify(value);
90
- handle_change();
91
- }
92
- }
93
-
94
- if (
95
- (Array.isArray(value) && value?.[0]?.length === 0) ||
96
- value.data?.[0]?.length === 0
97
- ) {
98
- value = {
99
- data: [Array(col_count?.[0] || 3).fill("")],
100
- headers: Array(col_count?.[0] || 3)
101
- .fill("")
102
- .map((_, i) => `${i + 1}`),
103
- metadata: null
104
- };
105
- }
106
-
107
- async function handle_value_change(data: {
108
- data: Data;
109
- headers: Headers;
110
- metadata: Metadata;
111
- }): Promise<void> {
112
- if (JSON.stringify(data) !== old_value) {
113
- value = { ...data };
114
- old_value = JSON.stringify(value);
115
- handle_change(data);
116
- }
117
- }
118
62
  </script>
119
63
 
120
64
  <Block
@@ -139,11 +83,15 @@
139
83
  {show_label}
140
84
  {row_count}
141
85
  {col_count}
142
- {values}
86
+ values={cell_values}
143
87
  {display_value}
144
88
  {styling}
145
89
  headers={_headers}
146
- on:change={(e) => handle_value_change(e.detail)}
90
+ on:change={(e) => {
91
+ value = e.detail;
92
+ gradio.dispatch("change");
93
+ }}
94
+ on:input={(e) => gradio.dispatch("input")}
147
95
  on:select={(e) => gradio.dispatch("select", e.detail)}
148
96
  {wrap}
149
97
  {datatype}
@@ -155,5 +103,7 @@
155
103
  {column_widths}
156
104
  upload={(...args) => gradio.client.upload(...args)}
157
105
  stream_handler={(...args) => gradio.client.stream(...args)}
106
+ bind:value_is_output
107
+ {show_fullscreen_button}
158
108
  />
159
109
  </Block>
package/dist/Index.svelte CHANGED
@@ -1,9 +1,10 @@
1
+ <svelte:options accessors={true} />
2
+
1
3
  <script context="module">export { default as BaseDataFrame } from "./shared/Table.svelte";
2
4
  export { default as BaseExample } from "./Example.svelte";
3
5
  </script>
4
6
 
5
- <script>import { afterUpdate, tick } from "svelte";
6
- import { Block } from "@gradio/atoms";
7
+ <script>import { Block } from "@gradio/atoms";
7
8
  import Table from "./shared/Table.svelte";
8
9
  import { StatusTracker } from "@gradio/statustracker";
9
10
  export let headers = [];
@@ -15,7 +16,6 @@ export let value = {
15
16
  headers: ["1", "2", "3"],
16
17
  metadata: null
17
18
  };
18
- let old_value = "";
19
19
  export let value_is_output = false;
20
20
  export let col_count;
21
21
  export let row_count;
@@ -33,46 +33,15 @@ export let latex_delimiters;
33
33
  export let max_height = void 0;
34
34
  export let loading_status;
35
35
  export let interactive;
36
- let _headers;
37
- let display_value;
38
- let styling;
39
- let values;
40
- async function handle_change(data) {
41
- let _data = data || value;
42
- _headers = [..._data.headers || headers];
43
- values = _data.data ? [..._data.data] : [];
44
- display_value = _data?.metadata?.display_value ? [..._data?.metadata?.display_value] : null;
45
- styling = !interactive && _data?.metadata?.styling ? [..._data?.metadata?.styling] : null;
46
- await tick();
47
- gradio.dispatch("change");
48
- if (!value_is_output) {
49
- gradio.dispatch("input");
50
- }
51
- }
52
- handle_change();
53
- afterUpdate(() => {
54
- value_is_output = false;
55
- });
56
- $: {
57
- if (old_value && JSON.stringify(value) !== old_value) {
58
- old_value = JSON.stringify(value);
59
- handle_change();
60
- }
61
- }
62
- if (Array.isArray(value) && value?.[0]?.length === 0 || value.data?.[0]?.length === 0) {
63
- value = {
64
- data: [Array(col_count?.[0] || 3).fill("")],
65
- headers: Array(col_count?.[0] || 3).fill("").map((_, i) => `${i + 1}`),
66
- metadata: null
67
- };
68
- }
69
- async function handle_value_change(data) {
70
- if (JSON.stringify(data) !== old_value) {
71
- value = { ...data };
72
- old_value = JSON.stringify(value);
73
- handle_change(data);
74
- }
75
- }
36
+ export let show_fullscreen_button = false;
37
+ $:
38
+ _headers = [...value.headers || headers];
39
+ $:
40
+ cell_values = value.data ? [...value.data] : [];
41
+ $:
42
+ display_value = value?.metadata?.display_value ? [...value?.metadata?.display_value] : null;
43
+ $:
44
+ styling = !interactive && value?.metadata?.styling ? [...value?.metadata?.styling] : null;
76
45
  </script>
77
46
 
78
47
  <Block
@@ -97,11 +66,15 @@ async function handle_value_change(data) {
97
66
  {show_label}
98
67
  {row_count}
99
68
  {col_count}
100
- {values}
69
+ values={cell_values}
101
70
  {display_value}
102
71
  {styling}
103
72
  headers={_headers}
104
- on:change={(e) => handle_value_change(e.detail)}
73
+ on:change={(e) => {
74
+ value = e.detail;
75
+ gradio.dispatch("change");
76
+ }}
77
+ on:input={(e) => gradio.dispatch("input")}
105
78
  on:select={(e) => gradio.dispatch("select", e.detail)}
106
79
  {wrap}
107
80
  {datatype}
@@ -113,5 +86,7 @@ async function handle_value_change(data) {
113
86
  {column_widths}
114
87
  upload={(...args) => gradio.client.upload(...args)}
115
88
  stream_handler={(...args) => gradio.client.stream(...args)}
89
+ bind:value_is_output
90
+ {show_fullscreen_button}
116
91
  />
117
92
  </Block>
@@ -3,18 +3,14 @@ export { default as BaseDataFrame } from "./shared/Table.svelte";
3
3
  export { default as BaseExample } from "./Example.svelte";
4
4
  import type { Gradio, SelectData } from "@gradio/utils";
5
5
  import type { LoadingStatus } from "@gradio/statustracker";
6
- import type { Headers, Data, Metadata, Datatype } from "./shared/utils";
6
+ import type { Headers, Datatype, DataframeValue } from "./shared/utils";
7
7
  declare const __propDef: {
8
8
  props: {
9
9
  headers?: Headers | undefined;
10
10
  elem_id?: string | undefined;
11
11
  elem_classes?: string[] | undefined;
12
12
  visible?: boolean | undefined;
13
- value?: {
14
- data: Data;
15
- headers: Headers;
16
- metadata: Metadata;
17
- } | undefined;
13
+ value?: DataframeValue | undefined;
18
14
  value_is_output?: boolean | undefined;
19
15
  col_count: [number, "fixed" | "dynamic"];
20
16
  row_count: [number, "fixed" | "dynamic"];
@@ -41,6 +37,7 @@ declare const __propDef: {
41
37
  max_height?: number | undefined;
42
38
  loading_status: LoadingStatus;
43
39
  interactive: boolean;
40
+ show_fullscreen_button?: boolean | undefined;
44
41
  };
45
42
  events: {
46
43
  [evt: string]: CustomEvent<any>;
@@ -51,4 +48,91 @@ export type IndexProps = typeof __propDef.props;
51
48
  export type IndexEvents = typeof __propDef.events;
52
49
  export type IndexSlots = typeof __propDef.slots;
53
50
  export default class Index extends SvelteComponent<IndexProps, IndexEvents, IndexSlots> {
51
+ get headers(): Headers | undefined;
52
+ /**accessor*/
53
+ set headers(_: Headers | undefined);
54
+ get elem_id(): string | undefined;
55
+ /**accessor*/
56
+ set elem_id(_: string | undefined);
57
+ get elem_classes(): string[] | undefined;
58
+ /**accessor*/
59
+ set elem_classes(_: string[] | undefined);
60
+ get visible(): boolean | undefined;
61
+ /**accessor*/
62
+ set visible(_: boolean | undefined);
63
+ get value(): DataframeValue | undefined;
64
+ /**accessor*/
65
+ set value(_: DataframeValue | undefined);
66
+ get value_is_output(): boolean | undefined;
67
+ /**accessor*/
68
+ set value_is_output(_: boolean | undefined);
69
+ get col_count(): [number, "fixed" | "dynamic"];
70
+ /**accessor*/
71
+ set col_count(_: [number, "fixed" | "dynamic"]);
72
+ get row_count(): [number, "fixed" | "dynamic"];
73
+ /**accessor*/
74
+ set row_count(_: [number, "fixed" | "dynamic"]);
75
+ get label(): string | null | undefined;
76
+ /**accessor*/
77
+ set label(_: string | null | undefined);
78
+ get show_label(): boolean | undefined;
79
+ /**accessor*/
80
+ set show_label(_: boolean | undefined);
81
+ get wrap(): boolean;
82
+ /**accessor*/
83
+ set wrap(_: boolean);
84
+ get datatype(): Datatype | Datatype[];
85
+ /**accessor*/
86
+ set datatype(_: Datatype | Datatype[]);
87
+ get scale(): number | null | undefined;
88
+ /**accessor*/
89
+ set scale(_: number | null | undefined);
90
+ get min_width(): number | undefined;
91
+ /**accessor*/
92
+ set min_width(_: number | undefined);
93
+ get root(): string;
94
+ /**accessor*/
95
+ set root(_: string);
96
+ get line_breaks(): boolean | undefined;
97
+ /**accessor*/
98
+ set line_breaks(_: boolean | undefined);
99
+ get column_widths(): string[] | undefined;
100
+ /**accessor*/
101
+ set column_widths(_: string[] | undefined);
102
+ get gradio(): Gradio<{
103
+ change: never;
104
+ select: SelectData;
105
+ input: never;
106
+ clear_status: LoadingStatus;
107
+ }>;
108
+ /**accessor*/
109
+ set gradio(_: Gradio<{
110
+ change: never;
111
+ select: SelectData;
112
+ input: never;
113
+ clear_status: LoadingStatus;
114
+ }>);
115
+ get latex_delimiters(): {
116
+ left: string;
117
+ right: string;
118
+ display: boolean;
119
+ }[];
120
+ /**accessor*/
121
+ set latex_delimiters(_: {
122
+ left: string;
123
+ right: string;
124
+ display: boolean;
125
+ }[]);
126
+ get max_height(): number | undefined;
127
+ /**accessor*/
128
+ set max_height(_: number | undefined);
129
+ get loading_status(): LoadingStatus;
130
+ /**accessor*/
131
+ set loading_status(_: LoadingStatus);
132
+ get interactive(): boolean;
133
+ /**accessor*/
134
+ set interactive(_: boolean);
135
+ get show_fullscreen_button(): boolean | undefined;
136
+ /**accessor*/
137
+ set show_fullscreen_button(_: boolean | undefined);
54
138
  }
@@ -8,7 +8,6 @@ export let header = false;
8
8
  export let datatype = "str";
9
9
  export let latex_delimiters;
10
10
  export let clear_on_focus = false;
11
- export let select_on_focus = false;
12
11
  export let line_breaks = true;
13
12
  export let editable = true;
14
13
  export let root;
@@ -20,10 +19,9 @@ function use_focus(node) {
20
19
  if (clear_on_focus) {
21
20
  _value = "";
22
21
  }
23
- if (select_on_focus) {
24
- node.select();
25
- }
26
- node.focus();
22
+ requestAnimationFrame(() => {
23
+ node.focus();
24
+ });
27
25
  return {};
28
26
  }
29
27
  function handle_blur({
@@ -49,6 +47,9 @@ function handle_keydown(event) {
49
47
  class:header
50
48
  tabindex="-1"
51
49
  on:blur={handle_blur}
50
+ on:mousedown|stopPropagation
51
+ on:mouseup|stopPropagation
52
+ on:click|stopPropagation
52
53
  use:use_focus
53
54
  on:keydown={handle_keydown}
54
55
  />
@@ -61,6 +62,8 @@ function handle_keydown(event) {
61
62
  class:edit
62
63
  on:focus|preventDefault
63
64
  style={styling}
65
+ class="table-cell-text"
66
+ placeholder=" "
64
67
  >
65
68
  {#if datatype === "html"}
66
69
  {@html value}
@@ -89,6 +92,7 @@ function handle_keydown(event) {
89
92
  outline: none;
90
93
  border: none;
91
94
  background: transparent;
95
+ cursor: text;
92
96
  }
93
97
 
94
98
  span {
@@ -99,11 +103,12 @@ function handle_keydown(event) {
99
103
  -moz-user-select: text;
100
104
  -ms-user-select: text;
101
105
  user-select: text;
106
+ cursor: text;
102
107
  }
103
108
 
104
109
  .header {
105
110
  transform: translateX(0);
106
- font: var(--weight-bold);
111
+ font-weight: var(--weight-bold);
107
112
  }
108
113
 
109
114
  .edit {
@@ -13,13 +13,15 @@ declare const __propDef: {
13
13
  display: boolean;
14
14
  }[];
15
15
  clear_on_focus?: boolean | undefined;
16
- select_on_focus?: boolean | undefined;
17
16
  line_breaks?: boolean | undefined;
18
17
  editable?: boolean | undefined;
19
18
  root: string;
20
19
  el: HTMLInputElement | null;
21
20
  };
22
21
  events: {
22
+ mousedown: MouseEvent;
23
+ mouseup: MouseEvent;
24
+ click: MouseEvent;
23
25
  dblclick: MouseEvent;
24
26
  focus: FocusEvent;
25
27
  blur: CustomEvent<any>;