<commit_before>![travis badge](https://travis-ci.org/ihmeuw/ihme-ui.svg) [![codecov.io](https://codecov.io/github/ihmeuw/ihme-ui/coverage.svg?branch=master)](https://codecov.io/github/ihmeuw/ihme-ui?branch=master)

# [IHME-UI](https://github.com/ihmeuw/ihme-ui)

ihme-ui is a collection of JavaScript and React-based visualization tools and user interface elements developed by the [Institute of Health Metrics and Evaluation](http://healthdata.org). These elements are used in IHME's [visualizations of global health metrics](http://www.healthdata.org/results/data-visualizations).

* [Installation](#installation)
* [API Reference](#api)
  * [\<Axis /\>](#axis-)
    * [\<XAxis /\>](#xaxis-)
    * [\<YAxis /\>](#yaxis-)
  * [\<AxisChart /\>](#axischart-)
  * [\<Button /\>](#button-)
  * [\<Choropleth /\>](#choropleth-)
  * [\<ChoroplethLegend /\>](#choroplethlegend-)
  * [\<Group /\>](#group-)
    * [\<Option /\>](#option-)
  * [\<HtmlLabel /\>](#htmllabel-)
  * [\<MultiSelect /\> and \<SingleSelect /\>](#multiselect--and-singleselect-)
  * [\<ResponsiveContainer /\>](#responsivecontainer-)
  * [\<Shape /\>](#shape-)
    * [\<Area /\>](#area-)
    * [\<Line /\>](#line-)
    * [\<MultiLine /\>](#multiline-)
    * [\<Scatter /\>](#scatter-)
    * [\<Symbol /\>](#symbol-)
  * [\<Slider /\>](#slider-)
  * [\<Spinner /\>](#spinner-)
  * [\<SvgText /\>](#svgtext-)
* [Test Utilities](#test-utilities)
  * [Data Generator](#data-generator)
* [Code Quality](#code-quality)

###### WORK IN PROGRESS: Not stable until v1.0.0

---

## Installation

To install ihme-ui tools and all dependencies:

```sh
npm install -S ihme-ui
```
To install demo files:

```sh
npm run demo
```

## API

### General notes
#### className

All className props are run through the [classnames](https://github.com/JedWatson/classnames) library, so can be a string, an object, or an array.

#### style

All style props can take an object. In some cases, the style prop can take a function that will compute and return a style object based on some criteria listed in the description.

---

### \<Axis /\>
`import Axis from 'ihme-ui/ui/axis'`

Chart axis

Property | Required | Type(s) | Defaults | Description
        --- | :---: | :---: | :---: | ---
`axisClassName` | no | [className](#className) | | className applied to group element directly containing axis
`axisStyle` | no | object | | inline styles applied to group element directly containing axis
`className` | no | [className](#className) | | className applied to outermost group element
`height` | yes, unless translate provided | number | 0 | height of charting area, minus padding
`label` | no | string | | the axis label
`labelClassName` | no | [className](#className) | | className applied to text element surrounding axis label
`labelStyle` | no | object | | inline applied to text element surrounding axis label
`orientation` | yes | string | | where to position axis line; will position ticks accordingly;<br />one of: "top", "right", "bottom", "left"
`padding` | no | object | { top: 40, bottom: 40, left: 50, right: 50 } | used to position label 
`scale` | yes | function | d3.scaleLinear() | appropriate scale for object
`style` | no | object | | inline styles to apply to outermost group element
`ticks` | no | number | | [number of axis ticks use](https://github.com/d3/d3-axis#axis_ticks)
`tickArguments` | no | array | | [alternative to tickValues and/or tickFormat](https://github.com/d3/d3-axis#axis_tickArguments)
`tickFormat` | no | function | | [format of axis ticks](https://github.com/d3/d3-axis#axis_tickFormat)
`tickPadding` | no | number | | [padding of axis ticks](https://github.com/d3/d3-axis#axis_tickPadding)
`tickSize` | no | number | | [size of both inner and outer tick lines](https://github.com/d3/d3-axis#axis_tickSize)
`tickSizeInner` | no | number | | [size of inner tick lines](https://github.com/d3/d3-axis#axis_tickSizeInner)
`tickSizeOuter` | no | number | | [size of outer tick lines](https://github.com/d3/d3-axis#axis_tickSizeOuter)
`tickValues` | no | object | | [user-specified tick values](https://github.com/d3/d3-axis#axis_tickValues)
`translate` | yes, unless width and height provided | object | | push axis in x or y direction
`width` | yes, unless translate provided | number | 0 | width of charting area, minus padding

#### \<XAxis />
`import { XAxis } from 'ihme-ui/ui/axis'`

Chart x-axis that extends \<Axis /> and provides some useful defaults

Property | Required | Type(s) | Defaults | Description
        --- | :---: | :---: | :---: | ---
`orientation` | no | string | "bottom" | where to position axis line; will position ticks accordingly;<br />one of: "top", "bottom"
`padding` | no | object | { top: 40, bottom: 40 } | used to position label 
`scales` | yes | object | { x: d3.scaleLinear() } | appropriate scale for object

#### \<YAxis />
`import { YAxis } from 'ihme-ui/ui/axis'`

Chart y-axis that extends \<Axis /> and provides some useful defaults

Property | Required | Type(s) | Defaults | Description
        --- | :---: | :---: | :---: | ---
`orientation` | no | string | "left" | where to position axis line; will position ticks accordingly;<br />one of: "right", "left"
`padding` | no | object | { left: 50, right: 50 } | used to position label 
`scales` | yes | object | { y: d3.scaleLinear() } | appropriate scale for object

### \<AxisChart /\>
`import AxisChart from 'ihme-ui/ui/axis-chart'`

Wraps and provides its child charting components width, height, scales, and padding

Property | Required | Type(s) | Defaults | Description
        --- | :---: | :---: | :---: | ---
`className` | no | [className](#className) | | className applied to outermost svg element
`height` | yes | number | | pixel height of line chart
`loading` | no | bool | | flag to delay rendering while fetching data
`padding`| no | object | { top: 20, bottom: 30, left: 50, right: 20 } | padding around the chart contents
`style` | no | object | | inline styles to apply to outermost svg element
`width` | yes | number | | pixel width of line chart
`xDomain` | no | array | | [min, max] for xScale (i.e., the domain of the data)
`xScaleType`| yes | string | | type of x scale<br />[name of d3 scale scale function](https://github.com/d3/d3-scale) 
`yDomain` | no | array | | [min, max] yScale (i.e., the range of the data)
`yScaleType` | yes | string | | type of y scale<br />[name of d3 scale scale function](https://github.com/d3/d3-scale)

### \<Button /\>
`import Button from 'ihme-ui/ui/button'`

Button with customizable id, name, class name, icon, animation, and click handler.

Property | Required | Type(s) | Defaults | Description
        --- | :---: | :---: | :---: | ---
`className` | no | [className](#className) | | className applied to button
`disabled` | no | boolean | | boolean value to set button as disabled
`disabledClassName` | no | [className](#className) | | className applied to button when disabled
`disabledStyle` | no | object | | inline styles to apply to outermost svg element when disabled
`icon` | no | string | | path to image to render within button tag
`id` | no | string | | id value for button
`name` | no | string | | name of button
`onClick` | no | function | | function to be executed on an onClick event
`showSpinner` | no | boolean | | boolean value to display a loading spinner
`style` | no | object | | inline styles to apply to outermost svg element
`text` | no | string | | text to render within button tag
`theme` | no | string | | color scheme of component (see button.css)

### \<Choropleth /\>
`import Choropleth from 'ihme-ui/ui/choropleth'`

Interactive map component

Property | Required | Type(s) | Defaults | Description
        --- | :---: | :---: | :---: | ---
`className` | no | [className](#className) | | className applied to outermost div
`colorScale` | yes | func | | function that accepts value of `keyfield` (str), and returns (str) stroke color for line
`controls` | no | bool |  | show zoom controls 
`controlsClassName` | no | [className](#className) | | className applied to controls container div 
`controlsButtonClassName` | no | [className](#className) | | className applied to controls buttons 
`controlsButtonStyle` | no | object | | inline styles to apply to controls buttons 
`controlsStyle` | no | object | | inline styles to apply to outermost div 
`data` | yes | array |  | array of datum objects 
`geometryKeyField` | yes | string, func | | uniquely identifying field of geometry objects; if a function, will be called with the geometry object as first parameter 
`height` | no | number | 400 | pixel height of containing element
`keyField` | yes | string, func |  | unique key of datum; if a function, will be called with the datum object as first parameter
`layers` | yes | array | | see [layers detail](#layers-detail)
`maxZoom` | no | number | | max allowable zoom factor; 1 === fit bounds 
`minZoom` | no | number | | min allowable zoom factor; 1 === fit bounds 
`onClick` | no | func | | passed to each path<br />function: (event, datum, Path) => {...}
`onMouseLeave` | no | func | | passed to each path<br />function: (event, datum, Path) => {...}
`onMouseMove` | no | func | | passed to each path<br />function: (event, datum, Path) => {...}
`onMouseOver` | no | func | | passed to each path<br />function: (event, datum, Path) => {...}
`selectedLocations` | no | array | | array of selected location objects
`style` | no | object | | inline styles applied outermost div
`topology` | yes | object | | full topojson object<br />for information, see [topojson wiki](https://github.com/topojson/topojson/wiki)
`valueField` | yes | string, func |  | key of datum that holds the value to display<br />function: (data, feature) => value
`width` | no | number | 600 | pixel width of containing element
`zoomStep` | no | number | 1.1 | amount to zoom in/out from zoom controls. current zoom scale is multiplied by prop value.<br />e.g. 1.1 is equal to 10% steps, 2.0 is equal to 100% steps

##### Layers detail 

Property | Required | Type(s) | Defaults | Description
        --- | :---: | :---: | :---: | ---
`className` | no | [className](#className) | | className applied to layer
`filterFn` | no | func | | optional function to filter mesh grid, passed adjacent geometries<br />refer to [https://github.com/mbostock/topojson/wiki/API-Reference#mesh](https://github.com/mbostock/topojson/wiki/API-Reference#mesh)
`name` | yes | string | | along with layer.type, will be part of the `key` of the layer; therefore, `${layer.type}-${layer.name}` needs to be unique
`object` | yes | string | | name corresponding to key within topojson objects collection
`selectedClassName` | no | [className](#className) | | className applied to selected paths
`selectedStyle` | no | [style](#style) | | inline styles applied to selected paths<br />func: (feature) => style object
`style` | no | [style](#style) | | inline styles applied to layer<br />func: (feature) => style object
`type` | yes | string | | whether the layer should be a feature collection or mesh grid<br />one of: "feature", "mesh"
`visible` | no | bool | | whether or not to render layer

### \<ChoroplethLegend /\>

Choropleth map legend with customizable color steps, color scale, data, appearance, and interaction handlers.

Property | Required | Type(s) | Description
        --- | :---: | :---: | ---
`colorSteps` | yes | object | array of color steps, e.g. ['#fff', '#ccc', '\#000', ...]
`colorScale` | yes | object | function that accepts data as a parameter and returns color<commit_msg>Choropleth props description nits<commit_after>![travis badge](https://travis-ci.org/ihmeuw/ihme-ui.svg) [![codecov.io](https://codecov.io/github/ihmeuw/ihme-ui/coverage.svg?branch=master)](https://codecov.io/github/ihmeuw/ihme-ui?branch=master)

# [IHME-UI](https://github.com/ihmeuw/ihme-ui)

ihme-ui is a collection of JavaScript and React-based visualization tools and user interface elements developed by the [Institute of Health Metrics and Evaluation](http://healthdata.org). These elements are used in IHME's [visualizations of global health metrics](http://www.healthdata.org/results/data-visualizations).

* [Installation](#installation)
* [API Reference](#api)
  * [\<Axis /\>](#axis-)
    * [\<XAxis /\>](#xaxis-)
    * [\<YAxis /\>](#yaxis-)
  * [\<AxisChart /\>](#axischart-)
  * [\<Button /\>](#button-)
  * [\<Choropleth /\>](#choropleth-)
  * [\<ChoroplethLegend /\>](#choroplethlegend-)
  * [\<Group /\>](#group-)
    * [\<Option /\>](#option-)
  * [\<HtmlLabel /\>](#htmllabel-)
  * [\<MultiSelect /\> and \<SingleSelect /\>](#multiselect--and-singleselect-)
  * [\<ResponsiveContainer /\>](#responsivecontainer-)
  * [\<Shape /\>](#shape-)
    * [\<Area /\>](#area-)
    * [\<Line /\>](#line-)
    * [\<MultiLine /\>](#multiline-)
    * [\<Scatter /\>](#scatter-)
    * [\<Symbol /\>](#symbol-)
  * [\<Slider /\>](#slider-)
  * [\<Spinner /\>](#spinner-)
  * [\<SvgText /\>](#svgtext-)
* [Test Utilities](#test-utilities)
  * [Data Generator](#data-generator)
* [Code Quality](#code-quality)

###### WORK IN PROGRESS: Not stable until v1.0.0

---

## Installation

To install ihme-ui tools and all dependencies:

```sh
npm install -S ihme-ui
```
To install demo files:

```sh
npm run demo
```

## API

### General notes
#### className

All className props are run through the [classnames](https://github.com/JedWatson/classnames) library, so can be a string, an object, or an array.

#### style

All style props can take an object. In some cases, the style prop can take a function that will compute and return a style object based on some criteria listed in the description.

---

### \<Axis /\>
`import Axis from 'ihme-ui/ui/axis'`

Chart axis

Property | Required | Type(s) | Defaults | Description
        --- | :---: | :---: | :---: | ---
`axisClassName` | no | [className](#className) | | className applied to group element directly containing axis
`axisStyle` | no | object | | inline styles applied to group element directly containing axis
`className` | no | [className](#className) | | className applied to outermost group element
`height` | yes, unless translate provided | number | 0 | height of charting area, minus padding
`label` | no | string | | the axis label
`labelClassName` | no | [className](#className) | | className applied to text element surrounding axis label
`labelStyle` | no | object | | inline applied to text element surrounding axis label
`orientation` | yes | string | | where to position axis line; will position ticks accordingly;<br />one of: "top", "right", "bottom", "left"
`padding` | no | object | { top: 40, bottom: 40, left: 50, right: 50 } | used to position label 
`scale` | yes | function | d3.scaleLinear() | appropriate scale for object
`style` | no | object | | inline styles to apply to outermost group element
`ticks` | no | number | | [number of axis ticks use](https://github.com/d3/d3-axis#axis_ticks)
`tickArguments` | no | array | | [alternative to tickValues and/or tickFormat](https://github.com/d3/d3-axis#axis_tickArguments)
`tickFormat` | no | function | | [format of axis ticks](https://github.com/d3/d3-axis#axis_tickFormat)
`tickPadding` | no | number | | [padding of axis ticks](https://github.com/d3/d3-axis#axis_tickPadding)
`tickSize` | no | number | | [size of both inner and outer tick lines](https://github.com/d3/d3-axis#axis_tickSize)
`tickSizeInner` | no | number | | [size of inner tick lines](https://github.com/d3/d3-axis#axis_tickSizeInner)
`tickSizeOuter` | no | number | | [size of outer tick lines](https://github.com/d3/d3-axis#axis_tickSizeOuter)
`tickValues` | no | object | | [user-specified tick values](https://github.com/d3/d3-axis#axis_tickValues)
`translate` | yes, unless width and height provided | object | | push axis in x or y direction
`width` | yes, unless translate provided | number | 0 | width of charting area, minus padding

#### \<XAxis />
`import { XAxis } from 'ihme-ui/ui/axis'`

Chart x-axis that extends \<Axis /> and provides some useful defaults

Property | Required | Type(s) | Defaults | Description
        --- | :---: | :---: | :---: | ---
`orientation` | no | string | "bottom" | where to position axis line; will position ticks accordingly;<br />one of: "top", "bottom"
`padding` | no | object | { top: 40, bottom: 40 } | used to position label 
`scales` | yes | object | { x: d3.scaleLinear() } | appropriate scale for object

#### \<YAxis />
`import { YAxis } from 'ihme-ui/ui/axis'`

Chart y-axis that extends \<Axis /> and provides some useful defaults

Property | Required | Type(s) | Defaults | Description
        --- | :---: | :---: | :---: | ---
`orientation` | no | string | "left" | where to position axis line; will position ticks accordingly;<br />one of: "right", "left"
`padding` | no | object | { left: 50, right: 50 } | used to position label 
`scales` | yes | object | { y: d3.scaleLinear() } | appropriate scale for object

### \<AxisChart /\>
`import AxisChart from 'ihme-ui/ui/axis-chart'`

Wraps and provides its child charting components width, height, scales, and padding

Property | Required | Type(s) | Defaults | Description
        --- | :---: | :---: | :---: | ---
`className` | no | [className](#className) | | className applied to outermost svg element
`height` | yes | number | | pixel height of line chart
`loading` | no | bool | | flag to delay rendering while fetching data
`padding`| no | object | { top: 20, bottom: 30, left: 50, right: 20 } | padding around the chart contents
`style` | no | object | | inline styles to apply to outermost svg element
`width` | yes | number | | pixel width of line chart
`xDomain` | no | array | | [min, max] for xScale (i.e., the domain of the data)
`xScaleType`| yes | string | | type of x scale<br />[name of d3 scale scale function](https://github.com/d3/d3-scale) 
`yDomain` | no | array | | [min, max] yScale (i.e., the range of the data)
`yScaleType` | yes | string | | type of y scale<br />[name of d3 scale scale function](https://github.com/d3/d3-scale)

### \<Button /\>
`import Button from 'ihme-ui/ui/button'`

Button with customizable id, name, class name, icon, animation, and click handler.

Property | Required | Type(s) | Defaults | Description
        --- | :---: | :---: | :---: | ---
`className` | no | [className](#className) | | className applied to button
`disabled` | no | boolean | | boolean value to set button as disabled
`disabledClassName` | no | [className](#className) | | className applied to button when disabled
`disabledStyle` | no | object | | inline styles to apply to outermost svg element when disabled
`icon` | no | string | | path to image to render within button tag
`id` | no | string | | id value for button
`name` | no | string | | name of button
`onClick` | no | function | | function to be executed on an onClick event
`showSpinner` | no | boolean | | boolean value to display a loading spinner
`style` | no | object | | inline styles to apply to outermost svg element
`text` | no | string | | text to render within button tag
`theme` | no | string | | color scheme of component (see button.css)

### \<Choropleth /\>
`import Choropleth from 'ihme-ui/ui/choropleth'`

Interactive map component

Property | Required | Type(s) | Defaults | Description
        --- | :---: | :---: | :---: | ---
`className` | no | [className](#className) | | className applied to outermost div
`colorScale` | yes | func | | function that accepts value of `keyfield` (str), and returns (str) stroke color for line
`controls` | no | bool |  | show zoom controls 
`controlsClassName` | no | [className](#className) | | className applied to controls container div 
`controlsButtonClassName` | no | [className](#className) | | className applied to controls buttons 
`controlsButtonStyle` | no | object | | inline styles to apply to controls buttons 
`controlsStyle` | no | object | | inline styles to apply to outermost div 
`data` | yes | array |  | array of datum objects 
`geometryKeyField` | yes | string, func | | uniquely identifying field of geometry objects; if a function, will be called with the geometry object as first parameter 
`height` | no | number | 400 | pixel height of containing element
`keyField` | yes | string, func |  | unique key of datum; if a function, will be called with the datum object as first parameter
`layers` | yes | array | | see [layers detail](#layers-detail)
`maxZoom` | no | number | | max allowable zoom factor; 1 === fit bounds 
`minZoom` | no | number | | min allowable zoom factor; 1 === fit bounds 
`onClick` | no | func | | passed to each path;<br />signature: (event, datum, Path) => {...}
`onMouseLeave` | no | func | | passed to each path;<br />signature: (event, datum, Path) => {...}
`onMouseMove` | no | func | | passed to each path;<br />signature: (event, datum, Path) => {...}
`onMouseOver` | no | func | | passed to each path;<br />signature: (event, datum, Path) => {...}
`selectedLocations` | no | array | | array of selected location objects
`style` | no | object | | inline styles applied outermost div
`topology` | yes | object | | full topojson object<br />for information, see [topojson wiki](https://github.com/topojson/topojson/wiki)
`valueField` | yes | string, func |  | key of datum that holds the value to display<br />function: (data, feature) => value
`width` | no | number | 600 | pixel width of containing element
`zoomStep` | no | number | 1.1 | amount to zoom in/out from zoom controls. current zoom scale is multiplied by prop value.<br />e.g. 1.1 is equal to 10% steps, 2.0 is equal to 100% steps

##### Layers detail 

Property | Required | Type(s) | Defaults | Description
        --- | :---: | :---: | :---: | ---
`className` | no | [className](#className) | | className applied to layer
`filterFn` | no | func | | optional function to filter mesh grid, passed adjacent geometries<br />refer to [https://github.com/mbostock/topojson/wiki/API-Reference#mesh](https://github.com/mbostock/topojson/wiki/API-Reference#mesh)
`name` | yes | string | | along with layer.type, will be part of the `key` of the layer; therefore, `${layer.type}-${layer.name}` needs to be unique
`object` | yes | string | | name corresponding to key within topojson objects collection
`selectedClassName` | no | [className](#className) | | className applied to selected paths
`selectedStyle` | no | [style](#style) | | inline styles applied to selected paths<br />func: (feature) => style object
`style` | no | [style](#style) | | inline styles applied to layer<br />func: (feature) => style object
`type` | yes | string | | whether the layer should be a feature collection or mesh grid<br />one of: "feature", "mesh"
`visible` | no | bool | | whether or not to render layer

### \<ChoroplethLegend /\>

Choropleth map legend with customizable color steps, color scale, data, appearance, and interaction handlers.

Property | Required | Type(s) | Description
        --- | :---: | :---: | ---
`colorSteps` | yes | object | array of color steps, e.g. ['#fff', '#ccc', '\#000', ...]
`colorScale` | yes | object | function that accepts data as a parameter and returns color
{'fraction_non_alphanumeric': 0.1593449441122953, 'fraction_numerical': 0.006585217918724547, 'mean_word_length': 3.7949729954299958, 'pattern_counts': {'":': 0, '<': 97, '<?xml version=': 0, '>': 111, 'https://': 36, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2667943', 'n_tokens_mistral': 7252, 'n_tokens_neox': 6923, 'n_words': 2498}