# @mirawision/reactive-hooks

A comprehensive collection of **50+ React hooks** for state management, UI interactions, device APIs, async operations, drag & drop, audio/speech, and more. Built with full TypeScript support and SSR safety.

## Installation

```bash
npm install @mirawision/reactive-hooks
```

or 

```bash
yarn add @mirawision/reactive-hooks
```

## Usage

### Import all hooks
```typescript
import { useToggle, useLocalStorage, useInput } from '@mirawision/reactive-hooks';
```

### Import individual hooks
```typescript
import { useToggle } from '@mirawision/reactive-hooks/use-toggle';
import { useLocalStorage } from '@mirawision/reactive-hooks/use-local-storage';
```

## Quick Overview

The library is organized into 7 main categories:

- **State Management** (13 hooks): Toggle, lists, pagination, sorting, URL params, infinite scroll
- **Storage & Persistence** (3 hooks): Local storage, session storage, cookies
- **UI & DOM Events** (13 hooks): Event listeners, gestures, drag & drop, keyboard shortcuts
- **Layout & Viewport** (6 hooks): Window size, element size, scroll, media queries
- **Device APIs & Browser State** (8 hooks): Geolocation, orientation, speech, audio
- **Async & Timing** (10 hooks): Fetch, retry, polling, debounce, throttle, queues
- **Lifecycle & Effects** (3 hooks): Mount state, update effects

## Hooks by Category

### State Management
- **`useToggle`**: Boolean state with toggle functionality
- **`useInput`**: Input field state with event handling
- **`useList`**: Array state with common operations
- **`usePrevious`**: Access previous state value
- **`useCheckboxes`**: Manage collection of checkboxes
- **`useSort`**: Manage sorting field and direction
- **`usePagination`**: Handle pagination with array slicing
- **`useNumber`**: Numeric state with min/max limits and step
- **`useIterator`**: Iterate over arrays or numeric ranges
- **`useQueryParams`**: URL query parameters as state
- **`useQueryParam`**: Single URL parameter as state
- **`useInfiniteScroll`**: Infinite loading with intersection observer

### Storage & Persistence
- **`useLocalStorage`**: localStorage state with sync
- **`useSessionStorage`**: sessionStorage state with sync
- **`useCookie`**: Cookie-based state management

### UI & DOM Events
- **`useEventListener`**: Safe DOM event subscription
- **`useOnClickOutside`**: Handle clicks outside element
- **`useHover`**: Track element hover state
- **`useFocus`**: Track element focus state
- **`useKeyPress`**: Keyboard event handling
- **`useShortcuts`**: Keyboard shortcuts with modifiers
- **`useLongPress`**: Long press detection for mouse/touch
- **`useSwipe`**: Swipe gesture detection
- **`useDrag`**: Drag functionality with data transfer
- **`useDragEvents`**: Custom drag event handlers
- **`useDropZone`**: File drop zone with filtering
- **`useEventOnToggle`**: Conditional event listeners
- **`useWindowScrollLock`**: Lock window scrolling for modals

### Layout & Viewport
- **`useWindowSize`**: Window dimensions with throttle
- **`useElementSize`**: Element dimensions with ResizeObserver
- **`useScroll`**: Scroll position tracking
- **`useIntersectionObserver`**: Element visibility tracking
- **`useMediaQuery`**: CSS media query matching
- **`useScreenSize`**: Responsive window dimensions

### Device APIs & Browser State
- **`useGeolocation`**: Device location tracking
- **`useDeviceOrientation`**: Device orientation angles
- **`useOnlineStatus`**: Network connectivity state
- **`usePageVisibility`**: Tab visibility tracking
- **`useSpeechSynthesis`**: Text-to-speech functionality
- **`useSystemVoices`**: Available speech synthesis voices
- **`useSpeechRecognition`**: Speech-to-text functionality
- **`useAudio`**: HTML5 audio playback control

### Async & Timing
- **`useAsync`**: Async function state wrapper
- **`useAsyncQueue`**: Sequential task execution
- **`useRetry`**: Retry failed operations
- **`usePolling`**: Periodic async execution
- **`useFetch`**: Fetch wrapper with abort/cache
- **`useDebounce`**: Delay value/function updates
- **`useThrottle`**: Limit update frequency
- **`useTimeout`**: Delayed callback execution
- **`useInterval`**: Repeated callback execution
- **`useClock`**: Timer with controls

