{"id":49544827,"url":"https://github.com/matheusmarnt/livecharts","last_synced_at":"2026-06-03T16:00:35.360Z","repository":{"id":355230936,"uuid":"1227291778","full_name":"matheusmarnt/livecharts","owner":"matheusmarnt","description":"Reactive charts for Laravel Livewire — pure PHP, multi-engine (ApexCharts + Chart.js), zero JavaScript required.","archived":false,"fork":false,"pushed_at":"2026-05-29T14:12:37.000Z","size":2176,"stargazers_count":3,"open_issues_count":2,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-29T16:07:04.308Z","etag":null,"topics":["alpinejs","analytics","apexcharts","chart-library","chartjs","charts","composer-package","dashboard","data-visualization","laravel","laravel-package","livewire","livewire-3","livewire-4","livewire-charts","livewire-component","php","php-package","reactive","real-time"],"latest_commit_sha":null,"homepage":"https://matheusmarnt.github.io/livecharts/","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/matheusmarnt.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":"matheusmarnt"}},"created_at":"2026-05-02T13:32:49.000Z","updated_at":"2026-05-29T14:11:53.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/matheusmarnt/livecharts","commit_stats":null,"previous_names":["matheusmarnt/livecharts"],"tags_count":32,"template":false,"template_full_name":null,"purl":"pkg:github/matheusmarnt/livecharts","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matheusmarnt%2Flivecharts","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matheusmarnt%2Flivecharts/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matheusmarnt%2Flivecharts/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matheusmarnt%2Flivecharts/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/matheusmarnt","download_url":"https://codeload.github.com/matheusmarnt/livecharts/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matheusmarnt%2Flivecharts/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33872298,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-03T02:00:06.370Z","response_time":59,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["alpinejs","analytics","apexcharts","chart-library","chartjs","charts","composer-package","dashboard","data-visualization","laravel","laravel-package","livewire","livewire-3","livewire-4","livewire-charts","livewire-component","php","php-package","reactive","real-time"],"created_at":"2026-05-02T18:01:05.129Z","updated_at":"2026-06-03T16:00:35.354Z","avatar_url":"https://github.com/matheusmarnt.png","language":"PHP","funding_links":["https://github.com/sponsors/matheusmarnt"],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n    \u003cimg src=\"art/livecharts.png\" alt=\"LiveCharts\" width=\"750\" /\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n    \u003ca href=\"https://packagist.org/packages/matheusmarnt/livecharts\"\u003e\u003cimg src=\"https://img.shields.io/packagist/v/matheusmarnt/livecharts.svg?style=flat-square\" alt=\"Latest Version on Packagist\" /\u003e\u003c/a\u003e\n    \u003ca href=\"https://github.com/matheusmarnt/livecharts/actions?query=workflow%3Atests+branch%3Amain\"\u003e\u003cimg src=\"https://img.shields.io/github/actions/workflow/status/matheusmarnt/livecharts/run-tests.yml?branch=main\u0026label=tests\u0026style=flat-square\" alt=\"Tests\" /\u003e\u003c/a\u003e\n    \u003ca href=\"https://github.com/matheusmarnt/livecharts/actions?query=workflow%3A%22Fix+PHP+code+style+issues%22+branch%3Amain\"\u003e\u003cimg src=\"https://img.shields.io/github/actions/workflow/status/matheusmarnt/livecharts/fix-php-code-style-issues.yml?branch=main\u0026label=code+style\u0026style=flat-square\" alt=\"Code Style\" /\u003e\u003c/a\u003e\n    \u003ca href=\"https://packagist.org/packages/matheusmarnt/livecharts\"\u003e\u003cimg src=\"https://img.shields.io/packagist/dt/matheusmarnt/livecharts.svg?style=flat-square\" alt=\"Total Downloads\" /\u003e\u003c/a\u003e\n    \u003ca href=\"LICENSE.md\"\u003e\u003cimg src=\"https://img.shields.io/badge/license-MIT-brightgreen?style=flat-square\" alt=\"License\" /\u003e\u003c/a\u003e\n    \u003ca href=\"https://laravel.com\"\u003e\u003cimg src=\"https://img.shields.io/badge/Laravel-10%7C11%7C12%7C13-FF2D20?style=flat-square\u0026logo=laravel\u0026logoColor=white\" alt=\"Laravel\" /\u003e\u003c/a\u003e\n    \u003ca href=\"https://livewire.laravel.com\"\u003e\u003cimg src=\"https://img.shields.io/badge/Livewire-3%7C4-FB70A9?style=flat-square\" alt=\"Livewire\" /\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n# LiveCharts\n\nReactive chart abstraction for Laravel — pure PHP API, multi-engine rendering, Livewire delivery.\n\nLiveCharts unifies ApexCharts and Chart.js behind a single fluent PHP API. Define charts in PHP, render them with one Livewire component, and update them reactively from your application state — no JavaScript boilerplate, no engine-specific configuration leaking into your views.\n\n## Features\n\n- **Fluent + class-based builders** — `LiveCharts::line()-\u003elabels(...)-\u003edataset(...)` or `class extends Chart`\n- **18 chart types** — line, bar, area, pie, donut, radar, scatter, bubble, heatmap, range bar, radial bar, polar area, box plot, treemap, candlestick, matrix, sankey, plus a generic factory\n- **Multi-engine** — ApexCharts and Chart.js out of the box, with `LiveCharts::registerEngine()` for custom adapters\n- **Livewire-native rendering** — single `\u003clivewire:livecharts :chart=\"$chart\" /\u003e` component handles mount, hydration, and re-render\n- **Reactive updates** — bind chart data to Livewire properties; the component re-renders when state changes\n- **Polling** — `Chart::poll(5000)` + `wire:poll=\"refresh\"` integration with a `livecharts:refreshed` event for userland data hydration\n- **Interaction events** — `onDataPointClick`, `onZoom`, `onSelection`, `onScroll` map directly to Livewire events\n- **Broadcasting** — push chart updates over Laravel Echo channels with `broadcastOn()` / `broadcastAs()`\n- **Theme-aware color tokens** — 289-case `TwColor` enum (all Tailwind v4 families + 4 extensions × 11 shades) with `dark:`/`light:` named-arg API: `-\u003etitleColor(dark: TwColor::Amber300, light: TwColor::Amber600)`. Charts re-color live on dark-mode toggle — no Livewire roundtrip\n- **Palette presets** — `-\u003epalette(TwPalette::Vibrant)` auto-fills dataset colors from theme-aware preset schemes\n- **Typography** — `-\u003etitleFont(size: 18, weight: 'bold', family: 'Inter')` for title, legend, and tooltip\n- **Theme detection** — `auto`, `light`, or `dark` modes; JS observer watches `\u003chtml class=\"dark\"\u003e` (or `prefers-color-scheme`) and re-colors charts live\n- **Local-first assets with CDN fallback** — engine bundles (`apexcharts.js`, `chartjs.js`) and Chart.js plugin bundles (treemap/matrix/sankey/financial/luxon/adapter-luxon) ship pre-built in `resources/dist`; switch between `local`, `cdn`, or `both` via config\n- **Vite build pipeline** — lib-mode IIFE outputs for `livecharts.js` + every engine and plugin shim, verified in CI\n- **Stub publishing** — `livecharts:install` can publish chart class stubs to `stubs/livecharts` for project-level customization\n- **Browser preview** — `php artisan livecharts:preview` launches a gallery of every chart type in your default browser\n- **i18n** — ships with `en`, `pt_BR`, and `es` translations\n- **Type-safe** — PHPStan level 8, PHP 8.2+, strict types throughout\n\n## Quick Start\n\n```bash\ncomposer require matheusmarnt/livecharts\nphp artisan livecharts:install\n```\n\nThis will:\n1. Publish `config/livecharts.php`\n2. Copy the LiveCharts JS runtime + engine bundles to `public/vendor/livecharts/js` (local-first delivery with CDN fallback by default — `LIVECHARTS_ASSETS_MODE=both`)\n3. Optionally publish chart class stubs to `stubs/livecharts`\n\n\u003e **Note:** The default asset mode is `both` (local first, CDN fallback). The files in `public/vendor/livecharts/js/` must exist for this to work. If you skip the install step or need to restore the assets after deployment, run:\n\u003e ```bash\n\u003e php artisan vendor:publish --tag=livecharts-assets --force\n\u003e ```\n\u003e If you prefer no local files at all, set `LIVECHARTS_ASSETS_MODE=cdn` in `.env` — no publish step needed.\n\nThen build a chart and render it:\n\n```php\nuse Matheusmarnt\\LiveCharts\\Facades\\LiveCharts;\n\n$chart = LiveCharts::line()\n    -\u003etitle('Monthly Revenue')\n    -\u003elabels(['Jan', 'Feb', 'Mar'])\n    -\u003edataset('2026', [100, 200, 150])\n    -\u003ecolors(['#3B82F6']);\n```\n\n```blade\n\u003clivewire:livecharts :chart=\"$chart\" /\u003e\n```\n\nPlace the asset directive once in your layout, **before `@livewireScripts`** and before the closing `\u003c/body\u003e` tag (or in the `\u003chead\u003e` when using a Blade layout with `@extends`/`@section`):\n\n```blade\n{{-- must come BEFORE @livewireScripts — livecharts.js registers Alpine components before Alpine starts --}}\n@liveChartsScripts\n@livewireScripts\n```\n\n## Building Charts\n\n### Fluent builder\n\nEvery method returns `$this`, so chains read top-down:\n\n```php\nLiveCharts::bar()\n    -\u003etitle('Sales by Region')\n    -\u003esubtitle('Q1 2026')\n    -\u003elabels(['North', 'South', 'East', 'West'])\n    -\u003edataset('Sales', [400, 300, 600, 250])\n    -\u003ecolors(['#10B981'])\n    -\u003estacked()\n    -\u003eheight(420)\n    -\u003etheme('auto');\n```\n\nAvailable factories: `line`, `bar`, `area`, `pie`, `donut`, `radar`, `scatter`, `bubble`, `heatmap`, `rangeBar`, `radialBar`, `polarArea`, `boxPlot`, `treemap`, `candlestick`, `matrix`, `sankey`, plus `make()` for the generic factory.\n\n### Class-based charts\n\nGenerate a dedicated class for reusable charts:\n\n```bash\nphp artisan make:chart RevenueChart --type=bar\n```\n\n```php\nnamespace App\\Charts;\n\nuse Matheusmarnt\\LiveCharts\\Charts\\Chart;\nuse Matheusmarnt\\LiveCharts\\Charts\\Dataset;\n\nclass RevenueChart extends Chart\n{\n    protected string $type = 'bar';\n\n    public function __construct()\n    {\n        parent::__construct();\n\n        $this\n            -\u003etitle('Revenue')\n            -\u003elabels(['Jan', 'Feb', 'Mar'])\n            -\u003edatasets([\n                Dataset::make('2026')-\u003edata([400, 300, 600])-\u003ecolor('#10B981'),\n            ]);\n    }\n}\n```\n\n```blade\n\u003clivewire:livecharts :chart=\"new App\\Charts\\RevenueChart\" /\u003e\n```\n\n\u003e **Stubs:** running `livecharts:install` and accepting the stubs prompt publishes the generator stub to `stubs/livecharts/chart.stub`. Edit that file to customize the boilerplate emitted by `make:chart`.\n\n## Reactive Charts\n\n### Polling\n\n```php\n$chart-\u003epoll(5000); // refresh every 5 seconds\n```\n\nThe Livewire component subscribes via `wire:poll=\"refresh\"` and dispatches a browser event on every tick:\n\n```js\nwindow.addEventListener('livecharts:refreshed', (e) =\u003e {\n    // e.detail.id — chart DOM id\n})\n```\n\nHydrate fresh data inside `refresh()` on a parent Livewire component, or react to the event on the client.\n\n### Click and zoom events\n\n```php\n$chart\n    -\u003eonDataPointClick('chart-clicked')\n    -\u003eonZoom('chart-zoomed')\n    -\u003eonSelection('chart-selected');\n```\n\nIn the parent component:\n\n```php\nuse Livewire\\Attributes\\On;\n\n#[On('chart-clicked')]\npublic function handle(array $data): void\n{\n    // $data: ['seriesIndex' =\u003e 0, 'dataPointIndex' =\u003e 2, 'value' =\u003e 150, 'label' =\u003e 'Mar']\n}\n```\n\n### Broadcasting\n\n```php\n$chart-\u003ebroadcastOn('private-charts.'.$user-\u003eid)-\u003ebroadcastAs('chart.updated');\n```\n\nSubscribe via Laravel Echo and the chart re-renders when the channel fires.\n\n## Multi-Engine\n\nThe default engine is `apexcharts`. Override globally in `config/livecharts.php` or per chart:\n\n```php\nLiveCharts::line()-\u003eengine('chartjs')-\u003elabels(...)-\u003edataset(...);\n```\n\nRegister a custom adapter at runtime:\n\n```php\nuse App\\LiveCharts\\Engines\\HighchartsAdapter;\nuse Matheusmarnt\\LiveCharts\\Facades\\LiveCharts;\n\nLiveCharts::registerEngine('highcharts', HighchartsAdapter::class);\n```\n\nImplement `Matheusmarnt\\LiveCharts\\Contracts\\EngineAdapter` and the engine becomes selectable from any chart.\n\n## Commands\n\n| Command | Description |\n|---|---|\n| `livecharts:install` | Publish config, copy the JS runtime + engine bundles, optionally publish chart stubs |\n| `make:chart {name} {--type=} {--engine=}` | Generate a new chart class under `app/Charts`; `--type`/`--engine` derived from `Chart::TYPES` and `EngineFactory::names()` |\n| `livecharts:preview {--no-open}` | Open the gallery of every chart type at `/livecharts/preview` in your default browser; `--no-open` only prints the URL |\n\n## Documentation\n\n- [Installation guide](docs/installation.md) — step-by-step setup, asset modes, engine selection, customization\n\n## Testing\n\n```bash\ncomposer test\n```\n\nRuns the Pest suite (301 tests) against the package's testbench harness — including 17 Pest arch rules, payload + adapter routing for every chart type, Livewire color-roundtrip tests (Bugs 1 \u0026 5), ApexCharts themed-color path tests, script-stack idempotency tests, wire:navigate asset strategy tests, and integration tests for UC-01 dashboard, UC-02 drill-down, UC-03 polling, and UC-04 multi-tenant flows. CI matrix: PHP 8.2-8.5 × Laravel 11/12/13 × Livewire 3/4 × prefer-lowest/stable × Ubuntu/Windows, with a `--min=90` coverage gate and PHPStan level 8 enforcement.\n\n## Changelog\n\nSee [CHANGELOG](CHANGELOG.md) for release history.\n\n## Contributing\n\nSee [CONTRIBUTING](CONTRIBUTING.md) for details.\n\n## Security\n\nIf you discover a security vulnerability, please email matheusmarnt@gmail.com instead of opening a public issue.\n\n## Credits\n\n- [Matheus Mariano](https://github.com/matheusmarnt)\n- [All Contributors](../../contributors)\n\n## License\n\nMIT — see [LICENSE](LICENSE.md).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmatheusmarnt%2Flivecharts","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmatheusmarnt%2Flivecharts","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmatheusmarnt%2Flivecharts/lists"}