blessed-components 0.0.1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -43
- package/ROADMAP.md +695 -302
- package/dist/index.cjs +57 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.js +51 -0
- package/dist/index.js.map +1 -1
- package/dist/progress-bar/blessed.cjs +60 -0
- package/dist/progress-bar/blessed.cjs.map +1 -0
- package/dist/progress-bar/blessed.d.cts +129 -0
- package/dist/progress-bar/blessed.d.ts +129 -0
- package/dist/progress-bar/blessed.js +54 -0
- package/dist/progress-bar/blessed.js.map +1 -0
- package/dist/progress-bar/index.cjs +33 -0
- package/dist/progress-bar/index.cjs.map +1 -0
- package/dist/progress-bar/index.d.cts +181 -0
- package/dist/progress-bar/index.d.ts +181 -0
- package/dist/progress-bar/index.js +31 -0
- package/dist/progress-bar/index.js.map +1 -0
- package/package.json +28 -12
- package/src/components/progress-bar/README.md +193 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/components/progress-bar/index.ts"],"names":[],"mappings":";;;AA6LO,SAAS,iBAAA,CAAkB;AAAA,EAChC,UAAA,GAAa,EAAE,KAAA,EAAO,QAAA,EAAK,QAAQ,QAAA,EAAI;AAAA,EACvC,cAAc,CAAC,EAAE,UAAA,EAAW,KAAM,GAAG,UAAU,CAAA,CAAA,CAAA;AAAA,EAC/C,KAAA;AAAA,EACA,GAAA,GAAM,GAAA;AAAA,EACN,GAAA,GAAM,CAAA;AAAA,EACN,KAAA;AAAA,EACA;AACF,CAAA,EAAqC;AACnC,EAAA,IAAI,CAAC,MAAA,CAAO,SAAA,CAAU,KAAK,CAAA,IAAK,QAAQ,CAAA,EAAG;AACzC,IAAA,MAAM,IAAI,WAAW,+CAA+C,CAAA;AAAA,EACtE;AAEA,EAAA,IAAI,CAAC,MAAA,CAAO,QAAA,CAAS,GAAG,CAAA,IAAK,CAAC,MAAA,CAAO,QAAA,CAAS,GAAG,CAAA,IAAK,GAAA,IAAO,GAAA,EAAK;AAChE,IAAA,MAAM,IAAI,WAAW,2CAA2C,CAAA;AAAA,EAClE;AAEA,EAAA,IAAI,CAAC,MAAA,CAAO,QAAA,CAAS,KAAK,CAAA,EAAG;AAC3B,IAAA,MAAM,IAAI,WAAW,mCAAmC,CAAA;AAAA,EAC1D;AAEA,EAAA,MAAM,YAAA,GAAe,KAAK,GAAA,CAAI,GAAA,EAAK,KAAK,GAAA,CAAI,GAAA,EAAK,KAAK,CAAC,CAAA;AACvD,EAAA,MAAM,aAAa,IAAA,CAAK,KAAA,CAAA,CAAQ,eAAe,GAAA,KAAQ,GAAA,GAAM,OAAQ,GAAG,CAAA;AACxE,EAAA,MAAM,WAAA,GAAc,IAAA,CAAK,KAAA,CAAO,UAAA,GAAa,MAAO,KAAK,CAAA;AACzD,EAAA,MAAM,KAAA,GACJ,UAAA,CAAW,MAAA,CAAO,MAAA,CAAO,WAAW,IAAI,UAAA,CAAW,KAAA,CAAM,MAAA,CAAO,KAAA,GAAQ,WAAW,CAAA;AACrF,EAAA,MAAM,MAAA,GAAS,KAAA,KAAU,MAAA,GAAY,EAAA,GAAK,GAAG,KAAK,CAAA,CAAA,CAAA;AAClD,EAAA,MAAM,YAAY,WAAA,CAAY,EAAE,UAAA,EAAY,KAAA,EAAO,cAAc,CAAA;AAEjE,EAAA,OAAO,CAAA,EAAG,MAAM,CAAA,EAAG,KAAK,IAAI,SAAS,CAAA,CAAA;AACvC","file":"index.cjs","sourcesContent":["/**\n * Options accepted by {@link renderProgressBar}.\n *\n * The renderer maps `value` from the inclusive numeric range defined by\n * `min` and `max` into a fixed-width terminal track. Values outside the range\n * are clamped before rendering.\n *\n * @example Basic percentage bar\n *\n * ```ts\n * renderProgressBar({\n * value: 50,\n * width: 10,\n * });\n * // \"█████░░░░░ 50%\"\n * ```\n *\n * @example Custom range and label\n *\n * ```ts\n * renderProgressBar({\n * label: 'Workers',\n * min: 0,\n * max: 8,\n * value: 6,\n * width: 8,\n * });\n * // \"Workers ██████░░ 75%\"\n * ```\n */\nexport interface RenderProgressBarOptions {\n /**\n * Characters used to render filled and empty cells.\n *\n * Each character should occupy one terminal cell. Multi-cell or combining\n * characters can make the visible track wider than `width`.\n *\n * @defaultValue `{ filled: '█', empty: '░' }`\n */\n characters?: ProgressBarCharacters;\n\n /**\n * Formats the value text appended after the track.\n *\n * The callback receives the clamped numeric value and its rounded\n * percentage. Returning an empty string leaves the trailing separator in\n * place; callers that need a track-only representation should account for\n * that when composing output.\n *\n * @defaultValue `({ percentage }) => `${percentage}%``\n */\n formatValue?: (context: ProgressBarValueContext) => string;\n\n /**\n * Optional text rendered before the track.\n *\n * Dynamic values must be escaped by the caller if the returned string will\n * later be inserted into a Blessed element with tags enabled. The bundled\n * Blessed adapter disables tags.\n */\n label?: string;\n\n /**\n * Upper bound of the numeric range.\n *\n * Must be finite and greater than `min`.\n *\n * @defaultValue `100`\n */\n max?: number;\n\n /**\n * Lower bound of the numeric range.\n *\n * Must be finite and lower than `max`.\n *\n * @defaultValue `0`\n */\n min?: number;\n\n /**\n * Current numeric value.\n *\n * The value must be finite. Values below `min` or above `max` are clamped\n * before the percentage and formatted value are calculated.\n */\n value: number;\n\n /**\n * Number of characters reserved for the progress track.\n *\n * This excludes the optional label, spaces, and formatted value. It must be\n * a positive integer.\n */\n width: number;\n}\n\n/**\n * Character pair used to draw a progress track.\n *\n * Use ASCII characters when the target terminal cannot display Unicode block\n * glyphs reliably.\n *\n * @example\n *\n * ```ts\n * const asciiCharacters: ProgressBarCharacters = {\n * filled: '#',\n * empty: '-',\n * };\n * ```\n */\nexport interface ProgressBarCharacters {\n /** Character repeated for unfilled track cells. */\n empty: string;\n\n /** Character repeated for filled track cells. */\n filled: string;\n}\n\n/**\n * Normalized value information passed to a progress value formatter.\n */\nexport interface ProgressBarValueContext {\n /**\n * Rounded progress in the inclusive range from `0` to `100`.\n */\n percentage: number;\n\n /**\n * Numeric value after it has been clamped to the configured range.\n */\n value: number;\n}\n\n/**\n * Renders a deterministic, single-line progress bar.\n *\n * This function is framework-independent and does not import Blessed. Import\n * it from `blessed-components/progress-bar` when only string rendering is\n * needed; that subpath keeps the Blessed adapter out of the module graph.\n *\n * The result has this structure:\n *\n * ```text\n * [label + space][fixed-width track][space][formatted value]\n * ```\n *\n * @param options - Numeric range, track width, characters, and text formatting.\n * @returns A plain terminal string. No ANSI sequences or Blessed tags are added.\n *\n * @throws `RangeError`\n * Thrown when `width` is not a positive integer.\n *\n * @throws `RangeError`\n * Thrown when `min` or `max` is not finite, or when `max` is not greater than\n * `min`.\n *\n * @throws `RangeError`\n * Thrown when `value` is not finite.\n *\n * @example Unicode output\n *\n * ```ts\n * import { renderProgressBar } from 'blessed-components/progress-bar';\n *\n * const output = renderProgressBar({\n * label: 'Quality',\n * value: 78,\n * width: 16,\n * });\n *\n * // \"Quality ████████████░░░░ 78%\"\n * ```\n *\n * @example ASCII output with a custom value\n *\n * ```ts\n * const output = renderProgressBar({\n * characters: { filled: '#', empty: '-' },\n * formatValue: ({ value }) => `${value} files`,\n * label: 'Uploaded',\n * value: 25,\n * width: 8,\n * });\n *\n * // \"Uploaded ##------ 25 files\"\n * ```\n */\nexport function renderProgressBar({\n characters = { empty: '░', filled: '█' },\n formatValue = ({ percentage }) => `${percentage}%`,\n label,\n max = 100,\n min = 0,\n value,\n width,\n}: RenderProgressBarOptions): string {\n if (!Number.isInteger(width) || width < 1) {\n throw new RangeError('ProgressBar width must be a positive integer.');\n }\n\n if (!Number.isFinite(min) || !Number.isFinite(max) || max <= min) {\n throw new RangeError('ProgressBar max must be greater than min.');\n }\n\n if (!Number.isFinite(value)) {\n throw new RangeError('ProgressBar value must be finite.');\n }\n\n const clampedValue = Math.min(max, Math.max(min, value));\n const percentage = Math.round(((clampedValue - min) / (max - min)) * 100);\n const filledWidth = Math.round((percentage / 100) * width);\n const track =\n characters.filled.repeat(filledWidth) + characters.empty.repeat(width - filledWidth);\n const prefix = label === undefined ? '' : `${label} `;\n const valueText = formatValue({ percentage, value: clampedValue });\n\n return `${prefix}${track} ${valueText}`;\n}\n"]}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Options accepted by {@link renderProgressBar}.
|
|
3
|
+
*
|
|
4
|
+
* The renderer maps `value` from the inclusive numeric range defined by
|
|
5
|
+
* `min` and `max` into a fixed-width terminal track. Values outside the range
|
|
6
|
+
* are clamped before rendering.
|
|
7
|
+
*
|
|
8
|
+
* @example Basic percentage bar
|
|
9
|
+
*
|
|
10
|
+
* ```ts
|
|
11
|
+
* renderProgressBar({
|
|
12
|
+
* value: 50,
|
|
13
|
+
* width: 10,
|
|
14
|
+
* });
|
|
15
|
+
* // "█████░░░░░ 50%"
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* @example Custom range and label
|
|
19
|
+
*
|
|
20
|
+
* ```ts
|
|
21
|
+
* renderProgressBar({
|
|
22
|
+
* label: 'Workers',
|
|
23
|
+
* min: 0,
|
|
24
|
+
* max: 8,
|
|
25
|
+
* value: 6,
|
|
26
|
+
* width: 8,
|
|
27
|
+
* });
|
|
28
|
+
* // "Workers ██████░░ 75%"
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
interface RenderProgressBarOptions {
|
|
32
|
+
/**
|
|
33
|
+
* Characters used to render filled and empty cells.
|
|
34
|
+
*
|
|
35
|
+
* Each character should occupy one terminal cell. Multi-cell or combining
|
|
36
|
+
* characters can make the visible track wider than `width`.
|
|
37
|
+
*
|
|
38
|
+
* @defaultValue `{ filled: '█', empty: '░' }`
|
|
39
|
+
*/
|
|
40
|
+
characters?: ProgressBarCharacters;
|
|
41
|
+
/**
|
|
42
|
+
* Formats the value text appended after the track.
|
|
43
|
+
*
|
|
44
|
+
* The callback receives the clamped numeric value and its rounded
|
|
45
|
+
* percentage. Returning an empty string leaves the trailing separator in
|
|
46
|
+
* place; callers that need a track-only representation should account for
|
|
47
|
+
* that when composing output.
|
|
48
|
+
*
|
|
49
|
+
* @defaultValue `({ percentage }) => `${percentage}%``
|
|
50
|
+
*/
|
|
51
|
+
formatValue?: (context: ProgressBarValueContext) => string;
|
|
52
|
+
/**
|
|
53
|
+
* Optional text rendered before the track.
|
|
54
|
+
*
|
|
55
|
+
* Dynamic values must be escaped by the caller if the returned string will
|
|
56
|
+
* later be inserted into a Blessed element with tags enabled. The bundled
|
|
57
|
+
* Blessed adapter disables tags.
|
|
58
|
+
*/
|
|
59
|
+
label?: string;
|
|
60
|
+
/**
|
|
61
|
+
* Upper bound of the numeric range.
|
|
62
|
+
*
|
|
63
|
+
* Must be finite and greater than `min`.
|
|
64
|
+
*
|
|
65
|
+
* @defaultValue `100`
|
|
66
|
+
*/
|
|
67
|
+
max?: number;
|
|
68
|
+
/**
|
|
69
|
+
* Lower bound of the numeric range.
|
|
70
|
+
*
|
|
71
|
+
* Must be finite and lower than `max`.
|
|
72
|
+
*
|
|
73
|
+
* @defaultValue `0`
|
|
74
|
+
*/
|
|
75
|
+
min?: number;
|
|
76
|
+
/**
|
|
77
|
+
* Current numeric value.
|
|
78
|
+
*
|
|
79
|
+
* The value must be finite. Values below `min` or above `max` are clamped
|
|
80
|
+
* before the percentage and formatted value are calculated.
|
|
81
|
+
*/
|
|
82
|
+
value: number;
|
|
83
|
+
/**
|
|
84
|
+
* Number of characters reserved for the progress track.
|
|
85
|
+
*
|
|
86
|
+
* This excludes the optional label, spaces, and formatted value. It must be
|
|
87
|
+
* a positive integer.
|
|
88
|
+
*/
|
|
89
|
+
width: number;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Character pair used to draw a progress track.
|
|
93
|
+
*
|
|
94
|
+
* Use ASCII characters when the target terminal cannot display Unicode block
|
|
95
|
+
* glyphs reliably.
|
|
96
|
+
*
|
|
97
|
+
* @example
|
|
98
|
+
*
|
|
99
|
+
* ```ts
|
|
100
|
+
* const asciiCharacters: ProgressBarCharacters = {
|
|
101
|
+
* filled: '#',
|
|
102
|
+
* empty: '-',
|
|
103
|
+
* };
|
|
104
|
+
* ```
|
|
105
|
+
*/
|
|
106
|
+
interface ProgressBarCharacters {
|
|
107
|
+
/** Character repeated for unfilled track cells. */
|
|
108
|
+
empty: string;
|
|
109
|
+
/** Character repeated for filled track cells. */
|
|
110
|
+
filled: string;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Normalized value information passed to a progress value formatter.
|
|
114
|
+
*/
|
|
115
|
+
interface ProgressBarValueContext {
|
|
116
|
+
/**
|
|
117
|
+
* Rounded progress in the inclusive range from `0` to `100`.
|
|
118
|
+
*/
|
|
119
|
+
percentage: number;
|
|
120
|
+
/**
|
|
121
|
+
* Numeric value after it has been clamped to the configured range.
|
|
122
|
+
*/
|
|
123
|
+
value: number;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Renders a deterministic, single-line progress bar.
|
|
127
|
+
*
|
|
128
|
+
* This function is framework-independent and does not import Blessed. Import
|
|
129
|
+
* it from `blessed-components/progress-bar` when only string rendering is
|
|
130
|
+
* needed; that subpath keeps the Blessed adapter out of the module graph.
|
|
131
|
+
*
|
|
132
|
+
* The result has this structure:
|
|
133
|
+
*
|
|
134
|
+
* ```text
|
|
135
|
+
* [label + space][fixed-width track][space][formatted value]
|
|
136
|
+
* ```
|
|
137
|
+
*
|
|
138
|
+
* @param options - Numeric range, track width, characters, and text formatting.
|
|
139
|
+
* @returns A plain terminal string. No ANSI sequences or Blessed tags are added.
|
|
140
|
+
*
|
|
141
|
+
* @throws `RangeError`
|
|
142
|
+
* Thrown when `width` is not a positive integer.
|
|
143
|
+
*
|
|
144
|
+
* @throws `RangeError`
|
|
145
|
+
* Thrown when `min` or `max` is not finite, or when `max` is not greater than
|
|
146
|
+
* `min`.
|
|
147
|
+
*
|
|
148
|
+
* @throws `RangeError`
|
|
149
|
+
* Thrown when `value` is not finite.
|
|
150
|
+
*
|
|
151
|
+
* @example Unicode output
|
|
152
|
+
*
|
|
153
|
+
* ```ts
|
|
154
|
+
* import { renderProgressBar } from 'blessed-components/progress-bar';
|
|
155
|
+
*
|
|
156
|
+
* const output = renderProgressBar({
|
|
157
|
+
* label: 'Quality',
|
|
158
|
+
* value: 78,
|
|
159
|
+
* width: 16,
|
|
160
|
+
* });
|
|
161
|
+
*
|
|
162
|
+
* // "Quality ████████████░░░░ 78%"
|
|
163
|
+
* ```
|
|
164
|
+
*
|
|
165
|
+
* @example ASCII output with a custom value
|
|
166
|
+
*
|
|
167
|
+
* ```ts
|
|
168
|
+
* const output = renderProgressBar({
|
|
169
|
+
* characters: { filled: '#', empty: '-' },
|
|
170
|
+
* formatValue: ({ value }) => `${value} files`,
|
|
171
|
+
* label: 'Uploaded',
|
|
172
|
+
* value: 25,
|
|
173
|
+
* width: 8,
|
|
174
|
+
* });
|
|
175
|
+
*
|
|
176
|
+
* // "Uploaded ##------ 25 files"
|
|
177
|
+
* ```
|
|
178
|
+
*/
|
|
179
|
+
declare function renderProgressBar({ characters, formatValue, label, max, min, value, width, }: RenderProgressBarOptions): string;
|
|
180
|
+
|
|
181
|
+
export { type ProgressBarCharacters, type ProgressBarValueContext, type RenderProgressBarOptions, renderProgressBar };
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Options accepted by {@link renderProgressBar}.
|
|
3
|
+
*
|
|
4
|
+
* The renderer maps `value` from the inclusive numeric range defined by
|
|
5
|
+
* `min` and `max` into a fixed-width terminal track. Values outside the range
|
|
6
|
+
* are clamped before rendering.
|
|
7
|
+
*
|
|
8
|
+
* @example Basic percentage bar
|
|
9
|
+
*
|
|
10
|
+
* ```ts
|
|
11
|
+
* renderProgressBar({
|
|
12
|
+
* value: 50,
|
|
13
|
+
* width: 10,
|
|
14
|
+
* });
|
|
15
|
+
* // "█████░░░░░ 50%"
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* @example Custom range and label
|
|
19
|
+
*
|
|
20
|
+
* ```ts
|
|
21
|
+
* renderProgressBar({
|
|
22
|
+
* label: 'Workers',
|
|
23
|
+
* min: 0,
|
|
24
|
+
* max: 8,
|
|
25
|
+
* value: 6,
|
|
26
|
+
* width: 8,
|
|
27
|
+
* });
|
|
28
|
+
* // "Workers ██████░░ 75%"
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
interface RenderProgressBarOptions {
|
|
32
|
+
/**
|
|
33
|
+
* Characters used to render filled and empty cells.
|
|
34
|
+
*
|
|
35
|
+
* Each character should occupy one terminal cell. Multi-cell or combining
|
|
36
|
+
* characters can make the visible track wider than `width`.
|
|
37
|
+
*
|
|
38
|
+
* @defaultValue `{ filled: '█', empty: '░' }`
|
|
39
|
+
*/
|
|
40
|
+
characters?: ProgressBarCharacters;
|
|
41
|
+
/**
|
|
42
|
+
* Formats the value text appended after the track.
|
|
43
|
+
*
|
|
44
|
+
* The callback receives the clamped numeric value and its rounded
|
|
45
|
+
* percentage. Returning an empty string leaves the trailing separator in
|
|
46
|
+
* place; callers that need a track-only representation should account for
|
|
47
|
+
* that when composing output.
|
|
48
|
+
*
|
|
49
|
+
* @defaultValue `({ percentage }) => `${percentage}%``
|
|
50
|
+
*/
|
|
51
|
+
formatValue?: (context: ProgressBarValueContext) => string;
|
|
52
|
+
/**
|
|
53
|
+
* Optional text rendered before the track.
|
|
54
|
+
*
|
|
55
|
+
* Dynamic values must be escaped by the caller if the returned string will
|
|
56
|
+
* later be inserted into a Blessed element with tags enabled. The bundled
|
|
57
|
+
* Blessed adapter disables tags.
|
|
58
|
+
*/
|
|
59
|
+
label?: string;
|
|
60
|
+
/**
|
|
61
|
+
* Upper bound of the numeric range.
|
|
62
|
+
*
|
|
63
|
+
* Must be finite and greater than `min`.
|
|
64
|
+
*
|
|
65
|
+
* @defaultValue `100`
|
|
66
|
+
*/
|
|
67
|
+
max?: number;
|
|
68
|
+
/**
|
|
69
|
+
* Lower bound of the numeric range.
|
|
70
|
+
*
|
|
71
|
+
* Must be finite and lower than `max`.
|
|
72
|
+
*
|
|
73
|
+
* @defaultValue `0`
|
|
74
|
+
*/
|
|
75
|
+
min?: number;
|
|
76
|
+
/**
|
|
77
|
+
* Current numeric value.
|
|
78
|
+
*
|
|
79
|
+
* The value must be finite. Values below `min` or above `max` are clamped
|
|
80
|
+
* before the percentage and formatted value are calculated.
|
|
81
|
+
*/
|
|
82
|
+
value: number;
|
|
83
|
+
/**
|
|
84
|
+
* Number of characters reserved for the progress track.
|
|
85
|
+
*
|
|
86
|
+
* This excludes the optional label, spaces, and formatted value. It must be
|
|
87
|
+
* a positive integer.
|
|
88
|
+
*/
|
|
89
|
+
width: number;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Character pair used to draw a progress track.
|
|
93
|
+
*
|
|
94
|
+
* Use ASCII characters when the target terminal cannot display Unicode block
|
|
95
|
+
* glyphs reliably.
|
|
96
|
+
*
|
|
97
|
+
* @example
|
|
98
|
+
*
|
|
99
|
+
* ```ts
|
|
100
|
+
* const asciiCharacters: ProgressBarCharacters = {
|
|
101
|
+
* filled: '#',
|
|
102
|
+
* empty: '-',
|
|
103
|
+
* };
|
|
104
|
+
* ```
|
|
105
|
+
*/
|
|
106
|
+
interface ProgressBarCharacters {
|
|
107
|
+
/** Character repeated for unfilled track cells. */
|
|
108
|
+
empty: string;
|
|
109
|
+
/** Character repeated for filled track cells. */
|
|
110
|
+
filled: string;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Normalized value information passed to a progress value formatter.
|
|
114
|
+
*/
|
|
115
|
+
interface ProgressBarValueContext {
|
|
116
|
+
/**
|
|
117
|
+
* Rounded progress in the inclusive range from `0` to `100`.
|
|
118
|
+
*/
|
|
119
|
+
percentage: number;
|
|
120
|
+
/**
|
|
121
|
+
* Numeric value after it has been clamped to the configured range.
|
|
122
|
+
*/
|
|
123
|
+
value: number;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Renders a deterministic, single-line progress bar.
|
|
127
|
+
*
|
|
128
|
+
* This function is framework-independent and does not import Blessed. Import
|
|
129
|
+
* it from `blessed-components/progress-bar` when only string rendering is
|
|
130
|
+
* needed; that subpath keeps the Blessed adapter out of the module graph.
|
|
131
|
+
*
|
|
132
|
+
* The result has this structure:
|
|
133
|
+
*
|
|
134
|
+
* ```text
|
|
135
|
+
* [label + space][fixed-width track][space][formatted value]
|
|
136
|
+
* ```
|
|
137
|
+
*
|
|
138
|
+
* @param options - Numeric range, track width, characters, and text formatting.
|
|
139
|
+
* @returns A plain terminal string. No ANSI sequences or Blessed tags are added.
|
|
140
|
+
*
|
|
141
|
+
* @throws `RangeError`
|
|
142
|
+
* Thrown when `width` is not a positive integer.
|
|
143
|
+
*
|
|
144
|
+
* @throws `RangeError`
|
|
145
|
+
* Thrown when `min` or `max` is not finite, or when `max` is not greater than
|
|
146
|
+
* `min`.
|
|
147
|
+
*
|
|
148
|
+
* @throws `RangeError`
|
|
149
|
+
* Thrown when `value` is not finite.
|
|
150
|
+
*
|
|
151
|
+
* @example Unicode output
|
|
152
|
+
*
|
|
153
|
+
* ```ts
|
|
154
|
+
* import { renderProgressBar } from 'blessed-components/progress-bar';
|
|
155
|
+
*
|
|
156
|
+
* const output = renderProgressBar({
|
|
157
|
+
* label: 'Quality',
|
|
158
|
+
* value: 78,
|
|
159
|
+
* width: 16,
|
|
160
|
+
* });
|
|
161
|
+
*
|
|
162
|
+
* // "Quality ████████████░░░░ 78%"
|
|
163
|
+
* ```
|
|
164
|
+
*
|
|
165
|
+
* @example ASCII output with a custom value
|
|
166
|
+
*
|
|
167
|
+
* ```ts
|
|
168
|
+
* const output = renderProgressBar({
|
|
169
|
+
* characters: { filled: '#', empty: '-' },
|
|
170
|
+
* formatValue: ({ value }) => `${value} files`,
|
|
171
|
+
* label: 'Uploaded',
|
|
172
|
+
* value: 25,
|
|
173
|
+
* width: 8,
|
|
174
|
+
* });
|
|
175
|
+
*
|
|
176
|
+
* // "Uploaded ##------ 25 files"
|
|
177
|
+
* ```
|
|
178
|
+
*/
|
|
179
|
+
declare function renderProgressBar({ characters, formatValue, label, max, min, value, width, }: RenderProgressBarOptions): string;
|
|
180
|
+
|
|
181
|
+
export { type ProgressBarCharacters, type ProgressBarValueContext, type RenderProgressBarOptions, renderProgressBar };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// src/components/progress-bar/index.ts
|
|
2
|
+
function renderProgressBar({
|
|
3
|
+
characters = { empty: "\u2591", filled: "\u2588" },
|
|
4
|
+
formatValue = ({ percentage }) => `${percentage}%`,
|
|
5
|
+
label,
|
|
6
|
+
max = 100,
|
|
7
|
+
min = 0,
|
|
8
|
+
value,
|
|
9
|
+
width
|
|
10
|
+
}) {
|
|
11
|
+
if (!Number.isInteger(width) || width < 1) {
|
|
12
|
+
throw new RangeError("ProgressBar width must be a positive integer.");
|
|
13
|
+
}
|
|
14
|
+
if (!Number.isFinite(min) || !Number.isFinite(max) || max <= min) {
|
|
15
|
+
throw new RangeError("ProgressBar max must be greater than min.");
|
|
16
|
+
}
|
|
17
|
+
if (!Number.isFinite(value)) {
|
|
18
|
+
throw new RangeError("ProgressBar value must be finite.");
|
|
19
|
+
}
|
|
20
|
+
const clampedValue = Math.min(max, Math.max(min, value));
|
|
21
|
+
const percentage = Math.round((clampedValue - min) / (max - min) * 100);
|
|
22
|
+
const filledWidth = Math.round(percentage / 100 * width);
|
|
23
|
+
const track = characters.filled.repeat(filledWidth) + characters.empty.repeat(width - filledWidth);
|
|
24
|
+
const prefix = label === void 0 ? "" : `${label} `;
|
|
25
|
+
const valueText = formatValue({ percentage, value: clampedValue });
|
|
26
|
+
return `${prefix}${track} ${valueText}`;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export { renderProgressBar };
|
|
30
|
+
//# sourceMappingURL=index.js.map
|
|
31
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/components/progress-bar/index.ts"],"names":[],"mappings":";AA6LO,SAAS,iBAAA,CAAkB;AAAA,EAChC,UAAA,GAAa,EAAE,KAAA,EAAO,QAAA,EAAK,QAAQ,QAAA,EAAI;AAAA,EACvC,cAAc,CAAC,EAAE,UAAA,EAAW,KAAM,GAAG,UAAU,CAAA,CAAA,CAAA;AAAA,EAC/C,KAAA;AAAA,EACA,GAAA,GAAM,GAAA;AAAA,EACN,GAAA,GAAM,CAAA;AAAA,EACN,KAAA;AAAA,EACA;AACF,CAAA,EAAqC;AACnC,EAAA,IAAI,CAAC,MAAA,CAAO,SAAA,CAAU,KAAK,CAAA,IAAK,QAAQ,CAAA,EAAG;AACzC,IAAA,MAAM,IAAI,WAAW,+CAA+C,CAAA;AAAA,EACtE;AAEA,EAAA,IAAI,CAAC,MAAA,CAAO,QAAA,CAAS,GAAG,CAAA,IAAK,CAAC,MAAA,CAAO,QAAA,CAAS,GAAG,CAAA,IAAK,GAAA,IAAO,GAAA,EAAK;AAChE,IAAA,MAAM,IAAI,WAAW,2CAA2C,CAAA;AAAA,EAClE;AAEA,EAAA,IAAI,CAAC,MAAA,CAAO,QAAA,CAAS,KAAK,CAAA,EAAG;AAC3B,IAAA,MAAM,IAAI,WAAW,mCAAmC,CAAA;AAAA,EAC1D;AAEA,EAAA,MAAM,YAAA,GAAe,KAAK,GAAA,CAAI,GAAA,EAAK,KAAK,GAAA,CAAI,GAAA,EAAK,KAAK,CAAC,CAAA;AACvD,EAAA,MAAM,aAAa,IAAA,CAAK,KAAA,CAAA,CAAQ,eAAe,GAAA,KAAQ,GAAA,GAAM,OAAQ,GAAG,CAAA;AACxE,EAAA,MAAM,WAAA,GAAc,IAAA,CAAK,KAAA,CAAO,UAAA,GAAa,MAAO,KAAK,CAAA;AACzD,EAAA,MAAM,KAAA,GACJ,UAAA,CAAW,MAAA,CAAO,MAAA,CAAO,WAAW,IAAI,UAAA,CAAW,KAAA,CAAM,MAAA,CAAO,KAAA,GAAQ,WAAW,CAAA;AACrF,EAAA,MAAM,MAAA,GAAS,KAAA,KAAU,MAAA,GAAY,EAAA,GAAK,GAAG,KAAK,CAAA,CAAA,CAAA;AAClD,EAAA,MAAM,YAAY,WAAA,CAAY,EAAE,UAAA,EAAY,KAAA,EAAO,cAAc,CAAA;AAEjE,EAAA,OAAO,CAAA,EAAG,MAAM,CAAA,EAAG,KAAK,IAAI,SAAS,CAAA,CAAA;AACvC","file":"index.js","sourcesContent":["/**\n * Options accepted by {@link renderProgressBar}.\n *\n * The renderer maps `value` from the inclusive numeric range defined by\n * `min` and `max` into a fixed-width terminal track. Values outside the range\n * are clamped before rendering.\n *\n * @example Basic percentage bar\n *\n * ```ts\n * renderProgressBar({\n * value: 50,\n * width: 10,\n * });\n * // \"█████░░░░░ 50%\"\n * ```\n *\n * @example Custom range and label\n *\n * ```ts\n * renderProgressBar({\n * label: 'Workers',\n * min: 0,\n * max: 8,\n * value: 6,\n * width: 8,\n * });\n * // \"Workers ██████░░ 75%\"\n * ```\n */\nexport interface RenderProgressBarOptions {\n /**\n * Characters used to render filled and empty cells.\n *\n * Each character should occupy one terminal cell. Multi-cell or combining\n * characters can make the visible track wider than `width`.\n *\n * @defaultValue `{ filled: '█', empty: '░' }`\n */\n characters?: ProgressBarCharacters;\n\n /**\n * Formats the value text appended after the track.\n *\n * The callback receives the clamped numeric value and its rounded\n * percentage. Returning an empty string leaves the trailing separator in\n * place; callers that need a track-only representation should account for\n * that when composing output.\n *\n * @defaultValue `({ percentage }) => `${percentage}%``\n */\n formatValue?: (context: ProgressBarValueContext) => string;\n\n /**\n * Optional text rendered before the track.\n *\n * Dynamic values must be escaped by the caller if the returned string will\n * later be inserted into a Blessed element with tags enabled. The bundled\n * Blessed adapter disables tags.\n */\n label?: string;\n\n /**\n * Upper bound of the numeric range.\n *\n * Must be finite and greater than `min`.\n *\n * @defaultValue `100`\n */\n max?: number;\n\n /**\n * Lower bound of the numeric range.\n *\n * Must be finite and lower than `max`.\n *\n * @defaultValue `0`\n */\n min?: number;\n\n /**\n * Current numeric value.\n *\n * The value must be finite. Values below `min` or above `max` are clamped\n * before the percentage and formatted value are calculated.\n */\n value: number;\n\n /**\n * Number of characters reserved for the progress track.\n *\n * This excludes the optional label, spaces, and formatted value. It must be\n * a positive integer.\n */\n width: number;\n}\n\n/**\n * Character pair used to draw a progress track.\n *\n * Use ASCII characters when the target terminal cannot display Unicode block\n * glyphs reliably.\n *\n * @example\n *\n * ```ts\n * const asciiCharacters: ProgressBarCharacters = {\n * filled: '#',\n * empty: '-',\n * };\n * ```\n */\nexport interface ProgressBarCharacters {\n /** Character repeated for unfilled track cells. */\n empty: string;\n\n /** Character repeated for filled track cells. */\n filled: string;\n}\n\n/**\n * Normalized value information passed to a progress value formatter.\n */\nexport interface ProgressBarValueContext {\n /**\n * Rounded progress in the inclusive range from `0` to `100`.\n */\n percentage: number;\n\n /**\n * Numeric value after it has been clamped to the configured range.\n */\n value: number;\n}\n\n/**\n * Renders a deterministic, single-line progress bar.\n *\n * This function is framework-independent and does not import Blessed. Import\n * it from `blessed-components/progress-bar` when only string rendering is\n * needed; that subpath keeps the Blessed adapter out of the module graph.\n *\n * The result has this structure:\n *\n * ```text\n * [label + space][fixed-width track][space][formatted value]\n * ```\n *\n * @param options - Numeric range, track width, characters, and text formatting.\n * @returns A plain terminal string. No ANSI sequences or Blessed tags are added.\n *\n * @throws `RangeError`\n * Thrown when `width` is not a positive integer.\n *\n * @throws `RangeError`\n * Thrown when `min` or `max` is not finite, or when `max` is not greater than\n * `min`.\n *\n * @throws `RangeError`\n * Thrown when `value` is not finite.\n *\n * @example Unicode output\n *\n * ```ts\n * import { renderProgressBar } from 'blessed-components/progress-bar';\n *\n * const output = renderProgressBar({\n * label: 'Quality',\n * value: 78,\n * width: 16,\n * });\n *\n * // \"Quality ████████████░░░░ 78%\"\n * ```\n *\n * @example ASCII output with a custom value\n *\n * ```ts\n * const output = renderProgressBar({\n * characters: { filled: '#', empty: '-' },\n * formatValue: ({ value }) => `${value} files`,\n * label: 'Uploaded',\n * value: 25,\n * width: 8,\n * });\n *\n * // \"Uploaded ##------ 25 files\"\n * ```\n */\nexport function renderProgressBar({\n characters = { empty: '░', filled: '█' },\n formatValue = ({ percentage }) => `${percentage}%`,\n label,\n max = 100,\n min = 0,\n value,\n width,\n}: RenderProgressBarOptions): string {\n if (!Number.isInteger(width) || width < 1) {\n throw new RangeError('ProgressBar width must be a positive integer.');\n }\n\n if (!Number.isFinite(min) || !Number.isFinite(max) || max <= min) {\n throw new RangeError('ProgressBar max must be greater than min.');\n }\n\n if (!Number.isFinite(value)) {\n throw new RangeError('ProgressBar value must be finite.');\n }\n\n const clampedValue = Math.min(max, Math.max(min, value));\n const percentage = Math.round(((clampedValue - min) / (max - min)) * 100);\n const filledWidth = Math.round((percentage / 100) * width);\n const track =\n characters.filled.repeat(filledWidth) + characters.empty.repeat(width - filledWidth);\n const prefix = label === undefined ? '' : `${label} `;\n const valueText = formatValue({ percentage, value: clampedValue });\n\n return `${prefix}${track} ${valueText}`;\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "blessed-components",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "Composable, typed terminal UI components for Blessed.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"blessed",
|
|
@@ -28,13 +28,24 @@
|
|
|
28
28
|
"types": "./dist/index.d.ts",
|
|
29
29
|
"import": "./dist/index.js",
|
|
30
30
|
"require": "./dist/index.cjs"
|
|
31
|
+
},
|
|
32
|
+
"./progress-bar": {
|
|
33
|
+
"types": "./dist/progress-bar/index.d.ts",
|
|
34
|
+
"import": "./dist/progress-bar/index.js",
|
|
35
|
+
"require": "./dist/progress-bar/index.cjs"
|
|
36
|
+
},
|
|
37
|
+
"./progress-bar/blessed": {
|
|
38
|
+
"types": "./dist/progress-bar/blessed.d.ts",
|
|
39
|
+
"import": "./dist/progress-bar/blessed.js",
|
|
40
|
+
"require": "./dist/progress-bar/blessed.cjs"
|
|
31
41
|
}
|
|
32
42
|
},
|
|
33
43
|
"files": [
|
|
34
44
|
"dist",
|
|
35
45
|
"LICENSE",
|
|
36
46
|
"README.md",
|
|
37
|
-
"ROADMAP.md"
|
|
47
|
+
"ROADMAP.md",
|
|
48
|
+
"src/components/*/README.md"
|
|
38
49
|
],
|
|
39
50
|
"sideEffects": false,
|
|
40
51
|
"engines": {
|
|
@@ -47,35 +58,40 @@
|
|
|
47
58
|
"scripts": {
|
|
48
59
|
"build": "tsup",
|
|
49
60
|
"clean": "rm -rf coverage dist",
|
|
50
|
-
"
|
|
51
|
-
"
|
|
61
|
+
"docs": "typedoc --options typedoc.json",
|
|
62
|
+
"docs:check": "typedoc --options typedoc.json --emit none",
|
|
63
|
+
"biome:check": "biome check .",
|
|
64
|
+
"format": "biome check --write .",
|
|
65
|
+
"format:check": "biome check .",
|
|
52
66
|
"lint": "eslint .",
|
|
67
|
+
"lint:fix": "eslint . --fix",
|
|
53
68
|
"release": "semantic-release",
|
|
54
|
-
"test": "vitest run
|
|
69
|
+
"test": "vitest run",
|
|
70
|
+
"test:package": "node tests/package-exports.mjs",
|
|
55
71
|
"test:watch": "vitest",
|
|
56
72
|
"typecheck": "tsc --noEmit",
|
|
57
|
-
"validate": "npm run format:check && npm run lint && npm run typecheck && npm test && npm run build",
|
|
73
|
+
"validate": "npm run format:check && npm run lint && npm run typecheck && npm test && npm run docs:check && npm run build && npm run test:package",
|
|
58
74
|
"prepublishOnly": "npm run validate"
|
|
59
75
|
},
|
|
60
76
|
"peerDependencies": {
|
|
61
77
|
"blessed": "^0.1.81"
|
|
62
78
|
},
|
|
63
79
|
"devDependencies": {
|
|
64
|
-
"@
|
|
80
|
+
"@biomejs/biome": "^2.5.0",
|
|
65
81
|
"@semantic-release/commit-analyzer": "^13.0.1",
|
|
82
|
+
"@semantic-release/exec": "^7.1.0",
|
|
66
83
|
"@semantic-release/github": "^12.0.8",
|
|
67
84
|
"@semantic-release/npm": "^13.1.5",
|
|
68
85
|
"@semantic-release/release-notes-generator": "^14.1.1",
|
|
69
86
|
"@types/blessed": "^0.1.27",
|
|
70
87
|
"@types/node": "^22.20.0",
|
|
71
88
|
"conventional-changelog-conventionalcommits": "^9.3.1",
|
|
72
|
-
"eslint": "^
|
|
73
|
-
"eslint-config-prettier": "^10.1.8",
|
|
74
|
-
"prettier": "^3.8.4",
|
|
89
|
+
"eslint": "^9.39.4",
|
|
75
90
|
"semantic-release": "^25.0.5",
|
|
91
|
+
"super-configs": "^1.15.0",
|
|
76
92
|
"tsup": "^8.5.1",
|
|
93
|
+
"typedoc": "^0.28.19",
|
|
77
94
|
"typescript": "^6.0.3",
|
|
78
|
-
"typescript-eslint": "^8.61.1",
|
|
79
95
|
"vitest": "^4.1.9"
|
|
80
96
|
}
|
|
81
|
-
}
|
|
97
|
+
}
|