UNPKG

@teaui/core

Version:

A high-level terminal UI library for Node

120 lines 3.79 kB
import { Container } from '../Container.js'; import { Style } from '../Style.js'; import { Palette } from '../Palette.js'; import { Stack } from './Stack.js'; import { Separator } from './Separator.js'; import { Text } from './Text.js'; /** * Internal base class for Alert and Callout. Not exported. * * Owns a managed Stack for child layout. Subclasses must call * `this.addDirect(view)` to add views to the Container directly * (bypassing the stack-forwarding `add()` override), and use * `this.contentStack` to place the stack in their view hierarchy. */ export class Notification extends Container { #stack; #title; #titleStyle; #titleView; #separator; constructor({ title, purpose, direction, children, child, ...props }) { super(props); this.#title = title; this.#titleStyle = new Style({ bold: true }); this.#stack = new Stack({ direction: direction ?? 'down' }); if (purpose) { this.purpose = Palette[purpose]; } if (child) { this.add(child); } else if (children) { for (const c of children) { this.add(c); } } // Resolve title after children are added so we can fall back to child heading this.#syncTitle(); } /** * The managed Stack that holds title + children. * Subclasses use this to place the stack in their view hierarchy. */ get contentStack() { return this.#stack; } /** * Add a view directly to the Container, bypassing the stack-forwarding * `add()` override. Used by subclasses to set up their view hierarchy. */ addDirect(child, at) { super.add(child, at); } update(props) { this.#updateNotification(props); super.update(props); } #updateNotification({ title, purpose, direction }) { this.#title = title; this.#stack.direction = direction ?? 'down'; this.#syncTitle(); if (purpose) { this.purpose = Palette[purpose]; } } /** * The resolved title: explicit `title` prop, or the first user child's * `heading`. */ #resolvedTitle() { if (this.#title !== undefined) return this.#title; return this.#firstUserChild()?.heading; } /** * Returns the first child that isn't the internal title/separator views. */ #firstUserChild() { for (const child of this.#stack.children) { if (child !== this.#titleView && child !== this.#separator) { return child; } } return undefined; } /** * Syncs the title view in the stack with the resolved title. */ #syncTitle() { const resolved = this.#resolvedTitle(); if (resolved) { if (this.#titleView) { this.#titleView.text = resolved; } else if (!this.#titleView) { this.#titleView = new Text({ text: resolved, style: this.#titleStyle, wrap: true, }); this.#separator = Separator.horizontal(); this.#stack.add(this.#titleView, 0); this.#stack.add(this.#separator, 1); } } else if (!resolved && this.#titleView) { this.#stack.removeChild(this.#titleView); this.#stack.removeChild(this.#separator); this.#titleView = undefined; this.#separator = undefined; } } add(child, at) { this.#stack.add(child, at); } removeChild(child) { this.#stack.removeChild(child); } } //# sourceMappingURL=Notification.js.map