Implement left and right click in Gallery component and show implicit images in Gallery grid (#4995)

* tweak responsive behaviour in gallery

* test

* add function to move left + right on click

* add changeset

* fix ts error

* Delete soft-eyes-repeat.md

* add changeset

* add gallery story

* change y overflow to scroll

---------

Co-authored-by: pngwn <hello@pngwn.io>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
This commit is contained in:
Hannah 2023-07-25 15:02:44 +01:00 committed by GitHub
parent 41c83070b0
commit 3f8c210b01
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 80 additions and 101 deletions

View File

@ -0,0 +1,7 @@
---
"@gradio/app": minor
"@gradio/gallery": minor
"gradio": minor
---
feat:Implement left and right click in `Gallery` component and show implicit images in `Gallery` grid

View File

@ -11,74 +11,74 @@
control: "text",
description: "The gallery label",
name: "label",
value: "Gradio Button"
value: "Gradio Button",
},
show_label: {
options: [true, false],
description: "Whether to show the label",
control: { type: "boolean" },
defaultValue: true
defaultValue: true,
},
grid_cols: {
options: [1, 2, 3, 4],
description: "The number of colums to show in grid",
control: { type: "select" },
defaultValue: 2
defaultValue: 2,
},
grid_rows: {
options: [1, 2, 3, 4],
description: "The number of rows to show in grid",
control: { type: "select" },
defaultValue: 2
defaultValue: 2,
},
height: {
options: ["auto", 500, 600],
description: "The height of the grid",
control: { type: "select" },
defaultValue: "auto"
defaultValue: "auto",
},
preview: {
options: [true, false],
description: "Whether to start the gallery in preview mode",
control: { type: "boolean" },
defaultValue: true
defaultValue: true,
},
allow_preview: {
options: [true, false],
description: "Whether to allow a preview mode in the gallery",
control: { type: "boolean" },
defaultValue: true
defaultValue: true,
},
object_fit: {
options: ["contain", "cover", "fill", "none", "scale-down"],
description: "How to display each indivial image in the grid",
control: { type: "select" },
defaultValue: "contain"
defaultValue: "contain",
},
show_share_button: {
options: [true, false],
description: "Whether to show the share button in the gallery",
control: { type: "boolean" },
defaultValue: false
}
defaultValue: false,
},
}}
/>
<Template let:args>
<Gallery
{...args}
value={[
[
"https://gradio-builds.s3.amazonaws.com/demo-files/cheetah_running.avif",
"A fast cheetah"
"A fast cheetah",
],
"https://gradio-builds.s3.amazonaws.com/demo-files/cheetah-002.jpg",
"https://gradio-builds.s3.amazonaws.com/demo-files/cheetah-003.jpg",
"https://gradio-builds.s3.amazonaws.com/demo-files/cheetah3.webp",
"https://gradio-builds.s3.amazonaws.com/demo-files/ghepardo-primo-piano.jpg",
"https://gradio-builds.s3.amazonaws.com/demo-files/main-qimg-0bbf31c18a22178cb7a8dd53640a3d05-lq.jpeg",
"https://gradio-builds.s3.amazonaws.com/demo-files/TheCheethcat.jpg"
"https://gradio-builds.s3.amazonaws.com/demo-files/TheCheethcat.jpg",
]}
{...args}
/>
</Template>
@ -96,7 +96,7 @@
label: "My Cheetah Gallery",
show_label: true,
grid_rows: 3,
grid_cols: 3
grid_cols: 3,
}}
/>
<Story
@ -104,14 +104,14 @@
args={{
label: "My Cheetah Gallery",
show_label: true,
grid_cols: 4
grid_cols: 4,
}}
/>
<Story
name="Gallery with height=600"
args={{
label: "My Cheetah Gallery",
height: 600
height: 600,
}}
/>
<Story
@ -119,7 +119,7 @@
args={{
label: "My Cheetah Gallery",
show_label: true,
allow_preview: false
allow_preview: false,
}}
/>
<Story
@ -127,7 +127,7 @@
args={{
label: "My Cheetah Gallery",
show_label: true,
preview: true
preview: true,
}}
/>
<Story
@ -135,7 +135,7 @@
args={{
label: "My Cheetah Gallery",
show_label: true,
object_fit: "scale-down"
object_fit: "scale-down",
}}
/>
<Story
@ -143,7 +143,7 @@
args={{
label: "My Cheetah Gallery",
show_label: true,
object_fit: "contain"
object_fit: "contain",
}}
/>
<Story
@ -151,7 +151,7 @@
args={{
label: "My Cheetah Gallery",
show_label: true,
object_fit: "cover"
object_fit: "cover",
}}
/>
<Story
@ -159,7 +159,7 @@
args={{
label: "My Cheetah Gallery",
show_label: true,
object_fit: "none"
object_fit: "none",
}}
/>
<Story
@ -167,7 +167,7 @@
args={{
label: "My Cheetah Gallery",
show_label: true,
object_fit: "fill"
object_fit: "fill",
}}
/>
<Story
@ -175,6 +175,24 @@
args={{
label: "My Cheetah Gallery",
show_label: true,
show_share_button: true
show_share_button: true,
}}
/>
<Story
name="Gallery with overflow of images"
args={{
label: "My Cheetah Gallery",
show_label: true,
grid_rows: 2,
grid_cols: 2,
height: 400,
value: [
"https://gradio-builds.s3.amazonaws.com/demo-files/cheetah-002.jpg",
"https://gradio-builds.s3.amazonaws.com/demo-files/cheetah-003.jpg",
"https://gradio-builds.s3.amazonaws.com/demo-files/ghepardo-primo-piano.jpg",
"https://gradio-builds.s3.amazonaws.com/demo-files/ghepardo-primo-piano.jpg",
"https://gradio-builds.s3.amazonaws.com/demo-files/cheetah-002.jpg",
],
}}
/>

