diff --git a/projects/demo/src/app/app.component.ts b/projects/demo/src/app/app.component.ts index bc42e95..4e9dc83 100644 --- a/projects/demo/src/app/app.component.ts +++ b/projects/demo/src/app/app.component.ts @@ -1,7 +1,6 @@ import { DecimalPipe } from '@angular/common'; import { Component } from '@angular/core'; -import { FaConfig, FaIconLibrary, FontAwesomeModule } from '@fortawesome/angular-fontawesome'; -import { IconDefinition, IconName } from '@fortawesome/fontawesome-svg-core'; +import { FaConfig, FaIconLibrary, FontAwesomeModule, IconDefinition } from '@fortawesome/angular-fontawesome'; import { faFlag, faUser as regularUser } from '@fortawesome/free-regular-svg-icons'; import { faAdjust, @@ -48,7 +47,7 @@ export class AppComponent { faSpinner = faSpinner; faDummy: IconDefinition = { prefix: 'fad', - iconName: 'dummy' as IconName, + iconName: 'dummy', icon: [512, 512, [], 'f030', ['M50 50 H412 V250 H50 Z', 'M50 262 H412 V462 H50 Z']], }; diff --git a/src/lib/config.ts b/src/lib/config.ts index 1bad0e3..9634ecd 100644 --- a/src/lib/config.ts +++ b/src/lib/config.ts @@ -1,5 +1,5 @@ import { Injectable } from '@angular/core'; -import { IconDefinition, IconPrefix } from '@fortawesome/fontawesome-svg-core'; +import { IconDefinition, IconPrefix } from './types'; @Injectable({ providedIn: 'root' }) export class FaConfig { diff --git a/src/lib/icon-library.ts b/src/lib/icon-library.ts index d488c03..1b2515f 100644 --- a/src/lib/icon-library.ts +++ b/src/lib/icon-library.ts @@ -1,5 +1,5 @@ import { Injectable } from '@angular/core'; -import { IconDefinition, IconName, IconPack, IconPrefix } from '@fortawesome/fontawesome-svg-core'; +import { IconDefinition, IconName, IconPack, IconPrefix } from './types'; export interface FaIconLibraryInterface { addIcons(...icons: IconDefinition[]): void; diff --git a/src/lib/icon/duotone-icon.component.ts b/src/lib/icon/duotone-icon.component.ts index c0827aa..e927823 100644 --- a/src/lib/icon/duotone-icon.component.ts +++ b/src/lib/icon/duotone-icon.component.ts @@ -1,5 +1,6 @@ import { Component, Input } from '@angular/core'; -import { IconDefinition, IconParams, IconProp } from '@fortawesome/fontawesome-svg-core'; +import { IconDefinition as CoreIconDefinition, IconParams } from '@fortawesome/fontawesome-svg-core'; +import { IconDefinition, IconProp } from '../types'; import { FaIconComponent } from './icon.component'; @Component({ @@ -49,7 +50,7 @@ export class FaDuotoneIconComponent extends FaIconComponent { */ @Input() secondaryColor?: string; - protected findIconDefinition(i: IconProp | IconDefinition): IconDefinition | null { + protected findIconDefinition(i: IconProp | IconDefinition): CoreIconDefinition | null { const definition = super.findIconDefinition(i); if (definition != null && !Array.isArray(definition.icon[4])) { diff --git a/src/lib/icon/icon.component.spec.ts b/src/lib/icon/icon.component.spec.ts index ba70a79..de6f57d 100644 --- a/src/lib/icon/icon.component.spec.ts +++ b/src/lib/icon/icon.component.spec.ts @@ -1,6 +1,5 @@ import { Component, ViewChild, ViewContainerRef } from '@angular/core'; import { TestBed } from '@angular/core/testing'; -import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { faUser as faUserRegular } from '@fortawesome/free-regular-svg-icons'; import { faCircle, faUser } from '@fortawesome/free-solid-svg-icons'; import { Subject } from 'rxjs'; @@ -8,6 +7,7 @@ import { startWith } from 'rxjs/operators'; import { initTest, queryByCss } from '../../testing/helpers'; import { FaConfig } from '../config'; import { FaIconLibrary } from '../icon-library'; +import { IconProp } from '../types'; import { FaIconComponent } from './icon.component'; describe('FaIconComponent', () => { diff --git a/src/lib/icon/icon.component.ts b/src/lib/icon/icon.component.ts index 88217e8..bf00db7 100644 --- a/src/lib/icon/icon.component.ts +++ b/src/lib/icon/icon.component.ts @@ -4,9 +4,8 @@ import { FaSymbol, FlipProp, icon, - IconDefinition, + IconDefinition as CoreIconDefinition, IconParams, - IconProp, parse, PullProp, RotateProp, @@ -22,6 +21,7 @@ import { faClassList } from '../shared/utils/classlist.util'; import { faNormalizeIconSpec } from '../shared/utils/normalize-icon-spec.util'; import { FaStackItemSizeDirective } from '../stack/stack-item-size.directive'; import { FaStackComponent } from '../stack/stack.component'; +import { IconDefinition, IconProp } from '../types'; @Component({ selector: 'fa-icon', @@ -86,18 +86,18 @@ export class FaIconComponent implements OnChanges { } } - ngOnChanges(changes: SimpleChanges) { + ngOnChanges(changes: SimpleChanges): void { if (this.icon == null && this.config.fallbackIcon == null) { faWarnIfIconSpecMissing(); return; } if (changes) { - const iconToBeRendered = this.icon != null ? this.icon : this.config.fallbackIcon; - const iconDefinition = this.findIconDefinition(iconToBeRendered); + const iconDefinition = this.findIconDefinition(this.icon ?? this.config.fallbackIcon); if (iconDefinition != null) { const params = this.buildParams(); - this.renderIcon(iconDefinition, params); + const renderedIcon = icon(iconDefinition, params); + this.renderedIconHTML = this.sanitizer.bypassSecurityTrustHtml(renderedIcon.html.join('\n')); } } } @@ -113,15 +113,15 @@ export class FaIconComponent implements OnChanges { this.ngOnChanges({}); } - protected findIconDefinition(i: IconProp | IconDefinition): IconDefinition | null { + protected findIconDefinition(i: IconProp | IconDefinition): CoreIconDefinition | null { const lookup = faNormalizeIconSpec(i, this.config.defaultPrefix); if ('icon' in lookup) { - return lookup; + return lookup as CoreIconDefinition; } const definition = this.iconLibrary.getIconDefinition(lookup.prefix, lookup.iconName); if (definition != null) { - return definition; + return definition as CoreIconDefinition; } faWarnIfIconDefinitionMissing(lookup); @@ -154,9 +154,4 @@ export class FaIconComponent implements OnChanges { }, }; } - - private renderIcon(definition: IconDefinition, params: IconParams) { - const renderedIcon = icon(definition, params); - this.renderedIconHTML = this.sanitizer.bypassSecurityTrustHtml(renderedIcon.html.join('\n')); - } } diff --git a/src/lib/public_api.ts b/src/lib/public_api.ts index 3226f33..d9b69fb 100644 --- a/src/lib/public_api.ts +++ b/src/lib/public_api.ts @@ -9,3 +9,4 @@ export { FaLayersCounterComponent } from './layers/layers-counter.component'; export { FaStackComponent } from './stack/stack.component'; export { FaStackItemSizeDirective } from './stack/stack-item-size.directive'; export { FaIconLibrary, FaIconLibraryInterface } from './icon-library'; +export { IconPrefix, IconName, IconLookup, IconDefinition, IconPack } from './types'; diff --git a/src/lib/shared/errors/warn-if-icon-html-missing.ts b/src/lib/shared/errors/warn-if-icon-html-missing.ts index ce4149a..4062a5f 100644 --- a/src/lib/shared/errors/warn-if-icon-html-missing.ts +++ b/src/lib/shared/errors/warn-if-icon-html-missing.ts @@ -1,4 +1,4 @@ -import { IconLookup } from '@fortawesome/fontawesome-svg-core'; +import { IconLookup } from '../../types'; export const faWarnIfIconDefinitionMissing = (iconSpec: IconLookup) => { throw new Error( diff --git a/src/lib/shared/models/props.model.ts b/src/lib/shared/models/props.model.ts index ad48af0..5d65e89 100644 --- a/src/lib/shared/models/props.model.ts +++ b/src/lib/shared/models/props.model.ts @@ -1,13 +1,13 @@ import { FaSymbol, FlipProp, - IconProp, PullProp, RotateProp, SizeProp, Styles, Transform, } from '@fortawesome/fontawesome-svg-core'; +import { IconProp } from '../../types'; /** * Fontawesome props. diff --git a/src/lib/shared/utils/is-icon-lookup.util.ts b/src/lib/shared/utils/is-icon-lookup.util.ts index 992b3bf..303f68c 100644 --- a/src/lib/shared/utils/is-icon-lookup.util.ts +++ b/src/lib/shared/utils/is-icon-lookup.util.ts @@ -1,4 +1,4 @@ -import { IconLookup, IconProp } from '@fortawesome/fontawesome-svg-core'; +import { IconLookup, IconProp } from '../../types'; /** * Returns if is IconLookup or not. diff --git a/src/lib/shared/utils/normalize-icon-spec.util.ts b/src/lib/shared/utils/normalize-icon-spec.util.ts index e53eb07..1ea9ff7 100644 --- a/src/lib/shared/utils/normalize-icon-spec.util.ts +++ b/src/lib/shared/utils/normalize-icon-spec.util.ts @@ -1,4 +1,4 @@ -import { IconDefinition, IconLookup, IconPrefix, IconProp } from '@fortawesome/fontawesome-svg-core'; +import { IconDefinition, IconLookup, IconPrefix, IconProp } from '../../types'; import { isIconLookup } from './is-icon-lookup.util'; /** @@ -12,9 +12,9 @@ export const faNormalizeIconSpec = ( return iconSpec; } - if (typeof iconSpec === 'string') { - return { prefix: defaultPrefix, iconName: iconSpec }; + if (Array.isArray(iconSpec) && iconSpec.length === 2) { + return { prefix: iconSpec[0], iconName: iconSpec[1] }; } - return { prefix: iconSpec[0], iconName: iconSpec[1] }; + return { prefix: defaultPrefix, iconName: iconSpec }; }; diff --git a/src/lib/types.ts b/src/lib/types.ts new file mode 100644 index 0000000..442e854 --- /dev/null +++ b/src/lib/types.ts @@ -0,0 +1,34 @@ +import { IconName as CoreIconName, IconPrefix as CoreIconPrefix } from '@fortawesome/fontawesome-svg-core'; + +// Currently, when a union type of a primitive type is combined with literal +// types, TypeScript loses all information about the combined literals. Thus, +// when such type is used in an IDE with autocompletion, no suggestions are +// made for the declared literals. +// Below types use a workaround from [Microsoft/TypeScript#29729](https://github.com/Microsoft/TypeScript/issues/29729). + +export type IconPrefix = CoreIconPrefix | (string & {}); + +export type IconName = CoreIconName | (string & {}); + +export interface IconLookup { + prefix: IconPrefix; + iconName: IconName; +} + +export interface IconDefinition { + prefix: IconPrefix; + iconName: IconName; + icon: [ + number, // width + number, // height + string[], // ligatures + string, // unicode + string | string[], // svgPathData + ]; +} + +export interface IconPack { + [key: string]: IconDefinition; +} + +export type IconProp = IconName | [IconPrefix, IconName] | IconLookup; diff --git a/src/testing/helpers.ts b/src/testing/helpers.ts index 3940371..3c63f1e 100644 --- a/src/testing/helpers.ts +++ b/src/testing/helpers.ts @@ -1,7 +1,6 @@ import { CommonModule } from '@angular/common'; import { Type } from '@angular/core'; import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { IconDefinition, IconName } from '@fortawesome/fontawesome-svg-core'; import { FaDuotoneIconComponent } from '../lib/icon/duotone-icon.component'; import { FaIconComponent } from '../lib/icon/icon.component'; import { FaLayersCounterComponent } from '../lib/layers/layers-counter.component'; @@ -9,6 +8,7 @@ import { FaLayersTextComponent } from '../lib/layers/layers-text.component'; import { FaLayersComponent } from '../lib/layers/layers.component'; import { FaStackItemSizeDirective } from '../lib/stack/stack-item-size.directive'; import { FaStackComponent } from '../lib/stack/stack.component'; +import { IconDefinition } from '../lib/types'; export const initTest = (component: Type, providers?: any[]): ComponentFixture => { TestBed.configureTestingModule({ @@ -33,6 +33,6 @@ export const queryByCss = (fixture: ComponentFixture, cssSelector: string): export const faDummy: IconDefinition = { prefix: 'fad', - iconName: 'dummy' as IconName, + iconName: 'dummy', icon: [512, 512, [], 'f030', ['M50 50 H412 V250 H50 Z', 'M50 262 H412 V462 H50 Z']], }; diff --git a/testing/src/icon/mock-icon-library.service.ts b/testing/src/icon/mock-icon-library.service.ts index 6b079f0..7686951 100644 --- a/testing/src/icon/mock-icon-library.service.ts +++ b/testing/src/icon/mock-icon-library.service.ts @@ -1,10 +1,9 @@ import { Injectable } from '@angular/core'; -import { FaIconLibraryInterface } from '@fortawesome/angular-fontawesome'; -import { IconDefinition, IconName, IconPrefix } from '@fortawesome/fontawesome-svg-core'; +import { FaIconLibraryInterface, IconDefinition, IconName, IconPrefix } from '@fortawesome/angular-fontawesome'; export const dummyIcon: IconDefinition = { prefix: 'fad', - iconName: 'dummy' as IconName, + iconName: 'dummy', icon: [512, 512, [], 'f030', 'M50 50 H462 V462 H50 Z'], };