@nice2dev/icons 1.3.15 → 1.3.16
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 +9 -0
- package/dist/cjs/NiceDesktopIconExporter.js +688 -599
- package/dist/cjs/NiceFaviconGenerator.js +603 -417
- package/dist/cjs/NiceIconPicker.js +788 -508
- package/dist/cjs/NiceIconPreview.js +246 -188
- package/dist/cjs/NiceIconSetCreator.js +683 -552
- package/dist/cjs/NiceIconStacker.js +547 -171
- package/dist/cjs/NiceIconValue.js +27 -35
- package/dist/cjs/NtdIconBadge.js +384 -360
- package/dist/cjs/NtdIconMorph.js +419 -354
- package/dist/cjs/NtdStateMorph.js +150 -147
- package/dist/cjs/advancedIconSearch.js +373 -510
- package/dist/cjs/animationControls.js +518 -642
- package/dist/cjs/client.js +12 -15
- package/dist/cjs/createIcon.js +349 -251
- package/dist/cjs/design-tokens.js +324 -390
- package/dist/cjs/figmaExport.js +162 -257
- package/dist/cjs/figmaSync.js +234 -316
- package/dist/cjs/headless-ui.js +240 -368
- package/dist/cjs/iconAnalytics.js +337 -393
- package/dist/cjs/iconHtml.js +64 -86
- package/dist/cjs/iconMetadata.js +392 -472
- package/dist/cjs/iconParts.js +120 -90
- package/dist/cjs/iconStack.js +136 -155
- package/dist/cjs/iconStyles.js +1609 -504
- package/dist/cjs/iconValue.js +359 -430
- package/dist/cjs/icons/accessibility.js +1119 -134
- package/dist/cjs/icons/actions.js +1290 -330
- package/dist/cjs/icons/ai.js +1424 -144
- package/dist/cjs/icons/brand.js +1344 -172
- package/dist/cjs/icons/business.js +903 -193
- package/dist/cjs/icons/devtech.js +1656 -227
- package/dist/cjs/icons/ecommerce.js +802 -111
- package/dist/cjs/icons/education.js +1345 -199
- package/dist/cjs/icons/files.js +1597 -328
- package/dist/cjs/icons/fintech.js +793 -104
- package/dist/cjs/icons/food.js +1507 -153
- package/dist/cjs/icons/fun.js +786 -109
- package/dist/cjs/icons/gaming.js +916 -170
- package/dist/cjs/icons/health.js +623 -112
- package/dist/cjs/icons/index.js +32 -35
- package/dist/cjs/icons/input.js +282 -83
- package/dist/cjs/icons/legal.js +1065 -122
- package/dist/cjs/icons/media.js +1061 -267
- package/dist/cjs/icons/navigation.js +387 -122
- package/dist/cjs/icons/omniverk.js +747 -90
- package/dist/cjs/icons/realestate.js +1520 -193
- package/dist/cjs/icons/saas.js +867 -98
- package/dist/cjs/icons/science.js +1451 -202
- package/dist/cjs/icons/shapes.js +1316 -308
- package/dist/cjs/icons/smarthome.js +786 -90
- package/dist/cjs/icons/social.js +591 -59
- package/dist/cjs/icons/sports.js +1225 -133
- package/dist/cjs/icons/sustainability.js +1211 -139
- package/dist/cjs/icons/travel.js +1470 -148
- package/dist/cjs/icons/ui.js +1508 -315
- package/dist/cjs/icons/weather.js +1160 -173
- package/dist/cjs/index.js +566 -568
- package/dist/cjs/lottieIntegration.js +261 -266
- package/dist/cjs/nicetodev-icons.css +1 -1
- package/dist/cjs/particleEffects.js +270 -251
- package/dist/cjs/resolver.js +229 -284
- package/dist/cjs/rsc.js +175 -193
- package/dist/cjs/sharpen.js +73 -130
- package/dist/cjs/smilAnimations.js +371 -165
- package/dist/cjs/stacking.js +87 -122
- package/dist/cjs/tailwind-plugin.js +280 -320
- package/dist/cjs/types.js +46 -72
- package/dist/cjs/utilities.js +163 -324
- package/dist/cjs/variantProps.js +12 -52
- package/dist/esm/NiceDesktopIconExporter.js +671 -598
- package/dist/esm/NiceFaviconGenerator.js +583 -416
- package/dist/esm/NiceIconPicker.js +789 -507
- package/dist/esm/NiceIconPreview.js +247 -187
- package/dist/esm/NiceIconSetCreator.js +685 -551
- package/dist/esm/NiceIconStacker.js +549 -170
- package/dist/esm/NiceIconValue.js +29 -34
- package/dist/esm/NtdIconBadge.js +388 -359
- package/dist/esm/NtdIconMorph.js +423 -353
- package/dist/esm/NtdStateMorph.js +152 -146
- package/dist/esm/advancedIconSearch.js +391 -509
- package/dist/esm/animationControls.js +527 -641
- package/dist/esm/client.js +48 -10
- package/dist/esm/createIcon.js +350 -250
- package/dist/esm/design-tokens.js +334 -387
- package/dist/esm/figmaExport.js +170 -256
- package/dist/esm/figmaSync.js +237 -315
- package/dist/esm/headless-ui.js +254 -365
- package/dist/esm/iconAnalytics.js +342 -392
- package/dist/esm/iconHtml.js +67 -85
- package/dist/esm/iconMetadata.js +404 -471
- package/dist/esm/iconParts.js +125 -89
- package/dist/esm/iconStack.js +145 -154
- package/dist/esm/iconStyles.js +1620 -503
- package/dist/esm/iconValue.js +361 -429
- package/dist/esm/icons/accessibility.js +1133 -133
- package/dist/esm/icons/actions.js +1320 -329
- package/dist/esm/icons/ai.js +1441 -143
- package/dist/esm/icons/brand.js +1351 -171
- package/dist/esm/icons/business.js +931 -201
- package/dist/esm/icons/devtech.js +1687 -226
- package/dist/esm/icons/ecommerce.js +816 -110
- package/dist/esm/icons/education.js +1364 -198
- package/dist/esm/icons/files.js +1628 -327
- package/dist/esm/icons/fintech.js +807 -103
- package/dist/esm/icons/food.js +1524 -152
- package/dist/esm/icons/fun.js +801 -108
- package/dist/esm/icons/gaming.js +933 -169
- package/dist/esm/icons/health.js +636 -111
- package/dist/esm/icons/index.js +596 -32
- package/dist/esm/icons/input.js +326 -82
- package/dist/esm/icons/legal.js +1079 -121
- package/dist/esm/icons/media.js +1086 -266
- package/dist/esm/icons/navigation.js +401 -121
- package/dist/esm/icons/omniverk.js +759 -89
- package/dist/esm/icons/realestate.js +1544 -198
- package/dist/esm/icons/saas.js +880 -97
- package/dist/esm/icons/science.js +1477 -208
- package/dist/esm/icons/shapes.js +1343 -307
- package/dist/esm/icons/smarthome.js +799 -89
- package/dist/esm/icons/social.js +599 -58
- package/dist/esm/icons/sports.js +1240 -132
- package/dist/esm/icons/sustainability.js +1226 -138
- package/dist/esm/icons/travel.js +1486 -147
- package/dist/esm/icons/ui.js +1540 -314
- package/dist/esm/icons/weather.js +1181 -172
- package/dist/esm/index.js +756 -58
- package/dist/esm/lottieIntegration.js +264 -265
- package/dist/esm/nicetodev-icons.css +1 -1
- package/dist/esm/particleEffects.js +271 -250
- package/dist/esm/resolver.js +231 -283
- package/dist/esm/rsc.js +182 -192
- package/dist/esm/sharpen.js +78 -129
- package/dist/esm/smilAnimations.js +376 -164
- package/dist/esm/stacking.js +99 -121
- package/dist/esm/tailwind-plugin.js +282 -319
- package/dist/esm/types.js +50 -71
- package/dist/esm/utilities.js +177 -321
- package/dist/esm/variantProps.js +23 -52
- package/package.json +15 -22
package/dist/esm/iconMetadata.js
CHANGED
|
@@ -12,507 +12,440 @@
|
|
|
12
12
|
* @since 2026-03
|
|
13
13
|
* @license MIT
|
|
14
14
|
*/
|
|
15
|
-
/* ────────────────────────────────────────────────────────────────────────────
|
|
16
|
-
CATEGORY METADATA
|
|
17
|
-
───────────────────────────────────────────────────────────────────────────── */
|
|
18
|
-
// audit-allow: i18n — English data for the host's icon browser and searchIcons(); no control of
|
|
19
|
-
// this package shows it.
|
|
20
15
|
const CATEGORY_INFO = {
|
|
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
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
16
|
+
actions: {
|
|
17
|
+
label: "Actions",
|
|
18
|
+
description: "Interactive action icons like play, pause, edit, delete",
|
|
19
|
+
color: "#3b82f6"
|
|
20
|
+
},
|
|
21
|
+
navigation: {
|
|
22
|
+
label: "Navigation",
|
|
23
|
+
description: "Arrows, chevrons, and directional icons",
|
|
24
|
+
color: "#8b5cf6"
|
|
25
|
+
},
|
|
26
|
+
ui: {
|
|
27
|
+
label: "UI Elements",
|
|
28
|
+
description: "Common interface elements and controls",
|
|
29
|
+
color: "#06b6d4"
|
|
30
|
+
},
|
|
31
|
+
media: {
|
|
32
|
+
label: "Media",
|
|
33
|
+
description: "Audio, video, and image related icons",
|
|
34
|
+
color: "#ec4899"
|
|
35
|
+
},
|
|
36
|
+
files: {
|
|
37
|
+
label: "Files & Documents",
|
|
38
|
+
description: "File types, folders, and document icons",
|
|
39
|
+
color: "#f59e0b"
|
|
40
|
+
},
|
|
41
|
+
social: {
|
|
42
|
+
label: "Social",
|
|
43
|
+
description: "Social media and communication icons",
|
|
44
|
+
color: "#10b981"
|
|
45
|
+
},
|
|
46
|
+
brand: {
|
|
47
|
+
label: "Brands",
|
|
48
|
+
description: "Company and service logos",
|
|
49
|
+
color: "#6366f1"
|
|
50
|
+
},
|
|
51
|
+
business: {
|
|
52
|
+
label: "Business",
|
|
53
|
+
description: "Office, work, and professional icons",
|
|
54
|
+
color: "#64748b"
|
|
55
|
+
},
|
|
56
|
+
weather: {
|
|
57
|
+
label: "Weather",
|
|
58
|
+
description: "Weather conditions and climate icons",
|
|
59
|
+
color: "#0ea5e9"
|
|
60
|
+
},
|
|
61
|
+
health: {
|
|
62
|
+
label: "Health",
|
|
63
|
+
description: "Medical and wellness icons",
|
|
64
|
+
color: "#ef4444"
|
|
65
|
+
},
|
|
66
|
+
shapes: {
|
|
67
|
+
label: "Shapes",
|
|
68
|
+
description: "Geometric shapes and patterns",
|
|
69
|
+
color: "#a855f7"
|
|
70
|
+
},
|
|
71
|
+
ecommerce: {
|
|
72
|
+
label: "E-Commerce",
|
|
73
|
+
description: "Shopping, cart, and retail icons",
|
|
74
|
+
color: "#f97316"
|
|
75
|
+
},
|
|
76
|
+
fintech: {
|
|
77
|
+
label: "Fintech",
|
|
78
|
+
description: "Crypto, blockchain, and financial technology",
|
|
79
|
+
color: "#eab308"
|
|
80
|
+
},
|
|
81
|
+
saas: {
|
|
82
|
+
label: "SaaS",
|
|
83
|
+
description: "Software as a service and analytics icons",
|
|
84
|
+
color: "#14b8a6"
|
|
85
|
+
},
|
|
86
|
+
smarthome: {
|
|
87
|
+
label: "Smart Home",
|
|
88
|
+
description: "IoT and home automation icons",
|
|
89
|
+
color: "#22c55e"
|
|
90
|
+
},
|
|
91
|
+
devtech: {
|
|
92
|
+
label: "DevTech",
|
|
93
|
+
description: "Developer tools and technology logos",
|
|
94
|
+
color: "#f43f5e"
|
|
95
|
+
},
|
|
96
|
+
fun: {
|
|
97
|
+
label: "Fun",
|
|
98
|
+
description: "Emoji, entertainment, and playful icons",
|
|
99
|
+
color: "#fbbf24"
|
|
100
|
+
},
|
|
101
|
+
gaming: {
|
|
102
|
+
label: "Gaming",
|
|
103
|
+
description: "Video games, esports, and entertainment",
|
|
104
|
+
color: "#8b5cf6"
|
|
105
|
+
},
|
|
106
|
+
ai: {
|
|
107
|
+
label: "AI & ML",
|
|
108
|
+
description: "Artificial intelligence and machine learning",
|
|
109
|
+
color: "#06b6d4"
|
|
110
|
+
},
|
|
111
|
+
sustainability: {
|
|
112
|
+
label: "Sustainability",
|
|
113
|
+
description: "Eco-friendly and environmental icons",
|
|
114
|
+
color: "#22c55e"
|
|
115
|
+
},
|
|
116
|
+
accessibility: {
|
|
117
|
+
label: "Accessibility",
|
|
118
|
+
description: "Accessibility features and inclusive design",
|
|
119
|
+
color: "#3b82f6"
|
|
120
|
+
},
|
|
121
|
+
legal: {
|
|
122
|
+
label: "Legal",
|
|
123
|
+
description: "Legal, compliance, and regulatory icons",
|
|
124
|
+
color: "#64748b"
|
|
125
|
+
}
|
|
131
126
|
};
|
|
132
|
-
/*
|
|
133
|
-
ICON METADATA REGISTRY
|
|
134
|
-
───────────────────────────────────────────────────────────────────────────── */
|
|
135
|
-
// Registry for all icon metadata
|
|
136
|
-
const iconRegistry = new Map();
|
|
137
|
-
/**
|
|
138
|
-
* Register an icon with its metadata.
|
|
139
|
-
* Called during icon module initialization.
|
|
140
|
-
*/
|
|
127
|
+
const iconRegistry = /* @__PURE__ */ new Map();
|
|
141
128
|
function registerIcon(name, icon, metadata) {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
129
|
+
iconRegistry.set(name, {
|
|
130
|
+
icon,
|
|
131
|
+
metadata: { ...metadata, name }
|
|
132
|
+
});
|
|
146
133
|
}
|
|
147
|
-
/**
|
|
148
|
-
* Get icon by name.
|
|
149
|
-
*/
|
|
150
134
|
function getIcon(name) {
|
|
151
|
-
|
|
152
|
-
return (_a = iconRegistry.get(name)) === null || _a === void 0 ? void 0 : _a.icon;
|
|
135
|
+
return iconRegistry.get(name)?.icon;
|
|
153
136
|
}
|
|
154
|
-
/**
|
|
155
|
-
* Get icon metadata by name.
|
|
156
|
-
*/
|
|
157
137
|
function getIconMetadata(name) {
|
|
158
|
-
|
|
159
|
-
return (_a = iconRegistry.get(name)) === null || _a === void 0 ? void 0 : _a.metadata;
|
|
138
|
+
return iconRegistry.get(name)?.metadata;
|
|
160
139
|
}
|
|
161
|
-
/**
|
|
162
|
-
* Get all registered icons.
|
|
163
|
-
*/
|
|
164
140
|
function getAllIcons() {
|
|
165
|
-
|
|
141
|
+
return new Map(iconRegistry);
|
|
166
142
|
}
|
|
167
|
-
/**
|
|
168
|
-
* Get icons by category.
|
|
169
|
-
*/
|
|
170
143
|
function getIconsByCategory(category) {
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
144
|
+
const results = [];
|
|
145
|
+
iconRegistry.forEach(({ icon, metadata }, name) => {
|
|
146
|
+
if (metadata.category === category) {
|
|
147
|
+
results.push({ name, icon, metadata });
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
return results.sort((a, b) => a.name.localeCompare(b.name));
|
|
178
151
|
}
|
|
179
|
-
/**
|
|
180
|
-
* Get all categories with icon counts.
|
|
181
|
-
*/
|
|
182
152
|
function getCategoryCounts() {
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
153
|
+
const counts = {};
|
|
154
|
+
iconRegistry.forEach(({ metadata }) => {
|
|
155
|
+
counts[metadata.category] = (counts[metadata.category] || 0) + 1;
|
|
156
|
+
});
|
|
157
|
+
return counts;
|
|
188
158
|
}
|
|
189
|
-
/* ────────────────────────────────────────────────────────────────────────────
|
|
190
|
-
SEARCH ENGINE
|
|
191
|
-
───────────────────────────────────────────────────────────────────────────── */
|
|
192
|
-
/**
|
|
193
|
-
* Calculate fuzzy match score between query and target string.
|
|
194
|
-
* Returns 0-1 score, higher is better match.
|
|
195
|
-
*/
|
|
196
159
|
function fuzzyMatch(query, target) {
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
160
|
+
const q = query.toLowerCase();
|
|
161
|
+
const t = target.toLowerCase();
|
|
162
|
+
if (t === q) {
|
|
163
|
+
return { score: 1, indices: [[0, t.length - 1]] };
|
|
164
|
+
}
|
|
165
|
+
if (t.startsWith(q)) {
|
|
166
|
+
return { score: 0.9, indices: [[0, q.length - 1]] };
|
|
167
|
+
}
|
|
168
|
+
const idx = t.indexOf(q);
|
|
169
|
+
if (idx !== -1) {
|
|
170
|
+
return { score: 0.7, indices: [[idx, idx + q.length - 1]] };
|
|
171
|
+
}
|
|
172
|
+
let qIdx = 0;
|
|
173
|
+
let score = 0;
|
|
174
|
+
const indices = [];
|
|
175
|
+
let matchStart = -1;
|
|
176
|
+
for (let tIdx = 0; tIdx < t.length && qIdx < q.length; tIdx++) {
|
|
177
|
+
if (t[tIdx] === q[qIdx]) {
|
|
178
|
+
if (matchStart === -1) {
|
|
179
|
+
matchStart = tIdx;
|
|
180
|
+
}
|
|
181
|
+
qIdx++;
|
|
182
|
+
score += 1;
|
|
183
|
+
if (tIdx > 0 && matchStart === tIdx - 1) {
|
|
184
|
+
score += 0.5;
|
|
185
|
+
}
|
|
186
|
+
if (tIdx === 0 || /[\s\-_]/.test(t[tIdx - 1])) {
|
|
187
|
+
score += 0.3;
|
|
188
|
+
}
|
|
189
|
+
} else if (matchStart !== -1) {
|
|
190
|
+
indices.push([matchStart, tIdx - 1]);
|
|
191
|
+
matchStart = -1;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
if (matchStart !== -1) {
|
|
195
|
+
indices.push([matchStart, q.length - 1]);
|
|
196
|
+
}
|
|
197
|
+
if (qIdx < q.length) {
|
|
198
|
+
return { score: 0, indices: [] };
|
|
199
|
+
}
|
|
200
|
+
const normalizedScore = Math.min(score / (q.length * 2), 0.6);
|
|
201
|
+
return { score: normalizedScore, indices };
|
|
202
|
+
}
|
|
203
|
+
function searchIcons(query, options = {}) {
|
|
204
|
+
const {
|
|
205
|
+
limit = 50,
|
|
206
|
+
categories,
|
|
207
|
+
threshold = 0.3,
|
|
208
|
+
fuzzy: _fuzzy = true,
|
|
209
|
+
sortBy = "score"
|
|
210
|
+
} = options;
|
|
211
|
+
if (!query.trim()) {
|
|
212
|
+
return [];
|
|
213
|
+
}
|
|
214
|
+
const q = query.toLowerCase().trim();
|
|
215
|
+
const results = [];
|
|
216
|
+
iconRegistry.forEach(({ icon, metadata }, name) => {
|
|
217
|
+
if (categories && categories.length > 0 && !categories.includes(metadata.category)) {
|
|
218
|
+
return;
|
|
202
219
|
}
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
220
|
+
let bestScore = 0;
|
|
221
|
+
const matches = [];
|
|
222
|
+
const nameMatch = fuzzyMatch(q, name);
|
|
223
|
+
if (nameMatch.score > 0) {
|
|
224
|
+
bestScore = Math.max(bestScore, nameMatch.score * 1);
|
|
225
|
+
matches.push({ field: "name", value: name, indices: nameMatch.indices });
|
|
206
226
|
}
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
227
|
+
for (const tag of metadata.tags) {
|
|
228
|
+
const tagMatch = fuzzyMatch(q, tag);
|
|
229
|
+
if (tagMatch.score > 0) {
|
|
230
|
+
bestScore = Math.max(bestScore, tagMatch.score * 0.9);
|
|
231
|
+
matches.push({ field: "tags", value: tag, indices: tagMatch.indices });
|
|
232
|
+
}
|
|
211
233
|
}
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
if (t[tIdx] === q[qIdx]) {
|
|
219
|
-
if (matchStart === -1) {
|
|
220
|
-
matchStart = tIdx;
|
|
221
|
-
}
|
|
222
|
-
qIdx++;
|
|
223
|
-
score += 1;
|
|
224
|
-
// Bonus for consecutive matches
|
|
225
|
-
if (tIdx > 0 && matchStart === tIdx - 1) {
|
|
226
|
-
score += 0.5;
|
|
227
|
-
}
|
|
228
|
-
// Bonus for word boundary match
|
|
229
|
-
if (tIdx === 0 || /[\s\-_]/.test(t[tIdx - 1])) {
|
|
230
|
-
score += 0.3;
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
else if (matchStart !== -1) {
|
|
234
|
-
indices.push([matchStart, tIdx - 1]);
|
|
235
|
-
matchStart = -1;
|
|
234
|
+
if (metadata.aliases) {
|
|
235
|
+
for (const alias of metadata.aliases) {
|
|
236
|
+
const aliasMatch = fuzzyMatch(q, alias);
|
|
237
|
+
if (aliasMatch.score > 0) {
|
|
238
|
+
bestScore = Math.max(bestScore, aliasMatch.score * 0.85);
|
|
239
|
+
matches.push({ field: "aliases", value: alias, indices: aliasMatch.indices });
|
|
236
240
|
}
|
|
241
|
+
}
|
|
237
242
|
}
|
|
238
|
-
|
|
239
|
-
|
|
243
|
+
const categoryMatch = fuzzyMatch(q, metadata.category);
|
|
244
|
+
if (categoryMatch.score > 0) {
|
|
245
|
+
bestScore = Math.max(bestScore, categoryMatch.score * 0.5);
|
|
246
|
+
matches.push({ field: "category", value: metadata.category, indices: categoryMatch.indices });
|
|
240
247
|
}
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
248
|
+
if (metadata.description) {
|
|
249
|
+
const descMatch = fuzzyMatch(q, metadata.description);
|
|
250
|
+
if (descMatch.score > 0) {
|
|
251
|
+
bestScore = Math.max(bestScore, descMatch.score * 0.4);
|
|
252
|
+
matches.push({
|
|
253
|
+
field: "description",
|
|
254
|
+
value: metadata.description,
|
|
255
|
+
indices: descMatch.indices
|
|
256
|
+
});
|
|
257
|
+
}
|
|
244
258
|
}
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
* ```ts
|
|
254
|
-
* const results = searchIcons('home', { limit: 10 });
|
|
255
|
-
* const filteredResults = searchIcons('cart', { categories: ['ecommerce'] });
|
|
256
|
-
* ```
|
|
257
|
-
*/
|
|
258
|
-
function searchIcons(query, options = {}) {
|
|
259
|
-
const { limit = 50, categories, threshold = 0.3, fuzzy: _fuzzy = true, sortBy = 'score', } = options;
|
|
260
|
-
if (!query.trim()) {
|
|
261
|
-
return [];
|
|
259
|
+
if (bestScore >= threshold) {
|
|
260
|
+
results.push({
|
|
261
|
+
icon,
|
|
262
|
+
name,
|
|
263
|
+
metadata,
|
|
264
|
+
score: bestScore,
|
|
265
|
+
matches
|
|
266
|
+
});
|
|
262
267
|
}
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
if (nameMatch.score > 0) {
|
|
275
|
-
bestScore = Math.max(bestScore, nameMatch.score * 1.0);
|
|
276
|
-
matches.push({ field: 'name', value: name, indices: nameMatch.indices });
|
|
277
|
-
}
|
|
278
|
-
// Match tags (high weight)
|
|
279
|
-
for (const tag of metadata.tags) {
|
|
280
|
-
const tagMatch = fuzzyMatch(q, tag);
|
|
281
|
-
if (tagMatch.score > 0) {
|
|
282
|
-
bestScore = Math.max(bestScore, tagMatch.score * 0.9);
|
|
283
|
-
matches.push({ field: 'tags', value: tag, indices: tagMatch.indices });
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
// Match aliases (medium weight)
|
|
287
|
-
if (metadata.aliases) {
|
|
288
|
-
for (const alias of metadata.aliases) {
|
|
289
|
-
const aliasMatch = fuzzyMatch(q, alias);
|
|
290
|
-
if (aliasMatch.score > 0) {
|
|
291
|
-
bestScore = Math.max(bestScore, aliasMatch.score * 0.85);
|
|
292
|
-
matches.push({ field: 'aliases', value: alias, indices: aliasMatch.indices });
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
// Match category (low weight)
|
|
297
|
-
const categoryMatch = fuzzyMatch(q, metadata.category);
|
|
298
|
-
if (categoryMatch.score > 0) {
|
|
299
|
-
bestScore = Math.max(bestScore, categoryMatch.score * 0.5);
|
|
300
|
-
matches.push({ field: 'category', value: metadata.category, indices: categoryMatch.indices });
|
|
301
|
-
}
|
|
302
|
-
// Match description (lowest weight)
|
|
303
|
-
if (metadata.description) {
|
|
304
|
-
const descMatch = fuzzyMatch(q, metadata.description);
|
|
305
|
-
if (descMatch.score > 0) {
|
|
306
|
-
bestScore = Math.max(bestScore, descMatch.score * 0.4);
|
|
307
|
-
matches.push({
|
|
308
|
-
field: 'description',
|
|
309
|
-
value: metadata.description,
|
|
310
|
-
indices: descMatch.indices,
|
|
311
|
-
});
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
if (bestScore >= threshold) {
|
|
315
|
-
results.push({
|
|
316
|
-
icon,
|
|
317
|
-
name,
|
|
318
|
-
metadata,
|
|
319
|
-
score: bestScore,
|
|
320
|
-
matches,
|
|
321
|
-
});
|
|
322
|
-
}
|
|
323
|
-
});
|
|
324
|
-
// Sort results
|
|
325
|
-
results.sort((a, b) => {
|
|
326
|
-
if (sortBy === 'score') {
|
|
327
|
-
return b.score - a.score;
|
|
328
|
-
}
|
|
329
|
-
else if (sortBy === 'name') {
|
|
330
|
-
return a.name.localeCompare(b.name);
|
|
331
|
-
}
|
|
332
|
-
else {
|
|
333
|
-
return a.metadata.category.localeCompare(b.metadata.category);
|
|
334
|
-
}
|
|
335
|
-
});
|
|
336
|
-
return results.slice(0, limit);
|
|
268
|
+
});
|
|
269
|
+
results.sort((a, b) => {
|
|
270
|
+
if (sortBy === "score") {
|
|
271
|
+
return b.score - a.score;
|
|
272
|
+
} else if (sortBy === "name") {
|
|
273
|
+
return a.name.localeCompare(b.name);
|
|
274
|
+
} else {
|
|
275
|
+
return a.metadata.category.localeCompare(b.metadata.category);
|
|
276
|
+
}
|
|
277
|
+
});
|
|
278
|
+
return results.slice(0, limit);
|
|
337
279
|
}
|
|
338
|
-
/**
|
|
339
|
-
* Get suggestions for incomplete search queries.
|
|
340
|
-
*/
|
|
341
280
|
function getSearchSuggestions(partialQuery, limit = 5) {
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
281
|
+
if (!partialQuery.trim()) {
|
|
282
|
+
return ["home", "user", "settings", "search", "heart"];
|
|
283
|
+
}
|
|
284
|
+
const q = partialQuery.toLowerCase().trim();
|
|
285
|
+
const suggestions = /* @__PURE__ */ new Set();
|
|
286
|
+
iconRegistry.forEach(({ metadata }, name) => {
|
|
287
|
+
if (name.toLowerCase().startsWith(q)) {
|
|
288
|
+
suggestions.add(name);
|
|
345
289
|
}
|
|
346
|
-
const
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
// Suggest matching tags
|
|
354
|
-
for (const tag of metadata.tags) {
|
|
355
|
-
if (tag.toLowerCase().startsWith(q)) {
|
|
356
|
-
suggestions.add(tag);
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
});
|
|
360
|
-
return Array.from(suggestions).slice(0, limit);
|
|
290
|
+
for (const tag of metadata.tags) {
|
|
291
|
+
if (tag.toLowerCase().startsWith(q)) {
|
|
292
|
+
suggestions.add(tag);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
});
|
|
296
|
+
return Array.from(suggestions).slice(0, limit);
|
|
361
297
|
}
|
|
362
|
-
/* ────────────────────────────────────────────────────────────────────────────
|
|
363
|
-
PRE-DEFINED ICON METADATA
|
|
364
|
-
This will be populated when icons are imported
|
|
365
|
-
───────────────────────────────────────────────────────────────────────────── */
|
|
366
|
-
// Example metadata definitions (actual ones will be in icon files)
|
|
367
|
-
// audit-allow: i18n — English search metadata: searchIcons() matches these words.
|
|
368
298
|
const UI_ICON_METADATA = {
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
299
|
+
NtdHome: {
|
|
300
|
+
category: "ui",
|
|
301
|
+
tags: ["home", "house", "main", "start", "dashboard"],
|
|
302
|
+
aliases: ["house", "residence"],
|
|
303
|
+
description: "Home or main page icon",
|
|
304
|
+
useCases: ["navigation", "home button", "main page link"],
|
|
305
|
+
related: ["NtdBuilding", "NtdDoor"]
|
|
306
|
+
},
|
|
307
|
+
NtdUser: {
|
|
308
|
+
category: "ui",
|
|
309
|
+
tags: ["user", "person", "profile", "account", "avatar"],
|
|
310
|
+
aliases: ["person", "profile", "account"],
|
|
311
|
+
description: "Single user or profile icon",
|
|
312
|
+
useCases: ["user profile", "account settings", "avatar placeholder"],
|
|
313
|
+
related: ["NtdUsers", "NtdUserPlus", "NtdUserMinus"]
|
|
314
|
+
},
|
|
315
|
+
NtdUsers: {
|
|
316
|
+
category: "ui",
|
|
317
|
+
tags: ["users", "people", "group", "team", "multiple"],
|
|
318
|
+
aliases: ["people", "group", "team"],
|
|
319
|
+
description: "Multiple users or team icon",
|
|
320
|
+
useCases: ["team management", "group selection", "participants"],
|
|
321
|
+
related: ["NtdUser", "NtdUserPlus"]
|
|
322
|
+
},
|
|
323
|
+
NtdSettings: {
|
|
324
|
+
category: "ui",
|
|
325
|
+
tags: ["settings", "gear", "cog", "preferences", "config", "options"],
|
|
326
|
+
aliases: ["gear", "cog", "preferences", "configuration"],
|
|
327
|
+
description: "Settings or configuration icon",
|
|
328
|
+
useCases: ["settings menu", "preferences", "system configuration"],
|
|
329
|
+
related: ["NtdSliders", "NtdTool"]
|
|
330
|
+
},
|
|
331
|
+
NtdSearch: {
|
|
332
|
+
category: "ui",
|
|
333
|
+
tags: ["search", "find", "magnifier", "lookup", "query"],
|
|
334
|
+
aliases: ["find", "magnifying glass", "lookup"],
|
|
335
|
+
description: "Search or find icon",
|
|
336
|
+
useCases: ["search bar", "find function", "global search"],
|
|
337
|
+
related: ["NtdFilter", "NtdZoomIn"]
|
|
338
|
+
},
|
|
339
|
+
NtdHeart: {
|
|
340
|
+
category: "ui",
|
|
341
|
+
tags: ["heart", "love", "favorite", "like", "wishlist"],
|
|
342
|
+
aliases: ["love", "favorite", "like"],
|
|
343
|
+
description: "Heart or favorite icon",
|
|
344
|
+
useCases: ["like button", "favorites", "wishlist", "health"],
|
|
345
|
+
related: ["NtdHeartBroken", "NtdStar", "NtdThumbUp"]
|
|
346
|
+
},
|
|
347
|
+
NtdStar: {
|
|
348
|
+
category: "ui",
|
|
349
|
+
tags: ["star", "favorite", "rating", "bookmark", "important"],
|
|
350
|
+
aliases: ["favorite", "rating", "bookmark"],
|
|
351
|
+
description: "Star icon for ratings or favorites",
|
|
352
|
+
useCases: ["rating system", "favorites", "bookmarks", "featured"],
|
|
353
|
+
related: ["NtdHeart", "NtdBookmark"]
|
|
354
|
+
},
|
|
355
|
+
NtdBell: {
|
|
356
|
+
category: "ui",
|
|
357
|
+
tags: ["bell", "notification", "alert", "alarm", "ring"],
|
|
358
|
+
aliases: ["notification", "alert", "alarm"],
|
|
359
|
+
description: "Bell for notifications or alerts",
|
|
360
|
+
useCases: ["notifications", "alerts", "reminders"],
|
|
361
|
+
related: ["NtdBellOff", "NtdAlarm"]
|
|
362
|
+
}
|
|
433
363
|
};
|
|
434
|
-
// audit-allow: i18n — English search metadata: searchIcons() matches these words.
|
|
435
364
|
const ACTION_ICON_METADATA = {
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
365
|
+
NtdPlay: {
|
|
366
|
+
category: "actions",
|
|
367
|
+
tags: ["play", "start", "begin", "media", "video", "audio"],
|
|
368
|
+
aliases: ["start", "begin"],
|
|
369
|
+
description: "Play media or start action",
|
|
370
|
+
useCases: ["media player", "start button", "begin process"],
|
|
371
|
+
related: ["NtdPause", "NtdStop"]
|
|
372
|
+
},
|
|
373
|
+
NtdPause: {
|
|
374
|
+
category: "actions",
|
|
375
|
+
tags: ["pause", "stop", "hold", "media", "wait"],
|
|
376
|
+
aliases: ["hold", "wait"],
|
|
377
|
+
description: "Pause media or action",
|
|
378
|
+
useCases: ["media player", "pause button"],
|
|
379
|
+
related: ["NtdPlay", "NtdStop"]
|
|
380
|
+
},
|
|
381
|
+
NtdPlus: {
|
|
382
|
+
category: "actions",
|
|
383
|
+
tags: ["plus", "add", "new", "create", "increase"],
|
|
384
|
+
aliases: ["add", "new", "create"],
|
|
385
|
+
description: "Add or increase",
|
|
386
|
+
useCases: ["add item", "create new", "increase value"],
|
|
387
|
+
related: ["NtdMinus", "NtdX"]
|
|
388
|
+
},
|
|
389
|
+
NtdMinus: {
|
|
390
|
+
category: "actions",
|
|
391
|
+
tags: ["minus", "remove", "delete", "decrease", "subtract"],
|
|
392
|
+
aliases: ["remove", "subtract"],
|
|
393
|
+
description: "Remove or decrease",
|
|
394
|
+
useCases: ["remove item", "decrease value"],
|
|
395
|
+
related: ["NtdPlus", "NtdTrash"]
|
|
396
|
+
},
|
|
397
|
+
NtdCheck: {
|
|
398
|
+
category: "actions",
|
|
399
|
+
tags: ["check", "done", "complete", "success", "confirm", "tick"],
|
|
400
|
+
aliases: ["done", "complete", "tick", "confirm"],
|
|
401
|
+
description: "Checkmark for completion or confirmation",
|
|
402
|
+
useCases: ["confirm action", "task complete", "selection"],
|
|
403
|
+
related: ["NtdX", "NtdCheckCircle"]
|
|
404
|
+
},
|
|
405
|
+
NtdX: {
|
|
406
|
+
category: "actions",
|
|
407
|
+
tags: ["x", "close", "cancel", "remove", "delete", "cross"],
|
|
408
|
+
aliases: ["close", "cancel", "cross"],
|
|
409
|
+
description: "Close or cancel action",
|
|
410
|
+
useCases: ["close modal", "cancel action", "remove item"],
|
|
411
|
+
related: ["NtdCheck", "NtdTrash"]
|
|
412
|
+
},
|
|
413
|
+
NtdMenu: {
|
|
414
|
+
category: "actions",
|
|
415
|
+
tags: ["menu", "hamburger", "navigation", "sidebar", "drawer"],
|
|
416
|
+
aliases: ["hamburger", "nav", "drawer"],
|
|
417
|
+
description: "Hamburger menu icon",
|
|
418
|
+
useCases: ["mobile menu", "sidebar toggle", "navigation"],
|
|
419
|
+
related: ["NtdClose", "NtdMoreVertical"]
|
|
420
|
+
},
|
|
421
|
+
NtdClose: {
|
|
422
|
+
category: "actions",
|
|
423
|
+
tags: ["close", "x", "exit", "dismiss", "cancel"],
|
|
424
|
+
aliases: ["exit", "dismiss"],
|
|
425
|
+
description: "Close or exit",
|
|
426
|
+
useCases: ["close modal", "dismiss notification", "exit view"],
|
|
427
|
+
related: ["NtdMenu", "NtdX"]
|
|
428
|
+
}
|
|
500
429
|
};
|
|
501
|
-
/* ────────────────────────────────────────────────────────────────────────────
|
|
502
|
-
INITIALIZATION
|
|
503
|
-
Auto-register metadata when icons are imported
|
|
504
|
-
───────────────────────────────────────────────────────────────────────────── */
|
|
505
|
-
/**
|
|
506
|
-
* Initialize metadata for a set of icons.
|
|
507
|
-
* Called in icon module files.
|
|
508
|
-
*/
|
|
509
430
|
function initializeIconMetadata(icons, metadata) {
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
431
|
+
Object.entries(icons).forEach(([name, icon]) => {
|
|
432
|
+
const meta = metadata[name];
|
|
433
|
+
if (meta) {
|
|
434
|
+
registerIcon(name, icon, meta);
|
|
435
|
+
}
|
|
436
|
+
});
|
|
516
437
|
}
|
|
517
|
-
|
|
518
|
-
|
|
438
|
+
export {
|
|
439
|
+
ACTION_ICON_METADATA,
|
|
440
|
+
CATEGORY_INFO,
|
|
441
|
+
UI_ICON_METADATA,
|
|
442
|
+
getAllIcons,
|
|
443
|
+
getCategoryCounts,
|
|
444
|
+
getIcon,
|
|
445
|
+
getIconMetadata,
|
|
446
|
+
getIconsByCategory,
|
|
447
|
+
getSearchSuggestions,
|
|
448
|
+
initializeIconMetadata,
|
|
449
|
+
registerIcon,
|
|
450
|
+
searchIcons
|
|
451
|
+
};
|