Utility Functions Reference
Complete reference for all FoundryKit utility functions
Utility Functions Reference
Complete reference for all FoundryKit utility functions, organized by category with detailed usage examples.
Class Name Utilities
cn
Conditionally join class names together. A powerful utility for handling dynamic class names.
import { cn } from '@foundrykit/utils'
// Basic usage
const className = cn('base-class', 'additional-class')
// Result: "base-class additional-class"
// Conditional classes
const buttonClass = cn(
'btn',
{
'btn-primary': variant === 'primary',
'btn-secondary': variant === 'secondary',
'btn-disabled': disabled
}
)
// With arrays
const cardClass = cn([
'card',
'shadow',
{ 'card-elevated': elevated }
])
// Complex example
const complexClass = cn(
'component',
size && `component-${size}`,
{
'component-active': isActive,
'component-loading': isLoading
},
className // Allow external className override
)
Parameters:
...inputs: ClassValue[]
- Class values to join
Returns:
string
- Joined class names
clsx
Alternative class name utility with different API.
import { clsx } from '@foundrykit/utils'
const className = clsx({
'btn': true,
'btn-primary': isPrimary,
'btn-large': size === 'large'
})
Date Utilities
formatDate
Format dates with customizable patterns.
import { formatDate } from '@foundrykit/utils'
const date = new Date('2024-01-15T10:30:00Z')
// Common formats
formatDate(date, 'MMM dd, yyyy') // "Jan 15, 2024"
formatDate(date, 'yyyy-MM-dd') // "2024-01-15"
formatDate(date, 'dd/MM/yyyy') // "15/01/2024"
formatDate(date, 'EEEE, MMMM do, yyyy') // "Monday, January 15th, 2024"
// Time formats
formatDate(date, 'HH:mm:ss') // "10:30:00"
formatDate(date, 'h:mm a') // "10:30 AM"
// Combined formats
formatDate(date, 'MMM dd, yyyy \'at\' h:mm a') // "Jan 15, 2024 at 10:30 AM"
Parameters:
date: Date | string | number
- Date to formatformat: string
- Format patternoptions?: { locale?: string }
- Formatting options
Returns:
string
- Formatted date string
parseDate
Parse date strings with specified format.
import { parseDate } from '@foundrykit/utils'
// Parse with format
const date1 = parseDate('2024-01-15', 'yyyy-MM-dd')
const date2 = parseDate('Jan 15, 2024', 'MMM dd, yyyy')
const date3 = parseDate('15/01/2024 10:30', 'dd/MM/yyyy HH:mm')
// With validation
const date4 = parseDate('invalid-date', 'yyyy-MM-dd') // Returns null
Parameters:
dateString: string
- Date string to parseformat: string
- Expected format patternoptions?: { strict?: boolean }
- Parsing options
Returns:
Date | null
- Parsed date or null if invalid
isValidDate
Check if a value is a valid date.
import { isValidDate } from '@foundrykit/utils'
isValidDate(new Date()) // true
isValidDate('2024-01-15') // true
isValidDate('invalid') // false
isValidDate(null) // false
getRelativeTime
Get relative time string (e.g., "2 hours ago").
import { getRelativeTime } from '@foundrykit/utils'
const now = new Date()
const pastDate = new Date(now.getTime() - 3600000) // 1 hour ago
getRelativeTime(pastDate) // "1 hour ago"
getRelativeTime(pastDate, now) // "1 hour ago"
// Future dates
const futureDate = new Date(now.getTime() + 3600000)
getRelativeTime(futureDate) // "in 1 hour"
Parameters:
date: Date
- Date to comparebaseDate?: Date
- Base date for comparison (defaults to now)options?: { locale?: string }
- Formatting options
Returns:
string
- Relative time string
Function Utilities
debounce
Create a debounced function that delays execution until after a specified delay.
import { debounce } from '@foundrykit/utils'
// Basic debouncing
const debouncedSearch = debounce((query: string) => {
performSearch(query)
}, 300)
// With options
const debouncedSave = debounce(
(data: any) => saveData(data),
1000,
{
leading: true, // Execute immediately on first call
trailing: false // Don't execute after delay
}
)
// Cancel debounced function
debouncedSearch.cancel()
// Flush immediately
debouncedSearch.flush()
Parameters:
func: Function
- Function to debouncedelay: number
- Delay in millisecondsoptions?: DebounceOptions
- Debounce options
Returns:
DebouncedFunction
- Debounced function with cancel/flush methods
throttle
Create a throttled function that executes at most once per specified interval.
import { throttle } from '@foundrykit/utils'
// Basic throttling
const throttledScroll = throttle(() => {
updateScrollPosition()
}, 100)
// With options
const throttledResize = throttle(
() => handleResize(),
250,
{
leading: true, // Execute immediately on first call
trailing: false // Don't execute after interval
}
)
// Cancel throttled function
throttledScroll.cancel()
Parameters:
func: Function
- Function to throttleinterval: number
- Interval in millisecondsoptions?: ThrottleOptions
- Throttle options
Returns:
ThrottledFunction
- Throttled function with cancel method
once
Create a function that executes only once.
import { once } from '@foundrykit/utils'
const initialize = once(() => {
console.log('Initializing...')
setupApplication()
})
initialize() // Logs "Initializing..." and runs setup
initialize() // Does nothing
initialize() // Does nothing
Parameters:
func: Function
- Function to execute once
Returns:
Function
- Function that executes only once
memoize
Create a memoized function that caches results based on arguments.
import { memoize } from '@foundrykit/utils'
// Basic memoization
const memoizedCalculation = memoize((x: number, y: number) => {
console.log('Calculating...') // Only logs on first call with same args
return x * y
})
memoizedCalculation(5, 10) // Logs "Calculating..." returns 50
memoizedCalculation(5, 10) // Returns 50 (cached)
// With custom key resolver
const memoizedFetch = memoize(
async (url: string) => {
const response = await fetch(url)
return response.json()
},
{
resolver: (url: string) => url // Custom cache key
}
)
// Clear cache
memoizedCalculation.cache.clear()
Parameters:
func: Function
- Function to memoizeoptions?: MemoizeOptions
- Memoization options
Returns:
MemoizedFunction
- Memoized function with cache property
Object Utilities
pick
Create a new object with only the specified properties.
import { pick } from '@foundrykit/utils'
const user = {
id: 1,
name: 'John Doe',
email: 'john@example.com',
password: 'secret',
role: 'admin'
}
// Pick specific properties
const publicUser = pick(user, ['id', 'name', 'email'])
// Result: { id: 1, name: 'John Doe', email: 'john@example.com' }
// Pick with array of keys
const userInfo = pick(user, ['name', 'role'])
// Result: { name: 'John Doe', role: 'admin' }
Parameters:
object: Record<string, any>
- Source objectkeys: string[]
- Keys to pick
Returns:
Record<string, any>
- New object with picked properties
omit
Create a new object without the specified properties.
import { omit } from '@foundrykit/utils'
const user = {
id: 1,
name: 'John Doe',
email: 'john@example.com',
password: 'secret',
apiKey: 'key123'
}
// Omit sensitive data
const safeUser = omit(user, ['password', 'apiKey'])
// Result: { id: 1, name: 'John Doe', email: 'john@example.com' }
Parameters:
object: Record<string, any>
- Source objectkeys: string[]
- Keys to omit
Returns:
Record<string, any>
- New object without omitted properties
deepMerge
Recursively merge objects.
import { deepMerge } from '@foundrykit/utils'
const defaults = {
theme: {
colors: {
primary: '#blue',
secondary: '#gray'
},
spacing: {
small: '8px',
medium: '16px'
}
},
features: {
darkMode: false
}
}
const userConfig = {
theme: {
colors: {
primary: '#red' // Override primary color
},
spacing: {
large: '32px' // Add large spacing
}
}
}
const config = deepMerge(defaults, userConfig)
// Result: Merged configuration with user overrides
Parameters:
target: Record<string, any>
- Target object...sources: Record<string, any>[]
- Source objects to merge
Returns:
Record<string, any>
- Deeply merged object
isEqual
Deep equality comparison for objects and arrays.
import { isEqual } from '@foundrykit/utils'
const obj1 = { a: 1, b: { c: 2 } }
const obj2 = { a: 1, b: { c: 2 } }
const obj3 = { a: 1, b: { c: 3 } }
isEqual(obj1, obj2) // true
isEqual(obj1, obj3) // false
// Works with arrays
const arr1 = [1, 2, { a: 3 }]
const arr2 = [1, 2, { a: 3 }]
isEqual(arr1, arr2) // true
Parameters:
a: any
- First valueb: any
- Second value
Returns:
boolean
- True if values are deeply equal
isEmpty
Check if a value is empty (null, undefined, empty string, array, or object).
import { isEmpty } from '@foundrykit/utils'
isEmpty(null) // true
isEmpty(undefined) // true
isEmpty('') // true
isEmpty([]) // true
isEmpty({}) // true
isEmpty(' ') // false (whitespace)
isEmpty([1]) // false
isEmpty({ a: 1 }) // false
Parameters:
value: any
- Value to check
Returns:
boolean
- True if value is empty
Array Utilities
unique
Remove duplicate items from an array.
import { unique } from '@foundrykit/utils'
// Basic deduplication
const numbers = [1, 2, 2, 3, 3, 4]
const uniqueNumbers = unique(numbers)
// Result: [1, 2, 3, 4]
// Object deduplication by property
const users = [
{ id: 1, name: 'John' },
{ id: 2, name: 'Jane' },
{ id: 1, name: 'John' } // Duplicate
]
const uniqueUsers = unique(users, 'id')
// Result: [{ id: 1, name: 'John' }, { id: 2, name: 'Jane' }]
// Custom key function
const uniqueByName = unique(users, user => user.name.toLowerCase())
Parameters:
array: T[]
- Array to deduplicatekey?: string | ((item: T) => any)
- Key or function to determine uniqueness
Returns:
T[]
- Array with duplicates removed
groupBy
Group array items by a property or function result.
import { groupBy } from '@foundrykit/utils'
const users = [
{ name: 'John', department: 'Engineering' },
{ name: 'Jane', department: 'Design' },
{ name: 'Bob', department: 'Engineering' },
{ name: 'Alice', department: 'Design' }
]
// Group by property
const byDepartment = groupBy(users, 'department')
// Result: {
// Engineering: [{ name: 'John', ... }, { name: 'Bob', ... }],
// Design: [{ name: 'Jane', ... }, { name: 'Alice', ... }]
// }
// Group by function
const byFirstLetter = groupBy(users, user => user.name[0])
// Result: { J: [John, Jane], B: [Bob], A: [Alice] }
Parameters:
array: T[]
- Array to groupkey: string | ((item: T) => string)
- Property or function for grouping
Returns:
Record<string, T[]>
- Grouped object
sortBy
Sort array by property or function result.
import { sortBy } from '@foundrykit/utils'
const products = [
{ name: 'Laptop', price: 999 },
{ name: 'Phone', price: 699 },
{ name: 'Tablet', price: 499 }
]
// Sort by property
const byPrice = sortBy(products, 'price')
// Result: [Tablet, Phone, Laptop] (ascending)
// Sort by function
const byNameLength = sortBy(products, product => product.name.length)
// Descending order
const byPriceDesc = sortBy(products, 'price').reverse()
Parameters:
array: T[]
- Array to sortkey: string | ((item: T) => any)
- Property or function for sorting
Returns:
T[]
- Sorted array
chunk
Split array into chunks of specified size.
import { chunk } from '@foundrykit/utils'
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
const chunks = chunk(numbers, 3)
// Result: [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]
const pairs = chunk(numbers, 2)
// Result: [[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]
Parameters:
array: T[]
- Array to chunksize: number
- Chunk size
Returns:
T[][]
- Array of chunks
flatten
Flatten nested arrays.
import { flatten } from '@foundrykit/utils'
// Single level flattening
const nested = [[1, 2], [3, 4], [5]]
const flat = flatten(nested)
// Result: [1, 2, 3, 4, 5]
// Deep flattening
const deepNested = [1, [2, [3, [4, 5]]]]
const deepFlat = flatten(deepNested, true) // Deep flatten
// Result: [1, 2, 3, 4, 5]
Parameters:
array: any[]
- Array to flattendeep?: boolean
- Whether to flatten deeply
Returns:
any[]
- Flattened array
String Utilities
capitalize
Capitalize the first letter of a string.
import { capitalize } from '@foundrykit/utils'
capitalize('hello world') // "Hello world"
capitalize('HELLO WORLD') // "Hello world"
capitalize('hello') // "Hello"
camelCase
Convert string to camelCase.
import { camelCase } from '@foundrykit/utils'
camelCase('hello world') // "helloWorld"
camelCase('hello-world') // "helloWorld"
camelCase('hello_world') // "helloWorld"
camelCase('Hello World') // "helloWorld"
kebabCase
Convert string to kebab-case.
import { kebabCase } from '@foundrykit/utils'
kebabCase('helloWorld') // "hello-world"
kebabCase('Hello World') // "hello-world"
kebabCase('hello_world') // "hello-world"
truncate
Truncate string to specified length with ellipsis.
import { truncate } from '@foundrykit/utils'
const longText = "This is a very long text that needs to be truncated"
truncate(longText, 20) // "This is a very lo..."
truncate(longText, 20, { suffix: ' [more]' }) // "This is a very lo [more]"
truncate(longText, 100) // Original text (shorter than limit)
Parameters:
text: string
- Text to truncatelength: number
- Maximum lengthoptions?: { suffix?: string }
- Truncation options
Returns:
string
- Truncated text
slugify
Create URL-friendly slugs from strings.
import { slugify } from '@foundrykit/utils'
slugify('Hello World!') // "hello-world"
slugify('Hello World! 123') // "hello-world-123"
slugify('Special @#$ Characters') // "special-characters"
slugify('Multiple Spaces') // "multiple-spaces"
Parameters:
text: string
- Text to slugifyoptions?: { separator?: string, lowercase?: boolean }
- Slug options
Returns:
string
- URL-friendly slug
Validation Utilities
isEmail
Validate email addresses.
import { isEmail } from '@foundrykit/utils'
isEmail('user@example.com') // true
isEmail('user.name+tag@example.com') // true
isEmail('invalid-email') // false
isEmail('user@') // false
isUrl
Validate URLs.
import { isUrl } from '@foundrykit/utils'
isUrl('https://example.com') // true
isUrl('http://localhost:3000') // true
isUrl('ftp://files.example.com') // true
isUrl('not-a-url') // false
isPhoneNumber
Validate phone numbers.
import { isPhoneNumber } from '@foundrykit/utils'
isPhoneNumber('+1-555-123-4567') // true
isPhoneNumber('(555) 123-4567') // true
isPhoneNumber('555.123.4567') // true
isPhoneNumber('invalid') // false
isValidJSON
Validate JSON strings.
import { isValidJSON } from '@foundrykit/utils'
isValidJSON('{"key": "value"}') // true
isValidJSON('[1, 2, 3]') // true
isValidJSON('invalid json') // false
validateSchema
Validate objects against a schema.
import { validateSchema } from '@foundrykit/utils'
const schema = {
name: { type: 'string', required: true, minLength: 2 },
age: { type: 'number', required: true, min: 0, max: 120 },
email: { type: 'string', required: false, validator: isEmail }
}
const data = {
name: 'John',
age: 30,
email: 'john@example.com'
}
const validation = validateSchema(data, schema)
// Result: { isValid: true, errors: {} }
const invalidData = {
name: 'J', // Too short
age: 150, // Too high
email: 'invalid-email'
}
const invalidValidation = validateSchema(invalidData, schema)
// Result: { isValid: false, errors: { name: '...', age: '...', email: '...' } }
Storage Utilities
localStorageGet
Safely get items from localStorage with JSON parsing.
import { localStorageGet } from '@foundrykit/utils'
// Get string value
const theme = localStorageGet('theme', 'light')
// Get object value
const user = localStorageGet('user', { name: '', email: '' })
// Get with type safety
const settings = localStorageGet<{ darkMode: boolean }>('settings', { darkMode: false })
localStorageSet
Safely set items to localStorage with JSON serialization.
import { localStorageSet } from '@foundrykit/utils'
// Set string value
localStorageSet('theme', 'dark')
// Set object value
localStorageSet('user', { name: 'John', email: 'john@example.com' })
localStorageRemove
Remove items from localStorage.
import { localStorageRemove } from '@foundrykit/utils'
localStorageRemove('theme')
localStorageRemove(['user', 'settings']) // Remove multiple items
URL Utilities
getQueryParams
Parse URL query parameters.
import { getQueryParams } from '@foundrykit/utils'
// From current URL
const params = getQueryParams()
// From specific URL
const params2 = getQueryParams('https://example.com?name=John&age=30')
// Result: { name: 'John', age: '30' }
buildUrl
Build URLs with query parameters.
import { buildUrl } from '@foundrykit/utils'
const url = buildUrl('https://api.example.com/users', {
page: 1,
limit: 10,
search: 'john'
})
// Result: "https://api.example.com/users?page=1&limit=10&search=john"
Next Steps
- Learn about common patterns for effective usage
- Review performance tips for optimization
- Check out best practices for optimal usage