### Lifecycle & Effects
- **`useIsMounted`**: Component mount state
- **`useUpdateEffect`**: Skip first render effect
- **`useFirstMountState`**: First render detection

## Example Usage

### State Management
```typescript
// Toggle state
const [isOpen, toggle] = useToggle(false);

// List operations
const [items, { push, remove, move }] = useList(['a', 'b', 'c']);

// Checkbox collection
const { values, toggle, setAll, allChecked } = useCheckboxes({
  item1: true,
  item2: false
});

// Sorting management
const { field, dir, setField, toggleDir } = useSort('name', 'asc');
const sortedItems = items.sort((a, b) => 
  dir === 'asc' ? a[field].localeCompare(b[field]) : b[field].localeCompare(a[field])
);

// Pagination
const { page, slice, next, prev } = usePagination(items.length, 10);
const pageItems = slice(items);

// Numeric state with limits
const { value, inc, dec } = useNumber(0, { min: 0, max: 100, step: 5 });

// Array/range iteration
const { value, next, hasNext } = useIterator(['a', 'b', 'c'], { loop: true });
const { value: index } = useIterator(5); // Iterates over 0..4
```

### Storage & Persistence
```typescript
// Local storage with sync
const [value, { set, remove }] = useLocalStorage('key', 'default');

// Cookie management
const [token, setToken, removeToken] = useCookie('auth-token', '', {
  days: 7,
  secure: true
});
```

