@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/dist/index.d.ts CHANGED
@@ -1,18 +1,32 @@
1
1
  import * as zustand from 'zustand';
2
+ import { StoreApi } from 'zustand';
3
+ import { ReactNode } from 'react';
2
4
 
5
+ /**
6
+ * Options for useAsyncAction hook
7
+ */
8
+ interface UseAsyncActionOptions {
9
+ /** Timeout in milliseconds after which the blocker will be automatically removed */
10
+ timeout?: number;
11
+ /** Callback invoked when the blocker is automatically removed due to timeout */
12
+ onTimeout?: (blockerId: string) => void;
13
+ }
3
14
  /**
4
15
  * Hook to wrap async functions with automatic blocking/unblocking
5
16
  *
6
17
  * Creates a wrapper function that automatically adds a blocker before executing
7
18
  * the async function and removes it after completion (success or failure).
8
19
  *
20
+ * Supports both global store and context store (via UIBlockingProvider).
21
+ *
9
22
  * @template T - The return type of the async function
10
23
  * @param actionId - Unique identifier for the action (used in blocker ID and reason)
11
24
  * @param scope - Scope(s) to block during execution (default: "global")
25
+ * @param options - Optional configuration including timeout
12
26
  * @returns Function that wraps async functions with blocking behavior
13
27
  *
14
28
  */
15
- declare const useAsyncAction: <T = unknown>(actionId: string, scope?: string | ReadonlyArray<string>) => ((asyncFn: () => Promise<T>) => Promise<T>);
29
+ declare const useAsyncAction: <T = unknown>(actionId: string, scope?: string | ReadonlyArray<string>, options?: UseAsyncActionOptions) => ((asyncFn: () => Promise<T>) => Promise<T>);
16
30
 
17
31
  type AnalyticsEventData = Record<string, string | number | ReadonlyArray<string> | undefined>;
18
32
  type AnalyticsProvider = "ga" | "mixpanel" | "amplitude";
@@ -43,6 +57,17 @@ type Middleware = (context: MiddlewareContext) => void | Promise<void>;
43
57
 
44
58
  declare const createAnalyticsMiddleware: (config: AnalyticsConfig) => Middleware;
45
59
 
60
+ /**
61
+ * Configure middleware for the UI blocking store
62
+ *
63
+ * This is a convenience function that registers multiple middleware at once.
64
+ * Each middleware will be registered with an auto-generated name based on its index.
65
+ *
66
+ * @param middlewares - Array of middleware functions to register
67
+ *
68
+ */
69
+ declare function configureMiddleware(middlewares: ReadonlyArray<Middleware>): void;
70
+
46
71
  declare const loggerMiddleware: Middleware;
47
72
 
48
73
  interface PerformanceConfig {
@@ -60,6 +85,10 @@ interface BlockerConfig {
60
85
  reason?: string;
61
86
  priority?: number;
62
87
  timestamp?: number;
88
+ /** Automatically remove the blocker after N milliseconds */
89
+ timeout?: number;
90
+ /** Callback invoked when the blocker is automatically removed due to timeout */
91
+ onTimeout?: (blockerId: string) => void;
63
92
  }
64
93
  /**
65
94
  * Stored blocker with all required fields
@@ -69,6 +98,12 @@ interface StoredBlocker {
69
98
  reason: string;
70
99
  priority: number;
71
100
  timestamp: number;
101
+ /** Timeout duration in milliseconds (if set) */
102
+ timeout?: number;
103
+ /** Internal timeout ID for cleanup */
104
+ timeoutId?: ReturnType<typeof setTimeout>;
105
+ /** Callback invoked when the blocker is automatically removed due to timeout */
106
+ onTimeout?: (blockerId: string) => void;
72
107
  }
