Loads of styling
This commit is contained in:
@@ -63,6 +63,7 @@
|
|||||||
"img-comparison-slider": "^8.0.0",
|
"img-comparison-slider": "^8.0.0",
|
||||||
"pollen-css": "^4.6.2",
|
"pollen-css": "^4.6.2",
|
||||||
"radix-icons-svelte": "^1.2.1",
|
"radix-icons-svelte": "^1.2.1",
|
||||||
|
"svelte-feather-icons": "^4.0.0",
|
||||||
"svelte-preprocess": "^5.0.3",
|
"svelte-preprocess": "^5.0.3",
|
||||||
"svelte-select": "^5.5.3",
|
"svelte-select": "^5.5.3",
|
||||||
"svelte-splitpanes": "^0.7.13",
|
"svelte-splitpanes": "^0.7.13",
|
||||||
|
|||||||
9
pnpm-lock.yaml
generated
9
pnpm-lock.yaml
generated
@@ -88,6 +88,9 @@ importers:
|
|||||||
radix-icons-svelte:
|
radix-icons-svelte:
|
||||||
specifier: ^1.2.1
|
specifier: ^1.2.1
|
||||||
version: 1.2.1
|
version: 1.2.1
|
||||||
|
svelte-feather-icons:
|
||||||
|
specifier: ^4.0.0
|
||||||
|
version: 4.0.0
|
||||||
svelte-preprocess:
|
svelte-preprocess:
|
||||||
specifier: ^5.0.3
|
specifier: ^5.0.3
|
||||||
version: 5.0.3(sass@1.61.0)(svelte@3.58.0)(typescript@5.0.3)
|
version: 5.0.3(sass@1.61.0)(svelte@3.58.0)(typescript@5.0.3)
|
||||||
@@ -6097,6 +6100,12 @@ packages:
|
|||||||
svelte: 3.58.0
|
svelte: 3.58.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/svelte-feather-icons@4.0.0:
|
||||||
|
resolution: {integrity: sha512-4ieUsjp+VYa1r6y80jDt9zRiRUZyJNbESpRdHdJJhiBubyuXX96A7f1UZSK4olxzP6Qsg5ZAuyZlnmvD+/swAA==}
|
||||||
|
dependencies:
|
||||||
|
svelte: 3.58.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
/svelte-floating-ui@1.2.8:
|
/svelte-floating-ui@1.2.8:
|
||||||
resolution: {integrity: sha512-8Ifi5CD2Ui7FX7NjJRmutFtXjrB8T/FMNoS2H8P81t5LHK4I9G4NIs007rLWG/nRl7y+zJUXa3tWuTjYXw/O5A==}
|
resolution: {integrity: sha512-8Ifi5CD2Ui7FX7NjJRmutFtXjrB8T/FMNoS2H8P81t5LHK4I9G4NIs007rLWG/nRl7y+zJUXa3tWuTjYXw/O5A==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
|
import { clamp, negmod } from "./utils";
|
||||||
|
|
||||||
export class ImageViewer {
|
export class ImageViewer {
|
||||||
root: HTMLDivElement;
|
root: HTMLDivElement;
|
||||||
lightboxModal: HTMLDivElement;
|
lightboxModal: HTMLDivElement;
|
||||||
|
currentImages: string[] = []
|
||||||
|
selectedIndex: number = -1;
|
||||||
currentGallery: HTMLDivElement | null = null;
|
currentGallery: HTMLDivElement | null = null;
|
||||||
private static _instance: ImageViewer;
|
private static _instance: ImageViewer;
|
||||||
|
|
||||||
@@ -22,6 +26,8 @@ export class ImageViewer {
|
|||||||
// A full size 'lightbox' preview modal shown when left clicking on gallery previews
|
// A full size 'lightbox' preview modal shown when left clicking on gallery previews
|
||||||
closeModal() {
|
closeModal() {
|
||||||
this.lightboxModal.style.display = "none";
|
this.lightboxModal.style.display = "none";
|
||||||
|
this.currentImages = []
|
||||||
|
this.selectedIndex = -1;
|
||||||
this.currentGallery = null;
|
this.currentGallery = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,30 +42,24 @@ export class ImageViewer {
|
|||||||
return visibleGalleryButtons;
|
return visibleGalleryButtons;
|
||||||
}
|
}
|
||||||
|
|
||||||
static selected_gallery_button(gallery: HTMLDivElement): HTMLButtonElement | null {
|
static selected_gallery_button(gallery: HTMLDivElement): [HTMLButtonElement | null, number] {
|
||||||
var allCurrentButtons = gallery.querySelectorAll('.preview > .thumbnails > .thumbnail-item.thumbnail-small.selected');
|
var allCurrentButtons = gallery.querySelectorAll('.preview > .thumbnails > .thumbnail-item.thumbnail-small.selected');
|
||||||
var visibleCurrentButton = null;
|
var visibleCurrentButton = null;
|
||||||
allCurrentButtons.forEach((elem) => {
|
let index = -1;
|
||||||
|
allCurrentButtons.forEach((elem, i) => {
|
||||||
if (elem.parentElement.offsetParent) {
|
if (elem.parentElement.offsetParent) {
|
||||||
visibleCurrentButton = elem;
|
visibleCurrentButton = elem;
|
||||||
|
index = i;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return visibleCurrentButton;
|
return [visibleCurrentButton, index];
|
||||||
}
|
}
|
||||||
|
|
||||||
showModal(event: Event) {
|
showModal(imageUrls: string[], index: number, galleryElem?: HTMLDivElement) {
|
||||||
const source = (event.target || event.srcElement) as HTMLImageElement;
|
this.currentImages = imageUrls
|
||||||
const galleryElem = source.closest<HTMLDivElement>("div.block")
|
this.selectedIndex = index
|
||||||
console.debug("[ImageViewer] showModal", event, source, galleryElem);
|
|
||||||
if (!galleryElem || ImageViewer.all_gallery_buttons(galleryElem).length === 0) {
|
|
||||||
console.error("No buttons found on gallery element!", galleryElem)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.currentGallery = galleryElem;
|
this.currentGallery = galleryElem;
|
||||||
this.modalImage.src = source.src
|
this.setModalImageSrc(imageUrls[index])
|
||||||
if (this.modalImage.style.display === 'none') {
|
|
||||||
this.lightboxModal.style.setProperty('background-image', 'url(' + source.src + ')');
|
|
||||||
}
|
|
||||||
this.lightboxModal.style.display = "flex";
|
this.lightboxModal.style.display = "flex";
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.modalImage.focus()
|
this.modalImage.focus()
|
||||||
@@ -68,52 +68,52 @@ export class ImageViewer {
|
|||||||
event.stopPropagation()
|
event.stopPropagation()
|
||||||
}
|
}
|
||||||
|
|
||||||
static negmod(n: number, m: number) {
|
static get_gallery_urls(galleryElem: HTMLDivElement): string[] {
|
||||||
return ((n % m) + m) % m;
|
return ImageViewer.all_gallery_buttons(galleryElem)
|
||||||
|
.map(b => (b.children[0] as HTMLImageElement).src)
|
||||||
}
|
}
|
||||||
|
|
||||||
updateOnBackgroundChange() {
|
refreshImages() {
|
||||||
|
if (this.currentGallery) {
|
||||||
|
this.currentImages = ImageViewer.get_gallery_urls(this.currentGallery)
|
||||||
|
let [_currentButton, index] = ImageViewer.selected_gallery_button(this.currentGallery);
|
||||||
|
this.selectedIndex = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
const selectedImageUrl = this.currentImages[this.selectedIndex];
|
||||||
|
this.setModalImageSrc(selectedImageUrl)
|
||||||
|
}
|
||||||
|
|
||||||
|
private setModalImageSrc(src: string, isTiling: boolean = false) {
|
||||||
const modalImage = this.modalImage
|
const modalImage = this.modalImage
|
||||||
if (modalImage && modalImage.offsetParent && this.currentGallery) {
|
const modal = this.lightboxModal
|
||||||
let currentButton = ImageViewer.selected_gallery_button(this.currentGallery);
|
modalImage.src = src;
|
||||||
|
if (isTiling) {
|
||||||
if (currentButton?.children?.length > 0 && modalImage.src != currentButton.children[0].src) {
|
modalImage.style.display = 'none';
|
||||||
modalImage.src = currentButton.children[0].src;
|
modal.style.setProperty('background-image', `url(${modalImage.src})`)
|
||||||
if (modalImage.style.display === 'none') {
|
} else {
|
||||||
this.lightboxModal.style.setProperty('background-image', `url(${modalImage.src})`)
|
modalImage.style.display = 'block';
|
||||||
}
|
modal.style.setProperty('background-image', 'none')
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
modalImageSwitch(offset: number) {
|
modalImageSwitch(offset: number) {
|
||||||
if (!this.currentGallery)
|
this.selectedIndex = negmod(this.selectedIndex + offset, this.currentImages.length - 1);
|
||||||
return
|
const selectedImageUrl = this.currentImages[this.selectedIndex];
|
||||||
|
|
||||||
|
this.setModalImageSrc(selectedImageUrl)
|
||||||
|
|
||||||
|
if (this.currentGallery) {
|
||||||
var galleryButtons = ImageViewer.all_gallery_buttons(this.currentGallery);
|
var galleryButtons = ImageViewer.all_gallery_buttons(this.currentGallery);
|
||||||
|
var [_currentButton, index] = ImageViewer.selected_gallery_button(this.currentGallery);
|
||||||
|
|
||||||
if (galleryButtons.length > 1) {
|
if (index != -1) {
|
||||||
var currentButton = ImageViewer.selected_gallery_button(this.currentGallery);
|
const nextButton = galleryButtons[negmod((index + offset), galleryButtons.length)]
|
||||||
|
|
||||||
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()
|
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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setTimeout(() => { this.lightboxModal.focus() }, 10)
|
||||||
}
|
}
|
||||||
|
|
||||||
modalNextImage(event) {
|
modalNextImage(event) {
|
||||||
@@ -140,7 +140,7 @@ export class ImageViewer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setupImageForLightbox(e: HTMLImageElement) {
|
setupGalleryImageForLightbox(e: HTMLImageElement) {
|
||||||
if (e.dataset.modded === "true")
|
if (e.dataset.modded === "true")
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -161,7 +161,21 @@ export class ImageViewer {
|
|||||||
const initiallyZoomed = true
|
const initiallyZoomed = true
|
||||||
this.modalZoomSet(this.modalImage, initiallyZoomed)
|
this.modalZoomSet(this.modalImage, initiallyZoomed)
|
||||||
evt.preventDefault()
|
evt.preventDefault()
|
||||||
this.showModal(evt)
|
|
||||||
|
const source = evt.target as HTMLImageElement;
|
||||||
|
|
||||||
|
const galleryElem = source.closest<HTMLDivElement>("div.block")
|
||||||
|
console.debug("[ImageViewer] showModal", event, source, galleryElem);
|
||||||
|
if (!galleryElem || ImageViewer.all_gallery_buttons(galleryElem).length === 0) {
|
||||||
|
console.error("No buttons found on gallery element!", galleryElem)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let urls = ImageViewer.get_gallery_urls(galleryElem)
|
||||||
|
const [_currentButton, index] = ImageViewer.selected_gallery_button(galleryElem)
|
||||||
|
|
||||||
|
this.showModal(urls, index, galleryElem)
|
||||||
|
evt.stopPropagation();
|
||||||
}, true);
|
}, true);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -181,17 +195,8 @@ export class ImageViewer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
modalTileImageToggle(event: Event) {
|
modalTileImageToggle(event: Event) {
|
||||||
const modalImage = this.modalImage
|
const isTiling = this.modalImage.style.display === 'none';
|
||||||
const modal = this.lightboxModal
|
this.setModalImageSrc(this.modalImage.src, isTiling)
|
||||||
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()
|
event.stopPropagation()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -298,7 +298,7 @@ export default class ComfyAPI {
|
|||||||
return Promise.reject(error)
|
return Promise.reject(error)
|
||||||
}
|
}
|
||||||
|
|
||||||
return fetch("/" + type, {
|
return fetch(this.getBackendUrl() + "/" + type, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
@@ -328,6 +328,6 @@ export default class ComfyAPI {
|
|||||||
* Interrupts the execution of the running prompt
|
* Interrupts the execution of the running prompt
|
||||||
*/
|
*/
|
||||||
async interrupt(): Promise<Response> {
|
async interrupt(): Promise<Response> {
|
||||||
return fetch("/interrupt", { method: "POST" });
|
return fetch(this.getBackendUrl() + "/interrupt", { method: "POST" });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -452,8 +452,6 @@ export default class ComfyApp {
|
|||||||
|
|
||||||
this.lGraph.start();
|
this.lGraph.start();
|
||||||
this.lGraph.eventBus.on("afterExecute", () => this.lCanvas.draw(true))
|
this.lGraph.eventBus.on("afterExecute", () => this.lCanvas.draw(true))
|
||||||
|
|
||||||
uiState.update(s => { s.uiUnlocked = this.lGraph._nodes.length === 0; return s; })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async initDefaultGraph() {
|
async initDefaultGraph() {
|
||||||
@@ -468,6 +466,7 @@ export default class ComfyApp {
|
|||||||
state = structuredClone(blankGraph)
|
state = structuredClone(blankGraph)
|
||||||
}
|
}
|
||||||
await this.deserialize(state)
|
await this.deserialize(state)
|
||||||
|
uiState.update(s => { s.uiUnlocked = true; return s; })
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -2,13 +2,19 @@
|
|||||||
import queueState, { type CompletedQueueEntry, type QueueEntry, type QueueEntryStatus } from "$lib/stores/queueState";
|
import queueState, { type CompletedQueueEntry, type QueueEntry, type QueueEntryStatus } from "$lib/stores/queueState";
|
||||||
import ProgressBar from "./ProgressBar.svelte";
|
import ProgressBar from "./ProgressBar.svelte";
|
||||||
import Spinner from "./Spinner.svelte";
|
import Spinner from "./Spinner.svelte";
|
||||||
|
import { ListIcon as List } from "svelte-feather-icons";
|
||||||
import { convertComfyOutputToComfyURL, convertFilenameToComfyURL, getNodeInfo } from "$lib/utils"
|
import { convertComfyOutputToComfyURL, convertFilenameToComfyURL, getNodeInfo } from "$lib/utils"
|
||||||
import type { Writable } from "svelte/store";
|
import type { Writable } from "svelte/store";
|
||||||
import type { QueueItemType } from "$lib/api";
|
import type { QueueItemType } from "$lib/api";
|
||||||
|
import { ImageViewer } from "$lib/ImageViewer";
|
||||||
|
import { Button } from "@gradio/button";
|
||||||
|
import type ComfyApp from "./ComfyApp";
|
||||||
|
import { tick } from "svelte";
|
||||||
|
|
||||||
let queuePending: Writable<QueueEntry[]> | null = null;
|
let queuePending: Writable<QueueEntry[]> | null = null;
|
||||||
let queueRunning: Writable<QueueEntry[]> | null = null;
|
let queueRunning: Writable<QueueEntry[]> | null = null;
|
||||||
let queueCompleted: Writable<CompletedQueueEntry[]> | null = null;
|
let queueCompleted: Writable<CompletedQueueEntry[]> | null = null;
|
||||||
|
let queueList: HTMLDivElement | null = null;
|
||||||
|
|
||||||
type QueueUIEntry = {
|
type QueueUIEntry = {
|
||||||
message: string,
|
message: string,
|
||||||
@@ -28,7 +34,6 @@
|
|||||||
let mode: QueueItemType = "queue";
|
let mode: QueueItemType = "queue";
|
||||||
|
|
||||||
function switchMode(newMode: QueueItemType) {
|
function switchMode(newMode: QueueItemType) {
|
||||||
console.warn("SwitchMode", newMode)
|
|
||||||
const changed = mode !== newMode
|
const changed = mode !== newMode
|
||||||
mode = newMode
|
mode = newMode
|
||||||
if (changed)
|
if (changed)
|
||||||
@@ -66,6 +71,9 @@
|
|||||||
message = `Prompt: ${entry.extraData.subgraphs.join(', ')}`
|
message = `Prompt: ${entry.extraData.subgraphs.join(', ')}`
|
||||||
|
|
||||||
let submessage = `Nodes: ${Object.keys(entry.prompt).length}`
|
let submessage = `Nodes: ${Object.keys(entry.prompt).length}`
|
||||||
|
if (Object.keys(entry.outputs).length > 0) {
|
||||||
|
submessage = `Images: ${Object.keys(entry.outputs).length}`
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
message,
|
message,
|
||||||
@@ -80,19 +88,47 @@
|
|||||||
const result = convertEntry(entry.entry);
|
const result = convertEntry(entry.entry);
|
||||||
result.status = entry.status;
|
result.status = entry.status;
|
||||||
result.error = entry.error;
|
result.error = entry.error;
|
||||||
|
|
||||||
|
if (result.status === "all_cached")
|
||||||
|
result.submessage = "(Execution was cached)"
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateFromQueue() {
|
async function updateFromQueue() {
|
||||||
_entries = $queuePending.map(convertEntry);
|
_entries = $queuePending.map(convertEntry).reverse(); // newest entries appear at the top
|
||||||
|
if (queueList) {
|
||||||
|
await tick(); // Wait for list size to be recalculated
|
||||||
|
queueList.scroll({ top: queueList.scrollHeight })
|
||||||
|
}
|
||||||
console.warn("[ComfyQueue] BUILDQUEUE", _entries, $queuePending)
|
console.warn("[ComfyQueue] BUILDQUEUE", _entries, $queuePending)
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateFromHistory() {
|
async function updateFromHistory() {
|
||||||
_entries = $queueCompleted.map(convertCompletedEntry);
|
_entries = $queueCompleted.map(convertCompletedEntry);
|
||||||
|
if (queueList) {
|
||||||
|
await tick(); // Wait for list size to be recalculated
|
||||||
|
queueList.scroll({ top: queueList.scrollHeight })
|
||||||
|
}
|
||||||
console.warn("[ComfyQueue] BUILDHISTORY", _entries, $queueCompleted)
|
console.warn("[ComfyQueue] BUILDHISTORY", _entries, $queueCompleted)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function showLightbox(entry: QueueUIEntry, e: Event) {
|
||||||
|
e.preventDefault()
|
||||||
|
if (!entry.images)
|
||||||
|
return
|
||||||
|
|
||||||
|
ImageViewer.instance.showModal(entry.images, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function interrupt() {
|
||||||
|
const app = (window as any).app as ComfyApp;
|
||||||
|
if (!app || !app.api)
|
||||||
|
return;
|
||||||
|
|
||||||
|
await app.api.interrupt();
|
||||||
|
}
|
||||||
|
|
||||||
let queued = false
|
let queued = false
|
||||||
$: queued = Boolean($queueState.runningNodeID || $queueState.progress);
|
$: queued = Boolean($queueState.runningNodeID || $queueState.progress);
|
||||||
|
|
||||||
@@ -101,11 +137,14 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="queue">
|
<div class="queue">
|
||||||
<div class="queue-entries">
|
<div class="queue-entries" bind:this={queueList}>
|
||||||
|
{#if _entries.length > 0}
|
||||||
{#each _entries as entry}
|
{#each _entries as entry}
|
||||||
<div class="queue-entry {entry.status}">
|
<div class="queue-entry {entry.status}">
|
||||||
{#if entry.images.length > 0}
|
{#if entry.images.length > 0}
|
||||||
|
<div class="queue-entry-images" on:click={(e) => showLightbox(entry, e)}>
|
||||||
<img class="queue-entry-image" src={entry.images[0]} alt="thumbnail" />
|
<img class="queue-entry-image" src={entry.images[0]} alt="thumbnail" />
|
||||||
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<!-- <div class="queue-entry-image-placeholder" /> -->
|
<!-- <div class="queue-entry-image-placeholder" /> -->
|
||||||
{/if}
|
{/if}
|
||||||
@@ -126,14 +165,26 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
|
{:else}
|
||||||
|
<div class="queue-empty">
|
||||||
|
<div class="queue-empty-container">
|
||||||
|
<div class="queue-empty-icon">
|
||||||
|
<List size="120rem" />
|
||||||
|
</div>
|
||||||
|
<div class="queue-empty-message">
|
||||||
|
(No entries)
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<div class="mode-buttons">
|
<div class="mode-buttons">
|
||||||
<div class="mode-button"
|
<div class="mode-button secondary"
|
||||||
on:click={() => switchMode("queue")}
|
on:click={() => switchMode("queue")}
|
||||||
class:mode-selected={mode === "queue"}>
|
class:mode-selected={mode === "queue"}>
|
||||||
Queue
|
Queue
|
||||||
</div>
|
</div>
|
||||||
<div class="mode-button"
|
<div class="mode-button secondary"
|
||||||
on:click={() => switchMode("history")}
|
on:click={() => switchMode("history")}
|
||||||
class:mode-selected={mode === "history"}>
|
class:mode-selected={mode === "history"}>
|
||||||
History
|
History
|
||||||
@@ -159,6 +210,11 @@
|
|||||||
<div>
|
<div>
|
||||||
<ProgressBar value={$queueState.progress?.value} max={$queueState.progress?.max} />
|
<ProgressBar value={$queueState.progress?.value} max={$queueState.progress?.max} />
|
||||||
</div>
|
</div>
|
||||||
|
<div class="queue-action-buttons">
|
||||||
|
<Button variant="secondary" on:click={interrupt} style={{ full_width: true }}>
|
||||||
|
Interrupt
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -177,13 +233,37 @@
|
|||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
height: $queue-height;
|
height: $queue-height;
|
||||||
max-height: $queue-height;
|
max-height: $queue-height;
|
||||||
|
|
||||||
|
> .queue-empty {
|
||||||
|
display: flex;
|
||||||
|
color: var(--comfy-accent-soft);
|
||||||
|
flex-direction: row;
|
||||||
|
margin: auto;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
> .queue-empty-container {
|
||||||
|
margin: auto;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
> .queue-empty-icon {
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
> .queue-empty-message {
|
||||||
|
margin: auto;
|
||||||
|
font-size: 32px;
|
||||||
|
font-weight: bolder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.queue-entry {
|
.queue-entry {
|
||||||
padding: 1.0rem;
|
padding: 1.0rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
border-bottom: 1px solid var(--panel-border-color);
|
border-bottom: 1px solid var(--block-border-color);
|
||||||
|
border-top: 1px solid var(--table-border-color);
|
||||||
background: var(--panel-background-fill);
|
background: var(--panel-background-fill);
|
||||||
|
|
||||||
&.success {
|
&.success {
|
||||||
@@ -193,7 +273,9 @@
|
|||||||
background: red;
|
background: red;
|
||||||
}
|
}
|
||||||
&.all_cached {
|
&.all_cached {
|
||||||
background: grey;
|
filter: brightness(80%);
|
||||||
|
background: var(--neutral-600);
|
||||||
|
color: var(--neutral-300);
|
||||||
}
|
}
|
||||||
&.running {
|
&.running {
|
||||||
/* background: lightblue; */
|
/* background: lightblue; */
|
||||||
@@ -203,8 +285,17 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.queue-entry-image {
|
.queue-entry-images {
|
||||||
width: var(--size-20);
|
height: 100%;
|
||||||
|
aspect-ratio: 1/1;
|
||||||
|
margin: auto;
|
||||||
|
|
||||||
|
> .queue-entry-image {
|
||||||
|
filter: none;
|
||||||
|
&:hover {
|
||||||
|
filter: brightness(120%) contrast(120%);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.queue-entry-image-placeholder {
|
.queue-entry-image-placeholder {
|
||||||
@@ -240,28 +331,45 @@
|
|||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
position:absolute;
|
position:absolute;
|
||||||
right: 0px;
|
right: 0px;
|
||||||
bottom:0px;
|
bottom: 0px;
|
||||||
padding: 0.0rem 0.4rem;
|
padding: 0.0rem 0.4rem;
|
||||||
color: var(--body-text-color);
|
color: var(--body-text-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.mode-buttons {
|
.mode-buttons {
|
||||||
height: calc($mode-buttons-height);
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
text-align: center;
|
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
> .mode-button {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.mode-button {
|
.mode-button {
|
||||||
|
height: calc($mode-buttons-height);
|
||||||
padding: 0.2rem;
|
padding: 0.2rem;
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
border: 1px solid var(--panel-border-color);
|
border: 1px solid var(--panel-border-color);
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
background: var(--button-secondary-background-fill);
|
text-align: center;
|
||||||
|
margin: auto;
|
||||||
|
|
||||||
|
&.primary {
|
||||||
|
background: var(--button-primary-background-fill);
|
||||||
|
&:hover {
|
||||||
|
background: var(--button-primary-background-fill-hover);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.secondary {
|
||||||
|
background: var(--button-secondary-background-fill);
|
||||||
&:hover {
|
&:hover {
|
||||||
background: var(--button-secondary-background-fill-hover);
|
background: var(--button-secondary-background-fill-hover);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
filter: brightness(120%);
|
filter: brightness(120%);
|
||||||
}
|
}
|
||||||
&:active {
|
&:active {
|
||||||
@@ -271,18 +379,17 @@
|
|||||||
filter: brightness(150%)
|
filter: brightness(150%)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.bottom {
|
.bottom {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: calc($pending-height);
|
height: calc($pending-height);
|
||||||
position: absolute;
|
position: absolute;
|
||||||
border: 2px solid var(--panel-border-color);
|
|
||||||
|
|
||||||
.node-name {
|
.node-name {
|
||||||
background-color: var(--comfy-node-name-background);
|
background-color: var(--comfy-node-name-background);
|
||||||
color: var(--comfy-node-name-foreground);
|
color: var(--comfy-node-name-foreground);
|
||||||
padding: 0.2em;
|
padding: 0.2em;
|
||||||
|
margin: 5px;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -302,7 +409,16 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&.queued {
|
&.queued {
|
||||||
height: calc($pending-height - $bottom-bar-height);
|
height: calc($pending-height - $mode-buttons-height - $bottom-bar-height - 16px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.queue-action-buttons {
|
||||||
|
margin: 5px;
|
||||||
|
height: 20px;
|
||||||
|
|
||||||
|
:global(button) {
|
||||||
|
border-radius: 0px !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,8 +23,8 @@
|
|||||||
|
|
||||||
<style>
|
<style>
|
||||||
.progress {
|
.progress {
|
||||||
width: 100%;
|
|
||||||
height: 30px;
|
height: 30px;
|
||||||
|
margin: 5px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
background: var(--comfy-progress-bar-background);
|
background: var(--comfy-progress-bar-background);
|
||||||
padding: 0px;
|
padding: 0px;
|
||||||
|
|||||||
@@ -161,7 +161,7 @@ export abstract class ComfyWidgetNode<T = any> extends ComfyGraphNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private triggerChangeEvent(value: any) {
|
private triggerChangeEvent(value: any) {
|
||||||
console.debug("[Widget] trigger changed", this, value)
|
// console.debug("[Widget] trigger changed", this, value)
|
||||||
const changedOutput = this.outputs[this.changedIndex]
|
const changedOutput = this.outputs[this.changedIndex]
|
||||||
if (changedOutput.type === BuiltInSlotType.EVENT)
|
if (changedOutput.type === BuiltInSlotType.EVENT)
|
||||||
this.triggerSlot(this.changedIndex, value)
|
this.triggerSlot(this.changedIndex, value)
|
||||||
@@ -271,7 +271,7 @@ export abstract class ComfyWidgetNode<T = any> extends ComfyGraphNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.debug("Property copy", input, this.properties)
|
// console.debug("Property copy", input, this.properties)
|
||||||
|
|
||||||
this.setValue(get(this.value))
|
this.setValue(get(this.value))
|
||||||
|
|
||||||
@@ -288,7 +288,7 @@ export abstract class ComfyWidgetNode<T = any> extends ComfyGraphNode {
|
|||||||
if (layoutEntry && layoutEntry.parent) {
|
if (layoutEntry && layoutEntry.parent) {
|
||||||
layoutEntry.parent.attrsChanged.set(get(layoutEntry.parent.attrsChanged) + 1)
|
layoutEntry.parent.attrsChanged.set(get(layoutEntry.parent.attrsChanged) + 1)
|
||||||
}
|
}
|
||||||
console.debug("propsChanged", this)
|
// console.debug("propsChanged", this)
|
||||||
this.propsChanged.set(get(this.propsChanged) + 1)
|
this.propsChanged.set(get(this.propsChanged) + 1)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -122,6 +122,34 @@ function statusUpdated(status: ComfyAPIStatusResponse | null) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function findEntryInPending(promptID: PromptID): [number, QueueEntry, Writable<QueueEntry[]>] | null {
|
||||||
|
const state = get(store);
|
||||||
|
let index = get(state.queuePending).findIndex(e => e.promptID === promptID)
|
||||||
|
if (index)
|
||||||
|
return [index, get(state.queuePending)[index], state.queuePending]
|
||||||
|
|
||||||
|
index = get(state.queueRunning).findIndex(e => e.promptID === promptID)
|
||||||
|
if (index)
|
||||||
|
return [index, get(state.queueRunning)[index], state.queueRunning]
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
function moveToCompleted(index: number, queue: Writable<QueueEntry[]>, status: QueueEntryStatus, error?: string) {
|
||||||
|
const state = get(store)
|
||||||
|
|
||||||
|
const entry = get(queue)[index];
|
||||||
|
entry.finishedAt = new Date() // Now
|
||||||
|
queue.update(qp => { qp.splice(index, 1); return qp });
|
||||||
|
state.queueCompleted.update(qc => {
|
||||||
|
const completed: CompletedQueueEntry = { entry, status, error }
|
||||||
|
qc.push(completed)
|
||||||
|
return qc
|
||||||
|
})
|
||||||
|
|
||||||
|
store.set(state)
|
||||||
|
}
|
||||||
|
|
||||||
function executingUpdated(promptID: PromptID | null, runningNodeID: NodeID | null) {
|
function executingUpdated(promptID: PromptID | null, runningNodeID: NodeID | null) {
|
||||||
console.debug("[queueState] executingUpdated", promptID, runningNodeID)
|
console.debug("[queueState] executingUpdated", promptID, runningNodeID)
|
||||||
store.update((s) => {
|
store.update((s) => {
|
||||||
@@ -131,20 +159,12 @@ function executingUpdated(promptID: PromptID | null, runningNodeID: NodeID | nul
|
|||||||
}
|
}
|
||||||
else if (promptID != null) {
|
else if (promptID != null) {
|
||||||
// Prompt finished executing.
|
// Prompt finished executing.
|
||||||
const queuePending = get(s.queuePending)
|
const [index, entry, queue] = findEntryInPending(promptID);
|
||||||
const index = queuePending.findIndex(e => e.promptID === promptID)
|
if (entry) {
|
||||||
if (index) {
|
moveToCompleted(index, queue, "success")
|
||||||
const entry = queuePending[index]
|
|
||||||
entry.finishedAt = new Date() // Now
|
|
||||||
s.queuePending.update(qp => { qp.splice(index, 1); return qp });
|
|
||||||
s.queueCompleted.update(qc => {
|
|
||||||
const completed: CompletedQueueEntry = {
|
|
||||||
entry,
|
|
||||||
status: "success",
|
|
||||||
}
|
}
|
||||||
qc.push(completed)
|
else {
|
||||||
return qc
|
console.error("[queueState] Could not find in pending! (executingUpdated)", promptID)
|
||||||
})
|
|
||||||
}
|
}
|
||||||
s.progress = null;
|
s.progress = null;
|
||||||
s.runningNodeID = null;
|
s.runningNodeID = null;
|
||||||
@@ -156,23 +176,14 @@ function executingUpdated(promptID: PromptID | null, runningNodeID: NodeID | nul
|
|||||||
function executionCached(promptID: PromptID, nodes: NodeID[]) {
|
function executionCached(promptID: PromptID, nodes: NodeID[]) {
|
||||||
console.debug("[queueState] executionCached", promptID, nodes)
|
console.debug("[queueState] executionCached", promptID, nodes)
|
||||||
store.update(s => {
|
store.update(s => {
|
||||||
const queuePending = get(s.queuePending)
|
const [index, entry, queue] = findEntryInPending(promptID);
|
||||||
const index = queuePending.findIndex(e => e.promptID === promptID)
|
if (entry) {
|
||||||
if (index) {
|
if (nodes.length >= Object.keys(entry.prompt).length) {
|
||||||
const entry = queuePending[index]
|
moveToCompleted(index, queue, "all_cached");
|
||||||
|
|
||||||
if (nodes.length >= Object.keys(entry.prompt.output).length) {
|
|
||||||
entry.finishedAt = new Date() // Now
|
|
||||||
s.queuePending.update(qp => { qp.splice(index, 1); return qp });
|
|
||||||
s.queueCompleted.update(qc => {
|
|
||||||
const completed: CompletedQueueEntry = {
|
|
||||||
entry,
|
|
||||||
status: "all_cached",
|
|
||||||
}
|
}
|
||||||
qc.push(completed)
|
|
||||||
return qc
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
console.error("[queueState] Could not find in pending! (executionCached)", promptID)
|
||||||
}
|
}
|
||||||
s.progress = null;
|
s.progress = null;
|
||||||
s.runningNodeID = null;
|
s.runningNodeID = null;
|
||||||
@@ -183,21 +194,12 @@ function executionCached(promptID: PromptID, nodes: NodeID[]) {
|
|||||||
function executionError(promptID: PromptID, message: string) {
|
function executionError(promptID: PromptID, message: string) {
|
||||||
console.debug("[queueState] executionError", promptID, message)
|
console.debug("[queueState] executionError", promptID, message)
|
||||||
store.update(s => {
|
store.update(s => {
|
||||||
const queuePending = get(s.queuePending)
|
const [index, entry, queue] = findEntryInPending(promptID);
|
||||||
const index = queuePending.findIndex(e => e.promptID === promptID)
|
if (entry) {
|
||||||
if (index) {
|
moveToCompleted(index, queue, "error", message)
|
||||||
const entry = s.queuePending[index]
|
|
||||||
entry.finishedAt = new Date() // Now
|
|
||||||
s.queuePending.update(qp => { qp.splice(index, 1); return qp });
|
|
||||||
s.queueCompleted.update(qc => {
|
|
||||||
const completed: CompletedQueueEntry = {
|
|
||||||
entry,
|
|
||||||
status: "error",
|
|
||||||
error: message
|
|
||||||
}
|
}
|
||||||
qc.push(completed)
|
else {
|
||||||
return qc
|
console.error("[queueState] Could not find in pending! (executionError)", promptID)
|
||||||
})
|
|
||||||
}
|
}
|
||||||
s.progress = null;
|
s.progress = null;
|
||||||
s.runningNodeID = null;
|
s.runningNodeID = null;
|
||||||
@@ -206,7 +208,7 @@ function executionError(promptID: PromptID, message: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function afterQueued(promptID: PromptID, number: number, prompt: SerializedPromptInputsAll, extraData: any) {
|
function afterQueued(promptID: PromptID, number: number, prompt: SerializedPromptInputsAll, extraData: any) {
|
||||||
console.debug("[queueState] afterQueued", promptID, Object.keys(prompt.nodes))
|
console.debug("[queueState] afterQueued", promptID, Object.keys(prompt))
|
||||||
store.update(s => {
|
store.update(s => {
|
||||||
const entry: QueueEntry = {
|
const entry: QueueEntry = {
|
||||||
number,
|
number,
|
||||||
@@ -226,11 +228,13 @@ function afterQueued(promptID: PromptID, number: number, prompt: SerializedPromp
|
|||||||
function onExecuted(promptID: PromptID, nodeID: NodeID, output: GalleryOutput) {
|
function onExecuted(promptID: PromptID, nodeID: NodeID, output: GalleryOutput) {
|
||||||
console.debug("[queueState] onExecuted", promptID, nodeID, output)
|
console.debug("[queueState] onExecuted", promptID, nodeID, output)
|
||||||
store.update(s => {
|
store.update(s => {
|
||||||
const queuePending = get(s.queuePending)
|
const [index, entry, queue] = findEntryInPending(promptID)
|
||||||
const entry = queuePending.find(e => e.promptID === promptID)
|
|
||||||
if (entry) {
|
if (entry) {
|
||||||
entry.outputs[nodeID] = output;
|
entry.outputs[nodeID] = output;
|
||||||
s.queuePending.update(qp => { qp.push(entry); return qp; })
|
queue.set(get(queue))
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.error("[queueState] Could not find in pending! (onExecuted)", promptID)
|
||||||
}
|
}
|
||||||
return s
|
return s
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -13,6 +13,10 @@ export function clamp(n: number, min: number, max: number): number {
|
|||||||
return Math.min(Math.max(n, min), max)
|
return Math.min(Math.max(n, min), max)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function negmod(n: number, m: number): number {
|
||||||
|
return ((n % m) + m) % m;
|
||||||
|
}
|
||||||
|
|
||||||
export function range(size: number, startAt: number = 0): ReadonlyArray<number> {
|
export function range(size: number, startAt: number = 0): ReadonlyArray<number> {
|
||||||
return [...Array(size).keys()].map(i => i + startAt);
|
return [...Array(size).keys()].map(i => i + startAt);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -122,14 +122,14 @@
|
|||||||
// the event might fire too early
|
// the event might fire too early
|
||||||
|
|
||||||
const callback = isMobile ? setupImageForMobileLightbox
|
const callback = isMobile ? setupImageForMobileLightbox
|
||||||
: ImageViewer.instance.setupImageForLightbox.bind(ImageViewer.instance)
|
: ImageViewer.instance.setupGalleryImageForLightbox.bind(ImageViewer.instance)
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const images = element.querySelectorAll<HTMLImageElement>('div.block div > img')
|
const images = element.querySelectorAll<HTMLImageElement>('div.block div > img')
|
||||||
if (images != null) {
|
if (images != null) {
|
||||||
images.forEach(callback);
|
images.forEach(callback);
|
||||||
}
|
}
|
||||||
ImageViewer.instance.updateOnBackgroundChange();
|
ImageViewer.instance.refreshImages();
|
||||||
}, 200)
|
}, 200)
|
||||||
|
|
||||||
// Update index
|
// Update index
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ body {
|
|||||||
:root {
|
:root {
|
||||||
--color-blue-500: #3985f5;
|
--color-blue-500: #3985f5;
|
||||||
|
|
||||||
|
--comfy-accent-soft: var(--neutral-400);
|
||||||
--comfy-splitpanes-background-fill: var(--secondary-100);
|
--comfy-splitpanes-background-fill: var(--secondary-100);
|
||||||
--comfy-splitpanes-background-fill-hover: var(--secondary-300);
|
--comfy-splitpanes-background-fill-hover: var(--secondary-300);
|
||||||
--comfy-splitpanes-background-fill-active: var(--secondary-400);
|
--comfy-splitpanes-background-fill-active: var(--secondary-400);
|
||||||
@@ -21,8 +22,8 @@ body {
|
|||||||
--comfy-dropdown-item-background-hover: var(--neutral-400);
|
--comfy-dropdown-item-background-hover: var(--neutral-400);
|
||||||
--comfy-dropdown-item-color-active: var(--neutral-100);
|
--comfy-dropdown-item-color-active: var(--neutral-100);
|
||||||
--comfy-dropdown-item-background-active: var(--secondary-600);
|
--comfy-dropdown-item-background-active: var(--secondary-600);
|
||||||
--comfy-progress-bar-background: var(--secondary-300);
|
--comfy-progress-bar-background: var(--neutral-300);
|
||||||
--comfy-progress-bar-foreground: #var(--body-text-color);
|
--comfy-progress-bar-foreground: var(--secondary-300);
|
||||||
--comfy-node-name-background: var(--color-red-300);
|
--comfy-node-name-background: var(--color-red-300);
|
||||||
--comfy-node-name-foreground: var(--body-text-color);
|
--comfy-node-name-foreground: var(--body-text-color);
|
||||||
--comfy-spinner-main-color: var(--neutral-400);
|
--comfy-spinner-main-color: var(--neutral-400);
|
||||||
@@ -32,6 +33,7 @@ body {
|
|||||||
.dark {
|
.dark {
|
||||||
color-scheme: dark;
|
color-scheme: dark;
|
||||||
|
|
||||||
|
--comfy-accent-soft: var(--neutral-600);
|
||||||
--comfy-splitpanes-background-fill: var(--panel-border-color);
|
--comfy-splitpanes-background-fill: var(--panel-border-color);
|
||||||
--comfy-splitpanes-background-fill-hover: var(--secondary-500);
|
--comfy-splitpanes-background-fill-hover: var(--secondary-500);
|
||||||
--comfy-splitpanes-background-fill-active: var(--secondary-300);
|
--comfy-splitpanes-background-fill-active: var(--secondary-300);
|
||||||
@@ -40,9 +42,9 @@ body {
|
|||||||
--comfy-dropdown-item-background-hover: var(--neutral-600);
|
--comfy-dropdown-item-background-hover: var(--neutral-600);
|
||||||
--comfy-dropdown-item-background-active: var(--secondary-600);
|
--comfy-dropdown-item-background-active: var(--secondary-600);
|
||||||
--comfy-dropdown-border-color: var(--neutral-600);
|
--comfy-dropdown-border-color: var(--neutral-600);
|
||||||
--comfy-progress-bar-background: var(--secondary-400);
|
--comfy-progress-bar-background: var(--neutral-500);
|
||||||
--comfy-progress-bar-foreground: #var(--body-text-color);
|
--comfy-progress-bar-foreground: var(--secondary-400);
|
||||||
--comfy-node-name-background: var(--primary-500);
|
--comfy-node-name-background: var(--neutral-700);
|
||||||
--comfy-node-name-foreground: var(--body-text-color);
|
--comfy-node-name-foreground: var(--body-text-color);
|
||||||
--comfy-spinner-main-color: var(--neutral-600);
|
--comfy-spinner-main-color: var(--neutral-600);
|
||||||
--comfy-spinner-accent-color: var(--secondary-600);
|
--comfy-spinner-accent-color: var(--secondary-600);
|
||||||
@@ -96,6 +98,30 @@ select {
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// button {
|
||||||
|
// filter: none;
|
||||||
|
// &.primary:active {
|
||||||
|
// filter: brightness(80%)
|
||||||
|
// }
|
||||||
|
// &.secondary:active {
|
||||||
|
// filter: brightness(80%)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
button {
|
||||||
|
&.primary:active {
|
||||||
|
border-color: var(--button-primary-border-color-active) !important;
|
||||||
|
background: var(--button-primary-background-fill-active) !important;
|
||||||
|
color: var(--button-primary-text-color-active) !important;
|
||||||
|
}
|
||||||
|
&.secondary:active {
|
||||||
|
border-color: var(--button-secondary-border-color-active) !important;
|
||||||
|
background: var(--button-secondary-background-fill-active) !important;
|
||||||
|
color: var(--button-secondary-text-color-active) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.widget {
|
.widget {
|
||||||
// padding: var(--ae-outside-gap-size);
|
// padding: var(--ae-outside-gap-size);
|
||||||
// border: 1px solid var(--ae-panel-border-color);
|
// border: 1px solid var(--ae-panel-border-color);
|
||||||
|
|||||||
@@ -180,16 +180,22 @@
|
|||||||
--button-large-text-weight: 600;
|
--button-large-text-weight: 600;
|
||||||
--button-primary-background-fill: linear-gradient(to bottom right, var(--primary-100), var(--primary-300));
|
--button-primary-background-fill: linear-gradient(to bottom right, var(--primary-100), var(--primary-300));
|
||||||
--button-primary-background-fill-hover: linear-gradient(to bottom right, var(--primary-100), var(--primary-200));
|
--button-primary-background-fill-hover: linear-gradient(to bottom right, var(--primary-100), var(--primary-200));
|
||||||
|
--button-primary-background-fill-active: linear-gradient(to bottom right, var(--primary-200), var(--primary-400));
|
||||||
--button-primary-border-color: var(--primary-200);
|
--button-primary-border-color: var(--primary-200);
|
||||||
--button-primary-border-color-hover: var(--button-primary-border-color);
|
--button-primary-border-color-hover: var(--button-primary-border-color);
|
||||||
|
--button-primary-border-color-active: var(--button-primary-border-color);
|
||||||
--button-primary-text-color: var(--primary-600);
|
--button-primary-text-color: var(--primary-600);
|
||||||
--button-primary-text-color-hover: var(--button-primary-text-color);
|
--button-primary-text-color-hover: var(--button-primary-text-color);
|
||||||
|
--button-primary-text-color-active: var(--button-primary-text-color);
|
||||||
--button-secondary-background-fill: linear-gradient(to bottom right, var(--neutral-100), var(--neutral-200));
|
--button-secondary-background-fill: linear-gradient(to bottom right, var(--neutral-100), var(--neutral-200));
|
||||||
--button-secondary-background-fill-hover: linear-gradient(to bottom right, var(--neutral-100), var(--neutral-100));
|
--button-secondary-background-fill-hover: linear-gradient(to bottom right, var(--neutral-100), var(--neutral-100));
|
||||||
|
--button-secondary-background-fill-active: linear-gradient(to bottom right, var(--neutral-200), var(--neutral-300));
|
||||||
--button-secondary-border-color: var(--neutral-200);
|
--button-secondary-border-color: var(--neutral-200);
|
||||||
--button-secondary-border-color-hover: var(--button-secondary-border-color);
|
--button-secondary-border-color-hover: var(--button-secondary-border-color);
|
||||||
|
--button-secondary-border-color-active: var(--button-secondary-border-color);
|
||||||
--button-secondary-text-color: var(--neutral-700);
|
--button-secondary-text-color: var(--neutral-700);
|
||||||
--button-secondary-text-color-hover: var(--button-secondary-text-color);
|
--button-secondary-text-color-hover: var(--button-secondary-text-color);
|
||||||
|
--button-secondary-text-color-active: var(--neutral-800);
|
||||||
--button-shadow: var(--shadow-drop);
|
--button-shadow: var(--shadow-drop);
|
||||||
--button-shadow-active: var(--shadow-inset);
|
--button-shadow-active: var(--shadow-inset);
|
||||||
--button-shadow-hover: var(--shadow-drop-lg);
|
--button-shadow-hover: var(--shadow-drop-lg);
|
||||||
@@ -277,16 +283,22 @@
|
|||||||
--button-cancel-text-color-hover: var(--button-cancel-text-color);
|
--button-cancel-text-color-hover: var(--button-cancel-text-color);
|
||||||
--button-primary-background-fill: linear-gradient(to bottom right, var(--primary-500), var(--primary-600));
|
--button-primary-background-fill: linear-gradient(to bottom right, var(--primary-500), var(--primary-600));
|
||||||
--button-primary-background-fill-hover: linear-gradient(to bottom right, var(--primary-500), var(--primary-500));
|
--button-primary-background-fill-hover: linear-gradient(to bottom right, var(--primary-500), var(--primary-500));
|
||||||
|
--button-primary-background-fill-active: linear-gradient(to bottom right, var(--primary-600), var(--primary-700));
|
||||||
--button-primary-border-color: var(--primary-500);
|
--button-primary-border-color: var(--primary-500);
|
||||||
--button-primary-border-color-hover: var(--button-primary-border-color);
|
--button-primary-border-color-hover: var(--button-primary-border-color);
|
||||||
|
--button-primary-border-color-active: var(--button-primary-border-color);
|
||||||
--button-primary-text-color: white;
|
--button-primary-text-color: white;
|
||||||
--button-primary-text-color-hover: var(--button-primary-text-color);
|
--button-primary-text-color-hover: var(--button-primary-text-color);
|
||||||
|
--button-primary-text-color-active: var(--neutral-300);
|
||||||
--button-secondary-background-fill: linear-gradient(to bottom right, var(--neutral-600), var(--neutral-700));
|
--button-secondary-background-fill: linear-gradient(to bottom right, var(--neutral-600), var(--neutral-700));
|
||||||
--button-secondary-background-fill-hover: linear-gradient(to bottom right, var(--neutral-600), var(--neutral-600));
|
--button-secondary-background-fill-hover: linear-gradient(to bottom right, var(--neutral-600), var(--neutral-600));
|
||||||
|
--button-secondary-background-fill-active: linear-gradient(to bottom right, var(--neutral-700), var(--neutral-800));
|
||||||
--button-secondary-border-color: var(--neutral-600);
|
--button-secondary-border-color: var(--neutral-600);
|
||||||
--button-secondary-border-color-hover: var(--button-secondary-border-color);
|
--button-secondary-border-color-hover: var(--button-secondary-border-color);
|
||||||
|
--button-secondary-border-color-active: var(--button-secondary-border-color);
|
||||||
--button-secondary-text-color: white;
|
--button-secondary-text-color: white;
|
||||||
--button-secondary-text-color-hover: var(--button-secondary-text-color);
|
--button-secondary-text-color-hover: var(--button-secondary-text-color);
|
||||||
|
--button-secondary-text-color-active: var(--neutral-300);
|
||||||
--name: default;
|
--name: default;
|
||||||
--primary-50: #fff7ed;
|
--primary-50: #fff7ed;
|
||||||
--primary-100: #ffedd5;
|
--primary-100: #ffedd5;
|
||||||
|
|||||||
Reference in New Issue
Block a user