# @data-ui/histogram

> React + d3 library for creating histograms

Latest version **0.0.84** (published 2019-11-19) · MIT license · 0 weekly downloads

## Install

```sh
npm install @data-ui/histogram
pnpm add @data-ui/histogram
yarn add @data-ui/histogram
bun add @data-ui/histogram
```

## Health

**Score 20/100 (F)** — status: abandoned.

Positive: esm support; no vulnerabilities.

Warnings: low downloads; no types; pre 1.0.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 0.0.84 |
| Published | 2019-11-19 |
| First published | 2017-08-04 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | none |
| Module format | ESM + CommonJS |
| Dependencies | 17 |
| Unpacked size | 119.4 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 558 |
| Author | Chris Williams @williaster |
| Maintainers | data-ui |
| Keywords | vx, react, d3, visualization, histogram, density, buckets, chart, data |

## Links

- npm: https://www.npmjs.com/package/@data-ui/histogram
- Repository: https://github.com/williaster/data-ui
- Homepage: https://github.com/williaster/data-ui#readme
- Issues: https://github.com/williaster/data-ui/issues
- npm.io page: https://npm.io/package/@data-ui/histogram

## Dependencies (17)

- [@vx/axis](https://npm.io/package/@vx/axis.md) ^0.0.179
- [d3-array](https://npm.io/package/d3-array.md) ^1.2.0
- [d3-scale](https://npm.io/package/d3-scale.md) ^1.0.6
- [@vx/curve](https://npm.io/package/@vx/curve.md) ^0.0.165
- [@vx/event](https://npm.io/package/@vx/event.md) ^0.0.179
- [@vx/glyph](https://npm.io/package/@vx/glyph.md) ^0.0.179
- [@vx/group](https://npm.io/package/@vx/group.md) ^0.0.170
- [@vx/scale](https://npm.io/package/@vx/scale.md) ^0.0.179
- [@vx/shape](https://npm.io/package/@vx/shape.md) ^0.0.179
- [prop-types](https://npm.io/package/prop-types.md) ^15.5.10
- [react-move](https://npm.io/package/react-move.md) ^2.1.0
- [@vx/pattern](https://npm.io/package/@vx/pattern.md) ^0.0.179
- [@vx/tooltip](https://npm.io/package/@vx/tooltip.md) 0.0.179
- [@vx/gradient](https://npm.io/package/@vx/gradient.md) ^0.0.165
- [@data-ui/theme](https://npm.io/package/@data-ui/theme.md) ^0.0.84
- [@vx/responsive](https://npm.io/package/@vx/responsive.md) ^0.0.192
- [@data-ui/shared](https://npm.io/package/@data-ui/shared.md) ^0.0.84

## Alternatives

- [d3-force-3d](https://npm.io/package/d3-force-3d.md) — 1.0M weekly downloads
- [ng2-charts](https://npm.io/package/ng2-charts.md) — 486.8K weekly downloads
- [@arcgis/core](https://npm.io/package/@arcgis/core.md) — 257.8K weekly downloads
- [react-sparklines](https://npm.io/package/react-sparklines.md) — 249.3K weekly downloads
- [react-native-gifted-charts](https://npm.io/package/react-native-gifted-charts.md) — 182.3K weekly downloads

## Recent versions

- 0.0.84 (latest) — 2019-11-19
- 0.0.83 — 2019-11-19
- 0.0.82 — 2019-11-04
- 0.0.81 — 2019-09-24
- 0.0.80 — 2019-07-24
- 0.0.79 — 2019-06-14
- 0.0.78 — 2019-04-10
- 0.0.77 — 2019-03-13
- 0.0.76 — 2019-02-25
- 0.0.75 — 2019-01-16
- 0.0.74 — 2018-11-28
- 0.0.73 — 2018-11-27
- 0.0.72 — 2018-11-27
- 0.0.71 — 2018-11-14
- 0.0.70 — 2018-11-14
- … 25 more at https://npm.io/package/@data-ui/histogram/versions

## README

# @data-ui/histogram

A React + d3 library for creating histograms. Vertical or horizontal, raw data or binned data, numeric or categorical bins, counts or densities, cumulative or not.

`npm install --save @data-ui/histogram`

<a title="package version" href="https://img.shields.io/npm/v/@data-ui/histogram.svg?style=flat-square">
  <img src="https://img.shields.io/npm/v/@data-ui/histogram.svg?style=flat-square" />
</a>
<p align="center">
  <img width="600px" src="https://user-images.githubusercontent.com/4496521/28901809-a03e88a6-77af-11e7-9882-468d362289bd.gif" />
</p>

Demo it live at <a href="https://williaster.github.io/data-ui" target="_blank">williaster.github.io/data-ui</a>.

## Example usage
Similar to the `@data-ui/xy-chart` package, this `@data-ui/histogram` package exports a parent `<Histogram />` container component that renders an svg and coordinates scales across its children. You can pass the parent container optionally-animated `<BarSeries />` and/or `<DensitySeries />` as well as `<XAxis />` and `<YAxis />`.

```javascript
import { Histogram, DensitySeries, BarSeries, withParentSize, XAxis, YAxis } from '@data-ui/histogram';

const ResponsiveHistogram = withParentSize(({ parentWidth, parentHeight, ...rest}) => (
  <Histogram
    width={parentWidth}
    height={parentHeight}
    {...rest}
  />
);

const rawData = Array(100).fill().map(Math.random);

...
  render () {
    return (
      <ResponsiveHistogram
        ariaLabel="My histogram of ..."
        orientation="vertical"
        cumulative={false}
        normalized={true}
        binCount={25}
        valueAccessor={datum => datum}
        binType="numeric"
        renderTooltip={({ event, datum, data, color }) => (
          <div>
            <strong style={{ color }}>{datum.bin0} to {datum.bin1}</strong>
            <div><strong>count </strong>{datum.count}</div>
            <div><strong>cumulative </strong>{datum.cumulative}</div>
            <div><strong>density </strong>{datum.density}</div>
          </div>
        )}
      >
        <BarSeries
          animated
          rawData={rawData /* or binnedData={...} */}
        />
        <XAxis />
        <YAxis />
      </ResponsiveHistogram>
    );
  }
```

Demo with the <a href="https://williaster.github.io/data-ui" target="_blank">Histogram playground</a>.

## Components

Check out the example source code and PropTable tabs in the Storybook <a href="https://williaster.github.io/data-ui" target="_blank">williaster.github.io/data-ui</a>.

### `<Histogram />`

Name | Type | Default | Description
------------ | ------------- | ------- | ----
ariaLabel | PropTypes.string.isRequired | - | Accessibility label
binValues | PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.number, PropTypes.string])) | null | Bin thresholds, overrides binCount
binCount | PropTypes.number | 10 | an approximate number of bins to use (if data is not already binned)
binType | PropTypes.oneOf(['numeric', 'categorical']) | 'numeric' | Specify whether to bins are categorical or numeric
children | PropTypes.node.isRequired | - | Child Series, Axis, or other
cumulative | PropTypes.bool | false | whether to show a cumulative histogram
height | PropTypes.number.isRequired | - | height of the visualization
horizontal | PropTypes.bool | false | whether the histograms is oriented vertically or horizontally
limits | PropTypes.array | null | values outside the limits are ignored
margin | PropTypes.shape({ top: PropTypes.number, right: PropTypes.number, bottom: PropTypes.number, left: PropTypes.number }) | { top: 32, right: 32, bottom: 64, left: 64 } | chart margin, leave room for axes and labels!
normalized | PropTypes.bool | false | whether the value axis is normalized as fraction of total
theme | PropTypes.object | {} | chart theme object, see theme below.
width | PropTypes.number.isRequired | - | width of the svg
valueAccessor | PropTypes.func | d => d | for raw data, how to access the bin value

### `<*Series />`
`<BarSeries />` and `<DensitySeries />` components accept _either_ `rawData` or `binnnedData`. Raw data can be in any format as long as the value of each datum can be accessed with the Histogram `valueAccessor` function. Binned data should have the following shapes:

```javascript
export const numericBinnedDatumShape = PropTypes.shape({
  id: PropTypes.string.isRequired,
  bin0: PropTypes.number.isRequired,
  bin1: PropTypes.number.isRequired,
  count: PropTypes.number.isRequired,
});

export const categoricalBinnedDatumShape = PropTypes.shape({
  id: PropTypes.string.isRequired,
  bin: PropTypes.string.isRequired,
  count: PropTypes.number.isRequired,
});
```

If both `rawData` and `binnnedData` are provided, `rawData` is ignored.

### `<BarSeries />`

Name | Type | Default | Description
------------ | ------------- | ------- | ----
animated | PropTypes.bool | true | whether to animate updates to the data in the series
rawData | PropTypes.array | [] | raw datum
binnedData | binnedDataShape | [] | binned data
fill | PropTypes.oneOfType([PropTypes.func, PropTypes.string]) | @data-ui/theme.color.default | determines bar fill color
fillOpacity | PropTypes.oneOfType([PropTypes.func, PropTypes.number]) | 0.7 | opacity of bar fill
stroke | PropTypes.oneOfType([PropTypes.func, PropTypes.string]) | 'white' | determines bar stroke color
strokeWidth | PropTypes.oneOfType([PropTypes.func, PropTypes.number]) | 1 | determines width of bar outline
onClick | PropTypes.func | -- | Called on bar click with a signature of `({ event, data, datum, color, index })`


### `<DensitySeries />`

For _raw data_ that is _numeric_, the `<DensitySeries />` plots an estimates of the probability density function, i.e., a kernel density estimate. If pre-aggregated and/or categorical data is passed to the Series, it plots an Area graph of values based on the data counts.

Name | Type | Default | Description
------------ | ------------- | ------- | ----
animated | PropTypes.bool | true | whether to animate updates to the data in the series
rawData | PropTypes.array | [] | raw datum
binnedData | binnedDataShape | [] | binned data
fill | PropTypes.oneOfType([PropTypes.func, PropTypes.string]) | @data-ui/theme.color.default | determines bar fill color
kernel | PropTypes.oneOf(['gaussian', 'parabolic']) | 'gaussian' | kernel function type, parabolic = epanechnikov kernel
showArea | PropTypes.bool | true | whether to show density area fill
showLine | PropTypes.bool | true | whether to show density line path
smoothing | PropTypes.number | 1 | smoothing constant for parabolic / epanechinikov kernel function
fillOpacity | PropTypes.oneOfType([PropTypes.func, PropTypes.number]) | 0.7 | opacity of area fill if shown
stroke | PropTypes.oneOfType([PropTypes.func, PropTypes.string]) | 'white' | determines line color if shown
strokeWidth | PropTypes.oneOfType([PropTypes.func, PropTypes.number]) | 2 | determines width of line path if shown
strokeDasharray | PropTypes.oneOfType([PropTypes.func, PropTypes.string]) | '' | determines dash pattern of line if shown
strokeLinecap | PropTypes.oneOf(['butt', 'square', 'round', 'inherit']) | 'round' | style of line path stroke
useEntireScale | PropTypes.bool | false | if true, density plots will scale to fill the entire y-range of the plot. if false, the maximum value is scaled to the count of the series


### `<XAxis />` and `<YAxis />`

Name | Type | Default | Description
------------ | ------------- | ------- | ----
axisStyles | axisStylesShape | {} | config object for axis and axis label styles, see theme below
label | PropTypes.oneOfType([PropTypes.string, PropTypes.element]) | <text {...axisStyles.label[orientation]} /> | string or component for axis labels
numTicks | PropTypes.number | null | approximate number of ticks
orientation | XAxis PropTypes.oneOf(['bottom', 'top']) or YAxis PropTypes.oneOf(['left', 'right']) | bottom, left | orientation of axis
tickStyles | tickStylesShape | {} | config object for styling ticks and tick labels, see theme below
tickLabelComponent | PropTypes.element | <text {...tickStyles.label[orientation]} /> | component to use for tick labels
tickFormat | PropTypes.func | null | (tick, tickIndex) => formatted tick
tickValues | PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.number, PropTypes.string])) | null | custom tick values


### Tooltips
Tooltips are supported for histogram `BarSeries`. The _easiest_ way to use tooltips out of the box is by passing a `renderTooltip` function to `<Histogram />` as shown in the above example. This function takes an object with the shape `{ event, datum, data, color }` as input and should return the inner contents of the tooltip (not the tooltip container!) as shown above.  `datum` corresponds to the _binned_ data point, see the above-specified shapes which depend on whether your bins are categorical or numeric. `color` represents the bar fill. If this function returns a `falsy` value, a tooltip will not be rendered.

Under the covers this will wrap the `<Histogram />` component in the exported `<WithTooltip />` HOC, which wraps the `svg` in a `<div />` and handles the positioning and rendering of an HTML-based tooltip with the contents returned by `renderTooltip()`. This tooltip is aware of the bounds of its container and should position itself "smartly".

If you'd like more customizability over tooltip rendering you can do either of the following:

1) Roll your own tooltip positioning logic and pass `onMouseMove` and `onMouseLeave` functions to `Histogram`. These functions are passed to the `<BarSeries />` children and are called with the signature `onMouseMove({ data, datum, event, color })` and `onMouseLeave()` upon appropriate trigger.

2) Wrap `<Histogram />` in `<WithTooltip />` yourself, which accepts props for additional customization:

Name | Type | Default | Description
------------ | ------------- | ------- | ----
children | PropTypes.func or PropTypes.object | - | Child function (to call) or element (to clone) with onMouseMove, onMouseLeave, and tooltipData props/keys
className | PropTypes.string | - | Class name to add to the `<div>` container wrapper
renderTooltip | PropTypes.func.isRequired | - | Renders the _contents_ of the tooltip, signature of `({ event, data, datum, color, index }) => node`. If this function returns a `falsy` value, a tooltip will not be rendered.
styles | PropTypes.object | {} | Styles to add to the `<div>` container wrapper
TooltipComponent | PropTypes.func or PropTypes.object | `@vx`'s `TooltipWithBounds` | Component (not instance) to use as the tooltip container component. It is passed `top` and `left` numbers for positioning
tooltipProps | PropTypes.object | - | Props that are passed to `TooltipComponent`
tooltipTimeout | PropTypes.number | 200 | Timeout in ms for the tooltip to hide upon calling `onMouseLeave`

### Theme
A theme object with the following shape can be passed to `<Histogram />` to style the chart, axes, and series. Alternatively, keys (eg `xAxisStyles`) can be passed directly to the axes components.

See <a href="https://github.com/williaster/data-ui/blob/master/packages/data-ui-theme/src/chartTheme.js" target="_blank">`@data-ui/theme`</a> for an example.

```
export const themeShape = PropTypes.shape({
  gridStyles: PropTypes.shape({
    stroke: PropTypes.string,
    strokeWidth: PropTypes.number,
  }),
  xAxisStyles: PropTypes.shape({
    stroke: PropTypes.string,
    strokeWidth: PropTypes.number,
    label: PropTypes.shape({
      bottom: PropTypes.object,
      top: PropTypes.object,
    }),
  }),
  yAxisStyles: PropTypes.shape({
    stroke: PropTypes.string,
    strokeWidth: PropTypes.number,
    label: PropTypes.shape({
      left: PropTypes.object,
      right: PropTypes.object,
    }),
  })
  xTickStyles: PropTypes.shape({
    stroke: PropTypes.string,
    tickLength: PropTypes.number,
    label: PropTypes.shape({
      bottom: PropTypes.object,
      top: PropTypes.object,
    }),
  }),
  yTickStyles: PropTypes.shape({
    stroke: PropTypes.string,
    tickLength: PropTypes.number,
    label: PropTypes.shape({
      left: PropTypes.object,
      right: PropTypes.object,
    }),
  }),
});
```

## Development
```
npm install
yarn run dev # or 'build'
```

---
_Source: https://npm.io/package/@data-ui/histogram · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
