Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | 1x 897x 5x 1x 3012x 3012x 3012x 3012x 3000x 3012x 3063x 3063x | /**
* Copyright (c) Siemens 2016 - 2025
* SPDX-License-Identifier: MIT
*/
import { NgClass } from '@angular/common';
import {
ChangeDetectionStrategy,
Component,
computed,
inject,
InjectionToken,
input,
Provider
} from '@angular/core';
import { IconService } from './si-icons';
/**
* Global configuration for icons.
*
* @experimental
*/
export interface IconConfig {
/**
* If true, the si-icon component will always render the icon font instead of the svg.
*
* @defaultValue true
*/
disableSvgIcons?: boolean;
}
const ICON_CONFIG = new InjectionToken<IconConfig>('ICON_CONFIG', {
providedIn: 'root',
factory: () => ({ disableSvgIcons: true })
});
/**
* Configure how Element handles icons. Provide only once in your global configuration.
*
* @experimental
*/
export const provideIconConfig = (config: IconConfig): Provider => ({
provide: ICON_CONFIG,
useValue: config
});
/**
* Component to render a font or SVG icon depending on the configuration.
* If no SVG icon is found, the component will fall back to render the icon-font.
* In that case, an application must ensure that the icon font is loaded.
* This component will only attach the respective class.
*
* The content of this component is hidden in the a11y tree.
* If needed, the consumer must set proper labels.
*
* @experimental
*/
@Component({
selector: 'si-icon',
imports: [NgClass],
template: ` <div
aria-hidden="true"
[ngClass]="svgIcon() ? '' : fontIcon()"
[innerHTML]="svgIcon()"
></div>`,
styles: `
:host {
display: inline-flex;
font-weight: normal;
vertical-align: middle;
line-height: 1;
::ng-deep svg {
display: block;
block-size: 1em;
fill: currentColor;
}
}
`,
changeDetection: ChangeDetectionStrategy.OnPush,
host: {
'[attr.data-icon]': 'icon()'
}
})
export class SiIconComponent {
/**
* Define which icon should be rendered.
* Provide using:
* - value of the icon map provided by `addIcons`
* - (not recommended): plain string in kebab-case or camelCase
*
* @example
* ```ts
* import { elementUser } from '@simpl/element-icons/ionic';
*
* @Component({template: `
* <si-icon [icon]="icons.elementUser" />
* <si-icon icon="element-user" />
* <si-icon icon="elementUser" />
*
* `})
* class MyComponent {
* icons = addIcons(elementUser);
* }
* ```
*/
readonly icon = input.required<string>();
private readonly config = inject(ICON_CONFIG);
private readonly iconService = inject(IconService);
protected readonly svgIcon = computed(() =>
this.config.disableSvgIcons ? undefined : this.iconService.getIcon(this.icon())
);
/** Icon class, which is ensured to be kebab-case. */
protected readonly fontIcon = computed(() =>
this.svgIcon() ? undefined : this.camelToKebabCase(this.icon())
);
private camelToKebabCase(str: string): string {
return str
?.replace(/([a-z])([A-Z0-9])/g, '$1-$2')
.replace(/([0-9])([A-Z])/g, '$1-$2')
.toLowerCase();
}
}
|