New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

chartjs-chart-treemap

Package Overview
Dependencies
Maintainers
1
Versions
27
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

chartjs-chart-treemap - npm Package Compare versions

Comparing version 2.0.2 to 2.1.0

910

dist/chartjs-chart-treemap.esm.js
/*!
* chartjs-chart-treemap v2.0.2
* chartjs-chart-treemap v2.1.0
* https://chartjs-chart-treemap.pages.dev/
* (c) 2021 Jukka Kurkela
* (c) 2022 Jukka Kurkela
* Released under the MIT license
*/
import { Chart, registry, DatasetController, Element } from 'chart.js';
import { toFont, valueOrDefault, isArray } from 'chart.js/helpers';
import { Element, Chart, registry, DatasetController } from 'chart.js';
import { isObject, addRoundedRectPath, toFont, isArray, toTRBL, toTRBLCorners, valueOrDefault, defined, clipArea, unclipArea } from 'chart.js/helpers';
const getValue = (item) => isObject(item) ? item.v : item;
const maxValue = (data) => data.reduce(function(m, v) {
return (m > getValue(v) ? m : getValue(v));
}, 0);
const minValue = (data, mx) => data.reduce(function(m, v) {
return (m < getValue(v) ? m : getValue(v));
}, mx);
const getGroupKey = (lvl) => '' + lvl;
function scanTreeObject(key, treeLeafKey, obj, tree = [], lvl = 0, result = []) {
const objIndex = lvl - 1;
if (key in obj && lvl > 0) {
const record = tree.reduce(function(reduced, item, i) {
if (i !== objIndex) {
reduced[getGroupKey(i)] = item;
}
return reduced;
}, {});
record[treeLeafKey] = tree[objIndex];
record[key] = obj[key];
result.push(record);
} else {
for (const childKey of Object.keys(obj)) {
const child = obj[childKey];
if (isObject(child)) {
tree.push(childKey);
scanTreeObject(key, treeLeafKey, child, tree, lvl + 1, result);
}
}
}
tree.splice(objIndex, 1);
return result;
}
function normalizeTreeToArray(key, treeLeafKey, obj) {
const data = scanTreeObject(key, treeLeafKey, obj);
if (!data.length) {
return data;
}
const max = data.reduce(function(maxVal, element) {
// minus 2 because _leaf and value properties are added
// on top to groups ones
const keys = Object.keys(element).length - 2;
return maxVal > keys ? maxVal : keys;
});
data.forEach(function(element) {
for (let i = 0; i < max; i++) {
const groupKey = getGroupKey(i);
if (!element[groupKey]) {
element[groupKey] = '';
}
}
});
return data;
}
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flat

