From 51945706d26726018dd2dbf957c2ddac123f9e5c Mon Sep 17 00:00:00 2001 From: dev Date: Fri, 15 May 2026 13:24:31 +0200 Subject: [PATCH] Route Soma drawer scroll guard timer --- .../drawer/drawer-provider.svelte.ts | 30 +++++++++++++++---- 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/src/uix/soma/components/drawer/drawer-provider.svelte.ts b/src/uix/soma/components/drawer/drawer-provider.svelte.ts index ce92c08ee..da2574bd9 100644 --- a/src/uix/soma/components/drawer/drawer-provider.svelte.ts +++ b/src/uix/soma/components/drawer/drawer-provider.svelte.ts @@ -34,6 +34,7 @@ import { DRAWER_LANGS } from './langs'; import { drawerMorfo } from '../../../morfo/components/drawer'; import { type SomaRuntime, type SomaRuntimePart } from '$soma'; import type { SemaSignatureOverride } from '$uix/sema'; +import type { TimerHandle } from '$timer'; // ── Direction resolution ──────────────────────────────────────────────────── @@ -404,7 +405,7 @@ export class DrawerContentProvider { // Scroll-drag guard: cancel gesture if user scrolled recently private scrollDragBlocked = $state(false); - private scrollTimer: ReturnType | null = null; + private scrollTimer: TimerHandle | null = null; // Tracks whether the current pointer interaction has already fired // drag-start. Reset on release so the next gesture re-fires it. private wasDragging = $state(false); @@ -698,15 +699,21 @@ export class DrawerContentProvider { if (!el) return; const onScroll = () => { this.scrollDragBlocked = true; - if (this.scrollTimer) clearTimeout(this.scrollTimer); - this.scrollTimer = setTimeout(() => { - this.scrollDragBlocked = false; - }, this.provider.opts.scrollLockTimeout.current); + this.clearScrollTimer(); + this.scrollTimer = this.provider.soma.uix.timers.schedule( + this.scrollTimerKey, + this.provider.opts.scrollLockTimeout.current, + () => { + this.scrollTimer = null; + this.scrollDragBlocked = false; + }, + { replace: true, meta: { component: 'drawer', action: 'scroll-drag-guard' } } + ); }; el.addEventListener('scroll', onScroll, { passive: true, capture: true }); return () => { el.removeEventListener('scroll', onScroll, { capture: true }); - if (this.scrollTimer) clearTimeout(this.scrollTimer); + this.clearScrollTimer(); }; }); @@ -828,6 +835,17 @@ export class DrawerContentProvider { readonly isPresent = $derived.by(() => this.provider.contentPresence.isPresent); + private clearScrollTimer() { + if (this.scrollTimer) { + this.scrollTimer.cancel(); + this.scrollTimer = null; + } + } + + private get scrollTimerKey() { + return `soma:drawer:${this.opts.id.current}:scroll-drag-guard`; + } + // Escape for non-modal (Dismissal layer is disabled for non-modal) readonly onkeydown = (e: KeyboardEvent) => { if (