diff --git a/gradio/components.py b/gradio/components.py index 2d689a5d70..9e2dab77c1 100644 --- a/gradio/components.py +++ b/gradio/components.py @@ -4700,6 +4700,7 @@ class Gallery(IOComponent, GallerySerializable, Selectable): height: str | None = None, preview: bool | None = None, object_fit: str | None = None, + detailed_view: bool = True, **kwargs, ): """ @@ -4719,12 +4720,14 @@ class Gallery(IOComponent, GallerySerializable, Selectable): height: Height of the gallery. preview: If True, will display the Gallery in preview mode, which shows all of the images as thumbnails and allows the user to click on them to view them in full size. object_fit: CSS object-fit property for the thumbnail images in the gallery. Can be "contain", "cover", "fill", "none", or "scale-down". + detailed_view: If True, images in the gallery will be enlarged when they are clicked. Default is True. """ self.grid_cols = columns self.grid_rows = rows self.height = height self.preview = preview self.object_fit = object_fit + self.detailed_view = detailed_view self.select: EventListenerMethod """ Event listener for when the user selects image within Gallery. @@ -4760,6 +4763,7 @@ class Gallery(IOComponent, GallerySerializable, Selectable): height: str | None = None, preview: bool | None = None, object_fit: str | None = None, + detailed_view: bool | None = None, ): updated_config = { "label": label, @@ -4774,6 +4778,7 @@ class Gallery(IOComponent, GallerySerializable, Selectable): "height": height, "preview": preview, "object_fit": object_fit, + "detailed_view": detailed_view, "__type__": "update", } return updated_config @@ -4786,6 +4791,7 @@ class Gallery(IOComponent, GallerySerializable, Selectable): "height": self.height, "preview": self.preview, "object_fit": self.object_fit, + "detailed_view": self.detailed_view, **IOComponent.get_config(self), } diff --git a/js/app/src/components/Gallery/Gallery.svelte b/js/app/src/components/Gallery/Gallery.svelte index 74a756bcf5..1a3ac5bfec 100644 --- a/js/app/src/components/Gallery/Gallery.svelte +++ b/js/app/src/components/Gallery/Gallery.svelte @@ -21,6 +21,7 @@ export let grid_rows: number | Array | undefined = undefined; export let height: number | "auto" = "auto"; export let preview: boolean; + export let detailed_view: boolean = true; export let object_fit: "contain" | "cover" | "fill" | "none" | "scale-down" = "cover"; @@ -49,5 +50,6 @@ {height} {preview} {object_fit} + {detailed_view} /> diff --git a/js/app/src/components/Gallery/Gallery.test.ts b/js/app/src/components/Gallery/Gallery.test.ts new file mode 100644 index 0000000000..f573cc59cc --- /dev/null +++ b/js/app/src/components/Gallery/Gallery.test.ts @@ -0,0 +1,106 @@ +import { test, describe, assert, afterEach, vi } from "vitest"; +import { cleanup, render } from "@gradio/tootils"; + +import Gallery from "./Gallery.svelte"; +import { scroll_to_img } from "@gradio/gallery"; +import type { LoadingStatus } from "../StatusTracker/types"; + +const loading_status = { + eta: 0, + queue_position: 1, + queue_size: 1, + status: "complete" as LoadingStatus["status"], + scroll_to_output: false, + visible: true, + fn_index: 0 +}; + +describe("Gallery", () => { + afterEach(() => { + cleanup(); + vi.restoreAllMocks(); + }); + + test("preview shows detailed image by default", async () => { + const mock = vi.fn().mockImplementation(scroll_to_img); + + const { component, getAllByTestId } = render(Gallery, { + loading_status, + label: "gallery", + // @ts-ignore + value: [ + [ + { + name: "https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=387&q=80", + data: null, + is_file: true + }, + "label 0" + ], + [ + { + name: "https://images.unsplash.com/photo-1542909168-82c3e7fdca5c?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8MXx8aHVtYW4lMjBmYWNlfGVufDB8fDB8fA%3D%3D&w=1000&q=80", + data: null, + is_file: true + }, + "label 1" + ] + ], + show_label: true, + mode: "dynamic", + root: "http://localhost:7860", + root_url: null, + preview: true + }); + + const details = getAllByTestId("detailed-image"); + + assert.equal(details.length, 1); + }); + + test("detailed view does not show larger image", async () => { + const mock = vi.fn().mockImplementation(scroll_to_img); + + const { component, queryAllByTestId } = render(Gallery, { + loading_status, + label: "gallery", + // @ts-ignore + value: [ + [ + { + name: "https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=387&q=80", + data: null, + is_file: true + }, + "label 0" + ], + [ + { + name: "https://images.unsplash.com/photo-1542909168-82c3e7fdca5c?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8MXx8aHVtYW4lMjBmYWNlfGVufDB8fDB8fA%3D%3D&w=1000&q=80", + data: null, + is_file: true + }, + "label 1" + ], + [ + { + name: "https://images.unsplash.com/photo-1601412436009-d964bd02edbc?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=464&q=80", + data: null, + is_file: true + }, + "label 2" + ] + ], + show_label: true, + mode: "dynamic", + root: "http://localhost:7860", + root_url: null, + preview: true, + detailed_view: false + }); + + const details = queryAllByTestId("detailed-image"); + + assert.equal(details.length, 0); + }); +}); diff --git a/js/gallery/src/Gallery.svelte b/js/gallery/src/Gallery.svelte index edf486f039..80c5cbe2ac 100644 --- a/js/gallery/src/Gallery.svelte +++ b/js/gallery/src/Gallery.svelte @@ -19,6 +19,7 @@ export let grid_rows: number | Array | undefined = undefined; export let height: number | "auto" = "auto"; export let preview: boolean; + export let detailed_view: boolean = true; export let object_fit: "contain" | "cover" | "fill" | "none" | "scale-down" = "cover"; @@ -175,7 +176,7 @@ {#if value === null || _value === null || _value.length === 0} {:else} - {#if selected_image !== null} + {#if selected_image !== null && detailed_view}
(selected_image = null)} /> (selected_image = next)} src={_value[selected_image][0].data} alt={_value[selected_image][1] || ""}