/* 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).
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.
Supports moment.js formatting.
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?
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:
{{DATE}} - date of entry
{{TIME}} - time of entry
{{ICON}} - entry's mood icon
{{NOTE}} - entry's note
{{EMOTIONS}} - comma-separated list of emotions, if any
`; 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 *) */