refactor: improve component visibility management and styling

This commit is contained in:
AEmotionStudio
2026-01-13 21:23:10 -08:00
parent 4de67e52a9
commit 608904d1a7
14 changed files with 208 additions and 14 deletions
+62
View File
@@ -661,4 +661,66 @@
.pulse {
animation: pulse 2s infinite;
}
/* Focus Node Button Styling - Premium Glass */
.focus-node-btn {
display: inline-flex;
align-items: center;
gap: 6px;
/* Ghost Style Default */
background: transparent;
color: var(--info-panel-accent-color, #74b9ff);
border: 1px solid var(--info-panel-accent-color, #74b9ff);
padding: 2px 10px;
border-radius: 6px;
font-weight: 600;
font-size: 0.9em;
letter-spacing: 0.02em;
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
box-shadow: 0 0 0 rgba(0, 0, 0, 0);
opacity: 0.9;
}
.focus-node-btn:hover {
/* Glowing active state */
background: var(--info-panel-accent-color, #74b9ff);
color: #fff;
/* Switch to white text on fill */
/* Create a glow effect using the accent color */
box-shadow: 0 4px 12px -2px var(--info-panel-accent-color, #74b9ff),
0 0 0 1px var(--info-panel-accent-color, #74b9ff);
transform: translateY(-1px) scale(1.02);
opacity: 1;
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
}
.focus-node-btn:active {
transform: translateY(0) scale(0.98);
box-shadow: 0 2px 4px -2px var(--info-panel-accent-color, #74b9ff);
filter: brightness(0.95);
}
.focus-node-btn .icon {
display: flex;
align-items: center;
transition: transform 0.2s ease;
}
.focus-node-btn:hover .icon {
transform: scale(1.1);
}
/* Ensure the SVG inside inherits color properly */
.focus-node-btn svg {
stroke: currentColor;
width: 14px;
height: 14px;
stroke-width: 2.5;
/* Make icon slightly bolder */
}
+3 -2
View File
@@ -8,6 +8,7 @@
import { StateManager } from './StateManager';
import { Icons } from '../shared/icons';
import { Logger } from '../shared/logger';
import { INFO_PANEL_ID } from '../shared/constants';
import { formatValue, getValueClass, getValueAttributes, formatWidgetValue } from './ValueFormatter';
import {
getCheckpointInfo,
@@ -56,7 +57,7 @@ export class UIManager {
createPanel(): void {
// Main panel container
this.elements.panel = document.createElement("div");
this.elements.panel.id = "comfyui-magnify-info-panel-pro-v2";
this.elements.panel.id = INFO_PANEL_ID;
this.elements.panel.className = `magnify-info-panel theme-${this.stateManager.state.currentTheme}`;
// Header
@@ -773,7 +774,7 @@ export class UIManager {
// Add Zoom to Node button
nodeContent.push({
label: 'Location',
value: `<span style="display: flex; align-items: center; gap: 6px;">${Icons.focus} Focus Node</span>`,
value: `<span class="focus-node-btn">${Icons.focus} Focus Node</span>`,
clickable: 'zoom',
nodeId: info.hoveredNode.id
});
+35 -3
View File
@@ -6,7 +6,7 @@
import type { ComfyApp, ComfyNode } from '../types/comfyui';
import { findLiteGraphCanvas, rectsOverlap, Rectangle } from '../shared/utils';
import { DEFAULT_PADDING, DEFAULT_GLASS_Y_OFFSET } from '../shared/constants';
import { DEFAULT_PADDING, DEFAULT_GLASS_Y_OFFSET, INFO_PANEL_ID } from '../shared/constants';
import { registerGlassSettings, registerAccessibilitySettings } from '../shared/settings';
import { ConfigManager } from './ConfigManager';
import { MagnifierState } from './MagnifierState';
@@ -139,8 +139,7 @@ export class MagnifyGlass {
if (state.active) {
// TURNING OFF - Force hide everything
state.active = false;
this.ui.hide();
this.forceHideAllComponents();
} else {
// TURNING ON
state.active = true;
@@ -151,6 +150,39 @@ export class MagnifyGlass {
}
}
/**
* Force hide all components including extensions (Info Panel, etc).
* This overcomes the "pinned" state of the info panel when the main tool is deactivated.
*/
private forceHideAllComponents(): void {
this.state.active = false;
this.ui.hide();
// 1. Nuclear option: Direct DOM ID targeting
// This is necessary because in some cases object references might be stale or logic might prevent hiding
const panelEl = document.getElementById(INFO_PANEL_ID);
if (panelEl) {
panelEl.style.display = 'none';
// Also force opacity 0 just in case transition handles display
panelEl.style.opacity = '0';
}
// Iterate through all registered extensions and hide them if they have a hide method
const extensions = window.comfyUIMagnifyGlassExtensions;
if (extensions && extensions.length > 0) {
extensions.forEach((extension: any) => {
// Check basically any likely property for a UI manager or direct hide method
if (extension && extension.uiManager && typeof extension.uiManager.hide === 'function') {
extension.uiManager.hide();
// Explicitly force display none if available to be extra sure
if (extension.uiManager.elements && extension.uiManager.elements.panel) {
extension.uiManager.elements.panel.style.display = 'none';
}
}
});
}
}
/**
* Set glass preview visibility WITHOUT affecting info panel.
* This is used by the toggle-glass hover control button.
+6
View File
@@ -43,6 +43,12 @@ function initializeInfoPanel() {
// Expose orchestrator globally if needed
window.infoPanelManager = infoPanel as any;
// Register as extension for central management (e.g. force hide on toggle)
if (!window.comfyUIMagnifyGlassExtensions) {
window.comfyUIMagnifyGlassExtensions = [];
}
window.comfyUIMagnifyGlassExtensions.push(infoPanel);
// CSS is loaded by UIManager.injectStyles() - no need to load separately
Logger.info('Info Panel extension initialized');
+1
View File
@@ -64,6 +64,7 @@ export const DEFAULT_OFFSET_STEP = 5;
export const DEFAULT_PANEL_WIDTH = 300;
export const DEFAULT_PANEL_MAX_HEIGHT = 300;
export const DEFAULT_PANEL_OPACITY = 100;
export const INFO_PANEL_ID = "comfyui-magnify-info-panel-pro-v2";
// Z-Index hierarchy
export const Z_INDEX = {
+62
View File
@@ -795,4 +795,66 @@
.pulse {
animation: pulse 2s infinite;
}
/* Focus Node Button Styling - Premium Glass */
.focus-node-btn {
display: inline-flex;
align-items: center;
gap: 6px;
/* Ghost Style Default */
background: transparent;
color: var(--info-panel-accent-color, #74b9ff);
border: 1px solid var(--info-panel-accent-color, #74b9ff);
padding: 2px 10px;
border-radius: 6px;
font-weight: 600;
font-size: 0.9em;
letter-spacing: 0.02em;
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
box-shadow: 0 0 0 rgba(0, 0, 0, 0);
opacity: 0.9;
}
.focus-node-btn:hover {
/* Glowing active state */
background: var(--info-panel-accent-color, #74b9ff);
color: #fff;
/* Switch to white text on fill */
/* Create a glow effect using the accent color */
box-shadow: 0 4px 12px -2px var(--info-panel-accent-color, #74b9ff),
0 0 0 1px var(--info-panel-accent-color, #74b9ff);
transform: translateY(-1px) scale(1.02);
opacity: 1;
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
}
.focus-node-btn:active {
transform: translateY(0) scale(0.98);
box-shadow: 0 2px 4px -2px var(--info-panel-accent-color, #74b9ff);
filter: brightness(0.95);
}
.focus-node-btn .icon {
display: flex;
align-items: center;
transition: transform 0.2s ease;
}
.focus-node-btn:hover .icon {
transform: scale(1.1);
}
/* Ensure the SVG inside inherits color properly */
.focus-node-btn svg {
stroke: currentColor;
width: 14px;
height: 14px;
stroke-width: 2.5;
/* Make icon slightly bolder */
}
+3 -2
View File
@@ -3,6 +3,7 @@ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { en
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
import { Icons } from "../shared/icons.js";
import { Logger } from "../shared/logger.js";
import { INFO_PANEL_ID } from "../shared/constants.js";
import { formatValue, getValueClass, getValueAttributes } from "./ValueFormatter.js";
import { getCheckpointInfo, getImageInfo, getTextBoxContent, getImportantNodeParameters } from "./NodeDataExtractor.js";
import { NodeSelector } from "./NodeSelector.js";
@@ -29,7 +30,7 @@ class UIManager {
*/
createPanel() {
this.elements.panel = document.createElement("div");
this.elements.panel.id = "comfyui-magnify-info-panel-pro-v2";
this.elements.panel.id = INFO_PANEL_ID;
this.elements.panel.className = `magnify-info-panel theme-${this.stateManager.state.currentTheme}`;
this.elements.header = document.createElement("div");
this.elements.header.className = "panel-header";
@@ -557,7 +558,7 @@ class UIManager {
}
nodeContent.push({
label: "Location",
value: `<span style="display: flex; align-items: center; gap: 6px;">${Icons.focus} Focus Node</span>`,
value: `<span class="focus-node-btn">${Icons.focus} Focus Node</span>`,
clickable: "zoom",
nodeId: info.hoveredNode.id
});
File diff suppressed because one or more lines are too long
+26 -3
View File
@@ -2,7 +2,7 @@ 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 { findLiteGraphCanvas, rectsOverlap } from "../shared/utils.js";
import { DEFAULT_PADDING, DEFAULT_GLASS_Y_OFFSET } from "../shared/constants.js";
import { INFO_PANEL_ID, DEFAULT_PADDING, DEFAULT_GLASS_Y_OFFSET } from "../shared/constants.js";
import { registerGlassSettings } from "../shared/settings/glassSettings.js";
import "/scripts/app.js";
import { registerAccessibilitySettings } from "../shared/settings/accessibilitySettings.js";
@@ -86,8 +86,7 @@ class MagnifyGlass {
toggle() {
const state = this.state;
if (state.active) {
state.active = false;
this.ui.hide();
this.forceHideAllComponents();
} else {
state.active = true;
this.ui.show();
@@ -96,6 +95,30 @@ class MagnifyGlass {
}
}
}
/**
* Force hide all components including extensions (Info Panel, etc).
* This overcomes the "pinned" state of the info panel when the main tool is deactivated.
*/
forceHideAllComponents() {
this.state.active = false;
this.ui.hide();
const panelEl = document.getElementById(INFO_PANEL_ID);
if (panelEl) {
panelEl.style.display = "none";
panelEl.style.opacity = "0";
}
const extensions = window.comfyUIMagnifyGlassExtensions;
if (extensions && extensions.length > 0) {
extensions.forEach((extension) => {
if (extension && extension.uiManager && typeof extension.uiManager.hide === "function") {
extension.uiManager.hide();
if (extension.uiManager.elements && extension.uiManager.elements.panel) {
extension.uiManager.elements.panel.style.display = "none";
}
}
});
}
}
/**
* Set glass preview visibility WITHOUT affecting info panel.
* This is used by the toggle-glass hover control button.
File diff suppressed because one or more lines are too long
+4
View File
@@ -23,6 +23,10 @@ function initializeInfoPanel() {
try {
const infoPanel = new InfoPanel(magnifyGlass);
window.infoPanelManager = infoPanel;
if (!window.comfyUIMagnifyGlassExtensions) {
window.comfyUIMagnifyGlassExtensions = [];
}
window.comfyUIMagnifyGlassExtensions.push(infoPanel);
Logger.info("Info Panel extension initialized");
} catch (e) {
Logger.error("Error during initialization:", e);
+1 -1
View File
@@ -1 +1 @@
{"version":3,"file":"magnify_info_panel.js","sources":["../src/magnify_info_panel.ts"],"sourcesContent":["/**\n * ComfyUI Magnify Info Panel - Main Entry Point\n * \n * Initializes the Info Panel extension.\n */\n\nimport { InfoPanel } from './info-panel';\nimport { Logger } from './shared/logger';\n// @ts-ignore\nimport { app } from \"/scripts/app.js\";\n\n// We rely on the global 'app' object provided by ComfyUI\n// No need to import it as it's global, but TypeScript needs to know about it.\n// We handled this in types/comfyui.d.ts\n\napp.registerExtension({\n name: \"comfyui.magnify.info.panel\",\n init() {\n // Wait for magnify glass to be available\n const checkDependencies = () => {\n if (window.comfyUIMagnifyGlass) {\n initializeInfoPanel();\n } else {\n setTimeout(checkDependencies, 100);\n }\n };\n\n checkDependencies();\n }\n});\n\nfunction initializeInfoPanel() {\n const magnifyGlass = window.comfyUIMagnifyGlass;\n if (!magnifyGlass) {\n Logger.error('Failed to find MagnifyGlass instance.');\n return;\n }\n\n try {\n // Initialize the info panel\n const infoPanel = new InfoPanel(magnifyGlass);\n\n // Expose orchestrator globally if needed\n window.infoPanelManager = infoPanel as any;\n\n // CSS is loaded by UIManager.injectStyles() - no need to load separately\n\n Logger.info('Info Panel extension initialized');\n } catch (e) {\n Logger.error('Error during initialization:', e);\n }\n}\n\n"],"names":[],"mappings":";;;AAeA,IAAI,kBAAkB;AAAA,EAClB,MAAM;AAAA,EACN,OAAO;AAEH,UAAM,oBAAoB,MAAM;AAC5B,UAAI,OAAO,qBAAqB;AAC5B,4BAAA;AAAA,MACJ,OAAO;AACH,mBAAW,mBAAmB,GAAG;AAAA,MACrC;AAAA,IACJ;AAEA,sBAAA;AAAA,EACJ;AACJ,CAAC;AAED,SAAS,sBAAsB;AAC3B,QAAM,eAAe,OAAO;AAC5B,MAAI,CAAC,cAAc;AACf,WAAO,MAAM,uCAAuC;AACpD;AAAA,EACJ;AAEA,MAAI;AAEA,UAAM,YAAY,IAAI,UAAU,YAAY;AAG5C,WAAO,mBAAmB;AAI1B,WAAO,KAAK,kCAAkC;AAAA,EAClD,SAAS,GAAG;AACR,WAAO,MAAM,gCAAgC,CAAC;AAAA,EAClD;AACJ;"}
{"version":3,"file":"magnify_info_panel.js","sources":["../src/magnify_info_panel.ts"],"sourcesContent":["/**\n * ComfyUI Magnify Info Panel - Main Entry Point\n * \n * Initializes the Info Panel extension.\n */\n\nimport { InfoPanel } from './info-panel';\nimport { Logger } from './shared/logger';\n// @ts-ignore\nimport { app } from \"/scripts/app.js\";\n\n// We rely on the global 'app' object provided by ComfyUI\n// No need to import it as it's global, but TypeScript needs to know about it.\n// We handled this in types/comfyui.d.ts\n\napp.registerExtension({\n name: \"comfyui.magnify.info.panel\",\n init() {\n // Wait for magnify glass to be available\n const checkDependencies = () => {\n if (window.comfyUIMagnifyGlass) {\n initializeInfoPanel();\n } else {\n setTimeout(checkDependencies, 100);\n }\n };\n\n checkDependencies();\n }\n});\n\nfunction initializeInfoPanel() {\n const magnifyGlass = window.comfyUIMagnifyGlass;\n if (!magnifyGlass) {\n Logger.error('Failed to find MagnifyGlass instance.');\n return;\n }\n\n try {\n // Initialize the info panel\n const infoPanel = new InfoPanel(magnifyGlass);\n\n // Expose orchestrator globally if needed\n window.infoPanelManager = infoPanel as any;\n\n // Register as extension for central management (e.g. force hide on toggle)\n if (!window.comfyUIMagnifyGlassExtensions) {\n window.comfyUIMagnifyGlassExtensions = [];\n }\n window.comfyUIMagnifyGlassExtensions.push(infoPanel);\n\n // CSS is loaded by UIManager.injectStyles() - no need to load separately\n\n Logger.info('Info Panel extension initialized');\n } catch (e) {\n Logger.error('Error during initialization:', e);\n }\n}\n\n"],"names":[],"mappings":";;;AAeA,IAAI,kBAAkB;AAAA,EAClB,MAAM;AAAA,EACN,OAAO;AAEH,UAAM,oBAAoB,MAAM;AAC5B,UAAI,OAAO,qBAAqB;AAC5B,4BAAA;AAAA,MACJ,OAAO;AACH,mBAAW,mBAAmB,GAAG;AAAA,MACrC;AAAA,IACJ;AAEA,sBAAA;AAAA,EACJ;AACJ,CAAC;AAED,SAAS,sBAAsB;AAC3B,QAAM,eAAe,OAAO;AAC5B,MAAI,CAAC,cAAc;AACf,WAAO,MAAM,uCAAuC;AACpD;AAAA,EACJ;AAEA,MAAI;AAEA,UAAM,YAAY,IAAI,UAAU,YAAY;AAG5C,WAAO,mBAAmB;AAG1B,QAAI,CAAC,OAAO,+BAA+B;AACvC,aAAO,gCAAgC,CAAA;AAAA,IAC3C;AACA,WAAO,8BAA8B,KAAK,SAAS;AAInD,WAAO,KAAK,kCAAkC;AAAA,EAClD,SAAS,GAAG;AACR,WAAO,MAAM,gCAAgC,CAAC;AAAA,EAClD;AACJ;"}
+2
View File
@@ -33,6 +33,7 @@ const DEFAULT_OFFSET_STEP = 5;
const DEFAULT_PANEL_WIDTH = 300;
const DEFAULT_PANEL_MAX_HEIGHT = 300;
const DEFAULT_PANEL_OPACITY = 100;
const INFO_PANEL_ID = "comfyui-magnify-info-panel-pro-v2";
const Z_INDEX = {
GLASS: 98999
};
@@ -57,6 +58,7 @@ export {
DIRECT_CAPTURE_KEYS,
GLASS_POSITIONS,
GLASS_SHAPES,
INFO_PANEL_ID,
PANEL_POSITIONS,
RESET_KEYS,
STORAGE_KEYS,
+1 -1
View File
@@ -1 +1 @@
{"version":3,"file":"constants.js","sources":["../../src/shared/constants.ts"],"sourcesContent":["/**\n * ComfyUI MagnifyGlass - Shared Constants\n * \n * Configuration constants shared between magnify glass and info panel modules.\n */\n\n// Glass positioning options\nexport const GLASS_POSITIONS = [\n \"Top\",\n \"Bottom\",\n \"Left\",\n \"Right\",\n \"Top-Left\",\n \"Top-Right\",\n \"Bottom-Left\",\n \"Bottom-Right\"\n] as const;\n\nexport type GlassPosition = typeof GLASS_POSITIONS[number];\n\n// Glass shape options\nexport const GLASS_SHAPES = [\n \"Circle\",\n \"Square\",\n \"Rounded Square\"\n] as const;\n\nexport type GlassShape = typeof GLASS_SHAPES[number];\n\n// Texture filtering modes\nexport const TEXTURE_FILTERS = [\n \"Linear\",\n \"Nearest\"\n] as const;\n\nexport type TextureFilter = typeof TEXTURE_FILTERS[number];\n\n// Info panel positions relative to glass\nexport const PANEL_POSITIONS = [\n \"Top\",\n \"Bottom\",\n \"Left\",\n \"Right\"\n] as const;\n\nexport type PanelPosition = typeof PANEL_POSITIONS[number];\n\n// Available keys for settings\nexport const ACTIVATION_KEYS = [\"x\", \"z\", \"m\", \"q\", \"v\", \"c\"] as const;\nexport const RESET_KEYS = [\"r\", \"o\", \"p\", \"k\", \"l\"] as const;\nexport const TOGGLE_FOLLOW_KEYS = [\"f\", \"g\", \"h\", \"j\", \"k\"] as const;\nexport const DIRECT_CAPTURE_KEYS = [\"d\", \"s\", \"a\", \"q\", \"e\"] as const;\n\n// UI Constants\nexport const DEFAULT_PADDING = 4;\nexport const DEFAULT_GLASS_Y_OFFSET = 200; // Starting Y position offset (below top bar with 3px gap)\nexport const DEFAULT_GLASS_SIZE = 300;\nexport const DEFAULT_ZOOM_FACTOR = 300; // 3x as percentage\nexport const DEFAULT_BORDER_WIDTH = 1;\nexport const DEFAULT_BORDER_COLOR = \"#6b7280\";\nexport const DEFAULT_OFFSET_STEP = 5;\n\n// Panel Constants\nexport const DEFAULT_PANEL_WIDTH = 300;\nexport const DEFAULT_PANEL_MAX_HEIGHT = 300;\nexport const DEFAULT_PANEL_OPACITY = 100;\n\n// Z-Index hierarchy\nexport const Z_INDEX = {\n GLASS: 98999,\n DEBUG: 99000,\n PANEL: 99999,\n CONTROLS: 99998\n} as const;\n\n// Animation durations (ms)\nexport const ANIMATION = {\n PANEL_TRANSITION: 300,\n AUTO_COLLAPSE_DELAY: 1500,\n THEME_DETECTION_INTERVAL: 2000\n} as const;\n\n// LocalStorage keys\nexport const STORAGE_KEYS = {\n OFFSET_X: 'comfyui_magnify_offset_x',\n OFFSET_Y: 'comfyui_magnify_offset_y'\n} as const;\n\n// BroadcastChannel for pop-out tab communication\nexport const BROADCAST_CHANNEL_NAME = 'comfyui-magnifyglass-popout';\n\n"],"names":[],"mappings":"AAOO,MAAM,kBAAkB;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACJ;AAKO,MAAM,eAAe;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AACJ;AAaO,MAAM,kBAAkB;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACJ;AAKO,MAAM,kBAAkB,CAAC,KAAK,KAAK,KAAK,KAAK,KAAK,GAAG;AACrD,MAAM,aAAa,CAAC,KAAK,KAAK,KAAK,KAAK,GAAG;AAC3C,MAAM,qBAAqB,CAAC,KAAK,KAAK,KAAK,KAAK,GAAG;AACnD,MAAM,sBAAsB,CAAC,KAAK,KAAK,KAAK,KAAK,GAAG;AAGpD,MAAM,kBAAkB;AACxB,MAAM,yBAAyB;AAC/B,MAAM,qBAAqB;AAC3B,MAAM,sBAAsB;AAC5B,MAAM,uBAAuB;AAC7B,MAAM,uBAAuB;AAC7B,MAAM,sBAAsB;AAG5B,MAAM,sBAAsB;AAC5B,MAAM,2BAA2B;AACjC,MAAM,wBAAwB;AAG9B,MAAM,UAAU;AAAA,EACnB,OAAO;AAIX;AAUO,MAAM,eAAe;AAAA,EACxB,UAAU;AAAA,EACV,UAAU;AACd;AAGO,MAAM,yBAAyB;"}
{"version":3,"file":"constants.js","sources":["../../src/shared/constants.ts"],"sourcesContent":["/**\n * ComfyUI MagnifyGlass - Shared Constants\n * \n * Configuration constants shared between magnify glass and info panel modules.\n */\n\n// Glass positioning options\nexport const GLASS_POSITIONS = [\n \"Top\",\n \"Bottom\",\n \"Left\",\n \"Right\",\n \"Top-Left\",\n \"Top-Right\",\n \"Bottom-Left\",\n \"Bottom-Right\"\n] as const;\n\nexport type GlassPosition = typeof GLASS_POSITIONS[number];\n\n// Glass shape options\nexport const GLASS_SHAPES = [\n \"Circle\",\n \"Square\",\n \"Rounded Square\"\n] as const;\n\nexport type GlassShape = typeof GLASS_SHAPES[number];\n\n// Texture filtering modes\nexport const TEXTURE_FILTERS = [\n \"Linear\",\n \"Nearest\"\n] as const;\n\nexport type TextureFilter = typeof TEXTURE_FILTERS[number];\n\n// Info panel positions relative to glass\nexport const PANEL_POSITIONS = [\n \"Top\",\n \"Bottom\",\n \"Left\",\n \"Right\"\n] as const;\n\nexport type PanelPosition = typeof PANEL_POSITIONS[number];\n\n// Available keys for settings\nexport const ACTIVATION_KEYS = [\"x\", \"z\", \"m\", \"q\", \"v\", \"c\"] as const;\nexport const RESET_KEYS = [\"r\", \"o\", \"p\", \"k\", \"l\"] as const;\nexport const TOGGLE_FOLLOW_KEYS = [\"f\", \"g\", \"h\", \"j\", \"k\"] as const;\nexport const DIRECT_CAPTURE_KEYS = [\"d\", \"s\", \"a\", \"q\", \"e\"] as const;\n\n// UI Constants\nexport const DEFAULT_PADDING = 4;\nexport const DEFAULT_GLASS_Y_OFFSET = 200; // Starting Y position offset (below top bar with 3px gap)\nexport const DEFAULT_GLASS_SIZE = 300;\nexport const DEFAULT_ZOOM_FACTOR = 300; // 3x as percentage\nexport const DEFAULT_BORDER_WIDTH = 1;\nexport const DEFAULT_BORDER_COLOR = \"#6b7280\";\nexport const DEFAULT_OFFSET_STEP = 5;\n\n// Panel Constants\nexport const DEFAULT_PANEL_WIDTH = 300;\nexport const DEFAULT_PANEL_MAX_HEIGHT = 300;\nexport const DEFAULT_PANEL_OPACITY = 100;\nexport const INFO_PANEL_ID = \"comfyui-magnify-info-panel-pro-v2\";\n\n// Z-Index hierarchy\nexport const Z_INDEX = {\n GLASS: 98999,\n DEBUG: 99000,\n PANEL: 99999,\n CONTROLS: 99998\n} as const;\n\n// Animation durations (ms)\nexport const ANIMATION = {\n PANEL_TRANSITION: 300,\n AUTO_COLLAPSE_DELAY: 1500,\n THEME_DETECTION_INTERVAL: 2000\n} as const;\n\n// LocalStorage keys\nexport const STORAGE_KEYS = {\n OFFSET_X: 'comfyui_magnify_offset_x',\n OFFSET_Y: 'comfyui_magnify_offset_y'\n} as const;\n\n// BroadcastChannel for pop-out tab communication\nexport const BROADCAST_CHANNEL_NAME = 'comfyui-magnifyglass-popout';\n\n"],"names":[],"mappings":"AAOO,MAAM,kBAAkB;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACJ;AAKO,MAAM,eAAe;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AACJ;AAaO,MAAM,kBAAkB;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACJ;AAKO,MAAM,kBAAkB,CAAC,KAAK,KAAK,KAAK,KAAK,KAAK,GAAG;AACrD,MAAM,aAAa,CAAC,KAAK,KAAK,KAAK,KAAK,GAAG;AAC3C,MAAM,qBAAqB,CAAC,KAAK,KAAK,KAAK,KAAK,GAAG;AACnD,MAAM,sBAAsB,CAAC,KAAK,KAAK,KAAK,KAAK,GAAG;AAGpD,MAAM,kBAAkB;AACxB,MAAM,yBAAyB;AAC/B,MAAM,qBAAqB;AAC3B,MAAM,sBAAsB;AAC5B,MAAM,uBAAuB;AAC7B,MAAM,uBAAuB;AAC7B,MAAM,sBAAsB;AAG5B,MAAM,sBAAsB;AAC5B,MAAM,2BAA2B;AACjC,MAAM,wBAAwB;AAC9B,MAAM,gBAAgB;AAGtB,MAAM,UAAU;AAAA,EACnB,OAAO;AAIX;AAUO,MAAM,eAAe;AAAA,EACxB,UAAU;AAAA,EACV,UAAU;AACd;AAGO,MAAM,yBAAyB;"}