or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

dom-events.mddom-utilities.mdfocus-accessibility.mdfunction-utilities.mdindex.mdmath-utilities.mdobject-manipulation.mdreact-utilities.mdresponsive.mdtype-checking.md
tile.json

function-utilities.mddocs/

Function Utilities

Utilities for function composition, conditional execution, event handler management, and control flow patterns. These utilities provide essential patterns for combining multiple functions, handling conditional logic, managing CSS classes, and implementing common functional programming patterns in React applications.

Capabilities

Function Composition

Utilities for combining and composing multiple functions.

/**
 * Combines multiple functions into a single function that calls all of them
 * @param fns - Array of functions to combine (can include undefined values)
 * @returns Combined function that calls all provided functions with the same arguments
 */
function callAll<T extends AnyFunction>(...fns: (T | undefined)[]): (...args: Parameters<T>) => void;

/**
 * Combines multiple event handlers, stopping execution if event.defaultPrevented becomes true
 * @param fns - Array of event handler functions (can include undefined values)
 * @returns Combined event handler that respects defaultPrevented
 */
function callAllHandlers<T extends (event: any) => void>(
  ...fns: (T | undefined)[]
): (event: Parameters<T>[0]) => void;

type AnyFunction<T = any> = (...args: T[]) => any;

Usage Examples:

import { callAll, callAllHandlers } from "@chakra-ui/utils";

// Basic function composition
const log1 = (message: string) => console.log("Log 1:", message);
const log2 = (message: string) => console.log("Log 2:", message);
const log3 = (message: string) => console.log("Log 3:", message);

const logAll = callAll(log1, log2, log3);
logAll("Hello World");
// Output:
// Log 1: Hello World
// Log 2: Hello World
// Log 3: Hello World

// Event handler composition
interface ButtonProps {
  onClick?: (event: React.MouseEvent) => void;
  onAnalyticsClick?: (event: React.MouseEvent) => void;
  onValidationClick?: (event: React.MouseEvent) => void;
}

function SmartButton({ onClick, onAnalyticsClick, onValidationClick, children }: ButtonProps & { children: React.ReactNode }) {
  const handleClick = callAllHandlers(
    onValidationClick,  // Run validation first
    onAnalyticsClick,   // Track analytics
    onClick             // Execute main action
  );
  
  return (
    <button onClick={handleClick}>
      {children}
    </button>
  );
}

// Usage with defaultPrevented
function ValidationButton() {
  const handleValidation = (event: React.MouseEvent) => {
    if (!isFormValid()) {
      event.preventDefault(); // Prevents subsequent handlers from running
      showValidationError();
    }
  };
  
  const handleAnalytics = (event: React.MouseEvent) => {
    console.log("Button clicked"); // Only runs if validation passes
  };
  
  const handleSubmit = (event: React.MouseEvent) => {
    console.log("Submitting form"); // Only runs if validation passes
  };
  
  return (
    <SmartButton
      onValidationClick={handleValidation}
      onAnalyticsClick={handleAnalytics}
      onClick={handleSubmit}
    >
      Submit Form
    </SmartButton>
  );
}

// Cleanup function composition
function useMultipleEffects() {
  React.useEffect(() => {
    const cleanup1 = setupEventListener();
    const cleanup2 = startPolling();
    const cleanup3 = subscribeToWebSocket();
    
    // Combine all cleanup functions
    return callAll(cleanup1, cleanup2, cleanup3);
  }, []);
}

// Higher-order component with composed functionality
function withLogging<P extends object>(
  Component: React.ComponentType<P>
) {
  return function LoggedComponent(props: P & { onMount?: () => void; onUnmount?: () => void }) {
    const { onMount, onUnmount, ...componentProps } = props;
    
    React.useEffect(() => {
      const mountLogger = () => console.log("Component mounted");
      const combinedOnMount = callAll(mountLogger, onMount);
      combinedOnMount();
      
      return () => {
        const unmountLogger = () => console.log("Component unmounted");
        const combinedOnUnmount = callAll(unmountLogger, onUnmount);
        combinedOnUnmount();
      };
    }, [onMount, onUnmount]);
    
    return <Component {...(componentProps as P)} />;
  };
}

