Files
OBS/.obsidian/plugins/mood-tracker/main.js
2025-01-16 00:06:11 +04:00

19203 lines
572 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
if you want to view the source, please visit the github repository of this plugin
*/
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __export = (target, all) => {
for (var name2 in all)
__defProp(target, name2, { get: all[name2], enumerable: true });
};
var __copyProps = (to2, from2, except, desc) => {
if (from2 && typeof from2 === "object" || typeof from2 === "function") {
for (let key of __getOwnPropNames(from2))
if (!__hasOwnProp.call(to2, key) && key !== except)
__defProp(to2, key, { get: () => from2[key], enumerable: !(desc = __getOwnPropDesc(from2, key)) || desc.enumerable });
}
return to2;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var __publicField = (obj, key, value) => {
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
return value;
};
// src/main.ts
var main_exports = {};
__export(main_exports, {
default: () => MoodTrackerPlugin
});
module.exports = __toCommonJS(main_exports);
var import_obsidian9 = require("obsidian");
// src/data/defaultEmotions.ts
var defaultEmotions = [
{
id: "17c2b0b6-cead-4281-a830-e09dd2d851f2",
name: "Love and joy",
sortOrder: 0,
color: "#76de91",
textColor: void 0,
emotions: [
"joyful",
"content",
"pleased",
"satisfied",
"happy",
"amused",
"delighted",
"cheerful",
"jovial",
"blissful",
"proud",
"triumphant",
"optimistic",
"eager",
"hopeful",
"enthusiastic",
"excited",
"euphoric",
"enchanted",
"loving",
"romantic",
"affectionate",
"passionate",
"attracted",
"sentimental",
"compassionate",
"peaceful",
"relieved"
]
},
{
id: "f4e5cdb9-a24d-4a16-9c10-ca567d419de2",
name: "Neutral and surprise",
sortOrder: 1,
color: "#f2d05e",
textColor: void 0,
emotions: [
"ok",
"fine",
"bored",
"surprised",
"shocked",
"dismayed",
"confused",
"disillusioned",
"perplexed",
"amazed",
"astonished",
"moved",
"touched"
]
},
{
id: "5f18d172-d07b-4914-8715-e6e656a21697",
name: "Anger and stress",
sortOrder: 2,
color: "#f04a1d",
textColor: void 0,
emotions: [
"stressed",
"angry",
"enraged",
"hateful",
"hostile",
"agitated",
"frustrated",
"irritated",
"annoyed",
"aggravated",
"envious",
"jealous",
"disgusted",
"contemptful "
]
},
{
id: "275e754f-7186-4c5c-9e56-17c75aac623d",
name: "Sadness and fear",
sortOrder: 3,
color: "#837ff0",
textColor: void 0,
emotions: [
"sad",
"hurt",
"agonizing",
"depressed",
"sorrowful",
"disappointed",
"dismayed",
"displeased",
"shameful",
"regretful",
"guilty",
"neglected",
"isolated",
"lonely",
"despaired",
"grieving",
"powerless",
"fearful",
"scared",
"helpless",
"frightened",
"panicking",
"hystetical",
"insecure",
"inferior",
"inadequate",
"nervous",
"anxious",
"worried",
"dreadful",
"mortified"
]
}
];
// src/settings/moodTrackerSettings.ts
var MoodTrackerSettings = class {
constructor() {
this.folderPath = "";
this.emotionGroups = [];
}
};
var DEFAULT_SETTINGS = {
folderPath: "./data/",
emotionGroups: defaultEmotions,
moodRatingLabelDict: {
1: "\u{1F628}",
2: "\u2639\uFE0F",
3: "\u{1F610}",
4: "\u{1F642}",
5: "\u{1F60A}"
},
moodRatingLabelSize: 3,
entryTemplate: "- {{ICON}} {{NOTE}}",
trackerModalTitle: "How are you feeling?",
useEmotions: true,
journalPosition: "## Mood Tracker",
addToJournal: false,
journalFilePath: "",
chartColor: "#b26aba"
};
// src/settings/settingsTab.ts
var import_obsidian5 = require("obsidian");
// src/settings/folderSetting/suggest.ts
var import_obsidian = require("obsidian");
// node_modules/@popperjs/core/lib/enums.js
var top = "top";
var bottom = "bottom";
var right = "right";
var left = "left";
var auto = "auto";
var basePlacements = [top, bottom, right, left];
var start = "start";
var end = "end";
var clippingParents = "clippingParents";
var viewport = "viewport";
var popper = "popper";
var reference = "reference";
var variationPlacements = /* @__PURE__ */ basePlacements.reduce(function(acc, placement) {
return acc.concat([placement + "-" + start, placement + "-" + end]);
}, []);
var placements = /* @__PURE__ */ [].concat(basePlacements, [auto]).reduce(function(acc, placement) {
return acc.concat([placement, placement + "-" + start, placement + "-" + end]);
}, []);
var beforeRead = "beforeRead";
var read = "read";
var afterRead = "afterRead";
var beforeMain = "beforeMain";
var main = "main";
var afterMain = "afterMain";
var beforeWrite = "beforeWrite";
var write = "write";
var afterWrite = "afterWrite";
var modifierPhases = [beforeRead, read, afterRead, beforeMain, main, afterMain, beforeWrite, write, afterWrite];
// node_modules/@popperjs/core/lib/dom-utils/getNodeName.js
function getNodeName(element2) {
return element2 ? (element2.nodeName || "").toLowerCase() : null;
}
// node_modules/@popperjs/core/lib/dom-utils/getWindow.js
function getWindow(node) {
if (node == null) {
return window;
}
if (node.toString() !== "[object Window]") {
var ownerDocument = node.ownerDocument;
return ownerDocument ? ownerDocument.defaultView || window : window;
}
return node;
}
// node_modules/@popperjs/core/lib/dom-utils/instanceOf.js
function isElement(node) {
var OwnElement = getWindow(node).Element;
return node instanceof OwnElement || node instanceof Element;
}
function isHTMLElement(node) {
var OwnElement = getWindow(node).HTMLElement;
return node instanceof OwnElement || node instanceof HTMLElement;
}
function isShadowRoot(node) {
if (typeof ShadowRoot === "undefined") {
return false;
}
var OwnElement = getWindow(node).ShadowRoot;
return node instanceof OwnElement || node instanceof ShadowRoot;
}
// node_modules/@popperjs/core/lib/modifiers/applyStyles.js
function applyStyles(_ref) {
var state = _ref.state;
Object.keys(state.elements).forEach(function(name2) {
var style = state.styles[name2] || {};
var attributes = state.attributes[name2] || {};
var element2 = state.elements[name2];
if (!isHTMLElement(element2) || !getNodeName(element2)) {
return;
}
Object.assign(element2.style, style);
Object.keys(attributes).forEach(function(name3) {
var value = attributes[name3];
if (value === false) {
element2.removeAttribute(name3);
} else {
element2.setAttribute(name3, value === true ? "" : value);
}
});
});
}
function effect(_ref2) {
var state = _ref2.state;
var initialStyles = {
popper: {
position: state.options.strategy,
left: "0",
top: "0",
margin: "0"
},
arrow: {
position: "absolute"
},
reference: {}
};
Object.assign(state.elements.popper.style, initialStyles.popper);
state.styles = initialStyles;
if (state.elements.arrow) {
Object.assign(state.elements.arrow.style, initialStyles.arrow);
}
return function() {
Object.keys(state.elements).forEach(function(name2) {
var element2 = state.elements[name2];
var attributes = state.attributes[name2] || {};
var styleProperties = Object.keys(state.styles.hasOwnProperty(name2) ? state.styles[name2] : initialStyles[name2]);
var style = styleProperties.reduce(function(style2, property) {
style2[property] = "";
return style2;
}, {});
if (!isHTMLElement(element2) || !getNodeName(element2)) {
return;
}
Object.assign(element2.style, style);
Object.keys(attributes).forEach(function(attribute) {
element2.removeAttribute(attribute);
});
});
};
}
var applyStyles_default = {
name: "applyStyles",
enabled: true,
phase: "write",
fn: applyStyles,
effect,
requires: ["computeStyles"]
};
// node_modules/@popperjs/core/lib/utils/getBasePlacement.js
function getBasePlacement(placement) {
return placement.split("-")[0];
}
// node_modules/@popperjs/core/lib/utils/math.js
var max = Math.max;
var min = Math.min;
var round = Math.round;
// node_modules/@popperjs/core/lib/utils/userAgent.js
function getUAString() {
var uaData = navigator.userAgentData;
if (uaData != null && uaData.brands && Array.isArray(uaData.brands)) {
return uaData.brands.map(function(item) {
return item.brand + "/" + item.version;
}).join(" ");
}
return navigator.userAgent;
}
// node_modules/@popperjs/core/lib/dom-utils/isLayoutViewport.js
function isLayoutViewport() {
return !/^((?!chrome|android).)*safari/i.test(getUAString());
}
// node_modules/@popperjs/core/lib/dom-utils/getBoundingClientRect.js
function getBoundingClientRect(element2, includeScale, isFixedStrategy) {
if (includeScale === void 0) {
includeScale = false;
}
if (isFixedStrategy === void 0) {
isFixedStrategy = false;
}
var clientRect = element2.getBoundingClientRect();
var scaleX = 1;
var scaleY = 1;
if (includeScale && isHTMLElement(element2)) {
scaleX = element2.offsetWidth > 0 ? round(clientRect.width) / element2.offsetWidth || 1 : 1;
scaleY = element2.offsetHeight > 0 ? round(clientRect.height) / element2.offsetHeight || 1 : 1;
}
var _ref = isElement(element2) ? getWindow(element2) : window, visualViewport = _ref.visualViewport;
var addVisualOffsets = !isLayoutViewport() && isFixedStrategy;
var x = (clientRect.left + (addVisualOffsets && visualViewport ? visualViewport.offsetLeft : 0)) / scaleX;
var y = (clientRect.top + (addVisualOffsets && visualViewport ? visualViewport.offsetTop : 0)) / scaleY;
var width = clientRect.width / scaleX;
var height = clientRect.height / scaleY;
return {
width,
height,
top: y,
right: x + width,
bottom: y + height,
left: x,
x,
y
};
}
// node_modules/@popperjs/core/lib/dom-utils/getLayoutRect.js
function getLayoutRect(element2) {
var clientRect = getBoundingClientRect(element2);
var width = element2.offsetWidth;
var height = element2.offsetHeight;
if (Math.abs(clientRect.width - width) <= 1) {
width = clientRect.width;
}
if (Math.abs(clientRect.height - height) <= 1) {
height = clientRect.height;
}
return {
x: element2.offsetLeft,
y: element2.offsetTop,
width,
height
};
}
// node_modules/@popperjs/core/lib/dom-utils/contains.js
function contains(parent, child) {
var rootNode = child.getRootNode && child.getRootNode();
if (parent.contains(child)) {
return true;
} else if (rootNode && isShadowRoot(rootNode)) {
var next = child;
do {
if (next && parent.isSameNode(next)) {
return true;
}
next = next.parentNode || next.host;
} while (next);
}
return false;
}
// node_modules/@popperjs/core/lib/dom-utils/getComputedStyle.js
function getComputedStyle2(element2) {
return getWindow(element2).getComputedStyle(element2);
}
// node_modules/@popperjs/core/lib/dom-utils/isTableElement.js
function isTableElement(element2) {
return ["table", "td", "th"].indexOf(getNodeName(element2)) >= 0;
}
// node_modules/@popperjs/core/lib/dom-utils/getDocumentElement.js
function getDocumentElement(element2) {
return ((isElement(element2) ? element2.ownerDocument : (
// $FlowFixMe[prop-missing]
element2.document
)) || window.document).documentElement;
}
// node_modules/@popperjs/core/lib/dom-utils/getParentNode.js
function getParentNode(element2) {
if (getNodeName(element2) === "html") {
return element2;
}
return (
// this is a quicker (but less type safe) way to save quite some bytes from the bundle
// $FlowFixMe[incompatible-return]
// $FlowFixMe[prop-missing]
element2.assignedSlot || // step into the shadow DOM of the parent of a slotted node
element2.parentNode || // DOM Element detected
(isShadowRoot(element2) ? element2.host : null) || // ShadowRoot detected
// $FlowFixMe[incompatible-call]: HTMLElement is a Node
getDocumentElement(element2)
);
}
// node_modules/@popperjs/core/lib/dom-utils/getOffsetParent.js
function getTrueOffsetParent(element2) {
if (!isHTMLElement(element2) || // https://github.com/popperjs/popper-core/issues/837
getComputedStyle2(element2).position === "fixed") {
return null;
}
return element2.offsetParent;
}
function getContainingBlock(element2) {
var isFirefox = /firefox/i.test(getUAString());
var isIE = /Trident/i.test(getUAString());
if (isIE && isHTMLElement(element2)) {
var elementCss = getComputedStyle2(element2);
if (elementCss.position === "fixed") {
return null;
}
}
var currentNode = getParentNode(element2);
if (isShadowRoot(currentNode)) {
currentNode = currentNode.host;
}
while (isHTMLElement(currentNode) && ["html", "body"].indexOf(getNodeName(currentNode)) < 0) {
var css = getComputedStyle2(currentNode);
if (css.transform !== "none" || css.perspective !== "none" || css.contain === "paint" || ["transform", "perspective"].indexOf(css.willChange) !== -1 || isFirefox && css.willChange === "filter" || isFirefox && css.filter && css.filter !== "none") {
return currentNode;
} else {
currentNode = currentNode.parentNode;
}
}
return null;
}
function getOffsetParent(element2) {
var window2 = getWindow(element2);
var offsetParent = getTrueOffsetParent(element2);
while (offsetParent && isTableElement(offsetParent) && getComputedStyle2(offsetParent).position === "static") {
offsetParent = getTrueOffsetParent(offsetParent);
}
if (offsetParent && (getNodeName(offsetParent) === "html" || getNodeName(offsetParent) === "body" && getComputedStyle2(offsetParent).position === "static")) {
return window2;
}
return offsetParent || getContainingBlock(element2) || window2;
}
// node_modules/@popperjs/core/lib/utils/getMainAxisFromPlacement.js
function getMainAxisFromPlacement(placement) {
return ["top", "bottom"].indexOf(placement) >= 0 ? "x" : "y";
}
// node_modules/@popperjs/core/lib/utils/within.js
function within(min2, value, max2) {
return max(min2, min(value, max2));
}
function withinMaxClamp(min2, value, max2) {
var v = within(min2, value, max2);
return v > max2 ? max2 : v;
}
// node_modules/@popperjs/core/lib/utils/getFreshSideObject.js
function getFreshSideObject() {
return {
top: 0,
right: 0,
bottom: 0,
left: 0
};
}
// node_modules/@popperjs/core/lib/utils/mergePaddingObject.js
function mergePaddingObject(paddingObject) {
return Object.assign({}, getFreshSideObject(), paddingObject);
}
// node_modules/@popperjs/core/lib/utils/expandToHashMap.js
function expandToHashMap(value, keys) {
return keys.reduce(function(hashMap, key) {
hashMap[key] = value;
return hashMap;
}, {});
}
// node_modules/@popperjs/core/lib/modifiers/arrow.js
var toPaddingObject = function toPaddingObject2(padding, state) {
padding = typeof padding === "function" ? padding(Object.assign({}, state.rects, {
placement: state.placement
})) : padding;
return mergePaddingObject(typeof padding !== "number" ? padding : expandToHashMap(padding, basePlacements));
};
function arrow(_ref) {
var _state$modifiersData$;
var state = _ref.state, name2 = _ref.name, options = _ref.options;
var arrowElement = state.elements.arrow;
var popperOffsets2 = state.modifiersData.popperOffsets;
var basePlacement = getBasePlacement(state.placement);
var axis = getMainAxisFromPlacement(basePlacement);
var isVertical = [left, right].indexOf(basePlacement) >= 0;
var len = isVertical ? "height" : "width";
if (!arrowElement || !popperOffsets2) {
return;
}
var paddingObject = toPaddingObject(options.padding, state);
var arrowRect = getLayoutRect(arrowElement);
var minProp = axis === "y" ? top : left;
var maxProp = axis === "y" ? bottom : right;
var endDiff = state.rects.reference[len] + state.rects.reference[axis] - popperOffsets2[axis] - state.rects.popper[len];
var startDiff = popperOffsets2[axis] - state.rects.reference[axis];
var arrowOffsetParent = getOffsetParent(arrowElement);
var clientSize = arrowOffsetParent ? axis === "y" ? arrowOffsetParent.clientHeight || 0 : arrowOffsetParent.clientWidth || 0 : 0;
var centerToReference = endDiff / 2 - startDiff / 2;
var min2 = paddingObject[minProp];
var max2 = clientSize - arrowRect[len] - paddingObject[maxProp];
var center = clientSize / 2 - arrowRect[len] / 2 + centerToReference;
var offset2 = within(min2, center, max2);
var axisProp = axis;
state.modifiersData[name2] = (_state$modifiersData$ = {}, _state$modifiersData$[axisProp] = offset2, _state$modifiersData$.centerOffset = offset2 - center, _state$modifiersData$);
}
function effect2(_ref2) {
var state = _ref2.state, options = _ref2.options;
var _options$element = options.element, arrowElement = _options$element === void 0 ? "[data-popper-arrow]" : _options$element;
if (arrowElement == null) {
return;
}
if (typeof arrowElement === "string") {
arrowElement = state.elements.popper.querySelector(arrowElement);
if (!arrowElement) {
return;
}
}
if (true) {
if (!isHTMLElement(arrowElement)) {
console.error(['Popper: "arrow" element must be an HTMLElement (not an SVGElement).', "To use an SVG arrow, wrap it in an HTMLElement that will be used as", "the arrow."].join(" "));
}
}
if (!contains(state.elements.popper, arrowElement)) {
if (true) {
console.error(['Popper: "arrow" modifier\'s `element` must be a child of the popper', "element."].join(" "));
}
return;
}
state.elements.arrow = arrowElement;
}
var arrow_default = {
name: "arrow",
enabled: true,
phase: "main",
fn: arrow,
effect: effect2,
requires: ["popperOffsets"],
requiresIfExists: ["preventOverflow"]
};
// node_modules/@popperjs/core/lib/utils/getVariation.js
function getVariation(placement) {
return placement.split("-")[1];
}
// node_modules/@popperjs/core/lib/modifiers/computeStyles.js
var unsetSides = {
top: "auto",
right: "auto",
bottom: "auto",
left: "auto"
};
function roundOffsetsByDPR(_ref, win) {
var x = _ref.x, y = _ref.y;
var dpr = win.devicePixelRatio || 1;
return {
x: round(x * dpr) / dpr || 0,
y: round(y * dpr) / dpr || 0
};
}
function mapToStyles(_ref2) {
var _Object$assign2;
var popper2 = _ref2.popper, popperRect = _ref2.popperRect, placement = _ref2.placement, variation = _ref2.variation, offsets = _ref2.offsets, position = _ref2.position, gpuAcceleration = _ref2.gpuAcceleration, adaptive = _ref2.adaptive, roundOffsets = _ref2.roundOffsets, isFixed = _ref2.isFixed;
var _offsets$x = offsets.x, x = _offsets$x === void 0 ? 0 : _offsets$x, _offsets$y = offsets.y, y = _offsets$y === void 0 ? 0 : _offsets$y;
var _ref3 = typeof roundOffsets === "function" ? roundOffsets({
x,
y
}) : {
x,
y
};
x = _ref3.x;
y = _ref3.y;
var hasX = offsets.hasOwnProperty("x");
var hasY = offsets.hasOwnProperty("y");
var sideX = left;
var sideY = top;
var win = window;
if (adaptive) {
var offsetParent = getOffsetParent(popper2);
var heightProp = "clientHeight";
var widthProp = "clientWidth";
if (offsetParent === getWindow(popper2)) {
offsetParent = getDocumentElement(popper2);
if (getComputedStyle2(offsetParent).position !== "static" && position === "absolute") {
heightProp = "scrollHeight";
widthProp = "scrollWidth";
}
}
offsetParent = offsetParent;
if (placement === top || (placement === left || placement === right) && variation === end) {
sideY = bottom;
var offsetY = isFixed && offsetParent === win && win.visualViewport ? win.visualViewport.height : (
// $FlowFixMe[prop-missing]
offsetParent[heightProp]
);
y -= offsetY - popperRect.height;
y *= gpuAcceleration ? 1 : -1;
}
if (placement === left || (placement === top || placement === bottom) && variation === end) {
sideX = right;
var offsetX = isFixed && offsetParent === win && win.visualViewport ? win.visualViewport.width : (
// $FlowFixMe[prop-missing]
offsetParent[widthProp]
);
x -= offsetX - popperRect.width;
x *= gpuAcceleration ? 1 : -1;
}
}
var commonStyles = Object.assign({
position
}, adaptive && unsetSides);
var _ref4 = roundOffsets === true ? roundOffsetsByDPR({
x,
y
}, getWindow(popper2)) : {
x,
y
};
x = _ref4.x;
y = _ref4.y;
if (gpuAcceleration) {
var _Object$assign;
return Object.assign({}, commonStyles, (_Object$assign = {}, _Object$assign[sideY] = hasY ? "0" : "", _Object$assign[sideX] = hasX ? "0" : "", _Object$assign.transform = (win.devicePixelRatio || 1) <= 1 ? "translate(" + x + "px, " + y + "px)" : "translate3d(" + x + "px, " + y + "px, 0)", _Object$assign));
}
return Object.assign({}, commonStyles, (_Object$assign2 = {}, _Object$assign2[sideY] = hasY ? y + "px" : "", _Object$assign2[sideX] = hasX ? x + "px" : "", _Object$assign2.transform = "", _Object$assign2));
}
function computeStyles(_ref5) {
var state = _ref5.state, options = _ref5.options;
var _options$gpuAccelerat = options.gpuAcceleration, gpuAcceleration = _options$gpuAccelerat === void 0 ? true : _options$gpuAccelerat, _options$adaptive = options.adaptive, adaptive = _options$adaptive === void 0 ? true : _options$adaptive, _options$roundOffsets = options.roundOffsets, roundOffsets = _options$roundOffsets === void 0 ? true : _options$roundOffsets;
if (true) {
var transitionProperty = getComputedStyle2(state.elements.popper).transitionProperty || "";
if (adaptive && ["transform", "top", "right", "bottom", "left"].some(function(property) {
return transitionProperty.indexOf(property) >= 0;
})) {
console.warn(["Popper: Detected CSS transitions on at least one of the following", 'CSS properties: "transform", "top", "right", "bottom", "left".', "\n\n", 'Disable the "computeStyles" modifier\'s `adaptive` option to allow', "for smooth transitions, or remove these properties from the CSS", "transition declaration on the popper element if only transitioning", "opacity or background-color for example.", "\n\n", "We recommend using the popper element as a wrapper around an inner", "element that can have any CSS property transitioned for animations."].join(" "));
}
}
var commonStyles = {
placement: getBasePlacement(state.placement),
variation: getVariation(state.placement),
popper: state.elements.popper,
popperRect: state.rects.popper,
gpuAcceleration,
isFixed: state.options.strategy === "fixed"
};
if (state.modifiersData.popperOffsets != null) {
state.styles.popper = Object.assign({}, state.styles.popper, mapToStyles(Object.assign({}, commonStyles, {
offsets: state.modifiersData.popperOffsets,
position: state.options.strategy,
adaptive,
roundOffsets
})));
}
if (state.modifiersData.arrow != null) {
state.styles.arrow = Object.assign({}, state.styles.arrow, mapToStyles(Object.assign({}, commonStyles, {
offsets: state.modifiersData.arrow,
position: "absolute",
adaptive: false,
roundOffsets
})));
}
state.attributes.popper = Object.assign({}, state.attributes.popper, {
"data-popper-placement": state.placement
});
}
var computeStyles_default = {
name: "computeStyles",
enabled: true,
phase: "beforeWrite",
fn: computeStyles,
data: {}
};
// node_modules/@popperjs/core/lib/modifiers/eventListeners.js
var passive = {
passive: true
};
function effect3(_ref) {
var state = _ref.state, instance11 = _ref.instance, options = _ref.options;
var _options$scroll = options.scroll, scroll = _options$scroll === void 0 ? true : _options$scroll, _options$resize = options.resize, resize = _options$resize === void 0 ? true : _options$resize;
var window2 = getWindow(state.elements.popper);
var scrollParents = [].concat(state.scrollParents.reference, state.scrollParents.popper);
if (scroll) {
scrollParents.forEach(function(scrollParent) {
scrollParent.addEventListener("scroll", instance11.update, passive);
});
}
if (resize) {
window2.addEventListener("resize", instance11.update, passive);
}
return function() {
if (scroll) {
scrollParents.forEach(function(scrollParent) {
scrollParent.removeEventListener("scroll", instance11.update, passive);
});
}
if (resize) {
window2.removeEventListener("resize", instance11.update, passive);
}
};
}
var eventListeners_default = {
name: "eventListeners",
enabled: true,
phase: "write",
fn: function fn() {
},
effect: effect3,
data: {}
};
// node_modules/@popperjs/core/lib/utils/getOppositePlacement.js
var hash = {
left: "right",
right: "left",
bottom: "top",
top: "bottom"
};
function getOppositePlacement(placement) {
return placement.replace(/left|right|bottom|top/g, function(matched) {
return hash[matched];
});
}
// node_modules/@popperjs/core/lib/utils/getOppositeVariationPlacement.js
var hash2 = {
start: "end",
end: "start"
};
function getOppositeVariationPlacement(placement) {
return placement.replace(/start|end/g, function(matched) {
return hash2[matched];
});
}
// node_modules/@popperjs/core/lib/dom-utils/getWindowScroll.js
function getWindowScroll(node) {
var win = getWindow(node);
var scrollLeft = win.pageXOffset;
var scrollTop = win.pageYOffset;
return {
scrollLeft,
scrollTop
};
}
// node_modules/@popperjs/core/lib/dom-utils/getWindowScrollBarX.js
function getWindowScrollBarX(element2) {
return getBoundingClientRect(getDocumentElement(element2)).left + getWindowScroll(element2).scrollLeft;
}
// node_modules/@popperjs/core/lib/dom-utils/getViewportRect.js
function getViewportRect(element2, strategy) {
var win = getWindow(element2);
var html = getDocumentElement(element2);
var visualViewport = win.visualViewport;
var width = html.clientWidth;
var height = html.clientHeight;
var x = 0;
var y = 0;
if (visualViewport) {
width = visualViewport.width;
height = visualViewport.height;
var layoutViewport = isLayoutViewport();
if (layoutViewport || !layoutViewport && strategy === "fixed") {
x = visualViewport.offsetLeft;
y = visualViewport.offsetTop;
}
}
return {
width,
height,
x: x + getWindowScrollBarX(element2),
y
};
}
// node_modules/@popperjs/core/lib/dom-utils/getDocumentRect.js
function getDocumentRect(element2) {
var _element$ownerDocumen;
var html = getDocumentElement(element2);
var winScroll = getWindowScroll(element2);
var body = (_element$ownerDocumen = element2.ownerDocument) == null ? void 0 : _element$ownerDocumen.body;
var width = max(html.scrollWidth, html.clientWidth, body ? body.scrollWidth : 0, body ? body.clientWidth : 0);
var height = max(html.scrollHeight, html.clientHeight, body ? body.scrollHeight : 0, body ? body.clientHeight : 0);
var x = -winScroll.scrollLeft + getWindowScrollBarX(element2);
var y = -winScroll.scrollTop;
if (getComputedStyle2(body || html).direction === "rtl") {
x += max(html.clientWidth, body ? body.clientWidth : 0) - width;
}
return {
width,
height,
x,
y
};
}
// node_modules/@popperjs/core/lib/dom-utils/isScrollParent.js
function isScrollParent(element2) {
var _getComputedStyle = getComputedStyle2(element2), overflow = _getComputedStyle.overflow, overflowX = _getComputedStyle.overflowX, overflowY = _getComputedStyle.overflowY;
return /auto|scroll|overlay|hidden/.test(overflow + overflowY + overflowX);
}
// node_modules/@popperjs/core/lib/dom-utils/getScrollParent.js
function getScrollParent(node) {
if (["html", "body", "#document"].indexOf(getNodeName(node)) >= 0) {
return node.ownerDocument.body;
}
if (isHTMLElement(node) && isScrollParent(node)) {
return node;
}
return getScrollParent(getParentNode(node));
}
// node_modules/@popperjs/core/lib/dom-utils/listScrollParents.js
function listScrollParents(element2, list) {
var _element$ownerDocumen;
if (list === void 0) {
list = [];
}
var scrollParent = getScrollParent(element2);
var isBody = scrollParent === ((_element$ownerDocumen = element2.ownerDocument) == null ? void 0 : _element$ownerDocumen.body);
var win = getWindow(scrollParent);
var target = isBody ? [win].concat(win.visualViewport || [], isScrollParent(scrollParent) ? scrollParent : []) : scrollParent;
var updatedList = list.concat(target);
return isBody ? updatedList : (
// $FlowFixMe[incompatible-call]: isBody tells us target will be an HTMLElement here
updatedList.concat(listScrollParents(getParentNode(target)))
);
}
// node_modules/@popperjs/core/lib/utils/rectToClientRect.js
function rectToClientRect(rect) {
return Object.assign({}, rect, {
left: rect.x,
top: rect.y,
right: rect.x + rect.width,
bottom: rect.y + rect.height
});
}
// node_modules/@popperjs/core/lib/dom-utils/getClippingRect.js
function getInnerBoundingClientRect(element2, strategy) {
var rect = getBoundingClientRect(element2, false, strategy === "fixed");
rect.top = rect.top + element2.clientTop;
rect.left = rect.left + element2.clientLeft;
rect.bottom = rect.top + element2.clientHeight;
rect.right = rect.left + element2.clientWidth;
rect.width = element2.clientWidth;
rect.height = element2.clientHeight;
rect.x = rect.left;
rect.y = rect.top;
return rect;
}
function getClientRectFromMixedType(element2, clippingParent, strategy) {
return clippingParent === viewport ? rectToClientRect(getViewportRect(element2, strategy)) : isElement(clippingParent) ? getInnerBoundingClientRect(clippingParent, strategy) : rectToClientRect(getDocumentRect(getDocumentElement(element2)));
}
function getClippingParents(element2) {
var clippingParents2 = listScrollParents(getParentNode(element2));
var canEscapeClipping = ["absolute", "fixed"].indexOf(getComputedStyle2(element2).position) >= 0;
var clipperElement = canEscapeClipping && isHTMLElement(element2) ? getOffsetParent(element2) : element2;
if (!isElement(clipperElement)) {
return [];
}
return clippingParents2.filter(function(clippingParent) {
return isElement(clippingParent) && contains(clippingParent, clipperElement) && getNodeName(clippingParent) !== "body";
});
}
function getClippingRect(element2, boundary, rootBoundary, strategy) {
var mainClippingParents = boundary === "clippingParents" ? getClippingParents(element2) : [].concat(boundary);
var clippingParents2 = [].concat(mainClippingParents, [rootBoundary]);
var firstClippingParent = clippingParents2[0];
var clippingRect = clippingParents2.reduce(function(accRect, clippingParent) {
var rect = getClientRectFromMixedType(element2, clippingParent, strategy);
accRect.top = max(rect.top, accRect.top);
accRect.right = min(rect.right, accRect.right);
accRect.bottom = min(rect.bottom, accRect.bottom);
accRect.left = max(rect.left, accRect.left);
return accRect;
}, getClientRectFromMixedType(element2, firstClippingParent, strategy));
clippingRect.width = clippingRect.right - clippingRect.left;
clippingRect.height = clippingRect.bottom - clippingRect.top;
clippingRect.x = clippingRect.left;
clippingRect.y = clippingRect.top;
return clippingRect;
}
// node_modules/@popperjs/core/lib/utils/computeOffsets.js
function computeOffsets(_ref) {
var reference2 = _ref.reference, element2 = _ref.element, placement = _ref.placement;
var basePlacement = placement ? getBasePlacement(placement) : null;
var variation = placement ? getVariation(placement) : null;
var commonX = reference2.x + reference2.width / 2 - element2.width / 2;
var commonY = reference2.y + reference2.height / 2 - element2.height / 2;
var offsets;
switch (basePlacement) {
case top:
offsets = {
x: commonX,
y: reference2.y - element2.height
};
break;
case bottom:
offsets = {
x: commonX,
y: reference2.y + reference2.height
};
break;
case right:
offsets = {
x: reference2.x + reference2.width,
y: commonY
};
break;
case left:
offsets = {
x: reference2.x - element2.width,
y: commonY
};
break;
default:
offsets = {
x: reference2.x,
y: reference2.y
};
}
var mainAxis = basePlacement ? getMainAxisFromPlacement(basePlacement) : null;
if (mainAxis != null) {
var len = mainAxis === "y" ? "height" : "width";
switch (variation) {
case start:
offsets[mainAxis] = offsets[mainAxis] - (reference2[len] / 2 - element2[len] / 2);
break;
case end:
offsets[mainAxis] = offsets[mainAxis] + (reference2[len] / 2 - element2[len] / 2);
break;
default:
}
}
return offsets;
}
// node_modules/@popperjs/core/lib/utils/detectOverflow.js
function detectOverflow(state, options) {
if (options === void 0) {
options = {};
}
var _options = options, _options$placement = _options.placement, placement = _options$placement === void 0 ? state.placement : _options$placement, _options$strategy = _options.strategy, strategy = _options$strategy === void 0 ? state.strategy : _options$strategy, _options$boundary = _options.boundary, boundary = _options$boundary === void 0 ? clippingParents : _options$boundary, _options$rootBoundary = _options.rootBoundary, rootBoundary = _options$rootBoundary === void 0 ? viewport : _options$rootBoundary, _options$elementConte = _options.elementContext, elementContext = _options$elementConte === void 0 ? popper : _options$elementConte, _options$altBoundary = _options.altBoundary, altBoundary = _options$altBoundary === void 0 ? false : _options$altBoundary, _options$padding = _options.padding, padding = _options$padding === void 0 ? 0 : _options$padding;
var paddingObject = mergePaddingObject(typeof padding !== "number" ? padding : expandToHashMap(padding, basePlacements));
var altContext = elementContext === popper ? reference : popper;
var popperRect = state.rects.popper;
var element2 = state.elements[altBoundary ? altContext : elementContext];
var clippingClientRect = getClippingRect(isElement(element2) ? element2 : element2.contextElement || getDocumentElement(state.elements.popper), boundary, rootBoundary, strategy);
var referenceClientRect = getBoundingClientRect(state.elements.reference);
var popperOffsets2 = computeOffsets({
reference: referenceClientRect,
element: popperRect,
strategy: "absolute",
placement
});
var popperClientRect = rectToClientRect(Object.assign({}, popperRect, popperOffsets2));
var elementClientRect = elementContext === popper ? popperClientRect : referenceClientRect;
var overflowOffsets = {
top: clippingClientRect.top - elementClientRect.top + paddingObject.top,
bottom: elementClientRect.bottom - clippingClientRect.bottom + paddingObject.bottom,
left: clippingClientRect.left - elementClientRect.left + paddingObject.left,
right: elementClientRect.right - clippingClientRect.right + paddingObject.right
};
var offsetData = state.modifiersData.offset;
if (elementContext === popper && offsetData) {
var offset2 = offsetData[placement];
Object.keys(overflowOffsets).forEach(function(key) {
var multiply = [right, bottom].indexOf(key) >= 0 ? 1 : -1;
var axis = [top, bottom].indexOf(key) >= 0 ? "y" : "x";
overflowOffsets[key] += offset2[axis] * multiply;
});
}
return overflowOffsets;
}
// node_modules/@popperjs/core/lib/utils/computeAutoPlacement.js
function computeAutoPlacement(state, options) {
if (options === void 0) {
options = {};
}
var _options = options, placement = _options.placement, boundary = _options.boundary, rootBoundary = _options.rootBoundary, padding = _options.padding, flipVariations = _options.flipVariations, _options$allowedAutoP = _options.allowedAutoPlacements, allowedAutoPlacements = _options$allowedAutoP === void 0 ? placements : _options$allowedAutoP;
var variation = getVariation(placement);
var placements2 = variation ? flipVariations ? variationPlacements : variationPlacements.filter(function(placement2) {
return getVariation(placement2) === variation;
}) : basePlacements;
var allowedPlacements = placements2.filter(function(placement2) {
return allowedAutoPlacements.indexOf(placement2) >= 0;
});
if (allowedPlacements.length === 0) {
allowedPlacements = placements2;
if (true) {
console.error(["Popper: The `allowedAutoPlacements` option did not allow any", "placements. Ensure the `placement` option matches the variation", "of the allowed placements.", 'For example, "auto" cannot be used to allow "bottom-start".', 'Use "auto-start" instead.'].join(" "));
}
}
var overflows = allowedPlacements.reduce(function(acc, placement2) {
acc[placement2] = detectOverflow(state, {
placement: placement2,
boundary,
rootBoundary,
padding
})[getBasePlacement(placement2)];
return acc;
}, {});
return Object.keys(overflows).sort(function(a, b) {
return overflows[a] - overflows[b];
});
}
// node_modules/@popperjs/core/lib/modifiers/flip.js
function getExpandedFallbackPlacements(placement) {
if (getBasePlacement(placement) === auto) {
return [];
}
var oppositePlacement = getOppositePlacement(placement);
return [getOppositeVariationPlacement(placement), oppositePlacement, getOppositeVariationPlacement(oppositePlacement)];
}
function flip(_ref) {
var state = _ref.state, options = _ref.options, name2 = _ref.name;
if (state.modifiersData[name2]._skip) {
return;
}
var _options$mainAxis = options.mainAxis, checkMainAxis = _options$mainAxis === void 0 ? true : _options$mainAxis, _options$altAxis = options.altAxis, checkAltAxis = _options$altAxis === void 0 ? true : _options$altAxis, specifiedFallbackPlacements = options.fallbackPlacements, padding = options.padding, boundary = options.boundary, rootBoundary = options.rootBoundary, altBoundary = options.altBoundary, _options$flipVariatio = options.flipVariations, flipVariations = _options$flipVariatio === void 0 ? true : _options$flipVariatio, allowedAutoPlacements = options.allowedAutoPlacements;
var preferredPlacement = state.options.placement;
var basePlacement = getBasePlacement(preferredPlacement);
var isBasePlacement = basePlacement === preferredPlacement;
var fallbackPlacements = specifiedFallbackPlacements || (isBasePlacement || !flipVariations ? [getOppositePlacement(preferredPlacement)] : getExpandedFallbackPlacements(preferredPlacement));
var placements2 = [preferredPlacement].concat(fallbackPlacements).reduce(function(acc, placement2) {
return acc.concat(getBasePlacement(placement2) === auto ? computeAutoPlacement(state, {
placement: placement2,
boundary,
rootBoundary,
padding,
flipVariations,
allowedAutoPlacements
}) : placement2);
}, []);
var referenceRect = state.rects.reference;
var popperRect = state.rects.popper;
var checksMap = /* @__PURE__ */ new Map();
var makeFallbackChecks = true;
var firstFittingPlacement = placements2[0];
for (var i = 0; i < placements2.length; i++) {
var placement = placements2[i];
var _basePlacement = getBasePlacement(placement);
var isStartVariation = getVariation(placement) === start;
var isVertical = [top, bottom].indexOf(_basePlacement) >= 0;
var len = isVertical ? "width" : "height";
var overflow = detectOverflow(state, {
placement,
boundary,
rootBoundary,
altBoundary,
padding
});
var mainVariationSide = isVertical ? isStartVariation ? right : left : isStartVariation ? bottom : top;
if (referenceRect[len] > popperRect[len]) {
mainVariationSide = getOppositePlacement(mainVariationSide);
}
var altVariationSide = getOppositePlacement(mainVariationSide);
var checks = [];
if (checkMainAxis) {
checks.push(overflow[_basePlacement] <= 0);
}
if (checkAltAxis) {
checks.push(overflow[mainVariationSide] <= 0, overflow[altVariationSide] <= 0);
}
if (checks.every(function(check) {
return check;
})) {
firstFittingPlacement = placement;
makeFallbackChecks = false;
break;
}
checksMap.set(placement, checks);
}
if (makeFallbackChecks) {
var numberOfChecks = flipVariations ? 3 : 1;
var _loop = function _loop2(_i2) {
var fittingPlacement = placements2.find(function(placement2) {
var checks2 = checksMap.get(placement2);
if (checks2) {
return checks2.slice(0, _i2).every(function(check) {
return check;
});
}
});
if (fittingPlacement) {
firstFittingPlacement = fittingPlacement;
return "break";
}
};
for (var _i = numberOfChecks; _i > 0; _i--) {
var _ret = _loop(_i);
if (_ret === "break")
break;
}
}
if (state.placement !== firstFittingPlacement) {
state.modifiersData[name2]._skip = true;
state.placement = firstFittingPlacement;
state.reset = true;
}
}
var flip_default = {
name: "flip",
enabled: true,
phase: "main",
fn: flip,
requiresIfExists: ["offset"],
data: {
_skip: false
}
};
// node_modules/@popperjs/core/lib/modifiers/hide.js
function getSideOffsets(overflow, rect, preventedOffsets) {
if (preventedOffsets === void 0) {
preventedOffsets = {
x: 0,
y: 0
};
}
return {
top: overflow.top - rect.height - preventedOffsets.y,
right: overflow.right - rect.width + preventedOffsets.x,
bottom: overflow.bottom - rect.height + preventedOffsets.y,
left: overflow.left - rect.width - preventedOffsets.x
};
}
function isAnySideFullyClipped(overflow) {
return [top, right, bottom, left].some(function(side) {
return overflow[side] >= 0;
});
}
function hide(_ref) {
var state = _ref.state, name2 = _ref.name;
var referenceRect = state.rects.reference;
var popperRect = state.rects.popper;
var preventedOffsets = state.modifiersData.preventOverflow;
var referenceOverflow = detectOverflow(state, {
elementContext: "reference"
});
var popperAltOverflow = detectOverflow(state, {
altBoundary: true
});
var referenceClippingOffsets = getSideOffsets(referenceOverflow, referenceRect);
var popperEscapeOffsets = getSideOffsets(popperAltOverflow, popperRect, preventedOffsets);
var isReferenceHidden = isAnySideFullyClipped(referenceClippingOffsets);
var hasPopperEscaped = isAnySideFullyClipped(popperEscapeOffsets);
state.modifiersData[name2] = {
referenceClippingOffsets,
popperEscapeOffsets,
isReferenceHidden,
hasPopperEscaped
};
state.attributes.popper = Object.assign({}, state.attributes.popper, {
"data-popper-reference-hidden": isReferenceHidden,
"data-popper-escaped": hasPopperEscaped
});
}
var hide_default = {
name: "hide",
enabled: true,
phase: "main",
requiresIfExists: ["preventOverflow"],
fn: hide
};
// node_modules/@popperjs/core/lib/modifiers/offset.js
function distanceAndSkiddingToXY(placement, rects, offset2) {
var basePlacement = getBasePlacement(placement);
var invertDistance = [left, top].indexOf(basePlacement) >= 0 ? -1 : 1;
var _ref = typeof offset2 === "function" ? offset2(Object.assign({}, rects, {
placement
})) : offset2, skidding = _ref[0], distance = _ref[1];
skidding = skidding || 0;
distance = (distance || 0) * invertDistance;
return [left, right].indexOf(basePlacement) >= 0 ? {
x: distance,
y: skidding
} : {
x: skidding,
y: distance
};
}
function offset(_ref2) {
var state = _ref2.state, options = _ref2.options, name2 = _ref2.name;
var _options$offset = options.offset, offset2 = _options$offset === void 0 ? [0, 0] : _options$offset;
var data = placements.reduce(function(acc, placement) {
acc[placement] = distanceAndSkiddingToXY(placement, state.rects, offset2);
return acc;
}, {});
var _data$state$placement = data[state.placement], x = _data$state$placement.x, y = _data$state$placement.y;
if (state.modifiersData.popperOffsets != null) {
state.modifiersData.popperOffsets.x += x;
state.modifiersData.popperOffsets.y += y;
}
state.modifiersData[name2] = data;
}
var offset_default = {
name: "offset",
enabled: true,
phase: "main",
requires: ["popperOffsets"],
fn: offset
};
// node_modules/@popperjs/core/lib/modifiers/popperOffsets.js
function popperOffsets(_ref) {
var state = _ref.state, name2 = _ref.name;
state.modifiersData[name2] = computeOffsets({
reference: state.rects.reference,
element: state.rects.popper,
strategy: "absolute",
placement: state.placement
});
}
var popperOffsets_default = {
name: "popperOffsets",
enabled: true,
phase: "read",
fn: popperOffsets,
data: {}
};
// node_modules/@popperjs/core/lib/utils/getAltAxis.js
function getAltAxis(axis) {
return axis === "x" ? "y" : "x";
}
// node_modules/@popperjs/core/lib/modifiers/preventOverflow.js
function preventOverflow(_ref) {
var state = _ref.state, options = _ref.options, name2 = _ref.name;
var _options$mainAxis = options.mainAxis, checkMainAxis = _options$mainAxis === void 0 ? true : _options$mainAxis, _options$altAxis = options.altAxis, checkAltAxis = _options$altAxis === void 0 ? false : _options$altAxis, boundary = options.boundary, rootBoundary = options.rootBoundary, altBoundary = options.altBoundary, padding = options.padding, _options$tether = options.tether, tether = _options$tether === void 0 ? true : _options$tether, _options$tetherOffset = options.tetherOffset, tetherOffset = _options$tetherOffset === void 0 ? 0 : _options$tetherOffset;
var overflow = detectOverflow(state, {
boundary,
rootBoundary,
padding,
altBoundary
});
var basePlacement = getBasePlacement(state.placement);
var variation = getVariation(state.placement);
var isBasePlacement = !variation;
var mainAxis = getMainAxisFromPlacement(basePlacement);
var altAxis = getAltAxis(mainAxis);
var popperOffsets2 = state.modifiersData.popperOffsets;
var referenceRect = state.rects.reference;
var popperRect = state.rects.popper;
var tetherOffsetValue = typeof tetherOffset === "function" ? tetherOffset(Object.assign({}, state.rects, {
placement: state.placement
})) : tetherOffset;
var normalizedTetherOffsetValue = typeof tetherOffsetValue === "number" ? {
mainAxis: tetherOffsetValue,
altAxis: tetherOffsetValue
} : Object.assign({
mainAxis: 0,
altAxis: 0
}, tetherOffsetValue);
var offsetModifierState = state.modifiersData.offset ? state.modifiersData.offset[state.placement] : null;
var data = {
x: 0,
y: 0
};
if (!popperOffsets2) {
return;
}
if (checkMainAxis) {
var _offsetModifierState$;
var mainSide = mainAxis === "y" ? top : left;
var altSide = mainAxis === "y" ? bottom : right;
var len = mainAxis === "y" ? "height" : "width";
var offset2 = popperOffsets2[mainAxis];
var min2 = offset2 + overflow[mainSide];
var max2 = offset2 - overflow[altSide];
var additive = tether ? -popperRect[len] / 2 : 0;
var minLen = variation === start ? referenceRect[len] : popperRect[len];
var maxLen = variation === start ? -popperRect[len] : -referenceRect[len];
var arrowElement = state.elements.arrow;
var arrowRect = tether && arrowElement ? getLayoutRect(arrowElement) : {
width: 0,
height: 0
};
var arrowPaddingObject = state.modifiersData["arrow#persistent"] ? state.modifiersData["arrow#persistent"].padding : getFreshSideObject();
var arrowPaddingMin = arrowPaddingObject[mainSide];
var arrowPaddingMax = arrowPaddingObject[altSide];
var arrowLen = within(0, referenceRect[len], arrowRect[len]);
var minOffset = isBasePlacement ? referenceRect[len] / 2 - additive - arrowLen - arrowPaddingMin - normalizedTetherOffsetValue.mainAxis : minLen - arrowLen - arrowPaddingMin - normalizedTetherOffsetValue.mainAxis;
var maxOffset = isBasePlacement ? -referenceRect[len] / 2 + additive + arrowLen + arrowPaddingMax + normalizedTetherOffsetValue.mainAxis : maxLen + arrowLen + arrowPaddingMax + normalizedTetherOffsetValue.mainAxis;
var arrowOffsetParent = state.elements.arrow && getOffsetParent(state.elements.arrow);
var clientOffset = arrowOffsetParent ? mainAxis === "y" ? arrowOffsetParent.clientTop || 0 : arrowOffsetParent.clientLeft || 0 : 0;
var offsetModifierValue = (_offsetModifierState$ = offsetModifierState == null ? void 0 : offsetModifierState[mainAxis]) != null ? _offsetModifierState$ : 0;
var tetherMin = offset2 + minOffset - offsetModifierValue - clientOffset;
var tetherMax = offset2 + maxOffset - offsetModifierValue;
var preventedOffset = within(tether ? min(min2, tetherMin) : min2, offset2, tether ? max(max2, tetherMax) : max2);
popperOffsets2[mainAxis] = preventedOffset;
data[mainAxis] = preventedOffset - offset2;
}
if (checkAltAxis) {
var _offsetModifierState$2;
var _mainSide = mainAxis === "x" ? top : left;
var _altSide = mainAxis === "x" ? bottom : right;
var _offset = popperOffsets2[altAxis];
var _len = altAxis === "y" ? "height" : "width";
var _min = _offset + overflow[_mainSide];
var _max = _offset - overflow[_altSide];
var isOriginSide = [top, left].indexOf(basePlacement) !== -1;
var _offsetModifierValue = (_offsetModifierState$2 = offsetModifierState == null ? void 0 : offsetModifierState[altAxis]) != null ? _offsetModifierState$2 : 0;
var _tetherMin = isOriginSide ? _min : _offset - referenceRect[_len] - popperRect[_len] - _offsetModifierValue + normalizedTetherOffsetValue.altAxis;
var _tetherMax = isOriginSide ? _offset + referenceRect[_len] + popperRect[_len] - _offsetModifierValue - normalizedTetherOffsetValue.altAxis : _max;
var _preventedOffset = tether && isOriginSide ? withinMaxClamp(_tetherMin, _offset, _tetherMax) : within(tether ? _tetherMin : _min, _offset, tether ? _tetherMax : _max);
popperOffsets2[altAxis] = _preventedOffset;
data[altAxis] = _preventedOffset - _offset;
}
state.modifiersData[name2] = data;
}
var preventOverflow_default = {
name: "preventOverflow",
enabled: true,
phase: "main",
fn: preventOverflow,
requiresIfExists: ["offset"]
};
// node_modules/@popperjs/core/lib/dom-utils/getHTMLElementScroll.js
function getHTMLElementScroll(element2) {
return {
scrollLeft: element2.scrollLeft,
scrollTop: element2.scrollTop
};
}
// node_modules/@popperjs/core/lib/dom-utils/getNodeScroll.js
function getNodeScroll(node) {
if (node === getWindow(node) || !isHTMLElement(node)) {
return getWindowScroll(node);
} else {
return getHTMLElementScroll(node);
}
}
// node_modules/@popperjs/core/lib/dom-utils/getCompositeRect.js
function isElementScaled(element2) {
var rect = element2.getBoundingClientRect();
var scaleX = round(rect.width) / element2.offsetWidth || 1;
var scaleY = round(rect.height) / element2.offsetHeight || 1;
return scaleX !== 1 || scaleY !== 1;
}
function getCompositeRect(elementOrVirtualElement, offsetParent, isFixed) {
if (isFixed === void 0) {
isFixed = false;
}
var isOffsetParentAnElement = isHTMLElement(offsetParent);
var offsetParentIsScaled = isHTMLElement(offsetParent) && isElementScaled(offsetParent);
var documentElement = getDocumentElement(offsetParent);
var rect = getBoundingClientRect(elementOrVirtualElement, offsetParentIsScaled, isFixed);
var scroll = {
scrollLeft: 0,
scrollTop: 0
};
var offsets = {
x: 0,
y: 0
};
if (isOffsetParentAnElement || !isOffsetParentAnElement && !isFixed) {
if (getNodeName(offsetParent) !== "body" || // https://github.com/popperjs/popper-core/issues/1078
isScrollParent(documentElement)) {
scroll = getNodeScroll(offsetParent);
}
if (isHTMLElement(offsetParent)) {
offsets = getBoundingClientRect(offsetParent, true);
offsets.x += offsetParent.clientLeft;
offsets.y += offsetParent.clientTop;
} else if (documentElement) {
offsets.x = getWindowScrollBarX(documentElement);
}
}
return {
x: rect.left + scroll.scrollLeft - offsets.x,
y: rect.top + scroll.scrollTop - offsets.y,
width: rect.width,
height: rect.height
};
}
// node_modules/@popperjs/core/lib/utils/orderModifiers.js
function order(modifiers) {
var map2 = /* @__PURE__ */ new Map();
var visited = /* @__PURE__ */ new Set();
var result = [];
modifiers.forEach(function(modifier) {
map2.set(modifier.name, modifier);
});
function sort(modifier) {
visited.add(modifier.name);
var requires = [].concat(modifier.requires || [], modifier.requiresIfExists || []);
requires.forEach(function(dep) {
if (!visited.has(dep)) {
var depModifier = map2.get(dep);
if (depModifier) {
sort(depModifier);
}
}
});
result.push(modifier);
}
modifiers.forEach(function(modifier) {
if (!visited.has(modifier.name)) {
sort(modifier);
}
});
return result;
}
function orderModifiers(modifiers) {
var orderedModifiers = order(modifiers);
return modifierPhases.reduce(function(acc, phase) {
return acc.concat(orderedModifiers.filter(function(modifier) {
return modifier.phase === phase;
}));
}, []);
}
// node_modules/@popperjs/core/lib/utils/debounce.js
function debounce(fn2) {
var pending;
return function() {
if (!pending) {
pending = new Promise(function(resolve2) {
Promise.resolve().then(function() {
pending = void 0;
resolve2(fn2());
});
});
}
return pending;
};
}
// node_modules/@popperjs/core/lib/utils/format.js
function format(str) {
for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
args[_key - 1] = arguments[_key];
}
return [].concat(args).reduce(function(p, c) {
return p.replace(/%s/, c);
}, str);
}
// node_modules/@popperjs/core/lib/utils/validateModifiers.js
var INVALID_MODIFIER_ERROR = 'Popper: modifier "%s" provided an invalid %s property, expected %s but got %s';
var MISSING_DEPENDENCY_ERROR = 'Popper: modifier "%s" requires "%s", but "%s" modifier is not available';
var VALID_PROPERTIES = ["name", "enabled", "phase", "fn", "effect", "requires", "options"];
function validateModifiers(modifiers) {
modifiers.forEach(function(modifier) {
[].concat(Object.keys(modifier), VALID_PROPERTIES).filter(function(value, index, self) {
return self.indexOf(value) === index;
}).forEach(function(key) {
switch (key) {
case "name":
if (typeof modifier.name !== "string") {
console.error(format(INVALID_MODIFIER_ERROR, String(modifier.name), '"name"', '"string"', '"' + String(modifier.name) + '"'));
}
break;
case "enabled":
if (typeof modifier.enabled !== "boolean") {
console.error(format(INVALID_MODIFIER_ERROR, modifier.name, '"enabled"', '"boolean"', '"' + String(modifier.enabled) + '"'));
}
break;
case "phase":
if (modifierPhases.indexOf(modifier.phase) < 0) {
console.error(format(INVALID_MODIFIER_ERROR, modifier.name, '"phase"', "either " + modifierPhases.join(", "), '"' + String(modifier.phase) + '"'));
}
break;
case "fn":
if (typeof modifier.fn !== "function") {
console.error(format(INVALID_MODIFIER_ERROR, modifier.name, '"fn"', '"function"', '"' + String(modifier.fn) + '"'));
}
break;
case "effect":
if (modifier.effect != null && typeof modifier.effect !== "function") {
console.error(format(INVALID_MODIFIER_ERROR, modifier.name, '"effect"', '"function"', '"' + String(modifier.fn) + '"'));
}
break;
case "requires":
if (modifier.requires != null && !Array.isArray(modifier.requires)) {
console.error(format(INVALID_MODIFIER_ERROR, modifier.name, '"requires"', '"array"', '"' + String(modifier.requires) + '"'));
}
break;
case "requiresIfExists":
if (!Array.isArray(modifier.requiresIfExists)) {
console.error(format(INVALID_MODIFIER_ERROR, modifier.name, '"requiresIfExists"', '"array"', '"' + String(modifier.requiresIfExists) + '"'));
}
break;
case "options":
case "data":
break;
default:
console.error('PopperJS: an invalid property has been provided to the "' + modifier.name + '" modifier, valid properties are ' + VALID_PROPERTIES.map(function(s) {
return '"' + s + '"';
}).join(", ") + '; but "' + key + '" was provided.');
}
modifier.requires && modifier.requires.forEach(function(requirement) {
if (modifiers.find(function(mod) {
return mod.name === requirement;
}) == null) {
console.error(format(MISSING_DEPENDENCY_ERROR, String(modifier.name), requirement, requirement));
}
});
});
});
}
// node_modules/@popperjs/core/lib/utils/uniqueBy.js
function uniqueBy(arr, fn2) {
var identifiers = /* @__PURE__ */ new Set();
return arr.filter(function(item) {
var identifier = fn2(item);
if (!identifiers.has(identifier)) {
identifiers.add(identifier);
return true;
}
});
}
// node_modules/@popperjs/core/lib/utils/mergeByName.js
function mergeByName(modifiers) {
var merged = modifiers.reduce(function(merged2, current) {
var existing = merged2[current.name];
merged2[current.name] = existing ? Object.assign({}, existing, current, {
options: Object.assign({}, existing.options, current.options),
data: Object.assign({}, existing.data, current.data)
}) : current;
return merged2;
}, {});
return Object.keys(merged).map(function(key) {
return merged[key];
});
}
// node_modules/@popperjs/core/lib/createPopper.js
var INVALID_ELEMENT_ERROR = "Popper: Invalid reference or popper argument provided. They must be either a DOM element or virtual element.";
var INFINITE_LOOP_ERROR = "Popper: An infinite loop in the modifiers cycle has been detected! The cycle has been interrupted to prevent a browser crash.";
var DEFAULT_OPTIONS = {
placement: "bottom",
modifiers: [],
strategy: "absolute"
};
function areValidElements() {
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
return !args.some(function(element2) {
return !(element2 && typeof element2.getBoundingClientRect === "function");
});
}
function popperGenerator(generatorOptions) {
if (generatorOptions === void 0) {
generatorOptions = {};
}
var _generatorOptions = generatorOptions, _generatorOptions$def = _generatorOptions.defaultModifiers, defaultModifiers2 = _generatorOptions$def === void 0 ? [] : _generatorOptions$def, _generatorOptions$def2 = _generatorOptions.defaultOptions, defaultOptions = _generatorOptions$def2 === void 0 ? DEFAULT_OPTIONS : _generatorOptions$def2;
return function createPopper2(reference2, popper2, options) {
if (options === void 0) {
options = defaultOptions;
}
var state = {
placement: "bottom",
orderedModifiers: [],
options: Object.assign({}, DEFAULT_OPTIONS, defaultOptions),
modifiersData: {},
elements: {
reference: reference2,
popper: popper2
},
attributes: {},
styles: {}
};
var effectCleanupFns = [];
var isDestroyed = false;
var instance11 = {
state,
setOptions: function setOptions(setOptionsAction) {
var options2 = typeof setOptionsAction === "function" ? setOptionsAction(state.options) : setOptionsAction;
cleanupModifierEffects();
state.options = Object.assign({}, defaultOptions, state.options, options2);
state.scrollParents = {
reference: isElement(reference2) ? listScrollParents(reference2) : reference2.contextElement ? listScrollParents(reference2.contextElement) : [],
popper: listScrollParents(popper2)
};
var orderedModifiers = orderModifiers(mergeByName([].concat(defaultModifiers2, state.options.modifiers)));
state.orderedModifiers = orderedModifiers.filter(function(m) {
return m.enabled;
});
if (true) {
var modifiers = uniqueBy([].concat(orderedModifiers, state.options.modifiers), function(_ref) {
var name2 = _ref.name;
return name2;
});
validateModifiers(modifiers);
if (getBasePlacement(state.options.placement) === auto) {
var flipModifier = state.orderedModifiers.find(function(_ref2) {
var name2 = _ref2.name;
return name2 === "flip";
});
if (!flipModifier) {
console.error(['Popper: "auto" placements require the "flip" modifier be', "present and enabled to work."].join(" "));
}
}
var _getComputedStyle = getComputedStyle2(popper2), marginTop = _getComputedStyle.marginTop, marginRight = _getComputedStyle.marginRight, marginBottom = _getComputedStyle.marginBottom, marginLeft = _getComputedStyle.marginLeft;
if ([marginTop, marginRight, marginBottom, marginLeft].some(function(margin) {
return parseFloat(margin);
})) {
console.warn(['Popper: CSS "margin" styles cannot be used to apply padding', "between the popper and its reference element or boundary.", "To replicate margin, use the `offset` modifier, as well as", "the `padding` option in the `preventOverflow` and `flip`", "modifiers."].join(" "));
}
}
runModifierEffects();
return instance11.update();
},
// Sync update it will always be executed, even if not necessary. This
// is useful for low frequency updates where sync behavior simplifies the
// logic.
// For high frequency updates (e.g. `resize` and `scroll` events), always
// prefer the async Popper#update method
forceUpdate: function forceUpdate() {
if (isDestroyed) {
return;
}
var _state$elements = state.elements, reference3 = _state$elements.reference, popper3 = _state$elements.popper;
if (!areValidElements(reference3, popper3)) {
if (true) {
console.error(INVALID_ELEMENT_ERROR);
}
return;
}
state.rects = {
reference: getCompositeRect(reference3, getOffsetParent(popper3), state.options.strategy === "fixed"),
popper: getLayoutRect(popper3)
};
state.reset = false;
state.placement = state.options.placement;
state.orderedModifiers.forEach(function(modifier) {
return state.modifiersData[modifier.name] = Object.assign({}, modifier.data);
});
var __debug_loops__ = 0;
for (var index = 0; index < state.orderedModifiers.length; index++) {
if (true) {
__debug_loops__ += 1;
if (__debug_loops__ > 100) {
console.error(INFINITE_LOOP_ERROR);
break;
}
}
if (state.reset === true) {
state.reset = false;
index = -1;
continue;
}
var _state$orderedModifie = state.orderedModifiers[index], fn2 = _state$orderedModifie.fn, _state$orderedModifie2 = _state$orderedModifie.options, _options = _state$orderedModifie2 === void 0 ? {} : _state$orderedModifie2, name2 = _state$orderedModifie.name;
if (typeof fn2 === "function") {
state = fn2({
state,
options: _options,
name: name2,
instance: instance11
}) || state;
}
}
},
// Async and optimistically optimized update it will not be executed if
// not necessary (debounced to run at most once-per-tick)
update: debounce(function() {
return new Promise(function(resolve2) {
instance11.forceUpdate();
resolve2(state);
});
}),
destroy: function destroy() {
cleanupModifierEffects();
isDestroyed = true;
}
};
if (!areValidElements(reference2, popper2)) {
if (true) {
console.error(INVALID_ELEMENT_ERROR);
}
return instance11;
}
instance11.setOptions(options).then(function(state2) {
if (!isDestroyed && options.onFirstUpdate) {
options.onFirstUpdate(state2);
}
});
function runModifierEffects() {
state.orderedModifiers.forEach(function(_ref3) {
var name2 = _ref3.name, _ref3$options = _ref3.options, options2 = _ref3$options === void 0 ? {} : _ref3$options, effect4 = _ref3.effect;
if (typeof effect4 === "function") {
var cleanupFn = effect4({
state,
name: name2,
instance: instance11,
options: options2
});
var noopFn = function noopFn2() {
};
effectCleanupFns.push(cleanupFn || noopFn);
}
});
}
function cleanupModifierEffects() {
effectCleanupFns.forEach(function(fn2) {
return fn2();
});
effectCleanupFns = [];
}
return instance11;
};
}
// node_modules/@popperjs/core/lib/popper.js
var defaultModifiers = [eventListeners_default, popperOffsets_default, computeStyles_default, applyStyles_default, offset_default, flip_default, preventOverflow_default, arrow_default, hide_default];
var createPopper = /* @__PURE__ */ popperGenerator({
defaultModifiers
});
// src/settings/folderSetting/suggest.ts
var wrapAround = (value, size) => {
return (value % size + size) % size;
};
var Suggest = class {
constructor(owner, containerEl, scope) {
this.owner = owner;
this.containerEl = containerEl;
containerEl.on(
"click",
".suggestion-item",
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
this.onSuggestionClick.bind(this)
);
containerEl.on(
"mousemove",
".suggestion-item",
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
this.onSuggestionMouseover.bind(this)
);
scope.register([], "ArrowUp", (event) => {
if (!event.isComposing) {
this.setSelectedItem(this.selectedItem - 1, true);
return false;
}
});
scope.register([], "ArrowDown", (event) => {
if (!event.isComposing) {
this.setSelectedItem(this.selectedItem + 1, true);
return false;
}
});
scope.register([], "Enter", (event) => {
if (!event.isComposing) {
this.useSelectedItem(event);
return false;
}
});
}
onSuggestionClick(event, el) {
event.preventDefault();
const item = this.suggestions.indexOf(el);
this.setSelectedItem(item, false);
this.useSelectedItem(event);
}
onSuggestionMouseover(_event, el) {
const item = this.suggestions.indexOf(el);
this.setSelectedItem(item, false);
}
setSuggestions(values) {
this.containerEl.empty();
const suggestionEls = [];
values.forEach((value) => {
const suggestionEl = this.containerEl.createDiv("suggestion-item");
this.owner.renderSuggestion(value, suggestionEl);
suggestionEls.push(suggestionEl);
});
this.values = values;
this.suggestions = suggestionEls;
this.setSelectedItem(0, false);
}
useSelectedItem(event) {
const currentValue = this.values[this.selectedItem];
if (currentValue) {
this.owner.selectSuggestion(currentValue, event);
}
}
setSelectedItem(selectedIndex, scrollIntoView) {
const normalizedIndex = wrapAround(
selectedIndex,
this.suggestions.length
);
const prevSelectedSuggestion = this.suggestions[this.selectedItem];
const selectedSuggestion = this.suggestions[normalizedIndex];
prevSelectedSuggestion == null ? void 0 : prevSelectedSuggestion.removeClass("is-selected");
selectedSuggestion == null ? void 0 : selectedSuggestion.addClass("is-selected");
this.selectedItem = normalizedIndex;
if (scrollIntoView) {
selectedSuggestion.scrollIntoView(false);
}
}
};
var TextInputSuggest = class {
constructor(app2, inputEl) {
this.app = app2;
this.inputEl = inputEl;
this.scope = new import_obsidian.Scope();
this.suggestEl = createDiv("suggestion-container");
const suggestion = this.suggestEl.createDiv("suggestion");
this.suggest = new Suggest(this, suggestion, this.scope);
this.scope.register([], "Escape", this.close.bind(this));
this.inputEl.addEventListener("input", this.onInputChanged.bind(this));
this.inputEl.addEventListener("focus", this.onInputChanged.bind(this));
this.inputEl.addEventListener("blur", this.close.bind(this));
this.suggestEl.on(
"mousedown",
".suggestion-container",
(event) => {
event.preventDefault();
}
);
}
onInputChanged() {
const inputStr = this.inputEl.value;
const suggestions = this.getSuggestions(inputStr);
if (!suggestions) {
this.close();
return;
}
if (suggestions.length > 0) {
this.suggest.setSuggestions(suggestions);
this.open(this.app.dom.appContainerEl, this.inputEl);
} else {
this.close();
}
}
open(container, inputEl) {
this.app.keymap.pushScope(this.scope);
container.appendChild(this.suggestEl);
this.popper = createPopper(inputEl, this.suggestEl, {
placement: "bottom-start",
modifiers: [
{
name: "sameWidth",
enabled: true,
fn: ({ state, instance: instance11 }) => {
const targetWidth = `${state.rects.reference.width}px`;
if (state.styles.popper.width === targetWidth) {
return;
}
state.styles.popper.width = targetWidth;
void instance11.update();
},
phase: "beforeWrite",
requires: ["computeStyles"]
}
]
});
}
close() {
this.app.keymap.popScope(this.scope);
this.suggest.setSuggestions([]);
if (this.popper)
this.popper.destroy();
this.suggestEl.detach();
}
};
// src/settings/folderSetting/fileSuggester.ts
var GenericTextSuggester = class extends TextInputSuggest {
constructor(app2, inputEl, items) {
super(app2, inputEl);
this.app = app2;
this.inputEl = inputEl;
this.items = items;
}
getSuggestions(inputStr) {
const inputLowerCase = inputStr.toLowerCase();
const filtered = this.items.filter((item) => {
if (item.toLowerCase().contains(inputLowerCase))
return item;
});
if (!filtered)
this.close();
if ((filtered == null ? void 0 : filtered.length) > 0)
return filtered;
return [];
}
selectSuggestion(item) {
this.inputEl.value = item;
this.inputEl.trigger("input");
this.close();
}
renderSuggestion(value, el) {
if (value)
el.setText(value);
}
};
// src/entities/IEmotionGroup.ts
var import_crypto = require("crypto");
var EmotionGroup = class {
constructor() {
this.id = (0, import_crypto.randomUUID)();
this.name = "emotion group";
this.color = "#b84444";
this.emotions = [];
}
};
// src/common/confirmationModal.ts
var import_obsidian2 = require("obsidian");
var ConfirmationModal = class extends import_obsidian2.Modal {
constructor(app2, title, onConfirmCallback, onCancelCallback) {
super(app2);
this.title = title;
this.onConfirmCallback = onConfirmCallback;
this.onCancelCallback = onCancelCallback;
}
onOpen() {
const { contentEl } = this;
this.titleEl.setText(this.title);
const btnsDiv = contentEl.createDiv();
btnsDiv.style.marginTop = "10px";
const okBtn = btnsDiv.createEl("button", { text: "Ok" });
okBtn.style.marginRight = "0.5rem";
okBtn.tabIndex = 0;
okBtn.onClickEvent(async () => await this.onConfirmCallback());
const cancelBtn = btnsDiv.createEl("button", { text: "Cancel" });
cancelBtn.tabIndex = 1;
cancelBtn.onClickEvent(() => {
if (this.onCancelCallback) {
this.onCancelCallback();
}
this.close();
});
}
onClose() {
const { contentEl } = this;
contentEl.empty();
}
};
// src/settings/folderSetting/moveDataModal.ts
var MoveDataModal = class extends ConfirmationModal {
constructor(app2, _plugin, newPath) {
super(
app2,
`Move mood tracking data from "${_plugin.settings.folderPath}" to "${newPath}" ?`,
() => this.onConfirmation()
);
this._plugin = _plugin;
this.newPath = newPath;
}
async onConfirmation() {
const adapter = this._plugin.app.vault.adapter;
const oldPathFull = this._plugin.settings.folderPath + "/" + this._plugin.dataFileName;
const newPathFull = this.newPath + "/" + this._plugin.dataFileName;
try {
await adapter.copy(oldPathFull, newPathFull);
await this._plugin.loadEntries();
} catch (error) {
this._plugin.showNotice(
"Error moving mood tracking data. See console for details."
);
if (await adapter.exists(newPathFull)) {
await adapter.remove(newPathFull);
}
throw error;
}
await adapter.remove(oldPathFull);
this._plugin.showNotice(
`Successfully moved mood tracking data from "${this._plugin.settings.folderPath}" to "${this.newPath}".`
);
this._plugin.settings.folderPath = this.newPath;
await this._plugin.saveSettings();
this.close();
}
onClose() {
const { contentEl } = this;
contentEl.empty();
}
};
// src/settings/emotionGroup/emotionGroupEditModal.ts
var import_obsidian3 = require("obsidian");
// node_modules/svelte/internal/index.mjs
function noop() {
}
function assign(tar, src) {
for (const k in src)
tar[k] = src[k];
return tar;
}
function run(fn2) {
return fn2();
}
function blank_object() {
return /* @__PURE__ */ Object.create(null);
}
function run_all(fns) {
fns.forEach(run);
}
function is_function(thing) {
return typeof thing === "function";
}
function safe_not_equal(a, b) {
return a != a ? b == b : a !== b || (a && typeof a === "object" || typeof a === "function");
}
function is_empty(obj) {
return Object.keys(obj).length === 0;
}
function exclude_internal_props(props) {
const result = {};
for (const k in props)
if (k[0] !== "$")
result[k] = props[k];
return result;
}
var is_hydrating = false;
function start_hydrating() {
is_hydrating = true;
}
function end_hydrating() {
is_hydrating = false;
}
function append(target, node) {
target.appendChild(node);
}
function append_styles(target, style_sheet_id, styles) {
const append_styles_to = get_root_for_style(target);
if (!append_styles_to.getElementById(style_sheet_id)) {
const style = element("style");
style.id = style_sheet_id;
style.textContent = styles;
append_stylesheet(append_styles_to, style);
}
}
function get_root_for_style(node) {
if (!node)
return document;
const root = node.getRootNode ? node.getRootNode() : node.ownerDocument;
if (root && root.host) {
return root;
}
return node.ownerDocument;
}
function append_stylesheet(node, style) {
append(node.head || node, style);
return style.sheet;
}
function insert(target, node, anchor) {
target.insertBefore(node, anchor || null);
}
function detach(node) {
if (node.parentNode) {
node.parentNode.removeChild(node);
}
}
function destroy_each(iterations, detaching) {
for (let i = 0; i < iterations.length; i += 1) {
if (iterations[i])
iterations[i].d(detaching);
}
}
function element(name2) {
return document.createElement(name2);
}
function text(data) {
return document.createTextNode(data);
}
function space() {
return text(" ");
}
function empty() {
return text("");
}
function listen(node, event, handler, options) {
node.addEventListener(event, handler, options);
return () => node.removeEventListener(event, handler, options);
}
function attr(node, attribute, value) {
if (value == null)
node.removeAttribute(attribute);
else if (node.getAttribute(attribute) !== value)
node.setAttribute(attribute, value);
}
function set_attributes(node, attributes) {
const descriptors2 = Object.getOwnPropertyDescriptors(node.__proto__);
for (const key in attributes) {
if (attributes[key] == null) {
node.removeAttribute(key);
} else if (key === "style") {
node.style.cssText = attributes[key];
} else if (key === "__value") {
node.value = node[key] = attributes[key];
} else if (descriptors2[key] && descriptors2[key].set) {
node[key] = attributes[key];
} else {
attr(node, key, attributes[key]);
}
}
}
function to_number(value) {
return value === "" ? null : +value;
}
function children(element2) {
return Array.from(element2.childNodes);
}
function set_data(text2, data) {
data = "" + data;
if (text2.data === data)
return;
text2.data = data;
}
function set_input_value(input, value) {
input.value = value == null ? "" : value;
}
function set_style(node, key, value, important) {
if (value === null) {
node.style.removeProperty(key);
} else {
node.style.setProperty(key, value, important ? "important" : "");
}
}
function toggle_class(element2, name2, toggle) {
element2.classList[toggle ? "add" : "remove"](name2);
}
function custom_event(type, detail, { bubbles = false, cancelable = false } = {}) {
const e = document.createEvent("CustomEvent");
e.initCustomEvent(type, bubbles, cancelable, detail);
return e;
}
var current_component;
function set_current_component(component) {
current_component = component;
}
function get_current_component() {
if (!current_component)
throw new Error("Function called outside component initialization");
return current_component;
}
function onMount(fn2) {
get_current_component().$$.on_mount.push(fn2);
}
function afterUpdate(fn2) {
get_current_component().$$.after_update.push(fn2);
}
function onDestroy(fn2) {
get_current_component().$$.on_destroy.push(fn2);
}
function createEventDispatcher() {
const component = get_current_component();
return (type, detail, { cancelable = false } = {}) => {
const callbacks = component.$$.callbacks[type];
if (callbacks) {
const event = custom_event(type, detail, { cancelable });
callbacks.slice().forEach((fn2) => {
fn2.call(component, event);
});
return !event.defaultPrevented;
}
return true;
};
}
function bubble(component, event) {
const callbacks = component.$$.callbacks[event.type];
if (callbacks) {
callbacks.slice().forEach((fn2) => fn2.call(this, event));
}
}
var dirty_components = [];
var binding_callbacks = [];
var render_callbacks = [];
var flush_callbacks = [];
var resolved_promise = /* @__PURE__ */ Promise.resolve();
var update_scheduled = false;
function schedule_update() {
if (!update_scheduled) {
update_scheduled = true;
resolved_promise.then(flush);
}
}
function add_render_callback(fn2) {
render_callbacks.push(fn2);
}
function add_flush_callback(fn2) {
flush_callbacks.push(fn2);
}
var seen_callbacks = /* @__PURE__ */ new Set();
var flushidx = 0;
function flush() {
if (flushidx !== 0) {
return;
}
const saved_component = current_component;
do {
try {
while (flushidx < dirty_components.length) {
const component = dirty_components[flushidx];
flushidx++;
set_current_component(component);
update(component.$$);
}
} catch (e) {
dirty_components.length = 0;
flushidx = 0;
throw e;
}
set_current_component(null);
dirty_components.length = 0;
flushidx = 0;
while (binding_callbacks.length)
binding_callbacks.pop()();
for (let i = 0; i < render_callbacks.length; i += 1) {
const callback2 = render_callbacks[i];
if (!seen_callbacks.has(callback2)) {
seen_callbacks.add(callback2);
callback2();
}
}
render_callbacks.length = 0;
} while (dirty_components.length);
while (flush_callbacks.length) {
flush_callbacks.pop()();
}
update_scheduled = false;
seen_callbacks.clear();
set_current_component(saved_component);
}
function update($$) {
if ($$.fragment !== null) {
$$.update();
run_all($$.before_update);
const dirty = $$.dirty;
$$.dirty = [-1];
$$.fragment && $$.fragment.p($$.ctx, dirty);
$$.after_update.forEach(add_render_callback);
}
}
function flush_render_callbacks(fns) {
const filtered = [];
const targets = [];
render_callbacks.forEach((c) => fns.indexOf(c) === -1 ? filtered.push(c) : targets.push(c));
targets.forEach((c) => c());
render_callbacks = filtered;
}
var outroing = /* @__PURE__ */ new Set();
var outros;
function group_outros() {
outros = {
r: 0,
c: [],
p: outros
// parent group
};
}
function check_outros() {
if (!outros.r) {
run_all(outros.c);
}
outros = outros.p;
}
function transition_in(block, local) {
if (block && block.i) {
outroing.delete(block);
block.i(local);
}
}
function transition_out(block, local, detach2, callback2) {
if (block && block.o) {
if (outroing.has(block))
return;
outroing.add(block);
outros.c.push(() => {
outroing.delete(block);
if (callback2) {
if (detach2)
block.d(1);
callback2();
}
});
block.o(local);
} else if (callback2) {
callback2();
}
}
var globals = typeof window !== "undefined" ? window : typeof globalThis !== "undefined" ? globalThis : global;
function get_spread_update(levels, updates) {
const update2 = {};
const to_null_out = {};
const accounted_for = { $$scope: 1 };
let i = levels.length;
while (i--) {
const o = levels[i];
const n = updates[i];
if (n) {
for (const key in o) {
if (!(key in n))
to_null_out[key] = 1;
}
for (const key in n) {
if (!accounted_for[key]) {
update2[key] = n[key];
accounted_for[key] = 1;
}
}
levels[i] = n;
} else {
for (const key in o) {
accounted_for[key] = 1;
}
}
}
for (const key in to_null_out) {
if (!(key in update2))
update2[key] = void 0;
}
return update2;
}
function get_spread_object(spread_props) {
return typeof spread_props === "object" && spread_props !== null ? spread_props : {};
}
var _boolean_attributes = [
"allowfullscreen",
"allowpaymentrequest",
"async",
"autofocus",
"autoplay",
"checked",
"controls",
"default",
"defer",
"disabled",
"formnovalidate",
"hidden",
"inert",
"ismap",
"loop",
"multiple",
"muted",
"nomodule",
"novalidate",
"open",
"playsinline",
"readonly",
"required",
"reversed",
"selected"
];
var boolean_attributes = /* @__PURE__ */ new Set([..._boolean_attributes]);
function bind(component, name2, callback2) {
const index = component.$$.props[name2];
if (index !== void 0) {
component.$$.bound[index] = callback2;
callback2(component.$$.ctx[index]);
}
}
function create_component(block) {
block && block.c();
}
function mount_component(component, target, anchor, customElement) {
const { fragment, after_update } = component.$$;
fragment && fragment.m(target, anchor);
if (!customElement) {
add_render_callback(() => {
const new_on_destroy = component.$$.on_mount.map(run).filter(is_function);
if (component.$$.on_destroy) {
component.$$.on_destroy.push(...new_on_destroy);
} else {
run_all(new_on_destroy);
}
component.$$.on_mount = [];
});
}
after_update.forEach(add_render_callback);
}
function destroy_component(component, detaching) {
const $$ = component.$$;
if ($$.fragment !== null) {
flush_render_callbacks($$.after_update);
run_all($$.on_destroy);
$$.fragment && $$.fragment.d(detaching);
$$.on_destroy = $$.fragment = null;
$$.ctx = [];
}
}
function make_dirty(component, i) {
if (component.$$.dirty[0] === -1) {
dirty_components.push(component);
schedule_update();
component.$$.dirty.fill(0);
}
component.$$.dirty[i / 31 | 0] |= 1 << i % 31;
}
function init(component, options, instance11, create_fragment11, not_equal, props, append_styles2, dirty = [-1]) {
const parent_component = current_component;
set_current_component(component);
const $$ = component.$$ = {
fragment: null,
ctx: [],
// state
props,
update: noop,
not_equal,
bound: blank_object(),
// lifecycle
on_mount: [],
on_destroy: [],
on_disconnect: [],
before_update: [],
after_update: [],
context: new Map(options.context || (parent_component ? parent_component.$$.context : [])),
// everything else
callbacks: blank_object(),
dirty,
skip_bound: false,
root: options.target || parent_component.$$.root
};
append_styles2 && append_styles2($$.root);
let ready = false;
$$.ctx = instance11 ? instance11(component, options.props || {}, (i, ret, ...rest) => {
const value = rest.length ? rest[0] : ret;
if ($$.ctx && not_equal($$.ctx[i], $$.ctx[i] = value)) {
if (!$$.skip_bound && $$.bound[i])
$$.bound[i](value);
if (ready)
make_dirty(component, i);
}
return ret;
}) : [];
$$.update();
ready = true;
run_all($$.before_update);
$$.fragment = create_fragment11 ? create_fragment11($$.ctx) : false;
if (options.target) {
if (options.hydrate) {
start_hydrating();
const nodes = children(options.target);
$$.fragment && $$.fragment.l(nodes);
nodes.forEach(detach);
} else {
$$.fragment && $$.fragment.c();
}
if (options.intro)
transition_in(component.$$.fragment);
mount_component(component, options.target, options.anchor, options.customElement);
end_hydrating();
flush();
}
set_current_component(parent_component);
}
var SvelteElement;
if (typeof HTMLElement === "function") {
SvelteElement = class extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: "open" });
}
connectedCallback() {
const { on_mount } = this.$$;
this.$$.on_disconnect = on_mount.map(run).filter(is_function);
for (const key in this.$$.slotted) {
this.appendChild(this.$$.slotted[key]);
}
}
attributeChangedCallback(attr2, _oldValue, newValue) {
this[attr2] = newValue;
}
disconnectedCallback() {
run_all(this.$$.on_disconnect);
}
$destroy() {
destroy_component(this, 1);
this.$destroy = noop;
}
$on(type, callback2) {
if (!is_function(callback2)) {
return noop;
}
const callbacks = this.$$.callbacks[type] || (this.$$.callbacks[type] = []);
callbacks.push(callback2);
return () => {
const index = callbacks.indexOf(callback2);
if (index !== -1)
callbacks.splice(index, 1);
};
}
$set($$props) {
if (this.$$set && !is_empty($$props)) {
this.$$.skip_bound = true;
this.$$set($$props);
this.$$.skip_bound = false;
}
}
};
}
var SvelteComponent = class {
$destroy() {
destroy_component(this, 1);
this.$destroy = noop;
}
$on(type, callback2) {
if (!is_function(callback2)) {
return noop;
}
const callbacks = this.$$.callbacks[type] || (this.$$.callbacks[type] = []);
callbacks.push(callback2);
return () => {
const index = callbacks.indexOf(callback2);
if (index !== -1)
callbacks.splice(index, 1);
};
}
$set($$props) {
if (this.$$set && !is_empty($$props)) {
this.$$.skip_bound = true;
this.$$set($$props);
this.$$.skip_bound = false;
}
}
};
// node_modules/svelte/store/index.mjs
var subscriber_queue = [];
function writable(value, start2 = noop) {
let stop;
const subscribers = /* @__PURE__ */ new Set();
function set2(new_value) {
if (safe_not_equal(value, new_value)) {
value = new_value;
if (stop) {
const run_queue = !subscriber_queue.length;
for (const subscriber of subscribers) {
subscriber[1]();
subscriber_queue.push(subscriber, value);
}
if (run_queue) {
for (let i = 0; i < subscriber_queue.length; i += 2) {
subscriber_queue[i][0](subscriber_queue[i + 1]);
}
subscriber_queue.length = 0;
}
}
}
}
function update2(fn2) {
set2(fn2(value));
}
function subscribe2(run2, invalidate = noop) {
const subscriber = [run2, invalidate];
subscribers.add(subscriber);
if (subscribers.size === 1) {
stop = start2(set2) || noop;
}
run2(value);
return () => {
subscribers.delete(subscriber);
if (subscribers.size === 0 && stop) {
stop();
stop = null;
}
};
}
return { set: set2, update: update2, subscribe: subscribe2 };
}
// src/store.ts
var plugin = writable();
var store_default = { plugin };
// src/settings/emotionGroup/EmotionGroupEditComponent.svelte
function add_css(target) {
append_styles(target, "svelte-1qnq7kl", ".edit-modal.svelte-1qnq7kl{height:100%;min-height:300px;display:flex;flex-direction:column;justify-content:space-between}.edit-modal-section.svelte-1qnq7kl{display:flex;flex-direction:row;justify-content:space-between}#emotionsInput.svelte-1qnq7kl{min-height:120px}");
}
function create_fragment(ctx) {
let div4;
let div0;
let label0;
let t1;
let input0;
let t2;
let div1;
let label1;
let t4;
let input1;
let t5;
let div2;
let label2;
let t7;
let textarea;
let textarea_value_value;
let t8;
let div3;
let button;
let mounted;
let dispose;
return {
c() {
div4 = element("div");
div0 = element("div");
label0 = element("label");
label0.textContent = "Group name";
t1 = space();
input0 = element("input");
t2 = space();
div1 = element("div");
label1 = element("label");
label1.textContent = "Background color";
t4 = space();
input1 = element("input");
t5 = space();
div2 = element("div");
label2 = element("label");
label2.textContent = "Emotions (separated by commas or newlines)";
t7 = space();
textarea = element("textarea");
t8 = space();
div3 = element("div");
button = element("button");
button.textContent = "Save";
attr(label0, "for", "nameInput");
attr(input0, "id", "nameInput");
attr(input0, "type", "text");
attr(div0, "class", "edit-modal-section svelte-1qnq7kl");
attr(label1, "for", "colorInput");
attr(input1, "id", "colorInput");
attr(input1, "type", "color");
attr(div1, "class", "edit-modal-section svelte-1qnq7kl");
attr(label2, "for", "emotionsInput");
attr(textarea, "id", "emotionsInput");
textarea.value = textarea_value_value = /*emotionGroup*/
ctx[0].emotions.join("\n");
attr(textarea, "class", "svelte-1qnq7kl");
attr(div2, "class", "edit-modal-section svelte-1qnq7kl");
attr(div4, "class", "edit-modal svelte-1qnq7kl");
},
m(target, anchor) {
insert(target, div4, anchor);
append(div4, div0);
append(div0, label0);
append(div0, t1);
append(div0, input0);
set_input_value(
input0,
/*emotionGroup*/
ctx[0].name
);
append(div4, t2);
append(div4, div1);
append(div1, label1);
append(div1, t4);
append(div1, input1);
set_input_value(
input1,
/*emotionGroup*/
ctx[0].color
);
append(div4, t5);
append(div4, div2);
append(div2, label2);
append(div2, t7);
append(div2, textarea);
append(div4, t8);
append(div4, div3);
append(div3, button);
if (!mounted) {
dispose = [
listen(
input0,
"input",
/*input0_input_handler*/
ctx[4]
),
listen(
input1,
"input",
/*input1_input_handler*/
ctx[5]
),
listen(
textarea,
"change",
/*onEmotionsChange*/
ctx[1]
),
listen(
button,
"click",
/*save*/
ctx[2]
)
];
mounted = true;
}
},
p(ctx2, [dirty]) {
if (dirty & /*emotionGroup*/
1 && input0.value !== /*emotionGroup*/
ctx2[0].name) {
set_input_value(
input0,
/*emotionGroup*/
ctx2[0].name
);
}
if (dirty & /*emotionGroup*/
1) {
set_input_value(
input1,
/*emotionGroup*/
ctx2[0].color
);
}
if (dirty & /*emotionGroup*/
1 && textarea_value_value !== (textarea_value_value = /*emotionGroup*/
ctx2[0].emotions.join("\n"))) {
textarea.value = textarea_value_value;
}
},
i: noop,
o: noop,
d(detaching) {
if (detaching)
detach(div4);
mounted = false;
run_all(dispose);
}
};
}
function instance($$self, $$props, $$invalidate) {
let { emotionGroup } = $$props;
let { closeModalFunc } = $$props;
let plugin2;
store_default.plugin.subscribe((p) => {
plugin2 = p;
});
function onEmotionsChange(event) {
$$invalidate(0, emotionGroup.emotions = event.target.value.split(/[\n,]/g), emotionGroup);
}
function save() {
plugin2.emotionService.saveEmotionsGroup(emotionGroup);
closeModalFunc();
}
function input0_input_handler() {
emotionGroup.name = this.value;
$$invalidate(0, emotionGroup);
}
function input1_input_handler() {
emotionGroup.color = this.value;
$$invalidate(0, emotionGroup);
}
$$self.$$set = ($$props2) => {
if ("emotionGroup" in $$props2)
$$invalidate(0, emotionGroup = $$props2.emotionGroup);
if ("closeModalFunc" in $$props2)
$$invalidate(3, closeModalFunc = $$props2.closeModalFunc);
};
return [
emotionGroup,
onEmotionsChange,
save,
closeModalFunc,
input0_input_handler,
input1_input_handler
];
}
var EmotionGroupEditComponent = class extends SvelteComponent {
constructor(options) {
super();
init(this, options, instance, create_fragment, safe_not_equal, { emotionGroup: 0, closeModalFunc: 3 }, add_css);
}
};
var EmotionGroupEditComponent_default = EmotionGroupEditComponent;
// src/settings/emotionGroup/emotionGroupEditModal.ts
var EmotionGroupEditModal = class extends import_obsidian3.Modal {
constructor(_plugin, _emotionGroup, app2) {
super(app2);
this._plugin = _plugin;
this._emotionGroup = _emotionGroup;
}
onOpen() {
store_default.plugin.set(this._plugin);
this.modalEl.addClass("mood-tracker-modal");
this.titleEl.innerText = "Edit emotion group";
this.component = new EmotionGroupEditComponent_default({
target: this.contentEl,
props: {
emotionGroup: this._emotionGroup,
closeModalFunc: () => this.close()
}
});
}
onClose() {
this.component.$destroy();
}
};
// src/settings/emotionGroup/emotionGroupDeleteModal.ts
var EmotionGroupDeleteModal = class extends ConfirmationModal {
constructor(app2, plugin2, settingsTab, emotionGroup) {
super(
app2,
`Delete emotion group "${emotionGroup.name}" ?`,
() => this.onConfirmation()
);
this.plugin = plugin2;
this.settingsTab = settingsTab;
this.emotionGroup = emotionGroup;
}
async onConfirmation() {
this.plugin.settings.emotionGroups.remove(this.emotionGroup);
this.plugin.saveSettings();
this.settingsTab.display();
this.close();
}
};
// src/settings/moodRatingLabel/moodRatingLabelsEditModal.ts
var import_obsidian4 = require("obsidian");
// src/settings/moodRatingLabel/MoodRatingLabelsEditComponent.svelte
function add_css2(target) {
append_styles(target, "svelte-j6wv8j", ".labels-aligned.svelte-j6wv8j div.svelte-j6wv8j{display:flex;flex-direction:row;justify-content:space-between}.mv-5.svelte-j6wv8j.svelte-j6wv8j{margin:5px 0}");
}
function create_fragment2(ctx) {
let div11;
let div6;
let div0;
let label0;
let t1;
let input0;
let t2;
let div1;
let label1;
let t4;
let input1;
let t5;
let div2;
let label2;
let t7;
let input2;
let t8;
let div3;
let label3;
let t10;
let input3;
let t11;
let div4;
let label4;
let t13;
let input4;
let t14;
let div5;
let label5;
let t15;
let t16_value = (
/*plugin*/
ctx[0].settings.moodRatingLabelSize + ""
);
let t16;
let t17;
let t18;
let input5;
let t19;
let div9;
let div7;
let t21;
let div8;
let t22_value = (
/*plugin*/
ctx[0].settings.moodRatingLabelDict[1] + ""
);
let t22;
let t23;
let t24_value = (
/*plugin*/
ctx[0].settings.moodRatingLabelDict[2] + ""
);
let t24;
let t25;
let t26_value = (
/*plugin*/
ctx[0].settings.moodRatingLabelDict[3] + ""
);
let t26;
let t27;
let t28_value = (
/*plugin*/
ctx[0].settings.moodRatingLabelDict[4] + ""
);
let t28;
let t29;
let t30_value = (
/*plugin*/
ctx[0].settings.moodRatingLabelDict[5] + ""
);
let t30;
let t31;
let div10;
let button;
let mounted;
let dispose;
return {
c() {
div11 = element("div");
div6 = element("div");
div0 = element("div");
label0 = element("label");
label0.textContent = "Very Good";
t1 = space();
input0 = element("input");
t2 = space();
div1 = element("div");
label1 = element("label");
label1.textContent = "Good";
t4 = space();
input1 = element("input");
t5 = space();
div2 = element("div");
label2 = element("label");
label2.textContent = "Ok";
t7 = space();
input2 = element("input");
t8 = space();
div3 = element("div");
label3 = element("label");
label3.textContent = "Bad";
t10 = space();
input3 = element("input");
t11 = space();
div4 = element("div");
label4 = element("label");
label4.textContent = "Very bad";
t13 = space();
input4 = element("input");
t14 = space();
div5 = element("div");
label5 = element("label");
t15 = text("Label size: ");
t16 = text(t16_value);
t17 = text(" rem");
t18 = space();
input5 = element("input");
t19 = space();
div9 = element("div");
div7 = element("div");
div7.textContent = "Preview:";
t21 = space();
div8 = element("div");
t22 = text(t22_value);
t23 = space();
t24 = text(t24_value);
t25 = space();
t26 = text(t26_value);
t27 = space();
t28 = text(t28_value);
t29 = space();
t30 = text(t30_value);
t31 = space();
div10 = element("div");
button = element("button");
button.textContent = "Save";
attr(label0, "for", "veryGood");
attr(input0, "id", "veryGood");
attr(input0, "type", "text");
attr(div0, "class", "mv-5 svelte-j6wv8j");
attr(label1, "for", "good");
attr(input1, "id", "good");
attr(input1, "type", "text");
attr(div1, "class", "mv-5 svelte-j6wv8j");
attr(label2, "for", "ok");
attr(input2, "id", "ok");
attr(input2, "type", "text");
attr(div2, "class", "mv-5 svelte-j6wv8j");
attr(label3, "for", "bad");
attr(input3, "id", "bad");
attr(input3, "type", "text");
attr(div3, "class", "mv-5 svelte-j6wv8j");
attr(label4, "for", "veryBad");
attr(input4, "id", "veryBad");
attr(input4, "type", "text");
attr(div4, "class", "mv-5 svelte-j6wv8j");
attr(label5, "for", "size");
attr(input5, "id", "size");
attr(input5, "type", "range");
attr(input5, "min", "0.5");
attr(input5, "max", "5");
attr(input5, "step", "0.5");
attr(div5, "class", "mv-5 svelte-j6wv8j");
attr(div6, "class", "labels-aligned svelte-j6wv8j");
set_style(
div8,
"font-size",
/*plugin*/
ctx[0].settings.moodRatingLabelSize + "rem"
);
attr(div9, "class", "mv-5 svelte-j6wv8j");
attr(div11, "class", "edit-mood-labels-modal");
},
m(target, anchor) {
insert(target, div11, anchor);
append(div11, div6);
append(div6, div0);
append(div0, label0);
append(div0, t1);
append(div0, input0);
set_input_value(
input0,
/*plugin*/
ctx[0].settings.moodRatingLabelDict[5]
);
append(div6, t2);
append(div6, div1);
append(div1, label1);
append(div1, t4);
append(div1, input1);
set_input_value(
input1,
/*plugin*/
ctx[0].settings.moodRatingLabelDict[4]
);
append(div6, t5);
append(div6, div2);
append(div2, label2);
append(div2, t7);
append(div2, input2);
set_input_value(
input2,
/*plugin*/
ctx[0].settings.moodRatingLabelDict[3]
);
append(div6, t8);
append(div6, div3);
append(div3, label3);
append(div3, t10);
append(div3, input3);
set_input_value(
input3,
/*plugin*/
ctx[0].settings.moodRatingLabelDict[2]
);
append(div6, t11);
append(div6, div4);
append(div4, label4);
append(div4, t13);
append(div4, input4);
set_input_value(
input4,
/*plugin*/
ctx[0].settings.moodRatingLabelDict[1]
);
append(div6, t14);
append(div6, div5);
append(div5, label5);
append(label5, t15);
append(label5, t16);
append(label5, t17);
append(div5, t18);
append(div5, input5);
set_input_value(
input5,
/*plugin*/
ctx[0].settings.moodRatingLabelSize
);
append(div11, t19);
append(div11, div9);
append(div9, div7);
append(div9, t21);
append(div9, div8);
append(div8, t22);
append(div8, t23);
append(div8, t24);
append(div8, t25);
append(div8, t26);
append(div8, t27);
append(div8, t28);
append(div8, t29);
append(div8, t30);
append(div11, t31);
append(div11, div10);
append(div10, button);
if (!mounted) {
dispose = [
listen(
input0,
"input",
/*input0_input_handler*/
ctx[3]
),
listen(
input1,
"input",
/*input1_input_handler*/
ctx[4]
),
listen(
input2,
"input",
/*input2_input_handler*/
ctx[5]
),
listen(
input3,
"input",
/*input3_input_handler*/
ctx[6]
),
listen(
input4,
"input",
/*input4_input_handler*/
ctx[7]
),
listen(
input5,
"change",
/*input5_change_input_handler*/
ctx[8]
),
listen(
input5,
"input",
/*input5_change_input_handler*/
ctx[8]
),
listen(
button,
"click",
/*save*/
ctx[1]
)
];
mounted = true;
}
},
p(ctx2, [dirty]) {
if (dirty & /*plugin*/
1 && input0.value !== /*plugin*/
ctx2[0].settings.moodRatingLabelDict[5]) {
set_input_value(
input0,
/*plugin*/
ctx2[0].settings.moodRatingLabelDict[5]
);
}
if (dirty & /*plugin*/
1 && input1.value !== /*plugin*/
ctx2[0].settings.moodRatingLabelDict[4]) {
set_input_value(
input1,
/*plugin*/
ctx2[0].settings.moodRatingLabelDict[4]
);
}
if (dirty & /*plugin*/
1 && input2.value !== /*plugin*/
ctx2[0].settings.moodRatingLabelDict[3]) {
set_input_value(
input2,
/*plugin*/
ctx2[0].settings.moodRatingLabelDict[3]
);
}
if (dirty & /*plugin*/
1 && input3.value !== /*plugin*/
ctx2[0].settings.moodRatingLabelDict[2]) {
set_input_value(
input3,
/*plugin*/
ctx2[0].settings.moodRatingLabelDict[2]
);
}
if (dirty & /*plugin*/
1 && input4.value !== /*plugin*/
ctx2[0].settings.moodRatingLabelDict[1]) {
set_input_value(
input4,
/*plugin*/
ctx2[0].settings.moodRatingLabelDict[1]
);
}
if (dirty & /*plugin*/
1 && t16_value !== (t16_value = /*plugin*/
ctx2[0].settings.moodRatingLabelSize + ""))
set_data(t16, t16_value);
if (dirty & /*plugin*/
1) {
set_input_value(
input5,
/*plugin*/
ctx2[0].settings.moodRatingLabelSize
);
}
if (dirty & /*plugin*/
1 && t22_value !== (t22_value = /*plugin*/
ctx2[0].settings.moodRatingLabelDict[1] + ""))
set_data(t22, t22_value);
if (dirty & /*plugin*/
1 && t24_value !== (t24_value = /*plugin*/
ctx2[0].settings.moodRatingLabelDict[2] + ""))
set_data(t24, t24_value);
if (dirty & /*plugin*/
1 && t26_value !== (t26_value = /*plugin*/
ctx2[0].settings.moodRatingLabelDict[3] + ""))
set_data(t26, t26_value);
if (dirty & /*plugin*/
1 && t28_value !== (t28_value = /*plugin*/
ctx2[0].settings.moodRatingLabelDict[4] + ""))
set_data(t28, t28_value);
if (dirty & /*plugin*/
1 && t30_value !== (t30_value = /*plugin*/
ctx2[0].settings.moodRatingLabelDict[5] + ""))
set_data(t30, t30_value);
if (dirty & /*plugin*/
1) {
set_style(
div8,
"font-size",
/*plugin*/
ctx2[0].settings.moodRatingLabelSize + "rem"
);
}
},
i: noop,
o: noop,
d(detaching) {
if (detaching)
detach(div11);
mounted = false;
run_all(dispose);
}
};
}
function instance2($$self, $$props, $$invalidate) {
let { closeModalFunc } = $$props;
let plugin2;
store_default.plugin.subscribe((p) => {
$$invalidate(0, plugin2 = p);
});
function save() {
plugin2.saveSettings();
closeModalFunc();
}
function input0_input_handler() {
plugin2.settings.moodRatingLabelDict[5] = this.value;
$$invalidate(0, plugin2);
}
function input1_input_handler() {
plugin2.settings.moodRatingLabelDict[4] = this.value;
$$invalidate(0, plugin2);
}
function input2_input_handler() {
plugin2.settings.moodRatingLabelDict[3] = this.value;
$$invalidate(0, plugin2);
}
function input3_input_handler() {
plugin2.settings.moodRatingLabelDict[2] = this.value;
$$invalidate(0, plugin2);
}
function input4_input_handler() {
plugin2.settings.moodRatingLabelDict[1] = this.value;
$$invalidate(0, plugin2);
}
function input5_change_input_handler() {
plugin2.settings.moodRatingLabelSize = to_number(this.value);
$$invalidate(0, plugin2);
}
$$self.$$set = ($$props2) => {
if ("closeModalFunc" in $$props2)
$$invalidate(2, closeModalFunc = $$props2.closeModalFunc);
};
return [
plugin2,
save,
closeModalFunc,
input0_input_handler,
input1_input_handler,
input2_input_handler,
input3_input_handler,
input4_input_handler,
input5_change_input_handler
];
}
var MoodRatingLabelsEditComponent = class extends SvelteComponent {
constructor(options) {
super();
init(this, options, instance2, create_fragment2, safe_not_equal, { closeModalFunc: 2 }, add_css2);
}
};
var MoodRatingLabelsEditComponent_default = MoodRatingLabelsEditComponent;
// src/settings/moodRatingLabel/moodRatingLabelsEditModal.ts
var MoodRatingLabelsEditModal = class extends import_obsidian4.Modal {
constructor(_plugin, app2) {
super(app2);
this._plugin = _plugin;
}
onOpen() {
store_default.plugin.set(this._plugin);
this.titleEl.innerText = "Edit mood rating labels";
this.component = new MoodRatingLabelsEditComponent_default({
target: this.contentEl,
props: {
closeModalFunc: () => this.close()
}
});
}
onClose() {
this.component.$destroy();
}
};
// src/settings/settingsTab.ts
var MoodTrackerSettingsTab = class extends import_obsidian5.PluginSettingTab {
constructor(_plugin, app2) {
super(app2, _plugin);
this._plugin = _plugin;
}
display() {
const { containerEl } = this;
containerEl.empty();
this.addTrackerModalTitleSetting();
this.addFolderPathSetting();
this.addChartColorSetting();
this.addMoodRatingLabelsSetting();
this.addAddToNoteSettings();
if (this._plugin.settings.addToJournal) {
this.addJournalPathSetting();
this.addJournalLocation();
this.addTemplateSetting();
}
this.addUseEmotionsSetting();
if (this._plugin.settings.useEmotions) {
this.addEmotionsSetting();
}
}
addTrackerModalTitleSetting() {
const setting = new import_obsidian5.Setting(this.containerEl);
setting.setName("Tracker modal title");
setting.setDesc("Title for mood tracker modal");
setting.addText((input) => {
input.inputEl.style.width = "min(400px, 35vw)";
input.setValue(this._plugin.settings.trackerModalTitle).onChange(async (value) => {
this._plugin.settings.trackerModalTitle = value;
await this._plugin.saveSettings();
});
});
}
// by C.Houmann (https://github.com/chhoumann/quickadd)
// TODO: try to implement better one, maybe look outside of obsidian plugins
addFolderPathSetting() {
const setting = new import_obsidian5.Setting(this.containerEl);
let path = this._plugin.settings.folderPath;
setting.setName("Folder to store data file");
setting.setDesc(
"A path to a folder where mood tracker data will be stored."
);
setting.addText((text2) => {
text2.inputEl.style.width = "min(335px, 35vw)";
text2.setPlaceholder("data/").setValue(this._plugin.settings.folderPath).onChange((0, import_obsidian5.debounce)(async (value) => {
if (value === this._plugin.settings.folderPath) {
return;
}
if (await this.app.vault.adapter.exists(value)) {
text2.inputEl.removeAttribute("style");
text2.inputEl.removeAttribute("title");
path = value;
return;
}
text2.inputEl.style.border = "1px solid red";
text2.inputEl.title = "Folder does not exist";
}, 500, true));
new GenericTextSuggester(
app,
text2.inputEl,
app.vault.getAllLoadedFiles().filter((f) => f instanceof import_obsidian5.TFolder && f.path !== "/").map((f) => f.path)
);
});
setting.addButton((button) => {
button.setButtonText("Apply").onClick(async () => {
new MoveDataModal(this.app, this._plugin, path).open();
});
});
}
addAddToNoteSettings() {
const setting = new import_obsidian5.Setting(this.containerEl);
setting.setName("Add mood tracking info to a note");
setting.descEl.innerHTML = `When adding a mood tracker entry, also add its info to a note (e.g daily journal).<br>
This is for journaling purposes only; main data is still stored in data.json`;
setting.addToggle((input) => {
input.setValue(this._plugin.settings.addToJournal).onChange(async (value) => {
this._plugin.settings.addToJournal = value;
await this._plugin.saveSettings();
this.display();
});
});
}
addChartColorSetting() {
const setting = new import_obsidian5.Setting(this.containerEl);
setting.setName("Chart color");
setting.setDesc("Primary color for the chart elements (e.g line or bar).");
setting.addColorPicker((picker) => {
var _a;
picker.setValue((_a = this._plugin.settings.chartColor) != null ? _a : "#000").onChange(async (value) => {
this._plugin.settings.chartColor = value;
await this._plugin.saveSettings();
});
});
}
addMoodRatingLabelsSetting() {
const setting = new import_obsidian5.Setting(this.containerEl);
setting.setName("Mood rating labels");
setting.setDesc("Labels to use for mood rating. Used in tracker modal and stats.");
setting.addButton((button) => {
button.setButtonText("Edit").onClick(async () => {
new MoodRatingLabelsEditModal(this._plugin, app).open();
});
});
}
addJournalPathSetting() {
const setting = new import_obsidian5.Setting(this.containerEl);
setting.setName("Note path");
setting.descEl.innerHTML = `Use a static file path, or {{DATE}} variable.<br>
Supports <a href="https://momentjs.com/docs/#/displaying/format/" target="_blank">moment.js formatting</a>.<br>
Example: journals/daily/{{DATE:YYYY-MM-DD}}.md
`;
setting.addText((input) => {
input.inputEl.style.width = "min(400px, 35vw)";
input.setValue(this._plugin.settings.journalFilePath).onChange(async (value) => {
this._plugin.settings.journalFilePath = value;
await this._plugin.saveSettings();
});
});
}
addJournalLocation() {
const setting = new import_obsidian5.Setting(this.containerEl);
setting.setName("Entry location");
setting.descEl.innerHTML = `Where in the journal should the Mood-Tracker entry be placed?<br>
Example: ## Mood Tracker
`;
setting.addText((input) => {
input.inputEl.style.width = "min(400px, 35vw)";
input.setValue(this._plugin.settings.journalPosition).onChange(async (value) => {
this._plugin.settings.journalPosition = value;
await this._plugin.saveSettings();
});
});
}
addTemplateSetting() {
const setting = new import_obsidian5.Setting(this.containerEl);
setting.setName("Template for inserting mood tracking entry in a note");
setting.descEl.innerHTML = `Available variables:<br>
{{DATE}} - date of entry <br>
{{TIME}} - time of entry <br>
{{ICON}} - entry's mood icon <br>
{{NOTE}} - entry's note <br>
{{EMOTIONS}} - comma-separated list of emotions, if any <br>
`;
setting.addText((input) => {
input.inputEl.style.width = "min(400px, 35vw)";
input.setValue(this._plugin.settings.entryTemplate).onChange(async (value) => {
this._plugin.settings.entryTemplate = value;
await this._plugin.saveSettings();
});
});
}
addUseEmotionsSetting() {
const setting = new import_obsidian5.Setting(this.containerEl);
setting.setName("Use emotions");
setting.setDesc("Track more nuanced emotions in addition to simple mood rating");
setting.addToggle((input) => {
input.setValue(this._plugin.settings.useEmotions).onChange(async (value) => {
this._plugin.settings.useEmotions = value;
await this._plugin.saveSettings();
this.display();
});
});
}
addEmotionsSetting() {
var _a;
const settingGroupEl = this.containerEl.createEl("div");
settingGroupEl.createEl("h4", { text: "Emotions" });
settingGroupEl.createEl("small", {
text: "A list of emotions, separated by commas or newlines. You can define one or many emotion groups, each with own color, if needed."
});
for (const [
index,
emotionGroup
] of this._plugin.settings.emotionGroups.entries()) {
const setting = new import_obsidian5.Setting(settingGroupEl);
setting.setName((_a = emotionGroup.name) != null ? _a : `Emotions group ${index}`);
setting.addExtraButton((cb) => {
cb.setIcon("arrow-up").setTooltip("Move element up").setDisabled(index === 0).onClick(() => {
if (index > 0) {
const temp = this._plugin.settings.emotionGroups[index - 1].sortOrder;
this._plugin.settings.emotionGroups[index - 1].sortOrder = emotionGroup.sortOrder;
emotionGroup.sortOrder = temp;
this._plugin.saveSettings();
this.display();
}
});
});
setting.addExtraButton((cb) => {
cb.setIcon("arrow-down").setTooltip("Move element down").setDisabled(index >= this._plugin.settings.emotionGroups.length - 1).onClick(() => {
if (index < this._plugin.settings.emotionGroups.length - 1) {
const temp = this._plugin.settings.emotionGroups[index + 1].sortOrder;
this._plugin.settings.emotionGroups[index + 1].sortOrder = emotionGroup.sortOrder;
emotionGroup.sortOrder = temp;
this._plugin.saveSettings();
this.display();
}
});
});
setting.addExtraButton((cb) => {
cb.setIcon("edit").setTooltip("Edit Group").onClick(() => {
const modal = new EmotionGroupEditModal(this._plugin, emotionGroup, this.app);
modal.open();
modal.onClose = () => {
this.display();
};
});
});
setting.addExtraButton((cb) => {
cb.setIcon("trash").setTooltip("Delete note set").onClick(async () => {
new EmotionGroupDeleteModal(
this.app,
this._plugin,
this,
emotionGroup
).open();
});
});
}
const addMoodSectionBtn = new import_obsidian5.ButtonComponent(settingGroupEl);
addMoodSectionBtn.setButtonText("Add Group");
addMoodSectionBtn.onClick(async () => {
this._plugin.settings.emotionGroups.push(new EmotionGroup());
await this._plugin.saveSettings();
this.display();
});
}
};
// src/trackerModal/trackerModal.ts
var import_obsidian6 = require("obsidian");
// node_modules/tslib/tslib.es6.js
function __awaiter(thisArg, _arguments, P, generator) {
function adopt(value) {
return value instanceof P ? value : new P(function(resolve2) {
resolve2(value);
});
}
return new (P || (P = Promise))(function(resolve2, reject) {
function fulfilled(value) {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
}
function rejected(value) {
try {
step(generator["throw"](value));
} catch (e) {
reject(e);
}
}
function step(result) {
result.done ? resolve2(result.value) : adopt(result.value).then(fulfilled, rejected);
}
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
}
// src/trackerModal/MoodRating.svelte
function add_css3(target) {
append_styles(target, "svelte-12cys5g", "span.svelte-12cys5g{margin:5px;transition:border 0.2s;border-radius:var(--radius-s);border:1px solid;border-color:transparent}span.svelte-12cys5g:hover,span.active.svelte-12cys5g{cursor:pointer;border-color:var(--text-faint);background-color:var(--color-base-40)}");
}
function create_fragment3(ctx) {
let span;
let t;
let mounted;
let dispose;
return {
c() {
span = element("span");
t = text(
/*emoji*/
ctx[0]
);
set_style(
span,
"font-size",
/*fontSize*/
ctx[2] + "rem"
);
attr(
span,
"title",
/*title*/
ctx[1]
);
attr(span, "class", "svelte-12cys5g");
toggle_class(
span,
"active",
/*isActive*/
ctx[3] === true
);
},
m(target, anchor) {
insert(target, span, anchor);
append(span, t);
if (!mounted) {
dispose = [
listen(
span,
"click",
/*setRating*/
ctx[4]
),
listen(
span,
"keypress",
/*setRating*/
ctx[4]
)
];
mounted = true;
}
},
p(ctx2, [dirty]) {
if (dirty & /*emoji*/
1)
set_data(
t,
/*emoji*/
ctx2[0]
);
if (dirty & /*fontSize*/
4) {
set_style(
span,
"font-size",
/*fontSize*/
ctx2[2] + "rem"
);
}
if (dirty & /*title*/
2) {
attr(
span,
"title",
/*title*/
ctx2[1]
);
}
if (dirty & /*isActive*/
8) {
toggle_class(
span,
"active",
/*isActive*/
ctx2[3] === true
);
}
},
i: noop,
o: noop,
d(detaching) {
if (detaching)
detach(span);
mounted = false;
run_all(dispose);
}
};
}
function instance3($$self, $$props, $$invalidate) {
let isActive;
let { emoji = "" } = $$props;
let { title = "" } = $$props;
let { rating } = $$props;
let { activeRating } = $$props;
let { fontSize } = $$props;
const dispatch = createEventDispatcher();
function setRating() {
dispatch("setRating", { rating: Number(rating) });
1;
}
$$self.$$set = ($$props2) => {
if ("emoji" in $$props2)
$$invalidate(0, emoji = $$props2.emoji);
if ("title" in $$props2)
$$invalidate(1, title = $$props2.title);
if ("rating" in $$props2)
$$invalidate(5, rating = $$props2.rating);
if ("activeRating" in $$props2)
$$invalidate(6, activeRating = $$props2.activeRating);
if ("fontSize" in $$props2)
$$invalidate(2, fontSize = $$props2.fontSize);
};
$$self.$$.update = () => {
if ($$self.$$.dirty & /*activeRating, rating*/
96) {
$:
$$invalidate(3, isActive = activeRating === Number(rating));
}
};
return [emoji, title, fontSize, isActive, setRating, rating, activeRating];
}
var MoodRating = class extends SvelteComponent {
constructor(options) {
super();
init(
this,
options,
instance3,
create_fragment3,
safe_not_equal,
{
emoji: 0,
title: 1,
rating: 5,
activeRating: 6,
fontSize: 2
},
add_css3
);
}
};
var MoodRating_default = MoodRating;
// src/trackerModal/MoodSelector.svelte
function add_css4(target) {
append_styles(target, "svelte-1vx9ttc", ".mood-section.svelte-1vx9ttc{display:flex;flex-direction:row;flex-wrap:wrap;justify-content:center;align-items:center;padding:5px 0}.mood-item.svelte-1vx9ttc{margin:3px;padding:5px;border-radius:var(--radius-s);border:1px solid;cursor:pointer;filter:opacity(60%)}.svelte-1vx9ttc:not(.mood-item.active, .mood-item:hover){background-color:var(--modal-background) !important}.mood-item.active.svelte-1vx9ttc,.mood-item.svelte-1vx9ttc:hover{filter:opacity(100%);border:1px solid;box-shadow:var(--shadow-s)}");
}
function get_each_context(ctx, list, i) {
const child_ctx = ctx.slice();
child_ctx[6] = list[i];
return child_ctx;
}
function get_each_context_1(ctx, list, i) {
const child_ctx = ctx.slice();
child_ctx[9] = list[i];
return child_ctx;
}
function create_each_block_1(ctx) {
let span;
let t_value = (
/*mood*/
ctx[9] + ""
);
let t;
let mounted;
let dispose;
function click_handler(...args) {
return (
/*click_handler*/
ctx[3](
/*mood*/
ctx[9],
...args
)
);
}
function keypress_handler(...args) {
return (
/*keypress_handler*/
ctx[4](
/*mood*/
ctx[9],
...args
)
);
}
return {
c() {
span = element("span");
t = text(t_value);
attr(span, "class", "mood-item svelte-1vx9ttc");
set_style(
span,
"border-color",
/*moodSection*/
ctx[6].color
);
set_style(
span,
"background-color",
/*moodSection*/
ctx[6].color
);
toggle_class(
span,
"active",
/*activeMoods*/
ctx[1].includes(
/*mood*/
ctx[9]
)
);
},
m(target, anchor) {
insert(target, span, anchor);
append(span, t);
if (!mounted) {
dispose = [
listen(span, "click", click_handler),
listen(span, "keypress", keypress_handler)
];
mounted = true;
}
},
p(new_ctx, dirty) {
ctx = new_ctx;
if (dirty & /*moodSections*/
1 && t_value !== (t_value = /*mood*/
ctx[9] + ""))
set_data(t, t_value);
if (dirty & /*moodSections*/
1) {
set_style(
span,
"border-color",
/*moodSection*/
ctx[6].color
);
}
if (dirty & /*moodSections*/
1) {
set_style(
span,
"background-color",
/*moodSection*/
ctx[6].color
);
}
if (dirty & /*activeMoods, moodSections*/
3) {
toggle_class(
span,
"active",
/*activeMoods*/
ctx[1].includes(
/*mood*/
ctx[9]
)
);
}
},
d(detaching) {
if (detaching)
detach(span);
mounted = false;
run_all(dispose);
}
};
}
function create_each_block(ctx) {
let div;
let t;
let each_value_1 = (
/*moodSection*/
ctx[6].emotions
);
let each_blocks = [];
for (let i = 0; i < each_value_1.length; i += 1) {
each_blocks[i] = create_each_block_1(get_each_context_1(ctx, each_value_1, i));
}
return {
c() {
div = element("div");
for (let i = 0; i < each_blocks.length; i += 1) {
each_blocks[i].c();
}
t = space();
attr(div, "class", "mood-section svelte-1vx9ttc");
},
m(target, anchor) {
insert(target, div, anchor);
for (let i = 0; i < each_blocks.length; i += 1) {
if (each_blocks[i]) {
each_blocks[i].m(div, null);
}
}
append(div, t);
},
p(ctx2, dirty) {
if (dirty & /*moodSections, activeMoods, toogleMood*/
7) {
each_value_1 = /*moodSection*/
ctx2[6].emotions;
let i;
for (i = 0; i < each_value_1.length; i += 1) {
const child_ctx = get_each_context_1(ctx2, each_value_1, i);
if (each_blocks[i]) {
each_blocks[i].p(child_ctx, dirty);
} else {
each_blocks[i] = create_each_block_1(child_ctx);
each_blocks[i].c();
each_blocks[i].m(div, t);
}
}
for (; i < each_blocks.length; i += 1) {
each_blocks[i].d(1);
}
each_blocks.length = each_value_1.length;
}
},
d(detaching) {
if (detaching)
detach(div);
destroy_each(each_blocks, detaching);
}
};
}
function create_fragment4(ctx) {
let div;
let each_value = (
/*moodSections*/
ctx[0]
);
let each_blocks = [];
for (let i = 0; i < each_value.length; i += 1) {
each_blocks[i] = create_each_block(get_each_context(ctx, each_value, i));
}
return {
c() {
div = element("div");
for (let i = 0; i < each_blocks.length; i += 1) {
each_blocks[i].c();
}
attr(div, "class", "mood-selector svelte-1vx9ttc");
},
m(target, anchor) {
insert(target, div, anchor);
for (let i = 0; i < each_blocks.length; i += 1) {
if (each_blocks[i]) {
each_blocks[i].m(div, null);
}
}
},
p(ctx2, [dirty]) {
if (dirty & /*moodSections, activeMoods, toogleMood*/
7) {
each_value = /*moodSections*/
ctx2[0];
let i;
for (i = 0; i < each_value.length; i += 1) {
const child_ctx = get_each_context(ctx2, each_value, i);
if (each_blocks[i]) {
each_blocks[i].p(child_ctx, dirty);
} else {
each_blocks[i] = create_each_block(child_ctx);
each_blocks[i].c();
each_blocks[i].m(div, null);
}
}
for (; i < each_blocks.length; i += 1) {
each_blocks[i].d(1);
}
each_blocks.length = each_value.length;
}
},
i: noop,
o: noop,
d(detaching) {
if (detaching)
detach(div);
destroy_each(each_blocks, detaching);
}
};
}
function instance4($$self, $$props, $$invalidate) {
let { moodSections } = $$props;
let { activeMoods } = $$props;
const dispatch = createEventDispatcher();
function toogleMood(mood) {
dispatch("toggleMood", { mood });
$$invalidate(0, moodSections);
}
const click_handler = (mood, e) => toogleMood(mood);
const keypress_handler = (mood, e) => toogleMood(mood);
$$self.$$set = ($$props2) => {
if ("moodSections" in $$props2)
$$invalidate(0, moodSections = $$props2.moodSections);
if ("activeMoods" in $$props2)
$$invalidate(1, activeMoods = $$props2.activeMoods);
};
return [moodSections, activeMoods, toogleMood, click_handler, keypress_handler];
}
var MoodSelector = class extends SvelteComponent {
constructor(options) {
super();
init(this, options, instance4, create_fragment4, safe_not_equal, { moodSections: 0, activeMoods: 1 }, add_css4);
}
};
var MoodSelector_default = MoodSelector;
// src/services/dateService.ts
var DateService = class {
static createDateString(date) {
return window.moment(date).format("YYYY-MM-DD");
}
static createDateTimeString(date) {
return window.moment(date).format("YYYY-MM-DDTHH:mm");
}
};
// src/trackerModal/TrackerModal.svelte
function add_css5(target) {
append_styles(target, "svelte-1yfab55", ".modal-inner-container.svelte-1yfab55>div.svelte-1yfab55{margin:0.5rem}.mood-rating-container.svelte-1yfab55.svelte-1yfab55{display:flex;flex-direction:row;align-items:center;justify-content:center;height:100%;width:100%}.note.svelte-1yfab55.svelte-1yfab55{width:100%;height:100%;resize:none;border:none;outline:none;padding:0.5rem;border:1px solid var(--background-modifier-border)}");
}
function create_if_block(ctx) {
let div;
let moodselector;
let updating_activeMoods;
let current;
function moodselector_activeMoods_binding(value) {
ctx[15](value);
}
let moodselector_props = { moodSections: (
/*moodSections*/
ctx[2]
) };
if (
/*entry*/
ctx[0].emotions !== void 0
) {
moodselector_props.activeMoods = /*entry*/
ctx[0].emotions;
}
moodselector = new MoodSelector_default({ props: moodselector_props });
binding_callbacks.push(() => bind(moodselector, "activeMoods", moodselector_activeMoods_binding));
moodselector.$on(
"toggleMood",
/*handleToggleMood*/
ctx[6]
);
return {
c() {
div = element("div");
create_component(moodselector.$$.fragment);
attr(div, "class", "feelings-container svelte-1yfab55");
},
m(target, anchor) {
insert(target, div, anchor);
mount_component(moodselector, div, null);
current = true;
},
p(ctx2, dirty) {
const moodselector_changes = {};
if (dirty & /*moodSections*/
4)
moodselector_changes.moodSections = /*moodSections*/
ctx2[2];
if (!updating_activeMoods && dirty & /*entry*/
1) {
updating_activeMoods = true;
moodselector_changes.activeMoods = /*entry*/
ctx2[0].emotions;
add_flush_callback(() => updating_activeMoods = false);
}
moodselector.$set(moodselector_changes);
},
i(local) {
if (current)
return;
transition_in(moodselector.$$.fragment, local);
current = true;
},
o(local) {
transition_out(moodselector.$$.fragment, local);
current = false;
},
d(detaching) {
if (detaching)
detach(div);
destroy_component(moodselector);
}
};
}
function create_fragment5(ctx) {
let div5;
let div0;
let h3;
let t0_value = (
/*plugin*/
ctx[1].settings.trackerModalTitle + ""
);
let t0;
let t1;
let div1;
let moodrating0;
let updating_activeRating;
let t2;
let moodrating1;
let updating_activeRating_1;
let t3;
let moodrating2;
let updating_activeRating_2;
let t4;
let moodrating3;
let updating_activeRating_3;
let t5;
let moodrating4;
let updating_activeRating_4;
let t6;
let t7;
let div2;
let textarea;
let t8;
let div4;
let div3;
let span;
let input;
let label;
let t10;
let button;
let current;
let mounted;
let dispose;
function moodrating0_activeRating_binding(value) {
ctx[10](value);
}
let moodrating0_props = {
emoji: (
/*moodRatingLabelDict*/
ctx[3][1]
),
fontSize: (
/*plugin*/
ctx[1].settings.moodRatingLabelSize
),
title: "very bad",
rating: "1"
};
if (
/*entry*/
ctx[0].moodRating !== void 0
) {
moodrating0_props.activeRating = /*entry*/
ctx[0].moodRating;
}
moodrating0 = new MoodRating_default({ props: moodrating0_props });
binding_callbacks.push(() => bind(moodrating0, "activeRating", moodrating0_activeRating_binding));
moodrating0.$on(
"setRating",
/*handleSetRating*/
ctx[5]
);
function moodrating1_activeRating_binding(value) {
ctx[11](value);
}
let moodrating1_props = {
emoji: (
/*moodRatingLabelDict*/
ctx[3][2]
),
fontSize: (
/*plugin*/
ctx[1].settings.moodRatingLabelSize
),
title: "bad",
rating: "2"
};
if (
/*entry*/
ctx[0].moodRating !== void 0
) {
moodrating1_props.activeRating = /*entry*/
ctx[0].moodRating;
}
moodrating1 = new MoodRating_default({ props: moodrating1_props });
binding_callbacks.push(() => bind(moodrating1, "activeRating", moodrating1_activeRating_binding));
moodrating1.$on(
"setRating",
/*handleSetRating*/
ctx[5]
);
function moodrating2_activeRating_binding(value) {
ctx[12](value);
}
let moodrating2_props = {
emoji: (
/*moodRatingLabelDict*/
ctx[3][3]
),
fontSize: (
/*plugin*/
ctx[1].settings.moodRatingLabelSize
),
title: "ok",
rating: "3"
};
if (
/*entry*/
ctx[0].moodRating !== void 0
) {
moodrating2_props.activeRating = /*entry*/
ctx[0].moodRating;
}
moodrating2 = new MoodRating_default({ props: moodrating2_props });
binding_callbacks.push(() => bind(moodrating2, "activeRating", moodrating2_activeRating_binding));
moodrating2.$on(
"setRating",
/*handleSetRating*/
ctx[5]
);
function moodrating3_activeRating_binding(value) {
ctx[13](value);
}
let moodrating3_props = {
emoji: (
/*moodRatingLabelDict*/
ctx[3][4]
),
fontSize: (
/*plugin*/
ctx[1].settings.moodRatingLabelSize
),
title: "good",
rating: "4"
};
if (
/*entry*/
ctx[0].moodRating !== void 0
) {
moodrating3_props.activeRating = /*entry*/
ctx[0].moodRating;
}
moodrating3 = new MoodRating_default({ props: moodrating3_props });
binding_callbacks.push(() => bind(moodrating3, "activeRating", moodrating3_activeRating_binding));
moodrating3.$on(
"setRating",
/*handleSetRating*/
ctx[5]
);
function moodrating4_activeRating_binding(value) {
ctx[14](value);
}
let moodrating4_props = {
emoji: (
/*moodRatingLabelDict*/
ctx[3][5]
),
fontSize: (
/*plugin*/
ctx[1].settings.moodRatingLabelSize
),
title: "very good",
rating: "5"
};
if (
/*entry*/
ctx[0].moodRating !== void 0
) {
moodrating4_props.activeRating = /*entry*/
ctx[0].moodRating;
}
moodrating4 = new MoodRating_default({ props: moodrating4_props });
binding_callbacks.push(() => bind(moodrating4, "activeRating", moodrating4_activeRating_binding));
moodrating4.$on(
"setRating",
/*handleSetRating*/
ctx[5]
);
let if_block = (
/*plugin*/
ctx[1].settings.useEmotions && create_if_block(ctx)
);
return {
c() {
div5 = element("div");
div0 = element("div");
h3 = element("h3");
t0 = text(t0_value);
t1 = space();
div1 = element("div");
create_component(moodrating0.$$.fragment);
t2 = space();
create_component(moodrating1.$$.fragment);
t3 = space();
create_component(moodrating2.$$.fragment);
t4 = space();
create_component(moodrating3.$$.fragment);
t5 = space();
create_component(moodrating4.$$.fragment);
t6 = space();
if (if_block)
if_block.c();
t7 = space();
div2 = element("div");
textarea = element("textarea");
t8 = space();
div4 = element("div");
div3 = element("div");
span = element("span");
span.textContent = "date & time of entry ";
input = element("input");
label = element("label");
t10 = space();
button = element("button");
button.textContent = "Save";
set_style(div0, "display", "flex");
set_style(div0, "justify-content", "center");
attr(div0, "class", "svelte-1yfab55");
attr(div1, "class", "mood-rating-container svelte-1yfab55");
attr(textarea, "class", "note svelte-1yfab55");
attr(textarea, "placeholder", "add a note about what you feel (optional)");
attr(div2, "class", "note-container svelte-1yfab55");
set_style(div2, "font-size", "100%");
attr(input, "id", "datetime");
attr(input, "type", "datetime-local");
input.value = /*dateTimeString*/
ctx[4];
set_style(input, "cursor", "pointer");
attr(label, "for", "datetime");
set_style(div3, "display", "flex");
set_style(div3, "align-items", "center");
set_style(div3, "gap", "0.8rem");
set_style(button, "cursor", "pointer");
set_style(div4, "display", "flex");
set_style(div4, "justify-content", "space-between");
attr(div4, "class", "svelte-1yfab55");
attr(div5, "class", "modal-inner-container svelte-1yfab55");
},
m(target, anchor) {
insert(target, div5, anchor);
append(div5, div0);
append(div0, h3);
append(h3, t0);
append(div5, t1);
append(div5, div1);
mount_component(moodrating0, div1, null);
append(div1, t2);
mount_component(moodrating1, div1, null);
append(div1, t3);
mount_component(moodrating2, div1, null);
append(div1, t4);
mount_component(moodrating3, div1, null);
append(div1, t5);
mount_component(moodrating4, div1, null);
append(div5, t6);
if (if_block)
if_block.m(div5, null);
append(div5, t7);
append(div5, div2);
append(div2, textarea);
set_input_value(
textarea,
/*entry*/
ctx[0].note
);
append(div5, t8);
append(div5, div4);
append(div4, div3);
append(div3, span);
append(div3, input);
append(div3, label);
append(div4, t10);
append(div4, button);
current = true;
if (!mounted) {
dispose = [
listen(
textarea,
"input",
/*textarea_input_handler*/
ctx[16]
),
listen(
input,
"change",
/*handleDateTimeChange*/
ctx[7]
),
listen(
button,
"click",
/*saveEntry*/
ctx[8]
)
];
mounted = true;
}
},
p(ctx2, [dirty]) {
if ((!current || dirty & /*plugin*/
2) && t0_value !== (t0_value = /*plugin*/
ctx2[1].settings.trackerModalTitle + ""))
set_data(t0, t0_value);
const moodrating0_changes = {};
if (dirty & /*moodRatingLabelDict*/
8)
moodrating0_changes.emoji = /*moodRatingLabelDict*/
ctx2[3][1];
if (dirty & /*plugin*/
2)
moodrating0_changes.fontSize = /*plugin*/
ctx2[1].settings.moodRatingLabelSize;
if (!updating_activeRating && dirty & /*entry*/
1) {
updating_activeRating = true;
moodrating0_changes.activeRating = /*entry*/
ctx2[0].moodRating;
add_flush_callback(() => updating_activeRating = false);
}
moodrating0.$set(moodrating0_changes);
const moodrating1_changes = {};
if (dirty & /*moodRatingLabelDict*/
8)
moodrating1_changes.emoji = /*moodRatingLabelDict*/
ctx2[3][2];
if (dirty & /*plugin*/
2)
moodrating1_changes.fontSize = /*plugin*/
ctx2[1].settings.moodRatingLabelSize;
if (!updating_activeRating_1 && dirty & /*entry*/
1) {
updating_activeRating_1 = true;
moodrating1_changes.activeRating = /*entry*/
ctx2[0].moodRating;
add_flush_callback(() => updating_activeRating_1 = false);
}
moodrating1.$set(moodrating1_changes);
const moodrating2_changes = {};
if (dirty & /*moodRatingLabelDict*/
8)
moodrating2_changes.emoji = /*moodRatingLabelDict*/
ctx2[3][3];
if (dirty & /*plugin*/
2)
moodrating2_changes.fontSize = /*plugin*/
ctx2[1].settings.moodRatingLabelSize;
if (!updating_activeRating_2 && dirty & /*entry*/
1) {
updating_activeRating_2 = true;
moodrating2_changes.activeRating = /*entry*/
ctx2[0].moodRating;
add_flush_callback(() => updating_activeRating_2 = false);
}
moodrating2.$set(moodrating2_changes);
const moodrating3_changes = {};
if (dirty & /*moodRatingLabelDict*/
8)
moodrating3_changes.emoji = /*moodRatingLabelDict*/
ctx2[3][4];
if (dirty & /*plugin*/
2)
moodrating3_changes.fontSize = /*plugin*/
ctx2[1].settings.moodRatingLabelSize;
if (!updating_activeRating_3 && dirty & /*entry*/
1) {
updating_activeRating_3 = true;
moodrating3_changes.activeRating = /*entry*/
ctx2[0].moodRating;
add_flush_callback(() => updating_activeRating_3 = false);
}
moodrating3.$set(moodrating3_changes);
const moodrating4_changes = {};
if (dirty & /*moodRatingLabelDict*/
8)
moodrating4_changes.emoji = /*moodRatingLabelDict*/
ctx2[3][5];
if (dirty & /*plugin*/
2)
moodrating4_changes.fontSize = /*plugin*/
ctx2[1].settings.moodRatingLabelSize;
if (!updating_activeRating_4 && dirty & /*entry*/
1) {
updating_activeRating_4 = true;
moodrating4_changes.activeRating = /*entry*/
ctx2[0].moodRating;
add_flush_callback(() => updating_activeRating_4 = false);
}
moodrating4.$set(moodrating4_changes);
if (
/*plugin*/
ctx2[1].settings.useEmotions
) {
if (if_block) {
if_block.p(ctx2, dirty);
if (dirty & /*plugin*/
2) {
transition_in(if_block, 1);
}
} else {
if_block = create_if_block(ctx2);
if_block.c();
transition_in(if_block, 1);
if_block.m(div5, t7);
}
} else if (if_block) {
group_outros();
transition_out(if_block, 1, 1, () => {
if_block = null;
});
check_outros();
}
if (dirty & /*entry*/
1) {
set_input_value(
textarea,
/*entry*/
ctx2[0].note
);
}
if (!current || dirty & /*dateTimeString*/
16) {
input.value = /*dateTimeString*/
ctx2[4];
}
},
i(local) {
if (current)
return;
transition_in(moodrating0.$$.fragment, local);
transition_in(moodrating1.$$.fragment, local);
transition_in(moodrating2.$$.fragment, local);
transition_in(moodrating3.$$.fragment, local);
transition_in(moodrating4.$$.fragment, local);
transition_in(if_block);
current = true;
},
o(local) {
transition_out(moodrating0.$$.fragment, local);
transition_out(moodrating1.$$.fragment, local);
transition_out(moodrating2.$$.fragment, local);
transition_out(moodrating3.$$.fragment, local);
transition_out(moodrating4.$$.fragment, local);
transition_out(if_block);
current = false;
},
d(detaching) {
if (detaching)
detach(div5);
destroy_component(moodrating0);
destroy_component(moodrating1);
destroy_component(moodrating2);
destroy_component(moodrating3);
destroy_component(moodrating4);
if (if_block)
if_block.d();
mounted = false;
run_all(dispose);
}
};
}
function instance5($$self, $$props, $$invalidate) {
let dateTimeString;
let plugin2;
let moodSections = [];
let moodRatingLabelDict = {};
let insertToNote = false;
let { entry } = $$props;
store_default.plugin.subscribe((p) => {
$$invalidate(2, moodSections = p.settings.emotionGroups);
$$invalidate(1, plugin2 = p);
$$invalidate(3, moodRatingLabelDict = p.settings.moodRatingLabelDict);
insertToNote = plugin2.settings.addToJournal;
});
function handleSetRating(event) {
$$invalidate(0, entry.moodRating = Number(event.detail.rating), entry);
}
function handleToggleMood(event) {
if (entry.emotions.includes(event.detail.mood)) {
$$invalidate(0, entry.emotions = entry.emotions.filter((m) => m !== event.detail.mood), entry);
} else {
entry.emotions.push(event.detail.mood);
}
}
function handleDateTimeChange(event) {
$$invalidate(0, entry.dateTime = window.moment(event.target.value).toDate(), entry);
}
function saveEntry() {
return __awaiter(this, void 0, void 0, function* () {
yield plugin2.saveEntry(entry);
if (insertToNote) {
plugin2.noteService.addEntryToJournal(entry);
}
closeModalFunc();
});
}
let { closeModalFunc } = $$props;
function moodrating0_activeRating_binding(value) {
if ($$self.$$.not_equal(entry.moodRating, value)) {
entry.moodRating = value;
$$invalidate(0, entry);
}
}
function moodrating1_activeRating_binding(value) {
if ($$self.$$.not_equal(entry.moodRating, value)) {
entry.moodRating = value;
$$invalidate(0, entry);
}
}
function moodrating2_activeRating_binding(value) {
if ($$self.$$.not_equal(entry.moodRating, value)) {
entry.moodRating = value;
$$invalidate(0, entry);
}
}
function moodrating3_activeRating_binding(value) {
if ($$self.$$.not_equal(entry.moodRating, value)) {
entry.moodRating = value;
$$invalidate(0, entry);
}
}
function moodrating4_activeRating_binding(value) {
if ($$self.$$.not_equal(entry.moodRating, value)) {
entry.moodRating = value;
$$invalidate(0, entry);
}
}
function moodselector_activeMoods_binding(value) {
if ($$self.$$.not_equal(entry.emotions, value)) {
entry.emotions = value;
$$invalidate(0, entry);
}
}
function textarea_input_handler() {
entry.note = this.value;
$$invalidate(0, entry);
}
$$self.$$set = ($$props2) => {
if ("entry" in $$props2)
$$invalidate(0, entry = $$props2.entry);
if ("closeModalFunc" in $$props2)
$$invalidate(9, closeModalFunc = $$props2.closeModalFunc);
};
$$self.$$.update = () => {
if ($$self.$$.dirty & /*entry*/
1) {
$:
$$invalidate(4, dateTimeString = DateService.createDateTimeString(entry.dateTime));
}
};
return [
entry,
plugin2,
moodSections,
moodRatingLabelDict,
dateTimeString,
handleSetRating,
handleToggleMood,
handleDateTimeChange,
saveEntry,
closeModalFunc,
moodrating0_activeRating_binding,
moodrating1_activeRating_binding,
moodrating2_activeRating_binding,
moodrating3_activeRating_binding,
moodrating4_activeRating_binding,
moodselector_activeMoods_binding,
textarea_input_handler
];
}
var TrackerModal = class extends SvelteComponent {
constructor(options) {
super();
init(this, options, instance5, create_fragment5, safe_not_equal, { entry: 0, closeModalFunc: 9 }, add_css5);
}
};
var TrackerModal_default = TrackerModal;
// src/entities/MoodTrackerEntry.ts
var MoodTrackerEntry = class {
constructor(moodRating = 3, emotions = [], note = "", dateTime = new Date()) {
this.id = crypto.randomUUID();
this.dateTime = dateTime;
this.moodRating = Number(moodRating);
this.emotions = emotions;
this.note = note;
}
};
// src/trackerModal/trackerModal.ts
var MoodTrackerModal = class extends import_obsidian6.Modal {
constructor(app2, plugin2, entry = new MoodTrackerEntry(), reopenStatsModalOnClose = false) {
super(app2);
this.plugin = plugin2;
this.entry = entry;
this.reopenStatsModalOnClose = reopenStatsModalOnClose;
}
async onOpen() {
store_default.plugin.set(this.plugin);
this.modalEl.addClass("mood-tracker-modal");
await this.plugin.loadEntries();
this.modal = new TrackerModal_default({
target: this.contentEl,
props: {
closeModalFunc: () => {
if (this.reopenStatsModalOnClose) {
this.plugin.openStatsModal(this.entry.dateTime);
}
this.close();
},
entry: this.entry
}
});
}
onClose() {
this.modal.$destroy();
}
};
// src/services/moodTrackerEntryService.ts
var MoodTrackerService = class {
/**
*
*/
constructor(persistenceService) {
this.persistenceService = persistenceService;
}
// add entry
addEntry(entry) {
}
// get day's info
//
};
// src/services/persistenceService.ts
var PersistenceService = class {
constructor(plugin2) {
this.plugin = plugin2;
}
get filepath() {
return this.plugin.settings.folderPath + "/" + this.plugin.dataFileName;
}
async getEntries() {
const adapter = this.plugin.app.vault.adapter;
await this.createDataFileIfNotExists();
try {
const fileData = await adapter.read(this.filepath);
if (!fileData) {
return new Array();
}
const data = JSON.parse(fileData);
data.forEach((entry) => {
entry.dateTime = new Date(entry.dateTime);
entry.moodRating = Number(entry.moodRating);
});
return data;
} catch (error) {
this.plugin.showNotice(`Error loading mood tracker entries from file ${this.filepath}: ${error}`);
console.warn(error);
}
}
async saveEntries() {
const adapter = this.plugin.app.vault.adapter;
await this.createDataFileIfNotExists();
try {
Date.prototype.toJSON = function() {
return window.moment(this).format();
};
const entries = this.plugin.entries;
const jsonData = JSON.stringify(entries, null, 2);
await adapter.write(this.filepath, jsonData);
} catch (error) {
this.plugin.showNotice(`Error saving mood tracker data to file ${this.filepath}: ${error}`);
console.warn(error);
}
}
async createDataFileIfNotExists() {
const adapter = this.plugin.app.vault.adapter;
if (!await adapter.exists(this.plugin.settings.folderPath)) {
this.plugin.showNotice(`Mood Tracker: folder "${this.plugin.settings.folderPath}" not found, creating it...`);
await adapter.mkdir(this.plugin.settings.folderPath);
this.plugin.showNotice(`Mood Tracker: created a folder "${this.plugin.settings.folderPath}". You can change the path in the settings; for now you'll have to move mood-tracker-data.json manually. Click to dismiss`, 3e4);
}
if (!await adapter.exists(this.filepath)) {
this.plugin.showNotice(`No mood tracker data file found at "${this.filepath}". Creating a new data file...`);
await adapter.write(this.filepath, "[]");
}
}
};
// src/statsModal/moodTrackerStatsModal.ts
var import_obsidian7 = require("obsidian");
// node_modules/@kurkle/color/dist/color.esm.js
function round2(v) {
return v + 0.5 | 0;
}
var lim = (v, l, h) => Math.max(Math.min(v, h), l);
function p2b(v) {
return lim(round2(v * 2.55), 0, 255);
}
function n2b(v) {
return lim(round2(v * 255), 0, 255);
}
function b2n(v) {
return lim(round2(v / 2.55) / 100, 0, 1);
}
function n2p(v) {
return lim(round2(v * 100), 0, 100);
}
var map$1 = { 0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, A: 10, B: 11, C: 12, D: 13, E: 14, F: 15, a: 10, b: 11, c: 12, d: 13, e: 14, f: 15 };
var hex = [..."0123456789ABCDEF"];
var h1 = (b) => hex[b & 15];
var h2 = (b) => hex[(b & 240) >> 4] + hex[b & 15];
var eq = (b) => (b & 240) >> 4 === (b & 15);
var isShort = (v) => eq(v.r) && eq(v.g) && eq(v.b) && eq(v.a);
function hexParse(str) {
var len = str.length;
var ret;
if (str[0] === "#") {
if (len === 4 || len === 5) {
ret = {
r: 255 & map$1[str[1]] * 17,
g: 255 & map$1[str[2]] * 17,
b: 255 & map$1[str[3]] * 17,
a: len === 5 ? map$1[str[4]] * 17 : 255
};
} else if (len === 7 || len === 9) {
ret = {
r: map$1[str[1]] << 4 | map$1[str[2]],
g: map$1[str[3]] << 4 | map$1[str[4]],
b: map$1[str[5]] << 4 | map$1[str[6]],
a: len === 9 ? map$1[str[7]] << 4 | map$1[str[8]] : 255
};
}
}
return ret;
}
var alpha = (a, f) => a < 255 ? f(a) : "";
function hexString(v) {
var f = isShort(v) ? h1 : h2;
return v ? "#" + f(v.r) + f(v.g) + f(v.b) + alpha(v.a, f) : void 0;
}
var HUE_RE = /^(hsla?|hwb|hsv)\(\s*([-+.e\d]+)(?:deg)?[\s,]+([-+.e\d]+)%[\s,]+([-+.e\d]+)%(?:[\s,]+([-+.e\d]+)(%)?)?\s*\)$/;
function hsl2rgbn(h, s, l) {
const a = s * Math.min(l, 1 - l);
const f = (n, k = (n + h / 30) % 12) => l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1);
return [f(0), f(8), f(4)];
}
function hsv2rgbn(h, s, v) {
const f = (n, k = (n + h / 60) % 6) => v - v * s * Math.max(Math.min(k, 4 - k, 1), 0);
return [f(5), f(3), f(1)];
}
function hwb2rgbn(h, w, b) {
const rgb = hsl2rgbn(h, 1, 0.5);
let i;
if (w + b > 1) {
i = 1 / (w + b);
w *= i;
b *= i;
}
for (i = 0; i < 3; i++) {
rgb[i] *= 1 - w - b;
rgb[i] += w;
}
return rgb;
}
function hueValue(r, g, b, d, max2) {
if (r === max2) {
return (g - b) / d + (g < b ? 6 : 0);
}
if (g === max2) {
return (b - r) / d + 2;
}
return (r - g) / d + 4;
}
function rgb2hsl(v) {
const range = 255;
const r = v.r / range;
const g = v.g / range;
const b = v.b / range;
const max2 = Math.max(r, g, b);
const min2 = Math.min(r, g, b);
const l = (max2 + min2) / 2;
let h, s, d;
if (max2 !== min2) {
d = max2 - min2;
s = l > 0.5 ? d / (2 - max2 - min2) : d / (max2 + min2);
h = hueValue(r, g, b, d, max2);
h = h * 60 + 0.5;
}
return [h | 0, s || 0, l];
}
function calln(f, a, b, c) {
return (Array.isArray(a) ? f(a[0], a[1], a[2]) : f(a, b, c)).map(n2b);
}
function hsl2rgb(h, s, l) {
return calln(hsl2rgbn, h, s, l);
}
function hwb2rgb(h, w, b) {
return calln(hwb2rgbn, h, w, b);
}
function hsv2rgb(h, s, v) {
return calln(hsv2rgbn, h, s, v);
}
function hue(h) {
return (h % 360 + 360) % 360;
}
function hueParse(str) {
const m = HUE_RE.exec(str);
let a = 255;
let v;
if (!m) {
return;
}
if (m[5] !== v) {
a = m[6] ? p2b(+m[5]) : n2b(+m[5]);
}
const h = hue(+m[2]);
const p1 = +m[3] / 100;
const p2 = +m[4] / 100;
if (m[1] === "hwb") {
v = hwb2rgb(h, p1, p2);
} else if (m[1] === "hsv") {
v = hsv2rgb(h, p1, p2);
} else {
v = hsl2rgb(h, p1, p2);
}
return {
r: v[0],
g: v[1],
b: v[2],
a
};
}
function rotate(v, deg) {
var h = rgb2hsl(v);
h[0] = hue(h[0] + deg);
h = hsl2rgb(h);
v.r = h[0];
v.g = h[1];
v.b = h[2];
}
function hslString(v) {
if (!v) {
return;
}
const a = rgb2hsl(v);
const h = a[0];
const s = n2p(a[1]);
const l = n2p(a[2]);
return v.a < 255 ? `hsla(${h}, ${s}%, ${l}%, ${b2n(v.a)})` : `hsl(${h}, ${s}%, ${l}%)`;
}
var map = {
x: "dark",
Z: "light",
Y: "re",
X: "blu",
W: "gr",
V: "medium",
U: "slate",
A: "ee",
T: "ol",
S: "or",
B: "ra",
C: "lateg",
D: "ights",
R: "in",
Q: "turquois",
E: "hi",
P: "ro",
O: "al",
N: "le",
M: "de",
L: "yello",
F: "en",
K: "ch",
G: "arks",
H: "ea",
I: "ightg",
J: "wh"
};
var names$1 = {
OiceXe: "f0f8ff",
antiquewEte: "faebd7",
aqua: "ffff",
aquamarRe: "7fffd4",
azuY: "f0ffff",
beige: "f5f5dc",
bisque: "ffe4c4",
black: "0",
blanKedOmond: "ffebcd",
Xe: "ff",
XeviTet: "8a2be2",
bPwn: "a52a2a",
burlywood: "deb887",
caMtXe: "5f9ea0",
KartYuse: "7fff00",
KocTate: "d2691e",
cSO: "ff7f50",
cSnflowerXe: "6495ed",
cSnsilk: "fff8dc",
crimson: "dc143c",
cyan: "ffff",
xXe: "8b",
xcyan: "8b8b",
xgTMnPd: "b8860b",
xWay: "a9a9a9",
xgYF: "6400",
xgYy: "a9a9a9",
xkhaki: "bdb76b",
xmagFta: "8b008b",
xTivegYF: "556b2f",
xSange: "ff8c00",
xScEd: "9932cc",
xYd: "8b0000",
xsOmon: "e9967a",
xsHgYF: "8fbc8f",
xUXe: "483d8b",
xUWay: "2f4f4f",
xUgYy: "2f4f4f",
xQe: "ced1",
xviTet: "9400d3",
dAppRk: "ff1493",
dApskyXe: "bfff",
dimWay: "696969",
dimgYy: "696969",
dodgerXe: "1e90ff",
fiYbrick: "b22222",
flSOwEte: "fffaf0",
foYstWAn: "228b22",
fuKsia: "ff00ff",
gaRsbSo: "dcdcdc",
ghostwEte: "f8f8ff",
gTd: "ffd700",
gTMnPd: "daa520",
Way: "808080",
gYF: "8000",
gYFLw: "adff2f",
gYy: "808080",
honeyMw: "f0fff0",
hotpRk: "ff69b4",
RdianYd: "cd5c5c",
Rdigo: "4b0082",
ivSy: "fffff0",
khaki: "f0e68c",
lavFMr: "e6e6fa",
lavFMrXsh: "fff0f5",
lawngYF: "7cfc00",
NmoncEffon: "fffacd",
ZXe: "add8e6",
ZcSO: "f08080",
Zcyan: "e0ffff",
ZgTMnPdLw: "fafad2",
ZWay: "d3d3d3",
ZgYF: "90ee90",
ZgYy: "d3d3d3",
ZpRk: "ffb6c1",
ZsOmon: "ffa07a",
ZsHgYF: "20b2aa",
ZskyXe: "87cefa",
ZUWay: "778899",
ZUgYy: "778899",
ZstAlXe: "b0c4de",
ZLw: "ffffe0",
lime: "ff00",
limegYF: "32cd32",
lRF: "faf0e6",
magFta: "ff00ff",
maPon: "800000",
VaquamarRe: "66cdaa",
VXe: "cd",
VScEd: "ba55d3",
VpurpN: "9370db",
VsHgYF: "3cb371",
VUXe: "7b68ee",
VsprRggYF: "fa9a",
VQe: "48d1cc",
VviTetYd: "c71585",
midnightXe: "191970",
mRtcYam: "f5fffa",
mistyPse: "ffe4e1",
moccasR: "ffe4b5",
navajowEte: "ffdead",
navy: "80",
Tdlace: "fdf5e6",
Tive: "808000",
TivedBb: "6b8e23",
Sange: "ffa500",
SangeYd: "ff4500",
ScEd: "da70d6",
pOegTMnPd: "eee8aa",
pOegYF: "98fb98",
pOeQe: "afeeee",
pOeviTetYd: "db7093",
papayawEp: "ffefd5",
pHKpuff: "ffdab9",
peru: "cd853f",
pRk: "ffc0cb",
plum: "dda0dd",
powMrXe: "b0e0e6",
purpN: "800080",
YbeccapurpN: "663399",
Yd: "ff0000",
Psybrown: "bc8f8f",
PyOXe: "4169e1",
saddNbPwn: "8b4513",
sOmon: "fa8072",
sandybPwn: "f4a460",
sHgYF: "2e8b57",
sHshell: "fff5ee",
siFna: "a0522d",
silver: "c0c0c0",
skyXe: "87ceeb",
UXe: "6a5acd",
UWay: "708090",
UgYy: "708090",
snow: "fffafa",
sprRggYF: "ff7f",
stAlXe: "4682b4",
tan: "d2b48c",
teO: "8080",
tEstN: "d8bfd8",
tomato: "ff6347",
Qe: "40e0d0",
viTet: "ee82ee",
JHt: "f5deb3",
wEte: "ffffff",
wEtesmoke: "f5f5f5",
Lw: "ffff00",
LwgYF: "9acd32"
};
function unpack() {
const unpacked = {};
const keys = Object.keys(names$1);
const tkeys = Object.keys(map);
let i, j, k, ok, nk;
for (i = 0; i < keys.length; i++) {
ok = nk = keys[i];
for (j = 0; j < tkeys.length; j++) {
k = tkeys[j];
nk = nk.replace(k, map[k]);
}
k = parseInt(names$1[ok], 16);
unpacked[nk] = [k >> 16 & 255, k >> 8 & 255, k & 255];
}
return unpacked;
}
var names;
function nameParse(str) {
if (!names) {
names = unpack();
names.transparent = [0, 0, 0, 0];
}
const a = names[str.toLowerCase()];
return a && {
r: a[0],
g: a[1],
b: a[2],
a: a.length === 4 ? a[3] : 255
};
}
var RGB_RE = /^rgba?\(\s*([-+.\d]+)(%)?[\s,]+([-+.e\d]+)(%)?[\s,]+([-+.e\d]+)(%)?(?:[\s,/]+([-+.e\d]+)(%)?)?\s*\)$/;
function rgbParse(str) {
const m = RGB_RE.exec(str);
let a = 255;
let r, g, b;
if (!m) {
return;
}
if (m[7] !== r) {
const v = +m[7];
a = m[8] ? p2b(v) : lim(v * 255, 0, 255);
}
r = +m[1];
g = +m[3];
b = +m[5];
r = 255 & (m[2] ? p2b(r) : lim(r, 0, 255));
g = 255 & (m[4] ? p2b(g) : lim(g, 0, 255));
b = 255 & (m[6] ? p2b(b) : lim(b, 0, 255));
return {
r,
g,
b,
a
};
}
function rgbString(v) {
return v && (v.a < 255 ? `rgba(${v.r}, ${v.g}, ${v.b}, ${b2n(v.a)})` : `rgb(${v.r}, ${v.g}, ${v.b})`);
}
var to = (v) => v <= 31308e-7 ? v * 12.92 : Math.pow(v, 1 / 2.4) * 1.055 - 0.055;
var from = (v) => v <= 0.04045 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);
function interpolate(rgb1, rgb2, t) {
const r = from(b2n(rgb1.r));
const g = from(b2n(rgb1.g));
const b = from(b2n(rgb1.b));
return {
r: n2b(to(r + t * (from(b2n(rgb2.r)) - r))),
g: n2b(to(g + t * (from(b2n(rgb2.g)) - g))),
b: n2b(to(b + t * (from(b2n(rgb2.b)) - b))),
a: rgb1.a + t * (rgb2.a - rgb1.a)
};
}
function modHSL(v, i, ratio) {
if (v) {
let tmp = rgb2hsl(v);
tmp[i] = Math.max(0, Math.min(tmp[i] + tmp[i] * ratio, i === 0 ? 360 : 1));
tmp = hsl2rgb(tmp);
v.r = tmp[0];
v.g = tmp[1];
v.b = tmp[2];
}
}
function clone(v, proto) {
return v ? Object.assign(proto || {}, v) : v;
}
function fromObject(input) {
var v = { r: 0, g: 0, b: 0, a: 255 };
if (Array.isArray(input)) {
if (input.length >= 3) {
v = { r: input[0], g: input[1], b: input[2], a: 255 };
if (input.length > 3) {
v.a = n2b(input[3]);
}
}
} else {
v = clone(input, { r: 0, g: 0, b: 0, a: 1 });
v.a = n2b(v.a);
}
return v;
}
function functionParse(str) {
if (str.charAt(0) === "r") {
return rgbParse(str);
}
return hueParse(str);
}
var Color = class {
constructor(input) {
if (input instanceof Color) {
return input;
}
const type = typeof input;
let v;
if (type === "object") {
v = fromObject(input);
} else if (type === "string") {
v = hexParse(input) || nameParse(input) || functionParse(input);
}
this._rgb = v;
this._valid = !!v;
}
get valid() {
return this._valid;
}
get rgb() {
var v = clone(this._rgb);
if (v) {
v.a = b2n(v.a);
}
return v;
}
set rgb(obj) {
this._rgb = fromObject(obj);
}
rgbString() {
return this._valid ? rgbString(this._rgb) : void 0;
}
hexString() {
return this._valid ? hexString(this._rgb) : void 0;
}
hslString() {
return this._valid ? hslString(this._rgb) : void 0;
}
mix(color2, weight) {
if (color2) {
const c1 = this.rgb;
const c2 = color2.rgb;
let w2;
const p = weight === w2 ? 0.5 : weight;
const w = 2 * p - 1;
const a = c1.a - c2.a;
const w1 = ((w * a === -1 ? w : (w + a) / (1 + w * a)) + 1) / 2;
w2 = 1 - w1;
c1.r = 255 & w1 * c1.r + w2 * c2.r + 0.5;
c1.g = 255 & w1 * c1.g + w2 * c2.g + 0.5;
c1.b = 255 & w1 * c1.b + w2 * c2.b + 0.5;
c1.a = p * c1.a + (1 - p) * c2.a;
this.rgb = c1;
}
return this;
}
interpolate(color2, t) {
if (color2) {
this._rgb = interpolate(this._rgb, color2._rgb, t);
}
return this;
}
clone() {
return new Color(this.rgb);
}
alpha(a) {
this._rgb.a = n2b(a);
return this;
}
clearer(ratio) {
const rgb = this._rgb;
rgb.a *= 1 - ratio;
return this;
}
greyscale() {
const rgb = this._rgb;
const val = round2(rgb.r * 0.3 + rgb.g * 0.59 + rgb.b * 0.11);
rgb.r = rgb.g = rgb.b = val;
return this;
}
opaquer(ratio) {
const rgb = this._rgb;
rgb.a *= 1 + ratio;
return this;
}
negate() {
const v = this._rgb;
v.r = 255 - v.r;
v.g = 255 - v.g;
v.b = 255 - v.b;
return this;
}
lighten(ratio) {
modHSL(this._rgb, 2, ratio);
return this;
}
darken(ratio) {
modHSL(this._rgb, 2, -ratio);
return this;
}
saturate(ratio) {
modHSL(this._rgb, 1, ratio);
return this;
}
desaturate(ratio) {
modHSL(this._rgb, 1, -ratio);
return this;
}
rotate(deg) {
rotate(this._rgb, deg);
return this;
}
};
// node_modules/chart.js/dist/chunks/helpers.segment.js
function noop2() {
}
var uid = (() => {
let id = 0;
return () => id++;
})();
function isNullOrUndef(value) {
return value === null || typeof value === "undefined";
}
function isArray(value) {
if (Array.isArray && Array.isArray(value)) {
return true;
}
const type = Object.prototype.toString.call(value);
if (type.slice(0, 7) === "[object" && type.slice(-6) === "Array]") {
return true;
}
return false;
}
function isObject(value) {
return value !== null && Object.prototype.toString.call(value) === "[object Object]";
}
function isNumberFinite(value) {
return (typeof value === "number" || value instanceof Number) && isFinite(+value);
}
function finiteOrDefault(value, defaultValue) {
return isNumberFinite(value) ? value : defaultValue;
}
function valueOrDefault(value, defaultValue) {
return typeof value === "undefined" ? defaultValue : value;
}
var toPercentage = (value, dimension) => typeof value === "string" && value.endsWith("%") ? parseFloat(value) / 100 : +value / dimension;
var toDimension = (value, dimension) => typeof value === "string" && value.endsWith("%") ? parseFloat(value) / 100 * dimension : +value;
function callback(fn2, args, thisArg) {
if (fn2 && typeof fn2.call === "function") {
return fn2.apply(thisArg, args);
}
}
function each2(loopable, fn2, thisArg, reverse) {
let i, len, keys;
if (isArray(loopable)) {
len = loopable.length;
if (reverse) {
for (i = len - 1; i >= 0; i--) {
fn2.call(thisArg, loopable[i], i);
}
} else {
for (i = 0; i < len; i++) {
fn2.call(thisArg, loopable[i], i);
}
}
} else if (isObject(loopable)) {
keys = Object.keys(loopable);
len = keys.length;
for (i = 0; i < len; i++) {
fn2.call(thisArg, loopable[keys[i]], keys[i]);
}
}
}
function _elementsEqual(a0, a1) {
let i, ilen, v0, v1;
if (!a0 || !a1 || a0.length !== a1.length) {
return false;
}
for (i = 0, ilen = a0.length; i < ilen; ++i) {
v0 = a0[i];
v1 = a1[i];
if (v0.datasetIndex !== v1.datasetIndex || v0.index !== v1.index) {
return false;
}
}
return true;
}
function clone2(source) {
if (isArray(source)) {
return source.map(clone2);
}
if (isObject(source)) {
const target = /* @__PURE__ */ Object.create(null);
const keys = Object.keys(source);
const klen = keys.length;
let k = 0;
for (; k < klen; ++k) {
target[keys[k]] = clone2(source[keys[k]]);
}
return target;
}
return source;
}
function isValidKey(key) {
return [
"__proto__",
"prototype",
"constructor"
].indexOf(key) === -1;
}
function _merger(key, target, source, options) {
if (!isValidKey(key)) {
return;
}
const tval = target[key];
const sval = source[key];
if (isObject(tval) && isObject(sval)) {
merge(tval, sval, options);
} else {
target[key] = clone2(sval);
}
}
function merge(target, source, options) {
const sources = isArray(source) ? source : [
source
];
const ilen = sources.length;
if (!isObject(target)) {
return target;
}
options = options || {};
const merger = options.merger || _merger;
let current;
for (let i = 0; i < ilen; ++i) {
current = sources[i];
if (!isObject(current)) {
continue;
}
const keys = Object.keys(current);
for (let k = 0, klen = keys.length; k < klen; ++k) {
merger(keys[k], target, current, options);
}
}
return target;
}
function mergeIf(target, source) {
return merge(target, source, {
merger: _mergerIf
});
}
function _mergerIf(key, target, source) {
if (!isValidKey(key)) {
return;
}
const tval = target[key];
const sval = source[key];
if (isObject(tval) && isObject(sval)) {
mergeIf(tval, sval);
} else if (!Object.prototype.hasOwnProperty.call(target, key)) {
target[key] = clone2(sval);
}
}
var keyResolvers = {
// Chart.helpers.core resolveObjectKey should resolve empty key to root object
"": (v) => v,
// default resolvers
x: (o) => o.x,
y: (o) => o.y
};
function _splitKey(key) {
const parts = key.split(".");
const keys = [];
let tmp = "";
for (const part of parts) {
tmp += part;
if (tmp.endsWith("\\")) {
tmp = tmp.slice(0, -1) + ".";
} else {
keys.push(tmp);
tmp = "";
}
}
return keys;
}
function _getKeyResolver(key) {
const keys = _splitKey(key);
return (obj) => {
for (const k of keys) {
if (k === "") {
break;
}
obj = obj && obj[k];
}
return obj;
};
}
function resolveObjectKey(obj, key) {
const resolver = keyResolvers[key] || (keyResolvers[key] = _getKeyResolver(key));
return resolver(obj);
}
function _capitalize(str) {
return str.charAt(0).toUpperCase() + str.slice(1);
}
var defined = (value) => typeof value !== "undefined";
var isFunction = (value) => typeof value === "function";
var setsEqual = (a, b) => {
if (a.size !== b.size) {
return false;
}
for (const item of a) {
if (!b.has(item)) {
return false;
}
}
return true;
};
function _isClickEvent(e) {
return e.type === "mouseup" || e.type === "click" || e.type === "contextmenu";
}
var PI = Math.PI;
var TAU = 2 * PI;
var PITAU = TAU + PI;
var INFINITY = Number.POSITIVE_INFINITY;
var RAD_PER_DEG = PI / 180;
var HALF_PI = PI / 2;
var QUARTER_PI = PI / 4;
var TWO_THIRDS_PI = PI * 2 / 3;
var log10 = Math.log10;
var sign = Math.sign;
function almostEquals(x, y, epsilon) {
return Math.abs(x - y) < epsilon;
}
function niceNum(range) {
const roundedRange = Math.round(range);
range = almostEquals(range, roundedRange, range / 1e3) ? roundedRange : range;
const niceRange = Math.pow(10, Math.floor(log10(range)));
const fraction = range / niceRange;
const niceFraction = fraction <= 1 ? 1 : fraction <= 2 ? 2 : fraction <= 5 ? 5 : 10;
return niceFraction * niceRange;
}
function _factorize(value) {
const result = [];
const sqrt = Math.sqrt(value);
let i;
for (i = 1; i < sqrt; i++) {
if (value % i === 0) {
result.push(i);
result.push(value / i);
}
}
if (sqrt === (sqrt | 0)) {
result.push(sqrt);
}
result.sort((a, b) => a - b).pop();
return result;
}
function isNumber(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
}
function almostWhole(x, epsilon) {
const rounded = Math.round(x);
return rounded - epsilon <= x && rounded + epsilon >= x;
}
function _setMinAndMaxByKey(array, target, property) {
let i, ilen, value;
for (i = 0, ilen = array.length; i < ilen; i++) {
value = array[i][property];
if (!isNaN(value)) {
target.min = Math.min(target.min, value);
target.max = Math.max(target.max, value);
}
}
}
function toRadians(degrees) {
return degrees * (PI / 180);
}
function toDegrees(radians) {
return radians * (180 / PI);
}
function _decimalPlaces(x) {
if (!isNumberFinite(x)) {
return;
}
let e = 1;
let p = 0;
while (Math.round(x * e) / e !== x) {
e *= 10;
p++;
}
return p;
}
function getAngleFromPoint(centrePoint, anglePoint) {
const distanceFromXCenter = anglePoint.x - centrePoint.x;
const distanceFromYCenter = anglePoint.y - centrePoint.y;
const radialDistanceFromCenter = Math.sqrt(distanceFromXCenter * distanceFromXCenter + distanceFromYCenter * distanceFromYCenter);
let angle = Math.atan2(distanceFromYCenter, distanceFromXCenter);
if (angle < -0.5 * PI) {
angle += TAU;
}
return {
angle,
distance: radialDistanceFromCenter
};
}
function distanceBetweenPoints(pt1, pt2) {
return Math.sqrt(Math.pow(pt2.x - pt1.x, 2) + Math.pow(pt2.y - pt1.y, 2));
}
function _angleDiff(a, b) {
return (a - b + PITAU) % TAU - PI;
}
function _normalizeAngle(a) {
return (a % TAU + TAU) % TAU;
}
function _angleBetween(angle, start2, end2, sameAngleIsFullCircle) {
const a = _normalizeAngle(angle);
const s = _normalizeAngle(start2);
const e = _normalizeAngle(end2);
const angleToStart = _normalizeAngle(s - a);
const angleToEnd = _normalizeAngle(e - a);
const startToAngle = _normalizeAngle(a - s);
const endToAngle = _normalizeAngle(a - e);
return a === s || a === e || sameAngleIsFullCircle && s === e || angleToStart > angleToEnd && startToAngle < endToAngle;
}
function _limitValue(value, min2, max2) {
return Math.max(min2, Math.min(max2, value));
}
function _int16Range(value) {
return _limitValue(value, -32768, 32767);
}
function _isBetween(value, start2, end2, epsilon = 1e-6) {
return value >= Math.min(start2, end2) - epsilon && value <= Math.max(start2, end2) + epsilon;
}
function _lookup(table, value, cmp) {
cmp = cmp || ((index) => table[index] < value);
let hi = table.length - 1;
let lo = 0;
let mid;
while (hi - lo > 1) {
mid = lo + hi >> 1;
if (cmp(mid)) {
lo = mid;
} else {
hi = mid;
}
}
return {
lo,
hi
};
}
var _lookupByKey = (table, key, value, last) => _lookup(table, value, last ? (index) => {
const ti = table[index][key];
return ti < value || ti === value && table[index + 1][key] === value;
} : (index) => table[index][key] < value);
var _rlookupByKey = (table, key, value) => _lookup(table, value, (index) => table[index][key] >= value);
function _filterBetween(values, min2, max2) {
let start2 = 0;
let end2 = values.length;
while (start2 < end2 && values[start2] < min2) {
start2++;
}
while (end2 > start2 && values[end2 - 1] > max2) {
end2--;
}
return start2 > 0 || end2 < values.length ? values.slice(start2, end2) : values;
}
var arrayEvents = [
"push",
"pop",
"shift",
"splice",
"unshift"
];
function listenArrayEvents(array, listener) {
if (array._chartjs) {
array._chartjs.listeners.push(listener);
return;
}
Object.defineProperty(array, "_chartjs", {
configurable: true,
enumerable: false,
value: {
listeners: [
listener
]
}
});
arrayEvents.forEach((key) => {
const method = "_onData" + _capitalize(key);
const base = array[key];
Object.defineProperty(array, key, {
configurable: true,
enumerable: false,
value(...args) {
const res = base.apply(this, args);
array._chartjs.listeners.forEach((object) => {
if (typeof object[method] === "function") {
object[method](...args);
}
});
return res;
}
});
});
}
function unlistenArrayEvents(array, listener) {
const stub = array._chartjs;
if (!stub) {
return;
}
const listeners = stub.listeners;
const index = listeners.indexOf(listener);
if (index !== -1) {
listeners.splice(index, 1);
}
if (listeners.length > 0) {
return;
}
arrayEvents.forEach((key) => {
delete array[key];
});
delete array._chartjs;
}
function _arrayUnique(items) {
const set2 = /* @__PURE__ */ new Set();
let i, ilen;
for (i = 0, ilen = items.length; i < ilen; ++i) {
set2.add(items[i]);
}
if (set2.size === ilen) {
return items;
}
return Array.from(set2);
}
var requestAnimFrame = function() {
if (typeof window === "undefined") {
return function(callback2) {
return callback2();
};
}
return window.requestAnimationFrame;
}();
function throttled(fn2, thisArg) {
let argsToUse = [];
let ticking = false;
return function(...args) {
argsToUse = args;
if (!ticking) {
ticking = true;
requestAnimFrame.call(window, () => {
ticking = false;
fn2.apply(thisArg, argsToUse);
});
}
};
}
function debounce3(fn2, delay) {
let timeout;
return function(...args) {
if (delay) {
clearTimeout(timeout);
timeout = setTimeout(fn2, delay, args);
} else {
fn2.apply(this, args);
}
return delay;
};
}
var _toLeftRightCenter = (align) => align === "start" ? "left" : align === "end" ? "right" : "center";
var _alignStartEnd = (align, start2, end2) => align === "start" ? start2 : align === "end" ? end2 : (start2 + end2) / 2;
var _textX = (align, left2, right2, rtl) => {
const check = rtl ? "left" : "right";
return align === check ? right2 : align === "center" ? (left2 + right2) / 2 : left2;
};
var atEdge = (t) => t === 0 || t === 1;
var elasticIn = (t, s, p) => -(Math.pow(2, 10 * (t -= 1)) * Math.sin((t - s) * TAU / p));
var elasticOut = (t, s, p) => Math.pow(2, -10 * t) * Math.sin((t - s) * TAU / p) + 1;
var effects = {
linear: (t) => t,
easeInQuad: (t) => t * t,
easeOutQuad: (t) => -t * (t - 2),
easeInOutQuad: (t) => (t /= 0.5) < 1 ? 0.5 * t * t : -0.5 * (--t * (t - 2) - 1),
easeInCubic: (t) => t * t * t,
easeOutCubic: (t) => (t -= 1) * t * t + 1,
easeInOutCubic: (t) => (t /= 0.5) < 1 ? 0.5 * t * t * t : 0.5 * ((t -= 2) * t * t + 2),
easeInQuart: (t) => t * t * t * t,
easeOutQuart: (t) => -((t -= 1) * t * t * t - 1),
easeInOutQuart: (t) => (t /= 0.5) < 1 ? 0.5 * t * t * t * t : -0.5 * ((t -= 2) * t * t * t - 2),
easeInQuint: (t) => t * t * t * t * t,
easeOutQuint: (t) => (t -= 1) * t * t * t * t + 1,
easeInOutQuint: (t) => (t /= 0.5) < 1 ? 0.5 * t * t * t * t * t : 0.5 * ((t -= 2) * t * t * t * t + 2),
easeInSine: (t) => -Math.cos(t * HALF_PI) + 1,
easeOutSine: (t) => Math.sin(t * HALF_PI),
easeInOutSine: (t) => -0.5 * (Math.cos(PI * t) - 1),
easeInExpo: (t) => t === 0 ? 0 : Math.pow(2, 10 * (t - 1)),
easeOutExpo: (t) => t === 1 ? 1 : -Math.pow(2, -10 * t) + 1,
easeInOutExpo: (t) => atEdge(t) ? t : t < 0.5 ? 0.5 * Math.pow(2, 10 * (t * 2 - 1)) : 0.5 * (-Math.pow(2, -10 * (t * 2 - 1)) + 2),
easeInCirc: (t) => t >= 1 ? t : -(Math.sqrt(1 - t * t) - 1),
easeOutCirc: (t) => Math.sqrt(1 - (t -= 1) * t),
easeInOutCirc: (t) => (t /= 0.5) < 1 ? -0.5 * (Math.sqrt(1 - t * t) - 1) : 0.5 * (Math.sqrt(1 - (t -= 2) * t) + 1),
easeInElastic: (t) => atEdge(t) ? t : elasticIn(t, 0.075, 0.3),
easeOutElastic: (t) => atEdge(t) ? t : elasticOut(t, 0.075, 0.3),
easeInOutElastic(t) {
const s = 0.1125;
const p = 0.45;
return atEdge(t) ? t : t < 0.5 ? 0.5 * elasticIn(t * 2, s, p) : 0.5 + 0.5 * elasticOut(t * 2 - 1, s, p);
},
easeInBack(t) {
const s = 1.70158;
return t * t * ((s + 1) * t - s);
},
easeOutBack(t) {
const s = 1.70158;
return (t -= 1) * t * ((s + 1) * t + s) + 1;
},
easeInOutBack(t) {
let s = 1.70158;
if ((t /= 0.5) < 1) {
return 0.5 * (t * t * (((s *= 1.525) + 1) * t - s));
}
return 0.5 * ((t -= 2) * t * (((s *= 1.525) + 1) * t + s) + 2);
},
easeInBounce: (t) => 1 - effects.easeOutBounce(1 - t),
easeOutBounce(t) {
const m = 7.5625;
const d = 2.75;
if (t < 1 / d) {
return m * t * t;
}
if (t < 2 / d) {
return m * (t -= 1.5 / d) * t + 0.75;
}
if (t < 2.5 / d) {
return m * (t -= 2.25 / d) * t + 0.9375;
}
return m * (t -= 2.625 / d) * t + 0.984375;
},
easeInOutBounce: (t) => t < 0.5 ? effects.easeInBounce(t * 2) * 0.5 : effects.easeOutBounce(t * 2 - 1) * 0.5 + 0.5
};
function isPatternOrGradient(value) {
if (value && typeof value === "object") {
const type = value.toString();
return type === "[object CanvasPattern]" || type === "[object CanvasGradient]";
}
return false;
}
function color(value) {
return isPatternOrGradient(value) ? value : new Color(value);
}
function getHoverColor(value) {
return isPatternOrGradient(value) ? value : new Color(value).saturate(0.5).darken(0.1).hexString();
}
var numbers = [
"x",
"y",
"borderWidth",
"radius",
"tension"
];
var colors = [
"color",
"borderColor",
"backgroundColor"
];
function applyAnimationsDefaults(defaults2) {
defaults2.set("animation", {
delay: void 0,
duration: 1e3,
easing: "easeOutQuart",
fn: void 0,
from: void 0,
loop: void 0,
to: void 0,
type: void 0
});
defaults2.describe("animation", {
_fallback: false,
_indexable: false,
_scriptable: (name2) => name2 !== "onProgress" && name2 !== "onComplete" && name2 !== "fn"
});
defaults2.set("animations", {
colors: {
type: "color",
properties: colors
},
numbers: {
type: "number",
properties: numbers
}
});
defaults2.describe("animations", {
_fallback: "animation"
});
defaults2.set("transitions", {
active: {
animation: {
duration: 400
}
},
resize: {
animation: {
duration: 0
}
},
show: {
animations: {
colors: {
from: "transparent"
},
visible: {
type: "boolean",
duration: 0
}
}
},
hide: {
animations: {
colors: {
to: "transparent"
},
visible: {
type: "boolean",
easing: "linear",
fn: (v) => v | 0
}
}
}
});
}
function applyLayoutsDefaults(defaults2) {
defaults2.set("layout", {
autoPadding: true,
padding: {
top: 0,
right: 0,
bottom: 0,
left: 0
}
});
}
var intlCache = /* @__PURE__ */ new Map();
function getNumberFormat(locale, options) {
options = options || {};
const cacheKey = locale + JSON.stringify(options);
let formatter = intlCache.get(cacheKey);
if (!formatter) {
formatter = new Intl.NumberFormat(locale, options);
intlCache.set(cacheKey, formatter);
}
return formatter;
}
function formatNumber(num, locale, options) {
return getNumberFormat(locale, options).format(num);
}
var formatters = {
values(value) {
return isArray(value) ? value : "" + value;
},
numeric(tickValue, index, ticks) {
if (tickValue === 0) {
return "0";
}
const locale = this.chart.options.locale;
let notation;
let delta = tickValue;
if (ticks.length > 1) {
const maxTick = Math.max(Math.abs(ticks[0].value), Math.abs(ticks[ticks.length - 1].value));
if (maxTick < 1e-4 || maxTick > 1e15) {
notation = "scientific";
}
delta = calculateDelta(tickValue, ticks);
}
const logDelta = log10(Math.abs(delta));
const numDecimal = Math.max(Math.min(-1 * Math.floor(logDelta), 20), 0);
const options = {
notation,
minimumFractionDigits: numDecimal,
maximumFractionDigits: numDecimal
};
Object.assign(options, this.options.ticks.format);
return formatNumber(tickValue, locale, options);
},
logarithmic(tickValue, index, ticks) {
if (tickValue === 0) {
return "0";
}
const remain = ticks[index].significand || tickValue / Math.pow(10, Math.floor(log10(tickValue)));
if ([
1,
2,
3,
5,
10,
15
].includes(remain) || index > 0.8 * ticks.length) {
return formatters.numeric.call(this, tickValue, index, ticks);
}
return "";
}
};
function calculateDelta(tickValue, ticks) {
let delta = ticks.length > 3 ? ticks[2].value - ticks[1].value : ticks[1].value - ticks[0].value;
if (Math.abs(delta) >= 1 && tickValue !== Math.floor(tickValue)) {
delta = tickValue - Math.floor(tickValue);
}
return delta;
}
var Ticks = {
formatters
};
function applyScaleDefaults(defaults2) {
defaults2.set("scale", {
display: true,
offset: false,
reverse: false,
beginAtZero: false,
bounds: "ticks",
grace: 0,
grid: {
display: true,
lineWidth: 1,
drawOnChartArea: true,
drawTicks: true,
tickLength: 8,
tickWidth: (_ctx, options) => options.lineWidth,
tickColor: (_ctx, options) => options.color,
offset: false
},
border: {
display: true,
dash: [],
dashOffset: 0,
width: 1
},
title: {
display: false,
text: "",
padding: {
top: 4,
bottom: 4
}
},
ticks: {
minRotation: 0,
maxRotation: 50,
mirror: false,
textStrokeWidth: 0,
textStrokeColor: "",
padding: 3,
display: true,
autoSkip: true,
autoSkipPadding: 3,
labelOffset: 0,
callback: Ticks.formatters.values,
minor: {},
major: {},
align: "center",
crossAlign: "near",
showLabelBackdrop: false,
backdropColor: "rgba(255, 255, 255, 0.75)",
backdropPadding: 2
}
});
defaults2.route("scale.ticks", "color", "", "color");
defaults2.route("scale.grid", "color", "", "borderColor");
defaults2.route("scale.border", "color", "", "borderColor");
defaults2.route("scale.title", "color", "", "color");
defaults2.describe("scale", {
_fallback: false,
_scriptable: (name2) => !name2.startsWith("before") && !name2.startsWith("after") && name2 !== "callback" && name2 !== "parser",
_indexable: (name2) => name2 !== "borderDash" && name2 !== "tickBorderDash" && name2 !== "dash"
});
defaults2.describe("scales", {
_fallback: "scale"
});
defaults2.describe("scale.ticks", {
_scriptable: (name2) => name2 !== "backdropPadding" && name2 !== "callback",
_indexable: (name2) => name2 !== "backdropPadding"
});
}
var overrides = /* @__PURE__ */ Object.create(null);
var descriptors = /* @__PURE__ */ Object.create(null);
function getScope$1(node, key) {
if (!key) {
return node;
}
const keys = key.split(".");
for (let i = 0, n = keys.length; i < n; ++i) {
const k = keys[i];
node = node[k] || (node[k] = /* @__PURE__ */ Object.create(null));
}
return node;
}
function set(root, scope, values) {
if (typeof scope === "string") {
return merge(getScope$1(root, scope), values);
}
return merge(getScope$1(root, ""), scope);
}
var Defaults = class {
constructor(_descriptors2, _appliers) {
this.animation = void 0;
this.backgroundColor = "rgba(0,0,0,0.1)";
this.borderColor = "rgba(0,0,0,0.1)";
this.color = "#666";
this.datasets = {};
this.devicePixelRatio = (context) => context.chart.platform.getDevicePixelRatio();
this.elements = {};
this.events = [
"mousemove",
"mouseout",
"click",
"touchstart",
"touchmove"
];
this.font = {
family: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",
size: 12,
style: "normal",
lineHeight: 1.2,
weight: null
};
this.hover = {};
this.hoverBackgroundColor = (ctx, options) => getHoverColor(options.backgroundColor);
this.hoverBorderColor = (ctx, options) => getHoverColor(options.borderColor);
this.hoverColor = (ctx, options) => getHoverColor(options.color);
this.indexAxis = "x";
this.interaction = {
mode: "nearest",
intersect: true,
includeInvisible: false
};
this.maintainAspectRatio = true;
this.onHover = null;
this.onClick = null;
this.parsing = true;
this.plugins = {};
this.responsive = true;
this.scale = void 0;
this.scales = {};
this.showLine = true;
this.drawActiveElementsOnTop = true;
this.describe(_descriptors2);
this.apply(_appliers);
}
set(scope, values) {
return set(this, scope, values);
}
get(scope) {
return getScope$1(this, scope);
}
describe(scope, values) {
return set(descriptors, scope, values);
}
override(scope, values) {
return set(overrides, scope, values);
}
route(scope, name2, targetScope, targetName) {
const scopeObject = getScope$1(this, scope);
const targetScopeObject = getScope$1(this, targetScope);
const privateName = "_" + name2;
Object.defineProperties(scopeObject, {
[privateName]: {
value: scopeObject[name2],
writable: true
},
[name2]: {
enumerable: true,
get() {
const local = this[privateName];
const target = targetScopeObject[targetName];
if (isObject(local)) {
return Object.assign({}, target, local);
}
return valueOrDefault(local, target);
},
set(value) {
this[privateName] = value;
}
}
});
}
apply(appliers) {
appliers.forEach((apply) => apply(this));
}
};
var defaults = /* @__PURE__ */ new Defaults({
_scriptable: (name2) => !name2.startsWith("on"),
_indexable: (name2) => name2 !== "events",
hover: {
_fallback: "interaction"
},
interaction: {
_scriptable: false,
_indexable: false
}
}, [
applyAnimationsDefaults,
applyLayoutsDefaults,
applyScaleDefaults
]);
function toFontString(font) {
if (!font || isNullOrUndef(font.size) || isNullOrUndef(font.family)) {
return null;
}
return (font.style ? font.style + " " : "") + (font.weight ? font.weight + " " : "") + font.size + "px " + font.family;
}
function _measureText(ctx, data, gc, longest, string) {
let textWidth = data[string];
if (!textWidth) {
textWidth = data[string] = ctx.measureText(string).width;
gc.push(string);
}
if (textWidth > longest) {
longest = textWidth;
}
return longest;
}
function _longestText(ctx, font, arrayOfThings, cache) {
cache = cache || {};
let data = cache.data = cache.data || {};
let gc = cache.garbageCollect = cache.garbageCollect || [];
if (cache.font !== font) {
data = cache.data = {};
gc = cache.garbageCollect = [];
cache.font = font;
}
ctx.save();
ctx.font = font;
let longest = 0;
const ilen = arrayOfThings.length;
let i, j, jlen, thing, nestedThing;
for (i = 0; i < ilen; i++) {
thing = arrayOfThings[i];
if (thing !== void 0 && thing !== null && isArray(thing) !== true) {
longest = _measureText(ctx, data, gc, longest, thing);
} else if (isArray(thing)) {
for (j = 0, jlen = thing.length; j < jlen; j++) {
nestedThing = thing[j];
if (nestedThing !== void 0 && nestedThing !== null && !isArray(nestedThing)) {
longest = _measureText(ctx, data, gc, longest, nestedThing);
}
}
}
}
ctx.restore();
const gcLen = gc.length / 2;
if (gcLen > arrayOfThings.length) {
for (i = 0; i < gcLen; i++) {
delete data[gc[i]];
}
gc.splice(0, gcLen);
}
return longest;
}
function _alignPixel(chart, pixel, width) {
const devicePixelRatio = chart.currentDevicePixelRatio;
const halfWidth = width !== 0 ? Math.max(width / 2, 0.5) : 0;
return Math.round((pixel - halfWidth) * devicePixelRatio) / devicePixelRatio + halfWidth;
}
function clearCanvas(canvas, ctx) {
ctx = ctx || canvas.getContext("2d");
ctx.save();
ctx.resetTransform();
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.restore();
}
function drawPoint(ctx, options, x, y) {
drawPointLegend(ctx, options, x, y, null);
}
function drawPointLegend(ctx, options, x, y, w) {
let type, xOffset, yOffset, size, cornerRadius, width, xOffsetW, yOffsetW;
const style = options.pointStyle;
const rotation = options.rotation;
const radius = options.radius;
let rad = (rotation || 0) * RAD_PER_DEG;
if (style && typeof style === "object") {
type = style.toString();
if (type === "[object HTMLImageElement]" || type === "[object HTMLCanvasElement]") {
ctx.save();
ctx.translate(x, y);
ctx.rotate(rad);
ctx.drawImage(style, -style.width / 2, -style.height / 2, style.width, style.height);
ctx.restore();
return;
}
}
if (isNaN(radius) || radius <= 0) {
return;
}
ctx.beginPath();
switch (style) {
default:
if (w) {
ctx.ellipse(x, y, w / 2, radius, 0, 0, TAU);
} else {
ctx.arc(x, y, radius, 0, TAU);
}
ctx.closePath();
break;
case "triangle":
width = w ? w / 2 : radius;
ctx.moveTo(x + Math.sin(rad) * width, y - Math.cos(rad) * radius);
rad += TWO_THIRDS_PI;
ctx.lineTo(x + Math.sin(rad) * width, y - Math.cos(rad) * radius);
rad += TWO_THIRDS_PI;
ctx.lineTo(x + Math.sin(rad) * width, y - Math.cos(rad) * radius);
ctx.closePath();
break;
case "rectRounded":
cornerRadius = radius * 0.516;
size = radius - cornerRadius;
xOffset = Math.cos(rad + QUARTER_PI) * size;
xOffsetW = Math.cos(rad + QUARTER_PI) * (w ? w / 2 - cornerRadius : size);
yOffset = Math.sin(rad + QUARTER_PI) * size;
yOffsetW = Math.sin(rad + QUARTER_PI) * (w ? w / 2 - cornerRadius : size);
ctx.arc(x - xOffsetW, y - yOffset, cornerRadius, rad - PI, rad - HALF_PI);
ctx.arc(x + yOffsetW, y - xOffset, cornerRadius, rad - HALF_PI, rad);
ctx.arc(x + xOffsetW, y + yOffset, cornerRadius, rad, rad + HALF_PI);
ctx.arc(x - yOffsetW, y + xOffset, cornerRadius, rad + HALF_PI, rad + PI);
ctx.closePath();
break;
case "rect":
if (!rotation) {
size = Math.SQRT1_2 * radius;
width = w ? w / 2 : size;
ctx.rect(x - width, y - size, 2 * width, 2 * size);
break;
}
rad += QUARTER_PI;
case "rectRot":
xOffsetW = Math.cos(rad) * (w ? w / 2 : radius);
xOffset = Math.cos(rad) * radius;
yOffset = Math.sin(rad) * radius;
yOffsetW = Math.sin(rad) * (w ? w / 2 : radius);
ctx.moveTo(x - xOffsetW, y - yOffset);
ctx.lineTo(x + yOffsetW, y - xOffset);
ctx.lineTo(x + xOffsetW, y + yOffset);
ctx.lineTo(x - yOffsetW, y + xOffset);
ctx.closePath();
break;
case "crossRot":
rad += QUARTER_PI;
case "cross":
xOffsetW = Math.cos(rad) * (w ? w / 2 : radius);
xOffset = Math.cos(rad) * radius;
yOffset = Math.sin(rad) * radius;
yOffsetW = Math.sin(rad) * (w ? w / 2 : radius);
ctx.moveTo(x - xOffsetW, y - yOffset);
ctx.lineTo(x + xOffsetW, y + yOffset);
ctx.moveTo(x + yOffsetW, y - xOffset);
ctx.lineTo(x - yOffsetW, y + xOffset);
break;
case "star":
xOffsetW = Math.cos(rad) * (w ? w / 2 : radius);
xOffset = Math.cos(rad) * radius;
yOffset = Math.sin(rad) * radius;
yOffsetW = Math.sin(rad) * (w ? w / 2 : radius);
ctx.moveTo(x - xOffsetW, y - yOffset);
ctx.lineTo(x + xOffsetW, y + yOffset);
ctx.moveTo(x + yOffsetW, y - xOffset);
ctx.lineTo(x - yOffsetW, y + xOffset);
rad += QUARTER_PI;
xOffsetW = Math.cos(rad) * (w ? w / 2 : radius);
xOffset = Math.cos(rad) * radius;
yOffset = Math.sin(rad) * radius;
yOffsetW = Math.sin(rad) * (w ? w / 2 : radius);
ctx.moveTo(x - xOffsetW, y - yOffset);
ctx.lineTo(x + xOffsetW, y + yOffset);
ctx.moveTo(x + yOffsetW, y - xOffset);
ctx.lineTo(x - yOffsetW, y + xOffset);
break;
case "line":
xOffset = w ? w / 2 : Math.cos(rad) * radius;
yOffset = Math.sin(rad) * radius;
ctx.moveTo(x - xOffset, y - yOffset);
ctx.lineTo(x + xOffset, y + yOffset);
break;
case "dash":
ctx.moveTo(x, y);
ctx.lineTo(x + Math.cos(rad) * (w ? w / 2 : radius), y + Math.sin(rad) * radius);
break;
case false:
ctx.closePath();
break;
}
ctx.fill();
if (options.borderWidth > 0) {
ctx.stroke();
}
}
function _isPointInArea(point, area, margin) {
margin = margin || 0.5;
return !area || point && point.x > area.left - margin && point.x < area.right + margin && point.y > area.top - margin && point.y < area.bottom + margin;
}
function clipArea(ctx, area) {
ctx.save();
ctx.beginPath();
ctx.rect(area.left, area.top, area.right - area.left, area.bottom - area.top);
ctx.clip();
}
function unclipArea(ctx) {
ctx.restore();
}
function _steppedLineTo(ctx, previous, target, flip2, mode) {
if (!previous) {
return ctx.lineTo(target.x, target.y);
}
if (mode === "middle") {
const midpoint = (previous.x + target.x) / 2;
ctx.lineTo(midpoint, previous.y);
ctx.lineTo(midpoint, target.y);
} else if (mode === "after" !== !!flip2) {
ctx.lineTo(previous.x, target.y);
} else {
ctx.lineTo(target.x, previous.y);
}
ctx.lineTo(target.x, target.y);
}
function _bezierCurveTo(ctx, previous, target, flip2) {
if (!previous) {
return ctx.lineTo(target.x, target.y);
}
ctx.bezierCurveTo(flip2 ? previous.cp1x : previous.cp2x, flip2 ? previous.cp1y : previous.cp2y, flip2 ? target.cp2x : target.cp1x, flip2 ? target.cp2y : target.cp1y, target.x, target.y);
}
function renderText(ctx, text2, x, y, font, opts = {}) {
const lines = isArray(text2) ? text2 : [
text2
];
const stroke = opts.strokeWidth > 0 && opts.strokeColor !== "";
let i, line;
ctx.save();
ctx.font = font.string;
setRenderOpts(ctx, opts);
for (i = 0; i < lines.length; ++i) {
line = lines[i];
if (opts.backdrop) {
drawBackdrop(ctx, opts.backdrop);
}
if (stroke) {
if (opts.strokeColor) {
ctx.strokeStyle = opts.strokeColor;
}
if (!isNullOrUndef(opts.strokeWidth)) {
ctx.lineWidth = opts.strokeWidth;
}
ctx.strokeText(line, x, y, opts.maxWidth);
}
ctx.fillText(line, x, y, opts.maxWidth);
decorateText(ctx, x, y, line, opts);
y += font.lineHeight;
}
ctx.restore();
}
function setRenderOpts(ctx, opts) {
if (opts.translation) {
ctx.translate(opts.translation[0], opts.translation[1]);
}
if (!isNullOrUndef(opts.rotation)) {
ctx.rotate(opts.rotation);
}
if (opts.color) {
ctx.fillStyle = opts.color;
}
if (opts.textAlign) {
ctx.textAlign = opts.textAlign;
}
if (opts.textBaseline) {
ctx.textBaseline = opts.textBaseline;
}
}
function decorateText(ctx, x, y, line, opts) {
if (opts.strikethrough || opts.underline) {
const metrics = ctx.measureText(line);
const left2 = x - metrics.actualBoundingBoxLeft;
const right2 = x + metrics.actualBoundingBoxRight;
const top2 = y - metrics.actualBoundingBoxAscent;
const bottom2 = y + metrics.actualBoundingBoxDescent;
const yDecoration = opts.strikethrough ? (top2 + bottom2) / 2 : bottom2;
ctx.strokeStyle = ctx.fillStyle;
ctx.beginPath();
ctx.lineWidth = opts.decorationWidth || 2;
ctx.moveTo(left2, yDecoration);
ctx.lineTo(right2, yDecoration);
ctx.stroke();
}
}
function drawBackdrop(ctx, opts) {
const oldColor = ctx.fillStyle;
ctx.fillStyle = opts.color;
ctx.fillRect(opts.left, opts.top, opts.width, opts.height);
ctx.fillStyle = oldColor;
}
function addRoundedRectPath(ctx, rect) {
const { x, y, w, h, radius } = rect;
ctx.arc(x + radius.topLeft, y + radius.topLeft, radius.topLeft, -HALF_PI, PI, true);
ctx.lineTo(x, y + h - radius.bottomLeft);
ctx.arc(x + radius.bottomLeft, y + h - radius.bottomLeft, radius.bottomLeft, PI, HALF_PI, true);
ctx.lineTo(x + w - radius.bottomRight, y + h);
ctx.arc(x + w - radius.bottomRight, y + h - radius.bottomRight, radius.bottomRight, HALF_PI, 0, true);
ctx.lineTo(x + w, y + radius.topRight);
ctx.arc(x + w - radius.topRight, y + radius.topRight, radius.topRight, 0, -HALF_PI, true);
ctx.lineTo(x + radius.topLeft, y);
}
var LINE_HEIGHT = /^(normal|(\d+(?:\.\d+)?)(px|em|%)?)$/;
var FONT_STYLE = /^(normal|italic|initial|inherit|unset|(oblique( -?[0-9]?[0-9]deg)?))$/;
function toLineHeight(value, size) {
const matches = ("" + value).match(LINE_HEIGHT);
if (!matches || matches[1] === "normal") {
return size * 1.2;
}
value = +matches[2];
switch (matches[3]) {
case "px":
return value;
case "%":
value /= 100;
break;
}
return size * value;
}
var numberOrZero = (v) => +v || 0;
function _readValueToProps(value, props) {
const ret = {};
const objProps = isObject(props);
const keys = objProps ? Object.keys(props) : props;
const read2 = isObject(value) ? objProps ? (prop) => valueOrDefault(value[prop], value[props[prop]]) : (prop) => value[prop] : () => value;
for (const prop of keys) {
ret[prop] = numberOrZero(read2(prop));
}
return ret;
}
function toTRBL(value) {
return _readValueToProps(value, {
top: "y",
right: "x",
bottom: "y",
left: "x"
});
}
function toTRBLCorners(value) {
return _readValueToProps(value, [
"topLeft",
"topRight",
"bottomLeft",
"bottomRight"
]);
}
function toPadding(value) {
const obj = toTRBL(value);
obj.width = obj.left + obj.right;
obj.height = obj.top + obj.bottom;
return obj;
}
function toFont(options, fallback) {
options = options || {};
fallback = fallback || defaults.font;
let size = valueOrDefault(options.size, fallback.size);
if (typeof size === "string") {
size = parseInt(size, 10);
}
let style = valueOrDefault(options.style, fallback.style);
if (style && !("" + style).match(FONT_STYLE)) {
console.warn('Invalid font style specified: "' + style + '"');
style = void 0;
}
const font = {
family: valueOrDefault(options.family, fallback.family),
lineHeight: toLineHeight(valueOrDefault(options.lineHeight, fallback.lineHeight), size),
size,
style,
weight: valueOrDefault(options.weight, fallback.weight),
string: ""
};
font.string = toFontString(font);
return font;
}
function resolve(inputs, context, index, info) {
let cacheable = true;
let i, ilen, value;
for (i = 0, ilen = inputs.length; i < ilen; ++i) {
value = inputs[i];
if (value === void 0) {
continue;
}
if (context !== void 0 && typeof value === "function") {
value = value(context);
cacheable = false;
}
if (index !== void 0 && isArray(value)) {
value = value[index % value.length];
cacheable = false;
}
if (value !== void 0) {
if (info && !cacheable) {
info.cacheable = false;
}
return value;
}
}
}
function _addGrace(minmax, grace, beginAtZero) {
const { min: min2, max: max2 } = minmax;
const change = toDimension(grace, (max2 - min2) / 2);
const keepZero = (value, add) => beginAtZero && value === 0 ? 0 : value + add;
return {
min: keepZero(min2, -Math.abs(change)),
max: keepZero(max2, change)
};
}
function createContext(parentContext, context) {
return Object.assign(Object.create(parentContext), context);
}
function _createResolver(scopes, prefixes = [
""
], rootScopes = scopes, fallback, getTarget = () => scopes[0]) {
if (!defined(fallback)) {
fallback = _resolve("_fallback", scopes);
}
const cache = {
[Symbol.toStringTag]: "Object",
_cacheable: true,
_scopes: scopes,
_rootScopes: rootScopes,
_fallback: fallback,
_getTarget: getTarget,
override: (scope) => _createResolver([
scope,
...scopes
], prefixes, rootScopes, fallback)
};
return new Proxy(cache, {
deleteProperty(target, prop) {
delete target[prop];
delete target._keys;
delete scopes[0][prop];
return true;
},
get(target, prop) {
return _cached(target, prop, () => _resolveWithPrefixes(prop, prefixes, scopes, target));
},
getOwnPropertyDescriptor(target, prop) {
return Reflect.getOwnPropertyDescriptor(target._scopes[0], prop);
},
getPrototypeOf() {
return Reflect.getPrototypeOf(scopes[0]);
},
has(target, prop) {
return getKeysFromAllScopes(target).includes(prop);
},
ownKeys(target) {
return getKeysFromAllScopes(target);
},
set(target, prop, value) {
const storage = target._storage || (target._storage = getTarget());
target[prop] = storage[prop] = value;
delete target._keys;
return true;
}
});
}
function _attachContext(proxy, context, subProxy, descriptorDefaults) {
const cache = {
_cacheable: false,
_proxy: proxy,
_context: context,
_subProxy: subProxy,
_stack: /* @__PURE__ */ new Set(),
_descriptors: _descriptors(proxy, descriptorDefaults),
setContext: (ctx) => _attachContext(proxy, ctx, subProxy, descriptorDefaults),
override: (scope) => _attachContext(proxy.override(scope), context, subProxy, descriptorDefaults)
};
return new Proxy(cache, {
deleteProperty(target, prop) {
delete target[prop];
delete proxy[prop];
return true;
},
get(target, prop, receiver) {
return _cached(target, prop, () => _resolveWithContext(target, prop, receiver));
},
getOwnPropertyDescriptor(target, prop) {
return target._descriptors.allKeys ? Reflect.has(proxy, prop) ? {
enumerable: true,
configurable: true
} : void 0 : Reflect.getOwnPropertyDescriptor(proxy, prop);
},
getPrototypeOf() {
return Reflect.getPrototypeOf(proxy);
},
has(target, prop) {
return Reflect.has(proxy, prop);
},
ownKeys() {
return Reflect.ownKeys(proxy);
},
set(target, prop, value) {
proxy[prop] = value;
delete target[prop];
return true;
}
});
}
function _descriptors(proxy, defaults2 = {
scriptable: true,
indexable: true
}) {
const { _scriptable = defaults2.scriptable, _indexable = defaults2.indexable, _allKeys = defaults2.allKeys } = proxy;
return {
allKeys: _allKeys,
scriptable: _scriptable,
indexable: _indexable,
isScriptable: isFunction(_scriptable) ? _scriptable : () => _scriptable,
isIndexable: isFunction(_indexable) ? _indexable : () => _indexable
};
}
var readKey = (prefix, name2) => prefix ? prefix + _capitalize(name2) : name2;
var needsSubResolver = (prop, value) => isObject(value) && prop !== "adapters" && (Object.getPrototypeOf(value) === null || value.constructor === Object);
function _cached(target, prop, resolve2) {
if (Object.prototype.hasOwnProperty.call(target, prop)) {
return target[prop];
}
const value = resolve2();
target[prop] = value;
return value;
}
function _resolveWithContext(target, prop, receiver) {
const { _proxy, _context, _subProxy, _descriptors: descriptors2 } = target;
let value = _proxy[prop];
if (isFunction(value) && descriptors2.isScriptable(prop)) {
value = _resolveScriptable(prop, value, target, receiver);
}
if (isArray(value) && value.length) {
value = _resolveArray(prop, value, target, descriptors2.isIndexable);
}
if (needsSubResolver(prop, value)) {
value = _attachContext(value, _context, _subProxy && _subProxy[prop], descriptors2);
}
return value;
}
function _resolveScriptable(prop, value, target, receiver) {
const { _proxy, _context, _subProxy, _stack } = target;
if (_stack.has(prop)) {
throw new Error("Recursion detected: " + Array.from(_stack).join("->") + "->" + prop);
}
_stack.add(prop);
value = value(_context, _subProxy || receiver);
_stack.delete(prop);
if (needsSubResolver(prop, value)) {
value = createSubResolver(_proxy._scopes, _proxy, prop, value);
}
return value;
}
function _resolveArray(prop, value, target, isIndexable) {
const { _proxy, _context, _subProxy, _descriptors: descriptors2 } = target;
if (defined(_context.index) && isIndexable(prop)) {
value = value[_context.index % value.length];
} else if (isObject(value[0])) {
const arr = value;
const scopes = _proxy._scopes.filter((s) => s !== arr);
value = [];
for (const item of arr) {
const resolver = createSubResolver(scopes, _proxy, prop, item);
value.push(_attachContext(resolver, _context, _subProxy && _subProxy[prop], descriptors2));
}
}
return value;
}
function resolveFallback(fallback, prop, value) {
return isFunction(fallback) ? fallback(prop, value) : fallback;
}
var getScope = (key, parent) => key === true ? parent : typeof key === "string" ? resolveObjectKey(parent, key) : void 0;
function addScopes(set2, parentScopes, key, parentFallback, value) {
for (const parent of parentScopes) {
const scope = getScope(key, parent);
if (scope) {
set2.add(scope);
const fallback = resolveFallback(scope._fallback, key, value);
if (defined(fallback) && fallback !== key && fallback !== parentFallback) {
return fallback;
}
} else if (scope === false && defined(parentFallback) && key !== parentFallback) {
return null;
}
}
return false;
}
function createSubResolver(parentScopes, resolver, prop, value) {
const rootScopes = resolver._rootScopes;
const fallback = resolveFallback(resolver._fallback, prop, value);
const allScopes = [
...parentScopes,
...rootScopes
];
const set2 = /* @__PURE__ */ new Set();
set2.add(value);
let key = addScopesFromKey(set2, allScopes, prop, fallback || prop, value);
if (key === null) {
return false;
}
if (defined(fallback) && fallback !== prop) {
key = addScopesFromKey(set2, allScopes, fallback, key, value);
if (key === null) {
return false;
}
}
return _createResolver(Array.from(set2), [
""
], rootScopes, fallback, () => subGetTarget(resolver, prop, value));
}
function addScopesFromKey(set2, allScopes, key, fallback, item) {
while (key) {
key = addScopes(set2, allScopes, key, fallback, item);
}
return key;
}
function subGetTarget(resolver, prop, value) {
const parent = resolver._getTarget();
if (!(prop in parent)) {
parent[prop] = {};
}
const target = parent[prop];
if (isArray(target) && isObject(value)) {
return value;
}
return target || {};
}
function _resolveWithPrefixes(prop, prefixes, scopes, proxy) {
let value;
for (const prefix of prefixes) {
value = _resolve(readKey(prefix, prop), scopes);
if (defined(value)) {
return needsSubResolver(prop, value) ? createSubResolver(scopes, proxy, prop, value) : value;
}
}
}
function _resolve(key, scopes) {
for (const scope of scopes) {
if (!scope) {
continue;
}
const value = scope[key];
if (defined(value)) {
return value;
}
}
}
function getKeysFromAllScopes(target) {
let keys = target._keys;
if (!keys) {
keys = target._keys = resolveKeysFromAllScopes(target._scopes);
}
return keys;
}
function resolveKeysFromAllScopes(scopes) {
const set2 = /* @__PURE__ */ new Set();
for (const scope of scopes) {
for (const key of Object.keys(scope).filter((k) => !k.startsWith("_"))) {
set2.add(key);
}
}
return Array.from(set2);
}
function _parseObjectDataRadialScale(meta, data, start2, count) {
const { iScale } = meta;
const { key = "r" } = this._parsing;
const parsed = new Array(count);
let i, ilen, index, item;
for (i = 0, ilen = count; i < ilen; ++i) {
index = i + start2;
item = data[index];
parsed[i] = {
r: iScale.parse(resolveObjectKey(item, key), index)
};
}
return parsed;
}
var EPSILON = Number.EPSILON || 1e-14;
var getPoint = (points, i) => i < points.length && !points[i].skip && points[i];
var getValueAxis = (indexAxis) => indexAxis === "x" ? "y" : "x";
function splineCurve(firstPoint, middlePoint, afterPoint, t) {
const previous = firstPoint.skip ? middlePoint : firstPoint;
const current = middlePoint;
const next = afterPoint.skip ? middlePoint : afterPoint;
const d01 = distanceBetweenPoints(current, previous);
const d12 = distanceBetweenPoints(next, current);
let s01 = d01 / (d01 + d12);
let s12 = d12 / (d01 + d12);
s01 = isNaN(s01) ? 0 : s01;
s12 = isNaN(s12) ? 0 : s12;
const fa = t * s01;
const fb = t * s12;
return {
previous: {
x: current.x - fa * (next.x - previous.x),
y: current.y - fa * (next.y - previous.y)
},
next: {
x: current.x + fb * (next.x - previous.x),
y: current.y + fb * (next.y - previous.y)
}
};
}
function monotoneAdjust(points, deltaK, mK) {
const pointsLen = points.length;
let alphaK, betaK, tauK, squaredMagnitude, pointCurrent;
let pointAfter = getPoint(points, 0);
for (let i = 0; i < pointsLen - 1; ++i) {
pointCurrent = pointAfter;
pointAfter = getPoint(points, i + 1);
if (!pointCurrent || !pointAfter) {
continue;
}
if (almostEquals(deltaK[i], 0, EPSILON)) {
mK[i] = mK[i + 1] = 0;
continue;
}
alphaK = mK[i] / deltaK[i];
betaK = mK[i + 1] / deltaK[i];
squaredMagnitude = Math.pow(alphaK, 2) + Math.pow(betaK, 2);
if (squaredMagnitude <= 9) {
continue;
}
tauK = 3 / Math.sqrt(squaredMagnitude);
mK[i] = alphaK * tauK * deltaK[i];
mK[i + 1] = betaK * tauK * deltaK[i];
}
}
function monotoneCompute(points, mK, indexAxis = "x") {
const valueAxis = getValueAxis(indexAxis);
const pointsLen = points.length;
let delta, pointBefore, pointCurrent;
let pointAfter = getPoint(points, 0);
for (let i = 0; i < pointsLen; ++i) {
pointBefore = pointCurrent;
pointCurrent = pointAfter;
pointAfter = getPoint(points, i + 1);
if (!pointCurrent) {
continue;
}
const iPixel = pointCurrent[indexAxis];
const vPixel = pointCurrent[valueAxis];
if (pointBefore) {
delta = (iPixel - pointBefore[indexAxis]) / 3;
pointCurrent[`cp1${indexAxis}`] = iPixel - delta;
pointCurrent[`cp1${valueAxis}`] = vPixel - delta * mK[i];
}
if (pointAfter) {
delta = (pointAfter[indexAxis] - iPixel) / 3;
pointCurrent[`cp2${indexAxis}`] = iPixel + delta;
pointCurrent[`cp2${valueAxis}`] = vPixel + delta * mK[i];
}
}
}
function splineCurveMonotone(points, indexAxis = "x") {
const valueAxis = getValueAxis(indexAxis);
const pointsLen = points.length;
const deltaK = Array(pointsLen).fill(0);
const mK = Array(pointsLen);
let i, pointBefore, pointCurrent;
let pointAfter = getPoint(points, 0);
for (i = 0; i < pointsLen; ++i) {
pointBefore = pointCurrent;
pointCurrent = pointAfter;
pointAfter = getPoint(points, i + 1);
if (!pointCurrent) {
continue;
}
if (pointAfter) {
const slopeDelta = pointAfter[indexAxis] - pointCurrent[indexAxis];
deltaK[i] = slopeDelta !== 0 ? (pointAfter[valueAxis] - pointCurrent[valueAxis]) / slopeDelta : 0;
}
mK[i] = !pointBefore ? deltaK[i] : !pointAfter ? deltaK[i - 1] : sign(deltaK[i - 1]) !== sign(deltaK[i]) ? 0 : (deltaK[i - 1] + deltaK[i]) / 2;
}
monotoneAdjust(points, deltaK, mK);
monotoneCompute(points, mK, indexAxis);
}
function capControlPoint(pt, min2, max2) {
return Math.max(Math.min(pt, max2), min2);
}
function capBezierPoints(points, area) {
let i, ilen, point, inArea, inAreaPrev;
let inAreaNext = _isPointInArea(points[0], area);
for (i = 0, ilen = points.length; i < ilen; ++i) {
inAreaPrev = inArea;
inArea = inAreaNext;
inAreaNext = i < ilen - 1 && _isPointInArea(points[i + 1], area);
if (!inArea) {
continue;
}
point = points[i];
if (inAreaPrev) {
point.cp1x = capControlPoint(point.cp1x, area.left, area.right);
point.cp1y = capControlPoint(point.cp1y, area.top, area.bottom);
}
if (inAreaNext) {
point.cp2x = capControlPoint(point.cp2x, area.left, area.right);
point.cp2y = capControlPoint(point.cp2y, area.top, area.bottom);
}
}
}
function _updateBezierControlPoints(points, options, area, loop, indexAxis) {
let i, ilen, point, controlPoints;
if (options.spanGaps) {
points = points.filter((pt) => !pt.skip);
}
if (options.cubicInterpolationMode === "monotone") {
splineCurveMonotone(points, indexAxis);
} else {
let prev = loop ? points[points.length - 1] : points[0];
for (i = 0, ilen = points.length; i < ilen; ++i) {
point = points[i];
controlPoints = splineCurve(prev, point, points[Math.min(i + 1, ilen - (loop ? 0 : 1)) % ilen], options.tension);
point.cp1x = controlPoints.previous.x;
point.cp1y = controlPoints.previous.y;
point.cp2x = controlPoints.next.x;
point.cp2y = controlPoints.next.y;
prev = point;
}
}
if (options.capBezierPoints) {
capBezierPoints(points, area);
}
}
function _isDomSupported() {
return typeof window !== "undefined" && typeof document !== "undefined";
}
function _getParentNode(domNode) {
let parent = domNode.parentNode;
if (parent && parent.toString() === "[object ShadowRoot]") {
parent = parent.host;
}
return parent;
}
function parseMaxStyle(styleValue, node, parentProperty) {
let valueInPixels;
if (typeof styleValue === "string") {
valueInPixels = parseInt(styleValue, 10);
if (styleValue.indexOf("%") !== -1) {
valueInPixels = valueInPixels / 100 * node.parentNode[parentProperty];
}
} else {
valueInPixels = styleValue;
}
return valueInPixels;
}
var getComputedStyle3 = (element2) => element2.ownerDocument.defaultView.getComputedStyle(element2, null);
function getStyle(el, property) {
return getComputedStyle3(el).getPropertyValue(property);
}
var positions = [
"top",
"right",
"bottom",
"left"
];
function getPositionedStyle(styles, style, suffix) {
const result = {};
suffix = suffix ? "-" + suffix : "";
for (let i = 0; i < 4; i++) {
const pos = positions[i];
result[pos] = parseFloat(styles[style + "-" + pos + suffix]) || 0;
}
result.width = result.left + result.right;
result.height = result.top + result.bottom;
return result;
}
var useOffsetPos = (x, y, target) => (x > 0 || y > 0) && (!target || !target.shadowRoot);
function getCanvasPosition(e, canvas) {
const touches = e.touches;
const source = touches && touches.length ? touches[0] : e;
const { offsetX, offsetY } = source;
let box = false;
let x, y;
if (useOffsetPos(offsetX, offsetY, e.target)) {
x = offsetX;
y = offsetY;
} else {
const rect = canvas.getBoundingClientRect();
x = source.clientX - rect.left;
y = source.clientY - rect.top;
box = true;
}
return {
x,
y,
box
};
}
function getRelativePosition(event, chart) {
if ("native" in event) {
return event;
}
const { canvas, currentDevicePixelRatio } = chart;
const style = getComputedStyle3(canvas);
const borderBox = style.boxSizing === "border-box";
const paddings = getPositionedStyle(style, "padding");
const borders = getPositionedStyle(style, "border", "width");
const { x, y, box } = getCanvasPosition(event, canvas);
const xOffset = paddings.left + (box && borders.left);
const yOffset = paddings.top + (box && borders.top);
let { width, height } = chart;
if (borderBox) {
width -= paddings.width + borders.width;
height -= paddings.height + borders.height;
}
return {
x: Math.round((x - xOffset) / width * canvas.width / currentDevicePixelRatio),
y: Math.round((y - yOffset) / height * canvas.height / currentDevicePixelRatio)
};
}
function getContainerSize(canvas, width, height) {
let maxWidth, maxHeight;
if (width === void 0 || height === void 0) {
const container = _getParentNode(canvas);
if (!container) {
width = canvas.clientWidth;
height = canvas.clientHeight;
} else {
const rect = container.getBoundingClientRect();
const containerStyle = getComputedStyle3(container);
const containerBorder = getPositionedStyle(containerStyle, "border", "width");
const containerPadding = getPositionedStyle(containerStyle, "padding");
width = rect.width - containerPadding.width - containerBorder.width;
height = rect.height - containerPadding.height - containerBorder.height;
maxWidth = parseMaxStyle(containerStyle.maxWidth, container, "clientWidth");
maxHeight = parseMaxStyle(containerStyle.maxHeight, container, "clientHeight");
}
}
return {
width,
height,
maxWidth: maxWidth || INFINITY,
maxHeight: maxHeight || INFINITY
};
}
var round1 = (v) => Math.round(v * 10) / 10;
function getMaximumSize(canvas, bbWidth, bbHeight, aspectRatio) {
const style = getComputedStyle3(canvas);
const margins = getPositionedStyle(style, "margin");
const maxWidth = parseMaxStyle(style.maxWidth, canvas, "clientWidth") || INFINITY;
const maxHeight = parseMaxStyle(style.maxHeight, canvas, "clientHeight") || INFINITY;
const containerSize = getContainerSize(canvas, bbWidth, bbHeight);
let { width, height } = containerSize;
if (style.boxSizing === "content-box") {
const borders = getPositionedStyle(style, "border", "width");
const paddings = getPositionedStyle(style, "padding");
width -= paddings.width + borders.width;
height -= paddings.height + borders.height;
}
width = Math.max(0, width - margins.width);
height = Math.max(0, aspectRatio ? width / aspectRatio : height - margins.height);
width = round1(Math.min(width, maxWidth, containerSize.maxWidth));
height = round1(Math.min(height, maxHeight, containerSize.maxHeight));
if (width && !height) {
height = round1(width / 2);
}
const maintainHeight = bbWidth !== void 0 || bbHeight !== void 0;
if (maintainHeight && aspectRatio && containerSize.height && height > containerSize.height) {
height = containerSize.height;
width = round1(Math.floor(height * aspectRatio));
}
return {
width,
height
};
}
function retinaScale(chart, forceRatio, forceStyle) {
const pixelRatio = forceRatio || 1;
const deviceHeight = Math.floor(chart.height * pixelRatio);
const deviceWidth = Math.floor(chart.width * pixelRatio);
chart.height = Math.floor(chart.height);
chart.width = Math.floor(chart.width);
const canvas = chart.canvas;
if (canvas.style && (forceStyle || !canvas.style.height && !canvas.style.width)) {
canvas.style.height = `${chart.height}px`;
canvas.style.width = `${chart.width}px`;
}
if (chart.currentDevicePixelRatio !== pixelRatio || canvas.height !== deviceHeight || canvas.width !== deviceWidth) {
chart.currentDevicePixelRatio = pixelRatio;
canvas.height = deviceHeight;
canvas.width = deviceWidth;
chart.ctx.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);
return true;
}
return false;
}
var supportsEventListenerOptions = function() {
let passiveSupported = false;
try {
const options = {
get passive() {
passiveSupported = true;
return false;
}
};
window.addEventListener("test", null, options);
window.removeEventListener("test", null, options);
} catch (e) {
}
return passiveSupported;
}();
function readUsedSize(element2, property) {
const value = getStyle(element2, property);
const matches = value && value.match(/^(\d+)(\.\d+)?px$/);
return matches ? +matches[1] : void 0;
}
function _pointInLine(p1, p2, t, mode) {
return {
x: p1.x + t * (p2.x - p1.x),
y: p1.y + t * (p2.y - p1.y)
};
}
function _steppedInterpolation(p1, p2, t, mode) {
return {
x: p1.x + t * (p2.x - p1.x),
y: mode === "middle" ? t < 0.5 ? p1.y : p2.y : mode === "after" ? t < 1 ? p1.y : p2.y : t > 0 ? p2.y : p1.y
};
}
function _bezierInterpolation(p1, p2, t, mode) {
const cp1 = {
x: p1.cp2x,
y: p1.cp2y
};
const cp2 = {
x: p2.cp1x,
y: p2.cp1y
};
const a = _pointInLine(p1, cp1, t);
const b = _pointInLine(cp1, cp2, t);
const c = _pointInLine(cp2, p2, t);
const d = _pointInLine(a, b, t);
const e = _pointInLine(b, c, t);
return _pointInLine(d, e, t);
}
var getRightToLeftAdapter = function(rectX, width) {
return {
x(x) {
return rectX + rectX + width - x;
},
setWidth(w) {
width = w;
},
textAlign(align) {
if (align === "center") {
return align;
}
return align === "right" ? "left" : "right";
},
xPlus(x, value) {
return x - value;
},
leftForLtr(x, itemWidth) {
return x - itemWidth;
}
};
};
var getLeftToRightAdapter = function() {
return {
x(x) {
return x;
},
setWidth(w) {
},
textAlign(align) {
return align;
},
xPlus(x, value) {
return x + value;
},
leftForLtr(x, _itemWidth) {
return x;
}
};
};
function getRtlAdapter(rtl, rectX, width) {
return rtl ? getRightToLeftAdapter(rectX, width) : getLeftToRightAdapter();
}
function overrideTextDirection(ctx, direction) {
let style, original;
if (direction === "ltr" || direction === "rtl") {
style = ctx.canvas.style;
original = [
style.getPropertyValue("direction"),
style.getPropertyPriority("direction")
];
style.setProperty("direction", direction, "important");
ctx.prevTextDirection = original;
}
}
function restoreTextDirection(ctx, original) {
if (original !== void 0) {
delete ctx.prevTextDirection;
ctx.canvas.style.setProperty("direction", original[0], original[1]);
}
}
function propertyFn(property) {
if (property === "angle") {
return {
between: _angleBetween,
compare: _angleDiff,
normalize: _normalizeAngle
};
}
return {
between: _isBetween,
compare: (a, b) => a - b,
normalize: (x) => x
};
}
function normalizeSegment({ start: start2, end: end2, count, loop, style }) {
return {
start: start2 % count,
end: end2 % count,
loop: loop && (end2 - start2 + 1) % count === 0,
style
};
}
function getSegment(segment, points, bounds) {
const { property, start: startBound, end: endBound } = bounds;
const { between, normalize } = propertyFn(property);
const count = points.length;
let { start: start2, end: end2, loop } = segment;
let i, ilen;
if (loop) {
start2 += count;
end2 += count;
for (i = 0, ilen = count; i < ilen; ++i) {
if (!between(normalize(points[start2 % count][property]), startBound, endBound)) {
break;
}
start2--;
end2--;
}
start2 %= count;
end2 %= count;
}
if (end2 < start2) {
end2 += count;
}
return {
start: start2,
end: end2,
loop,
style: segment.style
};
}
function _boundSegment(segment, points, bounds) {
if (!bounds) {
return [
segment
];
}
const { property, start: startBound, end: endBound } = bounds;
const count = points.length;
const { compare, between, normalize } = propertyFn(property);
const { start: start2, end: end2, loop, style } = getSegment(segment, points, bounds);
const result = [];
let inside = false;
let subStart = null;
let value, point, prevValue;
const startIsBefore = () => between(startBound, prevValue, value) && compare(startBound, prevValue) !== 0;
const endIsBefore = () => compare(endBound, value) === 0 || between(endBound, prevValue, value);
const shouldStart = () => inside || startIsBefore();
const shouldStop = () => !inside || endIsBefore();
for (let i = start2, prev = start2; i <= end2; ++i) {
point = points[i % count];
if (point.skip) {
continue;
}
value = normalize(point[property]);
if (value === prevValue) {
continue;
}
inside = between(value, startBound, endBound);
if (subStart === null && shouldStart()) {
subStart = compare(value, startBound) === 0 ? i : prev;
}
if (subStart !== null && shouldStop()) {
result.push(normalizeSegment({
start: subStart,
end: i,
loop,
count,
style
}));
subStart = null;
}
prev = i;
prevValue = value;
}
if (subStart !== null) {
result.push(normalizeSegment({
start: subStart,
end: end2,
loop,
count,
style
}));
}
return result;
}
function _boundSegments(line, bounds) {
const result = [];
const segments = line.segments;
for (let i = 0; i < segments.length; i++) {
const sub = _boundSegment(segments[i], line.points, bounds);
if (sub.length) {
result.push(...sub);
}
}
return result;
}
function findStartAndEnd(points, count, loop, spanGaps) {
let start2 = 0;
let end2 = count - 1;
if (loop && !spanGaps) {
while (start2 < count && !points[start2].skip) {
start2++;
}
}
while (start2 < count && points[start2].skip) {
start2++;
}
start2 %= count;
if (loop) {
end2 += start2;
}
while (end2 > start2 && points[end2 % count].skip) {
end2--;
}
end2 %= count;
return {
start: start2,
end: end2
};
}
function solidSegments(points, start2, max2, loop) {
const count = points.length;
const result = [];
let last = start2;
let prev = points[start2];
let end2;
for (end2 = start2 + 1; end2 <= max2; ++end2) {
const cur = points[end2 % count];
if (cur.skip || cur.stop) {
if (!prev.skip) {
loop = false;
result.push({
start: start2 % count,
end: (end2 - 1) % count,
loop
});
start2 = last = cur.stop ? end2 : null;
}
} else {
last = end2;
if (prev.skip) {
start2 = end2;
}
}
prev = cur;
}
if (last !== null) {
result.push({
start: start2 % count,
end: last % count,
loop
});
}
return result;
}
function _computeSegments(line, segmentOptions) {
const points = line.points;
const spanGaps = line.options.spanGaps;
const count = points.length;
if (!count) {
return [];
}
const loop = !!line._loop;
const { start: start2, end: end2 } = findStartAndEnd(points, count, loop, spanGaps);
if (spanGaps === true) {
return splitByStyles(line, [
{
start: start2,
end: end2,
loop
}
], points, segmentOptions);
}
const max2 = end2 < start2 ? end2 + count : end2;
const completeLoop = !!line._fullLoop && start2 === 0 && end2 === count - 1;
return splitByStyles(line, solidSegments(points, start2, max2, completeLoop), points, segmentOptions);
}
function splitByStyles(line, segments, points, segmentOptions) {
if (!segmentOptions || !segmentOptions.setContext || !points) {
return segments;
}
return doSplitByStyles(line, segments, points, segmentOptions);
}
function doSplitByStyles(line, segments, points, segmentOptions) {
const chartContext = line._chart.getContext();
const baseStyle = readStyle(line.options);
const { _datasetIndex: datasetIndex2, options: { spanGaps } } = line;
const count = points.length;
const result = [];
let prevStyle = baseStyle;
let start2 = segments[0].start;
let i = start2;
function addStyle(s, e, l, st) {
const dir = spanGaps ? -1 : 1;
if (s === e) {
return;
}
s += count;
while (points[s % count].skip) {
s -= dir;
}
while (points[e % count].skip) {
e += dir;
}
if (s % count !== e % count) {
result.push({
start: s % count,
end: e % count,
loop: l,
style: st
});
prevStyle = st;
start2 = e % count;
}
}
for (const segment of segments) {
start2 = spanGaps ? start2 : segment.start;
let prev = points[start2 % count];
let style;
for (i = start2 + 1; i <= segment.end; i++) {
const pt = points[i % count];
style = readStyle(segmentOptions.setContext(createContext(chartContext, {
type: "segment",
p0: prev,
p1: pt,
p0DataIndex: (i - 1) % count,
p1DataIndex: i % count,
datasetIndex: datasetIndex2
})));
if (styleChanged(style, prevStyle)) {
addStyle(start2, i - 1, segment.loop, prevStyle);
}
prev = pt;
prevStyle = style;
}
if (start2 < i - 1) {
addStyle(start2, i - 1, segment.loop, prevStyle);
}
}
return result;
}
function readStyle(options) {
return {
backgroundColor: options.backgroundColor,
borderCapStyle: options.borderCapStyle,
borderDash: options.borderDash,
borderDashOffset: options.borderDashOffset,
borderJoinStyle: options.borderJoinStyle,
borderWidth: options.borderWidth,
borderColor: options.borderColor
};
}
function styleChanged(style, prevStyle) {
return prevStyle && JSON.stringify(style) !== JSON.stringify(prevStyle);
}
// node_modules/chart.js/dist/chart.js
var Animator = class {
constructor() {
this._request = null;
this._charts = /* @__PURE__ */ new Map();
this._running = false;
this._lastDate = void 0;
}
_notify(chart, anims, date, type) {
const callbacks = anims.listeners[type];
const numSteps = anims.duration;
callbacks.forEach((fn2) => fn2({
chart,
initial: anims.initial,
numSteps,
currentStep: Math.min(date - anims.start, numSteps)
}));
}
_refresh() {
if (this._request) {
return;
}
this._running = true;
this._request = requestAnimFrame.call(window, () => {
this._update();
this._request = null;
if (this._running) {
this._refresh();
}
});
}
_update(date = Date.now()) {
let remaining = 0;
this._charts.forEach((anims, chart) => {
if (!anims.running || !anims.items.length) {
return;
}
const items = anims.items;
let i = items.length - 1;
let draw2 = false;
let item;
for (; i >= 0; --i) {
item = items[i];
if (item._active) {
if (item._total > anims.duration) {
anims.duration = item._total;
}
item.tick(date);
draw2 = true;
} else {
items[i] = items[items.length - 1];
items.pop();
}
}
if (draw2) {
chart.draw();
this._notify(chart, anims, date, "progress");
}
if (!items.length) {
anims.running = false;
this._notify(chart, anims, date, "complete");
anims.initial = false;
}
remaining += items.length;
});
this._lastDate = date;
if (remaining === 0) {
this._running = false;
}
}
_getAnims(chart) {
const charts = this._charts;
let anims = charts.get(chart);
if (!anims) {
anims = {
running: false,
initial: true,
items: [],
listeners: {
complete: [],
progress: []
}
};
charts.set(chart, anims);
}
return anims;
}
listen(chart, event, cb) {
this._getAnims(chart).listeners[event].push(cb);
}
add(chart, items) {
if (!items || !items.length) {
return;
}
this._getAnims(chart).items.push(...items);
}
has(chart) {
return this._getAnims(chart).items.length > 0;
}
start(chart) {
const anims = this._charts.get(chart);
if (!anims) {
return;
}
anims.running = true;
anims.start = Date.now();
anims.duration = anims.items.reduce((acc, cur) => Math.max(acc, cur._duration), 0);
this._refresh();
}
running(chart) {
if (!this._running) {
return false;
}
const anims = this._charts.get(chart);
if (!anims || !anims.running || !anims.items.length) {
return false;
}
return true;
}
stop(chart) {
const anims = this._charts.get(chart);
if (!anims || !anims.items.length) {
return;
}
const items = anims.items;
let i = items.length - 1;
for (; i >= 0; --i) {
items[i].cancel();
}
anims.items = [];
this._notify(chart, anims, Date.now(), "complete");
}
remove(chart) {
return this._charts.delete(chart);
}
};
var animator = /* @__PURE__ */ new Animator();
var transparent = "transparent";
var interpolators = {
boolean(from2, to2, factor) {
return factor > 0.5 ? to2 : from2;
},
color(from2, to2, factor) {
const c0 = color(from2 || transparent);
const c1 = c0.valid && color(to2 || transparent);
return c1 && c1.valid ? c1.mix(c0, factor).hexString() : to2;
},
number(from2, to2, factor) {
return from2 + (to2 - from2) * factor;
}
};
var Animation = class {
constructor(cfg, target, prop, to2) {
const currentValue = target[prop];
to2 = resolve([
cfg.to,
to2,
currentValue,
cfg.from
]);
const from2 = resolve([
cfg.from,
currentValue,
to2
]);
this._active = true;
this._fn = cfg.fn || interpolators[cfg.type || typeof from2];
this._easing = effects[cfg.easing] || effects.linear;
this._start = Math.floor(Date.now() + (cfg.delay || 0));
this._duration = this._total = Math.floor(cfg.duration);
this._loop = !!cfg.loop;
this._target = target;
this._prop = prop;
this._from = from2;
this._to = to2;
this._promises = void 0;
}
active() {
return this._active;
}
update(cfg, to2, date) {
if (this._active) {
this._notify(false);
const currentValue = this._target[this._prop];
const elapsed = date - this._start;
const remain = this._duration - elapsed;
this._start = date;
this._duration = Math.floor(Math.max(remain, cfg.duration));
this._total += elapsed;
this._loop = !!cfg.loop;
this._to = resolve([
cfg.to,
to2,
currentValue,
cfg.from
]);
this._from = resolve([
cfg.from,
currentValue,
to2
]);
}
}
cancel() {
if (this._active) {
this.tick(Date.now());
this._active = false;
this._notify(false);
}
}
tick(date) {
const elapsed = date - this._start;
const duration = this._duration;
const prop = this._prop;
const from2 = this._from;
const loop = this._loop;
const to2 = this._to;
let factor;
this._active = from2 !== to2 && (loop || elapsed < duration);
if (!this._active) {
this._target[prop] = to2;
this._notify(true);
return;
}
if (elapsed < 0) {
this._target[prop] = from2;
return;
}
factor = elapsed / duration % 2;
factor = loop && factor > 1 ? 2 - factor : factor;
factor = this._easing(Math.min(1, Math.max(0, factor)));
this._target[prop] = this._fn(from2, to2, factor);
}
wait() {
const promises = this._promises || (this._promises = []);
return new Promise((res, rej) => {
promises.push({
res,
rej
});
});
}
_notify(resolved) {
const method = resolved ? "res" : "rej";
const promises = this._promises || [];
for (let i = 0; i < promises.length; i++) {
promises[i][method]();
}
}
};
var Animations = class {
constructor(chart, config) {
this._chart = chart;
this._properties = /* @__PURE__ */ new Map();
this.configure(config);
}
configure(config) {
if (!isObject(config)) {
return;
}
const animationOptions = Object.keys(defaults.animation);
const animatedProps = this._properties;
Object.getOwnPropertyNames(config).forEach((key) => {
const cfg = config[key];
if (!isObject(cfg)) {
return;
}
const resolved = {};
for (const option of animationOptions) {
resolved[option] = cfg[option];
}
(isArray(cfg.properties) && cfg.properties || [
key
]).forEach((prop) => {
if (prop === key || !animatedProps.has(prop)) {
animatedProps.set(prop, resolved);
}
});
});
}
_animateOptions(target, values) {
const newOptions = values.options;
const options = resolveTargetOptions(target, newOptions);
if (!options) {
return [];
}
const animations = this._createAnimations(options, newOptions);
if (newOptions.$shared) {
awaitAll(target.options.$animations, newOptions).then(() => {
target.options = newOptions;
}, () => {
});
}
return animations;
}
_createAnimations(target, values) {
const animatedProps = this._properties;
const animations = [];
const running = target.$animations || (target.$animations = {});
const props = Object.keys(values);
const date = Date.now();
let i;
for (i = props.length - 1; i >= 0; --i) {
const prop = props[i];
if (prop.charAt(0) === "$") {
continue;
}
if (prop === "options") {
animations.push(...this._animateOptions(target, values));
continue;
}
const value = values[prop];
let animation = running[prop];
const cfg = animatedProps.get(prop);
if (animation) {
if (cfg && animation.active()) {
animation.update(cfg, value, date);
continue;
} else {
animation.cancel();
}
}
if (!cfg || !cfg.duration) {
target[prop] = value;
continue;
}
running[prop] = animation = new Animation(cfg, target, prop, value);
animations.push(animation);
}
return animations;
}
update(target, values) {
if (this._properties.size === 0) {
Object.assign(target, values);
return;
}
const animations = this._createAnimations(target, values);
if (animations.length) {
animator.add(this._chart, animations);
return true;
}
}
};
function awaitAll(animations, properties) {
const running = [];
const keys = Object.keys(properties);
for (let i = 0; i < keys.length; i++) {
const anim = animations[keys[i]];
if (anim && anim.active()) {
running.push(anim.wait());
}
}
return Promise.all(running);
}
function resolveTargetOptions(target, newOptions) {
if (!newOptions) {
return;
}
let options = target.options;
if (!options) {
target.options = newOptions;
return;
}
if (options.$shared) {
target.options = options = Object.assign({}, options, {
$shared: false,
$animations: {}
});
}
return options;
}
function scaleClip(scale, allowedOverflow) {
const opts = scale && scale.options || {};
const reverse = opts.reverse;
const min2 = opts.min === void 0 ? allowedOverflow : 0;
const max2 = opts.max === void 0 ? allowedOverflow : 0;
return {
start: reverse ? max2 : min2,
end: reverse ? min2 : max2
};
}
function defaultClip(xScale, yScale, allowedOverflow) {
if (allowedOverflow === false) {
return false;
}
const x = scaleClip(xScale, allowedOverflow);
const y = scaleClip(yScale, allowedOverflow);
return {
top: y.end,
right: x.end,
bottom: y.start,
left: x.start
};
}
function toClip(value) {
let t, r, b, l;
if (isObject(value)) {
t = value.top;
r = value.right;
b = value.bottom;
l = value.left;
} else {
t = r = b = l = value;
}
return {
top: t,
right: r,
bottom: b,
left: l,
disabled: value === false
};
}
function getSortedDatasetIndices(chart, filterVisible) {
const keys = [];
const metasets = chart._getSortedDatasetMetas(filterVisible);
let i, ilen;
for (i = 0, ilen = metasets.length; i < ilen; ++i) {
keys.push(metasets[i].index);
}
return keys;
}
function applyStack(stack, value, dsIndex, options = {}) {
const keys = stack.keys;
const singleMode = options.mode === "single";
let i, ilen, datasetIndex2, otherValue;
if (value === null) {
return;
}
for (i = 0, ilen = keys.length; i < ilen; ++i) {
datasetIndex2 = +keys[i];
if (datasetIndex2 === dsIndex) {
if (options.all) {
continue;
}
break;
}
otherValue = stack.values[datasetIndex2];
if (isNumberFinite(otherValue) && (singleMode || value === 0 || sign(value) === sign(otherValue))) {
value += otherValue;
}
}
return value;
}
function convertObjectDataToArray(data) {
const keys = Object.keys(data);
const adata = new Array(keys.length);
let i, ilen, key;
for (i = 0, ilen = keys.length; i < ilen; ++i) {
key = keys[i];
adata[i] = {
x: key,
y: data[key]
};
}
return adata;
}
function isStacked(scale, meta) {
const stacked = scale && scale.options.stacked;
return stacked || stacked === void 0 && meta.stack !== void 0;
}
function getStackKey(indexScale, valueScale, meta) {
return `${indexScale.id}.${valueScale.id}.${meta.stack || meta.type}`;
}
function getUserBounds(scale) {
const { min: min2, max: max2, minDefined, maxDefined } = scale.getUserBounds();
return {
min: minDefined ? min2 : Number.NEGATIVE_INFINITY,
max: maxDefined ? max2 : Number.POSITIVE_INFINITY
};
}
function getOrCreateStack(stacks, stackKey, indexValue) {
const subStack = stacks[stackKey] || (stacks[stackKey] = {});
return subStack[indexValue] || (subStack[indexValue] = {});
}
function getLastIndexInStack(stack, vScale, positive, type) {
for (const meta of vScale.getMatchingVisibleMetas(type).reverse()) {
const value = stack[meta.index];
if (positive && value > 0 || !positive && value < 0) {
return meta.index;
}
}
return null;
}
function updateStacks(controller, parsed) {
const { chart, _cachedMeta: meta } = controller;
const stacks = chart._stacks || (chart._stacks = {});
const { iScale, vScale, index: datasetIndex2 } = meta;
const iAxis = iScale.axis;
const vAxis = vScale.axis;
const key = getStackKey(iScale, vScale, meta);
const ilen = parsed.length;
let stack;
for (let i = 0; i < ilen; ++i) {
const item = parsed[i];
const { [iAxis]: index, [vAxis]: value } = item;
const itemStacks = item._stacks || (item._stacks = {});
stack = itemStacks[vAxis] = getOrCreateStack(stacks, key, index);
stack[datasetIndex2] = value;
stack._top = getLastIndexInStack(stack, vScale, true, meta.type);
stack._bottom = getLastIndexInStack(stack, vScale, false, meta.type);
const visualValues = stack._visualValues || (stack._visualValues = {});
visualValues[datasetIndex2] = value;
}
}
function getFirstScaleId(chart, axis) {
const scales = chart.scales;
return Object.keys(scales).filter((key) => scales[key].axis === axis).shift();
}
function createDatasetContext(parent, index) {
return createContext(parent, {
active: false,
dataset: void 0,
datasetIndex: index,
index,
mode: "default",
type: "dataset"
});
}
function createDataContext(parent, index, element2) {
return createContext(parent, {
active: false,
dataIndex: index,
parsed: void 0,
raw: void 0,
element: element2,
index,
mode: "default",
type: "data"
});
}
function clearStacks(meta, items) {
const datasetIndex2 = meta.controller.index;
const axis = meta.vScale && meta.vScale.axis;
if (!axis) {
return;
}
items = items || meta._parsed;
for (const parsed of items) {
const stacks = parsed._stacks;
if (!stacks || stacks[axis] === void 0 || stacks[axis][datasetIndex2] === void 0) {
return;
}
delete stacks[axis][datasetIndex2];
if (stacks[axis]._visualValues !== void 0 && stacks[axis]._visualValues[datasetIndex2] !== void 0) {
delete stacks[axis]._visualValues[datasetIndex2];
}
}
}
var isDirectUpdateMode = (mode) => mode === "reset" || mode === "none";
var cloneIfNotShared = (cached, shared) => shared ? cached : Object.assign({}, cached);
var createStack = (canStack, meta, chart) => canStack && !meta.hidden && meta._stacked && {
keys: getSortedDatasetIndices(chart, true),
values: null
};
var DatasetController = class {
constructor(chart, datasetIndex2) {
this.chart = chart;
this._ctx = chart.ctx;
this.index = datasetIndex2;
this._cachedDataOpts = {};
this._cachedMeta = this.getMeta();
this._type = this._cachedMeta.type;
this.options = void 0;
this._parsing = false;
this._data = void 0;
this._objectData = void 0;
this._sharedOptions = void 0;
this._drawStart = void 0;
this._drawCount = void 0;
this.enableOptionSharing = false;
this.supportsDecimation = false;
this.$context = void 0;
this._syncList = [];
this.datasetElementType = new.target.datasetElementType;
this.dataElementType = new.target.dataElementType;
this.initialize();
}
initialize() {
const meta = this._cachedMeta;
this.configure();
this.linkScales();
meta._stacked = isStacked(meta.vScale, meta);
this.addElements();
if (this.options.fill && !this.chart.isPluginEnabled("filler")) {
console.warn("Tried to use the 'fill' option without the 'Filler' plugin enabled. Please import and register the 'Filler' plugin and make sure it is not disabled in the options");
}
}
updateIndex(datasetIndex2) {
if (this.index !== datasetIndex2) {
clearStacks(this._cachedMeta);
}
this.index = datasetIndex2;
}
linkScales() {
const chart = this.chart;
const meta = this._cachedMeta;
const dataset = this.getDataset();
const chooseId = (axis, x, y, r) => axis === "x" ? x : axis === "r" ? r : y;
const xid = meta.xAxisID = valueOrDefault(dataset.xAxisID, getFirstScaleId(chart, "x"));
const yid = meta.yAxisID = valueOrDefault(dataset.yAxisID, getFirstScaleId(chart, "y"));
const rid = meta.rAxisID = valueOrDefault(dataset.rAxisID, getFirstScaleId(chart, "r"));
const indexAxis = meta.indexAxis;
const iid = meta.iAxisID = chooseId(indexAxis, xid, yid, rid);
const vid = meta.vAxisID = chooseId(indexAxis, yid, xid, rid);
meta.xScale = this.getScaleForId(xid);
meta.yScale = this.getScaleForId(yid);
meta.rScale = this.getScaleForId(rid);
meta.iScale = this.getScaleForId(iid);
meta.vScale = this.getScaleForId(vid);
}
getDataset() {
return this.chart.data.datasets[this.index];
}
getMeta() {
return this.chart.getDatasetMeta(this.index);
}
getScaleForId(scaleID) {
return this.chart.scales[scaleID];
}
_getOtherScale(scale) {
const meta = this._cachedMeta;
return scale === meta.iScale ? meta.vScale : meta.iScale;
}
reset() {
this._update("reset");
}
_destroy() {
const meta = this._cachedMeta;
if (this._data) {
unlistenArrayEvents(this._data, this);
}
if (meta._stacked) {
clearStacks(meta);
}
}
_dataCheck() {
const dataset = this.getDataset();
const data = dataset.data || (dataset.data = []);
const _data = this._data;
if (isObject(data)) {
this._data = convertObjectDataToArray(data);
} else if (_data !== data) {
if (_data) {
unlistenArrayEvents(_data, this);
const meta = this._cachedMeta;
clearStacks(meta);
meta._parsed = [];
}
if (data && Object.isExtensible(data)) {
listenArrayEvents(data, this);
}
this._syncList = [];
this._data = data;
}
}
addElements() {
const meta = this._cachedMeta;
this._dataCheck();
if (this.datasetElementType) {
meta.dataset = new this.datasetElementType();
}
}
buildOrUpdateElements(resetNewElements) {
const meta = this._cachedMeta;
const dataset = this.getDataset();
let stackChanged = false;
this._dataCheck();
const oldStacked = meta._stacked;
meta._stacked = isStacked(meta.vScale, meta);
if (meta.stack !== dataset.stack) {
stackChanged = true;
clearStacks(meta);
meta.stack = dataset.stack;
}
this._resyncElements(resetNewElements);
if (stackChanged || oldStacked !== meta._stacked) {
updateStacks(this, meta._parsed);
}
}
configure() {
const config = this.chart.config;
const scopeKeys = config.datasetScopeKeys(this._type);
const scopes = config.getOptionScopes(this.getDataset(), scopeKeys, true);
this.options = config.createResolver(scopes, this.getContext());
this._parsing = this.options.parsing;
this._cachedDataOpts = {};
}
parse(start2, count) {
const { _cachedMeta: meta, _data: data } = this;
const { iScale, _stacked } = meta;
const iAxis = iScale.axis;
let sorted = start2 === 0 && count === data.length ? true : meta._sorted;
let prev = start2 > 0 && meta._parsed[start2 - 1];
let i, cur, parsed;
if (this._parsing === false) {
meta._parsed = data;
meta._sorted = true;
parsed = data;
} else {
if (isArray(data[start2])) {
parsed = this.parseArrayData(meta, data, start2, count);
} else if (isObject(data[start2])) {
parsed = this.parseObjectData(meta, data, start2, count);
} else {
parsed = this.parsePrimitiveData(meta, data, start2, count);
}
const isNotInOrderComparedToPrev = () => cur[iAxis] === null || prev && cur[iAxis] < prev[iAxis];
for (i = 0; i < count; ++i) {
meta._parsed[i + start2] = cur = parsed[i];
if (sorted) {
if (isNotInOrderComparedToPrev()) {
sorted = false;
}
prev = cur;
}
}
meta._sorted = sorted;
}
if (_stacked) {
updateStacks(this, parsed);
}
}
parsePrimitiveData(meta, data, start2, count) {
const { iScale, vScale } = meta;
const iAxis = iScale.axis;
const vAxis = vScale.axis;
const labels = iScale.getLabels();
const singleScale = iScale === vScale;
const parsed = new Array(count);
let i, ilen, index;
for (i = 0, ilen = count; i < ilen; ++i) {
index = i + start2;
parsed[i] = {
[iAxis]: singleScale || iScale.parse(labels[index], index),
[vAxis]: vScale.parse(data[index], index)
};
}
return parsed;
}
parseArrayData(meta, data, start2, count) {
const { xScale, yScale } = meta;
const parsed = new Array(count);
let i, ilen, index, item;
for (i = 0, ilen = count; i < ilen; ++i) {
index = i + start2;
item = data[index];
parsed[i] = {
x: xScale.parse(item[0], index),
y: yScale.parse(item[1], index)
};
}
return parsed;
}
parseObjectData(meta, data, start2, count) {
const { xScale, yScale } = meta;
const { xAxisKey = "x", yAxisKey = "y" } = this._parsing;
const parsed = new Array(count);
let i, ilen, index, item;
for (i = 0, ilen = count; i < ilen; ++i) {
index = i + start2;
item = data[index];
parsed[i] = {
x: xScale.parse(resolveObjectKey(item, xAxisKey), index),
y: yScale.parse(resolveObjectKey(item, yAxisKey), index)
};
}
return parsed;
}
getParsed(index) {
return this._cachedMeta._parsed[index];
}
getDataElement(index) {
return this._cachedMeta.data[index];
}
applyStack(scale, parsed, mode) {
const chart = this.chart;
const meta = this._cachedMeta;
const value = parsed[scale.axis];
const stack = {
keys: getSortedDatasetIndices(chart, true),
values: parsed._stacks[scale.axis]._visualValues
};
return applyStack(stack, value, meta.index, {
mode
});
}
updateRangeFromParsed(range, scale, parsed, stack) {
const parsedValue = parsed[scale.axis];
let value = parsedValue === null ? NaN : parsedValue;
const values = stack && parsed._stacks[scale.axis];
if (stack && values) {
stack.values = values;
value = applyStack(stack, parsedValue, this._cachedMeta.index);
}
range.min = Math.min(range.min, value);
range.max = Math.max(range.max, value);
}
getMinMax(scale, canStack) {
const meta = this._cachedMeta;
const _parsed = meta._parsed;
const sorted = meta._sorted && scale === meta.iScale;
const ilen = _parsed.length;
const otherScale = this._getOtherScale(scale);
const stack = createStack(canStack, meta, this.chart);
const range = {
min: Number.POSITIVE_INFINITY,
max: Number.NEGATIVE_INFINITY
};
const { min: otherMin, max: otherMax } = getUserBounds(otherScale);
let i, parsed;
function _skip() {
parsed = _parsed[i];
const otherValue = parsed[otherScale.axis];
return !isNumberFinite(parsed[scale.axis]) || otherMin > otherValue || otherMax < otherValue;
}
for (i = 0; i < ilen; ++i) {
if (_skip()) {
continue;
}
this.updateRangeFromParsed(range, scale, parsed, stack);
if (sorted) {
break;
}
}
if (sorted) {
for (i = ilen - 1; i >= 0; --i) {
if (_skip()) {
continue;
}
this.updateRangeFromParsed(range, scale, parsed, stack);
break;
}
}
return range;
}
getAllParsedValues(scale) {
const parsed = this._cachedMeta._parsed;
const values = [];
let i, ilen, value;
for (i = 0, ilen = parsed.length; i < ilen; ++i) {
value = parsed[i][scale.axis];
if (isNumberFinite(value)) {
values.push(value);
}
}
return values;
}
getMaxOverflow() {
return false;
}
getLabelAndValue(index) {
const meta = this._cachedMeta;
const iScale = meta.iScale;
const vScale = meta.vScale;
const parsed = this.getParsed(index);
return {
label: iScale ? "" + iScale.getLabelForValue(parsed[iScale.axis]) : "",
value: vScale ? "" + vScale.getLabelForValue(parsed[vScale.axis]) : ""
};
}
_update(mode) {
const meta = this._cachedMeta;
this.update(mode || "default");
meta._clip = toClip(valueOrDefault(this.options.clip, defaultClip(meta.xScale, meta.yScale, this.getMaxOverflow())));
}
update(mode) {
}
draw() {
const ctx = this._ctx;
const chart = this.chart;
const meta = this._cachedMeta;
const elements = meta.data || [];
const area = chart.chartArea;
const active = [];
const start2 = this._drawStart || 0;
const count = this._drawCount || elements.length - start2;
const drawActiveElementsOnTop = this.options.drawActiveElementsOnTop;
let i;
if (meta.dataset) {
meta.dataset.draw(ctx, area, start2, count);
}
for (i = start2; i < start2 + count; ++i) {
const element2 = elements[i];
if (element2.hidden) {
continue;
}
if (element2.active && drawActiveElementsOnTop) {
active.push(element2);
} else {
element2.draw(ctx, area);
}
}
for (i = 0; i < active.length; ++i) {
active[i].draw(ctx, area);
}
}
getStyle(index, active) {
const mode = active ? "active" : "default";
return index === void 0 && this._cachedMeta.dataset ? this.resolveDatasetElementOptions(mode) : this.resolveDataElementOptions(index || 0, mode);
}
getContext(index, active, mode) {
const dataset = this.getDataset();
let context;
if (index >= 0 && index < this._cachedMeta.data.length) {
const element2 = this._cachedMeta.data[index];
context = element2.$context || (element2.$context = createDataContext(this.getContext(), index, element2));
context.parsed = this.getParsed(index);
context.raw = dataset.data[index];
context.index = context.dataIndex = index;
} else {
context = this.$context || (this.$context = createDatasetContext(this.chart.getContext(), this.index));
context.dataset = dataset;
context.index = context.datasetIndex = this.index;
}
context.active = !!active;
context.mode = mode;
return context;
}
resolveDatasetElementOptions(mode) {
return this._resolveElementOptions(this.datasetElementType.id, mode);
}
resolveDataElementOptions(index, mode) {
return this._resolveElementOptions(this.dataElementType.id, mode, index);
}
_resolveElementOptions(elementType, mode = "default", index) {
const active = mode === "active";
const cache = this._cachedDataOpts;
const cacheKey = elementType + "-" + mode;
const cached = cache[cacheKey];
const sharing = this.enableOptionSharing && defined(index);
if (cached) {
return cloneIfNotShared(cached, sharing);
}
const config = this.chart.config;
const scopeKeys = config.datasetElementScopeKeys(this._type, elementType);
const prefixes = active ? [
`${elementType}Hover`,
"hover",
elementType,
""
] : [
elementType,
""
];
const scopes = config.getOptionScopes(this.getDataset(), scopeKeys);
const names2 = Object.keys(defaults.elements[elementType]);
const context = () => this.getContext(index, active, mode);
const values = config.resolveNamedOptions(scopes, names2, context, prefixes);
if (values.$shared) {
values.$shared = sharing;
cache[cacheKey] = Object.freeze(cloneIfNotShared(values, sharing));
}
return values;
}
_resolveAnimations(index, transition, active) {
const chart = this.chart;
const cache = this._cachedDataOpts;
const cacheKey = `animation-${transition}`;
const cached = cache[cacheKey];
if (cached) {
return cached;
}
let options;
if (chart.options.animation !== false) {
const config = this.chart.config;
const scopeKeys = config.datasetAnimationScopeKeys(this._type, transition);
const scopes = config.getOptionScopes(this.getDataset(), scopeKeys);
options = config.createResolver(scopes, this.getContext(index, active, transition));
}
const animations = new Animations(chart, options && options.animations);
if (options && options._cacheable) {
cache[cacheKey] = Object.freeze(animations);
}
return animations;
}
getSharedOptions(options) {
if (!options.$shared) {
return;
}
return this._sharedOptions || (this._sharedOptions = Object.assign({}, options));
}
includeOptions(mode, sharedOptions) {
return !sharedOptions || isDirectUpdateMode(mode) || this.chart._animationsDisabled;
}
_getSharedOptions(start2, mode) {
const firstOpts = this.resolveDataElementOptions(start2, mode);
const previouslySharedOptions = this._sharedOptions;
const sharedOptions = this.getSharedOptions(firstOpts);
const includeOptions = this.includeOptions(mode, sharedOptions) || sharedOptions !== previouslySharedOptions;
this.updateSharedOptions(sharedOptions, mode, firstOpts);
return {
sharedOptions,
includeOptions
};
}
updateElement(element2, index, properties, mode) {
if (isDirectUpdateMode(mode)) {
Object.assign(element2, properties);
} else {
this._resolveAnimations(index, mode).update(element2, properties);
}
}
updateSharedOptions(sharedOptions, mode, newOptions) {
if (sharedOptions && !isDirectUpdateMode(mode)) {
this._resolveAnimations(void 0, mode).update(sharedOptions, newOptions);
}
}
_setStyle(element2, index, mode, active) {
element2.active = active;
const options = this.getStyle(index, active);
this._resolveAnimations(index, mode, active).update(element2, {
options: !active && this.getSharedOptions(options) || options
});
}
removeHoverStyle(element2, datasetIndex2, index) {
this._setStyle(element2, index, "active", false);
}
setHoverStyle(element2, datasetIndex2, index) {
this._setStyle(element2, index, "active", true);
}
_removeDatasetHoverStyle() {
const element2 = this._cachedMeta.dataset;
if (element2) {
this._setStyle(element2, void 0, "active", false);
}
}
_setDatasetHoverStyle() {
const element2 = this._cachedMeta.dataset;
if (element2) {
this._setStyle(element2, void 0, "active", true);
}
}
_resyncElements(resetNewElements) {
const data = this._data;
const elements = this._cachedMeta.data;
for (const [method, arg1, arg2] of this._syncList) {
this[method](arg1, arg2);
}
this._syncList = [];
const numMeta = elements.length;
const numData = data.length;
const count = Math.min(numData, numMeta);
if (count) {
this.parse(0, count);
}
if (numData > numMeta) {
this._insertElements(numMeta, numData - numMeta, resetNewElements);
} else if (numData < numMeta) {
this._removeElements(numData, numMeta - numData);
}
}
_insertElements(start2, count, resetNewElements = true) {
const meta = this._cachedMeta;
const data = meta.data;
const end2 = start2 + count;
let i;
const move = (arr) => {
arr.length += count;
for (i = arr.length - 1; i >= end2; i--) {
arr[i] = arr[i - count];
}
};
move(data);
for (i = start2; i < end2; ++i) {
data[i] = new this.dataElementType();
}
if (this._parsing) {
move(meta._parsed);
}
this.parse(start2, count);
if (resetNewElements) {
this.updateElements(data, start2, count, "reset");
}
}
updateElements(element2, start2, count, mode) {
}
_removeElements(start2, count) {
const meta = this._cachedMeta;
if (this._parsing) {
const removed = meta._parsed.splice(start2, count);
if (meta._stacked) {
clearStacks(meta, removed);
}
}
meta.data.splice(start2, count);
}
_sync(args) {
if (this._parsing) {
this._syncList.push(args);
} else {
const [method, arg1, arg2] = args;
this[method](arg1, arg2);
}
this.chart._dataChanges.push([
this.index,
...args
]);
}
_onDataPush() {
const count = arguments.length;
this._sync([
"_insertElements",
this.getDataset().data.length - count,
count
]);
}
_onDataPop() {
this._sync([
"_removeElements",
this._cachedMeta.data.length - 1,
1
]);
}
_onDataShift() {
this._sync([
"_removeElements",
0,
1
]);
}
_onDataSplice(start2, count) {
if (count) {
this._sync([
"_removeElements",
start2,
count
]);
}
const newCount = arguments.length - 2;
if (newCount) {
this._sync([
"_insertElements",
start2,
newCount
]);
}
}
_onDataUnshift() {
this._sync([
"_insertElements",
0,
arguments.length
]);
}
};
__publicField(DatasetController, "defaults", {});
__publicField(DatasetController, "datasetElementType", null);
__publicField(DatasetController, "dataElementType", null);
function getAllScaleValues(scale, type) {
if (!scale._cache.$bar) {
const visibleMetas = scale.getMatchingVisibleMetas(type);
let values = [];
for (let i = 0, ilen = visibleMetas.length; i < ilen; i++) {
values = values.concat(visibleMetas[i].controller.getAllParsedValues(scale));
}
scale._cache.$bar = _arrayUnique(values.sort((a, b) => a - b));
}
return scale._cache.$bar;
}
function computeMinSampleSize(meta) {
const scale = meta.iScale;
const values = getAllScaleValues(scale, meta.type);
let min2 = scale._length;
let i, ilen, curr, prev;
const updateMinAndPrev = () => {
if (curr === 32767 || curr === -32768) {
return;
}
if (defined(prev)) {
min2 = Math.min(min2, Math.abs(curr - prev) || min2);
}
prev = curr;
};
for (i = 0, ilen = values.length; i < ilen; ++i) {
curr = scale.getPixelForValue(values[i]);
updateMinAndPrev();
}
prev = void 0;
for (i = 0, ilen = scale.ticks.length; i < ilen; ++i) {
curr = scale.getPixelForTick(i);
updateMinAndPrev();
}
return min2;
}
function computeFitCategoryTraits(index, ruler, options, stackCount) {
const thickness = options.barThickness;
let size, ratio;
if (isNullOrUndef(thickness)) {
size = ruler.min * options.categoryPercentage;
ratio = options.barPercentage;
} else {
size = thickness * stackCount;
ratio = 1;
}
return {
chunk: size / stackCount,
ratio,
start: ruler.pixels[index] - size / 2
};
}
function computeFlexCategoryTraits(index, ruler, options, stackCount) {
const pixels = ruler.pixels;
const curr = pixels[index];
let prev = index > 0 ? pixels[index - 1] : null;
let next = index < pixels.length - 1 ? pixels[index + 1] : null;
const percent = options.categoryPercentage;
if (prev === null) {
prev = curr - (next === null ? ruler.end - ruler.start : next - curr);
}
if (next === null) {
next = curr + curr - prev;
}
const start2 = curr - (curr - Math.min(prev, next)) / 2 * percent;
const size = Math.abs(next - prev) / 2 * percent;
return {
chunk: size / stackCount,
ratio: options.barPercentage,
start: start2
};
}
function parseFloatBar(entry, item, vScale, i) {
const startValue = vScale.parse(entry[0], i);
const endValue = vScale.parse(entry[1], i);
const min2 = Math.min(startValue, endValue);
const max2 = Math.max(startValue, endValue);
let barStart = min2;
let barEnd = max2;
if (Math.abs(min2) > Math.abs(max2)) {
barStart = max2;
barEnd = min2;
}
item[vScale.axis] = barEnd;
item._custom = {
barStart,
barEnd,
start: startValue,
end: endValue,
min: min2,
max: max2
};
}
function parseValue(entry, item, vScale, i) {
if (isArray(entry)) {
parseFloatBar(entry, item, vScale, i);
} else {
item[vScale.axis] = vScale.parse(entry, i);
}
return item;
}
function parseArrayOrPrimitive(meta, data, start2, count) {
const iScale = meta.iScale;
const vScale = meta.vScale;
const labels = iScale.getLabels();
const singleScale = iScale === vScale;
const parsed = [];
let i, ilen, item, entry;
for (i = start2, ilen = start2 + count; i < ilen; ++i) {
entry = data[i];
item = {};
item[iScale.axis] = singleScale || iScale.parse(labels[i], i);
parsed.push(parseValue(entry, item, vScale, i));
}
return parsed;
}
function isFloatBar(custom) {
return custom && custom.barStart !== void 0 && custom.barEnd !== void 0;
}
function barSign(size, vScale, actualBase) {
if (size !== 0) {
return sign(size);
}
return (vScale.isHorizontal() ? 1 : -1) * (vScale.min >= actualBase ? 1 : -1);
}
function borderProps(properties) {
let reverse, start2, end2, top2, bottom2;
if (properties.horizontal) {
reverse = properties.base > properties.x;
start2 = "left";
end2 = "right";
} else {
reverse = properties.base < properties.y;
start2 = "bottom";
end2 = "top";
}
if (reverse) {
top2 = "end";
bottom2 = "start";
} else {
top2 = "start";
bottom2 = "end";
}
return {
start: start2,
end: end2,
reverse,
top: top2,
bottom: bottom2
};
}
function setBorderSkipped(properties, options, stack, index) {
let edge = options.borderSkipped;
const res = {};
if (!edge) {
properties.borderSkipped = res;
return;
}
if (edge === true) {
properties.borderSkipped = {
top: true,
right: true,
bottom: true,
left: true
};
return;
}
const { start: start2, end: end2, reverse, top: top2, bottom: bottom2 } = borderProps(properties);
if (edge === "middle" && stack) {
properties.enableBorderRadius = true;
if ((stack._top || 0) === index) {
edge = top2;
} else if ((stack._bottom || 0) === index) {
edge = bottom2;
} else {
res[parseEdge(bottom2, start2, end2, reverse)] = true;
edge = top2;
}
}
res[parseEdge(edge, start2, end2, reverse)] = true;
properties.borderSkipped = res;
}
function parseEdge(edge, a, b, reverse) {
if (reverse) {
edge = swap(edge, a, b);
edge = startEnd(edge, b, a);
} else {
edge = startEnd(edge, a, b);
}
return edge;
}
function swap(orig, v1, v2) {
return orig === v1 ? v2 : orig === v2 ? v1 : orig;
}
function startEnd(v, start2, end2) {
return v === "start" ? start2 : v === "end" ? end2 : v;
}
function setInflateAmount(properties, { inflateAmount }, ratio) {
properties.inflateAmount = inflateAmount === "auto" ? ratio === 1 ? 0.33 : 0 : inflateAmount;
}
var BarController = class extends DatasetController {
parsePrimitiveData(meta, data, start2, count) {
return parseArrayOrPrimitive(meta, data, start2, count);
}
parseArrayData(meta, data, start2, count) {
return parseArrayOrPrimitive(meta, data, start2, count);
}
parseObjectData(meta, data, start2, count) {
const { iScale, vScale } = meta;
const { xAxisKey = "x", yAxisKey = "y" } = this._parsing;
const iAxisKey = iScale.axis === "x" ? xAxisKey : yAxisKey;
const vAxisKey = vScale.axis === "x" ? xAxisKey : yAxisKey;
const parsed = [];
let i, ilen, item, obj;
for (i = start2, ilen = start2 + count; i < ilen; ++i) {
obj = data[i];
item = {};
item[iScale.axis] = iScale.parse(resolveObjectKey(obj, iAxisKey), i);
parsed.push(parseValue(resolveObjectKey(obj, vAxisKey), item, vScale, i));
}
return parsed;
}
updateRangeFromParsed(range, scale, parsed, stack) {
super.updateRangeFromParsed(range, scale, parsed, stack);
const custom = parsed._custom;
if (custom && scale === this._cachedMeta.vScale) {
range.min = Math.min(range.min, custom.min);
range.max = Math.max(range.max, custom.max);
}
}
getMaxOverflow() {
return 0;
}
getLabelAndValue(index) {
const meta = this._cachedMeta;
const { iScale, vScale } = meta;
const parsed = this.getParsed(index);
const custom = parsed._custom;
const value = isFloatBar(custom) ? "[" + custom.start + ", " + custom.end + "]" : "" + vScale.getLabelForValue(parsed[vScale.axis]);
return {
label: "" + iScale.getLabelForValue(parsed[iScale.axis]),
value
};
}
initialize() {
this.enableOptionSharing = true;
super.initialize();
const meta = this._cachedMeta;
meta.stack = this.getDataset().stack;
}
update(mode) {
const meta = this._cachedMeta;
this.updateElements(meta.data, 0, meta.data.length, mode);
}
updateElements(bars, start2, count, mode) {
const reset = mode === "reset";
const { index, _cachedMeta: { vScale } } = this;
const base = vScale.getBasePixel();
const horizontal = vScale.isHorizontal();
const ruler = this._getRuler();
const { sharedOptions, includeOptions } = this._getSharedOptions(start2, mode);
for (let i = start2; i < start2 + count; i++) {
const parsed = this.getParsed(i);
const vpixels = reset || isNullOrUndef(parsed[vScale.axis]) ? {
base,
head: base
} : this._calculateBarValuePixels(i);
const ipixels = this._calculateBarIndexPixels(i, ruler);
const stack = (parsed._stacks || {})[vScale.axis];
const properties = {
horizontal,
base: vpixels.base,
enableBorderRadius: !stack || isFloatBar(parsed._custom) || index === stack._top || index === stack._bottom,
x: horizontal ? vpixels.head : ipixels.center,
y: horizontal ? ipixels.center : vpixels.head,
height: horizontal ? ipixels.size : Math.abs(vpixels.size),
width: horizontal ? Math.abs(vpixels.size) : ipixels.size
};
if (includeOptions) {
properties.options = sharedOptions || this.resolveDataElementOptions(i, bars[i].active ? "active" : mode);
}
const options = properties.options || bars[i].options;
setBorderSkipped(properties, options, stack, index);
setInflateAmount(properties, options, ruler.ratio);
this.updateElement(bars[i], i, properties, mode);
}
}
_getStacks(last, dataIndex) {
const { iScale } = this._cachedMeta;
const metasets = iScale.getMatchingVisibleMetas(this._type).filter((meta) => meta.controller.options.grouped);
const stacked = iScale.options.stacked;
const stacks = [];
const skipNull = (meta) => {
const parsed = meta.controller.getParsed(dataIndex);
const val = parsed && parsed[meta.vScale.axis];
if (isNullOrUndef(val) || isNaN(val)) {
return true;
}
};
for (const meta of metasets) {
if (dataIndex !== void 0 && skipNull(meta)) {
continue;
}
if (stacked === false || stacks.indexOf(meta.stack) === -1 || stacked === void 0 && meta.stack === void 0) {
stacks.push(meta.stack);
}
if (meta.index === last) {
break;
}
}
if (!stacks.length) {
stacks.push(void 0);
}
return stacks;
}
_getStackCount(index) {
return this._getStacks(void 0, index).length;
}
_getStackIndex(datasetIndex2, name2, dataIndex) {
const stacks = this._getStacks(datasetIndex2, dataIndex);
const index = name2 !== void 0 ? stacks.indexOf(name2) : -1;
return index === -1 ? stacks.length - 1 : index;
}
_getRuler() {
const opts = this.options;
const meta = this._cachedMeta;
const iScale = meta.iScale;
const pixels = [];
let i, ilen;
for (i = 0, ilen = meta.data.length; i < ilen; ++i) {
pixels.push(iScale.getPixelForValue(this.getParsed(i)[iScale.axis], i));
}
const barThickness = opts.barThickness;
const min2 = barThickness || computeMinSampleSize(meta);
return {
min: min2,
pixels,
start: iScale._startPixel,
end: iScale._endPixel,
stackCount: this._getStackCount(),
scale: iScale,
grouped: opts.grouped,
ratio: barThickness ? 1 : opts.categoryPercentage * opts.barPercentage
};
}
_calculateBarValuePixels(index) {
const { _cachedMeta: { vScale, _stacked, index: datasetIndex2 }, options: { base: baseValue, minBarLength } } = this;
const actualBase = baseValue || 0;
const parsed = this.getParsed(index);
const custom = parsed._custom;
const floating = isFloatBar(custom);
let value = parsed[vScale.axis];
let start2 = 0;
let length = _stacked ? this.applyStack(vScale, parsed, _stacked) : value;
let head, size;
if (length !== value) {
start2 = length - value;
length = value;
}
if (floating) {
value = custom.barStart;
length = custom.barEnd - custom.barStart;
if (value !== 0 && sign(value) !== sign(custom.barEnd)) {
start2 = 0;
}
start2 += value;
}
const startValue = !isNullOrUndef(baseValue) && !floating ? baseValue : start2;
let base = vScale.getPixelForValue(startValue);
if (this.chart.getDataVisibility(index)) {
head = vScale.getPixelForValue(start2 + length);
} else {
head = base;
}
size = head - base;
if (Math.abs(size) < minBarLength) {
size = barSign(size, vScale, actualBase) * minBarLength;
if (value === actualBase) {
base -= size / 2;
}
const startPixel = vScale.getPixelForDecimal(0);
const endPixel = vScale.getPixelForDecimal(1);
const min2 = Math.min(startPixel, endPixel);
const max2 = Math.max(startPixel, endPixel);
base = Math.max(Math.min(base, max2), min2);
head = base + size;
if (_stacked && !floating) {
parsed._stacks[vScale.axis]._visualValues[datasetIndex2] = vScale.getValueForPixel(head) - vScale.getValueForPixel(base);
}
}
if (base === vScale.getPixelForValue(actualBase)) {
const halfGrid = sign(size) * vScale.getLineWidthForValue(actualBase) / 2;
base += halfGrid;
size -= halfGrid;
}
return {
size,
base,
head,
center: head + size / 2
};
}
_calculateBarIndexPixels(index, ruler) {
const scale = ruler.scale;
const options = this.options;
const skipNull = options.skipNull;
const maxBarThickness = valueOrDefault(options.maxBarThickness, Infinity);
let center, size;
if (ruler.grouped) {
const stackCount = skipNull ? this._getStackCount(index) : ruler.stackCount;
const range = options.barThickness === "flex" ? computeFlexCategoryTraits(index, ruler, options, stackCount) : computeFitCategoryTraits(index, ruler, options, stackCount);
const stackIndex = this._getStackIndex(this.index, this._cachedMeta.stack, skipNull ? index : void 0);
center = range.start + range.chunk * stackIndex + range.chunk / 2;
size = Math.min(maxBarThickness, range.chunk * range.ratio);
} else {
center = scale.getPixelForValue(this.getParsed(index)[scale.axis], index);
size = Math.min(maxBarThickness, ruler.min * ruler.ratio);
}
return {
base: center - size / 2,
head: center + size / 2,
center,
size
};
}
draw() {
const meta = this._cachedMeta;
const vScale = meta.vScale;
const rects = meta.data;
const ilen = rects.length;
let i = 0;
for (; i < ilen; ++i) {
if (this.getParsed(i)[vScale.axis] !== null) {
rects[i].draw(this._ctx);
}
}
}
};
__publicField(BarController, "id", "bar");
__publicField(BarController, "defaults", {
datasetElementType: false,
dataElementType: "bar",
categoryPercentage: 0.8,
barPercentage: 0.9,
grouped: true,
animations: {
numbers: {
type: "number",
properties: [
"x",
"y",
"base",
"width",
"height"
]
}
}
});
__publicField(BarController, "overrides", {
scales: {
_index_: {
type: "category",
offset: true,
grid: {
offset: true
}
},
_value_: {
type: "linear",
beginAtZero: true
}
}
});
function getRatioAndOffset(rotation, circumference, cutout) {
let ratioX = 1;
let ratioY = 1;
let offsetX = 0;
let offsetY = 0;
if (circumference < TAU) {
const startAngle = rotation;
const endAngle = startAngle + circumference;
const startX = Math.cos(startAngle);
const startY = Math.sin(startAngle);
const endX = Math.cos(endAngle);
const endY = Math.sin(endAngle);
const calcMax = (angle, a, b) => _angleBetween(angle, startAngle, endAngle, true) ? 1 : Math.max(a, a * cutout, b, b * cutout);
const calcMin = (angle, a, b) => _angleBetween(angle, startAngle, endAngle, true) ? -1 : Math.min(a, a * cutout, b, b * cutout);
const maxX = calcMax(0, startX, endX);
const maxY = calcMax(HALF_PI, startY, endY);
const minX = calcMin(PI, startX, endX);
const minY = calcMin(PI + HALF_PI, startY, endY);
ratioX = (maxX - minX) / 2;
ratioY = (maxY - minY) / 2;
offsetX = -(maxX + minX) / 2;
offsetY = -(maxY + minY) / 2;
}
return {
ratioX,
ratioY,
offsetX,
offsetY
};
}
var DoughnutController = class extends DatasetController {
constructor(chart, datasetIndex2) {
super(chart, datasetIndex2);
this.enableOptionSharing = true;
this.innerRadius = void 0;
this.outerRadius = void 0;
this.offsetX = void 0;
this.offsetY = void 0;
}
linkScales() {
}
parse(start2, count) {
const data = this.getDataset().data;
const meta = this._cachedMeta;
if (this._parsing === false) {
meta._parsed = data;
} else {
let getter = (i2) => +data[i2];
if (isObject(data[start2])) {
const { key = "value" } = this._parsing;
getter = (i2) => +resolveObjectKey(data[i2], key);
}
let i, ilen;
for (i = start2, ilen = start2 + count; i < ilen; ++i) {
meta._parsed[i] = getter(i);
}
}
}
_getRotation() {
return toRadians(this.options.rotation - 90);
}
_getCircumference() {
return toRadians(this.options.circumference);
}
_getRotationExtents() {
let min2 = TAU;
let max2 = -TAU;
for (let i = 0; i < this.chart.data.datasets.length; ++i) {
if (this.chart.isDatasetVisible(i) && this.chart.getDatasetMeta(i).type === this._type) {
const controller = this.chart.getDatasetMeta(i).controller;
const rotation = controller._getRotation();
const circumference = controller._getCircumference();
min2 = Math.min(min2, rotation);
max2 = Math.max(max2, rotation + circumference);
}
}
return {
rotation: min2,
circumference: max2 - min2
};
}
update(mode) {
const chart = this.chart;
const { chartArea } = chart;
const meta = this._cachedMeta;
const arcs = meta.data;
const spacing = this.getMaxBorderWidth() + this.getMaxOffset(arcs) + this.options.spacing;
const maxSize = Math.max((Math.min(chartArea.width, chartArea.height) - spacing) / 2, 0);
const cutout = Math.min(toPercentage(this.options.cutout, maxSize), 1);
const chartWeight = this._getRingWeight(this.index);
const { circumference, rotation } = this._getRotationExtents();
const { ratioX, ratioY, offsetX, offsetY } = getRatioAndOffset(rotation, circumference, cutout);
const maxWidth = (chartArea.width - spacing) / ratioX;
const maxHeight = (chartArea.height - spacing) / ratioY;
const maxRadius = Math.max(Math.min(maxWidth, maxHeight) / 2, 0);
const outerRadius = toDimension(this.options.radius, maxRadius);
const innerRadius = Math.max(outerRadius * cutout, 0);
const radiusLength = (outerRadius - innerRadius) / this._getVisibleDatasetWeightTotal();
this.offsetX = offsetX * outerRadius;
this.offsetY = offsetY * outerRadius;
meta.total = this.calculateTotal();
this.outerRadius = outerRadius - radiusLength * this._getRingWeightOffset(this.index);
this.innerRadius = Math.max(this.outerRadius - radiusLength * chartWeight, 0);
this.updateElements(arcs, 0, arcs.length, mode);
}
_circumference(i, reset) {
const opts = this.options;
const meta = this._cachedMeta;
const circumference = this._getCircumference();
if (reset && opts.animation.animateRotate || !this.chart.getDataVisibility(i) || meta._parsed[i] === null || meta.data[i].hidden) {
return 0;
}
return this.calculateCircumference(meta._parsed[i] * circumference / TAU);
}
updateElements(arcs, start2, count, mode) {
const reset = mode === "reset";
const chart = this.chart;
const chartArea = chart.chartArea;
const opts = chart.options;
const animationOpts = opts.animation;
const centerX = (chartArea.left + chartArea.right) / 2;
const centerY = (chartArea.top + chartArea.bottom) / 2;
const animateScale = reset && animationOpts.animateScale;
const innerRadius = animateScale ? 0 : this.innerRadius;
const outerRadius = animateScale ? 0 : this.outerRadius;
const { sharedOptions, includeOptions } = this._getSharedOptions(start2, mode);
let startAngle = this._getRotation();
let i;
for (i = 0; i < start2; ++i) {
startAngle += this._circumference(i, reset);
}
for (i = start2; i < start2 + count; ++i) {
const circumference = this._circumference(i, reset);
const arc = arcs[i];
const properties = {
x: centerX + this.offsetX,
y: centerY + this.offsetY,
startAngle,
endAngle: startAngle + circumference,
circumference,
outerRadius,
innerRadius
};
if (includeOptions) {
properties.options = sharedOptions || this.resolveDataElementOptions(i, arc.active ? "active" : mode);
}
startAngle += circumference;
this.updateElement(arc, i, properties, mode);
}
}
calculateTotal() {
const meta = this._cachedMeta;
const metaData = meta.data;
let total = 0;
let i;
for (i = 0; i < metaData.length; i++) {
const value = meta._parsed[i];
if (value !== null && !isNaN(value) && this.chart.getDataVisibility(i) && !metaData[i].hidden) {
total += Math.abs(value);
}
}
return total;
}
calculateCircumference(value) {
const total = this._cachedMeta.total;
if (total > 0 && !isNaN(value)) {
return TAU * (Math.abs(value) / total);
}
return 0;
}
getLabelAndValue(index) {
const meta = this._cachedMeta;
const chart = this.chart;
const labels = chart.data.labels || [];
const value = formatNumber(meta._parsed[index], chart.options.locale);
return {
label: labels[index] || "",
value
};
}
getMaxBorderWidth(arcs) {
let max2 = 0;
const chart = this.chart;
let i, ilen, meta, controller, options;
if (!arcs) {
for (i = 0, ilen = chart.data.datasets.length; i < ilen; ++i) {
if (chart.isDatasetVisible(i)) {
meta = chart.getDatasetMeta(i);
arcs = meta.data;
controller = meta.controller;
break;
}
}
}
if (!arcs) {
return 0;
}
for (i = 0, ilen = arcs.length; i < ilen; ++i) {
options = controller.resolveDataElementOptions(i);
if (options.borderAlign !== "inner") {
max2 = Math.max(max2, options.borderWidth || 0, options.hoverBorderWidth || 0);
}
}
return max2;
}
getMaxOffset(arcs) {
let max2 = 0;
for (let i = 0, ilen = arcs.length; i < ilen; ++i) {
const options = this.resolveDataElementOptions(i);
max2 = Math.max(max2, options.offset || 0, options.hoverOffset || 0);
}
return max2;
}
_getRingWeightOffset(datasetIndex2) {
let ringWeightOffset = 0;
for (let i = 0; i < datasetIndex2; ++i) {
if (this.chart.isDatasetVisible(i)) {
ringWeightOffset += this._getRingWeight(i);
}
}
return ringWeightOffset;
}
_getRingWeight(datasetIndex2) {
return Math.max(valueOrDefault(this.chart.data.datasets[datasetIndex2].weight, 1), 0);
}
_getVisibleDatasetWeightTotal() {
return this._getRingWeightOffset(this.chart.data.datasets.length) || 1;
}
};
__publicField(DoughnutController, "id", "doughnut");
__publicField(DoughnutController, "defaults", {
datasetElementType: false,
dataElementType: "arc",
animation: {
animateRotate: true,
animateScale: false
},
animations: {
numbers: {
type: "number",
properties: [
"circumference",
"endAngle",
"innerRadius",
"outerRadius",
"startAngle",
"x",
"y",
"offset",
"borderWidth",
"spacing"
]
}
},
cutout: "50%",
rotation: 0,
circumference: 360,
radius: "100%",
spacing: 0,
indexAxis: "r"
});
__publicField(DoughnutController, "descriptors", {
_scriptable: (name2) => name2 !== "spacing",
_indexable: (name2) => name2 !== "spacing"
});
__publicField(DoughnutController, "overrides", {
aspectRatio: 1,
plugins: {
legend: {
labels: {
generateLabels(chart) {
const data = chart.data;
if (data.labels.length && data.datasets.length) {
const { labels: { pointStyle, color: color2 } } = chart.legend.options;
return data.labels.map((label, i) => {
const meta = chart.getDatasetMeta(0);
const style = meta.controller.getStyle(i);
return {
text: label,
fillStyle: style.backgroundColor,
strokeStyle: style.borderColor,
fontColor: color2,
lineWidth: style.borderWidth,
pointStyle,
hidden: !chart.getDataVisibility(i),
index: i
};
});
}
return [];
}
},
onClick(e, legendItem, legend) {
legend.chart.toggleDataVisibility(legendItem.index);
legend.chart.update();
}
}
}
});
var PolarAreaController = class extends DatasetController {
constructor(chart, datasetIndex2) {
super(chart, datasetIndex2);
this.innerRadius = void 0;
this.outerRadius = void 0;
}
getLabelAndValue(index) {
const meta = this._cachedMeta;
const chart = this.chart;
const labels = chart.data.labels || [];
const value = formatNumber(meta._parsed[index].r, chart.options.locale);
return {
label: labels[index] || "",
value
};
}
parseObjectData(meta, data, start2, count) {
return _parseObjectDataRadialScale.bind(this)(meta, data, start2, count);
}
update(mode) {
const arcs = this._cachedMeta.data;
this._updateRadius();
this.updateElements(arcs, 0, arcs.length, mode);
}
getMinMax() {
const meta = this._cachedMeta;
const range = {
min: Number.POSITIVE_INFINITY,
max: Number.NEGATIVE_INFINITY
};
meta.data.forEach((element2, index) => {
const parsed = this.getParsed(index).r;
if (!isNaN(parsed) && this.chart.getDataVisibility(index)) {
if (parsed < range.min) {
range.min = parsed;
}
if (parsed > range.max) {
range.max = parsed;
}
}
});
return range;
}
_updateRadius() {
const chart = this.chart;
const chartArea = chart.chartArea;
const opts = chart.options;
const minSize = Math.min(chartArea.right - chartArea.left, chartArea.bottom - chartArea.top);
const outerRadius = Math.max(minSize / 2, 0);
const innerRadius = Math.max(opts.cutoutPercentage ? outerRadius / 100 * opts.cutoutPercentage : 1, 0);
const radiusLength = (outerRadius - innerRadius) / chart.getVisibleDatasetCount();
this.outerRadius = outerRadius - radiusLength * this.index;
this.innerRadius = this.outerRadius - radiusLength;
}
updateElements(arcs, start2, count, mode) {
const reset = mode === "reset";
const chart = this.chart;
const opts = chart.options;
const animationOpts = opts.animation;
const scale = this._cachedMeta.rScale;
const centerX = scale.xCenter;
const centerY = scale.yCenter;
const datasetStartAngle = scale.getIndexAngle(0) - 0.5 * PI;
let angle = datasetStartAngle;
let i;
const defaultAngle = 360 / this.countVisibleElements();
for (i = 0; i < start2; ++i) {
angle += this._computeAngle(i, mode, defaultAngle);
}
for (i = start2; i < start2 + count; i++) {
const arc = arcs[i];
let startAngle = angle;
let endAngle = angle + this._computeAngle(i, mode, defaultAngle);
let outerRadius = chart.getDataVisibility(i) ? scale.getDistanceFromCenterForValue(this.getParsed(i).r) : 0;
angle = endAngle;
if (reset) {
if (animationOpts.animateScale) {
outerRadius = 0;
}
if (animationOpts.animateRotate) {
startAngle = endAngle = datasetStartAngle;
}
}
const properties = {
x: centerX,
y: centerY,
innerRadius: 0,
outerRadius,
startAngle,
endAngle,
options: this.resolveDataElementOptions(i, arc.active ? "active" : mode)
};
this.updateElement(arc, i, properties, mode);
}
}
countVisibleElements() {
const meta = this._cachedMeta;
let count = 0;
meta.data.forEach((element2, index) => {
if (!isNaN(this.getParsed(index).r) && this.chart.getDataVisibility(index)) {
count++;
}
});
return count;
}
_computeAngle(index, mode, defaultAngle) {
return this.chart.getDataVisibility(index) ? toRadians(this.resolveDataElementOptions(index, mode).angle || defaultAngle) : 0;
}
};
__publicField(PolarAreaController, "id", "polarArea");
__publicField(PolarAreaController, "defaults", {
dataElementType: "arc",
animation: {
animateRotate: true,
animateScale: true
},
animations: {
numbers: {
type: "number",
properties: [
"x",
"y",
"startAngle",
"endAngle",
"innerRadius",
"outerRadius"
]
}
},
indexAxis: "r",
startAngle: 0
});
__publicField(PolarAreaController, "overrides", {
aspectRatio: 1,
plugins: {
legend: {
labels: {
generateLabels(chart) {
const data = chart.data;
if (data.labels.length && data.datasets.length) {
const { labels: { pointStyle, color: color2 } } = chart.legend.options;
return data.labels.map((label, i) => {
const meta = chart.getDatasetMeta(0);
const style = meta.controller.getStyle(i);
return {
text: label,
fillStyle: style.backgroundColor,
strokeStyle: style.borderColor,
fontColor: color2,
lineWidth: style.borderWidth,
pointStyle,
hidden: !chart.getDataVisibility(i),
index: i
};
});
}
return [];
}
},
onClick(e, legendItem, legend) {
legend.chart.toggleDataVisibility(legendItem.index);
legend.chart.update();
}
}
},
scales: {
r: {
type: "radialLinear",
angleLines: {
display: false
},
beginAtZero: true,
grid: {
circular: true
},
pointLabels: {
display: false
},
startAngle: 0
}
}
});
function abstract() {
throw new Error("This method is not implemented: Check that a complete date adapter is provided.");
}
var DateAdapterBase = class {
/**
* Override default date adapter methods.
* Accepts type parameter to define options type.
* @example
* Chart._adapters._date.override<{myAdapterOption: string}>({
* init() {
* console.log(this.options.myAdapterOption);
* }
* })
*/
static override(members) {
Object.assign(DateAdapterBase.prototype, members);
}
constructor(options) {
this.options = options || {};
}
// eslint-disable-next-line @typescript-eslint/no-empty-function
init() {
}
formats() {
return abstract();
}
parse() {
return abstract();
}
format() {
return abstract();
}
add() {
return abstract();
}
diff() {
return abstract();
}
startOf() {
return abstract();
}
endOf() {
return abstract();
}
};
var adapters = {
_date: DateAdapterBase
};
function binarySearch(metaset, axis, value, intersect) {
const { controller, data, _sorted } = metaset;
const iScale = controller._cachedMeta.iScale;
if (iScale && axis === iScale.axis && axis !== "r" && _sorted && data.length) {
const lookupMethod = iScale._reversePixels ? _rlookupByKey : _lookupByKey;
if (!intersect) {
return lookupMethod(data, axis, value);
} else if (controller._sharedOptions) {
const el = data[0];
const range = typeof el.getRange === "function" && el.getRange(axis);
if (range) {
const start2 = lookupMethod(data, axis, value - range);
const end2 = lookupMethod(data, axis, value + range);
return {
lo: start2.lo,
hi: end2.hi
};
}
}
}
return {
lo: 0,
hi: data.length - 1
};
}
function evaluateInteractionItems(chart, axis, position, handler, intersect) {
const metasets = chart.getSortedVisibleDatasetMetas();
const value = position[axis];
for (let i = 0, ilen = metasets.length; i < ilen; ++i) {
const { index, data } = metasets[i];
const { lo, hi } = binarySearch(metasets[i], axis, value, intersect);
for (let j = lo; j <= hi; ++j) {
const element2 = data[j];
if (!element2.skip) {
handler(element2, index, j);
}
}
}
}
function getDistanceMetricForAxis(axis) {
const useX = axis.indexOf("x") !== -1;
const useY = axis.indexOf("y") !== -1;
return function(pt1, pt2) {
const deltaX = useX ? Math.abs(pt1.x - pt2.x) : 0;
const deltaY = useY ? Math.abs(pt1.y - pt2.y) : 0;
return Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2));
};
}
function getIntersectItems(chart, position, axis, useFinalPosition, includeInvisible) {
const items = [];
if (!includeInvisible && !chart.isPointInArea(position)) {
return items;
}
const evaluationFunc = function(element2, datasetIndex2, index) {
if (!includeInvisible && !_isPointInArea(element2, chart.chartArea, 0)) {
return;
}
if (element2.inRange(position.x, position.y, useFinalPosition)) {
items.push({
element: element2,
datasetIndex: datasetIndex2,
index
});
}
};
evaluateInteractionItems(chart, axis, position, evaluationFunc, true);
return items;
}
function getNearestRadialItems(chart, position, axis, useFinalPosition) {
let items = [];
function evaluationFunc(element2, datasetIndex2, index) {
const { startAngle, endAngle } = element2.getProps([
"startAngle",
"endAngle"
], useFinalPosition);
const { angle } = getAngleFromPoint(element2, {
x: position.x,
y: position.y
});
if (_angleBetween(angle, startAngle, endAngle)) {
items.push({
element: element2,
datasetIndex: datasetIndex2,
index
});
}
}
evaluateInteractionItems(chart, axis, position, evaluationFunc);
return items;
}
function getNearestCartesianItems(chart, position, axis, intersect, useFinalPosition, includeInvisible) {
let items = [];
const distanceMetric = getDistanceMetricForAxis(axis);
let minDistance = Number.POSITIVE_INFINITY;
function evaluationFunc(element2, datasetIndex2, index) {
const inRange2 = element2.inRange(position.x, position.y, useFinalPosition);
if (intersect && !inRange2) {
return;
}
const center = element2.getCenterPoint(useFinalPosition);
const pointInArea = !!includeInvisible || chart.isPointInArea(center);
if (!pointInArea && !inRange2) {
return;
}
const distance = distanceMetric(position, center);
if (distance < minDistance) {
items = [
{
element: element2,
datasetIndex: datasetIndex2,
index
}
];
minDistance = distance;
} else if (distance === minDistance) {
items.push({
element: element2,
datasetIndex: datasetIndex2,
index
});
}
}
evaluateInteractionItems(chart, axis, position, evaluationFunc);
return items;
}
function getNearestItems(chart, position, axis, intersect, useFinalPosition, includeInvisible) {
if (!includeInvisible && !chart.isPointInArea(position)) {
return [];
}
return axis === "r" && !intersect ? getNearestRadialItems(chart, position, axis, useFinalPosition) : getNearestCartesianItems(chart, position, axis, intersect, useFinalPosition, includeInvisible);
}
function getAxisItems(chart, position, axis, intersect, useFinalPosition) {
const items = [];
const rangeMethod = axis === "x" ? "inXRange" : "inYRange";
let intersectsItem = false;
evaluateInteractionItems(chart, axis, position, (element2, datasetIndex2, index) => {
if (element2[rangeMethod](position[axis], useFinalPosition)) {
items.push({
element: element2,
datasetIndex: datasetIndex2,
index
});
intersectsItem = intersectsItem || element2.inRange(position.x, position.y, useFinalPosition);
}
});
if (intersect && !intersectsItem) {
return [];
}
return items;
}
var Interaction = {
evaluateInteractionItems,
modes: {
index(chart, e, options, useFinalPosition) {
const position = getRelativePosition(e, chart);
const axis = options.axis || "x";
const includeInvisible = options.includeInvisible || false;
const items = options.intersect ? getIntersectItems(chart, position, axis, useFinalPosition, includeInvisible) : getNearestItems(chart, position, axis, false, useFinalPosition, includeInvisible);
const elements = [];
if (!items.length) {
return [];
}
chart.getSortedVisibleDatasetMetas().forEach((meta) => {
const index = items[0].index;
const element2 = meta.data[index];
if (element2 && !element2.skip) {
elements.push({
element: element2,
datasetIndex: meta.index,
index
});
}
});
return elements;
},
dataset(chart, e, options, useFinalPosition) {
const position = getRelativePosition(e, chart);
const axis = options.axis || "xy";
const includeInvisible = options.includeInvisible || false;
let items = options.intersect ? getIntersectItems(chart, position, axis, useFinalPosition, includeInvisible) : getNearestItems(chart, position, axis, false, useFinalPosition, includeInvisible);
if (items.length > 0) {
const datasetIndex2 = items[0].datasetIndex;
const data = chart.getDatasetMeta(datasetIndex2).data;
items = [];
for (let i = 0; i < data.length; ++i) {
items.push({
element: data[i],
datasetIndex: datasetIndex2,
index: i
});
}
}
return items;
},
point(chart, e, options, useFinalPosition) {
const position = getRelativePosition(e, chart);
const axis = options.axis || "xy";
const includeInvisible = options.includeInvisible || false;
return getIntersectItems(chart, position, axis, useFinalPosition, includeInvisible);
},
nearest(chart, e, options, useFinalPosition) {
const position = getRelativePosition(e, chart);
const axis = options.axis || "xy";
const includeInvisible = options.includeInvisible || false;
return getNearestItems(chart, position, axis, options.intersect, useFinalPosition, includeInvisible);
},
x(chart, e, options, useFinalPosition) {
const position = getRelativePosition(e, chart);
return getAxisItems(chart, position, "x", options.intersect, useFinalPosition);
},
y(chart, e, options, useFinalPosition) {
const position = getRelativePosition(e, chart);
return getAxisItems(chart, position, "y", options.intersect, useFinalPosition);
}
}
};
var STATIC_POSITIONS = [
"left",
"top",
"right",
"bottom"
];
function filterByPosition(array, position) {
return array.filter((v) => v.pos === position);
}
function filterDynamicPositionByAxis(array, axis) {
return array.filter((v) => STATIC_POSITIONS.indexOf(v.pos) === -1 && v.box.axis === axis);
}
function sortByWeight(array, reverse) {
return array.sort((a, b) => {
const v0 = reverse ? b : a;
const v1 = reverse ? a : b;
return v0.weight === v1.weight ? v0.index - v1.index : v0.weight - v1.weight;
});
}
function wrapBoxes(boxes) {
const layoutBoxes = [];
let i, ilen, box, pos, stack, stackWeight;
for (i = 0, ilen = (boxes || []).length; i < ilen; ++i) {
box = boxes[i];
({ position: pos, options: { stack, stackWeight = 1 } } = box);
layoutBoxes.push({
index: i,
box,
pos,
horizontal: box.isHorizontal(),
weight: box.weight,
stack: stack && pos + stack,
stackWeight
});
}
return layoutBoxes;
}
function buildStacks(layouts2) {
const stacks = {};
for (const wrap of layouts2) {
const { stack, pos, stackWeight } = wrap;
if (!stack || !STATIC_POSITIONS.includes(pos)) {
continue;
}
const _stack = stacks[stack] || (stacks[stack] = {
count: 0,
placed: 0,
weight: 0,
size: 0
});
_stack.count++;
_stack.weight += stackWeight;
}
return stacks;
}
function setLayoutDims(layouts2, params) {
const stacks = buildStacks(layouts2);
const { vBoxMaxWidth, hBoxMaxHeight } = params;
let i, ilen, layout;
for (i = 0, ilen = layouts2.length; i < ilen; ++i) {
layout = layouts2[i];
const { fullSize } = layout.box;
const stack = stacks[layout.stack];
const factor = stack && layout.stackWeight / stack.weight;
if (layout.horizontal) {
layout.width = factor ? factor * vBoxMaxWidth : fullSize && params.availableWidth;
layout.height = hBoxMaxHeight;
} else {
layout.width = vBoxMaxWidth;
layout.height = factor ? factor * hBoxMaxHeight : fullSize && params.availableHeight;
}
}
return stacks;
}
function buildLayoutBoxes(boxes) {
const layoutBoxes = wrapBoxes(boxes);
const fullSize = sortByWeight(layoutBoxes.filter((wrap) => wrap.box.fullSize), true);
const left2 = sortByWeight(filterByPosition(layoutBoxes, "left"), true);
const right2 = sortByWeight(filterByPosition(layoutBoxes, "right"));
const top2 = sortByWeight(filterByPosition(layoutBoxes, "top"), true);
const bottom2 = sortByWeight(filterByPosition(layoutBoxes, "bottom"));
const centerHorizontal = filterDynamicPositionByAxis(layoutBoxes, "x");
const centerVertical = filterDynamicPositionByAxis(layoutBoxes, "y");
return {
fullSize,
leftAndTop: left2.concat(top2),
rightAndBottom: right2.concat(centerVertical).concat(bottom2).concat(centerHorizontal),
chartArea: filterByPosition(layoutBoxes, "chartArea"),
vertical: left2.concat(right2).concat(centerVertical),
horizontal: top2.concat(bottom2).concat(centerHorizontal)
};
}
function getCombinedMax(maxPadding, chartArea, a, b) {
return Math.max(maxPadding[a], chartArea[a]) + Math.max(maxPadding[b], chartArea[b]);
}
function updateMaxPadding(maxPadding, boxPadding) {
maxPadding.top = Math.max(maxPadding.top, boxPadding.top);
maxPadding.left = Math.max(maxPadding.left, boxPadding.left);
maxPadding.bottom = Math.max(maxPadding.bottom, boxPadding.bottom);
maxPadding.right = Math.max(maxPadding.right, boxPadding.right);
}
function updateDims(chartArea, params, layout, stacks) {
const { pos, box } = layout;
const maxPadding = chartArea.maxPadding;
if (!isObject(pos)) {
if (layout.size) {
chartArea[pos] -= layout.size;
}
const stack = stacks[layout.stack] || {
size: 0,
count: 1
};
stack.size = Math.max(stack.size, layout.horizontal ? box.height : box.width);
layout.size = stack.size / stack.count;
chartArea[pos] += layout.size;
}
if (box.getPadding) {
updateMaxPadding(maxPadding, box.getPadding());
}
const newWidth = Math.max(0, params.outerWidth - getCombinedMax(maxPadding, chartArea, "left", "right"));
const newHeight = Math.max(0, params.outerHeight - getCombinedMax(maxPadding, chartArea, "top", "bottom"));
const widthChanged = newWidth !== chartArea.w;
const heightChanged = newHeight !== chartArea.h;
chartArea.w = newWidth;
chartArea.h = newHeight;
return layout.horizontal ? {
same: widthChanged,
other: heightChanged
} : {
same: heightChanged,
other: widthChanged
};
}
function handleMaxPadding(chartArea) {
const maxPadding = chartArea.maxPadding;
function updatePos(pos) {
const change = Math.max(maxPadding[pos] - chartArea[pos], 0);
chartArea[pos] += change;
return change;
}
chartArea.y += updatePos("top");
chartArea.x += updatePos("left");
updatePos("right");
updatePos("bottom");
}
function getMargins(horizontal, chartArea) {
const maxPadding = chartArea.maxPadding;
function marginForPositions(positions2) {
const margin = {
left: 0,
top: 0,
right: 0,
bottom: 0
};
positions2.forEach((pos) => {
margin[pos] = Math.max(chartArea[pos], maxPadding[pos]);
});
return margin;
}
return horizontal ? marginForPositions([
"left",
"right"
]) : marginForPositions([
"top",
"bottom"
]);
}
function fitBoxes(boxes, chartArea, params, stacks) {
const refitBoxes = [];
let i, ilen, layout, box, refit, changed;
for (i = 0, ilen = boxes.length, refit = 0; i < ilen; ++i) {
layout = boxes[i];
box = layout.box;
box.update(layout.width || chartArea.w, layout.height || chartArea.h, getMargins(layout.horizontal, chartArea));
const { same, other } = updateDims(chartArea, params, layout, stacks);
refit |= same && refitBoxes.length;
changed = changed || other;
if (!box.fullSize) {
refitBoxes.push(layout);
}
}
return refit && fitBoxes(refitBoxes, chartArea, params, stacks) || changed;
}
function setBoxDims(box, left2, top2, width, height) {
box.top = top2;
box.left = left2;
box.right = left2 + width;
box.bottom = top2 + height;
box.width = width;
box.height = height;
}
function placeBoxes(boxes, chartArea, params, stacks) {
const userPadding = params.padding;
let { x, y } = chartArea;
for (const layout of boxes) {
const box = layout.box;
const stack = stacks[layout.stack] || {
count: 1,
placed: 0,
weight: 1
};
const weight = layout.stackWeight / stack.weight || 1;
if (layout.horizontal) {
const width = chartArea.w * weight;
const height = stack.size || box.height;
if (defined(stack.start)) {
y = stack.start;
}
if (box.fullSize) {
setBoxDims(box, userPadding.left, y, params.outerWidth - userPadding.right - userPadding.left, height);
} else {
setBoxDims(box, chartArea.left + stack.placed, y, width, height);
}
stack.start = y;
stack.placed += width;
y = box.bottom;
} else {
const height1 = chartArea.h * weight;
const width1 = stack.size || box.width;
if (defined(stack.start)) {
x = stack.start;
}
if (box.fullSize) {
setBoxDims(box, x, userPadding.top, width1, params.outerHeight - userPadding.bottom - userPadding.top);
} else {
setBoxDims(box, x, chartArea.top + stack.placed, width1, height1);
}
stack.start = x;
stack.placed += height1;
x = box.right;
}
}
chartArea.x = x;
chartArea.y = y;
}
var layouts = {
addBox(chart, item) {
if (!chart.boxes) {
chart.boxes = [];
}
item.fullSize = item.fullSize || false;
item.position = item.position || "top";
item.weight = item.weight || 0;
item._layers = item._layers || function() {
return [
{
z: 0,
draw(chartArea) {
item.draw(chartArea);
}
}
];
};
chart.boxes.push(item);
},
removeBox(chart, layoutItem) {
const index = chart.boxes ? chart.boxes.indexOf(layoutItem) : -1;
if (index !== -1) {
chart.boxes.splice(index, 1);
}
},
configure(chart, item, options) {
item.fullSize = options.fullSize;
item.position = options.position;
item.weight = options.weight;
},
update(chart, width, height, minPadding) {
if (!chart) {
return;
}
const padding = toPadding(chart.options.layout.padding);
const availableWidth = Math.max(width - padding.width, 0);
const availableHeight = Math.max(height - padding.height, 0);
const boxes = buildLayoutBoxes(chart.boxes);
const verticalBoxes = boxes.vertical;
const horizontalBoxes = boxes.horizontal;
each2(chart.boxes, (box) => {
if (typeof box.beforeLayout === "function") {
box.beforeLayout();
}
});
const visibleVerticalBoxCount = verticalBoxes.reduce((total, wrap) => wrap.box.options && wrap.box.options.display === false ? total : total + 1, 0) || 1;
const params = Object.freeze({
outerWidth: width,
outerHeight: height,
padding,
availableWidth,
availableHeight,
vBoxMaxWidth: availableWidth / 2 / visibleVerticalBoxCount,
hBoxMaxHeight: availableHeight / 2
});
const maxPadding = Object.assign({}, padding);
updateMaxPadding(maxPadding, toPadding(minPadding));
const chartArea = Object.assign({
maxPadding,
w: availableWidth,
h: availableHeight,
x: padding.left,
y: padding.top
}, padding);
const stacks = setLayoutDims(verticalBoxes.concat(horizontalBoxes), params);
fitBoxes(boxes.fullSize, chartArea, params, stacks);
fitBoxes(verticalBoxes, chartArea, params, stacks);
if (fitBoxes(horizontalBoxes, chartArea, params, stacks)) {
fitBoxes(verticalBoxes, chartArea, params, stacks);
}
handleMaxPadding(chartArea);
placeBoxes(boxes.leftAndTop, chartArea, params, stacks);
chartArea.x += chartArea.w;
chartArea.y += chartArea.h;
placeBoxes(boxes.rightAndBottom, chartArea, params, stacks);
chart.chartArea = {
left: chartArea.left,
top: chartArea.top,
right: chartArea.left + chartArea.w,
bottom: chartArea.top + chartArea.h,
height: chartArea.h,
width: chartArea.w
};
each2(boxes.chartArea, (layout) => {
const box = layout.box;
Object.assign(box, chart.chartArea);
box.update(chartArea.w, chartArea.h, {
left: 0,
top: 0,
right: 0,
bottom: 0
});
});
}
};
var BasePlatform = class {
acquireContext(canvas, aspectRatio) {
}
releaseContext(context) {
return false;
}
addEventListener(chart, type, listener) {
}
removeEventListener(chart, type, listener) {
}
getDevicePixelRatio() {
return 1;
}
getMaximumSize(element2, width, height, aspectRatio) {
width = Math.max(0, width || element2.width);
height = height || element2.height;
return {
width,
height: Math.max(0, aspectRatio ? Math.floor(width / aspectRatio) : height)
};
}
isAttached(canvas) {
return true;
}
updateConfig(config) {
}
};
var BasicPlatform = class extends BasePlatform {
acquireContext(item) {
return item && item.getContext && item.getContext("2d") || null;
}
updateConfig(config) {
config.options.animation = false;
}
};
var EXPANDO_KEY = "$chartjs";
var EVENT_TYPES = {
touchstart: "mousedown",
touchmove: "mousemove",
touchend: "mouseup",
pointerenter: "mouseenter",
pointerdown: "mousedown",
pointermove: "mousemove",
pointerup: "mouseup",
pointerleave: "mouseout",
pointerout: "mouseout"
};
var isNullOrEmpty = (value) => value === null || value === "";
function initCanvas(canvas, aspectRatio) {
const style = canvas.style;
const renderHeight = canvas.getAttribute("height");
const renderWidth = canvas.getAttribute("width");
canvas[EXPANDO_KEY] = {
initial: {
height: renderHeight,
width: renderWidth,
style: {
display: style.display,
height: style.height,
width: style.width
}
}
};
style.display = style.display || "block";
style.boxSizing = style.boxSizing || "border-box";
if (isNullOrEmpty(renderWidth)) {
const displayWidth = readUsedSize(canvas, "width");
if (displayWidth !== void 0) {
canvas.width = displayWidth;
}
}
if (isNullOrEmpty(renderHeight)) {
if (canvas.style.height === "") {
canvas.height = canvas.width / (aspectRatio || 2);
} else {
const displayHeight = readUsedSize(canvas, "height");
if (displayHeight !== void 0) {
canvas.height = displayHeight;
}
}
}
return canvas;
}
var eventListenerOptions = supportsEventListenerOptions ? {
passive: true
} : false;
function addListener(node, type, listener) {
node.addEventListener(type, listener, eventListenerOptions);
}
function removeListener(chart, type, listener) {
chart.canvas.removeEventListener(type, listener, eventListenerOptions);
}
function fromNativeEvent(event, chart) {
const type = EVENT_TYPES[event.type] || event.type;
const { x, y } = getRelativePosition(event, chart);
return {
type,
chart,
native: event,
x: x !== void 0 ? x : null,
y: y !== void 0 ? y : null
};
}
function nodeListContains(nodeList, canvas) {
for (const node of nodeList) {
if (node === canvas || node.contains(canvas)) {
return true;
}
}
}
function createAttachObserver(chart, type, listener) {
const canvas = chart.canvas;
const observer = new MutationObserver((entries) => {
let trigger = false;
for (const entry of entries) {
trigger = trigger || nodeListContains(entry.addedNodes, canvas);
trigger = trigger && !nodeListContains(entry.removedNodes, canvas);
}
if (trigger) {
listener();
}
});
observer.observe(document, {
childList: true,
subtree: true
});
return observer;
}
function createDetachObserver(chart, type, listener) {
const canvas = chart.canvas;
const observer = new MutationObserver((entries) => {
let trigger = false;
for (const entry of entries) {
trigger = trigger || nodeListContains(entry.removedNodes, canvas);
trigger = trigger && !nodeListContains(entry.addedNodes, canvas);
}
if (trigger) {
listener();
}
});
observer.observe(document, {
childList: true,
subtree: true
});
return observer;
}
var drpListeningCharts = /* @__PURE__ */ new Map();
var oldDevicePixelRatio = 0;
function onWindowResize() {
const dpr = window.devicePixelRatio;
if (dpr === oldDevicePixelRatio) {
return;
}
oldDevicePixelRatio = dpr;
drpListeningCharts.forEach((resize, chart) => {
if (chart.currentDevicePixelRatio !== dpr) {
resize();
}
});
}
function listenDevicePixelRatioChanges(chart, resize) {
if (!drpListeningCharts.size) {
window.addEventListener("resize", onWindowResize);
}
drpListeningCharts.set(chart, resize);
}
function unlistenDevicePixelRatioChanges(chart) {
drpListeningCharts.delete(chart);
if (!drpListeningCharts.size) {
window.removeEventListener("resize", onWindowResize);
}
}
function createResizeObserver(chart, type, listener) {
const canvas = chart.canvas;
const container = canvas && _getParentNode(canvas);
if (!container) {
return;
}
const resize = throttled((width, height) => {
const w = container.clientWidth;
listener(width, height);
if (w < container.clientWidth) {
listener();
}
}, window);
const observer = new ResizeObserver((entries) => {
const entry = entries[0];
const width = entry.contentRect.width;
const height = entry.contentRect.height;
if (width === 0 && height === 0) {
return;
}
resize(width, height);
});
observer.observe(container);
listenDevicePixelRatioChanges(chart, resize);
return observer;
}
function releaseObserver(chart, type, observer) {
if (observer) {
observer.disconnect();
}
if (type === "resize") {
unlistenDevicePixelRatioChanges(chart);
}
}
function createProxyAndListen(chart, type, listener) {
const canvas = chart.canvas;
const proxy = throttled((event) => {
if (chart.ctx !== null) {
listener(fromNativeEvent(event, chart));
}
}, chart);
addListener(canvas, type, proxy);
return proxy;
}
var DomPlatform = class extends BasePlatform {
acquireContext(canvas, aspectRatio) {
const context = canvas && canvas.getContext && canvas.getContext("2d");
if (context && context.canvas === canvas) {
initCanvas(canvas, aspectRatio);
return context;
}
return null;
}
releaseContext(context) {
const canvas = context.canvas;
if (!canvas[EXPANDO_KEY]) {
return false;
}
const initial = canvas[EXPANDO_KEY].initial;
[
"height",
"width"
].forEach((prop) => {
const value = initial[prop];
if (isNullOrUndef(value)) {
canvas.removeAttribute(prop);
} else {
canvas.setAttribute(prop, value);
}
});
const style = initial.style || {};
Object.keys(style).forEach((key) => {
canvas.style[key] = style[key];
});
canvas.width = canvas.width;
delete canvas[EXPANDO_KEY];
return true;
}
addEventListener(chart, type, listener) {
this.removeEventListener(chart, type);
const proxies = chart.$proxies || (chart.$proxies = {});
const handlers = {
attach: createAttachObserver,
detach: createDetachObserver,
resize: createResizeObserver
};
const handler = handlers[type] || createProxyAndListen;
proxies[type] = handler(chart, type, listener);
}
removeEventListener(chart, type) {
const proxies = chart.$proxies || (chart.$proxies = {});
const proxy = proxies[type];
if (!proxy) {
return;
}
const handlers = {
attach: releaseObserver,
detach: releaseObserver,
resize: releaseObserver
};
const handler = handlers[type] || removeListener;
handler(chart, type, proxy);
proxies[type] = void 0;
}
getDevicePixelRatio() {
return window.devicePixelRatio;
}
getMaximumSize(canvas, width, height, aspectRatio) {
return getMaximumSize(canvas, width, height, aspectRatio);
}
isAttached(canvas) {
const container = _getParentNode(canvas);
return !!(container && container.isConnected);
}
};
function _detectPlatform(canvas) {
if (!_isDomSupported() || typeof OffscreenCanvas !== "undefined" && canvas instanceof OffscreenCanvas) {
return BasicPlatform;
}
return DomPlatform;
}
var Element2 = class {
constructor() {
__publicField(this, "active", false);
}
tooltipPosition(useFinalPosition) {
const { x, y } = this.getProps([
"x",
"y"
], useFinalPosition);
return {
x,
y
};
}
hasValue() {
return isNumber(this.x) && isNumber(this.y);
}
getProps(props, final) {
const anims = this.$animations;
if (!final || !anims) {
return this;
}
const ret = {};
props.forEach((prop) => {
ret[prop] = anims[prop] && anims[prop].active() ? anims[prop]._to : this[prop];
});
return ret;
}
};
__publicField(Element2, "defaults", {});
__publicField(Element2, "defaultRoutes");
function autoSkip(scale, ticks) {
const tickOpts = scale.options.ticks;
const determinedMaxTicks = determineMaxTicks(scale);
const ticksLimit = Math.min(tickOpts.maxTicksLimit || determinedMaxTicks, determinedMaxTicks);
const majorIndices = tickOpts.major.enabled ? getMajorIndices(ticks) : [];
const numMajorIndices = majorIndices.length;
const first = majorIndices[0];
const last = majorIndices[numMajorIndices - 1];
const newTicks = [];
if (numMajorIndices > ticksLimit) {
skipMajors(ticks, newTicks, majorIndices, numMajorIndices / ticksLimit);
return newTicks;
}
const spacing = calculateSpacing(majorIndices, ticks, ticksLimit);
if (numMajorIndices > 0) {
let i, ilen;
const avgMajorSpacing = numMajorIndices > 1 ? Math.round((last - first) / (numMajorIndices - 1)) : null;
skip(ticks, newTicks, spacing, isNullOrUndef(avgMajorSpacing) ? 0 : first - avgMajorSpacing, first);
for (i = 0, ilen = numMajorIndices - 1; i < ilen; i++) {
skip(ticks, newTicks, spacing, majorIndices[i], majorIndices[i + 1]);
}
skip(ticks, newTicks, spacing, last, isNullOrUndef(avgMajorSpacing) ? ticks.length : last + avgMajorSpacing);
return newTicks;
}
skip(ticks, newTicks, spacing);
return newTicks;
}
function determineMaxTicks(scale) {
const offset2 = scale.options.offset;
const tickLength = scale._tickSize();
const maxScale = scale._length / tickLength + (offset2 ? 0 : 1);
const maxChart = scale._maxLength / tickLength;
return Math.floor(Math.min(maxScale, maxChart));
}
function calculateSpacing(majorIndices, ticks, ticksLimit) {
const evenMajorSpacing = getEvenSpacing(majorIndices);
const spacing = ticks.length / ticksLimit;
if (!evenMajorSpacing) {
return Math.max(spacing, 1);
}
const factors = _factorize(evenMajorSpacing);
for (let i = 0, ilen = factors.length - 1; i < ilen; i++) {
const factor = factors[i];
if (factor > spacing) {
return factor;
}
}
return Math.max(spacing, 1);
}
function getMajorIndices(ticks) {
const result = [];
let i, ilen;
for (i = 0, ilen = ticks.length; i < ilen; i++) {
if (ticks[i].major) {
result.push(i);
}
}
return result;
}
function skipMajors(ticks, newTicks, majorIndices, spacing) {
let count = 0;
let next = majorIndices[0];
let i;
spacing = Math.ceil(spacing);
for (i = 0; i < ticks.length; i++) {
if (i === next) {
newTicks.push(ticks[i]);
count++;
next = majorIndices[count * spacing];
}
}
}
function skip(ticks, newTicks, spacing, majorStart, majorEnd) {
const start2 = valueOrDefault(majorStart, 0);
const end2 = Math.min(valueOrDefault(majorEnd, ticks.length), ticks.length);
let count = 0;
let length, i, next;
spacing = Math.ceil(spacing);
if (majorEnd) {
length = majorEnd - majorStart;
spacing = length / Math.floor(length / spacing);
}
next = start2;
while (next < 0) {
count++;
next = Math.round(start2 + count * spacing);
}
for (i = Math.max(start2, 0); i < end2; i++) {
if (i === next) {
newTicks.push(ticks[i]);
count++;
next = Math.round(start2 + count * spacing);
}
}
}
function getEvenSpacing(arr) {
const len = arr.length;
let i, diff;
if (len < 2) {
return false;
}
for (diff = arr[0], i = 1; i < len; ++i) {
if (arr[i] - arr[i - 1] !== diff) {
return false;
}
}
return diff;
}
var reverseAlign = (align) => align === "left" ? "right" : align === "right" ? "left" : align;
var offsetFromEdge = (scale, edge, offset2) => edge === "top" || edge === "left" ? scale[edge] + offset2 : scale[edge] - offset2;
var getTicksLimit = (ticksLength, maxTicksLimit) => Math.min(maxTicksLimit || ticksLength, ticksLength);
function sample(arr, numItems) {
const result = [];
const increment = arr.length / numItems;
const len = arr.length;
let i = 0;
for (; i < len; i += increment) {
result.push(arr[Math.floor(i)]);
}
return result;
}
function getPixelForGridLine(scale, index, offsetGridLines) {
const length = scale.ticks.length;
const validIndex2 = Math.min(index, length - 1);
const start2 = scale._startPixel;
const end2 = scale._endPixel;
const epsilon = 1e-6;
let lineValue = scale.getPixelForTick(validIndex2);
let offset2;
if (offsetGridLines) {
if (length === 1) {
offset2 = Math.max(lineValue - start2, end2 - lineValue);
} else if (index === 0) {
offset2 = (scale.getPixelForTick(1) - lineValue) / 2;
} else {
offset2 = (lineValue - scale.getPixelForTick(validIndex2 - 1)) / 2;
}
lineValue += validIndex2 < index ? offset2 : -offset2;
if (lineValue < start2 - epsilon || lineValue > end2 + epsilon) {
return;
}
}
return lineValue;
}
function garbageCollect(caches, length) {
each2(caches, (cache) => {
const gc = cache.gc;
const gcLen = gc.length / 2;
let i;
if (gcLen > length) {
for (i = 0; i < gcLen; ++i) {
delete cache.data[gc[i]];
}
gc.splice(0, gcLen);
}
});
}
function getTickMarkLength(options) {
return options.drawTicks ? options.tickLength : 0;
}
function getTitleHeight(options, fallback) {
if (!options.display) {
return 0;
}
const font = toFont(options.font, fallback);
const padding = toPadding(options.padding);
const lines = isArray(options.text) ? options.text.length : 1;
return lines * font.lineHeight + padding.height;
}
function createScaleContext(parent, scale) {
return createContext(parent, {
scale,
type: "scale"
});
}
function createTickContext(parent, index, tick2) {
return createContext(parent, {
tick: tick2,
index,
type: "tick"
});
}
function titleAlign(align, position, reverse) {
let ret = _toLeftRightCenter(align);
if (reverse && position !== "right" || !reverse && position === "right") {
ret = reverseAlign(ret);
}
return ret;
}
function titleArgs(scale, offset2, position, align) {
const { top: top2, left: left2, bottom: bottom2, right: right2, chart } = scale;
const { chartArea, scales } = chart;
let rotation = 0;
let maxWidth, titleX, titleY;
const height = bottom2 - top2;
const width = right2 - left2;
if (scale.isHorizontal()) {
titleX = _alignStartEnd(align, left2, right2);
if (isObject(position)) {
const positionAxisID = Object.keys(position)[0];
const value = position[positionAxisID];
titleY = scales[positionAxisID].getPixelForValue(value) + height - offset2;
} else if (position === "center") {
titleY = (chartArea.bottom + chartArea.top) / 2 + height - offset2;
} else {
titleY = offsetFromEdge(scale, position, offset2);
}
maxWidth = right2 - left2;
} else {
if (isObject(position)) {
const positionAxisID1 = Object.keys(position)[0];
const value1 = position[positionAxisID1];
titleX = scales[positionAxisID1].getPixelForValue(value1) - width + offset2;
} else if (position === "center") {
titleX = (chartArea.left + chartArea.right) / 2 - width + offset2;
} else {
titleX = offsetFromEdge(scale, position, offset2);
}
titleY = _alignStartEnd(align, bottom2, top2);
rotation = position === "left" ? -HALF_PI : HALF_PI;
}
return {
titleX,
titleY,
maxWidth,
rotation
};
}
var Scale = class extends Element2 {
constructor(cfg) {
super();
this.id = cfg.id;
this.type = cfg.type;
this.options = void 0;
this.ctx = cfg.ctx;
this.chart = cfg.chart;
this.top = void 0;
this.bottom = void 0;
this.left = void 0;
this.right = void 0;
this.width = void 0;
this.height = void 0;
this._margins = {
left: 0,
right: 0,
top: 0,
bottom: 0
};
this.maxWidth = void 0;
this.maxHeight = void 0;
this.paddingTop = void 0;
this.paddingBottom = void 0;
this.paddingLeft = void 0;
this.paddingRight = void 0;
this.axis = void 0;
this.labelRotation = void 0;
this.min = void 0;
this.max = void 0;
this._range = void 0;
this.ticks = [];
this._gridLineItems = null;
this._labelItems = null;
this._labelSizes = null;
this._length = 0;
this._maxLength = 0;
this._longestTextCache = {};
this._startPixel = void 0;
this._endPixel = void 0;
this._reversePixels = false;
this._userMax = void 0;
this._userMin = void 0;
this._suggestedMax = void 0;
this._suggestedMin = void 0;
this._ticksLength = 0;
this._borderValue = 0;
this._cache = {};
this._dataLimitsCached = false;
this.$context = void 0;
}
init(options) {
this.options = options.setContext(this.getContext());
this.axis = options.axis;
this._userMin = this.parse(options.min);
this._userMax = this.parse(options.max);
this._suggestedMin = this.parse(options.suggestedMin);
this._suggestedMax = this.parse(options.suggestedMax);
}
parse(raw, index) {
return raw;
}
getUserBounds() {
let { _userMin, _userMax, _suggestedMin, _suggestedMax } = this;
_userMin = finiteOrDefault(_userMin, Number.POSITIVE_INFINITY);
_userMax = finiteOrDefault(_userMax, Number.NEGATIVE_INFINITY);
_suggestedMin = finiteOrDefault(_suggestedMin, Number.POSITIVE_INFINITY);
_suggestedMax = finiteOrDefault(_suggestedMax, Number.NEGATIVE_INFINITY);
return {
min: finiteOrDefault(_userMin, _suggestedMin),
max: finiteOrDefault(_userMax, _suggestedMax),
minDefined: isNumberFinite(_userMin),
maxDefined: isNumberFinite(_userMax)
};
}
getMinMax(canStack) {
let { min: min2, max: max2, minDefined, maxDefined } = this.getUserBounds();
let range;
if (minDefined && maxDefined) {
return {
min: min2,
max: max2
};
}
const metas = this.getMatchingVisibleMetas();
for (let i = 0, ilen = metas.length; i < ilen; ++i) {
range = metas[i].controller.getMinMax(this, canStack);
if (!minDefined) {
min2 = Math.min(min2, range.min);
}
if (!maxDefined) {
max2 = Math.max(max2, range.max);
}
}
min2 = maxDefined && min2 > max2 ? max2 : min2;
max2 = minDefined && min2 > max2 ? min2 : max2;
return {
min: finiteOrDefault(min2, finiteOrDefault(max2, min2)),
max: finiteOrDefault(max2, finiteOrDefault(min2, max2))
};
}
getPadding() {
return {
left: this.paddingLeft || 0,
top: this.paddingTop || 0,
right: this.paddingRight || 0,
bottom: this.paddingBottom || 0
};
}
getTicks() {
return this.ticks;
}
getLabels() {
const data = this.chart.data;
return this.options.labels || (this.isHorizontal() ? data.xLabels : data.yLabels) || data.labels || [];
}
getLabelItems(chartArea = this.chart.chartArea) {
const items = this._labelItems || (this._labelItems = this._computeLabelItems(chartArea));
return items;
}
beforeLayout() {
this._cache = {};
this._dataLimitsCached = false;
}
beforeUpdate() {
callback(this.options.beforeUpdate, [
this
]);
}
update(maxWidth, maxHeight, margins) {
const { beginAtZero, grace, ticks: tickOpts } = this.options;
const sampleSize = tickOpts.sampleSize;
this.beforeUpdate();
this.maxWidth = maxWidth;
this.maxHeight = maxHeight;
this._margins = margins = Object.assign({
left: 0,
right: 0,
top: 0,
bottom: 0
}, margins);
this.ticks = null;
this._labelSizes = null;
this._gridLineItems = null;
this._labelItems = null;
this.beforeSetDimensions();
this.setDimensions();
this.afterSetDimensions();
this._maxLength = this.isHorizontal() ? this.width + margins.left + margins.right : this.height + margins.top + margins.bottom;
if (!this._dataLimitsCached) {
this.beforeDataLimits();
this.determineDataLimits();
this.afterDataLimits();
this._range = _addGrace(this, grace, beginAtZero);
this._dataLimitsCached = true;
}
this.beforeBuildTicks();
this.ticks = this.buildTicks() || [];
this.afterBuildTicks();
const samplingEnabled = sampleSize < this.ticks.length;
this._convertTicksToLabels(samplingEnabled ? sample(this.ticks, sampleSize) : this.ticks);
this.configure();
this.beforeCalculateLabelRotation();
this.calculateLabelRotation();
this.afterCalculateLabelRotation();
if (tickOpts.display && (tickOpts.autoSkip || tickOpts.source === "auto")) {
this.ticks = autoSkip(this, this.ticks);
this._labelSizes = null;
this.afterAutoSkip();
}
if (samplingEnabled) {
this._convertTicksToLabels(this.ticks);
}
this.beforeFit();
this.fit();
this.afterFit();
this.afterUpdate();
}
configure() {
let reversePixels = this.options.reverse;
let startPixel, endPixel;
if (this.isHorizontal()) {
startPixel = this.left;
endPixel = this.right;
} else {
startPixel = this.top;
endPixel = this.bottom;
reversePixels = !reversePixels;
}
this._startPixel = startPixel;
this._endPixel = endPixel;
this._reversePixels = reversePixels;
this._length = endPixel - startPixel;
this._alignToPixels = this.options.alignToPixels;
}
afterUpdate() {
callback(this.options.afterUpdate, [
this
]);
}
beforeSetDimensions() {
callback(this.options.beforeSetDimensions, [
this
]);
}
setDimensions() {
if (this.isHorizontal()) {
this.width = this.maxWidth;
this.left = 0;
this.right = this.width;
} else {
this.height = this.maxHeight;
this.top = 0;
this.bottom = this.height;
}
this.paddingLeft = 0;
this.paddingTop = 0;
this.paddingRight = 0;
this.paddingBottom = 0;
}
afterSetDimensions() {
callback(this.options.afterSetDimensions, [
this
]);
}
_callHooks(name2) {
this.chart.notifyPlugins(name2, this.getContext());
callback(this.options[name2], [
this
]);
}
beforeDataLimits() {
this._callHooks("beforeDataLimits");
}
determineDataLimits() {
}
afterDataLimits() {
this._callHooks("afterDataLimits");
}
beforeBuildTicks() {
this._callHooks("beforeBuildTicks");
}
buildTicks() {
return [];
}
afterBuildTicks() {
this._callHooks("afterBuildTicks");
}
beforeTickToLabelConversion() {
callback(this.options.beforeTickToLabelConversion, [
this
]);
}
generateTickLabels(ticks) {
const tickOpts = this.options.ticks;
let i, ilen, tick2;
for (i = 0, ilen = ticks.length; i < ilen; i++) {
tick2 = ticks[i];
tick2.label = callback(tickOpts.callback, [
tick2.value,
i,
ticks
], this);
}
}
afterTickToLabelConversion() {
callback(this.options.afterTickToLabelConversion, [
this
]);
}
beforeCalculateLabelRotation() {
callback(this.options.beforeCalculateLabelRotation, [
this
]);
}
calculateLabelRotation() {
const options = this.options;
const tickOpts = options.ticks;
const numTicks = getTicksLimit(this.ticks.length, options.ticks.maxTicksLimit);
const minRotation = tickOpts.minRotation || 0;
const maxRotation = tickOpts.maxRotation;
let labelRotation = minRotation;
let tickWidth, maxHeight, maxLabelDiagonal;
if (!this._isVisible() || !tickOpts.display || minRotation >= maxRotation || numTicks <= 1 || !this.isHorizontal()) {
this.labelRotation = minRotation;
return;
}
const labelSizes = this._getLabelSizes();
const maxLabelWidth = labelSizes.widest.width;
const maxLabelHeight = labelSizes.highest.height;
const maxWidth = _limitValue(this.chart.width - maxLabelWidth, 0, this.maxWidth);
tickWidth = options.offset ? this.maxWidth / numTicks : maxWidth / (numTicks - 1);
if (maxLabelWidth + 6 > tickWidth) {
tickWidth = maxWidth / (numTicks - (options.offset ? 0.5 : 1));
maxHeight = this.maxHeight - getTickMarkLength(options.grid) - tickOpts.padding - getTitleHeight(options.title, this.chart.options.font);
maxLabelDiagonal = Math.sqrt(maxLabelWidth * maxLabelWidth + maxLabelHeight * maxLabelHeight);
labelRotation = toDegrees(Math.min(Math.asin(_limitValue((labelSizes.highest.height + 6) / tickWidth, -1, 1)), Math.asin(_limitValue(maxHeight / maxLabelDiagonal, -1, 1)) - Math.asin(_limitValue(maxLabelHeight / maxLabelDiagonal, -1, 1))));
labelRotation = Math.max(minRotation, Math.min(maxRotation, labelRotation));
}
this.labelRotation = labelRotation;
}
afterCalculateLabelRotation() {
callback(this.options.afterCalculateLabelRotation, [
this
]);
}
afterAutoSkip() {
}
beforeFit() {
callback(this.options.beforeFit, [
this
]);
}
fit() {
const minSize = {
width: 0,
height: 0
};
const { chart, options: { ticks: tickOpts, title: titleOpts, grid: gridOpts } } = this;
const display = this._isVisible();
const isHorizontal = this.isHorizontal();
if (display) {
const titleHeight = getTitleHeight(titleOpts, chart.options.font);
if (isHorizontal) {
minSize.width = this.maxWidth;
minSize.height = getTickMarkLength(gridOpts) + titleHeight;
} else {
minSize.height = this.maxHeight;
minSize.width = getTickMarkLength(gridOpts) + titleHeight;
}
if (tickOpts.display && this.ticks.length) {
const { first, last, widest, highest } = this._getLabelSizes();
const tickPadding = tickOpts.padding * 2;
const angleRadians = toRadians(this.labelRotation);
const cos = Math.cos(angleRadians);
const sin = Math.sin(angleRadians);
if (isHorizontal) {
const labelHeight = tickOpts.mirror ? 0 : sin * widest.width + cos * highest.height;
minSize.height = Math.min(this.maxHeight, minSize.height + labelHeight + tickPadding);
} else {
const labelWidth = tickOpts.mirror ? 0 : cos * widest.width + sin * highest.height;
minSize.width = Math.min(this.maxWidth, minSize.width + labelWidth + tickPadding);
}
this._calculatePadding(first, last, sin, cos);
}
}
this._handleMargins();
if (isHorizontal) {
this.width = this._length = chart.width - this._margins.left - this._margins.right;
this.height = minSize.height;
} else {
this.width = minSize.width;
this.height = this._length = chart.height - this._margins.top - this._margins.bottom;
}
}
_calculatePadding(first, last, sin, cos) {
const { ticks: { align, padding }, position } = this.options;
const isRotated = this.labelRotation !== 0;
const labelsBelowTicks = position !== "top" && this.axis === "x";
if (this.isHorizontal()) {
const offsetLeft = this.getPixelForTick(0) - this.left;
const offsetRight = this.right - this.getPixelForTick(this.ticks.length - 1);
let paddingLeft = 0;
let paddingRight = 0;
if (isRotated) {
if (labelsBelowTicks) {
paddingLeft = cos * first.width;
paddingRight = sin * last.height;
} else {
paddingLeft = sin * first.height;
paddingRight = cos * last.width;
}
} else if (align === "start") {
paddingRight = last.width;
} else if (align === "end") {
paddingLeft = first.width;
} else if (align !== "inner") {
paddingLeft = first.width / 2;
paddingRight = last.width / 2;
}
this.paddingLeft = Math.max((paddingLeft - offsetLeft + padding) * this.width / (this.width - offsetLeft), 0);
this.paddingRight = Math.max((paddingRight - offsetRight + padding) * this.width / (this.width - offsetRight), 0);
} else {
let paddingTop = last.height / 2;
let paddingBottom = first.height / 2;
if (align === "start") {
paddingTop = 0;
paddingBottom = first.height;
} else if (align === "end") {
paddingTop = last.height;
paddingBottom = 0;
}
this.paddingTop = paddingTop + padding;
this.paddingBottom = paddingBottom + padding;
}
}
_handleMargins() {
if (this._margins) {
this._margins.left = Math.max(this.paddingLeft, this._margins.left);
this._margins.top = Math.max(this.paddingTop, this._margins.top);
this._margins.right = Math.max(this.paddingRight, this._margins.right);
this._margins.bottom = Math.max(this.paddingBottom, this._margins.bottom);
}
}
afterFit() {
callback(this.options.afterFit, [
this
]);
}
isHorizontal() {
const { axis, position } = this.options;
return position === "top" || position === "bottom" || axis === "x";
}
isFullSize() {
return this.options.fullSize;
}
_convertTicksToLabels(ticks) {
this.beforeTickToLabelConversion();
this.generateTickLabels(ticks);
let i, ilen;
for (i = 0, ilen = ticks.length; i < ilen; i++) {
if (isNullOrUndef(ticks[i].label)) {
ticks.splice(i, 1);
ilen--;
i--;
}
}
this.afterTickToLabelConversion();
}
_getLabelSizes() {
let labelSizes = this._labelSizes;
if (!labelSizes) {
const sampleSize = this.options.ticks.sampleSize;
let ticks = this.ticks;
if (sampleSize < ticks.length) {
ticks = sample(ticks, sampleSize);
}
this._labelSizes = labelSizes = this._computeLabelSizes(ticks, ticks.length, this.options.ticks.maxTicksLimit);
}
return labelSizes;
}
_computeLabelSizes(ticks, length, maxTicksLimit) {
const { ctx, _longestTextCache: caches } = this;
const widths = [];
const heights = [];
const increment = Math.floor(length / getTicksLimit(length, maxTicksLimit));
let widestLabelSize = 0;
let highestLabelSize = 0;
let i, j, jlen, label, tickFont, fontString2, cache, lineHeight, width, height, nestedLabel;
for (i = 0; i < length; i += increment) {
label = ticks[i].label;
tickFont = this._resolveTickFontOptions(i);
ctx.font = fontString2 = tickFont.string;
cache = caches[fontString2] = caches[fontString2] || {
data: {},
gc: []
};
lineHeight = tickFont.lineHeight;
width = height = 0;
if (!isNullOrUndef(label) && !isArray(label)) {
width = _measureText(ctx, cache.data, cache.gc, width, label);
height = lineHeight;
} else if (isArray(label)) {
for (j = 0, jlen = label.length; j < jlen; ++j) {
nestedLabel = label[j];
if (!isNullOrUndef(nestedLabel) && !isArray(nestedLabel)) {
width = _measureText(ctx, cache.data, cache.gc, width, nestedLabel);
height += lineHeight;
}
}
}
widths.push(width);
heights.push(height);
widestLabelSize = Math.max(width, widestLabelSize);
highestLabelSize = Math.max(height, highestLabelSize);
}
garbageCollect(caches, length);
const widest = widths.indexOf(widestLabelSize);
const highest = heights.indexOf(highestLabelSize);
const valueAt = (idx) => ({
width: widths[idx] || 0,
height: heights[idx] || 0
});
return {
first: valueAt(0),
last: valueAt(length - 1),
widest: valueAt(widest),
highest: valueAt(highest),
widths,
heights
};
}
getLabelForValue(value) {
return value;
}
getPixelForValue(value, index) {
return NaN;
}
getValueForPixel(pixel) {
}
getPixelForTick(index) {
const ticks = this.ticks;
if (index < 0 || index > ticks.length - 1) {
return null;
}
return this.getPixelForValue(ticks[index].value);
}
getPixelForDecimal(decimal) {
if (this._reversePixels) {
decimal = 1 - decimal;
}
const pixel = this._startPixel + decimal * this._length;
return _int16Range(this._alignToPixels ? _alignPixel(this.chart, pixel, 0) : pixel);
}
getDecimalForPixel(pixel) {
const decimal = (pixel - this._startPixel) / this._length;
return this._reversePixels ? 1 - decimal : decimal;
}
getBasePixel() {
return this.getPixelForValue(this.getBaseValue());
}
getBaseValue() {
const { min: min2, max: max2 } = this;
return min2 < 0 && max2 < 0 ? max2 : min2 > 0 && max2 > 0 ? min2 : 0;
}
getContext(index) {
const ticks = this.ticks || [];
if (index >= 0 && index < ticks.length) {
const tick2 = ticks[index];
return tick2.$context || (tick2.$context = createTickContext(this.getContext(), index, tick2));
}
return this.$context || (this.$context = createScaleContext(this.chart.getContext(), this));
}
_tickSize() {
const optionTicks = this.options.ticks;
const rot = toRadians(this.labelRotation);
const cos = Math.abs(Math.cos(rot));
const sin = Math.abs(Math.sin(rot));
const labelSizes = this._getLabelSizes();
const padding = optionTicks.autoSkipPadding || 0;
const w = labelSizes ? labelSizes.widest.width + padding : 0;
const h = labelSizes ? labelSizes.highest.height + padding : 0;
return this.isHorizontal() ? h * cos > w * sin ? w / cos : h / sin : h * sin < w * cos ? h / cos : w / sin;
}
_isVisible() {
const display = this.options.display;
if (display !== "auto") {
return !!display;
}
return this.getMatchingVisibleMetas().length > 0;
}
_computeGridLineItems(chartArea) {
const axis = this.axis;
const chart = this.chart;
const options = this.options;
const { grid, position, border } = options;
const offset2 = grid.offset;
const isHorizontal = this.isHorizontal();
const ticks = this.ticks;
const ticksLength = ticks.length + (offset2 ? 1 : 0);
const tl = getTickMarkLength(grid);
const items = [];
const borderOpts = border.setContext(this.getContext());
const axisWidth = borderOpts.display ? borderOpts.width : 0;
const axisHalfWidth = axisWidth / 2;
const alignBorderValue = function(pixel) {
return _alignPixel(chart, pixel, axisWidth);
};
let borderValue, i, lineValue, alignedLineValue;
let tx1, ty1, tx2, ty2, x1, y1, x2, y2;
if (position === "top") {
borderValue = alignBorderValue(this.bottom);
ty1 = this.bottom - tl;
ty2 = borderValue - axisHalfWidth;
y1 = alignBorderValue(chartArea.top) + axisHalfWidth;
y2 = chartArea.bottom;
} else if (position === "bottom") {
borderValue = alignBorderValue(this.top);
y1 = chartArea.top;
y2 = alignBorderValue(chartArea.bottom) - axisHalfWidth;
ty1 = borderValue + axisHalfWidth;
ty2 = this.top + tl;
} else if (position === "left") {
borderValue = alignBorderValue(this.right);
tx1 = this.right - tl;
tx2 = borderValue - axisHalfWidth;
x1 = alignBorderValue(chartArea.left) + axisHalfWidth;
x2 = chartArea.right;
} else if (position === "right") {
borderValue = alignBorderValue(this.left);
x1 = chartArea.left;
x2 = alignBorderValue(chartArea.right) - axisHalfWidth;
tx1 = borderValue + axisHalfWidth;
tx2 = this.left + tl;
} else if (axis === "x") {
if (position === "center") {
borderValue = alignBorderValue((chartArea.top + chartArea.bottom) / 2 + 0.5);
} else if (isObject(position)) {
const positionAxisID = Object.keys(position)[0];
const value = position[positionAxisID];
borderValue = alignBorderValue(this.chart.scales[positionAxisID].getPixelForValue(value));
}
y1 = chartArea.top;
y2 = chartArea.bottom;
ty1 = borderValue + axisHalfWidth;
ty2 = ty1 + tl;
} else if (axis === "y") {
if (position === "center") {
borderValue = alignBorderValue((chartArea.left + chartArea.right) / 2);
} else if (isObject(position)) {
const positionAxisID1 = Object.keys(position)[0];
const value1 = position[positionAxisID1];
borderValue = alignBorderValue(this.chart.scales[positionAxisID1].getPixelForValue(value1));
}
tx1 = borderValue - axisHalfWidth;
tx2 = tx1 - tl;
x1 = chartArea.left;
x2 = chartArea.right;
}
const limit = valueOrDefault(options.ticks.maxTicksLimit, ticksLength);
const step = Math.max(1, Math.ceil(ticksLength / limit));
for (i = 0; i < ticksLength; i += step) {
const context = this.getContext(i);
const optsAtIndex = grid.setContext(context);
const optsAtIndexBorder = border.setContext(context);
const lineWidth = optsAtIndex.lineWidth;
const lineColor = optsAtIndex.color;
const borderDash = optsAtIndexBorder.dash || [];
const borderDashOffset = optsAtIndexBorder.dashOffset;
const tickWidth = optsAtIndex.tickWidth;
const tickColor = optsAtIndex.tickColor;
const tickBorderDash = optsAtIndex.tickBorderDash || [];
const tickBorderDashOffset = optsAtIndex.tickBorderDashOffset;
lineValue = getPixelForGridLine(this, i, offset2);
if (lineValue === void 0) {
continue;
}
alignedLineValue = _alignPixel(chart, lineValue, lineWidth);
if (isHorizontal) {
tx1 = tx2 = x1 = x2 = alignedLineValue;
} else {
ty1 = ty2 = y1 = y2 = alignedLineValue;
}
items.push({
tx1,
ty1,
tx2,
ty2,
x1,
y1,
x2,
y2,
width: lineWidth,
color: lineColor,
borderDash,
borderDashOffset,
tickWidth,
tickColor,
tickBorderDash,
tickBorderDashOffset
});
}
this._ticksLength = ticksLength;
this._borderValue = borderValue;
return items;
}
_computeLabelItems(chartArea) {
const axis = this.axis;
const options = this.options;
const { position, ticks: optionTicks } = options;
const isHorizontal = this.isHorizontal();
const ticks = this.ticks;
const { align, crossAlign, padding, mirror } = optionTicks;
const tl = getTickMarkLength(options.grid);
const tickAndPadding = tl + padding;
const hTickAndPadding = mirror ? -padding : tickAndPadding;
const rotation = -toRadians(this.labelRotation);
const items = [];
let i, ilen, tick2, label, x, y, textAlign, pixel, font, lineHeight, lineCount, textOffset;
let textBaseline = "middle";
if (position === "top") {
y = this.bottom - hTickAndPadding;
textAlign = this._getXAxisLabelAlignment();
} else if (position === "bottom") {
y = this.top + hTickAndPadding;
textAlign = this._getXAxisLabelAlignment();
} else if (position === "left") {
const ret = this._getYAxisLabelAlignment(tl);
textAlign = ret.textAlign;
x = ret.x;
} else if (position === "right") {
const ret1 = this._getYAxisLabelAlignment(tl);
textAlign = ret1.textAlign;
x = ret1.x;
} else if (axis === "x") {
if (position === "center") {
y = (chartArea.top + chartArea.bottom) / 2 + tickAndPadding;
} else if (isObject(position)) {
const positionAxisID = Object.keys(position)[0];
const value = position[positionAxisID];
y = this.chart.scales[positionAxisID].getPixelForValue(value) + tickAndPadding;
}
textAlign = this._getXAxisLabelAlignment();
} else if (axis === "y") {
if (position === "center") {
x = (chartArea.left + chartArea.right) / 2 - tickAndPadding;
} else if (isObject(position)) {
const positionAxisID1 = Object.keys(position)[0];
const value1 = position[positionAxisID1];
x = this.chart.scales[positionAxisID1].getPixelForValue(value1);
}
textAlign = this._getYAxisLabelAlignment(tl).textAlign;
}
if (axis === "y") {
if (align === "start") {
textBaseline = "top";
} else if (align === "end") {
textBaseline = "bottom";
}
}
const labelSizes = this._getLabelSizes();
for (i = 0, ilen = ticks.length; i < ilen; ++i) {
tick2 = ticks[i];
label = tick2.label;
const optsAtIndex = optionTicks.setContext(this.getContext(i));
pixel = this.getPixelForTick(i) + optionTicks.labelOffset;
font = this._resolveTickFontOptions(i);
lineHeight = font.lineHeight;
lineCount = isArray(label) ? label.length : 1;
const halfCount = lineCount / 2;
const color2 = optsAtIndex.color;
const strokeColor = optsAtIndex.textStrokeColor;
const strokeWidth = optsAtIndex.textStrokeWidth;
let tickTextAlign = textAlign;
if (isHorizontal) {
x = pixel;
if (textAlign === "inner") {
if (i === ilen - 1) {
tickTextAlign = !this.options.reverse ? "right" : "left";
} else if (i === 0) {
tickTextAlign = !this.options.reverse ? "left" : "right";
} else {
tickTextAlign = "center";
}
}
if (position === "top") {
if (crossAlign === "near" || rotation !== 0) {
textOffset = -lineCount * lineHeight + lineHeight / 2;
} else if (crossAlign === "center") {
textOffset = -labelSizes.highest.height / 2 - halfCount * lineHeight + lineHeight;
} else {
textOffset = -labelSizes.highest.height + lineHeight / 2;
}
} else {
if (crossAlign === "near" || rotation !== 0) {
textOffset = lineHeight / 2;
} else if (crossAlign === "center") {
textOffset = labelSizes.highest.height / 2 - halfCount * lineHeight;
} else {
textOffset = labelSizes.highest.height - lineCount * lineHeight;
}
}
if (mirror) {
textOffset *= -1;
}
if (rotation !== 0 && !optsAtIndex.showLabelBackdrop) {
x += lineHeight / 2 * Math.sin(rotation);
}
} else {
y = pixel;
textOffset = (1 - lineCount) * lineHeight / 2;
}
let backdrop;
if (optsAtIndex.showLabelBackdrop) {
const labelPadding = toPadding(optsAtIndex.backdropPadding);
const height = labelSizes.heights[i];
const width = labelSizes.widths[i];
let top2 = textOffset - labelPadding.top;
let left2 = 0 - labelPadding.left;
switch (textBaseline) {
case "middle":
top2 -= height / 2;
break;
case "bottom":
top2 -= height;
break;
}
switch (textAlign) {
case "center":
left2 -= width / 2;
break;
case "right":
left2 -= width;
break;
}
backdrop = {
left: left2,
top: top2,
width: width + labelPadding.width,
height: height + labelPadding.height,
color: optsAtIndex.backdropColor
};
}
items.push({
label,
font,
textOffset,
options: {
rotation,
color: color2,
strokeColor,
strokeWidth,
textAlign: tickTextAlign,
textBaseline,
translation: [
x,
y
],
backdrop
}
});
}
return items;
}
_getXAxisLabelAlignment() {
const { position, ticks } = this.options;
const rotation = -toRadians(this.labelRotation);
if (rotation) {
return position === "top" ? "left" : "right";
}
let align = "center";
if (ticks.align === "start") {
align = "left";
} else if (ticks.align === "end") {
align = "right";
} else if (ticks.align === "inner") {
align = "inner";
}
return align;
}
_getYAxisLabelAlignment(tl) {
const { position, ticks: { crossAlign, mirror, padding } } = this.options;
const labelSizes = this._getLabelSizes();
const tickAndPadding = tl + padding;
const widest = labelSizes.widest.width;
let textAlign;
let x;
if (position === "left") {
if (mirror) {
x = this.right + padding;
if (crossAlign === "near") {
textAlign = "left";
} else if (crossAlign === "center") {
textAlign = "center";
x += widest / 2;
} else {
textAlign = "right";
x += widest;
}
} else {
x = this.right - tickAndPadding;
if (crossAlign === "near") {
textAlign = "right";
} else if (crossAlign === "center") {
textAlign = "center";
x -= widest / 2;
} else {
textAlign = "left";
x = this.left;
}
}
} else if (position === "right") {
if (mirror) {
x = this.left + padding;
if (crossAlign === "near") {
textAlign = "right";
} else if (crossAlign === "center") {
textAlign = "center";
x -= widest / 2;
} else {
textAlign = "left";
x -= widest;
}
} else {
x = this.left + tickAndPadding;
if (crossAlign === "near") {
textAlign = "left";
} else if (crossAlign === "center") {
textAlign = "center";
x += widest / 2;
} else {
textAlign = "right";
x = this.right;
}
}
} else {
textAlign = "right";
}
return {
textAlign,
x
};
}
_computeLabelArea() {
if (this.options.ticks.mirror) {
return;
}
const chart = this.chart;
const position = this.options.position;
if (position === "left" || position === "right") {
return {
top: 0,
left: this.left,
bottom: chart.height,
right: this.right
};
}
if (position === "top" || position === "bottom") {
return {
top: this.top,
left: 0,
bottom: this.bottom,
right: chart.width
};
}
}
drawBackground() {
const { ctx, options: { backgroundColor }, left: left2, top: top2, width, height } = this;
if (backgroundColor) {
ctx.save();
ctx.fillStyle = backgroundColor;
ctx.fillRect(left2, top2, width, height);
ctx.restore();
}
}
getLineWidthForValue(value) {
const grid = this.options.grid;
if (!this._isVisible() || !grid.display) {
return 0;
}
const ticks = this.ticks;
const index = ticks.findIndex((t) => t.value === value);
if (index >= 0) {
const opts = grid.setContext(this.getContext(index));
return opts.lineWidth;
}
return 0;
}
drawGrid(chartArea) {
const grid = this.options.grid;
const ctx = this.ctx;
const items = this._gridLineItems || (this._gridLineItems = this._computeGridLineItems(chartArea));
let i, ilen;
const drawLine = (p1, p2, style) => {
if (!style.width || !style.color) {
return;
}
ctx.save();
ctx.lineWidth = style.width;
ctx.strokeStyle = style.color;
ctx.setLineDash(style.borderDash || []);
ctx.lineDashOffset = style.borderDashOffset;
ctx.beginPath();
ctx.moveTo(p1.x, p1.y);
ctx.lineTo(p2.x, p2.y);
ctx.stroke();
ctx.restore();
};
if (grid.display) {
for (i = 0, ilen = items.length; i < ilen; ++i) {
const item = items[i];
if (grid.drawOnChartArea) {
drawLine({
x: item.x1,
y: item.y1
}, {
x: item.x2,
y: item.y2
}, item);
}
if (grid.drawTicks) {
drawLine({
x: item.tx1,
y: item.ty1
}, {
x: item.tx2,
y: item.ty2
}, {
color: item.tickColor,
width: item.tickWidth,
borderDash: item.tickBorderDash,
borderDashOffset: item.tickBorderDashOffset
});
}
}
}
}
drawBorder() {
const { chart, ctx, options: { border, grid } } = this;
const borderOpts = border.setContext(this.getContext());
const axisWidth = border.display ? borderOpts.width : 0;
if (!axisWidth) {
return;
}
const lastLineWidth = grid.setContext(this.getContext(0)).lineWidth;
const borderValue = this._borderValue;
let x1, x2, y1, y2;
if (this.isHorizontal()) {
x1 = _alignPixel(chart, this.left, axisWidth) - axisWidth / 2;
x2 = _alignPixel(chart, this.right, lastLineWidth) + lastLineWidth / 2;
y1 = y2 = borderValue;
} else {
y1 = _alignPixel(chart, this.top, axisWidth) - axisWidth / 2;
y2 = _alignPixel(chart, this.bottom, lastLineWidth) + lastLineWidth / 2;
x1 = x2 = borderValue;
}
ctx.save();
ctx.lineWidth = borderOpts.width;
ctx.strokeStyle = borderOpts.color;
ctx.beginPath();
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.stroke();
ctx.restore();
}
drawLabels(chartArea) {
const optionTicks = this.options.ticks;
if (!optionTicks.display) {
return;
}
const ctx = this.ctx;
const area = this._computeLabelArea();
if (area) {
clipArea(ctx, area);
}
const items = this.getLabelItems(chartArea);
for (const item of items) {
const renderTextOptions = item.options;
const tickFont = item.font;
const label = item.label;
const y = item.textOffset;
renderText(ctx, label, 0, y, tickFont, renderTextOptions);
}
if (area) {
unclipArea(ctx);
}
}
drawTitle() {
const { ctx, options: { position, title, reverse } } = this;
if (!title.display) {
return;
}
const font = toFont(title.font);
const padding = toPadding(title.padding);
const align = title.align;
let offset2 = font.lineHeight / 2;
if (position === "bottom" || position === "center" || isObject(position)) {
offset2 += padding.bottom;
if (isArray(title.text)) {
offset2 += font.lineHeight * (title.text.length - 1);
}
} else {
offset2 += padding.top;
}
const { titleX, titleY, maxWidth, rotation } = titleArgs(this, offset2, position, align);
renderText(ctx, title.text, 0, 0, font, {
color: title.color,
maxWidth,
rotation,
textAlign: titleAlign(align, position, reverse),
textBaseline: "middle",
translation: [
titleX,
titleY
]
});
}
draw(chartArea) {
if (!this._isVisible()) {
return;
}
this.drawBackground();
this.drawGrid(chartArea);
this.drawBorder();
this.drawTitle();
this.drawLabels(chartArea);
}
_layers() {
const opts = this.options;
const tz = opts.ticks && opts.ticks.z || 0;
const gz = valueOrDefault(opts.grid && opts.grid.z, -1);
const bz = valueOrDefault(opts.border && opts.border.z, 0);
if (!this._isVisible() || this.draw !== Scale.prototype.draw) {
return [
{
z: tz,
draw: (chartArea) => {
this.draw(chartArea);
}
}
];
}
return [
{
z: gz,
draw: (chartArea) => {
this.drawBackground();
this.drawGrid(chartArea);
this.drawTitle();
}
},
{
z: bz,
draw: () => {
this.drawBorder();
}
},
{
z: tz,
draw: (chartArea) => {
this.drawLabels(chartArea);
}
}
];
}
getMatchingVisibleMetas(type) {
const metas = this.chart.getSortedVisibleDatasetMetas();
const axisID = this.axis + "AxisID";
const result = [];
let i, ilen;
for (i = 0, ilen = metas.length; i < ilen; ++i) {
const meta = metas[i];
if (meta[axisID] === this.id && (!type || meta.type === type)) {
result.push(meta);
}
}
return result;
}
_resolveTickFontOptions(index) {
const opts = this.options.ticks.setContext(this.getContext(index));
return toFont(opts.font);
}
_maxDigits() {
const fontSize = this._resolveTickFontOptions(0).lineHeight;
return (this.isHorizontal() ? this.width : this.height) / fontSize;
}
};
var TypedRegistry = class {
constructor(type, scope, override) {
this.type = type;
this.scope = scope;
this.override = override;
this.items = /* @__PURE__ */ Object.create(null);
}
isForType(type) {
return Object.prototype.isPrototypeOf.call(this.type.prototype, type.prototype);
}
register(item) {
const proto = Object.getPrototypeOf(item);
let parentScope;
if (isIChartComponent(proto)) {
parentScope = this.register(proto);
}
const items = this.items;
const id = item.id;
const scope = this.scope + "." + id;
if (!id) {
throw new Error("class does not have id: " + item);
}
if (id in items) {
return scope;
}
items[id] = item;
registerDefaults(item, scope, parentScope);
if (this.override) {
defaults.override(item.id, item.overrides);
}
return scope;
}
get(id) {
return this.items[id];
}
unregister(item) {
const items = this.items;
const id = item.id;
const scope = this.scope;
if (id in items) {
delete items[id];
}
if (scope && id in defaults[scope]) {
delete defaults[scope][id];
if (this.override) {
delete overrides[id];
}
}
}
};
function registerDefaults(item, scope, parentScope) {
const itemDefaults = merge(/* @__PURE__ */ Object.create(null), [
parentScope ? defaults.get(parentScope) : {},
defaults.get(scope),
item.defaults
]);
defaults.set(scope, itemDefaults);
if (item.defaultRoutes) {
routeDefaults(scope, item.defaultRoutes);
}
if (item.descriptors) {
defaults.describe(scope, item.descriptors);
}
}
function routeDefaults(scope, routes) {
Object.keys(routes).forEach((property) => {
const propertyParts = property.split(".");
const sourceName = propertyParts.pop();
const sourceScope = [
scope
].concat(propertyParts).join(".");
const parts = routes[property].split(".");
const targetName = parts.pop();
const targetScope = parts.join(".");
defaults.route(sourceScope, sourceName, targetScope, targetName);
});
}
function isIChartComponent(proto) {
return "id" in proto && "defaults" in proto;
}
var Registry = class {
constructor() {
this.controllers = new TypedRegistry(DatasetController, "datasets", true);
this.elements = new TypedRegistry(Element2, "elements");
this.plugins = new TypedRegistry(Object, "plugins");
this.scales = new TypedRegistry(Scale, "scales");
this._typedRegistries = [
this.controllers,
this.scales,
this.elements
];
}
add(...args) {
this._each("register", args);
}
remove(...args) {
this._each("unregister", args);
}
addControllers(...args) {
this._each("register", args, this.controllers);
}
addElements(...args) {
this._each("register", args, this.elements);
}
addPlugins(...args) {
this._each("register", args, this.plugins);
}
addScales(...args) {
this._each("register", args, this.scales);
}
getController(id) {
return this._get(id, this.controllers, "controller");
}
getElement(id) {
return this._get(id, this.elements, "element");
}
getPlugin(id) {
return this._get(id, this.plugins, "plugin");
}
getScale(id) {
return this._get(id, this.scales, "scale");
}
removeControllers(...args) {
this._each("unregister", args, this.controllers);
}
removeElements(...args) {
this._each("unregister", args, this.elements);
}
removePlugins(...args) {
this._each("unregister", args, this.plugins);
}
removeScales(...args) {
this._each("unregister", args, this.scales);
}
_each(method, args, typedRegistry) {
[
...args
].forEach((arg) => {
const reg = typedRegistry || this._getRegistryForType(arg);
if (typedRegistry || reg.isForType(arg) || reg === this.plugins && arg.id) {
this._exec(method, reg, arg);
} else {
each2(arg, (item) => {
const itemReg = typedRegistry || this._getRegistryForType(item);
this._exec(method, itemReg, item);
});
}
});
}
_exec(method, registry2, component) {
const camelMethod = _capitalize(method);
callback(component["before" + camelMethod], [], component);
registry2[method](component);
callback(component["after" + camelMethod], [], component);
}
_getRegistryForType(type) {
for (let i = 0; i < this._typedRegistries.length; i++) {
const reg = this._typedRegistries[i];
if (reg.isForType(type)) {
return reg;
}
}
return this.plugins;
}
_get(id, typedRegistry, type) {
const item = typedRegistry.get(id);
if (item === void 0) {
throw new Error('"' + id + '" is not a registered ' + type + ".");
}
return item;
}
};
var registry = /* @__PURE__ */ new Registry();
var PluginService = class {
constructor() {
this._init = [];
}
notify(chart, hook, args, filter) {
if (hook === "beforeInit") {
this._init = this._createDescriptors(chart, true);
this._notify(this._init, chart, "install");
}
const descriptors2 = filter ? this._descriptors(chart).filter(filter) : this._descriptors(chart);
const result = this._notify(descriptors2, chart, hook, args);
if (hook === "afterDestroy") {
this._notify(descriptors2, chart, "stop");
this._notify(this._init, chart, "uninstall");
}
return result;
}
_notify(descriptors2, chart, hook, args) {
args = args || {};
for (const descriptor of descriptors2) {
const plugin2 = descriptor.plugin;
const method = plugin2[hook];
const params = [
chart,
args,
descriptor.options
];
if (callback(method, params, plugin2) === false && args.cancelable) {
return false;
}
}
return true;
}
invalidate() {
if (!isNullOrUndef(this._cache)) {
this._oldCache = this._cache;
this._cache = void 0;
}
}
_descriptors(chart) {
if (this._cache) {
return this._cache;
}
const descriptors2 = this._cache = this._createDescriptors(chart);
this._notifyStateChanges(chart);
return descriptors2;
}
_createDescriptors(chart, all) {
const config = chart && chart.config;
const options = valueOrDefault(config.options && config.options.plugins, {});
const plugins = allPlugins(config);
return options === false && !all ? [] : createDescriptors(chart, plugins, options, all);
}
_notifyStateChanges(chart) {
const previousDescriptors = this._oldCache || [];
const descriptors2 = this._cache;
const diff = (a, b) => a.filter((x) => !b.some((y) => x.plugin.id === y.plugin.id));
this._notify(diff(previousDescriptors, descriptors2), chart, "stop");
this._notify(diff(descriptors2, previousDescriptors), chart, "start");
}
};
function allPlugins(config) {
const localIds = {};
const plugins = [];
const keys = Object.keys(registry.plugins.items);
for (let i = 0; i < keys.length; i++) {
plugins.push(registry.getPlugin(keys[i]));
}
const local = config.plugins || [];
for (let i1 = 0; i1 < local.length; i1++) {
const plugin2 = local[i1];
if (plugins.indexOf(plugin2) === -1) {
plugins.push(plugin2);
localIds[plugin2.id] = true;
}
}
return {
plugins,
localIds
};
}
function getOpts(options, all) {
if (!all && options === false) {
return null;
}
if (options === true) {
return {};
}
return options;
}
function createDescriptors(chart, { plugins, localIds }, options, all) {
const result = [];
const context = chart.getContext();
for (const plugin2 of plugins) {
const id = plugin2.id;
const opts = getOpts(options[id], all);
if (opts === null) {
continue;
}
result.push({
plugin: plugin2,
options: pluginOpts(chart.config, {
plugin: plugin2,
local: localIds[id]
}, opts, context)
});
}
return result;
}
function pluginOpts(config, { plugin: plugin2, local }, opts, context) {
const keys = config.pluginScopeKeys(plugin2);
const scopes = config.getOptionScopes(opts, keys);
if (local && plugin2.defaults) {
scopes.push(plugin2.defaults);
}
return config.createResolver(scopes, context, [
""
], {
scriptable: false,
indexable: false,
allKeys: true
});
}
function getIndexAxis(type, options) {
const datasetDefaults = defaults.datasets[type] || {};
const datasetOptions = (options.datasets || {})[type] || {};
return datasetOptions.indexAxis || options.indexAxis || datasetDefaults.indexAxis || "x";
}
function getAxisFromDefaultScaleID(id, indexAxis) {
let axis = id;
if (id === "_index_") {
axis = indexAxis;
} else if (id === "_value_") {
axis = indexAxis === "x" ? "y" : "x";
}
return axis;
}
function getDefaultScaleIDFromAxis(axis, indexAxis) {
return axis === indexAxis ? "_index_" : "_value_";
}
function axisFromPosition(position) {
if (position === "top" || position === "bottom") {
return "x";
}
if (position === "left" || position === "right") {
return "y";
}
}
function determineAxis(id, scaleOptions) {
if (id === "x" || id === "y" || id === "r") {
return id;
}
id = scaleOptions.axis || axisFromPosition(scaleOptions.position) || id.length > 1 && determineAxis(id[0].toLowerCase(), scaleOptions);
if (id) {
return id;
}
throw new Error(`Cannot determine type of '${name}' axis. Please provide 'axis' or 'position' option.`);
}
function mergeScaleConfig(config, options) {
const chartDefaults = overrides[config.type] || {
scales: {}
};
const configScales = options.scales || {};
const chartIndexAxis = getIndexAxis(config.type, options);
const scales = /* @__PURE__ */ Object.create(null);
Object.keys(configScales).forEach((id) => {
const scaleConf = configScales[id];
if (!isObject(scaleConf)) {
return console.error(`Invalid scale configuration for scale: ${id}`);
}
if (scaleConf._proxy) {
return console.warn(`Ignoring resolver passed as options for scale: ${id}`);
}
const axis = determineAxis(id, scaleConf);
const defaultId = getDefaultScaleIDFromAxis(axis, chartIndexAxis);
const defaultScaleOptions = chartDefaults.scales || {};
scales[id] = mergeIf(/* @__PURE__ */ Object.create(null), [
{
axis
},
scaleConf,
defaultScaleOptions[axis],
defaultScaleOptions[defaultId]
]);
});
config.data.datasets.forEach((dataset) => {
const type = dataset.type || config.type;
const indexAxis = dataset.indexAxis || getIndexAxis(type, options);
const datasetDefaults = overrides[type] || {};
const defaultScaleOptions = datasetDefaults.scales || {};
Object.keys(defaultScaleOptions).forEach((defaultID) => {
const axis = getAxisFromDefaultScaleID(defaultID, indexAxis);
const id = dataset[axis + "AxisID"] || axis;
scales[id] = scales[id] || /* @__PURE__ */ Object.create(null);
mergeIf(scales[id], [
{
axis
},
configScales[id],
defaultScaleOptions[defaultID]
]);
});
});
Object.keys(scales).forEach((key) => {
const scale = scales[key];
mergeIf(scale, [
defaults.scales[scale.type],
defaults.scale
]);
});
return scales;
}
function initOptions(config) {
const options = config.options || (config.options = {});
options.plugins = valueOrDefault(options.plugins, {});
options.scales = mergeScaleConfig(config, options);
}
function initData(data) {
data = data || {};
data.datasets = data.datasets || [];
data.labels = data.labels || [];
return data;
}
function initConfig(config) {
config = config || {};
config.data = initData(config.data);
initOptions(config);
return config;
}
var keyCache = /* @__PURE__ */ new Map();
var keysCached = /* @__PURE__ */ new Set();
function cachedKeys(cacheKey, generate) {
let keys = keyCache.get(cacheKey);
if (!keys) {
keys = generate();
keyCache.set(cacheKey, keys);
keysCached.add(keys);
}
return keys;
}
var addIfFound = (set2, obj, key) => {
const opts = resolveObjectKey(obj, key);
if (opts !== void 0) {
set2.add(opts);
}
};
var Config = class {
constructor(config) {
this._config = initConfig(config);
this._scopeCache = /* @__PURE__ */ new Map();
this._resolverCache = /* @__PURE__ */ new Map();
}
get platform() {
return this._config.platform;
}
get type() {
return this._config.type;
}
set type(type) {
this._config.type = type;
}
get data() {
return this._config.data;
}
set data(data) {
this._config.data = initData(data);
}
get options() {
return this._config.options;
}
set options(options) {
this._config.options = options;
}
get plugins() {
return this._config.plugins;
}
update() {
const config = this._config;
this.clearCache();
initOptions(config);
}
clearCache() {
this._scopeCache.clear();
this._resolverCache.clear();
}
datasetScopeKeys(datasetType) {
return cachedKeys(datasetType, () => [
[
`datasets.${datasetType}`,
""
]
]);
}
datasetAnimationScopeKeys(datasetType, transition) {
return cachedKeys(`${datasetType}.transition.${transition}`, () => [
[
`datasets.${datasetType}.transitions.${transition}`,
`transitions.${transition}`
],
[
`datasets.${datasetType}`,
""
]
]);
}
datasetElementScopeKeys(datasetType, elementType) {
return cachedKeys(`${datasetType}-${elementType}`, () => [
[
`datasets.${datasetType}.elements.${elementType}`,
`datasets.${datasetType}`,
`elements.${elementType}`,
""
]
]);
}
pluginScopeKeys(plugin2) {
const id = plugin2.id;
const type = this.type;
return cachedKeys(`${type}-plugin-${id}`, () => [
[
`plugins.${id}`,
...plugin2.additionalOptionScopes || []
]
]);
}
_cachedScopes(mainScope, resetCache) {
const _scopeCache = this._scopeCache;
let cache = _scopeCache.get(mainScope);
if (!cache || resetCache) {
cache = /* @__PURE__ */ new Map();
_scopeCache.set(mainScope, cache);
}
return cache;
}
getOptionScopes(mainScope, keyLists, resetCache) {
const { options, type } = this;
const cache = this._cachedScopes(mainScope, resetCache);
const cached = cache.get(keyLists);
if (cached) {
return cached;
}
const scopes = /* @__PURE__ */ new Set();
keyLists.forEach((keys) => {
if (mainScope) {
scopes.add(mainScope);
keys.forEach((key) => addIfFound(scopes, mainScope, key));
}
keys.forEach((key) => addIfFound(scopes, options, key));
keys.forEach((key) => addIfFound(scopes, overrides[type] || {}, key));
keys.forEach((key) => addIfFound(scopes, defaults, key));
keys.forEach((key) => addIfFound(scopes, descriptors, key));
});
const array = Array.from(scopes);
if (array.length === 0) {
array.push(/* @__PURE__ */ Object.create(null));
}
if (keysCached.has(keyLists)) {
cache.set(keyLists, array);
}
return array;
}
chartOptionScopes() {
const { options, type } = this;
return [
options,
overrides[type] || {},
defaults.datasets[type] || {},
{
type
},
defaults,
descriptors
];
}
resolveNamedOptions(scopes, names2, context, prefixes = [
""
]) {
const result = {
$shared: true
};
const { resolver, subPrefixes } = getResolver(this._resolverCache, scopes, prefixes);
let options = resolver;
if (needContext(resolver, names2)) {
result.$shared = false;
context = isFunction(context) ? context() : context;
const subResolver = this.createResolver(scopes, context, subPrefixes);
options = _attachContext(resolver, context, subResolver);
}
for (const prop of names2) {
result[prop] = options[prop];
}
return result;
}
createResolver(scopes, context, prefixes = [
""
], descriptorDefaults) {
const { resolver } = getResolver(this._resolverCache, scopes, prefixes);
return isObject(context) ? _attachContext(resolver, context, void 0, descriptorDefaults) : resolver;
}
};
function getResolver(resolverCache, scopes, prefixes) {
let cache = resolverCache.get(scopes);
if (!cache) {
cache = /* @__PURE__ */ new Map();
resolverCache.set(scopes, cache);
}
const cacheKey = prefixes.join();
let cached = cache.get(cacheKey);
if (!cached) {
const resolver = _createResolver(scopes, prefixes);
cached = {
resolver,
subPrefixes: prefixes.filter((p) => !p.toLowerCase().includes("hover"))
};
cache.set(cacheKey, cached);
}
return cached;
}
var hasFunction = (value) => isObject(value) && Object.getOwnPropertyNames(value).reduce((acc, key) => acc || isFunction(value[key]), false);
function needContext(proxy, names2) {
const { isScriptable, isIndexable } = _descriptors(proxy);
for (const prop of names2) {
const scriptable = isScriptable(prop);
const indexable = isIndexable(prop);
const value = (indexable || scriptable) && proxy[prop];
if (scriptable && (isFunction(value) || hasFunction(value)) || indexable && isArray(value)) {
return true;
}
}
return false;
}
var version = "4.2.1";
var KNOWN_POSITIONS = [
"top",
"bottom",
"left",
"right",
"chartArea"
];
function positionIsHorizontal(position, axis) {
return position === "top" || position === "bottom" || KNOWN_POSITIONS.indexOf(position) === -1 && axis === "x";
}
function compare2Level(l1, l2) {
return function(a, b) {
return a[l1] === b[l1] ? a[l2] - b[l2] : a[l1] - b[l1];
};
}
function onAnimationsComplete(context) {
const chart = context.chart;
const animationOptions = chart.options.animation;
chart.notifyPlugins("afterRender");
callback(animationOptions && animationOptions.onComplete, [
context
], chart);
}
function onAnimationProgress(context) {
const chart = context.chart;
const animationOptions = chart.options.animation;
callback(animationOptions && animationOptions.onProgress, [
context
], chart);
}
function getCanvas(item) {
if (_isDomSupported() && typeof item === "string") {
item = document.getElementById(item);
} else if (item && item.length) {
item = item[0];
}
if (item && item.canvas) {
item = item.canvas;
}
return item;
}
var instances = {};
var getChart = (key) => {
const canvas = getCanvas(key);
return Object.values(instances).filter((c) => c.canvas === canvas).pop();
};
function moveNumericKeys(obj, start2, move) {
const keys = Object.keys(obj);
for (const key of keys) {
const intKey = +key;
if (intKey >= start2) {
const value = obj[key];
delete obj[key];
if (move > 0 || intKey > start2) {
obj[intKey + move] = value;
}
}
}
}
function determineLastEvent(e, lastEvent, inChartArea, isClick) {
if (!inChartArea || e.type === "mouseout") {
return null;
}
if (isClick) {
return lastEvent;
}
return e;
}
function getDatasetArea(meta) {
const { xScale, yScale } = meta;
if (xScale && yScale) {
return {
left: xScale.left,
right: xScale.right,
top: yScale.top,
bottom: yScale.bottom
};
}
}
var Chart = class {
static register(...items) {
registry.add(...items);
invalidatePlugins();
}
static unregister(...items) {
registry.remove(...items);
invalidatePlugins();
}
constructor(item, userConfig) {
const config = this.config = new Config(userConfig);
const initialCanvas = getCanvas(item);
const existingChart = getChart(initialCanvas);
if (existingChart) {
throw new Error("Canvas is already in use. Chart with ID '" + existingChart.id + "' must be destroyed before the canvas with ID '" + existingChart.canvas.id + "' can be reused.");
}
const options = config.createResolver(config.chartOptionScopes(), this.getContext());
this.platform = new (config.platform || _detectPlatform(initialCanvas))();
this.platform.updateConfig(config);
const context = this.platform.acquireContext(initialCanvas, options.aspectRatio);
const canvas = context && context.canvas;
const height = canvas && canvas.height;
const width = canvas && canvas.width;
this.id = uid();
this.ctx = context;
this.canvas = canvas;
this.width = width;
this.height = height;
this._options = options;
this._aspectRatio = this.aspectRatio;
this._layers = [];
this._metasets = [];
this._stacks = void 0;
this.boxes = [];
this.currentDevicePixelRatio = void 0;
this.chartArea = void 0;
this._active = [];
this._lastEvent = void 0;
this._listeners = {};
this._responsiveListeners = void 0;
this._sortedMetasets = [];
this.scales = {};
this._plugins = new PluginService();
this.$proxies = {};
this._hiddenIndices = {};
this.attached = false;
this._animationsDisabled = void 0;
this.$context = void 0;
this._doResize = debounce3((mode) => this.update(mode), options.resizeDelay || 0);
this._dataChanges = [];
instances[this.id] = this;
if (!context || !canvas) {
console.error("Failed to create chart: can't acquire context from the given item");
return;
}
animator.listen(this, "complete", onAnimationsComplete);
animator.listen(this, "progress", onAnimationProgress);
this._initialize();
if (this.attached) {
this.update();
}
}
get aspectRatio() {
const { options: { aspectRatio, maintainAspectRatio }, width, height, _aspectRatio } = this;
if (!isNullOrUndef(aspectRatio)) {
return aspectRatio;
}
if (maintainAspectRatio && _aspectRatio) {
return _aspectRatio;
}
return height ? width / height : null;
}
get data() {
return this.config.data;
}
set data(data) {
this.config.data = data;
}
get options() {
return this._options;
}
set options(options) {
this.config.options = options;
}
get registry() {
return registry;
}
_initialize() {
this.notifyPlugins("beforeInit");
if (this.options.responsive) {
this.resize();
} else {
retinaScale(this, this.options.devicePixelRatio);
}
this.bindEvents();
this.notifyPlugins("afterInit");
return this;
}
clear() {
clearCanvas(this.canvas, this.ctx);
return this;
}
stop() {
animator.stop(this);
return this;
}
resize(width, height) {
if (!animator.running(this)) {
this._resize(width, height);
} else {
this._resizeBeforeDraw = {
width,
height
};
}
}
_resize(width, height) {
const options = this.options;
const canvas = this.canvas;
const aspectRatio = options.maintainAspectRatio && this.aspectRatio;
const newSize = this.platform.getMaximumSize(canvas, width, height, aspectRatio);
const newRatio = options.devicePixelRatio || this.platform.getDevicePixelRatio();
const mode = this.width ? "resize" : "attach";
this.width = newSize.width;
this.height = newSize.height;
this._aspectRatio = this.aspectRatio;
if (!retinaScale(this, newRatio, true)) {
return;
}
this.notifyPlugins("resize", {
size: newSize
});
callback(options.onResize, [
this,
newSize
], this);
if (this.attached) {
if (this._doResize(mode)) {
this.render();
}
}
}
ensureScalesHaveIDs() {
const options = this.options;
const scalesOptions = options.scales || {};
each2(scalesOptions, (axisOptions, axisID) => {
axisOptions.id = axisID;
});
}
buildOrUpdateScales() {
const options = this.options;
const scaleOpts = options.scales;
const scales = this.scales;
const updated = Object.keys(scales).reduce((obj, id) => {
obj[id] = false;
return obj;
}, {});
let items = [];
if (scaleOpts) {
items = items.concat(Object.keys(scaleOpts).map((id) => {
const scaleOptions = scaleOpts[id];
const axis = determineAxis(id, scaleOptions);
const isRadial = axis === "r";
const isHorizontal = axis === "x";
return {
options: scaleOptions,
dposition: isRadial ? "chartArea" : isHorizontal ? "bottom" : "left",
dtype: isRadial ? "radialLinear" : isHorizontal ? "category" : "linear"
};
}));
}
each2(items, (item) => {
const scaleOptions = item.options;
const id = scaleOptions.id;
const axis = determineAxis(id, scaleOptions);
const scaleType = valueOrDefault(scaleOptions.type, item.dtype);
if (scaleOptions.position === void 0 || positionIsHorizontal(scaleOptions.position, axis) !== positionIsHorizontal(item.dposition)) {
scaleOptions.position = item.dposition;
}
updated[id] = true;
let scale = null;
if (id in scales && scales[id].type === scaleType) {
scale = scales[id];
} else {
const scaleClass = registry.getScale(scaleType);
scale = new scaleClass({
id,
type: scaleType,
ctx: this.ctx,
chart: this
});
scales[scale.id] = scale;
}
scale.init(scaleOptions, options);
});
each2(updated, (hasUpdated, id) => {
if (!hasUpdated) {
delete scales[id];
}
});
each2(scales, (scale) => {
layouts.configure(this, scale, scale.options);
layouts.addBox(this, scale);
});
}
_updateMetasets() {
const metasets = this._metasets;
const numData = this.data.datasets.length;
const numMeta = metasets.length;
metasets.sort((a, b) => a.index - b.index);
if (numMeta > numData) {
for (let i = numData; i < numMeta; ++i) {
this._destroyDatasetMeta(i);
}
metasets.splice(numData, numMeta - numData);
}
this._sortedMetasets = metasets.slice(0).sort(compare2Level("order", "index"));
}
_removeUnreferencedMetasets() {
const { _metasets: metasets, data: { datasets } } = this;
if (metasets.length > datasets.length) {
delete this._stacks;
}
metasets.forEach((meta, index) => {
if (datasets.filter((x) => x === meta._dataset).length === 0) {
this._destroyDatasetMeta(index);
}
});
}
buildOrUpdateControllers() {
const newControllers = [];
const datasets = this.data.datasets;
let i, ilen;
this._removeUnreferencedMetasets();
for (i = 0, ilen = datasets.length; i < ilen; i++) {
const dataset = datasets[i];
let meta = this.getDatasetMeta(i);
const type = dataset.type || this.config.type;
if (meta.type && meta.type !== type) {
this._destroyDatasetMeta(i);
meta = this.getDatasetMeta(i);
}
meta.type = type;
meta.indexAxis = dataset.indexAxis || getIndexAxis(type, this.options);
meta.order = dataset.order || 0;
meta.index = i;
meta.label = "" + dataset.label;
meta.visible = this.isDatasetVisible(i);
if (meta.controller) {
meta.controller.updateIndex(i);
meta.controller.linkScales();
} else {
const ControllerClass = registry.getController(type);
const { datasetElementType, dataElementType } = defaults.datasets[type];
Object.assign(ControllerClass, {
dataElementType: registry.getElement(dataElementType),
datasetElementType: datasetElementType && registry.getElement(datasetElementType)
});
meta.controller = new ControllerClass(this, i);
newControllers.push(meta.controller);
}
}
this._updateMetasets();
return newControllers;
}
_resetElements() {
each2(this.data.datasets, (dataset, datasetIndex2) => {
this.getDatasetMeta(datasetIndex2).controller.reset();
}, this);
}
reset() {
this._resetElements();
this.notifyPlugins("reset");
}
update(mode) {
const config = this.config;
config.update();
const options = this._options = config.createResolver(config.chartOptionScopes(), this.getContext());
const animsDisabled = this._animationsDisabled = !options.animation;
this._updateScales();
this._checkEventBindings();
this._updateHiddenIndices();
this._plugins.invalidate();
if (this.notifyPlugins("beforeUpdate", {
mode,
cancelable: true
}) === false) {
return;
}
const newControllers = this.buildOrUpdateControllers();
this.notifyPlugins("beforeElementsUpdate");
let minPadding = 0;
for (let i = 0, ilen = this.data.datasets.length; i < ilen; i++) {
const { controller } = this.getDatasetMeta(i);
const reset = !animsDisabled && newControllers.indexOf(controller) === -1;
controller.buildOrUpdateElements(reset);
minPadding = Math.max(+controller.getMaxOverflow(), minPadding);
}
minPadding = this._minPadding = options.layout.autoPadding ? minPadding : 0;
this._updateLayout(minPadding);
if (!animsDisabled) {
each2(newControllers, (controller) => {
controller.reset();
});
}
this._updateDatasets(mode);
this.notifyPlugins("afterUpdate", {
mode
});
this._layers.sort(compare2Level("z", "_idx"));
const { _active, _lastEvent } = this;
if (_lastEvent) {
this._eventHandler(_lastEvent, true);
} else if (_active.length) {
this._updateHoverStyles(_active, _active, true);
}
this.render();
}
_updateScales() {
each2(this.scales, (scale) => {
layouts.removeBox(this, scale);
});
this.ensureScalesHaveIDs();
this.buildOrUpdateScales();
}
_checkEventBindings() {
const options = this.options;
const existingEvents = new Set(Object.keys(this._listeners));
const newEvents = new Set(options.events);
if (!setsEqual(existingEvents, newEvents) || !!this._responsiveListeners !== options.responsive) {
this.unbindEvents();
this.bindEvents();
}
}
_updateHiddenIndices() {
const { _hiddenIndices } = this;
const changes = this._getUniformDataChanges() || [];
for (const { method, start: start2, count } of changes) {
const move = method === "_removeElements" ? -count : count;
moveNumericKeys(_hiddenIndices, start2, move);
}
}
_getUniformDataChanges() {
const _dataChanges = this._dataChanges;
if (!_dataChanges || !_dataChanges.length) {
return;
}
this._dataChanges = [];
const datasetCount = this.data.datasets.length;
const makeSet = (idx) => new Set(_dataChanges.filter((c) => c[0] === idx).map((c, i) => i + "," + c.splice(1).join(",")));
const changeSet = makeSet(0);
for (let i = 1; i < datasetCount; i++) {
if (!setsEqual(changeSet, makeSet(i))) {
return;
}
}
return Array.from(changeSet).map((c) => c.split(",")).map((a) => ({
method: a[1],
start: +a[2],
count: +a[3]
}));
}
_updateLayout(minPadding) {
if (this.notifyPlugins("beforeLayout", {
cancelable: true
}) === false) {
return;
}
layouts.update(this, this.width, this.height, minPadding);
const area = this.chartArea;
const noArea = area.width <= 0 || area.height <= 0;
this._layers = [];
each2(this.boxes, (box) => {
if (noArea && box.position === "chartArea") {
return;
}
if (box.configure) {
box.configure();
}
this._layers.push(...box._layers());
}, this);
this._layers.forEach((item, index) => {
item._idx = index;
});
this.notifyPlugins("afterLayout");
}
_updateDatasets(mode) {
if (this.notifyPlugins("beforeDatasetsUpdate", {
mode,
cancelable: true
}) === false) {
return;
}
for (let i = 0, ilen = this.data.datasets.length; i < ilen; ++i) {
this.getDatasetMeta(i).controller.configure();
}
for (let i1 = 0, ilen1 = this.data.datasets.length; i1 < ilen1; ++i1) {
this._updateDataset(i1, isFunction(mode) ? mode({
datasetIndex: i1
}) : mode);
}
this.notifyPlugins("afterDatasetsUpdate", {
mode
});
}
_updateDataset(index, mode) {
const meta = this.getDatasetMeta(index);
const args = {
meta,
index,
mode,
cancelable: true
};
if (this.notifyPlugins("beforeDatasetUpdate", args) === false) {
return;
}
meta.controller._update(mode);
args.cancelable = false;
this.notifyPlugins("afterDatasetUpdate", args);
}
render() {
if (this.notifyPlugins("beforeRender", {
cancelable: true
}) === false) {
return;
}
if (animator.has(this)) {
if (this.attached && !animator.running(this)) {
animator.start(this);
}
} else {
this.draw();
onAnimationsComplete({
chart: this
});
}
}
draw() {
let i;
if (this._resizeBeforeDraw) {
const { width, height } = this._resizeBeforeDraw;
this._resize(width, height);
this._resizeBeforeDraw = null;
}
this.clear();
if (this.width <= 0 || this.height <= 0) {
return;
}
if (this.notifyPlugins("beforeDraw", {
cancelable: true
}) === false) {
return;
}
const layers = this._layers;
for (i = 0; i < layers.length && layers[i].z <= 0; ++i) {
layers[i].draw(this.chartArea);
}
this._drawDatasets();
for (; i < layers.length; ++i) {
layers[i].draw(this.chartArea);
}
this.notifyPlugins("afterDraw");
}
_getSortedDatasetMetas(filterVisible) {
const metasets = this._sortedMetasets;
const result = [];
let i, ilen;
for (i = 0, ilen = metasets.length; i < ilen; ++i) {
const meta = metasets[i];
if (!filterVisible || meta.visible) {
result.push(meta);
}
}
return result;
}
getSortedVisibleDatasetMetas() {
return this._getSortedDatasetMetas(true);
}
_drawDatasets() {
if (this.notifyPlugins("beforeDatasetsDraw", {
cancelable: true
}) === false) {
return;
}
const metasets = this.getSortedVisibleDatasetMetas();
for (let i = metasets.length - 1; i >= 0; --i) {
this._drawDataset(metasets[i]);
}
this.notifyPlugins("afterDatasetsDraw");
}
_drawDataset(meta) {
const ctx = this.ctx;
const clip = meta._clip;
const useClip = !clip.disabled;
const area = getDatasetArea(meta) || this.chartArea;
const args = {
meta,
index: meta.index,
cancelable: true
};
if (this.notifyPlugins("beforeDatasetDraw", args) === false) {
return;
}
if (useClip) {
clipArea(ctx, {
left: clip.left === false ? 0 : area.left - clip.left,
right: clip.right === false ? this.width : area.right + clip.right,
top: clip.top === false ? 0 : area.top - clip.top,
bottom: clip.bottom === false ? this.height : area.bottom + clip.bottom
});
}
meta.controller.draw();
if (useClip) {
unclipArea(ctx);
}
args.cancelable = false;
this.notifyPlugins("afterDatasetDraw", args);
}
isPointInArea(point) {
return _isPointInArea(point, this.chartArea, this._minPadding);
}
getElementsAtEventForMode(e, mode, options, useFinalPosition) {
const method = Interaction.modes[mode];
if (typeof method === "function") {
return method(this, e, options, useFinalPosition);
}
return [];
}
getDatasetMeta(datasetIndex2) {
const dataset = this.data.datasets[datasetIndex2];
const metasets = this._metasets;
let meta = metasets.filter((x) => x && x._dataset === dataset).pop();
if (!meta) {
meta = {
type: null,
data: [],
dataset: null,
controller: null,
hidden: null,
xAxisID: null,
yAxisID: null,
order: dataset && dataset.order || 0,
index: datasetIndex2,
_dataset: dataset,
_parsed: [],
_sorted: false
};
metasets.push(meta);
}
return meta;
}
getContext() {
return this.$context || (this.$context = createContext(null, {
chart: this,
type: "chart"
}));
}
getVisibleDatasetCount() {
return this.getSortedVisibleDatasetMetas().length;
}
isDatasetVisible(datasetIndex2) {
const dataset = this.data.datasets[datasetIndex2];
if (!dataset) {
return false;
}
const meta = this.getDatasetMeta(datasetIndex2);
return typeof meta.hidden === "boolean" ? !meta.hidden : !dataset.hidden;
}
setDatasetVisibility(datasetIndex2, visible) {
const meta = this.getDatasetMeta(datasetIndex2);
meta.hidden = !visible;
}
toggleDataVisibility(index) {
this._hiddenIndices[index] = !this._hiddenIndices[index];
}
getDataVisibility(index) {
return !this._hiddenIndices[index];
}
_updateVisibility(datasetIndex2, dataIndex, visible) {
const mode = visible ? "show" : "hide";
const meta = this.getDatasetMeta(datasetIndex2);
const anims = meta.controller._resolveAnimations(void 0, mode);
if (defined(dataIndex)) {
meta.data[dataIndex].hidden = !visible;
this.update();
} else {
this.setDatasetVisibility(datasetIndex2, visible);
anims.update(meta, {
visible
});
this.update((ctx) => ctx.datasetIndex === datasetIndex2 ? mode : void 0);
}
}
hide(datasetIndex2, dataIndex) {
this._updateVisibility(datasetIndex2, dataIndex, false);
}
show(datasetIndex2, dataIndex) {
this._updateVisibility(datasetIndex2, dataIndex, true);
}
_destroyDatasetMeta(datasetIndex2) {
const meta = this._metasets[datasetIndex2];
if (meta && meta.controller) {
meta.controller._destroy();
}
delete this._metasets[datasetIndex2];
}
_stop() {
let i, ilen;
this.stop();
animator.remove(this);
for (i = 0, ilen = this.data.datasets.length; i < ilen; ++i) {
this._destroyDatasetMeta(i);
}
}
destroy() {
this.notifyPlugins("beforeDestroy");
const { canvas, ctx } = this;
this._stop();
this.config.clearCache();
if (canvas) {
this.unbindEvents();
clearCanvas(canvas, ctx);
this.platform.releaseContext(ctx);
this.canvas = null;
this.ctx = null;
}
delete instances[this.id];
this.notifyPlugins("afterDestroy");
}
toBase64Image(...args) {
return this.canvas.toDataURL(...args);
}
bindEvents() {
this.bindUserEvents();
if (this.options.responsive) {
this.bindResponsiveEvents();
} else {
this.attached = true;
}
}
bindUserEvents() {
const listeners = this._listeners;
const platform = this.platform;
const _add = (type, listener2) => {
platform.addEventListener(this, type, listener2);
listeners[type] = listener2;
};
const listener = (e, x, y) => {
e.offsetX = x;
e.offsetY = y;
this._eventHandler(e);
};
each2(this.options.events, (type) => _add(type, listener));
}
bindResponsiveEvents() {
if (!this._responsiveListeners) {
this._responsiveListeners = {};
}
const listeners = this._responsiveListeners;
const platform = this.platform;
const _add = (type, listener2) => {
platform.addEventListener(this, type, listener2);
listeners[type] = listener2;
};
const _remove = (type, listener2) => {
if (listeners[type]) {
platform.removeEventListener(this, type, listener2);
delete listeners[type];
}
};
const listener = (width, height) => {
if (this.canvas) {
this.resize(width, height);
}
};
let detached;
const attached = () => {
_remove("attach", attached);
this.attached = true;
this.resize();
_add("resize", listener);
_add("detach", detached);
};
detached = () => {
this.attached = false;
_remove("resize", listener);
this._stop();
this._resize(0, 0);
_add("attach", attached);
};
if (platform.isAttached(this.canvas)) {
attached();
} else {
detached();
}
}
unbindEvents() {
each2(this._listeners, (listener, type) => {
this.platform.removeEventListener(this, type, listener);
});
this._listeners = {};
each2(this._responsiveListeners, (listener, type) => {
this.platform.removeEventListener(this, type, listener);
});
this._responsiveListeners = void 0;
}
updateHoverStyle(items, mode, enabled) {
const prefix = enabled ? "set" : "remove";
let meta, item, i, ilen;
if (mode === "dataset") {
meta = this.getDatasetMeta(items[0].datasetIndex);
meta.controller["_" + prefix + "DatasetHoverStyle"]();
}
for (i = 0, ilen = items.length; i < ilen; ++i) {
item = items[i];
const controller = item && this.getDatasetMeta(item.datasetIndex).controller;
if (controller) {
controller[prefix + "HoverStyle"](item.element, item.datasetIndex, item.index);
}
}
}
getActiveElements() {
return this._active || [];
}
setActiveElements(activeElements) {
const lastActive = this._active || [];
const active = activeElements.map(({ datasetIndex: datasetIndex2, index }) => {
const meta = this.getDatasetMeta(datasetIndex2);
if (!meta) {
throw new Error("No dataset found at index " + datasetIndex2);
}
return {
datasetIndex: datasetIndex2,
element: meta.data[index],
index
};
});
const changed = !_elementsEqual(active, lastActive);
if (changed) {
this._active = active;
this._lastEvent = null;
this._updateHoverStyles(active, lastActive);
}
}
notifyPlugins(hook, args, filter) {
return this._plugins.notify(this, hook, args, filter);
}
isPluginEnabled(pluginId) {
return this._plugins._cache.filter((p) => p.plugin.id === pluginId).length === 1;
}
_updateHoverStyles(active, lastActive, replay) {
const hoverOptions = this.options.hover;
const diff = (a, b) => a.filter((x) => !b.some((y) => x.datasetIndex === y.datasetIndex && x.index === y.index));
const deactivated = diff(lastActive, active);
const activated = replay ? active : diff(active, lastActive);
if (deactivated.length) {
this.updateHoverStyle(deactivated, hoverOptions.mode, false);
}
if (activated.length && hoverOptions.mode) {
this.updateHoverStyle(activated, hoverOptions.mode, true);
}
}
_eventHandler(e, replay) {
const args = {
event: e,
replay,
cancelable: true,
inChartArea: this.isPointInArea(e)
};
const eventFilter = (plugin2) => (plugin2.options.events || this.options.events).includes(e.native.type);
if (this.notifyPlugins("beforeEvent", args, eventFilter) === false) {
return;
}
const changed = this._handleEvent(e, replay, args.inChartArea);
args.cancelable = false;
this.notifyPlugins("afterEvent", args, eventFilter);
if (changed || args.changed) {
this.render();
}
return this;
}
_handleEvent(e, replay, inChartArea) {
const { _active: lastActive = [], options } = this;
const useFinalPosition = replay;
const active = this._getActiveElements(e, lastActive, inChartArea, useFinalPosition);
const isClick = _isClickEvent(e);
const lastEvent = determineLastEvent(e, this._lastEvent, inChartArea, isClick);
if (inChartArea) {
this._lastEvent = null;
callback(options.onHover, [
e,
active,
this
], this);
if (isClick) {
callback(options.onClick, [
e,
active,
this
], this);
}
}
const changed = !_elementsEqual(active, lastActive);
if (changed || replay) {
this._active = active;
this._updateHoverStyles(active, lastActive, replay);
}
this._lastEvent = lastEvent;
return changed;
}
_getActiveElements(e, lastActive, inChartArea, useFinalPosition) {
if (e.type === "mouseout") {
return [];
}
if (!inChartArea) {
return lastActive;
}
const hoverOptions = this.options.hover;
return this.getElementsAtEventForMode(e, hoverOptions.mode, hoverOptions, useFinalPosition);
}
};
__publicField(Chart, "defaults", defaults);
__publicField(Chart, "instances", instances);
__publicField(Chart, "overrides", overrides);
__publicField(Chart, "registry", registry);
__publicField(Chart, "version", version);
__publicField(Chart, "getChart", getChart);
function invalidatePlugins() {
return each2(Chart.instances, (chart) => chart._plugins.invalidate());
}
function setStyle(ctx, options, style = options) {
ctx.lineCap = valueOrDefault(style.borderCapStyle, options.borderCapStyle);
ctx.setLineDash(valueOrDefault(style.borderDash, options.borderDash));
ctx.lineDashOffset = valueOrDefault(style.borderDashOffset, options.borderDashOffset);
ctx.lineJoin = valueOrDefault(style.borderJoinStyle, options.borderJoinStyle);
ctx.lineWidth = valueOrDefault(style.borderWidth, options.borderWidth);
ctx.strokeStyle = valueOrDefault(style.borderColor, options.borderColor);
}
function lineTo(ctx, previous, target) {
ctx.lineTo(target.x, target.y);
}
function getLineMethod(options) {
if (options.stepped) {
return _steppedLineTo;
}
if (options.tension || options.cubicInterpolationMode === "monotone") {
return _bezierCurveTo;
}
return lineTo;
}
function pathVars(points, segment, params = {}) {
const count = points.length;
const { start: paramsStart = 0, end: paramsEnd = count - 1 } = params;
const { start: segmentStart, end: segmentEnd } = segment;
const start2 = Math.max(paramsStart, segmentStart);
const end2 = Math.min(paramsEnd, segmentEnd);
const outside = paramsStart < segmentStart && paramsEnd < segmentStart || paramsStart > segmentEnd && paramsEnd > segmentEnd;
return {
count,
start: start2,
loop: segment.loop,
ilen: end2 < start2 && !outside ? count + end2 - start2 : end2 - start2
};
}
function pathSegment(ctx, line, segment, params) {
const { points, options } = line;
const { count, start: start2, loop, ilen } = pathVars(points, segment, params);
const lineMethod = getLineMethod(options);
let { move = true, reverse } = params || {};
let i, point, prev;
for (i = 0; i <= ilen; ++i) {
point = points[(start2 + (reverse ? ilen - i : i)) % count];
if (point.skip) {
continue;
} else if (move) {
ctx.moveTo(point.x, point.y);
move = false;
} else {
lineMethod(ctx, prev, point, reverse, options.stepped);
}
prev = point;
}
if (loop) {
point = points[(start2 + (reverse ? ilen : 0)) % count];
lineMethod(ctx, prev, point, reverse, options.stepped);
}
return !!loop;
}
function fastPathSegment(ctx, line, segment, params) {
const points = line.points;
const { count, start: start2, ilen } = pathVars(points, segment, params);
const { move = true, reverse } = params || {};
let avgX = 0;
let countX = 0;
let i, point, prevX, minY, maxY, lastY;
const pointIndex = (index) => (start2 + (reverse ? ilen - index : index)) % count;
const drawX = () => {
if (minY !== maxY) {
ctx.lineTo(avgX, maxY);
ctx.lineTo(avgX, minY);
ctx.lineTo(avgX, lastY);
}
};
if (move) {
point = points[pointIndex(0)];
ctx.moveTo(point.x, point.y);
}
for (i = 0; i <= ilen; ++i) {
point = points[pointIndex(i)];
if (point.skip) {
continue;
}
const x = point.x;
const y = point.y;
const truncX = x | 0;
if (truncX === prevX) {
if (y < minY) {
minY = y;
} else if (y > maxY) {
maxY = y;
}
avgX = (countX * avgX + x) / ++countX;
} else {
drawX();
ctx.lineTo(x, y);
prevX = truncX;
countX = 0;
minY = maxY = y;
}
lastY = y;
}
drawX();
}
function _getSegmentMethod(line) {
const opts = line.options;
const borderDash = opts.borderDash && opts.borderDash.length;
const useFastPath = !line._decimated && !line._loop && !opts.tension && opts.cubicInterpolationMode !== "monotone" && !opts.stepped && !borderDash;
return useFastPath ? fastPathSegment : pathSegment;
}
function _getInterpolationMethod(options) {
if (options.stepped) {
return _steppedInterpolation;
}
if (options.tension || options.cubicInterpolationMode === "monotone") {
return _bezierInterpolation;
}
return _pointInLine;
}
function strokePathWithCache(ctx, line, start2, count) {
let path = line._path;
if (!path) {
path = line._path = new Path2D();
if (line.path(path, start2, count)) {
path.closePath();
}
}
setStyle(ctx, line.options);
ctx.stroke(path);
}
function strokePathDirect(ctx, line, start2, count) {
const { segments, options } = line;
const segmentMethod = _getSegmentMethod(line);
for (const segment of segments) {
setStyle(ctx, options, segment.style);
ctx.beginPath();
if (segmentMethod(ctx, line, segment, {
start: start2,
end: start2 + count - 1
})) {
ctx.closePath();
}
ctx.stroke();
}
}
var usePath2D = typeof Path2D === "function";
function draw(ctx, line, start2, count) {
if (usePath2D && !line.options.segment) {
strokePathWithCache(ctx, line, start2, count);
} else {
strokePathDirect(ctx, line, start2, count);
}
}
var LineElement = class extends Element2 {
constructor(cfg) {
super();
this.animated = true;
this.options = void 0;
this._chart = void 0;
this._loop = void 0;
this._fullLoop = void 0;
this._path = void 0;
this._points = void 0;
this._segments = void 0;
this._decimated = false;
this._pointsUpdated = false;
this._datasetIndex = void 0;
if (cfg) {
Object.assign(this, cfg);
}
}
updateControlPoints(chartArea, indexAxis) {
const options = this.options;
if ((options.tension || options.cubicInterpolationMode === "monotone") && !options.stepped && !this._pointsUpdated) {
const loop = options.spanGaps ? this._loop : this._fullLoop;
_updateBezierControlPoints(this._points, options, chartArea, loop, indexAxis);
this._pointsUpdated = true;
}
}
set points(points) {
this._points = points;
delete this._segments;
delete this._path;
this._pointsUpdated = false;
}
get points() {
return this._points;
}
get segments() {
return this._segments || (this._segments = _computeSegments(this, this.options.segment));
}
first() {
const segments = this.segments;
const points = this.points;
return segments.length && points[segments[0].start];
}
last() {
const segments = this.segments;
const points = this.points;
const count = segments.length;
return count && points[segments[count - 1].end];
}
interpolate(point, property) {
const options = this.options;
const value = point[property];
const points = this.points;
const segments = _boundSegments(this, {
property,
start: value,
end: value
});
if (!segments.length) {
return;
}
const result = [];
const _interpolate = _getInterpolationMethod(options);
let i, ilen;
for (i = 0, ilen = segments.length; i < ilen; ++i) {
const { start: start2, end: end2 } = segments[i];
const p1 = points[start2];
const p2 = points[end2];
if (p1 === p2) {
result.push(p1);
continue;
}
const t = Math.abs((value - p1[property]) / (p2[property] - p1[property]));
const interpolated = _interpolate(p1, p2, t, options.stepped);
interpolated[property] = point[property];
result.push(interpolated);
}
return result.length === 1 ? result[0] : result;
}
pathSegment(ctx, segment, params) {
const segmentMethod = _getSegmentMethod(this);
return segmentMethod(ctx, this, segment, params);
}
path(ctx, start2, count) {
const segments = this.segments;
const segmentMethod = _getSegmentMethod(this);
let loop = this._loop;
start2 = start2 || 0;
count = count || this.points.length - start2;
for (const segment of segments) {
loop &= segmentMethod(ctx, this, segment, {
start: start2,
end: start2 + count - 1
});
}
return !!loop;
}
draw(ctx, chartArea, start2, count) {
const options = this.options || {};
const points = this.points || [];
if (points.length && options.borderWidth) {
ctx.save();
draw(ctx, this, start2, count);
ctx.restore();
}
if (this.animated) {
this._pointsUpdated = false;
this._path = void 0;
}
}
};
__publicField(LineElement, "id", "line");
__publicField(LineElement, "defaults", {
borderCapStyle: "butt",
borderDash: [],
borderDashOffset: 0,
borderJoinStyle: "miter",
borderWidth: 3,
capBezierPoints: true,
cubicInterpolationMode: "default",
fill: false,
spanGaps: false,
stepped: false,
tension: 0
});
__publicField(LineElement, "defaultRoutes", {
backgroundColor: "backgroundColor",
borderColor: "borderColor"
});
__publicField(LineElement, "descriptors", {
_scriptable: true,
_indexable: (name2) => name2 !== "borderDash" && name2 !== "fill"
});
function inRange$1(el, pos, axis, useFinalPosition) {
const options = el.options;
const { [axis]: value } = el.getProps([
axis
], useFinalPosition);
return Math.abs(pos - value) < options.radius + options.hitRadius;
}
var PointElement = class extends Element2 {
constructor(cfg) {
super();
this.options = void 0;
this.parsed = void 0;
this.skip = void 0;
this.stop = void 0;
if (cfg) {
Object.assign(this, cfg);
}
}
inRange(mouseX, mouseY, useFinalPosition) {
const options = this.options;
const { x, y } = this.getProps([
"x",
"y"
], useFinalPosition);
return Math.pow(mouseX - x, 2) + Math.pow(mouseY - y, 2) < Math.pow(options.hitRadius + options.radius, 2);
}
inXRange(mouseX, useFinalPosition) {
return inRange$1(this, mouseX, "x", useFinalPosition);
}
inYRange(mouseY, useFinalPosition) {
return inRange$1(this, mouseY, "y", useFinalPosition);
}
getCenterPoint(useFinalPosition) {
const { x, y } = this.getProps([
"x",
"y"
], useFinalPosition);
return {
x,
y
};
}
size(options) {
options = options || this.options || {};
let radius = options.radius || 0;
radius = Math.max(radius, radius && options.hoverRadius || 0);
const borderWidth = radius && options.borderWidth || 0;
return (radius + borderWidth) * 2;
}
draw(ctx, area) {
const options = this.options;
if (this.skip || options.radius < 0.1 || !_isPointInArea(this, area, this.size(options) / 2)) {
return;
}
ctx.strokeStyle = options.borderColor;
ctx.lineWidth = options.borderWidth;
ctx.fillStyle = options.backgroundColor;
drawPoint(ctx, options, this.x, this.y);
}
getRange() {
const options = this.options || {};
return options.radius + options.hitRadius;
}
};
__publicField(PointElement, "id", "point");
/**
* @type {any}
*/
__publicField(PointElement, "defaults", {
borderWidth: 1,
hitRadius: 1,
hoverBorderWidth: 1,
hoverRadius: 4,
pointStyle: "circle",
radius: 3,
rotation: 0
});
/**
* @type {any}
*/
__publicField(PointElement, "defaultRoutes", {
backgroundColor: "backgroundColor",
borderColor: "borderColor"
});
function getBarBounds(bar, useFinalPosition) {
const { x, y, base, width, height } = bar.getProps([
"x",
"y",
"base",
"width",
"height"
], useFinalPosition);
let left2, right2, top2, bottom2, half;
if (bar.horizontal) {
half = height / 2;
left2 = Math.min(x, base);
right2 = Math.max(x, base);
top2 = y - half;
bottom2 = y + half;
} else {
half = width / 2;
left2 = x - half;
right2 = x + half;
top2 = Math.min(y, base);
bottom2 = Math.max(y, base);
}
return {
left: left2,
top: top2,
right: right2,
bottom: bottom2
};
}
function skipOrLimit(skip2, value, min2, max2) {
return skip2 ? 0 : _limitValue(value, min2, max2);
}
function parseBorderWidth(bar, maxW, maxH) {
const value = bar.options.borderWidth;
const skip2 = bar.borderSkipped;
const o = toTRBL(value);
return {
t: skipOrLimit(skip2.top, o.top, 0, maxH),
r: skipOrLimit(skip2.right, o.right, 0, maxW),
b: skipOrLimit(skip2.bottom, o.bottom, 0, maxH),
l: skipOrLimit(skip2.left, o.left, 0, maxW)
};
}
function parseBorderRadius(bar, maxW, maxH) {
const { enableBorderRadius } = bar.getProps([
"enableBorderRadius"
]);
const value = bar.options.borderRadius;
const o = toTRBLCorners(value);
const maxR = Math.min(maxW, maxH);
const skip2 = bar.borderSkipped;
const enableBorder = enableBorderRadius || isObject(value);
return {
topLeft: skipOrLimit(!enableBorder || skip2.top || skip2.left, o.topLeft, 0, maxR),
topRight: skipOrLimit(!enableBorder || skip2.top || skip2.right, o.topRight, 0, maxR),
bottomLeft: skipOrLimit(!enableBorder || skip2.bottom || skip2.left, o.bottomLeft, 0, maxR),
bottomRight: skipOrLimit(!enableBorder || skip2.bottom || skip2.right, o.bottomRight, 0, maxR)
};
}
function boundingRects(bar) {
const bounds = getBarBounds(bar);
const width = bounds.right - bounds.left;
const height = bounds.bottom - bounds.top;
const border = parseBorderWidth(bar, width / 2, height / 2);
const radius = parseBorderRadius(bar, 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(bar, x, y, useFinalPosition) {
const skipX = x === null;
const skipY = y === null;
const skipBoth = skipX && skipY;
const bounds = bar && !skipBoth && getBarBounds(bar, useFinalPosition);
return bounds && (skipX || _isBetween(x, bounds.left, bounds.right)) && (skipY || _isBetween(y, bounds.top, bounds.bottom));
}
function hasRadius(radius) {
return radius.topLeft || radius.topRight || radius.bottomLeft || radius.bottomRight;
}
function addNormalRectPath(ctx, rect) {
ctx.rect(rect.x, rect.y, rect.w, rect.h);
}
function inflateRect(rect, amount, refRect = {}) {
const x = rect.x !== refRect.x ? -amount : 0;
const y = rect.y !== refRect.y ? -amount : 0;
const w = (rect.x + rect.w !== refRect.x + refRect.w ? amount : 0) - x;
const h = (rect.y + rect.h !== refRect.y + refRect.h ? amount : 0) - y;
return {
x: rect.x + x,
y: rect.y + y,
w: rect.w + w,
h: rect.h + h,
radius: rect.radius
};
}
var BarElement = class extends Element2 {
constructor(cfg) {
super();
this.options = void 0;
this.horizontal = void 0;
this.base = void 0;
this.width = void 0;
this.height = void 0;
this.inflateAmount = void 0;
if (cfg) {
Object.assign(this, cfg);
}
}
draw(ctx) {
const { inflateAmount, options: { borderColor, backgroundColor } } = this;
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, inflateRect(outer, inflateAmount, inner));
ctx.clip();
addRectPath(ctx, inflateRect(inner, -inflateAmount, outer));
ctx.fillStyle = borderColor;
ctx.fill("evenodd");
}
ctx.beginPath();
addRectPath(ctx, inflateRect(inner, inflateAmount));
ctx.fillStyle = backgroundColor;
ctx.fill();
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, base, horizontal } = this.getProps([
"x",
"y",
"base",
"horizontal"
], useFinalPosition);
return {
x: horizontal ? (x + base) / 2 : x,
y: horizontal ? y : (y + base) / 2
};
}
getRange(axis) {
return axis === "x" ? this.width / 2 : this.height / 2;
}
};
__publicField(BarElement, "id", "bar");
__publicField(BarElement, "defaults", {
borderSkipped: "start",
borderWidth: 0,
borderRadius: 0,
inflateAmount: "auto",
pointStyle: void 0
});
__publicField(BarElement, "defaultRoutes", {
backgroundColor: "backgroundColor",
borderColor: "borderColor"
});
var BORDER_COLORS = [
"rgb(54, 162, 235)",
"rgb(255, 99, 132)",
"rgb(255, 159, 64)",
"rgb(255, 205, 86)",
"rgb(75, 192, 192)",
"rgb(153, 102, 255)",
"rgb(201, 203, 207)"
// grey
];
var BACKGROUND_COLORS = /* @__PURE__ */ BORDER_COLORS.map((color2) => color2.replace("rgb(", "rgba(").replace(")", ", 0.5)"));
function getBorderColor(i) {
return BORDER_COLORS[i % BORDER_COLORS.length];
}
function getBackgroundColor(i) {
return BACKGROUND_COLORS[i % BACKGROUND_COLORS.length];
}
function colorizeDefaultDataset(dataset, i) {
dataset.borderColor = getBorderColor(i);
dataset.backgroundColor = getBackgroundColor(i);
return ++i;
}
function colorizeDoughnutDataset(dataset, i) {
dataset.backgroundColor = dataset.data.map(() => getBorderColor(i++));
return i;
}
function colorizePolarAreaDataset(dataset, i) {
dataset.backgroundColor = dataset.data.map(() => getBackgroundColor(i++));
return i;
}
function getColorizer(chart) {
let i = 0;
return (dataset, datasetIndex2) => {
const controller = chart.getDatasetMeta(datasetIndex2).controller;
if (controller instanceof DoughnutController) {
i = colorizeDoughnutDataset(dataset, i);
} else if (controller instanceof PolarAreaController) {
i = colorizePolarAreaDataset(dataset, i);
} else if (controller) {
i = colorizeDefaultDataset(dataset, i);
}
};
}
function containsColorsDefinitions(descriptors2) {
let k;
for (k in descriptors2) {
if (descriptors2[k].borderColor || descriptors2[k].backgroundColor) {
return true;
}
}
return false;
}
function containsColorsDefinition(descriptor) {
return descriptor && (descriptor.borderColor || descriptor.backgroundColor);
}
var plugin_colors = {
id: "colors",
defaults: {
enabled: true,
forceOverride: false
},
beforeLayout(chart, _args, options) {
if (!options.enabled) {
return;
}
const { data: { datasets }, options: chartOptions } = chart.config;
const { elements } = chartOptions;
if (!options.forceOverride && (containsColorsDefinitions(datasets) || containsColorsDefinition(chartOptions) || elements && containsColorsDefinitions(elements))) {
return;
}
const colorizer = getColorizer(chart);
datasets.forEach(colorizer);
}
};
var getBoxSize = (labelOpts, fontSize) => {
let { boxHeight = fontSize, boxWidth = fontSize } = labelOpts;
if (labelOpts.usePointStyle) {
boxHeight = Math.min(boxHeight, fontSize);
boxWidth = labelOpts.pointStyleWidth || Math.min(boxWidth, fontSize);
}
return {
boxWidth,
boxHeight,
itemHeight: Math.max(fontSize, boxHeight)
};
};
var itemsEqual = (a, b) => a !== null && b !== null && a.datasetIndex === b.datasetIndex && a.index === b.index;
var Legend = class extends Element2 {
constructor(config) {
super();
this._added = false;
this.legendHitBoxes = [];
this._hoveredItem = null;
this.doughnutMode = false;
this.chart = config.chart;
this.options = config.options;
this.ctx = config.ctx;
this.legendItems = void 0;
this.columnSizes = void 0;
this.lineWidths = void 0;
this.maxHeight = void 0;
this.maxWidth = void 0;
this.top = void 0;
this.bottom = void 0;
this.left = void 0;
this.right = void 0;
this.height = void 0;
this.width = void 0;
this._margins = void 0;
this.position = void 0;
this.weight = void 0;
this.fullSize = void 0;
}
update(maxWidth, maxHeight, margins) {
this.maxWidth = maxWidth;
this.maxHeight = maxHeight;
this._margins = margins;
this.setDimensions();
this.buildLabels();
this.fit();
}
setDimensions() {
if (this.isHorizontal()) {
this.width = this.maxWidth;
this.left = this._margins.left;
this.right = this.width;
} else {
this.height = this.maxHeight;
this.top = this._margins.top;
this.bottom = this.height;
}
}
buildLabels() {
const labelOpts = this.options.labels || {};
let legendItems = callback(labelOpts.generateLabels, [
this.chart
], this) || [];
if (labelOpts.filter) {
legendItems = legendItems.filter((item) => labelOpts.filter(item, this.chart.data));
}
if (labelOpts.sort) {
legendItems = legendItems.sort((a, b) => labelOpts.sort(a, b, this.chart.data));
}
if (this.options.reverse) {
legendItems.reverse();
}
this.legendItems = legendItems;
}
fit() {
const { options, ctx } = this;
if (!options.display) {
this.width = this.height = 0;
return;
}
const labelOpts = options.labels;
const labelFont = toFont(labelOpts.font);
const fontSize = labelFont.size;
const titleHeight = this._computeTitleHeight();
const { boxWidth, itemHeight } = getBoxSize(labelOpts, fontSize);
let width, height;
ctx.font = labelFont.string;
if (this.isHorizontal()) {
width = this.maxWidth;
height = this._fitRows(titleHeight, fontSize, boxWidth, itemHeight) + 10;
} else {
height = this.maxHeight;
width = this._fitCols(titleHeight, labelFont, boxWidth, itemHeight) + 10;
}
this.width = Math.min(width, options.maxWidth || this.maxWidth);
this.height = Math.min(height, options.maxHeight || this.maxHeight);
}
_fitRows(titleHeight, fontSize, boxWidth, itemHeight) {
const { ctx, maxWidth, options: { labels: { padding } } } = this;
const hitboxes = this.legendHitBoxes = [];
const lineWidths = this.lineWidths = [
0
];
const lineHeight = itemHeight + padding;
let totalHeight = titleHeight;
ctx.textAlign = "left";
ctx.textBaseline = "middle";
let row = -1;
let top2 = -lineHeight;
this.legendItems.forEach((legendItem, i) => {
const itemWidth = boxWidth + fontSize / 2 + ctx.measureText(legendItem.text).width;
if (i === 0 || lineWidths[lineWidths.length - 1] + itemWidth + 2 * padding > maxWidth) {
totalHeight += lineHeight;
lineWidths[lineWidths.length - (i > 0 ? 0 : 1)] = 0;
top2 += lineHeight;
row++;
}
hitboxes[i] = {
left: 0,
top: top2,
row,
width: itemWidth,
height: itemHeight
};
lineWidths[lineWidths.length - 1] += itemWidth + padding;
});
return totalHeight;
}
_fitCols(titleHeight, labelFont, boxWidth, _itemHeight) {
const { ctx, maxHeight, options: { labels: { padding } } } = this;
const hitboxes = this.legendHitBoxes = [];
const columnSizes = this.columnSizes = [];
const heightLimit = maxHeight - titleHeight;
let totalWidth = padding;
let currentColWidth = 0;
let currentColHeight = 0;
let left2 = 0;
let col = 0;
this.legendItems.forEach((legendItem, i) => {
const { itemWidth, itemHeight } = calculateItemSize(boxWidth, labelFont, ctx, legendItem, _itemHeight);
if (i > 0 && currentColHeight + itemHeight + 2 * padding > heightLimit) {
totalWidth += currentColWidth + padding;
columnSizes.push({
width: currentColWidth,
height: currentColHeight
});
left2 += currentColWidth + padding;
col++;
currentColWidth = currentColHeight = 0;
}
hitboxes[i] = {
left: left2,
top: currentColHeight,
col,
width: itemWidth,
height: itemHeight
};
currentColWidth = Math.max(currentColWidth, itemWidth);
currentColHeight += itemHeight + padding;
});
totalWidth += currentColWidth;
columnSizes.push({
width: currentColWidth,
height: currentColHeight
});
return totalWidth;
}
adjustHitBoxes() {
if (!this.options.display) {
return;
}
const titleHeight = this._computeTitleHeight();
const { legendHitBoxes: hitboxes, options: { align, labels: { padding }, rtl } } = this;
const rtlHelper = getRtlAdapter(rtl, this.left, this.width);
if (this.isHorizontal()) {
let row = 0;
let left2 = _alignStartEnd(align, this.left + padding, this.right - this.lineWidths[row]);
for (const hitbox of hitboxes) {
if (row !== hitbox.row) {
row = hitbox.row;
left2 = _alignStartEnd(align, this.left + padding, this.right - this.lineWidths[row]);
}
hitbox.top += this.top + titleHeight + padding;
hitbox.left = rtlHelper.leftForLtr(rtlHelper.x(left2), hitbox.width);
left2 += hitbox.width + padding;
}
} else {
let col = 0;
let top2 = _alignStartEnd(align, this.top + titleHeight + padding, this.bottom - this.columnSizes[col].height);
for (const hitbox1 of hitboxes) {
if (hitbox1.col !== col) {
col = hitbox1.col;
top2 = _alignStartEnd(align, this.top + titleHeight + padding, this.bottom - this.columnSizes[col].height);
}
hitbox1.top = top2;
hitbox1.left += this.left + padding;
hitbox1.left = rtlHelper.leftForLtr(rtlHelper.x(hitbox1.left), hitbox1.width);
top2 += hitbox1.height + padding;
}
}
}
isHorizontal() {
return this.options.position === "top" || this.options.position === "bottom";
}
draw() {
if (this.options.display) {
const ctx = this.ctx;
clipArea(ctx, this);
this._draw();
unclipArea(ctx);
}
}
_draw() {
const { options: opts, columnSizes, lineWidths, ctx } = this;
const { align, labels: labelOpts } = opts;
const defaultColor = defaults.color;
const rtlHelper = getRtlAdapter(opts.rtl, this.left, this.width);
const labelFont = toFont(labelOpts.font);
const { padding } = labelOpts;
const fontSize = labelFont.size;
const halfFontSize = fontSize / 2;
let cursor;
this.drawTitle();
ctx.textAlign = rtlHelper.textAlign("left");
ctx.textBaseline = "middle";
ctx.lineWidth = 0.5;
ctx.font = labelFont.string;
const { boxWidth, boxHeight, itemHeight } = getBoxSize(labelOpts, fontSize);
const drawLegendBox = function(x, y, legendItem) {
if (isNaN(boxWidth) || boxWidth <= 0 || isNaN(boxHeight) || boxHeight < 0) {
return;
}
ctx.save();
const lineWidth = valueOrDefault(legendItem.lineWidth, 1);
ctx.fillStyle = valueOrDefault(legendItem.fillStyle, defaultColor);
ctx.lineCap = valueOrDefault(legendItem.lineCap, "butt");
ctx.lineDashOffset = valueOrDefault(legendItem.lineDashOffset, 0);
ctx.lineJoin = valueOrDefault(legendItem.lineJoin, "miter");
ctx.lineWidth = lineWidth;
ctx.strokeStyle = valueOrDefault(legendItem.strokeStyle, defaultColor);
ctx.setLineDash(valueOrDefault(legendItem.lineDash, []));
if (labelOpts.usePointStyle) {
const drawOptions = {
radius: boxHeight * Math.SQRT2 / 2,
pointStyle: legendItem.pointStyle,
rotation: legendItem.rotation,
borderWidth: lineWidth
};
const centerX = rtlHelper.xPlus(x, boxWidth / 2);
const centerY = y + halfFontSize;
drawPointLegend(ctx, drawOptions, centerX, centerY, labelOpts.pointStyleWidth && boxWidth);
} else {
const yBoxTop = y + Math.max((fontSize - boxHeight) / 2, 0);
const xBoxLeft = rtlHelper.leftForLtr(x, boxWidth);
const borderRadius = toTRBLCorners(legendItem.borderRadius);
ctx.beginPath();
if (Object.values(borderRadius).some((v) => v !== 0)) {
addRoundedRectPath(ctx, {
x: xBoxLeft,
y: yBoxTop,
w: boxWidth,
h: boxHeight,
radius: borderRadius
});
} else {
ctx.rect(xBoxLeft, yBoxTop, boxWidth, boxHeight);
}
ctx.fill();
if (lineWidth !== 0) {
ctx.stroke();
}
}
ctx.restore();
};
const fillText = function(x, y, legendItem) {
renderText(ctx, legendItem.text, x, y + itemHeight / 2, labelFont, {
strikethrough: legendItem.hidden,
textAlign: rtlHelper.textAlign(legendItem.textAlign)
});
};
const isHorizontal = this.isHorizontal();
const titleHeight = this._computeTitleHeight();
if (isHorizontal) {
cursor = {
x: _alignStartEnd(align, this.left + padding, this.right - lineWidths[0]),
y: this.top + padding + titleHeight,
line: 0
};
} else {
cursor = {
x: this.left + padding,
y: _alignStartEnd(align, this.top + titleHeight + padding, this.bottom - columnSizes[0].height),
line: 0
};
}
overrideTextDirection(this.ctx, opts.textDirection);
const lineHeight = itemHeight + padding;
this.legendItems.forEach((legendItem, i) => {
ctx.strokeStyle = legendItem.fontColor;
ctx.fillStyle = legendItem.fontColor;
const textWidth = ctx.measureText(legendItem.text).width;
const textAlign = rtlHelper.textAlign(legendItem.textAlign || (legendItem.textAlign = labelOpts.textAlign));
const width = boxWidth + halfFontSize + textWidth;
let x = cursor.x;
let y = cursor.y;
rtlHelper.setWidth(this.width);
if (isHorizontal) {
if (i > 0 && x + width + padding > this.right) {
y = cursor.y += lineHeight;
cursor.line++;
x = cursor.x = _alignStartEnd(align, this.left + padding, this.right - lineWidths[cursor.line]);
}
} else if (i > 0 && y + lineHeight > this.bottom) {
x = cursor.x = x + columnSizes[cursor.line].width + padding;
cursor.line++;
y = cursor.y = _alignStartEnd(align, this.top + titleHeight + padding, this.bottom - columnSizes[cursor.line].height);
}
const realX = rtlHelper.x(x);
drawLegendBox(realX, y, legendItem);
x = _textX(textAlign, x + boxWidth + halfFontSize, isHorizontal ? x + width : this.right, opts.rtl);
fillText(rtlHelper.x(x), y, legendItem);
if (isHorizontal) {
cursor.x += width + padding;
} else if (typeof legendItem.text !== "string") {
const fontLineHeight = labelFont.lineHeight;
cursor.y += calculateLegendItemHeight(legendItem, fontLineHeight);
} else {
cursor.y += lineHeight;
}
});
restoreTextDirection(this.ctx, opts.textDirection);
}
drawTitle() {
const opts = this.options;
const titleOpts = opts.title;
const titleFont = toFont(titleOpts.font);
const titlePadding = toPadding(titleOpts.padding);
if (!titleOpts.display) {
return;
}
const rtlHelper = getRtlAdapter(opts.rtl, this.left, this.width);
const ctx = this.ctx;
const position = titleOpts.position;
const halfFontSize = titleFont.size / 2;
const topPaddingPlusHalfFontSize = titlePadding.top + halfFontSize;
let y;
let left2 = this.left;
let maxWidth = this.width;
if (this.isHorizontal()) {
maxWidth = Math.max(...this.lineWidths);
y = this.top + topPaddingPlusHalfFontSize;
left2 = _alignStartEnd(opts.align, left2, this.right - maxWidth);
} else {
const maxHeight = this.columnSizes.reduce((acc, size) => Math.max(acc, size.height), 0);
y = topPaddingPlusHalfFontSize + _alignStartEnd(opts.align, this.top, this.bottom - maxHeight - opts.labels.padding - this._computeTitleHeight());
}
const x = _alignStartEnd(position, left2, left2 + maxWidth);
ctx.textAlign = rtlHelper.textAlign(_toLeftRightCenter(position));
ctx.textBaseline = "middle";
ctx.strokeStyle = titleOpts.color;
ctx.fillStyle = titleOpts.color;
ctx.font = titleFont.string;
renderText(ctx, titleOpts.text, x, y, titleFont);
}
_computeTitleHeight() {
const titleOpts = this.options.title;
const titleFont = toFont(titleOpts.font);
const titlePadding = toPadding(titleOpts.padding);
return titleOpts.display ? titleFont.lineHeight + titlePadding.height : 0;
}
_getLegendItemAt(x, y) {
let i, hitBox, lh;
if (_isBetween(x, this.left, this.right) && _isBetween(y, this.top, this.bottom)) {
lh = this.legendHitBoxes;
for (i = 0; i < lh.length; ++i) {
hitBox = lh[i];
if (_isBetween(x, hitBox.left, hitBox.left + hitBox.width) && _isBetween(y, hitBox.top, hitBox.top + hitBox.height)) {
return this.legendItems[i];
}
}
}
return null;
}
handleEvent(e) {
const opts = this.options;
if (!isListened(e.type, opts)) {
return;
}
const hoveredItem = this._getLegendItemAt(e.x, e.y);
if (e.type === "mousemove" || e.type === "mouseout") {
const previous = this._hoveredItem;
const sameItem = itemsEqual(previous, hoveredItem);
if (previous && !sameItem) {
callback(opts.onLeave, [
e,
previous,
this
], this);
}
this._hoveredItem = hoveredItem;
if (hoveredItem && !sameItem) {
callback(opts.onHover, [
e,
hoveredItem,
this
], this);
}
} else if (hoveredItem) {
callback(opts.onClick, [
e,
hoveredItem,
this
], this);
}
}
};
function calculateItemSize(boxWidth, labelFont, ctx, legendItem, _itemHeight) {
const itemWidth = calculateItemWidth(legendItem, boxWidth, labelFont, ctx);
const itemHeight = calculateItemHeight(_itemHeight, legendItem, labelFont.lineHeight);
return {
itemWidth,
itemHeight
};
}
function calculateItemWidth(legendItem, boxWidth, labelFont, ctx) {
let legendItemText = legendItem.text;
if (legendItemText && typeof legendItemText !== "string") {
legendItemText = legendItemText.reduce((a, b) => a.length > b.length ? a : b);
}
return boxWidth + labelFont.size / 2 + ctx.measureText(legendItemText).width;
}
function calculateItemHeight(_itemHeight, legendItem, fontLineHeight) {
let itemHeight = _itemHeight;
if (typeof legendItem.text !== "string") {
itemHeight = calculateLegendItemHeight(legendItem, fontLineHeight);
}
return itemHeight;
}
function calculateLegendItemHeight(legendItem, fontLineHeight) {
const labelHeight = legendItem.text ? legendItem.text.length + 0.5 : 0;
return fontLineHeight * labelHeight;
}
function isListened(type, opts) {
if ((type === "mousemove" || type === "mouseout") && (opts.onHover || opts.onLeave)) {
return true;
}
if (opts.onClick && (type === "click" || type === "mouseup")) {
return true;
}
return false;
}
var plugin_legend = {
id: "legend",
_element: Legend,
start(chart, _args, options) {
const legend = chart.legend = new Legend({
ctx: chart.ctx,
options,
chart
});
layouts.configure(chart, legend, options);
layouts.addBox(chart, legend);
},
stop(chart) {
layouts.removeBox(chart, chart.legend);
delete chart.legend;
},
beforeUpdate(chart, _args, options) {
const legend = chart.legend;
layouts.configure(chart, legend, options);
legend.options = options;
},
afterUpdate(chart) {
const legend = chart.legend;
legend.buildLabels();
legend.adjustHitBoxes();
},
afterEvent(chart, args) {
if (!args.replay) {
chart.legend.handleEvent(args.event);
}
},
defaults: {
display: true,
position: "top",
align: "center",
fullSize: true,
reverse: false,
weight: 1e3,
onClick(e, legendItem, legend) {
const index = legendItem.datasetIndex;
const ci = legend.chart;
if (ci.isDatasetVisible(index)) {
ci.hide(index);
legendItem.hidden = true;
} else {
ci.show(index);
legendItem.hidden = false;
}
},
onHover: null,
onLeave: null,
labels: {
color: (ctx) => ctx.chart.options.color,
boxWidth: 40,
padding: 10,
generateLabels(chart) {
const datasets = chart.data.datasets;
const { labels: { usePointStyle, pointStyle, textAlign, color: color2, useBorderRadius, borderRadius } } = chart.legend.options;
return chart._getSortedDatasetMetas().map((meta) => {
const style = meta.controller.getStyle(usePointStyle ? 0 : void 0);
const borderWidth = toPadding(style.borderWidth);
return {
text: datasets[meta.index].label,
fillStyle: style.backgroundColor,
fontColor: color2,
hidden: !meta.visible,
lineCap: style.borderCapStyle,
lineDash: style.borderDash,
lineDashOffset: style.borderDashOffset,
lineJoin: style.borderJoinStyle,
lineWidth: (borderWidth.width + borderWidth.height) / 4,
strokeStyle: style.borderColor,
pointStyle: pointStyle || style.pointStyle,
rotation: style.rotation,
textAlign: textAlign || style.textAlign,
borderRadius: useBorderRadius && (borderRadius || style.borderRadius),
datasetIndex: meta.index
};
}, this);
}
},
title: {
color: (ctx) => ctx.chart.options.color,
display: false,
position: "center",
text: ""
}
},
descriptors: {
_scriptable: (name2) => !name2.startsWith("on"),
labels: {
_scriptable: (name2) => ![
"generateLabels",
"filter",
"sort"
].includes(name2)
}
}
};
var Title = class extends Element2 {
constructor(config) {
super();
this.chart = config.chart;
this.options = config.options;
this.ctx = config.ctx;
this._padding = void 0;
this.top = void 0;
this.bottom = void 0;
this.left = void 0;
this.right = void 0;
this.width = void 0;
this.height = void 0;
this.position = void 0;
this.weight = void 0;
this.fullSize = void 0;
}
update(maxWidth, maxHeight) {
const opts = this.options;
this.left = 0;
this.top = 0;
if (!opts.display) {
this.width = this.height = this.right = this.bottom = 0;
return;
}
this.width = this.right = maxWidth;
this.height = this.bottom = maxHeight;
const lineCount = isArray(opts.text) ? opts.text.length : 1;
this._padding = toPadding(opts.padding);
const textSize = lineCount * toFont(opts.font).lineHeight + this._padding.height;
if (this.isHorizontal()) {
this.height = textSize;
} else {
this.width = textSize;
}
}
isHorizontal() {
const pos = this.options.position;
return pos === "top" || pos === "bottom";
}
_drawArgs(offset2) {
const { top: top2, left: left2, bottom: bottom2, right: right2, options } = this;
const align = options.align;
let rotation = 0;
let maxWidth, titleX, titleY;
if (this.isHorizontal()) {
titleX = _alignStartEnd(align, left2, right2);
titleY = top2 + offset2;
maxWidth = right2 - left2;
} else {
if (options.position === "left") {
titleX = left2 + offset2;
titleY = _alignStartEnd(align, bottom2, top2);
rotation = PI * -0.5;
} else {
titleX = right2 - offset2;
titleY = _alignStartEnd(align, top2, bottom2);
rotation = PI * 0.5;
}
maxWidth = bottom2 - top2;
}
return {
titleX,
titleY,
maxWidth,
rotation
};
}
draw() {
const ctx = this.ctx;
const opts = this.options;
if (!opts.display) {
return;
}
const fontOpts = toFont(opts.font);
const lineHeight = fontOpts.lineHeight;
const offset2 = lineHeight / 2 + this._padding.top;
const { titleX, titleY, maxWidth, rotation } = this._drawArgs(offset2);
renderText(ctx, opts.text, 0, 0, fontOpts, {
color: opts.color,
maxWidth,
rotation,
textAlign: _toLeftRightCenter(opts.align),
textBaseline: "middle",
translation: [
titleX,
titleY
]
});
}
};
function createTitle(chart, titleOpts) {
const title = new Title({
ctx: chart.ctx,
options: titleOpts,
chart
});
layouts.configure(chart, title, titleOpts);
layouts.addBox(chart, title);
chart.titleBlock = title;
}
var plugin_title = {
id: "title",
_element: Title,
start(chart, _args, options) {
createTitle(chart, options);
},
stop(chart) {
const titleBlock = chart.titleBlock;
layouts.removeBox(chart, titleBlock);
delete chart.titleBlock;
},
beforeUpdate(chart, _args, options) {
const title = chart.titleBlock;
layouts.configure(chart, title, options);
title.options = options;
},
defaults: {
align: "center",
display: false,
font: {
weight: "bold"
},
fullSize: true,
padding: 10,
position: "top",
text: "",
weight: 2e3
},
defaultRoutes: {
color: "color"
},
descriptors: {
_scriptable: true,
_indexable: false
}
};
var positioners = {
average(items) {
if (!items.length) {
return false;
}
let i, len;
let x = 0;
let y = 0;
let count = 0;
for (i = 0, len = items.length; i < len; ++i) {
const el = items[i].element;
if (el && el.hasValue()) {
const pos = el.tooltipPosition();
x += pos.x;
y += pos.y;
++count;
}
}
return {
x: x / count,
y: y / count
};
},
nearest(items, eventPosition) {
if (!items.length) {
return false;
}
let x = eventPosition.x;
let y = eventPosition.y;
let minDistance = Number.POSITIVE_INFINITY;
let i, len, nearestElement;
for (i = 0, len = items.length; i < len; ++i) {
const el = items[i].element;
if (el && el.hasValue()) {
const center = el.getCenterPoint();
const d = distanceBetweenPoints(eventPosition, center);
if (d < minDistance) {
minDistance = d;
nearestElement = el;
}
}
}
if (nearestElement) {
const tp = nearestElement.tooltipPosition();
x = tp.x;
y = tp.y;
}
return {
x,
y
};
}
};
function pushOrConcat(base, toPush) {
if (toPush) {
if (isArray(toPush)) {
Array.prototype.push.apply(base, toPush);
} else {
base.push(toPush);
}
}
return base;
}
function splitNewlines(str) {
if ((typeof str === "string" || str instanceof String) && str.indexOf("\n") > -1) {
return str.split("\n");
}
return str;
}
function createTooltipItem(chart, item) {
const { element: element2, datasetIndex: datasetIndex2, index } = item;
const controller = chart.getDatasetMeta(datasetIndex2).controller;
const { label, value } = controller.getLabelAndValue(index);
return {
chart,
label,
parsed: controller.getParsed(index),
raw: chart.data.datasets[datasetIndex2].data[index],
formattedValue: value,
dataset: controller.getDataset(),
dataIndex: index,
datasetIndex: datasetIndex2,
element: element2
};
}
function getTooltipSize(tooltip, options) {
const ctx = tooltip.chart.ctx;
const { body, footer, title } = tooltip;
const { boxWidth, boxHeight } = options;
const bodyFont = toFont(options.bodyFont);
const titleFont = toFont(options.titleFont);
const footerFont = toFont(options.footerFont);
const titleLineCount = title.length;
const footerLineCount = footer.length;
const bodyLineItemCount = body.length;
const padding = toPadding(options.padding);
let height = padding.height;
let width = 0;
let combinedBodyLength = body.reduce((count, bodyItem) => count + bodyItem.before.length + bodyItem.lines.length + bodyItem.after.length, 0);
combinedBodyLength += tooltip.beforeBody.length + tooltip.afterBody.length;
if (titleLineCount) {
height += titleLineCount * titleFont.lineHeight + (titleLineCount - 1) * options.titleSpacing + options.titleMarginBottom;
}
if (combinedBodyLength) {
const bodyLineHeight = options.displayColors ? Math.max(boxHeight, bodyFont.lineHeight) : bodyFont.lineHeight;
height += bodyLineItemCount * bodyLineHeight + (combinedBodyLength - bodyLineItemCount) * bodyFont.lineHeight + (combinedBodyLength - 1) * options.bodySpacing;
}
if (footerLineCount) {
height += options.footerMarginTop + footerLineCount * footerFont.lineHeight + (footerLineCount - 1) * options.footerSpacing;
}
let widthPadding = 0;
const maxLineWidth = function(line) {
width = Math.max(width, ctx.measureText(line).width + widthPadding);
};
ctx.save();
ctx.font = titleFont.string;
each2(tooltip.title, maxLineWidth);
ctx.font = bodyFont.string;
each2(tooltip.beforeBody.concat(tooltip.afterBody), maxLineWidth);
widthPadding = options.displayColors ? boxWidth + 2 + options.boxPadding : 0;
each2(body, (bodyItem) => {
each2(bodyItem.before, maxLineWidth);
each2(bodyItem.lines, maxLineWidth);
each2(bodyItem.after, maxLineWidth);
});
widthPadding = 0;
ctx.font = footerFont.string;
each2(tooltip.footer, maxLineWidth);
ctx.restore();
width += padding.width;
return {
width,
height
};
}
function determineYAlign(chart, size) {
const { y, height } = size;
if (y < height / 2) {
return "top";
} else if (y > chart.height - height / 2) {
return "bottom";
}
return "center";
}
function doesNotFitWithAlign(xAlign, chart, options, size) {
const { x, width } = size;
const caret = options.caretSize + options.caretPadding;
if (xAlign === "left" && x + width + caret > chart.width) {
return true;
}
if (xAlign === "right" && x - width - caret < 0) {
return true;
}
}
function determineXAlign(chart, options, size, yAlign) {
const { x, width } = size;
const { width: chartWidth, chartArea: { left: left2, right: right2 } } = chart;
let xAlign = "center";
if (yAlign === "center") {
xAlign = x <= (left2 + right2) / 2 ? "left" : "right";
} else if (x <= width / 2) {
xAlign = "left";
} else if (x >= chartWidth - width / 2) {
xAlign = "right";
}
if (doesNotFitWithAlign(xAlign, chart, options, size)) {
xAlign = "center";
}
return xAlign;
}
function determineAlignment(chart, options, size) {
const yAlign = size.yAlign || options.yAlign || determineYAlign(chart, size);
return {
xAlign: size.xAlign || options.xAlign || determineXAlign(chart, options, size, yAlign),
yAlign
};
}
function alignX(size, xAlign) {
let { x, width } = size;
if (xAlign === "right") {
x -= width;
} else if (xAlign === "center") {
x -= width / 2;
}
return x;
}
function alignY(size, yAlign, paddingAndSize) {
let { y, height } = size;
if (yAlign === "top") {
y += paddingAndSize;
} else if (yAlign === "bottom") {
y -= height + paddingAndSize;
} else {
y -= height / 2;
}
return y;
}
function getBackgroundPoint(options, size, alignment, chart) {
const { caretSize, caretPadding, cornerRadius } = options;
const { xAlign, yAlign } = alignment;
const paddingAndSize = caretSize + caretPadding;
const { topLeft, topRight, bottomLeft, bottomRight } = toTRBLCorners(cornerRadius);
let x = alignX(size, xAlign);
const y = alignY(size, yAlign, paddingAndSize);
if (yAlign === "center") {
if (xAlign === "left") {
x += paddingAndSize;
} else if (xAlign === "right") {
x -= paddingAndSize;
}
} else if (xAlign === "left") {
x -= Math.max(topLeft, bottomLeft) + caretSize;
} else if (xAlign === "right") {
x += Math.max(topRight, bottomRight) + caretSize;
}
return {
x: _limitValue(x, 0, chart.width - size.width),
y: _limitValue(y, 0, chart.height - size.height)
};
}
function getAlignedX(tooltip, align, options) {
const padding = toPadding(options.padding);
return align === "center" ? tooltip.x + tooltip.width / 2 : align === "right" ? tooltip.x + tooltip.width - padding.right : tooltip.x + padding.left;
}
function getBeforeAfterBodyLines(callback2) {
return pushOrConcat([], splitNewlines(callback2));
}
function createTooltipContext(parent, tooltip, tooltipItems) {
return createContext(parent, {
tooltip,
tooltipItems,
type: "tooltip"
});
}
function overrideCallbacks(callbacks, context) {
const override = context && context.dataset && context.dataset.tooltip && context.dataset.tooltip.callbacks;
return override ? callbacks.override(override) : callbacks;
}
var defaultCallbacks = {
beforeTitle: noop2,
title(tooltipItems) {
if (tooltipItems.length > 0) {
const item = tooltipItems[0];
const labels = item.chart.data.labels;
const labelCount = labels ? labels.length : 0;
if (this && this.options && this.options.mode === "dataset") {
return item.dataset.label || "";
} else if (item.label) {
return item.label;
} else if (labelCount > 0 && item.dataIndex < labelCount) {
return labels[item.dataIndex];
}
}
return "";
},
afterTitle: noop2,
beforeBody: noop2,
beforeLabel: noop2,
label(tooltipItem) {
if (this && this.options && this.options.mode === "dataset") {
return tooltipItem.label + ": " + tooltipItem.formattedValue || tooltipItem.formattedValue;
}
let label = tooltipItem.dataset.label || "";
if (label) {
label += ": ";
}
const value = tooltipItem.formattedValue;
if (!isNullOrUndef(value)) {
label += value;
}
return label;
},
labelColor(tooltipItem) {
const meta = tooltipItem.chart.getDatasetMeta(tooltipItem.datasetIndex);
const options = meta.controller.getStyle(tooltipItem.dataIndex);
return {
borderColor: options.borderColor,
backgroundColor: options.backgroundColor,
borderWidth: options.borderWidth,
borderDash: options.borderDash,
borderDashOffset: options.borderDashOffset,
borderRadius: 0
};
},
labelTextColor() {
return this.options.bodyColor;
},
labelPointStyle(tooltipItem) {
const meta = tooltipItem.chart.getDatasetMeta(tooltipItem.datasetIndex);
const options = meta.controller.getStyle(tooltipItem.dataIndex);
return {
pointStyle: options.pointStyle,
rotation: options.rotation
};
},
afterLabel: noop2,
afterBody: noop2,
beforeFooter: noop2,
footer: noop2,
afterFooter: noop2
};
function invokeCallbackWithFallback(callbacks, name2, ctx, arg) {
const result = callbacks[name2].call(ctx, arg);
if (typeof result === "undefined") {
return defaultCallbacks[name2].call(ctx, arg);
}
return result;
}
var Tooltip = class extends Element2 {
constructor(config) {
super();
this.opacity = 0;
this._active = [];
this._eventPosition = void 0;
this._size = void 0;
this._cachedAnimations = void 0;
this._tooltipItems = [];
this.$animations = void 0;
this.$context = void 0;
this.chart = config.chart;
this.options = config.options;
this.dataPoints = void 0;
this.title = void 0;
this.beforeBody = void 0;
this.body = void 0;
this.afterBody = void 0;
this.footer = void 0;
this.xAlign = void 0;
this.yAlign = void 0;
this.x = void 0;
this.y = void 0;
this.height = void 0;
this.width = void 0;
this.caretX = void 0;
this.caretY = void 0;
this.labelColors = void 0;
this.labelPointStyles = void 0;
this.labelTextColors = void 0;
}
initialize(options) {
this.options = options;
this._cachedAnimations = void 0;
this.$context = void 0;
}
_resolveAnimations() {
const cached = this._cachedAnimations;
if (cached) {
return cached;
}
const chart = this.chart;
const options = this.options.setContext(this.getContext());
const opts = options.enabled && chart.options.animation && options.animations;
const animations = new Animations(this.chart, opts);
if (opts._cacheable) {
this._cachedAnimations = Object.freeze(animations);
}
return animations;
}
getContext() {
return this.$context || (this.$context = createTooltipContext(this.chart.getContext(), this, this._tooltipItems));
}
getTitle(context, options) {
const { callbacks } = options;
const beforeTitle = invokeCallbackWithFallback(callbacks, "beforeTitle", this, context);
const title = invokeCallbackWithFallback(callbacks, "title", this, context);
const afterTitle = invokeCallbackWithFallback(callbacks, "afterTitle", this, context);
let lines = [];
lines = pushOrConcat(lines, splitNewlines(beforeTitle));
lines = pushOrConcat(lines, splitNewlines(title));
lines = pushOrConcat(lines, splitNewlines(afterTitle));
return lines;
}
getBeforeBody(tooltipItems, options) {
return getBeforeAfterBodyLines(invokeCallbackWithFallback(options.callbacks, "beforeBody", this, tooltipItems));
}
getBody(tooltipItems, options) {
const { callbacks } = options;
const bodyItems = [];
each2(tooltipItems, (context) => {
const bodyItem = {
before: [],
lines: [],
after: []
};
const scoped = overrideCallbacks(callbacks, context);
pushOrConcat(bodyItem.before, splitNewlines(invokeCallbackWithFallback(scoped, "beforeLabel", this, context)));
pushOrConcat(bodyItem.lines, invokeCallbackWithFallback(scoped, "label", this, context));
pushOrConcat(bodyItem.after, splitNewlines(invokeCallbackWithFallback(scoped, "afterLabel", this, context)));
bodyItems.push(bodyItem);
});
return bodyItems;
}
getAfterBody(tooltipItems, options) {
return getBeforeAfterBodyLines(invokeCallbackWithFallback(options.callbacks, "afterBody", this, tooltipItems));
}
getFooter(tooltipItems, options) {
const { callbacks } = options;
const beforeFooter = invokeCallbackWithFallback(callbacks, "beforeFooter", this, tooltipItems);
const footer = invokeCallbackWithFallback(callbacks, "footer", this, tooltipItems);
const afterFooter = invokeCallbackWithFallback(callbacks, "afterFooter", this, tooltipItems);
let lines = [];
lines = pushOrConcat(lines, splitNewlines(beforeFooter));
lines = pushOrConcat(lines, splitNewlines(footer));
lines = pushOrConcat(lines, splitNewlines(afterFooter));
return lines;
}
_createItems(options) {
const active = this._active;
const data = this.chart.data;
const labelColors = [];
const labelPointStyles = [];
const labelTextColors = [];
let tooltipItems = [];
let i, len;
for (i = 0, len = active.length; i < len; ++i) {
tooltipItems.push(createTooltipItem(this.chart, active[i]));
}
if (options.filter) {
tooltipItems = tooltipItems.filter((element2, index, array) => options.filter(element2, index, array, data));
}
if (options.itemSort) {
tooltipItems = tooltipItems.sort((a, b) => options.itemSort(a, b, data));
}
each2(tooltipItems, (context) => {
const scoped = overrideCallbacks(options.callbacks, context);
labelColors.push(invokeCallbackWithFallback(scoped, "labelColor", this, context));
labelPointStyles.push(invokeCallbackWithFallback(scoped, "labelPointStyle", this, context));
labelTextColors.push(invokeCallbackWithFallback(scoped, "labelTextColor", this, context));
});
this.labelColors = labelColors;
this.labelPointStyles = labelPointStyles;
this.labelTextColors = labelTextColors;
this.dataPoints = tooltipItems;
return tooltipItems;
}
update(changed, replay) {
const options = this.options.setContext(this.getContext());
const active = this._active;
let properties;
let tooltipItems = [];
if (!active.length) {
if (this.opacity !== 0) {
properties = {
opacity: 0
};
}
} else {
const position = positioners[options.position].call(this, active, this._eventPosition);
tooltipItems = this._createItems(options);
this.title = this.getTitle(tooltipItems, options);
this.beforeBody = this.getBeforeBody(tooltipItems, options);
this.body = this.getBody(tooltipItems, options);
this.afterBody = this.getAfterBody(tooltipItems, options);
this.footer = this.getFooter(tooltipItems, options);
const size = this._size = getTooltipSize(this, options);
const positionAndSize = Object.assign({}, position, size);
const alignment = determineAlignment(this.chart, options, positionAndSize);
const backgroundPoint = getBackgroundPoint(options, positionAndSize, alignment, this.chart);
this.xAlign = alignment.xAlign;
this.yAlign = alignment.yAlign;
properties = {
opacity: 1,
x: backgroundPoint.x,
y: backgroundPoint.y,
width: size.width,
height: size.height,
caretX: position.x,
caretY: position.y
};
}
this._tooltipItems = tooltipItems;
this.$context = void 0;
if (properties) {
this._resolveAnimations().update(this, properties);
}
if (changed && options.external) {
options.external.call(this, {
chart: this.chart,
tooltip: this,
replay
});
}
}
drawCaret(tooltipPoint, ctx, size, options) {
const caretPosition = this.getCaretPosition(tooltipPoint, size, options);
ctx.lineTo(caretPosition.x1, caretPosition.y1);
ctx.lineTo(caretPosition.x2, caretPosition.y2);
ctx.lineTo(caretPosition.x3, caretPosition.y3);
}
getCaretPosition(tooltipPoint, size, options) {
const { xAlign, yAlign } = this;
const { caretSize, cornerRadius } = options;
const { topLeft, topRight, bottomLeft, bottomRight } = toTRBLCorners(cornerRadius);
const { x: ptX, y: ptY } = tooltipPoint;
const { width, height } = size;
let x1, x2, x3, y1, y2, y3;
if (yAlign === "center") {
y2 = ptY + height / 2;
if (xAlign === "left") {
x1 = ptX;
x2 = x1 - caretSize;
y1 = y2 + caretSize;
y3 = y2 - caretSize;
} else {
x1 = ptX + width;
x2 = x1 + caretSize;
y1 = y2 - caretSize;
y3 = y2 + caretSize;
}
x3 = x1;
} else {
if (xAlign === "left") {
x2 = ptX + Math.max(topLeft, bottomLeft) + caretSize;
} else if (xAlign === "right") {
x2 = ptX + width - Math.max(topRight, bottomRight) - caretSize;
} else {
x2 = this.caretX;
}
if (yAlign === "top") {
y1 = ptY;
y2 = y1 - caretSize;
x1 = x2 - caretSize;
x3 = x2 + caretSize;
} else {
y1 = ptY + height;
y2 = y1 + caretSize;
x1 = x2 + caretSize;
x3 = x2 - caretSize;
}
y3 = y1;
}
return {
x1,
x2,
x3,
y1,
y2,
y3
};
}
drawTitle(pt, ctx, options) {
const title = this.title;
const length = title.length;
let titleFont, titleSpacing, i;
if (length) {
const rtlHelper = getRtlAdapter(options.rtl, this.x, this.width);
pt.x = getAlignedX(this, options.titleAlign, options);
ctx.textAlign = rtlHelper.textAlign(options.titleAlign);
ctx.textBaseline = "middle";
titleFont = toFont(options.titleFont);
titleSpacing = options.titleSpacing;
ctx.fillStyle = options.titleColor;
ctx.font = titleFont.string;
for (i = 0; i < length; ++i) {
ctx.fillText(title[i], rtlHelper.x(pt.x), pt.y + titleFont.lineHeight / 2);
pt.y += titleFont.lineHeight + titleSpacing;
if (i + 1 === length) {
pt.y += options.titleMarginBottom - titleSpacing;
}
}
}
}
_drawColorBox(ctx, pt, i, rtlHelper, options) {
const labelColors = this.labelColors[i];
const labelPointStyle = this.labelPointStyles[i];
const { boxHeight, boxWidth, boxPadding } = options;
const bodyFont = toFont(options.bodyFont);
const colorX = getAlignedX(this, "left", options);
const rtlColorX = rtlHelper.x(colorX);
const yOffSet = boxHeight < bodyFont.lineHeight ? (bodyFont.lineHeight - boxHeight) / 2 : 0;
const colorY = pt.y + yOffSet;
if (options.usePointStyle) {
const drawOptions = {
radius: Math.min(boxWidth, boxHeight) / 2,
pointStyle: labelPointStyle.pointStyle,
rotation: labelPointStyle.rotation,
borderWidth: 1
};
const centerX = rtlHelper.leftForLtr(rtlColorX, boxWidth) + boxWidth / 2;
const centerY = colorY + boxHeight / 2;
ctx.strokeStyle = options.multiKeyBackground;
ctx.fillStyle = options.multiKeyBackground;
drawPoint(ctx, drawOptions, centerX, centerY);
ctx.strokeStyle = labelColors.borderColor;
ctx.fillStyle = labelColors.backgroundColor;
drawPoint(ctx, drawOptions, centerX, centerY);
} else {
ctx.lineWidth = isObject(labelColors.borderWidth) ? Math.max(...Object.values(labelColors.borderWidth)) : labelColors.borderWidth || 1;
ctx.strokeStyle = labelColors.borderColor;
ctx.setLineDash(labelColors.borderDash || []);
ctx.lineDashOffset = labelColors.borderDashOffset || 0;
const outerX = rtlHelper.leftForLtr(rtlColorX, boxWidth - boxPadding);
const innerX = rtlHelper.leftForLtr(rtlHelper.xPlus(rtlColorX, 1), boxWidth - boxPadding - 2);
const borderRadius = toTRBLCorners(labelColors.borderRadius);
if (Object.values(borderRadius).some((v) => v !== 0)) {
ctx.beginPath();
ctx.fillStyle = options.multiKeyBackground;
addRoundedRectPath(ctx, {
x: outerX,
y: colorY,
w: boxWidth,
h: boxHeight,
radius: borderRadius
});
ctx.fill();
ctx.stroke();
ctx.fillStyle = labelColors.backgroundColor;
ctx.beginPath();
addRoundedRectPath(ctx, {
x: innerX,
y: colorY + 1,
w: boxWidth - 2,
h: boxHeight - 2,
radius: borderRadius
});
ctx.fill();
} else {
ctx.fillStyle = options.multiKeyBackground;
ctx.fillRect(outerX, colorY, boxWidth, boxHeight);
ctx.strokeRect(outerX, colorY, boxWidth, boxHeight);
ctx.fillStyle = labelColors.backgroundColor;
ctx.fillRect(innerX, colorY + 1, boxWidth - 2, boxHeight - 2);
}
}
ctx.fillStyle = this.labelTextColors[i];
}
drawBody(pt, ctx, options) {
const { body } = this;
const { bodySpacing, bodyAlign, displayColors, boxHeight, boxWidth, boxPadding } = options;
const bodyFont = toFont(options.bodyFont);
let bodyLineHeight = bodyFont.lineHeight;
let xLinePadding = 0;
const rtlHelper = getRtlAdapter(options.rtl, this.x, this.width);
const fillLineOfText = function(line) {
ctx.fillText(line, rtlHelper.x(pt.x + xLinePadding), pt.y + bodyLineHeight / 2);
pt.y += bodyLineHeight + bodySpacing;
};
const bodyAlignForCalculation = rtlHelper.textAlign(bodyAlign);
let bodyItem, textColor, lines, i, j, ilen, jlen;
ctx.textAlign = bodyAlign;
ctx.textBaseline = "middle";
ctx.font = bodyFont.string;
pt.x = getAlignedX(this, bodyAlignForCalculation, options);
ctx.fillStyle = options.bodyColor;
each2(this.beforeBody, fillLineOfText);
xLinePadding = displayColors && bodyAlignForCalculation !== "right" ? bodyAlign === "center" ? boxWidth / 2 + boxPadding : boxWidth + 2 + boxPadding : 0;
for (i = 0, ilen = body.length; i < ilen; ++i) {
bodyItem = body[i];
textColor = this.labelTextColors[i];
ctx.fillStyle = textColor;
each2(bodyItem.before, fillLineOfText);
lines = bodyItem.lines;
if (displayColors && lines.length) {
this._drawColorBox(ctx, pt, i, rtlHelper, options);
bodyLineHeight = Math.max(bodyFont.lineHeight, boxHeight);
}
for (j = 0, jlen = lines.length; j < jlen; ++j) {
fillLineOfText(lines[j]);
bodyLineHeight = bodyFont.lineHeight;
}
each2(bodyItem.after, fillLineOfText);
}
xLinePadding = 0;
bodyLineHeight = bodyFont.lineHeight;
each2(this.afterBody, fillLineOfText);
pt.y -= bodySpacing;
}
drawFooter(pt, ctx, options) {
const footer = this.footer;
const length = footer.length;
let footerFont, i;
if (length) {
const rtlHelper = getRtlAdapter(options.rtl, this.x, this.width);
pt.x = getAlignedX(this, options.footerAlign, options);
pt.y += options.footerMarginTop;
ctx.textAlign = rtlHelper.textAlign(options.footerAlign);
ctx.textBaseline = "middle";
footerFont = toFont(options.footerFont);
ctx.fillStyle = options.footerColor;
ctx.font = footerFont.string;
for (i = 0; i < length; ++i) {
ctx.fillText(footer[i], rtlHelper.x(pt.x), pt.y + footerFont.lineHeight / 2);
pt.y += footerFont.lineHeight + options.footerSpacing;
}
}
}
drawBackground(pt, ctx, tooltipSize, options) {
const { xAlign, yAlign } = this;
const { x, y } = pt;
const { width, height } = tooltipSize;
const { topLeft, topRight, bottomLeft, bottomRight } = toTRBLCorners(options.cornerRadius);
ctx.fillStyle = options.backgroundColor;
ctx.strokeStyle = options.borderColor;
ctx.lineWidth = options.borderWidth;
ctx.beginPath();
ctx.moveTo(x + topLeft, y);
if (yAlign === "top") {
this.drawCaret(pt, ctx, tooltipSize, options);
}
ctx.lineTo(x + width - topRight, y);
ctx.quadraticCurveTo(x + width, y, x + width, y + topRight);
if (yAlign === "center" && xAlign === "right") {
this.drawCaret(pt, ctx, tooltipSize, options);
}
ctx.lineTo(x + width, y + height - bottomRight);
ctx.quadraticCurveTo(x + width, y + height, x + width - bottomRight, y + height);
if (yAlign === "bottom") {
this.drawCaret(pt, ctx, tooltipSize, options);
}
ctx.lineTo(x + bottomLeft, y + height);
ctx.quadraticCurveTo(x, y + height, x, y + height - bottomLeft);
if (yAlign === "center" && xAlign === "left") {
this.drawCaret(pt, ctx, tooltipSize, options);
}
ctx.lineTo(x, y + topLeft);
ctx.quadraticCurveTo(x, y, x + topLeft, y);
ctx.closePath();
ctx.fill();
if (options.borderWidth > 0) {
ctx.stroke();
}
}
_updateAnimationTarget(options) {
const chart = this.chart;
const anims = this.$animations;
const animX = anims && anims.x;
const animY = anims && anims.y;
if (animX || animY) {
const position = positioners[options.position].call(this, this._active, this._eventPosition);
if (!position) {
return;
}
const size = this._size = getTooltipSize(this, options);
const positionAndSize = Object.assign({}, position, this._size);
const alignment = determineAlignment(chart, options, positionAndSize);
const point = getBackgroundPoint(options, positionAndSize, alignment, chart);
if (animX._to !== point.x || animY._to !== point.y) {
this.xAlign = alignment.xAlign;
this.yAlign = alignment.yAlign;
this.width = size.width;
this.height = size.height;
this.caretX = position.x;
this.caretY = position.y;
this._resolveAnimations().update(this, point);
}
}
}
_willRender() {
return !!this.opacity;
}
draw(ctx) {
const options = this.options.setContext(this.getContext());
let opacity = this.opacity;
if (!opacity) {
return;
}
this._updateAnimationTarget(options);
const tooltipSize = {
width: this.width,
height: this.height
};
const pt = {
x: this.x,
y: this.y
};
opacity = Math.abs(opacity) < 1e-3 ? 0 : opacity;
const padding = toPadding(options.padding);
const hasTooltipContent = this.title.length || this.beforeBody.length || this.body.length || this.afterBody.length || this.footer.length;
if (options.enabled && hasTooltipContent) {
ctx.save();
ctx.globalAlpha = opacity;
this.drawBackground(pt, ctx, tooltipSize, options);
overrideTextDirection(ctx, options.textDirection);
pt.y += padding.top;
this.drawTitle(pt, ctx, options);
this.drawBody(pt, ctx, options);
this.drawFooter(pt, ctx, options);
restoreTextDirection(ctx, options.textDirection);
ctx.restore();
}
}
getActiveElements() {
return this._active || [];
}
setActiveElements(activeElements, eventPosition) {
const lastActive = this._active;
const active = activeElements.map(({ datasetIndex: datasetIndex2, index }) => {
const meta = this.chart.getDatasetMeta(datasetIndex2);
if (!meta) {
throw new Error("Cannot find a dataset at index " + datasetIndex2);
}
return {
datasetIndex: datasetIndex2,
element: meta.data[index],
index
};
});
const changed = !_elementsEqual(lastActive, active);
const positionChanged = this._positionChanged(active, eventPosition);
if (changed || positionChanged) {
this._active = active;
this._eventPosition = eventPosition;
this._ignoreReplayEvents = true;
this.update(true);
}
}
handleEvent(e, replay, inChartArea = true) {
if (replay && this._ignoreReplayEvents) {
return false;
}
this._ignoreReplayEvents = false;
const options = this.options;
const lastActive = this._active || [];
const active = this._getActiveElements(e, lastActive, replay, inChartArea);
const positionChanged = this._positionChanged(active, e);
const changed = replay || !_elementsEqual(active, lastActive) || positionChanged;
if (changed) {
this._active = active;
if (options.enabled || options.external) {
this._eventPosition = {
x: e.x,
y: e.y
};
this.update(true, replay);
}
}
return changed;
}
_getActiveElements(e, lastActive, replay, inChartArea) {
const options = this.options;
if (e.type === "mouseout") {
return [];
}
if (!inChartArea) {
return lastActive;
}
const active = this.chart.getElementsAtEventForMode(e, options.mode, options, replay);
if (options.reverse) {
active.reverse();
}
return active;
}
_positionChanged(active, e) {
const { caretX, caretY, options } = this;
const position = positioners[options.position].call(this, active, e);
return position !== false && (caretX !== position.x || caretY !== position.y);
}
};
__publicField(Tooltip, "positioners", positioners);
var plugin_tooltip = {
id: "tooltip",
_element: Tooltip,
positioners,
afterInit(chart, _args, options) {
if (options) {
chart.tooltip = new Tooltip({
chart,
options
});
}
},
beforeUpdate(chart, _args, options) {
if (chart.tooltip) {
chart.tooltip.initialize(options);
}
},
reset(chart, _args, options) {
if (chart.tooltip) {
chart.tooltip.initialize(options);
}
},
afterDraw(chart) {
const tooltip = chart.tooltip;
if (tooltip && tooltip._willRender()) {
const args = {
tooltip
};
if (chart.notifyPlugins("beforeTooltipDraw", {
...args,
cancelable: true
}) === false) {
return;
}
tooltip.draw(chart.ctx);
chart.notifyPlugins("afterTooltipDraw", args);
}
},
afterEvent(chart, args) {
if (chart.tooltip) {
const useFinalPosition = args.replay;
if (chart.tooltip.handleEvent(args.event, useFinalPosition, args.inChartArea)) {
args.changed = true;
}
}
},
defaults: {
enabled: true,
external: null,
position: "average",
backgroundColor: "rgba(0,0,0,0.8)",
titleColor: "#fff",
titleFont: {
weight: "bold"
},
titleSpacing: 2,
titleMarginBottom: 6,
titleAlign: "left",
bodyColor: "#fff",
bodySpacing: 2,
bodyFont: {},
bodyAlign: "left",
footerColor: "#fff",
footerSpacing: 2,
footerMarginTop: 6,
footerFont: {
weight: "bold"
},
footerAlign: "left",
padding: 6,
caretPadding: 2,
caretSize: 5,
cornerRadius: 6,
boxHeight: (ctx, opts) => opts.bodyFont.size,
boxWidth: (ctx, opts) => opts.bodyFont.size,
multiKeyBackground: "#fff",
displayColors: true,
boxPadding: 0,
borderColor: "rgba(0,0,0,0)",
borderWidth: 0,
animation: {
duration: 400,
easing: "easeOutQuart"
},
animations: {
numbers: {
type: "number",
properties: [
"x",
"y",
"width",
"height",
"caretX",
"caretY"
]
},
opacity: {
easing: "linear",
duration: 200
}
},
callbacks: defaultCallbacks
},
defaultRoutes: {
bodyFont: "font",
footerFont: "font",
titleFont: "font"
},
descriptors: {
_scriptable: (name2) => name2 !== "filter" && name2 !== "itemSort" && name2 !== "external",
_indexable: false,
callbacks: {
_scriptable: false,
_indexable: false
},
animation: {
_fallback: false
},
animations: {
_fallback: "animation"
}
},
additionalOptionScopes: [
"interaction"
]
};
var addIfString = (labels, raw, index, addedLabels) => {
if (typeof raw === "string") {
index = labels.push(raw) - 1;
addedLabels.unshift({
index,
label: raw
});
} else if (isNaN(raw)) {
index = null;
}
return index;
};
function findOrAddLabel(labels, raw, index, addedLabels) {
const first = labels.indexOf(raw);
if (first === -1) {
return addIfString(labels, raw, index, addedLabels);
}
const last = labels.lastIndexOf(raw);
return first !== last ? index : first;
}
var validIndex = (index, max2) => index === null ? null : _limitValue(Math.round(index), 0, max2);
function _getLabelForValue(value) {
const labels = this.getLabels();
if (value >= 0 && value < labels.length) {
return labels[value];
}
return value;
}
var CategoryScale = class extends Scale {
constructor(cfg) {
super(cfg);
this._startValue = void 0;
this._valueRange = 0;
this._addedLabels = [];
}
init(scaleOptions) {
const added = this._addedLabels;
if (added.length) {
const labels = this.getLabels();
for (const { index, label } of added) {
if (labels[index] === label) {
labels.splice(index, 1);
}
}
this._addedLabels = [];
}
super.init(scaleOptions);
}
parse(raw, index) {
if (isNullOrUndef(raw)) {
return null;
}
const labels = this.getLabels();
index = isFinite(index) && labels[index] === raw ? index : findOrAddLabel(labels, raw, valueOrDefault(index, raw), this._addedLabels);
return validIndex(index, labels.length - 1);
}
determineDataLimits() {
const { minDefined, maxDefined } = this.getUserBounds();
let { min: min2, max: max2 } = this.getMinMax(true);
if (this.options.bounds === "ticks") {
if (!minDefined) {
min2 = 0;
}
if (!maxDefined) {
max2 = this.getLabels().length - 1;
}
}
this.min = min2;
this.max = max2;
}
buildTicks() {
const min2 = this.min;
const max2 = this.max;
const offset2 = this.options.offset;
const ticks = [];
let labels = this.getLabels();
labels = min2 === 0 && max2 === labels.length - 1 ? labels : labels.slice(min2, max2 + 1);
this._valueRange = Math.max(labels.length - (offset2 ? 0 : 1), 1);
this._startValue = this.min - (offset2 ? 0.5 : 0);
for (let value = min2; value <= max2; value++) {
ticks.push({
value
});
}
return ticks;
}
getLabelForValue(value) {
return _getLabelForValue.call(this, value);
}
configure() {
super.configure();
if (!this.isHorizontal()) {
this._reversePixels = !this._reversePixels;
}
}
getPixelForValue(value) {
if (typeof value !== "number") {
value = this.parse(value);
}
return value === null ? NaN : this.getPixelForDecimal((value - this._startValue) / this._valueRange);
}
getPixelForTick(index) {
const ticks = this.ticks;
if (index < 0 || index > ticks.length - 1) {
return null;
}
return this.getPixelForValue(ticks[index].value);
}
getValueForPixel(pixel) {
return Math.round(this._startValue + this.getDecimalForPixel(pixel) * this._valueRange);
}
getBasePixel() {
return this.bottom;
}
};
__publicField(CategoryScale, "id", "category");
__publicField(CategoryScale, "defaults", {
ticks: {
callback: _getLabelForValue
}
});
function generateTicks$1(generationOptions, dataRange) {
const ticks = [];
const MIN_SPACING = 1e-14;
const { bounds, step, min: min2, max: max2, precision, count, maxTicks, maxDigits, includeBounds } = generationOptions;
const unit = step || 1;
const maxSpaces = maxTicks - 1;
const { min: rmin, max: rmax } = dataRange;
const minDefined = !isNullOrUndef(min2);
const maxDefined = !isNullOrUndef(max2);
const countDefined = !isNullOrUndef(count);
const minSpacing = (rmax - rmin) / (maxDigits + 1);
let spacing = niceNum((rmax - rmin) / maxSpaces / unit) * unit;
let factor, niceMin, niceMax, numSpaces;
if (spacing < MIN_SPACING && !minDefined && !maxDefined) {
return [
{
value: rmin
},
{
value: rmax
}
];
}
numSpaces = Math.ceil(rmax / spacing) - Math.floor(rmin / spacing);
if (numSpaces > maxSpaces) {
spacing = niceNum(numSpaces * spacing / maxSpaces / unit) * unit;
}
if (!isNullOrUndef(precision)) {
factor = Math.pow(10, precision);
spacing = Math.ceil(spacing * factor) / factor;
}
if (bounds === "ticks") {
niceMin = Math.floor(rmin / spacing) * spacing;
niceMax = Math.ceil(rmax / spacing) * spacing;
} else {
niceMin = rmin;
niceMax = rmax;
}
if (minDefined && maxDefined && step && almostWhole((max2 - min2) / step, spacing / 1e3)) {
numSpaces = Math.round(Math.min((max2 - min2) / spacing, maxTicks));
spacing = (max2 - min2) / numSpaces;
niceMin = min2;
niceMax = max2;
} else if (countDefined) {
niceMin = minDefined ? min2 : niceMin;
niceMax = maxDefined ? max2 : niceMax;
numSpaces = count - 1;
spacing = (niceMax - niceMin) / numSpaces;
} else {
numSpaces = (niceMax - niceMin) / spacing;
if (almostEquals(numSpaces, Math.round(numSpaces), spacing / 1e3)) {
numSpaces = Math.round(numSpaces);
} else {
numSpaces = Math.ceil(numSpaces);
}
}
const decimalPlaces = Math.max(_decimalPlaces(spacing), _decimalPlaces(niceMin));
factor = Math.pow(10, isNullOrUndef(precision) ? decimalPlaces : precision);
niceMin = Math.round(niceMin * factor) / factor;
niceMax = Math.round(niceMax * factor) / factor;
let j = 0;
if (minDefined) {
if (includeBounds && niceMin !== min2) {
ticks.push({
value: min2
});
if (niceMin < min2) {
j++;
}
if (almostEquals(Math.round((niceMin + j * spacing) * factor) / factor, min2, relativeLabelSize(min2, minSpacing, generationOptions))) {
j++;
}
} else if (niceMin < min2) {
j++;
}
}
for (; j < numSpaces; ++j) {
ticks.push({
value: Math.round((niceMin + j * spacing) * factor) / factor
});
}
if (maxDefined && includeBounds && niceMax !== max2) {
if (ticks.length && almostEquals(ticks[ticks.length - 1].value, max2, relativeLabelSize(max2, minSpacing, generationOptions))) {
ticks[ticks.length - 1].value = max2;
} else {
ticks.push({
value: max2
});
}
} else if (!maxDefined || niceMax === max2) {
ticks.push({
value: niceMax
});
}
return ticks;
}
function relativeLabelSize(value, minSpacing, { horizontal, minRotation }) {
const rad = toRadians(minRotation);
const ratio = (horizontal ? Math.sin(rad) : Math.cos(rad)) || 1e-3;
const length = 0.75 * minSpacing * ("" + value).length;
return Math.min(minSpacing / ratio, length);
}
var LinearScaleBase = class extends Scale {
constructor(cfg) {
super(cfg);
this.start = void 0;
this.end = void 0;
this._startValue = void 0;
this._endValue = void 0;
this._valueRange = 0;
}
parse(raw, index) {
if (isNullOrUndef(raw)) {
return null;
}
if ((typeof raw === "number" || raw instanceof Number) && !isFinite(+raw)) {
return null;
}
return +raw;
}
handleTickRangeOptions() {
const { beginAtZero } = this.options;
const { minDefined, maxDefined } = this.getUserBounds();
let { min: min2, max: max2 } = this;
const setMin = (v) => min2 = minDefined ? min2 : v;
const setMax = (v) => max2 = maxDefined ? max2 : v;
if (beginAtZero) {
const minSign = sign(min2);
const maxSign = sign(max2);
if (minSign < 0 && maxSign < 0) {
setMax(0);
} else if (minSign > 0 && maxSign > 0) {
setMin(0);
}
}
if (min2 === max2) {
let offset2 = max2 === 0 ? 1 : Math.abs(max2 * 0.05);
setMax(max2 + offset2);
if (!beginAtZero) {
setMin(min2 - offset2);
}
}
this.min = min2;
this.max = max2;
}
getTickLimit() {
const tickOpts = this.options.ticks;
let { maxTicksLimit, stepSize } = tickOpts;
let maxTicks;
if (stepSize) {
maxTicks = Math.ceil(this.max / stepSize) - Math.floor(this.min / stepSize) + 1;
if (maxTicks > 1e3) {
console.warn(`scales.${this.id}.ticks.stepSize: ${stepSize} would result generating up to ${maxTicks} ticks. Limiting to 1000.`);
maxTicks = 1e3;
}
} else {
maxTicks = this.computeTickLimit();
maxTicksLimit = maxTicksLimit || 11;
}
if (maxTicksLimit) {
maxTicks = Math.min(maxTicksLimit, maxTicks);
}
return maxTicks;
}
computeTickLimit() {
return Number.POSITIVE_INFINITY;
}
buildTicks() {
const opts = this.options;
const tickOpts = opts.ticks;
let maxTicks = this.getTickLimit();
maxTicks = Math.max(2, maxTicks);
const numericGeneratorOptions = {
maxTicks,
bounds: opts.bounds,
min: opts.min,
max: opts.max,
precision: tickOpts.precision,
step: tickOpts.stepSize,
count: tickOpts.count,
maxDigits: this._maxDigits(),
horizontal: this.isHorizontal(),
minRotation: tickOpts.minRotation || 0,
includeBounds: tickOpts.includeBounds !== false
};
const dataRange = this._range || this;
const ticks = generateTicks$1(numericGeneratorOptions, dataRange);
if (opts.bounds === "ticks") {
_setMinAndMaxByKey(ticks, this, "value");
}
if (opts.reverse) {
ticks.reverse();
this.start = this.max;
this.end = this.min;
} else {
this.start = this.min;
this.end = this.max;
}
return ticks;
}
configure() {
const ticks = this.ticks;
let start2 = this.min;
let end2 = this.max;
super.configure();
if (this.options.offset && ticks.length) {
const offset2 = (end2 - start2) / Math.max(ticks.length - 1, 1) / 2;
start2 -= offset2;
end2 += offset2;
}
this._startValue = start2;
this._endValue = end2;
this._valueRange = end2 - start2;
}
getLabelForValue(value) {
return formatNumber(value, this.chart.options.locale, this.options.ticks.format);
}
};
var LinearScale = class extends LinearScaleBase {
determineDataLimits() {
const { min: min2, max: max2 } = this.getMinMax(true);
this.min = isNumberFinite(min2) ? min2 : 0;
this.max = isNumberFinite(max2) ? max2 : 1;
this.handleTickRangeOptions();
}
computeTickLimit() {
const horizontal = this.isHorizontal();
const length = horizontal ? this.width : this.height;
const minRotation = toRadians(this.options.ticks.minRotation);
const ratio = (horizontal ? Math.sin(minRotation) : Math.cos(minRotation)) || 1e-3;
const tickFont = this._resolveTickFontOptions(0);
return Math.ceil(length / Math.min(40, tickFont.lineHeight / ratio));
}
getPixelForValue(value) {
return value === null ? NaN : this.getPixelForDecimal((value - this._startValue) / this._valueRange);
}
getValueForPixel(pixel) {
return this._startValue + this.getDecimalForPixel(pixel) * this._valueRange;
}
};
__publicField(LinearScale, "id", "linear");
__publicField(LinearScale, "defaults", {
ticks: {
callback: Ticks.formatters.numeric
}
});
var log10Floor = (v) => Math.floor(log10(v));
var changeExponent = (v, m) => Math.pow(10, log10Floor(v) + m);
function isMajor(tickVal) {
const remain = tickVal / Math.pow(10, log10Floor(tickVal));
return remain === 1;
}
function steps(min2, max2, rangeExp) {
const rangeStep = Math.pow(10, rangeExp);
const start2 = Math.floor(min2 / rangeStep);
const end2 = Math.ceil(max2 / rangeStep);
return end2 - start2;
}
function startExp(min2, max2) {
const range = max2 - min2;
let rangeExp = log10Floor(range);
while (steps(min2, max2, rangeExp) > 10) {
rangeExp++;
}
while (steps(min2, max2, rangeExp) < 10) {
rangeExp--;
}
return Math.min(rangeExp, log10Floor(min2));
}
function generateTicks(generationOptions, { min: min2, max: max2 }) {
min2 = finiteOrDefault(generationOptions.min, min2);
const ticks = [];
const minExp = log10Floor(min2);
let exp = startExp(min2, max2);
let precision = exp < 0 ? Math.pow(10, Math.abs(exp)) : 1;
const stepSize = Math.pow(10, exp);
const base = minExp > exp ? Math.pow(10, minExp) : 0;
const start2 = Math.round((min2 - base) * precision) / precision;
const offset2 = Math.floor((min2 - base) / stepSize / 10) * stepSize * 10;
let significand = Math.floor((start2 - offset2) / Math.pow(10, exp));
let value = finiteOrDefault(generationOptions.min, Math.round((base + offset2 + significand * Math.pow(10, exp)) * precision) / precision);
while (value < max2) {
ticks.push({
value,
major: isMajor(value),
significand
});
if (significand >= 10) {
significand = significand < 15 ? 15 : 20;
} else {
significand++;
}
if (significand >= 20) {
exp++;
significand = 2;
precision = exp >= 0 ? 1 : precision;
}
value = Math.round((base + offset2 + significand * Math.pow(10, exp)) * precision) / precision;
}
const lastTick = finiteOrDefault(generationOptions.max, value);
ticks.push({
value: lastTick,
major: isMajor(lastTick),
significand
});
return ticks;
}
var LogarithmicScale = class extends Scale {
constructor(cfg) {
super(cfg);
this.start = void 0;
this.end = void 0;
this._startValue = void 0;
this._valueRange = 0;
}
parse(raw, index) {
const value = LinearScaleBase.prototype.parse.apply(this, [
raw,
index
]);
if (value === 0) {
this._zero = true;
return void 0;
}
return isNumberFinite(value) && value > 0 ? value : null;
}
determineDataLimits() {
const { min: min2, max: max2 } = this.getMinMax(true);
this.min = isNumberFinite(min2) ? Math.max(0, min2) : null;
this.max = isNumberFinite(max2) ? Math.max(0, max2) : null;
if (this.options.beginAtZero) {
this._zero = true;
}
if (this._zero && this.min !== this._suggestedMin && !isNumberFinite(this._userMin)) {
this.min = min2 === changeExponent(this.min, 0) ? changeExponent(this.min, -1) : changeExponent(this.min, 0);
}
this.handleTickRangeOptions();
}
handleTickRangeOptions() {
const { minDefined, maxDefined } = this.getUserBounds();
let min2 = this.min;
let max2 = this.max;
const setMin = (v) => min2 = minDefined ? min2 : v;
const setMax = (v) => max2 = maxDefined ? max2 : v;
if (min2 === max2) {
if (min2 <= 0) {
setMin(1);
setMax(10);
} else {
setMin(changeExponent(min2, -1));
setMax(changeExponent(max2, 1));
}
}
if (min2 <= 0) {
setMin(changeExponent(max2, -1));
}
if (max2 <= 0) {
setMax(changeExponent(min2, 1));
}
this.min = min2;
this.max = max2;
}
buildTicks() {
const opts = this.options;
const generationOptions = {
min: this._userMin,
max: this._userMax
};
const ticks = generateTicks(generationOptions, this);
if (opts.bounds === "ticks") {
_setMinAndMaxByKey(ticks, this, "value");
}
if (opts.reverse) {
ticks.reverse();
this.start = this.max;
this.end = this.min;
} else {
this.start = this.min;
this.end = this.max;
}
return ticks;
}
getLabelForValue(value) {
return value === void 0 ? "0" : formatNumber(value, this.chart.options.locale, this.options.ticks.format);
}
configure() {
const start2 = this.min;
super.configure();
this._startValue = log10(start2);
this._valueRange = log10(this.max) - log10(start2);
}
getPixelForValue(value) {
if (value === void 0 || value === 0) {
value = this.min;
}
if (value === null || isNaN(value)) {
return NaN;
}
return this.getPixelForDecimal(value === this.min ? 0 : (log10(value) - this._startValue) / this._valueRange);
}
getValueForPixel(pixel) {
const decimal = this.getDecimalForPixel(pixel);
return Math.pow(10, this._startValue + decimal * this._valueRange);
}
};
__publicField(LogarithmicScale, "id", "logarithmic");
__publicField(LogarithmicScale, "defaults", {
ticks: {
callback: Ticks.formatters.logarithmic,
major: {
enabled: true
}
}
});
function getTickBackdropHeight(opts) {
const tickOpts = opts.ticks;
if (tickOpts.display && opts.display) {
const padding = toPadding(tickOpts.backdropPadding);
return valueOrDefault(tickOpts.font && tickOpts.font.size, defaults.font.size) + padding.height;
}
return 0;
}
function measureLabelSize(ctx, font, label) {
label = isArray(label) ? label : [
label
];
return {
w: _longestText(ctx, font.string, label),
h: label.length * font.lineHeight
};
}
function determineLimits(angle, pos, size, min2, max2) {
if (angle === min2 || angle === max2) {
return {
start: pos - size / 2,
end: pos + size / 2
};
} else if (angle < min2 || angle > max2) {
return {
start: pos - size,
end: pos
};
}
return {
start: pos,
end: pos + size
};
}
function fitWithPointLabels(scale) {
const orig = {
l: scale.left + scale._padding.left,
r: scale.right - scale._padding.right,
t: scale.top + scale._padding.top,
b: scale.bottom - scale._padding.bottom
};
const limits = Object.assign({}, orig);
const labelSizes = [];
const padding = [];
const valueCount = scale._pointLabels.length;
const pointLabelOpts = scale.options.pointLabels;
const additionalAngle = pointLabelOpts.centerPointLabels ? PI / valueCount : 0;
for (let i = 0; i < valueCount; i++) {
const opts = pointLabelOpts.setContext(scale.getPointLabelContext(i));
padding[i] = opts.padding;
const pointPosition = scale.getPointPosition(i, scale.drawingArea + padding[i], additionalAngle);
const plFont = toFont(opts.font);
const textSize = measureLabelSize(scale.ctx, plFont, scale._pointLabels[i]);
labelSizes[i] = textSize;
const angleRadians = _normalizeAngle(scale.getIndexAngle(i) + additionalAngle);
const angle = Math.round(toDegrees(angleRadians));
const hLimits = determineLimits(angle, pointPosition.x, textSize.w, 0, 180);
const vLimits = determineLimits(angle, pointPosition.y, textSize.h, 90, 270);
updateLimits(limits, orig, angleRadians, hLimits, vLimits);
}
scale.setCenterPoint(orig.l - limits.l, limits.r - orig.r, orig.t - limits.t, limits.b - orig.b);
scale._pointLabelItems = buildPointLabelItems(scale, labelSizes, padding);
}
function updateLimits(limits, orig, angle, hLimits, vLimits) {
const sin = Math.abs(Math.sin(angle));
const cos = Math.abs(Math.cos(angle));
let x = 0;
let y = 0;
if (hLimits.start < orig.l) {
x = (orig.l - hLimits.start) / sin;
limits.l = Math.min(limits.l, orig.l - x);
} else if (hLimits.end > orig.r) {
x = (hLimits.end - orig.r) / sin;
limits.r = Math.max(limits.r, orig.r + x);
}
if (vLimits.start < orig.t) {
y = (orig.t - vLimits.start) / cos;
limits.t = Math.min(limits.t, orig.t - y);
} else if (vLimits.end > orig.b) {
y = (vLimits.end - orig.b) / cos;
limits.b = Math.max(limits.b, orig.b + y);
}
}
function buildPointLabelItems(scale, labelSizes, padding) {
const items = [];
const valueCount = scale._pointLabels.length;
const opts = scale.options;
const extra = getTickBackdropHeight(opts) / 2;
const outerDistance = scale.drawingArea;
const additionalAngle = opts.pointLabels.centerPointLabels ? PI / valueCount : 0;
for (let i = 0; i < valueCount; i++) {
const pointLabelPosition = scale.getPointPosition(i, outerDistance + extra + padding[i], additionalAngle);
const angle = Math.round(toDegrees(_normalizeAngle(pointLabelPosition.angle + HALF_PI)));
const size = labelSizes[i];
const y = yForAngle(pointLabelPosition.y, size.h, angle);
const textAlign = getTextAlignForAngle(angle);
const left2 = leftForTextAlign(pointLabelPosition.x, size.w, textAlign);
items.push({
x: pointLabelPosition.x,
y,
textAlign,
left: left2,
top: y,
right: left2 + size.w,
bottom: y + size.h
});
}
return items;
}
function getTextAlignForAngle(angle) {
if (angle === 0 || angle === 180) {
return "center";
} else if (angle < 180) {
return "left";
}
return "right";
}
function leftForTextAlign(x, w, align) {
if (align === "right") {
x -= w;
} else if (align === "center") {
x -= w / 2;
}
return x;
}
function yForAngle(y, h, angle) {
if (angle === 90 || angle === 270) {
y -= h / 2;
} else if (angle > 270 || angle < 90) {
y -= h;
}
return y;
}
function drawPointLabels(scale, labelCount) {
const { ctx, options: { pointLabels } } = scale;
for (let i = labelCount - 1; i >= 0; i--) {
const optsAtIndex = pointLabels.setContext(scale.getPointLabelContext(i));
const plFont = toFont(optsAtIndex.font);
const { x, y, textAlign, left: left2, top: top2, right: right2, bottom: bottom2 } = scale._pointLabelItems[i];
const { backdropColor } = optsAtIndex;
if (!isNullOrUndef(backdropColor)) {
const borderRadius = toTRBLCorners(optsAtIndex.borderRadius);
const padding = toPadding(optsAtIndex.backdropPadding);
ctx.fillStyle = backdropColor;
const backdropLeft = left2 - padding.left;
const backdropTop = top2 - padding.top;
const backdropWidth = right2 - left2 + padding.width;
const backdropHeight = bottom2 - top2 + padding.height;
if (Object.values(borderRadius).some((v) => v !== 0)) {
ctx.beginPath();
addRoundedRectPath(ctx, {
x: backdropLeft,
y: backdropTop,
w: backdropWidth,
h: backdropHeight,
radius: borderRadius
});
ctx.fill();
} else {
ctx.fillRect(backdropLeft, backdropTop, backdropWidth, backdropHeight);
}
}
renderText(ctx, scale._pointLabels[i], x, y + plFont.lineHeight / 2, plFont, {
color: optsAtIndex.color,
textAlign,
textBaseline: "middle"
});
}
}
function pathRadiusLine(scale, radius, circular, labelCount) {
const { ctx } = scale;
if (circular) {
ctx.arc(scale.xCenter, scale.yCenter, radius, 0, TAU);
} else {
let pointPosition = scale.getPointPosition(0, radius);
ctx.moveTo(pointPosition.x, pointPosition.y);
for (let i = 1; i < labelCount; i++) {
pointPosition = scale.getPointPosition(i, radius);
ctx.lineTo(pointPosition.x, pointPosition.y);
}
}
}
function drawRadiusLine(scale, gridLineOpts, radius, labelCount, borderOpts) {
const ctx = scale.ctx;
const circular = gridLineOpts.circular;
const { color: color2, lineWidth } = gridLineOpts;
if (!circular && !labelCount || !color2 || !lineWidth || radius < 0) {
return;
}
ctx.save();
ctx.strokeStyle = color2;
ctx.lineWidth = lineWidth;
ctx.setLineDash(borderOpts.dash);
ctx.lineDashOffset = borderOpts.dashOffset;
ctx.beginPath();
pathRadiusLine(scale, radius, circular, labelCount);
ctx.closePath();
ctx.stroke();
ctx.restore();
}
function createPointLabelContext(parent, index, label) {
return createContext(parent, {
label,
index,
type: "pointLabel"
});
}
var RadialLinearScale = class extends LinearScaleBase {
constructor(cfg) {
super(cfg);
this.xCenter = void 0;
this.yCenter = void 0;
this.drawingArea = void 0;
this._pointLabels = [];
this._pointLabelItems = [];
}
setDimensions() {
const padding = this._padding = toPadding(getTickBackdropHeight(this.options) / 2);
const w = this.width = this.maxWidth - padding.width;
const h = this.height = this.maxHeight - padding.height;
this.xCenter = Math.floor(this.left + w / 2 + padding.left);
this.yCenter = Math.floor(this.top + h / 2 + padding.top);
this.drawingArea = Math.floor(Math.min(w, h) / 2);
}
determineDataLimits() {
const { min: min2, max: max2 } = this.getMinMax(false);
this.min = isNumberFinite(min2) && !isNaN(min2) ? min2 : 0;
this.max = isNumberFinite(max2) && !isNaN(max2) ? max2 : 0;
this.handleTickRangeOptions();
}
computeTickLimit() {
return Math.ceil(this.drawingArea / getTickBackdropHeight(this.options));
}
generateTickLabels(ticks) {
LinearScaleBase.prototype.generateTickLabels.call(this, ticks);
this._pointLabels = this.getLabels().map((value, index) => {
const label = callback(this.options.pointLabels.callback, [
value,
index
], this);
return label || label === 0 ? label : "";
}).filter((v, i) => this.chart.getDataVisibility(i));
}
fit() {
const opts = this.options;
if (opts.display && opts.pointLabels.display) {
fitWithPointLabels(this);
} else {
this.setCenterPoint(0, 0, 0, 0);
}
}
setCenterPoint(leftMovement, rightMovement, topMovement, bottomMovement) {
this.xCenter += Math.floor((leftMovement - rightMovement) / 2);
this.yCenter += Math.floor((topMovement - bottomMovement) / 2);
this.drawingArea -= Math.min(this.drawingArea / 2, Math.max(leftMovement, rightMovement, topMovement, bottomMovement));
}
getIndexAngle(index) {
const angleMultiplier = TAU / (this._pointLabels.length || 1);
const startAngle = this.options.startAngle || 0;
return _normalizeAngle(index * angleMultiplier + toRadians(startAngle));
}
getDistanceFromCenterForValue(value) {
if (isNullOrUndef(value)) {
return NaN;
}
const scalingFactor = this.drawingArea / (this.max - this.min);
if (this.options.reverse) {
return (this.max - value) * scalingFactor;
}
return (value - this.min) * scalingFactor;
}
getValueForDistanceFromCenter(distance) {
if (isNullOrUndef(distance)) {
return NaN;
}
const scaledDistance = distance / (this.drawingArea / (this.max - this.min));
return this.options.reverse ? this.max - scaledDistance : this.min + scaledDistance;
}
getPointLabelContext(index) {
const pointLabels = this._pointLabels || [];
if (index >= 0 && index < pointLabels.length) {
const pointLabel = pointLabels[index];
return createPointLabelContext(this.getContext(), index, pointLabel);
}
}
getPointPosition(index, distanceFromCenter, additionalAngle = 0) {
const angle = this.getIndexAngle(index) - HALF_PI + additionalAngle;
return {
x: Math.cos(angle) * distanceFromCenter + this.xCenter,
y: Math.sin(angle) * distanceFromCenter + this.yCenter,
angle
};
}
getPointPositionForValue(index, value) {
return this.getPointPosition(index, this.getDistanceFromCenterForValue(value));
}
getBasePosition(index) {
return this.getPointPositionForValue(index || 0, this.getBaseValue());
}
getPointLabelPosition(index) {
const { left: left2, top: top2, right: right2, bottom: bottom2 } = this._pointLabelItems[index];
return {
left: left2,
top: top2,
right: right2,
bottom: bottom2
};
}
drawBackground() {
const { backgroundColor, grid: { circular } } = this.options;
if (backgroundColor) {
const ctx = this.ctx;
ctx.save();
ctx.beginPath();
pathRadiusLine(this, this.getDistanceFromCenterForValue(this._endValue), circular, this._pointLabels.length);
ctx.closePath();
ctx.fillStyle = backgroundColor;
ctx.fill();
ctx.restore();
}
}
drawGrid() {
const ctx = this.ctx;
const opts = this.options;
const { angleLines, grid, border } = opts;
const labelCount = this._pointLabels.length;
let i, offset2, position;
if (opts.pointLabels.display) {
drawPointLabels(this, labelCount);
}
if (grid.display) {
this.ticks.forEach((tick2, index) => {
if (index !== 0) {
offset2 = this.getDistanceFromCenterForValue(tick2.value);
const context = this.getContext(index);
const optsAtIndex = grid.setContext(context);
const optsAtIndexBorder = border.setContext(context);
drawRadiusLine(this, optsAtIndex, offset2, labelCount, optsAtIndexBorder);
}
});
}
if (angleLines.display) {
ctx.save();
for (i = labelCount - 1; i >= 0; i--) {
const optsAtIndex = angleLines.setContext(this.getPointLabelContext(i));
const { color: color2, lineWidth } = optsAtIndex;
if (!lineWidth || !color2) {
continue;
}
ctx.lineWidth = lineWidth;
ctx.strokeStyle = color2;
ctx.setLineDash(optsAtIndex.borderDash);
ctx.lineDashOffset = optsAtIndex.borderDashOffset;
offset2 = this.getDistanceFromCenterForValue(opts.ticks.reverse ? this.min : this.max);
position = this.getPointPosition(i, offset2);
ctx.beginPath();
ctx.moveTo(this.xCenter, this.yCenter);
ctx.lineTo(position.x, position.y);
ctx.stroke();
}
ctx.restore();
}
}
drawBorder() {
}
drawLabels() {
const ctx = this.ctx;
const opts = this.options;
const tickOpts = opts.ticks;
if (!tickOpts.display) {
return;
}
const startAngle = this.getIndexAngle(0);
let offset2, width;
ctx.save();
ctx.translate(this.xCenter, this.yCenter);
ctx.rotate(startAngle);
ctx.textAlign = "center";
ctx.textBaseline = "middle";
this.ticks.forEach((tick2, index) => {
if (index === 0 && !opts.reverse) {
return;
}
const optsAtIndex = tickOpts.setContext(this.getContext(index));
const tickFont = toFont(optsAtIndex.font);
offset2 = this.getDistanceFromCenterForValue(this.ticks[index].value);
if (optsAtIndex.showLabelBackdrop) {
ctx.font = tickFont.string;
width = ctx.measureText(tick2.label).width;
ctx.fillStyle = optsAtIndex.backdropColor;
const padding = toPadding(optsAtIndex.backdropPadding);
ctx.fillRect(-width / 2 - padding.left, -offset2 - tickFont.size / 2 - padding.top, width + padding.width, tickFont.size + padding.height);
}
renderText(ctx, tick2.label, 0, -offset2, tickFont, {
color: optsAtIndex.color
});
});
ctx.restore();
}
drawTitle() {
}
};
__publicField(RadialLinearScale, "id", "radialLinear");
__publicField(RadialLinearScale, "defaults", {
display: true,
animate: true,
position: "chartArea",
angleLines: {
display: true,
lineWidth: 1,
borderDash: [],
borderDashOffset: 0
},
grid: {
circular: false
},
startAngle: 0,
ticks: {
showLabelBackdrop: true,
callback: Ticks.formatters.numeric
},
pointLabels: {
backdropColor: void 0,
backdropPadding: 2,
display: true,
font: {
size: 10
},
callback(label) {
return label;
},
padding: 5,
centerPointLabels: false
}
});
__publicField(RadialLinearScale, "defaultRoutes", {
"angleLines.color": "borderColor",
"pointLabels.color": "color",
"ticks.color": "color"
});
__publicField(RadialLinearScale, "descriptors", {
angleLines: {
_fallback: "grid"
}
});
var INTERVALS = {
millisecond: {
common: true,
size: 1,
steps: 1e3
},
second: {
common: true,
size: 1e3,
steps: 60
},
minute: {
common: true,
size: 6e4,
steps: 60
},
hour: {
common: true,
size: 36e5,
steps: 24
},
day: {
common: true,
size: 864e5,
steps: 30
},
week: {
common: false,
size: 6048e5,
steps: 4
},
month: {
common: true,
size: 2628e6,
steps: 12
},
quarter: {
common: false,
size: 7884e6,
steps: 4
},
year: {
common: true,
size: 3154e7
}
};
var UNITS = /* @__PURE__ */ Object.keys(INTERVALS);
function sorter(a, b) {
return a - b;
}
function parse(scale, input) {
if (isNullOrUndef(input)) {
return null;
}
const adapter = scale._adapter;
const { parser, round: round3, isoWeekday } = scale._parseOpts;
let value = input;
if (typeof parser === "function") {
value = parser(value);
}
if (!isNumberFinite(value)) {
value = typeof parser === "string" ? adapter.parse(value, parser) : adapter.parse(value);
}
if (value === null) {
return null;
}
if (round3) {
value = round3 === "week" && (isNumber(isoWeekday) || isoWeekday === true) ? adapter.startOf(value, "isoWeek", isoWeekday) : adapter.startOf(value, round3);
}
return +value;
}
function determineUnitForAutoTicks(minUnit, min2, max2, capacity) {
const ilen = UNITS.length;
for (let i = UNITS.indexOf(minUnit); i < ilen - 1; ++i) {
const interval = INTERVALS[UNITS[i]];
const factor = interval.steps ? interval.steps : Number.MAX_SAFE_INTEGER;
if (interval.common && Math.ceil((max2 - min2) / (factor * interval.size)) <= capacity) {
return UNITS[i];
}
}
return UNITS[ilen - 1];
}
function determineUnitForFormatting(scale, numTicks, minUnit, min2, max2) {
for (let i = UNITS.length - 1; i >= UNITS.indexOf(minUnit); i--) {
const unit = UNITS[i];
if (INTERVALS[unit].common && scale._adapter.diff(max2, min2, unit) >= numTicks - 1) {
return unit;
}
}
return UNITS[minUnit ? UNITS.indexOf(minUnit) : 0];
}
function determineMajorUnit(unit) {
for (let i = UNITS.indexOf(unit) + 1, ilen = UNITS.length; i < ilen; ++i) {
if (INTERVALS[UNITS[i]].common) {
return UNITS[i];
}
}
}
function addTick(ticks, time, timestamps) {
if (!timestamps) {
ticks[time] = true;
} else if (timestamps.length) {
const { lo, hi } = _lookup(timestamps, time);
const timestamp = timestamps[lo] >= time ? timestamps[lo] : timestamps[hi];
ticks[timestamp] = true;
}
}
function setMajorTicks(scale, ticks, map2, majorUnit) {
const adapter = scale._adapter;
const first = +adapter.startOf(ticks[0].value, majorUnit);
const last = ticks[ticks.length - 1].value;
let major, index;
for (major = first; major <= last; major = +adapter.add(major, 1, majorUnit)) {
index = map2[major];
if (index >= 0) {
ticks[index].major = true;
}
}
return ticks;
}
function ticksFromTimestamps(scale, values, majorUnit) {
const ticks = [];
const map2 = {};
const ilen = values.length;
let i, value;
for (i = 0; i < ilen; ++i) {
value = values[i];
map2[value] = i;
ticks.push({
value,
major: false
});
}
return ilen === 0 || !majorUnit ? ticks : setMajorTicks(scale, ticks, map2, majorUnit);
}
var TimeScale = class extends Scale {
constructor(props) {
super(props);
this._cache = {
data: [],
labels: [],
all: []
};
this._unit = "day";
this._majorUnit = void 0;
this._offsets = {};
this._normalized = false;
this._parseOpts = void 0;
}
init(scaleOpts, opts = {}) {
const time = scaleOpts.time || (scaleOpts.time = {});
const adapter = this._adapter = new adapters._date(scaleOpts.adapters.date);
adapter.init(opts);
mergeIf(time.displayFormats, adapter.formats());
this._parseOpts = {
parser: time.parser,
round: time.round,
isoWeekday: time.isoWeekday
};
super.init(scaleOpts);
this._normalized = opts.normalized;
}
parse(raw, index) {
if (raw === void 0) {
return null;
}
return parse(this, raw);
}
beforeLayout() {
super.beforeLayout();
this._cache = {
data: [],
labels: [],
all: []
};
}
determineDataLimits() {
const options = this.options;
const adapter = this._adapter;
const unit = options.time.unit || "day";
let { min: min2, max: max2, minDefined, maxDefined } = this.getUserBounds();
function _applyBounds(bounds) {
if (!minDefined && !isNaN(bounds.min)) {
min2 = Math.min(min2, bounds.min);
}
if (!maxDefined && !isNaN(bounds.max)) {
max2 = Math.max(max2, bounds.max);
}
}
if (!minDefined || !maxDefined) {
_applyBounds(this._getLabelBounds());
if (options.bounds !== "ticks" || options.ticks.source !== "labels") {
_applyBounds(this.getMinMax(false));
}
}
min2 = isNumberFinite(min2) && !isNaN(min2) ? min2 : +adapter.startOf(Date.now(), unit);
max2 = isNumberFinite(max2) && !isNaN(max2) ? max2 : +adapter.endOf(Date.now(), unit) + 1;
this.min = Math.min(min2, max2 - 1);
this.max = Math.max(min2 + 1, max2);
}
_getLabelBounds() {
const arr = this.getLabelTimestamps();
let min2 = Number.POSITIVE_INFINITY;
let max2 = Number.NEGATIVE_INFINITY;
if (arr.length) {
min2 = arr[0];
max2 = arr[arr.length - 1];
}
return {
min: min2,
max: max2
};
}
buildTicks() {
const options = this.options;
const timeOpts = options.time;
const tickOpts = options.ticks;
const timestamps = tickOpts.source === "labels" ? this.getLabelTimestamps() : this._generate();
if (options.bounds === "ticks" && timestamps.length) {
this.min = this._userMin || timestamps[0];
this.max = this._userMax || timestamps[timestamps.length - 1];
}
const min2 = this.min;
const max2 = this.max;
const ticks = _filterBetween(timestamps, min2, max2);
this._unit = timeOpts.unit || (tickOpts.autoSkip ? determineUnitForAutoTicks(timeOpts.minUnit, this.min, this.max, this._getLabelCapacity(min2)) : determineUnitForFormatting(this, ticks.length, timeOpts.minUnit, this.min, this.max));
this._majorUnit = !tickOpts.major.enabled || this._unit === "year" ? void 0 : determineMajorUnit(this._unit);
this.initOffsets(timestamps);
if (options.reverse) {
ticks.reverse();
}
return ticksFromTimestamps(this, ticks, this._majorUnit);
}
afterAutoSkip() {
if (this.options.offsetAfterAutoskip) {
this.initOffsets(this.ticks.map((tick2) => +tick2.value));
}
}
initOffsets(timestamps = []) {
let start2 = 0;
let end2 = 0;
let first, last;
if (this.options.offset && timestamps.length) {
first = this.getDecimalForValue(timestamps[0]);
if (timestamps.length === 1) {
start2 = 1 - first;
} else {
start2 = (this.getDecimalForValue(timestamps[1]) - first) / 2;
}
last = this.getDecimalForValue(timestamps[timestamps.length - 1]);
if (timestamps.length === 1) {
end2 = last;
} else {
end2 = (last - this.getDecimalForValue(timestamps[timestamps.length - 2])) / 2;
}
}
const limit = timestamps.length < 3 ? 0.5 : 0.25;
start2 = _limitValue(start2, 0, limit);
end2 = _limitValue(end2, 0, limit);
this._offsets = {
start: start2,
end: end2,
factor: 1 / (start2 + 1 + end2)
};
}
_generate() {
const adapter = this._adapter;
const min2 = this.min;
const max2 = this.max;
const options = this.options;
const timeOpts = options.time;
const minor = timeOpts.unit || determineUnitForAutoTicks(timeOpts.minUnit, min2, max2, this._getLabelCapacity(min2));
const stepSize = valueOrDefault(options.ticks.stepSize, 1);
const weekday = minor === "week" ? timeOpts.isoWeekday : false;
const hasWeekday = isNumber(weekday) || weekday === true;
const ticks = {};
let first = min2;
let time, count;
if (hasWeekday) {
first = +adapter.startOf(first, "isoWeek", weekday);
}
first = +adapter.startOf(first, hasWeekday ? "day" : minor);
if (adapter.diff(max2, min2, minor) > 1e5 * stepSize) {
throw new Error(min2 + " and " + max2 + " are too far apart with stepSize of " + stepSize + " " + minor);
}
const timestamps = options.ticks.source === "data" && this.getDataTimestamps();
for (time = first, count = 0; time < max2; time = +adapter.add(time, stepSize, minor), count++) {
addTick(ticks, time, timestamps);
}
if (time === max2 || options.bounds === "ticks" || count === 1) {
addTick(ticks, time, timestamps);
}
return Object.keys(ticks).sort((a, b) => a - b).map((x) => +x);
}
getLabelForValue(value) {
const adapter = this._adapter;
const timeOpts = this.options.time;
if (timeOpts.tooltipFormat) {
return adapter.format(value, timeOpts.tooltipFormat);
}
return adapter.format(value, timeOpts.displayFormats.datetime);
}
format(value, format2) {
const options = this.options;
const formats = options.time.displayFormats;
const unit = this._unit;
const fmt = format2 || formats[unit];
return this._adapter.format(value, fmt);
}
_tickFormatFunction(time, index, ticks, format2) {
const options = this.options;
const formatter = options.ticks.callback;
if (formatter) {
return callback(formatter, [
time,
index,
ticks
], this);
}
const formats = options.time.displayFormats;
const unit = this._unit;
const majorUnit = this._majorUnit;
const minorFormat = unit && formats[unit];
const majorFormat = majorUnit && formats[majorUnit];
const tick2 = ticks[index];
const major = majorUnit && majorFormat && tick2 && tick2.major;
return this._adapter.format(time, format2 || (major ? majorFormat : minorFormat));
}
generateTickLabels(ticks) {
let i, ilen, tick2;
for (i = 0, ilen = ticks.length; i < ilen; ++i) {
tick2 = ticks[i];
tick2.label = this._tickFormatFunction(tick2.value, i, ticks);
}
}
getDecimalForValue(value) {
return value === null ? NaN : (value - this.min) / (this.max - this.min);
}
getPixelForValue(value) {
const offsets = this._offsets;
const pos = this.getDecimalForValue(value);
return this.getPixelForDecimal((offsets.start + pos) * offsets.factor);
}
getValueForPixel(pixel) {
const offsets = this._offsets;
const pos = this.getDecimalForPixel(pixel) / offsets.factor - offsets.end;
return this.min + pos * (this.max - this.min);
}
_getLabelSize(label) {
const ticksOpts = this.options.ticks;
const tickLabelWidth = this.ctx.measureText(label).width;
const angle = toRadians(this.isHorizontal() ? ticksOpts.maxRotation : ticksOpts.minRotation);
const cosRotation = Math.cos(angle);
const sinRotation = Math.sin(angle);
const tickFontSize = this._resolveTickFontOptions(0).size;
return {
w: tickLabelWidth * cosRotation + tickFontSize * sinRotation,
h: tickLabelWidth * sinRotation + tickFontSize * cosRotation
};
}
_getLabelCapacity(exampleTime) {
const timeOpts = this.options.time;
const displayFormats = timeOpts.displayFormats;
const format2 = displayFormats[timeOpts.unit] || displayFormats.millisecond;
const exampleLabel = this._tickFormatFunction(exampleTime, 0, ticksFromTimestamps(this, [
exampleTime
], this._majorUnit), format2);
const size = this._getLabelSize(exampleLabel);
const capacity = Math.floor(this.isHorizontal() ? this.width / size.w : this.height / size.h) - 1;
return capacity > 0 ? capacity : 1;
}
getDataTimestamps() {
let timestamps = this._cache.data || [];
let i, ilen;
if (timestamps.length) {
return timestamps;
}
const metas = this.getMatchingVisibleMetas();
if (this._normalized && metas.length) {
return this._cache.data = metas[0].controller.getAllParsedValues(this);
}
for (i = 0, ilen = metas.length; i < ilen; ++i) {
timestamps = timestamps.concat(metas[i].controller.getAllParsedValues(this));
}
return this._cache.data = this.normalize(timestamps);
}
getLabelTimestamps() {
const timestamps = this._cache.labels || [];
let i, ilen;
if (timestamps.length) {
return timestamps;
}
const labels = this.getLabels();
for (i = 0, ilen = labels.length; i < ilen; ++i) {
timestamps.push(parse(this, labels[i]));
}
return this._cache.labels = this._normalized ? timestamps : this.normalize(timestamps);
}
normalize(values) {
return _arrayUnique(values.sort(sorter));
}
};
__publicField(TimeScale, "id", "time");
__publicField(TimeScale, "defaults", {
bounds: "data",
adapters: {},
time: {
parser: false,
unit: false,
round: false,
isoWeekday: false,
minUnit: "millisecond",
displayFormats: {}
},
ticks: {
source: "auto",
callback: false,
major: {
enabled: false
}
}
});
function interpolate2(table, val, reverse) {
let lo = 0;
let hi = table.length - 1;
let prevSource, nextSource, prevTarget, nextTarget;
if (reverse) {
if (val >= table[lo].pos && val <= table[hi].pos) {
({ lo, hi } = _lookupByKey(table, "pos", val));
}
({ pos: prevSource, time: prevTarget } = table[lo]);
({ pos: nextSource, time: nextTarget } = table[hi]);
} else {
if (val >= table[lo].time && val <= table[hi].time) {
({ lo, hi } = _lookupByKey(table, "time", val));
}
({ time: prevSource, pos: prevTarget } = table[lo]);
({ time: nextSource, pos: nextTarget } = table[hi]);
}
const span = nextSource - prevSource;
return span ? prevTarget + (nextTarget - prevTarget) * (val - prevSource) / span : prevTarget;
}
var TimeSeriesScale = class extends TimeScale {
constructor(props) {
super(props);
this._table = [];
this._minPos = void 0;
this._tableRange = void 0;
}
initOffsets() {
const timestamps = this._getTimestampsForTable();
const table = this._table = this.buildLookupTable(timestamps);
this._minPos = interpolate2(table, this.min);
this._tableRange = interpolate2(table, this.max) - this._minPos;
super.initOffsets(timestamps);
}
buildLookupTable(timestamps) {
const { min: min2, max: max2 } = this;
const items = [];
const table = [];
let i, ilen, prev, curr, next;
for (i = 0, ilen = timestamps.length; i < ilen; ++i) {
curr = timestamps[i];
if (curr >= min2 && curr <= max2) {
items.push(curr);
}
}
if (items.length < 2) {
return [
{
time: min2,
pos: 0
},
{
time: max2,
pos: 1
}
];
}
for (i = 0, ilen = items.length; i < ilen; ++i) {
next = items[i + 1];
prev = items[i - 1];
curr = items[i];
if (Math.round((next + prev) / 2) !== curr) {
table.push({
time: curr,
pos: i / (ilen - 1)
});
}
}
return table;
}
_getTimestampsForTable() {
let timestamps = this._cache.all || [];
if (timestamps.length) {
return timestamps;
}
const data = this.getDataTimestamps();
const label = this.getLabelTimestamps();
if (data.length && label.length) {
timestamps = this.normalize(data.concat(label));
} else {
timestamps = data.length ? data : label;
}
timestamps = this._cache.all = timestamps;
return timestamps;
}
getDecimalForValue(value) {
return (interpolate2(this._table, value) - this._minPos) / this._tableRange;
}
getValueForPixel(pixel) {
const offsets = this._offsets;
const decimal = this.getDecimalForPixel(pixel) / offsets.factor - offsets.end;
return interpolate2(this._table, decimal * this._tableRange + this._minPos, true);
}
};
__publicField(TimeSeriesScale, "id", "timeseries");
__publicField(TimeSeriesScale, "defaults", TimeScale.defaults);
// node_modules/svelte-chartjs/utils/svelte.js
var eventPrefix = /^on/;
var events = [];
Object.keys(globalThis).forEach((key) => {
if (eventPrefix.test(key)) {
events.push(key.replace(eventPrefix, ""));
}
});
function useForwardEvents(getRef) {
const component = current_component;
const destructors = [];
function forward(e) {
bubble(component, e);
}
onMount(() => {
const ref = getRef();
events.forEach(ref instanceof Element ? (event) => destructors.push(listen(ref, event, forward)) : (event) => destructors.push(ref.$on(event, forward)));
});
onDestroy(() => {
while (destructors.length) {
destructors.pop()();
}
});
}
// node_modules/svelte-chartjs/Chart.svelte
function create_fragment6(ctx) {
let canvas;
let canvas_levels = [
/*props*/
ctx[1]
];
let canvas_data = {};
for (let i = 0; i < canvas_levels.length; i += 1) {
canvas_data = assign(canvas_data, canvas_levels[i]);
}
return {
c() {
canvas = element("canvas");
set_attributes(canvas, canvas_data);
},
m(target, anchor) {
insert(target, canvas, anchor);
ctx[8](canvas);
},
p: noop,
i: noop,
o: noop,
d(detaching) {
if (detaching)
detach(canvas);
ctx[8](null);
}
};
}
function clean(props) {
let { data, type, options, plugins, children: children2, $$scope, $$slots, ...rest } = props;
return rest;
}
function instance6($$self, $$props, $$invalidate) {
let { type } = $$props;
let { data = { datasets: [] } } = $$props;
let { options = {} } = $$props;
let { plugins = [] } = $$props;
let { updateMode = void 0 } = $$props;
let { chart = null } = $$props;
let canvasRef;
let props = clean($$props);
onMount(() => {
$$invalidate(2, chart = new Chart(canvasRef, { type, data, options, plugins }));
});
afterUpdate(() => {
if (!chart)
return;
$$invalidate(2, chart.data = data, chart);
Object.assign(chart.options, options);
chart.update(updateMode);
});
onDestroy(() => {
if (chart)
chart.destroy();
$$invalidate(2, chart = null);
});
useForwardEvents(() => canvasRef);
function canvas_binding($$value) {
binding_callbacks[$$value ? "unshift" : "push"](() => {
canvasRef = $$value;
$$invalidate(0, canvasRef);
});
}
$$self.$$set = ($$new_props) => {
$$invalidate(9, $$props = assign(assign({}, $$props), exclude_internal_props($$new_props)));
if ("type" in $$new_props)
$$invalidate(3, type = $$new_props.type);
if ("data" in $$new_props)
$$invalidate(4, data = $$new_props.data);
if ("options" in $$new_props)
$$invalidate(5, options = $$new_props.options);
if ("plugins" in $$new_props)
$$invalidate(6, plugins = $$new_props.plugins);
if ("updateMode" in $$new_props)
$$invalidate(7, updateMode = $$new_props.updateMode);
if ("chart" in $$new_props)
$$invalidate(2, chart = $$new_props.chart);
};
$$props = exclude_internal_props($$props);
return [
canvasRef,
props,
chart,
type,
data,
options,
plugins,
updateMode,
canvas_binding
];
}
var Chart2 = class extends SvelteComponent {
constructor(options) {
super();
init(this, options, instance6, create_fragment6, safe_not_equal, {
type: 3,
data: 4,
options: 5,
plugins: 6,
updateMode: 7,
chart: 2
});
}
};
var Chart_default = Chart2;
// node_modules/svelte-chartjs/Bar.svelte
function create_fragment7(ctx) {
let chart_1;
let updating_chart;
let current;
const chart_1_spread_levels = [
{ type: "bar" },
/*props*/
ctx[1]
];
function chart_1_chart_binding(value) {
ctx[4](value);
}
let chart_1_props = {};
for (let i = 0; i < chart_1_spread_levels.length; i += 1) {
chart_1_props = assign(chart_1_props, chart_1_spread_levels[i]);
}
if (
/*chart*/
ctx[0] !== void 0
) {
chart_1_props.chart = /*chart*/
ctx[0];
}
chart_1 = new Chart_default({ props: chart_1_props });
ctx[3](chart_1);
binding_callbacks.push(() => bind(chart_1, "chart", chart_1_chart_binding));
return {
c() {
create_component(chart_1.$$.fragment);
},
m(target, anchor) {
mount_component(chart_1, target, anchor);
current = true;
},
p(ctx2, [dirty]) {
const chart_1_changes = dirty & /*props*/
2 ? get_spread_update(chart_1_spread_levels, [chart_1_spread_levels[0], get_spread_object(
/*props*/
ctx2[1]
)]) : {};
if (!updating_chart && dirty & /*chart*/
1) {
updating_chart = true;
chart_1_changes.chart = /*chart*/
ctx2[0];
add_flush_callback(() => updating_chart = false);
}
chart_1.$set(chart_1_changes);
},
i(local) {
if (current)
return;
transition_in(chart_1.$$.fragment, local);
current = true;
},
o(local) {
transition_out(chart_1.$$.fragment, local);
current = false;
},
d(detaching) {
ctx[3](null);
destroy_component(chart_1, detaching);
}
};
}
function instance7($$self, $$props, $$invalidate) {
Chart.register(BarController);
let { chart = null } = $$props;
let props;
let baseChartRef;
useForwardEvents(() => baseChartRef);
function chart_1_binding($$value) {
binding_callbacks[$$value ? "unshift" : "push"](() => {
baseChartRef = $$value;
$$invalidate(2, baseChartRef);
});
}
function chart_1_chart_binding(value) {
chart = value;
$$invalidate(0, chart);
}
$$self.$$set = ($$new_props) => {
$$invalidate(5, $$props = assign(assign({}, $$props), exclude_internal_props($$new_props)));
if ("chart" in $$new_props)
$$invalidate(0, chart = $$new_props.chart);
};
$$self.$$.update = () => {
$:
$$invalidate(1, props = $$props);
};
$$props = exclude_internal_props($$props);
return [chart, props, baseChartRef, chart_1_binding, chart_1_chart_binding];
}
var Bar = class extends SvelteComponent {
constructor(options) {
super();
init(this, options, instance7, create_fragment7, safe_not_equal, { chart: 0 });
}
};
var Bar_default = Bar;
// src/stats/charts/colorHelpers.ts
function hexToRgba(hex2, alpha2 = 1) {
hex2 = hex2.replace(/^#/, "");
let r, g, b;
if (hex2.length === 3) {
r = parseInt(hex2[0] + hex2[0], 16);
g = parseInt(hex2[1] + hex2[1], 16);
b = parseInt(hex2[2] + hex2[2], 16);
} else if (hex2.length === 6) {
r = parseInt(hex2.slice(0, 2), 16);
g = parseInt(hex2.slice(2, 4), 16);
b = parseInt(hex2.slice(4, 6), 16);
} else {
throw new Error("Invalid hex color: " + hex2);
}
return `rgba(${r}, ${g}, ${b}, ${alpha2})`;
}
// src/stats/charts/BarChart.svelte
function create_fragment8(ctx) {
let bar;
let updating_chart;
let current;
function bar_chart_binding(value) {
ctx[5](value);
}
let bar_props = {
data: (
/*transformedData*/
ctx[1]
),
options: (
/*chartOptions*/
ctx[2]
)
};
if (
/*chartRef*/
ctx[0] !== void 0
) {
bar_props.chart = /*chartRef*/
ctx[0];
}
bar = new Bar_default({ props: bar_props });
binding_callbacks.push(() => bind(bar, "chart", bar_chart_binding));
return {
c() {
create_component(bar.$$.fragment);
},
m(target, anchor) {
mount_component(bar, target, anchor);
current = true;
},
p(ctx2, [dirty]) {
const bar_changes = {};
if (dirty & /*transformedData*/
2)
bar_changes.data = /*transformedData*/
ctx2[1];
if (!updating_chart && dirty & /*chartRef*/
1) {
updating_chart = true;
bar_changes.chart = /*chartRef*/
ctx2[0];
add_flush_callback(() => updating_chart = false);
}
bar.$set(bar_changes);
},
i(local) {
if (current)
return;
transition_in(bar.$$.fragment, local);
current = true;
},
o(local) {
transition_out(bar.$$.fragment, local);
current = false;
},
d(detaching) {
destroy_component(bar, detaching);
}
};
}
var datasetIndex = 0;
function instance8($$self, $$props, $$invalidate) {
let transformedData;
Chart.register(plugin_title, plugin_tooltip, plugin_legend, LineElement, BarElement, LinearScale, PointElement, CategoryScale, plugin_colors);
let { data = [] } = $$props;
let { plugin: plugin2 } = $$props;
let chartRef;
let activeElementIndex;
function transformData(rawData) {
return {
labels: rawData.map((d) => d.date),
datasets: [
{
label: "Average Mood Rating",
data: rawData.map((d) => d.moodRating),
//spanGaps: true,
backgroundColor: rawData.map((x) => hexToRgba(plugin2.settings.chartColor, 0.5)),
hoverBackgroundColor: hexToRgba(plugin2.settings.chartColor, 0.85)
}
]
//pointBackgroundColor: "var(--text-normal)",
};
}
const dispatch = createEventDispatcher();
const onClick = (e) => {
try {
const canvasPosition = getRelativePosition(e, chartRef);
const dataX = chartRef.scales.x.getValueForPixel(canvasPosition.x);
dispatch("clickChart", dataX);
let activeElements = chartRef.getElementsAtEventForMode(e, "nearest", { intersect: true }, true);
if (activeElements.length > 0) {
let firstElement = activeElements[0];
let index = firstElement.index;
$$invalidate(0, chartRef.data.datasets[datasetIndex].backgroundColor[activeElementIndex] = hexToRgba(plugin2.settings.chartColor, 0.5), chartRef);
$$invalidate(0, chartRef.data.datasets[datasetIndex].backgroundColor[index] = hexToRgba(plugin2.settings.chartColor, 0.85), chartRef);
activeElementIndex = index;
} else {
$$invalidate(0, chartRef.data.datasets[datasetIndex].backgroundColor[activeElementIndex] = hexToRgba(plugin2.settings.chartColor, 0.5), chartRef);
}
} catch (error) {
}
};
const chartOptions = {
responsive: true,
onClick,
scales: {
y: {
min: 1,
max: 5,
ticks: {
stepSize: 1,
callback(val, _) {
return plugin2.settings.moodRatingLabelDict[val];
}
}
}
}
};
function bar_chart_binding(value) {
chartRef = value;
$$invalidate(0, chartRef);
}
$$self.$$set = ($$props2) => {
if ("data" in $$props2)
$$invalidate(3, data = $$props2.data);
if ("plugin" in $$props2)
$$invalidate(4, plugin2 = $$props2.plugin);
};
$$self.$$.update = () => {
if ($$self.$$.dirty & /*data*/
8) {
$:
$$invalidate(1, transformedData = transformData(data));
}
};
return [chartRef, transformedData, chartOptions, data, plugin2, bar_chart_binding];
}
var BarChart = class extends SvelteComponent {
constructor(options) {
super();
init(this, options, instance8, create_fragment8, safe_not_equal, { data: 3, plugin: 4 });
}
};
var BarChart_default = BarChart;
// src/stats/statsHelpers.ts
function generateDatasetForDateRange(entries, start2, end2) {
const dayStats = getAverageMoodRatingByDay(entries);
const days = generateStringDatesForDateRange(start2, end2);
const dataset = days.map((day) => {
var _a;
const stat = dayStats.find((x) => x.date == day);
return {
date: day,
moodRating: stat == null ? void 0 : stat.moodRating,
emotions: (_a = stat == null ? void 0 : stat.emotions) != null ? _a : []
};
});
return dataset;
}
function getAverageMoodRatingByDay(entries) {
const entriesByDay = entries.reduce((acc, entry) => {
var _a;
const day = entry.dateTime.toISOString().split("T")[0];
const dayEntries = (_a = acc.get(day)) != null ? _a : [];
dayEntries.push(entry);
acc.set(day, dayEntries);
return acc;
}, /* @__PURE__ */ new Map());
const dayStats = [];
entriesByDay.forEach((dayEntries, day) => {
const dayStat = {
date: day,
moodRating: Math.round(dayEntries.reduce((acc, entry) => acc + entry.moodRating, 0) / dayEntries.length * 10) / 10,
emotions: dayEntries.reduce((acc, entry) => [...acc, ...entry.emotions], [])
};
dayStats.push(dayStat);
});
return dayStats;
}
function getTotalAverageMoodRating(stats) {
const daysWithValues = stats.filter((s) => s.moodRating && s.moodRating > 0);
const totalMoodRating = daysWithValues.reduce((acc, curr) => acc + curr.moodRating, 0);
return Math.round(totalMoodRating / daysWithValues.length * 10) / 10;
}
function getMostCommonMoodRating(entries) {
const moodRatings = entries.map((e) => e.moodRating);
const uniqueMoodRatings = [...new Set(moodRatings)];
const moodRatingCounts = uniqueMoodRatings.map((m) => {
return {
moodRating: m,
count: moodRatings.filter((a) => a === m).length
};
});
const sortedMoodRatings = moodRatingCounts.sort((a, b) => b.count - a.count);
const mostCommonMoodRating = sortedMoodRatings.map((m) => m.moodRating);
return mostCommonMoodRating[0];
}
function getMostCommonEmotions(stats, count) {
const allEmotions = stats.map((s) => s.emotions).flat();
const uniqueEmotions = [...new Set(allEmotions)];
const emotionCounts = uniqueEmotions.map((e) => {
return {
emotion: e,
count: allEmotions.filter((a) => a === e).length
};
});
const sortedEmotions = emotionCounts.sort((a, b) => b.count - a.count);
const mostCommonEmotions = sortedEmotions.map((e) => e.emotion);
return mostCommonEmotions.splice(0, count);
}
function generateStringDatesForDateRange(start2, end2) {
const datesArray = [];
const startDate = new Date(start2);
const startDateCorrected = startDate.getFullYear() > 2e3 ? startDate : new Date("2000-01-01");
const endDate = new Date(end2);
const currentDate = new Date();
const endDateCorrected = endDate.getFullYear() > currentDate.getFullYear() ? currentDate : endDate;
while (startDateCorrected <= endDateCorrected) {
const formattedDate = startDateCorrected.toISOString().split("T")[0];
datesArray.push(formattedDate);
startDateCorrected.setDate(startDateCorrected.getDate() + 1);
}
return datesArray;
}
// src/statsModal/deleteEntryModal.ts
var DeleteEntryModal = class extends ConfirmationModal {
constructor(plugin2, entry, onDeleteCallback) {
super(plugin2.app, "Delete mood tracking entry", () => this.deleteEntry(entry));
this.plugin = plugin2;
this.onDeleteCallback = onDeleteCallback;
this.setContent(`Delete mood tracking entry for ${entry.dateTime}?`);
}
async deleteEntry(entry) {
await this.plugin.deleteEntry(entry);
this.onDeleteCallback(entry);
this.close();
}
};
// src/statsModal/SelectedDay.svelte
function get_each_context2(ctx, list, i) {
const child_ctx = ctx.slice();
child_ctx[9] = list[i];
return child_ctx;
}
function create_else_block(ctx) {
let each_1_anchor;
let each_value = (
/*data*/
ctx[0]
);
let each_blocks = [];
for (let i = 0; i < each_value.length; i += 1) {
each_blocks[i] = create_each_block2(get_each_context2(ctx, each_value, i));
}
return {
c() {
for (let i = 0; i < each_blocks.length; i += 1) {
each_blocks[i].c();
}
each_1_anchor = empty();
},
m(target, anchor) {
for (let i = 0; i < each_blocks.length; i += 1) {
if (each_blocks[i]) {
each_blocks[i].m(target, anchor);
}
}
insert(target, each_1_anchor, anchor);
},
p(ctx2, dirty) {
if (dirty & /*data, moodRatingDict, getTimeFromDate, deleteEntry, openMoodTrackerModal*/
53) {
each_value = /*data*/
ctx2[0];
let i;
for (i = 0; i < each_value.length; i += 1) {
const child_ctx = get_each_context2(ctx2, each_value, i);
if (each_blocks[i]) {
each_blocks[i].p(child_ctx, dirty);
} else {
each_blocks[i] = create_each_block2(child_ctx);
each_blocks[i].c();
each_blocks[i].m(each_1_anchor.parentNode, each_1_anchor);
}
}
for (; i < each_blocks.length; i += 1) {
each_blocks[i].d(1);
}
each_blocks.length = each_value.length;
}
},
d(detaching) {
destroy_each(each_blocks, detaching);
if (detaching)
detach(each_1_anchor);
}
};
}
function create_if_block2(ctx) {
let div;
return {
c() {
div = element("div");
div.textContent = "No entries for this day. Click diagram to select another day.";
},
m(target, anchor) {
insert(target, div, anchor);
},
p: noop,
d(detaching) {
if (detaching)
detach(div);
}
};
}
function create_if_block_1(ctx) {
let span;
let t0;
let i;
let t1_value = (
/*entry*/
ctx[9].note + ""
);
let t1;
return {
c() {
span = element("span");
t0 = text("\u{1F4C4} ");
i = element("i");
t1 = text(t1_value);
},
m(target, anchor) {
insert(target, span, anchor);
append(span, t0);
append(span, i);
append(i, t1);
},
p(ctx2, dirty) {
if (dirty & /*data*/
1 && t1_value !== (t1_value = /*entry*/
ctx2[9].note + ""))
set_data(t1, t1_value);
},
d(detaching) {
if (detaching)
detach(span);
}
};
}
function create_each_block2(ctx) {
let div;
let span0;
let t1;
let span1;
let t3;
let span2;
let t4_value = getTimeFromDate(
/*entry*/
ctx[9].dateTime
) + "";
let t4;
let t5;
let t6_value = (
/*moodRatingDict*/
ctx[2][
/*entry*/
ctx[9].moodRating
] + ""
);
let t6;
let t7;
let t8_value = (
/*entry*/
ctx[9].emotions.join(", ") + ""
);
let t8;
let t9;
let t10;
let mounted;
let dispose;
function click_handler() {
return (
/*click_handler*/
ctx[7](
/*entry*/
ctx[9]
)
);
}
function click_handler_1() {
return (
/*click_handler_1*/
ctx[8](
/*entry*/
ctx[9]
)
);
}
let if_block = (
/*entry*/
ctx[9].note && create_if_block_1(ctx)
);
return {
c() {
div = element("div");
span0 = element("span");
span0.textContent = "\u270F\uFE0F";
t1 = space();
span1 = element("span");
span1.textContent = "\u{1F5D1}\uFE0F";
t3 = space();
span2 = element("span");
t4 = text(t4_value);
t5 = space();
t6 = text(t6_value);
t7 = space();
t8 = text(t8_value);
t9 = space();
if (if_block)
if_block.c();
t10 = space();
set_style(span0, "cursor", "pointer");
attr(span0, "title", "edit entry");
set_style(span1, "cursor", "pointer");
attr(span1, "title", "delete entry");
},
m(target, anchor) {
insert(target, div, anchor);
append(div, span0);
append(div, t1);
append(div, span1);
append(div, t3);
append(div, span2);
append(span2, t4);
append(span2, t5);
append(span2, t6);
append(span2, t7);
append(span2, t8);
append(div, t9);
if (if_block)
if_block.m(div, null);
append(div, t10);
if (!mounted) {
dispose = [
listen(span0, "click", click_handler),
listen(span1, "click", click_handler_1)
];
mounted = true;
}
},
p(new_ctx, dirty) {
ctx = new_ctx;
if (dirty & /*data*/
1 && t4_value !== (t4_value = getTimeFromDate(
/*entry*/
ctx[9].dateTime
) + ""))
set_data(t4, t4_value);
if (dirty & /*moodRatingDict, data*/
5 && t6_value !== (t6_value = /*moodRatingDict*/
ctx[2][
/*entry*/
ctx[9].moodRating
] + ""))
set_data(t6, t6_value);
if (dirty & /*data*/
1 && t8_value !== (t8_value = /*entry*/
ctx[9].emotions.join(", ") + ""))
set_data(t8, t8_value);
if (
/*entry*/
ctx[9].note
) {
if (if_block) {
if_block.p(ctx, dirty);
} else {
if_block = create_if_block_1(ctx);
if_block.c();
if_block.m(div, t10);
}
} else if (if_block) {
if_block.d(1);
if_block = null;
}
},
d(detaching) {
if (detaching)
detach(div);
if (if_block)
if_block.d();
mounted = false;
run_all(dispose);
}
};
}
function create_fragment9(ctx) {
let div1;
let h4;
let t0;
let t1;
let t2;
let div0;
let button;
let mounted;
let dispose;
function select_block_type(ctx2, dirty) {
if (!/*data*/
ctx2[0] || /*data*/
ctx2[0].length === 0)
return create_if_block2;
return create_else_block;
}
let current_block_type = select_block_type(ctx, -1);
let if_block = current_block_type(ctx);
return {
c() {
div1 = element("div");
h4 = element("h4");
t0 = text(
/*dateString*/
ctx[1]
);
t1 = space();
if_block.c();
t2 = space();
div0 = element("div");
button = element("button");
button.textContent = "add a new entry";
set_style(button, "cursor", "pointer");
set_style(button, "margin-top", "0.5rem");
},
m(target, anchor) {
insert(target, div1, anchor);
append(div1, h4);
append(h4, t0);
append(div1, t1);
if_block.m(div1, null);
append(div1, t2);
append(div1, div0);
append(div0, button);
if (!mounted) {
dispose = listen(
button,
"click",
/*openModalForNewEntry*/
ctx[3]
);
mounted = true;
}
},
p(ctx2, [dirty]) {
if (dirty & /*dateString*/
2)
set_data(
t0,
/*dateString*/
ctx2[1]
);
if (current_block_type === (current_block_type = select_block_type(ctx2, dirty)) && if_block) {
if_block.p(ctx2, dirty);
} else {
if_block.d(1);
if_block = current_block_type(ctx2);
if (if_block) {
if_block.c();
if_block.m(div1, t2);
}
}
},
i: noop,
o: noop,
d(detaching) {
if (detaching)
detach(div1);
if_block.d();
mounted = false;
dispose();
}
};
}
function getTimeFromDate(date) {
const hours = date.getHours().toString().padStart(2, "0");
const minutes = date.getMinutes().toString().padStart(2, "0");
return `${hours}:${minutes}`;
}
function instance9($$self, $$props, $$invalidate) {
let { data } = $$props;
let { dateString } = $$props;
let { plugin: plugin2 } = $$props;
let { moodRatingDict = plugin2.settings.moodRatingLabelDict } = $$props;
function openModalForNewEntry() {
const entry = new MoodTrackerEntry();
entry.dateTime = new Date(dateString);
entry.dateTime.setHours(9);
openMoodTrackerModal(entry);
}
function openMoodTrackerModal(entry) {
plugin2.openTrackerModal(entry, true);
}
function deleteEntry(entry) {
new DeleteEntryModal(
plugin2,
entry,
(entry2) => {
$$invalidate(0, data = data.filter((x) => x.id !== entry2.id));
}
).open();
}
const click_handler = (entry) => openMoodTrackerModal(entry);
const click_handler_1 = (entry) => deleteEntry(entry);
$$self.$$set = ($$props2) => {
if ("data" in $$props2)
$$invalidate(0, data = $$props2.data);
if ("dateString" in $$props2)
$$invalidate(1, dateString = $$props2.dateString);
if ("plugin" in $$props2)
$$invalidate(6, plugin2 = $$props2.plugin);
if ("moodRatingDict" in $$props2)
$$invalidate(2, moodRatingDict = $$props2.moodRatingDict);
};
return [
data,
dateString,
moodRatingDict,
openModalForNewEntry,
openMoodTrackerModal,
deleteEntry,
plugin2,
click_handler,
click_handler_1
];
}
var SelectedDay = class extends SvelteComponent {
constructor(options) {
super();
init(this, options, instance9, create_fragment9, safe_not_equal, {
data: 0,
dateString: 1,
plugin: 6,
moodRatingDict: 2
});
}
};
var SelectedDay_default = SelectedDay;
// src/statsModal/StatsComponent.svelte
function add_css6(target) {
append_styles(target, "svelte-1u58dq6", ".date-picker-container.svelte-1u58dq6{margin-bottom:0.5rem}.total-stats-container.svelte-1u58dq6{margin-top:1rem}");
}
function create_fragment10(ctx) {
let h22;
let t1;
let div0;
let t2;
let input0;
let input0_pattern_value;
let t3;
let input1;
let input1_pattern_value;
let t4;
let statschart;
let t5;
let div4;
let div1;
let t6;
let t7_value = (
/*moodRatingLabelDict*/
ctx[5][Math.round(
/*averageMoodRating*/
ctx[9]
)] + ""
);
let t7;
let t8;
let t9;
let t10;
let t11;
let div2;
let t12;
let t13_value = (
/*moodRatingLabelDict*/
ctx[5][
/*mostCommonMood*/
ctx[8]
] + ""
);
let t13;
let t14;
let div3;
let t15;
let t16_value = (
/*mostCommonEmotions*/
ctx[7].join(", ") + ""
);
let t16;
let t17;
let selectedday;
let current;
let mounted;
let dispose;
statschart = new BarChart_default({
props: {
data: (
/*processedData*/
ctx[1]
),
plugin: (
/*plugin*/
ctx[2]
)
}
});
statschart.$on(
"clickChart",
/*onClickChart*/
ctx[11]
);
selectedday = new SelectedDay_default({
props: {
plugin: (
/*plugin*/
ctx[2]
),
dateString: (
/*selectedDateString*/
ctx[0]
),
data: (
/*selectedDayData*/
ctx[6]
),
moodRatingDict: (
/*moodRatingLabelDict*/
ctx[5]
)
}
});
return {
c() {
h22 = element("h2");
h22.textContent = "Mood Tracking History";
t1 = space();
div0 = element("div");
t2 = text("from: ");
input0 = element("input");
t3 = text("\n to: ");
input1 = element("input");
t4 = space();
create_component(statschart.$$.fragment);
t5 = space();
div4 = element("div");
div1 = element("div");
t6 = text("Average mood: ");
t7 = text(t7_value);
t8 = text(" (");
t9 = text(
/*averageMoodRating*/
ctx[9]
);
t10 = text(")");
t11 = space();
div2 = element("div");
t12 = text("Most common mood: ");
t13 = text(t13_value);
t14 = space();
div3 = element("div");
t15 = text("Common emotions: ");
t16 = text(t16_value);
t17 = space();
create_component(selectedday.$$.fragment);
attr(input0, "type", "date");
attr(input0, "min", "2000-01-01");
attr(input0, "pattern", input0_pattern_value = "\\d" + 4 + "-\\d" + 2 + "-\\d" + 2);
attr(input1, "type", "date");
attr(input1, "min", "2000-01-01");
input1.required = true;
attr(input1, "pattern", input1_pattern_value = "\\d" + 4 + "-\\d" + 2 + "-\\d" + 2);
attr(div0, "class", "date-picker-container svelte-1u58dq6");
attr(div4, "class", "total-stats-container svelte-1u58dq6");
},
m(target, anchor) {
insert(target, h22, anchor);
insert(target, t1, anchor);
insert(target, div0, anchor);
append(div0, t2);
append(div0, input0);
set_input_value(
input0,
/*startDate*/
ctx[3]
);
append(div0, t3);
append(div0, input1);
set_input_value(
input1,
/*endDate*/
ctx[4]
);
insert(target, t4, anchor);
mount_component(statschart, target, anchor);
insert(target, t5, anchor);
insert(target, div4, anchor);
append(div4, div1);
append(div1, t6);
append(div1, t7);
append(div1, t8);
append(div1, t9);
append(div1, t10);
append(div4, t11);
append(div4, div2);
append(div2, t12);
append(div2, t13);
append(div4, t14);
append(div4, div3);
append(div3, t15);
append(div3, t16);
insert(target, t17, anchor);
mount_component(selectedday, target, anchor);
current = true;
if (!mounted) {
dispose = [
listen(
input0,
"input",
/*input0_input_handler*/
ctx[14]
),
listen(
input0,
"change",
/*generateDatasetDebounced*/
ctx[10]
),
listen(
input1,
"input",
/*input1_input_handler*/
ctx[15]
),
listen(
input1,
"change",
/*generateDatasetDebounced*/
ctx[10]
)
];
mounted = true;
}
},
p(ctx2, [dirty]) {
if (dirty & /*startDate*/
8) {
set_input_value(
input0,
/*startDate*/
ctx2[3]
);
}
if (dirty & /*endDate*/
16) {
set_input_value(
input1,
/*endDate*/
ctx2[4]
);
}
const statschart_changes = {};
if (dirty & /*processedData*/
2)
statschart_changes.data = /*processedData*/
ctx2[1];
if (dirty & /*plugin*/
4)
statschart_changes.plugin = /*plugin*/
ctx2[2];
statschart.$set(statschart_changes);
if ((!current || dirty & /*moodRatingLabelDict, averageMoodRating*/
544) && t7_value !== (t7_value = /*moodRatingLabelDict*/
ctx2[5][Math.round(
/*averageMoodRating*/
ctx2[9]
)] + ""))
set_data(t7, t7_value);
if (!current || dirty & /*averageMoodRating*/
512)
set_data(
t9,
/*averageMoodRating*/
ctx2[9]
);
if ((!current || dirty & /*moodRatingLabelDict, mostCommonMood*/
288) && t13_value !== (t13_value = /*moodRatingLabelDict*/
ctx2[5][
/*mostCommonMood*/
ctx2[8]
] + ""))
set_data(t13, t13_value);
if ((!current || dirty & /*mostCommonEmotions*/
128) && t16_value !== (t16_value = /*mostCommonEmotions*/
ctx2[7].join(", ") + ""))
set_data(t16, t16_value);
const selectedday_changes = {};
if (dirty & /*plugin*/
4)
selectedday_changes.plugin = /*plugin*/
ctx2[2];
if (dirty & /*selectedDateString*/
1)
selectedday_changes.dateString = /*selectedDateString*/
ctx2[0];
if (dirty & /*selectedDayData*/
64)
selectedday_changes.data = /*selectedDayData*/
ctx2[6];
if (dirty & /*moodRatingLabelDict*/
32)
selectedday_changes.moodRatingDict = /*moodRatingLabelDict*/
ctx2[5];
selectedday.$set(selectedday_changes);
},
i(local) {
if (current)
return;
transition_in(statschart.$$.fragment, local);
transition_in(selectedday.$$.fragment, local);
current = true;
},
o(local) {
transition_out(statschart.$$.fragment, local);
transition_out(selectedday.$$.fragment, local);
current = false;
},
d(detaching) {
if (detaching)
detach(h22);
if (detaching)
detach(t1);
if (detaching)
detach(div0);
if (detaching)
detach(t4);
destroy_component(statschart, detaching);
if (detaching)
detach(t5);
if (detaching)
detach(div4);
if (detaching)
detach(t17);
destroy_component(selectedday, detaching);
mounted = false;
run_all(dispose);
}
};
}
function subtractDays(date, days) {
const dateCopy = new Date(date);
dateCopy.setDate(dateCopy.getDate() - days);
return dateCopy;
}
function instance10($$self, $$props, $$invalidate) {
let averageMoodRating;
let mostCommonMood;
let mostCommonEmotions;
let selectedDayData;
var _a, _b, _c;
let plugin2;
let startDate = DateService.createDateString(subtractDays(new Date(), 14));
let endDate = DateService.createDateString(new Date());
let moodRatingLabelDict = {};
let timer;
let rawData = (_b = (_a = this.plugin) === null || _a === void 0 ? void 0 : _a.entries) !== null && _b !== void 0 ? _b : [];
let processedData = [];
store_default.plugin.subscribe((p) => {
var _a2, _b2, _c2;
$$invalidate(2, plugin2 = p);
$$invalidate(13, rawData = (_a2 = plugin2 === null || plugin2 === void 0 ? void 0 : plugin2.entries) !== null && _a2 !== void 0 ? _a2 : []);
$$invalidate(1, processedData = generateDatasetForDateRange(rawData, startDate, endDate));
$$invalidate(5, moodRatingLabelDict = (_c2 = (_b2 = plugin2 === null || plugin2 === void 0 ? void 0 : plugin2.settings) === null || _b2 === void 0 ? void 0 : _b2.moodRatingLabelDict) !== null && _c2 !== void 0 ? _c2 : {});
});
let { selectedDateString } = $$props;
function generateDatasetDebounced() {
clearTimeout(timer);
timer = setTimeout(
() => {
$$invalidate(1, processedData = generateDatasetForDateRange(rawData, startDate, endDate));
},
1e3
);
}
function onClickChart(event) {
$$invalidate(0, selectedDateString = processedData[event.detail].date);
}
function input0_input_handler() {
startDate = this.value;
$$invalidate(3, startDate);
}
function input1_input_handler() {
endDate = this.value;
$$invalidate(4, endDate);
}
$$self.$$set = ($$props2) => {
if ("selectedDateString" in $$props2)
$$invalidate(0, selectedDateString = $$props2.selectedDateString);
};
$$self.$$.update = () => {
if ($$self.$$.dirty & /*processedData*/
2) {
$:
$$invalidate(9, averageMoodRating = getTotalAverageMoodRating(processedData));
}
if ($$self.$$.dirty & /*rawData*/
8192) {
$:
$$invalidate(8, mostCommonMood = getMostCommonMoodRating(rawData));
}
if ($$self.$$.dirty & /*processedData*/
2) {
$:
$$invalidate(7, mostCommonEmotions = getMostCommonEmotions(processedData, 3));
}
if ($$self.$$.dirty & /*rawData, selectedDateString, _c*/
12289) {
$:
$$invalidate(6, selectedDayData = $$invalidate(12, _c = rawData.filter((d) => DateService.createDateString(d === null || d === void 0 ? void 0 : d.dateTime) === selectedDateString)) !== null && _c !== void 0 ? _c : []);
}
};
return [
selectedDateString,
processedData,
plugin2,
startDate,
endDate,
moodRatingLabelDict,
selectedDayData,
mostCommonEmotions,
mostCommonMood,
averageMoodRating,
generateDatasetDebounced,
onClickChart,
_c,
rawData,
input0_input_handler,
input1_input_handler
];
}
var StatsComponent = class extends SvelteComponent {
constructor(options) {
super();
init(this, options, instance10, create_fragment10, safe_not_equal, { selectedDateString: 0 }, add_css6);
}
};
var StatsComponent_default = StatsComponent;
// src/statsModal/moodTrackerStatsModal.ts
var MoodTrackerStatsModal = class extends import_obsidian7.Modal {
constructor(app2, plugin2, selectedDate) {
super(app2);
this.plugin = plugin2;
this.selectedDate = selectedDate;
}
async onOpen() {
store_default.plugin.set(this.plugin);
this.modalEl.addClass("mood-tracker-modal");
await this.plugin.loadEntries();
this.component = new StatsComponent_default({
target: this.contentEl,
props: {
selectedDateString: DateService.createDateString(this.selectedDate)
}
});
}
onClose() {
this.component.$destroy();
}
};
// src/filesIntegration/fileService.ts
var import_obsidian8 = require("obsidian");
// src/filesIntegration/createFileModal.ts
var CreateFileModal = class extends ConfirmationModal {
constructor(app2, path, content) {
super(app2, "File does not exist", () => this.createFile(path, content));
this.setContent(`The file at location "${path}" doesn't exist.
Would you like to create it?`);
}
async createFile(path, content) {
const { vault } = this.app;
const directoryPath = path.substring(0, path.lastIndexOf("/"));
if (directoryPath != "" && !vault.getFolderByPath(directoryPath)) {
await vault.createFolder(directoryPath);
}
await vault.create(path, content);
this.close();
}
};
// src/filesIntegration/fileService.ts
var FileService = class {
constructor(_plugin) {
this._plugin = _plugin;
}
async addEntryToJournal(entry) {
if (!this._plugin.settings.journalFilePath) {
await this.appendToCurrentNote(entry);
}
const filePath = this.replaceVariablesInTemplatedPath(
this._plugin.settings.journalFilePath,
entry.dateTime
);
const file = this._plugin.app.vault.getFileByPath(filePath);
if (file !== null) {
await this.appendEntryToFile(entry, file);
return;
}
const modal = new CreateFileModal(
this._plugin.app,
filePath,
this.getEntryAsString(entry)
);
modal.open();
}
async appendToCurrentNote(entry) {
const file = this._plugin.app.workspace.getActiveFile();
this.appendEntryToFile(entry, file);
}
replaceVariablesInTemplatedPath(templatedPath, date) {
const regex = /{{DATE:(.*?)}}/g;
return templatedPath.replace(regex, (match, dateFormat) => {
dateFormat != null ? dateFormat : dateFormat = "yyyy-MM-dd";
return window.moment(date).format(dateFormat);
});
}
async appendEntryToFile(entry, file) {
if (!(file instanceof import_obsidian8.TFile)) {
return;
}
const result = this.getEntryAsString(entry);
const content = await this._plugin.app.vault.read(file);
const contentArray = content.split("\n");
let index = contentArray.indexOf(this._plugin.settings.journalPosition);
if (index != -1 && index != contentArray.length && index + 1 != contentArray.length) {
while (contentArray[index + 1].startsWith("-")) {
index = index + 1;
if (index == contentArray.length || contentArray[index + 1] == void 0) {
break;
}
}
contentArray.splice(index + 1, 0, `${result}`);
this._plugin.app.vault.modify(file, contentArray.join("\n"));
} else {
if (index + 1 != contentArray.length) {
this._plugin.showNotice(
`could not find the selected position in your journal-file -> Adding mood to the bottom.`,
5e3,
`Mood Tracker`
);
}
let original_content = content.replace(/\n+$/g, "");
this._plugin.app.vault.modify(file, original_content + "\n" + result);
}
return;
}
getEntryAsString(entry) {
const templ = this._plugin.settings.entryTemplate;
return templ.replace("{{TIME}}", window.moment(entry.dateTime).format("HH:mm")).replace("{{DATE}}", window.moment(entry.dateTime).format("YYYY-MM-DD")).replace(
"{{ICON}}",
this._plugin.settings.moodRatingLabelDict[entry.moodRating]
).replace("{{EMOTIONS}}", entry.emotions.join(", ")).replace("{{NOTE}}", entry.note);
}
};
// src/services/dataIntegrityService.ts
var import_crypto2 = require("crypto");
var DataIntegrityService = class {
safeMergeData(entries1, entries2) {
const entryMap = /* @__PURE__ */ new Map();
const addEntriesToMap = (entries) => {
for (const entry of entries) {
entryMap.set(entry.id, entry);
}
};
addEntriesToMap(entries1);
addEntriesToMap(entries2);
return Array.from(entryMap.values());
}
fillMissingIds(emotionGroups) {
emotionGroups.forEach((eg) => {
if (!eg.id) {
eg.id = (0, import_crypto2.randomUUID)();
}
});
}
legacyEmotionSectionsToEmotionGroups(emotionSections) {
return emotionSections.map((x) => {
var _a;
const eg = new EmotionGroup();
eg.color = x.color;
eg.emotions = x.emotions;
eg.name = (_a = x.name) != null ? _a : "unnamed group";
eg.id = (0, import_crypto2.randomUUID)();
return eg;
});
}
};
// src/services/emotionsService.ts
var EmotionsService = class {
constructor(_plugin) {
this._plugin = _plugin;
}
async saveEmotionsGroup(emotionGroup) {
this._plugin.settings.emotionGroups.forEach((x) => {
if (x.id === emotionGroup.id) {
x = emotionGroup;
}
});
await this._plugin.saveSettings();
}
async deleteEmotionsGroup(emotionGroup) {
this._plugin.settings.emotionGroups.remove(emotionGroup);
await this._plugin.saveSettings();
}
sortEmotionGroups(emotionGroups) {
const maxSortOrder = emotionGroups.reduce((max2, group) => {
if (group.sortOrder !== void 0 && group.sortOrder > max2) {
return group.sortOrder;
}
return max2;
}, 0);
let nextSortOrder = maxSortOrder + 1;
const filledGroups = emotionGroups.map((emotionGroup) => ({
...emotionGroup,
sortOrder: emotionGroup.sortOrder !== void 0 ? emotionGroup.sortOrder : nextSortOrder++
}));
filledGroups.sort((a, b) => a.sortOrder - b.sortOrder);
return filledGroups;
}
};
// src/stats/statsCodeblockRenderer.ts
var STATS_CODEBLOCK_NAME = "mood-tracker-stats";
var defaultConfig = {
daysBeforeEnd: 14,
end: "today",
showAverage: false,
showMostCommonMood: false,
showCommonEmotionsList: false,
height: "350px",
width: "100%"
};
var StatsCodeblockRenderer = class {
constructor(code, parentEl, _plugin) {
this.parentEl = parentEl;
this._plugin = _plugin;
const config = this.parseConfig(code);
if (config === null) {
return;
}
this._config = config;
}
render() {
var _a, _b;
const rawData = (_b = (_a = this._plugin) == null ? void 0 : _a.entries) != null ? _b : [];
const endDate = this.getEndDate(this._config.end);
const startDate = window.moment(endDate).subtract(this._config.daysBeforeEnd, "days").toDate();
const processedData = generateDatasetForDateRange(
rawData,
startDate,
endDate
);
this._stats = processedData;
const containerEl = this.parentEl.createDiv("mood-tracker-stats-codeblock");
containerEl.style.height = this._config.height;
containerEl.style.width = this._config.width;
new BarChart_default({
target: containerEl,
props: {
data: processedData,
plugin: this._plugin
}
});
if (this._config.showAverage) {
this.renderAverage(this.parentEl);
}
if (this._config.showMostCommonMood) {
this.renderMostCommonMood(this.parentEl);
}
if (this._config.showCommonEmotionsList) {
this.renderCommonEmotionsList(this.parentEl);
}
}
getEndDate(rangeEndRaw) {
switch (rangeEndRaw) {
case "today":
return new Date();
case "previous-month":
return window.moment().subtract(1, "months").endOf("month").toDate();
case "current-month":
return window.moment().endOf("month").toDate();
case "previous-week":
return window.moment().subtract(1, "weeks").endOf("isoWeek").toDate();
case "current-week":
return window.moment().endOf("isoWeek").toDate();
default:
try {
return new Date(rangeEndRaw);
} catch (error) {
this._plugin.showNotice(
`Mood Tracker: error parsing date ${rangeEndRaw}.`
);
throw error;
}
}
}
renderAverage(containerEl) {
const averageMoodRating = getTotalAverageMoodRating(this._stats);
const text2 = `Average mood: ${this._plugin.settings.moodRatingLabelDict[Math.round(averageMoodRating)]} (${averageMoodRating})`;
containerEl.createDiv({ text: text2 });
}
renderMostCommonMood(containerEl) {
const mostCommonMood = getMostCommonMoodRating(this._plugin.entries);
const text2 = `Most common mood: ${this._plugin.settings.moodRatingLabelDict[mostCommonMood]}`;
containerEl.createDiv({ text: text2 });
}
renderCommonEmotionsList(containerEl) {
const mostCommonEmotions = getMostCommonEmotions(this._stats, 3);
const text2 = `Common emotions: ${mostCommonEmotions.join(", ")}`;
containerEl.createDiv({ text: text2 });
}
parseConfig(configStr) {
const configLines = configStr.split("\n").map((line) => line.trim()).filter((line) => line);
const config = defaultConfig;
for (const line of configLines) {
const [key, value] = line.split(":").map((part) => part.trim());
switch (key) {
case "end":
config.end = value;
break;
case "daysBeforeEnd":
config.daysBeforeEnd = Number.parseInt(value);
break;
case "showAverage":
config.showAverage = value.toLowerCase() === "true";
break;
case "showMostCommonMood":
config.showMostCommonMood = value.toLowerCase() === "true";
break;
case "showCommonEmotionsList":
config.showCommonEmotionsList = value.toLowerCase() === "true";
break;
}
}
return config;
}
};
// src/main.ts
var MoodTrackerPlugin = class extends import_obsidian9.Plugin {
constructor() {
super(...arguments);
this.dataFileName = "mood-tracker-data.json";
this.entries = [];
this.persistenceService = new PersistenceService(this);
this.dataIntegrityService = new DataIntegrityService();
this.noteService = new FileService(this);
this.emotionService = new EmotionsService(this);
this.moodTrackerService = new MoodTrackerService(
this.persistenceService
);
}
async onload() {
await this.loadSettings();
await this.loadEntries();
this.addRibbonIcons();
this.addCommands();
this.addCodeblockRenderers();
this.addSettingTab(new MoodTrackerSettingsTab(this, this.app));
}
onunload() {
}
openTrackerModal(entry = void 0, reopenStatsModalOnClose = false) {
new MoodTrackerModal(
this.app,
this,
entry,
reopenStatsModalOnClose
).open();
}
openStatsModal(selectedDate = new Date()) {
if (this.activeStatsModel) {
this.activeStatsModel.close();
}
this.activeStatsModel = new MoodTrackerStatsModal(
this.app,
this,
selectedDate
);
this.activeStatsModel.open();
}
async loadEntries() {
var _a;
const loadedEntries = (_a = await this.persistenceService.getEntries()) != null ? _a : [];
this.entries = this.dataIntegrityService.safeMergeData(
loadedEntries,
this.entries
);
}
async saveEntries() {
await this.persistenceService.saveEntries();
}
async saveEntry(entry) {
const index = this.entries.findIndex((e) => e.id === entry.id);
if (index === -1) {
this.entries.push(entry);
} else {
this.entries[index] = entry;
}
await this.saveEntries();
}
async deleteEntry(entry) {
const index = this.entries.findIndex((e) => e.id === entry.id);
if (index !== -1) {
this.entries.remove(entry);
}
await this.saveEntries();
}
showNotice(message, durationMs = 5e3, title) {
if (typeof title !== "undefined") {
const notice = new import_obsidian9.Notice("", durationMs);
notice.noticeEl.append(
createEl("strong", { text: title, cls: "mood-tracker-notice-header" }),
createEl("br"),
message
);
} else {
new import_obsidian9.Notice(message, durationMs);
}
}
async loadSettings() {
const loadedData = Object.assign(
{},
DEFAULT_SETTINGS,
await this.loadData()
);
const legacyEmotions = loadedData.emotions;
if (legacyEmotions && Array.isArray(legacyEmotions) && legacyEmotions.length > 0 && typeof legacyEmotions[0] === "string") {
const migratedSettings = new MoodTrackerSettings();
migratedSettings.folderPath = loadedData.folderPath;
migratedSettings.moodRatingLabelDict = loadedData.moodRatingLabelDict;
const emotionGroup = new EmotionGroup();
emotionGroup.color = "#b8c1cf";
emotionGroup.name = "";
emotionGroup.emotions = legacyEmotions;
migratedSettings.emotionGroups = [];
migratedSettings.emotionGroups.push(emotionGroup);
this.settings = Object.assign(
{},
DEFAULT_SETTINGS,
migratedSettings
);
this.showNotice(
"Mood Tracker has been updated. Check out the new emotion settings!",
15e3
);
await this.saveSettings();
} else {
this.settings = loadedData;
const legacyEmotionSections = loadedData.emotionSections;
if (legacyEmotionSections) {
const convertedLegacyEmotionSections = this.dataIntegrityService.legacyEmotionSectionsToEmotionGroups(
legacyEmotionSections
);
this.settings.emotionGroups.push(
...convertedLegacyEmotionSections
);
this.settings["emotionSections"] = null;
delete this.settings["emotionSections"];
}
this.settings.emotionGroups = this.emotionService.sortEmotionGroups(
this.settings.emotionGroups
);
this.dataIntegrityService.fillMissingIds(
this.settings.emotionGroups
);
await this.saveSettings();
}
}
async saveSettings() {
this.settings.emotionGroups = this.emotionService.sortEmotionGroups(
this.settings.emotionGroups
);
await this.saveData(this.settings);
}
addRibbonIcons() {
this.addRibbonIcon(
"smile-plus",
"Open Mood Tracker",
(evt) => {
this.openTrackerModal();
}
);
this.addRibbonIcon(
"line-chart",
"Open Mood Tracking History",
(evt) => {
this.openStatsModal();
}
);
}
addCommands() {
this.addCommand({
id: "open-mood-tracker",
name: "Open Tracker",
callback: () => {
this.openTrackerModal();
}
});
this.addCommand({
id: "open-mood-tracker-history",
name: "Open History",
callback: () => {
this.openStatsModal();
}
});
}
addCodeblockRenderers() {
this.registerMarkdownCodeBlockProcessor(STATS_CODEBLOCK_NAME, (source, el, ctx) => {
const renderer = new StatsCodeblockRenderer(source, el, this);
renderer.render();
});
}
};
/*! Bundled license information:
@kurkle/color/dist/color.esm.js:
(*!
* @kurkle/color v0.3.2
* https://github.com/kurkle/color#readme
* (c) 2023 Jukka Kurkela
* Released under the MIT License
*)
chart.js/dist/chunks/helpers.segment.js:
(*!
* Chart.js v4.2.1
* https://www.chartjs.org
* (c) 2023 Chart.js Contributors
* Released under the MIT License
*)
chart.js/dist/chart.js:
(*!
* Chart.js v4.2.1
* https://www.chartjs.org
* (c) 2023 Chart.js Contributors
* Released under the MIT License
*)
chart.js/dist/helpers.js:
(*!
* Chart.js v4.2.1
* https://www.chartjs.org
* (c) 2023 Chart.js Contributors
* Released under the MIT License
*)
*/