@helpers4/number 3.0.6 → 3.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/lib/index.d.ts +26 -3
- package/lib/index.js +9 -3
- package/lib/index.js.map +1 -1
- package/llms.txt +14 -3
- package/meta/api.json +39 -7
- package/meta/examples.json +5 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -46,6 +46,7 @@ A set of helpers for working with URLs.
|
|
|
46
46
|
- [promise](../promise)
|
|
47
47
|
- [set](../set)
|
|
48
48
|
- [string](../string)
|
|
49
|
+
- [structure](../structure)
|
|
49
50
|
- [type](../type)
|
|
50
51
|
- [url](../url)
|
|
51
52
|
- [version](../version)
|
|
@@ -73,6 +74,7 @@ A set of helpers for working with URLs.
|
|
|
73
74
|
| promise | [@helpers4/promise](https://www.npmjs.com/package/@helpers4/promise) | [Source](https://github.com/helpers4/helpers4/tree/main/helpers/promise) | Promise utilities and error handling |
|
|
74
75
|
| set | [@helpers4/set](https://www.npmjs.com/package/@helpers4/set) | [Source](https://github.com/helpers4/helpers4/tree/main/helpers/set) | Native Set manipulation utilities |
|
|
75
76
|
| string | [@helpers4/string](https://www.npmjs.com/package/@helpers4/string) | [Source](https://github.com/helpers4/helpers4/tree/main/helpers/string) | String manipulation and formatting utilities |
|
|
77
|
+
| structure | [@helpers4/structure](https://www.npmjs.com/package/@helpers4/structure) | [Source](https://github.com/helpers4/helpers4/tree/main/helpers/structure) | Generic, domain-agnostic data structures |
|
|
76
78
|
| type | [@helpers4/type](https://www.npmjs.com/package/@helpers4/type) | [Source](https://github.com/helpers4/helpers4/tree/main/helpers/type) | Compile-time TypeScript utility types |
|
|
77
79
|
| url | [@helpers4/url](https://www.npmjs.com/package/@helpers4/url) | [Source](https://github.com/helpers4/helpers4/tree/main/helpers/url) | URL parsing and manipulation utilities |
|
|
78
80
|
| version | [@helpers4/version](https://www.npmjs.com/package/@helpers4/version) | [Source](https://github.com/helpers4/helpers4/tree/main/helpers/version) | Version string manipulation utilities |
|
package/lib/index.d.ts
CHANGED
|
@@ -137,13 +137,32 @@ declare function formatCompact(value: number, locale?: string): string;
|
|
|
137
137
|
* Copyright (C) 2025 baxyz
|
|
138
138
|
* SPDX-License-Identifier: LGPL-3.0-or-later
|
|
139
139
|
*/
|
|
140
|
+
/**
|
|
141
|
+
* Options for {@link formatSize}.
|
|
142
|
+
* @since 3.0.8
|
|
143
|
+
*/
|
|
144
|
+
interface FormatSizeOptions {
|
|
145
|
+
/**
|
|
146
|
+
* Inserted between the number and the unit.
|
|
147
|
+
* @default '' (no separator, e.g. `'1.5KB'`)
|
|
148
|
+
*/
|
|
149
|
+
unitSeparator?: string;
|
|
150
|
+
/**
|
|
151
|
+
* Print the base unit (`B`) as a bare integer with no decimal point, since
|
|
152
|
+
* a fractional byte count is meaningless. Units at `KB` and above are
|
|
153
|
+
* unaffected and always keep one decimal place.
|
|
154
|
+
* @default false
|
|
155
|
+
*/
|
|
156
|
+
integerBelowFirstUnit?: boolean;
|
|
157
|
+
}
|
|
140
158
|
/**
|
|
141
159
|
* Format a byte count into a human-readable string with the appropriate unit.
|
|
142
160
|
*
|
|
143
161
|
* Each unit is 1024 of the previous (binary prefix). The result is formatted
|
|
144
|
-
* with one decimal place.
|
|
162
|
+
* with one decimal place, unless `integerBelowFirstUnit` is set.
|
|
145
163
|
*
|
|
146
164
|
* @param bytes - A non-negative integer representing a byte count.
|
|
165
|
+
* @param options - Options.
|
|
147
166
|
* @returns A human-readable string such as `'0.0B'`, `'1.5KB'`, `'3.2MB'`.
|
|
148
167
|
* @example
|
|
149
168
|
* formatSize(0) // '0.0B'
|
|
@@ -152,9 +171,13 @@ declare function formatCompact(value: number, locale?: string): string;
|
|
|
152
171
|
* formatSize(1536) // '1.5KB'
|
|
153
172
|
* formatSize(1_048_576) // '1.0MB'
|
|
154
173
|
* formatSize(1_073_741_824) // '1.0GB'
|
|
174
|
+
* @example
|
|
175
|
+
* formatSize(1536, { unitSeparator: ' ' }) // '1.5 KB'
|
|
176
|
+
* formatSize(512, { integerBelowFirstUnit: true }) // '512B'
|
|
177
|
+
* formatSize(512, { unitSeparator: ' ', integerBelowFirstUnit: true }) // '512 B'
|
|
155
178
|
* @since 2.0.0
|
|
156
179
|
*/
|
|
157
|
-
declare function formatSize(bytes: number): string;
|
|
180
|
+
declare function formatSize(bytes: number, options?: FormatSizeOptions): string;
|
|
158
181
|
|
|
159
182
|
/**
|
|
160
183
|
* This file is part of helpers4.
|
|
@@ -345,4 +368,4 @@ declare function randomIntBetween(min: number, max: number): number;
|
|
|
345
368
|
declare function roundTo(value: number, decimals: number): number;
|
|
346
369
|
|
|
347
370
|
export { clamp, correctFloat, extractNumber, formatCompact, formatSize, inRange, isEven, isNegative, isOdd, isPositive, lerp, randomBetween, randomIntBetween, roundTo };
|
|
348
|
-
export type { ExtractNumberOptions, InRangeOptions };
|
|
371
|
+
export type { ExtractNumberOptions, FormatSizeOptions, InRangeOptions };
|
package/lib/index.js
CHANGED
|
@@ -160,9 +160,10 @@ var UNITS = [
|
|
|
160
160
|
* Format a byte count into a human-readable string with the appropriate unit.
|
|
161
161
|
*
|
|
162
162
|
* Each unit is 1024 of the previous (binary prefix). The result is formatted
|
|
163
|
-
* with one decimal place.
|
|
163
|
+
* with one decimal place, unless `integerBelowFirstUnit` is set.
|
|
164
164
|
*
|
|
165
165
|
* @param bytes - A non-negative integer representing a byte count.
|
|
166
|
+
* @param options - Options.
|
|
166
167
|
* @returns A human-readable string such as `'0.0B'`, `'1.5KB'`, `'3.2MB'`.
|
|
167
168
|
* @example
|
|
168
169
|
* formatSize(0) // '0.0B'
|
|
@@ -171,16 +172,21 @@ var UNITS = [
|
|
|
171
172
|
* formatSize(1536) // '1.5KB'
|
|
172
173
|
* formatSize(1_048_576) // '1.0MB'
|
|
173
174
|
* formatSize(1_073_741_824) // '1.0GB'
|
|
175
|
+
* @example
|
|
176
|
+
* formatSize(1536, { unitSeparator: ' ' }) // '1.5 KB'
|
|
177
|
+
* formatSize(512, { integerBelowFirstUnit: true }) // '512B'
|
|
178
|
+
* formatSize(512, { unitSeparator: ' ', integerBelowFirstUnit: true }) // '512 B'
|
|
174
179
|
* @since 2.0.0
|
|
175
180
|
*/
|
|
176
|
-
function formatSize(bytes) {
|
|
181
|
+
function formatSize(bytes, options = {}) {
|
|
182
|
+
const { unitSeparator = "", integerBelowFirstUnit = false } = options;
|
|
177
183
|
let size = bytes;
|
|
178
184
|
let unitIndex = 0;
|
|
179
185
|
while (size >= 1024 && unitIndex < UNITS.length - 1) {
|
|
180
186
|
size /= 1024;
|
|
181
187
|
unitIndex++;
|
|
182
188
|
}
|
|
183
|
-
return `${size.toFixed(1)}${UNITS[unitIndex]}`;
|
|
189
|
+
return `${unitIndex === 0 && integerBelowFirstUnit ? `${size}` : size.toFixed(1)}${unitSeparator}${UNITS[unitIndex]}`;
|
|
184
190
|
}
|
|
185
191
|
//#endregion
|
|
186
192
|
//#region helpers/number/inRange.ts
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../helpers/number/clamp.ts","../../../helpers/number/correctFloat.ts","../../../helpers/number/extractNumber.ts","../../../helpers/number/formatCompact.ts","../../../helpers/number/formatSize.ts","../../../helpers/number/inRange.ts","../../../helpers/number/isEven.ts","../../../helpers/number/isNegative.ts","../../../helpers/number/isOdd.ts","../../../helpers/number/isPositive.ts","../../../helpers/number/lerp.ts","../../../helpers/number/random.ts","../../../helpers/number/roundTo.ts"],"sourcesContent":["/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Clamps a number between min and max values\n * @param value - The value to clamp\n * @param min - Minimum value\n * @param max - Maximum value\n * @returns Clamped value\n * @since 1.9.0\n */\nexport function clamp(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), max);\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Corrects floating-point arithmetic errors by rounding to a given number\n * of significant digits. Useful after calculations that accumulate binary\n * floating-point drift (e.g. `0.1 + 0.2 === 0.30000000000000004`).\n *\n * The default precision of 14 significant digits eliminates typical\n * rounding noise for values in the range used by most applications.\n * Note: for values whose integer part already consumes 14 or more digits\n * (i.e. |value| ≥ 1e13), toPrecision(14) has no room left for decimal\n * digits and will silently truncate them. Increase `precision` if you\n * need to correct drift in very large numbers.\n *\n * Note: IEEE-754 doubles carry at most ~17 significant decimal digits.\n * Precision values above 17 pad with digits that reflect the underlying\n * binary representation rather than correcting drift.\n *\n * @param value - The floating-point value to correct\n * @param precision - Integer number of significant digits between 1 and 100\n * (default: 14). Values above 17 are valid but expose binary noise beyond\n * IEEE-754's meaningful range.\n * @returns The corrected value\n * @example\n * correctFloat(0.1 + 0.2) // => 0.3\n * correctFloat(1.1 - 0.3) // => 0.8\n * correctFloat(0.1 * 3) // => 0.3\n *\n * // Custom precision: keep 4 significant digits\n * correctFloat(1.23456789, 4) // => 1.235\n * correctFloat(1.23456789, 6) // => 1.23457\n * @since 2.0.2\n */\nexport function correctFloat(value: number, precision: number = 14): number {\n if (!Number.isFinite(value)) {\n throw new RangeError(`correctFloat: value must be a finite number, got ${value}`);\n }\n if (!Number.isInteger(precision) || precision < 1 || precision > 100) {\n throw new RangeError(`correctFloat: precision must be an integer between 1 and 100, got ${precision}`);\n }\n const result = parseFloat(value.toPrecision(precision));\n // toPrecision(-0) produces \"0.000…\" (no minus sign per spec) — restore the sign bit.\n return Object.is(value, -0) ? -0 : result;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Options for {@link extractNumber}.\n */\nexport interface ExtractNumberOptions {\n /**\n * How to interpret a `-` immediately before the matched digits.\n * - `'auto'`: treated as a minus sign unless it is glued to a preceding letter/digit\n * (e.g. `'-111'` and `'xxx -111'` → negative, but `'xxx-111'` → separator, positive).\n * - `'strict'`: always treated as a minus sign.\n * - `'ignore'`: never treated as a minus sign (always a separator).\n * @default 'auto'\n */\n sign?: 'auto' | 'strict' | 'ignore';\n\n /**\n * How to interpret a trailing scientific-notation suffix (`e`/`E` + digits, e.g. `1.5e-10`).\n * - `'auto'`: treated as an exponent unless it is glued to a following letter/digit\n * (e.g. `'1e5'` and `'1e5 mol'` → exponential, but `'1e5kg'` → mantissa only).\n * - `'strict'`: always treated as an exponent.\n * - `'ignore'`: never treated as an exponent (mantissa only).\n * @default 'auto'\n */\n exponent?: 'auto' | 'strict' | 'ignore';\n}\n\n// (?<![\\p{L}\\p{N}_]) prevents matching a leading-dot decimal immediately after a word\n// character (e.g. the '.5' in 'text.5' is a property separator, not a decimal point).\n// No `g` flag — cloned per call via `new RegExp(…, 'gu')` so each invocation has its own lastIndex.\nconst NUMBER_TOKEN = /(-)?(\\d+(?:\\.\\d+)?|(?<![\\p{L}\\p{N}_])\\.\\d+)([eE][+-]?\\d+)?/u;\nconst WORD_CHAR = /[\\p{L}\\p{N}_]/u;\n\nfunction isWordChar(char: string | undefined): boolean {\n return char !== undefined && WORD_CHAR.test(char);\n}\n\n/**\n * Extracts the first number embedded anywhere in a string, or passes through a `number`.\n *\n * Unlike a plain `parseFloat`/`parseInt`, the number does not need to be at the start of\n * the string: digits are searched for anywhere, so leading/trailing text (units, labels, ...)\n * is ignored. A `-` before the digits and a scientific-notation suffix (`e`/`E`) are\n * disambiguated with {@link ExtractNumberOptions.sign} and {@link ExtractNumberOptions.exponent}.\n *\n * Returns `undefined` if no number can be found.\n *\n * @param value - The value to extract a number from\n * @param options - Options controlling sign and exponent disambiguation\n * @returns The extracted number, or `undefined` if none was found\n * @example\n * extractNumber('16.5px') // => 16.5\n * extractNumber('.5rem') // => 0.5 (leading-dot decimal)\n * extractNumber('-.5') // => -0.5 (leading-dot with sign)\n * extractNumber('Wafer 10') // => 10\n * extractNumber('xxx-111') // => 111 ('-' glued to text → separator)\n * extractNumber('xxx -111') // => -111 ('-' preceded by a space → sign)\n * extractNumber('x-.5') // => 0.5 ('-' glued to 'x' → separator; leading-dot decimal follows)\n * extractNumber('-111') // => -111 ('-' at the start of the string → sign)\n * extractNumber('1e5 mol') // => 100000\n * extractNumber('1e5kg') // => 1 ('e5' glued to text → mantissa only)\n * extractNumber('no number') // => undefined\n * extractNumber(42) // => 42\n * @since 2.0.4\n */\nexport function extractNumber(value: unknown, options: ExtractNumberOptions = {}): number | undefined {\n const { sign = 'auto', exponent = 'auto' } = options;\n\n if (typeof value === 'number') {\n return Number.isNaN(value) ? undefined : value;\n }\n\n if (typeof value !== 'string') {\n return undefined;\n }\n\n const re = new RegExp(NUMBER_TOKEN.source, 'gu');\n let match: RegExpExecArray | null;\n\n while ((match = re.exec(value)) !== null) {\n const [full, signChar, mantissa, exponentPart] = match;\n const start = match.index;\n\n if (signChar) {\n const before = value[start - 1];\n const keepSign = sign === 'strict' ? true : sign === 'ignore' ? false : !isWordChar(before);\n\n if (!keepSign) {\n // Re-scan from right after the '-' so the digits are matched as a fresh, unsigned number.\n re.lastIndex = start + 1;\n continue;\n }\n }\n\n const keepExponent = exponentPart\n ? exponent === 'strict'\n ? true\n : exponent === 'ignore'\n ? false\n : !isWordChar(value[start + full.length])\n : false;\n\n const numericText = (signChar ?? '') + mantissa + (keepExponent ? exponentPart : '');\n return Number(numericText);\n }\n\n return undefined;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Formats a number using compact notation (e.g. `1_500_000 → \"1.5M\"`).\n *\n * Thin wrapper over `Intl.NumberFormat` with `notation: 'compact'`. Companion\n * of `formatSize` in the same `format*` family.\n *\n * @param value - The number to format.\n * @param locale - BCP 47 locale tag. Defaults to the runtime locale.\n * @returns A compact string representation of the number.\n * @example\n * formatCompact(1_500_000); // '1.5M' (en-US locale)\n * formatCompact(1_000); // '1K'\n * formatCompact(999); // '999'\n * formatCompact(1_500_000, 'fr'); // '1,5 M'\n * @since 2.0.0\n */\nexport function formatCompact(value: number, locale?: string): string {\n return new Intl.NumberFormat(locale, { notation: 'compact' }).format(value);\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/** Size units in ascending order. */\nconst UNITS = ['B', 'KB', 'MB', 'GB', 'TB'] as const;\n\n/**\n * Format a byte count into a human-readable string with the appropriate unit.\n *\n * Each unit is 1024 of the previous (binary prefix). The result is formatted\n * with one decimal place.\n *\n * @param bytes - A non-negative integer representing a byte count.\n * @returns A human-readable string such as `'0.0B'`, `'1.5KB'`, `'3.2MB'`.\n * @example\n * formatSize(0) // '0.0B'\n * formatSize(512) // '512.0B'\n * formatSize(1024) // '1.0KB'\n * formatSize(1536) // '1.5KB'\n * formatSize(1_048_576) // '1.0MB'\n * formatSize(1_073_741_824) // '1.0GB'\n * @since 2.0.0\n */\nexport function formatSize(bytes: number): string {\n let size = bytes;\n let unitIndex = 0;\n\n while (size >= 1024 && unitIndex < UNITS.length - 1) {\n size /= 1024;\n unitIndex++;\n }\n\n return `${size.toFixed(1)}${UNITS[unitIndex]}`;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Options for {@link inRange}.\n */\nexport interface InRangeOptions {\n /**\n * Which boundary (or boundaries) are included in the range.\n * - `'both'` (default): `min <= value <= max`\n * - `'min'`: `min <= value < max`\n * - `'max'`: `min < value <= max`\n * - `'none'`: `min < value < max`\n */\n inclusive?: 'both' | 'min' | 'max' | 'none';\n}\n\n/**\n * Checks whether a number falls within `[min, max]` (both inclusive by default).\n *\n * @param value - The number to test\n * @param min - Lower bound\n * @param max - Upper bound\n * @param options - Boundary inclusion mode (default: `'both'`)\n * @returns `true` if `value` is within the specified range\n * @example\n * inRange(5, 1, 10) // => true\n * inRange(1, 1, 10) // => true (min inclusive)\n * inRange(1, 1, 10, { inclusive: 'none' }) // => false\n * inRange(10, 1, 10, { inclusive: 'max' }) // => true\n * @since 2.0.0\n */\nexport function inRange(value: number, min: number, max: number, options: InRangeOptions = {}): boolean {\n const { inclusive = 'both' } = options;\n const minOk = inclusive === 'both' || inclusive === 'min' ? value >= min : value > min;\n const maxOk = inclusive === 'both' || inclusive === 'max' ? value <= max : value < max;\n return minOk && maxOk;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Checks if a value is an even integer.\n *\n * Returns `false` for non-numbers, non-integers, `NaN`, `Infinity`, and odd integers.\n *\n * @param value - The value to check\n * @returns `true` if value is an integer divisible by 2\n * @example\n * isEven(2) // => true\n * isEven(0) // => true\n * isEven(-4) // => true\n * isEven(3) // => false\n * isEven(1.5) // => false (not an integer)\n * isEven('2') // => false\n * @since 2.0.3\n */\nexport function isEven(value: unknown): value is number {\n return typeof value === 'number' && Number.isInteger(value) && value % 2 === 0;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Checks if a value is a number less than 0.\n *\n * Returns `false` for `NaN`, `0`, positive numbers, and non-number types.\n *\n * @param value - The value to check\n * @returns True if value is a negative number\n * @example\n * isNegative(-1) // => true\n * isNegative(-0.5) // => true\n * isNegative(-Infinity) // => true\n * isNegative(0) // => false\n * isNegative(1) // => false\n * isNegative(NaN) // => false\n * @since 2.0.0\n */\nexport function isNegative(value: unknown): value is number {\n return typeof value === 'number' && value < 0;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Checks if a value is an odd integer.\n *\n * Returns `false` for non-numbers, non-integers, `NaN`, `Infinity`, and even integers.\n *\n * @param value - The value to check\n * @returns `true` if value is an integer not divisible by 2\n * @example\n * isOdd(3) // => true\n * isOdd(1) // => true\n * isOdd(-7) // => true\n * isOdd(2) // => false\n * isOdd(1.5) // => false (not an integer)\n * isOdd('3') // => false\n * @since 2.0.3\n */\nexport function isOdd(value: unknown): value is number {\n return typeof value === 'number' && Number.isInteger(value) && value % 2 !== 0;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Checks if a value is a number greater than 0.\n *\n * Returns `false` for `NaN`, `0`, negative numbers, and non-number types.\n *\n * @param value - The value to check\n * @returns True if value is a positive number\n * @example\n * isPositive(42) // => true\n * isPositive(0.1) // => true\n * isPositive(Infinity) // => true\n * isPositive(0) // => false\n * isPositive(-1) // => false\n * isPositive(NaN) // => false\n * @since 2.0.0\n */\nexport function isPositive(value: unknown): value is number {\n return typeof value === 'number' && value > 0;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Linearly interpolates between `start` and `end` by the factor `t`.\n *\n * - `t = 0` returns `start`.\n * - `t = 1` returns `end`.\n * - Values of `t` outside `[0, 1]` extrapolate beyond the range.\n *\n * @param start - The start value.\n * @param end - The end value.\n * @param t - The interpolation factor.\n * @returns The interpolated value.\n * @example\n * lerp(0, 100, 0); // 0\n * lerp(0, 100, 1); // 100\n * lerp(0, 100, 0.5); // 50\n * lerp(0, 100, 0.25); // 25\n * @since 2.0.0\n */\nexport function lerp(start: number, end: number, t: number): number {\n if (t === 0) return start;\n if (t === 1) return end;\n if (Object.is(start, end)) return start;\n return start + (end - start) * t;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Generates a random number between min and max (inclusive)\n * @param min - Minimum value\n * @param max - Maximum value\n * @returns Random number between min and max\n * @since 1.9.0\n */\nexport function randomBetween(min: number, max: number): number {\n return Math.random() * (max - min) + min;\n}\n\n/**\n * Generates a random integer between min and max (inclusive)\n * @param min - Minimum value\n * @param max - Maximum value\n * @returns Random integer between min and max\n * @since 1.9.0\n */\nexport function randomIntBetween(min: number, max: number): number {\n return Math.floor(Math.random() * (max - min + 1)) + min;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Rounds a number to specified decimal places\n * @param value - The number to round\n * @param decimals - Number of decimal places\n * @returns Rounded number\n * @since 1.9.0\n */\nexport function roundTo(value: number, decimals: number): number {\n const multiplier = Math.pow(10, decimals);\n return Math.round(value * multiplier) / multiplier;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../helpers/number/clamp.ts","../../../helpers/number/correctFloat.ts","../../../helpers/number/extractNumber.ts","../../../helpers/number/formatCompact.ts","../../../helpers/number/formatSize.ts","../../../helpers/number/inRange.ts","../../../helpers/number/isEven.ts","../../../helpers/number/isNegative.ts","../../../helpers/number/isOdd.ts","../../../helpers/number/isPositive.ts","../../../helpers/number/lerp.ts","../../../helpers/number/random.ts","../../../helpers/number/roundTo.ts"],"sourcesContent":["/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Clamps a number between min and max values\n * @param value - The value to clamp\n * @param min - Minimum value\n * @param max - Maximum value\n * @returns Clamped value\n * @since 1.9.0\n */\nexport function clamp(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), max);\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Corrects floating-point arithmetic errors by rounding to a given number\n * of significant digits. Useful after calculations that accumulate binary\n * floating-point drift (e.g. `0.1 + 0.2 === 0.30000000000000004`).\n *\n * The default precision of 14 significant digits eliminates typical\n * rounding noise for values in the range used by most applications.\n * Note: for values whose integer part already consumes 14 or more digits\n * (i.e. |value| ≥ 1e13), toPrecision(14) has no room left for decimal\n * digits and will silently truncate them. Increase `precision` if you\n * need to correct drift in very large numbers.\n *\n * Note: IEEE-754 doubles carry at most ~17 significant decimal digits.\n * Precision values above 17 pad with digits that reflect the underlying\n * binary representation rather than correcting drift.\n *\n * @param value - The floating-point value to correct\n * @param precision - Integer number of significant digits between 1 and 100\n * (default: 14). Values above 17 are valid but expose binary noise beyond\n * IEEE-754's meaningful range.\n * @returns The corrected value\n * @example\n * correctFloat(0.1 + 0.2) // => 0.3\n * correctFloat(1.1 - 0.3) // => 0.8\n * correctFloat(0.1 * 3) // => 0.3\n *\n * // Custom precision: keep 4 significant digits\n * correctFloat(1.23456789, 4) // => 1.235\n * correctFloat(1.23456789, 6) // => 1.23457\n * @since 2.0.2\n */\nexport function correctFloat(value: number, precision: number = 14): number {\n if (!Number.isFinite(value)) {\n throw new RangeError(`correctFloat: value must be a finite number, got ${value}`);\n }\n if (!Number.isInteger(precision) || precision < 1 || precision > 100) {\n throw new RangeError(`correctFloat: precision must be an integer between 1 and 100, got ${precision}`);\n }\n const result = parseFloat(value.toPrecision(precision));\n // toPrecision(-0) produces \"0.000…\" (no minus sign per spec) — restore the sign bit.\n return Object.is(value, -0) ? -0 : result;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Options for {@link extractNumber}.\n */\nexport interface ExtractNumberOptions {\n /**\n * How to interpret a `-` immediately before the matched digits.\n * - `'auto'`: treated as a minus sign unless it is glued to a preceding letter/digit\n * (e.g. `'-111'` and `'xxx -111'` → negative, but `'xxx-111'` → separator, positive).\n * - `'strict'`: always treated as a minus sign.\n * - `'ignore'`: never treated as a minus sign (always a separator).\n * @default 'auto'\n */\n sign?: 'auto' | 'strict' | 'ignore';\n\n /**\n * How to interpret a trailing scientific-notation suffix (`e`/`E` + digits, e.g. `1.5e-10`).\n * - `'auto'`: treated as an exponent unless it is glued to a following letter/digit\n * (e.g. `'1e5'` and `'1e5 mol'` → exponential, but `'1e5kg'` → mantissa only).\n * - `'strict'`: always treated as an exponent.\n * - `'ignore'`: never treated as an exponent (mantissa only).\n * @default 'auto'\n */\n exponent?: 'auto' | 'strict' | 'ignore';\n}\n\n// (?<![\\p{L}\\p{N}_]) prevents matching a leading-dot decimal immediately after a word\n// character (e.g. the '.5' in 'text.5' is a property separator, not a decimal point).\n// No `g` flag — cloned per call via `new RegExp(…, 'gu')` so each invocation has its own lastIndex.\nconst NUMBER_TOKEN = /(-)?(\\d+(?:\\.\\d+)?|(?<![\\p{L}\\p{N}_])\\.\\d+)([eE][+-]?\\d+)?/u;\nconst WORD_CHAR = /[\\p{L}\\p{N}_]/u;\n\nfunction isWordChar(char: string | undefined): boolean {\n return char !== undefined && WORD_CHAR.test(char);\n}\n\n/**\n * Extracts the first number embedded anywhere in a string, or passes through a `number`.\n *\n * Unlike a plain `parseFloat`/`parseInt`, the number does not need to be at the start of\n * the string: digits are searched for anywhere, so leading/trailing text (units, labels, ...)\n * is ignored. A `-` before the digits and a scientific-notation suffix (`e`/`E`) are\n * disambiguated with {@link ExtractNumberOptions.sign} and {@link ExtractNumberOptions.exponent}.\n *\n * Returns `undefined` if no number can be found.\n *\n * @param value - The value to extract a number from\n * @param options - Options controlling sign and exponent disambiguation\n * @returns The extracted number, or `undefined` if none was found\n * @example\n * extractNumber('16.5px') // => 16.5\n * extractNumber('.5rem') // => 0.5 (leading-dot decimal)\n * extractNumber('-.5') // => -0.5 (leading-dot with sign)\n * extractNumber('Wafer 10') // => 10\n * extractNumber('xxx-111') // => 111 ('-' glued to text → separator)\n * extractNumber('xxx -111') // => -111 ('-' preceded by a space → sign)\n * extractNumber('x-.5') // => 0.5 ('-' glued to 'x' → separator; leading-dot decimal follows)\n * extractNumber('-111') // => -111 ('-' at the start of the string → sign)\n * extractNumber('1e5 mol') // => 100000\n * extractNumber('1e5kg') // => 1 ('e5' glued to text → mantissa only)\n * extractNumber('no number') // => undefined\n * extractNumber(42) // => 42\n * @since 2.0.4\n */\nexport function extractNumber(value: unknown, options: ExtractNumberOptions = {}): number | undefined {\n const { sign = 'auto', exponent = 'auto' } = options;\n\n if (typeof value === 'number') {\n return Number.isNaN(value) ? undefined : value;\n }\n\n if (typeof value !== 'string') {\n return undefined;\n }\n\n const re = new RegExp(NUMBER_TOKEN.source, 'gu');\n let match: RegExpExecArray | null;\n\n while ((match = re.exec(value)) !== null) {\n const [full, signChar, mantissa, exponentPart] = match;\n const start = match.index;\n\n if (signChar) {\n const before = value[start - 1];\n const keepSign = sign === 'strict' ? true : sign === 'ignore' ? false : !isWordChar(before);\n\n if (!keepSign) {\n // Re-scan from right after the '-' so the digits are matched as a fresh, unsigned number.\n re.lastIndex = start + 1;\n continue;\n }\n }\n\n const keepExponent = exponentPart\n ? exponent === 'strict'\n ? true\n : exponent === 'ignore'\n ? false\n : !isWordChar(value[start + full.length])\n : false;\n\n const numericText = (signChar ?? '') + mantissa + (keepExponent ? exponentPart : '');\n return Number(numericText);\n }\n\n return undefined;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Formats a number using compact notation (e.g. `1_500_000 → \"1.5M\"`).\n *\n * Thin wrapper over `Intl.NumberFormat` with `notation: 'compact'`. Companion\n * of `formatSize` in the same `format*` family.\n *\n * @param value - The number to format.\n * @param locale - BCP 47 locale tag. Defaults to the runtime locale.\n * @returns A compact string representation of the number.\n * @example\n * formatCompact(1_500_000); // '1.5M' (en-US locale)\n * formatCompact(1_000); // '1K'\n * formatCompact(999); // '999'\n * formatCompact(1_500_000, 'fr'); // '1,5 M'\n * @since 2.0.0\n */\nexport function formatCompact(value: number, locale?: string): string {\n return new Intl.NumberFormat(locale, { notation: 'compact' }).format(value);\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/** Size units in ascending order. */\nconst UNITS = ['B', 'KB', 'MB', 'GB', 'TB'] as const;\n\n/**\n * Options for {@link formatSize}.\n * @since 3.0.8\n */\nexport interface FormatSizeOptions {\n /**\n * Inserted between the number and the unit.\n * @default '' (no separator, e.g. `'1.5KB'`)\n */\n unitSeparator?: string;\n /**\n * Print the base unit (`B`) as a bare integer with no decimal point, since\n * a fractional byte count is meaningless. Units at `KB` and above are\n * unaffected and always keep one decimal place.\n * @default false\n */\n integerBelowFirstUnit?: boolean;\n}\n\n/**\n * Format a byte count into a human-readable string with the appropriate unit.\n *\n * Each unit is 1024 of the previous (binary prefix). The result is formatted\n * with one decimal place, unless `integerBelowFirstUnit` is set.\n *\n * @param bytes - A non-negative integer representing a byte count.\n * @param options - Options.\n * @returns A human-readable string such as `'0.0B'`, `'1.5KB'`, `'3.2MB'`.\n * @example\n * formatSize(0) // '0.0B'\n * formatSize(512) // '512.0B'\n * formatSize(1024) // '1.0KB'\n * formatSize(1536) // '1.5KB'\n * formatSize(1_048_576) // '1.0MB'\n * formatSize(1_073_741_824) // '1.0GB'\n * @example\n * formatSize(1536, { unitSeparator: ' ' }) // '1.5 KB'\n * formatSize(512, { integerBelowFirstUnit: true }) // '512B'\n * formatSize(512, { unitSeparator: ' ', integerBelowFirstUnit: true }) // '512 B'\n * @since 2.0.0\n */\nexport function formatSize(bytes: number, options: FormatSizeOptions = {}): string {\n const { unitSeparator = '', integerBelowFirstUnit = false } = options;\n let size = bytes;\n let unitIndex = 0;\n\n while (size >= 1024 && unitIndex < UNITS.length - 1) {\n size /= 1024;\n unitIndex++;\n }\n\n const formattedSize = unitIndex === 0 && integerBelowFirstUnit ? `${size}` : size.toFixed(1);\n return `${formattedSize}${unitSeparator}${UNITS[unitIndex]}`;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Options for {@link inRange}.\n */\nexport interface InRangeOptions {\n /**\n * Which boundary (or boundaries) are included in the range.\n * - `'both'` (default): `min <= value <= max`\n * - `'min'`: `min <= value < max`\n * - `'max'`: `min < value <= max`\n * - `'none'`: `min < value < max`\n */\n inclusive?: 'both' | 'min' | 'max' | 'none';\n}\n\n/**\n * Checks whether a number falls within `[min, max]` (both inclusive by default).\n *\n * @param value - The number to test\n * @param min - Lower bound\n * @param max - Upper bound\n * @param options - Boundary inclusion mode (default: `'both'`)\n * @returns `true` if `value` is within the specified range\n * @example\n * inRange(5, 1, 10) // => true\n * inRange(1, 1, 10) // => true (min inclusive)\n * inRange(1, 1, 10, { inclusive: 'none' }) // => false\n * inRange(10, 1, 10, { inclusive: 'max' }) // => true\n * @since 2.0.0\n */\nexport function inRange(value: number, min: number, max: number, options: InRangeOptions = {}): boolean {\n const { inclusive = 'both' } = options;\n const minOk = inclusive === 'both' || inclusive === 'min' ? value >= min : value > min;\n const maxOk = inclusive === 'both' || inclusive === 'max' ? value <= max : value < max;\n return minOk && maxOk;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Checks if a value is an even integer.\n *\n * Returns `false` for non-numbers, non-integers, `NaN`, `Infinity`, and odd integers.\n *\n * @param value - The value to check\n * @returns `true` if value is an integer divisible by 2\n * @example\n * isEven(2) // => true\n * isEven(0) // => true\n * isEven(-4) // => true\n * isEven(3) // => false\n * isEven(1.5) // => false (not an integer)\n * isEven('2') // => false\n * @since 2.0.3\n */\nexport function isEven(value: unknown): value is number {\n return typeof value === 'number' && Number.isInteger(value) && value % 2 === 0;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Checks if a value is a number less than 0.\n *\n * Returns `false` for `NaN`, `0`, positive numbers, and non-number types.\n *\n * @param value - The value to check\n * @returns True if value is a negative number\n * @example\n * isNegative(-1) // => true\n * isNegative(-0.5) // => true\n * isNegative(-Infinity) // => true\n * isNegative(0) // => false\n * isNegative(1) // => false\n * isNegative(NaN) // => false\n * @since 2.0.0\n */\nexport function isNegative(value: unknown): value is number {\n return typeof value === 'number' && value < 0;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Checks if a value is an odd integer.\n *\n * Returns `false` for non-numbers, non-integers, `NaN`, `Infinity`, and even integers.\n *\n * @param value - The value to check\n * @returns `true` if value is an integer not divisible by 2\n * @example\n * isOdd(3) // => true\n * isOdd(1) // => true\n * isOdd(-7) // => true\n * isOdd(2) // => false\n * isOdd(1.5) // => false (not an integer)\n * isOdd('3') // => false\n * @since 2.0.3\n */\nexport function isOdd(value: unknown): value is number {\n return typeof value === 'number' && Number.isInteger(value) && value % 2 !== 0;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Checks if a value is a number greater than 0.\n *\n * Returns `false` for `NaN`, `0`, negative numbers, and non-number types.\n *\n * @param value - The value to check\n * @returns True if value is a positive number\n * @example\n * isPositive(42) // => true\n * isPositive(0.1) // => true\n * isPositive(Infinity) // => true\n * isPositive(0) // => false\n * isPositive(-1) // => false\n * isPositive(NaN) // => false\n * @since 2.0.0\n */\nexport function isPositive(value: unknown): value is number {\n return typeof value === 'number' && value > 0;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Linearly interpolates between `start` and `end` by the factor `t`.\n *\n * - `t = 0` returns `start`.\n * - `t = 1` returns `end`.\n * - Values of `t` outside `[0, 1]` extrapolate beyond the range.\n *\n * @param start - The start value.\n * @param end - The end value.\n * @param t - The interpolation factor.\n * @returns The interpolated value.\n * @example\n * lerp(0, 100, 0); // 0\n * lerp(0, 100, 1); // 100\n * lerp(0, 100, 0.5); // 50\n * lerp(0, 100, 0.25); // 25\n * @since 2.0.0\n */\nexport function lerp(start: number, end: number, t: number): number {\n if (t === 0) return start;\n if (t === 1) return end;\n if (Object.is(start, end)) return start;\n return start + (end - start) * t;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Generates a random number between min and max (inclusive)\n * @param min - Minimum value\n * @param max - Maximum value\n * @returns Random number between min and max\n * @since 1.9.0\n */\nexport function randomBetween(min: number, max: number): number {\n return Math.random() * (max - min) + min;\n}\n\n/**\n * Generates a random integer between min and max (inclusive)\n * @param min - Minimum value\n * @param max - Maximum value\n * @returns Random integer between min and max\n * @since 1.9.0\n */\nexport function randomIntBetween(min: number, max: number): number {\n return Math.floor(Math.random() * (max - min + 1)) + min;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Rounds a number to specified decimal places\n * @param value - The number to round\n * @param decimals - Number of decimal places\n * @returns Rounded number\n * @since 1.9.0\n */\nexport function roundTo(value: number, decimals: number): number {\n const multiplier = Math.pow(10, decimals);\n return Math.round(value * multiplier) / multiplier;\n}\n"],"mappings":";;;;;;;;;;;;;;AAcA,SAAgB,MAAM,OAAe,KAAa,KAAqB;CACrE,OAAO,KAAK,IAAI,KAAK,IAAI,OAAO,GAAG,GAAG,GAAG;AAC3C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACqBA,SAAgB,aAAa,OAAe,YAAoB,IAAY;CAC1E,IAAI,CAAC,OAAO,SAAS,KAAK,GACxB,MAAM,IAAI,WAAW,oDAAoD,OAAO;CAElF,IAAI,CAAC,OAAO,UAAU,SAAS,KAAK,YAAY,KAAK,YAAY,KAC/D,MAAM,IAAI,WAAW,qEAAqE,WAAW;CAEvG,MAAM,SAAS,WAAW,MAAM,YAAY,SAAS,CAAC;CAEtD,OAAO,OAAO,GAAG,OAAO,EAAE,IAAI,KAAK;AACrC;;;ACbA,IAAM,eAAe;AACrB,IAAM,YAAY;AAElB,SAAS,WAAW,MAAmC;CACrD,OAAO,SAAS,KAAA,KAAa,UAAU,KAAK,IAAI;AAClD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BA,SAAgB,cAAc,OAAgB,UAAgC,CAAC,GAAuB;CACpG,MAAM,EAAE,OAAO,QAAQ,WAAW,WAAW;CAE7C,IAAI,OAAO,UAAU,UACnB,OAAO,OAAO,MAAM,KAAK,IAAI,KAAA,IAAY;CAG3C,IAAI,OAAO,UAAU,UACnB;CAGF,MAAM,KAAK,IAAI,OAAO,aAAa,QAAQ,IAAI;CAC/C,IAAI;CAEJ,QAAQ,QAAQ,GAAG,KAAK,KAAK,OAAO,MAAM;EACxC,MAAM,CAAC,MAAM,UAAU,UAAU,gBAAgB;EACjD,MAAM,QAAQ,MAAM;EAEpB,IAAI,UAAU;GACZ,MAAM,SAAS,MAAM,QAAQ;GAG7B,IAAI,EAFa,SAAS,WAAW,OAAO,SAAS,WAAW,QAAQ,CAAC,WAAW,MAAM,IAE3E;IAEb,GAAG,YAAY,QAAQ;IACvB;GACF;EACF;EAEA,MAAM,eAAe,eACjB,aAAa,WACX,OACA,aAAa,WACX,QACA,CAAC,WAAW,MAAM,QAAQ,KAAK,OAAO,IAC1C;EAEJ,MAAM,eAAe,YAAY,MAAM,YAAY,eAAe,eAAe;EACjF,OAAO,OAAO,WAAW;CAC3B;AAGF;;;;;;;;;;;;;;;;;;;;;;;;ACzFA,SAAgB,cAAc,OAAe,QAAyB;CACpE,OAAO,IAAI,KAAK,aAAa,QAAQ,EAAE,UAAU,UAAU,CAAC,CAAC,CAAC,OAAO,KAAK;AAC5E;;;;;;;;;ACjBA,IAAM,QAAQ;CAAC;CAAK;CAAM;CAAM;CAAM;AAAI;;;;;;;;;;;;;;;;;;;;;;;AA2C1C,SAAgB,WAAW,OAAe,UAA6B,CAAC,GAAW;CACjF,MAAM,EAAE,gBAAgB,IAAI,wBAAwB,UAAU;CAC9D,IAAI,OAAO;CACX,IAAI,YAAY;CAEhB,OAAO,QAAQ,QAAQ,YAAY,MAAM,SAAS,GAAG;EACnD,QAAQ;EACR;CACF;CAGA,OAAO,GADe,cAAc,KAAK,wBAAwB,GAAG,SAAS,KAAK,QAAQ,CAAC,IACjE,gBAAgB,MAAM;AAClD;;;;;;;;;;;;;;;;;;AC3BA,SAAgB,QAAQ,OAAe,KAAa,KAAa,UAA0B,CAAC,GAAY;CACtG,MAAM,EAAE,YAAY,WAAW;CAG/B,QAFc,cAAc,UAAU,cAAc,QAAQ,SAAS,MAAM,QAAQ,SACrE,cAAc,UAAU,cAAc,QAAQ,SAAS,MAAM,QAAQ;AAErF;;;;;;;;;;;;;;;;;;;;;;;;AClBA,SAAgB,OAAO,OAAiC;CACtD,OAAO,OAAO,UAAU,YAAY,OAAO,UAAU,KAAK,KAAK,QAAQ,MAAM;AAC/E;;;;;;;;;;;;;;;;;;;;;;;;ACFA,SAAgB,WAAW,OAAiC;CAC1D,OAAO,OAAO,UAAU,YAAY,QAAQ;AAC9C;;;;;;;;;;;;;;;;;;;;;;;;ACFA,SAAgB,MAAM,OAAiC;CACrD,OAAO,OAAO,UAAU,YAAY,OAAO,UAAU,KAAK,KAAK,QAAQ,MAAM;AAC/E;;;;;;;;;;;;;;;;;;;;;;;;ACFA,SAAgB,WAAW,OAAiC;CAC1D,OAAO,OAAO,UAAU,YAAY,QAAQ;AAC9C;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA,SAAgB,KAAK,OAAe,KAAa,GAAmB;CAClE,IAAI,MAAM,GAAG,OAAO;CACpB,IAAI,MAAM,GAAG,OAAO;CACpB,IAAI,OAAO,GAAG,OAAO,GAAG,GAAG,OAAO;CAClC,OAAO,SAAS,MAAM,SAAS;AACjC;;;;;;;;;;;;;;;AChBA,SAAgB,cAAc,KAAa,KAAqB;CAC9D,OAAO,KAAK,OAAO,KAAK,MAAM,OAAO;AACvC;;;;;;;;AASA,SAAgB,iBAAiB,KAAa,KAAqB;CACjE,OAAO,KAAK,MAAM,KAAK,OAAO,KAAK,MAAM,MAAM,EAAE,IAAI;AACvD;;;;;;;;;;;;;;;ACbA,SAAgB,QAAQ,OAAe,UAA0B;CAC/D,MAAM,aAAa,KAAK,IAAI,IAAI,QAAQ;CACxC,OAAO,KAAK,MAAM,QAAQ,UAAU,IAAI;AAC1C"}
|
package/llms.txt
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# @helpers4/number
|
|
2
2
|
|
|
3
3
|
> Tree-shakable TypeScript utility functions for the `number` domain.
|
|
4
|
-
> Package: `@helpers4/number` — Version: 3.0.
|
|
4
|
+
> Package: `@helpers4/number` — Version: 3.0.9
|
|
5
5
|
> License: LGPL-3.0-or-later
|
|
6
6
|
|
|
7
7
|
## Installation
|
|
@@ -221,17 +221,18 @@ formatCompact(1_500_000, 'fr') // => '1,5 M'
|
|
|
221
221
|
Format a byte count into a human-readable string with the appropriate unit.
|
|
222
222
|
|
|
223
223
|
Each unit is 1024 of the previous (binary prefix). The result is formatted
|
|
224
|
-
with one decimal place.
|
|
224
|
+
with one decimal place, unless `integerBelowFirstUnit` is set.
|
|
225
225
|
|
|
226
226
|
```typescript
|
|
227
227
|
import { formatSize } from '@helpers4/number';
|
|
228
228
|
|
|
229
|
-
formatSize(bytes: number): string
|
|
229
|
+
formatSize(bytes: number, options: FormatSizeOptions): string
|
|
230
230
|
```
|
|
231
231
|
|
|
232
232
|
**Parameters:**
|
|
233
233
|
|
|
234
234
|
- `bytes: number` — A non-negative integer representing a byte count.
|
|
235
|
+
- `options: FormatSizeOptions` (default: `{}`) — Options.
|
|
235
236
|
|
|
236
237
|
**Returns:** `string` — A human-readable string such as `'0.0B'`, `'1.5KB'`, `'3.2MB'`.
|
|
237
238
|
|
|
@@ -249,6 +250,16 @@ formatSize(1_048_576) // '1.0MB'
|
|
|
249
250
|
formatSize(1_073_741_824) // '1.0GB'
|
|
250
251
|
```
|
|
251
252
|
|
|
253
|
+
*Space before the unit, and a bare integer below the first unit*
|
|
254
|
+
|
|
255
|
+
unitSeparator inserts a separator before the unit; integerBelowFirstUnit drops the decimal for byte counts under 1024.
|
|
256
|
+
|
|
257
|
+
```typescript
|
|
258
|
+
formatSize(1536, { unitSeparator: ' ' }) // '1.5 KB'
|
|
259
|
+
formatSize(512, { integerBelowFirstUnit: true }) // '512B'
|
|
260
|
+
formatSize(512, { unitSeparator: ' ', integerBelowFirstUnit: true }) // '512 B'
|
|
261
|
+
```
|
|
262
|
+
|
|
252
263
|
---
|
|
253
264
|
|
|
254
265
|
### `inRange`
|
package/meta/api.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"category": "number",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.9",
|
|
4
4
|
"functions": [
|
|
5
5
|
{
|
|
6
6
|
"name": "clamp",
|
|
@@ -120,7 +120,14 @@
|
|
|
120
120
|
"code": "```ts\nextractNumber('16.5px') // => 16.5\nextractNumber('.5rem') // => 0.5 (leading-dot decimal)\nextractNumber('-.5') // => -0.5 (leading-dot with sign)\nextractNumber('Wafer 10') // => 10\nextractNumber('xxx-111') // => 111 ('-' glued to text → separator)\nextractNumber('xxx -111') // => -111 ('-' preceded by a space → sign)\nextractNumber('x-.5') // => 0.5 ('-' glued to 'x' → separator; leading-dot decimal follows)\nextractNumber('-111') // => -111 ('-' at the start of the string → sign)\nextractNumber('1e5 mol') // => 100000\nextractNumber('1e5kg') // => 1 ('e5' glued to text → mantissa only)\nextractNumber('no number') // => undefined\nextractNumber(42) // => 42\n```"
|
|
121
121
|
}
|
|
122
122
|
],
|
|
123
|
-
"sourceFile": "extractNumber.ts"
|
|
123
|
+
"sourceFile": "extractNumber.ts",
|
|
124
|
+
"relatedTypes": [
|
|
125
|
+
{
|
|
126
|
+
"name": "ExtractNumberOptions",
|
|
127
|
+
"description": "Options for extractNumber.",
|
|
128
|
+
"typeDefinition": "interface ExtractNumberOptions {\n exponent?: \"auto\" | \"strict\" | \"ignore\";\n sign?: \"auto\" | \"strict\" | \"ignore\";\n}"
|
|
129
|
+
}
|
|
130
|
+
]
|
|
124
131
|
},
|
|
125
132
|
{
|
|
126
133
|
"name": "formatCompact",
|
|
@@ -167,17 +174,23 @@
|
|
|
167
174
|
{
|
|
168
175
|
"name": "formatSize",
|
|
169
176
|
"kind": "function",
|
|
170
|
-
"description": "Format a byte count into a human-readable string with the appropriate unit.\n\nEach unit is 1024 of the previous (binary prefix). The result is formatted\nwith one decimal place.",
|
|
177
|
+
"description": "Format a byte count into a human-readable string with the appropriate unit.\n\nEach unit is 1024 of the previous (binary prefix). The result is formatted\nwith one decimal place, unless `integerBelowFirstUnit` is set.",
|
|
171
178
|
"since": "2.0.0",
|
|
172
179
|
"signatures": [
|
|
173
180
|
{
|
|
174
|
-
"signature": "formatSize(bytes: number): string",
|
|
175
|
-
"description": "Format a byte count into a human-readable string with the appropriate unit.\n\nEach unit is 1024 of the previous (binary prefix). The result is formatted\nwith one decimal place.",
|
|
181
|
+
"signature": "formatSize(bytes: number, options: FormatSizeOptions): string",
|
|
182
|
+
"description": "Format a byte count into a human-readable string with the appropriate unit.\n\nEach unit is 1024 of the previous (binary prefix). The result is formatted\nwith one decimal place, unless `integerBelowFirstUnit` is set.",
|
|
176
183
|
"params": [
|
|
177
184
|
{
|
|
178
185
|
"name": "bytes",
|
|
179
186
|
"type": "number",
|
|
180
187
|
"description": "A non-negative integer representing a byte count."
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
"name": "options",
|
|
191
|
+
"type": "FormatSizeOptions",
|
|
192
|
+
"description": "Options.",
|
|
193
|
+
"defaultValue": "{}"
|
|
181
194
|
}
|
|
182
195
|
],
|
|
183
196
|
"returns": {
|
|
@@ -191,9 +204,21 @@
|
|
|
191
204
|
"title": "Format bytes to human-readable size",
|
|
192
205
|
"description": "Converts a raw byte count to a human-readable string using binary prefixes.",
|
|
193
206
|
"code": "formatSize(0) // '0.0B'\nformatSize(512) // '512.0B'\nformatSize(1024) // '1.0KB'\nformatSize(1_048_576) // '1.0MB'\nformatSize(1_073_741_824) // '1.0GB'"
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
"title": "Space before the unit, and a bare integer below the first unit",
|
|
210
|
+
"description": "unitSeparator inserts a separator before the unit; integerBelowFirstUnit drops the decimal for byte counts under 1024.",
|
|
211
|
+
"code": "formatSize(1536, { unitSeparator: ' ' }) // '1.5 KB'\nformatSize(512, { integerBelowFirstUnit: true }) // '512B'\nformatSize(512, { unitSeparator: ' ', integerBelowFirstUnit: true }) // '512 B'"
|
|
194
212
|
}
|
|
195
213
|
],
|
|
196
|
-
"sourceFile": "formatSize.ts"
|
|
214
|
+
"sourceFile": "formatSize.ts",
|
|
215
|
+
"relatedTypes": [
|
|
216
|
+
{
|
|
217
|
+
"name": "FormatSizeOptions",
|
|
218
|
+
"description": "Options for formatSize.",
|
|
219
|
+
"typeDefinition": "interface FormatSizeOptions {\n integerBelowFirstUnit?: boolean;\n unitSeparator?: string;\n}"
|
|
220
|
+
}
|
|
221
|
+
]
|
|
197
222
|
},
|
|
198
223
|
{
|
|
199
224
|
"name": "inRange",
|
|
@@ -245,7 +270,14 @@
|
|
|
245
270
|
"code": "inRange(5, 1, 10, { inclusive: 'none' }) // => true\ninRange(1, 1, 10, { inclusive: 'none' }) // => false\ninRange(10, 1, 10, { inclusive: 'none' }) // => false"
|
|
246
271
|
}
|
|
247
272
|
],
|
|
248
|
-
"sourceFile": "inRange.ts"
|
|
273
|
+
"sourceFile": "inRange.ts",
|
|
274
|
+
"relatedTypes": [
|
|
275
|
+
{
|
|
276
|
+
"name": "InRangeOptions",
|
|
277
|
+
"description": "Options for inRange.",
|
|
278
|
+
"typeDefinition": "interface InRangeOptions {\n inclusive?: \"min\" | \"max\" | \"both\" | \"none\";\n}"
|
|
279
|
+
}
|
|
280
|
+
]
|
|
249
281
|
},
|
|
250
282
|
{
|
|
251
283
|
"name": "isEven",
|
package/meta/examples.json
CHANGED
|
@@ -58,6 +58,11 @@
|
|
|
58
58
|
"title": "Format bytes to human-readable size",
|
|
59
59
|
"description": "Converts a raw byte count to a human-readable string using binary prefixes.",
|
|
60
60
|
"code": "formatSize(0) // '0.0B'\nformatSize(512) // '512.0B'\nformatSize(1024) // '1.0KB'\nformatSize(1_048_576) // '1.0MB'\nformatSize(1_073_741_824) // '1.0GB'"
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"title": "Space before the unit, and a bare integer below the first unit",
|
|
64
|
+
"description": "unitSeparator inserts a separator before the unit; integerBelowFirstUnit drops the decimal for byte counts under 1024.",
|
|
65
|
+
"code": "formatSize(1536, { unitSeparator: ' ' }) // '1.5 KB'\nformatSize(512, { integerBelowFirstUnit: true }) // '512B'\nformatSize(512, { unitSeparator: ' ', integerBelowFirstUnit: true }) // '512 B'"
|
|
61
66
|
}
|
|
62
67
|
]
|
|
63
68
|
},
|