(core) Enhance autocomplete and choice colors

Summary:
Choice columns can now add new choices directly
from the autocomplete menu. The autocomplete will
now highlight the first matching item, even if there are equally
ranked alternatives. No changes have been made to how the
autocomplete index is created, or how it scores items.

For choice and choice list columns, the filter menu will
now display values using their configured colors, similar to the
rest of the UI. Choice tokens throughout the UI now do a better
job of handling text overflow by showing an ellipsis whenever
there isn't enough space to show the full text of a choice.

Test Plan: Browser tests.

Reviewers: cyprien

Reviewed By: cyprien

Differential Revision: https://phab.getgrist.com/D2904
This commit is contained in:
George Gevoian
2021-07-15 08:50:28 -07:00
parent 997be24a21
commit 5b2666a88a
10 changed files with 350 additions and 178 deletions

View File

@@ -132,12 +132,10 @@ export class ACIndexImpl<Item extends ACItem> implements ACIndex<Item> {
const highlightFunc = highlightMatches.bind(null, searchWords);
// The best match is the first item. If it actually starts with the search text, AND has a
// strictly better score than other items, highlight it as a default selection. Otherwise, no
// item will be auto-selected.
// The best match is the first item. If any word in the item actually starts with the search
// text, highlight it as a default selection. Otherwise, no item will be auto-selected.
let selectIndex = -1;
if (items.length > 0 && items[0].cleanText.startsWith(cleanedSearchText) &&
(sortedMatches.length <= 1 || sortedMatches[1][1] < sortedMatches[0][1])) {
if (items.length > 0 && sortedMatches.length > 0 && startsWithText(items[0], cleanedSearchText)) {
selectIndex = 0;
}
return {items, highlightFunc, selectIndex};
@@ -248,3 +246,13 @@ function findCommonPrefixLength(text1: string, text2: string): number {
while (i < text1.length && text1[i] === text2[i]) { ++i; }
return i;
}
/**
* Checks whether `item` starts with `text`, or has any words that start with `text`.
*/
function startsWithText(item: ACItem, text: string): boolean {
if (item.cleanText.startsWith(text)) { return true; }
const words = item.cleanText.split(wordSepRegexp);
return words.some(w => w.startsWith(text));
}