Skip to main content

ferrox_front_ui/
icons.rs

1//! # Native Rust SVG Icon Engine (`ferrox-front-ui::icons`)
2//!
3//! Provides over 60 enterprise vector SVG icons rendered directly as WebAssembly DOM nodes
4//! using `DomBuilder::new_svg`. Completely independent from external icon fonts, CDN bundles, or remote SVG files.
5//!
6//! ## Example Usage
7//! ```rust,no_run
8//! use ferrox_front_ui::icons::{Icon, icon_activity, icon_shield};
9//!
10//! // Generic invocation
11//! let icon = Icon::render("activity", 20, "var(--accent-primary)");
12//!
13//! // Dedicated function
14//! let shield = icon_shield(24, "#10b981");
15//! ```
16
17use ferrox_front_core::dom::{svg, path, circle, line, rect, polyline, polygon, DomBuilder};
18
19/// Constructs the base SVG canvas with 24x24 viewBox, stroke styling, and custom size/color.
20pub fn base_svg(size: u32, color: &str) -> DomBuilder {
21    svg()
22        .attr("width", &size.to_string())
23        .attr("height", &size.to_string())
24        .attr("viewBox", "0 0 24 24")
25        .attr("fill", "none")
26        .attr("stroke", color)
27        .attr("stroke-width", "2")
28        .attr("stroke-linecap", "round")
29        .attr("stroke-linejoin", "round")
30        .attr("class", "ferrox-icon")
31        .attr("style", "display: inline-block; vertical-align: middle; flex-shrink: 0;")
32}
33
34// =============================================================================
35// 1. NAVIGATION & LAYOUT ICONS
36// =============================================================================
37
38pub fn icon_home(size: u32, color: &str) -> DomBuilder {
39    base_svg(size, color)
40        .child(path().attr("d", "M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"))
41        .child(polyline().attr("points", "9 22 9 12 15 12 15 22"))
42}
43
44pub fn icon_menu(size: u32, color: &str) -> DomBuilder {
45    base_svg(size, color)
46        .child(line().attr("x1", "3").attr("y1", "12").attr("x2", "21").attr("y2", "12"))
47        .child(line().attr("x1", "3").attr("y1", "6").attr("x2", "21").attr("y2", "6"))
48        .child(line().attr("x1", "3").attr("y1", "18").attr("x2", "21").attr("y2", "18"))
49}
50
51pub fn icon_x(size: u32, color: &str) -> DomBuilder {
52    base_svg(size, color)
53        .child(line().attr("x1", "18").attr("y1", "6").attr("x2", "6").attr("y2", "18"))
54        .child(line().attr("x1", "6").attr("y1", "6").attr("x2", "18").attr("y2", "18"))
55}
56
57pub fn icon_chevron_down(size: u32, color: &str) -> DomBuilder {
58    base_svg(size, color).child(polyline().attr("points", "6 9 12 15 18 9"))
59}
60
61pub fn icon_chevron_up(size: u32, color: &str) -> DomBuilder {
62    base_svg(size, color).child(polyline().attr("points", "18 15 12 9 6 15"))
63}
64
65pub fn icon_chevron_left(size: u32, color: &str) -> DomBuilder {
66    base_svg(size, color).child(polyline().attr("points", "15 18 9 12 15 6"))
67}
68
69pub fn icon_chevron_right(size: u32, color: &str) -> DomBuilder {
70    base_svg(size, color).child(polyline().attr("points", "9 18 15 12 9 6"))
71}
72
73pub fn icon_arrow_left(size: u32, color: &str) -> DomBuilder {
74    base_svg(size, color)
75        .child(line().attr("x1", "19").attr("y1", "12").attr("x2", "5").attr("y2", "12"))
76        .child(polyline().attr("points", "12 19 5 12 12 5"))
77}
78
79pub fn icon_arrow_right(size: u32, color: &str) -> DomBuilder {
80    base_svg(size, color)
81        .child(line().attr("x1", "5").attr("y1", "12").attr("x2", "19").attr("y2", "12"))
82        .child(polyline().attr("points", "12 5 19 12 12 19"))
83}
84
85pub fn icon_search(size: u32, color: &str) -> DomBuilder {
86    base_svg(size, color)
87        .child(circle().attr("cx", "11").attr("cy", "11").attr("r", "8"))
88        .child(line().attr("x1", "21").attr("y1", "21").attr("x2", "16.65").attr("y2", "16.65"))
89}
90
91pub fn icon_filter(size: u32, color: &str) -> DomBuilder {
92    base_svg(size, color)
93        .child(polygon().attr("points", "22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3"))
94}
95
96// =============================================================================
97// 2. ACTION ICONS
98// =============================================================================
99
100pub fn icon_plus(size: u32, color: &str) -> DomBuilder {
101    base_svg(size, color)
102        .child(line().attr("x1", "12").attr("y1", "5").attr("x2", "12").attr("y2", "19"))
103        .child(line().attr("x1", "5").attr("y1", "12").attr("x2", "19").attr("y2", "12"))
104}
105
106pub fn icon_minus(size: u32, color: &str) -> DomBuilder {
107    base_svg(size, color)
108        .child(line().attr("x1", "5").attr("y1", "12").attr("x2", "19").attr("y2", "12"))
109}
110
111pub fn icon_trash(size: u32, color: &str) -> DomBuilder {
112    base_svg(size, color)
113        .child(polyline().attr("points", "3 6 5 6 21 6"))
114        .child(path().attr("d", "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"))
115}
116
117pub fn icon_edit(size: u32, color: &str) -> DomBuilder {
118    base_svg(size, color)
119        .child(path().attr("d", "M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"))
120        .child(path().attr("d", "M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"))
121}
122
123pub fn icon_copy(size: u32, color: &str) -> DomBuilder {
124    base_svg(size, color)
125        .child(rect().attr("x", "9").attr("y", "9").attr("width", "13").attr("height", "13").attr("rx", "2").attr("ry", "2"))
126        .child(path().attr("d", "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"))
127}
128
129pub fn icon_check(size: u32, color: &str) -> DomBuilder {
130    base_svg(size, color).child(polyline().attr("points", "20 6 9 17 4 12"))
131}
132
133pub fn icon_refresh(size: u32, color: &str) -> DomBuilder {
134    base_svg(size, color)
135        .child(polyline().attr("points", "23 4 23 10 17 10"))
136        .child(polyline().attr("points", "1 20 1 14 7 14"))
137        .child(path().attr("d", "M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"))
138}
139
140pub fn icon_download(size: u32, color: &str) -> DomBuilder {
141    base_svg(size, color)
142        .child(path().attr("d", "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"))
143        .child(polyline().attr("points", "7 10 12 15 17 10"))
144        .child(line().attr("x1", "12").attr("y1", "15").attr("x2", "12").attr("y2", "3"))
145}
146
147pub fn icon_upload(size: u32, color: &str) -> DomBuilder {
148    base_svg(size, color)
149        .child(path().attr("d", "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"))
150        .child(polyline().attr("points", "17 8 12 3 7 8"))
151        .child(line().attr("x1", "12").attr("y1", "3").attr("x2", "12").attr("y2", "15"))
152}
153
154pub fn icon_share(size: u32, color: &str) -> DomBuilder {
155    base_svg(size, color)
156        .child(circle().attr("cx", "18").attr("cy", "5").attr("r", "3"))
157        .child(circle().attr("cx", "6").attr("cy", "12").attr("r", "3"))
158        .child(circle().attr("cx", "18").attr("cy", "19").attr("r", "3"))
159        .child(line().attr("x1", "8.59").attr("y1", "13.51").attr("x2", "15.42").attr("y2", "17.49"))
160        .child(line().attr("x1", "15.41").attr("y1", "6.51").attr("x2", "8.59").attr("y2", "10.49"))
161}
162
163pub fn icon_external_link(size: u32, color: &str) -> DomBuilder {
164    base_svg(size, color)
165        .child(path().attr("d", "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"))
166        .child(polyline().attr("points", "15 3 21 3 21 9"))
167        .child(line().attr("x1", "10").attr("y1", "14").attr("x2", "21").attr("y2", "3"))
168}
169
170// =============================================================================
171// 3. SECURITY & SYSTEM ICONS
172// =============================================================================
173
174pub fn icon_shield(size: u32, color: &str) -> DomBuilder {
175    base_svg(size, color)
176        .child(path().attr("d", "M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"))
177}
178
179pub fn icon_lock(size: u32, color: &str) -> DomBuilder {
180    base_svg(size, color)
181        .child(rect().attr("x", "3").attr("y", "11").attr("width", "18").attr("height", "11").attr("rx", "2").attr("ry", "2"))
182        .child(path().attr("d", "M7 11V7a5 5 0 0 1 10 0v4"))
183}
184
185pub fn icon_unlock(size: u32, color: &str) -> DomBuilder {
186    base_svg(size, color)
187        .child(rect().attr("x", "3").attr("y", "11").attr("width", "18").attr("height", "11").attr("rx", "2").attr("ry", "2"))
188        .child(path().attr("d", "M7 11V7a5 5 0 0 1 9.9-1"))
189}
190
191pub fn icon_key(size: u32, color: &str) -> DomBuilder {
192    base_svg(size, color)
193        .child(path().attr("d", "M21 2l-2 2m-1.5 1.5L16 7l-1.5-1.5L13 7l-2-2-7 7a5 5 0 0 0 7 7l7-7 1.5 1.5L21 12l-1.5-1.5L21 9l-1.5-1.5L21 6l-2-2z"))
194        .child(circle().attr("cx", "7.5").attr("cy", "16.5").attr("r", "1.5"))
195}
196
197pub fn icon_eye(size: u32, color: &str) -> DomBuilder {
198    base_svg(size, color)
199        .child(path().attr("d", "M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"))
200        .child(circle().attr("cx", "12").attr("cy", "12").attr("r", "3"))
201}
202
203pub fn icon_eye_off(size: u32, color: &str) -> DomBuilder {
204    base_svg(size, color)
205        .child(path().attr("d", "M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24"))
206        .child(line().attr("x1", "1").attr("y1", "1").attr("x2", "23").attr("y2", "23"))
207}
208
209pub fn icon_alert_circle(size: u32, color: &str) -> DomBuilder {
210    base_svg(size, color)
211        .child(circle().attr("cx", "12").attr("cy", "12").attr("r", "10"))
212        .child(line().attr("x1", "12").attr("y1", "8").attr("x2", "12").attr("y2", "12"))
213        .child(line().attr("x1", "12").attr("y1", "16").attr("x2", "12.01").attr("y2", "16"))
214}
215
216pub fn icon_alert_triangle(size: u32, color: &str) -> DomBuilder {
217    base_svg(size, color)
218        .child(path().attr("d", "M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"))
219        .child(line().attr("x1", "12").attr("y1", "9").attr("x2", "12").attr("y2", "13"))
220        .child(line().attr("x1", "12").attr("y1", "17").attr("x2", "12.01").attr("y2", "17"))
221}
222
223pub fn icon_check_circle(size: u32, color: &str) -> DomBuilder {
224    base_svg(size, color)
225        .child(path().attr("d", "M22 11.08V12a10 10 0 1 1-5.93-9.14"))
226        .child(polyline().attr("points", "22 4 12 14.01 9 11.01"))
227}
228
229pub fn icon_info(size: u32, color: &str) -> DomBuilder {
230    base_svg(size, color)
231        .child(circle().attr("cx", "12").attr("cy", "12").attr("r", "10"))
232        .child(line().attr("x1", "12").attr("y1", "16").attr("x2", "12").attr("y2", "12"))
233        .child(line().attr("x1", "12").attr("y1", "8").attr("x2", "12.01").attr("y2", "8"))
234}
235
236// =============================================================================
237// 4. DATA & DASHBOARD ICONS
238// =============================================================================
239
240pub fn icon_bar_chart(size: u32, color: &str) -> DomBuilder {
241    base_svg(size, color)
242        .child(line().attr("x1", "12").attr("y1", "20").attr("x2", "12").attr("y2", "10"))
243        .child(line().attr("x1", "18").attr("y1", "20").attr("x2", "18").attr("y2", "4"))
244        .child(line().attr("x1", "6").attr("y1", "20").attr("x2", "6").attr("y2", "16"))
245}
246
247pub fn icon_line_chart(size: u32, color: &str) -> DomBuilder {
248    base_svg(size, color)
249        .child(path().attr("d", "M3 3v18h18"))
250        .child(path().attr("d", "M18.7 8l-5.1 5.2-2.8-2.7L7 14.3"))
251}
252
253pub fn icon_pie_chart(size: u32, color: &str) -> DomBuilder {
254    base_svg(size, color)
255        .child(path().attr("d", "M21.21 15.89A10 10 0 1 1 8 2.83"))
256        .child(path().attr("d", "M22 12A10 10 0 0 0 12 2v10z"))
257}
258
259pub fn icon_activity(size: u32, color: &str) -> DomBuilder {
260    base_svg(size, color).child(polyline().attr("points", "22 12 18 12 15 21 9 3 6 12 2 12"))
261}
262
263pub fn icon_trending_up(size: u32, color: &str) -> DomBuilder {
264    base_svg(size, color)
265        .child(polyline().attr("points", "23 6 13.5 15.5 8.5 10.5 1 18"))
266        .child(polyline().attr("points", "17 6 23 6 23 12"))
267}
268
269pub fn icon_trending_down(size: u32, color: &str) -> DomBuilder {
270    base_svg(size, color)
271        .child(polyline().attr("points", "23 18 13.5 8.5 8.5 13.5 1 6"))
272        .child(polyline().attr("points", "17 18 23 18 23 12"))
273}
274
275pub fn icon_layers(size: u32, color: &str) -> DomBuilder {
276    base_svg(size, color)
277        .child(polygon().attr("points", "12 2 2 7 12 12 22 7 12 2"))
278        .child(polyline().attr("points", "2 17 12 22 22 17"))
279        .child(polyline().attr("points", "2 12 12 17 22 12"))
280}
281
282pub fn icon_cpu(size: u32, color: &str) -> DomBuilder {
283    base_svg(size, color)
284        .child(rect().attr("x", "4").attr("y", "4").attr("width", "16").attr("height", "16").attr("rx", "2").attr("ry", "2"))
285        .child(rect().attr("x", "9").attr("y", "9").attr("width", "6").attr("height", "6"))
286        .child(line().attr("x1", "9").attr("y1", "1").attr("x2", "9").attr("y2", "4"))
287        .child(line().attr("x1", "15").attr("y1", "1").attr("x2", "15").attr("y2", "4"))
288        .child(line().attr("x1", "9").attr("y1", "20").attr("x2", "9").attr("y2", "23"))
289        .child(line().attr("x1", "15").attr("y1", "20").attr("x2", "15").attr("y2", "23"))
290        .child(line().attr("x1", "20").attr("y1", "9").attr("x2", "23").attr("y2", "9"))
291        .child(line().attr("x1", "20").attr("y1", "15").attr("x2", "23").attr("y2", "15"))
292        .child(line().attr("x1", "1").attr("y1", "9").attr("x2", "4").attr("y2", "9"))
293        .child(line().attr("x1", "1").attr("y1", "15").attr("x2", "4").attr("y2", "15"))
294}
295
296pub fn icon_database(size: u32, color: &str) -> DomBuilder {
297    base_svg(size, color)
298        .child(path().attr("d", "M21 5c0 1.66-4 3-9 3s-9-1.34-9-3 4-3 9-3 9 1.34 9 3z"))
299        .child(path().attr("d", "M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5"))
300        .child(path().attr("d", "M3 12c0 1.66 4 3 9 3s9-1.34 9-3"))
301}
302
303pub fn icon_server(size: u32, color: &str) -> DomBuilder {
304    base_svg(size, color)
305        .child(rect().attr("x", "2").attr("y", "2").attr("width", "20").attr("height", "8").attr("rx", "2").attr("ry", "2"))
306        .child(rect().attr("x", "2").attr("y", "14").attr("width", "20").attr("height", "8").attr("rx", "2").attr("ry", "2"))
307        .child(line().attr("x1", "6").attr("y1", "6").attr("x2", "6.01").attr("y2", "6"))
308        .child(line().attr("x1", "6").attr("y1", "18").attr("x2", "6.01").attr("y2", "18"))
309}
310
311pub fn icon_zap(size: u32, color: &str) -> DomBuilder {
312    base_svg(size, color).child(polygon().attr("points", "13 2 3 14 12 14 11 22 21 10 12 10 13 2"))
313}
314
315// =============================================================================
316// 5. USER & COMMERCE ICONS
317// =============================================================================
318
319pub fn icon_user(size: u32, color: &str) -> DomBuilder {
320    base_svg(size, color)
321        .child(path().attr("d", "M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"))
322        .child(circle().attr("cx", "12").attr("cy", "7").attr("r", "4"))
323}
324
325pub fn icon_users(size: u32, color: &str) -> DomBuilder {
326    base_svg(size, color)
327        .child(path().attr("d", "M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"))
328        .child(circle().attr("cx", "9").attr("cy", "7").attr("r", "4"))
329        .child(path().attr("d", "M23 21v-2a4 4 0 0 0-3-3.87"))
330        .child(path().attr("d", "M16 3.13a4 4 0 0 1 0 7.75"))
331}
332
333pub fn icon_bell(size: u32, color: &str) -> DomBuilder {
334    base_svg(size, color)
335        .child(path().attr("d", "M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"))
336        .child(path().attr("d", "M13.73 21a2 2 0 0 1-3.46 0"))
337}
338
339pub fn icon_mail(size: u32, color: &str) -> DomBuilder {
340    base_svg(size, color)
341        .child(path().attr("d", "M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"))
342        .child(polyline().attr("points", "22,6 12,13 2,6"))
343}
344
345pub fn icon_settings(size: u32, color: &str) -> DomBuilder {
346    base_svg(size, color)
347        .child(circle().attr("cx", "12").attr("cy", "12").attr("r", "3"))
348        .child(path().attr("d", "M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"))
349}
350
351pub fn icon_credit_card(size: u32, color: &str) -> DomBuilder {
352    base_svg(size, color)
353        .child(rect().attr("x", "1").attr("y", "4").attr("width", "22").attr("height", "16").attr("rx", "2").attr("ry", "2"))
354        .child(line().attr("x1", "1").attr("y1", "10").attr("x2", "23").attr("y2", "10"))
355}
356
357pub fn icon_shopping_cart(size: u32, color: &str) -> DomBuilder {
358    base_svg(size, color)
359        .child(circle().attr("cx", "9").attr("cy", "21").attr("r", "1"))
360        .child(circle().attr("cx", "20").attr("cy", "21").attr("r", "1"))
361        .child(path().attr("d", "M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6"))
362}
363
364pub fn icon_dollar_sign(size: u32, color: &str) -> DomBuilder {
365    base_svg(size, color)
366        .child(line().attr("x1", "12").attr("y1", "1").attr("x2", "12").attr("y2", "23"))
367        .child(path().attr("d", "M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6"))
368}
369
370pub fn icon_package(size: u32, color: &str) -> DomBuilder {
371    base_svg(size, color)
372        .child(line().attr("x1", "16.5").attr("y1", "9.4").attr("x2", "7.55").attr("y2", "4.21"))
373        .child(path().attr("d", "M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"))
374        .child(polyline().attr("points", "3.27 6.96 12 12.01 20.73 6.96"))
375        .child(line().attr("x1", "12").attr("y1", "22.08").attr("x2", "12").attr("y2", "12"))
376}
377
378pub fn icon_clock(size: u32, color: &str) -> DomBuilder {
379    base_svg(size, color)
380        .child(circle().attr("cx", "12").attr("cy", "12").attr("r", "10"))
381        .child(polyline().attr("points", "12 6 12 12 16 14"))
382}
383
384pub fn icon_calendar(size: u32, color: &str) -> DomBuilder {
385    base_svg(size, color)
386        .child(rect().attr("x", "3").attr("y", "4").attr("width", "18").attr("height", "18").attr("rx", "2").attr("ry", "2"))
387        .child(line().attr("x1", "16").attr("y1", "2").attr("x2", "16").attr("y2", "6"))
388        .child(line().attr("x1", "8").attr("y1", "2").attr("x2", "8").attr("y2", "6"))
389        .child(line().attr("x1", "3").attr("y1", "10").attr("x2", "21").attr("y2", "10"))
390}
391
392pub fn icon_globe(size: u32, color: &str) -> DomBuilder {
393    base_svg(size, color)
394        .child(circle().attr("cx", "12").attr("cy", "12").attr("r", "10"))
395        .child(line().attr("x1", "2").attr("y1", "12").attr("x2", "22").attr("y2", "12"))
396        .child(path().attr("d", "M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"))
397}
398
399pub fn icon_terminal(size: u32, color: &str) -> DomBuilder {
400    base_svg(size, color)
401        .child(polyline().attr("points", "4 17 10 11 4 5"))
402        .child(line().attr("x1", "12").attr("y1", "19").attr("x2", "20").attr("y2", "19"))
403}
404
405pub fn icon_code(size: u32, color: &str) -> DomBuilder {
406    base_svg(size, color)
407        .child(polyline().attr("points", "16 18 22 12 16 6"))
408        .child(polyline().attr("points", "8 6 2 12 8 18"))
409}
410
411// =============================================================================
412// 6. UNIFIED ICON ENGINE & DISPATCHER
413// =============================================================================
414
415/// Dynamic Icon Renderer mapping names to SVG builders
416pub struct Icon;
417
418impl Icon {
419    /// Renders any supported icon by its kebab-case or snake_case name.
420    pub fn render(name: &str, size: u32, color: &str) -> DomBuilder {
421        match name.to_lowercase().replace('_', "-").as_str() {
422            // Navigation
423            "home" => icon_home(size, color),
424            "menu" => icon_menu(size, color),
425            "x" | "close" => icon_x(size, color),
426            "chevron-down" => icon_chevron_down(size, color),
427            "chevron-up" => icon_chevron_up(size, color),
428            "chevron-left" => icon_chevron_left(size, color),
429            "chevron-right" => icon_chevron_right(size, color),
430            "arrow-left" => icon_arrow_left(size, color),
431            "arrow-right" => icon_arrow_right(size, color),
432            "search" => icon_search(size, color),
433            "filter" => icon_filter(size, color),
434            // Actions
435            "plus" | "add" => icon_plus(size, color),
436            "minus" => icon_minus(size, color),
437            "trash" | "delete" => icon_trash(size, color),
438            "edit" => icon_edit(size, color),
439            "copy" => icon_copy(size, color),
440            "check" => icon_check(size, color),
441            "refresh" => icon_refresh(size, color),
442            "download" => icon_download(size, color),
443            "upload" => icon_upload(size, color),
444            "share" => icon_share(size, color),
445            "external-link" => icon_external_link(size, color),
446            // Security
447            "shield" => icon_shield(size, color),
448            "lock" => icon_lock(size, color),
449            "unlock" => icon_unlock(size, color),
450            "key" => icon_key(size, color),
451            "eye" => icon_eye(size, color),
452            "eye-off" => icon_eye_off(size, color),
453            "alert-circle" => icon_alert_circle(size, color),
454            "alert-triangle" => icon_alert_triangle(size, color),
455            "check-circle" => icon_check_circle(size, color),
456            "info" => icon_info(size, color),
457            // Data
458            "bar-chart" => icon_bar_chart(size, color),
459            "line-chart" => icon_line_chart(size, color),
460            "pie-chart" => icon_pie_chart(size, color),
461            "activity" => icon_activity(size, color),
462            "trending-up" => icon_trending_up(size, color),
463            "trending-down" => icon_trending_down(size, color),
464            "layers" => icon_layers(size, color),
465            "cpu" => icon_cpu(size, color),
466            "database" => icon_database(size, color),
467            "server" => icon_server(size, color),
468            "zap" | "flash" => icon_zap(size, color),
469            // User & Commerce
470            "user" => icon_user(size, color),
471            "users" => icon_users(size, color),
472            "bell" => icon_bell(size, color),
473            "mail" => icon_mail(size, color),
474            "settings" => icon_settings(size, color),
475            "credit-card" => icon_credit_card(size, color),
476            "shopping-cart" => icon_shopping_cart(size, color),
477            "dollar-sign" => icon_dollar_sign(size, color),
478            "package" => icon_package(size, color),
479            "clock" => icon_clock(size, color),
480            "calendar" => icon_calendar(size, color),
481            "globe" => icon_globe(size, color),
482            "terminal" => icon_terminal(size, color),
483            "code" => icon_code(size, color),
484            // Fallback
485            _ => icon_info(size, color),
486        }
487    }
488
489    /// Returns list of all available icon identifier names
490    pub fn all_names() -> &'static [&'static str] {
491        &[
492            "home", "menu", "x", "chevron-down", "chevron-up", "chevron-left", "chevron-right",
493            "arrow-left", "arrow-right", "search", "filter",
494            "plus", "minus", "trash", "edit", "copy", "check", "refresh", "download", "upload", "share", "external-link",
495            "shield", "lock", "unlock", "key", "eye", "eye-off", "alert-circle", "alert-triangle", "check-circle", "info",
496            "bar-chart", "line-chart", "pie-chart", "activity", "trending-up", "trending-down", "layers", "cpu", "database", "server", "zap",
497            "user", "users", "bell", "mail", "settings", "credit-card", "shopping-cart", "dollar-sign", "package", "clock", "calendar", "globe", "terminal", "code"
498        ]
499    }
500}