terminal-richjs 0.1.0 → 0.2.1

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/dist/index.cjs CHANGED
@@ -9,8 +9,6 @@ var chalk = require('chalk');
9
9
  var tinycolor = require('tinycolor2');
10
10
  var fs = require('fs');
11
11
  var hljs = require('highlight.js');
12
- var ansiEscapes = require('ansi-escapes');
13
- var cliSpinners = require('cli-spinners');
14
12
  var boxes = require('cli-boxes');
15
13
  var readline = require('readline');
16
14
  var marked = require('marked');
@@ -27,8 +25,6 @@ var chalk__default = /*#__PURE__*/_interopDefault(chalk);
27
25
  var tinycolor__default = /*#__PURE__*/_interopDefault(tinycolor);
28
26
  var fs__default = /*#__PURE__*/_interopDefault(fs);
29
27
  var hljs__default = /*#__PURE__*/_interopDefault(hljs);
30
- var ansiEscapes__default = /*#__PURE__*/_interopDefault(ansiEscapes);
31
- var cliSpinners__default = /*#__PURE__*/_interopDefault(cliSpinners);
32
28
  var boxes__default = /*#__PURE__*/_interopDefault(boxes);
33
29
  var readline__default = /*#__PURE__*/_interopDefault(readline);
34
30
  var TerminalRenderer__default = /*#__PURE__*/_interopDefault(TerminalRenderer);
@@ -70,6 +66,12 @@ var Terminal = class {
70
66
  }
71
67
  };
72
68
  var Style = class _Style {
69
+ /**
70
+ * Apply this style to text (alias for render).
71
+ */
72
+ apply(text) {
73
+ return this.render(text);
74
+ }
73
75
  color;
74
76
  backgroundColor;
75
77
  bold;
@@ -1053,253 +1055,488 @@ function getRenderResult(renderable, console, options) {
1053
1055
  // approximation
1054
1056
  };
1055
1057
  }
