diff --git a/src/uix/soma/components/dialog/dialog-provider.svelte.ts b/src/uix/soma/components/dialog/dialog-provider.svelte.ts index 8b57d2300..9bd406d1f 100644 --- a/src/uix/soma/components/dialog/dialog-provider.svelte.ts +++ b/src/uix/soma/components/dialog/dialog-provider.svelte.ts @@ -195,7 +195,13 @@ export class DialogProvider { */ dismissWith(action: 'save' | 'cancel' | 'dismiss' | 'dismiss-outside' | 'fail'): Promise { const eventName = action === 'fail' ? 'close-after-fail' : `close-${action}`; - return this.runtime.trigger(eventName); + return this.triggerClose(eventName); + } + + triggerClose(eventName: string, fallbackTarget?: HTMLElement): Promise { + const target = this.contentRef.current ?? fallbackTarget ?? this.triggerNode.current; + if (!target) return this.runtime.trigger(eventName); + return this.runtime.trigger(eventName, { fallbackTarget: target }); } setContentRef(el: HTMLElement | null) { @@ -235,6 +241,9 @@ export class DialogTriggerProvider { id: opts.id, ref: opts.ref, owner: this, + onRefChange: (el) => { + this.provider.triggerNode.current = el; + }, syncAttrs: true }); } @@ -331,12 +340,14 @@ export class DialogContentProvider { enabled: readableActive(() => this.provider.opts.open.current), onEscapeKeydown: readableActive(() => (e: KeyboardEvent) => { opts.onEscapeKeydown.current(e); - if (!e.defaultPrevented) void this.provider.runtime.trigger('close-dismiss'); + if (!e.defaultPrevented) + void this.provider.triggerClose('close-dismiss', opts.ref.current ?? undefined); }), escapeKeydownBehavior: resolvedEscapeBehavior, onInteractOutside: readableActive(() => (e: PointerEvent) => { opts.onInteractOutside.current(e); - if (!e.defaultPrevented) void this.provider.runtime.trigger('close-dismiss-outside'); + if (!e.defaultPrevented) + void this.provider.triggerClose('close-dismiss-outside', opts.ref.current ?? undefined); }), interactOutsideBehavior: resolvedInteractBehavior, onFocusOutside: opts.onFocusOutside, @@ -516,8 +527,8 @@ export class DialogCloseProvider { }); } - readonly onclick = (_e: SomaMouseEvent) => { - void this.provider.runtime.trigger('close-cancel'); + readonly onclick = (e: SomaMouseEvent) => { + void this.provider.triggerClose('close-cancel', e.currentTarget as HTMLElement); }; readonly props = $derived.by(() => ({ diff --git a/src/uix/soma/components/drawer/drawer-provider.svelte.ts b/src/uix/soma/components/drawer/drawer-provider.svelte.ts index 215267f12..ce92c08ee 100644 --- a/src/uix/soma/components/drawer/drawer-provider.svelte.ts +++ b/src/uix/soma/components/drawer/drawer-provider.svelte.ts @@ -244,7 +244,13 @@ export class DrawerProvider { */ dismissWith(action: 'save' | 'cancel' | 'dismiss' | 'dismiss-outside' | 'fail'): Promise { const eventName = action === 'fail' ? 'close-after-fail' : `close-${action}`; - return this.runtime.trigger(eventName); + return this.triggerClose(eventName); + } + + triggerClose(eventName: string, fallbackTarget?: HTMLElement): Promise { + const target = this.contentRef.current ?? fallbackTarget ?? this.triggerNode.current; + if (!target) return this.runtime.trigger(eventName); + return this.runtime.trigger(eventName, { fallbackTarget: target }); } readonly isNested = $derived.by(() => this.depth > 0); @@ -458,7 +464,8 @@ export class DrawerContentProvider { ), onEscapeKeydown: readableActive(() => (e: KeyboardEvent) => { opts.onEscapeKeydown.current(e); - if (!e.defaultPrevented) void this.provider.runtime.trigger('close-dismiss'); + if (!e.defaultPrevented) + void this.provider.triggerClose('close-dismiss', opts.ref.current ?? undefined); }), escapeKeydownBehavior: readableActive(() => opts.escapeKeydownBehavior.current ?? 'close'), onInteractOutside: readableActive(() => (_e: PointerEvent) => {}), @@ -829,7 +836,7 @@ export class DrawerContentProvider { this.provider.opts.dismissible.current ) { e.preventDefault(); - void this.provider.runtime.trigger('close-dismiss'); + void this.provider.triggerClose('close-dismiss', e.currentTarget as HTMLElement); } }; @@ -973,9 +980,9 @@ export class DrawerOverlayProvider { readonly isPresent = $derived.by(() => this.provider.overlayPresence.isPresent); - readonly onclick = () => { + readonly onclick = (e: SomaMouseEvent) => { if (this.provider.opts.dismissible.current) { - void this.provider.runtime.trigger('close-dismiss-outside'); + void this.provider.triggerClose('close-dismiss-outside', e.currentTarget as HTMLElement); } }; @@ -1132,8 +1139,8 @@ export class DrawerCloseProvider { }); } - readonly onclick = (_e: SomaMouseEvent) => { - void this.provider.runtime.trigger('close-cancel'); + readonly onclick = (e: SomaMouseEvent) => { + void this.provider.triggerClose('close-cancel', e.currentTarget as HTMLElement); }; readonly props = $derived.by(() => ({