View File

@ -10,22 +10,22 @@
export let label: string;
export let root: string;
export let root_url: null | string;
export let elem_id: string = "";
export let elem_classes: Array<string> = [];
export let visible: boolean = true;
export let elem_id = "";
export let elem_classes: string[] = [];
export let visible = true;
export let value: (FileData | string | [FileData | string, string])[] | null =
null;
export let container: boolean = true;
export let container = true;
export let scale: number | null = null;
export let min_width: number | undefined = undefined;
export let grid_cols: number | Array<number> | undefined = [2];
export let grid_rows: number | Array<number> | undefined = undefined;
export let grid_cols: number | number[] | undefined = [2];
export let grid_rows: number | number[] | undefined = undefined;
export let height: number | "auto" = "auto";
export let preview: boolean;
export let allow_preview: boolean = true;
export let allow_preview = true;
export let object_fit: "contain" | "cover" | "fill" | "none" | "scale-down" =
"cover";
export let show_share_button: boolean = false;
export let show_share_button = false;
</script>
<Block

View File

@ -11,7 +11,6 @@
import { normalise_file } from "@gradio/upload";
import { format_gallery_for_sharing } from "./utils";
export let container = true;
export let show_label = true;
export let label: string;
export let root = "";
@ -25,7 +24,7 @@
export let allow_preview = true;
export let object_fit: "contain" | "cover" | "fill" | "none" | "scale-down" =
"cover";
export let show_share_button: boolean = false;
export let show_share_button = false;
const dispatch = createEventDispatcher<{
select: SelectData;
@ -74,6 +73,19 @@
((selected_image ?? 0) + (_value?.length ?? 0) - 1) % (_value?.length ?? 0);
$: next = ((selected_image ?? 0) + 1) % (_value?.length ?? 0);
function handle_preview_click(event: MouseEvent): void {
const element = event.target as HTMLElement;
const x = event.clientX;
const width = element.offsetWidth;
const centerX = width / 2;
if (x < centerX) {
selected_image = previous;
} else {
selected_image = next;
}
}
function on_keydown(e: KeyboardEvent): void {
switch (e.code) {
case "Escape":
@ -99,7 +111,7 @@
if (selected_image !== null) {
dispatch("select", {
index: selected_image,
value: _value?.[selected_image][1]
value: _value?.[selected_image][1],
});
}
}
@ -132,52 +144,18 @@
container_element?.scrollTo({
left: pos < 0 ? 0 : pos,
behavior: "smooth"
behavior: "smooth",
});
}
let client_height = 0;
let window_height = 0;
let grid_cols_style = "";
let grid_rows_style = "";
$: {
let grid_cols_map = ["", "sm-", "md-", "lg-", "xl-", "2xl-"];
let _grid_cols = Array.isArray(grid_cols) ? grid_cols : [grid_cols];
grid_cols_style = [0, 0, 0, 0, 0, 0]
.map(
(_, i) =>
`--${grid_cols_map[i]}grid-cols: var(--grid-${
_grid_cols?.[i] || _grid_cols?.[_grid_cols?.length - 1]
});`
)
.join(" ");
}
$: {
let grid_rows_map = ["", "sm-", "md-", "lg-", "xl-", "2xl-"];
let _grid_rows = Array.isArray(grid_rows) ? grid_rows : [grid_rows];
grid_rows_style = [0, 0, 0, 0, 0, 0]
.map(
(_, i) =>
`--${grid_rows_map[i]}grid-rows: var(--grid-${
_grid_rows?.[i] || _grid_rows?.[_grid_rows?.length - 1]
});`
)
.join(" ");
}
</script>
<svelte:window bind:innerHeight={window_height} />
{#if show_label}
<BlockLabel
{show_label}
Icon={Image}
label={label || "Gallery"}
/>
<BlockLabel {show_label} Icon={Image} label={label || "Gallery"} />
{/if}
{#if value === null || _value === null || _value.length === 0}
<Empty unpadded_box={true} size="large"><Image /></Empty>
@ -191,7 +169,7 @@
<!-- svelte-ignore a11y-no-noninteractive-element-interactions -->
<img
data-testid="detailed-image"
on:click={() => (selected_image = next)}
on:click={(event) => handle_preview_click(event)}
src={_value[selected_image][0].data}
alt={_value[selected_image][1] || ""}
title={_value[selected_image][1] || null}
@ -235,7 +213,7 @@
>
<div
class="grid-container"
style="{grid_cols_style} {grid_rows_style} --object-fit: {object_fit}; height: {height}"
style="--grid-cols:{grid_cols}; --grid-rows:{grid_rows}; --object-fit: {object_fit}; height: {height};"
class:pt-6={show_label}
>
{#if show_share_button}
@ -374,41 +352,17 @@
position: relative;
padding: var(--size-2);
height: var(--size-full);
overflow-y: auto;
overflow-y: scroll;
}
.grid-container {
display: grid;
position: relative;
grid-template-rows: var(--grid-rows);
grid-template-columns: var(--grid-cols);
grid-template-rows: repeat(var(--grid-rows), minmax(100px, 1fr));
grid-template-columns: repeat(var(--grid-cols), minmax(100px, 1fr));
grid-auto-rows: minmax(100px, 1fr);
gap: var(--spacing-lg);
}
@media (--screen-sm) {
.grid-container {
grid-template-columns: var(--sm-grid-cols);
}
}
@media (--screen-md) {
.grid-container {
grid-template-columns: var(--md-grid-cols);
}
}
@media (--screen-lg) {
.grid-container {
grid-template-columns: var(--lg-grid-cols);
}
}
@media (--screen-xl) {
.grid-container {
grid-template-columns: var(--xl-grid-cols);
}
}
@media (--screen-xxl) {
.grid-container {
grid-template-columns: var(--2xl-grid-cols);
}
}
.thumbnail-lg > img {
width: var(--size-full);