@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 }}">