diff --git a/config/rollup/esm.js b/config/rollup/esm.js
index 8b25d0790..e972f8165 100644
--- a/config/rollup/esm.js
+++ b/config/rollup/esm.js
@@ -34,9 +34,10 @@ const plugins = [
preventAssignment: true
})
];
+
const external = id => /^d3-/.test(id);
-const bbPlugins = readdirSync(resolvePath("../../src/Plugin/"), {
+const bbPlugins = readdirSync(resolvePath("../src/Plugin/"), {
withFileTypes: true
})
.filter(dirent => dirent.isDirectory())
diff --git a/config/webpack/plugin.cjs b/config/webpack/plugin.cjs
index 8457ac1b0..a902d8c78 100644
--- a/config/webpack/plugin.cjs
+++ b/config/webpack/plugin.cjs
@@ -71,7 +71,7 @@ module.exports = (common, env) => {
return mergeWithCustomize({
customizeObject: customizeObject({
entry: "replace",
- output: "replace"
+ output: "append"
})
})(common, config);
};
diff --git a/demo/chart.js b/demo/chart.js
index 6b8023122..a57ddd5bd 100644
--- a/demo/chart.js
+++ b/demo/chart.js
@@ -395,14 +395,24 @@ code.data;
this.$chartArea.appendChild($el);
- if (/^(legend|tooltip)Template/.test(key)) {
+ if (/^(legend|tooltip)Template/.test(key) || /(sparkline)/.test(key)) {
+ const name = RegExp.$1;
+ let attrName = "id";
+
template = document.createElement("div");
- template.id = this.getLowerFirstCase(RegExp.$1);
+
+ if (key === "sparkline") {
+ attrName = "className";
+ }
+
+ template[attrName] = this.getLowerFirstCase(RegExp.$1);
template.style.textAlign = "center";
this.$chartArea.appendChild(template);
- template = "<div id=\""+ template.id +"\"></div>";
- } else if (typeKey[0] === "Plugins") {
+ template = "<div "+ attrName.replace(/name/i, "") +"=\""+ template[attrName] +"\"></div>";
+ }
+
+ if (typeKey[0] === "Plugins") {
type.options._plugins.forEach(function(v) {
plugins = Object.keys(v).map(function(p) {
return new bb.plugin[p](v[p]);
diff --git a/demo/demo.js b/demo/demo.js
index 15229ae75..e7abfd882 100644
--- a/demo/demo.js
+++ b/demo/demo.js
@@ -3078,6 +3078,76 @@ d3.select(".chart_area")
}
}]
}
+ },
+ Sparkline: {
+ description: "Generates multiple tiny charts from single instance.
Must load or import plugin before the use.",
+ options: {
+ size: {
+ width: 150,
+ height: 50
+ },
+ data: {
+ columns: [
+ ["data1", 130, 200, 150, 140, 160, 150],
+ ["data2", 200, 130, 90, 240, 130, 220],
+ ["data3", 300, 200, 160, 400, 250, 250],
+ ["data4", 300, 200, 160, 400, 250, 250],
+ ["data5", 30, 120, 250, 340, 160, 50],
+ ["data6", 290, 270, 220, 250, 260, 120],
+ ["data7", 283, 170, 275, 143, 220, 255],
+ ["data8", 130, 220, 350, 340, 260, 150],
+ ["data9", 330, 220, 150, 240, 360, 250],
+ ["data10", 300, 200, 160, 400, 250, 250],
+ ["data11", 230, 320, 510, 140, 160, 150],
+ ["data12", 200, 130, 90, 240, 130, 220],
+ ["data13", 300, 200, 160, 400, 250, 250],
+ ["data14", 230, 230, 390, 200, 290, 220],
+ ["data15", 130, 120, 150, 140, 160, 150],
+ ["data16", 290, 270, 220, 250, 160, 120],
+ ["data17", 283, 170, 275, 143, 220, 255],
+ ["data18", 130, 220, 150, 240, 360, 250],
+ ["data19", 350, 230, 390, 222, 321, 123],
+ ["data20", 300, 200, 160, 400, 250, 250],
+ ["data21", 330, 320, 350, 240, 260, 250],
+ ["data22", 200, 130, 90, 240, 130, 220],
+ ["data23", 300, 200, 160, 400, 250, 250],
+ ["data24", 321, 231, 129, 297, 333, 220],
+ ["data25", 230, 320, 250, 340, 260, 350],
+ ["data26", 290, 170, 210, 150, 160, 220],
+ ["data27", 283, 170, 275, 143, 220, 255],
+ ["data28", 330, 320, 350, 340, 360, 350],
+ ["data29", 50, 330, 90, 340, 130, 320],
+ ["data30", 300, 200, 160, 400, 250, 250],
+ ],
+ type: "area",
+ types: {
+ data1: "area",
+ data2: "area",
+ data4: "area-spline",
+ data5: "step",
+ data8: "area-step",
+ data9: "spline",
+ data10: "bar",
+ data12: "spline",
+ data15: "bar",
+ data20: "area-spline",
+ data21: "area",
+ data22: "area",
+ data23: "bar",
+ data24: "area-spline",
+ data25: "step",
+ data27: "area-step",
+ data28: "area-step",
+ data29: "spline",
+ data30: "bar",
+ }
+ },
+ _plugins: [{
+ sparkline: {
+ selector: ".sparkline"
+ }
+ }]
+ }
}
},
Point: {
diff --git a/demo/index.html b/demo/index.html
index 95cac54e9..c9c8ca3a0 100644
--- a/demo/index.html
+++ b/demo/index.html
@@ -184,6 +184,9 @@
Sample code
}),
plugins_tableview: path.map(function(p) {
return p + "plugin/billboardjs-plugin-tableview.js"
+ }),
+ plugins_sparkline: path.map(function(p) {
+ return p + "plugin/billboardjs-plugin-sparkline.js"
})
});
diff --git a/demo/tomorrow.css b/demo/tomorrow.css
index 09722e546..bf1fb1088 100644
--- a/demo/tomorrow.css
+++ b/demo/tomorrow.css
@@ -56,4 +56,18 @@ pre code {
#description {
font-size: 13px;
color: gray;
+}
+
+.sparkline {
+ border: solid 1px #eee;
+ width: 150px;
+ height: 50px;
+ float: left;
+}
+
+.chart_area::after {
+ display: block;
+ float: none;
+ clear: left;
+ content: "";
}
\ No newline at end of file
diff --git a/package.json b/package.json
index 31624125d..400c0c373 100644
--- a/package.json
+++ b/package.json
@@ -184,7 +184,7 @@
"style-loader": "^3.2.1",
"terser-webpack-plugin": "^5.1.4",
"tslib": "^2.3.1",
- "typescript": "^4.4.2",
+ "typescript": "^4.3.5",
"webpack": "^5.51.1",
"webpack-bundle-analyzer": "^4.4.2",
"webpack-clean": "^1.2.5",
diff --git a/src/ChartInternal/shape/bar.ts b/src/ChartInternal/shape/bar.ts
index a5cf5b7f9..1f7e46263 100644
--- a/src/ChartInternal/shape/bar.ts
+++ b/src/ChartInternal/shape/bar.ts
@@ -45,7 +45,7 @@ export default {
// Bars for each data
mainBarEnter.append("g")
.attr("class", classBars)
- .style("cursor", d => (isSelectable?.bind($$.api)(d) ? "pointer" : null));
+ .style("cursor", d => (isSelectable?.bind?.($$.api)(d) ? "pointer" : null));
},
/**
diff --git a/src/ChartInternal/shape/point.ts b/src/ChartInternal/shape/point.ts
index 54e952eea..b77ad4a64 100644
--- a/src/ChartInternal/shape/point.ts
+++ b/src/ChartInternal/shape/point.ts
@@ -250,13 +250,17 @@ export default {
};
},
- getCircles(i: number, id: string) {
- const $$ = this;
- const suffix = (isValue(i) ? `-${i}` : ``);
+ // getCircles(i: number, id: string) {
+ // const $$ = this;
+ // const suffix = (isValue(i) ? `-${i}` : ``);
- return (id ? $$.$el.main.selectAll(`.${CLASS.circles}${$$.getTargetSelectorSuffix(id)}`) : $$.$el.main)
- .selectAll(`.${CLASS.circle}${suffix}`);
- },
+ // if (!$$.$el.circle.empty()) {
+ // return $$.$el.circle.filter(d => d.id === (id || d.id) && (isValue(i) ? d.index === i : true));
+ // }
+
+ // return (id ? $$.$el.main.selectAll(`.${CLASS.circles}${$$.getTargetSelectorSuffix(id)}`) : $$.$el.main)
+ // .selectAll(`.${CLASS.circle}${suffix}`);
+ // },
expandCircles(i: number, id: string, reset?: boolean): void {
const $$ = this;
@@ -264,7 +268,7 @@ export default {
reset && $$.unexpandCircles();
- const circles = $$.getCircles(i, id).classed(CLASS.EXPANDED, true);
+ const circles = $$.getShapeByIndex("circle", i, id).classed(CLASS.EXPANDED, true);
const scale = r(circles) / $$.config.point_r;
const ratio = 1 - scale;
@@ -292,7 +296,7 @@ export default {
const $$ = this;
const r = $$.pointR.bind($$);
- const circles = $$.getCircles(i)
+ const circles = $$.getShapeByIndex("circle", i)
.filter(function() {
return d3Select(this).classed(CLASS.EXPANDED);
})
diff --git a/src/ChartInternal/shape/shape.ts b/src/ChartInternal/shape/shape.ts
index ccc9a82a1..5c7c2c90b 100644
--- a/src/ChartInternal/shape/shape.ts
+++ b/src/ChartInternal/shape/shape.ts
@@ -23,6 +23,7 @@ import {
curveStep as d3CurveStep
} from "d3-shape";
import {select as d3Select} from "d3-selection";
+import {d3Selection} from "types/types";
import CLASS from "../../config/classes";
import {capitalize, getUnique, isObjectType, isNumber, isValue, isUndefined, notEmpty} from "../../module/util";
@@ -156,7 +157,7 @@ export default {
);
return d => {
- const ind = $$.getIndices(indices, d.id);
+ const ind = $$.getIndices(indices, d.id, "getShapeX");
const index = d.id in ind ? ind[d.id] : 0;
const targetsNum = (ind.__max__ || 0) + 1;
let x = 0;
@@ -348,14 +349,24 @@ export default {
* @returns {d3Selection}
* @private
*/
- getShapeByIndex(shapeName: string, i: number, id?: string) {
+ getShapeByIndex(shapeName: string, i: number, id?: string): d3Selection {
const $$ = this;
- const {main} = $$.$el;
+ const {$el} = $$;
const suffix = (isValue(i) ? `-${i}` : ``);
+ let shape = $el[shapeName];
+
+ // filter from shape reference if has
+ if (shape && !shape.empty()) {
+ shape = shape
+ .filter(d => (id ? d.id === id : true))
+ .filter(d => (isValue(i) ? d.index === i : true));
+ } else {
+ shape = (id ? $el.main
+ .selectAll(`.${CLASS[`${shapeName}s`]}${$$.getTargetSelectorSuffix(id)}`) : $el.main)
+ .selectAll(`.${CLASS[shapeName]}${suffix}`);
+ }
- return (id ? main
- .selectAll(`.${CLASS[`${shapeName}s`]}${$$.getTargetSelectorSuffix(id)}`) : main)
- .selectAll(`.${CLASS[shapeName]}${suffix}`);
+ return shape;
},
isWithinShape(that, d): boolean {
diff --git a/src/Plugin/bubblecompare/index.ts b/src/Plugin/bubblecompare/index.ts
index 2c1d04175..0e91a7504 100644
--- a/src/Plugin/bubblecompare/index.ts
+++ b/src/Plugin/bubblecompare/index.ts
@@ -34,7 +34,7 @@ import Plugin from "../Plugin";
* });
* @example
* import {bb} from "billboard.js";
- * import BubbleCompare from "billboard.js/dist/billboardjs-plugin-bubblecompare.esm";
+ * import BubbleCompare from "billboard.js/dist/billboardjs-plugin-bubblecompare";
*
* bb.generate({
* plugins: [
diff --git a/src/Plugin/sparkline/Options.ts b/src/Plugin/sparkline/Options.ts
new file mode 100644
index 000000000..305230997
--- /dev/null
+++ b/src/Plugin/sparkline/Options.ts
@@ -0,0 +1,29 @@
+/**
+ * Copyright (c) 2021 ~ present NAVER Corp.
+ * billboard.js project is licensed under the MIT license
+ */
+/**
+ * Sparkline plugin option class
+ * @class SparklineOptions
+ * @param {Options} options Sparkline plugin options
+ * @augments Plugin
+ * @returns {TableviewOptions}
+ * @private
+ */
+export default class Options {
+ constructor() {
+ return {
+ /**
+ * Specify sparkline charts holder selector.
+ * - **NOTE:** The amount of holder should match with the amount of data. If has less, will append necessaray amount nodes as sibling of main chart.
+ * @name selector
+ * @memberof plugin-sparkline
+ * @type {string}
+ * @default undefined
+ * @example
+ * selector: ".sparkline"
+ */
+ selector: undefined
+ };
+ }
+}
diff --git a/src/Plugin/sparkline/index.ts b/src/Plugin/sparkline/index.ts
new file mode 100644
index 000000000..f165c16ae
--- /dev/null
+++ b/src/Plugin/sparkline/index.ts
@@ -0,0 +1,277 @@
+/**
+ * Copyright (c) 2021 ~ present NAVER Corp.
+ * billboard.js project is licensed under the MIT license
+ */
+import CLASS from "../../config/classes";
+import Plugin from "../Plugin";
+import Options from "./Options";
+import {IData} from "../../ChartInternal/data/IData";
+import {loadConfig} from "../../config/config";
+
+/**
+ * Sparkline plugin.
+ * Generates sparkline charts
+ * - **NOTE:**
+ * - Plugins aren't built-in. Need to be loaded or imported to be used.
+ * - Non required modules from billboard.js core, need to be installed separately.
+ *
+ * - **Bear in mind:**
+ * - Use this plugin to visualize multiple tiny chart only and chart APIs won't work properly.
+ * - Sparkline chart size will be based on the main chart element size. To control spakrline charts, is highly recommended to set `size` option.
+ * - Bubble, scatter and Arc(pie, donut, ratdar) types aren't supported.
+ * - Some options will be stricted to be:
+ * - `resize.auto = false`
+ * - `axis.x.show = false`
+ * - `axis.y.show = false`
+ * - `axis.y.padding = 10`
+ * - `legend.show = false`
+ *
+ * @class plugin-sparkline
+ * @param {object} options sparkline plugin options
+ * @augments Plugin
+ * @returns {Sparkline}
+ * @example
+ * // Plugin must be loaded before the use.
+ *
+ *
+ * var chart = bb.generate({
+ * ...
+ * plugins: [
+ * new bb.plugin.sparkline({
+ * selector: ".sparkline"
+ * }),
+ * ]
+ * });
+ * @example
+ * import {bb} from "billboard.js";
+ * import Sparkline from "billboard.js/dist/billboardjs-plugin-sparkline";
+ *
+ * bb.generate({
+ * ...
+ * plugins: [
+ * new Sparkline({ ... })
+ * ]
+ * })
+ */
+export default class Sparkline extends Plugin {
+ static version = `0.0.1`;
+ private config;
+ private element;
+
+ constructor(options) {
+ super(options);
+ this.config = new Options();
+
+ return this;
+ }
+
+ $beforeInit(): void {
+ loadConfig.call(this, this.options);
+
+ this.validate();
+ this.element = [].slice.call(document.querySelectorAll(this.config.selector));
+
+ // override internal methods
+ this.overrideInternals();
+
+ // override options
+ this.overrideOptions();
+
+ // bind event handlers's context
+ this.overHandler = this.overHandler.bind(this);
+ this.moveHandler = this.moveHandler.bind(this);
+ this.outHandler = this.outHandler.bind(this);
+ }
+
+ validate(): void {
+ const {$$, config} = this;
+ let msg = "";
+
+ if (!config.selector || !document.querySelector(config.selector)) {
+ msg = "No holder elements found from given selector option.";
+ }
+
+ if ($$.hasType("bubble") || $$.hasType("scatter") || $$.hasArcType($$.data.targets)) {
+ msg = "Contains non supported chart types.";
+ }
+
+ if (msg) {
+ throw new Error(`[Sparkline plugin] ${msg}`);
+ }
+ }
+
+ overrideInternals(): void {
+ const {$$} = this;
+ const {getBarW, getIndices} = $$;
+
+ // override internal methods to positioning bars
+ $$.getIndices = function(indices, id, caller) {
+ return caller === "getShapeX" ? {} : getIndices.call(this, indices, id);
+ };
+
+ $$.getBarW = function(type, axis) {
+ return getBarW.call(this, type, axis, 1);
+ };
+ }
+
+ overrideOptions(): void {
+ const {config} = this.$$;
+
+ config.legend_show = false;
+ config.resize_auto = false;
+
+ config.axis_x_show = false;
+ config.axis_x_padding = {
+ left: 15,
+ right: 15,
+ unit: "px"
+ };
+
+ config.axis_y_show = false;
+ config.axis_y_padding = 5;
+
+ if (!config.tooltip_position) {
+ config.tooltip_position = function(data, width, height) {
+ const {internal: {state: {event}}} = this;
+ let top = event.pageY - (height * 1.35);
+ let left = event.pageX - (width / 2);
+
+ if (top < 0) {
+ top = 0;
+ }
+
+ if (left < 0) {
+ left = 0;
+ }
+
+ return {top, left};
+ };
+ }
+ }
+
+ $init(): void {
+ const {$$} = this;
+ const {$el} = $$;
+
+ // make disable-ish main chart element
+ $el.chart
+ .style("width", "0")
+ .style("height", "0")
+ .style("pointer-events", "none");
+
+ document.body.appendChild($el.tooltip.node());
+ }
+
+ $afterInit(): void {
+ const {$$} = this;
+
+ $$.$el.svg.attr("style", null)
+ .style("width", "0")
+ .style("height", "0");
+
+ this.bindEvents(true);
+ }
+
+ /**
+ * Bind tooltip event handlers for each sparkline elements.
+ * @param {boolean} bind or unbind
+ * @private
+ */
+ bindEvents(bind = true): void {
+ if (this.$$.config.interaction_enabled) {
+ const method = `${bind ? "add" : "remove"}EventListener`;
+
+ this.element
+ .forEach(el => {
+ const svg = el.querySelector("svg");
+
+ svg[method]("mouseover", this.overHandler);
+ svg[method]("mousemove", this.moveHandler);
+ svg[method]("mouseout", this.outHandler);
+ });
+ }
+ }
+
+ overHandler(e): void {
+ const {$$} = this;
+ const {state: {eventReceiver}} = $$;
+
+ eventReceiver.rect = e.target.getBoundingClientRect();
+ }
+
+ moveHandler(e): void {
+ const {$$} = this;
+ const index = $$.getDataIndexFromEvent(e);
+ const data = $$.api.data(e.target.__id)?.[0] as IData;
+ const d = data?.values?.[index];
+
+ if (d && !d.name) {
+ d.name = d.id;
+ }
+
+ $$.state.event = e;
+ $$.setExpand(index, data.id, true);
+ $$.showTooltip([d], e.target);
+ }
+
+ outHandler(e): void {
+ const {$$} = this;
+
+ $$.state.event = e;
+ $$.unexpandCircles();
+ $$.hideTooltip();
+ }
+
+ $redraw(): void {
+ const {$$} = this;
+ const {$el} = $$;
+
+ let el = this.element;
+ const data = $$.api.data();
+ const svgWrapper = $el.chart.html().match(/`;
+ svg = el[i].querySelector("svg");
+ svg.__id = id;
+ }
+
+ if (!svg.querySelector(selector)) {
+ shape.style("opacity", null);
+ }
+
+ shape
+ .style("fill", "none")
+ .style("opacity", null);
+
+ svg.innerHTML = "";
+ svg.appendChild(shape.node());
+ });
+ }
+
+ $willDestroy(): void {
+ this.bindEvents(false);
+ this.element
+ .forEach(el => {
+ el.innerHTML = "";
+ });
+ }
+}
diff --git a/src/Plugin/stanford/index.ts b/src/Plugin/stanford/index.ts
index c5e9b9f12..f4ce0627f 100644
--- a/src/Plugin/stanford/index.ts
+++ b/src/Plugin/stanford/index.ts
@@ -91,7 +91,7 @@ import {compareEpochs, isEmpty, isFunction, isString, parseDate, pointInRegion}
* });
* @example
* import {bb} from "billboard.js";
- * import Stanford from "billboard.js/dist/billboardjs-plugin-stanford.esm";
+ * import Stanford from "billboard.js/dist/billboardjs-plugin-stanford";
*
* bb.generate({
* plugins: [
diff --git a/src/Plugin/tableview/index.ts b/src/Plugin/tableview/index.ts
index 871413e2f..d272ec56c 100644
--- a/src/Plugin/tableview/index.ts
+++ b/src/Plugin/tableview/index.ts
@@ -42,7 +42,7 @@ import {isNumber, tplProcess} from "../../module/util";
* });
* @example
* import {bb} from "billboard.js";
- * import TableView from "billboard.js/dist/billboardjs-plugin-tableview.esm";
+ * import TableView from "billboard.js/dist/billboardjs-plugin-tableview";
*
* bb.generate({
* ...
diff --git a/src/Plugin/textoverlap/index.ts b/src/Plugin/textoverlap/index.ts
index c90bf3daf..4b6e9aeac 100644
--- a/src/Plugin/textoverlap/index.ts
+++ b/src/Plugin/textoverlap/index.ts
@@ -50,7 +50,7 @@ import Options from "./Options";
* });
* @example
* import {bb} from "billboard.js";
- * import TextOverlap from "billboard.js/dist/billboardjs-plugin-textoverlap.esm";
+ * import TextOverlap from "billboard.js/dist/billboardjs-plugin-textoverlap";
*
* bb.generate({
* plugins: [
diff --git a/test/plugin/sparkline/sparkline-spec.ts b/test/plugin/sparkline/sparkline-spec.ts
new file mode 100644
index 000000000..7f9a378b8
--- /dev/null
+++ b/test/plugin/sparkline/sparkline-spec.ts
@@ -0,0 +1,86 @@
+/**
+ * Copyright (c) 2021 ~ present NAVER Corp.
+ * billboard.js project is licensed under the MIT license
+ */
+/* eslint-disable */
+import {expect} from "chai";
+import CLASS from "../../../src/config/classes";
+import Sparkline from "../../../src/Plugin/sparkline";
+import util from "../../assets/util";
+
+describe("PLUGIN: SPARKLINE", () => {
+ let chart;
+ const selector = ".sparkline";
+ const args = {
+ size: {
+ width: 150,
+ height: 50
+ },
+ data: {
+ columns: [
+ ["data1", 30, 20, 50],
+ ["data2", 200, 130, 90],
+ ["data3", 300, 200, 160]
+ ],
+ },
+ plugins: [
+ new Sparkline({
+ selector
+ })
+ ]
+ };
+ let body = document.body.innerHTML;
+
+ before(() => {
+ const div = document.createElement("div");
+
+ div.className = selector.replace(".", "");
+ document.body.append(div);
+ });
+
+ after(() => {
+ chart.destroy();
+ document.body.innerHTML = body;
+ });
+
+ beforeEach(() => {
+ chart = util.generate(args);
+ });
+
+ it("Sparkline generated correctly?", () => {
+ expect(document.body.querySelectorAll(selector).length).to.be.equal(chart.data().length);
+ });
+
+ it("check for tooltip interaction", () => {
+ const el = chart.plugins[0].element[0];
+ const {tooltip} = chart.$;
+ const svg = el.querySelector("svg");
+
+ // hover 1st chart element
+ util.fireEvent(svg, "mousemove", {
+ clientX: 10,
+ clientY: 10
+ }, chart);
+
+ expect(tooltip.style("display")).to.be.equal("block");
+
+ expect(tooltip.select("th").text()).to.be.equal("0");
+ expect(tooltip.select(".name").text()).to.be.equal("data1");
+ expect(tooltip.select(".value").text()).to.be.equal("30");
+
+ const circle = svg.querySelector(`.${CLASS.EXPANDED}`);
+
+ expect(circle).to.be.ok;
+ expect(circle.classList.contains(`${CLASS.circle}-0`)).to.be.true;
+
+ // when
+ util.fireEvent(svg, "mouseout", {
+ clientX: 10,
+ clientY: 10
+ }, chart);
+
+ expect(tooltip.style("display")).to.be.equal("none");
+
+ console.log(1);
+ })
+});
diff --git a/types/plugin/sparkline/index.d.ts b/types/plugin/sparkline/index.d.ts
new file mode 100644
index 000000000..f2f7f8dfe
--- /dev/null
+++ b/types/plugin/sparkline/index.d.ts
@@ -0,0 +1,28 @@
+/**
+ * Copyright (c) 2017 ~ present NAVER Corp.
+ * billboard.js project is licensed under the MIT license
+ */
+import {Plugin} from "../plugin";
+import {SparklineOptions} from "./options";
+
+export default class Sparkline extends Plugin {
+ /**
+ * Sparkline plugin.
+ * Generates sparkline charts
+ * - **NOTE:**
+ * - Plugins aren't built-in. Need to be loaded or imported to be used.
+ * - Non required modules from billboard.js core, need to be installed separately.
+ *
+ * - **Bear in mind:**
+ * - Use this plugin to visualize multiple tiny chart only and chart APIs won't work properly.
+ * - Sparkline chart size will be based on the main chart element size. To control spakrline charts, is highly recommended to set `size` option.
+ * - Bubble, scatter and Arc(pie, donut, ratdar) types aren't supported.
+ * - Some options will be stricted to be:
+ * - `resize.auto = false`
+ * - `axis.x.show = false`
+ * - `axis.y.show = false`
+ * - `axis.y.padding = 10`
+ * - `legend.show = false`
+ */
+ constructor(options: SparklineOptions);
+}
diff --git a/types/plugin/sparkline/options.d.ts b/types/plugin/sparkline/options.d.ts
new file mode 100644
index 000000000..849e20548
--- /dev/null
+++ b/types/plugin/sparkline/options.d.ts
@@ -0,0 +1,7 @@
+export interface SparklineOptions {
+ /**
+ * Specify sparkline charts holder selector.
+ * - **NOTE:** The amount of holder should match with the amount of data. If has less, will append necessaray amount nodes as sibling of main chart.
+ */
+ selector?: string;
+}