80 Commits

Author SHA1 Message Date
asantibanez
802416ee7a v3.0.0 released 2023-07-25 17:14:18 -05:00
asantibanez
d957e698bb Updated build 2023-07-25 17:10:45 -05:00
asantibanez
46d82cf6bc Refactored how event was triggered 2023-07-25 17:07:51 -05:00
asantibanez
1f26a9ed39 Updated README 2023-07-25 16:58:00 -05:00
asantibanez
55d76bcecd Fixed error dispatching 2023-07-25 16:51:53 -05:00
asantibanez
5034771e57 Added helper methods 2023-07-25 16:51:45 -05:00
asantibanez
6b2667f590 Changed properties visibility 2023-07-25 16:51:35 -05:00
asantibanez
c5784b0ced Added helper methods for PieChartModel 2023-07-25 16:28:59 -05:00
asantibanez
2d9bcfe480 Fixed event dispatching. Added tests. 2023-07-25 16:19:04 -05:00
asantibanez
aa822000af Made properties private so everything is accessed via methods 2023-07-25 16:18:48 -05:00
asantibanez
682b282fe8 Updated dependencies 2023-07-25 16:18:19 -05:00
asantibanez
de936c77d6 Fixed arguments 2023-07-25 16:18:03 -05:00
asantibanez
17efda3ed0 Merge branch 'master' of github.com:asantibanez/livewire-charts 2023-07-25 13:50:56 -05:00
Andrés Santibáñez
25b13b3573 Merge pull request #50 from syntaxlexx/theme-mods
Feat: added theme setting options - dark mode, palette
2023-07-25 14:48:22 -04:00
asantibanez
30eae50c04 Bumped up CI 2023-07-25 13:43:41 -05:00
asantibanez
c79dfeb0ab Refactored tests with new Testable class 2023-07-25 13:42:43 -05:00
asantibanez
3dcc97bef3 Started Livewire v3 support 2023-07-25 13:42:29 -05:00
/SyntaxLexx
c408b639e9 Merge branch 'master' into theme-mods 2023-06-10 03:44:07 +03:00
asantibanez
ac1e6130d4 Updated export 2023-02-01 18:32:57 -05:00
asantibanez
756781c3a9 Added ability to add custom configs to pie charts 2023-02-01 18:32:06 -05:00
asantibanez
93dbaffc61 Added custom configs to Column Chart 2023-02-01 18:28:06 -05:00
asantibanez
6926a504b1 Added deepmerge dependency 2023-02-01 18:24:15 -05:00
asantibanez
40828df23e Added ability to specify custom json config to charts 2023-02-01 18:23:53 -05:00
asantibanez
9f9554314e v2.5.0 released 2023-02-01 13:16:56 -05:00
asantibanez
c7997758bd Added ability to format value via "extras.formatted" 2023-02-01 13:13:28 -05:00
asantibanez
5bc85376a3 Extracted title 2023-02-01 13:13:28 -05:00
Andrés Santibáñez
e6c34e2d49 Merge pull request #83 from laravel-shift/l10-compatibility
Laravel 10.x Compatibility
2023-02-01 12:40:17 -05:00
asantibanez
66ce742311 v2.4.2 released 2023-02-01 12:38:11 -05:00
asantibanez
cd56963f6e Extracted value into variable 2023-02-01 12:35:21 -05:00
asantibanez
ce43d0b97c Fixed column title 2023-02-01 12:35:10 -05:00
Shift
d1ce67f9e5 Bump dependencies for Laravel 10 2023-01-31 19:47:59 +00:00
Lexx YungCarter
1e04ebf6d9 feat: merged with master 2022-10-17 16:02:42 +03:00
asantibanez
072a98da5c Updated CHANGELOG 2022-02-18 16:47:04 -05:00
asantibanez
27198d12b8 Fixed xAxis auto-labels for MultiColumnChart 2022-02-18 16:43:46 -05:00
asantibanez
8bfdaa1763 Updated README 2022-02-14 15:42:57 -05:00
asantibanez
aa94016b6e Added TreeMap chart
- Added tests
2022-02-14 15:38:59 -05:00
asantibanez
4a74606e4d Added shades support in trait 2022-02-14 15:37:59 -05:00
asantibanez
52abe77e7e Extracted radar chart js to file 2022-02-14 12:49:47 -05:00
asantibanez
202591954d Added install command 2022-02-14 12:49:36 -05:00
asantibanez
9e4d8ddf40 Added tests for Radar Chart component 2022-02-14 12:49:17 -05:00
Andrés Santibáñez
3e57a722b4 Merge pull request #54 from AlexHupe/master
Added RadarChart
2022-02-14 12:25:49 -05:00
Andrés Santibáñez
0c72c83dda Merge pull request #53 from nicko170/master
Allow setting type on Pie Chart Model
2022-02-14 12:22:16 -05:00
Andrés Santibáñez
327665919f Merge pull request #69 from asantibanez/update-to-laravel-9
Added support for L9. Upgraded dependencies
2022-02-14 10:42:35 -05:00
asantibanez
879734fe9c Updated CI 2022-02-14 10:33:10 -05:00
asantibanez
6754e94cde Added support for L9. Upgraded dependencies 2022-02-14 10:26:17 -05:00
Alex
9802ec2bcd Preview-Image 2021-10-15 19:51:13 +02:00
Alex
821ac7a454 Add RadarChart 2021-10-15 19:23:27 +02:00
nicko170
a7364ad51c compile 2021-08-27 16:14:40 +10:00
nicko170
47d0f028af adding pie chart type 2021-08-27 16:05:53 +10:00
Lexx YungCarter
9ad481000c fix: typo in palette 2021-08-01 05:16:16 +03:00
Lexx YungCarter
fe0c62be75 feat: added theme setting options - dark mode, pallates 2021-08-01 05:13:49 +03:00
Andrés Santibáñez
582ad340dd Updated docs 2021-02-12 00:29:24 -05:00
Andrés Santibáñez
35d8a80bb4 Updated docs 2021-02-12 00:26:33 -05:00
Andrés Santibáñez
665a3370b2 Added build 2021-02-12 00:26:10 -05:00
Andrés Santibáñez
84527ff809 Added color customization to multiline chart 2021-02-12 00:26:04 -05:00
Andrés Santibáñez
cefb5089e8 Updated docs 2021-02-12 00:22:32 -05:00
Andrés Santibáñez
bf644a5931 Updated docs 2021-02-12 00:20:11 -05:00
Andrés Santibáñez
3abe96bdb0 Added build 2021-02-12 00:17:20 -05:00
Andrés Santibáñez
171a333044 Added init method to all charts
- Added custom colors to pie chart
2021-02-12 00:17:11 -05:00
Andrés Santibáñez
372d6ffcb0 Added extra configuration options to column chart 2021-02-11 23:42:06 -05:00
asantibanez
0de38b041b Added new traits for colors and grid handling 2021-02-11 22:35:59 -05:00
asantibanez
b649aaef23 Added CI setup and PR templates 2020-12-16 09:27:18 -05:00
asantibanez
75f46fc1cf Updated .gitignore 2020-12-16 09:27:01 -05:00
asantibanez
11272bd21b Added base tests for components 2020-12-16 09:26:37 -05:00
Andrés Santibáñez
1e1075ba07 Merge pull request #24 from AlexHupe/patch-2
Add method 'addSeriesColumn' to readme
2020-12-16 08:55:51 -05:00
Andrés Santibáñez
1bfa52ca83 Merge pull request #26 from mokhosh/patch-1
Add support for php 8.0
2020-12-16 08:55:01 -05:00
Mo Khosh
3add4a148e Add support for php 8.0
Modify composer.json to allow php 8.0
2020-12-16 11:47:43 +03:30
Alexander Hupe
27606ff1e9 Add method 'addSeriesColumn' to readme 2020-12-07 16:33:03 +01:00
Andrés Santibáñez
230b706c63 Merge pull request #11 from hamidafghan/ifix-stroke-width
Added stroke width customization
2020-11-30 12:59:20 -05:00
Andrés Santibáñez
8b0bb9c250 Added custom stroke for Area Chart 2020-11-30 12:58:19 -05:00
Andrés Santibáñez
3d89d210b5 Added build 2020-11-30 12:48:14 -05:00
Andrés Santibáñez
f72c5294d9 Updated README 2020-11-30 12:45:44 -05:00
Andrés Santibáñez
76b64536d1 Added build system and assets for js 2020-11-30 12:13:03 -05:00
Andrés Santibáñez
fd4961d7ae Merge pull request #9 from AlexHupe/patch-1
Typo in README.md
2020-11-30 09:54:17 -05:00
hamidafghan
c61ca90905 Add stroke width 2020-11-24 10:36:09 +04:30
Alexander Hupe
67bd18bc48 Typo in README.md 2020-11-19 09:35:05 +01:00
Andrés Santibáñez
940109ef03 Fixed infinite growing charts 2020-11-09 10:53:42 -05:00
Andrés Santibáñez
0457a9a007 Updated CHANGELOG 2020-11-09 10:18:23 -05:00
Andrés Santibáñez
2c7317c3b8 Removed unused directives 2020-11-09 10:17:29 -05:00
Andrés Santibáñez
98df89eca4 Updated README 2020-11-09 08:49:16 -05:00
61 changed files with 26312 additions and 623 deletions

1
.github/CODEOWNERS vendored Normal file
View File

@@ -0,0 +1 @@
* @asantibanez

26
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@@ -0,0 +1,26 @@
---
name: Bug report
about: Create a report to help us improve
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. '...'
2. '...'
3. '...'
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Additional context**
Add any other context about the problem here.
**Solution Ideas**
Initial thoughts or details about how this could be fixed

14
.github/ISSUE_TEMPLATE/feature.md vendored Normal file
View File

@@ -0,0 +1,14 @@
---
name: Feature
about: New feature idea
---
### Summary
What's the new feature about? What should it do?
### Proposal
How should it work? API ideas?
### Additional Notes
Reference links or comments

18
.github/PULL_REQUEST_TEMPLATE vendored Normal file
View File

