export function getResolver(timeout = 5000) { const resolver = {} resolver.id = generateId(8) resolver.completed = false resolver.resolved = false resolver.rejected = false resolver.promise = new Promise((resolve, reject) => { resolver.reject = () => { resolver.completed = true resolver.rejected = true reject() } resolver.resolve = (data) => { resolver.completed = true resolver.resolved = true resolve(data) } }) resolver.timeout = setTimeout(() => { if (!resolver.completed) { resolver.reject() } }, timeout) return resolver } const DEBOUNCE_FN_TO_PROMISE = new WeakMap() export function debounce(fn, ms = 64) { if (!DEBOUNCE_FN_TO_PROMISE.get(fn)) { DEBOUNCE_FN_TO_PROMISE.set( fn, wait(ms).then(() => { DEBOUNCE_FN_TO_PROMISE.delete(fn) fn() }), ) } return DEBOUNCE_FN_TO_PROMISE.get(fn) } export function wait(ms = 16) { if (ms === 16) { return new Promise((resolve) => { requestAnimationFrame(() => { resolve() }) }) } return new Promise((resolve) => { setTimeout(() => { resolve() }, ms) }) } function dec2hex(dec) { return dec.toString(16).padStart(2, '0') } export function generateId(length) { const arr = new Uint8Array(length / 2) crypto.getRandomValues(arr) return Array.from(arr, dec2hex).join('') } export function getObjectValue(obj, objKey, def) { if (!obj || !objKey) return def const keys = objKey.split('.') const key = keys.shift() const found = obj[key] if (keys.length) { return getObjectValue(found, keys.join('.'), def) } return found } export function setObjectValue(obj, objKey, value, createMissingObjects = true) { if (!obj || !objKey) return obj const keys = objKey.split('.') const key = keys.shift() if (obj[key] === undefined) { if (!createMissingObjects) { return } obj[key] = {} } if (!keys.length) { obj[key] = value } else { if (typeof obj[key] != 'object') { obj[key] = {} } setObjectValue(obj[key], keys.join('.'), value, createMissingObjects) } return obj } export function moveArrayItem(arr, itemOrFrom, to) { const from = typeof itemOrFrom === 'number' ? itemOrFrom : arr.indexOf(itemOrFrom) arr.splice(to, 0, arr.splice(from, 1)[0]) } export function removeArrayItem(arr, itemOrIndex) { const index = typeof itemOrIndex === 'number' ? itemOrIndex : arr.indexOf(itemOrIndex) arr.splice(index, 1) } export function injectCss(href) { if (document.querySelector(`link[href^="${href}"]`)) { return Promise.resolve() } return new Promise((resolve) => { const link = document.createElement('link') link.setAttribute('rel', 'stylesheet') link.setAttribute('type', 'text/css') const timeout = setTimeout(resolve, 1000) link.addEventListener('load', (e) => { clearInterval(timeout) resolve() }) link.href = href document.head.appendChild(link) }) }