@okyrychenko-dev/react-action-guard 0.3.1 → 0.3.3

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/README.md CHANGED
@@ -26,8 +26,17 @@
26
26
 
27
27
  ```bash
28
28
  npm install @okyrychenko-dev/react-action-guard zustand
29
+ # or
30
+ yarn add @okyrychenko-dev/react-action-guard zustand
31
+ # or
32
+ pnpm add @okyrychenko-dev/react-action-guard zustand
29
33
  ```
30
34
 
35
+ This package requires the following peer dependencies:
36
+
37
+ - [React](https://react.dev/) ^17.0.0 || ^18.0.0
38
+ - [Zustand](https://zustand-demo.pmnd.rs/) - State management library
39
+
31
40
  ## Quick Start
32
41
 
33
42
  ```jsx
@@ -101,6 +110,43 @@ function SubmitButton() {
101
110
  }
102
111
  ```
103
112
 
113
+ #### `useBlockingInfo(scope)`
114
+
115
+ Gets detailed information about all active blockers for a specific scope.
116
+
117
+ **Parameters:**
118
+
119
+ - `scope?: string` - Scope to get blocking information for (default: "global")
120
+
121
+ **Returns:** `ReadonlyArray<BlockerInfo>` - Array of blocker information objects, sorted by priority (highest first)
122
+
123
+ **BlockerInfo:**
124
+
125
+ - `id: string` - Unique identifier of the blocker
126
+ - `reason?: string` - Reason for blocking
127
+ - `priority: number` - Priority level (0-100)
128
+ - `scope: string | string[]` - Scope(s) being blocked
129
+ - `timestamp: number` - When the blocker was added
130
+
131
+ **Example:**
132
+
133
+ ```jsx
134
+ function CheckoutButton() {
135
+ const blockers = useBlockingInfo("checkout");
136
+
137
+ if (blockers.length > 0) {
138
+ const topBlocker = blockers[0]; // Highest priority blocker
139
+ return (
140
+ <Tooltip content={`Blocked: ${topBlocker.reason}`}>
141
+ <Button disabled>Checkout ({blockers.length} blockers)</Button>
142
+ </Tooltip>
143
+ );
144
+ }
145
+
146
+ return <Button>Checkout</Button>;
147
+ }
148
+ ```
149
+
104
150
  #### `useAsyncAction(actionId, scope)`
105
151
 
106
152
  Wraps an async function with automatic blocking/unblocking.
@@ -323,20 +369,20 @@ The library includes a powerful middleware system that allows you to hook into b
323
369
  Track blocker events with your analytics provider (Google Analytics, Mixpanel, Amplitude, or custom).
324
370
 
325
371
  ```jsx
326
- import { configureMiddleware, analyticsMiddleware } from "@okyrychenko-dev/react-action-guard";
372
+ import { configureMiddleware, createAnalyticsMiddleware } from "@okyrychenko-dev/react-action-guard";
327
373
 
328
374
  // Google Analytics
329
- configureMiddleware([analyticsMiddleware({ provider: "ga" })]);
375
+ configureMiddleware([createAnalyticsMiddleware({ provider: "ga" })]);
330
376
 
331
377
  // Mixpanel
332
- configureMiddleware([analyticsMiddleware({ provider: "mixpanel" })]);
378
+ configureMiddleware([createAnalyticsMiddleware({ provider: "mixpanel" })]);
333
379
 
334
380
  // Amplitude
335
- configureMiddleware([analyticsMiddleware({ provider: "amplitude" })]);
381
+ configureMiddleware([createAnalyticsMiddleware({ provider: "amplitude" })]);
336
382
 
337
383
  // Custom analytics
338
384
  configureMiddleware([
339
- analyticsMiddleware({
385
+ createAnalyticsMiddleware({
340
386
  track: (event, data) => {
341
387
  myAnalytics.track(event, data);
342
388
  },
@@ -359,10 +405,10 @@ configureMiddleware([loggerMiddleware]);
359
405
  Monitor blocker performance and detect slow operations.
360
406
 
361
407
  ```jsx
362
- import { configureMiddleware, performanceMiddleware } from "@okyrychenko-dev/react-action-guard";
408
+ import { configureMiddleware, createPerformanceMiddleware } from "@okyrychenko-dev/react-action-guard";
363
409
 
364
410
  configureMiddleware([
365
- performanceMiddleware({
411
+ createPerformanceMiddleware({
366
412
  onSlowBlock: (blockerId, duration) => {
367
413
  console.warn(`Blocker ${blockerId} was active for ${duration}ms`);
368
414
  },
@@ -400,15 +446,15 @@ You can combine multiple middleware for comprehensive monitoring:
400
446
  ```jsx
401
447
  import {
402
448
  configureMiddleware,
403
- analyticsMiddleware,
449
+ createAnalyticsMiddleware,
404
450
  loggerMiddleware,
405
- performanceMiddleware,
451
+ createPerformanceMiddleware,
406
452
  } from "@okyrychenko-dev/react-action-guard";
407
453
 
408
454
  configureMiddleware([
409
455
  loggerMiddleware,
410
- analyticsMiddleware({ provider: "ga" }),
411
- performanceMiddleware({
456
+ createAnalyticsMiddleware({ provider: "ga" }),
457
+ createPerformanceMiddleware({
412
458
  slowBlockThreshold: 3000,
413
459
  onSlowBlock: (blockerId, duration) => {
414
460
  // Send to error tracking service
@@ -429,7 +475,7 @@ The library is fully tree-shakeable. Import only the features you need to keep y
429
475
  import { useBlocker } from "@okyrychenko-dev/react-action-guard";
430
476
 
431
477
  // Middleware is not included unless you import it
432
- import { configureMiddleware, analyticsMiddleware } from "@okyrychenko-dev/react-action-guard";
478
+ import { configureMiddleware, createAnalyticsMiddleware } from "@okyrychenko-dev/react-action-guard";
433
479
  ```
434
480
 
435
481
  The package is configured with `"sideEffects": false`, allowing modern bundlers (Webpack, Rollup, Vite) to eliminate unused code automatically.
package/dist/index.cjs CHANGED
@@ -234,6 +234,12 @@ function createBlockerConfig(config) {
234
234
  priority: config.priority
235
235
  };
236
236
  }
237
+ var useBlockingInfo = (scope = DEFAULT_SCOPE) => {
238
+ const activeBlockers = zustand.useStore(uiBlockingStoreApi, (state) => state.activeBlockers);
239
+ return react.useMemo(() => {
240
+ return uiBlockingStoreApi.getState().getBlockingInfo(scope);
241
+ }, [activeBlockers, scope]);
242
+ };
237
243
  function useConfigRef(config) {
238
244
  const configRef = react.useRef(config);
239
245
  react.useEffect(() => {
@@ -506,6 +512,15 @@ var createAnalyticsMiddleware = (config) => {
506
512
  };
507
513
  };
508
514
 
515
+ // src/middleware/configureMiddleware.ts
516
+ function configureMiddleware(middlewares) {
517
+ const store = uiBlockingStoreApi.getState();
518
+ middlewares.forEach((middleware, index) => {
519
+ const name = `middleware-${index.toString()}`;
520
+ store.registerMiddleware(name, middleware);
521
+ });
522
+ }
523
+
509
524
  // src/middleware/loggerMiddleware.utils.ts
510
525
  var getActionEmoji = (action) => {
511
526
  switch (action) {
@@ -591,12 +606,14 @@ var createPerformanceMiddleware = (config = {}) => {
591
606
  };
592
607
  };
593
608
 
609
+ exports.configureMiddleware = configureMiddleware;
594
610
  exports.createAnalyticsMiddleware = createAnalyticsMiddleware;
595
611
  exports.createPerformanceMiddleware = createPerformanceMiddleware;
596
612
  exports.loggerMiddleware = loggerMiddleware;
597
613
  exports.uiBlockingStoreApi = uiBlockingStoreApi;
598
614
  exports.useAsyncAction = useAsyncAction;
599
615
  exports.useBlocker = useBlocker;
616
+ exports.useBlockingInfo = useBlockingInfo;
600
617
  exports.useConditionalBlocker = useConditionalBlocker;
601
618
  exports.useConfirmableBlocker = useConfirmableBlocker;
602
619
  exports.useIsBlocked = useIsBlocked;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/store/uiBlockingStore.constants.ts","../src/store/uiBlockingStore.utils.ts","../src/store/uiBlockingStore.actions.ts","../src/store/uiBlockingStore.config.ts","../src/store/uiBlockingStore.store.ts","../src/hooks/useAsyncAction/useAsyncAction.ts","../src/hooks/useBlocker/useBlocker.ts","../src/hooks/useBlocker/useBlocker.utils.ts","../src/hooks/useConfigRef.ts","../src/hooks/useConditionalBlocker/useConditionalBlocker.ts","../src/hooks/useConfirmableBlocker/useConfirmableBlocker.ts","../src/hooks/useIsBlocked/useIsBlocked.ts","../src/hooks/useScheduledBlocker/useScheduledBlocker.utils.ts","../src/hooks/useScheduledBlocker/useScheduledBlocker.ts","../src/middleware/analyticsMiddleware.utils.ts","../src/middleware/analyticsMiddleware.ts","../src/middleware/loggerMiddleware.utils.ts","../src/middleware/loggerMiddleware.ts","../src/middleware/performanceMiddleware.utils.ts","../src/middleware/performanceMiddleware.ts"],"names":["createStore","useStore","useShallow","devtools","useCallback","useEffect","useRef","useState"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Default values and constants for UI Blocking Store\n */\n\n/**\n * Default scope for blockers\n */\nexport const DEFAULT_SCOPE = \"global\" as const;\n\n/**\n * Default reason when none is provided\n */\nexport const DEFAULT_REASON = \"Unknown\" as const;\n\n/**\n * Default priority for blockers\n */\nexport const DEFAULT_PRIORITY = 0 as const;\n\n/**\n * Default priority for async actions\n */\nexport const ASYNC_ACTION_PRIORITY = 20 as const;\n\n/**\n * DevTools store name\n */\nexport const DEVTOOLS_NAME = \"UIBlocking\" as const;\n","import { StateCreator, StoreApi, StoreMutators, createStore, useStore } from \"zustand\";\nimport { useShallow } from \"zustand/shallow\";\n\n/**\n * Creates a Zustand store with automatic shallow comparison for all selectors\n *\n * This utility wraps the standard Zustand store creation and automatically applies\n * `useShallow` to all selectors, preventing unnecessary re-renders when selected\n * values haven't changed (shallow equality).\n *\n * @template StoreState - The type of the store state\n * @template TMutators - Array of middleware mutators (e.g., devtools, persist)\n *\n * @param storeCreator - The state creator function for Zustand\n * @returns Object containing the store hook and store API\n *\n * @see https://docs.pmnd.rs/zustand/guides/prevent-rerenders-with-use-shallow\n */\nexport function createShallowStore<\n StoreState,\n TMutators extends Array<[keyof StoreMutators<StoreState, StoreState>, unknown]> = [],\n>(\n storeCreator: StateCreator<StoreState, [], TMutators, StoreState>\n): {\n useStore: <T>(selector: (state: StoreState) => T) => T;\n useStoreApi: StoreApi<StoreState>;\n} {\n const storeApi: StoreApi<StoreState> = createStore<StoreState, TMutators>(storeCreator);\n\n const useScopedStore = <T>(selector: (state: StoreState) => T): T => {\n return useStore(storeApi, useShallow(selector));\n };\n\n return { useStore: useScopedStore, useStoreApi: storeApi };\n}\n\n/**\n * Normalize scope to array format\n *\n * @param scope - Single scope or array of scopes\n * @returns Array of scopes\n *\n * @internal\n */\nexport function normalizeScopeToArray(scope: string | ReadonlyArray<string>): Array<string> {\n if (typeof scope === \"string\") {\n return [scope];\n }\n return Array.from(scope);\n}\n","import { Middleware, MiddlewareContext } from \"../middleware\";\nimport { DEFAULT_PRIORITY, DEFAULT_REASON, DEFAULT_SCOPE } from \"./uiBlockingStore.constants\";\nimport { normalizeScopeToArray } from \"./uiBlockingStore.utils\";\nimport type {\n BlockerConfig,\n BlockerInfo,\n StoredBlocker,\n UIBlockingStore,\n} from \"./uiBlockingStore.types\";\nimport type { StateCreator } from \"zustand\";\n\n/**\n * UI Blocking Store Slice\n *\n * Implements the state and actions for UI blocking management.\n * This slice follows the Zustand slice pattern for better code organization.\n */\nexport const createUIBlockingActions: StateCreator<UIBlockingStore, [], [], UIBlockingStore> = (\n set,\n get\n) => ({\n // State\n activeBlockers: new Map(),\n middlewares: new Map(),\n\n registerMiddleware: (name: string, middleware: Middleware) => {\n set((state) => {\n const newMiddlewares = new Map(state.middlewares);\n newMiddlewares.set(name, middleware);\n return { middlewares: newMiddlewares };\n });\n console.log(`[UIBlocking] Registered middleware: ${name}`);\n },\n\n unregisterMiddleware: (name: string) => {\n set((state) => {\n const newMiddlewares = new Map(state.middlewares);\n newMiddlewares.delete(name);\n return { middlewares: newMiddlewares };\n });\n console.log(`[UIBlocking] Unregistered middleware: ${name}`);\n },\n\n runMiddlewares: async (context: MiddlewareContext) => {\n const { middlewares } = get();\n\n for (const [name, middleware] of middlewares) {\n try {\n await middleware(context);\n } catch (error) {\n console.error(`[UIBlocking] Middleware \"${name}\" error:`, error);\n }\n }\n },\n\n // Actions\n /**\n * Add a blocker to the store\n *\n * @param id - Unique blocker identifier\n * @param config - Optional blocker configuration\n *\n */\n addBlocker: (id: string, config: BlockerConfig = {}): void => {\n set((state) => {\n const newBlockers = new Map(state.activeBlockers);\n const storedBlocker: StoredBlocker = {\n scope: config.scope ?? DEFAULT_SCOPE,\n reason: config.reason ?? DEFAULT_REASON,\n priority: config.priority ?? DEFAULT_PRIORITY,\n timestamp: config.timestamp ?? Date.now(),\n };\n newBlockers.set(id, storedBlocker);\n\n return { activeBlockers: newBlockers };\n });\n\n void get().runMiddlewares({\n action: \"add\",\n blockerId: id,\n config: {\n scope: config.scope,\n reason: config.reason,\n priority: config.priority,\n },\n timestamp: Date.now(),\n });\n },\n\n /**\n * Remove a blocker from the store\n *\n * @param id - Blocker identifier to remove\n *\n */\n removeBlocker: (id: string): void => {\n const prevBlocker = get().activeBlockers.get(id);\n\n set((state) => {\n const newBlockers = new Map(state.activeBlockers);\n newBlockers.delete(id);\n\n return { activeBlockers: newBlockers };\n });\n\n if (prevBlocker) {\n void get().runMiddlewares({\n action: \"remove\",\n blockerId: id,\n config: prevBlocker,\n timestamp: Date.now(),\n prevState: prevBlocker,\n });\n }\n },\n\n /**\n * Check if a scope is currently blocked\n *\n * @param scope - Scope or array of scopes to check (default: \"global\")\n * @returns True if any of the scopes are blocked\n *\n */\n isBlocked: (scope: string | ReadonlyArray<string> = DEFAULT_SCOPE): boolean => {\n const { activeBlockers } = get();\n const scopes = normalizeScopeToArray(scope);\n\n for (const [, blocker] of activeBlockers) {\n // Global blocking blocks everything\n if (blocker.scope === DEFAULT_SCOPE) {\n return true;\n }\n\n // Check scope intersection\n const blockerScopes = normalizeScopeToArray(blocker.scope);\n\n if (scopes.some((s) => blockerScopes.includes(s))) {\n return true;\n }\n }\n\n return false;\n },\n\n /**\n * Get detailed blocking information for a specific scope\n *\n * @param scope - Scope to get blocking information for\n * @returns Array of blockers affecting the scope, sorted by priority (highest first)\n *\n */\n getBlockingInfo: (scope: string): ReadonlyArray<BlockerInfo> => {\n const { activeBlockers } = get();\n const blockers: Array<BlockerInfo> = [];\n\n for (const [id, blocker] of activeBlockers) {\n const blockerScopes = normalizeScopeToArray(blocker.scope);\n\n if (blocker.scope === DEFAULT_SCOPE || blockerScopes.includes(scope)) {\n blockers.push({ id, ...blocker });\n }\n }\n\n return blockers.sort((a, b) => b.priority - a.priority);\n },\n\n /**\n * Clear all blockers from the store\n */\n clearAllBlockers: (): void => {\n set({ activeBlockers: new Map() });\n },\n\n /**\n * Clear all blockers for a specific scope\n *\n * @param scope - Scope to clear blockers for\n *\n */\n clearBlockersForScope: (scope: string): void => {\n set((state) => {\n const newBlockers = new Map();\n\n for (const [id, blocker] of state.activeBlockers) {\n const blockerScopes = normalizeScopeToArray(blocker.scope);\n\n if (!blockerScopes.includes(scope)) {\n newBlockers.set(id, blocker);\n }\n }\n\n return { activeBlockers: newBlockers };\n });\n },\n});\n","import { DEVTOOLS_NAME } from \"./uiBlockingStore.constants\";\nimport type { DevtoolsOptions } from \"zustand/middleware\";\n\n/**\n * DevTools configuration for UI Blocking Store\n *\n * Enables Redux DevTools integration only in development mode\n * for better debugging experience without production overhead.\n */\nexport const devtoolsConfig: DevtoolsOptions = {\n name: DEVTOOLS_NAME,\n enabled: process.env.NODE_ENV !== \"production\",\n};\n","import { devtools } from \"zustand/middleware\";\nimport { createUIBlockingActions } from \"./uiBlockingStore.actions\";\nimport { devtoolsConfig } from \"./uiBlockingStore.config\";\nimport { createShallowStore } from \"./uiBlockingStore.utils\";\nimport type { UIBlockingStore } from \"./uiBlockingStore.types\";\n\n/**\n * UI Blocking Store\n *\n * Global Zustand store for managing UI blocking state across the application.\n *\n * Features:\n * - Priority-based blocking system\n * - Scope-based blocking (global, specific areas, or multiple scopes)\n * - Automatic cleanup on unmount (when using hooks)\n * - DevTools integration for debugging\n * - Automatic shallow comparison for selectors\n *\n */\nconst { useStore: useUIBlockingStore, useStoreApi: uiBlockingStoreApi } = createShallowStore<\n UIBlockingStore,\n [[\"zustand/devtools\", never]]\n>(devtools(createUIBlockingActions, devtoolsConfig));\n\nexport { useUIBlockingStore, uiBlockingStoreApi };\n","import { useCallback } from \"react\";\nimport { ASYNC_ACTION_PRIORITY, useUIBlockingStore } from \"../../store\";\n\n/**\n * Hook to wrap async functions with automatic blocking/unblocking\n *\n * Creates a wrapper function that automatically adds a blocker before executing\n * the async function and removes it after completion (success or failure).\n *\n * @template T - The return type of the async function\n * @param actionId - Unique identifier for the action (used in blocker ID and reason)\n * @param scope - Scope(s) to block during execution (default: \"global\")\n * @returns Function that wraps async functions with blocking behavior\n *\n */\nexport const useAsyncAction = <T = unknown>(\n actionId: string,\n scope?: string | ReadonlyArray<string>\n): ((asyncFn: () => Promise<T>) => Promise<T>) => {\n const { addBlocker, removeBlocker } = useUIBlockingStore((state) => ({\n addBlocker: state.addBlocker,\n removeBlocker: state.removeBlocker,\n }));\n\n const executeWithBlocking = useCallback(\n async (asyncFn: () => Promise<T>): Promise<T> => {\n const blockerId = `${actionId}-${Date.now().toString()}`;\n\n try {\n addBlocker(blockerId, {\n scope,\n reason: `Executing ${actionId}`,\n priority: ASYNC_ACTION_PRIORITY,\n });\n\n return await asyncFn();\n } finally {\n removeBlocker(blockerId);\n }\n },\n [actionId, scope, addBlocker, removeBlocker]\n );\n\n return executeWithBlocking;\n};\n","import { useEffect } from \"react\";\nimport { type BlockerConfig, useUIBlockingStore } from \"../../store\";\n\n/**\n * Hook to automatically add and remove a blocker based on component lifecycle\n *\n * Automatically adds a blocker when the component mounts (or when activated)\n * and removes it when the component unmounts (or when deactivated).\n *\n * @param blockerId - Unique identifier for the blocker\n * @param config - Blocker configuration (scope, reason, priority)\n * @param isActive - Whether the blocker is currently active (default: true)\n *\n */\nexport const useBlocker = (blockerId: string, config: BlockerConfig, isActive = true): void => {\n const { addBlocker, removeBlocker } = useUIBlockingStore((state) => ({\n addBlocker: state.addBlocker,\n removeBlocker: state.removeBlocker,\n }));\n\n useEffect(() => {\n if (!isActive || !blockerId) {\n return;\n }\n\n addBlocker(blockerId, config);\n\n return () => {\n removeBlocker(blockerId);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [blockerId, isActive, addBlocker, removeBlocker]);\n};\n","import { BlockerConfig } from \"../../store\";\n\n/**\n * Creates a blocker configuration object from partial config.\n * Filters out undefined values to create a clean BlockerConfig.\n *\n * @param config - Partial blocker configuration\n * @returns Complete BlockerConfig object\n *\n */\nexport function createBlockerConfig(config: {\n scope?: string | ReadonlyArray<string>;\n reason?: string;\n priority?: number;\n}): BlockerConfig {\n return {\n scope: config.scope,\n reason: config.reason,\n priority: config.priority,\n };\n}\n","import { RefObject, useEffect, useRef } from \"react\";\n\n/**\n * Keeps a ref updated with the latest config value.\n * Useful for accessing current config in callbacks without stale closures.\n *\n * @param config - Configuration object to track\n * @returns Mutable ref that always contains the latest config\n *\n */\nexport function useConfigRef<T>(config: T): RefObject<T> {\n const configRef = useRef(config);\n\n useEffect(() => {\n configRef.current = config;\n }, [config]);\n\n return configRef;\n}\n","import { useCallback, useEffect, useRef } from \"react\";\nimport { useUIBlockingStore } from \"../../store\";\nimport { createBlockerConfig } from \"../useBlocker\";\nimport { useConfigRef } from \"../useConfigRef\";\nimport { ConditionalBlockerConfig } from \"./useConditionalBlocker.types\";\n\n/**\n * Hook for conditional blocking based on a condition function.\n *\n * Periodically checks a condition and blocks/unblocks based on the result.\n * The condition is evaluated at the specified interval (default 1000ms).\n *\n * @param blockerId - Unique identifier for this blocker\n * @param config - Configuration including condition function and check interval\n *\n */\nexport const useConditionalBlocker = <TState = unknown>(\n blockerId: string,\n config: ConditionalBlockerConfig<TState>\n): void => {\n const { addBlocker, removeBlocker } = useUIBlockingStore((state) => ({\n addBlocker: state.addBlocker,\n removeBlocker: state.removeBlocker,\n }));\n const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);\n const isBlockedRef = useRef(false);\n const configRef = useConfigRef(config);\n\n const checkCondition = useCallback(() => {\n const currentConfig = configRef.current;\n const shouldBlock = currentConfig.condition(currentConfig.state);\n\n // No state change needed\n if (shouldBlock === isBlockedRef.current) {\n return;\n }\n\n if (shouldBlock) {\n addBlocker(blockerId, createBlockerConfig(currentConfig));\n } else {\n removeBlocker(blockerId);\n }\n isBlockedRef.current = shouldBlock;\n }, [blockerId, addBlocker, removeBlocker, configRef]);\n\n useEffect(() => {\n checkCondition();\n\n const interval = configRef.current.checkInterval ?? 1000;\n intervalRef.current = setInterval(checkCondition, interval);\n\n return (): void => {\n if (intervalRef.current) {\n clearInterval(intervalRef.current);\n intervalRef.current = null;\n }\n if (isBlockedRef.current) {\n removeBlocker(blockerId);\n isBlockedRef.current = false;\n }\n };\n // configRef is stable and doesn't need to be in dependencies\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [checkCondition, blockerId, removeBlocker]);\n};\n","import { useCallback, useState } from \"react\";\nimport { useBlocker } from \"../useBlocker\";\nimport {\n ConfirmableBlockerConfig,\n UseConfirmableBlockerReturn,\n} from \"./useConfirmableBlocker.types\";\n\n/**\n * Hook for creating a confirmable action with blocking UI\n *\n */\nexport const useConfirmableBlocker = (\n blockerId: string,\n config: ConfirmableBlockerConfig\n): UseConfirmableBlockerReturn => {\n const [isDialogOpen, setIsDialogOpen] = useState(false);\n const [isExecuting, setIsExecuting] = useState(false);\n\n useBlocker(\n blockerId,\n {\n ...config,\n reason: config.reason ?? config.confirmMessage,\n },\n isDialogOpen || isExecuting\n );\n\n const execute = useCallback(() => {\n setIsDialogOpen(true);\n }, []);\n\n const onConfirm = useCallback(async () => {\n setIsDialogOpen(false);\n setIsExecuting(true);\n\n try {\n await config.onConfirm();\n } catch (error) {\n console.error(\"[UIBlocking] Confirmable action error:\", error);\n throw error;\n } finally {\n setIsExecuting(false);\n }\n }, [config]);\n\n const onCancel = useCallback(() => {\n setIsDialogOpen(false);\n config.onCancel?.();\n }, [config]);\n\n return {\n execute,\n isDialogOpen,\n isExecuting,\n confirmConfig: {\n title: config.confirmTitle ?? \"Confirm Action\",\n message: config.confirmMessage,\n confirmText: config.confirmButtonText ?? \"Confirm\",\n cancelText: config.cancelButtonText ?? \"Cancel\",\n },\n onConfirm,\n onCancel,\n };\n};\n","import { useUIBlockingStore } from \"../../store\";\n\n/**\n * Hook to check if a scope is currently blocked\n *\n * Returns a boolean indicating whether the specified scope(s) are blocked.\n * Automatically re-renders when the blocking state changes.\n *\n * @param scope - Scope or array of scopes to check (default: \"global\")\n * @returns True if any of the specified scopes are blocked\n *\n */\nexport const useIsBlocked = (scope?: string | ReadonlyArray<string>): boolean => {\n return useUIBlockingStore((state) => state.isBlocked(scope));\n};\n","import type { BlockingSchedule } from \"./useScheduledBlocker.types\";\n\n/**\n * Maximum safe timeout value for setTimeout in JavaScript (~24.8 days).\n * Values larger than this will cause setTimeout to trigger immediately.\n */\nexport const MAX_TIMEOUT_MS = 2147483647;\n\n/**\n * Validates a date value and converts it to timestamp.\n *\n * @param date - Date value as string, Date object, or number\n * @returns Timestamp in milliseconds, or NaN if invalid\n */\nexport function parseDate(date: string | Date | number): number {\n return new Date(date).getTime();\n}\n\n/**\n * Validates if a timestamp is valid (not NaN).\n *\n * @param timestamp - Timestamp to validate\n * @returns True if valid, false otherwise\n */\nexport function isValidTimestamp(timestamp: number): boolean {\n return !Number.isNaN(timestamp);\n}\n\n/**\n * Calculates the end time based on schedule configuration.\n * Duration takes precedence over end time if both are provided.\n *\n * @param schedule - Blocking schedule configuration\n * @param startTime - Start time in milliseconds\n * @returns End time in milliseconds, or undefined if not specified\n */\nexport function calculateEndTime(\n schedule: BlockingSchedule,\n startTime: number\n): number | undefined {\n if (schedule.duration) {\n return startTime + schedule.duration;\n }\n\n if (schedule.end) {\n const endTime = parseDate(schedule.end);\n return isValidTimestamp(endTime) ? endTime : undefined;\n }\n\n return undefined;\n}\n\n/**\n * Validates if a delay is within the safe setTimeout range.\n *\n * @param delay - Delay in milliseconds\n * @returns True if delay is safe to use with setTimeout\n */\nexport function isSafeTimeout(delay: number): boolean {\n return delay > 0 && delay <= MAX_TIMEOUT_MS;\n}\n\n/**\n * Determines if the current time is within a blocking schedule.\n *\n * @param startTime - Schedule start time in milliseconds\n * @param endTime - Schedule end time in milliseconds (optional)\n * @param now - Current time in milliseconds\n * @returns True if currently in the blocking period\n */\nexport function isInBlockingPeriod(\n startTime: number,\n endTime: number | undefined,\n now: number\n): boolean {\n if (startTime > now) {\n return false; // Not started yet\n }\n\n if (!endTime) {\n return true; // No end time means block indefinitely\n }\n\n return endTime > now; // Check if end time hasn't passed\n}\n\n/**\n * Checks if a schedule is completely in the past.\n *\n * @param startTime - Schedule start time in milliseconds\n * @param endTime - Schedule end time in milliseconds (optional)\n * @param now - Current time in milliseconds\n * @returns True if the schedule is in the past\n */\nexport function isScheduleInPast(\n startTime: number,\n endTime: number | undefined,\n now: number\n): boolean {\n if (!endTime) {\n return false; // No end time means it can still be active\n }\n\n return endTime <= now && startTime <= now;\n}\n","import { useCallback, useEffect, useRef } from \"react\";\nimport { useUIBlockingStore } from \"../../store\";\nimport { createBlockerConfig } from \"../useBlocker\";\nimport { useConfigRef } from \"../useConfigRef\";\nimport { ScheduledBlockerConfig } from \"./useScheduledBlocker.types\";\nimport {\n MAX_TIMEOUT_MS,\n calculateEndTime,\n isInBlockingPeriod,\n isSafeTimeout,\n isScheduleInPast,\n isValidTimestamp,\n parseDate,\n} from \"./useScheduledBlocker.utils\";\n\n/**\n * Hook for scheduling UI blocking for a specific time period.\n *\n * Blocks UI during a scheduled maintenance window or time period.\n * Supports start/end times as Date objects, ISO strings, or timestamps.\n * If both duration and end are provided, duration takes precedence.\n *\n * @param blockerId - Unique identifier for this blocker\n * @param config - Configuration including schedule and callbacks\n *\n */\nexport const useScheduledBlocker = (blockerId: string, config: ScheduledBlockerConfig): void => {\n const { addBlocker, removeBlocker } = useUIBlockingStore((state) => ({\n addBlocker: state.addBlocker,\n removeBlocker: state.removeBlocker,\n }));\n const timeoutsRef = useRef<{\n start?: ReturnType<typeof setTimeout>;\n end?: ReturnType<typeof setTimeout>;\n }>({});\n const configRef = useConfigRef(config);\n\n const cleanup = useCallback(() => {\n if (timeoutsRef.current.start) {\n clearTimeout(timeoutsRef.current.start);\n timeoutsRef.current.start = undefined;\n }\n if (timeoutsRef.current.end) {\n clearTimeout(timeoutsRef.current.end);\n timeoutsRef.current.end = undefined;\n }\n }, []);\n\n useEffect(() => {\n const currentConfig = configRef.current;\n const startTime = parseDate(currentConfig.schedule.start);\n const now = Date.now();\n\n // Validate start time\n if (!isValidTimestamp(startTime)) {\n console.error(`[UIBlocking] Invalid start time for blocker \"${blockerId}\"`);\n return;\n }\n\n const scheduleEnd = (): void => {\n const endTime = calculateEndTime(currentConfig.schedule, startTime);\n if (!endTime) {\n return;\n }\n\n const remainingTime = endTime - Date.now();\n if (remainingTime > 0) {\n timeoutsRef.current.end = setTimeout(() => {\n configRef.current.onScheduleEnd?.();\n removeBlocker(blockerId);\n }, remainingTime);\n }\n };\n\n const startBlocking = (): void => {\n const cfg = configRef.current;\n addBlocker(blockerId, createBlockerConfig(cfg));\n cfg.onScheduleStart?.();\n scheduleEnd();\n };\n\n // If start time hasn't arrived yet\n if (startTime > now) {\n const delay = startTime - now;\n\n if (!isSafeTimeout(delay)) {\n console.warn(\n `[UIBlocking] Schedule delay exceeds maximum timeout (${MAX_TIMEOUT_MS.toString()}ms) for blocker \"${blockerId}\"`\n );\n return;\n }\n\n timeoutsRef.current.start = setTimeout(startBlocking, delay);\n }\n // If already in blocking period or should start immediately\n else {\n const endTime = calculateEndTime(currentConfig.schedule, startTime);\n\n if (isInBlockingPeriod(startTime, endTime, now)) {\n startBlocking();\n } else if (isScheduleInPast(startTime, endTime, now)) {\n console.warn(`[UIBlocking] Schedule is in the past for blocker \"${blockerId}\"`);\n }\n }\n\n return (): void => {\n cleanup();\n removeBlocker(blockerId);\n };\n // configRef is stable and doesn't need to be in dependencies\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [blockerId, addBlocker, removeBlocker, cleanup]);\n};\n","import { AnalyticsEventData } from \"./analyticsMiddleware.types\";\nimport { MiddlewareContext } from \"./middleware.types\";\n\nconst capitalizeFirst = (str: string): string => {\n return str.charAt(0).toUpperCase() + str.slice(1);\n};\n\nexport const buildEventData = (context: MiddlewareContext): AnalyticsEventData => {\n const eventData: AnalyticsEventData = {\n blocker_id: context.blockerId,\n };\n const { scope, reason, priority } = context.config ?? {};\n\n if (scope !== undefined) {\n eventData.scope = Array.isArray(scope) ? scope.join(\",\") : scope;\n }\n\n if (reason !== undefined) {\n eventData.reason = reason;\n }\n\n if (priority !== undefined) {\n eventData.priority = priority;\n }\n\n return eventData;\n};\n\nexport const trackGoogleAnalytics = (action: string, eventData: AnalyticsEventData): void => {\n if (window.gtag) {\n window.gtag(\"event\", `ui_blocking_${action}`, eventData);\n }\n};\n\nexport const trackMixpanel = (action: string, eventData: AnalyticsEventData): void => {\n if (window.mixpanel) {\n const eventName = `UI Blocking ${action.split(\"_\").map(capitalizeFirst).join(\" \")}`;\n\n window.mixpanel.track(eventName, eventData);\n }\n};\n\nexport const trackAmplitude = (action: string, eventData: AnalyticsEventData): void => {\n if (window.amplitude) {\n const eventName = `UI Blocking ${action.split(\"_\").map(capitalizeFirst).join(\" \")}`;\n\n window.amplitude.track(eventName, eventData);\n }\n};\n\nexport const trackCustom = (\n trackFn: (event: string, data: AnalyticsEventData) => void,\n action: string,\n eventData: AnalyticsEventData\n): void => {\n try {\n trackFn(`ui_blocking_${action}`, eventData);\n } catch {\n // Silently ignore errors in custom tracker\n }\n};\n","import { AnalyticsConfig, AnalyticsEventData } from \"./analyticsMiddleware.types\";\nimport {\n buildEventData,\n trackAmplitude,\n trackCustom,\n trackGoogleAnalytics,\n trackMixpanel,\n} from \"./analyticsMiddleware.utils\";\nimport { Middleware, MiddlewareContext } from \"./middleware.types\";\n\nconst trackEvent = (\n config: AnalyticsConfig,\n context: MiddlewareContext,\n eventData: AnalyticsEventData\n): void => {\n if (\"provider\" in config) {\n switch (config.provider) {\n case \"ga\":\n trackGoogleAnalytics(context.action, eventData);\n return;\n case \"mixpanel\":\n trackMixpanel(context.action, eventData);\n return;\n case \"amplitude\":\n trackAmplitude(context.action, eventData);\n return;\n }\n }\n\n if (\"track\" in config) {\n trackCustom(config.track, context.action, eventData);\n }\n};\n\nexport const createAnalyticsMiddleware = (config: AnalyticsConfig): Middleware => {\n return (context) => {\n const eventData = buildEventData(context);\n\n trackEvent(config, context, eventData);\n };\n};\n","import { MiddlewareBlockerConfig, MiddlewareContext } from \"./middleware.types\";\n\nexport const getActionEmoji = (action: string): string => {\n switch (action) {\n case \"add\":\n return \"➕\";\n case \"remove\":\n return \"➖\";\n case \"update\":\n return \"🔄\";\n case \"cancel\":\n return \"❌\";\n case \"timeout\":\n return \"⏱️\";\n default:\n return \"❓\";\n }\n};\n\nconst extractConfigDetails = (config?: MiddlewareBlockerConfig): Record<string, unknown> => {\n if (!config) {\n return {};\n }\n\n const { scope, reason, priority } = config;\n\n const details: Record<string, unknown> = {\n scope,\n reason,\n };\n\n if (priority !== undefined) {\n details.priority = priority;\n }\n\n return details;\n};\n\nexport const formatLogData = (context: MiddlewareContext): Record<string, unknown> => {\n const configDetails = extractConfigDetails(context.config);\n\n if (context.prevState) {\n return {\n config: configDetails,\n prevState: extractConfigDetails(context.prevState),\n };\n }\n\n return configDetails;\n};\n","import { formatLogData, getActionEmoji } from \"./loggerMiddleware.utils\";\nimport { Middleware } from \"./middleware.types\";\n\nconst LOG_PREFIX = \"[UIBlocking]\";\n\nexport const loggerMiddleware: Middleware = (context) => {\n const emoji = getActionEmoji(context.action);\n const logData = formatLogData(context);\n\n console.log(LOG_PREFIX, emoji, context.blockerId, logData);\n};\n","export const handleAddAction = (\n blockerId: string,\n timestamp: number,\n blockStartTimes: Map<string, number>\n): void => {\n blockStartTimes.set(blockerId, timestamp);\n};\n","import { Middleware, MiddlewareContext } from \"./middleware.types\";\nimport { PerformanceConfig } from \"./performanceMiddleware.types\";\nimport { handleAddAction } from \"./performanceMiddleware.utils\";\n\nconst DEFAULT_SLOW_BLOCK_THRESHOLD = 3000;\nconst ACTION_ADD = \"add\";\nconst ACTION_REMOVE = \"remove\";\n\nconst handleRemoveAction = (\n context: MiddlewareContext,\n blockStartTimes: Map<string, number>,\n slowBlockThreshold: number,\n onSlowBlock?: (blockerId: string, duration: number) => void\n): void => {\n const startTime = blockStartTimes.get(context.blockerId);\n\n if (startTime === undefined) {\n return;\n }\n\n const duration = context.timestamp - startTime;\n blockStartTimes.delete(context.blockerId);\n\n if (duration >= slowBlockThreshold) {\n console.warn(\n `[UIBlocking] Slow block detected: \"${context.blockerId}\" took ${duration.toString()}ms`\n );\n\n onSlowBlock?.(context.blockerId, duration);\n }\n};\n\nexport const createPerformanceMiddleware = (config: PerformanceConfig = {}): Middleware => {\n const { slowBlockThreshold = DEFAULT_SLOW_BLOCK_THRESHOLD, onSlowBlock } = config;\n const blockStartTimes = new Map<string, number>();\n\n return (context) => {\n if (context.action === ACTION_ADD) {\n handleAddAction(context.blockerId, context.timestamp, blockStartTimes);\n } else if (context.action === ACTION_REMOVE) {\n handleRemoveAction(context, blockStartTimes, slowBlockThreshold, onSlowBlock);\n }\n };\n};\n"]}
1
+ {"version":3,"sources":["../src/store/uiBlockingStore.constants.ts","../src/store/uiBlockingStore.utils.ts","../src/store/uiBlockingStore.actions.ts","../src/store/uiBlockingStore.config.ts","../src/store/uiBlockingStore.store.ts","../src/hooks/useAsyncAction/useAsyncAction.ts","../src/hooks/useBlocker/useBlocker.ts","../src/hooks/useBlocker/useBlocker.utils.ts","../src/hooks/useBlockingInfo/useBlockingInfo.ts","../src/hooks/useConfigRef.ts","../src/hooks/useConditionalBlocker/useConditionalBlocker.ts","../src/hooks/useConfirmableBlocker/useConfirmableBlocker.ts","../src/hooks/useIsBlocked/useIsBlocked.ts","../src/hooks/useScheduledBlocker/useScheduledBlocker.utils.ts","../src/hooks/useScheduledBlocker/useScheduledBlocker.ts","../src/middleware/analyticsMiddleware.utils.ts","../src/middleware/analyticsMiddleware.ts","../src/middleware/configureMiddleware.ts","../src/middleware/loggerMiddleware.utils.ts","../src/middleware/loggerMiddleware.ts","../src/middleware/performanceMiddleware.utils.ts","../src/middleware/performanceMiddleware.ts"],"names":["createStore","useStore","useShallow","devtools","useCallback","useEffect","useMemo","useRef","useState"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Default values and constants for UI Blocking Store\n */\n\n/**\n * Default scope for blockers\n */\nexport const DEFAULT_SCOPE = \"global\" as const;\n\n/**\n * Default reason when none is provided\n */\nexport const DEFAULT_REASON = \"Unknown\" as const;\n\n/**\n * Default priority for blockers\n */\nexport const DEFAULT_PRIORITY = 0 as const;\n\n/**\n * Default priority for async actions\n */\nexport const ASYNC_ACTION_PRIORITY = 20 as const;\n\n/**\n * DevTools store name\n */\nexport const DEVTOOLS_NAME = \"UIBlocking\" as const;\n","import { StateCreator, StoreApi, StoreMutators, createStore, useStore } from \"zustand\";\nimport { useShallow } from \"zustand/shallow\";\n\n/**\n * Creates a Zustand store with automatic shallow comparison for all selectors\n *\n * This utility wraps the standard Zustand store creation and automatically applies\n * `useShallow` to all selectors, preventing unnecessary re-renders when selected\n * values haven't changed (shallow equality).\n *\n * @template StoreState - The type of the store state\n * @template TMutators - Array of middleware mutators (e.g., devtools, persist)\n *\n * @param storeCreator - The state creator function for Zustand\n * @returns Object containing the store hook and store API\n *\n * @see https://docs.pmnd.rs/zustand/guides/prevent-rerenders-with-use-shallow\n */\nexport function createShallowStore<\n StoreState,\n TMutators extends Array<[keyof StoreMutators<StoreState, StoreState>, unknown]> = [],\n>(\n storeCreator: StateCreator<StoreState, [], TMutators, StoreState>\n): {\n useStore: <T>(selector: (state: StoreState) => T) => T;\n useStoreApi: StoreApi<StoreState>;\n} {\n const storeApi: StoreApi<StoreState> = createStore<StoreState, TMutators>(storeCreator);\n\n const useScopedStore = <T>(selector: (state: StoreState) => T): T => {\n return useStore(storeApi, useShallow(selector));\n };\n\n return { useStore: useScopedStore, useStoreApi: storeApi };\n}\n\n/**\n * Normalize scope to array format\n *\n * @param scope - Single scope or array of scopes\n * @returns Array of scopes\n *\n * @internal\n */\nexport function normalizeScopeToArray(scope: string | ReadonlyArray<string>): Array<string> {\n if (typeof scope === \"string\") {\n return [scope];\n }\n return Array.from(scope);\n}\n","import { Middleware, MiddlewareContext } from \"../middleware\";\nimport { DEFAULT_PRIORITY, DEFAULT_REASON, DEFAULT_SCOPE } from \"./uiBlockingStore.constants\";\nimport { normalizeScopeToArray } from \"./uiBlockingStore.utils\";\nimport type {\n BlockerConfig,\n BlockerInfo,\n StoredBlocker,\n UIBlockingStore,\n} from \"./uiBlockingStore.types\";\nimport type { StateCreator } from \"zustand\";\n\n/**\n * UI Blocking Store Slice\n *\n * Implements the state and actions for UI blocking management.\n * This slice follows the Zustand slice pattern for better code organization.\n */\nexport const createUIBlockingActions: StateCreator<UIBlockingStore, [], [], UIBlockingStore> = (\n set,\n get\n) => ({\n // State\n activeBlockers: new Map(),\n middlewares: new Map(),\n\n registerMiddleware: (name: string, middleware: Middleware) => {\n set((state) => {\n const newMiddlewares = new Map(state.middlewares);\n newMiddlewares.set(name, middleware);\n return { middlewares: newMiddlewares };\n });\n console.log(`[UIBlocking] Registered middleware: ${name}`);\n },\n\n unregisterMiddleware: (name: string) => {\n set((state) => {\n const newMiddlewares = new Map(state.middlewares);\n newMiddlewares.delete(name);\n return { middlewares: newMiddlewares };\n });\n console.log(`[UIBlocking] Unregistered middleware: ${name}`);\n },\n\n runMiddlewares: async (context: MiddlewareContext) => {\n const { middlewares } = get();\n\n for (const [name, middleware] of middlewares) {\n try {\n await middleware(context);\n } catch (error) {\n console.error(`[UIBlocking] Middleware \"${name}\" error:`, error);\n }\n }\n },\n\n // Actions\n /**\n * Add a blocker to the store\n *\n * @param id - Unique blocker identifier\n * @param config - Optional blocker configuration\n *\n */\n addBlocker: (id: string, config: BlockerConfig = {}): void => {\n set((state) => {\n const newBlockers = new Map(state.activeBlockers);\n const storedBlocker: StoredBlocker = {\n scope: config.scope ?? DEFAULT_SCOPE,\n reason: config.reason ?? DEFAULT_REASON,\n priority: config.priority ?? DEFAULT_PRIORITY,\n timestamp: config.timestamp ?? Date.now(),\n };\n newBlockers.set(id, storedBlocker);\n\n return { activeBlockers: newBlockers };\n });\n\n void get().runMiddlewares({\n action: \"add\",\n blockerId: id,\n config: {\n scope: config.scope,\n reason: config.reason,\n priority: config.priority,\n },\n timestamp: Date.now(),\n });\n },\n\n /**\n * Remove a blocker from the store\n *\n * @param id - Blocker identifier to remove\n *\n */\n removeBlocker: (id: string): void => {\n const prevBlocker = get().activeBlockers.get(id);\n\n set((state) => {\n const newBlockers = new Map(state.activeBlockers);\n newBlockers.delete(id);\n\n return { activeBlockers: newBlockers };\n });\n\n if (prevBlocker) {\n void get().runMiddlewares({\n action: \"remove\",\n blockerId: id,\n config: prevBlocker,\n timestamp: Date.now(),\n prevState: prevBlocker,\n });\n }\n },\n\n /**\n * Check if a scope is currently blocked\n *\n * @param scope - Scope or array of scopes to check (default: \"global\")\n * @returns True if any of the scopes are blocked\n *\n */\n isBlocked: (scope: string | ReadonlyArray<string> = DEFAULT_SCOPE): boolean => {\n const { activeBlockers } = get();\n const scopes = normalizeScopeToArray(scope);\n\n for (const [, blocker] of activeBlockers) {\n // Global blocking blocks everything\n if (blocker.scope === DEFAULT_SCOPE) {\n return true;\n }\n\n // Check scope intersection\n const blockerScopes = normalizeScopeToArray(blocker.scope);\n\n if (scopes.some((s) => blockerScopes.includes(s))) {\n return true;\n }\n }\n\n return false;\n },\n\n /**\n * Get detailed blocking information for a specific scope\n *\n * @param scope - Scope to get blocking information for\n * @returns Array of blockers affecting the scope, sorted by priority (highest first)\n *\n */\n getBlockingInfo: (scope: string): ReadonlyArray<BlockerInfo> => {\n const { activeBlockers } = get();\n const blockers: Array<BlockerInfo> = [];\n\n for (const [id, blocker] of activeBlockers) {\n const blockerScopes = normalizeScopeToArray(blocker.scope);\n\n if (blocker.scope === DEFAULT_SCOPE || blockerScopes.includes(scope)) {\n blockers.push({ id, ...blocker });\n }\n }\n\n return blockers.sort((a, b) => b.priority - a.priority);\n },\n\n /**\n * Clear all blockers from the store\n */\n clearAllBlockers: (): void => {\n set({ activeBlockers: new Map() });\n },\n\n /**\n * Clear all blockers for a specific scope\n *\n * @param scope - Scope to clear blockers for\n *\n */\n clearBlockersForScope: (scope: string): void => {\n set((state) => {\n const newBlockers = new Map();\n\n for (const [id, blocker] of state.activeBlockers) {\n const blockerScopes = normalizeScopeToArray(blocker.scope);\n\n if (!blockerScopes.includes(scope)) {\n newBlockers.set(id, blocker);\n }\n }\n\n return { activeBlockers: newBlockers };\n });\n },\n});\n","import { DEVTOOLS_NAME } from \"./uiBlockingStore.constants\";\nimport type { DevtoolsOptions } from \"zustand/middleware\";\n\n/**\n * DevTools configuration for UI Blocking Store\n *\n * Enables Redux DevTools integration only in development mode\n * for better debugging experience without production overhead.\n */\nexport const devtoolsConfig: DevtoolsOptions = {\n name: DEVTOOLS_NAME,\n enabled: process.env.NODE_ENV !== \"production\",\n};\n","import { devtools } from \"zustand/middleware\";\nimport { createUIBlockingActions } from \"./uiBlockingStore.actions\";\nimport { devtoolsConfig } from \"./uiBlockingStore.config\";\nimport { createShallowStore } from \"./uiBlockingStore.utils\";\nimport type { UIBlockingStore } from \"./uiBlockingStore.types\";\n\n/**\n * UI Blocking Store\n *\n * Global Zustand store for managing UI blocking state across the application.\n *\n * Features:\n * - Priority-based blocking system\n * - Scope-based blocking (global, specific areas, or multiple scopes)\n * - Automatic cleanup on unmount (when using hooks)\n * - DevTools integration for debugging\n * - Automatic shallow comparison for selectors\n *\n */\nconst { useStore: useUIBlockingStore, useStoreApi: uiBlockingStoreApi } = createShallowStore<\n UIBlockingStore,\n [[\"zustand/devtools\", never]]\n>(devtools(createUIBlockingActions, devtoolsConfig));\n\nexport { useUIBlockingStore, uiBlockingStoreApi };\n","import { useCallback } from \"react\";\nimport { ASYNC_ACTION_PRIORITY, useUIBlockingStore } from \"../../store\";\n\n/**\n * Hook to wrap async functions with automatic blocking/unblocking\n *\n * Creates a wrapper function that automatically adds a blocker before executing\n * the async function and removes it after completion (success or failure).\n *\n * @template T - The return type of the async function\n * @param actionId - Unique identifier for the action (used in blocker ID and reason)\n * @param scope - Scope(s) to block during execution (default: \"global\")\n * @returns Function that wraps async functions with blocking behavior\n *\n */\nexport const useAsyncAction = <T = unknown>(\n actionId: string,\n scope?: string | ReadonlyArray<string>\n): ((asyncFn: () => Promise<T>) => Promise<T>) => {\n const { addBlocker, removeBlocker } = useUIBlockingStore((state) => ({\n addBlocker: state.addBlocker,\n removeBlocker: state.removeBlocker,\n }));\n\n const executeWithBlocking = useCallback(\n async (asyncFn: () => Promise<T>): Promise<T> => {\n const blockerId = `${actionId}-${Date.now().toString()}`;\n\n try {\n addBlocker(blockerId, {\n scope,\n reason: `Executing ${actionId}`,\n priority: ASYNC_ACTION_PRIORITY,\n });\n\n return await asyncFn();\n } finally {\n removeBlocker(blockerId);\n }\n },\n [actionId, scope, addBlocker, removeBlocker]\n );\n\n return executeWithBlocking;\n};\n","import { useEffect } from \"react\";\nimport { type BlockerConfig, useUIBlockingStore } from \"../../store\";\n\n/**\n * Hook to automatically add and remove a blocker based on component lifecycle\n *\n * Automatically adds a blocker when the component mounts (or when activated)\n * and removes it when the component unmounts (or when deactivated).\n *\n * @param blockerId - Unique identifier for the blocker\n * @param config - Blocker configuration (scope, reason, priority)\n * @param isActive - Whether the blocker is currently active (default: true)\n *\n */\nexport const useBlocker = (blockerId: string, config: BlockerConfig, isActive = true): void => {\n const { addBlocker, removeBlocker } = useUIBlockingStore((state) => ({\n addBlocker: state.addBlocker,\n removeBlocker: state.removeBlocker,\n }));\n\n useEffect(() => {\n if (!isActive || !blockerId) {\n return;\n }\n\n addBlocker(blockerId, config);\n\n return () => {\n removeBlocker(blockerId);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [blockerId, isActive, addBlocker, removeBlocker]);\n};\n","import { BlockerConfig } from \"../../store\";\n\n/**\n * Creates a blocker configuration object from partial config.\n * Filters out undefined values to create a clean BlockerConfig.\n *\n * @param config - Partial blocker configuration\n * @returns Complete BlockerConfig object\n *\n */\nexport function createBlockerConfig(config: {\n scope?: string | ReadonlyArray<string>;\n reason?: string;\n priority?: number;\n}): BlockerConfig {\n return {\n scope: config.scope,\n reason: config.reason,\n priority: config.priority,\n };\n}\n","import { useMemo } from \"react\";\nimport { useStore } from \"zustand\";\nimport { DEFAULT_SCOPE } from \"../../store\";\nimport { type BlockerInfo, uiBlockingStoreApi } from \"../../store\";\n\n/**\n * Hook to get detailed blocking information for a scope\n *\n * Returns an array of blocker information objects for the specified scope,\n * sorted by priority (highest first). Automatically re-renders when blockers change.\n *\n * Uses a stable reference - only re-renders when the actual blocker list changes,\n * not on every store update.\n *\n * @param scope - Scope to get blocking information for (default: \"global\")\n * @returns Array of blocker information objects, sorted by priority\n *\n * ```\n */\nexport const useBlockingInfo = (scope: string = DEFAULT_SCOPE): ReadonlyArray<BlockerInfo> => {\n // Subscribe to the activeBlockers Map to detect changes\n const activeBlockers = useStore(uiBlockingStoreApi, (state) => state.activeBlockers);\n\n // Recompute blockers only when activeBlockers or scope changes\n return useMemo(() => {\n return uiBlockingStoreApi.getState().getBlockingInfo(scope);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [activeBlockers, scope]);\n};\n","import { RefObject, useEffect, useRef } from \"react\";\n\n/**\n * Keeps a ref updated with the latest config value.\n * Useful for accessing current config in callbacks without stale closures.\n *\n * @param config - Configuration object to track\n * @returns Mutable ref that always contains the latest config\n *\n */\nexport function useConfigRef<T>(config: T): RefObject<T> {\n const configRef = useRef(config);\n\n useEffect(() => {\n configRef.current = config;\n }, [config]);\n\n return configRef;\n}\n","import { useCallback, useEffect, useRef } from \"react\";\nimport { useUIBlockingStore } from \"../../store\";\nimport { createBlockerConfig } from \"../useBlocker\";\nimport { useConfigRef } from \"../useConfigRef\";\nimport { ConditionalBlockerConfig } from \"./useConditionalBlocker.types\";\n\n/**\n * Hook for conditional blocking based on a condition function.\n *\n * Periodically checks a condition and blocks/unblocks based on the result.\n * The condition is evaluated at the specified interval (default 1000ms).\n *\n * @param blockerId - Unique identifier for this blocker\n * @param config - Configuration including condition function and check interval\n *\n */\nexport const useConditionalBlocker = <TState = unknown>(\n blockerId: string,\n config: ConditionalBlockerConfig<TState>\n): void => {\n const { addBlocker, removeBlocker } = useUIBlockingStore((state) => ({\n addBlocker: state.addBlocker,\n removeBlocker: state.removeBlocker,\n }));\n const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);\n const isBlockedRef = useRef(false);\n const configRef = useConfigRef(config);\n\n const checkCondition = useCallback(() => {\n const currentConfig = configRef.current;\n const shouldBlock = currentConfig.condition(currentConfig.state);\n\n // No state change needed\n if (shouldBlock === isBlockedRef.current) {\n return;\n }\n\n if (shouldBlock) {\n addBlocker(blockerId, createBlockerConfig(currentConfig));\n } else {\n removeBlocker(blockerId);\n }\n isBlockedRef.current = shouldBlock;\n }, [blockerId, addBlocker, removeBlocker, configRef]);\n\n useEffect(() => {\n checkCondition();\n\n const interval = configRef.current.checkInterval ?? 1000;\n intervalRef.current = setInterval(checkCondition, interval);\n\n return (): void => {\n if (intervalRef.current) {\n clearInterval(intervalRef.current);\n intervalRef.current = null;\n }\n if (isBlockedRef.current) {\n removeBlocker(blockerId);\n isBlockedRef.current = false;\n }\n };\n // configRef is stable and doesn't need to be in dependencies\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [checkCondition, blockerId, removeBlocker]);\n};\n","import { useCallback, useState } from \"react\";\nimport { useBlocker } from \"../useBlocker\";\nimport {\n ConfirmableBlockerConfig,\n UseConfirmableBlockerReturn,\n} from \"./useConfirmableBlocker.types\";\n\n/**\n * Hook for creating a confirmable action with blocking UI\n *\n */\nexport const useConfirmableBlocker = (\n blockerId: string,\n config: ConfirmableBlockerConfig\n): UseConfirmableBlockerReturn => {\n const [isDialogOpen, setIsDialogOpen] = useState(false);\n const [isExecuting, setIsExecuting] = useState(false);\n\n useBlocker(\n blockerId,\n {\n ...config,\n reason: config.reason ?? config.confirmMessage,\n },\n isDialogOpen || isExecuting\n );\n\n const execute = useCallback(() => {\n setIsDialogOpen(true);\n }, []);\n\n const onConfirm = useCallback(async () => {\n setIsDialogOpen(false);\n setIsExecuting(true);\n\n try {\n await config.onConfirm();\n } catch (error) {\n console.error(\"[UIBlocking] Confirmable action error:\", error);\n throw error;\n } finally {\n setIsExecuting(false);\n }\n }, [config]);\n\n const onCancel = useCallback(() => {\n setIsDialogOpen(false);\n config.onCancel?.();\n }, [config]);\n\n return {\n execute,\n isDialogOpen,\n isExecuting,\n confirmConfig: {\n title: config.confirmTitle ?? \"Confirm Action\",\n message: config.confirmMessage,\n confirmText: config.confirmButtonText ?? \"Confirm\",\n cancelText: config.cancelButtonText ?? \"Cancel\",\n },\n onConfirm,\n onCancel,\n };\n};\n","import { useUIBlockingStore } from \"../../store\";\n\n/**\n * Hook to check if a scope is currently blocked\n *\n * Returns a boolean indicating whether the specified scope(s) are blocked.\n * Automatically re-renders when the blocking state changes.\n *\n * @param scope - Scope or array of scopes to check (default: \"global\")\n * @returns True if any of the specified scopes are blocked\n *\n */\nexport const useIsBlocked = (scope?: string | ReadonlyArray<string>): boolean => {\n return useUIBlockingStore((state) => state.isBlocked(scope));\n};\n","import type { BlockingSchedule } from \"./useScheduledBlocker.types\";\n\n/**\n * Maximum safe timeout value for setTimeout in JavaScript (~24.8 days).\n * Values larger than this will cause setTimeout to trigger immediately.\n */\nexport const MAX_TIMEOUT_MS = 2147483647;\n\n/**\n * Validates a date value and converts it to timestamp.\n *\n * @param date - Date value as string, Date object, or number\n * @returns Timestamp in milliseconds, or NaN if invalid\n */\nexport function parseDate(date: string | Date | number): number {\n return new Date(date).getTime();\n}\n\n/**\n * Validates if a timestamp is valid (not NaN).\n *\n * @param timestamp - Timestamp to validate\n * @returns True if valid, false otherwise\n */\nexport function isValidTimestamp(timestamp: number): boolean {\n return !Number.isNaN(timestamp);\n}\n\n/**\n * Calculates the end time based on schedule configuration.\n * Duration takes precedence over end time if both are provided.\n *\n * @param schedule - Blocking schedule configuration\n * @param startTime - Start time in milliseconds\n * @returns End time in milliseconds, or undefined if not specified\n */\nexport function calculateEndTime(\n schedule: BlockingSchedule,\n startTime: number\n): number | undefined {\n if (schedule.duration) {\n return startTime + schedule.duration;\n }\n\n if (schedule.end) {\n const endTime = parseDate(schedule.end);\n return isValidTimestamp(endTime) ? endTime : undefined;\n }\n\n return undefined;\n}\n\n/**\n * Validates if a delay is within the safe setTimeout range.\n *\n * @param delay - Delay in milliseconds\n * @returns True if delay is safe to use with setTimeout\n */\nexport function isSafeTimeout(delay: number): boolean {\n return delay > 0 && delay <= MAX_TIMEOUT_MS;\n}\n\n/**\n * Determines if the current time is within a blocking schedule.\n *\n * @param startTime - Schedule start time in milliseconds\n * @param endTime - Schedule end time in milliseconds (optional)\n * @param now - Current time in milliseconds\n * @returns True if currently in the blocking period\n */\nexport function isInBlockingPeriod(\n startTime: number,\n endTime: number | undefined,\n now: number\n): boolean {\n if (startTime > now) {\n return false; // Not started yet\n }\n\n if (!endTime) {\n return true; // No end time means block indefinitely\n }\n\n return endTime > now; // Check if end time hasn't passed\n}\n\n/**\n * Checks if a schedule is completely in the past.\n *\n * @param startTime - Schedule start time in milliseconds\n * @param endTime - Schedule end time in milliseconds (optional)\n * @param now - Current time in milliseconds\n * @returns True if the schedule is in the past\n */\nexport function isScheduleInPast(\n startTime: number,\n endTime: number | undefined,\n now: number\n): boolean {\n if (!endTime) {\n return false; // No end time means it can still be active\n }\n\n return endTime <= now && startTime <= now;\n}\n","import { useCallback, useEffect, useRef } from \"react\";\nimport { useUIBlockingStore } from \"../../store\";\nimport { createBlockerConfig } from \"../useBlocker\";\nimport { useConfigRef } from \"../useConfigRef\";\nimport { ScheduledBlockerConfig } from \"./useScheduledBlocker.types\";\nimport {\n MAX_TIMEOUT_MS,\n calculateEndTime,\n isInBlockingPeriod,\n isSafeTimeout,\n isScheduleInPast,\n isValidTimestamp,\n parseDate,\n} from \"./useScheduledBlocker.utils\";\n\n/**\n * Hook for scheduling UI blocking for a specific time period.\n *\n * Blocks UI during a scheduled maintenance window or time period.\n * Supports start/end times as Date objects, ISO strings, or timestamps.\n * If both duration and end are provided, duration takes precedence.\n *\n * @param blockerId - Unique identifier for this blocker\n * @param config - Configuration including schedule and callbacks\n *\n */\nexport const useScheduledBlocker = (blockerId: string, config: ScheduledBlockerConfig): void => {\n const { addBlocker, removeBlocker } = useUIBlockingStore((state) => ({\n addBlocker: state.addBlocker,\n removeBlocker: state.removeBlocker,\n }));\n const timeoutsRef = useRef<{\n start?: ReturnType<typeof setTimeout>;\n end?: ReturnType<typeof setTimeout>;\n }>({});\n const configRef = useConfigRef(config);\n\n const cleanup = useCallback(() => {\n if (timeoutsRef.current.start) {\n clearTimeout(timeoutsRef.current.start);\n timeoutsRef.current.start = undefined;\n }\n if (timeoutsRef.current.end) {\n clearTimeout(timeoutsRef.current.end);\n timeoutsRef.current.end = undefined;\n }\n }, []);\n\n useEffect(() => {\n const currentConfig = configRef.current;\n const startTime = parseDate(currentConfig.schedule.start);\n const now = Date.now();\n\n // Validate start time\n if (!isValidTimestamp(startTime)) {\n console.error(`[UIBlocking] Invalid start time for blocker \"${blockerId}\"`);\n return;\n }\n\n const scheduleEnd = (): void => {\n const endTime = calculateEndTime(currentConfig.schedule, startTime);\n if (!endTime) {\n return;\n }\n\n const remainingTime = endTime - Date.now();\n if (remainingTime > 0) {\n timeoutsRef.current.end = setTimeout(() => {\n configRef.current.onScheduleEnd?.();\n removeBlocker(blockerId);\n }, remainingTime);\n }\n };\n\n const startBlocking = (): void => {\n const cfg = configRef.current;\n addBlocker(blockerId, createBlockerConfig(cfg));\n cfg.onScheduleStart?.();\n scheduleEnd();\n };\n\n // If start time hasn't arrived yet\n if (startTime > now) {\n const delay = startTime - now;\n\n if (!isSafeTimeout(delay)) {\n console.warn(\n `[UIBlocking] Schedule delay exceeds maximum timeout (${MAX_TIMEOUT_MS.toString()}ms) for blocker \"${blockerId}\"`\n );\n return;\n }\n\n timeoutsRef.current.start = setTimeout(startBlocking, delay);\n }\n // If already in blocking period or should start immediately\n else {\n const endTime = calculateEndTime(currentConfig.schedule, startTime);\n\n if (isInBlockingPeriod(startTime, endTime, now)) {\n startBlocking();\n } else if (isScheduleInPast(startTime, endTime, now)) {\n console.warn(`[UIBlocking] Schedule is in the past for blocker \"${blockerId}\"`);\n }\n }\n\n return (): void => {\n cleanup();\n removeBlocker(blockerId);\n };\n // configRef is stable and doesn't need to be in dependencies\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [blockerId, addBlocker, removeBlocker, cleanup]);\n};\n","import { AnalyticsEventData } from \"./analyticsMiddleware.types\";\nimport { MiddlewareContext } from \"./middleware.types\";\n\nconst capitalizeFirst = (str: string): string => {\n return str.charAt(0).toUpperCase() + str.slice(1);\n};\n\nexport const buildEventData = (context: MiddlewareContext): AnalyticsEventData => {\n const eventData: AnalyticsEventData = {\n blocker_id: context.blockerId,\n };\n const { scope, reason, priority } = context.config ?? {};\n\n if (scope !== undefined) {\n eventData.scope = Array.isArray(scope) ? scope.join(\",\") : scope;\n }\n\n if (reason !== undefined) {\n eventData.reason = reason;\n }\n\n if (priority !== undefined) {\n eventData.priority = priority;\n }\n\n return eventData;\n};\n\nexport const trackGoogleAnalytics = (action: string, eventData: AnalyticsEventData): void => {\n if (window.gtag) {\n window.gtag(\"event\", `ui_blocking_${action}`, eventData);\n }\n};\n\nexport const trackMixpanel = (action: string, eventData: AnalyticsEventData): void => {\n if (window.mixpanel) {\n const eventName = `UI Blocking ${action.split(\"_\").map(capitalizeFirst).join(\" \")}`;\n\n window.mixpanel.track(eventName, eventData);\n }\n};\n\nexport const trackAmplitude = (action: string, eventData: AnalyticsEventData): void => {\n if (window.amplitude) {\n const eventName = `UI Blocking ${action.split(\"_\").map(capitalizeFirst).join(\" \")}`;\n\n window.amplitude.track(eventName, eventData);\n }\n};\n\nexport const trackCustom = (\n trackFn: (event: string, data: AnalyticsEventData) => void,\n action: string,\n eventData: AnalyticsEventData\n): void => {\n try {\n trackFn(`ui_blocking_${action}`, eventData);\n } catch {\n // Silently ignore errors in custom tracker\n }\n};\n","import { AnalyticsConfig, AnalyticsEventData } from \"./analyticsMiddleware.types\";\nimport {\n buildEventData,\n trackAmplitude,\n trackCustom,\n trackGoogleAnalytics,\n trackMixpanel,\n} from \"./analyticsMiddleware.utils\";\nimport { Middleware, MiddlewareContext } from \"./middleware.types\";\n\nconst trackEvent = (\n config: AnalyticsConfig,\n context: MiddlewareContext,\n eventData: AnalyticsEventData\n): void => {\n if (\"provider\" in config) {\n switch (config.provider) {\n case \"ga\":\n trackGoogleAnalytics(context.action, eventData);\n return;\n case \"mixpanel\":\n trackMixpanel(context.action, eventData);\n return;\n case \"amplitude\":\n trackAmplitude(context.action, eventData);\n return;\n }\n }\n\n if (\"track\" in config) {\n trackCustom(config.track, context.action, eventData);\n }\n};\n\nexport const createAnalyticsMiddleware = (config: AnalyticsConfig): Middleware => {\n return (context) => {\n const eventData = buildEventData(context);\n\n trackEvent(config, context, eventData);\n };\n};\n","import { uiBlockingStoreApi } from \"../store/uiBlockingStore.store\";\nimport type { Middleware } from \"./middleware.types\";\n\n/**\n * Configure middleware for the UI blocking store\n *\n * This is a convenience function that registers multiple middleware at once.\n * Each middleware will be registered with an auto-generated name based on its index.\n *\n * @param middlewares - Array of middleware functions to register\n *\n */\nexport function configureMiddleware(middlewares: ReadonlyArray<Middleware>): void {\n const store = uiBlockingStoreApi.getState();\n\n middlewares.forEach((middleware, index) => {\n // Generate a unique name for each middleware\n const name = `middleware-${index.toString()}`;\n store.registerMiddleware(name, middleware);\n });\n}\n","import { MiddlewareBlockerConfig, MiddlewareContext } from \"./middleware.types\";\n\nexport const getActionEmoji = (action: string): string => {\n switch (action) {\n case \"add\":\n return \"➕\";\n case \"remove\":\n return \"➖\";\n case \"update\":\n return \"🔄\";\n case \"cancel\":\n return \"❌\";\n case \"timeout\":\n return \"⏱️\";\n default:\n return \"❓\";\n }\n};\n\nconst extractConfigDetails = (config?: MiddlewareBlockerConfig): Record<string, unknown> => {\n if (!config) {\n return {};\n }\n\n const { scope, reason, priority } = config;\n\n const details: Record<string, unknown> = {\n scope,\n reason,\n };\n\n if (priority !== undefined) {\n details.priority = priority;\n }\n\n return details;\n};\n\nexport const formatLogData = (context: MiddlewareContext): Record<string, unknown> => {\n const configDetails = extractConfigDetails(context.config);\n\n if (context.prevState) {\n return {\n config: configDetails,\n prevState: extractConfigDetails(context.prevState),\n };\n }\n\n return configDetails;\n};\n","import { formatLogData, getActionEmoji } from \"./loggerMiddleware.utils\";\nimport { Middleware } from \"./middleware.types\";\n\nconst LOG_PREFIX = \"[UIBlocking]\";\n\nexport const loggerMiddleware: Middleware = (context) => {\n const emoji = getActionEmoji(context.action);\n const logData = formatLogData(context);\n\n console.log(LOG_PREFIX, emoji, context.blockerId, logData);\n};\n","export const handleAddAction = (\n blockerId: string,\n timestamp: number,\n blockStartTimes: Map<string, number>\n): void => {\n blockStartTimes.set(blockerId, timestamp);\n};\n","import { Middleware, MiddlewareContext } from \"./middleware.types\";\nimport { PerformanceConfig } from \"./performanceMiddleware.types\";\nimport { handleAddAction } from \"./performanceMiddleware.utils\";\n\nconst DEFAULT_SLOW_BLOCK_THRESHOLD = 3000;\nconst ACTION_ADD = \"add\";\nconst ACTION_REMOVE = \"remove\";\n\nconst handleRemoveAction = (\n context: MiddlewareContext,\n blockStartTimes: Map<string, number>,\n slowBlockThreshold: number,\n onSlowBlock?: (blockerId: string, duration: number) => void\n): void => {\n const startTime = blockStartTimes.get(context.blockerId);\n\n if (startTime === undefined) {\n return;\n }\n\n const duration = context.timestamp - startTime;\n blockStartTimes.delete(context.blockerId);\n\n if (duration >= slowBlockThreshold) {\n console.warn(\n `[UIBlocking] Slow block detected: \"${context.blockerId}\" took ${duration.toString()}ms`\n );\n\n onSlowBlock?.(context.blockerId, duration);\n }\n};\n\nexport const createPerformanceMiddleware = (config: PerformanceConfig = {}): Middleware => {\n const { slowBlockThreshold = DEFAULT_SLOW_BLOCK_THRESHOLD, onSlowBlock } = config;\n const blockStartTimes = new Map<string, number>();\n\n return (context) => {\n if (context.action === ACTION_ADD) {\n handleAddAction(context.blockerId, context.timestamp, blockStartTimes);\n } else if (context.action === ACTION_REMOVE) {\n handleRemoveAction(context, blockStartTimes, slowBlockThreshold, onSlowBlock);\n }\n };\n};\n"]}
package/dist/index.d.cts CHANGED
@@ -43,6 +43,17 @@ type Middleware = (context: MiddlewareContext) => void | Promise<void>;
43
43
 
44
44
  declare const createAnalyticsMiddleware: (config: AnalyticsConfig) => Middleware;
45
45
 
46
+ /**
47
+ * Configure middleware for the UI blocking store
48
+ *
49
+ * This is a convenience function that registers multiple middleware at once.
50
+ * Each middleware will be registered with an auto-generated name based on its index.
51
+ *
52
+ * @param middlewares - Array of middleware functions to register
53
+ *
54
+ */
55
+ declare function configureMiddleware(middlewares: ReadonlyArray<Middleware>): void;
56
+
46
57
  declare const loggerMiddleware: Middleware;
47
58
 
48
59
  interface PerformanceConfig {
@@ -131,6 +142,22 @@ declare const uiBlockingStoreApi: zustand.StoreApi<UIBlockingStore>;
131
142
  */
132
143
  declare const useBlocker: (blockerId: string, config: BlockerConfig, isActive?: boolean) => void;
133
144
 
145
+ /**
146
+ * Hook to get detailed blocking information for a scope
147
+ *
148
+ * Returns an array of blocker information objects for the specified scope,
149
+ * sorted by priority (highest first). Automatically re-renders when blockers change.
150
+ *
151
+ * Uses a stable reference - only re-renders when the actual blocker list changes,
152
+ * not on every store update.
153
+ *
154
+ * @param scope - Scope to get blocking information for (default: "global")
155
+ * @returns Array of blocker information objects, sorted by priority
156
+ *
157
+ * ```
158
+ */
159
+ declare const useBlockingInfo: (scope?: string) => ReadonlyArray<BlockerInfo>;
160
+
134
161
  /**
135
162
  * Configuration for conditional blocker hook.
136
163
  *
@@ -261,4 +288,4 @@ interface ScheduledBlockerConfig extends BlockerConfig {
261
288
  */
262
289
  declare const useScheduledBlocker: (blockerId: string, config: ScheduledBlockerConfig) => void;
263
290
 
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 };
291
+ 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, configureMiddleware, createAnalyticsMiddleware, createPerformanceMiddleware, loggerMiddleware, uiBlockingStoreApi, useAsyncAction, useBlocker, useBlockingInfo, useConditionalBlocker, useConfirmableBlocker, useIsBlocked, useScheduledBlocker, useUIBlockingStore };
package/dist/index.d.ts CHANGED
@@ -43,6 +43,17 @@ type Middleware = (context: MiddlewareContext) => void | Promise<void>;
43
43
 
44
44
  declare const createAnalyticsMiddleware: (config: AnalyticsConfig) => Middleware;
45
45
 
46
+ /**
47
+ * Configure middleware for the UI blocking store
48
+ *
49
+ * This is a convenience function that registers multiple middleware at once.
50
+ * Each middleware will be registered with an auto-generated name based on its index.
51
+ *
52
+ * @param middlewares - Array of middleware functions to register
53
+ *
54
+ */
55
+ declare function configureMiddleware(middlewares: ReadonlyArray<Middleware>): void;
56
+
46
57
  declare const loggerMiddleware: Middleware;
47
58
 
48
59
  interface PerformanceConfig {
@@ -131,6 +142,22 @@ declare const uiBlockingStoreApi: zustand.StoreApi<UIBlockingStore>;
131
142
  */
132
143
  declare const useBlocker: (blockerId: string, config: BlockerConfig, isActive?: boolean) => void;
133
144
 
145
+ /**
146
+ * Hook to get detailed blocking information for a scope
147
+ *
148
+ * Returns an array of blocker information objects for the specified scope,
149
+ * sorted by priority (highest first). Automatically re-renders when blockers change.
150
+ *
151
+ * Uses a stable reference - only re-renders when the actual blocker list changes,
152
+ * not on every store update.
153
+ *
154
+ * @param scope - Scope to get blocking information for (default: "global")
155
+ * @returns Array of blocker information objects, sorted by priority
156
+ *
157
+ * ```
158
+ */
159
+ declare const useBlockingInfo: (scope?: string) => ReadonlyArray<BlockerInfo>;
160
+
134
161
  /**
135
162
  * Configuration for conditional blocker hook.
136
163
  *
@@ -261,4 +288,4 @@ interface ScheduledBlockerConfig extends BlockerConfig {
261
288
  */
262
289
  declare const useScheduledBlocker: (blockerId: string, config: ScheduledBlockerConfig) => void;
263
290
 
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 };
291
+ 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, configureMiddleware, createAnalyticsMiddleware, createPerformanceMiddleware, loggerMiddleware, uiBlockingStoreApi, useAsyncAction, useBlocker, useBlockingInfo, useConditionalBlocker, useConfirmableBlocker, useIsBlocked, useScheduledBlocker, useUIBlockingStore };
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { useCallback, useEffect, useRef, useState } from 'react';
1
+ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
2
2
  import { devtools } from 'zustand/middleware';
3
3
  import { createStore, useStore } from 'zustand';
4
4
  import { useShallow } from 'zustand/shallow';
@@ -232,6 +232,12 @@ function createBlockerConfig(config) {
232
232
  priority: config.priority
233
233
  };
234
234
  }
235
+ var useBlockingInfo = (scope = DEFAULT_SCOPE) => {
236
+ const activeBlockers = useStore(uiBlockingStoreApi, (state) => state.activeBlockers);
237
+ return useMemo(() => {
238
+ return uiBlockingStoreApi.getState().getBlockingInfo(scope);
239
+ }, [activeBlockers, scope]);
240
+ };
235
241
  function useConfigRef(config) {
236
242
  const configRef = useRef(config);
237
243
  useEffect(() => {
@@ -504,6 +510,15 @@ var createAnalyticsMiddleware = (config) => {
504
510
  };
505
511
  };
506
512
 
513
+ // src/middleware/configureMiddleware.ts
514
+ function configureMiddleware(middlewares) {
515
+ const store = uiBlockingStoreApi.getState();
516
+ middlewares.forEach((middleware, index) => {
517
+ const name = `middleware-${index.toString()}`;
518
+ store.registerMiddleware(name, middleware);
519
+ });
520
+ }
521
+
507
522
  // src/middleware/loggerMiddleware.utils.ts
508
523
  var getActionEmoji = (action) => {
509
524
  switch (action) {
@@ -589,6 +604,6 @@ var createPerformanceMiddleware = (config = {}) => {
589
604
  };
590
605
  };
591
606
 
592
- export { createAnalyticsMiddleware, createPerformanceMiddleware, loggerMiddleware, uiBlockingStoreApi, useAsyncAction, useBlocker, useConditionalBlocker, useConfirmableBlocker, useIsBlocked, useScheduledBlocker, useUIBlockingStore };
607
+ export { configureMiddleware, createAnalyticsMiddleware, createPerformanceMiddleware, loggerMiddleware, uiBlockingStoreApi, useAsyncAction, useBlocker, useBlockingInfo, useConditionalBlocker, useConfirmableBlocker, useIsBlocked, useScheduledBlocker, useUIBlockingStore };
593
608
  //# sourceMappingURL=index.js.map
594
609
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/store/uiBlockingStore.constants.ts","../src/store/uiBlockingStore.utils.ts","../src/store/uiBlockingStore.actions.ts","../src/store/uiBlockingStore.config.ts","../src/store/uiBlockingStore.store.ts","../src/hooks/useAsyncAction/useAsyncAction.ts","../src/hooks/useBlocker/useBlocker.ts","../src/hooks/useBlocker/useBlocker.utils.ts","../src/hooks/useConfigRef.ts","../src/hooks/useConditionalBlocker/useConditionalBlocker.ts","../src/hooks/useConfirmableBlocker/useConfirmableBlocker.ts","../src/hooks/useIsBlocked/useIsBlocked.ts","../src/hooks/useScheduledBlocker/useScheduledBlocker.utils.ts","../src/hooks/useScheduledBlocker/useScheduledBlocker.ts","../src/middleware/analyticsMiddleware.utils.ts","../src/middleware/analyticsMiddleware.ts","../src/middleware/loggerMiddleware.utils.ts","../src/middleware/loggerMiddleware.ts","../src/middleware/performanceMiddleware.utils.ts","../src/middleware/performanceMiddleware.ts"],"names":["useEffect","useRef","useCallback"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Default values and constants for UI Blocking Store\n */\n\n/**\n * Default scope for blockers\n */\nexport const DEFAULT_SCOPE = \"global\" as const;\n\n/**\n * Default reason when none is provided\n */\nexport const DEFAULT_REASON = \"Unknown\" as const;\n\n/**\n * Default priority for blockers\n */\nexport const DEFAULT_PRIORITY = 0 as const;\n\n/**\n * Default priority for async actions\n */\nexport const ASYNC_ACTION_PRIORITY = 20 as const;\n\n/**\n * DevTools store name\n */\nexport const DEVTOOLS_NAME = \"UIBlocking\" as const;\n","import { StateCreator, StoreApi, StoreMutators, createStore, useStore } from \"zustand\";\nimport { useShallow } from \"zustand/shallow\";\n\n/**\n * Creates a Zustand store with automatic shallow comparison for all selectors\n *\n * This utility wraps the standard Zustand store creation and automatically applies\n * `useShallow` to all selectors, preventing unnecessary re-renders when selected\n * values haven't changed (shallow equality).\n *\n * @template StoreState - The type of the store state\n * @template TMutators - Array of middleware mutators (e.g., devtools, persist)\n *\n * @param storeCreator - The state creator function for Zustand\n * @returns Object containing the store hook and store API\n *\n * @see https://docs.pmnd.rs/zustand/guides/prevent-rerenders-with-use-shallow\n */\nexport function createShallowStore<\n StoreState,\n TMutators extends Array<[keyof StoreMutators<StoreState, StoreState>, unknown]> = [],\n>(\n storeCreator: StateCreator<StoreState, [], TMutators, StoreState>\n): {\n useStore: <T>(selector: (state: StoreState) => T) => T;\n useStoreApi: StoreApi<StoreState>;\n} {\n const storeApi: StoreApi<StoreState> = createStore<StoreState, TMutators>(storeCreator);\n\n const useScopedStore = <T>(selector: (state: StoreState) => T): T => {\n return useStore(storeApi, useShallow(selector));\n };\n\n return { useStore: useScopedStore, useStoreApi: storeApi };\n}\n\n/**\n * Normalize scope to array format\n *\n * @param scope - Single scope or array of scopes\n * @returns Array of scopes\n *\n * @internal\n */\nexport function normalizeScopeToArray(scope: string | ReadonlyArray<string>): Array<string> {\n if (typeof scope === \"string\") {\n return [scope];\n }\n return Array.from(scope);\n}\n","import { Middleware, MiddlewareContext } from \"../middleware\";\nimport { DEFAULT_PRIORITY, DEFAULT_REASON, DEFAULT_SCOPE } from \"./uiBlockingStore.constants\";\nimport { normalizeScopeToArray } from \"./uiBlockingStore.utils\";\nimport type {\n BlockerConfig,\n BlockerInfo,\n StoredBlocker,\n UIBlockingStore,\n} from \"./uiBlockingStore.types\";\nimport type { StateCreator } from \"zustand\";\n\n/**\n * UI Blocking Store Slice\n *\n * Implements the state and actions for UI blocking management.\n * This slice follows the Zustand slice pattern for better code organization.\n */\nexport const createUIBlockingActions: StateCreator<UIBlockingStore, [], [], UIBlockingStore> = (\n set,\n get\n) => ({\n // State\n activeBlockers: new Map(),\n middlewares: new Map(),\n\n registerMiddleware: (name: string, middleware: Middleware) => {\n set((state) => {\n const newMiddlewares = new Map(state.middlewares);\n newMiddlewares.set(name, middleware);\n return { middlewares: newMiddlewares };\n });\n console.log(`[UIBlocking] Registered middleware: ${name}`);\n },\n\n unregisterMiddleware: (name: string) => {\n set((state) => {\n const newMiddlewares = new Map(state.middlewares);\n newMiddlewares.delete(name);\n return { middlewares: newMiddlewares };\n });\n console.log(`[UIBlocking] Unregistered middleware: ${name}`);\n },\n\n runMiddlewares: async (context: MiddlewareContext) => {\n const { middlewares } = get();\n\n for (const [name, middleware] of middlewares) {\n try {\n await middleware(context);\n } catch (error) {\n console.error(`[UIBlocking] Middleware \"${name}\" error:`, error);\n }\n }\n },\n\n // Actions\n /**\n * Add a blocker to the store\n *\n * @param id - Unique blocker identifier\n * @param config - Optional blocker configuration\n *\n */\n addBlocker: (id: string, config: BlockerConfig = {}): void => {\n set((state) => {\n const newBlockers = new Map(state.activeBlockers);\n const storedBlocker: StoredBlocker = {\n scope: config.scope ?? DEFAULT_SCOPE,\n reason: config.reason ?? DEFAULT_REASON,\n priority: config.priority ?? DEFAULT_PRIORITY,\n timestamp: config.timestamp ?? Date.now(),\n };\n newBlockers.set(id, storedBlocker);\n\n return { activeBlockers: newBlockers };\n });\n\n void get().runMiddlewares({\n action: \"add\",\n blockerId: id,\n config: {\n scope: config.scope,\n reason: config.reason,\n priority: config.priority,\n },\n timestamp: Date.now(),\n });\n },\n\n /**\n * Remove a blocker from the store\n *\n * @param id - Blocker identifier to remove\n *\n */\n removeBlocker: (id: string): void => {\n const prevBlocker = get().activeBlockers.get(id);\n\n set((state) => {\n const newBlockers = new Map(state.activeBlockers);\n newBlockers.delete(id);\n\n return { activeBlockers: newBlockers };\n });\n\n if (prevBlocker) {\n void get().runMiddlewares({\n action: \"remove\",\n blockerId: id,\n config: prevBlocker,\n timestamp: Date.now(),\n prevState: prevBlocker,\n });\n }\n },\n\n /**\n * Check if a scope is currently blocked\n *\n * @param scope - Scope or array of scopes to check (default: \"global\")\n * @returns True if any of the scopes are blocked\n *\n */\n isBlocked: (scope: string | ReadonlyArray<string> = DEFAULT_SCOPE): boolean => {\n const { activeBlockers } = get();\n const scopes = normalizeScopeToArray(scope);\n\n for (const [, blocker] of activeBlockers) {\n // Global blocking blocks everything\n if (blocker.scope === DEFAULT_SCOPE) {\n return true;\n }\n\n // Check scope intersection\n const blockerScopes = normalizeScopeToArray(blocker.scope);\n\n if (scopes.some((s) => blockerScopes.includes(s))) {\n return true;\n }\n }\n\n return false;\n },\n\n /**\n * Get detailed blocking information for a specific scope\n *\n * @param scope - Scope to get blocking information for\n * @returns Array of blockers affecting the scope, sorted by priority (highest first)\n *\n */\n getBlockingInfo: (scope: string): ReadonlyArray<BlockerInfo> => {\n const { activeBlockers } = get();\n const blockers: Array<BlockerInfo> = [];\n\n for (const [id, blocker] of activeBlockers) {\n const blockerScopes = normalizeScopeToArray(blocker.scope);\n\n if (blocker.scope === DEFAULT_SCOPE || blockerScopes.includes(scope)) {\n blockers.push({ id, ...blocker });\n }\n }\n\n return blockers.sort((a, b) => b.priority - a.priority);\n },\n\n /**\n * Clear all blockers from the store\n */\n clearAllBlockers: (): void => {\n set({ activeBlockers: new Map() });\n },\n\n /**\n * Clear all blockers for a specific scope\n *\n * @param scope - Scope to clear blockers for\n *\n */\n clearBlockersForScope: (scope: string): void => {\n set((state) => {\n const newBlockers = new Map();\n\n for (const [id, blocker] of state.activeBlockers) {\n const blockerScopes = normalizeScopeToArray(blocker.scope);\n\n if (!blockerScopes.includes(scope)) {\n newBlockers.set(id, blocker);\n }\n }\n\n return { activeBlockers: newBlockers };\n });\n },\n});\n","import { DEVTOOLS_NAME } from \"./uiBlockingStore.constants\";\nimport type { DevtoolsOptions } from \"zustand/middleware\";\n\n/**\n * DevTools configuration for UI Blocking Store\n *\n * Enables Redux DevTools integration only in development mode\n * for better debugging experience without production overhead.\n */\nexport const devtoolsConfig: DevtoolsOptions = {\n name: DEVTOOLS_NAME,\n enabled: process.env.NODE_ENV !== \"production\",\n};\n","import { devtools } from \"zustand/middleware\";\nimport { createUIBlockingActions } from \"./uiBlockingStore.actions\";\nimport { devtoolsConfig } from \"./uiBlockingStore.config\";\nimport { createShallowStore } from \"./uiBlockingStore.utils\";\nimport type { UIBlockingStore } from \"./uiBlockingStore.types\";\n\n/**\n * UI Blocking Store\n *\n * Global Zustand store for managing UI blocking state across the application.\n *\n * Features:\n * - Priority-based blocking system\n * - Scope-based blocking (global, specific areas, or multiple scopes)\n * - Automatic cleanup on unmount (when using hooks)\n * - DevTools integration for debugging\n * - Automatic shallow comparison for selectors\n *\n */\nconst { useStore: useUIBlockingStore, useStoreApi: uiBlockingStoreApi } = createShallowStore<\n UIBlockingStore,\n [[\"zustand/devtools\", never]]\n>(devtools(createUIBlockingActions, devtoolsConfig));\n\nexport { useUIBlockingStore, uiBlockingStoreApi };\n","import { useCallback } from \"react\";\nimport { ASYNC_ACTION_PRIORITY, useUIBlockingStore } from \"../../store\";\n\n/**\n * Hook to wrap async functions with automatic blocking/unblocking\n *\n * Creates a wrapper function that automatically adds a blocker before executing\n * the async function and removes it after completion (success or failure).\n *\n * @template T - The return type of the async function\n * @param actionId - Unique identifier for the action (used in blocker ID and reason)\n * @param scope - Scope(s) to block during execution (default: \"global\")\n * @returns Function that wraps async functions with blocking behavior\n *\n */\nexport const useAsyncAction = <T = unknown>(\n actionId: string,\n scope?: string | ReadonlyArray<string>\n): ((asyncFn: () => Promise<T>) => Promise<T>) => {\n const { addBlocker, removeBlocker } = useUIBlockingStore((state) => ({\n addBlocker: state.addBlocker,\n removeBlocker: state.removeBlocker,\n }));\n\n const executeWithBlocking = useCallback(\n async (asyncFn: () => Promise<T>): Promise<T> => {\n const blockerId = `${actionId}-${Date.now().toString()}`;\n\n try {\n addBlocker(blockerId, {\n scope,\n reason: `Executing ${actionId}`,\n priority: ASYNC_ACTION_PRIORITY,\n });\n\n return await asyncFn();\n } finally {\n removeBlocker(blockerId);\n }\n },\n [actionId, scope, addBlocker, removeBlocker]\n );\n\n return executeWithBlocking;\n};\n","import { useEffect } from \"react\";\nimport { type BlockerConfig, useUIBlockingStore } from \"../../store\";\n\n/**\n * Hook to automatically add and remove a blocker based on component lifecycle\n *\n * Automatically adds a blocker when the component mounts (or when activated)\n * and removes it when the component unmounts (or when deactivated).\n *\n * @param blockerId - Unique identifier for the blocker\n * @param config - Blocker configuration (scope, reason, priority)\n * @param isActive - Whether the blocker is currently active (default: true)\n *\n */\nexport const useBlocker = (blockerId: string, config: BlockerConfig, isActive = true): void => {\n const { addBlocker, removeBlocker } = useUIBlockingStore((state) => ({\n addBlocker: state.addBlocker,\n removeBlocker: state.removeBlocker,\n }));\n\n useEffect(() => {\n if (!isActive || !blockerId) {\n return;\n }\n\n addBlocker(blockerId, config);\n\n return () => {\n removeBlocker(blockerId);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [blockerId, isActive, addBlocker, removeBlocker]);\n};\n","import { BlockerConfig } from \"../../store\";\n\n/**\n * Creates a blocker configuration object from partial config.\n * Filters out undefined values to create a clean BlockerConfig.\n *\n * @param config - Partial blocker configuration\n * @returns Complete BlockerConfig object\n *\n */\nexport function createBlockerConfig(config: {\n scope?: string | ReadonlyArray<string>;\n reason?: string;\n priority?: number;\n}): BlockerConfig {\n return {\n scope: config.scope,\n reason: config.reason,\n priority: config.priority,\n };\n}\n","import { RefObject, useEffect, useRef } from \"react\";\n\n/**\n * Keeps a ref updated with the latest config value.\n * Useful for accessing current config in callbacks without stale closures.\n *\n * @param config - Configuration object to track\n * @returns Mutable ref that always contains the latest config\n *\n */\nexport function useConfigRef<T>(config: T): RefObject<T> {\n const configRef = useRef(config);\n\n useEffect(() => {\n configRef.current = config;\n }, [config]);\n\n return configRef;\n}\n","import { useCallback, useEffect, useRef } from \"react\";\nimport { useUIBlockingStore } from \"../../store\";\nimport { createBlockerConfig } from \"../useBlocker\";\nimport { useConfigRef } from \"../useConfigRef\";\nimport { ConditionalBlockerConfig } from \"./useConditionalBlocker.types\";\n\n/**\n * Hook for conditional blocking based on a condition function.\n *\n * Periodically checks a condition and blocks/unblocks based on the result.\n * The condition is evaluated at the specified interval (default 1000ms).\n *\n * @param blockerId - Unique identifier for this blocker\n * @param config - Configuration including condition function and check interval\n *\n */\nexport const useConditionalBlocker = <TState = unknown>(\n blockerId: string,\n config: ConditionalBlockerConfig<TState>\n): void => {\n const { addBlocker, removeBlocker } = useUIBlockingStore((state) => ({\n addBlocker: state.addBlocker,\n removeBlocker: state.removeBlocker,\n }));\n const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);\n const isBlockedRef = useRef(false);\n const configRef = useConfigRef(config);\n\n const checkCondition = useCallback(() => {\n const currentConfig = configRef.current;\n const shouldBlock = currentConfig.condition(currentConfig.state);\n\n // No state change needed\n if (shouldBlock === isBlockedRef.current) {\n return;\n }\n\n if (shouldBlock) {\n addBlocker(blockerId, createBlockerConfig(currentConfig));\n } else {\n removeBlocker(blockerId);\n }\n isBlockedRef.current = shouldBlock;\n }, [blockerId, addBlocker, removeBlocker, configRef]);\n\n useEffect(() => {\n checkCondition();\n\n const interval = configRef.current.checkInterval ?? 1000;\n intervalRef.current = setInterval(checkCondition, interval);\n\n return (): void => {\n if (intervalRef.current) {\n clearInterval(intervalRef.current);\n intervalRef.current = null;\n }\n if (isBlockedRef.current) {\n removeBlocker(blockerId);\n isBlockedRef.current = false;\n }\n };\n // configRef is stable and doesn't need to be in dependencies\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [checkCondition, blockerId, removeBlocker]);\n};\n","import { useCallback, useState } from \"react\";\nimport { useBlocker } from \"../useBlocker\";\nimport {\n ConfirmableBlockerConfig,\n UseConfirmableBlockerReturn,\n} from \"./useConfirmableBlocker.types\";\n\n/**\n * Hook for creating a confirmable action with blocking UI\n *\n */\nexport const useConfirmableBlocker = (\n blockerId: string,\n config: ConfirmableBlockerConfig\n): UseConfirmableBlockerReturn => {\n const [isDialogOpen, setIsDialogOpen] = useState(false);\n const [isExecuting, setIsExecuting] = useState(false);\n\n useBlocker(\n blockerId,\n {\n ...config,\n reason: config.reason ?? config.confirmMessage,\n },\n isDialogOpen || isExecuting\n );\n\n const execute = useCallback(() => {\n setIsDialogOpen(true);\n }, []);\n\n const onConfirm = useCallback(async () => {\n setIsDialogOpen(false);\n setIsExecuting(true);\n\n try {\n await config.onConfirm();\n } catch (error) {\n console.error(\"[UIBlocking] Confirmable action error:\", error);\n throw error;\n } finally {\n setIsExecuting(false);\n }\n }, [config]);\n\n const onCancel = useCallback(() => {\n setIsDialogOpen(false);\n config.onCancel?.();\n }, [config]);\n\n return {\n execute,\n isDialogOpen,\n isExecuting,\n confirmConfig: {\n title: config.confirmTitle ?? \"Confirm Action\",\n message: config.confirmMessage,\n confirmText: config.confirmButtonText ?? \"Confirm\",\n cancelText: config.cancelButtonText ?? \"Cancel\",\n },\n onConfirm,\n onCancel,\n };\n};\n","import { useUIBlockingStore } from \"../../store\";\n\n/**\n * Hook to check if a scope is currently blocked\n *\n * Returns a boolean indicating whether the specified scope(s) are blocked.\n * Automatically re-renders when the blocking state changes.\n *\n * @param scope - Scope or array of scopes to check (default: \"global\")\n * @returns True if any of the specified scopes are blocked\n *\n */\nexport const useIsBlocked = (scope?: string | ReadonlyArray<string>): boolean => {\n return useUIBlockingStore((state) => state.isBlocked(scope));\n};\n","import type { BlockingSchedule } from \"./useScheduledBlocker.types\";\n\n/**\n * Maximum safe timeout value for setTimeout in JavaScript (~24.8 days).\n * Values larger than this will cause setTimeout to trigger immediately.\n */\nexport const MAX_TIMEOUT_MS = 2147483647;\n\n/**\n * Validates a date value and converts it to timestamp.\n *\n * @param date - Date value as string, Date object, or number\n * @returns Timestamp in milliseconds, or NaN if invalid\n */\nexport function parseDate(date: string | Date | number): number {\n return new Date(date).getTime();\n}\n\n/**\n * Validates if a timestamp is valid (not NaN).\n *\n * @param timestamp - Timestamp to validate\n * @returns True if valid, false otherwise\n */\nexport function isValidTimestamp(timestamp: number): boolean {\n return !Number.isNaN(timestamp);\n}\n\n/**\n * Calculates the end time based on schedule configuration.\n * Duration takes precedence over end time if both are provided.\n *\n * @param schedule - Blocking schedule configuration\n * @param startTime - Start time in milliseconds\n * @returns End time in milliseconds, or undefined if not specified\n */\nexport function calculateEndTime(\n schedule: BlockingSchedule,\n startTime: number\n): number | undefined {\n if (schedule.duration) {\n return startTime + schedule.duration;\n }\n\n if (schedule.end) {\n const endTime = parseDate(schedule.end);\n return isValidTimestamp(endTime) ? endTime : undefined;\n }\n\n return undefined;\n}\n\n/**\n * Validates if a delay is within the safe setTimeout range.\n *\n * @param delay - Delay in milliseconds\n * @returns True if delay is safe to use with setTimeout\n */\nexport function isSafeTimeout(delay: number): boolean {\n return delay > 0 && delay <= MAX_TIMEOUT_MS;\n}\n\n/**\n * Determines if the current time is within a blocking schedule.\n *\n * @param startTime - Schedule start time in milliseconds\n * @param endTime - Schedule end time in milliseconds (optional)\n * @param now - Current time in milliseconds\n * @returns True if currently in the blocking period\n */\nexport function isInBlockingPeriod(\n startTime: number,\n endTime: number | undefined,\n now: number\n): boolean {\n if (startTime > now) {\n return false; // Not started yet\n }\n\n if (!endTime) {\n return true; // No end time means block indefinitely\n }\n\n return endTime > now; // Check if end time hasn't passed\n}\n\n/**\n * Checks if a schedule is completely in the past.\n *\n * @param startTime - Schedule start time in milliseconds\n * @param endTime - Schedule end time in milliseconds (optional)\n * @param now - Current time in milliseconds\n * @returns True if the schedule is in the past\n */\nexport function isScheduleInPast(\n startTime: number,\n endTime: number | undefined,\n now: number\n): boolean {\n if (!endTime) {\n return false; // No end time means it can still be active\n }\n\n return endTime <= now && startTime <= now;\n}\n","import { useCallback, useEffect, useRef } from \"react\";\nimport { useUIBlockingStore } from \"../../store\";\nimport { createBlockerConfig } from \"../useBlocker\";\nimport { useConfigRef } from \"../useConfigRef\";\nimport { ScheduledBlockerConfig } from \"./useScheduledBlocker.types\";\nimport {\n MAX_TIMEOUT_MS,\n calculateEndTime,\n isInBlockingPeriod,\n isSafeTimeout,\n isScheduleInPast,\n isValidTimestamp,\n parseDate,\n} from \"./useScheduledBlocker.utils\";\n\n/**\n * Hook for scheduling UI blocking for a specific time period.\n *\n * Blocks UI during a scheduled maintenance window or time period.\n * Supports start/end times as Date objects, ISO strings, or timestamps.\n * If both duration and end are provided, duration takes precedence.\n *\n * @param blockerId - Unique identifier for this blocker\n * @param config - Configuration including schedule and callbacks\n *\n */\nexport const useScheduledBlocker = (blockerId: string, config: ScheduledBlockerConfig): void => {\n const { addBlocker, removeBlocker } = useUIBlockingStore((state) => ({\n addBlocker: state.addBlocker,\n removeBlocker: state.removeBlocker,\n }));\n const timeoutsRef = useRef<{\n start?: ReturnType<typeof setTimeout>;\n end?: ReturnType<typeof setTimeout>;\n }>({});\n const configRef = useConfigRef(config);\n\n const cleanup = useCallback(() => {\n if (timeoutsRef.current.start) {\n clearTimeout(timeoutsRef.current.start);\n timeoutsRef.current.start = undefined;\n }\n if (timeoutsRef.current.end) {\n clearTimeout(timeoutsRef.current.end);\n timeoutsRef.current.end = undefined;\n }\n }, []);\n\n useEffect(() => {\n const currentConfig = configRef.current;\n const startTime = parseDate(currentConfig.schedule.start);\n const now = Date.now();\n\n // Validate start time\n if (!isValidTimestamp(startTime)) {\n console.error(`[UIBlocking] Invalid start time for blocker \"${blockerId}\"`);\n return;\n }\n\n const scheduleEnd = (): void => {\n const endTime = calculateEndTime(currentConfig.schedule, startTime);\n if (!endTime) {\n return;\n }\n\n const remainingTime = endTime - Date.now();\n if (remainingTime > 0) {\n timeoutsRef.current.end = setTimeout(() => {\n configRef.current.onScheduleEnd?.();\n removeBlocker(blockerId);\n }, remainingTime);\n }\n };\n\n const startBlocking = (): void => {\n const cfg = configRef.current;\n addBlocker(blockerId, createBlockerConfig(cfg));\n cfg.onScheduleStart?.();\n scheduleEnd();\n };\n\n // If start time hasn't arrived yet\n if (startTime > now) {\n const delay = startTime - now;\n\n if (!isSafeTimeout(delay)) {\n console.warn(\n `[UIBlocking] Schedule delay exceeds maximum timeout (${MAX_TIMEOUT_MS.toString()}ms) for blocker \"${blockerId}\"`\n );\n return;\n }\n\n timeoutsRef.current.start = setTimeout(startBlocking, delay);\n }\n // If already in blocking period or should start immediately\n else {\n const endTime = calculateEndTime(currentConfig.schedule, startTime);\n\n if (isInBlockingPeriod(startTime, endTime, now)) {\n startBlocking();\n } else if (isScheduleInPast(startTime, endTime, now)) {\n console.warn(`[UIBlocking] Schedule is in the past for blocker \"${blockerId}\"`);\n }\n }\n\n return (): void => {\n cleanup();\n removeBlocker(blockerId);\n };\n // configRef is stable and doesn't need to be in dependencies\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [blockerId, addBlocker, removeBlocker, cleanup]);\n};\n","import { AnalyticsEventData } from \"./analyticsMiddleware.types\";\nimport { MiddlewareContext } from \"./middleware.types\";\n\nconst capitalizeFirst = (str: string): string => {\n return str.charAt(0).toUpperCase() + str.slice(1);\n};\n\nexport const buildEventData = (context: MiddlewareContext): AnalyticsEventData => {\n const eventData: AnalyticsEventData = {\n blocker_id: context.blockerId,\n };\n const { scope, reason, priority } = context.config ?? {};\n\n if (scope !== undefined) {\n eventData.scope = Array.isArray(scope) ? scope.join(\",\") : scope;\n }\n\n if (reason !== undefined) {\n eventData.reason = reason;\n }\n\n if (priority !== undefined) {\n eventData.priority = priority;\n }\n\n return eventData;\n};\n\nexport const trackGoogleAnalytics = (action: string, eventData: AnalyticsEventData): void => {\n if (window.gtag) {\n window.gtag(\"event\", `ui_blocking_${action}`, eventData);\n }\n};\n\nexport const trackMixpanel = (action: string, eventData: AnalyticsEventData): void => {\n if (window.mixpanel) {\n const eventName = `UI Blocking ${action.split(\"_\").map(capitalizeFirst).join(\" \")}`;\n\n window.mixpanel.track(eventName, eventData);\n }\n};\n\nexport const trackAmplitude = (action: string, eventData: AnalyticsEventData): void => {\n if (window.amplitude) {\n const eventName = `UI Blocking ${action.split(\"_\").map(capitalizeFirst).join(\" \")}`;\n\n window.amplitude.track(eventName, eventData);\n }\n};\n\nexport const trackCustom = (\n trackFn: (event: string, data: AnalyticsEventData) => void,\n action: string,\n eventData: AnalyticsEventData\n): void => {\n try {\n trackFn(`ui_blocking_${action}`, eventData);\n } catch {\n // Silently ignore errors in custom tracker\n }\n};\n","import { AnalyticsConfig, AnalyticsEventData } from \"./analyticsMiddleware.types\";\nimport {\n buildEventData,\n trackAmplitude,\n trackCustom,\n trackGoogleAnalytics,\n trackMixpanel,\n} from \"./analyticsMiddleware.utils\";\nimport { Middleware, MiddlewareContext } from \"./middleware.types\";\n\nconst trackEvent = (\n config: AnalyticsConfig,\n context: MiddlewareContext,\n eventData: AnalyticsEventData\n): void => {\n if (\"provider\" in config) {\n switch (config.provider) {\n case \"ga\":\n trackGoogleAnalytics(context.action, eventData);\n return;\n case \"mixpanel\":\n trackMixpanel(context.action, eventData);\n return;\n case \"amplitude\":\n trackAmplitude(context.action, eventData);\n return;\n }\n }\n\n if (\"track\" in config) {\n trackCustom(config.track, context.action, eventData);\n }\n};\n\nexport const createAnalyticsMiddleware = (config: AnalyticsConfig): Middleware => {\n return (context) => {\n const eventData = buildEventData(context);\n\n trackEvent(config, context, eventData);\n };\n};\n","import { MiddlewareBlockerConfig, MiddlewareContext } from \"./middleware.types\";\n\nexport const getActionEmoji = (action: string): string => {\n switch (action) {\n case \"add\":\n return \"➕\";\n case \"remove\":\n return \"➖\";\n case \"update\":\n return \"🔄\";\n case \"cancel\":\n return \"❌\";\n case \"timeout\":\n return \"⏱️\";\n default:\n return \"❓\";\n }\n};\n\nconst extractConfigDetails = (config?: MiddlewareBlockerConfig): Record<string, unknown> => {\n if (!config) {\n return {};\n }\n\n const { scope, reason, priority } = config;\n\n const details: Record<string, unknown> = {\n scope,\n reason,\n };\n\n if (priority !== undefined) {\n details.priority = priority;\n }\n\n return details;\n};\n\nexport const formatLogData = (context: MiddlewareContext): Record<string, unknown> => {\n const configDetails = extractConfigDetails(context.config);\n\n if (context.prevState) {\n return {\n config: configDetails,\n prevState: extractConfigDetails(context.prevState),\n };\n }\n\n return configDetails;\n};\n","import { formatLogData, getActionEmoji } from \"./loggerMiddleware.utils\";\nimport { Middleware } from \"./middleware.types\";\n\nconst LOG_PREFIX = \"[UIBlocking]\";\n\nexport const loggerMiddleware: Middleware = (context) => {\n const emoji = getActionEmoji(context.action);\n const logData = formatLogData(context);\n\n console.log(LOG_PREFIX, emoji, context.blockerId, logData);\n};\n","export const handleAddAction = (\n blockerId: string,\n timestamp: number,\n blockStartTimes: Map<string, number>\n): void => {\n blockStartTimes.set(blockerId, timestamp);\n};\n","import { Middleware, MiddlewareContext } from \"./middleware.types\";\nimport { PerformanceConfig } from \"./performanceMiddleware.types\";\nimport { handleAddAction } from \"./performanceMiddleware.utils\";\n\nconst DEFAULT_SLOW_BLOCK_THRESHOLD = 3000;\nconst ACTION_ADD = \"add\";\nconst ACTION_REMOVE = \"remove\";\n\nconst handleRemoveAction = (\n context: MiddlewareContext,\n blockStartTimes: Map<string, number>,\n slowBlockThreshold: number,\n onSlowBlock?: (blockerId: string, duration: number) => void\n): void => {\n const startTime = blockStartTimes.get(context.blockerId);\n\n if (startTime === undefined) {\n return;\n }\n\n const duration = context.timestamp - startTime;\n blockStartTimes.delete(context.blockerId);\n\n if (duration >= slowBlockThreshold) {\n console.warn(\n `[UIBlocking] Slow block detected: \"${context.blockerId}\" took ${duration.toString()}ms`\n );\n\n onSlowBlock?.(context.blockerId, duration);\n }\n};\n\nexport const createPerformanceMiddleware = (config: PerformanceConfig = {}): Middleware => {\n const { slowBlockThreshold = DEFAULT_SLOW_BLOCK_THRESHOLD, onSlowBlock } = config;\n const blockStartTimes = new Map<string, number>();\n\n return (context) => {\n if (context.action === ACTION_ADD) {\n handleAddAction(context.blockerId, context.timestamp, blockStartTimes);\n } else if (context.action === ACTION_REMOVE) {\n handleRemoveAction(context, blockStartTimes, slowBlockThreshold, onSlowBlock);\n }\n };\n};\n"]}
1
+ {"version":3,"sources":["../src/store/uiBlockingStore.constants.ts","../src/store/uiBlockingStore.utils.ts","../src/store/uiBlockingStore.actions.ts","../src/store/uiBlockingStore.config.ts","../src/store/uiBlockingStore.store.ts","../src/hooks/useAsyncAction/useAsyncAction.ts","../src/hooks/useBlocker/useBlocker.ts","../src/hooks/useBlocker/useBlocker.utils.ts","../src/hooks/useBlockingInfo/useBlockingInfo.ts","../src/hooks/useConfigRef.ts","../src/hooks/useConditionalBlocker/useConditionalBlocker.ts","../src/hooks/useConfirmableBlocker/useConfirmableBlocker.ts","../src/hooks/useIsBlocked/useIsBlocked.ts","../src/hooks/useScheduledBlocker/useScheduledBlocker.utils.ts","../src/hooks/useScheduledBlocker/useScheduledBlocker.ts","../src/middleware/analyticsMiddleware.utils.ts","../src/middleware/analyticsMiddleware.ts","../src/middleware/configureMiddleware.ts","../src/middleware/loggerMiddleware.utils.ts","../src/middleware/loggerMiddleware.ts","../src/middleware/performanceMiddleware.utils.ts","../src/middleware/performanceMiddleware.ts"],"names":["useStore","useEffect","useRef","useCallback"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Default values and constants for UI Blocking Store\n */\n\n/**\n * Default scope for blockers\n */\nexport const DEFAULT_SCOPE = \"global\" as const;\n\n/**\n * Default reason when none is provided\n */\nexport const DEFAULT_REASON = \"Unknown\" as const;\n\n/**\n * Default priority for blockers\n */\nexport const DEFAULT_PRIORITY = 0 as const;\n\n/**\n * Default priority for async actions\n */\nexport const ASYNC_ACTION_PRIORITY = 20 as const;\n\n/**\n * DevTools store name\n */\nexport const DEVTOOLS_NAME = \"UIBlocking\" as const;\n","import { StateCreator, StoreApi, StoreMutators, createStore, useStore } from \"zustand\";\nimport { useShallow } from \"zustand/shallow\";\n\n/**\n * Creates a Zustand store with automatic shallow comparison for all selectors\n *\n * This utility wraps the standard Zustand store creation and automatically applies\n * `useShallow` to all selectors, preventing unnecessary re-renders when selected\n * values haven't changed (shallow equality).\n *\n * @template StoreState - The type of the store state\n * @template TMutators - Array of middleware mutators (e.g., devtools, persist)\n *\n * @param storeCreator - The state creator function for Zustand\n * @returns Object containing the store hook and store API\n *\n * @see https://docs.pmnd.rs/zustand/guides/prevent-rerenders-with-use-shallow\n */\nexport function createShallowStore<\n StoreState,\n TMutators extends Array<[keyof StoreMutators<StoreState, StoreState>, unknown]> = [],\n>(\n storeCreator: StateCreator<StoreState, [], TMutators, StoreState>\n): {\n useStore: <T>(selector: (state: StoreState) => T) => T;\n useStoreApi: StoreApi<StoreState>;\n} {\n const storeApi: StoreApi<StoreState> = createStore<StoreState, TMutators>(storeCreator);\n\n const useScopedStore = <T>(selector: (state: StoreState) => T): T => {\n return useStore(storeApi, useShallow(selector));\n };\n\n return { useStore: useScopedStore, useStoreApi: storeApi };\n}\n\n/**\n * Normalize scope to array format\n *\n * @param scope - Single scope or array of scopes\n * @returns Array of scopes\n *\n * @internal\n */\nexport function normalizeScopeToArray(scope: string | ReadonlyArray<string>): Array<string> {\n if (typeof scope === \"string\") {\n return [scope];\n }\n return Array.from(scope);\n}\n","import { Middleware, MiddlewareContext } from \"../middleware\";\nimport { DEFAULT_PRIORITY, DEFAULT_REASON, DEFAULT_SCOPE } from \"./uiBlockingStore.constants\";\nimport { normalizeScopeToArray } from \"./uiBlockingStore.utils\";\nimport type {\n BlockerConfig,\n BlockerInfo,\n StoredBlocker,\n UIBlockingStore,\n} from \"./uiBlockingStore.types\";\nimport type { StateCreator } from \"zustand\";\n\n/**\n * UI Blocking Store Slice\n *\n * Implements the state and actions for UI blocking management.\n * This slice follows the Zustand slice pattern for better code organization.\n */\nexport const createUIBlockingActions: StateCreator<UIBlockingStore, [], [], UIBlockingStore> = (\n set,\n get\n) => ({\n // State\n activeBlockers: new Map(),\n middlewares: new Map(),\n\n registerMiddleware: (name: string, middleware: Middleware) => {\n set((state) => {\n const newMiddlewares = new Map(state.middlewares);\n newMiddlewares.set(name, middleware);\n return { middlewares: newMiddlewares };\n });\n console.log(`[UIBlocking] Registered middleware: ${name}`);\n },\n\n unregisterMiddleware: (name: string) => {\n set((state) => {\n const newMiddlewares = new Map(state.middlewares);\n newMiddlewares.delete(name);\n return { middlewares: newMiddlewares };\n });\n console.log(`[UIBlocking] Unregistered middleware: ${name}`);\n },\n\n runMiddlewares: async (context: MiddlewareContext) => {\n const { middlewares } = get();\n\n for (const [name, middleware] of middlewares) {\n try {\n await middleware(context);\n } catch (error) {\n console.error(`[UIBlocking] Middleware \"${name}\" error:`, error);\n }\n }\n },\n\n // Actions\n /**\n * Add a blocker to the store\n *\n * @param id - Unique blocker identifier\n * @param config - Optional blocker configuration\n *\n */\n addBlocker: (id: string, config: BlockerConfig = {}): void => {\n set((state) => {\n const newBlockers = new Map(state.activeBlockers);\n const storedBlocker: StoredBlocker = {\n scope: config.scope ?? DEFAULT_SCOPE,\n reason: config.reason ?? DEFAULT_REASON,\n priority: config.priority ?? DEFAULT_PRIORITY,\n timestamp: config.timestamp ?? Date.now(),\n };\n newBlockers.set(id, storedBlocker);\n\n return { activeBlockers: newBlockers };\n });\n\n void get().runMiddlewares({\n action: \"add\",\n blockerId: id,\n config: {\n scope: config.scope,\n reason: config.reason,\n priority: config.priority,\n },\n timestamp: Date.now(),\n });\n },\n\n /**\n * Remove a blocker from the store\n *\n * @param id - Blocker identifier to remove\n *\n */\n removeBlocker: (id: string): void => {\n const prevBlocker = get().activeBlockers.get(id);\n\n set((state) => {\n const newBlockers = new Map(state.activeBlockers);\n newBlockers.delete(id);\n\n return { activeBlockers: newBlockers };\n });\n\n if (prevBlocker) {\n void get().runMiddlewares({\n action: \"remove\",\n blockerId: id,\n config: prevBlocker,\n timestamp: Date.now(),\n prevState: prevBlocker,\n });\n }\n },\n\n /**\n * Check if a scope is currently blocked\n *\n * @param scope - Scope or array of scopes to check (default: \"global\")\n * @returns True if any of the scopes are blocked\n *\n */\n isBlocked: (scope: string | ReadonlyArray<string> = DEFAULT_SCOPE): boolean => {\n const { activeBlockers } = get();\n const scopes = normalizeScopeToArray(scope);\n\n for (const [, blocker] of activeBlockers) {\n // Global blocking blocks everything\n if (blocker.scope === DEFAULT_SCOPE) {\n return true;\n }\n\n // Check scope intersection\n const blockerScopes = normalizeScopeToArray(blocker.scope);\n\n if (scopes.some((s) => blockerScopes.includes(s))) {\n return true;\n }\n }\n\n return false;\n },\n\n /**\n * Get detailed blocking information for a specific scope\n *\n * @param scope - Scope to get blocking information for\n * @returns Array of blockers affecting the scope, sorted by priority (highest first)\n *\n */\n getBlockingInfo: (scope: string): ReadonlyArray<BlockerInfo> => {\n const { activeBlockers } = get();\n const blockers: Array<BlockerInfo> = [];\n\n for (const [id, blocker] of activeBlockers) {\n const blockerScopes = normalizeScopeToArray(blocker.scope);\n\n if (blocker.scope === DEFAULT_SCOPE || blockerScopes.includes(scope)) {\n blockers.push({ id, ...blocker });\n }\n }\n\n return blockers.sort((a, b) => b.priority - a.priority);\n },\n\n /**\n * Clear all blockers from the store\n */\n clearAllBlockers: (): void => {\n set({ activeBlockers: new Map() });\n },\n\n /**\n * Clear all blockers for a specific scope\n *\n * @param scope - Scope to clear blockers for\n *\n */\n clearBlockersForScope: (scope: string): void => {\n set((state) => {\n const newBlockers = new Map();\n\n for (const [id, blocker] of state.activeBlockers) {\n const blockerScopes = normalizeScopeToArray(blocker.scope);\n\n if (!blockerScopes.includes(scope)) {\n newBlockers.set(id, blocker);\n }\n }\n\n return { activeBlockers: newBlockers };\n });\n },\n});\n","import { DEVTOOLS_NAME } from \"./uiBlockingStore.constants\";\nimport type { DevtoolsOptions } from \"zustand/middleware\";\n\n/**\n * DevTools configuration for UI Blocking Store\n *\n * Enables Redux DevTools integration only in development mode\n * for better debugging experience without production overhead.\n */\nexport const devtoolsConfig: DevtoolsOptions = {\n name: DEVTOOLS_NAME,\n enabled: process.env.NODE_ENV !== \"production\",\n};\n","import { devtools } from \"zustand/middleware\";\nimport { createUIBlockingActions } from \"./uiBlockingStore.actions\";\nimport { devtoolsConfig } from \"./uiBlockingStore.config\";\nimport { createShallowStore } from \"./uiBlockingStore.utils\";\nimport type { UIBlockingStore } from \"./uiBlockingStore.types\";\n\n/**\n * UI Blocking Store\n *\n * Global Zustand store for managing UI blocking state across the application.\n *\n * Features:\n * - Priority-based blocking system\n * - Scope-based blocking (global, specific areas, or multiple scopes)\n * - Automatic cleanup on unmount (when using hooks)\n * - DevTools integration for debugging\n * - Automatic shallow comparison for selectors\n *\n */\nconst { useStore: useUIBlockingStore, useStoreApi: uiBlockingStoreApi } = createShallowStore<\n UIBlockingStore,\n [[\"zustand/devtools\", never]]\n>(devtools(createUIBlockingActions, devtoolsConfig));\n\nexport { useUIBlockingStore, uiBlockingStoreApi };\n","import { useCallback } from \"react\";\nimport { ASYNC_ACTION_PRIORITY, useUIBlockingStore } from \"../../store\";\n\n/**\n * Hook to wrap async functions with automatic blocking/unblocking\n *\n * Creates a wrapper function that automatically adds a blocker before executing\n * the async function and removes it after completion (success or failure).\n *\n * @template T - The return type of the async function\n * @param actionId - Unique identifier for the action (used in blocker ID and reason)\n * @param scope - Scope(s) to block during execution (default: \"global\")\n * @returns Function that wraps async functions with blocking behavior\n *\n */\nexport const useAsyncAction = <T = unknown>(\n actionId: string,\n scope?: string | ReadonlyArray<string>\n): ((asyncFn: () => Promise<T>) => Promise<T>) => {\n const { addBlocker, removeBlocker } = useUIBlockingStore((state) => ({\n addBlocker: state.addBlocker,\n removeBlocker: state.removeBlocker,\n }));\n\n const executeWithBlocking = useCallback(\n async (asyncFn: () => Promise<T>): Promise<T> => {\n const blockerId = `${actionId}-${Date.now().toString()}`;\n\n try {\n addBlocker(blockerId, {\n scope,\n reason: `Executing ${actionId}`,\n priority: ASYNC_ACTION_PRIORITY,\n });\n\n return await asyncFn();\n } finally {\n removeBlocker(blockerId);\n }\n },\n [actionId, scope, addBlocker, removeBlocker]\n );\n\n return executeWithBlocking;\n};\n","import { useEffect } from \"react\";\nimport { type BlockerConfig, useUIBlockingStore } from \"../../store\";\n\n/**\n * Hook to automatically add and remove a blocker based on component lifecycle\n *\n * Automatically adds a blocker when the component mounts (or when activated)\n * and removes it when the component unmounts (or when deactivated).\n *\n * @param blockerId - Unique identifier for the blocker\n * @param config - Blocker configuration (scope, reason, priority)\n * @param isActive - Whether the blocker is currently active (default: true)\n *\n */\nexport const useBlocker = (blockerId: string, config: BlockerConfig, isActive = true): void => {\n const { addBlocker, removeBlocker } = useUIBlockingStore((state) => ({\n addBlocker: state.addBlocker,\n removeBlocker: state.removeBlocker,\n }));\n\n useEffect(() => {\n if (!isActive || !blockerId) {\n return;\n }\n\n addBlocker(blockerId, config);\n\n return () => {\n removeBlocker(blockerId);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [blockerId, isActive, addBlocker, removeBlocker]);\n};\n","import { BlockerConfig } from \"../../store\";\n\n/**\n * Creates a blocker configuration object from partial config.\n * Filters out undefined values to create a clean BlockerConfig.\n *\n * @param config - Partial blocker configuration\n * @returns Complete BlockerConfig object\n *\n */\nexport function createBlockerConfig(config: {\n scope?: string | ReadonlyArray<string>;\n reason?: string;\n priority?: number;\n}): BlockerConfig {\n return {\n scope: config.scope,\n reason: config.reason,\n priority: config.priority,\n };\n}\n","import { useMemo } from \"react\";\nimport { useStore } from \"zustand\";\nimport { DEFAULT_SCOPE } from \"../../store\";\nimport { type BlockerInfo, uiBlockingStoreApi } from \"../../store\";\n\n/**\n * Hook to get detailed blocking information for a scope\n *\n * Returns an array of blocker information objects for the specified scope,\n * sorted by priority (highest first). Automatically re-renders when blockers change.\n *\n * Uses a stable reference - only re-renders when the actual blocker list changes,\n * not on every store update.\n *\n * @param scope - Scope to get blocking information for (default: \"global\")\n * @returns Array of blocker information objects, sorted by priority\n *\n * ```\n */\nexport const useBlockingInfo = (scope: string = DEFAULT_SCOPE): ReadonlyArray<BlockerInfo> => {\n // Subscribe to the activeBlockers Map to detect changes\n const activeBlockers = useStore(uiBlockingStoreApi, (state) => state.activeBlockers);\n\n // Recompute blockers only when activeBlockers or scope changes\n return useMemo(() => {\n return uiBlockingStoreApi.getState().getBlockingInfo(scope);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [activeBlockers, scope]);\n};\n","import { RefObject, useEffect, useRef } from \"react\";\n\n/**\n * Keeps a ref updated with the latest config value.\n * Useful for accessing current config in callbacks without stale closures.\n *\n * @param config - Configuration object to track\n * @returns Mutable ref that always contains the latest config\n *\n */\nexport function useConfigRef<T>(config: T): RefObject<T> {\n const configRef = useRef(config);\n\n useEffect(() => {\n configRef.current = config;\n }, [config]);\n\n return configRef;\n}\n","import { useCallback, useEffect, useRef } from \"react\";\nimport { useUIBlockingStore } from \"../../store\";\nimport { createBlockerConfig } from \"../useBlocker\";\nimport { useConfigRef } from \"../useConfigRef\";\nimport { ConditionalBlockerConfig } from \"./useConditionalBlocker.types\";\n\n/**\n * Hook for conditional blocking based on a condition function.\n *\n * Periodically checks a condition and blocks/unblocks based on the result.\n * The condition is evaluated at the specified interval (default 1000ms).\n *\n * @param blockerId - Unique identifier for this blocker\n * @param config - Configuration including condition function and check interval\n *\n */\nexport const useConditionalBlocker = <TState = unknown>(\n blockerId: string,\n config: ConditionalBlockerConfig<TState>\n): void => {\n const { addBlocker, removeBlocker } = useUIBlockingStore((state) => ({\n addBlocker: state.addBlocker,\n removeBlocker: state.removeBlocker,\n }));\n const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);\n const isBlockedRef = useRef(false);\n const configRef = useConfigRef(config);\n\n const checkCondition = useCallback(() => {\n const currentConfig = configRef.current;\n const shouldBlock = currentConfig.condition(currentConfig.state);\n\n // No state change needed\n if (shouldBlock === isBlockedRef.current) {\n return;\n }\n\n if (shouldBlock) {\n addBlocker(blockerId, createBlockerConfig(currentConfig));\n } else {\n removeBlocker(blockerId);\n }\n isBlockedRef.current = shouldBlock;\n }, [blockerId, addBlocker, removeBlocker, configRef]);\n\n useEffect(() => {\n checkCondition();\n\n const interval = configRef.current.checkInterval ?? 1000;\n intervalRef.current = setInterval(checkCondition, interval);\n\n return (): void => {\n if (intervalRef.current) {\n clearInterval(intervalRef.current);\n intervalRef.current = null;\n }\n if (isBlockedRef.current) {\n removeBlocker(blockerId);\n isBlockedRef.current = false;\n }\n };\n // configRef is stable and doesn't need to be in dependencies\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [checkCondition, blockerId, removeBlocker]);\n};\n","import { useCallback, useState } from \"react\";\nimport { useBlocker } from \"../useBlocker\";\nimport {\n ConfirmableBlockerConfig,\n UseConfirmableBlockerReturn,\n} from \"./useConfirmableBlocker.types\";\n\n/**\n * Hook for creating a confirmable action with blocking UI\n *\n */\nexport const useConfirmableBlocker = (\n blockerId: string,\n config: ConfirmableBlockerConfig\n): UseConfirmableBlockerReturn => {\n const [isDialogOpen, setIsDialogOpen] = useState(false);\n const [isExecuting, setIsExecuting] = useState(false);\n\n useBlocker(\n blockerId,\n {\n ...config,\n reason: config.reason ?? config.confirmMessage,\n },\n isDialogOpen || isExecuting\n );\n\n const execute = useCallback(() => {\n setIsDialogOpen(true);\n }, []);\n\n const onConfirm = useCallback(async () => {\n setIsDialogOpen(false);\n setIsExecuting(true);\n\n try {\n await config.onConfirm();\n } catch (error) {\n console.error(\"[UIBlocking] Confirmable action error:\", error);\n throw error;\n } finally {\n setIsExecuting(false);\n }\n }, [config]);\n\n const onCancel = useCallback(() => {\n setIsDialogOpen(false);\n config.onCancel?.();\n }, [config]);\n\n return {\n execute,\n isDialogOpen,\n isExecuting,\n confirmConfig: {\n title: config.confirmTitle ?? \"Confirm Action\",\n message: config.confirmMessage,\n confirmText: config.confirmButtonText ?? \"Confirm\",\n cancelText: config.cancelButtonText ?? \"Cancel\",\n },\n onConfirm,\n onCancel,\n };\n};\n","import { useUIBlockingStore } from \"../../store\";\n\n/**\n * Hook to check if a scope is currently blocked\n *\n * Returns a boolean indicating whether the specified scope(s) are blocked.\n * Automatically re-renders when the blocking state changes.\n *\n * @param scope - Scope or array of scopes to check (default: \"global\")\n * @returns True if any of the specified scopes are blocked\n *\n */\nexport const useIsBlocked = (scope?: string | ReadonlyArray<string>): boolean => {\n return useUIBlockingStore((state) => state.isBlocked(scope));\n};\n","import type { BlockingSchedule } from \"./useScheduledBlocker.types\";\n\n/**\n * Maximum safe timeout value for setTimeout in JavaScript (~24.8 days).\n * Values larger than this will cause setTimeout to trigger immediately.\n */\nexport const MAX_TIMEOUT_MS = 2147483647;\n\n/**\n * Validates a date value and converts it to timestamp.\n *\n * @param date - Date value as string, Date object, or number\n * @returns Timestamp in milliseconds, or NaN if invalid\n */\nexport function parseDate(date: string | Date | number): number {\n return new Date(date).getTime();\n}\n\n/**\n * Validates if a timestamp is valid (not NaN).\n *\n * @param timestamp - Timestamp to validate\n * @returns True if valid, false otherwise\n */\nexport function isValidTimestamp(timestamp: number): boolean {\n return !Number.isNaN(timestamp);\n}\n\n/**\n * Calculates the end time based on schedule configuration.\n * Duration takes precedence over end time if both are provided.\n *\n * @param schedule - Blocking schedule configuration\n * @param startTime - Start time in milliseconds\n * @returns End time in milliseconds, or undefined if not specified\n */\nexport function calculateEndTime(\n schedule: BlockingSchedule,\n startTime: number\n): number | undefined {\n if (schedule.duration) {\n return startTime + schedule.duration;\n }\n\n if (schedule.end) {\n const endTime = parseDate(schedule.end);\n return isValidTimestamp(endTime) ? endTime : undefined;\n }\n\n return undefined;\n}\n\n/**\n * Validates if a delay is within the safe setTimeout range.\n *\n * @param delay - Delay in milliseconds\n * @returns True if delay is safe to use with setTimeout\n */\nexport function isSafeTimeout(delay: number): boolean {\n return delay > 0 && delay <= MAX_TIMEOUT_MS;\n}\n\n/**\n * Determines if the current time is within a blocking schedule.\n *\n * @param startTime - Schedule start time in milliseconds\n * @param endTime - Schedule end time in milliseconds (optional)\n * @param now - Current time in milliseconds\n * @returns True if currently in the blocking period\n */\nexport function isInBlockingPeriod(\n startTime: number,\n endTime: number | undefined,\n now: number\n): boolean {\n if (startTime > now) {\n return false; // Not started yet\n }\n\n if (!endTime) {\n return true; // No end time means block indefinitely\n }\n\n return endTime > now; // Check if end time hasn't passed\n}\n\n/**\n * Checks if a schedule is completely in the past.\n *\n * @param startTime - Schedule start time in milliseconds\n * @param endTime - Schedule end time in milliseconds (optional)\n * @param now - Current time in milliseconds\n * @returns True if the schedule is in the past\n */\nexport function isScheduleInPast(\n startTime: number,\n endTime: number | undefined,\n now: number\n): boolean {\n if (!endTime) {\n return false; // No end time means it can still be active\n }\n\n return endTime <= now && startTime <= now;\n}\n","import { useCallback, useEffect, useRef } from \"react\";\nimport { useUIBlockingStore } from \"../../store\";\nimport { createBlockerConfig } from \"../useBlocker\";\nimport { useConfigRef } from \"../useConfigRef\";\nimport { ScheduledBlockerConfig } from \"./useScheduledBlocker.types\";\nimport {\n MAX_TIMEOUT_MS,\n calculateEndTime,\n isInBlockingPeriod,\n isSafeTimeout,\n isScheduleInPast,\n isValidTimestamp,\n parseDate,\n} from \"./useScheduledBlocker.utils\";\n\n/**\n * Hook for scheduling UI blocking for a specific time period.\n *\n * Blocks UI during a scheduled maintenance window or time period.\n * Supports start/end times as Date objects, ISO strings, or timestamps.\n * If both duration and end are provided, duration takes precedence.\n *\n * @param blockerId - Unique identifier for this blocker\n * @param config - Configuration including schedule and callbacks\n *\n */\nexport const useScheduledBlocker = (blockerId: string, config: ScheduledBlockerConfig): void => {\n const { addBlocker, removeBlocker } = useUIBlockingStore((state) => ({\n addBlocker: state.addBlocker,\n removeBlocker: state.removeBlocker,\n }));\n const timeoutsRef = useRef<{\n start?: ReturnType<typeof setTimeout>;\n end?: ReturnType<typeof setTimeout>;\n }>({});\n const configRef = useConfigRef(config);\n\n const cleanup = useCallback(() => {\n if (timeoutsRef.current.start) {\n clearTimeout(timeoutsRef.current.start);\n timeoutsRef.current.start = undefined;\n }\n if (timeoutsRef.current.end) {\n clearTimeout(timeoutsRef.current.end);\n timeoutsRef.current.end = undefined;\n }\n }, []);\n\n useEffect(() => {\n const currentConfig = configRef.current;\n const startTime = parseDate(currentConfig.schedule.start);\n const now = Date.now();\n\n // Validate start time\n if (!isValidTimestamp(startTime)) {\n console.error(`[UIBlocking] Invalid start time for blocker \"${blockerId}\"`);\n return;\n }\n\n const scheduleEnd = (): void => {\n const endTime = calculateEndTime(currentConfig.schedule, startTime);\n if (!endTime) {\n return;\n }\n\n const remainingTime = endTime - Date.now();\n if (remainingTime > 0) {\n timeoutsRef.current.end = setTimeout(() => {\n configRef.current.onScheduleEnd?.();\n removeBlocker(blockerId);\n }, remainingTime);\n }\n };\n\n const startBlocking = (): void => {\n const cfg = configRef.current;\n addBlocker(blockerId, createBlockerConfig(cfg));\n cfg.onScheduleStart?.();\n scheduleEnd();\n };\n\n // If start time hasn't arrived yet\n if (startTime > now) {\n const delay = startTime - now;\n\n if (!isSafeTimeout(delay)) {\n console.warn(\n `[UIBlocking] Schedule delay exceeds maximum timeout (${MAX_TIMEOUT_MS.toString()}ms) for blocker \"${blockerId}\"`\n );\n return;\n }\n\n timeoutsRef.current.start = setTimeout(startBlocking, delay);\n }\n // If already in blocking period or should start immediately\n else {\n const endTime = calculateEndTime(currentConfig.schedule, startTime);\n\n if (isInBlockingPeriod(startTime, endTime, now)) {\n startBlocking();\n } else if (isScheduleInPast(startTime, endTime, now)) {\n console.warn(`[UIBlocking] Schedule is in the past for blocker \"${blockerId}\"`);\n }\n }\n\n return (): void => {\n cleanup();\n removeBlocker(blockerId);\n };\n // configRef is stable and doesn't need to be in dependencies\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [blockerId, addBlocker, removeBlocker, cleanup]);\n};\n","import { AnalyticsEventData } from \"./analyticsMiddleware.types\";\nimport { MiddlewareContext } from \"./middleware.types\";\n\nconst capitalizeFirst = (str: string): string => {\n return str.charAt(0).toUpperCase() + str.slice(1);\n};\n\nexport const buildEventData = (context: MiddlewareContext): AnalyticsEventData => {\n const eventData: AnalyticsEventData = {\n blocker_id: context.blockerId,\n };\n const { scope, reason, priority } = context.config ?? {};\n\n if (scope !== undefined) {\n eventData.scope = Array.isArray(scope) ? scope.join(\",\") : scope;\n }\n\n if (reason !== undefined) {\n eventData.reason = reason;\n }\n\n if (priority !== undefined) {\n eventData.priority = priority;\n }\n\n return eventData;\n};\n\nexport const trackGoogleAnalytics = (action: string, eventData: AnalyticsEventData): void => {\n if (window.gtag) {\n window.gtag(\"event\", `ui_blocking_${action}`, eventData);\n }\n};\n\nexport const trackMixpanel = (action: string, eventData: AnalyticsEventData): void => {\n if (window.mixpanel) {\n const eventName = `UI Blocking ${action.split(\"_\").map(capitalizeFirst).join(\" \")}`;\n\n window.mixpanel.track(eventName, eventData);\n }\n};\n\nexport const trackAmplitude = (action: string, eventData: AnalyticsEventData): void => {\n if (window.amplitude) {\n const eventName = `UI Blocking ${action.split(\"_\").map(capitalizeFirst).join(\" \")}`;\n\n window.amplitude.track(eventName, eventData);\n }\n};\n\nexport const trackCustom = (\n trackFn: (event: string, data: AnalyticsEventData) => void,\n action: string,\n eventData: AnalyticsEventData\n): void => {\n try {\n trackFn(`ui_blocking_${action}`, eventData);\n } catch {\n // Silently ignore errors in custom tracker\n }\n};\n","import { AnalyticsConfig, AnalyticsEventData } from \"./analyticsMiddleware.types\";\nimport {\n buildEventData,\n trackAmplitude,\n trackCustom,\n trackGoogleAnalytics,\n trackMixpanel,\n} from \"./analyticsMiddleware.utils\";\nimport { Middleware, MiddlewareContext } from \"./middleware.types\";\n\nconst trackEvent = (\n config: AnalyticsConfig,\n context: MiddlewareContext,\n eventData: AnalyticsEventData\n): void => {\n if (\"provider\" in config) {\n switch (config.provider) {\n case \"ga\":\n trackGoogleAnalytics(context.action, eventData);\n return;\n case \"mixpanel\":\n trackMixpanel(context.action, eventData);\n return;\n case \"amplitude\":\n trackAmplitude(context.action, eventData);\n return;\n }\n }\n\n if (\"track\" in config) {\n trackCustom(config.track, context.action, eventData);\n }\n};\n\nexport const createAnalyticsMiddleware = (config: AnalyticsConfig): Middleware => {\n return (context) => {\n const eventData = buildEventData(context);\n\n trackEvent(config, context, eventData);\n };\n};\n","import { uiBlockingStoreApi } from \"../store/uiBlockingStore.store\";\nimport type { Middleware } from \"./middleware.types\";\n\n/**\n * Configure middleware for the UI blocking store\n *\n * This is a convenience function that registers multiple middleware at once.\n * Each middleware will be registered with an auto-generated name based on its index.\n *\n * @param middlewares - Array of middleware functions to register\n *\n */\nexport function configureMiddleware(middlewares: ReadonlyArray<Middleware>): void {\n const store = uiBlockingStoreApi.getState();\n\n middlewares.forEach((middleware, index) => {\n // Generate a unique name for each middleware\n const name = `middleware-${index.toString()}`;\n store.registerMiddleware(name, middleware);\n });\n}\n","import { MiddlewareBlockerConfig, MiddlewareContext } from \"./middleware.types\";\n\nexport const getActionEmoji = (action: string): string => {\n switch (action) {\n case \"add\":\n return \"➕\";\n case \"remove\":\n return \"➖\";\n case \"update\":\n return \"🔄\";\n case \"cancel\":\n return \"❌\";\n case \"timeout\":\n return \"⏱️\";\n default:\n return \"❓\";\n }\n};\n\nconst extractConfigDetails = (config?: MiddlewareBlockerConfig): Record<string, unknown> => {\n if (!config) {\n return {};\n }\n\n const { scope, reason, priority } = config;\n\n const details: Record<string, unknown> = {\n scope,\n reason,\n };\n\n if (priority !== undefined) {\n details.priority = priority;\n }\n\n return details;\n};\n\nexport const formatLogData = (context: MiddlewareContext): Record<string, unknown> => {\n const configDetails = extractConfigDetails(context.config);\n\n if (context.prevState) {\n return {\n config: configDetails,\n prevState: extractConfigDetails(context.prevState),\n };\n }\n\n return configDetails;\n};\n","import { formatLogData, getActionEmoji } from \"./loggerMiddleware.utils\";\nimport { Middleware } from \"./middleware.types\";\n\nconst LOG_PREFIX = \"[UIBlocking]\";\n\nexport const loggerMiddleware: Middleware = (context) => {\n const emoji = getActionEmoji(context.action);\n const logData = formatLogData(context);\n\n console.log(LOG_PREFIX, emoji, context.blockerId, logData);\n};\n","export const handleAddAction = (\n blockerId: string,\n timestamp: number,\n blockStartTimes: Map<string, number>\n): void => {\n blockStartTimes.set(blockerId, timestamp);\n};\n","import { Middleware, MiddlewareContext } from \"./middleware.types\";\nimport { PerformanceConfig } from \"./performanceMiddleware.types\";\nimport { handleAddAction } from \"./performanceMiddleware.utils\";\n\nconst DEFAULT_SLOW_BLOCK_THRESHOLD = 3000;\nconst ACTION_ADD = \"add\";\nconst ACTION_REMOVE = \"remove\";\n\nconst handleRemoveAction = (\n context: MiddlewareContext,\n blockStartTimes: Map<string, number>,\n slowBlockThreshold: number,\n onSlowBlock?: (blockerId: string, duration: number) => void\n): void => {\n const startTime = blockStartTimes.get(context.blockerId);\n\n if (startTime === undefined) {\n return;\n }\n\n const duration = context.timestamp - startTime;\n blockStartTimes.delete(context.blockerId);\n\n if (duration >= slowBlockThreshold) {\n console.warn(\n `[UIBlocking] Slow block detected: \"${context.blockerId}\" took ${duration.toString()}ms`\n );\n\n onSlowBlock?.(context.blockerId, duration);\n }\n};\n\nexport const createPerformanceMiddleware = (config: PerformanceConfig = {}): Middleware => {\n const { slowBlockThreshold = DEFAULT_SLOW_BLOCK_THRESHOLD, onSlowBlock } = config;\n const blockStartTimes = new Map<string, number>();\n\n return (context) => {\n if (context.action === ACTION_ADD) {\n handleAddAction(context.blockerId, context.timestamp, blockStartTimes);\n } else if (context.action === ACTION_REMOVE) {\n handleRemoveAction(context, blockStartTimes, slowBlockThreshold, onSlowBlock);\n }\n };\n};\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@okyrychenko-dev/react-action-guard",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
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",