Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@sgratzl/chartjs-chart-boxplot

Package Overview
Dependencies
Maintainers
1
Versions
52
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@sgratzl/chartjs-chart-boxplot - npm Package Compare versions

Comparing version 4.3.3 to 4.4.0

27

build/index.d.ts

@@ -8,3 +8,3 @@ /**

import { TooltipModel, Element, ChartType, ScriptableAndArrayOptions, CommonHoverOptions, ScriptableContext, BarController, Scale, ChartMeta, UpdateMode, CartesianScaleTypeRegistry, ControllerDatasetOptions, AnimationOptions, Chart, ChartItem, ChartConfiguration } from 'chart.js';
import { TooltipModel, Element, ChartType, ScriptableAndArrayOptions, CommonHoverOptions, ScriptableContext, BarController, Scale, ChartMeta, UpdateMode, CartesianScaleTypeRegistry, ControllerDatasetOptions, BarControllerDatasetOptions, AnimationOptions, Chart, ChartItem, ChartConfiguration } from 'chart.js';

@@ -16,2 +16,6 @@ interface ExtendedTooltip extends TooltipModel<'boxplot' | 'violin'> {

};
_tooltipItem?: {
index: number;
datasetIndex: number;
};
}

@@ -33,2 +37,3 @@

itemBorderWidth: number;
itemHitRadius: number;
hitPadding: number;

@@ -75,3 +80,12 @@ outlierHitRadius: number;

inYRange(mouseY: number, useFinalPosition?: boolean): boolean;
protected _outlierIndexInRange(mouseX: number, mouseY: number, useFinalPosition?: boolean): number;
protected _outlierIndexInRange(mouseX: number, mouseY: number, useFinalPosition?: boolean): {
index: number;
x: number;
y: number;
} | null;
protected _itemIndexInRange(mouseX: number, mouseY: number, useFinalPosition?: boolean): {
index: number;
x: number;
y: number;
} | null;
protected _boxInRange(mouseX: number, mouseY: number, useFinalPosition?: boolean): boolean;

@@ -126,2 +140,3 @@ getCenterPoint(useFinalPosition?: boolean): {

itemBorderWidth: number;
itemHitRadius: number;
meanStyle: string;

@@ -144,3 +159,3 @@ meanRadius: number;

interface ElementOptionsByType<TType extends ChartType> {
boxplot: ScriptableAndArrayOptions<IBoxAndWhiskersOptions & CommonHoverOptions, ScriptableContext<TType>>;
boxandwhiskers: ScriptableAndArrayOptions<IBoxAndWhiskersOptions & CommonHoverOptions, ScriptableContext<TType>>;
}

@@ -214,2 +229,3 @@ }

itemBorderWidth: number;
itemHitRadius: number;
meanStyle: string;

@@ -252,2 +268,3 @@ meanRadius: number;

hoveredOutlierIndex: number;
hoveredItemIndex: number;
} & S;

@@ -266,3 +283,3 @@ };

}
interface BoxPlotControllerDatasetOptions extends ControllerDatasetOptions, IBoxplotOptions, ScriptableAndArrayOptions<IBoxAndWhiskersOptions, ScriptableContext<'boxplot'>>, ScriptableAndArrayOptions<CommonHoverOptions, ScriptableContext<'boxplot'>>, AnimationOptions<'boxplot'> {
interface BoxPlotControllerDatasetOptions extends ControllerDatasetOptions, Pick<BarControllerDatasetOptions, 'barPercentage' | 'barThickness' | 'categoryPercentage' | 'maxBarThickness' | 'minBarLength'>, IBoxplotOptions, ScriptableAndArrayOptions<IBoxAndWhiskersOptions, ScriptableContext<'boxplot'>>, ScriptableAndArrayOptions<CommonHoverOptions, ScriptableContext<'boxplot'>>, AnimationOptions<'boxplot'> {
}

@@ -297,3 +314,3 @@ type BoxPlotDataPoint = number[] | (Partial<IBoxPlot> & Pick<IBoxPlot, 'min' | 'max' | 'median' | 'q1' | 'q3'>);

type ViolinDataPoint = number[] | (Partial<IViolin> & Pick<IViolin, 'median' | 'coords'>);
interface ViolinControllerDatasetOptions extends ControllerDatasetOptions, IViolinOptions, ScriptableAndArrayOptions<IViolinElementOptions, ScriptableContext<'violin'>>, ScriptableAndArrayOptions<CommonHoverOptions, ScriptableContext<'violin'>>, AnimationOptions<'violin'> {
interface ViolinControllerDatasetOptions extends ControllerDatasetOptions, Pick<BarControllerDatasetOptions, 'barPercentage' | 'barThickness' | 'categoryPercentage' | 'maxBarThickness' | 'minBarLength'>, IViolinOptions, ScriptableAndArrayOptions<IViolinElementOptions, ScriptableContext<'violin'>>, ScriptableAndArrayOptions<CommonHoverOptions, ScriptableContext<'violin'>>, AnimationOptions<'violin'> {
}

@@ -300,0 +317,0 @@ interface IViolinChartOptions extends IViolinOptions {

89

build/index.js

@@ -173,2 +173,3 @@ /**

itemBorderWidth: 0,
itemHitRadius: 0,
meanStyle: 'circle',

@@ -302,3 +303,4 @@ meanRadius: 3,

return (this._boxInRange(mouseX, mouseY, useFinalPosition) ||
this._outlierIndexInRange(mouseX, mouseY, useFinalPosition) >= 0);
this._outlierIndexInRange(mouseX, mouseY, useFinalPosition) != null ||
this._itemIndexInRange(mouseX, mouseY, useFinalPosition) != null);
}

@@ -319,3 +321,3 @@ inXRange(mouseX, useFinalPosition) {

if ((vertical && Math.abs(mouseX - props.x) > hitRadius) || (!vertical && Math.abs(mouseY - props.y) > hitRadius)) {
return -1;
return null;
}

@@ -325,7 +327,44 @@ const toCompare = vertical ? mouseY : mouseX;

if (Math.abs(outliers[i] - toCompare) <= hitRadius) {
return i;
return vertical ? { index: i, x: props.x, y: outliers[i] } : { index: i, x: outliers[i], y: props.y };
}
}
return -1;
return null;
}
_itemIndexInRange(mouseX, mouseY, useFinalPosition) {
const hitRadius = this.options.itemHitRadius;
if (hitRadius <= 0) {
return null;
}
const props = this.getProps(['x', 'y', 'items', 'width', 'height', 'outliers'], useFinalPosition);
const vert = this.isVertical();
const { options } = this;
if (options.itemRadius <= 0 || !props.items || props.items.length <= 0) {
return null;
}
const random = rnd(this._datasetIndex * 1000 + this._index);
const outliers = new Set(props.outliers || []);
if (vert) {
for (let i = 0; i < props.items.length; i++) {
const y = props.items[i];
if (!outliers.has(y)) {
const x = props.x - props.width / 2 + random() * props.width;
if (Math.abs(x - mouseX) <= hitRadius && Math.abs(y - mouseY) <= hitRadius) {
return { index: i, x, y };
}
}
}
}
else {
for (let i = 0; i < props.items.length; i++) {
const x = props.items[i];
if (!outliers.has(x)) {
const y = props.y - props.height / 2 + random() * props.height;
if (Math.abs(x - mouseX) <= hitRadius && Math.abs(y - mouseY) <= hitRadius) {
return { index: i, x, y };
}
}
}
}
return null;
}
_boxInRange(mouseX, mouseY, useFinalPosition) {

@@ -352,22 +391,27 @@ const bounds = this._getHitBounds(useFinalPosition);

delete tooltip._tooltipOutlier;
delete tooltip._tooltipItem;
}
const props = this.getProps(['x', 'y']);
const index = this._outlierIndexInRange(eventPosition.x, eventPosition.y);
if (index < 0 || !tooltip) {
return this.getCenterPoint();
const info = this._outlierIndexInRange(eventPosition.x, eventPosition.y);
if (info != null && tooltip) {
tooltip._tooltipOutlier = {
index: info.index,
datasetIndex: this._datasetIndex,
};
return {
x: info.x,
y: info.y,
};
}
tooltip._tooltipOutlier = {
index,
datasetIndex: this._datasetIndex,
};
if (this.isVertical()) {
const itemInfo = this._itemIndexInRange(eventPosition.x, eventPosition.y);
if (itemInfo != null && tooltip) {
tooltip._tooltipItem = {
index: itemInfo.index,
datasetIndex: this._datasetIndex,
};
return {
x: props.x,
y: this._getOutliers()[index],
x: itemInfo.x,
y: itemInfo.y,
};
}
return {
x: this._getOutliers()[index],
y: props.y,
};
return this.getCenterPoint();
}

@@ -666,2 +710,5 @@ };

}
if (value && that._tooltipItem != null && item.datasetIndex === that._tooltipItem.datasetIndex) {
value.hoveredItemIndex = that._tooltipItem.index;
}
}

@@ -803,2 +850,3 @@ function outlierPositioner(items, eventPosition) {

hoveredOutlierIndex: -1,
hoveredItemIndex: -1,
};

@@ -811,2 +859,5 @@ this._transformStats(r.value, parsed, (v) => vScale.getLabelForValue(v));

}
if (this.hoveredItemIndex >= 0) {
return `(item: ${this.items[this.hoveredItemIndex]})`;
}
return s;

@@ -813,0 +864,0 @@ };

@@ -447,2 +447,5 @@ /**

}
if (value && that._tooltipItem != null && item.datasetIndex === that._tooltipItem.datasetIndex) {
value.hoveredItemIndex = that._tooltipItem.index;
}
}

@@ -584,2 +587,3 @@ function outlierPositioner(items, eventPosition) {

hoveredOutlierIndex: -1,
hoveredItemIndex: -1,
};

@@ -592,2 +596,5 @@ this._transformStats(r.value, parsed, (v) => vScale.getLabelForValue(v));

}
if (this.hoveredItemIndex >= 0) {
return `(item: ${this.items[this.hoveredItemIndex]})`;
}
return s;

@@ -621,2 +628,3 @@ };

itemBorderWidth: 0,
itemHitRadius: 0,
meanStyle: 'circle',

@@ -750,3 +758,4 @@ meanRadius: 3,

return (this._boxInRange(mouseX, mouseY, useFinalPosition) ||
this._outlierIndexInRange(mouseX, mouseY, useFinalPosition) >= 0);
this._outlierIndexInRange(mouseX, mouseY, useFinalPosition) != null ||
this._itemIndexInRange(mouseX, mouseY, useFinalPosition) != null);
}

@@ -767,3 +776,3 @@ inXRange(mouseX, useFinalPosition) {

if ((vertical && Math.abs(mouseX - props.x) > hitRadius) || (!vertical && Math.abs(mouseY - props.y) > hitRadius)) {
return -1;
return null;
}

@@ -773,7 +782,44 @@ const toCompare = vertical ? mouseY : mouseX;

if (Math.abs(outliers[i] - toCompare) <= hitRadius) {
return i;
return vertical ? { index: i, x: props.x, y: outliers[i] } : { index: i, x: outliers[i], y: props.y };
}
}
return -1;
return null;
}
_itemIndexInRange(mouseX, mouseY, useFinalPosition) {
const hitRadius = this.options.itemHitRadius;
if (hitRadius <= 0) {
return null;
}
const props = this.getProps(['x', 'y', 'items', 'width', 'height', 'outliers'], useFinalPosition);
const vert = this.isVertical();
const { options } = this;
if (options.itemRadius <= 0 || !props.items || props.items.length <= 0) {
return null;
}
const random = rnd(this._datasetIndex * 1000 + this._index);
const outliers = new Set(props.outliers || []);
if (vert) {
for (let i = 0; i < props.items.length; i++) {
const y = props.items[i];
if (!outliers.has(y)) {
const x = props.x - props.width / 2 + random() * props.width;
if (Math.abs(x - mouseX) <= hitRadius && Math.abs(y - mouseY) <= hitRadius) {
return { index: i, x, y };
}
}
}
}
else {
for (let i = 0; i < props.items.length; i++) {
const x = props.items[i];
if (!outliers.has(x)) {
const y = props.y - props.height / 2 + random() * props.height;
if (Math.abs(x - mouseX) <= hitRadius && Math.abs(y - mouseY) <= hitRadius) {
return { index: i, x, y };
}
}
}
}
return null;
}
_boxInRange(mouseX, mouseY, useFinalPosition) {

@@ -800,22 +846,27 @@ const bounds = this._getHitBounds(useFinalPosition);

delete tooltip._tooltipOutlier;
delete tooltip._tooltipItem;
}
const props = this.getProps(['x', 'y']);
const index = this._outlierIndexInRange(eventPosition.x, eventPosition.y);
if (index < 0 || !tooltip) {
return this.getCenterPoint();
const info = this._outlierIndexInRange(eventPosition.x, eventPosition.y);
if (info != null && tooltip) {
tooltip._tooltipOutlier = {
index: info.index,
datasetIndex: this._datasetIndex,
};
return {
x: info.x,
y: info.y,
};
}
tooltip._tooltipOutlier = {
index,
datasetIndex: this._datasetIndex,
};
if (this.isVertical()) {
const itemInfo = this._itemIndexInRange(eventPosition.x, eventPosition.y);
if (itemInfo != null && tooltip) {
tooltip._tooltipItem = {
index: itemInfo.index,
datasetIndex: this._datasetIndex,
};
return {
x: props.x,
y: this._getOutliers()[index],
x: itemInfo.x,
y: itemInfo.y,
};
}
return {
x: this._getOutliers()[index],
y: props.y,
};
return this.getCenterPoint();
}

@@ -822,0 +873,0 @@ }

@@ -1,2 +0,2 @@

!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).ChartBoxPlot={},t.Chart,t.Chart.helpers)}(this,(function(t,e,r){"use strict";const i=Math.sqrt(2*Math.PI);function o(t){const e=t.items.length,r=function(t,e,r){let i=Math.sqrt(function(t,e){return t*e/(e-1)}(e,r));return"number"==typeof t&&(i=Math.min(i,t/1.34)),1.06*i*Math.pow(r,-.2)}(t.iqr,t.variance,e);return o=>{let n=0,s=0;for(n=0;n<e;n++){const e=t.items[n];s+=(a=(o-e)/r,Math.exp(-.5*a*a)/i)}var a;return s/r/e}}function n(t,e,r){const i=e-1,o=e=>{const o=e*i,n=Math.floor(o),s=o-n,a=t[n];return 0===s?a:r(a,t[Math.min(n+1,i)],s)};return{q1:o(.25),median:o(.5),q3:o(.75)}}function s(t,e=t.length){return n(t,e,((t,e,r)=>t+r*(e-t)))}function a(t,e=t.length){return n(t,e,((t,e,r)=>t+(e-t)*r))}function l(t,e=t.length){return n(t,e,(t=>t))}function u(t,e=t.length){return n(t,e,((t,e)=>e))}function d(t,e=t.length){return n(t,e,((t,e,r)=>r<.5?t:e))}function m(t,e=t.length){return n(t,e,((t,e)=>.5*(t+e)))}function h(t,e=t.length){const r=e,i=Math.floor((r+3)/2)/2,o=e=>.5*(t[Math.floor(e)-1]+t[Math.ceil(e)-1]);return{q1:o(i),median:o((r+1)/2),q3:o(r+1-i)}}function c(t,e=t.length){return h(t,e)}function f(t,e,r,i,{eps:o,quantiles:n,coef:s,whiskersMode:a}){const l=(t,e)=>Math.abs(t-e)<o,{median:u,q1:d,q3:m}=n(t,e),h=m-d,c="number"==typeof s&&s>0;let f=c?Math.max(r,d-s*h):r,g=c?Math.min(i,m+s*h):i;const p=[];for(let r=0;r<e;r+=1){const e=t[r];if(e>=f||l(e,f)){"nearest"===a&&(f=e);break}0!==p.length&&l(p[p.length-1],e)||p.push(e)}const x=[];for(let r=e-1;r>=0;r-=1){const e=t[r];if(e<=g||l(e,g)){"nearest"===a&&(g=e);break}0!==x.length&&l(x[x.length-1],e)||0!==p.length&&l(p[p.length-1],e)||x.push(e)}return{median:u,q1:d,q3:m,iqr:h,outlier:p.concat(x.reverse()),whiskerHigh:g,whiskerLow:f}}function g(t,e){let r=0;for(let i=0;i<e;i++){r+=t[i]}r/=e;let i=0;for(let o=0;o<e;o++){const e=t[o];i+=(e-r)*(e-r)}return i/=e,{mean:r,variance:i}}function p(t,e={}){const r={coef:1.5,eps:.01,quantiles:s,validAndSorted:!1,whiskersMode:"nearest",...e},{missing:i,s:n,min:a,max:l}=r.validAndSorted?function(t){return 0===t.length?{min:Number.NaN,max:Number.NaN,missing:0,s:[]}:{min:t[0],max:t[t.length-1],missing:0,s:t}}(t):function(t){let e=0;const{length:r}=t,i=t instanceof Float64Array?new Float64Array(r):new Float32Array(r);for(let o=0;o<r;o+=1){const r=t[o];null==r||Number.isNaN(r)||(i[e]=r,e+=1)}const o=r-e;if(0===e)return{min:Number.NaN,max:Number.NaN,missing:o,s:[]};const n=e===r?i:i.subarray(0,e);return n.sort(((t,e)=>t===e?0:t<e?-1:1)),{min:n[0],max:n[n.length-1],missing:o,s:n}}(t),u={min:Number.NaN,max:Number.NaN,mean:Number.NaN,missing:i,iqr:Number.NaN,count:t.length,whiskerHigh:Number.NaN,whiskerLow:Number.NaN,outlier:[],median:Number.NaN,q1:Number.NaN,q3:Number.NaN,variance:0,items:[],kde:()=>0},d=t.length-i;if(0===d)return u;const m={min:a,max:l,count:t.length,missing:i,items:n,...g(n,d),...f(n,d,a,l,r)};return{...m,kde:o(m)}}const x={coef:1.5,quantiles:7,whiskersMode:"nearest"};function y(t){const e=null==t||"number"!=typeof t.coef?x.coef:t.coef,r=function(t){return"function"==typeof t?t:{hinges:c,fivenum:h,7:s,quantiles:s,linear:a,lower:l,higher:u,nearest:d,midpoint:m}[t]||s}(null==t||null==t.quantiles?s:t.quantiles);return{coef:e,quantiles:r,whiskersMode:null==t||"string"!=typeof t.whiskersMode?x.whiskersMode:t.whiskersMode}}function w(t,e){if(t){if("number"==typeof t.median&&"number"==typeof t.q1&&"number"==typeof t.q3){if(void 0===t.whiskerMin){const{coef:r}=y(e),{whiskerMin:i,whiskerMax:o}=function(t,e,r=1.5){const i=t.q3-t.q1,o="number"==typeof r&&r>0;let n=o?Math.max(t.min,t.q1-r*i):t.min,s=o?Math.min(t.max,t.q3+r*i):t.max;if(Array.isArray(e)){for(let t=0;t<e.length;t+=1){const r=e[t];if(r>=n){n=r;break}}for(let t=e.length-1;t>=0;t-=1){const r=e[t];if(r<=s){s=r;break}}}return{whiskerMin:n,whiskerMax:s}}(t,Array.isArray(t.items)?t.items.slice().sort(((t,e)=>t-e)):null,r);t.whiskerMin=i,t.whiskerMax=o}return t}if(Array.isArray(t))return function(t,e){const r=p("undefined"==typeof Float64Array||t instanceof Float32Array||t instanceof Float64Array?t:Float64Array.from(t),y(e));return{items:Array.from(r.items),outliers:r.outlier,whiskerMax:r.whiskerHigh,whiskerMin:r.whiskerLow,max:r.max,median:r.median,mean:r.mean,min:r.min,q1:r.q1,q3:r.q3}}(t,e)}}function b(t,e){if(t){if("number"==typeof t.median&&Array.isArray(t.coords))return t;if(Array.isArray(t))return function(t,e){if(0===t.length)return;const r=p("undefined"==typeof Float64Array||t instanceof Float32Array||t instanceof Float64Array?t:Float64Array.from(t),y(e)),i=function(t,e,r){const i=[],o=(e-t)/r;for(let r=t;r<=e&&o>0;r+=o)i.push(r);return i[i.length-1]!==e&&i.push(e),i}(r.min,r.max,e.points).map((t=>({v:t,estimate:r.kde(t)}))),o=i.reduce(((t,e)=>Math.max(t,e.estimate)),Number.NEGATIVE_INFINITY);return{max:r.max,min:r.min,mean:r.mean,median:r.median,q1:r.q1,q3:r.q3,items:Array.from(r.items),coords:i,outliers:[],maxEstimate:o}}(t,e)}}const k={number:(t,e,r)=>t===e||null==t?e:null==e?t:t+(e-t)*r};function q(t,e,r){return"number"==typeof t&&"number"==typeof e?k.number(t,e,r):Array.isArray(t)&&Array.isArray(e)?e.map(((e,i)=>k.number(t[i],e,r))):e}function M(t){const e=t.formattedValue,r=this;e&&null!=r._tooltipOutlier&&t.datasetIndex===r._tooltipOutlier.datasetIndex&&(e.hoveredOutlierIndex=r._tooltipOutlier.index)}function C(t,e){if(!t.length)return!1;let r=0,i=0,o=0;for(let n=0;n<t.length;n+=1){const s=t[n].element;if(s&&s.hasValue()){const t=s.tooltipPosition(e,this);r+=t.x,i+=t.y,o+=1}}return{x:r/o,y:i/o}}function v(t){const e=["borderColor","backgroundColor"].concat(t.filter((t=>t.endsWith("Color"))));return{animations:{numberArray:{fn:q,properties:["outliers","items"]},colors:{type:"color",properties:e}},transitions:{show:{animations:{colors:{type:"color",properties:e,from:"transparent"}}},hide:{animations:{colors:{type:"color",properties:e,to:"transparent"}}}},minStats:"min",maxStats:"max",...x}}function N(){return{plugins:{tooltip:{position:C.register().id,callbacks:{beforeLabel:M}}}}}C.id="average",C.register=()=>(e.Tooltip.positioners.average=C,C);let B=class extends e.BarController{_transformStats(t,e,r){for(const i of["min","max","median","q3","q1","mean"]){const o=e[i];"number"==typeof o&&(t[i]=r(o))}for(const i of["outliers","items"])Array.isArray(e[i])&&(t[i]=e[i].map(r))}getMinMax(t,e){const r=t.axis,i=this.options;t.axis=i.minStats;const{min:o}=super.getMinMax(t,e);t.axis=i.maxStats;const{max:n}=super.getMinMax(t,e);return t.axis=r,{min:o,max:n}}parsePrimitiveData(t,e,r,i){const o=t.vScale,n=t.iScale,s=n.getLabels(),a=[];for(let t=0;t<i;t+=1){const i=t+r,l={};l[n.axis]=n.parse(s[i],i);const u=this._parseStats(null==e?null:e[i],this.options);u&&(Object.assign(l,u),l[o.axis]=u.median),a.push(l)}return a}parseArrayData(t,e,r,i){return this.parsePrimitiveData(t,e,r,i)}parseObjectData(t,e,r,i){return this.parsePrimitiveData(t,e,r,i)}getLabelAndValue(t){const e=super.getLabelAndValue(t),{vScale:r}=this._cachedMeta,i=this.getParsed(t);if(!r||!i||"NaN"===e.value)return e;e.value={raw:i,hoveredOutlierIndex:-1},this._transformStats(e.value,i,(t=>r.getLabelForValue(t)));const o=this._toStringStats(e.value.raw);return e.value.toString=function(){return this.hoveredOutlierIndex>=0?`(outlier: ${this.outliers[this.hoveredOutlierIndex]})`:o},e}_toStringStats(t){const e=t=>null==t?"NaN":r.formatNumber(t,this.chart.options.locale,{});return`(min: ${e(t.min)}, 25% quantile: ${e(t.q1)}, median: ${e(t.median)}, mean: ${e(t.mean)}, 75% quantile: ${e(t.q3)}, max: ${e(t.max)})`}updateElement(t,e,r,i){const o="reset"===i,n=this._cachedMeta.vScale,s=this.getParsed(e),a=n.getBasePixel();r._datasetIndex=this.index,r._index=e,this._transformStats(r,s,(t=>o?a:n.getPixelForValue(t,e))),super.updateElement(t,e,r,i)}};const _={borderWidth:1,outlierStyle:"circle",outlierRadius:2,outlierBorderWidth:1,itemStyle:"circle",itemRadius:0,itemBorderWidth:0,meanStyle:"circle",meanRadius:3,meanBorderWidth:1,hitPadding:2,outlierHitRadius:4},S={outlierBackgroundColor:"backgroundColor",outlierBorderColor:"borderColor",itemBackgroundColor:"backgroundColor",itemBorderColor:"borderColor",meanBackgroundColor:"backgroundColor",meanBorderColor:"borderColor"},P=Object.keys(_).concat(Object.keys(S));class A extends e.Element{isVertical(){return!this.horizontal}_drawItems(t){const e=this.isVertical(),i=this.getProps(["x","y","items","width","height","outliers"]),{options:o}=this;if(o.itemRadius<=0||!i.items||i.items.length<=0)return;t.save(),t.strokeStyle=o.itemBorderColor,t.fillStyle=o.itemBackgroundColor,t.lineWidth=o.itemBorderWidth;const n=function(t=Date.now()){let e=t;return()=>(e=(9301*e+49297)%233280,e/233280)}(1e3*this._datasetIndex+this._index),s={pointStyle:o.itemStyle,radius:o.itemRadius,borderWidth:o.itemBorderWidth},a=new Set(i.outliers||[]);e?i.items.forEach((e=>{a.has(e)||r.drawPoint(t,s,i.x-i.width/2+n()*i.width,e)})):i.items.forEach((e=>{a.has(e)||r.drawPoint(t,s,e,i.y-i.height/2+n()*i.height)})),t.restore()}_drawOutliers(t){const e=this.isVertical(),i=this.getProps(["x","y","outliers"]),{options:o}=this;if(o.outlierRadius<=0||!i.outliers||0===i.outliers.length)return;t.save(),t.fillStyle=o.outlierBackgroundColor,t.strokeStyle=o.outlierBorderColor,t.lineWidth=o.outlierBorderWidth;const n={pointStyle:o.outlierStyle,radius:o.outlierRadius,borderWidth:o.outlierBorderWidth};e?i.outliers.forEach((e=>{r.drawPoint(t,n,i.x,e)})):i.outliers.forEach((e=>{r.drawPoint(t,n,e,i.y)})),t.restore()}_drawMeanDot(t){const e=this.isVertical(),i=this.getProps(["x","y","mean"]),{options:o}=this;if(o.meanRadius<=0||null==i.mean||Number.isNaN(i.mean))return;t.save(),t.fillStyle=o.meanBackgroundColor,t.strokeStyle=o.meanBorderColor,t.lineWidth=o.meanBorderWidth;const n={pointStyle:o.meanStyle,radius:o.meanRadius,borderWidth:o.meanBorderWidth};e?r.drawPoint(t,n,i.x,i.mean):r.drawPoint(t,n,i.mean,i.y),t.restore()}_getBounds(t){return{left:0,top:0,right:0,bottom:0}}_getHitBounds(t){const e=this.options.hitPadding,r=this._getBounds(t);return{left:r.left-e,top:r.top-e,right:r.right+e,bottom:r.bottom+e}}inRange(t,e,r){return(!Number.isNaN(this.x)||!Number.isNaN(this.y))&&(this._boxInRange(t,e,r)||this._outlierIndexInRange(t,e,r)>=0)}inXRange(t,e){const r=this._getHitBounds(e);return t>=r.left&&t<=r.right}inYRange(t,e){const r=this._getHitBounds(e);return t>=r.top&&t<=r.bottom}_outlierIndexInRange(t,e,r){const i=this.getProps(["x","y"],r),o=this.options.outlierHitRadius,n=this._getOutliers(r),s=this.isVertical();if(s&&Math.abs(t-i.x)>o||!s&&Math.abs(e-i.y)>o)return-1;const a=s?e:t;for(let t=0;t<n.length;t+=1)if(Math.abs(n[t]-a)<=o)return t;return-1}_boxInRange(t,e,r){const i=this._getHitBounds(r);return t>=i.left&&t<=i.right&&e>=i.top&&e<=i.bottom}getCenterPoint(t){const e=this.getProps(["x","y"],t);return{x:e.x,y:e.y}}_getOutliers(t){return this.getProps(["outliers"],t).outliers||[]}tooltipPosition(t,e){if(!t||"boolean"==typeof t)return this.getCenterPoint();e&&delete e._tooltipOutlier;const r=this.getProps(["x","y"]),i=this._outlierIndexInRange(t.x,t.y);return i<0||!e?this.getCenterPoint():(e._tooltipOutlier={index:i,datasetIndex:this._datasetIndex},this.isVertical()?{x:r.x,y:this._getOutliers()[i]}:{x:this._getOutliers()[i],y:r.y})}}const T=P.concat(["medianColor","lowerBackgroundColor"]);class R extends A{draw(t){t.save(),t.fillStyle=this.options.backgroundColor,t.strokeStyle=this.options.borderColor,t.lineWidth=this.options.borderWidth,this._drawBoxPlot(t),this._drawOutliers(t),this._drawMeanDot(t),t.restore(),this._drawItems(t)}_drawBoxPlot(t){this.isVertical()?this._drawBoxPlotVertical(t):this._drawBoxPlotHorizontal(t)}_drawBoxPlotVertical(t){const{options:e}=this,r=this.getProps(["x","width","q1","q3","median","whiskerMin","whiskerMax"]),{x:i}=r,{width:o}=r,n=i-o/2;r.q3>r.q1?t.fillRect(n,r.q1,o,r.q3-r.q1):t.fillRect(n,r.q3,o,r.q1-r.q3),t.save(),e.medianColor&&"transparent"!==e.medianColor&&"#0000"!==e.medianColor&&(t.strokeStyle=e.medianColor),t.beginPath(),t.moveTo(n,r.median),t.lineTo(n+o,r.median),t.closePath(),t.stroke(),t.restore(),t.save(),e.lowerBackgroundColor&&"transparent"!==e.lowerBackgroundColor&&"#0000"!==e.lowerBackgroundColor&&(t.fillStyle=e.lowerBackgroundColor,r.q3>r.q1?t.fillRect(n,r.median,o,r.q3-r.median):t.fillRect(n,r.median,o,r.q1-r.median)),t.restore(),r.q3>r.q1?t.strokeRect(n,r.q1,o,r.q3-r.q1):t.strokeRect(n,r.q3,o,r.q1-r.q3),t.beginPath(),t.moveTo(n,r.whiskerMin),t.lineTo(n+o,r.whiskerMin),t.moveTo(i,r.whiskerMin),t.lineTo(i,r.q1),t.moveTo(n,r.whiskerMax),t.lineTo(n+o,r.whiskerMax),t.moveTo(i,r.whiskerMax),t.lineTo(i,r.q3),t.closePath(),t.stroke()}_drawBoxPlotHorizontal(t){const{options:e}=this,r=this.getProps(["y","height","q1","q3","median","whiskerMin","whiskerMax"]),{y:i}=r,{height:o}=r,n=i-o/2;r.q3>r.q1?t.fillRect(r.q1,n,r.q3-r.q1,o):t.fillRect(r.q3,n,r.q1-r.q3,o),t.save(),e.medianColor&&"transparent"!==e.medianColor&&(t.strokeStyle=e.medianColor),t.beginPath(),t.moveTo(r.median,n),t.lineTo(r.median,n+o),t.closePath(),t.stroke(),t.restore(),t.save(),e.lowerBackgroundColor&&"transparent"!==e.lowerBackgroundColor&&(t.fillStyle=e.lowerBackgroundColor,r.q3>r.q1?t.fillRect(r.median,n,r.q3-r.median,o):t.fillRect(r.median,n,r.q1-r.median,o)),t.restore(),r.q3>r.q1?t.strokeRect(r.q1,n,r.q3-r.q1,o):t.strokeRect(r.q3,n,r.q1-r.q3,o),t.beginPath(),t.moveTo(r.whiskerMin,n),t.lineTo(r.whiskerMin,n+o),t.moveTo(r.whiskerMin,i),t.lineTo(r.q1,i),t.moveTo(r.whiskerMax,n),t.lineTo(r.whiskerMax,n+o),t.moveTo(r.whiskerMax,i),t.lineTo(r.q3,i),t.closePath(),t.stroke()}_getBounds(t){const e=this.isVertical();if(null==this.x)return{left:0,top:0,right:0,bottom:0};if(e){const{x:e,width:r,whiskerMax:i,whiskerMin:o}=this.getProps(["x","width","whiskerMin","whiskerMax"],t),n=e-r/2;return{left:n,top:i,right:n+r,bottom:o}}const{y:r,height:i,whiskerMax:o,whiskerMin:n}=this.getProps(["y","height","whiskerMin","whiskerMax"],t),s=r-i/2;return{left:n,top:s,right:o,bottom:s+i}}}R.id="boxandwhiskers",R.defaults={...e.BarElement.defaults,..._,medianColor:"transparent",lowerBackgroundColor:"transparent"},R.defaultRoutes={...e.BarElement.defaultRoutes,...S};class E extends A{draw(t){t.save(),t.fillStyle=this.options.backgroundColor,t.strokeStyle=this.options.borderColor,t.lineWidth=this.options.borderWidth;const e=this.getProps(["x","y","median","width","height","min","max","coords","maxEstimate"]);null!=e.median&&r.drawPoint(t,{pointStyle:"rectRot",radius:5,borderWidth:this.options.borderWidth},e.x,e.y),e.coords&&e.coords.length>0&&this._drawCoords(t,e),this._drawOutliers(t),this._drawMeanDot(t),t.restore(),this._drawItems(t)}_drawCoords(t,e){let r;if(r=null==e.maxEstimate?e.coords.reduce(((t,e)=>Math.max(t,e.estimate)),Number.NEGATIVE_INFINITY):e.maxEstimate,this.isVertical()){const{x:i,width:o}=e,n=o/2/r;t.moveTo(i,e.min),e.coords.forEach((e=>{t.lineTo(i-e.estimate*n,e.v)})),t.lineTo(i,e.max),t.moveTo(i,e.min),e.coords.forEach((e=>{t.lineTo(i+e.estimate*n,e.v)})),t.lineTo(i,e.max)}else{const{y:i,height:o}=e,n=o/2/r;t.moveTo(e.min,i),e.coords.forEach((e=>{t.lineTo(e.v,i-e.estimate*n)})),t.lineTo(e.max,i),t.moveTo(e.min,i),e.coords.forEach((e=>{t.lineTo(e.v,i+e.estimate*n)})),t.lineTo(e.max,i)}t.closePath(),t.stroke(),t.fill()}_getBounds(t){if(this.isVertical()){const{x:e,width:r,min:i,max:o}=this.getProps(["x","width","min","max"],t),n=e-r/2;return{left:n,top:o,right:n+r,bottom:i}}const{y:e,height:r,min:i,max:o}=this.getProps(["y","height","min","max"],t),n=e-r/2;return{left:i,top:n,right:o,bottom:n+r}}}function I(t,r,i,o=[],n=[]){e.registry.addControllers(i),Array.isArray(o)?e.registry.addElements(...o):e.registry.addElements(o),Array.isArray(n)?e.registry.addScales(...n):e.registry.addScales(n);const s=r;return s.type=t,s}E.id="violin",E.defaults={...e.BarElement.defaults,..._},E.defaultRoutes={...e.BarElement.defaultRoutes,...S};class W extends B{_parseStats(t,e){return w(t,e)}_transformStats(t,e,r){super._transformStats(t,e,r);for(const i of["whiskerMin","whiskerMax"])t[i]=r(e[i])}}W.id="boxplot",W.defaults=r.merge({},[e.BarController.defaults,v(T),{animations:{numbers:{type:"number",properties:e.BarController.defaults.animations.numbers.properties.concat(["q1","q3","min","max","median","whiskerMin","whiskerMax","mean"],T.filter((t=>!t.endsWith("Color"))))}},dataElementType:R.id}]),W.overrides=r.merge({},[e.BarController.overrides,N()]);class V extends e.Chart{constructor(t,r){super(t,I("boxplot",r,W,R,[e.LinearScale,e.CategoryScale]))}}V.id=W.id;class O extends B{_parseStats(t,e){return b(t,e)}_transformStats(t,e,r){super._transformStats(t,e,r),t.maxEstimate=e.maxEstimate,Array.isArray(e.coords)&&(t.coords=e.coords.map((t=>({...t,v:r(t.v)}))))}}O.id="violin",O.defaults=r.merge({},[e.BarController.defaults,v(P),{points:100,animations:{numbers:{type:"number",properties:e.BarController.defaults.animations.numbers.properties.concat(["q1","q3","min","max","median","maxEstimate"],P.filter((t=>!t.endsWith("Color"))))},kdeCoords:{fn:function(t,e,r){return Array.isArray(t)&&Array.isArray(e)?e.map(((e,i)=>({v:k.number(t[i]?t[i].v:null,e.v,r),estimate:k.number(t[i]?t[i].estimate:null,e.estimate,r)}))):e},properties:["coords"]}},dataElementType:E.id}]),O.overrides=r.merge({},[e.BarController.overrides,N()]);class F extends e.Chart{constructor(t,r){super(t,I("violin",r,O,E,[e.LinearScale,e.CategoryScale]))}}F.id=O.id,e.registry.addControllers(W,O),e.registry.addElements(R,E),t.BoxAndWiskers=R,t.BoxPlotChart=V,t.BoxPlotController=W,t.StatsBase=A,t.Violin=E,t.ViolinChart=F,t.ViolinController=O}));
!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).ChartBoxPlot={},t.Chart,t.Chart.helpers)}(this,(function(t,e,r){"use strict";const i=Math.sqrt(2*Math.PI);function o(t){const e=t.items.length,r=function(t,e,r){let i=Math.sqrt(function(t,e){return t*e/(e-1)}(e,r));return"number"==typeof t&&(i=Math.min(i,t/1.34)),1.06*i*Math.pow(r,-.2)}(t.iqr,t.variance,e);return o=>{let n=0,s=0;for(n=0;n<e;n++){const e=t.items[n];s+=(a=(o-e)/r,Math.exp(-.5*a*a)/i)}var a;return s/r/e}}function n(t,e,r){const i=e-1,o=e=>{const o=e*i,n=Math.floor(o),s=o-n,a=t[n];return 0===s?a:r(a,t[Math.min(n+1,i)],s)};return{q1:o(.25),median:o(.5),q3:o(.75)}}function s(t,e=t.length){return n(t,e,((t,e,r)=>t+r*(e-t)))}function a(t,e=t.length){return n(t,e,((t,e,r)=>t+(e-t)*r))}function l(t,e=t.length){return n(t,e,(t=>t))}function d(t,e=t.length){return n(t,e,((t,e)=>e))}function u(t,e=t.length){return n(t,e,((t,e,r)=>r<.5?t:e))}function h(t,e=t.length){return n(t,e,((t,e)=>.5*(t+e)))}function m(t,e=t.length){const r=e,i=Math.floor((r+3)/2)/2,o=e=>.5*(t[Math.floor(e)-1]+t[Math.ceil(e)-1]);return{q1:o(i),median:o((r+1)/2),q3:o(r+1-i)}}function c(t,e=t.length){return m(t,e)}function f(t,e,r,i,{eps:o,quantiles:n,coef:s,whiskersMode:a}){const l=(t,e)=>Math.abs(t-e)<o,{median:d,q1:u,q3:h}=n(t,e),m=h-u,c="number"==typeof s&&s>0;let f=c?Math.max(r,u-s*m):r,x=c?Math.min(i,h+s*m):i;const g=[];for(let r=0;r<e;r+=1){const e=t[r];if(e>=f||l(e,f)){"nearest"===a&&(f=e);break}0!==g.length&&l(g[g.length-1],e)||g.push(e)}const p=[];for(let r=e-1;r>=0;r-=1){const e=t[r];if(e<=x||l(e,x)){"nearest"===a&&(x=e);break}0!==p.length&&l(p[p.length-1],e)||0!==g.length&&l(g[g.length-1],e)||p.push(e)}return{median:d,q1:u,q3:h,iqr:m,outlier:g.concat(p.reverse()),whiskerHigh:x,whiskerLow:f}}function x(t,e){let r=0;for(let i=0;i<e;i++){r+=t[i]}r/=e;let i=0;for(let o=0;o<e;o++){const e=t[o];i+=(e-r)*(e-r)}return i/=e,{mean:r,variance:i}}function g(t,e={}){const r={coef:1.5,eps:.01,quantiles:s,validAndSorted:!1,whiskersMode:"nearest",...e},{missing:i,s:n,min:a,max:l}=r.validAndSorted?function(t){return 0===t.length?{min:Number.NaN,max:Number.NaN,missing:0,s:[]}:{min:t[0],max:t[t.length-1],missing:0,s:t}}(t):function(t){let e=0;const{length:r}=t,i=t instanceof Float64Array?new Float64Array(r):new Float32Array(r);for(let o=0;o<r;o+=1){const r=t[o];null==r||Number.isNaN(r)||(i[e]=r,e+=1)}const o=r-e;if(0===e)return{min:Number.NaN,max:Number.NaN,missing:o,s:[]};const n=e===r?i:i.subarray(0,e);return n.sort(((t,e)=>t===e?0:t<e?-1:1)),{min:n[0],max:n[n.length-1],missing:o,s:n}}(t),d={min:Number.NaN,max:Number.NaN,mean:Number.NaN,missing:i,iqr:Number.NaN,count:t.length,whiskerHigh:Number.NaN,whiskerLow:Number.NaN,outlier:[],median:Number.NaN,q1:Number.NaN,q3:Number.NaN,variance:0,items:[],kde:()=>0},u=t.length-i;if(0===u)return d;const h={min:a,max:l,count:t.length,missing:i,items:n,...x(n,u),...f(n,u,a,l,r)};return{...h,kde:o(h)}}const p={coef:1.5,quantiles:7,whiskersMode:"nearest"};function y(t){const e=null==t||"number"!=typeof t.coef?p.coef:t.coef,r=function(t){return"function"==typeof t?t:{hinges:c,fivenum:m,7:s,quantiles:s,linear:a,lower:l,higher:d,nearest:u,midpoint:h}[t]||s}(null==t||null==t.quantiles?s:t.quantiles);return{coef:e,quantiles:r,whiskersMode:null==t||"string"!=typeof t.whiskersMode?p.whiskersMode:t.whiskersMode}}function w(t,e){if(t){if("number"==typeof t.median&&"number"==typeof t.q1&&"number"==typeof t.q3){if(void 0===t.whiskerMin){const{coef:r}=y(e),{whiskerMin:i,whiskerMax:o}=function(t,e,r=1.5){const i=t.q3-t.q1,o="number"==typeof r&&r>0;let n=o?Math.max(t.min,t.q1-r*i):t.min,s=o?Math.min(t.max,t.q3+r*i):t.max;if(Array.isArray(e)){for(let t=0;t<e.length;t+=1){const r=e[t];if(r>=n){n=r;break}}for(let t=e.length-1;t>=0;t-=1){const r=e[t];if(r<=s){s=r;break}}}return{whiskerMin:n,whiskerMax:s}}(t,Array.isArray(t.items)?t.items.slice().sort(((t,e)=>t-e)):null,r);t.whiskerMin=i,t.whiskerMax=o}return t}if(Array.isArray(t))return function(t,e){const r=g("undefined"==typeof Float64Array||t instanceof Float32Array||t instanceof Float64Array?t:Float64Array.from(t),y(e));return{items:Array.from(r.items),outliers:r.outlier,whiskerMax:r.whiskerHigh,whiskerMin:r.whiskerLow,max:r.max,median:r.median,mean:r.mean,min:r.min,q1:r.q1,q3:r.q3}}(t,e)}}function b(t,e){if(t){if("number"==typeof t.median&&Array.isArray(t.coords))return t;if(Array.isArray(t))return function(t,e){if(0===t.length)return;const r=g("undefined"==typeof Float64Array||t instanceof Float32Array||t instanceof Float64Array?t:Float64Array.from(t),y(e)),i=function(t,e,r){const i=[],o=(e-t)/r;for(let r=t;r<=e&&o>0;r+=o)i.push(r);return i[i.length-1]!==e&&i.push(e),i}(r.min,r.max,e.points).map((t=>({v:t,estimate:r.kde(t)}))),o=i.reduce(((t,e)=>Math.max(t,e.estimate)),Number.NEGATIVE_INFINITY);return{max:r.max,min:r.min,mean:r.mean,median:r.median,q1:r.q1,q3:r.q3,items:Array.from(r.items),coords:i,outliers:[],maxEstimate:o}}(t,e)}}function k(t=Date.now()){let e=t;return()=>(e=(9301*e+49297)%233280,e/233280)}const q={number:(t,e,r)=>t===e||null==t?e:null==e?t:t+(e-t)*r};function M(t,e,r){return"number"==typeof t&&"number"==typeof e?q.number(t,e,r):Array.isArray(t)&&Array.isArray(e)?e.map(((e,i)=>q.number(t[i],e,r))):e}function C(t){const e=t.formattedValue,r=this;e&&null!=r._tooltipOutlier&&t.datasetIndex===r._tooltipOutlier.datasetIndex&&(e.hoveredOutlierIndex=r._tooltipOutlier.index),e&&null!=r._tooltipItem&&t.datasetIndex===r._tooltipItem.datasetIndex&&(e.hoveredItemIndex=r._tooltipItem.index)}function v(t,e){if(!t.length)return!1;let r=0,i=0,o=0;for(let n=0;n<t.length;n+=1){const s=t[n].element;if(s&&s.hasValue()){const t=s.tooltipPosition(e,this);r+=t.x,i+=t.y,o+=1}}return{x:r/o,y:i/o}}function _(t){const e=["borderColor","backgroundColor"].concat(t.filter((t=>t.endsWith("Color"))));return{animations:{numberArray:{fn:M,properties:["outliers","items"]},colors:{type:"color",properties:e}},transitions:{show:{animations:{colors:{type:"color",properties:e,from:"transparent"}}},hide:{animations:{colors:{type:"color",properties:e,to:"transparent"}}}},minStats:"min",maxStats:"max",...p}}function N(){return{plugins:{tooltip:{position:v.register().id,callbacks:{beforeLabel:C}}}}}v.id="average",v.register=()=>(e.Tooltip.positioners.average=v,v);let B=class extends e.BarController{_transformStats(t,e,r){for(const i of["min","max","median","q3","q1","mean"]){const o=e[i];"number"==typeof o&&(t[i]=r(o))}for(const i of["outliers","items"])Array.isArray(e[i])&&(t[i]=e[i].map(r))}getMinMax(t,e){const r=t.axis,i=this.options;t.axis=i.minStats;const{min:o}=super.getMinMax(t,e);t.axis=i.maxStats;const{max:n}=super.getMinMax(t,e);return t.axis=r,{min:o,max:n}}parsePrimitiveData(t,e,r,i){const o=t.vScale,n=t.iScale,s=n.getLabels(),a=[];for(let t=0;t<i;t+=1){const i=t+r,l={};l[n.axis]=n.parse(s[i],i);const d=this._parseStats(null==e?null:e[i],this.options);d&&(Object.assign(l,d),l[o.axis]=d.median),a.push(l)}return a}parseArrayData(t,e,r,i){return this.parsePrimitiveData(t,e,r,i)}parseObjectData(t,e,r,i){return this.parsePrimitiveData(t,e,r,i)}getLabelAndValue(t){const e=super.getLabelAndValue(t),{vScale:r}=this._cachedMeta,i=this.getParsed(t);if(!r||!i||"NaN"===e.value)return e;e.value={raw:i,hoveredOutlierIndex:-1,hoveredItemIndex:-1},this._transformStats(e.value,i,(t=>r.getLabelForValue(t)));const o=this._toStringStats(e.value.raw);return e.value.toString=function(){return this.hoveredOutlierIndex>=0?`(outlier: ${this.outliers[this.hoveredOutlierIndex]})`:this.hoveredItemIndex>=0?`(item: ${this.items[this.hoveredItemIndex]})`:o},e}_toStringStats(t){const e=t=>null==t?"NaN":r.formatNumber(t,this.chart.options.locale,{});return`(min: ${e(t.min)}, 25% quantile: ${e(t.q1)}, median: ${e(t.median)}, mean: ${e(t.mean)}, 75% quantile: ${e(t.q3)}, max: ${e(t.max)})`}updateElement(t,e,r,i){const o="reset"===i,n=this._cachedMeta.vScale,s=this.getParsed(e),a=n.getBasePixel();r._datasetIndex=this.index,r._index=e,this._transformStats(r,s,(t=>o?a:n.getPixelForValue(t,e))),super.updateElement(t,e,r,i)}};const S={borderWidth:1,outlierStyle:"circle",outlierRadius:2,outlierBorderWidth:1,itemStyle:"circle",itemRadius:0,itemBorderWidth:0,itemHitRadius:0,meanStyle:"circle",meanRadius:3,meanBorderWidth:1,hitPadding:2,outlierHitRadius:4},I={outlierBackgroundColor:"backgroundColor",outlierBorderColor:"borderColor",itemBackgroundColor:"backgroundColor",itemBorderColor:"borderColor",meanBackgroundColor:"backgroundColor",meanBorderColor:"borderColor"},P=Object.keys(S).concat(Object.keys(I));class A extends e.Element{isVertical(){return!this.horizontal}_drawItems(t){const e=this.isVertical(),i=this.getProps(["x","y","items","width","height","outliers"]),{options:o}=this;if(o.itemRadius<=0||!i.items||i.items.length<=0)return;t.save(),t.strokeStyle=o.itemBorderColor,t.fillStyle=o.itemBackgroundColor,t.lineWidth=o.itemBorderWidth;const n=k(1e3*this._datasetIndex+this._index),s={pointStyle:o.itemStyle,radius:o.itemRadius,borderWidth:o.itemBorderWidth},a=new Set(i.outliers||[]);e?i.items.forEach((e=>{a.has(e)||r.drawPoint(t,s,i.x-i.width/2+n()*i.width,e)})):i.items.forEach((e=>{a.has(e)||r.drawPoint(t,s,e,i.y-i.height/2+n()*i.height)})),t.restore()}_drawOutliers(t){const e=this.isVertical(),i=this.getProps(["x","y","outliers"]),{options:o}=this;if(o.outlierRadius<=0||!i.outliers||0===i.outliers.length)return;t.save(),t.fillStyle=o.outlierBackgroundColor,t.strokeStyle=o.outlierBorderColor,t.lineWidth=o.outlierBorderWidth;const n={pointStyle:o.outlierStyle,radius:o.outlierRadius,borderWidth:o.outlierBorderWidth};e?i.outliers.forEach((e=>{r.drawPoint(t,n,i.x,e)})):i.outliers.forEach((e=>{r.drawPoint(t,n,e,i.y)})),t.restore()}_drawMeanDot(t){const e=this.isVertical(),i=this.getProps(["x","y","mean"]),{options:o}=this;if(o.meanRadius<=0||null==i.mean||Number.isNaN(i.mean))return;t.save(),t.fillStyle=o.meanBackgroundColor,t.strokeStyle=o.meanBorderColor,t.lineWidth=o.meanBorderWidth;const n={pointStyle:o.meanStyle,radius:o.meanRadius,borderWidth:o.meanBorderWidth};e?r.drawPoint(t,n,i.x,i.mean):r.drawPoint(t,n,i.mean,i.y),t.restore()}_getBounds(t){return{left:0,top:0,right:0,bottom:0}}_getHitBounds(t){const e=this.options.hitPadding,r=this._getBounds(t);return{left:r.left-e,top:r.top-e,right:r.right+e,bottom:r.bottom+e}}inRange(t,e,r){return(!Number.isNaN(this.x)||!Number.isNaN(this.y))&&(this._boxInRange(t,e,r)||null!=this._outlierIndexInRange(t,e,r)||null!=this._itemIndexInRange(t,e,r))}inXRange(t,e){const r=this._getHitBounds(e);return t>=r.left&&t<=r.right}inYRange(t,e){const r=this._getHitBounds(e);return t>=r.top&&t<=r.bottom}_outlierIndexInRange(t,e,r){const i=this.getProps(["x","y"],r),o=this.options.outlierHitRadius,n=this._getOutliers(r),s=this.isVertical();if(s&&Math.abs(t-i.x)>o||!s&&Math.abs(e-i.y)>o)return null;const a=s?e:t;for(let t=0;t<n.length;t+=1)if(Math.abs(n[t]-a)<=o)return s?{index:t,x:i.x,y:n[t]}:{index:t,x:n[t],y:i.y};return null}_itemIndexInRange(t,e,r){const i=this.options.itemHitRadius;if(i<=0)return null;const o=this.getProps(["x","y","items","width","height","outliers"],r),n=this.isVertical(),{options:s}=this;if(s.itemRadius<=0||!o.items||o.items.length<=0)return null;const a=k(1e3*this._datasetIndex+this._index),l=new Set(o.outliers||[]);if(n)for(let r=0;r<o.items.length;r++){const n=o.items[r];if(!l.has(n)){const s=o.x-o.width/2+a()*o.width;if(Math.abs(s-t)<=i&&Math.abs(n-e)<=i)return{index:r,x:s,y:n}}}else for(let r=0;r<o.items.length;r++){const n=o.items[r];if(!l.has(n)){const s=o.y-o.height/2+a()*o.height;if(Math.abs(n-t)<=i&&Math.abs(s-e)<=i)return{index:r,x:n,y:s}}}return null}_boxInRange(t,e,r){const i=this._getHitBounds(r);return t>=i.left&&t<=i.right&&e>=i.top&&e<=i.bottom}getCenterPoint(t){const e=this.getProps(["x","y"],t);return{x:e.x,y:e.y}}_getOutliers(t){return this.getProps(["outliers"],t).outliers||[]}tooltipPosition(t,e){if(!t||"boolean"==typeof t)return this.getCenterPoint();e&&(delete e._tooltipOutlier,delete e._tooltipItem);const r=this._outlierIndexInRange(t.x,t.y);if(null!=r&&e)return e._tooltipOutlier={index:r.index,datasetIndex:this._datasetIndex},{x:r.x,y:r.y};const i=this._itemIndexInRange(t.x,t.y);return null!=i&&e?(e._tooltipItem={index:i.index,datasetIndex:this._datasetIndex},{x:i.x,y:i.y}):this.getCenterPoint()}}const R=P.concat(["medianColor","lowerBackgroundColor"]);class T extends A{draw(t){t.save(),t.fillStyle=this.options.backgroundColor,t.strokeStyle=this.options.borderColor,t.lineWidth=this.options.borderWidth,this._drawBoxPlot(t),this._drawOutliers(t),this._drawMeanDot(t),t.restore(),this._drawItems(t)}_drawBoxPlot(t){this.isVertical()?this._drawBoxPlotVertical(t):this._drawBoxPlotHorizontal(t)}_drawBoxPlotVertical(t){const{options:e}=this,r=this.getProps(["x","width","q1","q3","median","whiskerMin","whiskerMax"]),{x:i}=r,{width:o}=r,n=i-o/2;r.q3>r.q1?t.fillRect(n,r.q1,o,r.q3-r.q1):t.fillRect(n,r.q3,o,r.q1-r.q3),t.save(),e.medianColor&&"transparent"!==e.medianColor&&"#0000"!==e.medianColor&&(t.strokeStyle=e.medianColor),t.beginPath(),t.moveTo(n,r.median),t.lineTo(n+o,r.median),t.closePath(),t.stroke(),t.restore(),t.save(),e.lowerBackgroundColor&&"transparent"!==e.lowerBackgroundColor&&"#0000"!==e.lowerBackgroundColor&&(t.fillStyle=e.lowerBackgroundColor,r.q3>r.q1?t.fillRect(n,r.median,o,r.q3-r.median):t.fillRect(n,r.median,o,r.q1-r.median)),t.restore(),r.q3>r.q1?t.strokeRect(n,r.q1,o,r.q3-r.q1):t.strokeRect(n,r.q3,o,r.q1-r.q3),t.beginPath(),t.moveTo(n,r.whiskerMin),t.lineTo(n+o,r.whiskerMin),t.moveTo(i,r.whiskerMin),t.lineTo(i,r.q1),t.moveTo(n,r.whiskerMax),t.lineTo(n+o,r.whiskerMax),t.moveTo(i,r.whiskerMax),t.lineTo(i,r.q3),t.closePath(),t.stroke()}_drawBoxPlotHorizontal(t){const{options:e}=this,r=this.getProps(["y","height","q1","q3","median","whiskerMin","whiskerMax"]),{y:i}=r,{height:o}=r,n=i-o/2;r.q3>r.q1?t.fillRect(r.q1,n,r.q3-r.q1,o):t.fillRect(r.q3,n,r.q1-r.q3,o),t.save(),e.medianColor&&"transparent"!==e.medianColor&&(t.strokeStyle=e.medianColor),t.beginPath(),t.moveTo(r.median,n),t.lineTo(r.median,n+o),t.closePath(),t.stroke(),t.restore(),t.save(),e.lowerBackgroundColor&&"transparent"!==e.lowerBackgroundColor&&(t.fillStyle=e.lowerBackgroundColor,r.q3>r.q1?t.fillRect(r.median,n,r.q3-r.median,o):t.fillRect(r.median,n,r.q1-r.median,o)),t.restore(),r.q3>r.q1?t.strokeRect(r.q1,n,r.q3-r.q1,o):t.strokeRect(r.q3,n,r.q1-r.q3,o),t.beginPath(),t.moveTo(r.whiskerMin,n),t.lineTo(r.whiskerMin,n+o),t.moveTo(r.whiskerMin,i),t.lineTo(r.q1,i),t.moveTo(r.whiskerMax,n),t.lineTo(r.whiskerMax,n+o),t.moveTo(r.whiskerMax,i),t.lineTo(r.q3,i),t.closePath(),t.stroke()}_getBounds(t){const e=this.isVertical();if(null==this.x)return{left:0,top:0,right:0,bottom:0};if(e){const{x:e,width:r,whiskerMax:i,whiskerMin:o}=this.getProps(["x","width","whiskerMin","whiskerMax"],t),n=e-r/2;return{left:n,top:i,right:n+r,bottom:o}}const{y:r,height:i,whiskerMax:o,whiskerMin:n}=this.getProps(["y","height","whiskerMin","whiskerMax"],t),s=r-i/2;return{left:n,top:s,right:o,bottom:s+i}}}T.id="boxandwhiskers",T.defaults={...e.BarElement.defaults,...S,medianColor:"transparent",lowerBackgroundColor:"transparent"},T.defaultRoutes={...e.BarElement.defaultRoutes,...I};class E extends A{draw(t){t.save(),t.fillStyle=this.options.backgroundColor,t.strokeStyle=this.options.borderColor,t.lineWidth=this.options.borderWidth;const e=this.getProps(["x","y","median","width","height","min","max","coords","maxEstimate"]);null!=e.median&&r.drawPoint(t,{pointStyle:"rectRot",radius:5,borderWidth:this.options.borderWidth},e.x,e.y),e.coords&&e.coords.length>0&&this._drawCoords(t,e),this._drawOutliers(t),this._drawMeanDot(t),t.restore(),this._drawItems(t)}_drawCoords(t,e){let r;if(r=null==e.maxEstimate?e.coords.reduce(((t,e)=>Math.max(t,e.estimate)),Number.NEGATIVE_INFINITY):e.maxEstimate,this.isVertical()){const{x:i,width:o}=e,n=o/2/r;t.moveTo(i,e.min),e.coords.forEach((e=>{t.lineTo(i-e.estimate*n,e.v)})),t.lineTo(i,e.max),t.moveTo(i,e.min),e.coords.forEach((e=>{t.lineTo(i+e.estimate*n,e.v)})),t.lineTo(i,e.max)}else{const{y:i,height:o}=e,n=o/2/r;t.moveTo(e.min,i),e.coords.forEach((e=>{t.lineTo(e.v,i-e.estimate*n)})),t.lineTo(e.max,i),t.moveTo(e.min,i),e.coords.forEach((e=>{t.lineTo(e.v,i+e.estimate*n)})),t.lineTo(e.max,i)}t.closePath(),t.stroke(),t.fill()}_getBounds(t){if(this.isVertical()){const{x:e,width:r,min:i,max:o}=this.getProps(["x","width","min","max"],t),n=e-r/2;return{left:n,top:o,right:n+r,bottom:i}}const{y:e,height:r,min:i,max:o}=this.getProps(["y","height","min","max"],t),n=e-r/2;return{left:i,top:n,right:o,bottom:n+r}}}function W(t,r,i,o=[],n=[]){e.registry.addControllers(i),Array.isArray(o)?e.registry.addElements(...o):e.registry.addElements(o),Array.isArray(n)?e.registry.addScales(...n):e.registry.addScales(n);const s=r;return s.type=t,s}E.id="violin",E.defaults={...e.BarElement.defaults,...S},E.defaultRoutes={...e.BarElement.defaultRoutes,...I};class V extends B{_parseStats(t,e){return w(t,e)}_transformStats(t,e,r){super._transformStats(t,e,r);for(const i of["whiskerMin","whiskerMax"])t[i]=r(e[i])}}V.id="boxplot",V.defaults=r.merge({},[e.BarController.defaults,_(R),{animations:{numbers:{type:"number",properties:e.BarController.defaults.animations.numbers.properties.concat(["q1","q3","min","max","median","whiskerMin","whiskerMax","mean"],R.filter((t=>!t.endsWith("Color"))))}},dataElementType:T.id}]),V.overrides=r.merge({},[e.BarController.overrides,N()]);class O extends e.Chart{constructor(t,r){super(t,W("boxplot",r,V,T,[e.LinearScale,e.CategoryScale]))}}O.id=V.id;class F extends B{_parseStats(t,e){return b(t,e)}_transformStats(t,e,r){super._transformStats(t,e,r),t.maxEstimate=e.maxEstimate,Array.isArray(e.coords)&&(t.coords=e.coords.map((t=>({...t,v:r(t.v)}))))}}F.id="violin",F.defaults=r.merge({},[e.BarController.defaults,_(P),{points:100,animations:{numbers:{type:"number",properties:e.BarController.defaults.animations.numbers.properties.concat(["q1","q3","min","max","median","maxEstimate"],P.filter((t=>!t.endsWith("Color"))))},kdeCoords:{fn:function(t,e,r){return Array.isArray(t)&&Array.isArray(e)?e.map(((e,i)=>({v:q.number(t[i]?t[i].v:null,e.v,r),estimate:q.number(t[i]?t[i].estimate:null,e.estimate,r)}))):e},properties:["coords"]}},dataElementType:E.id}]),F.overrides=r.merge({},[e.BarController.overrides,N()]);class H extends e.Chart{constructor(t,r){super(t,W("violin",r,F,E,[e.LinearScale,e.CategoryScale]))}}H.id=F.id,e.registry.addControllers(V,F),e.registry.addElements(T,E),t.BoxAndWiskers=T,t.BoxPlotChart=O,t.BoxPlotController=V,t.StatsBase=A,t.Violin=E,t.ViolinChart=H,t.ViolinController=F}));
//# sourceMappingURL=index.umd.min.js.map
{
"name": "@sgratzl/chartjs-chart-boxplot",
"description": "Chart.js module for charting boxplots and violin charts",
"version": "4.3.3",
"version": "4.4.0",
"publishConfig": {

@@ -6,0 +6,0 @@ "access": "public"

@@ -14,2 +14,3 @@ import {

CartesianScaleTypeRegistry,
BarControllerDatasetOptions,
} from 'chart.js';

@@ -74,2 +75,6 @@ import { merge } from 'chart.js/helpers';

extends ControllerDatasetOptions,
Pick<
BarControllerDatasetOptions,
'barPercentage' | 'barThickness' | 'categoryPercentage' | 'maxBarThickness' | 'minBarLength'
>,
IBoxplotOptions,

@@ -76,0 +81,0 @@ ScriptableAndArrayOptions<IBoxAndWhiskersOptions, ScriptableContext<'boxplot'>>,

@@ -150,3 +150,6 @@ import { BarController, Element, ChartMeta, LinearScale, Scale, UpdateMode } from 'chart.js';

*/
getLabelAndValue(index: number): { label: string; value: string & { raw: S; hoveredOutlierIndex: number } & S } {
getLabelAndValue(index: number): {
label: string;
value: string & { raw: S; hoveredOutlierIndex: number; hoveredItemIndex: number } & S;
} {
const r = super.getLabelAndValue(index) as any;

@@ -161,2 +164,3 @@ const { vScale } = this._cachedMeta;

hoveredOutlierIndex: -1,
hoveredItemIndex: -1,
};

@@ -171,2 +175,6 @@ this._transformStats(r.value, parsed, (v) => vScale.getLabelForValue(v));

}
if (this.hoveredItemIndex >= 0) {
// TODO formatter
return `(item: ${this.items[this.hoveredItemIndex]})`;
}
return s;

