# clicknhold

React hook for handling long press events with progress tracking. Supports mouse, touch, and keyboard events.



## Installation

```bash
# NPM
npm install clicknhold

# Yarn
yarn add clicknhold

# PNPM
pnpm add clicknhold
```

### CDN

```html
<script src="https://cdn.jsdelivr.net/npm/clicknhold@latest/dist/index.min.js"></script>
```

або

```html
<script src="https://unpkg.com/clicknhold@latest/dist/index.min.js"></script>
```

## Basic Usage

```jsx
// Using hook directly
import { useClicknHold } from 'clicknhold';

function App() {
  const { isHolding, handlers } = useClicknHold({
    duration: 2000,
    onComplete: () => console.log('Completed!'),
    onProgress: (progress) => console.log(`Progress: ${progress}`),
  });

  return (
    <button {...handlers}>
      {isHolding ? 'Holding...' : 'Click and hold!'}
    </button>
  );
}

// Using pre-built components
import { DeleteHold, ConfirmHold, LoadHold } from 'clicknhold';

function App() {
  return (
    <div>
      <DeleteHold onDelete={() => console.log('Deleted!')} />
      <ConfirmHold onConfirm={() => console.log('Confirmed!')} />
      <LoadHold onLoad={() => console.log('Loaded!')} />
    </div>
  );
}
```

## Pre-built Components

### Default Durations
- `DeleteHold`: 2000ms
- `ConfirmHold`: 1500ms
- `LoadHold`: 2500ms

### Styling with Tailwind CSS

```jsx
// Basic styling
<DeleteHold 
  onDelete={() => alert('Deleted!')} 
  className="rounded-lg shadow-lg hover:shadow-xl"
/>

// Custom colors and effects
<ConfirmHold 
  onConfirm={() => alert('Confirmed!')} 
  className="bg-blue-600 hover:bg-blue-700 rounded-full px-8 
    transition-all duration-300 hover:scale-105"
/>

// Progress bar styling
<LoadHold 
  onLoad={() => alert('Loaded!')} 
  className="bg-purple-600 rounded-md [&>div]:bg-white/40 [&>div]:h-1"
/>

// Complex example
<div className="flex gap-4 p-4">
  <DeleteHold 
    onDelete={() => alert('Deleted!')} 
    className="bg-red-600 hover:bg-red-700 rounded-lg shadow-md
      transition-all duration-300 hover:shadow-lg
      [&>div]:bg-white/30 [&>div]:h-1"
  />
  
  <ConfirmHold 
    onConfirm={() => alert('Confirmed!')} 
    className="bg-blue-600 hover:bg-blue-700 rounded-full px-8
      shadow-md hover:shadow-xl transition-all duration-300"
  />
  
  <LoadHold 
    onLoad={() => alert('Loaded!')} 
    className="bg-purple-600 hover:bg-purple-700 rounded-md
      border-2 border-white/20 hover:scale-105 transition-transform"
  />
</div>
```

## API

### useClicknHold Options

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| duration | number | 2000 | Hold duration in milliseconds |
| onComplete | () => void | undefined | Callback triggered when hold completes |
| onStart | () => void | undefined | Callback triggered when hold starts |
| onCancel | () => void | undefined | Callback triggered when hold is cancelled |
| onProgress | (progress: number) => void | undefined | Callback for tracking progress (0-1) |
| disabled | boolean | false | Disable functionality |

### Component Props

All components (`DeleteHold`, `ConfirmHold`, `LoadHold`) accept:

| Prop | Type | Description |
|------|------|-------------|
| className | string | CSS classes (supports Tailwind) |
| style | CSSProperties | Inline styles |
| onDelete/onConfirm/onLoad | () => void | Callback on successful hold |

### Return Values

| Value | Type | Description |
|-------|------|-------------|
| isHolding | boolean | Hold state |
| handlers | object | Event handler object |
| startHolding | function | Function to programmatically start holding |
| stopHolding | function | Function to programmatically stop holding |

## Usage Examples

### Progress Bar

```jsx
function ProgressButton() {
  const [progress, setProgress] = useState(0);
  
  const { isHolding, handlers } = useClicknHold({
    duration: 3000,
    onProgress: setProgress,
    onComplete: () => alert('Done!'),
  });

  return (
    <button {...handlers} style={{ position: 'relative' }}>
      <div
        style={{
          position: 'absolute',
          bottom: 0,
          left: 0,
          height: '4px',
          width: `${progress * 100}%`,
          backgroundColor: 'blue',
          transition: 'width 0.1s linear',
        }}
      />
      {isHolding ? `${Math.round(progress * 100)}%` : 'Hold to load'}
    </button>
  );
}
```

### With Disabled State

```jsx
function DisableableButton() {
  const [isDisabled, setIsDisabled] = useState(false);
  
  const { isHolding, handlers } = useClicknHold({
    duration: 2000,
    disabled: isDisabled,
    onComplete: () => console.log('Completed!'),
  });

  return (
    <div>
      <button {...handlers}>
        {isHolding ? 'Holding...' : 'Click and hold'}
      </button>
      <label>
        <input
          type="checkbox"
          checked={isDisabled}
          onChange={(e) => setIsDisabled(e.target.checked)}
        />
        Disable functionality
      </label>
    </div>
  );
}
```

### Programmatic Control

```jsx
function ProgrammaticControl() {
  const { isHolding, startHolding, stopHolding } = useClicknHold({
    duration: 2000,
    onComplete: () => console.log('Completed!'),
  });

  return (
    <div>
      <button onClick={() => startHolding()}>Start</button>
      <button onClick={() => stopHolding()}>Stop</button>
      <div>Status: {isHolding ? 'Active' : 'Inactive'}</div>
    </div>
  );
}
```

## Features

- Mouse event support
- Touch screen support
- Keyboard support (Enter and Space)
- Progress tracking
- TypeScript support
- Tailwind CSS support
- No external dependencies
- Lightweight (~2KB gzipped)

## Browser Support

- Chrome ✓
- Firefox ✓
- Safari ✓
- Edge ✓
- IE 11 ✗

## License

MIT © [dolhocodev](https://github.com/dolhocodev)



