@gradio/tabs 0.5.0 → 0.5.2-dev.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 +12 -0
- package/Index.svelte +26 -32
- package/dist/Index.svelte +33 -28
- package/dist/Index.svelte.d.ts +18 -30
- package/dist/shared/OverflowIcon.svelte.d.ts +22 -21
- package/dist/shared/Tabs.svelte +171 -111
- package/dist/shared/Tabs.svelte.d.ts +35 -26
- package/dist/shared/Walkthrough.svelte +149 -110
- package/dist/shared/Walkthrough.svelte.d.ts +34 -25
- package/dist/types.d.ts +14 -0
- package/dist/types.js +1 -0
- package/package.json +4 -4
- package/shared/Tabs.svelte +18 -12
- package/shared/Walkthrough.svelte +5 -5
- package/types.ts +16 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @gradio/tabs
|
|
2
2
|
|
|
3
|
+
## 0.5.2-dev.0
|
|
4
|
+
|
|
5
|
+
### Dependency updates
|
|
6
|
+
|
|
7
|
+
- @gradio/utils@0.10.3-dev.0
|
|
8
|
+
|
|
9
|
+
## 0.5.1
|
|
10
|
+
|
|
11
|
+
### Fixes
|
|
12
|
+
|
|
13
|
+
- [#11784](https://github.com/gradio-app/gradio/pull/11784) [`d9dd3f5`](https://github.com/gradio-app/gradio/commit/d9dd3f54b7fb34cf7118e549d39fc63937ca3489) - Add "hidden" option to component's `visible` kwarg to render but visually hide the component. Thanks @pngwn!
|
|
14
|
+
|
|
3
15
|
## 0.5.0
|
|
4
16
|
|
|
5
17
|
### Features
|
package/Index.svelte
CHANGED
|
@@ -3,50 +3,44 @@
|
|
|
3
3
|
</script>
|
|
4
4
|
|
|
5
5
|
<script lang="ts">
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import Tabs, { type Tab } from "./shared/Tabs.svelte";
|
|
6
|
+
import { Gradio } from "@gradio/utils";
|
|
7
|
+
import Tabs from "./shared/Tabs.svelte";
|
|
9
8
|
import Walkthrough from "./shared/Walkthrough.svelte";
|
|
9
|
+
import type { TabsProps, TabsEvents } from "./types";
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
let props = $props();
|
|
12
|
+
const gradio = new Gradio<TabsEvents, TabsProps>(props);
|
|
12
13
|
|
|
13
|
-
|
|
14
|
-
export let elem_id = "";
|
|
15
|
-
export let elem_classes: string[] = [];
|
|
16
|
-
export let selected: number | string;
|
|
17
|
-
export let initial_tabs: Tab[] = [];
|
|
18
|
-
export let name: "tabs" | "walkthrough" = "tabs";
|
|
19
|
-
export let gradio:
|
|
20
|
-
| Gradio<{
|
|
21
|
-
change: never;
|
|
22
|
-
select: SelectData;
|
|
23
|
-
}>
|
|
24
|
-
| undefined;
|
|
14
|
+
let old_selected = $state(gradio.props.selected);
|
|
25
15
|
|
|
26
|
-
|
|
16
|
+
$effect(() => {
|
|
17
|
+
if (old_selected !== gradio.props.selected) {
|
|
18
|
+
old_selected = gradio.props.selected;
|
|
19
|
+
}
|
|
20
|
+
});
|
|
27
21
|
</script>
|
|
28
22
|
|
|
29
|
-
{#if name === "walkthrough"}
|
|
23
|
+
{#if gradio.props.name === "walkthrough"}
|
|
30
24
|
<Walkthrough
|
|
31
|
-
{visible}
|
|
32
|
-
{elem_id}
|
|
33
|
-
{elem_classes}
|
|
34
|
-
bind:selected
|
|
35
|
-
on:change={() => gradio
|
|
36
|
-
on:select={(e) => gradio
|
|
37
|
-
{initial_tabs}
|
|
25
|
+
visible={gradio.shared.visible}
|
|
26
|
+
elem_id={gradio.shared.elem_id}
|
|
27
|
+
elem_classes={gradio.shared.elem_classes}
|
|
28
|
+
bind:selected={gradio.props.selected}
|
|
29
|
+
on:change={() => gradio.dispatch("change")}
|
|
30
|
+
on:select={(e) => gradio.dispatch("select", e.detail)}
|
|
31
|
+
initial_tabs={gradio.props.initial_tabs}
|
|
38
32
|
>
|
|
39
33
|
<slot />
|
|
40
34
|
</Walkthrough>
|
|
41
35
|
{:else}
|
|
42
36
|
<Tabs
|
|
43
|
-
{visible}
|
|
44
|
-
{elem_id}
|
|
45
|
-
{elem_classes}
|
|
46
|
-
bind:selected
|
|
47
|
-
on:change={() => gradio
|
|
48
|
-
on:select={(e) => gradio
|
|
49
|
-
{initial_tabs}
|
|
37
|
+
visible={gradio.shared.visible}
|
|
38
|
+
elem_id={gradio.shared.elem_id}
|
|
39
|
+
elem_classes={gradio.shared.elem_classes}
|
|
40
|
+
bind:selected={gradio.props.selected}
|
|
41
|
+
on:change={() => gradio.dispatch("change")}
|
|
42
|
+
on:select={(e) => gradio.dispatch("select", e.detail)}
|
|
43
|
+
initial_tabs={gradio.props.initial_tabs}
|
|
50
44
|
>
|
|
51
45
|
<slot />
|
|
52
46
|
</Tabs>
|
package/dist/Index.svelte
CHANGED
|
@@ -1,41 +1,46 @@
|
|
|
1
|
-
<script context="module"
|
|
1
|
+
<script context="module" lang="ts">
|
|
2
|
+
export { default as BaseTabs, TABS, type Tab } from "./shared/Tabs.svelte";
|
|
2
3
|
</script>
|
|
3
4
|
|
|
4
|
-
<script
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
5
|
+
<script lang="ts">
|
|
6
|
+
import { Gradio } from "@gradio/utils";
|
|
7
|
+
import Tabs from "./shared/Tabs.svelte";
|
|
8
|
+
import Walkthrough from "./shared/Walkthrough.svelte";
|
|
9
|
+
import type { TabsProps, TabsEvents } from "./types";
|
|
10
|
+
|
|
11
|
+
let props = $props();
|
|
12
|
+
const gradio = new Gradio<TabsEvents, TabsProps>(props);
|
|
13
|
+
|
|
14
|
+
let old_selected = $state(gradio.props.selected);
|
|
15
|
+
|
|
16
|
+
$effect(() => {
|
|
17
|
+
if (old_selected !== gradio.props.selected) {
|
|
18
|
+
old_selected = gradio.props.selected;
|
|
19
|
+
}
|
|
20
|
+
});
|
|
16
21
|
</script>
|
|
17
22
|
|
|
18
|
-
{#if name === "walkthrough"}
|
|
23
|
+
{#if gradio.props.name === "walkthrough"}
|
|
19
24
|
<Walkthrough
|
|
20
|
-
{visible}
|
|
21
|
-
{elem_id}
|
|
22
|
-
{elem_classes}
|
|
23
|
-
bind:selected
|
|
24
|
-
on:change={() => gradio
|
|
25
|
-
on:select={(e) => gradio
|
|
26
|
-
{initial_tabs}
|
|
25
|
+
visible={gradio.shared.visible}
|
|
26
|
+
elem_id={gradio.shared.elem_id}
|
|
27
|
+
elem_classes={gradio.shared.elem_classes}
|
|
28
|
+
bind:selected={gradio.props.selected}
|
|
29
|
+
on:change={() => gradio.dispatch("change")}
|
|
30
|
+
on:select={(e) => gradio.dispatch("select", e.detail)}
|
|
31
|
+
initial_tabs={gradio.props.initial_tabs}
|
|
27
32
|
>
|
|
28
33
|
<slot />
|
|
29
34
|
</Walkthrough>
|
|
30
35
|
{:else}
|
|
31
36
|
<Tabs
|
|
32
|
-
{visible}
|
|
33
|
-
{elem_id}
|
|
34
|
-
{elem_classes}
|
|
35
|
-
bind:selected
|
|
36
|
-
on:change={() => gradio
|
|
37
|
-
on:select={(e) => gradio
|
|
38
|
-
{initial_tabs}
|
|
37
|
+
visible={gradio.shared.visible}
|
|
38
|
+
elem_id={gradio.shared.elem_id}
|
|
39
|
+
elem_classes={gradio.shared.elem_classes}
|
|
40
|
+
bind:selected={gradio.props.selected}
|
|
41
|
+
on:change={() => gradio.dispatch("change")}
|
|
42
|
+
on:select={(e) => gradio.dispatch("select", e.detail)}
|
|
43
|
+
initial_tabs={gradio.props.initial_tabs}
|
|
39
44
|
>
|
|
40
45
|
<slot />
|
|
41
46
|
</Tabs>
|
package/dist/Index.svelte.d.ts
CHANGED
|
@@ -1,33 +1,21 @@
|
|
|
1
|
-
import { SvelteComponent } from "svelte";
|
|
2
1
|
export { default as BaseTabs, TABS, type Tab } from "./shared/Tabs.svelte";
|
|
3
|
-
|
|
4
|
-
import
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
gradio: Gradio<{
|
|
14
|
-
change: never;
|
|
15
|
-
select: SelectData;
|
|
16
|
-
}> | undefined;
|
|
2
|
+
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
3
|
+
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
4
|
+
$$bindings?: Bindings;
|
|
5
|
+
} & Exports;
|
|
6
|
+
(internal: unknown, props: Props & {
|
|
7
|
+
$$events?: Events;
|
|
8
|
+
$$slots?: Slots;
|
|
9
|
+
}): Exports & {
|
|
10
|
+
$set?: any;
|
|
11
|
+
$on?: any;
|
|
17
12
|
};
|
|
18
|
-
|
|
19
|
-
prop_change: CustomEvent<any>;
|
|
20
|
-
} & {
|
|
21
|
-
[evt: string]: CustomEvent<any>;
|
|
22
|
-
};
|
|
23
|
-
slots: {
|
|
24
|
-
default: {};
|
|
25
|
-
};
|
|
26
|
-
exports?: {} | undefined;
|
|
27
|
-
bindings?: string | undefined;
|
|
28
|
-
};
|
|
29
|
-
export type IndexProps = typeof __propDef.props;
|
|
30
|
-
export type IndexEvents = typeof __propDef.events;
|
|
31
|
-
export type IndexSlots = typeof __propDef.slots;
|
|
32
|
-
export default class Index extends SvelteComponent<IndexProps, IndexEvents, IndexSlots> {
|
|
13
|
+
z_$$bindings?: Bindings;
|
|
33
14
|
}
|
|
15
|
+
declare const Index: $$__sveltets_2_IsomorphicComponent<any, {
|
|
16
|
+
[evt: string]: CustomEvent<any>;
|
|
17
|
+
}, {
|
|
18
|
+
default: {};
|
|
19
|
+
}, {}, "">;
|
|
20
|
+
type Index = InstanceType<typeof Index>;
|
|
21
|
+
export default Index;
|
|
@@ -1,25 +1,26 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
/** @typedef {typeof __propDef.slots} OverflowIconSlots */
|
|
4
|
-
export default class OverflowIcon extends SvelteComponent<{
|
|
1
|
+
export default OverflowIcon;
|
|
2
|
+
type OverflowIcon = SvelteComponent<{
|
|
5
3
|
[x: string]: never;
|
|
6
4
|
}, {
|
|
7
5
|
[evt: string]: CustomEvent<any>;
|
|
8
|
-
}, {}> {
|
|
9
|
-
|
|
10
|
-
export type OverflowIconProps = typeof __propDef.props;
|
|
11
|
-
export type OverflowIconEvents = typeof __propDef.events;
|
|
12
|
-
export type OverflowIconSlots = typeof __propDef.slots;
|
|
13
|
-
import { SvelteComponent } from "svelte";
|
|
14
|
-
declare const __propDef: {
|
|
15
|
-
props: {
|
|
16
|
-
[x: string]: never;
|
|
17
|
-
};
|
|
18
|
-
events: {
|
|
19
|
-
[evt: string]: CustomEvent<any>;
|
|
20
|
-
};
|
|
21
|
-
slots: {};
|
|
22
|
-
exports?: undefined;
|
|
23
|
-
bindings?: undefined;
|
|
6
|
+
}, {}> & {
|
|
7
|
+
$$bindings?: string | undefined;
|
|
24
8
|
};
|
|
25
|
-
|
|
9
|
+
declare const OverflowIcon: $$__sveltets_2_IsomorphicComponent<{
|
|
10
|
+
[x: string]: never;
|
|
11
|
+
}, {
|
|
12
|
+
[evt: string]: CustomEvent<any>;
|
|
13
|
+
}, {}, {}, string>;
|
|
14
|
+
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
15
|
+
new (options: import("svelte").ComponentConstructorOptions<Props>): import("svelte").SvelteComponent<Props, Events, Slots> & {
|
|
16
|
+
$$bindings?: Bindings;
|
|
17
|
+
} & Exports;
|
|
18
|
+
(internal: unknown, props: {
|
|
19
|
+
$$events?: Events;
|
|
20
|
+
$$slots?: Slots;
|
|
21
|
+
}): Exports & {
|
|
22
|
+
$set?: any;
|
|
23
|
+
$on?: any;
|
|
24
|
+
};
|
|
25
|
+
z_$$bindings?: Bindings;
|
|
26
|
+
}
|
package/dist/shared/Tabs.svelte
CHANGED
|
@@ -1,110 +1,164 @@
|
|
|
1
|
-
<script context="module"
|
|
1
|
+
<script context="module" lang="ts">
|
|
2
|
+
export const TABS = {};
|
|
3
|
+
|
|
4
|
+
export interface Tab {
|
|
5
|
+
label: string;
|
|
6
|
+
id: string | number;
|
|
7
|
+
elem_id: string | undefined;
|
|
8
|
+
visible: boolean | "hidden";
|
|
9
|
+
interactive: boolean;
|
|
10
|
+
scale: number | null;
|
|
11
|
+
}
|
|
2
12
|
</script>
|
|
3
13
|
|
|
4
|
-
<script
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
export let
|
|
11
|
-
export let
|
|
12
|
-
let
|
|
13
|
-
let
|
|
14
|
-
let
|
|
15
|
-
|
|
16
|
-
let
|
|
17
|
-
|
|
18
|
-
let
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
function
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
14
|
+
<script lang="ts">
|
|
15
|
+
import { setContext, createEventDispatcher, tick, onMount } from "svelte";
|
|
16
|
+
import OverflowIcon from "./OverflowIcon.svelte";
|
|
17
|
+
import { writable } from "svelte/store";
|
|
18
|
+
import type { SelectData } from "@gradio/utils";
|
|
19
|
+
|
|
20
|
+
export let visible: boolean | "hidden" = true;
|
|
21
|
+
export let elem_id = "";
|
|
22
|
+
export let elem_classes: string[] = [];
|
|
23
|
+
export let selected: number | string;
|
|
24
|
+
export let initial_tabs: Tab[];
|
|
25
|
+
|
|
26
|
+
let tabs: (Tab | null)[] = [...initial_tabs];
|
|
27
|
+
let visible_tabs: (Tab | null)[] = [...initial_tabs];
|
|
28
|
+
let overflow_tabs: (Tab | null)[] = [];
|
|
29
|
+
let overflow_menu_open = false;
|
|
30
|
+
let overflow_menu: HTMLElement;
|
|
31
|
+
|
|
32
|
+
$: has_tabs = tabs.length > 0;
|
|
33
|
+
|
|
34
|
+
let tab_nav_el: HTMLDivElement;
|
|
35
|
+
|
|
36
|
+
const selected_tab = writable<false | number | string>(
|
|
37
|
+
selected || tabs[0]?.id || false
|
|
38
|
+
);
|
|
39
|
+
const selected_tab_index = writable<number>(
|
|
40
|
+
tabs.findIndex((t) => t?.id === selected) || 0
|
|
41
|
+
);
|
|
42
|
+
const dispatch = createEventDispatcher<{
|
|
43
|
+
change: undefined;
|
|
44
|
+
select: SelectData;
|
|
45
|
+
}>();
|
|
46
|
+
|
|
47
|
+
let is_overflowing = false;
|
|
48
|
+
let overflow_has_selected_tab = false;
|
|
49
|
+
let tab_els: Record<string | number, HTMLElement> = {};
|
|
50
|
+
|
|
51
|
+
onMount(() => {
|
|
52
|
+
if (!tab_nav_el) return;
|
|
53
|
+
const observer = new IntersectionObserver((entries) => {
|
|
54
|
+
handle_menu_overflow();
|
|
55
|
+
});
|
|
56
|
+
observer.observe(tab_nav_el);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
setContext(TABS, {
|
|
60
|
+
register_tab: (tab: Tab, order: number) => {
|
|
61
|
+
tabs[order] = tab;
|
|
62
|
+
|
|
63
|
+
if ($selected_tab === false && tab.visible !== false && tab.interactive) {
|
|
64
|
+
$selected_tab = tab.id;
|
|
65
|
+
$selected_tab_index = order;
|
|
66
|
+
}
|
|
67
|
+
return order;
|
|
68
|
+
},
|
|
69
|
+
unregister_tab: (tab: Tab, order: number) => {
|
|
70
|
+
if ($selected_tab === tab.id) {
|
|
71
|
+
$selected_tab = tabs[0]?.id || false;
|
|
72
|
+
}
|
|
73
|
+
tabs[order] = null;
|
|
74
|
+
},
|
|
75
|
+
selected_tab,
|
|
76
|
+
selected_tab_index
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
function change_tab(id: string | number | undefined): void {
|
|
80
|
+
const tab_to_activate = tabs.find((t) => t?.id === id);
|
|
81
|
+
if (
|
|
82
|
+
id !== undefined &&
|
|
83
|
+
tab_to_activate &&
|
|
84
|
+
tab_to_activate.interactive &&
|
|
85
|
+
tab_to_activate.visible !== false &&
|
|
86
|
+
$selected_tab !== tab_to_activate.id
|
|
87
|
+
) {
|
|
88
|
+
selected = id;
|
|
89
|
+
$selected_tab = id;
|
|
90
|
+
$selected_tab_index = tabs.findIndex((t) => t?.id === id);
|
|
91
|
+
dispatch("change");
|
|
92
|
+
overflow_menu_open = false;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
$: (tabs, selected !== null && change_tab(selected));
|
|
97
|
+
$: (tabs, tab_nav_el, tab_els, handle_menu_overflow());
|
|
98
|
+
|
|
99
|
+
function handle_outside_click(event: MouseEvent): void {
|
|
100
|
+
if (
|
|
101
|
+
overflow_menu_open &&
|
|
102
|
+
overflow_menu &&
|
|
103
|
+
!overflow_menu.contains(event.target as Node)
|
|
104
|
+
) {
|
|
105
|
+
overflow_menu_open = false;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
async function handle_menu_overflow(): Promise<void> {
|
|
110
|
+
if (!tab_nav_el) return;
|
|
111
|
+
|
|
112
|
+
await tick();
|
|
113
|
+
const tab_nav_size = tab_nav_el.getBoundingClientRect();
|
|
114
|
+
|
|
115
|
+
let max_width = tab_nav_size.width;
|
|
116
|
+
const tab_sizes = get_tab_sizes(tabs, tab_els);
|
|
117
|
+
let last_visible_index = 0;
|
|
118
|
+
const offset = tab_nav_size.left;
|
|
119
|
+
|
|
120
|
+
for (let i = tabs.length - 1; i >= 0; i--) {
|
|
121
|
+
const tab = tabs[i];
|
|
122
|
+
if (!tab) continue;
|
|
123
|
+
const tab_rect = tab_sizes[tab.id];
|
|
124
|
+
if (!tab_rect) continue;
|
|
125
|
+
if (tab_rect.right - offset < max_width) {
|
|
126
|
+
last_visible_index = i;
|
|
127
|
+
break;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
overflow_tabs = tabs.slice(last_visible_index + 1);
|
|
132
|
+
visible_tabs = tabs.slice(0, last_visible_index + 1);
|
|
133
|
+
|
|
134
|
+
overflow_has_selected_tab = handle_overflow_has_selected_tab($selected_tab);
|
|
135
|
+
is_overflowing = overflow_tabs.length > 0;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
$: overflow_has_selected_tab =
|
|
139
|
+
handle_overflow_has_selected_tab($selected_tab);
|
|
140
|
+
|
|
141
|
+
function handle_overflow_has_selected_tab(
|
|
142
|
+
selected_tab: number | string | false
|
|
143
|
+
): boolean {
|
|
144
|
+
if (selected_tab === false) return false;
|
|
145
|
+
return overflow_tabs.some((t) => t?.id === selected_tab);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function get_tab_sizes(
|
|
149
|
+
tabs: (Tab | null)[],
|
|
150
|
+
tab_els: Record<string | number, HTMLElement>
|
|
151
|
+
): Record<string | number, DOMRect> {
|
|
152
|
+
const tab_sizes: Record<string | number, DOMRect> = {};
|
|
153
|
+
tabs.forEach((tab) => {
|
|
154
|
+
if (!tab) return;
|
|
155
|
+
tab_sizes[tab.id] = tab_els[tab.id]?.getBoundingClientRect();
|
|
156
|
+
});
|
|
157
|
+
return tab_sizes;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
$: tab_scale =
|
|
161
|
+
tabs[$selected_tab_index >= 0 ? $selected_tab_index : 0]?.scale;
|
|
108
162
|
</script>
|
|
109
163
|
|
|
110
164
|
<svelte:window
|
|
@@ -114,7 +168,8 @@ $: tab_scale = tabs[$selected_tab_index >= 0 ? $selected_tab_index : 0]?.scale;
|
|
|
114
168
|
|
|
115
169
|
<div
|
|
116
170
|
class="tabs {elem_classes.join(' ')}"
|
|
117
|
-
class:hide={
|
|
171
|
+
class:hide={visible === false}
|
|
172
|
+
class:hidden={visible === "hidden"}
|
|
118
173
|
id={elem_id}
|
|
119
174
|
style:flex-grow={tab_scale}
|
|
120
175
|
>
|
|
@@ -122,7 +177,7 @@ $: tab_scale = tabs[$selected_tab_index >= 0 ? $selected_tab_index : 0]?.scale;
|
|
|
122
177
|
<div class="tab-wrapper">
|
|
123
178
|
<div class="tab-container visually-hidden" aria-hidden="true">
|
|
124
179
|
{#each tabs as t, i}
|
|
125
|
-
{#if t?.visible}
|
|
180
|
+
{#if t && t?.visible !== false && t?.visible !== "hidden"}
|
|
126
181
|
<button bind:this={tab_els[t.id]}>
|
|
127
182
|
{t?.label}
|
|
128
183
|
</button>
|
|
@@ -131,7 +186,7 @@ $: tab_scale = tabs[$selected_tab_index >= 0 ? $selected_tab_index : 0]?.scale;
|
|
|
131
186
|
</div>
|
|
132
187
|
<div class="tab-container" bind:this={tab_nav_el} role="tablist">
|
|
133
188
|
{#each visible_tabs as t, i}
|
|
134
|
-
{#if t?.visible}
|
|
189
|
+
{#if t && t?.visible !== false}
|
|
135
190
|
<button
|
|
136
191
|
role="tab"
|
|
137
192
|
class:selected={t.id === $selected_tab}
|
|
@@ -144,7 +199,7 @@ $: tab_scale = tabs[$selected_tab_index >= 0 ? $selected_tab_index : 0]?.scale;
|
|
|
144
199
|
on:click={() => {
|
|
145
200
|
if (t.id !== $selected_tab) {
|
|
146
201
|
change_tab(t.id);
|
|
147
|
-
dispatch("select", { value: t.label, index: i });
|
|
202
|
+
dispatch("select", { value: t.label, index: i, id: t.id });
|
|
148
203
|
}
|
|
149
204
|
}}
|
|
150
205
|
>
|
|
@@ -155,7 +210,8 @@ $: tab_scale = tabs[$selected_tab_index >= 0 ? $selected_tab_index : 0]?.scale;
|
|
|
155
210
|
</div>
|
|
156
211
|
<span
|
|
157
212
|
class="overflow-menu"
|
|
158
|
-
class:hide={!is_overflowing ||
|
|
213
|
+
class:hide={!is_overflowing ||
|
|
214
|
+
!overflow_tabs.some((t) => t?.visible !== false)}
|
|
159
215
|
bind:this={overflow_menu}
|
|
160
216
|
>
|
|
161
217
|
<button
|
|
@@ -167,7 +223,7 @@ $: tab_scale = tabs[$selected_tab_index >= 0 ? $selected_tab_index : 0]?.scale;
|
|
|
167
223
|
</button>
|
|
168
224
|
<div class="overflow-dropdown" class:hide={!overflow_menu_open}>
|
|
169
225
|
{#each overflow_tabs as t}
|
|
170
|
-
{#if t?.visible}
|
|
226
|
+
{#if t?.visible !== false}
|
|
171
227
|
<button
|
|
172
228
|
on:click={() => change_tab(t?.id)}
|
|
173
229
|
class:selected={t?.id === $selected_tab}
|
|
@@ -195,6 +251,10 @@ $: tab_scale = tabs[$selected_tab_index >= 0 ? $selected_tab_index : 0]?.scale;
|
|
|
195
251
|
display: none;
|
|
196
252
|
}
|
|
197
253
|
|
|
254
|
+
.hidden {
|
|
255
|
+
display: none !important;
|
|
256
|
+
}
|
|
257
|
+
|
|
198
258
|
.tab-wrapper {
|
|
199
259
|
display: flex;
|
|
200
260
|
align-items: center;
|
|
@@ -1,37 +1,46 @@
|
|
|
1
|
-
import { SvelteComponent } from "svelte";
|
|
2
1
|
export declare const TABS: {};
|
|
3
2
|
export interface Tab {
|
|
4
3
|
label: string;
|
|
5
4
|
id: string | number;
|
|
6
5
|
elem_id: string | undefined;
|
|
7
|
-
visible: boolean;
|
|
6
|
+
visible: boolean | "hidden";
|
|
8
7
|
interactive: boolean;
|
|
9
8
|
scale: number | null;
|
|
10
9
|
}
|
|
11
10
|
import type { SelectData } from "@gradio/utils";
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
11
|
+
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
12
|
+
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
13
|
+
$$bindings?: Bindings;
|
|
14
|
+
} & Exports;
|
|
15
|
+
(internal: unknown, props: Props & {
|
|
16
|
+
$$events?: Events;
|
|
17
|
+
$$slots?: Slots;
|
|
18
|
+
}): Exports & {
|
|
19
|
+
$set?: any;
|
|
20
|
+
$on?: any;
|
|
19
21
|
};
|
|
20
|
-
|
|
21
|
-
change: CustomEvent<undefined>;
|
|
22
|
-
select: CustomEvent<SelectData>;
|
|
23
|
-
} & {
|
|
24
|
-
[evt: string]: CustomEvent<any>;
|
|
25
|
-
};
|
|
26
|
-
slots: {
|
|
27
|
-
default: {};
|
|
28
|
-
};
|
|
29
|
-
exports?: {} | undefined;
|
|
30
|
-
bindings?: string | undefined;
|
|
31
|
-
};
|
|
32
|
-
export type TabsProps = typeof __propDef.props;
|
|
33
|
-
export type TabsEvents = typeof __propDef.events;
|
|
34
|
-
export type TabsSlots = typeof __propDef.slots;
|
|
35
|
-
export default class Tabs extends SvelteComponent<TabsProps, TabsEvents, TabsSlots> {
|
|
22
|
+
z_$$bindings?: Bindings;
|
|
36
23
|
}
|
|
37
|
-
|
|
24
|
+
type $$__sveltets_2_PropsWithChildren<Props, Slots> = Props & (Slots extends {
|
|
25
|
+
default: any;
|
|
26
|
+
} ? Props extends Record<string, never> ? any : {
|
|
27
|
+
children?: any;
|
|
28
|
+
} : {});
|
|
29
|
+
declare const Tabs: $$__sveltets_2_IsomorphicComponent<$$__sveltets_2_PropsWithChildren<{
|
|
30
|
+
visible?: boolean | "hidden";
|
|
31
|
+
elem_id?: string;
|
|
32
|
+
elem_classes?: string[];
|
|
33
|
+
selected: number | string;
|
|
34
|
+
initial_tabs: Tab[];
|
|
35
|
+
}, {
|
|
36
|
+
default: {};
|
|
37
|
+
}>, {
|
|
38
|
+
change: CustomEvent<undefined>;
|
|
39
|
+
select: CustomEvent<SelectData>;
|
|
40
|
+
} & {
|
|
41
|
+
[evt: string]: CustomEvent<any>;
|
|
42
|
+
}, {
|
|
43
|
+
default: {};
|
|
44
|
+
}, {}, string>;
|
|
45
|
+
type Tabs = InstanceType<typeof Tabs>;
|
|
46
|
+
export default Tabs;
|
|
@@ -1,115 +1,154 @@
|
|
|
1
|
-
<script context="module"
|
|
1
|
+
<script context="module" lang="ts">
|
|
2
|
+
import { TABS, type Tab } from "./Tabs.svelte";
|
|
2
3
|
</script>
|
|
3
4
|
|
|
4
|
-
<script
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
export let
|
|
10
|
-
export let
|
|
11
|
-
let
|
|
12
|
-
let
|
|
13
|
-
let
|
|
14
|
-
|
|
15
|
-
let
|
|
16
|
-
let
|
|
17
|
-
let
|
|
18
|
-
let
|
|
19
|
-
let
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
let
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
5
|
+
<script lang="ts">
|
|
6
|
+
import { setContext, createEventDispatcher, tick, onMount } from "svelte";
|
|
7
|
+
import { writable } from "svelte/store";
|
|
8
|
+
import type { SelectData } from "@gradio/utils";
|
|
9
|
+
|
|
10
|
+
export let visible: boolean | "hidden" = true;
|
|
11
|
+
export let elem_id = "";
|
|
12
|
+
export let elem_classes: string[] = [];
|
|
13
|
+
export let selected: number | string;
|
|
14
|
+
export let initial_tabs: Tab[];
|
|
15
|
+
|
|
16
|
+
let tabs: (Tab | null)[] = [...initial_tabs];
|
|
17
|
+
let stepper_container: HTMLDivElement;
|
|
18
|
+
let show_labels_for_all = true;
|
|
19
|
+
let measurement_container: HTMLDivElement;
|
|
20
|
+
let step_buttons: HTMLButtonElement[] = [];
|
|
21
|
+
let step_labels: HTMLSpanElement[] = [];
|
|
22
|
+
let label_height = 0;
|
|
23
|
+
let compact = false;
|
|
24
|
+
let recompute_overflow = true;
|
|
25
|
+
$: has_tabs = tabs.length > 0;
|
|
26
|
+
|
|
27
|
+
const selected_tab = writable<false | number | string>(
|
|
28
|
+
selected || tabs[0]?.id || false
|
|
29
|
+
);
|
|
30
|
+
const selected_tab_index = writable<number>(
|
|
31
|
+
tabs.findIndex((t) => t?.id === selected) || 0
|
|
32
|
+
);
|
|
33
|
+
const dispatch = createEventDispatcher<{
|
|
34
|
+
change: undefined;
|
|
35
|
+
select: SelectData;
|
|
36
|
+
}>();
|
|
37
|
+
|
|
38
|
+
async function check_overflow(): Promise<void> {
|
|
39
|
+
if (!stepper_container || !measurement_container || !recompute_overflow)
|
|
40
|
+
return;
|
|
41
|
+
recompute_overflow = false;
|
|
42
|
+
await tick();
|
|
43
|
+
|
|
44
|
+
// First, show all labels to measure
|
|
45
|
+
show_labels_for_all = true;
|
|
46
|
+
await tick();
|
|
47
|
+
|
|
48
|
+
const SEP_WIDTH = 50;
|
|
49
|
+
const button_width =
|
|
50
|
+
step_buttons[0].getBoundingClientRect().width * step_buttons.length +
|
|
51
|
+
SEP_WIDTH * (step_buttons.length - 1);
|
|
52
|
+
|
|
53
|
+
const containerWidth = stepper_container.getBoundingClientRect().width;
|
|
54
|
+
const does_it_fit = button_width < containerWidth;
|
|
55
|
+
|
|
56
|
+
if (!does_it_fit) {
|
|
57
|
+
show_labels_for_all = false;
|
|
58
|
+
compact = true;
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
let max_height = 0;
|
|
63
|
+
let is_overlapping = false;
|
|
64
|
+
let last_right = 0;
|
|
65
|
+
|
|
66
|
+
for (const label of step_labels) {
|
|
67
|
+
const { height, width, left, right } = label.getBoundingClientRect();
|
|
68
|
+
if (height > max_height) {
|
|
69
|
+
max_height = height;
|
|
70
|
+
}
|
|
71
|
+
if (last_right && left - 10 < last_right && !is_overlapping) {
|
|
72
|
+
is_overlapping = true;
|
|
73
|
+
}
|
|
74
|
+
last_right = right;
|
|
75
|
+
}
|
|
76
|
+
label_height = max_height;
|
|
77
|
+
|
|
78
|
+
if (is_overlapping) {
|
|
79
|
+
show_labels_for_all = false;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
let last_width = 0;
|
|
84
|
+
|
|
85
|
+
onMount(() => {
|
|
86
|
+
check_overflow();
|
|
87
|
+
|
|
88
|
+
const observer = new ResizeObserver((entries) => {
|
|
89
|
+
if (entries[0].contentRect.width === last_width) return;
|
|
90
|
+
last_width = entries[0].contentRect.width;
|
|
91
|
+
compact = false;
|
|
92
|
+
recompute_overflow = true;
|
|
93
|
+
check_overflow();
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
if (stepper_container) {
|
|
97
|
+
observer.observe(stepper_container);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return () => {
|
|
101
|
+
observer.disconnect();
|
|
102
|
+
};
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
setContext(TABS, {
|
|
106
|
+
register_tab: (tab: Tab, order: number) => {
|
|
107
|
+
tabs[order] = tab;
|
|
108
|
+
|
|
109
|
+
if ($selected_tab === false && tab.visible && tab.interactive) {
|
|
110
|
+
$selected_tab = tab.id;
|
|
111
|
+
$selected_tab_index = order;
|
|
112
|
+
}
|
|
113
|
+
return order;
|
|
114
|
+
},
|
|
115
|
+
unregister_tab: (tab: Tab, order: number) => {
|
|
116
|
+
if ($selected_tab === tab.id) {
|
|
117
|
+
$selected_tab = tabs[0]?.id || false;
|
|
118
|
+
}
|
|
119
|
+
tabs[order] = null;
|
|
120
|
+
},
|
|
121
|
+
selected_tab,
|
|
122
|
+
selected_tab_index
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
function change_tab(id: string | number | undefined, index: number): void {
|
|
126
|
+
const tab_to_activate = tabs.find((t) => t?.id === id);
|
|
127
|
+
if (
|
|
128
|
+
id !== undefined &&
|
|
129
|
+
tab_to_activate &&
|
|
130
|
+
tab_to_activate.interactive &&
|
|
131
|
+
tab_to_activate.visible &&
|
|
132
|
+
$selected_tab !== tab_to_activate.id
|
|
133
|
+
) {
|
|
134
|
+
selected = id;
|
|
135
|
+
$selected_tab = id;
|
|
136
|
+
$selected_tab_index = tabs.findIndex((t) => t?.id === id);
|
|
137
|
+
dispatch("change");
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
$: (tabs,
|
|
142
|
+
selected !== null &&
|
|
143
|
+
change_tab(
|
|
144
|
+
selected,
|
|
145
|
+
tabs.findIndex((t) => t?.id === selected)
|
|
146
|
+
));
|
|
147
|
+
$: (tabs, check_overflow());
|
|
148
|
+
$: ($selected_tab_index, check_overflow());
|
|
149
|
+
|
|
150
|
+
$: tab_scale =
|
|
151
|
+
tabs[$selected_tab_index >= 0 ? $selected_tab_index : 0]?.scale;
|
|
113
152
|
</script>
|
|
114
153
|
|
|
115
154
|
<svelte:window on:resize={check_overflow} />
|
|
@@ -1,29 +1,38 @@
|
|
|
1
|
-
import { SvelteComponent } from "svelte";
|
|
2
1
|
import { type Tab } from "./Tabs.svelte";
|
|
3
2
|
import type { SelectData } from "@gradio/utils";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
3
|
+
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
4
|
+
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
5
|
+
$$bindings?: Bindings;
|
|
6
|
+
} & Exports;
|
|
7
|
+
(internal: unknown, props: Props & {
|
|
8
|
+
$$events?: Events;
|
|
9
|
+
$$slots?: Slots;
|
|
10
|
+
}): Exports & {
|
|
11
|
+
$set?: any;
|
|
12
|
+
$on?: any;
|
|
11
13
|
};
|
|
12
|
-
|
|
13
|
-
change: CustomEvent<undefined>;
|
|
14
|
-
select: CustomEvent<SelectData>;
|
|
15
|
-
} & {
|
|
16
|
-
[evt: string]: CustomEvent<any>;
|
|
17
|
-
};
|
|
18
|
-
slots: {
|
|
19
|
-
default: {};
|
|
20
|
-
};
|
|
21
|
-
exports?: {} | undefined;
|
|
22
|
-
bindings?: string | undefined;
|
|
23
|
-
};
|
|
24
|
-
export type WalkthroughProps = typeof __propDef.props;
|
|
25
|
-
export type WalkthroughEvents = typeof __propDef.events;
|
|
26
|
-
export type WalkthroughSlots = typeof __propDef.slots;
|
|
27
|
-
export default class Walkthrough extends SvelteComponent<WalkthroughProps, WalkthroughEvents, WalkthroughSlots> {
|
|
14
|
+
z_$$bindings?: Bindings;
|
|
28
15
|
}
|
|
29
|
-
|
|
16
|
+
type $$__sveltets_2_PropsWithChildren<Props, Slots> = Props & (Slots extends {
|
|
17
|
+
default: any;
|
|
18
|
+
} ? Props extends Record<string, never> ? any : {
|
|
19
|
+
children?: any;
|
|
20
|
+
} : {});
|
|
21
|
+
declare const Walkthrough: $$__sveltets_2_IsomorphicComponent<$$__sveltets_2_PropsWithChildren<{
|
|
22
|
+
visible?: boolean | "hidden";
|
|
23
|
+
elem_id?: string;
|
|
24
|
+
elem_classes?: string[];
|
|
25
|
+
selected: number | string;
|
|
26
|
+
initial_tabs: Tab[];
|
|
27
|
+
}, {
|
|
28
|
+
default: {};
|
|
29
|
+
}>, {
|
|
30
|
+
change: CustomEvent<undefined>;
|
|
31
|
+
select: CustomEvent<SelectData>;
|
|
32
|
+
} & {
|
|
33
|
+
[evt: string]: CustomEvent<any>;
|
|
34
|
+
}, {
|
|
35
|
+
default: {};
|
|
36
|
+
}, {}, string>;
|
|
37
|
+
type Walkthrough = InstanceType<typeof Walkthrough>;
|
|
38
|
+
export default Walkthrough;
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { SelectData } from "@gradio/utils";
|
|
2
|
+
import type { Tab } from "./shared/Tabs.svelte";
|
|
3
|
+
export interface TabsProps {
|
|
4
|
+
visible: boolean | "hidden";
|
|
5
|
+
elem_id: string;
|
|
6
|
+
elem_classes: string[];
|
|
7
|
+
selected: number | string;
|
|
8
|
+
initial_tabs: Tab[];
|
|
9
|
+
name: "tabs" | "walkthrough";
|
|
10
|
+
}
|
|
11
|
+
export interface TabsEvents {
|
|
12
|
+
change: never;
|
|
13
|
+
select: SelectData;
|
|
14
|
+
}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gradio/tabs",
|
|
3
|
-
"version": "0.5.0",
|
|
3
|
+
"version": "0.5.2-dev.0",
|
|
4
4
|
"description": "Gradio UI packages",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "",
|
|
@@ -17,13 +17,13 @@
|
|
|
17
17
|
"./package.json": "./package.json"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@gradio/utils": "^0.10.
|
|
20
|
+
"@gradio/utils": "^0.10.3-dev.0"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
|
-
"@gradio/preview": "^0.
|
|
23
|
+
"@gradio/preview": "^0.15.0-dev.0"
|
|
24
24
|
},
|
|
25
25
|
"peerDependencies": {
|
|
26
|
-
"svelte": "^
|
|
26
|
+
"svelte": "^5.43.4"
|
|
27
27
|
},
|
|
28
28
|
"repository": {
|
|
29
29
|
"type": "git",
|
package/shared/Tabs.svelte
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
label: string;
|
|
6
6
|
id: string | number;
|
|
7
7
|
elem_id: string | undefined;
|
|
8
|
-
visible: boolean;
|
|
8
|
+
visible: boolean | "hidden";
|
|
9
9
|
interactive: boolean;
|
|
10
10
|
scale: number | null;
|
|
11
11
|
}
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
import { writable } from "svelte/store";
|
|
18
18
|
import type { SelectData } from "@gradio/utils";
|
|
19
19
|
|
|
20
|
-
export let visible = true;
|
|
20
|
+
export let visible: boolean | "hidden" = true;
|
|
21
21
|
export let elem_id = "";
|
|
22
22
|
export let elem_classes: string[] = [];
|
|
23
23
|
export let selected: number | string;
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
register_tab: (tab: Tab, order: number) => {
|
|
61
61
|
tabs[order] = tab;
|
|
62
62
|
|
|
63
|
-
if ($selected_tab === false && tab.visible && tab.interactive) {
|
|
63
|
+
if ($selected_tab === false && tab.visible !== false && tab.interactive) {
|
|
64
64
|
$selected_tab = tab.id;
|
|
65
65
|
$selected_tab_index = order;
|
|
66
66
|
}
|
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
id !== undefined &&
|
|
83
83
|
tab_to_activate &&
|
|
84
84
|
tab_to_activate.interactive &&
|
|
85
|
-
tab_to_activate.visible &&
|
|
85
|
+
tab_to_activate.visible !== false &&
|
|
86
86
|
$selected_tab !== tab_to_activate.id
|
|
87
87
|
) {
|
|
88
88
|
selected = id;
|
|
@@ -93,8 +93,8 @@
|
|
|
93
93
|
}
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
-
$: tabs, selected !== null && change_tab(selected);
|
|
97
|
-
$: tabs, tab_nav_el, tab_els, handle_menu_overflow();
|
|
96
|
+
$: (tabs, selected !== null && change_tab(selected));
|
|
97
|
+
$: (tabs, tab_nav_el, tab_els, handle_menu_overflow());
|
|
98
98
|
|
|
99
99
|
function handle_outside_click(event: MouseEvent): void {
|
|
100
100
|
if (
|
|
@@ -168,7 +168,8 @@
|
|
|
168
168
|
|
|
169
169
|
<div
|
|
170
170
|
class="tabs {elem_classes.join(' ')}"
|
|
171
|
-
class:hide={
|
|
171
|
+
class:hide={visible === false}
|
|
172
|
+
class:hidden={visible === "hidden"}
|
|
172
173
|
id={elem_id}
|
|
173
174
|
style:flex-grow={tab_scale}
|
|
174
175
|
>
|
|
@@ -176,7 +177,7 @@
|
|
|
176
177
|
<div class="tab-wrapper">
|
|
177
178
|
<div class="tab-container visually-hidden" aria-hidden="true">
|
|
178
179
|
{#each tabs as t, i}
|
|
179
|
-
{#if t?.visible}
|
|
180
|
+
{#if t && t?.visible !== false && t?.visible !== "hidden"}
|
|
180
181
|
<button bind:this={tab_els[t.id]}>
|
|
181
182
|
{t?.label}
|
|
182
183
|
</button>
|
|
@@ -185,7 +186,7 @@
|
|
|
185
186
|
</div>
|
|
186
187
|
<div class="tab-container" bind:this={tab_nav_el} role="tablist">
|
|
187
188
|
{#each visible_tabs as t, i}
|
|
188
|
-
{#if t?.visible}
|
|
189
|
+
{#if t && t?.visible !== false}
|
|
189
190
|
<button
|
|
190
191
|
role="tab"
|
|
191
192
|
class:selected={t.id === $selected_tab}
|
|
@@ -198,7 +199,7 @@
|
|
|
198
199
|
on:click={() => {
|
|
199
200
|
if (t.id !== $selected_tab) {
|
|
200
201
|
change_tab(t.id);
|
|
201
|
-
dispatch("select", { value: t.label, index: i });
|
|
202
|
+
dispatch("select", { value: t.label, index: i, id: t.id });
|
|
202
203
|
}
|
|
203
204
|
}}
|
|
204
205
|
>
|
|
@@ -209,7 +210,8 @@
|
|
|
209
210
|
</div>
|
|
210
211
|
<span
|
|
211
212
|
class="overflow-menu"
|
|
212
|
-
class:hide={!is_overflowing ||
|
|
213
|
+
class:hide={!is_overflowing ||
|
|
214
|
+
!overflow_tabs.some((t) => t?.visible !== false)}
|
|
213
215
|
bind:this={overflow_menu}
|
|
214
216
|
>
|
|
215
217
|
<button
|
|
@@ -221,7 +223,7 @@
|
|
|
221
223
|
</button>
|
|
222
224
|
<div class="overflow-dropdown" class:hide={!overflow_menu_open}>
|
|
223
225
|
{#each overflow_tabs as t}
|
|
224
|
-
{#if t?.visible}
|
|
226
|
+
{#if t?.visible !== false}
|
|
225
227
|
<button
|
|
226
228
|
on:click={() => change_tab(t?.id)}
|
|
227
229
|
class:selected={t?.id === $selected_tab}
|
|
@@ -249,6 +251,10 @@
|
|
|
249
251
|
display: none;
|
|
250
252
|
}
|
|
251
253
|
|
|
254
|
+
.hidden {
|
|
255
|
+
display: none !important;
|
|
256
|
+
}
|
|
257
|
+
|
|
252
258
|
.tab-wrapper {
|
|
253
259
|
display: flex;
|
|
254
260
|
align-items: center;
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
import { writable } from "svelte/store";
|
|
8
8
|
import type { SelectData } from "@gradio/utils";
|
|
9
9
|
|
|
10
|
-
export let visible = true;
|
|
10
|
+
export let visible: boolean | "hidden" = true;
|
|
11
11
|
export let elem_id = "";
|
|
12
12
|
export let elem_classes: string[] = [];
|
|
13
13
|
export let selected: number | string;
|
|
@@ -138,14 +138,14 @@
|
|
|
138
138
|
}
|
|
139
139
|
}
|
|
140
140
|
|
|
141
|
-
$: tabs,
|
|
141
|
+
$: (tabs,
|
|
142
142
|
selected !== null &&
|
|
143
143
|
change_tab(
|
|
144
144
|
selected,
|
|
145
145
|
tabs.findIndex((t) => t?.id === selected)
|
|
146
|
-
);
|
|
147
|
-
$: tabs, check_overflow();
|
|
148
|
-
$: $selected_tab_index, check_overflow();
|
|
146
|
+
));
|
|
147
|
+
$: (tabs, check_overflow());
|
|
148
|
+
$: ($selected_tab_index, check_overflow());
|
|
149
149
|
|
|
150
150
|
$: tab_scale =
|
|
151
151
|
tabs[$selected_tab_index >= 0 ? $selected_tab_index : 0]?.scale;
|
package/types.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { SelectData } from "@gradio/utils";
|
|
2
|
+
import type { Tab } from "./shared/Tabs.svelte";
|
|
3
|
+
|
|
4
|
+
export interface TabsProps {
|
|
5
|
+
visible: boolean | "hidden";
|
|
6
|
+
elem_id: string;
|
|
7
|
+
elem_classes: string[];
|
|
8
|
+
selected: number | string;
|
|
9
|
+
initial_tabs: Tab[];
|
|
10
|
+
name: "tabs" | "walkthrough";
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface TabsEvents {
|
|
14
|
+
change: never;
|
|
15
|
+
select: SelectData;
|
|
16
|
+
}
|