Working lightbox modal ported from A1111
This commit is contained in:
196
src/lib/ImageViewer.ts
Normal file
196
src/lib/ImageViewer.ts
Normal file
@@ -0,0 +1,196 @@
|
|||||||
|
export class ImageViewer {
|
||||||
|
root: HTMLDivElement;
|
||||||
|
lightboxModal: HTMLDivElement;
|
||||||
|
currentGallery: HTMLDivElement | null = null;
|
||||||
|
private static _instance: ImageViewer;
|
||||||
|
|
||||||
|
static get instance(): ImageViewer {
|
||||||
|
if (!ImageViewer._instance)
|
||||||
|
ImageViewer._instance = new ImageViewer((window as any).app.rootEl)
|
||||||
|
return ImageViewer._instance
|
||||||
|
}
|
||||||
|
|
||||||
|
get modalImage(): HTMLImageElement | null {
|
||||||
|
return this.root.querySelector<HTMLImageElement>("#modalImage");
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(root: HTMLDivElement) {
|
||||||
|
this.root = root;
|
||||||
|
this.lightboxModal = this.root.querySelector<HTMLDivElement>("#lightboxModal");
|
||||||
|
}
|
||||||
|
|
||||||
|
// A full size 'lightbox' preview modal shown when left clicking on gallery previews
|
||||||
|
closeModal() {
|
||||||
|
this.lightboxModal.style.display = "none";
|
||||||
|
this.currentGallery = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static all_gallery_buttons(gallery: HTMLDivElement): HTMLButtonElement[] {
|
||||||
|
var allGalleryButtons = gallery.querySelectorAll('.preview > .thumbnails > .thumbnail-item.thumbnail-small');
|
||||||
|
var visibleGalleryButtons = [];
|
||||||
|
allGalleryButtons.forEach((elem) => {
|
||||||
|
if (elem.parentElement.offsetParent) {
|
||||||
|
visibleGalleryButtons.push(elem);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return visibleGalleryButtons;
|
||||||
|
}
|
||||||
|
|
||||||
|
static selected_gallery_button(gallery: HTMLDivElement): HTMLButtonElement | null {
|
||||||
|
var allCurrentButtons = gallery.querySelectorAll('.preview > .thumbnails > .thumbnail-item.thumbnail-small.selected');
|
||||||
|
var visibleCurrentButton = null;
|
||||||
|
allCurrentButtons.forEach((elem) => {
|
||||||
|
if (elem.parentElement.offsetParent) {
|
||||||
|
visibleCurrentButton = elem;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return visibleCurrentButton;
|
||||||
|
}
|
||||||
|
|
||||||
|
showModal(event: Event) {
|
||||||
|
const source = (event.target || event.srcElement) as HTMLImageElement;
|
||||||
|
const galleryElem = source.closest<HTMLDivElement>("div.block")
|
||||||
|
if (!galleryElem || ImageViewer.all_gallery_buttons(galleryElem).length === 0) {
|
||||||
|
console.error("No buttons found on gallery element!", galleryElem)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.currentGallery = galleryElem;
|
||||||
|
this.modalImage.src = source.src
|
||||||
|
if (this.modalImage.style.display === 'none') {
|
||||||
|
this.lightboxModal.style.setProperty('background-image', 'url(' + source.src + ')');
|
||||||
|
}
|
||||||
|
this.lightboxModal.style.display = "flex";
|
||||||
|
setTimeout(() => {
|
||||||
|
this.modalImage.focus()
|
||||||
|
}, 200)
|
||||||
|
|
||||||
|
event.stopPropagation()
|
||||||
|
}
|
||||||
|
|
||||||
|
static negmod(n: number, m: number) {
|
||||||
|
return ((n % m) + m) % m;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateOnBackgroundChange() {
|
||||||
|
const modalImage = this.modalImage
|
||||||
|
if (modalImage && modalImage.offsetParent && this.currentGallery) {
|
||||||
|
let currentButton = ImageViewer.selected_gallery_button(this.currentGallery);
|
||||||
|
|
||||||
|
if (currentButton?.children?.length > 0 && modalImage.src != currentButton.children[0].src) {
|
||||||
|
modalImage.src = currentButton.children[0].src;
|
||||||
|
if (modalImage.style.display === 'none') {
|
||||||
|
this.lightboxModal.style.setProperty('background-image', `url(${modalImage.src})`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
modalImageSwitch(offset: number) {
|
||||||
|
if (!this.currentGallery)
|
||||||
|
return
|
||||||
|
|
||||||
|
var galleryButtons = ImageViewer.all_gallery_buttons(this.currentGallery);
|
||||||
|
|
||||||
|
if (galleryButtons.length > 1) {
|
||||||
|
var currentButton = ImageViewer.selected_gallery_button(this.currentGallery);
|
||||||
|
|
||||||
|
var result = -1
|
||||||
|
galleryButtons.forEach((v, i) => {
|
||||||
|
if (v == currentButton) {
|
||||||
|
result = i
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (result != -1) {
|
||||||
|
const nextButton = galleryButtons[ImageViewer.negmod((result + offset), galleryButtons.length)]
|
||||||
|
nextButton.click()
|
||||||
|
const modalImage = this.modalImage;
|
||||||
|
const modal = this.lightboxModal
|
||||||
|
modalImage.src = nextButton.children[0].src;
|
||||||
|
if (modalImage.style.display === 'none') {
|
||||||
|
modal.style.setProperty('background-image', `url(${modalImage.src})`)
|
||||||
|
}
|
||||||
|
setTimeout(() => { modal.focus() }, 10)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
modalNextImage(event) {
|
||||||
|
this.modalImageSwitch(1)
|
||||||
|
event.stopPropagation()
|
||||||
|
}
|
||||||
|
|
||||||
|
modalPrevImage(event) {
|
||||||
|
this.modalImageSwitch(-1)
|
||||||
|
event.stopPropagation()
|
||||||
|
}
|
||||||
|
|
||||||
|
modalKeyHandler(event) {
|
||||||
|
switch (event.key) {
|
||||||
|
case "ArrowLeft":
|
||||||
|
this.modalPrevImage(event)
|
||||||
|
break;
|
||||||
|
case "ArrowRight":
|
||||||
|
this.modalNextImage(event)
|
||||||
|
break;
|
||||||
|
case "Escape":
|
||||||
|
this.closeModal();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setupImageForLightbox(e: HTMLImageElement) {
|
||||||
|
if (e.dataset.modded === "true")
|
||||||
|
return;
|
||||||
|
|
||||||
|
e.dataset.modded = "true";
|
||||||
|
e.style.cursor = 'pointer'
|
||||||
|
e.style.userSelect = 'none'
|
||||||
|
|
||||||
|
var isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1
|
||||||
|
|
||||||
|
// For Firefox, listening on click first switched to next image then shows the lightbox.
|
||||||
|
// If you know how to fix this without switching to mousedown event, please.
|
||||||
|
// For other browsers the event is click to make it possiblr to drag picture.
|
||||||
|
var event = isFirefox ? 'mousedown' : 'click'
|
||||||
|
|
||||||
|
e.addEventListener(event, (evt) => {
|
||||||
|
// if (!opts.js_modal_lightbox || evt.button != 0) return;
|
||||||
|
|
||||||
|
const initiallyZoomed = true
|
||||||
|
this.modalZoomSet(this.modalImage, initiallyZoomed)
|
||||||
|
evt.preventDefault()
|
||||||
|
this.showModal(evt)
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
modalZoomSet(modalImage: HTMLImageElement, enable: boolean) {
|
||||||
|
if (enable) {
|
||||||
|
modalImage.classList.add('modalImageFullscreen');
|
||||||
|
} else {
|
||||||
|
modalImage.classList.remove('modalImageFullscreen');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
modalZoomToggle(event: Event) {
|
||||||
|
const modalImage = this.modalImage;
|
||||||
|
this.modalZoomSet(modalImage, !modalImage.classList.contains('modalImageFullscreen'))
|
||||||
|
event.stopPropagation()
|
||||||
|
}
|
||||||
|
|
||||||
|
modalTileImageToggle(event: Event) {
|
||||||
|
const modalImage = this.modalImage
|
||||||
|
const modal = this.lightboxModal
|
||||||
|
const isTiling = modalImage.style.display === 'none';
|
||||||
|
if (isTiling) {
|
||||||
|
modalImage.style.display = 'block';
|
||||||
|
modal.style.setProperty('background-image', 'none')
|
||||||
|
} else {
|
||||||
|
modalImage.style.display = 'none';
|
||||||
|
modal.style.setProperty('background-image', `url(${modalImage.src})`)
|
||||||
|
}
|
||||||
|
|
||||||
|
event.stopPropagation()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,15 +6,19 @@
|
|||||||
import ComfyUIPane from "./ComfyUIPane.svelte";
|
import ComfyUIPane from "./ComfyUIPane.svelte";
|
||||||
import ComfyApp, { type SerializedAppState } from "./ComfyApp";
|
import ComfyApp, { type SerializedAppState } from "./ComfyApp";
|
||||||
import widgetState from "$lib/stores/widgetState";
|
import widgetState from "$lib/stores/widgetState";
|
||||||
|
import { ImageViewer } from "$lib/ImageViewer";
|
||||||
|
|
||||||
import { LGraph, LGraphNode } from "@litegraph-ts/core";
|
import { LGraph, LGraphNode } from "@litegraph-ts/core";
|
||||||
|
import LightboxModal from "./LightboxModal.svelte";
|
||||||
|
|
||||||
let app: ComfyApp = undefined;
|
let app: ComfyApp = undefined;
|
||||||
|
let imageViewer: ImageViewer;
|
||||||
let uiPane: ComfyUIPane = undefined;
|
let uiPane: ComfyUIPane = undefined;
|
||||||
|
let mainElem: HTMLDivElement;
|
||||||
let containerElem: HTMLDivElement;
|
let containerElem: HTMLDivElement;
|
||||||
let resizeTimeout: typeof Timer = -1;
|
let resizeTimeout: typeof Timer = -1;
|
||||||
|
|
||||||
function refreshView(event) {
|
function refreshView(event?: Event) {
|
||||||
clearTimeout(resizeTimeout);
|
clearTimeout(resizeTimeout);
|
||||||
resizeTimeout = setTimeout(app.resizeCanvas.bind(app), 250);
|
resizeTimeout = setTimeout(app.resizeCanvas.bind(app), 250);
|
||||||
}
|
}
|
||||||
@@ -87,9 +91,11 @@
|
|||||||
(window as any).app = app;
|
(window as any).app = app;
|
||||||
(window as any).appPane = uiPane;
|
(window as any).appPane = uiPane;
|
||||||
|
|
||||||
let wrappers = containerElem.querySelectorAll<HTMLDivNode>(".pane-wrapper")
|
imageViewer = new ImageViewer(app.rootEl);
|
||||||
|
|
||||||
|
let wrappers = containerElem.querySelectorAll<HTMLDivElement>(".pane-wrapper")
|
||||||
for (const wrapper of wrappers) {
|
for (const wrapper of wrappers) {
|
||||||
const paneNode = wrapper.parentNode; // get the node inside the <Pane/>
|
const paneNode = wrapper.parentNode as HTMLElement; // get the node inside the <Pane/>
|
||||||
paneNode.ontransitionend = () => {
|
paneNode.ontransitionend = () => {
|
||||||
app.resizeCanvas()
|
app.resizeCanvas()
|
||||||
}
|
}
|
||||||
@@ -97,38 +103,41 @@
|
|||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div id="dropzone" class="dropzone"></div>
|
<div id="main" bind:this={mainElem}>
|
||||||
<div id="container" bind:this={containerElem}>
|
<div id="dropzone" class="dropzone"></div>
|
||||||
<Splitpanes theme="comfy" on:resize={refreshView}>
|
<div id="container" bind:this={containerElem}>
|
||||||
<Pane>
|
<Splitpanes theme="comfy" on:resize={refreshView}>
|
||||||
<Splitpanes theme="comfy" on:resize={refreshView} horizontal="{true}">
|
<Pane>
|
||||||
<Pane>
|
<Splitpanes theme="comfy" on:resize={refreshView} horizontal="{true}">
|
||||||
<ComfyUIPane bind:this={uiPane} {app} />
|
<Pane>
|
||||||
</Pane>
|
<ComfyUIPane bind:this={uiPane} {app} />
|
||||||
<Pane bind:size={graphSize}>
|
</Pane>
|
||||||
<div class="canvas-wrapper pane-wrapper">
|
<Pane bind:size={graphSize}>
|
||||||
<canvas id="graph-canvas" />
|
<div class="canvas-wrapper pane-wrapper">
|
||||||
</div>
|
<canvas id="graph-canvas" />
|
||||||
</Pane>
|
</div>
|
||||||
</Splitpanes>
|
</Pane>
|
||||||
</Pane>
|
</Splitpanes>
|
||||||
<Pane bind:size={sidebarSize}>
|
</Pane>
|
||||||
<div class="sidebar-wrapper pane-wrapper">
|
<Pane bind:size={sidebarSize}>
|
||||||
Sidebar
|
<div class="sidebar-wrapper pane-wrapper">
|
||||||
</div>
|
Sidebar
|
||||||
</Pane>
|
</div>
|
||||||
</Splitpanes>
|
</Pane>
|
||||||
</div>
|
</Splitpanes>
|
||||||
<div id="bottombar">
|
</div>
|
||||||
<Button variant="primary" on:click={queuePrompt}>
|
<div id="bottombar">
|
||||||
Run
|
<Button variant="primary" on:click={queuePrompt}>
|
||||||
</Button>
|
Run
|
||||||
<Button variant="secondary" on:click={toggleGraph}>
|
</Button>
|
||||||
Toggle Graph
|
<Button variant="secondary" on:click={toggleGraph}>
|
||||||
</Button>
|
Toggle Graph
|
||||||
<Button variant="secondary" on:click={toggleSidebar}>
|
</Button>
|
||||||
Toggle Sidebar
|
<Button variant="secondary" on:click={toggleSidebar}>
|
||||||
</Button>
|
Toggle Sidebar
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
<LightboxModal />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ export type Progress = {
|
|||||||
|
|
||||||
export default class ComfyApp {
|
export default class ComfyApp {
|
||||||
api: ComfyAPI;
|
api: ComfyAPI;
|
||||||
|
rootEl: HTMLDivElement | null = null;
|
||||||
canvasEl: HTMLCanvasElement | null = null;
|
canvasEl: HTMLCanvasElement | null = null;
|
||||||
canvasCtx: CanvasRenderingContext2D | null = null;
|
canvasCtx: CanvasRenderingContext2D | null = null;
|
||||||
lGraph: LGraph | null = null;
|
lGraph: LGraph | null = null;
|
||||||
@@ -81,6 +82,7 @@ export default class ComfyApp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async setup(): Promise<void> {
|
async setup(): Promise<void> {
|
||||||
|
this.rootEl = document.getElementById("main") as HTMLDivElement;
|
||||||
this.canvasEl = document.getElementById("graph-canvas") as HTMLCanvasElement;
|
this.canvasEl = document.getElementById("graph-canvas") as HTMLCanvasElement;
|
||||||
this.lGraph = new LGraph();
|
this.lGraph = new LGraph();
|
||||||
this.lCanvas = new ComfyGraphCanvas(this, this.canvasEl, this.lGraph);
|
this.lCanvas = new ComfyGraphCanvas(this, this.canvasEl, this.lGraph);
|
||||||
|
|||||||
113
src/lib/components/LightboxModal.svelte
Normal file
113
src/lib/components/LightboxModal.svelte
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { ImageViewer } from "$lib/ImageViewer";
|
||||||
|
|
||||||
|
function toggleZoom(e: Event) {
|
||||||
|
ImageViewer.instance.modalZoomToggle(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
function previewTiling(e: Event) {
|
||||||
|
ImageViewer.instance.modalTileImageToggle(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeModal(e: Event) {
|
||||||
|
ImageViewer.instance.closeModal();
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleKey(e: KeyboardEvent) {
|
||||||
|
ImageViewer.instance.modalKeyHandler(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
function prevImage(e: Event) {
|
||||||
|
ImageViewer.instance.modalPrevImage(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
function nextImage(e: Event) {
|
||||||
|
ImageViewer.instance.modalNextImage(e);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div id="lightboxModal" on:keydown={handleKey}>
|
||||||
|
<div class="modalControls gradio-container" on:keydown={handleKey}>
|
||||||
|
<span class="modalZoom cursor" title="Toggle zoomed view" on:click={toggleZoom} on:keydown={handleKey}>⤡</span>
|
||||||
|
<span class="modalTileImage cursor" title="Preview tiling" on:click={previewTiling} on:keydown={handleKey}>⊞</span>
|
||||||
|
<span class="modalClose cursor" title="Close image viewer" on:click={closeModal} on:keydown={handleKey}>×</span>
|
||||||
|
</div>
|
||||||
|
<img id="modalImage" alt="Modal" tabIndex="0" on:keydown={handleKey}>
|
||||||
|
<a class="modalPrev" href="#" tabIndex="0" on:click={prevImage} on:keydown={handleKey}>❮</a>
|
||||||
|
<a class="modalNext" href="#" tabIndex="0" on:click={nextImage} on:keydown={handleKey}>❯</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
#lightboxModal{
|
||||||
|
display: none;
|
||||||
|
position: fixed;
|
||||||
|
z-index: 1001;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
overflow: auto;
|
||||||
|
background-color: rgba(20, 20, 20, 0.95);
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modalControls {
|
||||||
|
display: flex;
|
||||||
|
gap: 1em;
|
||||||
|
padding: 1em;
|
||||||
|
background-color: rgba(0,0,0,0.2);
|
||||||
|
}
|
||||||
|
.modalClose {
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
.modalControls span{
|
||||||
|
color: white;
|
||||||
|
font-size: 35px;
|
||||||
|
font-weight: bold;
|
||||||
|
cursor: pointer;
|
||||||
|
width: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modalControls span:hover, .modalControls span:focus{
|
||||||
|
color: #999;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#lightboxModal > img {
|
||||||
|
display: block;
|
||||||
|
margin: auto;
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#lightboxModal > img.modalImageFullscreen{
|
||||||
|
object-fit: contain;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modalPrev,
|
||||||
|
.modalNext {
|
||||||
|
cursor: pointer;
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
width: auto;
|
||||||
|
padding: 16px;
|
||||||
|
margin-top: -50px;
|
||||||
|
color: white;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 20px;
|
||||||
|
transition: 0.6s ease;
|
||||||
|
border-radius: 0 3px 3px 0;
|
||||||
|
user-select: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modalNext {
|
||||||
|
right: 0;
|
||||||
|
border-radius: 3px 0 0 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modalPrev:hover,
|
||||||
|
.modalNext:hover {
|
||||||
|
background-color: rgba(0, 0, 0, 0.8);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -24,7 +24,9 @@ export default class ComfySaveImageNode extends ComfyGraphNode {
|
|||||||
this._imageResults = Array.from(output.images); // TODO append?
|
this._imageResults = Array.from(output.images); // TODO append?
|
||||||
const galleryItems = this._imageResults.map(r => {
|
const galleryItems = this._imageResults.map(r => {
|
||||||
// TODO
|
// TODO
|
||||||
let entry: ComfyGalleryEntry = ["http://localhost:8188/" + r.type + "/" + r.filename, null]
|
const url = "http://localhost:8188/view?"
|
||||||
|
const params = new URLSearchParams(r)
|
||||||
|
let entry: ComfyGalleryEntry = [url + params, null]
|
||||||
return entry
|
return entry
|
||||||
});
|
});
|
||||||
this._galleryWidget.setValue(galleryItems)
|
this._galleryWidget.setValue(galleryItems)
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ function getNumberDefaults(inputData: any, defaultStep: number): NumberDefaults
|
|||||||
if (max == undefined) max = 2048;
|
if (max == undefined) max = 2048;
|
||||||
if (step == undefined) step = defaultStep;
|
if (step == undefined) step = defaultStep;
|
||||||
|
|
||||||
return { val: defaultVal, config: { min, max, step: 10.0 * step, precision: 0 } };
|
return { val: defaultVal, config: { min, max, step: step, precision: 0 } };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -40,7 +40,7 @@ const INT: WidgetFactory = (node: LGraphNode, inputName: string, inputData: any)
|
|||||||
inputName,
|
inputName,
|
||||||
val,
|
val,
|
||||||
function(v) {
|
function(v) {
|
||||||
const s = this.options.step / 10;
|
const s = this.options.step;
|
||||||
this.value = Math.round(v / s) * s;
|
this.value = Math.round(v / s) * s;
|
||||||
},
|
},
|
||||||
config
|
config
|
||||||
|
|||||||
@@ -1,20 +1,43 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import { onMount } from "svelte";
|
||||||
|
import { ImageViewer } from "$lib/ImageViewer";
|
||||||
import type { WidgetUIState } from "$lib/stores/widgetState";
|
import type { WidgetUIState } from "$lib/stores/widgetState";
|
||||||
import { Block } from "@gradio/atoms";
|
import { Block } from "@gradio/atoms";
|
||||||
import { Gallery } from "@gradio/gallery";
|
import { Gallery } from "@gradio/gallery";
|
||||||
|
import type { Styles } from "@gradio/utils";
|
||||||
export let item: WidgetUIState | null = null;
|
export let item: WidgetUIState | null = null;
|
||||||
</script>
|
|
||||||
|
|
||||||
<div class="wrapper comfy-gallery-widget">
|
let style: Styles = {
|
||||||
|
// grid_cols: [2],
|
||||||
|
grid: [3],
|
||||||
|
// object_fit: "cover",
|
||||||
|
}
|
||||||
|
let element: HTMLDivElement;
|
||||||
|
|
||||||
|
function updateForLightbox() {
|
||||||
|
// Wait for gradio gallery to show the large preview image, if no timeout then
|
||||||
|
// the event might fire too early
|
||||||
|
setTimeout(() => {
|
||||||
|
const images = element.querySelectorAll<HTMLImageElement>('div.block div > img')
|
||||||
|
if (images != null) {
|
||||||
|
images.forEach(ImageViewer.instance.setupImageForLightbox.bind(ImageViewer.instance));
|
||||||
|
}
|
||||||
|
ImageViewer.instance.updateOnBackgroundChange();
|
||||||
|
}, 200)
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<div class="wrapper comfy-gallery-widget" bind:this={element}>
|
||||||
{#if item}
|
{#if item}
|
||||||
<Block variant="solid" padding={false}>
|
<Block variant="solid" padding={false}>
|
||||||
<Gallery
|
<Gallery
|
||||||
bind:value={item.value}
|
bind:value={item.value}
|
||||||
label={item.widget.name}
|
label={item.widget.name}
|
||||||
show_label={true}
|
show_label={true}
|
||||||
|
{style}
|
||||||
root={""}
|
root={""}
|
||||||
root_url={""}
|
root_url={""}
|
||||||
on:select
|
on:select={updateForLightbox}
|
||||||
/>
|
/>
|
||||||
</Block>
|
</Block>
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
Reference in New Issue
Block a user