Skip to content

Commit ae11fe2

Browse files
refactor: using FlexSearch in font panel (#1749)
* using flex search in font
1 parent 3aa26c9 commit ae11fe2

File tree

3 files changed

+56
-17
lines changed

3 files changed

+56
-17
lines changed

apps/studio/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
"embla-carousel-wheel-gestures": "^8.0.1",
6060
"fflate": "^0.8.2",
6161
"fix-path": "^4.0.0",
62+
"flexsearch": "^0.8.151",
6263
"freestyle-sandboxes": "^0.0.36",
6364
"i18next": "^24.2.2",
6465
"istextorbinary": "^9.5.0",
@@ -95,11 +96,12 @@
9596
"@onlook/typescript": "*",
9697
"@playwright/test": "^1.42.1",
9798
"@tailwindcss/typography": "^0.5.15",
98-
"@types/babel__traverse": "^7.20.6",
9999
"@types/babel-generator": "^6.25.8",
100+
"@types/babel__traverse": "^7.20.6",
100101
"@types/bun": "^1.1.6",
101102
"@types/css-tree": "^2.3.8",
102103
"@types/download": "^8.0.5",
104+
"@types/flexsearch": "^0.7.42",
103105
"@types/istextorbinary": "^2.3.4",
104106
"@types/js-string-escape": "^1.0.3",
105107
"@types/lodash": "^4.17.7",

apps/studio/src/lib/editor/engine/font/index.ts

Lines changed: 47 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import type { ProjectsManager } from '@/lib/projects';
66
import type { Font } from '@onlook/models/assets';
77
import type { FontFile } from '@/routes/editor/LayersPanel/BrandTab/FontPanel/FontFiles';
88
import WebFont from 'webfontloader';
9+
import FlexSearch from 'flexsearch';
10+
import type { Document } from 'flexsearch';
911

1012
interface RawFont {
1113
id: string;
@@ -30,12 +32,36 @@ export class FontManager {
3032
private _currentFontIndex = 0;
3133
private _batchSize = 20;
3234
private _isFetching = false;
35+
private _fontSearchIndex: Document;
3336

3437
constructor(
3538
private editorEngine: EditorEngine,
3639
private projectsManager: ProjectsManager,
3740
) {
3841
makeAutoObservable(this);
42+
43+
// Initialize FlexSearch index
44+
this._fontSearchIndex = new FlexSearch.Document({
45+
document: {
46+
id: 'id',
47+
index: ['family'],
48+
store: true,
49+
},
50+
tokenize: 'forward',
51+
});
52+
53+
// Add all font families to the search index
54+
this._allFontFamilies.forEach((font) => {
55+
this._fontSearchIndex.add(font.id, {
56+
id: font.id,
57+
family: font.family,
58+
subsets: font.subsets,
59+
variable: font.variable,
60+
weights: font.weights,
61+
styles: font.styles,
62+
});
63+
});
64+
3965
this.loadInitialFonts();
4066

4167
// Watch for project changes and set up watcher when a project is selected
@@ -258,28 +284,33 @@ export class FontManager {
258284

259285
async searchFonts(query: string): Promise<Font[]> {
260286
if (!query) {
261-
return [];
262-
}
263-
264-
const searchResults = this._allFontFamilies
265-
.filter(
266-
(font) =>
267-
font.family.toLowerCase().includes(query.toLowerCase()) &&
268-
!this._fonts.some((f) => f.family === font.family),
269-
)
270-
.map((font) => this.convertFont(font));
271-
272-
if (searchResults.length === 0) {
273287
this._searchResults = [];
274288
return [];
275289
}
276290

277291
try {
278-
await this.loadFontBatch(searchResults);
279-
this._searchResults = searchResults;
280-
return searchResults;
292+
// Search using FlexSearch
293+
const searchResults = await this._fontSearchIndex.search(query, {
294+
limit: 20,
295+
suggest: true,
296+
enrich: true,
297+
});
298+
299+
const fonts = Object.values(searchResults)
300+
.flatMap((result) => result.result)
301+
.map((font) => this.convertFont(font.doc))
302+
.filter((font) => !this._fonts.some((f) => f.family === font.family));
303+
304+
if (fonts.length === 0) {
305+
this._searchResults = [];
306+
return [];
307+
}
308+
309+
await this.loadFontBatch(fonts);
310+
this._searchResults = fonts;
311+
return fonts;
281312
} catch (error) {
282-
console.error('Error loading search results:', error);
313+
console.error('Error searching fonts:', error);
283314
return [];
284315
}
285316
}

bun.lock

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
"embla-carousel-wheel-gestures": "^8.0.1",
4747
"fflate": "^0.8.2",
4848
"fix-path": "^4.0.0",
49+
"flexsearch": "^0.8.151",
4950
"freestyle-sandboxes": "^0.0.36",
5051
"i18next": "^24.2.2",
5152
"istextorbinary": "^9.5.0",
@@ -87,6 +88,7 @@
8788
"@types/bun": "^1.1.6",
8889
"@types/css-tree": "^2.3.8",
8990
"@types/download": "^8.0.5",
91+
"@types/flexsearch": "^0.7.42",
9092
"@types/istextorbinary": "^2.3.4",
9193
"@types/js-string-escape": "^1.0.3",
9294
"@types/lodash": "^4.17.7",
@@ -1003,6 +1005,8 @@
10031005

10041006
"@types/estree-jsx": ["@types/[email protected]", "", { "dependencies": { "@types/estree": "*" } }, "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg=="],
10051007

1008+
"@types/flexsearch": ["@types/[email protected]", "", { "dependencies": { "flexsearch": "*" } }, "sha512-FdKaw3dPgcCvqU9w8SGgqx8PrxFF2EKySRhEj1nc45HNe/2cBLff3pF52C67hzeUbNhq49t7XRIIibBd41vcIg=="],
1009+
10061010
"@types/fs-extra": ["@types/[email protected]", "", { "dependencies": { "@types/node": "*" } }, "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA=="],
10071011

10081012
"@types/got": ["@types/[email protected]", "", { "dependencies": { "@types/node": "*", "@types/tough-cookie": "*", "form-data": "^2.5.0" } }, "sha512-X4pj/HGHbXVLqTpKjA2ahI4rV/nNBc9mGO2I/0CgAra+F2dKgMXnENv2SRpemScBzBAI4vMelIVYViQxlSE6xA=="],
@@ -1687,6 +1691,8 @@
16871691

16881692
"flatted": ["[email protected]", "", {}, "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg=="],
16891693

1694+
"flexsearch": ["[email protected]", "", {}, "sha512-bMI/vDndsaldfmOLKGk5HMYSiXhX1sBiD/ENZKAnsQJaqC/yk51aTy0+Ny2hYcu+Utazy3s8NZA/zbh2o88ctQ=="],
1695+
16901696
"follow-redirects": ["[email protected]", "", {}, "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ=="],
16911697

16921698
"for-each": ["[email protected]", "", { "dependencies": { "is-callable": "^1.2.7" } }, "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg=="],

0 commit comments

Comments
 (0)