diff --git a/packages/frontend/editor-ui/src/components/Node/NodeCreation.vue b/packages/frontend/editor-ui/src/components/Node/NodeCreation.vue index ccbfe220c6..5eab16a6df 100644 --- a/packages/frontend/editor-ui/src/components/Node/NodeCreation.vue +++ b/packages/frontend/editor-ui/src/components/Node/NodeCreation.vue @@ -145,6 +145,7 @@ function onAskAssistantButtonClick() { icon="panel-right" :class="focusPanelActive ? $style.activeButton : ''" :active="focusPanelActive" + data-test-id="toggle-focus-panel-button" @click="toggleFocusPanel" /> diff --git a/packages/frontend/editor-ui/src/components/ParameterInput.vue b/packages/frontend/editor-ui/src/components/ParameterInput.vue index 3c14a9c1a3..ca02141847 100644 --- a/packages/frontend/editor-ui/src/components/ParameterInput.vue +++ b/packages/frontend/editor-ui/src/components/ParameterInput.vue @@ -201,6 +201,7 @@ const dateTimePickerOptions = ref({ ], }); const isFocused = ref(false); +const isMapperShown = ref(false); const contextNode = expressionLocalResolveCtx?.value?.workflow.getNode( expressionLocalResolveCtx.value.nodeName, @@ -611,11 +612,7 @@ const showDragnDropTip = computed( const shouldCaptureForPosthog = computed(() => node.value?.type === AI_TRANSFORM_NODE_TYPE); -const shouldShowMapper = computed( - () => - isFocused.value && - (isModelValueExpression.value || props.forceShowExpression || props.modelValue === ''), -); +const mapperElRef = computed(() => mapperRef.value?.contentRef); function isRemoteParameterOption(option: INodePropertyOptions) { return remoteParameterOptionsKeys.value.includes(option.name); @@ -802,6 +799,10 @@ async function setFocus() { } isFocused.value = true; + + if (isModelValueExpression.value || props.forceShowExpression || props.modelValue === '') { + isMapperShown.value = true; + } } emit('focus'); @@ -942,17 +943,19 @@ function expressionUpdated(value: string) { } function onBlur(event?: FocusEvent | KeyboardEvent) { - if ( - event?.target instanceof HTMLElement && - mapperRef.value?.contentRef && - (event.target === mapperRef.value.contentRef || - mapperRef.value.contentRef.contains(event.target)) - ) { - return; - } - emit('blur'); isFocused.value = false; + + if ( + !(event?.target instanceof Node && mapperElRef.value?.contains(event.target)) && + !( + event instanceof FocusEvent && + event.relatedTarget instanceof Node && + mapperElRef.value?.contains(event.relatedTarget) + ) + ) { + isMapperShown.value = false; + } } function onPaste(event: ClipboardEvent) { @@ -998,6 +1001,12 @@ function onUpdateTextInput(value: string) { onTextInputChange(value); } +function onClickOutsideMapper() { + if (!isFocused.value) { + isMapperShown.value = false; + } +} + async function optionSelected(command: string) { const prevValue = props.modelValue; @@ -1012,6 +1021,7 @@ async function optionSelected(command: string) { case 'removeExpression': isFocused.value = false; + isMapperShown.value = false; valueChanged( parseFromExpression( props.modelValue, @@ -1210,7 +1220,7 @@ onUpdated(async () => { } }); -onClickOutside(wrapper, onBlur); +onClickOutside(mapperElRef, onClickOutsideMapper);