@gradio/tabs 0.5.1 → 0.5.2

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,4 +1,19 @@
1
1
  # @gradio/tabs
2
+ ## 0.5.2
3
+
4
+ ### Features
5
+
6
+ - [#12438](https://github.com/gradio-app/gradio/pull/12438) [`25ffc03`](https://github.com/gradio-app/gradio/commit/25ffc0398f8feb43d817c02b2ab970c16de6d797) - Svelte5 migration and bugfix
7
+
8
+ ### Dependencies
9
+
10
+ - @gradio/utils@0.10.3
11
+
12
+ ## 0.5.2-dev.0
13
+
14
+ ### Dependency updates
15
+
16
+ - @gradio/utils@0.10.3-dev.0
2
17
 
3
18
  ## 0.5.1
4
19
 
package/Index.svelte CHANGED
@@ -3,50 +3,44 @@
3
3
  </script>
4
4
 
5
5
  <script lang="ts">
6
- import type { Gradio, SelectData } from "@gradio/utils";
7
- import { createEventDispatcher } from "svelte";
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
- const dispatch = createEventDispatcher();
11
+ let props = $props();
12
+ const gradio = new Gradio<TabsEvents, TabsProps>(props);
12
13
 
13
- export let visible: boolean | "hidden" = true;
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
- $: dispatch("prop_change", { selected });
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?.dispatch("change")}
36
- on:select={(e) => gradio?.dispatch("select", e.detail)}
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?.dispatch("change")}
48
- on:select={(e) => gradio?.dispatch("select", e.detail)}
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">export { default as BaseTabs, TABS } from "./shared/Tabs.svelte";
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>import { createEventDispatcher } from "svelte";
5
- import Tabs, {} from "./shared/Tabs.svelte";
6
- import Walkthrough from "./shared/Walkthrough.svelte";
7
- const dispatch = createEventDispatcher();
8
- export let visible = true;
9
- export let elem_id = "";
10
- export let elem_classes = [];
11
- export let selected;
12
- export let initial_tabs = [];
13
- export let name = "tabs";
14
- export let gradio;
15
- $: dispatch("prop_change", { selected });
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?.dispatch("change")}
25
- on:select={(e) => gradio?.dispatch("select", e.detail)}
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?.dispatch("change")}
37
- on:select={(e) => gradio?.dispatch("select", e.detail)}
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>
@@ -1,33 +1,21 @@
1
- import { SvelteComponent } from "svelte";
2
1
  export { default as BaseTabs, TABS, type Tab } from "./shared/Tabs.svelte";
