chartist 2.0.0-rc.2 → 2.0.0-rc.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chartist.min.css +1 -1
- package/dist/chartist.min.js +2 -1
- package/dist/index.cjs +808 -128
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +192 -52
- package/dist/index.css.map +1 -1
- package/dist/index.d.cts +3155 -2670
- package/dist/index.d.ts +3155 -2670
- package/dist/index.js +806 -129
- package/dist/index.js.map +1 -1
- package/dist/index.min.css +1 -1
- package/dist/index.min.css.map +1 -1
- package/dist/index.min.js +2 -1
- package/dist/index.min.js.map +1 -1
- package/dist/index.umd.js +2 -1
- package/dist/index.umd.js.map +1 -1
- package/dist/scss/_settings.scss +22 -0
- package/dist/scss/index.scss +107 -6
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -533,6 +533,21 @@ function deserialize(data) {
|
|
|
533
533
|
return parsedData;
|
|
534
534
|
}
|
|
535
535
|
//#endregion
|
|
536
|
+
//#region src/render/style.ts
|
|
537
|
+
/**
|
|
538
|
+
* Applies a style declaration list through the CSSOM. A Content Security
|
|
539
|
+
* Policy without `'unsafe-inline'` for styles blocks a `style` attribute set
|
|
540
|
+
* by a script, but not `element.style`; the browser still reflects the
|
|
541
|
+
* declarations into the `style` attribute, so the markup stays the same.
|
|
542
|
+
* Elements without a `style` property (none in HTML or SVG documents) get
|
|
543
|
+
* the attribute.
|
|
544
|
+
*/
|
|
545
|
+
function setStyle(element, value) {
|
|
546
|
+
const { style } = element;
|
|
547
|
+
if (style) style.cssText = value;
|
|
548
|
+
else element.setAttribute("style", value);
|
|
549
|
+
}
|
|
550
|
+
//#endregion
|
|
536
551
|
//#region src/svg/SvgList.ts
|
|
537
552
|
/**
|
|
538
553
|
* A list of {@link Svg} wrappers that calls an `Svg` method on all of them
|
|
@@ -920,7 +935,8 @@ var Svg = class Svg {
|
|
|
920
935
|
}
|
|
921
936
|
Object.keys(attributes).forEach((key) => {
|
|
922
937
|
if (attributes[key] === void 0) return;
|
|
923
|
-
if (key
|
|
938
|
+
if (key === "style") setStyle(this._node, String(attributes[key]));
|
|
939
|
+
else if (key.indexOf(":") !== -1) {
|
|
924
940
|
const namespacedAttribute = key.split(":");
|
|
925
941
|
this._node.setAttributeNS(namespaces[namespacedAttribute[0]], key, String(attributes[key]));
|
|
926
942
|
} else this._node.setAttribute(key, String(attributes[key]));
|
|
@@ -1505,6 +1521,65 @@ var BaseChart = class {
|
|
|
1505
1521
|
}
|
|
1506
1522
|
};
|
|
1507
1523
|
//#endregion
|
|
1524
|
+
//#region src/scene/node.ts
|
|
1525
|
+
const splitClasses = (names) => names.split(/\s+/).filter(Boolean);
|
|
1526
|
+
const builder = {
|
|
1527
|
+
attr(attributes) {
|
|
1528
|
+
const attrs = { ...this.attrs };
|
|
1529
|
+
for (const [name, value] of Object.entries(attributes)) if (value === void 0 || value === null) delete attrs[name];
|
|
1530
|
+
else attrs[name] = value;
|
|
1531
|
+
return withFields(this, { attrs });
|
|
1532
|
+
},
|
|
1533
|
+
addClass(names) {
|
|
1534
|
+
const added = splitClasses(names).filter((name, i, all) => !this.classes.includes(name) && all.indexOf(name) === i);
|
|
1535
|
+
return added.length ? withFields(this, { classes: [...this.classes, ...added] }) : this;
|
|
1536
|
+
},
|
|
1537
|
+
removeClass(names) {
|
|
1538
|
+
const removed = splitClasses(names);
|
|
1539
|
+
return withFields(this, { classes: this.classes.filter((name) => !removed.includes(name)) });
|
|
1540
|
+
},
|
|
1541
|
+
append(child, insertFirst = false) {
|
|
1542
|
+
return withFields(this, { children: insertFirst ? [child, ...this.children] : [...this.children, child] });
|
|
1543
|
+
},
|
|
1544
|
+
remove(child) {
|
|
1545
|
+
return withFields(this, { children: this.children.filter((existing) => existing !== child) });
|
|
1546
|
+
},
|
|
1547
|
+
replace(child, next) {
|
|
1548
|
+
return withFields(this, { children: this.children.map((existing) => existing === child ? next : existing) });
|
|
1549
|
+
},
|
|
1550
|
+
text(content) {
|
|
1551
|
+
return withFields(this, { content });
|
|
1552
|
+
},
|
|
1553
|
+
empty() {
|
|
1554
|
+
return withFields(this, {
|
|
1555
|
+
children: [],
|
|
1556
|
+
content: void 0
|
|
1557
|
+
});
|
|
1558
|
+
}
|
|
1559
|
+
};
|
|
1560
|
+
function create(fields) {
|
|
1561
|
+
const created = Object.create(builder);
|
|
1562
|
+
for (const [field, value] of Object.entries(fields)) if (value !== void 0) created[field] = value;
|
|
1563
|
+
return created;
|
|
1564
|
+
}
|
|
1565
|
+
function withFields(source, changes) {
|
|
1566
|
+
return create({
|
|
1567
|
+
...source,
|
|
1568
|
+
...changes
|
|
1569
|
+
});
|
|
1570
|
+
}
|
|
1571
|
+
function node(name, attributes = {}, className = "", meta = {}) {
|
|
1572
|
+
const attrs = {};
|
|
1573
|
+
for (const [attr, value] of Object.entries(attributes)) if (value !== void 0 && value !== null) attrs[attr] = value;
|
|
1574
|
+
return create({
|
|
1575
|
+
name,
|
|
1576
|
+
attrs,
|
|
1577
|
+
classes: [...new Set(splitClasses(className))],
|
|
1578
|
+
children: [],
|
|
1579
|
+
...meta
|
|
1580
|
+
});
|
|
1581
|
+
}
|
|
1582
|
+
//#endregion
|
|
1508
1583
|
//#region src/svg/SvgPath.ts
|
|
1509
1584
|
/**
|
|
1510
1585
|
* The parameters of each SVG path command, in the order the `d` attribute
|
|
@@ -2031,63 +2106,57 @@ function monotoneCubic(options) {
|
|
|
2031
2106
|
};
|
|
2032
2107
|
}
|
|
2033
2108
|
//#endregion
|
|
2034
|
-
//#region src/
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
const attrs = { ...this.attrs };
|
|
2039
|
-
for (const [name, value] of Object.entries(attributes)) if (value === void 0 || value === null) delete attrs[name];
|
|
2040
|
-
else attrs[name] = value;
|
|
2041
|
-
return withFields(this, { attrs });
|
|
2042
|
-
},
|
|
2043
|
-
addClass(names) {
|
|
2044
|
-
const added = splitClasses(names).filter((name, i, all) => !this.classes.includes(name) && all.indexOf(name) === i);
|
|
2045
|
-
return added.length ? withFields(this, { classes: [...this.classes, ...added] }) : this;
|
|
2046
|
-
},
|
|
2047
|
-
removeClass(names) {
|
|
2048
|
-
const removed = splitClasses(names);
|
|
2049
|
-
return withFields(this, { classes: this.classes.filter((name) => !removed.includes(name)) });
|
|
2050
|
-
},
|
|
2051
|
-
append(child, insertFirst = false) {
|
|
2052
|
-
return withFields(this, { children: insertFirst ? [child, ...this.children] : [...this.children, child] });
|
|
2053
|
-
},
|
|
2054
|
-
remove(child) {
|
|
2055
|
-
return withFields(this, { children: this.children.filter((existing) => existing !== child) });
|
|
2056
|
-
},
|
|
2057
|
-
replace(child, next) {
|
|
2058
|
-
return withFields(this, { children: this.children.map((existing) => existing === child ? next : existing) });
|
|
2059
|
-
},
|
|
2060
|
-
text(content) {
|
|
2061
|
-
return withFields(this, { content });
|
|
2062
|
-
},
|
|
2063
|
-
empty() {
|
|
2064
|
-
return withFields(this, {
|
|
2065
|
-
children: [],
|
|
2066
|
-
content: void 0
|
|
2067
|
-
});
|
|
2068
|
-
}
|
|
2069
|
-
};
|
|
2070
|
-
function create(fields) {
|
|
2071
|
-
const created = Object.create(builder);
|
|
2072
|
-
for (const [field, value] of Object.entries(fields)) if (value !== void 0) created[field] = value;
|
|
2073
|
-
return created;
|
|
2109
|
+
//#region src/layers/path.ts
|
|
2110
|
+
/** The interpolation for a `lineSmooth` option: smooth, straight or given. */
|
|
2111
|
+
function interpolationOf(lineSmooth) {
|
|
2112
|
+
return typeof lineSmooth === "function" ? lineSmooth : lineSmooth ? monotoneCubic() : none();
|
|
2074
2113
|
}
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2114
|
+
/**
|
|
2115
|
+
* The px shift that puts points in the middle of each step of a step axis,
|
|
2116
|
+
* where bars are centered, for `align: 'center'`.
|
|
2117
|
+
*/
|
|
2118
|
+
function centerShift(axisX, align) {
|
|
2119
|
+
return align === "center" && axisX.kind === "step" && !axisX.stretch ? (axisX.step ?? 0) / 2 : 0;
|
|
2080
2120
|
}
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2121
|
+
/**
|
|
2122
|
+
* Projects a series' values into the chart area and interpolates a path
|
|
2123
|
+
* through them. Holes break the path unless the interpolation fills them.
|
|
2124
|
+
* @param meta The meta of a value, attached to its path element.
|
|
2125
|
+
*/
|
|
2126
|
+
function seriesPath(values, axes, area, shift, interpolation, meta = () => void 0) {
|
|
2127
|
+
const pathCoordinates = [];
|
|
2128
|
+
const pathData = [];
|
|
2129
|
+
values.forEach((value, valueIndex) => {
|
|
2130
|
+
pathCoordinates.push(area.x1 + shift + axes.x.project(value, valueIndex, values), area.y1 - axes.y.project(value, valueIndex, values));
|
|
2131
|
+
pathData.push({
|
|
2132
|
+
value,
|
|
2133
|
+
valueIndex,
|
|
2134
|
+
meta: meta(valueIndex)
|
|
2135
|
+
});
|
|
2090
2136
|
});
|
|
2137
|
+
return interpolation(pathCoordinates, pathData);
|
|
2138
|
+
}
|
|
2139
|
+
/**
|
|
2140
|
+
* The same path traced backward: it starts where the path ends, and each
|
|
2141
|
+
* segment runs to the previous point, with a curve's control points
|
|
2142
|
+
* swapped, so it draws the same shape. Holes (`M` commands within the
|
|
2143
|
+
* path) are kept between the same points. Arcs aren't supported.
|
|
2144
|
+
*/
|
|
2145
|
+
function reversePath(path) {
|
|
2146
|
+
const reversed = new SvgPath();
|
|
2147
|
+
const elements = path.pathElements;
|
|
2148
|
+
for (let i = elements.length - 1; i >= 0; i--) {
|
|
2149
|
+
const element = elements[i];
|
|
2150
|
+
const target = elements[i - 1];
|
|
2151
|
+
if (i === elements.length - 1 || elements[i + 1].command === "M") reversed.move(element.x, element.y, false, element.data);
|
|
2152
|
+
if (element.command === "M" || !target) continue;
|
|
2153
|
+
if (element.command === "C") {
|
|
2154
|
+
const curve = element;
|
|
2155
|
+
reversed.curve(curve.x2, curve.y2, curve.x1, curve.y1, target.x, target.y, false, target.data);
|
|
2156
|
+
} else if (element.command === "L") reversed.line(target.x, target.y, false, target.data);
|
|
2157
|
+
else throw new Error(`Chartist: can't reverse a path with "${element.command}" commands`);
|
|
2158
|
+
}
|
|
2159
|
+
return reversed;
|
|
2091
2160
|
}
|
|
2092
2161
|
//#endregion
|
|
2093
2162
|
//#region src/layers/line.ts
|
|
@@ -2102,7 +2171,7 @@ const DEFAULTS = {
|
|
|
2102
2171
|
showArea: false,
|
|
2103
2172
|
areaBase: 0
|
|
2104
2173
|
};
|
|
2105
|
-
const CLASS_NAMES$
|
|
2174
|
+
const CLASS_NAMES$5 = {
|
|
2106
2175
|
series: "ct-series",
|
|
2107
2176
|
line: "ct-line",
|
|
2108
2177
|
point: "ct-point",
|
|
@@ -2168,7 +2237,7 @@ function seriesOption(series, options, key) {
|
|
|
2168
2237
|
*/
|
|
2169
2238
|
function line(options = {}) {
|
|
2170
2239
|
const classNames = {
|
|
2171
|
-
...CLASS_NAMES$
|
|
2240
|
+
...CLASS_NAMES$5,
|
|
2172
2241
|
...options.classNames
|
|
2173
2242
|
};
|
|
2174
2243
|
return {
|
|
@@ -2183,7 +2252,7 @@ function line(options = {}) {
|
|
|
2183
2252
|
const { x: axisX, y: axisY } = axes;
|
|
2184
2253
|
if (!axisX || !axisY || !normalized) throw new Error("Layer \"line\" needs an x and a y axis");
|
|
2185
2254
|
if (seriesIndexes && options.reverseData) throw new Error("Layer \"line\": a series selection can't be combined with reverseData");
|
|
2186
|
-
const shift = options.align
|
|
2255
|
+
const shift = centerShift(axisX, options.align);
|
|
2187
2256
|
const order = data.series.map((_, i) => i);
|
|
2188
2257
|
if (options.reverseData) order.reverse();
|
|
2189
2258
|
return order.map((dataIndex, localIndex) => {
|
|
@@ -2193,18 +2262,10 @@ function line(options = {}) {
|
|
|
2193
2262
|
const seriesName = safeHasProperty(series, "name") && series.name;
|
|
2194
2263
|
const seriesClassName = safeHasProperty(series, "className") && series.className;
|
|
2195
2264
|
const seriesMeta = safeHasProperty(series, "meta") ? series.meta : void 0;
|
|
2196
|
-
const
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
pathData.push({
|
|
2201
|
-
value,
|
|
2202
|
-
valueIndex,
|
|
2203
|
-
meta: getMetaData(series, valueIndex)
|
|
2204
|
-
});
|
|
2205
|
-
});
|
|
2206
|
-
const lineSmooth = seriesOption(series, options, "lineSmooth");
|
|
2207
|
-
const path = (typeof lineSmooth === "function" ? lineSmooth : lineSmooth ? monotoneCubic() : none())(pathCoordinates, pathData);
|
|
2265
|
+
const path = seriesPath(values, {
|
|
2266
|
+
x: axisX,
|
|
2267
|
+
y: axisY
|
|
2268
|
+
}, area, shift, interpolationOf(seriesOption(series, options, "lineSmooth")), (valueIndex) => getMetaData(series, valueIndex));
|
|
2208
2269
|
const seriesContext = {
|
|
2209
2270
|
series,
|
|
2210
2271
|
seriesIndex,
|
|
@@ -3201,9 +3262,8 @@ function layout(emitter, config, width, height) {
|
|
|
3201
3262
|
return result;
|
|
3202
3263
|
}
|
|
3203
3264
|
function compose(emitter, config, data, area, measureText, axes = {}, normalized, padding = config.padding, bindings = [], labels = "html", measureStyle) {
|
|
3204
|
-
const composed = [];
|
|
3205
3265
|
const byId = new Map((axes.all ?? []).map((axis) => [axis.id, axis]));
|
|
3206
|
-
config.layers.
|
|
3266
|
+
const layers = config.layers.map((layer, layerIndex) => {
|
|
3207
3267
|
const binding = bindings[layerIndex] ?? {};
|
|
3208
3268
|
const selection = data.flat ? void 0 : binding.series;
|
|
3209
3269
|
const layerData = selection ? {
|
|
@@ -3214,7 +3274,7 @@ function compose(emitter, config, data, area, measureText, axes = {}, normalized
|
|
|
3214
3274
|
...normalized,
|
|
3215
3275
|
series: selection.map((i) => normalized.series[i])
|
|
3216
3276
|
} : normalized;
|
|
3217
|
-
const
|
|
3277
|
+
const context = {
|
|
3218
3278
|
data: layerData,
|
|
3219
3279
|
area,
|
|
3220
3280
|
padding,
|
|
@@ -3230,12 +3290,29 @@ function compose(emitter, config, data, area, measureText, axes = {}, normalized
|
|
|
3230
3290
|
seriesIndexes: selection,
|
|
3231
3291
|
labels,
|
|
3232
3292
|
measureStyle
|
|
3233
|
-
}
|
|
3234
|
-
|
|
3235
|
-
|
|
3236
|
-
|
|
3237
|
-
|
|
3293
|
+
};
|
|
3294
|
+
return {
|
|
3295
|
+
layer,
|
|
3296
|
+
context,
|
|
3297
|
+
nodes: layer.compose(context).map((top) => assignKeys(top, layerIndex))
|
|
3298
|
+
};
|
|
3238
3299
|
});
|
|
3300
|
+
const refiners = layers.flatMap(({ layer, context }) => layer.refine ? [{
|
|
3301
|
+
refine: layer.refine.bind(layer),
|
|
3302
|
+
context
|
|
3303
|
+
}] : []);
|
|
3304
|
+
const refine = (current) => refiners.reduce((refined, { refine: refineNode, context }) => {
|
|
3305
|
+
const result = refineNode(refined, context);
|
|
3306
|
+
return result ? withFields(result, {
|
|
3307
|
+
key: refined.key,
|
|
3308
|
+
children: refined.children
|
|
3309
|
+
}) : refined;
|
|
3310
|
+
}, current);
|
|
3311
|
+
const composed = [];
|
|
3312
|
+
for (const { nodes } of layers) for (const top of nodes) {
|
|
3313
|
+
const result = mapNodes(top, (current) => current.role === void 0 ? void 0 : emitter.transform("compose", refiners.length > 0 ? refine(current) : current));
|
|
3314
|
+
if (result) composed.push(result);
|
|
3315
|
+
}
|
|
3239
3316
|
return composed;
|
|
3240
3317
|
}
|
|
3241
3318
|
function scene(emitter, config, children, size) {
|
|
@@ -3315,7 +3392,8 @@ const estimateText = (text, options = {}) => {
|
|
|
3315
3392
|
function setAttribute(element, name, value) {
|
|
3316
3393
|
const separator = name.indexOf(":");
|
|
3317
3394
|
const prefix = separator > 0 ? name.slice(0, separator) : "";
|
|
3318
|
-
if (
|
|
3395
|
+
if (name === "style") setStyle(element, String(value));
|
|
3396
|
+
else if (prefix && prefix !== "xmlns" && namespaces[prefix]) element.setAttributeNS(namespaces[prefix], name, String(value));
|
|
3319
3397
|
else element.setAttribute(name, String(value));
|
|
3320
3398
|
}
|
|
3321
3399
|
/**
|
|
@@ -3343,7 +3421,7 @@ function removePrevious(container) {
|
|
|
3343
3421
|
*/
|
|
3344
3422
|
function probe(document, name, options, read) {
|
|
3345
3423
|
const svg = document.createElementNS(namespaces.svg, "svg");
|
|
3346
|
-
svg
|
|
3424
|
+
setStyle(svg, "position: absolute; visibility: hidden; width: 0; height: 0;");
|
|
3347
3425
|
if (options.rootClass) svg.setAttribute("class", options.rootClass);
|
|
3348
3426
|
const node = document.createElementNS(namespaces.svg, name);
|
|
3349
3427
|
if (options.classes?.length) node.setAttribute("class", options.classes.join(" "));
|
|
@@ -3725,7 +3803,7 @@ function chart(target, config) {
|
|
|
3725
3803
|
probe.setAttribute("width", width);
|
|
3726
3804
|
probe.setAttribute("height", height);
|
|
3727
3805
|
const px = (value) => typeof value === "number" ? "px" : "";
|
|
3728
|
-
probe
|
|
3806
|
+
setStyle(probe, `width: ${width}${px(effective.width)}; height: ${height}${px(effective.height)};`);
|
|
3729
3807
|
container.appendChild(probe);
|
|
3730
3808
|
const measured = {
|
|
3731
3809
|
width: probe.clientWidth,
|
|
@@ -3874,7 +3952,7 @@ function axisNodes(axis, frame) {
|
|
|
3874
3952
|
const options = frame.options ?? (axis.dimension === "x" ? frame.axisX : frame.axisY);
|
|
3875
3953
|
const place = frame.place;
|
|
3876
3954
|
const projected = axis.ticks.map((tick, i) => axis.project(tick, i));
|
|
3877
|
-
const labelValues = axis.ticks.map(options.
|
|
3955
|
+
const labelValues = axis.ticks.map(options.labelTransform);
|
|
3878
3956
|
const gridOffset = axis.dimension === "x" ? area.y2 : area.x1;
|
|
3879
3957
|
const gridLength = axis.dimension === "x" ? area.height : area.width;
|
|
3880
3958
|
const grids = [];
|
|
@@ -3969,6 +4047,12 @@ function gridBackground(area, className) {
|
|
|
3969
4047
|
}, className, { role: "gridBackground" });
|
|
3970
4048
|
}
|
|
3971
4049
|
//#endregion
|
|
4050
|
+
//#region src/layers/label.ts
|
|
4051
|
+
/** The label function to use; `labelTransform` wins when both are set. */
|
|
4052
|
+
function labelTransformOf(options) {
|
|
4053
|
+
return options.labelTransform ?? options.labelInterpolationFnc ?? ((value) => value);
|
|
4054
|
+
}
|
|
4055
|
+
//#endregion
|
|
3972
4056
|
//#region src/scales/svgLabels.ts
|
|
3973
4057
|
/**
|
|
3974
4058
|
* SVG text labels: the label text wrapped into `tspan` lines and aligned
|
|
@@ -4067,7 +4151,7 @@ function svgLabels(measureText, kind, override = {}) {
|
|
|
4067
4151
|
* container('(width < 400px)'),
|
|
4068
4152
|
* {
|
|
4069
4153
|
* showPoint: false,
|
|
4070
|
-
* axisX: {
|
|
4154
|
+
* axisX: { labelTransform: value => String(value)[0] }
|
|
4071
4155
|
* }
|
|
4072
4156
|
* ]
|
|
4073
4157
|
* ]
|
|
@@ -4209,13 +4293,18 @@ function applyResponsive(base, entries, matching, merge) {
|
|
|
4209
4293
|
* option merge, window responsive options, the preset state that plugins
|
|
4210
4294
|
* (compat) read, and the grid and label layers.
|
|
4211
4295
|
*/
|
|
4296
|
+
/** An axis's options with its label function resolved from either name. */
|
|
4297
|
+
const drawn = (axis) => ({
|
|
4298
|
+
...axis,
|
|
4299
|
+
labelTransform: labelTransformOf(axis)
|
|
4300
|
+
});
|
|
4212
4301
|
function frame(options, context, svgLabel) {
|
|
4213
4302
|
return {
|
|
4214
4303
|
svgLabel,
|
|
4215
4304
|
area: context.area,
|
|
4216
4305
|
padding: context.padding,
|
|
4217
|
-
axisX: options.axisX,
|
|
4218
|
-
axisY: options.axisY,
|
|
4306
|
+
axisX: drawn(options.axisX),
|
|
4307
|
+
axisY: drawn(options.axisY),
|
|
4219
4308
|
classNames: options.classNames
|
|
4220
4309
|
};
|
|
4221
4310
|
}
|
|
@@ -4243,10 +4332,10 @@ function labelLayer(options, order = ["x", "y"]) {
|
|
|
4243
4332
|
type: "labels",
|
|
4244
4333
|
coordinates: ["cartesian"],
|
|
4245
4334
|
compose(context) {
|
|
4246
|
-
const svgLabel = context.labels === "svg" ? svgLabels(context.measureText, options.labelKind ?? "line") : void 0;
|
|
4247
4335
|
return [group(options.classNames.labelGroup, order.flatMap((dimension) => {
|
|
4248
4336
|
const axis = context.axes[dimension];
|
|
4249
|
-
|
|
4337
|
+
if (!axis) return [];
|
|
4338
|
+
return axisNodes(axis, frame(options, context, context.labels === "svg" ? svgLabels(context.measureText, options.labelKind ?? "line", options[dimension === "x" ? "axisX" : "axisY"].labelAlign) : void 0)).labels;
|
|
4250
4339
|
}))];
|
|
4251
4340
|
}
|
|
4252
4341
|
};
|
|
@@ -4446,6 +4535,7 @@ const lineSpec = {
|
|
|
4446
4535
|
config(data, preset) {
|
|
4447
4536
|
const options = preset;
|
|
4448
4537
|
const axisOptions = options;
|
|
4538
|
+
const { below = [], above = [] } = options.layers ?? {};
|
|
4449
4539
|
return {
|
|
4450
4540
|
data,
|
|
4451
4541
|
axes: presetAxes(axesConfig$1(options)),
|
|
@@ -4457,6 +4547,7 @@ const lineSpec = {
|
|
|
4457
4547
|
labels: options.labels,
|
|
4458
4548
|
layers: [
|
|
4459
4549
|
gridLayer(axisOptions),
|
|
4550
|
+
...below,
|
|
4460
4551
|
seriesGroup(line({
|
|
4461
4552
|
lineSmooth: options.lineSmooth,
|
|
4462
4553
|
showPoint: options.showPoint,
|
|
@@ -4467,6 +4558,7 @@ const lineSpec = {
|
|
|
4467
4558
|
reverseData: options.reverseData,
|
|
4468
4559
|
classNames: options.classNames
|
|
4469
4560
|
})),
|
|
4561
|
+
...above,
|
|
4470
4562
|
labelLayer(axisOptions)
|
|
4471
4563
|
]
|
|
4472
4564
|
};
|
|
@@ -4777,6 +4869,7 @@ function bar(options = {}) {
|
|
|
4777
4869
|
};
|
|
4778
4870
|
const horizontal = Boolean(options.horizontalBars);
|
|
4779
4871
|
const seriesBarDistance = options.seriesBarDistance ?? 15;
|
|
4872
|
+
const offset = options.offset ?? 0;
|
|
4780
4873
|
const stackMode = options.stackMode ?? "accumulate";
|
|
4781
4874
|
const stacks = options.stackBars && stackMode !== "overlap" && stackMode !== true;
|
|
4782
4875
|
return {
|
|
@@ -4837,6 +4930,7 @@ function bar(options = {}) {
|
|
|
4837
4930
|
if (!labelAxis.stretch) projected[labelPos] += periodHalfLength * (horizontal ? -1 : 1);
|
|
4838
4931
|
projected[labelPos] += options.stackBars || options.distributeSeries ? 0 : biPol * seriesBarDistance * (horizontal ? -1 : 1);
|
|
4839
4932
|
}
|
|
4933
|
+
projected[labelPos] += offset;
|
|
4840
4934
|
if (isAccumulateRelative) stack = Number(horizontal ? valueX : valueY) < 0 ? negStack : posStack;
|
|
4841
4935
|
const previousStack = stack[valueIndex] || zeroPoint;
|
|
4842
4936
|
stack[valueIndex] = previousStack - (zeroPoint - projected[counterPos]);
|
|
@@ -5037,6 +5131,7 @@ const barSpec = {
|
|
|
5037
5131
|
...seriesGroup(layer),
|
|
5038
5132
|
extent: extentOf.extent
|
|
5039
5133
|
};
|
|
5134
|
+
const { below = [], above = [] } = options.layers ?? {};
|
|
5040
5135
|
return {
|
|
5041
5136
|
data,
|
|
5042
5137
|
axes: presetAxes(axesConfig(options)),
|
|
@@ -5048,7 +5143,9 @@ const barSpec = {
|
|
|
5048
5143
|
labels: options.labels,
|
|
5049
5144
|
layers: [
|
|
5050
5145
|
gridLayer(axisOptions, order),
|
|
5146
|
+
...below,
|
|
5051
5147
|
bars,
|
|
5148
|
+
...above,
|
|
5052
5149
|
labelLayer({
|
|
5053
5150
|
...axisOptions,
|
|
5054
5151
|
labelKind: options.horizontalBars ? "horizontalBar" : "bar"
|
|
@@ -5136,12 +5233,40 @@ function cssWidth(measureStyle, sliceClass) {
|
|
|
5136
5233
|
const width = measureStyle?.("stroke-width", { classes: sliceClass.split(" ") });
|
|
5137
5234
|
return width && /^[\d.]+px$/.test(width) ? parseFloat(width) : void 0;
|
|
5138
5235
|
}
|
|
5139
|
-
const CLASS_NAMES$
|
|
5236
|
+
const CLASS_NAMES$4 = {
|
|
5140
5237
|
series: "ct-series",
|
|
5141
5238
|
slicePie: "ct-slice-pie",
|
|
5142
5239
|
sliceDonut: "ct-slice-donut",
|
|
5143
5240
|
label: "ct-label"
|
|
5144
5241
|
};
|
|
5242
|
+
/** The line height of a pie label with line breaks, in `em`. */
|
|
5243
|
+
const LINE_HEIGHT = 1.2;
|
|
5244
|
+
/**
|
|
5245
|
+
* A pie label's `text` at its anchor. One line is placed with `dx`/`dy`,
|
|
5246
|
+
* as in 1.x. A label with line breaks gets one `tspan` per line, one line
|
|
5247
|
+
* height apart, the block centered on the anchor (see #546).
|
|
5248
|
+
*/
|
|
5249
|
+
function labelText(text, position, anchor, className, ctx) {
|
|
5250
|
+
const lines = text.split("\n");
|
|
5251
|
+
const meta = {
|
|
5252
|
+
role: "label",
|
|
5253
|
+
ctx
|
|
5254
|
+
};
|
|
5255
|
+
if (lines.length === 1) return node("text", {
|
|
5256
|
+
dx: position.x,
|
|
5257
|
+
dy: position.y,
|
|
5258
|
+
"text-anchor": anchor
|
|
5259
|
+
}, className, meta).text(text);
|
|
5260
|
+
const shift = Math.round(-(lines.length - 1) * LINE_HEIGHT * 50) / 100;
|
|
5261
|
+
return withFields(node("text", {
|
|
5262
|
+
x: position.x,
|
|
5263
|
+
y: position.y,
|
|
5264
|
+
"text-anchor": anchor
|
|
5265
|
+
}, className, meta), { children: lines.map((line, index) => node("tspan", {
|
|
5266
|
+
x: position.x,
|
|
5267
|
+
dy: `${index ? LINE_HEIGHT : shift}em`
|
|
5268
|
+
}).text(line)) });
|
|
5269
|
+
}
|
|
5145
5270
|
/**
|
|
5146
5271
|
* Creates a layer that draws a flat series as pie or donut slices with
|
|
5147
5272
|
* labels, in the markup of the 1.x pie chart (a `g.ct-series` per slice,
|
|
@@ -5167,10 +5292,10 @@ const CLASS_NAMES$1 = {
|
|
|
5167
5292
|
*/
|
|
5168
5293
|
function pie(options = {}) {
|
|
5169
5294
|
const classNames = {
|
|
5170
|
-
...CLASS_NAMES$
|
|
5295
|
+
...CLASS_NAMES$4,
|
|
5171
5296
|
...options.classNames
|
|
5172
5297
|
};
|
|
5173
|
-
const
|
|
5298
|
+
const transform = labelTransformOf(options);
|
|
5174
5299
|
return {
|
|
5175
5300
|
type: "pie",
|
|
5176
5301
|
chartType: options.donut ? "donut" : "pie",
|
|
@@ -5266,7 +5391,7 @@ function pie(options = {}) {
|
|
|
5266
5391
|
y: center.y
|
|
5267
5392
|
} : polarToCartesian(center.x, center.y, labelRadius, startAngle + (endAngle - startAngle) / 2);
|
|
5268
5393
|
const rawValue = labels && !isFalseyButZero(labels[index]) ? labels[index] : values[index];
|
|
5269
|
-
const interpolated =
|
|
5394
|
+
const interpolated = transform(rawValue, index);
|
|
5270
5395
|
if (interpolated || interpolated === 0) {
|
|
5271
5396
|
const text = String(interpolated);
|
|
5272
5397
|
if (options.preventOverlappingLabelOffset) {
|
|
@@ -5274,24 +5399,17 @@ function pie(options = {}) {
|
|
|
5274
5399
|
labelPositions.forEach((item) => moveLabel(labelPosition, item, options.preventOverlappingLabelOffset, length));
|
|
5275
5400
|
labelPositions.push(labelPosition);
|
|
5276
5401
|
}
|
|
5277
|
-
labelNodes.push(
|
|
5278
|
-
|
|
5279
|
-
|
|
5280
|
-
|
|
5281
|
-
|
|
5282
|
-
|
|
5283
|
-
|
|
5284
|
-
|
|
5285
|
-
|
|
5286
|
-
|
|
5287
|
-
|
|
5288
|
-
text,
|
|
5289
|
-
series,
|
|
5290
|
-
meta: seriesMeta,
|
|
5291
|
-
x: labelPosition.x,
|
|
5292
|
-
y: labelPosition.y
|
|
5293
|
-
}
|
|
5294
|
-
}).text(text));
|
|
5402
|
+
labelNodes.push(labelText(text, labelPosition, determineAnchorPosition(center, labelPosition, options.labelDirection ?? "neutral"), classNames.label, {
|
|
5403
|
+
kind: "pie",
|
|
5404
|
+
index,
|
|
5405
|
+
seriesIndex: index,
|
|
5406
|
+
valueIndex: 0,
|
|
5407
|
+
text,
|
|
5408
|
+
series,
|
|
5409
|
+
meta: seriesMeta,
|
|
5410
|
+
x: labelPosition.x,
|
|
5411
|
+
y: labelPosition.y
|
|
5412
|
+
}));
|
|
5295
5413
|
}
|
|
5296
5414
|
}
|
|
5297
5415
|
startAngle = endAngle;
|
|
@@ -5338,6 +5456,7 @@ const pieSpec = {
|
|
|
5338
5456
|
defaults: pieDefaults,
|
|
5339
5457
|
config(data, preset) {
|
|
5340
5458
|
const options = preset;
|
|
5459
|
+
const { below = [], above = [] } = preset.layers ?? {};
|
|
5341
5460
|
return {
|
|
5342
5461
|
data,
|
|
5343
5462
|
coordinates: "polar",
|
|
@@ -5346,20 +5465,25 @@ const pieSpec = {
|
|
|
5346
5465
|
height: options.height,
|
|
5347
5466
|
viewBox: options.viewBox,
|
|
5348
5467
|
className: options.donut ? options.classNames.chartDonut : options.classNames.chartPie,
|
|
5349
|
-
layers: [
|
|
5350
|
-
|
|
5351
|
-
|
|
5352
|
-
|
|
5353
|
-
|
|
5354
|
-
|
|
5355
|
-
|
|
5356
|
-
|
|
5357
|
-
|
|
5358
|
-
|
|
5359
|
-
|
|
5360
|
-
|
|
5361
|
-
|
|
5362
|
-
|
|
5468
|
+
layers: [
|
|
5469
|
+
...below,
|
|
5470
|
+
pie({
|
|
5471
|
+
startAngle: options.startAngle,
|
|
5472
|
+
total: options.total,
|
|
5473
|
+
donut: options.donut,
|
|
5474
|
+
donutWidth: options.donutWidth,
|
|
5475
|
+
showLabel: options.showLabel,
|
|
5476
|
+
labelOffset: options.labelOffset,
|
|
5477
|
+
labelPosition: options.labelPosition,
|
|
5478
|
+
labelTransform: options.labelTransform,
|
|
5479
|
+
labelInterpolationFnc: options.labelInterpolationFnc,
|
|
5480
|
+
labelDirection: options.labelDirection,
|
|
5481
|
+
ignoreEmptyValues: options.ignoreEmptyValues,
|
|
5482
|
+
preventOverlappingLabelOffset: options.preventOverlappingLabelOffset,
|
|
5483
|
+
classNames: options.classNames
|
|
5484
|
+
}),
|
|
5485
|
+
...above
|
|
5486
|
+
]
|
|
5363
5487
|
};
|
|
5364
5488
|
}
|
|
5365
5489
|
};
|
|
@@ -5715,16 +5839,22 @@ const seriesColors = [
|
|
|
5715
5839
|
//#endregion
|
|
5716
5840
|
//#region src/render/string.ts
|
|
5717
5841
|
const escape = (value) => String(value).replace(/[&<>"']/g, (char) => escapingMap[char]);
|
|
5842
|
+
const nameStart = "A-Z_:a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD";
|
|
5843
|
+
const xmlName = new RegExp(`^[${nameStart}][${nameStart}\\-.0-9\\u00B7\\u0300-\\u036F\\u203F\\u2040]*$`);
|
|
5844
|
+
function checked(name, kind) {
|
|
5845
|
+
if (!xmlName.test(name)) throw new Error(`Chartist: "${name}" is not a valid ${kind} name`);
|
|
5846
|
+
return name;
|
|
5847
|
+
}
|
|
5718
5848
|
function attributes(current, position) {
|
|
5719
5849
|
const parts = [];
|
|
5720
5850
|
if (position === "root") parts.push(`xmlns="${namespaces.svg}"`, `xmlns:ct="${namespaces.ct}"`);
|
|
5721
5851
|
else if (position === "html-root") parts.push(`xmlns="${namespaces.xhtml}"`);
|
|
5722
5852
|
if (current.classes.length) parts.push(`class="${escape(current.classes.join(" "))}"`);
|
|
5723
|
-
for (const [name, value] of Object.entries(current.attrs)) if (name !== "xmlns") parts.push(`${name}="${escape(value)}"`);
|
|
5853
|
+
for (const [name, value] of Object.entries(current.attrs)) if (name !== "xmlns") parts.push(`${checked(name, "attribute")}="${escape(value)}"`);
|
|
5724
5854
|
return parts.length ? ` ${parts.join(" ")}` : "";
|
|
5725
5855
|
}
|
|
5726
5856
|
function serialize$1(current, position) {
|
|
5727
|
-
const open = `<${current.name}${attributes(current, position)}`;
|
|
5857
|
+
const open = `<${checked(current.name, "element")}${attributes(current, position)}`;
|
|
5728
5858
|
const childPosition = current.name === "foreignObject" ? "html-root" : "other";
|
|
5729
5859
|
const content = (current.content === void 0 ? "" : escape(current.content)) + current.children.map((child) => serialize$1(child, childPosition)).join("");
|
|
5730
5860
|
return content ? `${open}>${content}</${current.name}>` : `${open}/>`;
|
|
@@ -5855,6 +5985,550 @@ function toScene(config, size) {
|
|
|
5855
5985
|
}).scene;
|
|
5856
5986
|
}
|
|
5857
5987
|
//#endregion
|
|
5988
|
+
//#region src/layers/band.ts
|
|
5989
|
+
const CLASS_NAMES$3 = {
|
|
5990
|
+
band: "ct-band",
|
|
5991
|
+
area: "ct-band-area",
|
|
5992
|
+
inBand: "ct-in-band",
|
|
5993
|
+
outBand: "ct-out-band"
|
|
5994
|
+
};
|
|
5995
|
+
/** The series an edge follows, if it's a series. */
|
|
5996
|
+
function selectorOf(edge) {
|
|
5997
|
+
return typeof edge === "number" || isValues(edge) ? void 0 : typeof edge === "string" ? edge : edge.series;
|
|
5998
|
+
}
|
|
5999
|
+
function isValues(edge) {
|
|
6000
|
+
return Array.isArray(edge);
|
|
6001
|
+
}
|
|
6002
|
+
/** An edge's own values, normalized like a series' values. */
|
|
6003
|
+
function normalizedValues(values) {
|
|
6004
|
+
return values.map((value) => isNumeric(value) ? { y: Number(value) } : value && typeof value === "object" ? value : void 0);
|
|
6005
|
+
}
|
|
6006
|
+
/** The value of a normalized value along Y, or `undefined` for a hole. */
|
|
6007
|
+
function yOf(value) {
|
|
6008
|
+
const y = value !== null && typeof value === "object" ? value.y : value;
|
|
6009
|
+
return isNumeric(y) ? Number(y) : void 0;
|
|
6010
|
+
}
|
|
6011
|
+
function xOf(value) {
|
|
6012
|
+
return value !== null && typeof value === "object" ? value.x : void 0;
|
|
6013
|
+
}
|
|
6014
|
+
/**
|
|
6015
|
+
* The position of a series in the layer's data: the layer gets only the
|
|
6016
|
+
* series it selects, with their chart-wide indexes in `seriesIndexes`.
|
|
6017
|
+
*/
|
|
6018
|
+
function localIndex(selector, context) {
|
|
6019
|
+
const { data, seriesIndexes } = context;
|
|
6020
|
+
if (typeof selector === "string") return data.series.findIndex((series) => series.name === selector);
|
|
6021
|
+
return seriesIndexes ? seriesIndexes.indexOf(selector) : selector;
|
|
6022
|
+
}
|
|
6023
|
+
function chartIndex(selector, context) {
|
|
6024
|
+
const index = localIndex(selector, context);
|
|
6025
|
+
return context.seriesIndexes?.[index] ?? index;
|
|
6026
|
+
}
|
|
6027
|
+
/**
|
|
6028
|
+
* Works out the band's edges from the data in the context.
|
|
6029
|
+
* @param constant Changes a constant edge before it's used, e.g. to keep it
|
|
6030
|
+
* within the axis range for drawing.
|
|
6031
|
+
*/
|
|
6032
|
+
function bandEdges(options, context, constant = (value) => value) {
|
|
6033
|
+
const all = context.normalized?.series ?? [];
|
|
6034
|
+
const seriesOf = (selector) => all[localIndex(selector, context)] ?? [];
|
|
6035
|
+
if (options.series) {
|
|
6036
|
+
const group = options.series.map(seriesOf);
|
|
6037
|
+
return {
|
|
6038
|
+
constant: false,
|
|
6039
|
+
length: Math.max(0, ...group.map((values) => values.length)),
|
|
6040
|
+
at(valueIndex) {
|
|
6041
|
+
const defined = group.map((values) => values[valueIndex]).filter((value) => yOf(value) !== void 0);
|
|
6042
|
+
if (defined.length === 0) return;
|
|
6043
|
+
const ys = defined.map((value) => yOf(value));
|
|
6044
|
+
return {
|
|
6045
|
+
x: xOf(defined[0]),
|
|
6046
|
+
low: Math.min(...ys),
|
|
6047
|
+
high: Math.max(...ys)
|
|
6048
|
+
};
|
|
6049
|
+
}
|
|
6050
|
+
};
|
|
6051
|
+
}
|
|
6052
|
+
const edge = (option) => {
|
|
6053
|
+
if (option !== void 0 && isValues(option)) return { values: normalizedValues(option) };
|
|
6054
|
+
const selector = option === void 0 ? void 0 : selectorOf(option);
|
|
6055
|
+
return selector === void 0 ? { value: constant(option) } : { values: seriesOf(selector) };
|
|
6056
|
+
};
|
|
6057
|
+
const low = edge(options.low);
|
|
6058
|
+
const high = edge(options.high);
|
|
6059
|
+
const lengths = [low, high].flatMap((e) => "values" in e ? [e.values.length] : []);
|
|
6060
|
+
return {
|
|
6061
|
+
constant: lengths.length === 0,
|
|
6062
|
+
length: Math.max(0, ...lengths),
|
|
6063
|
+
at(valueIndex) {
|
|
6064
|
+
const lowValue = "values" in low ? low.values[valueIndex] : void 0;
|
|
6065
|
+
const highValue = "values" in high ? high.values[valueIndex] : void 0;
|
|
6066
|
+
const lowY = "value" in low ? low.value : yOf(lowValue);
|
|
6067
|
+
const highY = "value" in high ? high.value : yOf(highValue);
|
|
6068
|
+
if (lowY === void 0 || highY === void 0) return;
|
|
6069
|
+
return {
|
|
6070
|
+
x: xOf(lowValue) ?? xOf(highValue),
|
|
6071
|
+
low: lowY,
|
|
6072
|
+
high: highY
|
|
6073
|
+
};
|
|
6074
|
+
}
|
|
6075
|
+
};
|
|
6076
|
+
}
|
|
6077
|
+
/** The value a mark compares with the band: `y`, else `x`. */
|
|
6078
|
+
function markValue(value) {
|
|
6079
|
+
if (value !== null && typeof value === "object") {
|
|
6080
|
+
const { x, y } = value;
|
|
6081
|
+
return isNumeric(y) ? Number(y) : isNumeric(x) ? Number(x) : void 0;
|
|
6082
|
+
}
|
|
6083
|
+
return isNumeric(value) ? Number(value) : void 0;
|
|
6084
|
+
}
|
|
6085
|
+
function edgeContext(option, context) {
|
|
6086
|
+
if (option === void 0) return;
|
|
6087
|
+
if (isValues(option)) return { values: normalizedValues(option).map(yOf) };
|
|
6088
|
+
const selector = selectorOf(option);
|
|
6089
|
+
return selector === void 0 ? { value: option } : { seriesIndex: chartIndex(selector, context) };
|
|
6090
|
+
}
|
|
6091
|
+
/**
|
|
6092
|
+
* Creates a layer that fills the area between a low and a high edge
|
|
6093
|
+
* (`g.ct-band` with a `path.ct-band-area` per piece; the band breaks at
|
|
6094
|
+
* holes). Each edge is a constant value, values of its own (one per
|
|
6095
|
+
* label) or a series, or `series` names a group and the band covers their
|
|
6096
|
+
* minimum to their maximum at each value index. Constants and own values
|
|
6097
|
+
* widen the Y axis to include them. List the band
|
|
6098
|
+
* before the series layers to draw it behind them. It needs an X and a Y
|
|
6099
|
+
* axis, from {@link cartesianAxes}.
|
|
6100
|
+
*
|
|
6101
|
+
* @example
|
|
6102
|
+
* ```ts
|
|
6103
|
+
* import {
|
|
6104
|
+
* autoScaleAxis,
|
|
6105
|
+
* axisGrid,
|
|
6106
|
+
* axisLabels,
|
|
6107
|
+
* band,
|
|
6108
|
+
* cartesianAxes,
|
|
6109
|
+
* chart,
|
|
6110
|
+
* line,
|
|
6111
|
+
* stepAxis
|
|
6112
|
+
* } from 'chartist';
|
|
6113
|
+
*
|
|
6114
|
+
* const days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri'];
|
|
6115
|
+
*
|
|
6116
|
+
* chart('#chart', {
|
|
6117
|
+
* data: {
|
|
6118
|
+
* labels: days,
|
|
6119
|
+
* series: [{ name: 'visits', data: [12, 9, 7, 8, 5] }]
|
|
6120
|
+
* },
|
|
6121
|
+
* axes: cartesianAxes([
|
|
6122
|
+
* { id: 'day', side: 'bottom', type: stepAxis(), ticks: days },
|
|
6123
|
+
* { id: 'count', side: 'left', type: autoScaleAxis(), low: 0 }
|
|
6124
|
+
* ]),
|
|
6125
|
+
* layers: [
|
|
6126
|
+
* axisGrid(),
|
|
6127
|
+
* band({ low: 6, high: 10, mark: true }),
|
|
6128
|
+
* line(),
|
|
6129
|
+
* axisLabels()
|
|
6130
|
+
* ]
|
|
6131
|
+
* });
|
|
6132
|
+
* ```
|
|
6133
|
+
* @experimental
|
|
6134
|
+
*/
|
|
6135
|
+
function band(options) {
|
|
6136
|
+
const hasEdges = options.low !== void 0 || options.high !== void 0;
|
|
6137
|
+
if (options.series && hasEdges) throw new Error("Layer \"band\": series can't be combined with low and high");
|
|
6138
|
+
if (!options.series && (options.low === void 0 || options.high === void 0)) throw new Error("Layer \"band\": the band needs low and high, or series");
|
|
6139
|
+
const classNames = {
|
|
6140
|
+
...CLASS_NAMES$3,
|
|
6141
|
+
...options.classNames
|
|
6142
|
+
};
|
|
6143
|
+
const edgeSelectors = options.series ? void 0 : [options.low, options.high].flatMap((edge) => {
|
|
6144
|
+
const selector = edge === void 0 ? void 0 : selectorOf(edge);
|
|
6145
|
+
return selector === void 0 ? [] : [selector];
|
|
6146
|
+
});
|
|
6147
|
+
const ownValues = options.series ? [] : [options.low, options.high].flatMap((edge) => typeof edge === "number" ? [edge] : edge !== void 0 && isValues(edge) ? normalizedValues(edge).flatMap((value) => {
|
|
6148
|
+
const y = yOf(value);
|
|
6149
|
+
return y === void 0 ? [] : [y];
|
|
6150
|
+
}) : []);
|
|
6151
|
+
const layer = {
|
|
6152
|
+
type: "band",
|
|
6153
|
+
coordinates: ["cartesian"],
|
|
6154
|
+
axes: {
|
|
6155
|
+
x: options.x,
|
|
6156
|
+
y: options.y
|
|
6157
|
+
},
|
|
6158
|
+
series: options.series ?? edgeSelectors,
|
|
6159
|
+
extent({ axes }) {
|
|
6160
|
+
return axes.y !== void 0 && ownValues.length > 0 ? { [axes.y]: {
|
|
6161
|
+
low: Math.min(...ownValues),
|
|
6162
|
+
high: Math.max(...ownValues)
|
|
6163
|
+
} } : {};
|
|
6164
|
+
},
|
|
6165
|
+
compose(context) {
|
|
6166
|
+
const { area, axes } = context;
|
|
6167
|
+
const { x: axisX, y: axisY } = axes;
|
|
6168
|
+
if (!axisX || !axisY || !context.normalized) throw new Error("Layer \"band\" needs an x and a y axis");
|
|
6169
|
+
const range = axisY.range;
|
|
6170
|
+
const clamp = (value) => range ? Math.min(Math.max(value, range.min), range.max) : value;
|
|
6171
|
+
const edges = bandEdges(options, context, clamp);
|
|
6172
|
+
let pieces;
|
|
6173
|
+
if (edges.constant) {
|
|
6174
|
+
const { low, high } = edges.at(0);
|
|
6175
|
+
const lowY = area.y1 - axisY.project(low);
|
|
6176
|
+
const highY = area.y1 - axisY.project(high);
|
|
6177
|
+
pieces = [new SvgPath(true).move(area.x1, highY).line(area.x2, highY).line(area.x2, lowY).line(area.x1, lowY)];
|
|
6178
|
+
} else {
|
|
6179
|
+
const upper = [];
|
|
6180
|
+
const lower = [];
|
|
6181
|
+
for (let valueIndex = 0; valueIndex < edges.length; valueIndex++) {
|
|
6182
|
+
const at = edges.at(valueIndex);
|
|
6183
|
+
upper.push(at && {
|
|
6184
|
+
x: at.x,
|
|
6185
|
+
y: at.high
|
|
6186
|
+
});
|
|
6187
|
+
lower.push(at && {
|
|
6188
|
+
x: at.x,
|
|
6189
|
+
y: at.low
|
|
6190
|
+
});
|
|
6191
|
+
}
|
|
6192
|
+
const shift = centerShift(axisX, options.align);
|
|
6193
|
+
const interpolation = interpolationOf(options.lineSmooth ?? true);
|
|
6194
|
+
const pathOf = (values) => seriesPath(values, {
|
|
6195
|
+
x: axisX,
|
|
6196
|
+
y: axisY
|
|
6197
|
+
}, area, shift, interpolation).splitByCommand("M").filter((piece) => piece.pathElements.length > 1);
|
|
6198
|
+
const lowerPieces = pathOf(lower);
|
|
6199
|
+
pieces = pathOf(upper).flatMap((upperPiece, index) => {
|
|
6200
|
+
const lowerPiece = lowerPieces[index];
|
|
6201
|
+
if (!lowerPiece || lowerPiece.pathElements.length !== upperPiece.pathElements.length) return [];
|
|
6202
|
+
const back = reversePath(lowerPiece);
|
|
6203
|
+
const start = back.pathElements[0];
|
|
6204
|
+
back.position(0).remove(1).line(start.x, start.y, false, start.data);
|
|
6205
|
+
return [SvgPath.join([upperPiece, back], true)];
|
|
6206
|
+
});
|
|
6207
|
+
}
|
|
6208
|
+
const edgesContext = options.series ? { series: options.series.map((s) => chartIndex(s, context)) } : {
|
|
6209
|
+
low: edgeContext(options.low, context),
|
|
6210
|
+
high: edgeContext(options.high, context)
|
|
6211
|
+
};
|
|
6212
|
+
const children = pieces.map((path) => node("path", { d: path.stringify() }, classNames.area, {
|
|
6213
|
+
role: "band",
|
|
6214
|
+
ctx: {
|
|
6215
|
+
...edgesContext,
|
|
6216
|
+
path: path.clone()
|
|
6217
|
+
}
|
|
6218
|
+
}));
|
|
6219
|
+
return [withFields(node("g", {}, options.className ? `${classNames.band} ${options.className}` : classNames.band), { children })];
|
|
6220
|
+
}
|
|
6221
|
+
};
|
|
6222
|
+
if (!options.mark) return layer;
|
|
6223
|
+
return {
|
|
6224
|
+
...layer,
|
|
6225
|
+
refine(current, context) {
|
|
6226
|
+
if (current.role !== "point" && current.role !== "bar") return;
|
|
6227
|
+
const value = markValue(current.ctx.value);
|
|
6228
|
+
const at = bandEdges(options, context).at(current.ctx.valueIndex);
|
|
6229
|
+
if (value === void 0 || !at) return;
|
|
6230
|
+
const inBand = value >= Math.min(at.low, at.high) && value <= Math.max(at.low, at.high);
|
|
6231
|
+
return current.addClass(inBand ? classNames.inBand : classNames.outBand);
|
|
6232
|
+
}
|
|
6233
|
+
};
|
|
6234
|
+
}
|
|
6235
|
+
//#endregion
|
|
6236
|
+
//#region src/layers/targetLine.ts
|
|
6237
|
+
/**
|
|
6238
|
+
* Target line layer: a line across the chart area at a constant value on
|
|
6239
|
+
* one axis, such as a goal, a limit or an average, with an optional label.
|
|
6240
|
+
*/
|
|
6241
|
+
const CLASS_NAMES$2 = {
|
|
6242
|
+
line: "ct-target-line",
|
|
6243
|
+
label: "ct-target-label"
|
|
6244
|
+
};
|
|
6245
|
+
/** The distance in px between a label and its line or the area's edge. */
|
|
6246
|
+
const LABEL_INSET = 4;
|
|
6247
|
+
/**
|
|
6248
|
+
* Creates a layer that draws a line across the chart area at a constant
|
|
6249
|
+
* value on one axis, such as a goal or a limit (`line.ct-target-line`).
|
|
6250
|
+
* On a Y axis the line is horizontal, on an X axis vertical. It can have
|
|
6251
|
+
* a label, drawn as SVG text (`text.ct-target-label`) next to it inside
|
|
6252
|
+
* the chart area, and a class, e.g. `ct-series-b` for a series' color.
|
|
6253
|
+
* The axis widens to include the value, unless its own `low` or `high`
|
|
6254
|
+
* leave it out; a line outside the axis isn't drawn. For several lines,
|
|
6255
|
+
* add a layer per line.
|
|
6256
|
+
*
|
|
6257
|
+
* @example
|
|
6258
|
+
* ```ts
|
|
6259
|
+
* import {
|
|
6260
|
+
* autoScaleAxis,
|
|
6261
|
+
* axisGrid,
|
|
6262
|
+
* axisLabels,
|
|
6263
|
+
* cartesianAxes,
|
|
6264
|
+
* chart,
|
|
6265
|
+
* line,
|
|
6266
|
+
* stepAxis,
|
|
6267
|
+
* targetLine
|
|
6268
|
+
* } from 'chartist';
|
|
6269
|
+
*
|
|
6270
|
+
* const months = ['Jan', 'Feb', 'Mar', 'Apr'];
|
|
6271
|
+
*
|
|
6272
|
+
* chart('#chart', {
|
|
6273
|
+
* data: { labels: months, series: [[620, 810, 740, 930]] },
|
|
6274
|
+
* axes: cartesianAxes([
|
|
6275
|
+
* { id: 'month', side: 'bottom', type: stepAxis(), ticks: months },
|
|
6276
|
+
* { id: 'sales', side: 'left', type: autoScaleAxis(), low: 0 }
|
|
6277
|
+
* ]),
|
|
6278
|
+
* layers: [
|
|
6279
|
+
* axisGrid(),
|
|
6280
|
+
* line(),
|
|
6281
|
+
* targetLine({ value: 700, label: 'Min' }),
|
|
6282
|
+
* targetLine({ value: 1000, label: 'Goal', className: 'ct-series-b' }),
|
|
6283
|
+
* axisLabels()
|
|
6284
|
+
* ]
|
|
6285
|
+
* });
|
|
6286
|
+
* ```
|
|
6287
|
+
* @experimental
|
|
6288
|
+
*/
|
|
6289
|
+
function targetLine(options) {
|
|
6290
|
+
const { value, label, className } = options;
|
|
6291
|
+
if (!Number.isFinite(value)) throw new Error("Layer \"targetLine\" needs a value");
|
|
6292
|
+
const classNames = {
|
|
6293
|
+
...CLASS_NAMES$2,
|
|
6294
|
+
...options.classNames
|
|
6295
|
+
};
|
|
6296
|
+
const atStart = options.labelPosition === "start";
|
|
6297
|
+
return {
|
|
6298
|
+
type: "targetLine",
|
|
6299
|
+
coordinates: ["cartesian"],
|
|
6300
|
+
series: [],
|
|
6301
|
+
extent({ axes }) {
|
|
6302
|
+
const id = options.axis ?? axes.y;
|
|
6303
|
+
return id === void 0 ? {} : { [id]: {
|
|
6304
|
+
low: value,
|
|
6305
|
+
high: value
|
|
6306
|
+
} };
|
|
6307
|
+
},
|
|
6308
|
+
compose({ area, axes, measureText }) {
|
|
6309
|
+
const all = axes.all ?? [];
|
|
6310
|
+
const axis = options.axis === void 0 ? all.find((candidate) => candidate.dimension === "y") : all.find((candidate) => candidate.id === options.axis);
|
|
6311
|
+
if (!axis) throw new Error(options.axis === void 0 ? "Layer \"targetLine\" needs a y axis" : `Chartist: unknown axis "${options.axis}" in layer "targetLine"`);
|
|
6312
|
+
const horizontal = axis.dimension === "y";
|
|
6313
|
+
const relative = axis.project(value, value);
|
|
6314
|
+
if (!Number.isFinite(relative) || relative < -1e-9 || relative > axis.length + 1e-9) return [];
|
|
6315
|
+
const ends = horizontal ? {
|
|
6316
|
+
x1: area.x1,
|
|
6317
|
+
y1: area.y1 - relative,
|
|
6318
|
+
x2: area.x2,
|
|
6319
|
+
y2: area.y1 - relative
|
|
6320
|
+
} : {
|
|
6321
|
+
x1: area.x1 + relative,
|
|
6322
|
+
y1: area.y2,
|
|
6323
|
+
x2: area.x1 + relative,
|
|
6324
|
+
y2: area.y1
|
|
6325
|
+
};
|
|
6326
|
+
const extra = className ? ` ${className}` : "";
|
|
6327
|
+
const lineNode = node("line", ends, `${classNames.line}${extra}`, {
|
|
6328
|
+
role: "targetLine",
|
|
6329
|
+
ctx: {
|
|
6330
|
+
axis,
|
|
6331
|
+
value,
|
|
6332
|
+
...label !== void 0 && { label },
|
|
6333
|
+
...ends
|
|
6334
|
+
}
|
|
6335
|
+
});
|
|
6336
|
+
if (label === void 0 || label === "") return [lineNode];
|
|
6337
|
+
const labelClasses = `${classNames.label}${extra}`;
|
|
6338
|
+
let position;
|
|
6339
|
+
if (horizontal) position = {
|
|
6340
|
+
x: atStart ? area.x1 + LABEL_INSET : area.x2 - LABEL_INSET,
|
|
6341
|
+
y: ends.y1 - LABEL_INSET,
|
|
6342
|
+
anchor: atStart ? "start" : "end"
|
|
6343
|
+
};
|
|
6344
|
+
else {
|
|
6345
|
+
const fontSize = measureText(label, { classes: labelClasses.split(" ") }).fontSize ?? 12;
|
|
6346
|
+
position = {
|
|
6347
|
+
x: ends.x1 + LABEL_INSET,
|
|
6348
|
+
y: atStart ? area.y1 - LABEL_INSET : area.y2 + LABEL_INSET + textAscent * fontSize,
|
|
6349
|
+
anchor: "start"
|
|
6350
|
+
};
|
|
6351
|
+
}
|
|
6352
|
+
return [lineNode, node("text", {
|
|
6353
|
+
x: position.x,
|
|
6354
|
+
y: position.y,
|
|
6355
|
+
"text-anchor": position.anchor
|
|
6356
|
+
}, labelClasses, {
|
|
6357
|
+
role: "targetLabel",
|
|
6358
|
+
ctx: {
|
|
6359
|
+
axis,
|
|
6360
|
+
value,
|
|
6361
|
+
text: label,
|
|
6362
|
+
x: position.x,
|
|
6363
|
+
y: position.y
|
|
6364
|
+
}
|
|
6365
|
+
}).text(label)];
|
|
6366
|
+
}
|
|
6367
|
+
};
|
|
6368
|
+
}
|
|
6369
|
+
//#endregion
|
|
6370
|
+
//#region src/layers/trendLine.ts
|
|
6371
|
+
/**
|
|
6372
|
+
* Trend line layer: a least-squares straight line through each series'
|
|
6373
|
+
* values, drawn in the series' color.
|
|
6374
|
+
*/
|
|
6375
|
+
const CLASS_NAMES$1 = {
|
|
6376
|
+
series: "ct-series",
|
|
6377
|
+
line: "ct-trend-line"
|
|
6378
|
+
};
|
|
6379
|
+
/**
|
|
6380
|
+
* Fits a straight line through a series' values by least squares: X is
|
|
6381
|
+
* the value's index (`byIndex`, for step axes) or its `x`. Holes and
|
|
6382
|
+
* values without a number for X are skipped. Fewer than two values, or
|
|
6383
|
+
* values that all share one X, fit no line.
|
|
6384
|
+
*/
|
|
6385
|
+
function fit(values, byIndex) {
|
|
6386
|
+
const xs = [];
|
|
6387
|
+
const ys = [];
|
|
6388
|
+
values.forEach((value, index) => {
|
|
6389
|
+
const y = isDataHoleValue(value) ? void 0 : getMultiValue(value, "y");
|
|
6390
|
+
const x = byIndex ? index : getMultiValue(value, "x");
|
|
6391
|
+
if (typeof x === "number" && Number.isFinite(x) && Number.isFinite(y)) {
|
|
6392
|
+
xs.push(x);
|
|
6393
|
+
ys.push(y);
|
|
6394
|
+
}
|
|
6395
|
+
});
|
|
6396
|
+
if (xs.length < 2) return;
|
|
6397
|
+
const mean = (list) => list.reduce((sum, value) => sum + value, 0) / list.length;
|
|
6398
|
+
const meanX = mean(xs);
|
|
6399
|
+
const meanY = mean(ys);
|
|
6400
|
+
let covariance = 0;
|
|
6401
|
+
let variance = 0;
|
|
6402
|
+
xs.forEach((x, i) => {
|
|
6403
|
+
covariance += (x - meanX) * (ys[i] - meanY);
|
|
6404
|
+
variance += (x - meanX) ** 2;
|
|
6405
|
+
});
|
|
6406
|
+
if (variance === 0) return;
|
|
6407
|
+
const slope = covariance / variance;
|
|
6408
|
+
return {
|
|
6409
|
+
slope,
|
|
6410
|
+
intercept: meanY - slope * meanX,
|
|
6411
|
+
x1: Math.min(...xs),
|
|
6412
|
+
x2: Math.max(...xs)
|
|
6413
|
+
};
|
|
6414
|
+
}
|
|
6415
|
+
/** True when every value that isn't a hole has a number for X. */
|
|
6416
|
+
function hasX(values) {
|
|
6417
|
+
const present = values.filter((value) => !isDataHoleValue(value));
|
|
6418
|
+
return present.length > 0 && present.every((value) => typeof getMultiValue(value, "x") === "number");
|
|
6419
|
+
}
|
|
6420
|
+
/**
|
|
6421
|
+
* Creates a layer that draws a trend line for each series: the straight
|
|
6422
|
+
* line that fits its values best (least squares), from its smallest to its
|
|
6423
|
+
* largest X, as a `line.ct-trend-line` in a series group
|
|
6424
|
+
* (`g.ct-series.ct-series-a`), so it takes the series' color. On a step
|
|
6425
|
+
* axis X is the value's index, on a scale axis the value's `x`. Holes are
|
|
6426
|
+
* skipped, and a series with fewer than two values gets no line. The Y
|
|
6427
|
+
* axis widens to include the line's ends. Add it next to the {@link line}
|
|
6428
|
+
* or {@link bar} layer that draws the values.
|
|
6429
|
+
*
|
|
6430
|
+
* @example
|
|
6431
|
+
* ```ts
|
|
6432
|
+
* import {
|
|
6433
|
+
* autoScaleAxis,
|
|
6434
|
+
* axisGrid,
|
|
6435
|
+
* axisLabels,
|
|
6436
|
+
* cartesianAxes,
|
|
6437
|
+
* chart,
|
|
6438
|
+
* line,
|
|
6439
|
+
* stepAxis,
|
|
6440
|
+
* trendLine
|
|
6441
|
+
* } from 'chartist';
|
|
6442
|
+
*
|
|
6443
|
+
* const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'];
|
|
6444
|
+
*
|
|
6445
|
+
* chart('#chart', {
|
|
6446
|
+
* data: {
|
|
6447
|
+
* labels: months,
|
|
6448
|
+
* series: [{ name: 'sales', data: [620, 810, 740, 930, 880, 1020] }]
|
|
6449
|
+
* },
|
|
6450
|
+
* axes: cartesianAxes([
|
|
6451
|
+
* { id: 'month', side: 'bottom', type: stepAxis(), ticks: months },
|
|
6452
|
+
* { id: 'eur', side: 'left', type: autoScaleAxis() }
|
|
6453
|
+
* ]),
|
|
6454
|
+
* layers: [axisGrid(), line(), trendLine(), axisLabels()]
|
|
6455
|
+
* });
|
|
6456
|
+
* ```
|
|
6457
|
+
* @experimental
|
|
6458
|
+
*/
|
|
6459
|
+
function trendLine(options = {}) {
|
|
6460
|
+
const classNames = {
|
|
6461
|
+
...CLASS_NAMES$1,
|
|
6462
|
+
...options.classNames
|
|
6463
|
+
};
|
|
6464
|
+
return {
|
|
6465
|
+
type: "trendLine",
|
|
6466
|
+
coordinates: ["cartesian"],
|
|
6467
|
+
axes: {
|
|
6468
|
+
x: options.x,
|
|
6469
|
+
y: options.y
|
|
6470
|
+
},
|
|
6471
|
+
series: options.series,
|
|
6472
|
+
extent({ normalized, axes }) {
|
|
6473
|
+
if (axes.y === void 0) return {};
|
|
6474
|
+
const ends = normalized.series.flatMap((values) => {
|
|
6475
|
+
const fitted = fit(values, !hasX(values));
|
|
6476
|
+
return fitted ? [fitted.slope * fitted.x1 + fitted.intercept, fitted.slope * fitted.x2 + fitted.intercept] : [];
|
|
6477
|
+
});
|
|
6478
|
+
return ends.length > 0 ? { [axes.y]: {
|
|
6479
|
+
low: Math.min(...ends),
|
|
6480
|
+
high: Math.max(...ends)
|
|
6481
|
+
} } : {};
|
|
6482
|
+
},
|
|
6483
|
+
compose({ data, area, axes, normalized, seriesIndexes }) {
|
|
6484
|
+
const { x: axisX, y: axisY } = axes;
|
|
6485
|
+
if (!axisX || !axisY || !normalized) throw new Error("Layer \"trendLine\" needs an x and a y axis");
|
|
6486
|
+
const byIndex = axisX.kind === "step";
|
|
6487
|
+
const shift = centerShift(axisX, options.align);
|
|
6488
|
+
return data.series.flatMap((series, localIndex) => {
|
|
6489
|
+
const fitted = fit(normalized.series[localIndex], byIndex);
|
|
6490
|
+
if (!fitted) return [];
|
|
6491
|
+
const seriesIndex = seriesIndexes?.[localIndex] ?? localIndex;
|
|
6492
|
+
const { slope, intercept } = fitted;
|
|
6493
|
+
const at = (x) => ({
|
|
6494
|
+
x: area.x1 + shift + axisX.project(x, x),
|
|
6495
|
+
y: area.y1 - axisY.project(slope * x + intercept)
|
|
6496
|
+
});
|
|
6497
|
+
const start = at(fitted.x1);
|
|
6498
|
+
const end = at(fitted.x2);
|
|
6499
|
+
const ends = {
|
|
6500
|
+
x1: start.x,
|
|
6501
|
+
y1: start.y,
|
|
6502
|
+
x2: end.x,
|
|
6503
|
+
y2: end.y
|
|
6504
|
+
};
|
|
6505
|
+
const seriesContext = {
|
|
6506
|
+
series: {
|
|
6507
|
+
name: series.name,
|
|
6508
|
+
className: series.className,
|
|
6509
|
+
meta: series.meta,
|
|
6510
|
+
data: series.values
|
|
6511
|
+
},
|
|
6512
|
+
seriesIndex,
|
|
6513
|
+
meta: series.meta
|
|
6514
|
+
};
|
|
6515
|
+
return [withFields(node("g", {}, `${classNames.series} ${series.className || `${classNames.series}-${alphaNumerate(seriesIndex)}`}`, {
|
|
6516
|
+
role: "series",
|
|
6517
|
+
ctx: seriesContext
|
|
6518
|
+
}), { children: [node("line", ends, classNames.line, {
|
|
6519
|
+
role: "trendLine",
|
|
6520
|
+
ctx: {
|
|
6521
|
+
seriesIndex,
|
|
6522
|
+
slope,
|
|
6523
|
+
intercept,
|
|
6524
|
+
...ends
|
|
6525
|
+
}
|
|
6526
|
+
})] })];
|
|
6527
|
+
});
|
|
6528
|
+
}
|
|
6529
|
+
};
|
|
6530
|
+
}
|
|
6531
|
+
//#endregion
|
|
5858
6532
|
//#region src/layers/axes.ts
|
|
5859
6533
|
const CLASS_NAMES = {
|
|
5860
6534
|
grid: "ct-grid",
|
|
@@ -5880,7 +6554,7 @@ function drawnOptions(axis) {
|
|
|
5880
6554
|
},
|
|
5881
6555
|
showLabel: options.showLabel ?? true,
|
|
5882
6556
|
showGrid: options.showGrid ?? true,
|
|
5883
|
-
|
|
6557
|
+
labelTransform: labelTransformOf(options)
|
|
5884
6558
|
};
|
|
5885
6559
|
}
|
|
5886
6560
|
function selectedAxes(context, ids) {
|
|
@@ -6022,12 +6696,15 @@ function axisLabels(options = {}) {
|
|
|
6022
6696
|
coordinates: ["cartesian"],
|
|
6023
6697
|
series: [],
|
|
6024
6698
|
compose(context) {
|
|
6025
|
-
const
|
|
6026
|
-
return [withFields(node("g", {}, classNames.labelGroup), { children: selectedAxes(context, options.axes).flatMap((axis) => nodesOf(axis, context, classNames,
|
|
6699
|
+
const svg = (options.labels ?? context.labels) === "svg";
|
|
6700
|
+
return [withFields(node("g", {}, classNames.labelGroup), { children: selectedAxes(context, options.axes).flatMap((axis) => nodesOf(axis, context, classNames, svg ? svgLabels(context.measureText, "line", {
|
|
6701
|
+
...options.align,
|
|
6702
|
+
...axis.options.labelAlign
|
|
6703
|
+
}) : void 0).labels) })];
|
|
6027
6704
|
}
|
|
6028
6705
|
};
|
|
6029
6706
|
}
|
|
6030
6707
|
//#endregion
|
|
6031
|
-
export { AutoScaleAxis, Axis, BarChart, BaseChart, EPSILON, EventEmitter, FixedScaleAxis, interpolation_exports as Interpolation, LineChart, PieChart, StepAxis, Svg, SvgList, SvgPath, alphaNumerate, autoScaleAxis, axisGrid, axisLabels, axisUnits, bar, barChart, barChartConfig, cartesianAxes, chart, container, createChartRect, createGrid, createGridBackground, createLabel, createSvg, deserialize, determineAnchorPosition, domRenderer, each, easings, ensureUnit, escapingMap, estimateText, extend, findAll, fixedScaleAxis, getBounds, getHighLow, getMetaData, getMultiValue, getNumberOrUndefined, getSeriesOption, isArrayOfArrays, isArrayOfSeries, isDataHoleValue, isFalseyButZero, isMultiValue, isNumeric, line, lineChart, lineChartConfig, mapNodes, namespaces, node, noop, normalizeData, normalizePadding, optionsProvider, orderOfMagnitude, pie, pieChart, pieChartConfig, polarToCartesian, precision, projectLength, quantity, renderToString, responsive, rho, roundWithPrecision, safeHasProperty, serialMap, serialize, seriesColors, splitIntoSegments, stepAxis, sum, textAscent, times, toScene, withOptions };
|
|
6708
|
+
export { AutoScaleAxis, Axis, BarChart, BaseChart, EPSILON, EventEmitter, FixedScaleAxis, interpolation_exports as Interpolation, LineChart, PieChart, StepAxis, Svg, SvgList, SvgPath, alphaNumerate, autoScaleAxis, axisGrid, axisLabels, axisUnits, band, bar, barChart, barChartConfig, cartesianAxes, chart, container, createChartRect, createGrid, createGridBackground, createLabel, createSvg, deserialize, determineAnchorPosition, domRenderer, each, easings, ensureUnit, escapingMap, estimateText, extend, findAll, fixedScaleAxis, getBounds, getHighLow, getMetaData, getMultiValue, getNumberOrUndefined, getSeriesOption, isArrayOfArrays, isArrayOfSeries, isDataHoleValue, isFalseyButZero, isMultiValue, isNumeric, line, lineChart, lineChartConfig, mapNodes, namespaces, node, noop, normalizeData, normalizePadding, optionsProvider, orderOfMagnitude, pie, pieChart, pieChartConfig, polarToCartesian, precision, projectLength, quantity, renderToString, responsive, rho, roundWithPrecision, safeHasProperty, serialMap, serialize, seriesColors, splitIntoSegments, stepAxis, sum, targetLine, textAscent, times, toScene, trendLine, withOptions };
|
|
6032
6709
|
|
|
6033
6710
|
//# sourceMappingURL=index.js.map
|