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 * * * 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 { 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}); } }