Restyle the panel on ComfyUI palette tokens and drop the built-in themes. Add a header with Back/Forward, Prev/Next, Focus, Lock and a searchable Go to node picker, a subgraph/group breadcrumb, and simplified modes: Follow glass or Float, plus Sticky, Follow selection and Lock to node (replaces Hold). Fix widget edits (step2 steps, INT/FLOAT, commit on Enter/blur, undo), subgraph lookups, orphaned dropdown menus, global arrow-key capture, the pop-out editor, and remove Google Fonts loading and dead code. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
140 lines
5.1 KiB
JavaScript
140 lines
5.1 KiB
JavaScript
var __defProp = Object.defineProperty;
|
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
import { getSettingValue, clamp } from "../shared/utils.js";
|
|
import { DEFAULT_PANEL_SETTINGS } from "../shared/settings/defaults.js";
|
|
import "/scripts/app.js";
|
|
import { STORAGE_KEYS, PANEL_FONTS } from "../shared/constants.js";
|
|
class StateManager {
|
|
constructor() {
|
|
__publicField(this, "state");
|
|
this.state = {
|
|
// Panel visibility and positioning
|
|
isPanelVisible: false,
|
|
wasPanelVisibleBeforeHide: false,
|
|
isPanelMinimized: false,
|
|
isFloating: false,
|
|
floatPosition: null,
|
|
// Glass visibility
|
|
isGlassPreviewVisible: true,
|
|
isPanelHovered: false,
|
|
currentNodeId: null,
|
|
lockedNodeId: null,
|
|
lockedGraph: null,
|
|
showsSelection: false,
|
|
// Settings cache
|
|
settings: {}
|
|
};
|
|
this.loadSettings();
|
|
this.loadLayout();
|
|
}
|
|
/**
|
|
* Float mode, float position and minimized state are kept per browser.
|
|
*/
|
|
loadLayout() {
|
|
try {
|
|
const layout = JSON.parse(localStorage.getItem(STORAGE_KEYS.INSPECTOR_LAYOUT) || "{}");
|
|
this.state.isFloating = layout.floating === true;
|
|
this.state.isPanelMinimized = layout.minimized === true;
|
|
if (Number.isFinite(layout.x) && Number.isFinite(layout.y)) {
|
|
this.state.floatPosition = { x: layout.x, y: layout.y };
|
|
}
|
|
} catch (e) {
|
|
}
|
|
}
|
|
saveLayout() {
|
|
const { isFloating, floatPosition, isPanelMinimized } = this.state;
|
|
try {
|
|
localStorage.setItem(STORAGE_KEYS.INSPECTOR_LAYOUT, JSON.stringify({ floating: isFloating, minimized: isPanelMinimized, ...floatPosition }));
|
|
} catch (e) {
|
|
}
|
|
}
|
|
loadSettings() {
|
|
const defaults = DEFAULT_PANEL_SETTINGS;
|
|
Object.keys(defaults).forEach((key) => {
|
|
this.state.settings[key] = getSettingValue(key, defaults[key]);
|
|
});
|
|
this.state.settings["🔍MagnifyGlass.InfoPanelWidth"] = this.validateNumber(
|
|
this.state.settings["🔍MagnifyGlass.InfoPanelWidth"],
|
|
200,
|
|
600,
|
|
defaults["🔍MagnifyGlass.InfoPanelWidth"]
|
|
);
|
|
this.state.settings["🔍MagnifyGlass.InfoPanelMaxHeight"] = this.validateNumber(
|
|
this.state.settings["🔍MagnifyGlass.InfoPanelMaxHeight"],
|
|
200,
|
|
1500,
|
|
defaults["🔍MagnifyGlass.InfoPanelMaxHeight"]
|
|
);
|
|
this.state.settings["🔍MagnifyGlass.InfoPanelOpacity"] = this.validateNumber(
|
|
this.state.settings["🔍MagnifyGlass.InfoPanelOpacity"],
|
|
10,
|
|
100,
|
|
defaults["🔍MagnifyGlass.InfoPanelOpacity"]
|
|
);
|
|
this.state.settings["🔍MagnifyGlass.InfoPanelFontSize"] = this.validateNumber(
|
|
this.state.settings["🔍MagnifyGlass.InfoPanelFontSize"],
|
|
8,
|
|
24,
|
|
defaults["🔍MagnifyGlass.InfoPanelFontSize"]
|
|
);
|
|
this.state.settings["🔍MagnifyGlass.InfoPanelTextColor"] = this.validateColor(
|
|
this.state.settings["🔍MagnifyGlass.InfoPanelTextColor"],
|
|
defaults["🔍MagnifyGlass.InfoPanelTextColor"]
|
|
);
|
|
this.state.settings["🔍MagnifyGlass.InfoPanelAccentColor"] = this.validateColor(
|
|
this.state.settings["🔍MagnifyGlass.InfoPanelAccentColor"],
|
|
defaults["🔍MagnifyGlass.InfoPanelAccentColor"]
|
|
);
|
|
const validPanelPositions = ["Bottom", "Top", "Left", "Right"];
|
|
this.state.settings["🔍MagnifyGlass.InfoPanelPosition"] = this.validateStringOption(
|
|
this.state.settings["🔍MagnifyGlass.InfoPanelPosition"],
|
|
validPanelPositions,
|
|
defaults["🔍MagnifyGlass.InfoPanelPosition"]
|
|
);
|
|
const validControlPositions = ["top-left", "top-right", "bottom-left", "bottom-right", "top", "bottom", "left", "right"];
|
|
this.state.settings["🔍MagnifyGlass.ControlsPosition"] = this.validateStringOption(
|
|
this.state.settings["🔍MagnifyGlass.ControlsPosition"],
|
|
validControlPositions,
|
|
defaults["🔍MagnifyGlass.ControlsPosition"]
|
|
);
|
|
this.state.settings["🔍MagnifyGlass.InfoPanelFontFamily"] = this.validateStringOption(
|
|
this.state.settings["🔍MagnifyGlass.InfoPanelFontFamily"],
|
|
PANEL_FONTS,
|
|
defaults["🔍MagnifyGlass.InfoPanelFontFamily"]
|
|
);
|
|
}
|
|
/**
|
|
* Validate numeric input with bounds checking.
|
|
*/
|
|
validateNumber(value, min, max, fallback) {
|
|
const num = Number(value);
|
|
if (isNaN(num)) return fallback;
|
|
return clamp(num, min, max);
|
|
}
|
|
/**
|
|
* Validate color string (hex).
|
|
*/
|
|
validateColor(color, fallback) {
|
|
if (!color || typeof color !== "string") return fallback;
|
|
if (/^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{4}|[0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})$/.test(color)) {
|
|
return color;
|
|
}
|
|
return fallback;
|
|
}
|
|
/**
|
|
* Validate string against an allowlist.
|
|
*/
|
|
validateStringOption(value, options, fallback) {
|
|
if (typeof value !== "string") return fallback;
|
|
return options.includes(value) ? value : fallback;
|
|
}
|
|
toggleMinimized() {
|
|
this.state.isPanelMinimized = !this.state.isPanelMinimized;
|
|
return this.state.isPanelMinimized;
|
|
}
|
|
}
|
|
export {
|
|
StateManager
|
|
};
|