@esmalley/ts-utils 6.4.6 → 7.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +435 -24
- package/dist/cjs/index.js +7 -7
- package/dist/cjs/index.js.map +4 -4
- package/dist/esm/index.js +7 -7
- package/dist/esm/index.js.map +4 -4
- package/dist/types/Arithmetic.d.ts +92 -0
- package/dist/types/Arithmetic.d.ts.map +1 -1
- package/dist/types/Arrayifier.d.ts +83 -6
- package/dist/types/Arrayifier.d.ts.map +1 -1
- package/dist/types/CSV.d.ts +14 -0
- package/dist/types/CSV.d.ts.map +1 -1
- package/dist/types/Color.d.ts +21 -5
- package/dist/types/Color.d.ts.map +1 -1
- package/dist/types/Dates.d.ts +39 -0
- package/dist/types/Dates.d.ts.map +1 -1
- package/dist/types/Kontororu/Socket.d.ts.map +1 -1
- package/dist/types/Kontororu/Store.d.ts.map +1 -1
- package/dist/types/Kontororu.d.ts +12 -5
- package/dist/types/Kontororu.d.ts.map +1 -1
- package/dist/types/Numbers.d.ts +78 -0
- package/dist/types/Numbers.d.ts.map +1 -0
- package/dist/types/Objector.d.ts +14 -0
- package/dist/types/Objector.d.ts.map +1 -1
- package/dist/types/Sorter.d.ts.map +1 -1
- package/dist/types/Style.d.ts.map +1 -1
- package/dist/types/Tasker.d.ts +109 -0
- package/dist/types/Tasker.d.ts.map +1 -0
- package/dist/types/Textor.d.ts +10 -0
- package/dist/types/Textor.d.ts.map +1 -1
- package/dist/types/Toaster.d.ts +26 -1
- package/dist/types/Toaster.d.ts.map +1 -1
- package/dist/types/UuidService.d.ts +7 -0
- package/dist/types/UuidService.d.ts.map +1 -1
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +7 -2
package/dist/esm/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../../src/Arithmetic.ts", "../../src/Arrayifier.ts", "../../src/CSV.ts", "../../src/Color.ts", "../../src/Dates.ts", "../../src/Kontororu.ts", "../../src/Kontororu/Socket.ts", "../../src/Objector.ts", "../../src/Kontororu/Store.ts", "../../src/Sorter.ts", "../../src/
|
|
4
|
-
"sourcesContent": ["/*\n * Copyright 2026 Evan Smalley.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n */\n\nexport class Arithmetic {\n public static clamp(number: number, min: number, max: number): number {\n return Math.max(min, Math.min(number, max));\n }\n}\n\n", "/*\n * Copyright 2026 Evan Smalley.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n */\n\nexport class Arrayifier {\n // constructor() {\n // }\n\n\n /**\n * Shuffle / ranomize elements in an array\n * @param {array} array The array to shuffle\n * @return array\n */\n public static shuffle<T>(array: T[]): T[] {\n let currentIndex: number = array.length;\n let randomIndex: number;\n\n // While there remain elements to shuffle.\n while (currentIndex !== 0) {\n // Pick a remaining element.\n randomIndex = Math.floor(Math.random() * currentIndex);\n currentIndex--;\n\n // And swap it with the current element.\n // eslint-disable-next-line no-param-reassign\n [array[currentIndex], array[randomIndex]] = [\n array[randomIndex], array[currentIndex]];\n }\n\n return array;\n }\n\n /**\n * Recursively generates all combinations of size `r` from an array of `n` elements.\n *\n * @param {T[]} arr - The source array to generate combinations from\n * @param {number} n - The total number of elements in `arr` (i.e. arr.length)\n * @param {number} r - The size of each combination to generate\n * @param {number} index - Current position being filled in the combination (increments toward r)\n * @param {T[]} data - Temporary buffer holding the current combination being built\n * @param {number} i - Current index in `arr` being considered for inclusion\n * @param {T[][]} results - Accumulator array that collects each completed combination\n * @returns {T[][]} The accumulated list of all combinations once recursion completes\n *\n * @example\n * combination([1, 2, 3], 3, 2, 0, [], 0, [])\n * // returns [[1, 2], [1, 3], [2, 3]]\n */\n public static combination<T>(\n arr: T[],\n n: number,\n r: number,\n index: number,\n data: T[],\n i: number,\n results: T[][],\n ): T[][] {\n if (index === r) {\n results.push(data.slice(0, r));\n return results;\n }\n\n if (i >= n) {\n return results;\n }\n\n // eslint-disable-next-line no-param-reassign\n data[index] = arr[i];\n this.combination(arr, n, r, index + 1, data, i + 1, results);\n this.combination(arr, n, r, index, data, i + 1, results);\n\n return results;\n }\n\n /**\n * Get all combinations of every value in the provided array for a specified number\n * @param {Array} arr\n * @param {number} n\n * @param {number} r\n * @returns Array\n */\n public static getCombinations<T>(arr: T[], n: number, r: number): T[][] {\n const data: T[] = new Array(r);\n\n let results: T[][] = [];\n results = this.combination(arr, n, r, 0, data, 0, results);\n return results;\n }\n}\n", "/*\n * Copyright 2026 Evan Smalley.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n */\n\n/**\n * Everything to help with CSV generation\n */\nexport class CSV {\n /**\n * Convert an object to a CSV file and then download it\n */\n public static download(data: Record<string, Record<string, unknown>>): void {\n const rows: string[] = [];\n\n let setHeaders = false;\n let headers: string[] = [];\n for (const id in data) {\n const row = data[id];\n\n if (!setHeaders) {\n headers = Object.keys(row);\n rows.push(headers.join(','));\n setHeaders = true;\n }\n\n const values = headers.map((header) => JSON.stringify(row[header] || ''));\n rows.push(values.join(','));\n }\n\n const content = rows.join('\\n');\n\n // Create a Blob and trigger download\n const blob = new Blob([content], { type: 'text/csv' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = 'srating-data.csv';\n\n // Trigger download and clean up\n document.body.appendChild(a);\n a.click();\n URL.revokeObjectURL(url);\n a.remove();\n }\n}\n", "/* eslint-disable no-param-reassign */\n/* eslint-disable default-case */\n/* eslint-disable no-multi-assign */\n/*\n * Copyright 2026 Evan Smalley.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n */\n\n/* eslint-disable no-mixed-operators */\n/* eslint-disable no-bitwise */\n\n\nexport class Color {\n // constructor() {\n // }\n\n\n /**\n * A linear interpolator for hexadecimal colors\n * @param {string} a\n * @param {string} b\n * @param {number} amount\n * @example\n * // returns #7F7F7F\n * lerpColor('#000000', '#ffffff', 0.5)\n * @return {string}\n */\n public static lerpColor(a: string, b: string, amount: number): string {\n const ah = +a.replace('#', '0x');\n const ar = ah >> 16;\n const ag = ah >> 8 & 0xff;\n const ab = ah & 0xff;\n\n const bh = +b.replace('#', '0x');\n const br = bh >> 16;\n const bg = bh >> 8 & 0xff;\n const bb = bh & 0xff;\n\n const rr = ar + amount * (br - ar);\n const rg = ag + amount * (bg - ag);\n const rb = ab + amount * (bb - ab);\n\n return `#${((1 << 24) + (rr << 16) + (rg << 8) + rb | 0).toString(16).slice(1)}`;\n }\n\n /**\n * Get a color that will look readable based on a background color\n */\n public static getTextColor(color: string, backgroundColor: string, debug = false): string {\n // Convert hex colors to RGB\n /*\n let [r1, g1, b1] = Color.hexToRgb(color);\n const [r2, g2, b2] = Color.hexToRgb(backgroundColor);\n\n const brightnessBg = Color.calculateBrightness(r2, g2, b2);\n\n const targetBrightness = brightnessBg > 128 ? 50 : 150; // target brightness threshold for contrast\n\n while (true) {\n const brightnessColor = Color.calculateBrightness(r1, g1, b1);\n\n if (\n (brightnessBg > 128 && brightnessColor < targetBrightness) ||\n (brightnessBg <= 128 && brightnessColor > targetBrightness)\n ) {\n break;\n }\n\n if (brightnessBg > 128) {\n r1 = Math.max(0, r1 - 25);\n g1 = Math.max(0, g1 - 25);\n b1 = Math.max(0, b1 - 25);\n } else {\n r1 = Math.min(255, r1 + 25);\n g1 = Math.min(255, g1 + 25);\n b1 = Math.min(255, b1 + 25);\n }\n\n if ((r1 === 0 && g1 === 0 && b1 === 0) || (r1 === 255 && g1 === 255 && b1 === 255)) {\n break; // avoid infinite loop\n }\n }\n\n // Convert back to hex\n return Color.rgbToHex(r1, g1, b1);\n */\n let [r, g, b] = Color.hexToRgb(color);\n const [br, bg, bb] = Color.hexToRgb(backgroundColor);\n const contrastTarget = 4.5;\n\n if (debug) {\n console.log('Color.getContrastRatio([r, g, b], [br, bg, bb])', Color.getContrastRatio([r, g, b], [br, bg, bb]));\n }\n\n if (Color.getContrastRatio([r, g, b], [br, bg, bb]) >= contrastTarget) {\n return Color.rgbToHex(r, g, b);\n }\n\n const contrastToBlack = Color.getContrastRatio([0, 0, 0], [br, bg, bb]);\n const contrastToWhite = Color.getContrastRatio([255, 255, 255], [br, bg, bb]);\n\n const direction: 'lighter' | 'darker' =\n contrastToWhite > contrastToBlack ? 'lighter' : 'darker';\n\n\n if (debug) {\n console.log('contrastToBlack', contrastToBlack);\n console.log('contrastToWhite', contrastToWhite);\n console.log('direction', direction);\n }\n\n const adjust = (c: number, lighter: boolean) => {\n return lighter ? Math.min(255, c + 10) : Math.max(0, c - 10);\n };\n\n for (let i = 0; i < 25; i++) {\n r = adjust(r, direction === 'lighter');\n g = adjust(g, direction === 'lighter');\n b = adjust(b, direction === 'lighter');\n\n if (debug) {\n console.log('Color.getContrastRatio([r, g, b], [br, bg, bb]) 2', Color.getContrastRatio([r, g, b], [br, bg, bb]));\n }\n\n if (Color.getContrastRatio([r, g, b], [br, bg, bb]) >= contrastTarget) {\n break;\n }\n }\n\n return Color.rgbToHex(r, g, b);\n }\n\n public static getContrastRatio(rgb1: [number, number, number], rgb2: [number, number, number]): number {\n const luminance = (r: number, g: number, b: number): number => {\n const a = [r, g, b].map((v) => {\n v /= 255;\n return v <= 0.03928\n ? v / 12.92\n : Math.pow((v + 0.055) / 1.055, 2.4);\n });\n return a[0] * 0.2126 + a[1] * 0.7152 + a[2] * 0.0722;\n };\n\n const lum1 = luminance(...rgb1) + 0.05;\n const lum2 = luminance(...rgb2) + 0.05;\n\n return lum1 > lum2 ? lum1 / lum2 : lum2 / lum1;\n }\n\n /**\n * Take a hex (#fff) and an amount and darken the color, return a hex\n * @param {string} hex\n * @param {number} amount\n * @return {string} hex\n */\n // public static darken(hex: string, amount: number = 0.02): string {\n // const [r, g, b] = this.hexToRgb(hex);\n // const [h, s, l] = this.rgbToHsl(r, g, b);\n\n // const newL = Math.max(0, (l / 100) - amount) * 100;\n // const [r2, g2, b2] = this.hslToRgb(h, s, newL);\n\n // return this.rgbToHex(r2, g2, b2);\n // }\n\n /**\n * Take a hex (#fff) and an amount and lighten the color, return a hex\n * @param {string} hex\n * @param {number} amount\n * @return {string} hex\n */\n // public static lighten(hex: string, amount: number = 0.02): string {\n // const [r, g, b] = this.hexToRgb(hex);\n // const [h, s, l] = this.rgbToHsl(r, g, b);\n\n // const newL = Math.min(1, (l / 100) + amount) * 100;\n // const [r2, g2, b2] = this.hslToRgb(h, s, newL);\n\n // return this.rgbToHex(r2, g2, b2);\n // }\n\n /**\n * Mixes the color with black to create a Shade.\n * Prevents the \"muddy/brown\" look of HSL darkening.\n * @param {string} hex - The color to darken\n * @param {number} amount - 0 to 1 (e.g. 0.1 is 10% darker)\n * @return {string} hex\n */\n public static darken(hex: string, amount: number = 0.1): string {\n const [r, g, b] = this.hexToRgb(hex);\n\n // Calculate new color by mixing with black (0)\n // Formula: Current * (1 - amount)\n const remaining = 1 - amount;\n const r2 = Math.round(r * remaining);\n const g2 = Math.round(g * remaining);\n const b2 = Math.round(b * remaining);\n\n return this.rgbToHex(r2, g2, b2);\n }\n\n /**\n * Mixes the color with white to create a Tint.\n * cleaner and less \"washed out\" than HSL lightness adjustment.\n * @param {string} hex - The color to lighten\n * @param {number} amount - 0 to 1 (e.g. 0.1 is 10% lighter)\n * @return {string} hex\n */\n public static lighten(hex: string, amount: number = 0.1): string {\n const [r, g, b] = this.hexToRgb(hex);\n\n // Calculate new color by mixing with white (255)\n // Formula: Current + ((Target - Current) * amount)\n const r2 = Math.round(r + (255 - r) * amount);\n const g2 = Math.round(g + (255 - g) * amount);\n const b2 = Math.round(b + (255 - b) * amount);\n\n return this.rgbToHex(r2, g2, b2);\n }\n\n\n public static shadeColor(hex: string, percent: number): string {\n let [r, g, b] = Color.hexToRgb(hex);\n\n r = Math.min(255, Math.max(0, Math.round(r + (r * (percent / 100)))));\n g = Math.min(255, Math.max(0, Math.round(g + (g * (percent / 100)))));\n b = Math.min(255, Math.max(0, Math.round(b + (b * (percent / 100)))));\n\n return Color.rgbToHex(r, g, b);\n }\n\n\n /**\n * Are 2 colors similar to each other?\n * @param {string} color1\n * @param {string} color2\n * @param {number} threshold\n * @return {boolean}\n */\n public static areColorsSimilar(color1: string, color2: string, threshold = 50): boolean {\n const distance = Color.colorDistance(color1, color2);\n return distance < threshold;\n }\n\n\n /**\n * Inverts a hex color\n * @param {string} hex\n * @return {string} hex\n */\n public static invertColor(hex: string): string {\n const [r, g, b] = Color.hexToRgb(hex);\n\n // Invert each color component\n const invertedR = 255 - r;\n const invertedG = 255 - g;\n const invertedB = 255 - b;\n\n return Color.rgbToHex(invertedR, invertedG, invertedB);\n }\n\n\n /**\n * Takes a hex (#fff) and returns an rgba with the provided alpha\n * @param {string} hex\n * @param {number} alpha\n * @return {string} rgba()\n */\n public static alphaColor(hex: string, alpha: number): string {\n const [r, g, b] = this.hexToRgb(hex);\n\n return `rgba(${r}, ${g}, ${b}, ${alpha})`;\n }\n\n\n /**\n * Gets analogous colors\n * @param {string} hex\n * @return {Array<string>}\n */\n public static getAnalogousColors(hex: string): string[] {\n const [r, g, b] = Color.hexToRgb(hex);\n const [h, s, l] = Color.rgbToHsl(r, g, b);\n\n const analogousColors: string[] = [];\n const offset = 30; // Offset for analogous colors, usually 30 degrees\n\n for (let i = -1; i <= 1; i++) {\n if (i !== 0) {\n const newHue = (h + i * offset + 360) % 360;\n const [newR, newG, newB] = Color.hslToRgb(newHue, s, l);\n analogousColors.push(Color.rgbToHex(newR, newG, newB));\n }\n }\n\n return analogousColors;\n }\n\n\n /**\n * Convert hex to rgb\n * @param {string} hex\n * @return {Array} rgb\n */\n public static hexToRgb(hex: string): Array<number> {\n // Remove the hash at the start if it's there\n let h = hex.replace(/^#/, '');\n\n // Handle 3-character hex codes by expanding them to 6-character\n if (h.length === 3) {\n h = h.split('').map((char) => { return char + char; }).join('');\n }\n\n // Ensure it's a valid 6-character hex code\n if (h.length !== 6) {\n throw new Error(`Invalid hex color format: ${hex}`);\n }\n\n // Parse r, g, b values\n const bigint = parseInt(h, 16);\n const r = (bigint >> 16) & 255;\n const g = (bigint >> 8) & 255;\n const b = bigint & 255;\n\n return [r, g, b];\n }\n\n\n /**\n * Convert rgb to hex\n * @param {number} r\n * @param {number} g\n * @param {number} b\n * @return {string}\n */\n private static rgbToHex(r: number, g: number, b: number): string {\n return `#${((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1).toUpperCase()}`;\n }\n\n private static rgbToHsl(r: number, g: number, b: number) {\n r /= 255;\n g /= 255;\n b /= 255;\n const max = Math.max(r, g, b);\n const min = Math.min(r, g, b);\n let h = 0;\n let s = 0;\n const l = (max + min) / 2;\n\n if (max === min) {\n h = s = 0; // achromatic\n } else {\n const d = max - min;\n s = l > 0.5 ? d / (2 - max - min) : d / (max + min);\n switch (max) {\n case r: h = (g - b) / d + (g < b ? 6 : 0); break;\n case g: h = (b - r) / d + 2; break;\n case b: h = (r - g) / d + 4; break;\n }\n h /= 6;\n }\n return [h * 360, s * 100, l * 100];\n }\n\n private static hslToRgb(h: number, s: number, l: number) {\n let r;\n let g;\n let b;\n h /= 360;\n s /= 100;\n l /= 100;\n\n if (s === 0) {\n r = g = b = l; // achromatic\n } else {\n const hue2rgb = (p: number, q: number, t: number) => {\n if (t < 0) t += 1;\n if (t > 1) t -= 1;\n if (t < 1 / 6) return p + (q - p) * 6 * t;\n if (t < 1 / 3) return q;\n if (t < 1 / 2) return p + (q - p) * (2 / 3 - t) * 6;\n return p;\n };\n\n const q = l < 0.5 ? l * (1 + s) : l + s - l * s;\n const p = 2 * l - q;\n r = hue2rgb(p, q, h + 1 / 3);\n g = hue2rgb(p, q, h);\n b = hue2rgb(p, q, h - 1 / 3);\n }\n\n return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];\n }\n\n private static calculateBrightness(r: number, g: number, b: number): number {\n // Calculate the brightness of the color\n return (r * 299 + g * 587 + b * 114) / 1000;\n }\n\n private static colorDistance(color1: string, color2: string): number {\n const [r1, g1, b1] = Color.hexToRgb(color1);\n const [r2, g2, b2] = Color.hexToRgb(color2);\n\n const dr = r1 - r2;\n const dg = g1 - g2;\n const db = b1 - b2;\n\n return Math.sqrt(dr * dr + dg * dg + db * db);\n }\n}\n", "/*\n * Copyright 2026 Evan Smalley.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n */\n\n/* eslint-disable one-var-declaration-per-line */\n/* eslint-disable one-var */\n\nimport { IANATimeZone } from './Timezones.js';\n\n\nexport class Dates {\n // constructor() {\n // }\n\n /*\n * Robust Date Parsing\n * Handles:\n * - Date Objects / Numbers (Timestamps)\n * - ISO Strings (2025-01-01) -> Forces Local Midnight\n * - US Formats (01/05/2026)\n * - Mixed Time Formats (23:00 pm, 5:00pm, 14:30:00)\n */\n public static parse(\n str?: Date | string | number | undefined | null,\n utc = false,\n ): Date {\n // 1. Handle Null / Undefined -> Return Now\n if (!str) {\n return new Date();\n }\n\n // 2. Handle Existing Date Objects -> Return Copy\n if (str instanceof Date) {\n return new Date(str.getTime());\n }\n\n // 3. Handle Timestamps (Numbers)\n if (typeof str === 'number') {\n return new Date(str);\n }\n\n // 4. Handle Strings\n if (typeof str === 'string') {\n const input = str.trim();\n\n // CASE A: Strict ISO Date \"YYYY-MM-DD\"\n // Native JS parses this as UTC Midnight, which often shows as\n // previous day 7pm EST. We force \"T00:00:00\" to make it Local Midnight.\n if (/^\\d{4}-\\d{2}-\\d{2}$/.test(input)) {\n return utc ? new Date(`${input}T00:00:00Z`) : new Date(`${input}T00:00:00`);\n }\n\n // CASE B: Manual Parsing for Complex Strings\n // This handles \"2026-01-05 23:03:19 pm\", \"01/05/2026\", etc.\n\n // Step 1: Extract Date Part (YYYY-MM-DD or MM/DD/YYYY)\n // Regex looks for: (Group 1: Year/Month) -or/ (Group 2: Month/Day) -or/ (Group 3: Day/Year)\n let year, month, day, timePart = '';\n\n // Match YYYY-MM-DD or YYYY/MM/DD\n const isoMatch = input.match(/^(\\d{4})[-/](\\d{1,2})[-/](\\d{1,2})(.*)$/);\n\n // Match MM/DD/YYYY or MM-DD-YYYY\n const usMatch = input.match(/^(\\d{1,2})[-/](\\d{1,2})[-/](\\d{4})(.*)$/);\n\n if (isoMatch) {\n year = parseInt(isoMatch[1], 10);\n month = parseInt(isoMatch[2], 10) - 1; // JS Months are 0-11\n day = parseInt(isoMatch[3], 10);\n timePart = isoMatch[4];\n } else if (usMatch) {\n year = parseInt(usMatch[3], 10);\n month = parseInt(usMatch[1], 10) - 1;\n day = parseInt(usMatch[2], 10);\n timePart = usMatch[4];\n } else {\n // Fallback: Let the browser try its best if our regex fails\n const d = new Date(input);\n return isNaN(d.getTime()) ? new Date() : d;\n }\n\n // Step 2: Extract Time Part\n let hours = 0;\n let minutes = 0;\n let seconds = 0;\n\n // Look for HH:MM(:SS) and optional AM/PM in the remaining string\n if (timePart && timePart.trim().length > 0) {\n // Matches: 23:03, 23:03:19, 5:00pm, 5:00 pm\n const timeMatch = timePart.match(/(\\d{1,2}):(\\d{1,2})(?::(\\d{1,2}))?\\s*(am|pm|AM|PM)?/);\n\n if (timeMatch) {\n hours = parseInt(timeMatch[1], 10);\n minutes = parseInt(timeMatch[2], 10);\n seconds = timeMatch[3] ? parseInt(timeMatch[3], 10) : 0;\n const meridiem = timeMatch[4] ? timeMatch[4].toLowerCase() : null;\n\n // Step 3: Normalize Hours (12h to 24h)\n if (meridiem === 'pm' && hours < 12) {\n hours += 12;\n }\n if (meridiem === 'am' && hours === 12) {\n hours = 0;\n }\n // Note: If input is \"23:00 pm\", we ignore the 'pm' because 23 > 12.\n }\n }\n\n if (utc) {\n return new Date(Date.UTC(year, month, day, hours, minutes, seconds));\n }\n\n // Step 4: Construct Date in Local Time\n return new Date(year, month, day, hours, minutes, seconds);\n }\n\n return new Date();\n }\n\n public static getMonthsShort(): string[] {\n return ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];\n }\n\n public static getMonths(): string[] {\n return ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];\n }\n\n public static getDaysShort(): string[] {\n return ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];\n }\n\n public static getDays(): string[] {\n return ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];\n }\n\n /**\n * Format a date using php syntax\n *\n | Token | Meaning | Example |\n | ----- | ------------------------- | ------- |\n | `Y` | 4-digit year | 2025 |\n | `y` | 2-digit year | 25 |\n | `m` | 2-digit month | 03 |\n | `n` | month (no leading zero) | 3 |\n | `d` | day (2-digit) | 09 |\n | `j` | day (no leading zero) | 9 |\n | `S` | Ordinal suffix | th |\n | `H` | 24-hour | 14 |\n | `G` | 24-hour (no leading zero) | 14 |\n | `h` | 12-hour | 02 |\n | `g` | 12-hour (no leading zero) | 2 |\n | `i` | minutes | 05 |\n | `s` | seconds | 09 |\n | `A` | AM/PM | PM |\n | `a` | am/pm | pm |\n | `w` | day of week (0\u20136) | 1 |\n | `N` | day of week (1\u20137) | 2 |\n | `M` | short month name | Mar |\n | `F` | full month name | March |\n | `D` | short weekday | Mon |\n | `l` | full weekday | Monday |\n | `T` | Timezone abbreviation | EST |\n | `e` | Timezone identifier | America/New_York |\n */\n public static format(dateInput: Date | string, format: string, utc = false): string {\n const date = this.parse(dateInput);\n const pad = (n: number) => String(n).padStart(2, '0');\n\n const monthsShort = this.getMonthsShort();\n const monthsLong = this.getMonths();\n const daysShort = this.getDaysShort();\n const daysLong = this.getDays();\n\n const Y = utc ? date.getUTCFullYear() : date.getFullYear();\n const y = String(Y).slice(-2);\n const month = utc ? date.getUTCMonth() : date.getMonth();\n const dateNum = utc ? date.getUTCDate() : date.getDate();\n const day = utc ? date.getUTCDay() : date.getDay();\n const hours = utc ? date.getUTCHours() : date.getHours();\n const minutes = utc ? date.getUTCMinutes() : date.getMinutes();\n const seconds = utc ? date.getUTCSeconds() : date.getSeconds();\n\n // Dynamically look up current runtime/system timezone strings\n const tzAbbr = utc\n ? 'UTC'\n : new Intl.DateTimeFormat('en-US', { timeZoneName: 'short' })\n .format(date)\n .split(', ')\n .pop() || '';\n\n const tzIdentifier = utc\n ? 'UTC'\n : new Intl.DateTimeFormat('en-US', { timeZoneName: 'long' })\n .resolvedOptions().timeZone || '';\n\n // Logic for ordinal suffix (st, nd, rd, th)\n const getOrdinalSuffix = (n: number) => {\n const v = n % 100;\n // 11th, 12th, 13th are exceptions to the 1st, 2nd, 3rd rule\n if (v >= 11 && v <= 13) {\n return 'th';\n }\n\n switch (n % 10) {\n case 1: {\n return 'st';\n }\n case 2: {\n return 'nd';\n }\n case 3: {\n return 'rd';\n }\n default: {\n return 'th';\n }\n }\n };\n\n const tokens: Record<string, string> = {\n /// Year\n Y: String(Y),\n y,\n\n // Month\n m: pad(month + 1),\n n: String(month + 1),\n M: monthsShort[month],\n F: monthsLong[month],\n\n // Day\n d: pad(dateNum),\n j: String(dateNum),\n D: daysShort[day],\n l: daysLong[day],\n w: String(day), // 0 (Sun) - 6\n N: String(day === 0 ? 7 : day), // 1 (Mon) - 7 (Sun)\n S: getOrdinalSuffix(dateNum),\n\n // Time\n H: pad(hours),\n G: String(hours),\n h: pad(((hours + 11) % 12) + 1),\n g: String(((hours + 11) % 12) + 1),\n i: pad(minutes),\n s: pad(seconds),\n\n // AM/PM\n A: hours < 12 ? 'AM' : 'PM',\n a: hours < 12 ? 'am' : 'pm',\n\n // Timezone\n T: tzAbbr,\n e: tzIdentifier,\n };\n\n // Replace tokens using regex\n return format.replace(/\\\\(.)|([a-zA-Z])/g, (_, esc, token) => {\n if (esc) {\n // literal escaped char like \\H or \\Y \u2192 return the raw letter\n return esc;\n }\n return tokens[token] ?? token;\n });\n }\n\n public static add(date: Date | string, amount: number, unit: 'years' | 'months' | 'days' | 'hours' | 'minutes'): Date {\n const d = this.parse(date);\n\n if (unit === 'years') {\n const originalDay = d.getDate();\n d.setFullYear(d.getFullYear() + amount);\n // Handle Leap Year Rollover:\n // Feb 29, 2024 + 1 year -> Mar 1, 2025 (Standard JS behavior)\n // If strict \"same day or last day of month\" logic is desired (turning it into Feb 28):\n if (d.getDate() !== originalDay) {\n d.setDate(0); // Set to last day of previous month (Feb 28)\n }\n } else if (unit === 'months') {\n const originalDay = d.getDate();\n d.setMonth(d.getMonth() + amount);\n // Handle rollover: Jan 31 + 1 month -> Feb 28/29\n if (d.getDate() !== originalDay) {\n d.setDate(0); // Set to last day of previous month\n }\n } else if (unit === 'days') {\n // Use setDate to be DST safe (24h addition via ms is unsafe across DST)\n d.setDate(d.getDate() + amount);\n } else {\n const map: Record<'hours' | 'minutes', number> = {\n hours: amount * 60 * 60 * 1000,\n minutes: amount * 60 * 1000,\n };\n // Use getTime() for day/hour/minute units for simple millisecond addition\n d.setTime(d.getTime() + map[unit]);\n }\n\n return d;\n }\n\n public static subtract(\n date: Date | string,\n amount: number,\n unit: 'years' | 'months' | 'days' | 'hours' | 'minutes',\n ): Date {\n return this.add(date, -amount, unit);\n }\n\n public static fromNow(date: Date | string): string {\n const d = this.parse(date);\n const diff = Date.now() - d.getTime();\n const mins = Math.floor(diff / 60000);\n\n if (Math.abs(mins) < 1) {\n return 'just now';\n }\n\n // Handle future dates roughly\n if (mins < 0) {\n return 'in the future';\n }\n\n if (mins < 60) {\n return `${mins}m ago`;\n }\n\n const hours = Math.floor(mins / 60);\n\n if (hours < 24) {\n return `${hours}h ago`;\n }\n\n const days = Math.floor(hours / 24);\n\n return `${days}d ago`;\n }\n\n /**\n * Find the closest date in an array of dates\n */\n public static getClosestDate(dateToMatch: string | Date, datesArray: string[]): string | null {\n if (!datesArray.length) {\n return null;\n }\n\n const matchDate = this.parse(dateToMatch).getTime();\n\n let closestDate: string | null = null;\n let closestDist = Infinity;\n\n // eslint-disable-next-line no-restricted-syntax\n for (const dateStr of datesArray) {\n const currDate = this.parse(dateStr).getTime();\n const dist = Math.abs(currDate - matchDate);\n\n if (dist < closestDist) {\n closestDist = dist;\n closestDate = dateStr;\n } else if (dist === closestDist) {\n // Tie-breaker: Prefer the date that is in the future relative to the matchDate\n // Or if both are same direction, just keep the current one (or implementation defined)\n // Requirement: \"Both 17th and 19th have same dist. It should pick 19th\"\n if (currDate > matchDate) {\n closestDate = dateStr;\n }\n }\n }\n\n return closestDate;\n }\n\n public static getTodayEST(): string {\n return this.format(new Date().toLocaleString('en-US', { timeZone: 'America/New_York' }), 'Y-m-d');\n }\n\n public static getStartOfDay(date: Date | string): Date {\n const d = this.parse(date);\n d.setHours(0, 0, 0, 0);\n return d;\n }\n\n public static getStartOfMonth(date: Date | string): Date {\n const d = this.parse(date);\n d.setDate(1);\n d.setHours(0, 0, 0, 0);\n return d;\n }\n\n public static getStartOfGrid(date: Date | string): Date {\n const d = this.getStartOfMonth(date);\n const dayOfWeek = d.getDay(); // 0 (Sunday) is the start in standard JS\n\n // Move back to the beginning of the week\n const result = this.parse(d);\n // Subtract days to get to the start of the week (Sunday)\n result.setDate(d.getDate() - dayOfWeek);\n return result;\n }\n\n public static isSameDay(date1: Date | string, date2: Date | string): boolean {\n if (!date1 || !date2) {\n return false;\n }\n const d1 = this.parse(date1);\n const d2 = this.parse(date2);\n\n return (\n d1.getFullYear() === d2.getFullYear() &&\n d1.getMonth() === d2.getMonth() &&\n d1.getDate() === d2.getDate()\n );\n }\n\n // Helper to check if one date is before another (ignoring time)\n public static isBeforeDay(date1: Date | string, date2: Date | string): boolean {\n if (!date1 || !date2) {\n return false;\n }\n return this.getStartOfDay(date1).getTime() < this.getStartOfDay(date2).getTime();\n }\n\n // Helper to check if one date is after another (ignoring time)\n public static isAfterDay(date1: Date | string, date2: Date | string): boolean {\n if (!date1 || !date2) {\n return false;\n }\n return this.getStartOfDay(date1).getTime() > this.getStartOfDay(date2).getTime();\n }\n\n /**\n * Determines if a given date is observing Daylight Saving Time (DST)\n * relative to the runtime's local timezone.\n */\n public static isDST(dateInput?: Date | string | number | null): boolean {\n const d = this.parse(dateInput);\n const year = d.getFullYear();\n\n // Get the timezone offset for January 1st and July 1st of the same year\n const janOffset = new Date(year, 0, 1).getTimezoneOffset();\n const julOffset = new Date(year, 6, 1).getTimezoneOffset();\n\n // The standard time offset is always the maximum of the two.\n // Example (New York): EST is 300 mins behind UTC, EDT is 240 mins. Max is 300.\n // Example (Sydney): AEST is -600 mins, AEDT is -660 mins. Max is -600.\n const standardTimezoneOffset = Math.max(janOffset, julOffset);\n\n // If the date's offset is less than the standard offset, it is in DST\n return d.getTimezoneOffset() < standardTimezoneOffset;\n }\n\n /**\n * Extracts the exact wall-clock date and time components for a specific timezone.\n * @param dateInput The date to evaluate (defaults to now)\n * @param timeZone The target IANA timezone (e.g., 'America/New_York')\n * @returns An object containing numeric date components (month is 1-12)\n */\n public static getPartsInZone(\n dateInput?: Date | string | number | null,\n timeZone: IANATimeZone = 'America/New_York',\n ): {\n year: number;\n month: number;\n day: number;\n hour: number;\n minute: number;\n second: number;\n weekday: string;\n } {\n const d = this.parse(dateInput);\n\n const allTimeZones = Intl.supportedValuesOf('timeZone');\n\n if (!allTimeZones.includes(timeZone)) {\n throw new Error('Unsupported timeZone.');\n }\n\n const formatter = new Intl.DateTimeFormat('en-US', {\n timeZone,\n year: 'numeric',\n month: 'numeric',\n day: 'numeric',\n hour: 'numeric',\n minute: 'numeric',\n second: 'numeric',\n weekday: 'long', // Adds \"Monday\", \"Tuesday\", etc. to the output\n hourCycle: 'h23',\n });\n\n const parts = formatter.formatToParts(d);\n\n const getPart = (type: Intl.DateTimeFormatPartTypes) => parseInt(parts.find((p) => p.type === type)?.value || '0', 10);\n\n const weekday = parts.find((p) => p.type === 'weekday')?.value || '';\n\n return {\n year: getPart('year'),\n month: getPart('month'), // 1-12 format\n day: getPart('day'),\n hour: getPart('hour'), // 0-23 format\n minute: getPart('minute'),\n second: getPart('second'),\n weekday,\n };\n }\n\n /**\n * Calculates the difference between two dates (`date1 - date2`).\n *\n * @param date1 Primary date\n * @param date2 Comparison date (defaults to current time)\n * @param utc Whether to parse strings as UTC\n */\n public static diff(\n date1: Date | string | number,\n date2: Date | string | number = new Date(),\n utc = false,\n ): {\n milliseconds: number;\n seconds: number;\n minutes: number;\n hours: number;\n days: number;\n weeks: number;\n months: number;\n years: number;\n abs: {\n milliseconds: number;\n seconds: number;\n minutes: number;\n hours: number;\n days: number;\n weeks: number;\n months: number;\n years: number;\n }\n } {\n const d1 = this.parse(date1, utc);\n const d2 = this.parse(date2, utc);\n\n const ms = d1.getTime() - d2.getTime();\n\n // Calendar-based month and year differences\n const y1 = utc ? d1.getUTCFullYear() : d1.getFullYear();\n const y2 = utc ? d2.getUTCFullYear() : d2.getFullYear();\n const m1 = utc ? d1.getUTCMonth() : d1.getMonth();\n const m2 = utc ? d2.getUTCMonth() : d2.getMonth();\n\n const months = (y1 - y2) * 12 + (m1 - m2);\n const years = y1 - y2;\n\n const seconds = Math.trunc(ms / 1000);\n const minutes = Math.trunc(ms / (1000 * 60));\n const hours = Math.trunc(ms / (1000 * 60 * 60));\n const days = Math.trunc(ms / (1000 * 60 * 60 * 24));\n const weeks = Math.trunc(ms / (1000 * 60 * 60 * 24 * 7));\n\n return {\n milliseconds: ms,\n seconds,\n minutes,\n hours,\n days,\n weeks,\n months,\n years,\n // Helper containing absolute (positive) values\n abs: {\n milliseconds: Math.abs(ms),\n seconds: Math.abs(seconds),\n minutes: Math.abs(minutes),\n hours: Math.abs(hours),\n days: Math.abs(days),\n weeks: Math.abs(weeks),\n months: Math.abs(months),\n years: Math.abs(years),\n },\n };\n }\n}\n\n", "/*\n * Copyright 2026 Evan Smalley.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n */\n\n// \u30B3\u30F3\u30C8\u30ED\u30FC\u30EB\n\ntype Listeners = Array<(...args: unknown[]) => void>;\n\nexport class Kontororu extends EventTarget {\n constructor() {\n super();\n this.listeners = {};\n }\n\n private listeners: {\n [type: string]: Listeners;\n };\n\n addEventListener(type: string, listener: (...args: unknown[]) => void): this {\n super.addEventListener(type, listener);\n\n if (!this.listeners[type]) {\n this.listeners[type] = [];\n }\n this.listeners[type].push(listener);\n\n return this;\n }\n\n removeEventListener(type: string, listener: (...args: unknown[]) => void): this {\n super.removeEventListener(type, listener);\n\n if (this.listeners[type]) {\n this.listeners[type] = this.listeners[type].filter((l) => l !== listener);\n }\n\n return this;\n }\n\n removeAllEventListeners() {\n for (const type in this.listeners) {\n for (let i = this.listeners[type].length; i >= 0; i--) {\n this.removeEventListener(type, this.listeners[type][i]);\n }\n }\n }\n\n getListeners(type: string): Listeners | [] {\n return this.listeners[type] || [];\n }\n}\n\n\n", "/*\n * Copyright 2026 Evan Smalley.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n */\n\nimport { Kontororu } from '../Kontororu.js';\n\n\ninterface SocketConfig {\n hostname: string;\n port?: string | number;\n path: string;\n}\n\ntype ConnectionState = 'connected' | 'stale' | 'disconnected' | 'reconnected';\n\ntype SocketMessage = {\n type: 'subscribe' | 'unsubscribe' | 'data' | 'heartbeat';\n table: string;\n id: string;\n}\n\ntype SocketResponseMessage = {\n table: string;\n id: string;\n data: object;\n}\n\nconst debug = false;\n\nclass Socket extends Kontororu {\n private config?: SocketConfig;\n\n private ws?: WebSocket;\n\n private connection_state: ConnectionState = 'connected';\n\n private session_id?: string;\n\n private message_queue: SocketMessage[] = [];\n\n // Reconnection logic\n private reconnect_attempts: number = 0;\n private should_reconnect = true;\n private reconnect_timeout?: NodeJS.Timeout;\n\n // Heartbeat / Sleep Detection Logic\n private last_heartbeat_timestamp: number = Date.now();\n // How often the server pings THIS specific client (5 seconds)\n private readonly HEARTBEAT_INTERVAL_MS = 5000;\n // Calculate threshold: 2 missed beats + 1 second of network jitter buffer\n private readonly SUSPENSION_THRESHOLD_MS = (this.HEARTBEAT_INTERVAL_MS * 2) + 1000;\n // 3 Heartbeats + 1s buffer = 16 seconds\n private readonly DISCONNECT_THRESHOLD_MS = (this.HEARTBEAT_INTERVAL_MS * 3) + 1000;\n\n constructor() {\n super();\n if (typeof document !== 'undefined') {\n document.addEventListener('visibilitychange', (event) => {\n if (document.visibilityState === 'visible') {\n this.check_staleness('tab_switch');\n }\n });\n }\n\n if (typeof window !== 'undefined') {\n const offlineChecker = () => {\n const check = 3;\n let checked = 1;\n\n const checker = () => {\n if (checked > check) {\n return;\n }\n setTimeout(\n () => {\n this.check_staleness('offline');\n checked++;\n checker();\n },\n (this.HEARTBEAT_INTERVAL_MS) + 500,\n );\n };\n\n checker();\n };\n\n window.addEventListener('online', () => {\n window.removeEventListener('offline', offlineChecker);\n });\n window.addEventListener('offline', offlineChecker);\n }\n }\n\n private get_url() {\n if (!this.config) {\n throw new Error('Socket not configured');\n }\n\n const { hostname, port, path } = this.config;\n\n const protocol = (typeof window !== 'undefined' && window.location && window.location.protocol && window.location.protocol === 'https:' ? 'wss:' : 'ws:');\n\n return `${protocol}//${hostname}${port ? `:${port}` : ''}/${path}`;\n }\n\n public connect(session_id: string, config?: SocketConfig) {\n if (config) {\n this.config = config;\n }\n\n if (!session_id) {\n console.warn('session_id required to open ws');\n return;\n }\n\n if (\n this.ws &&\n (\n this.ws.readyState === WebSocket.OPEN ||\n this.ws.readyState === WebSocket.CONNECTING\n )\n ) {\n return;\n }\n\n this.ws = new WebSocket(this.get_url());\n\n if (debug) console.log('new websocket');\n\n this.session_id = session_id;\n\n // Reset heartbeat timer on new connection\n this.last_heartbeat_timestamp = Date.now();\n\n this.ws.addEventListener('open', (event) => this.handle_open(event));\n this.ws.addEventListener('message', (event) => this.handle_message(event));\n this.ws.addEventListener('close', (event) => this.handle_close(event));\n this.ws.addEventListener('error', (event) => this.handle_error(event));\n }\n\n /**\n * Send message if the websocket is open,\n * otherwise add it to the message queue\n */\n public message({ type, table, id }: SocketMessage) {\n const payload = { type, table, id };\n\n if (\n this.ws &&\n this.ws.readyState === WebSocket.OPEN\n ) {\n this.ws.send(JSON.stringify(payload));\n } else {\n this.message_queue.push(payload);\n }\n }\n\n public disconnect() {\n if (debug) console.log('websocket disconnect()');\n this.update_connection_state('disconnected');\n // if we are manually disconnecting we do not want an auto reconnect\n this.should_reconnect = false;\n this.ws?.close();\n this.ws = undefined;\n if (this.reconnect_timeout) {\n clearTimeout(this.reconnect_timeout);\n }\n }\n\n /**\n * Update the connection state, dispatch an event if it actually changed.\n */\n private update_connection_state(new_connection_state: ConnectionState) {\n const old_connection_state = this.connection_state;\n if (this.connection_state !== new_connection_state) {\n if (debug) console.log('update_connection_state', new_connection_state);\n this.connection_state = new_connection_state;\n\n if (debug) console.warn(`[Socket] State changed to: ${this.connection_state}`);\n this.dispatchEvent(new CustomEvent('connection_state', { detail: this.connection_state }));\n\n if (\n (new_connection_state === 'connected' || new_connection_state === 'reconnected') &&\n (old_connection_state === 'stale' || old_connection_state === 'disconnected')\n ) {\n this.dispatchEvent(new CustomEvent('refresh', { bubbles: true }));\n }\n }\n }\n\n\n /**\n * Helper to determine if we need to fetch missing data\n */\n private check_staleness(source: string) {\n const now = Date.now();\n const time_since_last = now - this.last_heartbeat_timestamp;\n\n if (debug) console.log('websocket check_staleness()', source, time_since_last);\n\n if (\n !this.ws ||\n this.ws.readyState === this.ws.CLOSED ||\n time_since_last > this.DISCONNECT_THRESHOLD_MS\n ) {\n this.update_connection_state('disconnected');\n return;\n }\n\n // If gap is larger than threshold, we missed messages\n if (time_since_last > this.SUSPENSION_THRESHOLD_MS) {\n this.update_connection_state('stale');\n } else {\n this.update_connection_state('connected');\n }\n }\n\n private handle_open(event: Event) {\n if (debug) console.log('websocket handle open()');\n\n if (\n this.ws &&\n this.ws.readyState === this.ws.OPEN\n ) {\n this.update_connection_state('connected');\n }\n // clear reconnect timeout if we connected\n if (this.reconnect_timeout) {\n clearTimeout(this.reconnect_timeout);\n }\n\n // If we are reconnecting (attempts > 0), we definitely missed data.\n if (this.reconnect_attempts > 0) {\n if (debug) console.log('[Socket] Reconnected. Triggering refresh.');\n this.dispatchEvent(new CustomEvent('refresh', { bubbles: true }));\n }\n\n // reset the reconnect attempts\n this.reconnect_attempts = 0;\n\n this.ws?.send(JSON.stringify({ type: 'session', table: 'session', id: this.session_id }));\n\n while (this.message_queue.length > 0) {\n const queuedMsg = this.message_queue.shift();\n this.ws?.send(JSON.stringify(queuedMsg));\n }\n }\n\n private handle_message(event: MessageEvent) {\n if (debug) console.log('websocket handle message()');\n\n try {\n const data = JSON.parse(event.data);\n\n if (debug) console.log('data', data);\n\n // HEARTBEAT CHECK: Intercept heartbeat messages\n if (data.type === 'heartbeat') {\n this.check_staleness('heartbeat');\n this.last_heartbeat_timestamp = Date.now();\n return; // Do not bubble 'heartbeat' to the UI\n }\n\n // todo not sure I like this\n const messageEvent = new CustomEvent('message', {\n detail: JSON.parse(event.data) as SocketResponseMessage,\n bubbles: true,\n });\n\n this.dispatchEvent(messageEvent);\n } catch (e) {\n const messageEvent = new CustomEvent('message', {\n detail: event.data as SocketResponseMessage,\n bubbles: true,\n });\n this.dispatchEvent(messageEvent);\n }\n }\n\n private handle_close(event: CloseEvent) {\n if (debug) console.log('websocket handle close()');\n this.update_connection_state('disconnected');\n if (this.should_reconnect) {\n const delay = Math.min(1000 * Math.pow(2, this.reconnect_attempts), 30000);\n if (debug) console.log(`Connection lost. Retrying in ${delay}ms... (Attempt ${this.reconnect_attempts + 1})`);\n\n this.reconnect_timeout = setTimeout(() => {\n this.reconnect_attempts++;\n if (this.session_id) {\n this.connect(this.session_id);\n }\n }, delay);\n }\n\n this.ws = undefined;\n }\n\n private handle_error(event: Event) {\n if (debug) console.log('websocket handle error()');\n this.update_connection_state('disconnected');\n console.error('WebSocket Error:', event);\n this.ws?.close();\n }\n}\n\nexport const socket: Socket = new Socket();\n", "/*\n * Copyright 2026 Evan Smalley.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n */\n\n/* eslint-disable no-restricted-syntax */\n\ntype Merge<T, U> = Omit<T, keyof U> & U;\n\ntype MergeAll<T extends object[]> =\n T extends [infer First extends object, ...infer Rest extends object[]]\n ? Rest extends []\n ? First // Base case: If there are no more items, just return the object\n : Merge<First, MergeAll<Rest>> // Otherwise, keep merging\n : unknown;\n\n/**\n * Class to manipulate objects\n */\nexport class Objector {\n // constructor() {\n // }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n public static deepClone<T>(obj: T, memo: WeakMap<any, any> = new WeakMap<any, any>()): T {\n // Check if the input is null or not an object/array\n if (obj === null || typeof obj !== 'object') {\n return obj;\n }\n\n // Check if the object is already in the memo\n if (memo.has(obj)) {\n return memo.get(obj);\n }\n\n // Handle built-in types\n if (obj instanceof Date) {\n return new Date(obj.getTime()) as unknown as T;\n }\n if (obj instanceof RegExp) {\n return new RegExp(obj.source, obj.flags) as unknown as T;\n }\n if (obj instanceof Map) {\n const clonedMap = new Map();\n memo.set(obj, clonedMap);\n obj.forEach((value, key) => clonedMap.set(key, Objector.deepClone(value, memo)));\n return clonedMap as unknown as T;\n }\n if (obj instanceof Set) {\n const newSet = new Set();\n for (const item of obj) {\n newSet.add(Objector.deepClone(item));\n }\n return newSet as unknown as T;\n }\n\n // Handle arrays\n if (Array.isArray(obj)) {\n const clonedArray = obj.map((item) => Objector.deepClone(item, memo)) as unknown as T;\n memo.set(obj, clonedArray);\n return clonedArray;\n }\n\n // Handle objects\n const clonedObj = Object.create(Object.getPrototypeOf(obj)) as Record<string | symbol, unknown>;\n memo.set(obj, clonedObj);\n\n // Cast the source 'obj' to a record so we can read its keys dynamically\n const sourceObj = obj as Record<string | symbol, unknown>;\n\n // per Gemini\n /**\n * While it appears to be two steps, the first step (Object.keys()) is a native C++ function in the JavaScript engine.\n * It's highly optimized for this specific task and is often faster than the JIT compiler can make the for...in loop with its conditional checks.\n */\n Object.keys(sourceObj).forEach((key) => {\n clonedObj[key] = Objector.deepClone(sourceObj[key], memo);\n });\n /*\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n clonedObj[key] = Objector.deepClone(obj[key], memo);\n }\n }\n */\n\n // Symbol keys\n Object.getOwnPropertySymbols(sourceObj).forEach((sym) => {\n if (Object.prototype.propertyIsEnumerable.call(sourceObj, sym)) {\n clonedObj[sym] = Objector.deepClone(sourceObj[sym], memo);\n }\n });\n\n return clonedObj as unknown as T;\n }\n\n /**\n * Deeply merges one or more source objects into a target object.\n *\n * - Each property from the sources is deep-cloned before being assigned.\n * - Existing properties in the target are overwritten by matching keys in later sources.\n * - Does not use spread or Object.assign.\n * - Mutates and returns the target object.\n *\n * @template T - The type of the target object.\n * @param {T} target - The object to extend.\n * @param {...U[]} sources - One or more source objects whose properties will be copied to the target.\n * @returns {T & U} The mutated target object containing all deep-cloned properties from the sources.\n *\n * @throws {TypeError} If the target is null or undefined.\n *\n * @example\n * const target = { a: 1 };\n * const source = { b: { nested: 2 } };\n * Objector.extender(target, source);\n * // target is now { a: 1, b: { nested: 2 } }\n */\n public static extender<T extends object, U extends object[]>(\n target: T,\n ...sources: U\n ): MergeAll<[T, ...U]> {\n if (target == null) {\n throw new TypeError('Cannot convert undefined or null to object');\n }\n\n const to = Object(target) as Record<string | symbol, unknown>;\n\n // eslint-disable-next-line no-restricted-syntax\n for (const source of sources) {\n if (source != null) {\n // Cast the source to an indexable record\n const s = source as Record<string | symbol, unknown>;\n // String keys\n // eslint-disable-next-line no-restricted-syntax\n for (const key of Object.keys(s)) {\n to[key] = Objector.deepClone(s[key]);\n }\n\n // Symbol keys\n const symbols = Object.getOwnPropertySymbols(s);\n // eslint-disable-next-line no-restricted-syntax\n for (const sym of symbols) {\n if (Object.prototype.propertyIsEnumerable.call(s, sym)) {\n to[sym] = Objector.deepClone(s[sym]);\n }\n }\n }\n }\n\n return to as MergeAll<[T, ...U]>;\n }\n}\n\n", "/*\n * Copyright 2026 Evan Smalley.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n */\n\nimport { Kontororu } from '../Kontororu.js';\nimport { Objector } from '../Objector.js';\n\n\nexport type StoreData = Record<string, Record<string, unknown>>;\n\nexport class Store<TStore extends StoreData = StoreData> extends Kontororu {\n private store: TStore = {} as TStore;\n\n /**\n * Load an object into the store\n */\n load(data: TStore) {\n this.store = data;\n }\n\n /**\n * Get the first result\n */\n get<K extends keyof TStore>(table: K, args: Record<string, unknown> = {}): TStore[K][string] | null {\n const results = this.read(table, args);\n const firstId = Object.keys(results)[0];\n return firstId ? (results[firstId] as TStore[K][string]) : null;\n }\n\n /**\n * Read the results\n */\n read<K extends keyof TStore>(table: K, args: Record<string, unknown> = {}): Record<string, TStore[K][string]> {\n const data = this.store[table];\n if (!data) {\n return {};\n }\n\n const primaryKey = `${String(table)}_id`;\n\n // Fast path: Direct primary key lookup\n if (primaryKey in args) {\n const id = args[primaryKey] as string;\n if (data[id]) {\n return { [id]: Objector.deepClone(data[id]) as TStore[K][string] };\n }\n return {};\n }\n\n // If no arguments are provided, return a deep clone of the entire table\n if (Object.keys(args).length === 0) {\n return Objector.deepClone(data) as Record<string, TStore[K][string]>;\n }\n\n const matches: Record<string, TStore[K][string]> = {};\n const mismatches: Record<string, boolean> = {};\n\n for (const id in data) {\n if (id in mismatches) {\n continue;\n }\n\n const row = data[id];\n if (!row || typeof row !== 'object' || Array.isArray(row)) {\n continue;\n }\n\n for (const column in args) {\n let match = false;\n const argVal = args[column];\n const rowVal = (row as Record<string, unknown>)[column];\n\n if (rowVal === argVal) {\n match = true;\n } else if (Array.isArray(argVal) && argVal.includes(rowVal)) {\n match = true;\n }\n\n if (match) {\n matches[id] = Objector.deepClone(row) as TStore[K][string];\n } else {\n mismatches[id] = true;\n delete matches[id];\n break;\n }\n }\n }\n\n return matches;\n }\n}\n", "/*\n * Copyright 2026 Evan Smalley.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n */\n\n/**\n * Table sorting helper utility\n */\nexport class Sorter {\n public static descendingComparator(a: Record<string, string | number>, b: Record<string, string | number>, orderBy: string, direction_?: string): number {\n if ((orderBy in a) && b[orderBy] === null) {\n return 1;\n }\n if (a[orderBy] === null && (orderBy in b)) {\n return -1;\n }\n\n const a_value = a[orderBy];\n const b_value = b[orderBy];\n\n const direction = direction_ || 'lower';\n\n if (b_value < a_value) {\n return direction === 'higher' ? 1 : -1;\n }\n if (b_value > a_value) {\n return direction === 'higher' ? -1 : 1;\n }\n return 0;\n }\n\n public static getComparator(order: string, orderBy: string, direction?: string): (a: Record<string, string | number>, b: Record<string, string | number>) => number {\n return order === 'desc'\n ? (a, b) => this.descendingComparator(a, b, orderBy, direction)\n : (a, b) => -this.descendingComparator(a, b, orderBy, direction);\n }\n}\n", "/*\n * Copyright 2026 Evan Smalley.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n */\n\n/* eslint-disable no-restricted-syntax */\n/* eslint-disable no-bitwise */\n\n\n\n\ntype CSSMap = Map<string, string>;\n\ninterface ZIndexConfig {\n appBar: number;\n drawer: number;\n fab: number;\n calendar: number;\n mobileStepper: number;\n modal: number;\n toast: number;\n speedDial: number;\n tooltip: number;\n}\n\ninterface StyleConfig {\n zIndex: ZIndexConfig;\n}\n\ninterface NavBarStyle {\n width: string;\n display: string;\n justifyContent: string;\n zIndex: number;\n position: string;\n overflowX: string;\n overflowY: string;\n scrollbarWidth: string;\n}\n\n/**\n * CSS in JS processor and other random style functions\n */\nexport class Style {\n public static getStyle(): StyleConfig {\n return {\n zIndex: Style.getZIndex(),\n };\n }\n\n public static getZIndex(): ZIndexConfig {\n return {\n appBar: 1100,\n drawer: 1200,\n fab: 1050,\n calendar: 1000,\n mobileStepper: 1000,\n modal: 1300,\n toast: 1400,\n speedDial: 1050,\n tooltip: 1500,\n };\n }\n\n public static getNavBar(): NavBarStyle {\n return {\n width: '100%',\n display: 'flex',\n justifyContent: 'center',\n zIndex: Style.getZIndex().appBar,\n position: 'fixed',\n overflowX: 'scroll',\n overflowY: 'hidden',\n scrollbarWidth: 'none',\n };\n }\n\n public static getShadow(depth: number): string {\n const shadows = [\n 'none',\n '0px 2px 1px -1px rgba(0,0,0,0.2),0px 1px 1px 0px rgba(0,0,0,0.14),0px 1px 3px 0px rgba(0,0,0,0.12)',\n '0px 3px 1px -2px rgba(0,0,0,0.2),0px 2px 2px 0px rgba(0,0,0,0.14),0px 1px 5px 0px rgba(0,0,0,0.12)',\n '0px 3px 3px -2px rgba(0,0,0,0.2),0px 3px 4px 0px rgba(0,0,0,0.14),0px 1px 8px 0px rgba(0,0,0,0.12)',\n '0px 2px 4px -1px rgba(0,0,0,0.2),0px 4px 5px 0px rgba(0,0,0,0.14),0px 1px 10px 0px rgba(0,0,0,0.12)',\n '0px 3px 5px -1px rgba(0,0,0,0.2),0px 5px 8px 0px rgba(0,0,0,0.14),0px 1px 14px 0px rgba(0,0,0,0.12)',\n '0px 3px 5px -1px rgba(0,0,0,0.2),0px 6px 10px 0px rgba(0,0,0,0.14),0px 1px 18px 0px rgba(0,0,0,0.12)',\n '0px 4px 5px -2px rgba(0,0,0,0.2),0px 7px 10px 1px rgba(0,0,0,0.14),0px 2px 16px 1px rgba(0,0,0,0.12)',\n '0px 5px 5px -3px rgba(0,0,0,0.2),0px 8px 10px 1px rgba(0,0,0,0.14),0px 3px 14px 2px rgba(0,0,0,0.12)',\n '0px 5px 6px -3px rgba(0,0,0,0.2),0px 9px 12px 1px rgba(0,0,0,0.14),0px 3px 16px 2px rgba(0,0,0,0.12)',\n '0px 6px 6px -3px rgba(0,0,0,0.2),0px 10px 14px 1px rgba(0,0,0,0.14),0px 4px 18px 3px rgba(0,0,0,0.12)',\n '0px 6px 7px -4px rgba(0,0,0,0.2),0px 11px 15px 1px rgba(0,0,0,0.14),0px 4px 20px 3px rgba(0,0,0,0.12)',\n '0px 7px 8px -4px rgba(0,0,0,0.2),0px 12px 17px 2px rgba(0,0,0,0.14),0px 5px 22px 4px rgba(0,0,0,0.12)',\n '0px 7px 8px -4px rgba(0,0,0,0.2),0px 13px 19px 2px rgba(0,0,0,0.14),0px 5px 24px 4px rgba(0,0,0,0.12)',\n '0px 7px 9px -4px rgba(0,0,0,0.2),0px 14px 21px 2px rgba(0,0,0,0.14),0px 5px 26px 4px rgba(0,0,0,0.12)',\n '0px 8px 9px -5px rgba(0,0,0,0.2),0px 15px 22px 2px rgba(0,0,0,0.14),0px 6px 28px 5px rgba(0,0,0,0.12)',\n '0px 8px 10px -5px rgba(0,0,0,0.2),0px 16px 24px 2px rgba(0,0,0,0.14),0px 6px 30px 5px rgba(0,0,0,0.12)',\n '0px 8px 11px -5px rgba(0,0,0,0.2),0px 17px 26px 2px rgba(0,0,0,0.14),0px 6px 32px 5px rgba(0,0,0,0.12)',\n '0px 9px 11px -5px rgba(0,0,0,0.2),0px 18px 28px 2px rgba(0,0,0,0.14),0px 7px 34px 6px rgba(0,0,0,0.12)',\n '0px 9px 12px -6px rgba(0,0,0,0.2),0px 19px 29px 2px rgba(0,0,0,0.14),0px 7px 36px 6px rgba(0,0,0,0.12)',\n '0px 10px 13px -6px rgba(0,0,0,0.2),0px 20px 31px 3px rgba(0,0,0,0.14),0px 8px 38px 7px rgba(0,0,0,0.12)',\n '0px 10px 13px -6px rgba(0,0,0,0.2),0px 21px 33px 3px rgba(0,0,0,0.14),0px 8px 40px 7px rgba(0,0,0,0.12)',\n '0px 10px 14px -6px rgba(0,0,0,0.2),0px 22px 35px 3px rgba(0,0,0,0.14),0px 8px 42px 7px rgba(0,0,0,0.12)',\n '0px 11px 14px -7px rgba(0,0,0,0.2),0px 23px 36px 3px rgba(0,0,0,0.14),0px 9px 44px 8px rgba(0,0,0,0.12)',\n '0px 11px 15px -7px rgba(0,0,0,0.2),0px 24px 38px 3px rgba(0,0,0,0.14),0px 9px 46px 8px rgba(0,0,0,0.12)',\n ];\n\n if (depth > shadows.length || depth < 0) {\n throw new Error(`min depth is 0, max depth is ${shadows.length}. Sent ${depth}`);\n }\n\n return shadows[depth];\n }\n\n /**\n *\n *\n *\n *\n * Below is all the CSS injection from js\n *\n *\n *\n */\n\n /**\n * Call this to add css as a style-sheet, so you can do css selectors like hover td {} etc\n */\n public static getStyleClassName(cssString: string | object, debug = false): string {\n if (debug) {\n console.log('getStyleClassName', cssString);\n }\n // console.time('getStyleClassName')\n const className = `css-${this.hashCSS(cssString, debug)}`;\n\n this.injectStyle(className, cssString, debug);\n // console.timeEnd('getStyleClassName')\n return className;\n }\n\n public static getMap(): CSSMap {\n return this.cssMap;\n }\n\n // SSR helper to get all collected styles\n public static getCSS(): string {\n console.warn('this does not work yet, in root layout need to add a context thing so it attaches css to style when streamed from server');\n return Array.from(this.cssMap.values()).join('\\n');\n }\n\n // Call after SSR render to clean up for next render\n public static flush(): void {\n this.styleCache.clear();\n this.cssMap.clear();\n }\n\n private static styleCache: Set<string> = new Set();\n\n private static cssMap: CSSMap = new Map(); // key: className, value: finalCSS\n\n private static hashCSS(css: string | object, debug = false): string {\n const canonicalize = (obj: object | string | number): object | string | number => {\n if (typeof obj !== 'object' || obj === null) {\n // Return primitives as is\n return obj;\n }\n\n if (Array.isArray(obj)) {\n // Recursively canonicalize array elements\n return obj.map(canonicalize);\n }\n\n // 1. Get and sort the keys of the current object level\n const sortedKeys = Object.keys(obj).sort();\n const canonical: { [key: string]: unknown } = {};\n\n // cast object to record\n const sourceObj = obj as Record<string, string | number>;\n\n // 2. Build a new object using the sorted keys, and recursively process values\n for (const key of sortedKeys) {\n canonical[key] = canonicalize(sourceObj[key]);\n }\n\n return canonical;\n };\n\n const normalize = (val: string | object): string => {\n if (typeof val === 'string') {\n return val;\n }\n if (typeof val === 'object' && val !== null) {\n const canonicalObject = canonicalize(val);\n // Step B: Stringify the canonical object without a replacer\n return JSON.stringify(canonicalObject);\n }\n return String(val);\n };\n\n const normalizedInput = normalize(css);\n\n if (debug) {\n console.log('normalizedInput', normalizedInput);\n }\n\n // Example hash using a simple DJB2 hash (or use a stronger hash like SHA-1/MD5 if needed)\n let hash = 5381;\n for (let i = 0; i < normalizedInput.length; i++) {\n hash = (hash * 33) ^ normalizedInput.charCodeAt(i);\n }\n return (hash >>> 0).toString(36); // base36 for short string\n }\n\n private static injectStyle(className: string, css: string | object, debug = false): void {\n if (\n this.styleCache.has(className)\n ) {\n return;\n }\n\n const finalCSS = this.processCSS(className, css, false, debug);\n\n // If on server, store it only\n if (typeof window === 'undefined') {\n this.cssMap.set(className, finalCSS);\n } else {\n const styleEl = document.createElement('style');\n styleEl.textContent = finalCSS;\n document.head.appendChild(styleEl);\n }\n\n this.styleCache.add(className);\n this.cssMap.set(className, finalCSS);\n }\n\n private static processCSS(className: string, css: string | object, isRecursive = false, debug = false): string {\n // Helper: remove trailing colon from selectors (e.g. 'td:' -> 'td')\n const cleanSelector = (sel:string): string => {\n return sel.replace(/:$/g, '');\n };\n\n // Convert camelCase to kebab-case for property names\n const toKebabCase = (str: string): string => {\n return str.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase();\n };\n\n // Helper: Remove the specific '}' that closed the block from the accumulated lines\n // so we don't duplicate it when wrapping the result in new braces.\n const removeLastBrace = (lines: string[]) => {\n if (lines.length === 0) return;\n const lastIdx = lines.length - 1;\n const lastLine = lines[lastIdx];\n\n const braceIdx = lastLine.lastIndexOf('}');\n if (braceIdx !== -1) {\n // Remove the brace\n const newLine = lastLine.substring(0, braceIdx) + lastLine.substring(braceIdx + 1);\n\n // If the line is now empty (or just whitespace), remove it entirely\n if (!newLine.trim()) {\n lines.pop();\n } else {\n // eslint-disable-next-line no-param-reassign\n lines[lastIdx] = newLine;\n }\n }\n };\n\n const requiresQuotes = new Set([\n 'content',\n 'quotes',\n 'cue',\n 'cue-before',\n 'cue-after',\n 'src',\n ]);\n\n // List of properties that should have units if the value is a number\n const lengthProps = new Set([\n 'width', 'height', 'top', 'left', 'right', 'bottom',\n 'margin', 'margin-top', 'margin-right', 'margin-bottom', 'margin-left',\n 'padding', 'padding-top', 'padding-right', 'padding-bottom', 'padding-left',\n 'font-size', 'border-width', 'border-radius', 'gap', 'column-gap', 'row-gap',\n 'min-width', 'min-height', 'max-width', 'max-height',\n ]);\n\n const non_recursive_at_rules = [\n '@keyframes',\n '@-webkit-keyframes',\n '@font-face',\n '@counter-style',\n ];\n\n const isNonRecursiveRule = (ruleName: string) => {\n return non_recursive_at_rules.some((prefix) => ruleName.startsWith(prefix));\n };\n\n const normalizeValue = (property: string, value: string | number): string | number => {\n if (!lengthProps.has(property)) {\n return value;\n }\n\n // If it's a number, add px\n if (typeof value === 'number') {\n return `${value}px`;\n }\n\n // If it's a numeric string with no unit, add px\n if (typeof value === 'string') {\n const trimmed = value.trim();\n\n // Match numeric string (integer or decimal), no unit\n if (/^-?\\d+(\\.\\d+)?$/.test(trimmed)) {\n return `${trimmed}px`;\n }\n\n // If it ends in known units or keywords, leave it alone\n return trimmed;\n }\n\n return value;\n };\n\n // Convert a line like \"backgroundColor: red;\" to \"background-color: red;\"\n const normalizeCSSLine = (line: string): string => {\n const colonIndex = line.indexOf(':');\n if (colonIndex === -1) {\n return line; // Not a CSS property line\n }\n\n const rawProperty = line.slice(0, colonIndex).trim();\n let value: string | number = line.slice(colonIndex + 1).trim();\n\n const property = toKebabCase(rawProperty);\n\n // Remove trailing comma\n if (value.endsWith(',')) {\n value = value.slice(0, -1).trim();\n }\n\n // Only strip quotes if it's NOT a property like 'content'\n if (!requiresQuotes.has(property)) {\n value = value\n .split(',')\n .map((part) => {\n const trimmed = part.trim();\n // Check if the part is wrapped in quotes\n const match = trimmed.match(/^[\"'](.*)[\"']$/);\n\n if (match) {\n const innerValue = match[1];\n // If there's a space, keep the quotes (e.g., \"Segoe UI\")\n // If no space, strip them (e.g., \"Arial\" -> Arial)\n return innerValue.includes(' ') ? trimmed : innerValue;\n }\n return trimmed;\n })\n .join(', ');\n }\n\n value = normalizeValue(property, value);\n\n let cssLine = `${property}: ${value}`;\n if (!cssLine.endsWith(';')) {\n cssLine += ';';\n }\n\n return cssLine;\n };\n\n // Convert CSS object into flat lines\n const objectToLines = (obj: object): string[] => {\n const lines: string[] = [];\n\n const sourceObj = obj as Record<string, unknown>;\n\n for (const key in sourceObj) {\n const value = sourceObj[key];\n\n if (typeof value === 'object' && value !== null) {\n lines.push(`${key} {`);\n const nested = objectToLines(value);\n lines.push(...nested);\n lines.push('}');\n } else {\n // Note:\n // - We add a comma here to support object syntax, normalizeCSSLine will handle removing it and adding semicolons later.\n // - Don't stringify strings, to avoid double-escaping quotes (e.g. content: '\"*\"')\n const finalValue = typeof value === 'string' ? value : String(value);\n lines.push(`${key}: ${finalValue},`);\n }\n }\n\n return lines;\n };\n\n // Prepare raw lines\n const lines = typeof css === 'string'\n ? css.trim().split('\\n').map((line) => line.trim()).filter(Boolean)\n : objectToLines(css);\n\n\n const topLevelRules: string[] = [];\n const nestedRules: string[] = [];\n const atRules: string[] = [];\n\n let currentNestedSelector: string | null = null;\n let currentAtRule: string | null = null;\n let atRuleLines: string[] = [];\n let atRuleBraceCount = 0;\n let nestedLines: string[] = [];\n let nestedBraceCount = 0;\n\n for (const line of lines) {\n // 1. AT-RULE HANDLING (@media, @keyframes)\n if (line.startsWith('@') || currentAtRule) {\n if (!currentAtRule) currentAtRule = line.split('{')[0].trim();\n atRuleLines.push(line);\n atRuleBraceCount += (line.match(/{/g) || []).length;\n atRuleBraceCount -= (line.match(/}/g) || []).length;\n\n if (atRuleBraceCount === 0) {\n const rawBlock = atRuleLines.join('\\n');\n const contentOnly = rawBlock.substring(rawBlock.indexOf('{') + 1, rawBlock.lastIndexOf('}')).trim();\n\n if (currentAtRule.startsWith('@keyframes')) {\n // Keyframes: Process units/semicolons but DO NOT wrap in class\n const processed = contentOnly.split('\\n').map((l) => {\n if (l.includes('{') || l.includes('}')) return l;\n return normalizeCSSLine(l);\n }).join(' ');\n atRules.push(`${currentAtRule} { ${processed} }`);\n } else {\n // Media Queries: Recursive call to wrap in class\n const processed = this.processCSS(className, contentOnly, false, debug);\n atRules.push(`${currentAtRule} { ${processed} }`);\n }\n currentAtRule = null;\n atRuleLines = [];\n }\n continue;\n }\n\n // 2. NESTED SELECTOR HANDLING (&:hover, ::before)\n if (line.includes('{') || currentNestedSelector) {\n if (!currentNestedSelector) {\n currentNestedSelector = line.split('{')[0].trim();\n\n // Identify \"Highlight Pseudo-elements\" that need global scoping for Safari/WebKit compatibility\n const isHighlightPseudo = /::(selection|target-text|highlight|spelling-error|grammar-error)/.test(currentNestedSelector);\n\n // Standard behavior: auto-prefix with '&' if it starts with ':'\n // Special behavior: If it's a Highlight Pseudo, we leave it alone so it stays global\n if (\n currentNestedSelector.startsWith(':') &&\n !currentNestedSelector.startsWith('&') &&\n !isHighlightPseudo\n ) {\n currentNestedSelector = `&${currentNestedSelector}`;\n }\n } else if (!line.includes('}')) {\n nestedLines.push(normalizeCSSLine(line));\n }\n\n nestedBraceCount += (line.match(/{/g) || []).length;\n nestedBraceCount -= (line.match(/}/g) || []).length;\n\n if (nestedBraceCount === 0) {\n const isHighlightPseudo = /::(selection|target-text|highlight|spelling-error|grammar-error)/.test(currentNestedSelector);\n\n // If it's a Highlight Pseudo, we DON'T prefix with the .className.\n // This makes it global, which is required for Safari to render it correctly.\n const selector = isHighlightPseudo\n ? currentNestedSelector\n : currentNestedSelector.replace(/&/g, `.${className}`);\n\n nestedRules.push(`${selector} { ${nestedLines.join(' ')} }`);\n currentNestedSelector = null;\n nestedLines = [];\n }\n continue;\n }\n\n // 3. TOP LEVEL PROPERTIES\n topLevelRules.push(normalizeCSSLine(line));\n }\n\n const topLevelCSS = (!isRecursive && topLevelRules.length > 0)\n ? `.${className} { ${topLevelRules.join(' ')} }`\n : topLevelRules.join(' ');\n\n return `${topLevelCSS} ${nestedRules.join(' ')} ${atRules.join(' ')}`.replace(/\\s\\s+/g, ' ').trim();\n }\n}\n\n", "/*\n * Copyright 2026 Evan Smalley.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n */\n\nexport class Textor {\n public static levenshtein(a: string, b: string): number {\n const matrix: number[][] = [];\n\n if (!a || !b) {\n return 0;\n }\n\n // Initialize the matrix with base case values\n for (let i = 0; i <= a.length; i++) {\n matrix[i] = [i];\n }\n for (let j = 0; j <= b.length; j++) {\n matrix[0][j] = j;\n }\n\n // Populate the matrix with distances\n for (let i = 1; i <= a.length; i++) {\n for (let j = 1; j <= b.length; j++) {\n const cost = a[i - 1] === b[j - 1] ? 0 : 1;\n\n matrix[i][j] = Math.min(\n matrix[i - 1][j] + 1, // Deletion\n matrix[i][j - 1] + 1, // Insertion\n matrix[i - 1][j - 1] + cost, // Substitution\n );\n }\n }\n\n // The final value is the Levenshtein distance\n return matrix[a.length][b.length];\n }\n\n public static toSentenceCase(str: string): string {\n if (!str) {\n return '';\n }\n\n // Trim the string to remove extra whitespace\n const trimmed = str.trim();\n\n // Convert the first letter to uppercase and the rest to lowercase\n return trimmed.charAt(0).toUpperCase() + trimmed.slice(1).toLowerCase();\n }\n\n /**\n * Generates pseudo-Latin Lorem Ipsum placeholder text.\n */\n public static generateLoremIpsum(\n paragraphs = 3,\n sentencesPerParagraph = 5,\n startWithLorem = true,\n ): string {\n const words = [\n 'lorem', 'ipsum', 'dolor', 'sit', 'amet', 'consectetur', 'adipiscing', 'elit',\n 'sed', 'do', 'eiusmod', 'tempor', 'incididunt', 'ut', 'labore', 'et', 'dolore',\n 'magna', 'aliqua', 'ut', 'enim', 'ad', 'minim', 'veniam', 'quis', 'nostrud',\n 'exercitation', 'ullamco', 'laboris', 'nisi', 'ut', 'aliquip', 'ex', 'ea',\n 'commodo', 'consequat', 'duis', 'aute', 'irure', 'dolor', 'in', 'reprehenderit',\n 'in', 'voluptate', 'velit', 'esse', 'cillum', 'dolore', 'eu', 'fugiat', 'nulla',\n 'pariatur', 'excepteur', 'sint', 'occaecat', 'cupidatat', 'non', 'proident',\n 'sunt', 'in', 'culpa', 'qui', 'officia', 'deserunt', 'mollit', 'anim', 'id',\n 'est', 'laborum',\n ];\n\n // Helper to get a random word from the pool\n const getRandomWord = () => words[Math.floor(Math.random() * words.length)];\n\n // Helper to generate a single sentence\n const generateSentence = (isFirstSentence = false) => {\n if (isFirstSentence && startWithLorem) {\n return 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.';\n }\n\n // Sentences typically range from 5 to 15 words\n const sentenceLength = Math.floor(Math.random() * 11) + 5;\n const sentenceWords = [];\n\n for (let i = 0; i < sentenceLength; i++) {\n sentenceWords.push(getRandomWord());\n }\n\n // Capitalize the first letter of the sentence\n let sentence = sentenceWords.join(' ');\n sentence = sentence.charAt(0).toUpperCase() + sentence.slice(1);\n\n // Occasionally add commas for realistic phrasing (approx. 20% chance if long enough)\n if (sentenceLength > 8 && Math.random() > 0.8) {\n const commaIndex = Math.floor(sentenceLength / 2);\n const splitSentence = sentence.split(' ');\n splitSentence[commaIndex] += ',';\n sentence = splitSentence.join(' ');\n }\n\n return `${sentence}.`;\n };\n\n const paragraphList = [];\n\n for (let p = 0; p < paragraphs; p++) {\n const sentenceCount = Math.max(3, Math.round(sentencesPerParagraph + (Math.random() * 4 - 2))); // slight variance\n const sentences = [];\n\n for (let s = 0; s < sentenceCount; s++) {\n // Only the absolute first sentence of the entire text gets the classic intro\n const isAbsoluteFirst = p === 0 && s === 0;\n sentences.push(generateSentence(isAbsoluteFirst));\n }\n\n paragraphList.push(sentences.join(' '));\n }\n\n // Join paragraphs with double line breaks\n return paragraphList.join('\\n\\n');\n }\n}\n", "/*\n * Copyright 2026 Evan Smalley.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n */\n\nexport type ThemeType = ReturnType<Theme['getTheme']>;\n\n// all these types are for jsr / deno because it cant use the dynamic one above >.>\n\ninterface ColorScale {\n 50: string;\n 100: string;\n 200: string;\n 300: string;\n 400: string;\n 500: string;\n 600: string;\n 700: string;\n 800: string;\n 900: string;\n A100: string;\n A200: string;\n A400: string;\n A700: string;\n}\n\ninterface BrownScale {\n 50: string;\n 100: string;\n 200: string;\n 300: string;\n 400: string;\n 500: string;\n 600: string;\n 700: string;\n 800: string;\n 900: string;\n}\n\ninterface ColorGroup {\n main: string;\n light: string;\n dark: string;\n}\n\ninterface ColorGroupWithContrast extends ColorGroup {\n contrastText: string;\n}\n\ninterface ActionConfig {\n active: string;\n disabled: string;\n disabledBackground: string;\n disabledOpacity: number;\n focus: string;\n focusOpacity: number;\n hover: string;\n hoverOpacity: number;\n selected: string;\n selectedOpacity: number;\n}\n\ninterface ColorPalette {\n grey: ColorScale;\n red: ColorScale;\n pink: ColorScale;\n purple: ColorScale;\n deepPurple: ColorScale;\n indigo: ColorScale;\n blue: ColorScale;\n lightBlue: ColorScale;\n cyan: ColorScale;\n teal: ColorScale;\n green: ColorScale;\n lightGreen: ColorScale;\n lime: ColorScale;\n yellow: ColorScale;\n amber: ColorScale;\n orange: ColorScale;\n deepOrange: ColorScale;\n brown: BrownScale;\n}\n\ninterface DarkTheme extends ColorPalette {\n mode: 'dark';\n background: { main: string };\n header: { main: string };\n primary: ColorGroup;\n secondary: ColorGroup;\n warning: ColorGroup;\n success: ColorGroup;\n error: ColorGroup;\n info: ColorGroup;\n text: { primary: string; secondary: string; disabled: string; icon: string };\n link: { primary: string };\n action: ActionConfig;\n}\n\ninterface LightTheme extends ColorPalette {\n mode: 'light';\n background: { main: string; light: string };\n header: { main: string };\n primary: ColorGroupWithContrast;\n secondary: ColorGroupWithContrast;\n warning: ColorGroupWithContrast;\n success: ColorGroupWithContrast;\n error: ColorGroupWithContrast;\n info: ColorGroupWithContrast;\n text: { primary: string; secondary: string; disabled: string };\n link: { primary: string };\n action: ActionConfig;\n}\n\n/**\n * Class to get the theme\n */\nexport class Theme {\n public constructor(mode: string) {\n this.mode = mode;\n\n if (mode !== 'light' && mode !== 'dark') {\n throw new Error(`Unknown theme: ${mode}`);\n }\n }\n\n private mode: string;\n\n public getTheme(): DarkTheme | LightTheme {\n if (this.mode === 'light') {\n return this.getLightTheme();\n }\n\n return this.getDarkTheme();\n }\n\n public getDarkTheme(): DarkTheme {\n return {\n mode: 'dark',\n background: {\n main: '#121212',\n },\n header: {\n main: this.getGrey()[900],\n },\n primary: {\n main: '#90caf9',\n light: '#e3f2fd',\n dark: '#42a5f5',\n },\n secondary: {\n main: '#ce93d8',\n light: '#f3e5f5',\n dark: '#ab47bc',\n },\n warning: {\n main: '#ffa726',\n light: '#ffb74d',\n dark: '#f57c00',\n },\n success: {\n main: '#66bb6a',\n light: '#81c784',\n dark: '#388e3c',\n },\n error: {\n main: '#f44336',\n dark: '#d32f2f',\n light: '#e57373',\n },\n info: {\n main: '#29b6f6',\n dark: '#0288d1',\n light: '#4fc3f7',\n },\n text: {\n primary: '#fff',\n secondary: '#B3B3B3',\n disabled: '#808080',\n icon: '#808080',\n },\n link: {\n primary: '#90caf9',\n },\n action: {\n active: '#fff',\n disabled: 'rgba(255, 255, 255, 0.3)',\n disabledBackground: 'rgba(255, 255, 255, 0.12)',\n disabledOpacity: 0.38,\n focus: 'rgba(255, 255, 255, 0.12)',\n focusOpacity: 0.12,\n hover: 'rgba(255, 255, 255, 0.08)',\n hoverOpacity: 0.08,\n selected: 'rgba(255, 255, 255, 0.16)',\n selectedOpacity: 0.16,\n },\n grey: this.getGrey(),\n red: this.getRed(),\n pink: this.getPink(),\n purple: this.getPurple(),\n deepPurple: this.getDeepPurple(),\n indigo: this.getIndigo(),\n blue: this.getBlue(),\n lightBlue: this.getLightBlue(),\n cyan: this.getCyan(),\n teal: this.getTeal(),\n green: this.getGreen(),\n lightGreen: this.getLightGreen(),\n lime: this.getLime(),\n yellow: this.getYellow(),\n amber: this.getAmber(),\n orange: this.getOrange(),\n deepOrange: this.getDeepOrange(),\n brown: this.getBrown(),\n };\n }\n\n public getLightTheme(): LightTheme {\n return {\n mode: 'light',\n background: {\n main: '#efefef',\n light: '#fff',\n },\n header: {\n main: this.getBlue()[700],\n },\n primary: {\n main: '#1976d2',\n light: '#42a5f5',\n dark: '#1565c0',\n contrastText: '#fff',\n },\n secondary: {\n main: '#9c27b0',\n light: '#ba68c8',\n dark: '#7b1fa2',\n contrastText: '#fff',\n },\n error: {\n main: '#d32f2f',\n light: '#ef5350',\n dark: '#c62828',\n contrastText: '#fff',\n },\n warning: {\n main: '#ed6c02',\n light: '#ff9800',\n dark: '#e65100',\n contrastText: '#fff',\n },\n info: {\n main: '#0288d1',\n light: '#03a9f4',\n dark: '#01579b',\n contrastText: '#fff',\n },\n success: {\n main: '#2e7d32',\n light: '#4caf50',\n dark: '#1b5e20',\n contrastText: '#fff',\n },\n text: {\n primary: '#222222',\n secondary: '#666666',\n disabled: '#9E9E9E',\n },\n link: {\n primary: '#1976d2',\n },\n action: {\n active: 'rgba(0, 0, 0, 0.54)',\n disabled: 'rgba(0, 0, 0, 0.26)',\n disabledBackground: 'rgba(0, 0, 0, 0.12)',\n disabledOpacity: 0.38,\n focus: 'rgba(0, 0, 0, 0.12)',\n focusOpacity: 0.12,\n hover: 'rgba(0, 0, 0, 0.04)',\n hoverOpacity: 0.04,\n selected: 'rgba(0, 0, 0, 0.08)',\n selectedOpacity: 0.08,\n },\n grey: this.getGrey(),\n red: this.getRed(),\n pink: this.getPink(),\n purple: this.getPurple(),\n deepPurple: this.getDeepPurple(),\n indigo: this.getIndigo(),\n blue: this.getBlue(),\n lightBlue: this.getLightBlue(),\n cyan: this.getCyan(),\n teal: this.getTeal(),\n green: this.getGreen(),\n lightGreen: this.getLightGreen(),\n lime: this.getLime(),\n yellow: this.getYellow(),\n amber: this.getAmber(),\n orange: this.getOrange(),\n deepOrange: this.getDeepOrange(),\n brown: this.getBrown(),\n };\n }\n\n private getGrey(): ColorScale {\n return {\n 50: '#fafafa',\n 100: '#f5f5f5',\n 200: '#eeeeee',\n 300: '#e0e0e0',\n 400: '#bdbdbd',\n 500: '#9e9e9e',\n 600: '#757575',\n 700: '#616161',\n 800: '#424242',\n 900: '#212121',\n A100: '#f5f5f5',\n A200: '#eeeeee',\n A400: '#bdbdbd',\n A700: '#616161',\n };\n }\n\n private getRed(): ColorScale {\n return {\n 50: '#ffebee',\n 100: '#ffcdd2',\n 200: '#ef9a9a',\n 300: '#e57373',\n 400: '#ef5350',\n 500: '#f44336',\n 600: '#e53935',\n 700: '#d32f2f',\n 800: '#c62828',\n 900: '#b71c1c',\n A100: '#ff8a80',\n A200: '#ff5252',\n A400: '#ff1744',\n A700: '#d50000',\n };\n }\n\n private getPink(): ColorScale {\n return {\n 50: '#fce4ec',\n 100: '#f8bbd0',\n 200: '#f48fb1',\n 300: '#f06292',\n 400: '#ec407a',\n 500: '#e91e63',\n 600: '#d81b60',\n 700: '#c2185b',\n 800: '#ad1457',\n 900: '#880e4f',\n A100: '#ff80ab',\n A200: '#ff4081',\n A400: '#f50057',\n A700: '#c51162',\n };\n }\n\n private getPurple(): ColorScale {\n return {\n 50: '#f3e5f5',\n 100: '#e1bee7',\n 200: '#ce93d8',\n 300: '#ba68c8',\n 400: '#ab47bc',\n 500: '#9c27b0',\n 600: '#8e24aa',\n 700: '#7b1fa2',\n 800: '#6a1b9a',\n 900: '#4a148c',\n A100: '#ea80fc',\n A200: '#e040fb',\n A400: '#d500f8',\n A700: '#aa00ff',\n };\n }\n\n private getDeepPurple(): ColorScale {\n return {\n 50: '#ede7f6',\n 100: '#d1c4e9',\n 200: '#b39ddb',\n 300: '#9575cd',\n 400: '#7e57c2',\n 500: '#673ab7',\n 600: '#5e35b1',\n 700: '#512da8',\n 800: '#4527a0',\n 900: '#311b92',\n A100: '#b388ff',\n A200: '#7c4dff',\n A400: '#651fff',\n A700: '#6200ea',\n };\n }\n\n private getIndigo(): ColorScale {\n return {\n 50: '#e8eaf6',\n 100: '#c5cae9',\n 200: '#9fa8da',\n 300: '#7986cb',\n 400: '#5c6bc0',\n 500: '#3f51b5',\n 600: '#3949ab',\n 700: '#303f9f',\n 800: '#283593',\n 900: '#1a237e',\n A100: '#8c9eff',\n A200: '#536dfe',\n A400: '#3d5afe',\n A700: '#304ffe',\n };\n }\n\n private getBlue(): ColorScale {\n return {\n 50: '#e3f2fd',\n 100: '#bbdefb',\n 200: '#90caf9',\n 300: '#64b5f6',\n 400: '#42a5f5',\n 500: '#2196f3',\n 600: '#1e88e5',\n 700: '#1976d2',\n 800: '#1565c0',\n 900: '#0d47a1',\n A100: '#82b1ff',\n A200: '#448aff',\n A400: '#2979ff',\n A700: '#2962ff',\n };\n }\n\n private getLightBlue(): ColorScale {\n return {\n 50: '#e1f5fe',\n 100: '#b3e5fc',\n 200: '#81d4fa',\n 300: '#4fc3f7',\n 400: '#29b6f6',\n 500: '#03a9f4',\n 600: '#039be5',\n 700: '#0288d1',\n 800: '#0277bd',\n 900: '#01579b',\n A100: '#80d8ff',\n A200: '#40c4ff',\n A400: '#00b0ff',\n A700: '#0091ea',\n };\n }\n\n private getCyan(): ColorScale {\n return {\n 50: '#e0f7fa',\n 100: '#b2ebf2',\n 200: '#80deea',\n 300: '#4dd0e1',\n 400: '#26c6da',\n 500: '#00bcd4',\n 600: '#00acc1',\n 700: '#0097a7',\n 800: '#00838f',\n 900: '#006064',\n A100: '#84ffff',\n A200: '#18ffff',\n A400: '#00e5ff',\n A700: '#00b8d4',\n };\n }\n\n private getTeal(): ColorScale {\n return {\n 50: '#e0f2f1',\n 100: '#b2dfdb',\n 200: '#80cbc4',\n 300: '#4db6ac',\n 400: '#26a69a',\n 500: '#009688',\n 600: '#00897b',\n 700: '#00796b',\n 800: '#00695c',\n 900: '#004d40',\n A100: '#a7ffeb',\n A200: '#64ffda',\n A400: '#1de9b6',\n A700: '#00bfa5',\n };\n }\n\n private getGreen(): ColorScale {\n return {\n 50: '#e8f5e9',\n 100: '#c8e6c9',\n 200: '#a5d6a7',\n 300: '#81c784',\n 400: '#66bb6a',\n 500: '#4caf50',\n 600: '#43a047',\n 700: '#388e3c',\n 800: '#2e7d32',\n 900: '#1b5e20',\n A100: '#b9f6ca',\n A200: '#69f0ae',\n A400: '#00e676',\n A700: '#00c853',\n };\n }\n\n private getLightGreen(): ColorScale {\n return {\n 50: '#f1f8e9',\n 100: '#dcedc8',\n 200: '#c5e1a5',\n 300: '#aed581',\n 400: '#9ccc65',\n 500: '#8bc34a',\n 600: '#7cb342',\n 700: '#689f38',\n 800: '#558b2f',\n 900: '#33691e',\n A100: '#ccff90',\n A200: '#b2ff59',\n A400: '#76ff03',\n A700: '#64dd17',\n };\n }\n\n private getLime(): ColorScale {\n return {\n 50: '#f9fbe7',\n 100: '#f0f4c3',\n 200: '#e6ee9c',\n 300: '#dce775',\n 400: '#d4e157',\n 500: '#cddc39',\n 600: '#c0ca33',\n 700: '#afb42b',\n 800: '#9fa827',\n 900: '#827717',\n A100: '#f4ff81',\n A200: '#eeff41',\n A400: '#c6ff00',\n A700: '#aeea00',\n };\n }\n\n private getYellow(): ColorScale {\n return {\n 50: '#fffde7',\n 100: '#fff9c4',\n 200: '#fff59d',\n 300: '#fff176',\n 400: '#ffee58',\n 500: '#ffeb3b',\n 600: '#fdd835',\n 700: '#fbc02d',\n 800: '#f9a825',\n 900: '#f57f17',\n A100: '#ffff8d',\n A200: '#ffff00',\n A400: '#ffea00',\n A700: '#ffd600',\n };\n }\n\n private getAmber(): ColorScale {\n return {\n 50: '#fff8e1',\n 100: '#ffecb3',\n 200: '#ffe082',\n 300: '#ffd54f',\n 400: '#ffca28',\n 500: '#ffc107',\n 600: '#ffb300',\n 700: '#ffa000',\n 800: '#ff8f00',\n 900: '#ff6f00',\n A100: '#ffe57f',\n A200: '#ffd740',\n A400: '#ffc400',\n A700: '#ffab00',\n };\n }\n\n private getOrange(): ColorScale {\n return {\n 50: '#fff3e0',\n 100: '#ffe0b2',\n 200: '#ffcc80',\n 300: '#ffb74d',\n 400: '#ffa726',\n 500: '#ff9800',\n 600: '#fb8c00',\n 700: '#f57c00',\n 800: '#ef6c00',\n 900: '#e65100',\n A100: '#ffd180',\n A200: '#ffab40',\n A400: '#ff9100',\n A700: '#ff6d00',\n };\n }\n\n private getDeepOrange(): ColorScale {\n return {\n 50: '#fbe9e7',\n 100: '#ffccbc',\n 200: '#ffab91',\n 300: '#ff8a65',\n 400: '#ff7043',\n 500: '#ff5722',\n 600: '#f4511e',\n 700: '#e64a19',\n 800: '#d84315',\n 900: '#bf360c',\n A100: '#ff9e80',\n A200: '#ff6e40',\n A400: '#ff3d00',\n A700: '#dd2c00',\n };\n }\n\n private getBrown(): BrownScale {\n return {\n 50: '#efebe9',\n 100: '#d7ccc8',\n 200: '#bcaaa4',\n 300: '#a1887f',\n 400: '#8d6e63',\n 500: '#795548',\n 600: '#6d4c41',\n 700: '#5d4037',\n 800: '#4e342e',\n 900: '#3e2723',\n };\n }\n}\n\n", "/*\n * Copyright 2026 Evan Smalley.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n */\n\n// Handles toast components throughout the app\n\nexport interface ToastItem {\n id: number;\n message: string;\n type: string;\n exiting?: boolean;\n}\n\n// Define the shape of the listener function\nexport type ToastListener = (toasts: ToastItem[]) => void;\n\nexport class Toaster {\n private listeners: ToastListener[] = [];\n\n private toasts: ToastItem[] = [];\n\n // React component will subscribe to this\n subscribe(listener: ToastListener): () => void {\n this.listeners.push(listener);\n return () => {\n this.listeners = this.listeners.filter((l) => l !== listener);\n };\n }\n\n notify(): void {\n this.listeners.forEach((listener) => listener(this.toasts));\n }\n\n requestClose(id: number): void {\n this.toasts = this.toasts.map((t) => {\n if (t.id === id) {\n return { ...t, exiting: true };\n }\n return t;\n });\n this.notify();\n }\n\n add(message: string, type = 'info'): void {\n const id = Date.now();\n this.toasts = [...this.toasts, { id, message, type }];\n this.notify();\n\n // Auto-remove\n setTimeout(() => {\n this.requestClose(id);\n }, 4000);\n }\n\n remove(id: number): void {\n this.toasts = this.toasts.filter((t) => t.id !== id);\n this.notify();\n }\n}\n\nexport const toaster: Toaster = new Toaster();\n\nexport const toast: {\n info: (msg: string) => void;\n error: (msg: string) => void;\n success: (msg: string) => void;\n} = {\n info: (msg: string) => toaster.add(msg, 'info'),\n error: (msg: string) => toaster.add(msg, 'error'),\n success: (msg: string) => toaster.add(msg, 'success'),\n};\n", "/* eslint-disable no-bitwise */\n/*\n * Copyright 2026 Evan Smalley.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n */\n\n\n/**\n * Generate UUIDv7\n */\nclass UuidService {\n private lastTimestamp = -1;\n private seqCounter = 0;\n\n private getRandomBytes(size: number): Uint8Array {\n if (typeof globalThis.crypto?.getRandomValues === 'function') {\n const bytes = new Uint8Array(size);\n globalThis.crypto.getRandomValues(bytes);\n return bytes;\n }\n\n throw new Error('Secure crypto functionality is not available in this environment.');\n }\n\n public generateUUIDv7Bytes(): Uint8Array {\n let now = Date.now();\n\n if (now === this.lastTimestamp) {\n this.seqCounter++;\n\n // 12-bit counter overflow (> 4095 IDs in 1ms): advance timestamp artificially\n if (this.seqCounter > 0x0fff) {\n this.lastTimestamp++;\n now = this.lastTimestamp;\n this.seqCounter = 0;\n }\n } else if (now < this.lastTimestamp) {\n // Clock drift / NTP rollback: hold timestamp and increment counter to maintain monotonicity\n this.seqCounter++;\n if (this.seqCounter > 0x0fff) {\n this.lastTimestamp++;\n this.seqCounter = 0;\n }\n now = this.lastTimestamp;\n } else {\n // New millisecond: update state and reset sequence counter\n this.lastTimestamp = now;\n this.seqCounter = 0;\n }\n\n // Allocate 16 random bytes for remaining entropy (rand_b)\n const buf = this.getRandomBytes(16);\n\n // 1. Write 48-bit Unix timestamp into bytes 0..5\n buf[0] = Math.floor(now / 0x10000000000) & 0xff;\n buf[1] = Math.floor(now / 0x100000000) & 0xff;\n buf[2] = (now >>> 24) & 0xff;\n buf[3] = (now >>> 16) & 0xff;\n buf[4] = (now >>> 8) & 0xff;\n buf[5] = now & 0xff;\n\n // 2. Byte 6: Version 7 (0x70) + upper 4 bits of 12-bit counter\n buf[6] = 0x70 | ((this.seqCounter >> 8) & 0x0f);\n\n // 3. Byte 7: Lower 8 bits of 12-bit counter\n buf[7] = this.seqCounter & 0xff;\n\n // 4. Byte 8: Set Variant RFC 4122 (0x80) on remaining random bits\n buf[8] = (buf[8] & 0x3f) | 0x80;\n\n return buf;\n }\n\n /**\n * Convert a UUID string to binary Uint8Array\n */\n public uuidToBin(uuid: string): Uint8Array {\n const hex = uuid.replaceAll('-', '');\n\n if (!/^[0-9a-fA-F]{32}$/.test(hex)) {\n throw new Error(`Invalid UUID: ${uuid}`);\n }\n\n const bytes = new Uint8Array(16);\n\n for (let i = 0; i < 16; i++) {\n bytes[i] = parseInt(hex.substring(i * 2, i * 2 + 2), 16);\n }\n\n return bytes;\n }\n\n /**\n * Convert binary Uint8Array/Buffer to formatted UUID string\n */\n public binToUuid(buffer: Uint8Array): string {\n if (buffer.length !== 16) {\n throw new Error('UUID buffer must contain exactly 16 bytes.');\n }\n let hex = '';\n for (let i = 0; i < buffer.length; i++) {\n hex += buffer[i].toString(16).padStart(2, '0');\n }\n\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;\n }\n}\n// export as a singleton\nexport const uuidService = new UuidService();\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["Arithmetic", "number", "min", "max", "Arrayifier", "array", "currentIndex", "randomIndex", "arr", "n", "r", "index", "data", "i", "
|
|
3
|
+
"sources": ["../../src/Arithmetic.ts", "../../src/Arrayifier.ts", "../../src/CSV.ts", "../../src/Color.ts", "../../src/Numbers.ts", "../../src/Dates.ts", "../../src/Kontororu.ts", "../../src/Tasker.ts", "../../src/Kontororu/Socket.ts", "../../src/Objector.ts", "../../src/Kontororu/Store.ts", "../../src/Sorter.ts", "../../src/Textor.ts", "../../src/Style.ts", "../../src/Theme.ts", "../../src/Toaster.ts", "../../src/UuidService.ts"],
|
|
4
|
+
"sourcesContent": ["/*\n * Copyright 2026 Evan Smalley.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n */\n\n/**\n * Bounding, interpolation, and descriptive statistics.\n *\n * Every aggregate ignores nothing and validates nothing: pass it clean numbers.\n * Aggregates over an empty list return NaN rather than 0, so an empty data set\n * is visibly empty instead of silently reading as a real zero.\n *\n * That split holds across the package: an aggregate with nothing to work on\n * yields NaN, because the caller is asking about data rather than supplying a\n * bad argument, while an argument that cannot be honoured at all -- a chunk\n * size below 1, a step of 0 -- throws.\n */\nexport class Arithmetic {\n /**\n * Restrict a number to the inclusive range [min, max].\n */\n public static clamp(number: number, min: number, max: number): number {\n return Math.max(min, Math.min(number, max));\n }\n\n /**\n * Linearly interpolate between `a` and `b`.\n *\n * `amount` is clamped to 0..1, so the result never overshoots the endpoints.\n *\n * @example\n * Arithmetic.lerp(0, 100, 0.25); // 25\n */\n public static lerp(a: number, b: number, amount: number): number {\n return a + (b - a) * Arithmetic.clamp(amount, 0, 1);\n }\n\n /**\n * Round to a fixed number of decimal places.\n *\n * Uses exponent shifting rather than `Math.round(v * 10 ** p) / 10 ** p`,\n * which misrounds the common half-way cases (0.5 at the target precision).\n * A negative precision rounds to tens, hundreds, and so on.\n *\n * @example\n * Arithmetic.round(1.005, 2); // 1.01\n * Arithmetic.round(1234, -2); // 1200\n */\n public static round(value: number, precision: number = 0): number {\n if (!Number.isFinite(value)) {\n return value;\n }\n\n const shift = (input: number, exponent: number): number => {\n const parts = `${input}e`.split('e');\n return Number(`${parts[0]}e${Number(parts[1]) + exponent}`);\n };\n\n return shift(Math.round(shift(value, precision)), -precision);\n }\n\n /**\n * Re-map a number from one range onto another.\n *\n * @example\n * // A rating of 1500 on a 1000..2000 scale, as a 0..100 score.\n * Arithmetic.mapRange(1500, 1000, 2000, 0, 100); // 50\n */\n public static mapRange(\n value: number,\n inMin: number,\n inMax: number,\n outMin: number,\n outMax: number,\n ): number {\n if (inMax === inMin) {\n return outMin;\n }\n\n return outMin + ((value - inMin) / (inMax - inMin)) * (outMax - outMin);\n }\n\n /**\n * Scale a value within [min, max] onto 0..1. The inverse of `lerp`.\n *\n * Returns 0 for a zero-width range rather than dividing by zero.\n */\n public static normalize(value: number, min: number, max: number): number {\n if (max === min) {\n return 0;\n }\n\n return (value - min) / (max - min);\n }\n\n /**\n * Total of every value. An empty list sums to 0.\n */\n public static sum(values: number[]): number {\n return values.reduce((total, value) => total + value, 0);\n }\n\n /**\n * Arithmetic mean. NaN when the list is empty.\n */\n public static mean(values: number[]): number {\n if (values.length === 0) {\n return NaN;\n }\n\n return Arithmetic.sum(values) / values.length;\n }\n\n /**\n * Middle value, averaging the two middle values for an even-length list.\n * NaN when the list is empty.\n */\n public static median(values: number[]): number {\n return Arithmetic.percentile(values, 50);\n }\n\n /**\n * The most frequent values, in first-seen order.\n *\n * Returns every tied value rather than picking one arbitrarily, and an empty\n * array for an empty list.\n */\n public static mode(values: number[]): number[] {\n if (values.length === 0) {\n return [];\n }\n\n const counts = new Map<number, number>();\n\n for (let i = 0; i < values.length; i++) {\n const value = values[i];\n counts.set(value, (counts.get(value) ?? 0) + 1);\n }\n\n // Walked rather than Math.max(...counts.values()): spreading a large set of\n // distinct values overflows the argument stack.\n let highest = 0;\n counts.forEach((count) => {\n if (count > highest) {\n highest = count;\n }\n });\n\n const modes: number[] = [];\n counts.forEach((count, value) => {\n if (count === highest) {\n modes.push(value);\n }\n });\n\n return modes;\n }\n\n /**\n * Variance. Sample variance (dividing by n - 1) by default; pass\n * `population` to divide by n instead.\n *\n * NaN when there are too few values to be meaningful \u2014 fewer than 2 for a\n * sample, or none at all for a population.\n */\n public static variance(values: number[], population: boolean = false): number {\n const divisor = population ? values.length : values.length - 1;\n\n if (divisor <= 0) {\n return NaN;\n }\n\n const average = Arithmetic.mean(values);\n const squaredDeviations = values.reduce(\n (total, value) => total + (value - average) ** 2,\n 0,\n );\n\n return squaredDeviations / divisor;\n }\n\n /**\n * Standard deviation, the square root of the variance.\n */\n public static stdDev(values: number[], population: boolean = false): number {\n return Math.sqrt(Arithmetic.variance(values, population));\n }\n\n /**\n * The value at the given percentile (0-100), interpolating linearly between\n * the two neighbouring values when the percentile falls between them.\n *\n * NaN when the list is empty.\n *\n * @example\n * Arithmetic.percentile([1, 2, 3, 4], 50); // 2.5\n */\n public static percentile(values: number[], p: number): number {\n if (values.length === 0) {\n return NaN;\n }\n\n const sorted = [...values].sort((a, b) => a - b);\n\n if (sorted.length === 1) {\n return sorted[0];\n }\n\n const position = (Arithmetic.clamp(p, 0, 100) / 100) * (sorted.length - 1);\n const lower = Math.floor(position);\n const upper = Math.ceil(position);\n\n if (lower === upper) {\n return sorted[lower];\n }\n\n return sorted[lower] + (sorted[upper] - sorted[lower]) * (position - lower);\n }\n}\n", "/*\n * Copyright 2026 Evan Smalley.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n */\n\n// Built once: a collator is far cheaper to reuse than String.localeCompare,\n// which rebuilds its collation table on every comparison.\nconst COLLATOR = new Intl.Collator();\n\nexport class Arrayifier {\n // constructor() {\n // }\n\n\n /**\n * Shuffle / ranomize elements in an array\n * @param {array} array The array to shuffle\n * @return array\n */\n public static shuffle<T>(array: T[]): T[] {\n let currentIndex: number = array.length;\n let randomIndex: number;\n\n // While there remain elements to shuffle.\n while (currentIndex !== 0) {\n // Pick a remaining element.\n randomIndex = Math.floor(Math.random() * currentIndex);\n currentIndex--;\n\n // And swap it with the current element.\n // eslint-disable-next-line no-param-reassign\n [array[currentIndex], array[randomIndex]] = [\n array[randomIndex], array[currentIndex]];\n }\n\n return array;\n }\n\n /**\n * Recursively generates all combinations of size `r` from an array of `n` elements.\n *\n * @param {T[]} arr - The source array to generate combinations from\n * @param {number} n - The total number of elements in `arr` (i.e. arr.length)\n * @param {number} r - The size of each combination to generate\n * @param {number} index - Current position being filled in the combination (increments toward r)\n * @param {T[]} data - Temporary buffer holding the current combination being built\n * @param {number} i - Current index in `arr` being considered for inclusion\n * @param {T[][]} results - Accumulator array that collects each completed combination\n * @returns {T[][]} The accumulated list of all combinations once recursion completes\n *\n * @example\n * combination([1, 2, 3], 3, 2, 0, [], 0, [])\n * // returns [[1, 2], [1, 3], [2, 3]]\n */\n public static combination<T>(\n arr: T[],\n n: number,\n r: number,\n index: number,\n data: T[],\n i: number,\n results: T[][],\n ): T[][] {\n if (index === r) {\n results.push(data.slice(0, r));\n return results;\n }\n\n if (i >= n) {\n return results;\n }\n\n // eslint-disable-next-line no-param-reassign\n data[index] = arr[i];\n this.combination(arr, n, r, index + 1, data, i + 1, results);\n this.combination(arr, n, r, index, data, i + 1, results);\n\n return results;\n }\n\n /**\n * Get all combinations of size `r` from the provided array.\n *\n * @param arr The source array\n * @param r The size of each combination\n *\n * @example\n * Arrayifier.getCombinations([1, 2, 3], 2);\n * // [[1, 2], [1, 3], [2, 3]]\n */\n public static getCombinations<T>(arr: T[], r: number): T[][];\n /**\n * Get all combinations of size `r`, considering only the first `n` elements.\n *\n * @param arr The source array\n * @param n How many leading elements to draw from\n * @param r The size of each combination\n */\n public static getCombinations<T>(arr: T[], n: number, r: number): T[][];\n public static getCombinations<T>(arr: T[], nOrR: number, maybeR?: number): T[][] {\n // Two-argument form: `n` is the whole array, so callers need not repeat\n // arr.length. The three-argument form is kept for existing callers.\n const n = maybeR === undefined ? arr.length : nOrR;\n const r = maybeR === undefined ? nOrR : maybeR;\n\n const data: T[] = new Array(r);\n\n let results: T[][] = [];\n results = this.combination(arr, n, r, 0, data, 0, results);\n return results;\n }\n\n /**\n * Split an array into consecutive chunks of at most `size`.\n *\n * @example\n * Arrayifier.chunk([1, 2, 3, 4, 5], 2); // [[1, 2], [3, 4], [5]]\n */\n public static chunk<T>(arr: T[], size: number): T[][] {\n if (size < 1) {\n throw new Error(`chunk size must be at least 1. Sent ${size}`);\n }\n\n const chunks: T[][] = [];\n\n for (let i = 0; i < arr.length; i += size) {\n chunks.push(arr.slice(i, i + size));\n }\n\n return chunks;\n }\n\n /**\n * Remove duplicate values, keeping the first occurrence of each.\n *\n * Compares by identity, so it suits primitives; use `uniqueBy` for objects.\n *\n * @example\n * Arrayifier.unique([1, 2, 2, 3, 1]); // [1, 2, 3]\n */\n public static unique<T>(arr: T[]): T[] {\n return [...new Set(arr)];\n }\n\n /**\n * Remove duplicates by a derived key, keeping the first of each key.\n *\n * @example\n * Arrayifier.uniqueBy(players, (p) => p.team_id);\n */\n public static uniqueBy<T, K>(arr: T[], keyFn: (item: T, index: number) => K): T[] {\n const seen = new Set<K>();\n\n return arr.filter((item, index) => {\n const key = keyFn(item, index);\n\n if (seen.has(key)) {\n return false;\n }\n\n seen.add(key);\n return true;\n });\n }\n\n /**\n * Bucket items by a derived key.\n *\n * @example\n * Arrayifier.groupBy(games, (g) => g.season);\n * // { 2025: [...], 2026: [...] }\n */\n public static groupBy<T, K extends string | number>(\n arr: T[],\n keyFn: (item: T, index: number) => K,\n ): Record<K, T[]> {\n // Null prototype: a key drawn from data can be '__proto__', which on a\n // plain object hits the prototype setter instead of creating an own entry.\n const groups = Object.create(null) as Record<K, T[]>;\n\n for (let i = 0; i < arr.length; i++) {\n const key = keyFn(arr[i], i);\n\n if (!groups[key]) {\n groups[key] = [];\n }\n\n groups[key].push(arr[i]);\n }\n\n return groups;\n }\n\n /**\n * Count items by a derived key.\n *\n * @example\n * Arrayifier.countBy(games, (g) => g.status); // { final: 12, live: 3 }\n */\n public static countBy<T, K extends string | number>(\n arr: T[],\n keyFn: (item: T, index: number) => K,\n ): Record<K, number> {\n // Null prototype for the same reason as `groupBy`: on a plain object a\n // '__proto__' key is swallowed by the prototype setter and the count lost.\n const counts = Object.create(null) as Record<K, number>;\n\n for (let i = 0; i < arr.length; i++) {\n const key = keyFn(arr[i], i);\n counts[key] = (counts[key] ?? 0) + 1;\n }\n\n return counts;\n }\n\n /**\n * Sort by a derived value, without mutating the input.\n *\n * Numbers compare numerically and everything else as strings. Null and\n * undefined keys sort last regardless of direction.\n *\n * @example\n * Arrayifier.sortBy(teams, (t) => t.rating, 'desc');\n */\n public static sortBy<T>(\n arr: T[],\n keyFn: (item: T) => string | number | null | undefined,\n direction: 'asc' | 'desc' = 'asc',\n ): T[] {\n const factor = direction === 'desc' ? -1 : 1;\n\n // Keys are derived once per item rather than once per comparison: sort\n // calls the comparator O(n log n) times, and keyFn is caller-supplied.\n const decorated = arr.map((item) => ({ item, key: keyFn(item) }));\n\n decorated.sort((a, b) => {\n const aKey = a.key;\n const bKey = b.key;\n\n const aEmpty = aKey === null || aKey === undefined;\n const bEmpty = bKey === null || bKey === undefined;\n\n if (aEmpty && bEmpty) {\n return 0;\n }\n if (aEmpty) {\n return 1;\n }\n if (bEmpty) {\n return -1;\n }\n\n if (typeof aKey === 'number' && typeof bKey === 'number') {\n return (aKey - bKey) * factor;\n }\n\n return COLLATOR.compare(String(aKey), String(bKey)) * factor;\n });\n\n return decorated.map((entry) => entry.item);\n }\n\n /**\n * Split into the items that satisfy the predicate and those that do not.\n *\n * @example\n * const [wins, losses] = Arrayifier.partition(games, (g) => g.won);\n */\n public static partition<T>(\n arr: T[],\n predicate: (item: T, index: number) => boolean,\n ): [T[], T[]] {\n const passed: T[] = [];\n const failed: T[] = [];\n\n arr.forEach((item, index) => {\n if (predicate(item, index)) {\n passed.push(item);\n } else {\n failed.push(item);\n }\n });\n\n return [passed, failed];\n }\n\n /**\n * A sequence of numbers from `start` up to but excluding `end`.\n *\n * Called with one argument, counts from 0 up to it.\n *\n * @example\n * Arrayifier.range(4); // [0, 1, 2, 3]\n * Arrayifier.range(1, 4); // [1, 2, 3]\n * Arrayifier.range(0, 10, 5); // [0, 5]\n */\n public static range(start: number, end?: number, step: number = 1): number[] {\n const from = end === undefined ? 0 : start;\n const to = end === undefined ? start : end;\n\n if (step === 0) {\n throw new Error('range step cannot be 0');\n }\n\n const values: number[] = [];\n\n if (step > 0) {\n for (let i = from; i < to; i += step) {\n values.push(i);\n }\n } else {\n for (let i = from; i > to; i += step) {\n values.push(i);\n }\n }\n\n return values;\n }\n}\n", "/*\n * Copyright 2026 Evan Smalley.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n */\n\n/**\n * Everything to help with CSV generation\n */\nexport class CSV {\n /**\n * Escape a single value for CSV.\n *\n * RFC 4180 escapes an embedded quote by doubling it, so JSON.stringify()\n * (which uses a backslash) cannot be used here.\n */\n private static escape(value: unknown): string {\n if (value === null || value === undefined) {\n return '';\n }\n\n const str = String(value);\n\n if (/[\",\\r\\n]/.test(str)) {\n return `\"${str.replaceAll('\"', '\"\"')}\"`;\n }\n\n return str;\n }\n\n /**\n * Convert an object of rows into a CSV string.\n *\n * Headers are the union of every row's keys, so rows that carry extra\n * columns are not silently truncated to the shape of the first row.\n */\n public static stringify(data: Record<string, Record<string, unknown>>): string {\n const headers: string[] = [];\n const seen = new Set<string>();\n\n for (const id in data) {\n Object.keys(data[id] ?? {}).forEach((key) => {\n if (!seen.has(key)) {\n seen.add(key);\n headers.push(key);\n }\n });\n }\n\n if (headers.length === 0) {\n return '';\n }\n\n const rows: string[] = [headers.map((header) => CSV.escape(header)).join(',')];\n\n for (const id in data) {\n const row = data[id] ?? {};\n // escape() handles the empty cases itself, so no `||` default here:\n // 0, false and '' are real values and have to survive as written.\n rows.push(headers.map((header) => CSV.escape(row[header])).join(','));\n }\n\n return rows.join('\\n');\n }\n\n /**\n * Convert an object to a CSV file and then download it\n */\n public static download(data: Record<string, Record<string, unknown>>): void {\n const content = CSV.stringify(data);\n\n // Create a Blob and trigger download\n const blob = new Blob([content], { type: 'text/csv' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = 'srating-data.csv';\n\n // Trigger download and clean up\n document.body.appendChild(a);\n a.click();\n URL.revokeObjectURL(url);\n a.remove();\n }\n}\n", "/* eslint-disable no-param-reassign */\n/* eslint-disable default-case */\n/* eslint-disable no-multi-assign */\n/*\n * Copyright 2026 Evan Smalley.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n */\n\n/* eslint-disable no-mixed-operators */\n/* eslint-disable no-bitwise */\n\n\nexport class Color {\n // constructor() {\n // }\n\n\n /**\n * A linear interpolator for hexadecimal colors\n * @param {string} a\n * @param {string} b\n * @param {number} amount\n * @example\n * // returns #7F7F7F\n * lerpColor('#000000', '#ffffff', 0.5)\n * @return {string}\n */\n public static lerpColor(a: string, b: string, amount: number): string {\n // Go through hexToRgb so shorthand (#fff) and invalid input are handled\n // consistently; parsing '0x' + the raw string treats '#fff' as 0x0fff.\n const [ar, ag, ab] = Color.hexToRgb(a);\n const [br, bg, bb] = Color.hexToRgb(b);\n\n // Channels have to stay within 0..255: a value outside that range carries\n // into the neighbouring byte of the packed integer below.\n const t = Math.min(1, Math.max(0, amount));\n\n const rr = Math.trunc(ar + t * (br - ar));\n const rg = Math.trunc(ag + t * (bg - ag));\n const rb = Math.trunc(ab + t * (bb - ab));\n\n return `#${((1 << 24) + (rr << 16) + (rg << 8) + rb).toString(16).slice(1)}`;\n }\n\n /**\n * Get a color that will look readable based on a background color\n */\n public static getTextColor(color: string, backgroundColor: string, debug = false): string {\n // Convert hex colors to RGB\n /*\n let [r1, g1, b1] = Color.hexToRgb(color);\n const [r2, g2, b2] = Color.hexToRgb(backgroundColor);\n\n const brightnessBg = Color.calculateBrightness(r2, g2, b2);\n\n const targetBrightness = brightnessBg > 128 ? 50 : 150; // target brightness threshold for contrast\n\n while (true) {\n const brightnessColor = Color.calculateBrightness(r1, g1, b1);\n\n if (\n (brightnessBg > 128 && brightnessColor < targetBrightness) ||\n (brightnessBg <= 128 && brightnessColor > targetBrightness)\n ) {\n break;\n }\n\n if (brightnessBg > 128) {\n r1 = Math.max(0, r1 - 25);\n g1 = Math.max(0, g1 - 25);\n b1 = Math.max(0, b1 - 25);\n } else {\n r1 = Math.min(255, r1 + 25);\n g1 = Math.min(255, g1 + 25);\n b1 = Math.min(255, b1 + 25);\n }\n\n if ((r1 === 0 && g1 === 0 && b1 === 0) || (r1 === 255 && g1 === 255 && b1 === 255)) {\n break; // avoid infinite loop\n }\n }\n\n // Convert back to hex\n return Color.rgbToHex(r1, g1, b1);\n */\n let [r, g, b] = Color.hexToRgb(color);\n const [br, bg, bb] = Color.hexToRgb(backgroundColor);\n const contrastTarget = 4.5;\n\n if (debug) {\n console.log('Color.getContrastRatio([r, g, b], [br, bg, bb])', Color.getContrastRatio([r, g, b], [br, bg, bb]));\n }\n\n if (Color.getContrastRatio([r, g, b], [br, bg, bb]) >= contrastTarget) {\n return Color.rgbToHex(r, g, b);\n }\n\n const contrastToBlack = Color.getContrastRatio([0, 0, 0], [br, bg, bb]);\n const contrastToWhite = Color.getContrastRatio([255, 255, 255], [br, bg, bb]);\n\n const direction: 'lighter' | 'darker' =\n contrastToWhite > contrastToBlack ? 'lighter' : 'darker';\n\n\n if (debug) {\n console.log('contrastToBlack', contrastToBlack);\n console.log('contrastToWhite', contrastToWhite);\n console.log('direction', direction);\n }\n\n const adjust = (c: number, lighter: boolean) => {\n return lighter ? Math.min(255, c + 10) : Math.max(0, c - 10);\n };\n\n for (let i = 0; i < 25; i++) {\n r = adjust(r, direction === 'lighter');\n g = adjust(g, direction === 'lighter');\n b = adjust(b, direction === 'lighter');\n\n if (debug) {\n console.log('Color.getContrastRatio([r, g, b], [br, bg, bb]) 2', Color.getContrastRatio([r, g, b], [br, bg, bb]));\n }\n\n if (Color.getContrastRatio([r, g, b], [br, bg, bb]) >= contrastTarget) {\n break;\n }\n }\n\n return Color.rgbToHex(r, g, b);\n }\n\n public static getContrastRatio(rgb1: [number, number, number], rgb2: [number, number, number]): number {\n const luminance = (r: number, g: number, b: number): number => {\n const a = [r, g, b].map((v) => {\n v /= 255;\n return v <= 0.03928\n ? v / 12.92\n : Math.pow((v + 0.055) / 1.055, 2.4);\n });\n return a[0] * 0.2126 + a[1] * 0.7152 + a[2] * 0.0722;\n };\n\n const lum1 = luminance(...rgb1) + 0.05;\n const lum2 = luminance(...rgb2) + 0.05;\n\n return lum1 > lum2 ? lum1 / lum2 : lum2 / lum1;\n }\n\n /**\n * Take a hex (#fff) and an amount and darken the color, return a hex\n * @param {string} hex\n * @param {number} amount\n * @return {string} hex\n */\n // public static darken(hex: string, amount: number = 0.02): string {\n // const [r, g, b] = this.hexToRgb(hex);\n // const [h, s, l] = this.rgbToHsl(r, g, b);\n\n // const newL = Math.max(0, (l / 100) - amount) * 100;\n // const [r2, g2, b2] = this.hslToRgb(h, s, newL);\n\n // return this.rgbToHex(r2, g2, b2);\n // }\n\n /**\n * Take a hex (#fff) and an amount and lighten the color, return a hex\n * @param {string} hex\n * @param {number} amount\n * @return {string} hex\n */\n // public static lighten(hex: string, amount: number = 0.02): string {\n // const [r, g, b] = this.hexToRgb(hex);\n // const [h, s, l] = this.rgbToHsl(r, g, b);\n\n // const newL = Math.min(1, (l / 100) + amount) * 100;\n // const [r2, g2, b2] = this.hslToRgb(h, s, newL);\n\n // return this.rgbToHex(r2, g2, b2);\n // }\n\n /**\n * Mixes the color with black to create a Shade.\n * Prevents the \"muddy/brown\" look of HSL darkening.\n * @param {string} hex - The color to darken\n * @param {number} amount - 0 to 1 (e.g. 0.1 is 10% darker)\n * @return {string} hex\n */\n public static darken(hex: string, amount: number = 0.1): string {\n const [r, g, b] = this.hexToRgb(hex);\n\n // Calculate new color by mixing with black (0)\n // Formula: Current * (1 - amount)\n const remaining = 1 - amount;\n const r2 = Math.round(r * remaining);\n const g2 = Math.round(g * remaining);\n const b2 = Math.round(b * remaining);\n\n return this.rgbToHex(r2, g2, b2);\n }\n\n /**\n * Mixes the color with white to create a Tint.\n * cleaner and less \"washed out\" than HSL lightness adjustment.\n * @param {string} hex - The color to lighten\n * @param {number} amount - 0 to 1 (e.g. 0.1 is 10% lighter)\n * @return {string} hex\n */\n public static lighten(hex: string, amount: number = 0.1): string {\n const [r, g, b] = this.hexToRgb(hex);\n\n // Calculate new color by mixing with white (255)\n // Formula: Current + ((Target - Current) * amount)\n const r2 = Math.round(r + (255 - r) * amount);\n const g2 = Math.round(g + (255 - g) * amount);\n const b2 = Math.round(b + (255 - b) * amount);\n\n return this.rgbToHex(r2, g2, b2);\n }\n\n\n public static shadeColor(hex: string, percent: number): string {\n let [r, g, b] = Color.hexToRgb(hex);\n\n r = Math.min(255, Math.max(0, Math.round(r + (r * (percent / 100)))));\n g = Math.min(255, Math.max(0, Math.round(g + (g * (percent / 100)))));\n b = Math.min(255, Math.max(0, Math.round(b + (b * (percent / 100)))));\n\n return Color.rgbToHex(r, g, b);\n }\n\n\n /**\n * Are 2 colors similar to each other?\n * @param {string} color1\n * @param {string} color2\n * @param {number} threshold\n * @return {boolean}\n */\n public static areColorsSimilar(color1: string, color2: string, threshold = 50): boolean {\n const distance = Color.colorDistance(color1, color2);\n return distance < threshold;\n }\n\n\n /**\n * Inverts a hex color\n * @param {string} hex\n * @return {string} hex\n */\n public static invertColor(hex: string): string {\n const [r, g, b] = Color.hexToRgb(hex);\n\n // Invert each color component\n const invertedR = 255 - r;\n const invertedG = 255 - g;\n const invertedB = 255 - b;\n\n return Color.rgbToHex(invertedR, invertedG, invertedB);\n }\n\n\n /**\n * Takes a hex (#fff) and returns an rgba with the provided alpha\n * @param {string} hex\n * @param {number} alpha\n * @return {string} rgba()\n */\n public static alphaColor(hex: string, alpha: number): string {\n const [r, g, b] = this.hexToRgb(hex);\n\n return `rgba(${r}, ${g}, ${b}, ${alpha})`;\n }\n\n\n /**\n * Gets analogous colors\n * @param {string} hex\n * @return {Array<string>}\n */\n public static getAnalogousColors(hex: string): string[] {\n const [r, g, b] = Color.hexToRgb(hex);\n const [h, s, l] = Color.rgbToHsl(r, g, b);\n\n const analogousColors: string[] = [];\n const offset = 30; // Offset for analogous colors, usually 30 degrees\n\n for (let i = -1; i <= 1; i++) {\n if (i !== 0) {\n const newHue = (h + i * offset + 360) % 360;\n const [newR, newG, newB] = Color.hslToRgb(newHue, s, l);\n analogousColors.push(Color.rgbToHex(newR, newG, newB));\n }\n }\n\n return analogousColors;\n }\n\n\n /**\n * Convert hex to rgb\n * @param {string} hex\n * @return {Array} rgb\n */\n public static hexToRgb(hex: string): [number, number, number] {\n // Remove the hash at the start if it's there\n let h = hex.replace(/^#/, '');\n\n // Handle 3-character hex codes by expanding them to 6-character\n if (h.length === 3) {\n h = h.split('').map((char) => { return char + char; }).join('');\n }\n\n // Ensure it's a valid 6-character hex code.\n // Checking the characters as well as the length matters: parseInt() on a\n // non-hex string yields NaN, and NaN >> 16 is 0, so an invalid input would\n // otherwise be silently reported as black.\n if (!/^[0-9a-fA-F]{6}$/.test(h)) {\n throw new Error(`Invalid hex color format: ${hex}`);\n }\n\n // Parse r, g, b values\n const bigint = parseInt(h, 16);\n const r = (bigint >> 16) & 255;\n const g = (bigint >> 8) & 255;\n const b = bigint & 255;\n\n return [r, g, b];\n }\n\n\n /**\n * Convert rgb to hex.\n *\n * Channels are rounded and clamped to 0..255, so a value outside that range\n * cannot overflow into the packed integer and produce a malformed string.\n *\n * @param {number} r\n * @param {number} g\n * @param {number} b\n * @return {string}\n */\n public static rgbToHex(r: number, g: number, b: number): string {\n const channel = (value: number) => Math.round(Math.min(255, Math.max(0, value)));\n\n return `#${((1 << 24) + (channel(r) << 16) + (channel(g) << 8) + channel(b)).toString(16).slice(1).toUpperCase()}`;\n }\n\n /**\n * Convert rgb to hsl, as [hue 0-360, saturation 0-100, lightness 0-100].\n *\n * @example\n * Color.rgbToHsl(255, 0, 0); // [0, 100, 50]\n */\n public static rgbToHsl(r: number, g: number, b: number): [number, number, number] {\n r /= 255;\n g /= 255;\n b /= 255;\n const max = Math.max(r, g, b);\n const min = Math.min(r, g, b);\n let h = 0;\n let s = 0;\n const l = (max + min) / 2;\n\n if (max === min) {\n h = s = 0; // achromatic\n } else {\n const d = max - min;\n s = l > 0.5 ? d / (2 - max - min) : d / (max + min);\n switch (max) {\n case r: h = (g - b) / d + (g < b ? 6 : 0); break;\n case g: h = (b - r) / d + 2; break;\n case b: h = (r - g) / d + 4; break;\n }\n h /= 6;\n }\n return [h * 360, s * 100, l * 100];\n }\n\n /**\n * Convert hsl to rgb. Hue wraps, saturation and lightness are 0-100.\n *\n * @example\n * Color.hslToRgb(0, 100, 50); // [255, 0, 0]\n */\n public static hslToRgb(h: number, s: number, l: number): [number, number, number] {\n let r;\n let g;\n let b;\n h /= 360;\n s /= 100;\n l /= 100;\n\n if (s === 0) {\n r = g = b = l; // achromatic\n } else {\n const hue2rgb = (p: number, q: number, t: number) => {\n if (t < 0) t += 1;\n if (t > 1) t -= 1;\n if (t < 1 / 6) return p + (q - p) * 6 * t;\n // The plateau runs to 1/2 and the falling edge to 2/3.\n if (t < 1 / 2) return q;\n if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;\n return p;\n };\n\n const q = l < 0.5 ? l * (1 + s) : l + s - l * s;\n const p = 2 * l - q;\n r = hue2rgb(p, q, h + 1 / 3);\n g = hue2rgb(p, q, h);\n b = hue2rgb(p, q, h - 1 / 3);\n }\n\n return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];\n }\n\n private static calculateBrightness(r: number, g: number, b: number): number {\n // Calculate the brightness of the color\n return (r * 299 + g * 587 + b * 114) / 1000;\n }\n\n private static colorDistance(color1: string, color2: string): number {\n const [r1, g1, b1] = Color.hexToRgb(color1);\n const [r2, g2, b2] = Color.hexToRgb(color2);\n\n const dr = r1 - r2;\n const dg = g1 - g2;\n const db = b1 - b2;\n\n return Math.sqrt(dr * dr + dg * dg + db * db);\n }\n}\n", "/*\n * Copyright 2026 Evan Smalley.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n */\n\nimport { Arithmetic } from './Arithmetic.js';\n\n// Constructing an Intl formatter costs orders of magnitude more than using one,\n// and these methods are called per row when rendering a table.\nconst FORMATTERS = new Map<string, Intl.NumberFormat>();\n\nconst MAGNITUDES: readonly (readonly [number, string])[] = [\n [1e12, 'T'],\n [1e9, 'B'],\n [1e6, 'M'],\n [1e3, 'K'],\n];\n\nconst DURATIONS: readonly (readonly [number, string])[] = [\n [86_400_000, 'd'],\n [3_600_000, 'h'],\n [60_000, 'm'],\n [1_000, 's'],\n [1, 'ms'],\n];\n\nconst BYTE_UNITS: readonly string[] = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];\n\n/**\n * Human-readable number formatting: ranks, compact counts, percentages,\n * durations, and file sizes.\n */\nexport class Numbers {\n /**\n * The English ordinal suffix for a number: 'st', 'nd', 'rd', or 'th'.\n *\n * @example\n * Numbers.ordinalSuffix(1); // 'st'\n * Numbers.ordinalSuffix(12); // 'th'\n */\n public static ordinalSuffix(value: number): string {\n const absolute = Math.abs(Math.trunc(value));\n\n // 11th, 12th and 13th break the 1st/2nd/3rd pattern.\n if (absolute % 100 >= 11 && absolute % 100 <= 13) {\n return 'th';\n }\n\n switch (absolute % 10) {\n case 1: {\n return 'st';\n }\n case 2: {\n return 'nd';\n }\n case 3: {\n return 'rd';\n }\n default: {\n return 'th';\n }\n }\n }\n\n /**\n * A number with its ordinal suffix attached.\n *\n * @example\n * Numbers.formatOrdinal(3); // '3rd'\n */\n public static formatOrdinal(value: number): string {\n const whole = Math.trunc(value);\n\n return `${whole}${Numbers.ordinalSuffix(whole)}`;\n }\n\n /**\n * A number with locale grouping separators.\n *\n * @example\n * Numbers.format(1234567.891, 2); // '1,234,567.89'\n */\n public static format(value: number, decimals?: number, locale: string = 'en-US'): string {\n if (!Number.isFinite(value)) {\n return String(value);\n }\n\n const maximumFractionDigits = decimals ?? 20;\n const key = `${locale}|${decimals ?? ''}|${maximumFractionDigits}`;\n\n let formatter = FORMATTERS.get(key);\n\n if (!formatter) {\n formatter = new Intl.NumberFormat(locale, {\n minimumFractionDigits: decimals,\n maximumFractionDigits,\n });\n FORMATTERS.set(key, formatter);\n }\n\n return formatter.format(value);\n }\n\n /**\n * A signed number, always carrying an explicit '+' or '-'.\n *\n * Useful for deltas such as a change in rank or rating.\n *\n * @example\n * Numbers.formatSigned(3); // '+3'\n * Numbers.formatSigned(0); // '0'\n */\n public static formatSigned(value: number, decimals?: number): string {\n if (value > 0) {\n return `+${Numbers.format(value, decimals)}`;\n }\n\n return Numbers.format(value, decimals);\n }\n\n /**\n * A large number shortened with a magnitude suffix.\n *\n * Implemented directly rather than through Intl's compact notation, whose\n * exact output varies with the runtime's ICU data.\n *\n * @example\n * Numbers.formatCompact(1234); // '1.2K'\n * Numbers.formatCompact(1500000); // '1.5M'\n */\n public static formatCompact(value: number, decimals: number = 1): string {\n if (!Number.isFinite(value)) {\n return String(value);\n }\n\n const absolute = Math.abs(value);\n const sign = value < 0 ? '-' : '';\n\n const unit = MAGNITUDES.find(([threshold]) => absolute >= threshold);\n\n if (!unit) {\n return `${Arithmetic.round(value, decimals)}`;\n }\n\n const [threshold, suffix] = unit;\n // Trim a trailing '.0' so whole magnitudes read as '2M', not '2.0M'.\n const scaled = Arithmetic.round(absolute / threshold, decimals);\n\n return `${sign}${scaled}${suffix}`;\n }\n\n /**\n * A ratio rendered as a percentage.\n *\n * @param fromRatio When true (the default) the input is a 0..1 ratio;\n * when false it is already a percentage.\n *\n * @example\n * Numbers.formatPercent(0.1234); // '12.3%'\n * Numbers.formatPercent(12.34, 1, false); // '12.3%'\n */\n public static formatPercent(\n value: number,\n decimals: number = 1,\n fromRatio: boolean = true,\n ): string {\n if (!Number.isFinite(value)) {\n return String(value);\n }\n\n const percent = fromRatio ? value * 100 : value;\n\n return `${Numbers.format(Arithmetic.round(percent, decimals), decimals)}%`;\n }\n\n /**\n * A duration in milliseconds as a compact human string.\n *\n * @param parts How many magnitude units to show, largest first.\n *\n * @example\n * Numbers.formatDuration(3_725_000); // '1h 2m'\n * Numbers.formatDuration(3_725_000, 3); // '1h 2m 5s'\n */\n public static formatDuration(ms: number, parts: number = 2): string {\n if (!Number.isFinite(ms)) {\n return String(ms);\n }\n\n const sign = ms < 0 ? '-' : '';\n let remaining = Math.abs(Math.trunc(ms));\n\n const pieces: [number, string][] = [];\n let started = false;\n\n for (let i = 0; i < DURATIONS.length; i++) {\n const [size, suffix] = DURATIONS[i];\n const amount = Math.floor(remaining / size);\n\n if (amount > 0) {\n started = true;\n }\n\n // Skip leading zero units, but keep interior ones (1h 0m 5s).\n if (started) {\n pieces.push([amount, suffix]);\n remaining -= amount * size;\n }\n }\n\n if (pieces.length === 0) {\n return '0ms';\n }\n\n const selected = pieces.slice(0, Math.max(1, parts));\n\n // Trailing zero units carry no information ('5s', not '5s 0ms'), unlike\n // the interior ones kept above.\n while (selected.length > 1 && selected[selected.length - 1][0] === 0) {\n selected.pop();\n }\n\n return `${sign}${selected.map(([amount, suffix]) => `${amount}${suffix}`).join(' ')}`;\n }\n\n /**\n * A byte count as a human-readable file size, using binary (1024) steps.\n *\n * @example\n * Numbers.formatBytes(1536); // '1.5 KB'\n */\n public static formatBytes(bytes: number, decimals: number = 1): string {\n if (!Number.isFinite(bytes)) {\n return String(bytes);\n }\n\n const absolute = Math.abs(bytes);\n const sign = bytes < 0 ? '-' : '';\n\n if (absolute < 1024) {\n return `${sign}${Math.trunc(absolute)} B`;\n }\n\n // Index of the largest unit that leaves a value of at least 1.\n const exponent = Math.min(\n Math.floor(Math.log(absolute) / Math.log(1024)),\n BYTE_UNITS.length - 1,\n );\n\n const scaled = Arithmetic.round(absolute / 1024 ** exponent, decimals);\n\n return `${sign}${scaled} ${BYTE_UNITS[exponent]}`;\n }\n}\n", "/*\n * Copyright 2026 Evan Smalley.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n */\n\n/* eslint-disable one-var-declaration-per-line */\n/* eslint-disable one-var */\n\nimport { IANATimeZone } from './Timezones.js';\nimport { Numbers } from './Numbers.js';\n\n\nexport class Dates {\n // constructor() {\n // }\n\n /*\n * Robust Date Parsing\n * Handles:\n * - Date Objects / Numbers (Timestamps)\n * - ISO Strings (2025-01-01) -> Forces Local Midnight\n * - US Formats (01/05/2026)\n * - Mixed Time Formats (23:00 pm, 5:00pm, 14:30:00)\n */\n public static parse(\n str?: Date | string | number | undefined | null,\n utc = false,\n ): Date {\n // 1. Handle Null / Undefined -> Return Now\n if (!str) {\n return new Date();\n }\n\n // 2. Handle Existing Date Objects -> Return Copy\n if (str instanceof Date) {\n return new Date(str.getTime());\n }\n\n // 3. Handle Timestamps (Numbers)\n if (typeof str === 'number') {\n return new Date(str);\n }\n\n // 4. Handle Strings\n if (typeof str === 'string') {\n const input = str.trim();\n\n // CASE A: Strict ISO Date \"YYYY-MM-DD\"\n // Native JS parses this as UTC Midnight, which often shows as\n // previous day 7pm EST. We force \"T00:00:00\" to make it Local Midnight.\n if (/^\\d{4}-\\d{2}-\\d{2}$/.test(input)) {\n return utc ? new Date(`${input}T00:00:00Z`) : new Date(`${input}T00:00:00`);\n }\n\n // CASE B: Manual Parsing for Complex Strings\n // This handles \"2026-01-05 23:03:19 pm\", \"01/05/2026\", etc.\n\n // Step 1: Extract Date Part (YYYY-MM-DD or MM/DD/YYYY)\n // Regex looks for: (Group 1: Year/Month) -or/ (Group 2: Month/Day) -or/ (Group 3: Day/Year)\n let year, month, day, timePart = '';\n\n // Match YYYY-MM-DD or YYYY/MM/DD\n const isoMatch = input.match(/^(\\d{4})[-/](\\d{1,2})[-/](\\d{1,2})(.*)$/);\n\n // Match MM/DD/YYYY or MM-DD-YYYY\n const usMatch = input.match(/^(\\d{1,2})[-/](\\d{1,2})[-/](\\d{4})(.*)$/);\n\n if (isoMatch) {\n year = parseInt(isoMatch[1], 10);\n month = parseInt(isoMatch[2], 10) - 1; // JS Months are 0-11\n day = parseInt(isoMatch[3], 10);\n timePart = isoMatch[4];\n } else if (usMatch) {\n year = parseInt(usMatch[3], 10);\n month = parseInt(usMatch[1], 10) - 1;\n day = parseInt(usMatch[2], 10);\n timePart = usMatch[4];\n } else {\n // Fallback: Let the browser try its best if our regex fails\n const d = new Date(input);\n return isNaN(d.getTime()) ? new Date() : d;\n }\n\n // Step 2: Extract Time Part\n let hours = 0;\n let minutes = 0;\n let seconds = 0;\n\n // Look for HH:MM(:SS) and optional AM/PM in the remaining string\n if (timePart && timePart.trim().length > 0) {\n // Matches: 23:03, 23:03:19, 5:00pm, 5:00 pm\n const timeMatch = timePart.match(/(\\d{1,2}):(\\d{1,2})(?::(\\d{1,2}))?\\s*(am|pm|AM|PM)?/);\n\n if (timeMatch) {\n hours = parseInt(timeMatch[1], 10);\n minutes = parseInt(timeMatch[2], 10);\n seconds = timeMatch[3] ? parseInt(timeMatch[3], 10) : 0;\n const meridiem = timeMatch[4] ? timeMatch[4].toLowerCase() : null;\n\n // Step 3: Normalize Hours (12h to 24h)\n if (meridiem === 'pm' && hours < 12) {\n hours += 12;\n }\n if (meridiem === 'am' && hours === 12) {\n hours = 0;\n }\n // Note: If input is \"23:00 pm\", we ignore the 'pm' because 23 > 12.\n }\n }\n\n if (utc) {\n return new Date(Date.UTC(year, month, day, hours, minutes, seconds));\n }\n\n // Step 4: Construct Date in Local Time\n return new Date(year, month, day, hours, minutes, seconds);\n }\n\n return new Date();\n }\n\n public static getMonthsShort(): string[] {\n return ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];\n }\n\n public static getMonths(): string[] {\n return ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];\n }\n\n public static getDaysShort(): string[] {\n return ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];\n }\n\n public static getDays(): string[] {\n return ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];\n }\n\n /**\n * Format a date using php syntax\n *\n | Token | Meaning | Example |\n | ----- | ------------------------- | ------- |\n | `Y` | 4-digit year | 2025 |\n | `y` | 2-digit year | 25 |\n | `m` | 2-digit month | 03 |\n | `n` | month (no leading zero) | 3 |\n | `d` | day (2-digit) | 09 |\n | `j` | day (no leading zero) | 9 |\n | `S` | Ordinal suffix | th |\n | `H` | 24-hour | 14 |\n | `G` | 24-hour (no leading zero) | 14 |\n | `h` | 12-hour | 02 |\n | `g` | 12-hour (no leading zero) | 2 |\n | `i` | minutes | 05 |\n | `s` | seconds | 09 |\n | `A` | AM/PM | PM |\n | `a` | am/pm | pm |\n | `w` | day of week (0\u20136) | 1 |\n | `N` | day of week (1\u20137) | 2 |\n | `M` | short month name | Mar |\n | `F` | full month name | March |\n | `D` | short weekday | Mon |\n | `l` | full weekday | Monday |\n | `T` | Timezone abbreviation | EST |\n | `e` | Timezone identifier | America/New_York |\n */\n public static format(dateInput: Date | string, format: string, utc = false): string {\n // `utc` has to reach the parser too: parsing \"2025-01-01\" as local midnight\n // and then reading UTC getters shifts the result by the local offset.\n const date = this.parse(dateInput, utc);\n const pad = (n: number) => String(n).padStart(2, '0');\n\n const monthsShort = this.getMonthsShort();\n const monthsLong = this.getMonths();\n const daysShort = this.getDaysShort();\n const daysLong = this.getDays();\n\n const Y = utc ? date.getUTCFullYear() : date.getFullYear();\n const y = String(Y).slice(-2);\n const month = utc ? date.getUTCMonth() : date.getMonth();\n const dateNum = utc ? date.getUTCDate() : date.getDate();\n const day = utc ? date.getUTCDay() : date.getDay();\n const hours = utc ? date.getUTCHours() : date.getHours();\n const minutes = utc ? date.getUTCMinutes() : date.getMinutes();\n const seconds = utc ? date.getUTCSeconds() : date.getSeconds();\n\n // Dynamically look up current runtime/system timezone strings\n const tzAbbr = utc\n ? 'UTC'\n : new Intl.DateTimeFormat('en-US', { timeZoneName: 'short' })\n .format(date)\n .split(', ')\n .pop() || '';\n\n const tzIdentifier = utc\n ? 'UTC'\n : new Intl.DateTimeFormat('en-US', { timeZoneName: 'long' })\n .resolvedOptions().timeZone || '';\n\n const tokens: Record<string, string> = {\n /// Year\n Y: String(Y),\n y,\n\n // Month\n m: pad(month + 1),\n n: String(month + 1),\n M: monthsShort[month],\n F: monthsLong[month],\n\n // Day\n d: pad(dateNum),\n j: String(dateNum),\n D: daysShort[day],\n l: daysLong[day],\n w: String(day), // 0 (Sun) - 6\n N: String(day === 0 ? 7 : day), // 1 (Mon) - 7 (Sun)\n S: Numbers.ordinalSuffix(dateNum),\n\n // Time\n H: pad(hours),\n G: String(hours),\n h: pad(((hours + 11) % 12) + 1),\n g: String(((hours + 11) % 12) + 1),\n i: pad(minutes),\n s: pad(seconds),\n\n // AM/PM\n A: hours < 12 ? 'AM' : 'PM',\n a: hours < 12 ? 'am' : 'pm',\n\n // Timezone\n T: tzAbbr,\n e: tzIdentifier,\n };\n\n // Replace tokens using regex\n return format.replace(/\\\\(.)|([a-zA-Z])/g, (_, esc, token) => {\n if (esc) {\n // literal escaped char like \\H or \\Y \u2192 return the raw letter\n return esc;\n }\n return tokens[token] ?? token;\n });\n }\n\n public static add(date: Date | string, amount: number, unit: 'years' | 'months' | 'days' | 'hours' | 'minutes'): Date {\n const d = this.parse(date);\n\n if (unit === 'years') {\n const originalDay = d.getDate();\n d.setFullYear(d.getFullYear() + amount);\n // Handle Leap Year Rollover:\n // Feb 29, 2024 + 1 year -> Mar 1, 2025 (Standard JS behavior)\n // If strict \"same day or last day of month\" logic is desired (turning it into Feb 28):\n if (d.getDate() !== originalDay) {\n d.setDate(0); // Set to last day of previous month (Feb 28)\n }\n } else if (unit === 'months') {\n const originalDay = d.getDate();\n d.setMonth(d.getMonth() + amount);\n // Handle rollover: Jan 31 + 1 month -> Feb 28/29\n if (d.getDate() !== originalDay) {\n d.setDate(0); // Set to last day of previous month\n }\n } else if (unit === 'days') {\n // Use setDate to be DST safe (24h addition via ms is unsafe across DST)\n d.setDate(d.getDate() + amount);\n } else {\n const map: Record<'hours' | 'minutes', number> = {\n hours: amount * 60 * 60 * 1000,\n minutes: amount * 60 * 1000,\n };\n // Use getTime() for day/hour/minute units for simple millisecond addition\n d.setTime(d.getTime() + map[unit]);\n }\n\n return d;\n }\n\n public static subtract(\n date: Date | string,\n amount: number,\n unit: 'years' | 'months' | 'days' | 'hours' | 'minutes',\n ): Date {\n return this.add(date, -amount, unit);\n }\n\n public static fromNow(date: Date | string): string {\n const d = this.parse(date);\n const diff = Date.now() - d.getTime();\n const mins = Math.floor(diff / 60000);\n\n if (Math.abs(mins) < 1) {\n return 'just now';\n }\n\n // Handle future dates roughly\n if (mins < 0) {\n return 'in the future';\n }\n\n if (mins < 60) {\n return `${mins}m ago`;\n }\n\n const hours = Math.floor(mins / 60);\n\n if (hours < 24) {\n return `${hours}h ago`;\n }\n\n const days = Math.floor(hours / 24);\n\n return `${days}d ago`;\n }\n\n /**\n * Find the closest date in an array of dates\n */\n public static getClosestDate(dateToMatch: string | Date, datesArray: string[]): string | null {\n if (!datesArray.length) {\n return null;\n }\n\n const matchDate = this.parse(dateToMatch).getTime();\n\n let closestDate: string | null = null;\n let closestDist = Infinity;\n\n // eslint-disable-next-line no-restricted-syntax\n for (const dateStr of datesArray) {\n const currDate = this.parse(dateStr).getTime();\n const dist = Math.abs(currDate - matchDate);\n\n if (dist < closestDist) {\n closestDist = dist;\n closestDate = dateStr;\n } else if (dist === closestDist) {\n // Tie-breaker: Prefer the date that is in the future relative to the matchDate\n // Or if both are same direction, just keep the current one (or implementation defined)\n // Requirement: \"Both 17th and 19th have same dist. It should pick 19th\"\n if (currDate > matchDate) {\n closestDate = dateStr;\n }\n }\n }\n\n return closestDate;\n }\n\n public static getTodayEST(): string {\n return this.format(new Date().toLocaleString('en-US', { timeZone: 'America/New_York' }), 'Y-m-d');\n }\n\n public static getStartOfDay(date: Date | string): Date {\n const d = this.parse(date);\n d.setHours(0, 0, 0, 0);\n return d;\n }\n\n public static getStartOfMonth(date: Date | string): Date {\n const d = this.parse(date);\n d.setDate(1);\n d.setHours(0, 0, 0, 0);\n return d;\n }\n\n /**\n * The last representable instant of the day, 23:59:59.999 local.\n */\n public static getEndOfDay(date: Date | string): Date {\n const d = this.parse(date);\n d.setHours(23, 59, 59, 999);\n return d;\n }\n\n /**\n * The last representable instant of the month.\n */\n public static getEndOfMonth(date: Date | string): Date {\n const d = this.parse(date);\n // Day 0 of the following month is the last day of this one.\n d.setMonth(d.getMonth() + 1, 0);\n d.setHours(23, 59, 59, 999);\n return d;\n }\n\n /**\n * How many days the date's month contains.\n */\n public static getDaysInMonth(date: Date | string): number {\n return this.getEndOfMonth(date).getDate();\n }\n\n public static getStartOfGrid(date: Date | string): Date {\n const d = this.getStartOfMonth(date);\n const dayOfWeek = d.getDay(); // 0 (Sunday) is the start in standard JS\n\n // Move back to the beginning of the week\n const result = this.parse(d);\n // Subtract days to get to the start of the week (Sunday)\n result.setDate(d.getDate() - dayOfWeek);\n return result;\n }\n\n /**\n * The Saturday closing the week that contains the end of the month.\n *\n * Pairs with `getStartOfGrid` to bound a full month view; feed both into\n * `eachDayOfInterval` to get the cells.\n */\n public static getEndOfGrid(date: Date | string): Date {\n const d = this.getEndOfMonth(date);\n const result = this.getStartOfDay(d);\n\n // 6 is Saturday, the last column of a Sunday-first grid.\n result.setDate(d.getDate() + (6 - d.getDay()));\n return result;\n }\n\n /**\n * Every day from `start` to `end` inclusive, as local midnights.\n *\n * Steps with setDate so it stays correct across DST boundaries. Returns an\n * empty array when `end` falls before `start`.\n *\n * @example\n * Dates.eachDayOfInterval(Dates.getStartOfGrid(d), Dates.getEndOfGrid(d));\n */\n public static eachDayOfInterval(start: Date | string, end: Date | string): Date[] {\n const last = this.getStartOfDay(end).getTime();\n const current = this.getStartOfDay(start);\n\n const days: Date[] = [];\n\n while (current.getTime() <= last) {\n days.push(new Date(current.getTime()));\n current.setDate(current.getDate() + 1);\n }\n\n return days;\n }\n\n /**\n * Whether a date falls between two others.\n *\n * Compares exact instants, not calendar days; pair with `getStartOfDay` and\n * `getEndOfDay` for a whole-day range. The bounds may be given in either\n * order.\n *\n * @param inclusive Whether a date landing exactly on a bound counts.\n */\n public static isBetween(\n date: Date | string,\n start: Date | string,\n end: Date | string,\n inclusive: boolean = true,\n ): boolean {\n const value = this.parse(date).getTime();\n const a = this.parse(start).getTime();\n const b = this.parse(end).getTime();\n\n const lower = Math.min(a, b);\n const upper = Math.max(a, b);\n\n return inclusive\n ? value >= lower && value <= upper\n : value > lower && value < upper;\n }\n\n public static isSameDay(date1: Date | string, date2: Date | string): boolean {\n if (!date1 || !date2) {\n return false;\n }\n const d1 = this.parse(date1);\n const d2 = this.parse(date2);\n\n return (\n d1.getFullYear() === d2.getFullYear() &&\n d1.getMonth() === d2.getMonth() &&\n d1.getDate() === d2.getDate()\n );\n }\n\n // Helper to check if one date is before another (ignoring time)\n public static isBeforeDay(date1: Date | string, date2: Date | string): boolean {\n if (!date1 || !date2) {\n return false;\n }\n return this.getStartOfDay(date1).getTime() < this.getStartOfDay(date2).getTime();\n }\n\n // Helper to check if one date is after another (ignoring time)\n public static isAfterDay(date1: Date | string, date2: Date | string): boolean {\n if (!date1 || !date2) {\n return false;\n }\n return this.getStartOfDay(date1).getTime() > this.getStartOfDay(date2).getTime();\n }\n\n /**\n * Determines if a given date is observing Daylight Saving Time (DST)\n * relative to the runtime's local timezone.\n */\n public static isDST(dateInput?: Date | string | number | null): boolean {\n const d = this.parse(dateInput);\n const year = d.getFullYear();\n\n // Get the timezone offset for January 1st and July 1st of the same year\n const janOffset = new Date(year, 0, 1).getTimezoneOffset();\n const julOffset = new Date(year, 6, 1).getTimezoneOffset();\n\n // The standard time offset is always the maximum of the two.\n // Example (New York): EST is 300 mins behind UTC, EDT is 240 mins. Max is 300.\n // Example (Sydney): AEST is -600 mins, AEDT is -660 mins. Max is -600.\n const standardTimezoneOffset = Math.max(janOffset, julOffset);\n\n // If the date's offset is less than the standard offset, it is in DST\n return d.getTimezoneOffset() < standardTimezoneOffset;\n }\n\n /**\n * Extracts the exact wall-clock date and time components for a specific timezone.\n * @param dateInput The date to evaluate (defaults to now)\n * @param timeZone The target IANA timezone (e.g., 'America/New_York')\n * @returns An object containing numeric date components (month is 1-12)\n */\n public static getPartsInZone(\n dateInput?: Date | string | number | null,\n timeZone: IANATimeZone = 'America/New_York',\n ): {\n year: number;\n month: number;\n day: number;\n hour: number;\n minute: number;\n second: number;\n weekday: string;\n } {\n const d = this.parse(dateInput);\n\n const allTimeZones = Intl.supportedValuesOf('timeZone');\n\n if (!allTimeZones.includes(timeZone)) {\n throw new Error('Unsupported timeZone.');\n }\n\n const formatter = new Intl.DateTimeFormat('en-US', {\n timeZone,\n year: 'numeric',\n month: 'numeric',\n day: 'numeric',\n hour: 'numeric',\n minute: 'numeric',\n second: 'numeric',\n weekday: 'long', // Adds \"Monday\", \"Tuesday\", etc. to the output\n hourCycle: 'h23',\n });\n\n const parts = formatter.formatToParts(d);\n\n const getPart = (type: Intl.DateTimeFormatPartTypes) => parseInt(parts.find((p) => p.type === type)?.value || '0', 10);\n\n const weekday = parts.find((p) => p.type === 'weekday')?.value || '';\n\n return {\n year: getPart('year'),\n month: getPart('month'), // 1-12 format\n day: getPart('day'),\n hour: getPart('hour'), // 0-23 format\n minute: getPart('minute'),\n second: getPart('second'),\n weekday,\n };\n }\n\n /**\n * Calculates the difference between two dates (`date1 - date2`).\n *\n * @param date1 Primary date\n * @param date2 Comparison date (defaults to current time)\n * @param utc Whether to parse strings as UTC\n */\n public static diff(\n date1: Date | string | number,\n date2: Date | string | number = new Date(),\n utc = false,\n ): {\n milliseconds: number;\n seconds: number;\n minutes: number;\n hours: number;\n days: number;\n weeks: number;\n months: number;\n years: number;\n abs: {\n milliseconds: number;\n seconds: number;\n minutes: number;\n hours: number;\n days: number;\n weeks: number;\n months: number;\n years: number;\n }\n } {\n const d1 = this.parse(date1, utc);\n const d2 = this.parse(date2, utc);\n\n const ms = d1.getTime() - d2.getTime();\n\n // Calendar-based month and year differences\n const y1 = utc ? d1.getUTCFullYear() : d1.getFullYear();\n const y2 = utc ? d2.getUTCFullYear() : d2.getFullYear();\n const m1 = utc ? d1.getUTCMonth() : d1.getMonth();\n const m2 = utc ? d2.getUTCMonth() : d2.getMonth();\n\n const months = (y1 - y2) * 12 + (m1 - m2);\n const years = y1 - y2;\n\n const seconds = Math.trunc(ms / 1000);\n const minutes = Math.trunc(ms / (1000 * 60));\n const hours = Math.trunc(ms / (1000 * 60 * 60));\n const days = Math.trunc(ms / (1000 * 60 * 60 * 24));\n const weeks = Math.trunc(ms / (1000 * 60 * 60 * 24 * 7));\n\n return {\n milliseconds: ms,\n seconds,\n minutes,\n hours,\n days,\n weeks,\n months,\n years,\n // Helper containing absolute (positive) values\n abs: {\n milliseconds: Math.abs(ms),\n seconds: Math.abs(seconds),\n minutes: Math.abs(minutes),\n hours: Math.abs(hours),\n days: Math.abs(days),\n weeks: Math.abs(weeks),\n months: Math.abs(months),\n years: Math.abs(years),\n },\n };\n }\n}\n\n", "/*\n * Copyright 2026 Evan Smalley.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n */\n\n// \u30B3\u30F3\u30C8\u30ED\u30FC\u30EB\n\ntype Listener = (...args: unknown[]) => void;\n\nexport class Kontororu extends EventTarget {\n /**\n * Set membership is what keeps registration, removal and teardown O(1) per\n * listener instead of a scan of everything registered for that type.\n *\n * A Map rather than an object literal because an event type is a\n * caller-supplied string: '__proto__' on an object literal resolves to the\n * prototype rather than to an entry of its own.\n */\n private listeners = new Map<string, Set<Listener>>();\n\n addEventListener(type: string, listener: Listener): this {\n super.addEventListener(type, listener);\n\n let registered = this.listeners.get(type);\n\n if (!registered) {\n registered = new Set();\n this.listeners.set(type, registered);\n }\n\n // EventTarget ignores a repeated (type, listener) pair, so the bookkeeping\n // must not record it twice either, or a single removeEventListener() would\n // leave a stale entry behind. A Set gives that without scanning.\n registered.add(listener);\n\n return this;\n }\n\n removeEventListener(type: string, listener: Listener): this {\n super.removeEventListener(type, listener);\n\n this.listeners.get(type)?.delete(listener);\n\n return this;\n }\n\n removeAllEventListeners() {\n // Removing entries from a Set mid-iteration is well defined -- an entry\n // deleted before it is reached is simply never visited -- so this walks\n // the live Set rather than a copy of it.\n this.listeners.forEach((registered, type) => {\n registered.forEach((listener) => {\n this.removeEventListener(type, listener);\n });\n });\n }\n\n getListeners(type: string): Listener[] {\n const registered = this.listeners.get(type);\n\n // A copy: the internal Set is the bookkeeping, and handing it out would let\n // a caller desynchronise it from the EventTarget underneath.\n return registered ? [...registered] : [];\n }\n}\n\n\n", "/*\n * Copyright 2026 Evan Smalley.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n/* These two stylistic rules misread the `(...args: any[]) => any` generic\n constraint on each wrapper as a function declaration. */\n/* eslint-disable space-before-function-paren */\n/* eslint-disable function-paren-newline */\n\n/**\n * A debounced or throttled wrapper, plus the controls to abandon or force a\n * pending call.\n */\nexport interface Scheduled<T extends (...args: any[]) => any> {\n (...args: Parameters<T>): void;\n /** Drop any pending call. */\n cancel: () => void;\n /** Run any pending call immediately. */\n flush: () => void;\n /** Whether a call is currently waiting to run. */\n pending: () => boolean;\n}\n\n/**\n * A memoized wrapper, plus access to its cache.\n */\nexport interface Memoized<T extends (...args: any[]) => any> {\n (...args: Parameters<T>): ReturnType<T>;\n /** Forget every cached result. */\n clear: () => void;\n /** How many results are cached. */\n size: () => number;\n}\n\nexport interface BackoffOptions {\n /** Delay before the first retry, in milliseconds. */\n delay?: number;\n /** Multiplier applied per attempt. */\n factor?: number;\n /** Ceiling for any single delay, in milliseconds. */\n maxDelay?: number;\n /** Randomize each delay across 0..computed, to avoid a thundering herd. */\n jitter?: boolean;\n}\n\nexport interface RetryOptions extends BackoffOptions {\n /** Total number of attempts, including the first. */\n attempts?: number;\n /** Called before each retry with the error and the upcoming attempt number. */\n onRetry?: (error: unknown, attempt: number) => void;\n /** Return false to stop retrying a particular error. */\n shouldRetry?: (error: unknown) => boolean;\n}\n\n/**\n * Wrappers for controlling how and when other functions run.\n */\nexport class Tasker {\n /**\n * Resolve after a delay.\n *\n * @example\n * await Tasker.sleep(250);\n */\n public static sleep(ms: number): Promise<void> {\n return new Promise((resolve) => {\n setTimeout(resolve, ms);\n });\n }\n\n /**\n * The delay to wait before a given retry attempt, growing exponentially.\n *\n * Attempt 0 is the delay before the first retry.\n *\n * @example\n * Tasker.backoff(0); // 1000\n * Tasker.backoff(3); // 8000\n */\n public static backoff(attempt: number, options: BackoffOptions = {}): number {\n const {\n delay = 1000,\n factor = 2,\n maxDelay = 30_000,\n jitter = false,\n } = options;\n\n const computed = Math.min(delay * factor ** Math.max(0, attempt), maxDelay);\n\n return jitter ? Math.random() * computed : computed;\n }\n\n /**\n * Call an async function until it succeeds, backing off between attempts.\n *\n * Rethrows the final error once the attempts are exhausted.\n *\n * @example\n * const data = await Tasker.retry(() => fetchRatings(), { attempts: 5 });\n */\n public static async retry<T>(\n fn: (attempt: number) => T | Promise<T>,\n options: RetryOptions = {},\n ): Promise<T> {\n const { attempts = 3, onRetry, shouldRetry, ...backoffOptions } = options;\n const total = Math.max(1, attempts);\n\n let lastError: unknown;\n\n for (let attempt = 0; attempt < total; attempt++) {\n try {\n // Sequential by design: each attempt waits for the previous to fail.\n // eslint-disable-next-line no-await-in-loop\n return await fn(attempt);\n } catch (error) {\n lastError = error;\n\n const isLast = attempt === total - 1;\n if (isLast || (shouldRetry && !shouldRetry(error))) {\n throw error;\n }\n\n if (onRetry) {\n onRetry(error, attempt + 1);\n }\n\n // eslint-disable-next-line no-await-in-loop\n await Tasker.sleep(Tasker.backoff(attempt, backoffOptions));\n }\n }\n\n throw lastError;\n }\n\n /**\n * Delay a function until it has stopped being called for `wait` ms.\n *\n * @param leading Run on the first call instead of after the pause.\n *\n * @example\n * const search = Tasker.debounce((term: string) => query(term), 300);\n */\n public static debounce<T extends (...args: any[]) => any>(\n fn: T,\n wait: number = 0,\n leading: boolean = false,\n ): Scheduled<T> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n let lastArgs: Parameters<T> | undefined;\n\n const run = () => {\n timer = undefined;\n\n if (lastArgs) {\n const args = lastArgs;\n lastArgs = undefined;\n fn(...args);\n }\n };\n\n const debounced = (...args: Parameters<T>): void => {\n const callNow = leading && timer === undefined;\n\n lastArgs = args;\n\n if (timer !== undefined) {\n clearTimeout(timer);\n }\n\n timer = setTimeout(run, wait);\n\n if (callNow) {\n lastArgs = undefined;\n fn(...args);\n }\n };\n\n debounced.cancel = () => {\n if (timer !== undefined) {\n clearTimeout(timer);\n timer = undefined;\n }\n lastArgs = undefined;\n };\n\n debounced.flush = () => {\n if (timer !== undefined) {\n clearTimeout(timer);\n run();\n }\n };\n\n debounced.pending = () => lastArgs !== undefined;\n\n return debounced;\n }\n\n /**\n * Allow a function to run at most once per `wait` ms.\n *\n * The first call runs immediately; a call made during the cooling-off period\n * runs once the period ends, carrying the most recent arguments.\n *\n * @example\n * const onScroll = Tasker.throttle(() => measure(), 100);\n */\n public static throttle<T extends (...args: any[]) => any>(\n fn: T,\n wait: number = 0,\n ): Scheduled<T> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n let lastArgs: Parameters<T> | undefined;\n\n const run = () => {\n if (lastArgs) {\n const args = lastArgs;\n lastArgs = undefined;\n // Keep the window open so a burst cannot collapse into back-to-back calls.\n timer = setTimeout(run, wait);\n fn(...args);\n } else {\n timer = undefined;\n }\n };\n\n const throttled = (...args: Parameters<T>): void => {\n if (timer !== undefined) {\n lastArgs = args;\n return;\n }\n\n timer = setTimeout(run, wait);\n fn(...args);\n };\n\n throttled.cancel = () => {\n if (timer !== undefined) {\n clearTimeout(timer);\n timer = undefined;\n }\n lastArgs = undefined;\n };\n\n throttled.flush = () => {\n if (lastArgs) {\n const args = lastArgs;\n lastArgs = undefined;\n fn(...args);\n }\n };\n\n throttled.pending = () => lastArgs !== undefined;\n\n return throttled;\n }\n\n /**\n * Cache a function's results, keyed by its arguments.\n *\n * The default key is a JSON serialization of the arguments, which suits\n * primitives; pass `keyFn` for anything else.\n *\n * @example\n * const ratingFor = Tasker.memoize((teamId: number) => compute(teamId));\n */\n public static memoize<T extends (...args: any[]) => any>(\n fn: T,\n keyFn?: (...args: Parameters<T>) => string,\n ): Memoized<T> {\n // CONSIDER(evan): the cache is unbounded. Callers keying on something\n // open-ended (a request id, a user-supplied string) will grow it forever;\n // an optional maxSize with FIFO eviction would cap that, at the cost of a\n // wider public interface.\n const cache = new Map<string, ReturnType<T>>();\n\n const memoized = (...args: Parameters<T>): ReturnType<T> => {\n const key = keyFn ? keyFn(...args) : JSON.stringify(args);\n const cached = cache.get(key);\n\n // Distinguishes a cached `undefined` from a miss without a second lookup.\n if (cached !== undefined || cache.has(key)) {\n return cached as ReturnType<T>;\n }\n\n const result = fn(...args) as ReturnType<T>;\n cache.set(key, result);\n\n return result;\n };\n\n memoized.clear = () => cache.clear();\n memoized.size = () => cache.size;\n\n return memoized;\n }\n\n /**\n * Allow a function to run only once, returning the first result thereafter.\n *\n * @example\n * const init = Tasker.once(() => connect());\n */\n public static once<T extends (...args: any[]) => any>(\n fn: T,\n ): (...args: Parameters<T>) => ReturnType<T> {\n let called = false;\n let result: ReturnType<T>;\n\n return (...args: Parameters<T>): ReturnType<T> => {\n if (!called) {\n called = true;\n result = fn(...args) as ReturnType<T>;\n }\n\n return result;\n };\n }\n}\n", "/*\n * Copyright 2026 Evan Smalley.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n */\n\nimport { Kontororu } from '../Kontororu.js';\nimport { Tasker } from '../Tasker.js';\n\n\ninterface SocketConfig {\n hostname: string;\n port?: string | number;\n path: string;\n}\n\ntype ConnectionState = 'connected' | 'stale' | 'disconnected' | 'reconnected';\n\ntype SocketMessage = {\n type: 'subscribe' | 'unsubscribe' | 'data' | 'heartbeat';\n table: string;\n id: string;\n}\n\ntype SocketResponseMessage = {\n table: string;\n id: string;\n data: object;\n}\n\nconst debug = false;\n\nclass Socket extends Kontororu {\n private config?: SocketConfig;\n\n private ws?: WebSocket;\n\n private connection_state: ConnectionState = 'connected';\n\n private session_id?: string;\n\n private message_queue: SocketMessage[] = [];\n\n // Reconnection logic\n private reconnect_attempts: number = 0;\n private should_reconnect = true;\n private reconnect_timeout?: NodeJS.Timeout;\n\n // Heartbeat / Sleep Detection Logic\n private last_heartbeat_timestamp: number = Date.now();\n // How often the server pings THIS specific client (5 seconds)\n private readonly HEARTBEAT_INTERVAL_MS = 5000;\n // Calculate threshold: 2 missed beats + 1 second of network jitter buffer\n private readonly SUSPENSION_THRESHOLD_MS = (this.HEARTBEAT_INTERVAL_MS * 2) + 1000;\n // 3 Heartbeats + 1s buffer = 16 seconds\n private readonly DISCONNECT_THRESHOLD_MS = (this.HEARTBEAT_INTERVAL_MS * 3) + 1000;\n\n constructor() {\n super();\n if (typeof document !== 'undefined') {\n document.addEventListener('visibilitychange', (event) => {\n if (document.visibilityState === 'visible') {\n this.check_staleness('tab_switch');\n }\n });\n }\n\n if (typeof window !== 'undefined') {\n let offline_timeout: ReturnType<typeof setTimeout> | undefined;\n\n const stopOfflineChecks = () => {\n if (offline_timeout) {\n clearTimeout(offline_timeout);\n offline_timeout = undefined;\n }\n };\n\n const offlineChecker = () => {\n // A flapping connection fires 'offline' repeatedly. Each run owns its\n // own `checked` counter but shares offline_timeout, so an earlier chain\n // left running would become uncancellable and poll forever.\n stopOfflineChecks();\n\n const check = 3;\n let checked = 1;\n\n const checker = () => {\n if (checked > check) {\n offline_timeout = undefined;\n return;\n }\n offline_timeout = setTimeout(\n () => {\n this.check_staleness('offline');\n checked++;\n checker();\n },\n (this.HEARTBEAT_INTERVAL_MS) + 500,\n );\n };\n\n checker();\n };\n\n window.addEventListener('online', () => {\n // Cancel the pending staleness polls rather than unregistering the\n // 'offline' handler, which would leave every later offline event\n // undetected.\n stopOfflineChecks();\n this.check_staleness('online');\n });\n window.addEventListener('offline', offlineChecker);\n }\n }\n\n private get_url() {\n if (!this.config) {\n throw new Error('Socket not configured');\n }\n\n const { hostname, port, path } = this.config;\n\n const protocol = (typeof window !== 'undefined' && window.location && window.location.protocol && window.location.protocol === 'https:' ? 'wss:' : 'ws:');\n\n return `${protocol}//${hostname}${port ? `:${port}` : ''}/${path}`;\n }\n\n public connect(session_id: string, config?: SocketConfig) {\n if (config) {\n this.config = config;\n }\n\n if (!session_id) {\n console.warn('session_id required to open ws');\n return;\n }\n\n if (\n this.ws &&\n (\n this.ws.readyState === WebSocket.OPEN ||\n this.ws.readyState === WebSocket.CONNECTING\n )\n ) {\n return;\n }\n\n // An explicit connect() re-arms auto-reconnect. Without this, a manual\n // disconnect() would disable reconnection for the rest of the page's life,\n // including for connections opened afterwards.\n this.should_reconnect = true;\n\n this.ws = new WebSocket(this.get_url());\n\n if (debug) console.log('new websocket');\n\n this.session_id = session_id;\n\n // Reset heartbeat timer on new connection\n this.last_heartbeat_timestamp = Date.now();\n\n this.ws.addEventListener('open', (event) => this.handle_open(event));\n this.ws.addEventListener('message', (event) => this.handle_message(event));\n this.ws.addEventListener('close', (event) => this.handle_close(event));\n this.ws.addEventListener('error', (event) => this.handle_error(event));\n }\n\n /**\n * Send message if the websocket is open,\n * otherwise add it to the message queue\n */\n public message({ type, table, id }: SocketMessage) {\n const payload = { type, table, id };\n\n if (\n this.ws &&\n this.ws.readyState === WebSocket.OPEN\n ) {\n this.ws.send(JSON.stringify(payload));\n } else {\n this.message_queue.push(payload);\n }\n }\n\n public disconnect() {\n if (debug) console.log('websocket disconnect()');\n this.update_connection_state('disconnected');\n // if we are manually disconnecting we do not want an auto reconnect\n this.should_reconnect = false;\n this.ws?.close();\n this.ws = undefined;\n if (this.reconnect_timeout) {\n clearTimeout(this.reconnect_timeout);\n }\n }\n\n /**\n * Update the connection state, dispatch an event if it actually changed.\n */\n private update_connection_state(new_connection_state: ConnectionState) {\n const old_connection_state = this.connection_state;\n if (this.connection_state !== new_connection_state) {\n if (debug) console.log('update_connection_state', new_connection_state);\n this.connection_state = new_connection_state;\n\n if (debug) console.warn(`[Socket] State changed to: ${this.connection_state}`);\n this.dispatchEvent(new CustomEvent('connection_state', { detail: this.connection_state }));\n\n if (\n (new_connection_state === 'connected' || new_connection_state === 'reconnected') &&\n (old_connection_state === 'stale' || old_connection_state === 'disconnected')\n ) {\n this.dispatchEvent(new CustomEvent('refresh', { bubbles: true }));\n }\n }\n }\n\n\n /**\n * Helper to determine if we need to fetch missing data\n */\n private check_staleness(source: string) {\n const now = Date.now();\n const time_since_last = now - this.last_heartbeat_timestamp;\n\n if (debug) console.log('websocket check_staleness()', source, time_since_last);\n\n if (\n !this.ws ||\n this.ws.readyState === this.ws.CLOSED ||\n time_since_last > this.DISCONNECT_THRESHOLD_MS\n ) {\n this.update_connection_state('disconnected');\n return;\n }\n\n // If gap is larger than threshold, we missed messages\n if (time_since_last > this.SUSPENSION_THRESHOLD_MS) {\n this.update_connection_state('stale');\n } else {\n this.update_connection_state('connected');\n }\n }\n\n private handle_open(event: Event) {\n if (debug) console.log('websocket handle open()');\n\n if (\n this.ws &&\n this.ws.readyState === this.ws.OPEN\n ) {\n this.update_connection_state('connected');\n }\n // clear reconnect timeout if we connected\n if (this.reconnect_timeout) {\n clearTimeout(this.reconnect_timeout);\n }\n\n // If we are reconnecting (attempts > 0), we definitely missed data.\n if (this.reconnect_attempts > 0) {\n if (debug) console.log('[Socket] Reconnected. Triggering refresh.');\n this.dispatchEvent(new CustomEvent('refresh', { bubbles: true }));\n }\n\n // reset the reconnect attempts\n this.reconnect_attempts = 0;\n\n this.ws?.send(JSON.stringify({ type: 'session', table: 'session', id: this.session_id }));\n\n while (this.message_queue.length > 0) {\n const queuedMsg = this.message_queue.shift();\n this.ws?.send(JSON.stringify(queuedMsg));\n }\n }\n\n private handle_message(event: MessageEvent) {\n if (debug) console.log('websocket handle message()');\n\n try {\n const data = JSON.parse(event.data);\n\n if (debug) console.log('data', data);\n\n // HEARTBEAT CHECK: Intercept heartbeat messages\n if (data.type === 'heartbeat') {\n this.check_staleness('heartbeat');\n this.last_heartbeat_timestamp = Date.now();\n return; // Do not bubble 'heartbeat' to the UI\n }\n\n // todo not sure I like this\n const messageEvent = new CustomEvent('message', {\n detail: JSON.parse(event.data) as SocketResponseMessage,\n bubbles: true,\n });\n\n this.dispatchEvent(messageEvent);\n } catch (e) {\n const messageEvent = new CustomEvent('message', {\n detail: event.data as SocketResponseMessage,\n bubbles: true,\n });\n this.dispatchEvent(messageEvent);\n }\n }\n\n private handle_close(event: CloseEvent) {\n if (debug) console.log('websocket handle close()');\n this.update_connection_state('disconnected');\n if (this.should_reconnect) {\n const delay = Tasker.backoff(this.reconnect_attempts, { delay: 1000, maxDelay: 30000 });\n if (debug) console.log(`Connection lost. Retrying in ${delay}ms... (Attempt ${this.reconnect_attempts + 1})`);\n\n this.reconnect_timeout = setTimeout(() => {\n this.reconnect_attempts++;\n if (this.session_id) {\n this.connect(this.session_id);\n }\n }, delay);\n }\n\n this.ws = undefined;\n }\n\n private handle_error(event: Event) {\n if (debug) console.log('websocket handle error()');\n this.update_connection_state('disconnected');\n console.error('WebSocket Error:', event);\n this.ws?.close();\n }\n}\n\nexport const socket: Socket = new Socket();\n", "/*\n * Copyright 2026 Evan Smalley.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n */\n\n/* eslint-disable no-restricted-syntax */\n\ntype Merge<T, U> = Omit<T, keyof U> & U;\n\ntype MergeAll<T extends object[]> =\n T extends [infer First extends object, ...infer Rest extends object[]]\n ? Rest extends []\n ? First // Base case: If there are no more items, just return the object\n : Merge<First, MergeAll<Rest>> // Otherwise, keep merging\n : unknown;\n\n/**\n * Class to manipulate objects\n */\nexport class Objector {\n // constructor() {\n // }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n public static deepClone<T>(obj: T, memo: WeakMap<any, any> = new WeakMap<any, any>()): T {\n // Check if the input is null or not an object/array\n if (obj === null || typeof obj !== 'object') {\n return obj;\n }\n\n // Check if the object is already in the memo\n if (memo.has(obj)) {\n return memo.get(obj);\n }\n\n // Handle built-in types.\n // Every branch registers its clone in the memo *before* recursing into\n // children, so self-referential structures terminate instead of\n // overflowing the stack, and repeated references stay shared.\n if (obj instanceof Date) {\n const clonedDate = new Date(obj.getTime());\n memo.set(obj, clonedDate);\n return clonedDate as unknown as T;\n }\n if (obj instanceof RegExp) {\n const clonedRegExp = new RegExp(obj.source, obj.flags);\n memo.set(obj, clonedRegExp);\n return clonedRegExp as unknown as T;\n }\n if (obj instanceof Map) {\n const clonedMap = new Map();\n memo.set(obj, clonedMap);\n obj.forEach((value, key) => clonedMap.set(key, Objector.deepClone(value, memo)));\n return clonedMap as unknown as T;\n }\n if (obj instanceof Set) {\n const newSet = new Set();\n memo.set(obj, newSet);\n for (const item of obj) {\n newSet.add(Objector.deepClone(item, memo));\n }\n return newSet as unknown as T;\n }\n\n // Handle arrays\n if (Array.isArray(obj)) {\n const clonedArray: unknown[] = new Array(obj.length);\n memo.set(obj, clonedArray);\n obj.forEach((item, index) => {\n clonedArray[index] = Objector.deepClone(item, memo);\n });\n return clonedArray as unknown as T;\n }\n\n // Handle objects\n const clonedObj = Object.create(Object.getPrototypeOf(obj)) as Record<string | symbol, unknown>;\n memo.set(obj, clonedObj);\n\n // Cast the source 'obj' to a record so we can read its keys dynamically\n const sourceObj = obj as Record<string | symbol, unknown>;\n\n // per Gemini\n /**\n * While it appears to be two steps, the first step (Object.keys()) is a native C++ function in the JavaScript engine.\n * It's highly optimized for this specific task and is often faster than the JIT compiler can make the for...in loop with its conditional checks.\n */\n Object.keys(sourceObj).forEach((key) => {\n clonedObj[key] = Objector.deepClone(sourceObj[key], memo);\n });\n /*\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n clonedObj[key] = Objector.deepClone(obj[key], memo);\n }\n }\n */\n\n // Symbol keys\n Object.getOwnPropertySymbols(sourceObj).forEach((sym) => {\n if (Object.prototype.propertyIsEnumerable.call(sourceObj, sym)) {\n clonedObj[sym] = Objector.deepClone(sourceObj[sym], memo);\n }\n });\n\n return clonedObj as unknown as T;\n }\n\n /**\n * Structurally compares two values.\n *\n * Handles the same shapes `deepClone` does \u2014 Date, RegExp, Map, Set, arrays,\n * plain objects and symbol keys \u2014 and tolerates circular references by\n * remembering which pairs are already being compared.\n *\n * NaN equals NaN, and +0 does not equal -0, matching `Object.is` rather than\n * `===`. Objects must share a prototype to be considered equal.\n *\n * @example\n * Objector.deepEqual({ a: [1, { b: 2 }] }, { a: [1, { b: 2 }] }); // true\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n public static deepEqual(a: unknown, b: unknown, seen: WeakMap<any, Set<any>> = new WeakMap()): boolean {\n if (Object.is(a, b)) {\n return true;\n }\n\n if (\n a === null || b === null ||\n typeof a !== 'object' || typeof b !== 'object'\n ) {\n return false;\n }\n\n if (Object.getPrototypeOf(a) !== Object.getPrototypeOf(b)) {\n return false;\n }\n\n // Already comparing this exact pair further up the stack: treat as equal\n // and let the rest of the traversal decide.\n const pairs = seen.get(a);\n if (pairs?.has(b)) {\n return true;\n }\n if (pairs) {\n pairs.add(b);\n } else {\n seen.set(a, new Set([b]));\n }\n\n if (a instanceof Date) {\n return a.getTime() === (b as Date).getTime();\n }\n\n if (a instanceof RegExp) {\n return a.source === (b as RegExp).source && a.flags === (b as RegExp).flags;\n }\n\n if (a instanceof Map) {\n const other = b as Map<unknown, unknown>;\n\n if (a.size !== other.size) {\n return false;\n }\n\n return [...a.entries()].every(\n ([key, value]) => other.has(key) && Objector.deepEqual(value, other.get(key), seen),\n );\n }\n\n if (a instanceof Set) {\n const other = b as Set<unknown>;\n\n if (a.size !== other.size) {\n return false;\n }\n\n const remaining = [...other];\n\n // Members have no keys to match on, so each one is paired against the\n // first structurally equal member not already claimed.\n return [...a].every((value) => {\n const match = remaining.findIndex((candidate) => Objector.deepEqual(value, candidate, seen));\n\n if (match === -1) {\n return false;\n }\n\n remaining.splice(match, 1);\n return true;\n });\n }\n\n if (Array.isArray(a)) {\n const other = b as unknown[];\n\n if (a.length !== other.length) {\n return false;\n }\n\n return a.every((value, index) => Objector.deepEqual(value, other[index], seen));\n }\n\n const aRecord = a as Record<string | symbol, unknown>;\n const bRecord = b as Record<string | symbol, unknown>;\n\n const aKeys = Object.keys(aRecord);\n const bKeys = Object.keys(bRecord);\n\n if (aKeys.length !== bKeys.length) {\n return false;\n }\n\n const keysMatch = aKeys.every(\n (key) => Object.prototype.hasOwnProperty.call(bRecord, key) &&\n Objector.deepEqual(aRecord[key], bRecord[key], seen),\n );\n\n if (!keysMatch) {\n return false;\n }\n\n const aSymbols = Object.getOwnPropertySymbols(aRecord)\n .filter((sym) => Object.prototype.propertyIsEnumerable.call(aRecord, sym));\n const bSymbols = Object.getOwnPropertySymbols(bRecord)\n .filter((sym) => Object.prototype.propertyIsEnumerable.call(bRecord, sym));\n\n if (aSymbols.length !== bSymbols.length) {\n return false;\n }\n\n return aSymbols.every(\n (sym) => Object.prototype.propertyIsEnumerable.call(bRecord, sym) &&\n Objector.deepEqual(aRecord[sym], bRecord[sym], seen),\n );\n }\n\n /**\n * Deeply merges one or more source objects into a target object.\n *\n * - Each property from the sources is deep-cloned before being assigned.\n * - Existing properties in the target are overwritten by matching keys in later sources.\n * - Does not use spread or Object.assign.\n * - Mutates and returns the target object.\n *\n * @template T - The type of the target object.\n * @param {T} target - The object to extend.\n * @param {...U[]} sources - One or more source objects whose properties will be copied to the target.\n * @returns {T & U} The mutated target object containing all deep-cloned properties from the sources.\n *\n * @throws {TypeError} If the target is null or undefined.\n *\n * @example\n * const target = { a: 1 };\n * const source = { b: { nested: 2 } };\n * Objector.extender(target, source);\n * // target is now { a: 1, b: { nested: 2 } }\n */\n public static extender<T extends object, U extends object[]>(\n target: T,\n ...sources: U\n ): MergeAll<[T, ...U]> {\n if (target == null) {\n throw new TypeError('Cannot convert undefined or null to object');\n }\n\n const to = Object(target) as Record<string | symbol, unknown>;\n\n // eslint-disable-next-line no-restricted-syntax\n for (const source of sources) {\n if (source != null) {\n // Cast the source to an indexable record\n const s = source as Record<string | symbol, unknown>;\n // String keys\n // eslint-disable-next-line no-restricted-syntax\n for (const key of Object.keys(s)) {\n to[key] = Objector.deepClone(s[key]);\n }\n\n // Symbol keys\n const symbols = Object.getOwnPropertySymbols(s);\n // eslint-disable-next-line no-restricted-syntax\n for (const sym of symbols) {\n if (Object.prototype.propertyIsEnumerable.call(s, sym)) {\n to[sym] = Objector.deepClone(s[sym]);\n }\n }\n }\n }\n\n return to as MergeAll<[T, ...U]>;\n }\n}\n\n", "/*\n * Copyright 2026 Evan Smalley.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n */\n\nimport { Kontororu } from '../Kontororu.js';\nimport { Objector } from '../Objector.js';\n\n\nexport type StoreData = Record<string, Record<string, unknown>>;\n\n/**\n * A query resolved once, ahead of the row scan.\n *\n * `values` and `lists` mirror `columns` by index. Resolving them per row costs\n * a lookup into `args` and an Array.isArray() call for every column of every\n * row, none of which can change between rows.\n */\ninterface Filter {\n columns: string[];\n values: unknown[];\n lists: boolean[];\n}\n\nfunction toFilter(args: Record<string, unknown>, skip?: string): Filter {\n const columns: string[] = [];\n const values: unknown[] = [];\n const lists: boolean[] = [];\n\n for (const column of Object.keys(args)) {\n if (column === skip) {\n continue;\n }\n\n const value = args[column];\n\n columns.push(column);\n values.push(value);\n lists.push(Array.isArray(value));\n }\n\n return { columns, values, lists };\n}\n\n/**\n * Whether a row satisfies every column of the filter, by strict equality or by\n * membership when the argument is an array.\n */\nfunction matchesRow(row: unknown, { columns, values, lists }: Filter): boolean {\n if (!row || typeof row !== 'object' || Array.isArray(row)) {\n return false;\n }\n\n const record = row as Record<string, unknown>;\n\n for (let i = 0; i < columns.length; i++) {\n const rowValue = record[columns[i]];\n\n if (rowValue === values[i]) {\n continue;\n }\n\n if (lists[i] && (values[i] as unknown[]).includes(rowValue)) {\n continue;\n }\n\n return false;\n }\n\n return true;\n}\n\nexport class Store<TStore extends StoreData = StoreData> extends Kontororu {\n private store: TStore = {} as TStore;\n\n /**\n * Load an object into the store\n */\n load(data: TStore) {\n this.store = data;\n }\n\n /**\n * Get the first result\n */\n get<K extends keyof TStore>(table: K, args: Record<string, unknown> = {}): TStore[K][string] | null {\n const results = this.read(table, args);\n const firstId = Object.keys(results)[0];\n return firstId ? (results[firstId] as TStore[K][string]) : null;\n }\n\n /**\n * Read the results\n */\n read<K extends keyof TStore>(table: K, args: Record<string, unknown> = {}): Record<string, TStore[K][string]> {\n const data = this.store[table];\n if (!data) {\n return {};\n }\n\n const primaryKey = `${String(table)}_id`;\n\n // Fast path: Direct primary key lookup.\n // Any remaining arguments still have to be applied to the row we found,\n // otherwise `read('user', { user_id: '1', active: true })` would return\n // user 1 even when that user is inactive.\n if (primaryKey in args) {\n const id = args[primaryKey] as string;\n const row = data[id];\n\n return row && matchesRow(row, toFilter(args, primaryKey))\n ? { [id]: Objector.deepClone(row) as TStore[K][string] }\n : {};\n }\n\n // If no arguments are provided, return a deep clone of the entire table\n if (Object.keys(args).length === 0) {\n return Objector.deepClone(data) as Record<string, TStore[K][string]>;\n }\n\n const filter = toFilter(args);\n const matches: Record<string, TStore[K][string]> = {};\n\n // Cloning only full matches matters more than the scan itself: a row is\n // wide, so cloning one that a later column rejects costs far more than\n // testing all of its columns first.\n for (const id in data) {\n const row = data[id];\n\n if (matchesRow(row, filter)) {\n matches[id] = Objector.deepClone(row) as TStore[K][string];\n }\n }\n\n return matches;\n }\n}\n", "/*\n * Copyright 2026 Evan Smalley.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n */\n\n/**\n * Table sorting helper utility\n */\nexport class Sorter {\n public static descendingComparator(a: Record<string, string | number>, b: Record<string, string | number>, orderBy: string, direction_?: string): number {\n const a_value = a[orderBy];\n const b_value = b[orderBy];\n\n // Null/undefined values always sort to the end, regardless of direction.\n // Both branches must be checked against the *values* (not key presence),\n // otherwise two null rows compare as non-equal and the comparator stops\n // being antisymmetric, which yields an inconsistent sort order.\n const a_empty = a_value === null || a_value === undefined;\n const b_empty = b_value === null || b_value === undefined;\n\n if (a_empty && b_empty) {\n return 0;\n }\n if (b_empty) {\n return 1;\n }\n if (a_empty) {\n return -1;\n }\n\n const direction = direction_ || 'lower';\n\n if (b_value < a_value) {\n return direction === 'higher' ? 1 : -1;\n }\n if (b_value > a_value) {\n return direction === 'higher' ? -1 : 1;\n }\n return 0;\n }\n\n public static getComparator(order: string, orderBy: string, direction?: string): (a: Record<string, string | number>, b: Record<string, string | number>) => number {\n return order === 'desc'\n ? (a, b) => this.descendingComparator(a, b, orderBy, direction)\n : (a, b) => -this.descendingComparator(a, b, orderBy, direction);\n }\n}\n", "/*\n * Copyright 2026 Evan Smalley.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n */\n\nexport class Textor {\n /**\n * Convert camelCase or PascalCase to kebab-case.\n *\n * Used to turn CSS-in-JS property names into real CSS properties, but it is\n * general purpose.\n *\n * @example\n * Textor.toKebabCase('backgroundColor'); // 'background-color'\n */\n public static toKebabCase(str: string): string {\n return str.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase();\n }\n\n public static levenshtein(a: string, b: string): number {\n const matrix: number[][] = [];\n\n // An empty string is `length` edits away from the other string,\n // not 0 edits away.\n if (!a) {\n return b ? b.length : 0;\n }\n if (!b) {\n return a.length;\n }\n\n // Initialize the matrix with base case values\n for (let i = 0; i <= a.length; i++) {\n matrix[i] = [i];\n }\n for (let j = 0; j <= b.length; j++) {\n matrix[0][j] = j;\n }\n\n // Populate the matrix with distances\n for (let i = 1; i <= a.length; i++) {\n for (let j = 1; j <= b.length; j++) {\n const cost = a[i - 1] === b[j - 1] ? 0 : 1;\n\n matrix[i][j] = Math.min(\n matrix[i - 1][j] + 1, // Deletion\n matrix[i][j - 1] + 1, // Insertion\n matrix[i - 1][j - 1] + cost, // Substitution\n );\n }\n }\n\n // The final value is the Levenshtein distance\n return matrix[a.length][b.length];\n }\n\n public static toSentenceCase(str: string): string {\n if (!str) {\n return '';\n }\n\n // Trim the string to remove extra whitespace\n const trimmed = str.trim();\n\n // Convert the first letter to uppercase and the rest to lowercase\n return trimmed.charAt(0).toUpperCase() + trimmed.slice(1).toLowerCase();\n }\n\n /**\n * Generates pseudo-Latin Lorem Ipsum placeholder text.\n */\n public static generateLoremIpsum(\n paragraphs = 3,\n sentencesPerParagraph = 5,\n startWithLorem = true,\n ): string {\n const words = [\n 'lorem', 'ipsum', 'dolor', 'sit', 'amet', 'consectetur', 'adipiscing', 'elit',\n 'sed', 'do', 'eiusmod', 'tempor', 'incididunt', 'ut', 'labore', 'et', 'dolore',\n 'magna', 'aliqua', 'ut', 'enim', 'ad', 'minim', 'veniam', 'quis', 'nostrud',\n 'exercitation', 'ullamco', 'laboris', 'nisi', 'ut', 'aliquip', 'ex', 'ea',\n 'commodo', 'consequat', 'duis', 'aute', 'irure', 'dolor', 'in', 'reprehenderit',\n 'in', 'voluptate', 'velit', 'esse', 'cillum', 'dolore', 'eu', 'fugiat', 'nulla',\n 'pariatur', 'excepteur', 'sint', 'occaecat', 'cupidatat', 'non', 'proident',\n 'sunt', 'in', 'culpa', 'qui', 'officia', 'deserunt', 'mollit', 'anim', 'id',\n 'est', 'laborum',\n ];\n\n // Helper to get a random word from the pool\n const getRandomWord = () => words[Math.floor(Math.random() * words.length)];\n\n // Helper to generate a single sentence\n const generateSentence = (isFirstSentence = false) => {\n if (isFirstSentence && startWithLorem) {\n return 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.';\n }\n\n // Sentences typically range from 5 to 15 words\n const sentenceLength = Math.floor(Math.random() * 11) + 5;\n const sentenceWords = [];\n\n for (let i = 0; i < sentenceLength; i++) {\n sentenceWords.push(getRandomWord());\n }\n\n // Capitalize the first letter of the sentence\n let sentence = sentenceWords.join(' ');\n sentence = sentence.charAt(0).toUpperCase() + sentence.slice(1);\n\n // Occasionally add commas for realistic phrasing (approx. 20% chance if long enough)\n if (sentenceLength > 8 && Math.random() > 0.8) {\n const commaIndex = Math.floor(sentenceLength / 2);\n const splitSentence = sentence.split(' ');\n splitSentence[commaIndex] += ',';\n sentence = splitSentence.join(' ');\n }\n\n return `${sentence}.`;\n };\n\n const paragraphList = [];\n\n for (let p = 0; p < paragraphs; p++) {\n const sentenceCount = Math.max(3, Math.round(sentencesPerParagraph + (Math.random() * 4 - 2))); // slight variance\n const sentences = [];\n\n for (let s = 0; s < sentenceCount; s++) {\n // Only the absolute first sentence of the entire text gets the classic intro\n const isAbsoluteFirst = p === 0 && s === 0;\n sentences.push(generateSentence(isAbsoluteFirst));\n }\n\n paragraphList.push(sentences.join(' '));\n }\n\n // Join paragraphs with double line breaks\n return paragraphList.join('\\n\\n');\n }\n}\n", "/*\n * Copyright 2026 Evan Smalley.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n */\n\n/* eslint-disable no-restricted-syntax */\n/* eslint-disable no-bitwise */\n\nimport { Textor } from './Textor.js';\n\n\n\n\ntype CSSMap = Map<string, string>;\n\ninterface ZIndexConfig {\n appBar: number;\n drawer: number;\n fab: number;\n calendar: number;\n mobileStepper: number;\n modal: number;\n toast: number;\n speedDial: number;\n tooltip: number;\n}\n\ninterface StyleConfig {\n zIndex: ZIndexConfig;\n}\n\ninterface NavBarStyle {\n width: string;\n display: string;\n justifyContent: string;\n zIndex: number;\n position: string;\n overflowX: string;\n overflowY: string;\n scrollbarWidth: string;\n}\n\n/**\n * CSS in JS processor and other random style functions\n */\nexport class Style {\n public static getStyle(): StyleConfig {\n return {\n zIndex: Style.getZIndex(),\n };\n }\n\n public static getZIndex(): ZIndexConfig {\n return {\n appBar: 1100,\n drawer: 1200,\n fab: 1050,\n calendar: 1000,\n mobileStepper: 1000,\n modal: 1300,\n toast: 1400,\n speedDial: 1050,\n tooltip: 1500,\n };\n }\n\n public static getNavBar(): NavBarStyle {\n return {\n width: '100%',\n display: 'flex',\n justifyContent: 'center',\n zIndex: Style.getZIndex().appBar,\n position: 'fixed',\n overflowX: 'scroll',\n overflowY: 'hidden',\n scrollbarWidth: 'none',\n };\n }\n\n public static getShadow(depth: number): string {\n const shadows = [\n 'none',\n '0px 2px 1px -1px rgba(0,0,0,0.2),0px 1px 1px 0px rgba(0,0,0,0.14),0px 1px 3px 0px rgba(0,0,0,0.12)',\n '0px 3px 1px -2px rgba(0,0,0,0.2),0px 2px 2px 0px rgba(0,0,0,0.14),0px 1px 5px 0px rgba(0,0,0,0.12)',\n '0px 3px 3px -2px rgba(0,0,0,0.2),0px 3px 4px 0px rgba(0,0,0,0.14),0px 1px 8px 0px rgba(0,0,0,0.12)',\n '0px 2px 4px -1px rgba(0,0,0,0.2),0px 4px 5px 0px rgba(0,0,0,0.14),0px 1px 10px 0px rgba(0,0,0,0.12)',\n '0px 3px 5px -1px rgba(0,0,0,0.2),0px 5px 8px 0px rgba(0,0,0,0.14),0px 1px 14px 0px rgba(0,0,0,0.12)',\n '0px 3px 5px -1px rgba(0,0,0,0.2),0px 6px 10px 0px rgba(0,0,0,0.14),0px 1px 18px 0px rgba(0,0,0,0.12)',\n '0px 4px 5px -2px rgba(0,0,0,0.2),0px 7px 10px 1px rgba(0,0,0,0.14),0px 2px 16px 1px rgba(0,0,0,0.12)',\n '0px 5px 5px -3px rgba(0,0,0,0.2),0px 8px 10px 1px rgba(0,0,0,0.14),0px 3px 14px 2px rgba(0,0,0,0.12)',\n '0px 5px 6px -3px rgba(0,0,0,0.2),0px 9px 12px 1px rgba(0,0,0,0.14),0px 3px 16px 2px rgba(0,0,0,0.12)',\n '0px 6px 6px -3px rgba(0,0,0,0.2),0px 10px 14px 1px rgba(0,0,0,0.14),0px 4px 18px 3px rgba(0,0,0,0.12)',\n '0px 6px 7px -4px rgba(0,0,0,0.2),0px 11px 15px 1px rgba(0,0,0,0.14),0px 4px 20px 3px rgba(0,0,0,0.12)',\n '0px 7px 8px -4px rgba(0,0,0,0.2),0px 12px 17px 2px rgba(0,0,0,0.14),0px 5px 22px 4px rgba(0,0,0,0.12)',\n '0px 7px 8px -4px rgba(0,0,0,0.2),0px 13px 19px 2px rgba(0,0,0,0.14),0px 5px 24px 4px rgba(0,0,0,0.12)',\n '0px 7px 9px -4px rgba(0,0,0,0.2),0px 14px 21px 2px rgba(0,0,0,0.14),0px 5px 26px 4px rgba(0,0,0,0.12)',\n '0px 8px 9px -5px rgba(0,0,0,0.2),0px 15px 22px 2px rgba(0,0,0,0.14),0px 6px 28px 5px rgba(0,0,0,0.12)',\n '0px 8px 10px -5px rgba(0,0,0,0.2),0px 16px 24px 2px rgba(0,0,0,0.14),0px 6px 30px 5px rgba(0,0,0,0.12)',\n '0px 8px 11px -5px rgba(0,0,0,0.2),0px 17px 26px 2px rgba(0,0,0,0.14),0px 6px 32px 5px rgba(0,0,0,0.12)',\n '0px 9px 11px -5px rgba(0,0,0,0.2),0px 18px 28px 2px rgba(0,0,0,0.14),0px 7px 34px 6px rgba(0,0,0,0.12)',\n '0px 9px 12px -6px rgba(0,0,0,0.2),0px 19px 29px 2px rgba(0,0,0,0.14),0px 7px 36px 6px rgba(0,0,0,0.12)',\n '0px 10px 13px -6px rgba(0,0,0,0.2),0px 20px 31px 3px rgba(0,0,0,0.14),0px 8px 38px 7px rgba(0,0,0,0.12)',\n '0px 10px 13px -6px rgba(0,0,0,0.2),0px 21px 33px 3px rgba(0,0,0,0.14),0px 8px 40px 7px rgba(0,0,0,0.12)',\n '0px 10px 14px -6px rgba(0,0,0,0.2),0px 22px 35px 3px rgba(0,0,0,0.14),0px 8px 42px 7px rgba(0,0,0,0.12)',\n '0px 11px 14px -7px rgba(0,0,0,0.2),0px 23px 36px 3px rgba(0,0,0,0.14),0px 9px 44px 8px rgba(0,0,0,0.12)',\n '0px 11px 15px -7px rgba(0,0,0,0.2),0px 24px 38px 3px rgba(0,0,0,0.14),0px 9px 46px 8px rgba(0,0,0,0.12)',\n ];\n\n if (depth >= shadows.length || depth < 0 || !Number.isInteger(depth)) {\n throw new Error(`min depth is 0, max depth is ${shadows.length - 1}. Sent ${depth}`);\n }\n\n return shadows[depth];\n }\n\n /**\n *\n *\n *\n *\n * Below is all the CSS injection from js\n *\n *\n *\n */\n\n /**\n * Call this to add css as a style-sheet, so you can do css selectors like hover td {} etc\n */\n public static getStyleClassName(cssString: string | object, debug = false): string {\n if (debug) {\n console.log('getStyleClassName', cssString);\n }\n // console.time('getStyleClassName')\n const className = `css-${this.hashCSS(cssString, debug)}`;\n\n this.injectStyle(className, cssString, debug);\n // console.timeEnd('getStyleClassName')\n return className;\n }\n\n public static getMap(): CSSMap {\n return this.cssMap;\n }\n\n // SSR helper to get all collected styles\n public static getCSS(): string {\n console.warn('this does not work yet, in root layout need to add a context thing so it attaches css to style when streamed from server');\n return Array.from(this.cssMap.values()).join('\\n');\n }\n\n // Call after SSR render to clean up for next render\n public static flush(): void {\n this.styleCache.clear();\n this.cssMap.clear();\n }\n\n private static styleCache: Set<string> = new Set();\n\n private static cssMap: CSSMap = new Map(); // key: className, value: finalCSS\n\n private static hashCSS(css: string | object, debug = false): string {\n const canonicalize = (obj: object | string | number): object | string | number => {\n if (typeof obj !== 'object' || obj === null) {\n // Return primitives as is\n return obj;\n }\n\n if (Array.isArray(obj)) {\n // Recursively canonicalize array elements\n return obj.map(canonicalize);\n }\n\n // 1. Get and sort the keys of the current object level\n const sortedKeys = Object.keys(obj).sort();\n const canonical: { [key: string]: unknown } = {};\n\n // cast object to record\n const sourceObj = obj as Record<string, string | number>;\n\n // 2. Build a new object using the sorted keys, and recursively process values\n for (const key of sortedKeys) {\n canonical[key] = canonicalize(sourceObj[key]);\n }\n\n return canonical;\n };\n\n const normalize = (val: string | object): string => {\n if (typeof val === 'string') {\n return val;\n }\n if (typeof val === 'object' && val !== null) {\n const canonicalObject = canonicalize(val);\n // Step B: Stringify the canonical object without a replacer\n return JSON.stringify(canonicalObject);\n }\n return String(val);\n };\n\n const normalizedInput = normalize(css);\n\n if (debug) {\n console.log('normalizedInput', normalizedInput);\n }\n\n // Example hash using a simple DJB2 hash (or use a stronger hash like SHA-1/MD5 if needed)\n let hash = 5381;\n for (let i = 0; i < normalizedInput.length; i++) {\n hash = (hash * 33) ^ normalizedInput.charCodeAt(i);\n }\n return (hash >>> 0).toString(36); // base36 for short string\n }\n\n private static injectStyle(className: string, css: string | object, debug = false): void {\n if (\n this.styleCache.has(className)\n ) {\n return;\n }\n\n const finalCSS = this.processCSS(className, css, false, debug);\n\n // If on server, store it only\n if (typeof window === 'undefined') {\n this.cssMap.set(className, finalCSS);\n } else {\n const styleEl = document.createElement('style');\n styleEl.textContent = finalCSS;\n document.head.appendChild(styleEl);\n }\n\n this.styleCache.add(className);\n this.cssMap.set(className, finalCSS);\n }\n\n private static processCSS(className: string, css: string | object, isRecursive = false, debug = false): string {\n // Helper: remove trailing colon from selectors (e.g. 'td:' -> 'td')\n const cleanSelector = (sel:string): string => {\n return sel.replace(/:$/g, '');\n };\n\n // Helper: Remove the specific '}' that closed the block from the accumulated lines\n // so we don't duplicate it when wrapping the result in new braces.\n const removeLastBrace = (lines: string[]) => {\n if (lines.length === 0) return;\n const lastIdx = lines.length - 1;\n const lastLine = lines[lastIdx];\n\n const braceIdx = lastLine.lastIndexOf('}');\n if (braceIdx !== -1) {\n // Remove the brace\n const newLine = lastLine.substring(0, braceIdx) + lastLine.substring(braceIdx + 1);\n\n // If the line is now empty (or just whitespace), remove it entirely\n if (!newLine.trim()) {\n lines.pop();\n } else {\n // eslint-disable-next-line no-param-reassign\n lines[lastIdx] = newLine;\n }\n }\n };\n\n const requiresQuotes = new Set([\n 'content',\n 'quotes',\n 'cue',\n 'cue-before',\n 'cue-after',\n 'src',\n ]);\n\n // List of properties that should have units if the value is a number\n const lengthProps = new Set([\n 'width', 'height', 'top', 'left', 'right', 'bottom',\n 'margin', 'margin-top', 'margin-right', 'margin-bottom', 'margin-left',\n 'padding', 'padding-top', 'padding-right', 'padding-bottom', 'padding-left',\n 'font-size', 'border-width', 'border-radius', 'gap', 'column-gap', 'row-gap',\n 'min-width', 'min-height', 'max-width', 'max-height',\n ]);\n\n const non_recursive_at_rules = [\n '@keyframes',\n '@-webkit-keyframes',\n '@font-face',\n '@counter-style',\n ];\n\n const isNonRecursiveRule = (ruleName: string) => {\n return non_recursive_at_rules.some((prefix) => ruleName.startsWith(prefix));\n };\n\n const normalizeValue = (property: string, value: string | number): string | number => {\n if (!lengthProps.has(property)) {\n return value;\n }\n\n // If it's a number, add px\n if (typeof value === 'number') {\n return `${value}px`;\n }\n\n // If it's a numeric string with no unit, add px\n if (typeof value === 'string') {\n const trimmed = value.trim();\n\n // Match numeric string (integer or decimal), no unit\n if (/^-?\\d+(\\.\\d+)?$/.test(trimmed)) {\n return `${trimmed}px`;\n }\n\n // If it ends in known units or keywords, leave it alone\n return trimmed;\n }\n\n return value;\n };\n\n // Convert a line like \"backgroundColor: red;\" to \"background-color: red;\"\n const normalizeCSSLine = (line: string): string => {\n const colonIndex = line.indexOf(':');\n if (colonIndex === -1) {\n return line; // Not a CSS property line\n }\n\n const rawProperty = line.slice(0, colonIndex).trim();\n let value: string | number = line.slice(colonIndex + 1).trim();\n\n const property = Textor.toKebabCase(rawProperty);\n\n // Remove trailing comma\n if (value.endsWith(',')) {\n value = value.slice(0, -1).trim();\n }\n\n // Only strip quotes if it's NOT a property like 'content'\n if (!requiresQuotes.has(property)) {\n value = value\n .split(',')\n .map((part) => {\n const trimmed = part.trim();\n // Check if the part is wrapped in quotes\n const match = trimmed.match(/^[\"'](.*)[\"']$/);\n\n if (match) {\n const innerValue = match[1];\n // If there's a space, keep the quotes (e.g., \"Segoe UI\")\n // If no space, strip them (e.g., \"Arial\" -> Arial)\n return innerValue.includes(' ') ? trimmed : innerValue;\n }\n return trimmed;\n })\n .join(', ');\n }\n\n value = normalizeValue(property, value);\n\n let cssLine = `${property}: ${value}`;\n if (!cssLine.endsWith(';')) {\n cssLine += ';';\n }\n\n return cssLine;\n };\n\n // Convert CSS object into flat lines\n const objectToLines = (obj: object): string[] => {\n const lines: string[] = [];\n\n const sourceObj = obj as Record<string, unknown>;\n\n for (const key in sourceObj) {\n const value = sourceObj[key];\n\n if (typeof value === 'object' && value !== null) {\n lines.push(`${key} {`);\n const nested = objectToLines(value);\n lines.push(...nested);\n lines.push('}');\n } else {\n // Note:\n // - We add a comma here to support object syntax, normalizeCSSLine will handle removing it and adding semicolons later.\n // - Don't stringify strings, to avoid double-escaping quotes (e.g. content: '\"*\"')\n const finalValue = typeof value === 'string' ? value : String(value);\n lines.push(`${key}: ${finalValue},`);\n }\n }\n\n return lines;\n };\n\n // Prepare raw lines\n const lines = typeof css === 'string'\n ? css.trim().split('\\n').map((line) => line.trim()).filter(Boolean)\n : objectToLines(css);\n\n\n const topLevelRules: string[] = [];\n const nestedRules: string[] = [];\n const atRules: string[] = [];\n\n let currentNestedSelector: string | null = null;\n let currentAtRule: string | null = null;\n let atRuleLines: string[] = [];\n let atRuleBraceCount = 0;\n let nestedLines: string[] = [];\n let nestedBraceCount = 0;\n\n for (const line of lines) {\n // 1. AT-RULE HANDLING (@media, @keyframes)\n if (line.startsWith('@') || currentAtRule) {\n if (!currentAtRule) currentAtRule = line.split('{')[0].trim();\n atRuleLines.push(line);\n atRuleBraceCount += (line.match(/{/g) || []).length;\n atRuleBraceCount -= (line.match(/}/g) || []).length;\n\n if (atRuleBraceCount === 0) {\n const rawBlock = atRuleLines.join('\\n');\n const contentOnly = rawBlock.substring(rawBlock.indexOf('{') + 1, rawBlock.lastIndexOf('}')).trim();\n\n if (currentAtRule.startsWith('@keyframes')) {\n // Keyframes: Process units/semicolons but DO NOT wrap in class\n const processed = contentOnly.split('\\n').map((l) => {\n if (l.includes('{') || l.includes('}')) return l;\n return normalizeCSSLine(l);\n }).join(' ');\n atRules.push(`${currentAtRule} { ${processed} }`);\n } else {\n // Media Queries: Recursive call to wrap in class\n const processed = this.processCSS(className, contentOnly, false, debug);\n atRules.push(`${currentAtRule} { ${processed} }`);\n }\n currentAtRule = null;\n atRuleLines = [];\n }\n continue;\n }\n\n // 2. NESTED SELECTOR HANDLING (&:hover, ::before)\n if (line.includes('{') || currentNestedSelector) {\n if (!currentNestedSelector) {\n currentNestedSelector = line.split('{')[0].trim();\n\n // Identify \"Highlight Pseudo-elements\" that need global scoping for Safari/WebKit compatibility\n const isHighlightPseudo = /::(selection|target-text|highlight|spelling-error|grammar-error)/.test(currentNestedSelector);\n\n // Standard behavior: auto-prefix with '&' if it starts with ':'\n // Special behavior: If it's a Highlight Pseudo, we leave it alone so it stays global\n if (\n currentNestedSelector.startsWith(':') &&\n !currentNestedSelector.startsWith('&') &&\n !isHighlightPseudo\n ) {\n currentNestedSelector = `&${currentNestedSelector}`;\n }\n } else if (!line.includes('}')) {\n nestedLines.push(normalizeCSSLine(line));\n }\n\n nestedBraceCount += (line.match(/{/g) || []).length;\n nestedBraceCount -= (line.match(/}/g) || []).length;\n\n if (nestedBraceCount === 0) {\n const isHighlightPseudo = /::(selection|target-text|highlight|spelling-error|grammar-error)/.test(currentNestedSelector);\n\n // If it's a Highlight Pseudo, we DON'T prefix with the .className.\n // This makes it global, which is required for Safari to render it correctly.\n const selector = isHighlightPseudo\n ? currentNestedSelector\n : currentNestedSelector.replace(/&/g, `.${className}`);\n\n nestedRules.push(`${selector} { ${nestedLines.join(' ')} }`);\n currentNestedSelector = null;\n nestedLines = [];\n }\n continue;\n }\n\n // 3. TOP LEVEL PROPERTIES\n topLevelRules.push(normalizeCSSLine(line));\n }\n\n const topLevelCSS = (!isRecursive && topLevelRules.length > 0)\n ? `.${className} { ${topLevelRules.join(' ')} }`\n : topLevelRules.join(' ');\n\n return `${topLevelCSS} ${nestedRules.join(' ')} ${atRules.join(' ')}`.replace(/\\s\\s+/g, ' ').trim();\n }\n}\n\n", "/*\n * Copyright 2026 Evan Smalley.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n */\n\nexport type ThemeType = ReturnType<Theme['getTheme']>;\n\n// all these types are for jsr / deno because it cant use the dynamic one above >.>\n\ninterface ColorScale {\n 50: string;\n 100: string;\n 200: string;\n 300: string;\n 400: string;\n 500: string;\n 600: string;\n 700: string;\n 800: string;\n 900: string;\n A100: string;\n A200: string;\n A400: string;\n A700: string;\n}\n\ninterface BrownScale {\n 50: string;\n 100: string;\n 200: string;\n 300: string;\n 400: string;\n 500: string;\n 600: string;\n 700: string;\n 800: string;\n 900: string;\n}\n\ninterface ColorGroup {\n main: string;\n light: string;\n dark: string;\n}\n\ninterface ColorGroupWithContrast extends ColorGroup {\n contrastText: string;\n}\n\ninterface ActionConfig {\n active: string;\n disabled: string;\n disabledBackground: string;\n disabledOpacity: number;\n focus: string;\n focusOpacity: number;\n hover: string;\n hoverOpacity: number;\n selected: string;\n selectedOpacity: number;\n}\n\ninterface ColorPalette {\n grey: ColorScale;\n red: ColorScale;\n pink: ColorScale;\n purple: ColorScale;\n deepPurple: ColorScale;\n indigo: ColorScale;\n blue: ColorScale;\n lightBlue: ColorScale;\n cyan: ColorScale;\n teal: ColorScale;\n green: ColorScale;\n lightGreen: ColorScale;\n lime: ColorScale;\n yellow: ColorScale;\n amber: ColorScale;\n orange: ColorScale;\n deepOrange: ColorScale;\n brown: BrownScale;\n}\n\ninterface DarkTheme extends ColorPalette {\n mode: 'dark';\n background: { main: string };\n header: { main: string };\n primary: ColorGroup;\n secondary: ColorGroup;\n warning: ColorGroup;\n success: ColorGroup;\n error: ColorGroup;\n info: ColorGroup;\n text: { primary: string; secondary: string; disabled: string; icon: string };\n link: { primary: string };\n action: ActionConfig;\n}\n\ninterface LightTheme extends ColorPalette {\n mode: 'light';\n background: { main: string; light: string };\n header: { main: string };\n primary: ColorGroupWithContrast;\n secondary: ColorGroupWithContrast;\n warning: ColorGroupWithContrast;\n success: ColorGroupWithContrast;\n error: ColorGroupWithContrast;\n info: ColorGroupWithContrast;\n text: { primary: string; secondary: string; disabled: string };\n link: { primary: string };\n action: ActionConfig;\n}\n\n/**\n * Class to get the theme\n */\nexport class Theme {\n public constructor(mode: string) {\n this.mode = mode;\n\n if (mode !== 'light' && mode !== 'dark') {\n throw new Error(`Unknown theme: ${mode}`);\n }\n }\n\n private mode: string;\n\n public getTheme(): DarkTheme | LightTheme {\n if (this.mode === 'light') {\n return this.getLightTheme();\n }\n\n return this.getDarkTheme();\n }\n\n public getDarkTheme(): DarkTheme {\n return {\n mode: 'dark',\n background: {\n main: '#121212',\n },\n header: {\n main: this.getGrey()[900],\n },\n primary: {\n main: '#90caf9',\n light: '#e3f2fd',\n dark: '#42a5f5',\n },\n secondary: {\n main: '#ce93d8',\n light: '#f3e5f5',\n dark: '#ab47bc',\n },\n warning: {\n main: '#ffa726',\n light: '#ffb74d',\n dark: '#f57c00',\n },\n success: {\n main: '#66bb6a',\n light: '#81c784',\n dark: '#388e3c',\n },\n error: {\n main: '#f44336',\n dark: '#d32f2f',\n light: '#e57373',\n },\n info: {\n main: '#29b6f6',\n dark: '#0288d1',\n light: '#4fc3f7',\n },\n text: {\n primary: '#fff',\n secondary: '#B3B3B3',\n disabled: '#808080',\n icon: '#808080',\n },\n link: {\n primary: '#90caf9',\n },\n action: {\n active: '#fff',\n disabled: 'rgba(255, 255, 255, 0.3)',\n disabledBackground: 'rgba(255, 255, 255, 0.12)',\n disabledOpacity: 0.38,\n focus: 'rgba(255, 255, 255, 0.12)',\n focusOpacity: 0.12,\n hover: 'rgba(255, 255, 255, 0.08)',\n hoverOpacity: 0.08,\n selected: 'rgba(255, 255, 255, 0.16)',\n selectedOpacity: 0.16,\n },\n grey: this.getGrey(),\n red: this.getRed(),\n pink: this.getPink(),\n purple: this.getPurple(),\n deepPurple: this.getDeepPurple(),\n indigo: this.getIndigo(),\n blue: this.getBlue(),\n lightBlue: this.getLightBlue(),\n cyan: this.getCyan(),\n teal: this.getTeal(),\n green: this.getGreen(),\n lightGreen: this.getLightGreen(),\n lime: this.getLime(),\n yellow: this.getYellow(),\n amber: this.getAmber(),\n orange: this.getOrange(),\n deepOrange: this.getDeepOrange(),\n brown: this.getBrown(),\n };\n }\n\n public getLightTheme(): LightTheme {\n return {\n mode: 'light',\n background: {\n main: '#efefef',\n light: '#fff',\n },\n header: {\n main: this.getBlue()[700],\n },\n primary: {\n main: '#1976d2',\n light: '#42a5f5',\n dark: '#1565c0',\n contrastText: '#fff',\n },\n secondary: {\n main: '#9c27b0',\n light: '#ba68c8',\n dark: '#7b1fa2',\n contrastText: '#fff',\n },\n error: {\n main: '#d32f2f',\n light: '#ef5350',\n dark: '#c62828',\n contrastText: '#fff',\n },\n warning: {\n main: '#ed6c02',\n light: '#ff9800',\n dark: '#e65100',\n contrastText: '#fff',\n },\n info: {\n main: '#0288d1',\n light: '#03a9f4',\n dark: '#01579b',\n contrastText: '#fff',\n },\n success: {\n main: '#2e7d32',\n light: '#4caf50',\n dark: '#1b5e20',\n contrastText: '#fff',\n },\n text: {\n primary: '#222222',\n secondary: '#666666',\n disabled: '#9E9E9E',\n },\n link: {\n primary: '#1976d2',\n },\n action: {\n active: 'rgba(0, 0, 0, 0.54)',\n disabled: 'rgba(0, 0, 0, 0.26)',\n disabledBackground: 'rgba(0, 0, 0, 0.12)',\n disabledOpacity: 0.38,\n focus: 'rgba(0, 0, 0, 0.12)',\n focusOpacity: 0.12,\n hover: 'rgba(0, 0, 0, 0.04)',\n hoverOpacity: 0.04,\n selected: 'rgba(0, 0, 0, 0.08)',\n selectedOpacity: 0.08,\n },\n grey: this.getGrey(),\n red: this.getRed(),\n pink: this.getPink(),\n purple: this.getPurple(),\n deepPurple: this.getDeepPurple(),\n indigo: this.getIndigo(),\n blue: this.getBlue(),\n lightBlue: this.getLightBlue(),\n cyan: this.getCyan(),\n teal: this.getTeal(),\n green: this.getGreen(),\n lightGreen: this.getLightGreen(),\n lime: this.getLime(),\n yellow: this.getYellow(),\n amber: this.getAmber(),\n orange: this.getOrange(),\n deepOrange: this.getDeepOrange(),\n brown: this.getBrown(),\n };\n }\n\n private getGrey(): ColorScale {\n return {\n 50: '#fafafa',\n 100: '#f5f5f5',\n 200: '#eeeeee',\n 300: '#e0e0e0',\n 400: '#bdbdbd',\n 500: '#9e9e9e',\n 600: '#757575',\n 700: '#616161',\n 800: '#424242',\n 900: '#212121',\n A100: '#f5f5f5',\n A200: '#eeeeee',\n A400: '#bdbdbd',\n A700: '#616161',\n };\n }\n\n private getRed(): ColorScale {\n return {\n 50: '#ffebee',\n 100: '#ffcdd2',\n 200: '#ef9a9a',\n 300: '#e57373',\n 400: '#ef5350',\n 500: '#f44336',\n 600: '#e53935',\n 700: '#d32f2f',\n 800: '#c62828',\n 900: '#b71c1c',\n A100: '#ff8a80',\n A200: '#ff5252',\n A400: '#ff1744',\n A700: '#d50000',\n };\n }\n\n private getPink(): ColorScale {\n return {\n 50: '#fce4ec',\n 100: '#f8bbd0',\n 200: '#f48fb1',\n 300: '#f06292',\n 400: '#ec407a',\n 500: '#e91e63',\n 600: '#d81b60',\n 700: '#c2185b',\n 800: '#ad1457',\n 900: '#880e4f',\n A100: '#ff80ab',\n A200: '#ff4081',\n A400: '#f50057',\n A700: '#c51162',\n };\n }\n\n private getPurple(): ColorScale {\n return {\n 50: '#f3e5f5',\n 100: '#e1bee7',\n 200: '#ce93d8',\n 300: '#ba68c8',\n 400: '#ab47bc',\n 500: '#9c27b0',\n 600: '#8e24aa',\n 700: '#7b1fa2',\n 800: '#6a1b9a',\n 900: '#4a148c',\n A100: '#ea80fc',\n A200: '#e040fb',\n A400: '#d500f8',\n A700: '#aa00ff',\n };\n }\n\n private getDeepPurple(): ColorScale {\n return {\n 50: '#ede7f6',\n 100: '#d1c4e9',\n 200: '#b39ddb',\n 300: '#9575cd',\n 400: '#7e57c2',\n 500: '#673ab7',\n 600: '#5e35b1',\n 700: '#512da8',\n 800: '#4527a0',\n 900: '#311b92',\n A100: '#b388ff',\n A200: '#7c4dff',\n A400: '#651fff',\n A700: '#6200ea',\n };\n }\n\n private getIndigo(): ColorScale {\n return {\n 50: '#e8eaf6',\n 100: '#c5cae9',\n 200: '#9fa8da',\n 300: '#7986cb',\n 400: '#5c6bc0',\n 500: '#3f51b5',\n 600: '#3949ab',\n 700: '#303f9f',\n 800: '#283593',\n 900: '#1a237e',\n A100: '#8c9eff',\n A200: '#536dfe',\n A400: '#3d5afe',\n A700: '#304ffe',\n };\n }\n\n private getBlue(): ColorScale {\n return {\n 50: '#e3f2fd',\n 100: '#bbdefb',\n 200: '#90caf9',\n 300: '#64b5f6',\n 400: '#42a5f5',\n 500: '#2196f3',\n 600: '#1e88e5',\n 700: '#1976d2',\n 800: '#1565c0',\n 900: '#0d47a1',\n A100: '#82b1ff',\n A200: '#448aff',\n A400: '#2979ff',\n A700: '#2962ff',\n };\n }\n\n private getLightBlue(): ColorScale {\n return {\n 50: '#e1f5fe',\n 100: '#b3e5fc',\n 200: '#81d4fa',\n 300: '#4fc3f7',\n 400: '#29b6f6',\n 500: '#03a9f4',\n 600: '#039be5',\n 700: '#0288d1',\n 800: '#0277bd',\n 900: '#01579b',\n A100: '#80d8ff',\n A200: '#40c4ff',\n A400: '#00b0ff',\n A700: '#0091ea',\n };\n }\n\n private getCyan(): ColorScale {\n return {\n 50: '#e0f7fa',\n 100: '#b2ebf2',\n 200: '#80deea',\n 300: '#4dd0e1',\n 400: '#26c6da',\n 500: '#00bcd4',\n 600: '#00acc1',\n 700: '#0097a7',\n 800: '#00838f',\n 900: '#006064',\n A100: '#84ffff',\n A200: '#18ffff',\n A400: '#00e5ff',\n A700: '#00b8d4',\n };\n }\n\n private getTeal(): ColorScale {\n return {\n 50: '#e0f2f1',\n 100: '#b2dfdb',\n 200: '#80cbc4',\n 300: '#4db6ac',\n 400: '#26a69a',\n 500: '#009688',\n 600: '#00897b',\n 700: '#00796b',\n 800: '#00695c',\n 900: '#004d40',\n A100: '#a7ffeb',\n A200: '#64ffda',\n A400: '#1de9b6',\n A700: '#00bfa5',\n };\n }\n\n private getGreen(): ColorScale {\n return {\n 50: '#e8f5e9',\n 100: '#c8e6c9',\n 200: '#a5d6a7',\n 300: '#81c784',\n 400: '#66bb6a',\n 500: '#4caf50',\n 600: '#43a047',\n 700: '#388e3c',\n 800: '#2e7d32',\n 900: '#1b5e20',\n A100: '#b9f6ca',\n A200: '#69f0ae',\n A400: '#00e676',\n A700: '#00c853',\n };\n }\n\n private getLightGreen(): ColorScale {\n return {\n 50: '#f1f8e9',\n 100: '#dcedc8',\n 200: '#c5e1a5',\n 300: '#aed581',\n 400: '#9ccc65',\n 500: '#8bc34a',\n 600: '#7cb342',\n 700: '#689f38',\n 800: '#558b2f',\n 900: '#33691e',\n A100: '#ccff90',\n A200: '#b2ff59',\n A400: '#76ff03',\n A700: '#64dd17',\n };\n }\n\n private getLime(): ColorScale {\n return {\n 50: '#f9fbe7',\n 100: '#f0f4c3',\n 200: '#e6ee9c',\n 300: '#dce775',\n 400: '#d4e157',\n 500: '#cddc39',\n 600: '#c0ca33',\n 700: '#afb42b',\n 800: '#9fa827',\n 900: '#827717',\n A100: '#f4ff81',\n A200: '#eeff41',\n A400: '#c6ff00',\n A700: '#aeea00',\n };\n }\n\n private getYellow(): ColorScale {\n return {\n 50: '#fffde7',\n 100: '#fff9c4',\n 200: '#fff59d',\n 300: '#fff176',\n 400: '#ffee58',\n 500: '#ffeb3b',\n 600: '#fdd835',\n 700: '#fbc02d',\n 800: '#f9a825',\n 900: '#f57f17',\n A100: '#ffff8d',\n A200: '#ffff00',\n A400: '#ffea00',\n A700: '#ffd600',\n };\n }\n\n private getAmber(): ColorScale {\n return {\n 50: '#fff8e1',\n 100: '#ffecb3',\n 200: '#ffe082',\n 300: '#ffd54f',\n 400: '#ffca28',\n 500: '#ffc107',\n 600: '#ffb300',\n 700: '#ffa000',\n 800: '#ff8f00',\n 900: '#ff6f00',\n A100: '#ffe57f',\n A200: '#ffd740',\n A400: '#ffc400',\n A700: '#ffab00',\n };\n }\n\n private getOrange(): ColorScale {\n return {\n 50: '#fff3e0',\n 100: '#ffe0b2',\n 200: '#ffcc80',\n 300: '#ffb74d',\n 400: '#ffa726',\n 500: '#ff9800',\n 600: '#fb8c00',\n 700: '#f57c00',\n 800: '#ef6c00',\n 900: '#e65100',\n A100: '#ffd180',\n A200: '#ffab40',\n A400: '#ff9100',\n A700: '#ff6d00',\n };\n }\n\n private getDeepOrange(): ColorScale {\n return {\n 50: '#fbe9e7',\n 100: '#ffccbc',\n 200: '#ffab91',\n 300: '#ff8a65',\n 400: '#ff7043',\n 500: '#ff5722',\n 600: '#f4511e',\n 700: '#e64a19',\n 800: '#d84315',\n 900: '#bf360c',\n A100: '#ff9e80',\n A200: '#ff6e40',\n A400: '#ff3d00',\n A700: '#dd2c00',\n };\n }\n\n private getBrown(): BrownScale {\n return {\n 50: '#efebe9',\n 100: '#d7ccc8',\n 200: '#bcaaa4',\n 300: '#a1887f',\n 400: '#8d6e63',\n 500: '#795548',\n 600: '#6d4c41',\n 700: '#5d4037',\n 800: '#4e342e',\n 900: '#3e2723',\n };\n }\n}\n\n", "/*\n * Copyright 2026 Evan Smalley.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n */\n\n// Handles toast components throughout the app\n\nexport interface ToastItem {\n id: number;\n message: string;\n type: string;\n exiting?: boolean;\n}\n\n// Define the shape of the listener function\nexport type ToastListener = (toasts: ToastItem[]) => void;\n\nexport class Toaster {\n private listeners: ToastListener[] = [];\n\n private toasts: ToastItem[] = [];\n\n // Monotonic counter. Date.now() collides when two toasts are added inside\n // the same millisecond, which makes remove()/requestClose() affect every\n // toast that shares the timestamp.\n private nextId = 0;\n\n // How long the UI has to play its exit animation before the toast is\n // dropped from the list.\n public static readonly EXIT_ANIMATION_MS = 500;\n\n // How long a toast stays up before it starts exiting.\n public static readonly AUTO_DISMISS_MS = 4000;\n\n /**\n * The current toasts.\n *\n * Returns a copy, so callers cannot mutate the internal list.\n */\n getToasts(): ToastItem[] {\n return [...this.toasts];\n }\n\n // React component will subscribe to this\n subscribe(listener: ToastListener): () => void {\n this.listeners.push(listener);\n return () => {\n this.listeners = this.listeners.filter((l) => l !== listener);\n };\n }\n\n notify(): void {\n this.listeners.forEach((listener) => listener(this.toasts));\n }\n\n /**\n * Start a toast's exit: flag it so the UI can animate, then drop it once the\n * animation has had time to play.\n *\n * Calling this twice for the same toast does not schedule a second removal.\n */\n requestClose(id: number): void {\n const target = this.toasts.find((t) => t.id === id);\n\n if (!target || target.exiting) {\n return;\n }\n\n this.toasts = this.toasts.map((t) => {\n if (t.id === id) {\n return { ...t, exiting: true };\n }\n return t;\n });\n this.notify();\n\n // Safety net, not the primary path. A UI normally removes the toast itself\n // when its exit animation ends, which is sooner than this. That callback\n // can fail to arrive though -- a backgrounded tab, an unmount mid-animation,\n // reduced-motion settings -- and nothing else would ever drop the toast.\n // remove() is silent when the consumer already handled it.\n setTimeout(() => {\n this.remove(id);\n }, Toaster.EXIT_ANIMATION_MS);\n }\n\n /**\n * Add a toast and return its id, so callers can dismiss it early.\n */\n add(message: string, type = 'info'): number {\n this.nextId += 1;\n const id = this.nextId;\n this.toasts = [...this.toasts, { id, message, type }];\n this.notify();\n\n // Auto-remove\n setTimeout(() => {\n this.requestClose(id);\n }, Toaster.AUTO_DISMISS_MS);\n\n return id;\n }\n\n /**\n * Remove a toast immediately, without waiting for an exit animation.\n *\n * Removing an id that is not present is silent: it broadcasts nothing, so a\n * consumer that has already removed the toast itself does not get a\n * redundant re-render from the safety-net removal in `requestClose`.\n */\n remove(id: number): void {\n const remaining = this.toasts.filter((t) => t.id !== id);\n\n if (remaining.length === this.toasts.length) {\n return;\n }\n\n this.toasts = remaining;\n this.notify();\n }\n}\n\nexport const toaster: Toaster = new Toaster();\n\nexport const toast: {\n info: (msg: string) => void;\n error: (msg: string) => void;\n success: (msg: string) => void;\n} = {\n info: (msg: string) => toaster.add(msg, 'info'),\n error: (msg: string) => toaster.add(msg, 'error'),\n success: (msg: string) => toaster.add(msg, 'success'),\n};\n", "/* eslint-disable no-bitwise */\n/*\n * Copyright 2026 Evan Smalley.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n */\n\n\n// 32 hex digits, with or without the canonical dashes already stripped.\nconst HEX_ONLY = /^[0-9a-fA-F]{32}$/;\n\n/**\n * Generate UUIDv7\n */\nclass UuidService {\n private lastTimestamp = -1;\n private seqCounter = 0;\n\n /**\n * Whether a string is a well-formed UUID, dashed or bare.\n *\n * @example\n * uuidService.isValid('01234567-89ab-7cde-8f01-23456789abcd'); // true\n */\n public isValid(uuid: string): boolean {\n return typeof uuid === 'string' && HEX_ONLY.test(uuid.replaceAll('-', ''));\n }\n\n private getRandomBytes(size: number): Uint8Array {\n if (typeof globalThis.crypto?.getRandomValues === 'function') {\n const bytes = new Uint8Array(size);\n globalThis.crypto.getRandomValues(bytes);\n return bytes;\n }\n\n throw new Error('Secure crypto functionality is not available in this environment.');\n }\n\n public generateUUIDv7Bytes(): Uint8Array {\n let now = Date.now();\n\n if (now === this.lastTimestamp) {\n this.seqCounter++;\n\n // 12-bit counter overflow (> 4095 IDs in 1ms): advance timestamp artificially\n if (this.seqCounter > 0x0fff) {\n this.lastTimestamp++;\n now = this.lastTimestamp;\n this.seqCounter = 0;\n }\n } else if (now < this.lastTimestamp) {\n // Clock drift / NTP rollback: hold timestamp and increment counter to maintain monotonicity\n this.seqCounter++;\n if (this.seqCounter > 0x0fff) {\n this.lastTimestamp++;\n this.seqCounter = 0;\n }\n now = this.lastTimestamp;\n } else {\n // New millisecond: update state and reset sequence counter\n this.lastTimestamp = now;\n this.seqCounter = 0;\n }\n\n // Allocate 16 random bytes for remaining entropy (rand_b)\n const buf = this.getRandomBytes(16);\n\n // 1. Write 48-bit Unix timestamp into bytes 0..5\n buf[0] = Math.floor(now / 0x10000000000) & 0xff;\n buf[1] = Math.floor(now / 0x100000000) & 0xff;\n buf[2] = (now >>> 24) & 0xff;\n buf[3] = (now >>> 16) & 0xff;\n buf[4] = (now >>> 8) & 0xff;\n buf[5] = now & 0xff;\n\n // 2. Byte 6: Version 7 (0x70) + upper 4 bits of 12-bit counter\n buf[6] = 0x70 | ((this.seqCounter >> 8) & 0x0f);\n\n // 3. Byte 7: Lower 8 bits of 12-bit counter\n buf[7] = this.seqCounter & 0xff;\n\n // 4. Byte 8: Set Variant RFC 4122 (0x80) on remaining random bits\n buf[8] = (buf[8] & 0x3f) | 0x80;\n\n return buf;\n }\n\n /**\n * Convert a UUID string to binary Uint8Array\n */\n public uuidToBin(uuid: string): Uint8Array {\n // Stripped once and validated in place: routing through isValid() would\n // build the same string a second time on every conversion.\n const hex = typeof uuid === 'string' ? uuid.replaceAll('-', '') : '';\n\n if (!HEX_ONLY.test(hex)) {\n throw new Error(`Invalid UUID: ${uuid}`);\n }\n\n const bytes = new Uint8Array(16);\n\n for (let i = 0; i < 16; i++) {\n bytes[i] = parseInt(hex.substring(i * 2, i * 2 + 2), 16);\n }\n\n return bytes;\n }\n\n /**\n * Convert binary Uint8Array/Buffer to formatted UUID string\n */\n public binToUuid(buffer: Uint8Array): string {\n if (buffer.length !== 16) {\n throw new Error('UUID buffer must contain exactly 16 bytes.');\n }\n let hex = '';\n for (let i = 0; i < buffer.length; i++) {\n hex += buffer[i].toString(16).padStart(2, '0');\n }\n\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;\n }\n}\n// export as a singleton\nexport const uuidService: UuidService = new UuidService();\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["Arithmetic", "_Arithmetic", "number", "min", "max", "a", "b", "amount", "value", "precision", "shift", "input", "exponent", "parts", "inMin", "inMax", "outMin", "outMax", "values", "total", "counts", "i", "highest", "count", "modes", "population", "divisor", "average", "p", "sorted", "position", "lower", "upper", "COLLATOR", "Arrayifier", "array", "currentIndex", "randomIndex", "arr", "n", "r", "index", "data", "results", "nOrR", "maybeR", "size", "chunks", "i", "keyFn", "seen", "item", "key", "groups", "counts", "direction", "factor", "decorated", "a", "b", "aKey", "bKey", "aEmpty", "bEmpty", "entry", "predicate", "passed", "failed", "start", "end", "step", "from", "to", "values", "CSV", "_CSV", "value", "str", "data", "headers", "seen", "id", "key", "rows", "header", "row", "content", "blob", "url", "a", "Color", "_Color", "a", "b", "amount", "ar", "ag", "ab", "br", "bg", "bb", "t", "rr", "rg", "rb", "color", "backgroundColor", "debug", "g", "contrastTarget", "contrastToBlack", "contrastToWhite", "direction", "adjust", "c", "lighter", "i", "rgb1", "rgb2", "luminance", "r", "v", "lum1", "lum2", "hex", "remaining", "r2", "g2", "b2", "percent", "color1", "color2", "threshold", "invertedR", "invertedG", "invertedB", "alpha", "h", "s", "l", "analogousColors", "offset", "newHue", "newR", "newG", "newB", "char", "bigint", "channel", "value", "max", "min", "d", "hue2rgb", "p", "q", "r1", "g1", "b1", "dr", "dg", "db", "FORMATTERS", "MAGNITUDES", "DURATIONS", "BYTE_UNITS", "Numbers", "_Numbers", "value", "absolute", "whole", "decimals", "locale", "maximumFractionDigits", "key", "formatter", "sign", "unit", "threshold", "Arithmetic", "suffix", "scaled", "fromRatio", "percent", "ms", "parts", "remaining", "pieces", "started", "i", "size", "amount", "selected", "bytes", "exponent", "Dates", "str", "utc", "input", "year", "month", "day", "timePart", "isoMatch", "usMatch", "d", "hours", "minutes", "seconds", "timeMatch", "meridiem", "dateInput", "format", "date", "pad", "n", "monthsShort", "monthsLong", "daysShort", "daysLong", "Y", "y", "dateNum", "tzAbbr", "tzIdentifier", "tokens", "Numbers", "_", "esc", "token", "amount", "unit", "originalDay", "map", "diff", "mins", "dateToMatch", "datesArray", "matchDate", "closestDate", "closestDist", "dateStr", "currDate", "dist", "dayOfWeek", "result", "start", "end", "last", "current", "days", "inclusive", "value", "a", "b", "lower", "upper", "date1", "date2", "d1", "d2", "janOffset", "julOffset", "standardTimezoneOffset", "timeZone", "parts", "getPart", "type", "p", "weekday", "ms", "y1", "y2", "m1", "m2", "months", "years", "weeks", "Kontororu", "__publicField", "type", "listener", "registered", "Tasker", "_Tasker", "ms", "resolve", "attempt", "options", "delay", "factor", "maxDelay", "jitter", "computed", "fn", "attempts", "onRetry", "shouldRetry", "backoffOptions", "total", "lastError", "error", "wait", "leading", "timer", "lastArgs", "run", "args", "debounced", "callNow", "throttled", "keyFn", "cache", "memoized", "key", "cached", "result", "called", "debug", "Socket", "Kontororu", "__publicField", "event", "offline_timeout", "stopOfflineChecks", "offlineChecker", "check", "checked", "checker", "hostname", "port", "path", "session_id", "config", "type", "table", "id", "payload", "new_connection_state", "old_connection_state", "source", "time_since_last", "queuedMsg", "data", "messageEvent", "delay", "Tasker", "socket", "Objector", "_Objector", "obj", "memo", "clonedDate", "clonedRegExp", "clonedMap", "value", "key", "newSet", "item", "clonedArray", "index", "clonedObj", "sourceObj", "sym", "a", "b", "seen", "pairs", "other", "remaining", "match", "candidate", "aRecord", "bRecord", "aKeys", "bKeys", "aSymbols", "bSymbols", "target", "sources", "to", "source", "symbols", "toFilter", "args", "skip", "columns", "values", "lists", "column", "value", "matchesRow", "row", "record", "i", "rowValue", "Store", "Kontororu", "__publicField", "data", "table", "results", "firstId", "primaryKey", "id", "Objector", "filter", "matches", "Sorter", "a", "b", "orderBy", "direction_", "a_value", "b_value", "a_empty", "b_empty", "direction", "order", "Textor", "str", "a", "b", "matrix", "i", "j", "cost", "trimmed", "paragraphs", "sentencesPerParagraph", "startWithLorem", "words", "getRandomWord", "generateSentence", "isFirstSentence", "sentenceLength", "sentenceWords", "sentence", "commaIndex", "splitSentence", "paragraphList", "p", "sentenceCount", "sentences", "s", "isAbsoluteFirst", "_Style", "depth", "shadows", "cssString", "debug", "className", "css", "canonicalize", "obj", "sortedKeys", "canonical", "sourceObj", "key", "normalizedInput", "val", "canonicalObject", "hash", "i", "finalCSS", "styleEl", "isRecursive", "cleanSelector", "sel", "removeLastBrace", "lines", "lastIdx", "lastLine", "braceIdx", "newLine", "requiresQuotes", "lengthProps", "non_recursive_at_rules", "isNonRecursiveRule", "ruleName", "prefix", "normalizeValue", "property", "value", "trimmed", "normalizeCSSLine", "line", "colonIndex", "rawProperty", "Textor", "part", "match", "innerValue", "cssLine", "objectToLines", "nested", "finalValue", "topLevelRules", "nestedRules", "atRules", "currentNestedSelector", "currentAtRule", "atRuleLines", "atRuleBraceCount", "nestedLines", "nestedBraceCount", "rawBlock", "contentOnly", "processed", "l", "isHighlightPseudo", "selector", "__publicField", "Style", "Theme", "mode", "__publicField", "_Toaster", "__publicField", "listener", "l", "id", "target", "t", "message", "type", "remaining", "Toaster", "toaster", "toast", "msg", "HEX_ONLY", "UuidService", "__publicField", "uuid", "size", "bytes", "now", "buf", "hex", "i", "buffer", "uuidService"]
|
|
7
7
|
}
|