# Welcome

<p align="right"><a href="https://npmjs.org/package/kepler.gl"><img src="https://img.shields.io/npm/v/kepler.gl.svg?style=flat" alt="version"> </a><a href="https://travis-ci.com/keplergl/kepler.gl"><img src="https://api.travis-ci.com/keplergl/kepler.gl.svg?branch=master" alt="build"> </a><a href="https://github.com/keplergl/kepler.gl"><img src="https://img.shields.io/github/stars/keplergl/kepler.gl.svg?style=flat" alt="stars"> </a><a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/License-MIT-blue.svg" alt="MIT License"> </a><a href="https://app.fossa.com/projects/custom%2B4458%2Fgithub.com%2Fkeplergl%2Fkepler.gl?ref=badge_shield"><img src="https://app.fossa.com/api/projects/custom%2B4458%2Fgithub.com%2Fkeplergl%2Fkepler.gl.svg?type=shield" alt="Fossa"> </a><a href="https://app.netlify.com/sites/keplergl/deploys"><img src="https://api.netlify.com/api/v1/badges/0c9b895c-acd0-43fd-8af7-fe960181b686/deploy-status" alt="Netlify Status"> </a><a href="https://coveralls.io/github/keplergl/kepler.gl?branch=master"><img src="https://coveralls.io/repos/github/keplergl/kepler.gl/badge.svg?branch=master" alt="Coverage Status"></a></p>

<h2 align="center">kepler.gl | <a href="https://kepler.gl">Website</a> | <a href="https://kepler.gl/#/demo">Demo App</a> | <a href="https://docs.kepler.gl/">Docs</a></h2>

####

[![Kepler.gl](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/website/icons/kepler.gl-logo.png)](http://kepler.gl)

[![Kepler.gl Demo](/files/R2CgGroyLUyk4rAgCO6M)](https://kepler.gl/demo)

[Kepler.gl](http://www.kepler.gl/) is a data-agnostic, high-performance web-based application for visual exploration of large-scale geolocation data sets. Built on top of [MapLibre GL](https://maplibre.org/) and [deck.gl](https://deck.gl/), kepler.gl can render millions of points representing thousands of trips and perform spatial aggregations on the fly.

Kepler.gl is also a React component that uses [Redux](https://redux.js.org/) to manage its state and data flow. It can be embedded into other React-Redux applications and is highly customizable. For information on how to embed kepler.gl in your app take a look at the [documentation](https://docs.kepler.gl/).

### Links

* [Website](http://www.kepler.gl/)
* [Demo](http://kepler.gl/#/demo)
* [Examples](https://github.com/keplergl/kepler.gl/tree/master/examples)
* [Get Started](/docs/api-reference/get-started)
* [App User Guide](/docs/user-guides)
* [Jupyter Widget User Guide](/docs/keplergl-jupyter)
* [Documentation](https://docs.kepler.gl/)
* [Stack Overflow](https://stackoverflow.com/questions/tagged/kepler.gl)
* [Contribution Guidelines](/contributing)
* [Api Reference](/docs/api-reference)
* [Roadmap](https://github.com/keplergl/kepler.gl/wiki/Kepler.gl-2019-Roadmap)

### Env

For **developing this repository**, use Node **20.19.3** (see `.nvmrc`): run `nvm install` and `nvm use`. Newer Node versions can make `yarn install` / `yarn bootstrap` try to compile the `gl` dev dependency from source; if that fails, see [Troubleshooting: gl package install](/contributing/developers#troubleshooting-gl-package-install).

When **using kepler.gl as a dependency** in your own app, use Node 20.19.3 or a supported LTS; older Node versions are not supported or tested.

### Install kepler.gl modules

Kepler.gl consists of different modules. Each module can be added to the project like this:

```sh
npm install --save @kepler.gl/components
// or
yarn add @kepler.gl/components
```

kepler.gl is built upon [mapbox](https://www.mapbox.com). You will need a [Mapbox Access Token](https://www.mapbox.com/help/define-access-token/) to use it.

If you don't use a module bundler, it's also fine. Kepler.gl npm package includes precompiled production UMD builds in the [umd folder](https://unpkg.com/kepler.gl/umd). You can add the script tag to your html file as it follows (latest version of Kepler.gl):

```html
<script src="https://unpkg.com/kepler.gl/umd/keplergl.min.js" />
```

or if you would like, you can load a specific version:

```html
<script src="https://unpkg.com/kepler.gl@3.0.0/umd/keplergl.min.js" />
```

### Develop kepler.gl

Take a look at the [development guide](/contributing/developers) to develop kepler.gl locally.

### Basic Usage

Here are the basic steps to import kepler.gl into your app. You also take a look at the examples folder. Each example in the folder can be installed and run locally.

#### 1. Mount reducer

Kepler.gl uses Redux to manage its internal state, along with [react-palm](https://github.com/btford/react-palm) middleware to handle side effects.

You need to add `taskMiddleware` of `react-palm` to your store too. We are actively working on a solution where `react-palm` will not be required, however it is still a very lightweight side effects management tool that is easier to test than react-thunk.

```js
import {createStore, combineReducers, applyMiddleware, compose} from 'redux';
import keplerGlReducer from '@kepler.gl/reducers';
import {enhanceReduxMiddleware} from '@kepler.gl/middleware';

const initialState = {};
const reducers = combineReducers({
  // <-- mount kepler.gl reducer in your app
  keplerGl: keplerGlReducer,

  // Your other reducers here
  app: appReducer
});

// using createStore
export default createStore(
  reducer,
  initialState,
  applyMiddleware(
    enhanceReduxMiddleware([
      /* Add other middlewares here */
    ])
  )
);
```

Or if use enhancer:

```js
// using enhancers
const initialState = {};
const middlewares = enhanceReduxMiddleware([
  // Add other middlewares here
]);
const enhancers = [applyMiddleware(...middlewares)];

export default createStore(reducer, initialState, compose(...enhancers));
```

If you mount kepler.gl reducer in another address instead of `keplerGl`, or the kepler.gl reducer is not mounted at root of your state, you will need to specify the path to it when you mount the component with the `getState` prop.

Read more about [Reducers](/docs/api-reference/reducers).

#### 2. Mount Component

```js
import KeplerGl from '@kepler.gl/components';

const Map = props => (
  <KeplerGl id="foo" width={width} mapboxApiAccessToken={token} height={height} />
);
```

#### Props

| Prop Name                     | Type          | Default Value             | Description                                                                                                                                                                                                             |
| ----------------------------- | ------------- | ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`                          | String        | `map`                     | The unique identifier for the KeplerGl instance. Required when multiple KeplerGl instances exist. It maps to the state in the reducer (e.g. component with id `foo` can be found in`state.keplerGl.foo`).               |
| `mapboxApiAccessToken`        | String        | `undefined`               | API token for Mapbox, used for rendering base maps. Create a free token at [Mapbox](https://www.mapbox.com).                                                                                                            |
| `getState`                    | Function      | `state => state.keplerGl` | Function that specifies the path to the root KeplerGl state in the reducer.                                                                                                                                             |
| `width`                       | Number        | `800`                     | The width of the KeplerGl UI in pixels.                                                                                                                                                                                 |
| `height`                      | Number        | `800`                     | The height of the KeplerGl UI in pixels.                                                                                                                                                                                |
| `appName`                     | String        | `Kepler.Gl`               | The app name displayed in the side panel header.                                                                                                                                                                        |
| `version`                     | String        | `v1.0`                    | The version displayed in the side panel header.                                                                                                                                                                         |
| `onSaveMap`                   | Function      | `undefined`               | A function called when the "Save Map URL" in side panel header is clicked.                                                                                                                                              |
| `onViewStateChange`           | Function      | `undefined`               | Triggered when the map viewport is updated. Receives `viewState` parameter with updated values like longitude, latitude, zoom, etc.                                                                                     |
| `getMapboxRef(mapbox, index)` | Function      | `undefined`               | Called when `KeplerGl` adds or removes a MapContainer with an inner Mapbox map. `mapbox` is a `MapRef` when added, or `null` when removed. `index` is `0` for the first map and `1` for the second map in a split view. |
| `actions`                     | Object        | `{}`                      | Custom action creators to override the default KeplerGl action creators. Only use custom action when you want to modify action payload.                                                                                 |
| `mint`                        | Boolean       | `true`                    | Determines whether to load a fresh empty state when mounted. When `false`, the state persists across remounts. Useful for modal use cases.                                                                              |
| `theme`                       | Object/String | `null`                    | Set to `"dark"`, `"light"`, or `"base"`, or pass a theme object to customize KeplerGl’s style.                                                                                                                          |
| `mapboxApiUrl`                | String        | `https://api.mapbox.com`  | The Mapbox API URL if you are using a custom Mapbox tile server.                                                                                                                                                        |
| `mapStylesReplaceDefault`     | Boolean       | `false`                   | Set to `true` to replace default map styles with custom ones. (see `mapStyles` prop)                                                                                                                                    |
| `mapStyles`                   | Array         | `[]`                      | An array of [custom map styles](#example-custom-map-style) for the map style selection panel. Styles replace the default ones if `mapStylesReplaceDefault` is `true`.                                                   |
| `initialUiState`              | Object        | `undefined`               | The initial UI state applied to the `uiState` reducer.                                                                                                                                                                  |
| `localeMessages`              | Object        | `undefined`               | Used to modify or add new translations. Read more about [Localization](/docs/api-reference/localization).                                                                                                               |

**Example Custom Map Style**

You can supply additional map styles to be displayed in [map style selection panel](https://github.com/keplergl/kepler.gl/blob/master/docs/user-guides/f-map-styles/1-base-map-styles.md). By default, additional map styles will be added to default map styles. If you pass `mapStylesReplaceDefault: true`, they will replace the default ones. kepler.gl will attempt to group layers of your style based on its `id` naming convention and use it to allow toggle visibility of [base map layers](https://github.com/keplergl/kepler.gl/blob/master/docs/user-guides/f-map-styles/2-map-layers.md). Supply your own `layerGroups` to override default for more accurate layer grouping.

Each `mapStyles` should has the following properties:

* `id` (String, required) unique string that should **not** be one of these reserved `dark` `light` `muted`. `muted_night`
* `label` (String, required) name to be displayed in map style selection panel
* `url` (String, required) mapbox style url or a url pointing to the map style json object written in [Mapbox GL Style Spec](https://docs.mapbox.com/mapbox-gl-js/style-spec/).
* `icon` (String, optional) image icon of the style, it can be a url, or an [image data url](https://flaviocopes.com/data-urls/#how-does-a-data-url-look)
* `layerGroups` (Array, optional)

```js
const mapStyles = [
  {
    id: 'my_dark_map',
    label: 'Dark Streets 9',
    url: 'mapbox://styles/mapbox/dark-v9',
    icon: `${apiHost}/styles/v1/mapbox/dark-v9/static/-122.3391,37.7922,9.19,0,0/400x300?access_token=${accessToken}&logo=false&attribution=false`,
    layerGroups: [
      {
        slug: 'label',
        filter: ({id}) => id.match(/(?=(label|place-|poi-))/),
        defaultVisibility: true
      },
      {
        slug: '3d building',
        filter: () => false,
        defaultVisibility: false
      }
    ]
  }
];
```

#### 3. Dispatch custom actions to `keplerGl` reducer.

One advantage of using the reducer over React component state to handle keplerGl state is the flexibility to customize its behavior. If you only have one `KeplerGl` instance in your app or never intend to dispatch actions to KeplerGl from outside the component itself, you don’t need to worry about forwarding dispatch and can move on to the next section. But life is full of customizations, and we want to make yours as enjoyable as possible.

There are multiple ways to dispatch actions to a specific `KeplerGl` instance.

* In the root reducer, with reducer updaters.

Each action is mapped to a reducer updater in kepler.gl. You can import the reducer updater corresponding to a specific action, and call it with the previous state and action payload to get the updated state. e.g. `updateVisDataUpdater` is the updater for `ActionTypes.UPDATE_VIS_DATA` (take a look at each reducer `reducers/vis-state.js` for action to updater mapping). Here is an example how you can listen to an app action `QUERY_SUCCESS` and call `updateVisDataUpdater` to load data into Kepler.Gl.

```js
import {keplerGlReducer, visStateUpdaters} from '@kepler.gl/reducers';

// Root Reducer
const reducers = combineReducers({
  keplerGl: keplerGlReducer,

  app: appReducer
});

const composedReducer = (state, action) => {
  switch (action.type) {
    case 'QUERY_SUCCESS':
      return {
        ...state,
        keplerGl: {
          ...state.keplerGl,

          // 'map' is the id of the keplerGl instance
          map: {
            ...state.keplerGl.map,
            visState: visStateUpdaters.updateVisDataUpdater(state.keplerGl.map.visState, {
              datasets: action.payload
            })
          }
        }
      };
  }
  return reducers(state, action);
};

export default composedReducer;
```

Read more about [using updaters to modify kepler.gl state](/docs/api-reference/advanced-usages/using-updaters)

* Using redux `connect`

You can add a dispatch function to your component that dispatches actions to a specific `keplerGl` component, using connect.

```js
// component
import KeplerGl from '@kepler.gl/components';

// action and forward dispatcher
import {toggleFullScreen, forwardTo} from '@kepler.gl/actions';
import {connect} from 'react-redux';

const MapContainer = props => (
  <div>
    <button onClick={() => props.keplerGlDispatch(toggleFullScreen())}/>
    <KeplerGl
      id="foo"
    />
  </div>
)

const mapStateToProps = state => state
const mapDispatchToProps = (dispatch, props) => ({
 dispatch,
 keplerGlDispatch: forwardTo(‘foo’, dispatch)
});

export default connect(
 mapStateToProps,
 mapDispatchToProps
)(MapContainer);
```

* Wrap action payload

You can also simply wrap an action into a forward action with the `wrapTo` helper

```js
// component
import KeplerGl from '@kepler.gl/components';

// action and forward dispatcher
import {toggleFullScreen, wrapTo} from '@kepler.gl/actions';

// create a function to wrapper action payload to 'foo'
const wrapToMap = wrapTo('foo');
const MapContainer = ({dispatch}) => (
  <div>
    <button onClick={() => dispatch(wrapToMap(toggleFullScreen())} />
    <KeplerGl
      id="foo"
    />
  </div>
);

```

Read more about [forward dispatching actions](/docs/api-reference/advanced-usages/forward-actions)

#### 4. Customize style.

Kepler.gl implements css styling using [Styled-Components](https://www.styled-components.com/). By using said framework Kepler.gl offers the ability to customize its style/theme using the following approaches:

* Passing a Theme prop
* Styled-Components ThemeProvider

The available properties to customize are listed here [theme](https://github.com/keplergl/kepler.gl/blob/master/src/styles/base.js).

[Custom theme example](https://github.com/keplergl/kepler.gl/tree/master/examples/custom-theme).

**Passing a Theme prop.**

You can customize Kepler.gl theme by passing a **theme** props to Kepler.gl react component as it follows:

```javascript
const white = '#ffffff';
const customTheme = {
  sidePanelBg: white,
  titleTextColor: '#000000',
  sidePanelHeaderBg: '#f7f7F7',
  subtextColorActive: '#2473bd'
};

return (
  <KeplerGl
    mapboxApiAccessToken={MAPBOX_TOKEN}
    id="map"
    width={800}
    height={800}
    theme={customTheme}
  />
);
```

As you can see the customTheme object defines certain properties which will override Kepler.gl default style rules.

**Styled-Components Theme Provider.**

In order to customize Kepler.gl theme using [ThemeProvider](https://www.styled-components.com/docs/api#themeprovider) you can simply wrap Kepler.gl using ThemeProvider as it follows:

```javascript
import {ThemeProvider} from 'styled-components';

const white = '#ffffff';
const customTheme = {
  sidePanelBg: white,
  titleTextColor: '#000000',
  sidePanelHeaderBg: '#f7f7F7',
  subtextColorActive: '#2473bd'
};

return (
  <ThemeProvider theme={customTheme}>
    <KeplerGl mapboxApiAccessToken={MAPBOX_TOKEN} id="map" width={800} height={800} />
  </ThemeProvider>
);
```

#### 5. Render Custom UI components.

Everyone wants the flexibility to render custom kepler.gl components. Kepler.gl has a dependency injection system that allow you to inject components to KeplerGl replacing existing ones. All you need to do is to create a component factory for the one you want to replace, import the original component factory and call `injectComponents` at the root component of your app where `KeplerGl` is mounted. Take a look at `examples/demo-app/src/app.js` and see how it renders a custom side panel header in kepler.gl

```javascript
import {injectComponents, PanelHeaderFactory} from '@kepler.gl/components';

// define custom header
const CustomHeader = () => <div>My kepler.gl app</div>;
const myCustomHeaderFactory = () => CustomHeader;

// Inject custom header into Kepler.gl, replacing default
const KeplerGl = injectComponents([[PanelHeaderFactory, myCustomHeaderFactory]]);

// render KeplerGl, it will render your custom header instead of the default
const MapContainer = () => (
  <div>
    <KeplerGl id="foo" />
  </div>
);
```

Using `withState` helper to add reducer state and actions to customized component as additional props.

```js
import {withState, injectComponents, PanelHeaderFactory} from '@kepler.gl/components';
import {visStateLens} from '@kepler.gl/reducers';

// custom action wrap to mounted instance
const addTodo = text =>
  wrapTo('map', {
    type: 'ADD_TODO',
    text
  });

// define custom header
const CustomHeader = ({visState, addTodo}) => (
  <div onClick={() => addTodo('hello')}>{`${
    Object.keys(visState.datasets).length
  } dataset loaded`}</div>
);

// now CustomHeader will receive `visState` and `addTodo` as additional props.
const myCustomHeaderFactory = () =>
  withState(
    // keplerGl state lenses
    [visStateLens],
    // customMapStateToProps
    headerStateToProps,
    // actions
    {addTodo}
  )(CustomHeader);
```

Read more about [replacing UI component](/docs/api-reference/advanced-usages/replace-ui-component)

#### 6. How to add data to map

To interact with a kepler.gl instance and add new data to it, you can dispatch the **`addDataToMap`** action from anywhere inside your app. It adds a dataset or multiple datasets to a kepler.gl instance and updates the full configuration (mapState, mapStyle, visState).

**Parameters**

* `data` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) **\*required**
  * `datasets` **(**[**Array**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)**<**[**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)**> |** [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)**)** **\*required** datasets can be a dataset or an array of datasets Each dataset object needs to have `info` and `data` property.
    * `datasets.info` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) -info of a dataset
      * `datasets.info.id` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) id of this dataset. If config is defined, `id` should matches the `dataId` in config.
      * `datasets.info.label` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) A display name of this dataset
    * `datasets.data` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) **\*required** The data object, in a tabular format with 2 properties `fields` and `rows`
      * `datasets.data.fields` [**Array**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)**<**[**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)**>** **\*required** Array of fields,
        * `datasets.data.fields.name` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) **\*required** Name of the field,
      * `datasets.data.rows` [**Array**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)**<**[**Array**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)**>** **\*required** Array of rows, in a tabular format with `fields` and `rows`
  * `options` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)
    * `options.centerMap` [**boolean**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean) `default: true` if `centerMap` is set to `true` kepler.gl will place the map view within the data points boundaries
    * `options.readOnly` [**boolean**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean) `default: false` if `readOnly` is set to `true` the left setting panel will be hidden
    * `options.keepExistingConfig` [**boolean**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean) `default: false` whether to keep exiting map config, including layers, filters and splitMaps.
* `config` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) this object will contain the full kepler.gl instance configuration {mapState, mapStyle, visState}

Kepler.gl provides an easy API `KeplerGlSchema.getConfigToSave` to generate a json blob of the current kepler instance configuration.

**Examples**

```javascript
// app.js
import {addDataToMap} from '@kepler.gl/actions';

const sampleTripData = {
  fields: [
    {name: 'tpep_pickup_datetime', format: 'YYYY-M-D H:m:s', type: 'timestamp'},
    {name: 'pickup_longitude', format: '', type: 'real'},
    {name: 'pickup_latitude', format: '', type: 'real'}
  ],
  rows: [
    ['2015-01-15 19:05:39 +00:00', -73.99389648, 40.75011063],
    ['2015-01-15 19:05:39 +00:00', -73.97642517, 40.73981094],
    ['2015-01-15 19:05:40 +00:00', -73.96870422, 40.75424576]
  ]
};

const sampleConfig = {
  visState: {
    filters: [
      {
        id: 'me',
        dataId: 'test_trip_data',
        name: 'tpep_pickup_datetime',
        type: 'timeRange',
        view: 'enlarged'
      }
    ]
  }
};

this.props.dispatch(
  addDataToMap({
    datasets: {
      info: {
        label: 'Sample Taxi Trips in New York City',
        id: 'test_trip_data'
      },
      data: sampleTripData
    },
    option: {
      centerMap: true,
      readOnly: false
    },
    config: sampleConfig
  })
);
```

Read more about [addDataToMap](/docs/api-reference/actions/actions#adddatatomap) and [Saving and loading maps with schema manager](/docs/api-reference/advanced-usages/saving-loading-w-schema).


# What's new?

This page shows features that have landed to kepler.gl in major versions. For a complete list of changes to kepler.gl including each minor version, please [visit the full change log](/changelog).

## 3.3

### deck.gl 9 / luma.gl 9 Rendering Stack

kepler.gl 3.3 upgrades the entire rendering stack from **deck.gl 8 / luma.gl 8** to **deck.gl 9.2 / luma.gl 9.2**. This is a major internal change that modernizes how WebGL resources, shaders, and rendering parameters are handled. Blending is now declarative via WebGPU-style string constants, all custom shaders target GLSL 300 es with Uniform Buffer Objects (UBOs), and the GPU initialization callback uses luma.gl's device-agnostic `Device` abstraction instead of a raw `WebGLRenderingContext`.

Most users will not need to change application code, but library consumers who extend layers or interact with the WebGL context directly should review the [Upgrade Guide](/upgrade-guide-v3.3).

### Editor Layer Migration

The editor layer (`EditableGeoJsonLayer` for draw/edit modes) has been migrated from the deprecated `@nebula.gl/layers` package to `@deck.gl-community/editable-layers`. The API remains the same.

### TypeScript 5.6

TypeScript has been upgraded from 4.7.2 to 5.6.3.

### More Bug Fixes and Improvements

* Fix blending for subtractive mode.
* Restore shadow effect uniform shadow during nighttime.
* Fix raster tile layer shaders (UBO migration, pipeline validation patch).
* Fix aggregation layer highlight outlines and infinite config changes.
* Fix H3, GeoJSON, line, and arc layer issues after the deck.gl 9 upgrade.
* Disable mouse-move and hover console logging by default.
* Fog effects.
* Internal improvements to aggregation layers.

For the complete list of commits, see the [full change log](/changelog).

## 3.2

*Released August 21st, 2025*

### Raster Tile Layer

The new [Raster Tile layer](/docs/user-guides/c-types-of-layers/n-raster-tile-layer) enables visualization of satellite and aerial imagery from raster PMTiles and Cloud-Optimized GeoTIFFs (via STAC). Use it to bring large imagery datasets into kepler.gl without dedicated tile infrastructure for raster PMTiles, or connect through a compatible raster tile server for COGs and elevation.

### WMS Layer

The new WMS layer adds support for rendering imagery and map tiles from OGC Web Map Service endpoints, allowing you to integrate enterprise or public WMS sources directly in kepler.gl.

### AI Assistant

* Generate idea buttons from the LLM to speed up workflows.
* More reliable local model connectivity (fix for Ollama connection issues).
* Configuration migrated to TypeScript for better npm consumption.

### More Bug Fixes and Improvements

* Fit-to-bounds: fix initial basemap and deck projections mismatch.
* Aggregation layers: fixes for custom color scales.
* Vector tiles: regression fixes for field extraction and setup flow.
* Image export: fixes when effects are enabled.
* Loading indicator: behavior and visibility improvements.
* DuckDB: fix importing files with spaces in column names.

For the complete list of commits, see the [full change log](/changelog).

## 3.1.1

*Released March 10th, 2025*

### DuckDB

The DuckDB integration has been updated in response to feedback and requests, speeding up workflows for projects with local data. Notable changes include:

* Users can now drag and drop files directly in kepler.gl to create a DuckDB table.
* The schema panel now always updates when running a query.
* Improved handling of DuckDB column types.

![DuckDB Drag and Drop](https://4sq-studio-public.s3.us-west-2.amazonaws.com/statics/keplergl/images/kepler-gl-duckdb-drag-drop.gif)

### Vector Tiles

The Vector Tile layer has received a number of optimizations, bug fixes, and quality-of-life improvements. Notable changes include:

* For older tilesets without fields in the metadata file, kepler.gl now attempts to retrieve fields from the tile data.
* Automatically center the map to the tileset bounds.
* Fix for UI freezes during initial Tileset setup.

### More Bug Fixes

A number of bug fixes have been deployed in response to community feedback. The most notable bug fixes are listed below, but you can view a full list of changes [in the full change log](/changelog).

* Fix for geocoder coordinates, allowing users to enter coordinates directly.
* Fix for icon layers at higher zoom levels—icons now remain the same size.
* Fix for a broken section of the Icon Layer UI.
* Ensure the RangeBrush updates when the slider range changes.
* Transform binary buffers to hex WKB when saving to JSON/HTML maps.
* Improved logic for changing layer types.
* Support arrow text labels from non-string vector sources.
* Export GeoArrow columns to CSV as GeoJSON.
* Restore support for string WKB data; save binary WKB as hex WKB.
* AI Assistant now sends messages to 127.0.0.1 instead of a remote Ollama URL.
* Fix for disappearing heatmaps when rendering black or duplicate colors.
* Fix for point column suggestions not working.
* Fix for crashes in GeoJSON and Trip layers when no data is present.
* Fix for the "Save Map" action when using the FSQ provider (overwrite logic).
* FSQ storage provider now prompts for login instead of auto-login after logout.

## 3.1

*Released January 29th, 2025*

### Vector Tiles

The new [Vector Tile layer](https://github.com/keplergl/kepler.gl/blob/master/docs/user-guides/c-types-of-layers/vector.md) allows the map to dynamically retrieve data based on the user's viewport and zoom level. This initial release supports both Mapbox Vector Tiles and PMTiles.

By leveraging the efficiency of vector tiles, users can visualize complex, large-scale datasets without compromising performance, making it easier to explore and analyze geospatial data.

![Vector layer](https://4sq-studio-public.s3.us-west-2.amazonaws.com/statics/keplergl/images/kepler-vector.gif)

### DuckDB Support & SQL Explorer

Leverage DuckDB directly within kepler.gl for your geospatial projects with big data. Write and execute SQL queries to perform custom analyses, visualizing the results on your map.

DuckDB enables in-browser data processing, allowing you to work with large datasets without the need for external infrastructure.

![SQL Data Explorer](https://4sq-studio-public.s3.us-west-2.amazonaws.com/statics/keplergl/images/kepler-duck-db.png)

### AI Assistant

Kepler’s AI assistant can edit the map, including filters, base map customization, and a variety of layer configurations. Accessible via text chat, voice chat, and screenshot. The assistant can also produce SQL from natural language, which can be passed to DuckDB.

![AI Assistant](https://4sq-studio-public.s3.us-west-2.amazonaws.com/statics/keplergl/images/kepler-ai-assistant.png)

### Base Map Updates: MapLibre + Mapbox

Mapbox and MapLibre base maps are now simultaneously supported.

### Color Scale Improvements

Custom color scale is now supported in categorical/ordinal fields, aggregate layers, and other layer components. In addition, custom breaks are now supported within the color scales.

### Value Formatting

Formatting for numeric values (e.g. 10,000 can be formatted 10k, $10,000.00, etc; .42 can be formatted as 42%).

### Animation Improvements

Includes various updates to the user interface for animation (for both time filters and the trip layer). You may also sync the layers (such as the trip layer) with filters, and conversely sync filters with the layer.

### Legend Improvements

The legend is now both movable and resizable, supports the editing of legend values, and offers a scale for radius scaling.

### Various Layer Improvements

A number of improvements to layers, including:

* Zoom to layer button lets users center their viewport on the layer’s data
* Point layer now supports geojson
* Arc layer supports creation from h3
* A vast number of other layer improvements

This release also includes a wide range of bug fixes and performance improvements, which can be viewed in the [full change log.](/changelog)


# Docs

## Table of contents

* [What's new?](/release-notes)
* [API References](/docs/api-reference)
* [User Guides](/docs/user-guides)
* [Jupyter Notebook](/docs/keplergl-jupyter)


# User guides

Kepler.gl is designed for geospatial data analysis. It allows technical and non-technical audiences to visualize trends in a city or region. With Kepler.gl, you can…

Visualize a large amount of location data in your browser. Playback geo-temporal trends over time. Explore, filter, and deeply engage with location data to gain insight

See the sample maps in the demo app for more examples.

![Kepler.gl sample map](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/image11.png)

This guide will teach you how to perform data analysis in Kepler.gl by adding data to a map, creating layers, adding filters, and more.

## Table of contents:

#### [Get Started](/docs/user-guides/j-get-started)

#### [The kepler.gl workflow](/docs/user-guides/b-kepler-gl-workflow)

* [Add data to the map](/docs/user-guides/b-kepler-gl-workflow/a-add-data-to-the-map)
* [Adding data layers](/docs/user-guides/b-kepler-gl-workflow/add-data-to-layers/a-adding-data-layers)
* [Create a layer](/docs/user-guides/b-kepler-gl-workflow/add-data-to-layers/b-create-a-layer)
* [Hide, edit and delete layers](/docs/user-guides/b-kepler-gl-workflow/add-data-to-layers/c-hide-edit-and-delete-layers)
* [Blend and rearrange layers](/docs/user-guides/b-kepler-gl-workflow/add-data-to-layers/d-blend-and-rearrange-layers)

#### [Layers](/docs/user-guides/c-types-of-layers)

* [Point](/docs/user-guides/c-types-of-layers/a-point)
* [Arc](/docs/user-guides/c-types-of-layers/b-arc)
* [Line](/docs/user-guides/c-types-of-layers/c-line)
* [Grid](/docs/user-guides/c-types-of-layers/d-grid)
* [Polygon](/docs/user-guides/c-types-of-layers/e-polygon)
* [Cluster](/docs/user-guides/c-types-of-layers/f-cluster)
* [Icon](/docs/user-guides/c-types-of-layers/g-icon)
* [Hexbin](/docs/user-guides/c-types-of-layers/h-hexbin)
* [Heatmap](/docs/user-guides/c-types-of-layers/i-heatmap)
* [H3](/docs/user-guides/c-types-of-layers/j-h3)
* [Trip](/docs/user-guides/c-types-of-layers/k-trip)
* [S2](/docs/user-guides/c-types-of-layers/l-s2)
* [Vector Tile Layer](/docs/user-guides/c-types-of-layers/m-vector-tile-layer)
* [Raster Tile Layer](/docs/user-guides/c-types-of-layers/n-raster-tile-layer)
* [WMS Layer](/docs/user-guides/c-types-of-layers/o-wms-layer)

#### [Layer attributes](/docs/user-guides/d-layer-attributes)

#### [Color Palettes](/docs/user-guides/l-color-attributes)

#### [Filters](/docs/user-guides/e-filters)

#### [Map styles](/docs/user-guides/f-map-styles#map-styles)

* [Base map styles](/docs/user-guides/f-map-styles#base-map-styles)
* [Map layers](/docs/user-guides/f-map-styles#toggle-map-layers)
* [Custom styles](/docs/user-guides/f-map-styles#custom-map-styles)

#### [Interactions](/docs/user-guides/g-interactions)

* [Tooltips](/docs/user-guides/g-interactions#tooltips)
* [Brushing](/docs/user-guides/g-interactions#brushing)
* [Display Coordinates](/docs/user-guides/g-interactions#display-coordinates)

#### [Map Settings](/docs/user-guides/m-map-settings)

* [View maps in 3d](/docs/user-guides/m-map-settings#view-maps-in-3d)
* [Globe view](/docs/user-guides/m-map-settings#globe-view)
* [Display legend](/docs/user-guides/m-map-settings#display-legend)
* [Split maps](/docs/user-guides/m-map-settings#split-maps)

#### [Effects](https://github.com/keplergl/kepler.gl/blob/master/docs/user-guides/effects.md)

* [Light & Shadow](https://github.com/keplergl/kepler.gl/blob/master/docs/user-guides/effects.md#light--shadow)
* [Post-processing (Ink, Blur, Sepia, …)](https://github.com/keplergl/kepler.gl/blob/master/docs/user-guides/effects.md#ink)
* [Distance Fog](https://github.com/keplergl/kepler.gl/blob/master/docs/user-guides/effects.md#distance-fog)
* [Surface Fog](https://github.com/keplergl/kepler.gl/blob/master/docs/user-guides/effects.md#surface-fog)

#### [SQL Data Explorer](https://github.com/keplergl/kepler.gl/blob/master/docs/user-guides/sql-data-explorer.md)

#### [AI Assistant](https://github.com/keplergl/kepler.gl/blob/master/docs/user-guides/ai-assistant.md)

#### [Time playback](/docs/user-guides/h-playback)

#### [Save and export](/docs/user-guides/k-save-and-export)

* [Export Image](/docs/user-guides/k-save-and-export#export-image)
* [Export Data](/docs/user-guides/k-save-and-export#export-data)
* [Export Map](/docs/user-guides/k-save-and-export#export-map)
* [Export Video](/docs/user-guides/k-save-and-export#export-video)

#### [FAQ](https://github.com/keplergl/kepler.gl/blob/master/docs/user-guides/i-FAQ.md)


# Get Started

Kepler.gl is a tool designed for geospatial data analysis. This guide will help you get started creating visualizations in kepler.gl.

## 1) Add Data to your Map

![Add data to the map pop up](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/image42.png)

Kepler.gl will prompt you to add data to your map as soon as you open the web page. Upload your own CSV or GEOJSON file, or add kepler.gl sample data. Sample data is a great way to explore and get familiar with kepler.gl’s features.

Read more about adding [Add data to the map](/docs/user-guides/b-kepler-gl-workflow/a-add-data-to-the-map).

## 2) Add Layers

![Add layer](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/j-get-started-layers.png)

Open the Data Layers menu to start building your visualization. Layers are simply data visualizations that can be built on top of one another. The map pictured above contains a GeoJSON path layer showing trip routes.

If you’re new to kepler.gl, play around with the different settings for each type of layer. Layers of the same type can differ greatly in appearance depending on how they’re configured, opening up new possibilities for data analysis.

Learn more about [adding data layers](/docs/user-guides/b-kepler-gl-workflow/add-data-to-layers/a-adding-data-layers) .

## 3) Add Filters

![choose a dataset](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/add-filter.png)

Add filters to your map to limit the data that is displayed. Filters must be based on the columns in your dataset. To create a new filter, open the Filter menu and click Add Filter. Note that filters apply to all layers and cannot be toggled on and off.

Learn more about [filters](/docs/user-guides/e-filters).

## 4) Customize Map Settings

![Customize Map Settings](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/interactions.png)

Change the settings on your map in the Interactions and Base Map menus. Customization options include tooltips, brush highlighting, base map style, map imagery toggles (water, parks, satellite image, etc.), and many more.

Read about [base map styles](/docs/user-guides/f-map-styles), [interactions](/docs/user-guides/g-interactions) and [map settings](/docs/user-guides/m-map-settings).

## 5) Save and Export

![Save and Export](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/export-save.png) Save your map as an image, export current map data, export current map as a json file to be load back into kepler.gl.

Read about [Save and export](/docs/user-guides/k-save-and-export).

[Back to table of contents](/docs/user-guides)


# Kepler.gl workflow

## Table of contents

* [Add data to the map](/docs/user-guides/b-kepler-gl-workflow/a-add-data-to-the-map)
* [Adding data layers](/docs/user-guides/b-kepler-gl-workflow/add-data-to-layers/a-adding-data-layers)
* [Create a layer](/docs/user-guides/b-kepler-gl-workflow/add-data-to-layers/b-create-a-layer)
* [Hide, edit and delete layers](/docs/user-guides/b-kepler-gl-workflow/add-data-to-layers/c-hide-edit-and-delete-layers)
* [Blend and rearrange layers](/docs/user-guides/b-kepler-gl-workflow/add-data-to-layers/d-blend-and-rearrange-layers)

[Back to table of contents](/docs/user-guides)


# Add data to layers


# Adding Data Layers

The term "Layer" refers to a layer of data visualization. For example, you might add a point layer to visualize all the instances where taxi trips began, as in the map of New York City below.

![Sample NYC Map](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/image43.png)

Each blue dot represents the point (latitude and longitude). Layers work like paint—you can build up multiple layers to change the appearance of the canvas. You might create a second point layer to show trip drop-off locations. The map then looks like this:

![Sample NYC Map with colors](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/image6.png)

Learn more about the [types of layers](/docs/user-guides/c-types-of-layers) available in Kepler.gl.

[Back to table of contents](/docs/user-guides)


# Create a Layer

1. Click the Data Layers icon in the left navigation bar. ![Add data layer](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/image39.png)
2. The Layers panel displays a list of existing layers and the name of the dataset the layers belong to (Sample Trip Data, in the example below). To create a new layer, click **Add Layer** at the bottom of the menu. ![Add layer](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/image16.png)
3. If your map contains multiple datasets, you’ll be asked to select the data source for your new layer. ![Select data source for layer](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/image28.png)
4. Select a layer type. Read about the different \[types of layers]. ![Select layer type](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/image41.png)
5. Fill in the required columns and adjust the optional settings if desired.
6. Collapse the layer settings menu when finished.

[Back to table of contents](/docs/user-guides)


# Blend and Rearrange Layers

&#x20;**Rearrange layers by dragging and dropping them in the Layers panel. The layers at the top of the list will be displayed in the foreground of the map.**\
\
&#x20;![Rearrange layers](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/image44.png)\ <br>

&#x20;**Blend layers by selecting an option from the dropdown at the bottom of the Layers panel.**\
\
&#x20;![Blend layers](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/image10.png)\
\
&#x20;**There are three different ways to blend layers: Normal, Additive, and Subtractive.**\ <br>

## Normal Blending

Normal layer blending does not alter the color values of overlapping data points. ![Normal blending](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/image19.png)

## Additive Blending

Additive blending adds the color values for overlapping data points. It makes layers, and particularly areas of high density, easier to visualize on a dark-colored map. ![Additive blending](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/image34.png)

## Subtractive Blending

Subtractive layer blending does not alter the color values of overlapping data points. ![Subtractive blending](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/image26.png)

[Back to table of contents](/docs/user-guides)


# Hide, Edit and Delete Layers

Each layer has its own tab in the **Data Layers** menu: ![Hide, edit and delete layers](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/image8.png)

Click the **down arrow** to open up the settings menu for that layer. Click the **trashcan** to delete a layer. Click the **eye** to toggle show/hide.

**Note**: The colored line on the left of each layer tab represents what dataset that layer belongs to.

[Back to table of contents](/docs/user-guides)


# Add Data to the Map

## Ways to Add Data

* Open kepler.gl/demo. You should see the following prompt:

![Add data to the map pop up](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/image42.png)

**kepler.gl is a pure client side app. Data lives only in your machine/browser. No information or maps is sent back up to our server.**

* Choose one of three ways to add data to your map

|                 |                                                                                                                                                                                                                                                                 |
| --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Local files** | Upload CSV / GeoJSON files. Because data is only stored in your browser, there is a **250mb** limit on how much data Chrome allows you to upload into a browser. For datasets larger than **250mb** you should directly load them from a remote URL. See below. |
| **From URL**    | Directly load data or map json by pasting a remote URL. You can link it to CSV                                                                                                                                                                                  |
| **Sample data** | Load one of kepler.gl’s sample datasets. The sample map data and config are directly loaded from [kepler.gl-data github](https://github.com/keplergl/kepler.gl-data) repo                                                                                       |

## Supported Projection Coordinate System

kepler.gl only supports [**Web Mercator**](https://en.wikipedia.org/wiki/Web_Mercator_projection) **EPSG:3857 -- WGS84**.

Geometry coordinates should be presented with a geographic coordinate reference system, using the WGS84 datum, and with longitude and latitude units of decimal degrees.

## Supported File Formats

* [CSV](#csv)
* [GeoJSON](#geojson)
* [GeoArrow](#geoarrow)
* [kepler.gl Json](#keplergl-json)

### CSV

CSV file should contain header row and multiple columns. Each row should be 1 feature. Each column should contain only 1 data type, based on which kepler.gl will use to create layers and filters.

| id | point\_latitude | point\_longitude | value | start\_time      |
| -- | --------------- | ---------------- | ----- | ---------------- |
| a  | 31.2384         | -127.30948       | 5     | 2019-08-01 12:00 |
| b  | 31.2311         | -127.30231       | 11    | 2019-08-01 12:05 |
| c  | 31.2334         | -127.30238       | 9     | 2019-08-01 11:55 |

#### 1. Data type detection

Because CSV file content is uploaded as strings, kepler.gl will attempt to detect column data type by parsing a sample of data in each column. kepler.gl can detect

| type              | data                                                                                                                                                                                                                                                             |
| ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| ***`boolean`***   | `True`, `False`                                                                                                                                                                                                                                                  |
| ***`date`***      | `2019-01-01`                                                                                                                                                                                                                                                     |
| ***`geojson`***   | **WKT string:** `POLYGON ((-74.158 40.835, -74.148 40.830, -74.151 40.832, -74.158 40.835))`, **or GeoJson String** `{"type":"Polygon","coordinates":[[[-74.158,40.835],[-74.157,40.839],[-74.148,40.830],[-74.150,40.833],[-74.151,40.832],[-74.158,40.835]]]}` |
| ***`integer`***   | `1`, `2`, `3`                                                                                                                                                                                                                                                    |
| ***`real`***      | `-74.158`, `40.832`                                                                                                                                                                                                                                              |
| ***`string`***    | `hello`, `world`                                                                                                                                                                                                                                                 |
| ***`timestamp`*** | `2018-09-01 00:00`, `1570306147`, `1570306147000`                                                                                                                                                                                                                |

**Note:** Make sure to clean up values such as `N/A`, `Null`, `\N`. If your column contains mixed type, kepler.gl will treat it as ***`string`*** to be safe.

#### 2. Layer detection based on column names

kepler.gl will auto detect layer, if the column names follows certain naming convention. kepler.gl creates a point layer if your CSV has columns that are named `<name>_lat` and `<name>_lng` or `<name>_latitude` and `<name>_longitude`, or `<name>_lat` and `<name>_lon`.

| layer       | auto create layer from column names                                                                                                                                                                                                                                                                                                                                       |
| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Point**   | Point layer names have to be in pairs, and **ends with** `<foo>lat, <foo>lng`; `<foo>latitude, <foo>longitude`; `<foo>lat, <foo>lon`                                                                                                                                                                                                                                      |
| **Arc**     | If two points layers are detected, one arc layer will be created                                                                                                                                                                                                                                                                                                          |
| **Icon**    | A column named `icon` is present                                                                                                                                                                                                                                                                                                                                          |
| **H3**      | A column named `h3_id` or `hexagon_id` is present                                                                                                                                                                                                                                                                                                                         |
| **Polygon** | A column content contains `geojson` data types. Acceptable formats include [Well-Known Text](http://www.postgis.net/docs/ST_AsText.html) e.g. `POLYGON ((-74.158 40.835, -74.148 40.830, -74.151 40.832, -74.158 40.835))` and [GeoJSON Geometry](https://tools.ietf.org/html/rfc7946#appendix-A). e.g. `{"type":"LineString","coordinates":[[100.0, 0.0],[101.0, 1.0]]}` |

#### 3. Embed Geometries in CSV

Geometries (Polygons, Points, LineStrings etc) can be embedded into CSV as a `GeoJSON` or `WKT` formatted string.

**`GeoJSON` String**

Use the geometry of a Feature, which includes type and coordinates. It should be a JSON formatted string, with the `"` corrected escaped. More info on [String escape in csv](https://gpdb.docs.pivotal.io/43250/admin_guide/load/topics/g-escaping-in-csv-formatted-files.html)

Example data.csv with GeoJSON

```txt
id,geometry
1,"{""type"":""Polygon"",""coordinates"":[[[-74.158491,40.835947],[-74.157914,40.83902]]]}"
```

**`WKT`String**

[The Well-Known Text (WKT)](https://dev.mysql.com/doc/refman/5.7/en/gis-data-formats.html#gis-wkt-format) representation of geometry values is designed for exchanging geometry data in ASCII form.

Example data.csv with WKT

```txt
id,geometry
1,"POLYGON((0 0,10 0,10 10,0 10,0 0),(5 5,7 5,7 7,5 7, 5 5))"
```

### GeoJSON

#### 1. Feature types

* kepler.gl accepts GeoJSON formatted JSON that contains a single [Feature](https://tools.ietf.org/html/rfc7946#section-3.2) object or a [FeatureCollection](https://tools.ietf.org/html/rfc7946#section-3.3) object. kepler.gl creates one **`Polygon`** layer per GeoJSON file.

  * A single GeoJSON Feature:

  ```json
    {
      "type": "Feature",
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          [
            [-10.0, -10.0],
            [10.0, -10.0],
            [10.0, 10.0],
            [-10.0, -10.0]
          ]
        ]
      },
      "properties": {
        "name": "foo"
      }
    }
  ```

  * GeoJSON Feature Collection.

  ```json
  {
    "type": "FeatureCollection",
    "features": [{
        "type": "Feature",
        "geometry": {
            "type": "Point",
            "coordinates": [102.0, 0.5]
        },
        "properties": {
            "prop0": "value0"
        }
    }, {
        "type": "Feature",
        "geometry": {
            "type": "LineString",
            "coordinates": [
                [102.0, 0.0],
                [103.0, 1.0],
                [104.0, 0.0],
                [105.0, 1.0]
            ]
        },
        "properties": {
          "prop0": "value0"
        }
    }]
  }
  ```

  kepler.gl will render all features in one `Polygon` layer even though they have different geometry types. Acceptable geometry types are

  * [Point](https://tools.ietf.org/html/rfc7946#section-3.1.2)
  * [MultiPoint](https://tools.ietf.org/html/rfc7946#section-3.1.3)
  * [LineString](https://tools.ietf.org/html/rfc7946#section-3.1.4)
  * [MultiLineString](https://tools.ietf.org/html/rfc7946#section-3.1.5)
  * [Polygon](https://tools.ietf.org/html/rfc7946#section-3.1.6)
  * [MultiPolygon](https://tools.ietf.org/html/rfc7946#section-3.1.7).

  Feature properties will be parsed as columns. You can apply color, filters based on them.

#### 2. Auto styling

kepler.gl will read styles from GeoJSON files. If you are a GeoJSON expert, you can add style declarations to feature properties. kepler.gl will use the declarations to automatically style your feature. The acceptable style properties are:

```json
"properties": {
  "lineColor": [130, 154, 227],
  "lineWidth": 0.5,
  "fillColor": [255, 0, 0],
  "radius": 1 // Point
}
```

* See an example below:

```json
{
  "type": "FeatureCollection",
  "features": [{
      "type": "Feature",
      "geometry": {
        "type": "LineString",
        "coordinates": [
          [-105.1547889, 39.9862516],
          [-105.1547167, 39.9862691]
        ]
      },
      "properties": {
        "id": "a1398a11-d1ce-421c-bf66-a456ff525de9",
        "lineColor": [130, 154, 227],
        "lineWidth": 0.1
      }
  }]
}
```

### GeoArrow

[GeoArrow](https://geoarrow.org/) file, a binary data format which can be visualized with the [PolygonLayer](https://docs.kepler.gl/docs/user-guides/c-types-of-layers/e-polygon).

### kepler.gl JSON

JSON file exported from kepler.gl. See "[Export Map as JSON](https://docs.kepler.gl/docs/user-guides/k-save-and-export#export-map-as-json)".

### Load Map Using URL

You load data or map through custom URL. It currently supports URLs with file extension of `csv`, `json` and `kepler.gl.json`

In addition, this also by-passes 250mb file upload size limit which allows you to upload larger file to Kepler.

![Load Map Using URL](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/a-load-map-using-url.gif)

### Use Kepler.gl’s Sample Maps

The sample maps are a great option for new users to explore Kepler.gl and get a feel for how it works.

1. At the initial load prompt select “Try sample data” in the top right corner.

![Try sample data pop up](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/image2.png)

2. Choose from the options to load the sample map and explore the configurations applied.

![Choose sample data pop up](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/image5.png)

### Add multiple datasets

To add additional datasets to your map:

1. Click **Add More Data** in the top right corner.

![Add more data](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/image22.png)

2. Choose one of the options above: upload a JSON/CSV file, or use Kepler.gl’s sample data.
3. Repeat as needed. There is no limit on the number of datasets you can add. However, adding too many might cause its performance to suffer.

[Back to table of contents](/docs/user-guides)


# Layers

## Single Feature Layers

Single feature layers render 1 feature

## Point

![Point layer](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/image34.png)

Point layers draw points for a given event or object based on its location - latitude and longitude.

## Arc

![Arc layer](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/c-arc-layer.png)

Arc layers draw an arc between two points. They’re useful for visualizing the distance between two points as well as comparing distances in 3D. Note that arc layers don’t show routes between points, but simply the distance between the two points. The tallest arc represents the greatest distance.

To draw arcs, your dataset must contain the latitude and longitude of two different points for each arc.

Layer Attributes: Color/ Color Based On, Opacity, Stroke Width/ Stroke Based On, High Precision Rendering

## Line

![Line layer](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/c-line-layer.png)

Line layers are the 2D version of arc layers. Both draw a line between two points to represent distance, but in a line layer, the drawing lies flat on the map.

Layer Attributes: Color, Stroke, High Precision Rendering

## Hexbin

![Hexbin layer](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/c-hexbin-layer.png)

Hexbin aggregates points into hexagons. The counts can be represented through color and/or height.

Layer Attributes: Color/ Color Based On, Filter by Count Percentile, Opacity, Hexagon Radius (km), Coverage (Radius), Enable Height, Elevation Scale/ Height Based On, High Precision Rendering

## Heatmap

![Heatmap layer](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/c-heat-map.png)

Heatmap is a graphical representation of data in which data values are represented as colors.

Layer Attributes: Color, Opacity, Radius, Weight

## Cluster

![Cluster layer](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/c-cluster-layer.png)

Cluster layers visualize aggregated data based on a geospatial radius.

Layer Attributes: Color, Cluster Size

## Icon

![Icon layer](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/image33.png)

Icon layers are a type of point layer. They allow you to differentiate between points by assigning icons to points based on a field. For example, you might use icons to differentiate between types of venues and points of interest.

Layer Attributes: Color, Radius, Label, High Precision Rendering

To see the icon menu, create a new icon layer and click how to draw an icon layer:

![How to Draw Icon Layer](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/image38.png)

## Grid

![Grid layer](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/image21.png) ![3D Grid layer](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/c-grid-layer.png)

Grids layers are similar to heatmaps. They show the density of points. They provide visual discrepancy in a map where multiple heatmap-style layers are present.

Layer Attributes: Color, Radius, Height, High Precision Rendering

## GeoJSON

![GeoJSON layer](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/image20.png) ![Polygon geoJSON layer](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/image7.png)

GeoJSON layers can display either paths, polygons or points. For example, a path GeoJSON layer can display data like trip routes. A polygon GeoJSON layer is essentially a [choropleth](https://en.wikipedia.org/wiki/Choropleth_map) layer and works best for rendering geofences. To add a GeoJSON layer, your dataset must contain geometry data.

## H3

![H3 layer - contour](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/c-h3-layer.png)

H3 layers visualize spatial data using [H3 Hexagonal Hierarchical Spatial Index](https://eng.uber.com/h3/).

To use H3 layer, you need a `hex_id` in your dataset, which can be generated using [h3-js](https://github.com/uber/h3-js) from latitude, longitude and resolution.

## S2 Layer

![S2 Layer](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/l-s2.png)

To use S2 layer, you need to assign a column containing S2 tokens.

## Vector Tile Layer

![Vector Tile layer](https://4sq-studio-public.s3.us-west-2.amazonaws.com/statics/keplergl/documentation/layer-types/vector-tile.png)

Vector Tile Layer makes it possible to visualize very large datasets through MVTs (Mapbox Vector Tiles). To optimize performance, the layer only loads and renders tiles containing features that are visible within the current viewport.

Supported URL templates:

* MVT (<https://api.mapbox.com/v4/mapbox.mapbox-streets-v8/{z}/{x}/{y}.mvt?access\\_token=your-mapbox-acceess-token>)
* pmtiles (<https://your-cdn/filename.pmtiles>)

For step-by-step instructions, see [Vector Tile Layer — How to add](/docs/user-guides/c-types-of-layers/m-vector-tile-layer).

## Raster Tile Layer (experimental)

![Raster Tile layer](https://4sq-studio-public.s3.us-west-2.amazonaws.com/statics/keplergl/documentation/layer-types/raster-tile.png)

Raster layers are used to show satellite and aerial imagery. They allow you to work interactively directly with massive, image collections stored in .pmtiles (in raster format) or Cloud Optimized GeoTIFF format.

Supported URL templates:

* Users can reference remote **.pmtiles files in raster format** for raster layers by supplying a direct link to the file.
* **Cloud-Optimized GeoTIFFs (COG)** can also be used in raster layers by providing standardized Spatio-Temporal Asset Catalog (STAC) metadata.

  * The metadata file must be a valid *STAC Item* or *STAC Collection*, version 1.0.0 or higher.
  * Raster data referenced in STAC assets should be Cloud-Optimized GeoTIFFs and need to be publicly accessible via HTTPS.
  * STAC item and collections *must have Electro-Optical and Raster extensions*, and at least one asset must have both eo:bands and raster:bands information. common\_name must be provided in eo:bands and data\_type must be provided in raster:bands.
  * To use COGs with STAC metadata, you must run your own raster tile server (e.g., TiTiler). Example implementation: [kepler-raster-server](https://github.com/igorDykhta/kepler-raster-server).

  Examples of raster .pmtiles:

  * Swiss historical - <https://public-bucket-for-tests.s3.us-east-1.amazonaws.com/historic-swis-18xx.pmtiles>

  Examples of supported STAC Items:

  * Bangladesh rivers — <https://4sq-studio-public.s3.us-west-2.amazonaws.com/sdk/examples/sample-data/raster/planet-skysat-opendata.json>
  * Antarctica ice — <https://4sq-studio-public.s3.us-west-2.amazonaws.com/sdk/examples/sample-data/raster/sentinel-2-l2a.json>
  * Kiribati island — <https://4sq-studio-public.s3.us-west-2.amazonaws.com/sdk/examples/sample-data/raster/stac-example.json>

  Examples of supported STAC Collections:

  * sentinel-2-l1c — <https://earth-search.aws.element84.com/v1/collections/sentinel-2-l1c>
  * modis-09A1-061 — <https://planetarycomputer.microsoft.com/api/stac/v1/collections/modis-09A1-061>
  * landsat-c2-l1 — <https://planetarycomputer.microsoft.com/api/stac/v1/collections/landsat-c2-l1>

For step-by-step instructions, see [Raster Tile Layer — How to add](/docs/user-guides/c-types-of-layers/n-raster-tile-layer).

## WMS Layer (experimental)

![WMS layer](https://4sq-studio-public.s3.us-west-2.amazonaws.com/statics/keplergl/documentation/layer-types/wms.png)

* Web Map Service (WMS) layers render raster tiles from OGC WMS servers.
* This feature is experimental and disabled by default. To try it, enable `enableWMSLayer: true` in the application configuration.
* When enabled, add a WMS service via the Tilesets modal by providing the service URL and selecting a named layer. Feature info on click is supported for queryable layers.

Examples of supported WMS Tiles:

* <https://ows.terrestris.de/osm/service>
* <https://opengeo.ncep.noaa.gov/geoserver/conus/conus\\_cref\\_qcd/ows>
* <https://gibs.earthdata.nasa.gov/wms/epsg4326/best/wms.cgi>
* <https://geo.stadt-muenster.de/mapserv/starkregen\\_serv>

For step-by-step instructions, see [WMS Layer — How to add](/docs/user-guides/c-types-of-layers/o-wms-layer).

## Flow Layer (experimental)

Flow layers visualize movement between locations as aggregated origin-destination flows. They are useful for displaying migration patterns, commute data, trade routes, and any dataset that represents movement between geographic points.

The layer automatically clusters nearby locations at different zoom levels, draws flow lines proportional to magnitude, and renders location totals as circles. It supports two column modes: **Lat/Lng** (source/target coordinates) and **H3** (source/target H3 hexagonal indices). An optional count column controls flow magnitude.

* This feature is experimental and currently enabled by default via `enableFlowLayer: true` in the application configuration.

Layer Attributes: Color Range, Opacity, Animation, Curved Lines, Adaptive Scales, Fade, Fade Amount, Clustering, Location Totals, Max Top Flows, Dark Base Map

For detailed instructions, see [Flow Layer](https://github.com/keplergl/kepler.gl/blob/master/docs/user-guides/c-types-of-layers/q-flow-layer.md).

## 3D Tile Layer (experimental)

3D Tile layers render photogrammetry meshes, buildings, terrain and other 3D content served as OGC 3D Tiles or I3S tilesets. The layer streams and renders tiles based on the current viewport and camera position, loading detail on demand.

Supported providers:

* OGC 3D Tiles 1.0 / 1.1 (any `tileset.json` endpoint)
* Google Photorealistic 3D Tiles (requires a Google Maps API key)
* Cesium Ion (requires a Cesium Ion access token)
* ArcGIS I3S scene services

Example ArcGIS I3S tileset:

* San Francisco Buildings — <https://tiles.arcgis.com/tiles/z2tnIkrLQ2BRzr6P/arcgis/rest/services/SanFrancisco\\_Bldgs/SceneServer/layers/0>

Example Cesium Ion tilesets (require access token):

* Washington DC mesh — <https://assets.ion.cesium.com/57588/tileset.json>
* Melbourne point cloud — <https://assets.ion.cesium.com/43978/tileset.json>
* Mount St. Helens — <https://assets.cesium.com/33301/tileset.json>

Example generic OGC 3D Tiles:

* Royal Exhibition Building (point cloud) — <https://raw.githubusercontent.com/visgl/deck.gl-data/master/3d-tiles/RoyalExhibitionBuilding/tileset.json>

For step-by-step instructions, see [3D Tile Layer — How to add](https://github.com/keplergl/kepler.gl/blob/master/docs/user-guides/c-types-of-layers/p-3d-tile-layer.md).

[Back to table of contents](/docs/user-guides)


# Point

![Point layer](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/image34.png)

Point layers draw points for a given event or object.

**Layer Attributes**

* Basic
  * Columns:
    * Latitude
    * Longitude
    * Altitude (optional)
* Fill
  * Enable fill - enabled by default
  * Single color / color based on
  * Color scale
  * Opacity
* Outline
  * Enable outline
  * Single color / color based on
  * Color scale
  * Stroke width
* Radius
  * Single radius / radius based on
  * Fixed radius to meter
* Text,
  * Font Size
  * Font Color
  * Text Anchor

[Back to table of contents](/docs/user-guides)


# S2 Layer

![S2 Layer](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/l-s2.png)

To use S2 layer, you need to assign a column containing S2 tokens.

### Naming Convention

Kepler.gl **auto generates** S2 layer from column named `s2` or `s2_token`

### Simple Dataset

| token    |        value        |
| -------- | :-----------------: |
| 80858004 |  0.5979242952642347 |
| 8085800c |  0.5446256069712141 |
| 80858014 |  0.1187171597109975 |
| 8085801c |  0.2859146314037557 |
| 80858024 | 0.19549012367504126 |
| 80858034 |  0.3373452974230604 |
| 8085803c |  0.9218176408795662 |
| 80858044 | 0.23470692356446143 |
| 8085804c |  0.1580509670379684 |
| 80858054 | 0.15992745628743954 |

[Back to table of contents](/docs/user-guides)


# Icon

![Icon layer](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/image33.png)

Icon layers are a type of point layer. They allow you to differentiate between points by assigning icons to points based on a field. For example, you might use icons to differentiate between types of venues and points of interest.

To see the icon menu, create a new icon layer and click how to draw an icon layer:

![How to Draw Icon Layer](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/image38.png)

[Back to table of contents](/docs/user-guides)


# Line

![Line layer](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/image3.png)

Line layers are the 2D version of arc layers. Both draw a line between two points to represent distance, but in a line layer, the drawing lies flat on the map.

[Back to table of contents](/docs/user-guides)


# Cluster

![Cluster layer](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/image46.png)

Cluster layers visualize aggregated data based on a geospatial radius.

[Back to table of contents](/docs/user-guides)


# Polygon

Polygon layer can display all geometry types defined by [RFC 7946 (GeoJSON)](https://tools.ietf.org/html/rfc7946): `Point`, `LineString`, `Polygon`, `MultiPoint`, `MultiLineString`, `MultiPolygon`.

You can load a GeoJSON file (with a single [`Feature`](https://tools.ietf.org/html/rfc7946#section-3.2) or a [`FeatureCollection`](https://tools.ietf.org/html/rfc7946#section-3.3)) or a GeoArrow file.

![GeoJSON layer](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/image20.png)

![Polygon layer - contour](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/layers-polygon-contour.png)

![Polygon geoJSON layer](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/image7.png)

![Polygon layer - buildings](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/layers-polygon-buildings.png)

A path GeoJSON layer can display data like trip routes or contours. Stroke color can be set with a numerical field.

A polygon GeoJSON layer is essentially a [choropleth](https://en.wikipedia.org/wiki/Choropleth_map) layer and works best for rendering geofences. Fill color or height can be set with a numerical field. For example, it can display population by census tracts.

To add a polygon layer, your dataset must contain geometry data.

[Back to table of contents](/docs/user-guides)


# Hexbin

![Hexbin layer](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/layers-hexbin.png)

Hexbin layers are similar to grid layers. They display distributions of aggregate metrics such as point count within each hexbin, average/max/min/median/sum of a numerical field, or mode/unique count of a string field. Both the color and height dimensions can encode data. Users can adjust the hexagon radius and the space between hexbins.

[Back to table of contents](/docs/user-guides)


# Grid

![Grid layer](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/image21.png) ![3D Grid layer](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/image17.png)

Grids layers are similar to heatmaps. They show the density of points. They provide visual discrepancy in a map where multiple heatmap-style layers are present.

[Back to table of contents](/docs/user-guides)


# H3

![H3 layer](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/layers-h3.png)

H3 layers visualize spatial data using [H3 Hexagonal Hierarchical Spatial Index](https://eng.uber.com/h3/).

To use H3 layer, you need a `hex_id` or `hexagon_id` in your dataset, which can be generated using [h3-js](https://github.com/uber/h3-js) from latitude, longitude and resolution.

## Naming Convention

kepler.gl **auto generates** H3 layer from column: `hex_id`, `hexagon_id`

## Sample dataset:

hex\_id | value | |----------|:------:| 89283082c2fffff | 64 | 8928308288fffff | 73 | 89283082c07ffff | 65 | 89283082817ffff | 74 | 89283082c3bffff | 66 | 89283082883ffff | 76 |

[Back to table of contents](/docs/user-guides)


# Heatmap

![Heatmap layer](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/layers-heat-map.png)

Heatmap layers describe the intensity of data at geographical points through a colored overlap. The intensity can be weighted by a numerical field.

[Back to table of contents](/docs/user-guides)


# Arc

![Arc layer](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/image37.png)

Arc layers draw an arc between two points. They’re useful for visualizing the distance between two points as well as comparing distances in 3D. Note that arc layers don’t show routes between points, but simply the distance between the two points. The tallest arc represents the greatest distance.

To draw arcs, your dataset must contain the latitude and longitude of two different points for each arc.

[Back to table of contents](/docs/user-guides)


# Trip layer

Trip layer can display animated path.

![Trip layer](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/k-trip.gif)

### How to use trip layer to animate path

**Data format** Currently trip layer supports a special `geoJSON` format where the coordinate `linestring` has a 4th element denoting timestamp.

In order to animate the path, the `geoJSON` data needs to contain `LineString` in its features' geometry, and the coordinates in the `LineString` need to have 4 elements in the format of `[longitude, latitude, altitude, timestamp]`, with the last element being a timestamp. Valid timestamp formats include unix in seconds such as `1564184363` or in milliseconds such as `1564184363000`.

**Sample data**

```
{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {
        "vendor":  "A"
      },
      "geometry": {
        "type": "LineString",
        "coordinates": [
          [-74.20986, 40.81773, 0, 1564184363],
          [-74.20987, 40.81765, 0, 1564184396],
          [-74.20998, 40.81746, 0, 1564184409]
        ]
      }
    }
  ]
}
```

**Note** Support for more data formats such as csv will be added in future releases.

**Layer attributes**

* Color

  The path can be colored by an attribute from the properties.

  ![](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/k-trip-attribute-colors.png)
* Stroke Width

  Stroke width can be set by an attribute from the properties.
* Trail Length

  Trail length determines how long it takes for a path to completely fade out in seconds. This can be adjusted using the slider. Short trail length retains few historical locations while long trail length retain more and show a longer tail.
* Animation speed

  Animation speed can be adjusted using the animation control at the bottom.

**When there are multiple layers**

* Multiple trip layers When you add multiple trip layers, the time range from all the layers will be combined and the animation control will span the entire time range of those layers.
* Multiple layers containing trip layer and other layers Other static layers can be added besides the trip layers. Upon hiding the trip layer, its animation control will also hide, giving place to the filter control.

**Export**

To export an animated map, you can use a screen recording or gif capture tool. You can also export the map as an interactive HTML to open in the browser.

[Back to table of contents](/docs/user-guides)


# Vector Tile Layer

Follow these steps to add a Vector Tile layer (MVT or pmtiles):

1. Open Add Data → Tilesets.
2. Select Vector Tile tileset type.
3. Enter a tileset URL:
   * Mapbox Vector Tiles (MVT) template, e.g. `https://api.mapbox.com/v4/mapbox.mapbox-streets-v8/{z}/{x}/{y}.mvt?access_token=YOUR_TOKEN`
   * pmtiles URL, e.g. `https://your-cdn/filename.pmtiles`
4. Click Add. A new Vector Tile layer will appear in the Layers panel.
5. Style the layer (color, stroke, height, dynamic color) in the Layers panel.

Notes:

* Use Vector Tile layer for vector data in MVT/pmtiles formats. For raster pmtiles or COG/STAC imagery, use Raster Tile layer.

Example Vector Tile sources:

* US population — <https://4sq-studio-public.s3.us-west-2.amazonaws.com/vector-tile/cb\\_v2/{z}/{x}/{y}.pbf>
* New Zealand buildings — <https://r2-public.protomaps.com/protomaps-sample-datasets/nz-buildings-v3.pmtiles>
* US Zip Codes - <https://r2-public.protomaps.com/protomaps-sample-datasets/cb\\_2018\\_us\\_zcta510\\_500k.pmtiles>
* Railways — <https://4sq-studio-public.s3.us-west-2.amazonaws.com/pmtiles-test/161727fe-7952-4e57-aa05-850b3086b0b2.pmtiles>

[Back to layer overview](/docs/user-guides/c-types-of-layers)


# Raster Tile layer

## Raster Tile Layer — How to add (experimental)

Use Raster Tile layer to visualize satellite/aerial imagery from raster pmtiles or COGs via STAC metadata.

1. Open Add Data → Tilesets.
2. Select Raster Tile tileset type.
3. Paste URL to the tileset:
   * pmtiles (raster format): provide a direct HTTPS URL to a .pmtiles file containing raster imagery. Raster pmtiles don't require dedicated raster tile servers, unless you want to use elevation meshes.
   * COG (.tif): provide a direct HTTPS URL to a Cloud Optimized GeoTIFF. The public [TiTiler](https://titiler.xyz) service is used automatically for metadata and tile serving. Elevation is not supported in this mode.
   * STAC Item/Collection (COGs): provide a HTTPS URL to a STAC Item or Collection. Both STAC 1.0.x (with EO + Raster extensions) and STAC 1.1.0+ (with core `bands`) are supported. For this option you need to provide a [compatible raster tile server](https://github.com/igorDykhta/kepler-raster-server).
4. Click Add.
5. Style band selection and opacity as needed in Layers panel.

Important notes for COGs via STAC:

* **STAC 1.0.x:** The STAC Item/Collection must include EO and Raster extensions with `eo:bands` and `raster:bands`.
* **STAC 1.1.0+:** Items using the core `bands` field (where band metadata lives directly on each asset instead of separate `eo:bands`/`raster:bands` extensions) are also supported. Each band object should include `data_type` and optionally `eo:common_name` and `statistics`.
* Both formats can coexist within a single STAC item (some assets using legacy extensions, others using core `bands`).
* COG assets must be publicly accessible over HTTPS.
* You must run your own raster tile server (e.g., TiTiler). Example implementation that supports collections and elevations: [kepler-raster-server](https://github.com/igorDykhta/kepler-raster-server).

## Loading standalone COG (.tif) files

You can load a Cloud Optimized GeoTIFF directly by pasting its URL (ending in `.tif` or `.tiff`) into the "Tileset metadata URL" field. When a COG URL is detected, kepler.gl automatically fetches STAC metadata from the public [TiTiler](https://titiler.xyz) service (`/cog/stac` endpoint) and sets `https://titiler.xyz` as the raster tile server.

* **No self-hosted server required** — the public TiTiler instance handles both metadata and tile serving.
* **Elevation is not available** when using the public TiTiler service.
* The COG file must be publicly accessible over HTTPS.
* If the "Raster tile servers" field is empty when you paste a `.tif` URL, it will be auto-filled with `https://titiler.xyz`.

## Elevation

To enable elevation rendering, you must provide one or more compatible raster tile servers when adding the tileset. Enter them in the "Raster tile servers" field of the Add Tileset form.

* For STAC Items/Collections: compatible raster tile servers are required.
* For raster .pmtiles: raster tile servers are optional for imagery, but required if you plan to use elevation.
* The server must expose COGs as XYZ tiles and support elevation/DEM tiles. Example implementation: [kepler-raster-server](https://github.com/igorDykhta/kepler-raster-server) (TiTiler-based).

Example Raster .pmtiles:

* Swiss historical - <https://public-bucket-for-tests.s3.us-east-1.amazonaws.com/historic-swis-18xx.pmtiles>

Example STAC Items:

* Bangladesh rivers — <https://4sq-studio-public.s3.us-west-2.amazonaws.com/sdk/examples/sample-data/raster/planet-skysat-opendata.json>
* Antarctica ice — <https://4sq-studio-public.s3.us-west-2.amazonaws.com/sdk/examples/sample-data/raster/sentinel-2-l2a.json>
* Kiribati island — <https://4sq-studio-public.s3.us-west-2.amazonaws.com/sdk/examples/sample-data/raster/stac-example.json>

Example STAC Collections:

* sentinel-2-l1c — <https://earth-search.aws.element84.com/v1/collections/sentinel-2-l1c>
* modis-09A1-061 — <https://planetarycomputer.microsoft.com/api/stac/v1/collections/modis-09A1-061>
* landsat-c2-l1 — <https://planetarycomputer.microsoft.com/api/stac/v1/collections/landsat-c2-l1>

[Back to layer overview](/docs/user-guides/c-types-of-layers)


# WMS layer

Use WMS Layer to render imagery from OGC Web Map Service (WMS) endpoints.

1. Open Add Data → Tilesets.
2. Select WMS tileset type.
3. Enter the WMS service URL (GetCapabilities endpoint or base service URL).
4. Click Add. A new WMS layer will appear in the Layers panel.
5. In the Layers panel you can select a named layer from the service.

Notes:

* Feature info on click is supported for queryable layers (`queryable=true`).

Example WMS services:

* <https://ows.terrestris.de/osm/service>
* <https://opengeo.ncep.noaa.gov/geoserver/conus/conus\\_cref\\_qcd/ows>
* <https://gibs.earthdata.nasa.gov/wms/epsg4326/best/wms.cgi>
* <https://geo.stadt-muenster.de/mapserv/starkregen\\_serv>

[Back to layer overview](/docs/user-guides/c-types-of-layers)


# Layer Attributes

| Layer Attribute                    | Description                                                                                                                                            | Available in                                   |
| ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------- |
| Color/Color based on               | Choose the color of your layer or assign color based on a field from your dataset(s).                                                                  | All layers                                     |
| High-precision rendering           | Activate high-precision rendering when zooming in closely on a layer. High-precision rendering sometimes results in a performance cost.                | Point, Arc, Line, Icon, GeoJSON, Hexagon, Grid |
| Radius/Radius based on             | Change the radius of points or assign radius values based on a field from your dataset(s).                                                             | Point, Icon, GeoJSON                           |
| Opacity                            | Change the transparency of a layer. 1 = opaque, 0 = invisible.                                                                                         | All layers                                     |
| Cluster size                       | Change the granularity of clusters. The lower the numerical value, the smaller the geospatial radius that will be used to aggregate clusters.          | Cluster                                        |
| Radius range                       | Set a lower and upper threshold for projected radius size.                                                                                             | Point, Icon, Geojson, Cluster                  |
| Stroke width/stroke width based on | Change the thickness of lines and arcs, or assign a width based on a field from your dataset(s).                                                       | Arc, line, Geojson                             |
| Stroke width range                 | Set a lower and upper threshold for projected stroke width.                                                                                            | Arc, Line, Geojson                             |
| Grid size                          | Change the number of square kilometers covered by each grid square.                                                                                    | Grid                                           |
| Color Palette                      | Choose from multiple, predefined or customized color palettes to apply to your layer. Predefined palettes are either Uber or ColorBrewer colors.       | All layers                                     |
| Color Scale                        | Choose either a quantile or quantized color scale. A quantile color scale is determined by rank, while a quantized color scale is determined by value. | All layers                                     |
| Height based on                    | Assign grid square height based on a field from your dataset.                                                                                          | Grid, Hexagon, S2                              |
| Filter by count percentile         | Increase or decrease the number of grid squares by choosing a range of percentiles to display.                                                         | Grid, Hexagon                                  |
| Coverage                           | Change what portion of each grid cell is covered by a color square.                                                                                    | Grid, Hexagon                                  |
| Height Scale                       | Change the height of the grid squares, hexagons or S2 when in 3D mode.                                                                                 | Grid, Hexagon, S2                              |
| Stroked                            | When activated, draws outlines around geoshapes.                                                                                                       | GeoJSON, Point                                 |
| Filled                             | When activated, geo shapes are filled in with colors.                                                                                                  | GeoJSON                                        |
| Extruded                           | In 3D mode, assign polygon height values based on some value from your dataset.                                                                        | GeoJSON                                        |
| Wireframe                          | Create outlines around extruded polygons.                                                                                                              | GeoJSON                                        |
| Stroke or radius based on          | Control the radius/thickness of GeoJSON line and point features.                                                                                       | GeoJSON                                        |

[Back to table of contents](/docs/user-guides)


# Color Palettes

Color palettes provide both predefined and customized options and can be applied to either fill or stroke. Predefined palettes comes in diverging, sequential and qualitative types.

To choose a palette:

1. Expand layer pane and click on the color bar from either filled color or stroke color section. Click on the three dots to select the field to color by.

![expand](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/l-color-attributes-0.png)

2. To choose a custom palette, toggle on custom button. Click on each color to pick new color either by clicking on the color picker or inputting HEX/RGB values. Colors steps can be added, removed or shuffled.

![toggle](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/l-color-attributes-1.png) ![toggle](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/l-color-attributes-2.png)

3. Your color is applied to your map as soon as you select the predefined palette or confirm the choices of customized colors.

![toggle](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/l-color-attributes-3.png)

[Back to table of contents](/docs/user-guides)


# Filters

Add filters to your map to limit the data that is displayed. Filters must be based on the columns in your dataset.

To add a filter:

1. Select Filters from the right navigation bar. ![select filters](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/image1.png)
2. The Filters panel displays the list of existing filters, color-coded by dataset. To create a new filter, Click **Add Filter**.
3. Choose a dataset, and then a field on which to filter your data. Filter values are defined by field data type (number, string, timestamp, etc.). ![choose a dataset](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/image29.png)
4. Your filter is applied to your map as soon as you specify the field and value.
5. Delete a filter anytime by clicking the **trashcan** to the right of the filter you wish to delete.

**Note**: filters apply to all layers in the same dataset on your map.

[Back to table of contents](/docs/user-guides)


# Map Styles

* [Base Map Styles](#base-map-styles)
* [Toggle Map Layers](#toggle-map-layers)
  * [Map Layers](#map-layers)
  * [Layer Order](#layer-order)
* [Custom Map Styles](#custom-map-styles)

![map styles](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/f-map-styles-0.png)

kepler.gl provide a set of [Mapbox](https://www.mapbox.com) basemap styles as background map, including 3D buildings! You can also add your own custom map style using the Mapbox style link.

## Base Map Styles

Open the **Base Map panel** to select from a list of default map styles.

![base map panel](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/f-map-styles-1.png)

Open the **base map style** drop down menu to change map color scheme and imagery. Options include:

* **Dark**: dark base map with light-colored text.
* **Light**: light base map with dark-colored text.

## Toggle Map Layers

![map layers](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/f-map-styles-2.png)

#### Map Layers

Hide and show water, buildings, roads, and more. Options include:

* **Labels**: shows labels for cities, neighborhoods, and so on.
* **Roads**: displays a translucent layer of road lines.
* **Borders**: shows state and continent borders.
* **Buildings**: shows building footprints.
* **Water**: displays bodies of water.
* **Land**: Shows parks, mountains, and other landscape features.
* **3d Building**: Shows 3D buildings on the map. 3D buildings are only visible in the 3D map view. Resolution automatically updates based on current map zoom level. Use the input below to edit 3D building color.

![3d building](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/f-map-styles-3.png)

#### Layer Order

To control the order in which map imagery layers are displayed, toggle the move to top icon:

![move to top icon](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/f-map-styles-4.png).

**TIP**: Move labels to the top on maps with colored layers to keep the labels from being concealed.

![Examples of ordered layers](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/f-map-styles-5.png)

## Custom Map Styles

![Add Custom Mapbox Styles button](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/image45.png)

To add a custom base map style, click the add map style button to open the custom map style modal, paste in the mapbox [style Url](https://www.mapbox.com/help/studio-manual-publish/#style-url). Note that you need to paste in your [mapbox access token](https://www.mapbox.com/account/) if your style is not [published](https://www.mapbox.com/help/studio-manual-publish/#style-url).

![Add Custom Mapbox Styles popup](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/image13.png)

[Back to table of contents](/docs/user-guides)


# Interactions

* [Tooltips](#tooltips)
* [Brushing](#brushing)
* [Display Coordinates](#display-coordinates)

You can toggle customization options on your map, including tooltips, brush highlighting, map imagery (water, parks, etc.), and more.

![Interaction menu](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/g-interactions-0.png)

To toggle customization options on your map:

1. Open the Interactions menu by clicking the Interactions icon:
2. Click the switch next to the options you wish to activate/deactivate.

There are three types of interactions to choose from: **Tooltip**, **Brushing** and **Coordinate**. Note that only one of tooltip and brushing can be on at a time.

## Tooltips

tooltip displays metrics when hovering over a data point. You can choose which fields are displayed from the tooltip config menu.

![tooltips](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/image25.png)

* **Image** Image can be added to tooltip. If field name contains `<img>` and the field content contains `http` url

| id | `<img>-tooltip`                      |
| -- | ------------------------------------ |
| 1  | `http://my-image.com/my-image-0.png` |
| 2  | `http://my-image.com/my-image-1.png` |

* **Web link** Tooltip can be a clickable weblink. To add a web link as tooltip, add a url that starts with `http://` to the field content.

![tooltips](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/g-interactions-1.png)

Tip: click a point to pin the tooltip info to the map. To unpin the tooltip, press the blue pin icon.

![pin/unpin tooltip](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/image15.png)

## Brushing

* **Brush**: Brush allows you to highlight areas with the cursor. When brush is turned on, all layers darken. Only the portion you hover over with the cursor is illuminated. Brush works well with arc layers in particular.

![brush](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/image12.png)

[Back to table of contents](/docs/user-guides)

## Display Coordinates

![coordinate](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/g-interactions-2.png)

When then on coordinate, a panel contains latitude and longitude will follow your mouse

[Back to table of contents](/docs/user-guides)


# Map Settings

* [Split Maps](#split-maps)
* [View Maps in 3D](#view-maps-in-3d)
* [Globe View](#globe-view)
* [Display Legend](#display-legend)

![Map Settings](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/m-map-settings-0.png)

## Split Maps

You can display a side-by-side comparison of the same map area with different layers with the Split Map functionality.

![Split Maps](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/image36.png)

1. Enable this by clicking the Split Map icon in the top right corner of your map:

![Split Maps Icon](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/m-map-settings-split.png)

2. Toggle the layers visible in each map with the layer icon in the top right corner of each map.

![Split Maps Icon](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/m-map-settings-layer.png)

![Toggle Layers](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/image35.png)

3. Zoom in and out on each map and the other will automatically mimic.

## View Maps in 3D

View your map in 3D by clicking the 3D icon in the top right corner of your map

![View Maps in 3D](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/m-map-settings-3d.png)

* **drag**: pan
* **cmd + drag** (mac) or **ctrl + drag** (win): rotate

![Map in 3D](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/f-map-styles-7.png)

## Globe View

Switch from the flat (web-mercator) map to a 3D globe projection to view your data wrapped onto a sphere. Toggle Globe view from the map view mode control in the top right corner of the map.

* **drag**: rotate the globe
* **scroll / pinch**: zoom in and out

Globe view is well suited to global-scale datasets and flows, and to presentation-style maps. It is built on deck.gl's globe projection and is still evolving, so a number of layers and interactions behave differently than in the flat map.

### Enabling globe view

The globe view option is enabled by default. Application developers can hide the globe entry in the map view mode control (leaving only Top/3D) by setting `enableGlobeView: false` in the application configuration:

```js
import KeplerGl from '@kepler.gl/components';
import {initApplicationConfig} from '@kepler.gl/utils';

initApplicationConfig({enableGlobeView: false});
```

### Camera and zoom constraints

To keep the basemap and interactions coherent, globe view applies a few constraints that do not exist in the flat map:

* **Zoom range is limited** (roughly zoom `2`–`12`). You can pull the globe further back than the flat map so the whole planet fits on screen, but **zooming in past zoom level `12` is currently disabled.** This cap is in place because, past that level in the current deck.gl 9.x globe projection, the vector basemap tileset (Mapbox Streets vector tiles) stops loading and renders as empty rectangles, and the camera becomes unstable — it drifts while panning and zooming, and zoom-to-cursor becomes inaccurate. Capping the zoom keeps the basemap and interactions coherent until the underlying tile/controller issue is resolved upstream. Satellite/raster basemaps hold up better at closer zoom, so the cap may be relaxed as globe support matures.
* **The camera can't be centered on the poles.** The center latitude is constrained to a band around the equator (about ±75°) so you can't stare straight down at a pole.
* **Reset bearing/pitch** recenters the view toward the equator.

### Supported layers

The following layers render correctly in globe view:

* Point
* Arc
* Line
* Grid
* Hexbin (Hexagon)
* H3 (Hexagon ID)
* Cluster
* Icon
* GeoJSON / Polygon
* 3D / Point (elevation)
* Trip
* Vector Tile
* Raster Tile
* Hex Tile
* Heatmap (see caveat below)

> **Heatmap in globe view.** The heatmap layer is supported in globe view, but works differently than on the flat map. Because a heatmap cannot be draped directly onto the sphere, the density is computed offscreen for the current data/view bounds and projected back onto the globe. As a result the effective radius adapts with zoom, and very large `Radius` values or extreme zoom levels can look different than on the flat map.

### Unsupported layers

These layers are hidden or disabled in globe view because their geometry does not project onto the sphere correctly:

* **Flow** — flow arrows are flat quads in the equatorial plane and collapse to nothing when viewed edge-on on the globe.
* **S2**
* **3D Tiles** (Tile3D)

If a layer is unsupported, kepler.gl will indicate that it is not available in globe view and keep it hidden until you return to the flat map.

### Globe appearance settings

When globe view is enabled, the **Base map** side panel shows a set of globe-specific appearance controls (in addition to the usual base map style picker). Each row has a visibility toggle, and some rows add a color swatch or a slider:

* **Atmosphere** — the glowing halo rendered around the globe. Turning it off also hides its sub-settings:
  * **Day/Night (terminator)** — shades the night side of the globe. The slider controls the shading opacity.
  * **Sun azimuth** — direction of the sun used for the day/night shading. The slider sets the angle (0–360°).
* **Base map** — the reference basemap draped on the sphere. Turning it off also hides its sub-layers:
  * **Labels** — place/road labels, with a color picker.
  * **Admin borders** — administrative boundary lines, with a color picker.
  * **Water** — water fill, with a color picker.
* **Surface** — the color of the globe's land surface.
* **Background** — the color of the empty space rendered around the globe. This color is also used as the background in image and video export.

### Known issues and limitations

* **Basemap breakdown at high zoom.** At high globe zoom the mapbox vector basemap tileset can stop loading and render as empty rectangles. Zoom is capped to avoid this. Satellite/raster basemaps generally hold up better at closer zoom.
* **Panning/zoom drift at high zoom.** Near the zoom cap the camera may drift while interacting. This is the primary reason for the zoom cap.
* **Zoom-to-cursor behaves differently for zoom-in vs zoom-out.** Zooming in keeps the point under the cursor fixed. Zooming out does not anchor to the cursor (exact anchoring is unstable near the globe's edge and tends to drift toward the poles); instead it zooms out while gently recentering toward the cursor location.
* **Arcs and lines on the far side.** Depending on depth handling, geometry on the back of the globe may be partially visible through the sphere.
* **Basemap differences.** Mapbox and MapLibre basemaps can look different in globe mode; some basemap styles are better tuned for the sphere than others.

> **Combining globe with swipe, video export, and effects:** Globe view, [swipe/split comparison](#split-maps), [video export](/docs/user-guides/k-save-and-export#export-video), and post-processing [effects](https://github.com/keplergl/kepler.gl/blob/master/docs/user-guides/effects.md) each work on their own, but their combinations (for example globe + swipe + video recording with effects active at the same time) have **limited support** and may not render or export exactly as expected. When you hit an issue, try disabling one of the features (e.g. turn off effects, exit swipe mode, or switch back to the flat map) before recording. Support for these combinations is expected to improve as globe support matures.

These limitations stem from the underlying deck.gl globe projection and are expected to improve as that support matures.

## Display Legend

Display a legend for visible layers on the map.

![Display Legend](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/m-map-settings-legend.png)

![Sample Legend](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/image14.png)

[Back to table of contents](/docs/user-guides)


# Time Playback

Follow these steps to create a playback video of an event:

1. Add a filter based on a time-related field, like timestamp. For GeoJson, property field should contain a timestamp entry.
2. The playback window will appear on the bottom of the map. The bars are distribution graphs of all data points by time. Select the desired rolling time window:

![select filters](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/h-playback-1.png)

3. Press play to start the video. Click on the speed value and select/input your desired value *1x*, *2x*, *4x* on the top right to change the playback speed.

![change speed](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/h-playback-2.gif)

4. Choose custom y axis. You can click **Select Y Axis** to change the default distribution graph to a timeseries of the selected column. An example use of this function is to show a distance vs. time graph of a given trip.

![custom y axis](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/h-playback-3.png)

## Zoom & precision controls

The enlarged timeline now lets you stay focused on the portion that matters:

* Use the mouse wheel to resize the window under the cursor, and pinch (or hold <kbd>Ctrl</kbd> on Windows/Linux or <kbd>⌘</kbd> on macOS while scrolling) to zoom the full timeline.
* A lightweight "Showing" bar appears whenever the full range is narrowed—click **Reset** to return to the original domain.
* Hold <kbd>Ctrl</kbd> (Windows/Linux) or <kbd>⌘</kbd> (macOS) and press the arrow keys to pan left/right, with <kbd>Shift</kbd> for bigger steps.

[Back to table of contents](/docs/user-guides)


# Save and Export

![Save and Export](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/k-save-and-export-1.png)

kepler.gl is a client-side only application. In the demo app, the data you uploaded stays in your browser. kepler.gl does not send or store any user data to any backends. This rule poses an limitation on how you can save and share your maps.

However, in the demo app, you can:

* [Export map as an image](#export-image).
* [Export filtered or unfiltered data as a csv](#export-data).
* [Export Map](#export-map)
* [Export Video](#export-video)
* [Share Public URL (Dropbox)](#export-dropbox)

## [Export Image](#export-image)

![Export Image](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/k-save-and-export-2.png)

You can export the current map as an image. The export window will use the current map viewport, and the preview will show the entire exported map area. To adjust the viewport, you will have to close the export dialog. You can choose different export ratios or resolutions, and also to add a map legend.

## [Export Data](#export-data)

![Export Data](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/k-save-and-export-3.png)

You can export map data as a csv file, with the option to export ONLY the filtered data or the entire dataset.

## [Export Map](#export-map)

You can export the current map using two different formats. The **Export Map** window provides two options:

* HTML: create a single html file loads and renders your current map.
* JSON: create a json file with your current map config and data.

### [Export Map as HTML](#export-html-map)

![Export Map as HTML](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/k-save-and-export-4.png)

To save and export your current map as HTML file, click on **Export Map** and subsequently on **Export**. When prompted provide your own mapbox token to be used in the newly generated file. If you don't provide a Mapbox Token, Kepler.gl will use a default one which can expire at anytime without any communication and therefore break your existing map.

#### How to update an exported map token

In order to edit the mapbox token in your html file you simply need to perform the following steps:

1. [Create a new mapbox token](https://docs.mapbox.com/help/how-mapbox-works/access-tokens/) or use your existing one.
2. Open the kepler.gl.map file with your favorite text editor.
3. Locate the following line in the exported file **kepler.gl.html**:

```javascript
  /**
   * Provide your MapBox Token
   **/
  const MAPBOX_TOKEN = 'CURRENT_TOKEN';
```

4. Replace the current value with a new valid token. The code should now look like the following:

```javascript
  /**
   * Provide your MapBox Token
   **/
  const MAPBOX_TOKEN = 'pk.eyJ1IjoidWJlcmRh...';
```

### [Export Map as JSON](#export-json-map)

![Export Map as JSON](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/k-save-and-export-5.png)

You can export the current map as a `json` file. This is useful when you are running your own kepler.gl application and want to load your map programmatically. The JSON file includes:

* dataset: processed data used to render your map
* config: layer, filter, map style and interaction settings. The map config includes the current layer, filter, map style and interaction settings.

**Note:** kepler.gl map config is coupled with loaded datasets. The **`dataId`** key is used to bind layers, filters and tooltip settings to a specific dataset. If you try to upload a configuration with a dataset in your own kepler.gl app, you also need to make sure your dataset **`id`** matches the **`dataId`** in the config.

## [Export Video](#export-video)

You can record an animated video of your map and download it directly from the browser. Open the export video dialog from the toolbar by clicking **Export Video**. The dialog has two tabs — **Animation** and **Settings** — along with a live map preview.

### Animation tab

The Animation tab controls the motion and timing of the recording.

| Setting      | Description                                                                                                                                                                                                                                                                    |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Duration** | Length of the video, from 0.1 s up to 10 s. Drag the slider or type a value. Longer recordings produce larger files.                                                                                                                                                           |
| **Camera**   | An optional camera animation applied during the recording. Available presets: **None** (static camera), **Orbit (90°)**, **Orbit (180°)**, **Orbit (360°)**, **Zoom Out**, and **Zoom In**. When set to *None*, the camera stays exactly where you position it in the preview. |

### Settings tab

The Settings tab controls the output file format and quality.

| Setting        | Description                                                                                                                                                                                                                                |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **File Name**  | Base name for the downloaded file. Defaults to `kepler.gl`.                                                                                                                                                                                |
| **Media Type** | Output format: **WebM Video** (default, small file size, supported by most browsers), **GIF** (widely compatible but larger), **PNG Sequence** (lossless frame-by-frame images), or **JPEG Sequence** (compressed frame-by-frame images).  |
| **Ratio**      | Aspect ratio of the output: **16:9** (widescreen) or **4:3** (standard).                                                                                                                                                                   |
| **Quality**    | Resolution of the output. Options depend on the selected aspect ratio. For 16:9: Good (540p), High (720p), Highest (1080p). For 4:3: Good (480p), High (960p), Highest (1440p). Higher resolutions produce sharper video but larger files. |
| **File Size**  | An estimated file size based on the current duration, resolution, and media type.                                                                                                                                                          |

### Preview and recording

The live preview in the dialog shows exactly what will be recorded, including all visible layers, active effects (brightness, fog, light & shadow, etc.), and the base map. You can pan, zoom, and tilt the map in the preview to set the starting camera position.

* **Play (▶)** — Preview the animation (camera movement, filter playback) without recording.
* **Stop (■)** — Stop a running preview or recording.
* **Render** — Start recording. The map plays through the configured animation and duration, then the browser downloads the resulting file automatically.

### Animated filters and trips

If your map has time-range filters in the *enlarged* (time-slider) view or filters synced with the layer timeline, the video recorder will animate them over the recording duration. Trip layers similarly animate their paths. The animation window mode of each filter (free, incremental, point, or interval) is respected during recording.

### Tips

* Use **WebM** format for the smallest file sizes and fastest rendering. Switch to **GIF** only when you need universal compatibility (e.g. embedding in documents that don't support video).
* For the sharpest results, choose the **Highest** quality setting, but be aware that 1080p or 1440p recordings take longer and produce larger files.
* Position your camera in the preview *before* clicking Render. If you selected a camera preset like *Orbit (360°)*, the orbit starts from whatever position you set.
* All active [effects](https://github.com/keplergl/kepler.gl/blob/master/docs/user-guides/effects.md) (post-processing filters, fog, lighting) are included in the recording.

> **Limited support for feature combinations:** [Globe view](/docs/user-guides/m-map-settings#globe-view), [swipe/split comparison](/docs/user-guides/m-map-settings#split-maps), video export, and post-processing [effects](https://github.com/keplergl/kepler.gl/blob/master/docs/user-guides/effects.md) each work on their own, but combining several at once (for example recording a video of a globe in swipe mode with effects active) has **limited support** and may not preview or export exactly as expected. If the preview looks wrong or the export fails, disable one of the features (turn off effects, exit swipe mode, or switch back to the flat map) and record again. Support for these combinations is expected to improve over time.

## [Share Public URL (Dropbox)](#export-dropbox)

![Export Map to Dropbox](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/k-save-and-export-5.png)

To export the current map into your Dropbox account, click on **Share Public Url** and select Dropbox as your cloud storage. Perform the authentication against Dropbox using your credentials. Once the authentication process is completed, click on **Upload** and Kepler.gl will push your current map onto your account.

At the end of the process Kepler.gl will automatically generate a permalink for your work you can share with other users.

[Back to table of contents](/docs/user-guides)


# FAQ


# API Reference

## Table of Contents

* [Overview](/docs/api-reference#overview)
* [Ecosystem](/docs/api-reference/ecosystem)
  * [Component](/docs/api-reference/ecosystem#component)
  * [Reducer and Forward Dispatcher](/docs/api-reference/ecosystem#reducer-and-forward-dispatcher)
  * [Actions and Updaters](/docs/api-reference/ecosystem#actions-and-updaters)
  * [Processors and Schema Manager](/docs/api-reference/ecosystem#processors-and-schema-manager)
* [Get Started](/docs/api-reference/get-started)
* Advanced Usage
  * [Using reducer plugin](/docs/api-reference/advanced-usages/reducer-plugin)
  * [Custom reducer initial state](/docs/api-reference/advanced-usages/custom-initial-state)
  * [Using updaters to modify kepler.gl state](/docs/api-reference/advanced-usages/using-updaters)
  * [Forward actions](/docs/api-reference/advanced-usages/forward-actions)
  * [Saving and loading maps with schema manager](/docs/api-reference/advanced-usages/saving-loading-w-schema)
  * [Replace UI component](/docs/api-reference/advanced-usages/replace-ui-component)
  * [Custom Mapbox Host](/docs/api-reference/advanced-usages/custom-mapbox-host)
  * [Custom Map Styles](https://github.com/keplergl/kepler.gl/tree/305edfcd70454f8d4d84b6be6d2bb4c349f99d3f/docs/api-reference/advanced-usages/custom-map-styles.md)
  * [Localization](/docs/api-reference/localization)
* API
  * [Components](/docs/api-reference/components)
  * [Reducers](broken://pages/-Me3P8YA3zR0Jt8l6IFB)
  * [Actions and Updaters](/docs/api-reference/actions/actions)
  * [Data Processor](/docs/api-reference/processors/processors)
  * [Schemas](/docs/api-reference/schemas)

## Overview

Kepler.gl is a **Redux-connected** component. You can embed kepler.gl in your App, which uses redux to manage its state. The basic implementation of kepler.gl reducer is simple. However, to make the most of it, it's recommended to have basic knowledge on:

* [React](https://reactjs.org/)
* [Redux](https://redux.js.org/) state container
* [React Redux connect](https://react-redux.js.org/)

To start out with kepler.gl, you simply need to add the Kepler.gl UI component and mount the Kepler.gl reducer. To give the user full access of all the functionalities of kepler.gl, this package also includes actions, schema managers and a set of utilities to load and save map data.


# ecosystem

### Ecosystem

The diagram below represents the data flow. Note that in most cases, you don't have to worry about action creators, forward dispatcher and state updaters, as they are handled under-the-hood by kepler.gl

![Data flow](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/api_data-flow.png)

### Component

The Kepler.gl component will call redux connect under the hood, and dispatch to the corresponding reducer instance.

To allow mounting of multiple instance of kepler.gl components in the same app, we implemented a local selector with forward dispatch system. The local selector will pass down the knowledge where the state of this instance lives, and the forward dispatch system will pass down a dispatch function that knows to dispatch action to the correct reducer instance. **Each kepler.gl component instance needs to have an unique id**.

Read more about [Component](/docs/api-reference/components).

### Reducer and Forward Dispatcher

![Forward Dispatcher](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/api_forward-dispatch.png)

The kepler.gl root reducer that user mounted in their app is in fact a wrapper reducer that stored the child state and update them based on forwarded actions. If an action is not a forwarded action, it pass down to all child reducers.

When a KeplerGl component instance is mounted with the id `foo`, the wrapper reducer will add a kepler.gl local state in the root state at key `foo`.

One of the biggest challenge of using local state is to dispatch actions that only modify a specific local state. For instance, if we have 2 kepler.gl components in our app, one with id `foo` other with id `bar`. Our keplerGl reducer is going to be `keplerGl: {foo: …, bar …}`. When foo dispatches an action, it only needs to update the state of foo, we need a way to decorate the action that the root reducer only pass it down to subreducer `foo`.

To solve this, kepler.gl has a forward dispatching system. It consists of a set of forward functions including `wrapTo`, `forwardTo` and `unwrap`. `wrapTo` wraps an action payload into an forward action by adding an address `_addr_` and a `_forward_` signature to its meta.

Each kepler.gl component receives a forward dispatcher as a prop, which dispatches a forwarded action to the root reducer. The root reducer will check if the given action has that address and if so, unwrap the action and pass it to the child reducer.

Read more about [Reducers](/docs/api-reference/reducers).

### Actions and Updaters

Actions in reducers are mapped to state transition functions. `UPDATE_MAP` is mapped to `updateMapUpdater`. An updater is the backbone of the redux reducer. It is a pure function that takes the previous state and an action, and returns the next state. `(oldState, action) => newState`. It describes how the state should transition upon receiving that action.

here is a snippet of the map state reducer in kepler.gl.

```js
/* Action Handlers */
const actionHandler = {
 [ActionTypes.FIT_BOUNDS]: fitBoundsUpdater,
 [ActionTypes.TOGGLE_PERSPECTIVE]: togglePerspectiveUpdater
};

/* Reducer */
export default handleActions(actionHandler, INITIAL_MAP_STATE);
```

This pattern allows a user to import a specific action updater in the app's root reducer and use it to directly modify kepler.gl’s state without dispatching the action. This will give user a lot of freedom to control over kepler.gl's state transition.

Read more about [Actions and Updaters](/docs/api-reference/actions).

### Processors and Schema Manager

![Processor and Schema](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/api_load-save.png)

Processors and schema manager are useful helpers to get data in and out of kepler.gl. You can use `processCsvData(csv)` and `processGeojson(geojson)` to parse csv or geoJson file and pass it to `addDataToMap()` action.

To save and reload the current map, you can call `KeplerGlSchema.save()` and pass it the instance state. It will return a json output containing map data and config. Pass this json file to `processKeplerglJSON()` and then `addDataToMap()` will reproduce the same map.

Read more about [Processors](/docs/api-reference/processors) and [Schema Manager](/docs/api-reference/schemas).


# Get Started

## Installation

Use Node v20 and above, older node versions have not been tested

```sh
npm install --save kepler.gl @kepler.gl/components @kepler.gl/reducers
```

## Get Mapbox Token

Kepler.gl is built on top of [Mapbox GL](https://www.mapbox.com). A mapbox account and an access token are needed to use kepler.gl in your app. Get a [Mapbox Access Token](https://www.mapbox.com/help/define-access-token/) at mapbox.com.

## Basic Usage

![Basic Usage](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/api_basic-usage.png)

### 0. Working Template

Check full example on [Github](https://github.com/keplergl/kepler.gl/tree/master/examples/get-started).

```js
import * as React from "react";
import ReactDOM from "react-dom/client";
import document from "global/document";

import { applyMiddleware, combineReducers, compose, createStore } from "redux";
import { connect, Provider } from "react-redux";

import keplerGlReducer, { enhanceReduxMiddleware } from "@kepler.gl/reducers";
import KeplerGl from "@kepler.gl/components";

import AutoSizer from "react-virtualized/dist/commonjs/AutoSizer";

const reducers = combineReducers({
  keplerGl: keplerGlReducer.initialState({
    uiState: {
      readOnly: false,
      currentModal: null,
    },
  }),
});

const middleWares = enhanceReduxMiddleware([
  // Add other middlewares here
]);

const enhancers = applyMiddleware(...middleWares);

const initialState = {};
const store = createStore(reducers, initialState, compose(enhancers));

const App = () => (
  <div
    style={{
      position: "absolute",
      top: "0px",
      left: "0px",
      width: "100%",
      height: "100%",
    }}
  >
    <AutoSizer>
      {({ height, width }) => (
        <KeplerGl
          mapboxApiAccessToken="xxx" // Replace with your mapbox token
          id="map"
          width={width}
          height={height}
        />
      )}
    </AutoSizer>
  </div>
);

const mapStateToProps = (state) => state;
const dispatchToProps = (dispatch) => ({ dispatch });
const ConnectedApp = connect(mapStateToProps, dispatchToProps)(App);
const Root = () => (
  <Provider store={store}>
    <ConnectedApp />
  </Provider>
);

export default Root;
```

### 1. Mount reducer

Kepler.gl uses [Redux](https://redux.js.org/) to manage its internal state, along with [react-palm](https://github.com/btford/react-palm) middleware to handle side effects. Mount kepler.gl reducer in your store, apply `taskMiddleware`.

```js
import keplerGlReducer from '@kepler.gl/reducers';
import {createStore, combineReducers, applyMiddleware} from 'redux';
import {taskMiddleware} from 'react-palm/tasks';

const reducer = combineReducers({
  // <-- mount kepler.gl reducer in your app
  keplerGl: keplerGlReducer,

  // Your other reducers here
  app: appReducer
});

// create store
const store = createStore(reducer, {}, applyMiddleware(taskMiddleware));
```

If you mount `keplerGlReducer` in another address instead of `keplerGl`, or it is not mounted at root of your reducer, you will need to specify the path to it when you mount the component with the `getState` prop.

### 2. Mount component

```js
import KeplerGl from '@kepler.gl/components';

const Map = props => (
  <KeplerGl
      id="foo"
      mapboxApiAccessToken={token}
      width={width}
      height={height}/>
);
```

### 3. Add data to map

In order to interact with a kepler.gl instance and add new data to it, you can dispatch the **`addDataToMap`** action from anywhere inside your app. It adds dataset(s) to a kepler.gl instance and updates the full configuration (mapState, mapStyle, visState).

Read more about [addDataToMap](/docs/api-reference/actions/actions#adddatatomap)

```js
import {addDataToMap} from '@kepler.gl/actions';

this.props.dispatch(
  addDataToMap({
    // datasets
    datasets: {
      info: {
        label: 'Sample Taxi Trips in New York City',
        id: 'test_trip_data'
      },
      data: sampleTripData
    },
    // option
    option: {
      centerMap: true,
      readOnly: false
    },
    // config
    config: {
      mapStyle: {styleType: 'light'}
    }
  })
);
```


# Advanced usages


# Saving and Loading Maps with Schema Manager

![Processor and Schema](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/api_load-save.png)

Kepler.gl provides a schema manager to save and load maps. It converts current map data and configuration into a smaller JSON blob. You can then load that JSON blob into an empty map by passing it to `addDataToMap`.

The reason kepler.gl provides a Schema manager is to make it easy for users to connect the kepler.gl client app to any database, saving map data / config and later load it back. With the schema manager, a map saved in an older version can still be parsed and loaded with the latest kepler.gl library.

### Save map

Pass the **instanceState** to `SchemaManager.save()`

* `SchemaManager.save()` will output a JSON blob including data and config.

Under the hood, `SchemaManager.save()` calls `SchemaManager.getDatasetToSave()` and `SchemaManager.getConfigToSave()`

* `SchemaManager.getDatasetToSave()` will output an array of dataset.
* `SchemaManager.getConfigToSave()` will output a JSON blob of the current config.

In the example below, `foo` is the id of the KeplerGl instance to be save.

```js
import KeplerGlSchema from '@kepler.gl/schemas';

const mapToSave = KeplerGlSchema.save(state.keplerGl.foo);
// mapToSave = {datasets: [], config: {}, info: {}};

const dataToSave = KeplerGlSchema.getDatasetToSave(state.keplerGl.foo);
// dataToSave = [{version: '', data: {id, label, color, allData, fields}}]

const configToSave = KeplerGlSchema.getConfigToSave(state.keplerGl.foo);
// configToSave = {version: '', config: {}}
```

### Load map

Pass saved data and config to `SchemaManager.load()`

* `SchemaManager.load()` will parsed saved config and data, apply version control, the output can then be passed to `addDataToMap` directly.

Under the hood, `SchemaManager.load()` calls `SchemaManager.parseSavedData()` and `SchemaManager.parseSavedConfig()`

* `SchemaManager.parseSavedData()` will output an array of parsed dataset.
* `SchemaManager.parseSavedConfig()` will output a JSON blob of the parsed config.

```js
import KeplerGlSchema from '@kepler.gl/schemas';
import {addDataToMap} from '@kepler.gl/actions';

const mapToLoad = KeplerGlSchema.load(savedDatasets, savedConfig);
// mapToLoad = {datasets: [], config: {}};

this.props.dispatch(addDataToMap(mapToLoad));
```

### Match config with another dataset

Often times, people want to keep a map config as template, then load it with different datasets. To match a config with a different dataset, you need to make sure `data.id` in the new dataset matches the old one.

```js
import KeplerGlSchema from '@kepler.gl/schemas';
import {addDataToMap} from '@kepler.gl/actions';

// save current map data and config
const {datasets, config} = KeplerGlSchema.save(state.keplerGl.foo);
// mapToLoad = {datasets: [], config: {}};

// receive some new data
const newData = someNewData;
// newData = [{rows, fields}]

// match id with old datasets
const newDatasets = newData.map((d, i) => ({
  version: datasets[i].version,
  data: {
    ...datasets[i].data,
    allData: d.rows,
    fields: d.fields
  }
}));

// load config with new datasets
const mapToLoad = KeplerGlSchema.load(newDatasets, config);

this.props.dispatch(addDataToMap(mapToLoad));
```


# Replace UI Component with Component Dependency Injection

To allow customize a child component, the library author usually has to pass the child component down as a prop from top of the component tree. This approach will work for component that are relatively small, but it won’t scale for kepler.gl because it has hundreds of child components. To give user the flexibility to render certain component differently. Kepler.gl has a dependency injection system that allows user to inject custom components to kepler.gl UI replacing the default ones at bootstrap time.

All you need to do is to create a component factory for the one you wish to replace, import the original component factory and call `injectComponents` at where `KeplerGl` is mounted. `injectComponents` will return a new `KeplerGl` component instance that renders the custom child component. This way we don’t have to keep track of hundreds of component as props and pass them all the way down. Dependency injection only happens once when `keplerGl` component is imported.

## Factory

For each high level component in kepler.gl, we export a `factory`. A `factory` is a function that takes a set of `dependencies` and return a component instance. In this example below, the `MapContainerFactory` takes `MapPopover` and `MapControl` as dependencies and returns the `MapContainer` component instance. Not all components are exported as factories in kepler.gl at the moment, we are still testing this feature.

```js
import MapPopoverFactory from 'components/map/map-popover';
import MapControlFactory from 'components/map/map-control';

function MapContainerFactory(MapPopover, MapControl) {
 return class MapContainer extends Component {
   render() {
     return (
       <div>
         <MapPopover {...popoverProps} />
         <MapControl {...controlProps} />
       </div>
      );
   }
 }
}

MapContainerFactory.deps = [MapPopoverFactory, MapControlFactory];
```

## Recipes

A recipe is an array of default factory, and the one to replace it. `[defaultFactory, customFactory]`. To replace default component, user can import the existing component factory, call `injectComponents` and pass in the new recipe to get a new `KeplerGl` instance.

### Inject Components

In kepler.gl, we create the app injector by calling provide with an array of default recipes. We then export a `injectComponents` function that user can call to inject a different recipe and returns a new kepler.gl instance.

Here is an example of how to use `injectComponents` to replace default `PanelHeader`.

```js
import {injectComponents, PanelHeaderFactory} from '@kepler.gl/components';

// define custom header
const CustomHeader = () => (<div>My kepler.gl app</div>);

// create a factory
const myCustomHeaderFactory = () => CustomHeader;

// Inject custom header into Kepler.gl,
const KeplerGl = injectComponents([
  [PanelHeaderFactory, myCustomHeaderFactory]
]);

// render KeplerGl, it will render your custom header
const MapContainer = () => <KeplerGl id="foo"/>;
```

## Pass custom component props

`injectComponents` allows user to render custom component, however, they usually also want to pass additional props to the customized component which current component injector doesn’t support. To enable passing additional props, we implemented a `withState`helper that passes additional props to the customized component. `withState` takes 3 arguments: `lenses`, `mapStateToProps` and `actionCreators`, They allows user to pass in kepler.gl instance state, state from other part of the app, and custom actions.

* `lense` - A getter function to get a piece of kepler.gl subreducer state. Kepler.gl exports lenses for all its sub-reducers. For instance when pass `mapStateLens` to `withState`, the component will receive `mapState` of current kepler.gl instance as a prop.
* `mapStateToProps` - A wild card to play. You can pass a `mapStateToProps` function to get the state from any part of the app. If the lenses aren’t enough, use `mapStateToProps`.
* `actions` - action creators that will be passed to `bindActionCreators`.

Here is an example of using `withState` helper to add reducer state and actions to customized component as additional props.

```js
import {withState, injectComponents, PanelHeaderFactory} from '@kepler.gl/components';
import {visStateLens} from '@kepler.gl/reducers';

// custom action wrap to mounted instance
const addTodo = (text) => ({
    type: 'ADD_TODO',
    text
});

// define custom header
const CustomHeader = ({visState, todos, addTodo}) => (
  <div onClick={() => addTodo('say hello')}>{`${Object.keys(visState.datasets).length} dataset loaded`}</div>
);

// now CustomHeader will receive `visState` `todos` and `addTodo` as additional props.
const myCustomHeaderFactory = () => withState(
  // subreducer lenses
  [visStateLens],

  // mapStateToProps
  state => ({
     todos: state.todos
  }),

  // actions
  {addTodo}
)(CustomHeader);
```


# Forward Dispatch Actions

One of the biggest challenge of using local state is to dispatch actions that only modify a specific instance of the state. For instance, if we have 2 kepler.gl components in our app, one with id `foo` other with id `bar`. Our keplerGl reducer is going to be `keplerGl: {foo: …, bar …}`. When `foo` dispatches an action, it only needs to update the state of `foo`, hence we need a way to decorate the action that the root reducer only pass it down to instance reducer `foo`. To solve this, we provide a set of forward functions called `wrapTo`, `forwardTo` and `unwrap`. `wrapTo` wraps an action payload into an forward action by adding an address `_addr_` and a `_forward_` signature to its `meta`. The root reducer will check if the given action has that address and if so, `unwrap` the action and pass it to the correct instance reducer.

**Here are the different options to dispatch forwarded actions to kepler.gl reducer.**

### 1. Use `forwardTo` to add a dispatch function to your component

You can add a dispatch function to your component that dispatches actions to a specific kepler.gl instance using connect.

```js
// component
import {KeplerGl} from '@kepler.gl/components';
import {connect} from 'react-redux';

// import action and forward dispatcher
import {toggleFullScreen, forwardTo} from '@kepler.gl/actions';


const MapContainer = props => (
  <div>
    <button onClick={() => props.keplerGlDispatch(toggleFullScreen())}/>
    <KeplerGl
      id="foo"
    />
  </div>
)

const mapStateToProps = state => state
const mapDispatchToProps = (dispatch, props) => ({
 dispatch,
 keplerGlDispatch: forwardTo(‘foo’, dispatch)
});

export default connect(
 mapStateToProps,
 mapDispatchToProps
)(MapContainer);
```

* 2. Use `wrapTo` to wrap action creator

You can also simply wrap an action into a forward action with the `wrapTo` helper

```js
// component
import {KeplerGl} from '@kepler.gl/components';

// action and wrapper
import {toggleFullScreen, wrapTo} from '@kepler.gl/actions';

// create a function to wrapper action payload to 'foo'
const wrapToMap = wrapTo('foo');
const MapContainer = ({dispatch}) => (
  <div>
    <button onClick={() => dispatch(wrapToMap(toggleFullScreen()))} />
    <KeplerGl id="foo"/>
  </div>
);

```


# Reducer Plugin

For advanced users, who want to add additional action handler to kepler.gl reducer, kepler.gl provides a reducer plugin function. `Reducer.plugin` will take additional action handlers and return a new reducer function. Plugin is only meant to be called where the store is initialized. The state passed into the additional action handler is the instance state.

`Reducer.plugin` will allow advanced users to extend the kepler.gl reducer behavior. Here is an example of adding an additional action `HIDE_AND_SHOW_SIDE_PANEL` handler that modifies the `uiState`.

```js
import {combineReducers} from 'redux';
import keplerGlReducer from '@kepler.gl/reducers';

const customizedKeplerGlReducer = keplerGlReducer
 .plugin({
   HIDE_AND_SHOW_SIDE_PANEL: (state, action) => ({
     ...state,
     uiState: {
       ...state.uiState,
       readOnly: !state.uiState.readOnly
     }
   })
 });

const reducers = combineReducers({
 keplerGl: customizedKeplerGlReducer,
 app: appReducer
});
```

Note that, reducer plugin **should not be used to override default kepler.gl actions** The following code will not change `SET_FILTER`, because plugins are handled after default actions.

```js
const customizedKeplerGlReducer = keplerGlReducer
 .plugin({
   [ActionTypes.SET_FILTER]: (state, action) => state
 });
```

For full implementation, take a look at the [custom reducer example](https://github.com/keplergl/kepler.gl/tree/master/examples/custom-reducer)


# Using Updaters

Updaters are state transition functions that mapped to actions. One action can map to multiple state updaters, each belongs to a subreducer.

This action-updater pattern allows a user to import a specific action updater in the app's root reducer and use it to directly modify kepler.gl’s state without dispatching the action. This will give user a lot of freedom to control over kepler.gl's state transition.

To achieve the same result with `togglePerspective` updating kepler.gl's map perspective mode. You can import and dispatch kepler.gl action `togglePerspective`:

```js
// action and forward dispatcher
import {togglePerspective} from '@kepler.gl/actions';

const MapContainer = ({dispatch}) => (
  <div>
    <button onClick={() => dispatch(togglePerspective())} />
    <KeplerGl id="foo"/>
  </div>
);
```

or import the corresponding updater `mapStateUpdaters.togglePerspectiveUpdater` and call it inside the root reducer. The example below demos how to add a button outside kepler.gl component, and update the map perspective when click it.

```js
import keplerGlReducer, {mapStateUpdaters} from '@kepler.gl/reducers';

// Root Reducer
const reducers = combineReducers({
 keplerGl: keplerGlReducer,
 app: appReducer
});

const composedReducer = (state, action) => {
 switch (action.type) {
   case 'CLICK_BUTTON':
     return {
       ...state,
       keplerGl: {
         ...state.keplerGl,
         foo: {
            ...state.keplerGl.foo,
            mapState: mapStateUpdaters.togglePerspectiveUpdater(
              state.keplerGl.foo.mapState
            )
         }
       }
     };
 }
 return reducers(state, action);
};

export default composedReducer;
```


# Custom reducer initial state

For advanced users who wish to modify the initial state of kepler.gl reducer, kepler.gl provides a reducer `initialState` function. `Reducer.initialState` will take the custom state and return a new reducer function. `initialState` is only meant to be called where the store is initialized. The custom state passed in will be shallow merged with the default `initialState`.

Here is an example modify `uiState` `initialState` to hide side panel, and selectively display map control button.

```js
import {combineReducers} from 'redux';
import keplerGlReducer from '@kepler.gl/reducers';

const customizedKeplerGlReducer = keplerGlReducer
  .initialState({
    uiState: {
      // hide side panel to disallow user customize the map
      readOnly: true,

      // customize which map control button to show
      mapControls: {
        visibleLayers: {
          show: false
        },
        mapLegend: {
          show: true,
          active: true
        },
        toggle3d: {
          show: false
        },
        splitMap: {
          show: false
        }
      }
    }
  });

const reducers = combineReducers({
 keplerGl: customizedKeplerGlReducer,
 app: appReducer
});
```

For full implementation, take a look at the [custom reducer example](https://github.com/keplergl/kepler.gl/tree/master/examples/custom-reducer)


# custom-mapbox-host

#### 1. Configuring Mapbox API hostname

The KeplerGL component accepts an optional parameter `mapboxApiUrl` to override the default value of `https://api.mapbox.com`.

```js
  <KeplerGl
      id="foo"
      mapboxApiAccessToken={token}
      mapboxApiUrl={"https://api.mapbox.cn"}
      width={width}
      height={height}/>
```

#### 2. Overriding the default MapStyles

The default MapStyles KeplerGL uses might not be accessible to you, in this case you will need to provide MapStyle overrides. During construction of your component:

```js
  this.token = '';
  this.apiHost = "https://api.mapbox.cn";
  this.mapStyles = [
    {
      id: 'dark',
      label: 'Dark Streets 9',
      url: 'mapbox://styles/mapbox/dark-v9',
      icon: `${this.apiHost}/styles/v1/mapbox/dark-v9/static/-122.3391,37.7922,9.19,0,0/400x300?access_token=${this.token}&logo=false&attribution=false`,
      layerGroups: [] // DEFAULT_LAYER_GROUPS
    },
    {
      id: 'light',
      label: 'Light Streets 9',
      url: 'mapbox://styles/mapbox/light-v9',
      icon: `${this.apiHost}/styles/v1/mapbox/light-v9/static/-122.3391,37.7922,9.19,0,0/400x300?access_token=${this.token}&logo=false&attribution=false`,
      layerGroups: [] // DEFAULT_LAYER_GROUPS
    }
  ];
```

and In render:

```js
  <KeplerGl
      id="foo"
      mapboxApiAccessToken={this.token}
      mapboxApiUrl={this.apiHost}
      mapStyles={this.mapStyles}
      width={width}
      height={height}/>
```


# Components

...Coming soon


# Reducers

### Reducers

Kepler.gl is a redux-connected component that utilizes redux to manage its state. The basic implementation of kepler.gl reducer is simple. However, to make the most of it, it's recommended to have basic knowledge on:

* [Redux](https://redux.js.org/) state container
* [React](https://reactjs.org/)
* [React Redux connect](https://react-redux.js.org/)

![Compose-reducer](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/api_reducers_compose-reducers.png)

It is important to understand the relationship between **kepler.gl reducer**, **instance reducer** and **subreducer**. Kepler.gl reducer is the root reducer that combines multiple instance reducer, which manages the state of each individual kepler.gl component. The instance reducer consists of 4 subreducers, each manages an independent part of the state.

### KeplerGl Reducer

To connect kepler.gl components to your Redux app you'll need the following pieces from the kepler.gl package:

* Redux Reducer: `keplerGlReducer` imported from `@kepler.gl/reducers`
* React Component: `KeplerGl` imported from `@kepler.gl/components`

These are the only 2 pieces you need to get kepler.gl up and running in your app. When you mount kepler.gl reducer in your app reducer (with `combineReducers`), it will then manages **ALL** KeplerGl component instances that you add to your app. Each kepler.gl instance state is stored in a instance reducer.

For instance, if you have 2 kepler.gl components in your App:

```js
import KeplerGl from '@kepler.gl/components';

const MapApp = () => (
  <div>
    <KeplerGl id="foo"/>
    <KeplerGl id="bar"/>
  </div>
);
```

Your redux state will be:

```js
state = {
  keplerGl: {
    foo: {},
    bar: {}
  },
  // ... other app state
  app: {}
}
```

### Instance Reducer

Each kepler.gl component state is stored in a instance reducer. A instance reducer has 4 subreducers. **`visState`**, **`mapState`**, **`mapStyle`** and **`uiState`**. Each of them manages a piece of state that is mostly self contained.

* **visState** - Manages all data and visualization related state, including datasets, layers, filters and interaction configs. Some of the key updaters are `updateVisDataUpdater`, `layerConfigChangeUpdater`, `setFilterUpdater`, `interactionConfigChangeUpdater`.
* **mapState** - Manages base map behavior including the viewport, drag rotate and toggle split maps. Key updates are `updateMapUpdater`, `toggleSplitMapUpdater` and `togglePerspectiveUpdater`.
* **mapStyle** - Manages base map style, including setting base map style, toggling base map layers and adding custom base map style.
* **uiState** - Manages all UI component transition state, including open / close side panel, current displayed panel etc. Note, ui state reducer is the only reducer that’s not saved in kepler.gl schema.

### Subreducer

The subreducers - **`visState`**, **`mapState`**, **`mapStyle`** and **`uiState`** - are assembled by a list of action handlers, each handler mapped to a state transition function named xxUpdater. For instance, here is a snippet of the map state reducer in kepler.gl:

```js
/* Action Handlers */
const actionHandler = {
 [ActionTypes.UPDATE_MAP]: updateMapUpdater,
 [ActionTypes.FIT_BOUNDS]: fitBoundsUpdater,
 [ActionTypes.TOGGLE_PERSPECTIVE]: togglePerspectiveUpdater
};
```

User can import a specific action handler in their root reducer and use it to directly modify kepler.gl’s state (without dispatching a kepler.gl action). This will give user the full control over kepler.gl’s component state.

Here is an example how you can listen to an app action `QUERY_SUCCESS` and call `updateVisDataUpdater` to load data into kepler.gl.

```js
import keplerGlReducer, {visStateUpdaters} from '@kepler.gl/reducers';

// Root Reducer
const reducers = combineReducers({
 keplerGl: keplerGlReducer,

 app: appReducer
});

const composedReducer = (state, action) => {
 switch (action.type) {
   case 'QUERY_SUCCESS':
     return {
       ...state,
       keplerGl: {
         ...state.keplerGl,

         // 'map' is the id of the keplerGl instance
         map: {
            ...state.keplerGl.map,
            visState: visStateUpdaters.updateVisDataUpdater(
              // you have to pass the subreducer state that the updater is associated with
              state.keplerGl.map.visState,
              {datasets: action.payload}
            )
         }
       }
     };
 }
 return reducers(state, action);
};

export default composedReducer;
```


# reducers

#### Table of Contents

* [keplerGlReducer](#keplerglreducer)
  * [keplerGlReducer.initialState](#keplerglreducerinitialstate)
  * [keplerGlReducer.plugin](#keplerglreducerplugin)
* [mapStateLens](#mapstatelens)
* [mapStyleLens](#mapstylelens)
* [providerStateLens](#providerstatelens)
* [uiStateLens](#uistatelens)
* [visStateLens](#visstatelens)

### keplerGlReducer

Kepler.gl reducer to be mounted to your store. You can mount `keplerGlReducer` at property `keplerGl`, if you choose to mount it at another address e.g. `foo` you will need to specify it when you mount `KeplerGl` component in your app with `getState: state => state.foo`

**Examples**

```javascript
import keplerGlReducer from '@kepler.gl/reducers';
import {createStore, combineReducers, applyMiddleware, compose} from 'redux';
import {taskMiddleware} from 'react-palm/tasks';

const initialState = {};
const reducers = combineReducers({
  // <-- mount kepler.gl reducer in your app
  keplerGl: keplerGlReducer,

  // Your other reducers here
  app: appReducer
});

// using createStore
export default createStore(reducers, initialState, applyMiddleware(taskMiddleware));
```

#### keplerGlReducer.initialState

Return a reducer that initiated with custom initial state. The parameter should be an object mapping from `subreducer` name to custom subreducer state, which will be shallow **merged** with default initial state.

Default subreducer state:

* [`visState`](/docs/api-reference/reducers/vis-state#INITIAL_VIS_STATE)
* [`mapState`](/docs/api-reference/reducers/map-state#INITIAL_MAP_STATE)
* [`mapStyle`](/docs/api-reference/reducers/map-style#INITIAL_MAP_STYLE)
* [`uiState`](/docs/api-reference/reducers/ui-state#INITIAL_UI_STATE)

**Parameters**

* `iniSt` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) custom state to be merged with default initial state

**Examples**

```javascript
const myKeplerGlReducer = keplerGlReducer
 .initialState({
   uiState: {readOnly: true}
 });
```

#### keplerGlReducer.plugin

Returns a kepler.gl reducer that will also pass each action through additional reducers specified. The parameter should be either a reducer map or a reducer function. The state passed into the additional action handler is the instance state. It will include all the subreducers `visState`, `uiState`, `mapState` and `mapStyle`. `.plugin` is only meant to be called once when mounting the keplerGlReducer to the store. **Note** This is an advanced option to give you more freedom to modify the internal state of the kepler.gl instance. You should only use this to adding additional actions instead of replacing default actions.

**Parameters**

* `customReducer` **(**[**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) **|** [**Function**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)**)** A reducer map or a reducer

**Examples**

```javascript
const myKeplerGlReducer = keplerGlReducer
 .plugin({
   // 1. as reducer map
   HIDE_AND_SHOW_SIDE_PANEL: (state, action) => ({
     ...state,
     uiState: {
       ...state.uiState,
       readOnly: !state.uiState.readOnly
     }
   })
 })
.plugin(handleActions({
  // 2. as reducer
  'HIDE_MAP_CONTROLS': (state, action) => ({
    ...state,
    uiState: {
      ...state.uiState,
      mapControls: hiddenMapControl
    }
  })
}, {}));
```

### mapStateLens

Connect subreducer `mapState`, used with `injectComponents`. Learn more at [Replace UI Component](/docs/api-reference/advanced-usages/replace-ui-component#pass-custom-component-props)

**Parameters**

* `reduxState` **any**

### mapStyleLens

Connect subreducer `mapStyle`, used with `injectComponents`. Learn more at [Replace UI Component](/docs/api-reference/advanced-usages/replace-ui-component#pass-custom-component-props)

**Parameters**

* `reduxState` **any**

### providerStateLens

Connect subreducer `providerState`, used with `injectComponents`. Learn more at [Replace UI Component](/docs/api-reference/advanced-usages/replace-ui-component#pass-custom-component-props)

**Parameters**

* `reduxState` **any**

### uiStateLens

Connect subreducer `uiState`, used with `injectComponents`. Learn more at [Replace UI Component](/docs/api-reference/advanced-usages/replace-ui-component#pass-custom-component-props)

**Parameters**

* `reduxState` **any**

### visStateLens

Connect subreducer `visState`, used with `injectComponents`. Learn more at [Replace UI Component](/docs/api-reference/advanced-usages/replace-ui-component#pass-custom-component-props)

**Parameters**

* `reduxState` **any**


# map-style

#### Table of Contents

* [mapStyleUpdaters](#mapstyleupdaters)
  * [INITIAL\_MAP\_STYLE](#initial_map_style)
    * [Properties](#properties)
  * [initMapStyleUpdater](#initmapstyleupdater)
  * [inputMapStyleUpdater](#inputmapstyleupdater)
  * [loadCustomMapStyleUpdater](#loadcustommapstyleupdater)
  * [loadMapStyleErrUpdater](#loadmapstyleerrupdater)
  * [loadMapStylesUpdater](#loadmapstylesupdater)
  * [mapConfigChangeUpdater](#mapconfigchangeupdater)
  * [mapStyleChangeUpdater](#mapstylechangeupdater)
  * [resetMapConfigMapStyleUpdater](#resetmapconfigmapstyleupdater)

### mapStyleUpdaters

Updaters for `mapStyle`. Can be used in your root reducer to directly modify kepler.gl's state. Read more about [Using updaters](/docs/api-reference/advanced-usages/using-updaters)

**Examples**

```javascript
import keplerGlReducer, {mapStyleUpdaters} from '@kepler.gl/reducers';
// Root Reducer
const reducers = combineReducers({
 keplerGl: keplerGlReducer,
 app: appReducer
});

const composedReducer = (state, action) => {
 switch (action.type) {
   // click button to hide label from background map
   case 'CLICK_BUTTON':
     return {
       ...state,
       keplerGl: {
         ...state.keplerGl,
         foo: {
            ...state.keplerGl.foo,
            mapStyle: mapStyleUpdaters.mapConfigChangeUpdater(
              state.keplerGl.foo.mapStyle,
              {payload: {visibleLayerGroups: {label: false, road: true, background: true}}}
            )
         }
       }
     };
 }
 return reducers(state, action);
};

export default composedReducer;
```

#### INITIAL\_MAP\_STYLE

Default initial `mapStyle`

**Properties**

* `styleType` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) Default: `'dark'`
* `visibleLayerGroups` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) Default: `{}`
* `topLayerGroups` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) Default: `{}`
* `mapStyles` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) mapping from style key to style object
* `mapboxApiAccessToken` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) Default: `null`
* `inputStyle` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) Default: `{}`
* `threeDBuildingColor` [**Array**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array) Default: `[r, g, b]`

#### initMapStyleUpdater

Propagate `mapStyle` reducer with `mapboxApiAccessToken` and `mapStylesReplaceDefault`. if mapStylesReplaceDefault is true mapStyles is emptied; loadMapStylesUpdater() will populate mapStyles.

* **Action**: [`keplerGlInit`](/docs/api-reference/actions/actions#keplerglinit)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)
* `action` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)
  * `action.payload` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)
    * `action.payload.mapboxApiAccessToken` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### inputMapStyleUpdater

Input a custom map style object

* **Action**: [`inputMapStyle`](/docs/api-reference/actions/actions#inputmapstyle)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) `mapStyle`
* `action` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) action object
  * `action.payload` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) inputStyle
    * `action.payload.url` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) style url e.g. `'mapbox://styles/heshan/xxxxxyyyyzzz'`
    * `action.payload.id` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) style url e.g. `'custom_style_1'`
    * `action.payload.style` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) actual mapbox style json
    * `action.payload.name` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) style name
    * `action.payload.layerGroups` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) layer groups that can be used to set map layer visibility
    * `action.payload.icon` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) icon image data url
  * `action.payload.inputStyle`
  * `action.payload.mapState`

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### loadCustomMapStyleUpdater

Callback when a custom map style object is received

* **Action**: [`loadCustomMapStyle`](/docs/api-reference/actions/actions#loadcustommapstyle)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) `mapStyle`
* `action` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)
  * `action.payload` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)
    * `action.payload.icon` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)
    * `action.payload.style` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)
    * `action.payload.error` **any**
  * `action.payload.icon`
  * `action.payload.style`
  * `action.payload.error`

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### loadMapStyleErrUpdater

Callback when load map style error

* **Action**: [`loadMapStyleErr`](/docs/api-reference/actions/actions#loadmapstyleerr)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) `mapStyle`
* `action` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)
  * `action.payload` **any** error

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### loadMapStylesUpdater

Callback when load map style success

* **Action**: [`loadMapStyles`](/docs/api-reference/actions/actions#loadmapstyles)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) `mapStyle`
* `action` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)
  * `action.payload` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) a `{[id]: style}` mapping

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### mapConfigChangeUpdater

Update `visibleLayerGroups`to change layer group visibility

* **Action**: [`mapConfigChange`](/docs/api-reference/actions/actions#mapconfigchange)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) `mapStyle`
* `action` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)
  * `action.payload` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) new config `{visibleLayerGroups: {label: false, road: true, background: true}}`

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### mapStyleChangeUpdater

Change to another map style. The selected style should already been loaded into `mapStyle.mapStyles`

* **Action**: [`mapStyleChange`](/docs/api-reference/actions/actions#mapstylechange)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) `mapStyle`
* `action` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)
  * `action.payload` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### resetMapConfigMapStyleUpdater

Reset map style config to initial state

* **Action**: [`resetMapConfig`](/docs/api-reference/actions/actions#resetmapconfig)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) `mapStyle`

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState


# map-state

#### Table of Contents

* [mapStateUpdaters](#mapstateupdaters)
  * [fitBoundsUpdater](#fitboundsupdater)
  * [INITIAL\_MAP\_STATE](#initial_map_state)
    * [Properties](#properties)
  * [receiveMapConfigUpdater](#receivemapconfigupdater)
  * [resetMapConfigUpdater](#resetmapconfigupdater)
  * [togglePerspectiveUpdater](#toggleperspectiveupdater)
  * [toggleSplitMapUpdater](#togglesplitmapupdater)
  * [updateMapUpdater](#updatemapupdater)

### mapStateUpdaters

Updaters for `mapState` reducer. Can be used in your root reducer to directly modify kepler.gl's state. Read more about [Using updaters](/docs/api-reference/advanced-usages/using-updaters)

**Examples**

```javascript
import keplerGlReducer, {mapStateUpdaters} from '@kepler.gl/reducers';
// Root Reducer
const reducers = combineReducers({
 keplerGl: keplerGlReducer,
 app: appReducer
});

const composedReducer = (state, action) => {
 switch (action.type) {
   // click button to close side panel
   case 'CLICK_BUTTON':
     return {
       ...state,
       keplerGl: {
         ...state.keplerGl,
         foo: {
            ...state.keplerGl.foo,
            mapState: mapStateUpdaters.fitBoundsUpdater(
              state.keplerGl.foo.mapState, {payload: [127.34, 31.09, 127.56, 31.59]}
            )
         }
       }
     };
 }
 return reducers(state, action);
};

export default composedReducer;
```

#### fitBoundsUpdater

Fit map viewport to bounds

* **Action**: [`fitBounds`](/docs/api-reference/actions/actions#fitbounds)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)
* `action` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)
  * `action.payload` [**Array**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)**<**[**number**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)**>** bounds as `[lngMin, latMin, lngMax, latMax]`

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### INITIAL\_MAP\_STATE

Default initial `mapState`

**Properties**

* `pitch` [**number**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number) Default: `0`
* `bearing` [**number**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number) Default: `0`
* `latitude` [**number**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number) Default: `37.75043`
* `longitude` [**number**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number) Default: `-122.34679`
* `zoom` [**number**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number) Default: `9`
* `dragRotate` [**boolean**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean) Default: `false`
* `width` [**number**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number) Default: `800`
* `height` [**number**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number) Default: `800`
* `isSplit` [**boolean**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean) Default: `false`

#### receiveMapConfigUpdater

Update `mapState` to propagate a new config

* **Action**: [`receiveMapConfig`](/docs/api-reference/actions/actions#receivemapconfig)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)
* `action` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)
  * `action.payload` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) saved map config
  * `action.payload.config` (optional, default `{}`)
  * `action.payload.options` (optional, default `{}`)
  * `action.payload.bounds` (optional, default `null`)

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### resetMapConfigUpdater

reset mapState to initial State

* **Action**: [`resetMapConfig`](/docs/api-reference/actions/actions#resetmapconfig)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) `mapState`

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### togglePerspectiveUpdater

Toggle between 3d and 2d map.

* **Action**: [`togglePerspective`](/docs/api-reference/actions/actions#toggleperspective)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### toggleSplitMapUpdater

Toggle between one or split maps

* **Action**: [`toggleSplitMap`](/docs/api-reference/actions/actions#togglesplitmap)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### updateMapUpdater

Update map viewport

* **Action**: [`updateMap`](/docs/api-reference/actions/actions#updatemap)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)
* `action` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)
  * `action.payload` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) viewport

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState


# combine

#### Table of Contents

* [combinedUpdaters](#combinedupdaters)
  * [addDataToMapUpdater](#adddatatomapupdater)

### combinedUpdaters

Some actions will affect the entire kepler.gl instance state. The updaters for these actions is exported as `combinedUpdaters`. These updater take the entire instance state as the first argument. Read more about [Using updaters](/docs/api-reference/advanced-usages/using-updaters)

**Examples**

```javascript
import keplerGlReducer, {combinedUpdaters} from '@kepler.gl/reducers';
// Root Reducer
const reducers = combineReducers({
 keplerGl: keplerGlReducer,
 app: appReducer
});

const composedReducer = (state, action) => {
 switch (action.type) {
   // add data to map after receiving data from remote sources
   case 'LOAD_REMOTE_RESOURCE_SUCCESS':
     return {
       ...state,
       keplerGl: {
         ...state.keplerGl,
         // pass in kepler.gl instance state to combinedUpdaters
         map:  combinedUpdaters.addDataToMapUpdater(
          state.keplerGl.map,
          {
            payload: {
              datasets: action.datasets,
              options: {readOnly: true},
              config: action.config
             }
           }
         )
       }
     };
 }
 return reducers(state, action);
};

export default composedReducer;
```

#### addDataToMapUpdater

Combine data and full configuration update in a single action

* **Action**: [`addDataToMap`](/docs/api-reference/actions/actions#adddatatomap)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) kepler.gl instance state, containing all subreducer state
* `action` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)
  * `action.payload` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) `{datasets, options, config}`
    * `action.payload.datasets` **(**[**Array**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)**<**[**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)**> |** [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)**)** **\*required** datasets can be a dataset or an array of datasets Each dataset object needs to have `info` and `data` property.
      * `action.payload.datasets.info` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) -info of a dataset
        * `action.payload.datasets.info.id` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) id of this dataset. If config is defined, `id` should matches the `dataId` in config.
        * `action.payload.datasets.info.label` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) A display name of this dataset
      * `action.payload.datasets.data` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) **\*required** The data object, in a tabular format with 2 properties `fields` and `rows`
        * `action.payload.datasets.data.fields` [**Array**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)**<**[**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)**>** **\*required** Array of fields,
          * `action.payload.datasets.data.fields.name` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) **\*required** Name of the field,
        * `action.payload.datasets.data.rows` [**Array**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)**<**[**Array**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)**>** **\*required** Array of rows, in a tabular format with `fields` and `rows`
    * `action.payload.options` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) option object `{centerMap: true}`
    * `action.payload.config` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) map config

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState


# ui-state

#### Table of Contents

* [uiStateUpdaters](#uistateupdaters)
  * [addNotificationUpdater](#addnotificationupdater)
  * [cleanupExportImage](#cleanupexportimage)
  * [DEFAULT\_EXPORT\_DATA](#default_export_data)
    * [Properties](#properties)
  * [DEFAULT\_EXPORT\_IMAGE](#default_export_image)
    * [Properties](#properties-1)
  * [DEFAULT\_MAP\_CONTROLS\_FEATURES](#default_map_controls_features)
    * [Properties](#properties-2)
  * [hideExportDropdownUpdater](#hideexportdropdownupdater)
  * [INITIAL\_UI\_STATE](#initial_ui_state)
    * [Properties](#properties-3)
  * [loadFilesErrUpdater](#loadfileserrupdater)
  * [loadFilesUpdater](#loadfilesupdater)
  * [openDeleteModalUpdater](#opendeletemodalupdater)
  * [removeNotificationUpdater](#removenotificationupdater)
  * [setExportDataTypeUpdater](#setexportdatatypeupdater)
  * [setExportDataUpdater](#setexportdataupdater)
  * [setExportFilteredUpdater](#setexportfilteredupdater)
  * [setExportImageDataUri](#setexportimagedatauri)
  * [setExportImageSetting](#setexportimagesetting)
  * [setExportSelectedDatasetUpdater](#setexportselecteddatasetupdater)
  * [showExportDropdownUpdater](#showexportdropdownupdater)
  * [startExportingImage](#startexportingimage)
  * [toggleMapControlUpdater](#togglemapcontrolupdater)
  * [toggleModalUpdater](#togglemodalupdater)
  * [toggleSidePanelUpdater](#togglesidepanelupdater)
  * [toggleSplitMapUpdater](#togglesplitmapupdater)
* [DEFAULT\_EXPORT\_HTML](#default_export_html)
  * [Properties](#properties-4)
* [setUserMapboxAccessTokenUpdater](#setusermapboxaccesstokenupdater)

### uiStateUpdaters

Updaters for `uiState` reducer. Can be used in your root reducer to directly modify kepler.gl's state. Read more about [Using updaters](/docs/api-reference/advanced-usages/using-updaters)

**Examples**

```javascript
import keplerGlReducer, {uiStateUpdaters} from '@kepler.gl/reducers';
// Root Reducer
const reducers = combineReducers({
 keplerGl: keplerGlReducer,
 app: appReducer
});

const composedReducer = (state, action) => {
 switch (action.type) {
   // click button to close side panel
   case 'CLICK_BUTTON':
     return {
       ...state,
       keplerGl: {
         ...state.keplerGl,
         foo: {
            ...state.keplerGl.foo,
            uiState: uiStateUpdaters.toggleSidePanelUpdater(
              state.keplerGl.foo.uiState, {payload: null}
            )
         }
       }
     };
 }
 return reducers(state, action);
};

export default composedReducer;
```

#### addNotificationUpdater

Add a notification to be displayed. Existing notification is going to be updated in case of matching ids.

* **Action**: [`addNotification`](/docs/api-reference/actions/actions#addnotification)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) `uiState`
* `action` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)
  * `action.payload` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### cleanupExportImage

Delete cached export image

* **Action**: [`cleanupExportImage`](/docs/api-reference/actions/actions#cleanupexportimage)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) `uiState`

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### DEFAULT\_EXPORT\_DATA

Default initial `exportData` settings

Type: [Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)

**Properties**

* `selectedDataset` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) Default: `''`,
* `dataType` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) Default: `'csv'`,
* `filtered` [**boolean**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean) Default: `true`,
* `config` [**boolean**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean) deprecated
* `data` [**boolean**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean) used in modal config export. Default: `false`

#### DEFAULT\_EXPORT\_IMAGE

Default image export config

Type: [Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)

**Properties**

* `ratio` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) Default: `'SCREEN'`,
* `resolution` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) Default: `'ONE_X'`,
* `legend` [**boolean**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean) Default: `false`,
* `imageDataUri` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) Default: `''`,
* `exporting` [**boolean**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean) Default: `false`
* `error` [**boolean**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean) Default: `false`

#### DEFAULT\_MAP\_CONTROLS\_FEATURES

A list of map control visibility and whether is it active.

Type: [Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)

**Properties**

* `visibleLayers` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) Default: `{show: true, active: false}`
* `mapLegend` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) Default: `{show: true, active: false}`
* `toggle3d` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) Default: `{show: true}`
* `splitMap` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) Default: `{show: true}`

#### hideExportDropdownUpdater

Hide side panel header dropdown, activated by clicking the share link on top of the side panel

* **Action**: [`hideExportDropdown`](/docs/api-reference/actions/actions#hideexportdropdown)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) `uiState`

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### INITIAL\_UI\_STATE

Default initial `uiState`

Type: [Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)

**Properties**

* `readOnly` [**boolean**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean) Default: `false`
* `activeSidePanel` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) Default: `'layer'`
* `currentModal` **(**[**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) **| null)** Default: `'addData'`
* `datasetKeyToRemove` **(**[**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) **| null)** Default: `null`
* `visibleDropdown` **(**[**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) **| null)** Default: `null`
* `exportImage` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) Default: [`DEFAULT_EXPORT_IMAGE`](#default_export_image)
* `exportData` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) Default: [`DEFAULT_EXPORT_DATA`](#default_export_data)
* `mapControls` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) Default: [`DEFAULT_MAP_CONTROLS`](#default_map_controls)
* `activeMapIndex` [**number**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number) defines which map the user clicked on. Default: 0

#### loadFilesErrUpdater

Handles load file error and set fileLoading property to false

* **Action**: [`loadFilesErr`](/docs/api-reference/actions/actions#loadfileserr)

**Parameters**

* `state`
* `error` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)
  * `error.error`

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### loadFilesUpdater

Fired when file loading begin

* **Action**: [`loadFiles`](/docs/api-reference/actions/actions#loadfiles)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) `uiState`

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### openDeleteModalUpdater

Toggle active map control panel

* **Action**: [`openDeleteModal`](/docs/api-reference/actions/actions#opendeletemodal)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) `uiState`
* `action` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)
  * `action.payload` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) dataset id

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### removeNotificationUpdater

Remove a notification

* **Action**: [`removeNotification`](/docs/api-reference/actions/actions#removenotification)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) `uiState`
* `action` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)
  * `action.payload` [**String**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) id of the notification to be removed

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### setExportDataTypeUpdater

Set data format for exporting data

* **Action**: [`setExportDataType`](/docs/api-reference/actions/actions#setexportdatatype)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) `uiState`
* `action` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)
  * `action.payload` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) one of `'text/csv'`

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### setExportDataUpdater

Whether to including data in map config, toggle between `true` or `false`

* **Action**: [`setExportData`](/docs/api-reference/actions/actions#setexportdata)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) `uiState`

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### setExportFilteredUpdater

Whether to export filtered data, `true` or `false`

* **Action**: [`setExportFiltered`](/docs/api-reference/actions/actions#setexportfiltered)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) `uiState`
* `action` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)
  * `action.payload` [**boolean**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### setExportImageDataUri

Set `exportImage.setExportImageDataUri` to a image dataUri

* **Action**: [`setExportImageDataUri`](/docs/api-reference/actions/actions#setexportimagedatauri)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) `uiState`
* `action` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)
  * `action.payload` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) export image data uri

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### setExportImageSetting

Set `exportImage.legend` to `true` or `false`

* **Action**: [`setExportImageSetting`](/docs/api-reference/actions/actions#setexportimagesetting)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) `uiState`
* `$1` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)
  * `$1.payload`

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### setExportSelectedDatasetUpdater

Set selected dataset for export

* **Action**: [`setExportSelectedDataset`](/docs/api-reference/actions/actions#setexportselecteddataset)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) `uiState`
* `action` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)
  * `action.payload` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) dataset id

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### showExportDropdownUpdater

Hide and show side panel header dropdown, activated by clicking the share link on top of the side panel

* **Action**: [`showExportDropdown`](/docs/api-reference/actions/actions#showexportdropdown)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) `uiState`
* `action` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)
  * `action.payload` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) id of the dropdown

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### startExportingImage

Set `exportImage.exporting` to `true`

* **Action**: [`startExportingImage`](/docs/api-reference/actions/actions#startexportingimage)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) `uiState`

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### toggleMapControlUpdater

Toggle active map control panel

* **Action**: [`toggleMapControl`](/docs/api-reference/actions/actions#togglemapcontrol)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) `uiState`
* `action` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) action
  * `action.payload` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) map control panel id, one of the keys of: [`DEFAULT_MAP_CONTROLS`](#default_map_controls)
  * `action.payload.panelId`
  * `action.payload.index` (optional, default `0`)

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### toggleModalUpdater

Show and hide modal dialog

* **Action**: [`toggleModal`](/docs/api-reference/actions/actions#togglemodal)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) `uiState`
* `action` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)
  * `action.payload` **(**[**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) **| null)** id of modal to be shown, null to hide modals. One of:- [`DATA_TABLE_ID`](https://github.com/keplergl/kepler.gl/blob/master/docs/api-reference/constants/default-settings.md#data_table_id)
    * [`DELETE_DATA_ID`](https://github.com/keplergl/kepler.gl/blob/master/docs/api-reference/constants/default-settings.md#delete_data_id)
    * [`ADD_DATA_ID`](https://github.com/keplergl/kepler.gl/blob/master/docs/api-reference/constants/default-settings.md#add_data_id)
    * [`EXPORT_IMAGE_ID`](https://github.com/keplergl/kepler.gl/blob/master/docs/api-reference/constants/default-settings.md#export_image_id)
    * [`EXPORT_DATA_ID`](https://github.com/keplergl/kepler.gl/blob/master/docs/api-reference/constants/default-settings.md#export_data_id)
    * [`ADD_MAP_STYLE_ID`](https://github.com/keplergl/kepler.gl/blob/master/docs/api-reference/constants/default-settings.md#add_map_style_id)

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### toggleSidePanelUpdater

Toggle active side panel

* **Action**: [`toggleSidePanel`](/docs/api-reference/actions/actions#togglesidepanel)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) `uiState`
* `action` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)
  * `action.payload` **(**[**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) **| null)** id of side panel to be shown, one of `layer`, `filter`, `interaction`, `map`. close side panel if `null`

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### toggleSplitMapUpdater

Handles toggle map split and reset all map control index to 0

* **Action**: [`toggleSplitMap`](/docs/api-reference/actions/actions#togglesplitmap)

**Parameters**

* `state`

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

### DEFAULT\_EXPORT\_HTML

Type: [Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)

#### Properties

* `exportMapboxAccessToken` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) Default: null, this is used when we provide a default mapbox token for users to take advantage of
* `userMapboxToken` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) Default: '', mapbox token provided by user through input field

### setUserMapboxAccessTokenUpdater

whether to export a mapbox access to HTML single page

* **Action**: [`setUserMapboxAccessToken`](/docs/api-reference/actions/actions#setusermapboxaccesstoken)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) `uiState`
* `action` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)
  * `action.payload` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState


# vis-state

#### Table of Contents

* [visStateUpdaters](#visstateupdaters)
  * [addFilterUpdater](#addfilterupdater)
  * [addLayerUpdater](#addlayerupdater)
  * [applyCPUFilterUpdater](#applycpufilterupdater)
  * [enlargeFilterUpdater](#enlargefilterupdater)
  * [INITIAL\_VIS\_STATE](#initial_vis_state)
    * [Properties](#properties)
  * [interactionConfigChangeUpdater](#interactionconfigchangeupdater)
  * [layerClickUpdater](#layerclickupdater)
  * [layerHoverUpdater](#layerhoverupdater)
  * [layerTypeChangeUpdater](#layertypechangeupdater)
  * [layerVisConfigChangeUpdater](#layervisconfigchangeupdater)
  * [layerVisualChannelChangeUpdater](#layervisualchannelchangeupdater)
  * [loadFilesErrUpdater](#loadfileserrupdater)
  * [loadFilesUpdater](#loadfilesupdater)
  * [mapClickUpdater](#mapclickupdater)
  * [receiveMapConfigUpdater](#receivemapconfigupdater)
  * [removeDatasetUpdater](#removedatasetupdater)
  * [removeFilterUpdater](#removefilterupdater)
  * [removeLayerUpdater](#removelayerupdater)
  * [reorderLayerUpdater](#reorderlayerupdater)
  * [resetMapConfigUpdater](#resetmapconfigupdater)
  * [setFilterPlotUpdater](#setfilterplotupdater)
  * [setFilterUpdater](#setfilterupdater)
  * [setMapInfoUpdater](#setmapinfoupdater)
  * [showDatasetTableUpdater](#showdatasettableupdater)
  * [toggleFilterAnimationUpdater](#togglefilteranimationupdater)
  * [toggleLayerForMapUpdater](#togglelayerformapupdater)
  * [toggleSplitMapUpdater](#togglesplitmapupdater)
  * [updateAnimationTimeUpdater](#updateanimationtimeupdater)
  * [updateFilterAnimationSpeedUpdater](#updatefilteranimationspeedupdater)
  * [updateLayerAnimationSpeedUpdater](#updatelayeranimationspeedupdater)
  * [updateLayerBlendingUpdater](#updatelayerblendingupdater)
  * [updateVisDataUpdater](#updatevisdataupdater)

### visStateUpdaters

Updaters for `visState` reducer. Can be used in your root reducer to directly modify kepler.gl's state. Read more about [Using updaters](/docs/api-reference/advanced-usages/using-updaters)

**Examples**

```javascript
import keplerGlReducer, {visStateUpdaters} from '@kepler.gl/reducers';
// Root Reducer
const reducers = combineReducers({
 keplerGl: keplerGlReducer,
 app: appReducer
});

const composedReducer = (state, action) => {
 switch (action.type) {
   case 'CLICK_BUTTON':
     return {
       ...state,
       keplerGl: {
         ...state.keplerGl,
         foo: {
            ...state.keplerGl.foo,
            visState: visStateUpdaters.enlargeFilterUpdater(
              state.keplerGl.foo.visState,
              {idx: 0}
            )
         }
       }
     };
 }
 return reducers(state, action);
};

export default composedReducer;
```

#### addFilterUpdater

Add a new filter

* **Action**: [`addFilter`](/docs/api-reference/actions/actions#addfilter)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) `visState`
* `action` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) action
  * `action.dataId` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) dataset `id` this new filter is associated with

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### addLayerUpdater

Add a new layer

* **Action**: [`addLayer`](/docs/api-reference/actions/actions#addlayer)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) `visState`
* `action` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) action
  * `action.props` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) new layer props

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### applyCPUFilterUpdater

When select dataset for export, apply cpu filter to selected dataset

* **Action**: [`applyCPUFilter`](/docs/api-reference/actions/actions#applycpufilter)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) `visState`
* `action` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)
  * `action.dataId` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) dataset id

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### enlargeFilterUpdater

Show larger time filter at bottom for time playback (apply to time filter only)

* **Action**: [`enlargeFilter`](/docs/api-reference/actions/actions#enlargefilter)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) `visState`
* `action` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) action
  * `action.idx` [**Number**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number) index of filter to enlarge

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### INITIAL\_VIS\_STATE

Default initial `visState`

Type: [Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)

**Properties**

* `layers` [**Array**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)
* `layerData` [**Array**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)
* `layerToBeMerged` [**Array**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)
* `layerOrder` [**Array**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)
* `filters` [**Array**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)
* `filterToBeMerged` [**Array**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)
* `datasets` [**Array**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)
* `editingDataset` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)
* `interactionConfig` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)
* `interactionToBeMerged` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)
* `layerBlending` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)
* `hoverInfo` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)
* `clicked` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)
* `mousePos` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)
* `splitMaps` [**Array**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array) a list of objects of layer availabilities and visibilities for each map
* `layerClasses` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)
* `animationConfig` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)
* `editor` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)

#### interactionConfigChangeUpdater

Update `interactionConfig`

* **Action**: [`interactionConfigChange`](/docs/api-reference/actions/actions#interactionconfigchange)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) `visState`
* `action` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) action
  * `action.config` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) new config as key value map: `{tooltip: {enabled: true}}`

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### layerClickUpdater

Trigger layer click event with clicked object

* **Action**: [`onLayerClick`](/docs/api-reference/actions/actions#onlayerclick)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) `visState`
* `action` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) action
  * `action.info` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) Object clicked, returned by deck.gl

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### layerHoverUpdater

Trigger layer hover event with hovered object

* **Action**: [`onLayerHover`](/docs/api-reference/actions/actions#onlayerhover)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) `visState`
* `action` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) action
  * `action.info` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) Object hovered, returned by deck.gl

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### layerTypeChangeUpdater

Update layer type. Previous layer config will be copied if applicable.

* **Action**: [`layerTypeChange`](/docs/api-reference/actions/actions#layertypechange)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) `visState`
* `action` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) action
  * `action.oldLayer` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) layer to be updated
  * `action.newType` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) new type

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### layerVisConfigChangeUpdater

Update layer `visConfig`

* **Action**: [`layerVisConfigChange`](/docs/api-reference/actions/actions#layervisconfigchange)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) `visState`
* `action` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) action
  * `action.oldLayer` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) layer to be updated
  * `action.newVisConfig` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) new visConfig as a key value map: e.g. `{opacity: 0.8}`

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### layerVisualChannelChangeUpdater

Update layer visual channel

* **Action**: [`layerVisualChannelConfigChange`](/docs/api-reference/actions/actions#layervisualchannelconfigchange)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) `visState`
* `action` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) action
  * `action.oldLayer` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) layer to be updated
  * `action.newConfig` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) new visual channel config
  * `action.channel` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) channel to be updated

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### loadFilesErrUpdater

Trigger loading file error

* **Action**: [`loadFilesErr`](/docs/api-reference/actions/actions#loadfileserr)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) `visState`
* `action` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) action
  * `action.error` **any**

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### loadFilesUpdater

Trigger file loading dispatch `addDataToMap` if succeed, or `loadFilesErr` if failed

* **Action**: [`loadFiles`](/docs/api-reference/actions/actions#loadfiles)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) `visState`
* `action` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) action
  * `action.files` [**Array**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)**<**[**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)**>** array of fileblob

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### mapClickUpdater

Trigger map click event, unselect clicked object

* **Action**: [`onMapClick`](/docs/api-reference/actions/actions#onmapclick)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) `visState`

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### receiveMapConfigUpdater

Propagate `visState` reducer with a new configuration. Current config will be override.

* **Action**: [`receiveMapConfig`](/docs/api-reference/actions/actions#receivemapconfig)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) `visState`
* `action` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) action
  * `action.payload` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) map config to be propagated
    * `action.payload.config` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) map config to be propagated
    * `action.payload.option` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) {keepExistingConfig: true | false}
  * `action.payload.config` (optional, default `{}`)
  * `action.payload.options` (optional, default `{}`)

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### removeDatasetUpdater

Remove a dataset and all layers, filters, tooltip configs that based on it

* **Action**: [`removeDataset`](/docs/api-reference/actions/actions#removedataset)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) `visState`
* `action` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) action
  * `action.key` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) dataset id

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### removeFilterUpdater

Remove a filter

* **Action**: [`removeFilter`](/docs/api-reference/actions/actions#removefilter)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) `visState`
* `action` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) action
  * `action.idx` [**Number**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number) index of filter to be removed

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### removeLayerUpdater

remove layer

* **Action**: [`removeLayer`](/docs/api-reference/actions/actions#removelayer)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) `visState`
* `action` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) action
  * `action.idx` [**Number**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number) index of layer to be removed

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### reorderLayerUpdater

Reorder layer

* **Action**: [`reorderLayer`](/docs/api-reference/actions/actions#reorderlayer)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) `visState`
* `action` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) action
  * `action.order` [**Array**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)**<**[**Number**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)**>** an array of layer indexes

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### resetMapConfigUpdater

reset visState to initial State

* **Action**: [`resetMapConfig`](/docs/api-reference/actions/actions#resetmapconfig)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) `visState`

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### setFilterPlotUpdater

Set the property of a filter plot

* **Action**: [`setFilterPlot`](/docs/api-reference/actions/actions#setfilterplot)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) `visState`
* `action` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) action
  * `action.idx` [**Number**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)
  * `action.newProp` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) key value mapping of new prop `{yAxis: 'histogram'}`

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### setFilterUpdater

Update filter property

* **Action**: [`setFilter`](/docs/api-reference/actions/actions#setfilter)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) `visState`
* `action` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) action
  * `action.idx` [**Number**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number) `idx` of filter to be updated
  * `action.prop` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) `prop` of filter, e,g, `dataId`, `name`, `value`
  * `action.value` **any** new value
* `datasetId` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) used when updating a prop (dataId, name) that can be linked to multiple datasets

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### setMapInfoUpdater

User input to update the info of the map

* **Action**: [`setMapInfo`](/docs/api-reference/actions/actions#setmapinfo)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) `visState`
* `action` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) action
  * `action.info` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) {title: 'hello'}

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### showDatasetTableUpdater

Display dataset table in a modal

* **Action**: [`showDatasetTable`](/docs/api-reference/actions/actions#showdatasettable)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) `visState`
* `action` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) action
  * `action.dataId` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) dataset id to show in table

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### toggleFilterAnimationUpdater

Start and end filter animation

* **Action**: [`toggleFilterAnimation`](/docs/api-reference/actions/actions#togglefilteranimation)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) `visState`
* `action` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) action
  * `action.idx` [**Number**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number) idx of filter

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### toggleLayerForMapUpdater

Toggle visibility of a layer in a split map

* **Action**: [`toggleLayerForMap`](/docs/api-reference/actions/actions#togglelayerformap)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)
* `action` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)
  * `action.mapIndex` [**Number**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number) index of the split map
  * `action.layerId` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) id of the layer

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### toggleSplitMapUpdater

Toggle visibility of a layer for a split map

* **Action**: [`toggleSplitMap`](/docs/api-reference/actions/actions#togglesplitmap)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) `visState`
* `action` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) action
  * `action.payload` **(**[**Number**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number) **|** [**undefined**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined)**)** index of the split map

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### updateAnimationTimeUpdater

Reset animation config current time to a specified value

* **Action**: [`updateAnimationTime`](/docs/api-reference/actions/actions#updateanimationtime)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) `visState`
* `action` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) action
  * `action.value` [**Number**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number) the value current time will be set to

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### updateFilterAnimationSpeedUpdater

Change filter animation speed

* **Action**: [`updateFilterAnimationSpeed`](/docs/api-reference/actions/actions#updatefilteranimationspeed)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) `visState`
* `action` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) action
  * `action.idx` [**Number**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number) `idx` of filter
  * `action.speed` [**Number**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number) `speed` to change it to. `speed` is a multiplier

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### updateLayerAnimationSpeedUpdater

Update animation speed with the vertical speed slider

* **Action**: [`updateLayerAnimationSpeed`](/docs/api-reference/actions/actions#updatelayeranimationspeed)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) `visState`
* `action` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) action
  * `action.speed` [**Number**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number) the updated speed of the animation

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### updateLayerBlendingUpdater

update layer blending mode

* **Action**: [`updateLayerBlending`](/docs/api-reference/actions/actions#updatelayerblending)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) `visState`
* `action` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) action
  * `action.mode` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) one of `additive`, `normal` and `subtractive`

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState

#### updateVisDataUpdater

Add new dataset to `visState`, with option to load a map config along with the datasets

* **Action**: [`updateVisData`](/docs/api-reference/actions/actions#updatevisdata)

**Parameters**

* `state` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) `visState`
* `action` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) action
  * `action.datasets` **(**[**Array**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)**<**[**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)**> |** [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)**)** **\*required** datasets can be a dataset or an array of datasets Each dataset object needs to have `info` and `data` property.
    * `action.datasets.info` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) -info of a dataset
      * `action.datasets.info.id` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) id of this dataset. If config is defined, `id` should matches the `dataId` in config.
      * `action.datasets.info.label` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) A display name of this dataset
    * `action.datasets.data` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) **\*required** The data object, in a tabular format with 2 properties `fields` and `rows`
      * `action.datasets.data.fields` [**Array**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)**<**[**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)**>** **\*required** Array of fields,
        * `action.datasets.data.fields.name` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) **\*required** Name of the field,
      * `action.datasets.data.rows` [**Array**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)**<**[**Array**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)**>** **\*required** Array of rows, in a tabular format with `fields` and `rows`
  * `action.options` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) option object `{centerMap: true, keepExistingConfig: false}`
  * `action.config` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) map config

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) nextState


# Processors

...Coming soon


# All processors

* [getFieldsFromData](#getfieldsfromdata)
* [processCsvData](#processcsvdata)
* [processGeojson](#processgeojson)
* [processKeplerglJSON](#processkeplergljson)
* [processRowObject](#processrowobject)

**getFieldsFromData**

Analyze field types from data in `string` format, e.g. uploaded csv. Assign `type`, `tableFieldIndex` and `format` (timestamp only) to each field

**Parameters**

* `data` [**Array**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)**<**[**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)**>** array of row object
* `fieldOrder` [**Array**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array) array of field names as string

**Examples**

```javascript
import {getFieldsFromData} from '@kepler.gl/processors';
const data = [{
  time: '2016-09-17 00:09:55',
  value: '4',
  surge: '1.2',
  isTrip: 'true',
  zeroOnes: '0'
}, {
  time: '2016-09-17 00:30:08',
  value: '3',
  surge: null,
  isTrip: 'false',
  zeroOnes: '1'
}, {
  time: null,
  value: '2',
  surge: '1.3',
  isTrip: null,
  zeroOnes: '1'
}];

const fieldOrder = ['time', 'value', 'surge', 'isTrip', 'zeroOnes'];
const fields = getFieldsFromData(data, fieldOrder);
// fields = [
// {name: 'time', format: 'YYYY-M-D H:m:s', tableFieldIndex: 1, type: 'timestamp'},
// {name: 'value', format: '', tableFieldIndex: 4, type: 'integer'},
// {name: 'surge', format: '', tableFieldIndex: 5, type: 'real'},
// {name: 'isTrip', format: '', tableFieldIndex: 6, type: 'boolean'},
// {name: 'zeroOnes', format: '', tableFieldIndex: 7, type: 'integer'}];
```

Returns [**Array**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)**<**[**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)**>** formatted fields

**processCsvData**

Process csv data, output a data object with `{fields: [], rows: []}`. The data object can be wrapped in a `dataset` and pass to [`addDataToMap`](/docs/api-reference/actions/actions#adddatatomap)

**Parameters**

* `rawData` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) raw csv string

**Examples**

```javascript
import {processCsvData} from '@kepler.gl/processors';

const testData = `gps_data.utc_timestamp,gps_data.lat,gps_data.lng,gps_data.types,epoch,has_result,id,time,begintrip_ts_utc,begintrip_ts_local,date
2016-09-17 00:09:55,29.9900937,31.2590542,driver_analytics,1472688000000,False,1,2016-09-23T00:00:00.000Z,2016-10-01 09:41:39+00:00,2016-10-01 09:41:39+00:00,2016-09-23
2016-09-17 00:10:56,29.9927699,31.2461142,driver_analytics,1472688000000,False,2,2016-09-23T00:00:00.000Z,2016-10-01 09:46:37+00:00,2016-10-01 16:46:37+00:00,2016-09-23
2016-09-17 00:11:56,29.9907261,31.2312742,driver_analytics,1472688000000,False,3,2016-09-23T00:00:00.000Z,,,2016-09-23
2016-09-17 00:12:58,29.9870074,31.2175827,driver_analytics,1472688000000,False,4,2016-09-23T00:00:00.000Z,,,2016-09-23`

const dataset = {
 info: {id: 'test_data', label: 'My Csv'},
 data: processCsvData(testData)
};

dispatch(addDataToMap({
 datasets: [dataset],
 options: {centerMap: true, readOnly: true}
}));
```

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) data object `{fields: [], rows: []}`

**processGeojson**

Process GeoJSON [`FeatureCollection`](http://wiki.geojson.org/GeoJSON_draft_version_6#FeatureCollection), output a data object with `{fields: [], rows: []}`. The data object can be wrapped in a `dataset` and pass to [`addDataToMap`](/docs/api-reference/actions/actions#adddatatomap)

**Parameters**

* `rawData` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) raw geojson feature collection

**Examples**

```javascript
import {addDataToMap} from '@kepler.gl/actions';
import {processGeojson} from '@kepler.gl/processors';

const geojson = {
	"type" : "FeatureCollection",
	"features" : [{
		"type" : "Feature",
		"properties" : {
			"capacity" : "10",
			"type" : "U-Rack"
		},
		"geometry" : {
			"type" : "Point",
			"coordinates" : [ -71.073283, 42.417500 ]
		}
	}]
};

dispatch(addDataToMap({
 datasets: {
   info: {
     label: 'Sample Taxi Trips in New York City',
     id: 'test_trip_data'
   },
   data: processGeojson(geojson)
 }
}));
```

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) dataset containing `fields` and `rows`

**processKeplerglJSON**

Process saved kepler.gl json to be pass to [`addDataToMap`](/docs/api-reference/actions/actions#adddatatomap). The json object should contain `datasets` and `config`.

**Parameters**

* `rawData` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)
  * `rawData.datasets` [**Array**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)
  * `rawData.config` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)

**Examples**

```javascript
import {addDataToMap} from '@kepler.gl/actions';
import {processKeplerglJSON} from '@kepler.gl/processors';

dispatch(addDataToMap(processKeplerglJSON(keplerGlJson)));
```

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) datasets and config `{datasets: {}, config: {}}`

**processRowObject**

Process data where each row is an object, output can be passed to [`addDataToMap`](/docs/api-reference/actions/actions#adddatatomap)

**Parameters**

* `rawData` [**Array**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)**<**[**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)**>** an array of row object, each object should have the same number of keys

**Examples**

```javascript
import {addDataToMap} from '@kepler.gl/actions';
import {processRowObject} from '@kepler.gl/processors';

const data = [
 {lat: 31.27, lng: 127.56, value: 3},
 {lat: 31.22, lng: 126.26, value: 1}
];

dispatch(addDataToMap({
 datasets: {
   info: {label: 'My Data', id: 'my_data'},
   data: processRowObject(data)
 }
}));
```

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) dataset containing `fields` and `rows`


# Schemas

...Coming Soon


# Actions

...Coming soon


# All actions

#### Table of Contents

* [forwardActions](#forwardactions)
  * [forwardTo](#forwardto)
  * [isForwardAction](#isforwardaction)
  * [unwrap](#unwrap)
  * [wrapTo](#wrapto)
* [ActionTypes](#actiontypes)
* [mapStyleActions](#mapstyleactions)
  * [addCustomMapStyle](#addcustommapstyle)
  * [inputMapStyle](#inputmapstyle)
  * [loadCustomMapStyle](#loadcustommapstyle)
  * [loadMapStyleErr](#loadmapstyleerr)
  * [loadMapStyles](#loadmapstyles)
  * [mapConfigChange](#mapconfigchange)
  * [mapStyleChange](#mapstylechange)
  * [requestMapStyles](#requestmapstyles)
  * [set3dBuildingColor](#set3dbuildingcolor)
* [main](#main)
  * [addDataToMap](#adddatatomap)
  * [keplerGlInit](#keplerglinit)
  * [receiveMapConfig](#receivemapconfig)
  * [resetMapConfig](#resetmapconfig)
* [visStateActions](#visstateactions)
  * [addFilter](#addfilter)
  * [addLayer](#addlayer)
  * [applyCPUFilter](#applycpufilter)
  * [enlargeFilter](#enlargefilter)
  * [interactionConfigChange](#interactionconfigchange)
  * [layerConfigChange](#layerconfigchange)
  * [layerTextLabelChange](#layertextlabelchange)
  * [layerTypeChange](#layertypechange)
  * [layerVisConfigChange](#layervisconfigchange)
  * [layerVisualChannelConfigChange](#layervisualchannelconfigchange)
  * [loadFiles](#loadfiles)
  * [loadFilesErr](#loadfileserr)
  * [onLayerClick](#onlayerclick)
  * [onLayerHover](#onlayerhover)
  * [onMapClick](#onmapclick)
  * [onMouseMove](#onmousemove)
  * [removeDataset](#removedataset)
  * [removeFilter](#removefilter)
  * [removeLayer](#removelayer)
  * [reorderLayer](#reorderlayer)
  * [setEditorMode](#seteditormode)
  * [setFilter](#setfilter)
  * [setFilterPlot](#setfilterplot)
  * [setMapInfo](#setmapinfo)
  * [showDatasetTable](#showdatasettable)
  * [toggleFilterAnimation](#togglefilteranimation)
  * [toggleLayerForMap](#togglelayerformap)
  * [updateAnimationTime](#updateanimationtime)
  * [updateFilterAnimationSpeed](#updatefilteranimationspeed)
  * [updateLayerAnimationSpeed](#updatelayeranimationspeed)
  * [updateLayerBlending](#updatelayerblending)
  * [updateVisData](#updatevisdata)
* [uiStateActions](#uistateactions)
  * [addNotification](#addnotification)
  * [cleanupExportImage](#cleanupexportimage)
  * [hideExportDropdown](#hideexportdropdown)
  * [openDeleteModal](#opendeletemodal)
  * [removeNotification](#removenotification)
  * [setExportData](#setexportdata)
  * [setExportDataType](#setexportdatatype)
  * [setExportFiltered](#setexportfiltered)
  * [setExportImageDataUri](#setexportimagedatauri)
  * [setExportImageSetting](#setexportimagesetting)
  * [setExportSelectedDataset](#setexportselecteddataset)
  * [setUserMapboxAccessToken](#setusermapboxaccesstoken)
  * [showExportDropdown](#showexportdropdown)
  * [startExportingImage](#startexportingimage)
  * [toggleMapControl](#togglemapcontrol)
  * [toggleModal](#togglemodal)
  * [toggleSidePanel](#togglesidepanel)
* [rootActions](#rootactions)
  * [deleteEntry](#deleteentry)
  * [registerEntry](#registerentry)
  * [renameEntry](#renameentry)
* [mapStateActions](#mapstateactions)
  * [fitBounds](#fitbounds)
  * [togglePerspective](#toggleperspective)
  * [toggleSplitMap](#togglesplitmap)
  * [updateMap](#updatemap)
* [layerColorUIChange](#layercoloruichange)
* [setExportMapFormat](#setexportmapformat)

### forwardActions

A set of helpers to forward dispatch actions to a specific instance reducer

#### forwardTo

Returns an action dispatcher that wraps and forwards the actions to a specific instance

**Parameters**

* `id` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) instance id
* `dispatch` [**Function**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function) action dispatcher

**Examples**

```javascript
// action and forward dispatcher
import {toggleSplitMap, forwardTo} from '@kepler.gl/actions';
import {connect} from 'react-redux';

const MapContainer = props => (
 <div>
  <button onClick={() => props.keplerGlDispatch(toggleSplitMap())}/>
 </div>
)

const mapDispatchToProps = (dispatch, props) => ({
 dispatch,
 keplerGlDispatch: forwardTo(‘foo’, dispatch)
});

export default connect(
 state => state,
 mapDispatchToProps
)(MapContainer);
```

#### isForwardAction

Whether an action is a forward action

**Parameters**

* `action` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) the action object

Returns [**boolean**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean) boolean - whether the action is a forward action

#### unwrap

Unwrap an action

**Parameters**

* `action` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) the action object

Returns [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) unwrapped action

#### wrapTo

Wrap an action into a forward action that only modify the state of a specific kepler.gl instance. kepler.gl reducer will look for signatures in the action to determine whether it needs to be forwarded to a specific instance reducer.

wrapTo can be curried. You can create a curried action wrapper by only supply the `id` argument

A forward action looks like this

```js
 {
   type: "@@kepler.gl/LAYER_CONFIG_CHANGE",
   payload: {
     type: '@@kepler.gl/LAYER_CONFIG_CHANGE',
     payload: {},
     meta: {
      // id of instance
       _id_: id
      // other meta
     }
   },
   meta: {
     _forward_: '@redux-forward/FORWARD',
     _addr_: '@@KG_id'
   }
 };
```

**Parameters**

* `id` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) The id to forward to
* `action` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) the action object {type: string, payload: \*}

**Examples**

```javascript
import {wrapTo, togglePerspective} from '@kepler.gl/actions';

// This action will only dispatch to the KeplerGl instance with `id: map_1`
this.props.dispatch(wrapTo('map_1', togglePerspective()));

// You can also create a curried action for each instance
const wrapToMap1 = wrapTo('map_1');
this.props.dispatch(wrapToMap1(togglePerspective()));
```

### ActionTypes

Kepler.gl action types, can be listened by reducers to perform additional tasks whenever an action is called in kepler.gl

Type: [Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)

**Examples**

```javascript
// store.js
import {handleActions} from 'redux-actions';
import {createStore, combineReducers, applyMiddleware} from 'redux';
import {taskMiddleware} from 'react-palm/tasks';

import keplerGlReducer from '@kepler.gl/reducers';
import {ActionTypes} from '@kepler.gl/actions';

const appReducer = handleActions(
  {
    // listen on kepler.gl map update action to store a copy of viewport in app state
    [ActionTypes.UPDATE_MAP]: (state, action) => ({
      ...state,
      viewport: action.payload
    })
  },
  {}
);

const reducers = combineReducers({
  app: appReducer,
  keplerGl: keplerGlReducer
});

export default createStore(reducers, {}, applyMiddleware(taskMiddleware));
```

### mapStyleActions

Actions handled mostly by `mapStyle` reducer. They manage the display of base map, such as loading and receiving base map styles, hiding and showing map layers, user input of custom map style url.

#### addCustomMapStyle

Add map style from user input to reducer and set it to current style This action is called when user click confirm after putting in a valid style url in the custom map style dialog. It should not be called from outside kepler.gl without a valid `inputStyle` in the `mapStyle` reducer. param {void}

* **ActionTypes**: [`ActionTypes.ADD_CUSTOM_MAP_STYLE`](#actiontypes)
* **Updaters**: [`mapStyleUpdaters.addCustomMapStyleUpdater`](/docs/api-reference/reducers/map-style#mapstyleupdatersaddcustommapstyleupdater)

#### inputMapStyle

Input a custom map style object

* **ActionTypes**: [`ActionTypes.INPUT_MAP_STYLE`](#actiontypes)
* **Updaters**: [`mapStyleUpdaters.inputMapStyleUpdater`](/docs/api-reference/reducers/map-style#mapstyleupdatersinputmapstyleupdater)

**Parameters**

* `inputStyle` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)
  * `inputStyle.url` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) style url e.g. `'mapbox://styles/heshan/xxxxxyyyyzzz'`
  * `inputStyle.id` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) style url e.g. `'custom_style_1'`
  * `inputStyle.style` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) actual mapbox style json
  * `inputStyle.name` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) style name
  * `inputStyle.layerGroups` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) layer groups that can be used to set map layer visibility
  * `inputStyle.icon` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) icon image data url
* `mapState` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) mapState is optional

#### loadCustomMapStyle

Callback when a custom map style object is received

* **ActionTypes**: [`ActionTypes.LOAD_CUSTOM_MAP_STYLE`](#actiontypes)
* **Updaters**: [`mapStyleUpdaters.loadCustomMapStyleUpdater`](/docs/api-reference/reducers/map-style#mapstyleupdatersloadcustommapstyleupdater)

**Parameters**

* `customMapStyle` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)
  * `customMapStyle.icon` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)
  * `customMapStyle.style` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)
  * `customMapStyle.error` **any**

#### loadMapStyleErr

Callback when load map style error

* **ActionTypes**: [`ActionTypes.LOAD_MAP_STYLE_ERR`](#actiontypes)
* **Updaters**: [`mapStyleUpdaters.loadMapStyleErrUpdater`](/docs/api-reference/reducers/map-style#mapstyleupdatersloadmapstyleerrupdater)

**Parameters**

* `error` **any**

#### loadMapStyles

Callback when load map style success

* **ActionTypes**: [`ActionTypes.LOAD_MAP_STYLES`](#actiontypes)
* **Updaters**: [`mapStyleUpdaters.loadMapStylesUpdater`](/docs/api-reference/reducers/map-style#mapstyleupdatersloadmapstylesupdater)

**Parameters**

* `newStyles` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) a `{[id]: style}` mapping

#### mapConfigChange

Update `visibleLayerGroups` to change layer group visibility

* **ActionTypes**: [`ActionTypes.MAP_CONFIG_CHANGE`](#actiontypes)
* **Updaters**: [`mapStyleUpdaters.mapConfigChangeUpdater`](/docs/api-reference/reducers/map-style#mapstyleupdatersmapconfigchangeupdater)

**Parameters**

* `mapStyle` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) new config `{visibleLayerGroups: {label: false, road: true, background: true}}`

#### mapStyleChange

Change to another map style. The selected style should already been loaded into `mapStyle.mapStyles`

* **ActionTypes**: [`ActionTypes.MAP_STYLE_CHANGE`](#actiontypes)
* **Updaters**: [`mapStyleUpdaters.mapStyleChangeUpdater`](/docs/api-reference/reducers/map-style#mapstyleupdatersmapstylechangeupdater)

**Parameters**

* `styleType` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) the style to change to

#### requestMapStyles

Request map style style object based on style.url.

* **ActionTypes**: [`ActionTypes.REQUEST_MAP_STYLES`](#actiontypes)
* **Updaters**: [`mapStyleUpdaters.requestMapStylesUpdater`](/docs/api-reference/reducers/map-style#mapstyleupdatersrequestmapstylesupdater)

**Parameters**

* `mapStyles` [**Array**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)**<**[**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)**>**

#### set3dBuildingColor

Set 3d building layer group color

* **ActionTypes**: [`ActionTypes.SET_3D_BUILDING_COLOR`](#actiontypes)
* **Updaters**: [`mapStyleUpdaters.set3dBuildingColorUpdater`](/docs/api-reference/reducers/map-style#mapstyleupdatersset3dbuildingcolorupdater)

**Parameters**

* `color` [**Array**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array) \[r, g, b]

### main

Main kepler.gl actions, these actions handles loading data and config into kepler.gl reducer. These actions are listened to by all subreducers.

#### addDataToMap

Add data to kepler.gl reducer, prepare map with preset configuration if config is passed. Kepler.gl provides a handy set of utils to parse data from different formats to the `data` object required in dataset. You rarely need to manually format the data object.

Use `KeplerGlSchema.getConfigToSave` to generate a json blob of the currents instance config. The config object value will always have higher precedence than the options properties.

Kepler.gl uses `dataId` in the config to match with loaded dataset. If you pass a config object, you need to match the `info.id` of your dataset to the `dataId` in each `layer`, `filter` and `interactionConfig.tooltips.fieldsToShow`

* **ActionTypes**: [`ActionTypes.ADD_DATA_TO_MAP`](#actiontypes)
* **Updaters**: [`combinedUpdaters.addDataToMapUpdater`](/docs/api-reference/reducers/combine#combinedupdatersadddatatomapupdater)

**Parameters**

* `data` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)
  * `data.datasets` **(**[**Array**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)**<**[**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)**> |** [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)**)** **\*required** datasets can be a dataset or an array of datasets Each dataset object needs to have `info` and `data` property.
    * `data.datasets.info` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) -info of a dataset
      * `data.datasets.info.id` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) id of this dataset. If config is defined, `id` should matches the `dataId` in config.
      * `data.datasets.info.label` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) A display name of this dataset
    * `data.datasets.data` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) **\*required** The data object, in a tabular format with 2 properties `fields` and `rows`
      * `data.datasets.data.fields` [**Array**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)**<**[**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)**>** **\*required** Array of fields,
        * `data.datasets.data.fields.name` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) **\*required** Name of the field,
      * `data.datasets.data.rows` [**Array**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)**<**[**Array**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)**>** **\*required** Array of rows, in a tabular format with `fields` and `rows`
  * `data.options` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)
    * `data.options.centerMap` [**boolean**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean) `default: true` if `centerMap` is set to `true` kepler.gl will place the map view within the data points boundaries. `options.centerMap` will override `config.mapState` if passed in.
    * `data.options.readOnly` [**boolean**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean) `default: false` if `readOnly` is set to `true` the left setting panel will be hidden
    * `data.options.keepExistingConfig` [**boolean**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean) whether to keep exiting map data and associated layer filter interaction config `default: false`.
  * `data.config` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) this object will contain the full kepler.gl instance configuration {mapState, mapStyle, visState}

**Examples**

```javascript
// app.js
import {addDataToMap} from '@kepler.gl/actions';

const sampleTripData = {
  fields: [
    {name: 'tpep_pickup_datetime', format: 'YYYY-M-D H:m:s', type: 'timestamp'},
    {name: 'pickup_longitude', format: '', type: 'real'},
    {name: 'pickup_latitude', format: '', type: 'real'}
  ],
  rows: [
    ['2015-01-15 19:05:39 +00:00', -73.99389648, 40.75011063],
    ['2015-01-15 19:05:39 +00:00', -73.97642517, 40.73981094],
    ['2015-01-15 19:05:40 +00:00', -73.96870422, 40.75424576]
  ]
};

const sampleConfig = {
  visState: {
    filters: [
      {
        id: 'me',
        dataId: 'test_trip_data',
        name: 'tpep_pickup_datetime',
        type: 'timeRange',
        view: 'enlarged'
      }
    ]
  }
};

this.props.dispatch(
  addDataToMap({
    datasets: {
      info: {
        label: 'Sample Taxi Trips in New York City',
        id: 'test_trip_data'
      },
      data: sampleTripData
    },
    options: {
      centerMap: true,
      readOnly: false,
      keepExistingConfig: false
    },
    info: {
      title: 'Taro and Blue',
      description: 'This is my map'
    },
    config: sampleConfig
  })
);
```

#### keplerGlInit

Initialize kepler.gl reducer. It is used to pass in `mapboxApiAccessToken` to `mapStyle` reducer.

* **ActionTypes**: [`ActionTypes.INIT`](#actiontypes)
* **Updaters**: [`mapStyleUpdaters.initMapStyleUpdater`](/docs/api-reference/reducers/map-style#mapstyleupdatersinitmapstyleupdater)

**Parameters**

* `payload` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)
  * `payload.mapboxApiAccessToken` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) mapboxApiAccessToken to be saved to mapStyle reducer
  * `payload.mapboxApiUrl` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) mapboxApiUrl to be saved to mapStyle reducer.
  * `payload.mapStylesReplaceDefault` [**Boolean**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean) mapStylesReplaceDefault to be saved to mapStyle reducer

#### receiveMapConfig

Pass config to kepler.gl instance, prepare the state with preset configs. Calling `KeplerGlSchema.parseSavedConfig` to convert saved config before passing it in is required.

You can call `receiveMapConfig` before passing in any data. The reducer will store layer and filter config, waiting for data to come in. When data arrives, you can call `addDataToMap` without passing any config, and the reducer will try to match preloaded configs. This behavior is designed to allow asynchronous data loading.

It is also useful when you want to prepare the kepler.gl instance with some preset layer and filter settings. **Note** Sequence is important, `receiveMapConfig` needs to be called **before** data is loaded. Currently kepler.gl doesn't allow calling `receiveMapConfig` after data is loaded. It will reset current configuration first then apply config to it.

* **ActionTypes**: [`ActionTypes.RECEIVE_MAP_CONFIG`](#actiontypes)
* **Updaters**: [`mapStateUpdaters.receiveMapConfigUpdater`](/docs/api-reference/reducers/map-state#mapstateupdatersreceivemapconfigupdater), [`mapStyleUpdaters.receiveMapConfigUpdater`](/docs/api-reference/reducers/map-style#mapstyleupdatersreceivemapconfigupdater), [`visStateUpdaters.receiveMapConfigUpdater`](/docs/api-reference/reducers/vis-state#visstateupdatersreceivemapconfigupdater)

**Parameters**

* `config` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) **\*required** The Config Object
* `options` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) **\*optional** The Option object
  * `options.centerMap` [**boolean**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean) `default: true` if `centerMap` is set to `true` kepler.gl will place the map view within the data points boundaries
  * `options.readOnly` [**boolean**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean) `default: false` if `readOnly` is set to `true` the left setting panel will be hidden
  * `options.keepExistingConfig` [**boolean**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean) whether to keep exiting layer filter and interaction config `default: false`.

**Examples**

```javascript
import {receiveMapConfig} from '@kepler.gl/actions';
import KeplerGlSchema from '@kepler.gl/schemas';

const parsedConfig = KeplerGlSchema.parseSavedConfig(config);
this.props.dispatch(receiveMapConfig(parsedConfig));
```

#### resetMapConfig

Reset all sub-reducers to its initial state. This can be used to clear out all configuration in the reducer.

* **ActionTypes**: [`ActionTypes.RESET_MAP_CONFIG`](#actiontypes)
* **Updaters**: [`mapStateUpdaters.resetMapConfigUpdater`](/docs/api-reference/reducers/map-state#mapstateupdatersresetmapconfigupdater), [`mapStyleUpdaters.resetMapConfigMapStyleUpdater`](/docs/api-reference/reducers/map-style#mapstyleupdatersresetmapconfigmapstyleupdater), [`mapStyleUpdaters.resetMapConfigMapStyleUpdater`](/docs/api-reference/reducers/map-style#mapstyleupdatersresetmapconfigmapstyleupdater), [`visStateUpdaters.resetMapConfigUpdater`](/docs/api-reference/reducers/vis-state#visstateupdatersresetmapconfigupdater)

### visStateActions

Actions handled mostly by `visState` reducer. They manage how data is processed, filtered and displayed on the map by operates on layers, filters and interaction settings.

#### addFilter

Add a new filter

* **ActionTypes**: [`ActionTypes.ADD_FILTER`](#actiontypes)
* **Updaters**: [`visStateUpdaters.addFilterUpdater`](/docs/api-reference/reducers/vis-state#visstateupdatersaddfilterupdater)

**Parameters**

* `dataId` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) dataset `id` this new filter is associated with

Returns **{type: ActionTypes.ADD\_FILTER, dataId: dataId}**

#### addLayer

Add a new layer

* **ActionTypes**: [`ActionTypes.ADD_LAYER`](#actiontypes)
* **Updaters**: [`visStateUpdaters.addLayerUpdater`](/docs/api-reference/reducers/vis-state#visstateupdatersaddlayerupdater)

**Parameters**

* `props` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) new layer props

Returns **{type: ActionTypes.ADD\_LAYER, props: props}**

#### applyCPUFilter

Trigger CPU filter of selected dataset

* **ActionTypes**: [`ActionTypes.APPLY_CPU_FILTER`](#actiontypes)
* **Updaters**: [`visStateUpdaters.applyCPUFilterUpdater`](/docs/api-reference/reducers/vis-state#visstateupdatersapplycpufilterupdater)

**Parameters**

* `dataId` **(**[**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) **| Array<**[**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**>)** single dataId or an array of dataIds

Returns **{type: ActionTypes.APPLY\_CPU\_FILTER, dataId:** [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**}**

#### enlargeFilter

Show larger time filter at bottom for time playback (apply to time filter only)

* **ActionTypes**: [`ActionTypes.ENLARGE_FILTER`](#actiontypes)
* **Updaters**: [`visStateUpdaters.enlargeFilterUpdater`](/docs/api-reference/reducers/vis-state#visstateupdatersenlargefilterupdater)

**Parameters**

* `idx` [**Number**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number) index of filter to enlarge

Returns **{type: ActionTypes.ENLARGE\_FILTER, idx: idx}**

#### interactionConfigChange

Update `interactionConfig`

* **ActionTypes**: [`ActionTypes.INTERACTION_CONFIG_CHANGE`](#actiontypes)
* **Updaters**: [`visStateUpdaters.interactionConfigChangeUpdater`](/docs/api-reference/reducers/vis-state#visstateupdatersinteractionconfigchangeupdater)

**Parameters**

* `config` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) new config as key value map: `{tooltip: {enabled: true}}`

Returns **{type: ActionTypes.INTERACTION\_CONFIG\_CHANGE, config: config}**

#### layerConfigChange

Update layer base config: dataId, label, column, isVisible

* **ActionTypes**: [`ActionTypes.LAYER_CONFIG_CHANGE`](#actiontypes)
* **Updaters**: [`visStateUpdaters.layerConfigChangeUpdater`](/docs/api-reference/reducers/vis-state#visstateupdaterslayerconfigchangeupdater)

**Parameters**

* `oldLayer` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) layer to be updated
* `newConfig` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) new config

Returns **{type: ActionTypes.LAYER\_CONFIG\_CHANGE, oldLayer: oldLayer, newConfig: newConfig}**

#### layerTextLabelChange

Update layer text label

* **ActionTypes**: [`ActionTypes.LAYER_TEXT_LABEL_CHANGE`](#actiontypes)
* **Updaters**: [`visStateUpdaters.layerTextLabelChangeUpdater`](/docs/api-reference/reducers/vis-state#visstateupdaterslayertextlabelchangeupdater)

**Parameters**

* `oldLayer` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) layer to be updated
* `idx` [**Number**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number) -`idx` of text label to be updated
* `prop` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) `prop` of text label, e,g, `anchor`, `alignment`, `color`, `size`, `field`
* `value` **any** new value

#### layerTypeChange

Update layer type. Previous layer config will be copied if applicable.

* **ActionTypes**: [`ActionTypes.LAYER_TYPE_CHANGE`](#actiontypes)
* **Updaters**: [`visStateUpdaters.layerTypeChangeUpdater`](/docs/api-reference/reducers/vis-state#visstateupdaterslayertypechangeupdater)

**Parameters**

* `oldLayer` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) layer to be updated
* `newType` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) new type

Returns **{type: ActionTypes.LAYER\_TYPE\_CHANGE, oldLayer: oldLayer, newType: newType}**

#### layerVisConfigChange

Update layer `visConfig`

* **ActionTypes**: [`ActionTypes.LAYER_VIS_CONFIG_CHANGE`](#actiontypes)
* **Updaters**: [`visStateUpdaters.layerVisConfigChangeUpdater`](/docs/api-reference/reducers/vis-state#visstateupdaterslayervisconfigchangeupdater)

**Parameters**

* `oldLayer` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) layer to be updated
* `newVisConfig` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) new visConfig as a key value map: e.g. `{opacity: 0.8}`

Returns **{type: ActionTypes.LAYER\_VIS\_CONFIG\_CHANGE, oldLayer: oldLayer, newVisConfig: newVisConfig}**

#### layerVisualChannelConfigChange

Update layer visual channel

* **ActionTypes**: [`ActionTypes.LAYER_VISUAL_CHANNEL_CHANGE`](#actiontypes)
* **Updaters**: [`visStateUpdaters.layerVisualChannelChangeUpdater`](/docs/api-reference/reducers/vis-state#visstateupdaterslayervisualchannelchangeupdater)

**Parameters**

* `oldLayer` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) layer to be updated
* `newConfig` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) new visual channel config
* `channel` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) channel to be updated

Returns **{type: ActionTypes.LAYER\_VISUAL\_CHANNEL\_CHANGE, oldLayer: oldLayer, newConfig: newConfig, channel: channel}**

#### loadFiles

Trigger file loading dispatch `addDataToMap` if succeed, or `loadFilesErr` if failed

* **ActionTypes**: [`ActionTypes.LOAD_FILES`](#actiontypes)
* **Updaters**: [`uiStateUpdaters.loadFilesUpdater`](/docs/api-reference/reducers/ui-state#uistateupdatersloadfilesupdater), [`visStateUpdaters.loadFilesUpdater`](/docs/api-reference/reducers/vis-state#visstateupdatersloadfilesupdater)

**Parameters**

* `files` [**Array**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)**<**[**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)**>** array of fileblob

Returns **{type: ActionTypes.LOAD\_FILES, files: any}**

#### loadFilesErr

Trigger loading file error

* **ActionTypes**: [`ActionTypes.LOAD_FILES_ERR`](#actiontypes)
* **Updaters**: [`uiStateUpdaters.loadFilesErrUpdater`](/docs/api-reference/reducers/ui-state#uistateupdatersloadfileserrupdater), [`visStateUpdaters.loadFilesErrUpdater`](/docs/api-reference/reducers/vis-state#visstateupdatersloadfileserrupdater)

**Parameters**

* `error` **any**

Returns **{type: ActionTypes.LOAD\_FILES\_ERR, error:** [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)**}**

#### onLayerClick

Trigger layer click event with clicked object

* **ActionTypes**: [`ActionTypes.LAYER_CLICK`](#actiontypes)
* **Updaters**: [`visStateUpdaters.layerClickUpdater`](/docs/api-reference/reducers/vis-state#visstateupdaterslayerclickupdater)

**Parameters**

* `info` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) Object clicked, returned by deck.gl

Returns **{type: ActionTypes.LAYER\_CLICK, info: info}**

#### onLayerHover

Trigger layer hover event with hovered object

* **ActionTypes**: [`ActionTypes.LAYER_HOVER`](#actiontypes)
* **Updaters**: [`visStateUpdaters.layerHoverUpdater`](/docs/api-reference/reducers/vis-state#visstateupdaterslayerhoverupdater)

**Parameters**

* `info` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) Object hovered, returned by deck.gl

Returns **{type: ActionTypes.LAYER\_HOVER, info: info}**

#### onMapClick

Trigger map click event, unselect clicked object

* **ActionTypes**: [`ActionTypes.MAP_CLICK`](#actiontypes)
* **Updaters**: [`visStateUpdaters.mapClickUpdater`](/docs/api-reference/reducers/vis-state#visstateupdatersmapclickupdater)

Returns **{type: ActionTypes.MAP\_CLICK}**

#### onMouseMove

Trigger map mouse move event, payload would be React-map-gl MapLayerMouseEvent <https://visgl.github.io/react-map-gl/docs/api-reference/types#maplayermouseevent>

* **ActionTypes**: [`ActionTypes.MOUSE_MOVE`](#actiontypes)
* **Updaters**: [`visStateUpdaters.mouseMoveUpdater`](/docs/api-reference/reducers/vis-state#visstateupdatersmousemoveupdater)

**Parameters**

* `evt` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) MapLayerMouseEvent

Returns **{type: ActionTypes.MOUSE\_MOVE}**

#### removeDataset

Remove a dataset and all layers, filters, tooltip configs that based on it

* **ActionTypes**: [`ActionTypes.REMOVE_DATASET`](#actiontypes)
* **Updaters**: [`visStateUpdaters.removeDatasetUpdater`](/docs/api-reference/reducers/vis-state#visstateupdatersremovedatasetupdater)

**Parameters**

* `key` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) dataset id

Returns **{type: ActionTypes.REMOVE\_DATASET, key: key}**

#### removeFilter

Remove a filter from `visState.filters`, once a filter is removed, data will be re-filtered and layer will be updated

* **ActionTypes**: [`ActionTypes.REMOVE_FILTER`](#actiontypes)
* **Updaters**: [`visStateUpdaters.removeFilterUpdater`](/docs/api-reference/reducers/vis-state#visstateupdatersremovefilterupdater)

**Parameters**

* `idx` [**Number**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number) idx of filter to be removed

Returns **{type: ActionTypes.REMOVE\_FILTER, idx: idx}**

#### removeLayer

Remove a layer

* **ActionTypes**: [`ActionTypes.REMOVE_LAYER`](#actiontypes)
* **Updaters**: [`visStateUpdaters.removeLayerUpdater`](/docs/api-reference/reducers/vis-state#visstateupdatersremovelayerupdater)

**Parameters**

* `idx` [**Number**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number) idx of layer to be removed

Returns **{type: ActionTypes.REMOVE\_LAYER, idx: idx}**

#### reorderLayer

Reorder layer, order is an array of layer indexes, index 0 will be the one at the bottom

* **ActionTypes**: [`ActionTypes.REORDER_LAYER`](#actiontypes)
* **Updaters**: [`visStateUpdaters.reorderLayerUpdater`](/docs/api-reference/reducers/vis-state#visstateupdatersreorderlayerupdater)

**Parameters**

* `order` [**Array**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)**<**[**Number**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)**>** an array of layer indexes

**Examples**

```javascript
// bring `layers[1]` below `layers[0]`, the sequence layers will be rendered is `1`, `0`, `2`, `3`.
// `1` will be at the bottom, `3` will be at the top.
this.props.dispatch(reorderLayer([1, 0, 2, 3]));
```

Returns **{type: ActionTypes.REORDER\_LAYER, order: order}**

#### setEditorMode

Set the map mode

* **ActionTypes**: [`ActionTypes.SET_EDITOR_MODE`](#actiontypes)
* **Updaters**: [`visStateUpdaters.setEditorModeUpdater`](/docs/api-reference/reducers/vis-state#visstateupdatersseteditormodeupdater)

**Parameters**

* `mode` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) one of EDITOR\_MODES

**Examples**

```javascript
import {setEditorMode} from '@kepler.gl/actions';
import {EDITOR_MODES} from '@kepler.gl/constants';

this.props.dispatch(setEditorMode(EDITOR_MODES.DRAW_POLYGON));
```

#### setFilter

Update filter property

* **ActionTypes**: [`ActionTypes.SET_FILTER`](#actiontypes)
* **Updaters**: [`visStateUpdaters.setFilterUpdater`](/docs/api-reference/reducers/vis-state#visstateupdaterssetfilterupdater)

**Parameters**

* `idx` [**Number**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number) -`idx` of filter to be updated
* `prop` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) `prop` of filter, e,g, `dataId`, `name`, `value`
* `value` **any** new value
* `valueIndex` [**Number**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number) array properties like dataset require index in order to improve performance

Returns **{type: ActionTypes.SET\_FILTER, idx: idx, prop: prop, value: value}**

#### setFilterPlot

Set the property of a filter plot

* **ActionTypes**: [`ActionTypes.SET_FILTER_PLOT`](#actiontypes)
* **Updaters**: [`visStateUpdaters.setFilterPlotUpdater`](/docs/api-reference/reducers/vis-state#visstateupdaterssetfilterplotupdater)

**Parameters**

* `idx` [**Number**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)
* `newProp` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) key value mapping of new prop `{yAxis: 'histogram'}`

Returns **{type: ActionTypes.SET\_FILTER\_PLOT, idx: any, newProp: any}**

#### setMapInfo

Set map info such as title and description

* **ActionTypes**: [`ActionTypes.SET_MAP_INFO`](#actiontypes)
* **Updaters**: [`visStateUpdaters.setMapInfoUpdater`](/docs/api-reference/reducers/vis-state#visstateupdaterssetmapinfoupdater)

**Parameters**

* `info` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) map info object, e.g. `{title: 'My Map', description: 'My map description'}`

Returns **{type: ActionTypes.SET\_MAP\_INFO, info: info}**

#### showDatasetTable

Display dataset table in a modal

* **ActionTypes**: [`ActionTypes.SHOW_DATASET_TABLE`](#actiontypes)
* **Updaters**: [`visStateUpdaters.showDatasetTableUpdater`](/docs/api-reference/reducers/vis-state#visstateupdatersshowdatasettableupdater)

**Parameters**

* `dataId` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) dataset id to show in table

Returns **{type: ActionTypes.SHOW\_DATASET\_TABLE, dataId: dataId}**

#### toggleFilterAnimation

Start and end filter animation

* **ActionTypes**: [`ActionTypes.TOGGLE_FILTER_ANIMATION`](#actiontypes)
* **Updaters**: [`visStateUpdaters.toggleFilterAnimationUpdater`](/docs/api-reference/reducers/vis-state#visstateupdaterstogglefilteranimationupdater)

**Parameters**

* `idx` [**Number**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number) idx of filter

Returns **{type: ActionTypes.TOGGLE\_FILTER\_ANIMATION, idx: idx}**

#### toggleLayerForMap

Toggle visibility of a layer in a split map

* **ActionTypes**: [`ActionTypes.TOGGLE_LAYER_FOR_MAP`](#actiontypes)
* **Updaters**: [`visStateUpdaters.toggleLayerForMapUpdater`](/docs/api-reference/reducers/vis-state#visstateupdaterstogglelayerformapupdater)

**Parameters**

* `mapIndex` [**Number**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number) index of the split map
* `layerId` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) id of the layer

Returns **{type: ActionTypes.TOGGLE\_LAYER\_FOR\_MAP, mapIndex: any, layerId: any}**

#### updateAnimationTime

Reset animation

* **ActionTypes**: [`ActionTypes.UPDATE_ANIMATION_TIME`](#actiontypes)
* **Updaters**: [`visStateUpdaters.updateAnimationTimeUpdater`](/docs/api-reference/reducers/vis-state#visstateupdatersupdateanimationtimeupdater)

**Parameters**

* `value` [**Number**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number) Current value of the slider

Returns **{type: ActionTypes.UPDATE\_ANIMATION\_TIME, value: value}**

#### updateFilterAnimationSpeed

Change filter animation speed

* **ActionTypes**: [`ActionTypes.UPDATE_FILTER_ANIMATION_SPEED`](#actiontypes)
* **Updaters**: [`visStateUpdaters.updateFilterAnimationSpeedUpdater`](/docs/api-reference/reducers/vis-state#visstateupdatersupdatefilteranimationspeedupdater)

**Parameters**

* `idx` [**Number**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number) `idx` of filter
* `speed` [**Number**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number) `speed` to change it to. `speed` is a multiplier

Returns **{type: ActionTypes.UPDATE\_FILTER\_ANIMATION\_SPEED, idx: idx, speed: speed}**

#### updateLayerAnimationSpeed

update trip layer animation speed

* **ActionTypes**: [`ActionTypes.UPDATE_LAYER_ANIMATION_SPEED`](#actiontypes)
* **Updaters**: [`visStateUpdaters.updateLayerAnimationSpeedUpdater`](/docs/api-reference/reducers/vis-state#visstateupdatersupdatelayeranimationspeedupdater)

**Parameters**

* `speed` [**Number**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number) `speed` to change it to. `speed` is a multiplier

Returns **{type: ActionTypes.UPDATE\_LAYER\_ANIMATION\_SPEED, speed: speed}**

#### updateLayerBlending

Update layer blending mode

* **ActionTypes**: [`ActionTypes.UPDATE_LAYER_BLENDING`](#actiontypes)
* **Updaters**: [`visStateUpdaters.updateLayerBlendingUpdater`](/docs/api-reference/reducers/vis-state#visstateupdatersupdatelayerblendingupdater)

**Parameters**

* `mode` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) one of `additive`, `normal` and `subtractive`

Returns **{type: ActionTypes.UPDATE\_LAYER\_BLENDING, mode: mode}**

#### updateVisData

Add new dataset to `visState`, with option to load a map config along with the datasets

* **ActionTypes**: [`ActionTypes.UPDATE_VIS_DATA`](#actiontypes)
* **Updaters**: [`visStateUpdaters.updateVisDataUpdater`](/docs/api-reference/reducers/vis-state#visstateupdatersupdatevisdataupdater)

**Parameters**

* `datasets` **(**[**Array**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)**<**[**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)**> |** [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)**)** **\*required** datasets can be a dataset or an array of datasets Each dataset object needs to have `info` and `data` property.
  * `datasets.info` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) -info of a dataset
    * `datasets.info.id` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) id of this dataset. If config is defined, `id` should matches the `dataId` in config.
    * `datasets.info.label` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) A display name of this dataset
  * `datasets.data` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) **\*required** The data object, in a tabular format with 2 properties `fields` and `rows`
    * `datasets.data.fields` [**Array**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)**<**[**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)**>** **\*required** Array of fields,
      * `datasets.data.fields.name` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) **\*required** Name of the field,
    * `datasets.data.rows` [**Array**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)**<**[**Array**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)**>** **\*required** Array of rows, in a tabular format with `fields` and `rows`
* `options` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)
  * `options.centerMap` [**boolean**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean) `default: true` if `centerMap` is set to `true` kepler.gl will place the map view within the data points boundaries
  * `options.readOnly` [**boolean**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean) `default: false` if `readOnly` is set to `true` the left setting panel will be hidden
* `config` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) this object will contain the full kepler.gl instance configuration {mapState, mapStyle, visState}

Returns **{type: ActionTypes.UPDATE\_VIS\_DATA, datasets: datasets, options: options, config: config}**

### uiStateActions

Actions handled mostly by `uiState` reducer. They manage UI changes in the app, such as open and close side panel, switch between tabs in the side panel, open and close modal dialog for exporting data / images etc. It also manages which settings are selected during image and map export

#### addNotification

Add a notification to be displayed. Existing notification is going to be updated in case of matching ids.

* **ActionTypes**: [`ActionTypes.ADD_NOTIFICATION`](#actiontypes)
* **Updaters**: [`uiStateUpdaters.addNotificationUpdater`](/docs/api-reference/reducers/ui-state#uistateupdatersaddnotificationupdater)

**Parameters**

* `notification` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) The `notification` object to be added

#### cleanupExportImage

Delete cached export image

* **ActionTypes**: [`ActionTypes.CLEANUP_EXPORT_IMAGE`](#actiontypes)
* **Updaters**: [`uiStateUpdaters.cleanupExportImage`](/docs/api-reference/reducers/ui-state#uistateupdaterscleanupexportimage)

#### hideExportDropdown

Hide side panel header dropdown, activated by clicking the share link on top of the side panel

* **ActionTypes**: [`ActionTypes.HIDE_EXPORT_DROPDOWN`](#actiontypes)
* **Updaters**: [`uiStateUpdaters.hideExportDropdownUpdater`](/docs/api-reference/reducers/ui-state#uistateupdatershideexportdropdownupdater)

#### openDeleteModal

Toggle active map control panel

* **ActionTypes**: [`ActionTypes.OPEN_DELETE_MODAL`](#actiontypes)
* **Updaters**: [`uiStateUpdaters.openDeleteModalUpdater`](/docs/api-reference/reducers/ui-state#uistateupdatersopendeletemodalupdater)

**Parameters**

* `datasetId` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) `id` of the dataset to be deleted

#### removeNotification

Remove a notification

* **ActionTypes**: [`ActionTypes.REMOVE_NOTIFICATION`](#actiontypes)
* **Updaters**: [`uiStateUpdaters.removeNotificationUpdater`](/docs/api-reference/reducers/ui-state#uistateupdatersremovenotificationupdater)

**Parameters**

* `id` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) `id` of the notification to be removed

#### setExportData

Whether to including data in map config, toggle between `true` or `false`

* **ActionTypes**: [`ActionTypes.SET_EXPORT_DATA`](#actiontypes)
* **Updaters**: [`uiStateUpdaters.setExportDataUpdater`](/docs/api-reference/reducers/ui-state#uistateupdaterssetexportdataupdater)

#### setExportDataType

Set data format for exporting data

* **ActionTypes**: [`ActionTypes.SET_EXPORT_DATA_TYPE`](#actiontypes)
* **Updaters**: [`uiStateUpdaters.setExportDataTypeUpdater`](/docs/api-reference/reducers/ui-state#uistateupdaterssetexportdatatypeupdater)

**Parameters**

* `dataType` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) one of `'text/csv'`

#### setExportFiltered

Whether to export filtered data, `true` or `false`

* **ActionTypes**: [`ActionTypes.SET_EXPORT_FILTERED`](#actiontypes)
* **Updaters**: [`uiStateUpdaters.setExportFilteredUpdater`](/docs/api-reference/reducers/ui-state#uistateupdaterssetexportfilteredupdater)

**Parameters**

* `payload` [**boolean**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean) set `true` to only export filtered data

#### setExportImageDataUri

Set `exportImage.setExportImageDataUri` to a dataUri

* **ActionTypes**: [`ActionTypes.SET_EXPORT_IMAGE_DATA_URI`](#actiontypes)
* **Updaters**: [`uiStateUpdaters.setExportImageDataUri`](/docs/api-reference/reducers/ui-state#uistateupdaterssetexportimagedatauri)

**Parameters**

* `dataUri` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) export image data uri

#### setExportImageSetting

Set `exportImage` settings: ratio, resolution, legend

* **ActionTypes**: [`ActionTypes.SET_EXPORT_IMAGE_SETTING`](#actiontypes)
* **Updaters**: [`uiStateUpdaters.setExportImageSetting`](/docs/api-reference/reducers/ui-state#uistateupdaterssetexportimagesetting)

**Parameters**

* `newSetting` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) {ratio: '1x'}

#### setExportSelectedDataset

Set selected dataset for export

* **ActionTypes**: [`ActionTypes.SET_EXPORT_SELECTED_DATASET`](#actiontypes)
* **Updaters**: [`uiStateUpdaters.setExportSelectedDatasetUpdater`](/docs/api-reference/reducers/ui-state#uistateupdaterssetexportselecteddatasetupdater)

**Parameters**

* `datasetId` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) dataset id

#### setUserMapboxAccessToken

Whether we export a mapbox access token used to create a single map html file

* **ActionTypes**: [`ActionTypes.SET_USER_MAPBOX_ACCESS_TOKEN`](#actiontypes)
* **Updaters**: [`uiStateUpdaters.setUserMapboxAccessTokenUpdater`](/docs/api-reference/reducers/ui-state#uistateupdaterssetusermapboxaccesstokenupdater)

**Parameters**

* `payload` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) mapbox access token

#### showExportDropdown

Hide and show side panel header dropdown, activated by clicking the share link on top of the side panel

* **ActionTypes**: [`ActionTypes.SHOW_EXPORT_DROPDOWN`](#actiontypes)
* **Updaters**: [`uiStateUpdaters.showExportDropdownUpdater`](/docs/api-reference/reducers/ui-state#uistateupdatersshowexportdropdownupdater)

**Parameters**

* `id` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) id of the dropdown

#### startExportingImage

Set `exportImage.exporting` to true

* **ActionTypes**: [`ActionTypes.START_EXPORTING_IMAGE`](#actiontypes)
* **Updaters**: [`uiStateUpdaters.startExportingImage`](/docs/api-reference/reducers/ui-state#uistateupdatersstartexportingimage)

#### toggleMapControl

Toggle active map control panel

* **ActionTypes**: [`ActionTypes.TOGGLE_MAP_CONTROL`](#actiontypes)
* **Updaters**: [`uiStateUpdaters.toggleMapControlUpdater`](/docs/api-reference/reducers/ui-state#uistateupdaterstogglemapcontrolupdater)

**Parameters**

* `panelId` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) map control panel id, one of the keys of: [`DEFAULT_MAP_CONTROLS`](#default_map_controls)

#### toggleModal

Show and hide modal dialog

* **ActionTypes**: [`ActionTypes.TOGGLE_MODAL`](#actiontypes)
* **Updaters**: [`uiStateUpdaters.toggleModalUpdater`](/docs/api-reference/reducers/ui-state#uistateupdaterstogglemodalupdater)

**Parameters**

* `id` **(**[**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) **| null)** id of modal to be shown, null to hide modals. One of:- [`DATA_TABLE_ID`](https://github.com/keplergl/kepler.gl/blob/master/docs/api-reference/constants/default-settings.md#data_table_id)
  * [`DELETE_DATA_ID`](https://github.com/keplergl/kepler.gl/blob/master/docs/api-reference/constants/default-settings.md#delete_data_id)
  * [`ADD_DATA_ID`](https://github.com/keplergl/kepler.gl/blob/master/docs/api-reference/constants/default-settings.md#add_data_id)
  * [`EXPORT_IMAGE_ID`](https://github.com/keplergl/kepler.gl/blob/master/docs/api-reference/constants/default-settings.md#export_image_id)
  * [`EXPORT_DATA_ID`](https://github.com/keplergl/kepler.gl/blob/master/docs/api-reference/constants/default-settings.md#export_data_id)
  * [`ADD_MAP_STYLE_ID`](https://github.com/keplergl/kepler.gl/blob/master/docs/api-reference/constants/default-settings.md#add_map_style_id)

#### toggleSidePanel

Toggle active side panel

* **ActionTypes**: [`ActionTypes.TOGGLE_SIDE_PANEL`](#actiontypes)
* **Updaters**: [`uiStateUpdaters.toggleSidePanelUpdater`](/docs/api-reference/reducers/ui-state#uistateupdaterstogglesidepanelupdater)

**Parameters**

* `id` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) id of side panel to be shown, one of `layer`, `filter`, `interaction`, `map`

### rootActions

Root actions managers adding and removing instances in root reducer. Under-the-hood, when a `KeplerGl` component is mounted or unmounted, it will automatically calls these actions to add itself to the root reducer. However, sometimes the data is ready before the component is registered in the reducer, in this case, you can manually call these actions or the corresponding updater to add it to the reducer.

#### deleteEntry

Delete an instance from `keplerGlReducer`. This action is called under-the-hood when a `KeplerGl` component is **un-mounted** to the dom. If `mint` is set to be `true` in the component prop, the instance state will be deleted from the root reducer. Otherwise, the root reducer will keep the instance state and later transfer it to a newly mounted component with the same `id`

* **ActionTypes**: [`ActionTypes.DELETE_ENTRY`](#actiontypes)
* **Updaters**:

**Parameters**

* `id` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) the id of the instance to be deleted

#### registerEntry

Add a new kepler.gl instance in `keplerGlReducer`. This action is called under-the-hood when a `KeplerGl` component is **mounted** to the dom. Note that if you dispatch actions such as adding data to a kepler.gl instance before the React component is mounted, the action will not be performed. Instance reducer can only handle actions when it is instantiated.

* **ActionTypes**: [`ActionTypes.REGISTER_ENTRY`](#actiontypes)
* **Updaters**:

**Parameters**

* `payload` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)
  * `payload.id` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) **\*required** The id of the instance
  * `payload.mint` [**boolean**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean) Whether to use a fresh empty state, when `mint: true` it will *always* load a fresh state when the component is re-mounted. When `mint: false` it will register with existing instance state under the same `id`, when the component is unmounted then mounted again. Default: `true`
  * `payload.mapboxApiAccessToken` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) mapboxApiAccessToken to be saved in `map-style` reducer.
  * `payload.mapboxApiUrl` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) mapboxApiUrl to be saved in `map-style` reducer.
  * `payload.mapStylesReplaceDefault` [**Boolean**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean) mapStylesReplaceDefault to be saved in `map-style` reducer.

#### renameEntry

Rename an instance in the root reducer, keep its entire state

* **ActionTypes**: [`ActionTypes.RENAME_ENTRY`](#actiontypes)
* **Updaters**:

**Parameters**

* `oldId` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) **\*required** old id
* `newId` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) **\*required** new id

### mapStateActions

Actions handled mostly by `mapState` reducer. They manage map viewport update, toggle between 2d and 3d map, toggle between single and split maps.

#### fitBounds

Fit map viewport to bounds

* **ActionTypes**: [`ActionTypes.FIT_BOUNDS`](#actiontypes)
* **Updaters**: [`mapStateUpdaters.fitBoundsUpdater`](/docs/api-reference/reducers/map-state#mapstateupdatersfitboundsupdater)

**Parameters**

* `bounds` [**Array**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)**<**[**Number**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)**>** as `[lngMin, latMin, lngMax, latMax]`

**Examples**

```javascript
import {fitBounds} from '@kepler.gl/actions';
this.props.dispatch(fitBounds([-122.23, 37.127, -122.11, 37.456]));
```

#### togglePerspective

Toggle between 3d and 2d map.

* **ActionTypes**: [`ActionTypes.TOGGLE_PERSPECTIVE`](#actiontypes)
* **Updaters**: [`mapStateUpdaters.togglePerspectiveUpdater`](/docs/api-reference/reducers/map-state#mapstateupdaterstoggleperspectiveupdater)

**Examples**

```javascript
import {togglePerspective} from '@kepler.gl/actions';
this.props.dispatch(togglePerspective());
```

#### toggleSplitMap

Toggle between single map or split maps

* **ActionTypes**: [`ActionTypes.TOGGLE_SPLIT_MAP`](#actiontypes)
* **Updaters**: [`mapStateUpdaters.toggleSplitMapUpdater`](/docs/api-reference/reducers/map-state#mapstateupdaterstogglesplitmapupdater), [`uiStateUpdaters.toggleSplitMapUpdater`](/docs/api-reference/reducers/ui-state#uistateupdaterstogglesplitmapupdater), [`visStateUpdaters.toggleSplitMapUpdater`](/docs/api-reference/reducers/vis-state#visstateupdaterstogglesplitmapupdater)

**Parameters**

* `index` [**Number**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)**?** index is provided, close split map at index

**Examples**

```javascript
import {toggleSplitMap} from '@kepler.gl/actions';
this.props.dispatch(toggleSplitMap());
```

#### updateMap

Update map viewport

* **ActionTypes**: [`ActionTypes.UPDATE_MAP`](#actiontypes)
* **Updaters**: [`mapStateUpdaters.updateMapUpdater`](/docs/api-reference/reducers/map-state#mapstateupdatersupdatemapupdater)

**Parameters**

* `viewport` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) viewport object container one or any of these properties `width`, `height`, `latitude` `longitude`, `zoom`, `pitch`, `bearing`, `dragRotate`
  * `viewport.width` [**Number**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)**?** Width of viewport
  * `viewport.height` [**Number**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)**?** Height of viewport
  * `viewport.zoom` [**Number**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)**?** Zoom of viewport
  * `viewport.pitch` [**Number**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)**?** Camera angle in degrees (0 is straight down)
  * `viewport.bearing` [**Number**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)**?** Map rotation in degrees (0 means north is up)
  * `viewport.latitude` [**Number**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)**?** Latitude center of viewport on map in mercator projection
  * `viewport.longitude` [**Number**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)**?** Longitude Center of viewport on map in mercator projection
  * `viewport.dragRotate` [**boolean**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)**?** Whether to enable drag and rotate map into perspective viewport

**Examples**

```javascript
import {updateMap} from '@kepler.gl/actions';
this.props.dispatch(
  updateMap({latitude: 37.75043, longitude: -122.34679, width: 800, height: 1200})
);
```

### layerColorUIChange

Set the color palette ui for layer color

* **ActionTypes**: [`ActionTypes.LAYER_COLOR_UI_CHANGE`](#actiontypes)
* **Updaters**: [`visStateUpdaters.layerColorUIChangeUpdater`](/docs/api-reference/reducers/vis-state#visstateupdaterslayercoloruichangeupdater)

**Parameters**

* `oldLayer` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) layer to be updated
* `prop` [**String**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) which color prop
* `newConfig` [**object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) to be merged

### setExportMapFormat

Set the export map format (html, json)

* **ActionTypes**: [`ActionTypes.SET_EXPORT_MAP_FORMAT`](#actiontypes)
* **Updaters**: [`uiStateUpdaters.setExportMapFormatUpdater`](/docs/api-reference/reducers/ui-state#uistateupdaterssetexportmapformatupdater)

**Parameters**

* `payload` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) map format


# Cloud providers

The kepler.gl application does not have a backend, however it offers integration point for optional commercial backends. Each backend can integrate with kepler by adding a "cloud provider" object to kepler's global list of cloud providers.

These objects must implement certain minimal set of methods, and can optionally implement others, depending on the capability of the backend.

The set of methods available for cloud providers to implement is subject to change as new features are added to the front-end.

## Cloud Provider Object

A "cloud provider" object provides:

* a name and an icon
* any service specific methods (such as `uploadFile`)
* a set of oauth2 methods to plug into the authentication flow and get access tokens

Cloud-providers providers can implement the following properties

| Field/method        | Description                                                          | Required? |
| ------------------- | -------------------------------------------------------------------- | --------- |
| `name`              | Name of the provider                                                 | required  |
| `displayName`       | Display name                                                         |           |
| `icon`              | React Element to render as Icon                                      |           |
| `thumbnail`         | Size of the thumbnail image of the map that required by the provider |           |
| `hasPrivateStorage` | To participate in kepler's build-in private map saving function      | required  |
| `hasSharingUrl`     | To participate in kepler's build-in share map via URL function       | required  |
| `getShareUrl`       | To show user the shared Url of the map                               |           |
| `getMapUrl`         | To update browser location once a map has been saved / loaded        |           |
| `getAccessToken`    | To participate in kepler's built-in oauth login routes               |           |
| `getUserName`       | To display user name of the logged in user                           |           |
| `login`             | Method called to perform user login                                  | required  |
| `logout`            | Method called to logout an user                                      | required  |
| `uploadMap`         | Method called to upload map to storage                               | required  |
| `listMaps`          | Method called to load a catalog of maps saved by the current user    | required  |
| `downloadMap`       | Method called to download a specific map                             | required  |

## Adding a new Cloud Provider

An instance of the provider is added to array of cloud providers in the file `src/cloud-providers/providers.js` then passed to kepler.gl demo app. An example provider: [Dropbox Provider](https://github.com/keplergl/kepler.gl/blob/master/examples/demo-app/src/cloud-providers/dropbox-provider.js)

```js
import {Provider} from '@kepler.gl/cloud-providers';

class MyProvider extends Provider {
    constructor() {
        this.name = 'foo';
        this.displayName = 'My Provider';
    }

    // ... other required methods below
}

const myProvider = new MyProvider();
const App = () =>
    <KeplerGl
        mapboxApiAccessToken={CLOUD_PROVIDERS_CONFIGURATION.MAPBOX_TOKEN}
        id="map"
        cloudProviders={[myProvider]}
    />
```

## Cloud Provider Instance Fields and Methods

See [Cloud Provider API](/docs/api-reference/cloud-providers/cloud-provider)


# Provider

#### Table of Contents

* [Provider](#provider)
  * [downloadMap](#downloadmap)
  * [getAccessToken](#getaccesstoken)
  * [getMapUrl](#getmapurl)
  * [getShareUrl](#getshareurl)
  * [getUserName](#getusername)
  * [hasPrivateStorage](#hasprivatestorage)
  * [hasSharingUrl](#hassharingurl)
  * [listMaps](#listmaps)
  * [login](#login)
  * [logout](#logout)
  * [uploadMap](#uploadmap)
* [MapResponse](#mapresponse)
* [Viz](#viz)

### Provider

The default provider class

**Parameters**

* `props` [**object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)
  * `props.name` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)
  * `props.displayName` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)
  * `props.icon` **ReactElement** React element
  * `props.thumbnail` [**object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) thumbnail size object
    * `props.thumbnail.width` [**number**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number) thumbnail width in pixels
    * `props.thumbnail.height` [**number**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number) thumbnail height in pixels

**Examples**

```javascript
const myProvider = new Provider({
 name: 'foo',
 displayName: 'Foo Storage'
 icon: Icon,
 thumbnail: {width: 300, height: 200}
})
```

#### downloadMap

This method will be called when user select a map to load from the storage map viewer

**Parameters**

* `loadParams` **any** the loadParams property of each visualization object

**Examples**

```javascript
async downloadMap(loadParams) {
 const mockResponse = {
   map: {
     datasets: [],
     config: {},
     info: {
       app: 'kepler.gl',
      created_at: '',
      title: 'test map',
       description: 'Hello this is my test dropbox map'
     }
   },
   // pass csv here if your provider currently only support save / load file as csv
   format: 'keplergl'
 };

 return mockResponse;
}
```

Returns [**MapResponse**](#mapresponse) the map object containing dataset config info and format option

#### getAccessToken

This method is called to determine whether user already logged in to this provider

Returns [**boolean**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean) true if a user already logged in

#### getMapUrl

This method is called by kepler.gl demo app to pushes a new location to history, becoming the current location.

**Parameters**

* `fullURL` [**boolean**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean) Whether to return the full url with domain, or just the location (optional, default `true`)

Returns [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) mapUrl

#### getShareUrl

This method is called after user share a map, to display the share url.

**Parameters**

* `fullUrl` [**boolean**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean) Whether to return the full url with domain, or just the location (optional, default `false`)

Returns [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) shareUrl

#### getUserName

This method is called to get the user name of the current user. It will be displayed in the cloud provider tile.

Returns [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) the user name of the logged in user

#### hasPrivateStorage

Whether this provider support upload map to a private storage. If truthy, user will be displayed with the storage save icon on the top right of the side bar.

Returns [**boolean**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)

#### hasSharingUrl

Whether this provider support share map via a public url, if truthy, user will be displayed with a share map via url under the export map option on the top right of the side bar

Returns [**boolean**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)

#### listMaps

This method is called to get a list of maps saved by the current logged in user.

**Examples**

```javascript
async listMaps() {
   return [
     {
       id: 'a',
       title: 'My map',
       description: 'My first kepler map',
       imageUrl: 'http://',
       updatedAt: 1582677787000,
       privateMap: false,
       loadParams: {}
     }
   ];
 }
```

Returns [**Array**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)**<**[**Viz**](#viz)**>** an array of Viz objects

#### login

This method will be called when user click the login button in the cloud provider tile. Upon login success, `onCloudLoginSuccess` has to be called to notify kepler.gl UI

**Parameters**

* `onCloudLoginSuccess` [**function**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function) callbacks to be called after login success

#### logout

This method will be called when user click the logout button under the cloud provider tile. Upon login success, `onCloudLoginSuccess` has to be called to notify kepler.gl UI

**Parameters**

* `onCloudLogoutSuccess` [**function**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function) callbacks to be called after logout success

#### uploadMap

This method will be called to upload map for saving and sharing. Kepler.gl will package map data, config, title, description and thumbnail for upload to storage. With the option to overwrite already saved map, and upload as private or public map.

**Parameters**

* `param` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)
  * `param.mapData` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) the map object
    * `param.mapData.map` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) {datasets. config, info: {title, description}}
    * `param.mapData.thumbnail` [**Blob**](https://developer.mozilla.org/docs/Web/API/Blob) A thumbnail of current map. thumbnail size can be defined by provider by this.thumbnail
  * `param.options` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) (optional, default `{}`)
    * `param.options.overwrite` [**boolean**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean) whether user choose to overwrite already saved map under the same name
    * `param.options.isPublic` [**boolean**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean) whether user wish to share the map with others. if isPublic is truthy, kepler will call this.getShareUrl() to display an URL they can share with others

### MapResponse

The returned object of `downloadMap`. The response object should contain: datasets: \[], config: {}, and info: {} each dataset object should be {info: {id, label}, data: {...}} to inform how kepler should process your data object, pass in `format`

Type: [Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)

#### Properties

* `map` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)
  * `map.datasets` [**Array**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)**<**[**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)**>**
  * `map.config` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)
  * `map.info` [**Object**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)
* `format` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) one of 'csv': csv file string, 'geojson': geojson object, 'row': row object, 'keplergl': datasets array saved using KeplerGlSchema.save

### Viz

Type: [Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)

#### Properties

* `id` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) An unique id
* `title` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) The title of the map
* `description` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) The description of the map
* `imageUrl` [**string**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) The imageUrl of the map
* `lastModification` [**number**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number) An epoch timestamp in milliseconds
* `privateMap` [**boolean**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean) Optional, whether if this map is private to the user, or can be accessed by others via URL
* `loadParams` **any** A property to be passed to `downloadMap`


# Custom theme

You can pass theme name or object used to customize Kepler.gl style. Kepler.gl provide an `'light'` theme besides the default 'dark' theme. When pass in a theme object Kepler.gl will use the value passed as input to overwrite values from [theme](https://github.com/keplergl/kepler.gl/blob/master/src/styles/src/base.ts).

```js
import KeplerGl from '@kepler.gl/components';

const Map = props => (
  <KeplerGl
    id="foo"
    width={width}
    mapboxApiAccessToken={token}
    height={height}
    theme="light"
  />
);
```

### Available Themes

| theme            |                                                                                                                                              |
| ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| `dark` (default) | ![Screen Shot 2020-03-11 at 2 11 45 PM](https://user-images.githubusercontent.com/3605556/76464370-78c13080-63a2-11ea-977e-9678a25580f9.png) |
| `light`          | ![Screen Shot 2020-03-11 at 2 10 15 PM](https://user-images.githubusercontent.com/3605556/76464360-74951300-63a2-11ea-82fe-3d055dc0b8dd.png) |
| `base`           | ![Screen Shot 2020-03-11 at 2 10 49 PM](https://user-images.githubusercontent.com/3605556/76464366-78289a00-63a2-11ea-944b-e5a9208bacde.png) |


# Localization

Kepler.gl supports localization through [react-intl](https://github.com/formatjs/react-intl). Locale is determined by `uiState.locale` value. Current supported languages are:

| locale code | Language   | Default? |
| ----------- | ---------- | -------- |
| en          | English    | default  |
| fi          | Finnish    |          |
| pt          | Portuguese |          |
| ca          | Catalan    |          |
| es          | Spanish    |          |
| ja          | Japanese   |          |
| cn          | Chinese    |          |
| ru          | Русский    |          |

## Changing default language

By default the first language is English `en`. The default language can be changed by giving locale value to uiState:

```js
import {combineReducers} from 'redux';
import keplerGlReducer from '@kepler.gl/reducers';
import {LOCALE_CODES} from '@kepler.gl/localization';

const customizedKeplerGlReducer = keplerGlReducer.initialState({
  uiState: {
    // use Finnish locale
    locale: LOCALE_CODES.fi
  }
});

const reducers = combineReducers({
  keplerGl: customizedKeplerGlReducer,
  app: appReducer
});
```

## Adding new language

Let's say we want to add the Swedish language to kepler.gl. Easiest way to add translation of new language is to follow these 3 steps:

* Find out the [language code](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) for Swedish: `sv`
* Add new translation file `src/localization/translations/sv.js` by copying `src/localization/translations/en.js` and translating the strings
* Update *LOCALES* in `src/localization/locales.js` to include new language translation:

  ```javascript
  export const LOCALES = {
    en : 'English',
    fi : 'Suomi',
    pt: 'Português',
    // add Swedish language
    sv: 'Svenska'
  }
  ```

## Modify default translation or add new translation

the `localeMessages` prop of `KeplerGl` takes additional translations and merge with default translation.

#### Example 1. Update default translation

To update the english translation of `layerManager.addData`, pass `localeMessages` like this.

```javascript
const localeMessages = {
  en: {
    ['layerManager.addData']: 'Add Data to Layer'
  }
};

const App = () => (
    <KeplerGl
      id="map"
      localeMessages={localeMessages}
      mapboxApiAccessToken={Token}
    />
);
```

#### Example 2. Pass additional translation

Sometimes together with dependency injection, you might need to add additional translations to the customized component. For example, adding an additional `settings` panel in the side panel, you will need to provide a translation for the panel name assigned to `sidebar.panels.settings`

```javascript
const localeMessages = {
  en: {
    ['sidebar.panels.settings']: 'Settings'
  }
};

const App = () => (
    <KeplerGl
      id="map"
      localeMessages={localeMessages}
      mapboxApiAccessToken={Token}
    />
);
```


# Jupyter Notebook

## Jupyter Notebook

### kepler.gl for Jupyter User Guide

#### Table of contents

* [Install](#install)
* [1. Load kepler.gl Map](#1-load-keplergl-map)
  * [`KeplerGl()`](#keplergl)
* [2. Add Data](#2-add-data)
  * [`.add_data()`](#add_data)
  * [`.data`](#data)
* [3. Data Format](#3-data-format)
  * [`CSV`](#csv)
  * [`GeoJSON`](#geojson)
  * [`DataFrame`](#dataframe)
  * [`GeoDataFrame`](#geodataframe)
  * [`WKT`](#wkt)
* [4. Customize the map](#4-customize-the-map)
* [5. Save and load config](#5-save-and-load-config)
  * [`.config`](#config)
* [6. Match config with data](#6-match-config-with-data)
* [7. Save Map](#7-save-map)
  * [`.save_to_html()`](#save_to_html)
  * [`._repr_html_()`](#_repr_html_)
* [Demo Notebooks](#demo-notebooks)
* [FAQ & Troubleshoot](#faq--troubleshoot)

### Install

#### Prerequisites

* Python >= 3
* ipywidgets >= 7.0.0

To install use pip:

```bash
$ pip install keplergl
```

If you're on Mac, used `pip install`, and you're running Notebook 5.3 and above, you don't need to run the following:

```bash
$ jupyter nbextension install --py --sys-prefix keplergl # can be skipped for notebook 5.3 and above
$ jupyter nbextension enable --py --sys-prefix keplergl # can be skipped for notebook 5.3 and above
```

If you are using Jupyter Lab, you will also need to install the JupyterLab extension. This require [node](https://nodejs.org/en/download/package-manager/#macos) `> 10.15.0`

If you use [Homebrew](https://brew.sh/) on Mac:

```bash
$ brew install node@10
```

Then install jupyter labextension.

```bash
$ jupyter labextension install @jupyter-widgets/jupyterlab-manager keplergl-jupyter
```

#### Prerequisites for JupyterLab

* Node > 10.15.0
* Python 3
* JupyterLab>=1.0.0

### 1. Load keplergl map

#### `KeplerGl()`

* Input:
  * **`height`** *optional* default: `400`

    Height of the map display
  * **`data`** `dict` *optional*

    Datasets as a dictionary, key is the name of the dataset. Read more on [Accepted data format](#3-data-format)
  * **`use_arrow`** `bool` *optional* default: `False`

    Allow load and render data faster using GeoArrow
  * **`config`** `dict` *optional*

    Map config as a dictionary. The `dataId` in the layer and filter settings should match the `name` of the dataset they are created under
  * **`show_docs`** `bool` *optional*

    By default, the User Guide URL (<https://docs.kepler.gl/docs/keplergl-jupyter>) will be printed when a map is created. To hide the User Guide URL, set `show_docs=False`.

The following command will load kepler.gl widget below a cell. **The map object created here is `map_1` it will be used throughout the code example in this doc.**

```python
# Load an empty map
from keplergl import KeplerGl
map_1 = KeplerGl()
map_1
```

![empty map](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/jupyter_empty_map.png)

You can also create the map and pass in the data or data and config at the same time. Follow the instruction to [match config with data](#6-match-config-with-data)

```python
# Load a map with data and config and height
from keplergl import KeplerGl
map_2 = KeplerGl(height=400, data={"data_1": my_df}, config=config)
map_2
```

![Load map with data and config](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/jupyter_widget.png)

### 2. Add Data

#### `.add_data()`

* Inputs
  * **`data`** *required* CSV, GeoJSON or DataFrame. Read more on [Accepted data format](#3-data-format)
  * **`name`** *required* Name of the data entry.
  * **`use_arrow`** *optional* Allow load and render data faster using GeoArrow.

`name` of the dataset will be the saved to the `dataId` property of each `layer`, `filter` and `interactionConfig` in the config.

kepler.gl expected the data to be **CSV**, **GeoJSON**, **DataFrame** or **GeoDataFrame**. You can call **`add_data`** multiple times to add multiple datasets to kepler.gl

```python
# DataFrame
df = pd.read_csv('hex-data.csv')
map_1.add_data(data=df, name='data_1')

# CSV
with open('csv-data.csv', 'r') as f:
    csvData = f.read()
map_1.add_data(data=csvData, name='data_2')

# GeoJSON as string
with open('sf_zip_geo.json', 'r') as f:
    geojson = f.read()

map_1.add_data(data=geojson, name='geojson')
```

![Add data to map](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/jupyter_add_data.png)

#### `.data`

Print the current data added to the map. As a `Dict`

```python
map_1.data
# {'data_1': 'hex_id,value\n89283082c2fffff,64\n8928308288fffff,73\n89283082c07ffff,65\n89283082817ffff,74\n89283082c3bffff,66\n8...`,
#  'data_3': 'location, lat, lng, name\n..',
#  'data_3': '{"type": "FeatureCollecti...'}
```

### 3. Data Format

kepler.gl supports **CSV**, **GeoJSON**, Pandas **DataFrame** or GeoPandas **GeoDataFrame**.

#### `CSV`

You can create a `CSV` string by reading from a CSV file.

```python
with open('csv-data.csv', 'r') as f:
    csvData = f.read()
# csvData = "hex_id,value\n89283082c2fffff,64\n8928308288fffff,73\n89283082c07ffff,65\n89283082817ffff,74\n89283082c3bffff,66\n8..."
map_1.add_data(data=csvData, name='data_2')
```

#### `GeoJSON`

According to [GeoJSON Specification (RFC 7946)](https://tools.ietf.org/html/rfc7946): GeoJSON is a format for encoding a variety of geographic data structures. A GeoJSON object may represent a region of space (a `Geometry`), a spatially bounded entity (a Feature), or a list of Features (a `FeatureCollection`). GeoJSON supports the following geometry types: `Point`, `LineString`, `Polygon`, `MultiPoint`, `MultiLineString`, `MultiPolygon`, and `GeometryCollection`. Features in GeoJSON contain a Geometry object and additional properties, and a FeatureCollection contains a list of Features.

kepler.gl supports all the GeoJSON types above excepts `GeometryCollection`. You can pass in either a single [`Feature`](https://tools.ietf.org/html/rfc7946#section-3.2) or a [`FeatureCollection`](https://tools.ietf.org/html/rfc7946#section-3.3). You can format the `GeoJSON` either as a `string` or a `dict` type

```python
feature = {
    "type": "Feature",
    "properties": {"name": "Coors Field"},
    "geometry": {"type": "Point", "coordinates": [-104.99404, 39.75621]}
}

featureCollection = {
    "type": "FeatureCollection",
    "features": [{
        "type": "Feature",
        "geometry": {"type": "Point", "coordinates": [102.0, 0.5]},
        "properties": {"prop0": "value0"}
    }]
}

map_1.add_data(data=feature, name="feature")
map_1.add_data(data=featureCollection, name="feature_collection")
```

Geometries (Polygons, LindStrings) can be embedded into CSV or DataFrame with a [`GeoJSON`](https://tools.ietf.org/html/rfc7946) Json string. Use the `geometry` property of a [`Feature`](https://tools.ietf.org/html/rfc7946#section-3.2), which includes `type` and `coordinates`.

```python
# GeoJson Feature geometry
geometryString = {
    'type': 'Polygon',
    'coordinates': [[[-74.158491,40.835947],[-74.148473,40.834522],[-74.142598,40.833128],[-74.151923,40.832074],[-74.158491,40.835947]]]
}

# create json string
json_str = json.dumps(geometryString)

# create data frame
df_with_geometry = pd.DataFrame({
    'id': [1],
    'geometry_string': [json_str]
})

# add to map
map_1.add_data(df_with_geometry, "df_with_geometry")
```

#### `DataFrame`

kepler.gl accepts [pandas.DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html)

```python
df = pd.DataFrame(
    {'City': ['Buenos Aires', 'Brasilia', 'Santiago', 'Bogota', 'Caracas'],
     'Latitude': [-34.58, -15.78, -33.45, 4.60, 10.48],
     'Longitude': [-58.66, -47.91, -70.66, -74.08, -66.86]})

w1.add_data(data=df, name='cities')
```

#### `GeoDataFrame`

kepler.gl accepts [geopandas.GeoDataFrame](https://geopandas.readthedocs.io/en/latest/data_structures.html#geodataframe), it automatically converts the current `geometry` column from shapely to wkt string and re-projects geometries to latitude and longitude (EPSG:4326) if the active `geometry` column is in a different projection.

```python
url = 'http://eric.clst.org/assets/wiki/uploads/Stuff/gz_2010_us_040_00_500k.json'
country_gdf = geopandas.read_file(url)
w1.add_data(data=country_gdf, name="state")
```

![US state](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/jupyter_geodataframe.png)

#### `WKT`

You can embed geometries (Polygon, LineStrings etc) into CSV or DataFrame using [`WKT`](https://dev.mysql.com/doc/refman/5.7/en/gis-data-formats.html#gis-wkt-format)

```python
# WKT
wkt_str = 'POLYGON ((-74.158491 40.835947, -74.130031 40.819962, -74.148818 40.830916, -74.151923 40.832074, -74.158491 40.835947))'

df_w_wkt = pd.DataFrame({
    'id': [1],
    'wkt_string': [wkt_str]
})

map_1.add_data(df_w_wkt, "df_w_wkt")
```

### 4. Customize the map

Interact with kepler.gl and customize layers and filters. Map data and config will be stored locally to the widget state. To make sure the map state is saved, select `Widgets > Save Notebook Widget State`, before shutting down the kernel.

![Map interaction](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/jupyter_custom_map.gif)

### 5. Save and load config

#### `.config`

you can print your current map configuration at any time in the notebook

```python
map_1.config
## {u'config': {u'mapState': {u'bearing': 2.6192893401015205,
#  u'dragRotate': True,
#   u'isSplit': False,
#   u'latitude': 37.76209132041332,
#   u'longitude': -122.42590232651203,
```

When the map is final, you can copy this config and load it later to reproduce the same map. Follow the instruction to [match config with data](#6-match-config-with-data).

**Apply config to a map:**

1. Directly apply config to the map.

```python
config = {
    'version': 'v1',
    'config': {
        'mapState': {
            'latitude': 37.76209132041332,
            'longitude': -122.42590232651203,
            'zoom': 12.32053899007826
        }
        ...
    }
},
map_1.add_data(data=df, name='data_1')
map_1.config = config
```

2. Load it when creating the map

```python
map_1 = KeplerGl(height=400, data={'data_1': my_df}, config=config)
```

If want to load the map next time with this saved config, the easiest way to do is to save the it to a file and use the magic command **%run** to load it w/o cluttering up your notebook.

```python
# Save map_1 config to a file
with open('hex_config.py', 'w') as f:
   f.write('config = {}'.format(map_1.config))

# load the config
%run hex_config.py
```

### 6. Match config with data

All layers, filters and tooltips are associated with a specific dataset. Therefore the `data` and `config` in the map has to be able to match each other. The `name` of the dataset is assigned to:

* `dataId` of `layer.config`,
* `dataId` of `filter`
* key in `interactionConfig.tooltip.fieldToShow`.

![Connect data and config](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/jupyter_connect_data_w_config.png)

You can use the same config on another dataset with the same name and schema.

### 7. Save Map

When you click in the map and change settings, config is saved to widget state. Closing the notebook and reopen it will reload current map. However, you need to manually select `Widget > Save Notebook Widget State` before shut downing the kernel to make sure it will be reloaded.

![Save Widget State](https://d1a3f4spazzrp4.cloudfront.net/kepler.gl/documentation/jupyter_save_state.png)

#### `.save_to_html()`

* input
  * **`data`**: *optional* A data dictionary {"name": data}, if not provided, will use current map data
  * **`config`**: *optional* map config dictionary, if not provided, will use current map config
  * **`file_name`**: *optional* the html file name, default is `keplergl_map.html`
  * **`read_only`**: *optional* if `read_only` is `True`, hide side panel to disable map customization

You can export your current map as an interactive html file.

```python
# this will save current map
map_1.save_to_html(file_name='first_map.html')

# this will save map with provided data and config
map_1.save_to_html(data={'data_1': df}, config=config, file_name='first_map.html')

# this will save map with the interaction panel disabled
map_1.save_to_html(file_name='first_map.html', read_only=True)
```

#### `._repr_html_()`

* input
  * **`data`**: *optional* A data dictionary {"name": data}, if not provided, will use current map data
  * **`config`**: *optional* map config dictionary, if not provided, will use current map config
  * **`read_only`**: *optional* if `read_only` is `True`, hide side panel to disable map customization

You can also directly serve the current map via a flask app. To do that return kepler’s map HTML representation. Here is an example on how to do that:

```python
from flask import Flask

app = Flask(__name__)

@app.route('/')
def index():
    return map_1._repr_html_()

if __name__ == '__main__':
    app.run(debug=True)
```

## Demo Notebooks

* [Load kepler.gl](https://github.com/keplergl/kepler.gl/blob/master/bindings/kepler.gl-jupyter/notebooks/Load%20kepler.gl.ipynb): Load kepler.gl widget, add data and config
* [Geometry as String](https://github.com/keplergl/kepler.gl/blob/master/bindings/kepler.gl-jupyter/notebooks/Geometry%20as%20String.ipynb): Embed Polygon geometries as `GeoJson` and `WKT` inside a `CSV`
* [GeoJSON](https://github.com/keplergl/kepler.gl/blob/master/bindings/kepler.gl-jupyter/notebooks/GeoJSON.ipynb): Load GeoJSON to kepler.gl
* [DataFrame](https://github.com/keplergl/kepler.gl/blob/master/bindings/kepler.gl-jupyter/notebooks/DataFrame.ipynb): Load DataFrame to kepler.gl
* [GeoDataFrame](https://github.com/keplergl/kepler.gl/blob/master/bindings/kepler.gl-jupyter/notebooks/GeoDataFrame.ipynb): Load GeoDataFrame to kepler.gl

## FAQ & Troubleshoot

**1. What about Microsoft Windows?**

keplergl is currently only published to PyPI, and unfortunately I use a Mac. If you encounter errors installing it on windows, [this issue](https://github.com/keplergl/kepler.gl/issues/557) might shed some light. Follow this issue for [conda](https://github.com/keplergl/kepler.gl/issues/646) support.

**2. Install keplergl-jupyter on Jupyter Lab failed?**

Make sure you are using node 8.15.0. and you have installed `@jupyter-widgets/jupyterlab-manager`. Depends on your JupyterLab version. You might need to install the specific version of [jupyterlab-manager](https://github.com/jupyter-widgets/ipywidgets/tree/master/packages/jupyterlab-manager). with `jupyter labextension install @jupyter-widgets/jupyterlab-manager@0.31`. When use it in Jupyter lab, keplergl is only supported in JupyterLab > 1.0 and Python 3.

Run `jupyter labextension install keplergl-jupyter --debug` and copy console output before creating an issue.

If you are running `install` and `uninstall` several times. You should run.

```
jupyter lab clean
jupyter lab build
```

**2.1 JavaScript heap out of memory when installing lab extension**

If you see this error during install labextension

```bash
$ FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory
```

run

```bash
$ export NODE_OPTIONS=--max-old-space-size=4096
```

**3. Is my lab extension successfully installed?**

Run `jupyter labextension list` You should see below. (Version may vary)

```bash
JupyterLab v1.1.4
Known labextensions:
   app dir: /Users/xxx/jupyter-python3/ENV3/share/jupyter/lab
        @jupyter-widgets/jupyterlab-manager v1.0.2  enabled  OK
        keplergl-jupyter v0.1.0  enabled  OK
```

**4. What's your python and node env**

Python

```
python==3.7.4
notebook==6.0.3
jupyterlab==2.1.2
ipywidgets==7.5.1
```

Node (Only for JupyterLab)

```
node==8.15.0
yarn==1.7.0
```


# Examples

A list of examples to demonstrate adding `kepler.gl` to your app. Each of the examples is a complete project that can be ran locally.

To start each example, cd into the folder then run:

```
yarn && yarn start
```

* [**Demo App**](/examples/demo-app)

  kepler.gl as a single page app, loading sample maps from remote url, saving map data to dropbox. This is also the source code of kepler.gl/#/demo.
* [**Open Modal**](/examples/open-modal)

  Open kepler.gl in a modal.
* [**Custom Reducer**](/examples/custom-reducer)

  Customize kepler.gl reducer initial state, adding more actions using plugin.
* [**umd client**](/examples/umd-client)

  A single html file loading kepler.gl
* [**Replace UI Component**](/examples/replace-component)

  Example showing how to replace kepler.gl default ui components using `injectComponents` method.
* [**Custom theme**](/examples/custom-theme)

  Customize kepler.gl theme by override default style properties.
* [**Node App**](/examples/node-app)

  Embed Kepler.gl in a node/express/webpack application.
* [**Custom map style**](https://github.com/keplergl/kepler.gl/tree/14c35fc048a745faab0c6770cab7a4625ccedda3/examples/custom-map-style/README.md)

  Demo how to use kepler.gl with other basemap services other than Mapbox.


# Node/Express

This example shows how to embed Kepler.gl in a node/express/webpack application.

#### 1. Install

```sh
yarn
```

#### 2. Mapbox Token

add mapbox access token to node env

```sh
export MapboxAccessToken=<your_mapbox_token>
```

#### 3. Start the app

```sh
yarn start
```


# Demo App

This is the src code of kepler.gl demo app. You can copy this folder out and run it locally.

#### Pre requirement

* [Node.js ^20.x](http://nodejs.org): We use Node to generate the documentation, run a development web server, run tests, and generate distributable files. Depending on your system, you can install Node either from source or as a pre-packaged bundle.
* [Yarn 4.4.0](https://yarnpkg.com): We use Yarn to install our Node.js module dependencies (rather than using npm). See the detailed [installation instructions](https://yarnpkg.com/getting-started/install).

#### 1. Install Dependencies

Go to the root directory and install the dependencies using yarn:

```sh
yarn bootstrap
```

If install fails while building the `gl` package, use Node 20.19.3 from the repo root `.nvmrc` (`nvm install` / `nvm use`), or see [Troubleshooting: gl package install](/contributing/developers#troubleshooting-gl-package-install).

If `yarn start` errors with missing `@kepler.gl/duckdb/components` (or other workspace `dist/` files), from the repo root run `yarn workspaces foreach -At run stab` or run full `yarn bootstrap` (not only `yarn install`).

Then, go to the `examples/demo-app` directory and install the dependencies using yarn:

```sh
yarn install
```

#### 2. Environment Variables

Create a `.env` file at the root directory by copying from `.env.template`:

```sh
cp .env.template .env
```

Then update the following environment variables in your `.env` file:

```sh
MAPBOX_ACCESS_TOKEN=<your_mapbox_token>
DROPBOX_CLIENT_ID=<your_dropbox_client_id>
MAPBOX_EXPORT_TOKEN=<your_mapbox_export_token>
CARTO_CLIENT_ID=<your_carto_client_id>
FOURSQUARE_CLIENT_ID=<your_foursquare_client_id>
FOURSQUARE_DOMAIN=<your_foursquare_domain>
FOURSQUARE_USER_MAPS_URL=<your_foursquare_user_map_url>
```

#### 3. Start the app

```sh
yarn start:local
```


# Replace Component

Example showing how to replace kepler.gl default components using `injectComponents` method.

#### 1. Install

```sh
yarn install
```

#### 2. Mapbox Token

add mapbox access token to node env

```sh
export MapboxAccessToken=<your_mapbox_token>
```

#### 3. Start the app

```sh
yarn start
```


# Open modal

Example showing how to open kepler.gl in a modal.

#### 1. Install

```sh
yarn
```

#### 2. Mapbox Token

add mapbox access token to node env

```sh
export MapboxAccessToken=<your_mapbox_token>
```

#### 3. Start the app

```sh
yarn start
```


# UMD client

A single html file loading kepler.gl. This html is loading kepler.gl and its dependencies from the script tags in the header. You can embed this html in your Medium or other single page blog page.

### Usage

Add your own Mapbox access token to line 48:

```js
 const MAPBOX_TOKEN = 'PROVIDE_MAPBOX_TOKEN';
```

**Note**: You will need internet to load the map and kepler.gl scripts.


# Customize kepler.gl Theme

This example show how to customize Kepler.gl theme

1. Define an object (theme) to override Kepler.gl style
2. Pass the newly created object as prop to KeplerGl react component

#### 1. Install

```sh
yarn
```

#### 2. Mapbox Token

add mapbox access token to node env

```sh
export MapboxAccessToken=<your_mapbox_token>
```

#### 3. Start the app

```sh
yarn start
```


# Customize kepler.gl Reducer

This example demos how to customize kepler.gl reducer

1. Customize reducer initialState by `keplerGlReducer.initialState`
2. Adding custom actions by `keplerGlReducer.plugins`

### Local dev

```
yarn
```

add mapbox access token to node env

```
export MapboxAccessToken=<your_mapbox_token>
```

then

```
yarn start
```


# Contributing

## CONTRIBUTING

Great to have you here. Here are a few ways you can help make kepler.gl even better!

* [Developer Certification of Origin (DCO)](/contributing#developer-certification-of-origin-dco)
* [Code of Conduct](/contributing#code-of-conduct)
* [Questions and Problems](/contributing#questions-and-problems)
* [Issues and Bugs](/contributing#issues-and-bugs)
* [Feature Requests](/contributing#feature-requests)
* [Improving Documentation](/contributing#improving-documentation)
* [Submitting Pull Request](/contributing#submit-pr)

### Developer Certification of Origin (DCO)

When committing code, kepler.gl requires [Developer Certificate of Origin (DCO)](https://probot.github.io/apps/dco/) process to be followed.

The DCO is a lightweight way for contributors to certify that they wrote or otherwise have the right to submit the code they are contributing to the project. Here is the full text of the DCO, reformatted for readability:

```
By making a contribution to this project, I certify that:

(a) The contribution was created in whole or in part by me and I have the right to submit it under the open source license indicated in the file; or

(b) The contribution is based upon previous work that, to the best of my knowledge, is covered under an appropriate open source license and I have the right under that license to submit that work with modifications, whether created in whole or in part by me, under the same open source license (unless I am permitted to submit under a different license), as indicated in the file; or

(c) The contribution was provided directly to me by some other person who certified (a), (b) or (c) and I have not modified it.

(d) I understand and agree that this project and the contribution are public and that a record of the contribution (including all personal information I submit with it, including my sign-off) is maintained indefinitely and may be redistributed consistent with this project or the open source license(s) involved.
```

#### DCO Sign-Off Methods

Contributors sign-off that they adhere to these requirements by adding a Signed-off-by line to commit messages.

```
Signed-off-by: Shan He <heshan0131@gmail.com>
```

Use the `-s` or `--signoff` command line to append this automatically to your commit message:

```
$ git commit -s -m 'This is my commit message'
```

### Code of Conduct

Help us keep kepler.gl open and inclusive. Please read and follow our [Code of Conduct](/contributing/code_of_conduct).

### Questions and Problems

We are trying to keep our Github page for issues, bugs and feature requests only. You've got much better chances of getting supports on [Stack Overflow](https://stackoverflow.com/questions/tagged/kepler.gl). Many people including our engineers are ready to answer questions on Stack Overflow. Your question might already been answered there.

### Issues and Bugs

If you find a bug, you can help us by submitting an [Issue](https://github.com/keplergl/kepler.gl/issues) to our GitHub Repository. Please use the github [Bug Report Template](https://github.com/keplergl/kepler.gl/issues/new?template=bug_report.md) and fill in as much as information as possible. Even better, you can submit a [Pull Request](https://github.com/keplergl/kepler.gl/pulls) with a fix.

## Feature Requests

If you want to contribute or add new features, please use [Issue](https://github.com/keplergl/kepler.gl/issues) on github projects to start a new discussion using the [Feature Request Template](https://github.com/keplergl/kepler.gl/issues/new?template=feature_request.md). If this receive a Go ahead, you can submit your patch as PR to the repository.

If you would like to implement a new feature then consider what kind of change it is:

* **Take a look at our** [**roadmap**](https://github.com/keplergl/kepler.gl/wiki/Roadmap) It lists out the items  we are planning to work on
* **Pick your item** Pick an item to execute
* **Claim the item** Reply in the ticket linked in the roadmap to claim the item, one of the member of the technical team will respond
* **Major Changes** that you wish to contribute to the project should be discussed first in an

  \[GitHub issue]\[github-issues] that clearly outlines the changes and benefits of the feature.
* **Small Changes** can directly be crafted and submitted to the [GitHub Repository](https://github.com/keplergl/kepler.gl)

  as a Pull Request. See the section about [Pull Request Submission Guidelines](/contributing#submit-pr), and

  for detailed information the [core development documentation](/contributing/developers).
* **Let's review your code** Create a pull request

### Improving Documentation

Questions about kepler.gl? you can checkout the examples and medium articles on [kepler.gl](https://keplergl.github.io/kepler.gl).

[User Guides](https://github.com/keplergl/kepler.gl/blob/master/docs/a-introduction.md) and API Docs are saved in the [docs](https://github.com/keplergl/kepler.gl/tree/master/docs) folder on Github. Help us improve documentation here by submitting a Pull Request.

### Submitting Pull Request

**First, follow the** [**development documentation**](/contributing/developers) **for detailed guidance on environment setup, code style, testing and commit message conventions.**

* Search [GitHub](https://github.com/keplergl/kepler.gl/pulls) for an open or closed Pull Request

  that relates to your submission. You don't want to duplicate effort.
* Create the [development environment](/contributing#setup)
* Make your changes in a new git branch:

```bash
$ git checkout -b my-fix-branch master
```

* Create your patch commit, **including appropriate test cases**.
* If the changes affect public APIs, change or add relevant [documentation](/contributing#documentation).
* Run [tests](/contributing#tests), and ensure that all tests pass.
* Commit your changes using a descriptive commit message that follows our

  [commit message conventions](/contributing#commits). Adherence to the conventions is required, because release notes are automatically generated from these messages.


# Developing Kepler.gl

## Table of contents

* [Development Setup](/contributing#development-setup)
* [Troubleshooting: gl package install](/contributing#troubleshooting-gl-package-install)
* [Running Tests](/contributing#running-tests)
* [Coding Rules](/contributing#coding-rules)
* [Commit Message Guidelines](/contributing#git-commit-guidelines)
* [Writing Documentation](/contributing#writing-documentation-this-part-is-not-available-yet)
* [Developing kepler.gl Website](/contributing#develop-the-kepler-gl-website)
* [Publish the website](/contributing#publish-the-website)
* [Publish a new version](/contributing#publish-kepler-gl-package-to-npm)

## Development Setup

This document describes how to set up your development environment to build and test Kepler.gl, and explains the basic mechanics of using `git`, `node`, `yarn`.

### Installing Dependencies

Before you can build Kepler.gl, you must install and configure the following dependencies on your machine:

* [Git](http://git-scm.com/): The [Github Guide to Installing Git](https://help.github.com/articles/set-up-git) is a good source of information.
* [Node.js ^20.x](http://nodejs.org): We use Node to generate the documentation, run a development web server, run tests, and generate distributable files. Depending on your system, you can install Node either from source or as a pre-packaged bundle.

  We recommend using [nvm](https://github.com/creationix/nvm) (or [nvm-windows](https://github.com/coreybutler/nvm-windows)) to manage and install Node.js, which makes it easy to change the version of Node.js per project.
* [Yarn 4.4.0](https://yarnpkg.com): We use Yarn to install our Node.js module dependencies (rather than using npm). See the detailed [installation instructions](https://yarnpkg.com/getting-started/install).
* [Volta](https://volta.sh/): We use Volta to manage Node and Yarn versions without you manually switching them

#### Fork Kepler.gl Repo

If you plan to contribute code to kepler.gl, you must have a [GitHub account](https://github.com/signup/free) so you can push code and open Pull Requests in the [GitHub Repository](https://github.com/keplergl/kepler.gl). You must [fork](http://help.github.com/forking) the [main kepler.gl repository](https://github.com/keplergl/kepler.gl) to [create a Pull Request](https://help.github.com/articles/creating-a-pull-request/).

#### Developing kepler.gl

If you are using Windows then using `WSL (Windows Subsystem for Linux)` is recommended. You can download a Linux Distribution like e.g. `Ubuntu` and inside of that distribution you can follow along with the next steps. You can find the detailed instructions about `WSL` [here](https://learn.microsoft.com/en-us/windows/wsl/).

If you are using MacOS or Linux then you can follow along.

Also please make sure the code editor you are using it has proper support for [EditorConfig](https://editorconfig.org/).VSCode has the [EditorConfig for VS Code](https://marketplace.visualstudio.com/items?itemName=EditorConfig.EditorConfig) Plugin. Please install necessary support for EditorConfig for your editor so that other code formatters do not have an effect on the Kepler.GL code.

To develop features, debug code, run tests, we use webpack to start a local web server and serve the kepler.gl demo app from the src directory.

```bash
# Clone your kepler.gl fork repository:
git clone git@github.com:<github username>/kepler.gl.git

# Go to the kepler.gl directory:
cd kepler.gl

# Add the main kepler.gl repository as an upstream remote to your repository:
git remote add upstream "git@github.com:keplergl/kepler.gl.git"
```

Install [volta](https://docs.volta.sh/guide/getting-started) On Unix, MacOS

```bash
# install Volta on Unix
curl https://get.volta.sh | bash
```

On Windows

```bash
winget install Volta.Volta
```

Install `nvm` to set the proper Node.js version for the project. Follow instructions to install nvm [here](https://github.com/nvm-sh/nvm).

```bash
# Install the proper Node.js version for the Kepler.gl project
nvm install

# Use the downloaded Node.js version for the Kepler.gl project
nvm use

# Enable Yarn
corepack enable
```

Install dependencies with Yarn

```bash
# Install Puppeteer
yarn dlx puppeteer


# Install JavaScript dependencies:
yarn install
yarn bootstrap

# Setup Mapbox access token locally
export MapboxAccessToken=<MapboxAccessToken>
# Set up other environment variables
export DropboxClientId=<DropboxClientId>
export MapboxExportToken=<MapboxExportToken>
export CartoClientId=<CartoClientId>
export FoursquareClientId=<FoursquareClientId>
export FoursquareDomain=<FoursquareDomain>
export FoursquareAPIURL=<FoursquareAPIURL>
export FoursquareUserMapsURL=<FoursquareUserMapsURL>

# Start the kepler.gl demo app
yarn start
```

An demo app will be served at `http://localhost:8080/`

This is the demo app we hosted on <http://kepler.gl/#/demo>. By default, it serves non-minified source code inside the src directory.

### Troubleshooting: gl package install

Yarn may report that the `gl` package (a dev dependency used for headless WebGL in tests) **could not be built**. That usually happens for one of two reasons:

1. **No prebuilt binary for your Node version and platform**\
   `prebuild-install` only ships binaries for certain Node releases and OS/arch pairs (for example, very new Node versions on Apple Silicon often have none). Yarn then falls back to compiling `gl` from source with `node-gyp`.
2. **Source build needs a `python` command**\
   The ANGLE sources invoked during that compile run `python` (not `python3`). macOS Command Line Tools typically install `python3` only, so the log shows `python: command not found` and `gyp ERR! configure error` even though `node-gyp` found Python 3.

**What to do**

* **Prefer the Node version pinned for this repo** (see `.nvmrc`, currently 20.19.3). After `nvm install` and `nvm use` (or Volta, as above), run `yarn install` / `yarn bootstrap` again. A matching prebuild is often available, so the native compile step never runs.
* **If you must use a newer Node** and the install compiles from source, ensure `python` is on your `PATH` and points to Python 3, for example on macOS:

  ```bash
  sudo mkdir -p /usr/local/bin
  sudo ln -sf /usr/bin/python3 /usr/local/bin/python
  ```

  Use another location if `/usr/local/bin` is not early in your `PATH`.

#### Develop with deck.gl

When develop, upgrade, debug deck.gl, Demo app can load deck.gl directly from src

```
// load deck.gl from node_modules/deck.gl/src, sub-modules from node_modules/@deck.gl/<module>/src
npm run start:deck

// load deck.gl src from the deck.gl folder parallel to kepler.gl
npm run start:deck-src
```

## Running Tests

* We write node and browser tests with [Tape](https://github.com/substack/tape), [Enzyme](https://airbnb.io/enzyme/), [jsDom](https://www.npmjs.com/package/jsdom) and [@probe.gl/test-util](https://uber-web.github.io/probe.gl/docs/modules/test-utils/browser-driver), and lint with [ESLint](https://eslint.org/). Make sure to run test before submitting your PR. To run all of the tests once

```bash
yarn test
```

* Yarn test runs lint and 3 tests in different env. To run them separately

```bash
# lint
yarn lint

# node tests
yarn test-node

# jsdom tests
yarn test-browser

# headless browser tests, uses probe.gl to run browser tests with puppeteer
yarn test-headless
```

* Here are some handy scripts / tricks for debugging tests

1. add `.only` to errored tests to only run 1 test at a time

```js
test.only('MapContainerFactory', t => {
  // tests
}
```

2. run all tests in chromium browser. This runs node, browser and headless browser tests in chromium browser and logs the output, you can step through the code with chrome developer tools

```bash
yarn test-browser-drive
```

3. Fast tests, runs node and browser tests without tap-spec output

```bash
yarn test-fast
```

To generate a coverage report

```bash
yarn cover
```

## Test React components

Enzyme is no longer supported therefore we are now transitioning to [testing library](https://testing-library.com/).

We have introduced an eslint rule to deprecate the usage of enzyme so if you attempt to create new tests using enzyme it will throw an error when running lint.

In order to create new tests cases please take advantage of [Testing Library](https://testing-library.com/). All necessary dependencies are already installed, you can start testing your React components by following this [doc](https://testing-library.com/docs/react-testing-library/intro);

### Migrating enzyme to React testing library

If you are interested in migrating enzyme tests to RTL (react testing library) feel free to check the [official migration guidelines](https://testing-library.com/docs/react-testing-library/migrate-from-enzyme/)

## Coding Rules

To ensure consistency throughout the source code, keep these rules in mind as you are working:

* All features or bug fixes **must be tested** by one or more \[specs]\[unit-testing].
* All public API methods **must be documented** with using jsdoc. To see how we document our APIs, please check out the existing source code and see the section about [writing documentation](#documentation)

This project use Eslint together Prettier. The linter should automatically inform you if you break any rules (like incorrect indenting, line breaking or if you forget a semicolon). Before doing a pull request, make sure to run the linter.

```bash
# To run the linter
yarn lint
```

## Git Commit Guidelines

To commit your changes, please follow our rules over how our git commit messages can be formatted. This leads to **more readable and unified messages** that are easy to follow. But also, we use the git commit messages to **generate the kepler.gl change log**.

### Commit Message Format

Each commit message consists of a **header** and a **body**. The header has a special format that includes a **type** and a **subject**. The **PR** # will be auto-generated once the PR is merged.

```
[<type>]<subject>(<pr>)
<BLANK LINE>
<body>

#e.g.
[Enhancement] Upgrade type-analyzer to pass 0/1 as integer (#317)

* Upgrade to type-analyzer@0.2.1
* Add test
```

The **header** is mandatory and the **scope** of the header is optional.

Any line of the commit message cannot be longer 100 characters! This allows the message to be easier to read on GitHub as well as in various git tools.

### Revert

If the commit reverts a previous commit, it should begin with `revert:` , followed by the header of the reverted commit. In the body it should say: `This reverts commit <hash>.`, where the hash is the SHA of the commit being reverted. A commit with this format is automatically created by the [`git revert`](https://git-scm.com/docs/git-revert) command.

### Type

Must be one of the following, capitalized.

* **\[Feat]**: A new feature
* **\[Enhancement]**: An update of a existing feature
* **\[Bug]**: A bug fix
* **\[Docs]**: Documentation only changes
* **\[Style]**: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, typos, etc)
* **\[Refactor]**: A code change that neither fixes a bug nor adds a feature
* **\[Perf]**: A code change that improves performance
* **\[Test]**: Adding missing or correcting existing tests
* **\[Chore]**: Changes to the build process or auxiliary tools and libraries such as documentation generation

### Subject

The subject contains succinct description of the change:

* use the imperative, present tense: "change" not "changed" nor "changes"
* don't capitalize first letter
* no dot (.) at the end

### Body

Just as in the **subject**, use the imperative, present tense: "change" not "changed" nor "changes". The body should include the motivation for the change and contrast this with previous behavior.

**Breaking Changes** should start with the word `BREAKING CHANGE:` with a space or two newlines. The rest of the commit message is then used for this.

## Writing Documentation (THIS PART IS NOT AVAILABLE YET)

The Kepler.gl project uses [jsdoc](http://usejsdoc.org/)

This means that all the docs are stored inline in the source code and so are kept in sync as it changes.

There is also extra content (the developer guide, error pages, the tutorial, and misceallenous pages) that live inside the Kepler.gl repository as markdown files.

This means that since we generate the documentation from the source code, we can easily provide version-specific documentation by simply checking out a version of Kepler.gl and running the build.

### Building and viewing the docs locally

We build Api docs from scratch using [documentation.js](https://documentation.js.org/). It generates docs from jsdoc:

```bash
yarn docs
```

### Writing jsdoc

You can find JSDoc instructions [here](http://usejsdoc.org/). Documentation.js is interested in the following block tags:

* `@param {type} name description` - describes a parameter of a function
* `@returns {type} description` - describes what a function returns
* `@property` - describes a property of an object
* `@description` - used to provide a description of a component in markdown
* `@example` - specifies an example.
* `@public` - Only methods with @public tag will be included in the docs

The `type` in `@param` and `@returns` must be wrapped in `{}` curly braces, e.g. `{Object|Array}`. Parameters can be made optional by *either* appending a `=` to the type, e.g. `{Object=}`, *or* by putting the `[name]` in square brackets. Default values are only possible with the second syntax by appending `=<value>` to the parameter name, e.g. `@param {boolean} [ownPropsOnly=false]`.

## Develop The kepler.gl Website

Make sure to export mapbox token in the same terminal before start the server.

```bash
$ export MapboxAccessToken=<insert_your_token>
```

In order to start

```bash
$ yarn web
```

To checkout the build

```bash
$ cd website && yarn build
```

## Publish the website

[Netlify](https://www.netlify.com/) is used to support kepler.gl demo website.

Netlify is connected to the following github triggers:

* Create a new PR
* Updated an existing PR
* Merge PR onto master

A new production version of kepler.gl website is automatically created and deployed every time a PR is merged onto master.

In order to support testing environment, Netlify is setup to generate build every time a PR is created or updated. By generating builds for new and updated PRs we support CI/CD so developers can test their own build in a production like environment

### Publish kepler.gl package to NPM

#### Requirements

To prepare a new release you need the following tool:

* [gh-release](https://www.npmjs.com/package/gh-release): this tool facilitates the creation of a new git tag (using package.json version number) and a github release (different from npm release)

Setup `gh-release` with your github api token ([instructions](https://www.npmjs.com/package/gh-release#command-line-interface))

### Push a new release

In order to publish a new version of kepler.gl a developer must perform the following steps:

1. Update **package.json** file with the new version value. Run `npm version major | minor | patch` to update version accordingly.
2. Update **CHANGELOG.md** with the latest commit changes. Print commits with `git log --pretty=oneline --abbrev-commit`
3. Create a new PR for review.
4. Once the PR is reviewed and merged, pull the latest changes locally.
5. Run `gh-release`: this command will create a new Github Release with the new updated CHANGELOG.md section.
6. Once the new Github Release is created, Github will automatically trigger a new Github Action flow that will automatically build and publish the new package version to NPM registry.

**After Release is completed and pushed**

* Update each of the example folder package.json kepler.gl dependency with the newer. To update all examples, run

```bash
npm run example-version
```

This step is required after the new version is published otherwise it would fail.

## Gitbook documentation

Kepler.gl documentation is hosted on [gitbook](https://kepler-gl.gitbook.io/kepler-gl/). For more information [read here](https://docs.gitbook.com/)

### Documentation structure

The documentation layout is defined by **SUMMARY.md** file where the table of contents define each entry has the following structure

```markdown
- [ENTRY_LABEL](FILE_PATH)
  e.g.
- [Welcome](README.md)
```

The above file is used by Gitbook to generate the doc navigation visible on the left-hand side of Kepler.gl doc website. Gitbook also has the ability to show description for each folder/section of the documentation by creating an entry in **SUMMARY.md** and create a new **README.md** file within said folder. The README.md file is a Gitbook convention that treats README files as if they were the main entry file for each folder.

The following is an example of doc section in SUMMARY.md file:

```markdown
- [User guides](docs/user-guides/README.md)
```

### Update Documentation

The integration with Gitbook allows to update the documentation in two different ways:

* Update doc files in the Kepler.gl repo. Follow the PR flow like any other changes
* Update documentation directly on Gitbook.

For both scenarios, changes will be propagated from one system to the other and vice versa. When updating Gitbook, a new git commit will be push to the Kepler.gl master branch.


# Contributor Covenant Code of Conduct

kepler.gl is an [OpenJS Foundation](https://openjsf.org/) project. Please be mindful of and adhere to the OpenJS Foundation's [Code of Conduct](https://github.com/openjs-foundation/cross-project-council/blob/main/CODE_OF_CONDUCT.md) when contributing to kepler.gl.


# Change Log

All notable changes to kepler.gl will be documented in this file.

## \[3.3.0-alpha.3] - July 12 2026

* 9e027002 chore(deps): upgrade editable-layers to 9.3.7, h3-js to v4, turf to v7 (#3526)
* 760a9649 fix: upgrade exportMapToHTML and UMD bundle to support React 19 (#3518)
* 73af58e9 fix: fix tooltip comparison for vector tile layers (#3519)
* 3831ee3b chore: update upgrade guide 3.3 (#3521)
* b4d28105 chore: remove outdated website-gatsby (#3522)
* 0626914d chore(deps): bump mistune from 3.2.1 to 3.3.0 in /bindings/python (#3523)
* b2f72775 chore(deps): bump soupsieve from 2.8.3 to 2.8.4 in /bindings/python (#3524)
* e961626f chore(deps): bump js-yaml in /bindings/kepler.gl-jupyter/js (#3509)
* 821acf55 chore(deps-dev): bump @babel/core in /bindings/kepler.gl-jupyter/js (#3497)
* 06436e34 chore(deps-dev): bump webpack-dev-server (#3510)
* 5bde6fa8 chore(deps): bump http-proxy-middleware (#3507)
* 0089de1c chore(deps): bump ws from 5.2.4 to 5.2.5 in /examples/demo-app (#3495)
* 91350af9 chore(deps): bump jupyterlab from 4.5.5 to 4.5.9 in /bindings/python (#3506)

## \[3.3.0-alpha.2] - July 10 2026

* 2884db5b chore(deps): bump js-yaml from 3.14.2 to 3.15.0 (#3517)
* a380afc2 chore: upgrade to React 19 (#3514)
* 3c0fe3f5 fix: bitmap layer fixes (#3474)
* 4e9d3813 fix: video export quality in single view not taken into account (#3516)
* b5a5ca0b fix: fix tooltip comparisson for aggregation layers (#3513)
* a9f39d7c chore(deps): bump js-yaml from 3.14.2 to 3.15.0 in /website (#3511)
* e45c0b05 chore(deps): bump http-proxy-middleware from 2.0.9 to 2.0.10 in /website (#3512)
* 0a71d674 chore(deps-dev): bump webpack-dev-server from 5.2.4 to 5.2.5 in /website (#3508)
* 372e53a2 feat: swipe view mode support in video export (#3503)
* d384cf53 feat: layer groups (#3488)
* 90ea55c4 feat(layers): Add API for custom icons in icon layer (#3502)
* 2476b9b4 chore: add examples; update broken links (#3500)
* e7747a9d chore(deps): bump ws in /bindings/kepler.gl-jupyter/js (#3499)
* edae08ae chore(deps): bump tornado from 6.5.4 to 6.5.7 in /bindings/python (#3496)
* d1b7b2d7 chore(deps): bump tar from 7.5.3 to 7.5.16 in /examples/demo-app (#3491)
* 3b0d6ee3 chore(deps): bump form-data from 3.0.4 to 3.0.5 in /examples/demo-app (#3490)
* 9712f838 chore(deps): bump launch-editor from 2.13.2 to 2.14.1 in /website (#3492)
* 7bd0357b chore(deps): bump ws from 5.2.4 to 5.2.5 (#3494)
* 2c787caa feat: swipe view mode (#3487)
* d5b9b2f9 chore(deps): bump js-yaml in /bindings/kepler.gl-jupyter/js (#3489)
* 56fe50f7 chore(deps): bump shell-quote from 1.8.3 to 1.8.4 in /website (#3481)
* 3a3e83e0 chore(deps): bump shell-quote from 1.8.1 to 1.8.4 (#3480)

## \[3.3.0-alpha.1] - June 1 2026

* cb062106 feat: bitmap layer (#3472)
* 4ef76964 feat: Add non-linear piecewise focus range to VisConfig sliders (#3465)
* 8c4b5f8f fix: fix checkbox regression (#3464)
* 7bd7d222 fix: heatmap layer - remove unused uniform blocks on mobile (#3463)
* 5880a25f feat: timeline zoom & precision controls in enlarged time filter (#3460)
* 34d1dc1e fix: fix heatmap layer crash on mobile (#3461)
* f7cc780d feat: Add Docker setup for running kepler.gl demo app locally (#3458)
* 9194faaf feat: improvements to the trip layer (#3451)
* cdd09b67 feat: geojson mode for aggregation layers (#3455)
* a656370e chore: clean up React warnings during test (#3450)
* 9bbc9cd5 feat: labels for geojson layer (#3449)
* de7360c8 chore(deps-dev): bump webpack-dev-server from 5.2.3 to 5.2.4 in /website (#3456)
* 52a9e6ec chore(deps): bump @tootallnate/once from 2.0.0 to 2.0.1 (#3454)
* c757f600 chore(deps): bump ws in /bindings/kepler.gl-jupyter/js (#3448)
* 023bb482 chore(deps): bump idna from 3.11 to 3.15 in /bindings/python (#3446)
* 4c639832 feat: improvements for timeline chart settings (#3444)
* 57154099 fix: ensure AI Assistant restart clears conversation history (#3442)
* 80882a2c chore: Convert class components to functional components (#3441)
* b008a1dd chore: Update the checkbox component to a functional component (#3440)
* 6c00e255 fix: on dataset change: this.\_rows\[e] is undefined (#3443)
* 25966764 feat: zoom and compass control (#3438)
* 3bca7250 feat: basic annotations (#3434)
* 98483629 fix: render tooltip comparison delta in separate column (#3435)
* b4790f0f fix: slider overlap text labels in collapsed time widget (#3437)
* 8e17ef50 chore(deps): bump fast-uri in /bindings/kepler.gl-jupyter/js (#3424)
* 57d101f0 chore(deps): bump @babel/plugin-transform-modules-systemjs in /website (#3428)
* 6df794f1 chore(deps): bump @babel/plugin-transform-modules-systemjs (#3427)
* d74098ec chore(deps): bump @babel/plugin-transform-modules-systemjs (#3426)
* 7b88dc68 chore(deps): bump fast-uri from 3.0.5 to 3.1.2 in /website (#3425)
* a09c383c chore(deps): bump fast-xml-builder from 1.1.5 to 1.2.0 (#3423)
* b5510491 chore(deps): bump fast-uri from 3.0.1 to 3.1.2 (#3422)
* f7166f7c chore(deps): bump mistune from 3.2.0 to 3.2.1 in /bindings/python (#3420)
* 6f8c6b89 chore(deps): bump jupyter-server in /bindings/python (#3418)
* a8753270 feat: adjust Y-axis domain to filtered time range (#3419)
* 3ada5d12 fix: stabilize Color By switching in vector tiles while dynamic color is enabled (#3416)
* 00883b19 fix: improve pmtile vector tile type detection (#3415)
* ad1f4a5f chore: layer icons to functional components (#3417)
* df047a7b Fix: Geocoder pin should place location at the bottom (#3421)
* afcb47d1 fix: clean up tooltip image resources on unmount to prevent memory leak (#3229) (#3323)
* 3150b8c0 fix: convert icon components from class to functional to resolve defaultProps deprecation (#2912) (#3325)
* d9f8adfd feat(processors): auto-detect delimiter for CSV/TSV/DSV files (#3414)
* 9c7af408 fix(kepler-jupyter): load config issue + empty geometry + json encoder (#3389)
* 602e61d3 feat: add font weight (#3408)
* 61134157 fix: Fix incorrect highlight position in point/arc layers when CPU-side filter is active (#3409)
* e6f3b02b fix: optimize raster tile layer UBOs not to fail in combination with effects (#3413)
* aff79301 feat: include locale in exported map and restore on open (#3407)
* 735bfc0d fix: Fix PointLayer polygon filtering for GeoJSON column mode (#3410)
* 06f59ea0 fix: fix for open streat map attribution (#3411)
* 43d97775 fix: arcgis tile 3d model crash due to unknown coord system (post deck.gl upgrade) (#3412)
* 6c45ba25 fix: Long Script Blocking time when adding data with WKT (#3406)
* 424a6af2 feat: limit geocoder search area to map viewport (#3405)
* 6c9294a8 fix: correct env variable instruction URLs (#2599) (#3315)
* 1380bf4a chore: bump dependabot dependencies; fix yarn lock (#3404)
* dc879675 Bump @langchain/core from 0.3.45 to 0.3.80 (#3268)
* 0eae29ba feat: Streamlined rectangle drag-to-filter for map layers (#3402)
* a9ca4a80 chore: fix tests (#3403)
* ea81bbf2 fix(geojson-layer): add null-safety checks to prevent crashes on malformed features (#2383) (#3337)
* 76ee8034 fix(export): scale point radius correctly for 2x resolution image export (#2592) (#3340)
* 833a7fd7 chore(deps): bump fast-xml-parser in /examples/demo-app (#3399)
* bc11c801 Bump http-proxy-middleware from 2.0.7 to 2.0.9 in /website (#3064)
* 59fd9eaa Bump mdast-util-to-hast from 13.2.0 to 13.2.1 in /examples/demo-app (#3258)
* 1a133e57 Bump form-data from 3.0.1 to 3.0.4 in /examples/demo-app (#3162)
* c6dde9ee Bump node-forge from 1.3.1 to 1.3.3 in /website (#3257)
* 359e272a Bump tar from 7.4.3 to 7.5.7 in /website (#3291)
* 42f6886d Bump tar from 7.4.3 to 7.5.3 in /examples/demo-app (#3280)
* 3f8bf476 Bump tar-fs from 2.1.1 to 2.1.4 (#3212)
* caca7a5e Bump js-yaml from 3.14.1 to 3.14.2 in /website (#3244)
* 254c7856 Bump js-yaml from 3.14.1 to 3.14.2 (#3239)
* ec80d66e Bump cipher-base from 1.0.4 to 1.0.6 (#3195)
* be6177df Bump brace-expansion from 2.0.1 to 2.0.2 in /examples/demo-app (#3140)
* a9cd3153 Bump brace-expansion from 1.1.11 to 1.1.12 in /website (#3144)
* 92a97077 Bump brace-expansion from 1.1.11 to 1.1.12 (#3145)
* cd5c077b feat: add COLUMN\_MODE\_GEOJSON to heatmap layer (#3397)
* 35d3173b Bump lodash-es from 4.17.21 to 4.17.23 (#3283)
* 169cd8e9 fix: integrate Maplibre support and update dependencies (#3395)
* 57278d23 fix: fix regressions after deck.gl 9.3.1 upgrade (#3396)
* 196216e3 chore: upgrade react-map-gl to 8, maplibre-gl to 4 (#3393)
* 62056d35 feat: basic flow layer implementation (#3386)
* 5d6613c2 chore: bump deck.gl to 9.3.1 (#3392)
* 761ceee0 chore(deps): bump lodash from 4.17.21 to 4.17.23 across all packages (#3390)
* 3ad493ae chore: Sync all localization files with English base translation (#3391)
* e50397e2 fix: time range filter histogram bar alignment and animation window padding (#3385)
* 2d2968d3 chore: upgrade to node 20 (#3387)
* dd403d45 fix: fixes related to deck.gl upgrade (#3380)
* eadf5ae5 feat: add optional higher pitch option (#3384)
* 72ea4614 fix: aggregation layers regressions after deck.gl upgrade (#3383)
* 2938e27f feat(kepler-jupyter): restore save\_to\_html() using kepler.gl UMD bundle from CDN (#3382)
* 595bd909 feat: add override for vis config (#3379)
* 992f5016 fix(effects): fixes for effects regressions (#3376)
* 806a32dd fix: video export fixes (#3378)
* 0255e95c fix: update allow hover tooltip (#3377)
* f096bc93 fix: updates to attribution logic for tiled layers (#3375)
* b0fc7605 feat: video export works with effects (#3373)
* 506e552b feat: upgrade heatmap layer from mapbox to deckgl (#3372)
* 0b975b39 fix: fix missing shadertools dependency (#3374)
* b42ea3a4 feat: add tooltip toggle (#3371)
* b87714fc feat(video-export): restore video export with hubble.gl (#3367)
* 0c8c8592 feat(raster-tile): Support STAC 1.1.0 core bands, description fallback, and tile debug borders (#3366)
* 04b16d3e fix(exported map): show effects button in exported map (html) (#3369)
* 31243cb7 fix(effects): fixes for effects (#3368)

## \[3.3.0-alpha.0] - Apr 5 2026

* 44d1e47f fix: preserve line breaks in tooltip field values (#3311)
* e2cc341b fix: geocoder coordinate search results not showing (#2245) (#3322)
* 1c2db0fd feat: add layer visibility toggle to map legend (#3303) (#3324)
* 385ed909 fix(components): disable preserveDrawingBuffer by default for better performance (#3326)
* f182d6cc fix(geojson-layer): initialize strokeColor for LineString features (#2305) (#3338)
* f25f1286 fix: boolean parsing for yes/no string values (#3346) (#3365)
* be6ba648d chore: deck.gl 9.2 upgrade & loaders.gl, luma.gl upgrades (#3271)
* bc59e880b chore: Update kepler-jupyter to use kepler.gl v3.2.0 (#3219)

## \[3.2.6] - Mar 16 2026

* b5ffed55b feat: add extra map export resolutions (#3357)
* faa000c6c feat(kepler-jupyter): version 0.4.0rc1 (#3345)
* efb072eb5 fix: colors not working in trip layer of TABLE mode (#3347)
* ca30df0e1 fix: create trip layer from duckdb table (#3344)
* cc33b0c8f feat: add support to DECIMAL column type (#3341)
* 40ce323a8 docs(localization): add translation guide for contributors (#3335)
* 35ab765d4 fix: tileset loading indicator improvements (#3331)
* cec11f3cb fix: add security warning about Mapbox token in HTML exports (#3139) (#3330)
* e2f672cdc fix: replace broken vis.academy link with docs.kepler.gl (#3309)
* 8c5030c3e fix: export zoom icon (#3308)
* 8cf4274bf fix: layer configurator icon update (#3306)
* 192f0fd2b feat: getDuckDBColumnTypes improvements (#3304)
* 3762a2b36 feat: make tile loading indicator more explicit (#3305)
* e5b7df170 rollback change, and truncate tooltip (#3300)
* cbb3204cf feat: Implement WKT validation in data-type.ts (#3298)
* e705fc8aa fix: name new point layer using label if provided (follow-up) (#3297)
* 4bdf8f4ff fix: name new point layer using label if provided
* cf76bba68 fix: hide Kepler editor tooltip “top-left jump” on invalid hover coords (#3294)
* 2ba9f6e22 fix: Clamp legend height if it exceeds available space (#3276)
* 562cb1ba8 kepler.gl-jupyter: codespell (#3273)

## \[3.2.5] - Dec 24 2025

* 81f490d94 fix: trigger a redraw from icon layer once the icons are loaded. (#3269)
* 26e4a17d4 fix(ai-assistant): clear LLM history on restart chat (#3262)
* 2d985982a fix: image export for non-webpack bundlers (#3266)

## \[3.2.4] - Dec 9 2025

* 82630dee3 fix: ensure icon layer render with the latest geometry (#3259)
* 422c1b347 fix: Avoid Monaco AMD bundle when importing `@kepler.gl/duckdb` (#3255)

## \[3.2.3] - Nov 28 2025

* 2288bc324 fix: Allow passing arrow tables to ArrowDataContainer (#3247)
* a0a4eefc1 fix: Yarn start failed (#3249)

## \[3.2.2] - Nov 25 2025

* f66ab3c61 fix: Allow passing arrow tables to ArrowDataContainer (#3242)
* e2efa50dd fix: copy geometry when geometry is of binary format (#3236)

## \[3.2.1] - Nov 3 2025

* d2b130f95 fix: detect h3 column in arrow (#3230)
* 2aa200913 fix: interaction panel causes layout shift (#3224)
* 2e24bd207 feat: extend bigInt casting to support UBIGINT HUGEINT UHUGEINT in duckdb (#3227)
* 79d745ae2 \[fix] fix for wkb/wkt saved in DuckDB as varchar (#3208)
* 24529655d fix: fixes to channel by value (#3216)
* f211ccd0a \[Bug]: Fix scrollTop reest when scrolling horizontally in data table (#3206)
* b6aee95f3 docs: add security escalation policy (#3210)
* a6e9cb998 feat: ai assistant support llm proxy server (#3188)
* 2005927bd \[fix] icon layer - render default icon in case svgIconUrl loading fails (#3204)
* 64ec955ae \[chore] Add missing release notes for 3.2 (#3200)
* 70a129c4e \[feat] vector tile layer - add feature uid selector (#3203)
* 2b8af8260 \[fix] vector tile layer - use highlightedFeatureId for hover (#3202)
* 32fb77f42 \[chore] bump demo-app example to kepler.gl 3.2 (#3201)
* 96dcef6b9 \[fix] fixes for legend (#3199)
* 26dd6e832 \[website] fix mobile layout (#3197)
* 7be817789 \[website] Add OpenJS Foundation copyright and logo (#3196)

## \[3.2.0] - Aug 21 2025

* 3b0be2dda \[chore] docs update (#3192)
* 9c132de28 \[chore] docs update (#3180)
* d4d8d184b \[chore] raster tile form - add link to docs (#3183)
* f91564fb9 \[fix] save raster layer config with layer, don't rely on app config (#3184)
* 420bbf2ad \[feat] add support for boolean filter in vector tiles (#3190)
* e4b64a080 \[chore] Replace Studio section with Desktop section (#3189)
* 751148111 \[chore] Fix and update examples to v3.1.10 (#3182)

## \[3.1.10] - Aug 14 2025

* 09297acc0 \[improvement] optimize speed of getCategoricalColorMap (#3178)
* 1545fafe5 \[chore] Update react-modal types version (#3173)
* fc1b91fa9 \[chore] Create props interface for LinkRenderer Component (#3172)
* 5f664c3a5 \[chore] pass through logoComponent to PlotContainer (#3176)
* 46cc44109 \[fix] fix for a crash in getBins when numeric strings are treated as numbers (#3175)
* 0850ef2eb \[chore] Update the Screenshot Image in Readme (#3171)
* f2001983a \[feat] export duckdb column logic (#3170)
* 3df1c4ddf \[chore] expose showDeleteDataset prop (#3166)
* 2a666ae0c \[chore] export dnd constants

## \[3.1.9] - July 28 2025

* 0d6d5fd1a \[chore] raster tile - hide server settings by default (#3163)
* 7551f5d7d \[fix] DuckDB mode: space in column name breaks file import (#3153) (#3156)
* 047334712 \[fix] fit to bounds - fix initial basemap and deck projections mismatch (#3155)
* d43e8bbff \[chore] replace ai-assistant model config file with ts for npm availability (#3154)
* 1a93a2b99 \[chore] raster tile layer tests (#3152)
* 343b554db \[feat] WMS layer improvements (#3151)
* c1d2b8616 \[fix] button spinner fix (#3150)
* a05b3cf6d \[fix] WMS layer fixes 2 (#3149)
* 1a47e08a5 \[fix] WMS layer fixes 1 (#3148)
* 272fd1ae7 \[Feat] WMS Layer - development (#3092)
* 9f656e06c \[Docs] Add tutorial Spatial Data Analysis with Kepler.gl AI Assistant (part1) (#3126)
* ca628b523 \[Chore] rewrite plot container for perf improvement (#3133)
* 49f4c3de2 \[chore] Update old imports (#3131)
* 3b6e9049a \[fix] improvements for raster tile layer (#3124)
* 4237b0a0e \[chore] migrate custom-palette from react-sortable-hoc to dnd-kit (#3128)
* 49fbf8faa \[fix] aggregation layers fixes for custom color scale (#3129)
* edf1f1ddd \[fix] spatial join ai instruction (#3127)

## \[3.1.8] - May 26 2025

* 4fd570c3e \[example] Kepler.gl getting started example with Vite (#3123)
* f57173d35 \[fix] DuckDB - cast BigInts to Double by default (#3120)
* fd4702c4f \[perf] disable strokes by default for polygons in geojson layer (#3118)
* 1542bb6f7 \[Feat] Add OSM road tool to support point analysis on road networks (#3117)
* 9da33316c \[feat] Generate "idea" buttons from LLM (#3115)
* 330030185 \[Fix] AI Connection to Ollama failed (#3113)
* be6ee823a \[Bug] fix update selected feature bbox (#3110)
* 0dcacc66e \[fix] Custom picker fix when called during initialization (#3107)
* 4fc1344a1 \[Chore] style tweak (#3109)
* 3769aaf74 \[Chore] Better handle add data to map error and loading indicator (#3106)

## \[3.1.7] - May 14 2025

* 014059b97 \[fix] fixes for raster tile layer (#3102)
* 518c515d1 \[feat] loading indicator improvements for tiled layers (#3097)
* e290f281e \[fix] fix for getFieldsFromTile regression (#3099)
* 7087ffe15 \[fix] fix tooltip crashing for trip layer (#3103)
* a231ebfc1 \[fix] fix for image export with effects (#3105)
* da38e26b9 \[chore] Update Comments in actions (#3098)
* 21aac1c85 \[fix] fixes for custom input (#3095)
* 271b8cc98 \[fix] fix types publishing for table module (#3096)
* 3d3bb9b54 \[chore] add cdnUrl option to application config (#3093)
* 9cdf73ea4 \[Bug] remove layer item z-index (#3091)

## \[3.1.6] - May 8 2025

* 33203a6de \[fix] fix loading indicotor not hidden regression (#3088)
* 913176bb6 \[bug] fix lodash imports regression (#3089)

## \[3.1.5] - May 8 2025

* 223d14b60 \[chore] ts fixes
* 3570ac429 \[feat] Raster Tile Layer - development in progress (#3048)
* 07e5beae2 \[chore] import add tileset dialog styling (#3085)
* 6568c0c94 \[Feat] Add Spatial Data Analysis tools to AI Assistants (#3057)
* fd08fa1a9 \[Chore] export more kepler-gl prop selector (#3081)

## \[3.1.4] - May 5 2025

* 03b8ea0a9 \[Chore] Use clonedeep in interaction config load (#3080)
* a6104eafe \[Chore] drop lodash per-method packages in favor of the main lodash (#3065)
* abb3fd473 \[feat] h3 layer from decimal format (#3066)
* 191f66161 \[fix] fix for exported maps. Change react-markdown to markdown-to-jsx (#3077)
* 3c83e74b3 \[chore] Added types in Action (#3075)
* 8baddbbaf \[Chore] export bottom widget field selector (#3078)
* afc21c263 \[chore] Fix TypeScript Errors (#3076)
* 822cd0e32 \[Style] align icon styles, use lucid icons (#3073)

## \[3.1.3] - May 2 2025

* d5ef5f713 \[Chore] remove dnd-kit from dependency of utils and reducer, remove use of withState in dnd context (#3067)

## \[3.1.2] - May 1 2025

* fb3615b90 \[chore] extra duckdb utils export (#3063)
* a0d14b770 \[fix] updateVisDataUpdater early exit (#3058)
* 111b3180d \[chore] pass props directly to Draggable legend, not withState (#3055)
* 6bb6c98a1 \[fix] Legend positioning fixes (#3052)
* 7d601f110 \[fix] Only open either the mapDraw dropdown or locale dropdown (#3056)
* 52a2d2a2b \[CHORE] disable auto lyaer creation based on color by int column (#3049)
* e935ef51d \[chore] extra exports from duckdb module (#3050)
* 864dbe5c6 \[Chore] Fix more style components warnings (#3047)
* 9de30e2ba \[Chore] Export duckdub utils, allow cols in validate dataset (#3042)
* 6cc1ee4ef \[Bug] Fix styled-components warnings for passing props to Dom (#3039)
* cb5c14f81 \[Bug] Add mapbox-gl dep to prevent Failed to resolve import in vite (#3036)
* 7c3365fcf \[chore] Get started minimal example with esbuild (#3028)
* 224975a25 \[chore] pass duckDB adapter via application config (#3023)

## \[3.1.1] - March 11 2025

* e271c8f8c \[fix] fix for potential freeze during add data pipeline (#3015)
* 9eef01c48 \[fix] make onFilteredItemsChange callback optional (#3016)
* 7107e4177 \[fix] fixes for vector-tile layer (#3013)
* b4b979d59 \[fix] schema panel displays temp table (#3014)
* ed2b5f322 \[chore] fix react deprecation warnings (#3011)
* ba75087a1 \[fix] DuckDB: update schema after running a query (#3009)
* b57b1ff9a \[chore] update umd example to latest stable release (#3010)
* 9762dc379 \[feat] DuckDb plugin: drag and drop file directly as table (#2952)
* 8e737e8cc \[chore] changes to webpack.config path separators (#2623)
* 8fbb3b0b4 \[fix] Fix Save map action for FSQ provider (overwrite logic) (#3006)
* df829fbe9 \[fix] fix for geocoder coordinates (#3002)
* 44acecf2a \[fix] adjust getZoomFactor for icon layer (#3004)
* 69ea2a176 \[fix] fix for Icon layer UI (#3003)
* 702b49e3f \[fix] Fix for More than one copy of react-palm was loaded error message (#3007)
* a67a7fcab \[Bug] make sure the RangeBrush updates on slider range changes (#2047)
* 631f7a304 \[fix] Update geojson-utils.ts to support GeometryCollections (#2059)
* ce867606f \[chore] Bump express from 4.19.2 to 4.21.0 (#2655)
* c9dd05f32 \[chore] Bump nanoid from 3.3.7 to 3.3.8 in /bindings/kepler.gl-jupyter/js (#2906)
* b2e24345c \[chore] Bump fast-xml-parser from 4.4.0 to 4.5.0 (#2688)
* 976b079b3 \[chore] Bump lodash from 4.17.19 to 4.17.21 in /src/deckgl-layers (#2858)
* 4074b320f \[chore] Bump esbuild from 0.23.1 to 0.25.0 in /examples/demo-app (#2994)
* 57573d344 \[chore] Bump elliptic from 6.6.0 to 6.6.1 (#2997)
* c5dbd571d \[chore] Fix lint issues displayed on GitHub's File Changes page (#3001)
* b98a39def \[fix] Transform binary buffers to hex wkb when saved to json/hmtl maps (#2998)
* 221b243c2 \[feat] improvements to duckDB column type handling (#2970)
* d30a95bcd \[fix] improvements for layer type change logic (#2995)
* 547ffeb0c \[fix] arrow text labels from non-string source vectors (#2990)
* 7e2e619e2 \[chore] updates to website (#2992)
* 7e2db2b7d \[chore] Improved Props and Gettings Started Docs (#2993)
* 1216d235b \[fix] export geoarrow to CSV as geojson (#2988)
* 2c525ed8e \[fix] restore suport for string wkb; save binary wkb as hex wkb (#2982)
* e149384df \[chore] update to hubble.gl 1.4 (#2987)
* c39778ce9 \[fix] AI Assistant sends messages to 127.0.0.1 instead of remote Ollama URL (#2985)
* 81780f5ab \[chore] Update README.md (#2981)
* f8fbf2461 \[fix] heatmap renders nothing with black color or duplicate color (#2978)
* 11350eecb \[chore] check for required env variables in demo-app and output a warning (#2977)
* 0325ef6ee \[fix] FSQ storage provider - use prompt instead of auto login after logout (#2975)
* bbe51b980 \[fix] fix for point column suggestion not working (#2974)
* fa1cc4f1e \[chore] Rename ".env.template " to ".env.template" to prevent git clone fail (#2976)
* 47cd3da81 \[keplergl-jupyter] Release v0.3.7 #2969
* 7bbe0b839 \[Jupyter]\[Fix] convert datetimes to str so they can convert to json (#2968)
* 5367abaee \[fix] fix geojson and trip layer crash without data (#2964)
* e1c9f869c \[fix] FSQ Storage provider temp fix (#2960)
* 098ee9b42 \[fix] fix for minzoom in examples (#2959)
* f7f10379e \[chore] update demo-app version (#2958)
* ab17e7565 \[chore] update banner mesasge (#2957)

## \[3.1.0] - January 29 2025

* 089aa8cf8 \[chore] vector tiles refactoring (#2945)
* 405c36e23 \[fix] DuckDB: make query result title more reusable (#2956)
* 8033578f2 \[docs] update docs for Kepler.gl release 3.1 (#2941)
* b1953cff7 \[feat] banner with extra release info (#2955)
* e95c4e5a4 \[fix] arrow tables - save timestamps as iso date string (#2953)
* 4aef54a93 \[fix] adjust margin for map save modal to show Save button without scrolling (#2954)
* f00b4b88d \[chore] testing mp4 embed with gitbook (#2951)
* f292d6181 \[Chore] Add DeepSeek in Ai Assistant (#2946)
* c5484e1ae \[fix] plumbing for DuckDB plugin support (#2949)
* da9988532 \[chore] demo-app bump kepler.gl version (#2944)

## \[3.1.0-alpha.7] - January 27 2025

* 7356c5afe \[fix] hotfix for arrow saving / loading, without support of binary data (#2943)
* 4031451b0 \[feat] duckdb plugin (#2798)
* 029bcc548 \[feat] loading indicator (#2936)
* 1a68d1bd2 \[Chore] Remove SQL plugin for AI Assistant (#2938)
* 4be4b6987 \[Misc] Update demo-app README.md (#2934)
* b38054fa8 \[Feat] AI Assistant Query (#2819)
* 4cd912097 \[fix] Added 24 limit for maximum zoom (#2635)
* b1bddd5fb \[chore] Fixes for using in a vite app (#2898)
* 4d1bfb3d0 \[feat] minZoom and maxZoom for examples (#2933)
* 81be74920 \[fix] don't auto create point layer from vector tiles (#2932)

## \[3.1.0-alpha.6] - January 22 2025

* 803b2f540 \[fix] remove dependencies from useEffect (prev componentDidMount in app.tsx) (#2930)
* 57926442f \[fix] use saved map config for saved maps instead of zoom in to data (#2929)
* 4af609245 \[chore] add dot.env, updates to demo-app build, update gitignore (#2928)
* ce23c7668 \[feat] duckdb module updates (#2927)
* fc974d852 \[feat] duckdb module placeholder (#2926)
* d1b3c9799 \[fix] demo-app resolve to proper node\_modules (#2925)
* 594250bc7 \[fix] fix demo-app yarn start (#2924)
* 913ba1ce0 \[feat] support for table plugin in demo examples and privately stored datasets (#2923)
* 630728190 \[fix] fixes for style editor preview and error (#2919)
* d6aa2757e \[fix] fix neighbor mode hovering crash in arc/line layers (#2920)
* e2bd71d4e \[fix] fix csv table examples for layers (#2921)
* a6e151a0f \[fix] vector tile layer fixes (#2911)

## \[3.1.0-alpha.5] - January 15 2025

* b117b08ab \[fix] fix for exported html maps

## \[3.1.0-alpha.4] - January 15 2025

* 933a91a2f \[fix] check for geoarrow extension in geojson layer (#2916)
* 0abe9979d \[fix] opening multiple examples breaks url (#2915)
* 49e7956e8 \[fix] Don't show 0 when description is empty (#2913)
* cb5d4ed42 \[fix] fix styled-components version in exported map (#2907)
* b1d243363 \[fix] adjust tooltip style (#2910)
* f0c57a869 \[fix] fix website commit section
* 2753321c5 \[feat] Vector Tile layer fixes (#2899)
* 073c585e4 \[Fix] add\_data() function failed in keplergl-jupyter
* 6e425972e \[feat] mapbox and maplibre simultaneous support (#2897)
* 22f9ba14d \[Chore] Fix lint error for Register actions (#2896)
* ccfc2e2ad \[fix] Image export legend positioning (#2895)
* cf02a3ca6 \[chore] Upgrade styled components to v6 (#2894)
* 4c9ffe827 \[fix] Prevent infinite useEffects loop in range-plot (#2892)
* 0b67c5409 \[fix] fixed onOptionSelected handler when option is null (#2891)
* 40ba839e3 \[fix] Add ellipsis in LayerTypeListItem (#2890)
* d0d31bdfa \[fix] Handle selecting geojson polygon with missing properties (#2889)
* 79801bec0 \[fix] Tippy tooltips in animation controls (#2888)
* 0ad53723a \[feat] Adding setAnimationConfig action (#2887)
* 67b001980 \[chore] export TimeFieldFilterProps (#2883)
* 603fde8d1 \[fix] Fixed issue when mapstate latitude or langitude are out of bounds (#2882)
* 92c9e6abc \[fix] Use floating-ui to deal with closing on click outside (#2886)
* 4bcf55bd6 \[Feat] Custom color scale for categorical/ordinal field (#2880)
* 23f603428 \[Bug] Prevent dragging legend component outside of container (#2885)
* d549fcd4e \[fix] copy map config style (#2878)
* 34444fa54 \[fix] check for allBins (#2876)
* 8335ba410 \[fix] Custom Color Scale fixes (#2875)
* 141236513 \[chore] Add several vis state mergers combineConfigs and improve TS (#2634)
* 9f3f08944 \[Chore] Add composedReducerSchema to schema manager (#2633)
* e633177ef \[chore] applyFilterConfig action (#2872)
* ceb930e2d \[Fix] incorrect multi-dataset filter domain (#2871)
* 00dd00279 \[fix] show scale options for Point Count in aggregation layers (#2870)
* a39fcf8c4 \[fix] pass strings to color palette inputs (#2873)
* b89b19c6a \[chore] Consolidate vis state tests (#2869)
* 77e785713 \[feat] Support custom ordinal color scale on string field in layer config (#2868)
* cccc4be2b \[feat] Free positioning of the legend (#2874)
* 2d1d8e5f5 \[Fix] add\_data() function in keplergl-jupyter (#2867)
* 3b46abd34 \[feat] add LayerToggleVisibility for single splitMap (#2863)
* b2b6f10c8 \[Release] Candidate Kepler-Jupyter v0.3.4 (#2588)
* 3bf006f41 \[fix] Remove legend layer groups height capping (#2864)
* f1245d7e5 \[chore] ts refactoring (#2861)
* a897715cc \[Feat] Add custom color scale for aggregate layers (#2860)
* 6bc594602 \[Feat] replaceDataInMap action - save colorsByDataId (#2859)
* be2f04e6d \[chore] add fsq color palettes (#2862)
* c7d3777fc \[fix] change process to globalThis.process (#2865)
* 5cb8a3431 \[chore] Create SECURITY.md (#2845)

## \[3.1.0-alpha.3] - December 25 2024

* 2cd7a859c \[chore] fix missing dependencies in workspaces (#2856)

## \[3.1.0-alpha.2] - December 24 2024

* f9b385a6e \[fix] Fixed time filter bug where points located at the borders of the domains were not correctly displayed (#2854)
* 59abc6a19 \[fix] fix for custom color scales with tile layer (#2853)
* 3a4bf667f \[feat] histogram and point layer fixes (#2852)
* f9c52e538 \[feat] color scale histogram (#2851)
* 3e7dc937a \[fix] custom palette issues (#2850)
* d55797991 \[docs] Replace yarn global add with yarn dlx for puppeteer installation (#2849)
* e106c1927 \[feat] Plumbing for vector tile layer (#2839)
* a2abbf72d \[fix] fix yarn cover regression (#2846)
* 6925bd429 \[docs] update demo-app/README.md (#2847)
* f05b6e37d \[chore] Bump nanoid from 3.3.7 to 3.3.8 in /website (#2840)
* 4baa44d9b \[chore] Bump nanoid from 3.3.7 to 3.3.8 (#2837)
* b09d7eb95 \[Enhancement] support mapbox url protocol (#2693)
* 215383661 \[Feat] Redesign color range to use chormajs and d3 color function (#2835)
* bded7af76 \[Feat] handle layer color scale by field.domainQuantiles (#2829)
* 5f7c26bd0 \[fix] Prevent duplicate legend in line and arc layers (#2830)
* 639c7a5b9 \[feat] Apply new legend style (#2831)
* f9c214dd5 \[chore] getSelectedFeature (#2832)
* efdf2ea8d \[chore] ts fixes (#2827)
* 074d123dd \[Feat] Add display format setting for table/tooltip (#2826)
* aec75d819 \[Chore] Minor ts refactoring (#2825)
* 1825b6572 \[fix] Expand legend (#2824)
* bb6a376e8 \[fix] adjust time range filter on value set (#2823)
* cef3faf19 \[Feat] add h3 typed column (#2822)
* c5d42ddc9 \[fix] Fix multiple field filtering in setFilterUpdater (#2821)
* c4d1cfff0 \[FEAT] support domain.domainStops in layer color, render color legend based on zoom (#2815)
* 3a4feac59 \[fix] Line layer is not displayed for between hex ids (#2820)
* 89411c820 \[fix] Typescript 4.4 fixes (#2816)
* 240289603 \[feat] Show selected fields in the tooltip for aggregation layers (#2814)
* 95c6ed14b \[chore] Bump elliptic from 6.5.7 to 6.6.1 in /bindings/kepler.gl-jupyter/js (#2818)
* fb3fa7b58 \[chore] Bump cross-spawn from 6.0.5 to 6.0.6 in /website (#2817)
* f476a1c4c \[chore] Bump elliptic from 6.5.7 to 6.6.0 (#2720)
* c727356f7 \[chore] Bump cross-spawn from 6.0.5 to 6.0.6 (#2772)
* 3950d73ab \[chore] Fixes in README.md (#2810)
* 786aa36cf \[Fix] Don't modify height for with fixed height enabled; Height UI unification (#2804)
* 2178d9057 \[fix] show sync layer animations when there is one dataset (#2803)
* 6f35313f7 \[chore] timeline refactoring (#2802)
* d50bbc831 \[fix] Updated plot when changing cross filters (#2801)
* b4dfa2fce \[fix] disable Share Map for FSQ provider (#2808)
* 86b5dda7e \[Feat] AI Assistant \[2] (#2777)
* 5a0cbca66 \[Bug] Fix issue with React StrictMode causing Dataset table to not display (#2683)
* b147db8d5 \[chore] Local Development Guide Update (#2806)
* 6223be939 \[fix] Foursquare storage provider improvements (#2800)

## \[3.1.0-alpha.1] - December 3 2024

* f6b37c6af \[fix] fixes for exported maps
* 979c9a5a1 \[fix] align upload icon (#2799)
* 6862eb85c \[fix] Fix for Try Sample Data (#2796)
* f4f7fd2b4 \[fix] fix examples - proper publicPath to include bundle chunks (#2795)
* 7ca7f9178 \[chore] prepublishOnly command fixes (#2793)
* 40c6c8b09 \[chore] npmpublish fixes - set npm registry manually (#2792)
* f60b94f48 \[chore] fix npmpublish action (#2791)
* e77981e13 \[chore] fix for package publishing (#2790)

## \[3.1.0-alpha.0] - November 26 2024

* 5b4f6537 \[feat] create new dataset action (#2778)
* a253cae1 \[chore] Update the keplergl processors update (#2776)
* 931e2c6b \[fix] Update the path to relative path in utils (#2775)
* ac469c13 \[chore] Updated imports for Kepler GL Reducers in docs (#2774)
* 13b469d8 \[chore] common-utils module (#2773)
* 6fd4f884 \[Feat] Kepler.gl AI Assistant \[1] (#2735)
* ab9e2530 \[fix] Time Sync fixes and tests (#2771)
* 1689ed68 \[fix] Custom color scale fixes (#2770)
* d0c9a3b9 \[feat] Support custom breaks in color scale (#2739)
* 3f645002 \[fix] restore arc and line layers in non-geoarrow modes (#2732)
* 966ee4c6 \[Chore] Custom Initial State and Forward Actions Docs update (#2731)
* e88577de \[chore] Docs action page import updates (#2729)
* d783b43c \[feat] experimental support for ARROW:extension:point; support for arrrow:wkb for geojson layer (#2716)
* 26687575 \[chore] Update Code examples in API Reference Get Started page (#2727)
* 8ea1cabe \[fix] Fixed synced filter domain and interval calculation (#2725)
* 695861b2 \[Bug] fix yaxis chat doesn't update (#2724)
* 8c37afaa \[fix] time sync bugfixes (#2723)
* 4c2a6b3c \[Improvement] Improved radius legend number formatting (#2726)
* c9658214 \[Doc] Improve keplergl-jupyter documentation (#2697)
* 934f8e89 \[feat] Improve timeline sync filer UI (#2722)
* d6f68379 \[fix] Time Sync bugfixes (#2721)
* 40f82127 \[feat] Sync filter with layer timeline (#2718)
* 0b6f320a \[Enhancement] Synced filter small tuneup to synced filter panel (#2715)
* caf6e485 \[fix] filter fields based on timestamp (#2714)
* c17dacf3 \[feat] Layer animation (#2713)
* 0507bd60 \[faat] deckgl-arrow-layers module (#2680)
* 8e4d723b \[feat] Allow function return type of getData in getFilterValueAccessor (#2708)
* e20d5e82 \[BUG] fix gpu filter update trigger attribute update in every render (#2707)
* 2d8161e3 \[Feat] add color picker to single color selector (#2699)
* b258e8a9 \[Bug] Fix synced time filter loaded value not saved (#892) (#2706)
* e5fe97be \[feat] Updated time filter sync style (#2705)
* cb705c63 \[fix] Prevent bottom time widget crash (#895) (#2703)
* ef2ac8f0 \[chore] Add runGpuFilterForPlot to export, ts changes to KeplerTableModel (#2702)
* ee695327 \[fix] remove duplicate "https:" in example (#2711)
* a743a276 \[fix] add map control buttons back (#2709)
* 97df4c94 \[Feat] Replaced filter enlarged with view: side | enlarged | minified - part 2 (#2537)
* 1c0ef9a9 \[feat] add deck.gl onFilteredItemsChange callback to DeckGl overlays (#2691)
* d6082fe6 \[feat] Time filter syncing (#2690)
* b28a263e \[feat] Implemented ability to invert time series trend colors (#2692)
* ecb5ed41 \[feat] Edit color legend value (#2681)
* 9c82daae \[Enhancement] Add billboard and fadeTrail toggles (#2684)
* 69fc6c65 \[Feat] Dynamic map lib config (#2678)
* 5764b069 \[Chore] Remove default props and react-onclickoutside in react functional components (#2679)
* 09e19f86 \[Fix] Tooltip not working in exported HTML map (#2556)
* a24ba5ec \[Feat] Support radius legend (#2677)
* 1e7415a3 \[Enhancement] call layer methods to validate visconfig when switching dataset (#2676)
* 25a5b60d \[Chore] Adding application config (#2658)
* a9135ac6 \[Feat] add geojson column mode for point layer (#2666)
* b6ac6540 \[Feat] Add neighbor column mode to arc layer, support arc from hex (#2665)
* 2bc59371 \[Feat] support create geojson path from point csv in polygon layer (#2664)
* 4c489940 \[chore] Split out column mode config into separate component (#2663)
* add6192b \[feat] Layer Column Mode (#2662)
* ef32f711 \[fix] Fixed disappearing animation time control (#2625)
* c70ae07e \[chore] Update @loaders to 4.1.1 (#2638)
* ad94d703 \[Fix] legend wasn't interactive in shadow DOM (#2630)
* 6ffb1dcb \[chore] Move create or update filter action (#2636)
* 16a3ac26 \[fix] Improved map bounds calculation and handled latitude issues (#2632)
* 7e3ea28b \[fix] prevent second shadow effect (#2631)
* f8e7b417 \[fix] Upgrade react-router from 3.2.5 to 3.2.6 (#2637)
* 56c9c3ed \[fix] Updated type data-utils getColumnFormatter method (#2640)
* 5d77b7ab \[chore] Add className for LayerManager (#2629)
* 6f45f1f0 \[feat] add autoFocus prop in TypeHead (#2646)
* 406b9787 \[fix] Reset default values when DropdownList component unmounts (#2648)
* cf39ab20 \[fix] Map controls tooltips break drag event positioning (#2649)
* e7deb4c6 \[chore] Exporting missing types for PlaybackControls (#2650)
* edd1fd98 \[fix] Making sure animated spinner has border width CSS prop set (#2651)
* b92b9707 \[fix] Disable polygon filter menu for non-polygon features (#2652)
* e40d9b6e \[feat] Call get after inject to create full cache (#2647)
* f15be57f \[fix] Fixed effect panel width (#2644)
* 04280b33 \[fix] Hiding legend scrollbar when in image export (#2643)
* 73704019 \[chore] Update modal with test id (#2642)
* 4f9d261c \[fix] data table right margin in header (#2641)
* 66b7fbdf \[chore] Replaced deprecated "assert" with "with". (#2654)
* fb7fd817 \[fix] build\_and\_publish fix (#2645)
* 9dbc80f1 \[chore] migrate from webpack to esbuild to build demo-app locally (#2616)
* 7b512cfa \[chore]: Upgrade to yarn 4 (#2610)
* a06d03c5 \[chore] Bump setuptools from 69.5.1 to 70.0.0 in /bindings/kepler.gl-jupyter (#2587)
* f977b4f2 \[chore] Bump elliptic from 6.5.6 to 6.5.7 (#2608)
* 40005446 \[chore] Fix cover script generate cover report (#2609)
* affc5b65 \[Chore] Upgrade to eslint 8.53.0 and prettier 2.8.8, fix lint and type errors (#2607)
* bc90b0e2 \[Chore] fix tests (#2602)
* e5111dad \[Bug] Fixes a number of issues preventing Kepler from building on fresh checkout (#2596)
* 9341911e \[Bug] Fix custom map style input (#2564)
* 89180277 \[chore] update deps; update doc; update version (#2568)
* ff52dda6 \[fix] jupyter widget: don't take over (#1723)
* 739aed86 \[deps] Bump ip from 1.1.5 to 1.1.9 (#2527)
* 44526ebc \[Feat] Kepler-Jupyter 0.3.4 with kepler v3 (#2565)
* 6667a966 \[Docs] Update node.js version in docs to v18 (#2558)
* 4932e76a \[Feat] use fixed height in geojson layer (#2533)
* 400120f3 \[Enhancement] call layer methods to validate visconfig when switching dataset (#2532)
* 1f9757b8 \[feat] Pass in custom transformRequest function (#2534)
* b644f203 \[Fix] layer popover mapIndex (#2535)
* 4b3c950f \[fix] Fix sample maps (#2529)
* 55fb2426 \[chore] Update COC to OpenJS (#2496)
* 0959de6a \[Feat]Support Zoom to layer in layer panel (#2516)
* ac0d3575 \[Chore] docs: Add GeoArrow to supported formats (#2503)
* 084d807f \[Chore] Bump path-parse from 1.0.6 to 1.0.7 (#1569)
* 46086e88 \[Chore] Bump cached-path-relative from 1.0.2 to 1.1.0 (#1687)
* b8e5f865 \[Chore] Bump ssri from 6.0.1 to 6.0.2 (#1866)
* 48e5839f \[Chore] Bump postcss from 7.0.35 to 7.0.39 (#1691)
* 03d844c4 \[Chore] Bump url-parse from 1.5.1 to 1.5.10 (#1724)
* f5d3be2c \[Chore] Bump async from 2.6.3 to 2.6.4 (#1810)
* 012e9d7e \[Chore] Bump shell-quote from 1.7.2 to 1.7.3 (#1847)
* 3222fa11 \[Chore] Bump minimist from 1.2.3 to 1.2.6 (#2520)
* 248a759d \[Chore] Bump hosted-git-info from 2.8.8 to 2.8.9 (#1865)
* 8659d4c9 \[Chore] Bump decode-uri-component from 0.2.0 to 0.2.2 (#2053)
* 354fb8d2 \[Chore] Bump browserify-sign from 4.2.1 to 4.2.2 (#2421)
* 59d81ef8 \[Chore] Bump @adobe/css-tools from 4.3.1 to 4.3.2 (#2464)
* 776f11bc \[Chore] Update docs to MapLibre and react-map-gl v7 (#2497)
* 0ad17b50 \[Chore] Bump follow-redirects from 1.15.1 to 1.15.4 (#2507)
* b3be6c9e \[Fix] fix example node-app arrow errors (#2508)
* 24acc1a0 \[Chore] Update Uber References (#2495)

## \[3.0.0] - December 21 2023

* 21a445fd \[chore] update readme, fix examples, show effects button (#2492)
* de8cb971 \[Fix] GeoArrow demo not working (#2491)

## \[3.0.0-alpha.2] - December 17 2023

* 5264c5f5 \[fix] add thumbnails (#2486)
* 34bb812e \[chore] Update all licenses to OpenJS recommendation (#2471)
* df87781a \[Feat] add polygon filter based on mean centers for GeoJsonLayer (#2476)
* 50924867 \[chore] Add file license header script (#2472)
* f33b09f8 \[Demo] Add GeoArrow sample dataset (#2483)
* 09aee384 \[feat] MapLibre basemap (#2461)
* 1544e202 \[Fix] basemap frozen when incrementally loading GeoArrow (#2474)
* b290d871 \[chore] pin luma.gl version to 8.5.21, to avoid mismatch (#2463)
* 955633df \[chore] bump loaders (#2480)
* b481611c \[fix] fix map import (#2479)
* 2024a6d8 \[Feat] GeoArrow incremental rendering (1) (#2459)
* aa1c7d10 \[chore] fix typo in landing page (#2402)
* 155a5825 \[fix] Fix cloud tile fetching logic (#2456)
* 5eb62a9b \[fix] Fixed website configuration to correctly import local kepler files (#2454)
* 39494866 \[fix] update min value for hexagonal pixelate effect (#2453)
* 8e7b0ad1 \[fix] Effects: fix possible 'undefined' in effect parameters (#2452)
* 84053786 \[chore] Validate parameters for effects (#2450)
* d60ef31d \[feat] Introduce Foursquare cloud provider (#2437)
* 82d616e4 \[fix] ScenegraphLayer has broken lighting and textures (#2443)
* 110c2991 \[chore] bump deck.gl, luma.gl, loaders.gl (#2442)
* f70b20ea \[fix] effects: prevent time reset with invalid valese (#2441)
* 3ca8df02 \[chore] Add effect MapControl test (#2440)
* 68bff82a \[fix] effect-related UI fixes (#2439)
* 82fc69e2 \[chore] Refactored cloud provider flow for performance and multi provider support (#2436)
* d975ea1e \[Feat] support GeoArrow format (#2385)
* ee6f0754 \[feat] Effect manager - UI improvements (timezone, time slider, time dropdown) (#2433)
* b5a6e9ce \[chore] Making EffectPanelHeader actions configurable (#2432)
* 1ae4cd02 \[feat] UI updates for effects (#2428)
* a69b0878 \[chore] Effects - config refactoring (#2422)
* bfec82e5 \[chore] Bump to loaders.gl\@4.0.0 (#2424)
* e6e5a4c9 \[Chore] export LayerBlendingSelector (#2419)
* a1878138 \[chore] SplitMap type changes (#2418)
* 5e0ad511 \[fix] Legend is rendered outside of widget (#2417)
* 473bd801 \[fix] feature menu not working in shadow DOM (#2416)
* b995c9b5 \[fix] Hexbin layer color aggregation incorrect on load (#2415)
* 58f0bb71 \[Chore] merge other properties in splitMap merger (#2413)
* bcb8c4e8 \[fix] long name in filter panel header (#2412)
* b8fa6ce1 \[chore] Remove paths from tsconfig (#2414)
* 79002ea6 \[feat] Support customized ref in useDimensions (#2409)
* 4d723317 \[feat] Update Icon Layer to allow passing in svg icons as a prop to bypass remote resource fetching (#2410)
* 2ff3738f \[fix] Viewports not always locked (#2408)
* 975a4762 \[fix] Using resolution-corrected mapState for image export (#2407)
* 7fae622e \[chore] adds additional properties to mock basemaps (#2411)
* df1397fd \[fix] handle empty properties in GeoJson file (#2381)
* c8e2a9f1 \[chore] move dev env to Node.js 18 (#2399)
* bb559750 \[fix] long names in tooltips (#2405)
* c9c34c86 \[chore] add custom classes to dropdown (#2404)
* 22dd6236 \[chore] Remove unused deps (#2403)
* a36ec68b \[fix] effect related fixes (split maps, shadows, timeline) (#2396)
* 5e7dd9b5 \[fix] Upgrade Mapbox SDK (#2397)
* b54c1739 \[chore] Upgrade to loaders.gl\@4.0 (#2394)
* e47ccc07 \[fix] Re-enabled plugin section in home page (#2400)
* 81a6e1fa \[fix] Update layer domain in addLayer (#2393)
* bed4b7f8 \[chore] Removed abs paths in mock state and layer utils (#2392)
* f1e654d8 \[fix] place null values at the end when sorting table (#2391)
* 4f51abc3 \[chore] extra typing for effects (#2390)
* 459ae555 \[chore] fix lint in cmpEffects (#2389)
* 87df1197 \[feat] Effects: shadow color picker; use animation & current time (#2387)
* dde3a6e3 \[chore] Fix ColorMap type (#2388)
* 08492a8a \[chore] Export effects types/utils and incapsulate dnd logic into new hooks (#2384)
* 2500a277 \[feat] reorder tooltips (#2378)
* fdecb052 \[fix] minor effect-related fixes (#2380)
* 5c16027d \[chore] Drag\&Drop context: extra check for the object type (#2379)
* a958586d \[fix] fix for process is undefined (#2376)
* 9eb6b328 \[chore] bump examples (#2375)

## \[3.0.0-alpha.1] - October 17 2023

* a3521948 \[feat] introduction of deck.gl effects (#2372)
* c798961d \[feat] Introduced dnd-context factory to better override dnd properties (#2364)
* 673646ac \[fix] fix map dropbox share (#2370)
* ec0881d7 \[fix] Fix react-map-gl mapbox api props (#2362)
* d0a86587 \[chore] Avoid confusion in viewstate context (#2361)
* 1fcdfde9 \[fix] fix image export (#2368)
* 89043bd0 \[fix] Fixed load remote map dialog exception (#2367)
* 7f9f211b \[fix] Improved validation of field pairs suggestions for LayerColumnConfig (#2359)
* fa1edab9 \[fix] add autoCreateTooltips as a prop in AddDataToMapOptions (#2358)
* e8220b0e \[chore] pass custom classes to ListHeader (#2357)
* 5a9fa5bd \[fix] Stronger AnimationConfig types (#2356)
* a2fd52ca \[fix] Fix mapbox/deck syncing issue (#2355)
* cfee75a2 \[fix] Text labels: can't set prop to false/0 with multiple labels (#2354)
* 357f77a8 \[fix] text outlines are barely visible after upgrade to deck 8.9 (#2353)
* 9d99f0b6 \[chore] Upgrade deck.gl to 8.9 (#2352)
* 032ad763 \[fix] Layer column config: sometimes a suggested field pair will hard crash (#2351)
* 56afb092 \[fix] remove  from field name when show in tooltip (#2350)
* a9181f69 \[feat] Table widged: pass getRowCell as prop (#2349)
* 1f169df1 \[fix] Improve data table horizontal overflow and dataset tabs overflow (#2348)
* f2559445 \[chore] Bump react-virtualized (#2347)
* ced842ea \[chore] Update public CDN URL (#2346)
* 6ef400d2 \[Fix] Dispatch click event instead of click() (#2345)
* cf9cf21a \[fix] Add guard for null legend label (#2344)
* b5405f52 \[fix] serializeLayer fixes (#2343)
* 4383bffd \[feat] Text layer: add outline width, outline color, background color (#2342)
* a59d8342 \[Fix] Resize observer crashes when passed a non-Element target (#2340)
* ec35ea97 \[feat] introduced jest to replace tape/sinon/enzyme for browser tests; upgrade typescript to 4.5.5 (#2339)
* 85fa66f3 \[feat] Adding applyLayerConfig action (#2337)
* ae26de55 \[fix] Fix website kepler.gl example (#2338)
* d14e7ff4 \[chore] Updated more deps to be compatible with react 18 (#2335)
* 70128119 \[chore] updated modal and panel title types to react 18 (#2334)
* a0e5db72 \[chore] Upgrade to react 18 (#2323)
* 52c69c54 \[feat] Add Deck onAfterRender callback prop support (#2332)
* 0b8ae8bc \[feat] deck.gl render callbacks (#2330)
* 6596187b \[fix] Remove fixed height for list item (#2331)
* bcd3ff1b \[fix] dropdown in color scale does not work (#2324)
* 203829aa \[fix] dropdown list alignment and spacing (#2325)
* ba6259d3 \[Fix] polygon context menu is offscreen (#2326)
* 6fd7f7a9 \[fix] When editing a custom basemap style do not unintentionally drop extra properties (#2327)
* b3472a37 \[chore] Upgrade deck to 8.8.27, loaders to 3.4.14 (#2320)
* d9c164bb \[Feat] Support WKB geometry column in CSV (#2312)
* cfada4d5 \[Chore] delete typeahead mousedown listener, pass onOptionSelected to ListItem (#2319)
* 2714c755 \[fix] fix horizontal "over scrolling" and misalignment of header row vs. data cells (#2318)
* d28674ea \[feat] Add onMouseMove callback (#2317)
* 66a6364f \[feat] add prop to allow turning off custom webkit scrollbar CSS (#2316)
* 69ce4d06 \[Chore] export action creator (#2315)
* e051eb55 \[fix] Fix map attribution color (#2314)
* 090ef0ba \[fix] Conditionally apply escapeXhtml to prevent export image crash (#2313)
* 8bb0d469 Introduce new fsq studio section in home page (#2308)
* 3e39337e updated cdn from unfolded to fsq (#2307)
* 5bae745b \[chore] drill disabled prop to layer-type-selector (#2274)
* b6a2b804 \[feat] Edit a custom base map style redux (#2281)
* 74bc22a6 \[feat] add complimentary base map style property (#2280)
* e056d01a \[feat] Remove a custom map style from the base maps side panel (#2279)
* e09ed287 \[fix] map style selector: provide backup UI content (#2277)
* 963df0cf \[chore] Update SavedCustomMapStyle accessToken property to be defined as optional (#2278)
* 46df6014 \[Chore] improved saved layer and interaction type (#2275)
* 2dff78ff \[fix] Long field names in filter UI obscure the delete icon (#2273)
* 32356b46 \[chore] pass through className prop to TippyTooltip (#2272)
* 52fb6844 \[chore] Add nx module tag (#2271)
* b255d60e \[chore] Add tooltip format (#2269)
* 7b45e4f1 \[fix] collapsible layer config group ui improvements (#2268)
* a1689540 \[chore] update browserslist deps (#2267)
* 5db83285 \[chore] specify filter id in addFilter (#2266)
* a8599dcf \[feat] Update custom map style updater to support managed map style (#2264)
* 84c07360 \[feat] Support map overlays (#2260)
* 8312d060 \[Chore] Upgrade to Node 14 (#2257)
* 23763f0b \[Chore] Add layer header action component to deps (#2265)
* 043db65f \[Chore] export single color palette selector (#2262)
* d362fc21 \[feat] H3 Layer separate layer opacity into unique fill opacity and stroke opacity (#2261)
* a1084016 \[fix] Use auto width for pinned column in table preview (#2259)
* c79e9f90 \[Chore] rewrite stack overflow functions (#2258)
* 9d57f575 \[chore] upgrade gl dependency version (#2256)
* 11242f01 \[Chore] Added collapsed prop for layer config group (#2255)
* 8d79f7d0 \[chore] export types and components (#2254)
* 4a659e84 \[feat] H3 Layer: default text label anchor to middle position (#2252)
* acd05e91 \[chore] export more components and types (#2251)
* f6be2491 \[Chore] expose functions and types to fix deep import issues (#2250)
* 5fcbcdab \[feat] H3 Layer: Add fill transparency and stroke color settings (#2249)
* 94cb2a15 \[feat] Layer property additions: H3 Layer: Add text labels (#2243)
* 9ba6bcdd \[Chore] add exports to expose functions and components types (#2242)
* 88dd4b36 \[fix] exported image has a thin white bar at the bottom (#2241)
* f562fbe0 \[fix] range slider doesn't work when step < 1 in dataset filter (#2240)
* fa3bb9c9 \[fix] Overlapping column names in drop down menu (#2239)
* 796a9d29 \[fix] time ticks are the same when using Minute to set interval (#2238)
* b9cd1ec4 \[Fix] Map popover z-index less than size panel (#2237)
* 8de7ae41 \[Fix] mapbox logo has not been styled correctly (#2236)
* ed5cb8ad \[Chore]: Add onClickControlBtn prop to MapControlButton to pass additional callbacks (#2235)
* 97126155 \[fix] Remove split map controls from legend in exported image (#2234)
* bc1cfc55 \[Chore] use unfolded cdn for base map, layer type select and icon layer svg (#2233)
* 07f8c9f9 \[feat] Add extraReducers arg to keplerGlReducer.initialState (#2232)
* a112c0e9 \[Fix] Feature Action Panel menu and editing tooltip are cut-off in dual map mode (#2231)
* 7fb4cada \[fix] Fix types for Typescript 4.8 (#2229)
* 41c80993 \[Chore] Pass onBruch, filter and datasets through range slide to plot (#2220)
* f80853b0 \[Chore] add test for vis state schema column save undefined typeerror (#2219)
* e1e165e6 \[Feat] Added new options parameter to override single action reducer default behavior (#2217)
* 1c1345b4 \[Bug] preserveLayerOrder when replace data (#2214)
* c06ceca7 \[chore] Exported layer utils methods and added onDragStart onDragEnd props (#2210)
* 7d3c6026 \[fix] Fixed bug when switching to dataset layer view (#2209)
* 2275b8e6 \[chore] Make dataId non-optional in layer config (#2205)
* c130a2f5 \[Fix] vis state schema column save undefined typeerror (#2211)
* d8a5defa \[Fix] ColorBlock component TypeError: e.color.slice(...).join is not a function (#2212)
* 1380644f \[Fix] time widget animation: apply same duration for last time filter (#2218)
* 1094e734 \[BUG] fix dropdown list fail to update when prop change (#2213)
* dafec9b8 \[Chore] add exports for scenegraph to layers index (#2215)
* 14c6d014 \[chore] layer testing support (#2216)
* e5686fda \[Bug] Fix composer types, schema types (#2208)
* 28fbcdbf \[feat] Convert layer order from idx to layer IDs (#2203)
* e1ccfdff \[Enhancement] Allow empty column when layer created from config (#2206)
* 30792f47 \[Fix] Add selected style for light dropdowns (#2207)
* 44aafd15 \[Feat] add kepler.gl to info.source in exported kepler.gl.json (#2195)
* 95fd2369 \[fix] Empty cells with date time data are filled with Invalid date (#2201)
* 3b73dc07 \[Feat] Add display format setting for table/tooltip (#2199)
* 87b79c3b \[Feat] add replaceDataInMap action (#2198)
* e9896def \[Feat] add table config with custom number format (#2192)
* e635e4cb \[fix] Fixed crash when switching to dataset layer view mode (#2191)
* a246574e \[Fix] Auto-display legend in split mode + Fix legend and layer panel bugs (#2190)
* 2d141ff5 \[fix] Layer drag and drop label is barely visible on light map (#2189)
* 70cde834 \[Fix] Drop the same layer multiple times to one map (#2188)
* 2f5da5ec \[Chore] Removed unneeded preventDefault (#2177)
* b364f3d8 \[Fix] intervals rendered incorrectly in time widget (#2183)
* c8475737 \[feat] Create layer correctly from saved layer config (#2179)
* 4c6e99e3 \[fix] previous drawn-selected geometries are lost after click Select geometry (#2175)
* 79d8c756 \[fix] support Polygon and LineString mode in idToPolygonGeo (#2182)
* 85897309 \[Fix] hide pinned selection outline when layer is hidden (#2181)
* d441d5fd \[feat] three dots button change (#2180)
* 4dd27abe \[Feat] Drag and drop interaction for split map (#2172)
* 485252ad \[fix] Improved split+unsynced mode for better handling (#2176)
* 90572720 \[fix] handle undefined values in updateViewport (#2178)
* afee4800 \[fix] hide side panel close button when data preview is open (#2174)
* 695bcccd \[feat] Improve disabled zoom lock text styling (#2173)
* 9fc98e86 \[Feat] Unlocked split map viewports (#2170)
* 8896dc13 \[fix] fix visible layers toggle for split maps mode(#2168)
* f0727c97 \[fix] type fixes for map popover (#2169)
* 04451827 \[Feat] enhance mouse selection toolset (#2164)
* f640822a \[Fix] round the float number to up to 4 decimal places in table (#2163)
* a41e0118 \[Chore] Add more types for schema (#2162)
* 502c1ba3 \[fix] remove duplicates from changelog (#2145)
* 7d996a68 \[fix] Fix onViewStateChange callback (#2154)
* 2e57238b \[chore] Type and export fixups (#2152)
* 245ac53b \[chore] update filter types (#2153)
* ce4e5c7e \[Fix] Datasets and basemap attributions separated by "|" (#2150)
* 1fd7bad0 \[Fix] Datasets attribution width styling (#2149)
* 06f085db \[Feat] render dataset attributions in map container (#2148)
* 425a6011 \[chore] ts fixes (#2147)
* abb0d1ce \[fix] improve handling of "interpolate" mapbox colors during basemap switching (#2144)
* a6a6b270 \[fix] fixes to async merger (#2139)
* 9d568af3 \[Feat] Support async mergers (#2129)
* 28c34901 \[Chore] support offset in map legend panel (#2130)
* 953711ac \[feat] Introduced updateDatasetProps to update dataset information (#2133)
* 332a94ad \[Feat] Add arrow and light theme props to TippyTooltip (#2140)
* c79896be \[Chore] Export LayerGroupColorPickerFactory from kepler-wide components (#2138)
* bf890fa9 \[chore] Update react-modal version (#2131)
* def2ce12 \[fix] Basemap overlay blending updater must pass through entire payload (#2137)
* e2848008 \[Feat] Add "No Basemap" option with map background color control (#2136)
* 5cc6faab \[fix] fixes the logic to set map overlay type properly when switching layer type (#2135)
* f605167f \[Chore] Request map styles on demand (#2134)
* fb829922 \[Feat] Add list toggle to filters (#2115)
* 20fcb662 \[Bug] Object and array field types made numeric (#2127)
* 31e44350 \[Chore] export LayerTypeListItem type (#2122)
* 390f5af8 \[chore] changes to order layers by datasets (#2114)
* 210af2b4 \[fix] remove constant scroll around layer config group (#2116)
* a438383b \[feat] Add minZoom, maxZoom, maxBounds (#2124)
* 0e5a4bbc \[Bug] data modal and data table scrollbar style (#2123)
* cdb69f4a \[chore] Export parseGeoJsonRawFeature from utils (#2121)
* 3d5db39e \[feat] add support for object and array field type (#2120)
* 1f20ef71 \[Feat] Introduce MapPopoverContent (for tooltip charts) (#2119)
* 918aaf98 \[Enhancement] Render data table with smarter cell size, prevent scroll back (#2117)
* b1d92c85 Bump ua-parser-js from 0.7.25 to 0.7.33 (#2112)
* 630e8ede \[Enhancement] Improve Feature action panel style (#2099)
* 20134f01 \[fix] Fixed time filter toggling and display the correct filter (#2098)
* 83673fd5 \[chore] bump nebula; add picking width for polygons; preserve rectangles; (#2097)
* eeb50d6a \[fix] Checking if drawing is active when delete an editor feature (#2093)
* d1abf3ee \[Enhancement] Fix dropdown list disabled color (#2094)
* 943ee50a \[Bug] fix update layer type reset layer dataId, new layer at the top (#2096)
* ac5f490e \[fix] fix layer config group collapsible content overflow (#2092)
* 608fa0f3 \[Feat] refactored AnimationControl to handle both layer and minified filter playback (#2079)
* 409db23e \[fix] CSS fixes to avoid conflicts with Jupyter styling when embedded without iframe (#2095)
* e1b70000 \[Enchancement] number formatting improvements (#2109)
* cf8d3321 \[Enchancement] number formatting improvements (#2106)
* c9cc689c \[fix] use dataset name as default h3 layer name (#2100)
* 7f01ca1c \[fix] Trip Layer: issues for path from 2 points (#2101)
* 92bae8e0 \[fix] Icon Layer - Labels are visible even if layer is hidden (#2102)
* 47cc281c fix: Open map control and geocoder for extension (#2103)
* 0cd0e379 \[fix] Improve render cell size script perf for data table rendering (#2104)
* 4e06992b \[Fix] Image export change resolution (#2105)
* 7d9d54b8 \[Feat] Map overlay blending (#2086)
* f4329fcc chore: more specific error message for context lost error (#2090)
* 14ef4366 \[Feat] Disable a layer after an error in Deck (#2072)
* d24ea4a5 \[fix] dont show hidden layers as options in polygon dropdown menu (#2085)
* fd3a7a8b \[fix] Prevent the app from crashing on geojson layer hover (#2087)
* a66f98f9 fix(filters): fix for broken filter state, load crash (#2069)
* 47b1124d fix 3d buildings rendering (#2080)
* 8edb5b2e \[fix] lock react-vis version to prevent CI fails (#2082)
* 9416be4a save and merge editor features in map config (#2071)
* 217b89e7 chore: Child support and type exports for FeatureActionPanel (#2070)
* f53188b9 show filtered out and hidden layers as options in polygon filter menu (#2068)
* b53a6b75 \[fix] Move FeatureActionPanel to class component (#2067)
* 0f7a4242 fix Cant right click on polygon or rectangle filters to get the menu (#2066)
* db549742 bump licence year to 2023 (#2073)
* a22e4259 [Feat](https://github.com/keplergl/kepler.gl/blob/master/Editor/README.md) Replace react-map-gl-draw with Nebula.gl (#2054)
* 3de77995 \[fix] fix import in demo-app carto provider (#2050)
* 3e7581b1 \[Feat] Add hasStats prop to data table adjust first cell size (#2040)
* 15d1426e FIX: Fix margin for style panel icons (#420) (#2041)
* a865ce8b \[fix] correct provider downloadMap type (#2049)
* c53d81fd Bump moment-timezone from 0.5.33 to 0.5.35 (#1966)
* efa32f75 \[fix] include CenterFlexbox in common components (#2035)
* 5f3d185f correct @kepler.gl/styles types file location (#2034)
* 76e1a4d0 \[fix] Updated dataset item cursor style (#2013)
* d0bcaa89 \[Fix]\[perf] String filter freezes browser when loading a large dataset (#2012)
* 1214bd9d \[fix] Time filter: Add padding if min/max values are the same (#2011)
* 36657380 \[fix] Fixed hex tile play animation (#2010)
* 6c266665 \[Fix] dropdown item title (#2009)
* 81fcbb41 Bump loader-utils from 1.4.0 to 1.4.2 (#2025)
* f1b7e1a8 \[Fix] no aggregation options can be selected for date field when groupby (#2008)
* b9a04468 \[Feat] Replaced filter enlarged with view: side | enlarged | minified (#2007)
* 6692585e Handle loading map style gracefully (#2005)
* 920659ff Add header cell stats control toggle (#2004)
* dbba7daa \[Chore] bump and fix examples for v3.0.0.alpha.0 (#2030)

## \[3.0.0-alpha.0] - November 5 2022

* 4eb6b24b \[Chore] dependencies update + publish process update (#1978)
* 72f201c9 kepler.gl-jupyter: Fixed wording in documentation (#1938)
* 791bbe21 \[Feat] make data table header cell overridable (#1995)
* 77ba9509 deck upgrade fix (#1997)
* 9b483b22 better regex for mapbox style boundary detection (#1996)
* 306da3a2 add onClose for color picker (#1992)
* 13bcaa06 update isRGBColor (#1991)
* 2845432e Moved animation control button to the right (#1990)
* 51a05ffe color picker crashes studio inside iframe (#1989)
* 73dba52e \[Chore] Extra memoization for components to prevent re-rendering (#1988)
* 4e88e839 \[Bug] "load from storage" and "Share" modals fix (#1976)
* 9029b8ea \[Feat] Hide Mapbox attribution when using non-Mapbox tiles (#1975)
* d77ffcb4 \[Feat] Improve fieldpair detection logic, add altitude (#1968)
* b70c35c2 \[Chore] refactor dynamic require (#1971)
* 8878cff4 \[Fix] polygon filter reload (#1970)
* ea738594 \[Chore]: Typescript 4.4 fixes (#1957)
* 49321f87 \[Feat] mobile bottom widget styling (#1930)
* db39b496 \[Chore]: Technical: Isolate components (#1967)
* 90248326 \[Chore] remove iconComponent from interactionConfig (#1973)
* 64542aa2 \[Chore] bump to deck 8.6.0 (#1959)
* ab5f9f33 \[Fix]: Item selector closeOnClickoutside conflict with portable (#1958)
* 9b81e49f \[Chore]: Technical: Isolate schemas (#1962)
* 57dea6a3 \[Chore]: Technical: Isolate reducers (#1961)
* 28578e76 Import for filters fixed (#1965)
* 359e0387 \[Bug] Fix getSampleData import (#1964)
* c2cb8213 \[Chore]: Technical: Isolate table-utils (#1949)
* af79e2e5 \[Bug] fix layer order not correctly reloaded (#1956)
* 47a184c6 \[Bug] Fix Range brush maximum update exceeds crashes (#1955)
* f9485018 \[Enhancement] improve tooltip format label, make it more intuitive (#1954)
* a42aae33 \[Enhancement] use portable in item-selector (#1953)
* 6e2fe3dd update layer selector types; get length for dc; (#1951)
* 0630c8b7 fix deck.gl version for src utils (#1950)
* d5f0f0cf \[Docs] fix broken link (#1952)
* 5e20ac68 \[Chore]: add class names to map control (#1940)
* c7ed4dbd \[Chore]: change types for modal (#1939)
* f53117fb \[Chore]: pin browserlist (#1935)
* 8ea93d40 \[Chore]: Technical: Isolate actions (#1948)
* f828f695 \[Feat]: Passing root context to tippy
* 34ebb889 \[Chore] Fix debounce typing
* 3db186e5 \[Chore] bump deck to 8.5.7 (#1934)
* 99b38d26 \[Feat] Implemented new feature flag by passing features flags prop (#1933)
* 50eda73f \[fix] 3d buildings aren't rendered without layers (#1931)
* f21afd8d \[Chore]: Technical: Isolate tasks (#1941)
* 88039cd3 \[Chore]: Technical: Isolate cloud-providers (#1942)
* a98a015b \[Bug] Fix getSampleData util import (#1947)
* 4615c480 \[Fix]: Kepler.gl site issue fixed (#1944)
* f2459c6c \[Chore]: Technical: Isolate utils (#1876)
* 88e15d5e \[Fix] fix lint (#1932)
* 3301a7c5 \[Chore]: bump deck to 8.5.4, loaders to 3.0.9 (#1928)
* 0889d0d1 \[Enhancement] (Map Control) use lazy tippy to improve map legend rendering perf (#1924)
* 82baedfb [Chore](https://github.com/keplergl/kepler.gl/blob/master/Types/README.md) move howto button out, add layer conf types, yarn lint (#1926)
* c9ef6972 \[Chore]: extra export (#1925)
* 4fc85960 \[Chore]: layer-utils, map-utils refactor (#1923)
* 5c38f851 \[fix] prevent deck crash due to layer id duplicate
* fb3f35ba \[Chore]: Use relative import in test-utils (#1921)
* eff5f902 Map Control: Use MapControlTooltip with TippyTooltip (#1920)
* 5551abd6 \[chore] Export IconButton type (#1919)
* d358b3a8 fixed findMinFromSorted when list is null (#1918)
* 3a3be58d \[Chore] Upgrade to deck 8.5.2 (#1917)
* 20d39b8c \[Enhancement] add bin to filter hiitogram construct (#1673)
* 41414ceb \[Enhancement] change export video playback button order (#1916)
* 38734422 fix color pick type using react-color types (#1915)
* f739a499 chore: Updated filter-selector, item-selector, range-slider file typescript definitions (#1902)
* 40ac3068 \[chore] test valueAccessor in field (#1906)
* f82494d6 \[Feat] Use custom style token if available instead of the default token (#1913)
* 77dc2560 \[BUG] Fix crash after layer type change (#1912)
* ac59ac7d \[Bug] rename dataset should not use spread (#1911)
* 486e3239 Prevent "Cannot read property 'layers' of undefined" error (#299) (#1910)
* fae2058f \[Bug] Fix map saved with empty filter cannt be load; validate empty filter.name when merging (#1909)
* 26b5f849 add type to keplerTable (#1905)
* bec013e5 improve reducer updater typing, change visstate to be more relaxed (#1908)
* 6c51a2ae \[feat] Hubble gl integration (#1899)
* d31fe649 \[Bug] Fix mouse event evt.point evt.lngLat undefined crash (#1903)
* 39427d46 \[Bug] fix trip layer timestamp check (#1904)
* cb76ae0f \[Enhancement] render warning in layer panel header (#1901)
* 9d171c60 \[Enhancement] set initial layer config when set layer type (#1898)
* 8d35d9b8 \[Chore] Export more type def (#1890)
* d90cd188 \[Chore] fix types and missing import (#1891)
* 28cbb759 update shader modifications for deck 8.4.16 (#1892)
* 66de62cf Fix crash: visualChannels: Cannot read property label of undefined (#1886)
* 57f77dd2 deck to 8.4.16 (#1889)
* 41dbd570 \[Enhancement] add disableDataOperation to dataset (#1897)
* 1f5e26c8 \[Enhancement] pass schema to processKeplerGlDataset (#1885)
* 156f898b \[Bug] fix comparison tooltip color and position (#1887)
* 6c99bb04 \[Bug] Disable layer copy when layer is invalid (#1882)
* dfd73a53 add supportedDatasetTypes to layer, show dataset selector even if there is only 1 or no option (#1883)
* 40a82dfa \[Enhancement] disable layer column selection if empty (#1888)
* 9c042fe5 Bump follow-redirects from 1.13.3 to 1.15.1 (#1871)
* 2a55a1e3 \[Enhancement] Improve style of layer header panel (#1881)
* ceb23e21 fix for cluster layer z-fighting; fix - render 3d building map style only once (#1874)
* a983be75 \[Bug] allow tooltip format to apply to aggregation layer hover (#1872)
* 723e6050 FILED\_TYPE\_DISPLAY -> FIELD\_TYPE\_DISPLAY (#1879)
* 7d328315 Chore: Fix lint script and issues (#1862)
* 940f9aad \[Chore]: Technical: Isolate styles (#1861)
* ad7646ac \[Chore]: Technical: Isolate localization (#1858)
* e798f317 Middleware isolation (#1860)
* 6c178d77 \[Chore]: Technical: Isolate processors (#1857)
* 9e315d25 \[Chore]: Technical: Isolate layers (#1856)
* c1e20348 \[Feat] Upgrade deck.gl\@8.4.11 luma.gl\@8.4.3 loaders.gl\@2.3.12 (#1674)
* b668fd28 \[Chore]: Technical: Isolate deckgl-layers (#1851)
* 9feddc66 Fonts issue fix (#1846)
* 9a3da3c0 \[Chore]: Technical: Translate deckgl-layers/cluster-layer (#1815)
* 10868ecf \[Chore]: Technical: constants and types modules isolation (#1840)
* fe293e71 \[Chore]: Technical: js to ts convertion components root modals (#1801)
* 55abc874 \[Chore]: Technical: Notification item types added (#1824)
* bd8c3327 \[Chore]: Technical: Translate map components to typescript (#1803)
* 371649c6 Debounce typings added (#1825)
* 1034c33d Lodash.memoize typings added (#1827)
* 69f8534d \[Chore]: Technical: fix linting errors of @types/styled-components plugin (#1834)
* 5ee0cd4f \[Chore]: Technical: add types for side panel root components (#1822)
* 9bee093e validate url of Add data modal (#1837)
* b7d8edf4 \[Chore]: Technical: add types for layer panel components (#1819)
* 7b95c236 hide layer size legend with nullish label (#1836)
* ecc743af \[Chore]: Technical:layer base config data allow to be null (#1835)
* 2b51c7bb \[Chore]: Technical: Fixed errors happening in folders/files due to the addition of @types/styled-components: components/common/slider (#1831)
* e27cf134 \[Chore]: Technical: fix attributes of styled components animation-control (#1829)
* 442d1b23 \[Chore]: Technical: add types for filters (#1809)
* fc8ab5af \[Chore]: Technical: Translate deckgl-layers/hexagon-layer (#1818)
* 959f1e0b \[Chore]: Technical: Translate deckgl-layers/grid-layer (#1816)
* cbd26743 add types for styled components in styles (#1830)
* f7715892 \[Chore]: Technical: Translate components to typescript (#1814)
* a5a347ba \[Chore]: Technical: Translate components to typescript (#1812)
* 9225e005 Throttle typings added (#1826)
* f0671f06 \[Chore]: Technical: add types for editor component (#1797)
* 4e8197d5 \[Chore]: Technical: add types for processors (#1798)
* 47e4963e \[Chore]: Technical: add types for side panel common (#1807)
* 0d3c98c8 \[Chore]: Technical: add types for filters side panel (#1799)
* 8c5e5075 \[Chore]: Technical: Translate layers final changes (#1783)
* e663bb16 \[Chore] fix typo in docs (stule -> style) (#1823)
* 2d557df3 Typings for some lodash packages added (#1817)
* ca45cef8 \[Bug] validate s2 token in s2 geometry layer (#1805)
* 7453b951 \[Chore]: Technical: components/geocoder translated to typescript (#1808)
* 5b918e00 Review fixes (#1813)
* ae1173ec \[Chore]: Technical: Translate deckgl-layers/layer-utils typesfix (#1791)
* 6a7d44bc \[Bug] Build fix (#1811)
* 8ac5bbc6 \[Bug] visual channels cannot read property 'label' of undefined (#1804)
* b7c6c8df Translate deckgl-layers/3d-building-layer to .ts (#1794)
* a5bcd814 \[Chore]: Technical: Translate root components to typescript (#1790)
* 258c82da add types for svg-icon-layer (#1796)
* 0de32bec \[Chore]: Technical: Translate deckgl-layers/line-layer (#1792)
* 013b9878 \[Chore]: Technical: Translate deckgl-layers/column-layer (#1793)
* f64b551f \[Chore]: Technical: Translate tasks (#1779)
* 65228a85 \[Bug]: fix grid hexbin and cluster layer crash (#1795)
* 7ada98a0 \[Chore]: Technical: Translate examples/custom-map-style (#1780)
* 84312384 \[Chore]: Technical: Translate deckgl-layers/layer-utils (#1789)
* ec3351b6 \[Chore]: Technical: Translate cloud-providers (#1778)
* 24e3549c Added deckgl-typings from community repo (#1787)
* 68abc5b5 \[Chore]: Technical: Translate geojson-layer (#1757)
* 2d2ba1d7 \[Chore]: Technical: Translate hexagon-layer (#1775)
* 543045d0 \[Chore]: Technical: Translate heatmap-layer (#1773)
* cf57260a \[Chore]: Technical: Translate trip-layer (#1777)
* e80c18b1 \[Chore]: Technical: Translate line-layer (#1776)
* 9a0ad623 \[Chore]: Technical: Translate cluster-layer (#1774)
* bc18a6c4 \[Chore]: Technical: Translate scenegraph-layer (#1768)
* 831504f9 \[Chore]: Technical: Translate icon-layer (#1763)
* b87bba3a \[Chore]: Technical: Translate grid-layer (#1761)
* 079da4cc \[Chore]: Technical: Translate h3-hexagon-layer (#1762)
* cd05dd4b \[Chore]: Technical: Translate point-layer (#1764)
* 0b3f2c0c \[Chore]: Technical: Translate s2-geometry-layer (#1765)
* 18342926 \[Chore]: Technical: Translate mapboxgl-layer (#1755)
* 9b695f85 \[Chore]: Technical: Translate aggregation-layer (#1753)
* 13ba6bb7 \[Chore]: Technical: Translate arc-layer (#1749)
* a3ada4e9 UN-14 Technical: Translate components/\[root files] to typescript: side-panel (#1712)
* fb2190f1 \[Bugfix]: Fixed Babel configuration (#1754)
* d9e9d8aa \[Chore]: Technical: Translate layer factory (#1748)
* c0f75341 \[Chore]: Technical: Translate components/common final part (#1750)
* b06dfb1c \[Chore] Typescript 'components/common/slider' (#1740)
* 0057a1e4 \[Chore]: Technical: Setup for different Visual channels per layer (#1751)
* 1193258b UN-14 Technical: Translate components/\[root files] to typescript: maps-layout (#1713)
* 8a06f711 Moving bottom-widget to ts (#1710)
* dd14702e \[Chore]: Technical: Translate base-layer (#1746)
* 4a687ed4 \[Chore]: Technical: Translate index and other files (#1745)
* 7a11260d \[Chore]: Technical: Translate table utils (#1742)
* 7ee74ebe \[Chore]: Technical: Translate filter-utils and gpu-filter-utils (#1744)
* e5d5d1ba \[Chore]: Components/common 1st part (#1729)
* d8abca9d \[Chore]: Technical: Translate utils (color and data) (#1732)
* 55a7b510 \[Chore]: Technical: Translate utils (dataset-utils and export-utils) (#1734)
* 0505fda4 \[Chore]: Technical: Translate redusers (vis-state) (#1727)
* 5304d4dc \[Chore]: Technical: Translate utils (files without d.ts typings) (#1728)
* 30616984 \[Chore]: Technical: Translate redusers (UI-state and provider-states) (#1726)
* 2ba94858 \[Chore]: Technical: Translate actions to typescript part 2 (#1725)
* e36cac5b UN-12 Technical: Translate redusers (main files) to typescript (#1722)
* fb170ae0 \[Feat]: Technical: Translate actions to typescript (#1704)
* cb542853 UN-13 Technical: Translate schemas to typescript (#1721)
* 8121893c \[Feat]: Technical: Translate redusers (map-state and map-style) to typescript (#1717)
* fbe626be \[Feat]: Technical: Translate redusers (composers and combined-updaters) to typescript (#1711)
* d8d7e44f \[Feat]: Technical: Translate localization to typescript (#1705)
* 614a5003 \[Feat]: Technical: Translate templates to typescript (#1702)
* 0ef5ccd8 \[Feat]: Technical: Translate middleware to typescript (#1703)
* 20ec6666 \[Feat]: Technical: Translate styles to typescript (#1701)
* 11c5b4cc \[Feat]: Technical: Translate constants to typescript (#1697)
* 283586d0 \[Feat]: Technical: Translate connect to typescript (#1700)
* 995f3f93 \[Feat]: Setup build process for ts source code support (#1688)
* b71dd6b4 \[Chore] Update license year 2022 (#1689)
* 0dfc7e1b \[Bug] fix filtered datasets memoization (#1678)
* 1e8b3c1a \[Enhancement] order layers by dataset (#1675)
* f9ae108a \[Enhancement] extract layers list to a separate component (#1665)
* 52993525 \[chore] export types, add script to build types (#1636)
* 6fb00fa0 \[Bug] fix pin table column overide dataset (#1625)
* 22ea7a9d \[Bug] do not display geocoder dataset in side panel
* a20db971 \[Feat] allow custom value in layer slider (#1631)
* 5e6b1c45 \[Bug] allow empty data rows (#1624)
* 612e18a9 \[Feat] support pin map legend in map control (#1614)
* bfcce3fd \[Enhancement]Allow changing MAX\_DEFAULT\_TOOLTIPS (#1627)
* a810ee13 \[Chore] added more properties to export layer type (#1613)
* 0931a55c \[Enhancement] Render map control tooltip with TippyTooltip (#1612)
* d0fb78de Add registry-url to avoid 404 issue when publishing keplergl npm package (#1623)
* 9936b7b7 \[Feat] add color picker to dataset tag (#1608)
* 3e3d1631 \[Jupyter] Update example versions
* 5b442c5d \[Jupyter] keplergl==0.3.2 (#1619)
* a56206c8 keplergl-jupyter v0.3.1
* e12039c6 \[Feat] Add Copy Button to Export Map Dialog (#1609)
* 3f876ac1 \[Jupyter] bump kepler.gl js version release keplergl-jupyter=0.3.1 (#1617)

## \[2.5.5] - September 12 2021

* 392e9a21 \[Bug] lock deck.gl to 8.2.0 (#1602)
* 6121a343 \[Chore] Fix explicit src import (#1596)
* 0b71f399 \[Bug] fix locale panel (#1603)
* 8b42be29 \[Bug] Fix integration with CARTO (#1600)
* e8ba7a05 \[Feat] add setMapControlVisibility action to set mapControl visibility (#1590)
* 78274562 \[Feat] add supportedFilterTypes to dataset (#1594)
* 41b364a6 \[Enhancement] s2 updateLayerMeta: push instead of spread (#1593)
* 1b5e0235 fix for long processing time of data-utils::unique (#1592)
* 91a52b16 \[Enhancement] Use layer.visible prop in deck.gl when toggle layer visibility (#1591)
* c106ee06 \[Chore] Create factory for LayerLegendHeader and LayerLegendContent (#1589)
* 878750c4 \[Feat] Add MapsLayoutFactory for custom split map layouts (#1588)
* d8db8f6f \[Chore] Refactored map control and decoupled action components (#1552)
* 2f8b19f2 \[Feat] update keplergl-jupyter widget for JupyterLab 3, add build for conda-forge (#1572)
* 6947c8c8 \[Feat] Added Russian localization (#1570)
* 9726a400 \[Docs] Data container upgrade notes (#1575)
* 070b04b2 \[Feature] Abstract Data Container (#1555)

## \[2.5.4] - July 31 2021

* 62d03ab2 \[Examples] update replace-component example (#1557)
* 089bb7a9 \[Jupyter] Make showing User Guide link optional for jupyter widget (#1559)
* 5985d201 \[Bug] Fix screenshot with images (#1558)

## \[2.5.3] - July 18 2021

* a4a6734a \[Docs] fix add data to map docs (#1551)
* 8524061e \[Enhancement] add displayName to field and show displayName whenever available (#1538)
* a0d2a76b \[Feat] Save and load highlightColor from layer config (#1550)
* a9b2ba07 \[Examples] fix panel toggle exmaple, add layer hove info demo (#1549)
* 9bcb3415 \[feat] Using tippy for map popover (#1539)
* 2e6f8b79 \[Chore] refactored side-panel from class to functional component (#1536)
* 16fab11c \[Bug] Geojson layer is not updated when dataset updated (#1533)
* 29cf0829 \[Enhancement] add toggleLayerAnimationControl action (#1537)
* 01e93966 \[Enhancement] add disableClose to map control (#1529)
* c6e5b8a6 \[Feat] use appName in exported image html json map and csv data (#1528)
* 72354560 \[Bug] Fix geojson layer duplicated index (#1530)
* 1ed0fd6d \[Bug] fix histogram in range (#1531)
* 305edfcd \[Docs] Update Map Styles Link (#1512)
* 1890133d \[Chore] Update peer dependencies for styled-components (#1527)

## \[2.5.2] - June 28 2021

* 1c7521b1 \[Bug] Fix center map accuracy (#1502)
* b662892a \[Bug] trim string value before passing to type analyzer (#1503)
* d35ad489 \[Website] Add ecosystem Section (#1491)
* 1935c70a \[Chore] Bump ini from 1.3.5 to 1.3.8 (#1385)
* b7d333b4 \[Chore] Bump y18n from 3.2.1 to 3.2.2 (#1449)
* aeb8b45a \[Chore] Bump ssri from 6.0.1 to 6.0.2 (#1460)
* 86577263 \[Chore] Bump ua-parser-js from 0.7.22 to 0.7.28 (#1471)
* f0fda0e4 \[Chore] Bump handlebars from 4.7.6 to 4.7.7 (#1472)
* 027aecfa \[Chore] Bump url-parse from 1.4.7 to 1.5.1 (#1473)
* 6d5981a0 \[Chore] Bump hosted-git-info from 2.8.8 to 2.8.9 (#1474)
* 54690fc8 \[Chore] Bump browserslist from 4.14.7 to 4.16.6 (#1494)
* 846ec388 \[Chore] Bump dns-packet from 1.3.1 to 1.3.4 (#1497)
* c6def591 \[Chore] Bump ws from 6.2.1 to 6.2.2 (#1500)
* 614750f4 \[Feat] Make keplergl-jupyter work with JupyterLab 3 (#1501)
* b4fcf7be \[Feature]: add copy geometry to feature action panel (#1495)
* d786d0f3 \[Bug] fix arc layer configurator render crash (#1490)
* b24cc57a \[Enhancement] Support elevation in Icon layer (#1483)
* d51f3050 \[Enhancement] Support elevation in Line layer (#1481)
* a09cd589 \[Enhancement] Elevation zoom factor toggle (#1478)
* 8a6d2635 \[Enhancement] add Japanese translation (#1469)
* 910eb5e7 \[Chore] Move 'uber-licence' to devDep (#1450)
* 0b03f3a6 \[Docs] fix typos on playback readme (#1482)
* 14c35fc0 \[Doc] Add example using none mapbox base map (#1440)

## \[2.5.1] - Mar 30 2021

* 16703c0b \[CHORE] add utils.js to package.json
* a15109b3 \[Feat] add timezone and timeFormat prop for time display in animation control and time - widget (#1411)
* 13c6171e Bump elliptic from 6.5.3 to 6.5.4 (#1435)
* cdcc0eea \[Enhancement] make panel tab a factory (#172) (#1412)
* 173811a3 \[bug]: Fixed range slider null selection bug (#1413)
* df3fee5c \[Bug]: Updated babel dependencies (#1410)
* 119c8933 \[Bug] fix update dataId not update layer data (#1414)
* b97b58a9 \[Enhancement] Choose the default field to be integer if no reals are present (#1409)
* 072876df \[bug] upgrade colorbrewer to 1.5.0 (#1439)
* d4698bb8 \[Chore] add initial version of ts-smoosh (#1437)
* 6b39c43f \[Chore] reformat changelog

## \[2.5.0] - Mar 3 2021

* 58af5b65 \[bug] Set colorbrewer version to 1.4.0 #1416 (#1428)
* a03250a4 CHORE: export processKeplerglDataset (#1422)
* ddaa8bf7 FIX: incorrect type strin -> string (#1421)
* 9e5bfdca \[Feat] Duplicate layer and add layer from config (#1401)
* 29bfa406 \[Bug] Interval animation doesn't stop when speed is set to 0 (#1397)
* 9476c293 feat: Converted dataset object to kepler table class (#1239)
* 498305cc \[Bug] save to map provider (#1399)
* 6728b30f \[Bug] Clamping slider values outside range (#1395)
* f0e51743 \[Enhancement] add changedFilters to datasets when filter data is called (#1396)
* 8d68001d \[Bug] Add style prop to kepler-gl container (#1398)
* d295c762 \[Enhancement]: Save filter speed to schema (#1394)
* fb801d70 \[Chore] Update license year (#1393)
* fa6deff0 (0116-babel-deps) \[Enhancement] Show an error notification for errors in deck (#1373)
* 5d4b4547 \[Bug] Bug fixes (#1388)
* 35bf90a9 \[Bug]: FIxed issue with map popover object being null (#1384)
* fc2fb04d \[CHORE] Typescript fixes (#1383)
* d6e28377 \[Bug] Fix 12350 format in tooltip (#1327)
* 2ea82deb \[Feat] fixed augumented numeric formats with \~ (#1369)
* e88b4f19 \[Bug] Fix speed button input on timeline (#1376)
* 7aeca210 \[Enhancement] bump loaders.gl to 2.3.3 (#1366)
* eff0a15d \[Enhancement] Choose layer color by default (point layer) (#1367)
* 823405ab \[Bug] fix arc layer configurator (#1375)
* a11c63c3 \[Enhancement] avoid calling mapPopover setstate infinitely (#1346)
* ae234e72 \[Bug] Prevent crash in react-map-gl when zoom cannot be calculated (#1365)
* be61b70b \[Enhancement] automatically re-project GeoDataFrame to EPSG:4326 (#1350)
* 2aad97f3 \[Bug] Added better check for bins in bottom widget (#1361)
* ef8bdbaf \[Chore]: Upgraded to node 12, migrate from TravisCi to Github actions (#1326)
* c7726680 \[Enhancement]: Added uiStateUpdater showDatasetTable in order to intercept showDatasetTable action (#1363)
* f33c76b4 \[FEAT] Add rename dataset reducer (#1362)
* 027985af \[Bug] Fixed color picker closure when selecting first custom palette value) (#1347)
* 7f3be27f \[Enhancement] check bounds before calling fitbounds (#1348)
* f046ac1b \[Enhancement] better arc layer column config layout (#1345)
* 2ea853b1 \[Bug] Fixed bug with fixed radius after remove size field in pointlayer (#1343)
* 32d80182 \[Bug] fixed geocoder crash and added ability to pass coordinates (#1342)
* c2ba7f04 \[Enhancement] Fix negative button border (#1344)
* 55f74dcd \[Enhancement] added check for oldLayerData (#1357)
* 223af2b6 \[Enhanment] extract valdiate layer and validate filter function (#1349)
* 06ea669d \[Enhancement] pass dataset to renderLayer function (#1341)
* 524fc591 \[Feat] Visual channel refactor generalize get accessor and updateTrigger (#1338)
* c1d4943b \[Enhancement] Adjust input light styles (#1340)
* 5642ca8b \[Chore] SidePanel panels are now passed through only through props or default ones (#1339)
* f802f393 \[Chore] Decouple table from dataset Id (#1337)
* c7f50fdc \[Chore] Export KeyEvent and downloadFile utils (#1335)
* 335f82a3 \[Enhancement] Added the ability to pass supported data types when exporting (#1336)
* 239051f0 keplergl==0.2.2
* 55053230 keplergl-jupyter\@0.2.2
* 1bac01ab update example app versions

## \[2.4.0] - Nov 30 2020

* 259022ee \[Upgrade] Support React 17 (#1323)
* 6c48c422 \[Enhancement] Export more utils (#1317)
* 81bc6b37 \[Enhancement] make provider injector function to get injectedApp back (#1318)
* 5e2b8988 \[Enhancement] update spanish and catalan translations (#1319)
* 334f0b76 \[Enhancement] extend template for light theme (#1305)
* abbe032e \[Chore] Dependency upgrade (#1314)
* f0a966cd \[Bug] check category (#1316)
* 7f5282b4 \[Feat] add incremental timeline animation (#1315)
* c1a251de \[Enhancement] make visConfigSwitch a factory (#1313)
* 37cf1457 \[Enhancement] Enable polygon filter on h3 layer (#1306)
* bdbea264 \[Feat] allow changing dataset in layer config (#1312)
* 28f5204d \[Bug] fix radio button style (#1310)
* c990a477 \[Enhancement] Upgrade d3-scale (#1311)
* ea69da8a \[Enhancement] fix item-selector dropdown value overflow nad tooltip pin color (#1309)
* d94de814 \[Chores] Exported default formatters (#1308)
* 307cd3d4 \[Bug] avoid duplicated h3 layer detection (#93) (#1307)
* 8bc11a37 \[Enhancement] Add inputBGdActive for light theme (#1301)
* 3f0f7a6c \[Bug] Check for valid layer pinned prop before performing comparison (#1297)
* 42acc1cf \[Bug] Fixed bug when reversing color schema (#1296)
* 9949888f Table of content -> Table of contents
* 9a13ce68 \[Chores] Fixed security vulnerabilities and added new factories (#1294)
* 3276cef3 Merge branch 'upwards\_update'
* 70687cab \[Docs] Add usage example in doc for *repr\_html* method (#1282)
* 32b519af \[Chores] Updated yarn.lock and file license
* aecbdc55 \[Bug] Fixed typo in renderedSize cell-size (#90)
* 9f8b84e1 upgrade react-palm to 3.3.7 (#89)
* 7410cfa5 \[Enhancement] Disable layer select option when no data is loaded (#88)
* 7a69c865 data table style tiny adjustment
* 21d09475 add fontFamily to input style
* 96c37618 export renderSize from cell-size.js
* f356fe43 \[Enhancement] Added modalStyle prop Portaled to override default values (#83)
* b6fd3916 \[Enhancement] UI input style improvement (#1284)
* 92a2bb65 \[Enhancement] Add preserveLayerOrder to layer merger (#1288)
* 480ead69 \[Enhancement] Add a CTA button type (#80) (#1286)
* d882ba09 \[Enhancement] Layer config: Add column validators (#1287)
* e8fc1c5e Export typeahead (#1289)
* ad5ec020 \[Enhancement] render last added filter first (#1285)
* 42569ec3 \[Enhancement] Export StyledDropdownSelect (#1283)
* 1b748471 \[Jupyter] add *repr\_html* method (#1202)
* fbbd4c45 \[Enhancement] export more utils and schema (#1280)
* e5a6f9e8 \[Enhancement] Improve schema and utils typing (#1279)
* ad651700 \[Enhancement] Create factory for histogram and line chart, add brush handle to range brush (#1274)
* 6681d2e2 \[Enhancement] pass light theme through to item selector (#1276)
* 0184cf1e \[Enhancement] add setTimeAnimation action (#70) (#1263)
* 908a5e2b \[Chores] Bump http-proxy from 1.18.0 to 1.18.1 (#1268)
* 7acb3d66 \[Auto] Bump elliptic from 6.5.2 to 6.5.3 (#1210)
* 490cafb0 \[Jupyter] Updated Docs for Jupyter (#1267)
* a7865c8d \[Enhancement] Added factory for the icons of the map control (#1273)
* 77b4e018 \[Enhancement] switch style tweak (#1262)
* 9dbb9e73 \[Bug] fix dropdown list item lineheight (#1261)
* d677c18f \[Feat] Move more css to theme and create more factories (#1248)
* 2ebd1368 \[Enhancement] Typescript improvement (#1254)
* 959f1a33 \[Bug] fix export image size not set (#1257)
* 678aacc2 \[Upgrade] upgrade react-palm to 3.3.6 (#1255)
* f54d6afb \[Enhancement] Map control style improve (#1253)
* 3e40a48c \[Website] disable banner (#1252)
* 3b81b59f \[Enhancement] Add new theme variables (#1245)
* b09aa2e1 \[Bug] Fix load data modal crash (#1244)
* 42670d89 \[Bug] Fix provider preview image during map save and share flow (#1243)
* efd3676d \[Bug] Fix component exports
* 0b91f4d1 \[Enhancement] Improve react intl support (#1237)
* 7ff0c459 \[Enhancement] Save merger and schema to visState (#1235)
* ## \[2.3.2] - Aug 16 2020
* 10468e19 \[Enhancement] Export more utils (#1233)
* 242dcf99 \[Enhancement] Upgrade dependencies and fix vulnerabilities (#1236)
* 3d72066f \[Bug] Fixed image export bug due to mapbox attrition logo (#1229)
* f4951102 \[Feat] add readonly prop to KeplerGl component (#1220)
* 04991352 \[Enhancement] Added props to panel-header iconComponent (#64) (#1219)
* b91785ec \[Feat] Auto detect h3 layer from h3 field data (#53) (#1218)

## \[2.3.1] - Aug 4 2020

* \[Bug] fix tooltip config, add boolean formatter (#1216)
* \[Enhancement] Geocoder interaction improvements (#1214)
* \[Enhancement] add options.autoCreateLayers to addDataToMap (#1215)
* \[Bug] Hide BottomWidgetContainer nothing to render (#1213)
* \[Enhancement] Cleanup unused babel plugins (#1211)
* \[Bug] fix file handler row parsing to support single geojson feature (#1212)
* \[Enhancement] Add KeplerGl.onDeckInitialized callback (#1193)
* \[Enhancement] Render geocode in readOnly mode (#1177)
* \[Feat] pass initialUiState to prop (#1187)
* \[Docs] Fix `replace-component` Readme (#1207)
* \[Jupyter] Convert to gdf to a dataframe instead of a copy (#1201)
* New image export approach (#1199)
* Add prop to disable file extension checking (#1195)
* Load: extract extensions from loader objects (#1194)
* Add `visState.loaders` to let app inject a list of loaders.gl loaders. (#1192)
* Enable modal prop types (#1190)
* Enable modal types (#1189)
* Add types to top-level KeplerGl component (#1188)
* Add typescript types for upload modal and components (#1185)
* Add types for composer helpers (#1186)
* \[Feat] add zoom to coordinate tooltip (#1179)
* \[Enhancement] export more layer configurator components (#1176)
* \[Bug/Enhancement] Pass PanelHeader props to the onClick handler of action items (#1181)
* \[Bug] Fix import of the user guide link (#1182)
* \[examples] update example version to 2.3.0

## \[2.3.0] - July 6 2020

* \[Enhancement] Improve animation sliders (#1157)
* \[Enhancement] speed control step to 0.001 (#1155)
* \[website] remove unused env, relax on package engines requirement (#1173)
* \[Feat] Pinned tooltip + Compare (#1132)
* \[Feat] Integration with loaders.gl 2.2 (#1156)
* \[Feat] Bump deck.gl and luma.gl to v8.2 (#1166)
* \[Chore] Bump websocket-extensions from 0.1.3 to 0.1.4 (#1138)
* \[Website] Add 2020 Survey (#1154)
* \[Bug] Tooltip formatting (#1129)
* \[Jupyter] Default centerMap to False so that zoom map state configurations are not (#1142)
* \[Enhancement] close modal when press escape key (#1134)
* \[Enhancement] Export time widget factories (#1133)
* \[Enhancement] filter invalid value when calculate trip layer domain (#1131)
* \[Feat] enable tooltip formatting in interaction config (#1102)
* \[Feat] Add type definition (#1116)
* \[RFC] table class RFC (#1109)
* \[Docs] adding missing bracket (#1094)
* add side-panel inner class (#1113)
* \[Bug] add hexagon layer translation (#1114)
* \[Jupyter] fix gitignore add missing files (#1118)
* \[Jupyter] Publish keplergl jupyter 0.2.0 (#1110)
* \[Enhancement] fix attribution color, add kepler smaller font (#1092)

## \[2.2.0] - May 10 2020

* \[Enhancement] Added Editor and FeatureActionPanel factories (#1093)
* \[Feat] Geocoder Search (#1068)
* \[Doc] Updated release docs with gh-release instructions (#1059)
* \[Bug] Aggregation layer fix out-of-domain coloring for valid strings (#1070)
* \[Feat] Add Spanish and Catalan translation (#1087)
* \[Doc] Update playback documentation (#1072)
* \[Bug] Fix link to umd folder
* \[Doc] Refactored doc files for better structure (#1084)
* \[Enhancement] Add Portuguese translations (#1063)
* \[Bug] Fixed download file for microsoft edge (#1074)
* \[Bug] Fix broken redirects in jupyter user guide (#1077)
* \[Docs] update upgrade guide (#1044)

## \[2.1.2] - April 3 2020

* \[Enhancement] Add support for localization and Finnish translations (#994)
* \[Bug] Fixes for case sensitive fields in CARTO storage (#1057)
* \[Chore] Removed engine requirements (#1049)
* \[Chore] Improve the secondary button color for base theme (#1048)
* \[Chore] Updated examples to v2.1.1 (#1043)

## \[2.1.1] - March 31 2020

* \[Chore] Updated example to 2.1.0 (#1041)

## \[2.1.0] - March 30 2020

* \[Enhancement] Remove table cell char limit and increased cell header height (#1038)
* \[Docs] CHANGELOG.md markup update (#1029)
* \[Enhancement] add classes to button for easier style override (#1035)
* \[Bugfix] Remove incorrect outlier calculation for better map centering (#1026)
* \[Bug] fix scatterplot stroke width in pixels (#1018)
* \[Test] e2e test (#940)
* \[Enhancement] Move layer panel visible toggle to end (#1017)
* \[Bug] export formatCsv (#1022)
* \[Enhancement] Refactor load file tasks to better handle multiple file types (#986)
* \[Bug] Fixed carto-provider example: importing the correct kepler.gl processor path (#1016)
* \[Feat] Add satellite basemap (#1007)
* \[Feat] Improved data table rendering (#1010)
* \[Chore] Upgrade to Node 10 (#1009)
* \[Feat] S2 layer (#800)
* \[BUG] Fix provider test (#1008)
* \[Enhancement] better handling provider tile update (#1000)
* \[Enhancement] Loading and error feedback for shared maps loaded from URL #1002 (#1003)
* \[Enhancement] adjust button color in light theme (#1004)
* \[Bug] Reset selected provider status after loading and before sharing (#999)
* \[Feat] Add more light themes (#1001)
* \[Bug] fix bug map loaded with custom map style not save correctly (#993)
* \[Bug] Fix username set to null after loading map from URL #995 (#996)
* \[Enhancement] Decrease filter step size for small domains (#958)

## \[2.0.1] - March 9 2020

* \[Bug] Add cloud-providers.js to package.json (#991)
* \[Feat] CARTO provider for cloud storage (#985)
* \[Bugfix] Fix typo on variable name (#987)
* \[Enhancement] pass appWebsite to logo component (#984)
* \[Chore] Removed testing from publish action (#980)
* \[Bug] remove console.log in filter.utils
* \[Feat] Load cloud map with provider (#947)

## \[2.0.0] - Feb 25 2020

* \[Enhancement] Independently customize Geojson layer fill stroke opacity (#966)
* \[Bug] Fix text collision on toggle input (#973)
* \[Chore] upgrade prettier to 1.19 to better handle single line function compositions (#971)
* \[Style] run prettier and lint on tests (#968)
* \[Bug] Select dataset filter bug (#965)
* \[Bug] fix hexagon layer hover crash (#964)
* \[Style] run prettier (#963)
* \[Feat] Allow adding custom side panel tabs
* \[Chore] Fix prettier update config (#767)
* \[Bug] Fixed json map export and added tests (#956)
* \[Bug] Resolve deck luma version conflict (#955)
* \[Feat] upgrade to deck.gl\@8 (#889)
* \[Feat] UI for save map to backend storage (#906)
* \[Bug] Fixed geo-filter extra layer issue (#936)
* \[Bug] Fix low projection accuracy in higher zoom level (#946)
* \[Bug] fix hexagon layer hover cause app crash (#933)
* \[Bug] fix heatmap crash when there is no filter (#934)
* \[Bug] should add redux devtools in demo app by default (#932)
* \[Feat] Gpu data filter (#878)
* \[Feat] Global export of image export constants (#923)
* \[Bug] Fix mix int/float column interpreted as sting (#927)
* \[Chore] Correctly update the copy changes to actions.js (#914)
* \[Enhancement] Hide data modal in export map (#920)
* \[Chore] remove action to publish to github package repo (#919)
* \[Feat] Geo-Operations: create and apply polygon filters (#595)
* \[Bug] Fix h3 layer projection error at edge of world map (#918)

## \[1.1.13] - Jan 17 2020

* \[Enhancement] added coordinate to tooltip export configuration (#876)
* \[Bug] mapState not applied in exported map html (#913)
* \[Chore] Update grammar, cleanup whitespace, fix broken link (#912)
* \[Docs] add Upgrade-guide
* \[Docs] Remove hyperlink with "Advanced Usage" (#903)
* \[Docs] add initial cloud provider api (#868)
* \[Enhancement] treat type-analyzer type: NUMBER as strings (#891)
* \[Bug] remove argument.length check in injector (#899)
* \[Enhancement] add disabled to layer-configurator group (#897)
* \[Bug] Fix a bug in file-drop.js that causes error in server side render (#896)
* \[Bug] Ensure all colors returned from get3DBuildingColor are RGB arrays (#871)
* \[Chore] License 2020 (#883)
* \[Bug] Correctly copy over field.filterProps when merging multiple filters (#884)
* \[Bug] Fix newDateEntries typo and formatting fixes (#870)
* \[Bug] Fix multiple geojson layer found when properties contain object and array (#872)
* \[Bug] fix demo-app resolve react-redux (#866)

## \[1.1.12] - Dec 14 2019

* \[Bug] Remove sqrt, log from default color aggregation for count (#856)
* \[Bug] fix cluster point count, cluster layer failed to render on export image (#855)
* \[Style] Remove extra semicolon (#850)
* \[Docs] Update api-reference overview links
* \[Bug] Don't merge domain when update filter name (#841)
* \[Enhancement] React 17: replace componentWillReceiveProps and componentWillMount (#745)
* \[Bug] Fixed delete dataset action (#835)
* \[Chore] Github action to publish npm package (#825)
* \[Enhancement] Demo App Cloud provider refactor (#831)

## \[1.1.11] - Nov 13 2019

* \[Bug] Correctly save filterProps to field while merging filter from config (#829)
* \[Docs] fixing api reference broken link (#812)
* \[Bug] fix empty geometry causing trip layer detection to fail (#826)
* \[Docs] update a-add-data-to-the-map.md with embed geometries in CSV

## \[1.1.10] - Oct 30 2019

* \[Docs] Add instructions for image and weblink in tooltip (#797)
* \[Enhancement] Add Bug Report User Guides to demo app panel header (#787)
* \[Docs] Fix typos in add-data-workflow-user-guide (#807)
* \[Feat] add stdev and variance aggregators to aggregation layer (#809)
* \[Feat] Multiple datasets per filter (#773)
* \[Bug] Fixed loading urls with query params (#780)
* \[Jupyter] Publish keplergl jupyter 0.1.2 (#784)

## \[1.1.9] - Oct 11 2019

* \[Enhancement] improve Geojson processing performance and error handling (#781)
* \[Enhancement] add file format instruction to file upload (#770)
* \[Bug] Filter invalid H3 IDs (#775)
* \[Bug] fix readonly in addDataToMap (#783)
* \[Enhancement] Expose LayerHoverInfoFactory and CoordinateInfoFactory (#769)
* \[Bug] Fixed dropbox upload in Firefox. Passing explicit file name to upload function
* \[Enhancement] Demo app sample info (#758)
* \[Enhancement] Generate custom map style icon from style url (#762)
* \[Jupyter]\[bug] fix lab widget window responsiveness, add version to header (#771)
* \[Jupyter]\[docs] add installation instruction to jupyter widget user guide
* \[Docs] Update add data to map docs
* \[Jupyter] Publish keplergl-jupyter for Jupyter labs (#764)
* \[Jupyter]\[bug] fix flashing html export when open in window (#756)
* \[Enhancement] Add logo and GA to exported html (#757)
* \[Docs] update Trip Layer md

## \[1.1.8] - Sep 30 2019

* \[Bug] Fix saving animation speed (#752)
* \[Feat] Add Trip Layer - Final (#699)
* \[Feat] add custom color editor (#601)
* \[Chore] add coverall (#748)
* \[Docs] mapboxApiUrl usage examples (#737)
* \[Feat] Support Policy page (#724)

## \[1.1.7] - Sep 11 2019

* \[Enhancement] Create more factories from SourceDataCatalog, add onClickTitle (#720)
* \[Enhancement] Express example (#704)
* \[Bug] check new layers based on new dataset id (#721)
* \[Feat] Add Log and Sqrt scale (#670)
* \[Chore] Add a script to automatically edit kepler.gl version (#714)

## \[1.1.6] - Sep 5 2019

* \[Bug] Upgrade to deck 7.1.11 (#715)

## \[1.1.5] - Sep 4 2019

* \[Bug] Unlock luma.gl version (#713)
* \[Bug] fix heatmap getBounds (#711)
* \[Feat] HTML Export: provide read only mode (#709)

## \[1.1.4] - Sep 3 2019

* \[Bug] Lock deck.gl to version 7.1.5 (#688)
* \[Enhancement] add keepExistingConfig option to addDataToMap (#619)
* \[Bug] Fixed issue with geojson fields (#683)
* \[Enhancement] Switch from callback refs to createRef (#622)
* \[Bug] Fix uglify error compiling dom-to-image in prod (#682)
* \[Enhancement] pass set useDevicePixels to deck.gl to plot container (#663)
* \[jupyter] Upgrade to kepler.gl v1.1.3 (#660)
* \[Chore] use xvfb as a service in travis-ci (#669)

## \[1.1.3] - Aug 5 2019

* \[Enhancement] Use preserved state to apply keplerGlInit. when mint=false (#649)
* \[Enhancement] Replace react-data-grid with react-virtualized (#629)

## \[1.1.2] - Aug 1 2019

* \[Bug] Fix issue in Layer.registerVisConfig preventing custom boolean properties
* \[Enhancement] Simplify map layer visible logic in splitMaps and deck, mapbox overlay renders (#642)
* Netlify badge (#641)
* \[Enhancement] Add 3d building color editor (#633)
* \[Enhancement] Update mapbox-gl css version (#634)
* \[Bug] fix SolidPolygonLayer import causing 3d building layer crash (#625)
* \[Bug] Don't show null for labels if there is no data (#626)
* \[Bug] add deckGlProps to pass preserveDrawingBuffer to plot container (#624)
* \[Enhancement] DemoApp: explicitly pass window\.fetch to Dropbox to suppress warning (#621)
* \[Enhancement] Use theme in histogram plot color (#607)
* \[Enhancement] Bump supercluster version (#590)
* \[Feat] Add mapboxApiUrl to `KeplerGL` (#554)
* \[Docs] Update link to the GitHub repo (#589)
* Fixed python3 compatiability and wrong variable in string format (#587)
* \[Bug] Remove isMouseOver state from MapPopover (#577)
* \[Docs] fix: Correct Custom Theme Example Link (#578)
* \[Bug]\[jupyter] Replacing print statement with () to make it Python 3 compatible (#582)
* Update build command: remove yarn since netlify runs yarn by default (#585)
* \[Jupyter] cleanup examples (#574)
* \[Feat] Publish keplergl jupyter 0.1.0a5 (#572)
* \[Chore] Add issue template for kepler.gl Jupyter
* \[Bug] Solve issue #547 avoid crash application (#564)

## \[1.1.1] - Jun 24 2019

* \[Bug] Fix radius rendering when value = 0 (#551)
* \[Docs] Updating Layer User Guides (#373)
* \[Feat] Display mouse coordinate (#550)
* \[Docs] Replace CLA with DCO (162a9f7)
* \[Style] fix README typo (c1fafbf)
* \[Docs] Add jupyter widget user guide link o README (17d3ec8)
* \[Chore] Add jupyter widget issue templates (a40c1fe)
* \[Feat] Bump deck.gl to v7.1.5 (#568)
* \[Feat] Add ScenegraphLayer (#540)
* \[Feat] Add kepler.gl-jupyter python package (#543)

## \[1.1.0] - Jun 15 2019

* Upgrade to deck.gl 7.1 (#559)
* \[Docs] update user documentation with newer layers and features (#552)
* Upgrade to deck.gl 7 and luma.gl 7 (#544)
* \[Bug] Display color legend for stroke color scale (#546)
* \[Enhancement] Image export error handling (#538)
* \[Bug] Fix typo on layer-configurator.js (#549)

## \[1.0.0] - May 23 2019

* \[Enhancement] Detecting mapbox token validity (#513)
* \[Enhancement] Netlify webpack optimization (#525)
* \[Feat] More control over point label (#515)
* \[Enhancement] Applied changes for enable netlify deployment (#516)
* \[Enhancement] Refactored modal dialog to be more responsive (#501)
* \[Bug] fix side panel unnecessary rerender (#512)
* \[Feat] Upgrade deck.gl to 6.4 (#456)
* \[BUG] Fixed layer list sorting dnd effect (#509)
* \[Feat] add onViewStateChange callback to KeplerGl (#506)
* \[Enhancement] More granular speed control (#500)
* \[Docs] update all uber links to keplergl org (#502)

## \[1.0.0-2] - May 2 2019

* \[Bug] Fix missing default map styles after loading custom map style from saved json (#490)
* \[Bug] Fix `fix radius` in point layer unclickable (#491)
* \[Bug] fix image export doesnt get called when map rendered (#494)
* \[Enhancement] Merge export config and map into one interaction (#488)

## \[1.0.0-1] - Apr 23 2019

* \[Bug] Fix point layer brushing and highlight (#487)
* \[Feat] Add a light theme to KeplerGl Prop (#489)
* \[Bug] Fix browse for file upload (#486)
* \[Enhancement] Cleanup load map style tasks (#472)
* \[Enhancement] load svg icons from aws, add bundle analyzer, reduce bundle size -1mb (#479)
* \[Bug] upgrade kepler.gl version in examples
* \[Docs] Fixed link to addDataToMap (#459)
* \[Enhancement] expand bottom widget to full length if in read only mode(#465)

## \[1.0.0-0] - Apr 2 2019

* \[Enhancement] Replace react anything sortable with React-Sortable-Hoc
* \[Enhancement] Replaced DI object storage with an actual Map
* \[Feat] Able to overwrite custom theme
* \[Chore] Upgraded waypoint library to support react16
* \[Chore] Dropbox UI enhancements
* \[Bug] Fix points disappear while panning across 180th meridian
* \[Chore] Tweak save and export documentation
* \[Chore] Add oss header and middleware.js
* \[Chore] Added file header for user-guide.js
* \[Feat] Single map page export
* \[Chore] Upgraded libraries: react, styled-components

**BREAKING CHANGES**

* React 15 is no longer supported
* Style components v4+ is now required because is now a peer dependency

## \[0.2.4] - Mar 13 2019

* \[Enhancement] Slider: use clientX to calculate delta to support windows IE and Tableau kepler.gl (#431)
* \[Bug] Range slider: correctly setting ranch brush selection when mount (#433)
* \[Feat] Add getMapboxRef prop (#372)
* \[Enhancement] Automatically loading custom dependencies when inject custom component factor (#430)
* \[Bug] Range brush width change should not trigger onBrush callback (#432)
* \[Bug] fix processor export, support previous (#428)

## \[0.2.3] - Mar 3 2019

* \[Docs] Export processors and Add Docs (#421)
* \[Docs] Add docs for actions and updaters (#368)
* \[Bug] Fix image export component failed to render (#418)

## \[0.2.2] - Feb 26 2019

* (HEAD -> master, origin/master, origin/HEAD) \[Bug] Fixed web doc link (#369)
* \[Bug]: Fixed example dependencies (#362)
* \[Bug] Fix missing 3d building layer in image export (#361)
* \[Bug] fix 3d building layer missing mapbox token, fix image export (#360)
* \[Docs] Add API Docs (#279)
* \[Feature] UMD module in unpkg (#349)
* Disabled banner (#352)

## \[0.2.1] - Feb 6 2019

* (HEAD -> master, origin/master) \[Feature] Collapsible layer group (#350)
* \[Enhancement] Added default feature flags to disable dropbox (#338)
* \[Bug]: fix alias and module resolve in webpack.config.local (#348)
* \[Enhancement] Upgraded Webpack, Babel and Eslint (#342)
* \[Feature] Notification systems with new UI panel and helpers to generate messages (#333)
* GitHub browser history (#321)
* \[Bug] Fix Maximum call stack size exceeded when double click (#323)
* \[Docs] Export identity actions individually and add JSDocs (#290)
* \[Docs] Edit PR guidance in contribution guidelines (#320)
* \[Docs] Add Contribution Guidelines (#261)
* (overide-style) \[Enhancement] Upgrade type-analyzer to pass 0/1 as integer (#317)
* \[Typo] Misspellings in comments (#314)
* \[Housekeeping] Update Copyright header to 2019, Happy New Year (#316)
* Feat: Implemented Dropbox integration (#312)

## \[0.2.1-beta.1] - Dec 17 2018

* \[Feature] Added a Tiled 3D Building Deck.gl Layer (#270)
* \[Enhancement] Fossa Integration (#309)
* \[Enhancement] Change BottomWidget to pure functional component (#249)
* \[Docs]: updated docs for better readability(alignments) (#255)
* \[Enhancement] export processKeplerglJSON from processors (#299)
* \[website] BugFix: missing tracking payload (#311)
* \[Enhancement] Hexbin Layer: smaller radius step and dynamic hover (#310)
* \[Bug] remove unpm from yarn.lock (#303)
* \[Enhancement] use mapbox style url for default (published) uber map styles (#292)
* \[Feature] Load data and kepler.gl file using URLs (#260)

## \[0.2.1-beta.0] - Nov 16 2018

* \[Bug] Fixing global color issue #130 for the heat map (#277)
* \[Enhancement] More exports (#284)

## \[0.2.0] - Nov 16 2018

* \[Enhancement] Export side panel component factories (#282)
* \[Feature] Upgrade to deck.gl v6 (#272)
* \[Refactor] Small update of readability (#250)
* \[website] Click logo should go to kepler.gl website (#251)
* \[Enhancement] Add contribution guidelines on contributing.md file (#108)
* \[Enhancement] Scan through all text labels to get the entire character set (#245)

## \[0.1.6] - Oct 3 2018

* \[Enhancement] save and load text label config (#242)

## \[0.1.5] - Oct 2 2018

* \[Enhancement] Fix z-fighting issue between text label and scatter plot (#234)
* \[Bug] Sort color steps (#241)
* \[Bug] fix a bug where field is valid is always false (#240)

## \[0.1.4] - Sep 15 2018

* \[Enhancement] Null check for missing arc column (#235)

## \[0.1.3] - Sep 10 2018

* \[Enhancement] Add H3 layer (#217) (#198)
* \[Enhancement] Add text label in Point layer (#166)

## \[0.1.2] - Aug 24 2018

* \[Bug] Fix server render error, remove react-ace (#206)

## \[0.1.1] - Aug 24 2018

* \[Enhancement] Bump react-palm\@1.1.2 (#215)

## \[0.1.0] - Aug 21 2018

* Upgrade to Deck.gl v5.3.4 (#153)

## \[0.0.28] - Aug 8 2018

* Fix cluster layer label rendering

## \[0.0.27] - Aug 3 2018

* Fix unable to fetch external stylesheets when taking the screenshot (#187)
* \[Bug] Avoid repeatedly calling HIDE\_EXPORT\_DROPDOWN (#180)

## \[0.0.26] - Aug 3 2018

* \[Bug] fix mapStyles loaded as an empty object after load map from config (#169)

## \[0.0.25] - Jul 10 2018

* \[Bug] Create ellipsis when dataset name is a long name (#109)
* \[Enhancement] Save custom reducer initialState, add custom-reducer example (#159)

## \[0.0.24] - Jul 5 2018

* \[Bug] fix image export failing (#155)
* \[Enhancement] Add default map styles to mapStyle reducer initial state (#147)

## \[0.0.23] - Jun 28 2018

* \[Enhancement] Consider all mew layers when calculating the map bounds (#142)
* \[Bug] Fix icon layer instructions (#131)
* \[Website] add banner to demo app for survey (#117)

## \[0.0.22] - Jun 10 2018

* \[Bug] new filter shouldn't be enlarged if there is already an enlarged filter (#93)
* \[Enhancement] Enable ordinal aggregation in aggregation layer (hex, grid, cluster) (#29)

## \[0.0.21]\[0.0.20] - Jun 4 2018

* \[Bug] TimeRangeSlider should not cache props.onChange (#100)


# Upgrade Guide

## Table of Content

* [v3.2 to v3.3](#upgrade-from-v32-to-v33)
* [v2.4 to v3.0](#upgrade-from-v24-to-v30)
* [v2.3 to v2.4](#upgrade-from-v23-to-v24)
* [v2.2 to v2.3](#upgrade-from-v22-to-v23)
* [v2.1 to v2.2](#upgrade-from-v21-to-v22)
* [v2.0 to v2.1](#upgrade-from-v20-to-v21)
* [v1.1.12 to v2.0](#upgrade-from-v1112-to-v20)
* [v1.1.11 to v1.1.12](#upgrade-from-v1111-to-v1112)

## Upgrade from v3.2 to v3.3

See the full upgrade guide: [**Upgrade Guide — kepler.gl 3.3**](/upgrade-guide-v3.3)

### Highlights

* **React 19** — kepler.gl now requires `react@^19.0.0` and `react-dom@^19.0.0`. React 18 is no longer supported.
* **react-redux v9** — upgraded from `^8.0.5` to `^9.1.0`
* **react-intl v7** — upgraded from `^6.3.0` to `^7.0.0`
* **react-map-gl 8 / maplibre-gl 4** — new `@vis.gl/react-maplibre` peer dependency
* **deck.gl 9 / luma.gl 9** — major rendering stack upgrade
* **Node.js 20** — minimum raised from 18.18.2 to 20.19.3
* **TypeScript 5.6** — upgraded from 4.7.2
* **HeatmapLayer** — rewritten from Mapbox GL to deck.gl base
* **`layerOrder`** — type changed from flat `string[]` to `(string | LayerOrderGroup)[]`
* **`LayerSelectorPanelFactory`** — removed from `@kepler.gl/components`

## Upgrade from v2.4 to v3.0

* TBD

## Upgrade from v2.3 to v2.4

### Breaking Changes

* Supports React 17
* Dependency Upgrades, major ones: `d3-xxx@^2`, `redux@4.0.5`, `type-analyzer@0.3.0`, `react-palm@~3.3.7`

### New Features

* Support incremental timeline animation
* Allow changing dataset in layer config
* Enable polygon filter for h3 layer
* Show last added filter at the top

### Bug Fixes

* Avoid duplicated h3 layer detection
* Fixed bug when reversing color palette not update

## Upgrade from v2.2 to v2.3

* Upgrade dependencies to `deck.gl@8.2.0`, `loaders.gl@2.2.5` and `luma.gl@8.2.0`. This should only affects projects with the above libraries in its dependencies.

## Upgrade from v2.1 to v2.2

### New Features

* **Interaction** - Added Geocoder in the interactin panel

### Improvements

* **Localization** - Added Spanish, Catalan, and Portuguese translations

### Bug Fixes

* **Layer** - Aggregation layer fix out-of-domain coloring for valid strings
* **Export** - Fixed download file for microsoft edge

### API Update

* **Components** - Exported map drawing editor factories

## Upgrade from v2.0 to v2.1

### Breaking Changes

* Upgrade Node v10 for dev development, node requirement is now at `>=10.15.0`

### New Features

* **Provider** - Add cloud provider API
* **Layer** - Added S2 Layer
* **Basemap** - Added satellite to base map styles options
* **Theme** - Added base UI theme to theme option as `base`

### Improvements

* **UI** - Improved data table and layer panel header
* **Filter** - Better handle filter steps for small domains

### Bug Fixes

* **Layer** - Remove incorrect outlier for better map center detection
* **Layer** - Fix point layer stroke width
* **Basemap** - Fix bug custom map style not saved correctly
* **Export** - Fix bug exported html blank

***

## Upgrade from v1.1.12 to v2.0

### Breaking Changes

* Upgrade deck.gl to `8.0.15`, this only affects projects with deck.gl in its dependencies. Because only one version of deck.gl can be loaded.

### New Features

* **GPU Filter** - Improved time and numeric filter performance by moving calculation to GPU
* **Geo Fitler** - Added drawing polygon function, allow filter layer based on polygon

### Improvements

* **Layer** - Improved GeoJson and H3 layer geometry rendering
* **UI** - Support custom side panel tabs. [example](https://github.com/keplergl/kepler.gl/tree/master/examples/replace-component)

### Bug Fixes

***

## Upgrade from v1.1.11 to v1.1.12

### Breaking Changes

#### Dependency Upgrade

* **react** and **react-dom**: minimum required version is now `^16.3`
* **react-redux** is upgraded to `^7.1.3`. If you have older version of `react-redux` in your app. You will have error loading kepler.gl, likely due to multiple version of `react-redux` installed.
* **react-palm**: required version is now `^3.1.2`.
* **react-route**: if you are using `react-router`, we suggest using `^3.2.5` to avoid `React 16.8` lifecycle deprecation warning in the console.

### Bug Fixes

* **Cluster Layer**: Fix incorrect cluster point count. Fix cluster layer missing in exported image.

### Moved from `kepler.gl/utils` to `@kepler.gl/table`

* `maybeToDate`
* `getNewDatasetColor`
* `createNewDataEntry`
* `setFilterGpuMode`
* `assignGpuChannels`
* `assignGpuChannel`
* `resetFilterGpuMode`
* `getGpuFilterProps`
* `getDatasetFieldIndexForFilter`

### Moved from `kepler.gl/utils` to `@kepler.gl/reducers`

* `findMapBounds`
* `exportData`
* `TOOLTIP_MINUS_SIGN`
* `getDefaultInteraction`
* `BRUSH_CONFIG`
* `findFieldsToShow`
* `getTooltipDisplayDeltaValue`
* `getTooltipDisplayValue`
* `LayersToRender`
* `AggregationLayerHoverData`
* `LayerHoverProp`
* `findDefaultLayer`
* `calculateLayerData`
* `getLayerHoverProp`
* `renderDeckGlLayer`
* `isLayerRenderable`
* `isLayerVisible`
* `prepareLayersForDeck`
* `prepareLayersToRender`
* `getCustomDeckLayers`
* `ComputeDeckLayersProps`
* `computeDeckLayers`

### Moved from `kepler.gl/processors` to `@kepler.gl/utils`

* `ACCEPTED_ANALYZER_TYPES`
* `validateInputData`
* `getSampleForTypeAnalyze`
* `getFieldsFromData`
* `renameDuplicateFields`
* `analyzerTypeToFieldType`

### Moved from `kepler.gl/templates` to `@kepler.gl/utils`

* `exportMapToHTML`

### Moved from `kepler.gl/layers` to `@kepler.gl/utils`

* `getCentroid`
* `idToPolygonGeo`
* `h3IsValid`
* `getHexFields`


# Upgrade Guide v3.3

kepler.gl 3.3 upgrades the rendering stack from **deck.gl 8 / luma.gl 8** to **deck.gl 9 / luma.gl 9**. This is a major dependency upgrade that changes how WebGL resources, shaders, and rendering parameters are handled under the hood. Most kepler.gl users will not need to change application code, but library consumers who extend layers, interact with the WebGL context directly, or depend on internal types should review this guide.

## Dependency Changes

| Package group   | Old version | New version   |
| --------------- | ----------- | ------------- |
| `react`         | ^18.2.0     | **^19.0.0**   |
| `react-dom`     | ^18.2.0     | **^19.0.0**   |
| `react-redux`   | ^8.0.5      | **^9.1.0**    |
| `react-intl`    | ^6.3.0      | **^7.0.0**    |
| `react-map-gl`  | ^7.1.6      | **^8.1.1**    |
| `maplibre-gl`   | ^3.6.2      | **^4.0.0**    |
| `@deck.gl/*`    | 8.9.x       | **9.2.11**    |
| `@luma.gl/*`    | 8.x         | **9.2.6**     |
| `@loaders.gl/*` | 3.x / 4.3.2 | **4.3.4**     |
| `math.gl`       | —           | **^4.1.0**    |
| `typescript`    | 4.7.2       | **5.6.3**     |
| Node.js         | >=18.18.2   | **>=20.19.3** |

### New dependencies

| Package                                 | Version | Notes                                         |
| --------------------------------------- | ------- | --------------------------------------------- |
| `@vis.gl/react-maplibre`                | 8.1.1   | MapLibre bindings for react-map-gl 8          |
| `maplibregl-mapbox-request-transformer` | ^0.0.2  | Mapbox-style URL transform for MapLibre       |
| `@deck.gl-community/editable-layers`    | 9.2.8   | Replaces `@nebula.gl/layers` for editor layer |
| `@deck.gl-community/layers`             | 9.2.8   | Community layers package                      |
| `@deck.gl/widgets`                      | 9.2.11  | New deck.gl 9 module                          |
| `@luma.gl/effects`                      | 9.2.6   | New luma.gl 9 module                          |
| `@luma.gl/webgpu`                       | 9.2.6   | Dev dependency for test environment           |

### Removed dependencies

| Package                             | Notes                                            |
| ----------------------------------- | ------------------------------------------------ |
| `hubble.gl/core`, `hubble.gl/react` | Removed from kepler.gl                           |
| `@nebula.gl/layers`                 | Replaced by `@deck.gl-community/editable-layers` |

### Yarn resolutions

All `@deck.gl/*`, `@loaders.gl/*`, and `@luma.gl/*` packages are pinned via resolutions. If your project has its own resolutions for these packages, make sure they are consistent with the versions above.

***

## Breaking Changes — React 19

kepler.gl 3.3 requires **React 19**. React 18 is no longer supported.

```sh
npm install react@^19.0.0 react-dom@^19.0.0 react-redux@^9.1.0
```

### Removed legacy lifecycle methods

All usage of deprecated lifecycle methods (`componentWillReceiveProps`, `componentWillMount`) has been removed. If you have custom components extending kepler.gl internals that rely on these methods, migrate them to `componentDidUpdate`, `getDerivedStateFromProps`, or hooks.

### `ref` handling

React 19 passes `ref` as a regular prop. If you have custom wrapper components using `React.forwardRef` around kepler.gl components, these will still work but `forwardRef` is no longer required for new components.

### Strict Mode

React 19 enforces stricter Strict Mode behavior. If your application uses `<React.StrictMode>`, you may notice double-invocation of effects during development. This does not affect production builds.

### `react-redux` v9

The upgrade to `react-redux@^9.1.0` drops the legacy context API. Ensure you are not relying on the removed `store` prop passed directly to connected components — use `<Provider store={store}>` at the root instead.

### `react-intl` v7

`react-intl` is upgraded to v7. If your app provides custom format configurations or uses `intlShape`, consult the [react-intl 7.x migration guide](https://formatjs.github.io/docs/react-intl/upgrade-guide-7x/).

### Upgrading custom components

If you use kepler.gl's dependency injection to replace built-in components:

1. Replace any class components with function components using hooks
2. Remove `defaultProps` declarations — use default parameter values instead
3. Update any `propTypes` usage (still functional but no longer shipped with kepler.gl)

***

## Breaking Changes — Map Libraries

### react-map-gl 8 and maplibre-gl 4

`react-map-gl` is upgraded from `^7.1.6` to `^8.1.1`, and `maplibre-gl` from `^3.6.2` to `^4.0.0`. A new dependency `@vis.gl/react-maplibre` (`8.1.1`) has been added.

```sh
npm install react-map-gl@^8.1.1 maplibre-gl@^4.0.0 @vis.gl/react-maplibre@8.1.1
```

If your application imports from `react-map-gl` directly (e.g., for custom map overlays), review the [react-map-gl 8.x upgrade guide](https://visgl.github.io/react-map-gl/docs/upgrade-guide) for API changes.

### maplibre-gl 4

maplibre-gl v4 includes breaking changes to the style specification and internal rendering pipeline. If you use `maplibregl` directly or supply custom map styles, consult the [maplibre-gl v4 changelog](https://github.com/maplibre/maplibre-gl-js/blob/main/CHANGELOG.md).

***

## Breaking Changes — Node.js

### Minimum Node.js version raised to 20

The minimum required Node.js version is now **20.19.3** (previously 18.18.2). Update your CI and development environments accordingly:

```sh
nvm install 20
nvm use 20
```

***

## Breaking Changes — Layers

### HeatmapLayer rewritten from Mapbox GL to deck.gl

`HeatmapLayer` no longer extends `MapboxGLLayer`. It now extends the base `Layer` class and renders using a deck.gl-based implementation.

**Impact:**

* If you extended `HeatmapLayer` or relied on its Mapbox GL internals, your subclass will break.
* The layer config type changed from `MapboxLayerGLConfig` to `LayerBaseConfig`.
* New visual config properties: `intensity`, `threshold`, `aggregation`.
* A new column mode `COLUMN_MODE_GEOJSON` is supported.

If you have custom code that checks `layer instanceof MapboxGLLayer` for heatmap layers, update it to check `layer instanceof Layer` or use `layer.type === 'heatmap'`.

### `layerOrder` type changed

The `layerOrder` property in `visState` changed from a flat `string[]` to `LayerOrderEntry[]`, where:

```typescript
type LayerOrderGroup = {
  id: string;
  label: string;
  isVisible: boolean;
  layerOrder: LayerOrder;
  isIncludedInLegend: boolean;
};
type LayerOrderEntry = string | LayerOrderGroup;
type LayerOrder = LayerOrderEntry[];
```

If your application reads or manipulates `state.keplerGl.*.visState.layerOrder` directly (e.g., for custom layer reordering), update your code to handle mixed arrays of layer IDs and group objects. Use the helper `getFlatLayerOrder(layerOrder)` from `@kepler.gl/utils` to get a flat list of layer IDs.

***

## Breaking Changes — Removed Exports

### `LayerSelectorPanelFactory` removed

`LayerSelectorPanelFactory` is no longer exported from `@kepler.gl/components`. If you were using dependency injection to replace this factory, the functionality has been reorganized — use the layer list panel and layer group components instead.

### `setLayerBlending` removed

The function `setLayerBlending` (previously exported from `@kepler.gl/utils`) is removed. Use `getLayerBlendingParameters` instead, which returns a `parameters` object for deck.gl 9.

***

## Breaking Changes — Behavior

### `preserveDrawingBuffer` disabled by default

The base map's WebGL context previously set `preserveDrawingBuffer: true` unconditionally. It is now **`false` by default** and only enabled during image/video export (`isExport: true`).

**Impact:** If your application calls `canvas.toDataURL()` or `canvas.toBlob()` on kepler.gl's map canvas outside of the built-in export flow, the canvas will now return blank data. To restore the old behavior, pass `preserveDrawingBuffer: true` via `bottomMapContainerProps` in your `MapContainer` override.

### `GEOCODER_ICON_SIZE` constant changed

`GEOCODER_ICON_SIZE` changed from `80` to `160` to compensate for anchor normalization in the new rendering stack. If you import this constant for custom geocoder styling, the rendered pin size should remain the same visually — but if you used the raw value for calculations, update accordingly.

***

## Breaking Changes for Library Consumers

### 1. WebGL context callback renamed

The `DeckGL` component callback changed from `onWebGLInitialized` to `onDeviceInitialized`. The callback now receives a luma.gl `Device` instead of a raw `WebGLRenderingContext`.

If you override `MapContainerFactory` and rely on the initialization callback:

```diff
- onWebGLInitialized={gl => this._onDeckInitialized(gl)}
+ onDeviceInitialized={device => this._onDeckInitialized(device)}
```

### 2. Layer blending is now declarative

In deck.gl 8, kepler.gl called `setParameters(gl, {...})` with GL constants before each render to set blending mode. In deck.gl 9, blending is set via a `parameters` prop on `DeckGL` using WebGPU-style string constants.

**Old (removed):**

```js
import {setParameters} from '@luma.gl/core';
setParameters(gl, {
  blendFunc: [GL.SRC_ALPHA, GL.ONE_MINUS_SRC_ALPHA],
  blendEquation: GL.FUNC_ADD
});
```

**New:**

```js
import {getLayerBlendingParameters} from '@kepler.gl/utils';
<DeckGL parameters={getLayerBlendingParameters(layerBlending)} />;
```

If your application calls `setParameters` for blending, migrate to the `parameters` prop instead.

### 3. GPU parameter constants

A new module `@kepler.gl/constants` exports WebGPU-style string constants that replace the old GL enum values throughout the codebase:

* `BLEND_FACTOR` — `'zero'`, `'one'`, `'src-alpha'`, etc.
* `BLEND_OPERATION` — `'add'`, `'subtract'`, etc.
* `FILTER_MODE` — `'nearest'`, `'linear'`
* `ADDRESS_MODE` — `'clamp-to-edge'`, `'repeat'`, `'mirror-repeat'`
* `TEXTURE_FORMAT` — `'r8uint'`, `'rgba8unorm'`, etc.
* `TOPOLOGY` — `'triangle-list'`, `'triangle-strip'`, etc.

If you referenced GL constants for kepler.gl layer configuration, switch to these string constants.

### 4. `setLayerBlending` removed

The function `setLayerBlending` (previously exported from `@kepler.gl/utils`) is removed. Use `getLayerBlendingParameters` instead, which returns a `parameters` object for deck.gl 9.

### 5. Aggregation layers use deck.gl 9 native CPU aggregation

`GridLayer` and `HexagonLayer` now use deck.gl 9's built-in CPU aggregation (`gpuAggregation: false`) instead of kepler.gl's custom `CPUAggregator`. This means:

* `onSetColorDomain` / `onSetElevationDomain` callbacks now receive `[min, max]` number arrays instead of `{domain, aggregatedBins}` objects.
* Per-bin filtering is applied at the accessor level (`getColorValue`, `getElevationValue`) rather than via a `_filterData` prop.
* `ClusterLayer` still uses the internal `CPUAggregator`.

If you listen to domain callbacks on aggregation layers, update your handler to accept the new format:

```diff
- onSetColorDomain={({domain, aggregatedBins}) => { ... }}
+ onSetColorDomain={domain => { /* domain is [min, max] */ }}
```

### 6. Shader changes — GLSL 300 es and UBOs

All custom shaders now target **GLSL 300 es**:

* `attribute` → `in`, `varying` → `in`/`out`
* `texture2D()` → `texture()`
* `gl_FragColor` → explicit `out vec4 fragColor`
* Uniforms are declared inside **Uniform Buffer Objects** (UBOs) instead of standalone `uniform` declarations. For example, `uniform float opacity` becomes a field inside a `uniform layerUniforms { float opacity; } layer;` block, accessed as `layer.opacity`.

If you have custom layers that inject into kepler.gl's shaders (via `editShader` or shader hooks), review the new GLSL 300 es syntax.

### 7. Model API changes in custom layers

If you extend any kepler.gl layer and interact with `Model` objects:

```diff
- model.setUniforms({elevationScale: 1.0});
+ model.shaderInputs.setProps({elevationScale: {elevationScale: 1.0}});
```

```diff
- model.draw();
+ model.draw(this.context.renderPass);
```

The `_getModel(gl)` pattern is replaced — models are now created from `super._getModel()` and modified via `model.setGeometry()`.

### 8. `PickInfo` type change

A custom `PickInfo<DataT>` type is now defined in `@kepler.gl/types`. This type is a relaxed version of deck.gl 9's `PickingInfo` to work around stricter generic inference in the `DeckGL` component's callback types. If you import `PickingInfo` from `@deck.gl/core`, be aware that kepler.gl's callbacks use `PickInfo` instead.

### 9. `MapViewState` type is locally defined

`MapViewState` is no longer imported from `@deck.gl/core/typed`. It is defined locally in `@kepler.gl/types` (from `reducers.d.ts`). If you were importing it from deck.gl, import from `@kepler.gl/types` instead.

### 10. Editor layers migrated to `@deck.gl-community`

The editor layer (`EditableGeoJsonLayer`) is now imported from `@deck.gl-community/editable-layers` instead of `@nebula.gl/layers`. If you extend or replace the editor layer factory, update your imports.

### 11. Lighting effect API changes

`CustomDeckLightingEffect` (kepler.gl's lighting/shadow effect) has been rewritten for deck.gl 9:

* `preRender` → `setup(context)` / `cleanup(context)` lifecycle
* `getModuleParameters` → `getShaderModuleProps`
* Shadow module uses UBO-based uniforms with `uniformTypes` declarations
* `Texture2D` constructor → `device.createTexture()`
* `addDefaultShaderModule` / `removeDefaultShaderModule` API on `deck` instance

If you extend `CustomDeckLightingEffect`, review the new lifecycle methods.

### 12. `MapView` with `legacyMeterSizes`

kepler.gl now creates `MapView` with `{legacyMeterSizes: true}` to preserve backward-compatible meter-based sizing behavior from deck.gl 8.

***

## Runtime Patches

kepler.gl 3.3 applies two patches to work around deck.gl 9 / luma.gl 9 issues. These are applied automatically and require no action, but are documented for awareness:

1. **`patchDeckRendererForPostProcessing()`** — Patches `DeckRenderer._resizeRenderBuffers` to add depth-stencil attachments to post-processing framebuffers. In deck.gl 9, FBOs are created without depth buffers by default, which breaks depth testing when post-processing effects are active.
2. **`patchPipelineValidation()`** — Patches `WEBGLRenderPipeline._getLinkStatus` to suppress false-positive "mixed sampler type" validation errors in luma.gl 9. This patch is applied lazily only when a raster tile layer is instantiated.

***

## New Features

### 3D Tile Layer (experimental)

A new **3D Tile Layer** enables rendering of photogrammetry meshes, buildings, terrain and other 3D content from OGC 3D Tiles and I3S tilesets. Supported providers:

* **OGC 3D Tiles 1.0 / 1.1** — any standard `tileset.json` endpoint.
* **Google Photorealistic 3D Tiles** — requires a Google Maps API key.
* **Cesium Ion** — requires a Cesium Ion access token.
* **ArcGIS I3S** — scene service endpoints.

Add a 3D tileset via the **Add Data → Tilesets** modal by selecting the "3D Tile" type. The layer supports opacity, point size configuration, zoom-to-layer, and the Light and Shadow effect. See the [3D Tile Layer user guide](https://github.com/keplergl/kepler.gl/blob/master/docs/user-guides/c-types-of-layers/p-3d-tile-layer.md) for details.

### Flow Layer

A new **Flow Layer** renders origin-destination flows as animated arcs with directional particles.

### Bitmap Overlay Layer

A new **Bitmap Overlay Layer** renders georeferenced raster images (PNG, JPEG) on the map.

### Swipe Compare Mode

A new map split mode (`MapSplitMode.SWIPE_COMPARE`) enables side-by-side comparison of layers using a draggable divider. Use the `setMapSplitMode` action to switch between `SINGLE_MAP`, `DUAL_MAP`, and `SWIPE_COMPARE`.

### Annotations

A new annotation system allows adding text labels, markers, and shapes directly on the map. New actions: `addAnnotation`, `removeAnnotation`, `updateAnnotation`, `duplicateAnnotation`, `setSelectedAnnotation`.

### Layer Groups

Layers can now be organized into named groups with shared visibility and legend controls. New actions: `addLayerGroup`, `removeLayerGroup`, `updateLayerGroup`, `addLayerToLayerGroup`, `removeLayerFromLayerGroup`.

### Other New Features

* **Zoom and compass controls** — on-map navigation buttons
* **Tooltip toggle** — ability to disable tooltips per-map
* **Higher pitch option** — configurable maximum pitch beyond the default 60°
* **GeoJSON mode for aggregation layers** — aggregate by polygon geometry
* **Labels for GeoJSON layer** — text label support on polygon/line features
* **Rectangle drag-to-filter** — streamlined rectangular area filter
* **Layer visibility toggle in map legend**
* **Locale persistence** — locale is included in exported maps and restored on load
* **Video export with effects** — post-processing effects are captured in video export
* **Non-linear piecewise focus range** for VisConfig sliders
* **CSV/TSV auto-delimiter detection** in data processors

### Fog post-processing effects

Two new post-processing effects are available:

* **Distance Fog** (`distanceFog`) — depth-buffer-based fog that increases with camera distance. Parameters: `density`, `fogStart`, `fogRange`, `fogColor`.
* **Surface Fog** (`surfaceFog`) — elevation-based ground fog applied below a configurable height in meters. Parameters: `density`, `height`, `thickness`, `fogColor`.

Both effects are registered in `POSTPROCESSING_EFFECTS` and can be created via `createEffect()`. Only one fog effect can be active at a time (enforced by the effect manager UI). Fog effects are ordered early in the post-processing chain to read the depth buffer before subsequent effects clear it.

***

## Known Issues

### Performance with tiled layers on older hardware

The deck.gl 9 upgrade introduces additional per-frame overhead in the layer management and GPU state pipelines compared to deck.gl 8. This may cause noticeable slowness when interacting with tiled layers (`Tile3DLayer`, raster tile layers) — especially when changing visual properties like opacity or when moving the camera over a scene with many visible tiles. The issue is more pronounced on older or lower-end GPUs and is currently under investigation.