Conditional Execution

Utilities for conditional function execution and value resolution.

/**
 * Executes a function if the value is a function, otherwise returns the value
 * @param valueOrFn - Either a value or a function that returns a value
 * @param args - Arguments to pass to the function if valueOrFn is a function
 * @returns The resolved value
 */
function runIfFn<T, U>(valueOrFn: T | ((...fnArgs: U[]) => T), ...args: U[]): T;

Usage Examples:

import { runIfFn } from "@chakra-ui/utils";

// Basic conditional execution
const staticValue = "Hello World";
const dynamicValue = (name: string) => `Hello ${name}`;

const result1 = runIfFn(staticValue);              // "Hello World"
const result2 = runIfFn(dynamicValue, "Alice");    // "Hello Alice"

// React component with flexible props
interface FlexibleComponentProps {
  content: React.ReactNode | ((props: { isActive: boolean }) => React.ReactNode);
  title: string | ((isLong: boolean) => string);
  isActive?: boolean;
}

function FlexibleComponent({ content, title, isActive = false }: FlexibleComponentProps) {
  const resolvedTitle = runIfFn(title, title.length > 20);
  const resolvedContent = runIfFn(content, { isActive });
  
  return (
    <div className={cx("flexible-component", isActive && "flexible-component--active")}>
      <h2>{resolvedTitle}</h2>
      <div>{resolvedContent}</div>
    </div>
  );
}

// Usage
<FlexibleComponent
  title={(isLong) => isLong ? "Very Long Title (Shortened)" : "Very Long Title That Should Be Shortened"}
  content={({ isActive }) => (
    <p>
      This content adapts to state: {isActive ? "Active" : "Inactive"}
    </p>
  )}
  isActive={true}
/>

// Theme configuration with dynamic values
interface ThemeConfig {
  colors: Record<string, string | ((mode: "light" | "dark") => string)>;
  spacing: Record<string, string | number | ((scale: number) => string)>;
}

function resolveTheme(config: ThemeConfig, mode: "light" | "dark", scale = 1) {
  return {
    colors: Object.fromEntries(
      Object.entries(config.colors).map(([key, value]) => [
        key,
        runIfFn(value, mode)
      ])
    ),
    spacing: Object.fromEntries(
      Object.entries(config.spacing).map(([key, value]) => [
        key,
        runIfFn(value, scale)
      ])
    )
  };
}

const themeConfig: ThemeConfig = {
  colors: {
    background: (mode) => mode === "light" ? "#ffffff" : "#000000",
    text: (mode) => mode === "light" ? "#000000" : "#ffffff",
    primary: "#007bff" // Static value
  },
  spacing: {
    sm: (scale) => `${8 * scale}px`,
    md: (scale) => `${16 * scale}px`,
    lg: 24 // Static value
  }
};

const lightTheme = resolveTheme(themeConfig, "light", 1);
const darkTheme = resolveTheme(themeConfig, "dark", 1.2);

// Conditional styling hook
function useConditionalStyles<T>(
  styles: T | ((props: any) => T),
  props: any
): T {
  return React.useMemo(() => runIfFn(styles, props), [styles, props]);
}

// Usage in component
interface StyledBoxProps {
  variant?: "primary" | "secondary";
  size?: "sm" | "md" | "lg";
  isDisabled?: boolean;
}

const boxStyles = (props: StyledBoxProps) => ({
  padding: props.size === "sm" ? "8px" : props.size === "lg" ? "24px" : "16px",
  backgroundColor: props.variant === "primary" ? "#007bff" : "#6c757d",
  opacity: props.isDisabled ? 0.5 : 1,
  cursor: props.isDisabled ? "not-allowed" : "pointer"
});

