@gradio/tabs 0.5.9 → 0.5.11
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 +12 -0
- package/Index.svelte +9 -7
- package/dist/Index.svelte +9 -7
- package/dist/shared/Tabs.svelte +37 -36
- package/package.json +1 -1
- package/shared/Tabs.svelte +37 -36
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @gradio/tabs
|
|
2
2
|
|
|
3
|
+
## 0.5.11
|
|
4
|
+
|
|
5
|
+
### Fixes
|
|
6
|
+
|
|
7
|
+
- [#13240](https://github.com/gradio-app/gradio/pull/13240) [`0d670ad`](https://github.com/gradio-app/gradio/commit/0d670adf41a0b510f7fd745495dce1664d38f0e5) - Fix browser freeze when a dataframe's value is set (e.g. via a tab select event), and only dispatch the tabs select event when the selected tab actually changes. Thanks @freddyaboulton!
|
|
8
|
+
|
|
9
|
+
## 0.5.10
|
|
10
|
+
|
|
11
|
+
### Fixes
|
|
12
|
+
|
|
13
|
+
- [#13303](https://github.com/gradio-app/gradio/pull/13303) [`79c5776`](https://github.com/gradio-app/gradio/commit/79c577680978adfb5eeaa01944635e14dc67e5f1) - Rework `Dataframe` wrapping, truncation, and column width sizing. Thanks @pngwn!
|
|
14
|
+
|
|
3
15
|
## 0.5.9
|
|
4
16
|
|
|
5
17
|
### Fixes
|
package/Index.svelte
CHANGED
|
@@ -7,24 +7,26 @@
|
|
|
7
7
|
import Tabs from "./shared/Tabs.svelte";
|
|
8
8
|
import Walkthrough from "./shared/Walkthrough.svelte";
|
|
9
9
|
import type { TabsProps, TabsEvents } from "./types";
|
|
10
|
-
import { untrack } from "svelte";
|
|
11
10
|
|
|
12
11
|
let props = $props();
|
|
13
12
|
const gradio = new Gradio<TabsEvents, TabsProps>(props);
|
|
14
13
|
|
|
14
|
+
let old_selected = gradio.props.selected;
|
|
15
|
+
|
|
15
16
|
$effect(() => {
|
|
16
|
-
if (gradio.props.selected) {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
if (old_selected !== gradio.props.selected) {
|
|
18
|
+
const i = gradio.props.initial_tabs.findIndex(
|
|
19
|
+
(t) => t.id === gradio.props.selected
|
|
20
|
+
);
|
|
21
|
+
if (i >= 0) {
|
|
21
22
|
gradio.dispatch("gradio_tab_select", {
|
|
22
23
|
value: gradio.props.initial_tabs[i].label,
|
|
23
24
|
index: i,
|
|
24
25
|
id: gradio.props.initial_tabs[i].id,
|
|
25
26
|
component_id: gradio.props.initial_tabs[i].component_id
|
|
26
27
|
});
|
|
27
|
-
}
|
|
28
|
+
}
|
|
29
|
+
old_selected = gradio.props.selected;
|
|
28
30
|
}
|
|
29
31
|
});
|
|
30
32
|
</script>
|
package/dist/Index.svelte
CHANGED
|
@@ -7,24 +7,26 @@
|
|
|
7
7
|
import Tabs from "./shared/Tabs.svelte";
|
|
8
8
|
import Walkthrough from "./shared/Walkthrough.svelte";
|
|
9
9
|
import type { TabsProps, TabsEvents } from "./types";
|
|
10
|
-
import { untrack } from "svelte";
|
|
11
10
|
|
|
12
11
|
let props = $props();
|
|
13
12
|
const gradio = new Gradio<TabsEvents, TabsProps>(props);
|
|
14
13
|
|
|
14
|
+
let old_selected = gradio.props.selected;
|
|
15
|
+
|
|
15
16
|
$effect(() => {
|
|
16
|
-
if (gradio.props.selected) {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
if (old_selected !== gradio.props.selected) {
|
|
18
|
+
const i = gradio.props.initial_tabs.findIndex(
|
|
19
|
+
(t) => t.id === gradio.props.selected
|
|
20
|
+
);
|
|
21
|
+
if (i >= 0) {
|
|
21
22
|
gradio.dispatch("gradio_tab_select", {
|
|
22
23
|
value: gradio.props.initial_tabs[i].label,
|
|
23
24
|
index: i,
|
|
24
25
|
id: gradio.props.initial_tabs[i].id,
|
|
25
26
|
component_id: gradio.props.initial_tabs[i].component_id
|
|
26
27
|
});
|
|
27
|
-
}
|
|
28
|
+
}
|
|
29
|
+
old_selected = gradio.props.selected;
|
|
28
30
|
}
|
|
29
31
|
});
|
|
30
32
|
</script>
|
package/dist/shared/Tabs.svelte
CHANGED
|
@@ -37,16 +37,20 @@
|
|
|
37
37
|
|
|
38
38
|
// When initial_tabs changes (e.g. a non-mounted tab's props were updated),
|
|
39
39
|
// sync the internal tabs array so the tab buttons reflect the new state.
|
|
40
|
-
//
|
|
41
|
-
//
|
|
40
|
+
// The tabs mutation is deferred via tick() because in Svelte 5 legacy mode
|
|
41
|
+
// $: effects track all reads inside called functions — writing tabs[i]
|
|
42
|
+
// through the $state proxy would track `tabs` as a dependency, creating
|
|
43
|
+
// an infinite self-triggering loop.
|
|
42
44
|
$: _sync_tabs(initial_tabs);
|
|
43
45
|
|
|
44
46
|
function _sync_tabs(new_tabs: Tab[]): void {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
47
|
+
tick().then(() => {
|
|
48
|
+
for (let i = 0; i < new_tabs.length; i++) {
|
|
49
|
+
if (new_tabs[i] && !mounted_tab_orders.has(i)) {
|
|
50
|
+
tabs[i] = new_tabs[i];
|
|
51
|
+
}
|
|
48
52
|
}
|
|
49
|
-
}
|
|
53
|
+
});
|
|
50
54
|
}
|
|
51
55
|
|
|
52
56
|
$: has_tabs = tabs.length > 0;
|
|
@@ -70,10 +74,11 @@
|
|
|
70
74
|
|
|
71
75
|
onMount(() => {
|
|
72
76
|
if (!tab_nav_el) return;
|
|
73
|
-
const
|
|
77
|
+
const ro = new ResizeObserver(() => {
|
|
74
78
|
handle_menu_overflow();
|
|
75
79
|
});
|
|
76
|
-
|
|
80
|
+
ro.observe(tab_nav_el);
|
|
81
|
+
return () => ro.disconnect();
|
|
77
82
|
});
|
|
78
83
|
|
|
79
84
|
setContext(TABS, {
|
|
@@ -128,33 +133,42 @@
|
|
|
128
133
|
}
|
|
129
134
|
}
|
|
130
135
|
|
|
136
|
+
// approximate width of the "..." overflow button including margin
|
|
137
|
+
const OVERFLOW_BTN_RESERVE = 48;
|
|
138
|
+
|
|
131
139
|
async function handle_menu_overflow(): Promise<void> {
|
|
132
140
|
if (!tab_nav_el) return;
|
|
133
141
|
|
|
134
142
|
await tick();
|
|
135
|
-
|
|
143
|
+
await new Promise((r) => requestAnimationFrame(r));
|
|
144
|
+
|
|
145
|
+
const available = tab_nav_el.clientWidth;
|
|
136
146
|
|
|
137
|
-
let
|
|
138
|
-
|
|
139
|
-
let last_visible_index = 0;
|
|
140
|
-
const offset = tab_nav_size.left;
|
|
147
|
+
let cumulative = 0;
|
|
148
|
+
let split_index = tabs.length;
|
|
141
149
|
|
|
142
|
-
for (let i =
|
|
150
|
+
for (let i = 0; i < tabs.length; i++) {
|
|
143
151
|
const tab = tabs[i];
|
|
144
|
-
if (!tab) continue;
|
|
145
|
-
const
|
|
146
|
-
if (!
|
|
147
|
-
|
|
148
|
-
|
|
152
|
+
if (!tab || tab.visible === false || tab.visible === "hidden") continue;
|
|
153
|
+
const el = tab_els[tab.id];
|
|
154
|
+
if (!el) continue;
|
|
155
|
+
cumulative += el.getBoundingClientRect().width;
|
|
156
|
+
const has_more = tabs
|
|
157
|
+
.slice(i + 1)
|
|
158
|
+
.some((t) => t && t.visible !== false && t.visible !== "hidden");
|
|
159
|
+
const limit = has_more ? available - OVERFLOW_BTN_RESERVE : available;
|
|
160
|
+
if (cumulative > limit) {
|
|
161
|
+
split_index = i;
|
|
149
162
|
break;
|
|
150
163
|
}
|
|
151
164
|
}
|
|
152
165
|
|
|
153
|
-
|
|
154
|
-
|
|
166
|
+
visible_tabs = tabs.slice(0, split_index);
|
|
167
|
+
overflow_tabs = tabs.slice(split_index);
|
|
155
168
|
|
|
156
169
|
overflow_has_selected_tab = handle_overflow_has_selected_tab($selected_tab);
|
|
157
|
-
is_overflowing =
|
|
170
|
+
is_overflowing =
|
|
171
|
+
overflow_tabs.filter((t) => t && t.visible !== false).length > 0;
|
|
158
172
|
}
|
|
159
173
|
|
|
160
174
|
$: overflow_has_selected_tab =
|
|
@@ -167,18 +181,6 @@
|
|
|
167
181
|
return overflow_tabs.some((t) => t?.id === selected_tab);
|
|
168
182
|
}
|
|
169
183
|
|
|
170
|
-
function get_tab_sizes(
|
|
171
|
-
tabs: (Tab | null)[],
|
|
172
|
-
tab_els: Record<string | number, HTMLElement>
|
|
173
|
-
): Record<string | number, DOMRect> {
|
|
174
|
-
const tab_sizes: Record<string | number, DOMRect> = {};
|
|
175
|
-
tabs.forEach((tab) => {
|
|
176
|
-
if (!tab) return;
|
|
177
|
-
tab_sizes[tab.id] = tab_els[tab.id]?.getBoundingClientRect();
|
|
178
|
-
});
|
|
179
|
-
return tab_sizes;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
184
|
$: tab_scale =
|
|
183
185
|
tabs[$selected_tab_index >= 0 ? $selected_tab_index : 0]?.scale;
|
|
184
186
|
</script>
|
|
@@ -277,9 +279,7 @@
|
|
|
277
279
|
<style>
|
|
278
280
|
.tabs {
|
|
279
281
|
position: relative;
|
|
280
|
-
display: flex;
|
|
281
282
|
flex-direction: column;
|
|
282
|
-
gap: var(--layout-gap);
|
|
283
283
|
}
|
|
284
284
|
|
|
285
285
|
.hide {
|
|
@@ -297,6 +297,7 @@
|
|
|
297
297
|
position: relative;
|
|
298
298
|
height: var(--size-8);
|
|
299
299
|
padding-bottom: var(--size-2);
|
|
300
|
+
margin-bottom: var(--layout-gap);
|
|
300
301
|
}
|
|
301
302
|
|
|
302
303
|
.tab-container {
|
package/package.json
CHANGED
package/shared/Tabs.svelte
CHANGED
|
@@ -37,16 +37,20 @@
|
|
|
37
37
|
|
|
38
38
|
// When initial_tabs changes (e.g. a non-mounted tab's props were updated),
|
|
39
39
|
// sync the internal tabs array so the tab buttons reflect the new state.
|
|
40
|
-
//
|
|
41
|
-
//
|
|
40
|
+
// The tabs mutation is deferred via tick() because in Svelte 5 legacy mode
|
|
41
|
+
// $: effects track all reads inside called functions — writing tabs[i]
|
|
42
|
+
// through the $state proxy would track `tabs` as a dependency, creating
|
|
43
|
+
// an infinite self-triggering loop.
|
|
42
44
|
$: _sync_tabs(initial_tabs);
|
|
43
45
|
|
|
44
46
|
function _sync_tabs(new_tabs: Tab[]): void {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
47
|
+
tick().then(() => {
|
|
48
|
+
for (let i = 0; i < new_tabs.length; i++) {
|
|
49
|
+
if (new_tabs[i] && !mounted_tab_orders.has(i)) {
|
|
50
|
+
tabs[i] = new_tabs[i];
|
|
51
|
+
}
|
|
48
52
|
}
|
|
49
|
-
}
|
|
53
|
+
});
|
|
50
54
|
}
|
|
51
55
|
|
|
52
56
|
$: has_tabs = tabs.length > 0;
|
|
@@ -70,10 +74,11 @@
|
|
|
70
74
|
|
|
71
75
|
onMount(() => {
|
|
72
76
|
if (!tab_nav_el) return;
|
|
73
|
-
const
|
|
77
|
+
const ro = new ResizeObserver(() => {
|
|
74
78
|
handle_menu_overflow();
|
|
75
79
|
});
|
|
76
|
-
|
|
80
|
+
ro.observe(tab_nav_el);
|
|
81
|
+
return () => ro.disconnect();
|
|
77
82
|
});
|
|
78
83
|
|
|
79
84
|
setContext(TABS, {
|
|
@@ -128,33 +133,42 @@
|
|
|
128
133
|
}
|
|
129
134
|
}
|
|
130
135
|
|
|
136
|
+
// approximate width of the "..." overflow button including margin
|
|
137
|
+
const OVERFLOW_BTN_RESERVE = 48;
|
|
138
|
+
|
|
131
139
|
async function handle_menu_overflow(): Promise<void> {
|
|
132
140
|
if (!tab_nav_el) return;
|
|
133
141
|
|
|
134
142
|
await tick();
|
|
135
|
-
|
|
143
|
+
await new Promise((r) => requestAnimationFrame(r));
|
|
144
|
+
|
|
145
|
+
const available = tab_nav_el.clientWidth;
|
|
136
146
|
|
|
137
|
-
let
|
|
138
|
-
|
|
139
|
-
let last_visible_index = 0;
|
|
140
|
-
const offset = tab_nav_size.left;
|
|
147
|
+
let cumulative = 0;
|
|
148
|
+
let split_index = tabs.length;
|
|
141
149
|
|
|
142
|
-
for (let i =
|
|
150
|
+
for (let i = 0; i < tabs.length; i++) {
|
|
143
151
|
const tab = tabs[i];
|
|
144
|
-
if (!tab) continue;
|
|
145
|
-
const
|
|
146
|
-
if (!
|
|
147
|
-
|
|
148
|
-
|
|
152
|
+
if (!tab || tab.visible === false || tab.visible === "hidden") continue;
|
|
153
|
+
const el = tab_els[tab.id];
|
|
154
|
+
if (!el) continue;
|
|
155
|
+
cumulative += el.getBoundingClientRect().width;
|
|
156
|
+
const has_more = tabs
|
|
157
|
+
.slice(i + 1)
|
|
158
|
+
.some((t) => t && t.visible !== false && t.visible !== "hidden");
|
|
159
|
+
const limit = has_more ? available - OVERFLOW_BTN_RESERVE : available;
|
|
160
|
+
if (cumulative > limit) {
|
|
161
|
+
split_index = i;
|
|
149
162
|
break;
|
|
150
163
|
}
|
|
151
164
|
}
|
|
152
165
|
|
|
153
|
-
|
|
154
|
-
|
|
166
|
+
visible_tabs = tabs.slice(0, split_index);
|
|
167
|
+
overflow_tabs = tabs.slice(split_index);
|
|
155
168
|
|
|
156
169
|
overflow_has_selected_tab = handle_overflow_has_selected_tab($selected_tab);
|
|
157
|
-
is_overflowing =
|
|
170
|
+
is_overflowing =
|
|
171
|
+
overflow_tabs.filter((t) => t && t.visible !== false).length > 0;
|
|
158
172
|
}
|
|
159
173
|
|
|
160
174
|
$: overflow_has_selected_tab =
|
|
@@ -167,18 +181,6 @@
|
|
|
167
181
|
return overflow_tabs.some((t) => t?.id === selected_tab);
|
|
168
182
|
}
|
|
169
183
|
|
|
170
|
-
function get_tab_sizes(
|
|
171
|
-
tabs: (Tab | null)[],
|
|
172
|
-
tab_els: Record<string | number, HTMLElement>
|
|
173
|
-
): Record<string | number, DOMRect> {
|
|
174
|
-
const tab_sizes: Record<string | number, DOMRect> = {};
|
|
175
|
-
tabs.forEach((tab) => {
|
|
176
|
-
if (!tab) return;
|
|
177
|
-
tab_sizes[tab.id] = tab_els[tab.id]?.getBoundingClientRect();
|
|
178
|
-
});
|
|
179
|
-
return tab_sizes;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
184
|
$: tab_scale =
|
|
183
185
|
tabs[$selected_tab_index >= 0 ? $selected_tab_index : 0]?.scale;
|
|
184
186
|
</script>
|
|
@@ -277,9 +279,7 @@
|
|
|
277
279
|
<style>
|
|
278
280
|
.tabs {
|
|
279
281
|
position: relative;
|
|
280
|
-
display: flex;
|
|
281
282
|
flex-direction: column;
|
|
282
|
-
gap: var(--layout-gap);
|
|
283
283
|
}
|
|
284
284
|
|
|
285
285
|
.hide {
|
|
@@ -297,6 +297,7 @@
|
|
|
297
297
|
position: relative;
|
|
298
298
|
height: var(--size-8);
|
|
299
299
|
padding-bottom: var(--size-2);
|
|
300
|
+
margin-bottom: var(--layout-gap);
|
|
300
301
|
}
|
|
301
302
|
|
|
302
303
|
.tab-container {
|