UNPKG

chrono-phylo-tree

Version:

A React-based phylogenetic tree visualization library

1,118 lines (1,117 loc) 51.2 kB
var Mt = Object.defineProperty; var Lt = (r, n, o) => n in r ? Mt(r, n, { enumerable: !0, configurable: !0, writable: !0, value: o }) : r[n] = o; var ct = (r, n, o) => Lt(r, typeof n != "symbol" ? n + "" : n, o); import { jsxs as X, Fragment as wt, jsx as y } from "react/jsx-runtime"; import { useState as P, useEffect as Et } from "react"; const Tt = (r, ...n) => r.sort( (o, a) => { for (const d of n) { const [c, l] = [o, a].map((_) => d(_)); if (c !== l) return c - l; } return 0; } ); class gt { constructor({ id: n, name: o = "", apparition: a = 0, duration: d = 0, ancestor: c, descendants: l = [], description: _, image: m }) { ct(this, "id"); ct(this, "name", ""); ct(this, "apparition", 0); ct(this, "duration", 0); ct(this, "ancestor"); ct(this, "descendants", []); ct(this, "description"); ct(this, "display", !0); ct(this, "image"); if (d <= 0) throw new Error("The duration of the species must be greater than 0"); this.id = n, this.name = o, this.apparition = a, this.duration = d, this.ancestor = c, this.descendants = l, this.description = _ === "" ? void 0 : _, this.image = m === "" ? void 0 : m; } onPosition(n = !0) { return n && this.firstAncestor().stepsUntil(this) % 2 === 0; } copy() { const n = this.firstAncestor(), o = n.allDescendants(!1).indexOf(this); return gt.fromJSON(n.toJSON()).allDescendants(!1)[o]; } unlinkAncestor() { if (!this.ancestor) return; this.ancestor.descendants = this.ancestor.descendants.filter((o) => o !== this); const n = this.ancestor; return this.ancestor = void 0, [n.firstAncestor(), this]; } unlinkDescendant(n) { if (this.descendants.includes(n)) return this.descendants = this.descendants.filter((o) => o !== n), n.ancestor = void 0, [this.firstAncestor(), n]; } linkAncestor(n) { if (!(this.ancestor === n && n.descendants.includes(this))) { if (n.apparition > this.apparition) throw new Error(`The ancestor's apparition (${n.apparition}) must be before or equal the descendant's apparition (${this.apparition})`); if (n.extinction() < this.apparition) throw new Error(`The ancestor's extinction (${n.extinction()}) must be after or equal the descendant's apparition (${this.apparition})`); this.ancestor !== n && this.unlinkAncestor(), this.ancestor = n, n.descendants.push(this); } } linkDescendant(n) { if (!(n.ancestor === this && this.descendants.includes(n))) { if (n.apparition < this.apparition) throw new Error(`The descendant's apparition (${n.apparition}) must be after or equal the ancestor's apparition (${this.apparition})`); if (n.extinction() > this.extinction()) throw new Error(`The descendant's extinction (${n.extinction()}) must be before or equal the ancestor's extinction (${this.extinction()})`); this.descendants.includes(n) || (n.ancestor && n.unlinkAncestor(), this.descendants.push(n), n.ancestor = this); } } linkDescendants(n) { for (const o of n) try { this.linkDescendant(o); } catch (a) { console.error(`Error linking descendant ${o.name} to ancestor ${this.name}:`, a); } } addDescendant({ id: n, name: o = "", afterApparition: a = 0, duration: d = 0, description: c, image: l, copy: _ = !1 }) { if (a < 0 || a > this.duration) throw new Error(`The apparition of the descendant must be between the apparition (${this.apparition}) and the extinction (${this.extinction()}) of the ancestor`); const m = _ ? this.copy() : this, s = new gt({ id: n, name: o, apparition: m.apparition + Math.max(a, 0), duration: Math.max(d, 0), description: c, image: l }); return s.linkAncestor(m), _ ? m : s; } removeDescendant(n) { this.descendants = this.descendants.filter((o) => o !== n); } addAncestor({ id: n, name: o = "", previousApparition: a = 0, duration: d = 0, description: c, image: l, display: _ = !0, copy: m = !1 }) { if (a < 0) throw new Error(`The apparition of the ancestor must be before or equal the apparition (${this.apparition}) of the descendant`); if (d < a) throw new Error(`The extiction of the ancestor must be after or equal the apparition (${this.apparition}) of the descendant`); const s = m ? this.copy() : this, p = new gt({ id: n, name: o, apparition: s.apparition - Math.max(a, 0), duration: d, description: c, image: l }); return p.display = _, s.linkAncestor(p), m ? s : p; } extinction() { return this.apparition + this.duration; } absoluteExtinction() { return this.descendants.length > 0 ? Math.max(...this.allDescendants(!1).map((n) => n.extinction())) : this.extinction(); } absoluteDuration() { return this.absoluteExtinction() - this.apparition; } firstAncestor(n = !1) { return this.ancestor ? this.ancestor.display || n ? this.ancestor.firstAncestor() : this : this; } cousinsExtinction() { return this.firstAncestor().absoluteExtinction(); } allDescendants(n = !0) { const o = n ? Tt(this.descendants, (s) => -s.apparition, (s) => -s.absoluteExtinction()) : this.descendants; if (o.length === 0) return [this]; const a = o.filter((s) => s.apparition >= this.extinction()), d = o.filter((s) => a.indexOf(s) === -1), l = (this.onPosition(n) ? Math.ceil : Math.floor)(a.length / 2), _ = a.slice(0, l), m = a.slice(l); return _.flatMap((s) => s.allDescendants(n)).concat([this]).concat(m.flatMap((s) => s.allDescendants(n))).concat(d.flatMap((s) => s.allDescendants(n))); } stepsChain(n, o = !1) { var a; return this.allDescendants(!1).includes(n) ? [this].concat(((a = this.descendants.find((d) => d.allDescendants(!1).includes(n))) == null ? void 0 : a.stepsChain(n)) ?? []).filter((d) => d.display || o) : []; } stepsUntil(n, o = !1) { if (this.allDescendants(!1).includes(n)) return this.stepsChain(n, o).length - 1; } stepsUntilLastDescendant(n = !1) { return this.descendants.length === 0 ? 0 : Math.max(...this.allDescendants(!1).filter((o) => o.descendants.length === 0).map((o) => this.stepsUntil(o, n) ?? 0)); } toJSON() { return { name: this.name, apparition: this.ancestor ? void 0 : this.apparition, afterApparition: this.ancestor ? this.apparition - this.ancestor.apparition : void 0, description: this.description, duration: this.duration, descendants: this.descendants.length > 0 ? this.descendants.map((n) => n.toJSON()) : void 0, image: this.image }; } async saveJSON(n) { try { const o = JSON.stringify(this.toJSON(), null, 2), a = new Blob([o], { type: "application/json" }), d = URL.createObjectURL(a), c = document.createElement("a"); c.href = d, c.download = n ?? `${this.name}.json`, c.click(), URL.revokeObjectURL(d); } catch (o) { console.error("Error saving file:", o); } } static fromJSON({ id: n, name: o, duration: a, description: d, image: c, descendants: l, ..._ }, m) { const s = _.afterApparition ?? 0, p = m ? m.apparition : _.apparition ?? 0, w = new gt({ id: n, name: o, apparition: p + s, duration: a, ancestor: m, description: d, image: c }); if (l) for (const A of l) w.descendants.push(gt.fromJSON(A, w)); return w; } } const Xt = ({ speciesList: r, width: n = 1e3, height: o = 50, padding: a = 0, stroke: d = "grey", format: c = (w) => w.toString(), chronoScale: l = !0, showImages: _ = !0, presentTime: m, handleMouseMove: s, children: p }) => { const w = r.map((F) => F.copy()), A = Math.min(...w.map((F) => F.apparition)), L = Math.max(...w.map((F) => F.apparition - A)), C = new gt({ name: "", apparition: A, duration: L }); return C.display = !1, C.linkDescendants(w), /* @__PURE__ */ y( It, { commonAncestor: C, width: n, height: o, padding: a, stroke: d, format: c, chronoScale: l, showImages: _, presentTime: m, handleMouseMove: s, children: (F, T, B, V) => p == null ? void 0 : p(F, T, B, V) } ); }, It = ({ commonAncestor: r, width: n = 1e3, height: o = 50, padding: a = 0, stroke: d = "grey", format: c = (w) => w.toString(), chronoScale: l = !0, showImages: _ = !0, presentTime: m, handleMouseMove: s, children: p }) => { const [w, A] = P(!1), [L, C] = P(void 0), [F, T] = P(void 0), [B, V] = P(r.allDescendants().reduce((t, e) => t.set(e, !0), /* @__PURE__ */ new Map())); Et(() => { V(r.allDescendants().reduce((t, e) => t.set(e, !0), /* @__PURE__ */ new Map())); }, [r]); const Z = (t) => { C(w ? void 0 : t), A(!w); }, rt = (t) => { const e = new Map(B); e.set(t, !B.get(t)), V(e); }, et = (t) => { T(t); }, K = m !== void 0 && l, g = (t) => _ ? t.map((e) => e.image ? 2 : 1).reduce((e, i) => e + i) : t.length; return /* @__PURE__ */ X(wt, { children: [ /* @__PURE__ */ y( "svg", { width: n * (K ? (Math.min(m, r.absoluteExtinction()) - r.apparition) / r.absoluteDuration() : 1), height: o * g(K ? r.allDescendants().filter((t) => t.apparition < m) : r.allDescendants()), onMouseMove: (t) => { s == null || s(t.clientX, t.clientY); }, children: /* @__PURE__ */ y( At, { commonAncestor: r, species: r, y: -1, scaleX: n / (l ? r.absoluteDuration() : Math.max(0, r.stepsUntilLastDescendant()) + 1), scaleY: o, padding: a, stroke: d, format: c, chronoScale: l, showImages: _, presentTime: m, toggleShowMenu: Z, hoverShowMenu: et, showDesc: B, changeShowDesc: rt } ) } ), p == null ? void 0 : p(L, w, Z, F) ] }); }, At = ({ commonAncestor: r, species: n, y: o, scaleX: a, scaleY: d, padding: c = 0, stroke: l = "grey", format: _ = (F) => F.toString(), chronoScale: m = !0, showImages: s = !0, presentTime: p = void 0, toggleShowMenu: w, hoverShowMenu: A, showDesc: L, changeShowDesc: C }) => { const F = p !== void 0 && m, T = r.allDescendants().filter((g) => F ? g.apparition < p : !0), B = T.indexOf(n), V = (m ? n.apparition - r.apparition : r.stepsUntil(n) ?? 0) * a, Z = V + (m ? Math.min(L.get(n) ? n.duration : n.absoluteDuration(), F ? p - n.apparition : n.absoluteDuration()) : 1) * a, rt = s && B > 0 ? [...Array(B).keys()].map((g) => T[g]).map((g) => (g.image ? 2 : 1) * d).reduce((g, t) => g + t) : B * d, et = n.descendants.filter((g) => F ? g.apparition < p : !0), K = et.length > 0 ? V + (Math.min(...et.map((g) => g.apparition)) - n.apparition) * a : Z; return /* @__PURE__ */ X("g", { children: [ o >= 0 && /* @__PURE__ */ y( "line", { x1: V, y1: o, x2: V, y2: rt, stroke: l } ), n.display && /* @__PURE__ */ y( jt, { commonAncestor: r, species: n, height: d, x1: V, x2: Z, x0: K, y: rt, stroke: l, changeShowDesc: () => C(n), showDesc: L.get(n), padding: c, format: _, chronoScale: m, showImages: s, presentTime: p, toggleShowMenu: w, hoverShowMenu: A } ), n.descendants.map((g, t) => /* @__PURE__ */ y("g", { className: L.get(n) && et.includes(g) ? "block" : "hidden", children: /* @__PURE__ */ y( At, { commonAncestor: r, species: g, y: g.display ? rt : -1, scaleX: a, scaleY: d, padding: c, stroke: l, format: _, chronoScale: m, showImages: s, presentTime: p, toggleShowMenu: w, showDesc: L, changeShowDesc: C, hoverShowMenu: A } ) }, T.length + t)) ] }, B); }, jt = ({ commonAncestor: r, species: n, height: o, x1: a, x2: d, x0: c, y: l, stroke: _, showDesc: m = !0, changeShowDesc: s = () => { }, padding: p = 0, format: w = (Z) => Z.toString(), chronoScale: A = !0, showImages: L = !0, presentTime: C, toggleShowMenu: F, hoverShowMenu: T, className: B, buttonClassName: V }) => { const Z = C !== void 0, rt = r.allDescendants().filter((i) => Z ? i.apparition < C : !0), et = (i) => rt.indexOf(i), K = n.ancestor && et(n) > et(n.ancestor) ? -3 : 1, g = n.descendants.filter((i) => Z ? i.apparition < C : !0), t = g.filter((i) => i.apparition === n.extinction()).length === 0, e = w(Math.min(m ? n.extinction() : n.absoluteExtinction(), Z ? C : n.absoluteExtinction())); return /* @__PURE__ */ X("g", { children: [ /* @__PURE__ */ y( "line", { x1: a, y1: l, x2: d, y2: l, stroke: _ } ), /* @__PURE__ */ y( "foreignObject", { x: a + p, y: l + p * K, width: (A ? c ?? d : d) - a - 2 * p, height: o + (L && n.image ? o : 0), children: /* @__PURE__ */ X("div", { className: `flex flex-row justify-between w-full ${B ?? ""}`, children: [ /* @__PURE__ */ y("div", { children: A ? w(n.apparition) : "" }), /* @__PURE__ */ X( "button", { className: `p-0.625 justify-center flex flex-col items-center ${V ?? ""}`, onClick: () => F(n), onMouseEnter: () => T(n), onMouseLeave: () => T(void 0), children: [ n.name, n.image && L && /* @__PURE__ */ y( "img", { src: n.image, alt: n.name, style: { height: o } } ) ] } ), g.length > 0 ? /* @__PURE__ */ y("button", { onClick: s, className: "h-1", style: { maxWidth: 4 }, children: (t || !m) && (!c || c === d) ? e : "" }) : /* @__PURE__ */ y("div", { children: A ? e : "" }) ] }) } ), A && c && c < d && /* @__PURE__ */ y( "foreignObject", { x: c + p, y: l + p * K, width: d - c - 2 * p, height: o, children: /* @__PURE__ */ y("div", { className: "flex flex-row justify-end w-full", children: (t || !m) && A ? e : "" }) } ) ] }); }, Ft = (r, n, o) => r < n ? n : r > o ? o : r; function Nt(r) { return r && r.__esModule && Object.prototype.hasOwnProperty.call(r, "default") ? r.default : r; } var vt = { exports: {} }; /* @license Papa Parse v5.5.2 https://github.com/mholt/PapaParse License: MIT */ var Pt = vt.exports, St; function Ut() { return St || (St = 1, function(r, n) { ((o, a) => { r.exports = a(); })(Pt, function o() { var a = typeof self < "u" ? self : typeof window < "u" ? window : a !== void 0 ? a : {}, d, c = !a.document && !!a.postMessage, l = a.IS_PAPA_WORKER || !1, _ = {}, m = 0, s = {}; function p(t) { this._handle = null, this._finished = !1, this._completed = !1, this._halted = !1, this._input = null, this._baseIndex = 0, this._partialLine = "", this._rowCount = 0, this._start = 0, this._nextChunk = null, this.isFirstChunk = !0, this._completeResults = { data: [], errors: [], meta: {} }, (function(e) { var i = et(e); i.chunkSize = parseInt(i.chunkSize), e.step || e.chunk || (i.chunkSize = null), this._handle = new F(i), (this._handle.streamer = this)._config = i; }).call(this, t), this.parseChunk = function(e, i) { var h = parseInt(this._config.skipFirstNLines) || 0; if (this.isFirstChunk && 0 < h) { let E = this._config.newline; E || (u = this._config.quoteChar || '"', E = this._handle.guessLineEndings(e, u)), e = [...e.split(E).slice(h)].join(E); } this.isFirstChunk && g(this._config.beforeFirstChunk) && (u = this._config.beforeFirstChunk(e)) !== void 0 && (e = u), this.isFirstChunk = !1, this._halted = !1; var h = this._partialLine + e, u = (this._partialLine = "", this._handle.parse(h, this._baseIndex, !this._finished)); if (!this._handle.paused() && !this._handle.aborted()) { if (e = u.meta.cursor, h = (this._finished || (this._partialLine = h.substring(e - this._baseIndex), this._baseIndex = e), u && u.data && (this._rowCount += u.data.length), this._finished || this._config.preview && this._rowCount >= this._config.preview), l) a.postMessage({ results: u, workerId: s.WORKER_ID, finished: h }); else if (g(this._config.chunk) && !i) { if (this._config.chunk(u, this._handle), this._handle.paused() || this._handle.aborted()) return void (this._halted = !0); this._completeResults = u = void 0; } return this._config.step || this._config.chunk || (this._completeResults.data = this._completeResults.data.concat(u.data), this._completeResults.errors = this._completeResults.errors.concat(u.errors), this._completeResults.meta = u.meta), this._completed || !h || !g(this._config.complete) || u && u.meta.aborted || (this._config.complete(this._completeResults, this._input), this._completed = !0), h || u && u.meta.paused || this._nextChunk(), u; } this._halted = !0; }, this._sendError = function(e) { g(this._config.error) ? this._config.error(e) : l && this._config.error && a.postMessage({ workerId: s.WORKER_ID, error: e, finished: !1 }); }; } function w(t) { var e; (t = t || {}).chunkSize || (t.chunkSize = s.RemoteChunkSize), p.call(this, t), this._nextChunk = c ? function() { this._readChunk(), this._chunkLoaded(); } : function() { this._readChunk(); }, this.stream = function(i) { this._input = i, this._nextChunk(); }, this._readChunk = function() { if (this._finished) this._chunkLoaded(); else { if (e = new XMLHttpRequest(), this._config.withCredentials && (e.withCredentials = this._config.withCredentials), c || (e.onload = K(this._chunkLoaded, this), e.onerror = K(this._chunkError, this)), e.open(this._config.downloadRequestBody ? "POST" : "GET", this._input, !c), this._config.downloadRequestHeaders) { var i, h = this._config.downloadRequestHeaders; for (i in h) e.setRequestHeader(i, h[i]); } var u; this._config.chunkSize && (u = this._start + this._config.chunkSize - 1, e.setRequestHeader("Range", "bytes=" + this._start + "-" + u)); try { e.send(this._config.downloadRequestBody); } catch (E) { this._chunkError(E.message); } c && e.status === 0 && this._chunkError(); } }, this._chunkLoaded = function() { e.readyState === 4 && (e.status < 200 || 400 <= e.status ? this._chunkError() : (this._start += this._config.chunkSize || e.responseText.length, this._finished = !this._config.chunkSize || this._start >= ((i) => (i = i.getResponseHeader("Content-Range")) !== null ? parseInt(i.substring(i.lastIndexOf("/") + 1)) : -1)(e), this.parseChunk(e.responseText))); }, this._chunkError = function(i) { i = e.statusText || i, this._sendError(new Error(i)); }; } function A(t) { (t = t || {}).chunkSize || (t.chunkSize = s.LocalChunkSize), p.call(this, t); var e, i, h = typeof FileReader < "u"; this.stream = function(u) { this._input = u, i = u.slice || u.webkitSlice || u.mozSlice, h ? ((e = new FileReader()).onload = K(this._chunkLoaded, this), e.onerror = K(this._chunkError, this)) : e = new FileReaderSync(), this._nextChunk(); }, this._nextChunk = function() { this._finished || this._config.preview && !(this._rowCount < this._config.preview) || this._readChunk(); }, this._readChunk = function() { var u = this._input, E = (this._config.chunkSize && (E = Math.min(this._start + this._config.chunkSize, this._input.size), u = i.call(u, this._start, E)), e.readAsText(u, this._config.encoding)); h || this._chunkLoaded({ target: { result: E } }); }, this._chunkLoaded = function(u) { this._start += this._config.chunkSize, this._finished = !this._config.chunkSize || this._start >= this._input.size, this.parseChunk(u.target.result); }, this._chunkError = function() { this._sendError(e.error); }; } function L(t) { var e; p.call(this, t = t || {}), this.stream = function(i) { return e = i, this._nextChunk(); }, this._nextChunk = function() { var i, h; if (!this._finished) return i = this._config.chunkSize, e = i ? (h = e.substring(0, i), e.substring(i)) : (h = e, ""), this._finished = !e, this.parseChunk(h); }; } function C(t) { p.call(this, t = t || {}); var e = [], i = !0, h = !1; this.pause = function() { p.prototype.pause.apply(this, arguments), this._input.pause(); }, this.resume = function() { p.prototype.resume.apply(this, arguments), this._input.resume(); }, this.stream = function(u) { this._input = u, this._input.on("data", this._streamData), this._input.on("end", this._streamEnd), this._input.on("error", this._streamError); }, this._checkIsFinished = function() { h && e.length === 1 && (this._finished = !0); }, this._nextChunk = function() { this._checkIsFinished(), e.length ? this.parseChunk(e.shift()) : i = !0; }, this._streamData = K(function(u) { try { e.push(typeof u == "string" ? u : u.toString(this._config.encoding)), i && (i = !1, this._checkIsFinished(), this.parseChunk(e.shift())); } catch (E) { this._streamError(E); } }, this), this._streamError = K(function(u) { this._streamCleanUp(), this._sendError(u); }, this), this._streamEnd = K(function() { this._streamCleanUp(), h = !0, this._streamData(""); }, this), this._streamCleanUp = K(function() { this._input.removeListener("data", this._streamData), this._input.removeListener("end", this._streamEnd), this._input.removeListener("error", this._streamError); }, this); } function F(t) { var e, i, h, u, E = Math.pow(2, 53), H = -E, at = /^\s*-?(\d+\.?|\.\d+|\d+\.\d+)([eE][-+]?\d+)?\s*$/, st = /^((\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z)))$/, D = this, U = 0, b = 0, Y = !1, k = !1, O = [], f = { data: [], errors: [], meta: {} }; function J(R) { return t.skipEmptyLines === "greedy" ? R.join("").trim() === "" : R.length === 1 && R[0].length === 0; } function $() { if (f && h && (ot("Delimiter", "UndetectableDelimiter", "Unable to auto-detect delimiting character; defaulted to '" + s.DefaultDelimiter + "'"), h = !1), t.skipEmptyLines && (f.data = f.data.filter(function(v) { return !J(v); })), G()) { let v = function(z, W) { g(t.transformHeader) && (z = t.transformHeader(z, W)), O.push(z); }; if (f) if (Array.isArray(f.data[0])) { for (var R = 0; G() && R < f.data.length; R++) f.data[R].forEach(v); f.data.splice(0, 1); } else f.data.forEach(v); } function M(v, z) { for (var W = t.header ? {} : [], I = 0; I < v.length; I++) { var j = I, S = v[I], S = ((ht, x) => ((N) => (t.dynamicTypingFunction && t.dynamicTyping[N] === void 0 && (t.dynamicTyping[N] = t.dynamicTypingFunction(N)), (t.dynamicTyping[N] || t.dynamicTyping) === !0))(ht) ? x === "true" || x === "TRUE" || x !== "false" && x !== "FALSE" && (((N) => { if (at.test(N) && (N = parseFloat(N), H < N && N < E)) return 1; })(x) ? parseFloat(x) : st.test(x) ? new Date(x) : x === "" ? null : x) : x)(j = t.header ? I >= O.length ? "__parsed_extra" : O[I] : j, S = t.transform ? t.transform(S, j) : S); j === "__parsed_extra" ? (W[j] = W[j] || [], W[j].push(S)) : W[j] = S; } return t.header && (I > O.length ? ot("FieldMismatch", "TooManyFields", "Too many fields: expected " + O.length + " fields but parsed " + I, b + z) : I < O.length && ot("FieldMismatch", "TooFewFields", "Too few fields: expected " + O.length + " fields but parsed " + I, b + z)), W; } var q; f && (t.header || t.dynamicTyping || t.transform) && (q = 1, !f.data.length || Array.isArray(f.data[0]) ? (f.data = f.data.map(M), q = f.data.length) : f.data = M(f.data, 0), t.header && f.meta && (f.meta.fields = O), b += q); } function G() { return t.header && O.length === 0; } function ot(R, M, q, v) { R = { type: R, code: M, message: q }, v !== void 0 && (R.row = v), f.errors.push(R); } g(t.step) && (u = t.step, t.step = function(R) { f = R, G() ? $() : ($(), f.data.length !== 0 && (U += R.data.length, t.preview && U > t.preview ? i.abort() : (f.data = f.data[0], u(f, D)))); }), this.parse = function(R, M, q) { var v = t.quoteChar || '"', v = (t.newline || (t.newline = this.guessLineEndings(R, v)), h = !1, t.delimiter ? g(t.delimiter) && (t.delimiter = t.delimiter(R), f.meta.delimiter = t.delimiter) : ((v = ((z, W, I, j, S) => { var ht, x, N, pt; S = S || [",", " ", "|", ";", s.RECORD_SEP, s.UNIT_SEP]; for (var mt = 0; mt < S.length; mt++) { for (var ut, yt = S[mt], tt = 0, dt = 0, Q = 0, nt = (N = void 0, new B({ comments: j, delimiter: yt, newline: W, preview: 10 }).parse(z)), ft = 0; ft < nt.data.length; ft++) I && J(nt.data[ft]) ? Q++ : (ut = nt.data[ft].length, dt += ut, N === void 0 ? N = ut : 0 < ut && (tt += Math.abs(ut - N), N = ut)); 0 < nt.data.length && (dt /= nt.data.length - Q), (x === void 0 || tt <= x) && (pt === void 0 || pt < dt) && 1.99 < dt && (x = tt, ht = yt, pt = dt); } return { successful: !!(t.delimiter = ht), bestDelimiter: ht }; })(R, t.newline, t.skipEmptyLines, t.comments, t.delimitersToGuess)).successful ? t.delimiter = v.bestDelimiter : (h = !0, t.delimiter = s.DefaultDelimiter), f.meta.delimiter = t.delimiter), et(t)); return t.preview && t.header && v.preview++, e = R, i = new B(v), f = i.parse(e, M, q), $(), Y ? { meta: { paused: !0 } } : f || { meta: { paused: !1 } }; }, this.paused = function() { return Y; }, this.pause = function() { Y = !0, i.abort(), e = g(t.chunk) ? "" : e.substring(i.getCharIndex()); }, this.resume = function() { D.streamer._halted ? (Y = !1, D.streamer.parseChunk(e, !0)) : setTimeout(D.resume, 3); }, this.aborted = function() { return k; }, this.abort = function() { k = !0, i.abort(), f.meta.aborted = !0, g(t.complete) && t.complete(f), e = ""; }, this.guessLineEndings = function(z, v) { z = z.substring(0, 1048576); var v = new RegExp(T(v) + "([^]*?)" + T(v), "gm"), q = (z = z.replace(v, "")).split("\r"), v = z.split(` `), z = 1 < v.length && v[0].length < q[0].length; if (q.length === 1 || z) return ` `; for (var W = 0, I = 0; I < q.length; I++) q[I][0] === ` ` && W++; return W >= q.length / 2 ? `\r ` : "\r"; }; } function T(t) { return t.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } function B(t) { var e = (t = t || {}).delimiter, i = t.newline, h = t.comments, u = t.step, E = t.preview, H = t.fastMode, at = null, st = !1, D = t.quoteChar == null ? '"' : t.quoteChar, U = D; if (t.escapeChar !== void 0 && (U = t.escapeChar), (typeof e != "string" || -1 < s.BAD_DELIMITERS.indexOf(e)) && (e = ","), h === e) throw new Error("Comment character same as delimiter"); h === !0 ? h = "#" : (typeof h != "string" || -1 < s.BAD_DELIMITERS.indexOf(h)) && (h = !1), i !== ` ` && i !== "\r" && i !== `\r ` && (i = ` `); var b = 0, Y = !1; this.parse = function(k, O, f) { if (typeof k != "string") throw new Error("Input must be a string"); var J = k.length, $ = e.length, G = i.length, ot = h.length, R = g(u), M = [], q = [], v = [], z = b = 0; if (!k) return tt(); if (H || H !== !1 && k.indexOf(D) === -1) { for (var W = k.split(i), I = 0; I < W.length; I++) { if (v = W[I], b += v.length, I !== W.length - 1) b += i.length; else if (f) return tt(); if (!h || v.substring(0, ot) !== h) { if (R) { if (M = [], pt(v.split(e)), dt(), Y) return tt(); } else pt(v.split(e)); if (E && E <= I) return M = M.slice(0, E), tt(!0); } } return tt(); } for (var j = k.indexOf(e, b), S = k.indexOf(i, b), ht = new RegExp(T(U) + T(D), "g"), x = k.indexOf(D, b); ; ) if (k[b] === D) for (x = b, b++; ; ) { if ((x = k.indexOf(D, x + 1)) === -1) return f || q.push({ type: "Quotes", code: "MissingQuotes", message: "Quoted field unterminated", row: M.length, index: b }), ut(); if (x === J - 1) return ut(k.substring(b, x).replace(ht, D)); if (D === U && k[x + 1] === U) x++; else if (D === U || x === 0 || k[x - 1] !== U) { j !== -1 && j < x + 1 && (j = k.indexOf(e, x + 1)); var N = mt((S = S !== -1 && S < x + 1 ? k.indexOf(i, x + 1) : S) === -1 ? j : Math.min(j, S)); if (k.substr(x + 1 + N, $) === e) { v.push(k.substring(b, x).replace(ht, D)), k[b = x + 1 + N + $] !== D && (x = k.indexOf(D, b)), j = k.indexOf(e, b), S = k.indexOf(i, b); break; } if (N = mt(S), k.substring(x + 1 + N, x + 1 + N + G) === i) { if (v.push(k.substring(b, x).replace(ht, D)), yt(x + 1 + N + G), j = k.indexOf(e, b), x = k.indexOf(D, b), R && (dt(), Y)) return tt(); if (E && M.length >= E) return tt(!0); break; } q.push({ type: "Quotes", code: "InvalidQuotes", message: "Trailing quote on quoted field is malformed", row: M.length, index: b }), x++; } } else if (h && v.length === 0 && k.substring(b, b + ot) === h) { if (S === -1) return tt(); b = S + G, S = k.indexOf(i, b), j = k.indexOf(e, b); } else if (j !== -1 && (j < S || S === -1)) v.push(k.substring(b, j)), b = j + $, j = k.indexOf(e, b); else { if (S === -1) break; if (v.push(k.substring(b, S)), yt(S + G), R && (dt(), Y)) return tt(); if (E && M.length >= E) return tt(!0); } return ut(); function pt(Q) { M.push(Q), z = b; } function mt(Q) { var nt = 0; return nt = Q !== -1 && (Q = k.substring(x + 1, Q)) && Q.trim() === "" ? Q.length : nt; } function ut(Q) { return f || (Q === void 0 && (Q = k.substring(b)), v.push(Q), b = J, pt(v), R && dt()), tt(); } function yt(Q) { b = Q, pt(v), v = [], S = k.indexOf(i, b); } function tt(Q) { if (t.header && !O && M.length && !st) { var nt = M[0], ft = {}, xt = new Set(nt); let Ot = !1; for (let _t = 0; _t < nt.length; _t++) { let lt = nt[_t]; if (ft[lt = g(t.transformHeader) ? t.transformHeader(lt, _t) : lt]) { let bt, Rt = ft[lt]; for (; bt = lt + "_" + Rt, Rt++, xt.has(bt); ) ; xt.add(bt), nt[_t] = bt, ft[lt]++, Ot = !0, (at = at === null ? {} : at)[bt] = lt; } else ft[lt] = 1, nt[_t] = lt; xt.add(lt); } Ot && console.warn("Duplicate headers found and renamed."), st = !0; } return { data: M, errors: q, meta: { delimiter: e, linebreak: i, aborted: Y, truncated: !!Q, cursor: z + (O || 0), renamedHeaders: at } }; } function dt() { u(tt()), M = [], q = []; } }, this.abort = function() { Y = !0; }, this.getCharIndex = function() { return b; }; } function V(t) { var e = t.data, i = _[e.workerId], h = !1; if (e.error) i.userError(e.error, e.file); else if (e.results && e.results.data) { var u = { abort: function() { h = !0, Z(e.workerId, { data: [], errors: [], meta: { aborted: !0 } }); }, pause: rt, resume: rt }; if (g(i.userStep)) { for (var E = 0; E < e.results.data.length && (i.userStep({ data: e.results.data[E], errors: e.results.errors, meta: e.results.meta }, u), !h); E++) ; delete e.results; } else g(i.userChunk) && (i.userChunk(e.results, u, e.file), delete e.results); } e.finished && !h && Z(e.workerId, e.results); } function Z(t, e) { var i = _[t]; g(i.userComplete) && i.userComplete(e), i.terminate(), delete _[t]; } function rt() { throw new Error("Not implemented."); } function et(t) { if (typeof t != "object" || t === null) return t; var e, i = Array.isArray(t) ? [] : {}; for (e in t) i[e] = et(t[e]); return i; } function K(t, e) { return function() { t.apply(e, arguments); }; } function g(t) { return typeof t == "function"; } return s.parse = function(t, e) { var i = (e = e || {}).dynamicTyping || !1; if (g(i) && (e.dynamicTypingFunction = i, i = {}), e.dynamicTyping = i, e.transform = !!g(e.transform) && e.transform, !e.worker || !s.WORKERS_SUPPORTED) return i = null, s.NODE_STREAM_INPUT, typeof t == "string" ? (t = ((h) => h.charCodeAt(0) !== 65279 ? h : h.slice(1))(t), i = new (e.download ? w : L)(e)) : t.readable === !0 && g(t.read) && g(t.on) ? i = new C(e) : (a.File && t instanceof File || t instanceof Object) && (i = new A(e)), i.stream(t); (i = (() => { var h; return !!s.WORKERS_SUPPORTED && (h = (() => { var u = a.URL || a.webkitURL || null, E = o.toString(); return s.BLOB_URL || (s.BLOB_URL = u.createObjectURL(new Blob(["var global = (function() { if (typeof self !== 'undefined') { return self; } if (typeof window !== 'undefined') { return window; } if (typeof global !== 'undefined') { return global; } return {}; })(); global.IS_PAPA_WORKER=true; ", "(", E, ")();"], { type: "text/javascript" }))); })(), (h = new a.Worker(h)).onmessage = V, h.id = m++, _[h.id] = h); })()).userStep = e.step, i.userChunk = e.chunk, i.userComplete = e.complete, i.userError = e.error, e.step = g(e.step), e.chunk = g(e.chunk), e.complete = g(e.complete), e.error = g(e.error), delete e.worker, i.postMessage({ input: t, config: e, workerId: i.id }); }, s.unparse = function(t, e) { var i = !1, h = !0, u = ",", E = `\r `, H = '"', at = H + H, st = !1, D = null, U = !1, b = ((() => { if (typeof e == "object") { if (typeof e.delimiter != "string" || s.BAD_DELIMITERS.filter(function(O) { return e.delimiter.indexOf(O) !== -1; }).length || (u = e.delimiter), typeof e.quotes != "boolean" && typeof e.quotes != "function" && !Array.isArray(e.quotes) || (i = e.quotes), typeof e.skipEmptyLines != "boolean" && typeof e.skipEmptyLines != "string" || (st = e.skipEmptyLines), typeof e.newline == "string" && (E = e.newline), typeof e.quoteChar == "string" && (H = e.quoteChar), typeof e.header == "boolean" && (h = e.header), Array.isArray(e.columns)) { if (e.columns.length === 0) throw new Error("Option columns is empty"); D = e.columns; } e.escapeChar !== void 0 && (at = e.escapeChar + H), e.escapeFormulae instanceof RegExp ? U = e.escapeFormulae : typeof e.escapeFormulae == "boolean" && e.escapeFormulae && (U = /^[=+\-@\t\r].*$/); } })(), new RegExp(T(H), "g")); if (typeof t == "string" && (t = JSON.parse(t)), Array.isArray(t)) { if (!t.length || Array.isArray(t[0])) return Y(null, t, st); if (typeof t[0] == "object") return Y(D || Object.keys(t[0]), t, st); } else if (typeof t == "object") return typeof t.data == "string" && (t.data = JSON.parse(t.data)), Array.isArray(t.data) && (t.fields || (t.fields = t.meta && t.meta.fields || D), t.fields || (t.fields = Array.isArray(t.data[0]) ? t.fields : typeof t.data[0] == "object" ? Object.keys(t.data[0]) : []), Array.isArray(t.data[0]) || typeof t.data[0] == "object" || (t.data = [t.data])), Y(t.fields || [], t.data || [], st); throw new Error("Unable to serialize unrecognized input"); function Y(O, f, J) { var $ = "", G = (typeof O == "string" && (O = JSON.parse(O)), typeof f == "string" && (f = JSON.parse(f)), Array.isArray(O) && 0 < O.length), ot = !Array.isArray(f[0]); if (G && h) { for (var R = 0; R < O.length; R++) 0 < R && ($ += u), $ += k(O[R], R); 0 < f.length && ($ += E); } for (var M = 0; M < f.length; M++) { var q = (G ? O : f[M]).length, v = !1, z = G ? Object.keys(f[M]).length === 0 : f[M].length === 0; if (J && !G && (v = J === "greedy" ? f[M].join("").trim() === "" : f[M].length === 1 && f[M][0].length === 0), J === "greedy" && G) { for (var W = [], I = 0; I < q; I++) { var j = ot ? O[I] : I; W.push(f[M][j]); } v = W.join("").trim() === ""; } if (!v) { for (var S = 0; S < q; S++) { 0 < S && !z && ($ += u); var ht = G && ot ? O[S] : S; $ += k(f[M][ht], S); } M < f.length - 1 && (!J || 0 < q && !z) && ($ += E); } } return $; } function k(O, f) { var J, $; return O == null ? "" : O.constructor === Date ? JSON.stringify(O).slice(1, 25) : ($ = !1, U && typeof O == "string" && U.test(O) && (O = "'" + O, $ = !0), J = O.toString().replace(b, at), ($ = $ || i === !0 || typeof i == "function" && i(O, f) || Array.isArray(i) && i[f] || ((G, ot) => { for (var R = 0; R < ot.length; R++) if (-1 < G.indexOf(ot[R])) return !0; return !1; })(J, s.BAD_DELIMITERS) || -1 < J.indexOf(u) || J.charAt(0) === " " || J.charAt(J.length - 1) === " ") ? H + J + H : J); } }, s.RECORD_SEP = "", s.UNIT_SEP = "", s.BYTE_ORDER_MARK = "\uFEFF", s.BAD_DELIMITERS = ["\r", ` `, '"', s.BYTE_ORDER_MARK], s.WORKERS_SUPPORTED = !c && !!a.Worker, s.NODE_STREAM_INPUT = 1, s.LocalChunkSize = 10485760, s.RemoteChunkSize = 5242880, s.DefaultDelimiter = ",", s.Parser = B, s.ParserHandle = F, s.NetworkStreamer = w, s.FileStreamer = A, s.StringStreamer = L, s.ReadableStreamStreamer = C, a.jQuery && ((d = a.jQuery).fn.parse = function(t) { var e = t.config || {}, i = []; return this.each(function(E) { if (!(d(this).prop("tagName").toUpperCase() === "INPUT" && d(this).attr("type").toLowerCase() === "file" && a.FileReader) || !this.files || this.files.length === 0) return !0; for (var H = 0; H < this.files.length; H++) i.push({ file: this.files[H], inputElem: this, instanceConfig: d.extend({}, e) }); }), h(), this; function h() { if (i.length === 0) g(t.complete) && t.complete(); else { var E, H, at, st, D = i[0]; if (g(t.before)) { var U = t.before(D.file, D.inputElem); if (typeof U == "object") { if (U.action === "abort") return E = "AbortError", H = D.file, at = D.inputElem, st = U.reason, void (g(t.error) && t.error({ name: E }, H, at, st)); if (U.action === "skip") return void u(); typeof U.config == "object" && (D.instanceConfig = d.extend(D.instanceConfig, U.config)); } else if (U === "skip") return void u(); } var b = D.instanceConfig.complete; D.instanceConfig.complete = function(Y) { g(b) && b(Y, D.file, D.inputElem), u(); }, s.parse(D.file, D.instanceConfig); } } function u() { i.splice(0, 1), h(); } }), l && (a.onmessage = function(t) { t = t.data, s.WORKER_ID === void 0 && t && (s.WORKER_ID = t.workerId), typeof t.input == "string" ? a.postMessage({ workerId: s.WORKER_ID, results: s.parse(t.input, t.config), finished: !0 }) : (a.File && t.input instanceof File || t.input instanceof Object) && (t = s.parse(t.input, t.config)) && a.postMessage({ workerId: s.WORKER_ID, results: t, finished: !0 }); }), (w.prototype = Object.create(p.prototype)).constructor = w, (A.prototype = Object.create(p.prototype)).constructor = A, (L.prototype = Object.create(L.prototype)).constructor = L, (C.prototype = Object.create(p.prototype)).constructor = C, s; }); }(vt)), vt.exports; } var qt = Ut(); const zt = /* @__PURE__ */ Nt(qt); let Ct = []; const kt = async (r) => { const a = await (await fetch(r)).body.getReader().read(), c = new TextDecoder("utf-8").decode(a.value), { data: l } = zt.parse(c, { header: !0, dynamicTyping: !0, delimiter: ";" }); return l; }, $t = (r = "/translate.csv") => (async (n = "/translate.csv") => { Ct = await kt(n); })(r), it = (r, n, o = [], a = "/translate.csv") => { const [d, c] = P([]); Et(() => { kt(a).then(c), $t(a); }, [n]); const l = d.find((_) => _.code === r) ?? Ct.find((_) => _.code === r); try { const _ = l[n]; return o.reduce((s, p, w) => s.replace(`{${w}}`, p), _); } catch { return; } }, Zt = async (r, n, o = [], a = "/translate.csv") => { const c = (await kt(a)).find((l) => l.code === r); try { const l = c[n]; return o.reduce((_, m, s) => _.replace(`{${s}}`, m), l); } catch { return ""; } }, Gt = (r = "/translate.csv") => { const [n, o] = P(/* @__PURE__ */ new Map()); return Et(() => { (async () => { const c = (await kt(r)).find((l) => l.code === "lan"); if (c) { delete c.code; const l = new Map(Object.entries(c)); o(l); } })(); }, []), n; }, Vt = ({ species: r, language: n, open: o, onClose: a, saveSpecies: d, createDescendant: c, createAncestor: l, deleteAncestor: _, deleteSpecies: m }) => { const [s, p] = P(r.name), [w, A] = P(r.apparition), [L, C] = P(r.duration), [F, T] = P(r.description ?? ""), [B, V] = P(!1), [Z, rt] = P(!1), [et, K] = P(r.image ?? ""), g = () => { V(!B); }, t = () => { rt(!Z); }, e = (i) => i.ancestor ? i.ancestor.descendants.length === 1 && e(i.ancestor) : !0; return /* @__PURE__ */ y(Jt, { open: o, onClose: a, children: /* @__PURE__ */ y("form", { style: { backgroundColor: "grey" }, className: "flex flex-col text-start w-auto fixed p-2.5", children: /* @__PURE__ */ X( Dt, { name: s, setName: p, apparition: w, setApparition: (i) => { A(r.ancestor ? Ft(i, r.ancestor.apparition, r.ancestor.extinction()) : i), C(r.descendants.length > 0 ? Math.max(Math.max(...r.descendants.map((h) => h.apparition)) - w, L) : L); }, minApparition: r.ancestor ? r.ancestor.apparition : void 0, maxApparition: r.ancestor ? r.ancestor.extinction() : void 0, duration: L, setDuration: C, minDuration: r.descendants.length > 0 ? Math.max(...r.descendants.map((i) => i.apparition)) - w : void 0, maxDuration: r.descendants.length > 0 ? Math.max(...r.descendants.map((i) => i.apparition)) - w : void 0, description: F, setDescription: T, image: et, setImage: K, language: n, children: [ /* @__PURE__ */ y("button", { onClick: async () => { try { await (d == null ? void 0 : d(r, s, w, L, F, et)), a == null || a(); } catch (i) { console.error(i); } }, children: it("spbtn00", n ?? "") }), /* @__PURE__ */ y("button", { type: "button", onClick: m, children: it("spbtn01", n ?? "") }), /* @__PURE__ */ y("button", { type: "button", onClick: g, children: it("spbtn02", n ?? "") }), B && /* @__PURE__ */ y( Bt, { species: r, language: n, onClose: a, createDescendant: c } ), r.ancestor ? e(r) && /* @__PURE__ */ y("button", { type: "button", onClick: async () => { try { await (_ == null ? void 0 : _()), a == null || a(); } catch (i) { console.error(i); } }, children: it("spbtn04" + (r.ancestor.ancestor ? "_0" : ""), n ?? "") }) : /* @__PURE__ */ y("button", { type: "button", onClick: t, children: it("spbtn03", n ?? "") }), Z && /* @__PURE__ */ y( Ht, { species: r, language: n, onClose: a, createAncestor: l } ), /* @__PURE__ */ y("button", { type: "button", onClick: a, children: it("spbtn05", n ?? "") }) ] } ) }) }); }, Dt = ({ name: r, setName: n, apparition: o, setApparition: a, minApparition: d, maxApparition: c, duration: l, setDuration: _, minDuration: m, maxDuration: s, description: p, setDescription: w, language: A, image: L, setImage: C, children: F }) => /* @__PURE__ */ X(wt, { children: [ /* @__PURE__ */ y("table", { children: /* @__PURE__ */ X("tbody", { children: [ /* @__PURE__ */ X("tr", { children: [ /* @__PURE__ */ X("td", { children: [ it("splbl00", A ?? ""), ":" ] }), /* @__PURE__ */ y("td", { children: /* @__PURE__ */ y( "input", { type: "text", value: r, onChange: (T) => n(T.target.value) } ) }) ] }), /* @__PURE__ */ X("tr", { children: [ /* @__PURE__ */ X("td", { children: [ it("splbl01", A ?? ""), ":" ] }), /* @__PURE__ */ y("td", { children: /* @__PURE__ */ y( "input", { type: "number", min: d, max: c, value: o, onChange: (T) => a(Number(T.target.value)) } ) }) ] }), /* @__PURE__ */ X("tr", { children: [ /* @__PURE__ */ X("td", { children: [ it("splbl02", A ?? ""), ":" ] }), /* @__PURE__ */ y("td", { children: /* @__PURE__ */ y( "input", { type: "number", min: m, max: s, value: l, onChange: (T) => _(Number(T.target.value)) } ) }) ] }), /* @__PURE__ */ X("tr", { children: [ /* @__PURE__ */ X("td", { children: [ it("splbl03", A ?? ""), ":" ] }), /* @__PURE__ */ y("td", { children: /* @__PURE__ */ y( "textarea", { value: p, onChange: (T) => w(T.target.value) } ) }) ] }), /* @__PURE__ */ X("tr", { children: [ /* @__PURE__ */ X("td", { children: [ it("splbl04", A ?? ""), ":" ] }), /* @__PURE__ */ y("td", { children: /* @__PURE__ */ y( "input", { type: "text", value: L, onChange: (T) => C(T.target.value) } ) }) ] }), /* @__PURE__ */ y("tr", { children: /* @__PURE__ */ y("td", { colSpan: 2, children: /* @__PURE__ */ y( "img", { src: L, style: { height: "100px" } } ) }) }) ] }) }), F ] }), Bt = ({ species: r, language: n, onClose: o, createDescendant: a }) => { const [d, c] = P(""), [l, _] = P(r.duration), [m, s] = P(r.duration), [p, w] = P(""), [A, L] = P(""); return /* @__PURE__ */ y(wt, { children: /* @__PURE__ */ y( Dt, { name: d, setName: c, apparition: r.apparition + l, setApparition: (C) => _(C - r.apparition), minApparition: r.apparition, maxApparition: r.extinction(), duration: m, setDuration: s, description: p, setDescription: w, image: A, setImage: L, language: n, children: /* @__PURE__ */ y("button", { type: "button", onClick: async () => { try { await (a == null ? void 0 : a(r, d, l, m, p, A)), o == null || o(); } catch (C) { console.error(C); } }, children: it("cdbtn00", n ?? "") }) } ) }); }, Ht = ({ species: r, language: n, onClose: o, createAncestor: a }) => { const [d, c] = P(""), [l, _] = P(r.duration), [m, s] = P(r.duration), [p, w] = P(""), [A, L] = P(""); return /* @__PURE__ */ y(wt, { children: /* @__PURE__ */ y( Dt, { name: d, setName: c, apparition: r.apparition - l, setApparition: (C) => { _(r.apparition - C), s(Math.max(r.apparition - C, m));