@gradio/tabitem 0.7.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # @gradio/tabitem
2
2
 
3
+ ## 0.8.0
4
+
5
+ ### Features
6
+
7
+ - [#13509](https://github.com/gradio-app/gradio/pull/13509) [`dcd072c`](https://github.com/gradio-app/gradio/commit/dcd072cd57f09ffd2dc5f97ae6afc505894824a6) - Migrate Chatbot, Tabs, TabItem to Svelte 5. Thanks @dawoodkhan82!
8
+
9
+ ### Dependency updates
10
+
11
+ - @gradio/tabs@0.7.0
12
+
3
13
  ## 0.7.0
4
14
 
5
15
  ### Features
package/Index.svelte CHANGED
@@ -22,7 +22,7 @@
22
22
  order={gradio.props.order}
23
23
  scale={gradio.props.scale}
24
24
  component_id={gradio.props.component_id}
25
- on:select={({ detail }) => gradio.dispatch("select", detail)}
25
+ onselect={(data) => gradio.dispatch("select", data)}
26
26
  >
27
27
  <slot />
28
28
  </TabItem>
package/TabItem.test.ts CHANGED
@@ -39,6 +39,54 @@ describe("TabItem", () => {
39
39
 
40
40
  expect(getByTestId("tab-content")).not.toBeVisible();
41
41
  });
42
+
43
+ test("uses a stable internal id when no explicit id is provided", async () => {
44
+ const on_register = vi.fn();
45
+ const { getByTestId } = await render(TabItemHarness, {
46
+ omit_id: true,
47
+ tab_selected: 1,
48
+ on_register
49
+ });
50
+
51
+ expect(getByTestId("tab-content")).toBeVisible();
52
+ await waitFor(() => {
53
+ expect(on_register).toHaveBeenCalledWith(
54
+ expect.objectContaining({ id: 1 })
55
+ );
56
+ });
57
+ });
58
+
59
+ test("keeps 0 as an explicit id", async () => {
60
+ const on_register = vi.fn();
61
+ const { getByTestId } = await render(TabItemHarness, {
62
+ tab_id: 0,
63
+ tab_selected: 0,
64
+ on_register
65
+ });
66
+
67
+ expect(getByTestId("tab-content")).toBeVisible();
68
+ await waitFor(() => {
69
+ expect(on_register).toHaveBeenCalledWith(
70
+ expect.objectContaining({ id: 0 })
71
+ );
72
+ });
73
+ });
74
+
75
+ test("keeps an empty string as an explicit id", async () => {
76
+ const on_register = vi.fn();
77
+ const { getByTestId } = await render(TabItemHarness, {
78
+ tab_id: "",
79
+ tab_selected: "",
80
+ on_register
81
+ });
82
+
83
+ expect(getByTestId("tab-content")).toBeVisible();
84
+ await waitFor(() => {
85
+ expect(on_register).toHaveBeenCalledWith(
86
+ expect.objectContaining({ id: "" })
87
+ );
88
+ });
89
+ });
42
90
  });
43
91
 
