AAE-40896 Create adf-icon directive (#11467)

* AAE-40896 Create adf-icon directive

* AAE-40896 Update ligature text method
This commit is contained in:
Diogo Bastos
2025-12-17 13:46:58 +00:00
committed by GitHub
parent fe39b3c1bd
commit 52cadb5b8a
3 changed files with 162 additions and 0 deletions
@@ -0,0 +1,99 @@
/*!
* @license
* Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Component } from '@angular/core';
import { MatIconModule } from '@angular/material/icon';
import { IconDirective } from './icon.directive';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { IconType, MatIconHarness, MatIconTestingModule } from '@angular/material/icon/testing';
import { HarnessLoader } from '@angular/cdk/testing';
import { ICON_ALIAS_MAP_TOKEN } from './icon-alias-map.token';
@Component({
template: `<mat-icon adf-icon [name]="name" />`,
standalone: true,
imports: [MatIconModule, IconDirective]
})
class TestComponent {
name: string;
}
describe('IconDirective', () => {
let fixture: ComponentFixture<TestComponent>;
let component: TestComponent;
let loader: HarnessLoader;
describe('alias map NOT provided', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [TestComponent, MatIconTestingModule]
});
fixture = TestBed.createComponent(TestComponent);
component = fixture.componentInstance;
loader = TestbedHarnessEnvironment.loader(fixture);
});
it('should append ligature text if no alias map is provided', async () => {
component.name = 'mock_ligature';
const iconHarness = await loader.getHarness(MatIconHarness);
expect(await iconHarness.getType()).toBe(IconType.FONT);
expect(await iconHarness.getName()).toContain('mock_ligature');
});
});
describe('alias map provided', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [TestComponent, MatIconTestingModule],
providers: [
{
provide: ICON_ALIAS_MAP_TOKEN,
useValue: {
mock_icon: 'mock_alias'
}
}
]
});
fixture = TestBed.createComponent(TestComponent);
component = fixture.componentInstance;
loader = TestbedHarnessEnvironment.loader(fixture);
});
it('should append ligature text if alias map is provided but name does not match any key', async () => {
component.name = 'mock_ligature';
const iconHarness = await loader.getHarness(MatIconHarness);
expect(await iconHarness.getType()).toBe(IconType.FONT);
expect(await iconHarness.getName()).toContain('mock_ligature');
});
it('should set svg icon if alias map is provided and name matches alias key', async () => {
component.name = 'mock_icon';
const iconHarness = await loader.getHarness(MatIconHarness);
expect(await iconHarness.getType()).toBe(IconType.SVG);
expect(await iconHarness.getName()).toContain('mock_alias');
});
});
});
+62
View File
@@ -0,0 +1,62 @@
/*!
* @license
* Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Directive, ElementRef, inject, Input, OnChanges } from '@angular/core';
import { ICON_ALIAS_MAP_TOKEN } from './icon-alias-map.token';
import { MatIcon } from '@angular/material/icon';
@Directive({
selector: 'mat-icon[adf-icon]'
})
export class IconDirective implements OnChanges {
private readonly matIcon = inject(MatIcon);
private readonly elementRef: ElementRef<HTMLElement> = inject(ElementRef);
private readonly aliasMap = inject(ICON_ALIAS_MAP_TOKEN, { optional: true });
@Input() name: string;
ngOnChanges() {
const iconAlias = this.aliasMap?.[this.name];
iconAlias ? this.setSvgIcon(iconAlias) : this.appendLigatureText();
}
private setSvgIcon(icon: string) {
this.matIcon.svgIcon = icon;
}
private appendLigatureText() {
this.resetSvg();
const element = this.elementRef.nativeElement;
const textNode = this.findTextNode(element);
if (textNode) {
textNode.nodeValue = this.name;
} else {
this.elementRef.nativeElement.appendChild(document.createTextNode(this.name));
}
}
private findTextNode(element: HTMLElement): ChildNode | undefined {
return Array.from(element.childNodes).find((node: ChildNode) => node.nodeType === Node.TEXT_NODE);
}
private resetSvg() {
this.matIcon.svgIcon = null;
}
}
+1
View File
@@ -18,3 +18,4 @@
export * from './icon.component';
export * from './icon-alias-map.type';
export * from './icon-alias-map.token';
export * from './icon.directive';