diff --git a/.changeset/calm-columns-appear.md b/.changeset/calm-columns-appear.md deleted file mode 100644 index fb97fe664e6..00000000000 --- a/.changeset/calm-columns-appear.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -"@gradio/column": patch -"@gradio/core": patch -"@gradio/dataset": patch -"@gradio/html": patch -"@gradio/json": patch -"@gradio/plot": patch -"@gradio/tabitem": patch -"@gradio/textbox": patch ---- - -fix: restore shared props lost during frontend prop partitioning diff --git a/demo/shared_props/run.py b/demo/shared_props/run.py deleted file mode 100644 index d12e9dc1792..00000000000 --- a/demo/shared_props/run.py +++ /dev/null @@ -1,70 +0,0 @@ -import matplotlib.pyplot as plt - -import gradio as gr -from gradio.media import get_image - - -def validate_text(value: str): - return gr.validate(bool(value.strip()), "Text is required") - - -def echo(value: str): - return value - - -figure, axis = plt.subplots() -axis.plot([0, 1, 2], [0, 1, 0]) - - -with gr.Blocks() as demo: - with gr.Row(): - with gr.Column(variant="panel", elem_id="panel-column"): - gr.Markdown("Panel column") - with gr.Column(variant="compact", elem_id="compact-column"): - gr.Button("Compact one") - gr.Button("Compact two") - - with gr.Row(): - gr.HTML( - "Padded HTML", - container=True, - padding=True, - elem_id="padded-html", - ) - gr.HTML( - "Unpadded HTML", - container=True, - padding=False, - elem_id="unpadded-html", - ) - - gr.JSON({"shared": "theme"}, elem_id="shared-json") - gr.Plot(figure, elem_id="shared-plot") - - with gr.Tabs(): - with gr.Tab("Scaled tab", scale=2, elem_id="scaled-tab"): - gr.Markdown("Scaled tab content") - with gr.Tab("Other tab"): - gr.Markdown("Other tab content") - - image_component = gr.Image(visible=False) - gr.Dataset( - components=[image_component], - samples=[[get_image("cheetah1.jpg")]], - label="Image examples", - elem_id="shared-dataset", - ) - - validated_text = gr.Textbox(label="Validated text") - validate_button = gr.Button("Validate text") - validated_output = gr.Textbox(label="Validated output", interactive=False) - validate_button.click( - echo, - validated_text, - validated_output, - validator=validate_text, - ) - - -if __name__ == "__main__": - demo.launch() diff --git a/js/column/Index.svelte b/js/column/Index.svelte index 5cf14ab0b7b..65b6fbf4148 100644 --- a/js/column/Index.svelte +++ b/js/column/Index.svelte @@ -13,7 +13,7 @@ ); - + diff --git a/js/core/src/Blocks.svelte b/js/core/src/Blocks.svelte index 0cdd18225de..4fc4faf66b0 100644 --- a/js/core/src/Blocks.svelte +++ b/js/core/src/Blocks.svelte @@ -163,7 +163,6 @@ { root, theme: theme_mode, - theme_mode, version, api_prefix, max_file_size, @@ -245,7 +244,6 @@ app_tree.reload(components, layout, dependencies, { root, theme: theme_mode, - theme_mode, version, api_prefix, max_file_size, diff --git a/js/core/src/types.ts b/js/core/src/types.ts index e578327b155..ac6137c141e 100644 --- a/js/core/src/types.ts +++ b/js/core/src/types.ts @@ -136,7 +136,6 @@ export type LoadingComponent = Promise<{ export interface AppConfig { root: string; theme: string; - theme_mode: ThemeMode; version: string; max_file_size?: number; autoscroll: boolean; diff --git a/js/dataset/Dataset.test.ts b/js/dataset/Dataset.test.ts deleted file mode 100644 index 452d609298f..00000000000 --- a/js/dataset/Dataset.test.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { afterEach, describe, expect, test } from "vitest"; -import { cleanup, render, waitFor } from "@self/tootils/render"; - -import Dataset from "./Index.svelte"; -import DatasetRootExample from "./DatasetRootExample.svelte"; - -describe("Dataset", () => { - afterEach(() => cleanup()); - - test("forwards the shared root to example components", async () => { - const result = await render(Dataset, { - components: [{ name: "textbox", class_id: "textbox" }], - component_props: [{}], - headers: ["Example"], - samples: [["sample"]], - sample_labels: null, - value: null, - root: "/gradio-root", - proxy_url: null, - samples_per_page: 10, - layout: "gallery", - show_label: false, - load_component: () => ({ - component: Promise.resolve({ default: DatasetRootExample }), - runtime: false - }) - }); - - await waitFor(() => { - expect(result.getByTestId("dataset-root")).toHaveTextContent( - "/gradio-root" - ); - }); - }); -}); diff --git a/js/dataset/DatasetRootExample.svelte b/js/dataset/DatasetRootExample.svelte deleted file mode 100644 index 46468140252..00000000000 --- a/js/dataset/DatasetRootExample.svelte +++ /dev/null @@ -1,5 +0,0 @@ - - -{root ?? "missing"} diff --git a/js/dataset/Index.svelte b/js/dataset/Index.svelte index 2b79fc2382f..0f44649a18a 100644 --- a/js/dataset/Index.svelte +++ b/js/dataset/Index.svelte @@ -54,7 +54,6 @@ onselect={(data) => gradio.dispatch("select", data)} load_component={gradio.shared.load_component} {...gradio.props} - root={gradio.shared.root} {samples} /> diff --git a/js/dataset/types.ts b/js/dataset/types.ts index 686bf51f64f..78e50a66537 100644 --- a/js/dataset/types.ts +++ b/js/dataset/types.ts @@ -7,6 +7,7 @@ export interface DatasetProps { samples: any[][] | null; sample_labels: string[] | null; value: number | null; + root: string; proxy_url: null | string; samples_per_page: number; diff --git a/js/html/Index.svelte b/js/html/Index.svelte index 096b6ce597d..c246aafa825 100644 --- a/js/html/Index.svelte +++ b/js/html/Index.svelte @@ -58,7 +58,7 @@ elem_id={gradio.shared.elem_id} elem_classes={gradio.shared.elem_classes} container={gradio.shared.container} - padding={gradio.shared.padding !== false} + padding={gradio.props.padding !== false} overflow_behavior="visible" > {#if gradio.shared.show_label && gradio.props.buttons && gradio.props.buttons.length > 0} diff --git a/js/html/types.ts b/js/html/types.ts index 974b40ecea6..f8497bb8ed0 100644 --- a/js/html/types.ts +++ b/js/html/types.ts @@ -13,6 +13,7 @@ export interface HTMLProps { head: string | null; component_class_name: string; buttons: (string | CustomButton)[] | null; + padding: boolean; } export interface HTMLEvents { diff --git a/js/json/Index.svelte b/js/json/Index.svelte index e6c5ecf2f31..19d94401ae7 100644 --- a/js/json/Index.svelte +++ b/js/json/Index.svelte @@ -64,7 +64,7 @@ { - await page.emulateMedia({ colorScheme: "dark" }); - await page.reload(); - - await expect(page.locator("#panel-column")).toHaveClass(/\bpanel\b/); - await expect(page.locator("#compact-column")).toHaveClass(/\bcompact\b/); - - await expect(page.locator("#padded-html")).toHaveClass(/\bpadded\b/); - await expect(page.locator("#unpadded-html")).not.toHaveClass(/\bpadded\b/); - - await expect(page.locator("#shared-json .json-node.root")).toHaveClass( - /\bdark-mode\b/ - ); - - const plot = page.locator("#shared-plot [data-testid='matplotlib'] img"); - await expect(plot).toBeVisible(); - await expect - .poll(() => plot.evaluate((image: HTMLImageElement) => image.naturalWidth)) - .toBeGreaterThan(0); - - const scaled_tab = page.getByRole("tabpanel").filter({ - has: page.getByText("Scaled tab content") - }); - await expect(scaled_tab).toHaveCSS("flex-grow", "2"); - - const dataset_image = page.locator("#shared-dataset img"); - await expect(dataset_image).toBeVisible(); - await expect - .poll(() => - dataset_image.evaluate((image: HTMLImageElement) => image.naturalWidth) - ) - .toBeGreaterThan(0); - - await page.getByRole("button", { name: "Validate text" }).click(); - await expect(page.getByText("Text is required")).toBeVisible(); - - await page.getByLabel("Validated text").fill("valid value"); - await expect(page.getByText("Text is required")).toBeHidden(); - - await page.getByRole("button", { name: "Validate text" }).click(); - await expect(page.getByLabel("Validated output")).toHaveValue("valid value"); -}); diff --git a/js/tabitem/Index.svelte b/js/tabitem/Index.svelte index 18c26367eaa..8b9c32383e3 100644 --- a/js/tabitem/Index.svelte +++ b/js/tabitem/Index.svelte @@ -20,7 +20,7 @@ interactive={gradio.shared.interactive} id={gradio.props.id} order={gradio.props.order} - scale={gradio.shared.scale} + scale={gradio.props.scale} component_id={gradio.props.component_id} onselect={(data) => gradio.dispatch("select", data)} > diff --git a/js/tabitem/types.ts b/js/tabitem/types.ts index 7468d4c771f..5138e9d1d7f 100644 --- a/js/tabitem/types.ts +++ b/js/tabitem/types.ts @@ -8,6 +8,7 @@ export interface TabItemProps { visible: boolean | "hidden"; interactive: boolean; order: number; + scale: number; component_id: number; } diff --git a/js/textbox/Index.svelte b/js/textbox/Index.svelte index a1d20ec22fa..bba29a87db2 100644 --- a/js/textbox/Index.svelte +++ b/js/textbox/Index.svelte @@ -32,7 +32,7 @@ async function handle_input(value: string): Promise { if (!gradio.shared || !gradio.props) return; - clear_validation_error(); + gradio.props.validation_error = null; gradio.props.value = value; await tick(); gradio.dispatch("input"); @@ -44,16 +44,9 @@ function handle_change(value: string): void { if (!gradio.shared || !gradio.props) return; - clear_validation_error(); + gradio.props.validation_error = null; gradio.props.value = value; } - - function clear_validation_error(): void { - gradio.shared.validation_error = null; - if (gradio.shared.loading_status) { - gradio.shared.loading_status.validation_error = null; - } - } { - clear_validation_error(); + gradio.shared.validation_error = null; gradio.dispatch("submit"); }} onblur={() => gradio.dispatch("blur")} diff --git a/js/textbox/Textbox.test.ts b/js/textbox/Textbox.test.ts index b1fd3982f91..7071c73ef5a 100644 --- a/js/textbox/Textbox.test.ts +++ b/js/textbox/Textbox.test.ts @@ -53,26 +53,6 @@ describe("Textbox", () => { expect(item.value).toBe("hi some text"); }); - - test.each(["input", "change"] as const)( - "%s clears the shared validation error", - async (event_name) => { - const result = await render(Textbox, { - ...default_props, - value: "", - validation_error: "Shared error", - loading_status: { validation_error: "Required" } - }); - const textbox = result.getByRole("textbox"); - - expect(result.getByText("Required")).toBeVisible(); - await fireEvent[event_name](textbox, { target: { value: "valid" } }); - - await waitFor(() => { - expect(result.queryByText("Required")).not.toBeInTheDocument(); - }); - } - ); }); describe("Props: type", () => { diff --git a/js/textbox/types.ts b/js/textbox/types.ts index addd2b0602c..8d9ad66b4e1 100644 --- a/js/textbox/types.ts +++ b/js/textbox/types.ts @@ -34,6 +34,7 @@ export interface TextboxProps { autoscroll: boolean; max_length: number; html_attributes: InputHTMLAttributes; + validation_error: string | null; } type FullAutoFill = diff --git a/js/utils/src/utils.svelte.ts b/js/utils/src/utils.svelte.ts index d2119856423..c1a602f3eeb 100644 --- a/js/utils/src/utils.svelte.ts +++ b/js/utils/src/utils.svelte.ts @@ -35,7 +35,7 @@ export interface SharedProps { client: Client; scale: number; min_width: number; - padding: boolean; + padding: number; load_component: load_component; loading_status?: any; label: string;