ag-charts-community
Version:
Advanced Charting / Charts supporting Javascript / Typescript / React / Angular / Vue
647 lines • 25.7 kB
JavaScript
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __read = (this && this.__read) || function (o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m) return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
}
catch (error) { e = { error: error }; }
finally {
try {
if (r && !r.done && (m = i["return"])) m.call(i);
}
finally { if (e) throw e.error; }
}
return ar;
};
var __spread = (this && this.__spread) || function () {
for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i]));
return ar;
};
var __values = (this && this.__values) || function(o) {
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
if (m) return m.call(o);
if (o && typeof o.length === "number") return {
next: function () {
if (o && i >= o.length) o = void 0;
return { value: o && o[i++], done: !o };
}
};
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
};
Object.defineProperty(exports, "__esModule", { value: true });
var chart_1 = require("./chart");
var series_1 = require("./series/series");
var legend_1 = require("./legend");
var chartTheme_1 = require("./themes/chartTheme");
var darkTheme_1 = require("./themes/darkTheme");
var materialLight_1 = require("./themes/materialLight");
var materialDark_1 = require("./themes/materialDark");
var pastelLight_1 = require("./themes/pastelLight");
var pastelDark_1 = require("./themes/pastelDark");
var solarLight_1 = require("./themes/solarLight");
var solarDark_1 = require("./themes/solarDark");
var vividLight_1 = require("./themes/vividLight");
var vividDark_1 = require("./themes/vividDark");
var array_1 = require("../util/array");
var object_1 = require("../util/object");
// In the config object consumed by the factory we don't specify the types of objects we want to create,
// and in the rare cases when we do, the string type is not the same as corresponding constructor's name.
// Also, the user provided config might miss certain mandatory properties.
// For that reason, we must be able to tell what to instantiate and with what defaults using only
// property's name and position in the config's hierarchy. To be able to do that we need the extra
// information missing from the user provided config. Such information is provided by chart mappings.
var agChartMappings_1 = require("./agChartMappings");
var lightTheme = new chartTheme_1.ChartTheme();
var darkTheme = new darkTheme_1.DarkTheme();
exports.lightThemes = {
'undefined': lightTheme,
'null': lightTheme,
'ag-default': lightTheme,
'ag-material': new materialLight_1.MaterialLight(),
'ag-pastel': new pastelLight_1.PastelLight(),
'ag-solar': new solarLight_1.SolarLight(),
'ag-vivid': new vividLight_1.VividLight(),
};
exports.darkThemes = {
'undefined': darkTheme,
'null': darkTheme,
'ag-default-dark': darkTheme,
'ag-material-dark': new materialDark_1.MaterialDark(),
'ag-pastel-dark': new pastelDark_1.PastelDark(),
'ag-solar-dark': new solarDark_1.SolarDark(),
'ag-vivid-dark': new vividDark_1.VividDark(),
};
exports.themes = __assign(__assign({}, exports.darkThemes), exports.lightThemes);
function getChartTheme(value) {
if (value instanceof chartTheme_1.ChartTheme) {
return value;
}
var stockTheme = exports.themes[value];
if (stockTheme) {
return stockTheme;
}
value = value;
if (value.baseTheme || value.overrides || value.palette) {
var baseTheme = getChartTheme(value.baseTheme);
return new baseTheme.constructor(value);
}
return lightTheme;
}
exports.getChartTheme = getChartTheme;
var firstColorIndex = 0;
var AgChart = /** @class */ (function () {
function AgChart() {
}
AgChart.create = function (options, container, data) {
options = Object.create(options); // avoid mutating user provided options
return AgChart.createOrUpdate({
options: options,
container: container,
data: data,
operation: function (options, theme) { return create(options, undefined, undefined, theme); },
});
};
AgChart.update = function (chart, options, container, data) {
if (!(chart && options)) {
return;
}
return AgChart.createOrUpdate({
chart: chart,
options: options,
container: container,
data: data,
operation: function (options, theme) { return update(chart, options, undefined, theme); },
});
};
AgChart.createOrUpdate = function (_a) {
var chart = _a.chart, options = _a.options, container = _a.container, data = _a.data, operation = _a.operation;
if (container) {
options.container = container;
}
if (data) {
options.data = data;
}
if (options.series && options.series.length > 0) {
options.series = processSeriesOptions(options.series);
}
// special handling when both `autoSize` and `width` / `height` are present in the options
var autoSize = options && options.autoSize !== false;
var theme = getChartTheme(options.theme);
firstColorIndex = 0;
var result = operation(options, theme);
if (chart == null && result instanceof chart_1.Chart) {
chart = result;
}
if (chart && autoSize) { // `autoSize` takes precedence over `width` / `height`
chart.autoSize = true;
}
return result;
};
AgChart.createComponent = create;
return AgChart;
}());
exports.AgChart = AgChart;
var pathToSeriesTypeMap = {
'cartesian.series': 'line',
'line.series': 'line',
'area.series': 'area',
'bar.series': 'bar',
'column.series': 'column',
'histogram.series': 'histogram',
'scatter.series': 'scatter',
'polar.series': 'pie',
'pie.series': 'pie'
};
var actualSeriesTypeMap = {
// Identity mappings.
'area': 'area',
'bar': 'bar',
'histogram': 'histogram',
'line': 'line',
'pie': 'pie',
'scatter': 'scatter',
'ohlc': 'ohlc',
'treemap': 'treemap',
// Aliases.
'column': 'bar',
};
function create(options, path, component, theme) {
var _a;
// Deprecate `chart.legend.item.marker.type` in integrated chart options.
options = Object.create(options);
if (component instanceof legend_1.LegendMarker) {
if (options.type) {
options.shape = options.type;
}
}
else {
options = provideDefaultType(options, path);
if (path) {
if (options.type) {
path = path + '.' + options.type;
}
}
else {
path = options.type;
}
}
if (!path) {
return;
}
var mapping = object_1.getValue(agChartMappings_1.mappings, path);
if (mapping) {
options = provideDefaultOptions(path, options, mapping, theme);
var meta = mapping.meta || {};
var constructorParams = meta.constructorParams || [];
var skipKeys = ['type', 'listeners'].concat(constructorParams);
// TODO: Constructor params processing could be improved, but it's good enough for current params.
var constructorParamValues = constructorParams
.map(function (param) { return options[param]; })
.filter(function (value) { return value !== undefined; });
if (!component) {
component = new ((_a = meta.constructor).bind.apply(_a, __spread([void 0], constructorParamValues)))();
if (theme && component instanceof series_1.Series) {
firstColorIndex = theme.setSeriesColors(component, options, firstColorIndex);
}
}
var _loop_1 = function (key) {
// Process every non-special key in the config object.
if (skipKeys.indexOf(key) < 0) {
var value = options[key];
if (value && key in mapping && !(meta.setAsIs && meta.setAsIs.indexOf(key) >= 0)) {
if (Array.isArray(value)) {
var subComponents = value
.map(function (config) {
var axis = create(config, path + '.' + key, undefined, theme);
if (theme && key === 'axes') {
var fakeTheme = {
getConfig: function (path) {
var parts = path.split('.');
var modifiedPath = parts.slice(0, 3).join('.') + '.' + axis.position;
var after = parts.slice(3);
if (after.length) {
modifiedPath += '.' + after.join('.');
}
var config = theme.getConfig(path);
var modifiedConfig = theme.getConfig(modifiedPath);
object_1.isObject(theme.getConfig(modifiedPath));
if (object_1.isObject(config) && object_1.isObject(modifiedConfig)) {
return object_1.deepMerge(config, modifiedConfig, chartTheme_1.mergeOptions);
}
return modifiedConfig;
}
};
update(axis, config, path + '.' + key, fakeTheme);
}
return axis;
})
.filter(function (instance) { return !!instance; });
component[key] = subComponents;
}
else {
if (mapping[key] && component[key]) {
// The instance property already exists on the component (e.g. chart.legend).
// Simply configure the existing instance, without creating a new one.
create(value, path + '.' + key, component[key], theme);
}
else {
var subComponent = create(value, value.type ? path : path + '.' + key, undefined, theme);
if (subComponent) {
component[key] = subComponent;
}
}
}
}
else { // if (key in meta.constructor.defaults) { // prevent users from creating custom properties
component[key] = value;
}
}
};
for (var key in options) {
_loop_1(key);
}
var listeners = options.listeners;
if (component && component.addEventListener && listeners) {
for (var key in listeners) {
if (listeners.hasOwnProperty(key)) {
var listener = listeners[key];
if (typeof listener === 'function') {
component.addEventListener(key, listener);
}
}
}
}
return component;
}
}
function update(component, options, path, theme) {
if (!(options && object_1.isObject(options))) {
return;
}
// Deprecate `chart.legend.item.marker.type` in integrated chart options.
if (component instanceof legend_1.LegendMarker) {
if (options.type) {
options.shape = options.type;
}
}
else {
options = provideDefaultType(options, path);
if (path) {
if (options.type) {
path = path + '.' + options.type;
}
}
else {
path = options.type;
}
}
if (!path) {
return;
}
var chart = path in agChartMappings_1.mappings ? component : undefined;
var mapping = object_1.getValue(agChartMappings_1.mappings, path);
if (mapping) {
options = provideDefaultOptions(path, options, mapping, theme);
var meta = mapping.meta || {};
var constructorParams = meta && meta.constructorParams || [];
var skipKeys = ['type'].concat(constructorParams);
for (var key in options) {
if (skipKeys.indexOf(key) < 0) {
var value = options[key];
var keyPath = path + '.' + key;
if (meta.setAsIs && meta.setAsIs.indexOf(key) >= 0) {
component[key] = value;
}
else {
var oldValue = component[key];
if (Array.isArray(oldValue) && Array.isArray(value)) {
if (chart) {
if (key === 'series') {
updateSeries(component, value, keyPath, theme);
}
else if (key === 'axes') {
updateAxes(component, value, keyPath, theme);
}
}
else {
component[key] = value;
}
}
else if (object_1.isObject(oldValue)) {
if (value) {
update(oldValue, value, value.type ? path : keyPath, theme);
}
else if (key in options) {
component[key] = value;
}
}
else {
var subComponent = object_1.isObject(value) && create(value, value.type ? path : keyPath, undefined, theme);
if (subComponent) {
component[key] = subComponent;
}
else {
if (chart && options.autoSize && (key === 'width' || key === 'height')) {
continue;
}
component[key] = value;
}
}
}
}
}
}
if (chart) {
chart.layoutPending = true;
}
}
function updateSeries(chart, configs, keyPath, theme) {
var allSeries = chart.series.slice();
var prevSeries;
var i = 0;
for (; i < configs.length; i++) {
var config = configs[i];
var series = allSeries[i];
if (series) {
config = provideDefaultType(config, keyPath);
var type = actualSeriesTypeMap[config.type];
if (series.type === type) {
if (theme) {
firstColorIndex = theme.setSeriesColors(series, config, firstColorIndex);
}
update(series, config, keyPath, theme);
}
else {
var newSeries = create(config, keyPath, undefined, theme);
chart.removeSeries(series);
chart.addSeriesAfter(newSeries, prevSeries);
series = newSeries;
}
}
else { // more new configs than existing series
var newSeries = create(config, keyPath, undefined, theme);
chart.addSeries(newSeries);
}
prevSeries = series;
}
// more existing series than new configs
for (; i < allSeries.length; i++) {
var series = allSeries[i];
if (series) {
chart.removeSeries(series);
}
}
}
function updateAxes(chart, configs, keyPath, theme) {
var e_1, _a;
var axes = chart.axes;
var axesToAdd = [];
var axesToUpdate = [];
var _loop_2 = function (config) {
var axisToUpdate = array_1.find(axes, function (axis) {
return axis.type === config.type && axis.position === config.position;
});
if (axisToUpdate) {
axesToUpdate.push(axisToUpdate);
update(axisToUpdate, config, keyPath, theme);
}
else {
var axisToAdd = create(config, keyPath, undefined, theme);
if (axisToAdd) {
axesToAdd.push(axisToAdd);
}
}
};
try {
for (var configs_1 = __values(configs), configs_1_1 = configs_1.next(); !configs_1_1.done; configs_1_1 = configs_1.next()) {
var config = configs_1_1.value;
_loop_2(config);
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (configs_1_1 && !configs_1_1.done && (_a = configs_1.return)) _a.call(configs_1);
}
finally { if (e_1) throw e_1.error; }
}
chart.axes = axesToUpdate.concat(axesToAdd);
}
function provideDefaultChartType(options) {
if (options.type) {
return options;
}
// If chart type is not specified, try to infer it from the type of first series.
var series = options.series && options.series[0];
if (series && series.type) {
options = Object.create(options);
options.type = series.type;
return options;
}
// If chart type is not specified in the first series either, set it to 'cartesian'.
options = Object.create(options);
options.type = 'cartesian';
return options;
}
function provideDefaultType(options, path) {
if (!path) { // if `path` is undefined, `options` is a top-level (chart) config
path = '';
options = provideDefaultChartType(options);
}
if (!options.type) {
var seriesType = pathToSeriesTypeMap[path];
if (seriesType) {
options = Object.create(options);
options.type = seriesType;
}
}
return options;
}
function skipThemeKey(key) {
return ['axes', 'series'].indexOf(key) >= 0;
}
var enabledKey = 'enabled';
/**
* If certain options were not provided by the user, use the defaults from the theme and the mapping.
* All three objects are provided for the current path in the config tree, not necessarily top-level.
*/
function provideDefaultOptions(path, options, mapping, theme) {
var isChartConfig = path.indexOf('.') < 0;
var themeDefaults = theme && theme.getConfig(path);
var defaults = mapping && mapping.meta && mapping.meta.defaults;
var isExplicitlyDisabled = options.enabled === false; // by the user
if (defaults || themeDefaults) {
options = Object.create(options);
}
// Fill in the gaps for properties not configured by the user using theme provided values.
for (var key in themeDefaults) {
// The default values for these special chart configs always come from the mappings, not theme.
if (isChartConfig && skipThemeKey(key)) {
continue;
}
if (!(key in options)) {
options[key] = themeDefaults[key];
}
}
// Fill in the gaps for properties not configured by the user, nor theme using chart mappings.
for (var key in defaults) {
if ((!themeDefaults || !(key in themeDefaults) || skipThemeKey(key)) && !(key in options)) {
options[key] = defaults[key];
}
}
// Special handling for the 'enabled' property. For example:
// title: { text: 'Quarterly Revenue' } // means title is enabled
// legend: {} // means legend is enabled
var hasEnabledKey = (themeDefaults && enabledKey in themeDefaults) ||
(defaults && enabledKey in defaults);
if (hasEnabledKey && !isExplicitlyDisabled) {
options[enabledKey] = true;
}
return options;
}
/**
* Groups the series options objects if they are of type `column` or `bar` and places them in an array at the index where the first instance of this series type was found.
* Returns an array of arrays containing the ordered and grouped series options objects.
*/
function groupSeriesByType(seriesOptions) {
var e_2, _a;
var indexMap = {
column: [],
bar: [],
line: [],
scatter: [],
area: [],
histogram: [],
ohlc: [],
pie: [],
treemap: [],
};
var result = [];
try {
for (var seriesOptions_1 = __values(seriesOptions), seriesOptions_1_1 = seriesOptions_1.next(); !seriesOptions_1_1.done; seriesOptions_1_1 = seriesOptions_1.next()) {
var s = seriesOptions_1_1.value;
var isColumnOrBar = s.type === 'column' || s.type === 'bar';
var isStackedArea = s.type === 'area' && s.stacked === true;
if (!isColumnOrBar && !isStackedArea) {
// No need to use index for these cases.
result.push([s]);
continue;
}
var seriesType = s.type || 'line';
if (seriesType === 'pie' || seriesType === 'treemap') {
throw new Error("AG Grid - Unexpected series type of: " + seriesType);
}
else if (indexMap[seriesType].length === 0) {
// Add indexed array to result on first addition.
result.push(indexMap[seriesType]);
}
indexMap[seriesType].push(s);
}
}
catch (e_2_1) { e_2 = { error: e_2_1 }; }
finally {
try {
if (seriesOptions_1_1 && !seriesOptions_1_1.done && (_a = seriesOptions_1.return)) _a.call(seriesOptions_1);
}
finally { if (e_2) throw e_2.error; }
}
return result;
}
exports.groupSeriesByType = groupSeriesByType;
/**
* Takes an array of bar or area series options objects and returns a single object with the combined area series options.
*/
function reduceSeries(series, enableBarSeriesSpecialCases) {
var e_3, _a;
var options = {};
var arrayValueProperties = ['yKeys', 'fills', 'strokes', 'yNames', 'hideInChart', 'hideInLegend'];
var stringValueProperties = ['yKey', 'fill', 'stroke', 'yName'];
try {
for (var series_2 = __values(series), series_2_1 = series_2.next(); !series_2_1.done; series_2_1 = series_2.next()) {
var s = series_2_1.value;
for (var property in s) {
var arrayValueProperty = arrayValueProperties.indexOf(property) > -1;
var stringValueProperty = stringValueProperties.indexOf(property) > -1;
if (arrayValueProperty && s[property].length > 0) {
options[property] = __spread((options[property] || []), s[property]);
}
else if (stringValueProperty) {
options[property + "s"] = __spread((options[property + "s"] || []), [s[property]]);
}
else if (enableBarSeriesSpecialCases && property === 'showInLegend') {
if (s[property] === false) {
options.hideInLegend = __spread((options.hideInLegend || []), (s.yKey ? [s.yKey] : s.yKeys));
}
}
else if (enableBarSeriesSpecialCases && property === 'grouped') {
if (s[property] === true) {
options[property] = s[property];
}
}
else {
options[property] = s[property];
}
}
}
}
catch (e_3_1) { e_3 = { error: e_3_1 }; }
finally {
try {
if (series_2_1 && !series_2_1.done && (_a = series_2.return)) _a.call(series_2);
}
finally { if (e_3) throw e_3.error; }
}
return options;
}
exports.reduceSeries = reduceSeries;
/**
* Transforms provided series options array into an array containing series options which are compatible with standalone charts series options.
*/
function processSeriesOptions(seriesOptions) {
var e_4, _a;
var result = [];
try {
for (var _b = __values(groupSeriesByType(seriesOptions)), _c = _b.next(); !_c.done; _c = _b.next()) {
var series = _c.value;
switch (series[0].type) {
case 'column':
case 'bar':
result.push(reduceSeries(series, true));
break;
case 'area':
result.push(reduceSeries(series, false));
break;
case 'line':
default:
if (series.length > 1) {
throw new Error('AG-Grid - unexpected grouping of series type: ' + series[0].type);
}
result.push(series[0]);
break;
}
}
}
catch (e_4_1) { e_4 = { error: e_4_1 }; }
finally {
try {
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}
finally { if (e_4) throw e_4.error; }
}
return result;
}
exports.processSeriesOptions = processSeriesOptions;
//# sourceMappingURL=agChart.js.map