perf(web/icons): per-icon lucide imports via centralised alias

Route all lucide-react icon usage through a single src/icons.ts
re-export that imports each icon from its own per-icon module
(lucide-react/dist/esm/icons/<name>) instead of the barrel.

Bundle-size impact: none (29kB icons chunk unchanged — tree-shaking
was already effective with sideEffects:false). Dev-experience win:
Vite transforms 247 modules instead of 1848 because the dep
optimiser no longer pre-bundles the full lucide barrel — faster
cold start and HMR.

Ambient d.ts declares the wildcard module so TS accepts per-icon
imports; lucide ships .d.ts only for the barrel.

Seven icons were renamed upstream and still work through the barrel
via aliases (AlertTriangle -> triangle-alert, BarChart3 -> chart-column,
CheckCircle -> circle-check-big, Filter -> funnel, PlusCircle ->
circle-plus, Sliders -> sliders-vertical, UploadCloud -> cloud-upload,
Fingerprint -> fingerprint-pattern). Component call sites stay on
the legacy names; the renames live only in icons.ts.
This commit is contained in:
2026-04-24 18:41:33 -04:00
parent 52cbb01555
commit c973ded2fc
32 changed files with 150 additions and 30 deletions

View File

@@ -1,5 +1,5 @@
import React, { useEffect, useRef, useState } from 'react';
import { X, Download, AlertTriangle } from 'lucide-react';
import { X, Download, AlertTriangle } from '../icons';
import api from '../utils/api';
import { useEscapeKey } from '../hooks/useEscapeKey';
import { useFocusTrap } from '../hooks/useFocusTrap';

View File

@@ -1,6 +1,6 @@
import React, { useEffect, useState } from 'react';
import { useParams, useNavigate } from 'react-router-dom';
import { Activity, ArrowLeft, ChevronDown, ChevronLeft, ChevronRight, ChevronUp, Crosshair, Fingerprint, Shield, Clock, Wifi, Lock, FileKey, Radio, Timer, Paperclip, Terminal, Package, FileText, Mail, AtSign } from 'lucide-react';
import { Activity, ArrowLeft, ChevronDown, ChevronLeft, ChevronRight, ChevronUp, Crosshair, Fingerprint, Shield, Clock, Wifi, Lock, FileKey, Radio, Timer, Paperclip, Terminal, Package, FileText, Mail, AtSign } from '../icons';
import api from '../utils/api';
import ArtifactDrawer from './ArtifactDrawer';
import MailDrawer from './MailDrawer';

View File

@@ -1,6 +1,6 @@
import React, { useEffect, useRef, useState } from 'react';
import { useSearchParams, useNavigate } from 'react-router-dom';
import { Search, ChevronLeft, ChevronRight, Users } from 'lucide-react';
import { Search, ChevronLeft, ChevronRight, Users } from '../icons';
import api from '../utils/api';
import EmptyState from './EmptyState/EmptyState';
import { useFocusSearch } from '../hooks/useFocusSearch';

View File

@@ -3,7 +3,7 @@ import { useSearchParams, useNavigate } from 'react-router-dom';
import {
Archive, Search, ChevronLeft, ChevronRight, Filter, Key, Package, ChevronRight as ChevR,
Target,
} from 'lucide-react';
} from '../icons';
import api from '../utils/api';
import BountyInspector from './BountyInspector';
import EmptyState from './EmptyState/EmptyState';

View File

@@ -1,5 +1,5 @@
import React from 'react';
import { X, Key, Package, Copy, Send, Ban } from 'lucide-react';
import { X, Key, Package, Copy, Send, Ban } from '../icons';
import { useToast } from './Toasts/useToast';
interface BountyEntry {

View File

@@ -3,7 +3,7 @@ import {
LayoutDashboard, Server, Network, Terminal, Archive, Crosshair,
PlusCircle, Pause, RefreshCw, Download, HardDrive, Package, Settings,
SearchX, Keyboard, Webhook,
} from 'lucide-react';
} from '../../icons';
import EmptyState from '../EmptyState/EmptyState';
import './CommandPalette.css';

View File

@@ -1,6 +1,6 @@
import React, { useEffect, useState } from 'react';
import api from '../utils/api';
import { Settings, Users, Sliders, Trash2, UserPlus, Key, Save, Shield, AlertTriangle, Palette, Activity, Square, RefreshCw, Play } from 'lucide-react';
import { Settings, Users, Sliders, Trash2, UserPlus, Key, Save, Shield, AlertTriangle, Palette, Activity, Square, RefreshCw, Play } from '../icons';
import { useToast } from './Toasts/useToast';
import './Dashboard.css';
import './Config.css';