1056
- var Live = class {
1057
- constructor(renderable, console, autoRefresh = true) {
1058
- this.renderable = renderable;
1059
- this.console = console;
1060
- this.autoRefresh = autoRefresh;
1058
+
1059
+ // src/status/spinners.ts
1060
+ var SPINNERS = {
1061
+ dots: {
1062
+ interval: 80,
1063
+ frames: "\u280B\u2819\u2839\u2838\u283C\u2834\u2826\u2827\u2807\u280F"
1064
+ },
1065
+ dots2: {
1066
+ interval: 80,
1067
+ frames: "\u28FE\u28FD\u28FB\u28BF\u287F\u28DF\u28EF\u28F7"
1068
+ },
1069
+ dots3: {
1070
+ interval: 80,
1071
+ frames: "\u280B\u2819\u281A\u281E\u2816\u2826\u2834\u2832\u2833\u2813"
1072
+ },
1073
+ line: {
1074
+ interval: 130,
1075
+ frames: ["-", "\\", "|", "/"]
1076
+ },
1077
+ line2: {
1078
+ interval: 100,
1079
+ frames: "\u2802-\u2013\u2014\u2013-"
1080
+ },
1081
+ pipe: {
1082
+ interval: 100,
1083
+ frames: "\u2524\u2518\u2534\u2514\u251C\u250C\u252C\u2510"
1084
+ },
1085
+ simpleDots: {
1086
+ interval: 400,
1087
+ frames: [". ", ".. ", "...", " "]
1088
+ },
1089
+ simpleDotsScrolling: {
1090
+ interval: 200,
1091
+ frames: [". ", ".. ", "...", " ..", " .", " "]
1092
+ },
1093
+ star: {
1094
+ interval: 70,
1095
+ frames: "\u2736\u2738\u2739\u273A\u2739\u2737"
1096
+ },
1097
+ star2: {
1098
+ interval: 80,
1099
+ frames: "+x*"
1100
+ },
1101
+ flip: {
1102
+ interval: 70,
1103
+ frames: "___-``'\xB4-___"
1104
+ },
1105
+ hamburger: {
1106
+ interval: 100,
1107
+ frames: "\u2631\u2632\u2634"
1108
+ },
1109
+ growVertical: {
1110
+ interval: 120,
1111
+ frames: "\u2581\u2583\u2584\u2585\u2586\u2587\u2586\u2585\u2584\u2583"
1112
+ },
1113
+ growHorizontal: {
1114
+ interval: 120,
1115
+ frames: "\u258F\u258E\u258D\u258C\u258B\u258A\u2589\u258A\u258B\u258C\u258D\u258E"
1116
+ },
1117
+ balloon: {
1118
+ interval: 140,
1119
+ frames: " .oO@* "
1120
+ },
1121
+ balloon2: {
1122
+ interval: 120,
1123
+ frames: ".oO\xB0Oo."
1124
+ },
1125
+ noise: {
1126
+ interval: 100,
1127
+ frames: "\u2593\u2592\u2591"
1128
+ },
1129
+ bounce: {
1130
+ interval: 120,
1131
+ frames: "\u2801\u2802\u2804\u2802"
1132
+ },
1133
+ boxBounce: {
1134
+ interval: 120,
1135
+ frames: "\u2596\u2598\u259D\u2597"
1136
+ },
1137
+ boxBounce2: {
1138
+ interval: 100,
1139
+ frames: "\u258C\u2580\u2590\u2584"
1140
+ },
1141
+ triangle: {
1142
+ interval: 50,
1143
+ frames: "\u25E2\u25E3\u25E4\u25E5"
1144
+ },
1145
+ arc: {
1146
+ interval: 100,
1147
+ frames: "\u25DC\u25E0\u25DD\u25DE\u25E1\u25DF"
1148
+ },
1149
+ circle: {
1150
+ interval: 120,
1151
+ frames: "\u25E1\u2299\u25E0"
1152
+ },
1153
+ squareCorners: {
1154
+ interval: 180,
1155
+ frames: "\u25F0\u25F3\u25F2\u25F1"
1156
+ },
1157
+ circleQuarters: {
1158
+ interval: 120,
1159
+ frames: "\u25F4\u25F7\u25F6\u25F5"
1160
+ },
1161
+ circleHalves: {
1162
+ interval: 50,
1163
+ frames: "\u25D0\u25D3\u25D1\u25D2"
1164
+ },
1165
+ toggle: {
1166
+ interval: 250,
1167
+ frames: "\u22B6\u22B7"
1168
+ },
1169
+ toggle2: {
1170
+ interval: 80,
1171
+ frames: "\u25AB\u25AA"
1172
+ },
1173
+ toggle3: {
1174
+ interval: 120,
1175
+ frames: "\u25A1\u25A0"
1176
+ },
1177
+ arrow: {
1178
+ interval: 100,
1179
+ frames: "\u2190\u2196\u2191\u2197\u2192\u2198\u2193\u2199"
1180
+ },
1181
+ arrow3: {
1182
+ interval: 120,
1183
+ frames: ["\u25B9\u25B9\u25B9\u25B9\u25B9", "\u25B8\u25B9\u25B9\u25B9\u25B9", "\u25B9\u25B8\u25B9\u25B9\u25B9", "\u25B9\u25B9\u25B8\u25B9\u25B9", "\u25B9\u25B9\u25B9\u25B8\u25B9", "\u25B9\u25B9\u25B9\u25B9\u25B8"]
1184
+ },
1185
+ bouncingBar: {
1186
+ interval: 80,
1187
+ frames: [
1188
+ "[ ]",
1189
+ "[= ]",
1190
+ "[== ]",
1191
+ "[=== ]",
1192
+ "[ ===]",
1193
+ "[ ==]",
1194
+ "[ =]",
1195
+ "[ ]",
1196
+ "[ =]",
1197
+ "[ ==]",
1198
+ "[ ===]",
1199
+ "[====]",
1200
+ "[=== ]",
1201
+ "[== ]",
1202
+ "[= ]"
1203
+ ]
1204
+ },
1205
+ bouncingBall: {
1206
+ interval: 80,
1207
+ frames: [
1208
+ "( \u25CF )",
1209
+ "( \u25CF )",
1210
+ "( \u25CF )",
1211
+ "( \u25CF )",
1212
+ "( \u25CF)",
1213
+ "( \u25CF )",
1214
+ "( \u25CF )",
1215
+ "( \u25CF )",
1216
+ "( \u25CF )",
1217
+ "(\u25CF )"
1218
+ ]
1219
+ },
1220
+ smiley: {
1221
+ interval: 200,
1222
+ frames: ["\u{1F604} ", "\u{1F61D} "]
1223
+ },
1224
+ monkey: {
1225
+ interval: 300,
1226
+ frames: ["\u{1F648} ", "\u{1F648} ", "\u{1F649} ", "\u{1F64A} "]
1227
+ },
1228
+ hearts: {
1229
+ interval: 100,
1230
+ frames: ["\u{1F49B} ", "\u{1F499} ", "\u{1F49C} ", "\u{1F49A} ", "\u2764\uFE0F "]
1231
+ },
1232
+ clock: {
1233
+ interval: 100,
1234
+ frames: ["\u{1F55B} ", "\u{1F550} ", "\u{1F551} ", "\u{1F552} ", "\u{1F553} ", "\u{1F554} ", "\u{1F555} ", "\u{1F556} ", "\u{1F557} ", "\u{1F558} ", "\u{1F559} ", "\u{1F55A} "]
1235
+ },
1236
+ earth: {
1237
+ interval: 180,
1238
+ frames: ["\u{1F30D} ", "\u{1F30E} ", "\u{1F30F} "]
1239
+ },
1240
+ moon: {
1241
+ interval: 80,
1242
+ frames: ["\u{1F311} ", "\u{1F312} ", "\u{1F313} ", "\u{1F314} ", "\u{1F315} ", "\u{1F316} ", "\u{1F317} ", "\u{1F318} "]
1243
+ },
1244
+ runner: {
1245
+ interval: 140,
1246
+ frames: ["\u{1F6B6} ", "\u{1F3C3} "]
1247
+ },
1248
+ weather: {
1249
+ interval: 100,
1250
+ frames: [
1251
+ "\u2600\uFE0F ",
1252
+ "\u{1F324} ",
1253
+ "\u26C5\uFE0F ",
1254
+ "\u{1F325} ",
1255
+ "\u2601\uFE0F ",
1256
+ "\u{1F327} ",
1257
+ "\u{1F328} ",
1258
+ "\u26C8 ",
1259
+ "\u{1F327} ",
1260
+ "\u2601\uFE0F ",
1261
+ "\u{1F325} ",
1262
+ "\u26C5\uFE0F ",
1263
+ "\u{1F324} ",
1264
+ "\u2600\uFE0F "
1265
+ ]
1266
+ },
1267
+ christmas: {
1268
+ interval: 400,
1269
+ frames: "\u{1F332}\u{1F384}"
1270
+ },
1271
+ point: {
1272
+ interval: 125,
1273
+ frames: ["\u2219\u2219\u2219", "\u25CF\u2219\u2219", "\u2219\u25CF\u2219", "\u2219\u2219\u25CF", "\u2219\u2219\u2219"]
1274
+ },
1275
+ layer: {
1276
+ interval: 150,
1277
+ frames: "-=\u2261"
1278
+ },
1279
+ aesthetic: {
1280
+ interval: 80,
1281
+ frames: [
1282
+ "\u25B0\u25B1\u25B1\u25B1\u25B1\u25B1\u25B1",
1283
+ "\u25B0\u25B0\u25B1\u25B1\u25B1\u25B1\u25B1",
1284
+ "\u25B0\u25B0\u25B0\u25B1\u25B1\u25B1\u25B1",
1285
+ "\u25B0\u25B0\u25B0\u25B0\u25B1\u25B1\u25B1",
1286
+ "\u25B0\u25B0\u25B0\u25B0\u25B0\u25B1\u25B1",
1287
+ "\u25B0\u25B0\u25B0\u25B0\u25B0\u25B0\u25B1",
1288
+ "\u25B0\u25B0\u25B0\u25B0\u25B0\u25B0\u25B0",
1289
+ "\u25B0\u25B1\u25B1\u25B1\u25B1\u25B1\u25B1"
1290
+ ]
1291
+ }
1292
+ };
1293
+ function getSpinner(name) {
1294
+ return SPINNERS[name];
1295
+ }
1296
+ function listSpinners() {
1297
+ return Object.keys(SPINNERS);
1298
+ }
1299
+
1300
+ // src/status/spinner.ts
1301
+ var Spinner = class {
1302
+ name;
1303
+ frames;
1304
+ interval;
1305
+ text;
1306
+ style;
1307
+ speed;
1308
+ startTime = null;
1309
+ frameNoOffset = 0;
1310
+ constructor(name = "dots", options = {}) {
1311
+ const spinner = SPINNERS[name];
1312
+ if (!spinner) {
1313
+ throw new Error(`No spinner called '${name}'. Use listSpinners() to see available spinners.`);
1314
+ }
1315
+ this.name = name;
1316
+ this.frames = typeof spinner.frames === "string" ? [...spinner.frames] : [...spinner.frames];
1317
+ this.interval = spinner.interval;
1318
+ this.text = options.text ?? "";
1319
+ this.style = options.style ?? "green";
1320
+ this.speed = options.speed ?? 1;
1321
+ }
1322
+ /**
1323
+ * Render the spinner for a given time.
1324
+ */
1325
+ render(time) {
1326
+ if (this.startTime === null) {
1327
+ this.startTime = time;
1328
+ }
1329
+ const frameNo = (time - this.startTime) * this.speed / (this.interval / 1e3) + this.frameNoOffset;
1330
+ const frame = this.frames[Math.floor(frameNo) % this.frames.length];
1331
+ const styledFrame = Style.parse(this.style).apply(frame);
1332
+ if (this.text) {
1333
+ return `${styledFrame} ${this.text}`;
1334
+ }
1335
+ return styledFrame;
1336
+ }
1337
+ /**
1338
+ * Get the current frame without time advancement (for static rendering).
1339
+ */
1340
+ getCurrentFrame() {
1341
+ const now = Date.now() / 1e3;
1342
+ return this.render(now);
1343
+ }
1344
+ /**
1345
+ * Update spinner properties.
1346
+ */
1347
+ update(options) {
1348
+ if (options.text !== void 0) this.text = options.text;
1349
+ if (options.style !== void 0) this.style = options.style;
1350
+ if (options.speed !== void 0) {
1351
+ this.frameNoOffset = this.startTime !== null ? (Date.now() / 1e3 - this.startTime) * this.speed / (this.interval / 1e3) + this.frameNoOffset : 0;
1352
+ this.startTime = Date.now() / 1e3;
1353
+ this.speed = options.speed;
1354
+ }
1355
+ }
1356
+ __rich_console__(_console, _consoleOptions) {
1357
+ const frame = this.getCurrentFrame();
1358
+ return {
1359
+ segments: [new Segment(`${frame}
1360
+ `, Style.null())],
1361
+ width: frame.length
1362
+ };
1363
+ }
1364
+ };
1365
+ function listSpinners2() {
1366
+ return Object.keys(SPINNERS);
1367
+ }
1368
+
1369
+ // src/status/status.ts
1370
+ var Status = class {
1371
+ spinner;
1372
+ message;
1373
+ interval = null;
1374
+ started = false;
1375
+ lastRenderedLines = 0;
1376
+ constructor(message, options = {}) {
1377
+ this.message = message;
1378
+ this.spinner = new Spinner(options.spinnerName ?? "dots");
1061
1379
  }
1062
- _started = false;
1063
- _lastHeight = 0;
1064
1380
  start() {
1065
- this._started = true;
1381
+ if (this.started) return;
1382
+ this.started = true;
1383
+ process.stdout.write("\x1B[?25l");
1384
+ this.interval = setInterval(() => {
1385
+ this.refresh();
1386
+ }, this.spinner.interval);
1066
1387
  this.refresh();
1067
1388
  }
1068
1389
  stop() {
1069
- this._started = false;
1070
- this.console.print("");
1390
+ if (!this.started) return;
1391
+ if (this.interval) {
1392
+ clearInterval(this.interval);
1393
+ this.interval = null;
1394
+ }
1395
+ if (this.lastRenderedLines > 0) {
1396
+ process.stdout.write(`\x1B[${this.lastRenderedLines}A`);
1397
+ for (let i = 0; i < this.lastRenderedLines; i++) {
1398
+ process.stdout.write("\x1B[2K\n");
1399
+ }
1400
+ process.stdout.write(`\x1B[${this.lastRenderedLines}A`);
1401
+ }
1402
+ process.stdout.write("\x1B[?25h");
1403
+ this.started = false;
1071
1404
  }
1072
- update(renderable) {
1073
- this.renderable = renderable;
1074
- this.refresh();
1405
+ update(message) {
1406
+ this.message = message;
1407
+ if (this.started) {
1408
+ this.refresh();
1409
+ }
1075
1410
  }
1076
1411
  refresh() {
1077
- if (!this._started) return;
1078
- if (this._lastHeight > 0) {
1079
- process.stdout.write(ansiEscapes__default.default.eraseLines(this._lastHeight));
1412
+ if (this.lastRenderedLines > 0) {
1413
+ process.stdout.write(`\x1B[${this.lastRenderedLines}A`);
1414
+ for (let i = 0; i < this.lastRenderedLines; i++) {
1415
+ process.stdout.write("\x1B[2K\n");
1416
+ }
1417
+ process.stdout.write(`\x1B[${this.lastRenderedLines}A`);
1080
1418
  }
1081
- const output = this.console.render(this.renderable);
1082
- const lines = output.split("\n").length;
1083
- this._lastHeight = lines;
1419
+ const frame = this.spinner.getCurrentFrame();
1420
+ const output = `${frame} ${this.message}
1421
+ `;
1422
+ this.lastRenderedLines = 1;
1084
1423
  process.stdout.write(output);
1085
1424
  }
1086
1425
  };
1087
- var Spinner = class {
1088
- // Type definition issues with cli-spinners
1089
- constructor(name = "dots", style = Style.null()) {
1090
- this.name = name;
1091
- this.style = style;
1092
- this.spinner = cliSpinners__default.default[name];
1426
+
1427
+ // src/console/console.ts
1428
+ var Console = class {
1429
+ error(message) {
1430
+ const text = String(message);
1431
+ process2__default.default.stderr.write(`\x1B[31m${text}\x1B[0m
1432
+ `);
1093
1433
  }
1094
- frame = 0;
1095
- // @ts-ignore
1096
- spinner;
1097
- get currentFrame() {
1098
- return this.spinner.frames[this.frame];
1434
+ terminal;
1435
+ markupParser;
1436
+ options;
1437
+ theme;
1438
+ constructor(options = {}) {
1439
+ this.options = options;
1440
+ this.terminal = new Terminal();
1441
+ this.theme = options.theme ?? DEFAULT_THEME;
1442
+ this.markupParser = new MarkupParser(this.theme);
1099
1443
  }
1100
- __rich_console__(_console, _options) {
1101
- return {
1102
- segments: [new Segment(this.currentFrame, this.style)],
1103
- width: 1
1104
- // approximates
1105
- };
1444
+ get width() {
1445
+ return this.options.width ?? this.terminal.width;
1106
1446
  }
1107
- nextFrame() {
1108
- this.frame = (this.frame + 1) % this.spinner.frames.length;
1447
+ get height() {
1448
+ return this.options.height ?? this.terminal.height;
1109
1449
  }
1110
- };
1111
-
1112
- // src/core/lines.ts
1113
- function splitLines(segments) {
1114
- const lines = [];
1115
- let currentLine = [];
1116
- for (const segment of segments) {
1117
- if (segment.text.includes("\n")) {
1118
- const parts = segment.text.split("\n");
1119
- for (let i = 0; i < parts.length; i++) {
1120
- const part = parts[i];
1121
- if (part) {
1122
- currentLine.push(new Segment(part, segment.style, segment.isControl));
1123
- }
1124
- if (i < parts.length - 1) {
1125
- lines.push(currentLine);
1126
- currentLine = [];
1127
- }
1128
- }
1129
- } else {
1130
- currentLine.push(segment);
1450
+ /**
1451
+ * Prints objects to the console.
1452
+ */
1453
+ print(...objects) {
1454
+ const lastObj = objects[objects.length - 1];
1455
+ let printObjects = objects;
1456
+ let options = {};
1457
+ if (objects.length > 1 && typeof lastObj === "object" && lastObj !== null && !isRenderable(lastObj) && ("style" in lastObj || "markup" in lastObj)) {
1458
+ options = objects.pop();
1459
+ printObjects = objects;
1131
1460
  }
1461
+ const output = printObjects.map((obj) => {
1462
+ if (typeof obj === "string") {
1463
+ return this.renderString(obj, options.markup ?? true);
1464
+ }
1465
+ if (isRenderable(obj)) {
1466
+ return this.render(obj);
1467
+ }
1468
+ return String(obj);
1469
+ }).join(" ");
1470
+ this.write(`${output}
1471
+ `);
1132
1472
  }
1133
- if (currentLine.length > 0) {
1134
- lines.push(currentLine);
1473
+ /**
1474
+ * Prints a formatted exception.
1475
+ */
1476
+ printException(error) {
1477
+ const traceback = new Traceback(error);
1478
+ this.print(traceback);
1135
1479
  }
1136
- return lines;
1137
- }
1138
- function padLine(line, width, style = Style.null()) {
1139
- const currentWidth = line.reduce((acc, s) => acc + s.cellLength(), 0);
1140
- if (currentWidth >= width) return line;
1141
- const padding = width - currentWidth;
1142
- return [...line, new Segment(" ".repeat(padding), style)];
1143
- }
1144
-
1145
- // src/layout/layout.ts
1146
- var Layout = class _Layout {
1147
- _renderable = null;
1148
- _children = [];
1149
- _direction = "column";
1150
- size;
1151
- ratio = 1;
1152
- minimumSize = 0;
1153
- visible = true;
1154
- constructor(renderable, options = {}) {
1155
- if (renderable) this._renderable = renderable;
1156
- this.size = options.size;
1157
- this.ratio = options.ratio ?? 1;
1158
- this.minimumSize = options.minimumSize ?? 0;
1159
- this.visible = options.visible ?? true;
1480
+ /**
1481
+ * Displays a status spinner.
1482
+ */
1483
+ status(message, options = {}) {
1484
+ return new Status(message, { spinnerName: options.spinner, ...options });
1160
1485
  }
1161
1486
  /**
1162
- * Split the layout into a row (horizontal split).
1487
+ * Run a task with a status spinner.
1163
1488
  */
1164
- splitRow(...layouts) {
1165
- this._direction = "row";
1166
- this._children = layouts.map((l) => l instanceof _Layout ? l : new _Layout(l));
1489
+ async withStatus(message, task, options = {}) {
1490
+ const status = new Status(message, { spinnerName: options.spinner });
1491
+ status.start();
1492
+ try {
1493
+ return await task(status);
1494
+ } finally {
1495
+ status.stop();
1496
+ }
1167
1497
  }
1168
1498
  /**
1169
- * Split the layout into a column (vertical split).
1499
+ * Renders a renderable object to a string.
1170
1500
  */
1171
- splitColumn(...layouts) {
1172
- this._direction = "column";
1173
- this._children = layouts.map((l) => l instanceof _Layout ? l : new _Layout(l));
1501
+ render(renderable) {
1502
+ const result = getRenderResult(renderable, this, this.options);
1503
+ return result.segments.map((s) => s.render()).join("");
1174
1504
  }
1175
- get renderable() {
1176
- return this._renderable;
1505
+ /**
1506
+ * Internal string rendering with markup and wrapping.
1507
+ */
1508
+ renderString(text, markup = true) {
1509
+ const segments = markup ? this.markupParser.parse(text) : [new Segment(text)];
1510
+ const rendered = segments.map((s) => s.render()).join("");
1511
+ return wrapAnsi__default.default(rendered, this.width, { hard: true });
1177
1512
  }
1178
- update(renderable) {
1179
- this._renderable = renderable;
1513
+ /**
1514
+ * Low-level write to stdout.
1515
+ */
1516
+ write(text) {
1517
+ process2__default.default.stdout.write(text);
1518
+ }
1519
+ };
1520
+ var Text = class {
1521
+ constructor(content, style = Style.null(), justify = "left", overflow = "fold", noWrap = false) {
1522
+ this.style = style;
1523
+ this.justify = justify;
1524
+ this.overflow = overflow;
1525
+ this.noWrap = noWrap;
1526
+ if (typeof content === "string") {
1527
+ const parser = new MarkupParser();
1528
+ this.segments = parser.parse(content);
1529
+ } else {
1530
+ this.segments = content;
1531
+ }
1180
1532
  }
1533
+ segments;
1181
1534
  __rich_console__(console, options) {
1182
- if (!this.visible) return { segments: [], width: 0, height: 0 };
1183
1535
  const width = options.width ?? console.width;
1184
- const height = options.height ?? console.height;
1185
- if (this._children.length === 0) {
1186
- if (this._renderable) {
1187
- return getRenderResult(this._renderable, console, { ...options, width, height });
1188
- }
1189
- return { segments: [], width, height: 0 };
1190
- }
1191
- const segments = [];
1192
- if (this._direction === "column") {
1193
- for (const child of this._children) {
1194
- if (!child.visible) continue;
1195
- const result = getRenderResult(child, console, { ...options, width });
1196
- segments.push(...result.segments);
1197
- const last = result.segments[result.segments.length - 1];
1198
- if (last && !last.text.endsWith("\n")) {
1199
- segments.push(new Segment("\n"));
1200
- }
1201
- }
1202
- } else {
1203
- const childWidths = this.calculateSizes(width, this._children);
1204
- const renderedLines = [];
1205
- let maxHeight = 0;
1206
- this._children.forEach((child, i) => {
1207
- if (!child.visible) {
1208
- renderedLines.push([]);
1209
- return;
1210
- }
1211
- const w = childWidths[i];
1212
- const result = getRenderResult(child, console, { ...options, width: w });
1213
- let childSegments = result.segments;
1214
- const lines = splitLines(childSegments);
1215
- renderedLines.push(lines);
1216
- if (lines.length > maxHeight) maxHeight = lines.length;
1217
- });
1218
- for (let y = 0; y < maxHeight; y++) {
1219
- for (let x = 0; x < this._children.length; x++) {
1220
- if (!this._children[x].visible) continue;
1221
- const lines = renderedLines[x];
1222
- const w = childWidths[x];
1223
- if (y < lines.length) {
1224
- const line = lines[y];
1225
- segments.push(...padLine(line, w));
1226
- } else {
1227
- segments.push(new Segment(" ".repeat(w)));
1228
- }
1229
- }
1230
- segments.push(new Segment("\n"));
1231
- }
1232
- }
1233
- return { segments, width, height };
1234
- }
1235
- /**
1236
- * Calculates the size (width for rows, height for columns) for each child
1237
- * based on constraints.
1238
- */
1239
- calculateSizes(availableSpace, children) {
1240
- const sizes = new Array(children.length).fill(0);
1241
- const visibleChildren = children.map((c, i) => ({ child: c, index: i })).filter((x) => x.child.visible);
1242
- if (visibleChildren.length === 0) return sizes;
1243
- let remainingSpace = availableSpace;
1244
- let totalRatio = 0;
1245
- for (const { child, index } of visibleChildren) {
1246
- if (child.size !== void 0) {
1247
- const size = Math.min(child.size, remainingSpace);
1248
- sizes[index] = size;
1249
- remainingSpace -= size;
1250
- } else if (child.minimumSize > 0) {
1251
- sizes[index] = child.minimumSize;
1252
- remainingSpace -= child.minimumSize;
1253
- }
1254
- if (child.size === void 0) {
1255
- totalRatio += child.ratio;
1256
- }
1257
- }
1258
- if (remainingSpace <= 0) return sizes;
1259
- if (totalRatio > 0) {
1260
- let distributed = 0;
1261
- for (let i = 0; i < visibleChildren.length; i++) {
1262
- const { child, index } = visibleChildren[i];
1263
- if (child.size === void 0) {
1264
- const share = Math.floor(child.ratio / totalRatio * remainingSpace);
1265
- sizes[index] += share;
1266
- distributed += share;
1267
- }
1268
- }
1269
- const dust = remainingSpace - distributed;
1270
- if (dust > 0) {
1271
- for (let i = visibleChildren.length - 1; i >= 0; i--) {
1272
- const { child, index } = visibleChildren[i];
1273
- if (child.size === void 0) {
1274
- sizes[index] += dust;
1275
- break;
1276
- }
1277
- }
1278
- }
1279
- }
1280
- return sizes;
1281
- }
1282
- };
1283
- var Text = class {
1284
- constructor(content, style = Style.null(), justify = "left", overflow = "fold", noWrap = false) {
1285
- this.style = style;
1286
- this.justify = justify;
1287
- this.overflow = overflow;
1288
- this.noWrap = noWrap;
1289
- if (typeof content === "string") {
1290
- const parser = new MarkupParser();
1291
- this.segments = parser.parse(content);
1292
- } else {
1293
- this.segments = content;
1294
- }
1295
- }
1296
- segments;
1297
- __rich_console__(console, options) {
1298
- const width = options.width ?? console.width;
1299
- const text = this.segments.map((s) => s.render()).join("");
1300
- let wrapped = text;
1301
- if (!this.noWrap) {
1302
- wrapped = wrapAnsi__default.default(text, width, { hard: true, trim: false });
1536
+ const text = this.segments.map((s) => s.render()).join("");
1537
+ let wrapped = text;
1538
+ if (!this.noWrap) {
1539
+ wrapped = wrapAnsi__default.default(text, width, { hard: true, trim: false });
1303
1540
  }
1304
1541
  const resultSegments = wrapped.split("\n").flatMap((line) => {
1305
1542
  return [new Segment(line), new Segment("\n", Style.null(), true)];
@@ -1310,131 +1547,6 @@ var Text = class {
1310
1547
  };
1311
1548
  }
1312
1549
  };
1313
-
1314
- // src/status/status.ts
1315
- var Status = class {
1316
- live;
1317
- spinner;
1318
- message;
1319
- interval = null;
1320
- constructor(message, options = {}) {
1321
- this.message = message;
1322
- this.spinner = new Spinner(options.spinner ?? "dots");
1323
- const console = options.console ?? new Console();
1324
- this.live = new Live(this.render(), console);
1325
- }
1326
- start() {
1327
- this.live.start();
1328
- this.interval = setInterval(() => {
1329
- this.spinner.nextFrame();
1330
- this.live.update(this.render());
1331
- }, 80);
1332
- }
1333
- stop() {
1334
- if (this.interval) clearInterval(this.interval);
1335
- this.live.stop();
1336
- }
1337
- update(message) {
1338
- this.message = message;
1339
- this.live.update(this.render());
1340
- }
1341
- render() {
1342
- const layout = new Layout();
1343
- layout.splitRow(
1344
- this.spinner,
1345
- new Text(" " + this.message)
1346
- );
1347
- return layout;
1348
- }
1349
- };
1350
-
1351
- // src/console/console.ts
1352
- var Console = class {
1353
- terminal;
1354
- markupParser;
1355
- options;
1356
- theme;
1357
- constructor(options = {}) {
1358
- this.options = options;
1359
- this.terminal = new Terminal();
1360
- this.theme = options.theme ?? DEFAULT_THEME;
1361
- this.markupParser = new MarkupParser(this.theme);
1362
- }
1363
- get width() {
1364
- return this.options.width ?? this.terminal.width;
1365
- }
1366
- get height() {
1367
- return this.options.height ?? this.terminal.height;
1368
- }
1369
- /**
1370
- * Prints objects to the console.
1371
- */
1372
- print(...objects) {
1373
- const lastObj = objects[objects.length - 1];
1374
- let printObjects = objects;
1375
- let options = {};
1376
- if (objects.length > 1 && typeof lastObj === "object" && lastObj !== null && !isRenderable(lastObj) && ("style" in lastObj || "markup" in lastObj)) {
1377
- options = objects.pop();
1378
- printObjects = objects;
1379
- }
1380
- const output = printObjects.map((obj) => {
1381
- if (typeof obj === "string") {
1382
- return this.renderString(obj, options.markup ?? true);
1383
- }
1384
- if (isRenderable(obj)) {
1385
- return this.render(obj);
1386
- }
1387
- return String(obj);
1388
- }).join(" ");
1389
- this.write(output + "\n");
1390
- }
1391
- /**
1392
- * Prints a formatted exception.
1393
- */
1394
- printException(error) {
1395
- const traceback = new Traceback(error);
1396
- this.print(traceback);
1397
- }
1398
- /**
1399
- * Displays a status spinner.
1400
- */
1401
- status(message, options = {}) {
1402
- return new Status(message, { console: this, ...options });
1403
- }
1404
- /**
1405
- * Run a task with a status spinner.
1406
- */
1407
- async withStatus(message, task, options = {}) {
1408
- const status = new Status(message, { console: this, ...options });
1409
- status.start();
1410
- try {
1411
- return await task(status);
1412
- } finally {
1413
- status.stop();
1414
- }
1415
- }
1416
- /**
1417
- * Renders a renderable object to a string.
1418
- */
1419
- render(renderable) {
1420
- const result = getRenderResult(renderable, this, this.options);
1421
- return result.segments.map((s) => s.render()).join("");
1422
- }
1423
- /**
1424
- * Internal string rendering with markup and wrapping.
1425
- */
1426
- renderString(text, markup = true) {
1427
- const segments = markup ? this.markupParser.parse(text) : [new Segment(text)];
1428
- const rendered = segments.map((s) => s.render()).join("");
1429
- return wrapAnsi__default.default(rendered, this.width, { hard: true });
1430
- }
1431
- /**
1432
- * Low-level write to stdout.
1433
- */
1434
- write(text) {
1435
- process2__default.default.stdout.write(text);
1436
- }
1437
- };
1438
1550
  var CUSTOM_BOXES = {
1439
1551
  // Rounded corners (may not be in all versions of cli-boxes)
1440
1552
  rounded: {
@@ -1643,6 +1755,39 @@ function listBoxStyles() {
1643
1755
  const cliBoxStyles = Object.keys(boxes__default.default);
1644
1756
  return [.../* @__PURE__ */ new Set([...customStyles, ...cliBoxStyles])];
1645
1757
  }
1758
+
1759
+ // src/core/lines.ts
1760
+ function splitLines(segments) {
1761
+ const lines = [];
1762
+ let currentLine = [];
1763
+ for (const segment of segments) {
1764
+ if (segment.text.includes("\n")) {
1765
+ const parts = segment.text.split("\n");
1766
+ for (let i = 0; i < parts.length; i++) {
1767
+ const part = parts[i];
1768
+ if (part) {
1769
+ currentLine.push(new Segment(part, segment.style, segment.isControl));
1770
+ }
1771
+ if (i < parts.length - 1) {
1772
+ lines.push(currentLine);
1773
+ currentLine = [];
1774
+ }
1775
+ }
1776
+ } else {
1777
+ currentLine.push(segment);
1778
+ }
1779
+ }
1780
+ if (currentLine.length > 0) {
1781
+ lines.push(currentLine);
1782
+ }
1783
+ return lines;
1784
+ }
1785
+ function padLine(line, width, style = Style.null()) {
1786
+ const currentWidth = line.reduce((acc, s) => acc + s.cellLength(), 0);
1787
+ if (currentWidth >= width) return line;
1788
+ const padding = width - currentWidth;
1789
+ return [...line, new Segment(" ".repeat(padding), style)];
1790
+ }
1646
1791
  var Panel = class _Panel {
1647
1792
  constructor(renderable, options = {}) {
1648
1793
  this.renderable = renderable;
@@ -2156,6 +2301,145 @@ var Tree = class _Tree {
2156
2301
  }
2157
2302
  };
2158
2303
 
2304
+ // src/layout/layout.ts
2305
+ var Layout = class _Layout {
2306
+ _renderable = null;
2307
+ _children = [];
2308
+ _direction = "column";
2309
+ size;
2310
+ ratio = 1;
2311
+ minimumSize = 0;
2312
+ visible = true;
2313
+ constructor(renderable, options = {}) {
2314
+ if (renderable) this._renderable = renderable;
2315
+ this.size = options.size;
2316
+ this.ratio = options.ratio ?? 1;
2317
+ this.minimumSize = options.minimumSize ?? 0;
2318
+ this.visible = options.visible ?? true;
2319
+ }
2320
+ /**
2321
+ * Split the layout into a row (horizontal split).
2322
+ */
2323
+ splitRow(...layouts) {
2324
+ this._direction = "row";
2325
+ this._children = layouts.map((l) => l instanceof _Layout ? l : new _Layout(l));
2326
+ }
2327
+ /**
2328
+ * Split the layout into a column (vertical split).
2329
+ */
2330
+ splitColumn(...layouts) {
2331
+ this._direction = "column";
2332
+ this._children = layouts.map((l) => l instanceof _Layout ? l : new _Layout(l));
2333
+ }
2334
+ get renderable() {
2335
+ return this._renderable;
2336
+ }
2337
+ update(renderable) {
2338
+ this._renderable = renderable;
2339
+ }
2340
+ __rich_console__(console, options) {
2341
+ if (!this.visible) return { segments: [], width: 0, height: 0 };
2342
+ const width = options.width ?? console.width;
2343
+ const height = options.height ?? console.height;
2344
+ if (this._children.length === 0) {
2345
+ if (this._renderable) {
2346
+ return getRenderResult(this._renderable, console, { ...options, width, height });
2347
+ }
2348
+ return { segments: [], width, height: 0 };
2349
+ }
2350
+ const segments = [];
2351
+ if (this._direction === "column") {
2352
+ for (const child of this._children) {
2353
+ if (!child.visible) continue;
2354
+ const result = getRenderResult(child, console, { ...options, width });
2355
+ segments.push(...result.segments);
2356
+ const last = result.segments[result.segments.length - 1];
2357
+ if (last && !last.text.endsWith("\n")) {
2358
+ segments.push(new Segment("\n"));
2359
+ }
2360
+ }
2361
+ } else {
2362
+ const childWidths = this.calculateSizes(width, this._children);
2363
+ const renderedLines = [];
2364
+ let maxHeight = 0;
2365
+ this._children.forEach((child, i) => {
2366
+ if (!child.visible) {
2367
+ renderedLines.push([]);
2368
+ return;
2369
+ }
2370
+ const w = childWidths[i];
2371
+ const result = getRenderResult(child, console, { ...options, width: w });
2372
+ let childSegments = result.segments;
2373
+ const lines = splitLines(childSegments);
2374
+ renderedLines.push(lines);
2375
+ if (lines.length > maxHeight) maxHeight = lines.length;
2376
+ });
2377
+ for (let y = 0; y < maxHeight; y++) {
2378
+ for (let x = 0; x < this._children.length; x++) {
2379
+ if (!this._children[x].visible) continue;
2380
+ const lines = renderedLines[x];
2381
+ const w = childWidths[x];
2382
+ if (y < lines.length) {
2383
+ const line = lines[y];
2384
+ segments.push(...padLine(line, w));
2385
+ } else {
2386
+ segments.push(new Segment(" ".repeat(w)));
2387
+ }
2388
+ }
2389
+ segments.push(new Segment("\n"));
2390
+ }
2391
+ }
2392
+ return { segments, width, height };
2393
+ }
2394
+ /**
2395
+ * Calculates the size (width for rows, height for columns) for each child
2396
+ * based on constraints.
2397
+ */
2398
+ calculateSizes(availableSpace, children) {
2399
+ const sizes = new Array(children.length).fill(0);
2400
+ const visibleChildren = children.map((c, i) => ({ child: c, index: i })).filter((x) => x.child.visible);
2401
+ if (visibleChildren.length === 0) return sizes;
2402
+ let remainingSpace = availableSpace;
2403
+ let totalRatio = 0;
2404
+ for (const { child, index } of visibleChildren) {
2405
+ if (child.size !== void 0) {
2406
+ const size = Math.min(child.size, remainingSpace);
2407
+ sizes[index] = size;
2408
+ remainingSpace -= size;
2409
+ } else if (child.minimumSize > 0) {
2410
+ sizes[index] = child.minimumSize;
2411
+ remainingSpace -= child.minimumSize;
2412
+ }
2413
+ if (child.size === void 0) {
2414
+ totalRatio += child.ratio;
2415
+ }
2416
+ }
2417
+ if (remainingSpace <= 0) return sizes;
2418
+ if (totalRatio > 0) {
2419
+ let distributed = 0;
2420
+ for (let i = 0; i < visibleChildren.length; i++) {
2421
+ const { child, index } = visibleChildren[i];
2422
+ if (child.size === void 0) {
2423
+ const share = Math.floor(child.ratio / totalRatio * remainingSpace);
2424
+ sizes[index] += share;
2425
+ distributed += share;
2426
+ }
2427
+ }
2428
+ const dust = remainingSpace - distributed;
2429
+ if (dust > 0) {
2430
+ for (let i = visibleChildren.length - 1; i >= 0; i--) {
2431
+ const { child, index } = visibleChildren[i];
2432
+ if (child.size === void 0) {
2433
+ sizes[index] += dust;
2434
+ break;
2435
+ }
2436
+ }
2437
+ }
2438
+ }
2439
+ return sizes;
2440
+ }
2441
+ };
2442
+
2159
2443
  // src/layout/grid.ts
2160
2444
  var Grid = class extends Layout {
2161
2445
  constructor() {
@@ -2268,6 +2552,187 @@ var Align = class _Align {
2268
2552
  return { segments, width };
2269
2553
  }
2270
2554
  };
2555
+
2556
+ // src/renderables/columns.ts
2557
+ var Columns = class {
2558
+ renderables;
2559
+ options;
2560
+ constructor(renderables = [], options = {}) {
2561
+ this.renderables = Array.from(renderables);
2562
+ this.options = {
2563
+ padding: options.padding ?? 1,
2564
+ expand: options.expand ?? false,
2565
+ equal: options.equal ?? false,
2566
+ columnFirst: options.columnFirst ?? false,
2567
+ rightToLeft: options.rightToLeft ?? false,
2568
+ ...options
2569
+ };
2570
+ }
2571
+ /**
2572
+ * Add a renderable to the columns.
2573
+ */
2574
+ add(renderable) {
2575
+ this.renderables.push(renderable);
2576
+ return this;
2577
+ }
2578
+ __rich_console__(console, consoleOptions) {
2579
+ if (this.renderables.length === 0) {
2580
+ return { segments: [], width: 0 };
2581
+ }
2582
+ const items = this.renderables.map((r) => {
2583
+ if (typeof r === "string") {
2584
+ return r;
2585
+ }
2586
+ const result = r.__rich_console__(console, consoleOptions);
2587
+ if ("segments" in result) {
2588
+ return result.segments.map((s) => s.text).join("");
2589
+ }
2590
+ return "";
2591
+ });
2592
+ const terminalWidth = consoleOptions.width ?? console.width ?? 80;
2593
+ const padding = this.options.padding ?? 1;
2594
+ const paddingStr = " ".repeat(padding);
2595
+ let columnWidth;
2596
+ if (this.options.width) {
2597
+ columnWidth = this.options.width;
2598
+ } else if (this.options.equal) {
2599
+ columnWidth = Math.max(...items.map((item) => this.getDisplayWidth(item)));
2600
+ } else {
2601
+ columnWidth = Math.max(...items.map((item) => this.getDisplayWidth(item)));
2602
+ }
2603
+ const columnCount = Math.max(
2604
+ 1,
2605
+ Math.floor((terminalWidth + padding) / (columnWidth + padding))
2606
+ );
2607
+ const lines = [];
2608
+ if (this.options.title) {
2609
+ lines.push(this.options.title);
2610
+ }
2611
+ const rows = [];
2612
+ if (this.options.columnFirst) {
2613
+ const rowCount = Math.ceil(items.length / columnCount);
2614
+ for (let row = 0; row < rowCount; row++) {
2615
+ const rowItems = [];
2616
+ for (let col = 0; col < columnCount; col++) {
2617
+ const index = col * rowCount + row;
2618
+ if (index < items.length) {
2619
+ rowItems.push(this.padItem(items[index], columnWidth));
2620
+ }
2621
+ }
2622
+ rows.push(rowItems);
2623
+ }
2624
+ } else {
2625
+ for (let i = 0; i < items.length; i += columnCount) {
2626
+ const rowItems = [];
2627
+ for (let j = 0; j < columnCount && i + j < items.length; j++) {
2628
+ rowItems.push(this.padItem(items[i + j], columnWidth));
2629
+ }
2630
+ rows.push(rowItems);
2631
+ }
2632
+ }
2633
+ for (const row of rows) {
2634
+ let rowItems = row;
2635
+ if (this.options.rightToLeft) {
2636
+ rowItems = [...row].reverse();
2637
+ }
2638
+ lines.push(rowItems.join(paddingStr));
2639
+ }
2640
+ const output = `${lines.join("\n")}
2641
+ `;
2642
+ return {
2643
+ segments: [new Segment(output, Style.null())],
2644
+ width: terminalWidth
2645
+ };
2646
+ }
2647
+ /**
2648
+ * Get the display width of a string (accounting for ANSI codes).
2649
+ */
2650
+ getDisplayWidth(text) {
2651
+ const stripped = text.replace(/\x1b\[[0-9;]*m/g, "");
2652
+ return stripped.length;
2653
+ }
2654
+ /**
2655
+ * Pad an item to the specified width.
2656
+ */
2657
+ padItem(item, width) {
2658
+ const currentWidth = this.getDisplayWidth(item);
2659
+ if (currentWidth >= width) {
2660
+ return item;
2661
+ }
2662
+ return item + " ".repeat(width - currentWidth);
2663
+ }
2664
+ };
2665
+
2666
+ // src/renderables/json.ts
2667
+ var JSON2 = class _JSON {
2668
+ text;
2669
+ highlight;
2670
+ constructor(json, options = {}) {
2671
+ const { indent = 2, sortKeys = false } = options;
2672
+ this.highlight = options.highlight ?? true;
2673
+ try {
2674
+ let data = globalThis.JSON.parse(json);
2675
+ if (sortKeys && typeof data === "object" && data !== null) {
2676
+ data = this.sortObject(data);
2677
+ }
2678
+ this.text = globalThis.JSON.stringify(data, null, indent);
2679
+ } catch {
2680
+ this.text = json;
2681
+ }
2682
+ }
2683
+ /**
2684
+ * Create JSON from any data object.
2685
+ */
2686
+ static fromData(data, options = {}) {
2687
+ const { indent = 2, sortKeys = false } = options;
2688
+ let processedData = data;
2689
+ if (sortKeys && typeof data === "object" && data !== null) {
2690
+ processedData = _JSON.prototype.sortObject(data);
2691
+ }
2692
+ const json = globalThis.JSON.stringify(processedData, null, indent);
2693
+ const instance = new _JSON(json, { ...options, sortKeys: false });
2694
+ return instance;
2695
+ }
2696
+ sortObject(obj) {
2697
+ if (Array.isArray(obj)) {
2698
+ return obj.map((item) => this.sortObject(item));
2699
+ }
2700
+ if (obj !== null && typeof obj === "object") {
2701
+ const sorted = {};
2702
+ const keys = Object.keys(obj).sort();
2703
+ for (const key of keys) {
2704
+ sorted[key] = this.sortObject(obj[key]);
2705
+ }
2706
+ return sorted;
2707
+ }
2708
+ return obj;
2709
+ }
2710
+ /**
2711
+ * Apply JSON syntax highlighting.
2712
+ */
2713
+ highlightJSON(text) {
2714
+ if (!this.highlight) {
2715
+ return text;
2716
+ }
2717
+ const highlighted = text.replace(/"([^"\\]|\\.)*"/g, (match) => {
2718
+ return Style.parse("#f1fa8c").apply(match);
2719
+ }).replace(/\b(-?\d+\.?\d*(?:e[+-]?\d+)?)\b/gi, (match) => {
2720
+ return Style.parse("#bd93f9").apply(match);
2721
+ }).replace(/\b(true|false)\b/g, (match) => {
2722
+ return match === "true" ? Style.parse("#50fa7b").apply(match) : Style.parse("#ff79c6").apply(match);
2723
+ }).replace(/\bnull\b/g, (match) => {
2724
+ return Style.parse("#8be9fd italic").apply(match);
2725
+ });
2726
+ return highlighted;
2727
+ }
2728
+ __rich_console__(_console, _consoleOptions) {
2729
+ const highlighted = this.highlightJSON(this.text);
2730
+ return {
2731
+ segments: [new Segment(highlighted + "\n", Style.null())],
2732
+ width: this.text.split("\n").reduce((max, line) => Math.max(max, line.length), 0)
2733
+ };
2734
+ }
2735
+ };
2271
2736
  var Prompt = class {
2272
2737
  static async ask(message, options = {}) {
2273
2738
  const console = options.console ?? new Console();
@@ -2422,6 +2887,9 @@ var ProgressBar = class {
2422
2887
  this.completed = completed;
2423
2888
  this.options = options;
2424
2889
  }
2890
+ render(_arg0) {
2891
+ throw new Error("Method not implemented.");
2892
+ }
2425
2893
  pulseOffset = 0;
2426
2894
  lastPulseTime = 0;
2427
2895
  __rich_console__(console, consoleOptions) {
@@ -2551,13 +3019,10 @@ var TimeRemainingColumn = class {
2551
3019
  // src/progress/progress.ts
2552
3020
  var Progress = class {
2553
3021
  tasks = [];
2554
- live;
2555
- console;
2556
3022
  taskIdCounter = 0;
2557
- constructor(options = {}) {
2558
- this.console = options.console ?? new Console();
2559
- this.live = new Live(new Layout(), this.console);
2560
- }
3023
+ started = false;
3024
+ refreshInterval = null;
3025
+ lastRenderedLines = 0;
2561
3026
  addTask(description, options = {}) {
2562
3027
  const taskId = this.taskIdCounter++;
2563
3028
  this.tasks.push({
@@ -2585,27 +3050,50 @@ var Progress = class {
2585
3050
  this.refresh();
2586
3051
  }
2587
3052
  start() {
2588
- this.live.start();
3053
+ if (this.started) return;
3054
+ this.started = true;
3055
+ process.stdout.write("\x1B[?25l");
3056
+ this.refreshInterval = setInterval(() => this.refresh(), 100);
3057
+ this.refresh();
2589
3058
  }
2590
3059
  stop() {
2591
- this.live.stop();
3060
+ if (!this.started) return;
3061
+ if (this.refreshInterval) {
3062
+ clearInterval(this.refreshInterval);
3063
+ this.refreshInterval = null;
3064
+ }
3065
+ process.stdout.write("\x1B[?25h");
3066
+ this.started = false;
2592
3067
  }
2593
3068
  refresh() {
2594
- const layout = new Layout();
2595
- const children = this.tasks.filter((t) => t.visible).map((task) => {
2596
- const row = new Layout();
2597
- row.splitRow(
2598
- new Text(task.description, void 0, "right"),
2599
- // Label
2600
- new ProgressBar(task.total, task.completed),
2601
- // Bar
2602
- new Text(`${Math.floor(task.completed / task.total * 100)}%`)
2603
- // Percent
2604
- );
2605
- return row;
2606
- });
2607
- layout.splitColumn(...children);
2608
- this.live.update(layout);
3069
+ if (!this.started) return;
3070
+ if (this.lastRenderedLines > 0) {
3071
+ process.stdout.write(`\x1B[${this.lastRenderedLines}A`);
3072
+ for (let i = 0; i < this.lastRenderedLines; i++) {
3073
+ process.stdout.write("\x1B[2K\n");
3074
+ }
3075
+ process.stdout.write(`\x1B[${this.lastRenderedLines}A`);
3076
+ }
3077
+ const lines = [];
3078
+ for (const task of this.tasks.filter((t) => t.visible)) {
3079
+ const percent = Math.floor(task.completed / task.total * 100);
3080
+ const barStr = this.renderSimpleBar(task.completed, task.total, 30);
3081
+ const percentStyle = percent >= 100 ? Style.parse("#50fa7b bold") : Style.parse("#61afef");
3082
+ lines.push(`${task.description.padEnd(20)} ${barStr} ${percentStyle.apply(`${percent}%`)}`);
3083
+ }
3084
+ const output = lines.join("\n") + "\n";
3085
+ this.lastRenderedLines = lines.length;
3086
+ process.stdout.write(output);
3087
+ }
3088
+ renderSimpleBar(completed, total, width) {
3089
+ const percentage = Math.min(1, Math.max(0, completed / total));
3090
+ const filledWidth = Math.floor(width * percentage);
3091
+ const remainingWidth = width - filledWidth;
3092
+ const filledStyle = percentage >= 1 ? Style.parse("#50fa7b bold") : Style.parse("#61afef");
3093
+ const remainingStyle = Style.parse("#3a3a3a dim");
3094
+ const filled = filledStyle.apply("\u2501".repeat(filledWidth));
3095
+ const remaining = remainingStyle.apply("\u2501".repeat(remainingWidth));
3096
+ return filled + remaining;
2609
3097
  }
2610
3098
  };
2611
3099
 
@@ -2626,6 +3114,293 @@ function* track(sequence, description = "Working...") {
2626
3114
  }
2627
3115
  }
2628
3116
 
3117
+ // src/live/live.ts
3118
+ var Live = class {
3119
+ transient;
3120
+ started = false;
3121
+ refreshThread = null;
3122
+ lastRenderedLines = 0;
3123
+ currentContent = "";
3124
+ constructor(options = {}) {
3125
+ this.transient = options.transient ?? false;
3126
+ }
3127
+ /**
3128
+ * Check if live display is currently running.
3129
+ */
3130
+ get isStarted() {
3131
+ return this.started;
3132
+ }
3133
+ /**
3134
+ * Update the displayed content.
3135
+ */
3136
+ update(content) {
3137
+ this.currentContent = content;
3138
+ }
3139
+ /**
3140
+ * Refresh the display with current content.
3141
+ */
3142
+ refresh() {
3143
+ if (!this.started) return;
3144
+ if (this.lastRenderedLines > 0) {
3145
+ process.stdout.write(`\x1B[${this.lastRenderedLines}A`);
3146
+ for (let i = 0; i < this.lastRenderedLines; i++) {
3147
+ process.stdout.write("\x1B[2K\n");
3148
+ }
3149
+ process.stdout.write(`\x1B[${this.lastRenderedLines}A`);
3150
+ }
3151
+ this.lastRenderedLines = (this.currentContent.match(/\n/g) || []).length + 1;
3152
+ process.stdout.write(`${this.currentContent}
3153
+ `);
3154
+ }
3155
+ /**
3156
+ * Start live display with a callback function.
3157
+ * The callback receives an update function to change the displayed content.
3158
+ */
3159
+ async start(callback) {
3160
+ if (this.started) {
3161
+ throw new Error("Live display already started");
3162
+ }
3163
+ this.started = true;
3164
+ process.stdout.write("\x1B[?25l");
3165
+ const updateFn = (content) => {
3166
+ this.currentContent = content;
3167
+ this.refresh();
3168
+ };
3169
+ try {
3170
+ await callback(updateFn);
3171
+ } finally {
3172
+ this.stop();
3173
+ }
3174
+ }
3175
+ /**
3176
+ * Stop live display.
3177
+ */
3178
+ stop() {
3179
+ if (!this.started) return;
3180
+ if (this.refreshThread) {
3181
+ clearInterval(this.refreshThread);
3182
+ this.refreshThread = null;
3183
+ }
3184
+ process.stdout.write("\x1B[?25h");
3185
+ if (this.transient && this.lastRenderedLines > 0) {
3186
+ process.stdout.write(`\x1B[${this.lastRenderedLines}A`);
3187
+ for (let i = 0; i < this.lastRenderedLines; i++) {
3188
+ process.stdout.write("\x1B[2K\n");
3189
+ }
3190
+ process.stdout.write(`\x1B[${this.lastRenderedLines}A`);
3191
+ }
3192
+ this.started = false;
3193
+ }
3194
+ };
3195
+ function sleep(ms) {
3196
+ return new Promise((resolve) => setTimeout(resolve, ms));
3197
+ }
3198
+
3199
+ // src/utils/emoji.ts
3200
+ var EMOJI = {
3201
+ // Common emojis
3202
+ rocket: "\u{1F680}",
3203
+ star: "\u2B50",
3204
+ sparkles: "\u2728",
3205
+ fire: "\u{1F525}",
3206
+ heart: "\u2764\uFE0F",
3207
+ thumbs_up: "\u{1F44D}",
3208
+ thumbs_down: "\u{1F44E}",
3209
+ clap: "\u{1F44F}",
3210
+ wave: "\u{1F44B}",
3211
+ ok_hand: "\u{1F44C}",
3212
+ // Faces
3213
+ smile: "\u{1F60A}",
3214
+ grin: "\u{1F601}",
3215
+ joy: "\u{1F602}",
3216
+ wink: "\u{1F609}",
3217
+ thinking: "\u{1F914}",
3218
+ sunglasses: "\u{1F60E}",
3219
+ heart_eyes: "\u{1F60D}",
3220
+ sob: "\u{1F62D}",
3221
+ angry: "\u{1F620}",
3222
+ scream: "\u{1F631}",
3223
+ skull: "\u{1F480}",
3224
+ ghost: "\u{1F47B}",
3225
+ robot: "\u{1F916}",
3226
+ // Status
3227
+ check: "\u2705",
3228
+ check_mark: "\u2714\uFE0F",
3229
+ x: "\u274C",
3230
+ cross_mark: "\u274C",
3231
+ warning: "\u26A0\uFE0F",
3232
+ exclamation: "\u2757",
3233
+ question: "\u2753",
3234
+ info: "\u2139\uFE0F",
3235
+ bulb: "\u{1F4A1}",
3236
+ gear: "\u2699\uFE0F",
3237
+ wrench: "\u{1F527}",
3238
+ hammer: "\u{1F528}",
3239
+ bug: "\u{1F41B}",
3240
+ construction: "\u{1F6A7}",
3241
+ // Weather & Nature
3242
+ sun: "\u2600\uFE0F",
3243
+ moon: "\u{1F319}",
3244
+ cloud: "\u2601\uFE0F",
3245
+ rain: "\u{1F327}\uFE0F",
3246
+ snow: "\u2744\uFE0F",
3247
+ thunder: "\u26A1",
3248
+ rainbow: "\u{1F308}",
3249
+ tree: "\u{1F333}",
3250
+ flower: "\u{1F338}",
3251
+ leaf: "\u{1F343}",
3252
+ // Objects
3253
+ book: "\u{1F4D6}",
3254
+ books: "\u{1F4DA}",
3255
+ pencil: "\u270F\uFE0F",
3256
+ pen: "\u{1F58A}\uFE0F",
3257
+ clipboard: "\u{1F4CB}",
3258
+ folder: "\u{1F4C1}",
3259
+ file_folder: "\u{1F4C1}",
3260
+ package: "\u{1F4E6}",
3261
+ inbox: "\u{1F4E5}",
3262
+ outbox: "\u{1F4E4}",
3263
+ email: "\u{1F4E7}",
3264
+ computer: "\u{1F4BB}",
3265
+ keyboard: "\u2328\uFE0F",
3266
+ phone: "\u{1F4F1}",
3267
+ camera: "\u{1F4F7}",
3268
+ video_camera: "\u{1F4F9}",
3269
+ clock: "\u{1F550}",
3270
+ hourglass: "\u23F3",
3271
+ key: "\u{1F511}",
3272
+ lock: "\u{1F512}",
3273
+ unlock: "\u{1F513}",
3274
+ link: "\u{1F517}",
3275
+ trophy: "\u{1F3C6}",
3276
+ medal: "\u{1F3C5}",
3277
+ crown: "\u{1F451}",
3278
+ gem: "\u{1F48E}",
3279
+ money: "\u{1F4B0}",
3280
+ coin: "\u{1FA99}",
3281
+ // Arrows & Symbols
3282
+ arrow_right: "\u27A1\uFE0F",
3283
+ arrow_left: "\u2B05\uFE0F",
3284
+ arrow_up: "\u2B06\uFE0F",
3285
+ arrow_down: "\u2B07\uFE0F",
3286
+ arrow_forward: "\u25B6\uFE0F",
3287
+ arrow_backward: "\u25C0\uFE0F",
3288
+ play: "\u25B6\uFE0F",
3289
+ pause: "\u23F8\uFE0F",
3290
+ stop: "\u23F9\uFE0F",
3291
+ refresh: "\u{1F504}",
3292
+ plus: "\u2795",
3293
+ minus: "\u2796",
3294
+ // Animals
3295
+ dog: "\u{1F415}",
3296
+ cat: "\u{1F408}",
3297
+ bird: "\u{1F426}",
3298
+ fish: "\u{1F41F}",
3299
+ butterfly: "\u{1F98B}",
3300
+ bee: "\u{1F41D}",
3301
+ snake: "\u{1F40D}",
3302
+ turtle: "\u{1F422}",
3303
+ crab: "\u{1F980}",
3304
+ octopus: "\u{1F419}",
3305
+ unicorn: "\u{1F984}",
3306
+ dragon: "\u{1F409}",
3307
+ // Food & Drink
3308
+ coffee: "\u2615",
3309
+ tea: "\u{1F375}",
3310
+ beer: "\u{1F37A}",
3311
+ wine: "\u{1F377}",
3312
+ pizza: "\u{1F355}",
3313
+ burger: "\u{1F354}",
3314
+ fries: "\u{1F35F}",
3315
+ taco: "\u{1F32E}",
3316
+ sushi: "\u{1F363}",
3317
+ apple: "\u{1F34E}",
3318
+ banana: "\u{1F34C}",
3319
+ cake: "\u{1F382}",
3320
+ cookie: "\u{1F36A}",
3321
+ // Celebrations
3322
+ party: "\u{1F389}",
3323
+ balloon: "\u{1F388}",
3324
+ confetti: "\u{1F38A}",
3325
+ gift: "\u{1F381}",
3326
+ christmas_tree: "\u{1F384}",
3327
+ fireworks: "\u{1F386}",
3328
+ // Hands
3329
+ point_up: "\u261D\uFE0F",
3330
+ point_down: "\u{1F447}",
3331
+ point_left: "\u{1F448}",
3332
+ point_right: "\u{1F449}",
3333
+ raised_hand: "\u270B",
3334
+ fist: "\u270A",
3335
+ v: "\u270C\uFE0F",
3336
+ muscle: "\u{1F4AA}",
3337
+ pray: "\u{1F64F}",
3338
+ // Transport
3339
+ car: "\u{1F697}",
3340
+ bus: "\u{1F68C}",
3341
+ train: "\u{1F686}",
3342
+ plane: "\u2708\uFE0F",
3343
+ ship: "\u{1F6A2}",
3344
+ bike: "\u{1F6B2}",
3345
+ // Places
3346
+ house: "\u{1F3E0}",
3347
+ office: "\u{1F3E2}",
3348
+ hospital: "\u{1F3E5}",
3349
+ school: "\u{1F3EB}",
3350
+ globe: "\u{1F30D}",
3351
+ earth: "\u{1F30D}",
3352
+ earth_americas: "\u{1F30E}",
3353
+ earth_asia: "\u{1F30F}",
3354
+ // Colors
3355
+ red_circle: "\u{1F534}",
3356
+ orange_circle: "\u{1F7E0}",
3357
+ yellow_circle: "\u{1F7E1}",
3358
+ green_circle: "\u{1F7E2}",
3359
+ blue_circle: "\u{1F535}",
3360
+ purple_circle: "\u{1F7E3}",
3361
+ white_circle: "\u26AA",
3362
+ black_circle: "\u26AB",
3363
+ // Misc
3364
+ zap: "\u26A1",
3365
+ boom: "\u{1F4A5}",
3366
+ hundred: "\u{1F4AF}",
3367
+ zzz: "\u{1F4A4}",
3368
+ speech_balloon: "\u{1F4AC}",
3369
+ thought_balloon: "\u{1F4AD}",
3370
+ mega: "\u{1F4E3}",
3371
+ bell: "\u{1F514}",
3372
+ pin: "\u{1F4CC}",
3373
+ scissors: "\u2702\uFE0F",
3374
+ art: "\u{1F3A8}",
3375
+ music: "\u{1F3B5}",
3376
+ notes: "\u{1F3B6}",
3377
+ mic: "\u{1F3A4}",
3378
+ headphones: "\u{1F3A7}",
3379
+ game: "\u{1F3AE}",
3380
+ dice: "\u{1F3B2}",
3381
+ // Programming
3382
+ terminal: "\u{1F4BB}",
3383
+ code: "\u{1F4BB}",
3384
+ database: "\u{1F5C4}\uFE0F",
3385
+ api: "\u{1F50C}",
3386
+ test_tube: "\u{1F9EA}",
3387
+ microscope: "\u{1F52C}",
3388
+ satellite: "\u{1F6F0}\uFE0F",
3389
+ atom: "\u269B\uFE0F"
3390
+ };
3391
+ function replaceEmoji(text) {
3392
+ return text.replace(/:([a-z0-9_]+):/gi, (match, name) => {
3393
+ const emoji = EMOJI[name.toLowerCase()];
3394
+ return emoji ?? match;
3395
+ });
3396
+ }
3397
+ function listEmoji() {
3398
+ return Object.keys(EMOJI);
3399
+ }
3400
+ function hasEmoji(name) {
3401
+ return name.toLowerCase() in EMOJI;
3402
+ }
3403
+
2629
3404
  // src/logging/logger.ts
2630
3405
  var Logger = class {
2631
3406
  handler;
@@ -2690,13 +3465,17 @@ var print = globalConsole.print.bind(globalConsole);
2690
3465
 
2691
3466
  exports.Align = Align;
2692
3467
  exports.Color = Color;
3468
+ exports.Columns = Columns;
2693
3469
  exports.Confirm = Confirm;
2694
3470
  exports.Console = Console;
2695
3471
  exports.DEFAULT_THEME = DEFAULT_THEME;
2696
3472
  exports.DRACULA = DRACULA;
3473
+ exports.EMOJI = EMOJI;
2697
3474
  exports.GITHUB_LIGHT = GITHUB_LIGHT;
2698
3475
  exports.Grid = Grid;
3476
+ exports.JSON = JSON2;
2699
3477
  exports.Layout = Layout;
3478
+ exports.Live = Live;
2700
3479
  exports.Logger = Logger;
2701
3480
  exports.MONOKAI = MONOKAI;
2702
3481
  exports.MONOKAI_THEME = MONOKAI_THEME;
@@ -2712,6 +3491,7 @@ exports.ProgressBar = ProgressBar;
2712
3491
  exports.Prompt = Prompt;
2713
3492
  exports.RichHandler = RichHandler;
2714
3493
  exports.Rule = Rule;
3494
+ exports.SPINNERS = SPINNERS;
2715
3495
  exports.SYNTAX_THEMES = SYNTAX_THEMES;
2716
3496
  exports.Segment = Segment;
2717
3497
  exports.Spinner = Spinner;
@@ -2726,13 +3506,20 @@ exports.TimeRemainingColumn = TimeRemainingColumn;
2726
3506
  exports.Traceback = Traceback;
2727
3507
  exports.Tree = Tree;
2728
3508
  exports.getBox = getBox;
3509
+ exports.getSpinner = getSpinner;
3510
+ exports.getSpinnerNames = listSpinners;
2729
3511
  exports.getTheme = getTheme;
3512
+ exports.hasEmoji = hasEmoji;
2730
3513
  exports.inspect = inspect;
2731
3514
  exports.install = install;
2732
3515
  exports.installTracebackHandler = installTracebackHandler;
2733
3516
  exports.isRenderable = isRenderable;
2734
3517
  exports.listBoxStyles = listBoxStyles;
3518
+ exports.listEmoji = listEmoji;
3519
+ exports.listSpinners = listSpinners2;
2735
3520
  exports.print = print;
3521
+ exports.replaceEmoji = replaceEmoji;
3522
+ exports.sleep = sleep;
2736
3523
  exports.track = track;
2737
3524
  //# sourceMappingURL=index.cjs.map
2738
3525
  //# sourceMappingURL=index.cjs.map