var __defProp = Object.defineProperty;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
import { defineComponent, watchEffect, computed, resolveDirective, withDirectives, openBlock, createElementBlock, normalizeStyle, createVNode, unref, createElementVNode, vShow, onMounted, onBeforeUnmount, createBlock, withCtx, renderSlot, createCommentVNode, resolveDynamicComponent, Fragment, renderList, toDisplayString, watch, ref, nextTick, mergeProps, markRaw, onUnmounted, withModifiers, withKeys, normalizeClass, createStaticVNode, Transition, reactive, readonly, provide, shallowRef, createTextVNode, isRef, toRaw, Teleport, toRefs, useId, onUpdated, inject, onErrorCaptured, useTemplateRef, mergeModels, useModel, toRef, withMemo, createSlots, useSlots } from "vue";
import { u as useWorkspaceStore, a as useSettingStore, b as app, s as showNativeSystemMenu, _ as _export_sfc, c as useWorkflowStore, d as useSidebarTabStore, e as useBottomPanelStore, f as useDialogService, g as useCanvasStore, h as useCanvasPositionConversion, i as useElementBounding, j as isComponentWidget, k as isDOMWidget, l as useEventListener, m as useDomWidgetStore, w as whenever, n as useChainCallback, o as useThrottleFn, p as api, r as renderMinimapToCanvas, q as useColorPaletteStore, t as calculateNodeBounds, v as enforceMinimumBounds, x as calculateMinimapScale, y as useRafFn, z as useCommandStore, A as useCanvasInteractions, L as LiteGraph, B as useNodeDefStore, C as isOverNodeInput, D as st, E as normalizeI18nKey, F as isOverNodeOutput, G as LGraphCanvas, H as getItemsColorOption, I as adjustColor, J as isColorable, S as SubgraphNode, K as isLGraphNode, M as useNodeHelpStore, N as useNodeLibrarySidebarTab, O as isLoad3dNode, P as t, Q as isImageNode, R as useSelectedLiteGraphItems, T as createBounds, U as useExtensionService, V as useTitleEditorStore, W as LGraphGroup, X as LGraphNode, Y as EditableText, Z as useDebounceFn, $ as defineStore, a0 as useMouse, a1 as useNodeFrequencyStore, a2 as useNodeBookmarkStore, a3 as highlightQuery, a4 as formatNumberWithSuffix, a5 as NodeSourceType, a6 as NodePreview, a7 as NodeSearchFilter, a8 as SearchFilterChip, a9 as useLitegraphService, aa as storeToRefs, ab as LinkReleaseTriggerAction, ac as axios, ad as COMFY_API_BASE_URL, ae as isAbortError, af as useSystemStatsStore, ag as compareVersions, ah as isElectron, ai as stringToLocale, aj as useConflictAcknowledgment, ak as electronAPI, al as formatVersionAnchor, am as marked, an as useConflictDetection, ao as useUserStore, ap as useKeybindingStore, aq as usePragmaticDraggable, ar as usePragmaticDroppable, as as useWorkflowThumbnail, at as useWorkflowService, au as debounce, av as useMutationObserver, aw as useResizeObserver, ax as useWorkflowBookmarkStore, ay as useScroll, az as useLayoutMutations, aA as QuadTree, aB as LayoutSource, aC as computedWithControl, aD as useExtensionStore, aE as NodeBadgeMode, aF as BadgePosition, aG as LGraphBadge, aH as toolkit, aI as useModelToNodeStore, aJ as ComfyNodeDefImpl, aK as ComfyModelDef, aL as ComfyWorkflow, aM as te, aN as LGraph, aO as LLink, aP as DragAndScale, aQ as ContextMenu$1, aR as CanvasPointer, aS as isVideoNode, aT as isAudioNode, aU as getStorageValue, aV as setStorageValue, aW as tryOnScopeDispose, aX as LinkMarkerShape, aY as layoutStore, aZ as log, a_ as getSlotPosition, a$ as LinkDirection, b0 as Reroute, b1 as LitegraphLinkAdapter, b2 as getSlotKey, b3 as calculateInputSlotPos, b4 as calculateOutputSlotPos, b5 as useErrorHandling, b6 as COMFY_VUE_NODE_DIMENSIONS, b7 as isSlotObject, b8 as renderMarkdownToHtml, b9 as useExecutionStore, ba as useToastStore, bb as IS_CONTROL_WIDGET, bc as updateControlWidgetLabel, bd as useColorPaletteService, be as ChangeTracker, bf as UnauthorizedError, bg as __vitePreload, bh as i18n, bi as migrateLegacyRerouteNodes, bj as useQueueSettingsStore, bk as useQueuePendingTaskCountStore, bl as useLocalStorage, bm as useDraggable, bn as watchDebounced, bo as useEventBus, bp as clamp, bq as appendJsonExt, br as useSubgraphNavigationStore, bs as forEachSubgraphNode, bt as useMenuItemStore, bu as useDialogStore, bv as useManagerStateStore, bw as _imports_0, bx as SettingDialogHeader, by as SettingDialogContent, bz as ManagerUIState, bA as useCurrentUser, bB as useFirebaseAuthActions, bC as _sfc_main$1C, bD as isNativeWindow, bE as useTitle, bF as getBaseButtonClasses, bG as getIconButtonSizeClasses, bH as getBorderButtonTypeClasses, bI as getButtonTypeClasses, bJ as getButtonSizeClasses, bK as useBreakpoints, bL as _sfc_main$1D, bM as getAllNonIoNodesInSubgraph, bN as useQueueStore, bO as getExecutionIdsForSelectedNodes, bP as LGraphEventMode, bQ as DEFAULT_DARK_COLOR_PALETTE, bR as DEFAULT_LIGHT_COLOR_PALETTE, bS as ManagerTab, bT as useNodeOutputStore, bU as config, bV as semver, bW as useStorage, bX as useFavicon, bY as useModelStore } from "./index-CTGitcrS.js";
import { useToast } from "primevue/usetoast";
import { useI18n } from "vue-i18n";
import Button from "primevue/button";
import Splitter from "primevue/splitter";
import SplitterPanel from "primevue/splitterpanel";
import Tab from "primevue/tab";
import TabList from "primevue/tablist";
import Tabs from "primevue/tabs";
import ButtonGroup from "primevue/buttongroup";
import { Button as Button$1, InputNumber, useToast as useToast$1 } from "primevue";
import Checkbox from "primevue/checkbox";
import Panel from "primevue/panel";
import SelectButton from "primevue/selectbutton";
import Dialog from "primevue/dialog";
import AutoComplete from "primevue/autocomplete";
import Chip from "primevue/chip";
import Tag from "primevue/tag";
import OverlayBadge from "primevue/overlaybadge";
import ContextMenu from "primevue/contextmenu";
import ScrollPanel from "primevue/scrollpanel";
import Popover from "primevue/popover";
import Menu from "primevue/menu";
import InputText from "primevue/inputtext";
import Chart from "primevue/chart";
import ColorPicker from "primevue/colorpicker";
import Select from "primevue/select";
import Galleria from "primevue/galleria";
import ImageCompare from "primevue/imagecompare";
import Textarea from "primevue/textarea";
import MultiSelect from "primevue/multiselect";
import Slider from "primevue/slider";
import ToggleSwitch from "primevue/toggleswitch";
import TreeSelect from "primevue/treeselect";
import Toast from "primevue/toast";
import SplitButton from "primevue/splitbutton";
import InputNumber$1 from "primevue/inputnumber";
import TieredMenu from "primevue/tieredmenu";
import Breadcrumb from "primevue/breadcrumb";
import { _ as _sfc_main$1B } from "./UserAvatar-C9bSkTC5.js";
import Divider from "primevue/divider";
import { u as useKeybindingService } from "./keybindingService-CqVnplbu.js";
import { u as useServerConfigStore } from "./serverConfigStore-D5-OKQJk.js";
import "@primevue/themes";
import "@primevue/themes/aura";
import "primevue/config";
import "primevue/confirmationservice";
import "primevue/toastservice";
import "primevue/tooltip";
import "primevue/blockui";
import "primevue/progressspinner";
import "primevue/message";
import "primevue/card";
import "primevue/listbox";
import "primevue/progressbar";
import "primevue/floatlabel";
import "primevue/tabpanels";
import "primevue/iconfield";
import "primevue/inputicon";
import "primevue/badge";
import "primevue/skeleton";
import "primevue/tree";
import "primevue/toolbar";
import "primevue/confirmpopup";
import "primevue/useconfirm";
import "primevue/confirmdialog";
import "primevue/tabpanel";
import "primevue/knob";
import "@primevue/forms";
import "@primevue/forms/resolvers/zod";
import "primevue/password";
import "primevue/dropdown";
import "primevue/tabmenu";
import "primevue/dataview";
import "primevue/column";
import "primevue/datatable";
import "primevue/avatar";
const _hoisted_1$1v = { class: "window-actions-spacer" };
const _sfc_main$1A = /* @__PURE__ */ defineComponent({
  __name: "MenuHamburger",
  setup(__props) {
    const workspaceState = useWorkspaceStore();
    const settingStore = useSettingStore();
    const exitFocusMode = /* @__PURE__ */ __name(() => {
      workspaceState.focusMode = false;
    }, "exitFocusMode");
    watchEffect(() => {
      if (settingStore.get("Comfy.UseNewMenu") !== "Disabled") {
        return;
      }
      if (workspaceState.focusMode) {
        app.ui.menuContainer.style.display = "none";
      } else {
        app.ui.menuContainer.style.display = "block";
      }
    });
    const menuSetting = computed(() => settingStore.get("Comfy.UseNewMenu"));
    const positionCSS = computed(
      () => (
        // 'Bottom' menuSetting shows the hamburger button in the bottom right corner
        // 'Disabled', 'Top' menuSetting shows the hamburger button in the top right corner
        menuSetting.value === "Bottom" ? { bottom: "0px", right: "0px" } : { top: "0px", right: "0px" }
      )
    );
    return (_ctx, _cache) => {
      const _directive_tooltip = resolveDirective("tooltip");
      return withDirectives((openBlock(), createElementBlock("div", {
        class: "comfy-menu-hamburger no-drag",
        style: normalizeStyle(positionCSS.value)
      }, [
        withDirectives(createVNode(unref(Button), {
          icon: "pi pi-bars",
          severity: "secondary",
          text: "",
          size: "large",
          "aria-label": _ctx.$t("menu.showMenu"),
          "aria-live": "assertive",
          onClick: exitFocusMode,
          onContextmenu: unref(showNativeSystemMenu)
        }, null, 8, ["aria-label", "onContextmenu"]), [
          [_directive_tooltip, { value: _ctx.$t("menu.showMenu"), showDelay: 300 }]
        ]),
        withDirectives(createElementVNode("div", _hoisted_1$1v, null, 512), [
          [vShow, menuSetting.value !== "Bottom"]
        ])
      ], 4)), [
        [vShow, unref(workspaceState).focusMode]
      ]);
    };
  }
});
const MenuHamburger = /* @__PURE__ */ _export_sfc(_sfc_main$1A, [["__scopeId", "data-v-ddec7ffc"]]);
const _sfc_main$1z = /* @__PURE__ */ defineComponent({
  __name: "UnloadWindowConfirmDialog",
  setup(__props) {
    const settingStore = useSettingStore();
    const workflowStore = useWorkflowStore();
    const handleBeforeUnload = /* @__PURE__ */ __name((event) => {
      if (settingStore.get("Comfy.Window.UnloadConfirmation") && workflowStore.modifiedWorkflows.length > 0) {
        event.preventDefault();
        return true;
      }
      return void 0;
    }, "handleBeforeUnload");
    onMounted(() => {
      window.addEventListener("beforeunload", handleBeforeUnload);
    });
    onBeforeUnmount(() => {
      window.removeEventListener("beforeunload", handleBeforeUnload);
    });
    return (_ctx, _cache) => {
      return openBlock(), createElementBlock("div");
    };
  }
});
const _sfc_main$1y = /* @__PURE__ */ defineComponent({
  __name: "LiteGraphCanvasSplitterOverlay",
  setup(__props) {
    const settingStore = useSettingStore();
    const sidebarLocation = computed(
      () => settingStore.get("Comfy.Sidebar.Location")
    );
    const unifiedWidth = computed(
      () => settingStore.get("Comfy.Sidebar.UnifiedWidth")
    );
    const sidebarPanelVisible = computed(
      () => useSidebarTabStore().activeSidebarTab !== null
    );
    const bottomPanelVisible = computed(
      () => useBottomPanelStore().bottomPanelVisible
    );
    const activeSidebarTabId = computed(
      () => useSidebarTabStore().activeSidebarTabId
    );
    const sidebarStateKey = computed(() => {
      return unifiedWidth.value ? "unified-sidebar" : activeSidebarTabId.value ?? "";
    });
    return (_ctx, _cache) => {
      return openBlock(), createBlock(unref(Splitter), {
        key: sidebarStateKey.value,
        class: "splitter-overlay-root splitter-overlay",
        "pt:gutter": sidebarPanelVisible.value ? "" : "hidden",
        "state-key": sidebarStateKey.value,
        "state-storage": "local"
      }, {
        default: withCtx(() => [
          sidebarLocation.value === "left" ? withDirectives((openBlock(), createBlock(unref(SplitterPanel), {
            key: 0,
            class: "side-bar-panel",
            "min-size": 10,
            size: 20
          }, {
            default: withCtx(() => [
              renderSlot(_ctx.$slots, "side-bar-panel", {}, void 0, true)
            ]),
            _: 3
          }, 512)), [
            [vShow, sidebarPanelVisible.value]
          ]) : createCommentVNode("", true),
          createVNode(unref(SplitterPanel), { size: 100 }, {
            default: withCtx(() => [
              createVNode(unref(Splitter), {
                class: "splitter-overlay max-w-full",
                layout: "vertical",
                "pt:gutter": bottomPanelVisible.value ? "" : "hidden",
                "state-key": "bottom-panel-splitter",
                "state-storage": "local"
              }, {
                default: withCtx(() => [
                  createVNode(unref(SplitterPanel), { class: "graph-canvas-panel relative" }, {
                    default: withCtx(() => [
                      renderSlot(_ctx.$slots, "graph-canvas-panel", {}, void 0, true)
                    ]),
                    _: 3
                  }),
                  withDirectives(createVNode(unref(SplitterPanel), { class: "bottom-panel" }, {
                    default: withCtx(() => [
                      renderSlot(_ctx.$slots, "bottom-panel", {}, void 0, true)
                    ]),
                    _: 3
                  }, 512), [
                    [vShow, bottomPanelVisible.value]
                  ])
                ]),
                _: 3
              }, 8, ["pt:gutter"])
            ]),
            _: 3
          }),
          sidebarLocation.value === "right" ? withDirectives((openBlock(), createBlock(unref(SplitterPanel), {
            key: 1,
            class: "side-bar-panel",
            "min-size": 10,
            size: 20
          }, {
            default: withCtx(() => [
              renderSlot(_ctx.$slots, "side-bar-panel", {}, void 0, true)
            ]),
            _: 3
          }, 512)), [
            [vShow, sidebarPanelVisible.value]
          ]) : createCommentVNode("", true)
        ]),
        _: 3
      }, 8, ["pt:gutter", "state-key"]);
    };
  }
});
const LiteGraphCanvasSplitterOverlay = /* @__PURE__ */ _export_sfc(_sfc_main$1y, [["__scopeId", "data-v-1e7f0b6b"]]);
const _sfc_main$1x = /* @__PURE__ */ defineComponent({
  __name: "ExtensionSlot",
  props: {
    extension: {}
  },
  setup(__props) {
    const props = __props;
    const mountCustomExtension = /* @__PURE__ */ __name((extension, el) => {
      extension.render(el);
    }, "mountCustomExtension");
    onBeforeUnmount(() => {
      if (props.extension.type === "custom" && props.extension.destroy) {
        props.extension.destroy();
      }
    });
    return (_ctx, _cache) => {
      return _ctx.extension.type === "vue" ? (openBlock(), createBlock(resolveDynamicComponent(_ctx.extension.component), { key: 0 })) : (openBlock(), createElementBlock("div", {
        key: 1,
        ref: /* @__PURE__ */ __name((el) => {
          if (el)
            mountCustomExtension(
              props.extension,
              el
            );
        }, "ref")
      }, null, 512));
    };
  }
});
const _hoisted_1$1u = { class: "flex flex-col h-full" };
const _hoisted_2$E = { class: "w-full flex justify-between" };
const _hoisted_3$r = { class: "tabs-container" };
const _hoisted_4$l = { class: "font-bold" };
const _hoisted_5$d = { class: "flex items-center gap-2" };
const _hoisted_6$b = { class: "grow h-0" };
const _sfc_main$1w = /* @__PURE__ */ defineComponent({
  __name: "BottomPanel",
  setup(__props) {
    const bottomPanelStore = useBottomPanelStore();
    const dialogService = useDialogService();
    const { t: t2 } = useI18n();
    const isShortcutsTabActive = computed(() => {
      const activeTabId = bottomPanelStore.activeBottomPanelTabId;
      return activeTabId === "shortcuts-essentials" || activeTabId === "shortcuts-view-controls";
    });
    const shouldCapitalizeTab = /* @__PURE__ */ __name((tabId) => {
      return tabId !== "shortcuts-essentials" && tabId !== "shortcuts-view-controls";
    }, "shouldCapitalizeTab");
    const getTabDisplayTitle = /* @__PURE__ */ __name((tab) => {
      const title = tab.titleKey ? t2(tab.titleKey) : tab.title || "";
      return shouldCapitalizeTab(tab.id) ? title.toUpperCase() : title;
    }, "getTabDisplayTitle");
    const openKeybindingSettings = /* @__PURE__ */ __name(async () => {
      dialogService.showSettingsDialog("keybinding");
    }, "openKeybindingSettings");
    const closeBottomPanel = /* @__PURE__ */ __name(() => {
      bottomPanelStore.activePanel = null;
    }, "closeBottomPanel");
    return (_ctx, _cache) => {
      return openBlock(), createElementBlock("div", _hoisted_1$1u, [
        (openBlock(), createBlock(unref(Tabs), {
          key: _ctx.$i18n.locale,
          value: unref(bottomPanelStore).activeBottomPanelTabId,
          "onUpdate:value": _cache[0] || (_cache[0] = ($event) => unref(bottomPanelStore).activeBottomPanelTabId = $event)
        }, {
          default: withCtx(() => [
            createVNode(unref(TabList), { "pt:tab-list": "border-none" }, {
              default: withCtx(() => [
                createElementVNode("div", _hoisted_2$E, [
                  createElementVNode("div", _hoisted_3$r, [
                    (openBlock(true), createElementBlock(Fragment, null, renderList(unref(bottomPanelStore).bottomPanelTabs, (tab) => {
                      return openBlock(), createBlock(unref(Tab), {
                        key: tab.id,
                        value: tab.id,
                        class: "p-3 border-none"
                      }, {
                        default: withCtx(() => [
                          createElementVNode("span", _hoisted_4$l, toDisplayString(getTabDisplayTitle(tab)), 1)
                        ]),
                        _: 2
                      }, 1032, ["value"]);
                    }), 128))
                  ]),
                  createElementVNode("div", _hoisted_5$d, [
                    isShortcutsTabActive.value ? (openBlock(), createBlock(unref(Button), {
                      key: 0,
                      label: _ctx.$t("shortcuts.manageShortcuts"),
                      icon: "pi pi-cog",
                      severity: "secondary",
                      size: "small",
                      text: "",
                      onClick: openKeybindingSettings
                    }, null, 8, ["label"])) : createCommentVNode("", true),
                    createVNode(unref(Button), {
                      class: "justify-self-end",
                      icon: "pi pi-times",
                      severity: "secondary",
                      size: "small",
                      text: "",
                      onClick: closeBottomPanel
                    })
                  ])
                ])
              ]),
              _: 1
            })
          ]),
          _: 1
        }, 8, ["value"])),
        createElementVNode("div", _hoisted_6$b, [
          unref(bottomPanelStore).bottomPanelVisible && unref(bottomPanelStore).activeBottomPanelTab ? (openBlock(), createBlock(_sfc_main$1x, {
            key: 0,
            extension: unref(bottomPanelStore).activeBottomPanelTab
          }, null, 8, ["extension"])) : createCommentVNode("", true)
        ])
      ]);
    };
  }
});
function useAbsolutePosition(options = {}) {
  const { useTransform = false } = options;
  const canvasStore = useCanvasStore();
  const lgCanvas = canvasStore.getCanvas();
  const { canvasPosToClientPos, update: updateCanvasPosition } = useCanvasPositionConversion(lgCanvas.canvas, lgCanvas);
  const settingStore = useSettingStore();
  watch(
    [
      () => settingStore.get("Comfy.Sidebar.Location"),
      () => settingStore.get("Comfy.Sidebar.Size"),
      () => settingStore.get("Comfy.UseNewMenu")
    ],
    () => updateCanvasPosition(),
    { flush: "post" }
  );
  const style = ref({});
  const computeStyle = /* @__PURE__ */ __name((position) => {
    const { pos, size, scale = lgCanvas.ds.scale } = position;
    const [left, top] = canvasPosToClientPos(pos);
    const [width, height] = size;
    return useTransform ? {
      position: "fixed",
      transformOrigin: "0 0",
      transform: `scale(${scale})`,
      left: `${left}px`,
      top: `${top}px`,
      width: `${width}px`,
      height: `${height}px`
    } : {
      position: "fixed",
      left: `${left}px`,
      top: `${top}px`,
      width: `${width * scale}px`,
      height: `${height * scale}px`
    };
  }, "computeStyle");
  const updatePosition = /* @__PURE__ */ __name((config2) => {
    style.value = computeStyle(config2);
  }, "updatePosition");
  return {
    style,
    updatePosition
  };
}
__name(useAbsolutePosition, "useAbsolutePosition");
function intersect(a, b) {
  const x1 = Math.max(a.x, b.x);
  const y1 = Math.max(a.y, b.y);
  const x2 = Math.min(a.x + a.width, b.x + b.width);
  const y2 = Math.min(a.y + a.height, b.y + b.height);
  if (x1 >= x2 || y1 >= y2) {
    return null;
  }
  return [x1, y1, x2 - x1, y2 - y1];
}
__name(intersect, "intersect");
const useDomClipping = /* @__PURE__ */ __name((options = {}) => {
  const style = ref({});
  const { margin = 4 } = options;
  const calculateClipPath = /* @__PURE__ */ __name((elementRect, canvasRect, isSelected, selectedArea) => {
    if (!isSelected && selectedArea) {
      const { scale, offset } = selectedArea;
      const intersection = intersect(
        {
          x: elementRect.left - canvasRect.left,
          y: elementRect.top - canvasRect.top,
          width: elementRect.width,
          height: elementRect.height
        },
        {
          x: (selectedArea.x + offset[0] - margin) * scale,
          y: (selectedArea.y + offset[1] - margin) * scale,
          width: (selectedArea.width + 2 * margin) * scale,
          height: (selectedArea.height + 2 * margin) * scale
        }
      );
      if (!intersection) {
        return "";
      }
      const clipX = (intersection[0] - elementRect.left + canvasRect.left) / scale + "px";
      const clipY = (intersection[1] - elementRect.top + canvasRect.top) / scale + "px";
      const clipWidth = intersection[2] / scale + "px";
      const clipHeight = intersection[3] / scale + "px";
      return `polygon(0% 0%, 0% 100%, ${clipX} 100%, ${clipX} ${clipY}, calc(${clipX} + ${clipWidth}) ${clipY}, calc(${clipX} + ${clipWidth}) calc(${clipY} + ${clipHeight}), ${clipX} calc(${clipY} + ${clipHeight}), ${clipX} 100%, 100% 100%, 100% 0%)`;
    }
    return "";
  }, "calculateClipPath");
  const updateClipPath = /* @__PURE__ */ __name((element, canvasElement, isSelected, selectedArea) => {
    const elementRect = element.getBoundingClientRect();
    const canvasRect = canvasElement.getBoundingClientRect();
    const clipPath = calculateClipPath(
      elementRect,
      canvasRect,
      isSelected,
      selectedArea
    );
    style.value = {
      clipPath: clipPath || "none",
      willChange: "clip-path"
    };
  }, "updateClipPath");
  return {
    style,
    updateClipPath
  };
}, "useDomClipping");
const _hoisted_1$1t = ["title"];
const _sfc_main$1v = /* @__PURE__ */ defineComponent({
  __name: "DomWidget",
  props: {
    widgetState: {}
  },
  emits: ["update:widgetValue"],
  setup(__props, { emit: __emit }) {
    const widget = __props.widgetState.widget;
    const emit = __emit;
    const widgetElement = ref();
    const style = ref({});
    const { style: positionStyle, updatePosition } = useAbsolutePosition({
      useTransform: true
    });
    const { style: clippingStyle, updateClipPath } = useDomClipping();
    const canvasStore = useCanvasStore();
    const settingStore = useSettingStore();
    const enableDomClipping = computed(
      () => settingStore.get("Comfy.DOMClippingEnabled")
    );
    const updateDomClipping = /* @__PURE__ */ __name(() => {
      const lgCanvas = canvasStore.canvas;
      if (!lgCanvas || !widgetElement.value) return;
      const selectedNode = Object.values(lgCanvas.selected_nodes ?? {})[0];
      if (!selectedNode) {
        updateClipPath(widgetElement.value, lgCanvas.canvas, false, void 0);
        return;
      }
      const isSelected = selectedNode === widget.node;
      const renderArea = selectedNode?.renderArea;
      const offset = lgCanvas.ds.offset;
      const scale = lgCanvas.ds.scale;
      const selectedAreaConfig = renderArea ? {
        x: renderArea[0],
        y: renderArea[1],
        width: renderArea[2],
        height: renderArea[3],
        scale,
        offset: [offset[0], offset[1]]
      } : void 0;
      updateClipPath(
        widgetElement.value,
        lgCanvas.canvas,
        isSelected,
        selectedAreaConfig
      );
    }, "updateDomClipping");
    const { left, top } = useElementBounding(canvasStore.getCanvas().canvas);
    watch(
      [() => __props.widgetState, left, top],
      ([widgetState, _, __]) => {
        updatePosition(widgetState);
        if (enableDomClipping.value) {
          updateDomClipping();
        }
        style.value = {
          ...positionStyle.value,
          ...enableDomClipping.value ? clippingStyle.value : {},
          zIndex: widgetState.zIndex,
          pointerEvents: widgetState.readonly || widget.computedDisabled ? "none" : "auto",
          opacity: widget.computedDisabled ? 0.5 : 1
        };
      },
      { deep: true }
    );
    watch(
      () => __props.widgetState.visible,
      (newVisible, oldVisible) => {
        if (!newVisible && oldVisible) {
          widget.options.onHide?.(widget);
        }
      }
    );
    const setupDOMEventListeners = /* @__PURE__ */ __name(() => {
      if (!isDOMWidget(widget) || !__props.widgetState.visible) return;
      if (widget.element.blur) {
        useEventListener(document, "mousedown", (event) => {
          if (!widget.element.contains(event.target)) {
            widget.element.blur();
          }
        });
      }
      for (const evt of widget.options.selectOn ?? ["focus", "click"]) {
        useEventListener(widget.element, evt, () => {
          const lgCanvas = canvasStore.canvas;
          lgCanvas?.selectNode(widget.node);
          lgCanvas?.bringToFront(widget.node);
        });
      }
    }, "setupDOMEventListeners");
    watch(
      () => __props.widgetState.visible,
      (visible) => {
        if (visible) {
          setupDOMEventListeners();
        }
      },
      { immediate: true }
    );
    const inputSpec = widget.node.constructor.nodeData;
    const tooltip = inputSpec?.inputs?.[widget.name]?.tooltip;
    const mountElementIfVisible = /* @__PURE__ */ __name(() => {
      if (__props.widgetState.visible && isDOMWidget(widget) && widgetElement.value) {
        if (!widgetElement.value.contains(widget.element)) {
          widgetElement.value.appendChild(widget.element);
        }
      }
    }, "mountElementIfVisible");
    onMounted(() => {
      nextTick(() => {
        mountElementIfVisible();
      }).catch((error) => {
        console.error("Error mounting DOM widget element:", error);
      });
    });
    watch(
      () => __props.widgetState.visible,
      () => {
        mountElementIfVisible();
      }
    );
    return (_ctx, _cache) => {
      return withDirectives((openBlock(), createElementBlock("div", {
        ref_key: "widgetElement",
        ref: widgetElement,
        class: "dom-widget",
        title: unref(tooltip),
        style: normalizeStyle(style.value)
      }, [
        unref(isComponentWidget)(unref(widget)) ? (openBlock(), createBlock(resolveDynamicComponent(unref(widget).component), mergeProps({
          key: 0,
          "model-value": unref(widget).value,
          widget: unref(widget)
        }, unref(widget).props, {
          "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => emit("update:widgetValue", $event))
        }), null, 16, ["model-value", "widget"])) : createCommentVNode("", true)
      ], 12, _hoisted_1$1t)), [
        [vShow, _ctx.widgetState.visible]
      ]);
    };
  }
});
const DomWidget = /* @__PURE__ */ _export_sfc(_sfc_main$1v, [["__scopeId", "data-v-031a2012"]]);
const _hoisted_1$1s = { class: "isolate" };
const _sfc_main$1u = /* @__PURE__ */ defineComponent({
  __name: "DomWidgets",
  setup(__props) {
    const domWidgetStore = useDomWidgetStore();
    const widgetStates = computed(() => [...domWidgetStore.widgetStates.values()]);
    const updateWidgets = /* @__PURE__ */ __name(() => {
      const lgCanvas = canvasStore.canvas;
      if (!lgCanvas) return;
      const lowQuality = lgCanvas.low_quality;
      const currentGraph = lgCanvas.graph;
      for (const widgetState of widgetStates.value) {
        const widget = widgetState.widget;
        if (!widget.isVisible()) {
          widgetState.visible = false;
          continue;
        }
        const node = widget.node;
        const isInCorrectGraph = currentGraph?.nodes.includes(node);
        widgetState.visible = !!isInCorrectGraph && lgCanvas.isNodeVisible(node) && !(widget.options.hideOnZoom && lowQuality);
        if (widgetState.visible && node) {
          const margin = widget.margin;
          widgetState.pos = [node.pos[0] + margin, node.pos[1] + margin + widget.y];
          widgetState.size = [
            (widget.width ?? node.width) - margin * 2,
            (widget.computedHeight ?? 50) - margin * 2
          ];
          widgetState.zIndex = lgCanvas.graph?.nodes.indexOf(node) ?? -1;
          widgetState.readonly = lgCanvas.read_only;
        }
      }
    }, "updateWidgets");
    const canvasStore = useCanvasStore();
    whenever(
      () => canvasStore.canvas,
      (canvas) => canvas.onDrawForeground = useChainCallback(
        canvas.onDrawForeground,
        updateWidgets
      ),
      { immediate: true }
    );
    return (_ctx, _cache) => {
      return openBlock(), createElementBlock("div", _hoisted_1$1s, [
        (openBlock(true), createElementBlock(Fragment, null, renderList(widgetStates.value, (widgetState) => {
          return openBlock(), createBlock(DomWidget, {
            key: widgetState.widget.id,
            "widget-state": widgetState,
            "onUpdate:widgetValue": /* @__PURE__ */ __name(($event) => widgetState.widget.value = $event, "onUpdate:widgetValue")
          }, null, 8, ["widget-state", "onUpdate:widgetValue"]);
        }), 128))
      ]);
    };
  }
});
const _hoisted_1$1r = {
  viewBox: "0 0 24 24",
  width: "1.2em",
  height: "1.2em"
};
function render$z(_ctx, _cache) {
  return openBlock(), createElementBlock("svg", _hoisted_1$1r, _cache[0] || (_cache[0] = [
    createElementVNode("g", {
      fill: "none",
      stroke: "currentColor",
      "stroke-linecap": "round",
      "stroke-linejoin": "round",
      "stroke-width": "2"
    }, [
      createElementVNode("circle", {
        cx: "6",
        cy: "19",
        r: "3"
      }),
      createElementVNode("path", { d: "M9 19h8.5c.4 0 .9-.1 1.3-.2M5.2 5.2A3.5 3.53 0 0 0 6.5 12H12M2 2l20 20m-1-6.7a3.5 3.5 0 0 0-3.3-3.3M15 5h-4.3" }),
      createElementVNode("circle", {
        cx: "18",
        cy: "5",
        r: "3"
      })
    ], -1)
  ]));
}
__name(render$z, "render$z");
const __unplugin_components_5$1 = markRaw({ name: "lucide-route-off", render: render$z });
const _hoisted_1$1q = {
  viewBox: "0 0 24 24",
  width: "1.2em",
  height: "1.2em"
};
function render$y(_ctx, _cache) {
  return openBlock(), createElementBlock("svg", _hoisted_1$1q, _cache[0] || (_cache[0] = [
    createElementVNode("path", {
      fill: "none",
      stroke: "currentColor",
      "stroke-linecap": "round",
      "stroke-linejoin": "round",
      "stroke-width": "2",
      d: "M15 14c.2-1 .7-1.7 1.5-2.5c1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5c.7.7 1.3 1.5 1.5 2.5m0 4h6m-5 4h4"
    }, null, -1)
  ]));
}
__name(render$y, "render$y");
const __unplugin_components_4$2 = markRaw({ name: "lucide-lightbulb", render: render$y });
const _hoisted_1$1p = {
  viewBox: "0 0 24 24",
  width: "1.2em",
  height: "1.2em"
};
function render$x(_ctx, _cache) {
  return openBlock(), createElementBlock("svg", _hoisted_1$1p, _cache[0] || (_cache[0] = [
    createElementVNode("path", {
      fill: "none",
      stroke: "currentColor",
      "stroke-linecap": "round",
      "stroke-linejoin": "round",
      "stroke-width": "2",
      d: "m6 9l6 6l6-6"
    }, null, -1)
  ]));
}
__name(render$x, "render$x");
const __unplugin_components_0$c = markRaw({ name: "lucide-chevron-down", render: render$x });
const _hoisted_1$1o = {
  viewBox: "0 0 24 24",
  width: "1.2em",
  height: "1.2em"
};
function render$w(_ctx, _cache) {
  return openBlock(), createElementBlock("svg", _hoisted_1$1o, _cache[0] || (_cache[0] = [
    createElementVNode("g", {
      fill: "none",
      stroke: "currentColor",
      "stroke-linecap": "round",
      "stroke-linejoin": "round",
      "stroke-width": "2"
    }, [
      createElementVNode("circle", {
        cx: "12",
        cy: "12",
        r: "3"
      }),
      createElementVNode("path", { d: "M3 7V5a2 2 0 0 1 2-2h2m10 0h2a2 2 0 0 1 2 2v2m0 10v2a2 2 0 0 1-2 2h-2M7 21H5a2 2 0 0 1-2-2v-2" })
    ], -1)
  ]));
}
__name(render$w, "render$w");
const __unplugin_components_2$4 = markRaw({ name: "lucide-focus", render: render$w });
const _hoisted_1$1n = {
  viewBox: "0 0 24 24",
  width: "1.2em",
  height: "1.2em"
};
function render$v(_ctx, _cache) {
  return openBlock(), createElementBlock("svg", _hoisted_1$1n, _cache[0] || (_cache[0] = [
    createElementVNode("g", {
      fill: "none",
      stroke: "currentColor",
      "stroke-linecap": "round",
      "stroke-linejoin": "round",
      "stroke-width": "2"
    }, [
      createElementVNode("path", { d: "M18 11V6a2 2 0 0 0-2-2a2 2 0 0 0-2 2m0 4V4a2 2 0 0 0-2-2a2 2 0 0 0-2 2v2m0 4.5V6a2 2 0 0 0-2-2a2 2 0 0 0-2 2v8" }),
      createElementVNode("path", { d: "M18 8a2 2 0 1 1 4 0v6a8 8 0 0 1-8 8h-2c-2.8 0-4.5-.86-5.99-2.34l-3.6-3.6a2 2 0 0 1 2.83-2.82L7 15" })
    ], -1)
  ]));
}
__name(render$v, "render$v");
const __unplugin_components_1$7 = markRaw({ name: "lucide-hand", render: render$v });
const _hoisted_1$1m = {
  viewBox: "0 0 24 24",
  width: "1.2em",
  height: "1.2em"
};
function render$u(_ctx, _cache) {
  return openBlock(), createElementBlock("svg", _hoisted_1$1m, _cache[0] || (_cache[0] = [
    createElementVNode("path", {
      fill: "none",
      stroke: "currentColor",
      "stroke-linecap": "round",
      "stroke-linejoin": "round",
      "stroke-width": "2",
      d: "M4.037 4.688a.495.495 0 0 1 .651-.651l16 6.5a.5.5 0 0 1-.063.947l-6.124 1.58a2 2 0 0 0-1.438 1.435l-1.579 6.126a.5.5 0 0 1-.947.063z"
    }, null, -1)
  ]));
}
__name(render$u, "render$u");
const __unplugin_components_0$b = markRaw({ name: "lucide-mouse-pointer2", render: render$u });
function useZoomControls() {
  const isModalVisible = ref(false);
  const showModal = /* @__PURE__ */ __name(() => {
    isModalVisible.value = true;
  }, "showModal");
  const hideModal = /* @__PURE__ */ __name(() => {
    isModalVisible.value = false;
  }, "hideModal");
  const toggleModal = /* @__PURE__ */ __name(() => {
    isModalVisible.value = !isModalVisible.value;
  }, "toggleModal");
  const hasActivePopup = computed(() => isModalVisible.value);
  return {
    isModalVisible,
    showModal,
    hideModal,
    toggleModal,
    hasActivePopup
  };
}
__name(useZoomControls, "useZoomControls");
function useMinimapGraph(graph, onGraphChanged) {
  const nodeStatesCache = /* @__PURE__ */ new Map();
  const linksCache = ref("");
  const lastNodeCount = ref(0);
  const updateFlags = ref({
    bounds: false,
    nodes: false,
    connections: false,
    viewport: false
  });
  const originalCallbacksMap = /* @__PURE__ */ new Map();
  const handleGraphChangedThrottled = useThrottleFn(() => {
    onGraphChanged();
  }, 500);
  const setupEventListeners = /* @__PURE__ */ __name(() => {
    const g = graph.value;
    if (!g) return;
    if (originalCallbacksMap.has(g.id)) {
      return;
    }
    const originalCallbacks = {
      onNodeAdded: g.onNodeAdded,
      onNodeRemoved: g.onNodeRemoved,
      onConnectionChange: g.onConnectionChange
    };
    originalCallbacksMap.set(g.id, originalCallbacks);
    g.onNodeAdded = function(node) {
      originalCallbacks.onNodeAdded?.call(this, node);
      void handleGraphChangedThrottled();
    };
    g.onNodeRemoved = function(node) {
      originalCallbacks.onNodeRemoved?.call(this, node);
      nodeStatesCache.delete(node.id);
      void handleGraphChangedThrottled();
    };
    g.onConnectionChange = function(node) {
      originalCallbacks.onConnectionChange?.call(this, node);
      void handleGraphChangedThrottled();
    };
  }, "setupEventListeners");
  const cleanupEventListeners = /* @__PURE__ */ __name((oldGraph) => {
    const g = oldGraph || graph.value;
    if (!g) return;
    const originalCallbacks = originalCallbacksMap.get(g.id);
    if (!originalCallbacks) {
      console.error(
        "Attempted to cleanup event listeners for graph that was never set up"
      );
      return;
    }
    g.onNodeAdded = originalCallbacks.onNodeAdded;
    g.onNodeRemoved = originalCallbacks.onNodeRemoved;
    g.onConnectionChange = originalCallbacks.onConnectionChange;
    originalCallbacksMap.delete(g.id);
  }, "cleanupEventListeners");
  const checkForChangesInternal = /* @__PURE__ */ __name(() => {
    const g = graph.value;
    if (!g) return false;
    let structureChanged = false;
    let positionChanged = false;
    let connectionChanged = false;
    if (g._nodes.length !== lastNodeCount.value) {
      structureChanged = true;
      lastNodeCount.value = g._nodes.length;
    }
    for (const node of g._nodes) {
      const key = node.id;
      const currentState = `${node.pos[0]},${node.pos[1]},${node.size[0]},${node.size[1]}`;
      if (nodeStatesCache.get(key) !== currentState) {
        positionChanged = true;
        nodeStatesCache.set(key, currentState);
      }
    }
    const currentLinks = JSON.stringify(g.links || {});
    if (currentLinks !== linksCache.value) {
      connectionChanged = true;
      linksCache.value = currentLinks;
    }
    const currentNodeIds = new Set(g._nodes.map((n) => n.id));
    for (const [nodeId] of nodeStatesCache) {
      if (!currentNodeIds.has(nodeId)) {
        nodeStatesCache.delete(nodeId);
        structureChanged = true;
      }
    }
    if (structureChanged || positionChanged) {
      updateFlags.value.bounds = true;
      updateFlags.value.nodes = true;
    }
    if (connectionChanged) {
      updateFlags.value.connections = true;
    }
    return structureChanged || positionChanged || connectionChanged;
  }, "checkForChangesInternal");
  const init = /* @__PURE__ */ __name(() => {
    setupEventListeners();
    api.addEventListener("graphChanged", handleGraphChangedThrottled);
  }, "init");
  const destroy = /* @__PURE__ */ __name(() => {
    cleanupEventListeners();
    api.removeEventListener("graphChanged", handleGraphChangedThrottled);
    nodeStatesCache.clear();
  }, "destroy");
  const clearCache = /* @__PURE__ */ __name(() => {
    nodeStatesCache.clear();
    linksCache.value = "";
    lastNodeCount.value = 0;
  }, "clearCache");
  return {
    updateFlags,
    setupEventListeners,
    cleanupEventListeners,
    checkForChanges: checkForChangesInternal,
    init,
    destroy,
    clearCache
  };
}
__name(useMinimapGraph, "useMinimapGraph");
function useMinimapInteraction(containerRef, bounds, scale, width, height, centerViewOn, canvas) {
  const isDragging = ref(false);
  const containerRect = ref({
    left: 0,
    top: 0,
    width,
    height
  });
  const updateContainerRect = /* @__PURE__ */ __name(() => {
    if (!containerRef.value) return;
    const rect = containerRef.value.getBoundingClientRect();
    containerRect.value = {
      left: rect.left,
      top: rect.top,
      width: rect.width,
      height: rect.height
    };
  }, "updateContainerRect");
  const handlePointerDown = /* @__PURE__ */ __name((e) => {
    isDragging.value = true;
    updateContainerRect();
    handlePointerMove(e);
  }, "handlePointerDown");
  const handlePointerMove = /* @__PURE__ */ __name((e) => {
    if (!isDragging.value || !canvas.value) return;
    const x = e.clientX - containerRect.value.left;
    const y = e.clientY - containerRect.value.top;
    const offsetX = (width - bounds.value.width * scale.value) / 2;
    const offsetY = (height - bounds.value.height * scale.value) / 2;
    const worldX = (x - offsetX) / scale.value + bounds.value.minX;
    const worldY = (y - offsetY) / scale.value + bounds.value.minY;
    centerViewOn(worldX, worldY);
  }, "handlePointerMove");
  const handlePointerUp = /* @__PURE__ */ __name(() => {
    isDragging.value = false;
  }, "handlePointerUp");
  const handleWheel = /* @__PURE__ */ __name((e) => {
    e.preventDefault();
    const c = canvas.value;
    if (!c) return;
    if (containerRect.value.left === 0 && containerRect.value.top === 0 && containerRef.value) {
      updateContainerRect();
    }
    const ds = c.ds;
    const delta = e.deltaY > 0 ? 0.9 : 1.1;
    const newScale = ds.scale * delta;
    const MIN_SCALE = 0.1;
    const MAX_SCALE = 10;
    if (newScale < MIN_SCALE || newScale > MAX_SCALE) return;
    const x = e.clientX - containerRect.value.left;
    const y = e.clientY - containerRect.value.top;
    const offsetX = (width - bounds.value.width * scale.value) / 2;
    const offsetY = (height - bounds.value.height * scale.value) / 2;
    const worldX = (x - offsetX) / scale.value + bounds.value.minX;
    const worldY = (y - offsetY) / scale.value + bounds.value.minY;
    ds.scale = newScale;
    centerViewOn(worldX, worldY);
  }, "handleWheel");
  return {
    isDragging,
    containerRect,
    updateContainerRect,
    handlePointerDown,
    handlePointerMove,
    handlePointerUp,
    handleWheel
  };
}
__name(useMinimapInteraction, "useMinimapInteraction");
function useMinimapRenderer(canvasRef, graph, bounds, scale, updateFlags, settings, width, height) {
  const needsFullRedraw = ref(true);
  const needsBoundsUpdate = ref(true);
  const renderMinimap = /* @__PURE__ */ __name(() => {
    const g = graph.value;
    if (!canvasRef.value || !g) return;
    const ctx = canvasRef.value.getContext("2d");
    if (!ctx) return;
    if (!g._nodes || g._nodes.length === 0) {
      ctx.clearRect(0, 0, width, height);
      return;
    }
    const needsRedraw = needsFullRedraw.value || updateFlags.value.nodes || updateFlags.value.connections;
    if (needsRedraw) {
      renderMinimapToCanvas(canvasRef.value, g, {
        bounds: bounds.value,
        scale: scale.value,
        settings: {
          nodeColors: settings.nodeColors.value,
          showLinks: settings.showLinks.value,
          showGroups: settings.showGroups.value,
          renderBypass: settings.renderBypass.value,
          renderError: settings.renderError.value
        },
        width,
        height
      });
      needsFullRedraw.value = false;
      updateFlags.value.nodes = false;
      updateFlags.value.connections = false;
    }
  }, "renderMinimap");
  const updateMinimap = /* @__PURE__ */ __name((updateBounds, updateViewport) => {
    if (needsBoundsUpdate.value || updateFlags.value.bounds) {
      updateBounds();
      needsBoundsUpdate.value = false;
      updateFlags.value.bounds = false;
      needsFullRedraw.value = true;
      updateFlags.value.viewport = true;
    }
    if (needsFullRedraw.value || updateFlags.value.nodes || updateFlags.value.connections) {
      renderMinimap();
    }
    if (updateFlags.value.viewport) {
      updateViewport();
      updateFlags.value.viewport = false;
    }
  }, "updateMinimap");
  const forceFullRedraw = /* @__PURE__ */ __name(() => {
    needsFullRedraw.value = true;
    updateFlags.value.bounds = true;
    updateFlags.value.nodes = true;
    updateFlags.value.connections = true;
    updateFlags.value.viewport = true;
  }, "forceFullRedraw");
  return {
    needsFullRedraw,
    needsBoundsUpdate,
    renderMinimap,
    updateMinimap,
    forceFullRedraw
  };
}
__name(useMinimapRenderer, "useMinimapRenderer");
function useMinimapSettings() {
  const settingStore = useSettingStore();
  const colorPaletteStore = useColorPaletteStore();
  const nodeColors = computed(
    () => settingStore.get("Comfy.Minimap.NodeColors")
  );
  const showLinks = computed(() => settingStore.get("Comfy.Minimap.ShowLinks"));
  const showGroups = computed(
    () => settingStore.get("Comfy.Minimap.ShowGroups")
  );
  const renderBypass = computed(
    () => settingStore.get("Comfy.Minimap.RenderBypassState")
  );
  const renderError = computed(
    () => settingStore.get("Comfy.Minimap.RenderErrorState")
  );
  const width = 250;
  const height = 200;
  const isLightTheme = computed(
    () => colorPaletteStore.completedActivePalette.light_theme
  );
  const containerStyles = computed(() => ({
    width: `${width}px`,
    height: `${height}px`,
    backgroundColor: isLightTheme.value ? "#FAF9F5" : "#15161C",
    border: `1px solid ${isLightTheme.value ? "#ccc" : "#333"}`,
    borderRadius: "8px"
  }));
  const panelStyles = computed(() => ({
    width: `210px`,
    height: `${height}px`,
    backgroundColor: isLightTheme.value ? "#FAF9F5" : "#15161C",
    border: `1px solid ${isLightTheme.value ? "#ccc" : "#333"}`,
    borderRadius: "8px"
  }));
  return {
    nodeColors,
    showLinks,
    showGroups,
    renderBypass,
    renderError,
    containerStyles,
    panelStyles,
    isLightTheme
  };
}
__name(useMinimapSettings, "useMinimapSettings");
function useCanvasTransformSync$1(syncFn, options = {}) {
  const { onStart, onStop, autoStart = true } = options;
  const { getCanvas } = useCanvasStore();
  const isActive = ref(false);
  let rafId2 = null;
  let lastTransform = {
    scale: 0,
    offsetX: 0,
    offsetY: 0
  };
  const hasTransformChanged = /* @__PURE__ */ __name((canvas) => {
    const ds = canvas.ds;
    return ds.scale !== lastTransform.scale || ds.offset[0] !== lastTransform.offsetX || ds.offset[1] !== lastTransform.offsetY;
  }, "hasTransformChanged");
  const sync = /* @__PURE__ */ __name(() => {
    if (!isActive.value) return;
    const canvas = getCanvas();
    if (!canvas) return;
    try {
      if (hasTransformChanged(canvas)) {
        lastTransform = {
          scale: canvas.ds.scale,
          offsetX: canvas.ds.offset[0],
          offsetY: canvas.ds.offset[1]
        };
        syncFn(canvas);
      }
    } catch (error) {
      console.error("Canvas transform sync error:", error);
    }
    rafId2 = requestAnimationFrame(sync);
  }, "sync");
  const startSync = /* @__PURE__ */ __name(() => {
    if (isActive.value) return;
    isActive.value = true;
    onStart?.();
    lastTransform = { scale: 0, offsetX: 0, offsetY: 0 };
    sync();
  }, "startSync");
  const stopSync = /* @__PURE__ */ __name(() => {
    isActive.value = false;
    if (rafId2 !== null) {
      cancelAnimationFrame(rafId2);
      rafId2 = null;
    }
    onStop?.();
  }, "stopSync");
  onUnmounted(stopSync);
  if (autoStart) {
    startSync();
  }
  return {
    isActive,
    startSync,
    stopSync
  };
}
__name(useCanvasTransformSync$1, "useCanvasTransformSync$1");
function useMinimapViewport(canvas, graph, width, height) {
  const bounds = ref({
    minX: 0,
    minY: 0,
    maxX: 0,
    maxY: 0,
    width: 0,
    height: 0
  });
  const scale = ref(1);
  const viewportTransform = ref({
    x: 0,
    y: 0,
    width: 0,
    height: 0
  });
  const canvasDimensions = ref({
    width: 0,
    height: 0
  });
  const updateCanvasDimensions = /* @__PURE__ */ __name(() => {
    const c = canvas.value;
    if (!c) return;
    const canvasEl = c.canvas;
    const dpr = window.devicePixelRatio || 1;
    canvasDimensions.value = {
      width: canvasEl.clientWidth || canvasEl.width / dpr,
      height: canvasEl.clientHeight || canvasEl.height / dpr
    };
  }, "updateCanvasDimensions");
  const calculateGraphBounds = /* @__PURE__ */ __name(() => {
    const g = graph.value;
    if (!g || !g._nodes || g._nodes.length === 0) {
      return { minX: 0, minY: 0, maxX: 100, maxY: 100, width: 100, height: 100 };
    }
    const bounds2 = calculateNodeBounds(g._nodes);
    if (!bounds2) {
      return { minX: 0, minY: 0, maxX: 100, maxY: 100, width: 100, height: 100 };
    }
    return enforceMinimumBounds(bounds2);
  }, "calculateGraphBounds");
  const calculateScale = /* @__PURE__ */ __name(() => {
    return calculateMinimapScale(bounds.value, width, height);
  }, "calculateScale");
  const updateViewport = /* @__PURE__ */ __name(() => {
    const c = canvas.value;
    if (!c) return;
    if (canvasDimensions.value.width === 0 || canvasDimensions.value.height === 0) {
      updateCanvasDimensions();
    }
    const ds = c.ds;
    const viewportWidth = canvasDimensions.value.width / ds.scale;
    const viewportHeight = canvasDimensions.value.height / ds.scale;
    const worldX = -ds.offset[0];
    const worldY = -ds.offset[1];
    const centerOffsetX = (width - bounds.value.width * scale.value) / 2;
    const centerOffsetY = (height - bounds.value.height * scale.value) / 2;
    viewportTransform.value = {
      x: (worldX - bounds.value.minX) * scale.value + centerOffsetX,
      y: (worldY - bounds.value.minY) * scale.value + centerOffsetY,
      width: viewportWidth * scale.value,
      height: viewportHeight * scale.value
    };
  }, "updateViewport");
  const updateBounds = /* @__PURE__ */ __name(() => {
    bounds.value = calculateGraphBounds();
    scale.value = calculateScale();
  }, "updateBounds");
  const centerViewOn = /* @__PURE__ */ __name((worldX, worldY) => {
    const c = canvas.value;
    if (!c) return;
    if (canvasDimensions.value.width === 0 || canvasDimensions.value.height === 0) {
      updateCanvasDimensions();
    }
    const ds = c.ds;
    const viewportWidth = canvasDimensions.value.width / ds.scale;
    const viewportHeight = canvasDimensions.value.height / ds.scale;
    ds.offset[0] = -(worldX - viewportWidth / 2);
    ds.offset[1] = -(worldY - viewportHeight / 2);
    c.setDirty(true, true);
  }, "centerViewOn");
  const { startSync: startViewportSync, stopSync: stopViewportSync } = useCanvasTransformSync$1(updateViewport, { autoStart: false });
  return {
    bounds: computed(() => bounds.value),
    scale: computed(() => scale.value),
    viewportTransform: computed(() => viewportTransform.value),
    canvasDimensions: computed(() => canvasDimensions.value),
    updateCanvasDimensions,
    updateViewport,
    updateBounds,
    centerViewOn,
    startViewportSync,
    stopViewportSync
  };
}
__name(useMinimapViewport, "useMinimapViewport");
function useMinimap() {
  const canvasStore = useCanvasStore();
  const workflowStore = useWorkflowStore();
  const settingStore = useSettingStore();
  const containerRef = ref();
  const canvasRef = ref();
  const minimapRef = ref(null);
  const visible = ref(true);
  const initialized = ref(false);
  const width = 250;
  const height = 200;
  const canvas = computed(() => canvasStore.canvas);
  const graph = computed(() => {
    const activeSubgraph = workflowStore.activeSubgraph;
    return activeSubgraph || canvas.value?.graph;
  });
  const settings = useMinimapSettings();
  const {
    nodeColors,
    showLinks,
    showGroups,
    renderBypass,
    renderError,
    containerStyles,
    panelStyles
  } = settings;
  const updateOption = /* @__PURE__ */ __name(async (key, value) => {
    await settingStore.set(key, value);
    renderer.forceFullRedraw();
    renderer.updateMinimap(viewport.updateBounds, viewport.updateViewport);
  }, "updateOption");
  const viewport = useMinimapViewport(canvas, graph, width, height);
  const interaction = useMinimapInteraction(
    containerRef,
    viewport.bounds,
    viewport.scale,
    width,
    height,
    viewport.centerViewOn,
    canvas
  );
  const graphManager = useMinimapGraph(graph, () => {
    renderer.forceFullRedraw();
    renderer.updateMinimap(viewport.updateBounds, viewport.updateViewport);
  });
  const renderer = useMinimapRenderer(
    canvasRef,
    graph,
    viewport.bounds,
    viewport.scale,
    graphManager.updateFlags,
    settings,
    width,
    height
  );
  const { pause: pauseChangeDetection, resume: resumeChangeDetection } = useRafFn(
    async () => {
      if (visible.value) {
        const hasChanges = await graphManager.checkForChanges();
        if (hasChanges) {
          renderer.updateMinimap(
            viewport.updateBounds,
            viewport.updateViewport
          );
        }
      }
    },
    { immediate: false }
  );
  const init = /* @__PURE__ */ __name(async () => {
    if (initialized.value) return;
    visible.value = settingStore.get("Comfy.Minimap.Visible");
    if (canvas.value && graph.value) {
      graphManager.init();
      if (containerRef.value) {
        interaction.updateContainerRect();
      }
      viewport.updateCanvasDimensions();
      window.addEventListener("resize", interaction.updateContainerRect);
      window.addEventListener("scroll", interaction.updateContainerRect);
      window.addEventListener("resize", viewport.updateCanvasDimensions);
      renderer.forceFullRedraw();
      renderer.updateMinimap(viewport.updateBounds, viewport.updateViewport);
      viewport.updateViewport();
      if (visible.value) {
        resumeChangeDetection();
        viewport.startViewportSync();
      }
      initialized.value = true;
    }
  }, "init");
  const destroy = /* @__PURE__ */ __name(() => {
    pauseChangeDetection();
    viewport.stopViewportSync();
    graphManager.destroy();
    window.removeEventListener("resize", interaction.updateContainerRect);
    window.removeEventListener("scroll", interaction.updateContainerRect);
    window.removeEventListener("resize", viewport.updateCanvasDimensions);
    initialized.value = false;
  }, "destroy");
  watch(
    canvas,
    async (newCanvas, oldCanvas) => {
      if (oldCanvas) {
        graphManager.cleanupEventListeners();
        pauseChangeDetection();
        viewport.stopViewportSync();
        graphManager.destroy();
        window.removeEventListener("resize", interaction.updateContainerRect);
        window.removeEventListener("scroll", interaction.updateContainerRect);
        window.removeEventListener("resize", viewport.updateCanvasDimensions);
      }
      if (newCanvas && !initialized.value) {
        await init();
      }
    },
    { immediate: true, flush: "post" }
  );
  watch(graph, (newGraph, oldGraph) => {
    if (newGraph && newGraph !== oldGraph) {
      graphManager.cleanupEventListeners(oldGraph || void 0);
      graphManager.setupEventListeners();
      renderer.forceFullRedraw();
      renderer.updateMinimap(viewport.updateBounds, viewport.updateViewport);
    }
  });
  watch(visible, async (isVisible) => {
    if (isVisible) {
      if (containerRef.value) {
        interaction.updateContainerRect();
      }
      viewport.updateCanvasDimensions();
      renderer.forceFullRedraw();
      await nextTick();
      await nextTick();
      renderer.updateMinimap(viewport.updateBounds, viewport.updateViewport);
      viewport.updateViewport();
      resumeChangeDetection();
      viewport.startViewportSync();
    } else {
      pauseChangeDetection();
      viewport.stopViewportSync();
    }
  });
  const toggle = /* @__PURE__ */ __name(async () => {
    visible.value = !visible.value;
    await settingStore.set("Comfy.Minimap.Visible", visible.value);
  }, "toggle");
  const setMinimapRef = /* @__PURE__ */ __name((ref2) => {
    minimapRef.value = ref2;
  }, "setMinimapRef");
  const viewportStyles = computed(() => {
    const transform = viewport.viewportTransform.value;
    return {
      transform: `translate(${transform.x}px, ${transform.y}px)`,
      width: `${transform.width}px`,
      height: `${transform.height}px`,
      border: `2px solid ${settings.isLightTheme.value ? "#E0E0E0" : "#FFF"}`,
      backgroundColor: `rgba(255, 255, 255, 0.2)`,
      willChange: "transform",
      backfaceVisibility: "hidden",
      perspective: "1000px",
      pointerEvents: "none"
    };
  });
  return {
    visible: computed(() => visible.value),
    initialized: computed(() => initialized.value),
    containerRef,
    canvasRef,
    containerStyles,
    viewportStyles,
    panelStyles,
    width,
    height,
    nodeColors,
    showLinks,
    showGroups,
    renderBypass,
    renderError,
    init,
    destroy,
    toggle,
    renderMinimap: renderer.renderMinimap,
    handlePointerDown: interaction.handlePointerDown,
    handlePointerMove: interaction.handlePointerMove,
    handlePointerUp: interaction.handlePointerUp,
    handleWheel: interaction.handleWheel,
    setMinimapRef,
    updateOption
  };
}
__name(useMinimap, "useMinimap");
const _hoisted_1$1l = {
  key: 0,
  class: "w-[250px] absolute flex justify-center right-2 md:right-11 z-1300 bottom-[66px] bg-inherit! border-0!"
};
const _hoisted_2$D = { class: "text-sm font-medium block" };
const _hoisted_3$q = { class: "text-sm text-gray-500 block" };
const _hoisted_4$k = { class: "text-sm font-medium block" };
const _hoisted_5$c = { class: "text-sm text-gray-500 block" };
const _hoisted_6$a = { class: "text-sm font-medium block" };
const _hoisted_7$8 = { class: "text-sm text-gray-500 block" };
const _hoisted_8$6 = { class: "text-sm font-medium block" };
const _hoisted_9$5 = { class: "text-sm text-gray-500 block" };
const _sfc_main$1t = /* @__PURE__ */ defineComponent({
  __name: "ZoomControlsModal",
  props: {
    visible: { type: Boolean }
  },
  setup(__props) {
    const { t: t2 } = useI18n();
    const minimap = useMinimap();
    const settingStore = useSettingStore();
    const commandStore = useCommandStore();
    const canvasStore = useCanvasStore();
    const { formatKeySequence } = useCommandStore();
    const props = __props;
    const interval = ref(null);
    const minimapToggleText = computed(
      () => settingStore.get("Comfy.Minimap.Visible") ? t2("zoomControls.hideMinimap") : t2("zoomControls.showMinimap")
    );
    const applyZoom = /* @__PURE__ */ __name((val) => {
      const inputValue = val.value;
      if (isNaN(inputValue) || inputValue < 1 || inputValue > 1e3) {
        return;
      }
      canvasStore.setAppZoomFromPercentage(inputValue);
    }, "applyZoom");
    const executeCommand = /* @__PURE__ */ __name((command) => {
      void commandStore.execute(command);
    }, "executeCommand");
    const startRepeat = /* @__PURE__ */ __name((command) => {
      if (interval.value) return;
      const cmd = /* @__PURE__ */ __name(() => commandStore.execute(command), "cmd");
      void cmd();
      interval.value = window.setInterval(cmd, 100);
    }, "startRepeat");
    const stopRepeat = /* @__PURE__ */ __name(() => {
      if (interval.value) {
        clearInterval(interval.value);
        interval.value = null;
      }
    }, "stopRepeat");
    const filteredMinimapStyles = computed(() => {
      return {
        ...minimap.containerStyles.value,
        height: void 0,
        width: void 0
      };
    });
    const zoomInCommandText = computed(
      () => formatKeySequence(commandStore.getCommand("Comfy.Canvas.ZoomIn"))
    );
    const zoomOutCommandText = computed(
      () => formatKeySequence(commandStore.getCommand("Comfy.Canvas.ZoomOut"))
    );
    const zoomToFitCommandText = computed(
      () => formatKeySequence(commandStore.getCommand("Comfy.Canvas.FitView"))
    );
    const showMinimapCommandText = computed(
      () => formatKeySequence(commandStore.getCommand("Comfy.Canvas.ToggleMinimap"))
    );
    const zoomInput = ref(null);
    const zoomInputContainer = ref(null);
    watch(
      () => props.visible,
      async (newVal) => {
        if (newVal) {
          await nextTick();
          const input = zoomInputContainer.value?.querySelector(
            "input"
          );
          input?.focus();
        }
      }
    );
    return (_ctx, _cache) => {
      return _ctx.visible ? (openBlock(), createElementBlock("div", _hoisted_1$1l, [
        createElementVNode("div", {
          class: "bg-white dark-theme:bg-[#2b2b2b] border border-gray-200 dark-theme:border-gray-700 rounded-lg shadow-lg p-4 w-4/5",
          style: normalizeStyle(filteredMinimapStyles.value),
          onClick: _cache[4] || (_cache[4] = withModifiers(() => {
          }, ["stop"]))
        }, [
          createElementVNode("div", null, [
            createVNode(unref(Button$1), {
              severity: "secondary",
              text: "",
              pt: {
                root: {
                  class: "flex items-center justify-between cursor-pointer p-2 rounded w-full text-left hover:bg-transparent! focus:bg-transparent! active:bg-transparent!"
                },
                label: {
                  class: "flex flex-col items-start w-full"
                }
              },
              onMousedown: _cache[0] || (_cache[0] = ($event) => startRepeat("Comfy.Canvas.ZoomIn")),
              onMouseup: stopRepeat,
              onMouseleave: stopRepeat
            }, {
              default: withCtx(() => [
                createElementVNode("span", _hoisted_2$D, toDisplayString(_ctx.$t("graphCanvasMenu.zoomIn")), 1),
                createElementVNode("span", _hoisted_3$q, toDisplayString(zoomInCommandText.value), 1)
              ]),
              _: 1
            }),
            createVNode(unref(Button$1), {
              severity: "secondary",
              text: "",
              pt: {
                root: {
                  class: "flex items-center justify-between cursor-pointer p-2 rounded w-full text-left hover:bg-transparent! focus:bg-transparent! active:bg-transparent!"
                },
                label: {
                  class: "flex flex-col items-start w-full"
                }
              },
              onMousedown: _cache[1] || (_cache[1] = ($event) => startRepeat("Comfy.Canvas.ZoomOut")),
              onMouseup: stopRepeat,
              onMouseleave: stopRepeat
            }, {
              default: withCtx(() => [
                createElementVNode("span", _hoisted_4$k, toDisplayString(_ctx.$t("graphCanvasMenu.zoomOut")), 1),
                createElementVNode("span", _hoisted_5$c, toDisplayString(zoomOutCommandText.value), 1)
              ]),
              _: 1
            }),
            createVNode(unref(Button$1), {
              severity: "secondary",
              text: "",
              pt: {
                root: {
                  class: "flex items-center justify-between cursor-pointer p-2 rounded w-full text-left hover:bg-transparent! focus:bg-transparent! active:bg-transparent!"
                },
                label: {
                  class: "flex flex-col items-start w-full"
                }
              },
              onClick: _cache[2] || (_cache[2] = ($event) => executeCommand("Comfy.Canvas.FitView"))
            }, {
              default: withCtx(() => [
                createElementVNode("span", _hoisted_6$a, toDisplayString(_ctx.$t("zoomControls.zoomToFit")), 1),
                createElementVNode("span", _hoisted_7$8, toDisplayString(zoomToFitCommandText.value), 1)
              ]),
              _: 1
            }),
            _cache[6] || (_cache[6] = createElementVNode("hr", { class: "border-[#E1DED5] mb-1 dark-theme:border-[#2E3037]" }, null, -1)),
            createVNode(unref(Button$1), {
              severity: "secondary",
              text: "",
              "data-testid": "toggle-minimap-button",
              pt: {
                root: {
                  class: "flex items-center justify-between cursor-pointer p-2 rounded w-full text-left hover:bg-transparent! focus:bg-transparent! active:bg-transparent!"
                },
                label: {
                  class: "flex flex-col items-start w-full"
                }
              },
              onClick: _cache[3] || (_cache[3] = ($event) => executeCommand("Comfy.Canvas.ToggleMinimap"))
            }, {
              default: withCtx(() => [
                createElementVNode("span", _hoisted_8$6, toDisplayString(minimapToggleText.value), 1),
                createElementVNode("span", _hoisted_9$5, toDisplayString(showMinimapCommandText.value), 1)
              ]),
              _: 1
            }),
            _cache[7] || (_cache[7] = createElementVNode("hr", { class: "border-[#E1DED5] mt-1 dark-theme:border-[#2E3037]" }, null, -1)),
            createElementVNode("div", {
              ref_key: "zoomInputContainer",
              ref: zoomInputContainer,
              class: "flex items-center px-2 bg-[#E7E6E6] focus-within:bg-[#F3F3F3] dark-theme:bg-[#8282821A] rounded p-2 zoomInputContainer"
            }, [
              createVNode(unref(InputNumber), {
                ref_key: "zoomInput",
                ref: zoomInput,
                "default-value": unref(canvasStore).appScalePercentage,
                min: 1,
                max: 1e3,
                "show-buttons": false,
                "use-grouping": false,
                unstyled: true,
                "input-class": "flex-1 bg-transparent border-none outline-hidden text-sm shadow-none my-0 ",
                fluid: "",
                onInput: applyZoom,
                onKeyup: withKeys(applyZoom, ["enter"])
              }, null, 8, ["default-value"]),
              _cache[5] || (_cache[5] = createElementVNode("span", { class: "text-sm text-gray-500 -ml-4" }, "%", -1))
            ], 512)
          ])
        ], 4)
      ])) : createCommentVNode("", true);
    };
  }
});
const _hoisted_1$1k = { class: "inline-flex text-xs" };
const _sfc_main$1s = /* @__PURE__ */ defineComponent({
  __name: "GraphCanvasMenu",
  setup(__props) {
    const { t: t2 } = useI18n();
    const commandStore = useCommandStore();
    const { formatKeySequence } = useCommandStore();
    const canvasStore = useCanvasStore();
    const settingStore = useSettingStore();
    const canvasInteractions = useCanvasInteractions();
    const workspaceStore = useWorkspaceStore();
    const minimap = useMinimap();
    const { isModalVisible, toggleModal, hideModal, hasActivePopup } = useZoomControls();
    const stringifiedMinimapStyles = computed(() => {
      const buttonGroupKeys = ["backgroundColor", "borderRadius", ""];
      const buttonKeys = ["backgroundColor", "borderRadius"];
      const additionalButtonStyles = {
        border: "none",
        width: "35px",
        height: "35px",
        "margin-right": "2px",
        "margin-left": "2px"
      };
      const containerStyles = minimap.containerStyles.value;
      const buttonStyles = {
        ...Object.fromEntries(
          Object.entries(containerStyles).filter(
            ([key]) => buttonKeys.includes(key)
          )
        ),
        ...additionalButtonStyles
      };
      const buttonGroupStyles = Object.entries(containerStyles).filter(([key]) => buttonGroupKeys.includes(key)).reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {});
      return { buttonStyles, buttonGroupStyles };
    });
    const isCanvasReadOnly = computed(() => canvasStore.canvas?.read_only ?? false);
    const isCanvasUnlocked = computed(() => !isCanvasReadOnly.value);
    const linkHidden = computed(
      () => settingStore.get("Comfy.LinkRenderMode") === LiteGraph.HIDDEN_LINK
    );
    const unlockCommandText = computed(
      () => formatKeySequence(
        commandStore.getCommand("Comfy.Canvas.Unlock")
      ).toUpperCase()
    );
    const lockCommandText = computed(
      () => formatKeySequence(commandStore.getCommand("Comfy.Canvas.Lock")).toUpperCase()
    );
    const fitViewCommandText = computed(
      () => formatKeySequence(
        commandStore.getCommand("Comfy.Canvas.FitView")
      ).toUpperCase()
    );
    const focusCommandText = computed(
      () => formatKeySequence(
        commandStore.getCommand("Workspace.ToggleFocusMode")
      ).toUpperCase()
    );
    const selectButtonClass = computed(
      () => isCanvasUnlocked.value ? "not-active:dark-theme:bg-[#262729]! not-active:bg-[#E7E6E6]!" : ""
    );
    const handButtonClass = computed(
      () => isCanvasReadOnly.value ? "not-active:dark-theme:bg-[#262729]! not-active:bg-[#E7E6E6]!" : ""
    );
    const zoomButtonClass = computed(() => [
      "w-16!",
      isModalVisible.value ? "not-active:dark-theme:bg-[#262729]! not-active:bg-[#E7E6E6]!" : "",
      "dark-theme:hover:bg-[#262729]! hover:bg-[#E7E6E6]!"
    ]);
    const focusButtonClass = computed(() => ({
      "dark-theme:hover:bg-[#262729]! hover:bg-[#E7E6E6]!": true,
      "not-active:dark-theme:bg-[#262729]! not-active:bg-[#E7E6E6]!": workspaceStore.focusMode
    }));
    const selectTooltip = computed(
      () => `${t2("graphCanvasMenu.select")} (${unlockCommandText.value})`
    );
    const handTooltip = computed(
      () => `${t2("graphCanvasMenu.hand")} (${lockCommandText.value})`
    );
    const fitViewTooltip = computed(
      () => `${t2("graphCanvasMenu.fitView")} (${fitViewCommandText.value})`
    );
    const focusModeTooltip = computed(
      () => `${t2("graphCanvasMenu.focusMode")} (${focusCommandText.value})`
    );
    const linkVisibilityTooltip = computed(
      () => linkHidden.value ? t2("graphCanvasMenu.showLinks") : t2("graphCanvasMenu.hideLinks")
    );
    const linkVisibilityAriaLabel = computed(
      () => linkHidden.value ? t2("graphCanvasMenu.showLinks") : t2("graphCanvasMenu.hideLinks")
    );
    const linkVisibleClass = computed(() => [
      linkHidden.value ? "not-active:dark-theme:bg-[#262729]! not-active:bg-[#E7E6E6]!" : "",
      "dark-theme:hover:bg-[#262729]! hover:bg-[#E7E6E6]!"
    ]);
    onMounted(() => {
      canvasStore.initScaleSync();
    });
    onBeforeUnmount(() => {
      canvasStore.cleanupScaleSync();
    });
    return (_ctx, _cache) => {
      const _component_i_lucide58mouse_pointer_2 = __unplugin_components_0$b;
      const _component_i_lucide58hand = __unplugin_components_1$7;
      const _component_i_lucide58focus = __unplugin_components_2$4;
      const _component_i_lucide58chevron_down = __unplugin_components_0$c;
      const _component_i_lucide58lightbulb = __unplugin_components_4$2;
      const _component_i_lucide58route_off = __unplugin_components_5$1;
      const _directive_tooltip = resolveDirective("tooltip");
      return openBlock(), createElementBlock("div", null, [
        createVNode(_sfc_main$1t, { visible: unref(isModalVisible) }, null, 8, ["visible"]),
        unref(hasActivePopup) ? (openBlock(), createElementBlock("div", {
          key: 0,
          class: "fixed inset-0 z-1200",
          onClick: _cache[0] || (_cache[0] = //@ts-ignore
          (...args) => unref(hideModal) && unref(hideModal)(...args))
        })) : createCommentVNode("", true),
        createVNode(unref(ButtonGroup), {
          class: "p-buttongroup-vertical p-1 absolute bottom-4 right-2 md:right-4",
          style: normalizeStyle(stringifiedMinimapStyles.value.buttonGroupStyles),
          onWheel: unref(canvasInteractions).handleWheel
        }, {
          default: withCtx(() => [
            withDirectives((openBlock(), createBlock(unref(Button), {
              style: normalizeStyle(stringifiedMinimapStyles.value.buttonStyles),
              severity: "secondary",
              "aria-label": selectTooltip.value,
              pressed: isCanvasReadOnly.value,
              icon: "i-material-symbols:pan-tool-outline",
              class: normalizeClass(selectButtonClass.value),
              onClick: _cache[1] || (_cache[1] = () => unref(commandStore).execute("Comfy.Canvas.Unlock"))
            }, {
              icon: withCtx(() => [
                createVNode(_component_i_lucide58mouse_pointer_2)
              ]),
              _: 1
            }, 8, ["style", "aria-label", "pressed", "class"])), [
              [
                _directive_tooltip,
                selectTooltip.value,
                void 0,
                { top: true }
              ]
            ]),
            withDirectives((openBlock(), createBlock(unref(Button), {
              severity: "secondary",
              "aria-label": handTooltip.value,
              pressed: isCanvasUnlocked.value,
              class: normalizeClass(handButtonClass.value),
              style: normalizeStyle(stringifiedMinimapStyles.value.buttonStyles),
              onClick: _cache[2] || (_cache[2] = () => unref(commandStore).execute("Comfy.Canvas.Lock"))
            }, {
              icon: withCtx(() => [
                createVNode(_component_i_lucide58hand)
              ]),
              _: 1
            }, 8, ["aria-label", "pressed", "class", "style"])), [
              [
                _directive_tooltip,
                handTooltip.value,
                void 0,
                { top: true }
              ]
            ]),
            _cache[6] || (_cache[6] = createElementVNode("div", { class: "w-px my-1 bg-[#E1DED5] dark-theme:bg-[#2E3037] mx-2" }, null, -1)),
            withDirectives((openBlock(), createBlock(unref(Button), {
              severity: "secondary",
              icon: "pi pi-expand",
              "aria-label": fitViewTooltip.value,
              style: normalizeStyle(stringifiedMinimapStyles.value.buttonStyles),
              class: "dark-theme:hover:bg-[#444444]! hover:bg-[#E7E6E6]!",
              onClick: _cache[3] || (_cache[3] = () => unref(commandStore).execute("Comfy.Canvas.FitView"))
            }, {
              icon: withCtx(() => [
                createVNode(_component_i_lucide58focus)
              ]),
              _: 1
            }, 8, ["aria-label", "style"])), [
              [
                _directive_tooltip,
                fitViewTooltip.value,
                void 0,
                { top: true }
              ]
            ]),
            withDirectives((openBlock(), createBlock(unref(Button), {
              ref: "zoomButton",
              severity: "secondary",
              label: unref(t2)("zoomControls.label"),
              class: normalizeClass(zoomButtonClass.value),
              "aria-label": unref(t2)("zoomControls.label"),
              "data-testid": "zoom-controls-button",
              style: normalizeStyle(stringifiedMinimapStyles.value.buttonStyles),
              onClick: unref(toggleModal)
            }, {
              default: withCtx(() => [
                createElementVNode("span", _hoisted_1$1k, [
                  createElementVNode("span", null, toDisplayString(unref(canvasStore).appScalePercentage) + "%", 1),
                  createVNode(_component_i_lucide58chevron_down)
                ])
              ]),
              _: 1
            }, 8, ["label", "class", "aria-label", "style", "onClick"])), [
              [
                _directive_tooltip,
                unref(t2)("zoomControls.label"),
                void 0,
                { top: true }
              ]
            ]),
            _cache[7] || (_cache[7] = createElementVNode("div", { class: "w-px my-1 bg-[#E1DED5] dark-theme:bg-[#2E3037] mx-2" }, null, -1)),
            withDirectives((openBlock(), createBlock(unref(Button), {
              ref: "focusButton",
              severity: "secondary",
              "aria-label": focusModeTooltip.value,
              "data-testid": "focus-mode-button",
              style: normalizeStyle(stringifiedMinimapStyles.value.buttonStyles),
              class: normalizeClass(focusButtonClass.value),
              onClick: _cache[4] || (_cache[4] = () => unref(commandStore).execute("Workspace.ToggleFocusMode"))
            }, {
              icon: withCtx(() => [
                createVNode(_component_i_lucide58lightbulb)
              ]),
              _: 1
            }, 8, ["aria-label", "style", "class"])), [
              [
                _directive_tooltip,
                focusModeTooltip.value,
                void 0,
                { top: true }
              ]
            ]),
            withDirectives((openBlock(), createBlock(unref(Button), {
              severity: "secondary",
              class: normalizeClass(linkVisibleClass.value),
              "aria-label": linkVisibilityAriaLabel.value,
              "data-testid": "toggle-link-visibility-button",
              style: normalizeStyle(stringifiedMinimapStyles.value.buttonStyles),
              onClick: _cache[5] || (_cache[5] = () => unref(commandStore).execute("Comfy.Canvas.ToggleLinkVisibility"))
            }, {
              icon: withCtx(() => [
                createVNode(_component_i_lucide58route_off)
              ]),
              _: 1
            }, 8, ["class", "aria-label", "style"])), [
              [
                _directive_tooltip,
                {
                  value: linkVisibilityTooltip.value,
                  pt: {
                    root: {
                      style: "z-index: 2; transform: translateY(-20px);"
                    }
                  }
                },
                void 0,
                { top: true }
              ]
            ])
          ]),
          _: 1
        }, 8, ["style", "onWheel"])
      ]);
    };
  }
});
const GraphCanvasMenu = /* @__PURE__ */ _export_sfc(_sfc_main$1s, [["__scopeId", "data-v-cf8fca61"]]);
const _hoisted_1$1j = {
  viewBox: "0 0 24 24",
  width: "1.2em",
  height: "1.2em"
};
function render$t(_ctx, _cache) {
  return openBlock(), createElementBlock("svg", _hoisted_1$1j, _cache[0] || (_cache[0] = [
    createElementVNode("path", {
      fill: "none",
      stroke: "currentColor",
      "stroke-linecap": "round",
      "stroke-linejoin": "round",
      "stroke-width": "2",
      d: "M18 6L6 18M6 6l12 12"
    }, null, -1)
  ]));
}
__name(render$t, "render$t");
const __unplugin_components_1$6 = markRaw({ name: "lucide-x", render: render$t });
const _hoisted_1$1i = {
  viewBox: "0 0 24 24",
  width: "1.2em",
  height: "1.2em"
};
function render$s(_ctx, _cache) {
  return openBlock(), createElementBlock("svg", _hoisted_1$1i, _cache[0] || (_cache[0] = [
    createElementVNode("g", {
      fill: "none",
      stroke: "currentColor",
      "stroke-linecap": "round",
      "stroke-linejoin": "round",
      "stroke-width": "2"
    }, [
      createElementVNode("path", { d: "M14 17H5M19 7h-9" }),
      createElementVNode("circle", {
        cx: "17",
        cy: "17",
        r: "3"
      }),
      createElementVNode("circle", {
        cx: "7",
        cy: "7",
        r: "3"
      })
    ], -1)
  ]));
}
__name(render$s, "render$s");
const __unplugin_components_0$a = markRaw({ name: "lucide-settings2", render: render$s });
const _hoisted_1$1h = {
  viewBox: "0 0 24 24",
  width: "1.2em",
  height: "1.2em"
};
function render$r(_ctx, _cache) {
  return openBlock(), createElementBlock("svg", _hoisted_1$1h, _cache[0] || (_cache[0] = [
    createElementVNode("path", {
      fill: "none",
      stroke: "currentColor",
      "stroke-linecap": "round",
      "stroke-linejoin": "round",
      "stroke-width": "2",
      d: "M2.992 16.342a2 2 0 0 1 .094 1.167l-1.065 3.29a1 1 0 0 0 1.236 1.168l3.413-.998a2 2 0 0 1 1.099.092a10 10 0 1 0-4.777-4.719M12 8v4m0 4h.01"
    }, null, -1)
  ]));
}
__name(render$r, "render$r");
const __unplugin_components_4$1 = markRaw({ name: "lucide-message-circle-warning", render: render$r });
const _hoisted_1$1g = {
  viewBox: "0 0 24 24",
  width: "1.2em",
  height: "1.2em"
};
function render$q(_ctx, _cache) {
  return openBlock(), createElementBlock("svg", _hoisted_1$1g, _cache[0] || (_cache[0] = [
    createElementVNode("g", {
      fill: "none",
      stroke: "currentColor",
      "stroke-linecap": "round",
      "stroke-linejoin": "round",
      "stroke-width": "2"
    }, [
      createElementVNode("path", { d: "M22 2L2 22" }),
      createElementVNode("circle", {
        cx: "12",
        cy: "12",
        r: "10"
      })
    ], -1)
  ]));
}
__name(render$q, "render$q");
const __unplugin_components_3$3 = markRaw({ name: "lucide-circle-slash2", render: render$q });
const _hoisted_1$1f = {
  viewBox: "0 0 24 24",
  width: "1.2em",
  height: "1.2em"
};
function render$p(_ctx, _cache) {
  return openBlock(), createElementBlock("svg", _hoisted_1$1f, _cache[0] || (_cache[0] = [
    createElementVNode("path", {
      fill: "none",
      stroke: "currentColor",
      "stroke-linecap": "round",
      "stroke-linejoin": "round",
      "stroke-width": "2",
      d: "M22 6H2m20 12H2M6 2v20M18 2v20"
    }, null, -1)
  ]));
}
__name(render$p, "render$p");
const __unplugin_components_2$3 = markRaw({ name: "lucide-frame", render: render$p });
const _hoisted_1$1e = {
  viewBox: "0 0 24 24",
  width: "1.2em",
  height: "1.2em"
};
function render$o(_ctx, _cache) {
  return openBlock(), createElementBlock("svg", _hoisted_1$1e, _cache[0] || (_cache[0] = [
    createElementVNode("g", {
      fill: "none",
      stroke: "currentColor",
      "stroke-linecap": "round",
      "stroke-linejoin": "round",
      "stroke-width": "2"
    }, [
      createElementVNode("circle", {
        cx: "6",
        cy: "19",
        r: "3"
      }),
      createElementVNode("path", { d: "M9 19h8.5a3.5 3.5 0 0 0 0-7h-11a3.5 3.5 0 0 1 0-7H15" }),
      createElementVNode("circle", {
        cx: "18",
        cy: "5",
        r: "3"
      })
    ], -1)
  ]));
}
__name(render$o, "render$o");
const __unplugin_components_1$5 = markRaw({ name: "lucide-route", render: render$o });
const _hoisted_1$1d = {
  viewBox: "0 0 24 24",
  width: "1.2em",
  height: "1.2em"
};
function render$n(_ctx, _cache) {
  return openBlock(), createElementBlock("svg", _hoisted_1$1d, _cache[0] || (_cache[0] = [
    createStaticVNode('<g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path d="M12 22a1 1 0 0 1 0-20a10 9 0 0 1 10 9a5 5 0 0 1-5 5h-2.25a1.75 1.75 0 0 0-1.4 2.8l.3.4a1.75 1.75 0 0 1-1.4 2.8z"></path><circle cx="13.5" cy="6.5" r=".5" fill="currentColor"></circle><circle cx="17.5" cy="10.5" r=".5" fill="currentColor"></circle><circle cx="6.5" cy="12.5" r=".5" fill="currentColor"></circle><circle cx="8.5" cy="7.5" r=".5" fill="currentColor"></circle></g>', 1)
  ]));
}
__name(render$n, "render$n");
const __unplugin_components_0$9 = markRaw({ name: "lucide-palette", render: render$n });
const _hoisted_1$1c = { class: "flex items-center gap-2" };
const _hoisted_2$C = { for: "node-colors" };
const _hoisted_3$p = { class: "flex items-center gap-2" };
const _hoisted_4$j = { for: "show-links" };
const _hoisted_5$b = { class: "flex items-center gap-2" };
const _hoisted_6$9 = { for: "show-groups" };
const _hoisted_7$7 = { class: "flex items-center gap-2" };
const _hoisted_8$5 = { for: "render-bypass" };
const _hoisted_9$4 = { class: "flex items-center gap-2" };
const _hoisted_10$4 = { for: "render-error" };
const _sfc_main$1r = /* @__PURE__ */ defineComponent({
  __name: "MiniMapPanel",
  props: {
    panelStyles: {},
    nodeColors: { type: Boolean },
    showLinks: { type: Boolean },
    showGroups: { type: Boolean },
    renderBypass: { type: Boolean },
    renderError: { type: Boolean }
  },
  emits: ["updateOption"],
  setup(__props) {
    return (_ctx, _cache) => {
      const _component_i_lucide58palette = __unplugin_components_0$9;
      const _component_i_lucide58route = __unplugin_components_1$5;
      const _component_i_lucide58frame = __unplugin_components_2$3;
      const _component_i_lucide58circle_slash_2 = __unplugin_components_3$3;
      const _component_i_lucide58message_circle_warning = __unplugin_components_4$1;
      return openBlock(), createElementBlock("div", {
        class: "minimap-panel p-3 mr-2 flex flex-col gap-3 text-sm",
        style: normalizeStyle(_ctx.panelStyles)
      }, [
        createElementVNode("div", _hoisted_1$1c, [
          createVNode(unref(Checkbox), {
            "input-id": "node-colors",
            name: "node-colors",
            "model-value": _ctx.nodeColors,
            binary: "",
            "onUpdate:modelValue": _cache[0] || (_cache[0] = (value) => _ctx.$emit("updateOption", "Comfy.Minimap.NodeColors", value))
          }, null, 8, ["model-value"]),
          createVNode(_component_i_lucide58palette),
          createElementVNode("label", _hoisted_2$C, toDisplayString(_ctx.$t("minimap.nodeColors")), 1)
        ]),
        createElementVNode("div", _hoisted_3$p, [
          createVNode(unref(Checkbox), {
            "input-id": "show-links",
            name: "show-links",
            "model-value": _ctx.showLinks,
            binary: "",
            "onUpdate:modelValue": _cache[1] || (_cache[1] = (value) => _ctx.$emit("updateOption", "Comfy.Minimap.ShowLinks", value))
          }, null, 8, ["model-value"]),
          createVNode(_component_i_lucide58route),
          createElementVNode("label", _hoisted_4$j, toDisplayString(_ctx.$t("minimap.showLinks")), 1)
        ]),
        createElementVNode("div", _hoisted_5$b, [
          createVNode(unref(Checkbox), {
            "input-id": "show-groups",
            name: "show-groups",
            "model-value": _ctx.showGroups,
            binary: "",
            "onUpdate:modelValue": _cache[2] || (_cache[2] = (value) => _ctx.$emit("updateOption", "Comfy.Minimap.ShowGroups", value))
          }, null, 8, ["model-value"]),
          createVNode(_component_i_lucide58frame),
          createElementVNode("label", _hoisted_6$9, toDisplayString(_ctx.$t("minimap.showGroups")), 1)
        ]),
        createElementVNode("div", _hoisted_7$7, [
          createVNode(unref(Checkbox), {
            "input-id": "render-bypass",
            name: "render-bypass",
            "model-value": _ctx.renderBypass,
            binary: "",
            "onUpdate:modelValue": _cache[3] || (_cache[3] = (value) => _ctx.$emit("updateOption", "Comfy.Minimap.RenderBypassState", value))
          }, null, 8, ["model-value"]),
          createVNode(_component_i_lucide58circle_slash_2),
          createElementVNode("label", _hoisted_8$5, toDisplayString(_ctx.$t("minimap.renderBypassState")), 1)
        ]),
        createElementVNode("div", _hoisted_9$4, [
          createVNode(unref(Checkbox), {
            "input-id": "render-error",
            name: "render-error",
            "model-value": _ctx.renderError,
            binary: "",
            "onUpdate:modelValue": _cache[4] || (_cache[4] = (value) => _ctx.$emit("updateOption", "Comfy.Minimap.RenderErrorState", value))
          }, null, 8, ["model-value"]),
          createVNode(_component_i_lucide58message_circle_warning),
          createElementVNode("label", _hoisted_10$4, toDisplayString(_ctx.$t("minimap.renderErrorState")), 1)
        ])
      ], 4);
    };
  }
});
const _hoisted_1$1b = ["width", "height"];
const _sfc_main$1q = /* @__PURE__ */ defineComponent({
  __name: "MiniMap",
  setup(__props) {
    const commandStore = useCommandStore();
    const minimapRef = ref();
    const {
      initialized,
      visible,
      containerRef,
      canvasRef,
      containerStyles,
      viewportStyles,
      width,
      height,
      panelStyles,
      nodeColors,
      showLinks,
      showGroups,
      renderBypass,
      renderError,
      updateOption,
      destroy,
      handlePointerDown,
      handlePointerMove,
      handlePointerUp,
      handleWheel,
      setMinimapRef
    } = useMinimap();
    const showOptionsPanel = ref(false);
    const toggleOptionsPanel = /* @__PURE__ */ __name(() => {
      showOptionsPanel.value = !showOptionsPanel.value;
    }, "toggleOptionsPanel");
    onMounted(() => {
      if (minimapRef.value) {
        setMinimapRef(minimapRef.value);
      }
    });
    onUnmounted(() => {
      destroy();
    });
    return (_ctx, _cache) => {
      const _component_i_lucide58settings_2 = __unplugin_components_0$a;
      const _component_i_lucide58x = __unplugin_components_1$6;
      return unref(visible) && unref(initialized) ? (openBlock(), createElementBlock("div", {
        key: 0,
        ref_key: "minimapRef",
        ref: minimapRef,
        class: "minimap-main-container flex absolute bottom-[66px] right-2 md:right-11 z-1000"
      }, [
        showOptionsPanel.value ? (openBlock(), createBlock(_sfc_main$1r, {
          key: 0,
          "panel-styles": unref(panelStyles),
          "node-colors": unref(nodeColors),
          "show-links": unref(showLinks),
          "show-groups": unref(showGroups),
          "render-bypass": unref(renderBypass),
          "render-error": unref(renderError),
          onUpdateOption: unref(updateOption)
        }, null, 8, ["panel-styles", "node-colors", "show-links", "show-groups", "render-bypass", "render-error", "onUpdateOption"])) : createCommentVNode("", true),
        createElementVNode("div", {
          ref_key: "containerRef",
          ref: containerRef,
          class: "litegraph-minimap relative",
          style: normalizeStyle(unref(containerStyles))
        }, [
          createVNode(unref(Button), {
            class: "absolute z-10",
            size: "small",
            text: "",
            severity: "secondary",
            onClick: withModifiers(toggleOptionsPanel, ["stop"])
          }, {
            icon: withCtx(() => [
              createVNode(_component_i_lucide58settings_2)
            ]),
            _: 1
          }),
          createVNode(unref(Button), {
            class: "absolute z-10 right-0",
            size: "small",
            text: "",
            severity: "secondary",
            "data-testid": "close-minmap-button",
            onClick: _cache[0] || (_cache[0] = withModifiers(() => unref(commandStore).execute("Comfy.Canvas.ToggleMinimap"), ["stop"]))
          }, {
            icon: withCtx(() => [
              createVNode(_component_i_lucide58x)
            ]),
            _: 1
          }),
          createElementVNode("hr", {
            class: "absolute top-5 bg-[#E1DED5] dark-theme:bg-[#262729] h-[1px] border-0",
            style: normalizeStyle({
              width: unref(containerStyles).width
            })
          }, null, 4),
          createElementVNode("canvas", {
            ref_key: "canvasRef",
            ref: canvasRef,
            width: unref(width),
            height: unref(height),
            class: "minimap-canvas"
          }, null, 8, _hoisted_1$1b),
          createElementVNode("div", {
            class: "minimap-viewport",
            style: normalizeStyle(unref(viewportStyles))
          }, null, 4),
          createElementVNode("div", {
            class: "absolute inset-0",
            onPointerdown: _cache[1] || (_cache[1] = //@ts-ignore
            (...args) => unref(handlePointerDown) && unref(handlePointerDown)(...args)),
            onPointermove: _cache[2] || (_cache[2] = //@ts-ignore
            (...args) => unref(handlePointerMove) && unref(handlePointerMove)(...args)),
            onPointerup: _cache[3] || (_cache[3] = //@ts-ignore
            (...args) => unref(handlePointerUp) && unref(handlePointerUp)(...args)),
            onPointerleave: _cache[4] || (_cache[4] = //@ts-ignore
            (...args) => unref(handlePointerUp) && unref(handlePointerUp)(...args)),
            onWheel: _cache[5] || (_cache[5] = //@ts-ignore
            (...args) => unref(handleWheel) && unref(handleWheel)(...args))
          }, null, 32)
        ], 4)
      ], 512)) : createCommentVNode("", true);
    };
  }
});
const MiniMap = /* @__PURE__ */ _export_sfc(_sfc_main$1q, [["__scopeId", "data-v-c777e5b8"]]);
const _sfc_main$1p = /* @__PURE__ */ defineComponent({
  __name: "NodeTooltip",
  setup(__props) {
    let idleTimeout;
    const nodeDefStore = useNodeDefStore();
    const settingStore = useSettingStore();
    const tooltipRef = ref();
    const tooltipText = ref("");
    const left = ref();
    const top = ref();
    const hideTooltip = /* @__PURE__ */ __name(() => tooltipText.value = "", "hideTooltip");
    const showTooltip = /* @__PURE__ */ __name(async (tooltip) => {
      if (!tooltip) return;
      left.value = app.canvas.mouse[0] + "px";
      top.value = app.canvas.mouse[1] + "px";
      tooltipText.value = tooltip;
      await nextTick();
      const rect = tooltipRef.value?.getBoundingClientRect();
      if (!rect) return;
      if (rect.right > window.innerWidth) {
        left.value = app.canvas.mouse[0] - rect.width + "px";
      }
      if (rect.top < 0) {
        top.value = app.canvas.mouse[1] + rect.height + "px";
      }
    }, "showTooltip");
    const onIdle = /* @__PURE__ */ __name(() => {
      const { canvas } = app;
      const node = canvas.node_over;
      if (!node) return;
      const ctor = node.constructor;
      const nodeDef = nodeDefStore.nodeDefsByName[node.type ?? ""];
      if (ctor.title_mode !== LiteGraph.NO_TITLE && canvas.graph_mouse[1] < node.pos[1]) {
        return showTooltip(nodeDef.description);
      }
      if (node.flags?.collapsed) return;
      const inputSlot = isOverNodeInput(
        node,
        canvas.graph_mouse[0],
        canvas.graph_mouse[1],
        [0, 0]
      );
      if (inputSlot !== -1) {
        const inputName = node.inputs[inputSlot].name;
        const translatedTooltip = st(
          `nodeDefs.${normalizeI18nKey(node.type ?? "")}.inputs.${normalizeI18nKey(inputName)}.tooltip`,
          nodeDef.inputs[inputName]?.tooltip ?? ""
        );
        return showTooltip(translatedTooltip);
      }
      const outputSlot = isOverNodeOutput(
        node,
        canvas.graph_mouse[0],
        canvas.graph_mouse[1],
        [0, 0]
      );
      if (outputSlot !== -1) {
        const translatedTooltip = st(
          `nodeDefs.${normalizeI18nKey(node.type ?? "")}.outputs.${outputSlot}.tooltip`,
          nodeDef.outputs[outputSlot]?.tooltip ?? ""
        );
        return showTooltip(translatedTooltip);
      }
      const widget = app.canvas.getWidgetAtCursor();
      if (widget && !isDOMWidget(widget)) {
        const translatedTooltip = st(
          `nodeDefs.${normalizeI18nKey(node.type ?? "")}.inputs.${normalizeI18nKey(widget.name)}.tooltip`,
          nodeDef.inputs[widget.name]?.tooltip ?? ""
        );
        return showTooltip(widget.tooltip ?? translatedTooltip);
      }
    }, "onIdle");
    const onMouseMove = /* @__PURE__ */ __name((e) => {
      hideTooltip();
      clearTimeout(idleTimeout);
      if (e.target.nodeName !== "CANVAS") return;
      idleTimeout = window.setTimeout(
        onIdle,
        settingStore.get("LiteGraph.Node.TooltipDelay")
      );
    }, "onMouseMove");
    useEventListener(window, "mousemove", onMouseMove);
    useEventListener(window, "click", hideTooltip);
    return (_ctx, _cache) => {
      return tooltipText.value ? (openBlock(), createElementBlock("div", {
        key: 0,
        ref_key: "tooltipRef",
        ref: tooltipRef,
        class: "node-tooltip",
        style: normalizeStyle({ left: left.value, top: top.value })
      }, toDisplayString(tooltipText.value), 5)) : createCommentVNode("", true);
    };
  }
});
const NodeTooltip = /* @__PURE__ */ _export_sfc(_sfc_main$1p, [["__scopeId", "data-v-69036aeb"]]);
const _hoisted_1$1a = {
  viewBox: "0 0 512 512",
  width: "1.2em",
  height: "1.2em"
};
function render$m(_ctx, _cache) {
  return openBlock(), createElementBlock("svg", _hoisted_1$1a, _cache[0] || (_cache[0] = [
    createElementVNode("path", {
      fill: "currentColor",
      d: "M486.945 25.055L347.49 52.945l23.78 23.784L390.544 96l-56.793 56.795c-27.393-22.7-57.978-32.844-86.97-32.06c-33.838.918-64.92 15.95-87.858 38.888c-22.94 22.94-38.084 54.114-39.406 88.178c-1.138 29.306 8.49 60.407 30.742 88.485L19.27 467.27l25.46 25.46l155.48-155.484l-12.476-12.726c-24.72-25.22-33.185-51.125-32.246-75.323s11.9-47.13 28.89-64.12c16.988-16.988 39.66-27.71 63.38-28.352c23.72-.643 49.04 8.152 73.633 33.5l12.727 13.115L416 121.457l43.055 43.053zM256 192a64 64 0 0 0-64 64a64 64 0 0 0 64 64a64 64 0 0 0 64-64a64 64 0 0 0-64-64"
    }, null, -1)
  ]));
}
__name(render$m, "render$m");
const __unplugin_components_0$8 = markRaw({ name: "game-icons-detour", render: render$m });
const _sfc_main$1o = /* @__PURE__ */ defineComponent({
  __name: "BypassButton",
  setup(__props) {
    const { t: t2 } = useI18n();
    const commandStore = useCommandStore();
    const canvasStore = useCanvasStore();
    return (_ctx, _cache) => {
      const _component_i_game_icons58detour = __unplugin_components_0$8;
      const _directive_tooltip = resolveDirective("tooltip");
      return withDirectives((openBlock(), createBlock(unref(Button), {
        severity: "secondary",
        text: "",
        "data-testid": "bypass-button",
        onClick: _cache[0] || (_cache[0] = () => unref(commandStore).execute("Comfy.Canvas.ToggleSelectedNodes.Bypass"))
      }, {
        icon: withCtx(() => [
          createVNode(_component_i_game_icons58detour)
        ]),
        _: 1
      })), [
        [vShow, unref(canvasStore).nodeSelected],
        [
          _directive_tooltip,
          {
            value: unref(t2)("commands.Comfy_Canvas_ToggleSelectedNodes_Bypass.label"),
            showDelay: 1e3
          },
          void 0,
          { top: true }
        ]
      ]);
    };
  }
});
const _hoisted_1$19 = { class: "relative" };
const _hoisted_2$B = { class: "flex items-center gap-1" };
const _hoisted_3$o = {
  key: 0,
  class: "color-picker-container absolute -top-10 left-1/2"
};
const _hoisted_4$i = ["data-testid"];
const _sfc_main$1n = /* @__PURE__ */ defineComponent({
  __name: "ColorPickerButton",
  setup(__props) {
    const { t: t2 } = useI18n();
    const canvasStore = useCanvasStore();
    const colorPaletteStore = useColorPaletteStore();
    const workflowStore = useWorkflowStore();
    const isLightTheme = computed(
      () => colorPaletteStore.completedActivePalette.light_theme
    );
    const toLightThemeColor = /* @__PURE__ */ __name((color) => adjustColor(color, { lightness: 0.5 }), "toLightThemeColor");
    const showColorPicker = ref(false);
    const NO_COLOR_OPTION = {
      name: "noColor",
      localizedName: t2("color.noColor"),
      value: {
        dark: LiteGraph.NODE_DEFAULT_BGCOLOR,
        light: toLightThemeColor(LiteGraph.NODE_DEFAULT_BGCOLOR)
      }
    };
    const colorOptions = [
      NO_COLOR_OPTION,
      ...Object.entries(LGraphCanvas.node_colors).map(([name, color]) => ({
        name,
        localizedName: t2(`color.${name}`),
        value: {
          dark: color.bgcolor,
          light: toLightThemeColor(color.bgcolor)
        }
      }))
    ];
    const selectedColorOption = ref(null);
    const applyColor = /* @__PURE__ */ __name((colorOption) => {
      const colorName = colorOption?.name ?? NO_COLOR_OPTION.name;
      const canvasColorOption = colorName === NO_COLOR_OPTION.name ? null : LGraphCanvas.node_colors[colorName];
      for (const item of canvasStore.selectedItems) {
        if (isColorable(item)) {
          item.setColorOption(canvasColorOption);
        }
      }
      canvasStore.canvas?.setDirty(true, true);
      currentColorOption.value = canvasColorOption;
      showColorPicker.value = false;
      workflowStore.activeWorkflow?.changeTracker.checkState();
    }, "applyColor");
    const currentColorOption = ref(null);
    const currentColor = computed(
      () => currentColorOption.value ? isLightTheme.value ? toLightThemeColor(currentColorOption.value?.bgcolor) : currentColorOption.value?.bgcolor : null
    );
    const localizedCurrentColorName = computed(() => {
      if (!currentColorOption.value?.bgcolor) return null;
      const colorOption = colorOptions.find(
        (option) => option.value.dark === currentColorOption.value?.bgcolor || option.value.light === currentColorOption.value?.bgcolor
      );
      return colorOption?.localizedName ?? NO_COLOR_OPTION.localizedName;
    });
    watch(
      () => canvasStore.selectedItems,
      (newSelectedItems) => {
        showColorPicker.value = false;
        selectedColorOption.value = null;
        currentColorOption.value = getItemsColorOption(newSelectedItems);
      }
    );
    return (_ctx, _cache) => {
      const _directive_tooltip = resolveDirective("tooltip");
      return openBlock(), createElementBlock("div", _hoisted_1$19, [
        withDirectives((openBlock(), createBlock(unref(Button), {
          severity: "secondary",
          text: "",
          onClick: _cache[0] || (_cache[0] = () => showColorPicker.value = !showColorPicker.value)
        }, {
          icon: withCtx(() => [
            createElementVNode("div", _hoisted_2$B, [
              createElementVNode("i", {
                class: "pi pi-circle-fill",
                style: normalizeStyle({ color: currentColor.value ?? "" })
              }, null, 4),
              _cache[1] || (_cache[1] = createElementVNode("i", {
                class: "pi pi-chevron-down",
                style: { fontSize: "0.5rem" }
              }, null, -1))
            ])
          ]),
          _: 1
        })), [
          [vShow, unref(canvasStore).nodeSelected || unref(canvasStore).groupSelected],
          [
            _directive_tooltip,
            {
              value: localizedCurrentColorName.value ?? unref(t2)("color.noColor"),
              showDelay: 512
            },
            void 0,
            { top: true }
          ]
        ]),
        showColorPicker.value ? (openBlock(), createElementBlock("div", _hoisted_3$o, [
          createVNode(unref(SelectButton), {
            "model-value": selectedColorOption.value,
            options: colorOptions,
            "option-label": "name",
            "data-key": "value",
            "onUpdate:modelValue": applyColor
          }, {
            option: withCtx(({ option }) => [
              withDirectives(createElementVNode("i", {
                class: "pi pi-circle-fill",
                style: normalizeStyle({
                  color: isLightTheme.value ? option.value.light : option.value.dark
                }),
                "data-testid": option.name
              }, null, 12, _hoisted_4$i), [
                [
                  _directive_tooltip,
                  option.localizedName,
                  void 0,
                  { top: true }
                ]
              ])
            ]),
            _: 1
          }, 8, ["model-value"])
        ])) : createCommentVNode("", true)
      ]);
    };
  }
});
const ColorPickerButton = /* @__PURE__ */ _export_sfc(_sfc_main$1n, [["__scopeId", "data-v-e0708a7e"]]);
const _hoisted_1$18 = {
  viewBox: "0 0 24 24",
  width: "1.2em",
  height: "1.2em"
};
function render$l(_ctx, _cache) {
  return openBlock(), createElementBlock("svg", _hoisted_1$18, _cache[0] || (_cache[0] = [
    createElementVNode("path", {
      fill: "none",
      stroke: "currentColor",
      "stroke-linecap": "round",
      "stroke-linejoin": "round",
      "stroke-width": "2",
      d: "m15 15l6 6m-6-6v4.8m0-4.8h4.8M9 19.8V15m0 0H4.2M9 15l-6 6M15 4.2V9m0 0h4.8M15 9l6-6M9 4.2V9m0 0H4.2M9 9L3 3"
    }, null, -1)
  ]));
}
__name(render$l, "render$l");
const __unplugin_components_1$4 = markRaw({ name: "lucide-shrink", render: render$l });
const _hoisted_1$17 = {
  viewBox: "0 0 24 24",
  width: "1.2em",
  height: "1.2em"
};
function render$k(_ctx, _cache) {
  return openBlock(), createElementBlock("svg", _hoisted_1$17, _cache[0] || (_cache[0] = [
    createElementVNode("path", {
      fill: "none",
      stroke: "currentColor",
      "stroke-linecap": "round",
      "stroke-linejoin": "round",
      "stroke-width": "2",
      d: "m15 15l6 6M15 9l6-6m0 13v5h-5m5-13V3h-5M3 16v5h5m-5 0l6-6M3 8V3h5m1 6L3 3"
    }, null, -1)
  ]));
}
__name(render$k, "render$k");
const __unplugin_components_0$7 = markRaw({ name: "lucide-expand", render: render$k });
const _sfc_main$1m = /* @__PURE__ */ defineComponent({
  __name: "ConvertToSubgraphButton",
  setup(__props) {
    const { t: t2 } = useI18n();
    const commandStore = useCommandStore();
    const canvasStore = useCanvasStore();
    const isUnpackVisible = computed(() => {
      return canvasStore.selectedItems?.length === 1 && canvasStore.selectedItems[0] instanceof SubgraphNode;
    });
    const isConvertVisible = computed(() => {
      return canvasStore.groupSelected || canvasStore.rerouteSelected || canvasStore.nodeSelected;
    });
    return (_ctx, _cache) => {
      const _component_i_lucide58expand = __unplugin_components_0$7;
      const _component_i_lucide58shrink = __unplugin_components_1$4;
      const _directive_tooltip = resolveDirective("tooltip");
      return isUnpackVisible.value ? withDirectives((openBlock(), createBlock(unref(Button), {
        key: 0,
        severity: "secondary",
        text: "",
        onClick: _cache[0] || (_cache[0] = () => unref(commandStore).execute("Comfy.Graph.UnpackSubgraph"))
      }, {
        icon: withCtx(() => [
          createVNode(_component_i_lucide58expand)
        ]),
        _: 1
      })), [
        [
          _directive_tooltip,
          {
            value: unref(t2)("commands.Comfy_Graph_UnpackSubgraph.label"),
            showDelay: 1e3
          },
          void 0,
          { top: true }
        ]
      ]) : isConvertVisible.value ? withDirectives((openBlock(), createBlock(unref(Button), {
        key: 1,
        severity: "secondary",
        text: "",
        onClick: _cache[1] || (_cache[1] = () => unref(commandStore).execute("Comfy.Graph.ConvertToSubgraph"))
      }, {
        icon: withCtx(() => [
          createVNode(_component_i_lucide58shrink)
        ]),
        _: 1
      })), [
        [
          _directive_tooltip,
          {
            value: unref(t2)("commands.Comfy_Graph_ConvertToSubgraph.label"),
            showDelay: 1e3
          },
          void 0,
          { top: true }
        ]
      ]) : createCommentVNode("", true);
    };
  }
});
const _sfc_main$1l = /* @__PURE__ */ defineComponent({
  __name: "DeleteButton",
  setup(__props) {
    const { t: t2 } = useI18n();
    const commandStore = useCommandStore();
    const canvasStore = useCanvasStore();
    const isDeletable = computed(
      () => canvasStore.selectedItems.some((x) => x.removable !== false)
    );
    return (_ctx, _cache) => {
      const _directive_tooltip = resolveDirective("tooltip");
      return withDirectives((openBlock(), createBlock(unref(Button), {
        severity: "danger",
        text: "",
        icon: "pi pi-trash",
        onClick: _cache[0] || (_cache[0] = () => unref(commandStore).execute("Comfy.Canvas.DeleteSelectedItems"))
      }, null, 512)), [
        [vShow, isDeletable.value],
        [
          _directive_tooltip,
          {
            value: unref(t2)("commands.Comfy_Canvas_DeleteSelectedItems.label"),
            showDelay: 1e3
          },
          void 0,
          { top: true }
        ]
      ]);
    };
  }
});
const _hoisted_1$16 = {
  viewBox: "0 0 24 24",
  width: "1.2em",
  height: "1.2em"
};
function render$j(_ctx, _cache) {
  return openBlock(), createElementBlock("svg", _hoisted_1$16, _cache[0] || (_cache[0] = [
    createElementVNode("path", {
      fill: "none",
      stroke: "currentColor",
      "stroke-linecap": "round",
      "stroke-linejoin": "round",
      "stroke-width": "2",
      d: "M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z"
    }, null, -1)
  ]));
}
__name(render$j, "render$j");
const __unplugin_components_1$3 = markRaw({ name: "lucide-play", render: render$j });
const _sfc_main$1k = /* @__PURE__ */ defineComponent({
  __name: "ExecuteButton",
  setup(__props) {
    const { t: t2 } = useI18n();
    const canvasStore = useCanvasStore();
    const commandStore = useCommandStore();
    const canvas = canvasStore.getCanvas();
    const buttonHovered = ref(false);
    const selectedOutputNodes = computed(
      () => canvasStore.selectedItems.filter(
        (item) => isLGraphNode(item) && item.constructor.nodeData?.output_node
      )
    );
    const isDisabled = computed(() => selectedOutputNodes.value.length === 0);
    function outputNodeStokeStyle() {
      if (this.selected && this.constructor.nodeData?.output_node && buttonHovered.value) {
        return { color: "orange", lineWidth: 2, padding: 10 };
      }
    }
    __name(outputNodeStokeStyle, "outputNodeStokeStyle");
    const handleMouseEnter = /* @__PURE__ */ __name(() => {
      buttonHovered.value = true;
      for (const node of selectedOutputNodes.value) {
        node.strokeStyles["outputNode"] = outputNodeStokeStyle;
      }
      canvas.setDirty(true);
    }, "handleMouseEnter");
    const handleMouseLeave = /* @__PURE__ */ __name(() => {
      buttonHovered.value = false;
      canvas.setDirty(true);
    }, "handleMouseLeave");
    const handleClick = /* @__PURE__ */ __name(async () => {
      await commandStore.execute("Comfy.QueueSelectedOutputNodes");
    }, "handleClick");
    return (_ctx, _cache) => {
      const _component_i_lucide58play = __unplugin_components_1$3;
      const _directive_tooltip = resolveDirective("tooltip");
      return withDirectives((openBlock(), createBlock(unref(Button), {
        severity: isDisabled.value ? "secondary" : "success",
        text: "",
        disabled: isDisabled.value,
        onMouseenter: _cache[0] || (_cache[0] = () => handleMouseEnter()),
        onMouseleave: _cache[1] || (_cache[1] = () => handleMouseLeave()),
        onClick: handleClick
      }, {
        default: withCtx(() => [
          createVNode(_component_i_lucide58play)
        ]),
        _: 1
      }, 8, ["severity", "disabled"])), [
        [vShow, unref(canvasStore).nodeSelected],
        [
          _directive_tooltip,
          {
            value: isDisabled.value ? unref(t2)("selectionToolbox.executeButton.disabledTooltip") : unref(t2)("selectionToolbox.executeButton.tooltip"),
            showDelay: 1e3
          },
          void 0,
          { top: true }
        ]
      ]);
    };
  }
});
const _sfc_main$1j = /* @__PURE__ */ defineComponent({
  __name: "ExtensionCommandButton",
  props: {
    command: {}
  },
  setup(__props) {
    const commandStore = useCommandStore();
    return (_ctx, _cache) => {
      const _directive_tooltip = resolveDirective("tooltip");
      return withDirectives((openBlock(), createBlock(unref(Button), {
        severity: "secondary",
        text: "",
        icon: typeof _ctx.command.icon === "function" ? _ctx.command.icon() : _ctx.command.icon,
        onClick: _cache[0] || (_cache[0] = () => unref(commandStore).execute(_ctx.command.id))
      }, null, 8, ["icon"])), [
        [
          _directive_tooltip,
          {
            value: unref(st)(`commands.${unref(normalizeI18nKey)(_ctx.command.id)}.label`, "") || void 0,
            showDelay: 1e3
          },
          void 0,
          { top: true }
        ]
      ]);
    };
  }
});
const _sfc_main$1i = /* @__PURE__ */ defineComponent({
  __name: "HelpButton",
  setup(__props) {
    const canvasStore = useCanvasStore();
    const nodeDefStore = useNodeDefStore();
    const sidebarTabStore = useSidebarTabStore();
    const nodeHelpStore = useNodeHelpStore();
    const { id: nodeLibraryTabId } = useNodeLibrarySidebarTab();
    const nodeDef = computed(() => {
      if (canvasStore.selectedItems.length !== 1) return null;
      const item = canvasStore.selectedItems[0];
      if (!isLGraphNode(item)) return null;
      return nodeDefStore.fromLGraphNode(item);
    });
    const showHelp = /* @__PURE__ */ __name(() => {
      const def = nodeDef.value;
      if (!def) return;
      if (sidebarTabStore.activeSidebarTabId !== nodeLibraryTabId) {
        sidebarTabStore.toggleSidebarTab(nodeLibraryTabId);
      }
      nodeHelpStore.openHelp(def);
    }, "showHelp");
    return (_ctx, _cache) => {
      const _directive_tooltip = resolveDirective("tooltip");
      return withDirectives((openBlock(), createBlock(unref(Button), {
        class: "help-button",
        text: "",
        icon: "pi pi-question-circle",
        severity: "secondary",
        onClick: showHelp
      }, null, 512)), [
        [vShow, nodeDef.value],
        [
          _directive_tooltip,
          {
            value: _ctx.$t("g.help"),
            showDelay: 1e3
          },
          void 0,
          { top: true }
        ]
      ]);
    };
  }
});
const _sfc_main$1h = /* @__PURE__ */ defineComponent({
  __name: "Load3DViewerButton",
  setup(__props) {
    const commandStore = useCommandStore();
    const canvasStore = useCanvasStore();
    const is3DNode = computed(() => {
      const enable3DViewer = useSettingStore().get("Comfy.Load3D.3DViewerEnable");
      const nodes = canvasStore.selectedItems.filter(isLGraphNode);
      return nodes.length === 1 && nodes.some(isLoad3dNode) && enable3DViewer;
    });
    const open3DViewer = /* @__PURE__ */ __name(() => {
      void commandStore.execute("Comfy.3DViewer.Open3DViewer");
    }, "open3DViewer");
    return (_ctx, _cache) => {
      const _directive_tooltip = resolveDirective("tooltip");
      return withDirectives((openBlock(), createBlock(unref(Button), {
        severity: "secondary",
        text: "",
        icon: "pi pi-pencil",
        onClick: open3DViewer
      }, null, 512)), [
        [vShow, is3DNode.value],
        [
          _directive_tooltip,
          {
            value: unref(t)("commands.Comfy_3DViewer_Open3DViewer.label"),
            showDelay: 1e3
          },
          void 0,
          { top: true }
        ]
      ]);
    };
  }
});
const _sfc_main$1g = /* @__PURE__ */ defineComponent({
  __name: "MaskEditorButton",
  setup(__props) {
    const commandStore = useCommandStore();
    const canvasStore = useCanvasStore();
    const isSingleImageNode = computed(() => {
      const { selectedItems } = canvasStore;
      const item = selectedItems[0];
      return selectedItems.length === 1 && isLGraphNode(item) && isImageNode(item);
    });
    const openMaskEditor = /* @__PURE__ */ __name(() => {
      void commandStore.execute("Comfy.MaskEditor.OpenMaskEditor");
    }, "openMaskEditor");
    return (_ctx, _cache) => {
      const _directive_tooltip = resolveDirective("tooltip");
      return withDirectives((openBlock(), createBlock(unref(Button), {
        severity: "secondary",
        text: "",
        icon: "pi pi-pencil",
        onClick: openMaskEditor
      }, null, 512)), [
        [vShow, isSingleImageNode.value],
        [
          _directive_tooltip,
          {
            value: unref(t)("commands.Comfy_MaskEditor_OpenMaskEditor.label"),
            showDelay: 1e3
          },
          void 0,
          { top: true }
        ]
      ]);
    };
  }
});
const _sfc_main$1f = /* @__PURE__ */ defineComponent({
  __name: "PinButton",
  setup(__props) {
    const { t: t2 } = useI18n();
    const commandStore = useCommandStore();
    const canvasStore = useCanvasStore();
    return (_ctx, _cache) => {
      const _directive_tooltip = resolveDirective("tooltip");
      return withDirectives((openBlock(), createBlock(unref(Button), {
        severity: "secondary",
        text: "",
        icon: "pi pi-thumbtack",
        onClick: _cache[0] || (_cache[0] = () => unref(commandStore).execute("Comfy.Canvas.ToggleSelected.Pin"))
      }, null, 512)), [
        [vShow, unref(canvasStore).nodeSelected || unref(canvasStore).groupSelected],
        [
          _directive_tooltip,
          {
            value: unref(t2)("commands.Comfy_Canvas_ToggleSelectedNodes_Pin.label"),
            showDelay: 1e3
          },
          void 0,
          { top: true }
        ]
      ]);
    };
  }
});
const isRefreshableWidget = /* @__PURE__ */ __name((widget) => widget != null && typeof widget === "object" && "refresh" in widget && typeof widget.refresh === "function", "isRefreshableWidget");
const useRefreshableSelection = /* @__PURE__ */ __name(() => {
  const graphStore = useCanvasStore();
  const selectedNodes = ref([]);
  watchEffect(() => {
    selectedNodes.value = graphStore.selectedItems.filter(isLGraphNode);
  });
  const refreshableWidgets = computed(
    () => selectedNodes.value.flatMap((node) => {
      if (!node.widgets) return [];
      const items = [];
      for (const widget of node.widgets) {
        if (isRefreshableWidget(widget)) {
          items.push(widget);
        }
      }
      return items;
    })
  );
  const isRefreshable = computed(() => refreshableWidgets.value.length > 0);
  async function refreshSelected() {
    if (!isRefreshable.value) return;
    await Promise.all(refreshableWidgets.value.map((item) => item.refresh()));
  }
  __name(refreshSelected, "refreshSelected");
  return {
    isRefreshable,
    refreshSelected
  };
}, "useRefreshableSelection");
const _sfc_main$1e = /* @__PURE__ */ defineComponent({
  __name: "RefreshSelectionButton",
  setup(__props) {
    const { isRefreshable, refreshSelected } = useRefreshableSelection();
    return (_ctx, _cache) => {
      return withDirectives((openBlock(), createBlock(unref(Button), {
        severity: "info",
        text: "",
        icon: "pi pi-refresh",
        onClick: unref(refreshSelected)
      }, null, 8, ["onClick"])), [
        [vShow, unref(isRefreshable)]
      ]);
    };
  }
});
function useSelectionToolboxPosition(toolboxRef) {
  const canvasStore = useCanvasStore();
  const lgCanvas = canvasStore.getCanvas();
  const { getSelectableItems } = useSelectedLiteGraphItems();
  const worldPosition = ref({ x: 0, y: 0 });
  const visible = ref(false);
  const updateSelectionBounds = /* @__PURE__ */ __name(() => {
    const selectableItems = getSelectableItems();
    if (!selectableItems.size) {
      visible.value = false;
      return;
    }
    visible.value = true;
    const bounds = createBounds(selectableItems);
    if (!bounds) {
      return;
    }
    const [xBase, y, width] = bounds;
    worldPosition.value = {
      x: xBase + width / 2,
      y
    };
    updateTransform();
  }, "updateSelectionBounds");
  const updateTransform = /* @__PURE__ */ __name(() => {
    if (!visible.value) return;
    const { scale, offset } = lgCanvas.ds;
    const canvasRect = lgCanvas.canvas.getBoundingClientRect();
    const screenX = (worldPosition.value.x + offset[0]) * scale + canvasRect.left;
    const screenY = (worldPosition.value.y + offset[1]) * scale + canvasRect.top;
    if (toolboxRef.value) {
      toolboxRef.value.style.setProperty("--tb-x", `${screenX}px`);
      toolboxRef.value.style.setProperty("--tb-y", `${screenY}px`);
    }
  }, "updateTransform");
  const { startSync, stopSync } = useCanvasTransformSync$1(updateTransform, {
    autoStart: false
  });
  watch(
    () => canvasStore.getCanvas().state.selectionChanged,
    (changed) => {
      if (changed) {
        updateSelectionBounds();
        canvasStore.getCanvas().state.selectionChanged = false;
        if (visible.value) {
          startSync();
        } else {
          stopSync();
        }
      }
    },
    { immediate: true }
  );
  watch(
    () => canvasStore.canvas?.state?.draggingItems,
    (dragging) => {
      if (dragging) {
        visible.value = false;
      } else {
        requestAnimationFrame(() => {
          updateSelectionBounds();
        });
      }
    }
  );
  return {
    visible
  };
}
__name(useSelectionToolboxPosition, "useSelectionToolboxPosition");
const _sfc_main$1d = /* @__PURE__ */ defineComponent({
  __name: "SelectionToolbox",
  setup(__props) {
    const commandStore = useCommandStore();
    const canvasStore = useCanvasStore();
    const extensionService = useExtensionService();
    const canvasInteractions = useCanvasInteractions();
    const toolboxRef = ref();
    const { visible } = useSelectionToolboxPosition(toolboxRef);
    const extensionToolboxCommands = computed(() => {
      const commandIds = new Set(
        canvasStore.selectedItems.map(
          (item) => extensionService.invokeExtensions("getSelectionToolboxCommands", item).flat()
        ).flat()
      );
      return Array.from(commandIds).map((commandId) => commandStore.getCommand(commandId)).filter((command) => command !== void 0);
    });
    return (_ctx, _cache) => {
      return openBlock(), createElementBlock("div", {
        ref_key: "toolboxRef",
        ref: toolboxRef,
        style: { "transform": "translate(var(--tb-x), var(--tb-y))" },
        class: "fixed left-0 top-0 z-40"
      }, [
        createVNode(Transition, { name: "slide-up" }, {
          default: withCtx(() => [
            unref(visible) ? (openBlock(), createBlock(unref(Panel), {
              key: 0,
              class: "rounded-lg selection-toolbox",
              pt: {
                header: "hidden",
                content: "p-0 flex flex-row"
              },
              onWheel: unref(canvasInteractions).handleWheel
            }, {
              default: withCtx(() => [
                createVNode(_sfc_main$1k),
                createVNode(ColorPickerButton),
                createVNode(_sfc_main$1o),
                createVNode(_sfc_main$1f),
                createVNode(_sfc_main$1h),
                createVNode(_sfc_main$1g),
                createVNode(_sfc_main$1m),
                createVNode(_sfc_main$1l),
                createVNode(_sfc_main$1e),
                (openBlock(true), createElementBlock(Fragment, null, renderList(extensionToolboxCommands.value, (command) => {
                  return openBlock(), createBlock(_sfc_main$1j, {
                    key: command.id,
                    command
                  }, null, 8, ["command"]);
                }), 128)),
                createVNode(_sfc_main$1i)
              ]),
              _: 1
            }, 8, ["onWheel"])) : createCommentVNode("", true)
          ]),
          _: 1
        })
      ], 512);
    };
  }
});
const SelectionToolbox = /* @__PURE__ */ _export_sfc(_sfc_main$1d, [["__scopeId", "data-v-9f1bfe4c"]]);
const _sfc_main$1c = /* @__PURE__ */ defineComponent({
  __name: "TitleEditor",
  setup(__props) {
    const settingStore = useSettingStore();
    const showInput = ref(false);
    const editedTitle = ref("");
    const { style: inputPositionStyle, updatePosition } = useAbsolutePosition();
    const inputFontStyle = ref({});
    const inputStyle = computed(() => ({
      ...inputPositionStyle.value,
      ...inputFontStyle.value
    }));
    const titleEditorStore = useTitleEditorStore();
    const canvasStore = useCanvasStore();
    const previousCanvasDraggable = ref(true);
    const onEdit = /* @__PURE__ */ __name((newValue) => {
      if (titleEditorStore.titleEditorTarget && newValue.trim() !== "") {
        const trimmedTitle = newValue.trim();
        titleEditorStore.titleEditorTarget.title = trimmedTitle;
        const target = titleEditorStore.titleEditorTarget;
        if (target instanceof LGraphNode && target.isSubgraphNode?.()) {
          target.subgraph.name = trimmedTitle;
        }
        app.graph.setDirtyCanvas(true, true);
      }
      showInput.value = false;
      titleEditorStore.titleEditorTarget = null;
      canvasStore.canvas.allow_dragcanvas = previousCanvasDraggable.value;
    }, "onEdit");
    watch(
      () => titleEditorStore.titleEditorTarget,
      (target) => {
        if (target === null) {
          return;
        }
        editedTitle.value = target.title;
        showInput.value = true;
        const canvas = canvasStore.canvas;
        previousCanvasDraggable.value = canvas.allow_dragcanvas;
        canvas.allow_dragcanvas = false;
        const scale = canvas.ds.scale;
        if (target instanceof LGraphGroup) {
          const group = target;
          updatePosition({
            pos: group.pos,
            size: [group.size[0], group.titleHeight]
          });
          inputFontStyle.value = { fontSize: `${group.font_size * scale}px` };
        } else if (target instanceof LGraphNode) {
          const node = target;
          const [x, y] = node.getBounding();
          updatePosition({
            pos: [x, y],
            size: [node.width, LiteGraph.NODE_TITLE_HEIGHT]
          });
          inputFontStyle.value = { fontSize: `${12 * scale}px` };
        }
      }
    );
    const canvasEventHandler = /* @__PURE__ */ __name((event) => {
      if (event.detail.subType === "group-double-click") {
        if (!settingStore.get("Comfy.Group.DoubleClickTitleToEdit")) {
          return;
        }
        const group = event.detail.group;
        const [_, y] = group.pos;
        const e = event.detail.originalEvent;
        const relativeY = e.canvasY - y;
        if (relativeY <= group.titleHeight) {
          titleEditorStore.titleEditorTarget = group;
        }
      } else if (event.detail.subType === "node-double-click") {
        if (!settingStore.get("Comfy.Node.DoubleClickTitleToEdit")) {
          return;
        }
        const node = event.detail.node;
        const [_, y] = node.pos;
        const e = event.detail.originalEvent;
        const relativeY = e.canvasY - y;
        if (relativeY <= 0) {
          titleEditorStore.titleEditorTarget = node;
        }
      }
    }, "canvasEventHandler");
    useEventListener(document, "litegraph:canvas", canvasEventHandler);
    return (_ctx, _cache) => {
      return showInput.value ? (openBlock(), createElementBlock("div", {
        key: 0,
        class: "group-title-editor node-title-editor",
        style: normalizeStyle(inputStyle.value)
      }, [
        createVNode(EditableText, {
          "is-editing": showInput.value,
          "model-value": editedTitle.value,
          onEdit
        }, null, 8, ["is-editing", "model-value"])
      ], 4)) : createCommentVNode("", true);
    };
  }
});
const TitleEditor = /* @__PURE__ */ _export_sfc(_sfc_main$1c, [["__scopeId", "data-v-e5829fcb"]]);
const useTransformState = /* @__PURE__ */ __name(() => {
  const camera = reactive({
    x: 0,
    y: 0,
    z: 1
  });
  const transformStyle = computed(() => ({
    transform: `scale(${camera.z}) translate(${camera.x}px, ${camera.y}px)`,
    transformOrigin: "0 0"
  }));
  const syncWithCanvas = /* @__PURE__ */ __name((canvas) => {
    if (!canvas || !canvas.ds) return;
    camera.x = canvas.ds.offset[0];
    camera.y = canvas.ds.offset[1];
    camera.z = canvas.ds.scale || 1;
  }, "syncWithCanvas");
  const canvasToScreen = /* @__PURE__ */ __name((point) => {
    return {
      x: point.x * camera.z + camera.x,
      y: point.y * camera.z + camera.y
    };
  }, "canvasToScreen");
  const screenToCanvas = /* @__PURE__ */ __name((point) => {
    return {
      x: (point.x - camera.x) / camera.z,
      y: (point.y - camera.y) / camera.z
    };
  }, "screenToCanvas");
  const getNodeScreenBounds = /* @__PURE__ */ __name((pos, size) => {
    const topLeft = canvasToScreen({ x: pos[0], y: pos[1] });
    const width = size[0] * camera.z;
    const height = size[1] * camera.z;
    return new DOMRect(topLeft.x, topLeft.y, width, height);
  }, "getNodeScreenBounds");
  const calculateAdjustedMargin = /* @__PURE__ */ __name((baseMargin) => {
    if (camera.z < 0.1) return Math.min(baseMargin * 5, 2);
    if (camera.z > 3) return Math.max(baseMargin * 0.5, 0.05);
    return baseMargin;
  }, "calculateAdjustedMargin");
  const isNodeTooSmall = /* @__PURE__ */ __name((nodeSize) => {
    const nodeScreenSize = Math.max(nodeSize[0], nodeSize[1]) * camera.z;
    return nodeScreenSize < 4;
  }, "isNodeTooSmall");
  const getExpandedViewportBounds = /* @__PURE__ */ __name((viewport, margin) => {
    const marginX = viewport.width * margin;
    const marginY = viewport.height * margin;
    return {
      left: -marginX,
      right: viewport.width + marginX,
      top: -marginY,
      bottom: viewport.height + marginY
    };
  }, "getExpandedViewportBounds");
  const testViewportIntersection = /* @__PURE__ */ __name((screenPos, nodeSize, bounds) => {
    const nodeRight = screenPos.x + nodeSize[0] * camera.z;
    const nodeBottom = screenPos.y + nodeSize[1] * camera.z;
    return !(nodeRight < bounds.left || screenPos.x > bounds.right || nodeBottom < bounds.top || screenPos.y > bounds.bottom);
  }, "testViewportIntersection");
  const isNodeInViewport = /* @__PURE__ */ __name((nodePos, nodeSize, viewport, margin = 0.2) => {
    if (isNodeTooSmall(nodeSize)) return false;
    const screenPos = canvasToScreen({ x: nodePos[0], y: nodePos[1] });
    const adjustedMargin = calculateAdjustedMargin(margin);
    const bounds = getExpandedViewportBounds(viewport, adjustedMargin);
    return testViewportIntersection(screenPos, nodeSize, bounds);
  }, "isNodeInViewport");
  const getViewportBounds = /* @__PURE__ */ __name((viewport, margin = 0.2) => {
    const marginX = viewport.width * margin;
    const marginY = viewport.height * margin;
    const topLeft = screenToCanvas({ x: -marginX, y: -marginY });
    const bottomRight = screenToCanvas({
      x: viewport.width + marginX,
      y: viewport.height + marginY
    });
    return {
      x: topLeft.x,
      y: topLeft.y,
      width: bottomRight.x - topLeft.x,
      height: bottomRight.y - topLeft.y
    };
  }, "getViewportBounds");
  return {
    camera: readonly(camera),
    transformStyle,
    syncWithCanvas,
    canvasToScreen,
    screenToCanvas,
    getNodeScreenBounds,
    isNodeInViewport,
    getViewportBounds
  };
}, "useTransformState");
function useCanvasTransformSync(canvas, syncFn, callbacks = {}, options = {}) {
  const { autoStart = true } = options;
  const { onStart, onUpdate, onStop } = callbacks;
  const isActive = ref(false);
  let rafId2 = null;
  const startSync = /* @__PURE__ */ __name(() => {
    if (isActive.value || !canvas) return;
    isActive.value = true;
    onStart?.();
    const sync = /* @__PURE__ */ __name(() => {
      if (!isActive.value || !canvas) return;
      try {
        const startTime = performance.now();
        syncFn(canvas);
        const endTime = performance.now();
        onUpdate?.(endTime - startTime);
      } catch (error) {
        console.warn("Canvas transform sync error:", error);
      }
      rafId2 = requestAnimationFrame(sync);
    }, "sync");
    sync();
  }, "startSync");
  const stopSync = /* @__PURE__ */ __name(() => {
    if (!isActive.value) return;
    if (rafId2 !== null) {
      cancelAnimationFrame(rafId2);
      rafId2 = null;
    }
    isActive.value = false;
    onStop?.();
  }, "stopSync");
  if (autoStart && canvas) {
    startSync();
  }
  onUnmounted(() => {
    stopSync();
  });
  return {
    isActive,
    startSync,
    stopSync
  };
}
__name(useCanvasTransformSync, "useCanvasTransformSync");
function useTransformSettling(target, options = {}) {
  const {
    settleDelay = 200,
    trackPan = false,
    pointerMoveThrottle = 16,
    passive = true
  } = options;
  const isTransforming = ref(false);
  let isPanning = false;
  const markTransformActive = /* @__PURE__ */ __name(() => {
    isTransforming.value = true;
  }, "markTransformActive");
  const markTransformSettled = useDebounceFn(() => {
    isTransforming.value = false;
  }, settleDelay);
  const handleTransformEvent = /* @__PURE__ */ __name(() => {
    markTransformActive();
    void markTransformSettled();
  }, "handleTransformEvent");
  const handleWheel = /* @__PURE__ */ __name(() => {
    handleTransformEvent();
  }, "handleWheel");
  const handlePointerDown = /* @__PURE__ */ __name(() => {
    if (trackPan) {
      isPanning = true;
      handleTransformEvent();
    }
  }, "handlePointerDown");
  const handlePointerMove = trackPan ? useThrottleFn(() => {
    if (isPanning) {
      handleTransformEvent();
    }
  }, pointerMoveThrottle) : void 0;
  const handlePointerEnd = /* @__PURE__ */ __name(() => {
    if (trackPan) {
      isPanning = false;
    }
  }, "handlePointerEnd");
  useEventListener(target, "wheel", handleWheel, {
    capture: true,
    passive
  });
  if (trackPan) {
    useEventListener(target, "pointerdown", handlePointerDown, {
      capture: true
    });
    if (handlePointerMove) {
      useEventListener(target, "pointermove", handlePointerMove, {
        capture: true,
        passive
      });
    }
    useEventListener(target, "pointerup", handlePointerEnd, {
      capture: true
    });
    useEventListener(target, "pointercancel", handlePointerEnd, {
      capture: true
    });
  }
  return {
    isTransforming
  };
}
__name(useTransformSettling, "useTransformSettling");
const _sfc_main$1b = /* @__PURE__ */ defineComponent({
  __name: "TransformPane",
  props: {
    canvas: {}
  },
  emits: ["rafStatusChange", "transformUpdate"],
  setup(__props, { emit: __emit }) {
    const props = __props;
    const {
      camera,
      transformStyle,
      syncWithCanvas,
      canvasToScreen,
      screenToCanvas,
      isNodeInViewport
    } = useTransformState();
    const canvasElement = computed(() => props.canvas?.canvas);
    const { isTransforming: isInteracting } = useTransformSettling(canvasElement, {
      settleDelay: 200,
      trackPan: true
    });
    provide("transformState", {
      camera,
      canvasToScreen,
      screenToCanvas,
      isNodeInViewport
    });
    const handlePointerDown = /* @__PURE__ */ __name((event) => {
      const target = event.target;
      const nodeElement = target.closest("[data-node-id]");
      if (nodeElement) {
      }
    }, "handlePointerDown");
    const emit = __emit;
    useCanvasTransformSync(props.canvas, syncWithCanvas, {
      onStart: /* @__PURE__ */ __name(() => emit("rafStatusChange", true), "onStart"),
      onUpdate: /* @__PURE__ */ __name((duration) => emit("transformUpdate", duration), "onUpdate"),
      onStop: /* @__PURE__ */ __name(() => emit("rafStatusChange", false), "onStop")
    });
    return (_ctx, _cache) => {
      return openBlock(), createElementBlock("div", {
        class: normalizeClass(["transform-pane", { "transform-pane--interacting": unref(isInteracting) }]),
        style: normalizeStyle(unref(transformStyle)),
        onPointerdown: handlePointerDown
      }, [
        renderSlot(_ctx.$slots, "default", {}, void 0, true)
      ], 38);
    };
  }
});
const TransformPane = /* @__PURE__ */ _export_sfc(_sfc_main$1b, [["__scopeId", "data-v-cbf29e5f"]]);
const useSearchBoxStore = defineStore("searchBox", () => {
  const settingStore = useSettingStore();
  const { x, y } = useMouse();
  const newSearchBoxEnabled = computed(
    () => settingStore.get("Comfy.NodeSearchBoxImpl") === "default"
  );
  const popoverRef = shallowRef(null);
  function setPopoverRef(popover) {
    popoverRef.value = popover;
  }
  __name(setPopoverRef, "setPopoverRef");
  const visible = ref(false);
  function toggleVisible() {
    if (newSearchBoxEnabled.value) {
      visible.value = !visible.value;
      return;
    }
    if (!popoverRef.value) return;
    popoverRef.value.showSearchBox(
      new MouseEvent("click", {
        clientX: x.value,
        clientY: y.value,
        // @ts-expect-error layerY is a nonstandard property
        layerY: y.value
      })
    );
  }
  __name(toggleVisible, "toggleVisible");
  return {
    newSearchBoxEnabled,
    setPopoverRef,
    toggleVisible,
    visible
  };
});
const _sfc_main$1a = {
  name: "AutoCompletePlus",
  extends: AutoComplete,
  emits: ["focused-option-changed"],
  data() {
    return {
      // Flag to determine if IME is active
      isComposing: false
    };
  },
  mounted() {
    if (typeof AutoComplete.mounted === "function") {
      AutoComplete.mounted.call(this);
    }
    const inputEl = this.$el.querySelector("input");
    if (inputEl) {
      inputEl.addEventListener("compositionstart", () => {
        this.isComposing = true;
      });
      inputEl.addEventListener("compositionend", () => {
        this.isComposing = false;
      });
    }
    this.$watch(
      () => this.focusedOptionIndex,
      (newVal, oldVal) => {
        this.$emit("focused-option-changed", newVal);
      }
    );
  },
  methods: {
    // Override onKeyDown to block Enter when IME is active
    onKeyDown(event) {
      if (event.key === "Enter" && this.isComposing) {
        event.preventDefault();
        event.stopPropagation();
        return;
      }
      AutoComplete.methods.onKeyDown.call(this, event);
    }
  }
};
const _hoisted_1$15 = { class: "option-container flex justify-between items-center px-2 py-0 cursor-pointer overflow-hidden w-full" };
const _hoisted_2$A = { class: "option-display-name font-semibold flex flex-col" };
const _hoisted_3$n = { key: 0 };
const _hoisted_4$h = ["innerHTML"];
const _hoisted_5$a = ["innerHTML"];
const _hoisted_6$8 = {
  key: 0,
  class: "option-category font-light text-sm text-muted overflow-hidden text-ellipsis whitespace-nowrap"
};
const _hoisted_7$6 = { class: "option-badges" };
const _sfc_main$19 = /* @__PURE__ */ defineComponent({
  __name: "NodeSearchItem",
  props: {
    nodeDef: {},
    currentQuery: {}
  },
  setup(__props) {
    const settingStore = useSettingStore();
    const showCategory = computed(
      () => settingStore.get("Comfy.NodeSearchBoxImpl.ShowCategory")
    );
    const showIdName = computed(
      () => settingStore.get("Comfy.NodeSearchBoxImpl.ShowIdName")
    );
    const showNodeFrequency = computed(
      () => settingStore.get("Comfy.NodeSearchBoxImpl.ShowNodeFrequency")
    );
    const nodeFrequencyStore = useNodeFrequencyStore();
    const nodeFrequency = computed(
      () => nodeFrequencyStore.getNodeFrequency(props.nodeDef)
    );
    const nodeBookmarkStore = useNodeBookmarkStore();
    const isBookmarked = computed(
      () => nodeBookmarkStore.isBookmarked(props.nodeDef)
    );
    const props = __props;
    return (_ctx, _cache) => {
      return openBlock(), createElementBlock("div", _hoisted_1$15, [
        createElementVNode("div", _hoisted_2$A, [
          createElementVNode("div", null, [
            isBookmarked.value ? (openBlock(), createElementBlock("span", _hoisted_3$n, _cache[0] || (_cache[0] = [
              createElementVNode("i", { class: "pi pi-bookmark-fill text-sm mr-1" }, null, -1)
            ]))) : createCommentVNode("", true),
            createElementVNode("span", {
              innerHTML: unref(highlightQuery)(_ctx.nodeDef.display_name, _ctx.currentQuery)
            }, null, 8, _hoisted_4$h),
            _cache[1] || (_cache[1] = createElementVNode("span", null, " ", -1)),
            showIdName.value ? (openBlock(), createBlock(unref(Tag), {
              key: 1,
              severity: "secondary"
            }, {
              default: withCtx(() => [
                createElementVNode("span", {
                  innerHTML: unref(highlightQuery)(_ctx.nodeDef.name, _ctx.currentQuery)
                }, null, 8, _hoisted_5$a)
              ]),
              _: 1
            })) : createCommentVNode("", true)
          ]),
          showCategory.value ? (openBlock(), createElementBlock("div", _hoisted_6$8, toDisplayString(_ctx.nodeDef.category.replaceAll("/", " > ")), 1)) : createCommentVNode("", true)
        ]),
        createElementVNode("div", _hoisted_7$6, [
          _ctx.nodeDef.experimental ? (openBlock(), createBlock(unref(Tag), {
            key: 0,
            value: _ctx.$t("g.experimental"),
            severity: "primary"
          }, null, 8, ["value"])) : createCommentVNode("", true),
          _ctx.nodeDef.deprecated ? (openBlock(), createBlock(unref(Tag), {
            key: 1,
            value: _ctx.$t("g.deprecated"),
            severity: "danger"
          }, null, 8, ["value"])) : createCommentVNode("", true),
          showNodeFrequency.value && nodeFrequency.value > 0 ? (openBlock(), createBlock(unref(Tag), {
            key: 2,
            value: unref(formatNumberWithSuffix)(nodeFrequency.value, { roundToInt: true }),
            severity: "secondary"
          }, null, 8, ["value"])) : createCommentVNode("", true),
          _ctx.nodeDef.nodeSource.type !== unref(NodeSourceType).Unknown ? (openBlock(), createBlock(unref(Chip), {
            key: 3,
            class: "text-sm font-light"
          }, {
            default: withCtx(() => [
              createTextVNode(toDisplayString(_ctx.nodeDef.nodeSource.displayText), 1)
            ]),
            _: 1
          })) : createCommentVNode("", true)
        ])
      ]);
    };
  }
});
const NodeSearchItem = /* @__PURE__ */ _export_sfc(_sfc_main$19, [["__scopeId", "data-v-2f72abbe"]]);
const _hoisted_1$14 = { class: "comfy-vue-node-search-container flex justify-center items-center w-full min-w-96" };
const _hoisted_2$z = {
  key: 0,
  class: "comfy-vue-node-preview-container absolute left-[-350px] top-[50px]"
};
const _hoisted_3$m = { class: "_dialog-body" };
const _sfc_main$18 = /* @__PURE__ */ defineComponent({
  __name: "NodeSearchBox",
  props: {
    filters: {},
    searchLimit: { default: 64 }
  },
  emits: ["addFilter", "removeFilter", "addNode"],
  setup(__props, { emit: __emit }) {
    const settingStore = useSettingStore();
    const { t: t2 } = useI18n();
    const enableNodePreview = computed(
      () => settingStore.get("Comfy.NodeSearchBoxImpl.NodePreview")
    );
    const nodeSearchFilterVisible = ref(false);
    const inputId = `comfy-vue-node-search-box-input-${Math.random()}`;
    const suggestions = ref([]);
    const hoveredSuggestion = ref(null);
    const currentQuery = ref("");
    const placeholder = computed(() => {
      return __props.filters.length === 0 ? t2("g.searchNodes") + "..." : "";
    });
    const nodeDefStore = useNodeDefStore();
    const nodeFrequencyStore = useNodeFrequencyStore();
    const search = /* @__PURE__ */ __name((query) => {
      const queryIsEmpty = query === "" && __props.filters.length === 0;
      currentQuery.value = query;
      suggestions.value = queryIsEmpty ? nodeFrequencyStore.topNodeDefs : [
        ...nodeDefStore.nodeSearchService.searchNode(query, __props.filters, {
          limit: __props.searchLimit
        })
      ];
    }, "search");
    const emit = __emit;
    let inputElement = null;
    const reFocusInput = /* @__PURE__ */ __name(async () => {
      inputElement ??= document.getElementById(inputId);
      if (inputElement) {
        inputElement.blur();
        await nextTick(() => inputElement?.focus());
      }
    }, "reFocusInput");
    onMounted(reFocusInput);
    const onAddFilter = /* @__PURE__ */ __name((filterAndValue) => {
      nodeSearchFilterVisible.value = false;
      emit("addFilter", filterAndValue);
    }, "onAddFilter");
    const onRemoveFilter = /* @__PURE__ */ __name(async (event, filterAndValue) => {
      event.stopPropagation();
      event.preventDefault();
      emit("removeFilter", filterAndValue);
      await reFocusInput();
    }, "onRemoveFilter");
    const setHoverSuggestion = /* @__PURE__ */ __name((index) => {
      if (index === -1) {
        hoveredSuggestion.value = null;
        return;
      }
      const value = suggestions.value[index];
      hoveredSuggestion.value = value;
    }, "setHoverSuggestion");
    return (_ctx, _cache) => {
      return openBlock(), createElementBlock("div", _hoisted_1$14, [
        enableNodePreview.value ? (openBlock(), createElementBlock("div", _hoisted_2$z, [
          hoveredSuggestion.value ? (openBlock(), createBlock(NodePreview, {
            key: hoveredSuggestion.value?.name || "",
            "node-def": hoveredSuggestion.value
          }, null, 8, ["node-def"])) : createCommentVNode("", true)
        ])) : createCommentVNode("", true),
        createVNode(unref(Button), {
          icon: "pi pi-filter",
          severity: "secondary",
          class: "filter-button z-10",
          onClick: _cache[0] || (_cache[0] = ($event) => nodeSearchFilterVisible.value = true)
        }),
        createVNode(unref(Dialog), {
          visible: nodeSearchFilterVisible.value,
          "onUpdate:visible": _cache[1] || (_cache[1] = ($event) => nodeSearchFilterVisible.value = $event),
          class: "min-w-96",
          "dismissable-mask": "",
          modal: "",
          onHide: reFocusInput
        }, {
          header: withCtx(() => [
            createElementVNode("h3", null, toDisplayString(_ctx.$t("g.addNodeFilterCondition")), 1)
          ]),
          default: withCtx(() => [
            createElementVNode("div", _hoisted_3$m, [
              createVNode(NodeSearchFilter, { onAddFilter })
            ])
          ]),
          _: 1
        }, 8, ["visible"]),
        createVNode(_sfc_main$1a, {
          "model-value": _ctx.filters,
          class: "comfy-vue-node-search-box z-10 grow",
          "scroll-height": "40vh",
          placeholder: placeholder.value,
          "input-id": inputId,
          "append-to": "self",
          suggestions: suggestions.value,
          "min-length": 0,
          delay: 100,
          loading: !unref(nodeFrequencyStore).isLoaded,
          "complete-on-focus": "",
          "auto-option-focus": "",
          "force-selection": "",
          multiple: "",
          "option-label": "display_name",
          onComplete: _cache[2] || (_cache[2] = ($event) => search($event.query)),
          onOptionSelect: _cache[3] || (_cache[3] = ($event) => emit("addNode", $event.value)),
          onFocusedOptionChanged: _cache[4] || (_cache[4] = ($event) => setHoverSuggestion($event))
        }, {
          option: withCtx(({ option }) => [
            createVNode(NodeSearchItem, {
              "node-def": option,
              "current-query": currentQuery.value
            }, null, 8, ["node-def", "current-query"])
          ]),
          chip: withCtx(({ value }) => [
            value.filterDef && value.value ? (openBlock(), createBlock(SearchFilterChip, {
              key: `${value.filterDef.id}-${value.value}`,
              text: value.value,
              badge: value.filterDef.invokeSequence.toUpperCase(),
              "badge-class": value.filterDef.invokeSequence + "-badge",
              onRemove: /* @__PURE__ */ __name(($event) => onRemoveFilter(
                $event,
                value
              ), "onRemove")
            }, null, 8, ["text", "badge", "badge-class", "onRemove"])) : createCommentVNode("", true)
          ]),
          _: 1
        }, 8, ["model-value", "placeholder", "suggestions", "loading"])
      ]);
    };
  }
});
const _sfc_main$17 = /* @__PURE__ */ defineComponent({
  __name: "NodeSearchBoxPopover",
  setup(__props, { expose: __expose }) {
    let triggerEvent = null;
    let listenerController = null;
    let disconnectOnReset = false;
    const settingStore = useSettingStore();
    const searchBoxStore = useSearchBoxStore();
    const litegraphService = useLitegraphService();
    const { visible, newSearchBoxEnabled } = storeToRefs(searchBoxStore);
    const dismissable = ref(true);
    const getNewNodeLocation = /* @__PURE__ */ __name(() => {
      return triggerEvent ? [triggerEvent.canvasX, triggerEvent.canvasY] : litegraphService.getCanvasCenter();
    }, "getNewNodeLocation");
    const nodeFilters = ref([]);
    const addFilter = /* @__PURE__ */ __name((filter) => {
      nodeFilters.value.push(filter);
    }, "addFilter");
    const removeFilter = /* @__PURE__ */ __name((filter) => {
      nodeFilters.value = nodeFilters.value.filter(
        (f) => toRaw(f) !== toRaw(filter)
      );
    }, "removeFilter");
    const clearFilters = /* @__PURE__ */ __name(() => {
      nodeFilters.value = [];
    }, "clearFilters");
    const closeDialog = /* @__PURE__ */ __name(() => {
      visible.value = false;
    }, "closeDialog");
    const canvasStore = useCanvasStore();
    const addNode = /* @__PURE__ */ __name((nodeDef) => {
      const node = litegraphService.addNodeOnGraph(nodeDef, {
        pos: getNewNodeLocation()
      });
      if (disconnectOnReset && triggerEvent) {
        canvasStore.getCanvas().linkConnector.connectToNode(node, triggerEvent);
      } else if (!triggerEvent) {
        console.warn("The trigger event was undefined when addNode was called.");
      }
      disconnectOnReset = false;
      useWorkflowStore().activeWorkflow?.changeTracker?.checkState();
      window.requestAnimationFrame(closeDialog);
    }, "addNode");
    const showSearchBox = /* @__PURE__ */ __name((e) => {
      if (newSearchBoxEnabled.value) {
        if (e?.pointerType === "touch") {
          setTimeout(() => {
            showNewSearchBox(e);
          }, 128);
        } else {
          showNewSearchBox(e);
        }
      } else {
        canvasStore.getCanvas().showSearchBox(e);
      }
    }, "showSearchBox");
    const getFirstLink = /* @__PURE__ */ __name(() => canvasStore.getCanvas().linkConnector.renderLinks.at(0), "getFirstLink");
    const nodeDefStore = useNodeDefStore();
    const showNewSearchBox = /* @__PURE__ */ __name((e) => {
      const firstLink = getFirstLink();
      if (firstLink) {
        const filter = firstLink.toType === "input" ? nodeDefStore.nodeSearchService.inputTypeFilter : nodeDefStore.nodeSearchService.outputTypeFilter;
        const dataType = firstLink.fromSlot.type?.toString() ?? "";
        addFilter({
          filterDef: filter,
          value: dataType
        });
      }
      visible.value = true;
      triggerEvent = e;
      dismissable.value = false;
      setTimeout(() => {
        dismissable.value = true;
      }, 300);
    }, "showNewSearchBox");
    const showContextMenu = /* @__PURE__ */ __name((e) => {
      const firstLink = getFirstLink();
      if (!firstLink) return;
      const { node, fromSlot, toType } = firstLink;
      const commonOptions = {
        e,
        allow_searchbox: true,
        showSearchBox: /* @__PURE__ */ __name(() => {
          cancelResetOnContextClose();
          showSearchBox(e);
        }, "showSearchBox")
      };
      const afterRerouteId = firstLink.fromReroute?.id;
      const connectionOptions = toType === "input" ? { nodeFrom: node, slotFrom: fromSlot, afterRerouteId } : { nodeTo: node, slotTo: fromSlot, afterRerouteId };
      const canvas = canvasStore.getCanvas();
      const menu = canvas.showConnectionMenu({
        ...connectionOptions,
        ...commonOptions
      });
      if (!menu) {
        console.warn("No menu was returned from showConnectionMenu");
        return;
      }
      triggerEvent = e;
      listenerController = new AbortController();
      const { signal } = listenerController;
      const options = { once: true, signal };
      useEventListener(
        canvas.canvas,
        "connect-new-default-node",
        (createEvent) => {
          if (!(createEvent instanceof CustomEvent))
            throw new Error("Invalid event");
          const node2 = createEvent.detail?.node;
          if (!(node2 instanceof LGraphNode)) throw new Error("Invalid node");
          disconnectOnReset = false;
          createEvent.preventDefault();
          canvas.linkConnector.connectToNode(node2, e);
        },
        options
      );
      const cancelResetOnContextClose = useEventListener(
        menu.controller.signal,
        "abort",
        reset,
        options
      );
    }, "showContextMenu");
    watchEffect(() => {
      const { canvas } = canvasStore;
      if (!canvas) return;
      LiteGraph.release_link_on_empty_shows_menu = false;
      canvas.allow_searchbox = false;
      useEventListener(
        canvas.linkConnector.events,
        "dropped-on-canvas",
        handleDroppedOnCanvas
      );
    });
    const canvasEventHandler = /* @__PURE__ */ __name((e) => {
      if (e.detail.subType === "empty-double-click") {
        showSearchBox(e.detail.originalEvent);
      } else if (e.detail.subType === "group-double-click") {
        const group = e.detail.group;
        const [_, y] = group.pos;
        const relativeY = e.detail.originalEvent.canvasY - y;
        if (relativeY > group.titleHeight) {
          showSearchBox(e.detail.originalEvent);
        }
      }
    }, "canvasEventHandler");
    const linkReleaseAction = computed(
      () => settingStore.get("Comfy.LinkRelease.Action")
    );
    const linkReleaseActionShift = computed(
      () => settingStore.get("Comfy.LinkRelease.ActionShift")
    );
    const preventDefault = /* @__PURE__ */ __name((e) => e.preventDefault(), "preventDefault");
    const cancelNextReset = /* @__PURE__ */ __name((e) => {
      e.preventDefault();
      const canvas = canvasStore.getCanvas();
      canvas.linkConnector.state.snapLinksPos = [e.detail.canvasX, e.detail.canvasY];
      useEventListener(canvas.linkConnector.events, "reset", preventDefault, {
        once: true
      });
    }, "cancelNextReset");
    const handleDroppedOnCanvas = /* @__PURE__ */ __name((e) => {
      disconnectOnReset = true;
      const action = e.detail.shiftKey ? linkReleaseActionShift.value : linkReleaseAction.value;
      switch (action) {
        case LinkReleaseTriggerAction.SEARCH_BOX:
          cancelNextReset(e);
          showSearchBox(e.detail);
          break;
        case LinkReleaseTriggerAction.CONTEXT_MENU:
          cancelNextReset(e);
          showContextMenu(e.detail);
          break;
        case LinkReleaseTriggerAction.NO_ACTION:
        default:
          break;
      }
    }, "handleDroppedOnCanvas");
    const reset = /* @__PURE__ */ __name(() => {
      listenerController?.abort();
      listenerController = null;
      triggerEvent = null;
      const canvas = canvasStore.getCanvas();
      canvas.linkConnector.events.removeEventListener("reset", preventDefault);
      if (disconnectOnReset) canvas.linkConnector.disconnectLinks();
      canvas.linkConnector.reset();
      canvas.setDirty(true, true);
    }, "reset");
    watch(visible, () => {
      if (!visible.value) reset();
    });
    useEventListener(document, "litegraph:canvas", canvasEventHandler);
    __expose({ showSearchBox });
    return (_ctx, _cache) => {
      return openBlock(), createElementBlock("div", null, [
        createVNode(unref(Dialog), {
          visible: unref(visible),
          "onUpdate:visible": _cache[0] || (_cache[0] = ($event) => isRef(visible) ? visible.value = $event : null),
          modal: "",
          "dismissable-mask": dismissable.value,
          pt: {
            root: {
              class: "invisible-dialog-root",
              role: "search"
            },
            mask: { class: "node-search-box-dialog-mask" },
            transition: {
              enterFromClass: "opacity-0 scale-75",
              // 100ms is the duration of the transition in the dialog component
              enterActiveClass: "transition-all duration-100 ease-out",
              leaveActiveClass: "transition-all duration-100 ease-in",
              leaveToClass: "opacity-0 scale-75"
            }
          },
          onHide: clearFilters
        }, {
          container: withCtx(() => [
            createVNode(_sfc_main$18, {
              filters: nodeFilters.value,
              onAddFilter: addFilter,
              onRemoveFilter: removeFilter,
              onAddNode: addNode
            }, null, 8, ["filters"])
          ]),
          _: 1
        }, 8, ["visible", "dismissable-mask"])
      ]);
    };
  }
});
const _hoisted_1$13 = {
  viewBox: "0 0 256 256",
  width: "1.2em",
  height: "1.2em"
};
function render$i(_ctx, _cache) {
  return openBlock(), createElementBlock("svg", _hoisted_1$13, _cache[0] || (_cache[0] = [
    createElementVNode("path", {
      fill: "currentColor",
      d: "m120 137l-72 64a12 12 0 1 1-16-18l61.91-55L32 73a12 12 0 1 1 16-18l72 64a12 12 0 0 1 0 18m96 43h-96a12 12 0 0 0 0 24h96a12 12 0 0 0 0-24"
    }, null, -1)
  ]));
}
__name(render$i, "render$i");
const __unplugin_components_0$6 = markRaw({ name: "ph-terminal-bold", render: render$i });
const _hoisted_1$12 = { class: "side-bar-button-content" };
const _hoisted_2$y = {
  key: 0,
  class: "side-bar-button-label"
};
const _sfc_main$16 = /* @__PURE__ */ defineComponent({
  __name: "SidebarIcon",
  props: {
    icon: { default: "" },
    selected: { type: Boolean, default: false },
    tooltip: { default: "" },
    tooltipSuffix: { default: "" },
    iconBadge: { type: [String, Function], default: "" },
    label: { default: "" },
    isSmall: { type: Boolean, default: false }
  },
  emits: ["click"],
  setup(__props, { emit: __emit }) {
    const { t: t2 } = useI18n();
    const emit = __emit;
    const overlayValue = computed(
      () => typeof __props.iconBadge === "function" ? __props.iconBadge() ?? "" : __props.iconBadge
    );
    const shouldShowBadge = computed(() => !!overlayValue.value);
    const computedTooltip = computed(() => t2(__props.tooltip) + __props.tooltipSuffix);
    return (_ctx, _cache) => {
      const _directive_tooltip = resolveDirective("tooltip");
      return withDirectives((openBlock(), createBlock(unref(Button), {
        text: "",
        pt: {
          root: {
            class: `side-bar-button ${_ctx.selected ? "p-button-primary side-bar-button-selected" : "p-button-secondary"}`,
            "aria-label": computedTooltip.value
          }
        },
        onClick: _cache[0] || (_cache[0] = ($event) => emit("click", $event))
      }, {
        icon: withCtx(() => [
          createElementVNode("div", _hoisted_1$12, [
            renderSlot(_ctx.$slots, "icon", {}, () => [
              shouldShowBadge.value ? (openBlock(), createBlock(unref(OverlayBadge), {
                key: 0,
                value: overlayValue.value
              }, {
                default: withCtx(() => [
                  typeof _ctx.icon === "string" ? (openBlock(), createElementBlock("i", {
                    key: 0,
                    class: normalizeClass(_ctx.icon + " side-bar-button-icon")
                  }, null, 2)) : (openBlock(), createBlock(resolveDynamicComponent(_ctx.icon), {
                    key: 1,
                    class: "side-bar-button-icon"
                  }))
                ]),
                _: 1
              }, 8, ["value"])) : typeof _ctx.icon === "string" ? (openBlock(), createElementBlock("i", {
                key: 1,
                class: normalizeClass(_ctx.icon + " side-bar-button-icon")
              }, null, 2)) : typeof _ctx.icon === "object" ? (openBlock(), createBlock(resolveDynamicComponent(_ctx.icon), {
                key: 2,
                class: "side-bar-button-icon"
              })) : createCommentVNode("", true)
            ], true),
            _ctx.label && !_ctx.isSmall ? (openBlock(), createElementBlock("span", _hoisted_2$y, toDisplayString(unref(t2)(_ctx.label)), 1)) : createCommentVNode("", true)
          ])
        ]),
        _: 3
      }, 8, ["pt"])), [
        [_directive_tooltip, {
          value: computedTooltip.value,
          showDelay: 300,
          hideDelay: 300
        }]
      ]);
    };
  }
});
const SidebarIcon = /* @__PURE__ */ _export_sfc(_sfc_main$16, [["__scopeId", "data-v-179455cd"]]);
const _sfc_main$15 = /* @__PURE__ */ defineComponent({
  __name: "SidebarBottomPanelToggleButton",
  setup(__props) {
    const bottomPanelStore = useBottomPanelStore();
    return (_ctx, _cache) => {
      const _component_i_ph58terminal_bold = __unplugin_components_0$6;
      return openBlock(), createBlock(SidebarIcon, {
        tooltip: _ctx.$t("menu.toggleBottomPanel"),
        selected: unref(bottomPanelStore).activePanel == "terminal",
        onClick: unref(bottomPanelStore).toggleBottomPanel
      }, {
        icon: withCtx(() => [
          createVNode(_component_i_ph58terminal_bold)
        ]),
        _: 1
      }, 8, ["tooltip", "selected", "onClick"]);
    };
  }
});
const _hoisted_1$11 = {
  viewBox: "0 0 24 24",
  width: "1.2em",
  height: "1.2em"
};
function render$h(_ctx, _cache) {
  return openBlock(), createElementBlock("svg", _hoisted_1$11, _cache[0] || (_cache[0] = [
    createElementVNode("g", {
      fill: "none",
      stroke: "currentColor",
      "stroke-linecap": "round",
      "stroke-linejoin": "round",
      "stroke-width": "2"
    }, [
      createElementVNode("path", { d: "M10 8h.01M12 12h.01M14 8h.01M16 12h.01M18 8h.01M6 8h.01M7 16h10m-9-4h.01" }),
      createElementVNode("rect", {
        width: "20",
        height: "16",
        x: "2",
        y: "4",
        rx: "2"
      })
    ], -1)
  ]));
}
__name(render$h, "render$h");
const __unplugin_components_0$5 = markRaw({ name: "lucide-keyboard", render: render$h });
const _sfc_main$14 = /* @__PURE__ */ defineComponent({
  __name: "SidebarShortcutsToggleButton",
  setup(__props) {
    const { t: t2 } = useI18n();
    const bottomPanelStore = useBottomPanelStore();
    const commandStore = useCommandStore();
    const command = commandStore.getCommand("Workspace.ToggleBottomPanel.Shortcuts");
    const { formatKeySequence } = commandStore;
    const isShortcutsPanelVisible = computed(
      () => bottomPanelStore.activePanel === "shortcuts"
    );
    const tooltipText = computed(
      () => `${t2("shortcuts.keyboardShortcuts")} (${formatKeySequence(command)})`
    );
    const toggleShortcutsPanel = /* @__PURE__ */ __name(() => {
      bottomPanelStore.togglePanel("shortcuts");
    }, "toggleShortcutsPanel");
    return (_ctx, _cache) => {
      const _component_i_lucide58keyboard = __unplugin_components_0$5;
      return openBlock(), createBlock(SidebarIcon, {
        tooltip: tooltipText.value,
        selected: isShortcutsPanelVisible.value,
        onClick: toggleShortcutsPanel
      }, {
        icon: withCtx(() => [
          createVNode(_component_i_lucide58keyboard)
        ]),
        _: 1
      }, 8, ["tooltip", "selected"]);
    };
  }
});
const _hoisted_1$10 = ["width", "height"];
const _hoisted_2$x = { "clip-path": "url(#clip0_1099_16244)" };
const _hoisted_3$l = ["stroke"];
const _sfc_main$13 = /* @__PURE__ */ defineComponent({
  __name: "PuzzleIcon",
  props: {
    size: { default: 16 },
    color: { default: "currentColor" },
    class: {}
  },
  setup(__props) {
    const iconClass = computed(() => __props.class || "");
    return (_ctx, _cache) => {
      return openBlock(), createElementBlock("svg", {
        xmlns: "http://www.w3.org/2000/svg",
        width: _ctx.size,
        height: _ctx.size,
        viewBox: "0 0 16 16",
        fill: "none",
        class: normalizeClass(iconClass.value)
      }, [
        createElementVNode("g", _hoisted_2$x, [
          createElementVNode("path", {
            d: "M4.99992 3.00016C4.99992 2.07969 5.74611 1.3335 6.66658 1.3335C7.58706 1.3335 8.33325 2.07969 8.33325 3.00016V4.00016H8.99992C9.9318 4.00016 10.3977 4.00016 10.7653 4.1524C11.2553 4.35539 11.6447 4.74474 11.8477 5.2348C11.9999 5.60234 11.9999 6.06828 11.9999 7.00016H12.9999C13.9204 7.00016 14.6666 7.74635 14.6666 8.66683C14.6666 9.5873 13.9204 10.3335 12.9999 10.3335H11.9999V11.4668C11.9999 12.5869 11.9999 13.147 11.7819 13.5748C11.5902 13.9511 11.2842 14.2571 10.9079 14.4488C10.4801 14.6668 9.92002 14.6668 8.79992 14.6668H8.33325V13.5002C8.33325 12.6717 7.66168 12.0002 6.83325 12.0002C6.00482 12.0002 5.33325 12.6717 5.33325 13.5002V14.6668H4.53325C3.41315 14.6668 2.85309 14.6668 2.42527 14.4488C2.04895 14.2571 1.74299 13.9511 1.55124 13.5748C1.33325 13.147 1.33325 12.5869 1.33325 11.4668V10.3335H2.33325C3.25373 10.3335 3.99992 9.5873 3.99992 8.66683C3.99992 7.74635 3.25373 7.00016 2.33325 7.00016H1.33325C1.33325 6.06828 1.33325 5.60234 1.48549 5.2348C1.68848 4.74474 2.07783 4.35539 2.56789 4.1524C2.93543 4.00016 3.40137 4.00016 4.33325 4.00016H4.99992V3.00016Z",
            stroke: _ctx.color,
            "stroke-width": "1.2",
            "stroke-linecap": "round",
            "stroke-linejoin": "round"
          }, null, 8, _hoisted_3$l)
        ]),
        _cache[0] || (_cache[0] = createElementVNode("defs", null, [
          createElementVNode("clipPath", { id: "clip0_1099_16244" }, [
            createElementVNode("rect", {
              width: "16",
              height: "16",
              fill: "white"
            })
          ])
        ], -1))
      ], 10, _hoisted_1$10);
    };
  }
});
const releaseApiClient = axios.create({
  baseURL: COMFY_API_BASE_URL,
  headers: {
    "Content-Type": "application/json"
  }
});
const useReleaseService = /* @__PURE__ */ __name(() => {
  const isLoading = ref(false);
  const error = ref(null);
  const handleApiError = /* @__PURE__ */ __name((err, context, routeSpecificErrors) => {
    if (!axios.isAxiosError(err))
      return err instanceof Error ? `${context}: ${err.message}` : `${context}: Unknown error occurred`;
    const axiosError = err;
    if (axiosError.response) {
      const { status, data } = axiosError.response;
      if (routeSpecificErrors && routeSpecificErrors[status])
        return routeSpecificErrors[status];
      switch (status) {
        case 400:
          return `Bad request: ${data?.message || "Invalid input"}`;
        case 401:
          return "Unauthorized: Authentication required";
        case 403:
          return `Forbidden: ${data?.message || "Access denied"}`;
        case 404:
          return `Not found: ${data?.message || "Resource not found"}`;
        case 500:
          return `Server error: ${data?.message || "Internal server error"}`;
        default:
          return `${context}: ${data?.message || axiosError.message}`;
      }
    }
    return `${context}: ${axiosError.message}`;
  }, "handleApiError");
  const executeApiRequest = /* @__PURE__ */ __name(async (apiCall, errorContext, routeSpecificErrors) => {
    isLoading.value = true;
    error.value = null;
    try {
      const response = await apiCall();
      return response.data;
    } catch (err) {
      if (isAbortError(err)) return null;
      error.value = handleApiError(err, errorContext, routeSpecificErrors);
      return null;
    } finally {
      isLoading.value = false;
    }
  }, "executeApiRequest");
  const getReleases = /* @__PURE__ */ __name(async (params, signal) => {
    const endpoint = "/releases";
    const errorContext = "Failed to get releases";
    const routeSpecificErrors = {
      400: "Invalid project or version parameter"
    };
    const apiResponse = await executeApiRequest(
      () => releaseApiClient.get(endpoint, {
        params,
        signal
      }),
      errorContext,
      routeSpecificErrors
    );
    return apiResponse;
  }, "getReleases");
  return {
    isLoading,
    error,
    getReleases
  };
}, "useReleaseService");
const useReleaseStore = defineStore("release", () => {
  const releases = ref([]);
  const isLoading = ref(false);
  const error = ref(null);
  const releaseService = useReleaseService();
  const systemStatsStore = useSystemStatsStore();
  const settingStore = useSettingStore();
  const currentComfyUIVersion = computed(
    () => systemStatsStore?.systemStats?.system?.comfyui_version ?? ""
  );
  const locale = computed(() => settingStore.get("Comfy.Locale"));
  const releaseVersion = computed(
    () => settingStore.get("Comfy.Release.Version")
  );
  const releaseStatus = computed(() => settingStore.get("Comfy.Release.Status"));
  const releaseTimestamp = computed(
    () => settingStore.get("Comfy.Release.Timestamp")
  );
  const showVersionUpdates = computed(
    () => settingStore.get("Comfy.Notification.ShowVersionUpdates")
  );
  const recentRelease = computed(() => {
    return releases.value[0] ?? null;
  });
  const recentReleases = computed(() => {
    return releases.value.slice(0, 3);
  });
  const THREE_DAYS_MS = 3 * 24 * 60 * 60 * 1e3;
  const isNewVersionAvailable = computed(
    () => !!recentRelease.value && compareVersions(
      recentRelease.value.version,
      currentComfyUIVersion.value
    ) > 0
  );
  const isLatestVersion = computed(
    () => !!recentRelease.value && !compareVersions(recentRelease.value.version, currentComfyUIVersion.value)
  );
  const hasMediumOrHighAttention = computed(
    () => recentReleases.value.slice(0, -1).some(
      (release) => release.attention === "medium" || release.attention === "high"
    )
  );
  const shouldShowToast = computed(() => {
    if (!isElectron()) {
      return false;
    }
    if (!showVersionUpdates.value) {
      return false;
    }
    if (!isNewVersionAvailable.value) {
      return false;
    }
    if (!hasMediumOrHighAttention.value) {
      return false;
    }
    if (releaseVersion.value === recentRelease.value?.version && ["skipped", "changelog seen"].includes(releaseStatus.value)) {
      return false;
    }
    return true;
  });
  const shouldShowRedDot = computed(() => {
    if (!isElectron()) {
      return false;
    }
    if (!showVersionUpdates.value) {
      return false;
    }
    if (!isNewVersionAvailable.value) {
      return false;
    }
    const { version } = recentRelease.value;
    if (releaseVersion.value === version && releaseStatus.value === "changelog seen") {
      return false;
    }
    if (hasMediumOrHighAttention.value) {
      return true;
    }
    if (releaseVersion.value === version && releaseStatus.value === "skipped" && releaseTimestamp.value && Date.now() - releaseTimestamp.value >= THREE_DAYS_MS) {
      return false;
    }
    return true;
  });
  const shouldShowPopup = computed(() => {
    if (!isElectron()) {
      return false;
    }
    if (!showVersionUpdates.value) {
      return false;
    }
    if (!isLatestVersion.value) {
      return false;
    }
    if (releaseVersion.value === recentRelease.value.version && releaseStatus.value === "what's new seen") {
      return false;
    }
    return true;
  });
  async function handleSkipRelease(version) {
    if (version !== recentRelease.value?.version || releaseStatus.value === "changelog seen") {
      return;
    }
    await settingStore.set("Comfy.Release.Version", version);
    await settingStore.set("Comfy.Release.Status", "skipped");
    await settingStore.set("Comfy.Release.Timestamp", Date.now());
  }
  __name(handleSkipRelease, "handleSkipRelease");
  async function handleShowChangelog(version) {
    if (version !== recentRelease.value?.version) {
      return;
    }
    await settingStore.set("Comfy.Release.Version", version);
    await settingStore.set("Comfy.Release.Status", "changelog seen");
    await settingStore.set("Comfy.Release.Timestamp", Date.now());
  }
  __name(handleShowChangelog, "handleShowChangelog");
  async function handleWhatsNewSeen(version) {
    if (version !== recentRelease.value?.version) {
      return;
    }
    await settingStore.set("Comfy.Release.Version", version);
    await settingStore.set("Comfy.Release.Status", "what's new seen");
    await settingStore.set("Comfy.Release.Timestamp", Date.now());
  }
  __name(handleWhatsNewSeen, "handleWhatsNewSeen");
  async function fetchReleases() {
    if (isLoading.value) {
      return;
    }
    if (!showVersionUpdates.value) {
      return;
    }
    if (systemStatsStore.systemStats?.system?.argv?.includes(
      "--disable-api-nodes"
    )) {
      return;
    }
    isLoading.value = true;
    error.value = null;
    try {
      if (!systemStatsStore.systemStats) {
        await systemStatsStore.fetchSystemStats();
      }
      const fetchedReleases = await releaseService.getReleases({
        project: "comfyui",
        current_version: currentComfyUIVersion.value,
        form_factor: systemStatsStore.getFormFactor(),
        locale: stringToLocale(locale.value)
      });
      if (fetchedReleases !== null) {
        releases.value = fetchedReleases;
      } else if (releaseService.error.value) {
        error.value = releaseService.error.value;
      }
    } catch (err) {
      error.value = err instanceof Error ? err.message : "Unknown error occurred";
    } finally {
      isLoading.value = false;
    }
  }
  __name(fetchReleases, "fetchReleases");
  async function initialize() {
    await fetchReleases();
  }
  __name(initialize, "initialize");
  return {
    releases,
    isLoading,
    error,
    recentRelease,
    recentReleases,
    shouldShowToast,
    shouldShowRedDot,
    shouldShowPopup,
    shouldShowUpdateButton: isNewVersionAvailable,
    handleSkipRelease,
    handleShowChangelog,
    handleWhatsNewSeen,
    fetchReleases,
    initialize
  };
});
const releaseStore = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
  __proto__: null,
  useReleaseStore
}, Symbol.toStringTag, { value: "Module" }));
const _hoisted_1$$ = {
  class: "help-center-menu",
  role: "menu",
  "aria-label": "Help Center Menu"
};
const _hoisted_2$w = {
  class: "help-menu-section",
  role: "menubar"
};
const _hoisted_3$k = ["onClick", "onMouseenter", "onMouseleave"];
const _hoisted_4$g = { class: "help-menu-icon-container" };
const _hoisted_5$9 = { class: "help-menu-icon" };
const _hoisted_6$7 = {
  key: 0,
  class: "menu-red-dot"
};
const _hoisted_7$5 = { class: "menu-label" };
const _hoisted_8$4 = {
  key: 0,
  class: "pi pi-chevron-right"
};
const _hoisted_9$3 = {
  key: 0,
  class: "submenu-divider"
};
const _hoisted_10$3 = ["onClick"];
const _hoisted_11$2 = { class: "menu-label" };
const _hoisted_12$1 = {
  key: 0,
  class: "whats-new-section"
};
const _hoisted_13$1 = { class: "section-description" };
const _hoisted_14$1 = {
  key: 0,
  role: "group",
  "aria-label": "Recent releases"
};
const _hoisted_15$1 = ["onClick", "onKeydown"];
const _hoisted_16$1 = { class: "release-content" };
const _hoisted_17$1 = { class: "release-title" };
const _hoisted_18$1 = ["datetime"];
const _hoisted_19$1 = { class: "normal-state" };
const _hoisted_20$1 = { class: "hover-state" };
const _hoisted_21$1 = {
  key: 1,
  class: "help-menu-item",
  role: "status",
  "aria-live": "polite"
};
const _hoisted_22$1 = {
  key: 2,
  class: "help-menu-item",
  role: "status"
};
const _sfc_main$12 = /* @__PURE__ */ defineComponent({
  __name: "HelpCenterMenuContent",
  emits: ["close"],
  setup(__props, { emit: __emit }) {
    const EXTERNAL_LINKS = {
      DOCS: "https://docs.comfy.org/",
      DISCORD: "https://www.comfy.org/discord",
      GITHUB: "https://github.com/comfyanonymous/ComfyUI",
      DESKTOP_GUIDE: "https://comfyorg.notion.site/",
      UPDATE_GUIDE: "https://docs.comfy.org/installation/update_comfyui"
    };
    const TIME_UNITS = {
      MINUTE: 60 * 1e3,
      HOUR: 60 * 60 * 1e3,
      DAY: 24 * 60 * 60 * 1e3,
      WEEK: 7 * 24 * 60 * 60 * 1e3,
      MONTH: 30 * 24 * 60 * 60 * 1e3,
      YEAR: 365 * 24 * 60 * 60 * 1e3
    };
    const SUBMENU_CONFIG = {
      DELAY_MS: 100,
      OFFSET_PX: 8,
      Z_INDEX: 10001
    };
    const { t: t2, locale } = useI18n();
    const releaseStore2 = useReleaseStore();
    const commandStore = useCommandStore();
    const settingStore = useSettingStore();
    const dialogService = useDialogService();
    const emit = __emit;
    const isSubmenuVisible = ref(false);
    const submenuRef = ref(null);
    const submenuStyle = ref({});
    let hoverTimeout = null;
    const hasReleases = computed(() => releaseStore2.releases.length > 0);
    const showVersionUpdates = computed(
      () => settingStore.get("Comfy.Notification.ShowVersionUpdates")
    );
    const { shouldShowRedDot: shouldShowManagerRedDot } = useConflictAcknowledgment();
    const moreItems = computed(() => {
      const allMoreItems = [
        {
          key: "desktop-guide",
          type: "item",
          label: t2("helpCenter.desktopUserGuide"),
          visible: isElectron(),
          action: /* @__PURE__ */ __name(() => {
            openExternalLink(EXTERNAL_LINKS.DESKTOP_GUIDE);
            emit("close");
          }, "action")
        },
        {
          key: "dev-tools",
          type: "item",
          label: t2("helpCenter.openDevTools"),
          visible: isElectron(),
          action: /* @__PURE__ */ __name(() => {
            openDevTools();
            emit("close");
          }, "action")
        },
        {
          key: "divider-1",
          type: "divider",
          visible: isElectron()
        },
        {
          key: "reinstall",
          type: "item",
          label: t2("helpCenter.reinstall"),
          visible: isElectron(),
          action: /* @__PURE__ */ __name(() => {
            onReinstall();
            emit("close");
          }, "action")
        }
      ];
      return allMoreItems.filter((item) => item.visible !== false);
    });
    const hasVisibleMoreItems = computed(() => {
      return !!moreItems.value.length;
    });
    const moreMenuItem = computed(
      () => menuItems.value.find((item) => item.key === "more")
    );
    const menuItems = computed(() => {
      return [
        {
          key: "docs",
          type: "item",
          icon: "pi pi-book",
          label: t2("helpCenter.docs"),
          action: /* @__PURE__ */ __name(() => {
            openExternalLink(EXTERNAL_LINKS.DOCS);
            emit("close");
          }, "action")
        },
        {
          key: "discord",
          type: "item",
          icon: "pi pi-discord",
          label: "Discord",
          action: /* @__PURE__ */ __name(() => {
            openExternalLink(EXTERNAL_LINKS.DISCORD);
            emit("close");
          }, "action")
        },
        {
          key: "github",
          type: "item",
          icon: "pi pi-github",
          label: t2("helpCenter.github"),
          action: /* @__PURE__ */ __name(() => {
            openExternalLink(EXTERNAL_LINKS.GITHUB);
            emit("close");
          }, "action")
        },
        {
          key: "help",
          type: "item",
          icon: "pi pi-question-circle",
          label: t2("helpCenter.helpFeedback"),
          action: /* @__PURE__ */ __name(() => {
            void commandStore.execute("Comfy.ContactSupport");
            emit("close");
          }, "action")
        },
        {
          key: "manager",
          type: "item",
          icon: _sfc_main$13,
          label: t2("helpCenter.managerExtension"),
          showRedDot: shouldShowManagerRedDot.value,
          action: /* @__PURE__ */ __name(() => {
            dialogService.showManagerDialog();
            emit("close");
          }, "action")
        },
        {
          key: "more",
          type: "item",
          icon: "",
          label: t2("helpCenter.more"),
          visible: hasVisibleMoreItems.value,
          action: /* @__PURE__ */ __name(() => {
          }, "action"),
          // No action for more item
          items: moreItems.value
        }
      ];
    });
    const openExternalLink = /* @__PURE__ */ __name((url) => {
      window.open(url, "_blank", "noopener,noreferrer");
    }, "openExternalLink");
    const clearHoverTimeout = /* @__PURE__ */ __name(() => {
      if (hoverTimeout) {
        clearTimeout(hoverTimeout);
        hoverTimeout = null;
      }
    }, "clearHoverTimeout");
    const calculateSubmenuPosition = /* @__PURE__ */ __name((button) => {
      const rect = button.getBoundingClientRect();
      const submenuWidth = 210;
      const visibleItemCount = moreMenuItem.value?.items?.filter((item) => item.visible !== false).length || 0;
      const estimatedHeight = visibleItemCount * 48 + 16;
      const submenuHeight = submenuRef.value?.offsetHeight || estimatedHeight;
      const viewportWidth = window.innerWidth;
      const viewportHeight = window.innerHeight;
      let top = rect.top;
      let left = rect.right + SUBMENU_CONFIG.OFFSET_PX;
      if (left + submenuWidth > viewportWidth) {
        left = rect.left - submenuWidth - SUBMENU_CONFIG.OFFSET_PX;
      }
      if (top + submenuHeight > viewportHeight) {
        top = Math.max(
          SUBMENU_CONFIG.OFFSET_PX,
          // Minimum distance from top of viewport
          rect.bottom - submenuHeight
        );
      }
      if (top < SUBMENU_CONFIG.OFFSET_PX) {
        top = SUBMENU_CONFIG.OFFSET_PX;
      }
      top -= 8;
      return {
        position: "fixed",
        top: `${top}px`,
        left: `${left}px`,
        zIndex: SUBMENU_CONFIG.Z_INDEX
      };
    }, "calculateSubmenuPosition");
    const formatReleaseDate = /* @__PURE__ */ __name((dateString) => {
      if (!dateString) return "date";
      const date = new Date(dateString);
      const now = /* @__PURE__ */ new Date();
      const diffTime = Math.abs(now.getTime() - date.getTime());
      const timeUnits = [
        { unit: TIME_UNITS.YEAR, suffix: "y" },
        { unit: TIME_UNITS.MONTH, suffix: "mo" },
        { unit: TIME_UNITS.WEEK, suffix: "w" },
        { unit: TIME_UNITS.DAY, suffix: "d" },
        { unit: TIME_UNITS.HOUR, suffix: "h" },
        { unit: TIME_UNITS.MINUTE, suffix: "min" }
      ];
      for (const { unit, suffix } of timeUnits) {
        const value = Math.floor(diffTime / unit);
        if (value > 0) {
          return `${value}${suffix} ago`;
        }
      }
      return "now";
    }, "formatReleaseDate");
    const shouldShowUpdateButton = /* @__PURE__ */ __name((release) => {
      return releaseStore2.shouldShowUpdateButton && release === releaseStore2.recentReleases[0];
    }, "shouldShowUpdateButton");
    const onMenuItemHover = /* @__PURE__ */ __name(async (key, event) => {
      if (key !== "more" || !moreMenuItem.value?.items) return;
      const hasVisibleItems = moreMenuItem.value.items.some(
        (item) => item.visible !== false
      );
      if (!hasVisibleItems) return;
      clearHoverTimeout();
      const moreButton = event.currentTarget;
      submenuStyle.value = calculateSubmenuPosition(moreButton);
      isSubmenuVisible.value = true;
      await nextTick();
      if (submenuRef.value) {
        submenuStyle.value = calculateSubmenuPosition(moreButton);
      }
    }, "onMenuItemHover");
    const onMenuItemLeave = /* @__PURE__ */ __name((key) => {
      if (key !== "more") return;
      hoverTimeout = window.setTimeout(() => {
        isSubmenuVisible.value = false;
      }, SUBMENU_CONFIG.DELAY_MS);
    }, "onMenuItemLeave");
    const onSubmenuHover = /* @__PURE__ */ __name(() => {
      clearHoverTimeout();
    }, "onSubmenuHover");
    const onSubmenuLeave = /* @__PURE__ */ __name(() => {
      isSubmenuVisible.value = false;
    }, "onSubmenuLeave");
    const openDevTools = /* @__PURE__ */ __name(() => {
      if (isElectron()) {
        electronAPI().openDevTools();
      }
    }, "openDevTools");
    const onReinstall = /* @__PURE__ */ __name(() => {
      if (isElectron()) {
        void electronAPI().reinstall();
      }
    }, "onReinstall");
    const onReleaseClick = /* @__PURE__ */ __name((release) => {
      void releaseStore2.handleShowChangelog(release.version);
      const versionAnchor = formatVersionAnchor(release.version);
      const changelogUrl = `${getChangelogUrl()}#${versionAnchor}`;
      openExternalLink(changelogUrl);
      emit("close");
    }, "onReleaseClick");
    const onUpdate = /* @__PURE__ */ __name((_) => {
      openExternalLink(EXTERNAL_LINKS.UPDATE_GUIDE);
      emit("close");
    }, "onUpdate");
    const getChangelogUrl = /* @__PURE__ */ __name(() => {
      const isChineseLocale = locale.value === "zh";
      return isChineseLocale ? "https://docs.comfy.org/zh-CN/changelog" : "https://docs.comfy.org/changelog";
    }, "getChangelogUrl");
    onMounted(async () => {
      if (!hasReleases.value) {
        await releaseStore2.fetchReleases();
      }
    });
    return (_ctx, _cache) => {
      return openBlock(), createElementBlock("div", _hoisted_1$$, [
        createElementVNode("nav", _hoisted_2$w, [
          (openBlock(true), createElementBlock(Fragment, null, renderList(menuItems.value, (menuItem) => {
            return withDirectives((openBlock(), createElementBlock("button", {
              key: menuItem.key,
              type: "button",
              class: normalizeClass(["help-menu-item", { "more-item": menuItem.key === "more" }]),
              role: "menuitem",
              onClick: menuItem.action,
              onMouseenter: /* @__PURE__ */ __name(($event) => onMenuItemHover(menuItem.key, $event), "onMouseenter"),
              onMouseleave: /* @__PURE__ */ __name(($event) => onMenuItemLeave(menuItem.key), "onMouseleave")
            }, [
              createElementVNode("div", _hoisted_4$g, [
                createElementVNode("div", _hoisted_5$9, [
                  typeof menuItem.icon === "object" ? (openBlock(), createBlock(resolveDynamicComponent(menuItem.icon), {
                    key: 0,
                    size: 16
                  })) : (openBlock(), createElementBlock("i", {
                    key: 1,
                    class: normalizeClass(menuItem.icon)
                  }, null, 2))
                ]),
                menuItem.showRedDot ? (openBlock(), createElementBlock("div", _hoisted_6$7)) : createCommentVNode("", true)
              ]),
              createElementVNode("span", _hoisted_7$5, toDisplayString(menuItem.label), 1),
              menuItem.key === "more" ? (openBlock(), createElementBlock("i", _hoisted_8$4)) : createCommentVNode("", true)
            ], 42, _hoisted_3$k)), [
              [vShow, menuItem.visible !== false]
            ]);
          }), 128))
        ]),
        (openBlock(), createBlock(Teleport, { to: "body" }, [
          isSubmenuVisible.value ? (openBlock(), createElementBlock("div", {
            key: 0,
            ref_key: "submenuRef",
            ref: submenuRef,
            class: "more-submenu",
            style: normalizeStyle(submenuStyle.value),
            onMouseenter: onSubmenuHover,
            onMouseleave: onSubmenuLeave
          }, [
            (openBlock(true), createElementBlock(Fragment, null, renderList(moreMenuItem.value?.items, (submenuItem) => {
              return openBlock(), createElementBlock(Fragment, {
                key: submenuItem.key
              }, [
                submenuItem.type === "divider" ? withDirectives((openBlock(), createElementBlock("div", _hoisted_9$3, null, 512)), [
                  [vShow, submenuItem.visible !== false]
                ]) : withDirectives((openBlock(), createElementBlock("button", {
                  key: 1,
                  type: "button",
                  class: "help-menu-item submenu-item",
                  role: "menuitem",
                  onClick: submenuItem.action
                }, [
                  createElementVNode("span", _hoisted_11$2, toDisplayString(submenuItem.label), 1)
                ], 8, _hoisted_10$3)), [
                  [vShow, submenuItem.visible !== false]
                ])
              ], 64);
            }), 128))
          ], 36)) : createCommentVNode("", true)
        ])),
        showVersionUpdates.value ? (openBlock(), createElementBlock("section", _hoisted_12$1, [
          createElementVNode("h3", _hoisted_13$1, toDisplayString(_ctx.$t("helpCenter.whatsNew")), 1),
          hasReleases.value ? (openBlock(), createElementBlock("div", _hoisted_14$1, [
            (openBlock(true), createElementBlock(Fragment, null, renderList(unref(releaseStore2).recentReleases, (release) => {
              return openBlock(), createElementBlock("article", {
                key: release.id || release.version,
                class: "help-menu-item release-menu-item",
                role: "button",
                tabindex: "0",
                onClick: /* @__PURE__ */ __name(($event) => onReleaseClick(release), "onClick"),
                onKeydown: [
                  withKeys(($event) => onReleaseClick(release), ["enter"]),
                  withKeys(withModifiers(($event) => onReleaseClick(release), ["prevent"]), ["space"])
                ]
              }, [
                _cache[0] || (_cache[0] = createElementVNode("i", {
                  class: "pi pi-refresh help-menu-icon",
                  "aria-hidden": "true"
                }, null, -1)),
                createElementVNode("div", _hoisted_16$1, [
                  createElementVNode("span", _hoisted_17$1, toDisplayString(_ctx.$t("g.releaseTitle", {
                    package: "Comfy",
                    version: release.version
                  })), 1),
                  createElementVNode("time", {
                    class: "release-date",
                    datetime: release.published_at
                  }, [
                    createElementVNode("span", _hoisted_19$1, toDisplayString(formatReleaseDate(release.published_at)), 1),
                    createElementVNode("span", _hoisted_20$1, toDisplayString(_ctx.$t("helpCenter.clickToLearnMore")), 1)
                  ], 8, _hoisted_18$1)
                ]),
                shouldShowUpdateButton(release) ? (openBlock(), createBlock(unref(Button), {
                  key: 0,
                  label: _ctx.$t("helpCenter.updateAvailable"),
                  size: "small",
                  class: "update-button",
                  onClick: withModifiers(($event) => onUpdate(release), ["stop"])
                }, null, 8, ["label", "onClick"])) : createCommentVNode("", true)
              ], 40, _hoisted_15$1);
            }), 128))
          ])) : unref(releaseStore2).isLoading ? (openBlock(), createElementBlock("div", _hoisted_21$1, [
            _cache[1] || (_cache[1] = createElementVNode("i", {
              class: "pi pi-spin pi-spinner help-menu-icon",
              "aria-hidden": "true"
            }, null, -1)),
            createElementVNode("span", null, toDisplayString(_ctx.$t("helpCenter.loadingReleases")), 1)
          ])) : (openBlock(), createElementBlock("div", _hoisted_22$1, [
            _cache[2] || (_cache[2] = createElementVNode("i", {
              class: "pi pi-info-circle help-menu-icon",
              "aria-hidden": "true"
            }, null, -1)),
            createElementVNode("span", null, toDisplayString(_ctx.$t("helpCenter.noRecentReleases")), 1)
          ]))
        ])) : createCommentVNode("", true)
      ]);
    };
  }
});
const HelpCenterMenuContent = /* @__PURE__ */ _export_sfc(_sfc_main$12, [["__scopeId", "data-v-b26f9be9"]]);
const _hoisted_1$_ = {
  key: 0,
  class: "release-toast-popup"
};
const _hoisted_2$v = { class: "release-notification-toast" };
const _hoisted_3$j = { class: "toast-header" };
const _hoisted_4$f = { class: "toast-text" };
const _hoisted_5$8 = { class: "toast-title" };
const _hoisted_6$6 = { class: "toast-version-badge" };
const _hoisted_7$4 = { class: "toast-actions-section" };
const _hoisted_8$3 = { class: "actions-row" };
const _hoisted_9$2 = { class: "left-actions" };
const _hoisted_10$2 = ["href"];
const _hoisted_11$1 = { class: "right-actions" };
const _sfc_main$11 = /* @__PURE__ */ defineComponent({
  __name: "ReleaseNotificationToast",
  setup(__props) {
    const { locale } = useI18n();
    const releaseStore2 = useReleaseStore();
    const isDismissed = ref(false);
    const latestRelease = computed(
      () => releaseStore2.recentRelease
    );
    const shouldShow = computed(
      () => releaseStore2.shouldShowToast && !isDismissed.value
    );
    const changelogUrl = computed(() => {
      const isChineseLocale = locale.value === "zh";
      const baseUrl = isChineseLocale ? "https://docs.comfy.org/zh-CN/changelog" : "https://docs.comfy.org/changelog";
      if (latestRelease.value?.version) {
        const versionAnchor = formatVersionAnchor(latestRelease.value.version);
        return `${baseUrl}#${versionAnchor}`;
      }
      return baseUrl;
    });
    let hideTimer = null;
    const startAutoHide = /* @__PURE__ */ __name(() => {
      if (hideTimer) clearTimeout(hideTimer);
      hideTimer = setTimeout(() => {
        dismissToast();
      }, 8e3);
    }, "startAutoHide");
    const clearAutoHide = /* @__PURE__ */ __name(() => {
      if (hideTimer) {
        clearTimeout(hideTimer);
        hideTimer = null;
      }
    }, "clearAutoHide");
    const dismissToast = /* @__PURE__ */ __name(() => {
      isDismissed.value = true;
      clearAutoHide();
    }, "dismissToast");
    const handleSkip = /* @__PURE__ */ __name(() => {
      if (latestRelease.value) {
        void releaseStore2.handleSkipRelease(latestRelease.value.version);
      }
      dismissToast();
    }, "handleSkip");
    const handleLearnMore = /* @__PURE__ */ __name(() => {
      if (latestRelease.value) {
        void releaseStore2.handleShowChangelog(latestRelease.value.version);
      }
      dismissToast();
    }, "handleLearnMore");
    const handleUpdate = /* @__PURE__ */ __name(() => {
      window.open("https://docs.comfy.org/installation/update_comfyui", "_blank");
      dismissToast();
    }, "handleUpdate");
    watch(shouldShow, (isVisible) => {
      if (isVisible) {
        startAutoHide();
      } else {
        clearAutoHide();
      }
    });
    onMounted(async () => {
      if (!releaseStore2.releases.length) {
        await releaseStore2.fetchReleases();
      }
    });
    return (_ctx, _cache) => {
      return shouldShow.value ? (openBlock(), createElementBlock("div", _hoisted_1$_, [
        createElementVNode("div", _hoisted_2$v, [
          createElementVNode("div", _hoisted_3$j, [
            _cache[0] || (_cache[0] = createElementVNode("div", { class: "toast-icon" }, [
              createElementVNode("i", { class: "pi pi-download" })
            ], -1)),
            createElementVNode("div", _hoisted_4$f, [
              createElementVNode("div", _hoisted_5$8, toDisplayString(_ctx.$t("releaseToast.newVersionAvailable")), 1),
              createElementVNode("div", _hoisted_6$6, toDisplayString(latestRelease.value?.version), 1)
            ])
          ]),
          createElementVNode("div", _hoisted_7$4, [
            createElementVNode("div", _hoisted_8$3, [
              createElementVNode("div", _hoisted_9$2, [
                createElementVNode("a", {
                  class: "learn-more-link",
                  href: changelogUrl.value,
                  target: "_blank",
                  rel: "noopener,noreferrer",
                  onClick: handleLearnMore
                }, toDisplayString(_ctx.$t("releaseToast.whatsNew")), 9, _hoisted_10$2)
              ]),
              createElementVNode("div", _hoisted_11$1, [
                createElementVNode("button", {
                  class: "skip-button",
                  onClick: handleSkip
                }, toDisplayString(_ctx.$t("releaseToast.skip")), 1),
                createElementVNode("button", {
                  class: "cta-button",
                  onClick: handleUpdate
                }, toDisplayString(_ctx.$t("releaseToast.update")), 1)
              ])
            ])
          ])
        ])
      ])) : createCommentVNode("", true);
    };
  }
});
const ReleaseNotificationToast = /* @__PURE__ */ _export_sfc(_sfc_main$11, [["__scopeId", "data-v-a462d327"]]);
const _hoisted_1$Z = {
  key: 0,
  class: "whats-new-popup-container"
};
const _hoisted_2$u = ["aria-label"];
const _hoisted_3$i = { class: "popup-content" };
const _hoisted_4$e = ["innerHTML"];
const _hoisted_5$7 = { class: "popup-actions" };
const _hoisted_6$5 = ["href"];
const _sfc_main$10 = /* @__PURE__ */ defineComponent({
  __name: "WhatsNewPopup",
  emits: ["whats-new-dismissed"],
  setup(__props, { expose: __expose, emit: __emit }) {
    const { locale, t: t2 } = useI18n();
    const releaseStore2 = useReleaseStore();
    const emit = __emit;
    const isDismissed = ref(false);
    const latestRelease = computed(
      () => releaseStore2.recentRelease
    );
    const shouldShow = computed(
      () => releaseStore2.shouldShowPopup && !isDismissed.value
    );
    const changelogUrl = computed(() => {
      const isChineseLocale = locale.value === "zh";
      const baseUrl = isChineseLocale ? "https://docs.comfy.org/zh-CN/changelog" : "https://docs.comfy.org/changelog";
      if (latestRelease.value?.version) {
        const versionAnchor = formatVersionAnchor(latestRelease.value.version);
        return `${baseUrl}#${versionAnchor}`;
      }
      return baseUrl;
    });
    const formattedContent = computed(() => {
      if (!latestRelease.value?.content) {
        return `<p>${t2("whatsNewPopup.noReleaseNotes")}</p>`;
      }
      try {
        return marked(latestRelease.value.content, {
          gfm: true
          // Enable GitHub Flavored Markdown
        });
      } catch (error) {
        console.error("Error parsing markdown:", error);
        return latestRelease.value.content.replace(/\n/g, "<br>");
      }
    });
    const show = /* @__PURE__ */ __name(() => {
      isDismissed.value = false;
    }, "show");
    const hide = /* @__PURE__ */ __name(() => {
      isDismissed.value = true;
      emit("whats-new-dismissed");
    }, "hide");
    const closePopup = /* @__PURE__ */ __name(async () => {
      if (latestRelease.value) {
        await releaseStore2.handleWhatsNewSeen(latestRelease.value.version);
      }
      hide();
    }, "closePopup");
    onMounted(async () => {
      if (!releaseStore2.releases.length) {
        await releaseStore2.fetchReleases();
      }
    });
    __expose({
      show,
      hide
    });
    return (_ctx, _cache) => {
      return shouldShow.value ? (openBlock(), createElementBlock("div", _hoisted_1$Z, [
        _cache[2] || (_cache[2] = createStaticVNode('<div class="help-center-arrow" data-v-10b7862a><svg xmlns="http://www.w3.org/2000/svg" width="16" height="19" viewBox="0 0 16 19" fill="none" data-v-10b7862a><path d="M15.25 1.27246L15.25 17.7275L0.999023 9.5L15.25 1.27246Z" fill="#353535" data-v-10b7862a></path><path d="M15.25 1.27246L0.999023 9.5" stroke="#4e4e4e" stroke-width="1" fill="none" data-v-10b7862a></path><path d="M0.999023 9.5L15.25 17.7275" stroke="#4e4e4e" stroke-width="1" fill="none" data-v-10b7862a></path></svg></div>', 1)),
        createElementVNode("div", {
          class: "whats-new-popup",
          onClick: _cache[0] || (_cache[0] = withModifiers(() => {
          }, ["stop"]))
        }, [
          createElementVNode("button", {
            class: "close-button",
            "aria-label": _ctx.$t("g.close"),
            onClick: closePopup
          }, _cache[1] || (_cache[1] = [
            createElementVNode("div", { class: "close-icon" }, null, -1)
          ]), 8, _hoisted_2$u),
          createElementVNode("div", _hoisted_3$i, [
            createElementVNode("div", {
              class: "content-text",
              innerHTML: formattedContent.value
            }, null, 8, _hoisted_4$e),
            createElementVNode("div", _hoisted_5$7, [
              createElementVNode("a", {
                class: "learn-more-link",
                href: changelogUrl.value,
                target: "_blank",
                rel: "noopener,noreferrer",
                onClick: closePopup
              }, toDisplayString(_ctx.$t("whatsNewPopup.learnMore")), 9, _hoisted_6$5)
            ])
          ])
        ])
      ])) : createCommentVNode("", true);
    };
  }
});
const WhatsNewPopup = /* @__PURE__ */ _export_sfc(_sfc_main$10, [["__scopeId", "data-v-10b7862a"]]);
const useHelpCenterStore = defineStore("helpCenter", () => {
  const isVisible = ref(false);
  const toggle = /* @__PURE__ */ __name(() => {
    isVisible.value = !isVisible.value;
  }, "toggle");
  const show = /* @__PURE__ */ __name(() => {
    isVisible.value = true;
  }, "show");
  const hide = /* @__PURE__ */ __name(() => {
    isVisible.value = false;
  }, "hide");
  return {
    isVisible,
    toggle,
    show,
    hide
  };
});
const _sfc_main$$ = /* @__PURE__ */ defineComponent({
  __name: "SidebarHelpCenterIcon",
  setup(__props) {
    const settingStore = useSettingStore();
    const releaseStore2 = useReleaseStore();
    const helpCenterStore = useHelpCenterStore();
    const { isVisible: isHelpCenterVisible } = storeToRefs(helpCenterStore);
    const { shouldShowRedDot: showReleaseRedDot } = storeToRefs(releaseStore2);
    const conflictDetection = useConflictDetection();
    const { showNodeConflictDialog } = useDialogService();
    const { shouldShowRedDot: shouldShowConflictRedDot, markConflictsAsSeen } = useConflictAcknowledgment();
    const shouldShowRedDot = computed(() => {
      const releaseRedDot = showReleaseRedDot;
      return releaseRedDot || shouldShowConflictRedDot.value;
    });
    const sidebarLocation = computed(
      () => settingStore.get("Comfy.Sidebar.Location")
    );
    const sidebarSize = computed(() => settingStore.get("Comfy.Sidebar.Size"));
    const toggleHelpCenter = /* @__PURE__ */ __name(() => {
      helpCenterStore.toggle();
    }, "toggleHelpCenter");
    const closeHelpCenter = /* @__PURE__ */ __name(() => {
      helpCenterStore.hide();
    }, "closeHelpCenter");
    const handleWhatsNewDismissed = /* @__PURE__ */ __name(async () => {
      try {
        const shouldShow = await conflictDetection.shouldShowConflictModalAfterUpdate();
        if (shouldShow) {
          showConflictModal();
        }
      } catch (error) {
        console.error("[HelpCenter] Error checking conflict modal:", error);
      }
    }, "handleWhatsNewDismissed");
    const showConflictModal = /* @__PURE__ */ __name(() => {
      showNodeConflictDialog({
        showAfterWhatsNew: true,
        dialogComponentProps: {
          onClose: /* @__PURE__ */ __name(() => {
            markConflictsAsSeen();
          }, "onClose")
        }
      });
    }, "showConflictModal");
    onMounted(async () => {
      await releaseStore2.initialize();
    });
    return (_ctx, _cache) => {
      return openBlock(), createElementBlock("div", null, [
        createVNode(SidebarIcon, {
          icon: "pi pi-question-circle",
          class: "comfy-help-center-btn",
          tooltip: _ctx.$t("sideToolbar.helpCenter"),
          "icon-badge": shouldShowRedDot.value ? "•" : "",
          onClick: toggleHelpCenter
        }, null, 8, ["tooltip", "icon-badge"]),
        (openBlock(), createBlock(Teleport, { to: "#graph-canvas-container" }, [
          unref(isHelpCenterVisible) ? (openBlock(), createElementBlock("div", {
            key: 0,
            class: normalizeClass(["help-center-popup", {
              "sidebar-left": sidebarLocation.value === "left",
              "sidebar-right": sidebarLocation.value === "right",
              "small-sidebar": sidebarSize.value === "small"
            }])
          }, [
            createVNode(HelpCenterMenuContent, { onClose: closeHelpCenter })
          ], 2)) : createCommentVNode("", true)
        ])),
        (openBlock(), createBlock(Teleport, { to: "#graph-canvas-container" }, [
          createVNode(ReleaseNotificationToast, {
            class: normalizeClass({
              "sidebar-left": sidebarLocation.value === "left",
              "sidebar-right": sidebarLocation.value === "right",
              "small-sidebar": sidebarSize.value === "small"
            })
          }, null, 8, ["class"])
        ])),
        (openBlock(), createBlock(Teleport, { to: "#graph-canvas-container" }, [
          createVNode(WhatsNewPopup, {
            class: normalizeClass({
              "sidebar-left": sidebarLocation.value === "left",
              "sidebar-right": sidebarLocation.value === "right",
              "small-sidebar": sidebarSize.value === "small"
            }),
            onWhatsNewDismissed: handleWhatsNewDismissed
          }, null, 8, ["class"])
        ])),
        (openBlock(), createBlock(Teleport, { to: "body" }, [
          unref(isHelpCenterVisible) ? (openBlock(), createElementBlock("div", {
            key: 0,
            class: "help-center-backdrop",
            onClick: closeHelpCenter
          })) : createCommentVNode("", true)
        ]))
      ]);
    };
  }
});
const SidebarHelpCenterIcon = /* @__PURE__ */ _export_sfc(_sfc_main$$, [["__scopeId", "data-v-9cda3dbd"]]);
const _sfc_main$_ = /* @__PURE__ */ defineComponent({
  __name: "SidebarLogoutIcon",
  setup(__props) {
    const { t: t2 } = useI18n();
    const userStore = useUserStore();
    const tooltip = computed(
      () => `${t2("sideToolbar.logout")} (${userStore.currentUser?.username})`
    );
    const logout = /* @__PURE__ */ __name(async () => {
      await userStore.logout();
      window.location.reload();
    }, "logout");
    return (_ctx, _cache) => {
      return openBlock(), createBlock(SidebarIcon, {
        icon: "pi pi-sign-out",
        tooltip: tooltip.value,
        onClick: logout
      }, null, 8, ["tooltip"]);
    };
  }
});
const _sfc_main$Z = /* @__PURE__ */ defineComponent({
  __name: "SidebarTemplatesButton",
  setup(__props) {
    const settingStore = useSettingStore();
    const commandStore = useCommandStore();
    const isSmall = computed(
      () => settingStore.get("Comfy.Sidebar.Size") === "small"
    );
    const openTemplates = /* @__PURE__ */ __name(() => {
      void commandStore.execute("Comfy.BrowseTemplates");
    }, "openTemplates");
    return (_ctx, _cache) => {
      return openBlock(), createBlock(SidebarIcon, {
        icon: "icon-[comfy--template]",
        tooltip: _ctx.$t("sideToolbar.templates"),
        label: _ctx.$t("sideToolbar.labels.templates"),
        "is-small": isSmall.value,
        class: "templates-tab-button",
        onClick: openTemplates
      }, null, 8, ["tooltip", "label", "is-small"]);
    };
  }
});
const _hoisted_1$Y = { class: "side-tool-bar-end" };
const _hoisted_2$t = {
  key: 0,
  class: "sidebar-content-container h-full overflow-y-auto overflow-x-hidden"
};
const _sfc_main$Y = /* @__PURE__ */ defineComponent({
  __name: "SideToolbar",
  setup(__props) {
    const workspaceStore = useWorkspaceStore();
    const settingStore = useSettingStore();
    const userStore = useUserStore();
    const teleportTarget = computed(
      () => settingStore.get("Comfy.Sidebar.Location") === "left" ? ".comfyui-body-left" : ".comfyui-body-right"
    );
    const isSmall = computed(
      () => settingStore.get("Comfy.Sidebar.Size") === "small"
    );
    const tabs = computed(() => workspaceStore.getSidebarTabs());
    const selectedTab = computed(() => workspaceStore.sidebarTab.activeSidebarTab);
    const onTabClick = /* @__PURE__ */ __name((item) => {
      workspaceStore.sidebarTab.toggleSidebarTab(item.id);
    }, "onTabClick");
    const keybindingStore = useKeybindingStore();
    const getTabTooltipSuffix = /* @__PURE__ */ __name((tab) => {
      const keybinding = keybindingStore.getKeybindingByCommandId(
        `Workspace.ToggleSidebarTab.${tab.id}`
      );
      return keybinding ? ` (${keybinding.combo.toString()})` : "";
    }, "getTabTooltipSuffix");
    return (_ctx, _cache) => {
      return openBlock(), createElementBlock(Fragment, null, [
        (openBlock(), createBlock(Teleport, { to: teleportTarget.value }, [
          createElementVNode("nav", {
            class: normalizeClass(["side-tool-bar-container", { "small-sidebar": isSmall.value }])
          }, [
            (openBlock(true), createElementBlock(Fragment, null, renderList(tabs.value, (tab) => {
              return openBlock(), createBlock(SidebarIcon, {
                key: tab.id,
                icon: tab.icon,
                "icon-badge": tab.iconBadge,
                tooltip: tab.tooltip,
                "tooltip-suffix": getTabTooltipSuffix(tab),
                label: tab.label || tab.title,
                "is-small": isSmall.value,
                selected: tab.id === selectedTab.value?.id,
                class: normalizeClass(tab.id + "-tab-button"),
                onClick: /* @__PURE__ */ __name(($event) => onTabClick(tab), "onClick")
              }, null, 8, ["icon", "icon-badge", "tooltip", "tooltip-suffix", "label", "is-small", "selected", "class", "onClick"]);
            }), 128)),
            createVNode(_sfc_main$Z),
            createElementVNode("div", _hoisted_1$Y, [
              unref(userStore).isMultiUserServer ? (openBlock(), createBlock(_sfc_main$_, { key: 0 })) : createCommentVNode("", true),
              createVNode(SidebarHelpCenterIcon),
              createVNode(_sfc_main$15),
              createVNode(_sfc_main$14)
            ])
          ], 2)
        ], 8, ["to"])),
        selectedTab.value ? (openBlock(), createElementBlock("div", _hoisted_2$t, [
          createVNode(_sfc_main$1x, { extension: selectedTab.value }, null, 8, ["extension"])
        ])) : createCommentVNode("", true)
      ], 64);
    };
  }
});
const SideToolbar = /* @__PURE__ */ _export_sfc(_sfc_main$Y, [["__scopeId", "data-v-9f7aa991"]]);
const _hoisted_1$X = { class: "workflow-preview-content" };
const _hoisted_2$s = {
  key: 0,
  class: "workflow-preview-thumbnail relative"
};
const _hoisted_3$h = ["src"];
const _hoisted_4$d = { class: "workflow-preview-footer" };
const _hoisted_5$6 = { class: "workflow-preview-name" };
const POPOVER_WIDTH = 250;
const _sfc_main$X = /* @__PURE__ */ defineComponent({
  __name: "WorkflowTabPopover",
  props: {
    workflowFilename: {},
    thumbnailUrl: {},
    isActiveTab: { type: Boolean }
  },
  setup(__props, { expose: __expose }) {
    const props = __props;
    const { thumbnailUrl, isActiveTab } = toRefs(props);
    const settingStore = useSettingStore();
    const positions = computed(() => {
      if (settingStore.get("Comfy.Workflow.WorkflowTabsPosition") === "Topbar" && settingStore.get("Comfy.UseNewMenu") === "Bottom") {
        return {
          positioner: "top-0",
          root: "p-popover-flipped",
          active: isActiveTab.value ? "translateY(-100%)" : void 0
        };
      }
      return {
        positioner: "bottom-0"
      };
    });
    const popoverRef = ref(null);
    const positionRef = ref(null);
    let hideTimeout = null;
    let showTimeout = null;
    const id = useId();
    const showPopover = /* @__PURE__ */ __name((event) => {
      if (hideTimeout) {
        clearTimeout(hideTimeout);
        hideTimeout = null;
      }
      if (showTimeout) {
        clearTimeout(showTimeout);
        showTimeout = null;
      }
      showTimeout = setTimeout(async () => {
        if (popoverRef.value && positionRef.value) {
          popoverRef.value.show(event, positionRef.value);
          await nextTick();
          const el = document.querySelector(
            `.workflow-popover-fade[data-popover-id="${id}"]`
          );
          if (el) {
            const middle = positionRef.value.getBoundingClientRect().left;
            const popoverWidth = el.getBoundingClientRect().width;
            const halfWidth = popoverWidth / 2;
            let pos = middle - halfWidth;
            let shift = 0;
            if (pos < 0) {
              shift = pos - 8;
              pos = 8;
            } else if (pos + popoverWidth > window.innerWidth) {
              const newPos = window.innerWidth - popoverWidth - 16;
              shift = pos - newPos;
              pos = newPos;
            }
            if (shift + halfWidth < 0) {
              shift = -halfWidth + 24;
            }
            el.style.left = `${pos}px`;
            el.style.setProperty("--shift", `${shift}px`);
          }
        }
      }, 200);
    }, "showPopover");
    const cancelHidePopover = /* @__PURE__ */ __name(() => {
    }, "cancelHidePopover");
    const hidePopover = /* @__PURE__ */ __name(() => {
      if (showTimeout) {
        clearTimeout(showTimeout);
        showTimeout = null;
      }
      hideTimeout = setTimeout(() => {
        if (popoverRef.value) {
          popoverRef.value.hide();
        }
      }, 100);
    }, "hidePopover");
    const togglePopover = /* @__PURE__ */ __name((event) => {
      if (popoverRef.value) {
        popoverRef.value.toggle(event);
      }
    }, "togglePopover");
    __expose({
      showPopover,
      hidePopover,
      togglePopover
    });
    return (_ctx, _cache) => {
      return openBlock(), createElementBlock(Fragment, null, [
        createElementVNode("div", {
          ref_key: "positionRef",
          ref: positionRef,
          class: normalizeClass(["absolute left-1/2 -translate-x-1/2", positions.value.positioner])
        }, null, 2),
        createVNode(unref(Popover), {
          ref_key: "popoverRef",
          ref: popoverRef,
          "append-to": "body",
          pt: {
            root: {
              class: "workflow-popover-fade fit-content " + positions.value.root,
              "data-popover-id": unref(id),
              style: {
                transform: positions.value.active
              }
            }
          },
          onMouseenter: cancelHidePopover,
          onMouseleave: hidePopover
        }, {
          default: withCtx(() => [
            createElementVNode("div", _hoisted_1$X, [
              unref(thumbnailUrl) && !unref(isActiveTab) ? (openBlock(), createElementBlock("div", _hoisted_2$s, [
                createElementVNode("img", {
                  src: unref(thumbnailUrl),
                  class: "block h-[200px] object-cover rounded-lg p-2",
                  style: normalizeStyle({ width: `${POPOVER_WIDTH}px` })
                }, null, 12, _hoisted_3$h)
              ])) : createCommentVNode("", true),
              createElementVNode("div", _hoisted_4$d, [
                createElementVNode("span", _hoisted_5$6, toDisplayString(_ctx.workflowFilename), 1)
              ])
            ])
          ]),
          _: 1
        }, 8, ["pt"])
      ], 64);
    };
  }
});
const WorkflowTabPopover = /* @__PURE__ */ _export_sfc(_sfc_main$X, [["__scopeId", "data-v-ae7948e9"]]);
const _hoisted_1$W = { class: "workflow-label text-sm max-w-[150px] truncate inline-block" };
const _hoisted_2$r = { class: "relative" };
const _hoisted_3$g = {
  key: 0,
  class: "status-indicator"
};
const _sfc_main$W = /* @__PURE__ */ defineComponent({
  __name: "WorkflowTab",
  props: {
    class: {},
    workflowOption: {}
  },
  setup(__props) {
    const props = __props;
    const { t: t2 } = useI18n();
    const workspaceStore = useWorkspaceStore();
    const workflowStore = useWorkflowStore();
    const settingStore = useSettingStore();
    const workflowTabRef = ref(null);
    const popoverRef = ref(null);
    const workflowThumbnail = useWorkflowThumbnail();
    const autoSaveSetting = computed(
      () => settingStore.get("Comfy.Workflow.AutoSave")
    );
    const autoSaveDelay = computed(
      () => settingStore.get("Comfy.Workflow.AutoSaveDelay")
    );
    const shouldShowStatusIndicator = computed(() => {
      if (workspaceStore.shiftDown) {
        return false;
      }
      if (!props.workflowOption.workflow.isPersisted) {
        return true;
      }
      if (props.workflowOption.workflow.isModified) {
        if (autoSaveSetting.value === "off") {
          return true;
        }
        if (autoSaveSetting.value === "after delay" && autoSaveDelay.value > 3e3) {
          return true;
        }
        return false;
      }
      return false;
    });
    const isActiveTab = computed(() => {
      return workflowStore.activeWorkflow?.key === props.workflowOption.workflow.key;
    });
    const thumbnailUrl = computed(() => {
      return workflowThumbnail.getThumbnail(props.workflowOption.workflow.key);
    });
    const handleMouseEnter = /* @__PURE__ */ __name((event) => {
      popoverRef.value?.showPopover(event);
    }, "handleMouseEnter");
    const handleMouseLeave = /* @__PURE__ */ __name(() => {
      popoverRef.value?.hidePopover();
    }, "handleMouseLeave");
    const handleClick = /* @__PURE__ */ __name((event) => {
      popoverRef.value?.togglePopover(event);
    }, "handleClick");
    const closeWorkflows = /* @__PURE__ */ __name(async (options) => {
      for (const opt of options) {
        if (!await useWorkflowService().closeWorkflow(opt.workflow, {
          warnIfUnsaved: !workspaceStore.shiftDown,
          hint: t2("sideToolbar.workflowTab.dirtyCloseHint")
        })) {
          break;
        }
      }
    }, "closeWorkflows");
    const onCloseWorkflow = /* @__PURE__ */ __name(async (option) => {
      await closeWorkflows([option]);
    }, "onCloseWorkflow");
    const tabGetter = /* @__PURE__ */ __name(() => workflowTabRef.value, "tabGetter");
    usePragmaticDraggable(tabGetter, {
      getInitialData: /* @__PURE__ */ __name(() => {
        return {
          workflowKey: props.workflowOption.workflow.key
        };
      }, "getInitialData")
    });
    usePragmaticDroppable(tabGetter, {
      getData: /* @__PURE__ */ __name(() => {
        return {
          workflowKey: props.workflowOption.workflow.key
        };
      }, "getData"),
      onDrop: /* @__PURE__ */ __name((e) => {
        const fromIndex = workflowStore.openWorkflows.findIndex(
          (wf) => wf.key === e.source.data.workflowKey
        );
        const toIndex = workflowStore.openWorkflows.findIndex(
          (wf) => wf.key === e.location.current.dropTargets[0]?.data.workflowKey
        );
        if (fromIndex !== toIndex) {
          workflowStore.reorderWorkflows(fromIndex, toIndex);
        }
      }, "onDrop")
    });
    onUnmounted(() => {
      popoverRef.value?.hidePopover();
    });
    return (_ctx, _cache) => {
      return openBlock(), createElementBlock(Fragment, null, [
        createElementVNode("div", mergeProps({
          ref_key: "workflowTabRef",
          ref: workflowTabRef,
          class: "flex p-2 gap-2 workflow-tab"
        }, _ctx.$attrs, {
          onMouseenter: handleMouseEnter,
          onMouseleave: handleMouseLeave,
          onClick: handleClick
        }), [
          createElementVNode("span", _hoisted_1$W, toDisplayString(_ctx.workflowOption.workflow.filename), 1),
          createElementVNode("div", _hoisted_2$r, [
            shouldShowStatusIndicator.value ? (openBlock(), createElementBlock("span", _hoisted_3$g, "•")) : createCommentVNode("", true),
            createVNode(unref(Button), {
              class: "close-button p-0 w-auto",
              icon: "pi pi-times",
              text: "",
              severity: "secondary",
              size: "small",
              onClick: _cache[0] || (_cache[0] = withModifiers(($event) => onCloseWorkflow(_ctx.workflowOption), ["stop"]))
            })
          ])
        ], 16),
        createVNode(WorkflowTabPopover, {
          ref_key: "popoverRef",
          ref: popoverRef,
          "workflow-filename": _ctx.workflowOption.workflow.filename,
          "thumbnail-url": thumbnailUrl.value,
          "is-active-tab": isActiveTab.value
        }, null, 8, ["workflow-filename", "thumbnail-url", "is-active-tab"])
      ], 64);
    };
  }
});
const WorkflowTab = /* @__PURE__ */ _export_sfc(_sfc_main$W, [["__scopeId", "data-v-3b7233a9"]]);
const useOverflowObserver = /* @__PURE__ */ __name((element, options) => {
  options = {
    debounceTime: 25,
    useMutationObserver: true,
    useResizeObserver: true,
    ...options
  };
  const isOverflowing = ref(false);
  const disposeFns = [];
  const disposed = ref(false);
  const checkOverflowFn = /* @__PURE__ */ __name(() => {
    isOverflowing.value = element.scrollWidth > element.clientWidth;
    options.onCheck?.(isOverflowing.value);
  }, "checkOverflowFn");
  const checkOverflow = options.debounceTime ? debounce(checkOverflowFn, options.debounceTime) : checkOverflowFn;
  if (options.useMutationObserver) {
    disposeFns.push(
      useMutationObserver(element, checkOverflow, {
        subtree: true,
        childList: true
      }).stop
    );
  }
  if (options.useResizeObserver) {
    disposeFns.push(useResizeObserver(element, checkOverflow).stop);
  }
  return {
    isOverflowing: readonly(isOverflowing),
    disposed: readonly(disposed),
    checkOverflow,
    dispose: /* @__PURE__ */ __name(() => {
      disposed.value = true;
      disposeFns.forEach((fn) => fn());
    }, "dispose")
  };
}, "useOverflowObserver");
const whileMouseDown = /* @__PURE__ */ __name((elementOrEvent, callback, interval = 30) => {
  const element = elementOrEvent instanceof HTMLElement ? elementOrEvent : elementOrEvent.target;
  let iteration = 0;
  const intervalId = setInterval(() => {
    callback(iteration++);
  }, interval);
  const dispose = /* @__PURE__ */ __name(() => {
    clearInterval(intervalId);
    disposeGlobal();
    disposeLocal();
  }, "dispose");
  const disposeGlobal = useEventListener(document, "mouseup", dispose);
  const disposeLocal = useEventListener(element, "mouseup", dispose);
  return {
    dispose
  };
}, "whileMouseDown");
const _sfc_main$V = /* @__PURE__ */ defineComponent({
  __name: "WorkflowOverflowMenu",
  props: {
    workflows: {},
    activeWorkflow: {}
  },
  setup(__props) {
    const props = __props;
    const menu = ref(null);
    const workflowService = useWorkflowService();
    const menuItems = computed(
      () => props.workflows.map((workflow) => ({
        label: workflow.filename,
        icon: props.activeWorkflow?.key === workflow.key ? "pi pi-check" : void 0,
        command: /* @__PURE__ */ __name(() => {
          void workflowService.openWorkflow(workflow);
        }, "command")
      }))
    );
    return (_ctx, _cache) => {
      const _directive_tooltip = resolveDirective("tooltip");
      return openBlock(), createElementBlock("div", null, [
        withDirectives(createVNode(unref(Button), {
          class: "rounded-none",
          icon: "pi pi-ellipsis-h",
          text: "",
          severity: "secondary",
          "aria-label": _ctx.$t("g.moreWorkflows"),
          onClick: _cache[0] || (_cache[0] = ($event) => menu.value?.toggle($event))
        }, null, 8, ["aria-label"]), [
          [_directive_tooltip, { value: _ctx.$t("g.moreWorkflows"), showDelay: 300 }]
        ]),
        createVNode(unref(Menu), {
          ref_key: "menu",
          ref: menu,
          model: menuItems.value,
          popup: true,
          class: "max-h-[40vh] overflow-auto"
        }, null, 8, ["model"])
      ]);
    };
  }
});
const _hoisted_1$V = {
  key: 3,
  class: "window-actions-spacer shrink-0 app-drag"
};
const _sfc_main$U = /* @__PURE__ */ defineComponent({
  __name: "WorkflowTabs",
  props: {
    class: {}
  },
  setup(__props) {
    const props = __props;
    const { t: t2 } = useI18n();
    const workspaceStore = useWorkspaceStore();
    const workflowStore = useWorkflowStore();
    const workflowBookmarkStore = useWorkflowBookmarkStore();
    const settingStore = useSettingStore();
    const workflowService = useWorkflowService();
    const rightClickedTab = ref();
    const menu = ref();
    const scrollPanelRef = ref();
    const showOverflowArrows = ref(false);
    const leftArrowEnabled = ref(false);
    const rightArrowEnabled = ref(false);
    const isDesktop = isElectron();
    const menuSetting = computed(() => settingStore.get("Comfy.UseNewMenu"));
    const workflowToOption = /* @__PURE__ */ __name((workflow) => ({
      value: workflow.path,
      workflow
    }), "workflowToOption");
    const options = computed(
      () => workflowStore.openWorkflows.map(workflowToOption)
    );
    const selectedWorkflow = computed(
      () => workflowStore.activeWorkflow ? workflowToOption(workflowStore.activeWorkflow) : null
    );
    const onWorkflowChange = /* @__PURE__ */ __name(async (option) => {
      if (!option) {
        return;
      }
      if (selectedWorkflow.value?.value === option.value) {
        return;
      }
      await workflowService.openWorkflow(option.workflow);
    }, "onWorkflowChange");
    const closeWorkflows = /* @__PURE__ */ __name(async (options2) => {
      for (const opt of options2) {
        if (!await workflowService.closeWorkflow(opt.workflow, {
          warnIfUnsaved: !workspaceStore.shiftDown
        })) {
          break;
        }
      }
    }, "closeWorkflows");
    const onCloseWorkflow = /* @__PURE__ */ __name(async (option) => {
      await closeWorkflows([option]);
    }, "onCloseWorkflow");
    const showContextMenu = /* @__PURE__ */ __name((event, option) => {
      rightClickedTab.value = option;
      menu.value.show(event);
    }, "showContextMenu");
    const contextMenuItems = computed(() => {
      const tab = rightClickedTab.value;
      if (!tab) return [];
      const index = options.value.findIndex((v) => v.workflow === tab.workflow);
      return [
        {
          label: t2("tabMenu.duplicateTab"),
          command: /* @__PURE__ */ __name(async () => {
            await workflowService.duplicateWorkflow(tab.workflow);
          }, "command")
        },
        {
          separator: true
        },
        {
          label: t2("tabMenu.closeTab"),
          command: /* @__PURE__ */ __name(() => onCloseWorkflow(tab), "command")
        },
        {
          label: t2("tabMenu.closeTabsToLeft"),
          command: /* @__PURE__ */ __name(() => closeWorkflows(options.value.slice(0, index)), "command"),
          disabled: index <= 0
        },
        {
          label: t2("tabMenu.closeTabsToRight"),
          command: /* @__PURE__ */ __name(() => closeWorkflows(options.value.slice(index + 1)), "command"),
          disabled: index === options.value.length - 1
        },
        {
          label: t2("tabMenu.closeOtherTabs"),
          command: /* @__PURE__ */ __name(() => closeWorkflows([
            ...options.value.slice(index + 1),
            ...options.value.slice(0, index)
          ]), "command"),
          disabled: options.value.length <= 1
        },
        {
          label: workflowBookmarkStore.isBookmarked(tab.workflow.path) ? t2("tabMenu.removeFromBookmarks") : t2("tabMenu.addToBookmarks"),
          command: /* @__PURE__ */ __name(() => workflowBookmarkStore.toggleBookmarked(tab.workflow.path), "command"),
          disabled: tab.workflow.isTemporary
        }
      ];
    });
    const commandStore = useCommandStore();
    const handleWheel = /* @__PURE__ */ __name((event) => {
      const scrollElement = event.currentTarget;
      const scrollAmount = event.deltaX || event.deltaY;
      scrollElement.scroll({
        left: scrollElement.scrollLeft + scrollAmount
      });
    }, "handleWheel");
    const scroll = /* @__PURE__ */ __name((direction) => {
      const scrollElement = scrollPanelRef.value.$el.querySelector(
        ".p-scrollpanel-content"
      );
      scrollElement.scrollBy({ left: direction * 20 });
    }, "scroll");
    watch(
      () => workflowStore.activeWorkflow,
      async () => {
        if (!selectedWorkflow.value) return;
        await nextTick();
        const activeTabElement = document.querySelector(".p-togglebutton-checked");
        if (!activeTabElement || !scrollPanelRef.value) return;
        const container = scrollPanelRef.value.$el.querySelector(
          ".p-scrollpanel-content"
        );
        if (!container) return;
        const tabRect = activeTabElement.getBoundingClientRect();
        const containerRect = container.getBoundingClientRect();
        const offsetLeft = tabRect.left - containerRect.left;
        const offsetRight = tabRect.right - containerRect.right;
        if (offsetRight > 0) {
          container.scrollBy({ left: offsetRight });
        } else if (offsetLeft < 0) {
          container.scrollBy({ left: offsetLeft });
        }
      },
      { immediate: true }
    );
    const scrollContent = computed(
      () => scrollPanelRef.value?.$el.querySelector(
        ".p-scrollpanel-content"
      )
    );
    let overflowObserver = null;
    let overflowWatch = null;
    watch(scrollContent, (value) => {
      const scrollState = useScroll(value);
      watch(scrollState.arrivedState, () => {
        leftArrowEnabled.value = !scrollState.arrivedState.left;
        rightArrowEnabled.value = !scrollState.arrivedState.right;
      });
      overflowObserver?.dispose();
      overflowWatch?.stop();
      overflowObserver = useOverflowObserver(value);
      overflowWatch = watch(
        overflowObserver.isOverflowing,
        (value2) => {
          showOverflowArrows.value = value2;
          void nextTick(() => {
            scrollState.measure();
          });
        },
        { immediate: true }
      );
    });
    onUpdated(() => {
      if (!overflowObserver?.disposed.value) {
        overflowObserver?.checkOverflow();
      }
    });
    return (_ctx, _cache) => {
      const _directive_tooltip = resolveDirective("tooltip");
      return openBlock(), createElementBlock("div", {
        class: normalizeClass(["workflow-tabs-container flex flex-row max-w-full h-full flex-auto overflow-hidden", { "workflow-tabs-container-desktop": unref(isDesktop) }])
      }, [
        showOverflowArrows.value ? (openBlock(), createBlock(unref(Button), {
          key: 0,
          icon: "pi pi-chevron-left",
          text: "",
          severity: "secondary",
          class: "overflow-arrow overflow-arrow-left",
          disabled: !leftArrowEnabled.value,
          onMousedown: _cache[0] || (_cache[0] = ($event) => unref(whileMouseDown)($event, () => scroll(-1)))
        }, null, 8, ["disabled"])) : createCommentVNode("", true),
        createVNode(unref(ScrollPanel), {
          ref_key: "scrollPanelRef",
          ref: scrollPanelRef,
          class: "overflow-hidden no-drag",
          "pt:content": {
            class: "p-0 w-full flex",
            onwheel: handleWheel
          },
          "pt:bar-x": "h-1"
        }, {
          default: withCtx(() => [
            createVNode(unref(SelectButton), {
              class: normalizeClass(["workflow-tabs bg-transparent", props.class]),
              "model-value": selectedWorkflow.value,
              options: options.value,
              "option-label": "label",
              "data-key": "value",
              "onUpdate:modelValue": onWorkflowChange
            }, {
              option: withCtx(({ option }) => [
                createVNode(WorkflowTab, {
                  "workflow-option": option,
                  onContextmenu: /* @__PURE__ */ __name(($event) => showContextMenu($event, option), "onContextmenu"),
                  onMouseup: withModifiers(($event) => onCloseWorkflow(option), ["middle"])
                }, null, 8, ["workflow-option", "onContextmenu", "onMouseup"])
              ]),
              _: 1
            }, 8, ["class", "model-value", "options"])
          ]),
          _: 1
        }, 8, ["pt:content"]),
        showOverflowArrows.value ? (openBlock(), createBlock(unref(Button), {
          key: 1,
          icon: "pi pi-chevron-right",
          text: "",
          severity: "secondary",
          class: "overflow-arrow overflow-arrow-right",
          disabled: !rightArrowEnabled.value,
          onMousedown: _cache[1] || (_cache[1] = ($event) => unref(whileMouseDown)($event, () => scroll(1)))
        }, null, 8, ["disabled"])) : createCommentVNode("", true),
        showOverflowArrows.value ? (openBlock(), createBlock(_sfc_main$V, {
          key: 2,
          workflows: unref(workflowStore).openWorkflows,
          "active-workflow": unref(workflowStore).activeWorkflow
        }, null, 8, ["workflows", "active-workflow"])) : createCommentVNode("", true),
        withDirectives(createVNode(unref(Button), {
          class: "new-blank-workflow-button shrink-0 no-drag rounded-none",
          icon: "pi pi-plus",
          text: "",
          severity: "secondary",
          "aria-label": _ctx.$t("sideToolbar.newBlankWorkflow"),
          onClick: _cache[2] || (_cache[2] = () => unref(commandStore).execute("Comfy.NewBlankWorkflow"))
        }, null, 8, ["aria-label"]), [
          [_directive_tooltip, { value: _ctx.$t("sideToolbar.newBlankWorkflow"), showDelay: 300 }]
        ]),
        createVNode(unref(ContextMenu), {
          ref_key: "menu",
          ref: menu,
          model: contextMenuItems.value
        }, null, 8, ["model"]),
        menuSetting.value !== "Bottom" && unref(isDesktop) ? (openBlock(), createElementBlock("div", _hoisted_1$V)) : createCommentVNode("", true)
      ], 2);
    };
  }
});
const WorkflowTabs = /* @__PURE__ */ _export_sfc(_sfc_main$U, [["__scopeId", "data-v-58bfb4fe"]]);
const _hoisted_1$U = { class: "w-auto max-w-full" };
const _sfc_main$T = /* @__PURE__ */ defineComponent({
  __name: "SecondRowWorkflowTabs",
  setup(__props) {
    return (_ctx, _cache) => {
      return openBlock(), createElementBlock("div", _hoisted_1$U, [
        createVNode(WorkflowTabs)
      ]);
    };
  }
});
const SecondRowWorkflowTabs = /* @__PURE__ */ _export_sfc(_sfc_main$T, [["__scopeId", "data-v-2dbac56c"]]);
const useGraphNodeManager = /* @__PURE__ */ __name((graph) => {
  const { moveNode, resizeNode, createNode, deleteNode, setSource } = useLayoutMutations();
  const vueNodeData = reactive(/* @__PURE__ */ new Map());
  const nodeState = reactive(/* @__PURE__ */ new Map());
  const nodePositions = reactive(/* @__PURE__ */ new Map());
  const nodeSizes = reactive(
    /* @__PURE__ */ new Map()
  );
  const nodeRefs = /* @__PURE__ */ new Map();
  const nodeMetadata = /* @__PURE__ */ new WeakMap();
  const performanceMetrics = reactive({
    fps: 0,
    frameTime: 0,
    updateTime: 0,
    nodeCount: 0,
    culledCount: 0,
    callbackUpdateCount: 0,
    rafUpdateCount: 0,
    adaptiveQuality: false
  });
  const spatialIndex = new QuadTree(
    { x: -1e4, y: -1e4, width: 2e4, height: 2e4 },
    { maxDepth: 6, maxItemsPerNode: 4 }
  );
  let lastSpatialQueryTime = 0;
  const spatialMetrics = reactive({
    queryTime: 0,
    nodesInIndex: 0
  });
  const pendingUpdates = /* @__PURE__ */ new Set();
  const criticalUpdates = /* @__PURE__ */ new Set();
  const lowPriorityUpdates = /* @__PURE__ */ new Set();
  let updateScheduled = false;
  let batchTimeoutId = null;
  const lastNodesSnapshot = /* @__PURE__ */ new Map();
  const attachMetadata = /* @__PURE__ */ __name((node) => {
    nodeMetadata.set(node, {
      lastRenderTime: performance.now(),
      cachedBounds: null,
      lodLevel: "high",
      spatialIndex: void 0
    });
  }, "attachMetadata");
  const extractVueNodeData = /* @__PURE__ */ __name((node) => {
    const safeWidgets = node.widgets?.map((widget) => {
      try {
        let value = widget.value;
        if (value === void 0 && widget.type === "combo" && widget.options?.values && Array.isArray(widget.options.values) && widget.options.values.length > 0) {
          value = widget.options.values[0];
        }
        return {
          name: widget.name,
          type: widget.type,
          value,
          options: widget.options ? { ...widget.options } : void 0,
          callback: widget.callback
        };
      } catch (error) {
        return {
          name: widget.name || "unknown",
          type: widget.type || "text",
          value: void 0,
          // Already a valid WidgetValue
          options: void 0,
          callback: void 0
        };
      }
    });
    return {
      id: String(node.id),
      title: node.title || "Untitled",
      type: node.type || "Unknown",
      mode: node.mode || 0,
      selected: node.selected || false,
      executing: false,
      // Will be updated separately based on execution state
      widgets: safeWidgets,
      inputs: node.inputs ? [...node.inputs] : void 0,
      outputs: node.outputs ? [...node.outputs] : void 0,
      flags: node.flags ? { ...node.flags } : void 0
    };
  }, "extractVueNodeData");
  const getNode = /* @__PURE__ */ __name((id) => {
    return nodeRefs.get(id);
  }, "getNode");
  const validateWidgetValue = /* @__PURE__ */ __name((value) => {
    if (value === null || value === void 0 || value === void 0) {
      return void 0;
    }
    if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
      return value;
    }
    if (typeof value === "object") {
      if (Array.isArray(value) && value.every((item) => item instanceof File)) {
        return value;
      }
      return value;
    }
    console.warn(`Invalid widget value type: ${typeof value}`, value);
    return void 0;
  }, "validateWidgetValue");
  const updateVueWidgetState = /* @__PURE__ */ __name((nodeId, widgetName, value) => {
    try {
      const currentData = vueNodeData.get(nodeId);
      if (!currentData?.widgets) return;
      const updatedWidgets = currentData.widgets.map(
        (w) => w.name === widgetName ? { ...w, value: validateWidgetValue(value) } : w
      );
      vueNodeData.set(nodeId, {
        ...currentData,
        widgets: updatedWidgets
      });
      performanceMetrics.callbackUpdateCount++;
    } catch (error) {
    }
  }, "updateVueWidgetState");
  const createWrappedWidgetCallback = /* @__PURE__ */ __name((widget, originalCallback, nodeId) => {
    let updateInProgress = false;
    return (value) => {
      if (updateInProgress) return;
      updateInProgress = true;
      try {
        if (value !== null && value !== void 0 && typeof value !== "string" && typeof value !== "number" && typeof value !== "boolean" && typeof value !== "object") {
          console.warn(`Invalid widget value type: ${typeof value}`);
          updateInProgress = false;
          return;
        }
        widget.value = value;
        if (originalCallback) {
          originalCallback.call(widget, value);
        }
        updateVueWidgetState(nodeId, widget.name, value);
      } finally {
        updateInProgress = false;
      }
    };
  }, "createWrappedWidgetCallback");
  const setupNodeWidgetCallbacks = /* @__PURE__ */ __name((node) => {
    if (!node.widgets) return;
    const nodeId = String(node.id);
    node.widgets.forEach((widget) => {
      const originalCallback = widget.callback;
      widget.callback = createWrappedWidgetCallback(
        widget,
        originalCallback,
        nodeId
      );
    });
  }, "setupNodeWidgetCallbacks");
  const scheduleUpdate = /* @__PURE__ */ __name((nodeId, priority = "normal") => {
    if (nodeId) {
      const state = nodeState.get(nodeId);
      if (state) state.dirty = true;
      if (priority === "critical") {
        criticalUpdates.add(nodeId);
        flush();
        return;
      } else if (priority === "low") {
        lowPriorityUpdates.add(nodeId);
      } else {
        pendingUpdates.add(nodeId);
      }
    }
    if (!updateScheduled) {
      updateScheduled = true;
      if (pendingUpdates.size > 10) {
        void nextTick(() => flush());
      } else {
        batchTimeoutId = window.setTimeout(() => flush(), 4);
      }
    }
  }, "scheduleUpdate");
  const flush = /* @__PURE__ */ __name(() => {
    const startTime = performance.now();
    if (batchTimeoutId !== null) {
      clearTimeout(batchTimeoutId);
      batchTimeoutId = null;
    }
    criticalUpdates.clear();
    pendingUpdates.clear();
    lowPriorityUpdates.clear();
    updateScheduled = false;
    syncWithGraph();
    const endTime = performance.now();
    performanceMetrics.updateTime = endTime - startTime;
  }, "flush");
  const syncWithGraph = /* @__PURE__ */ __name(() => {
    if (!graph?._nodes) return;
    const currentNodes = new Set(graph._nodes.map((n) => String(n.id)));
    for (const id of Array.from(vueNodeData.keys())) {
      if (!currentNodes.has(id)) {
        nodeRefs.delete(id);
        vueNodeData.delete(id);
        nodeState.delete(id);
        nodePositions.delete(id);
        nodeSizes.delete(id);
        lastNodesSnapshot.delete(id);
        spatialIndex.remove(id);
      }
    }
    graph._nodes.forEach((node) => {
      const id = String(node.id);
      nodeRefs.set(id, node);
      setupNodeWidgetCallbacks(node);
      vueNodeData.set(id, extractVueNodeData(node));
      if (!nodeState.has(id)) {
        nodeState.set(id, {
          visible: true,
          dirty: false,
          lastUpdate: performance.now(),
          culled: false
        });
        nodePositions.set(id, { x: node.pos[0], y: node.pos[1] });
        nodeSizes.set(id, { width: node.size[0], height: node.size[1] });
        attachMetadata(node);
        const bounds = {
          x: node.pos[0],
          y: node.pos[1],
          width: node.size[0],
          height: node.size[1]
        };
        spatialIndex.insert(id, bounds, id);
      }
    });
    performanceMetrics.nodeCount = vueNodeData.size;
    performanceMetrics.culledCount = Array.from(nodeState.values()).filter(
      (s) => s.culled
    ).length;
  }, "syncWithGraph");
  const getVisibleNodeIds = /* @__PURE__ */ __name((viewportBounds) => {
    const startTime = performance.now();
    const results = spatialIndex.query(viewportBounds);
    const visibleIds = new Set(results);
    lastSpatialQueryTime = performance.now() - startTime;
    spatialMetrics.queryTime = lastSpatialQueryTime;
    return visibleIds;
  }, "getVisibleNodeIds");
  const detectPositionChanges = /* @__PURE__ */ __name((node, id) => {
    const currentPos = nodePositions.get(id);
    if (!currentPos || currentPos.x !== node.pos[0] || currentPos.y !== node.pos[1]) {
      nodePositions.set(id, { x: node.pos[0], y: node.pos[1] });
      void moveNode(id, { x: node.pos[0], y: node.pos[1] });
      return true;
    }
    return false;
  }, "detectPositionChanges");
  const detectSizeChanges = /* @__PURE__ */ __name((node, id) => {
    const currentSize = nodeSizes.get(id);
    if (!currentSize || currentSize.width !== node.size[0] || currentSize.height !== node.size[1]) {
      nodeSizes.set(id, { width: node.size[0], height: node.size[1] });
      void resizeNode(id, {
        width: node.size[0],
        height: node.size[1]
      });
      return true;
    }
    return false;
  }, "detectSizeChanges");
  const updateSpatialIndex = /* @__PURE__ */ __name((node, id) => {
    const bounds = {
      x: node.pos[0],
      y: node.pos[1],
      width: node.size[0],
      height: node.size[1]
    };
    spatialIndex.update(id, bounds);
  }, "updateSpatialIndex");
  const updatePerformanceMetrics = /* @__PURE__ */ __name((startTime, positionUpdates, sizeUpdates) => {
    const endTime = performance.now();
    performanceMetrics.updateTime = endTime - startTime;
    performanceMetrics.nodeCount = vueNodeData.size;
    performanceMetrics.culledCount = Array.from(nodeState.values()).filter(
      (state) => state.culled
    ).length;
    spatialMetrics.nodesInIndex = spatialIndex.size;
    if (positionUpdates > 0 || sizeUpdates > 0) {
      performanceMetrics.rafUpdateCount++;
    }
  }, "updatePerformanceMetrics");
  const detectChangesInRAF = /* @__PURE__ */ __name(() => {
    const startTime = performance.now();
    if (!graph?._nodes) return;
    let positionUpdates = 0;
    let sizeUpdates = 0;
    setSource(LayoutSource.Canvas);
    for (const node of graph._nodes) {
      const id = String(node.id);
      const posChanged = detectPositionChanges(node, id);
      const sizeChanged = detectSizeChanges(node, id);
      if (posChanged) positionUpdates++;
      if (sizeChanged) sizeUpdates++;
      if (posChanged || sizeChanged) {
        updateSpatialIndex(node, id);
      }
    }
    updatePerformanceMetrics(startTime, positionUpdates, sizeUpdates);
  }, "detectChangesInRAF");
  const handleNodeAdded = /* @__PURE__ */ __name((node, originalCallback) => {
    const id = String(node.id);
    nodeRefs.set(id, node);
    setupNodeWidgetCallbacks(node);
    vueNodeData.set(id, extractVueNodeData(node));
    nodeState.set(id, {
      visible: true,
      dirty: false,
      lastUpdate: performance.now(),
      culled: false
    });
    nodePositions.set(id, { x: node.pos[0], y: node.pos[1] });
    nodeSizes.set(id, { width: node.size[0], height: node.size[1] });
    attachMetadata(node);
    const bounds = {
      x: node.pos[0],
      y: node.pos[1],
      width: node.size[0],
      height: node.size[1]
    };
    spatialIndex.insert(id, bounds, id);
    setSource(LayoutSource.Canvas);
    void createNode(id, {
      position: { x: node.pos[0], y: node.pos[1] },
      size: { width: node.size[0], height: node.size[1] },
      zIndex: node.order || 0,
      visible: true
    });
    if (originalCallback) {
      void originalCallback(node);
    }
  }, "handleNodeAdded");
  const handleNodeRemoved = /* @__PURE__ */ __name((node, originalCallback) => {
    const id = String(node.id);
    spatialIndex.remove(id);
    setSource(LayoutSource.Canvas);
    void deleteNode(id);
    nodeRefs.delete(id);
    vueNodeData.delete(id);
    nodeState.delete(id);
    nodePositions.delete(id);
    nodeSizes.delete(id);
    lastNodesSnapshot.delete(id);
    if (originalCallback) {
      originalCallback(node);
    }
  }, "handleNodeRemoved");
  const createCleanupFunction = /* @__PURE__ */ __name((originalOnNodeAdded, originalOnNodeRemoved, originalOnTrigger) => {
    return () => {
      graph.onNodeAdded = originalOnNodeAdded || void 0;
      graph.onNodeRemoved = originalOnNodeRemoved || void 0;
      graph.onTrigger = originalOnTrigger || void 0;
      if (batchTimeoutId !== null) {
        clearTimeout(batchTimeoutId);
        batchTimeoutId = null;
      }
      nodeRefs.clear();
      vueNodeData.clear();
      nodeState.clear();
      nodePositions.clear();
      nodeSizes.clear();
      lastNodesSnapshot.clear();
      pendingUpdates.clear();
      criticalUpdates.clear();
      lowPriorityUpdates.clear();
      spatialIndex.clear();
    };
  }, "createCleanupFunction");
  const setupEventListeners = /* @__PURE__ */ __name(() => {
    const originalOnNodeAdded = graph.onNodeAdded;
    const originalOnNodeRemoved = graph.onNodeRemoved;
    const originalOnTrigger = graph.onTrigger;
    graph.onNodeAdded = (node) => {
      handleNodeAdded(node, originalOnNodeAdded);
    };
    graph.onNodeRemoved = (node) => {
      handleNodeRemoved(node, originalOnNodeRemoved);
    };
    graph.onTrigger = (action, param) => {
      if (action === "node:property:changed" && param && typeof param === "object") {
        const event = param;
        const nodeId = String(event.nodeId);
        const currentData = vueNodeData.get(nodeId);
        if (currentData) {
          if (event.property === "title") {
            vueNodeData.set(nodeId, {
              ...currentData,
              title: String(event.newValue)
            });
          } else if (event.property === "flags.collapsed") {
            vueNodeData.set(nodeId, {
              ...currentData,
              flags: {
                ...currentData.flags,
                collapsed: Boolean(event.newValue)
              }
            });
          }
        }
      }
      if (originalOnTrigger) {
        originalOnTrigger(action, param);
      }
    };
    syncWithGraph();
    return createCleanupFunction(
      originalOnNodeAdded || void 0,
      originalOnNodeRemoved || void 0,
      originalOnTrigger || void 0
    );
  }, "setupEventListeners");
  const cleanup = setupEventListeners();
  if (graph._nodes && graph._nodes.length > 0) {
    graph._nodes.forEach((node) => {
      if (graph.onNodeAdded) {
        graph.onNodeAdded(node);
      }
    });
  }
  return {
    vueNodeData: readonly(vueNodeData),
    nodeState: readonly(nodeState),
    nodePositions: readonly(nodePositions),
    nodeSizes: readonly(nodeSizes),
    getNode,
    setupEventListeners,
    cleanup,
    scheduleUpdate,
    forceSync: syncWithGraph,
    detectChangesInRAF,
    getVisibleNodeIds,
    performanceMetrics,
    spatialMetrics: readonly(spatialMetrics),
    getSpatialIndexDebugInfo: /* @__PURE__ */ __name(() => spatialIndex.getDebugInfo(), "getSpatialIndexDebugInfo")
  };
}, "useGraphNodeManager");
function safePricingExecution(fn, node, fallback = "") {
  try {
    return fn(node);
  } catch (error) {
    if (false) {
      console.warn(
        "Pricing calculation failed for node:",
        node.constructor?.nodeData?.name,
        error
      );
    }
    return fallback;
  }
}
__name(safePricingExecution, "safePricingExecution");
const calculateRunwayDurationPrice = /* @__PURE__ */ __name((node) => {
  const durationWidget = node.widgets?.find(
    (w) => w.name === "duration"
  );
  if (!durationWidget) return "$0.05/second";
  const duration = Number(durationWidget.value);
  const validDuration = isNaN(duration) ? 5 : duration;
  const cost = (0.05 * validDuration).toFixed(2);
  return `$${cost}/Run`;
}, "calculateRunwayDurationPrice");
const pixversePricingCalculator = /* @__PURE__ */ __name((node) => {
  const durationWidget = node.widgets?.find(
    (w) => w.name === "duration_seconds"
  );
  const qualityWidget = node.widgets?.find(
    (w) => w.name === "quality"
  );
  const motionModeWidget = node.widgets?.find(
    (w) => w.name === "motion_mode"
  );
  if (!durationWidget || !qualityWidget) {
    return "$0.45-1.2/Run (varies with duration, quality & motion mode)";
  }
  const duration = String(durationWidget.value);
  const quality = String(qualityWidget.value);
  const motionMode = String(motionModeWidget?.value);
  if (duration.includes("5")) {
    if (quality.includes("1080p")) return "$1.2/Run";
    if (quality.includes("720p") && motionMode?.includes("fast"))
      return "$1.2/Run";
    if (quality.includes("720p") && motionMode?.includes("normal"))
      return "$0.6/Run";
    if (quality.includes("540p") && motionMode?.includes("fast"))
      return "$0.9/Run";
    if (quality.includes("540p") && motionMode?.includes("normal"))
      return "$0.45/Run";
    if (quality.includes("360p") && motionMode?.includes("fast"))
      return "$0.9/Run";
    if (quality.includes("360p") && motionMode?.includes("normal"))
      return "$0.45/Run";
    if (quality.includes("720p") && motionMode?.includes("fast"))
      return "$1.2/Run";
  } else if (duration.includes("8")) {
    if (quality.includes("720p") && motionMode?.includes("normal"))
      return "$1.2/Run";
    if (quality.includes("540p") && motionMode?.includes("normal"))
      return "$0.9/Run";
    if (quality.includes("540p") && motionMode?.includes("fast"))
      return "$1.2/Run";
    if (quality.includes("360p") && motionMode?.includes("normal"))
      return "$0.9/Run";
    if (quality.includes("360p") && motionMode?.includes("fast"))
      return "$1.2/Run";
    if (quality.includes("1080p") && motionMode?.includes("normal"))
      return "$1.2/Run";
    if (quality.includes("1080p") && motionMode?.includes("fast"))
      return "$1.2/Run";
    if (quality.includes("720p") && motionMode?.includes("normal"))
      return "$1.2/Run";
    if (quality.includes("720p") && motionMode?.includes("fast"))
      return "$1.2/Run";
  }
  return "$0.9/Run";
}, "pixversePricingCalculator");
const byteDanceVideoPricingCalculator = /* @__PURE__ */ __name((node) => {
  const modelWidget = node.widgets?.find(
    (w) => w.name === "model"
  );
  const durationWidget = node.widgets?.find(
    (w) => w.name === "duration"
  );
  const resolutionWidget = node.widgets?.find(
    (w) => w.name === "resolution"
  );
  if (!modelWidget || !durationWidget || !resolutionWidget) return "Token-based";
  const model = String(modelWidget.value).toLowerCase();
  const resolution = String(resolutionWidget.value).toLowerCase();
  const seconds = parseFloat(String(durationWidget.value));
  const priceByModel = {
    "seedance-1-0-pro": {
      "480p": [0.23, 0.24],
      "720p": [0.51, 0.56],
      "1080p": [1.18, 1.22]
    },
    "seedance-1-0-lite": {
      "480p": [0.17, 0.18],
      "720p": [0.37, 0.41],
      "1080p": [0.85, 0.88]
    }
  };
  const modelKey = model.includes("seedance-1-0-pro") ? "seedance-1-0-pro" : model.includes("seedance-1-0-lite") ? "seedance-1-0-lite" : "";
  const resKey = resolution.includes("1080") ? "1080p" : resolution.includes("720") ? "720p" : resolution.includes("480") ? "480p" : "";
  const baseRange = modelKey && resKey ? priceByModel[modelKey]?.[resKey] : void 0;
  if (!baseRange) return "Token-based";
  const [min10s, max10s] = baseRange;
  const scale = seconds / 10;
  const minCost = min10s * scale;
  const maxCost = max10s * scale;
  const minStr = `$${minCost.toFixed(2)}/Run`;
  const maxStr = `$${maxCost.toFixed(2)}/Run`;
  return minStr === maxStr ? minStr : `$${minCost.toFixed(2)}-$${maxCost.toFixed(2)}/Run`;
}, "byteDanceVideoPricingCalculator");
const apiNodeCosts = {
  FluxProCannyNode: {
    displayPrice: "$0.05/Run"
  },
  FluxProDepthNode: {
    displayPrice: "$0.05/Run"
  },
  FluxProExpandNode: {
    displayPrice: "$0.05/Run"
  },
  FluxProFillNode: {
    displayPrice: "$0.05/Run"
  },
  FluxProUltraImageNode: {
    displayPrice: "$0.06/Run"
  },
  FluxProKontextProNode: {
    displayPrice: "$0.04/Run"
  },
  FluxProKontextMaxNode: {
    displayPrice: "$0.08/Run"
  },
  IdeogramV1: {
    displayPrice: /* @__PURE__ */ __name((node) => {
      const numImagesWidget = node.widgets?.find(
        (w) => w.name === "num_images"
      );
      const turboWidget = node.widgets?.find(
        (w) => w.name === "turbo"
      );
      if (!numImagesWidget) return "$0.02-0.06 x num_images/Run";
      const numImages = Number(numImagesWidget.value) || 1;
      const turbo = String(turboWidget?.value).toLowerCase() === "true";
      const basePrice = turbo ? 0.02 : 0.06;
      const cost = (basePrice * numImages).toFixed(2);
      return `$${cost}/Run`;
    }, "displayPrice")
  },
  IdeogramV2: {
    displayPrice: /* @__PURE__ */ __name((node) => {
      const numImagesWidget = node.widgets?.find(
        (w) => w.name === "num_images"
      );
      const turboWidget = node.widgets?.find(
        (w) => w.name === "turbo"
      );
      if (!numImagesWidget) return "$0.05-0.08 x num_images/Run";
      const numImages = Number(numImagesWidget.value) || 1;
      const turbo = String(turboWidget?.value).toLowerCase() === "true";
      const basePrice = turbo ? 0.05 : 0.08;
      const cost = (basePrice * numImages).toFixed(2);
      return `$${cost}/Run`;
    }, "displayPrice")
  },
  IdeogramV3: {
    displayPrice: /* @__PURE__ */ __name((node) => {
      const renderingSpeedWidget = node.widgets?.find(
        (w) => w.name === "rendering_speed"
      );
      const numImagesWidget = node.widgets?.find(
        (w) => w.name === "num_images"
      );
      const characterInput = node.inputs?.find(
        (i) => i.name === "character_image"
      );
      const hasCharacter = typeof characterInput?.link !== "undefined" && characterInput.link != null;
      if (!renderingSpeedWidget)
        return "$0.03-0.08 x num_images/Run (varies with rendering speed & num_images)";
      const numImages = Number(numImagesWidget?.value) || 1;
      let basePrice = 0.06;
      const renderingSpeed = String(renderingSpeedWidget.value);
      if (renderingSpeed.toLowerCase().includes("quality")) {
        if (hasCharacter) {
          basePrice = 0.2;
        } else {
          basePrice = 0.09;
        }
      } else if (renderingSpeed.toLowerCase().includes("default")) {
        if (hasCharacter) {
          basePrice = 0.15;
        } else {
          basePrice = 0.06;
        }
      } else if (renderingSpeed.toLowerCase().includes("turbo")) {
        if (hasCharacter) {
          basePrice = 0.1;
        } else {
          basePrice = 0.03;
        }
      }
      const totalCost = (basePrice * numImages).toFixed(2);
      return `$${totalCost}/Run`;
    }, "displayPrice")
  },
  KlingCameraControlI2VNode: {
    displayPrice: "$0.49/Run"
  },
  KlingCameraControlT2VNode: {
    displayPrice: "$0.14/Run"
  },
  KlingDualCharacterVideoEffectNode: {
    displayPrice: /* @__PURE__ */ __name((node) => {
      const modeWidget = node.widgets?.find(
        (w) => w.name === "mode"
      );
      const modelWidget = node.widgets?.find(
        (w) => w.name === "model_name"
      );
      const durationWidget = node.widgets?.find(
        (w) => w.name === "duration"
      );
      if (!modeWidget || !modelWidget || !durationWidget)
        return "$0.14-2.80/Run (varies with model, mode & duration)";
      const modeValue = String(modeWidget.value);
      const durationValue = String(durationWidget.value);
      const modelValue = String(modelWidget.value);
      console.log("modelValue", modelValue);
      console.log("modeValue", modeValue);
      console.log("durationValue", durationValue);
      if (modelValue.includes("v1-6") || modelValue.includes("v1-5")) {
        if (modeValue.includes("pro")) {
          return durationValue.includes("10") ? "$0.98/Run" : "$0.49/Run";
        } else {
          return durationValue.includes("10") ? "$0.56/Run" : "$0.28/Run";
        }
      } else if (modelValue.includes("v1")) {
        if (modeValue.includes("pro")) {
          return durationValue.includes("10") ? "$0.98/Run" : "$0.49/Run";
        } else {
          return durationValue.includes("10") ? "$0.28/Run" : "$0.14/Run";
        }
      }
      return "$0.14/Run";
    }, "displayPrice")
  },
  KlingImage2VideoNode: {
    displayPrice: /* @__PURE__ */ __name((node) => {
      const modeWidget = node.widgets?.find(
        (w) => w.name === "mode"
      );
      const modelWidget = node.widgets?.find(
        (w) => w.name === "model_name"
      );
      const durationWidget = node.widgets?.find(
        (w) => w.name === "duration"
      );
      if (!modeWidget) {
        if (!modelWidget)
          return "$0.14-2.80/Run (varies with model, mode & duration)";
        const modelValue2 = String(modelWidget.value);
        if (modelValue2.includes("v2-1-master") || modelValue2.includes("v2-master")) {
          return "$1.40/Run";
        } else if (modelValue2.includes("v1-6") || modelValue2.includes("v1-5")) {
          return "$0.28/Run";
        }
        return "$0.14/Run";
      }
      const modeValue = String(modeWidget.value);
      const durationValue = String(durationWidget.value);
      const modelValue = String(modelWidget.value);
      console.log("modelValue", modelValue);
      console.log("modeValue", modeValue);
      console.log("durationValue", durationValue);
      if (modelValue.includes("v2-1-master") || modelValue.includes("v2-master")) {
        if (durationValue.includes("10")) {
          return "$2.80/Run";
        }
        return "$1.40/Run";
      } else if (modelValue.includes("v2-1") || modelValue.includes("v1-6") || modelValue.includes("v1-5")) {
        if (modeValue.includes("pro")) {
          return durationValue.includes("10") ? "$0.98/Run" : "$0.49/Run";
        } else {
          return durationValue.includes("10") ? "$0.56/Run" : "$0.28/Run";
        }
      } else if (modelValue.includes("v1")) {
        if (modeValue.includes("pro")) {
          return durationValue.includes("10") ? "$0.98/Run" : "$0.49/Run";
        } else {
          return durationValue.includes("10") ? "$0.28/Run" : "$0.14/Run";
        }
      }
      return "$0.14/Run";
    }, "displayPrice")
  },
  KlingImageGenerationNode: {
    displayPrice: /* @__PURE__ */ __name((node) => {
      const imageInputWidget = node.inputs?.find((i) => i.name === "image");
      const modality = imageInputWidget?.link ? "image to image" : "text to image";
      const modelWidget = node.widgets?.find(
        (w) => w.name === "model_name"
      );
      const nWidget = node.widgets?.find(
        (w) => w.name === "n"
      );
      if (!modelWidget)
        return "$0.0035-0.028 x n/Run (varies with modality & model)";
      const model = String(modelWidget.value);
      const n = Number(nWidget?.value) || 1;
      let basePrice = 0.014;
      if (modality.includes("text to image")) {
        if (model.includes("kling-v1-5") || model.includes("kling-v2")) {
          basePrice = 0.014;
        } else if (model.includes("kling-v1")) {
          basePrice = 35e-4;
        }
      } else if (modality.includes("image to image")) {
        if (model.includes("kling-v1-5")) {
          basePrice = 0.028;
        } else if (model.includes("kling-v1")) {
          basePrice = 35e-4;
        }
      }
      const totalCost = (basePrice * n).toFixed(4);
      return `$${totalCost}/Run`;
    }, "displayPrice")
  },
  KlingLipSyncAudioToVideoNode: {
    displayPrice: "~$0.10/Run"
  },
  KlingLipSyncTextToVideoNode: {
    displayPrice: "~$0.10/Run"
  },
  KlingSingleImageVideoEffectNode: {
    displayPrice: /* @__PURE__ */ __name((node) => {
      const effectSceneWidget = node.widgets?.find(
        (w) => w.name === "effect_scene"
      );
      if (!effectSceneWidget)
        return "$0.28-0.49/Run (varies with effect scene)";
      const effectScene = String(effectSceneWidget.value);
      if (effectScene.includes("fuzzyfuzzy") || effectScene.includes("squish")) {
        return "$0.28/Run";
      } else if (effectScene.includes("dizzydizzy")) {
        return "$0.49/Run";
      } else if (effectScene.includes("bloombloom")) {
        return "$0.49/Run";
      } else if (effectScene.includes("expansion")) {
        return "$0.28/Run";
      }
      return "$0.28/Run";
    }, "displayPrice")
  },
  KlingStartEndFrameNode: {
    displayPrice: /* @__PURE__ */ __name((node) => {
      const modeWidget = node.widgets?.find(
        (w) => w.name === "mode"
      );
      if (!modeWidget)
        return "$0.14-2.80/Run (varies with model, mode & duration)";
      const modeValue = String(modeWidget.value);
      if (modeValue.includes("v2-1")) {
        if (modeValue.includes("10s")) {
          return "$0.98/Run";
        }
        return "$0.49/Run";
      } else if (modeValue.includes("v2-master")) {
        if (modeValue.includes("10s")) {
          return "$2.80/Run";
        }
        return "$1.40/Run";
      } else if (modeValue.includes("v1-6")) {
        if (modeValue.includes("pro")) {
          return modeValue.includes("10s") ? "$0.98/Run" : "$0.49/Run";
        } else {
          return modeValue.includes("10s") ? "$0.56/Run" : "$0.28/Run";
        }
      } else if (modeValue.includes("v1")) {
        if (modeValue.includes("pro")) {
          return modeValue.includes("10s") ? "$0.98/Run" : "$0.49/Run";
        } else {
          return modeValue.includes("10s") ? "$0.28/Run" : "$0.14/Run";
        }
      }
      return "$0.14/Run";
    }, "displayPrice")
  },
  KlingTextToVideoNode: {
    displayPrice: /* @__PURE__ */ __name((node) => {
      const modeWidget = node.widgets?.find(
        (w) => w.name === "mode"
      );
      if (!modeWidget)
        return "$0.14-2.80/Run (varies with model, mode & duration)";
      const modeValue = String(modeWidget.value);
      if (modeValue.includes("v2-1-master")) {
        if (modeValue.includes("10s")) {
          return "$2.80/Run";
        }
        return "$1.40/Run";
      } else if (modeValue.includes("v2-master")) {
        if (modeValue.includes("10s")) {
          return "$2.80/Run";
        }
        return "$1.40/Run";
      } else if (modeValue.includes("v1-6")) {
        if (modeValue.includes("pro")) {
          return modeValue.includes("10s") ? "$0.98/Run" : "$0.49/Run";
        } else {
          return modeValue.includes("10s") ? "$0.56/Run" : "$0.28/Run";
        }
      } else if (modeValue.includes("v1")) {
        if (modeValue.includes("pro")) {
          return modeValue.includes("10s") ? "$0.98/Run" : "$0.49/Run";
        } else {
          return modeValue.includes("10s") ? "$0.28/Run" : "$0.14/Run";
        }
      }
      return "$0.14/Run";
    }, "displayPrice")
  },
  KlingVideoExtendNode: {
    displayPrice: "$0.28/Run"
  },
  KlingVirtualTryOnNode: {
    displayPrice: "$0.07/Run"
  },
  LumaImageToVideoNode: {
    displayPrice: /* @__PURE__ */ __name((node) => {
      const modelWidget = node.widgets?.find(
        (w) => w.name === "model"
      );
      const resolutionWidget = node.widgets?.find(
        (w) => w.name === "resolution"
      );
      const durationWidget = node.widgets?.find(
        (w) => w.name === "duration"
      );
      if (!modelWidget || !resolutionWidget || !durationWidget) {
        return "$0.14-11.47/Run (varies with model, resolution & duration)";
      }
      const model = String(modelWidget.value);
      const resolution = String(resolutionWidget.value).toLowerCase();
      const duration = String(durationWidget.value);
      console.log("model", model);
      console.log("resolution", resolution);
      console.log("duration", duration);
      if (model.includes("ray-flash-2")) {
        if (duration.includes("5s")) {
          if (resolution.includes("4k")) return "$2.19/Run";
          if (resolution.includes("1080p")) return "$0.55/Run";
          if (resolution.includes("720p")) return "$0.24/Run";
          if (resolution.includes("540p")) return "$0.14/Run";
        } else if (duration.includes("9s")) {
          if (resolution.includes("4k")) return "$3.95/Run";
          if (resolution.includes("1080p")) return "$0.99/Run";
          if (resolution.includes("720p")) return "$0.43/Run";
          if (resolution.includes("540p")) return "$0.252/Run";
        }
      } else if (model.includes("ray-2")) {
        if (duration.includes("5s")) {
          if (resolution.includes("4k")) return "$6.37/Run";
          if (resolution.includes("1080p")) return "$1.59/Run";
          if (resolution.includes("720p")) return "$0.71/Run";
          if (resolution.includes("540p")) return "$0.40/Run";
        } else if (duration.includes("9s")) {
          if (resolution.includes("4k")) return "$11.47/Run";
          if (resolution.includes("1080p")) return "$2.87/Run";
          if (resolution.includes("720p")) return "$1.28/Run";
          if (resolution.includes("540p")) return "$0.72/Run";
        }
      } else if (model.includes("ray-1.6")) {
        return "$0.35/Run";
      }
      return "$0.55/Run";
    }, "displayPrice")
  },
  LumaVideoNode: {
    displayPrice: /* @__PURE__ */ __name((node) => {
      const modelWidget = node.widgets?.find(
        (w) => w.name === "model"
      );
      const resolutionWidget = node.widgets?.find(
        (w) => w.name === "resolution"
      );
      const durationWidget = node.widgets?.find(
        (w) => w.name === "duration"
      );
      if (!modelWidget || !resolutionWidget || !durationWidget) {
        return "$0.14-11.47/Run (varies with model, resolution & duration)";
      }
      const model = String(modelWidget.value);
      const resolution = String(resolutionWidget.value).toLowerCase();
      const duration = String(durationWidget.value);
      if (model.includes("ray-flash-2")) {
        if (duration.includes("5s")) {
          if (resolution.includes("4k")) return "$2.19/Run";
          if (resolution.includes("1080p")) return "$0.55/Run";
          if (resolution.includes("720p")) return "$0.24/Run";
          if (resolution.includes("540p")) return "$0.14/Run";
        } else if (duration.includes("9s")) {
          if (resolution.includes("4k")) return "$3.95/Run";
          if (resolution.includes("1080p")) return "$0.99/Run";
          if (resolution.includes("720p")) return "$0.43/Run";
          if (resolution.includes("540p")) return "$0.252/Run";
        }
      } else if (model.includes("ray-2")) {
        if (duration.includes("5s")) {
          if (resolution.includes("4k")) return "$6.37/Run";
          if (resolution.includes("1080p")) return "$1.59/Run";
          if (resolution.includes("720p")) return "$0.71/Run";
          if (resolution.includes("540p")) return "$0.40/Run";
        } else if (duration.includes("9s")) {
          if (resolution.includes("4k")) return "$11.47/Run";
          if (resolution.includes("1080p")) return "$2.87/Run";
          if (resolution.includes("720p")) return "$1.28/Run";
          if (resolution.includes("540p")) return "$0.72/Run";
        }
      } else if (model.includes("ray-1-6")) {
        return "$0.35/Run";
      }
      return "$0.55/Run";
    }, "displayPrice")
  },
  MinimaxImageToVideoNode: {
    displayPrice: "$0.43/Run"
  },
  MinimaxTextToVideoNode: {
    displayPrice: "$0.43/Run"
  },
  MinimaxHailuoVideoNode: {
    displayPrice: /* @__PURE__ */ __name((node) => {
      const resolutionWidget = node.widgets?.find(
        (w) => w.name === "resolution"
      );
      const durationWidget = node.widgets?.find(
        (w) => w.name === "duration"
      );
      if (!resolutionWidget || !durationWidget) {
        return "$0.28-0.56/Run (varies with resolution & duration)";
      }
      const resolution = String(resolutionWidget.value);
      const duration = String(durationWidget.value);
      if (resolution.includes("768P")) {
        if (duration.includes("6")) return "$0.28/Run";
        if (duration.includes("10")) return "$0.56/Run";
      } else if (resolution.includes("1080P")) {
        if (duration.includes("6")) return "$0.49/Run";
      }
      return "$0.43/Run";
    }, "displayPrice")
  },
  OpenAIDalle2: {
    displayPrice: /* @__PURE__ */ __name((node) => {
      const sizeWidget = node.widgets?.find(
        (w) => w.name === "size"
      );
      const nWidget = node.widgets?.find(
        (w) => w.name === "n"
      );
      if (!sizeWidget) return "$0.016-0.02 x n/Run (varies with size & n)";
      const size = String(sizeWidget.value);
      const n = Number(nWidget?.value) || 1;
      let basePrice = 0.02;
      if (size.includes("1024x1024")) {
        basePrice = 0.02;
      } else if (size.includes("512x512")) {
        basePrice = 0.018;
      } else if (size.includes("256x256")) {
        basePrice = 0.016;
      }
      const totalCost = (basePrice * n).toFixed(3);
      return `$${totalCost}/Run`;
    }, "displayPrice")
  },
  OpenAIDalle3: {
    displayPrice: /* @__PURE__ */ __name((node) => {
      const sizeWidget = node.widgets?.find(
        (w) => w.name === "size"
      );
      const qualityWidget = node.widgets?.find(
        (w) => w.name === "quality"
      );
      if (!sizeWidget || !qualityWidget)
        return "$0.04-0.12/Run (varies with size & quality)";
      const size = String(sizeWidget.value);
      const quality = String(qualityWidget.value);
      if (size.includes("1024x1024")) {
        return quality.includes("hd") ? "$0.08/Run" : "$0.04/Run";
      } else if (size.includes("1792x1024") || size.includes("1024x1792")) {
        return quality.includes("hd") ? "$0.12/Run" : "$0.08/Run";
      }
      return "$0.04/Run";
    }, "displayPrice")
  },
  OpenAIGPTImage1: {
    displayPrice: /* @__PURE__ */ __name((node) => {
      const qualityWidget = node.widgets?.find(
        (w) => w.name === "quality"
      );
      const nWidget = node.widgets?.find(
        (w) => w.name === "n"
      );
      if (!qualityWidget)
        return "$0.011-0.30 x n/Run (varies with quality & n)";
      const quality = String(qualityWidget.value);
      const n = Number(nWidget?.value) || 1;
      let basePriceRange = "$0.046-0.07";
      if (quality.includes("high")) {
        basePriceRange = "$0.167-0.30";
      } else if (quality.includes("medium")) {
        basePriceRange = "$0.046-0.07";
      } else if (quality.includes("low")) {
        basePriceRange = "$0.011-0.02";
      }
      if (n === 1) {
        return `${basePriceRange}/Run`;
      } else {
        return `${basePriceRange} x ${n}/Run`;
      }
    }, "displayPrice")
  },
  PikaImageToVideoNode2_2: {
    displayPrice: /* @__PURE__ */ __name((node) => {
      const durationWidget = node.widgets?.find(
        (w) => w.name === "duration"
      );
      const resolutionWidget = node.widgets?.find(
        (w) => w.name === "resolution"
      );
      if (!durationWidget || !resolutionWidget) {
        return "$0.2-1.0/Run (varies with duration & resolution)";
      }
      const duration = String(durationWidget.value);
      const resolution = String(resolutionWidget.value);
      if (duration.includes("5")) {
        if (resolution.includes("1080p")) return "$0.45/Run";
        if (resolution.includes("720p")) return "$0.2/Run";
      } else if (duration.includes("10")) {
        if (resolution.includes("1080p")) return "$1.0/Run";
        if (resolution.includes("720p")) return "$0.6/Run";
      }
      return "$0.2/Run";
    }, "displayPrice")
  },
  PikaScenesV2_2: {
    displayPrice: /* @__PURE__ */ __name((node) => {
      const durationWidget = node.widgets?.find(
        (w) => w.name === "duration"
      );
      const resolutionWidget = node.widgets?.find(
        (w) => w.name === "resolution"
      );
      if (!durationWidget || !resolutionWidget) {
        return "$0.2-1.0/Run (varies with duration & resolution)";
      }
      const duration = String(durationWidget.value);
      const resolution = String(resolutionWidget.value);
      if (duration.includes("5")) {
        if (resolution.includes("720p")) return "$0.3/Run";
        if (resolution.includes("1080p")) return "$0.5/Run";
      } else if (duration.includes("10")) {
        if (resolution.includes("720p")) return "$0.4/Run";
        if (resolution.includes("1080p")) return "$1.5/Run";
      }
      return "$0.3/Run";
    }, "displayPrice")
  },
  PikaStartEndFrameNode2_2: {
    displayPrice: /* @__PURE__ */ __name((node) => {
      const durationWidget = node.widgets?.find(
        (w) => w.name === "duration"
      );
      const resolutionWidget = node.widgets?.find(
        (w) => w.name === "resolution"
      );
      if (!durationWidget || !resolutionWidget) {
        return "$0.2-1.0/Run (varies with duration & resolution)";
      }
      const duration = String(durationWidget.value);
      const resolution = String(resolutionWidget.value);
      if (duration.includes("5")) {
        if (resolution.includes("720p")) return "$0.2/Run";
        if (resolution.includes("1080p")) return "$0.3/Run";
      } else if (duration.includes("10")) {
        if (resolution.includes("720p")) return "$0.25/Run";
        if (resolution.includes("1080p")) return "$1.0/Run";
      }
      return "$0.2/Run";
    }, "displayPrice")
  },
  PikaTextToVideoNode2_2: {
    displayPrice: /* @__PURE__ */ __name((node) => {
      const durationWidget = node.widgets?.find(
        (w) => w.name === "duration"
      );
      const resolutionWidget = node.widgets?.find(
        (w) => w.name === "resolution"
      );
      if (!durationWidget || !resolutionWidget) {
        return "$0.2-1.5/Run (varies with duration & resolution)";
      }
      const duration = String(durationWidget.value);
      const resolution = String(resolutionWidget.value);
      if (duration.includes("5")) {
        if (resolution.includes("1080p")) return "$0.45/Run";
        if (resolution.includes("720p")) return "$0.2/Run";
      } else if (duration.includes("10")) {
        if (resolution.includes("1080p")) return "$1.0/Run";
        if (resolution.includes("720p")) return "$0.6/Run";
      }
      return "$0.45/Run";
    }, "displayPrice")
  },
  Pikadditions: {
    displayPrice: "$0.3/Run"
  },
  Pikaffects: {
    displayPrice: "$0.45/Run"
  },
  Pikaswaps: {
    displayPrice: "$0.3/Run"
  },
  PixverseImageToVideoNode: {
    displayPrice: pixversePricingCalculator
  },
  PixverseTextToVideoNode: {
    displayPrice: pixversePricingCalculator
  },
  PixverseTransitionVideoNode: {
    displayPrice: pixversePricingCalculator
  },
  RecraftCreativeUpscaleNode: {
    displayPrice: "$0.25/Run"
  },
  RecraftCrispUpscaleNode: {
    displayPrice: "$0.004/Run"
  },
  RecraftGenerateColorFromImageNode: {
    displayPrice: /* @__PURE__ */ __name((node) => {
      const nWidget = node.widgets?.find(
        (w) => w.name === "n"
      );
      if (!nWidget) return "$0.04 x n/Run";
      const n = Number(nWidget.value) || 1;
      const cost = (0.04 * n).toFixed(2);
      return `$${cost}/Run`;
    }, "displayPrice")
  },
  RecraftGenerateImageNode: {
    displayPrice: /* @__PURE__ */ __name((node) => {
      const nWidget = node.widgets?.find(
        (w) => w.name === "n"
      );
      if (!nWidget) return "$0.04 x n/Run";
      const n = Number(nWidget.value) || 1;
      const cost = (0.04 * n).toFixed(2);
      return `$${cost}/Run`;
    }, "displayPrice")
  },
  RecraftGenerateVectorImageNode: {
    displayPrice: /* @__PURE__ */ __name((node) => {
      const nWidget = node.widgets?.find(
        (w) => w.name === "n"
      );
      if (!nWidget) return "$0.08 x n/Run";
      const n = Number(nWidget.value) || 1;
      const cost = (0.08 * n).toFixed(2);
      return `$${cost}/Run`;
    }, "displayPrice")
  },
  RecraftImageInpaintingNode: {
    displayPrice: /* @__PURE__ */ __name((node) => {
      const nWidget = node.widgets?.find(
        (w) => w.name === "n"
      );
      if (!nWidget) return "$0.04 x n/Run";
      const n = Number(nWidget.value) || 1;
      const cost = (0.04 * n).toFixed(2);
      return `$${cost}/Run`;
    }, "displayPrice")
  },
  RecraftImageToImageNode: {
    displayPrice: /* @__PURE__ */ __name((node) => {
      const nWidget = node.widgets?.find(
        (w) => w.name === "n"
      );
      if (!nWidget) return "$0.04 x n/Run";
      const n = Number(nWidget.value) || 1;
      const cost = (0.04 * n).toFixed(2);
      return `$${cost}/Run`;
    }, "displayPrice")
  },
  RecraftRemoveBackgroundNode: {
    displayPrice: "$0.01/Run"
  },
  RecraftReplaceBackgroundNode: {
    displayPrice: "$0.04/Run"
  },
  RecraftTextToImageNode: {
    displayPrice: /* @__PURE__ */ __name((node) => {
      const nWidget = node.widgets?.find(
        (w) => w.name === "n"
      );
      if (!nWidget) return "$0.04 x n/Run";
      const n = Number(nWidget.value) || 1;
      const cost = (0.04 * n).toFixed(2);
      return `$${cost}/Run`;
    }, "displayPrice")
  },
  RecraftTextToVectorNode: {
    displayPrice: /* @__PURE__ */ __name((node) => {
      const nWidget = node.widgets?.find(
        (w) => w.name === "n"
      );
      if (!nWidget) return "$0.08 x n/Run";
      const n = Number(nWidget.value) || 1;
      const cost = (0.08 * n).toFixed(2);
      return `$${cost}/Run`;
    }, "displayPrice")
  },
  RecraftVectorizeImageNode: {
    displayPrice: /* @__PURE__ */ __name((node) => {
      const nWidget = node.widgets?.find(
        (w) => w.name === "n"
      );
      if (!nWidget) return "$0.01 x n/Run";
      const n = Number(nWidget.value) || 1;
      const cost = (0.01 * n).toFixed(2);
      return `$${cost}/Run`;
    }, "displayPrice")
  },
  StabilityStableImageSD_3_5Node: {
    displayPrice: /* @__PURE__ */ __name((node) => {
      const modelWidget = node.widgets?.find(
        (w) => w.name === "model"
      );
      if (!modelWidget) return "$0.035-0.065/Run (varies with model)";
      const model = String(modelWidget.value).toLowerCase();
      if (model.includes("large")) {
        return "$0.065/Run";
      } else if (model.includes("medium")) {
        return "$0.035/Run";
      }
      return "$0.035/Run";
    }, "displayPrice")
  },
  StabilityStableImageUltraNode: {
    displayPrice: "$0.08/Run"
  },
  StabilityUpscaleConservativeNode: {
    displayPrice: "$0.25/Run"
  },
  StabilityUpscaleCreativeNode: {
    displayPrice: "$0.25/Run"
  },
  StabilityUpscaleFastNode: {
    displayPrice: "$0.01/Run"
  },
  VeoVideoGenerationNode: {
    displayPrice: /* @__PURE__ */ __name((node) => {
      const durationWidget = node.widgets?.find(
        (w) => w.name === "duration_seconds"
      );
      if (!durationWidget) return "$2.50-5.0/Run (varies with duration)";
      const price = 0.5 * Number(durationWidget.value);
      return `$${price.toFixed(2)}/Run`;
    }, "displayPrice")
  },
  Veo3VideoGenerationNode: {
    displayPrice: /* @__PURE__ */ __name((node) => {
      const modelWidget = node.widgets?.find(
        (w) => w.name === "model"
      );
      const generateAudioWidget = node.widgets?.find(
        (w) => w.name === "generate_audio"
      );
      if (!modelWidget || !generateAudioWidget) {
        return "$2.00-6.00/Run (varies with model & audio generation)";
      }
      const model = String(modelWidget.value);
      const generateAudio = String(generateAudioWidget.value).toLowerCase() === "true";
      if (model.includes("veo-3.0-fast-generate-001")) {
        return generateAudio ? "$3.20/Run" : "$2.00/Run";
      } else if (model.includes("veo-3.0-generate-001")) {
        return generateAudio ? "$6.00/Run" : "$4.00/Run";
      }
      return "$2.00-6.00/Run";
    }, "displayPrice")
  },
  LumaImageNode: {
    displayPrice: /* @__PURE__ */ __name((node) => {
      const modelWidget = node.widgets?.find(
        (w) => w.name === "model"
      );
      const aspectRatioWidget = node.widgets?.find(
        (w) => w.name === "aspect_ratio"
      );
      if (!modelWidget || !aspectRatioWidget) {
        return "$0.0045-0.0182/Run (varies with model & aspect ratio)";
      }
      const model = String(modelWidget.value);
      if (model.includes("photon-flash-1")) {
        return "$0.0019/Run";
      } else if (model.includes("photon-1")) {
        return "$0.0073/Run";
      }
      return "$0.0172/Run";
    }, "displayPrice")
  },
  LumaImageModifyNode: {
    displayPrice: /* @__PURE__ */ __name((node) => {
      const modelWidget = node.widgets?.find(
        (w) => w.name === "model"
      );
      if (!modelWidget) {
        return "$0.0019-0.0073/Run (varies with model)";
      }
      const model = String(modelWidget.value);
      if (model.includes("photon-flash-1")) {
        return "$0.0019/Run";
      } else if (model.includes("photon-1")) {
        return "$0.0073/Run";
      }
      return "$0.0172/Run";
    }, "displayPrice")
  },
  MoonvalleyTxt2VideoNode: {
    displayPrice: /* @__PURE__ */ __name((node) => {
      const lengthWidget = node.widgets?.find(
        (w) => w.name === "length"
      );
      if (!lengthWidget) return "$1.50/Run";
      const length = String(lengthWidget.value);
      if (length === "5s") {
        return "$1.50/Run";
      } else if (length === "10s") {
        return "$3.00/Run";
      }
      return "$1.50/Run";
    }, "displayPrice")
  },
  MoonvalleyImg2VideoNode: {
    displayPrice: /* @__PURE__ */ __name((node) => {
      const lengthWidget = node.widgets?.find(
        (w) => w.name === "length"
      );
      if (!lengthWidget) return "$1.50/Run";
      const length = String(lengthWidget.value);
      if (length === "5s") {
        return "$1.50/Run";
      } else if (length === "10s") {
        return "$3.00/Run";
      }
      return "$1.50/Run";
    }, "displayPrice")
  },
  MoonvalleyVideo2VideoNode: {
    displayPrice: /* @__PURE__ */ __name((node) => {
      const lengthWidget = node.widgets?.find(
        (w) => w.name === "length"
      );
      if (!lengthWidget) return "$2.25/Run";
      const length = String(lengthWidget.value);
      if (length === "5s") {
        return "$2.25/Run";
      } else if (length === "10s") {
        return "$4.00/Run";
      }
      return "$2.25/Run";
    }, "displayPrice")
  },
  // Runway nodes - using actual node names from ComfyUI
  RunwayTextToImageNode: {
    displayPrice: "$0.08/Run"
  },
  RunwayImageToVideoNodeGen3a: {
    displayPrice: calculateRunwayDurationPrice
  },
  RunwayImageToVideoNodeGen4: {
    displayPrice: calculateRunwayDurationPrice
  },
  RunwayFirstLastFrameNode: {
    displayPrice: calculateRunwayDurationPrice
  },
  // Rodin nodes - all have the same pricing structure
  Rodin3D_Regular: {
    displayPrice: "$0.4/Run"
  },
  Rodin3D_Detail: {
    displayPrice: "$0.4/Run"
  },
  Rodin3D_Smooth: {
    displayPrice: "$0.4/Run"
  },
  Rodin3D_Sketch: {
    displayPrice: "$0.4/Run"
  },
  // Tripo nodes - using actual node names from ComfyUI
  TripoTextToModelNode: {
    displayPrice: /* @__PURE__ */ __name((node) => {
      const quadWidget = node.widgets?.find(
        (w) => w.name === "quad"
      );
      const styleWidget = node.widgets?.find(
        (w) => w.name === "style"
      );
      const textureWidget = node.widgets?.find(
        (w) => w.name === "texture"
      );
      const textureQualityWidget = node.widgets?.find(
        (w) => w.name === "texture_quality"
      );
      if (!quadWidget || !styleWidget || !textureWidget)
        return "$0.1-0.4/Run (varies with quad, style, texture & quality)";
      const quad = String(quadWidget.value).toLowerCase() === "true";
      const style = String(styleWidget.value).toLowerCase();
      const texture = String(textureWidget.value).toLowerCase() === "true";
      const textureQuality = String(
        textureQualityWidget?.value || "standard"
      ).toLowerCase();
      if (style.includes("none")) {
        if (!quad) {
          if (!texture) return "$0.10/Run";
          else return "$0.15/Run";
        } else {
          if (textureQuality.includes("detailed")) {
            if (!texture) return "$0.30/Run";
            else return "$0.35/Run";
          } else {
            if (!texture) return "$0.20/Run";
            else return "$0.25/Run";
          }
        }
      } else {
        if (!quad) {
          if (!texture) return "$0.15/Run";
          else return "$0.20/Run";
        } else {
          if (textureQuality.includes("detailed")) {
            if (!texture) return "$0.35/Run";
            else return "$0.40/Run";
          } else {
            if (!texture) return "$0.25/Run";
            else return "$0.30/Run";
          }
        }
      }
    }, "displayPrice")
  },
  TripoImageToModelNode: {
    displayPrice: /* @__PURE__ */ __name((node) => {
      const quadWidget = node.widgets?.find(
        (w) => w.name === "quad"
      );
      const styleWidget = node.widgets?.find(
        (w) => w.name === "style"
      );
      const textureWidget = node.widgets?.find(
        (w) => w.name === "texture"
      );
      const textureQualityWidget = node.widgets?.find(
        (w) => w.name === "texture_quality"
      );
      if (!quadWidget || !styleWidget || !textureWidget)
        return "$0.2-0.5/Run (varies with quad, style, texture & quality)";
      const quad = String(quadWidget.value).toLowerCase() === "true";
      const style = String(styleWidget.value).toLowerCase();
      const texture = String(textureWidget.value).toLowerCase() === "true";
      const textureQuality = String(
        textureQualityWidget?.value || "standard"
      ).toLowerCase();
      if (style.includes("none")) {
        if (!quad) {
          if (!texture) return "$0.20/Run";
          else return "$0.25/Run";
        } else {
          if (textureQuality.includes("detailed")) {
            if (!texture) return "$0.40/Run";
            else return "$0.45/Run";
          } else {
            if (!texture) return "$0.30/Run";
            else return "$0.35/Run";
          }
        }
      } else {
        if (!quad) {
          if (!texture) return "$0.25/Run";
          else return "$0.30/Run";
        } else {
          if (textureQuality.includes("detailed")) {
            if (!texture) return "$0.45/Run";
            else return "$0.50/Run";
          } else {
            if (!texture) return "$0.35/Run";
            else return "$0.40/Run";
          }
        }
      }
    }, "displayPrice")
  },
  TripoRefineNode: {
    displayPrice: "$0.3/Run"
  },
  TripoTextureNode: {
    displayPrice: /* @__PURE__ */ __name((node) => {
      const textureQualityWidget = node.widgets?.find(
        (w) => w.name === "texture_quality"
      );
      if (!textureQualityWidget) return "$0.1-0.2/Run (varies with quality)";
      const textureQuality = String(textureQualityWidget.value);
      return textureQuality.includes("detailed") ? "$0.2/Run" : "$0.1/Run";
    }, "displayPrice")
  },
  TripoConvertModelNode: {
    displayPrice: "$0.10/Run"
  },
  TripoRetargetRiggedModelNode: {
    displayPrice: "$0.10/Run"
  },
  TripoMultiviewToModelNode: {
    displayPrice: /* @__PURE__ */ __name((node) => {
      const quadWidget = node.widgets?.find(
        (w) => w.name === "quad"
      );
      const styleWidget = node.widgets?.find(
        (w) => w.name === "style"
      );
      const textureWidget = node.widgets?.find(
        (w) => w.name === "texture"
      );
      const textureQualityWidget = node.widgets?.find(
        (w) => w.name === "texture_quality"
      );
      if (!quadWidget || !styleWidget || !textureWidget)
        return "$0.2-0.5/Run (varies with quad, style, texture & quality)";
      const quad = String(quadWidget.value).toLowerCase() === "true";
      const style = String(styleWidget.value).toLowerCase();
      const texture = String(textureWidget.value).toLowerCase() === "true";
      const textureQuality = String(
        textureQualityWidget?.value || "standard"
      ).toLowerCase();
      if (style.includes("none")) {
        if (!quad) {
          if (!texture) return "$0.20/Run";
          else return "$0.25/Run";
        } else {
          if (textureQuality.includes("detailed")) {
            if (!texture) return "$0.40/Run";
            else return "$0.45/Run";
          } else {
            if (!texture) return "$0.30/Run";
            else return "$0.35/Run";
          }
        }
      } else {
        if (!quad) {
          if (!texture) return "$0.25/Run";
          else return "$0.30/Run";
        } else {
          if (textureQuality.includes("detailed")) {
            if (!texture) return "$0.45/Run";
            else return "$0.50/Run";
          } else {
            if (!texture) return "$0.35/Run";
            else return "$0.40/Run";
          }
        }
      }
    }, "displayPrice")
  },
  // Google/Gemini nodes
  GeminiNode: {
    displayPrice: /* @__PURE__ */ __name((node) => {
      const modelWidget = node.widgets?.find(
        (w) => w.name === "model"
      );
      if (!modelWidget) return "Token-based";
      const model = String(modelWidget.value);
      if (model.includes("veo-2.0")) {
        return "$0.5/second";
      } else if (model.includes("gemini-2.5-flash-preview-04-17")) {
        return "$0.0003/$0.0025 per 1K tokens";
      } else if (model.includes("gemini-2.5-flash")) {
        return "$0.0003/$0.0025 per 1K tokens";
      } else if (model.includes("gemini-2.5-pro-preview-05-06")) {
        return "$0.00125/$0.01 per 1K tokens";
      } else if (model.includes("gemini-2.5-pro")) {
        return "$0.00125/$0.01 per 1K tokens";
      }
      return "Token-based";
    }, "displayPrice")
  },
  GeminiImageNode: {
    displayPrice: "$0.03 per 1K tokens"
  },
  // OpenAI nodes
  OpenAIChatNode: {
    displayPrice: /* @__PURE__ */ __name((node) => {
      const modelWidget = node.widgets?.find(
        (w) => w.name === "model"
      );
      if (!modelWidget) return "Token-based";
      const model = String(modelWidget.value);
      if (model.includes("o4-mini")) {
        return "$0.0011/$0.0044 per 1K tokens";
      } else if (model.includes("o1-pro")) {
        return "$0.15/$0.60 per 1K tokens";
      } else if (model.includes("o1")) {
        return "$0.015/$0.06 per 1K tokens";
      } else if (model.includes("o3-mini")) {
        return "$0.0011/$0.0044 per 1K tokens";
      } else if (model.includes("o3")) {
        return "$0.01/$0.04 per 1K tokens";
      } else if (model.includes("gpt-4o")) {
        return "$0.0025/$0.01 per 1K tokens";
      } else if (model.includes("gpt-4.1-nano")) {
        return "$0.0001/$0.0004 per 1K tokens";
      } else if (model.includes("gpt-4.1-mini")) {
        return "$0.0004/$0.0016 per 1K tokens";
      } else if (model.includes("gpt-4.1")) {
        return "$0.002/$0.008 per 1K tokens";
      } else if (model.includes("gpt-5-nano")) {
        return "$0.00005/$0.0004 per 1K tokens";
      } else if (model.includes("gpt-5-mini")) {
        return "$0.00025/$0.002 per 1K tokens";
      } else if (model.includes("gpt-5")) {
        return "$0.00125/$0.01 per 1K tokens";
      }
      return "Token-based";
    }, "displayPrice")
  },
  ViduTextToVideoNode: {
    displayPrice: "$0.4/Run"
  },
  ViduImageToVideoNode: {
    displayPrice: "$0.4/Run"
  },
  ViduReferenceVideoNode: {
    displayPrice: "$0.4/Run"
  },
  ViduStartEndToVideoNode: {
    displayPrice: "$0.4/Run"
  },
  ByteDanceImageNode: {
    displayPrice: /* @__PURE__ */ __name((node) => {
      const modelWidget = node.widgets?.find(
        (w) => w.name === "model"
      );
      if (!modelWidget) return "Token-based";
      const model = String(modelWidget.value);
      if (model.includes("seedream-3-0-t2i")) {
        return "$0.03/Run";
      }
      return "Token-based";
    }, "displayPrice")
  },
  ByteDanceImageEditNode: {
    displayPrice: /* @__PURE__ */ __name((node) => {
      const modelWidget = node.widgets?.find(
        (w) => w.name === "model"
      );
      if (!modelWidget) return "Token-based";
      const model = String(modelWidget.value);
      if (model.includes("seededit-3-0-i2i")) {
        return "$0.03/Run";
      }
      return "Token-based";
    }, "displayPrice")
  },
  ByteDanceTextToVideoNode: {
    displayPrice: byteDanceVideoPricingCalculator
  },
  ByteDanceImageToVideoNode: {
    displayPrice: byteDanceVideoPricingCalculator
  },
  ByteDanceFirstLastFrameNode: {
    displayPrice: byteDanceVideoPricingCalculator
  },
  ByteDanceImageReferenceNode: {
    displayPrice: byteDanceVideoPricingCalculator
  }
};
const useNodePricing = /* @__PURE__ */ __name(() => {
  const getNodeDisplayPrice = /* @__PURE__ */ __name((node) => {
    if (!node.constructor?.nodeData?.api_node) return "";
    const nodeName = node.constructor.nodeData.name;
    const priceConfig = apiNodeCosts[nodeName];
    if (!priceConfig) return "";
    if (typeof priceConfig.displayPrice === "function") {
      return safePricingExecution(priceConfig.displayPrice, node, "");
    }
    return priceConfig.displayPrice;
  }, "getNodeDisplayPrice");
  const getNodePricingConfig = /* @__PURE__ */ __name((node) => apiNodeCosts[node.constructor.nodeData?.name ?? ""], "getNodePricingConfig");
  const getRelevantWidgetNames = /* @__PURE__ */ __name((nodeType) => {
    const widgetMap = {
      KlingTextToVideoNode: ["mode", "model_name", "duration"],
      KlingImage2VideoNode: ["mode", "model_name", "duration"],
      KlingImageGenerationNode: ["modality", "model_name", "n"],
      KlingDualCharacterVideoEffectNode: ["mode", "model_name", "duration"],
      KlingSingleImageVideoEffectNode: ["effect_scene"],
      KlingStartEndFrameNode: ["mode", "model_name", "duration"],
      MinimaxHailuoVideoNode: ["resolution", "duration"],
      OpenAIDalle3: ["size", "quality"],
      OpenAIDalle2: ["size", "n"],
      OpenAIGPTImage1: ["quality", "n"],
      IdeogramV1: ["num_images", "turbo"],
      IdeogramV2: ["num_images", "turbo"],
      IdeogramV3: ["rendering_speed", "num_images", "character_image"],
      FluxProKontextProNode: [],
      FluxProKontextMaxNode: [],
      VeoVideoGenerationNode: ["duration_seconds"],
      Veo3VideoGenerationNode: ["model", "generate_audio"],
      LumaVideoNode: ["model", "resolution", "duration"],
      LumaImageToVideoNode: ["model", "resolution", "duration"],
      LumaImageNode: ["model", "aspect_ratio"],
      LumaImageModifyNode: ["model", "aspect_ratio"],
      PikaTextToVideoNode2_2: ["duration", "resolution"],
      PikaImageToVideoNode2_2: ["duration", "resolution"],
      PikaScenesV2_2: ["duration", "resolution"],
      PikaStartEndFrameNode2_2: ["duration", "resolution"],
      PixverseTextToVideoNode: ["duration_seconds", "quality", "motion_mode"],
      PixverseTransitionVideoNode: [
        "duration_seconds",
        "motion_mode",
        "quality"
      ],
      PixverseImageToVideoNode: ["duration_seconds", "quality", "motion_mode"],
      StabilityStableImageSD_3_5Node: ["model"],
      RecraftTextToImageNode: ["n"],
      RecraftImageToImageNode: ["n"],
      RecraftImageInpaintingNode: ["n"],
      RecraftTextToVectorNode: ["n"],
      RecraftVectorizeImageNode: ["n"],
      RecraftGenerateColorFromImageNode: ["n"],
      RecraftGenerateImageNode: ["n"],
      RecraftGenerateVectorImageNode: ["n"],
      MoonvalleyTxt2VideoNode: ["length"],
      MoonvalleyImg2VideoNode: ["length"],
      MoonvalleyVideo2VideoNode: ["length"],
      // Runway nodes
      RunwayImageToVideoNodeGen3a: ["duration"],
      RunwayImageToVideoNodeGen4: ["duration"],
      RunwayFirstLastFrameNode: ["duration"],
      // Tripo nodes
      TripoTextToModelNode: ["quad", "style", "texture", "texture_quality"],
      TripoImageToModelNode: ["quad", "style", "texture", "texture_quality"],
      TripoTextureNode: ["texture_quality"],
      // Google/Gemini nodes
      GeminiNode: ["model"],
      // OpenAI nodes
      OpenAIChatNode: ["model"],
      // ByteDance
      ByteDanceImageNode: ["model"],
      ByteDanceImageEditNode: ["model"],
      ByteDanceTextToVideoNode: ["model", "duration", "resolution"],
      ByteDanceImageToVideoNode: ["model", "duration", "resolution"],
      ByteDanceFirstLastFrameNode: ["model", "duration", "resolution"],
      ByteDanceImageReferenceNode: ["model", "duration", "resolution"]
    };
    return widgetMap[nodeType] || [];
  }, "getRelevantWidgetNames");
  return {
    getNodeDisplayPrice,
    getNodePricingConfig,
    getRelevantWidgetNames
  };
}, "useNodePricing");
const useComputedWithWidgetWatch = /* @__PURE__ */ __name((node, options = {}) => {
  const { widgetNames, triggerCanvasRedraw = false } = options;
  const widgetValues = ref({});
  if (node.widgets) {
    const widgetsToObserve = widgetNames ? node.widgets.filter((widget) => widgetNames.includes(widget.name)) : node.widgets;
    const currentValues = {};
    widgetsToObserve.forEach((widget) => {
      currentValues[widget.name] = widget.value;
    });
    widgetValues.value = currentValues;
    widgetsToObserve.forEach((widget) => {
      widget.callback = useChainCallback(widget.callback, () => {
        widgetValues.value = {
          ...widgetValues.value,
          [widget.name]: widget.value
        };
        if (triggerCanvasRedraw) {
          node.graph?.setDirtyCanvas(true, true);
        }
      });
    });
    if (widgetNames && widgetNames.length > widgetsToObserve.length) {
      const indexesToObserve = widgetNames.map(
        (name) => widgetsToObserve.some((w) => w.name == name) ? -1 : node.inputs.findIndex((i) => i.name == name)
      ).filter((i) => i >= 0);
      node.onConnectionsChange = useChainCallback(
        node.onConnectionsChange,
        (_type, index, isConnected) => {
          if (!indexesToObserve.includes(index)) return;
          widgetValues.value = {
            ...widgetValues.value,
            [indexesToObserve[index]]: isConnected
          };
          if (triggerCanvasRedraw) {
            node.graph?.setDirtyCanvas(true, true);
          }
        }
      );
    }
  }
  return (computeFn) => {
    return computedWithControl(widgetValues, computeFn);
  };
}, "useComputedWithWidgetWatch");
const useNodeBadge = /* @__PURE__ */ __name(() => {
  const settingStore = useSettingStore();
  const extensionStore = useExtensionStore();
  const colorPaletteStore = useColorPaletteStore();
  const nodeSourceBadgeMode = computed(
    () => settingStore.get("Comfy.NodeBadge.NodeSourceBadgeMode")
  );
  const nodeIdBadgeMode = computed(
    () => settingStore.get("Comfy.NodeBadge.NodeIdBadgeMode")
  );
  const nodeLifeCycleBadgeMode = computed(
    () => settingStore.get(
      "Comfy.NodeBadge.NodeLifeCycleBadgeMode"
    )
  );
  const showApiPricingBadge = computed(
    () => settingStore.get("Comfy.NodeBadge.ShowApiPricing")
  );
  watch(
    [
      nodeSourceBadgeMode,
      nodeIdBadgeMode,
      nodeLifeCycleBadgeMode,
      showApiPricingBadge
    ],
    () => {
      app.graph?.setDirtyCanvas(true, true);
    }
  );
  const nodeDefStore = useNodeDefStore();
  function badgeTextVisible(nodeDef, badgeMode) {
    return !(badgeMode === NodeBadgeMode.None || nodeDef?.isCoreNode && badgeMode === NodeBadgeMode.HideBuiltIn);
  }
  __name(badgeTextVisible, "badgeTextVisible");
  onMounted(() => {
    const nodePricing = useNodePricing();
    extensionStore.registerExtension({
      name: "Comfy.NodeBadge",
      nodeCreated(node) {
        node.badgePosition = BadgePosition.TopRight;
        const badge = computed(() => {
          const nodeDef = nodeDefStore.fromLGraphNode(node);
          return new LGraphBadge({
            text: toolkit.truncate(
              [
                badgeTextVisible(nodeDef, nodeIdBadgeMode.value) ? `#${node.id}` : "",
                badgeTextVisible(nodeDef, nodeLifeCycleBadgeMode.value) ? nodeDef?.nodeLifeCycleBadgeText ?? "" : "",
                badgeTextVisible(nodeDef, nodeSourceBadgeMode.value) ? nodeDef?.nodeSource?.badgeText ?? "" : ""
              ].filter((s) => s.length > 0).join(" "),
              {
                length: 31
              }
            ),
            fgColor: colorPaletteStore.completedActivePalette.colors.litegraph_base.BADGE_FG_COLOR,
            bgColor: colorPaletteStore.completedActivePalette.colors.litegraph_base.BADGE_BG_COLOR
          });
        });
        node.badges.push(() => badge.value);
        if (node.constructor.nodeData?.api_node && showApiPricingBadge.value) {
          const pricingConfig = nodePricing.getNodePricingConfig(node);
          const hasDynamicPricing = typeof pricingConfig?.displayPrice === "function";
          let creditsBadge;
          const createBadge = /* @__PURE__ */ __name(() => {
            const price = nodePricing.getNodeDisplayPrice(node);
            const isLightTheme = colorPaletteStore.completedActivePalette.light_theme;
            return new LGraphBadge({
              text: price,
              iconOptions: {
                unicode: "",
                fontFamily: "PrimeIcons",
                color: isLightTheme ? adjustColor("#FABC25", { lightness: 0.5 }) : "#FABC25",
                bgColor: isLightTheme ? adjustColor("#654020", { lightness: 0.5 }) : "#654020",
                fontSize: 8
              },
              fgColor: colorPaletteStore.completedActivePalette.colors.litegraph_base.BADGE_FG_COLOR,
              bgColor: isLightTheme ? adjustColor("#8D6932", { lightness: 0.5 }) : "#8D6932"
            });
          }, "createBadge");
          if (hasDynamicPricing) {
            const relevantWidgetNames = nodePricing.getRelevantWidgetNames(
              node.constructor.nodeData?.name
            );
            const computedWithWidgetWatch = useComputedWithWidgetWatch(node, {
              widgetNames: relevantWidgetNames,
              triggerCanvasRedraw: true
            });
            creditsBadge = computedWithWidgetWatch(createBadge);
          } else {
            creditsBadge = computed(createBadge);
          }
          node.badges.push(() => creditsBadge.value);
        }
      }
    });
  });
}, "useNodeBadge");
const useCanvasDrop = /* @__PURE__ */ __name((canvasRef) => {
  const modelToNodeStore = useModelToNodeStore();
  const litegraphService = useLitegraphService();
  const workflowService = useWorkflowService();
  usePragmaticDroppable(() => canvasRef.value, {
    getDropEffect: /* @__PURE__ */ __name((args) => args.source.data.type === "tree-explorer-node" ? "copy" : "move", "getDropEffect"),
    onDrop: /* @__PURE__ */ __name(async (event) => {
      const loc = event.location.current.input;
      const dndData = event.source.data;
      if (dndData.type === "tree-explorer-node") {
        const node = dndData.data;
        if (node.data instanceof ComfyNodeDefImpl) {
          const nodeDef = node.data;
          const pos = app.clientPosToCanvasPos([loc.clientX, loc.clientY]);
          pos[1] += LiteGraph.NODE_TITLE_HEIGHT;
          litegraphService.addNodeOnGraph(nodeDef, { pos });
        } else if (node.data instanceof ComfyModelDef) {
          const model = node.data;
          const pos = app.clientPosToCanvasPos([loc.clientX, loc.clientY]);
          const nodeAtPos = app.graph.getNodeOnPos(pos[0], pos[1]);
          let targetProvider = null;
          let targetGraphNode = null;
          if (nodeAtPos) {
            const providers = modelToNodeStore.getAllNodeProviders(
              model.directory
            );
            for (const provider of providers) {
              if (provider.nodeDef.name === nodeAtPos.comfyClass) {
                targetGraphNode = nodeAtPos;
                targetProvider = provider;
              }
            }
          }
          if (!targetGraphNode) {
            const provider = modelToNodeStore.getNodeProvider(model.directory);
            if (provider) {
              targetGraphNode = litegraphService.addNodeOnGraph(
                provider.nodeDef,
                {
                  pos
                }
              );
              targetProvider = provider;
            }
          }
          if (targetGraphNode) {
            const widget = targetGraphNode.widgets?.find(
              (widget2) => widget2.name === targetProvider?.key
            );
            if (widget) {
              widget.value = model.file_name;
            }
          }
        } else if (node.data instanceof ComfyWorkflow) {
          const workflow = node.data;
          const position = app.clientPosToCanvasPos([
            loc.clientX,
            loc.clientY
          ]);
          await workflowService.insertWorkflow(workflow, { position });
        }
      }
    }, "onDrop")
  });
}, "useCanvasDrop");
const useContextMenuTranslation = /* @__PURE__ */ __name(() => {
  const f = LGraphCanvas.prototype.getCanvasMenuOptions;
  const getCanvasCenterMenuOptions = /* @__PURE__ */ __name(function(...args) {
    const res = f.apply(this, args);
    for (const item of res) {
      if (item?.content) {
        item.content = st(`contextMenu.${item.content}`, item.content);
      }
    }
    return res;
  }, "getCanvasCenterMenuOptions");
  LGraphCanvas.prototype.getCanvasMenuOptions = getCanvasCenterMenuOptions;
  function translateMenus(values, options) {
    if (!values) return;
    const reInput = /Convert (.*) to input/;
    const reWidget = /Convert (.*) to widget/;
    const cvt = st("contextMenu.Convert ", "Convert ");
    const tinp = st("contextMenu. to input", " to input");
    const twgt = st("contextMenu. to widget", " to widget");
    for (const value of values) {
      if (typeof value === "string") continue;
      translateMenus(value?.submenu?.options, options);
      if (!value?.content) {
        continue;
      }
      if (te(`contextMenu.${value.content}`)) {
        value.content = st(`contextMenu.${value.content}`, value.content);
      }
      const extraInfo = options.extra || options.parentMenu?.options?.extra;
      const matchInput = value.content?.match(reInput);
      if (matchInput) {
        let match = matchInput[1];
        extraInfo?.inputs?.find((i) => {
          if (i.name != match) return false;
          match = i.label ? i.label : i.name;
        });
        extraInfo?.widgets?.find((i) => {
          if (i.name != match) return false;
          match = i.label ? i.label : i.name;
        });
        value.content = cvt + match + tinp;
        continue;
      }
      const matchWidget = value.content?.match(reWidget);
      if (matchWidget) {
        let match = matchWidget[1];
        extraInfo?.inputs?.find((i) => {
          if (i.name != match) return false;
          match = i.label ? i.label : i.name;
        });
        extraInfo?.widgets?.find((i) => {
          if (i.name != match) return false;
          match = i.label ? i.label : i.name;
        });
        value.content = cvt + match + twgt;
        continue;
      }
    }
  }
  __name(translateMenus, "translateMenus");
  const OriginalContextMenu = LiteGraph.ContextMenu;
  function ContextMenu2(values, options) {
    if (options.title) {
      options.title = st(
        `nodeDefs.${normalizeI18nKey(options.title)}.display_name`,
        options.title
      );
    }
    translateMenus(values, options);
    const ctx = new OriginalContextMenu(values, options);
    return ctx;
  }
  __name(ContextMenu2, "ContextMenu");
  LiteGraph.ContextMenu = ContextMenu2;
  LiteGraph.ContextMenu.prototype = OriginalContextMenu.prototype;
}, "useContextMenuTranslation");
const useCopy = /* @__PURE__ */ __name(() => {
  const canvasStore = useCanvasStore();
  useEventListener(document, "copy", (e) => {
    if (!(e.target instanceof Element)) {
      return;
    }
    if (e.target instanceof HTMLTextAreaElement && e.target.type === "textarea" || e.target instanceof HTMLInputElement && e.target.type === "text") {
      return;
    }
    const isTargetInGraph = e.target.classList.contains("litegraph") || e.target.classList.contains("graph-canvas-container") || e.target.id === "graph-canvas";
    const canvas = canvasStore.canvas;
    if (isTargetInGraph && canvas?.selectedItems) {
      canvas.copyToClipboard();
      e.clipboardData?.setData("text", " ");
      e.preventDefault();
      e.stopImmediatePropagation();
      return false;
    }
  });
}, "useCopy");
const useGlobalLitegraph = /* @__PURE__ */ __name(() => {
  window["LiteGraph"] = LiteGraph;
  window["LGraph"] = LGraph;
  window["LLink"] = LLink;
  window["LGraphNode"] = LGraphNode;
  window["LGraphGroup"] = LGraphGroup;
  window["DragAndScale"] = DragAndScale;
  window["LGraphCanvas"] = LGraphCanvas;
  window["ContextMenu"] = ContextMenu$1;
  window["LGraphBadge"] = LGraphBadge;
}, "useGlobalLitegraph");
const useLitegraphSettings = /* @__PURE__ */ __name(() => {
  const settingStore = useSettingStore();
  const canvasStore = useCanvasStore();
  watchEffect(() => {
    const canvasInfoEnabled = settingStore.get("Comfy.Graph.CanvasInfo");
    if (canvasStore.canvas) {
      canvasStore.canvas.show_info = canvasInfoEnabled;
      canvasStore.canvas.draw(false, true);
    }
  });
  watchEffect(() => {
    const zoomSpeed = settingStore.get("Comfy.Graph.ZoomSpeed");
    if (canvasStore.canvas) {
      canvasStore.canvas.zoom_speed = zoomSpeed;
    }
  });
  watchEffect(() => {
    LiteGraph.snaps_for_comfy = settingStore.get(
      "Comfy.Node.AutoSnapLinkToSlot"
    );
  });
  watchEffect(() => {
    LiteGraph.snap_highlights_node = settingStore.get(
      "Comfy.Node.SnapHighlightsNode"
    );
  });
  watchEffect(() => {
    LGraphNode.keepAllLinksOnBypass = settingStore.get(
      "Comfy.Node.BypassAllLinksOnDelete"
    );
  });
  watchEffect(() => {
    LiteGraph.middle_click_slot_add_default_node = settingStore.get(
      "Comfy.Node.MiddleClickRerouteNode"
    );
  });
  watchEffect(() => {
    const linkRenderMode = settingStore.get("Comfy.LinkRenderMode");
    if (canvasStore.canvas) {
      canvasStore.canvas.links_render_mode = linkRenderMode;
      canvasStore.canvas.setDirty(
        /* fg */
        false,
        /* bg */
        true
      );
    }
  });
  watchEffect(() => {
    const minFontSizeForLOD = settingStore.get(
      "LiteGraph.Canvas.MinFontSizeForLOD"
    );
    if (canvasStore.canvas) {
      canvasStore.canvas.min_font_size_for_lod = minFontSizeForLOD;
      canvasStore.canvas.setDirty(
        /* fg */
        true,
        /* bg */
        true
      );
    }
  });
  watchEffect(() => {
    const linkMarkerShape = settingStore.get("Comfy.Graph.LinkMarkers");
    const { canvas } = canvasStore;
    if (canvas) {
      canvas.linkMarkerShape = linkMarkerShape;
      canvas.setDirty(false, true);
    }
  });
  watchEffect(() => {
    const maximumFps = settingStore.get("LiteGraph.Canvas.MaximumFps");
    const { canvas } = canvasStore;
    if (canvas) canvas.maximumFps = maximumFps;
  });
  watchEffect(() => {
    const dragZoomEnabled = settingStore.get("Comfy.Graph.CtrlShiftZoom");
    const { canvas } = canvasStore;
    if (canvas) canvas.dragZoomEnabled = dragZoomEnabled;
  });
  watchEffect(() => {
    CanvasPointer.doubleClickTime = settingStore.get(
      "Comfy.Pointer.DoubleClickTime"
    );
  });
  watchEffect(() => {
    CanvasPointer.bufferTime = settingStore.get("Comfy.Pointer.ClickBufferTime");
  });
  watchEffect(() => {
    CanvasPointer.maxClickDrift = settingStore.get("Comfy.Pointer.ClickDrift");
  });
  watchEffect(() => {
    LiteGraph.CANVAS_GRID_SIZE = settingStore.get("Comfy.SnapToGrid.GridSize");
  });
  watchEffect(() => {
    LiteGraph.alwaysSnapToGrid = settingStore.get("pysssss.SnapToGrid");
  });
  watchEffect(() => {
    LiteGraph.context_menu_scaling = settingStore.get(
      "LiteGraph.ContextMenu.Scaling"
    );
  });
  watchEffect(() => {
    LiteGraph.Reroute.maxSplineOffset = settingStore.get(
      "LiteGraph.Reroute.SplineOffset"
    );
  });
  watchEffect(() => {
    const navigationMode = settingStore.get("Comfy.Canvas.NavigationMode");
    LiteGraph.canvasNavigationMode = navigationMode;
    LiteGraph.macTrackpadGestures = navigationMode === "standard";
  });
  watchEffect(() => {
    LiteGraph.saveViewportWithGraph = settingStore.get(
      "Comfy.EnableWorkflowViewRestore"
    );
  });
}, "useLitegraphSettings");
const usePaste = /* @__PURE__ */ __name(() => {
  const workspaceStore = useWorkspaceStore();
  const canvasStore = useCanvasStore();
  const pasteItemsOnNode = /* @__PURE__ */ __name((items, node, contentType) => {
    if (!node) return;
    const filteredItems = Array.from(items).filter(
      (item) => item.type.startsWith(contentType)
    );
    const blob = filteredItems[0]?.getAsFile();
    if (!blob) return;
    node.pasteFile?.(blob);
    node.pasteFiles?.(
      Array.from(filteredItems).map((i) => i.getAsFile()).filter((f) => f !== null)
    );
  }, "pasteItemsOnNode");
  useEventListener(document, "paste", async (e) => {
    const isTargetInGraph = e.target instanceof Element && (e.target.classList.contains("litegraph") || e.target.classList.contains("graph-canvas-container") || e.target.id === "graph-canvas");
    if (!isTargetInGraph) return;
    if (workspaceStore.shiftDown) return;
    const { canvas } = canvasStore;
    if (!canvas) return;
    const { graph } = canvas;
    let data = e.clipboardData;
    if (!data) throw new Error("No clipboard data on clipboard event");
    const { items } = data;
    const currentNode = canvas.current_node;
    const isNodeSelected = currentNode?.is_selected;
    const isImageNodeSelected = isNodeSelected && isImageNode(currentNode);
    const isVideoNodeSelected = isNodeSelected && isVideoNode(currentNode);
    const isAudioNodeSelected = isNodeSelected && isAudioNode(currentNode);
    let imageNode = isImageNodeSelected ? currentNode : null;
    let audioNode = isAudioNodeSelected ? currentNode : null;
    const videoNode = isVideoNodeSelected ? currentNode : null;
    for (const item of items) {
      if (item.type.startsWith("image/")) {
        if (!imageNode) {
          const newNode = LiteGraph.createNode("LoadImage");
          if (newNode) {
            newNode.pos = [canvas.graph_mouse[0], canvas.graph_mouse[1]];
            imageNode = graph?.add(newNode) ?? null;
          }
          graph?.change();
        }
        pasteItemsOnNode(items, imageNode, "image");
        return;
      } else if (item.type.startsWith("video/")) {
        if (!videoNode) {
        } else {
          pasteItemsOnNode(items, videoNode, "video");
          return;
        }
      } else if (item.type.startsWith("audio/")) {
        if (!audioNode) {
          const newNode = LiteGraph.createNode("LoadAudio");
          if (newNode) {
            newNode.pos = [canvas.graph_mouse[0], canvas.graph_mouse[1]];
            audioNode = graph?.add(newNode) ?? null;
          }
          graph?.change();
        }
        pasteItemsOnNode(items, audioNode, "audio");
        return;
      }
    }
    data = data.getData("text/plain");
    let workflow = null;
    try {
      data = data.slice(data.indexOf("{"));
      workflow = JSON.parse(data);
    } catch (err) {
      try {
        data = data.slice(data.indexOf("workflow\n"));
        data = data.slice(data.indexOf("{"));
        workflow = JSON.parse(data);
      } catch (error) {
        workflow = null;
      }
    }
    if (workflow && workflow.version && workflow.nodes && workflow.extra) {
      await app.loadGraphData(workflow);
    } else {
      if (e.target instanceof HTMLTextAreaElement && e.target.type === "textarea" || e.target instanceof HTMLInputElement && e.target.type === "text") {
        return;
      }
      canvas.pasteFromClipboard();
    }
  });
}, "usePaste");
const useVueFeatureFlags = /* @__PURE__ */ __name(() => {
  const settingStore = useSettingStore();
  const isVueNodesEnabled = computed(() => {
    try {
      return settingStore.get("Comfy.VueNodes.Enabled") ?? false;
    } catch {
      return false;
    }
  });
  const shouldRenderVueNodes = computed(() => isVueNodesEnabled.value);
  const syncVueNodesFlag = /* @__PURE__ */ __name(() => {
    LiteGraph.vueNodesMode = isVueNodesEnabled.value;
  }, "syncVueNodesFlag");
  watch(isVueNodesEnabled, syncVueNodesFlag, { immediate: true });
  return {
    isVueNodesEnabled,
    shouldRenderVueNodes,
    syncVueNodesFlag
  };
}, "useVueFeatureFlags");
function useWorkflowAutoSave() {
  const workflowStore = useWorkflowStore();
  const settingStore = useSettingStore();
  const workflowService = useWorkflowService();
  const autoSaveSetting = computed(
    () => settingStore.get("Comfy.Workflow.AutoSave")
  );
  const autoSaveDelay = computed(
    () => settingStore.get("Comfy.Workflow.AutoSaveDelay")
  );
  let autoSaveTimeout = null;
  let isSaving = false;
  let needsAutoSave = false;
  const scheduleAutoSave = /* @__PURE__ */ __name(() => {
    if (autoSaveTimeout) {
      clearTimeout(autoSaveTimeout);
      autoSaveTimeout = null;
    }
    if (autoSaveSetting.value === "after delay") {
      if (isSaving) {
        needsAutoSave = true;
        return;
      }
      const delay = autoSaveDelay.value;
      autoSaveTimeout = setTimeout(async () => {
        const activeWorkflow = workflowStore.activeWorkflow;
        if (activeWorkflow?.isModified && activeWorkflow.isPersisted) {
          try {
            isSaving = true;
            await workflowService.saveWorkflow(activeWorkflow);
          } catch (err) {
            console.error("Auto save failed:", err);
          } finally {
            isSaving = false;
            if (needsAutoSave) {
              needsAutoSave = false;
              scheduleAutoSave();
            }
          }
        }
      }, delay);
    }
  }, "scheduleAutoSave");
  watch(
    autoSaveSetting,
    (newSetting) => {
      if (autoSaveTimeout) {
        clearTimeout(autoSaveTimeout);
        autoSaveTimeout = null;
      }
      if (newSetting === "after delay" && workflowStore.activeWorkflow?.isModified) {
        scheduleAutoSave();
      }
    },
    { immediate: true }
  );
  const onGraphChanged = /* @__PURE__ */ __name(() => {
    scheduleAutoSave();
  }, "onGraphChanged");
  api.addEventListener("graphChanged", onGraphChanged);
  onUnmounted(() => {
    if (autoSaveTimeout) {
      clearTimeout(autoSaveTimeout);
      autoSaveTimeout = null;
    }
    api.removeEventListener("graphChanged", onGraphChanged);
  });
}
__name(useWorkflowAutoSave, "useWorkflowAutoSave");
function useWorkflowPersistence() {
  const workflowStore = useWorkflowStore();
  const settingStore = useSettingStore();
  const workflowPersistenceEnabled = computed(
    () => settingStore.get("Comfy.Workflow.Persist")
  );
  const persistCurrentWorkflow = /* @__PURE__ */ __name(() => {
    if (!workflowPersistenceEnabled.value) return;
    const workflow = JSON.stringify(app.graph.serialize());
    localStorage.setItem("workflow", workflow);
    if (api.clientId) {
      sessionStorage.setItem(`workflow:${api.clientId}`, workflow);
    }
  }, "persistCurrentWorkflow");
  const loadWorkflowFromStorage = /* @__PURE__ */ __name(async (json, workflowName) => {
    if (!json) return false;
    const workflow = JSON.parse(json);
    await app.loadGraphData(workflow, true, true, workflowName);
    return true;
  }, "loadWorkflowFromStorage");
  const loadPreviousWorkflowFromStorage = /* @__PURE__ */ __name(async () => {
    const workflowName = getStorageValue("Comfy.PreviousWorkflow");
    const clientId = api.initialClientId ?? api.clientId;
    if (clientId) {
      const sessionWorkflow = sessionStorage.getItem(`workflow:${clientId}`);
      if (await loadWorkflowFromStorage(sessionWorkflow, workflowName)) {
        return true;
      }
    }
    const localWorkflow = localStorage.getItem("workflow");
    return await loadWorkflowFromStorage(localWorkflow, workflowName);
  }, "loadPreviousWorkflowFromStorage");
  const loadDefaultWorkflow = /* @__PURE__ */ __name(async () => {
    if (!settingStore.get("Comfy.TutorialCompleted")) {
      await settingStore.set("Comfy.TutorialCompleted", true);
      await useWorkflowService().loadBlankWorkflow();
      await useCommandStore().execute("Comfy.BrowseTemplates");
    } else {
      await app.loadGraphData();
    }
  }, "loadDefaultWorkflow");
  const restorePreviousWorkflow = /* @__PURE__ */ __name(async () => {
    if (!workflowPersistenceEnabled.value) return;
    try {
      const restored = await loadPreviousWorkflowFromStorage();
      if (!restored) {
        await loadDefaultWorkflow();
      }
    } catch (err) {
      console.error("Error loading previous workflow", err);
      await loadDefaultWorkflow();
    }
  }, "restorePreviousWorkflow");
  watch(
    () => workflowStore.activeWorkflow?.key,
    (activeWorkflowKey) => {
      if (!activeWorkflowKey) return;
      setStorageValue("Comfy.PreviousWorkflow", activeWorkflowKey);
      persistCurrentWorkflow();
    }
  );
  api.addEventListener("graphChanged", persistCurrentWorkflow);
  tryOnScopeDispose(() => {
    api.removeEventListener("graphChanged", persistCurrentWorkflow);
  });
  const openWorkflows = computed(() => workflowStore.openWorkflows);
  const activeWorkflow = computed(() => workflowStore.activeWorkflow);
  const restoreState = computed(
    () => {
      if (!openWorkflows.value || !activeWorkflow.value) {
        return { paths: [], activeIndex: -1 };
      }
      const paths = openWorkflows.value.filter((workflow) => workflow?.isPersisted && !workflow.isModified).map((workflow) => workflow.path);
      const activeIndex = openWorkflows.value.findIndex(
        (workflow) => workflow.path === activeWorkflow.value?.path
      );
      return { paths, activeIndex };
    }
  );
  const storedWorkflows = JSON.parse(
    getStorageValue("Comfy.OpenWorkflowsPaths") || "[]"
  );
  const storedActiveIndex = JSON.parse(
    getStorageValue("Comfy.ActiveWorkflowIndex") || "-1"
  );
  watch(restoreState, ({ paths, activeIndex }) => {
    if (workflowPersistenceEnabled.value) {
      setStorageValue("Comfy.OpenWorkflowsPaths", JSON.stringify(paths));
      setStorageValue("Comfy.ActiveWorkflowIndex", JSON.stringify(activeIndex));
    }
  });
  const restoreWorkflowTabsState = /* @__PURE__ */ __name(() => {
    if (!workflowPersistenceEnabled.value) return;
    const isRestorable = storedWorkflows?.length > 0 && storedActiveIndex >= 0;
    if (isRestorable) {
      workflowStore.openWorkflowsInBackground({
        left: storedWorkflows.slice(0, storedActiveIndex),
        right: storedWorkflows.slice(storedActiveIndex)
      });
    }
  }, "restoreWorkflowTabsState");
  return {
    restorePreviousWorkflow,
    restoreWorkflowTabsState
  };
}
__name(useWorkflowPersistence, "useWorkflowPersistence");
const CORE_SETTINGS = [
  {
    id: "Comfy.Memory.AllowManualUnload",
    name: "Allow manual unload of models and execution cache via user command",
    type: "hidden",
    defaultValue: true,
    versionAdded: "1.18.0"
  },
  {
    id: "Comfy.Validation.Workflows",
    name: "Validate workflows",
    type: "boolean",
    defaultValue: true
  },
  {
    id: "Comfy.NodeSearchBoxImpl",
    category: ["Comfy", "Node Search Box", "Implementation"],
    experimental: true,
    name: "Node search box implementation",
    type: "combo",
    options: ["default", "litegraph (legacy)"],
    defaultValue: "default"
  },
  {
    id: "Comfy.LinkRelease.Action",
    category: ["LiteGraph", "LinkRelease", "Action"],
    name: "Action on link release (No modifier)",
    type: "combo",
    options: Object.values(LinkReleaseTriggerAction),
    defaultValue: LinkReleaseTriggerAction.CONTEXT_MENU,
    defaultsByInstallVersion: {
      "1.24.1": LinkReleaseTriggerAction.SEARCH_BOX
    }
  },
  {
    id: "Comfy.LinkRelease.ActionShift",
    category: ["LiteGraph", "LinkRelease", "ActionShift"],
    name: "Action on link release (Shift)",
    type: "combo",
    options: Object.values(LinkReleaseTriggerAction),
    defaultValue: LinkReleaseTriggerAction.SEARCH_BOX,
    defaultsByInstallVersion: {
      "1.24.1": LinkReleaseTriggerAction.CONTEXT_MENU
    }
  },
  {
    id: "Comfy.NodeSearchBoxImpl.NodePreview",
    category: ["Comfy", "Node Search Box", "NodePreview"],
    name: "Node preview",
    tooltip: "Only applies to the default implementation",
    type: "boolean",
    defaultValue: true
  },
  {
    id: "Comfy.NodeSearchBoxImpl.ShowCategory",
    category: ["Comfy", "Node Search Box", "ShowCategory"],
    name: "Show node category in search results",
    tooltip: "Only applies to the default implementation",
    type: "boolean",
    defaultValue: true
  },
  {
    id: "Comfy.NodeSearchBoxImpl.ShowIdName",
    category: ["Comfy", "Node Search Box", "ShowIdName"],
    name: "Show node id name in search results",
    tooltip: "Only applies to the default implementation",
    type: "boolean",
    defaultValue: false
  },
  {
    id: "Comfy.NodeSearchBoxImpl.ShowNodeFrequency",
    category: ["Comfy", "Node Search Box", "ShowNodeFrequency"],
    name: "Show node frequency in search results",
    tooltip: "Only applies to the default implementation",
    type: "boolean",
    defaultValue: false
  },
  {
    id: "Comfy.Sidebar.Location",
    category: ["Appearance", "Sidebar", "Location"],
    name: "Sidebar location",
    type: "combo",
    options: ["left", "right"],
    defaultValue: "left"
  },
  {
    id: "Comfy.Sidebar.Size",
    category: ["Appearance", "Sidebar", "Size"],
    name: "Sidebar size",
    type: "combo",
    options: ["normal", "small"],
    // Default to small if the window is less than 1536px(2xl) wide.
    defaultValue: /* @__PURE__ */ __name(() => window.innerWidth < 1536 ? "small" : "normal", "defaultValue")
  },
  {
    id: "Comfy.Sidebar.UnifiedWidth",
    category: ["Appearance", "Sidebar", "UnifiedWidth"],
    name: "Unified sidebar width",
    type: "boolean",
    defaultValue: true,
    versionAdded: "1.18.1"
  },
  {
    id: "Comfy.TextareaWidget.FontSize",
    category: ["Appearance", "Node Widget", "TextareaWidget", "FontSize"],
    name: "Textarea widget font size",
    type: "slider",
    defaultValue: 10,
    attrs: {
      min: 8,
      max: 24
    }
  },
  {
    id: "Comfy.TextareaWidget.Spellcheck",
    category: ["Comfy", "Node Widget", "TextareaWidget", "Spellcheck"],
    name: "Textarea widget spellcheck",
    type: "boolean",
    defaultValue: false
  },
  {
    id: "Comfy.Workflow.SortNodeIdOnSave",
    name: "Sort node IDs when saving workflow",
    type: "boolean",
    defaultValue: false
  },
  {
    id: "Comfy.Graph.CanvasInfo",
    category: ["LiteGraph", "Canvas", "CanvasInfo"],
    name: "Show canvas info on bottom left corner (fps, etc.)",
    type: "boolean",
    defaultValue: true
  },
  {
    id: "Comfy.Node.ShowDeprecated",
    name: "Show deprecated nodes in search",
    tooltip: "Deprecated nodes are hidden by default in the UI, but remain functional in existing workflows that use them.",
    type: "boolean",
    defaultValue: false
  },
  {
    id: "Comfy.Node.ShowExperimental",
    name: "Show experimental nodes in search",
    tooltip: "Experimental nodes are marked as such in the UI and may be subject to significant changes or removal in future versions. Use with caution in production workflows",
    type: "boolean",
    defaultValue: true
  },
  {
    id: "Comfy.Node.Opacity",
    category: ["Appearance", "Node", "Opacity"],
    name: "Node opacity",
    type: "slider",
    defaultValue: 1,
    attrs: {
      min: 0.01,
      max: 1,
      step: 0.01
    }
  },
  {
    id: "Comfy.Workflow.ShowMissingNodesWarning",
    name: "Show missing nodes warning",
    type: "boolean",
    defaultValue: true
  },
  {
    id: "Comfy.Workflow.ShowMissingModelsWarning",
    name: "Show missing models warning",
    type: "boolean",
    defaultValue: true,
    experimental: true
  },
  {
    id: "Comfy.Graph.ZoomSpeed",
    category: ["LiteGraph", "Canvas", "ZoomSpeed"],
    name: "Canvas zoom speed",
    type: "slider",
    defaultValue: 1.1,
    attrs: {
      min: 1.01,
      max: 2.5,
      step: 0.01
    }
  },
  // Bookmarks are stored in the settings store.
  // Bookmarks are in format of category/display_name. e.g. "conditioning/CLIPTextEncode"
  {
    id: "Comfy.NodeLibrary.Bookmarks",
    name: "Node library bookmarks with display name (deprecated)",
    type: "hidden",
    defaultValue: [],
    deprecated: true
  },
  {
    id: "Comfy.NodeLibrary.Bookmarks.V2",
    name: "Node library bookmarks v2 with unique name",
    type: "hidden",
    defaultValue: []
  },
  // Stores mapping from bookmark folder name to its customization.
  {
    id: "Comfy.NodeLibrary.BookmarksCustomization",
    name: "Node library bookmarks customization",
    type: "hidden",
    defaultValue: {}
  },
  // Hidden setting used by the queue for how to fit images
  {
    id: "Comfy.Queue.ImageFit",
    name: "Queue image fit",
    type: "hidden",
    defaultValue: "cover"
  },
  {
    id: "Comfy.GroupSelectedNodes.Padding",
    category: ["LiteGraph", "Group", "Padding"],
    name: "Group selected nodes padding",
    type: "slider",
    defaultValue: 10,
    attrs: {
      min: 0,
      max: 100
    }
  },
  {
    id: "Comfy.Node.DoubleClickTitleToEdit",
    category: ["LiteGraph", "Node", "DoubleClickTitleToEdit"],
    name: "Double click node title to edit",
    type: "boolean",
    defaultValue: true
  },
  {
    id: "Comfy.Node.AllowImageSizeDraw",
    category: ["LiteGraph", "Node Widget", "AllowImageSizeDraw"],
    name: "Show width × height below the image preview",
    type: "boolean",
    defaultValue: true
  },
  {
    id: "Comfy.Group.DoubleClickTitleToEdit",
    category: ["LiteGraph", "Group", "DoubleClickTitleToEdit"],
    name: "Double click group title to edit",
    type: "boolean",
    defaultValue: true
  },
  {
    id: "Comfy.Window.UnloadConfirmation",
    name: "Show confirmation when closing window",
    type: "boolean",
    defaultValue: true,
    versionModified: "1.7.12"
  },
  {
    id: "Comfy.TreeExplorer.ItemPadding",
    category: ["Appearance", "Tree Explorer", "ItemPadding"],
    name: "Tree explorer item padding",
    type: "slider",
    defaultValue: 2,
    attrs: {
      min: 0,
      max: 8,
      step: 1
    }
  },
  {
    id: "Comfy.ModelLibrary.AutoLoadAll",
    name: "Automatically load all model folders",
    tooltip: "If true, all folders will load as soon as you open the model library (this may cause delays while it loads). If false, root level model folders will only load once you click on them.",
    type: "boolean",
    defaultValue: false
  },
  {
    id: "Comfy.ModelLibrary.NameFormat",
    name: "What name to display in the model library tree view",
    tooltip: 'Select "filename" to render a simplified view of the raw filename (without directory or ".safetensors" extension) in the model list. Select "title" to display the configurable model metadata title.',
    type: "combo",
    options: ["filename", "title"],
    defaultValue: "title"
  },
  {
    id: "Comfy.Locale",
    name: "Language",
    type: "combo",
    options: [
      { value: "en", text: "English" },
      { value: "zh", text: "中文" },
      { value: "zh-TW", text: "繁體中文" },
      { value: "ru", text: "Русский" },
      { value: "ja", text: "日本語" },
      { value: "ko", text: "한국어" },
      { value: "fr", text: "Français" },
      { value: "es", text: "Español" },
      { value: "ar", text: "عربي" }
    ],
    defaultValue: /* @__PURE__ */ __name(() => navigator.language.split("-")[0] || "en", "defaultValue")
  },
  {
    id: "Comfy.NodeBadge.NodeSourceBadgeMode",
    category: ["LiteGraph", "Node", "NodeSourceBadgeMode"],
    name: "Node source badge mode",
    type: "combo",
    options: Object.values(NodeBadgeMode),
    defaultValue: NodeBadgeMode.HideBuiltIn
  },
  {
    id: "Comfy.NodeBadge.NodeIdBadgeMode",
    category: ["LiteGraph", "Node", "NodeIdBadgeMode"],
    name: "Node ID badge mode",
    type: "combo",
    options: [NodeBadgeMode.None, NodeBadgeMode.ShowAll],
    defaultValue: NodeBadgeMode.None
  },
  {
    id: "Comfy.NodeBadge.NodeLifeCycleBadgeMode",
    category: ["LiteGraph", "Node", "NodeLifeCycleBadgeMode"],
    name: "Node life cycle badge mode",
    type: "combo",
    options: [NodeBadgeMode.None, NodeBadgeMode.ShowAll],
    defaultValue: NodeBadgeMode.ShowAll
  },
  {
    id: "Comfy.NodeBadge.ShowApiPricing",
    category: ["Comfy", "API Nodes"],
    name: "Show API node pricing badge",
    type: "boolean",
    defaultValue: true,
    versionAdded: "1.20.3"
  },
  {
    id: "Comfy.Notification.ShowVersionUpdates",
    category: ["Comfy", "Notification Preferences"],
    name: "Show version updates",
    tooltip: "Show updates for new models, and major new features.",
    type: "boolean",
    defaultValue: true
  },
  {
    id: "Comfy.ConfirmClear",
    category: ["Comfy", "Workflow", "ConfirmClear"],
    name: "Require confirmation when clearing workflow",
    type: "boolean",
    defaultValue: true
  },
  {
    id: "Comfy.PromptFilename",
    category: ["Comfy", "Workflow", "PromptFilename"],
    name: "Prompt for filename when saving workflow",
    type: "boolean",
    defaultValue: true
  },
  /**
   * file format for preview
   *
   * format;quality
   *
   * ex)
   * webp;50 -> webp, quality 50
   * jpeg;80 -> rgb, jpeg, quality 80
   *
   * @type {string}
   */
  {
    id: "Comfy.PreviewFormat",
    category: ["LiteGraph", "Node Widget", "PreviewFormat"],
    name: "Preview image format",
    tooltip: "When displaying a preview in the image widget, convert it to a lightweight image, e.g. webp, jpeg, webp;50, etc.",
    type: "text",
    defaultValue: ""
  },
  {
    id: "Comfy.DisableSliders",
    category: ["LiteGraph", "Node Widget", "DisableSliders"],
    name: "Disable node widget sliders",
    type: "boolean",
    defaultValue: false
  },
  {
    id: "Comfy.DisableFloatRounding",
    category: ["LiteGraph", "Node Widget", "DisableFloatRounding"],
    name: "Disable default float widget rounding.",
    tooltip: "(requires page reload) Cannot disable round when round is set by the node in the backend.",
    type: "boolean",
    defaultValue: false
  },
  {
    id: "Comfy.FloatRoundingPrecision",
    category: ["LiteGraph", "Node Widget", "FloatRoundingPrecision"],
    name: "Float widget rounding decimal places [0 = auto].",
    tooltip: "(requires page reload)",
    type: "slider",
    attrs: {
      min: 0,
      max: 6,
      step: 1
    },
    defaultValue: 0
  },
  {
    id: "LiteGraph.Node.TooltipDelay",
    name: "Tooltip Delay",
    type: "number",
    attrs: {
      min: 100,
      max: 3e3,
      step: 50
    },
    defaultValue: 500,
    versionAdded: "1.9.0"
  },
  {
    id: "Comfy.EnableTooltips",
    category: ["LiteGraph", "Node", "EnableTooltips"],
    name: "Enable Tooltips",
    type: "boolean",
    defaultValue: true
  },
  {
    id: "Comfy.DevMode",
    name: "Enable dev mode options (API save, etc.)",
    type: "boolean",
    defaultValue: false,
    onChange: /* @__PURE__ */ __name((value) => {
      const element = document.getElementById("comfy-dev-save-api-button");
      if (element) {
        element.style.display = value ? "flex" : "none";
      }
    }, "onChange")
  },
  {
    id: "Comfy.UseNewMenu",
    category: ["Comfy", "Menu", "UseNewMenu"],
    defaultValue: "Top",
    name: "Use new menu",
    type: "combo",
    options: ["Disabled", "Top", "Bottom"],
    tooltip: "Menu bar position. On mobile devices, the menu is always shown at the top.",
    migrateDeprecatedValue: /* @__PURE__ */ __name((value) => {
      if (value === "Floating") {
        return "Top";
      }
      return value;
    }, "migrateDeprecatedValue")
  },
  {
    id: "Comfy.Workflow.WorkflowTabsPosition",
    name: "Opened workflows position",
    type: "combo",
    options: ["Sidebar", "Topbar", "Topbar (2nd-row)"],
    // Default to topbar (2nd-row) if the window is less than 1536px(2xl) wide.
    defaultValue: /* @__PURE__ */ __name(() => window.innerWidth < 1536 ? "Topbar (2nd-row)" : "Topbar", "defaultValue")
  },
  {
    id: "Comfy.Graph.CanvasMenu",
    category: ["LiteGraph", "Canvas", "CanvasMenu"],
    name: "Show graph canvas menu",
    type: "boolean",
    defaultValue: true
  },
  {
    id: "Comfy.QueueButton.BatchCountLimit",
    name: "Batch count limit",
    tooltip: "The maximum number of tasks added to the queue at one button click",
    type: "number",
    defaultValue: 100,
    versionAdded: "1.3.5"
  },
  {
    id: "Comfy.Keybinding.UnsetBindings",
    name: "Keybindings unset by the user",
    type: "hidden",
    defaultValue: [],
    versionAdded: "1.3.7",
    versionModified: "1.7.3",
    migrateDeprecatedValue: /* @__PURE__ */ __name((value) => {
      return value.map((keybinding) => {
        if (keybinding["targetSelector"] === "#graph-canvas") {
          keybinding["targetElementId"] = "graph-canvas";
        }
        return keybinding;
      });
    }, "migrateDeprecatedValue")
  },
  {
    id: "Comfy.Keybinding.NewBindings",
    name: "Keybindings set by the user",
    type: "hidden",
    defaultValue: [],
    versionAdded: "1.3.7"
  },
  {
    id: "Comfy.Extension.Disabled",
    name: "Disabled extension names",
    type: "hidden",
    defaultValue: [],
    versionAdded: "1.3.11"
  },
  {
    id: "Comfy.LinkRenderMode",
    category: ["LiteGraph", "Graph", "LinkRenderMode"],
    name: "Link Render Mode",
    defaultValue: 2,
    type: "combo",
    options: [
      { value: LiteGraph.STRAIGHT_LINK, text: "Straight" },
      { value: LiteGraph.LINEAR_LINK, text: "Linear" },
      { value: LiteGraph.SPLINE_LINK, text: "Spline" },
      { value: LiteGraph.HIDDEN_LINK, text: "Hidden" }
    ]
  },
  {
    id: "Comfy.Node.AutoSnapLinkToSlot",
    category: ["LiteGraph", "Node", "AutoSnapLinkToSlot"],
    name: "Auto snap link to node slot",
    tooltip: "When dragging a link over a node, the link automatically snap to a viable input slot on the node",
    type: "boolean",
    defaultValue: true,
    versionAdded: "1.3.29"
  },
  {
    id: "Comfy.Node.SnapHighlightsNode",
    category: ["LiteGraph", "Node", "SnapHighlightsNode"],
    name: "Snap highlights node",
    tooltip: "When dragging a link over a node with viable input slot, highlight the node",
    type: "boolean",
    defaultValue: true,
    versionAdded: "1.3.29"
  },
  {
    id: "Comfy.Node.BypassAllLinksOnDelete",
    category: ["LiteGraph", "Node", "BypassAllLinksOnDelete"],
    name: "Keep all links when deleting nodes",
    tooltip: "When deleting a node, attempt to reconnect all of its input and output links (bypassing the deleted node)",
    type: "boolean",
    defaultValue: true,
    versionAdded: "1.3.40"
  },
  {
    id: "Comfy.Node.MiddleClickRerouteNode",
    category: ["LiteGraph", "Node", "MiddleClickRerouteNode"],
    name: "Middle-click creates a new Reroute node",
    type: "boolean",
    defaultValue: true,
    versionAdded: "1.3.42"
  },
  {
    id: "Comfy.Graph.LinkMarkers",
    category: ["LiteGraph", "Link", "LinkMarkers"],
    name: "Link midpoint markers",
    defaultValue: LinkMarkerShape.Circle,
    type: "combo",
    options: [
      { value: LinkMarkerShape.None, text: "None" },
      { value: LinkMarkerShape.Circle, text: "Circle" },
      { value: LinkMarkerShape.Arrow, text: "Arrow" }
    ],
    versionAdded: "1.3.42"
  },
  {
    id: "Comfy.DOMClippingEnabled",
    category: ["LiteGraph", "Node", "DOMClippingEnabled"],
    name: "Enable DOM element clipping (enabling may reduce performance)",
    type: "boolean",
    defaultValue: true
  },
  {
    id: "Comfy.Graph.CtrlShiftZoom",
    category: ["LiteGraph", "Canvas", "CtrlShiftZoom"],
    name: "Enable fast-zoom shortcut (Ctrl + Shift + Drag)",
    type: "boolean",
    defaultValue: true,
    versionAdded: "1.4.0"
  },
  {
    id: "Comfy.Pointer.ClickDrift",
    category: ["LiteGraph", "Pointer", "ClickDrift"],
    name: "Pointer click drift (maximum distance)",
    tooltip: "If the pointer moves more than this distance while holding a button down, it is considered dragging (rather than clicking).\n\nHelps prevent objects from being unintentionally nudged if the pointer is moved whilst clicking.",
    experimental: true,
    type: "slider",
    attrs: {
      min: 0,
      max: 20,
      step: 1
    },
    defaultValue: 6,
    versionAdded: "1.4.3"
  },
  {
    id: "Comfy.Pointer.ClickBufferTime",
    category: ["LiteGraph", "Pointer", "ClickBufferTime"],
    name: "Pointer click drift delay",
    tooltip: "After pressing a pointer button down, this is the maximum time (in milliseconds) that pointer movement can be ignored for.\n\nHelps prevent objects from being unintentionally nudged if the pointer is moved whilst clicking.",
    experimental: true,
    type: "slider",
    attrs: {
      min: 0,
      max: 1e3,
      step: 25
    },
    defaultValue: 150,
    versionAdded: "1.4.3"
  },
  {
    id: "Comfy.Pointer.DoubleClickTime",
    category: ["LiteGraph", "Pointer", "DoubleClickTime"],
    name: "Double click interval (maximum)",
    tooltip: "The maximum time in milliseconds between the two clicks of a double-click.  Increasing this value may assist if double-clicks are sometimes not registered.",
    type: "slider",
    attrs: {
      min: 100,
      max: 1e3,
      step: 50
    },
    defaultValue: 300,
    versionAdded: "1.4.3"
  },
  {
    id: "Comfy.SnapToGrid.GridSize",
    category: ["LiteGraph", "Canvas", "GridSize"],
    name: "Snap to grid size",
    type: "slider",
    attrs: {
      min: 1,
      max: 500
    },
    tooltip: "When dragging and resizing nodes while holding shift they will be aligned to the grid, this controls the size of that grid.",
    defaultValue: LiteGraph.CANVAS_GRID_SIZE
  },
  // Keep the 'pysssss.SnapToGrid' setting id so we don't need to migrate setting values.
  // Using a new setting id can cause existing users to lose their existing settings.
  {
    id: "pysssss.SnapToGrid",
    category: ["LiteGraph", "Canvas", "AlwaysSnapToGrid"],
    name: "Always snap to grid",
    type: "boolean",
    defaultValue: false,
    versionAdded: "1.3.13"
  },
  {
    id: "Comfy.Server.ServerConfigValues",
    name: "Server config values for frontend display",
    tooltip: "Server config values used for frontend display only",
    type: "hidden",
    // Mapping from server config id to value.
    defaultValue: {},
    versionAdded: "1.4.8"
  },
  {
    id: "Comfy.Server.LaunchArgs",
    name: "Server launch arguments",
    tooltip: "These are the actual arguments that are passed to the server when it is launched.",
    type: "hidden",
    defaultValue: {},
    versionAdded: "1.4.8"
  },
  {
    id: "Comfy.Queue.MaxHistoryItems",
    name: "Queue history size",
    tooltip: "The maximum number of tasks that show in the queue history.",
    type: "slider",
    attrs: {
      min: 2,
      max: 256,
      step: 2
    },
    defaultValue: 64,
    versionAdded: "1.4.12"
  },
  {
    id: "LiteGraph.Canvas.MaximumFps",
    name: "Maximum FPS",
    tooltip: "The maximum frames per second that the canvas is allowed to render. Caps GPU usage at the cost of smoothness. If 0, the screen refresh rate is used. Default: 0",
    type: "slider",
    attrs: {
      min: 0,
      max: 120
    },
    defaultValue: 0,
    versionAdded: "1.5.1"
  },
  {
    id: "Comfy.EnableWorkflowViewRestore",
    category: ["Comfy", "Workflow", "EnableWorkflowViewRestore"],
    name: "Save and restore canvas position and zoom level in workflows",
    type: "boolean",
    defaultValue: true,
    versionModified: "1.5.4"
  },
  {
    id: "Comfy.Workflow.ConfirmDelete",
    name: "Show confirmation when deleting workflows",
    type: "boolean",
    defaultValue: true,
    versionAdded: "1.5.6"
  },
  {
    id: "Comfy.ColorPalette",
    name: "The active color palette id",
    type: "hidden",
    defaultValue: "dark",
    versionModified: "1.6.7",
    migrateDeprecatedValue(value) {
      return value.startsWith("custom_") ? value.replace("custom_", "") : value;
    }
  },
  {
    id: "Comfy.CustomColorPalettes",
    name: "Custom color palettes",
    type: "hidden",
    defaultValue: {},
    versionModified: "1.6.7"
  },
  {
    id: "Comfy.WidgetControlMode",
    category: ["Comfy", "Node Widget", "WidgetControlMode"],
    name: "Widget control mode",
    tooltip: "Controls when widget values are updated (randomize/increment/decrement), either before the prompt is queued or after.",
    type: "combo",
    defaultValue: "after",
    options: ["before", "after"],
    versionModified: "1.6.10"
  },
  {
    id: "Comfy.TutorialCompleted",
    name: "Tutorial completed",
    type: "hidden",
    defaultValue: false,
    versionAdded: "1.8.7"
  },
  {
    id: "Comfy.InstalledVersion",
    name: "The frontend version that was running when the user first installed ComfyUI",
    type: "hidden",
    defaultValue: null,
    versionAdded: "1.24.0"
  },
  {
    id: "LiteGraph.ContextMenu.Scaling",
    name: "Scale node combo widget menus (lists) when zoomed in",
    defaultValue: false,
    type: "boolean",
    versionAdded: "1.8.8"
  },
  {
    id: "LiteGraph.Canvas.LowQualityRenderingZoomThreshold",
    type: "hidden",
    deprecated: true,
    name: "Low quality rendering zoom threshold (deprecated)",
    tooltip: "Zoom level threshold for performance mode. Lower values (0.1) = quality at all zoom levels. Higher values (1.0) = performance mode even when zoomed in. Performance mode simplifies rendering by hiding text labels, shadows, and details.",
    attrs: {
      min: 0.1,
      max: 1,
      step: 0.01
    },
    defaultValue: 0.6,
    versionAdded: "1.9.1",
    versionModified: "1.26.7"
  },
  {
    id: "LiteGraph.Canvas.MinFontSizeForLOD",
    name: "Zoom Node Level of Detail - font size threshold",
    tooltip: "Controls when the nodes switch to low quality LOD rendering. Uses font size in pixels to determine when to switch. Set to 0 to disable. Values 1-24 set the minimum font size threshold for LOD - higher values (24px) = switch nodes to simplified rendering sooner when zooming out, lower values (1px) = maintain full node quality longer.",
    type: "slider",
    attrs: {
      min: 0,
      max: 24,
      step: 1
    },
    defaultValue: 8,
    versionAdded: "1.26.7"
  },
  {
    id: "Comfy.Canvas.NavigationMode",
    category: ["LiteGraph", "Canvas", "CanvasNavigationMode"],
    name: "Canvas Navigation Mode",
    defaultValue: "legacy",
    type: "combo",
    options: [
      { value: "standard", text: "Standard (New)" },
      { value: "legacy", text: "Drag Navigation" }
    ],
    versionAdded: "1.25.0",
    defaultsByInstallVersion: {
      "1.25.0": "legacy"
    }
  },
  {
    id: "Comfy.Canvas.SelectionToolbox",
    category: ["LiteGraph", "Canvas", "SelectionToolbox"],
    name: "Show selection toolbox",
    type: "boolean",
    defaultValue: true,
    versionAdded: "1.10.5"
  },
  {
    id: "LiteGraph.Reroute.SplineOffset",
    name: "Reroute spline offset",
    tooltip: "The bezier control point offset from the reroute centre point",
    type: "slider",
    defaultValue: 20,
    attrs: {
      min: 0,
      max: 400
    },
    versionAdded: "1.15.7"
  },
  {
    id: "Comfy.Toast.DisableReconnectingToast",
    name: "Disable toasts when reconnecting or reconnected",
    type: "hidden",
    defaultValue: false,
    versionAdded: "1.15.12"
  },
  {
    id: "Comfy.Minimap.Visible",
    name: "Display minimap on canvas",
    type: "hidden",
    defaultValue: true,
    versionAdded: "1.25.0"
  },
  {
    id: "Comfy.Minimap.NodeColors",
    name: "Display node with its original color on minimap",
    type: "hidden",
    defaultValue: false,
    versionAdded: "1.26.0"
  },
  {
    id: "Comfy.Minimap.ShowLinks",
    name: "Display links on minimap",
    type: "hidden",
    defaultValue: true,
    versionAdded: "1.26.0"
  },
  {
    id: "Comfy.Minimap.ShowGroups",
    name: "Display node groups on minimap",
    type: "hidden",
    defaultValue: true,
    versionAdded: "1.26.0"
  },
  {
    id: "Comfy.Minimap.RenderBypassState",
    name: "Render bypass state on minimap",
    type: "hidden",
    defaultValue: true,
    versionAdded: "1.26.0"
  },
  {
    id: "Comfy.Minimap.RenderErrorState",
    name: "Render error state on minimap",
    type: "hidden",
    defaultValue: true,
    versionAdded: "1.26.0"
  },
  {
    id: "Comfy.Workflow.AutoSaveDelay",
    name: "Auto Save Delay (ms)",
    defaultValue: 1e3,
    type: "number",
    tooltip: 'Only applies if Auto Save is set to "after delay".',
    versionAdded: "1.16.0"
  },
  {
    id: "Comfy.Workflow.AutoSave",
    name: "Auto Save",
    type: "combo",
    options: ["off", "after delay"],
    // Room for other options like on focus change, tab change, window change
    defaultValue: "off",
    // Popular requst by users (https://github.com/Comfy-Org/ComfyUI_frontend/issues/1584#issuecomment-2536610154)
    versionAdded: "1.16.0"
  },
  {
    id: "Comfy.Workflow.Persist",
    name: "Persist workflow state and restore on page (re)load",
    type: "boolean",
    defaultValue: true,
    versionAdded: "1.16.1"
  },
  {
    id: "LiteGraph.Node.DefaultPadding",
    name: "Always shrink new nodes",
    tooltip: "Resize nodes to the smallest possible size when created. When disabled, a newly added node will be widened slightly to show widget values.",
    type: "boolean",
    defaultValue: false,
    versionAdded: "1.18.0"
  },
  {
    id: "Comfy.Canvas.BackgroundImage",
    category: ["Appearance", "Canvas", "Background"],
    name: "Canvas background image",
    type: "backgroundImage",
    tooltip: 'Image URL for the canvas background. You can right-click an image in the outputs panel and select "Set as Background" to use it, or upload your own image using the upload button.',
    defaultValue: "",
    versionAdded: "1.20.4",
    versionModified: "1.20.5"
  },
  // Release data stored in settings
  {
    id: "Comfy.Release.Version",
    name: "Last seen release version",
    type: "hidden",
    defaultValue: ""
  },
  {
    id: "Comfy.Release.Status",
    name: "Release status",
    type: "hidden",
    defaultValue: "skipped"
  },
  {
    id: "Comfy.Release.Timestamp",
    name: "Release seen timestamp",
    type: "hidden",
    defaultValue: 0
  },
  /**
   * Vue Node System Settings
   */
  {
    id: "Comfy.VueNodes.Enabled",
    name: "Enable Vue node rendering (hidden)",
    type: "hidden",
    tooltip: "Render nodes as Vue components instead of canvas. Hidden; toggle via Experimental keybinding.",
    defaultValue: false,
    experimental: true,
    versionAdded: "1.27.1"
  }
];
function useLayoutSync() {
  let unsubscribe = null;
  function startSync(canvas) {
    if (!canvas?.graph) return;
    unsubscribe = layoutStore.onChange((change) => {
      for (const nodeId of change.nodeIds) {
        const layout = layoutStore.getNodeLayoutRef(nodeId).value;
        if (!layout) continue;
        const liteNode = canvas.graph.getNodeById(parseInt(nodeId));
        if (!liteNode) continue;
        if (liteNode.pos[0] !== layout.position.x || liteNode.pos[1] !== layout.position.y) {
          liteNode.pos[0] = layout.position.x;
          liteNode.pos[1] = layout.position.y;
        }
        if (liteNode.size[0] !== layout.size.width || liteNode.size[1] !== layout.size.height) {
          liteNode.size[0] = layout.size.width;
          liteNode.size[1] = layout.size.height;
        }
      }
      canvas.setDirty(true, true);
    });
  }
  __name(startSync, "startSync");
  function stopSync() {
    if (unsubscribe) {
      unsubscribe();
      unsubscribe = null;
    }
  }
  __name(stopSync, "stopSync");
  onUnmounted(() => {
    stopSync();
  });
  return {
    startSync,
    stopSync
  };
}
__name(useLayoutSync, "useLayoutSync");
const logger = log.getLogger("useLinkLayoutSync");
function useLinkLayoutSync() {
  let canvas = null;
  let graph = null;
  let offscreenCtx = null;
  let adapter = null;
  let unsubscribeLayoutChange = null;
  let restoreHandlers = null;
  function buildLinkRenderContext() {
    if (!canvas) {
      throw new Error("Canvas not initialized");
    }
    return {
      // Canvas settings
      renderMode: canvas.links_render_mode,
      connectionWidth: canvas.connections_width,
      renderBorder: canvas.render_connections_border,
      lowQuality: canvas.low_quality,
      highQualityRender: canvas.highquality_render,
      scale: canvas.ds.scale,
      linkMarkerShape: canvas.linkMarkerShape,
      renderConnectionArrows: canvas.render_connection_arrows,
      // State
      highlightedLinks: new Set(Object.keys(canvas.highlighted_links)),
      // Colors
      defaultLinkColor: canvas.default_link_color,
      linkTypeColors: canvas.constructor.link_type_colors || {},
      // Pattern for disabled links
      disabledPattern: canvas._pattern
    };
  }
  __name(buildLinkRenderContext, "buildLinkRenderContext");
  function recomputeLinkById(linkId) {
    if (!graph || !adapter || !offscreenCtx || !canvas) return;
    const link = graph.links.get(linkId);
    if (!link || link.id === -1) return;
    const sourceNode = graph.getNodeById(link.origin_id);
    const targetNode = graph.getNodeById(link.target_id);
    if (!sourceNode || !targetNode) return;
    const sourceSlot = sourceNode.outputs?.[link.origin_slot];
    const targetSlot = targetNode.inputs?.[link.target_slot];
    if (!sourceSlot || !targetSlot) return;
    const startPos = getSlotPosition(sourceNode, link.origin_slot, false);
    const endPos = getSlotPosition(targetNode, link.target_slot, true);
    const startDir = sourceSlot.dir || LinkDirection.RIGHT;
    const endDir = targetSlot.dir || LinkDirection.LEFT;
    const reroutes = LLink.getReroutes(graph, link);
    const context = buildLinkRenderContext();
    if (reroutes.length > 0) {
      let segmentStartPos = startPos;
      let segmentStartDir = startDir;
      for (let i = 0; i < reroutes.length; i++) {
        const reroute = reroutes[i];
        reroute.calculateAngle(Date.now(), graph, [
          segmentStartPos[0],
          segmentStartPos[1]
        ]);
        const distance = Math.sqrt(
          (reroute.pos[0] - segmentStartPos[0]) ** 2 + (reroute.pos[1] - segmentStartPos[1]) ** 2
        );
        const dist = Math.min(Reroute.maxSplineOffset, distance * 0.25);
        const isFloatingInputChain = !sourceNode && targetNode;
        const startControl = isFloatingInputChain ? [0, 0] : [dist * reroute.cos, dist * reroute.sin];
        adapter.renderLinkDirect(
          offscreenCtx,
          segmentStartPos,
          reroute.pos,
          link,
          true,
          // skip_border
          0,
          // flow
          null,
          // color
          segmentStartDir,
          LinkDirection.CENTER,
          context,
          {
            startControl,
            endControl: reroute.controlPoint,
            reroute,
            disabled: false
          }
        );
        segmentStartPos = reroute.pos;
        segmentStartDir = LinkDirection.CENTER;
      }
      const lastReroute = reroutes[reroutes.length - 1];
      const finalDistance = Math.sqrt(
        (endPos[0] - lastReroute.pos[0]) ** 2 + (endPos[1] - lastReroute.pos[1]) ** 2
      );
      const finalDist = Math.min(Reroute.maxSplineOffset, finalDistance * 0.25);
      const finalStartControl = [
        finalDist * lastReroute.cos,
        finalDist * lastReroute.sin
      ];
      adapter.renderLinkDirect(
        offscreenCtx,
        lastReroute.pos,
        endPos,
        link,
        true,
        // skip_border
        0,
        // flow
        null,
        // color
        LinkDirection.CENTER,
        endDir,
        context,
        {
          startControl: finalStartControl,
          disabled: false
        }
      );
    } else {
      adapter.renderLinkDirect(
        offscreenCtx,
        startPos,
        endPos,
        link,
        true,
        // skip_border
        0,
        // flow
        null,
        // color
        startDir,
        endDir,
        context,
        {
          disabled: false
        }
      );
    }
  }
  __name(recomputeLinkById, "recomputeLinkById");
  function recomputeLinksForNode(nodeId) {
    if (!graph) return;
    const node = graph.getNodeById(nodeId);
    if (!node) return;
    const linkIds = /* @__PURE__ */ new Set();
    if (node.outputs) {
      for (const output of node.outputs) {
        if (output.links) {
          for (const linkId of output.links) {
            linkIds.add(linkId);
          }
        }
      }
    }
    if (node.inputs) {
      for (const input of node.inputs) {
        if (input.link !== null && input.link !== void 0) {
          linkIds.add(input.link);
        }
      }
    }
    for (const linkId of linkIds) {
      recomputeLinkById(linkId);
    }
  }
  __name(recomputeLinksForNode, "recomputeLinksForNode");
  function recomputeLinksForReroute(rerouteId) {
    if (!graph) return;
    const reroute = graph.reroutes.get(rerouteId);
    if (!reroute) return;
    for (const linkId of reroute.linkIds) {
      recomputeLinkById(linkId);
    }
  }
  __name(recomputeLinksForReroute, "recomputeLinksForReroute");
  function start(canvasInstance) {
    canvas = canvasInstance;
    graph = canvas.graph;
    if (!graph) return;
    const offscreenCanvas = document.createElement("canvas");
    offscreenCtx = offscreenCanvas.getContext("2d");
    if (!offscreenCtx) {
      logger.error("Failed to create offscreen canvas context");
      return;
    }
    adapter = new LitegraphLinkAdapter(graph);
    adapter.enableLayoutStoreWrites = true;
    for (const link of graph._links.values()) {
      if (link.id !== -1) {
        recomputeLinkById(link.id);
      }
    }
    unsubscribeLayoutChange = layoutStore.onChange((change) => {
      switch (change.operation.type) {
        case "moveNode":
        case "resizeNode":
          recomputeLinksForNode(parseInt(change.operation.nodeId));
          break;
        case "createLink":
          recomputeLinkById(change.operation.linkId);
          break;
        case "deleteLink":
          break;
        case "createReroute":
        case "deleteReroute":
          if ("linkIds" in change.operation) {
            for (const linkId of change.operation.linkIds) {
              recomputeLinkById(linkId);
            }
          }
          break;
        case "moveReroute":
          recomputeLinksForReroute(change.operation.rerouteId);
          break;
      }
    });
    const origTrigger = graph.onTrigger;
    graph.onTrigger = (action, param) => {
      if (action === "node:property:changed" && param?.property === "flags.collapsed") {
        const nodeId = parseInt(String(param.nodeId));
        if (!isNaN(nodeId)) {
          recomputeLinksForNode(nodeId);
        }
      }
      if (origTrigger) {
        origTrigger.call(graph, action, param);
      }
    };
    restoreHandlers = /* @__PURE__ */ __name(() => {
      if (graph) {
        graph.onTrigger = origTrigger || void 0;
      }
    }, "restoreHandlers");
  }
  __name(start, "start");
  function stop() {
    if (unsubscribeLayoutChange) {
      unsubscribeLayoutChange();
      unsubscribeLayoutChange = null;
    }
    if (restoreHandlers) {
      restoreHandlers();
      restoreHandlers = null;
    }
    canvas = null;
    graph = null;
    offscreenCtx = null;
    adapter = null;
  }
  __name(stop, "stop");
  onUnmounted(() => {
    stop();
  });
  return {
    start,
    stop
  };
}
__name(useLinkLayoutSync, "useLinkLayoutSync");
function registerSlotLayout(nodeId, slotIndex, isInput, position) {
  const slotKey = getSlotKey(nodeId, slotIndex, isInput);
  const slotSize = LiteGraph.NODE_SLOT_HEIGHT;
  const halfSize = slotSize / 2;
  const slotLayout = {
    nodeId,
    index: slotIndex,
    type: isInput ? "input" : "output",
    position: { x: position[0], y: position[1] },
    bounds: {
      x: position[0] - halfSize,
      y: position[1] - halfSize,
      width: slotSize,
      height: slotSize
    }
  };
  layoutStore.updateSlotLayout(slotKey, slotLayout);
}
__name(registerSlotLayout, "registerSlotLayout");
function registerNodeSlots(nodeId, context) {
  context.inputs.forEach((_, index) => {
    const position = calculateInputSlotPos(context, index);
    registerSlotLayout(nodeId, index, true, position);
  });
  context.outputs.forEach((_, index) => {
    const position = calculateOutputSlotPos(context, index);
    registerSlotLayout(nodeId, index, false, position);
  });
}
__name(registerNodeSlots, "registerNodeSlots");
function computeAndRegisterSlots(node) {
  const nodeId = String(node.id);
  const nodeLayout = layoutStore.getNodeLayoutRef(nodeId).value;
  const nodeX = nodeLayout?.position.x ?? node.pos[0];
  const nodeY = nodeLayout?.position.y ?? node.pos[1];
  const nodeWidth = nodeLayout?.size.width ?? node.size[0];
  const nodeHeight = nodeLayout?.size.height ?? node.size[1];
  node._setConcreteSlots();
  const collapsed = node.flags.collapsed ?? false;
  if (!collapsed) {
    node.arrange();
  }
  const context = {
    nodeX,
    nodeY,
    nodeWidth,
    nodeHeight,
    collapsed,
    collapsedWidth: node._collapsed_width,
    slotStartY: node.constructor.slot_start_y,
    inputs: node.inputs,
    outputs: node.outputs,
    widgets: node.widgets
  };
  registerNodeSlots(nodeId, context);
}
__name(computeAndRegisterSlots, "computeAndRegisterSlots");
function useSlotLayoutSync() {
  let unsubscribeLayoutChange = null;
  let restoreHandlers = null;
  function start(canvas) {
    if (LiteGraph.vueNodesMode) {
      return;
    }
    const graph = canvas?.graph;
    if (!graph) return;
    for (const node of graph._nodes) {
      computeAndRegisterSlots(node);
    }
    unsubscribeLayoutChange = layoutStore.onChange((change) => {
      for (const nodeId of change.nodeIds) {
        const node = graph.getNodeById(parseInt(nodeId));
        if (node) {
          computeAndRegisterSlots(node);
        }
      }
    });
    const origNodeAdded = graph.onNodeAdded;
    const origNodeRemoved = graph.onNodeRemoved;
    const origTrigger = graph.onTrigger;
    const origAfterChange = graph.onAfterChange;
    graph.onNodeAdded = (node) => {
      computeAndRegisterSlots(node);
      if (origNodeAdded) {
        origNodeAdded.call(graph, node);
      }
    };
    graph.onNodeRemoved = (node) => {
      layoutStore.deleteNodeSlotLayouts(String(node.id));
      if (origNodeRemoved) {
        origNodeRemoved.call(graph, node);
      }
    };
    graph.onTrigger = (action, param) => {
      if (action === "node:property:changed" && param?.property === "flags.collapsed") {
        const node = graph.getNodeById(parseInt(String(param.nodeId)));
        if (node) {
          computeAndRegisterSlots(node);
        }
      }
      if (origTrigger) {
        origTrigger.call(graph, action, param);
      }
    };
    graph.onAfterChange = (graph2, node) => {
      if (node && node.id) {
        computeAndRegisterSlots(node);
      }
      if (origAfterChange) {
        origAfterChange.call(graph2, graph2, node);
      }
    };
    restoreHandlers = /* @__PURE__ */ __name(() => {
      graph.onNodeAdded = origNodeAdded || void 0;
      graph.onNodeRemoved = origNodeRemoved || void 0;
      graph.onTrigger = origTrigger || void 0;
      graph.onAfterChange = origAfterChange || void 0;
    }, "restoreHandlers");
  }
  __name(start, "start");
  function stop() {
    if (unsubscribeLayoutChange) {
      unsubscribeLayoutChange();
      unsubscribeLayoutChange = null;
    }
    if (restoreHandlers) {
      restoreHandlers();
      restoreHandlers = null;
    }
  }
  __name(stop, "stop");
  onUnmounted(() => {
    stop();
  });
  return {
    start,
    stop
  };
}
__name(useSlotLayoutSync, "useSlotLayoutSync");
function useNodeLayout(nodeId) {
  const store = layoutStore;
  const mutations = useLayoutMutations();
  const transformState = inject("transformState");
  const layoutRef = store.getNodeLayoutRef(nodeId);
  const position = computed(() => {
    const layout = layoutRef.value;
    const pos = layout?.position ?? { x: 0, y: 0 };
    return pos;
  });
  const size = computed(
    () => layoutRef.value?.size ?? { width: 200, height: 100 }
  );
  const bounds = computed(
    () => layoutRef.value?.bounds ?? {
      x: position.value.x,
      y: position.value.y,
      width: size.value.width,
      height: size.value.height
    }
  );
  const isVisible = computed(() => layoutRef.value?.visible ?? true);
  const zIndex = computed(() => layoutRef.value?.zIndex ?? 0);
  let isDragging = false;
  let dragStartPos = null;
  let dragStartMouse = null;
  function startDrag(event) {
    if (!layoutRef.value) return;
    isDragging = true;
    dragStartPos = { ...position.value };
    dragStartMouse = { x: event.clientX, y: event.clientY };
    mutations.setSource(LayoutSource.Vue);
    const target = event.target;
    target.setPointerCapture(event.pointerId);
  }
  __name(startDrag, "startDrag");
  const handleDrag = /* @__PURE__ */ __name((event) => {
    if (!isDragging || !dragStartPos || !dragStartMouse || !transformState) {
      return;
    }
    const mouseDelta = {
      x: event.clientX - dragStartMouse.x,
      y: event.clientY - dragStartMouse.y
    };
    const canvasOrigin = transformState.screenToCanvas({ x: 0, y: 0 });
    const canvasWithDelta = transformState.screenToCanvas(mouseDelta);
    const canvasDelta = {
      x: canvasWithDelta.x - canvasOrigin.x,
      y: canvasWithDelta.y - canvasOrigin.y
    };
    const newPosition = {
      x: dragStartPos.x + canvasDelta.x,
      y: dragStartPos.y + canvasDelta.y
    };
    mutations.moveNode(nodeId, newPosition);
  }, "handleDrag");
  function endDrag(event) {
    if (!isDragging) return;
    isDragging = false;
    dragStartPos = null;
    dragStartMouse = null;
    const target = event.target;
    target.releasePointerCapture(event.pointerId);
  }
  __name(endDrag, "endDrag");
  function moveTo(position2) {
    mutations.setSource(LayoutSource.Vue);
    mutations.moveNode(nodeId, position2);
  }
  __name(moveTo, "moveTo");
  function resize(newSize) {
    mutations.setSource(LayoutSource.Vue);
    mutations.resizeNode(nodeId, newSize);
  }
  __name(resize, "resize");
  return {
    // Reactive state (via customRef)
    layoutRef,
    position,
    size,
    bounds,
    isVisible,
    zIndex,
    // Mutations
    moveTo,
    resize,
    // Drag handlers
    startDrag,
    handleDrag,
    endDrag,
    // Computed styles for Vue templates
    nodeStyle: computed(() => ({
      position: "absolute",
      left: `${position.value.x}px`,
      top: `${position.value.y}px`,
      width: `${size.value.width}px`,
      height: `${size.value.height}px`,
      zIndex: zIndex.value,
      cursor: isDragging ? "grabbing" : "grab"
    }))
  };
}
__name(useNodeLayout, "useNodeLayout");
var LODLevel = /* @__PURE__ */ ((LODLevel2) => {
  LODLevel2["MINIMAL"] = "minimal";
  LODLevel2["REDUCED"] = "reduced";
  LODLevel2["FULL"] = "full";
  return LODLevel2;
})(LODLevel || {});
const LOD_CONFIGS = {
  [
    "full"
    /* FULL */
  ]: {
    renderWidgets: true,
    renderSlots: true,
    renderContent: true,
    renderSlotLabels: true,
    renderWidgetLabels: true,
    cssClass: "lg-node--lod-full"
  },
  [
    "reduced"
    /* REDUCED */
  ]: {
    renderWidgets: true,
    renderSlots: true,
    renderContent: false,
    renderSlotLabels: false,
    renderWidgetLabels: false,
    cssClass: "lg-node--lod-reduced"
  },
  [
    "minimal"
    /* MINIMAL */
  ]: {
    renderWidgets: false,
    renderSlots: false,
    renderContent: false,
    renderSlotLabels: false,
    renderWidgetLabels: false,
    cssClass: "lg-node--lod-minimal"
  }
};
function useLOD(zoomRef) {
  const lodScore = computed(() => {
    const zoom = zoomRef.value;
    return Math.max(0, Math.min(1, zoom));
  });
  const lodLevel = computed(() => {
    const zoom = zoomRef.value;
    if (zoom > 0.8) return "full";
    if (zoom > 0.4) return "reduced";
    return "minimal";
  });
  const lodConfig = computed(() => LOD_CONFIGS[lodLevel.value]);
  const shouldRenderWidgets = computed(() => lodConfig.value.renderWidgets);
  const shouldRenderSlots = computed(() => lodConfig.value.renderSlots);
  const shouldRenderContent = computed(() => lodConfig.value.renderContent);
  const shouldRenderSlotLabels = computed(
    () => lodConfig.value.renderSlotLabels
  );
  const shouldRenderWidgetLabels = computed(
    () => lodConfig.value.renderWidgetLabels
  );
  const lodCssClass = computed(() => lodConfig.value.cssClass);
  const getEssentialWidgets = /* @__PURE__ */ __name((widgets2) => {
    if (lodLevel.value === "full") return widgets2;
    if (lodLevel.value === "minimal") return [];
    return widgets2.filter((widget) => {
      const type = widget?.type?.toLowerCase();
      return [
        "combo",
        "select",
        "toggle",
        "boolean",
        "slider",
        "number"
      ].includes(type);
    });
  }, "getEssentialWidgets");
  const lodMetrics = computed(() => ({
    level: lodLevel.value,
    zoom: zoomRef.value,
    widgetCount: shouldRenderWidgets.value ? "full" : "none",
    slotCount: shouldRenderSlots.value ? "full" : "none"
  }));
  return {
    // Core LOD state
    lodLevel: readonly(lodLevel),
    lodConfig: readonly(lodConfig),
    lodScore: readonly(lodScore),
    // Rendering decisions
    shouldRenderWidgets,
    shouldRenderSlots,
    shouldRenderContent,
    shouldRenderSlotLabels,
    shouldRenderWidgetLabels,
    // Styling
    lodCssClass,
    // Utilities
    getEssentialWidgets,
    lodMetrics
  };
}
__name(useLOD, "useLOD");
const LOD_THRESHOLDS = {
  FULL_THRESHOLD: 0.8,
  REDUCED_THRESHOLD: 0.4,
  MINIMAL_THRESHOLD: 0
};
function supportsFeatureAtZoom(zoom, feature) {
  const level = zoom > 0.8 ? "full" : zoom > 0.4 ? "reduced" : "minimal";
  return LOD_CONFIGS[level][feature];
}
__name(supportsFeatureAtZoom, "supportsFeatureAtZoom");
function r(e) {
  var t2, f, n = "";
  if ("string" == typeof e || "number" == typeof e) n += e;
  else if ("object" == typeof e) if (Array.isArray(e)) {
    var o = e.length;
    for (t2 = 0; t2 < o; t2++) e[t2] && (f = r(e[t2])) && (n && (n += " "), n += f);
  } else for (f in e) e[f] && (n && (n += " "), n += f);
  return n;
}
__name(r, "r");
function clsx() {
  for (var e, t2, f = 0, n = "", o = arguments.length; f < o; f++) (e = arguments[f]) && (t2 = r(e)) && (n && (n += " "), n += t2);
  return n;
}
__name(clsx, "clsx");
const CLASS_PART_SEPARATOR = "-";
const createClassGroupUtils = /* @__PURE__ */ __name((config2) => {
  const classMap = createClassMap(config2);
  const {
    conflictingClassGroups,
    conflictingClassGroupModifiers
  } = config2;
  const getClassGroupId = /* @__PURE__ */ __name((className) => {
    const classParts = className.split(CLASS_PART_SEPARATOR);
    if (classParts[0] === "" && classParts.length !== 1) {
      classParts.shift();
    }
    return getGroupRecursive(classParts, classMap) || getGroupIdForArbitraryProperty(className);
  }, "getClassGroupId");
  const getConflictingClassGroupIds = /* @__PURE__ */ __name((classGroupId, hasPostfixModifier) => {
    const conflicts = conflictingClassGroups[classGroupId] || [];
    if (hasPostfixModifier && conflictingClassGroupModifiers[classGroupId]) {
      return [...conflicts, ...conflictingClassGroupModifiers[classGroupId]];
    }
    return conflicts;
  }, "getConflictingClassGroupIds");
  return {
    getClassGroupId,
    getConflictingClassGroupIds
  };
}, "createClassGroupUtils");
const getGroupRecursive = /* @__PURE__ */ __name((classParts, classPartObject) => {
  if (classParts.length === 0) {
    return classPartObject.classGroupId;
  }
  const currentClassPart = classParts[0];
  const nextClassPartObject = classPartObject.nextPart.get(currentClassPart);
  const classGroupFromNextClassPart = nextClassPartObject ? getGroupRecursive(classParts.slice(1), nextClassPartObject) : void 0;
  if (classGroupFromNextClassPart) {
    return classGroupFromNextClassPart;
  }
  if (classPartObject.validators.length === 0) {
    return void 0;
  }
  const classRest = classParts.join(CLASS_PART_SEPARATOR);
  return classPartObject.validators.find(({
    validator
  }) => validator(classRest))?.classGroupId;
}, "getGroupRecursive");
const arbitraryPropertyRegex = /^\[(.+)\]$/;
const getGroupIdForArbitraryProperty = /* @__PURE__ */ __name((className) => {
  if (arbitraryPropertyRegex.test(className)) {
    const arbitraryPropertyClassName = arbitraryPropertyRegex.exec(className)[1];
    const property = arbitraryPropertyClassName?.substring(0, arbitraryPropertyClassName.indexOf(":"));
    if (property) {
      return "arbitrary.." + property;
    }
  }
}, "getGroupIdForArbitraryProperty");
const createClassMap = /* @__PURE__ */ __name((config2) => {
  const {
    theme,
    classGroups
  } = config2;
  const classMap = {
    nextPart: /* @__PURE__ */ new Map(),
    validators: []
  };
  for (const classGroupId in classGroups) {
    processClassesRecursively(classGroups[classGroupId], classMap, classGroupId, theme);
  }
  return classMap;
}, "createClassMap");
const processClassesRecursively = /* @__PURE__ */ __name((classGroup, classPartObject, classGroupId, theme) => {
  classGroup.forEach((classDefinition) => {
    if (typeof classDefinition === "string") {
      const classPartObjectToEdit = classDefinition === "" ? classPartObject : getPart(classPartObject, classDefinition);
      classPartObjectToEdit.classGroupId = classGroupId;
      return;
    }
    if (typeof classDefinition === "function") {
      if (isThemeGetter(classDefinition)) {
        processClassesRecursively(classDefinition(theme), classPartObject, classGroupId, theme);
        return;
      }
      classPartObject.validators.push({
        validator: classDefinition,
        classGroupId
      });
      return;
    }
    Object.entries(classDefinition).forEach(([key, classGroup2]) => {
      processClassesRecursively(classGroup2, getPart(classPartObject, key), classGroupId, theme);
    });
  });
}, "processClassesRecursively");
const getPart = /* @__PURE__ */ __name((classPartObject, path) => {
  let currentClassPartObject = classPartObject;
  path.split(CLASS_PART_SEPARATOR).forEach((pathPart) => {
    if (!currentClassPartObject.nextPart.has(pathPart)) {
      currentClassPartObject.nextPart.set(pathPart, {
        nextPart: /* @__PURE__ */ new Map(),
        validators: []
      });
    }
    currentClassPartObject = currentClassPartObject.nextPart.get(pathPart);
  });
  return currentClassPartObject;
}, "getPart");
const isThemeGetter = /* @__PURE__ */ __name((func) => func.isThemeGetter, "isThemeGetter");
const createLruCache = /* @__PURE__ */ __name((maxCacheSize) => {
  if (maxCacheSize < 1) {
    return {
      get: /* @__PURE__ */ __name(() => void 0, "get"),
      set: /* @__PURE__ */ __name(() => {
      }, "set")
    };
  }
  let cacheSize = 0;
  let cache = /* @__PURE__ */ new Map();
  let previousCache = /* @__PURE__ */ new Map();
  const update = /* @__PURE__ */ __name((key, value) => {
    cache.set(key, value);
    cacheSize++;
    if (cacheSize > maxCacheSize) {
      cacheSize = 0;
      previousCache = cache;
      cache = /* @__PURE__ */ new Map();
    }
  }, "update");
  return {
    get(key) {
      let value = cache.get(key);
      if (value !== void 0) {
        return value;
      }
      if ((value = previousCache.get(key)) !== void 0) {
        update(key, value);
        return value;
      }
    },
    set(key, value) {
      if (cache.has(key)) {
        cache.set(key, value);
      } else {
        update(key, value);
      }
    }
  };
}, "createLruCache");
const IMPORTANT_MODIFIER = "!";
const MODIFIER_SEPARATOR = ":";
const MODIFIER_SEPARATOR_LENGTH = MODIFIER_SEPARATOR.length;
const createParseClassName = /* @__PURE__ */ __name((config2) => {
  const {
    prefix,
    experimentalParseClassName
  } = config2;
  let parseClassName = /* @__PURE__ */ __name((className) => {
    const modifiers = [];
    let bracketDepth = 0;
    let parenDepth = 0;
    let modifierStart = 0;
    let postfixModifierPosition;
    for (let index = 0; index < className.length; index++) {
      let currentCharacter = className[index];
      if (bracketDepth === 0 && parenDepth === 0) {
        if (currentCharacter === MODIFIER_SEPARATOR) {
          modifiers.push(className.slice(modifierStart, index));
          modifierStart = index + MODIFIER_SEPARATOR_LENGTH;
          continue;
        }
        if (currentCharacter === "/") {
          postfixModifierPosition = index;
          continue;
        }
      }
      if (currentCharacter === "[") {
        bracketDepth++;
      } else if (currentCharacter === "]") {
        bracketDepth--;
      } else if (currentCharacter === "(") {
        parenDepth++;
      } else if (currentCharacter === ")") {
        parenDepth--;
      }
    }
    const baseClassNameWithImportantModifier = modifiers.length === 0 ? className : className.substring(modifierStart);
    const baseClassName = stripImportantModifier(baseClassNameWithImportantModifier);
    const hasImportantModifier = baseClassName !== baseClassNameWithImportantModifier;
    const maybePostfixModifierPosition = postfixModifierPosition && postfixModifierPosition > modifierStart ? postfixModifierPosition - modifierStart : void 0;
    return {
      modifiers,
      hasImportantModifier,
      baseClassName,
      maybePostfixModifierPosition
    };
  }, "parseClassName");
  if (prefix) {
    const fullPrefix = prefix + MODIFIER_SEPARATOR;
    const parseClassNameOriginal = parseClassName;
    parseClassName = /* @__PURE__ */ __name((className) => className.startsWith(fullPrefix) ? parseClassNameOriginal(className.substring(fullPrefix.length)) : {
      isExternal: true,
      modifiers: [],
      hasImportantModifier: false,
      baseClassName: className,
      maybePostfixModifierPosition: void 0
    }, "parseClassName");
  }
  if (experimentalParseClassName) {
    const parseClassNameOriginal = parseClassName;
    parseClassName = /* @__PURE__ */ __name((className) => experimentalParseClassName({
      className,
      parseClassName: parseClassNameOriginal
    }), "parseClassName");
  }
  return parseClassName;
}, "createParseClassName");
const stripImportantModifier = /* @__PURE__ */ __name((baseClassName) => {
  if (baseClassName.endsWith(IMPORTANT_MODIFIER)) {
    return baseClassName.substring(0, baseClassName.length - 1);
  }
  if (baseClassName.startsWith(IMPORTANT_MODIFIER)) {
    return baseClassName.substring(1);
  }
  return baseClassName;
}, "stripImportantModifier");
const createSortModifiers = /* @__PURE__ */ __name((config2) => {
  const orderSensitiveModifiers = Object.fromEntries(config2.orderSensitiveModifiers.map((modifier) => [modifier, true]));
  const sortModifiers = /* @__PURE__ */ __name((modifiers) => {
    if (modifiers.length <= 1) {
      return modifiers;
    }
    const sortedModifiers = [];
    let unsortedModifiers = [];
    modifiers.forEach((modifier) => {
      const isPositionSensitive = modifier[0] === "[" || orderSensitiveModifiers[modifier];
      if (isPositionSensitive) {
        sortedModifiers.push(...unsortedModifiers.sort(), modifier);
        unsortedModifiers = [];
      } else {
        unsortedModifiers.push(modifier);
      }
    });
    sortedModifiers.push(...unsortedModifiers.sort());
    return sortedModifiers;
  }, "sortModifiers");
  return sortModifiers;
}, "createSortModifiers");
const createConfigUtils = /* @__PURE__ */ __name((config2) => ({
  cache: createLruCache(config2.cacheSize),
  parseClassName: createParseClassName(config2),
  sortModifiers: createSortModifiers(config2),
  ...createClassGroupUtils(config2)
}), "createConfigUtils");
const SPLIT_CLASSES_REGEX = /\s+/;
const mergeClassList = /* @__PURE__ */ __name((classList, configUtils) => {
  const {
    parseClassName,
    getClassGroupId,
    getConflictingClassGroupIds,
    sortModifiers
  } = configUtils;
  const classGroupsInConflict = [];
  const classNames = classList.trim().split(SPLIT_CLASSES_REGEX);
  let result = "";
  for (let index = classNames.length - 1; index >= 0; index -= 1) {
    const originalClassName = classNames[index];
    const {
      isExternal,
      modifiers,
      hasImportantModifier,
      baseClassName,
      maybePostfixModifierPosition
    } = parseClassName(originalClassName);
    if (isExternal) {
      result = originalClassName + (result.length > 0 ? " " + result : result);
      continue;
    }
    let hasPostfixModifier = !!maybePostfixModifierPosition;
    let classGroupId = getClassGroupId(hasPostfixModifier ? baseClassName.substring(0, maybePostfixModifierPosition) : baseClassName);
    if (!classGroupId) {
      if (!hasPostfixModifier) {
        result = originalClassName + (result.length > 0 ? " " + result : result);
        continue;
      }
      classGroupId = getClassGroupId(baseClassName);
      if (!classGroupId) {
        result = originalClassName + (result.length > 0 ? " " + result : result);
        continue;
      }
      hasPostfixModifier = false;
    }
    const variantModifier = sortModifiers(modifiers).join(":");
    const modifierId = hasImportantModifier ? variantModifier + IMPORTANT_MODIFIER : variantModifier;
    const classId = modifierId + classGroupId;
    if (classGroupsInConflict.includes(classId)) {
      continue;
    }
    classGroupsInConflict.push(classId);
    const conflictGroups = getConflictingClassGroupIds(classGroupId, hasPostfixModifier);
    for (let i = 0; i < conflictGroups.length; ++i) {
      const group = conflictGroups[i];
      classGroupsInConflict.push(modifierId + group);
    }
    result = originalClassName + (result.length > 0 ? " " + result : result);
  }
  return result;
}, "mergeClassList");
function twJoin() {
  let index = 0;
  let argument;
  let resolvedValue;
  let string = "";
  while (index < arguments.length) {
    if (argument = arguments[index++]) {
      if (resolvedValue = toValue(argument)) {
        string && (string += " ");
        string += resolvedValue;
      }
    }
  }
  return string;
}
__name(twJoin, "twJoin");
const toValue = /* @__PURE__ */ __name((mix) => {
  if (typeof mix === "string") {
    return mix;
  }
  let resolvedValue;
  let string = "";
  for (let k = 0; k < mix.length; k++) {
    if (mix[k]) {
      if (resolvedValue = toValue(mix[k])) {
        string && (string += " ");
        string += resolvedValue;
      }
    }
  }
  return string;
}, "toValue");
function createTailwindMerge(createConfigFirst, ...createConfigRest) {
  let configUtils;
  let cacheGet;
  let cacheSet;
  let functionToCall = initTailwindMerge;
  function initTailwindMerge(classList) {
    const config2 = createConfigRest.reduce((previousConfig, createConfigCurrent) => createConfigCurrent(previousConfig), createConfigFirst());
    configUtils = createConfigUtils(config2);
    cacheGet = configUtils.cache.get;
    cacheSet = configUtils.cache.set;
    functionToCall = tailwindMerge;
    return tailwindMerge(classList);
  }
  __name(initTailwindMerge, "initTailwindMerge");
  function tailwindMerge(classList) {
    const cachedResult = cacheGet(classList);
    if (cachedResult) {
      return cachedResult;
    }
    const result = mergeClassList(classList, configUtils);
    cacheSet(classList, result);
    return result;
  }
  __name(tailwindMerge, "tailwindMerge");
  return /* @__PURE__ */ __name(function callTailwindMerge() {
    return functionToCall(twJoin.apply(null, arguments));
  }, "callTailwindMerge");
}
__name(createTailwindMerge, "createTailwindMerge");
const fromTheme = /* @__PURE__ */ __name((key) => {
  const themeGetter = /* @__PURE__ */ __name((theme) => theme[key] || [], "themeGetter");
  themeGetter.isThemeGetter = true;
  return themeGetter;
}, "fromTheme");
const arbitraryValueRegex = /^\[(?:(\w[\w-]*):)?(.+)\]$/i;
const arbitraryVariableRegex = /^\((?:(\w[\w-]*):)?(.+)\)$/i;
const fractionRegex = /^\d+\/\d+$/;
const tshirtUnitRegex = /^(\d+(\.\d+)?)?(xs|sm|md|lg|xl)$/;
const lengthUnitRegex = /\d+(%|px|r?em|[sdl]?v([hwib]|min|max)|pt|pc|in|cm|mm|cap|ch|ex|r?lh|cq(w|h|i|b|min|max))|\b(calc|min|max|clamp)\(.+\)|^0$/;
const colorFunctionRegex = /^(rgba?|hsla?|hwb|(ok)?(lab|lch)|color-mix)\(.+\)$/;
const shadowRegex = /^(inset_)?-?((\d+)?\.?(\d+)[a-z]+|0)_-?((\d+)?\.?(\d+)[a-z]+|0)/;
const imageRegex = /^(url|image|image-set|cross-fade|element|(repeating-)?(linear|radial|conic)-gradient)\(.+\)$/;
const isFraction = /* @__PURE__ */ __name((value) => fractionRegex.test(value), "isFraction");
const isNumber = /* @__PURE__ */ __name((value) => !!value && !Number.isNaN(Number(value)), "isNumber");
const isInteger = /* @__PURE__ */ __name((value) => !!value && Number.isInteger(Number(value)), "isInteger");
const isPercent = /* @__PURE__ */ __name((value) => value.endsWith("%") && isNumber(value.slice(0, -1)), "isPercent");
const isTshirtSize = /* @__PURE__ */ __name((value) => tshirtUnitRegex.test(value), "isTshirtSize");
const isAny = /* @__PURE__ */ __name(() => true, "isAny");
const isLengthOnly = /* @__PURE__ */ __name((value) => (
  // `colorFunctionRegex` check is necessary because color functions can have percentages in them which which would be incorrectly classified as lengths.
  // For example, `hsl(0 0% 0%)` would be classified as a length without this check.
  // I could also use lookbehind assertion in `lengthUnitRegex` but that isn't supported widely enough.
  lengthUnitRegex.test(value) && !colorFunctionRegex.test(value)
), "isLengthOnly");
const isNever = /* @__PURE__ */ __name(() => false, "isNever");
const isShadow = /* @__PURE__ */ __name((value) => shadowRegex.test(value), "isShadow");
const isImage = /* @__PURE__ */ __name((value) => imageRegex.test(value), "isImage");
const isAnyNonArbitrary = /* @__PURE__ */ __name((value) => !isArbitraryValue(value) && !isArbitraryVariable(value), "isAnyNonArbitrary");
const isArbitrarySize = /* @__PURE__ */ __name((value) => getIsArbitraryValue(value, isLabelSize, isNever), "isArbitrarySize");
const isArbitraryValue = /* @__PURE__ */ __name((value) => arbitraryValueRegex.test(value), "isArbitraryValue");
const isArbitraryLength = /* @__PURE__ */ __name((value) => getIsArbitraryValue(value, isLabelLength, isLengthOnly), "isArbitraryLength");
const isArbitraryNumber = /* @__PURE__ */ __name((value) => getIsArbitraryValue(value, isLabelNumber, isNumber), "isArbitraryNumber");
const isArbitraryPosition = /* @__PURE__ */ __name((value) => getIsArbitraryValue(value, isLabelPosition, isNever), "isArbitraryPosition");
const isArbitraryImage = /* @__PURE__ */ __name((value) => getIsArbitraryValue(value, isLabelImage, isImage), "isArbitraryImage");
const isArbitraryShadow = /* @__PURE__ */ __name((value) => getIsArbitraryValue(value, isLabelShadow, isShadow), "isArbitraryShadow");
const isArbitraryVariable = /* @__PURE__ */ __name((value) => arbitraryVariableRegex.test(value), "isArbitraryVariable");
const isArbitraryVariableLength = /* @__PURE__ */ __name((value) => getIsArbitraryVariable(value, isLabelLength), "isArbitraryVariableLength");
const isArbitraryVariableFamilyName = /* @__PURE__ */ __name((value) => getIsArbitraryVariable(value, isLabelFamilyName), "isArbitraryVariableFamilyName");
const isArbitraryVariablePosition = /* @__PURE__ */ __name((value) => getIsArbitraryVariable(value, isLabelPosition), "isArbitraryVariablePosition");
const isArbitraryVariableSize = /* @__PURE__ */ __name((value) => getIsArbitraryVariable(value, isLabelSize), "isArbitraryVariableSize");
const isArbitraryVariableImage = /* @__PURE__ */ __name((value) => getIsArbitraryVariable(value, isLabelImage), "isArbitraryVariableImage");
const isArbitraryVariableShadow = /* @__PURE__ */ __name((value) => getIsArbitraryVariable(value, isLabelShadow, true), "isArbitraryVariableShadow");
const getIsArbitraryValue = /* @__PURE__ */ __name((value, testLabel, testValue) => {
  const result = arbitraryValueRegex.exec(value);
  if (result) {
    if (result[1]) {
      return testLabel(result[1]);
    }
    return testValue(result[2]);
  }
  return false;
}, "getIsArbitraryValue");
const getIsArbitraryVariable = /* @__PURE__ */ __name((value, testLabel, shouldMatchNoLabel = false) => {
  const result = arbitraryVariableRegex.exec(value);
  if (result) {
    if (result[1]) {
      return testLabel(result[1]);
    }
    return shouldMatchNoLabel;
  }
  return false;
}, "getIsArbitraryVariable");
const isLabelPosition = /* @__PURE__ */ __name((label) => label === "position" || label === "percentage", "isLabelPosition");
const isLabelImage = /* @__PURE__ */ __name((label) => label === "image" || label === "url", "isLabelImage");
const isLabelSize = /* @__PURE__ */ __name((label) => label === "length" || label === "size" || label === "bg-size", "isLabelSize");
const isLabelLength = /* @__PURE__ */ __name((label) => label === "length", "isLabelLength");
const isLabelNumber = /* @__PURE__ */ __name((label) => label === "number", "isLabelNumber");
const isLabelFamilyName = /* @__PURE__ */ __name((label) => label === "family-name", "isLabelFamilyName");
const isLabelShadow = /* @__PURE__ */ __name((label) => label === "shadow", "isLabelShadow");
const validators = /* @__PURE__ */ Object.defineProperty({
  __proto__: null,
  isAny,
  isAnyNonArbitrary,
  isArbitraryImage,
  isArbitraryLength,
  isArbitraryNumber,
  isArbitraryPosition,
  isArbitraryShadow,
  isArbitrarySize,
  isArbitraryValue,
  isArbitraryVariable,
  isArbitraryVariableFamilyName,
  isArbitraryVariableImage,
  isArbitraryVariableLength,
  isArbitraryVariablePosition,
  isArbitraryVariableShadow,
  isArbitraryVariableSize,
  isFraction,
  isInteger,
  isNumber,
  isPercent,
  isTshirtSize
}, Symbol.toStringTag, {
  value: "Module"
});
const getDefaultConfig = /* @__PURE__ */ __name(() => {
  const themeColor = fromTheme("color");
  const themeFont = fromTheme("font");
  const themeText = fromTheme("text");
  const themeFontWeight = fromTheme("font-weight");
  const themeTracking = fromTheme("tracking");
  const themeLeading = fromTheme("leading");
  const themeBreakpoint = fromTheme("breakpoint");
  const themeContainer = fromTheme("container");
  const themeSpacing = fromTheme("spacing");
  const themeRadius = fromTheme("radius");
  const themeShadow = fromTheme("shadow");
  const themeInsetShadow = fromTheme("inset-shadow");
  const themeTextShadow = fromTheme("text-shadow");
  const themeDropShadow = fromTheme("drop-shadow");
  const themeBlur = fromTheme("blur");
  const themePerspective = fromTheme("perspective");
  const themeAspect = fromTheme("aspect");
  const themeEase = fromTheme("ease");
  const themeAnimate = fromTheme("animate");
  const scaleBreak = /* @__PURE__ */ __name(() => ["auto", "avoid", "all", "avoid-page", "page", "left", "right", "column"], "scaleBreak");
  const scalePosition = /* @__PURE__ */ __name(() => [
    "center",
    "top",
    "bottom",
    "left",
    "right",
    "top-left",
    // Deprecated since Tailwind CSS v4.1.0, see https://github.com/tailwindlabs/tailwindcss/pull/17378
    "left-top",
    "top-right",
    // Deprecated since Tailwind CSS v4.1.0, see https://github.com/tailwindlabs/tailwindcss/pull/17378
    "right-top",
    "bottom-right",
    // Deprecated since Tailwind CSS v4.1.0, see https://github.com/tailwindlabs/tailwindcss/pull/17378
    "right-bottom",
    "bottom-left",
    // Deprecated since Tailwind CSS v4.1.0, see https://github.com/tailwindlabs/tailwindcss/pull/17378
    "left-bottom"
  ], "scalePosition");
  const scalePositionWithArbitrary = /* @__PURE__ */ __name(() => [...scalePosition(), isArbitraryVariable, isArbitraryValue], "scalePositionWithArbitrary");
  const scaleOverflow = /* @__PURE__ */ __name(() => ["auto", "hidden", "clip", "visible", "scroll"], "scaleOverflow");
  const scaleOverscroll = /* @__PURE__ */ __name(() => ["auto", "contain", "none"], "scaleOverscroll");
  const scaleUnambiguousSpacing = /* @__PURE__ */ __name(() => [isArbitraryVariable, isArbitraryValue, themeSpacing], "scaleUnambiguousSpacing");
  const scaleInset = /* @__PURE__ */ __name(() => [isFraction, "full", "auto", ...scaleUnambiguousSpacing()], "scaleInset");
  const scaleGridTemplateColsRows = /* @__PURE__ */ __name(() => [isInteger, "none", "subgrid", isArbitraryVariable, isArbitraryValue], "scaleGridTemplateColsRows");
  const scaleGridColRowStartAndEnd = /* @__PURE__ */ __name(() => ["auto", {
    span: ["full", isInteger, isArbitraryVariable, isArbitraryValue]
  }, isInteger, isArbitraryVariable, isArbitraryValue], "scaleGridColRowStartAndEnd");
  const scaleGridColRowStartOrEnd = /* @__PURE__ */ __name(() => [isInteger, "auto", isArbitraryVariable, isArbitraryValue], "scaleGridColRowStartOrEnd");
  const scaleGridAutoColsRows = /* @__PURE__ */ __name(() => ["auto", "min", "max", "fr", isArbitraryVariable, isArbitraryValue], "scaleGridAutoColsRows");
  const scaleAlignPrimaryAxis = /* @__PURE__ */ __name(() => ["start", "end", "center", "between", "around", "evenly", "stretch", "baseline", "center-safe", "end-safe"], "scaleAlignPrimaryAxis");
  const scaleAlignSecondaryAxis = /* @__PURE__ */ __name(() => ["start", "end", "center", "stretch", "center-safe", "end-safe"], "scaleAlignSecondaryAxis");
  const scaleMargin = /* @__PURE__ */ __name(() => ["auto", ...scaleUnambiguousSpacing()], "scaleMargin");
  const scaleSizing = /* @__PURE__ */ __name(() => [isFraction, "auto", "full", "dvw", "dvh", "lvw", "lvh", "svw", "svh", "min", "max", "fit", ...scaleUnambiguousSpacing()], "scaleSizing");
  const scaleColor = /* @__PURE__ */ __name(() => [themeColor, isArbitraryVariable, isArbitraryValue], "scaleColor");
  const scaleBgPosition = /* @__PURE__ */ __name(() => [...scalePosition(), isArbitraryVariablePosition, isArbitraryPosition, {
    position: [isArbitraryVariable, isArbitraryValue]
  }], "scaleBgPosition");
  const scaleBgRepeat = /* @__PURE__ */ __name(() => ["no-repeat", {
    repeat: ["", "x", "y", "space", "round"]
  }], "scaleBgRepeat");
  const scaleBgSize = /* @__PURE__ */ __name(() => ["auto", "cover", "contain", isArbitraryVariableSize, isArbitrarySize, {
    size: [isArbitraryVariable, isArbitraryValue]
  }], "scaleBgSize");
  const scaleGradientStopPosition = /* @__PURE__ */ __name(() => [isPercent, isArbitraryVariableLength, isArbitraryLength], "scaleGradientStopPosition");
  const scaleRadius = /* @__PURE__ */ __name(() => [
    // Deprecated since Tailwind CSS v4.0.0
    "",
    "none",
    "full",
    themeRadius,
    isArbitraryVariable,
    isArbitraryValue
  ], "scaleRadius");
  const scaleBorderWidth = /* @__PURE__ */ __name(() => ["", isNumber, isArbitraryVariableLength, isArbitraryLength], "scaleBorderWidth");
  const scaleLineStyle = /* @__PURE__ */ __name(() => ["solid", "dashed", "dotted", "double"], "scaleLineStyle");
  const scaleBlendMode = /* @__PURE__ */ __name(() => ["normal", "multiply", "screen", "overlay", "darken", "lighten", "color-dodge", "color-burn", "hard-light", "soft-light", "difference", "exclusion", "hue", "saturation", "color", "luminosity"], "scaleBlendMode");
  const scaleMaskImagePosition = /* @__PURE__ */ __name(() => [isNumber, isPercent, isArbitraryVariablePosition, isArbitraryPosition], "scaleMaskImagePosition");
  const scaleBlur = /* @__PURE__ */ __name(() => [
    // Deprecated since Tailwind CSS v4.0.0
    "",
    "none",
    themeBlur,
    isArbitraryVariable,
    isArbitraryValue
  ], "scaleBlur");
  const scaleRotate = /* @__PURE__ */ __name(() => ["none", isNumber, isArbitraryVariable, isArbitraryValue], "scaleRotate");
  const scaleScale = /* @__PURE__ */ __name(() => ["none", isNumber, isArbitraryVariable, isArbitraryValue], "scaleScale");
  const scaleSkew = /* @__PURE__ */ __name(() => [isNumber, isArbitraryVariable, isArbitraryValue], "scaleSkew");
  const scaleTranslate = /* @__PURE__ */ __name(() => [isFraction, "full", ...scaleUnambiguousSpacing()], "scaleTranslate");
  return {
    cacheSize: 500,
    theme: {
      animate: ["spin", "ping", "pulse", "bounce"],
      aspect: ["video"],
      blur: [isTshirtSize],
      breakpoint: [isTshirtSize],
      color: [isAny],
      container: [isTshirtSize],
      "drop-shadow": [isTshirtSize],
      ease: ["in", "out", "in-out"],
      font: [isAnyNonArbitrary],
      "font-weight": ["thin", "extralight", "light", "normal", "medium", "semibold", "bold", "extrabold", "black"],
      "inset-shadow": [isTshirtSize],
      leading: ["none", "tight", "snug", "normal", "relaxed", "loose"],
      perspective: ["dramatic", "near", "normal", "midrange", "distant", "none"],
      radius: [isTshirtSize],
      shadow: [isTshirtSize],
      spacing: ["px", isNumber],
      text: [isTshirtSize],
      "text-shadow": [isTshirtSize],
      tracking: ["tighter", "tight", "normal", "wide", "wider", "widest"]
    },
    classGroups: {
      // --------------
      // --- Layout ---
      // --------------
      /**
       * Aspect Ratio
       * @see https://tailwindcss.com/docs/aspect-ratio
       */
      aspect: [{
        aspect: ["auto", "square", isFraction, isArbitraryValue, isArbitraryVariable, themeAspect]
      }],
      /**
       * Container
       * @see https://tailwindcss.com/docs/container
       * @deprecated since Tailwind CSS v4.0.0
       */
      container: ["container"],
      /**
       * Columns
       * @see https://tailwindcss.com/docs/columns
       */
      columns: [{
        columns: [isNumber, isArbitraryValue, isArbitraryVariable, themeContainer]
      }],
      /**
       * Break After
       * @see https://tailwindcss.com/docs/break-after
       */
      "break-after": [{
        "break-after": scaleBreak()
      }],
      /**
       * Break Before
       * @see https://tailwindcss.com/docs/break-before
       */
      "break-before": [{
        "break-before": scaleBreak()
      }],
      /**
       * Break Inside
       * @see https://tailwindcss.com/docs/break-inside
       */
      "break-inside": [{
        "break-inside": ["auto", "avoid", "avoid-page", "avoid-column"]
      }],
      /**
       * Box Decoration Break
       * @see https://tailwindcss.com/docs/box-decoration-break
       */
      "box-decoration": [{
        "box-decoration": ["slice", "clone"]
      }],
      /**
       * Box Sizing
       * @see https://tailwindcss.com/docs/box-sizing
       */
      box: [{
        box: ["border", "content"]
      }],
      /**
       * Display
       * @see https://tailwindcss.com/docs/display
       */
      display: ["block", "inline-block", "inline", "flex", "inline-flex", "table", "inline-table", "table-caption", "table-cell", "table-column", "table-column-group", "table-footer-group", "table-header-group", "table-row-group", "table-row", "flow-root", "grid", "inline-grid", "contents", "list-item", "hidden"],
      /**
       * Screen Reader Only
       * @see https://tailwindcss.com/docs/display#screen-reader-only
       */
      sr: ["sr-only", "not-sr-only"],
      /**
       * Floats
       * @see https://tailwindcss.com/docs/float
       */
      float: [{
        float: ["right", "left", "none", "start", "end"]
      }],
      /**
       * Clear
       * @see https://tailwindcss.com/docs/clear
       */
      clear: [{
        clear: ["left", "right", "both", "none", "start", "end"]
      }],
      /**
       * Isolation
       * @see https://tailwindcss.com/docs/isolation
       */
      isolation: ["isolate", "isolation-auto"],
      /**
       * Object Fit
       * @see https://tailwindcss.com/docs/object-fit
       */
      "object-fit": [{
        object: ["contain", "cover", "fill", "none", "scale-down"]
      }],
      /**
       * Object Position
       * @see https://tailwindcss.com/docs/object-position
       */
      "object-position": [{
        object: scalePositionWithArbitrary()
      }],
      /**
       * Overflow
       * @see https://tailwindcss.com/docs/overflow
       */
      overflow: [{
        overflow: scaleOverflow()
      }],
      /**
       * Overflow X
       * @see https://tailwindcss.com/docs/overflow
       */
      "overflow-x": [{
        "overflow-x": scaleOverflow()
      }],
      /**
       * Overflow Y
       * @see https://tailwindcss.com/docs/overflow
       */
      "overflow-y": [{
        "overflow-y": scaleOverflow()
      }],
      /**
       * Overscroll Behavior
       * @see https://tailwindcss.com/docs/overscroll-behavior
       */
      overscroll: [{
        overscroll: scaleOverscroll()
      }],
      /**
       * Overscroll Behavior X
       * @see https://tailwindcss.com/docs/overscroll-behavior
       */
      "overscroll-x": [{
        "overscroll-x": scaleOverscroll()
      }],
      /**
       * Overscroll Behavior Y
       * @see https://tailwindcss.com/docs/overscroll-behavior
       */
      "overscroll-y": [{
        "overscroll-y": scaleOverscroll()
      }],
      /**
       * Position
       * @see https://tailwindcss.com/docs/position
       */
      position: ["static", "fixed", "absolute", "relative", "sticky"],
      /**
       * Top / Right / Bottom / Left
       * @see https://tailwindcss.com/docs/top-right-bottom-left
       */
      inset: [{
        inset: scaleInset()
      }],
      /**
       * Right / Left
       * @see https://tailwindcss.com/docs/top-right-bottom-left
       */
      "inset-x": [{
        "inset-x": scaleInset()
      }],
      /**
       * Top / Bottom
       * @see https://tailwindcss.com/docs/top-right-bottom-left
       */
      "inset-y": [{
        "inset-y": scaleInset()
      }],
      /**
       * Start
       * @see https://tailwindcss.com/docs/top-right-bottom-left
       */
      start: [{
        start: scaleInset()
      }],
      /**
       * End
       * @see https://tailwindcss.com/docs/top-right-bottom-left
       */
      end: [{
        end: scaleInset()
      }],
      /**
       * Top
       * @see https://tailwindcss.com/docs/top-right-bottom-left
       */
      top: [{
        top: scaleInset()
      }],
      /**
       * Right
       * @see https://tailwindcss.com/docs/top-right-bottom-left
       */
      right: [{
        right: scaleInset()
      }],
      /**
       * Bottom
       * @see https://tailwindcss.com/docs/top-right-bottom-left
       */
      bottom: [{
        bottom: scaleInset()
      }],
      /**
       * Left
       * @see https://tailwindcss.com/docs/top-right-bottom-left
       */
      left: [{
        left: scaleInset()
      }],
      /**
       * Visibility
       * @see https://tailwindcss.com/docs/visibility
       */
      visibility: ["visible", "invisible", "collapse"],
      /**
       * Z-Index
       * @see https://tailwindcss.com/docs/z-index
       */
      z: [{
        z: [isInteger, "auto", isArbitraryVariable, isArbitraryValue]
      }],
      // ------------------------
      // --- Flexbox and Grid ---
      // ------------------------
      /**
       * Flex Basis
       * @see https://tailwindcss.com/docs/flex-basis
       */
      basis: [{
        basis: [isFraction, "full", "auto", themeContainer, ...scaleUnambiguousSpacing()]
      }],
      /**
       * Flex Direction
       * @see https://tailwindcss.com/docs/flex-direction
       */
      "flex-direction": [{
        flex: ["row", "row-reverse", "col", "col-reverse"]
      }],
      /**
       * Flex Wrap
       * @see https://tailwindcss.com/docs/flex-wrap
       */
      "flex-wrap": [{
        flex: ["nowrap", "wrap", "wrap-reverse"]
      }],
      /**
       * Flex
       * @see https://tailwindcss.com/docs/flex
       */
      flex: [{
        flex: [isNumber, isFraction, "auto", "initial", "none", isArbitraryValue]
      }],
      /**
       * Flex Grow
       * @see https://tailwindcss.com/docs/flex-grow
       */
      grow: [{
        grow: ["", isNumber, isArbitraryVariable, isArbitraryValue]
      }],
      /**
       * Flex Shrink
       * @see https://tailwindcss.com/docs/flex-shrink
       */
      shrink: [{
        shrink: ["", isNumber, isArbitraryVariable, isArbitraryValue]
      }],
      /**
       * Order
       * @see https://tailwindcss.com/docs/order
       */
      order: [{
        order: [isInteger, "first", "last", "none", isArbitraryVariable, isArbitraryValue]
      }],
      /**
       * Grid Template Columns
       * @see https://tailwindcss.com/docs/grid-template-columns
       */
      "grid-cols": [{
        "grid-cols": scaleGridTemplateColsRows()
      }],
      /**
       * Grid Column Start / End
       * @see https://tailwindcss.com/docs/grid-column
       */
      "col-start-end": [{
        col: scaleGridColRowStartAndEnd()
      }],
      /**
       * Grid Column Start
       * @see https://tailwindcss.com/docs/grid-column
       */
      "col-start": [{
        "col-start": scaleGridColRowStartOrEnd()
      }],
      /**
       * Grid Column End
       * @see https://tailwindcss.com/docs/grid-column
       */
      "col-end": [{
        "col-end": scaleGridColRowStartOrEnd()
      }],
      /**
       * Grid Template Rows
       * @see https://tailwindcss.com/docs/grid-template-rows
       */
      "grid-rows": [{
        "grid-rows": scaleGridTemplateColsRows()
      }],
      /**
       * Grid Row Start / End
       * @see https://tailwindcss.com/docs/grid-row
       */
      "row-start-end": [{
        row: scaleGridColRowStartAndEnd()
      }],
      /**
       * Grid Row Start
       * @see https://tailwindcss.com/docs/grid-row
       */
      "row-start": [{
        "row-start": scaleGridColRowStartOrEnd()
      }],
      /**
       * Grid Row End
       * @see https://tailwindcss.com/docs/grid-row
       */
      "row-end": [{
        "row-end": scaleGridColRowStartOrEnd()
      }],
      /**
       * Grid Auto Flow
       * @see https://tailwindcss.com/docs/grid-auto-flow
       */
      "grid-flow": [{
        "grid-flow": ["row", "col", "dense", "row-dense", "col-dense"]
      }],
      /**
       * Grid Auto Columns
       * @see https://tailwindcss.com/docs/grid-auto-columns
       */
      "auto-cols": [{
        "auto-cols": scaleGridAutoColsRows()
      }],
      /**
       * Grid Auto Rows
       * @see https://tailwindcss.com/docs/grid-auto-rows
       */
      "auto-rows": [{
        "auto-rows": scaleGridAutoColsRows()
      }],
      /**
       * Gap
       * @see https://tailwindcss.com/docs/gap
       */
      gap: [{
        gap: scaleUnambiguousSpacing()
      }],
      /**
       * Gap X
       * @see https://tailwindcss.com/docs/gap
       */
      "gap-x": [{
        "gap-x": scaleUnambiguousSpacing()
      }],
      /**
       * Gap Y
       * @see https://tailwindcss.com/docs/gap
       */
      "gap-y": [{
        "gap-y": scaleUnambiguousSpacing()
      }],
      /**
       * Justify Content
       * @see https://tailwindcss.com/docs/justify-content
       */
      "justify-content": [{
        justify: [...scaleAlignPrimaryAxis(), "normal"]
      }],
      /**
       * Justify Items
       * @see https://tailwindcss.com/docs/justify-items
       */
      "justify-items": [{
        "justify-items": [...scaleAlignSecondaryAxis(), "normal"]
      }],
      /**
       * Justify Self
       * @see https://tailwindcss.com/docs/justify-self
       */
      "justify-self": [{
        "justify-self": ["auto", ...scaleAlignSecondaryAxis()]
      }],
      /**
       * Align Content
       * @see https://tailwindcss.com/docs/align-content
       */
      "align-content": [{
        content: ["normal", ...scaleAlignPrimaryAxis()]
      }],
      /**
       * Align Items
       * @see https://tailwindcss.com/docs/align-items
       */
      "align-items": [{
        items: [...scaleAlignSecondaryAxis(), {
          baseline: ["", "last"]
        }]
      }],
      /**
       * Align Self
       * @see https://tailwindcss.com/docs/align-self
       */
      "align-self": [{
        self: ["auto", ...scaleAlignSecondaryAxis(), {
          baseline: ["", "last"]
        }]
      }],
      /**
       * Place Content
       * @see https://tailwindcss.com/docs/place-content
       */
      "place-content": [{
        "place-content": scaleAlignPrimaryAxis()
      }],
      /**
       * Place Items
       * @see https://tailwindcss.com/docs/place-items
       */
      "place-items": [{
        "place-items": [...scaleAlignSecondaryAxis(), "baseline"]
      }],
      /**
       * Place Self
       * @see https://tailwindcss.com/docs/place-self
       */
      "place-self": [{
        "place-self": ["auto", ...scaleAlignSecondaryAxis()]
      }],
      // Spacing
      /**
       * Padding
       * @see https://tailwindcss.com/docs/padding
       */
      p: [{
        p: scaleUnambiguousSpacing()
      }],
      /**
       * Padding X
       * @see https://tailwindcss.com/docs/padding
       */
      px: [{
        px: scaleUnambiguousSpacing()
      }],
      /**
       * Padding Y
       * @see https://tailwindcss.com/docs/padding
       */
      py: [{
        py: scaleUnambiguousSpacing()
      }],
      /**
       * Padding Start
       * @see https://tailwindcss.com/docs/padding
       */
      ps: [{
        ps: scaleUnambiguousSpacing()
      }],
      /**
       * Padding End
       * @see https://tailwindcss.com/docs/padding
       */
      pe: [{
        pe: scaleUnambiguousSpacing()
      }],
      /**
       * Padding Top
       * @see https://tailwindcss.com/docs/padding
       */
      pt: [{
        pt: scaleUnambiguousSpacing()
      }],
      /**
       * Padding Right
       * @see https://tailwindcss.com/docs/padding
       */
      pr: [{
        pr: scaleUnambiguousSpacing()
      }],
      /**
       * Padding Bottom
       * @see https://tailwindcss.com/docs/padding
       */
      pb: [{
        pb: scaleUnambiguousSpacing()
      }],
      /**
       * Padding Left
       * @see https://tailwindcss.com/docs/padding
       */
      pl: [{
        pl: scaleUnambiguousSpacing()
      }],
      /**
       * Margin
       * @see https://tailwindcss.com/docs/margin
       */
      m: [{
        m: scaleMargin()
      }],
      /**
       * Margin X
       * @see https://tailwindcss.com/docs/margin
       */
      mx: [{
        mx: scaleMargin()
      }],
      /**
       * Margin Y
       * @see https://tailwindcss.com/docs/margin
       */
      my: [{
        my: scaleMargin()
      }],
      /**
       * Margin Start
       * @see https://tailwindcss.com/docs/margin
       */
      ms: [{
        ms: scaleMargin()
      }],
      /**
       * Margin End
       * @see https://tailwindcss.com/docs/margin
       */
      me: [{
        me: scaleMargin()
      }],
      /**
       * Margin Top
       * @see https://tailwindcss.com/docs/margin
       */
      mt: [{
        mt: scaleMargin()
      }],
      /**
       * Margin Right
       * @see https://tailwindcss.com/docs/margin
       */
      mr: [{
        mr: scaleMargin()
      }],
      /**
       * Margin Bottom
       * @see https://tailwindcss.com/docs/margin
       */
      mb: [{
        mb: scaleMargin()
      }],
      /**
       * Margin Left
       * @see https://tailwindcss.com/docs/margin
       */
      ml: [{
        ml: scaleMargin()
      }],
      /**
       * Space Between X
       * @see https://tailwindcss.com/docs/margin#adding-space-between-children
       */
      "space-x": [{
        "space-x": scaleUnambiguousSpacing()
      }],
      /**
       * Space Between X Reverse
       * @see https://tailwindcss.com/docs/margin#adding-space-between-children
       */
      "space-x-reverse": ["space-x-reverse"],
      /**
       * Space Between Y
       * @see https://tailwindcss.com/docs/margin#adding-space-between-children
       */
      "space-y": [{
        "space-y": scaleUnambiguousSpacing()
      }],
      /**
       * Space Between Y Reverse
       * @see https://tailwindcss.com/docs/margin#adding-space-between-children
       */
      "space-y-reverse": ["space-y-reverse"],
      // --------------
      // --- Sizing ---
      // --------------
      /**
       * Size
       * @see https://tailwindcss.com/docs/width#setting-both-width-and-height
       */
      size: [{
        size: scaleSizing()
      }],
      /**
       * Width
       * @see https://tailwindcss.com/docs/width
       */
      w: [{
        w: [themeContainer, "screen", ...scaleSizing()]
      }],
      /**
       * Min-Width
       * @see https://tailwindcss.com/docs/min-width
       */
      "min-w": [{
        "min-w": [
          themeContainer,
          "screen",
          /** Deprecated. @see https://github.com/tailwindlabs/tailwindcss.com/issues/2027#issuecomment-2620152757 */
          "none",
          ...scaleSizing()
        ]
      }],
      /**
       * Max-Width
       * @see https://tailwindcss.com/docs/max-width
       */
      "max-w": [{
        "max-w": [
          themeContainer,
          "screen",
          "none",
          /** Deprecated since Tailwind CSS v4.0.0. @see https://github.com/tailwindlabs/tailwindcss.com/issues/2027#issuecomment-2620152757 */
          "prose",
          /** Deprecated since Tailwind CSS v4.0.0. @see https://github.com/tailwindlabs/tailwindcss.com/issues/2027#issuecomment-2620152757 */
          {
            screen: [themeBreakpoint]
          },
          ...scaleSizing()
        ]
      }],
      /**
       * Height
       * @see https://tailwindcss.com/docs/height
       */
      h: [{
        h: ["screen", "lh", ...scaleSizing()]
      }],
      /**
       * Min-Height
       * @see https://tailwindcss.com/docs/min-height
       */
      "min-h": [{
        "min-h": ["screen", "lh", "none", ...scaleSizing()]
      }],
      /**
       * Max-Height
       * @see https://tailwindcss.com/docs/max-height
       */
      "max-h": [{
        "max-h": ["screen", "lh", ...scaleSizing()]
      }],
      // ------------------
      // --- Typography ---
      // ------------------
      /**
       * Font Size
       * @see https://tailwindcss.com/docs/font-size
       */
      "font-size": [{
        text: ["base", themeText, isArbitraryVariableLength, isArbitraryLength]
      }],
      /**
       * Font Smoothing
       * @see https://tailwindcss.com/docs/font-smoothing
       */
      "font-smoothing": ["antialiased", "subpixel-antialiased"],
      /**
       * Font Style
       * @see https://tailwindcss.com/docs/font-style
       */
      "font-style": ["italic", "not-italic"],
      /**
       * Font Weight
       * @see https://tailwindcss.com/docs/font-weight
       */
      "font-weight": [{
        font: [themeFontWeight, isArbitraryVariable, isArbitraryNumber]
      }],
      /**
       * Font Stretch
       * @see https://tailwindcss.com/docs/font-stretch
       */
      "font-stretch": [{
        "font-stretch": ["ultra-condensed", "extra-condensed", "condensed", "semi-condensed", "normal", "semi-expanded", "expanded", "extra-expanded", "ultra-expanded", isPercent, isArbitraryValue]
      }],
      /**
       * Font Family
       * @see https://tailwindcss.com/docs/font-family
       */
      "font-family": [{
        font: [isArbitraryVariableFamilyName, isArbitraryValue, themeFont]
      }],
      /**
       * Font Variant Numeric
       * @see https://tailwindcss.com/docs/font-variant-numeric
       */
      "fvn-normal": ["normal-nums"],
      /**
       * Font Variant Numeric
       * @see https://tailwindcss.com/docs/font-variant-numeric
       */
      "fvn-ordinal": ["ordinal"],
      /**
       * Font Variant Numeric
       * @see https://tailwindcss.com/docs/font-variant-numeric
       */
      "fvn-slashed-zero": ["slashed-zero"],
      /**
       * Font Variant Numeric
       * @see https://tailwindcss.com/docs/font-variant-numeric
       */
      "fvn-figure": ["lining-nums", "oldstyle-nums"],
      /**
       * Font Variant Numeric
       * @see https://tailwindcss.com/docs/font-variant-numeric
       */
      "fvn-spacing": ["proportional-nums", "tabular-nums"],
      /**
       * Font Variant Numeric
       * @see https://tailwindcss.com/docs/font-variant-numeric
       */
      "fvn-fraction": ["diagonal-fractions", "stacked-fractions"],
      /**
       * Letter Spacing
       * @see https://tailwindcss.com/docs/letter-spacing
       */
      tracking: [{
        tracking: [themeTracking, isArbitraryVariable, isArbitraryValue]
      }],
      /**
       * Line Clamp
       * @see https://tailwindcss.com/docs/line-clamp
       */
      "line-clamp": [{
        "line-clamp": [isNumber, "none", isArbitraryVariable, isArbitraryNumber]
      }],
      /**
       * Line Height
       * @see https://tailwindcss.com/docs/line-height
       */
      leading: [{
        leading: [
          /** Deprecated since Tailwind CSS v4.0.0. @see https://github.com/tailwindlabs/tailwindcss.com/issues/2027#issuecomment-2620152757 */
          themeLeading,
          ...scaleUnambiguousSpacing()
        ]
      }],
      /**
       * List Style Image
       * @see https://tailwindcss.com/docs/list-style-image
       */
      "list-image": [{
        "list-image": ["none", isArbitraryVariable, isArbitraryValue]
      }],
      /**
       * List Style Position
       * @see https://tailwindcss.com/docs/list-style-position
       */
      "list-style-position": [{
        list: ["inside", "outside"]
      }],
      /**
       * List Style Type
       * @see https://tailwindcss.com/docs/list-style-type
       */
      "list-style-type": [{
        list: ["disc", "decimal", "none", isArbitraryVariable, isArbitraryValue]
      }],
      /**
       * Text Alignment
       * @see https://tailwindcss.com/docs/text-align
       */
      "text-alignment": [{
        text: ["left", "center", "right", "justify", "start", "end"]
      }],
      /**
       * Placeholder Color
       * @deprecated since Tailwind CSS v3.0.0
       * @see https://v3.tailwindcss.com/docs/placeholder-color
       */
      "placeholder-color": [{
        placeholder: scaleColor()
      }],
      /**
       * Text Color
       * @see https://tailwindcss.com/docs/text-color
       */
      "text-color": [{
        text: scaleColor()
      }],
      /**
       * Text Decoration
       * @see https://tailwindcss.com/docs/text-decoration
       */
      "text-decoration": ["underline", "overline", "line-through", "no-underline"],
      /**
       * Text Decoration Style
       * @see https://tailwindcss.com/docs/text-decoration-style
       */
      "text-decoration-style": [{
        decoration: [...scaleLineStyle(), "wavy"]
      }],
      /**
       * Text Decoration Thickness
       * @see https://tailwindcss.com/docs/text-decoration-thickness
       */
      "text-decoration-thickness": [{
        decoration: [isNumber, "from-font", "auto", isArbitraryVariable, isArbitraryLength]
      }],
      /**
       * Text Decoration Color
       * @see https://tailwindcss.com/docs/text-decoration-color
       */
      "text-decoration-color": [{
        decoration: scaleColor()
      }],
      /**
       * Text Underline Offset
       * @see https://tailwindcss.com/docs/text-underline-offset
       */
      "underline-offset": [{
        "underline-offset": [isNumber, "auto", isArbitraryVariable, isArbitraryValue]
      }],
      /**
       * Text Transform
       * @see https://tailwindcss.com/docs/text-transform
       */
      "text-transform": ["uppercase", "lowercase", "capitalize", "normal-case"],
      /**
       * Text Overflow
       * @see https://tailwindcss.com/docs/text-overflow
       */
      "text-overflow": ["truncate", "text-ellipsis", "text-clip"],
      /**
       * Text Wrap
       * @see https://tailwindcss.com/docs/text-wrap
       */
      "text-wrap": [{
        text: ["wrap", "nowrap", "balance", "pretty"]
      }],
      /**
       * Text Indent
       * @see https://tailwindcss.com/docs/text-indent
       */
      indent: [{
        indent: scaleUnambiguousSpacing()
      }],
      /**
       * Vertical Alignment
       * @see https://tailwindcss.com/docs/vertical-align
       */
      "vertical-align": [{
        align: ["baseline", "top", "middle", "bottom", "text-top", "text-bottom", "sub", "super", isArbitraryVariable, isArbitraryValue]
      }],
      /**
       * Whitespace
       * @see https://tailwindcss.com/docs/whitespace
       */
      whitespace: [{
        whitespace: ["normal", "nowrap", "pre", "pre-line", "pre-wrap", "break-spaces"]
      }],
      /**
       * Word Break
       * @see https://tailwindcss.com/docs/word-break
       */
      break: [{
        break: ["normal", "words", "all", "keep"]
      }],
      /**
       * Overflow Wrap
       * @see https://tailwindcss.com/docs/overflow-wrap
       */
      wrap: [{
        wrap: ["break-word", "anywhere", "normal"]
      }],
      /**
       * Hyphens
       * @see https://tailwindcss.com/docs/hyphens
       */
      hyphens: [{
        hyphens: ["none", "manual", "auto"]
      }],
      /**
       * Content
       * @see https://tailwindcss.com/docs/content
       */
      content: [{
        content: ["none", isArbitraryVariable, isArbitraryValue]
      }],
      // -------------------
      // --- Backgrounds ---
      // -------------------
      /**
       * Background Attachment
       * @see https://tailwindcss.com/docs/background-attachment
       */
      "bg-attachment": [{
        bg: ["fixed", "local", "scroll"]
      }],
      /**
       * Background Clip
       * @see https://tailwindcss.com/docs/background-clip
       */
      "bg-clip": [{
        "bg-clip": ["border", "padding", "content", "text"]
      }],
      /**
       * Background Origin
       * @see https://tailwindcss.com/docs/background-origin
       */
      "bg-origin": [{
        "bg-origin": ["border", "padding", "content"]
      }],
      /**
       * Background Position
       * @see https://tailwindcss.com/docs/background-position
       */
      "bg-position": [{
        bg: scaleBgPosition()
      }],
      /**
       * Background Repeat
       * @see https://tailwindcss.com/docs/background-repeat
       */
      "bg-repeat": [{
        bg: scaleBgRepeat()
      }],
      /**
       * Background Size
       * @see https://tailwindcss.com/docs/background-size
       */
      "bg-size": [{
        bg: scaleBgSize()
      }],
      /**
       * Background Image
       * @see https://tailwindcss.com/docs/background-image
       */
      "bg-image": [{
        bg: ["none", {
          linear: [{
            to: ["t", "tr", "r", "br", "b", "bl", "l", "tl"]
          }, isInteger, isArbitraryVariable, isArbitraryValue],
          radial: ["", isArbitraryVariable, isArbitraryValue],
          conic: [isInteger, isArbitraryVariable, isArbitraryValue]
        }, isArbitraryVariableImage, isArbitraryImage]
      }],
      /**
       * Background Color
       * @see https://tailwindcss.com/docs/background-color
       */
      "bg-color": [{
        bg: scaleColor()
      }],
      /**
       * Gradient Color Stops From Position
       * @see https://tailwindcss.com/docs/gradient-color-stops
       */
      "gradient-from-pos": [{
        from: scaleGradientStopPosition()
      }],
      /**
       * Gradient Color Stops Via Position
       * @see https://tailwindcss.com/docs/gradient-color-stops
       */
      "gradient-via-pos": [{
        via: scaleGradientStopPosition()
      }],
      /**
       * Gradient Color Stops To Position
       * @see https://tailwindcss.com/docs/gradient-color-stops
       */
      "gradient-to-pos": [{
        to: scaleGradientStopPosition()
      }],
      /**
       * Gradient Color Stops From
       * @see https://tailwindcss.com/docs/gradient-color-stops
       */
      "gradient-from": [{
        from: scaleColor()
      }],
      /**
       * Gradient Color Stops Via
       * @see https://tailwindcss.com/docs/gradient-color-stops
       */
      "gradient-via": [{
        via: scaleColor()
      }],
      /**
       * Gradient Color Stops To
       * @see https://tailwindcss.com/docs/gradient-color-stops
       */
      "gradient-to": [{
        to: scaleColor()
      }],
      // ---------------
      // --- Borders ---
      // ---------------
      /**
       * Border Radius
       * @see https://tailwindcss.com/docs/border-radius
       */
      rounded: [{
        rounded: scaleRadius()
      }],
      /**
       * Border Radius Start
       * @see https://tailwindcss.com/docs/border-radius
       */
      "rounded-s": [{
        "rounded-s": scaleRadius()
      }],
      /**
       * Border Radius End
       * @see https://tailwindcss.com/docs/border-radius
       */
      "rounded-e": [{
        "rounded-e": scaleRadius()
      }],
      /**
       * Border Radius Top
       * @see https://tailwindcss.com/docs/border-radius
       */
      "rounded-t": [{
        "rounded-t": scaleRadius()
      }],
      /**
       * Border Radius Right
       * @see https://tailwindcss.com/docs/border-radius
       */
      "rounded-r": [{
        "rounded-r": scaleRadius()
      }],
      /**
       * Border Radius Bottom
       * @see https://tailwindcss.com/docs/border-radius
       */
      "rounded-b": [{
        "rounded-b": scaleRadius()
      }],
      /**
       * Border Radius Left
       * @see https://tailwindcss.com/docs/border-radius
       */
      "rounded-l": [{
        "rounded-l": scaleRadius()
      }],
      /**
       * Border Radius Start Start
       * @see https://tailwindcss.com/docs/border-radius
       */
      "rounded-ss": [{
        "rounded-ss": scaleRadius()
      }],
      /**
       * Border Radius Start End
       * @see https://tailwindcss.com/docs/border-radius
       */
      "rounded-se": [{
        "rounded-se": scaleRadius()
      }],
      /**
       * Border Radius End End
       * @see https://tailwindcss.com/docs/border-radius
       */
      "rounded-ee": [{
        "rounded-ee": scaleRadius()
      }],
      /**
       * Border Radius End Start
       * @see https://tailwindcss.com/docs/border-radius
       */
      "rounded-es": [{
        "rounded-es": scaleRadius()
      }],
      /**
       * Border Radius Top Left
       * @see https://tailwindcss.com/docs/border-radius
       */
      "rounded-tl": [{
        "rounded-tl": scaleRadius()
      }],
      /**
       * Border Radius Top Right
       * @see https://tailwindcss.com/docs/border-radius
       */
      "rounded-tr": [{
        "rounded-tr": scaleRadius()
      }],
      /**
       * Border Radius Bottom Right
       * @see https://tailwindcss.com/docs/border-radius
       */
      "rounded-br": [{
        "rounded-br": scaleRadius()
      }],
      /**
       * Border Radius Bottom Left
       * @see https://tailwindcss.com/docs/border-radius
       */
      "rounded-bl": [{
        "rounded-bl": scaleRadius()
      }],
      /**
       * Border Width
       * @see https://tailwindcss.com/docs/border-width
       */
      "border-w": [{
        border: scaleBorderWidth()
      }],
      /**
       * Border Width X
       * @see https://tailwindcss.com/docs/border-width
       */
      "border-w-x": [{
        "border-x": scaleBorderWidth()
      }],
      /**
       * Border Width Y
       * @see https://tailwindcss.com/docs/border-width
       */
      "border-w-y": [{
        "border-y": scaleBorderWidth()
      }],
      /**
       * Border Width Start
       * @see https://tailwindcss.com/docs/border-width
       */
      "border-w-s": [{
        "border-s": scaleBorderWidth()
      }],
      /**
       * Border Width End
       * @see https://tailwindcss.com/docs/border-width
       */
      "border-w-e": [{
        "border-e": scaleBorderWidth()
      }],
      /**
       * Border Width Top
       * @see https://tailwindcss.com/docs/border-width
       */
      "border-w-t": [{
        "border-t": scaleBorderWidth()
      }],
      /**
       * Border Width Right
       * @see https://tailwindcss.com/docs/border-width
       */
      "border-w-r": [{
        "border-r": scaleBorderWidth()
      }],
      /**
       * Border Width Bottom
       * @see https://tailwindcss.com/docs/border-width
       */
      "border-w-b": [{
        "border-b": scaleBorderWidth()
      }],
      /**
       * Border Width Left
       * @see https://tailwindcss.com/docs/border-width
       */
      "border-w-l": [{
        "border-l": scaleBorderWidth()
      }],
      /**
       * Divide Width X
       * @see https://tailwindcss.com/docs/border-width#between-children
       */
      "divide-x": [{
        "divide-x": scaleBorderWidth()
      }],
      /**
       * Divide Width X Reverse
       * @see https://tailwindcss.com/docs/border-width#between-children
       */
      "divide-x-reverse": ["divide-x-reverse"],
      /**
       * Divide Width Y
       * @see https://tailwindcss.com/docs/border-width#between-children
       */
      "divide-y": [{
        "divide-y": scaleBorderWidth()
      }],
      /**
       * Divide Width Y Reverse
       * @see https://tailwindcss.com/docs/border-width#between-children
       */
      "divide-y-reverse": ["divide-y-reverse"],
      /**
       * Border Style
       * @see https://tailwindcss.com/docs/border-style
       */
      "border-style": [{
        border: [...scaleLineStyle(), "hidden", "none"]
      }],
      /**
       * Divide Style
       * @see https://tailwindcss.com/docs/border-style#setting-the-divider-style
       */
      "divide-style": [{
        divide: [...scaleLineStyle(), "hidden", "none"]
      }],
      /**
       * Border Color
       * @see https://tailwindcss.com/docs/border-color
       */
      "border-color": [{
        border: scaleColor()
      }],
      /**
       * Border Color X
       * @see https://tailwindcss.com/docs/border-color
       */
      "border-color-x": [{
        "border-x": scaleColor()
      }],
      /**
       * Border Color Y
       * @see https://tailwindcss.com/docs/border-color
       */
      "border-color-y": [{
        "border-y": scaleColor()
      }],
      /**
       * Border Color S
       * @see https://tailwindcss.com/docs/border-color
       */
      "border-color-s": [{
        "border-s": scaleColor()
      }],
      /**
       * Border Color E
       * @see https://tailwindcss.com/docs/border-color
       */
      "border-color-e": [{
        "border-e": scaleColor()
      }],
      /**
       * Border Color Top
       * @see https://tailwindcss.com/docs/border-color
       */
      "border-color-t": [{
        "border-t": scaleColor()
      }],
      /**
       * Border Color Right
       * @see https://tailwindcss.com/docs/border-color
       */
      "border-color-r": [{
        "border-r": scaleColor()
      }],
      /**
       * Border Color Bottom
       * @see https://tailwindcss.com/docs/border-color
       */
      "border-color-b": [{
        "border-b": scaleColor()
      }],
      /**
       * Border Color Left
       * @see https://tailwindcss.com/docs/border-color
       */
      "border-color-l": [{
        "border-l": scaleColor()
      }],
      /**
       * Divide Color
       * @see https://tailwindcss.com/docs/divide-color
       */
      "divide-color": [{
        divide: scaleColor()
      }],
      /**
       * Outline Style
       * @see https://tailwindcss.com/docs/outline-style
       */
      "outline-style": [{
        outline: [...scaleLineStyle(), "none", "hidden"]
      }],
      /**
       * Outline Offset
       * @see https://tailwindcss.com/docs/outline-offset
       */
      "outline-offset": [{
        "outline-offset": [isNumber, isArbitraryVariable, isArbitraryValue]
      }],
      /**
       * Outline Width
       * @see https://tailwindcss.com/docs/outline-width
       */
      "outline-w": [{
        outline: ["", isNumber, isArbitraryVariableLength, isArbitraryLength]
      }],
      /**
       * Outline Color
       * @see https://tailwindcss.com/docs/outline-color
       */
      "outline-color": [{
        outline: scaleColor()
      }],
      // ---------------
      // --- Effects ---
      // ---------------
      /**
       * Box Shadow
       * @see https://tailwindcss.com/docs/box-shadow
       */
      shadow: [{
        shadow: [
          // Deprecated since Tailwind CSS v4.0.0
          "",
          "none",
          themeShadow,
          isArbitraryVariableShadow,
          isArbitraryShadow
        ]
      }],
      /**
       * Box Shadow Color
       * @see https://tailwindcss.com/docs/box-shadow#setting-the-shadow-color
       */
      "shadow-color": [{
        shadow: scaleColor()
      }],
      /**
       * Inset Box Shadow
       * @see https://tailwindcss.com/docs/box-shadow#adding-an-inset-shadow
       */
      "inset-shadow": [{
        "inset-shadow": ["none", themeInsetShadow, isArbitraryVariableShadow, isArbitraryShadow]
      }],
      /**
       * Inset Box Shadow Color
       * @see https://tailwindcss.com/docs/box-shadow#setting-the-inset-shadow-color
       */
      "inset-shadow-color": [{
        "inset-shadow": scaleColor()
      }],
      /**
       * Ring Width
       * @see https://tailwindcss.com/docs/box-shadow#adding-a-ring
       */
      "ring-w": [{
        ring: scaleBorderWidth()
      }],
      /**
       * Ring Width Inset
       * @see https://v3.tailwindcss.com/docs/ring-width#inset-rings
       * @deprecated since Tailwind CSS v4.0.0
       * @see https://github.com/tailwindlabs/tailwindcss/blob/v4.0.0/packages/tailwindcss/src/utilities.ts#L4158
       */
      "ring-w-inset": ["ring-inset"],
      /**
       * Ring Color
       * @see https://tailwindcss.com/docs/box-shadow#setting-the-ring-color
       */
      "ring-color": [{
        ring: scaleColor()
      }],
      /**
       * Ring Offset Width
       * @see https://v3.tailwindcss.com/docs/ring-offset-width
       * @deprecated since Tailwind CSS v4.0.0
       * @see https://github.com/tailwindlabs/tailwindcss/blob/v4.0.0/packages/tailwindcss/src/utilities.ts#L4158
       */
      "ring-offset-w": [{
        "ring-offset": [isNumber, isArbitraryLength]
      }],
      /**
       * Ring Offset Color
       * @see https://v3.tailwindcss.com/docs/ring-offset-color
       * @deprecated since Tailwind CSS v4.0.0
       * @see https://github.com/tailwindlabs/tailwindcss/blob/v4.0.0/packages/tailwindcss/src/utilities.ts#L4158
       */
      "ring-offset-color": [{
        "ring-offset": scaleColor()
      }],
      /**
       * Inset Ring Width
       * @see https://tailwindcss.com/docs/box-shadow#adding-an-inset-ring
       */
      "inset-ring-w": [{
        "inset-ring": scaleBorderWidth()
      }],
      /**
       * Inset Ring Color
       * @see https://tailwindcss.com/docs/box-shadow#setting-the-inset-ring-color
       */
      "inset-ring-color": [{
        "inset-ring": scaleColor()
      }],
      /**
       * Text Shadow
       * @see https://tailwindcss.com/docs/text-shadow
       */
      "text-shadow": [{
        "text-shadow": ["none", themeTextShadow, isArbitraryVariableShadow, isArbitraryShadow]
      }],
      /**
       * Text Shadow Color
       * @see https://tailwindcss.com/docs/text-shadow#setting-the-shadow-color
       */
      "text-shadow-color": [{
        "text-shadow": scaleColor()
      }],
      /**
       * Opacity
       * @see https://tailwindcss.com/docs/opacity
       */
      opacity: [{
        opacity: [isNumber, isArbitraryVariable, isArbitraryValue]
      }],
      /**
       * Mix Blend Mode
       * @see https://tailwindcss.com/docs/mix-blend-mode
       */
      "mix-blend": [{
        "mix-blend": [...scaleBlendMode(), "plus-darker", "plus-lighter"]
      }],
      /**
       * Background Blend Mode
       * @see https://tailwindcss.com/docs/background-blend-mode
       */
      "bg-blend": [{
        "bg-blend": scaleBlendMode()
      }],
      /**
       * Mask Clip
       * @see https://tailwindcss.com/docs/mask-clip
       */
      "mask-clip": [{
        "mask-clip": ["border", "padding", "content", "fill", "stroke", "view"]
      }, "mask-no-clip"],
      /**
       * Mask Composite
       * @see https://tailwindcss.com/docs/mask-composite
       */
      "mask-composite": [{
        mask: ["add", "subtract", "intersect", "exclude"]
      }],
      /**
       * Mask Image
       * @see https://tailwindcss.com/docs/mask-image
       */
      "mask-image-linear-pos": [{
        "mask-linear": [isNumber]
      }],
      "mask-image-linear-from-pos": [{
        "mask-linear-from": scaleMaskImagePosition()
      }],
      "mask-image-linear-to-pos": [{
        "mask-linear-to": scaleMaskImagePosition()
      }],
      "mask-image-linear-from-color": [{
        "mask-linear-from": scaleColor()
      }],
      "mask-image-linear-to-color": [{
        "mask-linear-to": scaleColor()
      }],
      "mask-image-t-from-pos": [{
        "mask-t-from": scaleMaskImagePosition()
      }],
      "mask-image-t-to-pos": [{
        "mask-t-to": scaleMaskImagePosition()
      }],
      "mask-image-t-from-color": [{
        "mask-t-from": scaleColor()
      }],
      "mask-image-t-to-color": [{
        "mask-t-to": scaleColor()
      }],
      "mask-image-r-from-pos": [{
        "mask-r-from": scaleMaskImagePosition()
      }],
      "mask-image-r-to-pos": [{
        "mask-r-to": scaleMaskImagePosition()
      }],
      "mask-image-r-from-color": [{
        "mask-r-from": scaleColor()
      }],
      "mask-image-r-to-color": [{
        "mask-r-to": scaleColor()
      }],
      "mask-image-b-from-pos": [{
        "mask-b-from": scaleMaskImagePosition()
      }],
      "mask-image-b-to-pos": [{
        "mask-b-to": scaleMaskImagePosition()
      }],
      "mask-image-b-from-color": [{
        "mask-b-from": scaleColor()
      }],
      "mask-image-b-to-color": [{
        "mask-b-to": scaleColor()
      }],
      "mask-image-l-from-pos": [{
        "mask-l-from": scaleMaskImagePosition()
      }],
      "mask-image-l-to-pos": [{
        "mask-l-to": scaleMaskImagePosition()
      }],
      "mask-image-l-from-color": [{
        "mask-l-from": scaleColor()
      }],
      "mask-image-l-to-color": [{
        "mask-l-to": scaleColor()
      }],
      "mask-image-x-from-pos": [{
        "mask-x-from": scaleMaskImagePosition()
      }],
      "mask-image-x-to-pos": [{
        "mask-x-to": scaleMaskImagePosition()
      }],
      "mask-image-x-from-color": [{
        "mask-x-from": scaleColor()
      }],
      "mask-image-x-to-color": [{
        "mask-x-to": scaleColor()
      }],
      "mask-image-y-from-pos": [{
        "mask-y-from": scaleMaskImagePosition()
      }],
      "mask-image-y-to-pos": [{
        "mask-y-to": scaleMaskImagePosition()
      }],
      "mask-image-y-from-color": [{
        "mask-y-from": scaleColor()
      }],
      "mask-image-y-to-color": [{
        "mask-y-to": scaleColor()
      }],
      "mask-image-radial": [{
        "mask-radial": [isArbitraryVariable, isArbitraryValue]
      }],
      "mask-image-radial-from-pos": [{
        "mask-radial-from": scaleMaskImagePosition()
      }],
      "mask-image-radial-to-pos": [{
        "mask-radial-to": scaleMaskImagePosition()
      }],
      "mask-image-radial-from-color": [{
        "mask-radial-from": scaleColor()
      }],
      "mask-image-radial-to-color": [{
        "mask-radial-to": scaleColor()
      }],
      "mask-image-radial-shape": [{
        "mask-radial": ["circle", "ellipse"]
      }],
      "mask-image-radial-size": [{
        "mask-radial": [{
          closest: ["side", "corner"],
          farthest: ["side", "corner"]
        }]
      }],
      "mask-image-radial-pos": [{
        "mask-radial-at": scalePosition()
      }],
      "mask-image-conic-pos": [{
        "mask-conic": [isNumber]
      }],
      "mask-image-conic-from-pos": [{
        "mask-conic-from": scaleMaskImagePosition()
      }],
      "mask-image-conic-to-pos": [{
        "mask-conic-to": scaleMaskImagePosition()
      }],
      "mask-image-conic-from-color": [{
        "mask-conic-from": scaleColor()
      }],
      "mask-image-conic-to-color": [{
        "mask-conic-to": scaleColor()
      }],
      /**
       * Mask Mode
       * @see https://tailwindcss.com/docs/mask-mode
       */
      "mask-mode": [{
        mask: ["alpha", "luminance", "match"]
      }],
      /**
       * Mask Origin
       * @see https://tailwindcss.com/docs/mask-origin
       */
      "mask-origin": [{
        "mask-origin": ["border", "padding", "content", "fill", "stroke", "view"]
      }],
      /**
       * Mask Position
       * @see https://tailwindcss.com/docs/mask-position
       */
      "mask-position": [{
        mask: scaleBgPosition()
      }],
      /**
       * Mask Repeat
       * @see https://tailwindcss.com/docs/mask-repeat
       */
      "mask-repeat": [{
        mask: scaleBgRepeat()
      }],
      /**
       * Mask Size
       * @see https://tailwindcss.com/docs/mask-size
       */
      "mask-size": [{
        mask: scaleBgSize()
      }],
      /**
       * Mask Type
       * @see https://tailwindcss.com/docs/mask-type
       */
      "mask-type": [{
        "mask-type": ["alpha", "luminance"]
      }],
      /**
       * Mask Image
       * @see https://tailwindcss.com/docs/mask-image
       */
      "mask-image": [{
        mask: ["none", isArbitraryVariable, isArbitraryValue]
      }],
      // ---------------
      // --- Filters ---
      // ---------------
      /**
       * Filter
       * @see https://tailwindcss.com/docs/filter
       */
      filter: [{
        filter: [
          // Deprecated since Tailwind CSS v3.0.0
          "",
          "none",
          isArbitraryVariable,
          isArbitraryValue
        ]
      }],
      /**
       * Blur
       * @see https://tailwindcss.com/docs/blur
       */
      blur: [{
        blur: scaleBlur()
      }],
      /**
       * Brightness
       * @see https://tailwindcss.com/docs/brightness
       */
      brightness: [{
        brightness: [isNumber, isArbitraryVariable, isArbitraryValue]
      }],
      /**
       * Contrast
       * @see https://tailwindcss.com/docs/contrast
       */
      contrast: [{
        contrast: [isNumber, isArbitraryVariable, isArbitraryValue]
      }],
      /**
       * Drop Shadow
       * @see https://tailwindcss.com/docs/drop-shadow
       */
      "drop-shadow": [{
        "drop-shadow": [
          // Deprecated since Tailwind CSS v4.0.0
          "",
          "none",
          themeDropShadow,
          isArbitraryVariableShadow,
          isArbitraryShadow
        ]
      }],
      /**
       * Drop Shadow Color
       * @see https://tailwindcss.com/docs/filter-drop-shadow#setting-the-shadow-color
       */
      "drop-shadow-color": [{
        "drop-shadow": scaleColor()
      }],
      /**
       * Grayscale
       * @see https://tailwindcss.com/docs/grayscale
       */
      grayscale: [{
        grayscale: ["", isNumber, isArbitraryVariable, isArbitraryValue]
      }],
      /**
       * Hue Rotate
       * @see https://tailwindcss.com/docs/hue-rotate
       */
      "hue-rotate": [{
        "hue-rotate": [isNumber, isArbitraryVariable, isArbitraryValue]
      }],
      /**
       * Invert
       * @see https://tailwindcss.com/docs/invert
       */
      invert: [{
        invert: ["", isNumber, isArbitraryVariable, isArbitraryValue]
      }],
      /**
       * Saturate
       * @see https://tailwindcss.com/docs/saturate
       */
      saturate: [{
        saturate: [isNumber, isArbitraryVariable, isArbitraryValue]
      }],
      /**
       * Sepia
       * @see https://tailwindcss.com/docs/sepia
       */
      sepia: [{
        sepia: ["", isNumber, isArbitraryVariable, isArbitraryValue]
      }],
      /**
       * Backdrop Filter
       * @see https://tailwindcss.com/docs/backdrop-filter
       */
      "backdrop-filter": [{
        "backdrop-filter": [
          // Deprecated since Tailwind CSS v3.0.0
          "",
          "none",
          isArbitraryVariable,
          isArbitraryValue
        ]
      }],
      /**
       * Backdrop Blur
       * @see https://tailwindcss.com/docs/backdrop-blur
       */
      "backdrop-blur": [{
        "backdrop-blur": scaleBlur()
      }],
      /**
       * Backdrop Brightness
       * @see https://tailwindcss.com/docs/backdrop-brightness
       */
      "backdrop-brightness": [{
        "backdrop-brightness": [isNumber, isArbitraryVariable, isArbitraryValue]
      }],
      /**
       * Backdrop Contrast
       * @see https://tailwindcss.com/docs/backdrop-contrast
       */
      "backdrop-contrast": [{
        "backdrop-contrast": [isNumber, isArbitraryVariable, isArbitraryValue]
      }],
      /**
       * Backdrop Grayscale
       * @see https://tailwindcss.com/docs/backdrop-grayscale
       */
      "backdrop-grayscale": [{
        "backdrop-grayscale": ["", isNumber, isArbitraryVariable, isArbitraryValue]
      }],
      /**
       * Backdrop Hue Rotate
       * @see https://tailwindcss.com/docs/backdrop-hue-rotate
       */
      "backdrop-hue-rotate": [{
        "backdrop-hue-rotate": [isNumber, isArbitraryVariable, isArbitraryValue]
      }],
      /**
       * Backdrop Invert
       * @see https://tailwindcss.com/docs/backdrop-invert
       */
      "backdrop-invert": [{
        "backdrop-invert": ["", isNumber, isArbitraryVariable, isArbitraryValue]
      }],
      /**
       * Backdrop Opacity
       * @see https://tailwindcss.com/docs/backdrop-opacity
       */
      "backdrop-opacity": [{
        "backdrop-opacity": [isNumber, isArbitraryVariable, isArbitraryValue]
      }],
      /**
       * Backdrop Saturate
       * @see https://tailwindcss.com/docs/backdrop-saturate
       */
      "backdrop-saturate": [{
        "backdrop-saturate": [isNumber, isArbitraryVariable, isArbitraryValue]
      }],
      /**
       * Backdrop Sepia
       * @see https://tailwindcss.com/docs/backdrop-sepia
       */
      "backdrop-sepia": [{
        "backdrop-sepia": ["", isNumber, isArbitraryVariable, isArbitraryValue]
      }],
      // --------------
      // --- Tables ---
      // --------------
      /**
       * Border Collapse
       * @see https://tailwindcss.com/docs/border-collapse
       */
      "border-collapse": [{
        border: ["collapse", "separate"]
      }],
      /**
       * Border Spacing
       * @see https://tailwindcss.com/docs/border-spacing
       */
      "border-spacing": [{
        "border-spacing": scaleUnambiguousSpacing()
      }],
      /**
       * Border Spacing X
       * @see https://tailwindcss.com/docs/border-spacing
       */
      "border-spacing-x": [{
        "border-spacing-x": scaleUnambiguousSpacing()
      }],
      /**
       * Border Spacing Y
       * @see https://tailwindcss.com/docs/border-spacing
       */
      "border-spacing-y": [{
        "border-spacing-y": scaleUnambiguousSpacing()
      }],
      /**
       * Table Layout
       * @see https://tailwindcss.com/docs/table-layout
       */
      "table-layout": [{
        table: ["auto", "fixed"]
      }],
      /**
       * Caption Side
       * @see https://tailwindcss.com/docs/caption-side
       */
      caption: [{
        caption: ["top", "bottom"]
      }],
      // ---------------------------------
      // --- Transitions and Animation ---
      // ---------------------------------
      /**
       * Transition Property
       * @see https://tailwindcss.com/docs/transition-property
       */
      transition: [{
        transition: ["", "all", "colors", "opacity", "shadow", "transform", "none", isArbitraryVariable, isArbitraryValue]
      }],
      /**
       * Transition Behavior
       * @see https://tailwindcss.com/docs/transition-behavior
       */
      "transition-behavior": [{
        transition: ["normal", "discrete"]
      }],
      /**
       * Transition Duration
       * @see https://tailwindcss.com/docs/transition-duration
       */
      duration: [{
        duration: [isNumber, "initial", isArbitraryVariable, isArbitraryValue]
      }],
      /**
       * Transition Timing Function
       * @see https://tailwindcss.com/docs/transition-timing-function
       */
      ease: [{
        ease: ["linear", "initial", themeEase, isArbitraryVariable, isArbitraryValue]
      }],
      /**
       * Transition Delay
       * @see https://tailwindcss.com/docs/transition-delay
       */
      delay: [{
        delay: [isNumber, isArbitraryVariable, isArbitraryValue]
      }],
      /**
       * Animation
       * @see https://tailwindcss.com/docs/animation
       */
      animate: [{
        animate: ["none", themeAnimate, isArbitraryVariable, isArbitraryValue]
      }],
      // ------------------
      // --- Transforms ---
      // ------------------
      /**
       * Backface Visibility
       * @see https://tailwindcss.com/docs/backface-visibility
       */
      backface: [{
        backface: ["hidden", "visible"]
      }],
      /**
       * Perspective
       * @see https://tailwindcss.com/docs/perspective
       */
      perspective: [{
        perspective: [themePerspective, isArbitraryVariable, isArbitraryValue]
      }],
      /**
       * Perspective Origin
       * @see https://tailwindcss.com/docs/perspective-origin
       */
      "perspective-origin": [{
        "perspective-origin": scalePositionWithArbitrary()
      }],
      /**
       * Rotate
       * @see https://tailwindcss.com/docs/rotate
       */
      rotate: [{
        rotate: scaleRotate()
      }],
      /**
       * Rotate X
       * @see https://tailwindcss.com/docs/rotate
       */
      "rotate-x": [{
        "rotate-x": scaleRotate()
      }],
      /**
       * Rotate Y
       * @see https://tailwindcss.com/docs/rotate
       */
      "rotate-y": [{
        "rotate-y": scaleRotate()
      }],
      /**
       * Rotate Z
       * @see https://tailwindcss.com/docs/rotate
       */
      "rotate-z": [{
        "rotate-z": scaleRotate()
      }],
      /**
       * Scale
       * @see https://tailwindcss.com/docs/scale
       */
      scale: [{
        scale: scaleScale()
      }],
      /**
       * Scale X
       * @see https://tailwindcss.com/docs/scale
       */
      "scale-x": [{
        "scale-x": scaleScale()
      }],
      /**
       * Scale Y
       * @see https://tailwindcss.com/docs/scale
       */
      "scale-y": [{
        "scale-y": scaleScale()
      }],
      /**
       * Scale Z
       * @see https://tailwindcss.com/docs/scale
       */
      "scale-z": [{
        "scale-z": scaleScale()
      }],
      /**
       * Scale 3D
       * @see https://tailwindcss.com/docs/scale
       */
      "scale-3d": ["scale-3d"],
      /**
       * Skew
       * @see https://tailwindcss.com/docs/skew
       */
      skew: [{
        skew: scaleSkew()
      }],
      /**
       * Skew X
       * @see https://tailwindcss.com/docs/skew
       */
      "skew-x": [{
        "skew-x": scaleSkew()
      }],
      /**
       * Skew Y
       * @see https://tailwindcss.com/docs/skew
       */
      "skew-y": [{
        "skew-y": scaleSkew()
      }],
      /**
       * Transform
       * @see https://tailwindcss.com/docs/transform
       */
      transform: [{
        transform: [isArbitraryVariable, isArbitraryValue, "", "none", "gpu", "cpu"]
      }],
      /**
       * Transform Origin
       * @see https://tailwindcss.com/docs/transform-origin
       */
      "transform-origin": [{
        origin: scalePositionWithArbitrary()
      }],
      /**
       * Transform Style
       * @see https://tailwindcss.com/docs/transform-style
       */
      "transform-style": [{
        transform: ["3d", "flat"]
      }],
      /**
       * Translate
       * @see https://tailwindcss.com/docs/translate
       */
      translate: [{
        translate: scaleTranslate()
      }],
      /**
       * Translate X
       * @see https://tailwindcss.com/docs/translate
       */
      "translate-x": [{
        "translate-x": scaleTranslate()
      }],
      /**
       * Translate Y
       * @see https://tailwindcss.com/docs/translate
       */
      "translate-y": [{
        "translate-y": scaleTranslate()
      }],
      /**
       * Translate Z
       * @see https://tailwindcss.com/docs/translate
       */
      "translate-z": [{
        "translate-z": scaleTranslate()
      }],
      /**
       * Translate None
       * @see https://tailwindcss.com/docs/translate
       */
      "translate-none": ["translate-none"],
      // ---------------------
      // --- Interactivity ---
      // ---------------------
      /**
       * Accent Color
       * @see https://tailwindcss.com/docs/accent-color
       */
      accent: [{
        accent: scaleColor()
      }],
      /**
       * Appearance
       * @see https://tailwindcss.com/docs/appearance
       */
      appearance: [{
        appearance: ["none", "auto"]
      }],
      /**
       * Caret Color
       * @see https://tailwindcss.com/docs/just-in-time-mode#caret-color-utilities
       */
      "caret-color": [{
        caret: scaleColor()
      }],
      /**
       * Color Scheme
       * @see https://tailwindcss.com/docs/color-scheme
       */
      "color-scheme": [{
        scheme: ["normal", "dark", "light", "light-dark", "only-dark", "only-light"]
      }],
      /**
       * Cursor
       * @see https://tailwindcss.com/docs/cursor
       */
      cursor: [{
        cursor: ["auto", "default", "pointer", "wait", "text", "move", "help", "not-allowed", "none", "context-menu", "progress", "cell", "crosshair", "vertical-text", "alias", "copy", "no-drop", "grab", "grabbing", "all-scroll", "col-resize", "row-resize", "n-resize", "e-resize", "s-resize", "w-resize", "ne-resize", "nw-resize", "se-resize", "sw-resize", "ew-resize", "ns-resize", "nesw-resize", "nwse-resize", "zoom-in", "zoom-out", isArbitraryVariable, isArbitraryValue]
      }],
      /**
       * Field Sizing
       * @see https://tailwindcss.com/docs/field-sizing
       */
      "field-sizing": [{
        "field-sizing": ["fixed", "content"]
      }],
      /**
       * Pointer Events
       * @see https://tailwindcss.com/docs/pointer-events
       */
      "pointer-events": [{
        "pointer-events": ["auto", "none"]
      }],
      /**
       * Resize
       * @see https://tailwindcss.com/docs/resize
       */
      resize: [{
        resize: ["none", "", "y", "x"]
      }],
      /**
       * Scroll Behavior
       * @see https://tailwindcss.com/docs/scroll-behavior
       */
      "scroll-behavior": [{
        scroll: ["auto", "smooth"]
      }],
      /**
       * Scroll Margin
       * @see https://tailwindcss.com/docs/scroll-margin
       */
      "scroll-m": [{
        "scroll-m": scaleUnambiguousSpacing()
      }],
      /**
       * Scroll Margin X
       * @see https://tailwindcss.com/docs/scroll-margin
       */
      "scroll-mx": [{
        "scroll-mx": scaleUnambiguousSpacing()
      }],
      /**
       * Scroll Margin Y
       * @see https://tailwindcss.com/docs/scroll-margin
       */
      "scroll-my": [{
        "scroll-my": scaleUnambiguousSpacing()
      }],
      /**
       * Scroll Margin Start
       * @see https://tailwindcss.com/docs/scroll-margin
       */
      "scroll-ms": [{
        "scroll-ms": scaleUnambiguousSpacing()
      }],
      /**
       * Scroll Margin End
       * @see https://tailwindcss.com/docs/scroll-margin
       */
      "scroll-me": [{
        "scroll-me": scaleUnambiguousSpacing()
      }],
      /**
       * Scroll Margin Top
       * @see https://tailwindcss.com/docs/scroll-margin
       */
      "scroll-mt": [{
        "scroll-mt": scaleUnambiguousSpacing()
      }],
      /**
       * Scroll Margin Right
       * @see https://tailwindcss.com/docs/scroll-margin
       */
      "scroll-mr": [{
        "scroll-mr": scaleUnambiguousSpacing()
      }],
      /**
       * Scroll Margin Bottom
       * @see https://tailwindcss.com/docs/scroll-margin
       */
      "scroll-mb": [{
        "scroll-mb": scaleUnambiguousSpacing()
      }],
      /**
       * Scroll Margin Left
       * @see https://tailwindcss.com/docs/scroll-margin
       */
      "scroll-ml": [{
        "scroll-ml": scaleUnambiguousSpacing()
      }],
      /**
       * Scroll Padding
       * @see https://tailwindcss.com/docs/scroll-padding
       */
      "scroll-p": [{
        "scroll-p": scaleUnambiguousSpacing()
      }],
      /**
       * Scroll Padding X
       * @see https://tailwindcss.com/docs/scroll-padding
       */
      "scroll-px": [{
        "scroll-px": scaleUnambiguousSpacing()
      }],
      /**
       * Scroll Padding Y
       * @see https://tailwindcss.com/docs/scroll-padding
       */
      "scroll-py": [{
        "scroll-py": scaleUnambiguousSpacing()
      }],
      /**
       * Scroll Padding Start
       * @see https://tailwindcss.com/docs/scroll-padding
       */
      "scroll-ps": [{
        "scroll-ps": scaleUnambiguousSpacing()
      }],
      /**
       * Scroll Padding End
       * @see https://tailwindcss.com/docs/scroll-padding
       */
      "scroll-pe": [{
        "scroll-pe": scaleUnambiguousSpacing()
      }],
      /**
       * Scroll Padding Top
       * @see https://tailwindcss.com/docs/scroll-padding
       */
      "scroll-pt": [{
        "scroll-pt": scaleUnambiguousSpacing()
      }],
      /**
       * Scroll Padding Right
       * @see https://tailwindcss.com/docs/scroll-padding
       */
      "scroll-pr": [{
        "scroll-pr": scaleUnambiguousSpacing()
      }],
      /**
       * Scroll Padding Bottom
       * @see https://tailwindcss.com/docs/scroll-padding
       */
      "scroll-pb": [{
        "scroll-pb": scaleUnambiguousSpacing()
      }],
      /**
       * Scroll Padding Left
       * @see https://tailwindcss.com/docs/scroll-padding
       */
      "scroll-pl": [{
        "scroll-pl": scaleUnambiguousSpacing()
      }],
      /**
       * Scroll Snap Align
       * @see https://tailwindcss.com/docs/scroll-snap-align
       */
      "snap-align": [{
        snap: ["start", "end", "center", "align-none"]
      }],
      /**
       * Scroll Snap Stop
       * @see https://tailwindcss.com/docs/scroll-snap-stop
       */
      "snap-stop": [{
        snap: ["normal", "always"]
      }],
      /**
       * Scroll Snap Type
       * @see https://tailwindcss.com/docs/scroll-snap-type
       */
      "snap-type": [{
        snap: ["none", "x", "y", "both"]
      }],
      /**
       * Scroll Snap Type Strictness
       * @see https://tailwindcss.com/docs/scroll-snap-type
       */
      "snap-strictness": [{
        snap: ["mandatory", "proximity"]
      }],
      /**
       * Touch Action
       * @see https://tailwindcss.com/docs/touch-action
       */
      touch: [{
        touch: ["auto", "none", "manipulation"]
      }],
      /**
       * Touch Action X
       * @see https://tailwindcss.com/docs/touch-action
       */
      "touch-x": [{
        "touch-pan": ["x", "left", "right"]
      }],
      /**
       * Touch Action Y
       * @see https://tailwindcss.com/docs/touch-action
       */
      "touch-y": [{
        "touch-pan": ["y", "up", "down"]
      }],
      /**
       * Touch Action Pinch Zoom
       * @see https://tailwindcss.com/docs/touch-action
       */
      "touch-pz": ["touch-pinch-zoom"],
      /**
       * User Select
       * @see https://tailwindcss.com/docs/user-select
       */
      select: [{
        select: ["none", "text", "all", "auto"]
      }],
      /**
       * Will Change
       * @see https://tailwindcss.com/docs/will-change
       */
      "will-change": [{
        "will-change": ["auto", "scroll", "contents", "transform", isArbitraryVariable, isArbitraryValue]
      }],
      // -----------
      // --- SVG ---
      // -----------
      /**
       * Fill
       * @see https://tailwindcss.com/docs/fill
       */
      fill: [{
        fill: ["none", ...scaleColor()]
      }],
      /**
       * Stroke Width
       * @see https://tailwindcss.com/docs/stroke-width
       */
      "stroke-w": [{
        stroke: [isNumber, isArbitraryVariableLength, isArbitraryLength, isArbitraryNumber]
      }],
      /**
       * Stroke
       * @see https://tailwindcss.com/docs/stroke
       */
      stroke: [{
        stroke: ["none", ...scaleColor()]
      }],
      // ---------------------
      // --- Accessibility ---
      // ---------------------
      /**
       * Forced Color Adjust
       * @see https://tailwindcss.com/docs/forced-color-adjust
       */
      "forced-color-adjust": [{
        "forced-color-adjust": ["auto", "none"]
      }]
    },
    conflictingClassGroups: {
      overflow: ["overflow-x", "overflow-y"],
      overscroll: ["overscroll-x", "overscroll-y"],
      inset: ["inset-x", "inset-y", "start", "end", "top", "right", "bottom", "left"],
      "inset-x": ["right", "left"],
      "inset-y": ["top", "bottom"],
      flex: ["basis", "grow", "shrink"],
      gap: ["gap-x", "gap-y"],
      p: ["px", "py", "ps", "pe", "pt", "pr", "pb", "pl"],
      px: ["pr", "pl"],
      py: ["pt", "pb"],
      m: ["mx", "my", "ms", "me", "mt", "mr", "mb", "ml"],
      mx: ["mr", "ml"],
      my: ["mt", "mb"],
      size: ["w", "h"],
      "font-size": ["leading"],
      "fvn-normal": ["fvn-ordinal", "fvn-slashed-zero", "fvn-figure", "fvn-spacing", "fvn-fraction"],
      "fvn-ordinal": ["fvn-normal"],
      "fvn-slashed-zero": ["fvn-normal"],
      "fvn-figure": ["fvn-normal"],
      "fvn-spacing": ["fvn-normal"],
      "fvn-fraction": ["fvn-normal"],
      "line-clamp": ["display", "overflow"],
      rounded: ["rounded-s", "rounded-e", "rounded-t", "rounded-r", "rounded-b", "rounded-l", "rounded-ss", "rounded-se", "rounded-ee", "rounded-es", "rounded-tl", "rounded-tr", "rounded-br", "rounded-bl"],
      "rounded-s": ["rounded-ss", "rounded-es"],
      "rounded-e": ["rounded-se", "rounded-ee"],
      "rounded-t": ["rounded-tl", "rounded-tr"],
      "rounded-r": ["rounded-tr", "rounded-br"],
      "rounded-b": ["rounded-br", "rounded-bl"],
      "rounded-l": ["rounded-tl", "rounded-bl"],
      "border-spacing": ["border-spacing-x", "border-spacing-y"],
      "border-w": ["border-w-x", "border-w-y", "border-w-s", "border-w-e", "border-w-t", "border-w-r", "border-w-b", "border-w-l"],
      "border-w-x": ["border-w-r", "border-w-l"],
      "border-w-y": ["border-w-t", "border-w-b"],
      "border-color": ["border-color-x", "border-color-y", "border-color-s", "border-color-e", "border-color-t", "border-color-r", "border-color-b", "border-color-l"],
      "border-color-x": ["border-color-r", "border-color-l"],
      "border-color-y": ["border-color-t", "border-color-b"],
      translate: ["translate-x", "translate-y", "translate-none"],
      "translate-none": ["translate", "translate-x", "translate-y", "translate-z"],
      "scroll-m": ["scroll-mx", "scroll-my", "scroll-ms", "scroll-me", "scroll-mt", "scroll-mr", "scroll-mb", "scroll-ml"],
      "scroll-mx": ["scroll-mr", "scroll-ml"],
      "scroll-my": ["scroll-mt", "scroll-mb"],
      "scroll-p": ["scroll-px", "scroll-py", "scroll-ps", "scroll-pe", "scroll-pt", "scroll-pr", "scroll-pb", "scroll-pl"],
      "scroll-px": ["scroll-pr", "scroll-pl"],
      "scroll-py": ["scroll-pt", "scroll-pb"],
      touch: ["touch-x", "touch-y", "touch-pz"],
      "touch-x": ["touch"],
      "touch-y": ["touch"],
      "touch-pz": ["touch"]
    },
    conflictingClassGroupModifiers: {
      "font-size": ["leading"]
    },
    orderSensitiveModifiers: ["*", "**", "after", "backdrop", "before", "details-content", "file", "first-letter", "first-line", "marker", "placeholder", "selection"]
  };
}, "getDefaultConfig");
const mergeConfigs = /* @__PURE__ */ __name((baseConfig, {
  cacheSize,
  prefix,
  experimentalParseClassName,
  extend = {},
  override = {}
}) => {
  overrideProperty(baseConfig, "cacheSize", cacheSize);
  overrideProperty(baseConfig, "prefix", prefix);
  overrideProperty(baseConfig, "experimentalParseClassName", experimentalParseClassName);
  overrideConfigProperties(baseConfig.theme, override.theme);
  overrideConfigProperties(baseConfig.classGroups, override.classGroups);
  overrideConfigProperties(baseConfig.conflictingClassGroups, override.conflictingClassGroups);
  overrideConfigProperties(baseConfig.conflictingClassGroupModifiers, override.conflictingClassGroupModifiers);
  overrideProperty(baseConfig, "orderSensitiveModifiers", override.orderSensitiveModifiers);
  mergeConfigProperties(baseConfig.theme, extend.theme);
  mergeConfigProperties(baseConfig.classGroups, extend.classGroups);
  mergeConfigProperties(baseConfig.conflictingClassGroups, extend.conflictingClassGroups);
  mergeConfigProperties(baseConfig.conflictingClassGroupModifiers, extend.conflictingClassGroupModifiers);
  mergeArrayProperties(baseConfig, extend, "orderSensitiveModifiers");
  return baseConfig;
}, "mergeConfigs");
const overrideProperty = /* @__PURE__ */ __name((baseObject, overrideKey, overrideValue) => {
  if (overrideValue !== void 0) {
    baseObject[overrideKey] = overrideValue;
  }
}, "overrideProperty");
const overrideConfigProperties = /* @__PURE__ */ __name((baseObject, overrideObject) => {
  if (overrideObject) {
    for (const key in overrideObject) {
      overrideProperty(baseObject, key, overrideObject[key]);
    }
  }
}, "overrideConfigProperties");
const mergeConfigProperties = /* @__PURE__ */ __name((baseObject, mergeObject) => {
  if (mergeObject) {
    for (const key in mergeObject) {
      mergeArrayProperties(baseObject, mergeObject, key);
    }
  }
}, "mergeConfigProperties");
const mergeArrayProperties = /* @__PURE__ */ __name((baseObject, mergeObject, key) => {
  const mergeValue = mergeObject[key];
  if (mergeValue !== void 0) {
    baseObject[key] = baseObject[key] ? baseObject[key].concat(mergeValue) : mergeValue;
  }
}, "mergeArrayProperties");
const extendTailwindMerge = /* @__PURE__ */ __name((configExtension, ...createConfig) => typeof configExtension === "function" ? createTailwindMerge(getDefaultConfig, configExtension, ...createConfig) : createTailwindMerge(() => mergeConfigs(getDefaultConfig(), configExtension), ...createConfig), "extendTailwindMerge");
const twMerge = /* @__PURE__ */ createTailwindMerge(getDefaultConfig);
function cn(...inputs) {
  return twMerge(clsx(inputs));
}
__name(cn, "cn");
const _hoisted_1$T = {
  key: 0,
  class: "node-error p-2 text-red-500 text-sm"
};
const _hoisted_2$q = {
  key: 1,
  class: "lg-node-content"
};
const _sfc_main$S = /* @__PURE__ */ defineComponent({
  __name: "NodeContent",
  props: {
    node: {},
    nodeData: {},
    readonly: { type: Boolean },
    lodLevel: {}
  },
  setup(__props) {
    const renderError = ref(null);
    const { toastErrorHandler } = useErrorHandling();
    onErrorCaptured((error) => {
      renderError.value = error.message;
      toastErrorHandler(error);
      return false;
    });
    return (_ctx, _cache) => {
      return renderError.value ? (openBlock(), createElementBlock("div", _hoisted_1$T, toDisplayString(_ctx.$t("Node Content Error")), 1)) : (openBlock(), createElementBlock("div", _hoisted_2$q, [
        renderSlot(_ctx.$slots, "default")
      ]));
    };
  }
});
const _hoisted_1$S = {
  key: 0,
  class: "node-error p-4 text-red-500 text-sm"
};
const _hoisted_2$p = ["data-testid"];
const _hoisted_3$f = {
  class: "text-sm font-bold truncate flex-1",
  "data-testid": "node-title"
};
const _sfc_main$R = /* @__PURE__ */ defineComponent({
  __name: "NodeHeader",
  props: {
    node: {},
    nodeData: {},
    readonly: { type: Boolean },
    lodLevel: {},
    collapsed: { type: Boolean }
  },
  emits: ["collapse", "update:title"],
  setup(__props, { emit: __emit }) {
    const props = __props;
    const emit = __emit;
    const renderError = ref(null);
    const { toastErrorHandler } = useErrorHandling();
    onErrorCaptured((error) => {
      renderError.value = error.message;
      toastErrorHandler(error);
      return false;
    });
    const isEditing = ref(false);
    const nodeInfo = computed(() => props.nodeData || props.node);
    const displayTitle = ref(nodeInfo.value?.title || "Untitled");
    watch(
      () => nodeInfo.value?.title,
      (newTitle) => {
        if (newTitle && newTitle !== displayTitle.value) {
          displayTitle.value = newTitle;
        }
      }
    );
    const handleCollapse = /* @__PURE__ */ __name(() => {
      emit("collapse");
    }, "handleCollapse");
    const handleDoubleClick = /* @__PURE__ */ __name(() => {
      if (!props.readonly) {
        isEditing.value = true;
      }
    }, "handleDoubleClick");
    const handleTitleEdit = /* @__PURE__ */ __name((newTitle) => {
      isEditing.value = false;
      const trimmedTitle = newTitle.trim();
      if (trimmedTitle && trimmedTitle !== displayTitle.value) {
        emit("update:title", trimmedTitle);
      }
    }, "handleTitleEdit");
    const handleTitleCancel = /* @__PURE__ */ __name(() => {
      isEditing.value = false;
      displayTitle.value = nodeInfo.value?.title || "Untitled";
    }, "handleTitleCancel");
    return (_ctx, _cache) => {
      return renderError.value ? (openBlock(), createElementBlock("div", _hoisted_1$S, toDisplayString(_ctx.$t("Node Header Error")), 1)) : (openBlock(), createElementBlock("div", {
        key: 1,
        class: "lg-node-header flex items-center justify-between p-4 rounded-t-2xl cursor-move",
        "data-testid": `node-header-${nodeInfo.value?.id || ""}`,
        onDblclick: handleDoubleClick
      }, [
        withDirectives(createElementVNode("button", {
          class: "bg-transparent border-transparent flex items-center",
          "data-testid": "node-collapse-button",
          onClick: withModifiers(handleCollapse, ["stop"]),
          onDblclick: _cache[0] || (_cache[0] = withModifiers(() => {
          }, ["stop"]))
        }, [
          createElementVNode("i", {
            class: normalizeClass([_ctx.collapsed ? "pi pi-chevron-right" : "pi pi-chevron-down", "text-xs leading-none relative top-[1px] text-[#888682] dark-theme:text-[#5B5E7D]"])
          }, null, 2)
        ], 544), [
          [vShow, !_ctx.readonly]
        ]),
        createElementVNode("div", _hoisted_3$f, [
          createVNode(EditableText, {
            "model-value": displayTitle.value,
            "is-editing": isEditing.value,
            "input-attrs": { "data-testid": "node-title-input" },
            onEdit: handleTitleEdit,
            onCancel: handleTitleCancel
          }, null, 8, ["model-value", "is-editing"])
        ])
      ], 40, _hoisted_2$p));
    };
  }
});
const SLOT_TYPE_COLORS = {
  number: "#AAD",
  string: "#DCA",
  boolean: "#DAA",
  vec2: "#ADA",
  vec3: "#ADA",
  vec4: "#ADA",
  color: "#DDA",
  image: "#353",
  latent: "#858",
  conditioning: "#FFA",
  control_net: "#F8F",
  clip: "#FFD",
  vae: "#F82",
  model: "#B98",
  "*": "#AAA"
  // Default color
};
function getSlotColor(type) {
  if (!type) return SLOT_TYPE_COLORS["*"];
  const typeStr = String(type).toLowerCase();
  return SLOT_TYPE_COLORS[typeStr] || SLOT_TYPE_COLORS["*"];
}
__name(getSlotColor, "getSlotColor");
const measureQueue = /* @__PURE__ */ new Set();
let rafId = null;
const mountedComponents = /* @__PURE__ */ new WeakSet();
function scheduleMeasurement(fn) {
  measureQueue.add(fn);
  if (rafId === null) {
    rafId = requestAnimationFrame(() => {
      rafId = null;
      const batch = Array.from(measureQueue);
      measureQueue.clear();
      batch.forEach((measure) => measure());
    });
  }
}
__name(scheduleMeasurement, "scheduleMeasurement");
const cleanupFunctions = /* @__PURE__ */ new WeakMap();
function useDomSlotRegistration(options) {
  const { nodeId, slotIndex, isInput, element: elRef, transform } = options;
  if (!nodeId || nodeId === "") {
    return {
      remeasure: /* @__PURE__ */ __name(() => {
      }, "remeasure")
    };
  }
  const slotKey = getSlotKey(nodeId, slotIndex, isInput);
  const componentToken = {};
  const cachedOffset = ref(null);
  const lastMeasuredBounds = ref(null);
  const measureAndCacheOffset = /* @__PURE__ */ __name(() => {
    if (!mountedComponents.has(componentToken)) return;
    const el = elRef.value;
    if (!el || !transform?.screenToCanvas) return;
    const rect = el.getBoundingClientRect();
    if (lastMeasuredBounds.value) {
      const prev = lastMeasuredBounds.value;
      if (Math.abs(rect.left - prev.left) < 0.5 && Math.abs(rect.top - prev.top) < 0.5 && Math.abs(rect.width - prev.width) < 0.5 && Math.abs(rect.height - prev.height) < 0.5) {
        return;
      }
    }
    lastMeasuredBounds.value = rect;
    const centerScreen = {
      x: rect.left + rect.width / 2,
      y: rect.top + rect.height / 2
    };
    const centerCanvas = transform.screenToCanvas(centerScreen);
    const nodeLayout = layoutStore.getNodeLayoutRef(nodeId).value;
    if (nodeLayout) {
      cachedOffset.value = {
        x: centerCanvas.x - nodeLayout.position.x,
        y: centerCanvas.y - nodeLayout.position.y
      };
    }
    updateSlotPosition(centerCanvas);
  }, "measureAndCacheOffset");
  const updateFromCachedOffset = /* @__PURE__ */ __name(() => {
    if (!cachedOffset.value) {
      scheduleMeasurement(measureAndCacheOffset);
      return;
    }
    const nodeLayout = layoutStore.getNodeLayoutRef(nodeId).value;
    if (!nodeLayout) {
      return;
    }
    const centerCanvas = {
      x: nodeLayout.position.x + cachedOffset.value.x,
      y: nodeLayout.position.y + cachedOffset.value.y
    };
    updateSlotPosition(centerCanvas);
  }, "updateFromCachedOffset");
  const updateSlotPosition = /* @__PURE__ */ __name((centerCanvas) => {
    const size = LiteGraph.NODE_SLOT_HEIGHT;
    const half = size / 2;
    layoutStore.updateSlotLayout(slotKey, {
      nodeId,
      index: slotIndex,
      type: isInput ? "input" : "output",
      position: { x: centerCanvas.x, y: centerCanvas.y },
      bounds: {
        x: centerCanvas.x - half,
        y: centerCanvas.y - half,
        width: size,
        height: size
      }
    });
  }, "updateSlotPosition");
  onMounted(async () => {
    mountedComponents.add(componentToken);
    await nextTick();
    measureAndCacheOffset();
    const nodeRef = layoutStore.getNodeLayoutRef(nodeId);
    const stopWatcher = watch(
      nodeRef,
      (newLayout) => {
        if (newLayout) {
          updateFromCachedOffset();
        }
      },
      { immediate: false }
    );
    const cleanup = cleanupFunctions.get(elRef) || {};
    cleanup.stopWatcher = stopWatcher;
    const handleResize = /* @__PURE__ */ __name(() => {
      scheduleMeasurement(measureAndCacheOffset);
    }, "handleResize");
    window.addEventListener("resize", handleResize, { passive: true });
    cleanup.handleResize = handleResize;
    cleanupFunctions.set(elRef, cleanup);
  });
  onUnmounted(() => {
    mountedComponents.delete(componentToken);
    const cleanup = cleanupFunctions.get(elRef);
    if (cleanup) {
      if (cleanup.stopWatcher) cleanup.stopWatcher();
      if (cleanup.handleResize) {
        window.removeEventListener("resize", cleanup.handleResize);
      }
      cleanupFunctions.delete(elRef);
    }
    layoutStore.deleteSlotLayout(slotKey);
    measureQueue.delete(measureAndCacheOffset);
  });
  return {
    // Expose for forced remeasure on structural changes
    remeasure: /* @__PURE__ */ __name(() => scheduleMeasurement(measureAndCacheOffset), "remeasure")
  };
}
__name(useDomSlotRegistration, "useDomSlotRegistration");
const _sfc_main$Q = /* @__PURE__ */ defineComponent({
  __name: "SlotConnectionDot",
  props: {
    color: {},
    multi: { type: Boolean },
    class: { type: [Array, Object, String, Number, null, Boolean] }
  },
  setup(__props, { expose: __expose }) {
    const props = __props;
    const slotElRef = useTemplateRef("slot-el");
    __expose({
      slotElRef
    });
    return (_ctx, _cache) => {
      return openBlock(), createElementBlock("div", {
        class: normalizeClass(
          unref(cn)("size-6 flex items-center justify-center group/slot", props.class)
        )
      }, [
        createElementVNode("div", {
          ref: "slot-el",
          style: normalizeStyle({ backgroundColor: _ctx.color }),
          class: normalizeClass(
            unref(cn)(
              "bg-[#5B5E7D] rounded-full",
              "transition-all duration-150",
              "cursor-crosshair",
              "border border-solid border-black/5 dark-theme:border-white/10",
              "group-hover/slot:border-black/20 dark-theme:group-hover/slot:border-white/50 group-hover/slot:scale-125",
              _ctx.multi ? "w-3 h-6" : "size-3"
            )
          )
        }, null, 6)
      ], 2);
    };
  }
});
const _hoisted_1$R = {
  key: 0,
  class: "node-error p-1 text-red-500 text-xs"
};
const _hoisted_2$o = {
  key: 0,
  class: "whitespace-nowrap text-sm font-normal dark-theme:text-[#9FA2BD] text-[#888682]"
};
const _sfc_main$P = /* @__PURE__ */ defineComponent({
  __name: "InputSlot",
  props: {
    node: {},
    nodeId: {},
    slotData: {},
    index: {},
    connected: { type: Boolean },
    compatible: { type: Boolean },
    readonly: { type: Boolean },
    dotOnly: { type: Boolean }
  },
  setup(__props) {
    const props = __props;
    const renderError = ref(null);
    const { toastErrorHandler } = useErrorHandling();
    onErrorCaptured((error) => {
      renderError.value = error.message;
      toastErrorHandler(error);
      return false;
    });
    const slotColor = computed(() => getSlotColor(props.slotData.type));
    const slotHeight = COMFY_VUE_NODE_DIMENSIONS.components.SLOT_HEIGHT;
    const transformState = inject(
      "transformState",
      void 0
    );
    const connectionDotRef = ref();
    const slotElRef = ref(null);
    watch(
      connectionDotRef,
      (newValue) => {
        if (newValue?.slotElRef) {
          slotElRef.value = newValue.slotElRef.value;
        }
      },
      { immediate: true }
    );
    useDomSlotRegistration({
      nodeId: props.nodeId ?? "",
      slotIndex: props.index,
      isInput: true,
      element: slotElRef,
      transform: transformState
    });
    return (_ctx, _cache) => {
      return renderError.value ? (openBlock(), createElementBlock("div", _hoisted_1$R, "⚠️")) : (openBlock(), createElementBlock("div", {
        key: 1,
        class: normalizeClass(["lg-slot lg-slot--input flex items-center cursor-crosshair group rounded-r-lg", {
          "opacity-70": _ctx.readonly,
          "lg-slot--connected": _ctx.connected,
          "lg-slot--compatible": _ctx.compatible,
          "lg-slot--dot-only": _ctx.dotOnly,
          "pr-6 hover:bg-black/5 hover:dark:bg-white/5": !_ctx.dotOnly
        }]),
        style: normalizeStyle({
          height: unref(slotHeight) + "px"
        })
      }, [
        createVNode(_sfc_main$Q, {
          ref_key: "connectionDotRef",
          ref: connectionDotRef,
          color: slotColor.value,
          class: "-translate-x-1/2"
        }, null, 8, ["color"]),
        !_ctx.dotOnly ? (openBlock(), createElementBlock("span", _hoisted_2$o, toDisplayString(_ctx.slotData.localized_name || _ctx.slotData.name || `Input ${_ctx.index}`), 1)) : createCommentVNode("", true)
      ], 6));
    };
  }
});
const _hoisted_1$Q = {
  key: 0,
  class: "node-error p-1 text-red-500 text-xs"
};
const _hoisted_2$n = {
  key: 0,
  class: "whitespace-nowrap text-sm font-normal dark-theme:text-[#9FA2BD] text-[#888682]"
};
const _sfc_main$O = /* @__PURE__ */ defineComponent({
  __name: "OutputSlot",
  props: {
    node: {},
    nodeId: {},
    slotData: {},
    index: {},
    connected: { type: Boolean },
    compatible: { type: Boolean },
    readonly: { type: Boolean },
    dotOnly: { type: Boolean }
  },
  setup(__props) {
    const props = __props;
    const renderError = ref(null);
    const { toastErrorHandler } = useErrorHandling();
    onErrorCaptured((error) => {
      renderError.value = error.message;
      toastErrorHandler(error);
      return false;
    });
    const slotColor = computed(() => getSlotColor(props.slotData.type));
    const slotHeight = COMFY_VUE_NODE_DIMENSIONS.components.SLOT_HEIGHT;
    const transformState = inject(
      "transformState",
      void 0
    );
    const connectionDotRef = ref();
    const slotElRef = ref(null);
    watch(
      connectionDotRef,
      (newValue) => {
        if (newValue?.slotElRef) {
          slotElRef.value = newValue.slotElRef.value;
        }
      },
      { immediate: true }
    );
    useDomSlotRegistration({
      nodeId: props.nodeId ?? "",
      slotIndex: props.index,
      isInput: false,
      element: slotElRef,
      transform: transformState
    });
    return (_ctx, _cache) => {
      return renderError.value ? (openBlock(), createElementBlock("div", _hoisted_1$Q, "⚠️")) : (openBlock(), createElementBlock("div", {
        key: 1,
        class: normalizeClass(["lg-slot lg-slot--output flex items-center cursor-crosshair justify-end group rounded-l-lg", {
          "opacity-70": _ctx.readonly,
          "lg-slot--connected": _ctx.connected,
          "lg-slot--compatible": _ctx.compatible,
          "lg-slot--dot-only": _ctx.dotOnly,
          "pl-6 hover:bg-black/5 hover:dark:bg-white/5": !_ctx.dotOnly,
          "justify-center": _ctx.dotOnly
        }]),
        style: normalizeStyle({
          height: unref(slotHeight) + "px"
        })
      }, [
        !_ctx.dotOnly ? (openBlock(), createElementBlock("span", _hoisted_2$n, toDisplayString(_ctx.slotData.name || `Output ${_ctx.index}`), 1)) : createCommentVNode("", true),
        createVNode(_sfc_main$Q, {
          ref_key: "connectionDotRef",
          ref: connectionDotRef,
          color: slotColor.value,
          class: "translate-x-1/2"
        }, null, 8, ["color"])
      ], 6));
    };
  }
});
const _hoisted_1$P = {
  key: 0,
  class: "node-error p-2 text-red-500 text-sm"
};
const _hoisted_2$m = {
  key: 1,
  class: "lg-node-slots flex justify-between"
};
const _hoisted_3$e = {
  key: 0,
  class: "flex flex-col gap-1"
};
const _hoisted_4$c = {
  key: 1,
  class: "flex flex-col gap-1 ml-auto"
};
const _sfc_main$N = /* @__PURE__ */ defineComponent({
  __name: "NodeSlots",
  props: {
    node: {},
    nodeData: {},
    readonly: { type: Boolean },
    lodLevel: {}
  },
  setup(__props) {
    const props = __props;
    const nodeInfo = computed(() => props.nodeData || props.node || null);
    const filteredInputs = computed(() => {
      if (!nodeInfo.value?.inputs) return [];
      return nodeInfo.value.inputs.filter((input) => {
        if (isSlotObject(input) && "widget" in input && input.widget) {
          return false;
        }
        return true;
      }).map(
        (input) => isSlotObject(input) ? input : {
          name: typeof input === "string" ? input : "",
          type: "any",
          boundingRect: [0, 0, 0, 0]
        }
      );
    });
    const filteredOutputs = computed(() => {
      const outputs = nodeInfo.value?.outputs || [];
      return outputs.map(
        (output) => isSlotObject(output) ? output : {
          name: typeof output === "string" ? output : "",
          type: "any",
          boundingRect: [0, 0, 0, 0]
        }
      );
    });
    const getActualInputIndex = /* @__PURE__ */ __name((input, filteredIndex) => {
      if (!nodeInfo.value?.inputs) return filteredIndex;
      const actualIndex = nodeInfo.value.inputs.findIndex((i) => i === input);
      return actualIndex !== -1 ? actualIndex : filteredIndex;
    }, "getActualInputIndex");
    const renderError = ref(null);
    const { toastErrorHandler } = useErrorHandling();
    onErrorCaptured((error) => {
      renderError.value = error.message;
      toastErrorHandler(error);
      return false;
    });
    return (_ctx, _cache) => {
      return renderError.value ? (openBlock(), createElementBlock("div", _hoisted_1$P, toDisplayString(_ctx.$t("Node Slots Error")), 1)) : (openBlock(), createElementBlock("div", _hoisted_2$m, [
        filteredInputs.value.length ? (openBlock(), createElementBlock("div", _hoisted_3$e, [
          (openBlock(true), createElementBlock(Fragment, null, renderList(filteredInputs.value, (input, index) => {
            return openBlock(), createBlock(_sfc_main$P, {
              key: `input-${index}`,
              "slot-data": input,
              "node-id": nodeInfo.value?.id != null ? String(nodeInfo.value.id) : "",
              index: getActualInputIndex(input, index),
              readonly: _ctx.readonly
            }, null, 8, ["slot-data", "node-id", "index", "readonly"]);
          }), 128))
        ])) : createCommentVNode("", true),
        filteredOutputs.value.length ? (openBlock(), createElementBlock("div", _hoisted_4$c, [
          (openBlock(true), createElementBlock(Fragment, null, renderList(filteredOutputs.value, (output, index) => {
            return openBlock(), createBlock(_sfc_main$O, {
              key: `output-${index}`,
              "slot-data": output,
              "node-id": nodeInfo.value?.id != null ? String(nodeInfo.value.id) : "",
              index,
              readonly: _ctx.readonly
            }, null, 8, ["slot-data", "node-id", "index", "readonly"]);
          }), 128))
        ])) : createCommentVNode("", true)
      ]));
    };
  }
});
function useWidgetValue({
  widget,
  modelValue,
  defaultValue,
  emit,
  transform
}) {
  const localValue = ref(modelValue ?? defaultValue);
  const onChange = /* @__PURE__ */ __name((newValue) => {
    let processedValue;
    if (transform) {
      processedValue = transform(newValue);
    } else {
      if (typeof newValue === typeof defaultValue || newValue === null || newValue === void 0) {
        processedValue = newValue ?? defaultValue;
      } else {
        console.warn(
          `useWidgetValue: Type mismatch for widget ${widget.name}. Expected ${typeof defaultValue}, got ${typeof newValue}`
        );
        processedValue = defaultValue;
      }
    }
    localValue.value = processedValue;
    emit("update:modelValue", processedValue);
  }, "onChange");
  watch(
    () => modelValue,
    (newValue) => {
      localValue.value = newValue ?? defaultValue;
    }
  );
  return {
    localValue,
    onChange
  };
}
__name(useWidgetValue, "useWidgetValue");
function useStringWidgetValue(widget, modelValue, emit) {
  return useWidgetValue({
    widget,
    modelValue,
    defaultValue: "",
    emit,
    transform: /* @__PURE__ */ __name((value) => String(value || ""), "transform")
    // Handle undefined from PrimeVue
  });
}
__name(useStringWidgetValue, "useStringWidgetValue");
function useNumberWidgetValue(widget, modelValue, emit) {
  return useWidgetValue({
    widget,
    modelValue,
    defaultValue: 0,
    emit,
    transform: /* @__PURE__ */ __name((value) => {
      if (Array.isArray(value)) {
        return value.length > 0 ? value[0] ?? 0 : 0;
      }
      return Number(value) || 0;
    }, "transform")
  });
}
__name(useNumberWidgetValue, "useNumberWidgetValue");
function useBooleanWidgetValue(widget, modelValue, emit) {
  return useWidgetValue({
    widget,
    modelValue,
    defaultValue: false,
    emit,
    transform: /* @__PURE__ */ __name((value) => Boolean(value), "transform")
  });
}
__name(useBooleanWidgetValue, "useBooleanWidgetValue");
const STANDARD_EXCLUDED_PROPS = [
  "style",
  "class",
  "dt",
  "pt",
  "ptOptions",
  "unstyled"
];
const INPUT_EXCLUDED_PROPS = [
  ...STANDARD_EXCLUDED_PROPS,
  "inputClass",
  "inputStyle"
];
const PANEL_EXCLUDED_PROPS = [
  ...STANDARD_EXCLUDED_PROPS,
  "panelClass",
  "panelStyle",
  "overlayClass"
];
const GALLERIA_EXCLUDED_PROPS = [
  ...STANDARD_EXCLUDED_PROPS,
  "thumbnailsPosition",
  "verticalThumbnailViewPortHeight",
  "indicatorsPosition",
  "maskClass",
  "containerStyle",
  "containerClass",
  "galleriaClass"
];
const BADGE_EXCLUDED_PROPS = [
  ...STANDARD_EXCLUDED_PROPS,
  "badgeClass"
];
function filterWidgetProps(props, excludeList) {
  if (!props) return {};
  const filtered = {};
  for (const [key, value] of Object.entries(props)) {
    if (!excludeList.includes(key)) {
      filtered[key] = value;
    }
  }
  return filtered;
}
__name(filterWidgetProps, "filterWidgetProps");
const WidgetInputBaseClass = [
  // Background
  "bg-zinc-500/10",
  // Outline
  "border-none",
  "outline",
  "outline-1",
  "outline-offset-[-1px]",
  "outline-zinc-300/10",
  // Rounded
  "!rounded-lg",
  // Hover
  "hover:outline-blue-500/80"
].join(" ");
const _hoisted_1$O = {
  key: 0,
  class: "text-sm text-[#888682] dark-theme:text-[#9FA2BD] font-normal flex-1 truncate w-20"
};
const _hoisted_2$l = { class: "w-75" };
const _sfc_main$M = /* @__PURE__ */ defineComponent({
  __name: "WidgetLayoutField",
  props: {
    widget: {}
  },
  setup(__props) {
    const widgetHeight = COMFY_VUE_NODE_DIMENSIONS.components.STANDARD_WIDGET_HEIGHT;
    return (_ctx, _cache) => {
      return openBlock(), createElementBlock("div", {
        class: "flex items-center justify-between gap-2",
        style: normalizeStyle({ height: unref(widgetHeight) + "px" })
      }, [
        _ctx.widget.name ? (openBlock(), createElementBlock("p", _hoisted_1$O, toDisplayString(_ctx.widget.name), 1)) : createCommentVNode("", true),
        createElementVNode("div", _hoisted_2$l, [
          renderSlot(_ctx.$slots, "default")
        ])
      ], 4);
    };
  }
});
const _sfc_main$L = /* @__PURE__ */ defineComponent({
  __name: "WidgetInputText",
  props: {
    widget: {},
    modelValue: {},
    readonly: { type: Boolean }
  },
  emits: ["update:modelValue"],
  setup(__props, { emit: __emit }) {
    const props = __props;
    const emit = __emit;
    const { localValue, onChange } = useStringWidgetValue(
      props.widget,
      props.modelValue,
      emit
    );
    const filteredProps = computed(
      () => filterWidgetProps(props.widget.options, INPUT_EXCLUDED_PROPS)
    );
    return (_ctx, _cache) => {
      return openBlock(), createBlock(_sfc_main$M, { widget: _ctx.widget }, {
        default: withCtx(() => [
          createVNode(unref(InputText), mergeProps({
            modelValue: unref(localValue),
            "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => isRef(localValue) ? localValue.value = $event : null)
          }, filteredProps.value, {
            disabled: _ctx.readonly,
            class: unref(cn)(unref(WidgetInputBaseClass), "w-full text-xs py-2 px-4"),
            size: "small",
            "onUpdate:modelValue": unref(onChange)
          }), null, 16, ["modelValue", "disabled", "class", "onUpdate:modelValue"])
        ]),
        _: 1
      }, 8, ["widget"]);
    };
  }
});
const _hoisted_1$N = { class: "flex flex-col gap-1" };
const _hoisted_2$k = {
  key: 0,
  class: "text-sm opacity-80"
};
const _sfc_main$K = /* @__PURE__ */ defineComponent({
  __name: "WidgetButton",
  props: {
    widget: {},
    readonly: { type: Boolean }
  },
  setup(__props) {
    const props = __props;
    const BUTTON_EXCLUDED_PROPS = [...BADGE_EXCLUDED_PROPS, "iconClass"];
    const filteredProps = computed(
      () => filterWidgetProps(props.widget.options, BUTTON_EXCLUDED_PROPS)
    );
    const handleClick = /* @__PURE__ */ __name(() => {
      if (!props.readonly && props.widget.callback) {
        props.widget.callback();
      }
    }, "handleClick");
    return (_ctx, _cache) => {
      return openBlock(), createElementBlock("div", _hoisted_1$N, [
        _ctx.widget.name ? (openBlock(), createElementBlock("label", _hoisted_2$k, toDisplayString(_ctx.widget.name), 1)) : createCommentVNode("", true),
        createVNode(unref(Button), mergeProps(filteredProps.value, {
          disabled: _ctx.readonly,
          size: "small",
          onClick: handleClick
        }), null, 16, ["disabled"])
      ]);
    };
  }
});
const _hoisted_1$M = { class: "flex flex-col gap-1" };
const _hoisted_2$j = { class: "p-4 border border-gray-300 dark-theme:border-gray-600 rounded max-h-[48rem]" };
const _sfc_main$J = /* @__PURE__ */ defineComponent({
  __name: "WidgetChart",
  props: /* @__PURE__ */ mergeModels({
    widget: {},
    readonly: { type: Boolean }
  }, {
    "modelValue": { required: true },
    "modelModifiers": {}
  }),
  emits: ["update:modelValue"],
  setup(__props) {
    const value = useModel(__props, "modelValue");
    const props = __props;
    const chartType = computed(() => props.widget.options?.type ?? "line");
    const chartData = computed(() => value.value || { labels: [], datasets: [] });
    const chartOptions = computed(() => ({
      responsive: true,
      maintainAspectRatio: false,
      plugins: {
        legend: {
          labels: {
            color: "#FFF",
            usePointStyle: true,
            pointStyle: "circle"
          }
        }
      },
      scales: {
        x: {
          ticks: {
            color: "#9FA2BD"
          },
          grid: {
            display: true,
            color: "#9FA2BD",
            drawTicks: false,
            drawOnChartArea: true,
            drawBorder: false
          },
          border: {
            display: true,
            color: "#9FA2BD"
          }
        },
        y: {
          ticks: {
            color: "#9FA2BD"
          },
          grid: {
            display: false,
            drawTicks: false,
            drawOnChartArea: false,
            drawBorder: false
          },
          border: {
            display: true,
            color: "#9FA2BD"
          }
        }
      }
    }));
    return (_ctx, _cache) => {
      return openBlock(), createElementBlock("div", _hoisted_1$M, [
        createElementVNode("div", _hoisted_2$j, [
          createVNode(unref(Chart), {
            type: chartType.value,
            data: chartData.value,
            options: chartOptions.value
          }, null, 8, ["type", "data", "options"])
        ])
      ]);
    };
  }
});
const _hoisted_1$L = { class: "text-xs" };
const _sfc_main$I = /* @__PURE__ */ defineComponent({
  __name: "WidgetColorPicker",
  props: {
    widget: {},
    modelValue: {},
    readonly: { type: Boolean }
  },
  emits: ["update:modelValue"],
  setup(__props, { emit: __emit }) {
    const props = __props;
    const emit = __emit;
    const { localValue, onChange } = useWidgetValue({
      widget: props.widget,
      modelValue: props.modelValue,
      defaultValue: "#000000",
      emit
    });
    const COLOR_PICKER_EXCLUDED_PROPS = [...PANEL_EXCLUDED_PROPS];
    const filteredProps = computed(
      () => filterWidgetProps(props.widget.options, COLOR_PICKER_EXCLUDED_PROPS)
    );
    return (_ctx, _cache) => {
      return openBlock(), createBlock(_sfc_main$M, { widget: _ctx.widget }, {
        default: withCtx(() => [
          createElementVNode("label", {
            class: normalizeClass(
              unref(cn)(unref(WidgetInputBaseClass), "flex items-center gap-2 w-full px-4 py-2")
            )
          }, [
            createVNode(unref(ColorPicker), mergeProps({
              modelValue: unref(localValue),
              "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => isRef(localValue) ? localValue.value = $event : null)
            }, filteredProps.value, {
              disabled: _ctx.readonly,
              class: "w-8 h-4 !rounded-full overflow-hidden border-none",
              pt: {
                preview: "!w-full !h-full !border-none"
              },
              "onUpdate:modelValue": unref(onChange)
            }), null, 16, ["modelValue", "disabled", "onUpdate:modelValue"]),
            createElementVNode("span", _hoisted_1$L, "#" + toDisplayString(unref(localValue)), 1)
          ], 2)
        ]),
        _: 1
      }, 8, ["widget"]);
    };
  }
});
const _hoisted_1$K = {
  key: 0,
  class: "relative -mx-2",
  style: { "width": "calc(100% + 1rem)" }
};
const _hoisted_2$i = { class: "flex items-center justify-between gap-4 mb-2 px-2" };
const _hoisted_3$d = {
  key: 0,
  class: "text-xs opacity-80 min-w-[4em] truncate"
};
const _hoisted_4$b = { class: "flex items-center gap-1" };
const _hoisted_5$5 = { class: "relative group" };
const _hoisted_6$4 = ["src", "alt"];
const _hoisted_7$3 = {
  key: 0,
  class: "absolute top-2 right-2 flex gap-1 opacity-0 group-hover:opacity-100 transition-opacity duration-200"
};
const _hoisted_8$2 = {
  key: 1,
  class: "relative -mx-2",
  style: { "width": "calc(100% + 1rem)" }
};
const _hoisted_9$1 = { class: "flex items-center justify-between gap-4 mb-2 px-2" };
const _hoisted_10$1 = {
  key: 0,
  class: "text-xs opacity-80 min-w-[4em] truncate"
};
const _hoisted_11 = { class: "flex items-center gap-1" };
const _hoisted_12 = { class: "relative group px-2" };
const _hoisted_13 = {
  class: "bg-[#1a1b1e] rounded-lg p-4 flex items-center gap-4",
  style: { "border": "1px solid #262729" }
};
const _hoisted_14 = { class: "flex-1" };
const _hoisted_15 = { class: "text-sm font-medium mb-1" };
const _hoisted_16 = { class: "text-xs opacity-60" };
const _hoisted_17 = {
  key: 0,
  class: "flex gap-1"
};
const _hoisted_18 = {
  key: 2,
  class: "flex flex-col gap-1 w-full border border-solid p-1 rounded-lg",
  style: { borderColor: "#262729" }
};
const _hoisted_19 = {
  class: "border border-dashed p-1 rounded-md transition-colors duration-200 hover:border-[#5B5E7D]",
  style: { borderColor: "#262729" }
};
const _hoisted_20 = { class: "flex flex-col items-center gap-2 w-full py-4" };
const _hoisted_21 = { class: "text-xs opacity-60" };
const _hoisted_22 = ["accept", "disabled"];
const _sfc_main$H = /* @__PURE__ */ defineComponent({
  __name: "WidgetFileUpload",
  props: {
    widget: {},
    modelValue: {},
    readonly: { type: Boolean }
  },
  emits: ["update:modelValue"],
  setup(__props, { emit: __emit }) {
    const props = __props;
    const emit = __emit;
    const { localValue, onChange } = useWidgetValue({
      widget: props.widget,
      modelValue: props.modelValue,
      defaultValue: null,
      emit
    });
    const fileInputRef = ref(null);
    const selectedFile = computed(() => {
      const files = localValue.value || [];
      return files.length > 0 ? files[0] : null;
    });
    const detectFileType = /* @__PURE__ */ __name((file) => {
      const type = file.type?.toLowerCase() || "";
      const name = file.name?.toLowerCase() || "";
      if (type.startsWith("image/") || name.match(/\.(jpg|jpeg|png|gif|webp|svg)$/)) {
        return "image";
      }
      if (type.startsWith("video/") || name.match(/\.(mp4|webm|ogg|mov)$/)) {
        return "video";
      }
      if (type.startsWith("audio/") || name.match(/\.(mp3|wav|ogg|flac)$/)) {
        return "audio";
      }
      if (type === "application/pdf" || name.endsWith(".pdf")) {
        return "pdf";
      }
      if (type.includes("zip") || name.match(/\.(zip|rar|7z|tar|gz)$/)) {
        return "archive";
      }
      return "file";
    }, "detectFileType");
    const hasImageFile = computed(() => {
      return selectedFile.value && detectFileType(selectedFile.value) === "image";
    });
    const hasAudioFile = computed(() => {
      return selectedFile.value && detectFileType(selectedFile.value) === "audio";
    });
    const imageUrl = computed(() => {
      if (hasImageFile.value && selectedFile.value) {
        return URL.createObjectURL(selectedFile.value);
      }
      return "";
    });
    watch(imageUrl, (newUrl, oldUrl) => {
      if (oldUrl && oldUrl !== newUrl) {
        URL.revokeObjectURL(oldUrl);
      }
    });
    const triggerFileInput = /* @__PURE__ */ __name(() => {
      fileInputRef.value?.click();
    }, "triggerFileInput");
    const handleFileChange = /* @__PURE__ */ __name((event) => {
      const target = event.target;
      if (!props.readonly && target.files && target.files.length > 0) {
        const file = target.files[0];
        onChange([file]);
        target.value = "";
      }
    }, "handleFileChange");
    const clearFile = /* @__PURE__ */ __name(() => {
      onChange(null);
      if (fileInputRef.value) {
        fileInputRef.value.value = "";
      }
    }, "clearFile");
    const handleEdit = /* @__PURE__ */ __name(() => {
    }, "handleEdit");
    watch(localValue, (newValue) => {
      if (!newValue || newValue.length === 0) {
        if (fileInputRef.value) {
          fileInputRef.value.value = "";
        }
      }
    });
    onUnmounted(() => {
      if (imageUrl.value) {
        URL.revokeObjectURL(imageUrl.value);
      }
    });
    return (_ctx, _cache) => {
      return openBlock(), createElementBlock(Fragment, null, [
        hasImageFile.value ? (openBlock(), createElementBlock("div", _hoisted_1$K, [
          createElementVNode("div", _hoisted_2$i, [
            _ctx.widget.name ? (openBlock(), createElementBlock("label", _hoisted_3$d, toDisplayString(_ctx.widget.name), 1)) : createCommentVNode("", true),
            createElementVNode("div", _hoisted_4$b, [
              createVNode(unref(Select), {
                "model-value": selectedFile.value?.name,
                options: [selectedFile.value?.name || ""],
                disabled: true,
                class: "min-w-[8em] max-w-[20em] text-xs",
                size: "small",
                pt: {
                  option: "text-xs"
                }
              }, null, 8, ["model-value", "options"]),
              createVNode(unref(Button), {
                icon: "pi pi-folder",
                size: "small",
                class: "!w-8 !h-8",
                disabled: _ctx.readonly,
                onClick: triggerFileInput
              }, null, 8, ["disabled"])
            ])
          ]),
          createElementVNode("div", _hoisted_5$5, [
            createElementVNode("img", {
              src: imageUrl.value,
              alt: selectedFile.value?.name,
              class: "w-full h-auto"
            }, null, 8, _hoisted_6$4),
            _cache[2] || (_cache[2] = createElementVNode("div", { class: "absolute inset-0 bg-black bg-opacity-0 group-hover:bg-opacity-20 transition-all duration-200 pointer-events-none" }, null, -1)),
            !_ctx.readonly ? (openBlock(), createElementBlock("div", _hoisted_7$3, [
              createElementVNode("button", {
                class: "w-6 h-6 rounded flex items-center justify-center transition-all duration-150 focus:outline-none border-none",
                style: { "background-color": "#262729" },
                onClick: handleEdit
              }, _cache[0] || (_cache[0] = [
                createElementVNode("i", { class: "pi pi-pencil text-white text-xs" }, null, -1)
              ])),
              createElementVNode("button", {
                class: "w-6 h-6 rounded flex items-center justify-center transition-all duration-150 focus:outline-none border-none",
                style: { "background-color": "#262729" },
                onClick: clearFile
              }, _cache[1] || (_cache[1] = [
                createElementVNode("i", { class: "pi pi-times text-white text-xs" }, null, -1)
              ]))
            ])) : createCommentVNode("", true)
          ])
        ])) : hasAudioFile.value ? (openBlock(), createElementBlock("div", _hoisted_8$2, [
          createElementVNode("div", _hoisted_9$1, [
            _ctx.widget.name ? (openBlock(), createElementBlock("label", _hoisted_10$1, toDisplayString(_ctx.widget.name), 1)) : createCommentVNode("", true),
            createElementVNode("div", _hoisted_11, [
              createVNode(unref(Select), {
                "model-value": selectedFile.value?.name,
                options: [selectedFile.value?.name || ""],
                disabled: true,
                class: "min-w-[8em] max-w-[20em] text-xs",
                size: "small",
                pt: {
                  option: "text-xs"
                }
              }, null, 8, ["model-value", "options"]),
              createVNode(unref(Button), {
                icon: "pi pi-folder",
                size: "small",
                class: "!w-8 !h-8",
                disabled: _ctx.readonly,
                onClick: triggerFileInput
              }, null, 8, ["disabled"])
            ])
          ]),
          createElementVNode("div", _hoisted_12, [
            createElementVNode("div", _hoisted_13, [
              _cache[4] || (_cache[4] = createElementVNode("div", { class: "flex-shrink-0" }, [
                createElementVNode("i", { class: "pi pi-volume-up text-2xl opacity-60" })
              ], -1)),
              createElementVNode("div", _hoisted_14, [
                createElementVNode("div", _hoisted_15, toDisplayString(selectedFile.value?.name), 1),
                createElementVNode("div", _hoisted_16, toDisplayString(selectedFile.value ? (selectedFile.value.size / 1024).toFixed(1) + " KB" : ""), 1)
              ]),
              !_ctx.readonly ? (openBlock(), createElementBlock("div", _hoisted_17, [
                createElementVNode("button", {
                  class: "w-8 h-8 rounded flex items-center justify-center transition-all duration-150 focus:outline-none border-none hover:bg-[#262729]",
                  onClick: clearFile
                }, _cache[3] || (_cache[3] = [
                  createElementVNode("i", { class: "pi pi-times text-white text-sm" }, null, -1)
                ]))
              ])) : createCommentVNode("", true)
            ])
          ])
        ])) : (openBlock(), createElementBlock("div", _hoisted_18, [
          createElementVNode("div", _hoisted_19, [
            createElementVNode("div", _hoisted_20, [
              createElementVNode("span", _hoisted_21, toDisplayString(_ctx.$t("Drop your file or")), 1),
              createElementVNode("div", null, [
                createVNode(unref(Button), {
                  label: "Browse Files",
                  size: "small",
                  severity: "secondary",
                  class: "text-xs",
                  disabled: _ctx.readonly,
                  onClick: triggerFileInput
                }, null, 8, ["disabled"])
              ])
            ])
          ])
        ])),
        createElementVNode("input", {
          ref_key: "fileInputRef",
          ref: fileInputRef,
          type: "file",
          class: "hidden",
          accept: _ctx.widget.options?.accept,
          multiple: false,
          disabled: _ctx.readonly,
          onChange: handleFileChange
        }, null, 40, _hoisted_22)
      ], 64);
    };
  }
});
const _hoisted_1$J = { class: "flex flex-col gap-1" };
const _hoisted_2$h = ["src", "alt"];
const _hoisted_3$c = { class: "p-1 w-full h-full" };
const _hoisted_4$a = ["src", "alt"];
const _sfc_main$G = /* @__PURE__ */ defineComponent({
  __name: "WidgetGalleria",
  props: /* @__PURE__ */ mergeModels({
    widget: {},
    readonly: { type: Boolean }
  }, {
    "modelValue": { required: true },
    "modelModifiers": {}
  }),
  emits: ["update:modelValue"],
  setup(__props) {
    const value = useModel(__props, "modelValue");
    const props = __props;
    const activeIndex = ref(0);
    const filteredProps = computed(
      () => filterWidgetProps(props.widget.options, GALLERIA_EXCLUDED_PROPS)
    );
    const galleryImages = computed(() => {
      if (!value.value || !Array.isArray(value.value)) return [];
      return value.value.map((item, index) => {
        if (typeof item === "string") {
          return {
            itemImageSrc: item,
            thumbnailImageSrc: item,
            alt: `Image ${index + 1}`
          };
        }
        return item;
      });
    });
    const showThumbnails = computed(() => {
      return props.widget.options?.showThumbnails !== false && galleryImages.value.length > 1;
    });
    const showNavButtons = computed(() => {
      return props.widget.options?.showNavButtons !== false && galleryImages.value.length > 1;
    });
    return (_ctx, _cache) => {
      return openBlock(), createElementBlock("div", _hoisted_1$J, [
        createVNode(unref(Galleria), mergeProps({
          activeIndex: activeIndex.value,
          "onUpdate:activeIndex": _cache[0] || (_cache[0] = ($event) => activeIndex.value = $event),
          value: galleryImages.value
        }, filteredProps.value, {
          disabled: _ctx.readonly,
          "show-thumbnails": showThumbnails.value,
          "show-nav-buttons": showNavButtons.value,
          class: "max-w-full",
          pt: {
            thumbnails: {
              class: "overflow-hidden"
            },
            thumbnailContent: {
              class: "py-4 px-2"
            },
            thumbnailPrevButton: {
              class: "m-0"
            },
            thumbnailNextButton: {
              class: "m-0"
            }
          }
        }), {
          item: withCtx(({ item }) => [
            createElementVNode("img", {
              src: item.itemImageSrc || item.src || item,
              alt: item.alt || "Gallery image",
              class: "w-full h-auto max-h-64 object-contain"
            }, null, 8, _hoisted_2$h)
          ]),
          thumbnail: withCtx(({ item }) => [
            createElementVNode("div", _hoisted_3$c, [
              createElementVNode("img", {
                src: item.thumbnailImageSrc || item.src || item,
                alt: item.alt || "Gallery thumbnail",
                class: "w-full h-full object-cover rounded-lg"
              }, null, 8, _hoisted_4$a)
            ])
          ]),
          _: 1
        }, 16, ["activeIndex", "value", "disabled", "show-thumbnails", "show-nav-buttons"])
      ]);
    };
  }
});
const WidgetGalleria = /* @__PURE__ */ _export_sfc(_sfc_main$G, [["__scopeId", "data-v-7cc93f7a"]]);
const _hoisted_1$I = ["src", "alt"];
const _hoisted_2$g = ["src", "alt"];
const _sfc_main$F = /* @__PURE__ */ defineComponent({
  __name: "WidgetImageCompare",
  props: {
    widget: {},
    readonly: { type: Boolean }
  },
  setup(__props) {
    const props = __props;
    const beforeImage = computed(() => {
      const value = props.widget.value;
      return typeof value === "string" ? value : value?.before || "";
    });
    const afterImage = computed(() => {
      const value = props.widget.value;
      return typeof value === "string" ? "" : value?.after || "";
    });
    const beforeAlt = computed(() => {
      const value = props.widget.value;
      return typeof value === "object" && value?.beforeAlt ? value.beforeAlt : "Before image";
    });
    const afterAlt = computed(() => {
      const value = props.widget.value;
      return typeof value === "object" && value?.afterAlt ? value.afterAlt : "After image";
    });
    return (_ctx, _cache) => {
      return openBlock(), createBlock(unref(ImageCompare), {
        tabindex: _ctx.widget.options?.tabindex ?? 0,
        "aria-label": _ctx.widget.options?.ariaLabel,
        "aria-labelledby": _ctx.widget.options?.ariaLabelledby,
        pt: _ctx.widget.options?.pt,
        "pt-options": _ctx.widget.options?.ptOptions,
        unstyled: _ctx.widget.options?.unstyled
      }, {
        left: withCtx(() => [
          createElementVNode("img", {
            src: beforeImage.value,
            alt: beforeAlt.value,
            class: "w-full h-full object-cover"
          }, null, 8, _hoisted_1$I)
        ]),
        right: withCtx(() => [
          createElementVNode("img", {
            src: afterImage.value,
            alt: afterAlt.value,
            class: "w-full h-full object-cover"
          }, null, 8, _hoisted_2$g)
        ]),
        _: 1
      }, 8, ["tabindex", "aria-label", "aria-labelledby", "pt", "pt-options", "unstyled"]);
    };
  }
});
const _hoisted_1$H = ["innerHTML"];
const _sfc_main$E = /* @__PURE__ */ defineComponent({
  __name: "WidgetMarkdown",
  props: {
    widget: {},
    modelValue: {},
    readonly: { type: Boolean }
  },
  emits: ["update:modelValue"],
  setup(__props, { emit: __emit }) {
    const props = __props;
    const emit = __emit;
    const isEditing = ref(false);
    const textareaRef = ref();
    const { localValue, onChange } = useStringWidgetValue(
      props.widget,
      props.modelValue,
      emit
    );
    const renderedHtml = computed(() => {
      return renderMarkdownToHtml(localValue.value || "");
    });
    const startEditing = /* @__PURE__ */ __name(async () => {
      if (props.readonly || isEditing.value) return;
      isEditing.value = true;
      await nextTick();
      textareaRef.value?.$el?.focus();
    }, "startEditing");
    const handleBlur = /* @__PURE__ */ __name(() => {
      isEditing.value = false;
    }, "handleBlur");
    return (_ctx, _cache) => {
      return openBlock(), createElementBlock("div", {
        class: "widget-markdown relative w-full cursor-text",
        onClick: startEditing
      }, [
        !isEditing.value ? (openBlock(), createElementBlock("div", {
          key: 0,
          class: "comfy-markdown-content text-xs min-h-[60px] rounded-lg px-4 py-2 overflow-y-auto",
          innerHTML: renderedHtml.value
        }, null, 8, _hoisted_1$H)) : (openBlock(), createBlock(unref(Textarea), {
          key: 1,
          ref_key: "textareaRef",
          ref: textareaRef,
          modelValue: unref(localValue),
          "onUpdate:modelValue": [
            _cache[0] || (_cache[0] = ($event) => isRef(localValue) ? localValue.value = $event : null),
            unref(onChange)
          ],
          disabled: _ctx.readonly,
          class: "w-full text-xs",
          size: "small",
          rows: "6",
          pt: {
            root: {
              onBlur: handleBlur
            }
          },
          onClick: _cache[1] || (_cache[1] = withModifiers(() => {
          }, ["stop"])),
          onKeydown: _cache[2] || (_cache[2] = withModifiers(() => {
          }, ["stop"]))
        }, null, 8, ["modelValue", "disabled", "pt", "onUpdate:modelValue"]))
      ]);
    };
  }
});
const WidgetMarkdown = /* @__PURE__ */ _export_sfc(_sfc_main$E, [["__scopeId", "data-v-8e27a4d6"]]);
const _sfc_main$D = /* @__PURE__ */ defineComponent({
  __name: "WidgetMultiSelect",
  props: {
    widget: {},
    modelValue: {},
    readonly: { type: Boolean }
  },
  emits: ["update:modelValue"],
  setup(__props, { emit: __emit }) {
    const props = __props;
    const emit = __emit;
    const { localValue, onChange } = useWidgetValue({
      widget: props.widget,
      modelValue: props.modelValue,
      defaultValue: [],
      emit
    });
    const MULTISELECT_EXCLUDED_PROPS = [
      ...PANEL_EXCLUDED_PROPS,
      "overlayStyle"
    ];
    const filteredProps = computed(() => {
      const filtered = filterWidgetProps(
        props.widget.options,
        MULTISELECT_EXCLUDED_PROPS
      );
      const values = props.widget.options?.values;
      if (values && Array.isArray(values)) {
        filtered.options = values;
      }
      return filtered;
    });
    return (_ctx, _cache) => {
      return openBlock(), createBlock(_sfc_main$M, { widget: _ctx.widget }, {
        default: withCtx(() => [
          createVNode(unref(MultiSelect), mergeProps({
            modelValue: unref(localValue),
            "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => isRef(localValue) ? localValue.value = $event : null)
          }, filteredProps.value, {
            disabled: _ctx.readonly,
            class: unref(cn)(unref(WidgetInputBaseClass), "w-full text-xs"),
            size: "small",
            display: "chip",
            pt: {
              option: "text-xs"
            },
            "onUpdate:modelValue": unref(onChange)
          }), null, 16, ["modelValue", "disabled", "class", "onUpdate:modelValue"])
        ]),
        _: 1
      }, 8, ["widget"]);
    };
  }
});
const _sfc_main$C = /* @__PURE__ */ defineComponent({
  __name: "WidgetSelect",
  props: {
    widget: {},
    modelValue: {},
    readonly: { type: Boolean }
  },
  emits: ["update:modelValue"],
  setup(__props, { emit: __emit }) {
    const props = __props;
    const emit = __emit;
    const { localValue, onChange } = useWidgetValue({
      widget: props.widget,
      modelValue: props.modelValue,
      defaultValue: props.widget.options?.values?.[0] || "",
      emit
    });
    const filteredProps = computed(
      () => filterWidgetProps(props.widget.options, PANEL_EXCLUDED_PROPS)
    );
    const selectOptions = computed(() => {
      const options = props.widget.options;
      if (options?.values && Array.isArray(options.values)) {
        return options.values;
      }
      return [];
    });
    return (_ctx, _cache) => {
      return openBlock(), createBlock(_sfc_main$M, { widget: _ctx.widget }, {
        default: withCtx(() => [
          createVNode(unref(Select), mergeProps({
            modelValue: unref(localValue),
            "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => isRef(localValue) ? localValue.value = $event : null),
            options: selectOptions.value
          }, filteredProps.value, {
            disabled: _ctx.readonly,
            class: unref(cn)(unref(WidgetInputBaseClass), "w-full text-xs"),
            size: "small",
            pt: {
              option: "text-xs"
            },
            "onUpdate:modelValue": unref(onChange)
          }), null, 16, ["modelValue", "options", "disabled", "class", "onUpdate:modelValue"])
        ]),
        _: 1
      }, 8, ["widget"]);
    };
  }
});
const _hoisted_1$G = ["disabled", "onClick"];
const _sfc_main$B = /* @__PURE__ */ defineComponent({
  __name: "FormSelectButton",
  props: {
    modelValue: {},
    options: {},
    optionLabel: {},
    optionValue: {},
    disabled: { type: Boolean, default: false }
  },
  emits: ["update:modelValue"],
  setup(__props, { emit: __emit }) {
    const props = __props;
    const emit = __emit;
    const getOptionValue = /* @__PURE__ */ __name((option, index) => {
      if (typeof option === "object" && option !== null) {
        const valueField = props.optionValue ?? "value";
        const value = option[valueField] ?? option.value ?? option.name ?? option.label ?? index;
        return String(value);
      }
      return String(option);
    }, "getOptionValue");
    const getOptionLabel = /* @__PURE__ */ __name((option) => {
      if (typeof option === "object" && option !== null) {
        const labelField = props.optionLabel ?? "label";
        return option[labelField] ?? option.label ?? option.name ?? option.value ?? String(option);
      }
      return String(option);
    }, "getOptionLabel");
    const isSelected = /* @__PURE__ */ __name((option) => {
      const optionValue = getOptionValue(option, props.options.indexOf(option));
      return optionValue === String(props.modelValue ?? "");
    }, "isSelected");
    const handleSelect = /* @__PURE__ */ __name((option) => {
      if (props.disabled) return;
      const optionValue = getOptionValue(option, props.options.indexOf(option));
      emit("update:modelValue", optionValue);
    }, "handleSelect");
    return (_ctx, _cache) => {
      return openBlock(), createElementBlock("div", {
        class: normalizeClass(
          unref(cn)(
            unref(WidgetInputBaseClass),
            "p-1 inline-flex justify-center items-center gap-1"
          )
        )
      }, [
        (openBlock(true), createElementBlock(Fragment, null, renderList(_ctx.options, (option, index) => {
          return openBlock(), createElementBlock("button", {
            key: getOptionValue(option, index),
            class: normalizeClass(
              unref(cn)(
                "flex-1 h-6 px-5 py-[5px] rounded flex justify-center items-center gap-1 transition-all duration-150 ease-in-out",
                "bg-transparent border-none",
                "text-center text-xs font-normal",
                {
                  "bg-white": isSelected(option) && !_ctx.disabled,
                  "hover:bg-zinc-200/50": !isSelected(option) && !_ctx.disabled,
                  "opacity-50 cursor-not-allowed": _ctx.disabled,
                  "cursor-pointer": !_ctx.disabled
                },
                {
                  "text-neutral-900": isSelected(option) && !_ctx.disabled,
                  "text-zinc-500": !isSelected(option) || _ctx.disabled
                }
              )
            ),
            disabled: _ctx.disabled,
            onClick: /* @__PURE__ */ __name(($event) => handleSelect(option), "onClick")
          }, toDisplayString(getOptionLabel(option)), 11, _hoisted_1$G);
        }), 128))
      ], 2);
    };
  }
});
const _sfc_main$A = /* @__PURE__ */ defineComponent({
  __name: "WidgetSelectButton",
  props: {
    widget: {},
    modelValue: {},
    readonly: { type: Boolean }
  },
  emits: ["update:modelValue"],
  setup(__props, { emit: __emit }) {
    const props = __props;
    const emit = __emit;
    const { localValue, onChange } = useStringWidgetValue(
      props.widget,
      props.modelValue,
      emit
    );
    return (_ctx, _cache) => {
      return openBlock(), createBlock(_sfc_main$M, { widget: _ctx.widget }, {
        default: withCtx(() => [
          createVNode(_sfc_main$B, {
            modelValue: unref(localValue),
            "onUpdate:modelValue": [
              _cache[0] || (_cache[0] = ($event) => isRef(localValue) ? localValue.value = $event : null),
              unref(onChange)
            ],
            options: _ctx.widget.options?.values || [],
            disabled: _ctx.readonly,
            class: "w-full"
          }, null, 8, ["modelValue", "options", "disabled", "onUpdate:modelValue"])
        ]),
        _: 1
      }, 8, ["widget"]);
    };
  }
});
const _sfc_main$z = /* @__PURE__ */ defineComponent({
  __name: "WidgetSlider",
  props: {
    widget: {},
    modelValue: {},
    readonly: { type: Boolean }
  },
  emits: ["update:modelValue"],
  setup(__props, { emit: __emit }) {
    const props = __props;
    const emit = __emit;
    const { localValue, onChange } = useNumberWidgetValue(
      props.widget,
      props.modelValue,
      emit
    );
    const filteredProps = computed(
      () => filterWidgetProps(props.widget.options, STANDARD_EXCLUDED_PROPS)
    );
    const precision = computed(() => {
      const p = props.widget.options?.precision;
      return typeof p === "number" && p >= 0 ? p : void 0;
    });
    const stepValue = computed(() => {
      if (props.widget.options?.step !== void 0) {
        return String(props.widget.options.step);
      }
      if (precision.value !== void 0) {
        if (precision.value === 0) {
          return "1";
        }
        return (1 / Math.pow(10, precision.value)).toFixed(precision.value);
      }
      return "any";
    });
    const formatNumber = /* @__PURE__ */ __name((value) => {
      if (precision.value === void 0) {
        return String(value);
      }
      return value.toFixed(precision.value);
    }, "formatNumber");
    const applyPrecision = /* @__PURE__ */ __name((value) => {
      if (precision.value === void 0) {
        return value;
      }
      if (precision.value === 0) {
        return Math.round(value);
      }
      const multiplier = Math.pow(10, precision.value);
      return Math.round(value * multiplier) / multiplier;
    }, "applyPrecision");
    const inputDisplayValue = ref(formatNumber(localValue.value));
    watch(localValue, (newValue) => {
      inputDisplayValue.value = formatNumber(newValue);
    });
    const handleInputBlur = /* @__PURE__ */ __name((event) => {
      const target = event.target;
      const value = target.value || "0";
      const parsed = parseFloat(value);
      if (!isNaN(parsed)) {
        const roundedValue = applyPrecision(parsed);
        onChange(roundedValue);
        inputDisplayValue.value = formatNumber(roundedValue);
      }
    }, "handleInputBlur");
    const handleInputKeydown = /* @__PURE__ */ __name((event) => {
      if (event.key === "Enter") {
        const target = event.target;
        const value = target.value || "0";
        const parsed = parseFloat(value);
        if (!isNaN(parsed)) {
          const roundedValue = applyPrecision(parsed);
          onChange(roundedValue);
          inputDisplayValue.value = formatNumber(roundedValue);
        }
      }
    }, "handleInputKeydown");
    return (_ctx, _cache) => {
      return openBlock(), createBlock(_sfc_main$M, { widget: _ctx.widget }, {
        default: withCtx(() => [
          createElementVNode("div", {
            class: normalizeClass(
              unref(cn)(unref(WidgetInputBaseClass), "flex items-center gap-2 w-full pl-4 pr-2")
            )
          }, [
            createVNode(unref(Slider), mergeProps({
              modelValue: unref(localValue),
              "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => isRef(localValue) ? localValue.value = $event : null)
            }, filteredProps.value, {
              disabled: _ctx.readonly,
              class: "flex-grow text-xs",
              "onUpdate:modelValue": unref(onChange)
            }), null, 16, ["modelValue", "disabled", "onUpdate:modelValue"]),
            createVNode(unref(InputText), {
              modelValue: inputDisplayValue.value,
              "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => inputDisplayValue.value = $event),
              disabled: _ctx.readonly,
              type: "number",
              min: _ctx.widget.options?.min,
              max: _ctx.widget.options?.max,
              step: stepValue.value,
              class: "w-[4em] text-center text-xs px-0 !border-none !shadow-none !bg-transparent",
              size: "small",
              onBlur: handleInputBlur,
              onKeydown: handleInputKeydown
            }, null, 8, ["modelValue", "disabled", "min", "max", "step"])
          ], 2)
        ]),
        _: 1
      }, 8, ["widget"]);
    };
  }
});
const WidgetSlider = /* @__PURE__ */ _export_sfc(_sfc_main$z, [["__scopeId", "data-v-b2b6e035"]]);
const _sfc_main$y = /* @__PURE__ */ defineComponent({
  __name: "WidgetTextarea",
  props: {
    widget: {},
    modelValue: {},
    readonly: { type: Boolean },
    placeholder: {}
  },
  emits: ["update:modelValue"],
  setup(__props, { emit: __emit }) {
    const props = __props;
    const emit = __emit;
    const { localValue, onChange } = useStringWidgetValue(
      props.widget,
      props.modelValue,
      emit
    );
    const filteredProps = computed(
      () => filterWidgetProps(props.widget.options, INPUT_EXCLUDED_PROPS)
    );
    return (_ctx, _cache) => {
      return openBlock(), createBlock(unref(Textarea), mergeProps({
        modelValue: unref(localValue),
        "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => isRef(localValue) ? localValue.value = $event : null)
      }, filteredProps.value, {
        disabled: _ctx.readonly,
        class: unref(cn)(unref(WidgetInputBaseClass), "w-full text-xs"),
        placeholder: _ctx.placeholder || _ctx.widget.name || "",
        size: "small",
        rows: "3",
        "onUpdate:modelValue": unref(onChange)
      }), null, 16, ["modelValue", "disabled", "class", "placeholder", "onUpdate:modelValue"]);
    };
  }
});
const _sfc_main$x = /* @__PURE__ */ defineComponent({
  __name: "WidgetToggleSwitch",
  props: {
    widget: {},
    modelValue: { type: Boolean },
    readonly: { type: Boolean }
  },
  emits: ["update:modelValue"],
  setup(__props, { emit: __emit }) {
    const props = __props;
    const emit = __emit;
    const { localValue, onChange } = useBooleanWidgetValue(
      props.widget,
      props.modelValue,
      emit
    );
    const filteredProps = computed(
      () => filterWidgetProps(props.widget.options, STANDARD_EXCLUDED_PROPS)
    );
    return (_ctx, _cache) => {
      return openBlock(), createBlock(_sfc_main$M, { widget: _ctx.widget }, {
        default: withCtx(() => [
          createVNode(unref(ToggleSwitch), mergeProps({
            modelValue: unref(localValue),
            "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => isRef(localValue) ? localValue.value = $event : null)
          }, filteredProps.value, {
            disabled: _ctx.readonly,
            "onUpdate:modelValue": unref(onChange)
          }), null, 16, ["modelValue", "disabled", "onUpdate:modelValue"])
        ]),
        _: 1
      }, 8, ["widget"]);
    };
  }
});
const WidgetToggleSwitch = /* @__PURE__ */ _export_sfc(_sfc_main$x, [["__scopeId", "data-v-a907b670"]]);
const _sfc_main$w = /* @__PURE__ */ defineComponent({
  __name: "WidgetTreeSelect",
  props: {
    widget: {},
    modelValue: {},
    readonly: { type: Boolean }
  },
  emits: ["update:modelValue"],
  setup(__props, { emit: __emit }) {
    const props = __props;
    const emit = __emit;
    const { localValue, onChange } = useWidgetValue({
      widget: props.widget,
      modelValue: props.modelValue,
      defaultValue: null,
      emit
    });
    const TREE_SELECT_EXCLUDED_PROPS = [
      ...PANEL_EXCLUDED_PROPS,
      "inputClass",
      "inputStyle"
    ];
    const filteredProps = computed(
      () => filterWidgetProps(props.widget.options, TREE_SELECT_EXCLUDED_PROPS)
    );
    return (_ctx, _cache) => {
      return openBlock(), createBlock(_sfc_main$M, { widget: _ctx.widget }, {
        default: withCtx(() => [
          createVNode(unref(TreeSelect), mergeProps({
            modelValue: unref(localValue),
            "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => isRef(localValue) ? localValue.value = $event : null)
          }, filteredProps.value, {
            disabled: _ctx.readonly,
            class: unref(cn)(unref(WidgetInputBaseClass), "w-full text-xs"),
            size: "small",
            "onUpdate:modelValue": unref(onChange)
          }), null, 16, ["modelValue", "disabled", "class", "onUpdate:modelValue"])
        ]),
        _: 1
      }, 8, ["widget"]);
    };
  }
});
const coreWidgetDefinitions = [
  [
    "button",
    { component: _sfc_main$K, aliases: ["BUTTON"], essential: false }
  ],
  [
    "string",
    {
      component: _sfc_main$L,
      aliases: ["STRING", "text"],
      essential: false
    }
  ],
  ["int", { component: WidgetSlider, aliases: ["INT"], essential: true }],
  [
    "float",
    {
      component: WidgetSlider,
      aliases: ["FLOAT", "number", "slider"],
      essential: true
    }
  ],
  [
    "boolean",
    {
      component: WidgetToggleSwitch,
      aliases: ["BOOLEAN", "toggle"],
      essential: true
    }
  ],
  ["combo", { component: _sfc_main$C, aliases: ["COMBO"], essential: true }],
  [
    "color",
    { component: _sfc_main$I, aliases: ["COLOR"], essential: false }
  ],
  [
    "multiselect",
    { component: _sfc_main$D, aliases: ["MULTISELECT"], essential: false }
  ],
  [
    "selectbutton",
    {
      component: _sfc_main$A,
      aliases: ["SELECTBUTTON"],
      essential: false
    }
  ],
  [
    "textarea",
    {
      component: _sfc_main$y,
      aliases: ["TEXTAREA", "multiline", "customtext"],
      essential: false
    }
  ],
  ["chart", { component: _sfc_main$J, aliases: ["CHART"], essential: false }],
  [
    "imagecompare",
    {
      component: _sfc_main$F,
      aliases: ["IMAGECOMPARE"],
      essential: false
    }
  ],
  [
    "galleria",
    { component: WidgetGalleria, aliases: ["GALLERIA"], essential: false }
  ],
  [
    "fileupload",
    {
      component: _sfc_main$H,
      aliases: ["FILEUPLOAD", "file"],
      essential: false
    }
  ],
  [
    "treeselect",
    { component: _sfc_main$w, aliases: ["TREESELECT"], essential: false }
  ],
  [
    "markdown",
    { component: WidgetMarkdown, aliases: ["MARKDOWN"], essential: false }
  ]
];
const widgets = /* @__PURE__ */ new Map();
const aliasMap = /* @__PURE__ */ new Map();
for (const [type, def] of coreWidgetDefinitions) {
  widgets.set(type, def);
  for (const alias of def.aliases) {
    aliasMap.set(alias, type);
  }
}
const getCanonicalType = /* @__PURE__ */ __name((type) => aliasMap.get(type) || type, "getCanonicalType");
const getComponent = /* @__PURE__ */ __name((type) => {
  const canonicalType = getCanonicalType(type);
  return widgets.get(canonicalType)?.component || null;
}, "getComponent");
const isSupported = /* @__PURE__ */ __name((type) => {
  const canonicalType = getCanonicalType(type);
  return widgets.has(canonicalType);
}, "isSupported");
const isEssential = /* @__PURE__ */ __name((type) => {
  const canonicalType = getCanonicalType(type);
  return widgets.get(canonicalType)?.essential || false;
}, "isEssential");
const shouldRenderAsVue = /* @__PURE__ */ __name((widget) => {
  if (widget.options?.canvasOnly) return false;
  if (!widget.type) return false;
  return isSupported(widget.type);
}, "shouldRenderAsVue");
const _hoisted_1$F = {
  key: 0,
  class: "node-error p-2 text-red-500 text-sm"
};
const _hoisted_2$f = {
  key: 1,
  class: "lg-node-widgets flex flex-col gap-2 pr-4"
};
const _hoisted_3$b = { class: "opacity-0 group-hover:opacity-100 transition-opacity duration-150" };
const _sfc_main$v = /* @__PURE__ */ defineComponent({
  __name: "NodeWidgets",
  props: {
    node: {},
    nodeData: {},
    readonly: { type: Boolean },
    lodLevel: {}
  },
  setup(__props) {
    const props = __props;
    const renderError = ref(null);
    const { toastErrorHandler } = useErrorHandling();
    onErrorCaptured((error) => {
      renderError.value = error.message;
      toastErrorHandler(error);
      return false;
    });
    const nodeInfo = computed(() => props.nodeData || props.node);
    const processedWidgets = computed(() => {
      const info = nodeInfo.value;
      if (!info?.widgets) return [];
      const widgets2 = info.widgets;
      const lodLevel = props.lodLevel;
      const result = [];
      if (lodLevel === LODLevel.MINIMAL) {
        return [];
      }
      for (const widget of widgets2) {
        if (widget.options?.hidden) continue;
        if (widget.options?.canvasOnly) continue;
        if (!widget.type) continue;
        if (!shouldRenderAsVue(widget)) continue;
        if (lodLevel === LODLevel.REDUCED && !isEssential(widget.type)) continue;
        const vueComponent = getComponent(widget.type) || _sfc_main$L;
        const simplified = {
          name: widget.name,
          type: widget.type,
          value: widget.value,
          options: widget.options,
          callback: widget.callback
        };
        const updateHandler = /* @__PURE__ */ __name((value) => {
          if (widget.callback) {
            widget.callback(value);
          }
        }, "updateHandler");
        result.push({
          name: widget.name,
          type: widget.type,
          vueComponent,
          simplified,
          value: widget.value,
          updateHandler
        });
      }
      return result;
    });
    const getWidgetInputIndex = /* @__PURE__ */ __name((widget) => {
      const inputs = nodeInfo.value?.inputs;
      if (!inputs) return 0;
      const idx = inputs.findIndex((input) => {
        if (!input || typeof input !== "object") return false;
        if (!("name" in input && "type" in input)) return false;
        return "widget" in input && input.widget?.name === widget.name;
      });
      return idx >= 0 ? idx : 0;
    }, "getWidgetInputIndex");
    return (_ctx, _cache) => {
      return renderError.value ? (openBlock(), createElementBlock("div", _hoisted_1$F, toDisplayString(_ctx.$t("Node Widgets Error")), 1)) : (openBlock(), createElementBlock("div", _hoisted_2$f, [
        (openBlock(true), createElementBlock(Fragment, null, renderList(processedWidgets.value, (widget, index) => {
          return openBlock(), createElementBlock("div", {
            key: `widget-${index}-${widget.name}`,
            class: "lg-widget-container relative flex items-center group"
          }, [
            createElementVNode("div", _hoisted_3$b, [
              createVNode(_sfc_main$P, {
                "slot-data": {
                  name: widget.name,
                  type: widget.type,
                  boundingRect: [0, 0, 0, 0]
                },
                "node-id": nodeInfo.value?.id != null ? String(nodeInfo.value.id) : "",
                index: getWidgetInputIndex(widget),
                readonly: _ctx.readonly,
                "dot-only": true
              }, null, 8, ["slot-data", "node-id", "index", "readonly"])
            ]),
            (openBlock(), createBlock(resolveDynamicComponent(widget.vueComponent), {
              widget: widget.simplified,
              "model-value": widget.value,
              readonly: _ctx.readonly,
              class: "flex-1",
              "onUpdate:modelValue": widget.updateHandler
            }, null, 8, ["widget", "model-value", "readonly", "onUpdate:modelValue"]))
          ]);
        }), 128))
      ]));
    };
  }
});
const _hoisted_1$E = {
  key: 0,
  class: "node-error p-2 text-red-500 text-sm"
};
const _hoisted_2$e = ["data-node-id"];
const _hoisted_3$a = { class: "flex items-center" };
const _hoisted_4$9 = ["data-testid"];
const separatorClasses = "bg-[#e1ded5] dark-theme:bg-[#292A30] h-[1px] mx-0";
const _sfc_main$u = /* @__PURE__ */ defineComponent({
  __name: "LGraphNode",
  props: {
    nodeData: {},
    position: {},
    size: {},
    readonly: { type: Boolean },
    selected: { type: Boolean },
    executing: { type: Boolean },
    progress: {},
    error: {},
    zoomLevel: {}
  },
  emits: ["node-click", "slot-click", "update:collapsed", "update:title"],
  setup(__props, { emit: __emit }) {
    const props = __props;
    const emit = __emit;
    const zoomRef = toRef(() => props.zoomLevel ?? 1);
    const {
      lodLevel,
      shouldRenderWidgets,
      shouldRenderSlots,
      shouldRenderContent,
      lodCssClass
    } = useLOD(zoomRef);
    const isMinimalLOD = computed(() => lodLevel.value === LODLevel.MINIMAL);
    const renderError = ref(null);
    const { toastErrorHandler } = useErrorHandling();
    onErrorCaptured((error) => {
      renderError.value = error.message;
      toastErrorHandler(error);
      return false;
    });
    const {
      position: layoutPosition,
      startDrag,
      handleDrag: handleLayoutDrag,
      endDrag
    } = useNodeLayout(props.nodeData.id);
    const isDragging = ref(false);
    const dragStyle = computed(() => ({
      cursor: isDragging.value ? "grabbing" : "grab"
    }));
    const isCollapsed = ref(props.nodeData.flags?.collapsed ?? false);
    watch(
      () => props.nodeData.flags?.collapsed,
      (newCollapsed) => {
        if (newCollapsed !== void 0 && newCollapsed !== isCollapsed.value) {
          isCollapsed.value = newCollapsed;
        }
      }
    );
    const hasCustomContent = computed(() => {
      return false;
    });
    const shouldShowWidgets = computed(
      () => shouldRenderWidgets.value && props.nodeData.widgets?.length
    );
    const shouldShowContent = computed(
      () => shouldRenderContent.value && hasCustomContent.value
    );
    const handlePointerDown = /* @__PURE__ */ __name((event) => {
      if (!props.nodeData) {
        console.warn("LGraphNode: nodeData is null/undefined in handlePointerDown");
        return;
      }
      isDragging.value = true;
      startDrag(event);
      emit("node-click", event, props.nodeData);
    }, "handlePointerDown");
    const handlePointerMove = /* @__PURE__ */ __name((event) => {
      if (isDragging.value) {
        void handleLayoutDrag(event);
      }
    }, "handlePointerMove");
    const handlePointerUp = /* @__PURE__ */ __name((event) => {
      if (isDragging.value) {
        isDragging.value = false;
        void endDrag(event);
      }
    }, "handlePointerUp");
    const handleCollapse = /* @__PURE__ */ __name(() => {
      isCollapsed.value = !isCollapsed.value;
      emit("update:collapsed", props.nodeData.id, isCollapsed.value);
    }, "handleCollapse");
    const handleSlotClick = /* @__PURE__ */ __name((event, slotIndex, isInput) => {
      if (!props.nodeData) {
        console.warn("LGraphNode: nodeData is null/undefined in handleSlotClick");
        return;
      }
      emit("slot-click", event, props.nodeData, slotIndex, isInput);
    }, "handleSlotClick");
    const handleTitleUpdate = /* @__PURE__ */ __name((newTitle) => {
      emit("update:title", props.nodeData.id, newTitle);
    }, "handleTitleUpdate");
    return (_ctx, _cache) => {
      return renderError.value ? (openBlock(), createElementBlock("div", _hoisted_1$E, toDisplayString(_ctx.$t("Node Render Error")), 1)) : (openBlock(), createElementBlock("div", {
        key: 1,
        "data-node-id": _ctx.nodeData.id,
        class: normalizeClass(
          unref(cn)(
            "bg-white dark-theme:bg-[#15161A]",
            "min-w-[445px]",
            "lg-node absolute border border-solid rounded-2xl",
            "outline outline-transparent outline-2 hover:outline-black dark-theme:hover:outline-white",
            {
              "border-blue-500 ring-2 ring-blue-300": _ctx.selected,
              "border-[#e1ded5] dark-theme:border-[#292A30]": !_ctx.selected,
              "animate-pulse": _ctx.executing,
              "opacity-50": _ctx.nodeData.mode === 4,
              "border-red-500 bg-red-50": _ctx.error,
              "will-change-transform": isDragging.value
            },
            unref(lodCssClass)
          )
        ),
        style: normalizeStyle([
          {
            transform: `translate(${unref(layoutPosition).x ?? _ctx.position?.x ?? 0}px, ${(unref(layoutPosition).y ?? _ctx.position?.y ?? 0) - unref(LiteGraph).NODE_TITLE_HEIGHT}px)`,
            pointerEvents: "auto"
          },
          dragStyle.value
        ]),
        onPointerdown: handlePointerDown,
        onPointermove: handlePointerMove,
        onPointerup: handlePointerUp
      }, [
        createElementVNode("div", _hoisted_3$a, [
          isCollapsed.value ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [
            createVNode(_sfc_main$Q, {
              multi: "",
              class: "absolute left-0 -translate-x-1/2"
            }),
            createVNode(_sfc_main$Q, {
              multi: "",
              class: "absolute right-0 translate-x-1/2"
            })
          ], 64)) : createCommentVNode("", true),
          withMemo([_ctx.nodeData.title, unref(lodLevel), isCollapsed.value], () => createVNode(_sfc_main$R, {
            "node-data": _ctx.nodeData,
            readonly: _ctx.readonly,
            "lod-level": unref(lodLevel),
            collapsed: isCollapsed.value,
            onCollapse: handleCollapse,
            "onUpdate:title": handleTitleUpdate
          }, null, 8, ["node-data", "readonly", "lod-level", "collapsed"]), _cache, 0)
        ]),
        !isMinimalLOD.value && !isCollapsed.value ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [
          createElementVNode("div", {
            class: normalizeClass(unref(cn)(separatorClasses, "mb-4"))
          }, null, 2),
          createElementVNode("div", {
            class: "flex flex-col gap-4 pb-4",
            "data-testid": `node-body-${_ctx.nodeData.id}`
          }, [
            unref(shouldRenderSlots) ? withMemo([_ctx.nodeData.inputs?.length, _ctx.nodeData.outputs?.length, unref(lodLevel)], () => (openBlock(), createBlock(_sfc_main$N, {
              key: 0,
              "node-data": _ctx.nodeData,
              readonly: _ctx.readonly,
              "lod-level": unref(lodLevel),
              onSlotClick: handleSlotClick
            }, null, 8, ["node-data", "readonly", "lod-level"])), _cache, 1) : createCommentVNode("", true),
            unref(shouldRenderSlots) && shouldShowWidgets.value ? (openBlock(), createElementBlock("div", {
              key: 1,
              class: normalizeClass(separatorClasses)
            })) : createCommentVNode("", true),
            shouldShowWidgets.value ? withMemo([_ctx.nodeData.widgets?.length, unref(lodLevel)], () => (openBlock(), createBlock(_sfc_main$v, {
              key: 2,
              "node-data": _ctx.nodeData,
              readonly: _ctx.readonly,
              "lod-level": unref(lodLevel)
            }, null, 8, ["node-data", "readonly", "lod-level"])), _cache, 2) : createCommentVNode("", true),
            (unref(shouldRenderSlots) || shouldShowWidgets.value) && shouldShowContent.value ? (openBlock(), createElementBlock("div", {
              key: 3,
              class: normalizeClass(separatorClasses)
            })) : createCommentVNode("", true),
            shouldShowContent.value ? (openBlock(), createBlock(_sfc_main$S, {
              key: 4,
              "node-data": _ctx.nodeData,
              readonly: _ctx.readonly,
              "lod-level": unref(lodLevel)
            }, null, 8, ["node-data", "readonly", "lod-level"])) : createCommentVNode("", true)
          ], 8, _hoisted_4$9)
        ], 64)) : createCommentVNode("", true),
        _ctx.executing && _ctx.progress !== void 0 ? (openBlock(), createElementBlock("div", {
          key: 1,
          class: "absolute bottom-0 left-0 h-1 bg-primary-500 transition-all duration-300",
          style: normalizeStyle({ width: `${_ctx.progress * 100}%` })
        }, null, 4)) : createCommentVNode("", true)
      ], 46, _hoisted_2$e));
    };
  }
});
let pendingCallbacks = [];
let isNewUserDetermined = false;
let isNewUserCached = null;
const newUserService = /* @__PURE__ */ __name(() => {
  function checkIsNewUser(settingStore) {
    const isNewUserSettings = Object.keys(settingStore.settingValues).length === 0 || !settingStore.get("Comfy.TutorialCompleted");
    const hasNoWorkflow = !localStorage.getItem("workflow");
    const hasNoPreviousWorkflow = !localStorage.getItem(
      "Comfy.PreviousWorkflow"
    );
    return isNewUserSettings && hasNoWorkflow && hasNoPreviousWorkflow;
  }
  __name(checkIsNewUser, "checkIsNewUser");
  async function registerInitCallback(callback) {
    if (isNewUserDetermined) {
      if (isNewUserCached) {
        try {
          await callback();
        } catch (error) {
          console.error("New user initialization callback failed:", error);
        }
      }
    } else {
      pendingCallbacks.push(callback);
    }
  }
  __name(registerInitCallback, "registerInitCallback");
  async function initializeIfNewUser(settingStore) {
    if (isNewUserDetermined) return;
    isNewUserCached = checkIsNewUser(settingStore);
    isNewUserDetermined = true;
    if (!isNewUserCached) {
      pendingCallbacks = [];
      return;
    }
    await settingStore.set(
      "Comfy.InstalledVersion",
      "1.27.1"
    );
    for (const callback of pendingCallbacks) {
      try {
        await callback();
      } catch (error) {
        console.error("New user initialization callback failed:", error);
      }
    }
    pendingCallbacks = [];
  }
  __name(initializeIfNewUser, "initializeIfNewUser");
  function isNewUser() {
    return isNewUserDetermined ? isNewUserCached : null;
  }
  __name(isNewUser, "isNewUser");
  return {
    registerInitCallback,
    initializeIfNewUser,
    isNewUser
  };
}, "newUserService");
const _hoisted_1$D = { class: "absolute top-0 left-0 w-auto max-w-full pointer-events-auto" };
const _sfc_main$t = /* @__PURE__ */ defineComponent({
  __name: "GraphCanvas",
  emits: ["ready"],
  setup(__props, { emit: __emit }) {
    const emit = __emit;
    const canvasRef = ref(null);
    const nodeSearchboxPopoverRef = shallowRef(null);
    const settingStore = useSettingStore();
    const nodeDefStore = useNodeDefStore();
    const workspaceStore = useWorkspaceStore();
    const canvasStore = useCanvasStore();
    const executionStore = useExecutionStore();
    const toastStore = useToastStore();
    const layoutMutations = useLayoutMutations();
    const betaMenuEnabled = computed(
      () => settingStore.get("Comfy.UseNewMenu") !== "Disabled"
    );
    const workflowTabsPosition = computed(
      () => settingStore.get("Comfy.Workflow.WorkflowTabsPosition")
    );
    const canvasMenuEnabled = computed(
      () => settingStore.get("Comfy.Graph.CanvasMenu")
    );
    const tooltipEnabled = computed(() => settingStore.get("Comfy.EnableTooltips"));
    const selectionToolboxEnabled = computed(
      () => settingStore.get("Comfy.Canvas.SelectionToolbox")
    );
    const minimapEnabled = computed(() => settingStore.get("Comfy.Minimap.Visible"));
    const { shouldRenderVueNodes } = useVueFeatureFlags();
    const isVueNodesEnabled = computed(() => shouldRenderVueNodes.value);
    let nodeManager = null;
    let cleanupNodeManager = null;
    let slotSync = null;
    let linkSync = null;
    const vueNodeData = ref(/* @__PURE__ */ new Map());
    const nodeState = ref(/* @__PURE__ */ new Map());
    const nodePositions = ref(
      /* @__PURE__ */ new Map()
    );
    const nodeSizes = ref(
      /* @__PURE__ */ new Map()
    );
    let detectChangesInRAF = /* @__PURE__ */ __name(() => {
    }, "detectChangesInRAF");
    const nodeDataTrigger = ref(0);
    const initializeNodeManager = /* @__PURE__ */ __name(() => {
      if (!app.graph || nodeManager) return;
      nodeManager = useGraphNodeManager(app.graph);
      cleanupNodeManager = nodeManager.cleanup;
      vueNodeData.value = nodeManager.vueNodeData;
      nodeState.value = nodeManager.nodeState;
      nodePositions.value = nodeManager.nodePositions;
      nodeSizes.value = nodeManager.nodeSizes;
      detectChangesInRAF = nodeManager.detectChangesInRAF;
      const nodes = app.graph._nodes.map((node) => ({
        id: node.id.toString(),
        pos: node.pos,
        size: node.size
      }));
      layoutStore.initializeFromLiteGraph(nodes);
      for (const reroute of app.graph.reroutes.values()) {
        const [x, y] = reroute.pos;
        const parent = reroute.parentId ?? void 0;
        const linkIds = Array.from(reroute.linkIds);
        layoutMutations.createReroute(reroute.id, { x, y }, parent, linkIds);
      }
      for (const link of app.graph._links.values()) {
        layoutMutations.createLink(
          link.id,
          link.origin_id,
          link.origin_slot,
          link.target_id,
          link.target_slot
        );
      }
      const { startSync } = useLayoutSync();
      startSync(canvasStore.canvas);
      slotSync = useSlotLayoutSync();
      if (canvasStore.canvas) {
        slotSync.start(canvasStore.canvas);
      }
      linkSync = useLinkLayoutSync();
      if (canvasStore.canvas) {
        linkSync.start(canvasStore.canvas);
      }
      nodeDataTrigger.value++;
    }, "initializeNodeManager");
    const disposeNodeManagerAndSyncs = /* @__PURE__ */ __name(() => {
      if (!nodeManager) return;
      try {
        cleanupNodeManager?.();
      } catch {
      }
      nodeManager = null;
      cleanupNodeManager = null;
      if (slotSync) {
        slotSync.stop();
        slotSync = null;
      }
      if (linkSync) {
        linkSync.stop();
        linkSync = null;
      }
      vueNodeData.value = /* @__PURE__ */ new Map();
      nodeState.value = /* @__PURE__ */ new Map();
      nodePositions.value = /* @__PURE__ */ new Map();
      nodeSizes.value = /* @__PURE__ */ new Map();
    }, "disposeNodeManagerAndSyncs");
    watch(
      () => isVueNodesEnabled.value && Boolean(app.graph),
      (enabled) => {
        if (enabled) {
          initializeNodeManager();
        } else {
          disposeNodeManagerAndSyncs();
        }
      },
      { immediate: true }
    );
    const { syncWithCanvas } = useTransformState();
    const nodesToRender = computed(() => {
      if (!isVueNodesEnabled.value) {
        return [];
      }
      void nodeDataTrigger.value;
      if (!app.graph) {
        return [];
      }
      const allNodes = Array.from(vueNodeData.value.values());
      if (nodeManager && canvasStore.canvas && app.canvas) {
        const canvas = canvasStore.canvas;
        const manager = nodeManager;
        syncWithCanvas(app.canvas);
        const ds = canvas.ds;
        const viewport_width = canvas.canvas.width;
        const viewport_height = canvas.canvas.height;
        const canvasMarginDistance = 200;
        const margin_x = canvasMarginDistance * ds.scale;
        const margin_y = canvasMarginDistance * ds.scale;
        const filtered = allNodes.filter((nodeData) => {
          const node = manager.getNode(nodeData.id);
          if (!node) return false;
          const screen_x = (node.pos[0] + ds.offset[0]) * ds.scale;
          const screen_y = (node.pos[1] + ds.offset[1]) * ds.scale;
          const screen_width = node.size[0] * ds.scale;
          const screen_height = node.size[1] * ds.scale;
          const isVisible = !(screen_x + screen_width < -margin_x || screen_x > viewport_width + margin_x || screen_y + screen_height < -margin_y || screen_y > viewport_height + margin_y);
          return isVisible;
        });
        return filtered;
      }
      return allNodes;
    });
    let lastScale = 1;
    let lastOffsetX = 0;
    let lastOffsetY = 0;
    const handleTransformUpdate = /* @__PURE__ */ __name(() => {
      if (!isVueNodesEnabled.value) {
        return;
      }
      if (app.canvas?.ds) {
        const currentScale = app.canvas.ds.scale;
        const currentOffsetX = app.canvas.ds.offset[0];
        const currentOffsetY = app.canvas.ds.offset[1];
        if (currentScale !== lastScale || currentOffsetX !== lastOffsetX || currentOffsetY !== lastOffsetY) {
          syncWithCanvas(app.canvas);
          lastScale = currentScale;
          lastOffsetX = currentOffsetX;
          lastOffsetY = currentOffsetY;
        }
      }
      detectChangesInRAF();
      void nodesToRender.value.length;
    }, "handleTransformUpdate");
    const handleNodeSelect = /* @__PURE__ */ __name((event, nodeData) => {
      if (!canvasStore.canvas || !nodeManager) return;
      const node = nodeManager.getNode(nodeData.id);
      if (!node) return;
      if (!event.ctrlKey && !event.metaKey) {
        canvasStore.canvas.deselectAllNodes();
      }
      canvasStore.canvas.selectNode(node);
      if (!node.flags?.pinned) {
        layoutMutations.setSource(LayoutSource.Vue);
        layoutMutations.bringNodeToFront(nodeData.id);
      }
      node.selected = true;
      canvasStore.updateSelectedItems();
    }, "handleNodeSelect");
    const handleNodeCollapse = /* @__PURE__ */ __name((nodeId, collapsed) => {
      if (!nodeManager) return;
      const node = nodeManager.getNode(nodeId);
      if (!node) return;
      const currentCollapsed = node.flags?.collapsed ?? false;
      if (currentCollapsed !== collapsed) {
        node.collapse();
      }
    }, "handleNodeCollapse");
    const handleNodeTitleUpdate = /* @__PURE__ */ __name((nodeId, newTitle) => {
      if (!nodeManager) return;
      const node = nodeManager.getNode(nodeId);
      if (!node) return;
      node.title = newTitle;
    }, "handleNodeTitleUpdate");
    watchEffect(() => {
      nodeDefStore.showDeprecated = settingStore.get("Comfy.Node.ShowDeprecated");
    });
    watchEffect(() => {
      nodeDefStore.showExperimental = settingStore.get(
        "Comfy.Node.ShowExperimental"
      );
    });
    watchEffect(() => {
      const spellcheckEnabled = settingStore.get("Comfy.TextareaWidget.Spellcheck");
      const textareas = document.querySelectorAll(
        "textarea.comfy-multiline-input"
      );
      textareas.forEach((textarea) => {
        textarea.spellcheck = spellcheckEnabled;
        textarea.focus();
        textarea.blur();
      });
    });
    watch(
      () => settingStore.get("Comfy.WidgetControlMode"),
      () => {
        if (!canvasStore.canvas) return;
        for (const n of app.graph.nodes) {
          if (!n.widgets) continue;
          for (const w of n.widgets) {
            if (w[IS_CONTROL_WIDGET]) {
              updateControlWidgetLabel(w);
              if (w.linkedWidgets) {
                for (const l of w.linkedWidgets) {
                  updateControlWidgetLabel(l);
                }
              }
            }
          }
        }
        app.graph.setDirtyCanvas(true);
      }
    );
    const colorPaletteService = useColorPaletteService();
    const colorPaletteStore = useColorPaletteStore();
    watch(
      [() => canvasStore.canvas, () => settingStore.get("Comfy.ColorPalette")],
      async ([canvas, currentPaletteId]) => {
        if (!canvas) return;
        await colorPaletteService.loadColorPalette(currentPaletteId);
      }
    );
    watch(
      () => settingStore.get("Comfy.Canvas.BackgroundImage"),
      async () => {
        if (!canvasStore.canvas) return;
        const currentPaletteId = colorPaletteStore.activePaletteId;
        if (!currentPaletteId) return;
        await colorPaletteService.loadColorPalette(currentPaletteId);
        canvasStore.canvas.setDirty(false, true);
      }
    );
    watch(
      () => colorPaletteStore.activePaletteId,
      async (newValue) => {
        await settingStore.set("Comfy.ColorPalette", newValue);
      }
    );
    watch(
      () => [executionStore.nodeLocationProgressStates, canvasStore.canvas],
      ([nodeLocationProgressStates, canvas]) => {
        if (!canvas?.graph) return;
        for (const node of canvas.graph.nodes) {
          const nodeLocatorId = useWorkflowStore().nodeIdToNodeLocatorId(node.id);
          const progressState = nodeLocationProgressStates[nodeLocatorId];
          if (progressState && progressState.state === "running") {
            node.progress = progressState.value / progressState.max;
          } else {
            node.progress = void 0;
          }
        }
        canvas.graph.setDirtyCanvas(true, false);
      },
      { deep: true }
    );
    watch(
      () => executionStore.lastNodeErrors,
      (lastNodeErrors) => {
        const removeSlotError = /* @__PURE__ */ __name((node) => {
          for (const slot of node.inputs) {
            delete slot.hasErrors;
          }
          for (const slot of node.outputs) {
            delete slot.hasErrors;
          }
        }, "removeSlotError");
        for (const node of app.graph.nodes) {
          removeSlotError(node);
          const nodeErrors = lastNodeErrors?.[node.id];
          if (!nodeErrors) continue;
          for (const error of nodeErrors.errors) {
            if (error.extra_info && error.extra_info.input_name) {
              const inputIndex = node.findInputSlot(error.extra_info.input_name);
              if (inputIndex !== -1) {
                node.inputs[inputIndex].hasErrors = true;
              }
            }
          }
        }
        app.canvas.draw(true, true);
      }
    );
    useEventListener(
      canvasRef,
      "litegraph:no-items-selected",
      () => {
        toastStore.add({
          severity: "warn",
          summary: t("toastMessages.nothingSelected"),
          life: 2e3
        });
      },
      { passive: true }
    );
    const loadCustomNodesI18n = /* @__PURE__ */ __name(async () => {
      try {
        const i18nData = await api.getCustomNodesI18n();
        Object.entries(i18nData).forEach(([locale, message]) => {
          i18n.global.mergeLocaleMessage(locale, message);
        });
      } catch (error) {
        console.error("Failed to load custom nodes i18n", error);
      }
    }, "loadCustomNodesI18n");
    const comfyAppReady = ref(false);
    const workflowPersistence = useWorkflowPersistence();
    useCanvasDrop(canvasRef);
    useLitegraphSettings();
    useNodeBadge();
    onMounted(async () => {
      useGlobalLitegraph();
      useContextMenuTranslation();
      useCopy();
      usePaste();
      useWorkflowAutoSave();
      useVueFeatureFlags();
      app.vueAppReady = true;
      workspaceStore.spinner = true;
      ChangeTracker.init();
      await loadCustomNodesI18n();
      try {
        await settingStore.loadSettingValues();
      } catch (error) {
        if (error instanceof UnauthorizedError) {
          localStorage.removeItem("Comfy.userId");
          localStorage.removeItem("Comfy.userName");
          window.location.reload();
        } else {
          throw error;
        }
      }
      CORE_SETTINGS.forEach((setting) => {
        settingStore.addSetting(setting);
      });
      await newUserService().initializeIfNewUser(settingStore);
      await app.setup(canvasRef.value);
      canvasStore.canvas = app.canvas;
      canvasStore.canvas.render_canvas_border = false;
      workspaceStore.spinner = false;
      useSearchBoxStore().setPopoverRef(nodeSearchboxPopoverRef.value);
      window.app = app;
      window.graph = app.graph;
      comfyAppReady.value = true;
      if (isVueNodesEnabled.value) {
        if (app.graph && !nodeManager && app.graph._nodes.length === 0) {
          const originalOnNodeAdded = app.graph.onNodeAdded;
          app.graph.onNodeAdded = function(node) {
            app.graph.onNodeAdded = originalOnNodeAdded;
            if (isVueNodesEnabled.value && !nodeManager) {
              initializeNodeManager();
            }
            if (originalOnNodeAdded) {
              originalOnNodeAdded.call(this, node);
            }
          };
        }
      }
      app.canvas.onSelectionChange = useChainCallback(
        app.canvas.onSelectionChange,
        () => canvasStore.updateSelectedItems()
      );
      colorPaletteStore.customPalettes = settingStore.get(
        "Comfy.CustomColorPalettes"
      );
      await workflowPersistence.restorePreviousWorkflow();
      workflowPersistence.restoreWorkflowTabsState();
      const { useReleaseStore: useReleaseStore2 } = await __vitePreload(async () => {
        const { useReleaseStore: useReleaseStore3 } = await Promise.resolve().then(() => releaseStore);
        return { useReleaseStore: useReleaseStore3 };
      }, true ? void 0 : void 0, import.meta.url);
      const releaseStore$1 = useReleaseStore2();
      void releaseStore$1.initialize();
      watch(
        () => settingStore.get("Comfy.Locale"),
        async () => {
          await useCommandStore().execute("Comfy.RefreshNodeDefinitions");
          await useWorkflowService().reloadCurrentWorkflow();
        }
      );
      whenever(
        () => useCanvasStore().canvas,
        (canvas) => {
          useEventListener(canvas.canvas, "litegraph:set-graph", () => {
            useWorkflowStore().updateActiveGraph();
          });
        },
        { immediate: true }
      );
      emit("ready");
    });
    onUnmounted(() => {
      if (nodeManager) {
        nodeManager.cleanup();
        nodeManager = null;
      }
      if (slotSync) {
        slotSync.stop();
        slotSync = null;
      }
      if (linkSync) {
        linkSync.stop();
        linkSync = null;
      }
    });
    return (_ctx, _cache) => {
      return openBlock(), createElementBlock(Fragment, null, [
        comfyAppReady.value && betaMenuEnabled.value ? (openBlock(), createBlock(LiteGraphCanvasSplitterOverlay, { key: 0 }, createSlots({
          "graph-canvas-panel": withCtx(() => [
            createElementVNode("div", _hoisted_1$D, [
              workflowTabsPosition.value === "Topbar (2nd-row)" ? (openBlock(), createBlock(SecondRowWorkflowTabs, { key: 0 })) : createCommentVNode("", true)
            ]),
            canvasMenuEnabled.value ? (openBlock(), createBlock(GraphCanvasMenu, {
              key: 0,
              class: "pointer-events-auto"
            })) : createCommentVNode("", true),
            comfyAppReady.value && minimapEnabled.value ? (openBlock(), createBlock(MiniMap, {
              key: 1,
              class: "pointer-events-auto"
            })) : createCommentVNode("", true)
          ]),
          _: 2
        }, [
          !unref(workspaceStore).focusMode ? {
            name: "side-bar-panel",
            fn: withCtx(() => [
              createVNode(SideToolbar)
            ]),
            key: "0"
          } : void 0,
          !unref(workspaceStore).focusMode ? {
            name: "bottom-panel",
            fn: withCtx(() => [
              createVNode(_sfc_main$1w)
            ]),
            key: "1"
          } : void 0
        ]), 1024)) : createCommentVNode("", true),
        !betaMenuEnabled.value && canvasMenuEnabled.value ? (openBlock(), createBlock(GraphCanvasMenu, { key: 1 })) : createCommentVNode("", true),
        createElementVNode("canvas", {
          id: "graph-canvas",
          ref_key: "canvasRef",
          ref: canvasRef,
          tabindex: "1",
          class: "w-full h-full touch-none"
        }, null, 512),
        isVueNodesEnabled.value && unref(canvasStore).canvas && comfyAppReady.value ? (openBlock(), createBlock(TransformPane, {
          key: 2,
          canvas: unref(canvasStore).canvas,
          onTransformUpdate: handleTransformUpdate
        }, {
          default: withCtx(() => [
            (openBlock(true), createElementBlock(Fragment, null, renderList(nodesToRender.value, (nodeData) => {
              return openBlock(), createBlock(_sfc_main$u, {
                key: nodeData.id,
                "node-data": nodeData,
                position: nodePositions.value.get(nodeData.id),
                size: nodeSizes.value.get(nodeData.id),
                selected: nodeData.selected,
                readonly: false,
                executing: unref(executionStore).executingNodeId === nodeData.id,
                error: unref(executionStore).lastExecutionError?.node_id === nodeData.id ? "Execution error" : null,
                "zoom-level": unref(canvasStore).canvas?.ds?.scale || 1,
                "data-node-id": nodeData.id,
                onNodeClick: handleNodeSelect,
                "onUpdate:collapsed": handleNodeCollapse,
                "onUpdate:title": handleNodeTitleUpdate
              }, null, 8, ["node-data", "position", "size", "selected", "executing", "error", "zoom-level", "data-node-id"]);
            }), 128))
          ]),
          _: 1
        }, 8, ["canvas"])) : createCommentVNode("", true),
        tooltipEnabled.value ? (openBlock(), createBlock(NodeTooltip, { key: 3 })) : createCommentVNode("", true),
        createVNode(_sfc_main$17, {
          ref_key: "nodeSearchboxPopoverRef",
          ref: nodeSearchboxPopoverRef
        }, null, 512),
        comfyAppReady.value ? (openBlock(), createElementBlock(Fragment, { key: 4 }, [
          createVNode(TitleEditor),
          selectionToolboxEnabled.value ? (openBlock(), createBlock(SelectionToolbox, { key: 0 })) : createCommentVNode("", true),
          !unref(shouldRenderVueNodes) ? (openBlock(), createBlock(_sfc_main$1u, { key: 1 })) : createCommentVNode("", true)
        ], 64)) : createCommentVNode("", true)
      ], 64);
    };
  }
});
const _sfc_main$s = /* @__PURE__ */ defineComponent({
  __name: "GlobalToast",
  setup(__props) {
    const toast = useToast();
    const toastStore = useToastStore();
    const settingStore = useSettingStore();
    watch(
      () => toastStore.messagesToAdd,
      (newMessages) => {
        if (newMessages.length === 0) {
          return;
        }
        newMessages.forEach((message) => {
          toast.add(message);
        });
        toastStore.messagesToAdd = [];
      },
      { deep: true }
    );
    watch(
      () => toastStore.messagesToRemove,
      (messagesToRemove) => {
        if (messagesToRemove.length === 0) {
          return;
        }
        messagesToRemove.forEach((message) => {
          toast.remove(message);
        });
        toastStore.messagesToRemove = [];
      },
      { deep: true }
    );
    watch(
      () => toastStore.removeAllRequested,
      (requested) => {
        if (requested) {
          toast.removeAllGroups();
          toastStore.removeAllRequested = false;
        }
      }
    );
    function updateToastPosition() {
      const styleElement = document.getElementById("dynamic-toast-style") || createStyleElement();
      const rect = document.querySelector(".graph-canvas-container")?.getBoundingClientRect();
      if (!rect) return;
      styleElement.textContent = `
    .p-toast.p-component.p-toast-top-right {
      top: ${rect.top + 20}px !important;
      right: ${window.innerWidth - (rect.left + rect.width) + 20}px !important;
    }
  `;
    }
    __name(updateToastPosition, "updateToastPosition");
    function createStyleElement() {
      const style = document.createElement("style");
      style.id = "dynamic-toast-style";
      document.head.appendChild(style);
      return style;
    }
    __name(createStyleElement, "createStyleElement");
    watch(
      () => settingStore.get("Comfy.UseNewMenu"),
      () => nextTick(updateToastPosition),
      { immediate: true }
    );
    watch(
      () => settingStore.get("Comfy.Sidebar.Location"),
      () => nextTick(updateToastPosition),
      { immediate: true }
    );
    return (_ctx, _cache) => {
      return openBlock(), createBlock(unref(Toast));
    };
  }
});
const _hoisted_1$C = { class: "flex flex-col items-start flex-auto" };
const _hoisted_2$d = { class: "font-medium text-lg my-4" };
const _sfc_main$r = /* @__PURE__ */ defineComponent({
  __name: "RerouteMigrationToast",
  setup(__props) {
    const { t: t2 } = useI18n();
    const toast = useToast$1();
    const workflowStore = useWorkflowStore();
    const migrateToLitegraphReroute = /* @__PURE__ */ __name(async () => {
      const workflowJSON = app.graph.serialize();
      const migratedWorkflowJSON = migrateLegacyRerouteNodes(workflowJSON);
      await app.loadGraphData(
        migratedWorkflowJSON,
        false,
        false,
        workflowStore.activeWorkflow
      );
      toast.removeGroup("reroute-migration");
    }, "migrateToLitegraphReroute");
    return (_ctx, _cache) => {
      return openBlock(), createBlock(unref(Toast), { group: "reroute-migration" }, {
        message: withCtx(() => [
          createElementVNode("div", _hoisted_1$C, [
            createElementVNode("div", _hoisted_2$d, toDisplayString(unref(t2)("toastMessages.migrateToLitegraphReroute")), 1),
            createVNode(unref(Button), {
              class: "self-end",
              size: "small",
              label: unref(t2)("g.migrate"),
              severity: "warn",
              onClick: migrateToLitegraphReroute
            }, null, 8, ["label"])
          ])
        ]),
        _: 1
      });
    };
  }
});
const _hoisted_1$B = {
  viewBox: "0 0 24 24",
  width: "1.2em",
  height: "1.2em"
};
function render$g(_ctx, _cache) {
  return openBlock(), createElementBlock("svg", _hoisted_1$B, _cache[0] || (_cache[0] = [
    createElementVNode("path", {
      fill: "none",
      stroke: "currentColor",
      "stroke-linecap": "round",
      "stroke-linejoin": "round",
      "stroke-width": "2",
      d: "M10.029 4.285A2 2 0 0 0 7 6v12a2 2 0 0 0 3.029 1.715l9.997-5.998a2 2 0 0 0 .003-3.432zM3 4v16"
    }, null, -1)
  ]));
}
__name(render$g, "render$g");
const __unplugin_components_3$2 = markRaw({ name: "lucide-step-forward", render: render$g });
const _hoisted_1$A = {
  viewBox: "0 0 24 24",
  width: "1.2em",
  height: "1.2em"
};
function render$f(_ctx, _cache) {
  return openBlock(), createElementBlock("svg", _hoisted_1$A, _cache[0] || (_cache[0] = [
    createElementVNode("g", {
      fill: "none",
      stroke: "currentColor",
      "stroke-linecap": "round",
      "stroke-linejoin": "round",
      "stroke-width": "2"
    }, [
      createElementVNode("path", { d: "M12 6a2 2 0 0 1 3.414-1.414l6 6a2 2 0 0 1 0 2.828l-6 6A2 2 0 0 1 12 18z" }),
      createElementVNode("path", { d: "M2 6a2 2 0 0 1 3.414-1.414l6 6a2 2 0 0 1 0 2.828l-6 6A2 2 0 0 1 2 18z" })
    ], -1)
  ]));
}
__name(render$f, "render$f");
const __unplugin_components_2$2 = markRaw({ name: "lucide-fast-forward", render: render$f });
const _hoisted_1$z = {
  viewBox: "0 0 24 24",
  width: "1.2em",
  height: "1.2em"
};
function render$e(_ctx, _cache) {
  return openBlock(), createElementBlock("svg", _hoisted_1$z, _cache[0] || (_cache[0] = [
    createElementVNode("g", {
      fill: "none",
      stroke: "currentColor",
      "stroke-linecap": "round",
      "stroke-linejoin": "round",
      "stroke-width": "2"
    }, [
      createElementVNode("path", { d: "M3 5h6m-6 7h13M3 19h13m0-11l-3-3l3-3" }),
      createElementVNode("path", { d: "M21 19V7a2 2 0 0 0-2-2h-6" })
    ], -1)
  ]));
}
__name(render$e, "render$e");
const __unplugin_components_0$4 = markRaw({ name: "lucide-list-start", render: render$e });
const _hoisted_1$y = ["aria-label"];
const minQueueCount = 1;
const _sfc_main$q = /* @__PURE__ */ defineComponent({
  __name: "BatchCountEdit",
  setup(__props) {
    const queueSettingsStore = useQueueSettingsStore();
    const { batchCount } = storeToRefs(queueSettingsStore);
    const settingStore = useSettingStore();
    const maxQueueCount = computed(
      () => settingStore.get("Comfy.QueueButton.BatchCountLimit")
    );
    const handleClick = /* @__PURE__ */ __name((increment) => {
      let newCount;
      if (increment) {
        const originalCount = batchCount.value - 1;
        newCount = Math.min(originalCount * 2, maxQueueCount.value);
      } else {
        const originalCount = batchCount.value + 1;
        newCount = Math.floor(originalCount / 2);
      }
      batchCount.value = newCount;
    }, "handleClick");
    return (_ctx, _cache) => {
      const _directive_tooltip = resolveDirective("tooltip");
      return withDirectives((openBlock(), createElementBlock("div", {
        class: "batch-count",
        "aria-label": _ctx.$t("menu.batchCount")
      }, [
        createVNode(unref(InputNumber$1), {
          modelValue: unref(batchCount),
          "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => isRef(batchCount) ? batchCount.value = $event : null),
          class: "w-14",
          min: minQueueCount,
          max: maxQueueCount.value,
          fluid: "",
          "show-buttons": "",
          pt: {
            incrementButton: {
              class: "w-6",
              onmousedown: /* @__PURE__ */ __name(() => {
                handleClick(true);
              }, "onmousedown")
            },
            decrementButton: {
              class: "w-6",
              onmousedown: /* @__PURE__ */ __name(() => {
                handleClick(false);
              }, "onmousedown")
            }
          }
        }, null, 8, ["modelValue", "max", "pt"])
      ], 8, _hoisted_1$y)), [
        [
          _directive_tooltip,
          {
            value: _ctx.$t("menu.batchCount"),
            showDelay: 600
          },
          void 0,
          { bottom: true }
        ]
      ]);
    };
  }
});
const BatchCountEdit = /* @__PURE__ */ _export_sfc(_sfc_main$q, [["__scopeId", "data-v-78201e86"]]);
const _hoisted_1$x = { class: "queue-button-group flex" };
const _sfc_main$p = /* @__PURE__ */ defineComponent({
  __name: "ComfyQueueButton",
  setup(__props) {
    const workspaceStore = useWorkspaceStore();
    const queueCountStore = storeToRefs(useQueuePendingTaskCountStore());
    const { mode: queueMode } = storeToRefs(useQueueSettingsStore());
    const { t: t2 } = useI18n();
    const queueModeMenuItemLookup = computed(() => ({
      disabled: {
        key: "disabled",
        label: t2("menu.run"),
        tooltip: t2("menu.disabledTooltip"),
        command: /* @__PURE__ */ __name(() => {
          queueMode.value = "disabled";
        }, "command")
      },
      instant: {
        key: "instant",
        label: `${t2("menu.run")} (${t2("menu.instant")})`,
        tooltip: t2("menu.instantTooltip"),
        command: /* @__PURE__ */ __name(() => {
          queueMode.value = "instant";
        }, "command")
      },
      change: {
        key: "change",
        label: `${t2("menu.run")} (${t2("menu.onChange")})`,
        tooltip: t2("menu.onChangeTooltip"),
        command: /* @__PURE__ */ __name(() => {
          queueMode.value = "change";
        }, "command")
      }
    }));
    const activeQueueModeMenuItem = computed(
      () => queueModeMenuItemLookup.value[queueMode.value]
    );
    const queueModeMenuItems = computed(
      () => Object.values(queueModeMenuItemLookup.value)
    );
    const executingPrompt = computed(() => !!queueCountStore.count.value);
    const hasPendingTasks = computed(
      () => queueCountStore.count.value > 1 || queueMode.value !== "disabled"
    );
    const commandStore = useCommandStore();
    const queuePrompt = /* @__PURE__ */ __name(async (e) => {
      const commandId = "shiftKey" in e && e.shiftKey ? "Comfy.QueuePromptFront" : "Comfy.QueuePrompt";
      await commandStore.execute(commandId);
    }, "queuePrompt");
    return (_ctx, _cache) => {
      const _component_i_lucide58list_start = __unplugin_components_0$4;
      const _component_i_lucide58play = __unplugin_components_1$3;
      const _component_i_lucide58fast_forward = __unplugin_components_2$2;
      const _component_i_lucide58step_forward = __unplugin_components_3$2;
      const _directive_tooltip = resolveDirective("tooltip");
      return openBlock(), createElementBlock("div", _hoisted_1$x, [
        withDirectives((openBlock(), createBlock(unref(SplitButton), {
          class: "comfyui-queue-button",
          label: activeQueueModeMenuItem.value.label,
          severity: "primary",
          size: "small",
          model: queueModeMenuItems.value,
          "data-testid": "queue-button",
          onClick: queuePrompt
        }, {
          icon: withCtx(() => [
            unref(workspaceStore).shiftDown ? (openBlock(), createBlock(_component_i_lucide58list_start, { key: 0 })) : unref(queueMode) === "disabled" ? (openBlock(), createBlock(_component_i_lucide58play, { key: 1 })) : unref(queueMode) === "instant" ? (openBlock(), createBlock(_component_i_lucide58fast_forward, { key: 2 })) : unref(queueMode) === "change" ? (openBlock(), createBlock(_component_i_lucide58step_forward, { key: 3 })) : createCommentVNode("", true)
          ]),
          item: withCtx(({ item }) => [
            withDirectives(createVNode(unref(Button), {
              label: String(item.label),
              icon: item.icon,
              severity: item.key === unref(queueMode) ? "primary" : "secondary",
              size: "small",
              text: ""
            }, null, 8, ["label", "icon", "severity"]), [
              [_directive_tooltip, {
                value: item.tooltip,
                showDelay: 600
              }]
            ])
          ]),
          _: 1
        }, 8, ["label", "model"])), [
          [
            _directive_tooltip,
            {
              value: unref(workspaceStore).shiftDown ? _ctx.$t("menu.runWorkflowFront") : _ctx.$t("menu.runWorkflow"),
              showDelay: 600
            },
            void 0,
            { bottom: true }
          ]
        ]),
        createVNode(BatchCountEdit),
        createVNode(unref(ButtonGroup), { class: "execution-actions flex flex-nowrap" }, {
          default: withCtx(() => [
            withDirectives(createVNode(unref(Button), {
              icon: "pi pi-times",
              severity: executingPrompt.value ? "danger" : "secondary",
              disabled: !executingPrompt.value,
              text: "",
              "aria-label": _ctx.$t("menu.interrupt"),
              onClick: _cache[0] || (_cache[0] = () => unref(commandStore).execute("Comfy.Interrupt"))
            }, null, 8, ["severity", "disabled", "aria-label"]), [
              [
                _directive_tooltip,
                {
                  value: _ctx.$t("menu.interrupt"),
                  showDelay: 600
                },
                void 0,
                { bottom: true }
              ]
            ]),
            withDirectives(createVNode(unref(Button), {
              icon: "pi pi-stop",
              severity: hasPendingTasks.value ? "danger" : "secondary",
              disabled: !hasPendingTasks.value,
              text: "",
              "aria-label": _ctx.$t("sideToolbar.queueTab.clearPendingTasks"),
              onClick: _cache[1] || (_cache[1] = () => {
                if (unref(queueCountStore).count.value > 1) {
                  unref(commandStore).execute("Comfy.ClearPendingTasks");
                }
                queueMode.value = "disabled";
              })
            }, null, 8, ["severity", "disabled", "aria-label"]), [
              [
                _directive_tooltip,
                {
                  value: _ctx.$t("sideToolbar.queueTab.clearPendingTasks"),
                  showDelay: 600
                },
                void 0,
                { bottom: true }
              ]
            ])
          ]),
          _: 1
        })
      ]);
    };
  }
});
const ComfyQueueButton = /* @__PURE__ */ _export_sfc(_sfc_main$p, [["__scopeId", "data-v-43776fb9"]]);
const overlapThreshold = 20;
const _sfc_main$o = /* @__PURE__ */ defineComponent({
  __name: "ComfyActionbar",
  setup(__props) {
    const settingsStore = useSettingStore();
    const position = computed(() => settingsStore.get("Comfy.UseNewMenu"));
    const visible = computed(() => position.value !== "Disabled");
    const topMenuRef = inject("topMenuRef");
    const panelRef = ref(null);
    const dragHandleRef = ref(null);
    const isDocked = useLocalStorage("Comfy.MenuPosition.Docked", false);
    const storedPosition = useLocalStorage("Comfy.MenuPosition.Floating", {
      x: 0,
      y: 0
    });
    const {
      x,
      y,
      style,
      isDragging
    } = useDraggable(panelRef, {
      initialValue: { x: 0, y: 0 },
      handle: dragHandleRef,
      containerElement: document.body,
      onMove: /* @__PURE__ */ __name((event) => {
        if (position.value === "Top") {
          const minY = topMenuRef?.value?.getBoundingClientRect().top ?? 40;
          if (event.y < minY) {
            event.y = minY;
          }
        }
      }, "onMove")
    });
    watchDebounced(
      [x, y],
      ([newX, newY]) => {
        storedPosition.value = { x: newX, y: newY };
      },
      { debounce: 300 }
    );
    const setInitialPosition = /* @__PURE__ */ __name(() => {
      if (panelRef.value) {
        const screenWidth = window.innerWidth;
        const screenHeight = window.innerHeight;
        const menuWidth = panelRef.value.offsetWidth;
        const menuHeight = panelRef.value.offsetHeight;
        if (menuWidth === 0 || menuHeight === 0) {
          return;
        }
        if (storedPosition.value.x !== 0 || storedPosition.value.y !== 0) {
          x.value = clamp(storedPosition.value.x, 0, screenWidth - menuWidth);
          y.value = clamp(storedPosition.value.y, 0, screenHeight - menuHeight);
          captureLastDragState();
          return;
        }
        if (x.value === 0 && y.value === 0) {
          x.value = clamp((screenWidth - menuWidth) / 2, 0, screenWidth - menuWidth);
          y.value = clamp(
            screenHeight - menuHeight - 10,
            0,
            screenHeight - menuHeight
          );
          captureLastDragState();
        }
      }
    }, "setInitialPosition");
    onMounted(setInitialPosition);
    watch(visible, async (newVisible) => {
      if (newVisible) {
        await nextTick(setInitialPosition);
      }
    });
    const lastDragState = ref({
      x: x.value,
      y: y.value,
      windowWidth: window.innerWidth,
      windowHeight: window.innerHeight
    });
    const captureLastDragState = /* @__PURE__ */ __name(() => {
      lastDragState.value = {
        x: x.value,
        y: y.value,
        windowWidth: window.innerWidth,
        windowHeight: window.innerHeight
      };
    }, "captureLastDragState");
    watch(
      isDragging,
      (newIsDragging) => {
        if (!newIsDragging) {
          captureLastDragState();
        }
      },
      { immediate: true }
    );
    const adjustMenuPosition = /* @__PURE__ */ __name(() => {
      if (panelRef.value) {
        const screenWidth = window.innerWidth;
        const screenHeight = window.innerHeight;
        const menuWidth = panelRef.value.offsetWidth;
        const menuHeight = panelRef.value.offsetHeight;
        const distanceLeft = lastDragState.value.x;
        const distanceRight = lastDragState.value.windowWidth - (lastDragState.value.x + menuWidth);
        const distanceTop = lastDragState.value.y;
        const distanceBottom = lastDragState.value.windowHeight - (lastDragState.value.y + menuHeight);
        const distances = [
          { edge: "left", distance: distanceLeft },
          { edge: "right", distance: distanceRight },
          { edge: "top", distance: distanceTop },
          { edge: "bottom", distance: distanceBottom }
        ];
        const closestEdge = distances.reduce(
          (min, curr) => curr.distance < min.distance ? curr : min
        );
        const verticalRatio = lastDragState.value.y / lastDragState.value.windowHeight;
        const horizontalRatio = lastDragState.value.x / lastDragState.value.windowWidth;
        if (closestEdge.edge === "left") {
          x.value = closestEdge.distance;
          y.value = verticalRatio * screenHeight;
        } else if (closestEdge.edge === "right") {
          x.value = screenWidth - menuWidth - closestEdge.distance;
          y.value = verticalRatio * screenHeight;
        } else if (closestEdge.edge === "top") {
          x.value = horizontalRatio * screenWidth;
          y.value = closestEdge.distance;
        } else {
          x.value = horizontalRatio * screenWidth;
          y.value = screenHeight - menuHeight - closestEdge.distance;
        }
        x.value = clamp(x.value, 0, screenWidth - menuWidth);
        y.value = clamp(y.value, 0, screenHeight - menuHeight);
      }
    }, "adjustMenuPosition");
    useEventListener(window, "resize", adjustMenuPosition);
    const topMenuBounds = useElementBounding(topMenuRef);
    const isOverlappingWithTopMenu = computed(() => {
      if (!panelRef.value) {
        return false;
      }
      const { height } = panelRef.value.getBoundingClientRect();
      const actionbarBottom = y.value + height;
      const topMenuBottom = topMenuBounds.bottom.value;
      const overlapPixels = Math.min(actionbarBottom, topMenuBottom) - Math.max(y.value, topMenuBounds.top.value);
      return overlapPixels > overlapThreshold;
    });
    watch(isDragging, (newIsDragging) => {
      if (!newIsDragging) {
        isDocked.value = isOverlappingWithTopMenu.value;
      } else {
        isDocked.value = false;
      }
    });
    const eventBus = useEventBus("topMenu");
    watch([isDragging, isOverlappingWithTopMenu], ([dragging, overlapping]) => {
      eventBus.emit("updateHighlight", {
        isDragging: dragging,
        isOverlapping: overlapping
      });
    });
    return (_ctx, _cache) => {
      return openBlock(), createBlock(unref(Panel), {
        class: normalizeClass(["actionbar w-fit", { "is-dragging": unref(isDragging), "is-docked": unref(isDocked) }]),
        style: normalizeStyle(unref(style))
      }, {
        default: withCtx(() => [
          createElementVNode("div", {
            ref_key: "panelRef",
            ref: panelRef,
            class: "actionbar-content flex items-center select-none"
          }, [
            createElementVNode("span", {
              ref_key: "dragHandleRef",
              ref: dragHandleRef,
              class: "drag-handle cursor-move mr-2"
            }, null, 512),
            createVNode(ComfyQueueButton)
          ], 512)
        ]),
        _: 1
      }, 8, ["style", "class"]);
    };
  }
});
const Actionbar = /* @__PURE__ */ _export_sfc(_sfc_main$o, [["__scopeId", "data-v-f569bad7"]]);
const _hoisted_1$w = { class: "p-breadcrumb-item-label" };
const _hoisted_2$c = {
  key: 0,
  class: "pi pi-angle-down text-[10px]"
};
const _sfc_main$n = /* @__PURE__ */ defineComponent({
  __name: "SubgraphBreadcrumbItem",
  props: {
    item: {},
    isActive: { type: Boolean, default: false }
  },
  setup(__props) {
    const props = __props;
    const { t: t2 } = useI18n();
    const menu = ref();
    const dialogService = useDialogService();
    const workflowStore = useWorkflowStore();
    const workflowService = useWorkflowService();
    const isEditing = ref(false);
    const itemLabel = ref();
    const itemInputRef = ref();
    const wrapperRef = ref();
    const rename = /* @__PURE__ */ __name(async (newName, initialName) => {
      if (newName && newName !== initialName) {
        props.item.updateTitle?.(newName);
        if (workflowStore.activeSubgraph) {
          workflowStore.activeSubgraph.name = newName;
        } else if (workflowStore.activeWorkflow) {
          try {
            await workflowService.renameWorkflow(
              workflowStore.activeWorkflow,
              ComfyWorkflow.basePath + appendJsonExt(newName)
            );
          } catch (error) {
            console.error(error);
            dialogService.showErrorDialog(error);
            return;
          }
        }
        const navigationStore = useSubgraphNavigationStore();
        navigationStore.restoreState(navigationStore.exportState());
      }
    }, "rename");
    const isRoot = props.item.key === "root";
    const menuItems = computed(() => {
      return [
        {
          label: t2("g.rename"),
          icon: "pi pi-pencil",
          command: startRename
        },
        {
          label: t2("breadcrumbsMenu.duplicate"),
          icon: "pi pi-copy",
          command: /* @__PURE__ */ __name(async () => {
            await workflowService.duplicateWorkflow(workflowStore.activeWorkflow);
          }, "command"),
          visible: isRoot
        },
        {
          separator: true,
          visible: isRoot
        },
        {
          label: t2("menuLabels.Save"),
          icon: "pi pi-save",
          command: /* @__PURE__ */ __name(async () => {
            await useCommandStore().execute("Comfy.SaveWorkflow");
          }, "command"),
          visible: isRoot
        },
        {
          label: t2("menuLabels.Save As"),
          icon: "pi pi-save",
          command: /* @__PURE__ */ __name(async () => {
            await useCommandStore().execute("Comfy.SaveWorkflowAs");
          }, "command"),
          visible: isRoot
        },
        {
          separator: true
        },
        {
          label: t2("breadcrumbsMenu.clearWorkflow"),
          icon: "pi pi-trash",
          command: /* @__PURE__ */ __name(async () => {
            await useCommandStore().execute("Comfy.ClearWorkflow");
          }, "command")
        },
        {
          separator: true,
          visible: isRoot
        },
        {
          label: t2("breadcrumbsMenu.deleteWorkflow"),
          icon: "pi pi-times",
          command: /* @__PURE__ */ __name(async () => {
            await workflowService.deleteWorkflow(workflowStore.activeWorkflow);
          }, "command"),
          visible: isRoot
        }
      ];
    });
    const handleClick = /* @__PURE__ */ __name((event) => {
      if (isEditing.value) {
        return;
      }
      if (event.detail === 1) {
        if (props.isActive) {
          menu.value?.toggle(event);
        } else {
          props.item.command?.({ item: props.item, originalEvent: event });
        }
      } else if (props.isActive && event.detail === 2) {
        menu.value?.hide();
        event.stopPropagation();
        event.preventDefault();
        startRename();
      }
    }, "handleClick");
    const startRename = /* @__PURE__ */ __name(() => {
      isEditing.value = true;
      itemLabel.value = props.item.label;
      void nextTick(() => {
        if (itemInputRef.value?.$el) {
          itemInputRef.value.$el.focus();
          itemInputRef.value.$el.select();
          if (wrapperRef.value) {
            itemInputRef.value.$el.style.width = `${Math.max(200, wrapperRef.value.offsetWidth)}px`;
          }
        }
      });
    }, "startRename");
    const inputBlur = /* @__PURE__ */ __name(async (doRename) => {
      if (doRename) {
        await rename(itemLabel.value, props.item.label);
      }
      isEditing.value = false;
    }, "inputBlur");
    return (_ctx, _cache) => {
      const _directive_tooltip = resolveDirective("tooltip");
      return openBlock(), createElementBlock(Fragment, null, [
        withDirectives((openBlock(), createElementBlock("a", {
          ref_key: "wrapperRef",
          ref: wrapperRef,
          href: "#",
          class: normalizeClass(["cursor-pointer p-breadcrumb-item-link", {
            "flex items-center gap-1": _ctx.isActive,
            "p-breadcrumb-item-link-menu-visible": menu.value?.overlayVisible,
            "p-breadcrumb-item-link-icon-visible": _ctx.isActive,
            "active-breadcrumb-item": _ctx.isActive
          }]),
          onClick: handleClick
        }, [
          createElementVNode("span", _hoisted_1$w, toDisplayString(_ctx.item.label), 1),
          _ctx.isActive ? (openBlock(), createElementBlock("i", _hoisted_2$c)) : createCommentVNode("", true)
        ], 2)), [
          [
            _directive_tooltip,
            {
              value: _ctx.item.label,
              showDelay: 512
            },
            void 0,
            { bottom: true }
          ]
        ]),
        _ctx.isActive ? (openBlock(), createBlock(unref(Menu), {
          key: 0,
          ref_key: "menu",
          ref: menu,
          model: menuItems.value,
          popup: true,
          pt: {
            root: {
              style: "background-color: var(--comfy-menu-secondary-bg)"
            },
            itemLink: {
              class: "py-2"
            }
          }
        }, null, 8, ["model"])) : createCommentVNode("", true),
        isEditing.value ? (openBlock(), createBlock(unref(InputText), {
          key: 1,
          ref_key: "itemInputRef",
          ref: itemInputRef,
          modelValue: itemLabel.value,
          "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => itemLabel.value = $event),
          class: "fixed z-10000 text-[.8rem] px-2 py-2",
          onBlur: _cache[1] || (_cache[1] = ($event) => inputBlur(true)),
          onClick: _cache[2] || (_cache[2] = withModifiers(() => {
          }, ["stop"])),
          onKeydown: [
            _cache[3] || (_cache[3] = withKeys(($event) => inputBlur(true), ["enter"])),
            _cache[4] || (_cache[4] = withKeys(($event) => inputBlur(false), ["esc"]))
          ]
        }, null, 8, ["modelValue"])) : createCommentVNode("", true)
      ], 64);
    };
  }
});
const SubgraphBreadcrumbItem = /* @__PURE__ */ _export_sfc(_sfc_main$n, [["__scopeId", "data-v-b0078f03"]]);
const MIN_WIDTH = 28;
const ITEM_GAP = 8;
const ITEM_PADDING = 8;
const ICON_WIDTH = 20;
const _sfc_main$m = /* @__PURE__ */ defineComponent({
  __name: "SubgraphBreadcrumb",
  setup(__props) {
    const workflowStore = useWorkflowStore();
    const navigationStore = useSubgraphNavigationStore();
    const breadcrumbRef = ref();
    const workflowName = computed(() => workflowStore.activeWorkflow?.filename);
    const collapseTabs = ref(false);
    const overflowingTabs = ref(false);
    const breadcrumbElement = computed(() => {
      if (!breadcrumbRef.value) return null;
      const el = breadcrumbRef.value.$el;
      const list = el?.querySelector(".p-breadcrumb-list");
      return list;
    });
    const items = computed(() => {
      const items2 = navigationStore.navigationStack.map((subgraph) => ({
        label: subgraph.name,
        command: /* @__PURE__ */ __name(() => {
          const canvas = useCanvasStore().getCanvas();
          if (!canvas.graph) throw new TypeError("Canvas has no graph");
          canvas.setGraph(subgraph);
        }, "command"),
        updateTitle: /* @__PURE__ */ __name((title) => {
          const rootGraph = useCanvasStore().getCanvas().graph?.rootGraph;
          if (!rootGraph) return;
          forEachSubgraphNode(rootGraph, subgraph.id, (node) => {
            node.title = title;
          });
        }, "updateTitle")
      }));
      return [home.value, ...items2];
    });
    const home = computed(() => ({
      label: workflowName.value,
      icon: "pi pi-home",
      key: "root",
      command: /* @__PURE__ */ __name(() => {
        const canvas = useCanvasStore().getCanvas();
        if (!canvas.graph) throw new TypeError("Canvas has no graph");
        canvas.setGraph(canvas.graph.rootGraph);
      }, "command")
    }));
    let overflowObserver;
    watch(breadcrumbElement, (el) => {
      overflowObserver?.dispose();
      overflowObserver = void 0;
      if (!el) return;
      overflowObserver = useOverflowObserver(el, {
        onCheck: /* @__PURE__ */ __name((isOverflowing) => {
          overflowingTabs.value = isOverflowing;
          if (collapseTabs.value) {
            if (!isOverflowing) {
              const items2 = [
                ...el.querySelectorAll(".p-breadcrumb-item")
              ];
              if (items2.length < 3) return;
              const itemsWithIcon = items2.filter(
                (item) => item.querySelector(".p-breadcrumb-item-link-icon-visible")
              ).length;
              const separators = el.querySelectorAll(
                ".p-breadcrumb-separator"
              );
              const separator = separators[separators.length - 1];
              const separatorWidth = separator.offsetWidth;
              const itemsWidth = (MIN_WIDTH + ITEM_PADDING + ITEM_PADDING) * items2.length + itemsWithIcon * ICON_WIDTH;
              const separatorsWidth = (items2.length - 1) * separatorWidth;
              const gapsWidth = (items2.length - 1) * (ITEM_GAP * 2);
              const totalWidth = itemsWidth + separatorsWidth + gapsWidth;
              const containerWidth = el.clientWidth;
              if (totalWidth <= containerWidth) {
                collapseTabs.value = false;
              }
            }
          } else if (isOverflowing) {
            collapseTabs.value = true;
          }
        }, "onCheck")
      });
    });
    onUpdated(() => {
      if (!overflowObserver?.disposed.value) {
        overflowObserver?.checkOverflow();
      }
    });
    return (_ctx, _cache) => {
      return openBlock(), createElementBlock("div", {
        class: normalizeClass(["subgraph-breadcrumb w-auto", {
          "subgraph-breadcrumb-collapse": collapseTabs.value,
          "subgraph-breadcrumb-overflow": overflowingTabs.value
        }]),
        style: normalizeStyle({
          "--p-breadcrumb-gap": `${ITEM_GAP}px`,
          "--p-breadcrumb-item-min-width": `${MIN_WIDTH}px`,
          "--p-breadcrumb-item-padding": `${ITEM_PADDING}px`,
          "--p-breadcrumb-icon-width": `${ICON_WIDTH}px`
        })
      }, [
        createVNode(unref(Breadcrumb), {
          ref_key: "breadcrumbRef",
          ref: breadcrumbRef,
          class: "bg-transparent p-0",
          model: items.value,
          "aria-label": "Graph navigation"
        }, {
          item: withCtx(({ item }) => [
            createVNode(SubgraphBreadcrumbItem, {
              item,
              "is-active": item === items.value.at(-1)
            }, null, 8, ["item", "is-active"])
          ]),
          separator: withCtx(() => _cache[0] || (_cache[0] = [
            createElementVNode("span", { style: { "transform": "scale(1.5)" } }, " / ", -1)
          ])),
          _: 1
        }, 8, ["model"])
      ], 6);
    };
  }
});
const SubgraphBreadcrumb = /* @__PURE__ */ _export_sfc(_sfc_main$m, [["__scopeId", "data-v-ae463256"]]);
const _hoisted_1$v = { class: "flex items-center gap-2" };
const _hoisted_2$b = {
  key: 0,
  class: "pi pi-sun"
};
const _hoisted_3$9 = {
  key: 1,
  class: "pi pi-moon"
};
const _hoisted_4$8 = ["href", "onMousedown", "onClick"];
const _hoisted_5$4 = { class: "p-menubar-item-label text-nowrap" };
const _hoisted_6$3 = {
  key: 3,
  class: "ml-auto border border-surface rounded text-muted text-xs text-nowrap p-1 keybinding-tag"
};
const _hoisted_7$2 = {
  key: 4,
  class: "ml-auto pi pi-angle-right"
};
const _sfc_main$l = /* @__PURE__ */ defineComponent({
  __name: "CommandMenubar",
  setup(__props) {
    const colorPaletteStore = useColorPaletteStore();
    const menuItemsStore = useMenuItemStore();
    const commandStore = useCommandStore();
    const dialogStore = useDialogStore();
    const settingStore = useSettingStore();
    const { t: t2 } = useI18n();
    const menuRef = ref(null);
    const isLargeSidebar = computed(
      () => settingStore.get("Comfy.Sidebar.Size") !== "small"
    );
    const isTopMenu = computed(() => settingStore.get("Comfy.UseNewMenu") === "Top");
    const translateMenuItem = /* @__PURE__ */ __name((item) => {
      const label = typeof item.label === "function" ? item.label() : item.label;
      const translatedLabel = label ? t2(`menuLabels.${normalizeI18nKey(label)}`, label) : void 0;
      return {
        ...item,
        label: translatedLabel,
        items: item.items?.map(translateMenuItem)
      };
    }, "translateMenuItem");
    const showSettings = /* @__PURE__ */ __name((defaultPanel) => {
      dialogStore.showDialog({
        key: "global-settings",
        headerComponent: SettingDialogHeader,
        component: SettingDialogContent,
        props: {
          defaultPanel
        }
      });
    }, "showSettings");
    const managerStateStore = useManagerStateStore();
    const showManageExtensions = /* @__PURE__ */ __name(async () => {
      const state = managerStateStore.managerUIState;
      switch (state) {
        case ManagerUIState.DISABLED:
          showSettings("extension");
          break;
        case ManagerUIState.LEGACY_UI:
          try {
            await commandStore.execute("Comfy.Manager.Menu.ToggleVisibility");
          } catch {
            showSettings("extension");
          }
          break;
        case ManagerUIState.NEW_UI:
          useDialogService().showManagerDialog();
          break;
      }
    }, "showManageExtensions");
    const extraMenuItems = computed(() => [
      { separator: true },
      {
        key: "theme",
        label: t2("menu.theme")
      },
      { separator: true },
      {
        key: "browse-templates",
        label: t2("menuLabels.Browse Templates"),
        icon: "icon-[comfy--template]",
        command: /* @__PURE__ */ __name(() => commandStore.execute("Comfy.BrowseTemplates"), "command")
      },
      {
        key: "settings",
        label: t2("g.settings"),
        icon: "mdi mdi-cog-outline",
        command: /* @__PURE__ */ __name(() => showSettings(), "command")
      },
      {
        key: "manage-extensions",
        label: t2("menu.manageExtensions"),
        icon: "mdi mdi-puzzle-outline",
        command: showManageExtensions
      }
    ]);
    const lightLabel = computed(() => t2("menu.light"));
    const darkLabel = computed(() => t2("menu.dark"));
    const activeTheme = computed(() => {
      return colorPaletteStore.completedActivePalette.light_theme ? lightLabel.value : darkLabel.value;
    });
    const onThemeChange = /* @__PURE__ */ __name(async () => {
      await commandStore.execute("Comfy.ToggleTheme");
    }, "onThemeChange");
    const translatedItems = computed(() => {
      const items = menuItemsStore.menuItems.map(translateMenuItem);
      let helpIndex = items.findIndex((item) => item.key === "Help");
      let helpItem;
      if (helpIndex !== -1) {
        items[helpIndex].icon = "mdi mdi-help-circle-outline";
        const isLastItem = helpIndex !== items.length - 1;
        helpItem = items.splice(
          helpIndex,
          1,
          ...isLastItem ? [
            {
              separator: true
            }
          ] : []
        )[0];
      }
      helpIndex = items.length;
      items.splice(
        helpIndex,
        0,
        ...extraMenuItems.value,
        ...helpItem ? [
          {
            separator: true
          },
          helpItem
        ] : []
      );
      return items;
    });
    const onMenuShow = /* @__PURE__ */ __name(() => {
      void nextTick(() => {
        if (menuRef.value) {
          menuRef.value.dirty = true;
        }
      });
    }, "onMenuShow");
    const isZoomCommand = /* @__PURE__ */ __name((item) => {
      return item.comfyCommand?.id === "Comfy.Canvas.ZoomIn" || item.comfyCommand?.id === "Comfy.Canvas.ZoomOut";
    }, "isZoomCommand");
    const handleZoomMouseDown = /* @__PURE__ */ __name((item, event) => {
      if (item.comfyCommand) {
        whileMouseDown(
          event,
          async () => {
            await commandStore.execute(item.comfyCommand.id);
          },
          50
        );
      }
    }, "handleZoomMouseDown");
    const handleItemClick = /* @__PURE__ */ __name((item, event) => {
      if (isZoomCommand(item) || item.comfyCommand?.active) {
        event.preventDefault();
        event.stopPropagation();
        if (item.comfyCommand?.active) {
          item.command?.({
            item,
            originalEvent: event
          });
        }
        return false;
      }
    }, "handleItemClick");
    const hasActiveStateSiblings = /* @__PURE__ */ __name((item) => {
      return menuItemsStore.menuItemHasActiveStateChildren[item.parentPath];
    }, "hasActiveStateSiblings");
    return (_ctx, _cache) => {
      return openBlock(), createElementBlock(Fragment, null, [
        createElementVNode("div", {
          class: normalizeClass(["comfyui-logo-wrapper p-1 flex justify-center items-center cursor-pointer rounded-md mr-2", {
            "comfyui-logo-menu-visible": menuRef.value?.visible
          }]),
          style: normalizeStyle({
            minWidth: isLargeSidebar.value ? "4rem" : "auto"
          }),
          onClick: _cache[1] || (_cache[1] = ($event) => menuRef.value?.toggle($event))
        }, [
          createElementVNode("img", {
            src: _imports_0,
            alt: "ComfyUI Logo",
            class: "comfyui-logo h-7",
            onContextmenu: _cache[0] || (_cache[0] = //@ts-ignore
            (...args) => unref(showNativeSystemMenu) && unref(showNativeSystemMenu)(...args))
          }, null, 32),
          _cache[4] || (_cache[4] = createElementVNode("i", { class: "pi pi-angle-down ml-1 text-[10px]" }, null, -1))
        ], 6),
        createVNode(unref(TieredMenu), {
          ref_key: "menuRef",
          ref: menuRef,
          model: translatedItems.value,
          popup: true,
          class: normalizeClass(["comfy-command-menu", {
            "comfy-command-menu-top": isTopMenu.value
          }]),
          onShow: onMenuShow
        }, {
          item: withCtx(({ item, props }) => [
            item.key === "theme" ? (openBlock(), createElementBlock("div", {
              key: 0,
              class: "flex items-center gap-4 px-4 py-5",
              onClick: _cache[3] || (_cache[3] = withModifiers(() => {
              }, ["stop", "prevent"]))
            }, [
              createTextVNode(toDisplayString(item.label) + " ", 1),
              createVNode(unref(SelectButton), {
                options: [darkLabel.value, lightLabel.value],
                "model-value": activeTheme.value,
                onClick: _cache[2] || (_cache[2] = withModifiers(() => {
                }, ["stop", "prevent"])),
                "onUpdate:modelValue": onThemeChange
              }, {
                option: withCtx(({ option }) => [
                  createElementVNode("div", _hoisted_1$v, [
                    option === lightLabel.value ? (openBlock(), createElementBlock("i", _hoisted_2$b)) : createCommentVNode("", true),
                    option === darkLabel.value ? (openBlock(), createElementBlock("i", _hoisted_3$9)) : createCommentVNode("", true),
                    createElementVNode("span", null, toDisplayString(option), 1)
                  ])
                ]),
                _: 1
              }, 8, ["options", "model-value"])
            ])) : (openBlock(), createElementBlock("a", mergeProps({
              key: 1,
              class: "p-menubar-item-link px-4 py-2"
            }, props.action, {
              href: item.url,
              target: "_blank",
              class: typeof item.class === "function" ? item.class() : item.class,
              onMousedown: /* @__PURE__ */ __name(($event) => isZoomCommand(item) ? handleZoomMouseDown(item, $event) : void 0, "onMousedown"),
              onClick: /* @__PURE__ */ __name(($event) => handleItemClick(item, $event), "onClick")
            }), [
              hasActiveStateSiblings(item) ? (openBlock(), createElementBlock("i", {
                key: 0,
                class: normalizeClass(["p-menubar-item-icon pi pi-check text-sm", { invisible: !item.comfyCommand?.active?.() }])
              }, null, 2)) : item.icon && item.comfyCommand?.id !== "Comfy.NewBlankWorkflow" ? (openBlock(), createElementBlock("span", {
                key: 1,
                class: normalizeClass(["p-menubar-item-icon", item.icon])
              }, null, 2)) : createCommentVNode("", true),
              createElementVNode("span", _hoisted_5$4, toDisplayString(item.label), 1),
              item.comfyCommand?.id === "Comfy.NewBlankWorkflow" ? (openBlock(), createElementBlock("i", {
                key: 2,
                class: normalizeClass(["ml-auto", item.icon])
              }, null, 2)) : createCommentVNode("", true),
              item?.comfyCommand?.keybinding ? (openBlock(), createElementBlock("span", _hoisted_6$3, toDisplayString(item.comfyCommand.keybinding.combo.toString()), 1)) : createCommentVNode("", true),
              item.items ? (openBlock(), createElementBlock("i", _hoisted_7$2)) : createCommentVNode("", true)
            ], 16, _hoisted_4$8))
          ]),
          _: 1
        }, 8, ["model", "class"]),
        createVNode(SubgraphBreadcrumb)
      ], 64);
    };
  }
});
const CommandMenubar = /* @__PURE__ */ _export_sfc(_sfc_main$l, [["__scopeId", "data-v-2ca32118"]]);
const _hoisted_1$u = { class: "current-user-popover w-72" };
const _hoisted_2$a = { class: "p-3" };
const _hoisted_3$8 = { class: "flex flex-col items-center" };
const _hoisted_4$7 = { class: "text-lg font-semibold truncate my-0 mb-1" };
const _hoisted_5$3 = {
  key: 0,
  class: "text-sm text-muted truncate my-0"
};
const _hoisted_6$2 = { class: "w-full flex flex-col gap-2 p-2" };
const _hoisted_7$1 = { class: "text-muted text-sm" };
const _hoisted_8$1 = { class: "flex justify-between items-center" };
const _sfc_main$k = /* @__PURE__ */ defineComponent({
  __name: "CurrentUserPopover",
  emits: ["close"],
  setup(__props, { emit: __emit }) {
    const emit = __emit;
    const { userDisplayName, userEmail, userPhotoUrl, handleSignOut } = useCurrentUser();
    const authActions = useFirebaseAuthActions();
    const dialogService = useDialogService();
    const handleOpenUserSettings = /* @__PURE__ */ __name(() => {
      dialogService.showSettingsDialog("user");
      emit("close");
    }, "handleOpenUserSettings");
    const handleTopUp = /* @__PURE__ */ __name(() => {
      dialogService.showTopUpCreditsDialog();
      emit("close");
    }, "handleTopUp");
    const handleLogout = /* @__PURE__ */ __name(async () => {
      await handleSignOut();
      emit("close");
    }, "handleLogout");
    const handleOpenApiPricing = /* @__PURE__ */ __name(() => {
      window.open("https://docs.comfy.org/tutorials/api-nodes/pricing", "_blank");
      emit("close");
    }, "handleOpenApiPricing");
    onMounted(() => {
      void authActions.fetchBalance();
    });
    return (_ctx, _cache) => {
      return openBlock(), createElementBlock("div", _hoisted_1$u, [
        createElementVNode("div", _hoisted_2$a, [
          createElementVNode("div", _hoisted_3$8, [
            createVNode(_sfc_main$1B, {
              class: "mb-3",
              "photo-url": unref(userPhotoUrl),
              "pt:icon:class": {
                "text-2xl!": !unref(userPhotoUrl)
              },
              size: "large"
            }, null, 8, ["photo-url", "pt:icon:class"]),
            createElementVNode("h3", _hoisted_4$7, toDisplayString(unref(userDisplayName) || _ctx.$t("g.user")), 1),
            unref(userEmail) ? (openBlock(), createElementBlock("p", _hoisted_5$3, toDisplayString(unref(userEmail)), 1)) : createCommentVNode("", true)
          ])
        ]),
        createVNode(unref(Divider), { class: "my-2" }),
        createVNode(unref(Button), {
          class: "justify-start",
          label: _ctx.$t("userSettings.title"),
          icon: "pi pi-cog",
          text: "",
          fluid: "",
          severity: "secondary",
          onClick: handleOpenUserSettings
        }, null, 8, ["label"]),
        createVNode(unref(Divider), { class: "my-2" }),
        createVNode(unref(Button), {
          class: "justify-start",
          label: _ctx.$t("auth.signOut.signOut"),
          icon: "pi pi-sign-out",
          text: "",
          fluid: "",
          severity: "secondary",
          onClick: handleLogout
        }, null, 8, ["label"]),
        createVNode(unref(Divider), { class: "my-2" }),
        createVNode(unref(Button), {
          class: "justify-start",
          label: _ctx.$t("credits.apiPricing"),
          icon: "pi pi-external-link",
          text: "",
          fluid: "",
          severity: "secondary",
          onClick: handleOpenApiPricing
        }, null, 8, ["label"]),
        createVNode(unref(Divider), { class: "my-2" }),
        createElementVNode("div", _hoisted_6$2, [
          createElementVNode("div", _hoisted_7$1, toDisplayString(_ctx.$t("credits.yourCreditBalance")), 1),
          createElementVNode("div", _hoisted_8$1, [
            createVNode(_sfc_main$1C, { "text-class": "text-2xl" }),
            createVNode(unref(Button), {
              label: _ctx.$t("credits.topUp.topUp"),
              onClick: handleTopUp
            }, null, 8, ["label"])
          ])
        ])
      ]);
    };
  }
});
const _hoisted_1$t = { class: "flex items-center rounded-full bg-(--p-content-background)" };
const _sfc_main$j = /* @__PURE__ */ defineComponent({
  __name: "CurrentUserButton",
  setup(__props) {
    const { isLoggedIn, userPhotoUrl } = useCurrentUser();
    const popover = ref(null);
    const photoURL = computed(
      () => userPhotoUrl.value ?? void 0
    );
    const closePopover = /* @__PURE__ */ __name(() => {
      popover.value?.hide();
    }, "closePopover");
    return (_ctx, _cache) => {
      return openBlock(), createElementBlock("div", null, [
        unref(isLoggedIn) ? (openBlock(), createBlock(unref(Button), {
          key: 0,
          class: "user-profile-button p-1",
          severity: "secondary",
          text: "",
          "aria-label": "user profile",
          onClick: _cache[0] || (_cache[0] = ($event) => popover.value?.toggle($event))
        }, {
          default: withCtx(() => [
            createElementVNode("div", _hoisted_1$t, [
              createVNode(_sfc_main$1B, { "photo-url": photoURL.value }, null, 8, ["photo-url"]),
              _cache[1] || (_cache[1] = createElementVNode("i", {
                class: "pi pi-chevron-down px-1",
                style: { fontSize: "0.5rem" }
              }, null, -1))
            ])
          ]),
          _: 1
        })) : createCommentVNode("", true),
        createVNode(unref(Popover), {
          ref_key: "popover",
          ref: popover,
          "show-arrow": false
        }, {
          default: withCtx(() => [
            createVNode(_sfc_main$k, { onClose: closePopover })
          ]),
          _: 1
        }, 512)
      ]);
    };
  }
});
const _hoisted_1$s = {
  class: "w-full flex content-end z-1001 h-[38px]",
  style: { "background": "var(--border-color)" }
};
const _hoisted_2$9 = { class: "fixed top-0 left-0 app-drag w-full h-(--comfy-topbar-height)" };
const _sfc_main$i = /* @__PURE__ */ defineComponent({
  __name: "TopMenubar",
  setup(__props) {
    const workspaceState = useWorkspaceStore();
    const settingStore = useSettingStore();
    const menuSetting = computed(() => settingStore.get("Comfy.UseNewMenu"));
    const betaMenuEnabled = computed(() => menuSetting.value !== "Disabled");
    const showTopMenu = computed(
      () => betaMenuEnabled.value && !workspaceState.focusMode
    );
    const workflowTabsPosition = computed(
      () => settingStore.get("Comfy.Workflow.WorkflowTabsPosition")
    );
    const menuRight = ref(null);
    onMounted(() => {
      if (menuRight.value) {
        app.menu.element.style.width = "fit-content";
        menuRight.value.appendChild(app.menu.element);
      }
    });
    const topMenuRef = ref(null);
    provide("topMenuRef", topMenuRef);
    const eventBus = useEventBus("topMenu");
    const isDropZone = ref(false);
    const isDroppable = ref(false);
    eventBus.on((event, payload) => {
      if (event === "updateHighlight") {
        isDropZone.value = payload.isDragging;
        isDroppable.value = payload.isOverlapping && payload.isDragging;
      }
    });
    onMounted(() => {
      if (isElectron()) {
        electronAPI().changeTheme({
          height: topMenuRef.value?.getBoundingClientRect().height ?? 0
        });
      }
    });
    return (_ctx, _cache) => {
      return openBlock(), createElementBlock("div", null, [
        withDirectives(createElementVNode("div", _hoisted_1$s, [
          createVNode(WorkflowTabs)
        ], 512), [
          [vShow, showTopMenu.value && workflowTabsPosition.value === "Topbar"]
        ]),
        withDirectives(createElementVNode("div", {
          ref_key: "topMenuRef",
          ref: topMenuRef,
          class: normalizeClass(["comfyui-menu flex items-center", { dropzone: isDropZone.value, "dropzone-active": isDroppable.value }])
        }, [
          createVNode(CommandMenubar),
          _cache[0] || (_cache[0] = createElementVNode("div", { class: "grow min-w-0 app-drag h-full" }, null, -1)),
          createElementVNode("div", {
            ref_key: "menuRight",
            ref: menuRight,
            class: "comfyui-menu-right flex-shrink-1 overflow-auto"
          }, null, 512),
          createVNode(Actionbar),
          createVNode(_sfc_main$j, { class: "shrink-0" })
        ], 2), [
          [vShow, showTopMenu.value]
        ]),
        withDirectives(createElementVNode("div", _hoisted_2$9, null, 512), [
          [vShow, unref(isNativeWindow)() && !showTopMenu.value]
        ])
      ]);
    };
  }
});
const TopMenubar = /* @__PURE__ */ _export_sfc(_sfc_main$i, [["__scopeId", "data-v-95a7d5d6"]]);
const DEFAULT_TITLE = "ComfyUI";
const TITLE_SUFFIX = " - ComfyUI";
const useBrowserTabTitle = /* @__PURE__ */ __name(() => {
  const executionStore = useExecutionStore();
  const settingStore = useSettingStore();
  const workflowStore = useWorkflowStore();
  const executionText = computed(
    () => executionStore.isIdle ? "" : `[${Math.round(executionStore.executionProgress * 100)}%]`
  );
  const newMenuEnabled = computed(
    () => settingStore.get("Comfy.UseNewMenu") !== "Disabled"
  );
  const isUnsavedText = computed(
    () => workflowStore.activeWorkflow?.isModified || !workflowStore.activeWorkflow?.isPersisted ? " *" : ""
  );
  const workflowNameText = computed(() => {
    const workflowName = workflowStore.activeWorkflow?.filename;
    return workflowName ? isUnsavedText.value + workflowName + TITLE_SUFFIX : DEFAULT_TITLE;
  });
  const nodeExecutionTitle = computed(() => {
    const nodeProgressEntries = Object.entries(
      executionStore.nodeProgressStates
    );
    const runningNodes = nodeProgressEntries.filter(
      ([_, state2]) => state2.state === "running"
    );
    if (runningNodes.length === 0) {
      return "";
    }
    if (runningNodes.length > 1) {
      return `${executionText.value}[${runningNodes.length} ${t("g.nodesRunning", "nodes running")}]`;
    }
    const [nodeId, state] = runningNodes[0];
    const progress = Math.round(state.value / state.max * 100);
    const nodeType = executionStore.activePrompt?.workflow?.changeTracker?.activeState.nodes.find(
      (n) => String(n.id) === nodeId
    )?.type || "Node";
    return `${executionText.value}[${progress}%] ${nodeType}`;
  });
  const workflowTitle = computed(
    () => executionText.value + (newMenuEnabled.value ? workflowNameText.value : DEFAULT_TITLE)
  );
  const title = computed(() => nodeExecutionTitle.value || workflowTitle.value);
  useTitle(title);
}, "useBrowserTabTitle");
const _hoisted_1$r = {
  viewBox: "0 0 24 24",
  width: "1.2em",
  height: "1.2em"
};
function render$d(_ctx, _cache) {
  return openBlock(), createElementBlock("svg", _hoisted_1$r, _cache[0] || (_cache[0] = [
    createElementVNode("path", {
      fill: "none",
      stroke: "currentColor",
      "stroke-linecap": "round",
      "stroke-linejoin": "round",
      "stroke-width": "2",
      d: "M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
    }, null, -1)
  ]));
}
__name(render$d, "render$d");
const __unplugin_components_6 = markRaw({ name: "lucide-folder", render: render$d });
const _hoisted_1$q = {
  viewBox: "0 0 24 24",
  width: "1.2em",
  height: "1.2em"
};
function render$c(_ctx, _cache) {
  return openBlock(), createElementBlock("svg", _hoisted_1$q, _cache[0] || (_cache[0] = [
    createElementVNode("g", {
      fill: "none",
      stroke: "currentColor",
      "stroke-linecap": "round",
      "stroke-linejoin": "round",
      "stroke-width": "2"
    }, [
      createElementVNode("circle", {
        cx: "12",
        cy: "12",
        r: "10"
      }),
      createElementVNode("path", { d: "M12 16v-4m0-4h.01" })
    ], -1)
  ]));
}
__name(render$c, "render$c");
const __unplugin_components_5 = markRaw({ name: "lucide-info", render: render$c });
const _hoisted_1$p = {
  viewBox: "0 0 24 24",
  width: "1.2em",
  height: "1.2em"
};
function render$b(_ctx, _cache) {
  return openBlock(), createElementBlock("svg", _hoisted_1$p, _cache[0] || (_cache[0] = [
    createElementVNode("path", {
      fill: "none",
      stroke: "currentColor",
      "stroke-linecap": "round",
      "stroke-linejoin": "round",
      "stroke-width": "2",
      d: "M22 3H2l8 9.46V19l4 2v-8.54z"
    }, null, -1)
  ]));
}
__name(render$b, "render$b");
const __unplugin_components_4 = markRaw({ name: "lucide-filter", render: render$b });
const _hoisted_1$o = {
  viewBox: "0 0 24 24",
  width: "1.2em",
  height: "1.2em"
};
function render$a(_ctx, _cache) {
  return openBlock(), createElementBlock("svg", _hoisted_1$o, _cache[0] || (_cache[0] = [
    createElementVNode("g", {
      fill: "none",
      stroke: "currentColor",
      "stroke-linecap": "round",
      "stroke-linejoin": "round",
      "stroke-width": "2"
    }, [
      createElementVNode("path", { d: "M19 17V5a2 2 0 0 0-2-2H4" }),
      createElementVNode("path", { d: "M8 21h12a2 2 0 0 0 2-2v-1a1 1 0 0 0-1-1H11a1 1 0 0 0-1 1v1a2 2 0 1 1-4 0V5a2 2 0 1 0-4 0v2a1 1 0 0 0 1 1h3" })
    ], -1)
  ]));
}
__name(render$a, "render$a");
const __unplugin_components_3$1 = markRaw({ name: "lucide-scroll", render: render$a });
const _hoisted_1$n = {
  viewBox: "0 0 24 24",
  width: "1.2em",
  height: "1.2em"
};
function render$9(_ctx, _cache) {
  return openBlock(), createElementBlock("svg", _hoisted_1$n, _cache[0] || (_cache[0] = [
    createElementVNode("g", {
      fill: "none",
      stroke: "currentColor",
      "stroke-linecap": "round",
      "stroke-linejoin": "round",
      "stroke-width": "2"
    }, [
      createElementVNode("path", { d: "M12 15V3m9 12v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
      createElementVNode("path", { d: "m7 10l5 5l5-5" })
    ], -1)
  ]));
}
__name(render$9, "render$9");
const __unplugin_components_2$1 = markRaw({ name: "lucide-download", render: render$9 });
const _hoisted_1$m = {
  viewBox: "0 0 24 24",
  width: "1.2em",
  height: "1.2em"
};
function render$8(_ctx, _cache) {
  return openBlock(), createElementBlock("svg", _hoisted_1$m, _cache[0] || (_cache[0] = [
    createElementVNode("path", {
      fill: "none",
      stroke: "currentColor",
      "stroke-linecap": "round",
      "stroke-linejoin": "round",
      "stroke-width": "2",
      d: "M12 3v12m5-7l-5-5l-5 5m14 7v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"
    }, null, -1)
  ]));
}
__name(render$8, "render$8");
const __unplugin_components_1$2 = markRaw({ name: "lucide-upload", render: render$8 });
const _hoisted_1$l = {
  viewBox: "0 0 24 24",
  width: "1.2em",
  height: "1.2em"
};
function render$7(_ctx, _cache) {
  return openBlock(), createElementBlock("svg", _hoisted_1$l, _cache[0] || (_cache[0] = [
    createElementVNode("path", {
      fill: "none",
      stroke: "currentColor",
      "stroke-linecap": "round",
      "stroke-linejoin": "round",
      "stroke-width": "2",
      d: "M15.39 4.39a1 1 0 0 0 1.68-.474a2.5 2.5 0 1 1 3.014 3.015a1 1 0 0 0-.474 1.68l1.683 1.682a2.414 2.414 0 0 1 0 3.414L19.61 15.39a1 1 0 0 1-1.68-.474a2.5 2.5 0 1 0-3.014 3.015a1 1 0 0 1 .474 1.68l-1.683 1.682a2.414 2.414 0 0 1-3.414 0L8.61 19.61a1 1 0 0 0-1.68.474a2.5 2.5 0 1 1-3.014-3.015a1 1 0 0 0 .474-1.68l-1.683-1.682a2.414 2.414 0 0 1 0-3.414L4.39 8.61a1 1 0 0 1 1.68.474a2.5 2.5 0 1 0 3.014-3.015a1 1 0 0 1-.474-1.68l1.683-1.682a2.414 2.414 0 0 1 3.414 0z"
    }, null, -1)
  ]));
}
__name(render$7, "render$7");
const __unplugin_components_0$3 = markRaw({ name: "lucide-puzzle", render: render$7 });
const _sfc_main$h = /* @__PURE__ */ defineComponent({
  __name: "IconButton",
  props: {
    onClick: { type: Function },
    size: { default: "md" },
    type: { default: "secondary" },
    border: { type: Boolean, default: false },
    disabled: { type: Boolean, default: false },
    class: {}
  },
  setup(__props) {
    const buttonStyle = computed(() => {
      const baseClasses = `${getBaseButtonClasses()} p-0`;
      const sizeClasses = getIconButtonSizeClasses(__props.size);
      const typeClasses = __props.border ? getBorderButtonTypeClasses(__props.type) : getButtonTypeClasses(__props.type);
      return [baseClasses, sizeClasses, typeClasses, __props.class].filter(Boolean).join(" ");
    });
    return (_ctx, _cache) => {
      return openBlock(), createBlock(unref(Button), {
        unstyled: "",
        class: normalizeClass(buttonStyle.value),
        disabled: _ctx.disabled,
        onClick: _ctx.onClick
      }, {
        default: withCtx(() => [
          renderSlot(_ctx.$slots, "default")
        ]),
        _: 3
      }, 8, ["class", "disabled", "onClick"]);
    };
  }
});
const _hoisted_1$k = {
  viewBox: "0 0 24 24",
  width: "1.2em",
  height: "1.2em"
};
function render$6(_ctx, _cache) {
  return openBlock(), createElementBlock("svg", _hoisted_1$k, _cache[0] || (_cache[0] = [
    createElementVNode("g", {
      fill: "none",
      stroke: "currentColor",
      "stroke-linecap": "round",
      "stroke-linejoin": "round",
      "stroke-width": "2"
    }, [
      createElementVNode("circle", {
        cx: "12",
        cy: "12",
        r: "1"
      }),
      createElementVNode("circle", {
        cx: "12",
        cy: "5",
        r: "1"
      }),
      createElementVNode("circle", {
        cx: "12",
        cy: "19",
        r: "1"
      })
    ], -1)
  ]));
}
__name(render$6, "render$6");
const __unplugin_components_0$2 = markRaw({ name: "lucide-more-vertical", render: render$6 });
const _hoisted_1$j = { class: "relative inline-flex items-center" };
const _hoisted_2$8 = { class: "flex flex-col gap-1 p-2 min-w-40" };
const _sfc_main$g = /* @__PURE__ */ defineComponent({
  __name: "MoreButton",
  setup(__props) {
    const popover = ref();
    const toggle = /* @__PURE__ */ __name((event) => {
      popover.value?.toggle(event);
    }, "toggle");
    const hide = /* @__PURE__ */ __name(() => {
      popover.value?.hide();
    }, "hide");
    const pt = computed(() => ({
      root: {
        class: "absolute z-50"
      },
      content: {
        class: [
          "mt-2 bg-white dark-theme:bg-zinc-800 text-neutral dark-theme:text-white rounded-lg",
          "shadow-lg border border-zinc-200 dark-theme:border-zinc-700"
        ]
      }
    }));
    return (_ctx, _cache) => {
      const _component_i_lucide58more_vertical = __unplugin_components_0$2;
      return openBlock(), createElementBlock("div", _hoisted_1$j, [
        createVNode(_sfc_main$h, { onClick: toggle }, {
          default: withCtx(() => [
            createVNode(_component_i_lucide58more_vertical, { class: "text-sm" })
          ]),
          _: 1
        }),
        createVNode(unref(Popover), {
          ref_key: "popover",
          ref: popover,
          "append-to": "body",
          "auto-z-index": true,
          "base-z-index": 1e3,
          dismissable: true,
          "close-on-escape": true,
          unstyled: "",
          pt: pt.value
        }, {
          default: withCtx(() => [
            createElementVNode("div", _hoisted_2$8, [
              renderSlot(_ctx.$slots, "default", { close: hide })
            ])
          ]),
          _: 3
        }, 8, ["pt"])
      ]);
    };
  }
});
const _sfc_main$f = {};
const _hoisted_1$i = { class: "flex-1 w-full h-full" };
function _sfc_render$2(_ctx, _cache) {
  return openBlock(), createElementBlock("div", _hoisted_1$i, [
    renderSlot(_ctx.$slots, "default")
  ]);
}
__name(_sfc_render$2, "_sfc_render$2");
const CardBottom = /* @__PURE__ */ _export_sfc(_sfc_main$f, [["render", _sfc_render$2]]);
const _sfc_main$e = /* @__PURE__ */ defineComponent({
  __name: "CardContainer",
  props: {
    maxWidth: {},
    minWidth: {},
    ratio: { default: "square" }
  },
  setup(__props) {
    const containerClasses = computed(() => {
      const baseClasses = "flex flex-col bg-white dark-theme:bg-zinc-800 rounded-lg shadow-sm border border-zinc-200 dark-theme:border-zinc-700 overflow-hidden";
      const ratioClasses = {
        square: "aspect-256/308",
        portrait: "aspect-256/325",
        tallPortrait: "aspect-256/353"
      };
      return `${baseClasses} ${ratioClasses[__props.ratio]}`;
    });
    const containerStyle = computed(
      () => __props.maxWidth || __props.minWidth ? {
        maxWidth: `${__props.maxWidth}px`,
        minWidth: `${__props.minWidth}px`
      } : {}
    );
    return (_ctx, _cache) => {
      return openBlock(), createElementBlock("div", {
        class: normalizeClass(containerClasses.value),
        style: normalizeStyle(containerStyle.value)
      }, [
        renderSlot(_ctx.$slots, "top"),
        renderSlot(_ctx.$slots, "bottom")
      ], 6);
    };
  }
});
const _hoisted_1$h = { class: "absolute top-2 left-2 flex gap-2" };
const _hoisted_2$7 = { class: "absolute top-2 right-2 flex gap-2" };
const _hoisted_3$7 = { class: "absolute bottom-2 left-2 flex gap-2" };
const _hoisted_4$6 = { class: "absolute bottom-2 right-2 flex gap-2" };
const _sfc_main$d = /* @__PURE__ */ defineComponent({
  __name: "CardTop",
  props: {
    ratio: { default: "square" }
  },
  setup(__props) {
    const topStyle = computed(() => {
      const baseClasses = "relative p-0";
      const ratioClasses = {
        square: "aspect-square",
        landscape: "aspect-48/27"
      };
      return `${baseClasses} ${ratioClasses[__props.ratio]}`;
    });
    return (_ctx, _cache) => {
      return openBlock(), createElementBlock("div", {
        class: normalizeClass(topStyle.value)
      }, [
        renderSlot(_ctx.$slots, "default", { class: "absolute top-0 left-0 w-full h-full" }),
        createElementVNode("div", _hoisted_1$h, [
          renderSlot(_ctx.$slots, "top-left")
        ]),
        createElementVNode("div", _hoisted_2$7, [
          renderSlot(_ctx.$slots, "top-right")
        ]),
        createElementVNode("div", _hoisted_3$7, [
          renderSlot(_ctx.$slots, "bottom-left")
        ]),
        createElementVNode("div", _hoisted_4$6, [
          renderSlot(_ctx.$slots, "bottom-right")
        ])
      ], 2);
    };
  }
});
const _hoisted_1$g = { class: "inline-flex justify-center items-center gap-1 shrink-0 py-1 px-2 text-xs bg-[#D9D9D966]/40 rounded font-bold text-white/90" };
const _sfc_main$c = /* @__PURE__ */ defineComponent({
  __name: "SquareChip",
  props: {
    label: {}
  },
  setup(__props) {
    return (_ctx, _cache) => {
      return openBlock(), createElementBlock("div", _hoisted_1$g, [
        renderSlot(_ctx.$slots, "icon", { class: "text-xs text-white/90" }),
        createElementVNode("span", null, toDisplayString(_ctx.label), 1)
      ]);
    };
  }
});
const _hoisted_1$f = {
  viewBox: "0 0 24 24",
  width: "1.2em",
  height: "1.2em"
};
function render$5(_ctx, _cache) {
  return openBlock(), createElementBlock("svg", _hoisted_1$f, _cache[0] || (_cache[0] = [
    createElementVNode("path", {
      fill: "none",
      stroke: "currentColor",
      "stroke-linecap": "round",
      "stroke-linejoin": "round",
      "stroke-width": "2",
      d: "M20 6L9 17l-5-5"
    }, null, -1)
  ]));
}
__name(render$5, "render$5");
const __unplugin_components_1$1 = markRaw({ name: "lucide-check", render: render$5 });
const _hoisted_1$e = {
  viewBox: "0 0 24 24",
  width: "1.2em",
  height: "1.2em"
};
function render$4(_ctx, _cache) {
  return openBlock(), createElementBlock("svg", _hoisted_1$e, _cache[0] || (_cache[0] = [
    createElementVNode("g", {
      fill: "none",
      stroke: "currentColor",
      "stroke-linecap": "round",
      "stroke-linejoin": "round",
      "stroke-width": "2"
    }, [
      createElementVNode("path", { d: "m21 21l-4.34-4.34" }),
      createElementVNode("circle", {
        cx: "11",
        cy: "11",
        r: "8"
      })
    ], -1)
  ]));
}
__name(render$4, "render$4");
const __unplugin_components_0$1 = markRaw({ name: "lucide-search", render: render$4 });
const _sfc_main$b = /* @__PURE__ */ defineComponent({
  __name: "SearchBox",
  props: /* @__PURE__ */ mergeModels({
    placeHolder: {},
    showBorder: { type: Boolean, default: false }
  }, {
    "modelValue": {},
    "modelModifiers": {}
  }),
  emits: ["update:modelValue"],
  setup(__props) {
    const searchQuery = useModel(__props, "modelValue");
    const wrapperStyle = computed(() => {
      return __props.showBorder ? "flex w-full items-center rounded gap-2 bg-white dark-theme:bg-zinc-800 p-1 border border-solid border-zinc-200 dark-theme:border-zinc-700" : "flex w-full items-center rounded px-2 py-1.5 gap-2 bg-white dark-theme:bg-zinc-800";
    });
    const iconColorStyle = computed(() => {
      return !__props.showBorder ? "text-neutral" : "text-zinc-300 dark-theme:text-zinc-700";
    });
    return (_ctx, _cache) => {
      const _component_i_lucide58search = __unplugin_components_0$1;
      return openBlock(), createElementBlock("div", {
        class: normalizeClass(wrapperStyle.value)
      }, [
        createVNode(_component_i_lucide58search, {
          class: normalizeClass(iconColorStyle.value)
        }, null, 8, ["class"]),
        createVNode(unref(InputText), {
          modelValue: searchQuery.value,
          "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => searchQuery.value = $event),
          placeholder: _ctx.placeHolder || "Search...",
          type: "text",
          unstyled: "",
          class: "w-full p-0 border-none outline-hidden bg-transparent text-xs text-neutral dark-theme:text-white"
        }, null, 8, ["modelValue", "placeholder"])
      ], 2);
    };
  }
});
const _sfc_main$a = /* @__PURE__ */ defineComponent({
  __name: "TextButton",
  props: {
    label: {},
    onClick: { type: Function },
    size: { default: "md" },
    type: { default: "primary" },
    border: { type: Boolean, default: false },
    disabled: { type: Boolean, default: false },
    class: {}
  },
  setup(__props) {
    const buttonStyle = computed(() => {
      const baseClasses = getBaseButtonClasses();
      const sizeClasses = getButtonSizeClasses(__props.size);
      const typeClasses = __props.border ? getBorderButtonTypeClasses(__props.type) : getButtonTypeClasses(__props.type);
      return [baseClasses, sizeClasses, typeClasses, __props.class].filter(Boolean).join(" ");
    });
    return (_ctx, _cache) => {
      return openBlock(), createBlock(unref(Button), {
        unstyled: "",
        class: normalizeClass(buttonStyle.value),
        disabled: _ctx.disabled,
        onClick: _ctx.onClick
      }, {
        default: withCtx(() => [
          createElementVNode("span", null, toDisplayString(_ctx.label), 1)
        ]),
        _: 1
      }, 8, ["class", "disabled", "onClick"]);
    };
  }
});
const _hoisted_1$d = { class: "p-2 flex flex-col pb-0" };
const _hoisted_2$6 = {
  key: 1,
  class: "mt-2 flex items-center justify-between"
};
const _hoisted_3$6 = {
  key: 0,
  class: "text-sm text-neutral-400 dark-theme:text-zinc-500 px-1"
};
const _hoisted_4$5 = { class: "text-sm text-zinc-700 dark-theme:text-gray-200" };
const _hoisted_5$2 = {
  key: 0,
  class: "pointer-events-none absolute -right-2 -top-2 z-10 flex h-5 w-5 items-center justify-center rounded-full bg-blue-400 dark-theme:bg-blue-500 text-xs font-semibold text-white"
};
const _hoisted_6$1 = { class: "flex items-center gap-2" };
const _sfc_main$9 = /* @__PURE__ */ defineComponent({
  ...{
    inheritAttrs: false
  },
  __name: "MultiSelect",
  props: /* @__PURE__ */ mergeModels({
    label: {},
    showSearchBox: { type: Boolean, default: false },
    showSelectedCount: { type: Boolean, default: false },
    showClearButton: { type: Boolean, default: false },
    searchPlaceholder: { default: "Search..." }
  }, {
    "modelValue": {
      required: true
    },
    "modelModifiers": {},
    "searchQuery": {},
    "searchQueryModifiers": {}
  }),
  emits: ["update:modelValue", "update:searchQuery"],
  setup(__props) {
    const selectedItems = useModel(__props, "modelValue");
    const searchQuery = useModel(__props, "searchQuery");
    const selectedCount = computed(() => selectedItems.value.length);
    const pt = computed(() => ({
      root: /* @__PURE__ */ __name(({ props }) => ({
        class: [
          "relative inline-flex cursor-pointer select-none",
          "rounded-lg bg-white dark-theme:bg-zinc-800 text-neutral dark-theme:text-white",
          "transition-all duration-200 ease-in-out",
          "border-[2.5px] border-solid",
          selectedCount.value > 0 ? "border-blue-400 dark-theme:border-blue-500" : "border-transparent",
          { "opacity-60 cursor-default": props.disabled }
        ]
      }), "root"),
      labelContainer: {
        class: "flex-1 flex items-center overflow-hidden whitespace-nowrap pl-4 py-2 "
      },
      label: {
        class: "p-0"
      },
      dropdown: {
        class: "flex shrink-0 cursor-pointer items-center justify-center px-3"
      },
      header: /* @__PURE__ */ __name(() => ({
        class: __props.showSearchBox || __props.showSelectedCount || __props.showClearButton ? "block" : "hidden"
      }), "header"),
      // Overlay & list visuals unchanged
      overlay: "mt-2 bg-white dark-theme:bg-zinc-800 text-neutral dark-theme:text-white rounded-lg border border-solid border-zinc-100 dark-theme:border-zinc-700",
      list: {
        class: "flex flex-col gap-1 p-0 list-none border-none text-xs"
      },
      // Option row hover and focus tone
      option: /* @__PURE__ */ __name(({ context }) => ({
        class: [
          "flex gap-1 items-center p-2",
          "hover:bg-neutral-100/50 hover:dark-theme:bg-zinc-700/50",
          // Add focus/highlight state for keyboard navigation
          {
            "bg-neutral-100/50 dark-theme:bg-zinc-700/50": context?.focused
          }
        ]
      }), "option"),
      // Hide built-in checkboxes entirely via PT (no :deep)
      pcHeaderCheckbox: {
        root: { class: "hidden" },
        style: "display: none !important"
      },
      pcOptionCheckbox: {
        root: { class: "hidden" },
        style: "display: none !important"
      }
    }));
    return (_ctx, _cache) => {
      const _component_i_lucide58chevron_down = __unplugin_components_0$c;
      const _component_i_lucide58check = __unplugin_components_1$1;
      return openBlock(), createBlock(unref(MultiSelect), mergeProps({
        modelValue: selectedItems.value,
        "onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => selectedItems.value = $event)
      }, _ctx.$attrs, {
        "option-label": "name",
        unstyled: "",
        "max-selected-labels": 0,
        pt: pt.value
      }), createSlots({
        value: withCtx(() => [
          createElementVNode("span", _hoisted_4$5, toDisplayString(_ctx.label), 1),
          selectedCount.value > 0 ? (openBlock(), createElementBlock("span", _hoisted_5$2, toDisplayString(selectedCount.value), 1)) : createCommentVNode("", true)
        ]),
        dropdownicon: withCtx(() => [
          createVNode(_component_i_lucide58chevron_down, { class: "text-lg text-neutral-400" })
        ]),
        option: withCtx((slotProps) => [
          createElementVNode("div", _hoisted_6$1, [
            createElementVNode("div", {
              class: normalizeClass([
                "flex h-4 w-4 p-0.5 shrink-0 items-center justify-center rounded transition-all duration-200",
                slotProps.selected ? "border-[3px] border-blue-400 bg-blue-400 dark-theme:border-blue-500 dark-theme:bg-blue-500" : "border-[1px] border-neutral-300 dark-theme:border-zinc-600 bg-neutral-100 dark-theme:bg-zinc-700"
              ])
            }, [
              slotProps.selected ? (openBlock(), createBlock(_component_i_lucide58check, {
                key: 0,
                class: "text-xs text-bold text-white"
              })) : createCommentVNode("", true)
            ], 2),
            createVNode(unref(Button), {
              class: "border-none outline-none bg-transparent",
              unstyled: ""
            }, {
              default: withCtx(() => [
                createTextVNode(toDisplayString(slotProps.option.name), 1)
              ]),
              _: 2
            }, 1024)
          ])
        ]),
        _: 2
      }, [
        _ctx.showSearchBox || _ctx.showSelectedCount || _ctx.showClearButton ? {
          name: "header",
          fn: withCtx(() => [
            createElementVNode("div", _hoisted_1$d, [
              _ctx.showSearchBox ? (openBlock(), createBlock(_sfc_main$b, {
                key: 0,
                modelValue: searchQuery.value,
                "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => searchQuery.value = $event),
                class: normalizeClass(_ctx.showSelectedCount || _ctx.showClearButton ? "mb-2" : ""),
                "show-order": true,
                "place-holder": _ctx.searchPlaceholder
              }, null, 8, ["modelValue", "class", "place-holder"])) : createCommentVNode("", true),
              _ctx.showSelectedCount || _ctx.showClearButton ? (openBlock(), createElementBlock("div", _hoisted_2$6, [
                _ctx.showSelectedCount ? (openBlock(), createElementBlock("span", _hoisted_3$6, toDisplayString(selectedCount.value > 0 ? _ctx.$t("g.itemsSelected", { selectedCount: selectedCount.value }) : _ctx.$t("g.itemSelected", { selectedCount: selectedCount.value })), 1)) : createCommentVNode("", true),
                _ctx.showClearButton ? (openBlock(), createBlock(_sfc_main$a, {
                  key: 1,
                  label: _ctx.$t("g.clearAll"),
                  type: "transparent",
                  size: "fit-content",
                  class: "text-sm text-blue-500! dark-theme:text-blue-600!",
                  onClick: _cache[1] || (_cache[1] = withModifiers(($event) => selectedItems.value = [], ["stop"]))
                }, null, 8, ["label"])) : createCommentVNode("", true)
              ])) : createCommentVNode("", true),
              _cache[3] || (_cache[3] = createElementVNode("div", { class: "mt-4 h-px bg-zinc-200 dark-theme:bg-zinc-700" }, null, -1))
            ])
          ]),
          key: "0"
        } : void 0
      ]), 1040, ["modelValue", "pt"]);
    };
  }
});
const _hoisted_1$c = { class: "flex items-center gap-2 text-sm" };
const _hoisted_2$5 = {
  key: 0,
  class: "text-zinc-700 dark-theme:text-gray-200"
};
const _hoisted_3$5 = {
  key: 1,
  class: "text-zinc-700 dark-theme:text-gray-200"
};
const _hoisted_4$4 = { class: "flex items-center justify-between gap-3 w-full" };
const _hoisted_5$1 = { class: "truncate" };
const _sfc_main$8 = /* @__PURE__ */ defineComponent({
  ...{
    inheritAttrs: false
  },
  __name: "SingleSelect",
  props: /* @__PURE__ */ mergeModels({
    label: {},
    options: {}
  }, {
    "modelValue": { required: true },
    "modelModifiers": {}
  }),
  emits: ["update:modelValue"],
  setup(__props) {
    const selectedItem = useModel(__props, "modelValue");
    const getLabel = /* @__PURE__ */ __name((val) => {
      if (val == null) return __props.label ?? "";
      if (!__props.options) return __props.label ?? "";
      const found = __props.options.find((o) => o.value === val);
      return found ? found.name : __props.label ?? "";
    }, "getLabel");
    const pt = computed(() => ({
      root: /* @__PURE__ */ __name(({
        props
      }) => ({
        class: [
          // container
          "relative inline-flex cursor-pointer select-none items-center",
          // trigger surface
          "rounded-md",
          "bg-transparent text-neutral dark-theme:text-white",
          "border-0",
          // disabled
          { "opacity-60 cursor-default": props.disabled }
        ]
      }), "root"),
      label: {
        class: (
          // Align with MultiSelect labelContainer spacing
          "flex-1 flex items-center overflow-hidden whitespace-nowrap pl-4 py-2 outline-hidden"
        )
      },
      dropdown: {
        class: (
          // Right chevron touch area
          "flex shrink-0 items-center justify-center px-3 py-2"
        )
      },
      overlay: {
        class: [
          // dropdown panel
          "mt-2 bg-white dark-theme:bg-zinc-800 text-neutral dark-theme:text-white rounded-lg border border-solid border-zinc-100 dark-theme:border-zinc-700"
        ]
      },
      list: {
        class: (
          // Same list tone/size as MultiSelect
          "flex flex-col gap-1 p-0 list-none border-none text-xs"
        )
      },
      option: /* @__PURE__ */ __name(({
        context
      }) => ({
        class: [
          // Row layout
          "flex items-center justify-between gap-3 px-3 py-2",
          "hover:bg-neutral-100/50 hover:dark-theme:bg-zinc-700/50",
          // Selected state + check icon
          { "bg-neutral-100/50 dark-theme:bg-zinc-700/50": context.selected },
          // Add focus state for keyboard navigation
          { "bg-neutral-100/50 dark-theme:bg-zinc-700/50": context.focused }
        ]
      }), "option"),
      optionLabel: {
        class: "truncate"
      },
      optionGroupLabel: {
        class: "px-3 py-2 text-xs uppercase tracking-wide text-zinc-500 dark-theme:text-zinc-400"
      },
      emptyMessage: {
        class: "px-3 py-2 text-sm text-zinc-500 dark-theme:text-zinc-400"
      }
    }));
    return (_ctx, _cache) => {
      const _component_i_lucide58chevron_down = __unplugin_components_0$c;
      const _component_i_lucide58check = __unplugin_components_1$1;
      return openBlock(), createBlock(unref(Select), mergeProps({
        modelValue: selectedItem.value,
        "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => selectedItem.value = $event)
      }, _ctx.$attrs, {
        options: _ctx.options,
        "option-label": "name",
        "option-value": "value",
        unstyled: "",
        pt: pt.value
      }), {
        value: withCtx((slotProps) => [
          createElementVNode("div", _hoisted_1$c, [
            renderSlot(_ctx.$slots, "icon"),
            slotProps.value !== null && slotProps.value !== void 0 ? (openBlock(), createElementBlock("span", _hoisted_2$5, toDisplayString(getLabel(slotProps.value)), 1)) : (openBlock(), createElementBlock("span", _hoisted_3$5, toDisplayString(_ctx.label), 1))
          ])
        ]),
        dropdownicon: withCtx(() => [
          createVNode(_component_i_lucide58chevron_down, { class: "text-base text-neutral-400 dark-theme:text-gray-300" })
        ]),
        option: withCtx(({ option, selected }) => [
          createElementVNode("div", _hoisted_4$4, [
            createElementVNode("span", _hoisted_5$1, toDisplayString(option.name), 1),
            selected ? (openBlock(), createBlock(_component_i_lucide58check, {
              key: 0,
              class: "text-neutral-900 dark-theme:text-white"
            })) : createCommentVNode("", true)
          ])
        ]),
        _: 3
      }, 16, ["modelValue", "options", "pt"]);
    };
  }
});
const _hoisted_1$b = {
  viewBox: "0 0 24 24",
  width: "1.2em",
  height: "1.2em"
};
function render$3(_ctx, _cache) {
  return openBlock(), createElementBlock("svg", _hoisted_1$b, _cache[0] || (_cache[0] = [
    createElementVNode("g", {
      fill: "none",
      stroke: "currentColor",
      "stroke-linecap": "round",
      "stroke-linejoin": "round",
      "stroke-width": "2"
    }, [
      createElementVNode("rect", {
        width: "18",
        height: "18",
        x: "3",
        y: "3",
        rx: "2"
      }),
      createElementVNode("path", { d: "M15 3v18M8 9l3 3l-3 3" })
    ], -1)
  ]));
}
__name(render$3, "render$3");
const __unplugin_components_3 = markRaw({ name: "lucide-panel-right-close", render: render$3 });
const _hoisted_1$a = {
  viewBox: "0 0 24 24",
  width: "1.2em",
  height: "1.2em"
};
function render$2(_ctx, _cache) {
  return openBlock(), createElementBlock("svg", _hoisted_1$a, _cache[0] || (_cache[0] = [
    createElementVNode("g", {
      fill: "none",
      stroke: "currentColor",
      "stroke-linecap": "round",
      "stroke-linejoin": "round",
      "stroke-width": "2"
    }, [
      createElementVNode("rect", {
        width: "18",
        height: "18",
        x: "3",
        y: "3",
        rx: "2"
      }),
      createElementVNode("path", { d: "M9 3v18m7-6l-3-3l3-3" })
    ], -1)
  ]));
}
__name(render$2, "render$2");
const __unplugin_components_2 = markRaw({ name: "lucide-panel-left-close", render: render$2 });
const _hoisted_1$9 = {
  viewBox: "0 0 24 24",
  width: "1.2em",
  height: "1.2em"
};
function render$1(_ctx, _cache) {
  return openBlock(), createElementBlock("svg", _hoisted_1$9, _cache[0] || (_cache[0] = [
    createElementVNode("g", {
      fill: "none",
      stroke: "currentColor",
      "stroke-linecap": "round",
      "stroke-linejoin": "round",
      "stroke-width": "2"
    }, [
      createElementVNode("rect", {
        width: "18",
        height: "18",
        x: "3",
        y: "3",
        rx: "2"
      }),
      createElementVNode("path", { d: "M9 3v18" })
    ], -1)
  ]));
}
__name(render$1, "render$1");
const __unplugin_components_1 = markRaw({ name: "lucide-panel-left", render: render$1 });
const _hoisted_1$8 = {
  viewBox: "0 0 24 24",
  width: "1.2em",
  height: "1.2em"
};
function render(_ctx, _cache) {
  return openBlock(), createElementBlock("svg", _hoisted_1$8, _cache[0] || (_cache[0] = [
    createElementVNode("g", {
      fill: "none",
      stroke: "currentColor",
      "stroke-linecap": "round",
      "stroke-linejoin": "round",
      "stroke-width": "2"
    }, [
      createElementVNode("rect", {
        width: "18",
        height: "18",
        x: "3",
        y: "3",
        rx: "2"
      }),
      createElementVNode("path", { d: "M15 3v18" })
    ], -1)
  ]));
}
__name(render, "render");
const __unplugin_components_0 = markRaw({ name: "lucide-panel-right", render });
const OnCloseKey = Symbol();
const _hoisted_1$7 = { class: "base-widget-layout rounded-2xl overflow-hidden relative bg-zinc-50 dark-theme:bg-zinc-800" };
const _hoisted_2$4 = { class: "flex w-full h-full" };
const _hoisted_3$4 = { class: "flex-1 flex bg-zinc-100 dark-theme:bg-neutral-900" };
const _hoisted_4$3 = { class: "w-full h-full flex flex-col" };
const _hoisted_5 = {
  key: 0,
  class: "w-full h-16 px-6 py-4 flex justify-between gap-2"
};
const _hoisted_6 = { class: "flex-1 flex gap-2 shrink-0" };
const _hoisted_7 = { class: "flex flex-col flex-1 min-h-0" };
const _hoisted_8 = {
  key: 0,
  class: "text-xxl px-6 pt-2 pb-6 m-0"
};
const _hoisted_9 = { class: "min-h-0 px-6 pt-0 pb-10 overflow-y-auto scrollbar-hide" };
const _hoisted_10 = {
  key: 0,
  class: "w-1/4 min-w-40 max-w-80"
};
const _sfc_main$7 = /* @__PURE__ */ defineComponent({
  __name: "BaseWidgetLayout",
  props: {
    contentTitle: {}
  },
  setup(__props) {
    const BREAKPOINTS = { md: 880 };
    const PANEL_SIZES = {
      width: "w-1/3",
      minWidth: "min-w-40",
      maxWidth: "max-w-56"
    };
    const slots = useSlots();
    const closeDialog = inject(OnCloseKey, () => {
    });
    const breakpoints = useBreakpoints(BREAKPOINTS);
    const notMobile = breakpoints.greater("md");
    const isLeftPanelOpen = ref(true);
    const isRightPanelOpen = ref(false);
    const mobileMenuOpen = ref(false);
    const hasRightPanel = computed(() => !!slots.rightPanel);
    watch(notMobile, (isDesktop) => {
      if (!isDesktop) {
        mobileMenuOpen.value = false;
      }
    });
    const showLeftPanel = computed(() => {
      const shouldShow = notMobile.value ? isLeftPanelOpen.value : mobileMenuOpen.value;
      return shouldShow;
    });
    const toggleLeftPanel = /* @__PURE__ */ __name(() => {
      if (notMobile.value) {
        isLeftPanelOpen.value = !isLeftPanelOpen.value;
      } else {
        mobileMenuOpen.value = !mobileMenuOpen.value;
      }
    }, "toggleLeftPanel");
    const toggleRightPanel = /* @__PURE__ */ __name(() => {
      isRightPanelOpen.value = !isRightPanelOpen.value;
    }, "toggleRightPanel");
    return (_ctx, _cache) => {
      const _component_i_lucide58panel_right = __unplugin_components_0;
      const _component_i_lucide58panel_left = __unplugin_components_1;
      const _component_i_lucide58panel_left_close = __unplugin_components_2;
      const _component_i_lucide58panel_right_close = __unplugin_components_3;
      return openBlock(), createElementBlock("div", _hoisted_1$7, [
        withDirectives(createVNode(_sfc_main$h, {
          class: normalizeClass(["absolute top-4 right-16 z-10 transition-opacity duration-200", {
            "opacity-0 pointer-events-none": isRightPanelOpen.value || !hasRightPanel.value
          }]),
          onClick: toggleRightPanel
        }, {
          default: withCtx(() => [
            createVNode(_component_i_lucide58panel_right, { class: "text-sm" })
          ]),
          _: 1
        }, 8, ["class"]), [
          [vShow, !isRightPanelOpen.value && hasRightPanel.value]
        ]),
        createVNode(_sfc_main$h, {
          class: "absolute top-4 right-6 z-10 transition-opacity duration-200",
          onClick: unref(closeDialog)
        }, {
          default: withCtx(() => _cache[0] || (_cache[0] = [
            createElementVNode("i", { class: "pi pi-times text-sm" }, null, -1)
          ])),
          _: 1
        }, 8, ["onClick"]),
        createElementVNode("div", _hoisted_2$4, [
          createVNode(Transition, { name: "slide-panel" }, {
            default: withCtx(() => [
              _ctx.$slots.leftPanel && showLeftPanel.value ? (openBlock(), createElementBlock("nav", {
                key: 0,
                class: normalizeClass([
                  PANEL_SIZES.width,
                  PANEL_SIZES.minWidth,
                  PANEL_SIZES.maxWidth
                ])
              }, [
                renderSlot(_ctx.$slots, "leftPanel", {}, void 0, true)
              ], 2)) : createCommentVNode("", true)
            ]),
            _: 3
          }),
          createElementVNode("div", _hoisted_3$4, [
            createElementVNode("div", _hoisted_4$3, [
              _ctx.$slots.header ? (openBlock(), createElementBlock("header", _hoisted_5, [
                createElementVNode("div", _hoisted_6, [
                  !unref(notMobile) ? (openBlock(), createBlock(_sfc_main$h, {
                    key: 0,
                    onClick: toggleLeftPanel
                  }, {
                    default: withCtx(() => [
                      !showLeftPanel.value ? (openBlock(), createBlock(_component_i_lucide58panel_left, {
                        key: 0,
                        class: "text-sm"
                      })) : (openBlock(), createBlock(_component_i_lucide58panel_left_close, {
                        key: 1,
                        class: "text-sm"
                      }))
                    ]),
                    _: 1
                  })) : createCommentVNode("", true),
                  renderSlot(_ctx.$slots, "header", {}, void 0, true)
                ]),
                renderSlot(_ctx.$slots, "header-right-area", {}, void 0, true),
                createElementVNode("div", {
                  class: normalizeClass([
                    "flex justify-end gap-2 w-0",
                    hasRightPanel.value && !isRightPanelOpen.value ? "min-w-18" : "min-w-8"
                  ])
                }, [
                  isRightPanelOpen.value && hasRightPanel.value ? (openBlock(), createBlock(_sfc_main$h, {
                    key: 0,
                    onClick: toggleRightPanel
                  }, {
                    default: withCtx(() => [
                      createVNode(_component_i_lucide58panel_right_close, { class: "text-sm" })
                    ]),
                    _: 1
                  })) : createCommentVNode("", true)
                ], 2)
              ])) : createCommentVNode("", true),
              createElementVNode("main", _hoisted_7, [
                renderSlot(_ctx.$slots, "contentFilter", {}, void 0, true),
                !_ctx.$slots.leftPanel ? (openBlock(), createElementBlock("h2", _hoisted_8, toDisplayString(_ctx.contentTitle), 1)) : createCommentVNode("", true),
                createElementVNode("div", _hoisted_9, [
                  renderSlot(_ctx.$slots, "content", {}, void 0, true)
                ])
              ])
            ]),
            hasRightPanel.value && isRightPanelOpen.value ? (openBlock(), createElementBlock("aside", _hoisted_10, [
              renderSlot(_ctx.$slots, "rightPanel", {}, void 0, true)
            ])) : createCommentVNode("", true)
          ])
        ])
      ]);
    };
  }
});
const BaseWidgetLayout = /* @__PURE__ */ _export_sfc(_sfc_main$7, [["__scopeId", "data-v-548e9163"]]);
const _hoisted_1$6 = { class: "flex items-center" };
const _sfc_main$6 = /* @__PURE__ */ defineComponent({
  __name: "NavItem",
  props: {
    hasFolderIcon: { type: Boolean, default: true },
    active: { type: Boolean },
    onClick: { type: Function }
  },
  setup(__props) {
    return (_ctx, _cache) => {
      const _component_i_lucide58folder = __unplugin_components_6;
      return openBlock(), createElementBlock("div", {
        class: normalizeClass([
          "flex items-center gap-2 px-4 py-2 text-xs rounded-md transition-colors cursor-pointer",
          _ctx.active ? "bg-neutral-100 dark-theme:bg-zinc-700 text-neutral" : "text-neutral hover:bg-zinc-100 dark-theme:hover:bg-zinc-700/50"
        ]),
        role: "button",
        onClick: _cache[0] || (_cache[0] = //@ts-ignore
        (...args) => _ctx.onClick && _ctx.onClick(...args))
      }, [
        _ctx.hasFolderIcon ? (openBlock(), createBlock(_component_i_lucide58folder, {
          key: 0,
          class: "text-xs text-neutral"
        })) : createCommentVNode("", true),
        createElementVNode("span", _hoisted_1$6, [
          renderSlot(_ctx.$slots, "default")
        ])
      ], 2);
    };
  }
});
const _hoisted_1$5 = { class: "m-0 px-3 py-0 pt-5 text-xxs font-bold uppercase text-neutral-400 dark-theme:text-neutral-400" };
const _sfc_main$5 = /* @__PURE__ */ defineComponent({
  __name: "NavTitle",
  props: {
    title: {}
  },
  setup(__props) {
    return (_ctx, _cache) => {
      return openBlock(), createElementBlock("h3", _hoisted_1$5, toDisplayString(_ctx.title), 1);
    };
  }
});
const _sfc_main$4 = {};
const _hoisted_1$4 = { class: "flex items-center justify-between h-16 px-6" };
const _hoisted_2$3 = { class: "flex items-center gap-2 pl-1" };
const _hoisted_3$3 = { class: "font-bold text-base text-neutral" };
function _sfc_render$1(_ctx, _cache) {
  const _component_i_lucide58puzzle = __unplugin_components_0$3;
  return openBlock(), createElementBlock("header", _hoisted_1$4, [
    createElementVNode("div", _hoisted_2$3, [
      renderSlot(_ctx.$slots, "icon", {}, () => [
        createVNode(_component_i_lucide58puzzle, { class: "text-neutral text-base" })
      ]),
      createElementVNode("h2", _hoisted_3$3, [
        renderSlot(_ctx.$slots, "default")
      ])
    ])
  ]);
}
__name(_sfc_render$1, "_sfc_render$1");
const PanelHeader = /* @__PURE__ */ _export_sfc(_sfc_main$4, [["render", _sfc_render$1]]);
const _hoisted_1$3 = { class: "flex flex-col h-full w-full bg-white dark-theme:bg-zinc-800" };
const _hoisted_2$2 = { class: "flex-1 px-3 py-4 flex flex-col gap-1" };
const _hoisted_3$2 = {
  key: 0,
  class: "flex flex-col gap-2"
};
const _hoisted_4$2 = {
  key: 1,
  class: "flex flex-col gap-2"
};
const _sfc_main$3 = /* @__PURE__ */ defineComponent({
  __name: "LeftSidePanel",
  props: {
    navItems: { default: /* @__PURE__ */ __name(() => [], "default") },
    modelValue: {}
  },
  emits: ["update:modelValue"],
  setup(__props, { emit: __emit }) {
    const emit = __emit;
    const getFirstItemId = /* @__PURE__ */ __name(() => {
      if (!__props.navItems || __props.navItems.length === 0) {
        return null;
      }
      const firstEntry = __props.navItems[0];
      if ("items" in firstEntry && firstEntry.items.length > 0) {
        return firstEntry.items[0].id;
      }
      if ("id" in firstEntry) {
        return firstEntry.id;
      }
      return null;
    }, "getFirstItemId");
    const activeItem = computed({
      get: /* @__PURE__ */ __name(() => __props.modelValue ?? getFirstItemId(), "get"),
      set: /* @__PURE__ */ __name((value) => emit("update:modelValue", value), "set")
    });
    return (_ctx, _cache) => {
      return openBlock(), createElementBlock("div", _hoisted_1$3, [
        createVNode(PanelHeader, null, {
          icon: withCtx(() => [
            renderSlot(_ctx.$slots, "header-icon")
          ]),
          default: withCtx(() => [
            renderSlot(_ctx.$slots, "header-title")
          ]),
          _: 3
        }),
        createElementVNode("nav", _hoisted_2$2, [
          (openBlock(true), createElementBlock(Fragment, null, renderList(_ctx.navItems, (item, index) => {
            return openBlock(), createElementBlock(Fragment, { key: index }, [
              "items" in item ? (openBlock(), createElementBlock("div", _hoisted_3$2, [
                createVNode(_sfc_main$5, {
                  title: item.title
                }, null, 8, ["title"]),
                (openBlock(true), createElementBlock(Fragment, null, renderList(item.items, (subItem) => {
                  return openBlock(), createBlock(_sfc_main$6, {
                    key: subItem.id,
                    active: activeItem.value === subItem.id,
                    onClick: /* @__PURE__ */ __name(($event) => activeItem.value = subItem.id, "onClick")
                  }, {
                    default: withCtx(() => [
                      createTextVNode(toDisplayString(subItem.label), 1)
                    ]),
                    _: 2
                  }, 1032, ["active", "onClick"]);
                }), 128))
              ])) : (openBlock(), createElementBlock("div", _hoisted_4$2, [
                createVNode(_sfc_main$6, {
                  active: activeItem.value === item.id,
                  onClick: /* @__PURE__ */ __name(($event) => activeItem.value = item.id, "onClick")
                }, {
                  default: withCtx(() => [
                    createTextVNode(toDisplayString(item.label), 1)
                  ]),
                  _: 2
                }, 1032, ["active", "onClick"])
              ]))
            ], 64);
          }), 128))
        ])
      ]);
    };
  }
});
const _sfc_main$2 = {};
const _hoisted_1$2 = { class: "w-full h-full pl-4 pr-6 pb-8 bg-white dark-theme:bg-zinc-800" };
function _sfc_render(_ctx, _cache) {
  return openBlock(), createElementBlock("div", _hoisted_1$2, [
    renderSlot(_ctx.$slots, "default")
  ]);
}
__name(_sfc_render, "_sfc_render");
const RightSidePanel = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["render", _sfc_render]]);
const _hoisted_1$1 = { class: "text-neutral text-base" };
const _hoisted_2$1 = { class: "flex gap-2" };
const _hoisted_3$1 = { class: "relative px-6 pt-2 pb-4 flex gap-2" };
const _hoisted_4$1 = { class: "flex flex-wrap gap-2" };
const _sfc_main$1 = /* @__PURE__ */ defineComponent({
  __name: "SampleModelSelector",
  props: {
    onClose: { type: Function }
  },
  setup(__props) {
    const frameworkOptions = ref([
      { name: "Vue", value: "vue" },
      { name: "React", value: "react" },
      { name: "Angular", value: "angular" },
      { name: "Svelte", value: "svelte" }
    ]);
    const projectOptions = ref([
      { name: "Project A", value: "proj-a" },
      { name: "Project B", value: "proj-b" },
      { name: "Project C", value: "proj-c" }
    ]);
    const sortOptions = ref([
      { name: "Popular", value: "popular" },
      { name: "Latest", value: "latest" },
      { name: "A → Z", value: "az" }
    ]);
    const tempNavigation = ref([
      { id: "installed", label: "Installed" },
      {
        title: "TAGS",
        items: [
          { id: "tag-sd15", label: "SD 1.5" },
          { id: "tag-sdxl", label: "SDXL" },
          { id: "tag-utility", label: "Utility" }
        ]
      },
      {
        title: "CATEGORIES",
        items: [
          { id: "cat-models", label: "Models" },
          { id: "cat-nodes", label: "Nodes" }
        ]
      }
    ]);
    const { t: t2 } = useI18n();
    provide(OnCloseKey, __props.onClose);
    const searchQuery = ref("");
    const searchText = ref("");
    const selectedFrameworks = ref([]);
    const selectedProjects = ref([]);
    const selectedSort = ref("popular");
    const selectedNavItem = ref("installed");
    watch(searchText, (newQuery) => {
      console.log("searchText:", searchText.value, newQuery);
    });
    watch(searchQuery, (newQuery) => {
      console.log("searchQuery:", searchQuery.value, newQuery);
    });
    return (_ctx, _cache) => {
      const _component_i_lucide58puzzle = __unplugin_components_0$3;
      const _component_i_lucide58upload = __unplugin_components_1$2;
      const _component_i_lucide58download = __unplugin_components_2$1;
      const _component_i_lucide58scroll = __unplugin_components_3$1;
      const _component_i_lucide58filter = __unplugin_components_4;
      const _component_i_lucide58info = __unplugin_components_5;
      const _component_i_lucide58folder = __unplugin_components_6;
      return openBlock(), createBlock(BaseWidgetLayout, {
        "content-title": _ctx.$t("Checkpoints")
      }, {
        leftPanel: withCtx(() => [
          createVNode(_sfc_main$3, {
            modelValue: selectedNavItem.value,
            "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => selectedNavItem.value = $event),
            "nav-items": tempNavigation.value
          }, {
            "header-icon": withCtx(() => [
              createVNode(_component_i_lucide58puzzle, { class: "text-neutral" })
            ]),
            "header-title": withCtx(() => [
              createElementVNode("span", _hoisted_1$1, toDisplayString(unref(t2)("g.title")), 1)
            ]),
            _: 1
          }, 8, ["modelValue", "nav-items"])
        ]),
        header: withCtx(() => [
          createVNode(_sfc_main$b, {
            modelValue: searchQuery.value,
            "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => searchQuery.value = $event),
            class: "max-w-[384px]"
          }, null, 8, ["modelValue"])
        ]),
        "header-right-area": withCtx(() => [
          createElementVNode("div", _hoisted_2$1, [
            createVNode(_sfc_main$1D, {
              type: "primary",
              label: "Upload Model",
              onClick: /* @__PURE__ */ __name(() => {
              }, "onClick")
            }, {
              icon: withCtx(() => [
                createVNode(_component_i_lucide58upload)
              ]),
              _: 1
            }),
            createVNode(_sfc_main$g, null, {
              default: withCtx(({ close }) => [
                createVNode(_sfc_main$1D, {
                  type: "secondary",
                  label: "Settings",
                  onClick: /* @__PURE__ */ __name(() => {
                    close();
                  }, "onClick")
                }, {
                  icon: withCtx(() => [
                    createVNode(_component_i_lucide58download)
                  ]),
                  _: 2
                }, 1032, ["onClick"]),
                createVNode(_sfc_main$1D, {
                  type: "primary",
                  label: "Profile",
                  onClick: /* @__PURE__ */ __name(() => {
                    close();
                  }, "onClick")
                }, {
                  icon: withCtx(() => [
                    createVNode(_component_i_lucide58scroll)
                  ]),
                  _: 2
                }, 1032, ["onClick"])
              ]),
              _: 1
            })
          ])
        ]),
        contentFilter: withCtx(() => [
          createElementVNode("div", _hoisted_3$1, [
            createVNode(_sfc_main$9, {
              modelValue: selectedFrameworks.value,
              "onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => selectedFrameworks.value = $event),
              "search-query": searchText.value,
              "onUpdate:searchQuery": _cache[3] || (_cache[3] = ($event) => searchText.value = $event),
              class: "w-[250px]",
              label: "Select Frameworks",
              options: frameworkOptions.value,
              "show-search-box": true,
              "show-selected-count": true,
              "show-clear-button": true
            }, null, 8, ["modelValue", "search-query", "options"]),
            createVNode(_sfc_main$9, {
              modelValue: selectedProjects.value,
              "onUpdate:modelValue": _cache[4] || (_cache[4] = ($event) => selectedProjects.value = $event),
              label: "Select Projects",
              options: projectOptions.value
            }, null, 8, ["modelValue", "options"]),
            createVNode(_sfc_main$8, {
              modelValue: selectedSort.value,
              "onUpdate:modelValue": _cache[5] || (_cache[5] = ($event) => selectedSort.value = $event),
              label: "Sorting Type",
              options: sortOptions.value,
              class: "w-[135px]"
            }, {
              icon: withCtx(() => [
                createVNode(_component_i_lucide58filter)
              ]),
              _: 1
            }, 8, ["modelValue", "options"])
          ])
        ]),
        content: withCtx(() => [
          createElementVNode("div", _hoisted_4$1, [
            (openBlock(), createElementBlock(Fragment, null, renderList(100, (i) => {
              return createVNode(_sfc_main$e, {
                key: i,
                ratio: "square",
                "max-width": 480,
                "min-width": 230
              }, {
                top: withCtx(() => [
                  createVNode(_sfc_main$d, { ratio: "landscape" }, {
                    default: withCtx(() => _cache[6] || (_cache[6] = [
                      createElementVNode("div", { class: "w-full h-full bg-blue-500" }, null, -1)
                    ])),
                    "top-right": withCtx(() => [
                      createVNode(_sfc_main$h, {
                        class: "!bg-white !text-neutral-900",
                        onClick: /* @__PURE__ */ __name(() => {
                        }, "onClick")
                      }, {
                        default: withCtx(() => [
                          createVNode(_component_i_lucide58info)
                        ]),
                        _: 1
                      })
                    ]),
                    "bottom-right": withCtx(() => [
                      createVNode(_sfc_main$c, { label: "png" }),
                      createVNode(_sfc_main$c, { label: "1.2 MB" }),
                      createVNode(_sfc_main$c, { label: "LoRA" }, {
                        icon: withCtx(() => [
                          createVNode(_component_i_lucide58folder)
                        ]),
                        _: 1
                      })
                    ]),
                    _: 1
                  })
                ]),
                bottom: withCtx(() => [
                  createVNode(CardBottom)
                ]),
                _: 2
              }, 1024);
            }), 64))
          ])
        ]),
        rightPanel: withCtx(() => [
          createVNode(RightSidePanel)
        ]),
        _: 1
      }, 8, ["content-title"]);
    };
  }
});
const DIALOG_KEY = "global-model-selector";
const useModelSelectorDialog = /* @__PURE__ */ __name(() => {
  const dialogService = useDialogService();
  const dialogStore = useDialogStore();
  function hide() {
    dialogStore.closeDialog({ key: DIALOG_KEY });
  }
  __name(hide, "hide");
  function show() {
    dialogService.showLayoutDialog({
      key: DIALOG_KEY,
      component: _sfc_main$1,
      props: {
        onClose: hide
      }
    });
  }
  __name(show, "show");
  return {
    show,
    hide
  };
}, "useModelSelectorDialog");
const isOutputNode = /* @__PURE__ */ __name((node) => node.constructor.nodeData?.output_node, "isOutputNode");
const filterOutputNodes = /* @__PURE__ */ __name((nodes) => nodes.filter(isOutputNode), "filterOutputNodes");
const moveSelectedNodesVersionAdded = "1.22.2";
function useCoreCommands() {
  const workflowService = useWorkflowService();
  const workflowStore = useWorkflowStore();
  const dialogService = useDialogService();
  const colorPaletteStore = useColorPaletteStore();
  const firebaseAuthActions = useFirebaseAuthActions();
  const toastStore = useToastStore();
  const canvasStore = useCanvasStore();
  const executionStore = useExecutionStore();
  const bottomPanelStore = useBottomPanelStore();
  const { getSelectedNodes, toggleSelectedNodesMode } = useSelectedLiteGraphItems();
  const getTracker = /* @__PURE__ */ __name(() => workflowStore.activeWorkflow?.changeTracker, "getTracker");
  const moveSelectedNodes = /* @__PURE__ */ __name((positionUpdater) => {
    const selectedNodes = getSelectedNodes();
    if (selectedNodes.length === 0) return;
    const gridSize = useSettingStore().get("Comfy.SnapToGrid.GridSize");
    selectedNodes.forEach((node) => {
      node.pos = positionUpdater(node.pos, gridSize);
    });
    app.canvas.state.selectionChanged = true;
    app.canvas.setDirty(true, true);
  }, "moveSelectedNodes");
  const commands = [
    {
      id: "Comfy.NewBlankWorkflow",
      icon: "pi pi-plus",
      label: "New Blank Workflow",
      menubarLabel: "New",
      category: "essentials",
      function: /* @__PURE__ */ __name(() => workflowService.loadBlankWorkflow(), "function")
    },
    {
      id: "Comfy.OpenWorkflow",
      icon: "pi pi-folder-open",
      label: "Open Workflow",
      menubarLabel: "Open",
      category: "essentials",
      function: /* @__PURE__ */ __name(() => {
        app.ui.loadFile();
      }, "function")
    },
    {
      id: "Comfy.LoadDefaultWorkflow",
      icon: "pi pi-code",
      label: "Load Default Workflow",
      function: /* @__PURE__ */ __name(() => workflowService.loadDefaultWorkflow(), "function")
    },
    {
      id: "Comfy.SaveWorkflow",
      icon: "pi pi-save",
      label: "Save Workflow",
      menubarLabel: "Save",
      category: "essentials",
      function: /* @__PURE__ */ __name(async () => {
        const workflow = useWorkflowStore().activeWorkflow;
        if (!workflow) return;
        await workflowService.saveWorkflow(workflow);
      }, "function")
    },
    {
      id: "Comfy.SaveWorkflowAs",
      icon: "pi pi-save",
      label: "Save Workflow As",
      menubarLabel: "Save As",
      category: "essentials",
      function: /* @__PURE__ */ __name(async () => {
        const workflow = useWorkflowStore().activeWorkflow;
        if (!workflow) return;
        await workflowService.saveWorkflowAs(workflow);
      }, "function")
    },
    {
      id: "Comfy.ExportWorkflow",
      icon: "pi pi-download",
      label: "Export Workflow",
      menubarLabel: "Export",
      category: "essentials",
      function: /* @__PURE__ */ __name(async () => {
        await workflowService.exportWorkflow("workflow", "workflow");
      }, "function")
    },
    {
      id: "Comfy.ExportWorkflowAPI",
      icon: "pi pi-download",
      label: "Export Workflow (API Format)",
      menubarLabel: "Export (API)",
      function: /* @__PURE__ */ __name(async () => {
        await workflowService.exportWorkflow("workflow_api", "output");
      }, "function")
    },
    {
      id: "Comfy.Undo",
      icon: "pi pi-undo",
      label: "Undo",
      category: "essentials",
      function: /* @__PURE__ */ __name(async () => {
        await getTracker()?.undo?.();
      }, "function")
    },
    {
      id: "Comfy.Redo",
      icon: "pi pi-refresh",
      label: "Redo",
      category: "essentials",
      function: /* @__PURE__ */ __name(async () => {
        await getTracker()?.redo?.();
      }, "function")
    },
    {
      id: "Comfy.ClearWorkflow",
      icon: "pi pi-trash",
      label: "Clear Workflow",
      category: "essentials",
      function: /* @__PURE__ */ __name(() => {
        const settingStore = useSettingStore();
        if (!settingStore.get("Comfy.ConfirmClear") || confirm("Clear workflow?")) {
          app.clean();
          if (app.canvas.subgraph) {
            const subgraph = app.canvas.subgraph;
            const nonIoNodes = getAllNonIoNodesInSubgraph(subgraph);
            nonIoNodes.forEach((node) => subgraph.remove(node));
          } else {
            app.graph.clear();
          }
          api.dispatchCustomEvent("graphCleared");
        }
      }, "function")
    },
    {
      id: "Comfy.Canvas.ResetView",
      icon: "pi pi-expand",
      label: "Reset View",
      function: /* @__PURE__ */ __name(() => {
        useLitegraphService().resetView();
      }, "function")
    },
    {
      id: "Comfy.OpenClipspace",
      icon: "pi pi-clipboard",
      label: "Clipspace",
      function: /* @__PURE__ */ __name(() => {
        app.openClipspace();
      }, "function")
    },
    {
      id: "Comfy.RefreshNodeDefinitions",
      icon: "pi pi-refresh",
      label: "Refresh Node Definitions",
      category: "essentials",
      function: /* @__PURE__ */ __name(async () => {
        await app.refreshComboInNodes();
      }, "function")
    },
    {
      id: "Comfy.Interrupt",
      icon: "pi pi-stop",
      label: "Interrupt",
      category: "essentials",
      function: /* @__PURE__ */ __name(async () => {
        await api.interrupt(executionStore.activePromptId);
        toastStore.add({
          severity: "info",
          summary: t("g.interrupted"),
          detail: t("toastMessages.interrupted"),
          life: 1e3
        });
      }, "function")
    },
    {
      id: "Comfy.ClearPendingTasks",
      icon: "pi pi-stop",
      label: "Clear Pending Tasks",
      category: "essentials",
      function: /* @__PURE__ */ __name(async () => {
        await useQueueStore().clear(["queue"]);
        toastStore.add({
          severity: "info",
          summary: t("g.confirmed"),
          detail: t("toastMessages.pendingTasksDeleted"),
          life: 3e3
        });
      }, "function")
    },
    {
      id: "Comfy.BrowseTemplates",
      icon: "pi pi-folder-open",
      label: "Browse Templates",
      function: /* @__PURE__ */ __name(() => {
        dialogService.showTemplateWorkflowsDialog();
      }, "function")
    },
    {
      id: "Comfy.Canvas.ZoomIn",
      icon: "pi pi-plus",
      label: "Zoom In",
      category: "view-controls",
      function: /* @__PURE__ */ __name(() => {
        const ds = app.canvas.ds;
        ds.changeScale(
          ds.scale * 1.1,
          ds.element ? [ds.element.width / 2, ds.element.height / 2] : void 0
        );
        app.canvas.setDirty(true, true);
      }, "function")
    },
    {
      id: "Comfy.Canvas.ZoomOut",
      icon: "pi pi-minus",
      label: "Zoom Out",
      category: "view-controls",
      function: /* @__PURE__ */ __name(() => {
        const ds = app.canvas.ds;
        ds.changeScale(
          ds.scale / 1.1,
          ds.element ? [ds.element.width / 2, ds.element.height / 2] : void 0
        );
        app.canvas.setDirty(true, true);
      }, "function")
    },
    {
      id: "Experimental.ToggleVueNodes",
      label: /* @__PURE__ */ __name(() => `Experimental: ${useSettingStore().get("Comfy.VueNodes.Enabled") ? "Disable" : "Enable"} Vue Nodes`, "label"),
      function: /* @__PURE__ */ __name(async () => {
        const settingStore = useSettingStore();
        const current = settingStore.get("Comfy.VueNodes.Enabled") ?? false;
        await settingStore.set("Comfy.VueNodes.Enabled", !current);
      }, "function")
    },
    {
      id: "Comfy.Canvas.FitView",
      icon: "pi pi-expand",
      label: "Fit view to selected nodes",
      menubarLabel: "Zoom to fit",
      category: "view-controls",
      function: /* @__PURE__ */ __name(() => {
        if (app.canvas.empty) {
          toastStore.add({
            severity: "error",
            summary: t("toastMessages.emptyCanvas"),
            life: 3e3
          });
          return;
        }
        app.canvas.fitViewToSelectionAnimated();
      }, "function")
    },
    {
      id: "Comfy.Canvas.ToggleLock",
      icon: "pi pi-lock",
      label: "Canvas Toggle Lock",
      category: "view-controls",
      function: /* @__PURE__ */ __name(() => {
        app.canvas.state.readOnly = !app.canvas.state.readOnly;
      }, "function")
    },
    {
      id: "Comfy.Canvas.Lock",
      icon: "pi pi-lock",
      label: "Lock Canvas",
      category: "view-controls",
      function: /* @__PURE__ */ __name(() => {
        app.canvas.state.readOnly = true;
      }, "function")
    },
    {
      id: "Comfy.Canvas.Unlock",
      icon: "pi pi-lock-open",
      label: "Unlock Canvas",
      function: /* @__PURE__ */ __name(() => {
        app.canvas.state.readOnly = false;
      }, "function")
    },
    {
      id: "Comfy.Canvas.ToggleLinkVisibility",
      icon: "pi pi-eye",
      label: "Canvas Toggle Link Visibility",
      menubarLabel: "Node Links",
      versionAdded: "1.3.6",
      function: (() => {
        const settingStore = useSettingStore();
        let lastLinksRenderMode = LiteGraph.SPLINE_LINK;
        return async () => {
          const currentMode = settingStore.get("Comfy.LinkRenderMode");
          if (currentMode === LiteGraph.HIDDEN_LINK) {
            await settingStore.set("Comfy.LinkRenderMode", lastLinksRenderMode);
          } else {
            lastLinksRenderMode = currentMode;
            await settingStore.set(
              "Comfy.LinkRenderMode",
              LiteGraph.HIDDEN_LINK
            );
          }
        };
      })(),
      active: /* @__PURE__ */ __name(() => useSettingStore().get("Comfy.LinkRenderMode") !== LiteGraph.HIDDEN_LINK, "active")
    },
    {
      id: "Comfy.Canvas.ToggleMinimap",
      icon: "pi pi-map",
      label: "Canvas Toggle Minimap",
      menubarLabel: "Minimap",
      versionAdded: "1.24.1",
      function: /* @__PURE__ */ __name(async () => {
        const settingStore = useSettingStore();
        await settingStore.set(
          "Comfy.Minimap.Visible",
          !settingStore.get("Comfy.Minimap.Visible")
        );
      }, "function"),
      active: /* @__PURE__ */ __name(() => useSettingStore().get("Comfy.Minimap.Visible"), "active")
    },
    {
      id: "Comfy.QueuePrompt",
      icon: "pi pi-play",
      label: "Queue Prompt",
      versionAdded: "1.3.7",
      category: "essentials",
      function: /* @__PURE__ */ __name(async () => {
        const batchCount = useQueueSettingsStore().batchCount;
        await app.queuePrompt(0, batchCount);
      }, "function")
    },
    {
      id: "Comfy.QueuePromptFront",
      icon: "pi pi-play",
      label: "Queue Prompt (Front)",
      versionAdded: "1.3.7",
      category: "essentials",
      function: /* @__PURE__ */ __name(async () => {
        const batchCount = useQueueSettingsStore().batchCount;
        await app.queuePrompt(-1, batchCount);
      }, "function")
    },
    {
      id: "Comfy.QueueSelectedOutputNodes",
      icon: "pi pi-play",
      label: "Queue Selected Output Nodes",
      versionAdded: "1.19.6",
      function: /* @__PURE__ */ __name(async () => {
        const batchCount = useQueueSettingsStore().batchCount;
        const selectedNodes = getSelectedNodes();
        const selectedOutputNodes = filterOutputNodes(selectedNodes);
        if (selectedOutputNodes.length === 0) {
          toastStore.add({
            severity: "error",
            summary: t("toastMessages.nothingToQueue"),
            detail: t("toastMessages.pleaseSelectOutputNodes"),
            life: 3e3
          });
          return;
        }
        const executionIds = getExecutionIdsForSelectedNodes(selectedOutputNodes);
        await app.queuePrompt(0, batchCount, executionIds);
      }, "function")
    },
    {
      id: "Comfy.ShowSettingsDialog",
      icon: "pi pi-cog",
      label: "Show Settings Dialog",
      versionAdded: "1.3.7",
      category: "view-controls",
      function: /* @__PURE__ */ __name(() => {
        dialogService.showSettingsDialog();
      }, "function")
    },
    {
      id: "Comfy.Graph.GroupSelectedNodes",
      icon: "pi pi-sitemap",
      label: "Group Selected Nodes",
      versionAdded: "1.3.7",
      category: "essentials",
      function: /* @__PURE__ */ __name(() => {
        const { canvas } = app;
        if (!canvas.selectedItems?.size) {
          toastStore.add({
            severity: "error",
            summary: t("toastMessages.nothingToGroup"),
            detail: t("toastMessages.pleaseSelectNodesToGroup"),
            life: 3e3
          });
          return;
        }
        const group = new LGraphGroup();
        const padding = useSettingStore().get(
          "Comfy.GroupSelectedNodes.Padding"
        );
        group.resizeTo(canvas.selectedItems, padding);
        canvas.graph?.add(group);
        group.recomputeInsideNodes();
        useTitleEditorStore().titleEditorTarget = group;
      }, "function")
    },
    {
      id: "Workspace.NextOpenedWorkflow",
      icon: "pi pi-step-forward",
      label: "Next Opened Workflow",
      versionAdded: "1.3.9",
      function: /* @__PURE__ */ __name(async () => {
        await workflowService.loadNextOpenedWorkflow();
      }, "function")
    },
    {
      id: "Workspace.PreviousOpenedWorkflow",
      icon: "pi pi-step-backward",
      label: "Previous Opened Workflow",
      versionAdded: "1.3.9",
      function: /* @__PURE__ */ __name(async () => {
        await workflowService.loadPreviousOpenedWorkflow();
      }, "function")
    },
    {
      id: "Comfy.Canvas.ToggleSelectedNodes.Mute",
      icon: "pi pi-volume-off",
      label: "Mute/Unmute Selected Nodes",
      versionAdded: "1.3.11",
      category: "essentials",
      function: /* @__PURE__ */ __name(() => {
        toggleSelectedNodesMode(LGraphEventMode.NEVER);
        app.canvas.setDirty(true, true);
      }, "function")
    },
    {
      id: "Comfy.Canvas.ToggleSelectedNodes.Bypass",
      icon: "pi pi-shield",
      label: "Bypass/Unbypass Selected Nodes",
      versionAdded: "1.3.11",
      category: "essentials",
      function: /* @__PURE__ */ __name(() => {
        toggleSelectedNodesMode(LGraphEventMode.BYPASS);
        app.canvas.setDirty(true, true);
      }, "function")
    },
    {
      id: "Comfy.Canvas.ToggleSelectedNodes.Pin",
      icon: "pi pi-pin",
      label: "Pin/Unpin Selected Nodes",
      versionAdded: "1.3.11",
      category: "essentials",
      function: /* @__PURE__ */ __name(() => {
        getSelectedNodes().forEach((node) => {
          node.pin(!node.pinned);
        });
        app.canvas.setDirty(true, true);
      }, "function")
    },
    {
      id: "Comfy.Canvas.ToggleSelected.Pin",
      icon: "pi pi-pin",
      label: "Pin/Unpin Selected Items",
      versionAdded: "1.3.33",
      function: /* @__PURE__ */ __name(() => {
        for (const item of app.canvas.selectedItems) {
          if (item instanceof LGraphNode || item instanceof LGraphGroup) {
            item.pin(!item.pinned);
          }
        }
        app.canvas.setDirty(true, true);
      }, "function")
    },
    {
      id: "Comfy.Canvas.Resize",
      icon: "pi pi-minus",
      label: "Resize Selected Nodes",
      versionAdded: "",
      function: /* @__PURE__ */ __name(() => {
        getSelectedNodes().forEach((node) => {
          const optimalSize = node.computeSize();
          node.setSize([optimalSize[0], optimalSize[1]]);
        });
        app.canvas.setDirty(true, true);
      }, "function")
    },
    {
      id: "Comfy.Canvas.ToggleSelectedNodes.Collapse",
      icon: "pi pi-minus",
      label: "Collapse/Expand Selected Nodes",
      versionAdded: "1.3.11",
      function: /* @__PURE__ */ __name(() => {
        getSelectedNodes().forEach((node) => {
          node.collapse();
        });
        app.canvas.setDirty(true, true);
      }, "function")
    },
    {
      id: "Comfy.ToggleTheme",
      icon: "pi pi-moon",
      label: "Toggle Theme (Dark/Light)",
      versionAdded: "1.3.12",
      function: (() => {
        let previousDarkTheme = DEFAULT_DARK_COLOR_PALETTE.id;
        let previousLightTheme = DEFAULT_LIGHT_COLOR_PALETTE.id;
        return async () => {
          const settingStore = useSettingStore();
          const theme = colorPaletteStore.completedActivePalette;
          if (theme.light_theme) {
            previousLightTheme = theme.id;
            await settingStore.set("Comfy.ColorPalette", previousDarkTheme);
          } else {
            previousDarkTheme = theme.id;
            await settingStore.set("Comfy.ColorPalette", previousLightTheme);
          }
        };
      })()
    },
    {
      id: "Workspace.ToggleBottomPanel",
      icon: "pi pi-list",
      label: "Toggle Bottom Panel",
      menubarLabel: "Bottom Panel",
      versionAdded: "1.3.22",
      category: "view-controls",
      function: /* @__PURE__ */ __name(() => {
        bottomPanelStore.toggleBottomPanel();
      }, "function"),
      active: /* @__PURE__ */ __name(() => bottomPanelStore.bottomPanelVisible, "active")
    },
    {
      id: "Workspace.ToggleFocusMode",
      icon: "pi pi-eye",
      label: "Toggle Focus Mode",
      menubarLabel: "Focus Mode",
      versionAdded: "1.3.27",
      category: "view-controls",
      function: /* @__PURE__ */ __name(() => {
        useWorkspaceStore().toggleFocusMode();
      }, "function"),
      active: /* @__PURE__ */ __name(() => useWorkspaceStore().focusMode, "active")
    },
    {
      id: "Comfy.Graph.FitGroupToContents",
      icon: "pi pi-expand",
      label: "Fit Group To Contents",
      versionAdded: "1.4.9",
      function: /* @__PURE__ */ __name(() => {
        for (const group of app.canvas.selectedItems) {
          if (group instanceof LGraphGroup) {
            group.recomputeInsideNodes();
            const padding = useSettingStore().get(
              "Comfy.GroupSelectedNodes.Padding"
            );
            group.resizeTo(group.children, padding);
            app.graph.change();
          }
        }
      }, "function")
    },
    {
      id: "Comfy.Help.OpenComfyUIIssues",
      icon: "pi pi-github",
      label: "Open ComfyUI Issues",
      menubarLabel: "ComfyUI Issues",
      versionAdded: "1.5.5",
      function: /* @__PURE__ */ __name(() => {
        window.open(
          "https://github.com/comfyanonymous/ComfyUI/issues",
          "_blank"
        );
      }, "function")
    },
    {
      id: "Comfy.Help.OpenComfyUIDocs",
      icon: "pi pi-info-circle",
      label: "Open ComfyUI Docs",
      menubarLabel: "ComfyUI Docs",
      versionAdded: "1.5.5",
      function: /* @__PURE__ */ __name(() => {
        window.open("https://docs.comfy.org/", "_blank");
      }, "function")
    },
    {
      id: "Comfy.Help.OpenComfyOrgDiscord",
      icon: "pi pi-discord",
      label: "Open Comfy-Org Discord",
      menubarLabel: "Comfy-Org Discord",
      versionAdded: "1.5.5",
      function: /* @__PURE__ */ __name(() => {
        window.open("https://www.comfy.org/discord", "_blank");
      }, "function")
    },
    {
      id: "Workspace.SearchBox.Toggle",
      icon: "pi pi-search",
      label: "Toggle Search Box",
      versionAdded: "1.5.7",
      function: /* @__PURE__ */ __name(() => {
        useSearchBoxStore().toggleVisible();
      }, "function")
    },
    {
      id: "Comfy.Help.AboutComfyUI",
      icon: "pi pi-info-circle",
      label: "Open About ComfyUI",
      menubarLabel: "About ComfyUI",
      versionAdded: "1.6.4",
      function: /* @__PURE__ */ __name(() => {
        dialogService.showSettingsDialog("about");
      }, "function")
    },
    {
      id: "Comfy.DuplicateWorkflow",
      icon: "pi pi-clone",
      label: "Duplicate Current Workflow",
      versionAdded: "1.6.15",
      function: /* @__PURE__ */ __name(async () => {
        await workflowService.duplicateWorkflow(workflowStore.activeWorkflow);
      }, "function")
    },
    {
      id: "Workspace.CloseWorkflow",
      icon: "pi pi-times",
      label: "Close Current Workflow",
      versionAdded: "1.7.3",
      function: /* @__PURE__ */ __name(async () => {
        if (workflowStore.activeWorkflow)
          await workflowService.closeWorkflow(workflowStore.activeWorkflow);
      }, "function")
    },
    {
      id: "Comfy.ContactSupport",
      icon: "pi pi-question",
      label: "Contact Support",
      versionAdded: "1.17.8",
      function: /* @__PURE__ */ __name(() => {
        window.open("https://support.comfy.org/", "_blank");
      }, "function")
    },
    {
      id: "Comfy.Help.OpenComfyUIForum",
      icon: "pi pi-comments",
      label: "Open ComfyUI Forum",
      menubarLabel: "ComfyUI Forum",
      versionAdded: "1.8.2",
      function: /* @__PURE__ */ __name(() => {
        window.open("https://forum.comfy.org/", "_blank");
      }, "function")
    },
    {
      id: "Comfy.Canvas.DeleteSelectedItems",
      icon: "pi pi-trash",
      label: "Delete Selected Items",
      versionAdded: "1.10.5",
      function: /* @__PURE__ */ __name(() => {
        app.canvas.deleteSelected();
        app.canvas.setDirty(true, true);
      }, "function")
    },
    {
      id: "Comfy.Manager.CustomNodesManager.ShowCustomNodesMenu",
      icon: "pi pi-puzzle",
      label: "Custom Nodes Manager",
      versionAdded: "1.12.10",
      function: /* @__PURE__ */ __name(async () => {
        const managerState = useManagerStateStore().managerUIState;
        switch (managerState) {
          case ManagerUIState.DISABLED:
            dialogService.showSettingsDialog("extension");
            break;
          case ManagerUIState.LEGACY_UI:
            try {
              await useCommandStore().execute(
                "Comfy.Manager.Menu.ToggleVisibility"
                // This command is registered by legacy manager FE extension
              );
            } catch (error) {
              console.error("error", error);
              useToastStore().add({
                severity: "error",
                summary: t("g.error"),
                detail: t("manager.legacyMenuNotAvailable"),
                life: 3e3
              });
              dialogService.showManagerDialog();
            }
            break;
          case ManagerUIState.NEW_UI:
            dialogService.showManagerDialog();
            break;
        }
      }, "function")
    },
    {
      id: "Comfy.Manager.ShowUpdateAvailablePacks",
      icon: "pi pi-sync",
      label: "Check for Custom Node Updates",
      versionAdded: "1.17.0",
      function: /* @__PURE__ */ __name(() => {
        const managerStore = useManagerStateStore();
        const state = managerStore.managerUIState;
        switch (state) {
          case ManagerUIState.DISABLED:
            toastStore.add({
              severity: "error",
              summary: t("g.error"),
              detail: t("manager.notAvailable"),
              life: 3e3
            });
            break;
          case ManagerUIState.LEGACY_UI:
            useCommandStore().execute("Comfy.Manager.Menu.ToggleVisibility").catch(() => {
              dialogService.showSettingsDialog("extension");
            });
            break;
          case ManagerUIState.NEW_UI:
            dialogService.showManagerDialog();
            break;
        }
      }, "function")
    },
    {
      id: "Comfy.Manager.ShowMissingPacks",
      icon: "pi pi-exclamation-circle",
      label: "Install Missing Custom Nodes",
      versionAdded: "1.17.0",
      function: /* @__PURE__ */ __name(async () => {
        const managerStore = useManagerStateStore();
        const state = managerStore.managerUIState;
        switch (state) {
          case ManagerUIState.DISABLED:
            dialogService.showSettingsDialog("extension");
            break;
          case ManagerUIState.LEGACY_UI:
            try {
              await useCommandStore().execute(
                "Comfy.Manager.Menu.ToggleVisibility"
              );
            } catch {
              dialogService.showSettingsDialog("extension");
            }
            break;
          case ManagerUIState.NEW_UI:
            dialogService.showManagerDialog({
              initialTab: ManagerTab.Missing
            });
            break;
        }
      }, "function")
    },
    {
      id: "Comfy.Manager.ToggleManagerProgressDialog",
      icon: "pi pi-spinner",
      label: "Toggle the Custom Nodes Manager Progress Bar",
      versionAdded: "1.13.9",
      function: /* @__PURE__ */ __name(() => {
        dialogService.toggleManagerProgressDialog();
      }, "function")
    },
    {
      id: "Comfy.User.OpenSignInDialog",
      icon: "pi pi-user",
      label: "Open Sign In Dialog",
      versionAdded: "1.17.6",
      function: /* @__PURE__ */ __name(async () => {
        await dialogService.showSignInDialog();
      }, "function")
    },
    {
      id: "Comfy.User.SignOut",
      icon: "pi pi-sign-out",
      label: "Sign Out",
      versionAdded: "1.18.1",
      function: /* @__PURE__ */ __name(async () => {
        await firebaseAuthActions.logout();
      }, "function")
    },
    {
      id: "Comfy.Canvas.MoveSelectedNodes.Up",
      icon: "pi pi-arrow-up",
      label: "Move Selected Nodes Up",
      versionAdded: moveSelectedNodesVersionAdded,
      function: /* @__PURE__ */ __name(() => moveSelectedNodes(([x, y], gridSize) => [x, y - gridSize]), "function")
    },
    {
      id: "Comfy.Canvas.MoveSelectedNodes.Down",
      icon: "pi pi-arrow-down",
      label: "Move Selected Nodes Down",
      versionAdded: moveSelectedNodesVersionAdded,
      function: /* @__PURE__ */ __name(() => moveSelectedNodes(([x, y], gridSize) => [x, y + gridSize]), "function")
    },
    {
      id: "Comfy.Canvas.MoveSelectedNodes.Left",
      icon: "pi pi-arrow-left",
      label: "Move Selected Nodes Left",
      versionAdded: moveSelectedNodesVersionAdded,
      function: /* @__PURE__ */ __name(() => moveSelectedNodes(([x, y], gridSize) => [x - gridSize, y]), "function")
    },
    {
      id: "Comfy.Canvas.MoveSelectedNodes.Right",
      icon: "pi pi-arrow-right",
      label: "Move Selected Nodes Right",
      versionAdded: moveSelectedNodesVersionAdded,
      function: /* @__PURE__ */ __name(() => moveSelectedNodes(([x, y], gridSize) => [x + gridSize, y]), "function")
    },
    {
      id: "Comfy.Graph.ConvertToSubgraph",
      icon: "pi pi-sitemap",
      label: "Convert Selection to Subgraph",
      versionAdded: "1.20.1",
      category: "essentials",
      function: /* @__PURE__ */ __name(() => {
        const canvas = canvasStore.getCanvas();
        const graph = canvas.subgraph ?? canvas.graph;
        if (!graph) throw new TypeError("Canvas has no graph or subgraph set.");
        const res = graph.convertToSubgraph(canvas.selectedItems);
        if (!res) {
          toastStore.add({
            severity: "error",
            summary: t("toastMessages.cannotCreateSubgraph"),
            detail: t("toastMessages.failedToConvertToSubgraph"),
            life: 3e3
          });
          return;
        }
        const { node } = res;
        canvas.select(node);
        canvasStore.updateSelectedItems();
      }, "function")
    },
    {
      id: "Comfy.Graph.UnpackSubgraph",
      icon: "pi pi-sitemap",
      label: "Unpack the selected Subgraph",
      versionAdded: "1.20.1",
      category: "essentials",
      function: /* @__PURE__ */ __name(() => {
        const canvas = canvasStore.getCanvas();
        const graph = canvas.subgraph ?? canvas.graph;
        if (!graph) throw new TypeError("Canvas has no graph or subgraph set.");
        const subgraphNode = app.canvas.selectedItems.values().next().value;
        if (!(subgraphNode instanceof SubgraphNode)) return;
        useNodeOutputStore().revokeSubgraphPreviews(subgraphNode);
        graph.unpackSubgraph(subgraphNode);
      }, "function")
    },
    {
      id: "Comfy.OpenManagerDialog",
      icon: "mdi mdi-puzzle-outline",
      label: "Manager",
      function: /* @__PURE__ */ __name(() => {
        dialogService.showManagerDialog();
      }, "function")
    },
    {
      id: "Comfy.ToggleHelpCenter",
      icon: "pi pi-question-circle",
      label: "Help Center",
      function: /* @__PURE__ */ __name(() => {
        useHelpCenterStore().toggle();
      }, "function"),
      active: /* @__PURE__ */ __name(() => useHelpCenterStore().isVisible, "active")
    },
    {
      id: "Comfy.ToggleCanvasInfo",
      icon: "pi pi-info-circle",
      label: "Canvas Performance",
      function: /* @__PURE__ */ __name(async () => {
        const settingStore = useSettingStore();
        const currentValue = settingStore.get("Comfy.Graph.CanvasInfo");
        await settingStore.set("Comfy.Graph.CanvasInfo", !currentValue);
      }, "function"),
      active: /* @__PURE__ */ __name(() => useSettingStore().get("Comfy.Graph.CanvasInfo"), "active")
    },
    {
      id: "Workspace.ToggleBottomPanel.Shortcuts",
      icon: "pi pi-key",
      label: "Show Keybindings Dialog",
      versionAdded: "1.24.1",
      category: "view-controls",
      function: /* @__PURE__ */ __name(() => {
        bottomPanelStore.togglePanel("shortcuts");
      }, "function")
    },
    {
      id: "Comfy.Graph.ExitSubgraph",
      icon: "pi pi-arrow-up",
      label: "Exit Subgraph",
      versionAdded: "1.20.1",
      function: /* @__PURE__ */ __name(() => {
        const canvas = useCanvasStore().getCanvas();
        const navigationStore = useSubgraphNavigationStore();
        if (!canvas.graph) return;
        canvas.setGraph(
          navigationStore.navigationStack.at(-2) ?? canvas.graph.rootGraph
        );
      }, "function")
    },
    {
      id: "Comfy.Dev.ShowModelSelector",
      icon: "pi pi-box",
      label: "Show Model Selector (Dev)",
      versionAdded: "1.26.2",
      category: "view-controls",
      function: /* @__PURE__ */ __name(() => {
        const modelSelectorDialog = useModelSelectorDialog();
        modelSelectorDialog.show();
      }, "function")
    },
    {
      id: "Comfy.Manager.CustomNodesManager.ShowLegacyCustomNodesMenu",
      icon: "pi pi-bars",
      label: "Custom Nodes (Legacy)",
      versionAdded: "1.16.4",
      function: /* @__PURE__ */ __name(async () => {
        try {
          await useCommandStore().execute(
            "Comfy.Manager.CustomNodesManager.ToggleVisibility"
          );
        } catch (error) {
          useToastStore().add({
            severity: "error",
            summary: t("g.error"),
            detail: t("manager.legacyMenuNotAvailable"),
            life: 3e3
          });
        }
      }, "function")
    },
    {
      id: "Comfy.Manager.ShowLegacyManagerMenu",
      icon: "mdi mdi-puzzle",
      label: "Manager Menu (Legacy)",
      versionAdded: "1.16.4",
      function: /* @__PURE__ */ __name(async () => {
        try {
          await useCommandStore().execute("Comfy.Manager.Menu.ToggleVisibility");
        } catch (error) {
          useToastStore().add({
            severity: "error",
            summary: t("g.error"),
            detail: t("manager.legacyMenuNotAvailable"),
            life: 3e3
          });
        }
      }, "function")
    },
    {
      id: "Comfy.Memory.UnloadModels",
      icon: "mdi mdi-vacuum-outline",
      label: "Unload Models",
      versionAdded: "1.16.4",
      function: /* @__PURE__ */ __name(async () => {
        if (!useSettingStore().get("Comfy.Memory.AllowManualUnload")) {
          useToastStore().add({
            severity: "error",
            summary: t("g.error"),
            detail: t("g.commandProhibited", {
              command: "Comfy.Memory.UnloadModels"
            }),
            life: 3e3
          });
          return;
        }
        await api.freeMemory({ freeExecutionCache: false });
      }, "function")
    },
    {
      id: "Comfy.Memory.UnloadModelsAndExecutionCache",
      icon: "mdi mdi-vacuum-outline",
      label: "Unload Models and Execution Cache",
      versionAdded: "1.16.4",
      function: /* @__PURE__ */ __name(async () => {
        if (!useSettingStore().get("Comfy.Memory.AllowManualUnload")) {
          useToastStore().add({
            severity: "error",
            summary: t("g.error"),
            detail: t("g.commandProhibited", {
              command: "Comfy.Memory.UnloadModelsAndExecutionCache"
            }),
            life: 3e3
          });
          return;
        }
        await api.freeMemory({ freeExecutionCache: true });
      }, "function")
    }
  ];
  return commands.map((command) => ({ ...command, source: "System" }));
}
__name(useCoreCommands, "useCoreCommands");
const DISMISSAL_DURATION_MS = 7 * 24 * 60 * 60 * 1e3;
const useVersionCompatibilityStore = defineStore(
  "versionCompatibility",
  () => {
    const systemStatsStore = useSystemStatsStore();
    const frontendVersion = computed(() => config.app_version);
    const backendVersion = computed(
      () => systemStatsStore.systemStats?.system?.comfyui_version ?? ""
    );
    const requiredFrontendVersion = computed(
      () => systemStatsStore.systemStats?.system?.required_frontend_version ?? ""
    );
    const isFrontendOutdated = computed(() => {
      if (!frontendVersion.value || !requiredFrontendVersion.value || !semver.valid(frontendVersion.value) || !semver.valid(requiredFrontendVersion.value)) {
        return false;
      }
      return semver.gt(requiredFrontendVersion.value, frontendVersion.value);
    });
    const isFrontendNewer = computed(() => {
      return false;
    });
    const hasVersionMismatch = computed(() => {
      return isFrontendOutdated.value;
    });
    const versionKey = computed(() => {
      if (!frontendVersion.value || !backendVersion.value || !requiredFrontendVersion.value) {
        return null;
      }
      return `${frontendVersion.value}-${backendVersion.value}-${requiredFrontendVersion.value}`;
    });
    const dismissalStorage = useStorage(
      "comfy.versionMismatch.dismissals",
      {},
      localStorage,
      {
        serializer: {
          read: /* @__PURE__ */ __name((value) => {
            try {
              return JSON.parse(value);
            } catch {
              return {};
            }
          }, "read"),
          write: /* @__PURE__ */ __name((value) => JSON.stringify(value), "write")
        }
      }
    );
    const isDismissed = computed(() => {
      if (!versionKey.value) return false;
      const dismissedUntil = dismissalStorage.value[versionKey.value];
      if (!dismissedUntil) return false;
      return Date.now() < dismissedUntil;
    });
    const shouldShowWarning = computed(() => {
      return hasVersionMismatch.value && !isDismissed.value;
    });
    const warningMessage = computed(() => {
      if (isFrontendOutdated.value) {
        return {
          type: "outdated",
          frontendVersion: frontendVersion.value,
          requiredVersion: requiredFrontendVersion.value
        };
      }
      return null;
    });
    async function checkVersionCompatibility() {
      if (!systemStatsStore.systemStats) {
        await systemStatsStore.fetchSystemStats();
      }
    }
    __name(checkVersionCompatibility, "checkVersionCompatibility");
    function dismissWarning() {
      if (!versionKey.value) return;
      const dismissUntil = Date.now() + DISMISSAL_DURATION_MS;
      dismissalStorage.value = {
        ...dismissalStorage.value,
        [versionKey.value]: dismissUntil
      };
    }
    __name(dismissWarning, "dismissWarning");
    async function initialize() {
      await checkVersionCompatibility();
    }
    __name(initialize, "initialize");
    return {
      frontendVersion,
      backendVersion,
      requiredFrontendVersion,
      hasVersionMismatch,
      shouldShowWarning,
      warningMessage,
      isFrontendOutdated,
      isFrontendNewer,
      checkVersionCompatibility,
      dismissWarning,
      initialize
    };
  }
);
function useFrontendVersionMismatchWarning(options = {}) {
  const { immediate = false } = options;
  const { t: t2 } = useI18n();
  const toastStore = useToastStore();
  const versionCompatibilityStore = useVersionCompatibilityStore();
  let hasShownWarning = false;
  const showWarning = /* @__PURE__ */ __name(() => {
    if (hasShownWarning) return;
    const message = versionCompatibilityStore.warningMessage;
    if (!message) return;
    const detailMessage = t2("g.frontendOutdated", {
      frontendVersion: message.frontendVersion,
      requiredVersion: message.requiredVersion
    });
    const fullMessage = t2("g.versionMismatchWarningMessage", {
      warning: t2("g.versionMismatchWarning"),
      detail: detailMessage
    });
    toastStore.addAlert(fullMessage);
    hasShownWarning = true;
    versionCompatibilityStore.dismissWarning();
  }, "showWarning");
  onMounted(() => {
    if (immediate) {
      whenever(
        () => versionCompatibilityStore.shouldShowWarning,
        () => {
          showWarning();
        },
        {
          immediate: true,
          once: true
        }
      );
    }
  });
  return {
    showWarning,
    shouldShowWarning: computed(
      () => versionCompatibilityStore.shouldShowWarning
    ),
    dismissWarning: versionCompatibilityStore.dismissWarning,
    hasVersionMismatch: computed(
      () => versionCompatibilityStore.hasVersionMismatch
    )
  };
}
__name(useFrontendVersionMismatchWarning, "useFrontendVersionMismatchWarning");
const useProgressFavicon = /* @__PURE__ */ __name(() => {
  const defaultFavicon = "/assets/images/favicon_progress_16x16/frame_9.png";
  const favicon = useFavicon(defaultFavicon);
  const executionStore = useExecutionStore();
  const totalFrames = 10;
  watch(
    [() => executionStore.executionProgress, () => executionStore.isIdle],
    ([progress, isIdle]) => {
      if (isIdle) {
        favicon.value = defaultFavicon;
      } else {
        const frame = Math.min(
          Math.max(0, Math.floor(progress * totalFrames)),
          totalFrames - 1
        );
        favicon.value = `/assets/images/favicon_progress_16x16/frame_${frame}.png`;
      }
    }
  );
}, "useProgressFavicon");
var LatentPreviewMethod = /* @__PURE__ */ ((LatentPreviewMethod2) => {
  LatentPreviewMethod2["NoPreviews"] = "none";
  LatentPreviewMethod2["Auto"] = "auto";
  LatentPreviewMethod2["Latent2RGB"] = "latent2rgb";
  LatentPreviewMethod2["TAESD"] = "taesd";
  return LatentPreviewMethod2;
})(LatentPreviewMethod || {});
var LogLevel = /* @__PURE__ */ ((LogLevel2) => {
  LogLevel2["DEBUG"] = "DEBUG";
  LogLevel2["INFO"] = "INFO";
  LogLevel2["WARNING"] = "WARNING";
  LogLevel2["ERROR"] = "ERROR";
  LogLevel2["CRITICAL"] = "CRITICAL";
  return LogLevel2;
})(LogLevel || {});
var HashFunction = /* @__PURE__ */ ((HashFunction2) => {
  HashFunction2["MD5"] = "md5";
  HashFunction2["SHA1"] = "sha1";
  HashFunction2["SHA256"] = "sha256";
  HashFunction2["SHA512"] = "sha512";
  return HashFunction2;
})(HashFunction || {});
var CudaMalloc = /* @__PURE__ */ ((CudaMalloc2) => {
  CudaMalloc2["Auto"] = "auto";
  CudaMalloc2["Disable"] = "disable";
  CudaMalloc2["Enable"] = "enable";
  return CudaMalloc2;
})(CudaMalloc || {});
var FloatingPointPrecision = /* @__PURE__ */ ((FloatingPointPrecision2) => {
  FloatingPointPrecision2["AUTO"] = "auto";
  FloatingPointPrecision2["FP64"] = "fp64";
  FloatingPointPrecision2["FP32"] = "fp32";
  FloatingPointPrecision2["FP16"] = "fp16";
  FloatingPointPrecision2["BF16"] = "bf16";
  FloatingPointPrecision2["FP8E4M3FN"] = "fp8_e4m3fn";
  FloatingPointPrecision2["FP8E5M2"] = "fp8_e5m2";
  return FloatingPointPrecision2;
})(FloatingPointPrecision || {});
var CrossAttentionMethod = /* @__PURE__ */ ((CrossAttentionMethod2) => {
  CrossAttentionMethod2["Auto"] = "auto";
  CrossAttentionMethod2["Split"] = "split";
  CrossAttentionMethod2["Quad"] = "quad";
  CrossAttentionMethod2["Pytorch"] = "pytorch";
  return CrossAttentionMethod2;
})(CrossAttentionMethod || {});
var VramManagement = /* @__PURE__ */ ((VramManagement2) => {
  VramManagement2["Auto"] = "auto";
  VramManagement2["GPUOnly"] = "gpu-only";
  VramManagement2["HighVram"] = "highvram";
  VramManagement2["NormalVram"] = "normalvram";
  VramManagement2["LowVram"] = "lowvram";
  VramManagement2["NoVram"] = "novram";
  VramManagement2["CPU"] = "cpu";
  return VramManagement2;
})(VramManagement || {});
const SERVER_CONFIG_ITEMS = [
  // Network settings
  {
    id: "listen",
    name: "Host: The IP address to listen on",
    category: ["Network"],
    type: "text",
    defaultValue: "127.0.0.1"
  },
  {
    id: "port",
    name: "Port: The port to listen on",
    category: ["Network"],
    type: "number",
    // The default launch port for desktop app is 8000 instead of 8188.
    defaultValue: 8e3
  },
  {
    id: "tls-keyfile",
    name: "TLS Key File: Path to TLS key file for HTTPS",
    category: ["Network"],
    type: "text",
    defaultValue: ""
  },
  {
    id: "tls-certfile",
    name: "TLS Certificate File: Path to TLS certificate file for HTTPS",
    category: ["Network"],
    type: "text",
    defaultValue: ""
  },
  {
    id: "enable-cors-header",
    name: 'Enable CORS header: Use "*" for all origins or specify domain',
    category: ["Network"],
    type: "text",
    defaultValue: ""
  },
  {
    id: "max-upload-size",
    name: "Maximum upload size (MB)",
    category: ["Network"],
    type: "number",
    defaultValue: 100
  },
  // CUDA settings
  {
    id: "cuda-device",
    name: "CUDA device index to use",
    category: ["CUDA"],
    type: "number",
    defaultValue: null
  },
  {
    id: "cuda-malloc",
    name: "Use CUDA malloc for memory allocation",
    category: ["CUDA"],
    type: "combo",
    options: Object.values(CudaMalloc),
    defaultValue: CudaMalloc.Auto,
    getValue: /* @__PURE__ */ __name((value) => {
      switch (value) {
        case CudaMalloc.Auto:
          return {};
        case CudaMalloc.Enable:
          return {
            ["cuda-malloc"]: true
          };
        case CudaMalloc.Disable:
          return {
            ["disable-cuda-malloc"]: true
          };
      }
    }, "getValue")
  },
  // Precision settings
  {
    id: "global-precision",
    name: "Global floating point precision",
    category: ["Inference"],
    type: "combo",
    options: [
      FloatingPointPrecision.AUTO,
      FloatingPointPrecision.FP32,
      FloatingPointPrecision.FP16
    ],
    defaultValue: FloatingPointPrecision.AUTO,
    tooltip: "Global floating point precision",
    getValue: /* @__PURE__ */ __name((value) => {
      switch (value) {
        case FloatingPointPrecision.AUTO:
          return {};
        case FloatingPointPrecision.FP32:
          return {
            ["force-fp32"]: true
          };
        case FloatingPointPrecision.FP16:
          return {
            ["force-fp16"]: true
          };
        default:
          return {};
      }
    }, "getValue")
  },
  // UNET precision
  {
    id: "unet-precision",
    name: "UNET precision",
    category: ["Inference"],
    type: "combo",
    options: [
      FloatingPointPrecision.AUTO,
      FloatingPointPrecision.FP64,
      FloatingPointPrecision.FP32,
      FloatingPointPrecision.FP16,
      FloatingPointPrecision.BF16,
      FloatingPointPrecision.FP8E4M3FN,
      FloatingPointPrecision.FP8E5M2
    ],
    defaultValue: FloatingPointPrecision.AUTO,
    tooltip: "UNET precision",
    getValue: /* @__PURE__ */ __name((value) => {
      switch (value) {
        case FloatingPointPrecision.AUTO:
          return {};
        default:
          return {
            [`${value.toLowerCase()}-unet`]: true
          };
      }
    }, "getValue")
  },
  // VAE settings
  {
    id: "vae-precision",
    name: "VAE precision",
    category: ["Inference"],
    type: "combo",
    options: [
      FloatingPointPrecision.AUTO,
      FloatingPointPrecision.FP16,
      FloatingPointPrecision.FP32,
      FloatingPointPrecision.BF16
    ],
    defaultValue: FloatingPointPrecision.AUTO,
    tooltip: "VAE precision",
    getValue: /* @__PURE__ */ __name((value) => {
      switch (value) {
        case FloatingPointPrecision.AUTO:
          return {};
        default:
          return {
            [`${value.toLowerCase()}-vae`]: true
          };
      }
    }, "getValue")
  },
  {
    id: "cpu-vae",
    name: "Run VAE on CPU",
    category: ["Inference"],
    type: "boolean",
    defaultValue: false
  },
  // Text Encoder settings
  {
    id: "text-encoder-precision",
    name: "Text Encoder precision",
    category: ["Inference"],
    type: "combo",
    options: [
      FloatingPointPrecision.AUTO,
      FloatingPointPrecision.FP8E4M3FN,
      FloatingPointPrecision.FP8E5M2,
      FloatingPointPrecision.FP16,
      FloatingPointPrecision.FP32
    ],
    defaultValue: FloatingPointPrecision.AUTO,
    tooltip: "Text Encoder precision",
    getValue: /* @__PURE__ */ __name((value) => {
      switch (value) {
        case FloatingPointPrecision.AUTO:
          return {};
        default:
          return {
            [`${value.toLowerCase()}-text-enc`]: true
          };
      }
    }, "getValue")
  },
  // Memory and performance settings
  {
    id: "force-channels-last",
    name: "Force channels-last memory format",
    category: ["Memory"],
    type: "boolean",
    defaultValue: false
  },
  {
    id: "directml",
    name: "DirectML device index",
    category: ["Memory"],
    type: "number",
    defaultValue: null
  },
  {
    id: "disable-ipex-optimize",
    name: "Disable IPEX optimization",
    category: ["Memory"],
    type: "boolean",
    defaultValue: false
  },
  // Preview settings
  {
    id: "preview-method",
    name: "Method used for latent previews",
    category: ["Preview"],
    type: "combo",
    options: Object.values(LatentPreviewMethod),
    defaultValue: LatentPreviewMethod.NoPreviews
  },
  {
    id: "preview-size",
    name: "Size of preview images",
    category: ["Preview"],
    type: "slider",
    defaultValue: 512,
    attrs: {
      min: 128,
      max: 2048,
      step: 128
    }
  },
  // Cache settings
  {
    id: "cache-classic",
    name: "Use classic cache system",
    category: ["Cache"],
    type: "boolean",
    defaultValue: false
  },
  {
    id: "cache-lru",
    name: "Use LRU caching with a maximum of N node results cached.",
    category: ["Cache"],
    type: "number",
    defaultValue: null,
    tooltip: "May use more RAM/VRAM."
  },
  // Attention settings
  {
    id: "cross-attention-method",
    name: "Cross attention method",
    category: ["Attention"],
    type: "combo",
    options: Object.values(CrossAttentionMethod),
    defaultValue: CrossAttentionMethod.Auto,
    getValue: /* @__PURE__ */ __name((value) => {
      switch (value) {
        case CrossAttentionMethod.Auto:
          return {};
        default:
          return {
            [`use-${value.toLowerCase()}-cross-attention`]: true
          };
      }
    }, "getValue")
  },
  {
    id: "disable-xformers",
    name: "Disable xFormers optimization",
    type: "boolean",
    defaultValue: false
  },
  {
    id: "force-upcast-attention",
    name: "Force attention upcast",
    category: ["Attention"],
    type: "boolean",
    defaultValue: false
  },
  {
    id: "dont-upcast-attention",
    name: "Prevent attention upcast",
    category: ["Attention"],
    type: "boolean",
    defaultValue: false
  },
  // VRAM management
  {
    id: "vram-management",
    name: "VRAM management mode",
    category: ["Memory"],
    type: "combo",
    options: Object.values(VramManagement),
    defaultValue: VramManagement.Auto,
    getValue: /* @__PURE__ */ __name((value) => {
      switch (value) {
        case VramManagement.Auto:
          return {};
        default:
          return {
            [value]: true
          };
      }
    }, "getValue")
  },
  {
    id: "reserve-vram",
    name: "Reserved VRAM (GB)",
    category: ["Memory"],
    type: "number",
    defaultValue: null,
    tooltip: "Set the amount of vram in GB you want to reserve for use by your OS/other software. By default some amount is reverved depending on your OS."
  },
  // Misc settings
  {
    id: "default-hashing-function",
    name: "Default hashing function for model files",
    type: "combo",
    options: Object.values(HashFunction),
    defaultValue: HashFunction.SHA256
  },
  {
    id: "disable-smart-memory",
    name: "Disable smart memory management",
    tooltip: "Force ComfyUI to aggressively offload to regular ram instead of keeping models in vram when it can.",
    category: ["Memory"],
    type: "boolean",
    defaultValue: false
  },
  {
    id: "deterministic",
    name: "Make pytorch use slower deterministic algorithms when it can.",
    type: "boolean",
    defaultValue: false,
    tooltip: "Note that this might not make images deterministic in all cases."
  },
  {
    id: "fast",
    name: "Enable some untested and potentially quality deteriorating optimizations.",
    type: "boolean",
    defaultValue: false
  },
  {
    id: "dont-print-server",
    name: "Don't print server output to console.",
    type: "boolean",
    defaultValue: false
  },
  {
    id: "disable-metadata",
    name: "Disable saving prompt metadata in files.",
    type: "boolean",
    defaultValue: false
  },
  {
    id: "disable-all-custom-nodes",
    name: "Disable loading all custom nodes.",
    type: "boolean",
    defaultValue: false
  },
  {
    id: "log-level",
    name: "Logging verbosity level",
    type: "combo",
    options: Object.values(LogLevel),
    defaultValue: LogLevel.INFO,
    getValue: /* @__PURE__ */ __name((value) => {
      return {
        verbose: value
      };
    }, "getValue")
  },
  // Directories
  {
    id: "input-directory",
    name: "Input directory",
    category: ["Directories"],
    type: "text",
    defaultValue: ""
  },
  {
    id: "output-directory",
    name: "Output directory",
    category: ["Directories"],
    type: "text",
    defaultValue: ""
  }
];
function setupAutoQueueHandler() {
  const queueCountStore = useQueuePendingTaskCountStore();
  const queueSettingsStore = useQueueSettingsStore();
  let graphHasChanged = false;
  let internalCount = 0;
  api.addEventListener("graphChanged", () => {
    if (queueSettingsStore.mode === "change") {
      if (internalCount) {
        graphHasChanged = true;
      } else {
        graphHasChanged = false;
        void app.queuePrompt(0, queueSettingsStore.batchCount);
        internalCount++;
      }
    }
  });
  queueCountStore.$subscribe(
    async () => {
      internalCount = queueCountStore.count;
      if (!internalCount && !app.lastExecutionError) {
        if (queueSettingsStore.mode === "instant" || queueSettingsStore.mode === "change" && graphHasChanged) {
          graphHasChanged = false;
          await app.queuePrompt(0, queueSettingsStore.batchCount);
        }
      }
    },
    { detached: true }
  );
}
__name(setupAutoQueueHandler, "setupAutoQueueHandler");
const _hoisted_1 = { class: "comfyui-body grid h-full w-full overflow-hidden" };
const _hoisted_2 = {
  id: "comfyui-body-top",
  class: "comfyui-body-top"
};
const _hoisted_3 = {
  id: "comfyui-body-bottom",
  class: "comfyui-body-bottom"
};
const _hoisted_4 = {
  id: "graph-canvas-container",
  class: "graph-canvas-container"
};
const _sfc_main = /* @__PURE__ */ defineComponent({
  __name: "GraphView",
  setup(__props) {
    setupAutoQueueHandler();
    useProgressFavicon();
    useBrowserTabTitle();
    const { t: t2 } = useI18n();
    const toast = useToast();
    const settingStore = useSettingStore();
    const executionStore = useExecutionStore();
    const colorPaletteStore = useColorPaletteStore();
    const queueStore = useQueueStore();
    const versionCompatibilityStore = useVersionCompatibilityStore();
    const breakpoints = useBreakpoints({ md: 961 });
    const isMobile = breakpoints.smaller("md");
    const showTopMenu = computed(() => isMobile.value || useNewMenu.value === "Top");
    const showBottomMenu = computed(
      () => !isMobile.value && useNewMenu.value === "Bottom"
    );
    watch(
      () => colorPaletteStore.completedActivePalette,
      (newTheme) => {
        const DARK_THEME_CLASS = "dark-theme";
        if (newTheme.light_theme) {
          document.body.classList.remove(DARK_THEME_CLASS);
        } else {
          document.body.classList.add(DARK_THEME_CLASS);
        }
        if (isElectron()) {
          electronAPI().changeTheme({
            color: "rgba(0, 0, 0, 0)",
            symbolColor: newTheme.colors.comfy_base["input-text"]
          });
        }
      },
      { immediate: true }
    );
    if (isElectron()) {
      watch(
        () => queueStore.tasks,
        (newTasks, oldTasks) => {
          const oldRunningTaskIds = new Set(
            oldTasks.filter((task) => task.isRunning).map((task) => task.promptId)
          );
          newTasks.filter(
            (task) => oldRunningTaskIds.has(task.promptId) && task.isHistory
          ).forEach((task) => {
            electronAPI().Events.incrementUserProperty(
              `execution:${task.displayStatus.toLowerCase()}`,
              1
            );
            electronAPI().Events.trackEvent("execution", {
              status: task.displayStatus.toLowerCase()
            });
          });
        },
        { deep: true }
      );
    }
    watchEffect(() => {
      const fontSize = settingStore.get("Comfy.TextareaWidget.FontSize");
      document.documentElement.style.setProperty(
        "--comfy-textarea-font-size",
        `${fontSize}px`
      );
    });
    watchEffect(() => {
      const padding = settingStore.get("Comfy.TreeExplorer.ItemPadding");
      document.documentElement.style.setProperty(
        "--comfy-tree-explorer-item-padding",
        `${padding}px`
      );
    });
    watchEffect(() => {
      const locale = settingStore.get("Comfy.Locale");
      if (locale) {
        i18n.global.locale.value = locale;
      }
    });
    const useNewMenu = computed(() => {
      return settingStore.get("Comfy.UseNewMenu");
    });
    watchEffect(() => {
      if (useNewMenu.value === "Disabled") {
        app.ui.menuContainer.style.setProperty("display", "block");
        app.ui.restoreMenuPosition();
      } else {
        app.ui.menuContainer.style.setProperty("display", "none");
      }
    });
    watchEffect(() => {
      queueStore.maxHistoryItems = settingStore.get("Comfy.Queue.MaxHistoryItems");
    });
    const init = /* @__PURE__ */ __name(() => {
      const coreCommands = useCoreCommands();
      useCommandStore().registerCommands(coreCommands);
      useMenuItemStore().registerCoreMenuCommands();
      useKeybindingService().registerCoreKeybindings();
      useSidebarTabStore().registerCoreSidebarTabs();
      useBottomPanelStore().registerCoreBottomPanelTabs();
      app.extensionManager = useWorkspaceStore();
    }, "init");
    const queuePendingTaskCountStore = useQueuePendingTaskCountStore();
    const onStatus = /* @__PURE__ */ __name(async (e) => {
      queuePendingTaskCountStore.update(e);
      await queueStore.update();
    }, "onStatus");
    const onExecutionSuccess = /* @__PURE__ */ __name(async () => {
      await queueStore.update();
    }, "onExecutionSuccess");
    const reconnectingMessage = {
      severity: "error",
      summary: t2("g.reconnecting")
    };
    const onReconnecting = /* @__PURE__ */ __name(() => {
      if (!settingStore.get("Comfy.Toast.DisableReconnectingToast")) {
        toast.remove(reconnectingMessage);
        toast.add(reconnectingMessage);
      }
    }, "onReconnecting");
    const onReconnected = /* @__PURE__ */ __name(() => {
      if (!settingStore.get("Comfy.Toast.DisableReconnectingToast")) {
        toast.remove(reconnectingMessage);
        toast.add({
          severity: "success",
          summary: t2("g.reconnected"),
          life: 2e3
        });
      }
    }, "onReconnected");
    onMounted(() => {
      api.addEventListener("status", onStatus);
      api.addEventListener("execution_success", onExecutionSuccess);
      api.addEventListener("reconnecting", onReconnecting);
      api.addEventListener("reconnected", onReconnected);
      executionStore.bindExecutionEvents();
      try {
        init();
      } catch (e) {
        console.error("Failed to init ComfyUI frontend", e);
      }
    });
    onBeforeUnmount(() => {
      api.removeEventListener("status", onStatus);
      api.removeEventListener("execution_success", onExecutionSuccess);
      api.removeEventListener("reconnecting", onReconnecting);
      api.removeEventListener("reconnected", onReconnected);
      executionStore.unbindExecutionEvents();
    });
    useEventListener(window, "keydown", useKeybindingService().keybindHandler);
    const { wrapWithErrorHandling, wrapWithErrorHandlingAsync } = useErrorHandling();
    useFrontendVersionMismatchWarning({ immediate: true });
    void nextTick(() => {
      versionCompatibilityStore.initialize().catch((error) => {
        console.warn("Version compatibility check failed:", error);
      });
    });
    const onGraphReady = /* @__PURE__ */ __name(() => {
      requestIdleCallback(
        () => {
          wrapWithErrorHandling(useKeybindingService().registerUserKeybindings)();
          wrapWithErrorHandling(useServerConfigStore().loadServerConfig)(
            SERVER_CONFIG_ITEMS,
            settingStore.get("Comfy.Server.ServerConfigValues")
          );
          void wrapWithErrorHandlingAsync(useModelStore().loadModelFolders)();
          void wrapWithErrorHandlingAsync(
            useNodeFrequencyStore().loadNodeFrequencies
          )();
          useNodeDefStore().nodeSearchService.searchNode("");
        },
        { timeout: 1e3 }
      );
    }, "onGraphReady");
    return (_ctx, _cache) => {
      return openBlock(), createElementBlock(Fragment, null, [
        createElementVNode("div", _hoisted_1, [
          createElementVNode("div", _hoisted_2, [
            showTopMenu.value ? (openBlock(), createBlock(TopMenubar, { key: 0 })) : createCommentVNode("", true)
          ]),
          createElementVNode("div", _hoisted_3, [
            showBottomMenu.value ? (openBlock(), createBlock(TopMenubar, { key: 0 })) : createCommentVNode("", true)
          ]),
          _cache[0] || (_cache[0] = createElementVNode("div", {
            id: "comfyui-body-left",
            class: "comfyui-body-left"
          }, null, -1)),
          _cache[1] || (_cache[1] = createElementVNode("div", {
            id: "comfyui-body-right",
            class: "comfyui-body-right"
          }, null, -1)),
          createElementVNode("div", _hoisted_4, [
            createVNode(_sfc_main$t, { onReady: onGraphReady })
          ])
        ]),
        createVNode(_sfc_main$s),
        createVNode(_sfc_main$r),
        !unref(isElectron)() ? (openBlock(), createBlock(_sfc_main$1z, { key: 0 })) : createCommentVNode("", true),
        createVNode(MenuHamburger)
      ], 64);
    };
  }
});
const GraphView = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-d25259c0"]]);
export {
  GraphView as default
};
//# sourceMappingURL=GraphView-K2pKe74w.js.map
