pixelize-design-library 2.4.2-beta.63 → 2.4.2-beta.65
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +130 -8
- package/COMPONENT-GOTCHAS.md +63 -7
- package/DESIGN-GUIDE.md +8 -3
- package/dist/Components/Button/Button.styles.js +7 -2
- package/dist/Components/CopyButton/CopyButton.d.ts +3 -1
- package/dist/Components/CopyButton/CopyButton.js +2 -2
- package/dist/Components/Drawer/Drawer.d.ts +1 -1
- package/dist/Components/Drawer/Drawer.js +6 -2
- package/dist/Components/Drawer/DrawerProps.d.ts +4 -0
- package/dist/Components/Dropdown/DropDown.js +2 -9
- package/dist/Components/FilePreview/FilePreview.js +2 -1
- package/dist/Components/FileUploader/FileUploader.js +4 -0
- package/dist/Components/FileUploader/FileUploaderProps.d.ts +1 -1
- package/dist/Components/FormDrawer/FormDrawer.d.ts +1 -1
- package/dist/Components/FormDrawer/FormDrawer.js +3 -3
- package/dist/Components/FormDrawer/FormDrawerProps.d.ts +2 -0
- package/dist/Components/Input/TextInput.styles.js +10 -6
- package/dist/Components/KanbanBoard/KanbanBoard.js +6 -5
- package/dist/Components/Modal/dialogNaming.d.ts +8 -0
- package/dist/Components/Modal/dialogNaming.js +21 -0
- package/dist/Components/NavLauncher/LauncherTabs.js +2 -2
- package/dist/Components/NavLauncher/NavLauncher.d.ts +1 -1
- package/dist/Components/NavLauncher/NavLauncher.js +257 -47
- package/dist/Components/NavLauncher/NavLauncherProps.d.ts +79 -3
- package/dist/Components/NavLauncher/ScopeBar.d.ts +14 -0
- package/dist/Components/NavLauncher/ScopeBar.js +137 -0
- package/dist/Components/NavLauncher/engine/distance.d.ts +4 -0
- package/dist/Components/NavLauncher/engine/distance.js +41 -0
- package/dist/Components/NavLauncher/engine/engine.d.ts +84 -0
- package/dist/Components/NavLauncher/engine/engine.js +471 -0
- package/dist/Components/NavLauncher/engine/fold.d.ts +15 -0
- package/dist/Components/NavLauncher/engine/fold.js +83 -0
- package/dist/Components/NavLauncher/engine/index.d.ts +21 -0
- package/dist/Components/NavLauncher/engine/index.js +17 -0
- package/dist/Components/NavLauncher/launcherParts.d.ts +2 -0
- package/dist/Components/NavLauncher/launcherParts.js +11 -7
- package/dist/Components/NavLauncher/match.d.ts +13 -2
- package/dist/Components/NavLauncher/match.js +26 -12
- package/dist/Components/NavLauncher/searchLayout.d.ts +60 -0
- package/dist/Components/NavLauncher/searchLayout.js +108 -0
- package/dist/Components/NavLauncher/spotlight.d.ts +39 -0
- package/dist/Components/NavLauncher/spotlight.js +202 -0
- package/dist/Components/NavLauncher/spotlightParts.d.ts +49 -0
- package/dist/Components/NavLauncher/spotlightParts.js +108 -0
- package/dist/Components/NavigationBar/NavigationBar.js +2 -1
- package/dist/Components/OrgSwitcher/OrgSwitcher.js +2 -4
- package/dist/Components/ProfilePhotoViewer/ProfilePhotoViewer.js +6 -5
- package/dist/Components/ScrollToTop/ScrollToTop.js +4 -3
- package/dist/Components/SearchSelect/SearchSelect.js +4 -16
- package/dist/Components/Select/SelectPopup.js +1 -3
- package/dist/Components/Select/optionRowInk.d.ts +12 -0
- package/dist/Components/Select/optionRowInk.js +10 -1
- package/dist/Components/SelectSearch/SelectSearch.js +1 -10
- package/dist/Components/Table/Table.js +3 -2
- package/dist/Components/Table/TableProps.d.ts +1 -1
- package/dist/Components/Table/components/TableBody.js +9 -1
- package/dist/Components/Table/components/TableHeader.js +9 -2
- package/dist/Components/Table/components/TableLoading.d.ts +4 -1
- package/dist/Components/Table/components/TableLoading.js +13 -6
- package/dist/Components/Table/filters/CompactSelect.js +1 -10
- package/dist/Components/Table/variants/TableVariantContext.d.ts +1 -1
- package/dist/Components/Table/variants/TableVariantContext.js +3 -3
- package/dist/Components/WizardDialog/WizardDialog.d.ts +1 -1
- package/dist/Components/WizardDialog/WizardDialog.js +15 -3
- package/dist/Components/WizardDialog/WizardDialogProps.d.ts +5 -3
- package/dist/Components/WorkspaceWindow/WorkspaceTrayPreview.js +4 -0
- package/dist/Components/WorkspaceWindow/WorkspaceWindow.d.ts +2 -2
- package/dist/Components/WorkspaceWindow/WorkspaceWindow.js +26 -18
- package/dist/Components/WorkspaceWindow/WorkspaceWindowProps.d.ts +38 -8
- package/dist/Theme/chakra/Menu.styles.d.ts +8 -0
- package/dist/Theme/chakra/Menu.styles.js +7 -0
- package/dist/Theme/chakra/componentStyles.d.ts +8 -0
- package/dist/Theme/chakra/componentStyles.js +2 -2
- package/dist/Theme/chakra/ringShadow.d.ts +3 -0
- package/dist/Theme/chakra/ringShadow.js +7 -0
- package/dist/Theme/tokens/builders/accentText.d.ts +2 -0
- package/dist/Theme/tokens/builders/accentText.js +7 -1
- package/dist/Theme/tokens/builders/buildDarkPalette.d.ts +1 -1
- package/dist/Theme/tokens/builders/buildDarkPalette.js +5 -5
- package/dist/Theme/tokens/builders/filledSurface.d.ts +5 -1
- package/dist/Theme/tokens/builders/filledSurface.js +17 -4
- package/dist/Theme/tokens/builders/planeStep.d.ts +1 -0
- package/dist/Theme/tokens/builders/planeStep.js +5 -4
- package/dist/Utils/table.js +2 -2
- package/dist/esm/Components/Button/Button.styles.js +8 -3
- package/dist/esm/Components/CopyButton/CopyButton.js +2 -2
- package/dist/esm/Components/Drawer/Drawer.js +6 -2
- package/dist/esm/Components/Dropdown/DropDown.js +2 -9
- package/dist/esm/Components/FilePreview/FilePreview.js +3 -2
- package/dist/esm/Components/FileUploader/FileUploader.js +4 -0
- package/dist/esm/Components/FormDrawer/FormDrawer.js +3 -3
- package/dist/esm/Components/Input/TextInput.styles.js +10 -6
- package/dist/esm/Components/KanbanBoard/KanbanBoard.js +6 -5
- package/dist/esm/Components/Modal/dialogNaming.js +18 -0
- package/dist/esm/Components/NavLauncher/LauncherTabs.js +2 -2
- package/dist/esm/Components/NavLauncher/NavLauncher.js +259 -49
- package/dist/esm/Components/NavLauncher/ScopeBar.js +134 -0
- package/dist/esm/Components/NavLauncher/engine/distance.js +37 -0
- package/dist/esm/Components/NavLauncher/engine/engine.js +458 -0
- package/dist/esm/Components/NavLauncher/engine/fold.js +74 -0
- package/dist/esm/Components/NavLauncher/engine/index.js +14 -0
- package/dist/esm/Components/NavLauncher/launcherParts.js +10 -6
- package/dist/esm/Components/NavLauncher/match.js +25 -12
- package/dist/esm/Components/NavLauncher/searchLayout.js +100 -0
- package/dist/esm/Components/NavLauncher/spotlight.js +194 -0
- package/dist/esm/Components/NavLauncher/spotlightParts.js +95 -0
- package/dist/esm/Components/NavigationBar/NavigationBar.js +2 -1
- package/dist/esm/Components/OrgSwitcher/OrgSwitcher.js +2 -4
- package/dist/esm/Components/ProfilePhotoViewer/ProfilePhotoViewer.js +7 -6
- package/dist/esm/Components/ScrollToTop/ScrollToTop.js +5 -4
- package/dist/esm/Components/SearchSelect/SearchSelect.js +6 -18
- package/dist/esm/Components/Select/SelectPopup.js +2 -4
- package/dist/esm/Components/Select/optionRowInk.js +7 -0
- package/dist/esm/Components/SelectSearch/SelectSearch.js +2 -11
- package/dist/esm/Components/Table/Table.js +4 -3
- package/dist/esm/Components/Table/components/TableBody.js +10 -2
- package/dist/esm/Components/Table/components/TableHeader.js +10 -3
- package/dist/esm/Components/Table/components/TableLoading.js +10 -6
- package/dist/esm/Components/Table/filters/CompactSelect.js +2 -11
- package/dist/esm/Components/Table/variants/TableVariantContext.js +3 -3
- package/dist/esm/Components/WizardDialog/WizardDialog.js +15 -3
- package/dist/esm/Components/WorkspaceWindow/WorkspaceTrayPreview.js +4 -0
- package/dist/esm/Components/WorkspaceWindow/WorkspaceWindow.js +28 -20
- package/dist/esm/Theme/chakra/Menu.styles.js +7 -0
- package/dist/esm/Theme/chakra/componentStyles.js +2 -2
- package/dist/esm/Theme/chakra/ringShadow.js +3 -0
- package/dist/esm/Theme/tokens/builders/accentText.js +5 -0
- package/dist/esm/Theme/tokens/builders/buildDarkPalette.js +5 -5
- package/dist/esm/Theme/tokens/builders/filledSurface.js +18 -5
- package/dist/esm/Theme/tokens/builders/planeStep.js +3 -3
- package/dist/esm/Utils/table.js +2 -2
- package/dist/esm/index.js +6 -5
- package/dist/index.d.ts +10 -8
- package/dist/index.js +14 -6
- package/package.json +1 -1
|
@@ -0,0 +1,471 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.tokenize = exports.splitWords = exports.foldText = exports.editDistance = exports.usageBoosts = exports.highlightRanges = exports.matchesQuery = exports.createMatcher = exports.searchDocuments = exports.searchIndex = exports.createSearchIndex = void 0;
|
|
4
|
+
const distance_1 = require("./distance");
|
|
5
|
+
Object.defineProperty(exports, "editDistance", { enumerable: true, get: function () { return distance_1.editDistance; } });
|
|
6
|
+
const fold_1 = require("./fold");
|
|
7
|
+
Object.defineProperty(exports, "foldText", { enumerable: true, get: function () { return fold_1.foldText; } });
|
|
8
|
+
Object.defineProperty(exports, "splitWords", { enumerable: true, get: function () { return fold_1.splitWords; } });
|
|
9
|
+
Object.defineProperty(exports, "tokenize", { enumerable: true, get: function () { return fold_1.tokenize; } });
|
|
10
|
+
const KIND_SCORE = {
|
|
11
|
+
exact: 100,
|
|
12
|
+
prefix: 88,
|
|
13
|
+
word: 78,
|
|
14
|
+
"word-prefix": 68,
|
|
15
|
+
initialism: 60,
|
|
16
|
+
substring: 46,
|
|
17
|
+
fuzzy: 34,
|
|
18
|
+
subsequence: 16,
|
|
19
|
+
};
|
|
20
|
+
const COMPLETENESS = 6;
|
|
21
|
+
const SYNONYM_FACTOR = 0.92;
|
|
22
|
+
const STEM_PENALTY = 1;
|
|
23
|
+
const MAX_ALTERNATIVES = 12;
|
|
24
|
+
const UNBOUNDED_SLACK = 32;
|
|
25
|
+
const TAMIL_FINAL_MA = "ம்";
|
|
26
|
+
const WORD_RE = /[\p{L}\p{N}\p{M}]+/gu;
|
|
27
|
+
const charBit = (code) => {
|
|
28
|
+
if (code >= 97 && code <= 122)
|
|
29
|
+
return 1 << (code - 97);
|
|
30
|
+
return code >= 48 && code <= 57 ? 1 << 26 : 1 << (27 + (code % 4));
|
|
31
|
+
};
|
|
32
|
+
const maskOf = (text) => {
|
|
33
|
+
let mask = 0;
|
|
34
|
+
for (let i = 0; i < text.length; i += 1)
|
|
35
|
+
mask |= charBit(text.charCodeAt(i));
|
|
36
|
+
return mask;
|
|
37
|
+
};
|
|
38
|
+
const missingChars = (token, field) => {
|
|
39
|
+
let rest = token & ~field;
|
|
40
|
+
let count = 0;
|
|
41
|
+
for (; rest; count += 1)
|
|
42
|
+
rest &= rest - 1;
|
|
43
|
+
return count;
|
|
44
|
+
};
|
|
45
|
+
const maxEdits = (size) => (size >= 8 ? 2 : 1);
|
|
46
|
+
const writtenSize = (text, marked) => marked ? (0, fold_1.letters)(text).length : text.length;
|
|
47
|
+
const indexField = ({ name, text, weight = 1, }) => {
|
|
48
|
+
var _a;
|
|
49
|
+
const folded = (0, fold_1.foldText)(text).trim();
|
|
50
|
+
const words = [];
|
|
51
|
+
const starts = [];
|
|
52
|
+
for (const match of folded.matchAll(WORD_RE)) {
|
|
53
|
+
words.push(match[0]);
|
|
54
|
+
starts.push((_a = match.index) !== null && _a !== void 0 ? _a : 0);
|
|
55
|
+
}
|
|
56
|
+
const letterWords = (0, fold_1.hasMarks)(folded) ? words.map(fold_1.letters) : null;
|
|
57
|
+
return {
|
|
58
|
+
name,
|
|
59
|
+
text,
|
|
60
|
+
weight,
|
|
61
|
+
folded,
|
|
62
|
+
compact: words.join(""),
|
|
63
|
+
words,
|
|
64
|
+
starts,
|
|
65
|
+
initials: (letterWords !== null && letterWords !== void 0 ? letterWords : words).map((w) => w[0]).join(""),
|
|
66
|
+
mask: maskOf(folded),
|
|
67
|
+
letterWords,
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
const createSearchIndex = (documents) => {
|
|
71
|
+
const indexed = documents.map((doc, index) => {
|
|
72
|
+
const fields = doc.fields.filter((f) => f.text).map(indexField);
|
|
73
|
+
return {
|
|
74
|
+
id: doc.id,
|
|
75
|
+
index,
|
|
76
|
+
fields,
|
|
77
|
+
mask: fields.reduce((mask, f) => mask | f.mask, 0),
|
|
78
|
+
};
|
|
79
|
+
});
|
|
80
|
+
return { size: indexed.length, documents: indexed };
|
|
81
|
+
};
|
|
82
|
+
exports.createSearchIndex = createSearchIndex;
|
|
83
|
+
const startsLikely = (token, word) => word[0][0] === token[0][0] || (word[0] === token[1] && word[1] === token[0]);
|
|
84
|
+
const fuzzyScore = (token, words) => {
|
|
85
|
+
const max = maxEdits(token.length);
|
|
86
|
+
let best = 0;
|
|
87
|
+
for (let w = 0; w < words.length; w += 1) {
|
|
88
|
+
const word = words[w];
|
|
89
|
+
if (!startsLikely(token, word))
|
|
90
|
+
continue;
|
|
91
|
+
if (Math.abs(word.length - token.length) <= max) {
|
|
92
|
+
const d = (0, distance_1.editDistance)(token, word, max);
|
|
93
|
+
if (d <= max)
|
|
94
|
+
best = Math.max(best, KIND_SCORE.fuzzy - 8 * (d - 1));
|
|
95
|
+
}
|
|
96
|
+
if (token.length < 5 || best >= KIND_SCORE.fuzzy)
|
|
97
|
+
continue;
|
|
98
|
+
for (let len = token.length - 1; len <= token.length + 1; len += 1) {
|
|
99
|
+
if (len >= word.length)
|
|
100
|
+
break;
|
|
101
|
+
const d = (0, distance_1.editDistance)(token, word.slice(0, len), max);
|
|
102
|
+
if (d <= max)
|
|
103
|
+
best = Math.max(best, KIND_SCORE.fuzzy - 4 - 8 * (d - 1));
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return best;
|
|
107
|
+
};
|
|
108
|
+
const subsequenceOf = (need, have) => {
|
|
109
|
+
if (have.length <= need.length || have[0] !== need[0])
|
|
110
|
+
return null;
|
|
111
|
+
const positions = [0];
|
|
112
|
+
for (let i = 1, at = 1; i < need.length; i += 1) {
|
|
113
|
+
const next = have.indexOf(need[i], at);
|
|
114
|
+
if (next < 0)
|
|
115
|
+
return null;
|
|
116
|
+
positions.push(next);
|
|
117
|
+
at = next + 1;
|
|
118
|
+
}
|
|
119
|
+
return positions;
|
|
120
|
+
};
|
|
121
|
+
const offsetIn = (have, index) => typeof have === "string" ? index : have.slice(0, index).join("").length;
|
|
122
|
+
const subsequenceAt = (token, words, starts, marked) => {
|
|
123
|
+
const need = marked ? (0, fold_1.letters)(token) : token;
|
|
124
|
+
for (let k = 0; k < words.length; k += 1) {
|
|
125
|
+
const have = marked ? (0, fold_1.letters)(words[k]) : words[k];
|
|
126
|
+
const positions = subsequenceOf(need, have);
|
|
127
|
+
if (positions)
|
|
128
|
+
return positions.map((p) => starts[k] + offsetIn(have, p));
|
|
129
|
+
}
|
|
130
|
+
return null;
|
|
131
|
+
};
|
|
132
|
+
const fuzzyOnly = (token, field, floor) => {
|
|
133
|
+
var _a, _b;
|
|
134
|
+
if (KIND_SCORE.fuzzy < floor)
|
|
135
|
+
return null;
|
|
136
|
+
const score = fuzzyScore((_a = token.letters) !== null && _a !== void 0 ? _a : token.text, (_b = field.letterWords) !== null && _b !== void 0 ? _b : field.words);
|
|
137
|
+
return score > 0 ? { kind: "fuzzy", base: score } : null;
|
|
138
|
+
};
|
|
139
|
+
const matchToken = (tokenInfo, field, floor) => {
|
|
140
|
+
var _a, _b;
|
|
141
|
+
const { text: token, mask, edits, slack } = tokenInfo;
|
|
142
|
+
const missing = missingChars(mask, field.mask);
|
|
143
|
+
if (missing > 0)
|
|
144
|
+
return missing <= slack ? fuzzyOnly(tokenInfo, field, floor) : null;
|
|
145
|
+
const ratio = (COMPLETENESS * token.length) / Math.max(field.folded.length, token.length);
|
|
146
|
+
if (field.folded === token)
|
|
147
|
+
return { kind: "exact", base: KIND_SCORE.exact + COMPLETENESS };
|
|
148
|
+
if (field.folded.startsWith(token))
|
|
149
|
+
return { kind: "prefix", base: KIND_SCORE.prefix + ratio };
|
|
150
|
+
if (KIND_SCORE.word + COMPLETENESS < floor)
|
|
151
|
+
return null;
|
|
152
|
+
let isWordPrefix = false;
|
|
153
|
+
const { words } = field;
|
|
154
|
+
for (let w = 0; w < words.length; w += 1) {
|
|
155
|
+
if (words[w] === token)
|
|
156
|
+
return { kind: "word", base: KIND_SCORE.word + ratio };
|
|
157
|
+
if (words[w].startsWith(token))
|
|
158
|
+
isWordPrefix = true;
|
|
159
|
+
}
|
|
160
|
+
if (isWordPrefix)
|
|
161
|
+
return { kind: "word-prefix", base: KIND_SCORE["word-prefix"] + ratio };
|
|
162
|
+
if (token.length < 2 || KIND_SCORE.initialism < floor)
|
|
163
|
+
return null;
|
|
164
|
+
if (field.words.length >= 2 && field.initials.startsWith(token)) {
|
|
165
|
+
return { kind: "initialism", base: KIND_SCORE.initialism };
|
|
166
|
+
}
|
|
167
|
+
if (field.folded.includes(token) || field.compact.includes(token)) {
|
|
168
|
+
return { kind: "substring", base: KIND_SCORE.substring };
|
|
169
|
+
}
|
|
170
|
+
if (tokenInfo.exact)
|
|
171
|
+
return null;
|
|
172
|
+
if (edits > 0) {
|
|
173
|
+
const match = fuzzyOnly(tokenInfo, field, floor);
|
|
174
|
+
if (match)
|
|
175
|
+
return match;
|
|
176
|
+
}
|
|
177
|
+
if (KIND_SCORE.subsequence < floor)
|
|
178
|
+
return null;
|
|
179
|
+
const need = (_a = tokenInfo.letters) !== null && _a !== void 0 ? _a : token;
|
|
180
|
+
const lists = (_b = field.letterWords) !== null && _b !== void 0 ? _b : field.words;
|
|
181
|
+
return lists.some((have) => subsequenceOf(need, have))
|
|
182
|
+
? { kind: "subsequence", base: KIND_SCORE.subsequence }
|
|
183
|
+
: null;
|
|
184
|
+
};
|
|
185
|
+
const reachable = (token, doc) => missingChars(token.mask, doc.mask) <= token.slack ||
|
|
186
|
+
(token.stem !== null && missingChars(token.stem.mask, doc.mask) === 0);
|
|
187
|
+
const scoreTokens = (doc, alt) => {
|
|
188
|
+
const { tokens } = alt;
|
|
189
|
+
const { fields } = doc;
|
|
190
|
+
for (let t = 0; t < tokens.length; t += 1) {
|
|
191
|
+
if (!reachable(tokens[t], doc))
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
194
|
+
let total = 0;
|
|
195
|
+
const matches = [];
|
|
196
|
+
for (let t = 0; t < tokens.length; t += 1) {
|
|
197
|
+
const token = tokens[t];
|
|
198
|
+
let best = 0;
|
|
199
|
+
let found = null;
|
|
200
|
+
for (let f = 0; f < fields.length; f += 1) {
|
|
201
|
+
const field = fields[f];
|
|
202
|
+
for (let form = token, penalty = 0; form; form = form.stem, penalty = STEM_PENALTY) {
|
|
203
|
+
const match = matchToken(form, field, best / field.weight + penalty);
|
|
204
|
+
if (!match)
|
|
205
|
+
continue;
|
|
206
|
+
const score = (match.base - penalty) * field.weight;
|
|
207
|
+
if (score > best) {
|
|
208
|
+
best = score;
|
|
209
|
+
found = {
|
|
210
|
+
token: token.text,
|
|
211
|
+
field: field.name,
|
|
212
|
+
text: field.text,
|
|
213
|
+
kind: match.kind,
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
if (!found)
|
|
219
|
+
return null;
|
|
220
|
+
total += best;
|
|
221
|
+
matches.push(found);
|
|
222
|
+
}
|
|
223
|
+
let score = total / tokens.length;
|
|
224
|
+
if (tokens.length > 1) {
|
|
225
|
+
const { phrase } = alt;
|
|
226
|
+
for (let f = 0; f < fields.length; f += 1) {
|
|
227
|
+
const field = fields[f];
|
|
228
|
+
if (field.weight < 1)
|
|
229
|
+
continue;
|
|
230
|
+
if (field.folded === phrase)
|
|
231
|
+
score += 20;
|
|
232
|
+
else if (field.folded.startsWith(phrase))
|
|
233
|
+
score += 10;
|
|
234
|
+
else if (field.folded.includes(phrase))
|
|
235
|
+
score += 5;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
return { score, matches };
|
|
239
|
+
};
|
|
240
|
+
const compiled = new WeakMap();
|
|
241
|
+
const synonymGroups = (synonyms) => {
|
|
242
|
+
const cached = compiled.get(synonyms);
|
|
243
|
+
if (cached)
|
|
244
|
+
return cached;
|
|
245
|
+
const groups = Object.entries(synonyms).map(([term, phrases]) => [term, ...phrases].map(fold_1.tokenize).filter((tokens) => tokens.length > 0));
|
|
246
|
+
compiled.set(synonyms, groups);
|
|
247
|
+
return groups;
|
|
248
|
+
};
|
|
249
|
+
const findRun = (tokens, run) => {
|
|
250
|
+
for (let at = 0; at + run.length <= tokens.length; at += 1) {
|
|
251
|
+
if (run.every((t, i) => tokens[at + i] === t))
|
|
252
|
+
return at;
|
|
253
|
+
}
|
|
254
|
+
return -1;
|
|
255
|
+
};
|
|
256
|
+
const alternatives = (tokens, synonyms) => {
|
|
257
|
+
const out = [{ tokens }];
|
|
258
|
+
if (!synonyms || tokens.length === 0)
|
|
259
|
+
return out;
|
|
260
|
+
const seen = new Set([tokens.join(" ")]);
|
|
261
|
+
for (const group of synonymGroups(synonyms)) {
|
|
262
|
+
for (const member of group) {
|
|
263
|
+
const at = findRun(tokens, member);
|
|
264
|
+
if (at < 0)
|
|
265
|
+
continue;
|
|
266
|
+
for (const other of group) {
|
|
267
|
+
if (other === member)
|
|
268
|
+
continue;
|
|
269
|
+
const next = [
|
|
270
|
+
...tokens.slice(0, at),
|
|
271
|
+
...other,
|
|
272
|
+
...tokens.slice(at + member.length),
|
|
273
|
+
];
|
|
274
|
+
const key = next.join(" ");
|
|
275
|
+
if (seen.has(key))
|
|
276
|
+
continue;
|
|
277
|
+
seen.add(key);
|
|
278
|
+
out.push({ tokens: Array.from(new Set(next)), via: other.join(" ") });
|
|
279
|
+
if (out.length >= MAX_ALTERNATIVES)
|
|
280
|
+
return out;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
return out;
|
|
285
|
+
};
|
|
286
|
+
const stemOf = (text) => text.endsWith(TAMIL_FINAL_MA) && (0, fold_1.letters)(text).length > 2
|
|
287
|
+
? text.slice(0, -TAMIL_FINAL_MA.length)
|
|
288
|
+
: null;
|
|
289
|
+
const toToken = (text, fuzzy) => {
|
|
290
|
+
const written = (0, fold_1.hasMarks)(text) ? (0, fold_1.letters)(text) : null;
|
|
291
|
+
const size = written ? written.length : text.length;
|
|
292
|
+
const edits = fuzzy && size >= 4 ? maxEdits(size) : 0;
|
|
293
|
+
const stem = stemOf(text);
|
|
294
|
+
return {
|
|
295
|
+
text,
|
|
296
|
+
mask: maskOf(text),
|
|
297
|
+
edits,
|
|
298
|
+
slack: written && edits > 0 ? UNBOUNDED_SLACK : edits,
|
|
299
|
+
letters: written,
|
|
300
|
+
exact: false,
|
|
301
|
+
stem: stem === null
|
|
302
|
+
? null
|
|
303
|
+
: {
|
|
304
|
+
text: stem,
|
|
305
|
+
mask: maskOf(stem),
|
|
306
|
+
edits: 0,
|
|
307
|
+
slack: 0,
|
|
308
|
+
letters: null,
|
|
309
|
+
exact: true,
|
|
310
|
+
stem: null,
|
|
311
|
+
},
|
|
312
|
+
};
|
|
313
|
+
};
|
|
314
|
+
const compileQuery = (tokens, options) => alternatives(tokens, options.synonyms).map(({ tokens: words, via }) => ({
|
|
315
|
+
tokens: words.map((text) => toToken(text, options.fuzzy !== false)),
|
|
316
|
+
phrase: words.join(" "),
|
|
317
|
+
via,
|
|
318
|
+
}));
|
|
319
|
+
const searchIndex = (index, query, options = {}) => {
|
|
320
|
+
var _a, _b, _c;
|
|
321
|
+
const tokens = (0, fold_1.tokenize)(query);
|
|
322
|
+
if (tokens.length === 0)
|
|
323
|
+
return [];
|
|
324
|
+
const alts = compileQuery(tokens, options);
|
|
325
|
+
const hits = [];
|
|
326
|
+
const { documents } = index;
|
|
327
|
+
for (let d = 0; d < documents.length; d += 1) {
|
|
328
|
+
const doc = documents[d];
|
|
329
|
+
let best = null;
|
|
330
|
+
for (let a = 0; a < alts.length; a += 1) {
|
|
331
|
+
const alt = alts[a];
|
|
332
|
+
const result = scoreTokens(doc, alt);
|
|
333
|
+
if (!result)
|
|
334
|
+
continue;
|
|
335
|
+
const score = alt.via ? result.score * SYNONYM_FACTOR : result.score;
|
|
336
|
+
if (!best || score > best.score) {
|
|
337
|
+
best = {
|
|
338
|
+
id: doc.id,
|
|
339
|
+
index: doc.index,
|
|
340
|
+
score,
|
|
341
|
+
matches: result.matches,
|
|
342
|
+
synonym: alt.via,
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
if (!best)
|
|
347
|
+
continue;
|
|
348
|
+
best.score += (_b = (_a = options.boosts) === null || _a === void 0 ? void 0 : _a[doc.id]) !== null && _b !== void 0 ? _b : 0;
|
|
349
|
+
hits.push(best);
|
|
350
|
+
}
|
|
351
|
+
hits.sort((a, b) => b.score - a.score || a.index - b.index);
|
|
352
|
+
const floor = hits.length ? hits[0].score * ((_c = options.relativeCutoff) !== null && _c !== void 0 ? _c : 0) : 0;
|
|
353
|
+
const kept = floor > 0 ? hits.filter((hit) => hit.score >= floor) : hits;
|
|
354
|
+
return options.limit === undefined ? kept : kept.slice(0, options.limit);
|
|
355
|
+
};
|
|
356
|
+
exports.searchIndex = searchIndex;
|
|
357
|
+
const searchDocuments = (documents, query, options) => (0, exports.searchIndex)((0, exports.createSearchIndex)(documents), query, options);
|
|
358
|
+
exports.searchDocuments = searchDocuments;
|
|
359
|
+
/** Compiles `query` once; every query word must hit some text of the row. */
|
|
360
|
+
const createMatcher = (query, options = {}) => {
|
|
361
|
+
const tokens = (0, fold_1.tokenize)(query);
|
|
362
|
+
if (tokens.length === 0)
|
|
363
|
+
return () => true;
|
|
364
|
+
const alts = compileQuery(tokens, options);
|
|
365
|
+
return (...texts) => {
|
|
366
|
+
const fields = texts
|
|
367
|
+
.filter((text) => Boolean(text))
|
|
368
|
+
.map((text) => indexField({ name: "text", text }));
|
|
369
|
+
const doc = {
|
|
370
|
+
id: "",
|
|
371
|
+
index: 0,
|
|
372
|
+
fields,
|
|
373
|
+
mask: fields.reduce((mask, f) => mask | f.mask, 0),
|
|
374
|
+
};
|
|
375
|
+
return alts.some((alt) => scoreTokens(doc, alt) !== null);
|
|
376
|
+
};
|
|
377
|
+
};
|
|
378
|
+
exports.createMatcher = createMatcher;
|
|
379
|
+
/** One-off form of `createMatcher`: does `query` match the row made of `texts`? */
|
|
380
|
+
const matchesQuery = (query, ...texts) => (0, exports.createMatcher)(query)(...texts);
|
|
381
|
+
exports.matchesQuery = matchesQuery;
|
|
382
|
+
const markEnd = (text, end) => {
|
|
383
|
+
let at = end;
|
|
384
|
+
while (at < text.length && /\p{M}/u.test(text[at]))
|
|
385
|
+
at += 1;
|
|
386
|
+
return at;
|
|
387
|
+
};
|
|
388
|
+
const tokenRanges = (token, folded, words, starts, fuzzy) => {
|
|
389
|
+
var _a;
|
|
390
|
+
const ranges = [];
|
|
391
|
+
if (token.length >= 2) {
|
|
392
|
+
for (let at = folded.indexOf(token); at !== -1; at = folded.indexOf(token, at + token.length)) {
|
|
393
|
+
ranges.push([at, at + token.length]);
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
else {
|
|
397
|
+
words.forEach((word, i) => {
|
|
398
|
+
if (word.startsWith(token))
|
|
399
|
+
ranges.push([starts[i], starts[i] + 1]);
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
if (ranges.length || token.length < 2)
|
|
403
|
+
return ranges;
|
|
404
|
+
const marked = (0, fold_1.hasMarks)(token) || (0, fold_1.hasMarks)(folded);
|
|
405
|
+
const firsts = words.map((w) => (marked ? (0, fold_1.letters)(w)[0] : w[0]));
|
|
406
|
+
if (words.length >= 2 && firsts.join("").startsWith(token)) {
|
|
407
|
+
return Array.from(marked ? (0, fold_1.letters)(token) : token, (_, i) => [starts[i], starts[i] + firsts[i].length]);
|
|
408
|
+
}
|
|
409
|
+
if (fuzzy && writtenSize(token, marked) >= 4) {
|
|
410
|
+
words.forEach((word, i) => {
|
|
411
|
+
if (fuzzyScore(marked ? (0, fold_1.letters)(token) : token, [
|
|
412
|
+
marked ? (0, fold_1.letters)(word) : word,
|
|
413
|
+
]) > 0)
|
|
414
|
+
ranges.push([starts[i], starts[i] + word.length]);
|
|
415
|
+
});
|
|
416
|
+
if (ranges.length)
|
|
417
|
+
return ranges;
|
|
418
|
+
}
|
|
419
|
+
return ((_a = subsequenceAt(token, words, starts, marked)) !== null && _a !== void 0 ? _a : []).map((p) => [p, p + 1]);
|
|
420
|
+
};
|
|
421
|
+
/** Character ranges of `text` a query matched, in original-text offsets, merged and sorted. */
|
|
422
|
+
const highlightRanges = (text, query, options = {}) => {
|
|
423
|
+
var _a;
|
|
424
|
+
const tokens = Array.from(new Set(alternatives((0, fold_1.tokenize)(query), options.synonyms)
|
|
425
|
+
.flatMap((a) => a.tokens)
|
|
426
|
+
.flatMap((token) => {
|
|
427
|
+
const stem = stemOf(token);
|
|
428
|
+
return stem ? [token, stem] : [token];
|
|
429
|
+
})));
|
|
430
|
+
if (tokens.length === 0 || !text)
|
|
431
|
+
return [];
|
|
432
|
+
const { folded, map } = (0, fold_1.foldWithMap)(text);
|
|
433
|
+
const words = [];
|
|
434
|
+
const starts = [];
|
|
435
|
+
for (const match of folded.matchAll(WORD_RE)) {
|
|
436
|
+
words.push(match[0]);
|
|
437
|
+
starts.push((_a = match.index) !== null && _a !== void 0 ? _a : 0);
|
|
438
|
+
}
|
|
439
|
+
const ranges = tokens
|
|
440
|
+
.flatMap((token) => tokenRanges(token, folded, words, starts, options.fuzzy !== false))
|
|
441
|
+
.sort((a, b) => a[0] - b[0]);
|
|
442
|
+
const merged = [];
|
|
443
|
+
for (const [start, end] of ranges) {
|
|
444
|
+
const last = merged[merged.length - 1];
|
|
445
|
+
if (last && start <= last[1])
|
|
446
|
+
last[1] = Math.max(last[1], end);
|
|
447
|
+
else
|
|
448
|
+
merged.push([start, end]);
|
|
449
|
+
}
|
|
450
|
+
return merged.map(([start, end]) => {
|
|
451
|
+
var _a;
|
|
452
|
+
const lastChar = map[end - 1];
|
|
453
|
+
const width = ((_a = text.codePointAt(lastChar)) !== null && _a !== void 0 ? _a : 0) > 0xffff ? 2 : 1;
|
|
454
|
+
return [map[start], markEnd(text, lastChar + width)];
|
|
455
|
+
});
|
|
456
|
+
};
|
|
457
|
+
exports.highlightRanges = highlightRanges;
|
|
458
|
+
/** Additive ranking points from usage: pinned flat, frequent and recent decaying by position. */
|
|
459
|
+
const usageBoosts = (usage) => {
|
|
460
|
+
const out = {};
|
|
461
|
+
const add = (ids, weight, decays) => ids === null || ids === void 0 ? void 0 : ids.forEach((id, i) => {
|
|
462
|
+
var _a;
|
|
463
|
+
const factor = decays ? Math.max(0.25, 1 - i / ids.length) : 1;
|
|
464
|
+
out[id] = ((_a = out[id]) !== null && _a !== void 0 ? _a : 0) + weight * factor;
|
|
465
|
+
});
|
|
466
|
+
add(usage.pinnedIds, 3, false);
|
|
467
|
+
add(usage.frequentIds, 4, true);
|
|
468
|
+
add(usage.recentIds, 2, true);
|
|
469
|
+
return out;
|
|
470
|
+
};
|
|
471
|
+
exports.usageBoosts = usageBoosts;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** Case- and accent-insensitive form used for every comparison: "Crème Brûlée" -> "creme brulee". */
|
|
2
|
+
export declare const foldText: (text: string) => string;
|
|
3
|
+
export declare const splitWords: (folded: string) => string[];
|
|
4
|
+
/** Folded, de-duplicated query tokens in typing order. */
|
|
5
|
+
export declare const tokenize: (query: string) => string[];
|
|
6
|
+
/** True when folded text carries combining marks, so its written letters span several characters. */
|
|
7
|
+
export declare const hasMarks: (folded: string) => boolean;
|
|
8
|
+
/** Written letters: a base with its marks; a Devanagari conjunct counts as one. */
|
|
9
|
+
export declare const letters: (word: string) => string[];
|
|
10
|
+
/** Folded text plus each folded index's position in the original text. */
|
|
11
|
+
export type FoldedText = {
|
|
12
|
+
folded: string;
|
|
13
|
+
map: number[];
|
|
14
|
+
};
|
|
15
|
+
export declare const foldWithMap: (text: string) => FoldedText;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.foldWithMap = exports.letters = exports.hasMarks = exports.tokenize = exports.splitWords = exports.foldText = void 0;
|
|
4
|
+
// Accents, nukta and joiners fold away; vowel signs and viramas belong to the letter.
|
|
5
|
+
const OPTIONAL_MARKS =
|
|
6
|
+
// eslint-disable-next-line no-misleading-character-class -- each mark is removed on its own
|
|
7
|
+
/[\u0300-\u036f\u0591-\u05c7\u0610-\u061a\u064b-\u065f\u0670\u06d6-\u06ed\u093c\u1ab0-\u1aff\u1dc0-\u1dff\u200c\u200d\u20d0-\u20ff\ufe20-\ufe2f]/g;
|
|
8
|
+
const CHANDRABINDU = /\u0901/g;
|
|
9
|
+
const ANUSVARA = "\u0902";
|
|
10
|
+
const MARK = /\p{M}/u;
|
|
11
|
+
const SEPARATOR = /[^\p{L}\p{N}\p{M}]+/u;
|
|
12
|
+
const SPECIAL = {
|
|
13
|
+
ß: "ss",
|
|
14
|
+
æ: "ae",
|
|
15
|
+
œ: "oe",
|
|
16
|
+
ø: "o",
|
|
17
|
+
ł: "l",
|
|
18
|
+
đ: "d",
|
|
19
|
+
ı: "i",
|
|
20
|
+
};
|
|
21
|
+
const SPECIAL_RE = /[ßæœøłđı]/g;
|
|
22
|
+
const DEVANAGARI_VIRAMA = 0x094d;
|
|
23
|
+
/** Case- and accent-insensitive form used for every comparison: "Crème Brûlée" -> "creme brulee". */
|
|
24
|
+
const foldText = (text) => text
|
|
25
|
+
.normalize("NFKD")
|
|
26
|
+
.replace(OPTIONAL_MARKS, "")
|
|
27
|
+
.replace(CHANDRABINDU, ANUSVARA)
|
|
28
|
+
.toLowerCase()
|
|
29
|
+
.replace(SPECIAL_RE, (ch) => SPECIAL[ch]);
|
|
30
|
+
exports.foldText = foldText;
|
|
31
|
+
const splitWords = (folded) => folded.split(SEPARATOR).filter(Boolean);
|
|
32
|
+
exports.splitWords = splitWords;
|
|
33
|
+
/** Folded, de-duplicated query tokens in typing order. */
|
|
34
|
+
const tokenize = (query) => Array.from(new Set((0, exports.splitWords)((0, exports.foldText)(query))));
|
|
35
|
+
exports.tokenize = tokenize;
|
|
36
|
+
/** True when folded text carries combining marks, so its written letters span several characters. */
|
|
37
|
+
const hasMarks = (folded) => MARK.test(folded);
|
|
38
|
+
exports.hasMarks = hasMarks;
|
|
39
|
+
const isDevanagariConsonant = (code) => (code >= 0x0915 && code <= 0x0939) || (code >= 0x0978 && code <= 0x097f);
|
|
40
|
+
const markCodes = new Map();
|
|
41
|
+
const isMarkCode = (code, char) => {
|
|
42
|
+
if (code < 0x0300)
|
|
43
|
+
return false;
|
|
44
|
+
let known = markCodes.get(code);
|
|
45
|
+
if (known === undefined) {
|
|
46
|
+
known = MARK.test(char);
|
|
47
|
+
markCodes.set(code, known);
|
|
48
|
+
}
|
|
49
|
+
return known;
|
|
50
|
+
};
|
|
51
|
+
/** Written letters: a base with its marks; a Devanagari conjunct counts as one. */
|
|
52
|
+
const letters = (word) => {
|
|
53
|
+
var _a;
|
|
54
|
+
const out = [];
|
|
55
|
+
let previous = 0;
|
|
56
|
+
for (const char of word) {
|
|
57
|
+
const code = (_a = char.codePointAt(0)) !== null && _a !== void 0 ? _a : 0;
|
|
58
|
+
const joins = isMarkCode(code, char) ||
|
|
59
|
+
(previous === DEVANAGARI_VIRAMA && isDevanagariConsonant(code));
|
|
60
|
+
if (joins && out.length > 0)
|
|
61
|
+
out[out.length - 1] += char;
|
|
62
|
+
else
|
|
63
|
+
out.push(char);
|
|
64
|
+
previous = code;
|
|
65
|
+
}
|
|
66
|
+
return out;
|
|
67
|
+
};
|
|
68
|
+
exports.letters = letters;
|
|
69
|
+
const foldWithMap = (text) => {
|
|
70
|
+
let folded = "";
|
|
71
|
+
const map = [];
|
|
72
|
+
let at = 0;
|
|
73
|
+
for (const char of text) {
|
|
74
|
+
const piece = (0, exports.foldText)(char);
|
|
75
|
+
for (let i = 0; i < piece.length; i += 1)
|
|
76
|
+
map.push(at);
|
|
77
|
+
folded += piece;
|
|
78
|
+
at += char.length;
|
|
79
|
+
}
|
|
80
|
+
map.push(text.length);
|
|
81
|
+
return { folded, map };
|
|
82
|
+
};
|
|
83
|
+
exports.foldWithMap = foldWithMap;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export type { LauncherMatchKind, LauncherMatcher, LauncherSearchDocument, LauncherSearchField, LauncherSearchHit, LauncherSearchIndex, LauncherSearchOptions, LauncherSynonyms, LauncherTokenMatch, } from "./engine";
|
|
2
|
+
/** Framework-free ranked search used by NavLauncher; reusable by any list, picker or palette. */
|
|
3
|
+
export declare const LauncherSearchEngine: Readonly<{
|
|
4
|
+
createIndex: (documents: readonly import("./engine").LauncherSearchDocument[]) => import("./engine").LauncherSearchIndex;
|
|
5
|
+
search: (index: import("./engine").LauncherSearchIndex, query: string, options?: import("./engine").LauncherSearchOptions) => import("./engine").LauncherSearchHit[];
|
|
6
|
+
searchDocuments: (documents: readonly import("./engine").LauncherSearchDocument[], query: string, options?: import("./engine").LauncherSearchOptions) => import("./engine").LauncherSearchHit[];
|
|
7
|
+
createMatcher: (query: string, options?: {
|
|
8
|
+
fuzzy?: boolean | undefined;
|
|
9
|
+
synonyms?: import("./engine").LauncherSynonyms | undefined;
|
|
10
|
+
}) => import("./engine").LauncherMatcher;
|
|
11
|
+
matches: (query: string, ...texts: ReadonlyArray<string | null | undefined>) => boolean;
|
|
12
|
+
highlightRanges: (text: string, query: string, options?: Pick<import("./engine").LauncherSearchOptions, "synonyms" | "fuzzy">) => Array<[number, number]>;
|
|
13
|
+
usageBoosts: (usage: {
|
|
14
|
+
pinnedIds?: readonly string[];
|
|
15
|
+
frequentIds?: readonly string[];
|
|
16
|
+
recentIds?: readonly string[];
|
|
17
|
+
}) => Record<string, number>;
|
|
18
|
+
foldText: (text: string) => string;
|
|
19
|
+
tokenize: (query: string) => string[];
|
|
20
|
+
editDistance: (a: import("./distance").Sequence, b: import("./distance").Sequence, max: number) => number;
|
|
21
|
+
}>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LauncherSearchEngine = void 0;
|
|
4
|
+
const engine_1 = require("./engine");
|
|
5
|
+
/** Framework-free ranked search used by NavLauncher; reusable by any list, picker or palette. */
|
|
6
|
+
exports.LauncherSearchEngine = Object.freeze({
|
|
7
|
+
createIndex: engine_1.createSearchIndex,
|
|
8
|
+
search: engine_1.searchIndex,
|
|
9
|
+
searchDocuments: engine_1.searchDocuments,
|
|
10
|
+
createMatcher: engine_1.createMatcher,
|
|
11
|
+
matches: engine_1.matchesQuery,
|
|
12
|
+
highlightRanges: engine_1.highlightRanges,
|
|
13
|
+
usageBoosts: engine_1.usageBoosts,
|
|
14
|
+
foldText: engine_1.foldText,
|
|
15
|
+
tokenize: engine_1.tokenize,
|
|
16
|
+
editDistance: engine_1.editDistance,
|
|
17
|
+
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type ElementType, type FocusEvent, type KeyboardEvent, type MouseEvent, type ReactNode } from "react";
|
|
2
2
|
import type { PaletteProps } from "../../Theme/tokens/types";
|
|
3
3
|
import type { AppOption } from "../AppSwitcher/AppSwitcherProps";
|
|
4
|
+
import { type HighlightOptions } from "./match";
|
|
4
5
|
import type { LauncherLabels, LauncherModule, LauncherScreen } from "./NavLauncherProps";
|
|
5
6
|
export declare const ITEM_SELECTOR = "[data-launcher-item]";
|
|
6
7
|
export declare const TouchDensity: import("react").Provider<boolean>;
|
|
@@ -100,6 +101,7 @@ type RowIconProps = {
|
|
|
100
101
|
mt?: string;
|
|
101
102
|
};
|
|
102
103
|
export declare function RowIcon({ icon: Icon, size, stroke, mt }: RowIconProps): import("react/jsx-runtime").JSX.Element | null;
|
|
104
|
+
export declare const HighlightOptionsProvider: import("react").Provider<HighlightOptions | undefined>;
|
|
103
105
|
export declare function Highlight({ text, query }: {
|
|
104
106
|
text: string;
|
|
105
107
|
query: string;
|