@props(['name' => 'squares-2x2'])
@php
/**
* The single icon chokepoint for the whole app: every ``
* renders a Font Awesome 6 glyph.
*
* The `name` vocabulary is deliberately unchanged from the Heroicon set this
* component used to draw, so the ~1,000 existing call sites (and the icon
* names held in PHP nav/KPI config arrays) keep working untouched. One
* semantic name → one Font Awesome class, chosen once, here.
*
* Regular (outline) is the house weight. Font Awesome 6 *Free* only ships a
* regular cut for the ~160 glyphs listed in $regular below, so the map still
* names every glyph "fa-solid …" and the weight is decided in one place at
* the bottom of this block: anything with a regular cut is switched to it,
* everything else stays solid. Brands are used only where the mark has to be
* recognisable.
* A call site may also pass a raw Font Awesome class ("fa-solid fa-anchor")
* as the name for a one-off glyph that does not deserve a semantic alias;
* it goes through the same weight switch.
*/
$map = [
// Navigation / structure
'squares-2x2' => 'fa-solid fa-table-cells-large',
'rectangle-group' => 'fa-solid fa-layer-group',
// Splitting one product into the several pieces of work it really is.
'scissors' => 'fa-solid fa-scissors',
'home' => 'fa-solid fa-house',
'bars-3' => 'fa-solid fa-bars',
'ellipsis-horizontal' => 'fa-solid fa-ellipsis',
'queue-list' => 'fa-solid fa-list-ul',
'table-cells' => 'fa-solid fa-table',
'folder' => 'fa-solid fa-folder',
'inbox' => 'fa-solid fa-inbox',
'inbox-arrow-down' => 'fa-solid fa-inbox',
'archive-box' => 'fa-solid fa-box-archive',
'archive-box-x-mark' => 'fa-solid fa-box-open',
'puzzle-piece' => 'fa-solid fa-puzzle-piece',
'adjustments-horizontal' => 'fa-solid fa-sliders',
'swatch' => 'fa-solid fa-palette',
// People / org
'users' => 'fa-solid fa-users',
'user' => 'fa-solid fa-user',
'user-circle' => 'fa-solid fa-circle-user',
'user-plus' => 'fa-solid fa-user-plus',
'user-group' => 'fa-solid fa-user-group',
'identification' => 'fa-solid fa-id-card',
'building-office' => 'fa-solid fa-building',
'building-storefront' => 'fa-solid fa-shop',
'briefcase' => 'fa-solid fa-briefcase',
'academic-cap' => 'fa-solid fa-graduation-cap',
// Money / documents
'banknotes' => 'fa-solid fa-money-bill-1',
'currency-dollar' => 'fa-solid fa-dollar-sign',
'credit-card' => 'fa-solid fa-credit-card',
'wallet' => 'fa-solid fa-wallet',
'receipt-percent' => 'fa-solid fa-receipt',
'document' => 'fa-solid fa-file',
'document-text' => 'fa-solid fa-file-lines',
'document-currency-dollar' => 'fa-solid fa-file-invoice-dollar',
'document-duplicate' => 'fa-solid fa-copy',
'clipboard-document-list' => 'fa-solid fa-clipboard-list',
'clipboard-document-check' => 'fa-solid fa-clipboard-check',
'calculator' => 'fa-solid fa-calculator',
'scale' => 'fa-solid fa-scale-balanced',
'gift' => 'fa-solid fa-gift',
'tag' => 'fa-solid fa-tag',
// Operations
'cube' => 'fa-solid fa-cube',
'cubes' => 'fa-solid fa-cubes',
'truck' => 'fa-solid fa-truck',
'printer' => 'fa-solid fa-print',
'wrench-screwdriver' => 'fa-solid fa-screwdriver-wrench',
'shield-check' => 'fa-solid fa-shield-halved',
'flag' => 'fa-solid fa-flag',
'megaphone' => 'fa-solid fa-bullhorn',
'map-pin' => 'fa-solid fa-location-dot',
'qr-code' => 'fa-solid fa-qrcode',
'photo' => 'fa-solid fa-image',
'camera' => 'fa-solid fa-camera',
'paper-clip' => 'fa-solid fa-paperclip',
'link' => 'fa-solid fa-link',
'lock-closed' => 'fa-solid fa-lock',
'lock-open' => 'fa-solid fa-lock-open',
'key' => 'fa-solid fa-key',
'bolt' => 'fa-solid fa-bolt',
'fire' => 'fa-solid fa-fire',
'light-bulb' => 'fa-solid fa-lightbulb',
'trophy' => 'fa-solid fa-trophy',
'sparkles' => 'fa-solid fa-wand-magic-sparkles',
'sticky-note' => 'fa-solid fa-note-sticky',
'book-open' => 'fa-solid fa-book-open',
'beaker' => 'fa-solid fa-flask',
'cloud-arrow-up' => 'fa-solid fa-cloud-arrow-up',
'server-stack' => 'fa-solid fa-database',
'cog-6-tooth' => 'fa-solid fa-gear',
// Reporting
'chart-bar' => 'fa-solid fa-chart-bar',
'chart-pie' => 'fa-solid fa-chart-pie',
'presentation-chart-line' => 'fa-solid fa-chart-line',
'arrow-trending-up' => 'fa-solid fa-arrow-trend-up',
'arrow-trending-down' => 'fa-solid fa-arrow-trend-down',
'scale-balance' => 'fa-solid fa-arrow-up-wide-short',
'funnel' => 'fa-solid fa-filter',
'magnifying-glass' => 'fa-solid fa-magnifying-glass',
'eye' => 'fa-solid fa-eye',
'eye-slash' => 'fa-solid fa-eye-slash',
// Time
'clock' => 'fa-solid fa-clock',
'calendar' => 'fa-solid fa-calendar',
'calendar-days' => 'fa-solid fa-calendar-days',
'play' => 'fa-solid fa-play',
'pause-circle' => 'fa-solid fa-circle-pause',
'stop' => 'fa-solid fa-stop',
// Comms
'bell' => 'fa-solid fa-bell',
'bell-alert' => 'fa-solid fa-bell',
'envelope' => 'fa-solid fa-envelope',
'envelope-open' => 'fa-solid fa-envelope-open',
'phone' => 'fa-solid fa-phone',
'paper-airplane' => 'fa-solid fa-paper-plane',
'chat-bubble-left-right' => 'fa-solid fa-comments',
'chat-bubble-left-ellipsis' => 'fa-solid fa-comment-dots',
'whatsapp' => 'fa-brands fa-whatsapp',
// State
'check' => 'fa-solid fa-check',
'check-circle' => 'fa-solid fa-circle-check',
'x-mark' => 'fa-solid fa-xmark',
'x-circle' => 'fa-solid fa-circle-xmark',
'plus' => 'fa-solid fa-plus',
'plus-circle' => 'fa-solid fa-circle-plus',
'minus' => 'fa-solid fa-minus',
'minus-circle' => 'fa-solid fa-circle-minus',
'trash' => 'fa-solid fa-trash-can',
'pencil-square' => 'fa-solid fa-pen-to-square',
'pencil' => 'fa-solid fa-pencil',
'exclamation-triangle' => 'fa-solid fa-triangle-exclamation',
'exclamation-circle' => 'fa-solid fa-circle-exclamation',
'information-circle' => 'fa-solid fa-circle-info',
'question-mark-circle' => 'fa-solid fa-circle-question',
'no-symbol' => 'fa-solid fa-ban',
'star' => 'fa-solid fa-star',
'heart' => 'fa-solid fa-heart',
'spinner' => 'fa-solid fa-circle-notch fa-spin',
// Arrows
'arrow-right' => 'fa-solid fa-arrow-right',
'arrow-left' => 'fa-solid fa-arrow-left',
'arrow-up' => 'fa-solid fa-arrow-up',
'arrow-down' => 'fa-solid fa-arrow-down',
'arrow-up-right' => 'fa-solid fa-arrow-up-right-from-square',
'arrow-down-tray' => 'fa-solid fa-download',
'arrow-up-tray' => 'fa-solid fa-upload',
'arrow-path' => 'fa-solid fa-arrows-rotate',
'arrow-uturn-left' => 'fa-solid fa-arrow-rotate-left',
'arrows-right-left' => 'fa-solid fa-right-left',
'arrows-pointing-out' => 'fa-solid fa-up-right-and-down-left-from-center',
'arrows-pointing-in' => 'fa-solid fa-down-left-and-up-right-to-center',
'arrow-right-start-on-rectangle' => 'fa-solid fa-right-from-bracket',
'chevron-up' => 'fa-solid fa-chevron-up',
'chevron-down' => 'fa-solid fa-chevron-down',
'chevron-left' => 'fa-solid fa-chevron-left',
'chevron-right' => 'fa-solid fa-chevron-right',
'chevron-up-down' => 'fa-solid fa-sort',
// Devices / media
'device-phone-mobile' => 'fa-solid fa-mobile-screen-button',
'computer-desktop' => 'fa-solid fa-desktop',
'video-camera' => 'fa-solid fa-video',
'microphone' => 'fa-solid fa-microphone',
'speaker-wave' => 'fa-solid fa-volume-high',
// Text / editor
'align-left' => 'fa-solid fa-align-left',
'align-center' => 'fa-solid fa-align-center',
'align-right' => 'fa-solid fa-align-right',
'list-bullet' => 'fa-solid fa-list-ul',
'numbered-list' => 'fa-solid fa-list-ol',
'bold' => 'fa-solid fa-bold',
'italic' => 'fa-solid fa-italic',
'underline' => 'fa-solid fa-underline',
];
$glyph = str_starts_with($name, 'fa-')
? $name
: ($map[$name] ?? $map['squares-2x2']);
/**
* Every glyph Font Awesome 6 Free cuts in regular (weight 400) — i.e. the
* contents of node_modules/@fortawesome/fontawesome-free/svgs/regular. Asking
* for `fa-regular` on anything outside this list renders a blank box, so the
* switch below is a whitelist, not a blanket rename.
*/
$regular = [
'address-book', 'address-card', 'bell', 'bell-slash', 'bookmark', 'building',
'calendar', 'calendar-check', 'calendar-days', 'calendar-minus', 'calendar-plus',
'calendar-xmark', 'chart-bar', 'chess-bishop', 'chess-king', 'chess-knight',
'chess-pawn', 'chess-queen', 'chess-rook', 'circle', 'circle-check', 'circle-dot',
'circle-down', 'circle-left', 'circle-pause', 'circle-play', 'circle-question',
'circle-right', 'circle-stop', 'circle-up', 'circle-user', 'circle-xmark',
'clipboard', 'clock', 'clone', 'closed-captioning', 'comment', 'comment-dots',
'comments', 'compass', 'copy', 'copyright', 'credit-card', 'envelope',
'envelope-open', 'eye', 'eye-slash', 'file', 'file-audio', 'file-code',
'file-excel', 'file-image', 'file-lines', 'file-pdf', 'file-powerpoint',
'file-video', 'file-word', 'file-zipper', 'flag', 'floppy-disk', 'folder',
'folder-closed', 'folder-open', 'font-awesome', 'futbol', 'gem', 'hand',
'hand-back-fist', 'hand-lizard', 'hand-peace', 'hand-point-down', 'hand-point-left',
'hand-point-right', 'hand-point-up', 'hand-pointer', 'hand-scissors', 'hand-spock',
'handshake', 'hard-drive', 'heart', 'hospital', 'hourglass', 'hourglass-half',
'id-badge', 'id-card', 'image', 'images', 'keyboard', 'lemon', 'life-ring',
'lightbulb', 'map', 'message', 'money-bill-1', 'moon', 'newspaper', 'note-sticky',
'object-group', 'object-ungroup', 'paper-plane', 'paste', 'pen-to-square',
'rectangle-list', 'rectangle-xmark', 'registered', 'share-from-square',
'snowflake', 'square', 'square-caret-down', 'square-caret-left',
'square-caret-right', 'square-caret-up', 'square-check', 'square-full',
'square-minus', 'square-plus', 'star', 'star-half', 'star-half-stroke', 'sun',
'thumbs-down', 'thumbs-up', 'trash-can', 'user', 'window-maximize',
'window-minimize', 'window-restore',
];
if (str_contains($glyph, 'fa-solid ')
&& preg_match('/(?:^|\s)fa-([a-z0-9-]+)/', str_replace('fa-solid', '', $glyph), $g)
&& in_array($g[1], $regular, true)) {
$glyph = str_replace('fa-solid', 'fa-regular', $glyph);
}
/**
* Call sites size icons with Tailwind box utilities (h-4 w-4, h-[18px], …)
* because that is what the SVG needed. A glyph is sized by font-size, not by
* its box, so read the box back off the class list and set a font-size that
* fills it. The 0.9 factor is optical: a Font Awesome glyph carries more ink
* than the 1.5px outline stroke it replaced, so it sits marginally smaller.
* It is applied to both weights so a regular glyph and a solid one sitting
* side by side still measure the same.
*/
$classes = (string) $attributes->get('class');
$box = 24.0;
if (preg_match('/(?:^|\s)(?:h|size)-\[(\d+(?:\.\d+)?)px\]/', $classes, $m)) {
$box = (float) $m[1];
} elseif (preg_match('/(?:^|\s)(?:h|size)-(\d+(?:\.5)?)(?:\s|$)/', $classes, $m)) {
$box = (float) $m[1] * 4;
}
$fontSize = round($box * 0.9, 2);
$callerStyle = (string) $attributes->get('style');
$style = 'font-size:' . $fontSize . 'px' . ($callerStyle !== '' ? ';' . $callerStyle : '');
$sizing = preg_match('/(?:^|\s)(?:h|size)-/', $classes) ? '' : ' h-6 w-6';
@endphp
except(['style', 'stroke-width', 'stroke', 'fill'])->merge([
'class' => $glyph . ' bp-icon' . $sizing,
'aria-hidden' => 'true',
]) }} style="{{ $style }}">