Skip to content

Commit

Permalink
feat: add react-vega-lite
Browse files Browse the repository at this point in the history
  • Loading branch information
kristw committed Apr 3, 2019
1 parent f7b83d6 commit 87b3512
Show file tree
Hide file tree
Showing 4 changed files with 198 additions and 0 deletions.
148 changes: 148 additions & 0 deletions packages/react-vega-lite/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
<!--**Introduction**-->
<!--| [API Reference](https://github.com/kristw/react-vega-lite/blob/master/docs/api.md)-->
<!--| [Demo](https://kristw.github.io/react-vega-lite)-->

# react-vega-lite [![NPM version][npm-image]][npm-url] [![Dependency Status][daviddm-image]][daviddm-url]

<!--[![Build Status][travis-image]][travis-url]-->

Convert Vega Lite spec into React class conveniently, inspired by this [tutorial](https://medium.com/@pbesh/react-and-vega-an-alternative-visualization-example-cd76e07dc1cd#.omslw1xy8) by @pbeshai

`react-vega-lite: 1.x.x` was update with breaking changes to support Vega-Lite 2.0, which is still in beta.
If you are looking to use React with Vega Lite 1.x, please use `react-vega-lite: 0.0.1`.

## Examples

- http://vega.github.io/react-vega-lite/

## Install

```bash
npm install vega vega-lite react-vega react-vega-lite --save
```

## Example code

There are two approaches to use this libary.

### Approach#1 Create class from spec, then get a React class to use

#### BarChart.js

```javascript
import React, { PropTypes } from 'react';
import {createClassFromLiteSpec} from 'react-vega-lite';

export default createClassFromLiteSpec('BarChart', {
"description": "A simple bar chart with embedded data.",
"mark": "bar",
"encoding": {
"x": {"field": "a", "type": "ordinal"},
"y": {"field": "b", "type": "quantitative"}
}
});
```

#### main.js

```javascript
import React from 'react';
import ReactDOM from 'react-dom';
import BarChart from './BarChart.js';

const barData = {
"values": [
{"a": "A","b": 20}, {"a": "B","b": 34}, {"a": "C","b": 55},
{"a": "D","b": 19}, {"a": "E","b": 40}, {"a": "F","b": 34},
{"a": "G","b": 91}, {"a": "H","b": 78}, {"a": "I","b": 25}
]
};

ReactDOM.render(
<BarChart data={barData} />,
document.getElementById('bar-container')
);
```

### Approach#2 Use `<VegaLite>` generic class and pass in `spec` for dynamic component.

Provides a bit more flexibility, but at the cost of extra checks for spec changes.

#### main.js

```javascript
import React from 'react';
import ReactDOM from 'react-dom';
import VegaLite from 'react-vega-lite';

const spec = {
"description": "A simple bar chart with embedded data.",
"mark": "bar",
"encoding": {
"x": {"field": "a", "type": "ordinal"},
"y": {"field": "b", "type": "quantitative"}
}
};

const barData = {
"values": [
{"a": "A","b": 20}, {"a": "B","b": 34}, {"a": "C","b": 55},
{"a": "D","b": 19}, {"a": "E","b": 40}, {"a": "F","b": 34},
{"a": "G","b": 91}, {"a": "H","b": 78}, {"a": "I","b": 25}
]
};

ReactDOM.render(
<VegaLite spec={spec} data={barData} />,
document.getElementById('bar-container')
);
```

### Props

React class `VegaLite` and any output class from `createClassFromLiteSpec` have these properties:

- **className**:String
- **style**:Object

- **width**:Number
- **height**:Number
- **padding**:Object
- **renderer**:String
- **logLevel**:Number
- **background**:String
- **enableHover**:Boolean

- **data**:Object

- **onSignal***XXX*

- **onNewView**
- **onParseError**

which are the same with `react-vega`. Please refer to [react-vega documentation](https://github.com/kristw/react-vega#props).

### Static function

Any class created from `createClassFromLiteSpec` will have this function.

- Chart.**getSpec()** - return `spec`

## Frequently Asked Questions

### How to use Vega Tooltip?

You can pass the [`vega-tooltip`](https://github.com/vega/vega-tooltip) handler instance to the `tooltip` property.

```javascript
import { Handler } from 'vega-tooltip';

<VegaLite spec={spec} data={barData} tooltip={new Handler().call} />
```

[npm-image]: https://badge.fury.io/js/react-vega-lite.svg
[npm-url]: https://npmjs.org/package/react-vega-lite
[travis-image]: https://travis-ci.org/kristw/react-vega-lite.svg?branch=master
[travis-url]: https://travis-ci.org/kristw/react-vega-lite
[daviddm-image]: https://david-dm.org/kristw/react-vega-lite.svg?theme=shields.io
[daviddm-url]: https://david-dm.org/kristw/react-vega-lite
20 changes: 20 additions & 0 deletions packages/react-vega-lite/src/VegaLite.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from 'react';
import * as vl from 'vega-lite';
import Vega from 'react-vega';

const VegaLite = props => {
const parsedProps = { ...props };
const { spec, data } = props;
const combinedSpec = { ...spec };
if (data) {
combinedSpec.data = data;
delete parsedProps.data;
}
parsedProps.spec = vl.compile(combinedSpec).spec;

return <Vega {...parsedProps} />;
};

VegaLite.propTypes = Vega.propTypes;

export default VegaLite;
25 changes: 25 additions & 0 deletions packages/react-vega-lite/src/createClassFromLiteSpec.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import React from 'react';
import VegaLite from './VegaLite';

// USAGE:
// createClassFromLiteSpec(name, spec);
// createClassFromLiteSpec(spec);
export default function createClassFromLiteSpec(...args) {
const spec = args.length === 1 ? args[0] : args[1];

// eslint-disable-next-line react/forbid-foreign-prop-types
const propTypes = { ...VegaLite.propTypes };
delete propTypes.spec;

function Chart(props) {
return <VegaLite spec={spec} {...props} />;
}

Chart.getSpec = function getSpec() {
return spec;
};

Chart.propTypes = propTypes;

return Chart;
}
5 changes: 5 additions & 0 deletions packages/react-vega-lite/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import VegaLite from './VegaLite';
import _createClassFromLiteSpec from './createClassFromLiteSpec';

export default VegaLite;
export const createClassFromLiteSpec = _createClassFromLiteSpec;

0 comments on commit 87b3512

Please sign in to comment.