@@ -28,2 +87,18 @@ function flatten(input) {

function getPath(groups, value, defaultValue) {
if (!groups.length) {
return;
}
const path = [];
for (const grp of groups) {
const item = value[grp];
if (item === '') {
path.push(defaultValue);
break;
}
path.push(item);
}
return path.length ? path.join('.') : defaultValue;
}
/**

@@ -33,21 +108,25 @@ * @param {[]} values

* @param {string} key
* @param {string} treeeLeafKey
* @param {string} [mainGrp]
* @param {*} [mainValue]
* @param {[]} groups
*/
function group(values, grp, key, mainGrp, mainValue) {
function group(values, grp, key, treeLeafKey, mainGrp, mainValue, groups = []) {
const tmp = Object.create(null);
const data = Object.create(null);
const ret = [];
let g, i, n, v;
let g, i, n;
for (i = 0, n = values.length; i < n; ++i) {
v = values[i];
const v = values[i];
if (mainGrp && v[mainGrp] !== mainValue) {
continue;
}
g = v[grp] || '';
g = v[grp] || v[treeLeafKey] || '';
if (!(g in tmp)) {
tmp[g] = 0;
tmp[g] = {value: 0};
data[g] = [];
}
tmp[g] += +v[key];
tmp[g].value += +v[key];
tmp[g].label = v[grp] || '';
tmp[g].path = getPath(groups, v, g);
data[g].push(v);

@@ -57,5 +136,8 @@ }

Object.keys(tmp).forEach((k) => {
v = {children: data[k]};
v[key] = +tmp[k];
v[grp] = k;
const v = {children: data[k]};
v[key] = +tmp[k].value;
v[grp] = tmp[k].label;
v.label = k;
v.path = tmp[k].path;
if (mainGrp) {

@@ -70,7 +152,2 @@ v[mainGrp] = mainValue;

function isObject(obj) {
const type = typeof obj;
return type === 'function' || type === 'object' && !!obj;
}
function index(values, key) {

@@ -122,2 +199,383 @@ let n = values.length;

const widthCache = new Map();
/**
* Helper function to get the bounds of the rect
* @param {TreemapElement} rect the rect
* @param {boolean} [useFinalPosition]
* @return {object} bounds of the rect
* @private
*/
function getBounds(rect, useFinalPosition) {
const {x, y, width, height} = rect.getProps(['x', 'y', 'width', 'height'], useFinalPosition);
return {left: x, top: y, right: x + width, bottom: y + height};
}
function limit(value, min, max) {
return Math.max(Math.min(value, max), min);
}
function parseBorderWidth(value, maxW, maxH) {
const o = toTRBL(value);
return {
t: limit(o.top, 0, maxH),
r: limit(o.right, 0, maxW),
b: limit(o.bottom, 0, maxH),
l: limit(o.left, 0, maxW)
};
}
function parseBorderRadius(value, maxW, maxH) {
const o = toTRBLCorners(value);
const maxR = Math.min(maxW, maxH);
return {
topLeft: limit(o.topLeft, 0, maxR),
topRight: limit(o.topRight, 0, maxR),
bottomLeft: limit(o.bottomLeft, 0, maxR),
bottomRight: limit(o.bottomRight, 0, maxR)
};
}
function boundingRects(rect) {
const bounds = getBounds(rect);
const width = bounds.right - bounds.left;
const height = bounds.bottom - bounds.top;
const border = parseBorderWidth(rect.options.borderWidth, width / 2, height / 2);
const radius = parseBorderRadius(rect.options.borderRadius, width / 2, height / 2);
return {
outer: {
x: bounds.left,
y: bounds.top,
w: width,
h: height,
radius
},
inner: {
x: bounds.left + border.l,
y: bounds.top + border.t,
w: width - border.l - border.r,
h: height - border.t - border.b,
radius: {
topLeft: Math.max(0, radius.topLeft - Math.max(border.t, border.l)),
topRight: Math.max(0, radius.topRight - Math.max(border.t, border.r)),
bottomLeft: Math.max(0, radius.bottomLeft - Math.max(border.b, border.l)),
bottomRight: Math.max(0, radius.bottomRight - Math.max(border.b, border.r)),
}
}
};
}
function inRange(rect, x, y, useFinalPosition) {
const skipX = x === null;
const skipY = y === null;
const bounds = !rect || (skipX && skipY) ? false : getBounds(rect, useFinalPosition);
return bounds
&& (skipX || x >= bounds.left && x <= bounds.right)
&& (skipY || y >= bounds.top && y <= bounds.bottom);
}
function hasRadius(radius) {
return radius.topLeft || radius.topRight || radius.bottomLeft || radius.bottomRight;
}
/**
* Add a path of a rectangle to the current sub-path
* @param {CanvasRenderingContext2D} ctx Context
* @param {*} rect Bounding rect
*/
function addNormalRectPath(ctx, rect) {
ctx.rect(rect.x, rect.y, rect.w, rect.h);
}
function shouldDrawCaption(rect, options) {
if (!options || !options.display) {
return false;
}
const {w, h} = rect;
const font = toFont(options.font);
const min = font.lineHeight;
const padding = limit(valueOrDefault(options.padding, 3) * 2, 0, Math.min(w, h));
return (w - padding) > min && (h - padding) > min;
}
function drawText(ctx, rect, options, item, levels) {
const {captions, labels} = options;
ctx.save();
ctx.beginPath();
ctx.rect(rect.x, rect.y, rect.w, rect.h);
ctx.clip();
const isLeaf = (!('l' in item) || item.l === levels);
if (isLeaf && labels.display) {
drawLabel(ctx, rect, options);
} else if (!isLeaf && shouldDrawCaption(rect, captions)) {
drawCaption(ctx, rect, options, item);
}
ctx.restore();
}
function drawCaption(ctx, rect, options, item) {
const {captions, spacing, rtl} = options;
const {color, hoverColor, font, hoverFont, padding, align, formatter} = captions;
const oColor = (rect.active ? hoverColor : color) || color;
const oAlign = align || (rtl ? 'right' : 'left');
const optFont = (rect.active ? hoverFont : font) || font;
const oFont = toFont(optFont);
const lh = oFont.lineHeight / 2;
const x = calculateX(rect, oAlign, padding);
ctx.fillStyle = oColor;
ctx.font = oFont.string;
ctx.textAlign = oAlign;
ctx.textBaseline = 'middle';
ctx.fillText(formatter || item.g, x, rect.y + padding + spacing + lh);
}
function measureLabelSize(ctx, lines, fonts) {
const fontsKey = fonts.reduce(function(prev, item) {
prev += item.string;
return prev;
}, '');
const mapKey = lines.join() + fontsKey + (ctx._measureText ? '-spriting' : '');
if (!widthCache.has(mapKey)) {
ctx.save();
const count = lines.length;
let width = 0;
let height = 0;
for (let i = 0; i < count; i++) {
const font = fonts[Math.min(i, fonts.length - 1)];
ctx.font = font.string;
const text = lines[i];
width = Math.max(width, ctx.measureText(text).width);
height += font.lineHeight;
}
ctx.restore();
widthCache.set(mapKey, {width, height});
}
return widthCache.get(mapKey);
}
function labelToDraw(ctx, rect, options, labelSize) {
const {overflow, padding} = options;
const {width, height} = labelSize;
if (overflow === 'hidden') {
return !((width + padding * 2) > rect.w || (height + padding * 2) > rect.h);
}
return true;
}
function drawLabel(ctx, rect, options) {
const labels = options.labels;
const content = labels.formatter;
if (!content) {
return;
}
const contents = isArray(content) ? content : [content];
const {font, hoverFont} = labels;
const optFont = (rect.active ? hoverFont : font) || font;
const fonts = isArray(optFont) ? optFont.map(f => toFont(f)) : [toFont(optFont)];
const labelSize = measureLabelSize(ctx, contents, fonts);
if (!labelToDraw(ctx, rect, labels, labelSize)) {
return;
}
const {color, hoverColor, align} = labels;
const optColor = (rect.active ? hoverColor : color) || color;
const colors = isArray(optColor) ? optColor : [optColor];
const xyPoint = calculateXYLabel(rect, labels, labelSize);
ctx.textAlign = align;
ctx.textBaseline = 'middle';
let lhs = 0;
contents.forEach(function(l, i) {
const c = colors[Math.min(i, colors.length - 1)];
const f = fonts[Math.min(i, fonts.length - 1)];
const lh = f.lineHeight;
ctx.font = f.string;
ctx.fillStyle = c;
ctx.fillText(l, xyPoint.x, xyPoint.y + lh / 2 + lhs);
lhs += lh;
});
}
function drawDivider(ctx, rect, options, item) {
const dividers = options.dividers;
if (!dividers.display || !item._data.children.length) {
return;
}
const {x, y, w, h} = rect;
const {lineColor, lineCapStyle, lineDash, lineDashOffset, lineWidth} = dividers;
ctx.save();
ctx.strokeStyle = lineColor;
ctx.lineCap = lineCapStyle;
ctx.setLineDash(lineDash);
ctx.lineDashOffset = lineDashOffset;
ctx.lineWidth = lineWidth;
ctx.beginPath();
if (w > h) {
const w2 = w / 2;
ctx.moveTo(x + w2, y);
ctx.lineTo(x + w2, y + h);
} else {
const h2 = h / 2;
ctx.moveTo(x, y + h2);
ctx.lineTo(x + w, y + h2);
}
ctx.stroke();
ctx.restore();
}
function calculateXYLabel(rect, options, labelSize) {
const {align, position, padding} = options;
let x, y;
x = calculateX(rect, align, padding);
if (position === 'top') {
y = rect.y + padding;
} else if (position === 'bottom') {
y = rect.y + rect.h - padding - labelSize.height;
} else {
y = rect.y + (rect.h - labelSize.height) / 2 + padding;
}
return {x, y};
}
function calculateX(rect, align, padding) {
if (align === 'left') {
return rect.x + padding;
} else if (align === 'right') {
return rect.x + rect.w - padding;
}
return rect.x + rect.w / 2;
}
class TreemapElement extends Element {
constructor(cfg) {
super();
this.options = undefined;
this.width = undefined;
this.height = undefined;
if (cfg) {
Object.assign(this, cfg);
}
}
draw(ctx, data, levels = 0) {
if (!data) {
return;
}
const options = this.options;
const {inner, outer} = boundingRects(this);
const addRectPath = hasRadius(outer.radius) ? addRoundedRectPath : addNormalRectPath;
ctx.save();
if (outer.w !== inner.w || outer.h !== inner.h) {
ctx.beginPath();
addRectPath(ctx, outer);
ctx.clip();
addRectPath(ctx, inner);
ctx.fillStyle = options.borderColor;
ctx.fill('evenodd');
}
ctx.beginPath();
addRectPath(ctx, inner);
ctx.fillStyle = options.backgroundColor;
ctx.fill();
drawDivider(ctx, inner, options, data);
drawText(ctx, inner, options, data, levels);
ctx.restore();
}
inRange(mouseX, mouseY, useFinalPosition) {
return inRange(this, mouseX, mouseY, useFinalPosition);
}
inXRange(mouseX, useFinalPosition) {
return inRange(this, mouseX, null, useFinalPosition);
}
inYRange(mouseY, useFinalPosition) {
return inRange(this, null, mouseY, useFinalPosition);
}
getCenterPoint(useFinalPosition) {
const {x, y, width, height} = this.getProps(['x', 'y', 'width', 'height'], useFinalPosition);
return {
x: x + width / 2,
y: y + height / 2
};
}
tooltipPosition() {
return this.getCenterPoint();
}
getRange(axis) {
return axis === 'x' ? this.width / 2 : this.height / 2;
}
}
TreemapElement.id = 'treemap';
TreemapElement.defaults = {
label: undefined,
borderRadius: 0,
borderWidth: 0,
captions: {
align: undefined,
color: 'black',
display: true,
font: {},
formatter: (ctx) => ctx.raw.g || ctx.raw._data.label || '',
padding: 3
},
dividers: {
display: false,
lineCapStyle: 'butt',
lineColor: 'black',
lineDash: [],
lineDashOffset: 0,
lineWidth: 1,
},
labels: {
align: 'center',
color: 'black',
display: false,
font: {},
formatter(ctx) {
if (ctx.raw.g) {
return [ctx.raw.g, ctx.raw.v + ''];
}
return ctx.raw._data.label ? [ctx.raw._data.label, ctx.raw.v + ''] : ctx.raw.v + '';
},
overflow: 'cut',
position: 'middle',
padding: 3
},
rtl: false,
spacing: 0.5
};
TreemapElement.descriptors = {
labels: {
_fallback: true
},
captions: {
_fallback: true
},
_scriptable: true,
_indexable: false
};
TreemapElement.defaultRoutes = {
backgroundColor: 'backgroundColor',
borderColor: 'borderColor'
};
function round(v, n) {

@@ -361,3 +819,3 @@ // @ts-ignore

var version = "2.0.2";
var version = "2.1.0";

@@ -387,83 +845,20 @@ function rectNotEqual(r1, r2) {

function shouldDrawCaption(rect, font) {
if (!font) {
return false;
}
const w = rect.width || rect.w;
const h = rect.height || rect.h;
const min = font.lineHeight * 2;
return w > min && h > min;
}
function drawCaption(ctx, rect, item, opts, levels) {
ctx.save();
ctx.beginPath();
ctx.rect(rect.x, rect.y, rect.width, rect.height);
ctx.clip();
if (!('l' in item) || item.l === levels) {
drawLabels(ctx, item, rect);
} else if (opts.captions && opts.captions.display) {
drawCaptionLabel(ctx, item, rect);
}
ctx.restore();
}
function drawCaptionLabel(ctx, item, rect) {
const opts = rect.options;
const captionsOpts = opts.captions || {};
const borderWidth = opts.borderWidth || 0;
const spacing = valueOrDefault(opts.spacing, 0) + borderWidth;
const color = (rect.active ? captionsOpts.hoverColor : captionsOpts.color) || captionsOpts.color;
const padding = captionsOpts.padding;
const align = captionsOpts.align || (opts.rtl ? 'right' : 'left');
const optFont = (rect.active ? captionsOpts.hoverFont : captionsOpts.font) || captionsOpts.font;
const font = toFont(optFont);
const x = calculateX(rect, align, padding, borderWidth);
ctx.fillStyle = color;
ctx.font = font.string;
ctx.textAlign = align;
ctx.textBaseline = 'middle';
ctx.fillText(captionsOpts.formatter || item.g, x, rect.y + padding + spacing + (font.lineHeight / 2));
}
function drawDivider(ctx, rect) {
const opts = rect.options;
const dividersOpts = opts.dividers || {};
const w = rect.width || rect.w;
const h = rect.height || rect.h;
ctx.save();
ctx.strokeStyle = dividersOpts.lineColor || 'black';
ctx.lineCap = dividersOpts.lineCapStyle;
ctx.setLineDash(dividersOpts.lineDash || []);
ctx.lineDashOffset = dividersOpts.lineDashOffset;
ctx.lineWidth = dividersOpts.lineWidth;
ctx.beginPath();
if (w > h) {
const w2 = w / 2;
ctx.moveTo(rect.x + w2, rect.y);
ctx.lineTo(rect.x + w2, rect.y + h);
} else {
const h2 = h / 2;
ctx.moveTo(rect.x, rect.y + h2);
ctx.lineTo(rect.x + w, rect.y + h2);
}
ctx.stroke();
ctx.restore();
}
function buildData(dataset, mainRect, captions) {
function buildData(dataset, mainRect) {
const key = dataset.key || '';
const treeLeafKey = dataset.treeLeafKey || '_leaf';
let tree = dataset.tree || [];
if (isObject(tree)) {
tree = normalizeTreeToArray(key, treeLeafKey, tree);
}
const groups = dataset.groups || [];
const glen = groups.length;
const sp = valueOrDefault(dataset.spacing, 0) + valueOrDefault(dataset.borderWidth, 0);
const captionsFont = captions.font || {};
const font = toFont(captionsFont);
const sp = valueOrDefault(dataset.spacing, 0);
const captions = dataset.captions || {display: true};
const font = toFont(captions.font);
const padding = valueOrDefault(captions.padding, 3);
function recur(gidx, rect, parent, gs) {
const g = groups[gidx];
const pg = (gidx > 0) && groups[gidx - 1];
const gdata = group(tree, g, key, pg, parent);
const g = getGroupKey(groups[gidx]);
const pg = (gidx > 0) && getGroupKey(groups[gidx - 1]);
const gdata = group(tree, g, key, treeLeafKey, pg, parent, groups.filter((item, index) => index <= gidx));
const gsq = squarify(gdata, rect, key, g, gidx, gs);

@@ -474,4 +869,11 @@ const ret = gsq.slice();

gsq.forEach((sq) => {
subRect = {x: sq.x + sp, y: sq.y + sp, w: sq.w - 2 * sp, h: sq.h - 2 * sp};
if (valueOrDefault(captions.display, true) && shouldDrawCaption(sq, font)) {
const bw = parseBorderWidth(dataset.borderWidth, sq.w / 2, sq.h / 2);
subRect = {
x: sq.x + sp + bw.l,
y: sq.y + sp + bw.t,
w: sq.w - 2 * sp - bw.l - bw.r,
h: sq.h - 2 * sp - bw.t - bw.b,
rtl: rect.rtl
};
if (shouldDrawCaption(subRect, captions)) {
subRect.y += font.lineHeight + padding * 2;

@@ -495,49 +897,17 @@ subRect.h -= font.lineHeight + padding * 2;

function drawLabels(ctx, item, rect) {
const opts = rect.options;
const labelsOpts = opts.labels;
if (!labelsOpts || !labelsOpts.display) {
return;
}
const optColor = (rect.active ? labelsOpts.hoverColor : labelsOpts.color) || labelsOpts.color;
const optFont = (rect.active ? labelsOpts.hoverFont : labelsOpts.font) || labelsOpts.font;
const font = toFont(optFont);
const lh = font.lineHeight;
const label = labelsOpts.formatter;
if (label) {
const labels = isArray(label) ? label : [label];
const xyPoint = calculateXYLabel(opts, rect, labels, lh);
ctx.font = font.string;
ctx.textAlign = labelsOpts.align;
ctx.textBaseline = labelsOpts.position;
ctx.fillStyle = optColor;
labels.forEach((l, i) => ctx.fillText(l, xyPoint.x, xyPoint.y + i * lh));
}
function getMinMax(data, useTree) {
const vMax = useTree ? 1 : maxValue(data);
const vMin = useTree ? 0 : minValue(data, vMax);
return {vMin, vMax};
}
function calculateXYLabel(options, rect, labels, lineHeight) {
const labelsOpts = options.labels;
const borderWidth = options.borderWidth || 0;
const {align, position, padding} = labelsOpts;
let x, y;
x = calculateX(rect, align, padding, borderWidth);
if (position === 'top') {
y = rect.y + padding + borderWidth;
} else if (position === 'bottom') {
y = rect.y + rect.height - padding - borderWidth - (labels.length - 1) * lineHeight;
} else {
y = rect.y + rect.height / 2 - labels.length * lineHeight / 4;
}
return {x, y};
function getArea({xScale, yScale}, data, rtl, useTree) {
const {vMin, vMax} = getMinMax(data, useTree);
const xMin = xScale.getPixelForValue(0);
const xMax = xScale.getPixelForValue(1);
const yMin = yScale.getPixelForValue(vMin);
const yMax = yScale.getPixelForValue(vMax);
return {x: xMin, y: yMax, w: xMax - xMin, h: yMin - yMax, rtl};
}
function calculateX(rect, align, padding, borderWidth) {
if (align === 'left') {
return rect.x + padding + borderWidth;
} else if (align === 'right') {
return rect.x + rect.width - padding - borderWidth;
}
return rect.x + rect.width / 2;
}
class TreemapController extends DatasetController {

@@ -550,2 +920,3 @@ constructor(chart, datasetIndex) {

this._groups = undefined;
this._useTree = undefined;
}

@@ -558,2 +929,23 @@

/**
* TODO: to be removed when https://github.com/kurkle/chartjs-chart-treemap/issues/137
* will be implemented
*/
updateRangeFromParsed(range, scale) {
if (range.updated) {
return;
}
range.updated = true;
if (scale.axis === 'x') {
range.min = 0;
range.max = 1;
return;
}
const me = this;
const dataset = me.getDataset();
const {vMin, vMax} = getMinMax(dataset.data, me._useTree);
range.min = vMin;
range.max = vMax;
}
update(mode) {

@@ -563,9 +955,10 @@ const me = this;

const dataset = me.getDataset();
if (!defined(me._useTree)) {
me._useTree = !!dataset.tree;
}
const groups = dataset.groups || (dataset.groups = []);
const captions = dataset.captions ? dataset.captions : {};
const area = me.chart.chartArea;
const key = dataset.key || '';
const rtl = !!dataset.rtl;
const mainRect = {x: area.left, y: area.top, w: area.right - area.left, h: area.bottom - area.top, rtl};
const mainRect = getArea(meta, dataset.data, rtl, me._useTree);

@@ -577,3 +970,3 @@ if (mode === 'reset' || rectNotEqual(me._rect, mainRect) || me._key !== key || arrayNotEqual(me._groups, groups)) {

dataset.data = buildData(dataset, mainRect, captions);
dataset.data = buildData(dataset, mainRect);
// @ts-ignore using private stuff

@@ -588,9 +981,2 @@ me._dataCheck();

resolveDataElementOptions(index, mode) {
const options = super.resolveDataElementOptions(index, mode);
const result = Object.isFrozen(options) ? Object.assign({}, options) : options;
result.font = toFont(options.captions.font);
return result;
}
updateElements(rects, start, count, mode) {

@@ -626,37 +1012,19 @@ const me = this;

_drawDividers(ctx, data, metadata) {
for (let i = 0, ilen = metadata.length; i < ilen; ++i) {
const rect = metadata[i];
const item = data[i];
const dividersOpts = rect.options.dividers || {};
if (dividersOpts.display && item._data.children.length > 1) {
drawDivider(ctx, rect);
}
}
}
_drawRects(ctx, data, metadata, levels) {
for (let i = 0, ilen = metadata.length; i < ilen; ++i) {
const rect = metadata[i];
const item = data[i];
if (!rect.hidden) {
rect.draw(ctx);
const opts = rect.options;
if (shouldDrawCaption(rect, opts.captions.font)) {
drawCaption(ctx, rect, item, opts, levels);
}
}
}
}
draw() {
const me = this;
const ctx = me.chart.ctx;
const area = me.chart.chartArea;
const metadata = me.getMeta().data || [];
const dataset = me.getDataset();
const levels = (dataset.groups || []).length - 1;
const data = dataset.data || [];
const data = dataset.data;
me._drawRects(ctx, data, metadata, levels);
me._drawDividers(ctx, data, metadata);
clipArea(ctx, area);
for (let i = 0, ilen = metadata.length; i < ilen; ++i) {
const rect = metadata[i];
if (!rect.hidden) {
rect.draw(ctx, data[i], levels);
}
}
unclipArea(ctx);
}

@@ -679,9 +1047,2 @@ }

borderWidth: 0,
spacing: 0.5,
dividers: {
display: false,
lineWidth: 1,
}
};

@@ -717,3 +1078,3 @@

const dataItem = dataset.data[item.dataIndex];
const label = dataItem.g || dataset.label;
const label = dataItem.g || dataItem._data.label || dataset.label;
return (label ? label + ': ' : '') + dataItem.v;

@@ -753,2 +1114,4 @@ }

};
} else {
console.warn('Unable to register the treemap positioner because tooltip plugin is not registered');
}

@@ -764,179 +1127,2 @@ };

/**
* Helper function to get the bounds of the rect
* @param {TreemapElement} rect the rect
* @param {boolean} [useFinalPosition]
* @return {object} bounds of the rect
* @private
*/
function getBounds(rect, useFinalPosition) {
const {x, y, width, height} = rect.getProps(['x', 'y', 'width', 'height'], useFinalPosition);
return {left: x, top: y, right: x + width, bottom: y + height};
}
function limit(value, min, max) {
return Math.max(Math.min(value, max), min);
}
function parseBorderWidth(value, maxW, maxH) {
let t, r, b, l;
if (isObject(value)) {
t = +value.top || 0;
r = +value.right || 0;
b = +value.bottom || 0;
l = +value.left || 0;
} else {
t = r = b = l = +value || 0;
}
return {
t: limit(t, 0, maxH),
r: limit(r, 0, maxW),
b: limit(b, 0, maxH),
l: limit(l, 0, maxW)
};
}
function boundingRects(rect) {
const bounds = getBounds(rect);
const width = bounds.right - bounds.left;
const height = bounds.bottom - bounds.top;
const border = parseBorderWidth(rect.options.borderWidth, width / 2, height / 2);
return {
outer: {
x: bounds.left,
y: bounds.top,
w: width,
h: height
},
inner: {
x: bounds.left + border.l,
y: bounds.top + border.t,
w: width - border.l - border.r,
h: height - border.t - border.b
}
};
}
function inRange(rect, x, y, useFinalPosition) {
const skipX = x === null;
const skipY = y === null;
const bounds = !rect || (skipX && skipY) ? false : getBounds(rect, useFinalPosition);
return bounds
&& (skipX || x >= bounds.left && x <= bounds.right)
&& (skipY || y >= bounds.top && y <= bounds.bottom);
}
class TreemapElement extends Element {
constructor(cfg) {
super();
this.options = undefined;
this.width = undefined;
this.height = undefined;
if (cfg) {
Object.assign(this, cfg);
}
}
draw(ctx) {
const options = this.options;
const {inner, outer} = boundingRects(this);
ctx.save();
if (outer.w !== inner.w || outer.h !== inner.h) {
ctx.beginPath();
ctx.rect(outer.x, outer.y, outer.w, outer.h);
ctx.clip();
ctx.rect(inner.x, inner.y, inner.w, inner.h);
ctx.fillStyle = options.backgroundColor;
ctx.fill();
ctx.fillStyle = options.borderColor;
ctx.fill('evenodd');
} else {
ctx.fillStyle = options.backgroundColor;
ctx.fillRect(inner.x, inner.y, inner.w, inner.h);
}
ctx.restore();
}
inRange(mouseX, mouseY, useFinalPosition) {
return inRange(this, mouseX, mouseY, useFinalPosition);
}
inXRange(mouseX, useFinalPosition) {
return inRange(this, mouseX, null, useFinalPosition);
}
inYRange(mouseY, useFinalPosition) {
return inRange(this, null, mouseY, useFinalPosition);
}
getCenterPoint(useFinalPosition) {
const {x, y, width, height} = this.getProps(['x', 'y', 'width', 'height'], useFinalPosition);
return {
x: x + width / 2,
y: y + height / 2
};
}
tooltipPosition() {
return this.getCenterPoint();
}
getRange(axis) {
return axis === 'x' ? this.width / 2 : this.height / 2;
}
}
TreemapElement.id = 'treemap';
TreemapElement.defaults = {
borderWidth: undefined,
spacing: undefined,
label: undefined,
rtl: undefined,
dividers: {
display: false,
lineCapStyle: 'butt',
lineColor: 'black',
lineDash: undefined,
lineDashOffset: 0,
lineWidth: 0,
},
captions: {
align: undefined,
color: undefined,
display: true,
formatter: (ctx) => ctx.raw.g || '',
font: {},
padding: 3
},
labels: {
align: 'center',
color: undefined,
display: false,
formatter: (ctx) => ctx.raw.g ? [ctx.raw.g, ctx.raw.v] : ctx.raw.v,
font: {},
position: 'middle',
padding: 3
}
};
TreemapElement.descriptors = {
_scriptable: true,
_indexable: false
};
TreemapElement.defaultRoutes = {
backgroundColor: 'backgroundColor',
borderColor: 'borderColor'
};
export { TreemapController, TreemapElement };
/*!
* chartjs-chart-treemap v2.0.2
* chartjs-chart-treemap v2.1.0
* https://chartjs-chart-treemap.pages.dev/
* (c) 2021 Jukka Kurkela
* (c) 2022 Jukka Kurkela
* Released under the MIT license

@@ -13,2 +13,61 @@ */

const getValue = (item) => helpers.isObject(item) ? item.v : item;
const maxValue = (data) => data.reduce(function(m, v) {
return (m > getValue(v) ? m : getValue(v));
}, 0);
const minValue = (data, mx) => data.reduce(function(m, v) {
return (m < getValue(v) ? m : getValue(v));
}, mx);
const getGroupKey = (lvl) => '' + lvl;
function scanTreeObject(key, treeLeafKey, obj, tree = [], lvl = 0, result = []) {
const objIndex = lvl - 1;
if (key in obj && lvl > 0) {
const record = tree.reduce(function(reduced, item, i) {
if (i !== objIndex) {
reduced[getGroupKey(i)] = item;
}
return reduced;
}, {});
record[treeLeafKey] = tree[objIndex];
record[key] = obj[key];
result.push(record);
} else {
for (const childKey of Object.keys(obj)) {
const child = obj[childKey];
if (helpers.isObject(child)) {
tree.push(childKey);
scanTreeObject(key, treeLeafKey, child, tree, lvl + 1, result);
}
}
}
tree.splice(objIndex, 1);
return result;
}
function normalizeTreeToArray(key, treeLeafKey, obj) {
const data = scanTreeObject(key, treeLeafKey, obj);
if (!data.length) {
return data;
}
const max = data.reduce(function(maxVal, element) {
// minus 2 because _leaf and value properties are added
// on top to groups ones
const keys = Object.keys(element).length - 2;
return maxVal > keys ? maxVal : keys;
});
data.forEach(function(element) {
for (let i = 0; i < max; i++) {
const groupKey = getGroupKey(i);
if (!element[groupKey]) {
element[groupKey] = '';
}
}
});
return data;
}
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flat

@@ -32,2 +91,18 @@ function flatten(input) {

function getPath(groups, value, defaultValue) {
if (!groups.length) {
return;
}
const path = [];
for (const grp of groups) {
const item = value[grp];
if (item === '') {
path.push(defaultValue);
break;
}
path.push(item);
}
return path.length ? path.join('.') : defaultValue;
}
/**

@@ -37,21 +112,25 @@ * @param {[]} values

* @param {string} key
* @param {string} treeeLeafKey
* @param {string} [mainGrp]
* @param {*} [mainValue]
* @param {[]} groups
*/
function group(values, grp, key, mainGrp, mainValue) {
function group(values, grp, key, treeLeafKey, mainGrp, mainValue, groups = []) {
const tmp = Object.create(null);
const data = Object.create(null);
const ret = [];
let g, i, n, v;
let g, i, n;
for (i = 0, n = values.length; i < n; ++i) {
v = values[i];
const v = values[i];
if (mainGrp && v[mainGrp] !== mainValue) {
continue;
}
g = v[grp] || '';
g = v[grp] || v[treeLeafKey] || '';
if (!(g in tmp)) {
tmp[g] = 0;
tmp[g] = {value: 0};
data[g] = [];
}
tmp[g] += +v[key];
tmp[g].value += +v[key];
tmp[g].label = v[grp] || '';
tmp[g].path = getPath(groups, v, g);
data[g].push(v);

@@ -61,5 +140,8 @@ }

Object.keys(tmp).forEach((k) => {
v = {children: data[k]};
v[key] = +tmp[k];
v[grp] = k;
const v = {children: data[k]};
v[key] = +tmp[k].value;
v[grp] = tmp[k].label;
v.label = k;
v.path = tmp[k].path;
if (mainGrp) {

@@ -74,7 +156,2 @@ v[mainGrp] = mainValue;

function isObject(obj) {
const type = typeof obj;
return type === 'function' || type === 'object' && !!obj;
}
function index(values, key) {

@@ -88,3 +165,3 @@ let n = values.length;

const obj = isObject(values[0]);
const obj = helpers.isObject(values[0]);
key = obj ? key : 'v';

@@ -127,2 +204,383 @@

const widthCache = new Map();
/**
* Helper function to get the bounds of the rect
* @param {TreemapElement} rect the rect
* @param {boolean} [useFinalPosition]
* @return {object} bounds of the rect
* @private
*/
function getBounds(rect, useFinalPosition) {
const {x, y, width, height} = rect.getProps(['x', 'y', 'width', 'height'], useFinalPosition);
return {left: x, top: y, right: x + width, bottom: y + height};
}
function limit(value, min, max) {
return Math.max(Math.min(value, max), min);
}
function parseBorderWidth(value, maxW, maxH) {
const o = helpers.toTRBL(value);
return {
t: limit(o.top, 0, maxH),
r: limit(o.right, 0, maxW),
b: limit(o.bottom, 0, maxH),
l: limit(o.left, 0, maxW)
};
}
function parseBorderRadius(value, maxW, maxH) {
const o = helpers.toTRBLCorners(value);
const maxR = Math.min(maxW, maxH);
return {
topLeft: limit(o.topLeft, 0, maxR),
topRight: limit(o.topRight, 0, maxR),
bottomLeft: limit(o.bottomLeft, 0, maxR),
bottomRight: limit(o.bottomRight, 0, maxR)
};
}
function boundingRects(rect) {
const bounds = getBounds(rect);
const width = bounds.right - bounds.left;
const height = bounds.bottom - bounds.top;
const border = parseBorderWidth(rect.options.borderWidth, width / 2, height / 2);
const radius = parseBorderRadius(rect.options.borderRadius, width / 2, height / 2);
return {
outer: {
x: bounds.left,
y: bounds.top,
w: width,
h: height,
radius
},
inner: {
x: bounds.left + border.l,
y: bounds.top + border.t,
w: width - border.l - border.r,
h: height - border.t - border.b,
radius: {
topLeft: Math.max(0, radius.topLeft - Math.max(border.t, border.l)),
topRight: Math.max(0, radius.topRight - Math.max(border.t, border.r)),
bottomLeft: Math.max(0, radius.bottomLeft - Math.max(border.b, border.l)),
bottomRight: Math.max(0, radius.bottomRight - Math.max(border.b, border.r)),
}
}
};
}
function inRange(rect, x, y, useFinalPosition) {
const skipX = x === null;
const skipY = y === null;
const bounds = !rect || (skipX && skipY) ? false : getBounds(rect, useFinalPosition);
return bounds
&& (skipX || x >= bounds.left && x <= bounds.right)
&& (skipY || y >= bounds.top && y <= bounds.bottom);
}
function hasRadius(radius) {
return radius.topLeft || radius.topRight || radius.bottomLeft || radius.bottomRight;
}
/**
* Add a path of a rectangle to the current sub-path
* @param {CanvasRenderingContext2D} ctx Context
* @param {*} rect Bounding rect
*/
function addNormalRectPath(ctx, rect) {
ctx.rect(rect.x, rect.y, rect.w, rect.h);
}
function shouldDrawCaption(rect, options) {
if (!options || !options.display) {
return false;
}
const {w, h} = rect;
const font = helpers.toFont(options.font);
const min = font.lineHeight;
const padding = limit(helpers.valueOrDefault(options.padding, 3) * 2, 0, Math.min(w, h));
return (w - padding) > min && (h - padding) > min;
}
function drawText(ctx, rect, options, item, levels) {
const {captions, labels} = options;
ctx.save();
ctx.beginPath();
ctx.rect(rect.x, rect.y, rect.w, rect.h);
ctx.clip();
const isLeaf = (!('l' in item) || item.l === levels);
if (isLeaf && labels.display) {
drawLabel(ctx, rect, options);
} else if (!isLeaf && shouldDrawCaption(rect, captions)) {
drawCaption(ctx, rect, options, item);
}
ctx.restore();
}
function drawCaption(ctx, rect, options, item) {
const {captions, spacing, rtl} = options;
const {color, hoverColor, font, hoverFont, padding, align, formatter} = captions;
const oColor = (rect.active ? hoverColor : color) || color;
const oAlign = align || (rtl ? 'right' : 'left');
const optFont = (rect.active ? hoverFont : font) || font;
const oFont = helpers.toFont(optFont);
const lh = oFont.lineHeight / 2;
const x = calculateX(rect, oAlign, padding);
ctx.fillStyle = oColor;
ctx.font = oFont.string;
ctx.textAlign = oAlign;
ctx.textBaseline = 'middle';
ctx.fillText(formatter || item.g, x, rect.y + padding + spacing + lh);
}
function measureLabelSize(ctx, lines, fonts) {
const fontsKey = fonts.reduce(function(prev, item) {
prev += item.string;
return prev;
}, '');
const mapKey = lines.join() + fontsKey + (ctx._measureText ? '-spriting' : '');
if (!widthCache.has(mapKey)) {
ctx.save();
const count = lines.length;
let width = 0;
let height = 0;
for (let i = 0; i < count; i++) {
const font = fonts[Math.min(i, fonts.length - 1)];
ctx.font = font.string;
const text = lines[i];
width = Math.max(width, ctx.measureText(text).width);
height += font.lineHeight;
}
ctx.restore();
widthCache.set(mapKey, {width, height});
}
return widthCache.get(mapKey);
}
function labelToDraw(ctx, rect, options, labelSize) {
const {overflow, padding} = options;
const {width, height} = labelSize;
if (overflow === 'hidden') {
return !((width + padding * 2) > rect.w || (height + padding * 2) > rect.h);
}
return true;
}
function drawLabel(ctx, rect, options) {
const labels = options.labels;
const content = labels.formatter;
if (!content) {
return;
}
const contents = helpers.isArray(content) ? content : [content];
const {font, hoverFont} = labels;
const optFont = (rect.active ? hoverFont : font) || font;
const fonts = helpers.isArray(optFont) ? optFont.map(f => helpers.toFont(f)) : [helpers.toFont(optFont)];
const labelSize = measureLabelSize(ctx, contents, fonts);
if (!labelToDraw(ctx, rect, labels, labelSize)) {
return;
}
const {color, hoverColor, align} = labels;
const optColor = (rect.active ? hoverColor : color) || color;
const colors = helpers.isArray(optColor) ? optColor : [optColor];
const xyPoint = calculateXYLabel(rect, labels, labelSize);
ctx.textAlign = align;
ctx.textBaseline = 'middle';
let lhs = 0;
contents.forEach(function(l, i) {
const c = colors[Math.min(i, colors.length - 1)];
const f = fonts[Math.min(i, fonts.length - 1)];
const lh = f.lineHeight;
ctx.font = f.string;
ctx.fillStyle = c;
ctx.fillText(l, xyPoint.x, xyPoint.y + lh / 2 + lhs);
lhs += lh;
});
}
function drawDivider(ctx, rect, options, item) {
const dividers = options.dividers;
if (!dividers.display || !item._data.children.length) {
return;
}
const {x, y, w, h} = rect;
const {lineColor, lineCapStyle, lineDash, lineDashOffset, lineWidth} = dividers;
ctx.save();
ctx.strokeStyle = lineColor;
ctx.lineCap = lineCapStyle;
ctx.setLineDash(lineDash);
ctx.lineDashOffset = lineDashOffset;
ctx.lineWidth = lineWidth;
ctx.beginPath();
if (w > h) {
const w2 = w / 2;
ctx.moveTo(x + w2, y);
ctx.lineTo(x + w2, y + h);
} else {
const h2 = h / 2;
ctx.moveTo(x, y + h2);
ctx.lineTo(x + w, y + h2);
}
ctx.stroke();
ctx.restore();
}
function calculateXYLabel(rect, options, labelSize) {
const {align, position, padding} = options;
let x, y;
x = calculateX(rect, align, padding);
if (position === 'top') {
y = rect.y + padding;
} else if (position === 'bottom') {
y = rect.y + rect.h - padding - labelSize.height;
} else {
y = rect.y + (rect.h - labelSize.height) / 2 + padding;
}
return {x, y};
}
function calculateX(rect, align, padding) {
if (align === 'left') {
return rect.x + padding;
} else if (align === 'right') {
return rect.x + rect.w - padding;
}
return rect.x + rect.w / 2;
}
class TreemapElement extends chart_js.Element {
constructor(cfg) {
super();
this.options = undefined;
this.width = undefined;
this.height = undefined;
if (cfg) {
Object.assign(this, cfg);
}
}
draw(ctx, data, levels = 0) {
if (!data) {
return;
}
const options = this.options;
const {inner, outer} = boundingRects(this);
const addRectPath = hasRadius(outer.radius) ? helpers.addRoundedRectPath : addNormalRectPath;
ctx.save();
if (outer.w !== inner.w || outer.h !== inner.h) {
ctx.beginPath();
addRectPath(ctx, outer);
ctx.clip();
addRectPath(ctx, inner);
ctx.fillStyle = options.borderColor;
ctx.fill('evenodd');
}
ctx.beginPath();
addRectPath(ctx, inner);
ctx.fillStyle = options.backgroundColor;
ctx.fill();
drawDivider(ctx, inner, options, data);
drawText(ctx, inner, options, data, levels);
ctx.restore();
}
inRange(mouseX, mouseY, useFinalPosition) {
return inRange(this, mouseX, mouseY, useFinalPosition);
}
inXRange(mouseX, useFinalPosition) {
return inRange(this, mouseX, null, useFinalPosition);
}
inYRange(mouseY, useFinalPosition) {
return inRange(this, null, mouseY, useFinalPosition);
}
getCenterPoint(useFinalPosition) {
const {x, y, width, height} = this.getProps(['x', 'y', 'width', 'height'], useFinalPosition);
return {
x: x + width / 2,
y: y + height / 2
};
}
tooltipPosition() {
return this.getCenterPoint();
}
getRange(axis) {
return axis === 'x' ? this.width / 2 : this.height / 2;
}
}
TreemapElement.id = 'treemap';
TreemapElement.defaults = {
label: undefined,
borderRadius: 0,
borderWidth: 0,
captions: {
align: undefined,
color: 'black',
display: true,
font: {},
formatter: (ctx) => ctx.raw.g || ctx.raw._data.label || '',
padding: 3
},
dividers: {
display: false,
lineCapStyle: 'butt',
lineColor: 'black',
lineDash: [],
lineDashOffset: 0,
lineWidth: 1,
},
labels: {
align: 'center',
color: 'black',
display: false,
font: {},
formatter(ctx) {
if (ctx.raw.g) {
return [ctx.raw.g, ctx.raw.v + ''];
}
return ctx.raw._data.label ? [ctx.raw._data.label, ctx.raw.v + ''] : ctx.raw.v + '';
},
overflow: 'cut',
position: 'middle',
padding: 3
},
rtl: false,
spacing: 0.5
};
TreemapElement.descriptors = {
labels: {
_fallback: true
},
captions: {
_fallback: true
},
_scriptable: true,
_indexable: false
};
TreemapElement.defaultRoutes = {
backgroundColor: 'backgroundColor',
borderColor: 'borderColor'
};
function round(v, n) {

@@ -366,3 +824,3 @@ // @ts-ignore

var version = "2.0.2";
var version = "2.1.0";

@@ -392,83 +850,20 @@ function rectNotEqual(r1, r2) {

function shouldDrawCaption(rect, font) {
if (!font) {
return false;
}
const w = rect.width || rect.w;
const h = rect.height || rect.h;
const min = font.lineHeight * 2;
return w > min && h > min;
}
function drawCaption(ctx, rect, item, opts, levels) {
ctx.save();
ctx.beginPath();
ctx.rect(rect.x, rect.y, rect.width, rect.height);
ctx.clip();
if (!('l' in item) || item.l === levels) {
drawLabels(ctx, item, rect);
} else if (opts.captions && opts.captions.display) {
drawCaptionLabel(ctx, item, rect);
}
ctx.restore();
}
function drawCaptionLabel(ctx, item, rect) {
const opts = rect.options;
const captionsOpts = opts.captions || {};
const borderWidth = opts.borderWidth || 0;
const spacing = helpers.valueOrDefault(opts.spacing, 0) + borderWidth;
const color = (rect.active ? captionsOpts.hoverColor : captionsOpts.color) || captionsOpts.color;
const padding = captionsOpts.padding;
const align = captionsOpts.align || (opts.rtl ? 'right' : 'left');
const optFont = (rect.active ? captionsOpts.hoverFont : captionsOpts.font) || captionsOpts.font;
const font = helpers.toFont(optFont);
const x = calculateX(rect, align, padding, borderWidth);
ctx.fillStyle = color;
ctx.font = font.string;
ctx.textAlign = align;
ctx.textBaseline = 'middle';
ctx.fillText(captionsOpts.formatter || item.g, x, rect.y + padding + spacing + (font.lineHeight / 2));
}
function drawDivider(ctx, rect) {
const opts = rect.options;
const dividersOpts = opts.dividers || {};
const w = rect.width || rect.w;
const h = rect.height || rect.h;
ctx.save();
ctx.strokeStyle = dividersOpts.lineColor || 'black';
ctx.lineCap = dividersOpts.lineCapStyle;
ctx.setLineDash(dividersOpts.lineDash || []);
ctx.lineDashOffset = dividersOpts.lineDashOffset;
ctx.lineWidth = dividersOpts.lineWidth;
ctx.beginPath();
if (w > h) {
const w2 = w / 2;
ctx.moveTo(rect.x + w2, rect.y);
ctx.lineTo(rect.x + w2, rect.y + h);
} else {
const h2 = h / 2;
ctx.moveTo(rect.x, rect.y + h2);
ctx.lineTo(rect.x + w, rect.y + h2);
}
ctx.stroke();
ctx.restore();
}
function buildData(dataset, mainRect, captions) {
function buildData(dataset, mainRect) {
const key = dataset.key || '';
const treeLeafKey = dataset.treeLeafKey || '_leaf';
let tree = dataset.tree || [];
if (helpers.isObject(tree)) {
tree = normalizeTreeToArray(key, treeLeafKey, tree);
}
const groups = dataset.groups || [];
const glen = groups.length;
const sp = helpers.valueOrDefault(dataset.spacing, 0) + helpers.valueOrDefault(dataset.borderWidth, 0);
const captionsFont = captions.font || {};
const font = helpers.toFont(captionsFont);
const sp = helpers.valueOrDefault(dataset.spacing, 0);
const captions = dataset.captions || {display: true};
const font = helpers.toFont(captions.font);
const padding = helpers.valueOrDefault(captions.padding, 3);
function recur(gidx, rect, parent, gs) {
const g = groups[gidx];
const pg = (gidx > 0) && groups[gidx - 1];
const gdata = group(tree, g, key, pg, parent);
const g = getGroupKey(groups[gidx]);
const pg = (gidx > 0) && getGroupKey(groups[gidx - 1]);
const gdata = group(tree, g, key, treeLeafKey, pg, parent, groups.filter((item, index) => index <= gidx));
const gsq = squarify(gdata, rect, key, g, gidx, gs);

@@ -479,4 +874,11 @@ const ret = gsq.slice();

gsq.forEach((sq) => {
subRect = {x: sq.x + sp, y: sq.y + sp, w: sq.w - 2 * sp, h: sq.h - 2 * sp};
if (helpers.valueOrDefault(captions.display, true) && shouldDrawCaption(sq, font)) {
const bw = parseBorderWidth(dataset.borderWidth, sq.w / 2, sq.h / 2);
subRect = {
x: sq.x + sp + bw.l,
y: sq.y + sp + bw.t,
w: sq.w - 2 * sp - bw.l - bw.r,
h: sq.h - 2 * sp - bw.t - bw.b,
rtl: rect.rtl
};
if (shouldDrawCaption(subRect, captions)) {
subRect.y += font.lineHeight + padding * 2;

@@ -500,49 +902,17 @@ subRect.h -= font.lineHeight + padding * 2;

function drawLabels(ctx, item, rect) {
const opts = rect.options;
const labelsOpts = opts.labels;
if (!labelsOpts || !labelsOpts.display) {
return;
}
const optColor = (rect.active ? labelsOpts.hoverColor : labelsOpts.color) || labelsOpts.color;
const optFont = (rect.active ? labelsOpts.hoverFont : labelsOpts.font) || labelsOpts.font;
const font = helpers.toFont(optFont);
const lh = font.lineHeight;
const label = labelsOpts.formatter;
if (label) {
const labels = helpers.isArray(label) ? label : [label];
const xyPoint = calculateXYLabel(opts, rect, labels, lh);
ctx.font = font.string;
ctx.textAlign = labelsOpts.align;
ctx.textBaseline = labelsOpts.position;
ctx.fillStyle = optColor;
labels.forEach((l, i) => ctx.fillText(l, xyPoint.x, xyPoint.y + i * lh));
}
function getMinMax(data, useTree) {
const vMax = useTree ? 1 : maxValue(data);
const vMin = useTree ? 0 : minValue(data, vMax);
return {vMin, vMax};
}
function calculateXYLabel(options, rect, labels, lineHeight) {
const labelsOpts = options.labels;
const borderWidth = options.borderWidth || 0;
const {align, position, padding} = labelsOpts;
let x, y;
x = calculateX(rect, align, padding, borderWidth);
if (position === 'top') {
y = rect.y + padding + borderWidth;
} else if (position === 'bottom') {
y = rect.y + rect.height - padding - borderWidth - (labels.length - 1) * lineHeight;
} else {
y = rect.y + rect.height / 2 - labels.length * lineHeight / 4;
}
return {x, y};
function getArea({xScale, yScale}, data, rtl, useTree) {
const {vMin, vMax} = getMinMax(data, useTree);
const xMin = xScale.getPixelForValue(0);
const xMax = xScale.getPixelForValue(1);
const yMin = yScale.getPixelForValue(vMin);
const yMax = yScale.getPixelForValue(vMax);
return {x: xMin, y: yMax, w: xMax - xMin, h: yMin - yMax, rtl};
}
function calculateX(rect, align, padding, borderWidth) {
if (align === 'left') {
return rect.x + padding + borderWidth;
} else if (align === 'right') {
return rect.x + rect.width - padding - borderWidth;
}
return rect.x + rect.width / 2;
}
class TreemapController extends chart_js.DatasetController {

@@ -555,2 +925,3 @@ constructor(chart, datasetIndex) {

this._groups = undefined;
this._useTree = undefined;
}

@@ -563,2 +934,23 @@

/**
* TODO: to be removed when https://github.com/kurkle/chartjs-chart-treemap/issues/137
* will be implemented
*/
updateRangeFromParsed(range, scale) {
if (range.updated) {
return;
}
range.updated = true;
if (scale.axis === 'x') {
range.min = 0;
range.max = 1;
return;
}
const me = this;
const dataset = me.getDataset();
const {vMin, vMax} = getMinMax(dataset.data, me._useTree);
range.min = vMin;
range.max = vMax;
}
update(mode) {

@@ -568,9 +960,10 @@ const me = this;

const dataset = me.getDataset();
if (!helpers.defined(me._useTree)) {
me._useTree = !!dataset.tree;
}
const groups = dataset.groups || (dataset.groups = []);
const captions = dataset.captions ? dataset.captions : {};
const area = me.chart.chartArea;
const key = dataset.key || '';
const rtl = !!dataset.rtl;
const mainRect = {x: area.left, y: area.top, w: area.right - area.left, h: area.bottom - area.top, rtl};
const mainRect = getArea(meta, dataset.data, rtl, me._useTree);

@@ -582,3 +975,3 @@ if (mode === 'reset' || rectNotEqual(me._rect, mainRect) || me._key !== key || arrayNotEqual(me._groups, groups)) {

dataset.data = buildData(dataset, mainRect, captions);
dataset.data = buildData(dataset, mainRect);
// @ts-ignore using private stuff

@@ -593,9 +986,2 @@ me._dataCheck();

resolveDataElementOptions(index, mode) {
const options = super.resolveDataElementOptions(index, mode);
const result = Object.isFrozen(options) ? Object.assign({}, options) : options;
result.font = helpers.toFont(options.captions.font);
return result;
}
updateElements(rects, start, count, mode) {

@@ -631,37 +1017,19 @@ const me = this;

_drawDividers(ctx, data, metadata) {
for (let i = 0, ilen = metadata.length; i < ilen; ++i) {
const rect = metadata[i];
const item = data[i];
const dividersOpts = rect.options.dividers || {};
if (dividersOpts.display && item._data.children.length > 1) {
drawDivider(ctx, rect);
}
}
}
_drawRects(ctx, data, metadata, levels) {
for (let i = 0, ilen = metadata.length; i < ilen; ++i) {
const rect = metadata[i];
const item = data[i];
if (!rect.hidden) {
rect.draw(ctx);
const opts = rect.options;
if (shouldDrawCaption(rect, opts.captions.font)) {
drawCaption(ctx, rect, item, opts, levels);
}
}
}
}
draw() {
const me = this;
const ctx = me.chart.ctx;
const area = me.chart.chartArea;
const metadata = me.getMeta().data || [];
const dataset = me.getDataset();
const levels = (dataset.groups || []).length - 1;
const data = dataset.data || [];
const data = dataset.data;
me._drawRects(ctx, data, metadata, levels);
me._drawDividers(ctx, data, metadata);
helpers.clipArea(ctx, area);
for (let i = 0, ilen = metadata.length; i < ilen; ++i) {
const rect = metadata[i];
if (!rect.hidden) {
rect.draw(ctx, data[i], levels);
}
}
helpers.unclipArea(ctx);
}

@@ -684,9 +1052,2 @@ }

borderWidth: 0,
spacing: 0.5,
dividers: {
display: false,
lineWidth: 1,
}
};

@@ -722,3 +1083,3 @@

const dataItem = dataset.data[item.dataIndex];
const label = dataItem.g || dataset.label;
const label = dataItem.g || dataItem._data.label || dataset.label;
return (label ? label + ': ' : '') + dataItem.v;

@@ -758,2 +1119,4 @@ }

};
} else {
console.warn('Unable to register the treemap positioner because tooltip plugin is not registered');
}

@@ -769,185 +1132,11 @@ };

/**
* Helper function to get the bounds of the rect
* @param {TreemapElement} rect the rect
* @param {boolean} [useFinalPosition]
* @return {object} bounds of the rect
* @private
*/
function getBounds(rect, useFinalPosition) {
const {x, y, width, height} = rect.getProps(['x', 'y', 'width', 'height'], useFinalPosition);
return {left: x, top: y, right: x + width, bottom: y + height};
}
function limit(value, min, max) {
return Math.max(Math.min(value, max), min);
}
function parseBorderWidth(value, maxW, maxH) {
let t, r, b, l;
if (isObject(value)) {
t = +value.top || 0;
r = +value.right || 0;
b = +value.bottom || 0;
l = +value.left || 0;
} else {
t = r = b = l = +value || 0;
}
return {
t: limit(t, 0, maxH),
r: limit(r, 0, maxW),
b: limit(b, 0, maxH),
l: limit(l, 0, maxW)
};
}
function boundingRects(rect) {
const bounds = getBounds(rect);
const width = bounds.right - bounds.left;
const height = bounds.bottom - bounds.top;
const border = parseBorderWidth(rect.options.borderWidth, width / 2, height / 2);
return {
outer: {
x: bounds.left,
y: bounds.top,
w: width,
h: height
},
inner: {
x: bounds.left + border.l,
y: bounds.top + border.t,
w: width - border.l - border.r,
h: height - border.t - border.b
}
};
}
function inRange(rect, x, y, useFinalPosition) {
const skipX = x === null;
const skipY = y === null;
const bounds = !rect || (skipX && skipY) ? false : getBounds(rect, useFinalPosition);
return bounds
&& (skipX || x >= bounds.left && x <= bounds.right)
&& (skipY || y >= bounds.top && y <= bounds.bottom);
}
class TreemapElement extends chart_js.Element {
constructor(cfg) {
super();
this.options = undefined;
this.width = undefined;
this.height = undefined;
if (cfg) {
Object.assign(this, cfg);
}
}
draw(ctx) {
const options = this.options;
const {inner, outer} = boundingRects(this);
ctx.save();
if (outer.w !== inner.w || outer.h !== inner.h) {
ctx.beginPath();
ctx.rect(outer.x, outer.y, outer.w, outer.h);
ctx.clip();
ctx.rect(inner.x, inner.y, inner.w, inner.h);
ctx.fillStyle = options.backgroundColor;
ctx.fill();
ctx.fillStyle = options.borderColor;
ctx.fill('evenodd');
} else {
ctx.fillStyle = options.backgroundColor;
ctx.fillRect(inner.x, inner.y, inner.w, inner.h);
}
ctx.restore();
}
inRange(mouseX, mouseY, useFinalPosition) {
return inRange(this, mouseX, mouseY, useFinalPosition);
}
inXRange(mouseX, useFinalPosition) {
return inRange(this, mouseX, null, useFinalPosition);
}
inYRange(mouseY, useFinalPosition) {
return inRange(this, null, mouseY, useFinalPosition);
}
getCenterPoint(useFinalPosition) {
const {x, y, width, height} = this.getProps(['x', 'y', 'width', 'height'], useFinalPosition);
return {
x: x + width / 2,
y: y + height / 2
};
}
tooltipPosition() {
return this.getCenterPoint();
}
getRange(axis) {
return axis === 'x' ? this.width / 2 : this.height / 2;
}
}
TreemapElement.id = 'treemap';
TreemapElement.defaults = {
borderWidth: undefined,
spacing: undefined,
label: undefined,
rtl: undefined,
dividers: {
display: false,
lineCapStyle: 'butt',
lineColor: 'black',
lineDash: undefined,
lineDashOffset: 0,
lineWidth: 0,
},
captions: {
align: undefined,
color: undefined,
display: true,
formatter: (ctx) => ctx.raw.g || '',
font: {},
padding: 3
},
labels: {
align: 'center',
color: undefined,
display: false,
formatter: (ctx) => ctx.raw.g ? [ctx.raw.g, ctx.raw.v] : ctx.raw.v,
font: {},
position: 'middle',
padding: 3
}
};
TreemapElement.descriptors = {
_scriptable: true,
_indexable: false
};
TreemapElement.defaultRoutes = {
backgroundColor: 'backgroundColor',
borderColor: 'borderColor'
};
chart_js.Chart.register(TreemapController, TreemapElement);
exports.flatten = flatten;
exports.getGroupKey = getGroupKey;
exports.group = group;
exports.index = index;
exports.isObject = isObject;
exports.maxValue = maxValue;
exports.minValue = minValue;
exports.normalizeTreeToArray = normalizeTreeToArray;
exports.requireVersion = requireVersion;

@@ -954,0 +1143,0 @@ exports.sort = sort;

/*!
* chartjs-chart-treemap v2.0.2
* chartjs-chart-treemap v2.1.0
* https://chartjs-chart-treemap.pages.dev/
* (c) 2021 Jukka Kurkela
* (c) 2022 Jukka Kurkela
* Released under the MIT license
*/
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("chart.js"),require("chart.js/helpers")):"function"==typeof define&&define.amd?define(["exports","chart.js","chart.js/helpers"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self)["chartjs-chart-treemap"]={},t.Chart,t.Chart.helpers)}(this,(function(t,e,n){"use strict";function i(t){const e=[...t],n=[];for(;e.length;){const t=e.pop();Array.isArray(t)?e.push(...t):n.push(t)}return n.reverse()}function r(t,e,n,i,r){const o=Object.create(null),s=Object.create(null),a=[];let l,h,u,c;for(h=0,u=t.length;h<u;++h)c=t[h],i&&c[i]!==r||(l=c[e]||"",l in o||(o[l]=0,s[l]=[]),o[l]+=+c[n],s[l].push(c));return Object.keys(o).forEach((t=>{c={children:s[t]},c[n]=+o[t],c[e]=t,i&&(c[i]=r),a.push(c)})),a}function o(t){const e=typeof t;return"function"===e||"object"===e&&!!t}function s(t,e){let n,i=t.length;if(!i)return e;const r=o(t[0]);for(e=r?e:"v",n=0,i=t.length;n<i;++n)r?t[n]._idx=n:t[n]={v:t[n],_idx:n};return e}function a(t,e){e?t.sort(((t,n)=>+n[e]-+t[e])):t.sort(((t,e)=>+e-+t))}function l(t,e){let n,i,r;for(n=0,i=0,r=t.length;i<r;++i)n+=e?+t[i][e]:+t[i];return n}function h(t,e){const n=e.split(".");if(!t.split(".").reduce(((t,e,i)=>t&&e<=n[i]),!0))throw new Error(`Chart.js v${e} is not supported. v${t} or newer is required.`)}function u(t,e){return+(Math.round(t+"e+"+e)+"e-"+e)||0}function c(t,e,n,i){const r=t._normalized,o=e*r/n,s=Math.sqrt(r*o),a=r/s;return{d1:s,d2:a,w:"_ix"===i?s:a,h:"_ix"===i?a:s}}const d=(t,e)=>u(t.rtl?t.x+t.w-t._ix-e:t.x+t._ix,4);function p(t,e,n,i){const r={x:d(t,n.w),y:u(t.y+t._iy,4),w:u(n.w,4),h:u(n.h,4),a:u(e._normalized,4),v:e.value,s:i,_data:e._data};return e.group&&(r.g=e.group,r.l=e.level,r.gs=e.groupSum),r}class g{constructor(t){const e=this;t=t||{w:1,h:1},e.rtl=!!t.rtl,e.x=t.x||t.left||0,e.y=t.y||t.top||0,e._ix=0,e._iy=0,e.w=t.w||t.width||t.right-t.left,e.h=t.h||t.height||t.bottom-t.top}get area(){return this.w*this.h}get iw(){return this.w-this._ix}get ih(){return this.h-this._iy}get dir(){const t=this.ih;return t<=this.iw&&t>0?"y":"x"}get side(){return"x"===this.dir?this.iw:this.ih}map(t){const e=this,n=[],i=t.nsum,r=t.get(),o=e.dir,s=e.side,a=s*s,l="x"===o?"_ix":"_iy",h=i*i;let u=0,d=0;for(const i of r){const r=c(i,a,h,l);d+=r.d1,u=Math.max(u,r.d2),n.push(p(e,i,r,t.sum)),e[l]+=r.d1}return e["y"===o?"_ix":"_iy"]+=u,e[l]-=d,n}}const f=Math.min,m=Math.max;function y(t,e){const n=+e[t.key],i=n*t.ratio;return e._normalized=i,{min:f(t.min,n),max:m(t.max,n),sum:t.sum+n,nmin:f(t.nmin,i),nmax:m(t.nmax,i),nsum:t.nsum+i}}function x(t,e,n){t._arr.push(e),function(t,e){Object.assign(t,e)}(t,n)}class v{constructor(t,e){const n=this;n.key=t,n.ratio=e,n.reset()}get length(){return this._arr.length}reset(){const t=this;t._arr=[],t._hist=[],t.sum=0,t.nsum=0,t.min=1/0,t.max=-1/0,t.nmin=1/0,t.nmax=-1/0}push(t){x(this,t,y(this,t))}pushIf(t,e,...n){const i=y(this,t);if(!e((r=this,{min:r.min,max:r.max,sum:r.sum,nmin:r.nmin,nmax:r.nmax,nsum:r.nsum}),i,n))return t;var r;x(this,t,i)}get(){return this._arr}}function w(t,e,n){if(0===t.sum)return!0;const[i]=n,r=t.nsum*t.nsum,o=e.nsum*e.nsum,s=i*i,a=Math.max(s*t.nmax/r,r/(s*t.nmin));return Math.max(s*e.nmax/o,o/(s*e.nmin))<=a}function b(t,e,n,r,o,h){t=t||[];const u=[],c=new g(e),d=new v("value",c.area/l(t,n));let p=c.side;const f=t.length;let m,y;if(!f)return u;const x=t.slice();n=s(x,n),a(x,n);const b=t=>r&&x[t][r];for(m=0;m<f;++m)y={value:(_=m,n?+x[_][n]:+x[_]),groupSum:h,_data:t[x[m]._idx],level:void 0,group:void 0},r&&(y.level=o,y.group=b(m)),y=d.pushIf(y,w,p),y&&(u.push(c.map(d)),p=c.side,d.reset(),d.push(y));var _;return d.length&&u.push(c.map(d)),i(u)}function _(t,e){if(!e)return!1;const n=t.width||t.w,i=t.height||t.h,r=2*e.lineHeight;return n>r&&i>r}function O(t,e,i,r,o){t.save(),t.beginPath(),t.rect(e.x,e.y,e.width,e.height),t.clip(),"l"in i&&i.l!==o?r.captions&&r.captions.display&&function(t,e,i){const r=i.options,o=r.captions||{},s=r.borderWidth||0,a=n.valueOrDefault(r.spacing,0)+s,l=(i.active?o.hoverColor:o.color)||o.color,h=o.padding,u=o.align||(r.rtl?"right":"left"),c=(i.active?o.hoverFont:o.font)||o.font,d=n.toFont(c),p=D(i,u,h,s);t.fillStyle=l,t.font=d.string,t.textAlign=u,t.textBaseline="middle",t.fillText(o.formatter||e.g,p,i.y+h+a+d.lineHeight/2)}(t,i,e):function(t,e,i){const r=i.options,o=r.labels;if(!o||!o.display)return;const s=(i.active?o.hoverColor:o.color)||o.color,a=(i.active?o.hoverFont:o.font)||o.font,l=n.toFont(a),h=l.lineHeight,u=o.formatter;if(u){const e=n.isArray(u)?u:[u],a=function(t,e,n,i){const r=t.labels,o=t.borderWidth||0,{align:s,position:a,padding:l}=r;let h,u;h=D(e,s,l,o),u="top"===a?e.y+l+o:"bottom"===a?e.y+e.height-l-o-(n.length-1)*i:e.y+e.height/2-n.length*i/4;return{x:h,y:u}}(r,i,e,h);t.font=l.string,t.textAlign=o.align,t.textBaseline=o.position,t.fillStyle=s,e.forEach(((e,n)=>t.fillText(e,a.x,a.y+n*h)))}}(t,0,e),t.restore()}function C(t,e){const n=e.options.dividers||{},i=e.width||e.w,r=e.height||e.h;if(t.save(),t.strokeStyle=n.lineColor||"black",t.lineCap=n.lineCapStyle,t.setLineDash(n.lineDash||[]),t.lineDashOffset=n.lineDashOffset,t.lineWidth=n.lineWidth,t.beginPath(),i>r){const n=i/2;t.moveTo(e.x+n,e.y),t.lineTo(e.x+n,e.y+r)}else{const n=r/2;t.moveTo(e.x,e.y+n),t.lineTo(e.x+i,e.y+n)}t.stroke(),t.restore()}function D(t,e,n,i){return"left"===e?t.x+n+i:"right"===e?t.x+t.width-n-i:t.x+t.width/2}class k extends e.DatasetController{constructor(t,e){super(t,e),this._rect=void 0,this._key=void 0,this._groups=void 0}initialize(){this.enableOptionSharing=!0,super.initialize()}update(t){const e=this,i=e.getMeta(),o=e.getDataset(),s=o.groups||(o.groups=[]),a=o.captions?o.captions:{},l=e.chart.chartArea,h=o.key||"",u=!!o.rtl,c={x:l.left,y:l.top,w:l.right-l.left,h:l.bottom-l.top,rtl:u};var d,p;"reset"!==t&&(d=e._rect,p=c,d&&p&&d.x===p.x&&d.y===p.y&&d.w===p.w&&d.h===p.h)&&e._key===h&&!function(t,e){let n,i;if(t.lenght!==e.length)return!0;for(n=0,i=t.length;n<i;++n)if(t[n]!==e[n])return!0;return!1}(e._groups,s)||(e._rect=c,e._groups=s.slice(),e._key=h,o.data=function(t,e,i){const o=t.key||"";let s=t.tree||[];const a=t.groups||[],l=a.length,h=n.valueOrDefault(t.spacing,0)+n.valueOrDefault(t.borderWidth,0),u=i.font||{},c=n.toFont(u),d=n.valueOrDefault(i.padding,3);return!s.length&&t.data.length&&(s=t.tree=t.data),l?function t(e,u,p,g){const f=a[e],m=e>0&&a[e-1],y=b(r(s,f,o,m,p),u,o,f,e,g),x=y.slice();let v;return e<l-1&&y.forEach((r=>{v={x:r.x+h,y:r.y+h,w:r.w-2*h,h:r.h-2*h},n.valueOrDefault(i.display,!0)&&_(r,c)&&(v.y+=c.lineHeight+2*d,v.h-=c.lineHeight+2*d),x.push(...t(e+1,v,r.g,r.s))})),x}(0,e):b(s,e,o)}(o,c,a),e._dataCheck(),e._resyncElements()),e.updateElements(i.data,0,i.data.length,t)}resolveDataElementOptions(t,e){const i=super.resolveDataElementOptions(t,e),r=Object.isFrozen(i)?Object.assign({},i):i;return r.font=n.toFont(i.captions.font),r}updateElements(t,e,n,i){const r=this,o="reset"===i,s=r.getDataset(),a=r._rect.options=r.resolveDataElementOptions(e,i),l=r.getSharedOptions(a),h=r.includeOptions(i,l);for(let a=e;a<e+n;a++){const e=s.data[a],n=l||r.resolveDataElementOptions(a,i),u=n.spacing,c=2*u,d={x:e.x+u,y:e.y+u,width:o?0:e.w-c,height:o?0:e.h-c,hidden:c>e.w||c>e.h};h&&(d.options=n),r.updateElement(t[a],a,d,i)}r.updateSharedOptions(l,i,a)}_drawDividers(t,e,n){for(let i=0,r=n.length;i<r;++i){const r=n[i],o=e[i];(r.options.dividers||{}).display&&o._data.children.length>1&&C(t,r)}}_drawRects(t,e,n,i){for(let r=0,o=n.length;r<o;++r){const o=n[r],s=e[r];if(!o.hidden){o.draw(t);const e=o.options;_(o,e.captions.font)&&O(t,o,s,e,i)}}}draw(){const t=this,e=t.chart.ctx,n=t.getMeta().data||[],i=t.getDataset(),r=(i.groups||[]).length-1,o=i.data||[];t._drawRects(e,o,n,r),t._drawDividers(e,o,n)}}function j(t,e){const{x:n,y:i,width:r,height:o}=t.getProps(["x","y","width","height"],e);return{left:n,top:i,right:n+r,bottom:i+o}}function E(t,e,n){return Math.max(Math.min(t,n),e)}function S(t){const e=j(t),n=e.right-e.left,i=e.bottom-e.top,r=function(t,e,n){let i,r,s,a;return o(t)?(i=+t.top||0,r=+t.right||0,s=+t.bottom||0,a=+t.left||0):i=r=s=a=+t||0,{t:E(i,0,n),r:E(r,0,e),b:E(s,0,n),l:E(a,0,e)}}(t.options.borderWidth,n/2,i/2);return{outer:{x:e.left,y:e.top,w:n,h:i},inner:{x:e.left+r.l,y:e.top+r.t,w:n-r.l-r.r,h:i-r.t-r.b}}}function M(t,e,n,i){const r=null===e,o=null===n,s=!(!t||r&&o)&&j(t,i);return s&&(r||e>=s.left&&e<=s.right)&&(o||n>=s.top&&n<=s.bottom)}k.id="treemap",k.version="2.0.2",k.defaults={dataElementType:"treemap",animations:{numbers:{type:"number",properties:["x","y","width","height"]}},borderWidth:0,spacing:.5,dividers:{display:!1,lineWidth:1}},k.descriptors={_scriptable:!0,_indexable:!1},k.overrides={interaction:{mode:"point",intersect:!0},hover:{},plugins:{tooltip:{position:"treemap",intersect:!0,callbacks:{title(t){if(t.length){return t[0].dataset.key||""}return""},label(t){const e=t.dataset,n=e.data[t.dataIndex],i=n.g||e.label;return(i?i+": ":"")+n.v}}}},scales:{x:{type:"linear",display:!1},y:{type:"linear",display:!1}}},k.beforeRegister=function(){h("3.6",e.Chart.version)},k.afterRegister=function(){const t=e.registry.plugins.get("tooltip");t&&(t.positioners.treemap=function(t){if(!t.length)return!1;return t[t.length-1].element.tooltipPosition()})},k.afterUnregister=function(){const t=e.registry.plugins.get("tooltip");t&&delete t.positioners.treemap};class P extends e.Element{constructor(t){super(),this.options=void 0,this.width=void 0,this.height=void 0,t&&Object.assign(this,t)}draw(t){const e=this.options,{inner:n,outer:i}=S(this);t.save(),i.w!==n.w||i.h!==n.h?(t.beginPath(),t.rect(i.x,i.y,i.w,i.h),t.clip(),t.rect(n.x,n.y,n.w,n.h),t.fillStyle=e.backgroundColor,t.fill(),t.fillStyle=e.borderColor,t.fill("evenodd")):(t.fillStyle=e.backgroundColor,t.fillRect(n.x,n.y,n.w,n.h)),t.restore()}inRange(t,e,n){return M(this,t,e,n)}inXRange(t,e){return M(this,t,null,e)}inYRange(t,e){return M(this,null,t,e)}getCenterPoint(t){const{x:e,y:n,width:i,height:r}=this.getProps(["x","y","width","height"],t);return{x:e+i/2,y:n+r/2}}tooltipPosition(){return this.getCenterPoint()}getRange(t){return"x"===t?this.width/2:this.height/2}}P.id="treemap",P.defaults={borderWidth:void 0,spacing:void 0,label:void 0,rtl:void 0,dividers:{display:!1,lineCapStyle:"butt",lineColor:"black",lineDash:void 0,lineDashOffset:0,lineWidth:0},captions:{align:void 0,color:void 0,display:!0,formatter:t=>t.raw.g||"",font:{},padding:3},labels:{align:"center",color:void 0,display:!1,formatter:t=>t.raw.g?[t.raw.g,t.raw.v]:t.raw.v,font:{},position:"middle",padding:3}},P.descriptors={_scriptable:!0,_indexable:!1},P.defaultRoutes={backgroundColor:"backgroundColor",borderColor:"borderColor"},e.Chart.register(k,P),t.flatten=i,t.group=r,t.index=s,t.isObject=o,t.requireVersion=h,t.sort=a,t.sum=l,Object.defineProperty(t,"__esModule",{value:!0})}));
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("chart.js"),require("chart.js/helpers")):"function"==typeof define&&define.amd?define(["exports","chart.js","chart.js/helpers"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self)["chartjs-chart-treemap"]={},t.Chart,t.Chart.helpers)}(this,(function(t,e,n){"use strict";const i=t=>n.isObject(t)?t.v:t,r=t=>t.reduce((function(t,e){return t>i(e)?t:i(e)}),0),o=(t,e)=>t.reduce((function(t,e){return t<i(e)?t:i(e)}),e),s=t=>""+t;function a(t,e,i,r=[],o=0,l=[]){const h=o-1;if(t in i&&o>0){const n=r.reduce((function(t,e,n){return n!==h&&(t[s(n)]=e),t}),{});n[e]=r[h],n[t]=i[t],l.push(n)}else for(const s of Object.keys(i)){const h=i[s];n.isObject(h)&&(r.push(s),a(t,e,h,r,o+1,l))}return r.splice(h,1),l}function l(t,e,n){const i=a(t,e,n);if(!i.length)return i;const r=i.reduce((function(t,e){const n=Object.keys(e).length-2;return t>n?t:n}));return i.forEach((function(t){for(let e=0;e<r;e++){const n=s(e);t[n]||(t[n]="")}})),i}function h(t){const e=[...t],n=[];for(;e.length;){const t=e.pop();Array.isArray(t)?e.push(...t):n.push(t)}return n.reverse()}function u(t,e,n){if(!t.length)return;const i=[];for(const r of t){const t=e[r];if(""===t){i.push(n);break}i.push(t)}return i.length?i.join("."):n}function c(t,e,n,i,r,o,s=[]){const a=Object.create(null),l=Object.create(null),h=[];let c,d,f;for(d=0,f=t.length;d<f;++d){const h=t[d];r&&h[r]!==o||(c=h[e]||h[i]||"",c in a||(a[c]={value:0},l[c]=[]),a[c].value+=+h[n],a[c].label=h[e]||"",a[c].path=u(s,h,c),l[c].push(h))}return Object.keys(a).forEach((t=>{const i={children:l[t]};i[n]=+a[t].value,i[e]=a[t].label,i.label=t,i.path=a[t].path,r&&(i[r]=o),h.push(i)})),h}function d(t,e){let i,r=t.length;if(!r)return e;const o=n.isObject(t[0]);for(e=o?e:"v",i=0,r=t.length;i<r;++i)o?t[i]._idx=i:t[i]={v:t[i],_idx:i};return e}function f(t,e){e?t.sort(((t,n)=>+n[e]-+t[e])):t.sort(((t,e)=>+e-+t))}function p(t,e){let n,i,r;for(n=0,i=0,r=t.length;i<r;++i)n+=e?+t[i][e]:+t[i];return n}function g(t,e){const n=e.split(".");if(!t.split(".").reduce(((t,e,i)=>t&&e<=n[i]),!0))throw new Error(`Chart.js v${e} is not supported. v${t} or newer is required.`)}const m=new Map;function x(t,e){const{x:n,y:i,width:r,height:o}=t.getProps(["x","y","width","height"],e);return{left:n,top:i,right:n+r,bottom:i+o}}function y(t,e,n){return Math.max(Math.min(t,n),e)}function b(t,e,i){const r=n.toTRBL(t);return{t:y(r.top,0,i),r:y(r.right,0,e),b:y(r.bottom,0,i),l:y(r.left,0,e)}}function v(t){const e=x(t),i=e.right-e.left,r=e.bottom-e.top,o=b(t.options.borderWidth,i/2,r/2),s=function(t,e,i){const r=n.toTRBLCorners(t),o=Math.min(e,i);return{topLeft:y(r.topLeft,0,o),topRight:y(r.topRight,0,o),bottomLeft:y(r.bottomLeft,0,o),bottomRight:y(r.bottomRight,0,o)}}(t.options.borderRadius,i/2,r/2);return{outer:{x:e.left,y:e.top,w:i,h:r,radius:s},inner:{x:e.left+o.l,y:e.top+o.t,w:i-o.l-o.r,h:r-o.t-o.b,radius:{topLeft:Math.max(0,s.topLeft-Math.max(o.t,o.l)),topRight:Math.max(0,s.topRight-Math.max(o.t,o.r)),bottomLeft:Math.max(0,s.bottomLeft-Math.max(o.b,o.l)),bottomRight:Math.max(0,s.bottomRight-Math.max(o.b,o.r))}}}}function w(t,e,n,i){const r=null===e,o=null===n,s=!(!t||r&&o)&&x(t,i);return s&&(r||e>=s.left&&e<=s.right)&&(o||n>=s.top&&n<=s.bottom)}function _(t,e){t.rect(e.x,e.y,e.w,e.h)}function M(t,e){if(!e||!e.display)return!1;const{w:i,h:r}=t,o=n.toFont(e.font).lineHeight,s=y(2*n.valueOrDefault(e.padding,3),0,Math.min(i,r));return i-s>o&&r-s>o}function k(t,e,i,r,o){const{captions:s,labels:a}=i;t.save(),t.beginPath(),t.rect(e.x,e.y,e.w,e.h),t.clip();const l=!("l"in r)||r.l===o;l&&a.display?function(t,e,i){const r=i.labels,o=r.formatter;if(!o)return;const s=n.isArray(o)?o:[o],{font:a,hoverFont:l}=r,h=(e.active?l:a)||a,u=n.isArray(h)?h.map((t=>n.toFont(t))):[n.toFont(h)],c=function(t,e,n){const i=n.reduce((function(t,e){return t+=e.string}),""),r=e.join()+i+(t._measureText?"-spriting":"");if(!m.has(r)){t.save();const i=e.length;let o=0,s=0;for(let r=0;r<i;r++){const i=n[Math.min(r,n.length-1)];t.font=i.string;const a=e[r];o=Math.max(o,t.measureText(a).width),s+=i.lineHeight}t.restore(),m.set(r,{width:o,height:s})}return m.get(r)}(t,s,u);if(!function(t,e,n,i){const{overflow:r,padding:o}=n,{width:s,height:a}=i;if("hidden"===r)return!(s+2*o>e.w||a+2*o>e.h);return!0}(0,e,r,c))return;const{color:d,hoverColor:f,align:p}=r,g=(e.active?f:d)||d,x=n.isArray(g)?g:[g],y=function(t,e,n){const{align:i,position:r,padding:o}=e;let s,a;s=O(t,i,o),a="top"===r?t.y+o:"bottom"===r?t.y+t.h-o-n.height:t.y+(t.h-n.height)/2+o;return{x:s,y:a}}(e,r,c);t.textAlign=p,t.textBaseline="middle";let b=0;s.forEach((function(e,n){const i=x[Math.min(n,x.length-1)],r=u[Math.min(n,u.length-1)],o=r.lineHeight;t.font=r.string,t.fillStyle=i,t.fillText(e,y.x,y.y+o/2+b),b+=o}))}(t,e,i):!l&&M(e,s)&&function(t,e,i,r){const{captions:o,spacing:s,rtl:a}=i,{color:l,hoverColor:h,font:u,hoverFont:c,padding:d,align:f,formatter:p}=o,g=(e.active?h:l)||l,m=f||(a?"right":"left"),x=(e.active?c:u)||u,y=n.toFont(x),b=y.lineHeight/2,v=O(e,m,d);t.fillStyle=g,t.font=y.string,t.textAlign=m,t.textBaseline="middle",t.fillText(p||r.g,v,e.y+d+s+b)}(t,e,i,r),t.restore()}function O(t,e,n){return"left"===e?t.x+n:"right"===e?t.x+t.w-n:t.x+t.w/2}class R extends e.Element{constructor(t){super(),this.options=void 0,this.width=void 0,this.height=void 0,t&&Object.assign(this,t)}draw(t,e,i=0){if(!e)return;const r=this.options,{inner:o,outer:s}=v(this),a=(l=s.radius).topLeft||l.topRight||l.bottomLeft||l.bottomRight?n.addRoundedRectPath:_;var l;t.save(),s.w===o.w&&s.h===o.h||(t.beginPath(),a(t,s),t.clip(),a(t,o),t.fillStyle=r.borderColor,t.fill("evenodd")),t.beginPath(),a(t,o),t.fillStyle=r.backgroundColor,t.fill(),function(t,e,n,i){const r=n.dividers;if(!r.display||!i._data.children.length)return;const{x:o,y:s,w:a,h:l}=e,{lineColor:h,lineCapStyle:u,lineDash:c,lineDashOffset:d,lineWidth:f}=r;if(t.save(),t.strokeStyle=h,t.lineCap=u,t.setLineDash(c),t.lineDashOffset=d,t.lineWidth=f,t.beginPath(),a>l){const e=a/2;t.moveTo(o+e,s),t.lineTo(o+e,s+l)}else{const e=l/2;t.moveTo(o,s+e),t.lineTo(o+a,s+e)}t.stroke(),t.restore()}(t,o,r,e),k(t,o,r,e,i),t.restore()}inRange(t,e,n){return w(this,t,e,n)}inXRange(t,e){return w(this,t,null,e)}inYRange(t,e){return w(this,null,t,e)}getCenterPoint(t){const{x:e,y:n,width:i,height:r}=this.getProps(["x","y","width","height"],t);return{x:e+i/2,y:n+r/2}}tooltipPosition(){return this.getCenterPoint()}getRange(t){return"x"===t?this.width/2:this.height/2}}function C(t,e){return+(Math.round(t+"e+"+e)+"e-"+e)||0}function j(t,e,n,i){const r=t._normalized,o=e*r/n,s=Math.sqrt(r*o),a=r/s;return{d1:s,d2:a,w:"_ix"===i?s:a,h:"_ix"===i?a:s}}R.id="treemap",R.defaults={label:void 0,borderRadius:0,borderWidth:0,captions:{align:void 0,color:"black",display:!0,font:{},formatter:t=>t.raw.g||t.raw._data.label||"",padding:3},dividers:{display:!1,lineCapStyle:"butt",lineColor:"black",lineDash:[],lineDashOffset:0,lineWidth:1},labels:{align:"center",color:"black",display:!1,font:{},formatter:t=>t.raw.g?[t.raw.g,t.raw.v+""]:t.raw._data.label?[t.raw._data.label,t.raw.v+""]:t.raw.v+"",overflow:"cut",position:"middle",padding:3},rtl:!1,spacing:.5},R.descriptors={labels:{_fallback:!0},captions:{_fallback:!0},_scriptable:!0,_indexable:!1},R.defaultRoutes={backgroundColor:"backgroundColor",borderColor:"borderColor"};const T=(t,e)=>C(t.rtl?t.x+t.w-t._ix-e:t.x+t._ix,4);function P(t,e,n,i){const r={x:T(t,n.w),y:C(t.y+t._iy,4),w:C(n.w,4),h:C(n.h,4),a:C(e._normalized,4),v:e.value,s:i,_data:e._data};return e.group&&(r.g=e.group,r.l=e.level,r.gs=e.groupSum),r}class D{constructor(t){const e=this;t=t||{w:1,h:1},e.rtl=!!t.rtl,e.x=t.x||t.left||0,e.y=t.y||t.top||0,e._ix=0,e._iy=0,e.w=t.w||t.width||t.right-t.left,e.h=t.h||t.height||t.bottom-t.top}get area(){return this.w*this.h}get iw(){return this.w-this._ix}get ih(){return this.h-this._iy}get dir(){const t=this.ih;return t<=this.iw&&t>0?"y":"x"}get side(){return"x"===this.dir?this.iw:this.ih}map(t){const e=this,n=[],i=t.nsum,r=t.get(),o=e.dir,s=e.side,a=s*s,l="x"===o?"_ix":"_iy",h=i*i;let u=0,c=0;for(const i of r){const r=j(i,a,h,l);c+=r.d1,u=Math.max(u,r.d2),n.push(P(e,i,r,t.sum)),e[l]+=r.d1}return e["y"===o?"_ix":"_iy"]+=u,e[l]-=c,n}}const L=Math.min,S=Math.max;function E(t,e){const n=+e[t.key],i=n*t.ratio;return e._normalized=i,{min:L(t.min,n),max:S(t.max,n),sum:t.sum+n,nmin:L(t.nmin,i),nmax:S(t.nmax,i),nsum:t.nsum+i}}function F(t,e,n){t._arr.push(e),function(t,e){Object.assign(t,e)}(t,n)}class A{constructor(t,e){const n=this;n.key=t,n.ratio=e,n.reset()}get length(){return this._arr.length}reset(){const t=this;t._arr=[],t._hist=[],t.sum=0,t.nsum=0,t.min=1/0,t.max=-1/0,t.nmin=1/0,t.nmax=-1/0}push(t){F(this,t,E(this,t))}pushIf(t,e,...n){const i=E(this,t);if(!e((r=this,{min:r.min,max:r.max,sum:r.sum,nmin:r.nmin,nmax:r.nmax,nsum:r.nsum}),i,n))return t;var r;F(this,t,i)}get(){return this._arr}}function V(t,e,n){if(0===t.sum)return!0;const[i]=n,r=t.nsum*t.nsum,o=e.nsum*e.nsum,s=i*i,a=Math.max(s*t.nmax/r,r/(s*t.nmin));return Math.max(s*e.nmax/o,o/(s*e.nmin))<=a}function z(t,e,n,i,r,o){t=t||[];const s=[],a=new D(e),l=new A("value",a.area/p(t,n));let u=a.side;const c=t.length;let g,m;if(!c)return s;const x=t.slice();n=d(x,n),f(x,n);const y=t=>i&&x[t][i];for(g=0;g<c;++g)m={value:(b=g,n?+x[b][n]:+x[b]),groupSum:o,_data:t[x[g]._idx],level:void 0,group:void 0},i&&(m.level=r,m.group=y(g)),m=l.pushIf(m,V,u),m&&(s.push(a.map(l)),u=a.side,l.reset(),l.push(m));var b;return l.length&&s.push(a.map(l)),h(s)}function H(t,e){const n=e?1:r(t);return{vMin:e?0:o(t,n),vMax:n}}class W extends e.DatasetController{constructor(t,e){super(t,e),this._rect=void 0,this._key=void 0,this._groups=void 0,this._useTree=void 0}initialize(){this.enableOptionSharing=!0,super.initialize()}updateRangeFromParsed(t,e){if(t.updated)return;if(t.updated=!0,"x"===e.axis)return t.min=0,void(t.max=1);const n=this.getDataset(),{vMin:i,vMax:r}=H(n.data,this._useTree);t.min=i,t.max=r}update(t){const e=this,i=e.getMeta(),r=e.getDataset();n.defined(e._useTree)||(e._useTree=!!r.tree);const o=r.groups||(r.groups=[]),a=r.key||"",h=!!r.rtl,u=function({xScale:t,yScale:e},n,i,r){const{vMin:o,vMax:s}=H(n,r),a=t.getPixelForValue(0),l=t.getPixelForValue(1),h=e.getPixelForValue(o),u=e.getPixelForValue(s);return{x:a,y:u,w:l-a,h:h-u,rtl:i}}(i,r.data,h,e._useTree);var d,f;"reset"!==t&&(d=e._rect,f=u,d&&f&&d.x===f.x&&d.y===f.y&&d.w===f.w&&d.h===f.h)&&e._key===a&&!function(t,e){let n,i;if(t.lenght!==e.length)return!0;for(n=0,i=t.length;n<i;++n)if(t[n]!==e[n])return!0;return!1}(e._groups,o)||(e._rect=u,e._groups=o.slice(),e._key=a,r.data=function(t,e){const i=t.key||"",r=t.treeLeafKey||"_leaf";let o=t.tree||[];n.isObject(o)&&(o=l(i,r,o));const a=t.groups||[],h=a.length,u=n.valueOrDefault(t.spacing,0),d=t.captions||{display:!0},f=n.toFont(d.font),p=n.valueOrDefault(d.padding,3);return!o.length&&t.data.length&&(o=t.tree=t.data),h?function e(n,l,g,m){const x=s(a[n]),y=n>0&&s(a[n-1]),v=c(o,x,i,r,y,g,a.filter(((t,e)=>e<=n))),w=z(v,l,i,x,n,m),_=w.slice();let k;return n<h-1&&w.forEach((i=>{const r=b(t.borderWidth,i.w/2,i.h/2);k={x:i.x+u+r.l,y:i.y+u+r.t,w:i.w-2*u-r.l-r.r,h:i.h-2*u-r.t-r.b,rtl:l.rtl},M(k,d)&&(k.y+=f.lineHeight+2*p,k.h-=f.lineHeight+2*p),_.push(...e(n+1,k,i.g,i.s))})),_}(0,e):z(o,e,i)}(r,u),e._dataCheck(),e._resyncElements()),e.updateElements(i.data,0,i.data.length,t)}updateElements(t,e,n,i){const r=this,o="reset"===i,s=r.getDataset(),a=r._rect.options=r.resolveDataElementOptions(e,i),l=r.getSharedOptions(a),h=r.includeOptions(i,l);for(let a=e;a<e+n;a++){const e=s.data[a],n=l||r.resolveDataElementOptions(a,i),u=n.spacing,c=2*u,d={x:e.x+u,y:e.y+u,width:o?0:e.w-c,height:o?0:e.h-c,hidden:c>e.w||c>e.h};h&&(d.options=n),r.updateElement(t[a],a,d,i)}r.updateSharedOptions(l,i,a)}draw(){const t=this,e=t.chart.ctx,i=t.chart.chartArea,r=t.getMeta().data||[],o=t.getDataset(),s=(o.groups||[]).length-1,a=o.data;n.clipArea(e,i);for(let t=0,n=r.length;t<n;++t){const n=r[t];n.hidden||n.draw(e,a[t],s)}n.unclipArea(e)}}W.id="treemap",W.version="2.1.0",W.defaults={dataElementType:"treemap",animations:{numbers:{type:"number",properties:["x","y","width","height"]}}},W.descriptors={_scriptable:!0,_indexable:!1},W.overrides={interaction:{mode:"point",intersect:!0},hover:{},plugins:{tooltip:{position:"treemap",intersect:!0,callbacks:{title(t){if(t.length){return t[0].dataset.key||""}return""},label(t){const e=t.dataset,n=e.data[t.dataIndex],i=n.g||n._data.label||e.label;return(i?i+": ":"")+n.v}}}},scales:{x:{type:"linear",display:!1},y:{type:"linear",display:!1}}},W.beforeRegister=function(){g("3.6",e.Chart.version)},W.afterRegister=function(){const t=e.registry.plugins.get("tooltip");t?t.positioners.treemap=function(t){if(!t.length)return!1;return t[t.length-1].element.tooltipPosition()}:console.warn("Unable to register the treemap positioner because tooltip plugin is not registered")},W.afterUnregister=function(){const t=e.registry.plugins.get("tooltip");t&&delete t.positioners.treemap},e.Chart.register(W,R),t.flatten=h,t.getGroupKey=s,t.group=c,t.index=d,t.maxValue=r,t.minValue=o,t.normalizeTreeToArray=l,t.requireVersion=g,t.sort=f,t.sum=p,Object.defineProperty(t,"__esModule",{value:!0})}));
{
"name": "chartjs-chart-treemap",
"homepage": "https://chartjs-chart-treemap.pages.dev/",
"version": "2.0.2",
"version": "2.1.0",
"description": "Chart.js module for creating treemap charts",

@@ -13,2 +13,3 @@ "main": "dist/chartjs-chart-treemap.js",

"dev": "karma start --no-signle-run --auto-watch --browsers chrome",
"dev:ff": "karma start --no-signle-run --auto-watch --browsers firefox",
"docs": "npm run build && vuepress build docs --no-cache",

@@ -22,2 +23,3 @@ "docs:dev": "npm run build && vuepress dev docs --no-cache",

"test-lint": "npm run lint",
"test-types": "tsc -p types/tests/",
"test-karma": "karma start --auto-watch --single-run"

@@ -44,5 +46,5 @@ },

"devDependencies": {
"@rollup/plugin-commonjs": "^21.0.1",
"@rollup/plugin-json": "^4.1.0",
"@rollup/plugin-node-resolve": "^13.0.0",
"@rollup/plugin-commonjs": "^23.0.0",
"@rollup/plugin-json": "^5.0.0",
"@rollup/plugin-node-resolve": "^15.0.0",
"@typescript-eslint/eslint-plugin": "^5.4.0",

@@ -52,4 +54,6 @@ "@typescript-eslint/parser": "^5.4.0",

"chartjs-adapter-date-fns": "^2.0.0",
"chartjs-test-utils": "^0.3.0",
"concurrently": "^6.0.1",
"chartjs-plugin-datalabels": "^2.0.0",
"chartjs-plugin-zoom": "^1.2.0",
"chartjs-test-utils": "^0.5.0",
"concurrently": "^7.4.0",
"cross-env": "^7.0.3",

@@ -60,5 +64,5 @@ "date-fns": "^2.20.2",

"eslint-plugin-es": "^4.1.0",
"eslint-plugin-html": "^6.1.2",
"eslint-plugin-markdown": "^2.0.1",
"jasmine-core": "^3.7.1",
"eslint-plugin-html": "^7.1.0",
"eslint-plugin-markdown": "^3.0.0",
"jasmine-core": "^4.4.0",
"karma": "^6.3.2",

@@ -68,9 +72,9 @@ "karma-chrome-launcher": "^3.1.0",

"karma-firefox-launcher": "^2.1.0",
"karma-jasmine": "^4.0.1",
"karma-jasmine-html-reporter": "^1.5.4",
"karma-rollup-preprocessor": "^7.0.7",
"karma-spec-reporter": "0.0.32",
"karma-jasmine": "^5.1.0",
"karma-jasmine-html-reporter": "^2.0.0",
"karma-rollup-preprocessor": "7.0.7",
"karma-spec-reporter": "^0.0.34",
"karma-summary-reporter": "^3.0.0",
"pixelmatch": "^5.2.1",
"rollup": "^2.45.1",
"rollup": "^2.79.1",
"rollup-plugin-analyzer": "^4.0.0",

@@ -77,0 +81,0 @@ "rollup-plugin-istanbul": "^3.0.0",

@@ -5,5 +5,6 @@ import {

DatasetController,
Element,
Element, VisualElement,
ScriptableContext, Color, Scriptable, FontSpec
} from 'chart.js';
import { AnyObject } from 'chart.js/types/basic';

@@ -27,8 +28,9 @@ type TreemapScriptableContext = ScriptableContext<'treemap'> & {

align?: Scriptable<LabelAlign, TreemapScriptableContext>,
color?: Scriptable<Color, TreemapScriptableContext>,
color?: Scriptable<Color | Color[], TreemapScriptableContext>,
display?: boolean;
formatter?: Scriptable<string | Array<string>, TreemapScriptableContext>,
font?: FontSpec,
hoverColor?: Scriptable<Color, TreemapScriptableContext>,
hoverFont?: FontSpec,
font?: Scriptable<FontSpec | FontSpec[], TreemapScriptableContext>,
hoverColor?: Scriptable<Color | Color[], TreemapScriptableContext>,
hoverFont?: Scriptable<FontSpec | FontSpec[], TreemapScriptableContext>,
overflow?: Scriptable<LabelOverflow, TreemapScriptableContext>
padding?: number,

@@ -42,2 +44,4 @@ position?: Scriptable<LabelPosition, TreemapScriptableContext>

export type LabelOverflow = 'cut' | 'hidden';
type TreemapControllerDatasetDividersOptions = {

@@ -71,3 +75,4 @@ display?: boolean,

groups?: Array<keyof DType>;
tree: number[] | DType[];
tree: number[] | DType[] | AnyObject;
treeLeafKey?: keyof DType;
key?: keyof DType;

@@ -114,3 +119,3 @@ }

defaultDataPoint: TreemapDataPoint;
metaExtensions: {};
metaExtensions: AnyObject;
parsedDataType: unknown,

@@ -125,3 +130,3 @@ scales: never;

type TreemapOptions = {
export interface TreemapOptions {
backgroundColor: Color;

@@ -132,3 +137,3 @@ borderColor: Color;

type TreemapConfig = {
export interface TreemapConfig {
x: number;

@@ -146,3 +151,7 @@ y: number;

export type TreemapElement = Element<TreemapConfig, TreemapOptions>;
export interface TreemapElement<
T extends TreemapConfig = TreemapConfig,
O extends TreemapOptions = TreemapOptions
> extends Element<T, O>, VisualElement {}
export const TreemapElement: ChartComponent & {

@@ -149,0 +158,0 @@ prototype: TreemapElement;

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc