@teaui/core
Version:
A high-level terminal UI library for Node
82 lines • 3 kB
JavaScript
import { Point, Rect } from '../geometry.js';
import { Style } from '../Style.js';
import { Palette } from '../Palette.js';
import { Notification } from './Notification.js';
export class Callout extends Notification {
constructor(props = {}) {
super(props);
this.contentStack.purpose = this.#childPalette();
this.addDirect(this.contentStack);
}
update(props) {
super.update(props);
this.#updateStyles();
this.invalidateRender();
}
#backgroundStyle() {
return new Style({
foreground: this.purpose.textColor,
background: this.purpose.darkenColor,
});
}
#barStyle() {
return new Style({
foreground: this.purpose.highlightColor,
background: this.purpose.darkenColor,
});
}
#topBottomBarStyle() {
return new Style({
foreground: this.purpose.highlightColor,
background: 'default',
});
}
/**
* Creates a derived purpose for children where all background properties match the
* callout's background, so Separator, Text, etc. render with a consistent
* background color.
*/
#childPalette() {
const t = this.purpose;
return new Palette({
text: t.textColor,
contrastText: t.contrastTextColor,
dimText: t.dimTextColor,
dimBackground: t.darkenColor,
controlBackground: t.darkenColor,
textBackground: t.textBackgroundColor,
highlight: t.highlightColor,
darken: t.darkenColor,
tableChecked: t.tableCheckedColor,
tableCheckedHighlight: t.tableCheckedHighlightColor,
});
}
#updateStyles() {
this.contentStack.purpose = this.#childPalette();
}
naturalSize(available) {
const innerAvailable = available.shrink(2, 0);
const innerSize = super.naturalSize(innerAvailable);
return innerSize.grow(2, 2);
}
render(viewport) {
if (viewport.isEmpty) {
return;
}
// Paint dim background with bright foreground
viewport.paint(this.#backgroundStyle());
// Draw left accent bar
for (let y = 0; y < viewport.contentSize.height; y++) {
viewport.write(LEFT_HIGHLIGHT, new Point(0, y), this.#barStyle());
}
const repeatCount = viewport.contentSize.width;
viewport.write(TOP_HIGHLIGHT.repeat(repeatCount), new Point(0, 0), this.#topBottomBarStyle());
viewport.write(BOTTOM_HIGHLIGHT.repeat(repeatCount), new Point(0, viewport.contentSize.height - 1), this.#topBottomBarStyle());
// Render children offset by 2 columns (bar + space)
viewport.clipped(new Rect(new Point(2, 1), viewport.contentSize.shrink(2, 2)), inside => super.render(inside));
}
}
const TOP_HIGHLIGHT = '▄';
const BOTTOM_HIGHLIGHT = '▀';
const LEFT_HIGHLIGHT = '▌';
//# sourceMappingURL=Callout.js.map