diff --git a/CHANGELOG.md b/CHANGELOG.md index 4475401824..91a47f5e7c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## New Features: -No changes to highlight. +- Allow the web component `space`, `src`, and `host` attributes to be updated dynamically by [@pngwn](https://github.com/pngwn) in [PR 4461](https://github.com/gradio-app/gradio/pull/4461) ## Bug Fixes: diff --git a/js/_cdn-test/index.html b/js/_cdn-test/index.html index 72822ad390..fec597e816 100644 --- a/js/_cdn-test/index.html +++ b/js/_cdn-test/index.html @@ -19,7 +19,7 @@ Vite App -

Hello title

+ - + > --> - + +

Config Error

Working

- + + --> - + + diff --git a/js/app/src/main.ts b/js/app/src/main.ts index 79f9b01471..8ae2a5508c 100644 --- a/js/app/src/main.ts +++ b/js/app/src/main.ts @@ -14,11 +14,46 @@ FONTS = "__FONTS_CSS__"; function create_custom_element() { class GradioApp extends HTMLElement { + control_page_title: string | null; + initial_height: string; + is_embed: string; + container: string; + info: string | true; + autoscroll: string | null; + eager: string | null; + theme_mode: ThemeMode | null; + host: string | null; + space: string | null; + src: string | null; + app?: Index; + loading: boolean; + updating: { name: string; value: string } | false; + constructor() { super(); + this.host = this.getAttribute("host"); + this.space = this.getAttribute("space"); + this.src = this.getAttribute("src"); + + this.control_page_title = this.getAttribute("control_page_title"); + this.initial_height = this.getAttribute("initial_height") ?? "300px"; // default: 300px + this.is_embed = this.getAttribute("embed") ?? "true"; // default: true + this.container = this.getAttribute("container") ?? "true"; // default: true + this.info = this.getAttribute("info") ?? true; // default: true + this.autoscroll = this.getAttribute("autoscroll"); + this.eager = this.getAttribute("eager"); + this.theme_mode = this.getAttribute("theme_mode") as ThemeMode | null; + this.updating = false; + this.loading = false; } async connectedCallback() { + this.loading = true; + + if (this.app) { + this.app.$destroy(); + } + if (typeof FONTS !== "string") { FONTS.forEach((f) => mount_css(f, document.head)); } @@ -37,43 +72,96 @@ function create_custom_element() { observer.observe(this, { childList: true }); - const host = this.getAttribute("host"); - const space = this.getAttribute("space"); - const src = this.getAttribute("src"); + // if (this.) - const control_page_title = this.getAttribute("control_page_title"); - const initial_height = this.getAttribute("initial_height") ?? "300px"; // default: 300px - const is_embed = this.getAttribute("embed") ?? "true"; // default: true - const container = this.getAttribute("container") ?? "true"; // default: true - const info = this.getAttribute("info") ?? true; // default: true - const autoscroll = this.getAttribute("autoscroll"); - const eager = this.getAttribute("eager"); - const theme_mode = this.getAttribute("theme_mode") as ThemeMode | null; - - const app = new Index({ + this.app = new Index({ target: this, props: { // embed source - space: space ? space.trim() : space, - src: src ? src.trim() : src, - host: host ? host.trim() : host, + space: this.space ? this.space.trim() : this.space, + src: this.src ? this.src.trim() : this.src, + host: this.host ? this.host.trim() : this.host, // embed info - info: info === "false" ? false : true, - container: container === "false" ? false : true, - is_embed: is_embed === "false" ? false : true, - initial_height, - eager: eager === "true" ? true : false, + info: this.info === "false" ? false : true, + container: this.container === "false" ? false : true, + is_embed: this.is_embed === "false" ? false : true, + initial_height: this.initial_height, + eager: this.eager === "true" ? true : false, // gradio meta info version: GRADIO_VERSION, - theme_mode, + theme_mode: this.theme_mode, // misc global behaviour - autoscroll: autoscroll === "true" ? true : false, - control_page_title: control_page_title === "true" ? true : false, + autoscroll: this.autoscroll === "true" ? true : false, + control_page_title: this.control_page_title === "true" ? true : false, // for gradio docs // TODO: Remove -- i think this is just for autoscroll behavhiour, app vs embeds app_mode: window.__gradio_mode__ === "app" } }); + + if (this.updating) { + this.setAttribute(this.updating.name, this.updating.value); + } + + this.loading = false; + } + + static get observedAttributes() { + return ["src", "space", "host"]; + } + + attributeChangedCallback(name: string, old_val: string, new_val: string) { + if ( + (name === "host" || name === "space" || name === "src") && + new_val !== old_val + ) { + this.updating = { name, value: new_val }; + if (this.loading) return; + + if (this.app) { + this.app.$destroy(); + } + + this.space = null; + this.host = null; + this.src = null; + + if (name === "host") { + this.host = new_val; + } else if (name === "space") { + this.space = new_val; + } else if (name === "src") { + this.src = new_val; + } + + this.app = new Index({ + target: this, + props: { + // embed source + space: this.space ? this.space.trim() : this.space, + src: this.src ? this.src.trim() : this.src, + host: this.host ? this.host.trim() : this.host, + // embed info + info: this.info === "false" ? false : true, + container: this.container === "false" ? false : true, + is_embed: this.is_embed === "false" ? false : true, + initial_height: this.initial_height, + eager: this.eager === "true" ? true : false, + // gradio meta info + version: GRADIO_VERSION, + theme_mode: this.theme_mode, + // misc global behaviour + autoscroll: this.autoscroll === "true" ? true : false, + control_page_title: + this.control_page_title === "true" ? true : false, + // for gradio docs + // TODO: Remove -- i think this is just for autoscroll behavhiour, app vs embeds + app_mode: window.__gradio_mode__ === "app" + } + }); + + this.updating = false; + } } } if (!customElements.get("gradio-app"))