44
92
  describe("Events: select", () => {
@@ -13,7 +13,10 @@
13
13
  const selected_tab_index = writable<number>(cfg.tab_selected_index ?? 0);
14
14
 
15
15
  setContext(TABS, {
16
- register_tab: (_tab: any, order: number) => order,
16
+ register_tab: (tab: any, order: number) => {
17
+ cfg.on_register?.(tab);
18
+ return order;
19
+ },
17
20
  unregister_tab: () => {},
18
21
  selected_tab,
19
22
  selected_tab_index
@@ -22,13 +25,13 @@
22
25
 
23
26
  <BaseTabItem
24
27
  label="First Tab"
25
- id="t1"
28
+ id={cfg.omit_id ? undefined : (cfg.tab_id ?? "t1")}
26
29
  order={0}
27
30
  visible={cfg.tab_visible ?? true}
28
31
  interactive={true}
29
32
  scale={0}
30
33
  component_id={1}
31
- on:select={(e) => cfg.on_tab_select?.(e.detail)}
34
+ onselect={(data) => cfg.on_tab_select?.(data)}
32
35
  >
33
36
  <div data-testid="tab-content">tab panel content</div>
34
37
  </BaseTabItem>
package/dist/Index.svelte CHANGED
@@ -22,7 +22,7 @@
22
22
  order={gradio.props.order}
23
23
  scale={gradio.props.scale}
24
24
  component_id={gradio.props.component_id}
25
- on:select={({ detail }) => gradio.dispatch("select", detail)}
25
+ onselect={(data) => gradio.dispatch("select", data)}
26
26
  >
27
27
  <slot />
28
28
  </TabItem>
@@ -13,7 +13,10 @@
13
13
  const selected_tab_index = writable<number>(cfg.tab_selected_index ?? 0);
14
14
 
15
15
  setContext(TABS, {
16
- register_tab: (_tab: any, order: number) => order,
16
+ register_tab: (tab: any, order: number) => {
17
+ cfg.on_register?.(tab);
18
+ return order;
19
+ },
17
20
  unregister_tab: () => {},
18
21
  selected_tab,
19
22
  selected_tab_index
@@ -22,13 +25,13 @@
22
25
 
23
26
  <BaseTabItem
24
27
  label="First Tab"
25
- id="t1"
28
+ id={cfg.omit_id ? undefined : (cfg.tab_id ?? "t1")}
26
29
  order={0}
27
30
  visible={cfg.tab_visible ?? true}
28
31
  interactive={true}
29
32
  scale={0}
30
33
  component_id={1}
31
- on:select={(e) => cfg.on_tab_select?.(e.detail)}
34
+ onselect={(data) => cfg.on_tab_select?.(data)}
32
35
  >
33
36
  <div data-testid="tab-content">tab panel content</div>
34
37
  </BaseTabItem>
@@ -1,56 +1,81 @@
1
1
  <script lang="ts">
2
- import { getContext, onMount, createEventDispatcher, tick } from "svelte";
2
+ import { getContext, tick, untrack } from "svelte";
3
3
  import { TABS } from "@gradio/tabs";
4
4
  import { BaseColumn } from "@gradio/column";
5
5
  import type { SelectData } from "@gradio/utils";
6
6
 
7
- export let elem_id = "";
8
- export let elem_classes: string[] = [];
9
- export let label: string;
10
- export let id: string | number | object = {};
11
- export let visible: boolean | "hidden";
12
- export let interactive: boolean;
13
- export let order: number;
14
- export let scale: number;
15
- export let component_id: number;
16
-
17
- const dispatch = createEventDispatcher<{ select: SelectData }>();
7
+ let {
8
+ elem_id = "",
9
+ elem_classes = [],
10
+ label,
11
+ id,
12
+ visible,
13
+ interactive,
14
+ order,
15
+ scale,
16
+ component_id,
17
+ onselect
18
+ }: {
19
+ elem_id?: string;
20
+ elem_classes?: string[];
21
+ label: string;
22
+ id?: string | number | null;
23
+ visible: boolean | "hidden";
24
+ interactive: boolean;
25
+ order: number;
26
+ scale: number;
27
+ component_id: number;
28
+ onselect?: (data: SelectData) => void;
29
+ } = $props();
18
30
 
19
31
  const { register_tab, unregister_tab, selected_tab, selected_tab_index } =
20
32
  getContext(TABS) as any;
21
33
 
22
- let tab_index: number;
34
+ let tab_index = $state<number | undefined>(undefined);
23
35
 
24
36
  function _register_tab(obj: string, order: number): number {
25
37
  obj = JSON.parse(obj);
26
38
  return register_tab(obj, order);
27
39
  }
28
40
 
29
- $: props_json = JSON.stringify({
30
- label,
31
- id,
32
- elem_id,
33
- visible,
34
- interactive,
35
- scale,
36
- component_id
37
- });
41
+ let tab_id = $derived(id ?? component_id);
38
42
 
39
- $: tab_index = _register_tab(props_json, order);
43
+ let props_json = $derived(
44
+ JSON.stringify({
45
+ label,
46
+ id: tab_id,
47
+ elem_id,
48
+ visible,
49
+ interactive,
50
+ scale,
51
+ component_id
52
+ })
53
+ );
40
54
 
41
- onMount(() => {
42
- return (): void => unregister_tab({ label, id, elem_id }, order);
55
+ let is_visible = $derived(visible !== false && visible !== "hidden");
56
+
57
+ $effect(() => {
58
+ const tab_props = props_json;
59
+ tab_index = untrack(() => _register_tab(tab_props, order));
60
+ });
61
+
62
+ $effect(() => {
63
+ return (): void => unregister_tab({ label, id: tab_id, elem_id }, order);
43
64
  });
44
65
 
45
- $: $selected_tab_index === tab_index &&
46
- tick().then(() => dispatch("select", { value: label, index: tab_index }));
66
+ $effect(() => {
67
+ const index = tab_index;
68
+ if (index !== undefined && $selected_tab_index === index) {
69
+ tick().then(() => onselect?.({ value: label, index }));
70
+ }
71
+ });
47
72
  </script>
48
73
 
49
74
  <div
50
75
  id={elem_id}
51
76
  class="tabitem {elem_classes.join(' ')}"
52
77
  class:grow-children={scale >= 1}
53
- style:display={$selected_tab === id && visible !== false ? "flex" : "none"}
78
+ style:display={$selected_tab === tab_id && is_visible ? "flex" : "none"}
54
79
  style:flex-grow={scale}
55
80
  role="tabpanel"
56
81
  >
@@ -1,4 +1,16 @@
1
1
  import type { SelectData } from "@gradio/utils";
2
+ type $$ComponentProps = {
3
+ elem_id?: string;
4
+ elem_classes?: string[];
5
+ label: string;
6
+ id?: string | number | null;
7
+ visible: boolean | "hidden";
8
+ interactive: boolean;
9
+ order: number;
10
+ scale: number;
11
+ component_id: number;
12
+ onselect?: (data: SelectData) => void;
13
+ };
2
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> {
3
15
  new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
4
16
  $$bindings?: Bindings;
@@ -17,24 +29,12 @@ type $$__sveltets_2_PropsWithChildren<Props, Slots> = Props & (Slots extends {
17
29
  } ? Props extends Record<string, never> ? any : {
18
30
  children?: any;
19
31
  } : {});
20
- declare const TabItem: $$__sveltets_2_IsomorphicComponent<$$__sveltets_2_PropsWithChildren<{
21
- elem_id?: string;
22
- elem_classes?: string[];
23
- label: string;
24
- id?: string | number | object;
25
- visible: boolean | "hidden";
26
- interactive: boolean;
27
- order: number;
28
- scale: number;
29
- component_id: number;
30
- }, {
32
+ declare const TabItem: $$__sveltets_2_IsomorphicComponent<$$__sveltets_2_PropsWithChildren<$$ComponentProps, {
31
33
  default: {};
32
34
  }>, {
33
- select: CustomEvent<SelectData>;
34
- } & {
35
35
  [evt: string]: CustomEvent<any>;
36
36
  }, {
37
37
  default: {};
38
- }, {}, string>;
38
+ }, {}, "">;
39
39
  type TabItem = InstanceType<typeof TabItem>;
40
40
  export default TabItem;
package/dist/types.d.ts CHANGED
@@ -3,7 +3,7 @@ export interface TabItemProps {
3
3
  elem_id: string;
4
4
  elem_classes: string[];
5
5
  label: string;
6
- id: string | number;
6
+ id?: string | number | null;
7
7
  visible: boolean | "hidden";
8
8
  interactive: boolean;
9
9
  order: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gradio/tabitem",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "description": "Gradio UI packages",
5
5
  "type": "module",
6
6
  "author": "",
@@ -16,9 +16,9 @@
16
16
  "./package.json": "./package.json"
17
17
  },
18
18
  "dependencies": {
19
- "@gradio/tabs": "^0.6.0",
20
19
  "@gradio/column": "^0.3.3",
21
- "@gradio/utils": "^0.12.2"
20
+ "@gradio/utils": "^0.12.2",
21
+ "@gradio/tabs": "^0.7.0"
22
22
  },
23
23
  "devDependencies": {
24
24
  "@gradio/preview": "^0.16.2"
@@ -1,56 +1,81 @@
1
1
  <script lang="ts">
2
- import { getContext, onMount, createEventDispatcher, tick } from "svelte";
2
+ import { getContext, tick, untrack } from "svelte";
3
3
  import { TABS } from "@gradio/tabs";
4
4
  import { BaseColumn } from "@gradio/column";
5
5
  import type { SelectData } from "@gradio/utils";
6
6
 
7
- export let elem_id = "";
8
- export let elem_classes: string[] = [];
9
- export let label: string;
10
- export let id: string | number | object = {};
11
- export let visible: boolean | "hidden";
12
- export let interactive: boolean;
13
- export let order: number;
14
- export let scale: number;
15
- export let component_id: number;
16
-
17
- const dispatch = createEventDispatcher<{ select: SelectData }>();
7
+ let {
8
+ elem_id = "",
9
+ elem_classes = [],
10
+ label,
11
+ id,
12
+ visible,
13
+ interactive,
14
+ order,
15
+ scale,
16
+ component_id,
17
+ onselect
18
+ }: {
19
+ elem_id?: string;
20
+ elem_classes?: string[];
21
+ label: string;
22
+ id?: string | number | null;
23
+ visible: boolean | "hidden";
24
+ interactive: boolean;
25
+ order: number;
26
+ scale: number;
27
+ component_id: number;
28
+ onselect?: (data: SelectData) => void;
29
+ } = $props();
18
30
 
19
31
  const { register_tab, unregister_tab, selected_tab, selected_tab_index } =
20
32
  getContext(TABS) as any;
21
33
 
22
- let tab_index: number;
34
+ let tab_index = $state<number | undefined>(undefined);
23
35
 
24
36
  function _register_tab(obj: string, order: number): number {
25
37
  obj = JSON.parse(obj);
26
38
  return register_tab(obj, order);
27
39
  }
28
40
 
29
- $: props_json = JSON.stringify({
30
- label,
31
- id,
32
- elem_id,
33
- visible,
34
- interactive,
35
- scale,
36
- component_id
37
- });
41
+ let tab_id = $derived(id ?? component_id);
38
42
 
39
- $: tab_index = _register_tab(props_json, order);
43
+ let props_json = $derived(
44
+ JSON.stringify({
45
+ label,
46
+ id: tab_id,
47
+ elem_id,
48
+ visible,
49
+ interactive,
50
+ scale,
51
+ component_id
52
+ })
53
+ );
40
54
 
41
- onMount(() => {
42
- return (): void => unregister_tab({ label, id, elem_id }, order);
55
+ let is_visible = $derived(visible !== false && visible !== "hidden");
56
+
57
+ $effect(() => {
58
+ const tab_props = props_json;
59
+ tab_index = untrack(() => _register_tab(tab_props, order));
60
+ });
61
+
62
+ $effect(() => {
63
+ return (): void => unregister_tab({ label, id: tab_id, elem_id }, order);
43
64
  });
44
65
 
45
- $: $selected_tab_index === tab_index &&
46
- tick().then(() => dispatch("select", { value: label, index: tab_index }));
66
+ $effect(() => {
67
+ const index = tab_index;
68
+ if (index !== undefined && $selected_tab_index === index) {
69
+ tick().then(() => onselect?.({ value: label, index }));
70
+ }
71
+ });
47
72
  </script>
48
73
 
49
74
  <div
50
75
  id={elem_id}
51
76
  class="tabitem {elem_classes.join(' ')}"
52
77
  class:grow-children={scale >= 1}
53
- style:display={$selected_tab === id && visible !== false ? "flex" : "none"}
78
+ style:display={$selected_tab === tab_id && is_visible ? "flex" : "none"}
54
79
  style:flex-grow={scale}
55
80
  role="tabpanel"
56
81
  >
package/types.ts CHANGED
@@ -4,7 +4,7 @@ export interface TabItemProps {
4
4
  elem_id: string;
5
5
  elem_classes: string[];
6
6
  label: string;
7
- id: string | number;
7
+ id?: string | number | null;
8
8
  visible: boolean | "hidden";
9
9
  interactive: boolean;
10
10
  order: number;