mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-06-28 05:31:16 -03:00
Compare commits
6 Commits
v1.0.11
...
dd5b213adc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dd5b213adc | ||
|
|
d9ee9b3155 | ||
|
|
01dac57c35 | ||
|
|
7f92d09239 | ||
|
|
62f9e3f44a | ||
|
|
e55895786d |
@@ -81,7 +81,7 @@ def read_safetensors_metadata(file_path: str) -> dict[str, Any]:
|
|||||||
return {}
|
return {}
|
||||||
header = json.loads(header_bytes.decode("utf-8"))
|
header = json.loads(header_bytes.decode("utf-8"))
|
||||||
return header.get("__metadata__", {})
|
return header.get("__metadata__", {})
|
||||||
except (OSError, json.JSONDecodeError, UnicodeDecodeError, struct.error):
|
except (OSError, json.JSONDecodeError, UnicodeDecodeError, struct.error, MemoryError, Exception):
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ import sys
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
|
from platformdirs import user_config_dir
|
||||||
|
|
||||||
logging.basicConfig(
|
logging.basicConfig(
|
||||||
level=logging.INFO,
|
level=logging.INFO,
|
||||||
format="%(asctime)s - %(levelname)s - %(message)s",
|
format="%(asctime)s - %(levelname)s - %(message)s",
|
||||||
@@ -53,10 +55,7 @@ def resolve_settings_path() -> Path:
|
|||||||
if isinstance(payload, dict) and payload.get("use_portable_settings") is True:
|
if isinstance(payload, dict) and payload.get("use_portable_settings") is True:
|
||||||
return portable
|
return portable
|
||||||
|
|
||||||
config_home = os.environ.get("XDG_CONFIG_HOME")
|
return Path(user_config_dir(APP_NAME, appauthor=False)) / "settings.json"
|
||||||
if config_home:
|
|
||||||
return Path(config_home).expanduser() / APP_NAME / "settings.json"
|
|
||||||
return Path.home() / ".config" / APP_NAME / "settings.json"
|
|
||||||
|
|
||||||
|
|
||||||
def load_json(path: Path) -> dict[str, Any]:
|
def load_json(path: Path) -> dict[str, Any]:
|
||||||
|
|||||||
@@ -39,6 +39,8 @@ import sys
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
|
from platformdirs import user_config_dir
|
||||||
|
|
||||||
logging.basicConfig(
|
logging.basicConfig(
|
||||||
level=logging.INFO,
|
level=logging.INFO,
|
||||||
format="%(message)s",
|
format="%(message)s",
|
||||||
@@ -68,10 +70,7 @@ def resolve_settings_path() -> Path:
|
|||||||
if isinstance(payload, dict) and payload.get("use_portable_settings") is True:
|
if isinstance(payload, dict) and payload.get("use_portable_settings") is True:
|
||||||
return portable
|
return portable
|
||||||
|
|
||||||
config_home = os.environ.get("XDG_CONFIG_HOME")
|
return Path(user_config_dir(APP_NAME, appauthor=False)) / "settings.json"
|
||||||
if config_home:
|
|
||||||
return Path(config_home).expanduser() / APP_NAME / "settings.json"
|
|
||||||
return Path.home() / ".config" / APP_NAME / "settings.json"
|
|
||||||
|
|
||||||
|
|
||||||
def _load_json(path: Path) -> dict[str, Any]:
|
def _load_json(path: Path) -> dict[str, Any]:
|
||||||
|
|||||||
@@ -5,7 +5,8 @@
|
|||||||
ref="textareaRef"
|
ref="textareaRef"
|
||||||
:placeholder="placeholder"
|
:placeholder="placeholder"
|
||||||
:spellcheck="spellcheck ?? false"
|
:spellcheck="spellcheck ?? false"
|
||||||
:class="['text-input', { 'vue-dom-mode': isVueDomMode }]"
|
:class="['text-input', { 'vue-dom-mode': isVueDomMode, 'lm-wheel-scrollable': isVueDomMode }]"
|
||||||
|
:style="maxHeight && isVueDomMode ? { maxHeight: maxHeight + 'px' } : undefined"
|
||||||
@input="onInput"
|
@input="onInput"
|
||||||
@wheel="onWheel"
|
@wheel="onWheel"
|
||||||
/>
|
/>
|
||||||
@@ -47,6 +48,7 @@ const props = defineProps<{
|
|||||||
placeholder?: string
|
placeholder?: string
|
||||||
showPreview?: boolean
|
showPreview?: boolean
|
||||||
spellcheck?: boolean
|
spellcheck?: boolean
|
||||||
|
maxHeight?: number
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
// Reactive ref for Vue DOM mode
|
// Reactive ref for Vue DOM mode
|
||||||
|
|||||||
@@ -655,13 +655,16 @@ function createAutocompleteTextWidgetFactory(
|
|||||||
// Get spellcheck setting from ComfyUI settings (default: false)
|
// Get spellcheck setting from ComfyUI settings (default: false)
|
||||||
const spellcheck = app.ui?.settings?.getSettingValue?.('Comfy.TextareaWidget.Spellcheck') ?? false
|
const spellcheck = app.ui?.settings?.getSettingValue?.('Comfy.TextareaWidget.Spellcheck') ?? false
|
||||||
|
|
||||||
|
const maxHeight = modelType === 'loras' ? AUTOCOMPLETE_TEXT_WIDGET_MAX_HEIGHT : undefined
|
||||||
|
|
||||||
const vueApp = createApp(AutocompleteTextWidget, {
|
const vueApp = createApp(AutocompleteTextWidget, {
|
||||||
widget,
|
widget,
|
||||||
node,
|
node,
|
||||||
modelType,
|
modelType,
|
||||||
placeholder: inputOptions.placeholder || widgetName,
|
placeholder: inputOptions.placeholder || widgetName,
|
||||||
showPreview: true,
|
showPreview: true,
|
||||||
spellcheck
|
spellcheck,
|
||||||
|
maxHeight
|
||||||
})
|
})
|
||||||
|
|
||||||
vueApp.use(PrimeVue, {
|
vueApp.use(PrimeVue, {
|
||||||
@@ -673,6 +676,10 @@ function createAutocompleteTextWidgetFactory(
|
|||||||
const appKey = instanceId
|
const appKey = instanceId
|
||||||
vueApps.set(appKey, vueApp)
|
vueApps.set(appKey, vueApp)
|
||||||
|
|
||||||
|
if (maxHeight) {
|
||||||
|
container.style.maxHeight = `${maxHeight}px`
|
||||||
|
}
|
||||||
|
|
||||||
widget.onRemove = createVueWidgetCleanup(vueApp, () => {
|
widget.onRemove = createVueWidgetCleanup(vueApp, () => {
|
||||||
vueApps.delete(appKey)
|
vueApps.delete(appKey)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import {
|
|||||||
EMPTY_CONTAINER_HEIGHT
|
EMPTY_CONTAINER_HEIGHT
|
||||||
} from "./loras_widget_utils.js";
|
} from "./loras_widget_utils.js";
|
||||||
import { initDrag, createContextMenu, initHeaderDrag, initReorderDrag, handleKeyboardNavigation } from "./loras_widget_events.js";
|
import { initDrag, createContextMenu, initHeaderDrag, initReorderDrag, handleKeyboardNavigation } from "./loras_widget_events.js";
|
||||||
import { forwardMiddleMouseToCanvas, forwardWheelToCanvas } from "./utils.js";
|
import { forwardMiddleMouseToCanvas, forwardWheelToCanvas, enableListWheelScroll } from "./utils.js";
|
||||||
import { PreviewTooltip } from "./preview_tooltip.js";
|
import { PreviewTooltip } from "./preview_tooltip.js";
|
||||||
import { ensureLmStyles } from "./lm_styles_loader.js";
|
import { ensureLmStyles } from "./lm_styles_loader.js";
|
||||||
import { getStrengthStepPreference } from "./settings.js";
|
import { getStrengthStepPreference } from "./settings.js";
|
||||||
@@ -24,11 +24,18 @@ export function addLorasWidget(node, name, opts, callback) {
|
|||||||
container.className = "lm-loras-container";
|
container.className = "lm-loras-container";
|
||||||
|
|
||||||
forwardMiddleMouseToCanvas(container);
|
forwardMiddleMouseToCanvas(container);
|
||||||
|
// Capture-phase handler: scroll the list with the wheel when it overflows.
|
||||||
|
// Falls through to forwardWheelToCanvas (canvas zoom) when the list is short.
|
||||||
|
enableListWheelScroll(container);
|
||||||
forwardWheelToCanvas(container);
|
forwardWheelToCanvas(container);
|
||||||
|
|
||||||
// Set initial height using CSS variables approach
|
// Set initial height using CSS variables approach
|
||||||
const defaultHeight = 200;
|
const defaultHeight = 200;
|
||||||
|
|
||||||
|
// Content height (capped at 12 rows by renderLoras), kept up to date and used
|
||||||
|
// to fix the widget/node height in both Canvas and Nodes 2.0 (Vue) modes.
|
||||||
|
let currentContentHeight = defaultHeight;
|
||||||
|
|
||||||
// Check if this is a randomizer node (lock button instead of drag handle)
|
// Check if this is a randomizer node (lock button instead of drag handle)
|
||||||
const isRandomizerNode = opts?.isRandomizerNode === true;
|
const isRandomizerNode = opts?.isRandomizerNode === true;
|
||||||
|
|
||||||
@@ -198,7 +205,7 @@ export function addLorasWidget(node, name, opts, callback) {
|
|||||||
container.appendChild(emptyMessage);
|
container.appendChild(emptyMessage);
|
||||||
|
|
||||||
// Set fixed height for empty state
|
// Set fixed height for empty state
|
||||||
updateWidgetHeight(container, EMPTY_CONTAINER_HEIGHT, defaultHeight, node);
|
currentContentHeight = updateWidgetHeight(container, EMPTY_CONTAINER_HEIGHT, defaultHeight, node);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -645,7 +652,7 @@ export function addLorasWidget(node, name, opts, callback) {
|
|||||||
|
|
||||||
// Calculate height based on number of loras and fixed sizes
|
// Calculate height based on number of loras and fixed sizes
|
||||||
const calculatedHeight = CONTAINER_PADDING + HEADER_HEIGHT + (Math.min(totalVisibleEntries, 12) * LORA_ENTRY_HEIGHT);
|
const calculatedHeight = CONTAINER_PADDING + HEADER_HEIGHT + (Math.min(totalVisibleEntries, 12) * LORA_ENTRY_HEIGHT);
|
||||||
updateWidgetHeight(container, calculatedHeight, defaultHeight, node);
|
currentContentHeight = updateWidgetHeight(container, calculatedHeight, defaultHeight, node);
|
||||||
|
|
||||||
// After all LoRA elements are created, apply selection state as the last step
|
// After all LoRA elements are created, apply selection state as the last step
|
||||||
// This ensures the selection state is not overwritten
|
// This ensures the selection state is not overwritten
|
||||||
@@ -727,12 +734,31 @@ export function addLorasWidget(node, name, opts, callback) {
|
|||||||
widgetValue = updatedValue;
|
widgetValue = updatedValue;
|
||||||
renderLoras(widgetValue, widget);
|
renderLoras(widgetValue, widget);
|
||||||
},
|
},
|
||||||
|
// The list area is capped at 12 rows (see calculatedHeight); beyond that the
|
||||||
|
// container scrolls. Report that capped height as both the min and preferred
|
||||||
|
// size so the node height stays fixed to the list, matching Canvas mode.
|
||||||
|
getMinHeight: () => currentContentHeight,
|
||||||
|
getHeight: () => currentContentHeight,
|
||||||
hideOnZoom: true,
|
hideOnZoom: true,
|
||||||
selectOn: ['click', 'focus']
|
selectOn: ['click', 'focus']
|
||||||
});
|
});
|
||||||
|
|
||||||
widget.value = defaultValue;
|
widget.value = defaultValue;
|
||||||
|
|
||||||
|
// Canonical LiteGraph sizing hook (Canvas mode): fix the widget to the capped
|
||||||
|
// content height. Rows beyond the 12-row cap scroll inside the container.
|
||||||
|
widget.computeSize = (width) => [width, currentContentHeight];
|
||||||
|
|
||||||
|
// Nodes 2.0 / Vue mode reads computeLayoutSize for the node's size. Pin both
|
||||||
|
// the min and max to the capped content height so the list area is fixed to
|
||||||
|
// 12 rows (scrolling beyond), matching Canvas mode, instead of the layout
|
||||||
|
// engine measuring the full DOM and locking the node fully expanded.
|
||||||
|
widget.computeLayoutSize = () => ({
|
||||||
|
minHeight: currentContentHeight,
|
||||||
|
maxHeight: currentContentHeight,
|
||||||
|
minWidth: 400,
|
||||||
|
});
|
||||||
|
|
||||||
widget.callback = callback;
|
widget.callback = callback;
|
||||||
|
|
||||||
widget.onRemove = () => {
|
widget.onRemove = () => {
|
||||||
|
|||||||
@@ -18,21 +18,28 @@ export function formatLoraValue(loras) {
|
|||||||
return loras;
|
return loras;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function to update widget height consistently
|
// Resolve the capped (12-row) height of the widget and physically cap the
|
||||||
|
// container so the list area never grows past it.
|
||||||
|
// `height` is the raw content height (already capped at 12 rows by the caller);
|
||||||
|
// the result never drops below defaultHeight.
|
||||||
|
// The max-height is the reliable lever: Nodes 2.0 / Vue mode measures the
|
||||||
|
// rendered DOM to size the node, so without an actual height cap on the element
|
||||||
|
// the list always shows every row. max-height bounds the element regardless of
|
||||||
|
// what the layout engine measures, and the overflow makes the extra rows scroll.
|
||||||
|
// Returns the resolved height so callers can also report it to ComfyUI.
|
||||||
export function updateWidgetHeight(container, height, defaultHeight, node) {
|
export function updateWidgetHeight(container, height, defaultHeight, node) {
|
||||||
// Ensure minimum height
|
const cappedHeight = Math.max(defaultHeight, height);
|
||||||
const finalHeight = Math.max(defaultHeight, height);
|
|
||||||
|
|
||||||
// Update CSS variables
|
container.style.maxHeight = `${cappedHeight}px`;
|
||||||
container.style.setProperty('--comfy-widget-min-height', `${finalHeight}px`);
|
|
||||||
container.style.setProperty('--comfy-widget-height', `${finalHeight}px`);
|
|
||||||
|
|
||||||
// Force node to update size after a short delay to ensure DOM is updated
|
// Force node to redraw after a short delay to ensure the DOM is updated.
|
||||||
if (node) {
|
if (node) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
node.setDirtyCanvas(true, true);
|
node.setDirtyCanvas(true, true);
|
||||||
}, 10);
|
}, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return cappedHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine if clip entry should be shown - now based on expanded property or initial diff values
|
// Determine if clip entry should be shown - now based on expanded property or initial diff values
|
||||||
|
|||||||
@@ -784,6 +784,59 @@ export function forwardWheelToCanvas(container, options = {}) {
|
|||||||
}, { passive: false });
|
}, { passive: false });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Marks elements whose wheel scrolling must win over the canvas zoom.
|
||||||
|
const LIST_WHEEL_SCROLL_CLASS = 'lm-wheel-scrollable';
|
||||||
|
let listWheelScrollHookInstalled = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Keep vertical wheel scrolling inside a scrollable widget container instead of
|
||||||
|
* letting ComfyUI zoom the canvas.
|
||||||
|
*
|
||||||
|
* In Nodes 2.0 / Vue mode ComfyUI's wheel→zoom handler runs on the document /
|
||||||
|
* canvas in the capture phase, which is *outer* than the widget, so a listener
|
||||||
|
* on the container (even in capture) fires too late. The reliable place to win
|
||||||
|
* is a single hook on `window` in the capture phase — the very first step of
|
||||||
|
* event dispatch. When the wheel is over a marked, scrollable element we scroll
|
||||||
|
* it manually and fully consume the event; otherwise we leave it alone so canvas
|
||||||
|
* zoom keeps working.
|
||||||
|
* @param {HTMLElement} container - The scrollable element (overflow: auto)
|
||||||
|
*/
|
||||||
|
export function enableListWheelScroll(container) {
|
||||||
|
if (!container) return;
|
||||||
|
container.classList.add(LIST_WHEEL_SCROLL_CLASS);
|
||||||
|
|
||||||
|
if (listWheelScrollHookInstalled) return;
|
||||||
|
listWheelScrollHookInstalled = true;
|
||||||
|
|
||||||
|
window.addEventListener('wheel', (event) => {
|
||||||
|
// Let pinch/zoom and horizontal gestures fall through to the canvas.
|
||||||
|
if (event.ctrlKey) return;
|
||||||
|
if (Math.abs(event.deltaX) > Math.abs(event.deltaY)) return;
|
||||||
|
|
||||||
|
const target = event.target;
|
||||||
|
if (!target || typeof target.closest !== 'function') return;
|
||||||
|
const el = target.closest(`.${LIST_WHEEL_SCROLL_CLASS}`);
|
||||||
|
if (!el) return;
|
||||||
|
|
||||||
|
const canScrollY = el.scrollHeight > el.clientHeight + 1;
|
||||||
|
if (!canScrollY) return; // Nothing to scroll → allow canvas zoom.
|
||||||
|
|
||||||
|
// Translate the wheel delta to pixels (line / page modes → approx px).
|
||||||
|
const unit = event.deltaMode === 1
|
||||||
|
? 16
|
||||||
|
: event.deltaMode === 2
|
||||||
|
? el.clientHeight
|
||||||
|
: 1;
|
||||||
|
|
||||||
|
el.scrollTop += event.deltaY * unit;
|
||||||
|
|
||||||
|
// Consume the event so neither ComfyUI's zoom nor forwardWheelToCanvas react.
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
event.stopImmediatePropagation();
|
||||||
|
}, { capture: true, passive: false });
|
||||||
|
}
|
||||||
|
|
||||||
// Get connected Lora Pool node from pool_config input
|
// Get connected Lora Pool node from pool_config input
|
||||||
export function getConnectedPoolConfigNode(node) {
|
export function getConnectedPoolConfigNode(node) {
|
||||||
if (!node?.inputs) {
|
if (!node?.inputs) {
|
||||||
|
|||||||
@@ -2118,14 +2118,14 @@ to { transform: rotate(360deg);
|
|||||||
padding: 20px 0;
|
padding: 20px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.autocomplete-text-widget[data-v-5514bf46] {
|
.autocomplete-text-widget[data-v-1c610e5d] {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
.input-wrapper[data-v-5514bf46] {
|
.input-wrapper[data-v-1c610e5d] {
|
||||||
position: relative;
|
position: relative;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -2133,7 +2133,7 @@ to { transform: rotate(360deg);
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Canvas mode styles (default) - matches built-in comfy-multiline-input */
|
/* Canvas mode styles (default) - matches built-in comfy-multiline-input */
|
||||||
.text-input[data-v-5514bf46] {
|
.text-input[data-v-1c610e5d] {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background-color: var(--comfy-input-bg, #222);
|
background-color: var(--comfy-input-bg, #222);
|
||||||
@@ -2150,7 +2150,7 @@ to { transform: rotate(360deg);
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Vue DOM mode styles - matches built-in p-textarea in Vue DOM mode */
|
/* Vue DOM mode styles - matches built-in p-textarea in Vue DOM mode */
|
||||||
.text-input.vue-dom-mode[data-v-5514bf46] {
|
.text-input.vue-dom-mode[data-v-1c610e5d] {
|
||||||
background-color: var(--color-charcoal-400, #313235);
|
background-color: var(--color-charcoal-400, #313235);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
padding: 8px 12px 30px 12px; /* Reserve bottom space for clear button */
|
padding: 8px 12px 30px 12px; /* Reserve bottom space for clear button */
|
||||||
@@ -2159,12 +2159,12 @@ to { transform: rotate(360deg);
|
|||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-family: inherit;
|
font-family: inherit;
|
||||||
}
|
}
|
||||||
.text-input[data-v-5514bf46]:focus {
|
.text-input[data-v-1c610e5d]:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear button styles */
|
/* Clear button styles */
|
||||||
.clear-button[data-v-5514bf46] {
|
.clear-button[data-v-1c610e5d] {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 6px;
|
right: 6px;
|
||||||
bottom: 6px; /* Changed from top to bottom */
|
bottom: 6px; /* Changed from top to bottom */
|
||||||
@@ -2187,31 +2187,31 @@ to { transform: rotate(360deg);
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Show clear button when hovering over input wrapper */
|
/* Show clear button when hovering over input wrapper */
|
||||||
.input-wrapper:hover .clear-button[data-v-5514bf46] {
|
.input-wrapper:hover .clear-button[data-v-1c610e5d] {
|
||||||
opacity: 0.7;
|
opacity: 0.7;
|
||||||
pointer-events: auto;
|
pointer-events: auto;
|
||||||
}
|
}
|
||||||
.clear-button[data-v-5514bf46]:hover {
|
.clear-button[data-v-1c610e5d]:hover {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
background: rgba(255, 100, 100, 0.8);
|
background: rgba(255, 100, 100, 0.8);
|
||||||
}
|
}
|
||||||
.clear-button svg[data-v-5514bf46] {
|
.clear-button svg[data-v-1c610e5d] {
|
||||||
width: 12px;
|
width: 12px;
|
||||||
height: 12px;
|
height: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Vue DOM mode adjustments for clear button */
|
/* Vue DOM mode adjustments for clear button */
|
||||||
.text-input.vue-dom-mode ~ .clear-button[data-v-5514bf46] {
|
.text-input.vue-dom-mode ~ .clear-button[data-v-1c610e5d] {
|
||||||
right: 8px;
|
right: 8px;
|
||||||
bottom: 10px; /* Changed from top to bottom, adjusted for Vue DOM padding */
|
bottom: 10px; /* Changed from top to bottom, adjusted for Vue DOM padding */
|
||||||
width: 20px;
|
width: 20px;
|
||||||
height: 20px;
|
height: 20px;
|
||||||
background: rgba(107, 114, 128, 0.6);
|
background: rgba(107, 114, 128, 0.6);
|
||||||
}
|
}
|
||||||
.text-input.vue-dom-mode ~ .clear-button[data-v-5514bf46]:hover {
|
.text-input.vue-dom-mode ~ .clear-button[data-v-1c610e5d]:hover {
|
||||||
background: oklch(62% 0.18 25);
|
background: oklch(62% 0.18 25);
|
||||||
}
|
}
|
||||||
.text-input.vue-dom-mode ~ .clear-button svg[data-v-5514bf46] {
|
.text-input.vue-dom-mode ~ .clear-button svg[data-v-1c610e5d] {
|
||||||
width: 14px;
|
width: 14px;
|
||||||
height: 14px;
|
height: 14px;
|
||||||
}`));
|
}`));
|
||||||
@@ -14783,7 +14783,8 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|||||||
modelType: {},
|
modelType: {},
|
||||||
placeholder: {},
|
placeholder: {},
|
||||||
showPreview: { type: Boolean },
|
showPreview: { type: Boolean },
|
||||||
spellcheck: { type: Boolean }
|
spellcheck: { type: Boolean },
|
||||||
|
maxHeight: {}
|
||||||
},
|
},
|
||||||
setup(__props) {
|
setup(__props) {
|
||||||
const props = __props;
|
const props = __props;
|
||||||
@@ -14913,10 +14914,11 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|||||||
ref: textareaRef,
|
ref: textareaRef,
|
||||||
placeholder: __props.placeholder,
|
placeholder: __props.placeholder,
|
||||||
spellcheck: __props.spellcheck ?? false,
|
spellcheck: __props.spellcheck ?? false,
|
||||||
class: normalizeClass(["text-input", { "vue-dom-mode": isVueDomMode.value }]),
|
class: normalizeClass(["text-input", { "vue-dom-mode": isVueDomMode.value, "lm-wheel-scrollable": isVueDomMode.value }]),
|
||||||
|
style: normalizeStyle(__props.maxHeight && isVueDomMode.value ? { maxHeight: __props.maxHeight + "px" } : void 0),
|
||||||
onInput,
|
onInput,
|
||||||
onWheel
|
onWheel
|
||||||
}, null, 42, _hoisted_3),
|
}, null, 46, _hoisted_3),
|
||||||
showClearButton.value ? (openBlock(), createElementBlock("button", {
|
showClearButton.value ? (openBlock(), createElementBlock("button", {
|
||||||
key: 0,
|
key: 0,
|
||||||
type: "button",
|
type: "button",
|
||||||
@@ -14949,7 +14951,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const AutocompleteTextWidget = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-5514bf46"]]);
|
const AutocompleteTextWidget = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-1c610e5d"]]);
|
||||||
function createVueWidgetCleanup(vueApp, onCleanup) {
|
function createVueWidgetCleanup(vueApp, onCleanup) {
|
||||||
let didUnmount = false;
|
let didUnmount = false;
|
||||||
return () => {
|
return () => {
|
||||||
@@ -15799,13 +15801,15 @@ function createAutocompleteTextWidgetFactory(node, widgetName, modelType, inputO
|
|||||||
);
|
);
|
||||||
widget.metadataWidget = metadataWidget;
|
widget.metadataWidget = metadataWidget;
|
||||||
const spellcheck = ((_c = (_b = (_a2 = app$1.ui) == null ? void 0 : _a2.settings) == null ? void 0 : _b.getSettingValue) == null ? void 0 : _c.call(_b, "Comfy.TextareaWidget.Spellcheck")) ?? false;
|
const spellcheck = ((_c = (_b = (_a2 = app$1.ui) == null ? void 0 : _a2.settings) == null ? void 0 : _b.getSettingValue) == null ? void 0 : _c.call(_b, "Comfy.TextareaWidget.Spellcheck")) ?? false;
|
||||||
|
const maxHeight = modelType === "loras" ? AUTOCOMPLETE_TEXT_WIDGET_MAX_HEIGHT : void 0;
|
||||||
const vueApp = createApp(AutocompleteTextWidget, {
|
const vueApp = createApp(AutocompleteTextWidget, {
|
||||||
widget,
|
widget,
|
||||||
node,
|
node,
|
||||||
modelType,
|
modelType,
|
||||||
placeholder: inputOptions.placeholder || widgetName,
|
placeholder: inputOptions.placeholder || widgetName,
|
||||||
showPreview: true,
|
showPreview: true,
|
||||||
spellcheck
|
spellcheck,
|
||||||
|
maxHeight
|
||||||
});
|
});
|
||||||
vueApp.use(PrimeVue, {
|
vueApp.use(PrimeVue, {
|
||||||
unstyled: true,
|
unstyled: true,
|
||||||
@@ -15814,6 +15818,9 @@ function createAutocompleteTextWidgetFactory(node, widgetName, modelType, inputO
|
|||||||
vueApp.mount(container);
|
vueApp.mount(container);
|
||||||
const appKey = instanceId;
|
const appKey = instanceId;
|
||||||
vueApps.set(appKey, vueApp);
|
vueApps.set(appKey, vueApp);
|
||||||
|
if (maxHeight) {
|
||||||
|
container.style.maxHeight = `${maxHeight}px`;
|
||||||
|
}
|
||||||
widget.onRemove = createVueWidgetCleanup(vueApp, () => {
|
widget.onRemove = createVueWidgetCleanup(vueApp, () => {
|
||||||
vueApps.delete(appKey);
|
vueApps.delete(appKey);
|
||||||
});
|
});
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user