mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-26 09:44:06 +00:00
fix(types): remove @ts-expect-error suppressions from src/scripts
This commit is contained in:
@@ -15,7 +15,7 @@ import '@/assets/css/style.css'
|
||||
|
||||
const ComfyUIPreset = definePreset(Aura, {
|
||||
semantic: {
|
||||
// @ts-expect-error fix me
|
||||
// @ts-expect-error PrimeVue type issue
|
||||
primary: Aura['primitive'].blue
|
||||
}
|
||||
})
|
||||
|
||||
@@ -14,7 +14,7 @@ import { i18n } from '@/i18n'
|
||||
|
||||
const ComfyUIPreset = definePreset(Aura, {
|
||||
semantic: {
|
||||
// @ts-expect-error prime type quirk
|
||||
// @ts-expect-error PrimeVue type issue
|
||||
primary: Aura['primitive'].blue
|
||||
}
|
||||
})
|
||||
|
||||
@@ -15,7 +15,7 @@ import router from './router'
|
||||
|
||||
const ComfyUIPreset = definePreset(Aura, {
|
||||
semantic: {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
// @ts-expect-error PrimeVue type issue
|
||||
primary: Aura['primitive'].blue
|
||||
}
|
||||
})
|
||||
|
||||
@@ -162,8 +162,8 @@ export class ComfyApp {
|
||||
|
||||
// TODO: Migrate internal usage to the
|
||||
/** @deprecated Use {@link rootGraph} instead */
|
||||
get graph(): unknown {
|
||||
return this.rootGraphInternal!
|
||||
get graph(): LGraph | undefined {
|
||||
return this.rootGraphInternal
|
||||
}
|
||||
|
||||
get rootGraph(): LGraph {
|
||||
@@ -1194,8 +1194,12 @@ export class ComfyApp {
|
||||
}
|
||||
|
||||
try {
|
||||
// @ts-expect-error Discrepancies between zod and litegraph - in progress
|
||||
this.rootGraph.configure(graphData)
|
||||
// TODO: Align ComfyWorkflowJSON (Zod schema) with ISerialisedGraph (litegraph types)
|
||||
// The schemas are structurally compatible at runtime but TypeScript can't verify this.
|
||||
// See: https://github.com/Comfy-Org/ComfyUI_frontend/issues/XXXX
|
||||
this.rootGraph.configure(
|
||||
graphData as Parameters<typeof this.rootGraph.configure>[0]
|
||||
)
|
||||
|
||||
// Save original renderer version before scaling (it gets modified during scaling)
|
||||
const originalMainGraphRenderer =
|
||||
|
||||
@@ -198,13 +198,15 @@ abstract class BaseDOMWidgetImpl<V extends object | string>
|
||||
}
|
||||
|
||||
override createCopyForNode(node: LGraphNode): this {
|
||||
// @ts-expect-error
|
||||
const cloned: this = new (this.constructor as typeof this)({
|
||||
const constructorArg = {
|
||||
node: node,
|
||||
name: this.name,
|
||||
type: this.type,
|
||||
options: this.options
|
||||
})
|
||||
}
|
||||
const cloned: this = new (this.constructor as new (
|
||||
obj: typeof constructorArg
|
||||
) => this)(constructorArg)
|
||||
cloned.value = this.value
|
||||
// Preserve the Y position from the original widget to maintain proper positioning
|
||||
// when widgets are promoted through subgraph nesting
|
||||
@@ -231,14 +233,16 @@ export class DOMWidgetImpl<T extends HTMLElement, V extends object | string>
|
||||
}
|
||||
|
||||
override createCopyForNode(node: LGraphNode): this {
|
||||
// @ts-expect-error
|
||||
const cloned: this = new (this.constructor as typeof this)({
|
||||
const constructorArg = {
|
||||
node: node,
|
||||
name: this.name,
|
||||
type: this.type,
|
||||
element: this.element, // Include the element!
|
||||
element: this.element,
|
||||
options: this.options
|
||||
})
|
||||
}
|
||||
const cloned: this = new (this.constructor as new (
|
||||
obj: typeof constructorArg
|
||||
) => this)(constructorArg)
|
||||
cloned.value = this.value
|
||||
// Preserve the Y position from the original widget to maintain proper positioning
|
||||
// when widgets are promoted through subgraph nesting
|
||||
|
||||
@@ -318,14 +318,16 @@ function parseAvifMetadata(buffer: ArrayBuffer): ComfyMetadata {
|
||||
return metadata
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
function parseExifData(exifData) {
|
||||
function parseExifData(exifData: Uint8Array) {
|
||||
// Check for the correct TIFF header (0x4949 for little-endian or 0x4D4D for big-endian)
|
||||
const isLittleEndian = String.fromCharCode(...exifData.slice(0, 2)) === 'II'
|
||||
|
||||
// Function to read 16-bit and 32-bit integers from binary data
|
||||
// @ts-expect-error fixme ts strict error
|
||||
function readInt(offset, isLittleEndian, length) {
|
||||
function readInt(
|
||||
offset: number,
|
||||
isLittleEndian: boolean,
|
||||
length: number
|
||||
): number | undefined {
|
||||
let arr = exifData.slice(offset, offset + length)
|
||||
if (length === 2) {
|
||||
return new DataView(arr.buffer, arr.byteOffset, arr.byteLength).getUint16(
|
||||
@@ -343,12 +345,12 @@ function parseExifData(exifData) {
|
||||
// Read the offset to the first IFD (Image File Directory)
|
||||
const ifdOffset = readInt(4, isLittleEndian, 4)
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
function parseIFD(offset) {
|
||||
function parseIFD(offset: number) {
|
||||
const numEntries = readInt(offset, isLittleEndian, 2)
|
||||
const result = {}
|
||||
const result: Record<number, string | undefined> = {}
|
||||
|
||||
if (numEntries === undefined) return result
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
for (let i = 0; i < numEntries; i++) {
|
||||
const entryOffset = offset + 2 + i * 12
|
||||
const tag = readInt(entryOffset, isLittleEndian, 2)
|
||||
@@ -358,22 +360,23 @@ function parseExifData(exifData) {
|
||||
|
||||
// Read the value(s) based on the data type
|
||||
let value
|
||||
if (type === 2) {
|
||||
if (type === 2 && valueOffset !== undefined && numValues !== undefined) {
|
||||
// ASCII string
|
||||
value = new TextDecoder('utf-8').decode(
|
||||
// @ts-expect-error fixme ts strict error
|
||||
exifData.subarray(valueOffset, valueOffset + numValues - 1)
|
||||
)
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
result[tag] = value
|
||||
if (tag !== undefined) {
|
||||
result[tag] = value
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// Parse the first IFD
|
||||
if (ifdOffset === undefined) return {}
|
||||
const ifdData = parseIFD(ifdOffset)
|
||||
return ifdData
|
||||
}
|
||||
|
||||
@@ -6,8 +6,7 @@ export function getFromFlacBuffer(buffer: ArrayBuffer): Record<string, string> {
|
||||
const signature = String.fromCharCode(...new Uint8Array(buffer, 0, 4))
|
||||
if (signature !== 'fLaC') {
|
||||
console.error('Not a valid FLAC file')
|
||||
// @ts-expect-error fixme ts strict error
|
||||
return
|
||||
return {}
|
||||
}
|
||||
|
||||
// Parse metadata blocks
|
||||
@@ -30,17 +29,18 @@ export function getFromFlacBuffer(buffer: ArrayBuffer): Record<string, string> {
|
||||
if (isLastBlock) break
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
return vorbisComment
|
||||
return vorbisComment ?? {}
|
||||
}
|
||||
|
||||
export function getFromFlacFile(file: File): Promise<Record<string, string>> {
|
||||
return new Promise((r) => {
|
||||
const reader = new FileReader()
|
||||
reader.onload = function (event) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const arrayBuffer = event.target.result as ArrayBuffer
|
||||
r(getFromFlacBuffer(arrayBuffer))
|
||||
if (event.target?.result instanceof ArrayBuffer) {
|
||||
r(getFromFlacBuffer(event.target.result))
|
||||
} else {
|
||||
r({})
|
||||
}
|
||||
}
|
||||
reader.readAsArrayBuffer(file)
|
||||
})
|
||||
@@ -50,14 +50,11 @@ export function getFromFlacFile(file: File): Promise<Record<string, string>> {
|
||||
function parseVorbisComment(dataView: DataView): Record<string, string> {
|
||||
let offset = 0
|
||||
const vendorLength = dataView.getUint32(offset, true)
|
||||
offset += 4
|
||||
// @ts-expect-error unused variable
|
||||
const vendorString = getString(dataView, offset, vendorLength)
|
||||
offset += vendorLength
|
||||
offset += 4 + vendorLength
|
||||
|
||||
const userCommentListLength = dataView.getUint32(offset, true)
|
||||
offset += 4
|
||||
const comments = {}
|
||||
const comments: Record<string, string> = {}
|
||||
for (let i = 0; i < userCommentListLength; i++) {
|
||||
const commentLength = dataView.getUint32(offset, true)
|
||||
offset += 4
|
||||
@@ -67,7 +64,6 @@ function parseVorbisComment(dataView: DataView): Record<string, string> {
|
||||
const ind = comment.indexOf('=')
|
||||
const key = comment.substring(0, ind)
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
comments[key] = comment.substring(ind + 1)
|
||||
}
|
||||
|
||||
|
||||
@@ -46,8 +46,9 @@ export function getFromPngFile(file: File) {
|
||||
return new Promise<Record<string, string>>((r) => {
|
||||
const reader = new FileReader()
|
||||
reader.onload = (event) => {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
r(getFromPngBuffer(event.target.result as ArrayBuffer))
|
||||
if (event.target?.result instanceof ArrayBuffer) {
|
||||
r(getFromPngBuffer(event.target.result))
|
||||
}
|
||||
}
|
||||
|
||||
reader.readAsArrayBuffer(file)
|
||||
|
||||
@@ -94,17 +94,19 @@ export function $el<TTag extends string>(
|
||||
return element as ElementType<TTag>
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
function dragElement(dragEl): () => void {
|
||||
function dragElement(dragEl: HTMLElement): () => void {
|
||||
var posDiffX = 0,
|
||||
posDiffY = 0,
|
||||
posStartX = 0,
|
||||
posStartY = 0,
|
||||
newPosX = 0,
|
||||
newPosY = 0
|
||||
if (dragEl.getElementsByClassName('drag-handle')[0]) {
|
||||
const handle = dragEl.getElementsByClassName('drag-handle')[0] as
|
||||
| HTMLElement
|
||||
| undefined
|
||||
if (handle) {
|
||||
// if present, the handle is where you move the DIV from:
|
||||
dragEl.getElementsByClassName('drag-handle')[0].onmousedown = dragMouseDown
|
||||
handle.onmousedown = dragMouseDown
|
||||
} else {
|
||||
// otherwise, move the DIV from anywhere inside the DIV:
|
||||
dragEl.onmousedown = dragMouseDown
|
||||
@@ -151,7 +153,6 @@ function dragElement(dragEl): () => void {
|
||||
dragEl.style.top = newPosY + 'px'
|
||||
dragEl.style.bottom = 'unset'
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
if (savePos) {
|
||||
localStorage.setItem(
|
||||
'Comfy.MenuPosition',
|
||||
@@ -174,13 +175,11 @@ function dragElement(dragEl): () => void {
|
||||
}
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
let savePos = undefined
|
||||
let savePos: boolean | undefined = undefined
|
||||
restorePos()
|
||||
savePos = true
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
function dragMouseDown(e) {
|
||||
function dragMouseDown(e: MouseEvent) {
|
||||
e = e || window.event
|
||||
e.preventDefault()
|
||||
// get the mouse cursor position at startup:
|
||||
@@ -191,8 +190,7 @@ function dragElement(dragEl): () => void {
|
||||
document.onmousemove = elementDrag
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
function elementDrag(e) {
|
||||
function elementDrag(e: MouseEvent) {
|
||||
e = e || window.event
|
||||
e.preventDefault()
|
||||
|
||||
@@ -230,16 +228,15 @@ function dragElement(dragEl): () => void {
|
||||
}
|
||||
|
||||
class ComfyList {
|
||||
#type
|
||||
#text
|
||||
#reverse
|
||||
#type: 'queue' | 'history'
|
||||
#text: string
|
||||
#reverse: boolean
|
||||
element: HTMLDivElement
|
||||
button?: HTMLButtonElement
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
constructor(text, type?, reverse?) {
|
||||
constructor(text: string, type?: 'queue' | 'history', reverse?: boolean) {
|
||||
this.#text = text
|
||||
this.#type = type || text.toLowerCase()
|
||||
this.#type = type || (text.toLowerCase() as 'queue' | 'history')
|
||||
this.#reverse = reverse || false
|
||||
this.element = $el('div.comfy-list') as HTMLDivElement
|
||||
this.element.style.display = 'none'
|
||||
@@ -257,46 +254,45 @@ class ComfyList {
|
||||
textContent: section
|
||||
}),
|
||||
$el('div.comfy-list-items', [
|
||||
// @ts-expect-error fixme ts strict error
|
||||
...(this.#reverse ? items[section].reverse() : items[section]).map(
|
||||
(item: TaskItem) => {
|
||||
// Allow items to specify a custom remove action (e.g. for interrupt current prompt)
|
||||
const removeAction =
|
||||
'remove' in item
|
||||
? item.remove
|
||||
: {
|
||||
name: 'Delete',
|
||||
cb: () => api.deleteItem(this.#type, item.prompt[1])
|
||||
}
|
||||
return $el('div', { textContent: item.prompt[0] + ': ' }, [
|
||||
$el('button', {
|
||||
textContent: 'Load',
|
||||
onclick: async () => {
|
||||
await app.loadGraphData(
|
||||
// @ts-expect-error fixme ts strict error
|
||||
item.prompt[3].extra_pnginfo.workflow,
|
||||
true,
|
||||
false
|
||||
)
|
||||
if ('outputs' in item) {
|
||||
app.nodeOutputs = {}
|
||||
for (const [key, value] of Object.entries(item.outputs)) {
|
||||
const realKey = item['meta']?.[key]?.display_node ?? key
|
||||
app.nodeOutputs[realKey] = value
|
||||
}
|
||||
...(this.#reverse
|
||||
? (items[section as keyof typeof items] as TaskItem[]).reverse()
|
||||
: (items[section as keyof typeof items] as TaskItem[])
|
||||
).map((item: TaskItem) => {
|
||||
// Allow items to specify a custom remove action (e.g. for interrupt current prompt)
|
||||
const removeAction =
|
||||
'remove' in item
|
||||
? item.remove
|
||||
: {
|
||||
name: 'Delete',
|
||||
cb: () => api.deleteItem(this.#type, item.prompt[1])
|
||||
}
|
||||
return $el('div', { textContent: item.prompt[0] + ': ' }, [
|
||||
$el('button', {
|
||||
textContent: 'Load',
|
||||
onclick: async () => {
|
||||
await app.loadGraphData(
|
||||
item.prompt[3].extra_pnginfo?.workflow,
|
||||
true,
|
||||
false
|
||||
)
|
||||
if ('outputs' in item) {
|
||||
app.nodeOutputs = {}
|
||||
for (const [key, value] of Object.entries(item.outputs)) {
|
||||
const realKey = item['meta']?.[key]?.display_node ?? key
|
||||
app.nodeOutputs[realKey] = value
|
||||
}
|
||||
}
|
||||
}),
|
||||
$el('button', {
|
||||
textContent: removeAction.name,
|
||||
onclick: async () => {
|
||||
await removeAction.cb()
|
||||
await this.update()
|
||||
}
|
||||
})
|
||||
])
|
||||
}
|
||||
)
|
||||
}
|
||||
}),
|
||||
$el('button', {
|
||||
textContent: removeAction.name,
|
||||
onclick: async () => {
|
||||
await removeAction.cb()
|
||||
await this.update()
|
||||
}
|
||||
})
|
||||
])
|
||||
})
|
||||
])
|
||||
]),
|
||||
$el('div.comfy-list-actions', [
|
||||
@@ -320,16 +316,14 @@ class ComfyList {
|
||||
|
||||
async show() {
|
||||
this.element.style.display = 'block'
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.button.textContent = 'Close'
|
||||
if (this.button) this.button.textContent = 'Close'
|
||||
|
||||
await this.load()
|
||||
}
|
||||
|
||||
hide() {
|
||||
this.element.style.display = 'none'
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.button.textContent = 'View ' + this.#text
|
||||
if (this.button) this.button.textContent = 'View ' + this.#text
|
||||
}
|
||||
|
||||
toggle() {
|
||||
@@ -351,23 +345,15 @@ export class ComfyUI {
|
||||
lastQueueSize: number
|
||||
queue: ComfyList
|
||||
history: ComfyList
|
||||
// @ts-expect-error fixme ts strict error
|
||||
autoQueueMode: string
|
||||
// @ts-expect-error fixme ts strict error
|
||||
graphHasChanged: boolean
|
||||
// @ts-expect-error fixme ts strict error
|
||||
autoQueueEnabled: boolean
|
||||
// @ts-expect-error fixme ts strict error
|
||||
menuContainer: HTMLDivElement
|
||||
// @ts-expect-error fixme ts strict error
|
||||
queueSize: Element
|
||||
// @ts-expect-error fixme ts strict error
|
||||
restoreMenuPosition: () => void
|
||||
// @ts-expect-error fixme ts strict error
|
||||
loadFile: () => void
|
||||
autoQueueMode!: string
|
||||
graphHasChanged!: boolean
|
||||
autoQueueEnabled!: boolean
|
||||
menuContainer!: HTMLDivElement
|
||||
queueSize!: Element
|
||||
restoreMenuPosition!: () => void
|
||||
loadFile!: () => void
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
constructor(app) {
|
||||
constructor(app: ComfyApp) {
|
||||
this.app = app
|
||||
this.dialog = new ComfyDialog()
|
||||
this.settings = new ComfySettingsDialog(app)
|
||||
@@ -417,9 +403,8 @@ export class ComfyUI {
|
||||
}
|
||||
],
|
||||
{
|
||||
// @ts-expect-error fixme ts strict error
|
||||
onChange: (value) => {
|
||||
this.autoQueueMode = value.item.value
|
||||
this.autoQueueMode = value.item.value ?? value.item.text
|
||||
}
|
||||
}
|
||||
)
|
||||
@@ -486,14 +471,13 @@ export class ComfyUI {
|
||||
$el('label', { innerHTML: 'Extra options' }, [
|
||||
$el('input', {
|
||||
type: 'checkbox',
|
||||
// @ts-expect-error fixme ts strict error
|
||||
onchange: (i) => {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
document.getElementById('extraOptions').style.display = i
|
||||
.srcElement.checked
|
||||
? 'block'
|
||||
: 'none'
|
||||
this.batchCount = i.srcElement.checked
|
||||
onchange: (e: Event) => {
|
||||
const extraOptions = document.getElementById('extraOptions')
|
||||
const target = e.target
|
||||
if (!(target instanceof HTMLInputElement) || !extraOptions)
|
||||
return
|
||||
extraOptions.style.display = target.checked ? 'block' : 'none'
|
||||
this.batchCount = target.checked
|
||||
? Number.parseInt(
|
||||
(
|
||||
document.getElementById(
|
||||
@@ -524,18 +508,15 @@ export class ComfyUI {
|
||||
value: this.batchCount,
|
||||
min: '1',
|
||||
style: { width: '35%', marginLeft: '0.4em' },
|
||||
// @ts-expect-error fixme ts strict error
|
||||
oninput: (i) => {
|
||||
this.batchCount = i.target.value
|
||||
/* Even though an <input> element with a type of range logically represents a number (since
|
||||
it's used for numeric input), the value it holds is still treated as a string in HTML and
|
||||
JavaScript. This behavior is consistent across all <input> elements regardless of their type
|
||||
(like text, number, or range), where the .value property is always a string. */
|
||||
;(
|
||||
document.getElementById(
|
||||
'batchCountInputRange'
|
||||
) as HTMLInputElement
|
||||
).value = this.batchCount.toString()
|
||||
oninput: (e: Event) => {
|
||||
if (!(e.target instanceof HTMLInputElement)) return
|
||||
this.batchCount = Number.parseInt(e.target.value) || 1
|
||||
const rangeInput = document.getElementById(
|
||||
'batchCountInputRange'
|
||||
)
|
||||
if (rangeInput instanceof HTMLInputElement) {
|
||||
rangeInput.value = this.batchCount.toString()
|
||||
}
|
||||
}
|
||||
}),
|
||||
$el('input', {
|
||||
@@ -544,15 +525,15 @@ export class ComfyUI {
|
||||
min: '1',
|
||||
max: '100',
|
||||
value: this.batchCount,
|
||||
// @ts-expect-error fixme ts strict error
|
||||
oninput: (i) => {
|
||||
this.batchCount = i.srcElement.value
|
||||
// Note
|
||||
;(
|
||||
document.getElementById(
|
||||
'batchCountInputNumber'
|
||||
) as HTMLInputElement
|
||||
).value = i.srcElement.value
|
||||
oninput: (e: Event) => {
|
||||
if (!(e.target instanceof HTMLInputElement)) return
|
||||
this.batchCount = Number.parseInt(e.target.value) || 1
|
||||
const numberInput = document.getElementById(
|
||||
'batchCountInputNumber'
|
||||
)
|
||||
if (numberInput instanceof HTMLInputElement) {
|
||||
numberInput.value = e.target.value
|
||||
}
|
||||
}
|
||||
})
|
||||
]),
|
||||
@@ -566,8 +547,8 @@ export class ComfyUI {
|
||||
type: 'checkbox',
|
||||
checked: false,
|
||||
title: 'Automatically queue prompt when the queue size hits 0',
|
||||
// @ts-expect-error fixme ts strict error
|
||||
onchange: (e) => {
|
||||
onchange: (e: Event) => {
|
||||
if (!(e.target instanceof HTMLInputElement)) return
|
||||
this.autoQueueEnabled = e.target.checked
|
||||
autoQueueModeEl.style.display = this.autoQueueEnabled
|
||||
? ''
|
||||
@@ -682,8 +663,8 @@ export class ComfyUI {
|
||||
|
||||
this.restoreMenuPosition = dragElement(this.menuContainer)
|
||||
|
||||
// @ts-expect-error
|
||||
this.setStatus({ exec_info: { queue_remaining: 'X' } })
|
||||
// Initialize with placeholder text before first status update
|
||||
this.queueSize.textContent = 'Queue size: X'
|
||||
}
|
||||
|
||||
setStatus(status: StatusWsMessageStatus | null) {
|
||||
|
||||
@@ -2,21 +2,17 @@ import { $el } from '../../ui'
|
||||
import { ComfyDialog } from '../dialog'
|
||||
|
||||
export class ComfyAsyncDialog extends ComfyDialog<HTMLDialogElement> {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
#resolve: (value: any) => void
|
||||
#resolve!: (value: any) => void
|
||||
|
||||
constructor(actions?: Array<string | { value?: any; text: string }>) {
|
||||
super(
|
||||
'dialog.comfy-dialog.comfyui-dialog',
|
||||
// @ts-expect-error fixme ts strict error
|
||||
actions?.map((opt) => {
|
||||
if (typeof opt === 'string') {
|
||||
opt = { text: opt }
|
||||
}
|
||||
const option = typeof opt === 'string' ? { text: opt } : opt
|
||||
return $el('button.comfyui-button', {
|
||||
type: 'button',
|
||||
textContent: opt.text,
|
||||
onclick: () => this.close(opt.value ?? opt.text)
|
||||
textContent: option.text,
|
||||
onclick: () => this.close(option.value ?? option.text)
|
||||
})
|
||||
})
|
||||
)
|
||||
|
||||
@@ -26,18 +26,17 @@ export class ComfyButton implements ComfyComponent<HTMLElement> {
|
||||
isOver = false
|
||||
iconElement = $el('i.mdi')
|
||||
contentElement = $el('span')
|
||||
// @ts-expect-error fixme ts strict error
|
||||
popup: ComfyPopup
|
||||
popup: ComfyPopup | null = null
|
||||
element: HTMLElement
|
||||
overIcon: string
|
||||
iconSize: number
|
||||
content: string | HTMLElement
|
||||
icon: string
|
||||
tooltip: string
|
||||
classList: ClassList
|
||||
hidden: boolean
|
||||
enabled: boolean
|
||||
action: (e: Event, btn: ComfyButton) => void
|
||||
overIcon!: string
|
||||
iconSize!: number
|
||||
content!: string | HTMLElement
|
||||
icon!: string
|
||||
tooltip!: string
|
||||
classList!: ClassList
|
||||
hidden!: boolean
|
||||
enabled!: boolean
|
||||
action!: (e: Event, btn: ComfyButton) => void
|
||||
|
||||
constructor({
|
||||
icon,
|
||||
@@ -70,22 +69,18 @@ export class ComfyButton implements ComfyComponent<HTMLElement> {
|
||||
[this.iconElement, this.contentElement]
|
||||
)
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.icon = prop(
|
||||
this,
|
||||
'icon',
|
||||
icon,
|
||||
toggleElement(this.iconElement, { onShow: this.updateIcon })
|
||||
)
|
||||
// @ts-expect-error fixme ts strict error
|
||||
)!
|
||||
this.overIcon = prop(this, 'overIcon', overIcon, () => {
|
||||
if (this.isOver) {
|
||||
this.updateIcon()
|
||||
}
|
||||
})
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.iconSize = prop(this, 'iconSize', iconSize, this.updateIcon)
|
||||
// @ts-expect-error fixme ts strict error
|
||||
})!
|
||||
this.iconSize = prop(this, 'iconSize', iconSize, this.updateIcon)!
|
||||
this.content = prop(
|
||||
this,
|
||||
'content',
|
||||
@@ -94,32 +89,30 @@ export class ComfyButton implements ComfyComponent<HTMLElement> {
|
||||
onShow: (el, v) => {
|
||||
if (typeof v === 'string') {
|
||||
el.textContent = v
|
||||
} else {
|
||||
} else if (v) {
|
||||
el.replaceChildren(v)
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
)!
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.tooltip = prop(this, 'tooltip', tooltip, (v) => {
|
||||
if (v) {
|
||||
this.element.title = v
|
||||
} else {
|
||||
this.element.removeAttribute('title')
|
||||
}
|
||||
})
|
||||
})!
|
||||
if (tooltip !== undefined) {
|
||||
this.element.setAttribute('aria-label', tooltip)
|
||||
}
|
||||
this.classList = prop(this, 'classList', classList, this.updateClasses)
|
||||
this.hidden = prop(this, 'hidden', false, this.updateClasses)
|
||||
this.classList = prop(this, 'classList', classList, this.updateClasses)!
|
||||
this.hidden = prop(this, 'hidden', false, this.updateClasses)!
|
||||
this.enabled = prop(this, 'enabled', enabled, () => {
|
||||
this.updateClasses()
|
||||
;(this.element as HTMLButtonElement).disabled = !this.enabled
|
||||
})
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.action = prop(this, 'action', action)
|
||||
})!
|
||||
this.action = prop(this, 'action', action)!
|
||||
this.element.addEventListener('click', (e) => {
|
||||
if (this.popup) {
|
||||
// we are either a touch device or triggered by click not hover
|
||||
@@ -130,14 +123,12 @@ export class ComfyButton implements ComfyComponent<HTMLElement> {
|
||||
this.action?.(e, this)
|
||||
})
|
||||
|
||||
if (visibilitySetting?.id) {
|
||||
if (visibilitySetting?.id && app?.ui?.settings) {
|
||||
const settingUpdated = () => {
|
||||
this.hidden =
|
||||
// @ts-expect-error fixme ts strict error
|
||||
app.ui.settings.getSettingValue(visibilitySetting.id) !==
|
||||
visibilitySetting.showValue
|
||||
}
|
||||
// @ts-expect-error fixme ts strict error
|
||||
app.ui.settings.addEventListener(
|
||||
visibilitySetting.id + '.change',
|
||||
settingUpdated
|
||||
@@ -170,12 +161,12 @@ export class ComfyButton implements ComfyComponent<HTMLElement> {
|
||||
this.popup = popup
|
||||
|
||||
if (mode === 'hover') {
|
||||
for (const el of [this.element, this.popup.element]) {
|
||||
for (const el of [this.element, popup.element]) {
|
||||
el.addEventListener('mouseenter', () => {
|
||||
this.popup.open = !!++this.#over
|
||||
popup.open = !!++this.#over
|
||||
})
|
||||
el.addEventListener('mouseleave', () => {
|
||||
this.popup.open = !!--this.#over
|
||||
popup.open = !!--this.#over
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,8 @@ export class ComfyButtonGroup {
|
||||
}
|
||||
|
||||
update() {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.element.replaceChildren(...this.buttons.map((b) => b['element'] ?? b))
|
||||
this.element.replaceChildren(
|
||||
...this.buttons.map((b) => ('element' in b ? b.element : b))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,8 +89,7 @@ export class ComfyPopup extends EventTarget {
|
||||
this.dispatchEvent(new CustomEvent('change'))
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
#escHandler = (e) => {
|
||||
#escHandler = (e: KeyboardEvent) => {
|
||||
if (e.key === 'Escape') {
|
||||
this.open = false
|
||||
e.preventDefault()
|
||||
@@ -98,9 +97,8 @@ export class ComfyPopup extends EventTarget {
|
||||
}
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
#clickHandler = (e) => {
|
||||
/** @type {any} */
|
||||
#clickHandler = (e: MouseEvent) => {
|
||||
if (!(e.target instanceof Node)) return
|
||||
const target = e.target
|
||||
if (
|
||||
!this.element.contains(target) &&
|
||||
|
||||
@@ -4,11 +4,10 @@ export class ComfyDialog<
|
||||
T extends HTMLElement = HTMLElement
|
||||
> extends EventTarget {
|
||||
element: T
|
||||
// @ts-expect-error fixme ts strict error
|
||||
textElement: HTMLElement
|
||||
#buttons: HTMLButtonElement[] | null
|
||||
textElement!: HTMLElement
|
||||
#buttons: HTMLElement[] | null
|
||||
|
||||
constructor(type = 'div', buttons = null) {
|
||||
constructor(type = 'div', buttons: HTMLElement[] | null = null) {
|
||||
super()
|
||||
this.#buttons = buttons
|
||||
this.element = $el(type + '.comfy-modal', { parent: document.body }, [
|
||||
@@ -35,11 +34,10 @@ export class ComfyDialog<
|
||||
this.element.style.display = 'none'
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
show(html) {
|
||||
show(html?: string | HTMLElement | HTMLElement[]) {
|
||||
if (typeof html === 'string') {
|
||||
this.textElement.innerHTML = html
|
||||
} else {
|
||||
} else if (html) {
|
||||
this.textElement.replaceChildren(
|
||||
...(html instanceof Array ? html : [html])
|
||||
)
|
||||
|
||||
@@ -40,87 +40,94 @@ styleElement.textContent = `
|
||||
document.head.append(styleElement)
|
||||
|
||||
export class DraggableList extends EventTarget {
|
||||
listContainer
|
||||
// @ts-expect-error fixme ts strict error
|
||||
draggableItem
|
||||
// @ts-expect-error fixme ts strict error
|
||||
pointerStartX
|
||||
// @ts-expect-error fixme ts strict error
|
||||
pointerStartY
|
||||
// @ts-expect-error fixme ts strict error
|
||||
scrollYMax
|
||||
listContainer: HTMLElement
|
||||
draggableItem: HTMLElement | null = null
|
||||
pointerStartX: number = 0
|
||||
pointerStartY: number = 0
|
||||
scrollYMax: number = 0
|
||||
itemsGap = 0
|
||||
items = []
|
||||
itemSelector
|
||||
items: HTMLElement[] = []
|
||||
itemSelector: string
|
||||
handleClass = 'drag-handle'
|
||||
off = []
|
||||
offDrag = []
|
||||
off: (() => void)[] = []
|
||||
offDrag: (() => void)[] = []
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
constructor(element, itemSelector) {
|
||||
constructor(element: HTMLElement, itemSelector: string) {
|
||||
super()
|
||||
this.listContainer = element
|
||||
this.itemSelector = itemSelector
|
||||
|
||||
if (!this.listContainer) return
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.off.push(this.on(this.listContainer, 'mousedown', this.dragStart))
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.off.push(this.on(this.listContainer, 'touchstart', this.dragStart))
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.off.push(this.on(document, 'mouseup', this.dragEnd))
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.off.push(this.on(document, 'touchend', this.dragEnd))
|
||||
}
|
||||
|
||||
getAllItems() {
|
||||
getAllItems(): HTMLElement[] {
|
||||
if (!this.items?.length) {
|
||||
this.items = Array.from(
|
||||
this.listContainer.querySelectorAll(this.itemSelector)
|
||||
this.listContainer.querySelectorAll<HTMLElement>(this.itemSelector)
|
||||
)
|
||||
this.items.forEach((element) => {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
element.classList.add('is-idle')
|
||||
})
|
||||
}
|
||||
return this.items
|
||||
}
|
||||
|
||||
getIdleItems() {
|
||||
getIdleItems(): HTMLElement[] {
|
||||
return this.getAllItems().filter((item) =>
|
||||
// @ts-expect-error fixme ts strict error
|
||||
item.classList.contains('is-idle')
|
||||
)
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
isItemAbove(item) {
|
||||
isItemAbove(item: HTMLElement): boolean {
|
||||
return item.hasAttribute('data-is-above')
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
isItemToggled(item) {
|
||||
isItemToggled(item: HTMLElement): boolean {
|
||||
return item.hasAttribute('data-is-toggled')
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
on(source, event, listener, options?) {
|
||||
listener = listener.bind(this)
|
||||
source.addEventListener(event, listener, options)
|
||||
return () => source.removeEventListener(event, listener)
|
||||
on<K extends keyof DocumentEventMap>(
|
||||
source: Document,
|
||||
event: K,
|
||||
listener: (e: DocumentEventMap[K]) => void,
|
||||
options?: AddEventListenerOptions
|
||||
): () => void
|
||||
on<K extends keyof HTMLElementEventMap>(
|
||||
source: HTMLElement,
|
||||
event: K,
|
||||
listener: (e: HTMLElementEventMap[K]) => void,
|
||||
options?: AddEventListenerOptions
|
||||
): () => void
|
||||
on(
|
||||
source: Document | HTMLElement,
|
||||
event: string,
|
||||
listener: (e: Event) => void,
|
||||
options?: AddEventListenerOptions
|
||||
): () => void {
|
||||
const boundListener = listener.bind(this)
|
||||
source.addEventListener(event, boundListener, options)
|
||||
return () => source.removeEventListener(event, boundListener)
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
dragStart(e) {
|
||||
if (e.target.classList.contains(this.handleClass)) {
|
||||
this.draggableItem = e.target.closest(this.itemSelector)
|
||||
}
|
||||
dragStart(e: MouseEvent | TouchEvent) {
|
||||
const target = e.target
|
||||
if (!(target instanceof HTMLElement)) return
|
||||
if (!target.classList.contains(this.handleClass)) return
|
||||
|
||||
this.draggableItem = target.closest<HTMLElement>(this.itemSelector)
|
||||
|
||||
if (!this.draggableItem) return
|
||||
|
||||
this.pointerStartX = e.clientX || e.touches[0].clientX
|
||||
this.pointerStartY = e.clientY || e.touches[0].clientY
|
||||
const clientX = 'clientX' in e ? e.clientX : e.touches[0].clientX
|
||||
const clientY = 'clientY' in e ? e.clientY : e.touches[0].clientY
|
||||
|
||||
this.pointerStartX = clientX
|
||||
this.pointerStartY = clientY
|
||||
this.scrollYMax =
|
||||
this.listContainer.scrollHeight - this.listContainer.clientHeight
|
||||
|
||||
@@ -128,10 +135,8 @@ export class DraggableList extends EventTarget {
|
||||
this.initDraggableItem()
|
||||
this.initItemsState()
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.offDrag.push(this.on(document, 'mousemove', this.drag))
|
||||
this.offDrag.push(
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.on(document, 'touchmove', this.drag, { passive: false })
|
||||
)
|
||||
|
||||
@@ -139,7 +144,6 @@ export class DraggableList extends EventTarget {
|
||||
new CustomEvent('dragstart', {
|
||||
detail: {
|
||||
element: this.draggableItem,
|
||||
// @ts-expect-error fixme ts strict error
|
||||
position: this.getAllItems().indexOf(this.draggableItem)
|
||||
}
|
||||
})
|
||||
@@ -155,9 +159,7 @@ export class DraggableList extends EventTarget {
|
||||
const item1 = this.getIdleItems()[0]
|
||||
const item2 = this.getIdleItems()[1]
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const item1Rect = item1.getBoundingClientRect()
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const item2Rect = item2.getBoundingClientRect()
|
||||
|
||||
this.itemsGap = Math.abs(item1Rect.bottom - item2Rect.top)
|
||||
@@ -165,27 +167,25 @@ export class DraggableList extends EventTarget {
|
||||
|
||||
initItemsState() {
|
||||
this.getIdleItems().forEach((item, i) => {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
if (this.getAllItems().indexOf(this.draggableItem) > i) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
if (this.getAllItems().indexOf(this.draggableItem!) > i) {
|
||||
item.dataset.isAbove = ''
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
initDraggableItem() {
|
||||
if (!this.draggableItem) return
|
||||
this.draggableItem.classList.remove('is-idle')
|
||||
this.draggableItem.classList.add('is-draggable')
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
drag(e) {
|
||||
drag(e: MouseEvent | TouchEvent) {
|
||||
if (!this.draggableItem) return
|
||||
|
||||
e.preventDefault()
|
||||
|
||||
const clientX = e.clientX || e.touches[0].clientX
|
||||
const clientY = e.clientY || e.touches[0].clientY
|
||||
const clientX = 'clientX' in e ? e.clientX : e.touches[0].clientX
|
||||
const clientY = 'clientY' in e ? e.clientY : e.touches[0].clientY
|
||||
|
||||
const listRect = this.listContainer.getBoundingClientRect()
|
||||
|
||||
@@ -207,28 +207,24 @@ export class DraggableList extends EventTarget {
|
||||
}
|
||||
|
||||
updateIdleItemsStateAndPosition() {
|
||||
if (!this.draggableItem) return
|
||||
const draggableItemRect = this.draggableItem.getBoundingClientRect()
|
||||
const draggableItemY = draggableItemRect.top + draggableItemRect.height / 2
|
||||
|
||||
// Update state
|
||||
this.getIdleItems().forEach((item) => {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const itemRect = item.getBoundingClientRect()
|
||||
const itemY = itemRect.top + itemRect.height / 2
|
||||
if (this.isItemAbove(item)) {
|
||||
if (draggableItemY <= itemY) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
item.dataset.isToggled = ''
|
||||
} else {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
delete item.dataset.isToggled
|
||||
}
|
||||
} else {
|
||||
if (draggableItemY >= itemY) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
item.dataset.isToggled = ''
|
||||
} else {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
delete item.dataset.isToggled
|
||||
}
|
||||
}
|
||||
@@ -238,10 +234,8 @@ export class DraggableList extends EventTarget {
|
||||
this.getIdleItems().forEach((item) => {
|
||||
if (this.isItemToggled(item)) {
|
||||
const direction = this.isItemAbove(item) ? 1 : -1
|
||||
// @ts-expect-error fixme ts strict error
|
||||
item.style.transform = `translateY(${direction * (draggableItemRect.height + this.itemsGap)}px)`
|
||||
} else {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
item.style.transform = ''
|
||||
}
|
||||
})
|
||||
@@ -255,7 +249,8 @@ export class DraggableList extends EventTarget {
|
||||
}
|
||||
|
||||
applyNewItemsOrder() {
|
||||
const reorderedItems = []
|
||||
if (!this.draggableItem) return
|
||||
const reorderedItems: HTMLElement[] = []
|
||||
|
||||
let oldPosition = -1
|
||||
this.getAllItems().forEach((item, index) => {
|
||||
@@ -282,7 +277,6 @@ export class DraggableList extends EventTarget {
|
||||
this.listContainer.appendChild(item)
|
||||
})
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.items = reorderedItems
|
||||
|
||||
this.dispatchEvent(
|
||||
@@ -302,13 +296,13 @@ export class DraggableList extends EventTarget {
|
||||
this.unsetDraggableItem()
|
||||
this.unsetItemState()
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.offDrag.forEach((f) => f())
|
||||
this.offDrag = []
|
||||
}
|
||||
|
||||
unsetDraggableItem() {
|
||||
this.draggableItem.style = null
|
||||
if (!this.draggableItem) return
|
||||
this.draggableItem.style.transform = ''
|
||||
this.draggableItem.classList.remove('is-draggable')
|
||||
this.draggableItem.classList.add('is-idle')
|
||||
this.draggableItem = null
|
||||
@@ -316,17 +310,13 @@ export class DraggableList extends EventTarget {
|
||||
|
||||
unsetItemState() {
|
||||
this.getIdleItems().forEach((item) => {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
delete item.dataset.isAbove
|
||||
// @ts-expect-error fixme ts strict error
|
||||
delete item.dataset.isToggled
|
||||
// @ts-expect-error fixme ts strict error
|
||||
item.style.transform = ''
|
||||
})
|
||||
}
|
||||
|
||||
dispose() {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.off.forEach((f) => f())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,13 +3,15 @@ import type { LGraphNode } from '@/lib/litegraph/src/LGraphNode'
|
||||
import { app } from '../app'
|
||||
import { $el } from '../ui'
|
||||
|
||||
interface ImageLike {
|
||||
naturalWidth: number
|
||||
naturalHeight: number
|
||||
}
|
||||
|
||||
export function calculateImageGrid(
|
||||
// @ts-expect-error fixme ts strict error
|
||||
imgs,
|
||||
// @ts-expect-error fixme ts strict error
|
||||
dw,
|
||||
// @ts-expect-error fixme ts strict error
|
||||
dh
|
||||
imgs: ImageLike[],
|
||||
dw: number,
|
||||
dh: number
|
||||
): {
|
||||
cellWidth: number
|
||||
cellHeight: number
|
||||
@@ -22,7 +24,11 @@ export function calculateImageGrid(
|
||||
let h = imgs[0].naturalHeight
|
||||
const numImages = imgs.length
|
||||
|
||||
let cellWidth, cellHeight, cols, rows, shiftX
|
||||
let cellWidth = 0
|
||||
let cellHeight = 0
|
||||
let cols = 1
|
||||
let rows = 1
|
||||
let shiftX = 0
|
||||
// compact style
|
||||
for (let c = 1; c <= numImages; c++) {
|
||||
const r = Math.ceil(numImages / c)
|
||||
@@ -46,63 +52,47 @@ export function calculateImageGrid(
|
||||
}
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
return { cellWidth, cellHeight, cols, rows, shiftX }
|
||||
}
|
||||
|
||||
/** @knipIgnoreUnusedButUsedByCustomNodes */
|
||||
export function createImageHost(node: LGraphNode) {
|
||||
const el = $el('div.comfy-img-preview')
|
||||
// @ts-expect-error fixme ts strict error
|
||||
let currentImgs
|
||||
let currentImgs: HTMLImageElement[] | null = null
|
||||
let first = true
|
||||
|
||||
function updateSize() {
|
||||
let w = null
|
||||
let h = null
|
||||
if (!currentImgs) return
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
if (currentImgs) {
|
||||
let elH = el.clientHeight
|
||||
if (first) {
|
||||
first = false
|
||||
// On first run, if we are small then grow a bit
|
||||
if (elH < 190) {
|
||||
elH = 190
|
||||
}
|
||||
el.style.setProperty('--comfy-widget-min-height', elH.toString())
|
||||
} else {
|
||||
el.style.setProperty('--comfy-widget-min-height', null)
|
||||
let elH = el.clientHeight
|
||||
if (first) {
|
||||
first = false
|
||||
// On first run, if we are small then grow a bit
|
||||
if (elH < 190) {
|
||||
elH = 190
|
||||
}
|
||||
|
||||
const nw = node.size[0]
|
||||
;({ cellWidth: w, cellHeight: h } = calculateImageGrid(
|
||||
currentImgs,
|
||||
nw - 20,
|
||||
elH
|
||||
))
|
||||
// @ts-expect-error fixme ts strict error
|
||||
w += 'px'
|
||||
// @ts-expect-error fixme ts strict error
|
||||
h += 'px'
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
el.style.setProperty('--comfy-img-preview-width', w)
|
||||
// @ts-expect-error fixme ts strict error
|
||||
el.style.setProperty('--comfy-img-preview-height', h)
|
||||
el.style.setProperty('--comfy-widget-min-height', elH.toString())
|
||||
} else {
|
||||
el.style.setProperty('--comfy-widget-min-height', null)
|
||||
}
|
||||
|
||||
const nw = node.size[0]
|
||||
const { cellWidth, cellHeight } = calculateImageGrid(
|
||||
currentImgs,
|
||||
nw - 20,
|
||||
elH
|
||||
)
|
||||
|
||||
el.style.setProperty('--comfy-img-preview-width', `${cellWidth}px`)
|
||||
el.style.setProperty('--comfy-img-preview-height', `${cellHeight}px`)
|
||||
}
|
||||
return {
|
||||
el,
|
||||
getCurrentImage() {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
return currentImgs?.[0]
|
||||
},
|
||||
// @ts-expect-error fixme ts strict error
|
||||
updateImages(imgs) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
updateImages(imgs: HTMLImageElement[]) {
|
||||
if (imgs !== currentImgs) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
if (currentImgs == null) {
|
||||
requestAnimationFrame(() => {
|
||||
updateSize()
|
||||
@@ -126,10 +116,9 @@ export function createImageHost(node: LGraphNode) {
|
||||
)
|
||||
el.style.pointerEvents = 'none'
|
||||
|
||||
if (!over) return
|
||||
if (!over || !currentImgs) return
|
||||
// Set the overIndex so Open Image etc work
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const idx = currentImgs.indexOf(over)
|
||||
const idx = currentImgs.indexOf(over as HTMLImageElement)
|
||||
node.overIndex = idx
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,42 +1,42 @@
|
||||
import { $el } from '../ui'
|
||||
|
||||
/**
|
||||
* @typedef { { text: string, value?: string, tooltip?: string } } ToggleSwitchItem
|
||||
*/
|
||||
interface ToggleSwitchItem {
|
||||
text: string
|
||||
value?: string
|
||||
tooltip?: string
|
||||
selected?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a toggle switch element
|
||||
* @param { string } name
|
||||
* @param { Array<string> | ToggleSwitchItem } items
|
||||
* @param { Object } [opts]
|
||||
* @param { (e: { item: ToggleSwitchItem, prev?: ToggleSwitchItem }) => void } [opts.onChange]
|
||||
*/
|
||||
// @ts-expect-error fixme ts strict error
|
||||
export function toggleSwitch(name, items, e?) {
|
||||
export function toggleSwitch(
|
||||
name: string,
|
||||
items: (string | ToggleSwitchItem)[],
|
||||
e?: {
|
||||
onChange?: (e: { item: ToggleSwitchItem; prev?: ToggleSwitchItem }) => void
|
||||
}
|
||||
) {
|
||||
const onChange = e?.onChange
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
let selectedIndex
|
||||
// @ts-expect-error fixme ts strict error
|
||||
let elements
|
||||
let selectedIndex: number | null = null
|
||||
let elements: HTMLLabelElement[]
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
function updateSelected(index) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
function updateSelected(index: number) {
|
||||
if (selectedIndex != null) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
elements[selectedIndex].classList.remove('comfy-toggle-selected')
|
||||
}
|
||||
onChange?.({
|
||||
item: items[index],
|
||||
// @ts-expect-error fixme ts strict error
|
||||
prev: selectedIndex == null ? undefined : items[selectedIndex]
|
||||
item: items[index] as ToggleSwitchItem,
|
||||
prev:
|
||||
selectedIndex == null
|
||||
? undefined
|
||||
: (items[selectedIndex] as ToggleSwitchItem)
|
||||
})
|
||||
selectedIndex = index
|
||||
// @ts-expect-error fixme ts strict error
|
||||
elements[selectedIndex].classList.add('comfy-toggle-selected')
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
elements = items.map((item, i) => {
|
||||
if (typeof item === 'string') item = { text: item }
|
||||
if (!item.value) item.value = item.text
|
||||
@@ -66,7 +66,10 @@ export function toggleSwitch(name, items, e?) {
|
||||
const container = $el('div.comfy-toggle-switch', elements)
|
||||
|
||||
if (selectedIndex == null) {
|
||||
elements[0].children[0].checked = true
|
||||
const firstInput = elements[0].children[0]
|
||||
if (firstInput instanceof HTMLInputElement) {
|
||||
firstInput.checked = true
|
||||
}
|
||||
updateSelected(0)
|
||||
}
|
||||
|
||||
|
||||
@@ -26,21 +26,19 @@ export function applyClasses(
|
||||
}
|
||||
}
|
||||
|
||||
export function toggleElement(
|
||||
export function toggleElement<T = unknown>(
|
||||
element: HTMLElement,
|
||||
{
|
||||
onHide,
|
||||
onShow
|
||||
}: {
|
||||
onHide?: (el: HTMLElement) => void
|
||||
// @ts-expect-error fixme ts strict error
|
||||
onShow?: (el: HTMLElement, value) => void
|
||||
onShow?: (el: HTMLElement, value: T) => void
|
||||
} = {}
|
||||
) {
|
||||
let placeholder: HTMLElement | Comment
|
||||
let hidden: boolean
|
||||
// @ts-expect-error fixme ts strict error
|
||||
return (value) => {
|
||||
return (value: T) => {
|
||||
if (value) {
|
||||
if (hidden) {
|
||||
hidden = false
|
||||
|
||||
@@ -76,15 +76,12 @@ export function prop<T>(
|
||||
name: string
|
||||
) => void
|
||||
): T {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
let currentValue
|
||||
let currentValue: T = defaultValue
|
||||
Object.defineProperty(target, name, {
|
||||
get() {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
return currentValue
|
||||
},
|
||||
set(newValue) {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
const prevValue = currentValue
|
||||
currentValue = newValue
|
||||
onChanged?.(currentValue, prevValue, target, name)
|
||||
|
||||
Reference in New Issue
Block a user