FoundryKit

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 format
  • format: string - Format pattern
  • options?: { 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 parse
  • format: string - Expected format pattern
  • options?: { 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 compare
  • baseDate?: 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 debounce
  • delay: number - Delay in milliseconds
  • options?: 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 throttle
  • interval: number - Interval in milliseconds
  • options?: 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 memoize
  • options?: 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 object
  • keys: 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 object
  • keys: 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 value
  • b: 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 deduplicate
  • key?: 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 group
  • key: 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 sort
  • key: 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 chunk
  • size: 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 flatten
  • deep?: 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 truncate
  • length: number - Maximum length
  • options?: { 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 slugify
  • options?: { 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