LCOV - code coverage report
Current view: top level - dashql-app/src/ui/foundations - symbol_icon.tsx Coverage Total Hit
Test: DashQL 915828b Lines: 100.0 % 131 131
Test Date: 2026-11-06 19:30:32

            Line data    Source code
       1              : import * as React from 'react';
       2              : import icons from '@ankoh/dashql-svg-symbols';
       3              : 
       4              : export type IconSize = number | 'small' | 'medium' | 'large';
       5              : 
       6              : export interface IconProps extends Omit<React.SVGProps<SVGSVGElement>, 'size' | 'title'> {
       7              :     size?: IconSize;
       8              :     title?: string;
       9              :     verticalAlign?: React.CSSProperties['verticalAlign'];
      10              : }
      11              : 
      12              : export type Icon = React.FC<IconProps>;
      13              : 
      14              : type SymbolVariants = Readonly<Record<number, string>>;
      15              : 
      16            1 : const ICON_SIZE: Record<Exclude<IconSize, number>, number> = {
      17            1 :     small: 16,
      18            1 :     medium: 32,
      19            1 :     large: 64,
      20            1 : };
      21              : 
      22            1 : function resolveSize(size: IconSize | undefined): number {
      23            1 :     if (typeof size === 'number') {
      24            1 :         return size;
      25              :     }
      26            1 :     return size == null ? 16 : ICON_SIZE[size];
      27            1 : }
      28              : 
      29            1 : function resolveSymbol(variants: SymbolVariants, size: number): string {
      30            1 :     const naturalSizes = Object.keys(variants).map(Number).sort((a, b) => a - b);
      31            1 :     let naturalSize = naturalSizes[0];
      32            1 :     for (const candidate of naturalSizes) {
      33            1 :         if (candidate > size) {
      34            1 :             break;
      35              :         }
      36            1 :         naturalSize = candidate;
      37            1 :     }
      38            1 :     return variants[naturalSize];
      39            1 : }
      40              : 
      41            1 : function createIcon(variants: SymbolVariants): Icon {
      42            1 :     return React.forwardRef<SVGSVGElement, IconProps>((props, ref) => {
      43            1 :         const {
      44            1 :             'aria-label': ariaLabel,
      45            1 :             'aria-labelledby': ariaLabelledBy,
      46            1 :             className,
      47            1 :             fill = 'currentColor',
      48            1 :             size,
      49            1 :             style,
      50            1 :             tabIndex,
      51            1 :             title,
      52            1 :             verticalAlign = 'text-bottom',
      53            1 :             ...svgProps
      54            1 :         } = props;
      55            1 :         const pixels = resolveSize(size);
      56            1 :         const labelled = Boolean(ariaLabel || ariaLabelledBy);
      57            1 :         const symbol = resolveSymbol(variants, pixels);
      58              : 
      59            1 :         return (
      60            1 :             <svg
      61            1 :                 ref={ref}
      62            1 :                 {...svgProps}
      63            1 :                 aria-hidden={labelled ? undefined : 'true'}
      64            1 :                 aria-label={ariaLabel}
      65            1 :                 aria-labelledby={ariaLabelledBy}
      66            1 :                 className={className}
      67            1 :                 color={fill}
      68            1 :                 display="inline-block"
      69            1 :                 fill="currentColor"
      70            1 :                 focusable={tabIndex != null && tabIndex >= 0 ? 'true' : 'false'}
      71            1 :                 height={pixels}
      72            1 :                 overflow="visible"
      73            1 :                 role={labelled ? 'img' : undefined}
      74            1 :                 style={{ verticalAlign, ...style }}
      75            1 :                 tabIndex={tabIndex}
      76            1 :                 width={pixels}
      77              :             >
      78            1 :                 {title != null && <title>{title}</title>}
      79            1 :                 <use xlinkHref={`${icons}#${symbol}`} />
      80            1 :             </svg>
      81              :         );
      82            1 :     });
      83            1 : }
      84              : 
      85            1 : const SYMBOL_ICONS = new Map<string, Icon>();
      86              : 
      87            1 : export function SymbolIcon(symbol: string): Icon {
      88            1 :     const cached = SYMBOL_ICONS.get(symbol);
      89            1 :     if (cached != null) {
      90            1 :         return cached;
      91              :     }
      92            1 :     const icon = createIcon({ 16: symbol });
      93            1 :     SYMBOL_ICONS.set(symbol, icon);
      94            1 :     return icon;
      95            1 : }
      96              : 
      97            1 : export const AlertIcon = createIcon({ 16: 'alert_16' });
      98            1 : export const BracesIcon = createIcon({ 16: 'braces_16' });
      99            1 : export const BookIcon = createIcon({ 16: 'book_16', 24: 'book_24' });
     100            1 : export const BroomIcon = createIcon({ 16: 'broom_16', 24: 'broom_24' });
     101            1 : export const CheckIcon = createIcon({ 16: 'check_16', 24: 'check_24' });
     102            1 : export const ChecklistIcon = createIcon({ 16: 'checklist_16' });
     103            1 : export const ChevronDownIcon = createIcon({ 12: 'chevron_down_12', 16: 'chevron_down_16', 24: 'chevron_down_24' });
     104            1 : export const ChevronLeftIcon = createIcon({ 12: 'chevron_left_12', 16: 'chevron_left_16', 24: 'chevron_left_24' });
     105            1 : export const ChevronRightIcon = createIcon({ 12: 'chevron_right_12', 16: 'chevron_right_16', 24: 'chevron_right_24' });
     106            1 : export const ChevronUpIcon = createIcon({ 12: 'chevron_up_12', 16: 'chevron_up_16', 24: 'chevron_up_24' });
     107            1 : export const CircleSlashIcon = createIcon({ 16: 'circle_slash_16', 24: 'circle_slash' });
     108            1 : export const CodeIcon = createIcon({ 16: 'code_16' });
     109            1 : export const ComposeIcon = createIcon({ 16: 'compose_16', 24: 'compose_24' });
     110            1 : export const CopyIcon = createIcon({ 16: 'copy_16' });
     111            1 : export const CpuIcon = createIcon({ 16: 'cpu_16', 24: 'cpu_24' });
     112            1 : export const DashIcon = createIcon({ 16: 'dash_16' });
     113            1 : export const DashboardIcon = createIcon({ 16: 'dashboard_16', 24: 'dashboard_24' });
     114            1 : export const DatabaseIcon = createIcon({ 16: 'database_16', 24: 'database' });
     115            1 : export const DownloadIcon = createIcon({ 16: 'download_16', 24: 'download' });
     116            1 : export const EyeIcon = createIcon({ 16: 'eye_16', 24: 'eye_24' });
     117            1 : export const EyeClosedIcon = createIcon({ 16: 'eye_closed_16', 24: 'eye_closed_24' });
     118            1 : export const FileBadgeIcon = createIcon({ 16: 'file_badge_16' });
     119            1 : export const FileDirectoryFillIcon = createIcon({ 16: 'file_directory_fill_16', 24: 'folder_fill' });
     120            1 : export const FileDirectoryIcon = createIcon({ 16: 'file_directory_16', 24: 'folder' });
     121            1 : export const FileDirectoryOpenFillIcon = createIcon({ 16: 'file_directory_open_fill_16' });
     122            1 : export const FileDirectoryPlusIcon = createIcon({ 16: 'file_directory_plus_16', 24: 'file_directory_plus_24' });
     123            1 : export const FileIcon = createIcon({ 16: 'file_16', 24: 'file' });
     124            1 : export const GraphIcon = createIcon({ 16: 'graph_16', 24: 'graph_24' });
     125            1 : export const HeartIcon = createIcon({ 16: 'heart_16' });
     126            1 : export const HistoryIcon = createIcon({ 16: 'history_16' });
     127            1 : export const KeyIcon = createIcon({ 16: 'key_16' });
     128            1 : export const LibraryIcon = createIcon({ 16: 'library_16', 24: 'library_24' });
     129            1 : export const LinkIcon = createIcon({ 16: 'link_16' });
     130            1 : export const ListUnorderedIcon = createIcon({ 16: 'list_unordered_16' });
     131            1 : export const LockIcon = createIcon({ 16: 'lock_16' });
     132            1 : export const PaperAirplaneIcon = createIcon({ 16: 'paper_airplane_16' });
     133            1 : export const PaperclipIcon = createIcon({ 16: 'paperclip_16' });
     134            1 : export const PencilIcon = createIcon({ 16: 'pencil_16', 24: 'pencil_24' });
     135            1 : export const PersonIcon = createIcon({ 16: 'person_16', 24: 'person_24' });
     136            1 : export const PlugIcon = createIcon({ 16: 'plug_16', 24: 'plug_24' });
     137            1 : export const PlusIcon = createIcon({ 16: 'plus_16', 24: 'plus_24' });
     138            1 : export const ProjectIcon = createIcon({ 16: 'project_16' });
     139            1 : export const RowsIcon = createIcon({ 16: 'rows_16', 24: 'rows' });
     140            1 : export const SaveIcon = createIcon({ 16: 'save_16' });
     141            1 : export const SearchIcon = createIcon({ 16: 'search_16' });
     142            1 : export const ScreenFullIcon = createIcon({ 16: 'screen_full_16', 24: 'screen_full_24' });
     143            1 : export const ScreenNormalIcon = createIcon({ 16: 'screen_normal_16', 24: 'screen_normal_24' });
     144            1 : export const StackIcon = createIcon({ 16: 'stack_16', 24: 'stack_24' });
     145            1 : export const StackPlusIcon = createIcon({ 16: 'stack_plus_16', 24: 'stack_plus_24' });
     146            1 : export const SquareFillIcon = createIcon({ 16: 'square_fill_16' });
     147            1 : export const SyncIcon = createIcon({ 16: 'sync_16' });
     148            1 : export const TableIcon = createIcon({ 16: 'table_16' });
     149            1 : export const ThreeBarsIcon = createIcon({ 16: 'three_bars_16' });
     150            1 : export const ToolsIcon = createIcon({ 16: 'tools_16', 24: 'tools_24' });
     151            1 : export const TrashIcon = createIcon({ 16: 'trash_16', 24: 'trash_24' });
     152            1 : export const TriangleDownIcon = createIcon({ 16: 'triangle_down_16', 24: 'triangle_down_24' });
     153            1 : export const UnlinkIcon = createIcon({ 16: 'unlink_16' });
     154            1 : export const UploadIcon = createIcon({ 16: 'upload_16', 24: 'upload_24' });
     155            1 : export const XCircleFillIcon = createIcon({ 16: 'x_circle_16' });
     156            1 : export const XIcon = createIcon({ 12: 'x_12', 16: 'x_16', 24: 'x_24' });
     157            1 : export const ZoomInIcon = createIcon({ 16: 'zoom_in_16' });
     158            1 : export const ZoomOutIcon = createIcon({ 16: 'zoom_out_16' });
        

Generated by: LCOV version 2.0-1