function StyledBox(props: StyledBoxProps & { children: React.ReactNode }) {
  const styles = useConditionalStyles(boxStyles, props);
  
  return (
    <div style={styles}>
      {props.children}
    </div>
  );
}

CSS Class Management

Utility for combining CSS class names with conditional logic.

/**
 * Combines class names, filtering out falsy values
 * @param classNames - Variable number of class name arguments (strings, booleans, objects, etc.)
 * @returns Combined class name string with falsy values filtered out
 */
function cx(...classNames: any[]): string;

Usage Examples:

import { cx } from "@chakra-ui/utils";

// Basic class combination
const className1 = cx("btn", "btn-primary");                    // "btn btn-primary"
const className2 = cx("card", false && "card-active", "shadow"); // "card shadow"
const className3 = cx("text", null, undefined, "bold");         // "text bold"

// Conditional classes
interface ButtonProps {
  variant?: "primary" | "secondary" | "ghost";
  size?: "sm" | "md" | "lg";
  isActive?: boolean;
  isDisabled?: boolean;
  isLoading?: boolean;
  className?: string;
}

function Button({ 
  variant = "primary", 
  size = "md", 
  isActive, 
  isDisabled, 
  isLoading,
  className,
  children 
}: ButtonProps & { children: React.ReactNode }) {
  const buttonClassName = cx(
    "btn",                                    // Base class
    `btn--${variant}`,                        // Variant class
    `btn--${size}`,                          // Size class
    isActive && "btn--active",               // Conditional classes
    isDisabled && "btn--disabled",
    isLoading && "btn--loading",
    className                                // User-provided class
  );
  
  return (
    <button 
      className={buttonClassName}
      disabled={isDisabled || isLoading}
    >
      {isLoading ? "Loading..." : children}
    </button>
  );
}

// Advanced conditional styling
interface CardProps {
  elevation?: 0 | 1 | 2 | 3;
  padding?: "none" | "sm" | "md" | "lg";
  border?: boolean;
  rounded?: boolean;
  interactive?: boolean;
  selected?: boolean;
  error?: boolean;
  className?: string;
}

function Card({ 
  elevation = 1,
  padding = "md",
  border = false,
  rounded = true,
  interactive = false,
  selected = false,
  error = false,
  className,
  children 
}: CardProps & { children: React.ReactNode }) {
  return (
    <div
      className={cx(
        "card",
        elevation > 0 && `card--elevation-${elevation}`,
        padding !== "none" && `card--padding-${padding}`,
        border && "card--bordered",
        rounded && "card--rounded",
        interactive && "card--interactive",
        selected && "card--selected",
        error && "card--error",
        className
      )}
    >
      {children}
    </div>
  );
}

// Dynamic class generation with objects
function generateClasses(props: Record<string, any>, classMap: Record<string, string>) {
  const classes = Object.entries(props)
    .filter(([key, value]) => value && classMap[key])
    .map(([key]) => classMap[key]);
  
  return cx(...classes);
}

// Usage with class mapping
const alertClassMap = {
  success: "alert--success",
  warning: "alert--warning", 
  error: "alert--error",
  info: "alert--info",
  dismissible: "alert--dismissible",
  centered: "alert--centered"
};

interface AlertProps {
  success?: boolean;
  warning?: boolean;
  error?: boolean;
  info?: boolean;
  dismissible?: boolean;
  centered?: boolean;
  className?: string;
}

function Alert(props: AlertProps & { children: React.ReactNode }) {
  const { children, className, ...flagProps } = props;
  const alertClasses = generateClasses(flagProps, alertClassMap);
  
  return (
    <div className={cx("alert", alertClasses, className)}>
      {children}
    </div>
  );
}

// CSS Modules integration
import styles from "./Component.module.css";

function ModularComponent({ isActive, size, className }: any) {
  return (
    <div
      className={cx(
        styles.component,                    // CSS Module class
        styles[`component--${size}`],        // Dynamic CSS Module class
        isActive && styles["component--active"],
        className                           // External class
      )}
    >
      Content
    </div>
  );
}

// Utility for styled-components or emotion
const createStyledClasses = (baseClass: string) => {
  return {
    base: baseClass,
    with: (...modifiers: (string | boolean | undefined | null)[]) => {
      return cx(baseClass, ...modifiers);
    }
  };
};

const buttonClasses = createStyledClasses("btn");
const primaryButton = buttonClasses.with("btn--primary", true && "btn--active");
// Result: "btn btn--primary btn--active"

Lazy Evaluation

Utilities for lazy loading and conditional rendering patterns.

/**
 * Determines if disclosure content should render based on lazy loading mode
 * @param options - Lazy loading configuration options
 * @returns true if content should render
 */
function lazyDisclosure(options: LazyOptions): boolean;

interface LazyOptions {
  wasSelected?: boolean;
  isSelected?: boolean;
  mode?: LazyMode;
}

type LazyMode = "unmount" | "keepMounted";

Usage Examples:

import { lazyDisclosure } from "@chakra-ui/utils";

// Lazy tab content
function LazyTabs({ activeTab, mode = "unmount" }: { activeTab: number; mode?: LazyMode }) {
  const [visitedTabs, setVisitedTabs] = React.useState(new Set([activeTab]));
  
  React.useEffect(() => {
    setVisitedTabs(prev => new Set([...prev, activeTab]));
  }, [activeTab]);
  
  const tabs = [
    { title: "Overview", content: <OverviewContent /> },
    { title: "Details", content: <DetailsContent /> },
    { title: "Settings", content: <SettingsContent /> }
  ];
  
  return (
    <div className="lazy-tabs">
      <div className="tab-list">
        {tabs.map((tab, index) => (
          <button
            key={index}
            className={cx("tab", index === activeTab && "tab--active")}
            onClick={() => setActiveTab(index)}
          >
            {tab.title}
          </button>
        ))}
      </div>
      
      <div className="tab-content">
        {tabs.map((tab, index) => {
          const shouldRender = lazyDisclosure({
            wasSelected: visitedTabs.has(index),
            isSelected: index === activeTab,
            mode
          });
          
          if (!shouldRender) return null;
          
          return (
            <div
              key={index}
              className={cx("tab-panel", index === activeTab && "tab-panel--active")}
              style={{ display: index === activeTab ? "block" : "none" }}
            >
              {tab.content}
            </div>
          );
        })}
      </div>
    </div>
  );
}

// Lazy accordion
function LazyAccordion({ items, mode = "unmount" }: { items: AccordionItem[]; mode?: LazyMode }) {
  const [openItems, setOpenItems] = React.useState(new Set<number>());
  const [visitedItems, setVisitedItems] = React.useState(new Set<number>());
  
  const toggleItem = (index: number) => {
    setOpenItems(prev => {
      const newSet = new Set(prev);
      if (newSet.has(index)) {
        newSet.delete(index);
      } else {
        newSet.add(index);
        setVisitedItems(visited => new Set([...visited, index]));
      }
      return newSet;
    });
  };
  
  return (
    <div className="lazy-accordion">
      {items.map((item, index) => {
        const isOpen = openItems.has(index);
        const shouldRenderContent = lazyDisclosure({
          wasSelected: visitedItems.has(index),
          isSelected: isOpen,
          mode
        });
        
        return (
          <div key={index} className="accordion-item">
            <button
              className="accordion-header"
              onClick={() => toggleItem(index)}
              aria-expanded={isOpen}
            >
              {item.title}
            </button>
            
            {shouldRenderContent && (
              <div 
                className={cx("accordion-content", isOpen && "accordion-content--open")}
                style={{ display: isOpen ? "block" : "none" }}
              >
                {item.content}
              </div>
            )}
          </div>
        );
      })}
    </div>
  );
}

Warning Utilities

Development-time warning utilities for debugging and validation.

/**
 * Displays a console warning in development mode based on a condition
 * @param options - Warning configuration
 */
function warn(options: WarnOptions): void;

interface WarnOptions {
  condition: boolean;
  message: string;
}

Usage Examples:

import { warn } from "@chakra-ui/utils";

// Development warnings for prop validation
interface ComponentProps {
  children: React.ReactNode;
  size?: "sm" | "md" | "lg";
  variant?: "primary" | "secondary";
}

function ValidatedComponent({ children, size = "md", variant = "primary" }: ComponentProps) {
  // Warn about deprecated combinations
  warn({
    condition: size === "sm" && variant === "secondary",
    message: "Small secondary variant is deprecated and will be removed in v2.0. Use primary variant instead."
  });
  
  // Warn about missing required props
  warn({
    condition: !children,
    message: "ValidatedComponent requires children prop to render properly."
  });
  
  return (
    <div className={cx("component", `component--${size}`, `component--${variant}`)}>
      {children}
    </div>
  );
}

// Hook with validation warnings
function useLocalStorage(key: string, defaultValue: any) {
  warn({
    condition: typeof key !== "string" || key.length === 0,
    message: "useLocalStorage: key must be a non-empty string"
  });
  
  warn({
    condition: typeof window === "undefined",
    message: "useLocalStorage: localStorage is not available in server-side rendering"
  });
  
  const [value, setValue] = React.useState(() => {
    try {
      const item = window?.localStorage?.getItem(key);
      return item ? JSON.parse(item) : defaultValue;
    } catch (error) {
      warn({
        condition: true,
        message: `useLocalStorage: Failed to parse localStorage value for key "${key}"`
      });
      return defaultValue;
    }
  });
  
  const setStoredValue = (newValue: any) => {
    try {
      setValue(newValue);
      window?.localStorage?.setItem(key, JSON.stringify(newValue));
    } catch (error) {
      warn({
        condition: true,
        message: `useLocalStorage: Failed to set localStorage value for key "${key}"`
      });
    }
  };
  
  return [value, setStoredValue];
}

Component Utilities

Utilities for component lifecycle management and module interoperability.

/**
 * Determines whether the children of a disclosure widget should be rendered based on lazy behavior
 * @param options - Configuration options for lazy disclosure
 * @returns true if content should be rendered
 */
function lazyDisclosure(options: LazyOptions): boolean;

/**
 * Ensures proper ES module interoperability by returning the default export or the module itself
 * @param mod - Module to process
 * @returns The default export or the module
 */
function interopDefault<T>(mod: T): T;

interface LazyOptions {
  enabled?: boolean;
  isSelected?: boolean;
  wasSelected?: boolean;
  mode?: LazyMode;
}

type LazyMode = "unmount" | "keepMounted";

Usage Examples:

import { lazyDisclosure, interopDefault } from "@chakra-ui/utils";

// Lazy loading for tabs
function TabPanel({ 
  children, 
  isSelected, 
  wasSelected, 
  isLazy = false 
}: TabPanelProps) {
  const shouldRender = lazyDisclosure({
    enabled: isLazy,
    isSelected,
    wasSelected,
    mode: "keepMounted"
  });
  
  if (!shouldRender) {
    return null;
  }
  
  return <div role="tabpanel">{children}</div>;
}

// Accordion with lazy content
function AccordionItem({ 
  isExpanded, 
  wasExpanded, 
  children, 
  isLazy = true 
}: AccordionItemProps) {
  const shouldRender = lazyDisclosure({
    enabled: isLazy,
    isSelected: isExpanded,
    wasSelected: wasExpanded,
    mode: "unmount" // Unmount when collapsed
  });
  
  return (
    <div>
      <button>Toggle</button>
      {shouldRender && (
        <div className="accordion-content">
          {children}
        </div>
      )}
    </div>
  );
}

// Module interoperability
async function loadComponent() {
  const module = await import("./SomeComponent");
  const Component = interopDefault(module);
  return Component;
}