From 0ca339103f4ad856db57f08031bb59518b5c33ba Mon Sep 17 00:00:00 2001 From: Joel Date: Thu, 30 Apr 2026 16:33:29 +0800 Subject: [PATCH] fix: var reference picker can not choose sub vars (#35732) Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> --- eslint-suppressions.json | 5 --- .../__tests__/index.spec.tsx | 42 +++++++++++++++++++ .../plugins/component-picker-block/index.tsx | 13 +++--- .../object-child-tree-panel/picker/field.tsx | 2 +- .../variable/var-reference-vars.tsx | 5 ++- 5 files changed, 54 insertions(+), 13 deletions(-) diff --git a/eslint-suppressions.json b/eslint-suppressions.json index 7b24f216aa..272fa034ad 100644 --- a/eslint-suppressions.json +++ b/eslint-suppressions.json @@ -1744,11 +1744,6 @@ "count": 4 } }, - "web/app/components/base/prompt-editor/plugins/component-picker-block/index.tsx": { - "ts/no-explicit-any": { - "count": 1 - } - }, "web/app/components/base/prompt-editor/plugins/component-picker-block/menu.tsx": { "erasable-syntax-only/parameter-properties": { "count": 1 diff --git a/web/app/components/base/prompt-editor/plugins/component-picker-block/__tests__/index.spec.tsx b/web/app/components/base/prompt-editor/plugins/component-picker-block/__tests__/index.spec.tsx index a09e25f6e9..d14de7d58b 100644 --- a/web/app/components/base/prompt-editor/plugins/component-picker-block/__tests__/index.spec.tsx +++ b/web/app/components/base/prompt-editor/plugins/component-picker-block/__tests__/index.spec.tsx @@ -29,6 +29,7 @@ import { } from 'lexical' import * as React from 'react' import { GeneratorType } from '@/app/components/app/configuration/config/automatic/types' +import { VAR_REFERENCE_CHILD_POPUP_CLASS_NAME } from '@/app/components/workflow/nodes/_base/components/variable/var-reference-vars' import { VarType } from '@/app/components/workflow/types' import { useEventEmitterContextContext } from '@/context/event-emitter' import { EventEmitterContextProvider } from '@/context/event-emitter-provider' @@ -928,5 +929,46 @@ describe('ComponentPicker (component-picker-block/index.tsx)', () => { vi.useRealTimers() }) + + it('does not hide the menu when focus moves into a variable child popup', async () => { + const captures: Captures = { editor: null, eventEmitter: null } + + render(( + + )) + + const editor = await waitForEditor(captures) + await setEditorText(editor, '/', true) + expect(await screen.findByText('payload')).toBeInTheDocument() + + vi.useFakeTimers() + + const popupTarget = document.createElement('button') + const popup = document.createElement('div') + popup.classList.add(VAR_REFERENCE_CHILD_POPUP_CLASS_NAME) + popup.appendChild(popupTarget) + document.body.appendChild(popup) + + act(() => { + editor.dispatchCommand(BLUR_COMMAND, new FocusEvent('blur-sm', { relatedTarget: popupTarget })) + }) + + act(() => { + vi.advanceTimersByTime(200) + }) + + expect(screen.queryByText('payload')).toBeInTheDocument() + + popup.remove() + vi.useRealTimers() + }) }) }) diff --git a/web/app/components/base/prompt-editor/plugins/component-picker-block/index.tsx b/web/app/components/base/prompt-editor/plugins/component-picker-block/index.tsx index 503af4077d..10c371916b 100644 --- a/web/app/components/base/prompt-editor/plugins/component-picker-block/index.tsx +++ b/web/app/components/base/prompt-editor/plugins/component-picker-block/index.tsx @@ -14,6 +14,7 @@ import type { WorkflowVariableBlockType, } from '../../types' import type { PickerBlockMenuOption } from './menu' +import type { EventEmitterValue } from '@/context/event-emitter' import { flip, offset, @@ -39,7 +40,7 @@ import { } from 'react' import ReactDOM from 'react-dom' import { GeneratorType } from '@/app/components/app/configuration/config/automatic/types' -import VarReferenceVars from '@/app/components/workflow/nodes/_base/components/variable/var-reference-vars' +import VarReferenceVars, { VAR_REFERENCE_CHILD_POPUP_CLASS_NAME } from '@/app/components/workflow/nodes/_base/components/variable/var-reference-vars' import { useEventEmitterContextContext } from '@/context/event-emitter' import { useBasicTypeaheadTriggerMatch } from '../../hooks' import { $splitNodeContainingQuery } from '../../utils' @@ -119,7 +120,9 @@ const ComponentPicker = ({ (event) => { clearBlurTimer() const target = event?.relatedTarget as HTMLElement - if (!target?.classList?.contains('var-search-input')) + const isVariableMenuTarget = target?.classList?.contains('var-search-input') + || target?.closest?.(`.${VAR_REFERENCE_CHILD_POPUP_CLASS_NAME}`) + if (!isVariableMenuTarget) blurTimerRef.current = setTimeout(() => setBlurHidden(true), 200) return false }, @@ -143,8 +146,8 @@ const ComponentPicker = ({ } }, [editor, clearBlurTimer]) - eventEmitter?.useSubscription((v: any) => { - if (v.type === INSERT_VARIABLE_VALUE_BLOCK_COMMAND) + eventEmitter?.useSubscription((v: EventEmitterValue) => { + if (typeof v !== 'string' && v.type === INSERT_VARIABLE_VALUE_BLOCK_COMMAND && typeof v.payload === 'string') editor.dispatchCommand(INSERT_VARIABLE_VALUE_BLOCK_COMMAND, `{{${v.payload}}}`) }) @@ -303,7 +306,7 @@ const ComponentPicker = ({ } ) - }, [blurHidden, allFlattenOptions.length, workflowVariableBlock?.show, floatingStyles, isPositioned, refs, workflowVariableOptions, isSupportFileVar, handleClose, currentBlock?.generatorType, handleSelectWorkflowVariable, queryString, workflowVariableBlock?.showManageInputField, workflowVariableBlock?.onManageInputField]) + }, [blurHidden, allFlattenOptions.length, workflowVariableBlock?.show, floatingStyles, isPositioned, refs, workflowVariableOptions, isSupportFileVar, handleClose, currentBlock?.generatorType, handleSelectWorkflowVariable, queryString, triggerString, workflowVariableBlock?.showManageInputField, workflowVariableBlock?.onManageInputField]) return ( = ({ disabled={depth !== MAX_DEPTH + 1} render={(
!readonly && onSelect?.([...valueSelector, name])} >
diff --git a/web/app/components/workflow/nodes/_base/components/variable/var-reference-vars.tsx b/web/app/components/workflow/nodes/_base/components/variable/var-reference-vars.tsx index 38fef9016d..420888cb13 100644 --- a/web/app/components/workflow/nodes/_base/components/variable/var-reference-vars.tsx +++ b/web/app/components/workflow/nodes/_base/components/variable/var-reference-vars.tsx @@ -29,6 +29,7 @@ import { } from './var-reference-vars.helpers' const VAR_SEARCH_INPUT_CLASS_NAME = 'var-search-input' +export const VAR_REFERENCE_CHILD_POPUP_CLASS_NAME = 'var-reference-vars-child-popup' const resolveValueSelector = ({ itemData, @@ -210,7 +211,7 @@ const Item: FC = ({ className={cn( (isObj || isStructureOutput) ? 'pr-1' : 'pr-[18px]', (isHovering || isSelected) && ((isObj || isStructureOutput) ? 'bg-components-panel-on-panel-item-bg-hover' : 'bg-state-base-hover'), - 'relative flex h-6 w-full cursor-pointer items-center rounded-md pl-3', + 'relative flex h-6 w-full cursor-pointer items-center rounded-md pl-3 outline-none focus:outline-none focus-visible:outline-none', className, )} data-selected={isSelected ? 'true' : 'false'} @@ -263,7 +264,7 @@ const Item: FC = ({