UNPKG

ts-browser-helpers

Version:

A collection of utility classes, functions and decorators for javascript/typescript projects, for use in the browser.

1,267 lines (1,266 loc) 49.8 kB
/** * @license * ts-browser-helpers v0.19.4 * Copyright 2022-2025 repalash <palash@shaders.app> * MIT License * See ./dependencies.txt for bundled third-party dependencies and licenses. */ class H { constructor() { this._eventListeners = {}, this.dispatchEvent = this.dispatchEvent.bind(this), this.addEventListener = this.addEventListener.bind(this), this.removeEventListener = this.removeEventListener.bind(this), this.hasEventListener = this.hasEventListener.bind(this); } addEventListener(e, i) { const n = this._eventListeners; n[e] === void 0 && (n[e] = []), n[e].includes(i) || n[e].push(i); } hasEventListener(e, i) { const n = this._eventListeners; return n[e] !== void 0 && n[e].includes(i); } removeEventListener(e, i) { const r = this._eventListeners[e]; if (r !== void 0) { const o = r.indexOf(i); o !== -1 && r.splice(o, 1); } } dispatchEvent(e) { const n = this._eventListeners[e.type]; if (n !== void 0) { e.target = this; const r = n.slice(0); for (let o = 0, s = r.length; o < s; o++) r[o].call(this, e); } } } async function pe(t) { return new Promise((e) => setTimeout(e, Math.max(0, t))); } function _() { return (typeof performance > "u" ? Date : performance).now(); } class me extends H { constructor() { super(...arguments), this._onPointerDown = (e) => { if (e.button !== 0 || !this._element) return; this._pointerUp = void 0; const i = e.clientX / this._element.clientWidth * 2 - 1, n = -(e.clientY / this._element.clientHeight) * 2 + 1, r = _(); this._pointerDown = { x: i, y: n, time: r }, this._pointer = this._pointerDown, this.dispatchEvent({ type: "dragStart", pointer: this._pointerDown }); }, this._onPointerMove = (e) => { if (!this._pointerDown || !this._pointer || !this._element) return; const i = e.clientX / this._element.clientWidth * 2 - 1, n = -(e.clientY / this._element.clientHeight) * 2 + 1, r = _(); this.dispatchEvent({ type: "drag", pointer: this._pointer, drag: { x: i - this._pointerDown.x, y: n - this._pointerDown.y, time: r - this._pointerDown.time }, delta: { x: i - this._pointer.x, y: n - this._pointer.y, time: r - this._pointer.time } }), this._pointer = { x: i, y: n, time: _() }, e.buttons % 2 === 0 && this._onPointerUp(e); }, this._onPointerUp = (e) => { if (e.button !== 0 || !this._pointerDown || !this._element) return; const i = e.clientX / this._element.clientWidth * 2 - 1, n = -(e.clientY / this._element.clientHeight) * 2 + 1, r = _(); this._pointerUp = { x: i, y: n, time: r }, this.dispatchEvent({ type: "dragEnd", pointer: this._pointerUp, drag: { x: this._pointerUp.x - this._pointerDown.x, y: this._pointerUp.y - this._pointerDown.y, time: this._pointerUp.time - this._pointerDown.time } }), this._pointerDown = void 0, this._pointer = void 0; }; } get element() { return this._element; } set element(e) { this._element !== e && (this._element && this._removeElement(), this._element = e, this._element && this._addElement()); } _removeElement() { var e, i, n, r, o; (e = this._element) == null || e.removeEventListener("pointerdown", this._onPointerDown), (i = this._element) == null || i.removeEventListener("pointermove", this._onPointerMove), (n = this._element) == null || n.removeEventListener("pointerup", this._onPointerUp), (r = this._element) == null || r.removeEventListener("pointercancel", this._onPointerUp), (o = this._element) == null || o.removeEventListener("pointerout", this._onPointerUp); } _addElement() { var e, i, n, r, o; (e = this._element) == null || e.addEventListener("pointerdown", this._onPointerDown), (i = this._element) == null || i.addEventListener("pointermove", this._onPointerMove), (n = this._element) == null || n.addEventListener("pointerup", this._onPointerUp), (r = this._element) == null || r.addEventListener("pointercancel", this._onPointerUp), (o = this._element) == null || o.addEventListener("pointerout", this._onPointerUp); } dispose() { this.element = void 0; } } class ge { constructor(e) { this.options = { limit: 500, // maximum commands stack size debug: !1, // whether to emit execution status in console bindHotKeys: !1 // whether to bind "undo" and "redo" commands to "Ctrl+Z", "Ctrl+Y" & "Ctrl+Shift+Z" hot keys // useTransactions: true // whether to initialize transactions manager }, this.enabled = !0, this.presets = {}, this._keyDown = (i) => { if (!this.enabled) return; const n = i.ctrlKey || i.metaKey; i.code === "KeyZ" && n && !i.shiftKey ? this.undo() : (i.code === "KeyZ" && n && i.shiftKey || i.code === "KeyY" && i.ctrlKey) && this.redo(); }, Object.assign(this.options, e), this.limit = e.limit, this.options = e, this.reset(), e.bindHotKeys && this.bindHotKeys(), this.log(`Initialized with stack limit of ${this.limit} commands`); } /** * Bind 'undo' and 'redo' actions to 'Ctrl/Cmd+Z', 'Ctrl+Y' & 'Ctrl/Cmd+Shift+Z' hot keys. * It is a basic implementation for quick testing and should be replaced with custom event handlers * for more flexible processing. * @returns {JSUndoManager} */ bindHotKeys() { return this.log("Bound 'undo' and 'redo' actions to 'Ctrl/Cmd+Z', 'Ctrl+Y' & 'Ctrl/Cmd+Shift+Z' hot keys"), (this.options.hotKeyRoot ?? document).addEventListener("keydown", this._keyDown), this; } /** * Removes the event listeners and clears the stack */ dispose() { return (this.options.hotKeyRoot ?? document).removeEventListener("keydown", this._keyDown), this.reset(); } /** * Remember executed command containing "redo" and "undo" functions * @param {Object|Function} command - either an object with "redo" and "undo" functions * @returns {JSUndoManager} */ record(e) { return this.enabled ? (this._record(e), this) : this; } replaceLast(e) { const i = this.peek(); if (i) return this.log("replace", i, "with", e), this.stack[this.sp] = e, this; } /** * Execute function and record it with its opposite "undo" function * @param {Object|Function} command - either an object with "redo" and "undo" functions * @param {Function} [undo] - "undo" function, used if the first argument is also a function * @returns {JSUndoManager} */ execute(e) { if (!this.enabled) return; let i = this._rc(e), n = i.redo; return this.record.apply(this, i), this.log("Executing function..."), n.apply(e), this; } _rc(e) { if (e.type) { const i = this.presets[e.type]; if (typeof i == "function") return i(e); throw console.error(e, i, this.presets), new Error("Preset command not found"); } else return e; } _record(e) { this.enabled && (this.log("Recording command", e), this._rebase(), this.stack.push(e), this.sp++, this._keepLimit()); } //forget "future" commands if stack pointer is not at the end _rebase() { this.canRedo() && (this.stack.length = this.sp + 1); } //sustain limited size of stack; cut extra commands starting with the latest ones _keepLimit() { if (this.stack.length <= this.limit) return; let e = this.stack.length - this.limit; this.log("Stack size reached its limit: ${this.limit} commands. Cutting off most old commands..."), e === 1 ? this.stack.shift() : this.stack.splice(0, e), this.sp -= e; } /** * Undo previous command if possible * @returns {JSUndoManager} */ undo() { if (!this.canUndo()) return this; let e = this.stack[this.sp]; return this.log("undo"), this.sp--, this._rc(e).undo(), this; } /** * Check whether undoing previous command is possible * @returns {boolean} */ canUndo() { return this.sp >= 0 && this.enabled; } /** * Get the last command that was done */ peek() { return this.canUndo() ? this.stack[this.sp] : null; } /** * Redo the command which was previously undone * @returns {JSUndoManager} */ redo() { if (!this.canRedo()) return this; let e = this.stack[this.sp + 1]; return this.log("redo"), this.sp++, this._rc(e).redo(), this; } /** * Check whether redoing command is possible * @returns {boolean} */ canRedo() { return this.sp < this.stack.length - 1 && this.enabled; } /** * Gets the last command that was undone */ peekForward() { return this.canRedo() ? this.stack[this.sp + 1] : null; } /** * Change stack size limit initially defined in the constructor options * @param {number} limit */ setLimit(e) { let i = this.stack.length - this.sp - 1; if (e < 1 || typeof e != "number") throw new TypeError(`JSUndoManager.setLimit(): unexpected argument limit=${e}. Should be a positive number`); return e < i ? console.warn(`JSUndoManager.setLimit(): cannot set stack limit (${e}) less than the number of 'redoable' commands (${i})`) : (this.limit = Math.floor(e), this._keepLimit()), this; } /** * Reset all commands from memory */ reset() { return this.log("reset"), this.stack = [], this.sp = -1, this; } /** * Check whether the commands stack is empty * @returns {boolean} */ isEmpty() { return !this.stack.length; } /** * Check whether the commands stack size reaches its limit * @returns {boolean} */ isFull() { return this.stack.length === this.limit; } /** * Get number of commands in memory stack * @returns {Number} */ getSize() { return this.stack.length; } log(e, ...i) { this.options.debug && console.log(`Command Manager: ${e}`, ...i); } } /* @license * Copyright 2020 Google LLC. All Rights Reserved. * Licensed under the Apache License, Version 2.0 (the 'License'); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an 'AS IS' BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ const w = class w { constructor(e = w.DECAY_MILLISECONDS) { this.velocity = 0, this.naturalFrequency = 0, this.setDecayTime(e); } setDecayTime(e) { this.naturalFrequency = 1 / Math.max(w.MIN_DECAY_MILLISECONDS, e); } update(e, i, n, r) { const o = 2e-4 * this.naturalFrequency; if (e == null || r === 0 || e === i && this.velocity === 0) return i; if (n < 0) return e; const s = e - i, a = this.velocity + this.naturalFrequency * s, c = s + n * a, u = Math.exp(-this.naturalFrequency * n), l = (a - this.naturalFrequency * c) * u, h = -this.naturalFrequency * (l + a * u); return Math.abs(l) < o * Math.abs(r) && h * s >= 0 ? (this.velocity = 0, i) : (this.velocity = l, i + c * u); } }; w.SETTLING_TIME = 1e4, w.MIN_DECAY_MILLISECONDS = 1e-3, w.DECAY_MILLISECONDS = 50; let M = w; function we() { const t = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas"); return t.style.display = "block", t; } function ye({ innerHTML: t = "", id: e, classList: i, addToBody: n = !0, elementTag: r = "div" }) { const o = document.createElement(r); return e && (o.id = e), o.innerHTML = t, i && o.classList.add(...i), n && document.body.appendChild(o), o; } async function N(t) { return new Promise((e, i) => { const n = new Image(); n.onload = () => e(n), n.onerror = i, n.crossOrigin = "anonymous", n.decoding = "sync", n.src = t; }); } function W(t, e = document.head) { const i = document.createElement("style"); return i.type = "text/css", i.innerText = t, e == null || e.appendChild(i), i; } async function ve(t, e = document.head) { return new Promise((i, n) => { const r = document.createElement("script"); r.setAttribute("src", t), r.addEventListener("load", () => i(r)), r.addEventListener("error", n), e.appendChild(r); }); } async function be(t, e) { var n; t.innerHTML = e; const i = t.getElementsByTagName("script"); for (let r = 0; r < i.length; r++) { const o = i[r], s = V(o); let a = !1; await new Promise((c) => { s.onload = c, s.onerror = () => { a = !0, c(void 0); }; }), !a && ((n = o.parentNode) == null || n.replaceChild(s, o)); } } function V(t, e) { e = e ?? document.createElement("script"), e.type = t.type || "text/javascript", e.text = t.text; for (let i = 0; i < t.attributes.length; i++) { const n = t.attributes[i]; e.setAttribute(n.name, n.value); } return e; } function xe(t) { if (!window) return console.warn("window is required"), ""; let e = ""; const i = new Uint8Array(t), n = i.byteLength; for (let r = 0; r < n; r++) e += String.fromCharCode(i[r]); return window.btoa(e); } function ke(t) { if (!window) return console.warn("window is required"), new Uint8Array(0); const e = window.atob(t), i = e.length, n = new Uint8Array(i); for (let r = 0; r < i; r++) n[r] = e.charCodeAt(r); return n.buffer; } const B = { Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array }; function Ee(t, e) { return new B[t](e); } function Ce(t) { return t.replace( /\w\S*/g, function(e) { return e.charAt(0).toUpperCase() + e.substr(1).toLowerCase(); } ); } function _e(t) { return t.replace( /([-_][a-z])/ig, (e) => e.toUpperCase().replace("-", "").replace("_", "") ); } function Se(t) { if (!t || t === "" || t.match(/__MACOSX\/.*\._/)) return ""; t = t.replace(/\?.*$/, ""); const e = t.split(/[\\/]/).pop() ?? "", i = e.lastIndexOf("."); return e === "" || i < 1 ? "" : e.slice(i + 1); } function Le(t) { return t.substring(t.lastIndexOf("/") + 1); } function Y(t) { return RegExp.escape ? RegExp.escape(t) : t.replace(/[.*+?^${}()|[\]/\\=!:]/g, "\\$&"); } function f(t, e, i) { return t.replace(new RegExp(Y(e), "g"), i); } function Ae(t, e, i, { replaceAll: n = !1, prepend: r = !1, append: o = !1, notFoundCallback: s = () => { } } = {}) { if (s && !t.includes(e)) return s(), t; let a = i; return r ? a = i + e : o && (a = e + i), n ? t.replaceAll(e, a) : t.replace(e, a); } function ze(t) { return t.sort(), t[0].split("").map((e, i) => t[t.length - 1][i] === e ? e : "\0").join("").split("\0").at(0) || ""; } function g(t) { return t.replace(/[&<>"']/g, function(e) { switch (e) { case "&": return "&amp;"; case "<": return "&lt;"; case ">": return "&gt;"; case '"': return "&quot;"; case "'": return "&#39;"; default: return e; } }); } const Ue = (t, ...e) => String.raw({ raw: t }, ...e), K = (t, ...e) => String.raw({ raw: t }, ...e), Oe = (t, ...e) => String.raw({ raw: t }, ...e), J = (t, ...e) => { let i = String.raw({ raw: t }, ...e); return i = f(i, "%", "%25"), i = f(i, "> <", "><"), i = f(i, "; }", ";}"), i = f(i, "<", "%3c"), i = f(i, ">", "%3e"), i = f(i, '"', "'"), i = f(i, "#", "%23"), i = f(i, "{", "%7b"), i = f(i, "}", "%7d"), i = f(i, "|", "%7c"), i = f(i, "^", "%5e"), i = f(i, "`", "%60"), i = f(i, "@", "%40"), i = f(i, "&", "&amp;"), i = f(i, ` `, "%0A"), "data:image/svg+xml;charset=UTF-8," + i; }; function De(t = document.head) { return W(K` ::-webkit-scrollbar { width: 8px; /* for vertical scrollbars */ height: 8px; /* for horizontal scrollbars */ } ::-webkit-scrollbar-track { background: rgba(64, 64, 64, 0.4); border-radius: 6px; } ::-webkit-scrollbar-thumb { background: rgba(128, 128, 128, 0.2); border-radius: 6px; } ::-webkit-scrollbar-corner {background: rgba(0,0,0,0.5);} `, t); } function G(t, e) { const i = window.URL.createObjectURL(t), n = document.createElement("a"); n.style.display = "none", n.href = i, n.download = e, document.body.appendChild(n), n.click(), setTimeout(() => { document.body.removeChild(n), window.URL.revokeObjectURL(i); }, 1e3); } async function X(t) { return new Promise((e, i) => { const n = new FileReader(); n.onload = (r) => e(n.result), n.onerror = (r) => i(n.error), n.onabort = (r) => i(new Error("Read aborted")), n.readAsDataURL(t); }); } function Ie(t, e) { return G(t, e ?? t.name); } async function Pe(t = !1, e = !1, i) { const n = document.createElement("input"); n.type = "file", n.multiple = t, n.accept = i || "*", n.webkitdirectory = e, n.style.display = "none", document.body.appendChild(n), n.click(); const r = await new Promise((o) => { n.onchange = (s) => { o(Array.from(n.files || [])); }; }); return document.body.removeChild(n), r; } function Te() { let t = !1; return function(e) { (/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i.test(e) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(e.substr(0, 4))) && (t = !0); }(navigator.userAgent || navigator.vendor || window.opera), t; } function Me(t) { return t < 0.04045 ? t * 0.0773993808 : Math.pow(t * 0.9478672986 + 0.0521327014, 2.4); } function $e(t) { return t < 31308e-7 ? t * 12.92 : 1.055 * Math.pow(t, 0.41666) - 0.055; } function Re(t, e = 1, i = 1) { const n = document.createElement("canvas"); n.width = e, n.height = i; const r = n.getContext("2d"); r.fillStyle = "#" + t, r.fillRect(0, 0, e, i); const o = n.toDataURL(); return n.remove(), o; } function Z(t, e) { let i; do i = Object.getOwnPropertyDescriptor(t, e); while (!i && (t = Object.getPrototypeOf(t))); return i; } function Q(t, e, i = !0, n = !1) { const r = Z(t, e); return !!(r != null && r.set) || i && (r == null ? void 0 : r.writable) !== !1 && (r == null ? void 0 : r.get) === void 0 || n && !r; } function D(t, e, i, n = !0, r = !1) { return t && Q(t, e, n, r) ? (t[e] = i, !0) : !1; } function Fe(t, ...e) { return typeof t == "function" && (t = t(...e)), t; } function qe(t, e, i) { for (const n of i) { const r = t[n]; r !== void 0 && D(e, n, r, !0); } return e; } function He(t, e) { for (const i of e) if (!t.includes(i)) return !1; return !0; } function j(t, e) { for (let i = t.length - 1; i >= 0; i--) if (e(t[i])) return i; return -1; } function Ne(t, e) { return function(...i) { return t(), e && e.call(this, ...i); }; } function We(t, e) { return function(...i) { return t(...i), e && e.call(this, ...i); }; } function Ve(t, e, i = !1) { for (typeof t == "string" && (t = t.split(".")); t.length > 0; ) { if (!e) return e; const n = t.splice(0, 1)[0]; if (!(n.length < 1)) if (Array.isArray(e)) e = e[parseInt(n)]; else if (typeof e == "object" && n in e) e = e[n]; else { if (i) throw new Error("invalid access, check " + n + " in " + e); return; } } return e; } function Be(t, e) { return Object.keys(t).find((i) => t[i] === e); } function L(t, e) { return Object.hasOwn ? Object.hasOwn(t, e) : t.hasOwnProperty(e); } function Ye(t, e, i = !0) { const n = i ? t : {}, r = Object.keys(t); for (const o of r) n[o] = e(t[o], o); return n; } function $(t, e) { return Object.fromEntries(Object.entries(t).map((i) => e(i))); } const A = { // object priority: 1 / 0, serialize: (t, e) => $(t, ([i, n]) => [i, m.Serialize(n, e, !1)]), deserialize: (t, e, i) => Object.assign(e || {}, $(t, ([n, r]) => [n, m.Deserialize(r, e == null ? void 0 : e[n], i, !1)])), isType: (t) => (t.constructor || Object) === Object }, d = class d { static GetSerializer(e) { return d.Serializers.find((i) => i.isType(e)); } static RegisterSerializer(...e) { for (const i of e) { const n = i.priority ?? 1e10, r = j(d.Serializers, (o) => o.priority !== void 0 && o.priority < n); r >= 0 ? d.Serializers.splice(r + 1, 0, i) : d.Serializers.push(i); } } static UnregisterSerializer(...e) { for (const i of e) { const n = d.Serializers.indexOf(i); n >= 0 && d.Serializers.splice(n, 1); } } /** * Serialize an object * @param obj - object to serialize * @param meta - Optional object to store common meta-data/resources across the serialization process of multiple objects * @param isThis - true if called from inside the serialization function, like custom {@link IJSONSerializable.toJSON}. */ static Serialize(e, i, n = !1) { if (typeof e == "function") return; if (!n) { const s = d.GetSerializer(e); if (s) return s.serialize(e, i); if (typeof e.toJSON == "function") { const a = e.toJSON(i, !0); return e.serializableClassId && a && (a.serializableClassId = e.serializableClassId), a; } } let r = e.constructor ?? Object; const o = {}; for (; r && r !== Object; ) { const s = d.TypeMap.get(r) ?? []; for (const [a, c] of s) o[a] = d.Serialize(e[c], i, !1); r = Object.getPrototypeOf(r); } return e.serializableClassId && (o.serializableClassId = e.serializableClassId), o; } /** * Deserialize an object * @param data - data to deserialize * @param obj - current object that's set. If of the same class/type the data is deserialized into that instead of creating new objects. * @param meta - Optional object to retrieve common meta-data/resources across the deserialization process of multiple objects. Objects in meta must be class instances, not js objects. (like Material, Texture, Object3D etc) * @param isThis - true if called from inside the deserialization function, like custom {@link IJSONSerializable.fromJSON} */ static Deserialize(e, i, n, r = !1) { if (e === void 0 || i === e) return i; if (e && typeof e == "object" && (e.constructor || Object) === Object && e.resource && typeof e.resource == "string" && e.uuid) { const s = n == null ? void 0 : n[e.resource]; if (!s) return console.warn(`Serialization: Resource ${e.resource} not found`), i; const a = s[e.uuid]; if (!a) return console.warn(`Serialization: Resource ${e.resource} with uuid ${e.uuid} not found`), i; if (e = a, typeof e == "object" && (e.__useCount = e.__useCount ? e.__useCount + 1 : 1), i === e) return i; if (e && typeof e == "object") { if ((e.constructor || Object) !== Object) return i && console.warn("Serialization: replacing object", i, "with deserialized object", e), e; console.error("Serialization: during Deserialize, meta should only have class instances, not js objects", e, i, n); } } if (e && typeof e == "object" && (e.constructor || Object) !== Object && !Array.isArray(e) && !e.serializableClassId) { if (e instanceof Blob) return e; console.warn("Serialization: Data might already be deserialized. It will be cloned, or copied to source", e, "source", i, e.constructor, e.constructor !== Object); } if (e && typeof e == "object") { const s = (a) => { const c = d.SerializableClasses.get(a); c && (c.DataInConstructor ? i = new c(e) : i = new c()); }; e.serializableClassId && (!i || i.serializableClassId !== e.serializableClassId) && s(e.serializableClassId), e.type && (!i || i.type !== e.type) && s(e.type), !Array.isArray(i) && Array.isArray(e) ? i = [] : typeof i != "object" && (e.constructor || Object) === Object && (i = {}); } if (typeof i == "function") return console.error("Serialization: Cannot deserialize into a function", i, e), i; if (!r) { const s = d.GetSerializer(e); if (s && s !== A) return s.deserialize(e, i, n); } if (!e || i === void 0 || i === null || typeof i != "object") return e; if (!r && typeof (i == null ? void 0 : i.fromJSON) == "function") return i.fromJSON(e, n, !0), i; let o = i.constructor ?? Object; if (o === Object) return A.deserialize(e, i, n); for (; o && o !== Object; ) { const s = d.TypeMap.get(o) ?? []; for (const [a, c] of s) { const u = i[c], l = d.Deserialize(e[a], u, n, !1); l !== u && D(i, c, l, !0); } o = Object.getPrototypeOf(o); } return i; } }; d.TypeMap = /* @__PURE__ */ new Map(), d.SerializableClasses = /* @__PURE__ */ new Map(), d.Serializers = [ { // arrays priority: 0, isType: (e) => Array.isArray(e), serialize: (e, i) => e.map((n) => d.Serialize(n, i, !1)), deserialize: (e, i, n) => { const r = e.length; Array.isArray(i) || (i = []); for (let o = 0; o < r; o++) { const s = e[o], a = i.length > o ? d.Deserialize(s, i[o], n, !1) : d.Deserialize(s, void 0, n, !1); i.length <= o ? i.push(a) : i[o] = a; } return i; } }, { // primitives priority: 0, isType: (e) => !e || typeof e != "object", serialize: (e) => { if (e && typeof e == "number") { if (e === 1 / 0) return "Infinity"; if (e === -1 / 0) return "-Infinity"; if (isNaN(e)) return "NaN"; } return e; }, deserialize: (e, i) => { if (typeof i == "number") { if (e === "Infinity") return 1 / 0; if (e === "-Infinity") return -1 / 0; if (e === "NaN") return NaN; if (typeof e == "number" || !e) return e; } return e; } }, A ]; let m = d; const k = class k { static callFunction(e, i, n = []) { if (!i) return e(...n); if (e.name && i[e.name] === e) return e.call(i, ...n); k.methodMap.has(i) || k.methodMap.set(i, /* @__PURE__ */ new WeakMap()); const r = k.methodMap.get(i); if (!r.has(e)) { let o = i; for (; o; ) { const s = Object.values(Object.getOwnPropertyDescriptors(o)); for (let a of s) if (a.value === e) return r.set(e, !0), e.call(i, ...n); o = Object.getPrototypeOf(o); } r.set(e, !1); } return r.get(e) ? e.call(i, ...n) : e(...n); } }; k.methodMap = /* @__PURE__ */ new WeakMap(); let U = k; function I(t, e = "param") { if (!t) throw new Error("onChange: fnKey is undefined, make sure the function exists or provide a string"); return (i, n, r) => { const o = { get() { return this[`_oc_${n}`]; }, set(s) { var u; const a = this[`_oc_${n}`]; if (a === s) return; this[`_oc_${n}`] = s; const c = e === "param" ? [n, s, a, this] : e === "object" ? [{ key: n, value: s, oldValue: a, target: this }] : []; typeof t == "string" ? (u = this[t]) == null || u.call(this, ...c) : typeof t == "function" && U.callFunction(t, this, c); } }; if (r) return L(r, "value") && delete r.value, L(r, "writable") && delete r.writable, L(r, "initializer") && delete r.initializer, Object.assign(r, o); Object.defineProperty(i, n, o); }; } function Ke(t, e = "void") { if (!t) throw new Error("onChange: fnKey is undefined, make sure the function exists or provide a string"); return I(t, e); } function Je(t, e = "object") { if (!t) throw new Error("onChange: fnKey is undefined, make sure the function exists or provide a string"); return I(t, e); } function Ge(t) { return I((e, i, n, r) => { if (!r.dispatchEvent) throw new Error("onChangeDispatchEvent: target does not have dispatchEvent"); r.dispatchEvent({ type: t || `${e}-changed`, detail: { key: e, value: i, oldValue: n } }); }, "param"); } function Xe(t) { return (e, i) => { const n = e.constructor; if (n === Object) throw new Error("All properties in an object are serialized by default"); m.TypeMap.has(n) || m.TypeMap.set(n, []), m.TypeMap.get(n).push([t || i, i]); }; } function Ze(t) { return (e) => (e = class extends e { constructor() { super(...arguments), this.serializableClassId = t; } // static DataInConstructor = false // if constructor is equivalent to fromJSON, see LUTCubeTextureWrapper. }, m.SerializableClasses.set(t, e), e); } async function Qe(t, e, i, n = 12) { const r = typeof e == "string" ? new TextEncoder().encode(e) : e, o = await crypto.subtle.digest("SHA-256", r), s = crypto.getRandomValues(new Uint8Array(n)), a = Array.from(s).map((x) => String.fromCharCode(x)).join(""), c = { name: "AES-GCM", iv: s }, u = await crypto.subtle.importKey("raw", o, c, !1, ["encrypt"]), l = typeof t == "string" ? new TextEncoder().encode(t) : t, h = await crypto.subtle.encrypt(c, u, l), v = new Uint8Array(h), p = Array.from(v), b = p.map((x) => String.fromCharCode(x)).join(""), E = i ? typeof i == "string" ? i : new TextDecoder().decode(i) : "", C = i ? typeof i == "string" ? new TextEncoder().encode(i) : Array.from(i) : []; return typeof t == "string" ? E + a + b : new Uint8Array([...C, ...s, ...p]); } async function je(t, e, i = 12) { const n = typeof e == "string" ? new TextEncoder().encode(e) : e, r = await crypto.subtle.digest("SHA-256", n), o = t.slice(0, i), a = { name: "AES-GCM", iv: typeof o == "string" ? new Uint8Array(Array.from(o).map((h) => h.charCodeAt(0))) : o }, c = await crypto.subtle.importKey("raw", r, a, !1, ["decrypt"]), u = t.slice(i), l = typeof u == "string" ? new Uint8Array(Array.from(u).map((h) => h.charCodeAt(0))) : u; try { const h = await crypto.subtle.decrypt(a, c, l); return typeof t == "string" ? new TextDecoder().decode(h) : new Uint8Array(h); } catch { throw new Error("Decrypt failed"); } } async function et() { return "showOpenFilePicker" in window ? window.showOpenFilePicker().then((t) => t[0]) : window.chooseFileSystemEntries(); } function tt() { if ("showSaveFilePicker" in window) { const e = { types: [{ description: "Text file", accept: { "text/plain": [".txt"] } }] }; return window.showSaveFilePicker(e); } const t = { type: "save-file", accepts: [{ description: "Text file", extensions: ["txt"], mimeTypes: ["text/plain"] }] }; return window.chooseFileSystemEntries(t); } function it(t) { return t.text ? t.text() : ee(t); } function ee(t) { return new Promise((e) => { const i = new FileReader(); i.addEventListener("loadend", (n) => { const r = (n.srcElement || n.target).result; e(r); }), i.readAsText(t); }); } async function nt(t, e) { if (t.createWriter) { const n = await t.createWriter(); await n.write(0, e), await n.close(); return; } const i = await t.createWritable(); await i.write(e), await i.close(); } async function rt(t, e) { const i = {}; return e && (i.writable = !0, i.mode = "readwrite"), await t.queryPermission(i) === "granted" || await t.requestPermission(i) === "granted"; } function R(t, e = 8192, i = !1) { var c; const n = t.width || t.videoWidth, r = t.height || t.videoHeight; if (!n || !r) throw new Error("Invalid bitmap"); const o = document.createElement("canvas"); o.width = Math.min(e, n), o.height = Math.floor(1 + o.width * r / n); const s = t instanceof ImageBitmap, a = s && i && Math.abs(o.width - n) < 0.5 ? o.getContext("bitmaprenderer") : void 0; return a ? a.transferFromImageBitmap(t) : (c = o.getContext("2d")) == null || c.drawImage(t, 0, 0, o.width, o.height), s && i && t.close(), o; } function ot(t, e = 8192, i = !1, n = "image/png") { if (!(t.width || t.videoWidth) || !(t.height || t.videoHeight)) return ""; const r = R(t, e, !1), o = r.toDataURL(n); return r.remove(), i && t instanceof ImageBitmap && t.close(), o; } async function st(t, e = 8192, i = !1, n = "image/png") { if (!(t.width || t.videoWidth) || !(t.height || t.videoHeight)) return Promise.reject("Invalid bitmap"); const r = R(t, e, !1); return new Promise((o, s) => { r.toBlob((a) => { a ? o(a) : s("Could not get blob"), r.remove(), i && t instanceof ImageBitmap && t.close(); }, n); }); } async function at(t) { return new Promise((e, i) => { const n = new Image(); n.addEventListener("load", () => { const r = document.createElement("canvas"); r.width = n.width, r.height = n.height; const o = r.getContext("2d"); if (!o) { i(new Error("Could not get 2d context")); return; } o.drawImage(n, 0, 0, r.width, r.height); const s = o.getImageData(0, 0, r.width, r.height); e(s), r.remove(), n.remove(); }, !1), n.addEventListener("error", (r) => { n.remove(), i(r); }, !1), n.src = t; }); } function te(t, { backgroundColor: e = "", scale: i = 1, width: n = 512, height: r = 512 }) { const o = document.createElement("canvas"), s = o.getContext("2d"), a = i, c = n, u = r; return o.width = c * a, o.height = u * a, o.style.width = `${c}`, o.style.height = `${u}`, (e == null ? void 0 : e.length) > 0 && (s.fillStyle = e, s.fillRect(0, 0, o.width, o.height)), s.drawImage(t, 0, 0, o.width, o.height), o; } function ct(t) { const e = document.createElement("canvas"); return e.width = t.width, e.height = t.height, e.getContext("2d").putImageData(t, 0, 0), e; } function lt() { const t = document.createElement("canvas"); return t.getContext && t.getContext("2d") ? t.toDataURL("image/webp").startsWith("data:image/webp") : !1; } function ut(t) { const e = document.createElement("canvas"); e.width = t.width || t.videoWidth || 1, e.height = t.height || t.videoHeight || 1; const i = e.getContext("2d"); if (!i) throw new Error("Unable to get 2d context"); return i.translate(0, t.height || t.videoHeight || 1), i.scale(1, -1), i.drawImage(t, 0, 0), e; } function dt(t) { return new Promise((e, i) => { const n = new Image(), r = URL.createObjectURL(t); n.onload = () => { URL.revokeObjectURL(r), e(n); }, n.onerror = (o) => { URL.revokeObjectURL(r), i(o); }, n.src = r; }); } const ft = (t) => `data:image/svg+xml,%3Csvg width='16' height='16' viewBox='0 0 16 16' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Crect width='16' height='16' fill='%23${t}'/%3E%3C/svg%3E%0A`, ht = (t) => `data:image/svg+xml,%3Csvg width='16' height='16' viewBox='0 0 16 16' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Ccircle cx='8' cy='8' r='7' fill='%23${t}'/%3E%3C/svg%3E%0A`, pt = (t) => `data:image/svg+xml,%3Csvg viewBox='0 0 80 14' xmlns='http://www.w3.org/2000/svg'%3E%3Ctext style='font: 8px "Roboto Mono", "Source Code Pro", Menlo, Courier, monospace; fill: white;' x='9' y='9'%3E${t}%3C/text%3E%3C/svg%3E%0A`, F = async (t, e) => { const i = await N(t); return te(i, e); }, ie = async (t, e) => await F(t, e).then((i) => i.toDataURL("image/png")), ne = async (t) => X(await (await fetch(t)).blob()); async function mt(t, e = ne) { const i = t.match(/(((ftp|https?):\/\/)[\-\w@:%_\+.~#?,&\/\/=]+)/g); if (i) for (const n of i) { const r = await e(n); t = t.replace(n, r); } return t; } function q(t, e, { width: i, height: n }, r = !0) { const o = ` <svg viewBox="0 0 ${i} ${n}" xmlns="http://www.w3.org/2000/svg"> <style> ${e} </style> <foreignObject x="0" y="0" width="100%" height="100%"> <div xmlns="http://www.w3.org/1999/xhtml" style="height: 100%; width: 100%; position: absolute: top:0; left:0"> ${t} </div> </foreignObject> </svg> `; return r ? J(o) : o; } async function gt(t, e, i) { const n = q(t, e, i); return await F(n, i); } async function wt(t, e, i) { const n = q(t, e, i); return await ie(n, i); } function yt(t, e) { return Math.abs(t) > Math.abs(e) ? t : e; } function vt(t, e, i) { const n = i ? 1 : 0, r = ~(1 << e); return t & r | n << e; } function bt(t, e) { const i = ~(1 << e); return t & i; } function xt() { const t = (n, r) => n.toString(16).padStart(r, "0"), e = crypto.getRandomValues(new Uint8Array(16)); e[6] = e[6] & 15 | 64, e[8] = e[8] & 63 | 128; const i = new DataView(e.buffer); return `${t(i.getUint32(0), 8)}-${t(i.getUint16(4), 4)}-${t(i.getUint16(6), 4)}-${t(i.getUint16(8), 4)}-${t(i.getUint32(10), 8)}${t(i.getUint16(14), 4)}`; } function kt(t, e = null) { var n; return (n = window == null ? void 0 : window.location) != null && n.href ? new URL(window.location.href).searchParams.get(t) ?? e : e; } function Et(t, e, i = !1) { var r; if (!((r = window == null ? void 0 : window.location) != null && r.href)) return; const n = new URLSearchParams(window.location.search); e == null ? n.has(t) && n.delete(t) : n.set(t, e), i ? window.location.search = n.toString() : window.history.replaceState({}, "", "?" + n.toString()); } function Ct(t, e = "/") { return t.join(e); } function _t(t, e) { const i = (e ? `var Module = { locateFile: function(s) { return "${e}"; } }; ` : "") + `importScripts( "${t}" );`; return URL.createObjectURL(new Blob([i], { type: "text/javascript" })); } const St = { alert: async (t) => window.alert(t), prompt: async (t, e, i) => window.prompt(t, e), confirm: async (t) => window.confirm(t), confirmSync: (t) => window.confirm(t) }, re = '.dialog-container{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);z-index:1000;border-radius:10px;padding:20px;max-width:calc(100% - 32px);width:calc(100% - 32px);color:#0a0a0a;background-color:#fff;border:1px solid oklch(.922 0 0);box-shadow:#0000 0 0,#0000 0 0,#0000 0 0,#0000 0 0,#0000001a 0 10px 15px -3px,#0000001a 0 4px 6px -4px;display:flex;gap:1rem;flex-direction:column;box-sizing:border-box;font-family:Inter,-apple-system,"system-ui",Segoe UI,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";transition:max-width .5s,width .5s,height .5s}.dialog-content{display:flex;flex-direction:column;gap:.5rem;text-align:center}.dialog-title{font-size:1.125rem;font-weight:600;line-height:1.5;color:#0a0a0a}.dialog-message{color:#737373;font-size:.875rem;line-height:1.42}.dialog-footer{display:flex;gap:10px;flex-direction:column-reverse}@media (width >= 40rem){.dialog-content{text-align:left}.dialog-container{max-width:512px;width:512px}.dialog-footer{flex-direction:row;justify-content:flex-end}}.dialog-button,.dialog-input{height:2.25rem;box-sizing:border-box}.dialog-input{width:100%;padding:.25rem .75rem;font-size:1rem;border:1px solid oklch(.922 0 0);border-radius:.5rem;background:transparent;color:#0a0a0a;outline:none;transition:outline-width .2s}.dialog-button{padding:.5rem 1rem;box-shadow:#0000 0 0,#0000 0 0,#0000 0 0,#0000000d 0 1px 2px;border-radius:.5rem;border:1px solid oklch(.922 0 0);cursor:pointer;font-size:.875rem;background-color:#fff;color:#0a0a0a;transition:background-color .2s ease,color .2s ease,outline-width .2s ease}.dialog-button:focus,.dialog-input:focus{outline:3px solid #6d7a8c66}.dialog-button:hover{background-color:#f8f8f8}.dialog-ok{background-color:#0a0a0a;color:#fff}.dialog-ok:hover{background-color:#222}.dialog-link{max-width:100%;display:inline-block;vertical-align:bottom;text-decoration:underline;color:var(#2563eb);overflow:hidden}.dialog-link-text{display:inline-block;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;vertical-align:bottom}'; let S = null; function oe(t) { const e = /((https?:\/\/|www\.)[^\s<]+)/g; return t.replace(e, (i) => { let n = i; return n.startsWith("http") || (n = "https://" + n), `<a href="${n}" target="_blank" rel="noopener noreferrer" class="dialog-link"><span class="dialog-link-text">${g(i)}</span></a>`; }); } function se(t) { const e = g(t); return oe(e).replace(/\n/g, "<br>"); } function P(t) { return ` ${t.title ? `<div class="dialog-title">${g(t.title)}</div>` : ""} <div class="dialog-message">${se(t.message)}</div> `; } const ae = (t) => ` <div class="dialog-content"> ${P(t)} </div> <div class="dialog-footer"> ${t.ok && `<button class="dialog-button dialog-ok">${g(t.ok)}</button>` || ""} </div> `, ce = (t) => ` <div class="dialog-content"> ${P(t)} </div> <div class="dialog-footer"> ${t.cancel && `<button class="dialog-button dialog-cancel">${g(t.cancel)}</button>` || ""} ${t.ok && `<button class="dialog-button dialog-ok">${g(t.ok)}</button>` || ""} </div> `, le = (t) => ` <div class="dialog-content"> ${P(t)} <input class="dialog-input" type="text" value="${t.defaultValue ?? ""}" style="margin-top:0.5rem;"/> </div> <div class="dialog-footer"> ${t.cancel && `<button class="dialog-button dialog-cancel">${g(t.cancel)}</button>` || ""} ${t.ok && `<button class="dialog-button dialog-ok">${g(t.ok)}</button>` || ""} </div> `; function ue() { S || (S = document.createElement("style"), S.textContent = re, document.head.appendChild(S)); } function z(t, { message: e, ...i }) { ue(); const n = document.createElement("div"), r = e == null ? void 0 : e.split(":")[0]; return r && e && (e = e.replace(r + ":", "").trim()), n.innerHTML = t({ ...i, message: e, title: r }), n.classList.add("dialog-container"), document.body.appendChild(n), n; } const Lt = { alert: async (t) => { const e = z(ae, { message: t || "Alert", ok: "Okay" }); return new Promise((i) => { const n = e.querySelector(".dialog-ok"), r = (s) => { (s.key === "Enter" || s.key === "Escape") && (s.preventDefault(), n == null || n.click()); }, o = () => { window.removeEventListener("keydown", r), document.body.removeChild(e); }; window.addEventListener("keydown", r), n == null || n.addEventListener("click", () => { o(), i(); }), n == null || n.focus(); }); }, prompt: async (t, e, i = !0) => { const n = z(le, { message: t || "Enter some text", ok: "OK", cancel: i ? "Cancel" : void 0, defaultValue: e }); return new Promise((r) => { const o = n.querySelector(".dialog-ok"), s = n.querySelector(".dialog-cancel"), a = n.querySelector(".dialog-input"); a.addEventListener("keydown", (l) => { l.key === "Enter" && (l.preventDefault(), o == null || o.click()); }); const c = (l) => { l.key === "Escape" && s && (l.preventDefault(), s == null || s.click()); }, u = () => { window.removeEventListener("keydown", c), document.body.removeChild(n); }; window.addEventListener("keydown", c), o == null || o.addEventListener("click", () => { const l = a.value; u(), r(l); }), s == null || s.addEventListener("click", () => { u(), r(null); }), a == null || a.focus(), a == null || a.select(); }); }, confirm: async (t) => { const e = z(ce, { message: t || "Are you sure?", ok: "Yes", cancel: "No" }); return new Promise((i) => { const n = e.querySelector(".dialog-ok"), r = e.querySelector(".dialog-cancel"), o = (a) => { a.key === "Escape" && r && (a.preventDefault(), r.click()); }, s = () => { window.removeEventListener("keydown", o), document.body.removeChild(e); }; window.addEventListener("keydown", o), n == null || n.addEventListener("click", () => { s(), i(!0); }), r == null || r.addEventListener("click", () => { s(), i(!1); }), r == null || r.focus(); }); }, confirmSync: (t) => window.confirm(t) }; function y(t) { return t === null || typeof t != "object" ? t : Array.isArray(t) ? t.map(y) : !t._ui_isPrimitive && typeof t.clone == "function" && t._ui_primitiveClone !== !1 ? t.clone() : t; } function T(t, e) { return t === null || typeof t != "object" ? t === e : Array.isArray(t) ? Array.isArray(e) && t.length === e.length && t.every((i, n) => T(i, e[n])) : !t._ui_isPrimitive && typeof t.equals == "function" && t._ui_primitiveEquals !== !1 ? !!t.equals(e) : t === e; } function O(t, e) { if (e === null || typeof e != "object") return e; if (Array.isArray(e)) if (t && Array.isArray(t)) { if (t.length < e.length) { for (let i = 0; i < t.length; i++) t[i] = O(t[i], e[i]); for (let i = t.length; i < e.length; i++) t.push(y(e[i])); } else { for (let i = 0; i < e.length; i++) t[i] = O(t[i], e[i]); t.length = e.length; } return t; } else return y(e); else return !e._ui_isPrimitive && typeof e.copy == "function" && e._ui_primitiveCopy !== !1 ? t && typeof t == "object" && !Array.isArray(t) && !t._ui_isPrimitive && typeof t.copy == "function" && t._ui_primitiveCopy !== !1 ? (t.copy(e), t) : y(e) : e; } function de(t, e, i, n = 2e3) { if (!t || !t.enabled) return; const r = e; if (r.type !== i) return t.record(e); const o = t.peek(); let s = !!o && o.type === i && o.uid === r.uid; if (s) { const a = o; !a.final && r.time - a.time < n ? (r.lastVal = a.lastVal, r.val = y(r.val), t.replaceLast(r)) : s = !1; } s || T(r.lastVal, r.val) || (r.val = y(r.val), t.record(r)); } function At(t, e, i, n, r, o, s = !0, a = 2e3, c = !1, u) { const [l, h] = e, v = n.lastValue ?? (l == null ? void 0 : l[h]); let p = !1; const b = n.last ?? !0, E = T(v, i), C = y(v); E ? p = !b : l ? O(v, i) !== v ? p = !D(l, h, i, !0, !0) : p = !1 : p = !0; const x = !p && (b || !E); return s && x && t && de(t, { type: o, lastVal: C, val: i, final: b, props: n, time: Date.now(), uid: r, binding: c ? e : void 0, // save binding only if required, otherwise it could cause memory leaks onUndoRedo: u }, o, a), { last: b, value: i, lastValue: C, undoable: x }; } export { M as Damper, U as FnCaller, ge as JSUndoManager, $e as LinearToSRGB, me as PointerDragHelper, Me as SRGBToLinear, m as Serialization, H as SimpleEventDispatcher, B as TYPED_ARRAYS, yt as absMax, je as aesGcmDecrypt, Qe as aesGcmEncrypt, xe as arrayBufferToBase64, ke as base64ToArrayBuffer, X as blobToDataURL, dt as blobToImage, ut as canvasFlipY, bt as clearBit, y as clonePrimitive, V as cloneScriptTag, Re as colorToDataUrl, O as copyPrimitive, qe as copyProps, we as createCanvasElement, ye as createDiv, N as createImage, ve as createScriptFromURL, W as createStyles, K as css, Ve as deepAccessObject, G as downloadBlob, Ie as downloadFile, mt as embedUrlRefs, T as equalsPrimitive, g as escapeHtml, Y as escapeRegExp, j as findLastIndex, et as getFileHandle, Le as getFilenameFromPath, Be as getKeyByValue, tt as getNewFileHandle, Fe as getOrCall, Z as getPropertyDescriptor, Ee as getTypedArray, kt as getUrlQueryParam, Ue as glsl, Oe as html, Lt as htmlDialogWrapper, gt as htmlToCanvas, wt as htmlToPng, q as htmlToSvg, ot as imageBitmapToBase64, st as imageBitmapToBlob, R as imageBitmapToCanvas, ct as imageDataToCanvas, te as imageToCanvas, at as imageUrlToImageData, He as includesAll, Q as isPropertyWritable, lt as isWebpExportSupported, ze as longestCommonPrefix, ft as makeColorSvg, ht as makeColorSvgCircle, pt as makeTextSvg, Te as mobileAndTabletCheck, _ as now, L as objectHasOwn, Ye as objectMap, $ as objectMap2, I as onChange, Ke as onChange2, Je as onChange3, Ge as onChangeDispatchEvent, Se as parseFileExtension, Ct as pathJoin, De as prettyScrollbar, it as readFile, de as recordUndoCommand, _t as remoteWorkerURL, f as replaceAll, Ae as safeReplaceString, D as safeSetProperty, Ze as serializable, Xe as serialize, be as setInnerHTMLWithScripts, Et as setUrlQueryParam, At as setValueUndoCommand, F as svgToCanvas, ie as svgToPng, J as svgUrl, pe as timeout, _e as toCamelCase, Ce as toTitleCase, vt as updateBit, Pe as uploadFile, xt as uuidV4, rt as verifyPermission, St as windowDialogWrapper, Ne as wrapThisFunction, We as wrapThisFunction2, nt as writeFile }; //# sourceMappingURL=bundle.esm.js.map