73
108
  /**
74
109
  * Blocker information including its ID
@@ -124,6 +159,8 @@ declare const uiBlockingStoreApi: zustand.StoreApi<UIBlockingStore>;
124
159
  * Automatically adds a blocker when the component mounts (or when activated)
125
160
  * and removes it when the component unmounts (or when deactivated).
126
161
  *
162
+ * Supports both global store and context store (via UIBlockingProvider).
163
+ *
127
164
  * @param blockerId - Unique identifier for the blocker
128
165
  * @param config - Blocker configuration (scope, reason, priority)
129
166
  * @param isActive - Whether the blocker is currently active (default: true)
@@ -131,6 +168,24 @@ declare const uiBlockingStoreApi: zustand.StoreApi<UIBlockingStore>;
131
168
  */
132
169
  declare const useBlocker: (blockerId: string, config: BlockerConfig, isActive?: boolean) => void;
133
170
 
171
+ /**
172
+ * Hook to get detailed blocking information for a scope
173
+ *
174
+ * Returns an array of blocker information objects for the specified scope,
175
+ * sorted by priority (highest first). Automatically re-renders when blockers change.
176
+ *
177
+ * Uses a stable reference - only re-renders when the actual blocker list changes,
178
+ * not on every store update.
179
+ *
180
+ * Supports both global store and context store (via UIBlockingProvider).
181
+ *
182
+ * @param scope - Scope to get blocking information for (default: "global")
183
+ * @returns Array of blocker information objects, sorted by priority
184
+ *
185
+ * ```
186
+ */
187
+ declare const useBlockingInfo: (scope?: string) => ReadonlyArray<BlockerInfo>;
188
+
134
189
  /**
135
190
  * Configuration for conditional blocker hook.
136
191
  *
@@ -154,6 +209,8 @@ interface ConditionalBlockerConfig<TState = unknown> extends Omit<BlockerConfig,
154
209
  * Periodically checks a condition and blocks/unblocks based on the result.
155
210
  * The condition is evaluated at the specified interval (default 1000ms).
156
211
  *
212
+ * Supports both global store and context store (via UIBlockingProvider).
213
+ *
157
214
  * @param blockerId - Unique identifier for this blocker
158
215
  * @param config - Configuration including condition function and check interval
159
216
  *
@@ -213,6 +270,8 @@ declare const useConfirmableBlocker: (blockerId: string, config: ConfirmableBloc
213
270
  * Returns a boolean indicating whether the specified scope(s) are blocked.
214
271
  * Automatically re-renders when the blocking state changes.
215
272
  *
273
+ * Supports both global store and context store (via UIBlockingProvider).
274
+ *
216
275
  * @param scope - Scope or array of scopes to check (default: "global")
217
276
  * @returns True if any of the specified scopes are blocked
218
277
  *
@@ -255,10 +314,148 @@ interface ScheduledBlockerConfig extends BlockerConfig {
255
314
  * Supports start/end times as Date objects, ISO strings, or timestamps.
256
315
  * If both duration and end are provided, duration takes precedence.
257
316
  *
317
+ * Supports both global store and context store (via UIBlockingProvider).
318
+ *
258
319
  * @param blockerId - Unique identifier for this blocker
259
320
  * @param config - Configuration including schedule and callbacks
260
321
  *
261
322
  */
262
323
  declare const useScheduledBlocker: (blockerId: string, config: ScheduledBlockerConfig) => void;
263
324
 
