@okyrychenko-dev/react-action-guard-devtools 0.1.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.
- package/LICENSE +21 -0
- package/README.md +394 -0
- package/dist/index.cjs +893 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.css +363 -0
- package/dist/index.css.map +1 -0
- package/dist/index.d.cts +160 -0
- package/dist/index.d.ts +160 -0
- package/dist/index.js +882 -0
- package/dist/index.js.map +1 -0
- package/package.json +99 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Oleksii Kyrychenko
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
# @okyrychenko-dev/react-action-guard-devtools
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@okyrychenko-dev/react-action-guard-devtools)
|
|
4
|
+
[](https://www.npmjs.com/package/@okyrychenko-dev/react-action-guard-devtools)
|
|
5
|
+
[](https://opensource.org/licenses/MIT)
|
|
6
|
+
|
|
7
|
+
> Developer tools for [@okyrychenko-dev/react-action-guard](https://github.com/okyrychenko-dev/react-action-guard) - visualize, debug, and monitor UI blocking events in real-time
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- π **Real-time Timeline** - Visual timeline of all blocking events with duration tracking
|
|
12
|
+
- π― **Active Blockers View** - See all currently active blockers at a glance
|
|
13
|
+
- π **Filtering** - Search by blocker ID or reason (advanced filters via store API)
|
|
14
|
+
- βΈοΈ **Pause/Resume** - Pause event recording to inspect specific moments
|
|
15
|
+
- π **Detailed Event Info** - View full configuration, duration, and state changes
|
|
16
|
+
- π¨ **Customizable Position** - Place devtools panel on the left or right
|
|
17
|
+
- π **Zero Config** - Works out of the box with automatic middleware registration
|
|
18
|
+
- π **Production Safe** - Automatically disabled in production builds
|
|
19
|
+
- πΎ **Event History** - Configurable event limit to manage memory usage
|
|
20
|
+
- π¨ **Clean UI** - Minimalistic design that doesn't interfere with your app
|
|
21
|
+
|
|
22
|
+
## Installation
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npm install @okyrychenko-dev/react-action-guard-devtools
|
|
26
|
+
# or
|
|
27
|
+
yarn add @okyrychenko-dev/react-action-guard-devtools
|
|
28
|
+
# or
|
|
29
|
+
pnpm add @okyrychenko-dev/react-action-guard-devtools
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
This package requires the following peer dependencies:
|
|
33
|
+
|
|
34
|
+
- [@okyrychenko-dev/react-action-guard](https://github.com/okyrychenko-dev/react-action-guard) ^0.5.0
|
|
35
|
+
- [React](https://react.dev/) ^17.0.0 || ^18.0.0 || ^19.0.0
|
|
36
|
+
|
|
37
|
+
## Quick Start
|
|
38
|
+
|
|
39
|
+
Add the devtools component to your app root:
|
|
40
|
+
|
|
41
|
+
```jsx
|
|
42
|
+
import { ActionGuardDevtools } from "@okyrychenko-dev/react-action-guard-devtools";
|
|
43
|
+
|
|
44
|
+
function App() {
|
|
45
|
+
return (
|
|
46
|
+
<>
|
|
47
|
+
<YourApp />
|
|
48
|
+
<ActionGuardDevtools />
|
|
49
|
+
</>
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
That's it! The devtools will automatically register middleware and start tracking all blocking events.
|
|
55
|
+
|
|
56
|
+
## Component API
|
|
57
|
+
|
|
58
|
+
### `<ActionGuardDevtools />`
|
|
59
|
+
|
|
60
|
+
The main devtools component that renders the toggle button and panel.
|
|
61
|
+
|
|
62
|
+
#### Props
|
|
63
|
+
|
|
64
|
+
| Prop | Type | Default | Description |
|
|
65
|
+
| ------------------ | -------------------- | ----------- | ----------------------------------------------------- |
|
|
66
|
+
| `position` | `DevtoolsPosition` | `"right"` | Position of the toggle button and panel |
|
|
67
|
+
| `defaultOpen` | `boolean` | `false` | Whether the panel is open by default |
|
|
68
|
+
| `maxEvents` | `number` | `200` | Maximum number of events to store in history |
|
|
69
|
+
| `showInProduction` | `boolean` | `false` | Whether to show devtools in production |
|
|
70
|
+
| `store` | `UIBlockingStoreApi` | `undefined` | Custom store instance from UIBlockingProvider context |
|
|
71
|
+
|
|
72
|
+
#### Position Options
|
|
73
|
+
|
|
74
|
+
- `"left"` - Left side
|
|
75
|
+
- `"right"` - Right side
|
|
76
|
+
|
|
77
|
+
#### Examples
|
|
78
|
+
|
|
79
|
+
**Custom Position and Max Events:**
|
|
80
|
+
|
|
81
|
+
```jsx
|
|
82
|
+
<ActionGuardDevtools position="right" maxEvents={500} />
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
**Open by Default (Development):**
|
|
86
|
+
|
|
87
|
+
```jsx
|
|
88
|
+
<ActionGuardDevtools defaultOpen={true} position="left" />
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
**Enable in Production (Not Recommended):**
|
|
92
|
+
|
|
93
|
+
```jsx
|
|
94
|
+
<ActionGuardDevtools showInProduction={true} />
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
**With UIBlockingProvider (Isolated Store):**
|
|
98
|
+
|
|
99
|
+
```jsx
|
|
100
|
+
import { UIBlockingProvider, useUIBlockingContext } from "@okyrychenko-dev/react-action-guard";
|
|
101
|
+
import { ActionGuardDevtools } from "@okyrychenko-dev/react-action-guard-devtools";
|
|
102
|
+
|
|
103
|
+
function DevtoolsWithProvider() {
|
|
104
|
+
const store = useUIBlockingContext();
|
|
105
|
+
return <ActionGuardDevtools store={store} />;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function App() {
|
|
109
|
+
return (
|
|
110
|
+
<UIBlockingProvider>
|
|
111
|
+
<YourApp />
|
|
112
|
+
<DevtoolsWithProvider />
|
|
113
|
+
</UIBlockingProvider>
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Advanced Usage
|
|
119
|
+
|
|
120
|
+
### Manual Middleware Registration
|
|
121
|
+
|
|
122
|
+
If you need more control, you can register the middleware manually:
|
|
123
|
+
|
|
124
|
+
```jsx
|
|
125
|
+
import {
|
|
126
|
+
createDevtoolsMiddleware,
|
|
127
|
+
DEVTOOLS_MIDDLEWARE_NAME,
|
|
128
|
+
} from "@okyrychenko-dev/react-action-guard-devtools";
|
|
129
|
+
import { uiBlockingStoreApi } from "@okyrychenko-dev/react-action-guard";
|
|
130
|
+
|
|
131
|
+
// Register middleware
|
|
132
|
+
const middleware = createDevtoolsMiddleware();
|
|
133
|
+
uiBlockingStoreApi.getState().registerMiddleware(DEVTOOLS_MIDDLEWARE_NAME, middleware);
|
|
134
|
+
|
|
135
|
+
// Later, unregister if needed
|
|
136
|
+
uiBlockingStoreApi.getState().unregisterMiddleware(DEVTOOLS_MIDDLEWARE_NAME);
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Accessing Devtools Store
|
|
140
|
+
|
|
141
|
+
For advanced use cases, you can access the devtools store directly:
|
|
142
|
+
|
|
143
|
+
```jsx
|
|
144
|
+
import { useDevtoolsStore } from "@okyrychenko-dev/react-action-guard-devtools";
|
|
145
|
+
|
|
146
|
+
function CustomDevtoolsComponent() {
|
|
147
|
+
const { events, isOpen, toggleOpen, clearEvents, isPaused, togglePause } = useDevtoolsStore();
|
|
148
|
+
|
|
149
|
+
return (
|
|
150
|
+
<div>
|
|
151
|
+
<button onClick={toggleOpen}>Toggle Devtools</button>
|
|
152
|
+
<button onClick={clearEvents}>Clear History</button>
|
|
153
|
+
<button onClick={togglePause}>{isPaused ? "Resume" : "Pause"}</button>
|
|
154
|
+
<p>Total Events: {events.length}</p>
|
|
155
|
+
</div>
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### Store Selectors
|
|
161
|
+
|
|
162
|
+
The library provides optimized selectors for filtering events:
|
|
163
|
+
|
|
164
|
+
```jsx
|
|
165
|
+
import {
|
|
166
|
+
useDevtoolsStore,
|
|
167
|
+
selectFilteredEvents,
|
|
168
|
+
selectUniqueScopes,
|
|
169
|
+
} from "@okyrychenko-dev/react-action-guard-devtools";
|
|
170
|
+
|
|
171
|
+
function EventList() {
|
|
172
|
+
// Get filtered events based on current filter settings
|
|
173
|
+
const filteredEvents = useDevtoolsStore(selectFilteredEvents);
|
|
174
|
+
|
|
175
|
+
// Get list of unique scopes from all events
|
|
176
|
+
const scopes = useDevtoolsStore(selectUniqueScopes);
|
|
177
|
+
|
|
178
|
+
return (
|
|
179
|
+
<div>
|
|
180
|
+
<h3>Scopes: {scopes.join(", ")}</h3>
|
|
181
|
+
<ul>
|
|
182
|
+
{filteredEvents.map((event) => (
|
|
183
|
+
<li key={event.id}>{event.blockerId}</li>
|
|
184
|
+
))}
|
|
185
|
+
</ul>
|
|
186
|
+
</div>
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## UI Features
|
|
192
|
+
|
|
193
|
+
### Timeline View
|
|
194
|
+
|
|
195
|
+
The timeline shows all blocking events in chronological order:
|
|
196
|
+
|
|
197
|
+
- **Color coding**:
|
|
198
|
+
- π’ Green - "add" events (blocker activated)
|
|
199
|
+
- π΄ Red - "remove" events (blocker deactivated)
|
|
200
|
+
- π΅ Blue - "update" events (blocker configuration changed)
|
|
201
|
+
- π Orange - "timeout" events (blocker auto-removed due to timeout)
|
|
202
|
+
- π Orange - "cancel" events (blocker cancelled)
|
|
203
|
+
- **Duration display**: Shows how long blockers were active
|
|
204
|
+
- **Expandable details**: Click any event to see full configuration
|
|
205
|
+
- **Scope indicators**: Visual tags showing which scopes are affected
|
|
206
|
+
|
|
207
|
+
### Active Blockers View
|
|
208
|
+
|
|
209
|
+
See all currently active blockers with:
|
|
210
|
+
|
|
211
|
+
- Priority sorting (highest first)
|
|
212
|
+
- Scope and reason information
|
|
213
|
+
- How long each blocker has been active
|
|
214
|
+
|
|
215
|
+
### Filtering
|
|
216
|
+
|
|
217
|
+
Filter events by:
|
|
218
|
+
|
|
219
|
+
- **Search**: Search by blocker ID or reason
|
|
220
|
+
|
|
221
|
+
For action/scope filtering, use `useDevtoolsStore` and `setFilter` in your own UI.
|
|
222
|
+
|
|
223
|
+
### Controls
|
|
224
|
+
|
|
225
|
+
- **Pause/Resume**: Stop recording new events to inspect a specific moment
|
|
226
|
+
- **Clear**: Remove all events from history
|
|
227
|
+
- **Minimize**: Collapse panel to just show active blocker count
|
|
228
|
+
- **Close**: Hide devtools panel completely
|
|
229
|
+
|
|
230
|
+
### Keyboard Shortcuts
|
|
231
|
+
|
|
232
|
+
When the panel is open (and focus is not in an input):
|
|
233
|
+
|
|
234
|
+
- `Esc` - Close panel
|
|
235
|
+
- `Space` - Pause/Resume recording
|
|
236
|
+
- `C` - Clear events
|
|
237
|
+
|
|
238
|
+
## TypeScript Support
|
|
239
|
+
|
|
240
|
+
The package is written in TypeScript and includes full type definitions:
|
|
241
|
+
|
|
242
|
+
```typescript
|
|
243
|
+
import type {
|
|
244
|
+
// Component types
|
|
245
|
+
ActionGuardDevtoolsProps,
|
|
246
|
+
|
|
247
|
+
// Event types
|
|
248
|
+
DevtoolsEvent,
|
|
249
|
+
DevtoolsFilter,
|
|
250
|
+
|
|
251
|
+
// Store types
|
|
252
|
+
DevtoolsState,
|
|
253
|
+
DevtoolsActions,
|
|
254
|
+
DevtoolsStore,
|
|
255
|
+
|
|
256
|
+
// Position type
|
|
257
|
+
DevtoolsPosition,
|
|
258
|
+
} from "@okyrychenko-dev/react-action-guard-devtools";
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
## Use Cases
|
|
262
|
+
|
|
263
|
+
### Debugging Complex Blocking Logic
|
|
264
|
+
|
|
265
|
+
```jsx
|
|
266
|
+
import { useBlocker } from "@okyrychenko-dev/react-action-guard";
|
|
267
|
+
import { ActionGuardDevtools } from "@okyrychenko-dev/react-action-guard-devtools";
|
|
268
|
+
|
|
269
|
+
function ComplexForm() {
|
|
270
|
+
const [step, setStep] = useState(1);
|
|
271
|
+
|
|
272
|
+
// Multiple blockers with different priorities
|
|
273
|
+
useBlocker(
|
|
274
|
+
"validation",
|
|
275
|
+
{
|
|
276
|
+
scope: "form",
|
|
277
|
+
priority: 10,
|
|
278
|
+
},
|
|
279
|
+
!isValid
|
|
280
|
+
);
|
|
281
|
+
|
|
282
|
+
useBlocker(
|
|
283
|
+
"api-call",
|
|
284
|
+
{
|
|
285
|
+
scope: ["form", "navigation"],
|
|
286
|
+
priority: 100,
|
|
287
|
+
},
|
|
288
|
+
isLoading
|
|
289
|
+
);
|
|
290
|
+
|
|
291
|
+
// Devtools shows you exactly what's blocking and why
|
|
292
|
+
return (
|
|
293
|
+
<>
|
|
294
|
+
<form>...</form>
|
|
295
|
+
<ActionGuardDevtools defaultOpen={true} />
|
|
296
|
+
</>
|
|
297
|
+
);
|
|
298
|
+
}
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### Monitoring Production Issues
|
|
302
|
+
|
|
303
|
+
```jsx
|
|
304
|
+
// Enable devtools in production for specific users/scenarios
|
|
305
|
+
const isDebugMode = localStorage.getItem("debug") === "true";
|
|
306
|
+
|
|
307
|
+
function App() {
|
|
308
|
+
return (
|
|
309
|
+
<>
|
|
310
|
+
<YourApp />
|
|
311
|
+
<ActionGuardDevtools showInProduction={isDebugMode} position="left" />
|
|
312
|
+
</>
|
|
313
|
+
);
|
|
314
|
+
}
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
### Performance Monitoring
|
|
318
|
+
|
|
319
|
+
```jsx
|
|
320
|
+
import { useDevtoolsStore } from "@okyrychenko-dev/react-action-guard-devtools";
|
|
321
|
+
|
|
322
|
+
function PerformanceMonitor() {
|
|
323
|
+
const events = useDevtoolsStore((state) => state.events);
|
|
324
|
+
|
|
325
|
+
// Find slow blockers
|
|
326
|
+
const slowBlockers = events
|
|
327
|
+
.filter((e) => e.duration && e.duration > 5000)
|
|
328
|
+
.map((e) => ({
|
|
329
|
+
id: e.blockerId,
|
|
330
|
+
duration: e.duration,
|
|
331
|
+
}));
|
|
332
|
+
|
|
333
|
+
if (slowBlockers.length > 0) {
|
|
334
|
+
console.warn("Slow blockers detected:", slowBlockers);
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
return null;
|
|
338
|
+
}
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
## Development
|
|
342
|
+
|
|
343
|
+
```bash
|
|
344
|
+
# Install dependencies
|
|
345
|
+
npm install
|
|
346
|
+
|
|
347
|
+
# Run tests
|
|
348
|
+
npm run test
|
|
349
|
+
|
|
350
|
+
# Run tests with UI
|
|
351
|
+
npm run test:ui
|
|
352
|
+
|
|
353
|
+
# Run tests with coverage
|
|
354
|
+
npm run test:coverage
|
|
355
|
+
|
|
356
|
+
# Build the package
|
|
357
|
+
npm run build
|
|
358
|
+
|
|
359
|
+
# Type checking
|
|
360
|
+
npm run typecheck
|
|
361
|
+
|
|
362
|
+
# Lint code
|
|
363
|
+
npm run lint
|
|
364
|
+
|
|
365
|
+
# Fix lint errors
|
|
366
|
+
npm run lint:fix
|
|
367
|
+
|
|
368
|
+
# Format code
|
|
369
|
+
npm run format
|
|
370
|
+
|
|
371
|
+
# Watch mode for development
|
|
372
|
+
npm run dev
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
## Contributing
|
|
376
|
+
|
|
377
|
+
Contributions are welcome! Please ensure:
|
|
378
|
+
|
|
379
|
+
1. All tests pass (`npm run test`)
|
|
380
|
+
2. Code is properly typed (`npm run typecheck`)
|
|
381
|
+
3. Linting passes (`npm run lint`)
|
|
382
|
+
4. Code is formatted (`npm run format`)
|
|
383
|
+
|
|
384
|
+
## Changelog
|
|
385
|
+
|
|
386
|
+
See [CHANGELOG.md](./CHANGELOG.md) for a detailed list of changes in each version.
|
|
387
|
+
|
|
388
|
+
## Related Projects
|
|
389
|
+
|
|
390
|
+
- [@okyrychenko-dev/react-action-guard](https://github.com/okyrychenko-dev/react-action-guard) - Main library for UI blocking management
|
|
391
|
+
|
|
392
|
+
## License
|
|
393
|
+
|
|
394
|
+
MIT Β© Oleksii Kyrychenko
|