fix(nodes): fix the same backdrop containing-block bug in the shared .llm-modal popup
While verifying the dialog style convergence, found that generic-node's "Edit <field>" popup and container-node's "Edit Name" popup have the same bug just fixed in bias-annotations: they render inside the node card, which rete.js positions with a CSS transform for pan/zoom, so their fixed-position .llm-modal-backdrop was trapped inside the node's own box instead of covering the page — confirmed live, the backdrop's bounding rect matched the node's box (280x533) rather than the viewport. This popup is the primary way to edit any short parameter on any node in the editor, so the bug was hit far more often than the bias one. Same fix: promote the backdrop to a native <dialog> shown via showModal(), move the dimming to ::backdrop, and guard showModal() since jsdom doesn't implement it. Verified live: the backdrop's rect now spans the full viewport for both generic-node and container-node, and closing via a backdrop click still works. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
803e70e6e5
commit
46976b1f92
|
|
@ -76,7 +76,7 @@
|
|||
</div>
|
||||
|
||||
@if (nameEditorOpen) {
|
||||
<div class="llm-modal-backdrop" (pointerdown)="$event.stopPropagation()" (click)="cancelNameEditor($event)">
|
||||
<dialog #nameEditorDialog class="llm-modal-backdrop" (pointerdown)="$event.stopPropagation()" (click)="onNameEditorDialogClick($event)" (cancel)="cancelNameEditor($event)">
|
||||
<div class="llm-modal" (pointerdown)="$event.stopPropagation()" (click)="$event.stopPropagation()">
|
||||
<div class="llm-modal-title">Edit Name</div>
|
||||
<div class="llm-modal-field">
|
||||
|
|
@ -94,7 +94,7 @@
|
|||
<button type="button" class="llm-btn llm-btn-primary" [disabled]="!draftName.trim()" (pointerdown)="$event.stopPropagation()" (click)="saveNameEditor($event)">Save</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</dialog>
|
||||
}
|
||||
|
||||
<div class="container-node__ports">
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { CommonModule } from '@angular/common';
|
||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, HostBinding, HostListener, Input, OnDestroy, inject } from '@angular/core';
|
||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, HostBinding, HostListener, Input, OnDestroy, effect, inject, viewChild } from '@angular/core';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
import { currentFlowPortValueKind, flowValueKindLabel, FlowData, FLOW_DEPENDANT_PORT_KEY, FLOW_DEPENDENCY_PORT_KEY } from '@models/flow';
|
||||
|
|
@ -109,6 +109,29 @@ export class ContainerNodeComponent implements OnDestroy {
|
|||
nameEditorOpen = false;
|
||||
draftName = '';
|
||||
|
||||
/**
|
||||
* This template renders inside a node card, which rete.js positions with a
|
||||
* CSS `transform` for pan/zoom, so a plain fixed-position backdrop would be
|
||||
* confined to the node's box. A native `<dialog>` shown via `showModal()`
|
||||
* escapes that via the browser's top layer, same fix as bias-annotations.
|
||||
*/
|
||||
private readonly nameEditorDialog = viewChild<ElementRef<HTMLDialogElement>>('nameEditorDialog');
|
||||
|
||||
constructor() {
|
||||
effect(() => {
|
||||
const dialog = this.nameEditorDialog()?.nativeElement;
|
||||
if (dialog && typeof dialog.showModal === 'function' && !dialog.open) {
|
||||
dialog.showModal();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onNameEditorDialogClick(event: MouseEvent) {
|
||||
if (event.target === this.nameEditorDialog()?.nativeElement) {
|
||||
this.cancelNameEditor(event);
|
||||
}
|
||||
}
|
||||
|
||||
get isSchemaLoading() {
|
||||
return this.schemaLoading;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -534,7 +534,7 @@
|
|||
(annotationsChange)="updateBiasAnnotations($event)" />
|
||||
|
||||
@if (localEditorOpen) {
|
||||
<div class="llm-modal-backdrop" (pointerdown)="$event.stopPropagation()" (click)="closeSimpleParamEditor($event)">
|
||||
<dialog #simpleEditorDialog class="llm-modal-backdrop" (pointerdown)="$event.stopPropagation()" (click)="onSimpleEditorDialogClick($event)" (cancel)="closeSimpleParamEditor($event)">
|
||||
<div class="llm-modal" (pointerdown)="$event.stopPropagation()" (click)="$event.stopPropagation()">
|
||||
<div class="llm-modal-title">Edit {{ localEditorLabel }}</div>
|
||||
@if (localEditorBindableAsInput && localEditorPath !== 'name') {
|
||||
|
|
@ -605,7 +605,7 @@
|
|||
<button type="button" class="llm-btn llm-btn-primary" [disabled]="!canSaveLocalEditor()" (pointerdown)="$event.stopPropagation()" (click)="saveSimpleParamEditor($event)">Save</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</dialog>
|
||||
}
|
||||
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { CommonModule } from '@angular/common';
|
||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, effect, ElementRef, HostBinding, HostListener, inject, Input, OnDestroy } from '@angular/core';
|
||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, effect, ElementRef, HostBinding, HostListener, inject, Input, OnDestroy, viewChild } from '@angular/core';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
import { BiasAnnotation, BiasAnnotationsDescriptor, BlockType, currentFlowPortValueKind, flowValueKindLabel, FlowBlock, FlowData, FlowPort, FlowValueKind, FLOW_DEPENDANT_PORT_KEY, FLOW_DEPENDENCY_PORT_KEY, isProbeExecutable, normalizeFlowPortValueKinds } from '@models/flow';
|
||||
|
|
@ -204,6 +204,14 @@ export class GenericNodeComponent implements OnDestroy {
|
|||
private conditionalRequiredByPath = new Map<string, boolean>();
|
||||
private refreshingConditionalRequirements = false;
|
||||
|
||||
/**
|
||||
* This template renders inside a node card, which rete.js positions with a
|
||||
* CSS `transform` for pan/zoom, so a plain fixed-position backdrop would be
|
||||
* confined to the node's box. A native `<dialog>` shown via `showModal()`
|
||||
* escapes that via the browser's top layer, same fix as bias-annotations.
|
||||
*/
|
||||
private readonly simpleEditorDialog = viewChild<ElementRef<HTMLDialogElement>>('simpleEditorDialog');
|
||||
|
||||
constructor() {
|
||||
effect(() => {
|
||||
const descriptorSignal = (this.blocksService as BlocksService & {
|
||||
|
|
@ -214,6 +222,19 @@ export class GenericNodeComponent implements OnDestroy {
|
|||
this.data.data.__biasAnnotationsProperty = property;
|
||||
}
|
||||
});
|
||||
|
||||
effect(() => {
|
||||
const dialog = this.simpleEditorDialog()?.nativeElement;
|
||||
if (dialog && typeof dialog.showModal === 'function' && !dialog.open) {
|
||||
dialog.showModal();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onSimpleEditorDialogClick(event: MouseEvent) {
|
||||
if (event.target === this.simpleEditorDialog()?.nativeElement) {
|
||||
this.closeSimpleParamEditor(event);
|
||||
}
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
|
|
|
|||
|
|
@ -166,7 +166,17 @@ body.node-focus-modal-open {
|
|||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
max-width: 100vw;
|
||||
max-height: 100vh;
|
||||
margin: 0;
|
||||
padding: 12px;
|
||||
border: none;
|
||||
background: transparent;
|
||||
color: inherit;
|
||||
}
|
||||
.llm-modal-backdrop::backdrop {
|
||||
background: rgba(15, 23, 42, 0.45);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue