JSPM

@tuel/performance

1.1.2
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 146
  • Score
    100M100P100Q52850F
  • License MIT

Specialized performance utilities for animations, reduced motion, and optimization controls

Package Exports

  • @tuel/performance

Readme

@tuel/performance

Specialized performance utilities for animations, reduced motion support, and optimization controls.

npm version TypeScript License: MIT

Features

  • Accessibility First - Automatic prefers-reduced-motion detection
  • 🎯 Frame Control - RequestAnimationFrame management and throttling
  • 📊 Performance Monitoring - Track FPS and animation performance
  • 🔧 Optimization Hooks - Intersection Observer, memoization, and callbacks
  • 🚀 Zero Config - Works out of the box with sensible defaults
  • 🌳 Tree-shakeable - Import only what you need

Installation

pnpm add @tuel/performance

# Peer dependencies
pnpm add react react-dom framer-motion

Quick Start

Reduced Motion Support

import { useReducedMotion, ReducedMotionWrapper } from '@tuel/performance';

function AnimatedComponent() {
  const shouldReduceMotion = useReducedMotion();

  return (
    <div 
      style={{ 
        transition: shouldReduceMotion ? 'none' : 'all 0.3s ease' 
      }}
    >
      {/* Your content */}
    </div>
  );
}

// Or use the wrapper component
function App() {
  return (
    <ReducedMotionWrapper>
      {(prefersReducedMotion) => (
        <div>Motion reduced: {prefersReducedMotion ? 'Yes' : 'No'}</div>
      )}
    </ReducedMotionWrapper>
  );
}

API Reference

Reduced Motion Hooks

useReducedMotion()

Detects if user prefers reduced motion.

const shouldReduceMotion = useReducedMotion();

if (shouldReduceMotion) {
  // Disable or simplify animations
}

useSafeAnimation(duration, options)

Returns safe animation duration based on reduced motion preference.

const duration = useSafeAnimation(1000); // Returns 0 if reduced motion is preferred

<motion.div
  animate={{ opacity: 1 }}
  transition={{ duration: duration / 1000 }}
/>

useSafeDuration(duration)

Simplified version that returns 0 for reduced motion or original duration.

const duration = useSafeDuration(500); // 500ms or 0ms

isReducedMotionPreferred()

Utility function to check reduced motion preference (non-hook).

if (isReducedMotionPreferred()) {
  console.log('User prefers reduced motion');
}

withReducedMotion(Component)

HOC that passes reduced motion state to component.

const SafeAnimatedComponent = withReducedMotion(MyComponent);

// MyComponent receives prefersReducedMotion prop
function MyComponent({ prefersReducedMotion }) {
  return <div>{/* ... */}</div>;
}

Frame Control

useFrameControl(options)

Advanced RequestAnimationFrame management.

import { useFrameControl } from '@tuel/performance';

function AnimationComponent() {
  const { start, stop, stats } = useFrameControl({
    fps: 60,
    onFrame: (timestamp, frameCount) => {
      console.log('Frame:', frameCount);
    },
    onFpsUpdate: (currentFps) => {
      console.log('FPS:', currentFps);
    }
  });

  return (
    <div>
      <button onClick={start}>Start Animation</button>
      <button onClick={stop}>Stop Animation</button>
      <div>FPS: {stats.fps}</div>
    </div>
  );
}

Options:

  • fps?: number - Target frames per second (default: 60)
  • onFrame?: (timestamp: number, frameCount: number) => void
  • onFpsUpdate?: (fps: number) => void

Returns:

  • start: () => void - Start the animation loop
  • stop: () => void - Stop the animation loop
  • stats: FrameStats - Current frame statistics

useThrottledFrame(callback, fps)

Throttled RAF callback at specific FPS.

import { useThrottledFrame } from '@tuel/performance';

function ScrollAnimation() {
  useThrottledFrame((timestamp) => {
    // Called at most 30 times per second
    updateScrollAnimation(timestamp);
  }, 30);

  return <div>{/* ... */}</div>;
}

Optimization Hooks

useOptimizedIntersection(ref, options)

Optimized Intersection Observer hook.

import { useOptimizedIntersection } from '@tuel/performance';

function LazyComponent() {
  const ref = useRef(null);
  const isVisible = useOptimizedIntersection(ref, {
    threshold: 0.5,
    rootMargin: '100px',
  });

  return (
    <div ref={ref}>
      {isVisible && <ExpensiveComponent />}
    </div>
  );
}

useOptimizedCallback(callback, deps)

Memoized callback with performance optimization.

import { useOptimizedCallback } from '@tuel/performance';

function Component() {
  const handleClick = useOptimizedCallback(() => {
    // Expensive operation
    processData();
  }, []);

  return <button onClick={handleClick}>Click</button>;
}

useOptimizedMemo(factory, deps)

Optimized memoization hook.

import { useOptimizedMemo } from '@tuel/performance';

function DataComponent({ items }) {
  const processedData = useOptimizedMemo(
    () => expensiveCalculation(items),
    [items]
  );

  return <div>{processedData}</div>;
}

usePerformanceMonitor(options)

Monitor component rendering performance.

import { usePerformanceMonitor } from '@tuel/performance';

function PerformanceSensitiveComponent() {
  const metrics = usePerformanceMonitor({
    component: 'MyComponent',
    logToConsole: true,
  });

  return (
    <div>
      <div>Render count: {metrics.renderCount}</div>
      <div>Avg render time: {metrics.avgRenderTime}ms</div>
    </div>
  );
}

Usage Examples

Complete Animation with Performance Controls

import { 
  useReducedMotion, 
  useFrameControl, 
  useOptimizedIntersection 
} from '@tuel/performance';
import { useRef } from 'react';

function PerformantAnimation() {
  const ref = useRef(null);
  const shouldReduceMotion = useReducedMotion();
  const isVisible = useOptimizedIntersection(ref, { threshold: 0.3 });
  
  const { start, stop } = useFrameControl({
    fps: shouldReduceMotion ? 0 : 60,
    onFrame: (timestamp) => {
      if (!isVisible) return;
      updateAnimation(timestamp);
    }
  });

  useEffect(() => {
    if (isVisible && !shouldReduceMotion) {
      start();
    } else {
      stop();
    }
  }, [isVisible, shouldReduceMotion]);

  return <div ref={ref}>{/* Animation content */}</div>;
}

Framer Motion Integration

import { motion } from 'framer-motion';
import { useSafeAnimation } from '@tuel/performance';

function SafeMotionComponent() {
  const duration = useSafeAnimation(1000);

  return (
    <motion.div
      initial={{ opacity: 0, y: 20 }}
      animate={{ opacity: 1, y: 0 }}
      transition={{ 
        duration: duration / 1000,
        ease: 'easeOut'
      }}
    >
      Content
    </motion.div>
  );
}

TypeScript Support

All hooks and utilities are fully typed:

import type { 
  ReducedMotionOptions,
  FrameControlOptions,
  PerformanceMetrics 
} from '@tuel/performance';

Accessibility

This package helps ensure your animations are accessible:

  • ✅ Automatic prefers-reduced-motion detection
  • ✅ Zero animation durations when motion should be reduced
  • ✅ Hooks work seamlessly with animation libraries
  • ✅ No animations when user has motion sensitivity

Performance Best Practices

  1. Use frame throttling for non-critical animations (30fps instead of 60fps)
  2. Lazy load animations using useOptimizedIntersection
  3. Monitor performance in development with usePerformanceMonitor
  4. Respect user preferences always check useReducedMotion

Browser Support

  • Chrome/Edge 90+
  • Firefox 88+
  • Safari 14+
  • All modern browsers with matchMedia API support

Contributing

See CONTRIBUTING.md for development setup and guidelines.

License

MIT © Omer Akben