From f504079fac1968236fbe3d140a5e2f652d793590 Mon Sep 17 00:00:00 2001 From: Alexander Ciesielski Date: Tue, 21 May 2024 17:06:01 +0200 Subject: [PATCH] feat(icon): new component and example usage in menu --- src/app/components/icon/icon.css | 0 src/app/components/icon/icon.spec.ts | 46 +++++++++++++++++++++++++ src/app/components/icon/icon.ts | 38 ++++++++++++++++++++ src/app/components/icon/ng-package.json | 6 ++++ src/app/components/icon/public_api.ts | 1 + src/app/components/menu/menu.ts | 9 +++-- 6 files changed, 97 insertions(+), 3 deletions(-) create mode 100644 src/app/components/icon/icon.css create mode 100755 src/app/components/icon/icon.spec.ts create mode 100755 src/app/components/icon/icon.ts create mode 100644 src/app/components/icon/ng-package.json create mode 100644 src/app/components/icon/public_api.ts diff --git a/src/app/components/icon/icon.css b/src/app/components/icon/icon.css new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/app/components/icon/icon.spec.ts b/src/app/components/icon/icon.spec.ts new file mode 100755 index 00000000000..590ef0343b9 --- /dev/null +++ b/src/app/components/icon/icon.spec.ts @@ -0,0 +1,46 @@ +import { Component, Input } from '@angular/core'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { By } from '@angular/platform-browser'; +import { Icon, PIconComponent, P_ICON_COMPONENT } from './icon'; + +describe('Icon', () => { + let fixture: ComponentFixture; + + beforeEach(() => TestBed.configureTestingModule({ imports: [Icon] })); + + it('should display default template if no override has been defined', () => { + fixture = TestBed.createComponent(Icon); + fixture.componentInstance.icon = 'pi pi-check'; + fixture.componentInstance.iconStyle = { color: 'red' }; + + fixture.detectChanges(); + const iconEl = fixture.debugElement.query(By.css('i')); + expect(iconEl).toBeTruthy(); + }); + + it('should display custom component if override has been defined', () => { + @Component({ + standalone: true, + selector: 'custom-icon', + template: ` Hello world! ` + }) + class CustomIconComponent implements PIconComponent { + @Input() icon: string; + @Input() iconStyle?: any; + @Input() iconClass?: any; + } + + TestBed.overrideProvider(P_ICON_COMPONENT, { useValue: CustomIconComponent }); + fixture = TestBed.createComponent(Icon); + fixture.componentInstance.icon = 'pi pi-check'; + fixture.componentInstance.iconStyle = { color: 'red' }; + + fixture.detectChanges(); + const customIconEl = fixture.debugElement.query(By.css('custom-icon')); + expect(customIconEl).toBeTruthy(); + + const customIconComponent = customIconEl.componentInstance as CustomIconComponent; + expect(customIconComponent.icon).toBe('pi pi-check'); + expect(customIconComponent.iconStyle).toEqual({ color: 'red' }); + }); +}); diff --git a/src/app/components/icon/icon.ts b/src/app/components/icon/icon.ts new file mode 100755 index 00000000000..4efe08e5896 --- /dev/null +++ b/src/app/components/icon/icon.ts @@ -0,0 +1,38 @@ +import { NgClass, NgComponentOutlet, NgStyle } from '@angular/common'; +import { ChangeDetectionStrategy, Component, InjectionToken, Input, Type, inject } from '@angular/core'; + +export interface PIconComponent { + icon: string; + iconStyle?: NgStyle['ngStyle']; +} + +export const P_ICON_COMPONENT = new InjectionToken>('P_ICON_COMPONENT'); + +/** + * Icon is a simple component to render an icon. + * @group Components + */ +@Component({ + standalone: true, + imports: [NgClass, NgStyle, NgComponentOutlet], + selector: 'p-icon', + template: ` + @if(!iconComponentClass) { + + } @else { + + } + `, + styleUrls: ['./icon.css'], + changeDetection: ChangeDetectionStrategy.OnPush, + host: { + class: 'p-element' + // style: 'display: contents' + } +}) +export class Icon implements PIconComponent { + @Input({ required: true }) icon: string; + @Input() iconStyle?: NgStyle['ngStyle']; + + protected readonly iconComponentClass = inject(P_ICON_COMPONENT, { optional: true }); +} diff --git a/src/app/components/icon/ng-package.json b/src/app/components/icon/ng-package.json new file mode 100644 index 00000000000..ab5467eb7e4 --- /dev/null +++ b/src/app/components/icon/ng-package.json @@ -0,0 +1,6 @@ +{ + "$schema": "ng-packagr/ng-package.schema.json", + "lib": { + "entryFile": "public_api.ts" + } + } \ No newline at end of file diff --git a/src/app/components/icon/public_api.ts b/src/app/components/icon/public_api.ts new file mode 100644 index 00000000000..af77d84efcc --- /dev/null +++ b/src/app/components/icon/public_api.ts @@ -0,0 +1 @@ +export * from './icon'; diff --git a/src/app/components/menu/menu.ts b/src/app/components/menu/menu.ts index bc764ea4a30..1acb820f2b0 100755 --- a/src/app/components/menu/menu.ts +++ b/src/app/components/menu/menu.ts @@ -23,7 +23,6 @@ import { ViewRef, booleanAttribute, computed, - effect, forwardRef, numberAttribute, signal @@ -36,6 +35,7 @@ import { RippleModule } from 'primeng/ripple'; import { TooltipModule } from 'primeng/tooltip'; import { Nullable, VoidListener } from 'primeng/ts-helpers'; import { UniqueComponentId, ZIndexUtils } from 'primeng/utils'; +import { Icon } from '../icon/icon'; @Pipe({ name: 'safeHtml' @@ -103,7 +103,10 @@ export class SafeHtmlPipe implements PipeTransform { - + @if(item.icon) { + + } + {{ item.label }} {{ item.badge }} @@ -821,7 +824,7 @@ export class Menu implements OnDestroy { } @NgModule({ - imports: [CommonModule, RouterModule, RippleModule, TooltipModule], + imports: [CommonModule, RouterModule, RippleModule, TooltipModule, Icon], exports: [Menu, RouterModule, TooltipModule], declarations: [Menu, MenuItemContent, SafeHtmlPipe] })