@teaui/core
Version:
A high-level terminal UI library for Node
120 lines • 3.79 kB
JavaScript
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