@@ -0,0 +1,18 @@
## Summary
[Provide a summary of the change.]
## Issue
[If exists, provide a link to the corresponding issue(s).]
## Type of Change
- [ ] :rocket: New Feature
- [ ] :bug: Bug Fix
- [ ] :hammer: Refactor
- [ ] :question: [Other]
## Screenshot/Video
[Provide a screenshot or video that describes the change if applicable]

29
.github/workflows/phpunit.yml vendored Normal file
View File

@@ -0,0 +1,29 @@
name: PHPUnit
on: [push]
jobs:
phpunit:
runs-on: ubuntu-latest
steps:
- name: Cancel Previous Run
uses: styfle/cancel-workflow-action@0.6.0
with:
access_token: ${{ github.token }}
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.1'
extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, gd, exif, imagick, bcmath
coverage: none
- name: Checkout code
uses: actions/checkout@v2
- name: Install Composer dependencies
run: composer install --ignore-platform-reqs
- name: Run tests
run: ./vendor/bin/phpunit

2
.gitignore vendored
View File

@@ -5,3 +5,5 @@ docs
vendor
coverage
.DS_STORE
node_modules
.phpunit.result.cache

View File

@@ -1,5 +1,50 @@
# Changelog
## 3.0.0 - 2023-07-25
- Added Livewire v3 support
- Added ability to set chart theme (thanks to @syntaxlexx)
- Added ability to configure chart via JSON properties
## 2.5.0 - 2023-02-01
- Added tooltip override via `extras.tooltip`
## 2.4.2 - 2023-02-01
- Fixed hover title on column chart
## 2.4.1 - 2022-02-18
- Fixed xAxis auto-categories for MultiColumnChart
## 2.4.0 - 2022-02-14
- Added Radar Chart (thanks to @AlexHupe)
- Added Tree Map Chart
- Added "donut" type to Pie Chart (thanks to @nicko170)
## 2.3.0 - 2021-02-12
- Added `init()` method for better boot and $wire hoisting
- Added color customization for columns, multiline and pie chart
## 2.2.0 - 2020-12-16
- Added support for PHP 8
- Updated docs
- Added base tests for components and CI
## 2.1.0 - 2020-11-30
- Added stroke width customization
- Added stroke support for Area Chart
## 2.0.0 - 2020-11-30
- Added build system for JS charts code
- Added Blade directive to include assets
- Updated installation and advanced usage instructions
## 1.5.2 - 2020-11-09
- Fixed infinite growing charts
## 1.5.1 - 2020-11-09
- Removed unused Alpine directives
## 1.5.0 - 2020-11-09
- Added `LivewireCharts` facade to create any chart model

127
README.md
View File

