@ggterm/core 0.2.11 → 0.2.12
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/cli-plot.js +642 -0
- package/dist/cli.js +608 -0
- package/dist/geoms/braille.d.ts +39 -0
- package/dist/geoms/braille.d.ts.map +1 -0
- package/dist/geoms/bullet.d.ts +37 -0
- package/dist/geoms/bullet.d.ts.map +1 -0
- package/dist/geoms/dumbbell.d.ts +36 -0
- package/dist/geoms/dumbbell.d.ts.map +1 -0
- package/dist/geoms/index.d.ts +6 -0
- package/dist/geoms/index.d.ts.map +1 -1
- package/dist/geoms/lollipop.d.ts +35 -0
- package/dist/geoms/lollipop.d.ts.map +1 -0
- package/dist/geoms/sparkline.d.ts +36 -0
- package/dist/geoms/sparkline.d.ts.map +1 -0
- package/dist/geoms/waffle.d.ts +36 -0
- package/dist/geoms/waffle.d.ts.map +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +628 -0
- package/dist/pipeline/render-geoms.d.ts +31 -0
- package/dist/pipeline/render-geoms.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2360,6 +2360,469 @@ function renderGeomBeeswarm(data, geom, aes, scales, canvas) {
|
|
|
2360
2360
|
}
|
|
2361
2361
|
}
|
|
2362
2362
|
}
|
|
2363
|
+
function renderGeomDumbbell(data, geom, aes, scales, canvas) {
|
|
2364
|
+
const lineColor = parseColorToRgba(geom.params.lineColor ?? "#666666");
|
|
2365
|
+
const alpha = geom.params.alpha ?? 1;
|
|
2366
|
+
const shape = getPointShape(geom.params.shape);
|
|
2367
|
+
const plotLeft = Math.round(scales.x.range[0]);
|
|
2368
|
+
const plotRight = Math.round(scales.x.range[1]);
|
|
2369
|
+
const plotTop = Math.round(Math.min(scales.y.range[0], scales.y.range[1]));
|
|
2370
|
+
const plotBottom = Math.round(Math.max(scales.y.range[0], scales.y.range[1]));
|
|
2371
|
+
const defaultColors = [
|
|
2372
|
+
{ r: 79, g: 169, b: 238, a: 1 },
|
|
2373
|
+
{ r: 238, g: 136, b: 102, a: 1 },
|
|
2374
|
+
{ r: 102, g: 204, b: 153, a: 1 },
|
|
2375
|
+
{ r: 204, g: 102, b: 204, a: 1 }
|
|
2376
|
+
];
|
|
2377
|
+
for (let i = 0;i < data.length; i++) {
|
|
2378
|
+
const row = data[i];
|
|
2379
|
+
const xVal = row[aes.x];
|
|
2380
|
+
const xendVal = row["xend"] ?? row[aes.x];
|
|
2381
|
+
const yVal = row[aes.y];
|
|
2382
|
+
if (xVal === null || xVal === undefined || yVal === null || yVal === undefined) {
|
|
2383
|
+
continue;
|
|
2384
|
+
}
|
|
2385
|
+
const x1 = Math.round(scales.x.map(xVal));
|
|
2386
|
+
const x2 = Math.round(scales.x.map(xendVal));
|
|
2387
|
+
const cy = Math.round(scales.y.map(yVal));
|
|
2388
|
+
let startColor;
|
|
2389
|
+
let endColor;
|
|
2390
|
+
if (geom.params.color) {
|
|
2391
|
+
startColor = parseColorToRgba(geom.params.color);
|
|
2392
|
+
} else if (scales.color && aes.color) {
|
|
2393
|
+
startColor = getPointColor(row, aes, scales.color);
|
|
2394
|
+
} else {
|
|
2395
|
+
startColor = defaultColors[0];
|
|
2396
|
+
}
|
|
2397
|
+
if (geom.params.colorEnd) {
|
|
2398
|
+
endColor = parseColorToRgba(geom.params.colorEnd);
|
|
2399
|
+
} else {
|
|
2400
|
+
endColor = geom.params.color ? startColor : defaultColors[1];
|
|
2401
|
+
}
|
|
2402
|
+
if (alpha < 1) {
|
|
2403
|
+
startColor = { ...startColor, a: alpha };
|
|
2404
|
+
endColor = { ...endColor, a: alpha };
|
|
2405
|
+
}
|
|
2406
|
+
if (cy >= plotTop && cy <= plotBottom) {
|
|
2407
|
+
const left = Math.max(plotLeft, Math.min(x1, x2));
|
|
2408
|
+
const right = Math.min(plotRight, Math.max(x1, x2));
|
|
2409
|
+
for (let x = left;x <= right; x++) {
|
|
2410
|
+
canvas.drawChar(x, cy, "─", lineColor);
|
|
2411
|
+
}
|
|
2412
|
+
}
|
|
2413
|
+
if (x1 >= plotLeft && x1 <= plotRight && cy >= plotTop && cy <= plotBottom) {
|
|
2414
|
+
canvas.drawChar(x1, cy, shape, startColor);
|
|
2415
|
+
}
|
|
2416
|
+
if (x2 >= plotLeft && x2 <= plotRight && cy >= plotTop && cy <= plotBottom) {
|
|
2417
|
+
canvas.drawChar(x2, cy, shape, endColor);
|
|
2418
|
+
}
|
|
2419
|
+
}
|
|
2420
|
+
}
|
|
2421
|
+
function renderGeomLollipop(data, geom, aes, scales, canvas) {
|
|
2422
|
+
const alpha = geom.params.alpha ?? 1;
|
|
2423
|
+
const baseline = geom.params.baseline ?? 0;
|
|
2424
|
+
const direction = geom.params.direction ?? "vertical";
|
|
2425
|
+
const shape = getPointShape(geom.params.shape);
|
|
2426
|
+
const plotLeft = Math.round(scales.x.range[0]);
|
|
2427
|
+
const plotRight = Math.round(scales.x.range[1]);
|
|
2428
|
+
const plotTop = Math.round(Math.min(scales.y.range[0], scales.y.range[1]));
|
|
2429
|
+
const plotBottom = Math.round(Math.max(scales.y.range[0], scales.y.range[1]));
|
|
2430
|
+
const defaultColors = [
|
|
2431
|
+
{ r: 79, g: 169, b: 238, a: 1 },
|
|
2432
|
+
{ r: 238, g: 136, b: 102, a: 1 },
|
|
2433
|
+
{ r: 102, g: 204, b: 153, a: 1 },
|
|
2434
|
+
{ r: 204, g: 102, b: 204, a: 1 },
|
|
2435
|
+
{ r: 255, g: 200, b: 87, a: 1 },
|
|
2436
|
+
{ r: 138, g: 201, b: 222, a: 1 }
|
|
2437
|
+
];
|
|
2438
|
+
const xValues = [...new Set(data.map((row) => row[aes.x]))];
|
|
2439
|
+
for (let i = 0;i < data.length; i++) {
|
|
2440
|
+
const row = data[i];
|
|
2441
|
+
const xVal = row[aes.x];
|
|
2442
|
+
const yVal = row[aes.y];
|
|
2443
|
+
if (xVal === null || xVal === undefined || yVal === null || yVal === undefined) {
|
|
2444
|
+
continue;
|
|
2445
|
+
}
|
|
2446
|
+
const cx = Math.round(scales.x.map(xVal));
|
|
2447
|
+
const cy = Math.round(scales.y.map(yVal));
|
|
2448
|
+
let color;
|
|
2449
|
+
if (geom.params.color) {
|
|
2450
|
+
color = parseColorToRgba(geom.params.color);
|
|
2451
|
+
} else if (scales.color && aes.color) {
|
|
2452
|
+
color = getPointColor(row, aes, scales.color);
|
|
2453
|
+
} else {
|
|
2454
|
+
const categoryIdx = xValues.indexOf(xVal);
|
|
2455
|
+
color = defaultColors[categoryIdx % defaultColors.length];
|
|
2456
|
+
}
|
|
2457
|
+
let lineColor;
|
|
2458
|
+
if (geom.params.lineColor) {
|
|
2459
|
+
lineColor = parseColorToRgba(geom.params.lineColor);
|
|
2460
|
+
} else {
|
|
2461
|
+
lineColor = {
|
|
2462
|
+
r: Math.round(color.r * 0.7),
|
|
2463
|
+
g: Math.round(color.g * 0.7),
|
|
2464
|
+
b: Math.round(color.b * 0.7),
|
|
2465
|
+
a: color.a
|
|
2466
|
+
};
|
|
2467
|
+
}
|
|
2468
|
+
if (alpha < 1) {
|
|
2469
|
+
color = { ...color, a: alpha };
|
|
2470
|
+
lineColor = { ...lineColor, a: alpha };
|
|
2471
|
+
}
|
|
2472
|
+
if (direction === "vertical") {
|
|
2473
|
+
let baselineY = Math.round(scales.y.map(baseline));
|
|
2474
|
+
baselineY = Math.max(plotTop, Math.min(plotBottom, baselineY));
|
|
2475
|
+
if (cx >= plotLeft && cx <= plotRight) {
|
|
2476
|
+
const top = Math.min(cy, baselineY);
|
|
2477
|
+
const bottom = Math.max(cy, baselineY);
|
|
2478
|
+
for (let y = top;y <= bottom; y++) {
|
|
2479
|
+
if (y >= plotTop && y <= plotBottom) {
|
|
2480
|
+
canvas.drawChar(cx, y, "│", lineColor);
|
|
2481
|
+
}
|
|
2482
|
+
}
|
|
2483
|
+
}
|
|
2484
|
+
if (cx >= plotLeft && cx <= plotRight && cy >= plotTop && cy <= plotBottom) {
|
|
2485
|
+
canvas.drawChar(cx, cy, shape, color);
|
|
2486
|
+
}
|
|
2487
|
+
} else {
|
|
2488
|
+
let baselineX = Math.round(scales.x.map(baseline));
|
|
2489
|
+
baselineX = Math.max(plotLeft, Math.min(plotRight, baselineX));
|
|
2490
|
+
if (cy >= plotTop && cy <= plotBottom) {
|
|
2491
|
+
const left = Math.min(cx, baselineX);
|
|
2492
|
+
const right = Math.max(cx, baselineX);
|
|
2493
|
+
for (let x = left;x <= right; x++) {
|
|
2494
|
+
if (x >= plotLeft && x <= plotRight) {
|
|
2495
|
+
canvas.drawChar(x, cy, "─", lineColor);
|
|
2496
|
+
}
|
|
2497
|
+
}
|
|
2498
|
+
}
|
|
2499
|
+
if (cx >= plotLeft && cx <= plotRight && cy >= plotTop && cy <= plotBottom) {
|
|
2500
|
+
canvas.drawChar(cx, cy, shape, color);
|
|
2501
|
+
}
|
|
2502
|
+
}
|
|
2503
|
+
}
|
|
2504
|
+
}
|
|
2505
|
+
function renderGeomWaffle(data, geom, aes, scales, canvas) {
|
|
2506
|
+
const rows = geom.params.rows ?? 10;
|
|
2507
|
+
const cols = geom.params.cols ?? 10;
|
|
2508
|
+
const fillChar = geom.params.fill_char ?? "█";
|
|
2509
|
+
const emptyChar = geom.params.empty_char ?? "░";
|
|
2510
|
+
const showLegend = geom.params.show_legend ?? true;
|
|
2511
|
+
const flip = geom.params.flip ?? false;
|
|
2512
|
+
const gap = geom.params.gap ?? 0;
|
|
2513
|
+
const plotLeft = Math.round(scales.x.range[0]);
|
|
2514
|
+
const plotRight = Math.round(scales.x.range[1]);
|
|
2515
|
+
const plotTop = Math.round(Math.min(scales.y.range[0], scales.y.range[1]));
|
|
2516
|
+
const plotBottom = Math.round(Math.max(scales.y.range[0], scales.y.range[1]));
|
|
2517
|
+
const defaultColors = [
|
|
2518
|
+
{ r: 79, g: 169, b: 238, a: 1 },
|
|
2519
|
+
{ r: 238, g: 136, b: 102, a: 1 },
|
|
2520
|
+
{ r: 102, g: 204, b: 153, a: 1 },
|
|
2521
|
+
{ r: 204, g: 102, b: 204, a: 1 },
|
|
2522
|
+
{ r: 255, g: 200, b: 87, a: 1 },
|
|
2523
|
+
{ r: 138, g: 201, b: 222, a: 1 },
|
|
2524
|
+
{ r: 255, g: 153, b: 153, a: 1 },
|
|
2525
|
+
{ r: 170, g: 170, b: 170, a: 1 }
|
|
2526
|
+
];
|
|
2527
|
+
const fillField = aes.fill || aes.color || "category";
|
|
2528
|
+
const valueField = aes.y || "value";
|
|
2529
|
+
const categories = new Map;
|
|
2530
|
+
let totalValue = 0;
|
|
2531
|
+
for (const row of data) {
|
|
2532
|
+
const cat = String(row[fillField] ?? "default");
|
|
2533
|
+
const val = Number(row[valueField]) || 1;
|
|
2534
|
+
categories.set(cat, (categories.get(cat) ?? 0) + val);
|
|
2535
|
+
totalValue += val;
|
|
2536
|
+
}
|
|
2537
|
+
const cellsPerCategory = [];
|
|
2538
|
+
const categoryList = [...categories.keys()];
|
|
2539
|
+
let cellsAssigned = 0;
|
|
2540
|
+
for (let i = 0;i < categoryList.length; i++) {
|
|
2541
|
+
const cat = categoryList[i];
|
|
2542
|
+
const val = categories.get(cat);
|
|
2543
|
+
const proportion = val / totalValue;
|
|
2544
|
+
const cells = Math.round(proportion * rows * cols);
|
|
2545
|
+
const color = scales.color?.map(cat) ?? defaultColors[i % defaultColors.length];
|
|
2546
|
+
cellsPerCategory.push({ category: cat, cells, color });
|
|
2547
|
+
cellsAssigned += cells;
|
|
2548
|
+
}
|
|
2549
|
+
if (cellsAssigned < rows * cols && cellsPerCategory.length > 0) {
|
|
2550
|
+
cellsPerCategory[0].cells += rows * cols - cellsAssigned;
|
|
2551
|
+
}
|
|
2552
|
+
const grid = [];
|
|
2553
|
+
for (const { cells, color } of cellsPerCategory) {
|
|
2554
|
+
for (let i = 0;i < cells; i++) {
|
|
2555
|
+
grid.push({ char: fillChar, color });
|
|
2556
|
+
}
|
|
2557
|
+
}
|
|
2558
|
+
const emptyColor = { r: 80, g: 80, b: 80, a: 0.3 };
|
|
2559
|
+
while (grid.length < rows * cols) {
|
|
2560
|
+
grid.push({ char: emptyChar, color: emptyColor });
|
|
2561
|
+
}
|
|
2562
|
+
const availableWidth = plotRight - plotLeft - (showLegend ? 15 : 0);
|
|
2563
|
+
const availableHeight = plotBottom - plotTop;
|
|
2564
|
+
const cellWidth = Math.max(1, Math.floor(availableWidth / cols)) + gap;
|
|
2565
|
+
const cellHeight = Math.max(1, Math.floor(availableHeight / rows)) + gap;
|
|
2566
|
+
for (let row = 0;row < rows; row++) {
|
|
2567
|
+
for (let col = 0;col < cols; col++) {
|
|
2568
|
+
let idx;
|
|
2569
|
+
if (flip) {
|
|
2570
|
+
idx = row * cols + col;
|
|
2571
|
+
} else {
|
|
2572
|
+
idx = col * rows + (rows - 1 - row);
|
|
2573
|
+
}
|
|
2574
|
+
if (idx >= grid.length)
|
|
2575
|
+
continue;
|
|
2576
|
+
const cell = grid[idx];
|
|
2577
|
+
const x = plotLeft + col * cellWidth;
|
|
2578
|
+
const y = plotTop + row * cellHeight;
|
|
2579
|
+
if (x >= plotLeft && x < plotRight - (showLegend ? 15 : 0) && y >= plotTop && y <= plotBottom) {
|
|
2580
|
+
canvas.drawChar(x, y, cell.char, cell.color);
|
|
2581
|
+
}
|
|
2582
|
+
}
|
|
2583
|
+
}
|
|
2584
|
+
if (showLegend) {
|
|
2585
|
+
const legendX = plotRight - 12;
|
|
2586
|
+
let legendY = plotTop;
|
|
2587
|
+
for (let i = 0;i < cellsPerCategory.length && legendY < plotBottom; i++) {
|
|
2588
|
+
const { category, cells, color } = cellsPerCategory[i];
|
|
2589
|
+
const pct = Math.round(cells / (rows * cols) * 100);
|
|
2590
|
+
const label = `${category.slice(0, 6)} ${pct}%`;
|
|
2591
|
+
canvas.drawChar(legendX, legendY, "█", color);
|
|
2592
|
+
canvas.drawString(legendX + 2, legendY, label, { r: 180, g: 180, b: 180, a: 1 });
|
|
2593
|
+
legendY += 2;
|
|
2594
|
+
}
|
|
2595
|
+
}
|
|
2596
|
+
}
|
|
2597
|
+
function renderGeomSparkline(data, geom, aes, scales, canvas) {
|
|
2598
|
+
const sparkType = geom.params.sparkType ?? "bar";
|
|
2599
|
+
const width = geom.params.width ?? 20;
|
|
2600
|
+
const showMinmax = geom.params.show_minmax ?? false;
|
|
2601
|
+
const normalize = geom.params.normalize ?? true;
|
|
2602
|
+
const minColor = parseColorToRgba(geom.params.min_color ?? "#e74c3c");
|
|
2603
|
+
const maxColor = parseColorToRgba(geom.params.max_color ?? "#2ecc71");
|
|
2604
|
+
const plotLeft = Math.round(scales.x.range[0]);
|
|
2605
|
+
const plotTop = Math.round(Math.min(scales.y.range[0], scales.y.range[1]));
|
|
2606
|
+
const plotBottom = Math.round(Math.max(scales.y.range[0], scales.y.range[1]));
|
|
2607
|
+
const SPARK_CHARS = ["▁", "▂", "▃", "▄", "▅", "▆", "▇", "█"];
|
|
2608
|
+
const defaultColor = { r: 79, g: 169, b: 238, a: 1 };
|
|
2609
|
+
const groupField = aes.group || aes.color;
|
|
2610
|
+
const groups = new Map;
|
|
2611
|
+
if (groupField) {
|
|
2612
|
+
for (const row of data) {
|
|
2613
|
+
const key = String(row[groupField] ?? "default");
|
|
2614
|
+
if (!groups.has(key))
|
|
2615
|
+
groups.set(key, []);
|
|
2616
|
+
groups.get(key).push(row);
|
|
2617
|
+
}
|
|
2618
|
+
} else {
|
|
2619
|
+
groups.set("default", [...data]);
|
|
2620
|
+
}
|
|
2621
|
+
let currentY = plotTop;
|
|
2622
|
+
for (const [groupKey, groupData] of groups) {
|
|
2623
|
+
const sorted = aes.x ? [...groupData].sort((a, b) => Number(a[aes.x]) - Number(b[aes.x])) : groupData;
|
|
2624
|
+
const values = sorted.map((row) => Number(row[aes.y]) || 0);
|
|
2625
|
+
if (values.length === 0)
|
|
2626
|
+
continue;
|
|
2627
|
+
const minVal = Math.min(...values);
|
|
2628
|
+
const maxVal = Math.max(...values);
|
|
2629
|
+
const minIdx = values.indexOf(minVal);
|
|
2630
|
+
const maxIdx = values.indexOf(maxVal);
|
|
2631
|
+
const range = maxVal - minVal || 1;
|
|
2632
|
+
const color = scales.color?.map(groupKey) ?? defaultColor;
|
|
2633
|
+
const sparkValues = [];
|
|
2634
|
+
if (values.length <= width) {
|
|
2635
|
+
sparkValues.push(...values);
|
|
2636
|
+
} else {
|
|
2637
|
+
for (let i = 0;i < width; i++) {
|
|
2638
|
+
const idx = Math.floor(i * values.length / width);
|
|
2639
|
+
sparkValues.push(values[idx]);
|
|
2640
|
+
}
|
|
2641
|
+
}
|
|
2642
|
+
for (let i = 0;i < sparkValues.length; i++) {
|
|
2643
|
+
const val = sparkValues[i];
|
|
2644
|
+
const normalized = normalize ? (val - minVal) / range : val / (maxVal || 1);
|
|
2645
|
+
const charIdx = Math.min(7, Math.max(0, Math.floor(normalized * 8)));
|
|
2646
|
+
const char = sparkType === "dot" ? "•" : SPARK_CHARS[charIdx];
|
|
2647
|
+
const x = plotLeft + i;
|
|
2648
|
+
const y = currentY;
|
|
2649
|
+
let pointColor = color;
|
|
2650
|
+
if (showMinmax) {
|
|
2651
|
+
const origIdx = Math.floor(i * values.length / sparkValues.length);
|
|
2652
|
+
if (origIdx === minIdx)
|
|
2653
|
+
pointColor = minColor;
|
|
2654
|
+
else if (origIdx === maxIdx)
|
|
2655
|
+
pointColor = maxColor;
|
|
2656
|
+
}
|
|
2657
|
+
if (x < plotLeft + width && y >= plotTop && y <= plotBottom) {
|
|
2658
|
+
canvas.drawChar(x, y, char, pointColor);
|
|
2659
|
+
}
|
|
2660
|
+
}
|
|
2661
|
+
if (groupField && groups.size > 1) {
|
|
2662
|
+
const labelX = plotLeft + width + 1;
|
|
2663
|
+
canvas.drawString(labelX, currentY, groupKey.slice(0, 8), { r: 180, g: 180, b: 180, a: 1 });
|
|
2664
|
+
}
|
|
2665
|
+
currentY += 2;
|
|
2666
|
+
}
|
|
2667
|
+
}
|
|
2668
|
+
function renderGeomBullet(data, geom, aes, scales, canvas) {
|
|
2669
|
+
const width = geom.params.width ?? 40;
|
|
2670
|
+
const targetChar = geom.params.target_char ?? "│";
|
|
2671
|
+
const barChar = geom.params.bar_char ?? "█";
|
|
2672
|
+
const rangeChars = geom.params.range_chars ?? ["░", "▒", "▓"];
|
|
2673
|
+
const showValues = geom.params.show_values ?? true;
|
|
2674
|
+
const targetColor = parseColorToRgba(geom.params.target_color ?? "#e74c3c");
|
|
2675
|
+
const plotLeft = Math.round(scales.x.range[0]);
|
|
2676
|
+
const plotTop = Math.round(Math.min(scales.y.range[0], scales.y.range[1]));
|
|
2677
|
+
const plotBottom = Math.round(Math.max(scales.y.range[0], scales.y.range[1]));
|
|
2678
|
+
const defaultColors = [
|
|
2679
|
+
{ r: 79, g: 169, b: 238, a: 1 },
|
|
2680
|
+
{ r: 238, g: 136, b: 102, a: 1 },
|
|
2681
|
+
{ r: 102, g: 204, b: 153, a: 1 }
|
|
2682
|
+
];
|
|
2683
|
+
const rangeColors = [
|
|
2684
|
+
{ r: 60, g: 60, b: 60, a: 1 },
|
|
2685
|
+
{ r: 90, g: 90, b: 90, a: 1 },
|
|
2686
|
+
{ r: 120, g: 120, b: 120, a: 1 }
|
|
2687
|
+
];
|
|
2688
|
+
let currentY = plotTop;
|
|
2689
|
+
for (let i = 0;i < data.length; i++) {
|
|
2690
|
+
const row = data[i];
|
|
2691
|
+
const label = aes.x ? String(row[aes.x]).slice(0, 10) : `Item ${i + 1}`;
|
|
2692
|
+
const value = Number(row[aes.y]) || 0;
|
|
2693
|
+
const target = Number(row["target"]) || null;
|
|
2694
|
+
const maxValue = Number(row["max"]) || Math.max(value, target || 0) * 1.2;
|
|
2695
|
+
const ranges = row["ranges"] ?? [maxValue * 0.6, maxValue * 0.8, maxValue];
|
|
2696
|
+
const color = scales.color?.map(label) ?? defaultColors[i % defaultColors.length];
|
|
2697
|
+
const labelWidth = 12;
|
|
2698
|
+
canvas.drawString(plotLeft, currentY, label.padEnd(labelWidth), { r: 180, g: 180, b: 180, a: 1 });
|
|
2699
|
+
const barStart = plotLeft + labelWidth;
|
|
2700
|
+
const barWidth = Math.min(width, scales.x.range[1] - barStart - (showValues ? 8 : 0));
|
|
2701
|
+
for (let r = ranges.length - 1;r >= 0; r--) {
|
|
2702
|
+
const rangeWidth = Math.round(ranges[r] / maxValue * barWidth);
|
|
2703
|
+
for (let x = 0;x < rangeWidth; x++) {
|
|
2704
|
+
if (barStart + x <= scales.x.range[1]) {
|
|
2705
|
+
canvas.drawChar(barStart + x, currentY, rangeChars[r], rangeColors[r]);
|
|
2706
|
+
}
|
|
2707
|
+
}
|
|
2708
|
+
}
|
|
2709
|
+
const valueWidth = Math.round(value / maxValue * barWidth);
|
|
2710
|
+
for (let x = 0;x < valueWidth; x++) {
|
|
2711
|
+
if (barStart + x <= scales.x.range[1]) {
|
|
2712
|
+
canvas.drawChar(barStart + x, currentY, barChar, color);
|
|
2713
|
+
}
|
|
2714
|
+
}
|
|
2715
|
+
if (target !== null) {
|
|
2716
|
+
const targetX = barStart + Math.round(target / maxValue * barWidth);
|
|
2717
|
+
if (targetX >= barStart && targetX <= barStart + barWidth) {
|
|
2718
|
+
canvas.drawChar(targetX, currentY, targetChar, targetColor);
|
|
2719
|
+
}
|
|
2720
|
+
}
|
|
2721
|
+
if (showValues) {
|
|
2722
|
+
const valueStr = value.toFixed(0);
|
|
2723
|
+
canvas.drawString(barStart + barWidth + 2, currentY, valueStr, { r: 180, g: 180, b: 180, a: 1 });
|
|
2724
|
+
}
|
|
2725
|
+
currentY += 2;
|
|
2726
|
+
if (currentY > plotBottom)
|
|
2727
|
+
break;
|
|
2728
|
+
}
|
|
2729
|
+
}
|
|
2730
|
+
function renderGeomBraille(data, geom, aes, scales, canvas) {
|
|
2731
|
+
const brailleType = geom.params.brailleType ?? "point";
|
|
2732
|
+
const fill = geom.params.fill ?? false;
|
|
2733
|
+
const alpha = geom.params.alpha ?? 1;
|
|
2734
|
+
const BRAILLE_BASE = 10240;
|
|
2735
|
+
const DOTS = [
|
|
2736
|
+
[1, 2, 4, 64],
|
|
2737
|
+
[8, 16, 32, 128]
|
|
2738
|
+
];
|
|
2739
|
+
const plotLeft = Math.round(scales.x.range[0]);
|
|
2740
|
+
const plotRight = Math.round(scales.x.range[1]);
|
|
2741
|
+
const plotTop = Math.round(Math.min(scales.y.range[0], scales.y.range[1]));
|
|
2742
|
+
const plotBottom = Math.round(Math.max(scales.y.range[0], scales.y.range[1]));
|
|
2743
|
+
const plotWidth = plotRight - plotLeft;
|
|
2744
|
+
const plotHeight = plotBottom - plotTop;
|
|
2745
|
+
const brailleWidth = plotWidth;
|
|
2746
|
+
const brailleHeight = plotHeight;
|
|
2747
|
+
const buffer = [];
|
|
2748
|
+
for (let y = 0;y < brailleHeight; y++) {
|
|
2749
|
+
buffer[y] = new Array(brailleWidth).fill(0);
|
|
2750
|
+
}
|
|
2751
|
+
const defaultColor = { r: 79, g: 169, b: 238, a: 1 };
|
|
2752
|
+
const color = geom.params.color ? parseColorToRgba(geom.params.color) : defaultColor;
|
|
2753
|
+
const finalColor = alpha < 1 ? { ...color, a: alpha } : color;
|
|
2754
|
+
const sorted = aes.x ? [...data].sort((a, b) => Number(a[aes.x]) - Number(b[aes.x])) : data;
|
|
2755
|
+
const setDot = (canvasX, canvasY) => {
|
|
2756
|
+
const subX = (canvasX - plotLeft) * 2;
|
|
2757
|
+
const subY = (canvasY - plotTop) * 4;
|
|
2758
|
+
const cellX = Math.floor(subX / 2);
|
|
2759
|
+
const cellY = Math.floor(subY / 4);
|
|
2760
|
+
const dotCol = subX % 2;
|
|
2761
|
+
const dotRow = subY % 4;
|
|
2762
|
+
if (cellX >= 0 && cellX < brailleWidth && cellY >= 0 && cellY < brailleHeight) {
|
|
2763
|
+
if (dotCol >= 0 && dotCol < 2 && dotRow >= 0 && dotRow < 4) {
|
|
2764
|
+
buffer[cellY][cellX] |= DOTS[dotCol][dotRow];
|
|
2765
|
+
}
|
|
2766
|
+
}
|
|
2767
|
+
};
|
|
2768
|
+
let prevCx = null;
|
|
2769
|
+
let prevCy = null;
|
|
2770
|
+
for (const row of sorted) {
|
|
2771
|
+
const xVal = row[aes.x];
|
|
2772
|
+
const yVal = row[aes.y];
|
|
2773
|
+
if (xVal === null || xVal === undefined || yVal === null || yVal === undefined) {
|
|
2774
|
+
prevCx = null;
|
|
2775
|
+
prevCy = null;
|
|
2776
|
+
continue;
|
|
2777
|
+
}
|
|
2778
|
+
const cx = Math.round(scales.x.map(xVal));
|
|
2779
|
+
const cy = Math.round(scales.y.map(yVal));
|
|
2780
|
+
if (brailleType === "line" && prevCx !== null && prevCy !== null) {
|
|
2781
|
+
const dx = Math.abs(cx - prevCx);
|
|
2782
|
+
const dy = Math.abs(cy - prevCy);
|
|
2783
|
+
const sx = prevCx < cx ? 1 : -1;
|
|
2784
|
+
const sy = prevCy < cy ? 1 : -1;
|
|
2785
|
+
let err = dx - dy;
|
|
2786
|
+
let x = prevCx;
|
|
2787
|
+
let y = prevCy;
|
|
2788
|
+
while (true) {
|
|
2789
|
+
if (x >= plotLeft && x < plotRight && y >= plotTop && y < plotBottom) {
|
|
2790
|
+
setDot(x, y);
|
|
2791
|
+
if (fill) {
|
|
2792
|
+
for (let fy = y;fy < plotBottom; fy++) {
|
|
2793
|
+
setDot(x, fy);
|
|
2794
|
+
}
|
|
2795
|
+
}
|
|
2796
|
+
}
|
|
2797
|
+
if (x === cx && y === cy)
|
|
2798
|
+
break;
|
|
2799
|
+
const e2 = 2 * err;
|
|
2800
|
+
if (e2 > -dy) {
|
|
2801
|
+
err -= dy;
|
|
2802
|
+
x += sx;
|
|
2803
|
+
}
|
|
2804
|
+
if (e2 < dx) {
|
|
2805
|
+
err += dx;
|
|
2806
|
+
y += sy;
|
|
2807
|
+
}
|
|
2808
|
+
}
|
|
2809
|
+
} else {
|
|
2810
|
+
if (cx >= plotLeft && cx < plotRight && cy >= plotTop && cy < plotBottom) {
|
|
2811
|
+
setDot(cx, cy);
|
|
2812
|
+
}
|
|
2813
|
+
}
|
|
2814
|
+
prevCx = cx;
|
|
2815
|
+
prevCy = cy;
|
|
2816
|
+
}
|
|
2817
|
+
for (let y = 0;y < brailleHeight; y++) {
|
|
2818
|
+
for (let x = 0;x < brailleWidth; x++) {
|
|
2819
|
+
if (buffer[y][x] > 0) {
|
|
2820
|
+
const char = String.fromCharCode(BRAILLE_BASE + buffer[y][x]);
|
|
2821
|
+
canvas.drawChar(plotLeft + x, plotTop + y, char, finalColor);
|
|
2822
|
+
}
|
|
2823
|
+
}
|
|
2824
|
+
}
|
|
2825
|
+
}
|
|
2363
2826
|
function renderGeom(data, geom, aes, scales, canvas, coordType) {
|
|
2364
2827
|
switch (geom.type) {
|
|
2365
2828
|
case "point":
|
|
@@ -2445,6 +2908,24 @@ function renderGeom(data, geom, aes, scales, canvas, coordType) {
|
|
|
2445
2908
|
case "quasirandom":
|
|
2446
2909
|
renderGeomBeeswarm(data, geom, aes, scales, canvas);
|
|
2447
2910
|
break;
|
|
2911
|
+
case "dumbbell":
|
|
2912
|
+
renderGeomDumbbell(data, geom, aes, scales, canvas);
|
|
2913
|
+
break;
|
|
2914
|
+
case "lollipop":
|
|
2915
|
+
renderGeomLollipop(data, geom, aes, scales, canvas);
|
|
2916
|
+
break;
|
|
2917
|
+
case "waffle":
|
|
2918
|
+
renderGeomWaffle(data, geom, aes, scales, canvas);
|
|
2919
|
+
break;
|
|
2920
|
+
case "sparkline":
|
|
2921
|
+
renderGeomSparkline(data, geom, aes, scales, canvas);
|
|
2922
|
+
break;
|
|
2923
|
+
case "bullet":
|
|
2924
|
+
renderGeomBullet(data, geom, aes, scales, canvas);
|
|
2925
|
+
break;
|
|
2926
|
+
case "braille":
|
|
2927
|
+
renderGeomBraille(data, geom, aes, scales, canvas);
|
|
2928
|
+
break;
|
|
2448
2929
|
default:
|
|
2449
2930
|
break;
|
|
2450
2931
|
}
|
|
@@ -5817,9 +6298,136 @@ function geom_quasirandom(options = {}) {
|
|
|
5817
6298
|
return geom_beeswarm({ ...options, method: "center" });
|
|
5818
6299
|
}
|
|
5819
6300
|
|
|
6301
|
+
// src/geoms/dumbbell.ts
|
|
6302
|
+
function geom_dumbbell(options = {}) {
|
|
6303
|
+
return {
|
|
6304
|
+
type: "dumbbell",
|
|
6305
|
+
stat: "identity",
|
|
6306
|
+
position: "identity",
|
|
6307
|
+
params: {
|
|
6308
|
+
size: options.size ?? 2,
|
|
6309
|
+
sizeEnd: options.sizeEnd ?? options.size ?? 2,
|
|
6310
|
+
color: options.color,
|
|
6311
|
+
colorEnd: options.colorEnd ?? options.color,
|
|
6312
|
+
lineColor: options.lineColor ?? "#666666",
|
|
6313
|
+
lineWidth: options.lineWidth ?? 1,
|
|
6314
|
+
alpha: options.alpha ?? 1,
|
|
6315
|
+
shape: options.shape ?? "circle"
|
|
6316
|
+
}
|
|
6317
|
+
};
|
|
6318
|
+
}
|
|
6319
|
+
|
|
6320
|
+
// src/geoms/lollipop.ts
|
|
6321
|
+
function geom_lollipop(options = {}) {
|
|
6322
|
+
return {
|
|
6323
|
+
type: "lollipop",
|
|
6324
|
+
stat: "identity",
|
|
6325
|
+
position: "identity",
|
|
6326
|
+
params: {
|
|
6327
|
+
size: options.size ?? 2,
|
|
6328
|
+
color: options.color,
|
|
6329
|
+
lineColor: options.lineColor,
|
|
6330
|
+
lineWidth: options.lineWidth ?? 1,
|
|
6331
|
+
alpha: options.alpha ?? 1,
|
|
6332
|
+
shape: options.shape ?? "circle",
|
|
6333
|
+
direction: options.direction ?? "vertical",
|
|
6334
|
+
baseline: options.baseline ?? 0
|
|
6335
|
+
}
|
|
6336
|
+
};
|
|
6337
|
+
}
|
|
6338
|
+
|
|
6339
|
+
// src/geoms/waffle.ts
|
|
6340
|
+
function geom_waffle(options = {}) {
|
|
6341
|
+
return {
|
|
6342
|
+
type: "waffle",
|
|
6343
|
+
stat: "identity",
|
|
6344
|
+
position: "identity",
|
|
6345
|
+
params: {
|
|
6346
|
+
rows: options.rows ?? 10,
|
|
6347
|
+
cols: options.cols ?? 10,
|
|
6348
|
+
n_total: options.n_total ?? 100,
|
|
6349
|
+
fill_char: options.fill_char ?? "█",
|
|
6350
|
+
empty_char: options.empty_char ?? "░",
|
|
6351
|
+
alpha: options.alpha ?? 1,
|
|
6352
|
+
show_legend: options.show_legend ?? true,
|
|
6353
|
+
flip: options.flip ?? false,
|
|
6354
|
+
gap: options.gap ?? 0
|
|
6355
|
+
}
|
|
6356
|
+
};
|
|
6357
|
+
}
|
|
6358
|
+
|
|
6359
|
+
// src/geoms/sparkline.ts
|
|
6360
|
+
function geom_sparkline(options = {}) {
|
|
6361
|
+
return {
|
|
6362
|
+
type: "sparkline",
|
|
6363
|
+
stat: "identity",
|
|
6364
|
+
position: "identity",
|
|
6365
|
+
params: {
|
|
6366
|
+
sparkType: options.type ?? "bar",
|
|
6367
|
+
width: options.width ?? 20,
|
|
6368
|
+
height: options.height ?? 1,
|
|
6369
|
+
show_minmax: options.show_minmax ?? false,
|
|
6370
|
+
color: options.color,
|
|
6371
|
+
min_color: options.min_color ?? "#e74c3c",
|
|
6372
|
+
max_color: options.max_color ?? "#2ecc71",
|
|
6373
|
+
normalize: options.normalize ?? true
|
|
6374
|
+
}
|
|
6375
|
+
};
|
|
6376
|
+
}
|
|
6377
|
+
var SPARK_BARS, SPARK_DOTS;
|
|
6378
|
+
var init_sparkline = __esm(() => {
|
|
6379
|
+
SPARK_BARS = ["▁", "▂", "▃", "▄", "▅", "▆", "▇", "█"];
|
|
6380
|
+
SPARK_DOTS = ["⠀", "⢀", "⢠", "⢰", "⢸", "⣸", "⣾", "⣿"];
|
|
6381
|
+
});
|
|
6382
|
+
|
|
6383
|
+
// src/geoms/bullet.ts
|
|
6384
|
+
function geom_bullet(options = {}) {
|
|
6385
|
+
return {
|
|
6386
|
+
type: "bullet",
|
|
6387
|
+
stat: "identity",
|
|
6388
|
+
position: "identity",
|
|
6389
|
+
params: {
|
|
6390
|
+
width: options.width ?? 40,
|
|
6391
|
+
height: options.height ?? 1,
|
|
6392
|
+
target_char: options.target_char ?? "│",
|
|
6393
|
+
bar_char: options.bar_char ?? "█",
|
|
6394
|
+
range_chars: options.range_chars ?? ["░", "▒", "▓"],
|
|
6395
|
+
show_values: options.show_values ?? true,
|
|
6396
|
+
color: options.color,
|
|
6397
|
+
target_color: options.target_color ?? "#e74c3c",
|
|
6398
|
+
orientation: options.orientation ?? "horizontal"
|
|
6399
|
+
}
|
|
6400
|
+
};
|
|
6401
|
+
}
|
|
6402
|
+
|
|
6403
|
+
// src/geoms/braille.ts
|
|
6404
|
+
function geom_braille(options = {}) {
|
|
6405
|
+
return {
|
|
6406
|
+
type: "braille",
|
|
6407
|
+
stat: "identity",
|
|
6408
|
+
position: "identity",
|
|
6409
|
+
params: {
|
|
6410
|
+
brailleType: options.type ?? "point",
|
|
6411
|
+
color: options.color,
|
|
6412
|
+
fill: options.fill ?? false,
|
|
6413
|
+
alpha: options.alpha ?? 1,
|
|
6414
|
+
dot_size: options.dot_size ?? 1
|
|
6415
|
+
}
|
|
6416
|
+
};
|
|
6417
|
+
}
|
|
6418
|
+
var BRAILLE_BASE = 10240, BRAILLE_DOTS;
|
|
6419
|
+
var init_braille = __esm(() => {
|
|
6420
|
+
BRAILLE_DOTS = [
|
|
6421
|
+
[1, 2, 4, 64],
|
|
6422
|
+
[8, 16, 32, 128]
|
|
6423
|
+
];
|
|
6424
|
+
});
|
|
6425
|
+
|
|
5820
6426
|
// src/geoms/index.ts
|
|
5821
6427
|
var init_geoms = __esm(() => {
|
|
5822
6428
|
init_ridgeline();
|
|
6429
|
+
init_sparkline();
|
|
6430
|
+
init_braille();
|
|
5823
6431
|
});
|
|
5824
6432
|
|
|
5825
6433
|
// src/stats/index.ts
|
|
@@ -10322,11 +10930,13 @@ __export(exports_src, {
|
|
|
10322
10930
|
getColorEscape: () => getColorEscape,
|
|
10323
10931
|
getCapabilities: () => getCapabilities,
|
|
10324
10932
|
getAvailablePalettes: () => getAvailablePalettes,
|
|
10933
|
+
geom_waffle: () => geom_waffle,
|
|
10325
10934
|
geom_vline: () => geom_vline,
|
|
10326
10935
|
geom_violin: () => geom_violin,
|
|
10327
10936
|
geom_tile: () => geom_tile,
|
|
10328
10937
|
geom_text: () => geom_text,
|
|
10329
10938
|
geom_step: () => geom_step,
|
|
10939
|
+
geom_sparkline: () => geom_sparkline,
|
|
10330
10940
|
geom_smooth: () => geom_smooth,
|
|
10331
10941
|
geom_segment: () => geom_segment,
|
|
10332
10942
|
geom_rug: () => geom_rug,
|
|
@@ -10340,6 +10950,7 @@ __export(exports_src, {
|
|
|
10340
10950
|
geom_pointrange: () => geom_pointrange,
|
|
10341
10951
|
geom_point: () => geom_point,
|
|
10342
10952
|
geom_path: () => geom_path,
|
|
10953
|
+
geom_lollipop: () => geom_lollipop,
|
|
10343
10954
|
geom_linerange: () => geom_linerange,
|
|
10344
10955
|
geom_line: () => geom_line,
|
|
10345
10956
|
geom_label: () => geom_label,
|
|
@@ -10349,12 +10960,15 @@ __export(exports_src, {
|
|
|
10349
10960
|
geom_freqpoly: () => geom_freqpoly,
|
|
10350
10961
|
geom_errorbarh: () => geom_errorbarh,
|
|
10351
10962
|
geom_errorbar: () => geom_errorbar,
|
|
10963
|
+
geom_dumbbell: () => geom_dumbbell,
|
|
10352
10964
|
geom_density_2d: () => geom_density_2d,
|
|
10353
10965
|
geom_curve: () => geom_curve,
|
|
10354
10966
|
geom_crossbar: () => geom_crossbar,
|
|
10355
10967
|
geom_contour_filled: () => geom_contour_filled,
|
|
10356
10968
|
geom_contour: () => geom_contour,
|
|
10357
10969
|
geom_col: () => geom_col,
|
|
10970
|
+
geom_bullet: () => geom_bullet,
|
|
10971
|
+
geom_braille: () => geom_braille,
|
|
10358
10972
|
geom_boxplot: () => geom_boxplot,
|
|
10359
10973
|
geom_bin2d: () => geom_bin2d,
|
|
10360
10974
|
geom_beeswarm: () => geom_beeswarm,
|
|
@@ -10426,6 +11040,8 @@ __export(exports_src, {
|
|
|
10426
11040
|
annotate: () => annotate,
|
|
10427
11041
|
TerminalCanvas: () => TerminalCanvas,
|
|
10428
11042
|
StreamingPlot: () => StreamingPlot,
|
|
11043
|
+
SPARK_DOTS: () => SPARK_DOTS,
|
|
11044
|
+
SPARK_BARS: () => SPARK_BARS,
|
|
10429
11045
|
SHAPE_CHARS: () => SHAPE_CHARS,
|
|
10430
11046
|
RollingAggregator: () => RollingAggregator,
|
|
10431
11047
|
RendererChain: () => RendererChain,
|
|
@@ -10445,6 +11061,8 @@ __export(exports_src, {
|
|
|
10445
11061
|
DEFAULT_BG: () => DEFAULT_BG,
|
|
10446
11062
|
CanvasDiff: () => CanvasDiff,
|
|
10447
11063
|
Binner: () => Binner,
|
|
11064
|
+
BRAILLE_DOTS: () => BRAILLE_DOTS,
|
|
11065
|
+
BRAILLE_BASE: () => BRAILLE_BASE,
|
|
10448
11066
|
ANSI_16_COLORS: () => ANSI_16_COLORS
|
|
10449
11067
|
});
|
|
10450
11068
|
var init_src = __esm(() => {
|
|
@@ -10574,11 +11192,13 @@ export {
|
|
|
10574
11192
|
getColorEscape,
|
|
10575
11193
|
getCapabilities,
|
|
10576
11194
|
getAvailablePalettes,
|
|
11195
|
+
geom_waffle,
|
|
10577
11196
|
geom_vline,
|
|
10578
11197
|
geom_violin,
|
|
10579
11198
|
geom_tile,
|
|
10580
11199
|
geom_text,
|
|
10581
11200
|
geom_step,
|
|
11201
|
+
geom_sparkline,
|
|
10582
11202
|
geom_smooth,
|
|
10583
11203
|
geom_segment,
|
|
10584
11204
|
geom_rug,
|
|
@@ -10592,6 +11212,7 @@ export {
|
|
|
10592
11212
|
geom_pointrange,
|
|
10593
11213
|
geom_point,
|
|
10594
11214
|
geom_path,
|
|
11215
|
+
geom_lollipop,
|
|
10595
11216
|
geom_linerange,
|
|
10596
11217
|
geom_line,
|
|
10597
11218
|
geom_label,
|
|
@@ -10601,12 +11222,15 @@ export {
|
|
|
10601
11222
|
geom_freqpoly,
|
|
10602
11223
|
geom_errorbarh,
|
|
10603
11224
|
geom_errorbar,
|
|
11225
|
+
geom_dumbbell,
|
|
10604
11226
|
geom_density_2d,
|
|
10605
11227
|
geom_curve,
|
|
10606
11228
|
geom_crossbar,
|
|
10607
11229
|
geom_contour_filled,
|
|
10608
11230
|
geom_contour,
|
|
10609
11231
|
geom_col,
|
|
11232
|
+
geom_bullet,
|
|
11233
|
+
geom_braille,
|
|
10610
11234
|
geom_boxplot,
|
|
10611
11235
|
geom_bin2d,
|
|
10612
11236
|
geom_beeswarm,
|
|
@@ -10678,6 +11302,8 @@ export {
|
|
|
10678
11302
|
annotate,
|
|
10679
11303
|
TerminalCanvas,
|
|
10680
11304
|
StreamingPlot,
|
|
11305
|
+
SPARK_DOTS,
|
|
11306
|
+
SPARK_BARS,
|
|
10681
11307
|
SHAPE_CHARS,
|
|
10682
11308
|
RollingAggregator,
|
|
10683
11309
|
RendererChain,
|
|
@@ -10697,5 +11323,7 @@ export {
|
|
|
10697
11323
|
DEFAULT_BG,
|
|
10698
11324
|
CanvasDiff,
|
|
10699
11325
|
Binner,
|
|
11326
|
+
BRAILLE_DOTS,
|
|
11327
|
+
BRAILLE_BASE,
|
|
10700
11328
|
ANSI_16_COLORS
|
|
10701
11329
|
};
|