### Device APIs
```typescript
// Geolocation tracking
const { coords, error } = useGeolocation({
  enableHighAccuracy: true,
  watch: true
});

// Device orientation
const { alpha, beta, gamma } = useDeviceOrientation();

// Tab visibility
const isVisible = usePageVisibility();
if (!isVisible) {
  pauseVideoPlayback();
}

// Lock window scrolling for modal
function Modal({ isOpen }) {
  useWindowScrollLock(isOpen);
  return isOpen ? <div>Modal content</div> : null;
}

// Global keyboard shortcuts
useShortcuts([
  { combo: 'Ctrl+S', handler: (e) => saveDocument(e) },
  { combo: 'Ctrl+Shift+Z', handler: (e) => redo(e) },
  { combo: 'Meta+K', handler: (e) => openCommandPalette(e) }
]);

// URL query parameters as state
const [params, setParams] = useQueryParams();
const page = params.get('page') || '1';
setParams({ page: '2', sort: 'desc' });

// Single URL parameter
const [page, setPage] = useQueryParam('page');
setPage('3', { replace: true }); // Replace history state

// Infinite scroll
function List() {
  const { ref, loading } = useInfiniteScroll({
    hasMore: items.length < total,
    loadMore: () => fetchNextPage(),
  });

  return (
    <div>
      {items.map(item => <Item key={item.id} {...item} />)}
      <div ref={ref}>{loading ? 'Loading...' : null}</div>
    </div>
  );
}

// Long press detection
function Button() {
  const handlers = useLongPress(() => console.log('long press!'), {
    delay: 500,
    cancelOnMove: true,
  });
  return <button {...handlers}>Press and hold</button>;
}

// Swipe gestures
function Card() {
  const ref = useRef(null);
  const { swiping, dir } = useSwipe(ref, {
    minDistance: 50,
    onSwipe: (dir, info) => console.log(dir, info),
  });
  return <div ref={ref} style={{ opacity: swiping ? 0.5 : 1 }} />;
}

// Drag and drop
function DraggableItem({ id, data }) {
  const ref = useRef(null);
  const { dragging } = useDrag(ref, { id, ...data });
  return (
    <div ref={ref} style={{ opacity: dragging ? 0.5 : 1 }}>
      Draggable Item
    </div>
  );
}

function DropZone() {
  const ref = useRef(null);
  const { over } = useDropZone(ref, {
    onDrop: (files) => console.log('Dropped files:', files),
    multiple: true,
    accept: 'image/*,.pdf'
  });
  return (
    <div ref={ref} style={{ border: over ? '2px dashed blue' : '2px dashed gray' }}>
      Drop files here
    </div>
  );
}

// Custom drag events
function CustomDragArea() {
  const ref = useRef(null);
  useDragEvents(ref, {
    onDragStart: (e) => console.log('Drag started'),
    onDrop: (e) => {
      const data = e.dataTransfer.getData('application/json');
      console.log('Dropped data:', JSON.parse(data));
    }
  });
  return <div ref={ref}>Custom drag area</div>;
}

// Custom drag events
function CustomDragArea() {
  const ref = useRef(null);
  useDragEvents(ref, {
    onDragStart: (e) => console.log('Drag started'),
    onDrop: (e) => {
      const data = e.dataTransfer.getData('application/json');
      console.log('Dropped data:', JSON.parse(data));
    }
  });
  return <div ref={ref}>Custom drag area</div>;
}

// Text-to-speech
function TextReader() {
  const { speak, speaking, pause, resume } = useSpeechSynthesis();
  const voices = useSystemVoices();
  return (
    <div>
      <button onClick={() => speak('Hello world', { rate: 1.5 })}>
        {speaking ? 'Speaking...' : 'Speak'}
      </button>
      <select>{voices.map(v => <option key={v.name}>{v.name}</option>)}</select>
    </div>
  );
}

// Speech recognition
function VoiceInput() {
  const { transcript, listening, start, stop } = useSpeechRecognition({
    continuous: true,
    interimResults: true,
  });
  return (
    <div>
      <button onClick={listening ? stop : start}>
        {listening ? 'Stop' : 'Start'} listening
      </button>
      <p>{transcript}</p>
    </div>
  );
}

// Audio player
function AudioPlayer() {
  const { audioRef, playing, play, pause, currentTime, duration, volume, setVolume } = useAudio('/audio.mp3');
  
  return (
    <div>
      <audio ref={audioRef} />
      <button onClick={playing ? pause : play}>
        {playing ? 'Pause' : 'Play'}
      </button>
      <input
        type="range"
        min="0"
        max={duration}
        value={currentTime}
        onChange={(e) => seek(Number(e.target.value))}
      />
      <input
        type="range"
        min="0"
        max="1"
        step="0.1"
        value={volume}
        onChange={(e) => setVolume(Number(e.target.value))}
      />
      <span>{Math.floor(currentTime)}s / {Math.floor(duration)}s</span>
    </div>
  );
}
```

### Async Operations
```typescript
// Sequential task queue
const queue = useAsyncQueue();
await queue.enqueue(() => saveData());

// Retry with backoff
const { run, error } = useRetry(fetchData, {
  retries: 3,
  delayMs: 1000
});

// Debounced search
const debouncedQuery = useDebounce(searchQuery, 300);
```

## Features

- **50+ Hooks**: Comprehensive coverage of React development needs
- **Type-safe**: Full TypeScript support with detailed type definitions
- **Tree-shakeable**: Import only what you need, reduce bundle size
- **Well-tested**: Extensive test coverage for all hooks
- **SSR-safe**: Server-side rendering support with graceful degradation
- **Lightweight**: Minimal dependencies, optimized for performance
- **React 16.8+ compatible**: Modern hooks API with backward compatibility (supports React 19)
- **Cross-platform**: Works across browsers, devices, and platforms
- **Accessibility**: Built with accessibility best practices in mind
- **Performance**: Optimized for performance with proper cleanup and memoization

## Library Statistics

- **Total Hooks**: 56 hooks across 7 categories
- **TypeScript Coverage**: 100% with full type definitions
- **Test Coverage**: Comprehensive tests for all hooks
- **Bundle Size**: Tree-shakeable, import only what you need
- **Browser Support**: Modern browsers with SSR safety
- **React Versions**: 16.8+ (hooks support, including React 19)

## API Reference

Each hook is documented with TypeScript types and JSDoc comments. For detailed API documentation:
1. See the TypeScript definitions
2. Check individual hook files
3. Refer to test files for usage examples

## Contributing

Contributions are welcome! Please read our contributing guidelines for details.