mirror of
https://gitlab.com/openstapps/openstapps.git
synced 2026-01-20 00:23:03 +00:00
134 lines
3.3 KiB
TypeScript
134 lines
3.3 KiB
TypeScript
/*
|
|
* 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,
|
|
Host,
|
|
Input,
|
|
OnChanges,
|
|
OnDestroy,
|
|
OnInit,
|
|
Optional,
|
|
Self,
|
|
ViewContainerRef,
|
|
} from '@angular/core';
|
|
import {IconComponent} from './icon.component';
|
|
import {IonIcon} from '@ionic/angular';
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
const noop = () => {};
|
|
const noopProperty = {
|
|
set: noop,
|
|
get: noop,
|
|
};
|
|
|
|
@Directive({
|
|
selector: 'ion-icon',
|
|
})
|
|
export class IonIconDirective implements OnInit, OnDestroy, OnChanges {
|
|
@Input() name: string;
|
|
|
|
@Input() md: string;
|
|
|
|
@Input() ios: string;
|
|
|
|
@Input() fill = false;
|
|
|
|
@Input() weight: number;
|
|
|
|
@Input() size: number;
|
|
|
|
@Input() grade: number;
|
|
|
|
private mutationObserver: MutationObserver;
|
|
|
|
iconComponent?: ComponentRef<IconComponent>;
|
|
|
|
private static get mode(): 'md' | 'ios' {
|
|
return document.querySelector(':root')?.getAttribute('mode') as
|
|
| 'md'
|
|
| 'ios';
|
|
}
|
|
|
|
constructor(
|
|
private element: ElementRef,
|
|
private viewContainerRef: ViewContainerRef,
|
|
@Host() @Self() @Optional() private ionIcon: IonIcon,
|
|
) {}
|
|
|
|
ngOnInit() {
|
|
this.iconComponent = this.viewContainerRef.createComponent(
|
|
IconComponent,
|
|
{},
|
|
);
|
|
|
|
this.element.nativeElement.insertBefore(
|
|
this.iconComponent.location.nativeElement,
|
|
this.element.nativeElement.firstChild,
|
|
);
|
|
|
|
this.mutationObserver = new MutationObserver(() => {
|
|
const inner =
|
|
this.element.nativeElement.shadowRoot.querySelector('.icon-inner');
|
|
if (!inner) return;
|
|
|
|
inner.insertBefore(document.createElement('slot'), inner.firstChild);
|
|
});
|
|
this.mutationObserver.observe(this.element.nativeElement.shadowRoot, {
|
|
childList: true,
|
|
});
|
|
|
|
this.ngOnChanges();
|
|
// this will effectively completely disable the ion-icon component
|
|
for (const name of ['src', 'name', 'icon', 'md', 'ios']) {
|
|
this.disableProperty(name);
|
|
}
|
|
}
|
|
|
|
ngOnDestroy() {
|
|
this.mutationObserver.disconnect();
|
|
}
|
|
|
|
ngOnChanges() {
|
|
if (!this.iconComponent) return;
|
|
for (const key of ['name', 'weight', 'fill', 'size', 'grade'] as Array<
|
|
keyof IconComponent & keyof IonIconDirective
|
|
>) {
|
|
// @ts-expect-error type mismatch
|
|
this.iconComponent.instance[key] = this[key];
|
|
}
|
|
|
|
for (const mode of ['md', 'ios'] as Array<'md' | 'ios'>) {
|
|
if (this[mode] && IonIconDirective.mode === mode) {
|
|
this.iconComponent.instance.name = this[mode];
|
|
}
|
|
}
|
|
|
|
if (this.size) {
|
|
this.element.nativeElement.style.cssText = `font-size: ${this.size}px;`;
|
|
}
|
|
}
|
|
|
|
disableProperty(name: string) {
|
|
Object.defineProperty(
|
|
Object.getPrototypeOf((this.ionIcon as unknown as {el: HTMLElement}).el),
|
|
name,
|
|
noopProperty,
|
|
);
|
|
}
|
|
}
|