Working lightbox modal ported from A1111
This commit is contained in:
@@ -6,15 +6,19 @@
|
||||
import ComfyUIPane from "./ComfyUIPane.svelte";
|
||||
import ComfyApp, { type SerializedAppState } from "./ComfyApp";
|
||||
import widgetState from "$lib/stores/widgetState";
|
||||
import { ImageViewer } from "$lib/ImageViewer";
|
||||
|
||||
import { LGraph, LGraphNode } from "@litegraph-ts/core";
|
||||
import LightboxModal from "./LightboxModal.svelte";
|
||||
|
||||
let app: ComfyApp = undefined;
|
||||
let imageViewer: ImageViewer;
|
||||
let uiPane: ComfyUIPane = undefined;
|
||||
let mainElem: HTMLDivElement;
|
||||
let containerElem: HTMLDivElement;
|
||||
let resizeTimeout: typeof Timer = -1;
|
||||
|
||||
function refreshView(event) {
|
||||
function refreshView(event?: Event) {
|
||||
clearTimeout(resizeTimeout);
|
||||
resizeTimeout = setTimeout(app.resizeCanvas.bind(app), 250);
|
||||
}
|
||||
@@ -87,9 +91,11 @@
|
||||
(window as any).app = app;
|
||||
(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) {
|
||||
const paneNode = wrapper.parentNode; // get the node inside the <Pane/>
|
||||
const paneNode = wrapper.parentNode as HTMLElement; // get the node inside the <Pane/>
|
||||
paneNode.ontransitionend = () => {
|
||||
app.resizeCanvas()
|
||||
}
|
||||
@@ -97,38 +103,41 @@
|
||||
})
|
||||
</script>
|
||||
|
||||
<div id="dropzone" class="dropzone"></div>
|
||||
<div id="container" bind:this={containerElem}>
|
||||
<Splitpanes theme="comfy" on:resize={refreshView}>
|
||||
<Pane>
|
||||
<Splitpanes theme="comfy" on:resize={refreshView} horizontal="{true}">
|
||||
<Pane>
|
||||
<ComfyUIPane bind:this={uiPane} {app} />
|
||||
</Pane>
|
||||
<Pane bind:size={graphSize}>
|
||||
<div class="canvas-wrapper pane-wrapper">
|
||||
<canvas id="graph-canvas" />
|
||||
</div>
|
||||
</Pane>
|
||||
</Splitpanes>
|
||||
</Pane>
|
||||
<Pane bind:size={sidebarSize}>
|
||||
<div class="sidebar-wrapper pane-wrapper">
|
||||
Sidebar
|
||||
</div>
|
||||
</Pane>
|
||||
</Splitpanes>
|
||||
</div>
|
||||
<div id="bottombar">
|
||||
<Button variant="primary" on:click={queuePrompt}>
|
||||
Run
|
||||
</Button>
|
||||
<Button variant="secondary" on:click={toggleGraph}>
|
||||
Toggle Graph
|
||||
</Button>
|
||||
<Button variant="secondary" on:click={toggleSidebar}>
|
||||
Toggle Sidebar
|
||||
</Button>
|
||||
<div id="main" bind:this={mainElem}>
|
||||
<div id="dropzone" class="dropzone"></div>
|
||||
<div id="container" bind:this={containerElem}>
|
||||
<Splitpanes theme="comfy" on:resize={refreshView}>
|
||||
<Pane>
|
||||
<Splitpanes theme="comfy" on:resize={refreshView} horizontal="{true}">
|
||||
<Pane>
|
||||
<ComfyUIPane bind:this={uiPane} {app} />
|
||||
</Pane>
|
||||
<Pane bind:size={graphSize}>
|
||||
<div class="canvas-wrapper pane-wrapper">
|
||||
<canvas id="graph-canvas" />
|
||||
</div>
|
||||
</Pane>
|
||||
</Splitpanes>
|
||||
</Pane>
|
||||
<Pane bind:size={sidebarSize}>
|
||||
<div class="sidebar-wrapper pane-wrapper">
|
||||
Sidebar
|
||||
</div>
|
||||
</Pane>
|
||||
</Splitpanes>
|
||||
</div>
|
||||
<div id="bottombar">
|
||||
<Button variant="primary" on:click={queuePrompt}>
|
||||
Run
|
||||
</Button>
|
||||
<Button variant="secondary" on:click={toggleGraph}>
|
||||
Toggle Graph
|
||||
</Button>
|
||||
<Button variant="secondary" on:click={toggleSidebar}>
|
||||
Toggle Sidebar
|
||||
</Button>
|
||||
</div>
|
||||
<LightboxModal />
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
@@ -59,6 +59,7 @@ export type Progress = {
|
||||
|
||||
export default class ComfyApp {
|
||||
api: ComfyAPI;
|
||||
rootEl: HTMLDivElement | null = null;
|
||||
canvasEl: HTMLCanvasElement | null = null;
|
||||
canvasCtx: CanvasRenderingContext2D | null = null;
|
||||
lGraph: LGraph | null = null;
|
||||
@@ -81,6 +82,7 @@ export default class ComfyApp {
|
||||
}
|
||||
|
||||
async setup(): Promise<void> {
|
||||
this.rootEl = document.getElementById("main") as HTMLDivElement;
|
||||
this.canvasEl = document.getElementById("graph-canvas") as HTMLCanvasElement;
|
||||
this.lGraph = new 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>
|
||||
Reference in New Issue
Block a user