|
|
|
@ -34,6 +34,7 @@ import { DRAWER_LANGS } from './langs';
|
|
|
|
import { drawerMorfo } from '../../../morfo/components/drawer';
|
|
|
|
import { drawerMorfo } from '../../../morfo/components/drawer';
|
|
|
|
import { type SomaRuntime, type SomaRuntimePart } from '$soma';
|
|
|
|
import { type SomaRuntime, type SomaRuntimePart } from '$soma';
|
|
|
|
import type { SemaSignatureOverride } from '$uix/sema';
|
|
|
|
import type { SemaSignatureOverride } from '$uix/sema';
|
|
|
|
|
|
|
|
import type { TimerHandle } from '$timer';
|
|
|
|
|
|
|
|
|
|
|
|
// ── Direction resolution ────────────────────────────────────────────────────
|
|
|
|
// ── Direction resolution ────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
|
|
@ -404,7 +405,7 @@ export class DrawerContentProvider {
|
|
|
|
|
|
|
|
|
|
|
|
// Scroll-drag guard: cancel gesture if user scrolled recently
|
|
|
|
// Scroll-drag guard: cancel gesture if user scrolled recently
|
|
|
|
private scrollDragBlocked = $state(false);
|
|
|
|
private scrollDragBlocked = $state(false);
|
|
|
|
private scrollTimer: ReturnType<typeof setTimeout> | null = null;
|
|
|
|
private scrollTimer: TimerHandle | null = null;
|
|
|
|
// Tracks whether the current pointer interaction has already fired
|
|
|
|
// Tracks whether the current pointer interaction has already fired
|
|
|
|
// drag-start. Reset on release so the next gesture re-fires it.
|
|
|
|
// drag-start. Reset on release so the next gesture re-fires it.
|
|
|
|
private wasDragging = $state(false);
|
|
|
|
private wasDragging = $state(false);
|
|
|
|
@ -698,15 +699,21 @@ export class DrawerContentProvider {
|
|
|
|
if (!el) return;
|
|
|
|
if (!el) return;
|
|
|
|
const onScroll = () => {
|
|
|
|
const onScroll = () => {
|
|
|
|
this.scrollDragBlocked = true;
|
|
|
|
this.scrollDragBlocked = true;
|
|
|
|
if (this.scrollTimer) clearTimeout(this.scrollTimer);
|
|
|
|
this.clearScrollTimer();
|
|
|
|
this.scrollTimer = setTimeout(() => {
|
|
|
|
this.scrollTimer = this.provider.soma.uix.timers.schedule(
|
|
|
|
|
|
|
|
this.scrollTimerKey,
|
|
|
|
|
|
|
|
this.provider.opts.scrollLockTimeout.current,
|
|
|
|
|
|
|
|
() => {
|
|
|
|
|
|
|
|
this.scrollTimer = null;
|
|
|
|
this.scrollDragBlocked = false;
|
|
|
|
this.scrollDragBlocked = false;
|
|
|
|
}, this.provider.opts.scrollLockTimeout.current);
|
|
|
|
},
|
|
|
|
|
|
|
|
{ replace: true, meta: { component: 'drawer', action: 'scroll-drag-guard' } }
|
|
|
|
|
|
|
|
);
|
|
|
|
};
|
|
|
|
};
|
|
|
|
el.addEventListener('scroll', onScroll, { passive: true, capture: true });
|
|
|
|
el.addEventListener('scroll', onScroll, { passive: true, capture: true });
|
|
|
|
return () => {
|
|
|
|
return () => {
|
|
|
|
el.removeEventListener('scroll', onScroll, { capture: true });
|
|
|
|
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);
|
|
|
|
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)
|
|
|
|
// Escape for non-modal (Dismissal layer is disabled for non-modal)
|
|
|
|
readonly onkeydown = (e: KeyboardEvent) => {
|
|
|
|
readonly onkeydown = (e: KeyboardEvent) => {
|
|
|
|
if (
|
|
|
|
if (
|
|
|
|
|