mirror of
https://gitlab.com/openstapps/openstapps.git
synced 2026-01-20 16:42:56 +00:00
refactor: migrate to material symbols icon set
This commit is contained in:
145
src/app/util/ion-icon/replace-util.ts
Normal file
145
src/app/util/ion-icon/replace-util.ts
Normal file
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Copyright (C) 2022 StApps
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {
|
||||
ComponentRef,
|
||||
Directive,
|
||||
ElementRef,
|
||||
OnDestroy,
|
||||
OnInit,
|
||||
ViewContainerRef,
|
||||
} from '@angular/core';
|
||||
import {IonIcon} from '@ionic/angular';
|
||||
import {IonIconDirective} from './ion-icon.directive';
|
||||
|
||||
export type IconData = Omit<
|
||||
Partial<IonIconDirective>,
|
||||
| 'ngOnChanges'
|
||||
| 'ngOnInit'
|
||||
| 'viewContainerRef'
|
||||
| 'ngOnDestroy'
|
||||
| 'element'
|
||||
| 'ionIcon'
|
||||
| 'disableProperty'
|
||||
>;
|
||||
|
||||
/**
|
||||
* A utility class to replace ion-icons in other ionic components.
|
||||
*/
|
||||
@Directive()
|
||||
export abstract class IconReplacer implements OnInit, OnDestroy {
|
||||
private mutationObserver: MutationObserver;
|
||||
|
||||
protected slotName = 'sc-icon';
|
||||
|
||||
/**
|
||||
* The host element
|
||||
*
|
||||
* This will be either element.nativeElement.shadowRoot or element.nativeElement
|
||||
* depending on the iconDomLocation
|
||||
*/
|
||||
protected host: HTMLElement;
|
||||
|
||||
/**
|
||||
* @param element The host element
|
||||
* @param viewContainerRef The view container ref
|
||||
* @param iconDomLocation If the icon is placed inside the shadow dom or not
|
||||
* @protected
|
||||
*/
|
||||
protected constructor(
|
||||
private readonly element: ElementRef,
|
||||
private readonly viewContainerRef: ViewContainerRef,
|
||||
private readonly iconDomLocation: 'shadow' | 'light',
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Replace the icons here
|
||||
*/
|
||||
abstract replace(): void;
|
||||
|
||||
/**
|
||||
* If any additional work needs to be done, this
|
||||
* is called during ngOnInit
|
||||
*/
|
||||
init() {
|
||||
// noop
|
||||
}
|
||||
|
||||
/**
|
||||
* If you need to do cleanup, this method is called during ngOnDestroy
|
||||
*/
|
||||
destroy() {
|
||||
// noop
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.host =
|
||||
this.iconDomLocation === 'shadow'
|
||||
? this.element.nativeElement.shadowRoot
|
||||
: this.element.nativeElement;
|
||||
|
||||
this.init();
|
||||
|
||||
this.mutationObserver = new MutationObserver(() => this.replace());
|
||||
this.mutationObserver.observe(this.host, {
|
||||
childList: true,
|
||||
});
|
||||
}
|
||||
|
||||
replaceIcon(parent: HTMLElement | null, iconData: IconData) {
|
||||
if (!parent) return;
|
||||
|
||||
const icon = parent.querySelector('ion-icon');
|
||||
if (!icon) return;
|
||||
|
||||
const scIcon = this.createIcon(iconData);
|
||||
// @ts-expect-error can be spread
|
||||
scIcon.location.nativeElement.classList.add(...icon.classList);
|
||||
|
||||
if (this.iconDomLocation === 'shadow') {
|
||||
// shadow dom needs to utilize slotting, to put it outside
|
||||
// the shadow dom, otherwise it won't receive any css data
|
||||
const slot = document.createElement('slot');
|
||||
slot.name = this.slotName;
|
||||
icon.replaceWith(slot);
|
||||
|
||||
scIcon.location.nativeElement.slot = this.slotName;
|
||||
this.element.nativeElement.append(scIcon.location.nativeElement);
|
||||
} else {
|
||||
icon.replaceWith(scIcon.location.nativeElement);
|
||||
}
|
||||
}
|
||||
|
||||
private createIcon(iconData: IconData): ComponentRef<IonIcon> {
|
||||
const ionIcon = this.viewContainerRef.createComponent(IonIcon, {});
|
||||
const iconDirective = new IonIconDirective(
|
||||
ionIcon.location,
|
||||
this.viewContainerRef,
|
||||
ionIcon.instance,
|
||||
);
|
||||
for (const key in iconData) {
|
||||
// @ts-expect-error type mismatch
|
||||
iconDirective[key] = iconData[key];
|
||||
}
|
||||
iconDirective.ngOnInit();
|
||||
|
||||
return ionIcon;
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.mutationObserver.disconnect();
|
||||
this.destroy();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user