Skip to content

Commit e61f962

Browse files
committed
docs: update documentation for v0.4.0
- Add v0.4.0 new features section (React Hook support) - Update Breaking Changes section (UMD format removal) - Expand "Why Blokr?" section with comparison table of alternative solutions - Add React Hook section with usage examples, API, and allowGlobal parameter - Remove CDN UMD examples - Simplify "Limitations" section
1 parent 144ece8 commit e61f962

1 file changed

Lines changed: 163 additions & 55 deletions

File tree

README.md

Lines changed: 163 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -5,66 +5,90 @@
55

66
Lightweight library to block user interactions in browsers.
77

8-
## ⚠️ Breaking Changes in v0.3.0
9-
10-
Version 0.3.0 introduces significant API changes from v0.2.x:
11-
12-
- **Factory function instead of singleton**: `blokr()` returns an instance instead of being a singleton object
13-
- **Options-based API**: `lock({ timeout, scope })` instead of separate `setTimeout()` method
14-
- **No reference counting**: Multiple `lock()` calls return `false` instead of incrementing a counter
15-
- **No `setTimeout()` method**: Use `lock({ timeout })` option instead
16-
- **No `unlock(abort)` parameter**: `unlock()` always releases the lock immediately
17-
18-
**Migration guide:** See [Migration from v0.2.x](#migration-from-v02x) below.
19-
20-
**Note:** This library is under active development. Future versions may introduce additional breaking changes. Please refer to the changelog before upgrading.
21-
228
## Features
239

2410
- **Factory-based API**: Support for both global and element-specific locks
25-
- **Scope filtering**: Control which events to block (`inside`, `outside`, `self`)
2611
- **No overlay elements**: Blocks interactions without adding elements to the DOM
27-
- **All interaction types**: Blocks mouse, keyboard, touch, and wheel events
12+
- **Scope filtering**: Control which events to block (`inside`, `outside`, `self`)
2813
- **Per-lock timeout**: Optional automatic unlock after specified time
29-
- **No dependencies**: Zero external dependencies
3014
- **TypeScript**: Full type support included
15+
- **React Hook**: Built-in `useBlokr()` hook for React components
3116

3217
## Why Blokr?
3318

34-
### Problems with CSS-based Solutions
19+
### Comparison with Alternative Solutions
20+
21+
Blokr provides a unique approach to blocking user interactions. Here's how it compares with other techniques:
22+
23+
#### The `inert` Attribute
24+
25+
The HTML5 `inert` attribute marks an element as "inert," preventing user interactions including keyboard navigation.
26+
27+
#### CSS `pointer-events: none`
28+
29+
CSS `pointer-events: none` disables mouse and touch events on elements, but cannot block keyboard events or prevent tab navigation.
30+
31+
#### The `<dialog>` Element
32+
33+
The HTML5 `<dialog>` element creates a modal dialog but adds a DOM element and provides limited scope flexibility for non-modal use cases.
34+
35+
#### Comparison Summary
36+
37+
| Feature | Blokr | inert | pointer-events | dialog |
38+
|---------|-------|-------|----------------|--------|
39+
| Blocks keyboard events |||||
40+
| Global interaction lock |||||
41+
| Inside/outside scope |||||
42+
| Timeout protection |||||
43+
| No DOM overlay |||||
44+
| No DOM modifications |||||
45+
46+
**Key differentiators:**
47+
48+
- **Global interaction lock**: Blokr can block interactions across the entire page, not just within specific elements
49+
- **Inside/outside scope**: Unique ability to selectively block events inside or outside a target element
50+
- **Timeout protection**: Automatic unlock prevents permanent locks due to errors or forgotten cleanup
51+
- **No DOM modifications**: Works purely via event listeners without modifying DOM structure or attributes
3552

36-
While CSS `pointer-events: none` can disable interactions, it has several limitations:
53+
## What's New in v0.4.0
3754

38-
1. **Cannot block keyboard events**: Tab navigation and keyboard shortcuts still work
39-
2. **No timeout protection**: No automatic unlock if code fails to re-enable interactions
40-
3. **Requires DOM manipulation**: Must add/remove CSS classes or inline styles
41-
4. **Cannot scope events**: Cannot selectively block events inside/outside an element
42-
5. **z-index issues**: Overlay approaches require careful z-index management
55+
- **React Hook support**: New `useBlokr()` hook for React applications (React 18+ required)
4356

44-
### How Blokr Solves These Problems
57+
## ⚠️ Breaking Changes in v0.4.0
4558

46-
- **Blocks all interaction types**: Mouse, keyboard, touch, and wheel events
47-
- **Optional timeout protection**: Automatically unlock after specified time
48-
-**No DOM changes**: Works via event listeners only
49-
-**Flexible scoping**: Block events inside, outside, or only on specific elements
50-
-**No z-index conflicts**: No overlay elements needed
51-
-**TypeScript support**: Full type definitions included
59+
- **UMD format removed**: CDN usage now requires ES modules only (`blokr/dist/index.js`)
60+
- **No breaking changes to core API**: All v0.3.0 JavaScript APIs remain unchanged
61+
62+
For changes from v0.2.x, see the [Migration from v0.2.x](#migration-from-v02x) section below.
63+
64+
**Note:** This library is under active development. Future versions may introduce additional breaking changes. Please refer to the changelog before upgrading.
5265

5366
## Installation
5467

5568
```bash
5669
npm install blokr
5770
```
5871

59-
## Usage
72+
### React Hook Support
73+
74+
The `useBlokr()` React Hook is included in the same package. React 18.0+ or React 19.0+ is required to use the hook:
75+
76+
```bash
77+
npm install blokr react
78+
```
79+
80+
The `react` package is an optional peer dependency. If you don't use React, you can ignore this requirement.
81+
82+
## Usage (Vanilla)
6083

61-
### Basic Usage (ES Modules)
84+
### Basic Usage
6285

6386
```typescript
6487
import blokr from 'blokr';
6588

6689
// Global lock - blocks all user interactions
6790
const instance = blokr();
91+
6892
instance.lock();
6993

7094
// Check if locked
@@ -90,7 +114,7 @@ instance.lock();
90114
// Or explicitly specify scope
91115
instance.lock({ scope: 'inside' }); // Block events inside container
92116
instance.lock({ scope: 'outside' }); // Block events outside container
93-
instance.lock({ scope: 'self' }); // Block events on container itself only
117+
instance.lock({ scope: 'self' }); // Block events on the container only
94118
```
95119

96120
### Auto-timeout
@@ -107,21 +131,6 @@ instance.lock({ timeout: 5000 });
107131
instance.lock({ timeout: 0 });
108132
```
109133

110-
### CDN Usage (UMD)
111-
112-
```html
113-
<script src="https://unpkg.com/blokr/dist/blokr.js"></script>
114-
<script>
115-
// Note: global name is 'blokr' (lowercase) in v0.3.0
116-
const instance = window.blokr();
117-
instance.lock();
118-
119-
setTimeout(() => {
120-
instance.unlock();
121-
}, 3000);
122-
</script>
123-
```
124-
125134
### CDN Usage (ES Modules)
126135

127136
```html
@@ -166,9 +175,9 @@ Locks user interactions. Returns `true` if lock was applied, `false` if already
166175
**Parameters:**
167176
- `options.timeout` (optional): Auto-unlock timeout in milliseconds. Default: `0` (no timeout)
168177
- `options.scope` (optional): Event blocking scope. Default: `'inside'`
169-
- `'inside'`: Block events inside target element (default)
170-
- `'outside'`: Block events outside target element
171-
- `'self'`: Block events on target element itself only
178+
- `'inside'`: Block events inside the target element (default)
179+
- `'outside'`: Block events outside the target element
180+
- `'self'`: Block events on the target element only
172181

173182
**Returns:** `true` if lock was applied, `false` if already locked
174183

@@ -320,6 +329,107 @@ async function loadData() {
320329
}
321330
```
322331

332+
## React Hook
333+
334+
The `useBlokr()` hook provides a React-friendly way to manage user interaction blocking. It works seamlessly with the factory-based API and manages refs automatically.
335+
336+
### Import
337+
338+
```typescript
339+
import { useBlokr } from 'blokr/react';
340+
```
341+
342+
### Basic Usage
343+
344+
```tsx
345+
import { useBlokr } from 'blokr/react';
346+
347+
export function PageWithLinks() {
348+
const { target, lock, unlock, isLocked } = useBlokr<HTMLDivElement>();
349+
350+
const handleLock = () => {
351+
lock({ timeout: 5000 }); // Auto-unlock after 5 seconds
352+
};
353+
354+
return (
355+
<>
356+
<div ref={target}>
357+
<a href="/page1">Go to Page 1</a>
358+
</div>
359+
<button onClick={handleLock}>Lock Link</button>
360+
<button onClick={unlock}>Unlock</button>
361+
</>
362+
);
363+
}
364+
```
365+
366+
### Options
367+
368+
The `lock()` function accepts the same options as the core API:
369+
370+
```tsx
371+
const { target, lock, unlock } = useBlokr<HTMLDivElement>();
372+
373+
// With timeout (auto-unlock after 5 seconds)
374+
lock({ timeout: 5000 });
375+
376+
// With scope
377+
lock({ scope: 'inside' }); // Block inside the element
378+
lock({ scope: 'outside' }); // Block outside the element
379+
lock({ scope: 'self' }); // Block on the element only
380+
381+
// With both options
382+
lock({ scope: 'inside', timeout: 5000 });
383+
```
384+
385+
### Hook API
386+
387+
#### `useBlokr<T = Element>(allowGlobal?: boolean): { target: RefObject<T | null>; lock: (options?: Options) => boolean; unlock: () => void; isLocked: () => boolean }`
388+
389+
Returns an object containing a ref and three control functions for managing user interaction blocking.
390+
391+
**Type Parameters:**
392+
- `T` (optional): The DOM element type. Default: `Element`
393+
394+
**Parameters:**
395+
- `allowGlobal` (optional): If `true`, enables global lock mode that blocks interactions across the entire page instead of a specific element. When using global lock, the `target` ref is not needed. Default: `false`
396+
397+
**Returns:** An object with:
398+
- `target`: A React ref to assign to the target element (`RefObject<T | null>`)
399+
- `lock`: Function to lock user interactions on the element (`(options?: Options) => boolean`)
400+
- `unlock`: Function to unlock user interactions (`() => void`)
401+
- `isLocked`: Function to check if currently locked (`() => boolean`)
402+
403+
**Parameters (lock function):**
404+
- `options.timeout` (optional): Auto-unlock timeout in milliseconds
405+
- `options.scope` (optional): Event blocking scope (`'inside'`, `'outside'`, or `'self'`)
406+
407+
**Returns (lock function):** `true` if lock was applied, `false` if already locked or if the ref is not set (when using element-specific lock)
408+
409+
### allowGlobal Parameter
410+
411+
The `allowGlobal` parameter enables global lock mode, which blocks user interactions across the entire page instead of scoping to a specific element.
412+
413+
**Global Lock (`allowGlobal=true`):**
414+
```tsx
415+
// No need to destructure 'target' since we're not using element-specific locking
416+
const { lock, unlock, isLocked } = useBlokr(true);
417+
418+
// Locks all interactions across the entire page
419+
lock(); // Blocks all user interactions globally
420+
```
421+
422+
**Element-Specific Lock (Default: `allowGlobal=false`):**
423+
```tsx
424+
const { target, lock, unlock, isLocked } = useBlokr<HTMLDivElement>();
425+
426+
// Attach target to an element
427+
<div ref={target}>Content</div>
428+
429+
// Lock only affects this specific element (by default, scope='inside')
430+
lock(); // Blocks interactions inside the div
431+
```
432+
323433
## Migration from v0.2.x
324434

325435
### API Changes
@@ -374,9 +484,7 @@ instance.lock({ scope: 'self' });
374484

375485
## Limitations
376486

377-
- **Only blocks genuine user interactions**: Programmatically triggered events (e.g., `element.click()`) are not blocked.
378-
- **Event listener priority**: Event listeners are registered at the capture phase. May not work correctly when used with event delegation libraries. Loading Blokr before other libraries may resolve this issue.
379-
- **Target-specific locks accept Elements only**: The `blokr(target)` factory function only accepts DOM `Element` nodes. To block interactions across the entire page, use the global lock: `blokr()` (without a target parameter).
487+
- **Event listener priority**: Event listeners are registered at the capture phase. May not work correctly when used with event delegation libraries.
380488

381489
## License
382490

0 commit comments

Comments
 (0)