1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
import {
POPULAR_COLLECTIONS,
getIconSvgUrl,
searchIcons,
} from "@/lib/iconify-api";
import { buildStickerId, parseStickerId } from "../sticker-id";
import type {
StickerItem,
StickerProvider,
StickerSearchResult,
} from "../types";
const ICONS_PROVIDER_ID = "icons";
const DEFAULT_SEARCH_LIMIT = 100;
const ICONS_PREFIXES = Array.from(
new Set(
[...POPULAR_COLLECTIONS.general, ...POPULAR_COLLECTIONS.brands].map(
(collection) => collection.prefix,
),
),
);
const DEFAULT_ICONS_BROWSE = [
"mdi:home",
"mdi:star",
"mdi:heart",
"mdi:check-circle",
"mdi:account",
"mdi:camera",
"mdi:music",
"mdi:map-marker",
"mdi:calendar",
"mdi:lightning-bolt",
"mdi:cog",
"mdi:rocket",
];
function getDisplayNameFromIconName({
iconName,
}: {
iconName: string;
}): string {
const [, rawName = iconName] = iconName.split(":");
return rawName.replaceAll("-", " ").replaceAll("_", " ");
}
function toStickerItem({ iconName }: { iconName: string }): StickerItem {
return {
id: buildStickerId({
providerId: ICONS_PROVIDER_ID,
providerValue: iconName,
}),
provider: ICONS_PROVIDER_ID,
name: getDisplayNameFromIconName({ iconName }),
previewUrl: getIconSvgUrl(iconName, { width: 64, height: 64 }),
metadata: { iconName },
};
}
function computeHasMore({
total,
limit,
start = 0,
}: {
total: number;
limit: number;
start?: number;
}): boolean {
return start + limit < total;
}
export const iconsProvider: StickerProvider = {
id: ICONS_PROVIDER_ID,
async search({
query,
options,
}: {
query: string;
options?: { limit?: number };
}): Promise<StickerSearchResult> {
const limit = options?.limit ?? DEFAULT_SEARCH_LIMIT;
const searchResult = await searchIcons(query, limit, ICONS_PREFIXES);
return {
items: searchResult.icons.map((iconName) => toStickerItem({ iconName })),
total: searchResult.total,
hasMore: computeHasMore({
total: searchResult.total,
limit: searchResult.limit,
start: searchResult.start,
}),
};
},
async browse({
options,
}: {
options?: { page?: number; limit?: number };
}): Promise<StickerSearchResult> {
const limit = options?.limit ?? DEFAULT_ICONS_BROWSE.length;
const items = DEFAULT_ICONS_BROWSE.slice(0, limit).map((iconName) =>
toStickerItem({ iconName }),
);
return {
items,
total: items.length,
hasMore: false,
};
},
resolveUrl({
stickerId,
options,
}: {
stickerId: string;
options?: { width?: number; height?: number };
}): string {
const { providerValue } = parseStickerId({ stickerId });
return getIconSvgUrl(providerValue, {
width: options?.width,
height: options?.height,
});
},
};
|