Skip to content

Commit 4eae398

Browse files
committed
Migrate ui.js
1 parent 1605020 commit 4eae398

File tree

2 files changed

+117
-81
lines changed

2 files changed

+117
-81
lines changed

src/scripts/ui.ts

Lines changed: 98 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -2,72 +2,70 @@ import { api } from "./api.js";
22
import { ComfyDialog as _ComfyDialog } from "./ui/dialog.js";
33
import { toggleSwitch } from "./ui/toggleSwitch.js";
44
import { ComfySettingsDialog } from "./ui/settings.js";
5+
import { ComfyApp, app } from "./app.js";
56

67
export const ComfyDialog = _ComfyDialog;
78

8-
/**
9-
*
10-
* @param { string } tag HTML Element Tag and optional classes e.g. div.class1.class2
11-
* @param { string | Element | Element[] | {
12-
* parent?: Element,
13-
* $?: (el: Element) => void,
14-
* dataset?: DOMStringMap,
15-
* style?: CSSStyleDeclaration,
16-
* for?: string
17-
* ...any
18-
* } | undefined } [propsOrChildren]
19-
* @param { Element[] | Element | undefined } [children]
20-
* @returns
21-
*/
22-
export function $el(tag, propsOrChildren, children) {
23-
const split = tag.split(".");
24-
const element = document.createElement(split.shift());
25-
if (split.length > 0) {
26-
element.classList.add(...split);
27-
}
28-
29-
if (propsOrChildren) {
30-
if (typeof propsOrChildren === "string") {
31-
propsOrChildren = { textContent: propsOrChildren };
32-
} else if (propsOrChildren instanceof Element) {
33-
propsOrChildren = [propsOrChildren];
34-
}
35-
if (Array.isArray(propsOrChildren)) {
36-
element.append(...propsOrChildren);
37-
} else {
38-
const { parent, $: cb, dataset, style } = propsOrChildren;
39-
delete propsOrChildren.parent;
40-
delete propsOrChildren.$;
41-
delete propsOrChildren.dataset;
42-
delete propsOrChildren.style;
43-
44-
if (Object.hasOwn(propsOrChildren, "for")) {
45-
element.setAttribute("for", propsOrChildren.for)
46-
}
47-
48-
if (style) {
49-
Object.assign(element.style, style);
50-
}
51-
52-
if (dataset) {
53-
Object.assign(element.dataset, dataset);
54-
}
55-
56-
Object.assign(element, propsOrChildren);
57-
if (children) {
58-
element.append(...(children instanceof Array ? children : [children]));
59-
}
60-
61-
if (parent) {
62-
parent.append(element);
63-
}
64-
65-
if (cb) {
66-
cb(element);
67-
}
68-
}
69-
}
70-
return element;
9+
type Position2D = {
10+
x: number,
11+
y: number
12+
};
13+
14+
type Props = {
15+
parent?: HTMLElement,
16+
$?: (el: HTMLElement) => void,
17+
dataset?: DOMStringMap,
18+
style?: Partial<CSSStyleDeclaration>,
19+
for?: string,
20+
textContent?: string,
21+
[key: string]: any
22+
};
23+
24+
export function $el(tag: string, propsOrChildren?: string | Element | Element[] | Props, children?: Element[] | Element): HTMLElement {
25+
const split = tag.split(".");
26+
const element = document.createElement(split.shift() as string);
27+
if (split.length > 0) {
28+
element.classList.add(...split);
29+
}
30+
31+
if (propsOrChildren) {
32+
if (typeof propsOrChildren === "string") {
33+
propsOrChildren = { textContent: propsOrChildren };
34+
} else if (propsOrChildren instanceof Element) {
35+
propsOrChildren = [propsOrChildren];
36+
}
37+
if (Array.isArray(propsOrChildren)) {
38+
element.append(...propsOrChildren);
39+
} else {
40+
const { parent, $: cb, dataset, style, ...rest } = propsOrChildren as Props;
41+
42+
if (rest.for) {
43+
element.setAttribute("for", rest.for)
44+
}
45+
46+
if (style) {
47+
Object.assign(element.style, style);
48+
}
49+
50+
if (dataset) {
51+
Object.assign(element.dataset, dataset);
52+
}
53+
54+
Object.assign(element, rest);
55+
if (children) {
56+
element.append(...(Array.isArray(children) ? children : [children]));
57+
}
58+
59+
if (parent) {
60+
parent.append(element);
61+
}
62+
63+
if (cb) {
64+
cb(element);
65+
}
66+
}
67+
}
68+
return element;
7169
}
7270

7371
function dragElement(dragEl, settings) {
@@ -130,9 +128,9 @@ function dragElement(dragEl, settings) {
130128
}
131129

132130
function restorePos() {
133-
let pos = localStorage.getItem("Comfy.MenuPosition");
134-
if (pos) {
135-
pos = JSON.parse(pos);
131+
let posString = localStorage.getItem("Comfy.MenuPosition");
132+
if (posString) {
133+
const pos = JSON.parse(posString) as Position2D;
136134
newPosX = pos.x;
137135
newPosY = pos.y;
138136
positionElement();
@@ -198,12 +196,14 @@ class ComfyList {
198196
#type;
199197
#text;
200198
#reverse;
199+
element: HTMLDivElement;
200+
button?: HTMLButtonElement;
201201

202-
constructor(text, type, reverse) {
202+
constructor(text, type?, reverse?) {
203203
this.#text = text;
204204
this.#type = type || text.toLowerCase();
205205
this.#reverse = reverse || false;
206-
this.element = $el("div.comfy-list");
206+
this.element = $el("div.comfy-list") as HTMLDivElement;
207207
this.element.style.display = "none";
208208
}
209209

@@ -289,6 +289,20 @@ class ComfyList {
289289
}
290290

291291
export class ComfyUI {
292+
app: ComfyApp;
293+
dialog: _ComfyDialog;
294+
settings: ComfySettingsDialog;
295+
batchCount: number;
296+
lastQueueSize: number;
297+
queue: ComfyList;
298+
history: ComfyList;
299+
autoQueueMode: string;
300+
graphHasChanged: boolean;
301+
autoQueueEnabled: boolean;
302+
menuHamburger: HTMLDivElement;
303+
menuContainer: HTMLDivElement;
304+
queueSize: Element;
305+
292306
constructor(app) {
293307
this.app = app;
294308
this.dialog = new ComfyDialog();
@@ -371,7 +385,7 @@ export class ComfyUI {
371385
onchange: () => {
372386
app.handleFile(fileInput.files[0]);
373387
},
374-
});
388+
}) as HTMLInputElement;
375389

376390
const autoQueueModeEl = toggleSwitch(
377391
"autoQueueMode",
@@ -408,7 +422,7 @@ export class ComfyUI {
408422
},
409423
},
410424
[$el("div"), $el("div"), $el("div")]
411-
);
425+
) as HTMLDivElement;
412426

413427
this.menuContainer = $el("div.comfy-menu", { parent: document.body }, [
414428
$el("div.drag-handle.comfy-menu-header", {
@@ -446,8 +460,9 @@ export class ComfyUI {
446460
type: "checkbox",
447461
onchange: (i) => {
448462
document.getElementById("extraOptions").style.display = i.srcElement.checked ? "block" : "none";
449-
this.batchCount = i.srcElement.checked ? document.getElementById("batchCountInputRange").value : 1;
450-
document.getElementById("autoQueueCheckbox").checked = false;
463+
this.batchCount = i.srcElement.checked ?
464+
Number.parseInt((document.getElementById("batchCountInputRange") as HTMLInputElement).value) : 1;
465+
(document.getElementById("autoQueueCheckbox") as HTMLInputElement).checked = false;
451466
this.autoQueueEnabled = false;
452467
},
453468
}),
@@ -462,10 +477,14 @@ export class ComfyUI {
462477
type: "number",
463478
value: this.batchCount,
464479
min: "1",
465-
style: { width: "35%", "margin-left": "0.4em" },
480+
style: { width: "35%", "marginLeft": "0.4em" },
466481
oninput: (i) => {
467482
this.batchCount = i.target.value;
468-
document.getElementById("batchCountInputRange").value = this.batchCount;
483+
/* Even though an <input> element with a type of range logically represents a number (since
484+
it's used for numeric input), the value it holds is still treated as a string in HTML and
485+
JavaScript. This behavior is consistent across all <input> elements regardless of their type
486+
(like text, number, or range), where the .value property is always a string. */
487+
(document.getElementById("batchCountInputRange") as HTMLInputElement).value = this.batchCount.toString();
469488
},
470489
}),
471490
$el("input", {
@@ -476,7 +495,8 @@ export class ComfyUI {
476495
value: this.batchCount,
477496
oninput: (i) => {
478497
this.batchCount = i.srcElement.value;
479-
document.getElementById("batchCountInputNumber").value = i.srcElement.value;
498+
// Note
499+
(document.getElementById("batchCountInputNumber") as HTMLInputElement).value = i.srcElement.value;
480500
},
481501
}),
482502
]),
@@ -505,7 +525,7 @@ export class ComfyUI {
505525
onclick: () => app.queuePrompt(-1, this.batchCount)
506526
}),
507527
$el("button", {
508-
$: (b) => (this.queue.button = b),
528+
$: (b) => (this.queue.button = b as HTMLButtonElement),
509529
id: "comfy-view-queue-button",
510530
textContent: "View Queue",
511531
onclick: () => {
@@ -514,7 +534,7 @@ export class ComfyUI {
514534
},
515535
}),
516536
$el("button", {
517-
$: (b) => (this.history.button = b),
537+
$: (b) => (this.history.button = b as HTMLButtonElement),
518538
id: "comfy-view-history-button",
519539
textContent: "View History",
520540
onclick: () => {
@@ -615,7 +635,7 @@ export class ComfyUI {
615635
app.resetView();
616636
}
617637
}),
618-
]);
638+
]) as HTMLDivElement;
619639

620640
const devMode = this.settings.addSetting({
621641
id: "Comfy.DevMode",

src/scripts/ui/settings.ts

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,30 @@ import { api } from "../api.js";
33
import { ComfyDialog } from "./dialog.js";
44
import type { ComfyApp } from "../app.js";
55

6+
/* The Setting entry stored in `ComfySettingsDialog` */
67
interface Setting {
78
id: string;
89
onChange?: (value: any, oldValue?: any) => void;
910
name: string;
1011
render: () => HTMLElement;
1112
}
1213

14+
interface SettingOption {
15+
text: string;
16+
value?: string;
17+
}
18+
19+
interface SettingParams {
20+
id: string;
21+
name: string;
22+
type: string | ((name: string, setter: (v: any) => void, value: any, attrs: any) => HTMLElement);
23+
defaultValue: any;
24+
onChange?: (newValue: any, oldValue?: any) => void;
25+
attrs?: any;
26+
tooltip?: string;
27+
options?: SettingOption[] | ((value: any) => SettingOption[]);
28+
}
29+
1330
export class ComfySettingsDialog extends ComfyDialog {
1431
app: ComfyApp;
1532
settingsValues: any;
@@ -114,7 +131,8 @@ export class ComfySettingsDialog extends ComfyDialog {
114131
});
115132
}
116133

117-
addSetting({ id, name, type, defaultValue, onChange, attrs = {}, tooltip = "", options = undefined }) {
134+
addSetting(params: SettingParams) {
135+
const { id, name, type, defaultValue, onChange, attrs = {}, tooltip = "", options = undefined } = params;
118136
if (!id) {
119137
throw new Error("Settings must have an ID");
120138
}
@@ -321,8 +339,6 @@ export class ComfySettingsDialog extends ComfyDialog {
321339
{
322340
style: { display: "none" },
323341
},
324-
// TODO remove this once ui.js is migrated.
325-
// @ts-ignore
326342
[$el("th"), $el("th", { style: { width: "33%" } })]
327343
),
328344
...this.settings.sort((a, b) => a.name.localeCompare(b.name)).map((s) => s.render())

0 commit comments

Comments
 (0)