Search by

smronju / nativephp-charts

smronju

Native line, area, bar, scatter, candlestick, radar, pie, and doughnut charts for NativePHP Mobile — drawn on-device with SwiftUI Canvas / Jetpack Compose Canvas, no web view or JS charting library.

Package info

github.com/smronju/nativephp-charts

Type:nativephp-plugin

pkg:composer/smronju/nativephp-charts

Statistics

Installs: 6

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

1.1.0 2026-09-15 20:18 UTC

This package is auto-updated.

Last update: 2026-09-15 20:18:49 UTC


README

Native line, area, bar, scatter, candlestick, radar, pie, and doughnut charts for NativePHP Mobile — drawn on-device with SwiftUI Canvas (iOS) and Jetpack Compose Canvas (Android), the same drawing primitives core's own native:canvas/native:rect use. No web view, no bundled JS charting library, no third-party charting dependency on either platform.

Android-first: this plugin has been verified on a real Android device. iOS renders through the same code path but has not yet been verified on a real device or simulator — see iOS status before shipping an iOS build that uses it.

Documentation

Installation

composer require smronju/nativephp-charts
php artisan vendor:publish --tag=nativephp-plugins-provider
php artisan native:plugin:register smronju/nativephp-charts
php artisan native:plugin:list

Then rebuild with php artisan native:run.

Quick start

<native:chart> is a single self-closing element for every chart type — type picks the shape, series carries the data:

<native:chart
    type="line"
    :series="[
        ['values' => [120, 340, 200, 410], 'color' => theme('primary')],
        ['values' => [80, 150, 90, 60], 'color' => theme('secondary')],
    ]"
    class="w-full h-48"
/>

This element only draws shapes — no axis labels, no legend, no value formatting. Category labels and a legend are ordinary native:text alongside it, since the screen already has the same labels/series data in PHP to render those from:

<native:chart type="line" :series="$series" class="w-full h-48" />

<native:row class="w-full justify-between px-1">
    @foreach ($labels as $label)
        <native:text class="text-xs text-theme-on-surface-variant">{{ $label }}</native:text>
    @endforeach
</native:row>

Available chart types

Chart type Series data Reads
Line line values (one per shared category) Every series
Area area values (one per shared category) Every series — overlay fill only, not stacked
Bar bar values (one per shared category) Every series, as grouped bars
Scatter scatter points (a list of {x, y} pairs) Every series
Candlestick candlestick candles (a list of {open, high, low, close}) series[0] only
Radar radar values (one per axis, 3+ required) Every series
Pie pie values (one per slice) series[0] only
Doughnut doughnut values (one per slice) series[0] only

Every listed chart renders natively on Android via Jetpack Compose Canvas, and through the same code path on iOS via SwiftUI Canvas (see iOS status).

Chart examples

Line, area, and bar

Line, area, and bar all read values off every series, plotted index-for-index against a scale shared across every series (0 to the largest value anywhere), so multiple series stay visually comparable. Every series needs the same number of values.

{{-- Line --}}
<native:chart type="line" :series="[
    ['values' => [120, 340, 200, 410], 'color' => theme('primary')],
]" class="w-full h-48" />

{{-- Area — overlay only; series fill independently and semi-transparently, not stacked --}}
<native:chart type="area" :series="[
    ['values' => [42, 51, 62, 58], 'color' => '#2563EB'],
    ['values' => [28, 34, 40, 37], 'color' => '#F59E0B'],
]" class="w-full h-48" />

{{-- Bar — multiple series render as grouped bars per category --}}
<native:chart type="bar" :series="[
    ['values' => [42000, 51800], 'color' => '#7C3AED'],
    ['values' => [31000, 38600], 'color' => '#0F766E'],
]" class="w-full h-48" />

Scatter

Scatter reads points instead of values — real {x, y} coordinates, not evenly spaced categories. Both axes scale to the actual min/max across every series' points.

<native:chart type="scatter" :series="[[
    'points' => [
        ['x' => 1.2, 'y' => 0.34],
        ['x' => 2.8, 'y' => 0.47],
    ],
    'color' => '#2563EB',
]]" class="w-full h-48" />

Candlestick

Candlestick reads candles off series[0] only — a candlestick chart has exactly one instrument. Each candle needs open, high, low, and close; the body colors green when it closed at or above where it opened, red otherwise, unless overridden with rising-color/falling-color.

<native:chart
    type="candlestick"
    :series="[[
        'candles' => [
            ['open' => 36.72, 'high' => 36.91, 'low' => 36.68, 'close' => 36.84],
            ['open' => 36.84, 'high' => 36.88, 'low' => 36.70, 'close' => 36.76],
        ],
    ]]"
    rising-color="#15803D"
    falling-color="#B91C1C"
    class="w-full h-48"
/>

Radar

Radar reads values off every series too, but as one value per axis rather than per x position — every series needs at least 3 of them to form a polygon. It draws grid rings, axis spokes, and each series' filled polygon; it does not draw axis labels (see Scope).

<native:chart type="radar" :series="[[
    'values' => [88, 92, 74],
    'color' => '#6366F1',
]]" class="w-full h-48" />

Pie and doughnut

Both read only series[0]['values']; each value becomes one slice sized by its share of the total. series[0]['colors'] gives each slice its own color (falls back to the built-in palette, cycling by index, when omitted). Doughnut draws the same slices as a ring instead of a filled wedge.

<native:chart type="pie" :series="[[
    'values' => [58, 27, 15],
    'colors' => ['#7C3AED', '#2563EB', '#F59E0B'],
]]" class="w-full h-48" />

<native:chart type="doughnut" :series="[[
    'values' => [48200, 31750, 9650],
    'colors' => ['#2563EB', '#7C3AED', '#F59E0B'],
]]" class="w-full h-48" />

Colors

color (line/area/bar/scatter/radar — the whole series draws in one color) and colors (pie/doughnut — one per slice, parallel to values) accept anything a theme config value does — hex, #RRGGBBAA, a Tailwind palette name, an opacity modifier (primary/40) — resolved via the same theme()-driven element-prop resolver every other themed element uses. Omit color(s) entirely and each series falls back to a built-in six-color palette, cycling by index.

rising-color and falling-color are candlestick-only, defaulting to green and red when not set; every other chart type ignores them.

Scope

This element deliberately stays a shape-drawing surface, not a full charting system:

  • No axis labels, tick marks, or gridlines with values (radar's grid rings are unlabeled reference lines only).
  • No legend, tooltips, or point-selection callbacks.
  • No locale-aware value formatting (currency, percent, number grouping) — pass already-formatted labels to your own native:text instead.
  • Area charts support overlay fills only; stacked (cumulative) areas are not implemented.
  • Every "reads series[0] only" chart type (candlestick, pie, doughnut) ignores any further series rather than rejecting them.

If you need any of the above, either build it in Blade around this element (as the labels/legend examples above do) or reach for a more complete charting plugin.

iOS status

The Swift renderer (resources/ios/NativephpChartsChartRenderer.swift) mirrors the Android one point-for-point, but SwiftUI's Path.addArc angle/clockwise convention is a well-known gotcha (its clockwise flag is inverted by the view's flipped y-axis) — the pie/doughnut angle math has not been confirmed on a real device or simulator. Radar's polygon math uses plain trigonometry rather than addArc, so it doesn't carry the same risk, but none of the four newer chart types (area, scatter, candlestick, radar) have been visually verified on either platform yet — only compiled successfully. Verify every chart type on a real device before relying on it in production.

License

MIT