@@ -173,0 +181,0 @@ };

@@ -14,2 +14,3 @@ import {

CartesianScaleTypeRegistry,
BarControllerDatasetOptions,
} from 'chart.js';

@@ -83,2 +84,6 @@ import { merge } from 'chart.js/helpers';

extends ControllerDatasetOptions,
Pick<
BarControllerDatasetOptions,
'barPercentage' | 'barThickness' | 'categoryPercentage' | 'maxBarThickness' | 'minBarLength'
>,
IViolinOptions,

@@ -85,0 +90,0 @@ ScriptableAndArrayOptions<IViolinElementOptions, ScriptableContext<'violin'>>,

@@ -119,2 +119,9 @@ import { Element } from 'chart.js';

itemBorderWidth: number;
/**
* hit radius for hit test of items
* @default 0
* @scriptable
* @indexable
*/
itemHitRadius: number;

@@ -199,2 +206,3 @@ /**

itemBorderWidth: 0,
itemHitRadius: 0,

@@ -404,3 +412,4 @@ meanStyle: 'circle',

this._boxInRange(mouseX, mouseY, useFinalPosition) ||
this._outlierIndexInRange(mouseX, mouseY, useFinalPosition) >= 0
this._outlierIndexInRange(mouseX, mouseY, useFinalPosition) != null ||
this._itemIndexInRange(mouseX, mouseY, useFinalPosition) != null
);

@@ -428,3 +437,7 @@ }

*/
protected _outlierIndexInRange(mouseX: number, mouseY: number, useFinalPosition?: boolean): number {
protected _outlierIndexInRange(
mouseX: number,
mouseY: number,
useFinalPosition?: boolean
): { index: number; x: number; y: number } | null {
const props = this.getProps(['x', 'y'], useFinalPosition);

@@ -437,3 +450,3 @@ const hitRadius = this.options.outlierHitRadius;

if ((vertical && Math.abs(mouseX - props.x) > hitRadius) || (!vertical && Math.abs(mouseY - props.y) > hitRadius)) {
return -1;
return null;
}

@@ -443,6 +456,6 @@ const toCompare = vertical ? mouseY : mouseX;

if (Math.abs(outliers[i] - toCompare) <= hitRadius) {
return i;
return vertical ? { index: i, x: props.x, y: outliers[i] } : { index: i, x: outliers[i], y: props.y };
}
}
return -1;
return null;
}