View File

@@ -1,7 +1,7 @@
import React, { useEffect, useMemo, useRef, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import './Dashboard.css';
import { Shield, Users, Activity, Clock, Paperclip, Crosshair, Flame, Archive, ShieldOff, Server } from 'lucide-react';
import { Shield, Users, Activity, Clock, Paperclip, Crosshair, Flame, Archive, ShieldOff, Server } from '../icons';
import { parseEventBody } from '../utils/parseEventBody';
import ArtifactDrawer from './ArtifactDrawer';
import EmptyState from './EmptyState/EmptyState';

View File

@@ -2,7 +2,7 @@ import React, { useEffect, useMemo, useRef, useState } from 'react';
import {
Cpu, Database, Globe, Monitor, Network, PlusCircle, PowerOff,
RefreshCw, Server, Shield, Terminal,
} from 'lucide-react';
} from '../icons';
import api from '../utils/api';
import { ARCHETYPES as FALLBACK_ARCHETYPES, DEFAULT_SERVICES } from './MazeNET/data';
import { useToast } from './Toasts/useToast';

View File

@@ -1,5 +1,5 @@
import React from 'react';
import type { LucideIcon } from 'lucide-react';
import type { LucideIcon } from '../../icons';
import './EmptyState.css';
interface CTA {

View File

@@ -4,7 +4,7 @@ import {
Menu, X, Search, Activity, LayoutDashboard, Terminal, Settings, LogOut,
Server, Archive, Package, Network, ChevronDown, ChevronRight, HardDrive,
ShieldAlert, Bell, Webhook,
} from 'lucide-react';
} from '../icons';
import { prefetchRoute } from '../routePrefetch';
import './Layout.css';

View File

@@ -4,7 +4,7 @@ import { useSearchParams } from 'react-router-dom';
import {
Terminal, Search, BarChart3, ChevronLeft, ChevronRight,
Play, Pause, Paperclip, Download, Radio, X as XIcon,
} from 'lucide-react';
} from '../icons';
import api from '../utils/api';
import { parseEventBody } from '../utils/parseEventBody';
import ArtifactDrawer from './ArtifactDrawer';

View File

@@ -1,7 +1,7 @@
import React, { useState } from 'react';
import api from '../utils/api';
import './Login.css';
import { Activity } from 'lucide-react';
import { Activity } from '../icons';
interface LoginProps {
onLogin: (token: string) => void;

View File

@@ -1,5 +1,5 @@
import React, { useEffect, useRef, useState } from 'react';
import { X, Download, AlertTriangle, Paperclip } from 'lucide-react';
import { X, Download, AlertTriangle, Paperclip } from '../icons';
import api from '../utils/api';
import { useEscapeKey } from '../hooks/useEscapeKey';
import { useFocusTrap } from '../hooks/useFocusTrap';

View File

@@ -1,5 +1,5 @@
import React, { forwardRef, useMemo } from 'react';
import { RotateCcw, LayoutGrid, ZoomIn, ZoomOut } from 'lucide-react';
import { RotateCcw, LayoutGrid, ZoomIn, ZoomOut } from '../../icons';
import NetBox from './NetBox';
import NodeCard from './NodeCard';
import type { Net, MazeNode, Edge } from './types';

View File

@@ -1,5 +1,5 @@
import React, { useEffect, useRef, useState } from 'react';
import { ChevronRight } from 'lucide-react';
import { ChevronRight } from '../../icons';
export interface MenuItem {
label: string;

View File

@@ -2,7 +2,7 @@ import React, { useMemo } from 'react';
import {
ArrowLeft, ArrowRight, Crosshair, Globe, GitMerge, MousePointer2, Plus,
Server, Trash2, X, Shield,
} from 'lucide-react';
} from '../../icons';
import type { Net, MazeNode, Edge } from './types';
import { DEFAULT_SERVICES } from './data';

View File

@@ -4,7 +4,7 @@ import {
PanelRightOpen, PanelRightClose, PanelLeftOpen, PanelLeftClose,
Maximize2, Minimize2, RotateCcw, UploadCloud, ArrowLeft,
Plus, Trash2, Zap, Copy, Eye, ShieldAlert, GitMerge, Server,
} from 'lucide-react';
} from '../../icons';
import './MazeNET.css';
import axios from '../../utils/api';
import Palette from './Palette';

