Route Soma typeahead resets through timers

active-uix
dev 5 months ago
parent 51945706d2
commit 66a943093b

@ -11,6 +11,7 @@ import type { GridListSelectionMode } from './types';
import { gridListMorfo } from '../../../morfo/components/grid-list';
import type { SomaRuntime, SomaRuntimePart } from '../../runtime.svelte';
import type { TimerHandle } from '$timer';
const attrs = createAttrs(gridListMorfo);
@ -55,7 +56,7 @@ export class GridListProvider {
readonly field = FieldProvider.get();
private typeaheadBuffer = '';
private typeaheadTimer: ReturnType<typeof setTimeout> | null = null;
private typeaheadTimer: TimerHandle | null = null;
/** Anchor for Shift+Click range selection. */
private anchor: string | null = null;
@ -71,9 +72,7 @@ export class GridListProvider {
});
$effect(() => {
return () => {
if (this.typeaheadTimer) clearTimeout(this.typeaheadTimer);
};
return () => this.clearTypeaheadTimer();
});
}
@ -367,10 +366,16 @@ export class GridListProvider {
private handleTypeahead(char: string, fromIndex: number) {
this.typeaheadBuffer += char.toLowerCase();
if (this.typeaheadTimer) clearTimeout(this.typeaheadTimer);
this.typeaheadTimer = setTimeout(() => {
this.clearTypeaheadTimer();
this.typeaheadTimer = this.soma.uix.timers.schedule(
this.typeaheadTimerKey,
this.opts.typeaheadTimeout.current,
() => {
this.typeaheadTimer = null;
this.typeaheadBuffer = '';
}, this.opts.typeaheadTimeout.current);
},
{ replace: true, meta: { component: 'grid-list', action: 'typeahead-reset' } }
);
const rows = this.getRows();
if (rows.length === 0) return;
@ -390,6 +395,17 @@ export class GridListProvider {
}
}
private clearTypeaheadTimer() {
if (this.typeaheadTimer) {
this.typeaheadTimer.cancel();
this.typeaheadTimer = null;
}
}
private get typeaheadTimerKey() {
return `soma:grid-list:${this.opts.id.current}:typeahead`;
}
handleRowClick(value: string, e: SomaMouseEvent<HTMLElement>) {
if (this.isDisabled || this.isReadonly) return;
const mode =

@ -17,6 +17,7 @@ import type { ListboxSelectionMode } from './types';
import { listboxMorfo } from '../../../morfo/components/listbox';
import type { SomaRuntime, SomaRuntimePart } from '../../runtime.svelte';
import type { TimerHandle } from '$timer';
const attrs = createAttrs(listboxMorfo);
@ -64,7 +65,7 @@ export class ListboxProvider {
focused = $state(false);
private typeaheadBuffer = '';
private typeaheadTimer: ReturnType<typeof setTimeout> | null = null;
private typeaheadTimer: TimerHandle | null = null;
private constructor(opts: ListboxOpts) {
this.opts = opts;
@ -78,9 +79,7 @@ export class ListboxProvider {
});
$effect(() => {
return () => {
if (this.typeaheadTimer) clearTimeout(this.typeaheadTimer);
};
return () => this.clearTypeaheadTimer();
});
}
@ -261,10 +260,16 @@ export class ListboxProvider {
private handleTypeahead(char: string, fromIndex: number) {
this.typeaheadBuffer += char.toLowerCase();
if (this.typeaheadTimer) clearTimeout(this.typeaheadTimer);
this.typeaheadTimer = setTimeout(() => {
this.clearTypeaheadTimer();
this.typeaheadTimer = this.soma.uix.timers.schedule(
this.typeaheadTimerKey,
this.opts.typeaheadTimeout.current,
() => {
this.typeaheadTimer = null;
this.typeaheadBuffer = '';
}, this.opts.typeaheadTimeout.current);
},
{ replace: true, meta: { component: 'listbox', action: 'typeahead-reset' } }
);
const items = this.getItems();
if (items.length === 0) return;
@ -284,6 +289,17 @@ export class ListboxProvider {
}
}
private clearTypeaheadTimer() {
if (this.typeaheadTimer) {
this.typeaheadTimer.cancel();
this.typeaheadTimer = null;
}
}
private get typeaheadTimerKey() {
return `soma:listbox:${this.opts.id.current}:typeahead`;
}
handleItemClick(value: string, e: SomaMouseEvent<HTMLElement>) {
if (this.isDisabled || this.isReadonly) return;
if (this.opts.selectionMode.current === 'multiple') {

@ -16,6 +16,7 @@ import type { TreeGridSelectionMode } from './types';
import { treeGridMorfo } from '../../../morfo/components/tree-grid';
import type { SomaRuntime, SomaRuntimePart } from '../../runtime.svelte';
import type { TimerHandle } from '$timer';
const attrs = createAttrs(treeGridMorfo);
@ -59,7 +60,7 @@ export class TreeGridProvider {
}
private typeaheadBuffer = '';
private typeaheadTimer: ReturnType<typeof setTimeout> | null = null;
private typeaheadTimer: TimerHandle | null = null;
private anchor: string | null = null;
private constructor(opts: TreeGridOpts) {
@ -73,9 +74,7 @@ export class TreeGridProvider {
context: TreeGridProvider.ctx
});
$effect(() => {
return () => {
if (this.typeaheadTimer) clearTimeout(this.typeaheadTimer);
};
return () => this.clearTypeaheadTimer();
});
}
@ -380,10 +379,16 @@ export class TreeGridProvider {
private handleTypeahead(char: string, fromIndex: number) {
this.typeaheadBuffer += char.toLowerCase();
if (this.typeaheadTimer) clearTimeout(this.typeaheadTimer);
this.typeaheadTimer = setTimeout(() => {
this.clearTypeaheadTimer();
this.typeaheadTimer = this.soma.uix.timers.schedule(
this.typeaheadTimerKey,
this.opts.typeaheadTimeout.current,
() => {
this.typeaheadTimer = null;
this.typeaheadBuffer = '';
}, this.opts.typeaheadTimeout.current);
},
{ replace: true, meta: { component: 'tree-grid', action: 'typeahead-reset' } }
);
const rows = this.getVisibleRows();
if (rows.length === 0) return;
@ -403,6 +408,17 @@ export class TreeGridProvider {
}
}
private clearTypeaheadTimer() {
if (this.typeaheadTimer) {
this.typeaheadTimer.cancel();
this.typeaheadTimer = null;
}
}
private get typeaheadTimerKey() {
return `soma:tree-grid:${this.opts.id.current}:typeahead`;
}
handleRowClick(value: string, e: SomaMouseEvent<HTMLElement>) {
if (this.opts.disabled.current || this.opts.readonly.current) return;
const mode =

@ -9,6 +9,7 @@ import { TREE_VIEW_LANGS } from './langs';
import { treeViewMorfo } from '../../../morfo/components/tree-view';
import type { SomaRuntime, SomaRuntimePart } from '../../runtime.svelte';
import type { TimerHandle } from '$timer';
const attrs = createAttrs(treeViewMorfo);
@ -68,7 +69,7 @@ export class TreeViewProvider {
// Typeahead
private typeaheadBuffer = '';
private typeaheadTimer: ReturnType<typeof setTimeout> | null = null;
private typeaheadTimer: TimerHandle | null = null;
private constructor(opts: TreeViewOpts) {
this.opts = opts;
@ -83,12 +84,7 @@ export class TreeViewProvider {
// Cleanup typeahead timer on unmount
$effect(() => {
return () => {
if (this.typeaheadTimer) {
clearTimeout(this.typeaheadTimer);
this.typeaheadTimer = null;
}
};
return () => this.clearTypeaheadTimer();
});
}
@ -170,10 +166,16 @@ export class TreeViewProvider {
if (!this.opts.typeahead.current) return;
this.typeaheadBuffer += char.toLowerCase();
if (this.typeaheadTimer) clearTimeout(this.typeaheadTimer);
this.typeaheadTimer = setTimeout(() => {
this.clearTypeaheadTimer();
this.typeaheadTimer = this.soma.uix.timers.schedule(
this.typeaheadTimerKey,
500,
() => {
this.typeaheadTimer = null;
this.typeaheadBuffer = '';
}, 500);
},
{ replace: true, meta: { component: 'tree-view', action: 'typeahead-reset' } }
);
const items = this.getVisibleItems();
const match = items.find((el) => {
@ -183,6 +185,17 @@ export class TreeViewProvider {
if (match) this.focusItem(match);
}
private clearTypeaheadTimer() {
if (this.typeaheadTimer) {
this.typeaheadTimer.cancel();
this.typeaheadTimer = null;
}
}
private get typeaheadTimerKey() {
return `soma:tree-view:${this.opts.id.current}:typeahead`;
}
// ── Keyboard (root-level) ────────────────────────────────────────────────
private handleExpandKey(activeEl: HTMLElement, items: HTMLElement[], currentIndex: number) {

Loading…
Cancel
Save

Powered by TurnKey Linux.