@gradio/tabs 0.4.5 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @gradio/tabs
2
2
 
3
+ ## 0.5.1
4
+
5
+ ### Fixes
6
+
7
+ - [#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!
8
+
9
+ ## 0.5.0
10
+
11
+ ### Features
12
+
13
+ - [#11783](https://github.com/gradio-app/gradio/pull/11783) [`f407daf`](https://github.com/gradio-app/gradio/commit/f407daf8046f37e042ab8b86730ff0ab8d174bcf) - Add Walkthrough and Step compoents to facilitate multi-step workflows. Thanks @pngwn!
14
+
3
15
  ## 0.4.5
4
16
 
5
17
  ### Fixes
package/Index.svelte CHANGED
@@ -6,14 +6,16 @@
6
6
  import type { Gradio, SelectData } from "@gradio/utils";
7
7
  import { createEventDispatcher } from "svelte";
8
8
  import Tabs, { type Tab } from "./shared/Tabs.svelte";
9
+ import Walkthrough from "./shared/Walkthrough.svelte";
9
10
 
10
11
  const dispatch = createEventDispatcher();
11
12
 
12
- export let visible = true;
13
+ export let visible: boolean | "hidden" = true;
13
14
  export let elem_id = "";
14
15
  export let elem_classes: string[] = [];
15
16
  export let selected: number | string;
16
17
  export let initial_tabs: Tab[] = [];
18
+ export let name: "tabs" | "walkthrough" = "tabs";
17
19
  export let gradio:
18
20
  | Gradio<{
19
21
  change: never;
@@ -24,14 +26,28 @@
24
26
  $: dispatch("prop_change", { selected });
25
27
  </script>
26
28
 
27
- <Tabs
28
- {visible}
29
- {elem_id}
30
- {elem_classes}
31
- bind:selected
32
- on:change={() => gradio?.dispatch("change")}
33
- on:select={(e) => gradio?.dispatch("select", e.detail)}
34
- {initial_tabs}
35
- >
36
- <slot />
37
- </Tabs>
29
+ {#if name === "walkthrough"}
30
+ <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}
38
+ >
39
+ <slot />
40
+ </Walkthrough>
41
+ {:else}
42
+ <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}
50
+ >
51
+ <slot />
52
+ </Tabs>
53
+ {/if}
@@ -0,0 +1,116 @@
1
+ <script>
2
+ import { Meta, Template, Story } from "@storybook/addon-svelte-csf";
3
+ import Tabs from "./Index.svelte";
4
+ import TabItem from "../tabitem/Index.svelte";
5
+ </script>
6
+
7
+ <Meta title="Components/Walkthrough" component={Tabs} />
8
+
9
+ <Template let:args>
10
+ <Tabs {...args} name="walkthrough">
11
+ <TabItem
12
+ order={0}
13
+ id="tab-1"
14
+ label="Image Tab"
15
+ gradio={undefined}
16
+ visible
17
+ interactive
18
+ elem_classes={["editor-tabitem"]}
19
+ scale={0}
20
+ >
21
+ <img
22
+ style="width: 200px;"
23
+ alt="Cheetah"
24
+ src="https://gradio-builds.s3.amazonaws.com/demo-files/ghepardo-primo-piano.jpg"
25
+ />
26
+ </TabItem>
27
+ <TabItem
28
+ order={1}
29
+ id="tab-2"
30
+ label="Hidden Tab"
31
+ gradio={undefined}
32
+ visible={false}
33
+ interactive
34
+ elem_classes={["editor-tabitem"]}
35
+ scale={0}
36
+ >
37
+ Secret Tab
38
+ </TabItem>
39
+ <TabItem
40
+ order={2}
41
+ id="tab-3"
42
+ label="Visible Tab"
43
+ gradio={undefined}
44
+ visible
45
+ interactive
46
+ elem_classes={["editor-tabitem"]}
47
+ scale={0}
48
+ >
49
+ Visible Tab
50
+ </TabItem>
51
+ <TabItem
52
+ order={3}
53
+ id="tab-4"
54
+ label="Visible Tab"
55
+ gradio={undefined}
56
+ visible
57
+ interactive
58
+ elem_classes={["editor-tabitem"]}
59
+ scale={0}
60
+ >
61
+ Visible Tab
62
+ </TabItem>
63
+ </Tabs>
64
+ </Template>
65
+
66
+ <Story name="Tabs Walkthrough" args={{}} />
67
+
68
+ <Story name="TabsLastInvisible" args={{}}>
69
+ <Tabs selected="tab-1" gradio={undefined} name="walkthrough">
70
+ <TabItem
71
+ order={0}
72
+ id="tab-1"
73
+ label="This is visible tab 1"
74
+ gradio={undefined}
75
+ visible
76
+ interactive
77
+ scale={0}
78
+ ></TabItem>
79
+ <TabItem
80
+ order={1}
81
+ id="tab-2"
82
+ label="This is visible tab 2"
83
+ gradio={undefined}
84
+ visible
85
+ interactive
86
+ scale={0}
87
+ ></TabItem>
88
+ <TabItem
89
+ order={2}
90
+ id="tab-3"
91
+ label="This is visible tab 3"
92
+ gradio={undefined}
93
+ visible
94
+ interactive
95
+ scale={0}
96
+ ></TabItem>
97
+ <TabItem
98
+ order={3}
99
+ id="tab-4"
100
+ label="This is invisible tab 4"
101
+ gradio={undefined}
102
+ visible={false}
103
+ interactive
104
+ scale={0}
105
+ ></TabItem>
106
+ <TabItem
107
+ order={4}
108
+ id="tab-5"
109
+ label="This is invisible tab 5"
110
+ gradio={undefined}
111
+ visible={false}
112
+ interactive
113
+ scale={0}
114
+ ></TabItem>
115
+ </Tabs>
116
+ </Story>
package/dist/Index.svelte CHANGED
@@ -3,25 +3,40 @@
3
3
 
4
4
  <script>import { createEventDispatcher } from "svelte";
5
5
  import Tabs, {} from "./shared/Tabs.svelte";
6
+ import Walkthrough from "./shared/Walkthrough.svelte";
6
7
  const dispatch = createEventDispatcher();
7
8
  export let visible = true;
8
9
  export let elem_id = "";
9
10
  export let elem_classes = [];
10
11
  export let selected;
11
12
  export let initial_tabs = [];
13
+ export let name = "tabs";
12
14
  export let gradio;
13
- $:
14
- dispatch("prop_change", { selected });
15
+ $: dispatch("prop_change", { selected });
15
16
  </script>
16
17
 
17
- <Tabs
18
- {visible}
19
- {elem_id}
20
- {elem_classes}
21
- bind:selected
22
- on:change={() => gradio?.dispatch("change")}
23
- on:select={(e) => gradio?.dispatch("select", e.detail)}
24
- {initial_tabs}
25
- >
26
- <slot />
27
- </Tabs>
18
+ {#if name === "walkthrough"}
19
+ <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}
27
+ >
28
+ <slot />
29
+ </Walkthrough>
30
+ {:else}
31
+ <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}
39
+ >
40
+ <slot />
41
+ </Tabs>
42
+ {/if}
@@ -4,11 +4,12 @@ import type { Gradio, SelectData } from "@gradio/utils";
4
4
  import { type Tab } from "./shared/Tabs.svelte";
5
5
  declare const __propDef: {
6
6
  props: {
7
- visible?: boolean | undefined;
8
- elem_id?: string | undefined;
9
- elem_classes?: string[] | undefined;
7
+ visible?: boolean | "hidden";
8
+ elem_id?: string;
9
+ elem_classes?: string[];
10
10
  selected: number | string;
11
- initial_tabs?: Tab[] | undefined;
11
+ initial_tabs?: Tab[];
12
+ name?: "tabs" | "walkthrough";
12
13
  gradio: Gradio<{
13
14
  change: never;
14
15
  select: SelectData;
@@ -22,6 +23,8 @@ declare const __propDef: {
22
23
  slots: {
23
24
  default: {};
24
25
  };
26
+ exports?: {} | undefined;
27
+ bindings?: string | undefined;
25
28
  };
26
29
  export type IndexProps = typeof __propDef.props;
27
30
  export type IndexEvents = typeof __propDef.events;
@@ -19,5 +19,7 @@ declare const __propDef: {
19
19
  [evt: string]: CustomEvent<any>;
20
20
  };
21
21
  slots: {};
22
+ exports?: undefined;
23
+ bindings?: undefined;
22
24
  };
23
25
  export {};
@@ -14,8 +14,7 @@ let visible_tabs = [...initial_tabs];
14
14
  let overflow_tabs = [];
15
15
  let overflow_menu_open = false;
16
16
  let overflow_menu;
17
- $:
18
- has_tabs = tabs.length > 0;
17
+ $: has_tabs = tabs.length > 0;
19
18
  let tab_nav_el;
20
19
  const selected_tab = writable(
21
20
  selected || tabs[0]?.id || false
@@ -28,6 +27,7 @@ let is_overflowing = false;
28
27
  let overflow_has_selected_tab = false;
29
28
  let tab_els = {};
30
29
  onMount(() => {
30
+ if (!tab_nav_el) return;
31
31
  const observer = new IntersectionObserver((entries) => {
32
32
  handle_menu_overflow();
33
33
  });
@@ -36,7 +36,7 @@ onMount(() => {
36
36
  setContext(TABS, {
37
37
  register_tab: (tab, order) => {
38
38
  tabs[order] = tab;
39
- if ($selected_tab === false && tab.visible && tab.interactive) {
39
+ if ($selected_tab === false && tab.visible !== false && tab.interactive) {
40
40
  $selected_tab = tab.id;
41
41
  $selected_tab_index = order;
42
42
  }
@@ -53,7 +53,7 @@ setContext(TABS, {
53
53
  });
54
54
  function change_tab(id) {
55
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 && $selected_tab !== tab_to_activate.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
57
  selected = id;
58
58
  $selected_tab = id;
59
59
  $selected_tab_index = tabs.findIndex((t) => t?.id === id);
@@ -61,18 +61,15 @@ function change_tab(id) {
61
61
  overflow_menu_open = false;
62
62
  }
63
63
  }
64
- $:
65
- tabs, selected !== null && change_tab(selected);
66
- $:
67
- tabs, tab_nav_el, tab_els, handle_menu_overflow();
64
+ $: tabs, selected !== null && change_tab(selected);
65
+ $: tabs, tab_nav_el, tab_els, handle_menu_overflow();
68
66
  function handle_outside_click(event) {
69
67
  if (overflow_menu_open && overflow_menu && !overflow_menu.contains(event.target)) {
70
68
  overflow_menu_open = false;
71
69
  }
72
70
  }
73
71
  async function handle_menu_overflow() {
74
- if (!tab_nav_el)
75
- return;
72
+ if (!tab_nav_el) return;
76
73
  await tick();
77
74
  const tab_nav_size = tab_nav_el.getBoundingClientRect();
78
75
  let max_width = tab_nav_size.width;
@@ -81,11 +78,9 @@ async function handle_menu_overflow() {
81
78
  const offset = tab_nav_size.left;
82
79
  for (let i = tabs.length - 1; i >= 0; i--) {
83
80
  const tab = tabs[i];
84
- if (!tab)
85
- continue;
81
+ if (!tab) continue;
86
82
  const tab_rect = tab_sizes[tab.id];
87
- if (!tab_rect)
88
- continue;
83
+ if (!tab_rect) continue;
89
84
  if (tab_rect.right - offset < max_width) {
90
85
  last_visible_index = i;
91
86
  break;
@@ -96,24 +91,20 @@ async function handle_menu_overflow() {
96
91
  overflow_has_selected_tab = handle_overflow_has_selected_tab($selected_tab);
97
92
  is_overflowing = overflow_tabs.length > 0;
98
93
  }
99
- $:
100
- overflow_has_selected_tab = handle_overflow_has_selected_tab($selected_tab);
94
+ $: overflow_has_selected_tab = handle_overflow_has_selected_tab($selected_tab);
101
95
  function handle_overflow_has_selected_tab(selected_tab2) {
102
- if (selected_tab2 === false)
103
- return false;
96
+ if (selected_tab2 === false) return false;
104
97
  return overflow_tabs.some((t) => t?.id === selected_tab2);
105
98
  }
106
99
  function get_tab_sizes(tabs2, tab_els2) {
107
100
  const tab_sizes = {};
108
101
  tabs2.forEach((tab) => {
109
- if (!tab)
110
- return;
102
+ if (!tab) return;
111
103
  tab_sizes[tab.id] = tab_els2[tab.id]?.getBoundingClientRect();
112
104
  });
113
105
  return tab_sizes;
114
106
  }
115
- $:
116
- tab_scale = tabs[$selected_tab_index >= 0 ? $selected_tab_index : 0]?.scale;
107
+ $: tab_scale = tabs[$selected_tab_index >= 0 ? $selected_tab_index : 0]?.scale;
117
108
  </script>
118
109
 
119
110
  <svelte:window
@@ -123,7 +114,8 @@ $:
123
114
 
124
115
  <div
125
116
  class="tabs {elem_classes.join(' ')}"
126
- class:hide={!visible}
117
+ class:hide={visible === false}
118
+ class:hidden={visible === "hidden"}
127
119
  id={elem_id}
128
120
  style:flex-grow={tab_scale}
129
121
  >
@@ -131,7 +123,7 @@ $:
131
123
  <div class="tab-wrapper">
132
124
  <div class="tab-container visually-hidden" aria-hidden="true">
133
125
  {#each tabs as t, i}
134
- {#if t?.visible}
126
+ {#if t && t?.visible !== false && t?.visible !== "hidden"}
135
127
  <button bind:this={tab_els[t.id]}>
136
128
  {t?.label}
137
129
  </button>
@@ -140,7 +132,7 @@ $:
140
132
  </div>
141
133
  <div class="tab-container" bind:this={tab_nav_el} role="tablist">
142
134
  {#each visible_tabs as t, i}
143
- {#if t?.visible}
135
+ {#if t && t?.visible !== false}
144
136
  <button
145
137
  role="tab"
146
138
  class:selected={t.id === $selected_tab}
@@ -164,7 +156,8 @@ $:
164
156
  </div>
165
157
  <span
166
158
  class="overflow-menu"
167
- class:hide={!is_overflowing || !overflow_tabs.some((t) => t?.visible)}
159
+ class:hide={!is_overflowing ||
160
+ !overflow_tabs.some((t) => t?.visible !== false)}
168
161
  bind:this={overflow_menu}
169
162
  >
170
163
  <button
@@ -176,7 +169,7 @@ $:
176
169
  </button>
177
170
  <div class="overflow-dropdown" class:hide={!overflow_menu_open}>
178
171
  {#each overflow_tabs as t}
179
- {#if t?.visible}
172
+ {#if t?.visible !== false}
180
173
  <button
181
174
  on:click={() => change_tab(t?.id)}
182
175
  class:selected={t?.id === $selected_tab}
@@ -204,6 +197,10 @@ $:
204
197
  display: none;
205
198
  }
206
199
 
200
+ .hidden {
201
+ display: none !important;
202
+ }
203
+
207
204
  .tab-wrapper {
208
205
  display: flex;
209
206
  align-items: center;
@@ -4,16 +4,16 @@ export interface Tab {
4
4
  label: string;
5
5
  id: string | number;
6
6
  elem_id: string | undefined;
7
- visible: boolean;
7
+ visible: boolean | "hidden";
8
8
  interactive: boolean;
9
9
  scale: number | null;
10
10
  }
11
11
  import type { SelectData } from "@gradio/utils";
12
12
  declare const __propDef: {
13
13
  props: {
14
- visible?: boolean | undefined;
15
- elem_id?: string | undefined;
16
- elem_classes?: string[] | undefined;
14
+ visible?: boolean | "hidden";
15
+ elem_id?: string;
16
+ elem_classes?: string[];
17
17
  selected: number | string;
18
18
  initial_tabs: Tab[];
19
19
  };
@@ -26,6 +26,8 @@ declare const __propDef: {
26
26
  slots: {
27
27
  default: {};
28
28
  };
29
+ exports?: {} | undefined;
30
+ bindings?: string | undefined;
29
31
  };
30
32
  export type TabsProps = typeof __propDef.props;
31
33
  export type TabsEvents = typeof __propDef.events;