UNPKG

@igo2/utils

Version:
1 lines 80.7 kB
{"version":3,"file":"igo2-utils.mjs","sources":["../../../packages/utils/src/lib/base64.ts","../../../packages/utils/src/lib/cache.utils.ts","../../../packages/utils/src/lib/user-agent.ts","../../../packages/utils/src/lib/clipboard.ts","../../../packages/utils/src/lib/compression/compression.utils.ts","../../../packages/utils/src/lib/change.interface.ts","../../../packages/utils/src/lib/string-utils.ts","../../../packages/utils/src/lib/change.ts","../../../packages/utils/src/lib/date.utils.ts","../../../packages/utils/src/lib/dom.utils.ts","../../../packages/utils/src/lib/files/excel.ts","../../../packages/utils/src/lib/files/file.ts","../../../packages/utils/src/lib/object-utils.ts","../../../packages/utils/src/lib/number-utils.ts","../../../packages/utils/src/lib/strenum.ts","../../../packages/utils/src/lib/theme.utils.ts","../../../packages/utils/src/lib/tree/tree.ts","../../../packages/utils/src/lib/uuid.ts","../../../packages/utils/src/lib/watcher.ts","../../../packages/utils/src/public_api.ts","../../../packages/utils/src/igo2-utils.ts"],"sourcesContent":["/* eslint-disable */\n\nconst ALPHA =\n 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';\n\nexport class Base64 {\n private static PADCHAR: string = '=';\n private static ALPHA: string = ALPHA;\n\n private static getByte(s: string, i: number): number {\n const x = s.charCodeAt(i);\n return x;\n }\n\n private static getByte64(s: string, i: number): number {\n const idx = this.ALPHA.indexOf(s.charAt(i));\n return idx;\n }\n\n public static decode(s: string): string {\n let pads = 0,\n i,\n b10,\n imax = s.length,\n x = [];\n\n s = String(s);\n\n if (imax === 0) {\n return s;\n }\n\n if (s.charAt(imax - 1) === this.PADCHAR) {\n pads = 1;\n if (s.charAt(imax - 2) === this.PADCHAR) {\n pads = 2;\n }\n imax -= 4;\n }\n\n for (i = 0; i < imax; i += 4) {\n b10 =\n (this.getByte64(s, i) << 18) |\n (this.getByte64(s, i + 1) << 12) |\n (this.getByte64(s, i + 2) << 6) |\n this.getByte64(s, i + 3);\n x.push(String.fromCharCode(b10 >> 16, (b10 >> 8) & 255, b10 & 255));\n }\n\n switch (pads) {\n case 1:\n b10 =\n (this.getByte64(s, i) << 18) |\n (this.getByte64(s, i + 1) << 12) |\n (this.getByte64(s, i + 2) << 6);\n x.push(String.fromCharCode(b10 >> 16, (b10 >> 8) & 255));\n break;\n case 2:\n b10 = (this.getByte64(s, i) << 18) | (this.getByte64(s, i + 1) << 12);\n x.push(String.fromCharCode(b10 >> 16));\n break;\n }\n\n return x.join('');\n }\n\n public static encode(s: string): string {\n s = String(s);\n\n let i,\n b10,\n x = [],\n imax = s.length - (s.length % 3);\n\n if (s.length === 0) {\n return s;\n }\n\n for (i = 0; i < imax; i += 3) {\n b10 =\n (this.getByte(s, i) << 16) |\n (this.getByte(s, i + 1) << 8) |\n this.getByte(s, i + 2);\n x.push(this.ALPHA.charAt(b10 >> 18));\n x.push(this.ALPHA.charAt((b10 >> 12) & 63));\n x.push(this.ALPHA.charAt((b10 >> 6) & 63));\n x.push(this.ALPHA.charAt(b10 & 63));\n }\n\n switch (s.length - imax) {\n case 1:\n b10 = this.getByte(s, i) << 16;\n x.push(\n this.ALPHA.charAt(b10 >> 18) +\n this.ALPHA.charAt((b10 >> 12) & 63) +\n this.PADCHAR +\n this.PADCHAR\n );\n break;\n case 2:\n b10 = (this.getByte(s, i) << 16) | (this.getByte(s, i + 1) << 8);\n x.push(\n this.ALPHA.charAt(b10 >> 18) +\n this.ALPHA.charAt((b10 >> 12) & 63) +\n this.ALPHA.charAt((b10 >> 6) & 63) +\n this.PADCHAR\n );\n break;\n }\n\n return x.join('');\n }\n}\n","import { HttpParams } from '@angular/common/http';\n\nexport function customCacheHasher(parameters: unknown[]): unknown[] {\n return parameters.map((param) => {\n if (param instanceof HttpParams) {\n return param.toString();\n }\n return param !== undefined ? JSON.parse(JSON.stringify(param)) : param;\n });\n}\n","import Bowser from 'bowser';\n\nexport interface UserAgent extends Bowser.Parser.Parser {\n compareVersion: (version: string) => boolean;\n}\n\nexport const userAgent = Bowser.getParser(\n window.navigator.userAgent\n) as UserAgent;\n","import { userAgent } from './user-agent';\n\nexport class Clipboard {\n static copy(element: HTMLTextAreaElement | string): boolean {\n let successful = false;\n if (typeof element === 'string') {\n const textArea = Clipboard.createTextArea(element);\n Clipboard.selectText(textArea);\n successful = Clipboard.copyTextToClipboard();\n Clipboard.destroyTextArea(textArea);\n } else {\n Clipboard.selectText(element);\n successful = Clipboard.copyTextToClipboard();\n }\n return successful;\n }\n\n private static createTextArea(text: string): HTMLTextAreaElement {\n const textArea = document.createElement('textArea') as HTMLTextAreaElement;\n textArea.value = text;\n document.body.appendChild(textArea);\n return textArea;\n }\n\n private static destroyTextArea(textArea) {\n document.body.removeChild(textArea);\n }\n\n private static selectText(textArea) {\n if (userAgent.getOSName() === 'iOS') {\n const oldContentEditable = textArea.contentEditable;\n const oldReadOnly = textArea.readOnly;\n const range = document.createRange();\n const selection = window.getSelection();\n\n textArea.contenteditable = true;\n textArea.readonly = false;\n range.selectNodeContents(textArea);\n selection.removeAllRanges();\n selection.addRange(range);\n textArea.setSelectionRange(0, 999999);\n textArea.contentEditable = oldContentEditable;\n textArea.readOnly = oldReadOnly;\n } else {\n textArea.select();\n }\n }\n\n private static copyTextToClipboard(): boolean {\n if (!(userAgent.getOSName() === 'iOS' && userAgent.compareVersion('<10'))) {\n return document.execCommand('copy');\n }\n return false;\n }\n}\n","import { Observable, Observer } from 'rxjs';\n\nimport { CompressedData } from './compressedData.interface';\n\nfunction getNumber(v: number, endposition: number, length: number) {\n const mask = (1 << length) - 1;\n return (v >> endposition) & mask;\n}\n\nexport class Compression {\n private base64Index = new Map<string, number>();\n private indexBase64 = new Map<number, string>();\n\n constructor() {\n this.generateBase64Index();\n }\n\n private generateBase64Index() {\n // https://fr.wikipedia.org/wiki/Base64\n // A-Z => [0, 25]\n for (let i = 0; i < 26; i++) {\n this.base64Index.set(String.fromCharCode('A'.charCodeAt(0) + i), i);\n this.indexBase64.set(i, String.fromCharCode('A'.charCodeAt(0) + i));\n }\n // a-z => [26, 51]\n for (let i = 0; i < 26; i++) {\n this.base64Index.set(String.fromCharCode('a'.charCodeAt(0) + i), i + 26);\n this.indexBase64.set(i + 26, String.fromCharCode('a'.charCodeAt(0) + i));\n }\n // 0-9 => [52, 61]\n for (let i = 0; i < 10; i++) {\n this.base64Index.set(String.fromCharCode('0'.charCodeAt(0) + i), i + 52);\n this.indexBase64.set(i + 52, String.fromCharCode('0'.charCodeAt(0) + i));\n }\n // + / => [62, 63]\n this.base64Index.set('+', 62);\n this.base64Index.set('/', 63);\n this.indexBase64.set(62, '+');\n this.indexBase64.set(63, '/');\n }\n\n compressBlob(blob: Blob): Observable<CompressedData> {\n if (!blob) {\n return;\n }\n\n const observable = new Observable((observer: Observer<CompressedData>) => {\n const reader = new FileReader();\n reader.readAsDataURL(blob);\n reader.onload = () => {\n const base64 = reader.result.valueOf() as string;\n const text64 = base64.substr(base64.indexOf(',') + 1);\n const compressed = this.compressStringBase64(text64);\n const compressedData: CompressedData = {\n length: text64.length,\n type: blob.type,\n object: compressed\n };\n observer.next(compressedData);\n };\n });\n return observable;\n }\n\n decompressBlob(compressedData: CompressedData): Blob {\n const object = compressedData.object;\n const length = compressedData.length;\n const decompressed: string = this.decompressStringBase64(object, length);\n const byteCharacters = atob(decompressed);\n const byteNumbers = new Array(byteCharacters.length);\n for (let i = 0; i < byteCharacters.length; i++) {\n byteNumbers[i] = byteCharacters.charCodeAt(i);\n }\n const byteArray = new Uint8Array(byteNumbers);\n const blob = new Blob([byteArray], { type: compressedData.type });\n return blob;\n }\n\n private compressStringBase64(s: string): string {\n let out = '';\n let bits = 16;\n let chr = 0;\n let rem = 0;\n for (const c of s) {\n const value = this.base64Index.get(c);\n if (bits > 6) {\n bits -= 6;\n chr += value << bits;\n } else {\n rem = 6 - bits;\n chr += value >> rem;\n out += String.fromCharCode(chr);\n chr = value << (16 - rem);\n bits = 16 - rem;\n }\n }\n if (s.length % 8 !== 0) {\n out += String.fromCharCode(chr);\n }\n return String.fromCharCode(9731) + out;\n }\n\n private decompressStringBase64(c: string, length: number): string {\n if (!c) {\n return;\n }\n\n if (c.charCodeAt(0) !== 9731) {\n return c;\n }\n\n let chr = 0;\n let rem = 0;\n let bits = 16;\n let out = '';\n let j = 1;\n let value = c.charCodeAt(j);\n for (let i = 0; i < length; i++) {\n if (bits > 6) {\n bits -= 6;\n chr = getNumber(value, bits, 6);\n out += this.indexBase64.get(chr);\n } else {\n rem = 6 - bits;\n chr = getNumber(value, 0, bits) << rem;\n value = c.charCodeAt(++j);\n chr += getNumber(value, 16 - rem, rem);\n out += this.indexBase64.get(chr);\n bits = 16 - rem;\n }\n }\n return out;\n }\n}\n","export enum ChangeType {\n ADDED = 'added',\n DELETED = 'deleted',\n MODIFIED = 'modified'\n}\n\nexport interface Change {\n type: ChangeType;\n keysChanged?: {\n key: string;\n newValue: any;\n oldValue: any;\n }[];\n}\n\nexport interface GroupingChanges {\n added: ChangeItem[];\n deleted: ChangeItem[];\n modified: ChangeItem[];\n}\n\nexport interface ChangeItem {\n change: Change;\n value: any;\n oldValue?: any;\n newValue?: any;\n}\n","export class StringUtils {\n static diff(s1: string, s2: string, p = 4): string {\n if (!s1 && !s2) {\n return '';\n }\n if (!s1) {\n return '<span class=\"inserted\">' + s2 + '</span>';\n }\n if (!s2) {\n return '<span class=\"deleted\">' + s1 + '</span>';\n }\n s1 = s1.toString();\n s2 = s2.toString();\n const changeData = StringUtils.getChanges(s1, s2, '', p);\n const nextS = s2.slice(\n changeData.mtc.length + changeData.ins.length + changeData.sbs.length\n ); // remaining part of \"s\"\n const nextThis = s1.slice(\n changeData.mtc.length + changeData.del.length + changeData.sbs.length\n ); // remaining part of \"this\"\n let result = ''; // the glorious result\n if (changeData.del.length > 0) {\n changeData.del = '<span class=\"deleted\">' + changeData.del + '</span>';\n }\n if (changeData.ins.length > 0) {\n changeData.ins = '<span class=\"inserted\">' + changeData.ins + '</span>';\n }\n result = changeData.mtc + changeData.del + changeData.ins + changeData.sbs;\n result +=\n nextThis !== '' || nextS !== ''\n ? StringUtils.diff(nextThis, nextS, p)\n : '';\n return result;\n }\n\n private static getMatchingSubstring(s, l, m) {\n // returns the first matching substring in-between the two strings\n let i = 0;\n let match = false;\n const slen = s.length;\n const o = { fis: slen, mtc: m, sbs: '' }; // temporary object used to construct the cd (change data) object\n\n while (i < slen) {\n // eslint-disable-next-line @typescript-eslint/no-unused-expressions\n l[i] === s[i]\n ? match\n ? (o.sbs += s[i]) // o.sbs holds the matching substring itsef\n : ((match = true), (o.fis = i), (o.sbs = s[i]))\n : match\n ? (i = slen) // stop after the first found substring\n : // eslint-disable-next-line no-self-assign\n (i = i);\n ++i;\n }\n return o;\n }\n\n private static getChanges(s1, s2, m, p) {\n const isThisLonger = s1.length >= s1.length ? true : false;\n let [longer, shorter] = isThisLonger ? [s1, s2] : [s2, s1]; // assignment of longer and shorter by es6 destructuring\n let bi = 0; // base index designating the index of first mismacthing character in both strings\n\n while (shorter[bi] === longer[bi] && bi < shorter.length) {\n ++bi;\n } // make bi the index of first mismatching character\n longer = longer.split('').slice(bi); // as the longer string will be rotated it is converted into array\n shorter = shorter.slice(bi); // shorter and longer now starts from the first mismatching character\n\n const len = longer.length; // length of the longer string\n let cd: any = {\n fis: shorter.length, // the index of matching string in the shorter string\n fil: len, // the index of matching string in the longer string\n sbs: '', // the matching substring itself\n mtc: m + s2.slice(0, bi)\n }; // if exists mtc holds the matching string at the front\n let sub: any = { sbs: '' }; // returned substring per 1 character rotation of the longer string\n\n if (shorter !== '') {\n for (let rc = 0; rc < len && sub.sbs.length < p; rc++) {\n // rc -> rotate count, p -> precision factor\n sub = StringUtils.getMatchingSubstring(\n shorter,\n StringUtils.rotateArray(longer, rc),\n cd.mtc\n ); // rotate longer string 1 char and get substring\n sub.fil =\n rc < len - sub.fis\n ? sub.fis + rc // mismatch is longer than the mismatch in short\n : sub.fis - len + rc; // mismatch is shorter than the mismatch in short\n if (sub.sbs.length > cd.sbs.length) {\n cd = sub; // only keep the one with the longest substring.\n }\n }\n }\n // insert the mismatching delete subsrt and insert substr to the cd object and attach the previous substring\n [cd.del, cd.ins] = isThisLonger\n ? [longer.slice(0, cd.fil).join(''), shorter.slice(0, cd.fis)]\n : [shorter.slice(0, cd.fis), longer.slice(0, cd.fil).join('')];\n return cd.del.indexOf(' ') === -1 ||\n cd.ins.indexOf(' ') === -1 ||\n cd.del === '' ||\n cd.ins === '' ||\n cd.sbs === ''\n ? cd\n : StringUtils.getChanges(cd.del, cd.ins, cd.mtc, p);\n }\n\n private static rotateArray(array, n) {\n const len = array.length;\n const res = new Array(array.length);\n if (n % len === 0) {\n return array.slice();\n } else {\n for (let i = 0; i < len; i++) {\n res[i] = array[(i + (len + (n % len))) % len];\n }\n }\n return res;\n }\n\n static isValidNumber(value: string): boolean {\n return !isNaN(Number(value));\n }\n\n static isOctalNumber(value: string): boolean {\n return (\n StringUtils.isValidNumber(value) &&\n value.startsWith('0') &&\n value.length > 1\n );\n }\n}\n","import { ChangeType, GroupingChanges } from './change.interface';\nimport { StringUtils } from './string-utils';\n\nexport class ChangeUtils {\n static findChanges(\n obj1: any[],\n obj2: any[],\n ignoreKeys: string[] = []\n ): GroupingChanges {\n const items: GroupingChanges = {\n added: [],\n deleted: [],\n modified: []\n };\n\n if (!obj1 || !obj2) {\n return items;\n }\n\n const obj1Clone: any = [...obj1];\n const obj2Clone: any = [...obj2];\n\n for (const fromItem of obj1Clone) {\n const index = obj2Clone.findIndex((s) => s.id === fromItem.id);\n\n if (index === -1) {\n items.deleted.push({\n change: { type: ChangeType.DELETED },\n value: fromItem\n });\n continue;\n }\n\n const toItem = obj2Clone.splice(index, 1)[0];\n const fromItemClone = JSON.parse(JSON.stringify(fromItem));\n const toItemClone = JSON.parse(JSON.stringify(toItem));\n\n const keysChanged = ChangeUtils.compareObject(\n fromItemClone,\n toItemClone,\n undefined,\n ignoreKeys\n );\n\n if (keysChanged.length) {\n items.modified.push({\n change: {\n type: ChangeType.MODIFIED,\n keysChanged\n },\n value: fromItemClone,\n oldValue: fromItem,\n newValue: toItem\n });\n }\n }\n\n items.added = obj2Clone.map((itemAdded) => {\n return {\n change: { type: ChangeType.ADDED },\n value: itemAdded\n };\n });\n\n return items;\n }\n\n private static compareObject(fromItem, toItem, baseKey?, ignoreKeys = []) {\n const fromItemClone = JSON.parse(JSON.stringify(fromItem));\n const toItemClone = JSON.parse(JSON.stringify(toItem));\n\n const keys: any = new Set([\n ...Object.keys(fromItem),\n ...Object.keys(toItem)\n ]);\n let keysChanged = [];\n keys.forEach((key) => {\n const keyString = baseKey ? `${baseKey}.${key}` : key;\n if (ignoreKeys.indexOf(keyString) !== -1) {\n return;\n }\n\n if (Array.isArray(fromItem[key])) {\n fromItem[key] = fromItem[key].join(',<br>');\n }\n if (Array.isArray(toItem[key])) {\n toItem[key] = toItem[key].join(',<br>');\n }\n\n if (\n typeof fromItem[key] === 'object' &&\n typeof toItem[key] === 'object' &&\n fromItem[key] !== null &&\n toItem[key] !== null\n ) {\n keysChanged = keysChanged.concat(\n this.compareObject(fromItem[key], toItem[key], keyString)\n );\n } else {\n if (fromItem[key] !== toItem[key]) {\n keysChanged.push({\n key: keyString,\n oldValue: fromItemClone[key],\n newValue: toItemClone[key]\n });\n fromItem[key] = StringUtils.diff(fromItem[key], toItem[key]);\n }\n }\n });\n\n return keysChanged;\n }\n}\n","const ISO8601_REGEX = new RegExp(\n '(d{4}-[01]d-[0-3]dT[0-2]d:[0-5]d:[0-5]d.d+)|(d{4}-[01]d-[0-3]dT[0-2]d:[0-5]d:[0-5]d)|(d{4}-[01]d-[0-3]dT[0-2]d:[0-5]d)'\n);\nconst ISO8601_UTCTIME_REGEX = new RegExp(\n '(-?(?:[1-9][0-9]*)?[0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(\\\\.[0-9]+)?(Z)?'\n);\n\nexport function isIsoDate(value: string): boolean {\n if (!ISO8601_REGEX.test(value) && !ISO8601_UTCTIME_REGEX.test(value)) {\n return false;\n }\n const d = new Date(value);\n return d instanceof Date && !isNaN(d.getTime());\n}\n","export class DomUtils {\n static create<K extends keyof HTMLElementTagNameMap>(\n doc: Document,\n tagName: K,\n options?: Partial<HTMLElementTagNameMap[K]>\n ): HTMLElementTagNameMap[K] {\n const el = doc.createElement(tagName);\n\n for (const key in options) {\n el[key] = options[key];\n }\n\n return el;\n }\n\n static remove(node: HTMLElement | SVGElement): void {\n if (!node.parentNode) {\n return;\n }\n node.parentNode.removeChild(node);\n }\n}\n","import type {\n ColInfo,\n JSON2SheetOpts,\n WorkBook,\n WorkSheet,\n WritingOptions\n} from 'xlsx';\n\nexport async function createExcelWorkBook(\n workSheet?: WorkSheet,\n workSheetName?: string\n): Promise<WorkBook> {\n const { utils } = await import('xlsx');\n\n return utils.book_new(workSheet, workSheetName);\n}\nexport async function addExcelSheetToWorkBook<T = Record<string, unknown>>(\n title: string,\n rows: T[],\n workBook: WorkBook,\n opts?: {\n json2SheetOpts?: JSON2SheetOpts;\n bookAppendSheetOpts?: { roll?: boolean };\n }\n): Promise<void> {\n const { utils } = await import('xlsx');\n\n const worksheet = utils.json_to_sheet(rows, opts?.json2SheetOpts);\n\n /* calculate column width */\n if (rows?.length) {\n worksheet['!cols'] = getColumnsInfo(rows);\n }\n\n const SHEET_NAME_MAX_LENGTH = 31;\n let sheetName =\n title.length >= SHEET_NAME_MAX_LENGTH\n ? title.substring(0, SHEET_NAME_MAX_LENGTH)\n : title;\n\n if (workBook.SheetNames.includes(sheetName)) {\n sheetName = `${sheetName.substring(0, SHEET_NAME_MAX_LENGTH - 3)}_${workBook.SheetNames.length}`;\n }\n\n utils.book_append_sheet(\n workBook,\n worksheet,\n sheetName,\n opts?.bookAppendSheetOpts?.roll\n );\n}\n\nexport async function writeExcelFile(\n workBook: WorkBook,\n filename: string,\n opts?: WritingOptions\n) {\n const cleanedFileName = filename.toLowerCase().endsWith('.xlsx')\n ? filename.slice(0, -5)\n : filename;\n const { writeFile } = await import('xlsx');\n writeFile(workBook, `${cleanedFileName}.xlsx`, opts);\n}\n\nfunction getColumnsInfo<T = Record<string, unknown>>(rows: T[]): ColInfo[] {\n const columns = Object.keys(rows[0]);\n return columns.map((column) => ({\n wch: getColumnMaxWidth(column, rows)\n }));\n}\n\nfunction getColumnMaxWidth<T = Record<string, unknown>>(\n column: string,\n rows: T[]\n): number {\n return rows.reduce(\n (width, row) => Math.max(width, row[column]?.toString().length ?? 0),\n column.length\n );\n}\n","/**\n * Trigger download of a file\n *\n * @param content File content\n * @param mimeType File mime type\n * @param fileName File name\n */\nexport function downloadContent(\n content: string,\n mimeType: string,\n fileName: string\n) {\n const uri = `data:${mimeType},${encodeURIComponent(content)}`;\n downloadFromUri(uri, fileName);\n}\n\nexport function downloadBlob(blob: Blob, fileName: string) {\n const url = window.URL.createObjectURL(blob);\n downloadFromUri(url, fileName);\n}\n\n/**\n * Trigger download of a file\n *\n * @param content File content\n * @param mimeType File mime type\n * @param fileName File name\n */\nexport function downloadFromUri(uri: string, fileName: string) {\n const element = document.createElement('a');\n element.setAttribute('href', uri);\n element.setAttribute('download', fileName);\n element.style.display = 'none';\n document.body.appendChild(element);\n\n element.click();\n\n document.body.removeChild(element);\n}\n\n/**\n * Validate if string is valid json object\n * @param jsonString\n * @return boolean\n */\nexport function isValidJSON(jsonString: string): boolean {\n try {\n return JSON.parse(jsonString) && !!jsonString;\n } catch {\n return false;\n }\n}\n","/* eslint-disable no-prototype-builtins */\nexport class ObjectUtils {\n static resolve(obj: object, key: string): any {\n const keysArray = key.replace(/\\[/g, '.').replace(/\\]/g, '').split('.');\n let current = obj;\n while (keysArray.length) {\n if (typeof current !== 'object') {\n return undefined;\n }\n current = current[keysArray.shift()];\n }\n\n return current;\n }\n\n static isObject(item: object) {\n return (\n item &&\n typeof item === 'object' &&\n !Array.isArray(item) &&\n item !== null &&\n !(item instanceof Date)\n );\n }\n\n static mergeDeep(\n target: object,\n source: object,\n ignoreUndefined = false\n ): any {\n const output = Object.assign({}, target);\n if (ObjectUtils.isObject(target) && ObjectUtils.isObject(source)) {\n Object.keys(source)\n .filter((key) => !ignoreUndefined || source[key] !== undefined)\n .forEach((key) => {\n if (ObjectUtils.isObject(source[key])) {\n if (!(key in target)) {\n Object.assign(output, { [key]: source[key] });\n } else {\n output[key] = ObjectUtils.mergeDeep(\n target[key],\n source[key],\n ignoreUndefined\n );\n }\n } else {\n Object.assign(output, { [key]: source[key] });\n }\n });\n }\n return output;\n }\n\n static copyDeep(src): any {\n const target = Array.isArray(src) ? [] : {};\n for (const prop in src) {\n if (src.hasOwnProperty(prop)) {\n const value = src[prop];\n if (value && typeof value === 'object') {\n target[prop] = this.copyDeep(value);\n } else {\n target[prop] = value;\n }\n }\n }\n return target;\n }\n\n static removeDuplicateCaseInsensitive(obj: object) {\n const summaryCapitalizeObject = {};\n const capitalizeObject = {};\n const upperCaseCount = [];\n\n for (const property in obj) {\n if (obj.hasOwnProperty(property)) {\n const upperCaseProperty = property.toUpperCase();\n if (!summaryCapitalizeObject.hasOwnProperty(upperCaseProperty)) {\n summaryCapitalizeObject[upperCaseProperty] = [\n { [property]: obj[property] }\n ];\n } else {\n summaryCapitalizeObject[upperCaseProperty].push({\n [property]: obj[property]\n });\n }\n // counting the number of uppercase lettersMna\n upperCaseCount.push({\n key: property,\n count: property.replace(/[^A-Z]/g, '').length\n });\n }\n }\n for (const capitalizedProperty in summaryCapitalizeObject) {\n if (summaryCapitalizeObject.hasOwnProperty(capitalizedProperty)) {\n if (summaryCapitalizeObject.hasOwnProperty(capitalizedProperty)) {\n const capitalizedPropertyObject =\n summaryCapitalizeObject[capitalizedProperty];\n if (capitalizedPropertyObject.length === 1) {\n // for single params (no duplicates)\n const singlePossibility = capitalizedPropertyObject[0];\n capitalizeObject[capitalizedProperty] =\n singlePossibility[Object.keys(singlePossibility)[0]];\n } else if (capitalizedPropertyObject.length > 1) {\n // defining the closest to lowercase property\n const paramClosestToLowercase = upperCaseCount\n .filter(\n (f) => f.key.toLowerCase() === capitalizedProperty.toLowerCase()\n )\n .reduce((prev, current) => {\n return prev.y < current.y ? prev : current;\n });\n capitalizeObject[paramClosestToLowercase.key.toUpperCase()] =\n obj[paramClosestToLowercase.key];\n }\n }\n }\n }\n for (const property in obj) {\n if (obj.hasOwnProperty(property)) {\n delete obj[property];\n }\n }\n\n for (const property in capitalizeObject) {\n if (capitalizeObject.hasOwnProperty(property)) {\n obj[property] = capitalizeObject[property];\n }\n }\n }\n\n static removeUndefined(obj: object): any {\n const output = {};\n if (ObjectUtils.isObject(obj)) {\n Object.keys(obj)\n .filter((key) => obj[key] !== undefined)\n .forEach((key) => {\n if (ObjectUtils.isObject(obj[key]) || Array.isArray(obj[key])) {\n output[key] = ObjectUtils.removeUndefined(obj[key]);\n } else {\n output[key] = obj[key];\n }\n });\n\n return output;\n }\n\n if (Array.isArray(obj)) {\n return obj.map((o) => ObjectUtils.removeUndefined(o));\n }\n\n return obj;\n }\n\n static removeNull(obj: object): any {\n const output = {};\n if (ObjectUtils.isObject(obj)) {\n Object.keys(obj)\n .filter((key) => obj[key] !== null)\n .forEach((key) => {\n if (ObjectUtils.isObject(obj[key]) || Array.isArray(obj[key])) {\n output[key] = ObjectUtils.removeNull(obj[key]);\n } else {\n output[key] = obj[key];\n }\n });\n\n return output;\n }\n\n if (Array.isArray(obj)) {\n return obj.map((o) => ObjectUtils.removeNull(o));\n }\n\n return obj;\n }\n\n static naturalCompare(a, b, direction = 'asc', nullsFirst?: boolean) {\n if (direction === 'desc') {\n b = [a, (a = b)][0];\n }\n\n // nullsFirst = undefined : end if direction = 'asc', first if direction = 'desc'\n // nullsFirst = true : always first\n // nullsFirst = false : always end\n if (\n a === null ||\n a === '' ||\n a === undefined ||\n b === null ||\n b === '' ||\n b === undefined\n ) {\n const nullScore =\n a === b\n ? 0\n : a === undefined\n ? 3\n : b === undefined\n ? -3\n : a === null\n ? 2\n : b === null\n ? -2\n : a === ''\n ? 1\n : -1;\n if (direction === 'desc') {\n return nullsFirst !== false ? nullScore : nullScore * -1;\n }\n return nullsFirst === true ? nullScore * -1 : nullScore;\n }\n\n const ax = [];\n const bx = [];\n a = '' + a;\n b = '' + b;\n\n a.replace(/(\\d+)|(\\D+)/g, (_, $1, $2) => {\n ax.push([$1 || Infinity, $2 || '']);\n });\n\n b.replace(/(\\d+)|(\\D+)/g, (_, $1, $2) => {\n bx.push([$1 || Infinity, $2 || '']);\n });\n\n while (ax.length && bx.length) {\n const an = ax.shift();\n const bn = bx.shift();\n const nn = an[0] - bn[0] || an[1].localeCompare(bn[1]);\n if (nn) {\n return nn;\n }\n }\n\n return ax.length - bx.length;\n }\n\n /**\n * Return true if two object are equivalent.\n * Objects are considered equivalent if they have the same properties and\n * if all of their properties (first-level only) share the same value.\n * @param obj1 First object\n * @param obj2 Second object\n * @returns Whether two objects arer equivalent\n */\n static objectsAreEquivalent(obj1: object, obj2: object): boolean {\n if (obj1 === obj2) {\n return true;\n }\n\n const obj1Props = Object.getOwnPropertyNames(obj1);\n const obj2Props = Object.getOwnPropertyNames(obj2);\n if (obj1Props.length !== obj2Props.length) {\n return false;\n }\n\n for (const prop of obj1Props) {\n if (obj1[prop] !== obj2[prop]) {\n return false;\n }\n }\n\n return true;\n }\n\n /**\n * Return a new object with an array of keys removed\n * @param obj Source object\n * @param keys Keys to remove\n * @returns A new object\n */\n static removeKeys(obj: object, keys: string[]): object {\n const newObj = Object.keys(obj)\n .filter((key) => keys.indexOf(key) < 0)\n .reduce((_obj, key) => {\n _obj[key] = obj[key];\n return _obj;\n }, {});\n\n return newObj;\n }\n\n static isEmpty(obj: object): boolean {\n return Object.keys(obj).length === 0;\n }\n}\n","export class NumberUtils {\n static roundToNDecimal(num: number, decimal = 3): number {\n const roundFactor = Math.pow(10, decimal);\n return Math.round(num * roundFactor) / roundFactor;\n }\n}\n","/** Utility function to create a K:V from a list of strings */\nexport function strEnum<T extends string>(o: T[]): { [K in T]: K } {\n return o.reduce((res, key) => {\n res[key] = key;\n return res;\n }, Object.create(null));\n}\n","import { DomUtils } from './dom.utils';\n\nconst PATH_PREBUILT_THEMES = 'assets/igo2/core/theming/prebuilt-themes';\nconst LINK_ID = 'theme-styles';\n\nexport function loadTheme(\n doc: Document,\n themeName: string,\n path: string = PATH_PREBUILT_THEMES\n): void {\n const src = `${path}/${themeName}.css`;\n const head = doc.getElementsByTagName('head')[0];\n\n const themeLink = doc.getElementById(LINK_ID) as HTMLLinkElement;\n\n if (themeLink) {\n themeLink.href = src;\n } else {\n createHtmlLink(doc, src, head);\n }\n}\n\nfunction createHtmlLink(doc: Document, src: string, parent: HTMLElement): void {\n const element = DomUtils.create(doc, 'link', {\n id: LINK_ID,\n rel: 'stylesheet',\n href: src\n });\n parent.appendChild(element);\n}\n","interface ITreeConfig<T> {\n getChildren: (dataNode: T) => T[] | undefined | null;\n getId: (dataNode: T) => string;\n getLevel: (dataNode: T) => number;\n reverse?: boolean;\n}\n\nexport const TREE_SEPERATOR = '.';\n\nexport class Tree<T> {\n private _data: T[];\n\n getChildren: (dataNode: T) => T[] | undefined | null;\n getId: (dataNode: T) => string;\n getLevel: (dataNode: T) => number;\n\n constructor(\n initialData: T[],\n private config: ITreeConfig<T>\n ) {\n this.getChildren = config.getChildren;\n this.getId = config.getId;\n this.getLevel = config.getLevel;\n\n this._data = this.sortDeep(initialData);\n }\n\n get data(): readonly T[] {\n return this._data;\n }\n\n get flattened(): readonly T[] {\n return this.flatten([...this.data]);\n }\n\n add(...nodes: T[]): T[] {\n this.sortDeep(nodes);\n this._data.unshift(...nodes);\n return nodes;\n }\n\n addBefore(beforeId: string | undefined, ...nodes: T[]): void {\n this.sortDeep(nodes);\n this._addBefore(beforeId, this._data, ...nodes);\n }\n\n remove(...nodes: T[]): T[] {\n return this._remove(...nodes);\n }\n\n clear(): void {\n this._data = [];\n }\n\n exist(node: T): boolean {\n const id = this.getId(node);\n return this.flattened.some((layer) => this.getId(layer) === id);\n }\n\n /**\n * Move a node to a different position\n * @param node\n * @param beforeTo The position of index into the tree. If -1 move at the end\n */\n moveTo(beforeTo: number[], ...nodes: T[]): T[] {\n const clonedBeforeTo = [...beforeTo];\n const lastIndex = clonedBeforeTo.pop();\n const recipient = this.getAncestorAtPosition(clonedBeforeTo);\n const beforeId =\n lastIndex === -1 || lastIndex >= recipient.length\n ? null\n : this.getId(recipient[lastIndex]);\n\n const nodesToMove = nodes.filter((node) => beforeId !== this.getId(node));\n return this.move(beforeId, recipient, ...nodesToMove);\n }\n\n getPosition(node: T): number[] {\n const id = this.getId(node);\n return this._getPosition(id);\n }\n\n private _addBefore(\n beforeId: string | undefined,\n recipient = this._data,\n ...nodes: T[]\n ): T[] {\n if (!beforeId) {\n recipient.push(...nodes);\n return nodes;\n }\n\n const beforeIndex = this.getIndex(beforeId, recipient);\n recipient.splice(beforeIndex, 0, ...nodes);\n\n return nodes;\n }\n\n private _remove(...nodes: T[]): T[] {\n return nodes.reduce((acc: T[], node) => {\n const ancestor = this.getNodeAncestor(node);\n if (!ancestor) {\n return;\n }\n\n const index = this.getIndex(this.getId(node), ancestor);\n if (index === -1) {\n return;\n }\n ancestor.splice(index, 1);\n\n return acc.concat(node);\n }, []);\n }\n\n /**\n * Move an node before an id\n * @param node Node to be move\n * @param recipient\n * @param beforeId\n */\n private move(\n beforeId: string | undefined,\n recipient: T[],\n ...nodes: T[]\n ): T[] {\n this._remove(...nodes);\n return this._addBefore(beforeId, recipient, ...nodes);\n }\n\n private _getPosition(\n id: string,\n ancestorsIndex: number[] = [],\n values = this._data\n ) {\n let indexList: number[];\n values.some((value, index) => {\n if (this.getId(value) === id) {\n indexList = ancestorsIndex.concat(index);\n return true;\n }\n\n const children = this.getChildren(value);\n if (children) {\n const groupIndexList = this._getPosition(\n id,\n ancestorsIndex.concat(index),\n children\n );\n if (groupIndexList) {\n indexList = groupIndexList;\n return true;\n }\n }\n\n return false;\n });\n return indexList;\n }\n\n private getAncestorAtPosition(position: number[]) {\n if (!position.length) {\n return this._data;\n }\n const node = this.getNodeByPosition(position);\n return this.getChildren(node);\n }\n\n /** Recursive */\n private sortDeep(data = this._data): T[] {\n data.forEach((node) => {\n const children = this.getChildren(node);\n if (children) {\n this.sortDeep(children);\n }\n });\n return this.sort(data);\n }\n\n private sort(children: T[]): T[] {\n const sorted = children.sort((a, b) => this.getLevel(a) - this.getLevel(b));\n return this.config.reverse ? sorted.reverse() : sorted;\n }\n\n /** Recursive */\n private _getNodeById(id: string, data = this._data): T {\n let node: T;\n data.some((item) => {\n if (this.getId(item) === id) {\n node = item;\n return true;\n }\n\n const children = this.getChildren(item);\n if (children) {\n node = this._getNodeById(id, children);\n if (node) {\n return true;\n }\n }\n\n return false;\n });\n return node;\n }\n\n getNodeByPosition(indexes: number[]): T {\n if (indexes.length > 1) {\n return indexes.reduce((previousValue: T, index) => {\n const ancestor = previousValue\n ? this.getChildren(previousValue)\n : this._data;\n return this._getByIndex(index, ancestor);\n }, null);\n } else {\n return this._getByIndex(indexes[0]);\n }\n }\n\n private _getByIndex(index: number, ancestor = this._data) {\n return ancestor[index];\n }\n\n private getNodeAncestor(node: T): T[] {\n const id = this.getId(node);\n return this.getAncestorById(id);\n }\n\n /** Recursive */\n private getAncestorById(id: string, data = this._data): T[] | undefined {\n let ancestor: T[];\n data.some((item) => {\n if (this.getId(item) === id) {\n ancestor = data;\n return true;\n }\n\n const children = this.getChildren(item);\n if (children) {\n ancestor = this.getAncestorById(id, children);\n if (ancestor) {\n return true;\n }\n }\n\n return false;\n });\n return ancestor;\n }\n\n /** Recursive */\n private flatten(nodes: T[]): T[] {\n return nodes.reduce((list, node) => {\n const children = this.getChildren(node);\n if (children) {\n const flattened = this.flatten(children);\n list.push(node, ...flattened);\n } else {\n list.push(node);\n }\n return list;\n }, [] as T[]);\n }\n\n private getIndex(id: string, ancestor: T[]): number {\n return ancestor.findIndex((node) => this.getId(node) === id);\n }\n}\n","export function S4() {\n return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);\n}\n\nexport function uuid() {\n const id = `${S4()}${S4()}-${S4()}-${S4()}-${S4()}-${S4()}${S4()}${S4()}`;\n return id.toLowerCase();\n}\n","import { Subject, Subscription } from 'rxjs';\nimport { distinctUntilChanged } from 'rxjs/operators';\n\nexport enum SubjectStatus {\n Error = 0,\n Done = 1,\n Working = 2,\n Waiting = 3\n}\n\nexport abstract class Watcher {\n public status$ = new Subject<SubjectStatus>();\n protected status$$: Subscription;\n\n get status(): SubjectStatus {\n return this._status;\n }\n set status(value: SubjectStatus) {\n this._status = value;\n this.status$.next(value);\n }\n private _status: SubjectStatus;\n\n protected abstract watch();\n\n protected abstract unwatch();\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n subscribe(callback: Function, scope?: any) {\n this.watch();\n\n this.status$$ = this.status$.pipe(distinctUntilChanged()).subscribe(() => {\n callback.call(scope, this);\n });\n }\n\n unsubscribe() {\n this.unwatch();\n if (this.status$$ !== undefined) {\n this.status$$.unsubscribe();\n this.status$$ = undefined;\n }\n this.status = SubjectStatus.Waiting;\n }\n}\n","/*\n * Public API Surface of utils\n */\n\nexport * from './lib';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public_api';\n"],"names":[],"mappings":";;;;;AAAA;AAEA,MAAM,KAAK,GACT,kEAAkE,CAAC;MAExD,MAAM,CAAA;AACT,IAAA,OAAO,OAAO,GAAW,GAAG,CAAC;AAC7B,IAAA,OAAO,KAAK,GAAW,KAAK,CAAC;AAE7B,IAAA,OAAO,OAAO,CAAC,CAAS,EAAE,CAAS,EAAA;QACzC,MAAM,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;AAC1B,QAAA,OAAO,CAAC,CAAC;KACV;AAEO,IAAA,OAAO,SAAS,CAAC,CAAS,EAAE,CAAS,EAAA;AAC3C,QAAA,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;AAC5C,QAAA,OAAO,GAAG,CAAC;KACZ;IAEM,OAAO,MAAM,CAAC,CAAS,EAAA;AAC5B,QAAA,IAAI,IAAI,GAAG,CAAC,EACV,CAAC,EACD,GAAG,EACH,IAAI,GAAG,CAAC,CAAC,MAAM,EACf,CAAC,GAAG,EAAE,CAAC;AAET,QAAA,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;AAEd,QAAA,IAAI,IAAI,KAAK,CAAC,EAAE;AACd,YAAA,OAAO,CAAC,CAAC;SACV;AAED,QAAA,IAAI,CAAC,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC,OAAO,EAAE;YACvC,IAAI,GAAG,CAAC,CAAC;AACT,YAAA,IAAI,CAAC,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC,OAAO,EAAE;gBACvC,IAAI,GAAG,CAAC,CAAC;aACV;YACD,IAAI,IAAI,CAAC,CAAC;SACX;AAED,QAAA,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,IAAI,CAAC,EAAE;YAC5B,GAAG;gBACD,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE;AAC3B,qBAAC,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;AAChC,qBAAC,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;oBAC/B,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;YAC3B,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,IAAI,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,IAAI,GAAG,EAAE,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC;SACrE;QAED,QAAQ,IAAI;AACV,YAAA,KAAK,CAAC;gBACJ,GAAG;oBACD,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE;AAC3B,yBAAC,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;AAChC,yBAAC,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;gBAClC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,IAAI,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC;gBACzD,MAAM;AACR,YAAA,KAAK,CAAC;AACJ,gBAAA,GAAG,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;AACtE,gBAAA,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC;gBACvC,MAAM;SACT;AAED,QAAA,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;KACnB;IAEM,OAAO,MAAM,CAAC,CAAS,EAAA;AAC5B,QAAA,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;QAEd,IAAI,CAAC,EACH,GAAG,EACH,CAAC,GAAG,EAAE,EACN,IAAI,GAAG,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AAEnC,QAAA,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE;AAClB,YAAA,OAAO,CAAC,CAAC;SACV;AAED,QAAA,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,IAAI,CAAC,EAAE;YAC5B,GAAG;gBACD,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE;AACzB,qBAAC,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;oBAC7B,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;AACzB,YAAA,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC;AACrC,YAAA,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AAC5C,YAAA,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;AAC3C,YAAA,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,GAAG,EAAE,CAAC,CAAC,CAAC;SACrC;AAED,QAAA,QAAQ,CAAC,CAAC,MAAM,GAAG,IAAI;AACrB,YAAA,KAAK,CAAC;gBACJ,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;AAC/B,gBAAA,CAAC,CAAC,IAAI,CACJ,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC;AAC1B,oBAAA,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,IAAI,EAAE,IAAI,EAAE,CAAC;AACnC,oBAAA,IAAI,CAAC,OAAO;oBACZ,IAAI,CAAC,OAAO,CACf,CAAC;gBACF,MAAM;AACR,YAAA,KAAK,CAAC;AACJ,gBAAA,GAAG,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AACjE,gBAAA,CAAC,CAAC,IAAI,CACJ,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC;AAC1B,oBAAA,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,IAAI,EAAE,IAAI,EAAE,CAAC;AACnC,oBAAA,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;oBAClC,IAAI,CAAC,OAAO,CACf,CAAC;gBACF,MAAM;SACT;AAED,QAAA,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;KACnB;;;AC7GG,SAAU,iBAAiB,CAAC,UAAqB,EAAA;AACrD,IAAA,OAAO,UAAU,CAAC,GAAG,CAAC,CAAC,KAAK,KAAI;AAC9B,QAAA,IAAI,KAAK,YAAY,UAAU,EAAE;AAC/B,YAAA,OAAO,KAAK,CAAC,QAAQ,EAAE,CAAC;SACzB;QACD,OAAO,KAAK,KAAK,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,GAAG,KAAK,CAAC;AACzE,KAAC,CAAC,CAAC;AACL;;ACHO,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,CACvC,MAAM,CAAC,SAAS,CAAC,SAAS;;MCLf,SAAS,CAAA;IACpB,OAAO,IAAI,CAAC,OAAqC,EAAA;QAC/C,IAAI,UAAU,GAAG,KAAK,CAAC;AACvB,QAAA,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE;YAC/B,MAAM,QAAQ,GAAG,SAAS,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;AACnD,YAAA,SAAS,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;AAC/B,YAAA,UAAU,GAAG,SAAS,CAAC,mBAAmB,EAAE,CAAC;AAC7C,YAAA,SAAS,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;SACrC;aAAM;AACL,YAAA,SAAS,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;AAC9B,YAAA,UAAU,GAAG,SAAS,CAAC,mBAAmB,EAAE,CAAC;SAC9C;AACD,QAAA,OAAO,UAAU,CAAC;KACnB;IAEO,OAAO,cAAc,CAAC,IAAY,EAAA;QACxC,MAAM,QAAQ,GAAG,QAAQ,CAAC,aAAa,CAAC,UAAU,CAAwB,CAAC;AAC3E,QAAA,QAAQ,CAAC,KAAK,GAAG,IAAI,CAAC;AACtB,QAAA,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;AACpC,QAAA,OAAO,QAAQ,CAAC;KACjB;IAEO,OAAO,eAAe,CAAC,QAAQ,EAAA;AACrC,QAAA,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;KACrC;IAEO,OAAO,UAAU,CAAC,QAAQ,EAAA;AAChC,QAAA,IAAI,SAAS,CAAC,SAAS,EAAE,KAAK,KAAK,EAAE;AACnC,YAAA,MAAM,kBAAkB,GAAG,QAAQ,CAAC,eAAe,CAAC;AACpD,YAAA,MAAM,WAAW,GAAG,QAAQ,CAAC,QAAQ,CAAC;AACtC,YAAA,MAAM,KAAK,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;AACrC,YAAA,MAAM,SAAS,GAAG,MAAM,CAAC,YAAY,EAAE,CAAC;AAExC,YAAA,QAAQ,CAAC,eAAe,GAAG,IAAI,CAAC;AAChC,YAAA,QAAQ,CAAC,QAAQ,GAAG,KAAK,CAAC;AAC1B,YAAA,KAAK,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC;YACnC,SAAS,CAAC,eAAe,EAAE,CAAC;AAC5B,YAAA,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AAC1B,YAAA,QAAQ,CAAC,iBAAiB,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;AACtC,YAAA,QAAQ,CAAC,eAAe,GAAG,kBAAkB,CAAC;AAC9C,YAAA,QAAQ,CAAC,QAAQ,GAAG,WAAW,CAAC;SACjC;aAAM;YACL,QAAQ,CAAC,MAAM,EAAE,CAAC;SACnB;KACF;AAEO,IAAA,OAAO,mBAAmB,GAAA;AAChC,QAAA,IAAI,EAAE,SAAS,CAAC,SAAS,EAAE,KAAK,KAAK,IAAI,SAAS,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,EAAE;AACzE,YAAA,OAAO,QAAQ,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;SACrC;AACD,QAAA,OAAO,KAAK,CAAC;KACd;AACF;;AClDD,SAAS,SAAS,CAAC,CAAS,EAAE,WAAmB,EAAE,MAAc,EAAA;IAC/D,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,MAAM,IAAI,CAAC,CAAC;AAC/B,IAAA,OAAO,CAAC,CAAC,IAAI,WAAW,IAAI,IAAI,CAAC;AACnC,CAAC;MAEY,WAAW,CAAA;AACd,IAAA,WAAW,GAAG,IAAI,GAAG,EAAkB,CAAC;AACxC,IAAA,WAAW,GAAG,IAAI,GAAG,EAAkB,CAAC;AAEhD,IAAA,WAAA,GAAA;QACE,IAAI,CAAC,mBAAmB,EAAE,CAAC;KAC5B;IAEO,mBAAmB,GAAA;;;AAGzB,QAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE;YAC3B,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YACpE,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;SACrE;;AAED,QAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE;YAC3B,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC;YACzE,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;SAC1E;;AAED,QAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE;YAC3B,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC;YACzE,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;SAC1E;;QAED,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QAC9B,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QAC9B,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;QAC9B,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;KAC/B;AAED,IAAA,YAAY,CAAC,IAAU,EAAA;QACrB,IAAI,CAAC,IAAI,EAAE;YACT,OAAO;SACR;QAED,MAAM,UAAU,GAAG,IAAI,UAAU,CAAC,CAAC,QAAkC,KAAI;AACvE,YAAA,MAAM,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;AAChC,YAAA,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;AAC3B,YAAA,MAAM,CAAC,MAAM,GAAG,MAAK;gBACnB,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,EAAY,CAAC;AACjD,gBAAA,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;gBACtD,MAAM,UAAU,GAAG,IAAI,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC;AACrD,gBAAA,MAAM,cAAc,GAAmB;oBACrC,MAAM,EAAE,MAAM,CAAC,MAAM;oBACrB,IAAI,EAAE,IAAI,CAAC,IAAI;AACf,oBAAA,MAAM,EAAE,UAAU;iBACnB,CAAC;AACF,gBAAA,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;AAChC,aAAC,CAAC;AACJ,SAAC,CAAC,CAAC;AACH,QAAA,OAAO,UAAU,CAAC;KACnB;AAED,IAAA,cAAc,CAAC,cAA8B,EAAA;AAC3C,QAAA,MAAM,MAAM,GAAG,cAAc,CAAC,MAAM,CAAC;AACrC,QAAA,MAAM,MAAM,GAAG,cAAc,CAAC,MAAM,CAAC;QACrC,MAAM,YAAY,GAAW,IAAI,CAAC,sBAAsB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACzE,QAAA,MAAM,cAAc,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC;QAC1C,MAAM,WAAW,GAAG,IAAI,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;AACrD,QAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,cAAc,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;YAC9C,WAAW,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;SAC/C;AACD,QAAA,MAAM,SAAS,GAAG,IAAI,UAAU,CAAC,WAAW,CAAC,CAAC;AAC9C,QAAA,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC,SAAS,CAAC,EAAE,EAAE,IAAI,EAAE,cAAc,CAAC,IAAI,EAAE,CAAC,CAAC;AAClE,QAAA,OAAO,IAAI,CAAC;KACb;AAEO,IAAA,oBAAoB,CAAC,CAAS,EAAA;QACpC,IAAI,GAAG,GAAG,EAAE,CAAC;QACb,IAAI,IAAI,GAAG,EAAE,CAAC;QACd,IAAI,GAAG,GAAG,CAAC,CAAC;QACZ,IAAI,GAAG,GAAG,CAAC,CAAC;AACZ,QAAA,KAAK,MAAM,CAAC,IAAI,CAAC,EAAE;YACjB,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AACtC,YAAA,IAAI,IAAI,GAAG,CAAC,EAAE;gBACZ,IAAI,IAAI,CAAC,CAAC;AACV,gBAAA,GAAG,IAAI,KAAK,IAAI,IAAI,CAAC;aACtB;iBAAM;AACL,gBAAA,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC;AACf,gBAAA,GAAG,IAAI,KAAK,IAAI,GAAG,CAAC;AACpB,gBAAA,GAAG,IAAI,MAAM,CAAC,Y