3
- import type { Gradio, SelectData } from "@gradio/utils";
4
- import { type Tab } from "./shared/Tabs.svelte";
5
- declare const __propDef: {
6
- props: {
7
- visible?: boolean | "hidden";
8
- elem_id?: string;
9
- elem_classes?: string[];
10
- selected: number | string;
11
- initial_tabs?: Tab[];
12
- name?: "tabs" | "walkthrough";
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
- events: {
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
- /** @typedef {typeof __propDef.props} OverflowIconProps */
2
- /** @typedef {typeof __propDef.events} OverflowIconEvents */
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
- export {};
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
+ }
@@ -1,110 +1,164 @@
1
- <script context="module">export const TABS = {};
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>import { setContext, createEventDispatcher, tick, onMount } from "svelte";
5
- import OverflowIcon from "./OverflowIcon.svelte";
6
- import { writable } from "svelte/store";
7
- export let visible = true;
8
- export let elem_id = "";
9
- export let elem_classes = [];
10
- export let selected;
11
- export let initial_tabs;
12
- let tabs = [...initial_tabs];
13
- let visible_tabs = [...initial_tabs];
14
- let overflow_tabs = [];
15
- let overflow_menu_open = false;
16
- let overflow_menu;
17
- $: has_tabs = tabs.length > 0;
18
- let tab_nav_el;
19
- const selected_tab = writable(
20
- selected || tabs[0]?.id || false
21
- );
22
- const selected_tab_index = writable(
23
- tabs.findIndex((t) => t?.id === selected) || 0
24
- );
25
- const dispatch = createEventDispatcher();
26
- let is_overflowing = false;
27
- let overflow_has_selected_tab = false;
28
- let tab_els = {};
29
- onMount(() => {
30
- if (!tab_nav_el) return;
31
- const observer = new IntersectionObserver((entries) => {
32
- handle_menu_overflow();
33
- });
34
- observer.observe(tab_nav_el);
35
- });
36
- setContext(TABS, {
37
- register_tab: (tab, order) => {
38
- tabs[order] = tab;
39
- if ($selected_tab === false && tab.visible !== false && tab.interactive) {
40
- $selected_tab = tab.id;
41
- $selected_tab_index = order;
42
- }
43
- return order;
44
- },
45
- unregister_tab: (tab, order) => {
46
- if ($selected_tab === tab.id) {
47
- $selected_tab = tabs[0]?.id || false;
48
- }
49
- tabs[order] = null;
50
- },
51
- selected_tab,
52
- selected_tab_index
53
- });
54
- function change_tab(id) {
55
- const tab_to_activate = tabs.find((t) => t?.id === id);
56
- if (id !== void 0 && tab_to_activate && tab_to_activate.interactive && tab_to_activate.visible !== false && $selected_tab !== tab_to_activate.id) {
57
- selected = id;
58
- $selected_tab = id;
59
- $selected_tab_index = tabs.findIndex((t) => t?.id === id);
60
- dispatch("change");
61
- overflow_menu_open = false;
62
- }
63
- }
64
- $: tabs, selected !== null && change_tab(selected);
65
- $: tabs, tab_nav_el, tab_els, handle_menu_overflow();
66
- function handle_outside_click(event) {
67
- if (overflow_menu_open && overflow_menu && !overflow_menu.contains(event.target)) {
68
- overflow_menu_open = false;
69
- }
70
- }
71
- async function handle_menu_overflow() {
72
- if (!tab_nav_el) return;
73
- await tick();
74
- const tab_nav_size = tab_nav_el.getBoundingClientRect();
75
- let max_width = tab_nav_size.width;
76
- const tab_sizes = get_tab_sizes(tabs, tab_els);
77
- let last_visible_index = 0;
78
- const offset = tab_nav_size.left;
79
- for (let i = tabs.length - 1; i >= 0; i--) {
80
- const tab = tabs[i];
81
- if (!tab) continue;
82
- const tab_rect = tab_sizes[tab.id];
83
- if (!tab_rect) continue;
84
- if (tab_rect.right - offset < max_width) {
85
- last_visible_index = i;
86
- break;
87
- }
88
- }
89
- overflow_tabs = tabs.slice(last_visible_index + 1);
90
- visible_tabs = tabs.slice(0, last_visible_index + 1);
91
- overflow_has_selected_tab = handle_overflow_has_selected_tab($selected_tab);
92
- is_overflowing = overflow_tabs.length > 0;
93
- }
94
- $: overflow_has_selected_tab = handle_overflow_has_selected_tab($selected_tab);
95
- function handle_overflow_has_selected_tab(selected_tab2) {
96
- if (selected_tab2 === false) return false;
97
- return overflow_tabs.some((t) => t?.id === selected_tab2);
98
- }
99
- function get_tab_sizes(tabs2, tab_els2) {
100
- const tab_sizes = {};
101
- tabs2.forEach((tab) => {
102
- if (!tab) return;
103
- tab_sizes[tab.id] = tab_els2[tab.id]?.getBoundingClientRect();
104
- });
105
- return tab_sizes;
106
- }
107
- $: tab_scale = tabs[$selected_tab_index >= 0 ? $selected_tab_index : 0]?.scale;
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
@@ -145,7 +199,7 @@ $: tab_scale = tabs[$selected_tab_index >= 0 ? $selected_tab_index : 0]?.scale;
145
199
  on:click={() => {
146
200
  if (t.id !== $selected_tab) {
147
201
  change_tab(t.id);
148
- dispatch("select", { value: t.label, index: i });
202
+ dispatch("select", { value: t.label, index: i, id: t.id });
149
203
  }
150
204
  }}
151
205
  >
@@ -1,4 +1,3 @@
1
- import { SvelteComponent } from "svelte";
2
1
  export declare const TABS: {};
3
2
  export interface Tab {
4
3
  label: string;
@@ -9,29 +8,39 @@ export interface Tab {
9
8
  scale: number | null;
10
9
  }
11
10
  import type { SelectData } from "@gradio/utils";
12
- declare const __propDef: {
13
- props: {
14
- visible?: boolean | "hidden";
15
- elem_id?: string;
16
- elem_classes?: string[];
17
- selected: number | string;
18
- initial_tabs: Tab[];
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
- events: {
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
- export {};
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">import { TABS } from "./Tabs.svelte";
1
+ <script context="module" lang="ts">
2
+ import { TABS, type Tab } from "./Tabs.svelte";
2
3
  </script>
3
4
 
4
- <script>import { setContext, createEventDispatcher, tick, onMount } from "svelte";
5
- import { writable } from "svelte/store";
6
- export let visible = true;
7
- export let elem_id = "";
8
- export let elem_classes = [];
9
- export let selected;
10
- export let initial_tabs;
11
- let tabs = [...initial_tabs];
12
- let stepper_container;
13
- let show_labels_for_all = true;
14
- let measurement_container;
15
- let step_buttons = [];
16
- let step_labels = [];
17
- let label_height = 0;
18
- let compact = false;
19
- let recompute_overflow = true;
20
- $: has_tabs = tabs.length > 0;
21
- const selected_tab = writable(
22
- selected || tabs[0]?.id || false
23
- );
24
- const selected_tab_index = writable(
25
- tabs.findIndex((t) => t?.id === selected) || 0
26
- );
27
- const dispatch = createEventDispatcher();
28
- async function check_overflow() {
29
- if (!stepper_container || !measurement_container || !recompute_overflow)
30
- return;
31
- recompute_overflow = false;
32
- await tick();
33
- show_labels_for_all = true;
34
- await tick();
35
- const SEP_WIDTH = 50;
36
- const button_width = step_buttons[0].getBoundingClientRect().width * step_buttons.length + SEP_WIDTH * (step_buttons.length - 1);
37
- const containerWidth = stepper_container.getBoundingClientRect().width;
38
- const does_it_fit = button_width < containerWidth;
39
- if (!does_it_fit) {
40
- show_labels_for_all = false;
41
- compact = true;
42
- return;
43
- }
44
- let max_height = 0;
45
- let is_overlapping = false;
46
- let last_right = 0;
47
- for (const label of step_labels) {
48
- const { height, width, left, right } = label.getBoundingClientRect();
49
- if (height > max_height) {
50
- max_height = height;
51
- }
52
- if (last_right && left - 10 < last_right && !is_overlapping) {
53
- is_overlapping = true;
54
- }
55
- last_right = right;
56
- }
57
- label_height = max_height;
58
- if (is_overlapping) {
59
- show_labels_for_all = false;
60
- }
61
- }
62
- let last_width = 0;
63
- onMount(() => {
64
- check_overflow();
65
- const observer = new ResizeObserver((entries) => {
66
- if (entries[0].contentRect.width === last_width) return;
67
- last_width = entries[0].contentRect.width;
68
- compact = false;
69
- recompute_overflow = true;
70
- check_overflow();
71
- });
72
- if (stepper_container) {
73
- observer.observe(stepper_container);
74
- }
75
- return () => {
76
- observer.disconnect();
77
- };
78
- });
79
- setContext(TABS, {
80
- register_tab: (tab, order) => {
81
- tabs[order] = tab;
82
- if ($selected_tab === false && tab.visible && tab.interactive) {
83
- $selected_tab = tab.id;
84
- $selected_tab_index = order;
85
- }
86
- return order;
87
- },
88
- unregister_tab: (tab, order) => {
89
- if ($selected_tab === tab.id) {
90
- $selected_tab = tabs[0]?.id || false;
91
- }
92
- tabs[order] = null;
93
- },
94
- selected_tab,
95
- selected_tab_index
96
- });
97
- function change_tab(id, index) {
98
- const tab_to_activate = tabs.find((t) => t?.id === id);
99
- if (id !== void 0 && tab_to_activate && tab_to_activate.interactive && tab_to_activate.visible && $selected_tab !== tab_to_activate.id) {
100
- selected = id;
101
- $selected_tab = id;
102
- $selected_tab_index = tabs.findIndex((t) => t?.id === id);
103
- dispatch("change");
104
- }
105
- }
106
- $: tabs, selected !== null && change_tab(
107
- selected,
108
- tabs.findIndex((t) => t?.id === selected)
109
- );
110
- $: tabs, check_overflow();
111
- $: $selected_tab_index, check_overflow();
112
- $: tab_scale = tabs[$selected_tab_index >= 0 ? $selected_tab_index : 0]?.scale;
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
- declare const __propDef: {
5
- props: {
6
- visible?: boolean | "hidden";
7
- elem_id?: string;
8
- elem_classes?: string[];
9
- selected: number | string;
10
- initial_tabs: Tab[];
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
- events: {
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
- export {};
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;
@@ -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.1",
3
+ "version": "0.5.2",
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.2"
20
+ "@gradio/utils": "^0.10.3"
21
21
  },
22
22
  "devDependencies": {
23
- "@gradio/preview": "^0.14.0"
23
+ "@gradio/preview": "^0.15.0"
24
24
  },
25
25
  "peerDependencies": {
26
- "svelte": "^4.0.0"
26
+ "svelte": "^5.43.4"
27
27
  },
28
28
  "repository": {
29
29
  "type": "git",
@@ -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 (
@@ -199,7 +199,7 @@
199
199
  on:click={() => {
200
200
  if (t.id !== $selected_tab) {
201
201
  change_tab(t.id);
202
- dispatch("select", { value: t.label, index: i });
202
+ dispatch("select", { value: t.label, index: i, id: t.id });
203
203
  }
204
204
  }}
205
205
  >
@@ -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
+ }