UNPKG

vlens

Version:

Data Centric Routing & Rendering Mini-Framework

168 lines (140 loc) 4.28 kB
// direction: 1 one step down, -1 one step up export function reorderListItem<T>(list: T[], index: number, direction: number) { let otherIndex = index + direction; let item = list[index]; let otherItem = list[otherIndex]; list[index] = otherItem; list[otherIndex] = item; } export function removeListItem<T>(list: T[], item: T) { let idx = list.indexOf(item) if (idx !== -1) { list.splice(idx, 1) } } export function toggleListItem<T>(list: T[], item: T) { let idx = list.indexOf(item) if (idx !== -1) { list.splice(idx, 1) } else { list.push(item) } } const CURSOR_DIV_ID = 'global-cursor' export function setGlobalCursor(cursorStyle: string) { // create a transparent div with a specific id // if div already exists, remove it and recrate it. // I know it's dumb but at least it's more reliable { let existing = document.getElementById(CURSOR_DIV_ID); if (existing) { existing.remove(); } } let div = document.createElement('div'); div.id = CURSOR_DIV_ID; div.style.position = 'fixed'; div.style.top = '0'; div.style.left = '0'; div.style.right = '0'; div.style.bottom = '0'; div.style.background = 'transparent'; div.style.zIndex = '10000000000'; div.style.cursor = cursorStyle; document.body.appendChild(div); } export function unsetGlobalCursor() { let existing = document.getElementById(CURSOR_DIV_ID); if (existing) { existing.remove(); } } export interface ArrayMove { src: number; dest: number; } function arraySwap<T>(array: T[], swap: ArrayMove) { let src_item = array[swap.src]; let dest_item = array[swap.dest]; array[swap.src] = dest_item; array[swap.dest] = src_item; } // move item in array without resizing array // sounds dumb but prevents flicker when array is a list of child nodes export function arrayBubbleMove<T>(array: T[], swap: ArrayMove) { if (swap.src < swap.dest) { for (let i = swap.src; i < swap.dest - 1; i++) { arraySwap(array, { src: i, dest: i + 1 }) } } else { for (let i = swap.src; i > swap.dest; i--) { arraySwap(array, { src: i, dest: i - 1 }) } } } export function removePrefix(s: string, prefix: string): string { if (s.startsWith(prefix)) { return s.substring(prefix.length); } else { return s; } } export function intUrlArg(route: string, prefix: string, fallback: number = 0): number { let arg = removePrefix(route, prefix) return parseIntOrFallback(arg, fallback); } export function numberOrFallback(numValue: number, fallback: number = 0): number { if (Number.isSafeInteger(numValue)) { return numValue } else { return fallback } } export function parseIntOrFallback(s: string | null, fallback: number = 0): number { if (s === null) { return fallback } return numberOrFallback(parseInt(s), fallback) } export function urlParams(path: string): URLSearchParams { let idx = path.indexOf('?') if (idx == 0) { return new URLSearchParams() } else { return new URLSearchParams(path.substring(idx)) } } export function intParam(p: URLSearchParams, name: string, fallback: number = 0): number { let strValue = p.get(name) return parseIntOrFallback(p.get(name), fallback) } export function measure(repeat: number, fn: Function) { let t1 = performance.now() for(let i = 0; i < repeat; i++) { fn() } let t2 = performance.now() let dur = t2 - t1 return dur.toFixed(2) + "ms" } export function timeout(ms: number): Promise<void> { if (ms <= 0) { return Promise.resolve() } return new Promise(r => setTimeout(r, ms)) } export function timeoutUntil(time: number) { return timeout(time - Date.now()) } export async function minimumWait<T>(ms: number, p: Promise<T>): Promise<T> { let start = Date.now() let result = await p; await timeoutUntil(start + ms) return result } export function assert(t: unknown, msg: string) { if (t === null) { console.error("assertion error:", msg) throw new Error("Assertion Error") } }