@@ -5,6 +5,7 @@
## Preview
![preview](https://github.com/asantibanez/livewire-charts/raw/master/preview.gif)
![preview](./preview_radarchart.gif)
## Demo
@@ -18,11 +19,19 @@ You can install the package via composer:
composer require asantibanez/livewire-charts
```
Next, you must export the package public scripts. To do this run
```bash
php artisan livewire-charts:install
```
This command will export a `vendor/livewire-charts` folder under the `public` directory of your app which is used
by the `@livewireChartsScripts` directive. More on this topic later.
## Requirements
This package requires the following packages/libraries to work:
- `Laravel Livewire v2` (https://laravel-livewire.com/)
- `Alpine Js` (https://github.com/alpinejs/alpine)
- `Laravel Livewire v3` (https://livewire.laravel.com/)
- `Apex Charts` (https://apexcharts.com/)
Please follow each package/library instructions on how to set them properly in your project.
@@ -32,16 +41,20 @@ Please follow each package/library instructions on how to set them properly in y
## Usage
Livewire Charts supports out of the box the following types of charts
- Line Chart (`LivewireLineChart` component)
- Line/Multi Line Chart (`LivewireLineChart` component)
- Pie Chart (`LivewirePieChart` component)
- Column Chart (`LivewireColumnChart` component)
- Column/Multi Line Chart (`LivewireColumnChart` component)
- Area Chart (`LivewireAreaChart` component)
- Radar Chart (`LivewireRadarChart` component)
- Tree Map Chart (`LivewireTreeMapChart` component)
Each one comes with its own "model" class that allows you to define the chart's data and render behavior.
- `LivewireLineChart` uses `LineChartModel` to set up data points, markers, events and other ui customizations.
- `LivewirePieChart` uses `PieChartModel` to set up data slices, events and other ui customizations.
- `LivewireColumnChart` uses `ColumnChartModel` to set up data columns, events and other ui customizations.
- `LivewireAreaChart` uses `AreaChartModel` to set up data points, events and other ui customizations.
- `LivewireRadarChart` uses `RadarChartModel` to set up data points, events and other ui customizations.
- `LivewireTreeMapChart` uses `TreeMapChartModel` to set up data blocks, events and other ui customizations.
For example, to render a column chart, we can create an instance of `ColumnChartModel` and add some data to it
```php
@@ -60,9 +73,18 @@ With `$columnChartModel` at hand, we pass it to our `LivewireColumnChart` compon
```blade
<livewire:livewire-column-chart
{{-- key="{{ $columnChartModel->reactiveKey() }}" --}}
:column-chart-model="$columnChartModel"
/>
```
>Note: Optionally add "key" to enable props reactivity if needed 💪
Next, include the `@livewireChartsScripts` directive next to your other app scripts
```html
<livewire:scripts />
@livewireChartsScripts
```
And that's it! You have a beautiful rendered chart in seconds. 👌
@@ -71,6 +93,21 @@ And that's it! You have a beautiful rendered chart in seconds. 👌
>Note: You can use these charts inside other Livewire components too. Just render them in your Blade template and you
are good to go. 👍
## LivewireCharts facade
Chart models can also be created using the `LivewireCharts` facade.
```php
LivewireCharts::lineChartModel();
LivewireCharts::multiLineChartModel();
LivewireCharts::columnChartModel();
LivewireCharts::multiColumnChartModel();
LivewireCharts::pieChartModel();
LivewireCharts::areaChartModel();
LivewireCharts::radarChartModel();
LivewireCharts::treeMapChartModel();
```
## Enabling Interactions
To enable click events, you must use the `with[XXX]ClickEvent($eventName)` method present in every model class and
@@ -89,10 +126,12 @@ $columnChartModel =
We can listen to the `onClickEvent` registering a listener in any other Livewire component.
```php
protected $listeners = [
'onColumnClick' => 'handleOnColumnClick',
];
```
#[On('onColumnClick')]
public function handleOnColumnClick($event)
{
// Handle event
}
```
## "Reactive" Charts
@@ -129,7 +168,7 @@ The parent component renders the charts as follows
For each chart, a specific model class needs to be used. Here, it is detailed the api available
for each type of chart.
#### All
### All
| Method | Description |
|--------|-------------|
@@ -138,13 +177,15 @@ for each type of chart.
| setDataLabelsEnabled(boolean $enabled) | Enables/disables data labels |
| withDataLabels() | Enables data labels |
| withoutDataLabels() | Disables data labels |
| withLegends() | Shows legends |
| withoutLegends() | Hides legends |
| withLegend() | Shows legends |
| withoutLegend() | Hides legends |
| setColors(array $colors) | Set colors for chart |
| addColors(string $color) | Append $color to $colors set |
| setXAxisCategories(array $categories) | Enables custom categories for chart X Axis |
| sparklined() | Enables Apex Charts sparkline feature |
| setSparklineEnabled(boolean $isEnabled) | Enables/Disables Apex Charts sparkline feature |
#### LivewireLineChart
### LivewireLineChart
| Method | Description |
|--------|-------------|
@@ -155,26 +196,32 @@ for each type of chart.
| addMarker(string $title, double $value) | Adds a marker point to the line chart. Markers are used to emphasize particular points in the chart (singleLine only) |
| withOnPointClickEvent(string $eventName) | Event Name that will be fired when a point/marker of the chart is clicked |
#### LivewireColumnChart
### LivewireColumnChart
| Method | Description |
|--------|-------------|
| setOpacity(int $opacity) | Sets columns' opacity |
| multiColumn() | Sets chart to display multiple column series |
| singleColumn() | Sets chart to display a single column series |
| stacked() | Sets chart to display column series stacked |
| addColumn(string $title, double $value, string $color, array $extras = []) | Adds a column to the chart with the specified color. `$extras` is forwarded on click event |
| onColumnClickEventName(string $eventName) | Event Name that will be fired when a column of the chart is clicked |
| Method | Description |
|---------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------|
| setOpacity(int $opacity) | Sets columns' opacity |
| setColumnWidth(int $columnWidth) | Sets columns' width |
| setHorizontal() | Displays columns horizontally |
| setVertical() | Displays columns vertically |
| multiColumn() | Sets chart to display multiple column series |
| singleColumn() | Sets chart to display a single column series |
| stacked() | Sets chart to display column series stacked |
| addColumn(string $title, double $value, string $color, array $extras = []) | Adds a column to the chart with the specified color. `$extras` is forwarded on click event |
| addSeriesColumn(string $seriesName, string $title, double $value, array $extras = []) | Adds a column to a multicolumn chart. `$extras` is forwarded on click event |
| onColumnClickEventName(string $eventName) | Event Name that will be fired when a column of the chart is clicked |
#### LivewirePieChart
### LivewirePieChart
| Method | Description |
|--------|-------------|
| setOpacity(int $opacity) | Sets slices' opacity |
| Method | Description |
|---------------------------------------------------------------------------|-------------------------------------------------------------------------------------------|
| setOpacity(int $opacity) | Sets slices' opacity |
| asPie() | Displays chart as pie |
| asDonut() | Displays chart as donut |
| addSlice(string $title, double $value, string $color, array $extras = []) | Adds a slice to the chart with the specified color. `$extras` is forwarded on click event |
| withOnSliceClickEvent(string $eventName) | Event Name that will be fired when a column of the chart is clicked |
| withOnSliceClickEvent(string $eventName) | Event Name that will be fired when a column of the chart is clicked |
#### LivewireAreaChart
### LivewireAreaChart
| Method | Description |
|--------|-------------|
@@ -183,6 +230,32 @@ for each type of chart.
| setXAxisVisible(boolean $visible) | Shows/hides xAxis labels |
| setYAxisVisible(boolean $visible) | Shows/hides yAxis labels |
### LivewireRadarChart
| Method | Description |
|--------|-------------|
| addSeries(string $seriesName, string $title, double $value, array $extras = []) | |
| withOnPointClickEvent(string $eventName) | Event Name that will be fired when a point of the chart is clicked |
### LivewireTreeMapChart
| Method | Description |
|--------|-------------|
| addBlock(string $title, double $value, array $extras = []) | Adds a block to the default series|
| addSeriesBlock(string $seriesName, string $title, double $value, array $extras = []) | Adds a block to the specified series|
| withOnBlockClickEvent(string $eventName) | Event Name that will be fired when a block of the chart is clicked |
| setDistributed(bool $distributed) | Set whether the chart uses distribution or not |
## Advanced Usage - Integrating Scripts
The directive `@livewireChartsScripts` adds a `script` tag that includes `public/vendor/livewire-charts/app.js`.
If you want to include this script in your build system, you can export the package scripts
with `php artisan vendor:publish` and selecting `livewire-charts:scripts`. This will export `js/vendor/livewire-charts`
inside your resources folder. You can then adjust imports as you see fit in your project.
>Note: You must remove @livewireChartsScripts directive so it doesn't clash with the scripts in your build system.
## Troubleshooting
Chart components must be placed inside a container with fixed height. This is because the chart will use all the given

View File

@@ -16,13 +16,13 @@
}
],
"require": {
"php": "^7.2|^7.3|^7.4",
"illuminate/support": "^7.0|^8.0",
"livewire/livewire": "^2.3"
"php": "^7.2|^7.3|^7.4|^8.0",
"illuminate/support": "^7.0|^8.0|^9.0|^10.0",
"livewire/livewire": "^3.0"
},
"require-dev": {
"orchestra/testbench": "^4.0|^5.0",
"phpunit/phpunit": "^8.0"
"orchestra/testbench": "^5.0|^6.0|^7.0|^8.0",
"phpunit/phpunit": "^8.0|^9.5.10"
},
"autoload": {
"psr-4": {
@@ -37,7 +37,6 @@
"scripts": {
"test": "vendor/bin/phpunit",
"test-coverage": "vendor/bin/phpunit --coverage-html coverage"
},
"config": {
"sort-packages": true
@@ -51,5 +50,7 @@
"LivewireCharts": "Asantibanez\\LivewireCharts\\LivewireChartsFacade"
}
}
}
},
"minimum-stability": "dev",
"prefer-stable": true
}

3
mix-manifest.json Normal file
View File

@@ -0,0 +1,3 @@
{
"/public/app.js": "/public/app.js"
}

24163
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

19
package.json Normal file
View File

@@ -0,0 +1,19 @@
{
"scripts": {
"dev": "npm run development",
"development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
"watch": "npm run development -- --watch",
"watch-poll": "npm run watch -- --watch-poll",
"prod": "npm run production",
"production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
},
"devDependencies": {
"apexcharts": "^3.22.2",
"cross-env": "^7.0.2",
"laravel-mix": "^5.0.9",
"vue-template-compiler": "^2.6.12"
},
"dependencies": {
"deepmerge": "^2.2.1"
}
}

View File

@@ -22,7 +22,7 @@
<logging>
<log type="tap" target="build/report.tap"/>
<log type="junit" target="build/report.junit.xml"/>
<log type="coverage-html" target="build/coverage" charset="UTF-8" yui="true" highlight="true"/>
<log type="coverage-html" target="build/coverage"/>
<log type="coverage-text" target="build/coverage.txt"/>
<log type="coverage-clover" target="build/logs/clover.xml"/>
</logging>

BIN
preview_radarchart.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

2
public/app.js Normal file

File diff suppressed because one or more lines are too long

13
public/app.js.LICENSE.txt Normal file
View File

@@ -0,0 +1,13 @@
/*!
* ApexCharts v3.41.0
* (c) 2018-2023 ApexCharts
* Released under the MIT License.
*/
/*! svg.draggable.js - v2.2.2 - 2019-01-08
* https://github.com/svgdotjs/svg.draggable.js
* Copyright (c) 2019 Wout Fierens; Licensed MIT */
/*! svg.filter.js - v2.0.2 - 2016-02-24
* https://github.com/wout/svg.filter.js
* Copyright (c) 2016 Wout Fierens; Licensed MIT */

19
resources/js/app.js Normal file
View File

@@ -0,0 +1,19 @@
import ApexCharts from 'apexcharts'
import areaChart from "./areaChart"
import columnChart from "./columnChart"
import multiColumnChart from "./multiColumnChart";
import lineChart from "./lineChart"
import multiLineChart from "./multiLineChart"
import pieChart from "./pieChart"
import radarChart from "./radarChart"
import treeMapChart from "./treeMapChart"
window.ApexCharts = ApexCharts
window.livewireChartsAreaChart = areaChart
window.livewireChartsColumnChart = columnChart
window.livewireChartsLineChart = lineChart
window.livewireChartsMultiLineChart = multiLineChart
window.livewireChartsPieChart = pieChart
window.livewireChartsMultiColumnChart = multiColumnChart
window.livewireChartsRadarChart = radarChart
window.livewireChartsTreeMapChart = treeMapChart

97
resources/js/areaChart.js Normal file
View File

@@ -0,0 +1,97 @@
const areaChart = () => {
return {
chart: null,
init() {
setTimeout(() => {
this.drawChart(this.$wire)
}, 0)
},
drawChart(component) {
if (this.chart) {
this.chart.destroy()
}
const title = component.get('areaChartModel.title');
const animated = component.get('areaChartModel.animated') || false;
const dataLabels = component.get('areaChartModel.dataLabels') || {};
const onPointClickEventName = component.get('areaChartModel.onPointClickEventName')
const data = component.get('areaChartModel.data');
const sparkline = component.get('areaChartModel.sparkline');
const categories = component.get('areaChartModel.xAxis.categories').length > 0
? component.get('areaChartModel.xAxis.categories')
: data.map(item => item.title)
;
var options = {
series: [{
name: title,
data: data.map(item => item.value)
}],
chart: {
type: 'area',
height: '100%',
...sparkline,
zoom: { enabled: false },
toolbar: { show: false },
animations: { enabled: animated },
events: {
markerClick: function(event, chartContext, { dataPointIndex }) {
if (!onPointClickEventName) {
return
}
const point = data[dataPointIndex]
component.call('onPointClick', point)
}
}
},
dataLabels: dataLabels,
colors: [component.get('areaChartModel.color') || '#2E93fA'],
stroke: component.get('areaChartModel.stroke') || {},
title: {
text: title,
align: 'center'
},
labels: data.map(item => item.title),
xaxis: {
labels: component.get('areaChartModel.xAxis.labels'),
categories: categories,
},
yaxis: component.get('areaChartModel.yAxis') || {},
grid: {
padding: {
left: 0,
top: 0,
right: 0,
bottom: 0,
}
},
theme: component.get('areaChartModel.theme') || {},
};
this.chart = new ApexCharts(this.$refs.container, options);
this.chart.render();
}
}
}
export default areaChart

121
resources/js/columnChart.js Normal file
View File

@@ -0,0 +1,121 @@
import { mergedOptionsWithJsonConfig } from './helpers'
const columnChart = () => {
return {
chart: null,
init() {
setTimeout(() => {
this.drawChart(this.$wire)
}, 0)
},
drawChart(component) {
if (this.chart) {
this.chart.destroy()
}
const title = component.get('columnChartModel.title')
const animated = component.get('columnChartModel.animated') || false;
const onColumnClickEventName = component.get('columnChartModel.onColumnClickEventName')
const dataLabels = component.get('columnChartModel.dataLabels') || {};
const sparkline = component.get('columnChartModel.sparkline');
const legend = component.get('columnChartModel.legend')
const grid = component.get('columnChartModel.grid');
const columnWidth = component.get('columnChartModel.columnWidth');
const horizontal = component.get('columnChartModel.horizontal');
const jsonConfig = component.get('columnChartModel.jsonConfig');
const data = component.get('columnChartModel.data');
const series = [{
name: title,
data: data.map(item => item.value)
}]
const options = {
series: series,
chart: {
type: 'bar',
height: '100%',
...sparkline,
toolbar: { show: false },
animations: { enabled: animated },
events: {
dataPointSelection: function(event, chartContext, config) {
if (!onColumnClickEventName) {
return
}
const { dataPointIndex } = config
const column = data[dataPointIndex]
component.call('onColumnClick', column)
},
}
},
colors: data.map(item => item.color),
labels: {
style: {
colors: data.map(item => item.color),
},
},
legend: legend,
grid: grid,
plotOptions: {
bar: {
horizontal: horizontal,
columnWidth: `${columnWidth}%`,
distributed: true,
},
},
dataLabels: dataLabels,
xaxis: {
categories: data.map(item => item.title),
},
yaxis: {
title: {
text: title,
}
},
fill: {
opacity: component.get('columnChartModel.opacity') || 0.5
},
theme: component.get('columnChartModel.theme') || {},
tooltip: {
y: {
formatter: function(value, series) {
return data[series.dataPointIndex].extras.tooltip || value;
}
}
},
};
const colors = component.get('columnChartModel.colors');
if (colors && colors.length > 0) {
options['colors'] = colors
}
this.chart = new ApexCharts(this.$refs.container, mergedOptionsWithJsonConfig(options, jsonConfig));
this.chart.render();
}
}
}
export default columnChart

27
resources/js/helpers.js Normal file
View File

@@ -0,0 +1,27 @@
import deepmerge from 'deepmerge'
export const addPathToObjectWithValue = (obj, path, value) => {
const pList = path.split('.');
const key = pList.pop();
const pointer = pList.reduce((accumulator, currentValue) => {
if (accumulator[currentValue] === undefined) accumulator[currentValue] = {};
return accumulator[currentValue];
}, obj);
pointer[key] = value;
return obj;
}
export const mergedOptionsWithJsonConfig = (options, jsonConfig) => {
const customOptions = Object.keys(jsonConfig)
.reduce(function (obj, key) {
const value = jsonConfig[key]
if (typeof value === 'string' && value.includes('function')) {
return addPathToObjectWithValue(obj, key, eval('(' + value + ')'))
}
return addPathToObjectWithValue(obj, key, eval(value))
}, {})
return deepmerge(options, customOptions)
}

118
resources/js/lineChart.js Normal file
View File

@@ -0,0 +1,118 @@
const lineChart = () => {
return {
chart: null,
init() {
setTimeout(() => {
this.drawChart(this.$wire)
}, 0)
},
drawChart(component) {
if (this.chart) {
this.chart.destroy()
}
const title = component.get('lineChartModel.title');
const animated = component.get('lineChartModel.animated') || false;
const dataLabels = component.get('lineChartModel.dataLabels') || {};
const data = component.get('lineChartModel.data');
const onPointClickEventName = component.get('lineChartModel.onPointClickEventName');
const sparkline = component.get('lineChartModel.sparkline');
const series = [{
name: title,
data: data.map(item => item.value),
}]
const categories = component.get('lineChartModel.xAxis.categories').length > 0
? component.get('lineChartModel.xAxis.categories')
: data.map(item => item.title)
const options = {
series: series,
chart: {
type: 'line',
height: '100%',
...sparkline,
zoom: { enabled: false },
toolbar: { show: false },
animations: { enabled: animated },
events: {
markerClick: function(event, chartContext, { dataPointIndex }) {
if (!onPointClickEventName) {
return
}
const point = data[dataPointIndex]
component.call('onPointClick', point)
}
}
},
dataLabels: dataLabels,
stroke: component.get('lineChartModel.stroke') || {},
theme: component.get('lineChartModel.theme') || {},
title: {
text: title,
align: 'center'
},
xaxis: {
labels: component.get('lineChartModel.xAxis.labels'),
categories: categories,
},
yaxis: component.get('lineChartModel.yAxis') || {},
annotations: {
points: component.get('lineChartModel.markers').map(item => {
return {
x: item.title,
y: item.value,
marker: {
size: 6,
fillColor: '#fff',
strokeColor: item.strokeColor,
radius: 2,
},
label: {
offsetY: 0,
style: {
color: item.textColor,
background: item.textBackgroundColor,
},
text: item.text || '',
}
}
}
)
},
tooltip: {
y: {
formatter: function(value, series) {
return data[series.dataPointIndex].extras.tooltip || value;
}
}
},
};
this.chart = new ApexCharts(this.$refs.container, options);
this.chart.render();
}
}
}
export default lineChart

View File

@@ -0,0 +1,109 @@
const multiColumnChart = () => {
return {
chart: null,
init() {
setTimeout(() => {
this.drawChart(this.$wire)
}, 0)
},
drawChart(component) {
if (this.chart) {
this.chart.destroy()
}
const title = component.get('columnChartModel.title')
const stacked = component.get('columnChartModel.isStacked');
const animated = component.get('columnChartModel.animated');
const onColumnClickEventName = component.get('columnChartModel.onColumnClickEventName')
const dataLabels = component.get('columnChartModel.dataLabels');
const sparkline = component.get('columnChartModel.sparkline');
const legend = component.get('columnChartModel.legend')
const grid = component.get('columnChartModel.grid');
const columnWidth = component.get('columnChartModel.columnWidth');
const horizontal = component.get('columnChartModel.horizontal');
const data = component.get('columnChartModel.data');
const series = Object.keys(data)
.map(seriesName => ({
name: seriesName,
data: data[seriesName].map(item => item.value)
}))
const categories = component.get('columnChartModel.xAxis.categories').length > 0
? component.get('columnChartModel.xAxis.categories')
: data[series[0].name].map(item => item.title)
;
const options = {
series: series,
chart: {
type: 'bar',
height: '100%',
stacked: stacked,
...sparkline,
toolbar: { show: false },
animations: { enabled: animated },
events: {
dataPointSelection: function(event, chartContext, {seriesIndex, dataPointIndex}) {
if (!onColumnClickEventName) {
return
}
const column = data[series[seriesIndex].name][dataPointIndex]
component.call('onColumnClick', column)
},
}
},
legend: legend,
grid: grid,
plotOptions: {
bar: {
horizontal: horizontal,
columnWidth: `${columnWidth}%`,
},
},
dataLabels: dataLabels,
xaxis: {
categories: categories,
},
yaxis: {
title: {
text: title,
}
},
fill: {
opacity: component.get('columnChartModel.opacity'),
},
theme: component.get('columnChartModel.theme') || {},
};
const colors = component.get('columnChartModel.colors');
if (colors && colors.length > 0) {
options['colors'] = colors
}
this.chart = new ApexCharts(this.$refs.container, options);
this.chart.render();
}
}
}
export default multiColumnChart

View File

@@ -0,0 +1,93 @@
const multiLineChart = () => {
return {
chart: null,
init() {
setTimeout(() => {
this.drawChart(this.$wire)
}, 0)
},
drawChart(component) {
if (this.chart) {
this.chart.destroy()
}
const title = component.get('lineChartModel.title');
const animated = component.get('lineChartModel.animated') || false;
const dataLabels = component.get('lineChartModel.dataLabels') || {};
const data = component.get('lineChartModel.data');
const onPointClickEventName = component.get('lineChartModel.onPointClickEventName');
const sparkline = component.get('lineChartModel.sparkline');
const series = Object.keys(data).map(key => {
return {
name: key,
data: data[key].map(item => item.value),
}
})
const categories = component.get('lineChartModel.xAxis.categories').length > 0
? component.get('lineChartModel.xAxis.categories')
: data[series[0].name].map(item => item.title)
const options = {
series: series,
chart: {
type: 'line',
height: '100%',
...sparkline,
zoom: { enabled: false },
toolbar: { show: false },
animations: { enabled: animated },
events: {
markerClick: function(event, chartContext, { seriesIndex, dataPointIndex }) {
if (!onPointClickEventName) {
return
}
const point = data[series[seriesIndex].name][dataPointIndex]
component.call('onPointClick', point)
}
}
},
dataLabels: dataLabels,
stroke: component.get('lineChartModel.stroke') || {},
title: {
text: title,
align: 'center'
},
xaxis: {
labels: component.get('lineChartModel.xAxis.labels'),
categories: categories,
},
yaxis: component.get('lineChartModel.yAxis') || {},
theme: component.get('lineChartModel.theme') || {},
};
const colors = component.get('lineChartModel.colors');
if (colors && colors.length > 0) {
options['colors'] = colors
}
this.chart = new ApexCharts(this.$refs.container, options);
this.chart.render();
}
}
}
export default multiLineChart

102
resources/js/pieChart.js Normal file
View File

@@ -0,0 +1,102 @@
import {mergedOptionsWithJsonConfig} from './helpers'
const pieChart = () => {
return {
chart: null,
init() {
setTimeout(() => {
this.drawChart(this.$wire)
}, 0)
},
drawChart(component) {
if (this.chart) {
this.chart.destroy()
}
const title = component.get('pieChartModel.title');
const animated = component.get('pieChartModel.animated') || false
const dataLabels = component.get('pieChartModel.dataLabels') || {}
const onSliceClickEventName = component.get('pieChartModel.onSliceClickEventName')
const data = component.get('pieChartModel.data')
const sparkline = component.get('pieChartModel.sparkline')
const type = component.get('pieChartModel.type')
const jsonConfig = component.get('pieChartModel.jsonConfig');
const options = {
series: data.map(item => item.value),
chart: {
height: '100%',
type: type,
...sparkline,
animations: { enabled: animated },
events: {
dataPointSelection: function(event, chartContext, config) {
if (!onSliceClickEventName) {
return
}
const { dataPointIndex } = config
const slice = data[dataPointIndex]
component.call('onSliceClick', slice)
},
}
},
labels: data.map(item => item.title),
dataLabels: dataLabels,
colors: data.map(item => item.color),
fill: {
opacity: component.get('pieChartModel.opacity'),
},
title: {
text: title,
align: 'center',
},
responsive: [
{
breakpoint: 600,
options: {
legend: {
position: 'bottom'
}
}
}
],
legend: component.get('pieChartModel.legend') || {},
theme: component.get('pieChartModel.theme') || {},
tooltip: {
y: {
formatter: function(value, series) {
return data[series.dataPointIndex].extras.tooltip || value;
}
}
},
};
const colors = component.get('pieChartModel.colors');
if (colors && colors.length > 0) {
options['colors'] = colors
}
this.chart = new ApexCharts(this.$refs.container, mergedOptionsWithJsonConfig(options, jsonConfig));
this.chart.render();
}
}
}
export default pieChart

View File

@@ -0,0 +1,97 @@
const radarChart = () => {
return {
chart: null,
init() {
setTimeout(() => {
this.drawChart(this.$wire)
}, 0)
},
drawChart(component) {
if (this.chart) {
this.chart.destroy()
}
const title = component.get('radarChartModel.title');
const animated = component.get('radarChartModel.animated');
const onPointClickEventName = component.get('areaChartModel.onPointClickEventName');
const dataLabels = component.get('radarChartModel.dataLabels');
const data = component.get('radarChartModel.data');
const sparkline = component.get('radarChartModel.sparkline');
const colors = component.get('radarChartModel.colors');
const series = Object.keys(data)
.map(seriesName => ({
name: seriesName,
data: data[seriesName].map(item => item.value)
}))
const categories = component.get('radarChartModel.xAxis.categories').length > 0
? component.get('radarChartModel.xAxis.categories')
: data[series[0].name].map(item => item.title)
;
const options = {
series: series,
chart: {
type: 'radar',
height: '100%',
...sparkline,
toolbar: {show: false},
animations: {enabled: animated},
events: {
markerClick: function(event, chartContext, {seriesIndex, dataPointIndex}) {
if (!onPointClickEventName) {
return
}
const point = data[series[seriesIndex].name][dataPointIndex]
component.call('onPointClick', point)
},
}
},
legend: component.get('radarChartModel.legend'),
plotOptions: {
bar: {
horizontal: false,
columnWidth: '50%',
},
},
dataLabels: dataLabels,
xaxis: {
categories: categories,
},
title: { text: title },
fill: {
opacity: component.get('radarChartModel.opacity'),
},
colors: colors,
markers: {
size: 4
},
};
this.chart = new ApexCharts(this.$refs.container, options);
this.chart.render();
}
}
}
export default radarChart

View File

@@ -0,0 +1,78 @@
const treeMapChart = () => {
return {
chart: null,
init() {
setTimeout(() => {
this.drawChart(this.$wire)
}, 0)
},
drawChart(component) {
if (this.chart) {
this.chart.destroy()
}
const title = component.get('treeMapChartModel.title');
const animated = component.get('treeMapChartModel.animated');
const distributed = component.get('treeMapChartModel.distributed');
const onBlockClickEventName = component.get('treeMapChartModel.onBlockClickEventName');
const data = component.get('treeMapChartModel.data');
const colors = component.get('treeMapChartModel.colors');
const enableShades = component.get('treeMapChartModel.enableShades');
const series = Object.keys(data)
.map(seriesName => ({
name: seriesName,
data: data[seriesName].map(item => ({
x: item.title,
y: item.value,
}))
}))
const options = {
series: series,
legend: { show: false },
title: { text: title },
chart: {
height: '100%',
type: 'treemap',
toolbar: {show: false},
animations: {enabled: animated},
events: {
click: function(event, chartContext, {seriesIndex, dataPointIndex}) {
if (!onBlockClickEventName) {
return
}
const block = data[series[seriesIndex].name][dataPointIndex]
component.call('onBlockClick', block)
},
}
},
plotOptions: {
treemap: {
distributed: distributed,
enableShades: enableShades,
}
},
colors: colors,
};
this.chart = new ApexCharts(this.$refs.container, options);
this.chart.render();
}
}
}
export default treeMapChart

View File

@@ -1,99 +1,8 @@
<div
class="w-full h-full"
x-data="{ ...areaChart() }"
x-init="drawChart(@this)"
x-on:draw-column-chart.window="drawChart(@this)"
style="width: 100%; height: 100%;"
x-data="{ ...livewireChartsAreaChart() }"
x-init="init()"
>
<div wire:ignore x-ref="container"></div>
<script>
function areaChart() {
return {
chart: null,
drawChart(component) {
if (this.chart) {
this.chart.destroy()
}
const title = component.get('areaChartModel.title');
const animated = component.get('areaChartModel.animated') || false;
const dataLabels = component.get('areaChartModel.dataLabels') || {};
const onPointClickEventName = component.get('areaChartModel.onPointClickEventName')
const data = component.get('areaChartModel.data');
const sparkline = component.get('areaChartModel.sparkline');
const categories = component.get('areaChartModel.xAxis.categories').length > 0
? component.get('areaChartModel.xAxis.categories')
: data.map(item => item.title)
;
var options = {
series: [{
name: title,
data: data.map(item => item.value)
}],
chart: {
type: 'area',
height: '100%',
...sparkline,
zoom: { enabled: false },
toolbar: { show: false },
animations: { enabled: animated },
events: {
markerClick: function(event, chartContext, { dataPointIndex }) {
if (!onPointClickEventName) {
return
}
const point = data[dataPointIndex]
component.call('onPointClick', point)
}
}
},
dataLabels: dataLabels,
colors: [component.get('areaChartModel.color') || '#2E93fA'],
stroke: {
curve: 'straight'
},
title: {
text: title,
align: 'center'
},
labels: data.map(item => item.title),
xaxis: {
labels: component.get('areaChartModel.xAxis.labels'),
categories: categories,
},
yaxis: component.get('areaChartModel.yAxis') || {},
grid: {
padding: {
left: 0,
top: 0,
right: 0,
bottom: 0,
}
},
};
this.chart = new ApexCharts(this.$refs.container, options);
this.chart.render();
}
}
}
</script>
</div>

View File

@@ -1,93 +1,8 @@
<div
class="w-full h-full"
x-data="{ ...columnChart() }"
x-init="drawChart(@this)"
x-on:draw-column-chart.window="drawChart(@this)"
style="width: 100%; height: 100%;"
x-data="{ ...livewireChartsColumnChart() }"
x-init="init()"
>
<div wire:ignore x-ref="container"></div>
<script>
function columnChart() {
return {
chart: null,
drawChart(component) {
if (this.chart) {
this.chart.destroy()
}
const animated = component.get('columnChartModel.animated') || false;
const onColumnClickEventName = component.get('columnChartModel.onColumnClickEventName')
const dataLabels = component.get('columnChartModel.dataLabels') || {};
const data = component.get('columnChartModel.data');
const sparkline = component.get('columnChartModel.sparkline');
const options = {
series: [{ data: data.map(item => item.value)}],
chart: {
type: 'bar',
height: '100%',
...sparkline,
toolbar: { show: false },
animations: { enabled: animated },
events: {
dataPointSelection: function(event, chartContext, config) {
if (!onColumnClickEventName) {
return
}
const { dataPointIndex } = config
const column = data[dataPointIndex]
component.call('onColumnClick', column)
},
}
},
colors: data.map(item => item.color),
labels: {
style: {
colors: data.map(item => item.color),
},
},
legend: component.get('columnChartModel.legend') || {},
plotOptions: {
bar: {
horizontal: false,
columnWidth: '40%',
distributed: true,
},
},
dataLabels: dataLabels,
xaxis: {
categories: data.map(item => item.title),
},
yaxis: {
title: {
text: component.get('columnChartModel.title'),
}
},
fill: {
opacity: component.get('columnChartModel.opacity') || 0.5
},
};
this.chart = new ApexCharts(this.$refs.container, options);
this.chart.render();
}
}
}
</script>
</div>

View File

@@ -1,109 +1,8 @@
<div
class="w-full h-full"
x-data="{ ...lineChart() }"
x-init="drawChart(@this)"
style="width: 100%; height: 100%;"
x-data="{ ...livewireChartsLineChart() }"
x-init="init()"
>
<div wire:ignore x-ref="container"></div>
<script>
function lineChart() {
return {
chart: null,
drawChart(component) {
if (this.chart) {
this.chart.destroy()
}
const title = component.get('lineChartModel.title');
const animated = component.get('lineChartModel.animated') || false;
const dataLabels = component.get('lineChartModel.dataLabels') || {};
const data = component.get('lineChartModel.data');
const onPointClickEventName = component.get('lineChartModel.onPointClickEventName');
const sparkline = component.get('lineChartModel.sparkline');
const series = [{
name: title,
data: data.map(item => item.value),
}]
const categories = component.get('lineChartModel.xAxis.categories').length > 0
? component.get('lineChartModel.xAxis.categories')
: data.map(item => item.title)
const options = {
series: series,
chart: {
type: 'line',
height: '100%',
...sparkline,
zoom: { enabled: false },
toolbar: { show: false },
animations: { enabled: animated },
events: {
markerClick: function(event, chartContext, { dataPointIndex }) {
if (!onPointClickEventName) {
return
}
const point = data[dataPointIndex]
component.call('onPointClick', point)
}
}
},
dataLabels: dataLabels,
stroke: component.get('lineChartModel.stroke') || {},
title: {
text: title,
align: 'center'
},
xaxis: {
labels: component.get('lineChartModel.xAxis.labels'),
categories: categories,
},
yaxis: component.get('lineChartModel.yAxis') || {},
annotations: {
points: component.get('lineChartModel.markers').map(item => {
return {
x: item.title,
y: item.value,
marker: {
size: 6,
fillColor: '#fff',
strokeColor: item.strokeColor,
radius: 2,
},
label: {
offsetY: 0,
style: {
color: item.textColor,
background: item.textBackgroundColor,
},
text: item.text || '',
}
}
}
)
},
};
this.chart = new ApexCharts(this.$refs.container, options);
this.chart.render();
}
}
}
</script>
</div>

View File

@@ -1,96 +1,8 @@
<div
class="w-full h-full"
x-data="{ ...multiColumnChart() }"
x-init="drawChart(@this)"
x-on:draw-column-chart.window="drawChart(@this)"
style="width: 100%; height: 100%;"
x-data="{ ...livewireChartsMultiColumnChart() }"
x-init="init()"
>
<div wire:ignore x-ref="container"></div>
<script>
function multiColumnChart() {
return {
chart: null,
drawChart(component) {
if (this.chart) {
this.chart.destroy()
}
const stacked = component.get('columnChartModel.isStacked');
const animated = component.get('columnChartModel.animated');
const onColumnClickEventName = component.get('columnChartModel.onColumnClickEventName')
const dataLabels = component.get('columnChartModel.dataLabels');
const data = component.get('columnChartModel.data');
const sparkline = component.get('columnChartModel.sparkline');
const series = Object.keys(data)
.map(seriesName => ({
name: seriesName,
data: data[seriesName].map(item => item.value)
}))
const categories = component.get('columnChartModel.xAxis.categories').length > 0
? component.get('columnChartModel.xAxis.categories')
: data[series[0].name].map(item => item.title)
;
const options = {
series: series,
chart: {
type: 'bar',
height: '100%',
stacked: stacked,
...sparkline,
toolbar: { show: false },
animations: { enabled: animated },
events: {
dataPointSelection: function(event, chartContext, {seriesIndex, dataPointIndex}) {
if (!onColumnClickEventName) {
return
}
const column = data[series[seriesIndex].name][dataPointIndex]
component.call('onColumnClick', column)
},
}
},
legend: component.get('columnChartModel.legend'),
plotOptions: {
bar: {
horizontal: false,
columnWidth: '50%',
},
},
dataLabels: dataLabels,
xaxis: {
categories: categories,
},
yaxis: {
title: {
text: component.get('columnChartModel.title'),
}
},
fill: {
opacity: component.get('columnChartModel.opacity'),
},
};
this.chart = new ApexCharts(this.$refs.container, options);
this.chart.render();
}
}
}
</script>
</div>

View File

@@ -1,87 +1,8 @@
<div
class="w-full h-full"
x-data="{ ...multiLineChart() }"
x-init="drawChart(@this)"
style="width: 100%; height: 100%;"
x-data="{ ...livewireChartsMultiLineChart() }"
x-init="init()"
>
<div wire:ignore x-ref="container"></div>
<script>
function multiLineChart() {
return {
chart: null,
drawChart(component) {
if (this.chart) {
this.chart.destroy()
}
const title = component.get('lineChartModel.title');
const animated = component.get('lineChartModel.animated') || false;
const dataLabels = component.get('lineChartModel.dataLabels') || {};
const data = component.get('lineChartModel.data');
const onPointClickEventName = component.get('lineChartModel.onPointClickEventName');
const sparkline = component.get('lineChartModel.sparkline');
const series = Object.keys(data).map(key => {
return {
name: key,
data: data[key].map(item => item.value),
}
})
const categories = component.get('lineChartModel.xAxis.categories').length > 0
? component.get('lineChartModel.xAxis.categories')
: data[series[0].name].map(item => item.title)
const options = {
series: series,
chart: {
type: 'line',
height: '100%',
...sparkline,
zoom: { enabled: false },
toolbar: { show: false },
animations: { enabled: animated },
events: {
markerClick: function(event, chartContext, { seriesIndex, dataPointIndex }) {
if (!onPointClickEventName) {
return
}
const point = data[series[seriesIndex].name][dataPointIndex]
component.call('onPointClick', point)
}
}
},
dataLabels: dataLabels,
stroke: component.get('lineChartModel.stroke') || {},
title: {
text: title,
align: 'center'
},
xaxis: {
labels: component.get('lineChartModel.xAxis.labels'),
categories: categories,
},
yaxis: component.get('lineChartModel.yAxis') || {},
};
this.chart = new ApexCharts(this.$refs.container, options);
this.chart.render();
}
}
}
</script>
</div>

View File

@@ -1,85 +1,8 @@
<div
class="w-full h-full"
x-data="{ ...pieChart() }"
x-init="drawChart(@this)"
style="width: 100%; height: 100%;"
x-data="{ ...livewireChartsPieChart() }"
x-init="init()"
>
<div wire:ignore x-ref="container"></div>
<script>
function pieChart() {
return {
chart: null,
drawChart(component) {
if (this.chart) {
this.chart.destroy()
}
const title = component.get('pieChartModel.title');
const animated = component.get('pieChartModel.animated') || false
const dataLabels = component.get('pieChartModel.dataLabels') || {}
const onSliceClickEventName = component.get('pieChartModel.onSliceClickEventName')
const data = component.get('pieChartModel.data')
const sparkline = component.get('pieChartModel.sparkline')
const options = {
series: data.map(item => item.value),
chart: {
height: '100%',
type: 'pie',
...sparkline,
animations: { enabled: animated },
events: {
dataPointSelection: function(event, chartContext, config) {
if (!onSliceClickEventName) {
return
}
const { dataPointIndex } = config
const slice = data[dataPointIndex]
component.call('onSliceClick', slice)
},
}
},
labels: data.map(item => item.title),
dataLabels: dataLabels,
colors: data.map(item => item.color),
fill: {
opacity: component.get('pieChartModel.opacity'),
},
title: {
text: title,
align: 'center',
},
responsive: [
{
breakpoint: 600,
options: {
legend: {
position: 'bottom'
}
}
}
],
legend: component.get('pieChartModel.legend') || {},
};
this.chart = new ApexCharts(this.$refs.container, options);
this.chart.render();
}
}
}
</script>
</div>

View File

@@ -0,0 +1,7 @@
<div
style="width: 100%; height: 100%;"
x-data="{ ...livewireChartsRadarChart() }"
x-init="init()"
>
<div wire:ignore x-ref="container"></div>
</div>

View File

@@ -0,0 +1,7 @@
<div
style="width: 100%; height: 100%;"
x-data="{ ...livewireChartsTreeMapChart() }"
x-init="init()"
>
<div wire:ignore x-ref="container"></div>
</div>

View File

@@ -26,7 +26,7 @@ class LivewireColumnChart extends Component
return;
}
$this->emit($onColumnClickEventName, $column);
$this->dispatch($onColumnClickEventName, $column);
}
public function render()

View File

@@ -26,7 +26,7 @@ class LivewirePieChart extends Component
return;
}
$this->emit($onSliceClickEventName, $slice);
$this->dispatch($onSliceClickEventName, $slice);
}
public function render()

View File

@@ -0,0 +1,36 @@
<?php
namespace Asantibanez\LivewireCharts\Charts;
use Asantibanez\LivewireCharts\Models\RadarChartModel;
use Livewire\Component;
/**
* Class LivewireRadarChart
* @package Asantibanez\LivewireCharts\Charts
*/
class LivewireRadarChart extends Component
{
public $radarChartModel;
public function mount(RadarChartModel $radarChartModel)
{
$this->radarChartModel = $radarChartModel->toArray();
}
public function onPointClick($point)
{
$onPointClickEventName = data_get($this->radarChartModel, 'onPointClickEventName', null);
if ($onPointClickEventName === null) {
return;
}
$this->emit($onPointClickEventName, $point);
}
public function render()
{
return view('livewire-charts::livewire-radar-chart');
}
}

View File

@@ -0,0 +1,36 @@
<?php
namespace Asantibanez\LivewireCharts\Charts;
use Asantibanez\LivewireCharts\Models\TreeMapChartModel;
use Livewire\Component;
/**
* Class LivewireTreeMapChart
* @package Asantibanez\LivewireCharts\Charts
*/
class LivewireTreeMapChart extends Component
{
public $treeMapChartModel;
public function mount(TreeMapChartModel $treeMapChartModel)
{
$this->treeMapChartModel = $treeMapChartModel->toArray();
}
public function onBlockClick($block)
{
$onBlockClickEventName = data_get($this->treeMapChartModel, 'onBlockClickEventName');
if ($onBlockClickEventName === null) {
return;
}
$this->dispatch($onBlockClickEventName, $block);
}
public function render()
{
return view('livewire-charts::livewire-tree-map-chart');
}
}

View File

@@ -0,0 +1,17 @@
<?php
namespace Asantibanez\LivewireCharts\Console;
use Illuminate\Console\Command;
class InstallCommand extends Command
{
protected $signature = 'livewire-charts:install';
protected $description = 'Installs Livewire Charts';
public function handle()
{
$this->call('vendor:publish', ['--tag' => 'livewire-charts:public']);
}
}

View File

@@ -6,6 +6,8 @@ use Asantibanez\LivewireCharts\Models\AreaChartModel;
use Asantibanez\LivewireCharts\Models\ColumnChartModel;
use Asantibanez\LivewireCharts\Models\LineChartModel;
use Asantibanez\LivewireCharts\Models\PieChartModel;
use Asantibanez\LivewireCharts\Models\RadarChartModel;
use Asantibanez\LivewireCharts\Models\TreeMapChartModel;
use Illuminate\Support\Facades\Facade;
/**
@@ -17,6 +19,8 @@ use Illuminate\Support\Facades\Facade;
* @method static ColumnChartModel multiColumnChartModel()
* @method static AreaChartModel areaChartModel()
* @method static PieChartModel pieChartModel()
* @method static RadarChartModel radarChartModel()
* @method static TreeMapChartModel treeMapChartModel()
*/
class LivewireCharts extends Facade
{

View File

@@ -8,6 +8,8 @@ use Asantibanez\LivewireCharts\Models\AreaChartModel;
use Asantibanez\LivewireCharts\Models\ColumnChartModel;
use Asantibanez\LivewireCharts\Models\LineChartModel;
use Asantibanez\LivewireCharts\Models\PieChartModel;
use Asantibanez\LivewireCharts\Models\RadarChartModel;
use Asantibanez\LivewireCharts\Models\TreeMapChartModel;
class LivewireCharts
{
@@ -44,4 +46,14 @@ class LivewireCharts
{
return new PieChartModel;
}
public function radarChartModel()
{
return new RadarChartModel();
}
public function treeMapChartModel()
{
return new TreeMapChartModel();
}
}

View File

@@ -6,35 +6,82 @@ use Asantibanez\LivewireCharts\Charts\LivewireAreaChart;
use Asantibanez\LivewireCharts\Charts\LivewireColumnChart;
use Asantibanez\LivewireCharts\Charts\LivewireLineChart;
use Asantibanez\LivewireCharts\Charts\LivewirePieChart;
use Asantibanez\LivewireCharts\Charts\LivewireRadarChart;
use Asantibanez\LivewireCharts\Charts\LivewireTreeMapChart;
use Asantibanez\LivewireCharts\Console\InstallCommand;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\ServiceProvider;
use Livewire\Livewire;
class LivewireChartsServiceProvider extends ServiceProvider
{
/**
* Bootstrap the application services.
*/
public function boot()
{
$this->loadViewsFrom(__DIR__.'/../resources/views', 'livewire-charts');
$this->registerCommands();
if ($this->app->runningInConsole()) {
$this->publishes([
__DIR__.'/../resources/views' => resource_path('views/vendor/livewire-charts'),
], 'livewire-charts-views');
}
$this->registerViews();
Livewire::component('livewire-line-chart', LivewireLineChart::class);
Livewire::component('livewire-column-chart', LivewireColumnChart::class);
Livewire::component('livewire-pie-chart', LivewirePieChart::class);
Livewire::component('livewire-area-chart', LivewireAreaChart::class);
$this->registerPublishables();
$this->registerComponents();
$this->registerDirectives();
}
/**
* Register the application services.
*/
public function register()
{
$this->app->bind('livewirecharts', LivewireCharts::class);
}
private function registerCommands()
{
if ($this->app->runningInConsole()) {
$this->commands([
InstallCommand::class,
]);
}
}
private function registerViews()
{
$this->loadViewsFrom(__DIR__.'/../resources/views', 'livewire-charts');
}
private function registerPublishables()
{
if ($this->app->runningInConsole()) {
$this->publishes([
__DIR__.'/../resources/views' => resource_path('views/vendor/livewire-charts'),
], 'livewire-charts:views');
$this->publishes([
__DIR__.'/../resources/js' => resource_path('js/vendor/livewire-charts'),
], 'livewire-charts:scripts');
$this->publishes([
__DIR__.'/../public' => public_path('vendor/livewire-charts'),
], 'livewire-charts:public');
}
}
private function registerComponents()
{
Livewire::component('livewire-line-chart', LivewireLineChart::class);
Livewire::component('livewire-column-chart', LivewireColumnChart::class);
Livewire::component('livewire-pie-chart', LivewirePieChart::class);
Livewire::component('livewire-area-chart', LivewireAreaChart::class);
Livewire::component('livewire-radar-chart', LivewireRadarChart::class);
Livewire::component('livewire-tree-map-chart', LivewireTreeMapChart::class);
}
private function registerDirectives()
{
Blade::directive('livewireChartsScripts', function () {
$scriptsUrl = asset('/vendor/livewire-charts/app.js');
return <<<EOF
<script src="$scriptsUrl"></script>
EOF;
});
}
}

View File

@@ -16,6 +16,10 @@ class BaseChartModel
use HasLegend;
use HasDataLabels;
use HasSparkline;
use HasGrid;
use HasColors;
use HasTheme;
use HasJsonConfig;
public function __construct()
{
@@ -26,6 +30,10 @@ class BaseChartModel
$this->initLegend();
$this->initDataLabels();
$this->initSparkline();
$this->initGrid();
$this->initColors();
$this->initTheme();
$this->initJsonConfig();
}
public function reactiveKey()
@@ -42,7 +50,11 @@ class BaseChartModel
$this->strokeToArray(),
$this->legendToArray(),
$this->dataLabelsToArray(),
$this->sparklineToArray()
$this->sparklineToArray(),
$this->gridToArray(),
$this->colorsToArray(),
$this->themeToArray(),
$this->jsonConfigToArray(),
);
}
@@ -55,5 +67,9 @@ class BaseChartModel
$this->legendFromArray($array);
$this->dataLabelsFromArray($array);
$this->sparklineFromArray($array);
$this->gridFromArray($array);
$this->colorsFromArray($array);
$this->themeFromArray($array);
$this->jsonConfigFromArray($array);
}
}

View File

@@ -11,15 +11,19 @@ namespace Asantibanez\LivewireCharts\Models;
*/
class ColumnChartModel extends BaseChartModel
{
public $opacity;
private $opacity;
public $isMultiColumn;
private $columnWidth;
public $isStacked;
private $horizontal;
public $onColumnClickEventName;
private $isMultiColumn;
public $data;
private $isStacked;
private $onColumnClickEventName;
private $data;
public function __construct()
{
@@ -27,7 +31,11 @@ class ColumnChartModel extends BaseChartModel
$this->onColumnClickEventName = null;
$this->opacity = 0.5;
$this->opacity = 0.75;
$this->columnWidth = 70;
$this->horizontal = false;
$this->isMultiColumn = false;
@@ -57,6 +65,27 @@ class ColumnChartModel extends BaseChartModel
return $this;
}
public function setHorizontal()
{
$this->horizontal = true;
return $this;
}
public function setVertical()
{
$this->horizontal = false;
return $this;
}
public function setColumnWidth($value)
{
$this->columnWidth = $value;
return $this;
}
public function setOpacity($opacity)
{
$this->opacity = $opacity;
@@ -104,6 +133,8 @@ class ColumnChartModel extends BaseChartModel
return array_merge(parent::toArray(), [
'onColumnClickEventName' => $this->onColumnClickEventName,
'opacity' => $this->opacity,
'horizontal' => $this->horizontal,
'columnWidth' => $this->columnWidth,
'isMultiColumn' => $this->isMultiColumn,
'isStacked' => $this->isStacked,
'data' => $this->data->toArray(),
@@ -118,6 +149,10 @@ class ColumnChartModel extends BaseChartModel
$this->opacity = data_get($array, 'opacity', 0.5);
$this->columnWidth = data_get($array, 'columnWidth', 70);
$this->horizontal = data_get($array, 'horizontal', false);
$this->isMultiColumn = data_get($array, 'isMultiColumn', false);
$this->isStacked = data_get($array, 'isStacked', false);

67
src/Models/HasColors.php Normal file
View File

@@ -0,0 +1,67 @@
<?php
namespace Asantibanez\LivewireCharts\Models;
trait HasColors
{
private $colors;
private $enableShades;
public function setColors($colors)
{
$this->colors = $colors;
return $this;
}
public function addColor($color)
{
$this->colors[] = $color;
return $this;
}
public function enableShades()
{
$this->enableShades = true;
return $this;
}
public function disableShades()
{
$this->enableShades = false;
return $this;
}
protected function initColors()
{
$this->colors = $this->defaultColors();
$this->enableShades = true;
}
private function defaultColors()
{
return [];
}
protected function colorsFromArray($array)
{
$this->colors = data_get($array, 'colors', $this->defaultColors());
$this->enableShades = data_get($array, 'enableShades', true);
}
protected function colorsToArray()
{
return [
'colors' => $this->colors,
'enableShades' => $this->enableShades,
];
}
}

66
src/Models/HasGrid.php Normal file
View File

@@ -0,0 +1,66 @@
<?php
namespace Asantibanez\LivewireCharts\Models;
trait HasGrid
{
private $grid;
public function setGridVisible($visible)
{
data_set($this->grid, 'show', $visible);
return $this;
}
public function withGrid()
{
data_set($this->grid, 'show', true);
return $this;
}
public function withoutGrid()
{
data_set($this->grid, 'show', false);
return $this;
}
protected function initGrid()
{
$this->grid = $this->defaultGrid();
}
private function defaultGrid()
{
return [
'show' => false,
'position' => 'back',
'xaxis' => [
'lines' => [
'show' => true,
],
],
'yaxis' => [
'lines' => [
'show' => true,
],
],
];
}
protected function gridFromArray($array)
{
$this->grid = data_get($array, 'grid', $this->defaultGrid());
}
protected function gridToArray()
{
return [
'grid' => $this->grid,
];
}
}

View File

@@ -0,0 +1,39 @@
<?php
namespace Asantibanez\LivewireCharts\Models;
trait HasJsonConfig
{
private $jsonConfig;
public function setJsonConfig($jsonConfig)
{
$this->jsonConfig = $jsonConfig;
return $this;
}
protected function initJsonConfig()
{
$this->jsonConfig = [];
}
private function defaultJsonConfig()
{
return [];
}
protected function jsonConfigFromArray($array)
{
$this->jsonConfig = data_get($array, 'jsonConfig', $this->defaultJsonConfig());
}
protected function jsonConfigToArray()
{
return [
'jsonConfig' => $this->jsonConfig,
];
}
}

View File

@@ -7,6 +7,7 @@ namespace Asantibanez\LivewireCharts\Models;
trait HasStroke
{
private $stroke;
private $width;
public function initStroke()
{
@@ -17,6 +18,7 @@ trait HasStroke
{
return [
'curve' => 'straight',
'width' => 4
];
}
@@ -34,6 +36,13 @@ trait HasStroke
return $this;
}
public function setStrokeWidth($width)
{
data_set($this->stroke, 'width', $width);
return $this;
}
protected function strokeToArray()
{
return [

125
src/Models/HasTheme.php Normal file
View File

@@ -0,0 +1,125 @@
<?php
namespace Asantibanez\LivewireCharts\Models;
trait HasTheme
{
private $theme;
private $mode;
private $palette;
/**
* Initialize
*/
public function initTheme()
{
$this->theme = $this->defaultTheme();
}
/**
* set default theme
*
* @return array $theme
*/
private function defaultTheme()
{
return [
'mode' => 'light',
'palette' => 'palette1'
];
}
/**
* set theme mode
*
* @param string $mode
*
* @return $this
*/
public function setThemeMode(string $mode)
{
data_set($this->theme, 'mode', $mode);
return $this;
}
/**
* set theme mode to dark theme
*
* @return $this
*/
public function darkMode()
{
data_set($this->theme, 'mode', 'dark');
return $this;
}
/**
* set theme mode to light theme
*
* @return $this
*/
public function lightMode()
{
data_set($this->theme, 'mode', 'light');
return $this;
}
/**
* set the dark mode option to on or off
*
* @param bool $status = true
*
* @return $this
*/
public function setDarkMode(bool $status = true)
{
data_set($this->theme, 'mode', $status ? 'dark' : 'light');
return $this;
}
/**
* set theme pallete
*
* @param string $pallete
*
* @return $this
*/
public function setThemePalette(string $palette)
{
data_set($this->theme, 'palette', $palette);
return $this;
}
/**
* convert the theme to array
*
* @param string $mode
*
* @return $this
*/
protected function themeToArray()
{
return [
'theme' => $this->theme,
];
}
/**
* set theme from array
*
* @param string $mode
*
* @return $this
*/
protected function themeFromArray($array)
{
$this->theme = data_get($array, 'theme', $this->defaultTheme());
}
}

View File

@@ -9,11 +9,13 @@ namespace Asantibanez\LivewireCharts\Models;
*/
class PieChartModel extends BaseChartModel
{
public $onSliceClickEventName;
private $onSliceClickEventName;
public $opacity;
private $opacity;
public $data;
private $type;
private $data;
public function __construct()
{
@@ -23,6 +25,8 @@ class PieChartModel extends BaseChartModel
$this->opacity = 0.75;
$this->type = 'pie';
$this->data = collect();
}
@@ -33,6 +37,23 @@ class PieChartModel extends BaseChartModel
return $this;
}
public function setType($type)
{
$this->type = $type;
return $this;
}
public function asPie()
{
return $this->setType('pie');
}
public function asDonut()
{
return $this->setType('donut');
}
public function withOnSliceClickEvent($onSliceClickEventName)
{
$this->onSliceClickEventName = $onSliceClickEventName;
@@ -57,6 +78,7 @@ class PieChartModel extends BaseChartModel
return array_merge(parent::toArray(), [
'onSliceClickEventName' => $this->onSliceClickEventName,
'opacity' => $this->opacity,
'type' => $this->type,
'data' => $this->data->toArray(),
]);
}
@@ -69,6 +91,8 @@ class PieChartModel extends BaseChartModel
$this->opacity = data_get($array, 'opacity', 0.75);
$this->type = data_get($array, 'type', 'pie');
$this->data = collect(data_get($array, 'data', []));
}
}

View File

@@ -0,0 +1,95 @@
<?php
namespace Asantibanez\LivewireCharts\Models;
/**
* Class ColumnChartModel
* @package Asantibanez\LivewireCharts\Models
* @property boolean $isMultiColumn
* @property boolean $isStacked
*/
class RadarChartModel extends BaseChartModel
{
public $opacity;
public $colors;
public $onPointClickEventName;
public $data;
public function __construct()
{
parent::__construct();
$this->onPointClickEventName = null;
$this->opacity = 0.5;
$this->colors = ['#2E93fA', '#66DA26', '#546E7A', '#E91E63', '#FF9800'];
$this->data = collect();
}
public function setColors($colors)
{
$this->colors = $colors;
return $this;
}
public function setOpacity($opacity)
{
$this->opacity = $opacity;
return $this;
}
public function withOnPointClickEvent($onPointClickEventName)
{
$this->onPointClickEventName = $onPointClickEventName;
return $this;
}
public function addSeries($seriesName, $title, $value, $extras = [])
{
$series = $this->data->get($seriesName, collect());
$series->push([
'seriesName' => $seriesName,
'title' => $title,
'value' => $value,
'extras' => $extras,
]);
$this->data->put($seriesName, $series);
return $this;
}
public function toArray()
{
return array_merge(parent::toArray(), [
'onPointClickEventName' => $this->onPointClickEventName,
'opacity' => $this->opacity,
'colors' => $this->colors,
'data' => $this->data->toArray(),
]);
}
public function fromArray($array)
{
parent::fromArray($array);
$this->onPointClickEventName = data_get($array, 'onPointClickEventName', null);
$this->opacity = data_get($array, 'opacity', 0.5);
$this->colors = data_get($array, 'color', '#90cdf4');
$this->data = collect(data_get($array, 'data', []));
}
}

View File

@@ -0,0 +1,84 @@
<?php
namespace Asantibanez\LivewireCharts\Models;
/**
* Class TreeMapChartModel
* @package Asantibanez\LivewireCharts\Models
*/
class TreeMapChartModel extends BaseChartModel
{
use HasTitle;
use HasColors;
public $data;
public $distributed;
public $onBlockClickEventName;
public function __construct()
{
parent::__construct();
$this->data = collect();
$this->distributed = false;
$this->setColors(['#2E93fA']);
}
public function setDistributed($distributed)
{
$this->distributed = $distributed;
return $this;
}
public function addBlock($title, $value, $extras = [])
{
return $this->addSeriesBlock($this->title, $title, $value, $extras);
}
public function addSeriesBlock($seriesName, $title, $value, $extras = [])
{
$series = $this->data->get($seriesName, collect());
$series->push([
'seriesName' => $seriesName,
'title' => $title,
'value' => $value,
'extras' => $extras,
]);
$this->data->put($seriesName, $series);
return $this;
}
public function withOnBlockClickEvent($onBlockClickEventName)
{
$this->onBlockClickEventName = $onBlockClickEventName;
return $this;
}
public function toArray()
{
return array_merge(parent::toArray(), [
'data' => $this->data->toArray(),
'distributed' => $this->distributed,
'onBlockClickEventName' => $this->onBlockClickEventName,
]);
}
public function fromArray($array)
{
parent::fromArray($array);
$this->data = collect(data_get($array, 'data', []));
$this->distributed = data_get($array, 'distributed', false);
$this->onBlockClickEventName = data_get($array, 'onBlockClickEventName', null);
}
}

View File

@@ -1,21 +0,0 @@
<?php
namespace Asantibanez\LivewireCharts\Tests;
use Orchestra\Testbench\TestCase;
use Asantibanez\LivewireCharts\LivewireChartsServiceProvider;
class ExampleTest extends TestCase
{
protected function getPackageProviders($app)
{
return [LivewireChartsServiceProvider::class];
}
/** @test */
public function true_is_true()
{
$this->assertTrue(true);
}
}

25
tests/LivewireAreaChartTest.php Executable file
View File

@@ -0,0 +1,25 @@
<?php
namespace Asantibanez\LivewireCharts\Tests;
use Asantibanez\LivewireCharts\Charts\LivewireAreaChart;
use Livewire\Features\SupportTesting\Testable;
use Livewire\Livewire;
class LivewireAreaChartTest extends TestCase
{
private function buildComponent() : Testable
{
return Livewire::test(LivewireAreaChart::class);
}
/** @test */
public function can_build_component()
{
//Act
$component = $this->buildComponent();
//Assert
$this->assertNotNull($component);
}
}

View File

@@ -0,0 +1,44 @@
<?php
namespace Asantibanez\LivewireCharts\Tests;
use Asantibanez\LivewireCharts\Charts\LivewireColumnChart;
use Livewire\Features\SupportTesting\Testable;
use Livewire\Livewire;
class LivewireColumnChartTest extends TestCase
{
private function buildComponent() : Testable
{
return Livewire::test(LivewireColumnChart::class);
}
/** @test */
public function can_build_component()
{
//Act
$component = $this->buildComponent();
//Assert
$this->assertNotNull($component);
}
/** @test */
public function should_emit_event_if_present()
{
//Arrange
$component = $this->buildComponent();
$columnChartModel = $component->columnChartModel;
data_set($columnChartModel, 'onColumnClickEventName', 'custom-event');
$component->set('columnChartModel', $columnChartModel);
//Act
$component->runAction('onColumnClick', []);
//Assert
$component->assertDispatched('custom-event');
}
}

25
tests/LivewireLineChartTest.php Executable file
View File

@@ -0,0 +1,25 @@
<?php
namespace Asantibanez\LivewireCharts\Tests;
use Asantibanez\LivewireCharts\Charts\LivewireLineChart;
use Livewire\Features\SupportTesting\Testable;
use Livewire\Livewire;
class LivewireLineChartTest extends TestCase
{
private function buildComponent() : Testable
{
return Livewire::test(LivewireLineChart::class);
}
/** @test */
public function can_build_component()
{
//Act
$component = $this->buildComponent();
//Assert
$this->assertNotNull($component);
}
}

44
tests/LivewirePieChartTest.php Executable file
View File

@@ -0,0 +1,44 @@
<?php
namespace Asantibanez\LivewireCharts\Tests;
use Asantibanez\LivewireCharts\Charts\LivewirePieChart;
use Livewire\Features\SupportTesting\Testable;
use Livewire\Livewire;
class LivewirePieChartTest extends TestCase
{
private function buildComponent() : Testable
{
return Livewire::test(LivewirePieChart::class);
}
/** @test */
public function can_build_component()
{
//Act
$component = $this->buildComponent();
//Assert
$this->assertNotNull($component);
}
/** @test */
public function should_emit_event_if_present()
{
//Arrange
$component = $this->buildComponent();
$pieChartModel = $component->pieChartModel;
data_set($pieChartModel, 'onSliceClickEventName', 'custom-event');
$component->set('pieChartModel', $pieChartModel);
//Act
$component->runAction('onSliceClick', []);
//Assert
$component->assertDispatched('custom-event');
}
}

View File

@@ -0,0 +1,25 @@
<?php
namespace Asantibanez\LivewireCharts\Tests;
use Asantibanez\LivewireCharts\Charts\LivewireRadarChart;
use Livewire\Features\SupportTesting\Testable;
use Livewire\Livewire;
class LivewireRadarChartTest extends TestCase
{
private function buildComponent() : Testable
{
return Livewire::test(LivewireRadarChart::class);
}
/** @test */
public function can_build_component()
{
//Act
$component = $this->buildComponent();
//Assert
$this->assertNotNull($component);
}
}

View File

@@ -0,0 +1,44 @@
<?php
namespace Asantibanez\LivewireCharts\Tests;
use Asantibanez\LivewireCharts\Charts\LivewireTreeMapChart;
use Livewire\Features\SupportTesting\Testable;
use Livewire\Livewire;
class LivewireTreeMapChartTest extends TestCase
{
private function buildComponent() : Testable
{
return Livewire::test(LivewireTreeMapChart::class);
}
/** @test */
public function can_build_component()
{
//Act
$component = $this->buildComponent();
//Assert
$this->assertNotNull($component);
}
/** @test */
public function should_emit_event_if_present()
{
//Arrange
$component = $this->buildComponent();
$treeMapChartModel = $component->treeMapChartModel;
data_set($treeMapChartModel, 'onBlockClickEventName', 'custom-event');
$component->set('treeMapChartModel', $treeMapChartModel);
//Act
$component->runAction('onBlockClick', []);
//Assert
$component->assertDispatched('custom-event');
}
}

25
tests/TestCase.php Executable file
View File

@@ -0,0 +1,25 @@
<?php
namespace Asantibanez\LivewireCharts\Tests;
use Asantibanez\LivewireCharts\LivewireChartsServiceProvider;
use Livewire\LivewireServiceProvider;
use Orchestra\Testbench\TestCase as BaseTestCase;
class TestCase extends BaseTestCase
{
protected function getPackageProviders($app)
{
return [
LivewireServiceProvider::class,
LivewireChartsServiceProvider::class
];
}
protected function getEnvironmentSetUp($app)
{
$app['config']->set('app.key', 'base64:Hupx3yAySikrM2/edkZQNQHslgDWYfiBfCuSThJ5SK8=');
}
}

3
webpack.mix.js Normal file
View File

@@ -0,0 +1,3 @@
let mix = require('laravel-mix')
mix.js('resources/js/app.js', 'public/')