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