Number Helpers
Utility functions for number formatting, validation, and manipulation
Overview
Number Helpers provide utility functions for working with numbers in various formats, including currency formatting, ordinal numbers, input validation, and numeric operations.
Installation
npx shadcn@latest add https://foodease-dev-registry.cap.reachcinema.io/r/v1/number-helpers.jsonFunctions
formatNumber
Format a number in a human-readable way with thousands separators, decimal places, and custom prefixes/suffixes.
import { formatNumber } from "@/lib/numberHelpers"
// Basic usage
formatNumber({ number: 123456 })
// Output: "123,456.00"
// Without decimals
formatNumber({ number: 123456, decimalAmount: 0 })
// Output: "123,456"
// Custom delimiter
formatNumber({ number: 123456, delimiter: " " })
// Output: "123 456.00"
// Currency
formatNumber({ number: 1234.56, prefix: "$" })
// Output: "$1,234.56"
// Negative numbers
formatNumber({ number: -1234.56, prefix: "$" })
// Output: "- $1,234.56"Parameters:
interface Config {
number: number | string // The value to format
decimalAmount?: number // Number of decimal places (default: 2)
decimalMark?: string // Decimal indicator (default: ".")
delimiter?: string // Thousands separator (default: ",")
prefix?: string // Text before number (e.g., "$")
suffix?: string // Text after number (e.g., "%")
}Examples:
// US currency
formatNumber({ number: 1234.56, prefix: "$", decimalAmount: 2 })
// "$1,234.56"
// European format
formatNumber({
number: 1234.56,
prefix: "€",
delimiter: ".",
decimalMark: ","
})
// "€1.234,56"
// Percentage
formatNumber({ number: 87.5, suffix: "%", decimalAmount: 1 })
// "87.5%"
// Large numbers
formatNumber({ number: 1000000, decimalAmount: 0 })
// "1,000,000"formatOrdinal
Format a number using SI suffixes (K, M, G, T, P, E) for large numbers.
import { formatOrdinal } from "@/lib/numberHelpers"
formatOrdinal(1000) // "1K"
formatOrdinal(1500) // "2K" (rounded)
formatOrdinal(1500, 1) // "1.5K" (1 decimal)
formatOrdinal(1000000) // "1M"
formatOrdinal(1000000000) // "1G"Parameters:
num: number- The number to formatdigits?: number- Number of decimal places (default: 0)
restrictToNumber
Restrict input to numeric digits only, preserving negative signs.
import { restrictToNumber } from "@/lib/numberHelpers"
restrictToNumber("abc123def") // "123"
restrictToNumber("-123") // "-123"
restrictToNumber("12.34.56") // "123456"
restrictToNumber("$1,234") // "1234"
// No leading zeros
restrictToNumber("0123", true) // "123"Parameters:
value?: string- The input stringnoZero?: boolean- Remove leading zeros (default: false)
Use case: Perfect for PIN keyboards and integer-only inputs.
restrictToNumberAndOneDot
Restrict input to numeric digits and allow one decimal point.
import { restrictToNumberAndOneDot } from "@/lib/numberHelpers"
restrictToNumberAndOneDot("abc12.34def") // "12.34"
restrictToNumberAndOneDot("12.34.56") // "12.3456" (removes extra dots)
restrictToNumberAndOneDot("-123.45") // "-123.45"
restrictToNumberAndOneDot("$1,234.56") // "1234.56"Parameters:
value?: string- The input string
Use case: Ideal for amount keyboards and decimal number inputs.
clamp
Constrain a number to be within a specified range.
import { clamp } from "@/lib/numberHelpers"
clamp(50, 0, 100) // 50
clamp(150, 0, 100) // 100 (clamped to max)
clamp(-10, 0, 100) // 0 (clamped to min)Parameters:
num: number- The number to clamp (default: 0)min: number- Minimum value (default: 0)max: number- Maximum value (default: 0)
formatRank
Format a number as an ordinal rank (1st, 2nd, 3rd, etc.).
import { formatRank } from "@/lib/numberHelpers"
formatRank(1) // "1st"
formatRank(2) // "2nd"
formatRank(3) // "3rd"
formatRank(4) // "4th"
formatRank(11) // "11th"
formatRank(21) // "21st"
formatRank(100) // "100th"Parameters:
number: number- The number to format
Examples
Currency Formatter Component
import { formatNumber } from "@/lib/numberHelpers"
export function Price({ amount }: { amount: number }) {
return (
<span>
{formatNumber({
number: amount,
prefix: "$",
decimalAmount: 2
})}
</span>
)
}
// Usage
<Price amount={1234.56} /> // "$1,234.56"Validated Number Input
import { useState, ChangeEvent } from "react"
import { restrictToNumberAndOneDot } from "@/lib/numberHelpers"
import { Input } from "@/components/ui/input"
export function AmountInput() {
const [value, setValue] = useState("")
const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
const cleaned = restrictToNumberAndOneDot(e.target.value)
setValue(cleaned)
}
return (
<Input
value={value}
onChange={handleChange}
placeholder="0.00"
/>
)
}File Size Formatter
import { formatOrdinal } from "@/lib/numberHelpers"
export function FileSize({ bytes }: { bytes: number }) {
return <span>{formatOrdinal(bytes, 2)}B</span>
}
// Usage
<FileSize bytes={1024} /> // "1KB"
<FileSize bytes={1536} /> // "1.5KB"
<FileSize bytes={1048576} /> // "1MB"Leaderboard Ranks
import { formatRank } from "@/lib/numberHelpers"
export function Leaderboard({ players }) {
return (
<ul>
{players.map((player, index) => (
<li key={player.id}>
<span className="font-semibold">{formatRank(index + 1)}</span>
{" "}{player.name} - {player.score}
</li>
))}
</ul>
)
}Range Slider with Clamp
import { useState } from "react"
import { clamp } from "@/lib/numberHelpers"
export function VolumeControl() {
const [volume, setVolume] = useState(50)
const adjustVolume = (delta: number) => {
setVolume(prev => clamp(prev + delta, 0, 100))
}
return (
<div>
<button onClick={() => adjustVolume(-10)}>-</button>
<span>{volume}%</span>
<button onClick={() => adjustVolume(10)}>+</button>
</div>
)
}Multi-Format Display
import { formatNumber, formatOrdinal, formatRank } from "@/lib/numberHelpers"
export function StatCard({ value, format }: {
value: number
format: "currency" | "ordinal" | "rank"
}) {
const formatted = {
currency: formatNumber({ number: value, prefix: "$", decimalAmount: 2 }),
ordinal: formatOrdinal(value, 1),
rank: formatRank(value),
}[format]
return <div className="stat-value">{formatted}</div>
}Error Handling
formatNumber
Throws an error if:
- Number is not valid (NaN)
- Number exceeds
Number.MAX_SAFE_INTEGER
try {
formatNumber({ number: "invalid" })
} catch (error) {
console.error(error) // "Number is not valid."
}Type Definitions
interface Config {
number: number | string
decimalAmount?: number
decimalMark?: string
delimiter?: string
prefix?: string
suffix?: string
}
function formatNumber(config: Config): string
function formatOrdinal(num: number, digits?: number): string
function restrictToNumber(value?: string, noZero?: boolean): string
function restrictToNumberAndOneDot(value?: string): string
function clamp(num?: number, min?: number, max?: number): number
function formatRank(number: number): stringDependencies
None - pure utility functions with no external dependencies.