@okyrychenko-dev/react-action-guard 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +75 -28
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -4,25 +4,18 @@
4
4
  [![npm downloads](https://img.shields.io/npm/dm/@okyrychenko-dev/react-action-guard.svg)](https://www.npmjs.com/package/@okyrychenko-dev/react-action-guard)
5
5
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
6
6
 
7
- > Elegant UI blocking management for React applications with priorities, scopes, and automatic cleanup
8
-
9
- ## Features
10
-
11
- - Priority-based blocking system
12
- - Scoped blocking (global, specific areas, or multiple scopes)
13
- - Automatic cleanup on unmount
14
- - **Timeout mechanism** - auto-remove blockers after specified time
15
- - **Provider pattern** - isolated stores for SSR, testing, and micro-frontends
16
- - Advanced hooks for different use cases:
17
- - Confirmable blockers with custom dialogs
18
- - Scheduled blocking for maintenance windows
19
- - Conditional blocking based on application state
20
- - Async action wrapping with timeout support
21
- - Advanced middleware system for analytics, logging, and performance monitoring
22
- - TypeScript support with full type safety (including optional type-safe scopes)
23
- - Built on Zustand for efficient state management
24
- - Tree-shakeable - import only what you need
25
- - Hooks-based API
7
+ > Coordinate UI blocking across async actions and competing interactions in React
8
+
9
+ `react-action-guard` helps you prevent duplicate submits, conflicting actions, and stale UI interactions without scattering local `isLoading` flags across components.
10
+
11
+ ## Why Use It
12
+
13
+ - Wrap async work with `useAsyncAction` and get blocker cleanup automatically
14
+ - Coordinate blocking by `scope` across unrelated components
15
+ - Inspect current blockers with `useIsBlocked` and `useBlockingInfo`
16
+ - Isolate state per provider for SSR, tests, and micro-frontends
17
+ - Extend lifecycle events with optional middleware
18
+ - Add advanced hooks for scheduled, confirmable, or conditional flows when needed
26
19
 
27
20
  ## Installation
28
21
 
@@ -48,15 +41,43 @@ If you previously imported `createShallowStore`, `createStoreToolkit`, `createSt
48
41
  ## Quick Start
49
42
 
50
43
  ```jsx
51
- import { useBlocker, useIsBlocked } from "@okyrychenko-dev/react-action-guard";
44
+ import { useAsyncAction, useIsBlocked } from "@okyrychenko-dev/react-action-guard";
52
45
 
53
- function MyComponent() {
54
- const isBlocked = useIsBlocked("my-scope");
46
+ function SaveButton() {
47
+ const isSaving = useIsBlocked("form");
48
+ const runSave = useAsyncAction("save-profile", "form");
49
+
50
+ const handleClick = async () => {
51
+ await runSave(async () => {
52
+ await api.saveProfile();
53
+ });
54
+ };
55
55
 
56
- return <button disabled={isBlocked}>Click me</button>;
56
+ return <button onClick={handleClick} disabled={isSaving}>Save</button>;
57
57
  }
58
58
  ```
59
59
 
60
+ ## Core Concepts
61
+
62
+ - `scope` lets you coordinate blocking across components like `"form"`, `"navigation"`, or `"checkout"`
63
+ - `useAsyncAction` is the fastest path for async workflows
64
+ - `useBlocker` is the lower-level hook when you already have your own boolean state
65
+ - `UIBlockingProvider` gives you isolated state instead of the default global store
66
+
67
+ ## Core Use Cases
68
+
69
+ ### Prevent duplicate async actions
70
+
71
+ Use `useAsyncAction` when a button, mutation, or workflow should block while work is in flight.
72
+
73
+ ### Coordinate multiple components
74
+
75
+ Use shared scopes when one component starts work and another component should react by disabling UI or showing blocker details.
76
+
77
+ ### Isolate blocking domains
78
+
79
+ Use `UIBlockingProvider` when each request, test, or micro-frontend should get its own store instance.
80
+
60
81
  ## Documentation
61
82
 
62
83
  📚 **Interactive Storybook Documentation** - Run locally to explore live examples and detailed guides for all hooks
@@ -71,6 +92,15 @@ npm run storybook
71
92
 
72
93
  ### Hooks
73
94
 
95
+ #### Core hooks
96
+
97
+ Start with these first:
98
+
99
+ - `useAsyncAction`
100
+ - `useBlocker`
101
+ - `useIsBlocked`
102
+ - `useBlockingInfo`
103
+
74
104
  #### `useBlocker(blockerId, config, isActive?)`
75
105
 
76
106
  Automatically adds a blocker when the component mounts and removes it on unmount.
@@ -235,9 +265,18 @@ function ApiComponent() {
235
265
  }
236
266
  ```
237
267
 
268
+ #### Advanced hooks
269
+
270
+ These hooks are useful, but they are not the main onboarding path for most apps:
271
+
272
+ - `useConfirmableBlocker` for confirmation flows
273
+ - `useScheduledBlocker` for time-window blocking
274
+ - `useConditionalBlocker` for polling-based conditional synchronization
275
+
238
276
  #### `useConfirmableBlocker(blockerId, config)`
239
277
 
240
278
  Creates a confirmable action with UI blocking while the dialog is open or the action is running.
279
+ Use it for advanced confirmation flows after the core hooks are already a good fit.
241
280
 
242
281
  **Parameters:**
243
282
 
@@ -302,6 +341,7 @@ function UnsavedChangesGuard({ discardChanges }) {
302
341
  #### `useScheduledBlocker(blockerId, config)`
303
342
 
304
343
  Blocks UI during a scheduled time period or maintenance window.
344
+ Use it when blocking is driven by time windows rather than user-triggered async work.
305
345
 
306
346
  **Parameters:**
307
347
 
@@ -342,6 +382,7 @@ function MaintenanceWindow() {
342
382
  #### `useConditionalBlocker(blockerId, config)`
343
383
 
344
384
  Periodically checks a condition and blocks/unblocks based on the result.
385
+ Use this when polling is an acceptable tradeoff and the condition is not naturally event-driven.
345
386
 
346
387
  **Parameters:**
347
388
 
@@ -523,7 +564,9 @@ uiBlockingStoreApi.getState().addBlocker("server-call", {
523
564
 
524
565
  ## Middleware System
525
566
 
526
- The library includes a powerful middleware system that allows you to hook into blocker lifecycle events for analytics, logging, and performance monitoring.
567
+ Middleware is optional. Use it when you need analytics, logging, or performance visibility around blocker lifecycle events.
568
+
569
+ Most applications can start without middleware and add it later if blocker observability becomes important.
527
570
 
528
571
  ### Middleware Actions
529
572
 
@@ -551,6 +594,8 @@ Middleware receives events for the following actions:
551
594
 
552
595
  ### Built-in Middleware
553
596
 
597
+ These are extensions around the blocker lifecycle, not the primary onboarding path for the library.
598
+
554
599
  #### Analytics Middleware
555
600
 
556
601
  Track blocker events with your analytics provider (Google Analytics, Mixpanel, Amplitude, or custom).
@@ -645,7 +690,7 @@ configureMiddleware([myCustomMiddleware]);
645
690
 
646
691
  ### Combining Middleware
647
692
 
648
- You can combine multiple middleware for comprehensive monitoring:
693
+ You can combine multiple middleware when you need broader observability:
649
694
 
650
695
  ```jsx
651
696
  import {
@@ -740,6 +785,8 @@ useBlocker("save", { scope: "typo" }); // Type error
740
785
 
741
786
  ## Use Cases
742
787
 
788
+ The first four examples below are the most representative starting points.
789
+
743
790
  ### Loading States
744
791
 
745
792
  ```jsx
@@ -783,7 +830,7 @@ function UserForm() {
783
830
  }
784
831
  ```
785
832
 
786
- ### Unsaved Changes Protection
833
+ ### Advanced: Unsaved Changes Protection
787
834
 
788
835
  ```jsx
789
836
  import { useConfirmableBlocker } from "@okyrychenko-dev/react-action-guard";
@@ -880,7 +927,7 @@ function MultiStepWizard() {
880
927
  }
881
928
  ```
882
929
 
883
- ### Scheduled Maintenance Window
930
+ ### Advanced: Scheduled Maintenance Window
884
931
 
885
932
  ```jsx
886
933
  import { useScheduledBlocker } from "@okyrychenko-dev/react-action-guard";
@@ -907,7 +954,7 @@ function App() {
907
954
  }
908
955
  ```
909
956
 
910
- ### Dynamic Blocking Based on State
957
+ ### Advanced: Dynamic Blocking Based on State
911
958
 
912
959
  ```jsx
913
960
  import { useConditionalBlocker } from "@okyrychenko-dev/react-action-guard";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@okyrychenko-dev/react-action-guard",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "type": "module",
5
5
  "description": "Elegant UI blocking management for React applications with priorities, scopes, and automatic cleanup",
6
6
  "main": "./dist/index.js",