diff options
Diffstat (limited to 'src/Utils.ts')
-rw-r--r-- | src/Utils.ts | 348 |
1 files changed, 203 insertions, 145 deletions
diff --git a/src/Utils.ts b/src/Utils.ts index 6699aa133..528a429d0 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -1,5 +1,5 @@ import v4 = require('uuid/v4'); -import v5 = require("uuid/v5"); +import v5 = require('uuid/v5'); import { ColorState } from 'react-color'; import { Socket } from 'socket.io'; import { Colors } from './client/views/global/globalEnums'; @@ -16,7 +16,7 @@ export namespace Utils { return new Promise((resolve, reject) => { temporaryFileReader.onerror = () => { temporaryFileReader.abort(); - reject(new DOMException("Problem parsing input file.")); + reject(new DOMException('Problem parsing input file.')); }; temporaryFileReader.onload = () => { @@ -34,7 +34,7 @@ export namespace Utils { return v5(seed, v5.URL); } - export function GetScreenTransform(ele?: HTMLElement): { scale: number, translateX: number, translateY: number } { + export function GetScreenTransform(ele?: HTMLElement): { scale: number; translateX: number; translateY: number } { if (!ele) { return { scale: 1, translateX: 1, translateY: 1 }; } @@ -50,12 +50,12 @@ export namespace Utils { ['log', 'warn'].forEach(function (method) { const old = (console as any)[method]; (console as any)[method] = function () { - let stack = new Error("").stack?.split(/\n/); + let stack = new Error('').stack?.split(/\n/); // Chrome includes a single "Error" line, FF doesn't. if (stack && stack[0].indexOf('Error') === 0) { stack = stack.slice(1); } - const message = (stack?.[1] || "Stack undefined!").trim(); + const message = (stack?.[1] || 'Stack undefined!').trim(); const args = ([] as any[]).slice.apply(arguments).concat([message]); return old.apply(console, args); }; @@ -79,7 +79,7 @@ export namespace Utils { } export function CorsProxy(url: string): string { - return prepend("/corsProxy/") + encodeURIComponent(url); + return prepend('/corsProxy/') + encodeURIComponent(url); } export function CopyText(text: string) { @@ -88,14 +88,13 @@ export namespace Utils { export function decimalToHexString(number: number) { if (number < 0) { - number = 0xFFFFFFFF + number + 1; + number = 0xffffffff + number + 1; } - return (number < 16 ? "0" : "") + number.toString(16).toUpperCase(); + return (number < 16 ? '0' : '') + number.toString(16).toUpperCase(); } export function colorString(color: ColorState) { - return color.hex.startsWith("#") ? - color.hex + (color.rgb.a ? decimalToHexString(Math.round(color.rgb.a * 255)) : "ff") : color.hex; + return color.hex.startsWith('#') ? color.hex + (color.rgb.a ? decimalToHexString(Math.round(color.rgb.a * 255)) : 'ff') : color.hex; } export function fromRGBAstr(rgba: string) { @@ -110,8 +109,8 @@ export namespace Utils { return { r: r, g: g, b: b, a: a }; } - const isTransparentFunctionHack = "isTransparent(__value__)"; - export const noRecursionHack = "__noRecursion"; + const isTransparentFunctionHack = 'isTransparent(__value__)'; + export const noRecursionHack = '__noRecursion'; export function IsRecursiveFilter(val: string) { return !val.includes(noRecursionHack); } @@ -120,18 +119,18 @@ export namespace Utils { } export function IsTransparentFilter() { // bcz: isTransparent(__value__) is a hack. it would be nice to have acual functions be parsed, but now Doc.matchFieldValue is hardwired to recognize just this one - return `backgroundColor:${isTransparentFunctionHack},${noRecursionHack}:check`;// bcz: hack. noRecursion should probably be either another ':' delimited field, or it should be a modifier to the comparision (eg., check, x, etc) field + return `backgroundColor:${isTransparentFunctionHack},${noRecursionHack}:check`; // bcz: hack. noRecursion should probably be either another ':' delimited field, or it should be a modifier to the comparision (eg., check, x, etc) field } export function IsOpaqueFilter() { // bcz: isTransparent(__value__) is a hack. it would be nice to have acual functions be parsed, but now Doc.matchFieldValue is hardwired to recognize just this one - return `backgroundColor:${isTransparentFunctionHack},${noRecursionHack}:x`;// bcz: hack. noRecursion should probably be either another ':' delimited field, or it should be a modifier to the comparision (eg., check, x, etc) field + return `backgroundColor:${isTransparentFunctionHack},${noRecursionHack}:x`; // bcz: hack. noRecursion should probably be either another ':' delimited field, or it should be a modifier to the comparision (eg., check, x, etc) field } export function PropUnsetFilter(prop: string) { return `${prop}:any,${noRecursionHack}:unset`; } - export function toRGBAstr(col: { r: number, g: number, b: number, a?: number }) { - return "rgba(" + col.r + "," + col.g + "," + col.b + (col.a !== undefined ? "," + col.a : "") + ")"; + export function toRGBAstr(col: { r: number; g: number; b: number; a?: number }) { + return 'rgba(' + col.r + ',' + col.g + ',' + col.b + (col.a !== undefined ? ',' + col.a : '') + ')'; } export function HSLtoRGB(h: number, s: number, l: number) { @@ -140,23 +139,35 @@ export namespace Utils { // l /= 100; const c = (1 - Math.abs(2 * l - 1)) * s, - x = c * (1 - Math.abs((h / 60) % 2 - 1)), + x = c * (1 - Math.abs(((h / 60) % 2) - 1)), m = l - c / 2; let r = 0, g = 0, b = 0; if (0 <= h && h < 60) { - r = c; g = x; b = 0; + r = c; + g = x; + b = 0; } else if (60 <= h && h < 120) { - r = x; g = c; b = 0; + r = x; + g = c; + b = 0; } else if (120 <= h && h < 180) { - r = 0; g = c; b = x; + r = 0; + g = c; + b = x; } else if (180 <= h && h < 240) { - r = 0; g = x; b = c; + r = 0; + g = x; + b = c; } else if (240 <= h && h < 300) { - r = x; g = 0; b = c; + r = x; + g = 0; + b = c; } else if (300 <= h && h < 360) { - r = c; g = 0; b = x; + r = c; + g = 0; + b = x; } r = Math.round((r + m) * 255); g = Math.round((g + m) * 255); @@ -221,18 +232,17 @@ export namespace Utils { export function distanceBetweenHorizontalLines(xs: number, xe: number, y: number, xs2: number, xe2: number, y2: number): [number, number[]] { if ((xs2 <= xs && xe2 >= xs) || (xs2 <= xe && xe2 >= xe) || (xs2 >= xs && xe2 <= xe)) return [Math.abs(y - y2), [Math.max(xs, xs2), y, Math.min(xe, xe2), y]]; if (xe2 <= xs) return [Math.sqrt((xe2 - xs) * (xe2 - xs) + (y2 - y) * (y2 - y)), [xs, y, xs, y]]; - //if (xs2 > xe) + //if (xs2 > xe) return [Math.sqrt((xs2 - xe) * (xs2 - xe) + (y2 - y) * (y2 - y)), [xe, y, xe, y]]; } export function distanceBetweenVerticalLines(x: number, ys: number, ye: number, x2: number, ys2: number, ye2: number): [number, number[]] { if ((ys2 <= ys && ye2 >= ys) || (ys2 <= ye && ye2 >= ye) || (ys2 >= ys && ye2 <= ye)) return [Math.abs(x - x2), [x, Math.max(ys, ys2), x, Math.min(ye, ye2)]]; if (ye2 <= ys) return [Math.sqrt((ye2 - ys) * (ye2 - ys) + (x2 - x) * (x2 - x)), [x, ys, x, ys]]; - //if (ys2 > ye) + //if (ys2 > ye) return [Math.sqrt((ys2 - ye) * (ys2 - ye) + (x2 - x) * (x2 - x)), [x, ye, x, ye]]; } function project(px: number, py: number, ax: number, ay: number, bx: number, by: number) { - if (ax === bx && ay === by) return { point: { x: ax, y: ay }, left: false, dot: 0, t: 0 }; const atob = { x: bx - ax, y: by - ay }; const atop = { x: px - ax, y: py - ay }; @@ -245,30 +255,41 @@ export namespace Utils { return { point: { x: ax + atob.x * t, - y: ay + atob.y * t + y: ay + atob.y * t, }, left: dot < 1, dot: dot, - t: t + t: t, }; } - export function closestPtBetweenRectangles(l: number, t: number, w: number, h: number, - l1: number, t1: number, w1: number, h1: number, - x: number, y: number) { + export function closestPtBetweenRectangles(l: number, t: number, w: number, h: number, l1: number, t1: number, w1: number, h1: number, x: number, y: number) { const r = l + w, b = t + h; const r1 = l1 + w1, b1 = t1 + h1; - const hsegs = [[l, r, t, l1, r1, t1], [l, r, b, l1, r1, t1], [l, r, t, l1, r1, b1], [l, r, b, l1, r1, b1]]; - const vsegs = [[l, t, b, l1, t1, b1], [r, t, b, l1, t1, b1], [l, t, b, r1, t1, b1], [r, t, b, r1, t1, b1]]; - const res = hsegs.reduce((closest, seg) => { - const res = distanceBetweenHorizontalLines(seg[0], seg[1], seg[2], seg[3], seg[4], seg[5]); - return (res[0] < closest[0]) ? res : closest; - }, [Number.MAX_VALUE, []] as [number, number[]]); + const hsegs = [ + [l, r, t, l1, r1, t1], + [l, r, b, l1, r1, t1], + [l, r, t, l1, r1, b1], + [l, r, b, l1, r1, b1], + ]; + const vsegs = [ + [l, t, b, l1, t1, b1], + [r, t, b, l1, t1, b1], + [l, t, b, r1, t1, b1], + [r, t, b, r1, t1, b1], + ]; + const res = hsegs.reduce( + (closest, seg) => { + const res = distanceBetweenHorizontalLines(seg[0], seg[1], seg[2], seg[3], seg[4], seg[5]); + return res[0] < closest[0] ? res : closest; + }, + [Number.MAX_VALUE, []] as [number, number[]] + ); const fres = vsegs.reduce((closest, seg) => { const res = distanceBetweenVerticalLines(seg[0], seg[1], seg[2], seg[3], seg[4], seg[5]); - return (res[0] < closest[0]) ? res : closest; + return res[0] < closest[0] ? res : closest; }, res); const near = project(x, y, fres[1][0], fres[1][1], fres[1][2], fres[1][3]); @@ -279,8 +300,7 @@ export namespace Utils { const r = l + w, b = t + h; - x = clamp(x, l, r), - y = clamp(y, t, b); + (x = clamp(x, l, r)), (y = clamp(y, t, b)); const dl = Math.abs(x - l), dr = Math.abs(x - r), @@ -289,18 +309,18 @@ export namespace Utils { const m = Math.min(dl, dr, dt, db); - return (m === dt) ? [x, t] : - (m === db) ? [x, b] : - (m === dl) ? [l, y] : [r, y]; + return m === dt ? [x, t] : m === db ? [x, b] : m === dl ? [l, y] : [r, y]; } export function GetClipboardText(): string { - const textArea = document.createElement("textarea"); + const textArea = document.createElement('textarea'); document.body.appendChild(textArea); textArea.focus(); textArea.select(); - try { document.execCommand('paste'); } catch (err) { } + try { + document.execCommand('paste'); + } catch (err) {} const val = textArea.value; document.body.removeChild(textArea); @@ -318,7 +338,7 @@ export namespace Utils { if (logFilter !== undefined && logFilter !== message.type) { return; } - const idString = (message.id || "").padStart(36, ' '); + const idString = (message.id || '').padStart(36, ' '); prefix = prefix.padEnd(16, ' '); console.log(`${prefix}: ${idString}, ${receiving ? 'receiving' : 'sending'} ${messageName} with data ${JSON.stringify(message)} `); } @@ -331,14 +351,14 @@ export namespace Utils { } export function Emit<T>(socket: Socket | SocketIOClient.Socket, message: Message<T>, args: T) { - log("Emit", message.Name, args, false); + log('Emit', message.Name, args, false); socket.emit(message.Message, args); } export function EmitCallback<T>(socket: Socket | SocketIOClient.Socket, message: Message<T>, args: T): Promise<any>; export function EmitCallback<T>(socket: Socket | SocketIOClient.Socket, message: Message<T>, args: T, fn: (args: any) => any): void; export function EmitCallback<T>(socket: Socket | SocketIOClient.Socket, message: Message<T>, args: T, fn?: (args: any) => any): void | Promise<any> { - log("Emit", message.Name, args, false); + log('Emit', message.Name, args, false); if (fn) { socket.emit(message.Message, args, loggingCallback('Receiving', fn, message.Name)); } else { @@ -358,30 +378,33 @@ export namespace Utils { } export type RoomHandler = (socket: Socket, room: string) => any; export type UsedSockets = Socket | SocketIOClient.Socket; - export type RoomMessage = "create or join" | "created" | "joined"; + export type RoomMessage = 'create or join' | 'created' | 'joined'; export function AddRoomHandler(socket: Socket, message: RoomMessage, handler: RoomHandler) { socket.on(message, room => handler(socket, room)); } } -export function OmitKeys(obj: any, keys: string[], pattern?: string, addKeyFunc?: (dup: any) => void): { omit: any, extract: any } { +export function OmitKeys(obj: any, keys: string[], pattern?: string, addKeyFunc?: (dup: any) => void): { omit: any; extract: any } { const omit: any = { ...obj }; const extract: any = {}; keys.forEach(key => { extract[key] = omit[key]; delete omit[key]; }); - pattern && Array.from(Object.keys(omit)).filter(key => key.match(pattern)).forEach(key => { - extract[key] = omit[key]; - delete omit[key]; - }); + pattern && + Array.from(Object.keys(omit)) + .filter(key => key.match(pattern)) + .forEach(key => { + extract[key] = omit[key]; + delete omit[key]; + }); addKeyFunc?.(omit); return { omit, extract }; } export function WithKeys(obj: any, keys: string[], addKeyFunc?: (dup: any) => void) { const dup: any = {}; - keys.forEach(key => dup[key] = obj[key]); + keys.forEach(key => (dup[key] = obj[key])); addKeyFunc && addKeyFunc(dup); return dup; } @@ -402,31 +425,39 @@ export function timenow() { export function incrementTitleCopy(title: string) { const numstr = title.match(/.*(\{([0-9]*)\})+/); - const copyNumStr = `{${1 + (numstr ? (+numstr[2]) : 0)}}`; - return (numstr ? title.replace(numstr[1], "") : title) + copyNumStr; + const copyNumStr = `{${1 + (numstr ? +numstr[2] : 0)}}`; + return (numstr ? title.replace(numstr[1], '') : title) + copyNumStr; } export function formatTime(time: number) { time = Math.round(time); const hours = Math.floor(time / 60 / 60); - const minutes = Math.floor(time / 60) - (hours * 60); + const minutes = Math.floor(time / 60) - hours * 60; const seconds = time % 60; - return (hours ? hours.toString() + ":" : "") + minutes.toString().padStart(2, '0') + ':' + seconds.toString().padStart(2, '0'); + return (hours ? hours.toString() + ':' : '') + minutes.toString().padStart(2, '0') + ':' + seconds.toString().padStart(2, '0'); } // x is furthest left, y is furthest top, r is furthest right, b is furthest bottom -export function aggregateBounds(boundsList: { x: number, y: number, width?: number, height?: number }[], xpad: number, ypad: number) { - const bounds = boundsList.map(b => ({ x: b.x, y: b.y, r: b.x + (b.width || 0), b: b.y + (b.height || 0) })).reduce((bounds, b) => ({ - x: Math.min(b.x, bounds.x), y: Math.min(b.y, bounds.y), - r: Math.max(b.r, bounds.r), b: Math.max(b.b, bounds.b) - }), { x: Number.MAX_VALUE, y: Number.MAX_VALUE, r: -Number.MAX_VALUE, b: -Number.MAX_VALUE }); +export function aggregateBounds(boundsList: { x: number; y: number; width?: number; height?: number }[], xpad: number, ypad: number) { + const bounds = boundsList + .map(b => ({ x: b.x, y: b.y, r: b.x + (b.width || 0), b: b.y + (b.height || 0) })) + .reduce( + (bounds, b) => ({ + x: Math.min(b.x, bounds.x), + y: Math.min(b.y, bounds.y), + r: Math.max(b.r, bounds.r), + b: Math.max(b.b, bounds.b), + }), + { x: Number.MAX_VALUE, y: Number.MAX_VALUE, r: -Number.MAX_VALUE, b: -Number.MAX_VALUE } + ); return { - x: bounds.x !== Number.MAX_VALUE ? bounds.x - xpad : bounds.x, y: bounds.y !== Number.MAX_VALUE ? bounds.y - ypad : bounds.y, - r: bounds.r !== -Number.MAX_VALUE ? bounds.r + xpad : bounds.r, b: bounds.b !== -Number.MAX_VALUE ? bounds.b + ypad : bounds.b + x: bounds.x !== Number.MAX_VALUE ? bounds.x - xpad : bounds.x, + y: bounds.y !== Number.MAX_VALUE ? bounds.y - ypad : bounds.y, + r: bounds.r !== -Number.MAX_VALUE ? bounds.r + xpad : bounds.r, + b: bounds.b !== -Number.MAX_VALUE ? bounds.b + ypad : bounds.b, }; } -export function intersectRect(r1: { left: number, top: number, width: number, height: number }, - r2: { left: number, top: number, width: number, height: number }) { +export function intersectRect(r1: { left: number; top: number; width: number; height: number }, r2: { left: number; top: number; width: number; height: number }) { return !(r2.left > r1.left + r1.width || r2.left + r2.width < r1.left || r2.top > r1.top + r1.height || r2.top + r2.height < r1.top); } @@ -434,36 +465,63 @@ export function percent2frac(percent: string) { return Number(percent.substr(0, percent.length - 1)) / 100; } -export function numberRange(num: number) { return num > 0 && num < 1000 ? Array.from(Array(num)).map((v, i) => i) : []; } +export function numberRange(num: number) { + return num > 0 && num < 1000 ? Array.from(Array(num)).map((v, i) => i) : []; +} -export function returnTransparent() { return "transparent"; } +export function returnTransparent() { + return 'transparent'; +} -export function returnTrue() { return true; } +export function returnTrue() { + return true; +} -export function returnFalse() { return false; } +export function returnFalse() { + return false; +} -export function returnAll() { return "all"; } +export function returnAll() { + return 'all'; +} -export function returnNone() { return "none"; } +export function returnNone() { + return 'none'; +} -export function returnVal(val1?: number, val2?: number) { return val1 !== undefined ? val1 : val2 !== undefined ? val2 : 0; } +export function returnVal(val1?: number, val2?: number) { + return val1 !== undefined ? val1 : val2 !== undefined ? val2 : 0; +} -export function returnOne() { return 1; } +export function returnOne() { + return 1; +} -export function returnZero() { return 0; } +export function returnZero() { + return 0; +} -export function returnEmptyString() { return ""; } +export function returnEmptyString() { + return ''; +} -export function returnEmptyFilter() { return [] as string[]; } +export function returnEmptyFilter() { + return [] as string[]; +} -export function returnEmptyDoclist() { return [] as any[]; } +export function returnEmptyDoclist() { + return [] as any[]; +} export let emptyPath = []; -export function emptyFunction() { return undefined; } - -export function unimplementedFunction() { throw new Error("This function is not implemented, but should be."); } +export function emptyFunction() { + return undefined; +} +export function unimplementedFunction() { + throw new Error('This function is not implemented, but should be.'); +} export type Without<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>; @@ -484,7 +542,6 @@ export function DeepCopy<K, V>(source: Map<K, V>, predicate?: Predicate<K, V>) { } export namespace JSONUtils { - export function tryParse(source: string) { let results: any; try { @@ -494,7 +551,6 @@ export namespace JSONUtils { } return results; } - } const easeInOutQuad = (currentTime: number, start: number, change: number, duration: number) => { @@ -509,52 +565,57 @@ const easeInOutQuad = (currentTime: number, start: number, change: number, durat }; export function smoothScroll(duration: number, element: HTMLElement | HTMLElement[], to: number) { - const elements = (element instanceof HTMLElement ? [element] : element); + const elements = element instanceof HTMLElement ? [element] : element; const starts = elements.map(element => element.scrollTop); const startDate = new Date().getTime(); const animateScroll = () => { const currentDate = new Date().getTime(); const currentTime = currentDate - startDate; - elements.map((element, i) => element.scrollTop = easeInOutQuad(currentTime, starts[i], to - starts[i], duration)); + elements.map((element, i) => (element.scrollTop = easeInOutQuad(currentTime, starts[i], to - starts[i], duration))); if (currentTime < duration) { requestAnimationFrame(animateScroll); } else { - elements.forEach(element => element.scrollTop = to); + elements.forEach(element => (element.scrollTop = to)); } }; animateScroll(); } export function smoothScrollHorizontal(duration: number, element: HTMLElement | HTMLElement[], to: number) { - const elements = (element instanceof HTMLElement ? [element] : element); + const elements = element instanceof HTMLElement ? [element] : element; const starts = elements.map(element => element.scrollLeft); const startDate = new Date().getTime(); const animateScroll = () => { const currentDate = new Date().getTime(); const currentTime = currentDate - startDate; - elements.map((element, i) => element.scrollLeft = easeInOutQuad(currentTime, starts[i], to - starts[i], duration)); + elements.map((element, i) => (element.scrollLeft = easeInOutQuad(currentTime, starts[i], to - starts[i], duration))); if (currentTime < duration) { requestAnimationFrame(animateScroll); } else { - elements.forEach(element => element.scrollLeft = to); + elements.forEach(element => (element.scrollLeft = to)); } }; animateScroll(); } -export function addStyleSheet(styleType: string = "text/css") { - const style = document.createElement("style"); +export function addStyleSheet(styleType: string = 'text/css') { + const style = document.createElement('style'); style.type = styleType; const sheets = document.head.appendChild(style); return (sheets as any).sheet; } -export function addStyleSheetRule(sheet: any, selector: any, css: any, selectorPrefix = ".") { - const propText = typeof css === "string" ? css : Object.keys(css).map(p => p + ":" + (p === "content" ? "'" + css[p] + "'" : css[p])).join(";"); - return sheet.insertRule(selectorPrefix + selector + "{" + propText + "}", sheet.cssRules.length); +export function addStyleSheetRule(sheet: any, selector: any, css: any, selectorPrefix = '.') { + const propText = + typeof css === 'string' + ? css + : Object.keys(css) + .map(p => p + ':' + (p === 'content' ? "'" + css[p] + "'" : css[p])) + .join(';'); + return sheet.insertRule(selectorPrefix + selector + '{' + propText + '}', sheet.cssRules.length); } export function removeStyleSheetRule(sheet: any, rule: number) { if (sheet.rules.length) { @@ -573,33 +634,35 @@ export function clearStyleSheetRules(sheet: any) { export function simulateMouseClick(element: Element | null | undefined, x: number, y: number, sx: number, sy: number, rightClick = true) { if (!element) return; - ["pointerdown", "pointerup"].map(event => element.dispatchEvent( - new PointerEvent(event, { + ['pointerdown', 'pointerup'].map(event => { + const me = new PointerEvent(event, { view: window, bubbles: true, cancelable: true, button: 2, - pointerType: "mouse", + pointerType: 'mouse', clientX: x, clientY: y, screenX: sx, screenY: sy, - }))); + }); + (me as any).dash = true; + element.dispatchEvent(me); + }); if (rightClick) { - const me = - new MouseEvent("contextmenu", { - view: window, - bubbles: true, - cancelable: true, - button: 2, - clientX: x, - clientY: y, - movementX: 0, - movementY: 0, - screenX: sx, - screenY: sy, - }); + const me = new MouseEvent('contextmenu', { + view: window, + bubbles: true, + cancelable: true, + button: 2, + clientX: x, + clientY: y, + movementX: 0, + movementY: 0, + screenX: sx, + screenY: sy, + }); (me as any).dash = true; element.dispatchEvent(me); } @@ -607,27 +670,25 @@ export function simulateMouseClick(element: Element | null | undefined, x: numbe export function DashColor(color: string) { try { - return color ? Color(color.toLowerCase()) : Color("transparent"); + return color ? Color(color.toLowerCase()) : Color('transparent'); } catch (e) { - console.log("COLOR error:", e); - return Color("red"); + console.log('COLOR error:', e); + return Color('red'); } } export function lightOrDark(color: any) { - if (color === "transparent") return "gray"; - if (color.startsWith?.("linear")) return "black"; - const nonAlphaColor = color.startsWith("#") ? (color as string).substring(0, 7) : - color.startsWith("rgba") ? color.replace(/,.[^,]*\)/, ")").replace("rgba", "rgb") : color; + if (color === 'transparent') return 'gray'; + if (color.startsWith?.('linear')) return 'black'; + const nonAlphaColor = color.startsWith('#') ? (color as string).substring(0, 7) : color.startsWith('rgba') ? color.replace(/,.[^,]*\)/, ')').replace('rgba', 'rgb') : color; const col = DashColor(nonAlphaColor).rgb(); - const colsum = (col.red() + col.green() + col.blue()); + const colsum = col.red() + col.green() + col.blue(); if (colsum / col.alpha() > 400 || col.alpha() < 0.25) return Colors.DARK_GRAY; else return Colors.WHITE; } - export function getWordAtPoint(elem: any, x: number, y: number): string | undefined { - if (elem.tagName === "INPUT") return "input"; + if (elem.tagName === 'INPUT') return 'input'; if (elem.nodeType === elem.TEXT_NODE) { const range = elem.ownerDocument.createRange(); range.selectNodeContents(elem); @@ -637,12 +698,11 @@ export function getWordAtPoint(elem: any, x: number, y: number): string | undefi range.setStart(elem, currentPos); range.setEnd(elem, currentPos + 1); const rangeRect = range.getBoundingClientRect(); - if (rangeRect.left <= x && rangeRect.right >= x && - rangeRect.top <= y && rangeRect.bottom >= y) { - range.expand?.("word"); // doesn't exist in firefox + if (rangeRect.left <= x && rangeRect.right >= x && rangeRect.top <= y && rangeRect.bottom >= y) { + range.expand?.('word'); // doesn't exist in firefox const ret = range.toString(); range.detach(); - return (ret); + return ret; } currentPos += 1; } @@ -651,8 +711,7 @@ export function getWordAtPoint(elem: any, x: number, y: number): string | undefi const range = childNode.ownerDocument.createRange(); range.selectNodeContents(childNode); const rangeRect = range.getBoundingClientRect(); - if (rangeRect.left <= x && rangeRect.right >= x && - rangeRect.top <= y && rangeRect.bottom >= y) { + if (rangeRect.left <= x && rangeRect.right >= x && rangeRect.top <= y && rangeRect.bottom >= y) { range.detach(); const word = getWordAtPoint(childNode, x, y); if (word) return word; @@ -681,17 +740,17 @@ export function StopEvent(e: React.PointerEvent | React.MouseEvent) { * Helper method for converting pixel string eg. '32px' into number eg. 32 * @param value: string with 'px' ending * @returns value: number - * + * * Example: * '32px' -> 32 */ -export function numberValue(value: string | undefined):number { +export function numberValue(value: string | undefined): number { if (value == undefined) return 0; return parseInt(value); } export function numbersAlmostEqual(num1: number, num2: number) { - return Math.abs( num1 - num2 ) < 0.2; + return Math.abs(num1 - num2) < 0.2; } export function setupMoveUpEvents( @@ -705,7 +764,7 @@ export function setupMoveUpEvents( noDoubleTapTimeout?: () => void ) { const doubleTapTimeout = 300; - (target as any)._doubleTap = (Date.now() - (target as any)._lastTap < doubleTapTimeout); + (target as any)._doubleTap = Date.now() - (target as any)._lastTap < doubleTapTimeout; (target as any)._lastTap = Date.now(); (target as any)._downX = (target as any)._lastX = e.clientX; (target as any)._downY = (target as any)._lastY = e.clientY; @@ -717,10 +776,9 @@ export function setupMoveUpEvents( clearTimeout((target as any)._doubleTime); (target as any)._doubleTime = undefined; } - if (moveEvent(e, [(target as any)._downX, (target as any)._downY], - [e.clientX - (target as any)._lastX, e.clientY - (target as any)._lastY])) { - document.removeEventListener("pointermove", _moveEvent); - document.removeEventListener("pointerup", _upEvent); + if (moveEvent(e, [(target as any)._downX, (target as any)._downY], [e.clientX - (target as any)._lastX, e.clientY - (target as any)._lastY])) { + document.removeEventListener('pointermove', _moveEvent); + document.removeEventListener('pointerup', _upEvent); } } (target as any)._lastX = e.clientX; @@ -743,18 +801,18 @@ export function setupMoveUpEvents( } (target as any)._noClick = clickEvent(e, (target as any)._doubleTap); } - document.removeEventListener("pointermove", _moveEvent); - document.removeEventListener("pointerup", _upEvent); + document.removeEventListener('pointermove', _moveEvent); + document.removeEventListener('pointerup', _upEvent); }; const _clickEvent = (e: MouseEvent): void => { if ((target as any)._noClick) e.stopPropagation(); - document.removeEventListener("click", _clickEvent, true); - } + document.removeEventListener('click', _clickEvent, true); + }; if (stopPropagation) { e.stopPropagation(); e.preventDefault(); } - document.addEventListener("pointermove", _moveEvent); - document.addEventListener("pointerup", _upEvent); - document.addEventListener("click", _clickEvent, true); -}
\ No newline at end of file + document.addEventListener('pointermove', _moveEvent); + document.addEventListener('pointerup', _upEvent); + document.addEventListener('click', _clickEvent, true); +} |