| 1 | // Icon path data sourced from lucide-react v0.574.0 (ISC). |
| 2 | // We inline the SVG node tuples so inserted icons render without the React runtime. |
| 3 | |
| 4 | export type IconNodeTuple = |
| 5 | | ['path', { d: string }] |
| 6 | | ['circle', { cx: number; cy: number; r: number }] |
| 7 | | ['ellipse', { cx: number; cy: number; rx: number; ry: number }] |
| 8 | | ['line', { x1: number; x2: number; y1: number; y2: number }] |
| 9 | | ['rect', { x: number; y: number; width: number; height: number; rx?: number; ry?: number }] |
| 10 | |
| 11 | export type IconDefinition = |
| 12 | | { |
| 13 | id: string |
| 14 | label: string |
| 15 | variant?: 'stroke' |
| 16 | nodes: IconNodeTuple[] |
| 17 | } |
| 18 | | { |
| 19 | id: string |
| 20 | label: string |
| 21 | variant: 'badge' |
| 22 | badgeNumber: number |
| 23 | } |
| 24 | |
| 25 | /** All registry icons share lucide's 24x24 viewBox. */ |
| 26 | export const ICON_VIEWBOX = 24 |
| 27 | |
| 28 | const STROKE_ICONS: IconDefinition[] = [ |
| 29 | { |
| 30 | id: 'sparkles', |
| 31 | label: 'Sparkles', |
| 32 | nodes: [ |
| 33 | ['path', { d: 'M11.017 2.814a1 1 0 0 1 1.966 0l1.051 5.558a2 2 0 0 0 1.594 1.594l5.558 1.051a1 1 0 0 1 0 1.966l-5.558 1.051a2 2 0 0 0-1.594 1.594l-1.051 5.558a1 1 0 0 1-1.966 0l-1.051-5.558a2 2 0 0 0-1.594-1.594l-5.558-1.051a1 1 0 0 1 0-1.966l5.558-1.051a2 2 0 0 0 1.594-1.594z' }], |
| 34 | ['path', { d: 'M20 2v4' }], |
| 35 | ['path', { d: 'M22 4h-4' }], |
| 36 | ['circle', { cx: 4, cy: 20, r: 2 }] |
| 37 | ] |
| 38 | }, |
| 39 | { |
| 40 | id: 'star', |
| 41 | label: 'Star', |
| 42 | nodes: [ |
| 43 | ['path', { d: 'M11.525 2.295a.53.53 0 0 1 .95 0l2.31 4.679a2.123 2.123 0 0 0 1.595 1.16l5.166.756a.53.53 0 0 1 .294.904l-3.736 3.638a2.123 2.123 0 0 0-.611 1.878l.882 5.14a.53.53 0 0 1-.771.56l-4.618-2.428a2.122 2.122 0 0 0-1.973 0L6.396 21.01a.53.53 0 0 1-.77-.56l.881-5.139a2.122 2.122 0 0 0-.611-1.879L2.16 9.795a.53.53 0 0 1 .294-.906l5.165-.755a2.122 2.122 0 0 0 1.597-1.16z' }] |
| 44 | ] |
| 45 | }, |
| 46 | { |
| 47 | id: 'heart', |
| 48 | label: 'Heart', |
| 49 | nodes: [ |
| 50 | ['path', { d: 'M2 9.5a5.5 5.5 0 0 1 9.591-3.676.56.56 0 0 0 .818 0A5.49 5.49 0 0 1 22 9.5c0 2.29-1.5 4-3 5.5l-5.492 5.313a2 2 0 0 1-3 .019L5 15c-1.5-1.5-3-3.2-3-5.5' }] |
| 51 | ] |
| 52 | }, |
| 53 | { |
| 54 | id: 'check', |
| 55 | label: 'Check', |
| 56 | nodes: [['path', { d: 'M20 6 9 17l-5-5' }]] |
| 57 | }, |
| 58 | { |
| 59 | id: 'x', |
| 60 | label: 'Close', |
| 61 | nodes: [ |
| 62 | ['path', { d: 'M18 6 6 18' }], |
| 63 | ['path', { d: 'm6 6 12 12' }] |
| 64 | ] |
| 65 | }, |
| 66 | { |
| 67 | id: 'plus', |
| 68 | label: 'Plus', |
| 69 | nodes: [ |
| 70 | ['path', { d: 'M5 12h14' }], |
| 71 | ['path', { d: 'M12 5v14' }] |
| 72 | ] |
| 73 | }, |
| 74 | { |
| 75 | id: 'minus', |
| 76 | label: 'Minus', |
| 77 | nodes: [['path', { d: 'M5 12h14' }]] |
| 78 | }, |
| 79 | { |
| 80 | id: 'arrow-left', |
| 81 | label: 'Arrow left', |
| 82 | nodes: [ |
| 83 | ['path', { d: 'm12 19-7-7 7-7' }], |
| 84 | ['path', { d: 'M19 12H5' }] |
| 85 | ] |
| 86 | }, |
| 87 | { |
| 88 | id: 'arrow-right', |
| 89 | label: 'Arrow right', |
| 90 | nodes: [ |
| 91 | ['path', { d: 'M5 12h14' }], |
| 92 | ['path', { d: 'm12 5 7 7-7 7' }] |
| 93 | ] |
| 94 | }, |
| 95 | { |
| 96 | id: 'arrow-up', |
| 97 | label: 'Arrow up', |
| 98 | nodes: [ |
| 99 | ['path', { d: 'm5 12 7-7 7 7' }], |
| 100 | ['path', { d: 'M12 19V5' }] |
| 101 | ] |
| 102 | }, |
| 103 | { |
| 104 | id: 'arrow-down', |
| 105 | label: 'Arrow down', |
| 106 | nodes: [ |
| 107 | ['path', { d: 'M12 5v14' }], |
| 108 | ['path', { d: 'm19 12-7 7-7-7' }] |
| 109 | ] |
| 110 | }, |
| 111 | { |
| 112 | id: 'arrow-up-right', |
| 113 | label: 'Arrow up right', |
| 114 | nodes: [ |
| 115 | ['path', { d: 'M7 7h10v10' }], |
| 116 | ['path', { d: 'M7 17 17 7' }] |
| 117 | ] |
| 118 | }, |
| 119 | { |
| 120 | id: 'chevron-left', |
| 121 | label: 'Chevron left', |
| 122 | nodes: [['path', { d: 'm15 18-6-6 6-6' }]] |
| 123 | }, |
| 124 | { |
| 125 | id: 'chevron-right', |
| 126 | label: 'Chevron right', |
| 127 | nodes: [['path', { d: 'm9 18 6-6-6-6' }]] |
| 128 | }, |
| 129 | { |
| 130 | id: 'chevron-up', |
| 131 | label: 'Chevron up', |
| 132 | nodes: [['path', { d: 'm18 15-6-6-6 6' }]] |
| 133 | }, |
| 134 | { |
| 135 | id: 'chevron-down', |
| 136 | label: 'Chevron down', |
| 137 | nodes: [['path', { d: 'm6 9 6 6 6-6' }]] |
| 138 | }, |
| 139 | { |
| 140 | id: 'circle-alert', |
| 141 | label: 'Alert', |
| 142 | nodes: [ |
| 143 | ['circle', { cx: 12, cy: 12, r: 10 }], |
| 144 | ['line', { x1: 12, x2: 12, y1: 8, y2: 12 }], |
| 145 | ['line', { x1: 12, x2: 12.01, y1: 16, y2: 16 }] |
| 146 | ] |
| 147 | }, |
| 148 | { |
| 149 | id: 'circle-help', |
| 150 | label: 'Help', |
| 151 | nodes: [ |
| 152 | ['circle', { cx: 12, cy: 12, r: 10 }], |
| 153 | ['path', { d: 'M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3' }], |
| 154 | ['path', { d: 'M12 17h.01' }] |
| 155 | ] |
| 156 | }, |
| 157 | { |
| 158 | id: 'info', |
| 159 | label: 'Info', |
| 160 | nodes: [ |
| 161 | ['circle', { cx: 12, cy: 12, r: 10 }], |
| 162 | ['path', { d: 'M12 16v-4' }], |
| 163 | ['path', { d: 'M12 8h.01' }] |
| 164 | ] |
| 165 | }, |
| 166 | { |
| 167 | id: 'lightbulb', |
| 168 | label: 'Lightbulb', |
| 169 | nodes: [ |
| 170 | ['path', { d: 'M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5' }], |
| 171 | ['path', { d: 'M9 18h6' }], |
| 172 | ['path', { d: 'M10 22h4' }] |
| 173 | ] |
| 174 | }, |
| 175 | { |
| 176 | id: 'target', |
| 177 | label: 'Target', |
| 178 | nodes: [ |
| 179 | ['circle', { cx: 12, cy: 12, r: 10 }], |
| 180 | ['circle', { cx: 12, cy: 12, r: 6 }], |
| 181 | ['circle', { cx: 12, cy: 12, r: 2 }] |
| 182 | ] |
| 183 | }, |
| 184 | { |
| 185 | id: 'clock', |
| 186 | label: 'Clock', |
| 187 | nodes: [ |
| 188 | ['circle', { cx: 12, cy: 12, r: 10 }], |
| 189 | ['path', { d: 'M12 6v6l4 2' }] |
| 190 | ] |
| 191 | }, |
| 192 | { |
| 193 | id: 'calendar', |
| 194 | label: 'Calendar', |
| 195 | nodes: [ |
| 196 | ['path', { d: 'M8 2v4' }], |
| 197 | ['path', { d: 'M16 2v4' }], |
| 198 | ['rect', { x: 3, y: 4, width: 18, height: 18, rx: 2 }], |
| 199 | ['path', { d: 'M3 10h18' }] |
| 200 | ] |
| 201 | }, |
| 202 | { |
| 203 | id: 'mail', |
| 204 | label: 'Mail', |
| 205 | nodes: [ |
| 206 | ['rect', { x: 2, y: 4, width: 20, height: 16, rx: 2 }], |
| 207 | ['path', { d: 'm22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7' }] |
| 208 | ] |
| 209 | }, |
| 210 | { |
| 211 | id: 'phone', |
| 212 | label: 'Phone', |
| 213 | nodes: [ |
| 214 | ['path', { d: 'M13.832 16.568a1 1 0 0 0 1.213-.303l.355-.465A2 2 0 0 1 17 15h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2A18 18 0 0 1 2 4a2 2 0 0 1 2-2h3a2 2 0 0 1 2 2v3a2 2 0 0 1-.8 1.6l-.468.351a1 1 0 0 0-.292 1.233 14 14 0 0 0 6.392 6.384' }] |
| 215 | ] |
| 216 | }, |
| 217 | { |
| 218 | id: 'map-pin', |
| 219 | label: 'Map pin', |
| 220 | nodes: [ |
| 221 | ['path', { d: 'M20 10c0 6-8 12-8 12S4 16 4 10a8 8 0 0 1 16 0' }], |
| 222 | ['circle', { cx: 12, cy: 10, r: 3 }] |
| 223 | ] |
| 224 | }, |
| 225 | { |
| 226 | id: 'search', |
| 227 | label: 'Search', |
| 228 | nodes: [ |
| 229 | ['path', { d: 'm21 21-4.34-4.34' }], |
| 230 | ['circle', { cx: 11, cy: 11, r: 8 }] |
| 231 | ] |
| 232 | }, |
| 233 | { |
| 234 | id: 'link', |
| 235 | label: 'Link', |
| 236 | nodes: [ |
| 237 | ['path', { d: 'M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71' }], |
| 238 | ['path', { d: 'M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71' }] |
| 239 | ] |
| 240 | }, |
| 241 | { |
| 242 | id: 'download', |
| 243 | label: 'Download', |
| 244 | nodes: [ |
| 245 | ['path', { d: 'M12 15V3' }], |
| 246 | ['path', { d: 'M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4' }], |
| 247 | ['path', { d: 'm7 10 5 5 5-5' }] |
| 248 | ] |
| 249 | }, |
| 250 | { |
| 251 | id: 'upload', |
| 252 | label: 'Upload', |
| 253 | nodes: [ |
| 254 | ['path', { d: 'M12 3v12' }], |
| 255 | ['path', { d: 'm17 8-5-5-5 5' }], |
| 256 | ['path', { d: 'M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4' }] |
| 257 | ] |
| 258 | }, |
| 259 | { |
| 260 | id: 'chart-column', |
| 261 | label: 'Chart', |
| 262 | nodes: [ |
| 263 | ['path', { d: 'M3 3v16a2 2 0 0 0 2 2h16' }], |
| 264 | ['path', { d: 'M18 17V9' }], |
| 265 | ['path', { d: 'M13 17V5' }], |
| 266 | ['path', { d: 'M8 17v-3' }] |
| 267 | ] |
| 268 | }, |
| 269 | { |
| 270 | id: 'chart-pie', |
| 271 | label: 'Pie chart', |
| 272 | nodes: [ |
| 273 | ['path', { d: 'M21 12c.552 0 1.005-.449.95-.998a10 10 0 0 0-8.953-8.951C12.449 1.996 12 2.449 12 3v8a1 1 0 0 0 1 1z' }], |
| 274 | ['path', { d: 'M21.21 15.89A10 10 0 1 1 8 2.83' }] |
| 275 | ] |
| 276 | }, |
| 277 | { |
| 278 | id: 'trending-up', |
| 279 | label: 'Trending up', |
| 280 | nodes: [ |
| 281 | ['path', { d: 'M16 7h6v6' }], |
| 282 | ['path', { d: 'm22 7-8.5 8.5-5-5L2 17' }] |
| 283 | ] |
| 284 | }, |
| 285 | { |
| 286 | id: 'database', |
| 287 | label: 'Database', |
| 288 | nodes: [ |
| 289 | ['ellipse', { cx: 12, cy: 5, rx: 9, ry: 3 }], |
| 290 | ['path', { d: 'M3 5v14a9 3 0 0 0 18 0V5' }], |
| 291 | ['path', { d: 'M3 12a9 3 0 0 0 18 0' }] |
| 292 | ] |
| 293 | }, |
| 294 | { |
| 295 | id: 'image', |
| 296 | label: 'Image', |
| 297 | nodes: [ |
| 298 | ['rect', { width: 18, height: 18, x: 3, y: 3, rx: 2, ry: 2 }], |
| 299 | ['circle', { cx: 9, cy: 9, r: 2 }], |
| 300 | ['path', { d: 'm21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21' }] |
| 301 | ] |
| 302 | }, |
| 303 | { |
| 304 | id: 'video', |
| 305 | label: 'Video', |
| 306 | nodes: [ |
| 307 | ['path', { d: 'm16 13 5.223 3.482a.5.5 0 0 0 .777-.416V7.87a.5.5 0 0 0-.752-.432L16 10.5' }], |
| 308 | ['rect', { x: 2, y: 6, width: 14, height: 12, rx: 2 }] |
| 309 | ] |
| 310 | }, |
| 311 | { |
| 312 | id: 'file-text', |
| 313 | label: 'File', |
| 314 | nodes: [ |
| 315 | ['path', { d: 'M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z' }], |
| 316 | ['path', { d: 'M14 2v5a1 1 0 0 0 1 1h5' }], |
| 317 | ['path', { d: 'M10 9H8' }], |
| 318 | ['path', { d: 'M16 13H8' }], |
| 319 | ['path', { d: 'M16 17H8' }] |
| 320 | ] |
| 321 | }, |
| 322 | { |
| 323 | id: 'folder', |
| 324 | label: 'Folder', |
| 325 | nodes: [ |
| 326 | ['path', { d: 'M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2z' }] |
| 327 | ] |
| 328 | }, |
| 329 | { |
| 330 | id: 'book-open', |
| 331 | label: 'Book open', |
| 332 | nodes: [ |
| 333 | ['path', { d: 'M12 7v14' }], |
| 334 | ['path', { d: 'M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z' }] |
| 335 | ] |
| 336 | }, |
| 337 | { |
| 338 | id: 'users', |
| 339 | label: 'Users', |
| 340 | nodes: [ |
| 341 | ['path', { d: 'M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2' }], |
| 342 | ['path', { d: 'M16 3.128a4 4 0 0 1 0 7.744' }], |
| 343 | ['path', { d: 'M22 21v-2a4 4 0 0 0-3-3.87' }], |
| 344 | ['circle', { cx: 9, cy: 7, r: 4 }] |
| 345 | ] |
| 346 | }, |
| 347 | { |
| 348 | id: 'user-check', |
| 349 | label: 'User check', |
| 350 | nodes: [ |
| 351 | ['path', { d: 'M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2' }], |
| 352 | ['circle', { cx: 9, cy: 7, r: 4 }], |
| 353 | ['path', { d: 'm16 11 2 2 4-4' }] |
| 354 | ] |
| 355 | }, |
| 356 | { |
| 357 | id: 'shield-check', |
| 358 | label: 'Shield check', |
| 359 | nodes: [ |
| 360 | ['path', { d: 'M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.68-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z' }], |
| 361 | ['path', { d: 'm9 12 2 2 4-4' }] |
| 362 | ] |
| 363 | }, |
| 364 | { |
| 365 | id: 'lock', |
| 366 | label: 'Lock', |
| 367 | nodes: [ |
| 368 | ['rect', { x: 3, y: 11, width: 18, height: 11, rx: 2 }], |
| 369 | ['path', { d: 'M7 11V7a5 5 0 0 1 10 0v4' }] |
| 370 | ] |
| 371 | }, |
| 372 | { |
| 373 | id: 'globe', |
| 374 | label: 'Globe', |
| 375 | nodes: [ |
| 376 | ['circle', { cx: 12, cy: 12, r: 10 }], |
| 377 | ['path', { d: 'M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20' }], |
| 378 | ['path', { d: 'M2 12h20' }] |
| 379 | ] |
| 380 | }, |
| 381 | { |
| 382 | id: 'flag', |
| 383 | label: 'Flag', |
| 384 | nodes: [ |
| 385 | ['path', { d: 'M4 22V4a1 1 0 0 1 .4-.8A6 6 0 0 1 8 2c4 0 5 2 8 2 1.3 0 2.3-.3 3-.7a1 1 0 0 1 1 0V15a1 1 0 0 1-.4.8A6 6 0 0 1 16 17c-4 0-5-2-8-2a6 6 0 0 0-4 1.3' }] |
| 386 | ] |
| 387 | }, |
| 388 | { |
| 389 | id: 'trophy', |
| 390 | label: 'Trophy', |
| 391 | nodes: [ |
| 392 | ['path', { d: 'M10 14.66v1.626a2 2 0 0 1-.976 1.696A5 5 0 0 0 7 21h10a5 5 0 0 0-2.024-3.018A2 2 0 0 1 14 16.286V14.66' }], |
| 393 | ['path', { d: 'M18 9h1.5a1.5 1.5 0 0 0 0-3H18' }], |
| 394 | ['path', { d: 'M6 9H4.5a1.5 1.5 0 0 1 0-3H6' }], |
| 395 | ['path', { d: 'M6 2h12v7a6 6 0 0 1-12 0z' }] |
| 396 | ] |
| 397 | }, |
| 398 | { |
| 399 | id: 'rocket', |
| 400 | label: 'Rocket', |
| 401 | nodes: [ |
| 402 | ['path', { d: 'M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 0 0-2.91-.09z' }], |
| 403 | ['path', { d: 'm12 15-3-3a22 22 0 0 1 2-3.95A12.88 12.88 0 0 1 22 2c0 2.72-.78 7.5-6 11a22.35 22.35 0 0 1-4 2z' }], |
| 404 | ['path', { d: 'M9 12H4s.55-3.03 2-4c1.62-1.08 5 0 5 0' }], |
| 405 | ['path', { d: 'M12 15v5s3.03-.55 4-2c1.08-1.62 0-5 0-5' }] |
| 406 | ] |
| 407 | }, |
| 408 | { |
| 409 | id: 'zap', |
| 410 | label: 'Zap', |
| 411 | nodes: [['path', { d: 'M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46L12 9h8a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46L12 14z' }]] |
| 412 | }, |
| 413 | { |
| 414 | id: 'settings', |
| 415 | label: 'Settings', |
| 416 | nodes: [ |
| 417 | ['path', { d: 'M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915' }], |
| 418 | ['circle', { cx: 12, cy: 12, r: 3 }] |
| 419 | ] |
| 420 | } |
| 421 | ] |
| 422 | |
| 423 | /** Numbered solid badges 1-9, common for step / process slides. */ |
| 424 | const NUMBER_BADGES: IconDefinition[] = Array.from({ length: 9 }, (_, i) => ({ |
| 425 | id: `number-${i + 1}`, |
| 426 | label: `Number ${i + 1}`, |
| 427 | variant: 'badge' as const, |
| 428 | badgeNumber: i + 1 |
| 429 | })) |
| 430 | |
| 431 | export const ICON_LIST: IconDefinition[] = [...STROKE_ICONS, ...NUMBER_BADGES] |
| 432 | |
| 433 | const ICON_REGISTRY: Record<string, IconDefinition> = Object.fromEntries( |
| 434 | ICON_LIST.map((icon) => [icon.id, icon]) |
| 435 | ) |
| 436 | |
| 437 | export function getIconDefinition(iconId: string): IconDefinition | undefined { |
| 438 | return ICON_REGISTRY[iconId] |
| 439 | } |
| 440 | |
| 441 | export function isRegisteredIconId(iconId: string): boolean { |
| 442 | return Boolean(ICON_REGISTRY[iconId]) |
| 443 | } |
| 444 | |
| 445 | /** Outer <svg> attributes for the given icon variant. */ |
| 446 | export function iconOuterSvgAttrs(def: IconDefinition): string { |
| 447 | if (def.variant === 'badge') { |
| 448 | // Badge: outer svg is just a coordinate frame; the inner circle uses currentColor fill. |
| 449 | return 'fill="none"' |
| 450 | } |
| 451 | return 'fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"' |
| 452 | } |
| 453 | |
| 454 | /** Serialize an icon's inner SVG markup. Shared by the builder and the picker preview. */ |
| 455 | export function serializeIconInner(def: IconDefinition): string { |
| 456 | if (def.variant === 'badge') { |
| 457 | const n = def.badgeNumber |
| 458 | return `<circle cx="12" cy="12" r="10" fill="currentColor" /><text x="12" y="17" text-anchor="middle" font-size="14" font-weight="700" fill="#fff" stroke="none" font-family="inherit">${n}</text>` |
| 459 | } |
| 460 | return def.nodes |
| 461 | .map(([tag, attrs]) => { |
| 462 | const parts = Object.entries(attrs).map(([key, value]) => `${key}="${value}"`) |
| 463 | return `<${tag} ${parts.join(' ')} />` |
| 464 | }) |
| 465 | .join('') |
| 466 | } |
| 467 |