264
- export { type AmplitudeConfig, type AnalyticsConfig, type AnalyticsEventData, type AnalyticsProvider, type BlockerConfig, type BlockerInfo, type BlockingAction, type BlockingSchedule, type ConditionalBlockerConfig, type ConfirmDialogConfig, type ConfirmableBlockerConfig, type CustomAnalyticsConfig, type GoogleAnalyticsConfig, type Middleware, type MiddlewareContext, type MixpanelConfig, type PerformanceConfig, type ScheduledBlockerConfig, type StoredBlocker, type UIBlockingStore, type UIBlockingStoreActions, type UIBlockingStoreState, type UseConfirmableBlockerReturn, createAnalyticsMiddleware, createPerformanceMiddleware, loggerMiddleware, uiBlockingStoreApi, useAsyncAction, useBlocker, useConditionalBlocker, useConfirmableBlocker, useIsBlocked, useScheduledBlocker, useUIBlockingStore };
325
+ /**
326
+ * Default scope type
327
+ */
328
+ type DefaultScopes = "global";
329
+ /**
330
+ * Utility type for scope values - can be a single scope or array of scopes
331
+ */
332
+ type ScopeValue<TScope extends string = string> = TScope | ReadonlyArray<TScope>;
333
+ /**
334
+ * Type-safe blocker configuration with generic scope type
335
+ */
336
+ interface BlockerConfigTyped<TScope extends string> {
337
+ /** Scope(s) to block */
338
+ scope?: ScopeValue<TScope>;
339
+ /** Human-readable reason for blocking */
340
+ reason?: string;
341
+ /** Priority level (higher priority blockers take precedence) */
342
+ priority?: number;
343
+ /** Timestamp when the blocker was created */
344
+ timestamp?: number;
345
+ /** Timeout in milliseconds after which the blocker will be automatically removed */
346
+ timeout?: number;
347
+ /** Callback invoked when the blocker is automatically removed due to timeout */
348
+ onTimeout?: (blockerId: string) => void;
349
+ }
350
+
351
+ /**
352
+ * Return type for createTypedHooks factory
353
+ */
354
+ interface TypedHooks<TScope extends string> {
355
+ /**
356
+ * Type-safe version of useBlocker hook
357
+ */
358
+ useBlocker: (blockerId: string, config: BlockerConfigTyped<TScope>, isActive?: boolean) => void;
359
+ /**
360
+ * Type-safe version of useIsBlocked hook
361
+ */
362
+ useIsBlocked: (scope?: ScopeValue<TScope>) => boolean;
363
+ /**
364
+ * Type-safe version of useAsyncAction hook
365
+ */
366
+ useAsyncAction: <T = unknown>(actionId: string, scope?: ScopeValue<TScope>, options?: UseAsyncActionOptions) => (asyncFn: () => Promise<T>) => Promise<T>;
367
+ /**
368
+ * Type-safe version of useBlockingInfo hook
369
+ */
370
+ useBlockingInfo: (scope: TScope) => ReturnType<typeof useBlockingInfo>;
371
+ }
372
+ /**
373
+ * Creates type-safe versions of all blocking hooks with your custom scope types
374
+ *
375
+ * @template TScope - Union type of allowed scope strings
376
+ * @returns Object with type-safe hook functions
377
+ *
378
+ * @example
379
+ * ```typescript
380
+ * // Define your app's scopes
381
+ * type AppScopes = "global" | "form" | "navigation" | "checkout";
382
+ *
383
+ * // Create typed hooks
384
+ * const { useBlocker, useIsBlocked, useAsyncAction } = createTypedHooks<AppScopes>();
385
+ *
386
+ * // Now TypeScript will catch typos
387
+ * useBlocker("id", { scope: "form" }); // ✓ OK
388
+ * useBlocker("id", { scope: "typo" }); // ✗ Type error!
389
+ * ```
390
+ */
391
+ declare function createTypedHooks<TScope extends string>(): TypedHooks<TScope>;
392
+
393
+ /**
394
+ * Props for UIBlockingProvider component
395
+ */
396
+ interface UIBlockingProviderProps {
397
+ children: ReactNode;
398
+ /** Enable Redux DevTools integration (default: true in development) */
399
+ enableDevtools?: boolean;
400
+ /** Name for Redux DevTools (default: "UIBlocking") */
401
+ devtoolsName?: string;
402
+ /** Initial middlewares to register */
403
+ middlewares?: ReadonlyArray<Middleware>;
404
+ }
405
+ /**
406
+ * Provider component for isolated UI blocking state
407
+ *
408
+ * Use this to create an isolated store instance for:
409
+ * - Server-side rendering (each request gets its own store)
410
+ * - Testing (no need for beforeEach cleanup)
411
+ * - Micro-frontends (isolated state per app)
412
+ *
413
+ * @example
414
+ * ```tsx
415
+ * // SSR - each request gets its own store
416
+ * function App() {
417
+ * return (
418
+ * <UIBlockingProvider>
419
+ * <MyComponent />
420
+ * </UIBlockingProvider>
421
+ * );
422
+ * }
423
+ *
424
+ * // Testing - isolated store per test
425
+ * function renderWithProvider(ui: ReactElement) {
426
+ * return render(
427
+ * <UIBlockingProvider>{ui}</UIBlockingProvider>
428
+ * );
429
+ * }
430
+ * ```
431
+ */
432
+ declare function UIBlockingProvider({ children, enableDevtools, devtoolsName, middlewares, }: UIBlockingProviderProps): ReactNode;
433
+ /**
434
+ * Hook to access the UIBlocking store from context
435
+ *
436
+ * Throws an error if used outside of UIBlockingProvider.
437
+ * Use useUIBlockingStoreFromContext for safe access with fallback.
438
+ *
439
+ * @returns The store API from the nearest UIBlockingProvider
440
+ * @throws Error if used outside of UIBlockingProvider
441
+ */
442
+ declare function useUIBlockingContext(): StoreApi<UIBlockingStore>;
443
+ /**
444
+ * Hook to check if we're inside a UIBlockingProvider
445
+ *
446
+ * @returns true if inside UIBlockingProvider, false otherwise
447
+ */
448
+ declare function useIsInsideUIBlockingProvider(): boolean;
449
+ /**
450
+ * Hook to use the UIBlocking store from context with a selector
451
+ *
452
+ * This is similar to useUIBlockingStore but uses the context store.
453
+ * Automatically applies shallow comparison to prevent unnecessary re-renders.
454
+ *
455
+ * @param selector - Selector function to pick state from the store
456
+ * @returns Selected state value
457
+ * @throws Error if used outside of UIBlockingProvider
458
+ */
459
+ declare function useUIBlockingStoreFromContext<T>(selector: (state: UIBlockingStore) => T): T;
460
+
461
+ export { type AmplitudeConfig, type AnalyticsConfig, type AnalyticsEventData, type AnalyticsProvider, type BlockerConfig, type BlockerConfigTyped, type BlockerInfo, type BlockingAction, type BlockingSchedule, type ConditionalBlockerConfig, type ConfirmDialogConfig, type ConfirmableBlockerConfig, type CustomAnalyticsConfig, type DefaultScopes, type GoogleAnalyticsConfig, type Middleware, type MiddlewareContext, type MixpanelConfig, type PerformanceConfig, type ScheduledBlockerConfig, type ScopeValue, type StoredBlocker, type TypedHooks, UIBlockingProvider, type UIBlockingProviderProps, type UIBlockingStore, type UIBlockingStoreActions, type UIBlockingStoreState, type UseAsyncActionOptions, type UseConfirmableBlockerReturn, configureMiddleware, createAnalyticsMiddleware, createPerformanceMiddleware, createTypedHooks, loggerMiddleware, uiBlockingStoreApi, useAsyncAction, useBlocker, useBlockingInfo, useConditionalBlocker, useConfirmableBlocker, useIsBlocked, useIsInsideUIBlockingProvider, useScheduledBlocker, useUIBlockingContext, useUIBlockingStore, useUIBlockingStoreFromContext };
package/dist/index.js CHANGED
@@ -1,7 +1,8 @@
1
- import { useCallback, useEffect, useRef, useState } from 'react';
2
- import { devtools } from 'zustand/middleware';
1
+ import { createContext, useRef, useMemo, useContext, useCallback, useEffect, useState } from 'react';
3
2
  import { createStore, useStore } from 'zustand';
