fix(editor): Make auto-completion work in zoomed view (no-changelog) (#18048)

This commit is contained in:
Suguru Inoue
2025-08-08 14:47:45 +02:00
committed by GitHub
parent c896bb2b4a
commit 6f4c76c78c
6 changed files with 34 additions and 10 deletions

View File

@@ -10,7 +10,12 @@ import Telemetry from '@/components/Telemetry.vue';
import AskAssistantFloatingButton from '@/components/AskAssistant/Chat/AskAssistantFloatingButton.vue'; import AskAssistantFloatingButton from '@/components/AskAssistant/Chat/AskAssistantFloatingButton.vue';
import AssistantsHub from '@/components/AskAssistant/AssistantsHub.vue'; import AssistantsHub from '@/components/AskAssistant/AssistantsHub.vue';
import { loadLanguage } from '@n8n/i18n'; import { loadLanguage } from '@n8n/i18n';
import { APP_MODALS_ELEMENT_ID, HIRING_BANNER, VIEWS } from '@/constants'; import {
APP_MODALS_ELEMENT_ID,
CODEMIRROR_TOOLTIP_CONTAINER_ELEMENT_ID,
HIRING_BANNER,
VIEWS,
} from '@/constants';
import { useRootStore } from '@n8n/stores/useRootStore'; import { useRootStore } from '@n8n/stores/useRootStore';
import { useAssistantStore } from '@/stores/assistant.store'; import { useAssistantStore } from '@/stores/assistant.store';
import { useBuilderStore } from '@/stores/builder.store'; import { useBuilderStore } from '@/stores/builder.store';
@@ -135,6 +140,7 @@ watch(
<AskAssistantFloatingButton v-if="showAssistantFloatingButton" /> <AskAssistantFloatingButton v-if="showAssistantFloatingButton" />
</div> </div>
<AssistantsHub /> <AssistantsHub />
<div :id="CODEMIRROR_TOOLTIP_CONTAINER_ELEMENT_ID" />
</div> </div>
</template> </template>

View File

@@ -206,7 +206,11 @@ export const useExpressionEditor = ({
const state = EditorState.create({ const state = EditorState.create({
doc: toValue(editorValue), doc: toValue(editorValue),
extensions: [ extensions: [
TARGET_NODE_PARAMETER_FACET.of(toValue(targetNodeParameterContext)), TARGET_NODE_PARAMETER_FACET.of(
expressionLocalResolveContext.value
? { nodeName: expressionLocalResolveContext.value.nodeName, parameterPath: '' }
: toValue(targetNodeParameterContext),
),
customExtensions.value.of(toValue(extensions)), customExtensions.value.of(toValue(extensions)),
readOnlyExtensions.value.of([EditorState.readOnly.of(toValue(isReadOnly))]), readOnlyExtensions.value.of([EditorState.readOnly.of(toValue(isReadOnly))]),
telemetryExtensions.value.of([]), telemetryExtensions.value.of([]),

View File

@@ -14,6 +14,7 @@ const APP_Z_INDEXES = {
TOASTS: 2100, TOASTS: 2100,
ASK_ASSISTANT_FLOATING_BUTTON: 3000, ASK_ASSISTANT_FLOATING_BUTTON: 3000,
ASK_ASSISTANT_FLOATING_BUTTON_TOOLTIP: 3000, ASK_ASSISTANT_FLOATING_BUTTON_TOOLTIP: 3000,
CODEMIRROR_TOOLTIP: 3000,
DRAGGABLE: 9999999, DRAGGABLE: 9999999,
ACTIVE_STICKY: 9999999, ACTIVE_STICKY: 9999999,
WORKFLOW_PREVIEW_NDV: 9999999, WORKFLOW_PREVIEW_NDV: 9999999,

View File

@@ -953,8 +953,8 @@ export const ExpressionLocalResolveContextSymbol = Symbol(
'ExpressionLocalResolveContext', 'ExpressionLocalResolveContext',
) as InjectionKey<ComputedRef<ExpressionLocalResolveContext | undefined>>; ) as InjectionKey<ComputedRef<ExpressionLocalResolveContext | undefined>>;
/** Auth */
export const APP_MODALS_ELEMENT_ID = 'app-modals'; export const APP_MODALS_ELEMENT_ID = 'app-modals';
export const CODEMIRROR_TOOLTIP_CONTAINER_ELEMENT_ID = 'cm-tooltip-container';
export const AI_NODES_PACKAGE_NAME = '@n8n/n8n-nodes-langchain'; export const AI_NODES_PACKAGE_NAME = '@n8n/n8n-nodes-langchain';

View File

@@ -12,12 +12,14 @@ import {
hoverTooltip, hoverTooltip,
keymap, keymap,
showTooltip, showTooltip,
tooltips,
type Command, type Command,
type EditorView, type EditorView,
type Tooltip, type Tooltip,
} from '@codemirror/view'; } from '@codemirror/view';
import type { SyntaxNode } from '@lezer/common'; import type { SyntaxNode } from '@lezer/common';
import type { createInfoBoxRenderer } from '../completions/infoBoxRenderer'; import type { createInfoBoxRenderer } from '../completions/infoBoxRenderer';
import { CODEMIRROR_TOOLTIP_CONTAINER_ELEMENT_ID } from '@/constants';
const findNearestParentOfType = const findNearestParentOfType =
(type: string) => (type: string) =>
@@ -308,6 +310,9 @@ export const closeCursorInfoBox: Command = (view) => {
export const infoBoxTooltips = (): Extension[] => { export const infoBoxTooltips = (): Extension[] => {
return [ return [
tooltips({
parent: document.getElementById(CODEMIRROR_TOOLTIP_CONTAINER_ELEMENT_ID) ?? undefined,
}),
cursorInfoBoxTooltip, cursorInfoBoxTooltip,
hoverInfoBoxTooltip, hoverInfoBoxTooltip,
keymap.of([ keymap.of([

View File

@@ -1,13 +1,21 @@
#cm-tooltip-container {
position: relative;
z-index: var(--z-index-codemirror-tooltip);
max-width: 0;
max-height: 0;
}
.code-node-editor .cm-editor .cm-tooltip-autocomplete > ul[role='listbox'] { .code-node-editor .cm-editor .cm-tooltip-autocomplete > ul[role='listbox'] {
border-bottom: none; border-bottom: none;
border-bottom-left-radius: 0; border-bottom-left-radius: 0;
border-bottom-right-radius: 0; border-bottom-right-radius: 0;
} }
.cm-editor .cm-tooltip-autocomplete { #cm-tooltip-container .cm-tooltip-autocomplete {
background-color: var(--color-background-xlight) !important; background-color: var(--color-background-xlight) !important;
box-shadow: var(--box-shadow-light); box-shadow: var(--box-shadow-light);
border: none; border: none;
border-radius: var(--border-radius-base);
.cm-tooltip { .cm-tooltip {
overflow: hidden; overflow: hidden;
@@ -90,9 +98,9 @@
} }
} }
.cm-editor .cm-tooltip.cm-completionInfo, #cm-tooltip-container .cm-tooltip.cm-completionInfo,
.cm-editor .cm-tooltip.cm-cursorInfo, #cm-tooltip-container .cm-tooltip.cm-cursorInfo,
.cm-editor .cm-tooltip-hover { #cm-tooltip-container .cm-tooltip-hover {
// Add padding when infobox only contains text // Add padding when infobox only contains text
&:not(:has(div)) { &:not(:has(div)) {
padding: var(--spacing-xs); padding: var(--spacing-xs);
@@ -293,7 +301,7 @@
} }
} }
.cm-editor .cm-tooltip.cm-completionInfo { #cm-tooltip-container .cm-tooltip.cm-completionInfo {
background-color: var(--color-background-xlight); background-color: var(--color-background-xlight);
border: var(--border-base); border: var(--border-base);
box-shadow: var(--box-shadow-light); box-shadow: var(--box-shadow-light);
@@ -335,8 +343,8 @@
} }
} }
.cm-editor .cm-tooltip.cm-cursorInfo, #cm-tooltip-container .cm-tooltip.cm-cursorInfo,
.cm-editor .cm-tooltip-hover { #cm-tooltip-container .cm-tooltip-hover {
background-color: var(--color-infobox-background); background-color: var(--color-infobox-background);
border: var(--border-base); border: var(--border-base);
box-shadow: var(--box-shadow-light); box-shadow: var(--box-shadow-light);