composer require sugarcraft/sugar-chartsPHP port of NimbleMarkets/ntcharts β terminal charts for SugarCraft. v0 ships the canvas foundation plus three self-contained chart types.
use SugarCraft\Charts\Sparkline\Sparkline;
use SugarCraft\Charts\BarChart\BarChart;
use SugarCraft\Charts\LineChart\LineChart;
echo Sparkline::new([1, 3, 2, 8, 5, 4, 7, 6], 8)->view() . PHP_EOL;
// βββββ
βββ
echo BarChart::new([['cpu', 0.7], ['mem', 0.4], ['disk', 0.9]], 20, 5)->view() . PHP_EOL;
// 0.9 β€ β β
// 0.7 β€β β β
// 0.4 β€β β β
// βββββββββ
// cpu mem disk
echo LineChart::new([1, 4, 2, 8, 6, 3, 7], 30, 6)->view() . PHP_EOL;Charts also expose short-form aliases on the most-used setters:
data/size/min/max/point/xRange/yRange/colors/palette/bars/barWidth/showLabels/showAxis, etc. The upstream-mirroringwith*long forms still work; pick the form that reads best at the call site.
| Component | Role | Notable knobs |
|---|---|---|
Charts\Canvas\Canvas |
Fixed-size cell grid; each cell holds a rune + optional Sprinkles Style. |
setCell / setLines / setString / setRunes / fill / fillLine / shiftUp / shiftDown / shiftLeft / shiftRight / setCellStyle / getCellStyle |
Charts\Canvas\BrailleGrid |
Sub-cell scratch buffer (2 cols Γ 4 rows of dots per cell). Paint dots, then copy to a Canvas. |
set / unset / toggle / isSet / rune / paint(Canvas, x0, y0, ?Style) / clear |
Charts\Canvas\Graph |
Drawing primitives over a Canvas. |
drawHLine / drawVLine / drawXYAxis / drawXYAxisLabel / drawString / drawLine / drawLinePoints / fillRect / drawColumn / drawColumns / drawRows / drawCandlestick / drawBrailleRune / drawBraillePatterns / drawVerticalLineUp / drawVerticalLineDown / drawHorizontalLineLeft / drawHorizontalLineRight / getCirclePoints / getCirclePointsWithLimit / getFullCirclePoints / getFullCirclePointsWithLimit / getLinePointsWithLimit |
Charts\Sparkline\Sparkline |
Single-row series renderer using the 8 Unicode bar glyphs. | push / pushAll / clear / withMin / withMax / withStyle(?Style) / withNoAutoMaxValue(bool) / withWidth |
Charts\BarChart\BarChart |
Labeled vertical bars; auto-scales to a configurable min / max. | withBarWidth / withBarGap / withNoAutoBarWidth / push(Bar|array) / pushAll(iterable) / clear |
Charts\LineChart\LineChart |
Single-series ASCII plot drawn onto a Canvas with configurable axes. | withYRange / withXRange / withXYRange / autoAdjustRange / withXLabelFormatter / withYLabelFormatter / withAxes / withXLabels / withYLabels / withCanvas / withTheme / withFill |
Charts\LineChart\TimeSeries |
LineChart variant accepting [\DateTimeImmutable, value] tuples. |
push / withPoints / withTimeFormat / withXLabelCount / withTimeRange(?start, ?end) / getTimeRange() |
Charts\LineChart\Streamline |
Single-row streaming line β auto-windowed to width. | push / pushAll / clear / withSize / withMin / withMax / withYRange |
Charts\LineChart\Wavelinechart |
XY scatter / wave plot driven by (x, y) pairs. |
push / pushAll / clear / withSize / withXRange / withYRange / withXYRange / withPoint |
Charts\Heatmap\Heatmap |
2D grid coloured by value with optional palette / legend. | withSize / withMin / withMax / withPalette / withLegend / withColors(cold, hot) / withColorProfile / withCellStyle(?Style) / withAutoValueRange(bool) / pushPoint(HeatPoint) / pushAll |
Charts\OHLC\OHLC |
Candlestick chart for (high, open, close, low) rows. |
withSize / withCandleStyle / withWickStyle |
Charts\Scatter\Scatter |
XY scatter plot. | push / pushAll / withSize / withMin / withMax |
Charts\Aggregation\BucketByTime |
Groups timestamped values into time buckets with configurable aggregation. | sum / mean / min / max / first / last factory methods + add / addMany / compute |
Charts\Aggregation\MovingAverage |
Sliding-window aggregator β SMA and EMA. | simple / centered / ema static factories + add / addMany / computeSimple / values / clear |
Charts\Aggregation\Resample |
Upsample or downsample timestamped series to a target cadence. | last / mean / linear / nearest factories + resample auto-detection |
Charts\Picture\Picture |
Inline image renderer (Sixel today; Kitty / iTerm2 protocols pending). | withFromFile / withDimensions / view |
Aggregation classes process raw time-series data before charting:
use SugarCraft\Charts\Aggregation\{BucketByTime, MovingAverage, Resample};
// BucketByTime: group into 1-hour buckets, sum values per bucket.
$buckets = BucketByTime::sum(3600, [
['ts' => strtotime('2024-01-01 00:10'), 'value' => 10],
['ts' => strtotime('2024-01-01 00:45'), 'value' => 15],
['ts' => strtotime('2024-01-01 01:05'), 'value' => 20],
]);
// β [{ts: 0, value: 25}, {ts: 3600, value: 20}]
// MovingAverage: 3-point SMA and EMA.
$sma = MovingAverage::simple(3, [1, 4, 2, 8, 6]);
// β [0.0, 0.0, 2.33β¦, 4.67β¦, 5.33β¦]
$ema = MovingAverage::ema(3, [1, 4, 2, 8, 6]);
// β [1.0, 2.5, 2.25, 5.13, 5.56]
// Resample: downsample to 30-second cadence (last value), or upsample (linear interp).
$down = Resample::last(30, $timestampedData);
$up = Resample::linear(30, $timestampedData);Charts support high-resolution dot-matrix (braille) rendering via
SugarCraft\Dash\Plot\Braille\BrailleCanvas. Pass a BrailleCanvas
instance via withCanvas() to switch from character-cell to 2Γ4
sub-cell resolution:
use SugarCraft\Charts\LineChart\LineChart;
use SugarCraft\Dash\Plot\Braille\BrailleCanvas;
$canvas = new BrailleCanvas(80, 24);
$chart = LineChart::new([1, 4, 2, 8, 6], 80, 24)
->withCanvas($canvas);
echo $chart->view();Charts inherit candy-sprinkles
Theme palette support via withTheme(). All Theme:: factory methods
are supported:
use SugarCraft\Charts\LineChart\LineChart;
use SugarCraft\Sprinkles\Theme;
$chart = LineChart::new([3, 1, 4, 1, 5, 9, 2, 6], 40, 8)
->withTheme(Theme::dracula())
->withLegend();
echo $chart->view();Available themes: Theme::ansi() / Theme::dark() / Theme::light() /
Theme::dracula() / Theme::tokyoNight() / Theme::oneDark() /
Theme::githubDark() / Theme::solarizedDark() / Theme::solarizedLight().
All chart renderers build their output via candy-buffer.
Do not re-implement string padding or cell-grid assembly β use the Buffer class directly.
Graph is a static-method utility β every draw call takes a Canvas
plus coordinates in canvas (cell) space (top-left origin). Pair with
BrailleGrid for sub-cell precision:
use SugarCraft\Charts\Canvas\{Canvas, BrailleGrid, Graph};
$canvas = new Canvas(40, 8);
Graph::drawXYAxis($canvas, 1, 6, 38);
Graph::drawString($canvas, 4, 0, 'Demo');
// Sub-cell line via BrailleGrid.
$grid = new BrailleGrid(38, 6);
foreach (Graph::getLinePointsWithLimit(0, 0, 75, 23, limit: 200) as [$x, $y]) {
$grid->set($x, $y);
}
$grid->paint($canvas, 1, 0);
echo $canvas->view();Heatmap::withPalette([Color, β¦]) interpolates between an arbitrary
number of stops (β₯ 2). withColors(Color $cold, Color $hot) is the
two-stop shortcut. withColorProfile(ColorProfile) overrides the
auto-detected output profile when piping to non-tty / Sixel-capable
sinks. Heatmap::withCellStyle(Style) overlays additional attributes
(bold / background / etc.) on top of every cell's foreground gradient.
| Component | State |
|---|---|
| Canvas, BrailleGrid, Graph primitives | π’ v1 |
| Sparkline | π’ v1 |
| BarChart | π’ v1 (multi-bar grouped datasets pending) |
| LineChart | π’ v1 (zoom/pan + dataset styles pending) |
| TimeSeries | π’ v1 (multi-dataset + update-handler variants pending) |
| Streamline, Wavelinechart | π’ v1 |
| Heatmap | π’ v1 (default-color-scale getter/setter pending) |
| OHLC | π‘ candlestick rendering only β volume sub-pane + multi-series pending |
| Scatter | π‘ single-dataset only β per-point rune/style sets pending |
| Picture | π‘ Sixel renderer only β Kitty graphics protocol + iTerm2 inline + half-block fallback pending |
Render output is covered by golden-file snapshot tests. Fixture files live
in tests/fixtures/ with a .golden extension and are compared against
actual ANSI byte output via SugarCraft\Testing\Snapshot\Assertions::assertGoldenAnsi().
To re-record fixtures after intentional output changes:
UPDATE_GOLDENS=1 vendor/bin/phpunitcd sugar-charts && composer install && vendor/bin/phpunit- SugarCraft monorepo
- Upstream: NimbleMarkets/ntcharts







