@okyrychenko-dev/react-action-guard 0.3.2 → 0.4.0

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2025 Olexii Kyrychenko
3
+ Copyright (c) 2025 Oleksii Kyrychenko
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -11,13 +11,15 @@
11
11
  - Priority-based blocking system
12
12
  - Scoped blocking (global, specific areas, or multiple scopes)
13
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
14
16
  - Advanced hooks for different use cases:
15
17
  - Confirmable blockers with custom dialogs
16
18
  - Scheduled blocking for maintenance windows
17
19
  - Conditional blocking based on application state
18
- - Async action wrapping
20
+ - Async action wrapping with timeout support
19
21
  - Advanced middleware system for analytics, logging, and performance monitoring
20
- - TypeScript support with full type safety
22
+ - TypeScript support with full type safety (including optional type-safe scopes)
21
23
  - Built on Zustand for efficient state management
22
24
  - Tree-shakeable - import only what you need
23
25
  - Hooks-based API
@@ -34,8 +36,8 @@ pnpm add @okyrychenko-dev/react-action-guard zustand
34
36
 
35
37
  This package requires the following peer dependencies:
36
38
 
37
- - [React](https://react.dev/) ^17.0.0 || ^18.0.0
38
- - [Zustand](https://zustand-demo.pmnd.rs/) - State management library
39
+ - [React](https://react.dev/) ^17.0.0 || ^18.0.0 || ^19.0.0
40
+ - [Zustand](https://zustand-demo.pmnd.rs/) ^4.5.7 || ^5.0.0 - State management library
39
41
 
40
42
  ## Quick Start
41
43
 
@@ -74,6 +76,8 @@ Automatically adds a blocker when the component mounts and removes it on unmount
74
76
  - `scope?: string | string[]` - Scope(s) to block (default: "global")
75
77
  - `reason?: string` - Reason for blocking (for debugging)
76
78
  - `priority?: number` - Priority level (higher = more important)
79
+ - `timeout?: number` - Auto-remove after N milliseconds
80
+ - `onTimeout?: (blockerId: string) => void` - Callback when auto-removed
77
81
  - `isActive?: boolean` - Whether the blocker is active (default: true)
78
82
 
79
83
  **Example:**
@@ -88,6 +92,33 @@ function MyComponent() {
88
92
 
89
93
  return <div>Content</div>;
90
94
  }
95
+
96
+ // With timeout - auto-removes after 30 seconds
97
+ function SaveButton() {
98
+ const [isSaving, setIsSaving] = useState(false);
99
+
100
+ useBlocker("save-operation", {
101
+ scope: "form",
102
+ reason: "Saving...",
103
+ timeout: 30000,
104
+ onTimeout: (id) => {
105
+ console.warn(`Operation ${id} timed out`);
106
+ showNotification("Operation timed out");
107
+ setIsSaving(false);
108
+ },
109
+ }, isSaving);
110
+
111
+ const handleSave = async () => {
112
+ setIsSaving(true);
113
+ try {
114
+ await saveData();
115
+ } finally {
116
+ setIsSaving(false);
117
+ }
118
+ };
119
+
120
+ return <button onClick={handleSave} disabled={isSaving}>Save</button>;
121
+ }
91
122
  ```
92
123
 
93
124
  #### `useIsBlocked(scope)`
@@ -110,7 +141,44 @@ function SubmitButton() {
110
141
  }
111
142
  ```
112
143
 
113
- #### `useAsyncAction(actionId, scope)`
144
+ #### `useBlockingInfo(scope)`
145
+
146
+ Gets detailed information about all active blockers for a specific scope.
147
+
148
+ **Parameters:**
149
+
150
+ - `scope?: string` - Scope to get blocking information for (default: "global")
151
+
152
+ **Returns:** `ReadonlyArray<BlockerInfo>` - Array of blocker information objects, sorted by priority (highest first)
153
+
154
+ **BlockerInfo:**
155
+
156
+ - `id: string` - Unique identifier of the blocker
157
+ - `reason?: string` - Reason for blocking
158
+ - `priority: number` - Priority level (0-100)
159
+ - `scope: string | string[]` - Scope(s) being blocked
160
+ - `timestamp: number` - When the blocker was added
161
+
162
+ **Example:**
163
+
164
+ ```jsx
165
+ function CheckoutButton() {
166
+ const blockers = useBlockingInfo("checkout");
167
+
168
+ if (blockers.length > 0) {
169
+ const topBlocker = blockers[0]; // Highest priority blocker
170
+ return (
171
+ <Tooltip content={`Blocked: ${topBlocker.reason}`}>
172
+ <Button disabled>Checkout ({blockers.length} blockers)</Button>
173
+ </Tooltip>
174
+ );
175
+ }
176
+
177
+ return <Button>Checkout</Button>;
178
+ }
179
+ ```
180
+
181
+ #### `useAsyncAction(actionId, scope, options)`
114
182
 
115
183
  Wraps an async function with automatic blocking/unblocking.
116
184
 
@@ -118,6 +186,9 @@ Wraps an async function with automatic blocking/unblocking.
118
186
 
119
187
  - `actionId: string` - Identifier for the action
120
188
  - `scope?: string | string[]` - Scope(s) to block during execution
189
+ - `options?: UseAsyncActionOptions` - Optional configuration
190
+ - `timeout?: number` - Auto-remove blocker after N milliseconds
191
+ - `onTimeout?: (blockerId: string) => void` - Callback when timed out
121
192
 
122
193
  **Returns:** `(asyncFn: () => Promise<T>) => Promise<T>` - Function wrapper
123
194
 
@@ -135,6 +206,23 @@ function MyComponent() {
135
206
 
136
207
  return <button onClick={handleSave}>Save</button>;
137
208
  }
209
+
210
+ // With timeout - prevents infinite blocking if operation hangs
211
+ function ApiComponent() {
212
+ const execute = useAsyncAction("api-call", "global", {
213
+ timeout: 60000, // 1 minute timeout
214
+ onTimeout: (id) => {
215
+ showError("Request timed out. Please try again.");
216
+ },
217
+ });
218
+
219
+ const fetchData = () => execute(async () => {
220
+ const response = await fetch("/api/data");
221
+ return response.json();
222
+ });
223
+
224
+ return <button onClick={fetchData}>Fetch Data</button>;
225
+ }
138
226
  ```
139
227
 
140
228
  #### `useConfirmableBlocker(blockerId, config, options)`
@@ -159,7 +247,7 @@ Creates a blocker that requires user confirmation before being removed.
159
247
  **Example:**
160
248
 
161
249
  ```jsx
162
- function UnsavedChangesGuard() {
250
+ function UnsavedChangesGuard({ hasUnsavedChanges, discardChanges }) {
163
251
  const { isBlocking, requestRemoval } = useConfirmableBlocker(
164
252
  "unsaved-changes",
165
253
  {
@@ -269,6 +357,56 @@ function NetworkStatusBlocker() {
269
357
  }
270
358
  ```
271
359
 
360
+ ### Provider (Optional)
361
+
362
+ #### `UIBlockingProvider`
363
+
364
+ Provides an isolated store instance for SSR, testing, or micro-frontends. Without the provider, hooks use a global store.
365
+
366
+ **Props:**
367
+
368
+ - `children: ReactNode` - Child components
369
+ - `enableDevtools?: boolean` - Enable Redux DevTools (default: true in development)
370
+ - `devtoolsName?: string` - Name for DevTools (default: "UIBlocking")
371
+ - `middlewares?: Middleware[]` - Initial middlewares to register
372
+
373
+ **Example:**
374
+
375
+ ```jsx
376
+ import { UIBlockingProvider } from "@okyrychenko-dev/react-action-guard";
377
+
378
+ // SSR - each request gets isolated state
379
+ function App() {
380
+ return (
381
+ <UIBlockingProvider>
382
+ <MyApp />
383
+ </UIBlockingProvider>
384
+ );
385
+ }
386
+
387
+ // Testing - isolated state per test, no cleanup needed
388
+ function renderWithProvider(ui) {
389
+ return render(
390
+ <UIBlockingProvider>{ui}</UIBlockingProvider>
391
+ );
392
+ }
393
+
394
+ // Micro-frontends - each app has its own blocking state
395
+ function MicroFrontend() {
396
+ return (
397
+ <UIBlockingProvider devtoolsName="MicroApp-Blocking">
398
+ <MicroApp />
399
+ </UIBlockingProvider>
400
+ );
401
+ }
402
+ ```
403
+
404
+ #### Context Hooks
405
+
406
+ - `useUIBlockingContext()` - Get store from context (throws if outside provider)
407
+ - `useIsInsideUIBlockingProvider()` - Check if inside a provider
408
+ - `useUIBlockingStoreFromContext(selector)` - Select state from context store
409
+
272
410
  ### Store
273
411
 
274
412
  #### `useUIBlockingStore`
@@ -332,20 +470,23 @@ The library includes a powerful middleware system that allows you to hook into b
332
470
  Track blocker events with your analytics provider (Google Analytics, Mixpanel, Amplitude, or custom).
333
471
 
334
472
  ```jsx
335
- import { configureMiddleware, analyticsMiddleware } from "@okyrychenko-dev/react-action-guard";
473
+ import {
474
+ configureMiddleware,
475
+ createAnalyticsMiddleware,
476
+ } from "@okyrychenko-dev/react-action-guard";
336
477
 
337
478
  // Google Analytics
338
- configureMiddleware([analyticsMiddleware({ provider: "ga" })]);
479
+ configureMiddleware([createAnalyticsMiddleware({ provider: "ga" })]);
339
480
 
340
481
  // Mixpanel
341
- configureMiddleware([analyticsMiddleware({ provider: "mixpanel" })]);
482
+ configureMiddleware([createAnalyticsMiddleware({ provider: "mixpanel" })]);
342
483
 
343
484
  // Amplitude
344
- configureMiddleware([analyticsMiddleware({ provider: "amplitude" })]);
485
+ configureMiddleware([createAnalyticsMiddleware({ provider: "amplitude" })]);
345
486
 
346
487
  // Custom analytics
347
488
  configureMiddleware([
348
- analyticsMiddleware({
489
+ createAnalyticsMiddleware({
349
490
  track: (event, data) => {
350
491
  myAnalytics.track(event, data);
351
492
  },
@@ -368,10 +509,13 @@ configureMiddleware([loggerMiddleware]);
368
509
  Monitor blocker performance and detect slow operations.
369
510
 
370
511
  ```jsx
371
- import { configureMiddleware, performanceMiddleware } from "@okyrychenko-dev/react-action-guard";
512
+ import {
513
+ configureMiddleware,
514
+ createPerformanceMiddleware,
515
+ } from "@okyrychenko-dev/react-action-guard";
372
516
 
373
517
  configureMiddleware([
374
- performanceMiddleware({
518
+ createPerformanceMiddleware({
375
519
  onSlowBlock: (blockerId, duration) => {
376
520
  console.warn(`Blocker ${blockerId} was active for ${duration}ms`);
377
521
  },
@@ -409,15 +553,15 @@ You can combine multiple middleware for comprehensive monitoring:
409
553
  ```jsx
410
554
  import {
411
555
  configureMiddleware,
412
- analyticsMiddleware,
556
+ createAnalyticsMiddleware,
413
557
  loggerMiddleware,
414
- performanceMiddleware,
558
+ createPerformanceMiddleware,
415
559
  } from "@okyrychenko-dev/react-action-guard";
416
560
 
417
561
  configureMiddleware([
418
562
  loggerMiddleware,
419
- analyticsMiddleware({ provider: "ga" }),
420
- performanceMiddleware({
563
+ createAnalyticsMiddleware({ provider: "ga" }),
564
+ createPerformanceMiddleware({
421
565
  slowBlockThreshold: 3000,
422
566
  onSlowBlock: (blockerId, duration) => {
423
567
  // Send to error tracking service
@@ -438,7 +582,10 @@ The library is fully tree-shakeable. Import only the features you need to keep y
438
582
  import { useBlocker } from "@okyrychenko-dev/react-action-guard";
439
583
 
440
584
  // Middleware is not included unless you import it
441
- import { configureMiddleware, analyticsMiddleware } from "@okyrychenko-dev/react-action-guard";
585
+ import {
586
+ configureMiddleware,
587
+ createAnalyticsMiddleware,
588
+ } from "@okyrychenko-dev/react-action-guard";
442
589
  ```
443
590
 
444
591
  The package is configured with `"sideEffects": false`, allowing modern bundlers (Webpack, Rollup, Vite) to eliminate unused code automatically.
@@ -703,4 +850,4 @@ See [CHANGELOG.md](./CHANGELOG.md) for a detailed list of changes in each versio
703
850
 
704
851
  ## License
705
852
 
706
- MIT © Olexii Kyrychenko
853
+ MIT © Oleksii Kyrychenko
package/dist/index.cjs CHANGED
@@ -1,9 +1,10 @@
1
1
  'use strict';
2
2
 
3
3
  var react = require('react');
4
- var middleware = require('zustand/middleware');
5
4
  var zustand = require('zustand');
5
+ var middleware = require('zustand/middleware');
6
6
  var shallow = require('zustand/shallow');
7
+ var jsxRuntime = require('react/jsx-runtime');
7
8
 
8
9
  // src/hooks/useAsyncAction/useAsyncAction.ts
9
10
 
@@ -67,13 +68,40 @@ var createUIBlockingActions = (set, get) => ({
67
68
  *
68
69
  */
69
70
  addBlocker: (id, config = {}) => {
71
+ const existingBlocker = get().activeBlockers.get(id);
72
+ if (existingBlocker?.timeoutId) {
73
+ clearTimeout(existingBlocker.timeoutId);
74
+ }
75
+ let timeoutId;
76
+ if (config.timeout && config.timeout > 0) {
77
+ timeoutId = setTimeout(() => {
78
+ if (get().activeBlockers.has(id)) {
79
+ config.onTimeout?.(id);
80
+ void get().runMiddlewares({
81
+ action: "timeout",
82
+ blockerId: id,
83
+ config: {
84
+ scope: config.scope,
85
+ reason: config.reason,
86
+ priority: config.priority,
87
+ timeout: config.timeout
88
+ },
89
+ timestamp: Date.now()
90
+ });
91
+ get().removeBlocker(id);
92
+ }
93
+ }, config.timeout);
94
+ }
70
95
  set((state) => {
71
96
  const newBlockers = new Map(state.activeBlockers);
72
97
  const storedBlocker = {
73
98
  scope: config.scope ?? DEFAULT_SCOPE,
74
99
  reason: config.reason ?? DEFAULT_REASON,
75
100
  priority: config.priority ?? DEFAULT_PRIORITY,
76
- timestamp: config.timestamp ?? Date.now()
101
+ timestamp: config.timestamp ?? Date.now(),
102
+ timeout: config.timeout,
103
+ timeoutId,
104
+ onTimeout: config.onTimeout
77
105
  };
78
106
  newBlockers.set(id, storedBlocker);
79
107
  return { activeBlockers: newBlockers };
@@ -84,7 +112,8 @@ var createUIBlockingActions = (set, get) => ({
84
112
  config: {
85
113
  scope: config.scope,
86
114
  reason: config.reason,
87
- priority: config.priority
115
+ priority: config.priority,
116
+ timeout: config.timeout
88
117
  },
89
118
  timestamp: Date.now()
90
119
  });
@@ -97,6 +126,9 @@ var createUIBlockingActions = (set, get) => ({
97
126
  */
98
127
  removeBlocker: (id) => {
99
128
  const prevBlocker = get().activeBlockers.get(id);
129
+ if (prevBlocker?.timeoutId) {
130
+ clearTimeout(prevBlocker.timeoutId);
131
+ }
100
132
  set((state) => {
101
133
  const newBlockers = new Map(state.activeBlockers);
102
134
  newBlockers.delete(id);
@@ -155,6 +187,12 @@ var createUIBlockingActions = (set, get) => ({
155
187
  * Clear all blockers from the store
156
188
  */
157
189
  clearAllBlockers: () => {
190
+ const { activeBlockers } = get();
191
+ for (const [, blocker] of activeBlockers) {
192
+ if (blocker.timeoutId) {
193
+ clearTimeout(blocker.timeoutId);
194
+ }
195
+ }
158
196
  set({ activeBlockers: /* @__PURE__ */ new Map() });
159
197
  },
160
198
  /**
@@ -164,6 +202,13 @@ var createUIBlockingActions = (set, get) => ({
164
202
  *
165
203
  */
166
204
  clearBlockersForScope: (scope) => {
205
+ const { activeBlockers } = get();
206
+ for (const [, blocker] of activeBlockers) {
207
+ const blockerScopes = normalizeScopeToArray(blocker.scope);
208
+ if (blockerScopes.includes(scope) && blocker.timeoutId) {
209
+ clearTimeout(blocker.timeoutId);
210
+ }
211
+ }
167
212
  set((state) => {
168
213
  const newBlockers = /* @__PURE__ */ new Map();
169
214
  for (const [id, blocker] of state.activeBlockers) {
@@ -176,6 +221,45 @@ var createUIBlockingActions = (set, get) => ({
176
221
  });
177
222
  }
178
223
  });
224
+ var UIBlockingContext = react.createContext(null);
225
+ function UIBlockingProvider({
226
+ children,
227
+ enableDevtools = process.env.NODE_ENV === "development",
228
+ devtoolsName = "UIBlocking",
229
+ middlewares = []
230
+ }) {
231
+ const middlewaresRef = react.useRef(middlewares);
232
+ const store = react.useMemo(() => {
233
+ const baseStore = enableDevtools ? zustand.createStore(
234
+ middleware.devtools(createUIBlockingActions, {
235
+ name: devtoolsName,
236
+ enabled: enableDevtools
237
+ })
238
+ ) : zustand.createStore(createUIBlockingActions);
239
+ middlewaresRef.current.forEach((mw, index) => {
240
+ baseStore.getState().registerMiddleware(`provider-middleware-${index.toString()}`, mw);
241
+ });
242
+ return baseStore;
243
+ }, [enableDevtools, devtoolsName]);
244
+ return /* @__PURE__ */ jsxRuntime.jsx(UIBlockingContext.Provider, { value: store, children });
245
+ }
246
+ function useUIBlockingContext() {
247
+ const store = react.useContext(UIBlockingContext);
248
+ if (!store) {
249
+ throw new Error(
250
+ "useUIBlockingContext must be used within UIBlockingProvider. Either wrap your app in <UIBlockingProvider> or use the global store via useUIBlockingStore."
251
+ );
252
+ }
253
+ return store;
254
+ }
255
+ function useIsInsideUIBlockingProvider() {
256
+ const store = react.useContext(UIBlockingContext);
257
+ return store !== null;
258
+ }
259
+ function useUIBlockingStoreFromContext(selector) {
260
+ const store = useUIBlockingContext();
261
+ return zustand.useStore(store, shallow.useShallow(selector));
262
+ }
179
263
 
180
264
  // src/store/uiBlockingStore.config.ts
181
265
  var devtoolsConfig = {
@@ -186,9 +270,19 @@ var devtoolsConfig = {
186
270
  // src/store/uiBlockingStore.store.ts
187
271
  var { useStore: useUIBlockingStore, useStoreApi: uiBlockingStoreApi } = createShallowStore(middleware.devtools(createUIBlockingActions, devtoolsConfig));
188
272
 
273
+ // src/context/useResolvedStore.ts
274
+ function useResolvedStore() {
275
+ const contextStore = react.useContext(UIBlockingContext);
276
+ return contextStore ?? uiBlockingStoreApi;
277
+ }
278
+ function useResolvedStoreWithSelector(selector) {
279
+ const store = useResolvedStore();
280
+ return zustand.useStore(store, shallow.useShallow(selector));
281
+ }
282
+
189
283
  // src/hooks/useAsyncAction/useAsyncAction.ts
190
- var useAsyncAction = (actionId, scope) => {
191
- const { addBlocker, removeBlocker } = useUIBlockingStore((state) => ({
284
+ var useAsyncAction = (actionId, scope, options) => {
285
+ const { addBlocker, removeBlocker } = useResolvedStoreWithSelector((state) => ({
192
286
  addBlocker: state.addBlocker,
193
287
  removeBlocker: state.removeBlocker
194
288
  }));
@@ -199,19 +293,21 @@ var useAsyncAction = (actionId, scope) => {
199
293
  addBlocker(blockerId, {
200
294
  scope,
201
295
  reason: `Executing ${actionId}`,
202
- priority: ASYNC_ACTION_PRIORITY
296
+ priority: ASYNC_ACTION_PRIORITY,
297
+ timeout: options?.timeout,
298
+ onTimeout: options?.onTimeout
203
299
  });
204
300
  return await asyncFn();
205
301
  } finally {
206
302
  removeBlocker(blockerId);
207
303
  }
208
304
  },
209
- [actionId, scope, addBlocker, removeBlocker]
305
+ [actionId, scope, options?.timeout, options?.onTimeout, addBlocker, removeBlocker]
210
306
  );
211
307
  return executeWithBlocking;
212
308
  };
213
309
  var useBlocker = (blockerId, config, isActive = true) => {
214
- const { addBlocker, removeBlocker } = useUIBlockingStore((state) => ({
310
+ const { addBlocker, removeBlocker } = useResolvedStoreWithSelector((state) => ({
215
311
  addBlocker: state.addBlocker,
216
312
  removeBlocker: state.removeBlocker
217
313
  }));
@@ -234,6 +330,13 @@ function createBlockerConfig(config) {
234
330
  priority: config.priority
235
331
  };
236
332
  }
333
+ var useBlockingInfo = (scope = DEFAULT_SCOPE) => {
334
+ const store = useResolvedStore();
335
+ const activeBlockers = zustand.useStore(store, (state) => state.activeBlockers);
336
+ return react.useMemo(() => {
337
+ return store.getState().getBlockingInfo(scope);
338
+ }, [activeBlockers, scope, store]);
339
+ };
237
340
  function useConfigRef(config) {
238
341
  const configRef = react.useRef(config);
239
342
  react.useEffect(() => {
@@ -244,7 +347,7 @@ function useConfigRef(config) {
244
347
 
245
348
  // src/hooks/useConditionalBlocker/useConditionalBlocker.ts
246
349
  var useConditionalBlocker = (blockerId, config) => {
247
- const { addBlocker, removeBlocker } = useUIBlockingStore((state) => ({
350
+ const { addBlocker, removeBlocker } = useResolvedStoreWithSelector((state) => ({
248
351
  addBlocker: state.addBlocker,
249
352
  removeBlocker: state.removeBlocker
250
353
  }));
@@ -327,7 +430,7 @@ var useConfirmableBlocker = (blockerId, config) => {
327
430
 
328
431
  // src/hooks/useIsBlocked/useIsBlocked.ts
329
432
  var useIsBlocked = (scope) => {
330
- return useUIBlockingStore((state) => state.isBlocked(scope));
433
+ return useResolvedStoreWithSelector((state) => state.isBlocked(scope));
331
434
  };
332
435
 
333
436
  // src/hooks/useScheduledBlocker/useScheduledBlocker.utils.ts
@@ -369,7 +472,7 @@ function isScheduleInPast(startTime, endTime, now) {
369
472
 
370
473
  // src/hooks/useScheduledBlocker/useScheduledBlocker.ts
371
474
  var useScheduledBlocker = (blockerId, config) => {
372
- const { addBlocker, removeBlocker } = useUIBlockingStore((state) => ({
475
+ const { addBlocker, removeBlocker } = useResolvedStoreWithSelector((state) => ({
373
476
  addBlocker: state.addBlocker,
374
477
  removeBlocker: state.removeBlocker
375
478
  }));
@@ -506,6 +609,15 @@ var createAnalyticsMiddleware = (config) => {
506
609
  };
507
610
  };
508
611
 
612
+ // src/middleware/configureMiddleware.ts
613
+ function configureMiddleware(middlewares) {
614
+ const store = uiBlockingStoreApi.getState();
615
+ middlewares.forEach((middleware, index) => {
616
+ const name = `middleware-${index.toString()}`;
617
+ store.registerMiddleware(name, middleware);
618
+ });
619
+ }
620
+
509
621
  // src/middleware/loggerMiddleware.utils.ts
510
622
  var getActionEmoji = (action) => {
511
623
  switch (action) {
@@ -591,16 +703,39 @@ var createPerformanceMiddleware = (config = {}) => {
591
703
  };
592
704
  };
593
705
 
706
+ // src/createTypedHooks.ts
707
+ function createTypedHooks() {
708
+ return {
709
+ useBlocker: (blockerId, config, isActive) => {
710
+ useBlocker(blockerId, config, isActive);
711
+ },
712
+ useIsBlocked: (scope) => {
713
+ return useIsBlocked(scope);
714
+ },
715
+ useAsyncAction: (actionId, scope, options) => {
716
+ return useAsyncAction(actionId, scope, options);
717
+ },
718
+ useBlockingInfo: (scope) => useBlockingInfo(scope)
719
+ };
720
+ }
721
+
722
+ exports.UIBlockingProvider = UIBlockingProvider;
723
+ exports.configureMiddleware = configureMiddleware;
594
724
  exports.createAnalyticsMiddleware = createAnalyticsMiddleware;
595
725
  exports.createPerformanceMiddleware = createPerformanceMiddleware;
726
+ exports.createTypedHooks = createTypedHooks;
596
727
  exports.loggerMiddleware = loggerMiddleware;
597
728
  exports.uiBlockingStoreApi = uiBlockingStoreApi;
598
729
  exports.useAsyncAction = useAsyncAction;
599
730
  exports.useBlocker = useBlocker;
731
+ exports.useBlockingInfo = useBlockingInfo;
600
732
  exports.useConditionalBlocker = useConditionalBlocker;
601
733
  exports.useConfirmableBlocker = useConfirmableBlocker;
602
734
  exports.useIsBlocked = useIsBlocked;
735
+ exports.useIsInsideUIBlockingProvider = useIsInsideUIBlockingProvider;
603
736
  exports.useScheduledBlocker = useScheduledBlocker;
737
+ exports.useUIBlockingContext = useUIBlockingContext;
604
738
  exports.useUIBlockingStore = useUIBlockingStore;
739
+ exports.useUIBlockingStoreFromContext = useUIBlockingStoreFromContext;
605
740
  //# sourceMappingURL=index.cjs.map
606
741
  //# sourceMappingURL=index.cjs.map