UNPKG

@teaui/core

Version:

A high-level terminal UI library for Node

200 lines 7.25 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Progress = void 0; const View_1 = require("../View"); const geometry_1 = require("../geometry"); const Style_1 = require("../Style"); class Progress extends View_1.View { #direction = 'horizontal'; #range = [0, 100]; #value = 0; #showPercent = false; constructor(props) { super(props); this.#update(props); } update(props) { this.#update(props); super.update(props); } #update({ direction, min, max, value, showPercent }) { this.#direction = direction ?? 'horizontal'; this.#range = [min ?? 0, max ?? 100]; this.#showPercent = showPercent ?? false; this.#value = value ?? this.#range[0]; } get value() { return this.#value; } set value(value) { this.#value = value; if (value !== this.#value) { this.#value = value; this.invalidateRender(); } } naturalSize(available) { return new geometry_1.Size(available.width, 1); } render(viewport) { if (viewport.isEmpty) { return; } const pt = geometry_1.Point.zero.mutableCopy(); let percent = ''; if (this.#showPercent) { const percentNum = (0, geometry_1.interpolate)(this.#value, this.#range, [0, 100], true); percent = `${Math.round(percentNum)}%`; } const percentStartPoint = new geometry_1.Point(~~((viewport.contentSize.width - percent.length) / 2), viewport.contentSize.height <= 1 ? 0 : 1); const textStyle = this.theme.text(); const controlStyle = this.theme.ui({ isHover: true }).invert().merge({ background: textStyle.background, }); const altTextStyle = new Style_1.Style({ foreground: textStyle.foreground, background: controlStyle.foreground, }); if (this.#direction === 'horizontal') { this.#renderHorizontal(viewport, percent, percentStartPoint, textStyle, controlStyle, altTextStyle); } else { this.#renderVertical(viewport, percent, percentStartPoint, textStyle, controlStyle, altTextStyle); } } #renderHorizontal(viewport, percent, percentStartPoint, textStyle, controlStyle, altTextStyle) { const progressX = Math.round((0, geometry_1.interpolate)(this.#value, this.#range, [0, viewport.contentSize.width - 1], true)); viewport.visibleRect.forEachPoint(pt => { let char, style = textStyle; if (this.#showPercent && pt.x >= percentStartPoint.x && pt.x - percentStartPoint.x < percent.length && pt.y === percentStartPoint.y) { char = percent[pt.x - percentStartPoint.x]; if (pt.x <= progressX) { style = altTextStyle; } else { style = textStyle; } } else { const min = Math.min(...this.#range); if (pt.x <= progressX && this.#value > min) { if (pt.y === 0 && viewport.contentSize.height > 1) { char = '▄'; } else if (pt.y === viewport.contentSize.height - 1 && viewport.contentSize.height > 1) { char = '▀'; } else { char = '█'; } style = controlStyle; } else if (viewport.contentSize.height === 1) { if (pt.x === 0) { char = '╶'; } else if (pt.x === viewport.contentSize.width - 1) { char = '╴'; } else { char = '─'; } } else if (pt.y === 0) { if (pt.x === 0) { char = '╭'; } else if (pt.x === viewport.contentSize.width - 1) { char = '╮'; } else { char = '─'; } } else if (pt.y === viewport.contentSize.height - 1) { if (pt.x === 0) { char = '╰'; } else if (pt.x === viewport.contentSize.width - 1) { char = '╯'; } else { char = '─'; } } else if (pt.x === 0 || pt.x === viewport.contentSize.width - 1) { char = '│'; } else { char = ' '; } } viewport.write(char, pt, style); }); } #renderVertical(viewport, _percent, _percentStartPoint, textStyle, controlStyle, _altTextStyle) { const progressY = Math.round((0, geometry_1.interpolate)(this.#value, this.#range, [viewport.contentSize.height - 1, 0], true)); viewport.visibleRect.forEachPoint(pt => { let char, style = textStyle; if (pt.y >= progressY) { if (pt.x === 0 && viewport.contentSize.width > 1) { char = '▐'; } else if (pt.x === viewport.contentSize.width - 1 && viewport.contentSize.width > 1) { char = '▌'; } else { char = '█'; } style = controlStyle; } else if (viewport.contentSize.width === 1) { if (pt.y === 0) { char = '╷'; } else if (pt.y === viewport.contentSize.height - 1) { char = '╵'; } else { char = '│'; } } else if (pt.x === 0) { if (pt.y === 0) { char = '╭'; } else if (pt.y === viewport.contentSize.height - 1) { char = '╰'; } else { char = '│'; } } else if (pt.x === viewport.contentSize.width - 1) { if (pt.y === 0) { char = '╮'; } else if (pt.y === viewport.contentSize.height - 1) { char = '╯'; } else { char = '│'; } } else if (pt.y === 0 || pt.y === viewport.contentSize.height - 1) { char = '─'; } else { char = ' '; } viewport.write(char, pt, style); }); } } exports.Progress = Progress; //# sourceMappingURL=Progress.js.map