Files
AEmotionStudio-ComfyUI-Magn…/web/info-panel/StateManager.js
T
Æmotion StudioandClaude Opus 5.5 4b06ee92bb Update the Inspector panel look, navigation and editing
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>
2026-11-04 06:47:21 -08:00

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
};