feat(autocomplete): support Tab accept and configurable suffix behavior (#863)

This commit is contained in:
Will Miao
2026-03-28 19:18:23 +08:00
parent a82f89d14a
commit 1ed5eef985
7 changed files with 633 additions and 95 deletions

View File

@@ -36,6 +36,8 @@ export interface AutocompleteTextWidgetInterface {
inputEl?: HTMLTextAreaElement
callback?: (v: string) => void
onSetValue?: (v: string) => void
metadataWidget?: { value?: unknown }
name?: string
}
const props = defineProps<{
@@ -171,6 +173,9 @@ onMounted(() => {
// Register textarea reference with widget
if (textareaRef.value) {
props.widget.inputEl = textareaRef.value
;(textareaRef.value as any)._autocompleteHostWidget = props.widget
;(textareaRef.value as any)._autocompleteMetadataWidget = props.widget.metadataWidget
;(textareaRef.value as any)._autocompleteTextWidgetName = props.widget.name ?? 'text'
// Also store on the container element for cloned widgets (subgraph promotion)
// When widgets are promoted to subgraph nodes, the cloned widget shares the same
@@ -208,6 +213,9 @@ onUnmounted(() => {
// Remove external value change event listener
if (textareaRef.value) {
delete (textareaRef.value as any)._autocompleteHostWidget
delete (textareaRef.value as any)._autocompleteMetadataWidget
delete (textareaRef.value as any)._autocompleteTextWidgetName
textareaRef.value.removeEventListener('lora-manager:autocomplete-value-changed', onExternalValueChange as EventListener)
}

View File

@@ -411,6 +411,7 @@ function createAutocompleteTextWidgetFactory(
modelType: 'loras' | 'embeddings' | 'prompt',
inputOptions: { placeholder?: string } = {}
) {
const metadataWidgetName = `__lm_autocomplete_meta_${widgetName}`
const container = document.createElement('div')
container.id = `autocomplete-text-widget-${node.id}-${widgetName}`
container.style.width = '100%'
@@ -427,6 +428,15 @@ function createAutocompleteTextWidgetFactory(
const widgetElementRef = { inputEl: undefined as HTMLTextAreaElement | undefined }
;(container as any).__widgetInputEl = widgetElementRef
const metadataWidget = node.addWidget('text', metadataWidgetName, {
version: 1,
textWidgetName: widgetName
})
metadataWidget.type = 'LORA_MANAGER_AUTOCOMPLETE_METADATA'
metadataWidget.hidden = true
metadataWidget.computeSize = () => [0, -4]
metadataWidget.serializeValue = () => metadataWidget.value
const widget = node.addDOMWidget(
widgetName,
`AUTOCOMPLETE_TEXT_${modelType.toUpperCase()}`,
@@ -463,6 +473,7 @@ function createAutocompleteTextWidgetFactory(
})
}
)
widget.metadataWidget = metadataWidget
// Get spellcheck setting from ComfyUI settings (default: false)
const spellcheck = app.ui?.settings?.getSettingValue?.('Comfy.TextareaWidget.Spellcheck') ?? false