@@ -453,2 +466,50 @@

*/
protected _itemIndexInRange(
mouseX: number,
mouseY: number,
useFinalPosition?: boolean
): { index: number; x: number; y: number } | null {
const hitRadius = this.options.itemHitRadius;
if (hitRadius <= 0) {
return null;
}
const props = this.getProps(['x', 'y', 'items', 'width', 'height', 'outliers'], useFinalPosition);
const vert = this.isVertical();
const { options } = this;
if (options.itemRadius <= 0 || !props.items || props.items.length <= 0) {
return null;
}
// jitter based on random data
// use the dataset index and index to initialize the random number generator
const random = rnd(this._datasetIndex * 1000 + this._index);
const outliers = new Set(props.outliers || []);
if (vert) {
for (let i = 0; i < props.items.length; i++) {
const y = props.items[i];
if (!outliers.has(y)) {
const x = props.x - props.width / 2 + random() * props.width;
if (Math.abs(x - mouseX) <= hitRadius && Math.abs(y - mouseY) <= hitRadius) {
return { index: i, x, y };
}
}
}
} else {
for (let i = 0; i < props.items.length; i++) {
const x = props.items[i];
if (!outliers.has(x)) {
const y = props.y - props.height / 2 + random() * props.height;
if (Math.abs(x - mouseX) <= hitRadius && Math.abs(y - mouseY) <= hitRadius) {
return { index: i, x, y };
}
}
}
}
return null;
}
/**
* @hidden
*/
protected _boxInRange(mouseX: number, mouseY: number, useFinalPosition?: boolean): boolean {

@@ -492,26 +553,38 @@ const bounds = this._getHitBounds(useFinalPosition);

delete tooltip._tooltipOutlier;
// eslint-disable-next-line no-param-reassign
delete tooltip._tooltipItem;
}
const props = this.getProps(['x', 'y']);
const index = this._outlierIndexInRange(eventPosition.x, eventPosition.y);
if (index < 0 || !tooltip) {
return this.getCenterPoint();
//outlier
const info = this._outlierIndexInRange(eventPosition.x, eventPosition.y);
if (info != null && tooltip) {
// hack in the data of the hovered outlier
// eslint-disable-next-line no-param-reassign
tooltip._tooltipOutlier = {
index: info.index,
datasetIndex: this._datasetIndex,
};
return {
x: info.x,
y: info.y,
};
}
// hack in the data of the hovered outlier
// eslint-disable-next-line no-param-reassign
tooltip._tooltipOutlier = {
index,
datasetIndex: this._datasetIndex,
};
if (this.isVertical()) {
// items
const itemInfo = this._itemIndexInRange(eventPosition.x, eventPosition.y);
if (itemInfo != null && tooltip) {
// hack in the data of the hovered outlier
// eslint-disable-next-line no-param-reassign
tooltip._tooltipItem = {
index: itemInfo.index,
datasetIndex: this._datasetIndex,
};
return {
x: props.x as number,
y: this._getOutliers()[index],
x: itemInfo.x,
y: itemInfo.y,
};
}
return {
x: this._getOutliers()[index],
y: props.y as number,
};
// fallback
return this.getCenterPoint();
}
}

@@ -262,4 +262,4 @@ import { BarElement, ChartType, CommonHoverOptions, ScriptableAndArrayOptions, ScriptableContext } from 'chart.js';

export interface ElementOptionsByType<TType extends ChartType> {
boxplot: ScriptableAndArrayOptions<IBoxAndWhiskersOptions & CommonHoverOptions, ScriptableContext<TType>>;
boxandwhiskers: ScriptableAndArrayOptions<IBoxAndWhiskersOptions & CommonHoverOptions, ScriptableContext<TType>>;
}
}

@@ -8,2 +8,6 @@ import { InteractionItem, TooltipItem, Tooltip, TooltipModel } from 'chart.js';

};
_tooltipItem?: {
index: number;
datasetIndex: number;
};
}

@@ -23,2 +27,5 @@

}
if (value && that._tooltipItem != null && item.datasetIndex === that._tooltipItem.datasetIndex) {
value.hoveredItemIndex = that._tooltipItem.index;
}
}

@@ -25,0 +32,0 @@

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

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