2025-03-04 04:17:38 +00:00
|
|
|
import { HistorySuggestion } from '../../utils/suggestions';
|
|
|
|
import { InputHistory } from './history';
|
|
|
|
import { HistoryStore } from './store';
|
|
|
|
import { AutocompletableInput } from '../input';
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Stores a set of histories identified by their unique IDs.
|
|
|
|
*/
|
|
|
|
class InputHistoriesPool {
|
|
|
|
private histories = new Map<string, InputHistory>();
|
|
|
|
|
|
|
|
load(historyId: string): InputHistory {
|
|
|
|
const existing = this.histories.get(historyId);
|
|
|
|
|
|
|
|
if (existing) {
|
|
|
|
return existing;
|
|
|
|
}
|
|
|
|
|
|
|
|
const store = new HistoryStore(historyId);
|
|
|
|
const newHistory = new InputHistory(store);
|
|
|
|
this.histories.set(historyId, newHistory);
|
|
|
|
|
|
|
|
return newHistory;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const histories = new InputHistoriesPool();
|
|
|
|
|
|
|
|
export function listen() {
|
|
|
|
// Only load the history for the input element when it gets focused.
|
|
|
|
document.addEventListener('focusin', event => {
|
|
|
|
const input = AutocompletableInput.fromElement(event.target);
|
|
|
|
|
|
|
|
if (!input?.historyId) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
histories.load(input.historyId);
|
|
|
|
});
|
|
|
|
|
2025-03-14 23:10:06 +00:00
|
|
|
document.addEventListener('submit', event => {
|
|
|
|
if (!(event.target instanceof HTMLFormElement)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const input = [...event.target.elements]
|
|
|
|
.map(elem => AutocompletableInput.fromElement(elem))
|
|
|
|
.find(it => it !== null && it.hasHistory());
|
|
|
|
|
|
|
|
if (!input) {
|
|
|
|
return;
|
|
|
|
}
|
2025-03-04 04:17:38 +00:00
|
|
|
|
2025-03-14 23:10:06 +00:00
|
|
|
histories.load(input.historyId).write(input.snapshot.trimmedValue);
|
2025-03-04 04:17:38 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns suggestions based on history for the input. Unless the `limit` is
|
|
|
|
* specified as an argument, it will return the maximum number of suggestions
|
|
|
|
* allowed by the input.
|
|
|
|
*/
|
|
|
|
export function listSuggestions(input: AutocompletableInput, limit?: number): HistorySuggestion[] {
|
|
|
|
if (!input.hasHistory()) {
|
|
|
|
return [];
|
|
|
|
}
|
|
|
|
|
|
|
|
const value = input.snapshot.trimmedValue.toLowerCase();
|
|
|
|
|
|
|
|
return histories
|
|
|
|
.load(input.historyId)
|
|
|
|
.listSuggestions(value, limit ?? input.maxSuggestions)
|
|
|
|
.map(content => new HistorySuggestion(content, value.length));
|
|
|
|
}
|