mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-07-13 20:21:16 -03:00
fix(ui): allow autocomplete textarea resize in app mode (#1020)
This commit is contained in:
@@ -271,12 +271,14 @@ onUnmounted(() => {
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
padding: 2px 2px 24px 2px; /* Reserve bottom space for clear button */
|
padding: 2px 2px 24px 2px; /* Reserve bottom space for clear button */
|
||||||
resize: none;
|
|
||||||
border: none;
|
border: none;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
font-size: var(--comfy-textarea-font-size, 10px);
|
font-size: var(--comfy-textarea-font-size, 10px);
|
||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
|
/* resize:none set here (0,2,0). Overridden to vertical in app mode
|
||||||
|
by the :global(.\[\&_textarea\]\:resize-y) .text-input rule below. */
|
||||||
|
resize: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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 */
|
||||||
@@ -350,4 +352,19 @@ onUnmounted(() => {
|
|||||||
width: 14px;
|
width: 14px;
|
||||||
height: 14px;
|
height: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Non-scoped !important override: scoped .text-input[data-v-xxx] (0,2,0)
|
||||||
|
beats the app-mode Tailwind rule (0,1,1), so we use !important here to
|
||||||
|
force resize:vertical only when inside the app-mode widget list.
|
||||||
|
The data-testid attribute scoping prevents it from leaking into graph
|
||||||
|
mode. This is the only !important in the widget stylesheets.
|
||||||
|
-->
|
||||||
|
<style>
|
||||||
|
[data-testid="app-mode-widget-item"] textarea,
|
||||||
|
[data-testid="builder-widget-item"] textarea {
|
||||||
|
resize: vertical !important;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -553,22 +553,22 @@ function normalizeAutocompleteWidgetValues(node: any, info: any) {
|
|||||||
|
|
||||||
function applyAutocompleteTextLayoutFix(
|
function applyAutocompleteTextLayoutFix(
|
||||||
widget: any,
|
widget: any,
|
||||||
container: HTMLElement | undefined,
|
_container: HTMLElement | undefined,
|
||||||
isVueMode: boolean
|
isVueMode: boolean
|
||||||
): void {
|
): void {
|
||||||
|
// In Vue rendering mode the WidgetDOM wrapper handles sizing, so we
|
||||||
|
// only provide a computeSize hint and leave the container unconstrained.
|
||||||
|
// In canvas mode we clear all custom sizing so LiteGraph's default
|
||||||
|
// widget-area layout takes over. Neither path sets a hard max-height;
|
||||||
|
// the textarea can grow freely (e.g. in app mode where
|
||||||
|
// [&_textarea]:resize-y applies).
|
||||||
if (isVueMode) {
|
if (isVueMode) {
|
||||||
;(widget as any).computeLayoutSize = undefined
|
;(widget as any).computeLayoutSize = undefined
|
||||||
widget.computeSize = (width?: number) =>
|
widget.computeSize = (width?: number) =>
|
||||||
[width ?? 200, AUTOCOMPLETE_TEXT_WIDGET_MAX_HEIGHT - 4]
|
[width ?? 200, AUTOCOMPLETE_TEXT_WIDGET_MAX_HEIGHT - 4]
|
||||||
if (container) {
|
|
||||||
container.style.minHeight = `${AUTOCOMPLETE_TEXT_WIDGET_MAX_HEIGHT}px`
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
delete (widget as any).computeLayoutSize
|
delete (widget as any).computeLayoutSize
|
||||||
delete (widget as any).computeSize
|
delete (widget as any).computeSize
|
||||||
if (container) {
|
|
||||||
container.style.minHeight = ''
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -743,8 +743,12 @@ function createAutocompleteTextWidgetFactory(
|
|||||||
vueApps.set(appKey, vueApp)
|
vueApps.set(appKey, vueApp)
|
||||||
|
|
||||||
if (maxHeight) {
|
if (maxHeight) {
|
||||||
container.style.maxHeight = `${maxHeight}px`
|
// Set only minHeight as a true minimum — remove maxHeight so the
|
||||||
container.style.minHeight = `${maxHeight}px`
|
// textarea can grow when the user resizes it in app mode (where
|
||||||
|
// [&_textarea]:resize-y applies). Graph mode (canvas & Vue render)
|
||||||
|
// is unaffected because LiteGraph's layout system still governs
|
||||||
|
// the widget area size.
|
||||||
|
container.style.minHeight = `${AUTOCOMPLETE_TEXT_WIDGET_MIN_HEIGHT}px`
|
||||||
}
|
}
|
||||||
|
|
||||||
if (modelType === 'loras') {
|
if (modelType === 'loras') {
|
||||||
|
|||||||
@@ -2118,14 +2118,14 @@ to { transform: rotate(360deg);
|
|||||||
padding: 20px 0;
|
padding: 20px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.autocomplete-text-widget[data-v-8555b560] {
|
.autocomplete-text-widget[data-v-3f3d7a1a] {
|
||||||
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-8555b560] {
|
.input-wrapper[data-v-3f3d7a1a] {
|
||||||
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-8555b560] {
|
.text-input[data-v-3f3d7a1a] {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background-color: var(--comfy-input-bg, #222);
|
background-color: var(--comfy-input-bg, #222);
|
||||||
@@ -2141,16 +2141,18 @@ to { transform: rotate(360deg);
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
padding: 2px 2px 24px 2px; /* Reserve bottom space for clear button */
|
padding: 2px 2px 24px 2px; /* Reserve bottom space for clear button */
|
||||||
resize: none;
|
|
||||||
border: none;
|
border: none;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
font-size: var(--comfy-textarea-font-size, 10px);
|
font-size: var(--comfy-textarea-font-size, 10px);
|
||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
|
/* resize:none set here (0,2,0). Overridden to vertical in app mode
|
||||||
|
by the :global(.\\[\\&_textarea\\]\\:resize-y) .text-input rule below. */
|
||||||
|
resize: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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-8555b560] {
|
.text-input.vue-dom-mode[data-v-3f3d7a1a] {
|
||||||
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 +2161,12 @@ to { transform: rotate(360deg);
|
|||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-family: inherit;
|
font-family: inherit;
|
||||||
}
|
}
|
||||||
.text-input[data-v-8555b560]:focus {
|
.text-input[data-v-3f3d7a1a]:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear button styles */
|
/* Clear button styles */
|
||||||
.clear-button[data-v-8555b560] {
|
.clear-button[data-v-3f3d7a1a] {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 6px;
|
right: 6px;
|
||||||
bottom: 6px; /* Changed from top to bottom */
|
bottom: 6px; /* Changed from top to bottom */
|
||||||
@@ -2187,33 +2189,39 @@ 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-8555b560] {
|
.input-wrapper:hover .clear-button[data-v-3f3d7a1a] {
|
||||||
opacity: 0.7;
|
opacity: 0.7;
|
||||||
pointer-events: auto;
|
pointer-events: auto;
|
||||||
}
|
}
|
||||||
.clear-button[data-v-8555b560]:hover {
|
.clear-button[data-v-3f3d7a1a]:hover {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
background: rgba(255, 100, 100, 0.8);
|
background: rgba(255, 100, 100, 0.8);
|
||||||
}
|
}
|
||||||
.clear-button svg[data-v-8555b560] {
|
.clear-button svg[data-v-3f3d7a1a] {
|
||||||
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-8555b560] {
|
.text-input.vue-dom-mode ~ .clear-button[data-v-3f3d7a1a] {
|
||||||
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-8555b560]:hover {
|
.text-input.vue-dom-mode ~ .clear-button[data-v-3f3d7a1a]:hover {
|
||||||
background: oklch(62% 0.18 25);
|
background: oklch(62% 0.18 25);
|
||||||
}
|
}
|
||||||
.text-input.vue-dom-mode ~ .clear-button svg[data-v-8555b560] {
|
.text-input.vue-dom-mode ~ .clear-button svg[data-v-3f3d7a1a] {
|
||||||
width: 14px;
|
width: 14px;
|
||||||
height: 14px;
|
height: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[data-testid="app-mode-widget-item"] textarea,
|
||||||
|
[data-testid="builder-widget-item"] textarea {
|
||||||
|
resize: vertical !important;
|
||||||
}`));
|
}`));
|
||||||
document.head.appendChild(elementStyle);
|
document.head.appendChild(elementStyle);
|
||||||
}
|
}
|
||||||
@@ -14952,7 +14960,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const AutocompleteTextWidget = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-8555b560"]]);
|
const AutocompleteTextWidget = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-3f3d7a1a"]]);
|
||||||
function createVueWidgetCleanup(vueApp, onCleanup) {
|
function createVueWidgetCleanup(vueApp, onCleanup) {
|
||||||
let didUnmount = false;
|
let didUnmount = false;
|
||||||
return () => {
|
return () => {
|
||||||
@@ -15718,19 +15726,13 @@ function normalizeAutocompleteWidgetValues(node, info) {
|
|||||||
info.widgets_values = repairedValues;
|
info.widgets_values = repairedValues;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function applyAutocompleteTextLayoutFix(widget, container, isVueMode) {
|
function applyAutocompleteTextLayoutFix(widget, _container, isVueMode) {
|
||||||
if (isVueMode) {
|
if (isVueMode) {
|
||||||
widget.computeLayoutSize = void 0;
|
widget.computeLayoutSize = void 0;
|
||||||
widget.computeSize = (width) => [width ?? 200, AUTOCOMPLETE_TEXT_WIDGET_MAX_HEIGHT - 4];
|
widget.computeSize = (width) => [width ?? 200, AUTOCOMPLETE_TEXT_WIDGET_MAX_HEIGHT - 4];
|
||||||
if (container) {
|
|
||||||
container.style.minHeight = `${AUTOCOMPLETE_TEXT_WIDGET_MAX_HEIGHT}px`;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
delete widget.computeLayoutSize;
|
delete widget.computeLayoutSize;
|
||||||
delete widget.computeSize;
|
delete widget.computeSize;
|
||||||
if (container) {
|
|
||||||
container.style.minHeight = "";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const initVueDomModeListener = () => {
|
const initVueDomModeListener = () => {
|
||||||
@@ -15875,8 +15877,7 @@ function createAutocompleteTextWidgetFactory(node, widgetName, modelType, inputO
|
|||||||
const appKey = instanceId;
|
const appKey = instanceId;
|
||||||
vueApps.set(appKey, vueApp);
|
vueApps.set(appKey, vueApp);
|
||||||
if (maxHeight) {
|
if (maxHeight) {
|
||||||
container.style.maxHeight = `${maxHeight}px`;
|
container.style.minHeight = `${AUTOCOMPLETE_TEXT_WIDGET_MIN_HEIGHT}px`;
|
||||||
container.style.minHeight = `${maxHeight}px`;
|
|
||||||
}
|
}
|
||||||
if (modelType === "loras") {
|
if (modelType === "loras") {
|
||||||
applyAutocompleteTextLayoutFix(
|
applyAutocompleteTextLayoutFix(
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user