# @nebula.js/sn-pie-chart

A pie chart is a circular chart divided into more slices that each represent a proportion of the whole. Pie charts are most visually efficient when a small number (10 or fewer) of slices are displayed.

## Requirements

Requires `@nebula.js/stardust` version `1.7.0` or later.

## Installing

If you use npm: `npm install @nebula.js/sn-pie-chart`. You can also load through the script tag directly from [https://unpkg.com](https://unpkg.com/@nebula.js/sn-pie-chart).

## Usage

```js
import { embed } from '@nebula.js/stardust';
import pie from '@nebula.js/sn-pie-chart';

// 'app' is an enigma app model
const nuked = embed(app, {
  types: [{ // register pie chart
    name: 'piechart',
    load: () => Promise.resolve(pie);
  }]
});

nuked.render({
  element: document.querySelector('.pie'),
  type: 'piechart',
  fields: ['Year', '=Avg(Price)'],

  // Overrides default properties
  properties: {
    title: 'Price of Cars by Year',
    dataPoint: {
        labelMode: 'none'
    },
  },
});
```

## More examples

### One dimension, one measure, value labels

```js
nuked.render({
  element: document.querySelector('.pie'),
  type: 'piechart',
  fields: ['Country', '=Avg(Price)'],

  // Overrides default properties
  properties: {
    title: 'Price of Cars by Country',
    dataPoint: {
      labelMode: 'value',
    },
  },
});
```

### One dimension, two measures, percentage labels

```js
nuked.render({
  element: document.querySelector('.pie'),
  type: 'piechart',
  fields: ['Country', '=Avg(Price)', '=Avg(Horsepower)'],

  // Overrides default properties
  properties: {
    title: 'Price and horsepower by country',
    dataPoint: {
      labelMode: 'share',
    },
  },
});
```

### One dimension, one measure, donut chart view

```js
nuked.render({
  element: document.querySelector('.pie'),
  type: 'piechart',
  fields: ['Country', '=Avg(Price)'],

  // Overrides default properties
  properties: {
    title: 'Price by country',
    dataPoint: {
      labelMode: 'share',
    },
    donut: {
      showAsDonut: true,
    },
  },
});
```

### One dimension, two measures, donut chart view

```js
nuked.render({
  element: document.querySelector('.pie'),
  type: 'piechart',
  fields: ['Country', '=Avg(Price)', '=Avg(Horsepower)'],

  // Overrides default properties
  properties: {
    title: 'Price and horsepower by country',
    dataPoint: {
      labelMode: 'share',
    },
    donut: {
      showAsDonut: true,
    },
  },
});
```

## Pie chart plugins

A plugin can be passed into a pie chart to add or modify its capability
or visual appearance.
A plugin needs to be defined before it can be rendered together with the chart.

```js
// Step 1: define the plugin

// Modifying the look of the dimension title component
const totalPopulationLabelPlugin = {
  info: {
    name: 'total-title-plugin',
    type: 'component-definition',
  },
  fn: ({ keys, layout }) => {
    const componentDefinition = {
      type: 'text',
      text: 'World Total: 7.9 Billions',
      layout: { dock: 'bottom' },
    };
    return componentDefinition;
  },
};

// Step 2: passing the plugin definition into the render function

// Render a pie chart with plugins
nuked.render({
  element: document.querySelector('#object'),
  type: 'sn-pie-chart',
  plugins: [totalPopulationLabelPlugin],
  fields: ['Country', '=Sum(Population)'],
  properties: {
    dataPoint: { labelMode: 'value' },
  },
});
```

The plugin definition is an object, with two properties `info` and `fn`.
The `fn` returns a `picasso.js` component. To build this component,
some important chart internals are passed into the argument object of `fn`.

```js
// Structure of the argument object of fn
const pluginArgs = {
  layout,
  keys: {
    SCALE: { FILL },
    COMPONENT: { DIMENSION_TITLE, SLICES, PIE_LABELS },
  },
};
```

With plugins, you can either add new components or modify existing components
of the pie chart.

### Modify existing components

As an example, the appearance of the slices can be
modified by plugins.

To overide an existing component, `fn` should returns a `picasso.js` component
that has the same `key` as the existing component (`keys.COMPONENT.SLICES` in
this example)

```js
// Modifying the look of the slices component
const slicesPlugin = {
  info: {
    name: 'pie-plugin',
    type: 'component-definition',
  },
  fn: ({ keys, layout }) => {
    const componentDefinition = {
      type: 'pie',

      // Provide the same name as the exisiting component to override it
      key: keys.COMPONENT.SLICES,
      settings: {
        slice: {
          innerRadius: 0.6,
          strokeWidth: 0,
          stroke: 'red',
          outerRadius: 0.8,
          cornerRadius: 2,
        },
      },
    };
    return componentDefinition;
  },
};
```

### Add new components

The new component can be a standard Picasso component
or a custom Picasso component. The code for adding a new component is
similar to that for modifying an existing component, the only difference
is that the `key` should be different from that of
any of the existing components.

### Plugins disclaimer

- The plugins API is still experimental.
- We can not guarantee our charts to be compatible with all different settings, especially when modifying existing components.
