68 lines
2.2 KiB
TypeScript
68 lines
2.2 KiB
TypeScript
import {CommonModule} from '@angular/common';
|
|
import {Component, Input, Optional} from '@angular/core';
|
|
import {MiniMessageComponent as MiniMessageNode, ResolvedStyle} from '../../mini-message/mini-message.types';
|
|
import {hoverEventToTitle, mergeStyle, ownText, styleToNgStyle} from '../../mini-message/mini-message.util';
|
|
import {ObfuscatedDirective} from '../../mini-message/obfuscated.directive';
|
|
import {MiniMessageInteractionService} from '../../mini-message/mini-message-interaction.service';
|
|
|
|
/**
|
|
* Renders a Paper/Adventure component-JSON tree as styled HTML.
|
|
*
|
|
* Usage:
|
|
* providers: [MiniMessageInteractionService] // once, at the root that hosts <mini-message>
|
|
* <mini-message [node]="myComponentJson"></mini-message>
|
|
*
|
|
* Then subscribe to click events (run_command / suggest_command / copy_to_clipboard /
|
|
* change_page) via the injected MiniMessageInteractionService.clicks$; open_url is handled
|
|
* natively as a real link so no subscription is needed for that case.
|
|
*/
|
|
@Component({
|
|
selector: 'mini-message',
|
|
standalone: true,
|
|
imports: [CommonModule, ObfuscatedDirective],
|
|
templateUrl: './mini-message.component.html',
|
|
styleUrl: './mini-message.component.scss',
|
|
})
|
|
export class MiniMessageComponent {
|
|
@Input() node!: MiniMessageNode;
|
|
@Input() parentStyle?: ResolvedStyle;
|
|
|
|
constructor(@Optional() private readonly interaction: MiniMessageInteractionService | null) {
|
|
}
|
|
|
|
get style(): ResolvedStyle {
|
|
return mergeStyle(this.parentStyle, this.node);
|
|
}
|
|
|
|
get ngStyle(): Record<string, string> {
|
|
return styleToNgStyle(this.style);
|
|
}
|
|
|
|
get text(): string {
|
|
return ownText(this.node);
|
|
}
|
|
|
|
get hoverTitle(): string | null {
|
|
return hoverEventToTitle(this.node.hoverEvent);
|
|
}
|
|
|
|
get isUrlLink(): boolean {
|
|
return this.node.clickEvent?.action === 'open_url';
|
|
}
|
|
|
|
get hasNonUrlClick(): boolean {
|
|
return !!this.node.clickEvent && this.node.clickEvent.action !== 'open_url';
|
|
}
|
|
|
|
onClick(): void {
|
|
const click = this.node.clickEvent;
|
|
if (!click) return;
|
|
|
|
if (click.action === 'copy_to_clipboard') {
|
|
navigator.clipboard?.writeText(click.value);
|
|
}
|
|
|
|
this.interaction?.emitClick({action: click.action, value: click.value});
|
|
}
|
|
}
|