Documentation / Number

Number

Utilities for clamping, generating, and aggregating numbers. Import from the root or from koyojs/Number.

// Root import
import { clamp, randomInt, sum } from "koyojs";

// Per-module import
import { clamp } from "koyojs/Number";
clampclamp(value: number, min: number, max: number): number

Clamps a number between a minimum and maximum value. If the value is below min it returns min; if it is above max it returns max; otherwise it returns the value unchanged. Throws a RangeError if min > max.

ParameterTypeDescription
valuenumberThe number to clamp.
minnumberLower bound (inclusive). Must be ≤ max.
maxnumberUpper bound (inclusive). Must be ≥ min.
returnsnumber
import { clamp } from "koyojs";

clamp(150, 0, 100);  // 100  — above max, capped
clamp(-5,  0, 100);  // 0    — below min, floored
clamp(42,  0, 100);  // 42   — in range, returned as-is

// Volume slider — keep within 0–100%
const volume = clamp(rawInput, 0, 100);

// CSS opacity — must stay in 0.0–1.0
const opacity = clamp(userAlpha / 255, 0, 1);

// Pagination — never below page 1 or above the last page
const page = clamp(requestedPage, 1, totalPages);

// Restrict canvas drawing coordinates to viewport
const x = clamp(pointerX, 0, canvas.width);
const y = clamp(pointerY, 0, canvas.height);

randomIntrandomInt(min: number, max: number): number

Returns a random integer between min and max, both inclusive. Uses Math.random internally — suitable for UI and game purposes, not cryptographic use. Throws a TypeError if either argument is not an integer, and a RangeError if min > max.

ParameterTypeDescription
minnumberLower bound (inclusive). Must be an integer and ≤ max.
maxnumberUpper bound (inclusive). Must be an integer and ≥ min.
returnsnumber
import { randomInt } from "koyojs";

randomInt(1, 6);    // 1 | 2 | 3 | 4 | 5 | 6  — simulates a die
randomInt(0, 100);  // any integer from 0 to 100

// Pick a random item from an array
const fruits = ["apple", "banana", "cherry", "mango"];
const pick = fruits[randomInt(0, fruits.length - 1)];

// Generate a 6-digit numeric OTP (UI placeholder / demo only)
const otp = randomInt(100000, 999999).toString();

// Randomize a stagger delay for animations (0–300 ms)
cards.forEach(card => {
  card.style.animationDelay = `${randomInt(0, 300)}ms`;
});

// Shuffle an array using Fisher-Yates
function shuffle<T>(arr: T[]): T[] {
  const a = [...arr];
  for (let i = a.length - 1; i > 0; i--) {
    const j = randomInt(0, i);
    [a[i], a[j]] = [a[j], a[i]];
  }
  return a;
}

sumsum(values: number[]): number

Returns the sum of all numbers in an array. Returns 0 for an empty array.

ParameterTypeDescription
valuesnumber[]The array of numbers to sum.
returnsnumber
import { sum } from "koyojs";

sum([1, 2, 3, 4, 5]);  // 15
sum([]);                // 0
sum([-1, 1]);           // 0
sum([0.1, 0.2]);        // 0.30000000000000004  — standard JS float precision

// Shopping cart total
const cart = [
  { name: "Keyboard", price: 89.99 },
  { name: "Mouse",    price: 39.99 },
  { name: "Monitor",  price: 349.00 },
];
const total = sum(cart.map(item => item.price));  // 478.98

// Aggregate daily visitor counts
const week = [120, 240, 310, 180, 95, 410, 280];
const weeklyTotal = sum(week);  // 1635

// Calculate total hours from a timesheet
const hours = entries.map(e => e.duration);
const totalHours = sum(hours);

averageaverage(values: number[]): number

Returns the arithmetic mean of an array of numbers. Throws a RangeError if the array is empty — guard against empty input before calling.

ParameterTypeDescription
valuesnumber[]A non-empty array of numbers.
returnsnumber
import { average } from "koyojs";

average([1, 2, 3]);        // 2
average([10, 20, 30]);     // 20
average([7]);              // 7
average([1, 2]);           // 1.5

// ⚠️ Throws RangeError on an empty array — always guard first
const score = scores.length > 0 ? average(scores) : null;

// Star rating display
const reviews = [4, 5, 3, 4, 5, 4, 2];
const rating = average(reviews).toFixed(1);  // "3.9"

// Dashboard metric — average response time
const latencies = requests.map(r => r.durationMs);
const avgMs = average(latencies);
console.log(`Average response: ${avgMs.toFixed(0)}ms`);

// Normalize scores to a 0–10 scale
const normalized = rawScores.map(s => clamp(average(rawScores) - s + 5, 0, 10));

isEvenisEven(value: number): boolean

Returns true if the integer is even. Throws a TypeError if the argument is not an integer.

ParameterTypeDescription
valuenumberAn integer to test.
returnsboolean
import { isEven } from "koyojs";

isEven(4);    // true
isEven(7);    // false
isEven(0);    // true
isEven(-2);   // true
isEven(-3);   // false

// Zebra-stripe table rows
rows.map((row, i) => (
  <tr class={isEven(i) ? "row-light" : "row-dark"}>{...}</tr>
));

// Alternate card layout in a masonry grid
items.map((item, i) => ({
  ...item,
  alignSelf: isEven(i) ? "flex-start" : "flex-end",
}));

// Split an array into even-indexed and odd-indexed items
const evens = arr.filter((_, i) => isEven(i));
const odds  = arr.filter((_, i) => !isEven(i));

isOddisOdd(value: number): boolean

Returns true if the integer is odd. Implemented as `!isEven(value)` — also throws a TypeError for non-integers.

ParameterTypeDescription
valuenumberAn integer to test.
returnsboolean
import { isOdd } from "koyojs";

isOdd(3);    // true
isOdd(4);    // false
isOdd(-1);   // true
isOdd(0);    // false

// Show a divider after every odd item in a list
items.map((item, i) => (
  <>
    <Item data={item} />
    {isOdd(i + 1) && i < items.length - 1 && <Divider />}
  </>
));

// Group items into pairs (first of each pair is at an odd 1-based index)
const pairs = items.reduce<(typeof items)[]>((acc, item, i) => {
  if (isOdd(i + 1)) acc.push([item]);
  else acc[acc.length - 1].push(item);
  return acc;
}, []);