@w3ux/utils 3.1.0 → 3.1.1
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/index.cjs +14 -0
- package/index.cjs.map +1 -1
- package/index.d.cts +4 -2
- package/index.d.ts +4 -2
- package/index.js +13 -0
- package/index.js.map +1 -1
- package/package.json +1 -1
package/index.cjs
CHANGED
|
@@ -37,6 +37,7 @@ __export(index_exports, {
|
|
|
37
37
|
matchedProperties: () => matchedProperties,
|
|
38
38
|
maxBigInt: () => maxBigInt,
|
|
39
39
|
mergeDeep: () => mergeDeep,
|
|
40
|
+
mergeRefs: () => mergeRefs,
|
|
40
41
|
minBigInt: () => minBigInt,
|
|
41
42
|
minDecimalPlaces: () => minDecimalPlaces,
|
|
42
43
|
pageFromUri: () => pageFromUri,
|
|
@@ -198,6 +199,18 @@ var u8aConcat = (...u8as) => {
|
|
|
198
199
|
return result;
|
|
199
200
|
};
|
|
200
201
|
|
|
202
|
+
// src/jsx.ts
|
|
203
|
+
var mergeRefs = (el, internalRef, externalRef) => {
|
|
204
|
+
internalRef.current = el;
|
|
205
|
+
if (externalRef) {
|
|
206
|
+
if (typeof externalRef === "function") {
|
|
207
|
+
externalRef(el);
|
|
208
|
+
} else {
|
|
209
|
+
externalRef.current = el;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
|
|
201
214
|
// src/unit.ts
|
|
202
215
|
var planckToUnit = (val, units) => {
|
|
203
216
|
try {
|
|
@@ -411,6 +424,7 @@ var mergeDeep = (target, ...sources) => {
|
|
|
411
424
|
matchedProperties,
|
|
412
425
|
maxBigInt,
|
|
413
426
|
mergeDeep,
|
|
427
|
+
mergeRefs,
|
|
414
428
|
minBigInt,
|
|
415
429
|
minDecimalPlaces,
|
|
416
430
|
pageFromUri,
|
package/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/base.ts","../src/convert.ts","../src/unit.ts"],"sourcesContent":["/* @license Copyright 2024 w3ux authors & contributors\nSPDX-License-Identifier: GPL-3.0-only */\n\nexport * from './base'\nexport * from './convert'\nexport * from './unit'\n","/* @license Copyright 2024 w3ux authors & contributors\nSPDX-License-Identifier: GPL-3.0-only */\n\n/**\n * Ensures a number has at least the specified number of decimal places, retaining commas in the output if they are present in the input.\n *\n * @function minDecimalPlaces\n * @param {string | number | BigInt} val - The input number, which can be a `string` with or without commas, a `number`, or a `BigInt`.\n * @param {number} minDecimals - The minimum number of decimal places to enforce.\n * @returns {string} The formatted number as a string, padded with zeros if needed to meet `minDecimals`, retaining commas if originally provided.\n * If `val` is invalid, returns \"0\".\n * @example\n * // Pads \"1,234.5\" to have at least 3 decimal places, with commas\n * minDecimalPlaces(\"1,234.5\", 3); // returns \"1,234.500\"\n *\n * // Returns \"1234.56\" unchanged\n * minDecimalPlaces(1234.56, 2); // returns \"1234.56\"\n *\n * // Pads BigInt 1234 with 2 decimals\n * minDecimalPlaces(BigInt(1234), 2); // returns \"1234.00\"\n */\nexport const minDecimalPlaces = (\n\tval: string | number | bigint,\n\tminDecimals: number,\n): string => {\n\ttry {\n\t\t// Determine if we should retain commas based on original input type\n\t\tconst retainCommas = typeof val === 'string' && val.includes(',')\n\n\t\t// Convert `val` to a plain string for processing\n\t\tconst strVal =\n\t\t\ttypeof val === 'string' ? val.replace(/,/g, '') : val.toString()\n\n\t\t// Separate integer and decimal parts\n\t\tconst [integerPart, fractionalPart = ''] = strVal.split('.')\n\n\t\t// Parse the integer part as a BigInt\n\t\tconst whole = BigInt(integerPart || '0')\n\n\t\t// Calculate missing decimal places\n\t\tconst missingDecimals = minDecimals - fractionalPart.length\n\n\t\t// Format the integer part back with commas only if the input had commas\n\t\tconst formattedWhole = retainCommas\n\t\t\t? Intl.NumberFormat('en-US').format(whole)\n\t\t\t: whole.toString()\n\n\t\t// If missing decimals are needed, pad with zeros; otherwise, return the original value\n\t\treturn missingDecimals > 0\n\t\t\t? `${formattedWhole}.${fractionalPart}${'0'.repeat(missingDecimals)}`\n\t\t\t: `${formattedWhole}.${fractionalPart}`\n\t} catch {\n\t\t// The provided value is not a valid number, return \"0\".\n\t\treturn '0'\n\t}\n}\n\n/**\n * @name camelize\n * @summary Converts a string of text to camelCase.\n */\nexport const camelize = (str: string) => {\n\tconst convertToString = (string: string) => {\n\t\tif (string) {\n\t\t\tif (typeof string === 'string') {\n\t\t\t\treturn string\n\t\t\t}\n\t\t\treturn String(string)\n\t\t}\n\t\treturn ''\n\t}\n\n\tconst toWords = (inp: string) =>\n\t\tconvertToString(inp).match(\n\t\t\t/[A-Z\\xC0-\\xD6\\xD8-\\xDE]?[a-z\\xDF-\\xF6\\xF8-\\xFF]+|[A-Z\\xC0-\\xD6\\xD8-\\xDE]+(?![a-z\\xDF-\\xF6\\xF8-\\xFF])|\\d+/g,\n\t\t)\n\n\tconst simpleCamelCase = (inp: string[]) => {\n\t\tlet result = ''\n\t\tfor (let i = 0; i < inp?.length; i++) {\n\t\t\tconst currString = inp[i]\n\t\t\tlet tmpStr = currString.toLowerCase()\n\t\t\tif (i !== 0) {\n\t\t\t\ttmpStr =\n\t\t\t\t\ttmpStr.slice(0, 1).toUpperCase() + tmpStr.slice(1, tmpStr.length)\n\t\t\t}\n\t\t\tresult += tmpStr\n\t\t}\n\t\treturn result\n\t}\n\n\tconst w = toWords(str)?.map((a) => a.toLowerCase())\n\treturn simpleCamelCase(w || [])\n}\n\n/**\n * @name ellipsisFn\n * @summary Receives an address and creates ellipsis on the given string, based on parameters.\n * @param str - The string to apply the ellipsis on\n * @param amount - The amount of characters that the ellipsis will be\n * @param position - where the ellipsis will apply; if center the amount of character is the\n * same for beginning and end; if \"start\" or \"end\" then its only once the amount; defaults to \"start\"\n */\nexport const ellipsisFn = (\n\tstr: string,\n\tamount = 6,\n\tposition: 'start' | 'end' | 'center' = 'center',\n) => {\n\tconst half = str.length / 2\n\n\t// having an amount less than 4 is a bit extreme so we default there\n\tif (amount <= 4) {\n\t\tif (position === 'center') {\n\t\t\treturn str.slice(0, 4) + '...' + str.slice(-4)\n\t\t}\n\t\tif (position === 'end') {\n\t\t\treturn str.slice(0, 4) + '...'\n\t\t}\n\t\treturn '...' + str.slice(-4)\n\t}\n\t// if the amount requested is in a \"logical\" amount - meaning that it can display the address\n\t// without repeating the same information twice - then go for it;\n\tif (position === 'center') {\n\t\treturn amount >= (str.length - 2) / 2\n\t\t\t? str.slice(0, half - 3) + '...' + str.slice(-(half - 3))\n\t\t\t: str.slice(0, amount) + '...' + str.slice(-amount)\n\t}\n\t// else, the user has been mistaskenly extreme, so just show the maximum possible amount\n\tif (amount >= str.length) {\n\t\tif (position === 'end') {\n\t\t\treturn str.slice(0, str.length - 3) + '...'\n\t\t}\n\t\treturn '...' + str.slice(-(str.length - 3))\n\t} else {\n\t\tif (position === 'end') {\n\t\t\treturn str.slice(0, amount) + '...'\n\t\t}\n\t\treturn '...' + str.slice(amount)\n\t}\n}\n\n/**\n * @name pageFromUri\n * @summary Use url variables to load the default components upon the first page visit.\n */\nexport const pageFromUri = (pathname: string, fallback: string) => {\n\tconst lastUriItem = pathname.substring(pathname.lastIndexOf('/') + 1)\n\tconst page = lastUriItem.trim() === '' ? fallback : lastUriItem\n\treturn page.trim()\n}\n\n/**\n * @name rmCommas\n * @summary Removes the commas from a string.\n */\nexport const rmCommas = (val: string): string => val.replace(/,/g, '')\n\n/**\n * @name rmDecimals\n * @summary Removes the decimal point and decimals from a string.\n */\nexport const rmDecimals = (str: string) => str.split('.')[0]\n\n/**\n * @name shuffle\n * @summary Shuffle a set of objects.\n */\nexport const shuffle = <T>(array: T[]) => {\n\tlet currentIndex = array.length\n\tlet randomIndex\n\twhile (currentIndex !== 0) {\n\t\trandomIndex = Math.floor(Math.random() * currentIndex)\n\t\tcurrentIndex--\n\t\t;[array[currentIndex], array[randomIndex]] = [\n\t\t\tarray[randomIndex],\n\t\t\tarray[currentIndex],\n\t\t]\n\t}\n\treturn array\n}\n\n/**\n * @name withTimeout\n * @summary Timeout a promise after a specified number of milliseconds.\n */\nexport const withTimeout = (\n\tms: number,\n\tpromise: Promise<unknown>,\n\toptions?: {\n\t\tonTimeout?: () => void\n\t},\n) => {\n\tconst timeout = new Promise((resolve) =>\n\t\tsetTimeout(async () => {\n\t\t\tif (typeof options?.onTimeout === 'function') {\n\t\t\t\toptions.onTimeout()\n\t\t\t}\n\t\t\tresolve(undefined)\n\t\t}, ms),\n\t)\n\treturn Promise.race([promise, timeout])\n}\n\n/**\n * @name withTimeoutThrow\n * @summary Timeout a promise after a specified number of milliseconds by throwing an error\n */\nexport const withTimeoutThrow = <T>(\n\tms: number,\n\tpromise: Promise<T>,\n\toptions?: {\n\t\tonTimeout?: () => void\n\t},\n) => {\n\tconst timeout = new Promise((reject) =>\n\t\tsetTimeout(async () => {\n\t\t\tif (typeof options?.onTimeout === 'function') {\n\t\t\t\toptions.onTimeout()\n\t\t\t}\n\t\t\treject('Function timeout')\n\t\t}, ms),\n\t)\n\treturn Promise.race([promise, timeout])\n}\n\n/**\n * @name appendOrEmpty\n * @summary Returns ` value` if a condition is truthy, or an empty string otherwise.\n */\nexport const appendOrEmpty = (\n\tcondition: boolean | string | undefined,\n\tvalue: string,\n) => (condition ? ` ${value}` : '')\n\n/**\n * @name appendOr\n * @summary Returns ` value` if condition is truthy, or ` fallback` otherwise.\n */\nexport const appendOr = (\n\tcondition: boolean | string | undefined,\n\tvalue: string,\n\tfallback: string,\n) => (condition ? ` ${value}` : ` ${fallback}`)\n\n/**\n * @name removeHexPrefix\n * @summary Takes a string str as input and returns a new string with the \"0x\" prefix removed if it\n * exists at the beginning of the input string.\n */\nexport const removeHexPrefix = (str: string): string => str.replace(/^0x/, '')\n\n// Check if 2 sets contain the same elements.\n// biome-ignore lint/suspicious/noExplicitAny: <>\nexport const eqSet = (xs: Set<any>, ys: Set<any>) =>\n\txs.size === ys.size && [...xs].every((x) => ys.has(x))\n\n// Check if one set contains all the elements of another set.\n// biome-ignore lint/suspicious/noExplicitAny: <>\nexport const isSuperset = (set: Set<any>, subset: Set<any>) => {\n\tfor (const elem of subset) {\n\t\tif (!set.has(elem)) {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\n/**\n * Finds the maximum value among a list of BigInt values.\n *\n * @function maxBigInt\n * @param {...bigint} values - A list of BigInt values to compare.\n * @returns {bigint} The largest BigInt value in the provided list.\n * @example\n * // Returns the maximum BigInt value\n * maxBigInt(10n, 50n, 30n, 100n, 20n); // 100n\n */\nexport const maxBigInt = (...values: bigint[]): bigint =>\n\tvalues.reduce((max, current) => (current > max ? current : max))\n\n/**\n * Finds the minimum value among a list of BigInt values.\n *\n * @function minBigInt\n * @param {...bigint} values - A list of BigInt values to compare.\n * @returns {bigint} The smallest BigInt value in the provided list.\n * @example\n * // Returns the minimum BigInt value\n * minBigInt(10n, 50n, 30n, 100n, 20n); // 10n\n */\nexport const minBigInt = (...values: bigint[]): bigint =>\n\tvalues.reduce((min, current) => (current < min ? current : min))\n","// /* @license Copyright 2024 w3ux authors & contributors\n// SPDX-License-Identifier: GPL-3.0-only */\n\n/**\n * Concatenates multiple Uint8Array instances into a single Uint8Array.\n *\n * @param {Uint8Array[]} u8as - An array of Uint8Array instances to concatenate.\n * @returns {Uint8Array} A new Uint8Array containing all the input arrays concatenated.\n */\nexport const u8aConcat = (...u8as: Uint8Array[]): Uint8Array => {\n\t// Calculate the total length of the resulting Uint8Array\n\tconst totalLength = u8as.reduce((sum, u8a) => sum + u8a.length, 0)\n\n\t// Create a new Uint8Array with the total length\n\tconst result = new Uint8Array(totalLength)\n\n\tlet offset = 0 // Initialize the offset for placing elements\n\tfor (const u8a of u8as) {\n\t\tresult.set(u8a, offset) // Set the current Uint8Array at the current offset\n\t\toffset += u8a.length // Update the offset for the next Uint8Array\n\t}\n\n\treturn result\n}\n","/* @license Copyright 2024 w3ux authors & contributors\nSPDX-License-Identifier: GPL-3.0-only */\n\nimport type { RefObject } from 'react'\nimport { rmCommas, rmDecimals } from './base'\nimport type { AnyObject } from './types'\n\n/**\n * Converts an on-chain balance value from planck to a decimal value in token units.\n *\n * @function planckToUnit\n * @param {number | BigInt | string} val - The balance value in planck. Accepts a `number`, `BigInt`, or `string`.\n * @param {number} units - The number of decimal places in the token unit (10^units planck per 1 token).\n * @returns {string} The equivalent token unit value as a decimal string.\n * @example\n * // Convert 1500000000000 planck to tokens with 12 decimal places\n * planckToUnit(\"1500000000000\", 12); // returns \"1.5\"\n */\nexport const planckToUnit = (\n\tval: number | bigint | string,\n\tunits: number,\n): string => {\n\ttry {\n\t\t// Ensure `units` is a positive integer.\n\t\tunits = Math.max(Math.round(units), 0)\n\n\t\t// Convert `val` to BigInt based on its type\n\t\tconst bigIntVal =\n\t\t\ttypeof val === 'bigint'\n\t\t\t\t? val\n\t\t\t\t: BigInt(\n\t\t\t\t\t\ttypeof val === 'number'\n\t\t\t\t\t\t\t? Math.floor(val).toString()\n\t\t\t\t\t\t\t: rmDecimals(rmCommas(val)),\n\t\t\t\t\t)\n\n\t\tconst divisor = units === 0 ? 1n : BigInt(10) ** BigInt(units)\n\n\t\t// Integer division and remainder for the fractional part\n\t\tconst integerPart = bigIntVal / divisor\n\t\tconst fractionalPart = bigIntVal % divisor\n\n\t\t// Format fractional part with leading zeros to maintain `units` decimal places\n\t\tconst fractionalStr =\n\t\t\tunits > 0 ? `.${fractionalPart.toString().padStart(units, '0')}` : ``\n\n\t\t// Combine integer and fractional parts as a decimal string\n\t\treturn `${integerPart}${fractionalStr}`\n\t} catch {\n\t\treturn '0'\n\t}\n}\n\n/**\n * Converts a token unit value to an integer value in planck.\n *\n * @function unitToPlanck\n * @param {string | number | BigInt} val - The token unit value to convert. Accepts a string, number, or BigInt.\n * @param {number} units - The number of decimal places for conversion (10^units planck per 1 token).\n * @returns {BigInt} The equivalent value in planck as a BigInt.\n * @example\n * // Convert \"1.5\" tokens to planck with 12 decimal places\n * unitToPlanck(\"1.5\", 12); // returns BigInt(\"1500000000000\")\n */\nexport const unitToPlanck = (\n\tval: string | number | bigint,\n\tunits: number,\n): bigint => {\n\ttry {\n\t\t// Ensure `units` is a positive integer.\n\t\tunits = Math.max(Math.round(units), 0)\n\n\t\t// Convert `val` to a string; if empty or invalid, default to \"0\"\n\t\tconst strVal =\n\t\t\t(typeof val === 'string' ? rmCommas(val) : val.toString()) || '0'\n\n\t\t// Split into integer and fractional parts\n\t\tconst [integerPart, fractionalPart = ''] = strVal.split('.')\n\n\t\t// Process the integer part by converting to BigInt and scaling it to the given units\n\t\tlet bigIntValue = BigInt(integerPart) * BigInt(10) ** BigInt(units)\n\n\t\t// Process the fractional part if it exists\n\t\tif (fractionalPart) {\n\t\t\tlet fractionalValue: bigint\n\n\t\t\tif (fractionalPart.length > units) {\n\t\t\t\t// If fractional part exceeds units, truncate it\n\t\t\t\tfractionalValue = BigInt(fractionalPart.slice(0, units))\n\t\t\t} else {\n\t\t\t\t// Otherwise, pad the fractional part to match units\n\t\t\t\tfractionalValue = BigInt(fractionalPart.padEnd(units, '0'))\n\t\t\t}\n\n\t\t\tbigIntValue += fractionalValue\n\t\t}\n\n\t\treturn bigIntValue\n\t} catch {\n\t\treturn BigInt(0)\n\t}\n}\n\n/**\n * @name remToUnit\n * @summary Converts a rem string to a number.\n */\nexport const remToUnit = (rem: string) =>\n\tNumber(rem.slice(0, rem.length - 3)) *\n\tparseFloat(getComputedStyle(document.documentElement).fontSize)\n\n/**\n * @name capitalizeFirstLetter\n * @summary Capitalize the first letter of a string.\n */\nexport const capitalizeFirstLetter = (string: string) =>\n\tstring.charAt(0).toUpperCase() + string.slice(1)\n\n/**\n * @name snakeToCamel\n * @summary converts a string from snake / kebab-case to camel-case.\n */\nexport const snakeToCamel = (str: string) =>\n\tstr\n\t\t.toLowerCase()\n\t\t.replace(/([-_][a-z])/g, (group) =>\n\t\t\tgroup.toUpperCase().replace('-', '').replace('_', ''),\n\t\t)\n\n/**\n * @name setStateWithRef\n * @summary Synchronize React state and its reference with the provided value.\n */\nexport const setStateWithRef = <T>(\n\tvalue: T,\n\tsetState: (_state: T) => void,\n\tref: RefObject<T>,\n): void => {\n\tsetState(value)\n\tref.current = value\n}\n\n/**\n * @name localStorageOrDefault\n * @summary Retrieve the local stroage value with the key, return defult value if it is not\n * found.\n */\nexport const localStorageOrDefault = <T>(\n\tkey: string,\n\t_default: T,\n\tparse = false,\n): T | string => {\n\tconst val: string | null = localStorage.getItem(key)\n\n\tif (val === null) {\n\t\treturn _default\n\t}\n\n\tif (parse) {\n\t\treturn JSON.parse(val) as T\n\t}\n\treturn val\n}\n\n/**\n * @name extractUrlValue\n * @summary Extracts a URL value from a URL string.\n */\nexport const extractUrlValue = (key: string, url?: string) => {\n\tif (typeof url === 'undefined') {\n\t\turl = window.location.href\n\t}\n\tconst match = url.match(`[?&]${key}=([^&]+)`)\n\treturn match ? match[1] : null\n}\n\n/**\n * @name varToUrlHash\n * @summary Puts a variable into the URL hash as a param.\n * @description\n * Since url variables are added to the hash and are not treated as URL params, the params are split\n * and parsed into a `URLSearchParams`.\n */\nexport const varToUrlHash = (\n\tkey: string,\n\tval: string,\n\taddIfMissing: boolean,\n) => {\n\tconst hash = window.location.hash\n\tconst [page, params] = hash.split('?')\n\tconst searchParams = new URLSearchParams(params)\n\n\tif (searchParams.get(key) === null && !addIfMissing) {\n\t\treturn\n\t}\n\tsearchParams.set(key, val)\n\twindow.location.hash = `${page}?${searchParams.toString()}`\n}\n\n/**\n * @name removeVarFromUrlHash\n * @summary\n * Removes a variable `key` from the URL hash if it exists. Removes dangling `?` if no URL variables\n * exist.\n */\nexport const removeVarFromUrlHash = (key: string) => {\n\tconst hash = window.location.hash\n\tconst [page, params] = hash.split('?')\n\tconst searchParams = new URLSearchParams(params)\n\tif (searchParams.get(key) === null) {\n\t\treturn\n\t}\n\tsearchParams.delete(key)\n\tconst paramsAsStr = searchParams.toString()\n\twindow.location.hash = `${page}${paramsAsStr ? `?${paramsAsStr}` : ``}`\n}\n\n/**\n * @name sortWithNull\n * @summary Sorts an array with nulls last.\n */\nexport const sortWithNull =\n\t(ascending: boolean) => (a: unknown, b: unknown) => {\n\t\t// if both items are undefined, treat them as equal\n\t\tif (typeof a === 'undefined' && typeof b === 'undefined') {\n\t\t\treturn 0\n\t\t}\n\t\t// if either item is undefined, sort it last\n\t\tif (typeof a === 'undefined' || typeof b === 'undefined') {\n\t\t\treturn typeof a === 'undefined' ? 1 : -1\n\t\t}\n\t\t// equal items sort equally\n\t\tif (a === b) {\n\t\t\treturn 0\n\t\t}\n\t\t// nulls sort after anything else\n\t\tif (a === null) {\n\t\t\treturn 1\n\t\t}\n\t\tif (b === null) {\n\t\t\treturn -1\n\t\t}\n\t\t// otherwise, if we're ascending, lowest sorts first\n\t\tif (ascending) {\n\t\t\treturn a < b ? -1 : 1\n\t\t}\n\t\t// if descending, highest sorts first\n\t\treturn a < b ? 1 : -1\n\t}\n\n/**\n * @name applyWidthAsPadding\n * @summary Applies width of subject to paddingRight of container.\n */\nexport const applyWidthAsPadding = (\n\tsubjectRef: RefObject<HTMLDivElement | null>,\n\tcontainerRef: RefObject<HTMLDivElement | null>,\n) => {\n\tif (containerRef.current && subjectRef.current) {\n\t\tcontainerRef.current.style.paddingRight = `${\n\t\t\tsubjectRef.current.offsetWidth + remToUnit('1rem')\n\t\t}px`\n\t}\n}\n\n/**\n * @name unescape\n * @summary Replaces \\” with “\n */\nexport const unescape = (val: string) => val.replace(/\\\\\"/g, '\"')\n\n/**\n * @name inChrome\n * @summary Whether the application is rendering in Chrome.\n */\nexport const inChrome = () => {\n\tconst isChromium = (window as Window & { chrome?: boolean })?.chrome || null\n\tconst winNav = (window as Window)?.navigator || null\n\tconst isOpera =\n\t\ttypeof (window as Window & { opr?: boolean })?.opr !== 'undefined'\n\tconst isIEedge = winNav?.userAgent.indexOf('Edg') > -1 || false\n\tconst isIOSChrome = winNav?.userAgent.match('CriOS') || false\n\n\tif (isIOSChrome) {\n\t\treturn true\n\t}\n\tif (\n\t\tisChromium !== null &&\n\t\ttypeof isChromium !== 'undefined' &&\n\t\tisOpera === false &&\n\t\tisIEedge === false\n\t) {\n\t\treturn true\n\t}\n\treturn false\n}\n\n/**\n * @name addedTo\n * @summary Given 2 objects and some keys, return items in the fresh object that do not exist in the\n * stale object by matching the given common key values of both objects.\n */\nexport const addedTo = (\n\tfresh: AnyObject[],\n\tstale: AnyObject[],\n\tkeys: string[],\n): AnyObject[] =>\n\ttypeof fresh !== 'object' || typeof stale !== 'object' || !keys.length\n\t\t? []\n\t\t: fresh.filter(\n\t\t\t\t(freshItem) =>\n\t\t\t\t\t!stale.find((staleItem) =>\n\t\t\t\t\t\tkeys.every((key) =>\n\t\t\t\t\t\t\t!(key in staleItem) || !(key in freshItem)\n\t\t\t\t\t\t\t\t? false\n\t\t\t\t\t\t\t\t: staleItem[key] === freshItem[key],\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t)\n\n/**\n * @name removedFrom\n * @summary Given 2 objects and some keys, return items in the stale object that do not exist in the\n * fresh object by matching the given common key values of both objects.\n */\nexport const removedFrom = (\n\tfresh: AnyObject[],\n\tstale: AnyObject[],\n\tkeys: string[],\n): AnyObject[] =>\n\ttypeof fresh !== 'object' || typeof stale !== 'object' || !keys.length\n\t\t? []\n\t\t: stale.filter(\n\t\t\t\t(staleItem) =>\n\t\t\t\t\t!fresh.find((freshItem) =>\n\t\t\t\t\t\tkeys.every((key) =>\n\t\t\t\t\t\t\t!(key in staleItem) || !(key in freshItem)\n\t\t\t\t\t\t\t\t? false\n\t\t\t\t\t\t\t\t: freshItem[key] === staleItem[key],\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t)\n\n/**\n * @name matchedProperties\n * @summary Given 2 objects and some keys, return items in object 1 that also exist in object 2 by\n * matching the given common key values of both objects.\n */\nexport const matchedProperties = (\n\tobjX: AnyObject[],\n\tobjY: AnyObject[],\n\tkeys: string[],\n): AnyObject[] =>\n\ttypeof objX !== 'object' || typeof objY !== 'object' || !keys.length\n\t\t? []\n\t\t: objY.filter((x) =>\n\t\t\t\tobjX.find((y) =>\n\t\t\t\t\tkeys.every((key) =>\n\t\t\t\t\t\t!(key in x) || !(key in y) ? false : y[key] === x[key],\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t)\n\n/**\n * @name isValidHttpUrl\n * @summary Give a string, return whether it is a valid http URL.\n * @param string - The string to check.\n */\nexport const isValidHttpUrl = (string: string) => {\n\tlet url: URL\n\ttry {\n\t\turl = new URL(string)\n\t} catch (_) {\n\t\treturn false\n\t}\n\treturn url.protocol === 'http:' || url.protocol === 'https:'\n}\n\n/**\n * @name makeCancelable\n * @summary Makes a promise cancellable.\n * @param promise - The promise to make cancellable.\n */\nexport const makeCancelable = (promise: Promise<AnyObject>) => {\n\tlet hasCanceled = false\n\n\tconst wrappedPromise = new Promise((resolve, reject) => {\n\t\tpromise.then((val) =>\n\t\t\thasCanceled ? reject(Error('Cancelled')) : resolve(val),\n\t\t)\n\t\tpromise.catch((error) =>\n\t\t\thasCanceled ? reject(Error('Cancelled')) : reject(error),\n\t\t)\n\t})\n\n\treturn {\n\t\tpromise: wrappedPromise,\n\t\tcancel: () => {\n\t\t\thasCanceled = true\n\t\t},\n\t}\n}\n\n/**\n * @name unimplemented\n * @summary A placeholder function to signal a deliberate unimplementation.\n * Consumes an arbitrary number of props.\n */\nexport const unimplemented = (_props?: unknown) => {\n\t/* unimplemented */\n}\n\n/**\n * Deep merge two objects.\n * @param target\n * @param ...sources\n */\n\nexport const mergeDeep = (\n\ttarget: AnyObject,\n\t...sources: AnyObject[]\n): AnyObject => {\n\tif (!sources.length) {\n\t\treturn target\n\t}\n\n\tconst isObject = (item: AnyObject) =>\n\t\titem && typeof item === 'object' && !Array.isArray(item)\n\tconst source = sources.shift()\n\n\tif (isObject(target) && isObject(source)) {\n\t\tfor (const key in source) {\n\t\t\tif (isObject(source[key])) {\n\t\t\t\tif (!target[key]) {\n\t\t\t\t\tObject.assign(target, { [key]: {} })\n\t\t\t\t}\n\t\t\t\tmergeDeep(target[key], source[key])\n\t\t\t} else {\n\t\t\t\tObject.assign(target, { [key]: source[key] })\n\t\t\t}\n\t\t}\n\t}\n\treturn mergeDeep(target, ...sources)\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/base.ts","../src/convert.ts","../src/jsx.ts","../src/unit.ts"],"sourcesContent":["/* @license Copyright 2024 w3ux authors & contributors\nSPDX-License-Identifier: GPL-3.0-only */\n\nexport * from './base'\nexport * from './convert'\nexport * from './jsx'\nexport * from './unit'\n","/* @license Copyright 2024 w3ux authors & contributors\nSPDX-License-Identifier: GPL-3.0-only */\n\n/**\n * Ensures a number has at least the specified number of decimal places, retaining commas in the output if they are present in the input.\n *\n * @function minDecimalPlaces\n * @param {string | number | BigInt} val - The input number, which can be a `string` with or without commas, a `number`, or a `BigInt`.\n * @param {number} minDecimals - The minimum number of decimal places to enforce.\n * @returns {string} The formatted number as a string, padded with zeros if needed to meet `minDecimals`, retaining commas if originally provided.\n * If `val` is invalid, returns \"0\".\n * @example\n * // Pads \"1,234.5\" to have at least 3 decimal places, with commas\n * minDecimalPlaces(\"1,234.5\", 3); // returns \"1,234.500\"\n *\n * // Returns \"1234.56\" unchanged\n * minDecimalPlaces(1234.56, 2); // returns \"1234.56\"\n *\n * // Pads BigInt 1234 with 2 decimals\n * minDecimalPlaces(BigInt(1234), 2); // returns \"1234.00\"\n */\nexport const minDecimalPlaces = (\n\tval: string | number | bigint,\n\tminDecimals: number,\n): string => {\n\ttry {\n\t\t// Determine if we should retain commas based on original input type\n\t\tconst retainCommas = typeof val === 'string' && val.includes(',')\n\n\t\t// Convert `val` to a plain string for processing\n\t\tconst strVal =\n\t\t\ttypeof val === 'string' ? val.replace(/,/g, '') : val.toString()\n\n\t\t// Separate integer and decimal parts\n\t\tconst [integerPart, fractionalPart = ''] = strVal.split('.')\n\n\t\t// Parse the integer part as a BigInt\n\t\tconst whole = BigInt(integerPart || '0')\n\n\t\t// Calculate missing decimal places\n\t\tconst missingDecimals = minDecimals - fractionalPart.length\n\n\t\t// Format the integer part back with commas only if the input had commas\n\t\tconst formattedWhole = retainCommas\n\t\t\t? Intl.NumberFormat('en-US').format(whole)\n\t\t\t: whole.toString()\n\n\t\t// If missing decimals are needed, pad with zeros; otherwise, return the original value\n\t\treturn missingDecimals > 0\n\t\t\t? `${formattedWhole}.${fractionalPart}${'0'.repeat(missingDecimals)}`\n\t\t\t: `${formattedWhole}.${fractionalPart}`\n\t} catch {\n\t\t// The provided value is not a valid number, return \"0\".\n\t\treturn '0'\n\t}\n}\n\n/**\n * @name camelize\n * @summary Converts a string of text to camelCase.\n */\nexport const camelize = (str: string) => {\n\tconst convertToString = (string: string) => {\n\t\tif (string) {\n\t\t\tif (typeof string === 'string') {\n\t\t\t\treturn string\n\t\t\t}\n\t\t\treturn String(string)\n\t\t}\n\t\treturn ''\n\t}\n\n\tconst toWords = (inp: string) =>\n\t\tconvertToString(inp).match(\n\t\t\t/[A-Z\\xC0-\\xD6\\xD8-\\xDE]?[a-z\\xDF-\\xF6\\xF8-\\xFF]+|[A-Z\\xC0-\\xD6\\xD8-\\xDE]+(?![a-z\\xDF-\\xF6\\xF8-\\xFF])|\\d+/g,\n\t\t)\n\n\tconst simpleCamelCase = (inp: string[]) => {\n\t\tlet result = ''\n\t\tfor (let i = 0; i < inp?.length; i++) {\n\t\t\tconst currString = inp[i]\n\t\t\tlet tmpStr = currString.toLowerCase()\n\t\t\tif (i !== 0) {\n\t\t\t\ttmpStr =\n\t\t\t\t\ttmpStr.slice(0, 1).toUpperCase() + tmpStr.slice(1, tmpStr.length)\n\t\t\t}\n\t\t\tresult += tmpStr\n\t\t}\n\t\treturn result\n\t}\n\n\tconst w = toWords(str)?.map((a) => a.toLowerCase())\n\treturn simpleCamelCase(w || [])\n}\n\n/**\n * @name ellipsisFn\n * @summary Receives an address and creates ellipsis on the given string, based on parameters.\n * @param str - The string to apply the ellipsis on\n * @param amount - The amount of characters that the ellipsis will be\n * @param position - where the ellipsis will apply; if center the amount of character is the\n * same for beginning and end; if \"start\" or \"end\" then its only once the amount; defaults to \"start\"\n */\nexport const ellipsisFn = (\n\tstr: string,\n\tamount = 6,\n\tposition: 'start' | 'end' | 'center' = 'center',\n) => {\n\tconst half = str.length / 2\n\n\t// having an amount less than 4 is a bit extreme so we default there\n\tif (amount <= 4) {\n\t\tif (position === 'center') {\n\t\t\treturn str.slice(0, 4) + '...' + str.slice(-4)\n\t\t}\n\t\tif (position === 'end') {\n\t\t\treturn str.slice(0, 4) + '...'\n\t\t}\n\t\treturn '...' + str.slice(-4)\n\t}\n\t// if the amount requested is in a \"logical\" amount - meaning that it can display the address\n\t// without repeating the same information twice - then go for it;\n\tif (position === 'center') {\n\t\treturn amount >= (str.length - 2) / 2\n\t\t\t? str.slice(0, half - 3) + '...' + str.slice(-(half - 3))\n\t\t\t: str.slice(0, amount) + '...' + str.slice(-amount)\n\t}\n\t// else, the user has been mistaskenly extreme, so just show the maximum possible amount\n\tif (amount >= str.length) {\n\t\tif (position === 'end') {\n\t\t\treturn str.slice(0, str.length - 3) + '...'\n\t\t}\n\t\treturn '...' + str.slice(-(str.length - 3))\n\t} else {\n\t\tif (position === 'end') {\n\t\t\treturn str.slice(0, amount) + '...'\n\t\t}\n\t\treturn '...' + str.slice(amount)\n\t}\n}\n\n/**\n * @name pageFromUri\n * @summary Use url variables to load the default components upon the first page visit.\n */\nexport const pageFromUri = (pathname: string, fallback: string) => {\n\tconst lastUriItem = pathname.substring(pathname.lastIndexOf('/') + 1)\n\tconst page = lastUriItem.trim() === '' ? fallback : lastUriItem\n\treturn page.trim()\n}\n\n/**\n * @name rmCommas\n * @summary Removes the commas from a string.\n */\nexport const rmCommas = (val: string): string => val.replace(/,/g, '')\n\n/**\n * @name rmDecimals\n * @summary Removes the decimal point and decimals from a string.\n */\nexport const rmDecimals = (str: string) => str.split('.')[0]\n\n/**\n * @name shuffle\n * @summary Shuffle a set of objects.\n */\nexport const shuffle = <T>(array: T[]) => {\n\tlet currentIndex = array.length\n\tlet randomIndex\n\twhile (currentIndex !== 0) {\n\t\trandomIndex = Math.floor(Math.random() * currentIndex)\n\t\tcurrentIndex--\n\t\t;[array[currentIndex], array[randomIndex]] = [\n\t\t\tarray[randomIndex],\n\t\t\tarray[currentIndex],\n\t\t]\n\t}\n\treturn array\n}\n\n/**\n * @name withTimeout\n * @summary Timeout a promise after a specified number of milliseconds.\n */\nexport const withTimeout = (\n\tms: number,\n\tpromise: Promise<unknown>,\n\toptions?: {\n\t\tonTimeout?: () => void\n\t},\n) => {\n\tconst timeout = new Promise((resolve) =>\n\t\tsetTimeout(async () => {\n\t\t\tif (typeof options?.onTimeout === 'function') {\n\t\t\t\toptions.onTimeout()\n\t\t\t}\n\t\t\tresolve(undefined)\n\t\t}, ms),\n\t)\n\treturn Promise.race([promise, timeout])\n}\n\n/**\n * @name withTimeoutThrow\n * @summary Timeout a promise after a specified number of milliseconds by throwing an error\n */\nexport const withTimeoutThrow = <T>(\n\tms: number,\n\tpromise: Promise<T>,\n\toptions?: {\n\t\tonTimeout?: () => void\n\t},\n) => {\n\tconst timeout = new Promise((reject) =>\n\t\tsetTimeout(async () => {\n\t\t\tif (typeof options?.onTimeout === 'function') {\n\t\t\t\toptions.onTimeout()\n\t\t\t}\n\t\t\treject('Function timeout')\n\t\t}, ms),\n\t)\n\treturn Promise.race([promise, timeout])\n}\n\n/**\n * @name appendOrEmpty\n * @summary Returns ` value` if a condition is truthy, or an empty string otherwise.\n */\nexport const appendOrEmpty = (\n\tcondition: boolean | string | undefined,\n\tvalue: string,\n) => (condition ? ` ${value}` : '')\n\n/**\n * @name appendOr\n * @summary Returns ` value` if condition is truthy, or ` fallback` otherwise.\n */\nexport const appendOr = (\n\tcondition: boolean | string | undefined,\n\tvalue: string,\n\tfallback: string,\n) => (condition ? ` ${value}` : ` ${fallback}`)\n\n/**\n * @name removeHexPrefix\n * @summary Takes a string str as input and returns a new string with the \"0x\" prefix removed if it\n * exists at the beginning of the input string.\n */\nexport const removeHexPrefix = (str: string): string => str.replace(/^0x/, '')\n\n// Check if 2 sets contain the same elements.\n// biome-ignore lint/suspicious/noExplicitAny: <>\nexport const eqSet = (xs: Set<any>, ys: Set<any>) =>\n\txs.size === ys.size && [...xs].every((x) => ys.has(x))\n\n// Check if one set contains all the elements of another set.\n// biome-ignore lint/suspicious/noExplicitAny: <>\nexport const isSuperset = (set: Set<any>, subset: Set<any>) => {\n\tfor (const elem of subset) {\n\t\tif (!set.has(elem)) {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\n/**\n * Finds the maximum value among a list of BigInt values.\n *\n * @function maxBigInt\n * @param {...bigint} values - A list of BigInt values to compare.\n * @returns {bigint} The largest BigInt value in the provided list.\n * @example\n * // Returns the maximum BigInt value\n * maxBigInt(10n, 50n, 30n, 100n, 20n); // 100n\n */\nexport const maxBigInt = (...values: bigint[]): bigint =>\n\tvalues.reduce((max, current) => (current > max ? current : max))\n\n/**\n * Finds the minimum value among a list of BigInt values.\n *\n * @function minBigInt\n * @param {...bigint} values - A list of BigInt values to compare.\n * @returns {bigint} The smallest BigInt value in the provided list.\n * @example\n * // Returns the minimum BigInt value\n * minBigInt(10n, 50n, 30n, 100n, 20n); // 10n\n */\nexport const minBigInt = (...values: bigint[]): bigint =>\n\tvalues.reduce((min, current) => (current < min ? current : min))\n","// /* @license Copyright 2024 w3ux authors & contributors\n// SPDX-License-Identifier: GPL-3.0-only */\n\n/**\n * Concatenates multiple Uint8Array instances into a single Uint8Array.\n *\n * @param {Uint8Array[]} u8as - An array of Uint8Array instances to concatenate.\n * @returns {Uint8Array} A new Uint8Array containing all the input arrays concatenated.\n */\nexport const u8aConcat = (...u8as: Uint8Array[]): Uint8Array => {\n\t// Calculate the total length of the resulting Uint8Array\n\tconst totalLength = u8as.reduce((sum, u8a) => sum + u8a.length, 0)\n\n\t// Create a new Uint8Array with the total length\n\tconst result = new Uint8Array(totalLength)\n\n\tlet offset = 0 // Initialize the offset for placing elements\n\tfor (const u8a of u8as) {\n\t\tresult.set(u8a, offset) // Set the current Uint8Array at the current offset\n\t\toffset += u8a.length // Update the offset for the next Uint8Array\n\t}\n\n\treturn result\n}\n","/* @license Copyright 2024 w3ux authors & contributors\nSPDX-License-Identifier: GPL-3.0-only */\n\nimport type { ForwardedRef, RefObject } from 'react'\n\n// Merge an external ref (callback or RefObject) with an internal ref so both stay in sync\nexport const mergeRefs = <T extends HTMLElement>(\n\tel: T | null,\n\tinternalRef: RefObject<HTMLElement | null>,\n\texternalRef: ForwardedRef<T>,\n): void => {\n\tinternalRef.current = el\n\tif (externalRef) {\n\t\tif (typeof externalRef === 'function') {\n\t\t\texternalRef(el)\n\t\t} else {\n\t\t\texternalRef.current = el\n\t\t}\n\t}\n}\n","/* @license Copyright 2024 w3ux authors & contributors\nSPDX-License-Identifier: GPL-3.0-only */\n\nimport type { RefObject } from 'react'\nimport { rmCommas, rmDecimals } from './base'\nimport type { AnyObject } from './types'\n\n/**\n * Converts an on-chain balance value from planck to a decimal value in token units.\n *\n * @function planckToUnit\n * @param {number | BigInt | string} val - The balance value in planck. Accepts a `number`, `BigInt`, or `string`.\n * @param {number} units - The number of decimal places in the token unit (10^units planck per 1 token).\n * @returns {string} The equivalent token unit value as a decimal string.\n * @example\n * // Convert 1500000000000 planck to tokens with 12 decimal places\n * planckToUnit(\"1500000000000\", 12); // returns \"1.5\"\n */\nexport const planckToUnit = (\n\tval: number | bigint | string,\n\tunits: number,\n): string => {\n\ttry {\n\t\t// Ensure `units` is a positive integer.\n\t\tunits = Math.max(Math.round(units), 0)\n\n\t\t// Convert `val` to BigInt based on its type\n\t\tconst bigIntVal =\n\t\t\ttypeof val === 'bigint'\n\t\t\t\t? val\n\t\t\t\t: BigInt(\n\t\t\t\t\t\ttypeof val === 'number'\n\t\t\t\t\t\t\t? Math.floor(val).toString()\n\t\t\t\t\t\t\t: rmDecimals(rmCommas(val)),\n\t\t\t\t\t)\n\n\t\tconst divisor = units === 0 ? 1n : BigInt(10) ** BigInt(units)\n\n\t\t// Integer division and remainder for the fractional part\n\t\tconst integerPart = bigIntVal / divisor\n\t\tconst fractionalPart = bigIntVal % divisor\n\n\t\t// Format fractional part with leading zeros to maintain `units` decimal places\n\t\tconst fractionalStr =\n\t\t\tunits > 0 ? `.${fractionalPart.toString().padStart(units, '0')}` : ``\n\n\t\t// Combine integer and fractional parts as a decimal string\n\t\treturn `${integerPart}${fractionalStr}`\n\t} catch {\n\t\treturn '0'\n\t}\n}\n\n/**\n * Converts a token unit value to an integer value in planck.\n *\n * @function unitToPlanck\n * @param {string | number | BigInt} val - The token unit value to convert. Accepts a string, number, or BigInt.\n * @param {number} units - The number of decimal places for conversion (10^units planck per 1 token).\n * @returns {BigInt} The equivalent value in planck as a BigInt.\n * @example\n * // Convert \"1.5\" tokens to planck with 12 decimal places\n * unitToPlanck(\"1.5\", 12); // returns BigInt(\"1500000000000\")\n */\nexport const unitToPlanck = (\n\tval: string | number | bigint,\n\tunits: number,\n): bigint => {\n\ttry {\n\t\t// Ensure `units` is a positive integer.\n\t\tunits = Math.max(Math.round(units), 0)\n\n\t\t// Convert `val` to a string; if empty or invalid, default to \"0\"\n\t\tconst strVal =\n\t\t\t(typeof val === 'string' ? rmCommas(val) : val.toString()) || '0'\n\n\t\t// Split into integer and fractional parts\n\t\tconst [integerPart, fractionalPart = ''] = strVal.split('.')\n\n\t\t// Process the integer part by converting to BigInt and scaling it to the given units\n\t\tlet bigIntValue = BigInt(integerPart) * BigInt(10) ** BigInt(units)\n\n\t\t// Process the fractional part if it exists\n\t\tif (fractionalPart) {\n\t\t\tlet fractionalValue: bigint\n\n\t\t\tif (fractionalPart.length > units) {\n\t\t\t\t// If fractional part exceeds units, truncate it\n\t\t\t\tfractionalValue = BigInt(fractionalPart.slice(0, units))\n\t\t\t} else {\n\t\t\t\t// Otherwise, pad the fractional part to match units\n\t\t\t\tfractionalValue = BigInt(fractionalPart.padEnd(units, '0'))\n\t\t\t}\n\n\t\t\tbigIntValue += fractionalValue\n\t\t}\n\n\t\treturn bigIntValue\n\t} catch {\n\t\treturn BigInt(0)\n\t}\n}\n\n/**\n * @name remToUnit\n * @summary Converts a rem string to a number.\n */\nexport const remToUnit = (rem: string) =>\n\tNumber(rem.slice(0, rem.length - 3)) *\n\tparseFloat(getComputedStyle(document.documentElement).fontSize)\n\n/**\n * @name capitalizeFirstLetter\n * @summary Capitalize the first letter of a string.\n */\nexport const capitalizeFirstLetter = (string: string) =>\n\tstring.charAt(0).toUpperCase() + string.slice(1)\n\n/**\n * @name snakeToCamel\n * @summary converts a string from snake / kebab-case to camel-case.\n */\nexport const snakeToCamel = (str: string) =>\n\tstr\n\t\t.toLowerCase()\n\t\t.replace(/([-_][a-z])/g, (group) =>\n\t\t\tgroup.toUpperCase().replace('-', '').replace('_', ''),\n\t\t)\n\n/**\n * @name setStateWithRef\n * @summary Synchronize React state and its reference with the provided value.\n */\nexport const setStateWithRef = <T>(\n\tvalue: T,\n\tsetState: (_state: T) => void,\n\tref: RefObject<T>,\n): void => {\n\tsetState(value)\n\tref.current = value\n}\n\n/**\n * @name localStorageOrDefault\n * @summary Retrieve the local stroage value with the key, return defult value if it is not\n * found.\n */\nexport const localStorageOrDefault = <T>(\n\tkey: string,\n\t_default: T,\n\tparse = false,\n): T | string => {\n\tconst val: string | null = localStorage.getItem(key)\n\n\tif (val === null) {\n\t\treturn _default\n\t}\n\n\tif (parse) {\n\t\treturn JSON.parse(val) as T\n\t}\n\treturn val\n}\n\n/**\n * @name extractUrlValue\n * @summary Extracts a URL value from a URL string.\n */\nexport const extractUrlValue = (key: string, url?: string) => {\n\tif (typeof url === 'undefined') {\n\t\turl = window.location.href\n\t}\n\tconst match = url.match(`[?&]${key}=([^&]+)`)\n\treturn match ? match[1] : null\n}\n\n/**\n * @name varToUrlHash\n * @summary Puts a variable into the URL hash as a param.\n * @description\n * Since url variables are added to the hash and are not treated as URL params, the params are split\n * and parsed into a `URLSearchParams`.\n */\nexport const varToUrlHash = (\n\tkey: string,\n\tval: string,\n\taddIfMissing: boolean,\n) => {\n\tconst hash = window.location.hash\n\tconst [page, params] = hash.split('?')\n\tconst searchParams = new URLSearchParams(params)\n\n\tif (searchParams.get(key) === null && !addIfMissing) {\n\t\treturn\n\t}\n\tsearchParams.set(key, val)\n\twindow.location.hash = `${page}?${searchParams.toString()}`\n}\n\n/**\n * @name removeVarFromUrlHash\n * @summary\n * Removes a variable `key` from the URL hash if it exists. Removes dangling `?` if no URL variables\n * exist.\n */\nexport const removeVarFromUrlHash = (key: string) => {\n\tconst hash = window.location.hash\n\tconst [page, params] = hash.split('?')\n\tconst searchParams = new URLSearchParams(params)\n\tif (searchParams.get(key) === null) {\n\t\treturn\n\t}\n\tsearchParams.delete(key)\n\tconst paramsAsStr = searchParams.toString()\n\twindow.location.hash = `${page}${paramsAsStr ? `?${paramsAsStr}` : ``}`\n}\n\n/**\n * @name sortWithNull\n * @summary Sorts an array with nulls last.\n */\nexport const sortWithNull =\n\t(ascending: boolean) => (a: unknown, b: unknown) => {\n\t\t// if both items are undefined, treat them as equal\n\t\tif (typeof a === 'undefined' && typeof b === 'undefined') {\n\t\t\treturn 0\n\t\t}\n\t\t// if either item is undefined, sort it last\n\t\tif (typeof a === 'undefined' || typeof b === 'undefined') {\n\t\t\treturn typeof a === 'undefined' ? 1 : -1\n\t\t}\n\t\t// equal items sort equally\n\t\tif (a === b) {\n\t\t\treturn 0\n\t\t}\n\t\t// nulls sort after anything else\n\t\tif (a === null) {\n\t\t\treturn 1\n\t\t}\n\t\tif (b === null) {\n\t\t\treturn -1\n\t\t}\n\t\t// otherwise, if we're ascending, lowest sorts first\n\t\tif (ascending) {\n\t\t\treturn a < b ? -1 : 1\n\t\t}\n\t\t// if descending, highest sorts first\n\t\treturn a < b ? 1 : -1\n\t}\n\n/**\n * @name applyWidthAsPadding\n * @summary Applies width of subject to paddingRight of container.\n */\nexport const applyWidthAsPadding = (\n\tsubjectRef: RefObject<HTMLDivElement | null>,\n\tcontainerRef: RefObject<HTMLDivElement | null>,\n) => {\n\tif (containerRef.current && subjectRef.current) {\n\t\tcontainerRef.current.style.paddingRight = `${\n\t\t\tsubjectRef.current.offsetWidth + remToUnit('1rem')\n\t\t}px`\n\t}\n}\n\n/**\n * @name unescape\n * @summary Replaces \\” with “\n */\nexport const unescape = (val: string) => val.replace(/\\\\\"/g, '\"')\n\n/**\n * @name inChrome\n * @summary Whether the application is rendering in Chrome.\n */\nexport const inChrome = () => {\n\tconst isChromium = (window as Window & { chrome?: boolean })?.chrome || null\n\tconst winNav = (window as Window)?.navigator || null\n\tconst isOpera =\n\t\ttypeof (window as Window & { opr?: boolean })?.opr !== 'undefined'\n\tconst isIEedge = winNav?.userAgent.indexOf('Edg') > -1 || false\n\tconst isIOSChrome = winNav?.userAgent.match('CriOS') || false\n\n\tif (isIOSChrome) {\n\t\treturn true\n\t}\n\tif (\n\t\tisChromium !== null &&\n\t\ttypeof isChromium !== 'undefined' &&\n\t\tisOpera === false &&\n\t\tisIEedge === false\n\t) {\n\t\treturn true\n\t}\n\treturn false\n}\n\n/**\n * @name addedTo\n * @summary Given 2 objects and some keys, return items in the fresh object that do not exist in the\n * stale object by matching the given common key values of both objects.\n */\nexport const addedTo = (\n\tfresh: AnyObject[],\n\tstale: AnyObject[],\n\tkeys: string[],\n): AnyObject[] =>\n\ttypeof fresh !== 'object' || typeof stale !== 'object' || !keys.length\n\t\t? []\n\t\t: fresh.filter(\n\t\t\t\t(freshItem) =>\n\t\t\t\t\t!stale.find((staleItem) =>\n\t\t\t\t\t\tkeys.every((key) =>\n\t\t\t\t\t\t\t!(key in staleItem) || !(key in freshItem)\n\t\t\t\t\t\t\t\t? false\n\t\t\t\t\t\t\t\t: staleItem[key] === freshItem[key],\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t)\n\n/**\n * @name removedFrom\n * @summary Given 2 objects and some keys, return items in the stale object that do not exist in the\n * fresh object by matching the given common key values of both objects.\n */\nexport const removedFrom = (\n\tfresh: AnyObject[],\n\tstale: AnyObject[],\n\tkeys: string[],\n): AnyObject[] =>\n\ttypeof fresh !== 'object' || typeof stale !== 'object' || !keys.length\n\t\t? []\n\t\t: stale.filter(\n\t\t\t\t(staleItem) =>\n\t\t\t\t\t!fresh.find((freshItem) =>\n\t\t\t\t\t\tkeys.every((key) =>\n\t\t\t\t\t\t\t!(key in staleItem) || !(key in freshItem)\n\t\t\t\t\t\t\t\t? false\n\t\t\t\t\t\t\t\t: freshItem[key] === staleItem[key],\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t)\n\n/**\n * @name matchedProperties\n * @summary Given 2 objects and some keys, return items in object 1 that also exist in object 2 by\n * matching the given common key values of both objects.\n */\nexport const matchedProperties = (\n\tobjX: AnyObject[],\n\tobjY: AnyObject[],\n\tkeys: string[],\n): AnyObject[] =>\n\ttypeof objX !== 'object' || typeof objY !== 'object' || !keys.length\n\t\t? []\n\t\t: objY.filter((x) =>\n\t\t\t\tobjX.find((y) =>\n\t\t\t\t\tkeys.every((key) =>\n\t\t\t\t\t\t!(key in x) || !(key in y) ? false : y[key] === x[key],\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t)\n\n/**\n * @name isValidHttpUrl\n * @summary Give a string, return whether it is a valid http URL.\n * @param string - The string to check.\n */\nexport const isValidHttpUrl = (string: string) => {\n\tlet url: URL\n\ttry {\n\t\turl = new URL(string)\n\t} catch (_) {\n\t\treturn false\n\t}\n\treturn url.protocol === 'http:' || url.protocol === 'https:'\n}\n\n/**\n * @name makeCancelable\n * @summary Makes a promise cancellable.\n * @param promise - The promise to make cancellable.\n */\nexport const makeCancelable = (promise: Promise<AnyObject>) => {\n\tlet hasCanceled = false\n\n\tconst wrappedPromise = new Promise((resolve, reject) => {\n\t\tpromise.then((val) =>\n\t\t\thasCanceled ? reject(Error('Cancelled')) : resolve(val),\n\t\t)\n\t\tpromise.catch((error) =>\n\t\t\thasCanceled ? reject(Error('Cancelled')) : reject(error),\n\t\t)\n\t})\n\n\treturn {\n\t\tpromise: wrappedPromise,\n\t\tcancel: () => {\n\t\t\thasCanceled = true\n\t\t},\n\t}\n}\n\n/**\n * @name unimplemented\n * @summary A placeholder function to signal a deliberate unimplementation.\n * Consumes an arbitrary number of props.\n */\nexport const unimplemented = (_props?: unknown) => {\n\t/* unimplemented */\n}\n\n/**\n * Deep merge two objects.\n * @param target\n * @param ...sources\n */\n\nexport const mergeDeep = (\n\ttarget: AnyObject,\n\t...sources: AnyObject[]\n): AnyObject => {\n\tif (!sources.length) {\n\t\treturn target\n\t}\n\n\tconst isObject = (item: AnyObject) =>\n\t\titem && typeof item === 'object' && !Array.isArray(item)\n\tconst source = sources.shift()\n\n\tif (isObject(target) && isObject(source)) {\n\t\tfor (const key in source) {\n\t\t\tif (isObject(source[key])) {\n\t\t\t\tif (!target[key]) {\n\t\t\t\t\tObject.assign(target, { [key]: {} })\n\t\t\t\t}\n\t\t\t\tmergeDeep(target[key], source[key])\n\t\t\t} else {\n\t\t\t\tObject.assign(target, { [key]: source[key] })\n\t\t\t}\n\t\t}\n\t}\n\treturn mergeDeep(target, ...sources)\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACqBO,IAAM,mBAAmB,CAC/B,KACA,gBACY;AACZ,MAAI;AAEH,UAAM,eAAe,OAAO,QAAQ,YAAY,IAAI,SAAS,GAAG;AAGhE,UAAM,SACL,OAAO,QAAQ,WAAW,IAAI,QAAQ,MAAM,EAAE,IAAI,IAAI,SAAS;AAGhE,UAAM,CAAC,aAAa,iBAAiB,EAAE,IAAI,OAAO,MAAM,GAAG;AAG3D,UAAM,QAAQ,OAAO,eAAe,GAAG;AAGvC,UAAM,kBAAkB,cAAc,eAAe;AAGrD,UAAM,iBAAiB,eACpB,KAAK,aAAa,OAAO,EAAE,OAAO,KAAK,IACvC,MAAM,SAAS;AAGlB,WAAO,kBAAkB,IACtB,GAAG,cAAc,IAAI,cAAc,GAAG,IAAI,OAAO,eAAe,CAAC,KACjE,GAAG,cAAc,IAAI,cAAc;AAAA,EACvC,QAAQ;AAEP,WAAO;AAAA,EACR;AACD;AAMO,IAAM,WAAW,CAAC,QAAgB;AACxC,QAAM,kBAAkB,CAAC,WAAmB;AAC3C,QAAI,QAAQ;AACX,UAAI,OAAO,WAAW,UAAU;AAC/B,eAAO;AAAA,MACR;AACA,aAAO,OAAO,MAAM;AAAA,IACrB;AACA,WAAO;AAAA,EACR;AAEA,QAAM,UAAU,CAAC,QAChB,gBAAgB,GAAG,EAAE;AAAA,IACpB;AAAA,EACD;AAED,QAAM,kBAAkB,CAAC,QAAkB;AAC1C,QAAI,SAAS;AACb,aAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACrC,YAAM,aAAa,IAAI,CAAC;AACxB,UAAI,SAAS,WAAW,YAAY;AACpC,UAAI,MAAM,GAAG;AACZ,iBACC,OAAO,MAAM,GAAG,CAAC,EAAE,YAAY,IAAI,OAAO,MAAM,GAAG,OAAO,MAAM;AAAA,MAClE;AACA,gBAAU;AAAA,IACX;AACA,WAAO;AAAA,EACR;AAEA,QAAM,IAAI,QAAQ,GAAG,GAAG,IAAI,CAAC,MAAM,EAAE,YAAY,CAAC;AAClD,SAAO,gBAAgB,KAAK,CAAC,CAAC;AAC/B;AAUO,IAAM,aAAa,CACzB,KACA,SAAS,GACT,WAAuC,aACnC;AACJ,QAAM,OAAO,IAAI,SAAS;AAG1B,MAAI,UAAU,GAAG;AAChB,QAAI,aAAa,UAAU;AAC1B,aAAO,IAAI,MAAM,GAAG,CAAC,IAAI,QAAQ,IAAI,MAAM,EAAE;AAAA,IAC9C;AACA,QAAI,aAAa,OAAO;AACvB,aAAO,IAAI,MAAM,GAAG,CAAC,IAAI;AAAA,IAC1B;AACA,WAAO,QAAQ,IAAI,MAAM,EAAE;AAAA,EAC5B;AAGA,MAAI,aAAa,UAAU;AAC1B,WAAO,WAAW,IAAI,SAAS,KAAK,IACjC,IAAI,MAAM,GAAG,OAAO,CAAC,IAAI,QAAQ,IAAI,MAAM,EAAE,OAAO,EAAE,IACtD,IAAI,MAAM,GAAG,MAAM,IAAI,QAAQ,IAAI,MAAM,CAAC,MAAM;AAAA,EACpD;AAEA,MAAI,UAAU,IAAI,QAAQ;AACzB,QAAI,aAAa,OAAO;AACvB,aAAO,IAAI,MAAM,GAAG,IAAI,SAAS,CAAC,IAAI;AAAA,IACvC;AACA,WAAO,QAAQ,IAAI,MAAM,EAAE,IAAI,SAAS,EAAE;AAAA,EAC3C,OAAO;AACN,QAAI,aAAa,OAAO;AACvB,aAAO,IAAI,MAAM,GAAG,MAAM,IAAI;AAAA,IAC/B;AACA,WAAO,QAAQ,IAAI,MAAM,MAAM;AAAA,EAChC;AACD;AAMO,IAAM,cAAc,CAAC,UAAkB,aAAqB;AAClE,QAAM,cAAc,SAAS,UAAU,SAAS,YAAY,GAAG,IAAI,CAAC;AACpE,QAAM,OAAO,YAAY,KAAK,MAAM,KAAK,WAAW;AACpD,SAAO,KAAK,KAAK;AAClB;AAMO,IAAM,WAAW,CAAC,QAAwB,IAAI,QAAQ,MAAM,EAAE;AAM9D,IAAM,aAAa,CAAC,QAAgB,IAAI,MAAM,GAAG,EAAE,CAAC;AAMpD,IAAM,UAAU,CAAI,UAAe;AACzC,MAAI,eAAe,MAAM;AACzB,MAAI;AACJ,SAAO,iBAAiB,GAAG;AAC1B,kBAAc,KAAK,MAAM,KAAK,OAAO,IAAI,YAAY;AACrD;AACC,KAAC,MAAM,YAAY,GAAG,MAAM,WAAW,CAAC,IAAI;AAAA,MAC5C,MAAM,WAAW;AAAA,MACjB,MAAM,YAAY;AAAA,IACnB;AAAA,EACD;AACA,SAAO;AACR;AAMO,IAAM,cAAc,CAC1B,IACA,SACA,YAGI;AACJ,QAAM,UAAU,IAAI;AAAA,IAAQ,CAAC,YAC5B,WAAW,YAAY;AACtB,UAAI,OAAO,SAAS,cAAc,YAAY;AAC7C,gBAAQ,UAAU;AAAA,MACnB;AACA,cAAQ,MAAS;AAAA,IAClB,GAAG,EAAE;AAAA,EACN;AACA,SAAO,QAAQ,KAAK,CAAC,SAAS,OAAO,CAAC;AACvC;AAMO,IAAM,mBAAmB,CAC/B,IACA,SACA,YAGI;AACJ,QAAM,UAAU,IAAI;AAAA,IAAQ,CAAC,WAC5B,WAAW,YAAY;AACtB,UAAI,OAAO,SAAS,cAAc,YAAY;AAC7C,gBAAQ,UAAU;AAAA,MACnB;AACA,aAAO,kBAAkB;AAAA,IAC1B,GAAG,EAAE;AAAA,EACN;AACA,SAAO,QAAQ,KAAK,CAAC,SAAS,OAAO,CAAC;AACvC;AAMO,IAAM,gBAAgB,CAC5B,WACA,UACK,YAAY,IAAI,KAAK,KAAK;AAMzB,IAAM,WAAW,CACvB,WACA,OACA,aACK,YAAY,IAAI,KAAK,KAAK,IAAI,QAAQ;AAOrC,IAAM,kBAAkB,CAAC,QAAwB,IAAI,QAAQ,OAAO,EAAE;AAItE,IAAM,QAAQ,CAAC,IAAc,OACnC,GAAG,SAAS,GAAG,QAAQ,CAAC,GAAG,EAAE,EAAE,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;AAI/C,IAAM,aAAa,CAAC,KAAe,WAAqB;AAC9D,aAAW,QAAQ,QAAQ;AAC1B,QAAI,CAAC,IAAI,IAAI,IAAI,GAAG;AACnB,aAAO;AAAA,IACR;AAAA,EACD;AACA,SAAO;AACR;AAYO,IAAM,YAAY,IAAI,WAC5B,OAAO,OAAO,CAAC,KAAK,YAAa,UAAU,MAAM,UAAU,GAAI;AAYzD,IAAM,YAAY,IAAI,WAC5B,OAAO,OAAO,CAAC,KAAK,YAAa,UAAU,MAAM,UAAU,GAAI;;;AC1RzD,IAAM,YAAY,IAAI,SAAmC;AAE/D,QAAM,cAAc,KAAK,OAAO,CAAC,KAAK,QAAQ,MAAM,IAAI,QAAQ,CAAC;AAGjE,QAAM,SAAS,IAAI,WAAW,WAAW;AAEzC,MAAI,SAAS;AACb,aAAW,OAAO,MAAM;AACvB,WAAO,IAAI,KAAK,MAAM;AACtB,cAAU,IAAI;AAAA,EACf;AAEA,SAAO;AACR;;;ACjBO,IAAM,YAAY,CACxB,IACA,aACA,gBACU;AACV,cAAY,UAAU;AACtB,MAAI,aAAa;AAChB,QAAI,OAAO,gBAAgB,YAAY;AACtC,kBAAY,EAAE;AAAA,IACf,OAAO;AACN,kBAAY,UAAU;AAAA,IACvB;AAAA,EACD;AACD;;;ACDO,IAAM,eAAe,CAC3B,KACA,UACY;AACZ,MAAI;AAEH,YAAQ,KAAK,IAAI,KAAK,MAAM,KAAK,GAAG,CAAC;AAGrC,UAAM,YACL,OAAO,QAAQ,WACZ,MACA;AAAA,MACA,OAAO,QAAQ,WACZ,KAAK,MAAM,GAAG,EAAE,SAAS,IACzB,WAAW,SAAS,GAAG,CAAC;AAAA,IAC5B;AAEH,UAAM,UAAU,UAAU,IAAI,KAAK,OAAO,EAAE,KAAK,OAAO,KAAK;AAG7D,UAAM,cAAc,YAAY;AAChC,UAAM,iBAAiB,YAAY;AAGnC,UAAM,gBACL,QAAQ,IAAI,IAAI,eAAe,SAAS,EAAE,SAAS,OAAO,GAAG,CAAC,KAAK;AAGpE,WAAO,GAAG,WAAW,GAAG,aAAa;AAAA,EACtC,QAAQ;AACP,WAAO;AAAA,EACR;AACD;AAaO,IAAM,eAAe,CAC3B,KACA,UACY;AACZ,MAAI;AAEH,YAAQ,KAAK,IAAI,KAAK,MAAM,KAAK,GAAG,CAAC;AAGrC,UAAM,UACJ,OAAO,QAAQ,WAAW,SAAS,GAAG,IAAI,IAAI,SAAS,MAAM;AAG/D,UAAM,CAAC,aAAa,iBAAiB,EAAE,IAAI,OAAO,MAAM,GAAG;AAG3D,QAAI,cAAc,OAAO,WAAW,IAAI,OAAO,EAAE,KAAK,OAAO,KAAK;AAGlE,QAAI,gBAAgB;AACnB,UAAI;AAEJ,UAAI,eAAe,SAAS,OAAO;AAElC,0BAAkB,OAAO,eAAe,MAAM,GAAG,KAAK,CAAC;AAAA,MACxD,OAAO;AAEN,0BAAkB,OAAO,eAAe,OAAO,OAAO,GAAG,CAAC;AAAA,MAC3D;AAEA,qBAAe;AAAA,IAChB;AAEA,WAAO;AAAA,EACR,QAAQ;AACP,WAAO,OAAO,CAAC;AAAA,EAChB;AACD;AAMO,IAAM,YAAY,CAAC,QACzB,OAAO,IAAI,MAAM,GAAG,IAAI,SAAS,CAAC,CAAC,IACnC,WAAW,iBAAiB,SAAS,eAAe,EAAE,QAAQ;AAMxD,IAAM,wBAAwB,CAAC,WACrC,OAAO,OAAO,CAAC,EAAE,YAAY,IAAI,OAAO,MAAM,CAAC;AAMzC,IAAM,eAAe,CAAC,QAC5B,IACE,YAAY,EACZ;AAAA,EAAQ;AAAA,EAAgB,CAAC,UACzB,MAAM,YAAY,EAAE,QAAQ,KAAK,EAAE,EAAE,QAAQ,KAAK,EAAE;AACrD;AAMK,IAAM,kBAAkB,CAC9B,OACA,UACA,QACU;AACV,WAAS,KAAK;AACd,MAAI,UAAU;AACf;AAOO,IAAM,wBAAwB,CACpC,KACA,UACA,QAAQ,UACQ;AAChB,QAAM,MAAqB,aAAa,QAAQ,GAAG;AAEnD,MAAI,QAAQ,MAAM;AACjB,WAAO;AAAA,EACR;AAEA,MAAI,OAAO;AACV,WAAO,KAAK,MAAM,GAAG;AAAA,EACtB;AACA,SAAO;AACR;AAMO,IAAM,kBAAkB,CAAC,KAAa,QAAiB;AAC7D,MAAI,OAAO,QAAQ,aAAa;AAC/B,UAAM,OAAO,SAAS;AAAA,EACvB;AACA,QAAM,QAAQ,IAAI,MAAM,OAAO,GAAG,UAAU;AAC5C,SAAO,QAAQ,MAAM,CAAC,IAAI;AAC3B;AASO,IAAM,eAAe,CAC3B,KACA,KACA,iBACI;AACJ,QAAM,OAAO,OAAO,SAAS;AAC7B,QAAM,CAAC,MAAM,MAAM,IAAI,KAAK,MAAM,GAAG;AACrC,QAAM,eAAe,IAAI,gBAAgB,MAAM;AAE/C,MAAI,aAAa,IAAI,GAAG,MAAM,QAAQ,CAAC,cAAc;AACpD;AAAA,EACD;AACA,eAAa,IAAI,KAAK,GAAG;AACzB,SAAO,SAAS,OAAO,GAAG,IAAI,IAAI,aAAa,SAAS,CAAC;AAC1D;AAQO,IAAM,uBAAuB,CAAC,QAAgB;AACpD,QAAM,OAAO,OAAO,SAAS;AAC7B,QAAM,CAAC,MAAM,MAAM,IAAI,KAAK,MAAM,GAAG;AACrC,QAAM,eAAe,IAAI,gBAAgB,MAAM;AAC/C,MAAI,aAAa,IAAI,GAAG,MAAM,MAAM;AACnC;AAAA,EACD;AACA,eAAa,OAAO,GAAG;AACvB,QAAM,cAAc,aAAa,SAAS;AAC1C,SAAO,SAAS,OAAO,GAAG,IAAI,GAAG,cAAc,IAAI,WAAW,KAAK,EAAE;AACtE;AAMO,IAAM,eACZ,CAAC,cAAuB,CAAC,GAAY,MAAe;AAEnD,MAAI,OAAO,MAAM,eAAe,OAAO,MAAM,aAAa;AACzD,WAAO;AAAA,EACR;AAEA,MAAI,OAAO,MAAM,eAAe,OAAO,MAAM,aAAa;AACzD,WAAO,OAAO,MAAM,cAAc,IAAI;AAAA,EACvC;AAEA,MAAI,MAAM,GAAG;AACZ,WAAO;AAAA,EACR;AAEA,MAAI,MAAM,MAAM;AACf,WAAO;AAAA,EACR;AACA,MAAI,MAAM,MAAM;AACf,WAAO;AAAA,EACR;AAEA,MAAI,WAAW;AACd,WAAO,IAAI,IAAI,KAAK;AAAA,EACrB;AAEA,SAAO,IAAI,IAAI,IAAI;AACpB;AAMM,IAAM,sBAAsB,CAClC,YACA,iBACI;AACJ,MAAI,aAAa,WAAW,WAAW,SAAS;AAC/C,iBAAa,QAAQ,MAAM,eAAe,GACzC,WAAW,QAAQ,cAAc,UAAU,MAAM,CAClD;AAAA,EACD;AACD;AAMO,IAAM,WAAW,CAAC,QAAgB,IAAI,QAAQ,QAAQ,GAAG;AAMzD,IAAM,WAAW,MAAM;AAC7B,QAAM,aAAc,QAA0C,UAAU;AACxE,QAAM,SAAU,QAAmB,aAAa;AAChD,QAAM,UACL,OAAQ,QAAuC,QAAQ;AACxD,QAAM,WAAW,QAAQ,UAAU,QAAQ,KAAK,IAAI,MAAM;AAC1D,QAAM,cAAc,QAAQ,UAAU,MAAM,OAAO,KAAK;AAExD,MAAI,aAAa;AAChB,WAAO;AAAA,EACR;AACA,MACC,eAAe,QACf,OAAO,eAAe,eACtB,YAAY,SACZ,aAAa,OACZ;AACD,WAAO;AAAA,EACR;AACA,SAAO;AACR;AAOO,IAAM,UAAU,CACtB,OACA,OACA,SAEA,OAAO,UAAU,YAAY,OAAO,UAAU,YAAY,CAAC,KAAK,SAC7D,CAAC,IACD,MAAM;AAAA,EACN,CAAC,cACA,CAAC,MAAM;AAAA,IAAK,CAAC,cACZ,KAAK;AAAA,MAAM,CAAC,QACX,EAAE,OAAO,cAAc,EAAE,OAAO,aAC7B,QACA,UAAU,GAAG,MAAM,UAAU,GAAG;AAAA,IACpC;AAAA,EACD;AACF;AAOI,IAAM,cAAc,CAC1B,OACA,OACA,SAEA,OAAO,UAAU,YAAY,OAAO,UAAU,YAAY,CAAC,KAAK,SAC7D,CAAC,IACD,MAAM;AAAA,EACN,CAAC,cACA,CAAC,MAAM;AAAA,IAAK,CAAC,cACZ,KAAK;AAAA,MAAM,CAAC,QACX,EAAE,OAAO,cAAc,EAAE,OAAO,aAC7B,QACA,UAAU,GAAG,MAAM,UAAU,GAAG;AAAA,IACpC;AAAA,EACD;AACF;AAOI,IAAM,oBAAoB,CAChC,MACA,MACA,SAEA,OAAO,SAAS,YAAY,OAAO,SAAS,YAAY,CAAC,KAAK,SAC3D,CAAC,IACD,KAAK;AAAA,EAAO,CAAC,MACb,KAAK;AAAA,IAAK,CAAC,MACV,KAAK;AAAA,MAAM,CAAC,QACX,EAAE,OAAO,MAAM,EAAE,OAAO,KAAK,QAAQ,EAAE,GAAG,MAAM,EAAE,GAAG;AAAA,IACtD;AAAA,EACD;AACD;AAOI,IAAM,iBAAiB,CAAC,WAAmB;AACjD,MAAI;AACJ,MAAI;AACH,UAAM,IAAI,IAAI,MAAM;AAAA,EACrB,SAAS,GAAG;AACX,WAAO;AAAA,EACR;AACA,SAAO,IAAI,aAAa,WAAW,IAAI,aAAa;AACrD;AAOO,IAAM,iBAAiB,CAAC,YAAgC;AAC9D,MAAI,cAAc;AAElB,QAAM,iBAAiB,IAAI,QAAQ,CAAC,SAAS,WAAW;AACvD,YAAQ;AAAA,MAAK,CAAC,QACb,cAAc,OAAO,MAAM,WAAW,CAAC,IAAI,QAAQ,GAAG;AAAA,IACvD;AACA,YAAQ;AAAA,MAAM,CAAC,UACd,cAAc,OAAO,MAAM,WAAW,CAAC,IAAI,OAAO,KAAK;AAAA,IACxD;AAAA,EACD,CAAC;AAED,SAAO;AAAA,IACN,SAAS;AAAA,IACT,QAAQ,MAAM;AACb,oBAAc;AAAA,IACf;AAAA,EACD;AACD;AAOO,IAAM,gBAAgB,CAAC,WAAqB;AAEnD;AAQO,IAAM,YAAY,CACxB,WACG,YACY;AACf,MAAI,CAAC,QAAQ,QAAQ;AACpB,WAAO;AAAA,EACR;AAEA,QAAM,WAAW,CAAC,SACjB,QAAQ,OAAO,SAAS,YAAY,CAAC,MAAM,QAAQ,IAAI;AACxD,QAAM,SAAS,QAAQ,MAAM;AAE7B,MAAI,SAAS,MAAM,KAAK,SAAS,MAAM,GAAG;AACzC,eAAW,OAAO,QAAQ;AACzB,UAAI,SAAS,OAAO,GAAG,CAAC,GAAG;AAC1B,YAAI,CAAC,OAAO,GAAG,GAAG;AACjB,iBAAO,OAAO,QAAQ,EAAE,CAAC,GAAG,GAAG,CAAC,EAAE,CAAC;AAAA,QACpC;AACA,kBAAU,OAAO,GAAG,GAAG,OAAO,GAAG,CAAC;AAAA,MACnC,OAAO;AACN,eAAO,OAAO,QAAQ,EAAE,CAAC,GAAG,GAAG,OAAO,GAAG,EAAE,CAAC;AAAA,MAC7C;AAAA,IACD;AAAA,EACD;AACA,SAAO,UAAU,QAAQ,GAAG,OAAO;AACpC;","names":[]}
|
package/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { RefObject } from 'react';
|
|
1
|
+
import { RefObject, ForwardedRef } from 'react';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Ensures a number has at least the specified number of decimal places, retaining commas in the output if they are present in the input.
|
|
@@ -116,6 +116,8 @@ declare const minBigInt: (...values: bigint[]) => bigint;
|
|
|
116
116
|
*/
|
|
117
117
|
declare const u8aConcat: (...u8as: Uint8Array[]) => Uint8Array;
|
|
118
118
|
|
|
119
|
+
declare const mergeRefs: <T extends HTMLElement>(el: T | null, internalRef: RefObject<HTMLElement | null>, externalRef: ForwardedRef<T>) => void;
|
|
120
|
+
|
|
119
121
|
type AnyObject = any;
|
|
120
122
|
|
|
121
123
|
/**
|
|
@@ -254,4 +256,4 @@ declare const unimplemented: (_props?: unknown) => void;
|
|
|
254
256
|
*/
|
|
255
257
|
declare const mergeDeep: (target: AnyObject, ...sources: AnyObject[]) => AnyObject;
|
|
256
258
|
|
|
257
|
-
export { addedTo, appendOr, appendOrEmpty, applyWidthAsPadding, camelize, capitalizeFirstLetter, ellipsisFn, eqSet, extractUrlValue, inChrome, isSuperset, isValidHttpUrl, localStorageOrDefault, makeCancelable, matchedProperties, maxBigInt, mergeDeep, minBigInt, minDecimalPlaces, pageFromUri, planckToUnit, remToUnit, removeHexPrefix, removeVarFromUrlHash, removedFrom, rmCommas, rmDecimals, setStateWithRef, shuffle, snakeToCamel, sortWithNull, u8aConcat, unescape, unimplemented, unitToPlanck, varToUrlHash, withTimeout, withTimeoutThrow };
|
|
259
|
+
export { addedTo, appendOr, appendOrEmpty, applyWidthAsPadding, camelize, capitalizeFirstLetter, ellipsisFn, eqSet, extractUrlValue, inChrome, isSuperset, isValidHttpUrl, localStorageOrDefault, makeCancelable, matchedProperties, maxBigInt, mergeDeep, mergeRefs, minBigInt, minDecimalPlaces, pageFromUri, planckToUnit, remToUnit, removeHexPrefix, removeVarFromUrlHash, removedFrom, rmCommas, rmDecimals, setStateWithRef, shuffle, snakeToCamel, sortWithNull, u8aConcat, unescape, unimplemented, unitToPlanck, varToUrlHash, withTimeout, withTimeoutThrow };
|
package/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { RefObject } from 'react';
|
|
1
|
+
import { RefObject, ForwardedRef } from 'react';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Ensures a number has at least the specified number of decimal places, retaining commas in the output if they are present in the input.
|
|
@@ -116,6 +116,8 @@ declare const minBigInt: (...values: bigint[]) => bigint;
|
|
|
116
116
|
*/
|
|
117
117
|
declare const u8aConcat: (...u8as: Uint8Array[]) => Uint8Array;
|
|
118
118
|
|
|
119
|
+
declare const mergeRefs: <T extends HTMLElement>(el: T | null, internalRef: RefObject<HTMLElement | null>, externalRef: ForwardedRef<T>) => void;
|
|
120
|
+
|
|
119
121
|
type AnyObject = any;
|
|
120
122
|
|
|
121
123
|
/**
|
|
@@ -254,4 +256,4 @@ declare const unimplemented: (_props?: unknown) => void;
|
|
|
254
256
|
*/
|
|
255
257
|
declare const mergeDeep: (target: AnyObject, ...sources: AnyObject[]) => AnyObject;
|
|
256
258
|
|
|
257
|
-
export { addedTo, appendOr, appendOrEmpty, applyWidthAsPadding, camelize, capitalizeFirstLetter, ellipsisFn, eqSet, extractUrlValue, inChrome, isSuperset, isValidHttpUrl, localStorageOrDefault, makeCancelable, matchedProperties, maxBigInt, mergeDeep, minBigInt, minDecimalPlaces, pageFromUri, planckToUnit, remToUnit, removeHexPrefix, removeVarFromUrlHash, removedFrom, rmCommas, rmDecimals, setStateWithRef, shuffle, snakeToCamel, sortWithNull, u8aConcat, unescape, unimplemented, unitToPlanck, varToUrlHash, withTimeout, withTimeoutThrow };
|
|
259
|
+
export { addedTo, appendOr, appendOrEmpty, applyWidthAsPadding, camelize, capitalizeFirstLetter, ellipsisFn, eqSet, extractUrlValue, inChrome, isSuperset, isValidHttpUrl, localStorageOrDefault, makeCancelable, matchedProperties, maxBigInt, mergeDeep, mergeRefs, minBigInt, minDecimalPlaces, pageFromUri, planckToUnit, remToUnit, removeHexPrefix, removeVarFromUrlHash, removedFrom, rmCommas, rmDecimals, setStateWithRef, shuffle, snakeToCamel, sortWithNull, u8aConcat, unescape, unimplemented, unitToPlanck, varToUrlHash, withTimeout, withTimeoutThrow };
|
package/index.js
CHANGED
|
@@ -135,6 +135,18 @@ var u8aConcat = (...u8as) => {
|
|
|
135
135
|
return result;
|
|
136
136
|
};
|
|
137
137
|
|
|
138
|
+
// src/jsx.ts
|
|
139
|
+
var mergeRefs = (el, internalRef, externalRef) => {
|
|
140
|
+
internalRef.current = el;
|
|
141
|
+
if (externalRef) {
|
|
142
|
+
if (typeof externalRef === "function") {
|
|
143
|
+
externalRef(el);
|
|
144
|
+
} else {
|
|
145
|
+
externalRef.current = el;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
|
|
138
150
|
// src/unit.ts
|
|
139
151
|
var planckToUnit = (val, units) => {
|
|
140
152
|
try {
|
|
@@ -347,6 +359,7 @@ export {
|
|
|
347
359
|
matchedProperties,
|
|
348
360
|
maxBigInt,
|
|
349
361
|
mergeDeep,
|
|
362
|
+
mergeRefs,
|
|
350
363
|
minBigInt,
|
|
351
364
|
minDecimalPlaces,
|
|
352
365
|
pageFromUri,
|
package/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/base.ts","../src/convert.ts","../src/unit.ts"],"sourcesContent":["/* @license Copyright 2024 w3ux authors & contributors\nSPDX-License-Identifier: GPL-3.0-only */\n\n/**\n * Ensures a number has at least the specified number of decimal places, retaining commas in the output if they are present in the input.\n *\n * @function minDecimalPlaces\n * @param {string | number | BigInt} val - The input number, which can be a `string` with or without commas, a `number`, or a `BigInt`.\n * @param {number} minDecimals - The minimum number of decimal places to enforce.\n * @returns {string} The formatted number as a string, padded with zeros if needed to meet `minDecimals`, retaining commas if originally provided.\n * If `val` is invalid, returns \"0\".\n * @example\n * // Pads \"1,234.5\" to have at least 3 decimal places, with commas\n * minDecimalPlaces(\"1,234.5\", 3); // returns \"1,234.500\"\n *\n * // Returns \"1234.56\" unchanged\n * minDecimalPlaces(1234.56, 2); // returns \"1234.56\"\n *\n * // Pads BigInt 1234 with 2 decimals\n * minDecimalPlaces(BigInt(1234), 2); // returns \"1234.00\"\n */\nexport const minDecimalPlaces = (\n\tval: string | number | bigint,\n\tminDecimals: number,\n): string => {\n\ttry {\n\t\t// Determine if we should retain commas based on original input type\n\t\tconst retainCommas = typeof val === 'string' && val.includes(',')\n\n\t\t// Convert `val` to a plain string for processing\n\t\tconst strVal =\n\t\t\ttypeof val === 'string' ? val.replace(/,/g, '') : val.toString()\n\n\t\t// Separate integer and decimal parts\n\t\tconst [integerPart, fractionalPart = ''] = strVal.split('.')\n\n\t\t// Parse the integer part as a BigInt\n\t\tconst whole = BigInt(integerPart || '0')\n\n\t\t// Calculate missing decimal places\n\t\tconst missingDecimals = minDecimals - fractionalPart.length\n\n\t\t// Format the integer part back with commas only if the input had commas\n\t\tconst formattedWhole = retainCommas\n\t\t\t? Intl.NumberFormat('en-US').format(whole)\n\t\t\t: whole.toString()\n\n\t\t// If missing decimals are needed, pad with zeros; otherwise, return the original value\n\t\treturn missingDecimals > 0\n\t\t\t? `${formattedWhole}.${fractionalPart}${'0'.repeat(missingDecimals)}`\n\t\t\t: `${formattedWhole}.${fractionalPart}`\n\t} catch {\n\t\t// The provided value is not a valid number, return \"0\".\n\t\treturn '0'\n\t}\n}\n\n/**\n * @name camelize\n * @summary Converts a string of text to camelCase.\n */\nexport const camelize = (str: string) => {\n\tconst convertToString = (string: string) => {\n\t\tif (string) {\n\t\t\tif (typeof string === 'string') {\n\t\t\t\treturn string\n\t\t\t}\n\t\t\treturn String(string)\n\t\t}\n\t\treturn ''\n\t}\n\n\tconst toWords = (inp: string) =>\n\t\tconvertToString(inp).match(\n\t\t\t/[A-Z\\xC0-\\xD6\\xD8-\\xDE]?[a-z\\xDF-\\xF6\\xF8-\\xFF]+|[A-Z\\xC0-\\xD6\\xD8-\\xDE]+(?![a-z\\xDF-\\xF6\\xF8-\\xFF])|\\d+/g,\n\t\t)\n\n\tconst simpleCamelCase = (inp: string[]) => {\n\t\tlet result = ''\n\t\tfor (let i = 0; i < inp?.length; i++) {\n\t\t\tconst currString = inp[i]\n\t\t\tlet tmpStr = currString.toLowerCase()\n\t\t\tif (i !== 0) {\n\t\t\t\ttmpStr =\n\t\t\t\t\ttmpStr.slice(0, 1).toUpperCase() + tmpStr.slice(1, tmpStr.length)\n\t\t\t}\n\t\t\tresult += tmpStr\n\t\t}\n\t\treturn result\n\t}\n\n\tconst w = toWords(str)?.map((a) => a.toLowerCase())\n\treturn simpleCamelCase(w || [])\n}\n\n/**\n * @name ellipsisFn\n * @summary Receives an address and creates ellipsis on the given string, based on parameters.\n * @param str - The string to apply the ellipsis on\n * @param amount - The amount of characters that the ellipsis will be\n * @param position - where the ellipsis will apply; if center the amount of character is the\n * same for beginning and end; if \"start\" or \"end\" then its only once the amount; defaults to \"start\"\n */\nexport const ellipsisFn = (\n\tstr: string,\n\tamount = 6,\n\tposition: 'start' | 'end' | 'center' = 'center',\n) => {\n\tconst half = str.length / 2\n\n\t// having an amount less than 4 is a bit extreme so we default there\n\tif (amount <= 4) {\n\t\tif (position === 'center') {\n\t\t\treturn str.slice(0, 4) + '...' + str.slice(-4)\n\t\t}\n\t\tif (position === 'end') {\n\t\t\treturn str.slice(0, 4) + '...'\n\t\t}\n\t\treturn '...' + str.slice(-4)\n\t}\n\t// if the amount requested is in a \"logical\" amount - meaning that it can display the address\n\t// without repeating the same information twice - then go for it;\n\tif (position === 'center') {\n\t\treturn amount >= (str.length - 2) / 2\n\t\t\t? str.slice(0, half - 3) + '...' + str.slice(-(half - 3))\n\t\t\t: str.slice(0, amount) + '...' + str.slice(-amount)\n\t}\n\t// else, the user has been mistaskenly extreme, so just show the maximum possible amount\n\tif (amount >= str.length) {\n\t\tif (position === 'end') {\n\t\t\treturn str.slice(0, str.length - 3) + '...'\n\t\t}\n\t\treturn '...' + str.slice(-(str.length - 3))\n\t} else {\n\t\tif (position === 'end') {\n\t\t\treturn str.slice(0, amount) + '...'\n\t\t}\n\t\treturn '...' + str.slice(amount)\n\t}\n}\n\n/**\n * @name pageFromUri\n * @summary Use url variables to load the default components upon the first page visit.\n */\nexport const pageFromUri = (pathname: string, fallback: string) => {\n\tconst lastUriItem = pathname.substring(pathname.lastIndexOf('/') + 1)\n\tconst page = lastUriItem.trim() === '' ? fallback : lastUriItem\n\treturn page.trim()\n}\n\n/**\n * @name rmCommas\n * @summary Removes the commas from a string.\n */\nexport const rmCommas = (val: string): string => val.replace(/,/g, '')\n\n/**\n * @name rmDecimals\n * @summary Removes the decimal point and decimals from a string.\n */\nexport const rmDecimals = (str: string) => str.split('.')[0]\n\n/**\n * @name shuffle\n * @summary Shuffle a set of objects.\n */\nexport const shuffle = <T>(array: T[]) => {\n\tlet currentIndex = array.length\n\tlet randomIndex\n\twhile (currentIndex !== 0) {\n\t\trandomIndex = Math.floor(Math.random() * currentIndex)\n\t\tcurrentIndex--\n\t\t;[array[currentIndex], array[randomIndex]] = [\n\t\t\tarray[randomIndex],\n\t\t\tarray[currentIndex],\n\t\t]\n\t}\n\treturn array\n}\n\n/**\n * @name withTimeout\n * @summary Timeout a promise after a specified number of milliseconds.\n */\nexport const withTimeout = (\n\tms: number,\n\tpromise: Promise<unknown>,\n\toptions?: {\n\t\tonTimeout?: () => void\n\t},\n) => {\n\tconst timeout = new Promise((resolve) =>\n\t\tsetTimeout(async () => {\n\t\t\tif (typeof options?.onTimeout === 'function') {\n\t\t\t\toptions.onTimeout()\n\t\t\t}\n\t\t\tresolve(undefined)\n\t\t}, ms),\n\t)\n\treturn Promise.race([promise, timeout])\n}\n\n/**\n * @name withTimeoutThrow\n * @summary Timeout a promise after a specified number of milliseconds by throwing an error\n */\nexport const withTimeoutThrow = <T>(\n\tms: number,\n\tpromise: Promise<T>,\n\toptions?: {\n\t\tonTimeout?: () => void\n\t},\n) => {\n\tconst timeout = new Promise((reject) =>\n\t\tsetTimeout(async () => {\n\t\t\tif (typeof options?.onTimeout === 'function') {\n\t\t\t\toptions.onTimeout()\n\t\t\t}\n\t\t\treject('Function timeout')\n\t\t}, ms),\n\t)\n\treturn Promise.race([promise, timeout])\n}\n\n/**\n * @name appendOrEmpty\n * @summary Returns ` value` if a condition is truthy, or an empty string otherwise.\n */\nexport const appendOrEmpty = (\n\tcondition: boolean | string | undefined,\n\tvalue: string,\n) => (condition ? ` ${value}` : '')\n\n/**\n * @name appendOr\n * @summary Returns ` value` if condition is truthy, or ` fallback` otherwise.\n */\nexport const appendOr = (\n\tcondition: boolean | string | undefined,\n\tvalue: string,\n\tfallback: string,\n) => (condition ? ` ${value}` : ` ${fallback}`)\n\n/**\n * @name removeHexPrefix\n * @summary Takes a string str as input and returns a new string with the \"0x\" prefix removed if it\n * exists at the beginning of the input string.\n */\nexport const removeHexPrefix = (str: string): string => str.replace(/^0x/, '')\n\n// Check if 2 sets contain the same elements.\n// biome-ignore lint/suspicious/noExplicitAny: <>\nexport const eqSet = (xs: Set<any>, ys: Set<any>) =>\n\txs.size === ys.size && [...xs].every((x) => ys.has(x))\n\n// Check if one set contains all the elements of another set.\n// biome-ignore lint/suspicious/noExplicitAny: <>\nexport const isSuperset = (set: Set<any>, subset: Set<any>) => {\n\tfor (const elem of subset) {\n\t\tif (!set.has(elem)) {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\n/**\n * Finds the maximum value among a list of BigInt values.\n *\n * @function maxBigInt\n * @param {...bigint} values - A list of BigInt values to compare.\n * @returns {bigint} The largest BigInt value in the provided list.\n * @example\n * // Returns the maximum BigInt value\n * maxBigInt(10n, 50n, 30n, 100n, 20n); // 100n\n */\nexport const maxBigInt = (...values: bigint[]): bigint =>\n\tvalues.reduce((max, current) => (current > max ? current : max))\n\n/**\n * Finds the minimum value among a list of BigInt values.\n *\n * @function minBigInt\n * @param {...bigint} values - A list of BigInt values to compare.\n * @returns {bigint} The smallest BigInt value in the provided list.\n * @example\n * // Returns the minimum BigInt value\n * minBigInt(10n, 50n, 30n, 100n, 20n); // 10n\n */\nexport const minBigInt = (...values: bigint[]): bigint =>\n\tvalues.reduce((min, current) => (current < min ? current : min))\n","// /* @license Copyright 2024 w3ux authors & contributors\n// SPDX-License-Identifier: GPL-3.0-only */\n\n/**\n * Concatenates multiple Uint8Array instances into a single Uint8Array.\n *\n * @param {Uint8Array[]} u8as - An array of Uint8Array instances to concatenate.\n * @returns {Uint8Array} A new Uint8Array containing all the input arrays concatenated.\n */\nexport const u8aConcat = (...u8as: Uint8Array[]): Uint8Array => {\n\t// Calculate the total length of the resulting Uint8Array\n\tconst totalLength = u8as.reduce((sum, u8a) => sum + u8a.length, 0)\n\n\t// Create a new Uint8Array with the total length\n\tconst result = new Uint8Array(totalLength)\n\n\tlet offset = 0 // Initialize the offset for placing elements\n\tfor (const u8a of u8as) {\n\t\tresult.set(u8a, offset) // Set the current Uint8Array at the current offset\n\t\toffset += u8a.length // Update the offset for the next Uint8Array\n\t}\n\n\treturn result\n}\n","/* @license Copyright 2024 w3ux authors & contributors\nSPDX-License-Identifier: GPL-3.0-only */\n\nimport type { RefObject } from 'react'\nimport { rmCommas, rmDecimals } from './base'\nimport type { AnyObject } from './types'\n\n/**\n * Converts an on-chain balance value from planck to a decimal value in token units.\n *\n * @function planckToUnit\n * @param {number | BigInt | string} val - The balance value in planck. Accepts a `number`, `BigInt`, or `string`.\n * @param {number} units - The number of decimal places in the token unit (10^units planck per 1 token).\n * @returns {string} The equivalent token unit value as a decimal string.\n * @example\n * // Convert 1500000000000 planck to tokens with 12 decimal places\n * planckToUnit(\"1500000000000\", 12); // returns \"1.5\"\n */\nexport const planckToUnit = (\n\tval: number | bigint | string,\n\tunits: number,\n): string => {\n\ttry {\n\t\t// Ensure `units` is a positive integer.\n\t\tunits = Math.max(Math.round(units), 0)\n\n\t\t// Convert `val` to BigInt based on its type\n\t\tconst bigIntVal =\n\t\t\ttypeof val === 'bigint'\n\t\t\t\t? val\n\t\t\t\t: BigInt(\n\t\t\t\t\t\ttypeof val === 'number'\n\t\t\t\t\t\t\t? Math.floor(val).toString()\n\t\t\t\t\t\t\t: rmDecimals(rmCommas(val)),\n\t\t\t\t\t)\n\n\t\tconst divisor = units === 0 ? 1n : BigInt(10) ** BigInt(units)\n\n\t\t// Integer division and remainder for the fractional part\n\t\tconst integerPart = bigIntVal / divisor\n\t\tconst fractionalPart = bigIntVal % divisor\n\n\t\t// Format fractional part with leading zeros to maintain `units` decimal places\n\t\tconst fractionalStr =\n\t\t\tunits > 0 ? `.${fractionalPart.toString().padStart(units, '0')}` : ``\n\n\t\t// Combine integer and fractional parts as a decimal string\n\t\treturn `${integerPart}${fractionalStr}`\n\t} catch {\n\t\treturn '0'\n\t}\n}\n\n/**\n * Converts a token unit value to an integer value in planck.\n *\n * @function unitToPlanck\n * @param {string | number | BigInt} val - The token unit value to convert. Accepts a string, number, or BigInt.\n * @param {number} units - The number of decimal places for conversion (10^units planck per 1 token).\n * @returns {BigInt} The equivalent value in planck as a BigInt.\n * @example\n * // Convert \"1.5\" tokens to planck with 12 decimal places\n * unitToPlanck(\"1.5\", 12); // returns BigInt(\"1500000000000\")\n */\nexport const unitToPlanck = (\n\tval: string | number | bigint,\n\tunits: number,\n): bigint => {\n\ttry {\n\t\t// Ensure `units` is a positive integer.\n\t\tunits = Math.max(Math.round(units), 0)\n\n\t\t// Convert `val` to a string; if empty or invalid, default to \"0\"\n\t\tconst strVal =\n\t\t\t(typeof val === 'string' ? rmCommas(val) : val.toString()) || '0'\n\n\t\t// Split into integer and fractional parts\n\t\tconst [integerPart, fractionalPart = ''] = strVal.split('.')\n\n\t\t// Process the integer part by converting to BigInt and scaling it to the given units\n\t\tlet bigIntValue = BigInt(integerPart) * BigInt(10) ** BigInt(units)\n\n\t\t// Process the fractional part if it exists\n\t\tif (fractionalPart) {\n\t\t\tlet fractionalValue: bigint\n\n\t\t\tif (fractionalPart.length > units) {\n\t\t\t\t// If fractional part exceeds units, truncate it\n\t\t\t\tfractionalValue = BigInt(fractionalPart.slice(0, units))\n\t\t\t} else {\n\t\t\t\t// Otherwise, pad the fractional part to match units\n\t\t\t\tfractionalValue = BigInt(fractionalPart.padEnd(units, '0'))\n\t\t\t}\n\n\t\t\tbigIntValue += fractionalValue\n\t\t}\n\n\t\treturn bigIntValue\n\t} catch {\n\t\treturn BigInt(0)\n\t}\n}\n\n/**\n * @name remToUnit\n * @summary Converts a rem string to a number.\n */\nexport const remToUnit = (rem: string) =>\n\tNumber(rem.slice(0, rem.length - 3)) *\n\tparseFloat(getComputedStyle(document.documentElement).fontSize)\n\n/**\n * @name capitalizeFirstLetter\n * @summary Capitalize the first letter of a string.\n */\nexport const capitalizeFirstLetter = (string: string) =>\n\tstring.charAt(0).toUpperCase() + string.slice(1)\n\n/**\n * @name snakeToCamel\n * @summary converts a string from snake / kebab-case to camel-case.\n */\nexport const snakeToCamel = (str: string) =>\n\tstr\n\t\t.toLowerCase()\n\t\t.replace(/([-_][a-z])/g, (group) =>\n\t\t\tgroup.toUpperCase().replace('-', '').replace('_', ''),\n\t\t)\n\n/**\n * @name setStateWithRef\n * @summary Synchronize React state and its reference with the provided value.\n */\nexport const setStateWithRef = <T>(\n\tvalue: T,\n\tsetState: (_state: T) => void,\n\tref: RefObject<T>,\n): void => {\n\tsetState(value)\n\tref.current = value\n}\n\n/**\n * @name localStorageOrDefault\n * @summary Retrieve the local stroage value with the key, return defult value if it is not\n * found.\n */\nexport const localStorageOrDefault = <T>(\n\tkey: string,\n\t_default: T,\n\tparse = false,\n): T | string => {\n\tconst val: string | null = localStorage.getItem(key)\n\n\tif (val === null) {\n\t\treturn _default\n\t}\n\n\tif (parse) {\n\t\treturn JSON.parse(val) as T\n\t}\n\treturn val\n}\n\n/**\n * @name extractUrlValue\n * @summary Extracts a URL value from a URL string.\n */\nexport const extractUrlValue = (key: string, url?: string) => {\n\tif (typeof url === 'undefined') {\n\t\turl = window.location.href\n\t}\n\tconst match = url.match(`[?&]${key}=([^&]+)`)\n\treturn match ? match[1] : null\n}\n\n/**\n * @name varToUrlHash\n * @summary Puts a variable into the URL hash as a param.\n * @description\n * Since url variables are added to the hash and are not treated as URL params, the params are split\n * and parsed into a `URLSearchParams`.\n */\nexport const varToUrlHash = (\n\tkey: string,\n\tval: string,\n\taddIfMissing: boolean,\n) => {\n\tconst hash = window.location.hash\n\tconst [page, params] = hash.split('?')\n\tconst searchParams = new URLSearchParams(params)\n\n\tif (searchParams.get(key) === null && !addIfMissing) {\n\t\treturn\n\t}\n\tsearchParams.set(key, val)\n\twindow.location.hash = `${page}?${searchParams.toString()}`\n}\n\n/**\n * @name removeVarFromUrlHash\n * @summary\n * Removes a variable `key` from the URL hash if it exists. Removes dangling `?` if no URL variables\n * exist.\n */\nexport const removeVarFromUrlHash = (key: string) => {\n\tconst hash = window.location.hash\n\tconst [page, params] = hash.split('?')\n\tconst searchParams = new URLSearchParams(params)\n\tif (searchParams.get(key) === null) {\n\t\treturn\n\t}\n\tsearchParams.delete(key)\n\tconst paramsAsStr = searchParams.toString()\n\twindow.location.hash = `${page}${paramsAsStr ? `?${paramsAsStr}` : ``}`\n}\n\n/**\n * @name sortWithNull\n * @summary Sorts an array with nulls last.\n */\nexport const sortWithNull =\n\t(ascending: boolean) => (a: unknown, b: unknown) => {\n\t\t// if both items are undefined, treat them as equal\n\t\tif (typeof a === 'undefined' && typeof b === 'undefined') {\n\t\t\treturn 0\n\t\t}\n\t\t// if either item is undefined, sort it last\n\t\tif (typeof a === 'undefined' || typeof b === 'undefined') {\n\t\t\treturn typeof a === 'undefined' ? 1 : -1\n\t\t}\n\t\t// equal items sort equally\n\t\tif (a === b) {\n\t\t\treturn 0\n\t\t}\n\t\t// nulls sort after anything else\n\t\tif (a === null) {\n\t\t\treturn 1\n\t\t}\n\t\tif (b === null) {\n\t\t\treturn -1\n\t\t}\n\t\t// otherwise, if we're ascending, lowest sorts first\n\t\tif (ascending) {\n\t\t\treturn a < b ? -1 : 1\n\t\t}\n\t\t// if descending, highest sorts first\n\t\treturn a < b ? 1 : -1\n\t}\n\n/**\n * @name applyWidthAsPadding\n * @summary Applies width of subject to paddingRight of container.\n */\nexport const applyWidthAsPadding = (\n\tsubjectRef: RefObject<HTMLDivElement | null>,\n\tcontainerRef: RefObject<HTMLDivElement | null>,\n) => {\n\tif (containerRef.current && subjectRef.current) {\n\t\tcontainerRef.current.style.paddingRight = `${\n\t\t\tsubjectRef.current.offsetWidth + remToUnit('1rem')\n\t\t}px`\n\t}\n}\n\n/**\n * @name unescape\n * @summary Replaces \\” with “\n */\nexport const unescape = (val: string) => val.replace(/\\\\\"/g, '\"')\n\n/**\n * @name inChrome\n * @summary Whether the application is rendering in Chrome.\n */\nexport const inChrome = () => {\n\tconst isChromium = (window as Window & { chrome?: boolean })?.chrome || null\n\tconst winNav = (window as Window)?.navigator || null\n\tconst isOpera =\n\t\ttypeof (window as Window & { opr?: boolean })?.opr !== 'undefined'\n\tconst isIEedge = winNav?.userAgent.indexOf('Edg') > -1 || false\n\tconst isIOSChrome = winNav?.userAgent.match('CriOS') || false\n\n\tif (isIOSChrome) {\n\t\treturn true\n\t}\n\tif (\n\t\tisChromium !== null &&\n\t\ttypeof isChromium !== 'undefined' &&\n\t\tisOpera === false &&\n\t\tisIEedge === false\n\t) {\n\t\treturn true\n\t}\n\treturn false\n}\n\n/**\n * @name addedTo\n * @summary Given 2 objects and some keys, return items in the fresh object that do not exist in the\n * stale object by matching the given common key values of both objects.\n */\nexport const addedTo = (\n\tfresh: AnyObject[],\n\tstale: AnyObject[],\n\tkeys: string[],\n): AnyObject[] =>\n\ttypeof fresh !== 'object' || typeof stale !== 'object' || !keys.length\n\t\t? []\n\t\t: fresh.filter(\n\t\t\t\t(freshItem) =>\n\t\t\t\t\t!stale.find((staleItem) =>\n\t\t\t\t\t\tkeys.every((key) =>\n\t\t\t\t\t\t\t!(key in staleItem) || !(key in freshItem)\n\t\t\t\t\t\t\t\t? false\n\t\t\t\t\t\t\t\t: staleItem[key] === freshItem[key],\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t)\n\n/**\n * @name removedFrom\n * @summary Given 2 objects and some keys, return items in the stale object that do not exist in the\n * fresh object by matching the given common key values of both objects.\n */\nexport const removedFrom = (\n\tfresh: AnyObject[],\n\tstale: AnyObject[],\n\tkeys: string[],\n): AnyObject[] =>\n\ttypeof fresh !== 'object' || typeof stale !== 'object' || !keys.length\n\t\t? []\n\t\t: stale.filter(\n\t\t\t\t(staleItem) =>\n\t\t\t\t\t!fresh.find((freshItem) =>\n\t\t\t\t\t\tkeys.every((key) =>\n\t\t\t\t\t\t\t!(key in staleItem) || !(key in freshItem)\n\t\t\t\t\t\t\t\t? false\n\t\t\t\t\t\t\t\t: freshItem[key] === staleItem[key],\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t)\n\n/**\n * @name matchedProperties\n * @summary Given 2 objects and some keys, return items in object 1 that also exist in object 2 by\n * matching the given common key values of both objects.\n */\nexport const matchedProperties = (\n\tobjX: AnyObject[],\n\tobjY: AnyObject[],\n\tkeys: string[],\n): AnyObject[] =>\n\ttypeof objX !== 'object' || typeof objY !== 'object' || !keys.length\n\t\t? []\n\t\t: objY.filter((x) =>\n\t\t\t\tobjX.find((y) =>\n\t\t\t\t\tkeys.every((key) =>\n\t\t\t\t\t\t!(key in x) || !(key in y) ? false : y[key] === x[key],\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t)\n\n/**\n * @name isValidHttpUrl\n * @summary Give a string, return whether it is a valid http URL.\n * @param string - The string to check.\n */\nexport const isValidHttpUrl = (string: string) => {\n\tlet url: URL\n\ttry {\n\t\turl = new URL(string)\n\t} catch (_) {\n\t\treturn false\n\t}\n\treturn url.protocol === 'http:' || url.protocol === 'https:'\n}\n\n/**\n * @name makeCancelable\n * @summary Makes a promise cancellable.\n * @param promise - The promise to make cancellable.\n */\nexport const makeCancelable = (promise: Promise<AnyObject>) => {\n\tlet hasCanceled = false\n\n\tconst wrappedPromise = new Promise((resolve, reject) => {\n\t\tpromise.then((val) =>\n\t\t\thasCanceled ? reject(Error('Cancelled')) : resolve(val),\n\t\t)\n\t\tpromise.catch((error) =>\n\t\t\thasCanceled ? reject(Error('Cancelled')) : reject(error),\n\t\t)\n\t})\n\n\treturn {\n\t\tpromise: wrappedPromise,\n\t\tcancel: () => {\n\t\t\thasCanceled = true\n\t\t},\n\t}\n}\n\n/**\n * @name unimplemented\n * @summary A placeholder function to signal a deliberate unimplementation.\n * Consumes an arbitrary number of props.\n */\nexport const unimplemented = (_props?: unknown) => {\n\t/* unimplemented */\n}\n\n/**\n * Deep merge two objects.\n * @param target\n * @param ...sources\n */\n\nexport const mergeDeep = (\n\ttarget: AnyObject,\n\t...sources: AnyObject[]\n): AnyObject => {\n\tif (!sources.length) {\n\t\treturn target\n\t}\n\n\tconst isObject = (item: AnyObject) =>\n\t\titem && typeof item === 'object' && !Array.isArray(item)\n\tconst source = sources.shift()\n\n\tif (isObject(target) && isObject(source)) {\n\t\tfor (const key in source) {\n\t\t\tif (isObject(source[key])) {\n\t\t\t\tif (!target[key]) {\n\t\t\t\t\tObject.assign(target, { [key]: {} })\n\t\t\t\t}\n\t\t\t\tmergeDeep(target[key], source[key])\n\t\t\t} else {\n\t\t\t\tObject.assign(target, { [key]: source[key] })\n\t\t\t}\n\t\t}\n\t}\n\treturn mergeDeep(target, ...sources)\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/base.ts","../src/convert.ts","../src/jsx.ts","../src/unit.ts"],"sourcesContent":["/* @license Copyright 2024 w3ux authors & contributors\nSPDX-License-Identifier: GPL-3.0-only */\n\n/**\n * Ensures a number has at least the specified number of decimal places, retaining commas in the output if they are present in the input.\n *\n * @function minDecimalPlaces\n * @param {string | number | BigInt} val - The input number, which can be a `string` with or without commas, a `number`, or a `BigInt`.\n * @param {number} minDecimals - The minimum number of decimal places to enforce.\n * @returns {string} The formatted number as a string, padded with zeros if needed to meet `minDecimals`, retaining commas if originally provided.\n * If `val` is invalid, returns \"0\".\n * @example\n * // Pads \"1,234.5\" to have at least 3 decimal places, with commas\n * minDecimalPlaces(\"1,234.5\", 3); // returns \"1,234.500\"\n *\n * // Returns \"1234.56\" unchanged\n * minDecimalPlaces(1234.56, 2); // returns \"1234.56\"\n *\n * // Pads BigInt 1234 with 2 decimals\n * minDecimalPlaces(BigInt(1234), 2); // returns \"1234.00\"\n */\nexport const minDecimalPlaces = (\n\tval: string | number | bigint,\n\tminDecimals: number,\n): string => {\n\ttry {\n\t\t// Determine if we should retain commas based on original input type\n\t\tconst retainCommas = typeof val === 'string' && val.includes(',')\n\n\t\t// Convert `val` to a plain string for processing\n\t\tconst strVal =\n\t\t\ttypeof val === 'string' ? val.replace(/,/g, '') : val.toString()\n\n\t\t// Separate integer and decimal parts\n\t\tconst [integerPart, fractionalPart = ''] = strVal.split('.')\n\n\t\t// Parse the integer part as a BigInt\n\t\tconst whole = BigInt(integerPart || '0')\n\n\t\t// Calculate missing decimal places\n\t\tconst missingDecimals = minDecimals - fractionalPart.length\n\n\t\t// Format the integer part back with commas only if the input had commas\n\t\tconst formattedWhole = retainCommas\n\t\t\t? Intl.NumberFormat('en-US').format(whole)\n\t\t\t: whole.toString()\n\n\t\t// If missing decimals are needed, pad with zeros; otherwise, return the original value\n\t\treturn missingDecimals > 0\n\t\t\t? `${formattedWhole}.${fractionalPart}${'0'.repeat(missingDecimals)}`\n\t\t\t: `${formattedWhole}.${fractionalPart}`\n\t} catch {\n\t\t// The provided value is not a valid number, return \"0\".\n\t\treturn '0'\n\t}\n}\n\n/**\n * @name camelize\n * @summary Converts a string of text to camelCase.\n */\nexport const camelize = (str: string) => {\n\tconst convertToString = (string: string) => {\n\t\tif (string) {\n\t\t\tif (typeof string === 'string') {\n\t\t\t\treturn string\n\t\t\t}\n\t\t\treturn String(string)\n\t\t}\n\t\treturn ''\n\t}\n\n\tconst toWords = (inp: string) =>\n\t\tconvertToString(inp).match(\n\t\t\t/[A-Z\\xC0-\\xD6\\xD8-\\xDE]?[a-z\\xDF-\\xF6\\xF8-\\xFF]+|[A-Z\\xC0-\\xD6\\xD8-\\xDE]+(?![a-z\\xDF-\\xF6\\xF8-\\xFF])|\\d+/g,\n\t\t)\n\n\tconst simpleCamelCase = (inp: string[]) => {\n\t\tlet result = ''\n\t\tfor (let i = 0; i < inp?.length; i++) {\n\t\t\tconst currString = inp[i]\n\t\t\tlet tmpStr = currString.toLowerCase()\n\t\t\tif (i !== 0) {\n\t\t\t\ttmpStr =\n\t\t\t\t\ttmpStr.slice(0, 1).toUpperCase() + tmpStr.slice(1, tmpStr.length)\n\t\t\t}\n\t\t\tresult += tmpStr\n\t\t}\n\t\treturn result\n\t}\n\n\tconst w = toWords(str)?.map((a) => a.toLowerCase())\n\treturn simpleCamelCase(w || [])\n}\n\n/**\n * @name ellipsisFn\n * @summary Receives an address and creates ellipsis on the given string, based on parameters.\n * @param str - The string to apply the ellipsis on\n * @param amount - The amount of characters that the ellipsis will be\n * @param position - where the ellipsis will apply; if center the amount of character is the\n * same for beginning and end; if \"start\" or \"end\" then its only once the amount; defaults to \"start\"\n */\nexport const ellipsisFn = (\n\tstr: string,\n\tamount = 6,\n\tposition: 'start' | 'end' | 'center' = 'center',\n) => {\n\tconst half = str.length / 2\n\n\t// having an amount less than 4 is a bit extreme so we default there\n\tif (amount <= 4) {\n\t\tif (position === 'center') {\n\t\t\treturn str.slice(0, 4) + '...' + str.slice(-4)\n\t\t}\n\t\tif (position === 'end') {\n\t\t\treturn str.slice(0, 4) + '...'\n\t\t}\n\t\treturn '...' + str.slice(-4)\n\t}\n\t// if the amount requested is in a \"logical\" amount - meaning that it can display the address\n\t// without repeating the same information twice - then go for it;\n\tif (position === 'center') {\n\t\treturn amount >= (str.length - 2) / 2\n\t\t\t? str.slice(0, half - 3) + '...' + str.slice(-(half - 3))\n\t\t\t: str.slice(0, amount) + '...' + str.slice(-amount)\n\t}\n\t// else, the user has been mistaskenly extreme, so just show the maximum possible amount\n\tif (amount >= str.length) {\n\t\tif (position === 'end') {\n\t\t\treturn str.slice(0, str.length - 3) + '...'\n\t\t}\n\t\treturn '...' + str.slice(-(str.length - 3))\n\t} else {\n\t\tif (position === 'end') {\n\t\t\treturn str.slice(0, amount) + '...'\n\t\t}\n\t\treturn '...' + str.slice(amount)\n\t}\n}\n\n/**\n * @name pageFromUri\n * @summary Use url variables to load the default components upon the first page visit.\n */\nexport const pageFromUri = (pathname: string, fallback: string) => {\n\tconst lastUriItem = pathname.substring(pathname.lastIndexOf('/') + 1)\n\tconst page = lastUriItem.trim() === '' ? fallback : lastUriItem\n\treturn page.trim()\n}\n\n/**\n * @name rmCommas\n * @summary Removes the commas from a string.\n */\nexport const rmCommas = (val: string): string => val.replace(/,/g, '')\n\n/**\n * @name rmDecimals\n * @summary Removes the decimal point and decimals from a string.\n */\nexport const rmDecimals = (str: string) => str.split('.')[0]\n\n/**\n * @name shuffle\n * @summary Shuffle a set of objects.\n */\nexport const shuffle = <T>(array: T[]) => {\n\tlet currentIndex = array.length\n\tlet randomIndex\n\twhile (currentIndex !== 0) {\n\t\trandomIndex = Math.floor(Math.random() * currentIndex)\n\t\tcurrentIndex--\n\t\t;[array[currentIndex], array[randomIndex]] = [\n\t\t\tarray[randomIndex],\n\t\t\tarray[currentIndex],\n\t\t]\n\t}\n\treturn array\n}\n\n/**\n * @name withTimeout\n * @summary Timeout a promise after a specified number of milliseconds.\n */\nexport const withTimeout = (\n\tms: number,\n\tpromise: Promise<unknown>,\n\toptions?: {\n\t\tonTimeout?: () => void\n\t},\n) => {\n\tconst timeout = new Promise((resolve) =>\n\t\tsetTimeout(async () => {\n\t\t\tif (typeof options?.onTimeout === 'function') {\n\t\t\t\toptions.onTimeout()\n\t\t\t}\n\t\t\tresolve(undefined)\n\t\t}, ms),\n\t)\n\treturn Promise.race([promise, timeout])\n}\n\n/**\n * @name withTimeoutThrow\n * @summary Timeout a promise after a specified number of milliseconds by throwing an error\n */\nexport const withTimeoutThrow = <T>(\n\tms: number,\n\tpromise: Promise<T>,\n\toptions?: {\n\t\tonTimeout?: () => void\n\t},\n) => {\n\tconst timeout = new Promise((reject) =>\n\t\tsetTimeout(async () => {\n\t\t\tif (typeof options?.onTimeout === 'function') {\n\t\t\t\toptions.onTimeout()\n\t\t\t}\n\t\t\treject('Function timeout')\n\t\t}, ms),\n\t)\n\treturn Promise.race([promise, timeout])\n}\n\n/**\n * @name appendOrEmpty\n * @summary Returns ` value` if a condition is truthy, or an empty string otherwise.\n */\nexport const appendOrEmpty = (\n\tcondition: boolean | string | undefined,\n\tvalue: string,\n) => (condition ? ` ${value}` : '')\n\n/**\n * @name appendOr\n * @summary Returns ` value` if condition is truthy, or ` fallback` otherwise.\n */\nexport const appendOr = (\n\tcondition: boolean | string | undefined,\n\tvalue: string,\n\tfallback: string,\n) => (condition ? ` ${value}` : ` ${fallback}`)\n\n/**\n * @name removeHexPrefix\n * @summary Takes a string str as input and returns a new string with the \"0x\" prefix removed if it\n * exists at the beginning of the input string.\n */\nexport const removeHexPrefix = (str: string): string => str.replace(/^0x/, '')\n\n// Check if 2 sets contain the same elements.\n// biome-ignore lint/suspicious/noExplicitAny: <>\nexport const eqSet = (xs: Set<any>, ys: Set<any>) =>\n\txs.size === ys.size && [...xs].every((x) => ys.has(x))\n\n// Check if one set contains all the elements of another set.\n// biome-ignore lint/suspicious/noExplicitAny: <>\nexport const isSuperset = (set: Set<any>, subset: Set<any>) => {\n\tfor (const elem of subset) {\n\t\tif (!set.has(elem)) {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\n/**\n * Finds the maximum value among a list of BigInt values.\n *\n * @function maxBigInt\n * @param {...bigint} values - A list of BigInt values to compare.\n * @returns {bigint} The largest BigInt value in the provided list.\n * @example\n * // Returns the maximum BigInt value\n * maxBigInt(10n, 50n, 30n, 100n, 20n); // 100n\n */\nexport const maxBigInt = (...values: bigint[]): bigint =>\n\tvalues.reduce((max, current) => (current > max ? current : max))\n\n/**\n * Finds the minimum value among a list of BigInt values.\n *\n * @function minBigInt\n * @param {...bigint} values - A list of BigInt values to compare.\n * @returns {bigint} The smallest BigInt value in the provided list.\n * @example\n * // Returns the minimum BigInt value\n * minBigInt(10n, 50n, 30n, 100n, 20n); // 10n\n */\nexport const minBigInt = (...values: bigint[]): bigint =>\n\tvalues.reduce((min, current) => (current < min ? current : min))\n","// /* @license Copyright 2024 w3ux authors & contributors\n// SPDX-License-Identifier: GPL-3.0-only */\n\n/**\n * Concatenates multiple Uint8Array instances into a single Uint8Array.\n *\n * @param {Uint8Array[]} u8as - An array of Uint8Array instances to concatenate.\n * @returns {Uint8Array} A new Uint8Array containing all the input arrays concatenated.\n */\nexport const u8aConcat = (...u8as: Uint8Array[]): Uint8Array => {\n\t// Calculate the total length of the resulting Uint8Array\n\tconst totalLength = u8as.reduce((sum, u8a) => sum + u8a.length, 0)\n\n\t// Create a new Uint8Array with the total length\n\tconst result = new Uint8Array(totalLength)\n\n\tlet offset = 0 // Initialize the offset for placing elements\n\tfor (const u8a of u8as) {\n\t\tresult.set(u8a, offset) // Set the current Uint8Array at the current offset\n\t\toffset += u8a.length // Update the offset for the next Uint8Array\n\t}\n\n\treturn result\n}\n","/* @license Copyright 2024 w3ux authors & contributors\nSPDX-License-Identifier: GPL-3.0-only */\n\nimport type { ForwardedRef, RefObject } from 'react'\n\n// Merge an external ref (callback or RefObject) with an internal ref so both stay in sync\nexport const mergeRefs = <T extends HTMLElement>(\n\tel: T | null,\n\tinternalRef: RefObject<HTMLElement | null>,\n\texternalRef: ForwardedRef<T>,\n): void => {\n\tinternalRef.current = el\n\tif (externalRef) {\n\t\tif (typeof externalRef === 'function') {\n\t\t\texternalRef(el)\n\t\t} else {\n\t\t\texternalRef.current = el\n\t\t}\n\t}\n}\n","/* @license Copyright 2024 w3ux authors & contributors\nSPDX-License-Identifier: GPL-3.0-only */\n\nimport type { RefObject } from 'react'\nimport { rmCommas, rmDecimals } from './base'\nimport type { AnyObject } from './types'\n\n/**\n * Converts an on-chain balance value from planck to a decimal value in token units.\n *\n * @function planckToUnit\n * @param {number | BigInt | string} val - The balance value in planck. Accepts a `number`, `BigInt`, or `string`.\n * @param {number} units - The number of decimal places in the token unit (10^units planck per 1 token).\n * @returns {string} The equivalent token unit value as a decimal string.\n * @example\n * // Convert 1500000000000 planck to tokens with 12 decimal places\n * planckToUnit(\"1500000000000\", 12); // returns \"1.5\"\n */\nexport const planckToUnit = (\n\tval: number | bigint | string,\n\tunits: number,\n): string => {\n\ttry {\n\t\t// Ensure `units` is a positive integer.\n\t\tunits = Math.max(Math.round(units), 0)\n\n\t\t// Convert `val` to BigInt based on its type\n\t\tconst bigIntVal =\n\t\t\ttypeof val === 'bigint'\n\t\t\t\t? val\n\t\t\t\t: BigInt(\n\t\t\t\t\t\ttypeof val === 'number'\n\t\t\t\t\t\t\t? Math.floor(val).toString()\n\t\t\t\t\t\t\t: rmDecimals(rmCommas(val)),\n\t\t\t\t\t)\n\n\t\tconst divisor = units === 0 ? 1n : BigInt(10) ** BigInt(units)\n\n\t\t// Integer division and remainder for the fractional part\n\t\tconst integerPart = bigIntVal / divisor\n\t\tconst fractionalPart = bigIntVal % divisor\n\n\t\t// Format fractional part with leading zeros to maintain `units` decimal places\n\t\tconst fractionalStr =\n\t\t\tunits > 0 ? `.${fractionalPart.toString().padStart(units, '0')}` : ``\n\n\t\t// Combine integer and fractional parts as a decimal string\n\t\treturn `${integerPart}${fractionalStr}`\n\t} catch {\n\t\treturn '0'\n\t}\n}\n\n/**\n * Converts a token unit value to an integer value in planck.\n *\n * @function unitToPlanck\n * @param {string | number | BigInt} val - The token unit value to convert. Accepts a string, number, or BigInt.\n * @param {number} units - The number of decimal places for conversion (10^units planck per 1 token).\n * @returns {BigInt} The equivalent value in planck as a BigInt.\n * @example\n * // Convert \"1.5\" tokens to planck with 12 decimal places\n * unitToPlanck(\"1.5\", 12); // returns BigInt(\"1500000000000\")\n */\nexport const unitToPlanck = (\n\tval: string | number | bigint,\n\tunits: number,\n): bigint => {\n\ttry {\n\t\t// Ensure `units` is a positive integer.\n\t\tunits = Math.max(Math.round(units), 0)\n\n\t\t// Convert `val` to a string; if empty or invalid, default to \"0\"\n\t\tconst strVal =\n\t\t\t(typeof val === 'string' ? rmCommas(val) : val.toString()) || '0'\n\n\t\t// Split into integer and fractional parts\n\t\tconst [integerPart, fractionalPart = ''] = strVal.split('.')\n\n\t\t// Process the integer part by converting to BigInt and scaling it to the given units\n\t\tlet bigIntValue = BigInt(integerPart) * BigInt(10) ** BigInt(units)\n\n\t\t// Process the fractional part if it exists\n\t\tif (fractionalPart) {\n\t\t\tlet fractionalValue: bigint\n\n\t\t\tif (fractionalPart.length > units) {\n\t\t\t\t// If fractional part exceeds units, truncate it\n\t\t\t\tfractionalValue = BigInt(fractionalPart.slice(0, units))\n\t\t\t} else {\n\t\t\t\t// Otherwise, pad the fractional part to match units\n\t\t\t\tfractionalValue = BigInt(fractionalPart.padEnd(units, '0'))\n\t\t\t}\n\n\t\t\tbigIntValue += fractionalValue\n\t\t}\n\n\t\treturn bigIntValue\n\t} catch {\n\t\treturn BigInt(0)\n\t}\n}\n\n/**\n * @name remToUnit\n * @summary Converts a rem string to a number.\n */\nexport const remToUnit = (rem: string) =>\n\tNumber(rem.slice(0, rem.length - 3)) *\n\tparseFloat(getComputedStyle(document.documentElement).fontSize)\n\n/**\n * @name capitalizeFirstLetter\n * @summary Capitalize the first letter of a string.\n */\nexport const capitalizeFirstLetter = (string: string) =>\n\tstring.charAt(0).toUpperCase() + string.slice(1)\n\n/**\n * @name snakeToCamel\n * @summary converts a string from snake / kebab-case to camel-case.\n */\nexport const snakeToCamel = (str: string) =>\n\tstr\n\t\t.toLowerCase()\n\t\t.replace(/([-_][a-z])/g, (group) =>\n\t\t\tgroup.toUpperCase().replace('-', '').replace('_', ''),\n\t\t)\n\n/**\n * @name setStateWithRef\n * @summary Synchronize React state and its reference with the provided value.\n */\nexport const setStateWithRef = <T>(\n\tvalue: T,\n\tsetState: (_state: T) => void,\n\tref: RefObject<T>,\n): void => {\n\tsetState(value)\n\tref.current = value\n}\n\n/**\n * @name localStorageOrDefault\n * @summary Retrieve the local stroage value with the key, return defult value if it is not\n * found.\n */\nexport const localStorageOrDefault = <T>(\n\tkey: string,\n\t_default: T,\n\tparse = false,\n): T | string => {\n\tconst val: string | null = localStorage.getItem(key)\n\n\tif (val === null) {\n\t\treturn _default\n\t}\n\n\tif (parse) {\n\t\treturn JSON.parse(val) as T\n\t}\n\treturn val\n}\n\n/**\n * @name extractUrlValue\n * @summary Extracts a URL value from a URL string.\n */\nexport const extractUrlValue = (key: string, url?: string) => {\n\tif (typeof url === 'undefined') {\n\t\turl = window.location.href\n\t}\n\tconst match = url.match(`[?&]${key}=([^&]+)`)\n\treturn match ? match[1] : null\n}\n\n/**\n * @name varToUrlHash\n * @summary Puts a variable into the URL hash as a param.\n * @description\n * Since url variables are added to the hash and are not treated as URL params, the params are split\n * and parsed into a `URLSearchParams`.\n */\nexport const varToUrlHash = (\n\tkey: string,\n\tval: string,\n\taddIfMissing: boolean,\n) => {\n\tconst hash = window.location.hash\n\tconst [page, params] = hash.split('?')\n\tconst searchParams = new URLSearchParams(params)\n\n\tif (searchParams.get(key) === null && !addIfMissing) {\n\t\treturn\n\t}\n\tsearchParams.set(key, val)\n\twindow.location.hash = `${page}?${searchParams.toString()}`\n}\n\n/**\n * @name removeVarFromUrlHash\n * @summary\n * Removes a variable `key` from the URL hash if it exists. Removes dangling `?` if no URL variables\n * exist.\n */\nexport const removeVarFromUrlHash = (key: string) => {\n\tconst hash = window.location.hash\n\tconst [page, params] = hash.split('?')\n\tconst searchParams = new URLSearchParams(params)\n\tif (searchParams.get(key) === null) {\n\t\treturn\n\t}\n\tsearchParams.delete(key)\n\tconst paramsAsStr = searchParams.toString()\n\twindow.location.hash = `${page}${paramsAsStr ? `?${paramsAsStr}` : ``}`\n}\n\n/**\n * @name sortWithNull\n * @summary Sorts an array with nulls last.\n */\nexport const sortWithNull =\n\t(ascending: boolean) => (a: unknown, b: unknown) => {\n\t\t// if both items are undefined, treat them as equal\n\t\tif (typeof a === 'undefined' && typeof b === 'undefined') {\n\t\t\treturn 0\n\t\t}\n\t\t// if either item is undefined, sort it last\n\t\tif (typeof a === 'undefined' || typeof b === 'undefined') {\n\t\t\treturn typeof a === 'undefined' ? 1 : -1\n\t\t}\n\t\t// equal items sort equally\n\t\tif (a === b) {\n\t\t\treturn 0\n\t\t}\n\t\t// nulls sort after anything else\n\t\tif (a === null) {\n\t\t\treturn 1\n\t\t}\n\t\tif (b === null) {\n\t\t\treturn -1\n\t\t}\n\t\t// otherwise, if we're ascending, lowest sorts first\n\t\tif (ascending) {\n\t\t\treturn a < b ? -1 : 1\n\t\t}\n\t\t// if descending, highest sorts first\n\t\treturn a < b ? 1 : -1\n\t}\n\n/**\n * @name applyWidthAsPadding\n * @summary Applies width of subject to paddingRight of container.\n */\nexport const applyWidthAsPadding = (\n\tsubjectRef: RefObject<HTMLDivElement | null>,\n\tcontainerRef: RefObject<HTMLDivElement | null>,\n) => {\n\tif (containerRef.current && subjectRef.current) {\n\t\tcontainerRef.current.style.paddingRight = `${\n\t\t\tsubjectRef.current.offsetWidth + remToUnit('1rem')\n\t\t}px`\n\t}\n}\n\n/**\n * @name unescape\n * @summary Replaces \\” with “\n */\nexport const unescape = (val: string) => val.replace(/\\\\\"/g, '\"')\n\n/**\n * @name inChrome\n * @summary Whether the application is rendering in Chrome.\n */\nexport const inChrome = () => {\n\tconst isChromium = (window as Window & { chrome?: boolean })?.chrome || null\n\tconst winNav = (window as Window)?.navigator || null\n\tconst isOpera =\n\t\ttypeof (window as Window & { opr?: boolean })?.opr !== 'undefined'\n\tconst isIEedge = winNav?.userAgent.indexOf('Edg') > -1 || false\n\tconst isIOSChrome = winNav?.userAgent.match('CriOS') || false\n\n\tif (isIOSChrome) {\n\t\treturn true\n\t}\n\tif (\n\t\tisChromium !== null &&\n\t\ttypeof isChromium !== 'undefined' &&\n\t\tisOpera === false &&\n\t\tisIEedge === false\n\t) {\n\t\treturn true\n\t}\n\treturn false\n}\n\n/**\n * @name addedTo\n * @summary Given 2 objects and some keys, return items in the fresh object that do not exist in the\n * stale object by matching the given common key values of both objects.\n */\nexport const addedTo = (\n\tfresh: AnyObject[],\n\tstale: AnyObject[],\n\tkeys: string[],\n): AnyObject[] =>\n\ttypeof fresh !== 'object' || typeof stale !== 'object' || !keys.length\n\t\t? []\n\t\t: fresh.filter(\n\t\t\t\t(freshItem) =>\n\t\t\t\t\t!stale.find((staleItem) =>\n\t\t\t\t\t\tkeys.every((key) =>\n\t\t\t\t\t\t\t!(key in staleItem) || !(key in freshItem)\n\t\t\t\t\t\t\t\t? false\n\t\t\t\t\t\t\t\t: staleItem[key] === freshItem[key],\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t)\n\n/**\n * @name removedFrom\n * @summary Given 2 objects and some keys, return items in the stale object that do not exist in the\n * fresh object by matching the given common key values of both objects.\n */\nexport const removedFrom = (\n\tfresh: AnyObject[],\n\tstale: AnyObject[],\n\tkeys: string[],\n): AnyObject[] =>\n\ttypeof fresh !== 'object' || typeof stale !== 'object' || !keys.length\n\t\t? []\n\t\t: stale.filter(\n\t\t\t\t(staleItem) =>\n\t\t\t\t\t!fresh.find((freshItem) =>\n\t\t\t\t\t\tkeys.every((key) =>\n\t\t\t\t\t\t\t!(key in staleItem) || !(key in freshItem)\n\t\t\t\t\t\t\t\t? false\n\t\t\t\t\t\t\t\t: freshItem[key] === staleItem[key],\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t)\n\n/**\n * @name matchedProperties\n * @summary Given 2 objects and some keys, return items in object 1 that also exist in object 2 by\n * matching the given common key values of both objects.\n */\nexport const matchedProperties = (\n\tobjX: AnyObject[],\n\tobjY: AnyObject[],\n\tkeys: string[],\n): AnyObject[] =>\n\ttypeof objX !== 'object' || typeof objY !== 'object' || !keys.length\n\t\t? []\n\t\t: objY.filter((x) =>\n\t\t\t\tobjX.find((y) =>\n\t\t\t\t\tkeys.every((key) =>\n\t\t\t\t\t\t!(key in x) || !(key in y) ? false : y[key] === x[key],\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t)\n\n/**\n * @name isValidHttpUrl\n * @summary Give a string, return whether it is a valid http URL.\n * @param string - The string to check.\n */\nexport const isValidHttpUrl = (string: string) => {\n\tlet url: URL\n\ttry {\n\t\turl = new URL(string)\n\t} catch (_) {\n\t\treturn false\n\t}\n\treturn url.protocol === 'http:' || url.protocol === 'https:'\n}\n\n/**\n * @name makeCancelable\n * @summary Makes a promise cancellable.\n * @param promise - The promise to make cancellable.\n */\nexport const makeCancelable = (promise: Promise<AnyObject>) => {\n\tlet hasCanceled = false\n\n\tconst wrappedPromise = new Promise((resolve, reject) => {\n\t\tpromise.then((val) =>\n\t\t\thasCanceled ? reject(Error('Cancelled')) : resolve(val),\n\t\t)\n\t\tpromise.catch((error) =>\n\t\t\thasCanceled ? reject(Error('Cancelled')) : reject(error),\n\t\t)\n\t})\n\n\treturn {\n\t\tpromise: wrappedPromise,\n\t\tcancel: () => {\n\t\t\thasCanceled = true\n\t\t},\n\t}\n}\n\n/**\n * @name unimplemented\n * @summary A placeholder function to signal a deliberate unimplementation.\n * Consumes an arbitrary number of props.\n */\nexport const unimplemented = (_props?: unknown) => {\n\t/* unimplemented */\n}\n\n/**\n * Deep merge two objects.\n * @param target\n * @param ...sources\n */\n\nexport const mergeDeep = (\n\ttarget: AnyObject,\n\t...sources: AnyObject[]\n): AnyObject => {\n\tif (!sources.length) {\n\t\treturn target\n\t}\n\n\tconst isObject = (item: AnyObject) =>\n\t\titem && typeof item === 'object' && !Array.isArray(item)\n\tconst source = sources.shift()\n\n\tif (isObject(target) && isObject(source)) {\n\t\tfor (const key in source) {\n\t\t\tif (isObject(source[key])) {\n\t\t\t\tif (!target[key]) {\n\t\t\t\t\tObject.assign(target, { [key]: {} })\n\t\t\t\t}\n\t\t\t\tmergeDeep(target[key], source[key])\n\t\t\t} else {\n\t\t\t\tObject.assign(target, { [key]: source[key] })\n\t\t\t}\n\t\t}\n\t}\n\treturn mergeDeep(target, ...sources)\n}\n"],"mappings":";AAqBO,IAAM,mBAAmB,CAC/B,KACA,gBACY;AACZ,MAAI;AAEH,UAAM,eAAe,OAAO,QAAQ,YAAY,IAAI,SAAS,GAAG;AAGhE,UAAM,SACL,OAAO,QAAQ,WAAW,IAAI,QAAQ,MAAM,EAAE,IAAI,IAAI,SAAS;AAGhE,UAAM,CAAC,aAAa,iBAAiB,EAAE,IAAI,OAAO,MAAM,GAAG;AAG3D,UAAM,QAAQ,OAAO,eAAe,GAAG;AAGvC,UAAM,kBAAkB,cAAc,eAAe;AAGrD,UAAM,iBAAiB,eACpB,KAAK,aAAa,OAAO,EAAE,OAAO,KAAK,IACvC,MAAM,SAAS;AAGlB,WAAO,kBAAkB,IACtB,GAAG,cAAc,IAAI,cAAc,GAAG,IAAI,OAAO,eAAe,CAAC,KACjE,GAAG,cAAc,IAAI,cAAc;AAAA,EACvC,QAAQ;AAEP,WAAO;AAAA,EACR;AACD;AAMO,IAAM,WAAW,CAAC,QAAgB;AACxC,QAAM,kBAAkB,CAAC,WAAmB;AAC3C,QAAI,QAAQ;AACX,UAAI,OAAO,WAAW,UAAU;AAC/B,eAAO;AAAA,MACR;AACA,aAAO,OAAO,MAAM;AAAA,IACrB;AACA,WAAO;AAAA,EACR;AAEA,QAAM,UAAU,CAAC,QAChB,gBAAgB,GAAG,EAAE;AAAA,IACpB;AAAA,EACD;AAED,QAAM,kBAAkB,CAAC,QAAkB;AAC1C,QAAI,SAAS;AACb,aAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACrC,YAAM,aAAa,IAAI,CAAC;AACxB,UAAI,SAAS,WAAW,YAAY;AACpC,UAAI,MAAM,GAAG;AACZ,iBACC,OAAO,MAAM,GAAG,CAAC,EAAE,YAAY,IAAI,OAAO,MAAM,GAAG,OAAO,MAAM;AAAA,MAClE;AACA,gBAAU;AAAA,IACX;AACA,WAAO;AAAA,EACR;AAEA,QAAM,IAAI,QAAQ,GAAG,GAAG,IAAI,CAAC,MAAM,EAAE,YAAY,CAAC;AAClD,SAAO,gBAAgB,KAAK,CAAC,CAAC;AAC/B;AAUO,IAAM,aAAa,CACzB,KACA,SAAS,GACT,WAAuC,aACnC;AACJ,QAAM,OAAO,IAAI,SAAS;AAG1B,MAAI,UAAU,GAAG;AAChB,QAAI,aAAa,UAAU;AAC1B,aAAO,IAAI,MAAM,GAAG,CAAC,IAAI,QAAQ,IAAI,MAAM,EAAE;AAAA,IAC9C;AACA,QAAI,aAAa,OAAO;AACvB,aAAO,IAAI,MAAM,GAAG,CAAC,IAAI;AAAA,IAC1B;AACA,WAAO,QAAQ,IAAI,MAAM,EAAE;AAAA,EAC5B;AAGA,MAAI,aAAa,UAAU;AAC1B,WAAO,WAAW,IAAI,SAAS,KAAK,IACjC,IAAI,MAAM,GAAG,OAAO,CAAC,IAAI,QAAQ,IAAI,MAAM,EAAE,OAAO,EAAE,IACtD,IAAI,MAAM,GAAG,MAAM,IAAI,QAAQ,IAAI,MAAM,CAAC,MAAM;AAAA,EACpD;AAEA,MAAI,UAAU,IAAI,QAAQ;AACzB,QAAI,aAAa,OAAO;AACvB,aAAO,IAAI,MAAM,GAAG,IAAI,SAAS,CAAC,IAAI;AAAA,IACvC;AACA,WAAO,QAAQ,IAAI,MAAM,EAAE,IAAI,SAAS,EAAE;AAAA,EAC3C,OAAO;AACN,QAAI,aAAa,OAAO;AACvB,aAAO,IAAI,MAAM,GAAG,MAAM,IAAI;AAAA,IAC/B;AACA,WAAO,QAAQ,IAAI,MAAM,MAAM;AAAA,EAChC;AACD;AAMO,IAAM,cAAc,CAAC,UAAkB,aAAqB;AAClE,QAAM,cAAc,SAAS,UAAU,SAAS,YAAY,GAAG,IAAI,CAAC;AACpE,QAAM,OAAO,YAAY,KAAK,MAAM,KAAK,WAAW;AACpD,SAAO,KAAK,KAAK;AAClB;AAMO,IAAM,WAAW,CAAC,QAAwB,IAAI,QAAQ,MAAM,EAAE;AAM9D,IAAM,aAAa,CAAC,QAAgB,IAAI,MAAM,GAAG,EAAE,CAAC;AAMpD,IAAM,UAAU,CAAI,UAAe;AACzC,MAAI,eAAe,MAAM;AACzB,MAAI;AACJ,SAAO,iBAAiB,GAAG;AAC1B,kBAAc,KAAK,MAAM,KAAK,OAAO,IAAI,YAAY;AACrD;AACC,KAAC,MAAM,YAAY,GAAG,MAAM,WAAW,CAAC,IAAI;AAAA,MAC5C,MAAM,WAAW;AAAA,MACjB,MAAM,YAAY;AAAA,IACnB;AAAA,EACD;AACA,SAAO;AACR;AAMO,IAAM,cAAc,CAC1B,IACA,SACA,YAGI;AACJ,QAAM,UAAU,IAAI;AAAA,IAAQ,CAAC,YAC5B,WAAW,YAAY;AACtB,UAAI,OAAO,SAAS,cAAc,YAAY;AAC7C,gBAAQ,UAAU;AAAA,MACnB;AACA,cAAQ,MAAS;AAAA,IAClB,GAAG,EAAE;AAAA,EACN;AACA,SAAO,QAAQ,KAAK,CAAC,SAAS,OAAO,CAAC;AACvC;AAMO,IAAM,mBAAmB,CAC/B,IACA,SACA,YAGI;AACJ,QAAM,UAAU,IAAI;AAAA,IAAQ,CAAC,WAC5B,WAAW,YAAY;AACtB,UAAI,OAAO,SAAS,cAAc,YAAY;AAC7C,gBAAQ,UAAU;AAAA,MACnB;AACA,aAAO,kBAAkB;AAAA,IAC1B,GAAG,EAAE;AAAA,EACN;AACA,SAAO,QAAQ,KAAK,CAAC,SAAS,OAAO,CAAC;AACvC;AAMO,IAAM,gBAAgB,CAC5B,WACA,UACK,YAAY,IAAI,KAAK,KAAK;AAMzB,IAAM,WAAW,CACvB,WACA,OACA,aACK,YAAY,IAAI,KAAK,KAAK,IAAI,QAAQ;AAOrC,IAAM,kBAAkB,CAAC,QAAwB,IAAI,QAAQ,OAAO,EAAE;AAItE,IAAM,QAAQ,CAAC,IAAc,OACnC,GAAG,SAAS,GAAG,QAAQ,CAAC,GAAG,EAAE,EAAE,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;AAI/C,IAAM,aAAa,CAAC,KAAe,WAAqB;AAC9D,aAAW,QAAQ,QAAQ;AAC1B,QAAI,CAAC,IAAI,IAAI,IAAI,GAAG;AACnB,aAAO;AAAA,IACR;AAAA,EACD;AACA,SAAO;AACR;AAYO,IAAM,YAAY,IAAI,WAC5B,OAAO,OAAO,CAAC,KAAK,YAAa,UAAU,MAAM,UAAU,GAAI;AAYzD,IAAM,YAAY,IAAI,WAC5B,OAAO,OAAO,CAAC,KAAK,YAAa,UAAU,MAAM,UAAU,GAAI;;;AC1RzD,IAAM,YAAY,IAAI,SAAmC;AAE/D,QAAM,cAAc,KAAK,OAAO,CAAC,KAAK,QAAQ,MAAM,IAAI,QAAQ,CAAC;AAGjE,QAAM,SAAS,IAAI,WAAW,WAAW;AAEzC,MAAI,SAAS;AACb,aAAW,OAAO,MAAM;AACvB,WAAO,IAAI,KAAK,MAAM;AACtB,cAAU,IAAI;AAAA,EACf;AAEA,SAAO;AACR;;;ACjBO,IAAM,YAAY,CACxB,IACA,aACA,gBACU;AACV,cAAY,UAAU;AACtB,MAAI,aAAa;AAChB,QAAI,OAAO,gBAAgB,YAAY;AACtC,kBAAY,EAAE;AAAA,IACf,OAAO;AACN,kBAAY,UAAU;AAAA,IACvB;AAAA,EACD;AACD;;;ACDO,IAAM,eAAe,CAC3B,KACA,UACY;AACZ,MAAI;AAEH,YAAQ,KAAK,IAAI,KAAK,MAAM,KAAK,GAAG,CAAC;AAGrC,UAAM,YACL,OAAO,QAAQ,WACZ,MACA;AAAA,MACA,OAAO,QAAQ,WACZ,KAAK,MAAM,GAAG,EAAE,SAAS,IACzB,WAAW,SAAS,GAAG,CAAC;AAAA,IAC5B;AAEH,UAAM,UAAU,UAAU,IAAI,KAAK,OAAO,EAAE,KAAK,OAAO,KAAK;AAG7D,UAAM,cAAc,YAAY;AAChC,UAAM,iBAAiB,YAAY;AAGnC,UAAM,gBACL,QAAQ,IAAI,IAAI,eAAe,SAAS,EAAE,SAAS,OAAO,GAAG,CAAC,KAAK;AAGpE,WAAO,GAAG,WAAW,GAAG,aAAa;AAAA,EACtC,QAAQ;AACP,WAAO;AAAA,EACR;AACD;AAaO,IAAM,eAAe,CAC3B,KACA,UACY;AACZ,MAAI;AAEH,YAAQ,KAAK,IAAI,KAAK,MAAM,KAAK,GAAG,CAAC;AAGrC,UAAM,UACJ,OAAO,QAAQ,WAAW,SAAS,GAAG,IAAI,IAAI,SAAS,MAAM;AAG/D,UAAM,CAAC,aAAa,iBAAiB,EAAE,IAAI,OAAO,MAAM,GAAG;AAG3D,QAAI,cAAc,OAAO,WAAW,IAAI,OAAO,EAAE,KAAK,OAAO,KAAK;AAGlE,QAAI,gBAAgB;AACnB,UAAI;AAEJ,UAAI,eAAe,SAAS,OAAO;AAElC,0BAAkB,OAAO,eAAe,MAAM,GAAG,KAAK,CAAC;AAAA,MACxD,OAAO;AAEN,0BAAkB,OAAO,eAAe,OAAO,OAAO,GAAG,CAAC;AAAA,MAC3D;AAEA,qBAAe;AAAA,IAChB;AAEA,WAAO;AAAA,EACR,QAAQ;AACP,WAAO,OAAO,CAAC;AAAA,EAChB;AACD;AAMO,IAAM,YAAY,CAAC,QACzB,OAAO,IAAI,MAAM,GAAG,IAAI,SAAS,CAAC,CAAC,IACnC,WAAW,iBAAiB,SAAS,eAAe,EAAE,QAAQ;AAMxD,IAAM,wBAAwB,CAAC,WACrC,OAAO,OAAO,CAAC,EAAE,YAAY,IAAI,OAAO,MAAM,CAAC;AAMzC,IAAM,eAAe,CAAC,QAC5B,IACE,YAAY,EACZ;AAAA,EAAQ;AAAA,EAAgB,CAAC,UACzB,MAAM,YAAY,EAAE,QAAQ,KAAK,EAAE,EAAE,QAAQ,KAAK,EAAE;AACrD;AAMK,IAAM,kBAAkB,CAC9B,OACA,UACA,QACU;AACV,WAAS,KAAK;AACd,MAAI,UAAU;AACf;AAOO,IAAM,wBAAwB,CACpC,KACA,UACA,QAAQ,UACQ;AAChB,QAAM,MAAqB,aAAa,QAAQ,GAAG;AAEnD,MAAI,QAAQ,MAAM;AACjB,WAAO;AAAA,EACR;AAEA,MAAI,OAAO;AACV,WAAO,KAAK,MAAM,GAAG;AAAA,EACtB;AACA,SAAO;AACR;AAMO,IAAM,kBAAkB,CAAC,KAAa,QAAiB;AAC7D,MAAI,OAAO,QAAQ,aAAa;AAC/B,UAAM,OAAO,SAAS;AAAA,EACvB;AACA,QAAM,QAAQ,IAAI,MAAM,OAAO,GAAG,UAAU;AAC5C,SAAO,QAAQ,MAAM,CAAC,IAAI;AAC3B;AASO,IAAM,eAAe,CAC3B,KACA,KACA,iBACI;AACJ,QAAM,OAAO,OAAO,SAAS;AAC7B,QAAM,CAAC,MAAM,MAAM,IAAI,KAAK,MAAM,GAAG;AACrC,QAAM,eAAe,IAAI,gBAAgB,MAAM;AAE/C,MAAI,aAAa,IAAI,GAAG,MAAM,QAAQ,CAAC,cAAc;AACpD;AAAA,EACD;AACA,eAAa,IAAI,KAAK,GAAG;AACzB,SAAO,SAAS,OAAO,GAAG,IAAI,IAAI,aAAa,SAAS,CAAC;AAC1D;AAQO,IAAM,uBAAuB,CAAC,QAAgB;AACpD,QAAM,OAAO,OAAO,SAAS;AAC7B,QAAM,CAAC,MAAM,MAAM,IAAI,KAAK,MAAM,GAAG;AACrC,QAAM,eAAe,IAAI,gBAAgB,MAAM;AAC/C,MAAI,aAAa,IAAI,GAAG,MAAM,MAAM;AACnC;AAAA,EACD;AACA,eAAa,OAAO,GAAG;AACvB,QAAM,cAAc,aAAa,SAAS;AAC1C,SAAO,SAAS,OAAO,GAAG,IAAI,GAAG,cAAc,IAAI,WAAW,KAAK,EAAE;AACtE;AAMO,IAAM,eACZ,CAAC,cAAuB,CAAC,GAAY,MAAe;AAEnD,MAAI,OAAO,MAAM,eAAe,OAAO,MAAM,aAAa;AACzD,WAAO;AAAA,EACR;AAEA,MAAI,OAAO,MAAM,eAAe,OAAO,MAAM,aAAa;AACzD,WAAO,OAAO,MAAM,cAAc,IAAI;AAAA,EACvC;AAEA,MAAI,MAAM,GAAG;AACZ,WAAO;AAAA,EACR;AAEA,MAAI,MAAM,MAAM;AACf,WAAO;AAAA,EACR;AACA,MAAI,MAAM,MAAM;AACf,WAAO;AAAA,EACR;AAEA,MAAI,WAAW;AACd,WAAO,IAAI,IAAI,KAAK;AAAA,EACrB;AAEA,SAAO,IAAI,IAAI,IAAI;AACpB;AAMM,IAAM,sBAAsB,CAClC,YACA,iBACI;AACJ,MAAI,aAAa,WAAW,WAAW,SAAS;AAC/C,iBAAa,QAAQ,MAAM,eAAe,GACzC,WAAW,QAAQ,cAAc,UAAU,MAAM,CAClD;AAAA,EACD;AACD;AAMO,IAAM,WAAW,CAAC,QAAgB,IAAI,QAAQ,QAAQ,GAAG;AAMzD,IAAM,WAAW,MAAM;AAC7B,QAAM,aAAc,QAA0C,UAAU;AACxE,QAAM,SAAU,QAAmB,aAAa;AAChD,QAAM,UACL,OAAQ,QAAuC,QAAQ;AACxD,QAAM,WAAW,QAAQ,UAAU,QAAQ,KAAK,IAAI,MAAM;AAC1D,QAAM,cAAc,QAAQ,UAAU,MAAM,OAAO,KAAK;AAExD,MAAI,aAAa;AAChB,WAAO;AAAA,EACR;AACA,MACC,eAAe,QACf,OAAO,eAAe,eACtB,YAAY,SACZ,aAAa,OACZ;AACD,WAAO;AAAA,EACR;AACA,SAAO;AACR;AAOO,IAAM,UAAU,CACtB,OACA,OACA,SAEA,OAAO,UAAU,YAAY,OAAO,UAAU,YAAY,CAAC,KAAK,SAC7D,CAAC,IACD,MAAM;AAAA,EACN,CAAC,cACA,CAAC,MAAM;AAAA,IAAK,CAAC,cACZ,KAAK;AAAA,MAAM,CAAC,QACX,EAAE,OAAO,cAAc,EAAE,OAAO,aAC7B,QACA,UAAU,GAAG,MAAM,UAAU,GAAG;AAAA,IACpC;AAAA,EACD;AACF;AAOI,IAAM,cAAc,CAC1B,OACA,OACA,SAEA,OAAO,UAAU,YAAY,OAAO,UAAU,YAAY,CAAC,KAAK,SAC7D,CAAC,IACD,MAAM;AAAA,EACN,CAAC,cACA,CAAC,MAAM;AAAA,IAAK,CAAC,cACZ,KAAK;AAAA,MAAM,CAAC,QACX,EAAE,OAAO,cAAc,EAAE,OAAO,aAC7B,QACA,UAAU,GAAG,MAAM,UAAU,GAAG;AAAA,IACpC;AAAA,EACD;AACF;AAOI,IAAM,oBAAoB,CAChC,MACA,MACA,SAEA,OAAO,SAAS,YAAY,OAAO,SAAS,YAAY,CAAC,KAAK,SAC3D,CAAC,IACD,KAAK;AAAA,EAAO,CAAC,MACb,KAAK;AAAA,IAAK,CAAC,MACV,KAAK;AAAA,MAAM,CAAC,QACX,EAAE,OAAO,MAAM,EAAE,OAAO,KAAK,QAAQ,EAAE,GAAG,MAAM,EAAE,GAAG;AAAA,IACtD;AAAA,EACD;AACD;AAOI,IAAM,iBAAiB,CAAC,WAAmB;AACjD,MAAI;AACJ,MAAI;AACH,UAAM,IAAI,IAAI,MAAM;AAAA,EACrB,SAAS,GAAG;AACX,WAAO;AAAA,EACR;AACA,SAAO,IAAI,aAAa,WAAW,IAAI,aAAa;AACrD;AAOO,IAAM,iBAAiB,CAAC,YAAgC;AAC9D,MAAI,cAAc;AAElB,QAAM,iBAAiB,IAAI,QAAQ,CAAC,SAAS,WAAW;AACvD,YAAQ;AAAA,MAAK,CAAC,QACb,cAAc,OAAO,MAAM,WAAW,CAAC,IAAI,QAAQ,GAAG;AAAA,IACvD;AACA,YAAQ;AAAA,MAAM,CAAC,UACd,cAAc,OAAO,MAAM,WAAW,CAAC,IAAI,OAAO,KAAK;AAAA,IACxD;AAAA,EACD,CAAC;AAED,SAAO;AAAA,IACN,SAAS;AAAA,IACT,QAAQ,MAAM;AACb,oBAAc;AAAA,IACf;AAAA,EACD;AACD;AAOO,IAAM,gBAAgB,CAAC,WAAqB;AAEnD;AAQO,IAAM,YAAY,CACxB,WACG,YACY;AACf,MAAI,CAAC,QAAQ,QAAQ;AACpB,WAAO;AAAA,EACR;AAEA,QAAM,WAAW,CAAC,SACjB,QAAQ,OAAO,SAAS,YAAY,CAAC,MAAM,QAAQ,IAAI;AACxD,QAAM,SAAS,QAAQ,MAAM;AAE7B,MAAI,SAAS,MAAM,KAAK,SAAS,MAAM,GAAG;AACzC,eAAW,OAAO,QAAQ;AACzB,UAAI,SAAS,OAAO,GAAG,CAAC,GAAG;AAC1B,YAAI,CAAC,OAAO,GAAG,GAAG;AACjB,iBAAO,OAAO,QAAQ,EAAE,CAAC,GAAG,GAAG,CAAC,EAAE,CAAC;AAAA,QACpC;AACA,kBAAU,OAAO,GAAG,GAAG,OAAO,GAAG,CAAC;AAAA,MACnC,OAAO;AACN,eAAO,OAAO,QAAQ,EAAE,CAAC,GAAG,GAAG,OAAO,GAAG,EAAE,CAAC;AAAA,MAC7C;AAAA,IACD;AAAA,EACD;AACA,SAAO,UAAU,QAAQ,GAAG,OAAO;AACpC;","names":[]}
|