View File

@@ -1,5 +1,5 @@
import React from 'react';
import { Globe, GitMerge, ShieldAlert } from 'lucide-react';
import { Globe, GitMerge, ShieldAlert } from '../../icons';
import type { Net } from './types';
import type { ResizeHandle } from './useMazeInteraction';

View File

@@ -2,7 +2,7 @@ import React from 'react';
import {
Server, Monitor, Shield, Database, Cpu, Globe, Users, HardDrive, Eye,
type LucideIcon,
} from 'lucide-react';
} from '../../icons';
import type { MazeNode } from './types';
import { DEFAULT_SERVICES } from './data';

View File

@@ -1,7 +1,7 @@
import React from 'react';
import { GitMerge, ShieldAlert, Server, Monitor, Shield, Database, Cpu, Globe,
Terminal, Lock, Folder, HardDrive, Users, KeyRound,
Radio, Zap, Wifi, Circle, Mail, Phone, Activity, Box } from 'lucide-react';
Radio, Zap, Wifi, Circle, Mail, Phone, Activity, Box } from '../../icons';
import type { ServiceDef, Archetype, ServiceGroup } from './data';
import { SERVICE_GROUP_ORDER } from './data';
import type { PaletteDrag } from './useMazeInteraction';

View File

@@ -1,5 +1,5 @@
import React, { useEffect, useRef } from 'react';
import { X, type LucideIcon } from 'lucide-react';
import { X, type LucideIcon } from '../../icons';
import { useEscapeKey } from '../../hooks/useEscapeKey';
import { useFocusTrap } from '../../hooks/useFocusTrap';
import './Modal.css';

View File

@@ -5,7 +5,7 @@ import './Dashboard.css';
import {
Upload, RefreshCw, RotateCcw, Package, AlertTriangle, CheckCircle,
Wifi, WifiOff, Server,
} from 'lucide-react';
} from '../icons';
interface HostRelease {
host_uuid: string;

View File

@@ -1,5 +1,5 @@
import React, { useEffect, useRef, useState } from 'react';
import { X, AlertTriangle } from 'lucide-react';
import { X, AlertTriangle } from '../icons';
import api from '../utils/api';
import { useEscapeKey } from '../hooks/useEscapeKey';
import { useFocusTrap } from '../hooks/useFocusTrap';

View File

@@ -1,5 +1,5 @@
import React from 'react';
import { Keyboard } from 'lucide-react';
import { Keyboard } from '../../icons';
import Modal from '../Modal/Modal';
import './ShortcutsHelp.css';

View File

@@ -8,7 +8,7 @@ import './DeckyFleet.css';
import {
AlertTriangle, Check, Copy, HardDrive, PowerOff, RefreshCw, RotateCcw,
Server, Trash2, UserPlus, Wifi, WifiOff,
} from 'lucide-react';
} from '../icons';
interface SwarmHost {
uuid: string;

View File

@@ -2,7 +2,7 @@ import React from 'react';
import {
CheckCircle, RefreshCw, Download, Upload, Pause, Play, AlertTriangle,
Info, Terminal, Activity, ShieldAlert,
} from 'lucide-react';
} from '../../icons';
import type { Toast } from './toast-context';
import './Toasts.css';

View File

@@ -1,5 +1,5 @@
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { X, Server, Cpu, FileText, Sparkles, Check } from 'lucide-react';
import { X, Server, Cpu, FileText, Sparkles, Check } from '../../icons';
import api from '../../utils/api';
import { useEscapeKey } from '../../hooks/useEscapeKey';
import { useFocusTrap } from '../../hooks/useFocusTrap';

View File

@@ -1,6 +1,6 @@
import React, { useCallback, useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { Network, Plus, Power, Trash2, UploadCloud, RefreshCw, Skull } from 'lucide-react';
import { Network, Plus, Power, Trash2, UploadCloud, RefreshCw, Skull } from '../../icons';
import api from '../../utils/api';
import { clearLayout } from '../MazeNET/useMazeLayoutStore';
import CreateTopologyWizard from './CreateTopologyWizard';

View File

@@ -2,7 +2,7 @@ import React, { useEffect, useMemo, useState } from 'react';
import {
Plus, Trash2, Pencil, Zap, AlertTriangle, Copy, X, Save,
Check, Webhook as WebhookIcon,
} from 'lucide-react';
} from '../icons';
import api from '../utils/api';
import { useToast } from './Toasts/useToast';
import './Dashboard.css';