3
+ import { devtools } from 'zustand/middleware';
4
4
  import { useShallow } from 'zustand/shallow';
5
+ import { jsx } from 'react/jsx-runtime';
5
6
 
6
7
  // src/hooks/useAsyncAction/useAsyncAction.ts
7
8
 
@@ -65,13 +66,40 @@ var createUIBlockingActions = (set, get) => ({
65
66
  *
66
67
  */
67
68
  addBlocker: (id, config = {}) => {
69
+ const existingBlocker = get().activeBlockers.get(id);
70
+ if (existingBlocker?.timeoutId) {
71
+ clearTimeout(existingBlocker.timeoutId);
72
+ }
73
+ let timeoutId;
74
+ if (config.timeout && config.timeout > 0) {
75
+ timeoutId = setTimeout(() => {
76
+ if (get().activeBlockers.has(id)) {
77
+ config.onTimeout?.(id);
78
+ void get().runMiddlewares({
79
+ action: "timeout",
80
+ blockerId: id,
81
+ config: {
82
+ scope: config.scope,
83
+ reason: config.reason,
84
+ priority: config.priority,
85
+ timeout: config.timeout
86
+ },
87
+ timestamp: Date.now()
88
+ });
89
+ get().removeBlocker(id);
90
+ }
91
+ }, config.timeout);
92
+ }
68
93
  set((state) => {
69
94
  const newBlockers = new Map(state.activeBlockers);
70
95
  const storedBlocker = {
71
96
  scope: config.scope ?? DEFAULT_SCOPE,
72
97
  reason: config.reason ?? DEFAULT_REASON,
73
98
  priority: config.priority ?? DEFAULT_PRIORITY,
74
- timestamp: config.timestamp ?? Date.now()
99
+ timestamp: config.timestamp ?? Date.now(),
100
+ timeout: config.timeout,
101
+ timeoutId,
102
+ onTimeout: config.onTimeout
75
103
  };
76
104
  newBlockers.set(id, storedBlocker);
77
105
  return { activeBlockers: newBlockers };
@@ -82,7 +110,8 @@ var createUIBlockingActions = (set, get) => ({
82
110
  config: {
83
111
  scope: config.scope,
84
112
  reason: config.reason,
85
- priority: config.priority
113
+ priority: config.priority,
114
+ timeout: config.timeout
86
115
  },
87
116
  timestamp: Date.now()
88
117
  });
@@ -95,6 +124,9 @@ var createUIBlockingActions = (set, get) => ({
95
124
  */
96
125
  removeBlocker: (id) => {
97
126
  const prevBlocker = get().activeBlockers.get(id);
127
+ if (prevBlocker?.timeoutId) {
128
+ clearTimeout(prevBlocker.timeoutId);
129
+ }
98
130
  set((state) => {
99
131
  const newBlockers = new Map(state.activeBlockers);
100
132
  newBlockers.delete(id);
@@ -153,6 +185,12 @@ var createUIBlockingActions = (set, get) => ({
153
185
  * Clear all blockers from the store
154
186
  */
155
187
  clearAllBlockers: () => {
188
+ const { activeBlockers } = get();
189
+ for (const [, blocker] of activeBlockers) {
190
+ if (blocker.timeoutId) {
191
+ clearTimeout(blocker.timeoutId);
192
+ }
193
+ }
156
194
  set({ activeBlockers: /* @__PURE__ */ new Map() });
157
195
  },
158
196
  /**
@@ -162,6 +200,13 @@ var createUIBlockingActions = (set, get) => ({
162
200
  *
163
201
  */
164
202
  clearBlockersForScope: (scope) => {
203
+ const { activeBlockers } = get();
204
+ for (const [, blocker] of activeBlockers) {
205
+ const blockerScopes = normalizeScopeToArray(blocker.scope);
206
+ if (blockerScopes.includes(scope) && blocker.timeoutId) {
207
+ clearTimeout(blocker.timeoutId);
208
+ }
209
+ }
165
210
  set((state) => {
166
211
  const newBlockers = /* @__PURE__ */ new Map();
167
212
  for (const [id, blocker] of state.activeBlockers) {
@@ -174,6 +219,45 @@ var createUIBlockingActions = (set, get) => ({
174
219
  });
175
220
  }
176
221
  });
222
+ var UIBlockingContext = createContext(null);
223
+ function UIBlockingProvider({
224
+ children,
225
+ enableDevtools = process.env.NODE_ENV === "development",
226
+ devtoolsName = "UIBlocking",
227
+ middlewares = []
228
+ }) {
229
+ const middlewaresRef = useRef(middlewares);
230
+ const store = useMemo(() => {
231
+ const baseStore = enableDevtools ? createStore(
232
+ devtools(createUIBlockingActions, {
233
+ name: devtoolsName,
234
+ enabled: enableDevtools
235
+ })
236
+ ) : createStore(createUIBlockingActions);
237
+ middlewaresRef.current.forEach((mw, index) => {
238
+ baseStore.getState().registerMiddleware(`provider-middleware-${index.toString()}`, mw);
239
+ });
240
+ return baseStore;
241
+ }, [enableDevtools, devtoolsName]);
242
+ return /* @__PURE__ */ jsx(UIBlockingContext.Provider, { value: store, children });
243
+ }
244
+ function useUIBlockingContext() {
245
+ const store = useContext(UIBlockingContext);
246
+ if (!store) {
247
+ throw new Error(
248
+ "useUIBlockingContext must be used within UIBlockingProvider. Either wrap your app in <UIBlockingProvider> or use the global store via useUIBlockingStore."
249
+ );
250
+ }
251
+ return store;
252
+ }
253
+ function useIsInsideUIBlockingProvider() {
254
+ const store = useContext(UIBlockingContext);
255
+ return store !== null;
256
+ }
257
+ function useUIBlockingStoreFromContext(selector) {
258
+ const store = useUIBlockingContext();
259
+ return useStore(store, useShallow(selector));
260
+ }
177
261
 
178
262
  // src/store/uiBlockingStore.config.ts
179
263
  var devtoolsConfig = {
@@ -184,9 +268,19 @@ var devtoolsConfig = {
184
268
  // src/store/uiBlockingStore.store.ts
185
269
  var { useStore: useUIBlockingStore, useStoreApi: uiBlockingStoreApi } = createShallowStore(devtools(createUIBlockingActions, devtoolsConfig));
186
270
 
271
+ // src/context/useResolvedStore.ts
272
+ function useResolvedStore() {
273
+ const contextStore = useContext(UIBlockingContext);
274
+ return contextStore ?? uiBlockingStoreApi;
275
+ }
276
+ function useResolvedStoreWithSelector(selector) {
277
+ const store = useResolvedStore();
278
+ return useStore(store, useShallow(selector));
279
+ }
280
+
187
281
  // src/hooks/useAsyncAction/useAsyncAction.ts
188
- var useAsyncAction = (actionId, scope) => {
189
- const { addBlocker, removeBlocker } = useUIBlockingStore((state) => ({
282
+ var useAsyncAction = (actionId, scope, options) => {
283
+ const { addBlocker, removeBlocker } = useResolvedStoreWithSelector((state) => ({
190
284
  addBlocker: state.addBlocker,
191
285
  removeBlocker: state.removeBlocker
192
286
  }));
@@ -197,19 +291,21 @@ var useAsyncAction = (actionId, scope) => {
197
291
  addBlocker(blockerId, {
198
292
  scope,
199
293
  reason: `Executing ${actionId}`,
200
- priority: ASYNC_ACTION_PRIORITY
294
+ priority: ASYNC_ACTION_PRIORITY,
295
+ timeout: options?.timeout,
296
+ onTimeout: options?.onTimeout
201
297
  });
202
298
  return await asyncFn();
203
299
  } finally {
204
300
  removeBlocker(blockerId);
205
301
  }
206
302
  },
207
- [actionId, scope, addBlocker, removeBlocker]
303
+ [actionId, scope, options?.timeout, options?.onTimeout, addBlocker, removeBlocker]
208
304
  );
209
305
  return executeWithBlocking;
210
306
  };
211
307
  var useBlocker = (blockerId, config, isActive = true) => {
212
- const { addBlocker, removeBlocker } = useUIBlockingStore((state) => ({
308
+ const { addBlocker, removeBlocker } = useResolvedStoreWithSelector((state) => ({
213
309
  addBlocker: state.addBlocker,
214
310
  removeBlocker: state.removeBlocker
215
311
  }));
@@ -232,6 +328,13 @@ function createBlockerConfig(config) {
232
328
  priority: config.priority
233
329
  };
234
330
  }
331
+ var useBlockingInfo = (scope = DEFAULT_SCOPE) => {
332
+ const store = useResolvedStore();
333
+ const activeBlockers = useStore(store, (state) => state.activeBlockers);
334
+ return useMemo(() => {
335
+ return store.getState().getBlockingInfo(scope);
336
+ }, [activeBlockers, scope, store]);
337
+ };
235
338
  function useConfigRef(config) {
236
339
  const configRef = useRef(config);
237
340
  useEffect(() => {
@@ -242,7 +345,7 @@ function useConfigRef(config) {
242
345
 
243
346
  // src/hooks/useConditionalBlocker/useConditionalBlocker.ts
244
347
  var useConditionalBlocker = (blockerId, config) => {
245
- const { addBlocker, removeBlocker } = useUIBlockingStore((state) => ({
348
+ const { addBlocker, removeBlocker } = useResolvedStoreWithSelector((state) => ({
246
349
  addBlocker: state.addBlocker,
247
350
  removeBlocker: state.removeBlocker
248
351
  }));
@@ -325,7 +428,7 @@ var useConfirmableBlocker = (blockerId, config) => {
325
428
 
326
429
  // src/hooks/useIsBlocked/useIsBlocked.ts
327
430
  var useIsBlocked = (scope) => {
328
- return useUIBlockingStore((state) => state.isBlocked(scope));
431
+ return useResolvedStoreWithSelector((state) => state.isBlocked(scope));
329
432
  };
330
433
 
331
434
  // src/hooks/useScheduledBlocker/useScheduledBlocker.utils.ts
@@ -367,7 +470,7 @@ function isScheduleInPast(startTime, endTime, now) {
367
470
 
368
471
  // src/hooks/useScheduledBlocker/useScheduledBlocker.ts
369
472
  var useScheduledBlocker = (blockerId, config) => {
370
- const { addBlocker, removeBlocker } = useUIBlockingStore((state) => ({
473
+ const { addBlocker, removeBlocker } = useResolvedStoreWithSelector((state) => ({
371
474
  addBlocker: state.addBlocker,
372
475
  removeBlocker: state.removeBlocker
373
476
  }));
@@ -504,6 +607,15 @@ var createAnalyticsMiddleware = (config) => {
504
607
  };
505
608
  };
506
609
 
610
+ // src/middleware/configureMiddleware.ts
611
+ function configureMiddleware(middlewares) {
612
+ const store = uiBlockingStoreApi.getState();
613
+ middlewares.forEach((middleware, index) => {
614
+ const name = `middleware-${index.toString()}`;
615
+ store.registerMiddleware(name, middleware);
616
+ });
617
+ }
618
+
507
619
  // src/middleware/loggerMiddleware.utils.ts
508
620
  var getActionEmoji = (action) => {
509
621
  switch (action) {
@@ -589,6 +701,22 @@ var createPerformanceMiddleware = (config = {}) => {
589
701
  };
590
702
  };
591
703
 
592
- export { createAnalyticsMiddleware, createPerformanceMiddleware, loggerMiddleware, uiBlockingStoreApi, useAsyncAction, useBlocker, useConditionalBlocker, useConfirmableBlocker, useIsBlocked, useScheduledBlocker, useUIBlockingStore };
704
+ // src/createTypedHooks.ts
705
+ function createTypedHooks() {
706
+ return {
707
+ useBlocker: (blockerId, config, isActive) => {
708
+ useBlocker(blockerId, config, isActive);
709
+ },
710
+ useIsBlocked: (scope) => {
711
+ return useIsBlocked(scope);
712
+ },
713
+ useAsyncAction: (actionId, scope, options) => {
714
+ return useAsyncAction(actionId, scope, options);
715
+ },
716
+ useBlockingInfo: (scope) => useBlockingInfo(scope)
717
+ };
718
+ }
719
+
720
+ export { UIBlockingProvider, configureMiddleware, createAnalyticsMiddleware, createPerformanceMiddleware, createTypedHooks, loggerMiddleware, uiBlockingStoreApi, useAsyncAction, useBlocker, useBlockingInfo, useConditionalBlocker, useConfirmableBlocker, useIsBlocked, useIsInsideUIBlockingProvider, useScheduledBlocker, useUIBlockingContext, useUIBlockingStore, useUIBlockingStoreFromContext };
593
721
  //# sourceMappingURL=index.js.map
594
722
  //# sourceMappingURL=index.js.map