UNPKG

bbl-gantt

Version:

一个框架无关的JS甘特图库,支持resize、拖拽新建、支持自定义样式、以及支持duration模式等功能。A framework-independent JS Gantt chart library, supporting resize, drag-and-drop to create new tasks, custom styling, and duration mode functionalities.

1,735 lines 330 kB
const methods$1 = {}; const names = []; function registerMethods(name, m) { if (Array.isArray(name)) { for (const _name of name) { registerMethods(_name, m); } return; } if (typeof name === "object") { for (const _name in name) { registerMethods(_name, name[_name]); } return; } addMethodNames(Object.getOwnPropertyNames(m)); methods$1[name] = Object.assign(methods$1[name] || {}, m); } function getMethodsFor(name) { return methods$1[name] || {}; } function getMethodNames() { return [...new Set(names)]; } function addMethodNames(_names) { names.push(..._names); } function map(array2, block) { let i; const il = array2.length; const result = []; for (i = 0; i < il; i++) { result.push(block(array2[i])); } return result; } function filter(array2, block) { let i; const il = array2.length; const result = []; for (i = 0; i < il; i++) { if (block(array2[i])) { result.push(array2[i]); } } return result; } function radians(d) { return d % 360 * Math.PI / 180; } function unCamelCase(s) { return s.replace(/([A-Z])/g, function(m, g) { return "-" + g.toLowerCase(); }); } function capitalize(s) { return s.charAt(0).toUpperCase() + s.slice(1); } function proportionalSize(element, width2, height2, box) { if (width2 == null || height2 == null) { box = box || element.bbox(); if (width2 == null) { width2 = box.width / box.height * height2; } else if (height2 == null) { height2 = box.height / box.width * width2; } } return { width: width2, height: height2 }; } function getOrigin(o, element) { const origin = o.origin; let ox = o.ox != null ? o.ox : o.originX != null ? o.originX : "center"; let oy = o.oy != null ? o.oy : o.originY != null ? o.originY : "center"; if (origin != null) { [ox, oy] = Array.isArray(origin) ? origin : typeof origin === "object" ? [origin.x, origin.y] : [origin, origin]; } const condX = typeof ox === "string"; const condY = typeof oy === "string"; if (condX || condY) { const { height: height2, width: width2, x: x2, y: y2 } = element.bbox(); if (condX) { ox = ox.includes("left") ? x2 : ox.includes("right") ? x2 + width2 : x2 + width2 / 2; } if (condY) { oy = oy.includes("top") ? y2 : oy.includes("bottom") ? y2 + height2 : y2 + height2 / 2; } } return [ox, oy]; } const descriptiveElements = /* @__PURE__ */ new Set(["desc", "metadata", "title"]); const isDescriptive = (element) => descriptiveElements.has(element.nodeName); const writeDataToDom = (element, data2, defaults = {}) => { const cloned = { ...data2 }; for (const key in cloned) { if (cloned[key].valueOf() === defaults[key]) { delete cloned[key]; } } if (Object.keys(cloned).length) { element.node.setAttribute("data-svgjs", JSON.stringify(cloned)); } else { element.node.removeAttribute("data-svgjs"); element.node.removeAttribute("svgjs:data"); } }; const svg = "http://www.w3.org/2000/svg"; const html = "http://www.w3.org/1999/xhtml"; const xmlns = "http://www.w3.org/2000/xmlns/"; const xlink = "http://www.w3.org/1999/xlink"; const globals = { window: typeof window === "undefined" ? null : window, document: typeof document === "undefined" ? null : document }; function getWindow() { return globals.window; } class Base { // constructor (node/*, {extensions = []} */) { // // this.tags = [] // // // // for (let extension of extensions) { // // extension.setup.call(this, node) // // this.tags.push(extension.name) // // } // } } const elements = {}; const root$1 = "___SYMBOL___ROOT___"; function create(name, ns = svg) { return globals.document.createElementNS(ns, name); } function makeInstance(element, isHTML = false) { if (element instanceof Base) return element; if (typeof element === "object") { return adopter(element); } if (element == null) { return new elements[root$1](); } if (typeof element === "string" && element.charAt(0) !== "<") { return adopter(globals.document.querySelector(element)); } const wrapper = isHTML ? globals.document.createElement("div") : create("svg"); wrapper.innerHTML = element; element = adopter(wrapper.firstChild); wrapper.removeChild(wrapper.firstChild); return element; } function nodeOrNew(name, node) { return node && (node instanceof globals.window.Node || node.ownerDocument && node instanceof node.ownerDocument.defaultView.Node) ? node : create(name); } function adopt(node) { if (!node) return null; if (node.instance instanceof Base) return node.instance; if (node.nodeName === "#document-fragment") { return new elements.Fragment(node); } let className = capitalize(node.nodeName || "Dom"); if (className === "LinearGradient" || className === "RadialGradient") { className = "Gradient"; } else if (!elements[className]) { className = "Dom"; } return new elements[className](node); } let adopter = adopt; function register(element, name = element.name, asRoot = false) { elements[name] = element; if (asRoot) elements[root$1] = element; addMethodNames(Object.getOwnPropertyNames(element.prototype)); return element; } function getClass(name) { return elements[name]; } let did = 1e3; function eid(name) { return "Svgjs" + capitalize(name) + did++; } function assignNewId(node) { for (let i = node.children.length - 1; i >= 0; i--) { assignNewId(node.children[i]); } if (node.id) { node.id = eid(node.nodeName); return node; } return node; } function extend(modules, methods2) { let key, i; modules = Array.isArray(modules) ? modules : [modules]; for (i = modules.length - 1; i >= 0; i--) { for (key in methods2) { modules[i].prototype[key] = methods2[key]; } } } function wrapWithAttrCheck(fn) { return function(...args) { const o = args[args.length - 1]; if (o && o.constructor === Object && !(o instanceof Array)) { return fn.apply(this, args.slice(0, -1)).attr(o); } else { return fn.apply(this, args); } }; } function siblings() { return this.parent().children(); } function position() { return this.parent().index(this); } function next() { return this.siblings()[this.position() + 1]; } function prev() { return this.siblings()[this.position() - 1]; } function forward() { const i = this.position(); const p = this.parent(); p.add(this.remove(), i + 1); return this; } function backward() { const i = this.position(); const p = this.parent(); p.add(this.remove(), i ? i - 1 : 0); return this; } function front() { const p = this.parent(); p.add(this.remove()); return this; } function back() { const p = this.parent(); p.add(this.remove(), 0); return this; } function before(element) { element = makeInstance(element); element.remove(); const i = this.position(); this.parent().add(element, i); return this; } function after(element) { element = makeInstance(element); element.remove(); const i = this.position(); this.parent().add(element, i + 1); return this; } function insertBefore(element) { element = makeInstance(element); element.before(this); return this; } function insertAfter(element) { element = makeInstance(element); element.after(this); return this; } registerMethods("Dom", { siblings, position, next, prev, forward, backward, front, back, before, after, insertBefore, insertAfter }); const numberAndUnit = /^([+-]?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?)([a-z%]*)$/i; const hex = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i; const rgb = /rgb\((\d+),(\d+),(\d+)\)/; const reference = /(#[a-z_][a-z0-9\-_]*)/i; const transforms = /\)\s*,?\s*/; const whitespace = /\s/g; const isHex = /^#[a-f0-9]{3}$|^#[a-f0-9]{6}$/i; const isRgb = /^rgb\(/; const isBlank = /^(\s+)?$/; const isNumber = /^[+-]?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?$/i; const isImage = /\.(jpg|jpeg|png|gif|svg)(\?[^=]+.*)?/i; const delimiter = /[\s,]+/; const isPathLetter = /[MLHVCSQTAZ]/i; function classes() { const attr2 = this.attr("class"); return attr2 == null ? [] : attr2.trim().split(delimiter); } function hasClass(name) { return this.classes().indexOf(name) !== -1; } function addClass(name) { if (!this.hasClass(name)) { const array2 = this.classes(); array2.push(name); this.attr("class", array2.join(" ")); } return this; } function removeClass(name) { if (this.hasClass(name)) { this.attr( "class", this.classes().filter(function(c) { return c !== name; }).join(" ") ); } return this; } function toggleClass(name) { return this.hasClass(name) ? this.removeClass(name) : this.addClass(name); } registerMethods("Dom", { classes, hasClass, addClass, removeClass, toggleClass }); function css(style, val) { const ret = {}; if (arguments.length === 0) { this.node.style.cssText.split(/\s*;\s*/).filter(function(el) { return !!el.length; }).forEach(function(el) { const t = el.split(/\s*:\s*/); ret[t[0]] = t[1]; }); return ret; } if (arguments.length < 2) { if (Array.isArray(style)) { for (const name of style) { const cased = name; ret[name] = this.node.style.getPropertyValue(cased); } return ret; } if (typeof style === "string") { return this.node.style.getPropertyValue(style); } if (typeof style === "object") { for (const name in style) { this.node.style.setProperty( name, style[name] == null || isBlank.test(style[name]) ? "" : style[name] ); } } } if (arguments.length === 2) { this.node.style.setProperty( style, val == null || isBlank.test(val) ? "" : val ); } return this; } function show() { return this.css("display", ""); } function hide() { return this.css("display", "none"); } function visible() { return this.css("display") !== "none"; } registerMethods("Dom", { css, show, hide, visible }); function data(a, v, r) { if (a == null) { return this.data( map( filter( this.node.attributes, (el) => el.nodeName.indexOf("data-") === 0 ), (el) => el.nodeName.slice(5) ) ); } else if (a instanceof Array) { const data2 = {}; for (const key of a) { data2[key] = this.data(key); } return data2; } else if (typeof a === "object") { for (v in a) { this.data(v, a[v]); } } else if (arguments.length < 2) { try { return JSON.parse(this.attr("data-" + a)); } catch (e) { return this.attr("data-" + a); } } else { this.attr( "data-" + a, v === null ? null : r === true || typeof v === "string" || typeof v === "number" ? v : JSON.stringify(v) ); } return this; } registerMethods("Dom", { data }); function remember(k, v) { if (typeof arguments[0] === "object") { for (const key in k) { this.remember(key, k[key]); } } else if (arguments.length === 1) { return this.memory()[k]; } else { this.memory()[k] = v; } return this; } function forget() { if (arguments.length === 0) { this._memory = {}; } else { for (let i = arguments.length - 1; i >= 0; i--) { delete this.memory()[arguments[i]]; } } return this; } function memory() { return this._memory = this._memory || {}; } registerMethods("Dom", { remember, forget, memory }); function sixDigitHex(hex2) { return hex2.length === 4 ? [ "#", hex2.substring(1, 2), hex2.substring(1, 2), hex2.substring(2, 3), hex2.substring(2, 3), hex2.substring(3, 4), hex2.substring(3, 4) ].join("") : hex2; } function componentHex(component) { const integer = Math.round(component); const bounded = Math.max(0, Math.min(255, integer)); const hex2 = bounded.toString(16); return hex2.length === 1 ? "0" + hex2 : hex2; } function is(object, space) { for (let i = space.length; i--; ) { if (object[space[i]] == null) { return false; } } return true; } function getParameters(a, b) { const params = is(a, "rgb") ? { _a: a.r, _b: a.g, _c: a.b, _d: 0, space: "rgb" } : is(a, "xyz") ? { _a: a.x, _b: a.y, _c: a.z, _d: 0, space: "xyz" } : is(a, "hsl") ? { _a: a.h, _b: a.s, _c: a.l, _d: 0, space: "hsl" } : is(a, "lab") ? { _a: a.l, _b: a.a, _c: a.b, _d: 0, space: "lab" } : is(a, "lch") ? { _a: a.l, _b: a.c, _c: a.h, _d: 0, space: "lch" } : is(a, "cmyk") ? { _a: a.c, _b: a.m, _c: a.y, _d: a.k, space: "cmyk" } : { _a: 0, _b: 0, _c: 0, space: "rgb" }; params.space = b || params.space; return params; } function cieSpace(space) { if (space === "lab" || space === "xyz" || space === "lch") { return true; } else { return false; } } function hueToRgb(p, q, t) { if (t < 0) t += 1; if (t > 1) t -= 1; if (t < 1 / 6) return p + (q - p) * 6 * t; if (t < 1 / 2) return q; if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6; return p; } class Color { constructor(...inputs) { this.init(...inputs); } // Test if given value is a color static isColor(color) { return color && (color instanceof Color || this.isRgb(color) || this.test(color)); } // Test if given value is an rgb object static isRgb(color) { return color && typeof color.r === "number" && typeof color.g === "number" && typeof color.b === "number"; } /* Generating random colors */ static random(mode = "vibrant", t) { const { random, round, sin, PI: pi } = Math; if (mode === "vibrant") { const l = (81 - 57) * random() + 57; const c = (83 - 45) * random() + 45; const h = 360 * random(); const color = new Color(l, c, h, "lch"); return color; } else if (mode === "sine") { t = t == null ? random() : t; const r = round(80 * sin(2 * pi * t / 0.5 + 0.01) + 150); const g = round(50 * sin(2 * pi * t / 0.5 + 4.6) + 200); const b = round(100 * sin(2 * pi * t / 0.5 + 2.3) + 150); const color = new Color(r, g, b); return color; } else if (mode === "pastel") { const l = (94 - 86) * random() + 86; const c = (26 - 9) * random() + 9; const h = 360 * random(); const color = new Color(l, c, h, "lch"); return color; } else if (mode === "dark") { const l = 10 + 10 * random(); const c = (125 - 75) * random() + 86; const h = 360 * random(); const color = new Color(l, c, h, "lch"); return color; } else if (mode === "rgb") { const r = 255 * random(); const g = 255 * random(); const b = 255 * random(); const color = new Color(r, g, b); return color; } else if (mode === "lab") { const l = 100 * random(); const a = 256 * random() - 128; const b = 256 * random() - 128; const color = new Color(l, a, b, "lab"); return color; } else if (mode === "grey") { const grey = 255 * random(); const color = new Color(grey, grey, grey); return color; } else { throw new Error("Unsupported random color mode"); } } // Test if given value is a color string static test(color) { return typeof color === "string" && (isHex.test(color) || isRgb.test(color)); } cmyk() { const { _a, _b, _c } = this.rgb(); const [r, g, b] = [_a, _b, _c].map((v) => v / 255); const k = Math.min(1 - r, 1 - g, 1 - b); if (k === 1) { return new Color(0, 0, 0, 1, "cmyk"); } const c = (1 - r - k) / (1 - k); const m = (1 - g - k) / (1 - k); const y2 = (1 - b - k) / (1 - k); const color = new Color(c, m, y2, k, "cmyk"); return color; } hsl() { const { _a, _b, _c } = this.rgb(); const [r, g, b] = [_a, _b, _c].map((v) => v / 255); const max = Math.max(r, g, b); const min = Math.min(r, g, b); const l = (max + min) / 2; const isGrey = max === min; const delta = max - min; const s = isGrey ? 0 : l > 0.5 ? delta / (2 - max - min) : delta / (max + min); const h = isGrey ? 0 : max === r ? ((g - b) / delta + (g < b ? 6 : 0)) / 6 : max === g ? ((b - r) / delta + 2) / 6 : max === b ? ((r - g) / delta + 4) / 6 : 0; const color = new Color(360 * h, 100 * s, 100 * l, "hsl"); return color; } init(a = 0, b = 0, c = 0, d = 0, space = "rgb") { a = !a ? 0 : a; if (this.space) { for (const component in this.space) { delete this[this.space[component]]; } } if (typeof a === "number") { space = typeof d === "string" ? d : space; d = typeof d === "string" ? 0 : d; Object.assign(this, { _a: a, _b: b, _c: c, _d: d, space }); } else if (a instanceof Array) { this.space = b || (typeof a[3] === "string" ? a[3] : a[4]) || "rgb"; Object.assign(this, { _a: a[0], _b: a[1], _c: a[2], _d: a[3] || 0 }); } else if (a instanceof Object) { const values = getParameters(a, b); Object.assign(this, values); } else if (typeof a === "string") { if (isRgb.test(a)) { const noWhitespace = a.replace(whitespace, ""); const [_a2, _b2, _c2] = rgb.exec(noWhitespace).slice(1, 4).map((v) => parseInt(v)); Object.assign(this, { _a: _a2, _b: _b2, _c: _c2, _d: 0, space: "rgb" }); } else if (isHex.test(a)) { const hexParse = (v) => parseInt(v, 16); const [, _a2, _b2, _c2] = hex.exec(sixDigitHex(a)).map(hexParse); Object.assign(this, { _a: _a2, _b: _b2, _c: _c2, _d: 0, space: "rgb" }); } else throw Error("Unsupported string format, can't construct Color"); } const { _a, _b, _c, _d } = this; const components = this.space === "rgb" ? { r: _a, g: _b, b: _c } : this.space === "xyz" ? { x: _a, y: _b, z: _c } : this.space === "hsl" ? { h: _a, s: _b, l: _c } : this.space === "lab" ? { l: _a, a: _b, b: _c } : this.space === "lch" ? { l: _a, c: _b, h: _c } : this.space === "cmyk" ? { c: _a, m: _b, y: _c, k: _d } : {}; Object.assign(this, components); } lab() { const { x: x2, y: y2, z } = this.xyz(); const l = 116 * y2 - 16; const a = 500 * (x2 - y2); const b = 200 * (y2 - z); const color = new Color(l, a, b, "lab"); return color; } lch() { const { l, a, b } = this.lab(); const c = Math.sqrt(a ** 2 + b ** 2); let h = 180 * Math.atan2(b, a) / Math.PI; if (h < 0) { h *= -1; h = 360 - h; } const color = new Color(l, c, h, "lch"); return color; } /* Conversion Methods */ rgb() { if (this.space === "rgb") { return this; } else if (cieSpace(this.space)) { let { x: x2, y: y2, z } = this; if (this.space === "lab" || this.space === "lch") { let { l, a, b: b2 } = this; if (this.space === "lch") { const { c, h } = this; const dToR = Math.PI / 180; a = c * Math.cos(dToR * h); b2 = c * Math.sin(dToR * h); } const yL = (l + 16) / 116; const xL = a / 500 + yL; const zL = yL - b2 / 200; const ct = 16 / 116; const mx = 8856e-6; const nm = 7.787; x2 = 0.95047 * (xL ** 3 > mx ? xL ** 3 : (xL - ct) / nm); y2 = 1 * (yL ** 3 > mx ? yL ** 3 : (yL - ct) / nm); z = 1.08883 * (zL ** 3 > mx ? zL ** 3 : (zL - ct) / nm); } const rU = x2 * 3.2406 + y2 * -1.5372 + z * -0.4986; const gU = x2 * -0.9689 + y2 * 1.8758 + z * 0.0415; const bU = x2 * 0.0557 + y2 * -0.204 + z * 1.057; const pow = Math.pow; const bd = 31308e-7; const r = rU > bd ? 1.055 * pow(rU, 1 / 2.4) - 0.055 : 12.92 * rU; const g = gU > bd ? 1.055 * pow(gU, 1 / 2.4) - 0.055 : 12.92 * gU; const b = bU > bd ? 1.055 * pow(bU, 1 / 2.4) - 0.055 : 12.92 * bU; const color = new Color(255 * r, 255 * g, 255 * b); return color; } else if (this.space === "hsl") { let { h, s, l } = this; h /= 360; s /= 100; l /= 100; if (s === 0) { l *= 255; const color2 = new Color(l, l, l); return color2; } const q = l < 0.5 ? l * (1 + s) : l + s - l * s; const p = 2 * l - q; const r = 255 * hueToRgb(p, q, h + 1 / 3); const g = 255 * hueToRgb(p, q, h); const b = 255 * hueToRgb(p, q, h - 1 / 3); const color = new Color(r, g, b); return color; } else if (this.space === "cmyk") { const { c, m, y: y2, k } = this; const r = 255 * (1 - Math.min(1, c * (1 - k) + k)); const g = 255 * (1 - Math.min(1, m * (1 - k) + k)); const b = 255 * (1 - Math.min(1, y2 * (1 - k) + k)); const color = new Color(r, g, b); return color; } else { return this; } } toArray() { const { _a, _b, _c, _d, space } = this; return [_a, _b, _c, _d, space]; } toHex() { const [r, g, b] = this._clamped().map(componentHex); return `#${r}${g}${b}`; } toRgb() { const [rV, gV, bV] = this._clamped(); const string = `rgb(${rV},${gV},${bV})`; return string; } toString() { return this.toHex(); } xyz() { const { _a: r255, _b: g255, _c: b255 } = this.rgb(); const [r, g, b] = [r255, g255, b255].map((v) => v / 255); const rL = r > 0.04045 ? Math.pow((r + 0.055) / 1.055, 2.4) : r / 12.92; const gL = g > 0.04045 ? Math.pow((g + 0.055) / 1.055, 2.4) : g / 12.92; const bL = b > 0.04045 ? Math.pow((b + 0.055) / 1.055, 2.4) : b / 12.92; const xU = (rL * 0.4124 + gL * 0.3576 + bL * 0.1805) / 0.95047; const yU = (rL * 0.2126 + gL * 0.7152 + bL * 0.0722) / 1; const zU = (rL * 0.0193 + gL * 0.1192 + bL * 0.9505) / 1.08883; const x2 = xU > 8856e-6 ? Math.pow(xU, 1 / 3) : 7.787 * xU + 16 / 116; const y2 = yU > 8856e-6 ? Math.pow(yU, 1 / 3) : 7.787 * yU + 16 / 116; const z = zU > 8856e-6 ? Math.pow(zU, 1 / 3) : 7.787 * zU + 16 / 116; const color = new Color(x2, y2, z, "xyz"); return color; } /* Input and Output methods */ _clamped() { const { _a, _b, _c } = this.rgb(); const { max, min, round } = Math; const format = (v) => max(0, min(round(v), 255)); return [_a, _b, _c].map(format); } /* Constructing colors */ } class Point { // Initialize constructor(...args) { this.init(...args); } // Clone point clone() { return new Point(this); } init(x2, y2) { const base = { x: 0, y: 0 }; const source = Array.isArray(x2) ? { x: x2[0], y: x2[1] } : typeof x2 === "object" ? { x: x2.x, y: x2.y } : { x: x2, y: y2 }; this.x = source.x == null ? base.x : source.x; this.y = source.y == null ? base.y : source.y; return this; } toArray() { return [this.x, this.y]; } transform(m) { return this.clone().transformO(m); } // Transform point with matrix transformO(m) { if (!Matrix.isMatrixLike(m)) { m = new Matrix(m); } const { x: x2, y: y2 } = this; this.x = m.a * x2 + m.c * y2 + m.e; this.y = m.b * x2 + m.d * y2 + m.f; return this; } } function point(x2, y2) { return new Point(x2, y2).transformO(this.screenCTM().inverseO()); } function unpoint(x2, y2) { return new Point(x2, y2).transformO(this.screenCTM()); } function closeEnough(a, b, threshold) { return Math.abs(b - a) < 1e-6; } class Matrix { constructor(...args) { this.init(...args); } static formatTransforms(o) { const flipBoth = o.flip === "both" || o.flip === true; const flipX = o.flip && (flipBoth || o.flip === "x") ? -1 : 1; const flipY = o.flip && (flipBoth || o.flip === "y") ? -1 : 1; const skewX = o.skew && o.skew.length ? o.skew[0] : isFinite(o.skew) ? o.skew : isFinite(o.skewX) ? o.skewX : 0; const skewY = o.skew && o.skew.length ? o.skew[1] : isFinite(o.skew) ? o.skew : isFinite(o.skewY) ? o.skewY : 0; const scaleX = o.scale && o.scale.length ? o.scale[0] * flipX : isFinite(o.scale) ? o.scale * flipX : isFinite(o.scaleX) ? o.scaleX * flipX : flipX; const scaleY = o.scale && o.scale.length ? o.scale[1] * flipY : isFinite(o.scale) ? o.scale * flipY : isFinite(o.scaleY) ? o.scaleY * flipY : flipY; const shear = o.shear || 0; const theta = o.rotate || o.theta || 0; const origin = new Point( o.origin || o.around || o.ox || o.originX, o.oy || o.originY ); const ox = origin.x; const oy = origin.y; const position2 = new Point( o.position || o.px || o.positionX || NaN, o.py || o.positionY || NaN ); const px = position2.x; const py = position2.y; const translate = new Point( o.translate || o.tx || o.translateX, o.ty || o.translateY ); const tx = translate.x; const ty = translate.y; const relative = new Point( o.relative || o.rx || o.relativeX, o.ry || o.relativeY ); const rx2 = relative.x; const ry2 = relative.y; return { scaleX, scaleY, skewX, skewY, shear, theta, rx: rx2, ry: ry2, tx, ty, ox, oy, px, py }; } static fromArray(a) { return { a: a[0], b: a[1], c: a[2], d: a[3], e: a[4], f: a[5] }; } static isMatrixLike(o) { return o.a != null || o.b != null || o.c != null || o.d != null || o.e != null || o.f != null; } // left matrix, right matrix, target matrix which is overwritten static matrixMultiply(l, r, o) { const a = l.a * r.a + l.c * r.b; const b = l.b * r.a + l.d * r.b; const c = l.a * r.c + l.c * r.d; const d = l.b * r.c + l.d * r.d; const e = l.e + l.a * r.e + l.c * r.f; const f = l.f + l.b * r.e + l.d * r.f; o.a = a; o.b = b; o.c = c; o.d = d; o.e = e; o.f = f; return o; } around(cx2, cy2, matrix) { return this.clone().aroundO(cx2, cy2, matrix); } // Transform around a center point aroundO(cx2, cy2, matrix) { const dx2 = cx2 || 0; const dy2 = cy2 || 0; return this.translateO(-dx2, -dy2).lmultiplyO(matrix).translateO(dx2, dy2); } // Clones this matrix clone() { return new Matrix(this); } // Decomposes this matrix into its affine parameters decompose(cx2 = 0, cy2 = 0) { const a = this.a; const b = this.b; const c = this.c; const d = this.d; const e = this.e; const f = this.f; const determinant = a * d - b * c; const ccw = determinant > 0 ? 1 : -1; const sx = ccw * Math.sqrt(a * a + b * b); const thetaRad = Math.atan2(ccw * b, ccw * a); const theta = 180 / Math.PI * thetaRad; const ct = Math.cos(thetaRad); const st = Math.sin(thetaRad); const lam = (a * c + b * d) / determinant; const sy = c * sx / (lam * a - b) || d * sx / (lam * b + a); const tx = e - cx2 + cx2 * ct * sx + cy2 * (lam * ct * sx - st * sy); const ty = f - cy2 + cx2 * st * sx + cy2 * (lam * st * sx + ct * sy); return { // Return the affine parameters scaleX: sx, scaleY: sy, shear: lam, rotate: theta, translateX: tx, translateY: ty, originX: cx2, originY: cy2, // Return the matrix parameters a: this.a, b: this.b, c: this.c, d: this.d, e: this.e, f: this.f }; } // Check if two matrices are equal equals(other) { if (other === this) return true; const comp = new Matrix(other); return closeEnough(this.a, comp.a) && closeEnough(this.b, comp.b) && closeEnough(this.c, comp.c) && closeEnough(this.d, comp.d) && closeEnough(this.e, comp.e) && closeEnough(this.f, comp.f); } // Flip matrix on x or y, at a given offset flip(axis, around) { return this.clone().flipO(axis, around); } flipO(axis, around) { return axis === "x" ? this.scaleO(-1, 1, around, 0) : axis === "y" ? this.scaleO(1, -1, 0, around) : this.scaleO(-1, -1, axis, around || axis); } // Initialize init(source) { const base = Matrix.fromArray([1, 0, 0, 1, 0, 0]); source = source instanceof Element ? source.matrixify() : typeof source === "string" ? Matrix.fromArray(source.split(delimiter).map(parseFloat)) : Array.isArray(source) ? Matrix.fromArray(source) : typeof source === "object" && Matrix.isMatrixLike(source) ? source : typeof source === "object" ? new Matrix().transform(source) : arguments.length === 6 ? Matrix.fromArray([].slice.call(arguments)) : base; this.a = source.a != null ? source.a : base.a; this.b = source.b != null ? source.b : base.b; this.c = source.c != null ? source.c : base.c; this.d = source.d != null ? source.d : base.d; this.e = source.e != null ? source.e : base.e; this.f = source.f != null ? source.f : base.f; return this; } inverse() { return this.clone().inverseO(); } // Inverses matrix inverseO() { const a = this.a; const b = this.b; const c = this.c; const d = this.d; const e = this.e; const f = this.f; const det = a * d - b * c; if (!det) throw new Error("Cannot invert " + this); const na = d / det; const nb = -b / det; const nc = -c / det; const nd = a / det; const ne = -(na * e + nc * f); const nf = -(nb * e + nd * f); this.a = na; this.b = nb; this.c = nc; this.d = nd; this.e = ne; this.f = nf; return this; } lmultiply(matrix) { return this.clone().lmultiplyO(matrix); } lmultiplyO(matrix) { const r = this; const l = matrix instanceof Matrix ? matrix : new Matrix(matrix); return Matrix.matrixMultiply(l, r, this); } // Left multiplies by the given matrix multiply(matrix) { return this.clone().multiplyO(matrix); } multiplyO(matrix) { const l = this; const r = matrix instanceof Matrix ? matrix : new Matrix(matrix); return Matrix.matrixMultiply(l, r, this); } // Rotate matrix rotate(r, cx2, cy2) { return this.clone().rotateO(r, cx2, cy2); } rotateO(r, cx2 = 0, cy2 = 0) { r = radians(r); const cos = Math.cos(r); const sin = Math.sin(r); const { a, b, c, d, e, f } = this; this.a = a * cos - b * sin; this.b = b * cos + a * sin; this.c = c * cos - d * sin; this.d = d * cos + c * sin; this.e = e * cos - f * sin + cy2 * sin - cx2 * cos + cx2; this.f = f * cos + e * sin - cx2 * sin - cy2 * cos + cy2; return this; } // Scale matrix scale() { return this.clone().scaleO(...arguments); } scaleO(x2, y2 = x2, cx2 = 0, cy2 = 0) { if (arguments.length === 3) { cy2 = cx2; cx2 = y2; y2 = x2; } const { a, b, c, d, e, f } = this; this.a = a * x2; this.b = b * y2; this.c = c * x2; this.d = d * y2; this.e = e * x2 - cx2 * x2 + cx2; this.f = f * y2 - cy2 * y2 + cy2; return this; } // Shear matrix shear(a, cx2, cy2) { return this.clone().shearO(a, cx2, cy2); } // eslint-disable-next-line no-unused-vars shearO(lx, cx2 = 0, cy2 = 0) { const { a, b, c, d, e, f } = this; this.a = a + b * lx; this.c = c + d * lx; this.e = e + f * lx - cy2 * lx; return this; } // Skew Matrix skew() { return this.clone().skewO(...arguments); } skewO(x2, y2 = x2, cx2 = 0, cy2 = 0) { if (arguments.length === 3) { cy2 = cx2; cx2 = y2; y2 = x2; } x2 = radians(x2); y2 = radians(y2); const lx = Math.tan(x2); const ly = Math.tan(y2); const { a, b, c, d, e, f } = this; this.a = a + b * lx; this.b = b + a * ly; this.c = c + d * lx; this.d = d + c * ly; this.e = e + f * lx - cy2 * lx; this.f = f + e * ly - cx2 * ly; return this; } // SkewX skewX(x2, cx2, cy2) { return this.skew(x2, 0, cx2, cy2); } // SkewY skewY(y2, cx2, cy2) { return this.skew(0, y2, cx2, cy2); } toArray() { return [this.a, this.b, this.c, this.d, this.e, this.f]; } // Convert matrix to string toString() { return "matrix(" + this.a + "," + this.b + "," + this.c + "," + this.d + "," + this.e + "," + this.f + ")"; } // Transform a matrix into another matrix by manipulating the space transform(o) { if (Matrix.isMatrixLike(o)) { const matrix = new Matrix(o); return matrix.multiplyO(this); } const t = Matrix.formatTransforms(o); const current = this; const { x: ox, y: oy } = new Point(t.ox, t.oy).transform(current); const transformer = new Matrix().translateO(t.rx, t.ry).lmultiplyO(current).translateO(-ox, -oy).scaleO(t.scaleX, t.scaleY).skewO(t.skewX, t.skewY).shearO(t.shear).rotateO(t.theta).translateO(ox, oy); if (isFinite(t.px) || isFinite(t.py)) { const origin = new Point(ox, oy).transform(transformer); const dx2 = isFinite(t.px) ? t.px - origin.x : 0; const dy2 = isFinite(t.py) ? t.py - origin.y : 0; transformer.translateO(dx2, dy2); } transformer.translateO(t.tx, t.ty); return transformer; } // Translate matrix translate(x2, y2) { return this.clone().translateO(x2, y2); } translateO(x2, y2) { this.e += x2 || 0; this.f += y2 || 0; return this; } valueOf() { return { a: this.a, b: this.b, c: this.c, d: this.d, e: this.e, f: this.f }; } } function ctm() { return new Matrix(this.node.getCTM()); } function screenCTM() { try { if (typeof this.isRoot === "function" && !this.isRoot()) { const rect = this.rect(1, 1); const m = rect.node.getScreenCTM(); rect.remove(); return new Matrix(m); } return new Matrix(this.node.getScreenCTM()); } catch (e) { return new Matrix(); } } register(Matrix, "Matrix"); function parser() { if (!parser.nodes) { const svg2 = makeInstance().size(2, 0); svg2.node.style.cssText = [ "opacity: 0", "position: absolute", "left: -100%", "top: -100%", "overflow: hidden" ].join(";"); svg2.attr("focusable", "false"); svg2.attr("aria-hidden", "true"); const path = svg2.path().node; parser.nodes = { svg: svg2, path }; } if (!parser.nodes.svg.node.parentNode) { const b = globals.document.body || globals.document.documentElement; parser.nodes.svg.addTo(b); } return parser.nodes; } function isNulledBox(box) { return !box.width && !box.height && !box.x && !box.y; } function domContains(node) { return node === globals.document || (globals.document.documentElement.contains || function(node2) { while (node2.parentNode) { node2 = node2.parentNode; } return node2 === globals.document; }).call(globals.document.documentElement, node); } class Box { constructor(...args) { this.init(...args); } addOffset() { this.x += globals.window.pageXOffset; this.y += globals.window.pageYOffset; return new Box(this); } init(source) { const base = [0, 0, 0, 0]; source = typeof source === "string" ? source.split(delimiter).map(parseFloat) : Array.isArray(source) ? source : typeof source === "object" ? [ source.left != null ? source.left : source.x, source.top != null ? source.top : source.y, source.width, source.height ] : arguments.length === 4 ? [].slice.call(arguments) : base; this.x = source[0] || 0; this.y = source[1] || 0; this.width = this.w = source[2] || 0; this.height = this.h = source[3] || 0; this.x2 = this.x + this.w; this.y2 = this.y + this.h; this.cx = this.x + this.w / 2; this.cy = this.y + this.h / 2; return this; } isNulled() { return isNulledBox(this); } // Merge rect box with another, return a new instance merge(box) { const x2 = Math.min(this.x, box.x); const y2 = Math.min(this.y, box.y); const width2 = Math.max(this.x + this.width, box.x + box.width) - x2; const height2 = Math.max(this.y + this.height, box.y + box.height) - y2; return new Box(x2, y2, width2, height2); } toArray() { return [this.x, this.y, this.width, this.height]; } toString() { return this.x + " " + this.y + " " + this.width + " " + this.height; } transform(m) { if (!(m instanceof Matrix)) { m = new Matrix(m); } let xMin = Infinity; let xMax = -Infinity; let yMin = Infinity; let yMax = -Infinity; const pts = [ new Point(this.x, this.y), new Point(this.x2, this.y), new Point(this.x, this.y2), new Point(this.x2, this.y2) ]; pts.forEach(function(p) { p = p.transform(m); xMin = Math.min(xMin, p.x); xMax = Math.max(xMax, p.x); yMin = Math.min(yMin, p.y); yMax = Math.max(yMax, p.y); }); return new Box(xMin, yMin, xMax - xMin, yMax - yMin); } } function getBox(el, getBBoxFn, retry) { let box; try { box = getBBoxFn(el.node); if (isNulledBox(box) && !domContains(el.node)) { throw new Error("Element not in the dom"); } } catch (e) { box = retry(el); } return box; } function bbox() { const getBBox = (node) => node.getBBox(); const retry = (el) => { try { const clone = el.clone().addTo(parser().svg).show(); const box2 = clone.node.getBBox(); clone.remove(); return box2; } catch (e) { throw new Error( `Getting bbox of element "${el.node.nodeName}" is not possible: ${e.toString()}` ); } }; const box = getBox(this, getBBox, retry); const bbox2 = new Box(box); return bbox2; } function rbox(el) { const getRBox = (node) => node.getBoundingClientRect(); const retry = (el2) => { throw new Error( `Getting rbox of element "${el2.node.nodeName}" is not possible` ); }; const box = getBox(this, getRBox, retry); const rbox2 = new Box(box); if (el) { return rbox2.transform(el.screenCTM().inverseO()); } return rbox2.addOffset(); } function inside(x2, y2) { const box = this.bbox(); return x2 > box.x && y2 > box.y && x2 < box.x + box.width && y2 < box.y + box.height; } registerMethods({ viewbox: { viewbox(x2, y2, width2, height2) { if (x2 == null) return new Box(this.attr("viewBox")); return this.attr("viewBox", new Box(x2, y2, width2, height2)); }, zoom(level, point2) { let { width: width2, height: height2 } = this.attr(["width", "height"]); if (!width2 && !height2 || typeof width2 === "string" || typeof height2 === "string") { width2 = this.node.clientWidth; height2 = this.node.clientHeight; } if (!width2 || !height2) { throw new Error( "Impossible to get absolute width and height. Please provide an absolute width and height attribute on the zooming element" ); } const v = this.viewbox(); const zoomX = width2 / v.width; const zoomY = height2 / v.height; const zoom = Math.min(zoomX, zoomY); if (level == null) { return zoom; } let zoomAmount = zoom / level; if (zoomAmount === Infinity) zoomAmount = Number.MAX_SAFE_INTEGER / 100; point2 = point2 || new Point(width2 / 2 / zoomX + v.x, height2 / 2 / zoomY + v.y); const box = new Box(v).transform( new Matrix({ scale: zoomAmount, origin: point2 }) ); return this.viewbox(box); } } }); register(Box, "Box"); class List extends Array { constructor(arr = [], ...args) { super(arr, ...args); if (typeof arr === "number") return this; this.length = 0; this.push(...arr); } } extend([List], { each(fnOrMethodName, ...args) { if (typeof fnOrMethodName === "function") { return this.map((el, i, arr) => { return fnOrMethodName.call(el, el, i, arr); }); } else { return this.map((el) => { return el[fnOrMethodName](...args); }); } }, toArray() { return Array.prototype.concat.apply([], this); } }); const reserved = ["toArray", "constructor", "each"]; List.extend = function(methods2) { methods2 = methods2.reduce((obj, name) => { if (reserved.includes(name)) return obj; if (name[0] === "_") return obj; if (name in Array.prototype) { obj["$" + name] = Array.prototype[name]; } obj[name] = function(...attrs2) { return this.each(name, ...attrs2); }; return obj; }, {}); extend([List], methods2); }; function baseFind(query, parent) { return new List( map((parent || globals.document).querySelectorAll(query), function(node) { return adopt(node); }) ); } function find$1(query) { return baseFind(query, this.node); } function findOne(query) { return adopt(this.node.querySelector(query)); } let listenerId = 0; const windowEvents = {}; function getEvents(instance) { let n = instance.getEventHolder(); if (n === globals.window) n = windowEvents; if (!n.events) n.events = {}; return n.events; } function getEventTarget(instance) { return instance.getEventTarget(); } function clearEvents(instance) { let n = instance.getEventHolder(); if (n === globals.window) n = windowEvents; if (n.events) n.events = {}; } function on(node, events, listener, binding, options) { const l = listener.bind(binding || node); const instance = makeInstance(node); const bag = getEvents(instance); const n = getEventTarget(instance); events = Array.isArray(events) ? events : events.split(delimiter); if (!listener._svgjsListenerId) { listener._svgjsListenerId = ++listenerId; } events.forEach(function(event) { const ev = event.split(".")[0]; const ns = event.split(".")[1] || "*"; bag[ev] = bag[ev] || {}; bag[ev][ns] = bag[ev][ns] || {}; bag[ev][ns][listener._svgjsListenerId] = l; n.addEventListener(ev, l, options || false); }); } function off(node, events, listener, options) { const instance = makeInstance(node); const bag = getEvents(instance); const n = getEventTarget(instance); if (typeof listener === "function") { listener = listener._svgjsListenerId; if (!listener) return; } events = Array.isArray(events) ? events : (events || "").split(delimiter); events.forEach(function(event) { const ev = event && event.split(".")[0]; const ns = event && event.split(".")[1]; let namespace, l; if (listener) { if (bag[ev] && bag[ev][ns || "*"]) { n.removeEventListener( ev, bag[ev][ns || "*"][listener], options || false ); delete bag[ev][ns || "*"][listener]; } } else if (ev && ns) { if (bag[ev] && bag[ev][ns]) { for (l in bag[ev][ns]) { off(n, [ev, ns].join("."), l); } delete bag[ev][ns]; } } else if (ns) { for (event in bag) { for (namespace in bag[event]) { if (ns === namespace) { off(n, [event, ns].join(".")); } } } } else if (ev) { if (bag[ev]) { for (namespace in bag[ev]) { off(n, [ev, namespace].join(".")); } delete bag[ev]; } } else { for (event in bag) { off(n, event); } clearEvents(instance); } }); } function dispatch(node, event, data2, options) { const n = getEventTarget(node); if (event instanceof globals.window.Event) { n.dispatchEvent(event); } else { event = new globals.window.CustomEvent(event, { detail: data2, cancelable: true, ...options }); n.dispatchEvent(event); } return event; } class EventTarget extends Base { addEventListener() { } dispatch(event, data2, options) { return dispatch(this, event, data2, options); } dispatchEvent(event) { const bag = this.getEventHolder().events; if (!bag) return true; const events = bag[event.type]; for (const i in events) { for (const j in events[i]) { events[i][j](event); } } return !event.defaultPrevented; } // Fire given event fire(event, data2, options) { this.dispatch(event, data2, options); return this; } getEventHolder() { return this; } getEventTarget() { return this; } // Unbind event from listener off(event, listener, options) { off(this, event, listener, options); return this; } // Bind given event to listener on(event, listener, binding, options) { on(this, event, listener, binding, options); return this; } removeEventListener() { } } register(EventTarget, "EventTarget"); function noop() { } const timeline = { duration: 400, ease: ">", delay: 0 }; const attrs = { // fill and stroke "fill-opacity": 1, "stroke-opacity": 1, "stroke-width": 0, "stroke-linejoin": "miter", "stroke-linecap": "butt", fill: "#000000", stroke: "#000000", opacity: 1, // position x: 0, y: 0, cx: 0, cy: 0, // size width: 0, height: 0, // radius r: 0, rx: 0, ry: 0, // gradient offset: 0, "stop-opacity": 1, "stop-color": "#000000", // text "text-anchor": "start" }; class SVGArray extends Array { constructor(...args) { super(...args); this.init(...args); } clone() { return new this.constructor(this); } init(arr) { if (typeof arr === "number") return this; this.length = 0; this.push(...this.parse(arr)); return this; } // Parse whitespace separated string parse(array2 = []) { if (array2 instanceof Array) return array2; return array2.trim().split(delimiter).map(parseFloat); } toArray() { return Array.prototype.concat.apply([], this); } toSet() { return new Set(this); } toString() { return this.join(" "); } // Flattens the array if needed valueOf() { const ret = []; ret.push(...this); return ret; } } class SVGNumber { // Initialize constructor(...args) { this.init(...args); } convert(unit) { return new SVGNumber(this.value, unit); } // Divide number divide(number) { number = new SVGNumber(number); return new SVGNumber(this / number, this.unit || number.unit); } init(value, unit) { unit = Array.isArray(value) ? value[1] : unit; value = Array.isArray(value) ? value[0] : value; this.value = 0; this.unit = unit || ""; if (typeof value === "number") { this.value = isNaN(value) ? 0 : !isFinite(value) ? value < 0 ? -34e37 : 34e37 : value; } else if (typeof value === "string") { unit = value.match(numberAndUnit); if (unit) { this.value = parseFloat(unit[1]); if (unit[5] === "%") { this.value /= 100; } else if (unit[5] === "s") { this.value *= 1e3; } this.unit = unit[5]; } } else { if (value instanceof SVGNumber) { this.value = value.valueOf(); this.unit = value.unit; } } return this; } // Subtract number minus(number) { number = new SVGNumber(number); return new SVGNumber(this - number, this.unit || number.unit); } // Add number plus(number) { number = new SVGNumber(number); return new SVGNumber(this + number, this.unit || number.unit); } // Multiply number times(number) { number = new SVGNumber(number); return new SVGNumber(this * number, this.unit || number.unit); } toArray() { return [this.value, this.unit]; } toJSON() { return this.toString(); } toString() { return (this.unit === "%" ? ~~(this.value * 1e8) / 1e6 : this.unit === "s" ? this.value / 1e3 : this.value) + this.unit; } valueOf() { return this.value; } } const colorAttributes = /* @__PURE__ */ new Set([ "fill", "stroke", "color", "bgcolor", "stop-color", "flood-color", "lighting-color" ]); const hooks = []; function registerAttrHook(fn) { hooks.push(fn); } function attr(attr2, val, ns) { if (attr2 == null) { attr2 = {}; val = this.node.attributes; for (const node of val) { attr2[node.nodeName] = isNumber.test(node.nodeValue) ? parseFloat(node.nodeValue) : node.nodeValue; } return attr2; } else if (attr2 instanceof Array) { return attr2.reduce((last, curr) => { last[curr] = this.attr(curr); return last; }, {}); } else if (typeof attr2 === "object" && attr2.constructor === Object) { for (val in attr2) this.attr(val, attr2[val]); } else if (val === null) { this.node.removeAttribute(attr2); } else if (val == null) { val = this.node.getAttribute(attr2); return val == null ? attrs[attr2] : isNumber.test(val) ? parseFloat(val) : val; } else { val = hooks.reduce((_val, hook) => { return hook(attr2, _val, this); }, val); if (typeof val === "number") { val = new SVGNumber(val); } else if (colorAttributes.has(attr2) && Color.isColor(val)) { val = new Color(val); } else if (val.constructor === Array) { val = new SVGArray(val); } if (attr2 === "leading") { if (this.leading) { this.leading(val); } } else { typeof ns === "string" ? this.node.setAttributeNS(ns, attr2, val.toString()) : this.node.setAttribute(attr2, val.toString()); } if (this.rebuild && (attr2 === "font-size" || attr2 === "x")) { this.rebuild(); } } return this; } class Dom extends EventTarget { constructor(node, attrs2) { super(); this.node = node; this.type = node.nodeName; if (attrs2 && node !== attrs2) { this.attr(attrs2); } } // Add given element at a position add(element, i) { element = makeInstance(element); if (element.removeNamespace && this.node instanceof globals.window.SVGElement) { element.removeNamespace(); } if (i == null) { this.node.appendChild(element.node); } else if (element.node !== this.node.childNodes[i]) { this.node.insertBefore(element.node, this.node.childNodes[i]); } return this; } // Add element to given container and return self addTo(parent, i) { return makeInstance(parent).put(this, i); } // Returns all child elements children() { return new List( map(this.node.children, function(node) { return adopt(node); }) ); } // Remove all elements in this container clear() { while (this.node.hasChildNodes()) { t