Ensure tabs render in SSR mode and reduce time it takes for them to render. (#9728)

* fix tabs in SSR

* format

* add changeset

* remove log

* add changeset

* more ifx

* fix more

* more fix

* types

---------

Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
This commit is contained in:
pngwn 2024-10-16 21:11:17 +01:00 committed by GitHub
parent 7ec57cb018
commit d0b2ce8c0f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 63 additions and 12 deletions

View File

@ -0,0 +1,7 @@
---
"@gradio/core": patch
"@gradio/tabs": patch
"gradio": patch
---
fix:Ensure tabs render in SSR mode and reduce time it takes for them to render.

View File

@ -290,6 +290,26 @@ export function create_components(initial_layout: ComponentMeta | undefined): {
);
}
if (instance.type === "tabs") {
instance.children =
instance?.children?.map((c) => ({
...c,
props: {
...c.props,
id: c.props.id || c.id
}
})) || [];
const child_tab_items = instance.children?.filter(
(child) => child.type === "tabitem"
);
instance.props.inital_tabs = child_tab_items?.map((child) => ({
label: child.props.label,
id: child.props.id,
visible: child.props.visible,
interactive: child.props.interactive
}));
}
return instance;
}

View File

@ -9,10 +9,19 @@
const dispatch = createEventDispatcher();
interface Tab {
name: string;
id: string | number;
elem_id: string | undefined;
visible: boolean;
interactive: boolean;
}
export let visible = true;
export let elem_id = "";
export let elem_classes: string[] = [];
export let selected: number | string;
export let inital_tabs: Tab[];
export let gradio: Gradio<{
change: never;
select: SelectData;
@ -28,6 +37,7 @@
bind:selected
on:change={() => gradio.dispatch("change")}
on:select={(e) => gradio.dispatch("select", e.detail)}
{inital_tabs}
>
<slot />
</Tabs>

View File

@ -7,7 +7,8 @@
setContext,
createEventDispatcher,
onMount,
onDestroy
onDestroy,
tick
} from "svelte";
import OverflowIcon from "./OverflowIcon.svelte";
import { writable } from "svelte/store";
@ -15,7 +16,7 @@
interface Tab {
name: string;
id: object;
id: string | number;
elem_id: string | undefined;
visible: boolean;
interactive: boolean;
@ -24,9 +25,10 @@
export let visible = true;
export let elem_id = "";
export let elem_classes: string[] = [];
export let selected: number | string | object;
export let selected: number | string;
export let inital_tabs: Tab[];
let tabs: Tab[] = [];
let tabs: Tab[] = inital_tabs;
let overflow_menu_open = false;
let overflow_menu: HTMLElement;
@ -35,8 +37,12 @@
let tab_nav_el: HTMLElement;
let overflow_nav: HTMLElement;
const selected_tab = writable<false | object | number | string>(false);
const selected_tab_index = writable<number>(0);
const selected_tab = writable<false | number | string>(
selected || tabs[0]?.id || false
);
const selected_tab_index = writable<number>(
tabs.findIndex((t) => t.id === selected) || 0
);
const dispatch = createEventDispatcher<{
change: undefined;
select: SelectData;
@ -72,20 +78,19 @@
selected_tab_index
});
function change_tab(id: object | string | number): void {
function change_tab(id: string | number): void {
const tab_to_activate = tabs.find((t) => t.id === id);
if (
tab_to_activate &&
tab_to_activate.interactive &&
tab_to_activate.visible
tab_to_activate.visible &&
$selected_tab !== tab_to_activate.id
) {
selected = id;
$selected_tab = id;
$selected_tab_index = tabs.findIndex((t) => t.id === id);
dispatch("change");
overflow_menu_open = false;
} else {
console.warn("Attempted to select a non-interactive or hidden tab.");
}
}
@ -149,10 +154,19 @@
nav_items.forEach((item) => tab_nav_el.appendChild(item));
overflow_items.forEach((item) => overflow_nav.appendChild(item));
overflow_has_selected_tab = handle_overflow_has_selected_tab($selected_tab);
}
overflow_has_selected_tab = tabs.some(
$: overflow_has_selected_tab =
handle_overflow_has_selected_tab($selected_tab);
function handle_overflow_has_selected_tab(
selected_tab: number | string | false
): boolean {
if (selected_tab === false || !overflow_nav) return false;
return tabs.some(
(t) =>
t.id === $selected_tab &&
t.id === selected_tab &&
overflow_nav.contains(document.querySelector(`[data-tab-id="${t.id}"]`))
);
}