char-fork/llama.cpp

git clone https://git.t4t.associates/char-fork/llama.cpp

Aleksander Grygierui: Linting & Formatting scripts (#26819)92d1bb0c9

char/aliceai-t5-moe
2.5 KiB117 linesraw
1import { KeyboardKey } from '$lib/enums';
2
3/**
4 * Shared keyboard navigation state for the chat-form pickers: a highlighted
5 * row, a scroll trigger, and Arrow/Escape/Enter handling.
6 */
7export interface UsePickerNavigationOptions {
8	/** Gates all key handling. */
9	isOpen: () => boolean;
10	count: () => number;
11	/**
12	 * Resolve the row to highlight for a movement step, or -1 when no move
13	 * is possible. Defaults to plain wraparound across `count()`.
14	 */
15	step?: (from: number, dir: 1 | -1) => number;
16	onClose: () => void;
17	/** Called on Enter when `hoveredIndex` points at a selectable row. */
18	onSelect: (index: number) => void;
19}
20
21function wrapStep(from: number, dir: 1 | -1, count: number): number {
22	return dir === 1 ? (from + 1) % count : from <= 0 ? count - 1 : from - 1;
23}
24
25export function usePickerNavigation(opts: UsePickerNavigationOptions) {
26	let hoveredIndex = $state(-1);
27	let scrollTrigger = $state(0);
28
29	function resolve(from: number, dir: 1 | -1): number {
30		const n = opts.count();
31
32		if (n === 0) return -1;
33
34		if (opts.step) return opts.step(from, dir);
35
36		return wrapStep(from, dir, n);
37	}
38
39	function move(dir: 1 | -1) {
40		const next = resolve(hoveredIndex, dir);
41
42		if (next >= 0) {
43			hoveredIndex = next;
44			scrollTrigger++;
45		}
46	}
47
48	/** Reset the highlight without bumping the scroll trigger. */
49	function reset(index: number) {
50		hoveredIndex = index;
51	}
52
53	/** Bump the scroll trigger without moving the highlight. */
54	function bumpScroll() {
55		scrollTrigger++;
56	}
57
58	/** Mouse hover highlights a row but must NOT bump the scroll trigger. */
59	function setHover(index: number) {
60		hoveredIndex = index;
61	}
62
63	function handleKeydown(event: KeyboardEvent): boolean {
64		if (!opts.isOpen()) return false;
65
66		if (event.key === KeyboardKey.ESCAPE) {
67			event.preventDefault();
68			opts.onClose();
69
70			return true;
71		}
72
73		if (event.key === KeyboardKey.ARROW_DOWN) {
74			event.preventDefault();
75			move(1);
76
77			return true;
78		}
79
80		if (event.key === KeyboardKey.ARROW_UP) {
81			event.preventDefault();
82			move(-1);
83
84			return true;
85		}
86
87		if (event.key === KeyboardKey.ENTER) {
88			if (hoveredIndex >= 0 && hoveredIndex < opts.count()) {
89				event.preventDefault();
90				opts.onSelect(hoveredIndex);
91
92				return true;
93			}
94
95			// No selectable row - let the caller's Enter-to-submit run.
96			return false;
97		}
98
99		return false;
100	}
101
102	return {
103		bumpScroll,
104		handleKeydown,
105		get hoveredIndex() {
106			return hoveredIndex;
107		},
108		move,
109		reset,
110		get scrollTrigger() {
111			return scrollTrigger;
112		},
113		setHover
114	};
115}
116
117export type UsePickerNavigationReturn = ReturnType<typeof usePickerNavigation>;