@okyrychenko-dev/react-action-guard 1.0.5 โ†’ 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/store/uiBlockingStore.constants.ts","../src/store/uiBlockingStore.utils.ts","../src/store/uiBlockingStore.actions.ts","../src/context/UIBlockingContext.tsx","../src/store/uiBlockingStore.config.ts","../src/store/uiBlockingStore.store.ts","../src/context/useResolvedStore.ts","../src/store/blockerId.utils.ts","../src/hooks/useBlockerIdAllocator/useBlockerIdAllocator.ts","../src/hooks/useAsyncAction/useAsyncAction.ts","../src/hooks/useBlocker/useBlocker.utils.ts","../src/hooks/useBlocker/useBlocker.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","../src/createTypedHooks.ts","../src/index.ts"],"names":["createStoreProvider","jsx","createShallowStore","devtools","useStore","useShallow","useCallback","allocateBlockerId","shallow","useRef","useMemo","useEffect","useState","scheduleEnd"],"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/react/shallow\";\nimport { ShallowStoreBindings } from \"./uiBlockingStore.types\";\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 * Supports two usage patterns:\n * - `useStore()` - Returns the entire store state\n * - `useStore(selector)` - Returns the result of the selector function\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): ShallowStoreBindings<StoreState> {\n const storeApi: StoreApi<StoreState> = createStore<StoreState, TMutators>(storeCreator);\n\n function useScopedStore(): StoreState;\n function useScopedStore<T>(selector: (state: StoreState) => T): T;\n function useScopedStore<T>(selector?: (state: StoreState) => T): T | StoreState {\n const actualSelector = (state: StoreState): T | StoreState =>\n selector ? selector(state) : state;\n\n return useStore(storeApi, useShallow(actualSelector));\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 { BlockingAction, Middleware, MiddlewareContext } from \"../middleware\";\nimport { DEFAULT_PRIORITY, DEFAULT_REASON, DEFAULT_SCOPE } from \"./uiBlockingStore.constants\";\nimport { normalizeScopeToArray } from \"./uiBlockingStore.utils\";\nimport type { StateCreator } from \"zustand\";\nimport type {\n BlockerConfig,\n BlockerInfo,\n StoredBlocker,\n UIBlockingStore,\n} from \"./uiBlockingStore.types\";\n\n/**\n * Normalize priority value to ensure it's non-negative\n */\nfunction normalizePriority(priority?: number, fallback: number = DEFAULT_PRIORITY): number {\n return priority !== undefined ? Math.max(0, priority) : fallback;\n}\n\n/**\n * Create middleware context object\n */\nfunction createMiddlewareContext(\n action: BlockingAction,\n blockerId: string,\n config?: Partial<BlockerConfig>,\n prevState?: Partial<BlockerConfig>\n): MiddlewareContext {\n return {\n action,\n blockerId,\n config,\n timestamp: Date.now(),\n ...(prevState && { prevState }),\n };\n}\n\nfunction toPublicBlockerConfig(blocker: StoredBlocker): BlockerConfig {\n return {\n scope: blocker.scope,\n reason: blocker.reason,\n priority: blocker.priority,\n timestamp: blocker.timestamp,\n timeout: blocker.timeout,\n onTimeout: blocker.onTimeout,\n };\n}\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 },\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 },\n\n runMiddlewares: async (context: MiddlewareContext) => {\n const { middlewares } = get();\n\n for (const [, middleware] of middlewares) {\n try {\n await middleware(context);\n } catch {\n // Swallow middleware failures so observability hooks never break core blocker flow.\n }\n }\n },\n\n // Actions\n /**\n * Adds a new blocker or overwrites an existing one.\n *\n * If a blocker with the same ID already exists, it will be replaced and any\n * existing timeout will be cleared. The blocker is active immediately after\n * being added. Triggers middleware with 'add' action.\n *\n * @param id - Unique identifier for the blocker. Must be unique within the store.\n * @param config - Blocker configuration. All fields are optional with defaults applied.\n *\n * @example\n * Basic usage\n * ```ts\n * store.getState().addBlocker('save-operation', {\n * scope: 'form',\n * reason: 'Saving data...',\n * priority: 70\n * });\n * ```\n *\n * @example\n * With timeout\n * ```ts\n * store.getState().addBlocker('api-call', {\n * scope: 'global',\n * reason: 'Loading...',\n * timeout: 30000, // Auto-remove after 30 seconds\n * onTimeout: (id) => console.warn(`${id} timed out`)\n * });\n * ```\n *\n * @see {@link removeBlocker} to remove a blocker\n * @see {@link updateBlocker} to update an existing blocker\n */\n addBlocker: (id: string, config: BlockerConfig = {}): void => {\n // Clear existing timeout if blocker is being overwritten\n const existingBlocker = get().activeBlockers.get(id);\n if (existingBlocker?.timeoutId) {\n clearTimeout(existingBlocker.timeoutId);\n }\n\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n\n // Set up timeout if specified\n if (config.timeout && config.timeout > 0) {\n timeoutId = setTimeout(() => {\n // Check if blocker still exists\n const blocker = get().activeBlockers.get(id);\n\n if (blocker) {\n // Call onTimeout callback before removing\n blocker.onTimeout?.(id);\n\n // Run timeout middleware\n void get().runMiddlewares(\n createMiddlewareContext(\"timeout\", id, {\n scope: blocker.scope,\n reason: blocker.reason,\n priority: blocker.priority,\n timeout: blocker.timeout,\n })\n );\n\n // Remove the blocker (this will also run \"remove\" middleware)\n get().removeBlocker(id);\n }\n }, config.timeout);\n }\n\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: normalizePriority(config.priority),\n timestamp: config.timestamp ?? Date.now(),\n timeout: config.timeout,\n timeoutId,\n onTimeout: config.onTimeout,\n };\n newBlockers.set(id, storedBlocker);\n\n return { activeBlockers: newBlockers };\n });\n\n void get().runMiddlewares(\n createMiddlewareContext(\"add\", id, {\n scope: config.scope,\n reason: config.reason,\n priority: config.priority,\n timeout: config.timeout,\n })\n );\n },\n\n /**\n * Updates an existing blocker or creates it if it doesn't exist.\n *\n * Merges the provided configuration with existing blocker data. If the timeout\n * is changed, the timeout timer is restarted. Triggers middleware with 'update' action.\n *\n * @param id - Identifier of the blocker to update\n * @param config - Partial configuration to merge with existing blocker data\n *\n * @example\n * Update blocker reason\n * ```ts\n * store.getState().updateBlocker('save', {\n * reason: 'Saving additional data...'\n * });\n * ```\n *\n * @example\n * Extend timeout\n * ```ts\n * store.getState().updateBlocker('api-call', {\n * timeout: 60000 // Extend to 60 seconds\n * });\n * ```\n *\n * @see {@link addBlocker} to create a new blocker\n */\n updateBlocker: (id: string, config: Partial<BlockerConfig> = {}): void => {\n const existingBlocker = get().activeBlockers.get(id);\n\n if (!existingBlocker) {\n get().addBlocker(id, config);\n return;\n }\n\n // Handle timeout update - restart timer if timeout changed\n let timeoutId = existingBlocker.timeoutId;\n const timeoutChanged =\n config.timeout !== undefined && config.timeout !== existingBlocker.timeout;\n\n if (timeoutChanged) {\n // Clear old timeout\n if (existingBlocker.timeoutId) {\n clearTimeout(existingBlocker.timeoutId);\n }\n\n // Set up new timeout if specified\n if (config.timeout && config.timeout > 0) {\n const newTimeout = config.timeout;\n\n timeoutId = setTimeout(() => {\n const blocker = get().activeBlockers.get(id);\n\n if (blocker) {\n blocker.onTimeout?.(id);\n\n void get().runMiddlewares(\n createMiddlewareContext(\"timeout\", id, {\n scope: blocker.scope,\n reason: blocker.reason,\n priority: blocker.priority,\n timeout: blocker.timeout,\n })\n );\n\n get().removeBlocker(id);\n }\n }, newTimeout);\n } else {\n timeoutId = undefined;\n }\n }\n\n const updatedBlocker: StoredBlocker = {\n ...existingBlocker,\n scope: config.scope ?? existingBlocker.scope,\n reason: config.reason ?? existingBlocker.reason,\n priority: normalizePriority(config.priority, existingBlocker.priority),\n timestamp: config.timestamp ?? existingBlocker.timestamp,\n timeout: config.timeout ?? existingBlocker.timeout,\n timeoutId,\n onTimeout: config.onTimeout ?? existingBlocker.onTimeout,\n };\n\n set((state) => {\n const newBlockers = new Map(state.activeBlockers);\n newBlockers.set(id, updatedBlocker);\n\n return { activeBlockers: newBlockers };\n });\n\n void get().runMiddlewares(\n createMiddlewareContext(\n \"update\",\n id,\n {\n scope: updatedBlocker.scope,\n reason: updatedBlocker.reason,\n priority: updatedBlocker.priority,\n timeout: updatedBlocker.timeout,\n onTimeout: updatedBlocker.onTimeout,\n timestamp: updatedBlocker.timestamp,\n },\n {\n scope: existingBlocker.scope,\n reason: existingBlocker.reason,\n priority: existingBlocker.priority,\n timeout: existingBlocker.timeout,\n onTimeout: existingBlocker.onTimeout,\n timestamp: existingBlocker.timestamp,\n }\n )\n );\n },\n\n /**\n * Removes a blocker from the store.\n *\n * Clears any associated timeout and triggers middleware with 'remove' action.\n * Safe to call even if the blocker doesn't exist (no-op in that case).\n *\n * @param id - Identifier of the blocker to remove\n *\n * @example\n * ```ts\n * // Add and remove a blocker\n * store.getState().addBlocker('temp', { scope: 'form' });\n * // ... later\n * store.getState().removeBlocker('temp');\n * ```\n *\n * @see {@link addBlocker} to add a blocker\n * @see {@link clearAllBlockers} to remove all blockers at once\n */\n removeBlocker: (id: string): void => {\n const prevBlocker = get().activeBlockers.get(id);\n\n // Clear timeout if it exists\n if (prevBlocker?.timeoutId) {\n clearTimeout(prevBlocker.timeoutId);\n }\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 const publicConfig = toPublicBlockerConfig(prevBlocker);\n void get().runMiddlewares(createMiddlewareContext(\"remove\", id, publicConfig, publicConfig));\n }\n },\n\n /**\n * Checks if one or more scopes are currently blocked.\n *\n * Returns true if ANY blocker affects the specified scope(s). Global scope\n * blockers will cause this to return true for any scope check.\n *\n * @param scope - Scope(s) to check. Defaults to \"global\" if not specified.\n * Can be a single scope string or array of scopes.\n * @returns true if any of the specified scopes are currently blocked\n *\n * @example\n * Single scope check\n * ```ts\n * const isFormBlocked = store.getState().isBlocked('form');\n * console.log(isFormBlocked); // true or false\n * ```\n *\n * @example\n * Multiple scopes check\n * ```ts\n * const isBlocked = store.getState().isBlocked(['form', 'navigation']);\n * // Returns true if either 'form' OR 'navigation' has active blockers\n * ```\n *\n * @see {@link getBlockingInfo} for detailed blocker information\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 * Gets detailed information about all blockers affecting a specific scope.\n *\n * Returns an array of blocker objects sorted by priority (highest first).\n * Includes global blockers and scope-specific blockers. Each blocker object\n * contains id, reason, priority, scope, timestamp, and timeout information.\n *\n * @param scope - Scope to get blocking information for\n * @returns Array of {@link BlockerInfo} objects, sorted by priority descending\n *\n * @example\n * Display blocker details\n * ```ts\n * const blockers = store.getState().getBlockingInfo('form');\n * blockers.forEach(blocker => {\n * console.log(`${blocker.id}: ${blocker.reason}`);\n * console.log(`Priority: ${blocker.priority}`);\n * });\n * ```\n *\n * @example\n * Get highest priority blocker\n * ```ts\n * const blockers = store.getState().getBlockingInfo('navigation');\n * const topBlocker = blockers[0]; // Highest priority\n * if (topBlocker) {\n * console.log(`Top blocker: ${topBlocker.reason}`);\n * }\n * ```\n *\n * @see {@link isBlocked} for a simple boolean check\n * @see {@link BlockerInfo} for the structure of returned objects\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 const { timeoutId: _timeoutId, ...publicBlocker } = blocker;\n blockers.push({ id, ...publicBlocker });\n }\n }\n\n return blockers.sort((a, b) => b.priority - a.priority);\n },\n\n /**\n * Removes all active blockers from the store.\n *\n * Clears all timeouts and triggers middleware with 'clear' action.\n * Useful for resetting the blocking state.\n *\n * @example\n * ```ts\n * // Clear all blockers on logout\n * store.getState().clearAllBlockers();\n * ```\n *\n * @see {@link clearBlockersForScope} to clear blockers for a specific scope\n */\n clearAllBlockers: (): void => {\n const { activeBlockers } = get();\n const count = activeBlockers.size;\n\n // Clear all timeouts before clearing blockers\n for (const [, blocker] of activeBlockers) {\n if (blocker.timeoutId) {\n clearTimeout(blocker.timeoutId);\n }\n }\n\n set({ activeBlockers: new Map() });\n\n // Notify middleware about clear action\n if (count > 0) {\n void get().runMiddlewares({\n action: \"clear\",\n blockerId: \"*\",\n timestamp: Date.now(),\n count,\n });\n }\n },\n\n /**\n * Removes all blockers that affect a specific scope.\n *\n * Clears timeouts for removed blockers and triggers middleware with\n * 'clear_scope' action. Global scope blockers are NOT cleared by this method.\n *\n * @param scope - Scope to clear blockers for\n *\n * @example\n * Clear form blockers\n * ```ts\n * // Clear all blockers affecting 'form' scope\n * store.getState().clearBlockersForScope('form');\n * ```\n *\n * @example\n * Clear on navigation\n * ```ts\n * // Clear navigation blockers when user navigates away\n * store.getState().clearBlockersForScope('navigation');\n * ```\n *\n * @see {@link clearAllBlockers} to clear all blockers\n */\n clearBlockersForScope: (scope: string): void => {\n const { activeBlockers } = get();\n let count = 0;\n\n // Clear timeouts for blockers that will be removed\n for (const [, blocker] of activeBlockers) {\n const blockerScopes = normalizeScopeToArray(blocker.scope);\n if (blockerScopes.includes(scope)) {\n if (blocker.timeoutId) {\n clearTimeout(blocker.timeoutId);\n }\n count++;\n }\n }\n\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 // Notify middleware about clear_scope action\n if (count > 0) {\n void get().runMiddlewares({\n action: \"clear_scope\",\n blockerId: \"*\",\n timestamp: Date.now(),\n scope,\n count,\n });\n }\n },\n});\n","import { createStoreProvider } from \"@okyrychenko-dev/react-zustand-toolkit\";\nimport { type ReactNode } from \"react\";\nimport { type StoreApi } from \"zustand\";\nimport { createUIBlockingActions } from \"../store/uiBlockingStore.actions\";\nimport type { Middleware } from \"../middleware\";\nimport type { UIBlockingStore } from \"../store/uiBlockingStore.types\";\n\n/**\n * Props for the {@link UIBlockingProvider} component.\n *\n * Configures an isolated UI blocking store instance for a subtree of your app.\n * Useful for SSR, testing, micro-frontends, or any scenario where you need\n * independent blocking state.\n *\n * @public\n * @since 0.6.0\n */\nexport interface UIBlockingProviderProps {\n children: ReactNode;\n /** Initial middlewares to register */\n middlewares?: ReadonlyArray<Middleware>;\n}\n\n/**\n * Base provider implementation created using toolkit's createStoreProvider.\n * @internal\n */\nconst {\n Provider: BaseUIBlockingProvider,\n useContextStoreApi: useUIBlockingContext,\n useContextStore: baseUseUIBlockingStoreFromContext,\n useIsInsideProvider: useIsInsideUIBlockingProvider,\n useContextStoreOptional: useOptionalUIBlockingContext,\n} = createStoreProvider(createUIBlockingActions, \"UIBlocking\");\n\nexport function useUIBlockingStoreFromContext(): UIBlockingStore;\nexport function useUIBlockingStoreFromContext<T>(\n selector: (state: UIBlockingStore) => T,\n equalityFn?: (a: T, b: T) => boolean\n): T;\nexport function useUIBlockingStoreFromContext<T>(\n selector?: (state: UIBlockingStore) => T,\n equalityFn?: (a: T, b: T) => boolean\n): T | UIBlockingStore {\n if (selector) {\n return baseUseUIBlockingStoreFromContext(selector, equalityFn);\n }\n\n return baseUseUIBlockingStoreFromContext();\n}\n\n/**\n * Provider component for isolated UI blocking state management.\n *\n * Creates an independent store instance for a subtree of your application.\n * Each provider has its own isolated blocking state, separate from the global\n * store and other provider instances.\n *\n * **Use cases:**\n * - Server-Side Rendering (SSR) - Avoid state sharing between requests\n * - Testing - Isolated state for each test\n * - Micro-frontends - Independent blocking state per micro-app\n * - Modals/Dialogs - Scoped blocking within a dialog\n *\n * Uses `createStoreProvider` from `@okyrychenko-dev/react-zustand-toolkit` with\n * provider-scoped store creation and middleware registration.\n *\n * @param props - Provider configuration\n * @param props.children - React children to wrap with the provider\n * @param props.middlewares - Array of middleware functions to register on store creation\n *\n * @example\n * Basic SSR setup\n * ```tsx\n * import { UIBlockingProvider } from '@okyrychenko-dev/react-action-guard';\n *\n * function App() {\n * return (\n * <UIBlockingProvider>\n * <MyApplication />\n * </UIBlockingProvider>\n * );\n * }\n * ```\n *\n * @example\n * With middleware\n * ```tsx\n * import { UIBlockingProvider, loggerMiddleware } from '@okyrychenko-dev/react-action-guard';\n *\n * function App() {\n * return (\n * <UIBlockingProvider\n * middlewares={[loggerMiddleware]}\n * >\n * <MyApplication />\n * </UIBlockingProvider>\n * );\n * }\n * ```\n *\n * @example\n * Multiple providers for micro-frontends\n * ```tsx\n * function MicroFrontendApp() {\n * return (\n * <div>\n * <UIBlockingProvider>\n * <MicroApp1 />\n * </UIBlockingProvider>\n *\n * <UIBlockingProvider>\n * <MicroApp2 />\n * </UIBlockingProvider>\n * </div>\n * );\n * }\n * ```\n *\n * @example\n * Testing with isolated state\n * ```tsx\n * // In your test file\n * import { render } from '@testing-library/react';\n * import { UIBlockingProvider } from '@okyrychenko-dev/react-action-guard';\n *\n * test('blocker behavior', () => {\n * render(\n * <UIBlockingProvider>\n * <ComponentUnderTest />\n * </UIBlockingProvider>\n * );\n * // Each test gets isolated state\n * });\n * ```\n *\n * @see {@link useUIBlockingContext} to access the store from context\n * @see {@link useIsInsideUIBlockingProvider} to check if inside a provider\n * @see {@link UIBlockingProviderProps} for prop details\n *\n * @public\n * @since 0.6.0\n */\nexport function UIBlockingProvider({\n children,\n middlewares = [],\n}: UIBlockingProviderProps): ReactNode {\n const handleStoreInit = (store: StoreApi<UIBlockingStore>): void => {\n // Register initial middlewares\n middlewares.forEach((mw, index) => {\n store.getState().registerMiddleware(`provider-middleware-${index.toString()}`, mw);\n });\n };\n\n return <BaseUIBlockingProvider onStoreInit={handleStoreInit}>{children}</BaseUIBlockingProvider>;\n}\n\n/**\n * Hook to access the store API from {@link UIBlockingProvider} context.\n * Returns the Zustand store API for the nearest UIBlockingProvider ancestor.\n * Throws an error if called outside a provider.\n * Use this when you need direct access to the store API (for subscribing,\n * getting state snapshots, etc.) rather than reactive hook access.\n * @returns Store API from the nearest UIBlockingProvider\n * @throws Error if called outside UIBlockingProvider\n * @example\n * Access store API in a component\n * ```tsx\n * function MyComponent() {\n * const storeApi = useUIBlockingContext();\n * useEffect(() => {\n * // Subscribe to changes\n * const unsubscribe = storeApi.subscribe((state) => {\n * console.log('Blockers:', state.activeBlockers.size);\n * });\n * return unsubscribe;\n * }, [storeApi]);\n * return <div>...</div>;\n * }\n * ```\n * @see {@link useUIBlockingStoreFromContext} for reactive hook access\n * @see {@link UIBlockingProvider} for provider setup\n * @public\n * @since 0.6.0\n */\n\n/**\n * Hook to access UI blocking store state from {@link UIBlockingProvider} context.\n * Works like {@link useUIBlockingStore} but uses the provider's isolated store\n * instead of the global store. Supports selective subscriptions for performance.\n * @returns Store state and actions from the nearest UIBlockingProvider\n * @throws Error if called outside UIBlockingProvider\n *\n * @example\n * Access full store\n * ```tsx\n * function MyComponent() {\n * const store = useUIBlockingStoreFromContext();\n *\n * return (\n * <button onClick={() => store.addBlocker('test', { scope: 'form' })}>\n * Add Blocker\n * </button>\n * );\n * }\n * ```\n *\n * @example\n * Selective subscription (recommended)\n * ```tsx\n * function BlockerCount() {\n * const count = useUIBlockingStoreFromContext(\n * (state) => state.activeBlockers.size\n * );\n * return <div>{count} active blockers</div>;\n * }\n * ```\n * @see {@link useUIBlockingContext} for store API access\n * @see {@link UIBlockingProvider} for provider setup\n * @public\n * @since 0.6.0\n */\n\n/**\n * Hook to check if the component is inside a {@link UIBlockingProvider}.\n * Returns true if the component is rendered within a UIBlockingProvider,\n * false otherwise. Useful for conditional logic or debugging.\n * @returns true if inside a UIBlockingProvider, false otherwise\n * @example\n * Conditional provider usage\n * ```tsx\n * function MyComponent() {\n * const isInProvider = useIsInsideUIBlockingProvider();\n * if (!isInProvider) {\n * console.warn('Component rendered outside UIBlockingProvider');\n * }\n * return <div>In provider: {isInProvider ? 'Yes' : 'No'}</div>;\n * }\n * ```\n * @example\n * Debug helper\n * ```tsx\n * function DebugInfo() {\n * const isInProvider = useIsInsideUIBlockingProvider();\n * return (\n * <div>\n * <p>Provider status: {isInProvider ? 'โœ…' : 'โŒ'}</p>\n * </div>\n * );\n * }\n * ```\n * @see {@link UIBlockingProvider} for provider setup\n * @public\n * @since 0.6.0\n */\n\n// Export hooks from base provider\nexport {\n useUIBlockingContext,\n useIsInsideUIBlockingProvider,\n useOptionalUIBlockingContext,\n /** @deprecated Use `useOptionalUIBlockingContext`. */\n useOptionalUIBlockingContext as useOptionalContext,\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 { createShallowStore } from \"@okyrychenko-dev/react-zustand-toolkit\";\nimport { devtools } from \"zustand/middleware\";\nimport { createUIBlockingActions } from \"./uiBlockingStore.actions\";\nimport { devtoolsConfig } from \"./uiBlockingStore.config\";\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 storeBindings = createShallowStore<UIBlockingStore, [[\"zustand/devtools\", never]]>(\n devtools(createUIBlockingActions, devtoolsConfig)\n);\n\nconst uiBlockingStoreApi = storeBindings.useStoreApi;\n\nexport function useUIBlockingStore(): UIBlockingStore;\nexport function useUIBlockingStore<T>(\n selector: (state: UIBlockingStore) => T,\n equalityFn?: (a: T, b: T) => boolean\n): T;\nexport function useUIBlockingStore<T>(\n selector?: (state: UIBlockingStore) => T,\n equalityFn?: (a: T, b: T) => boolean\n): T | UIBlockingStore {\n if (selector) {\n return storeBindings.useStore(selector, equalityFn);\n }\n\n return storeBindings.useStore();\n}\nexport { uiBlockingStoreApi };\n","import { type StoreApi, useStore } from \"zustand\";\nimport { useShallow } from \"zustand/shallow\";\nimport { uiBlockingStoreApi } from \"../store/uiBlockingStore.store\";\nimport { useOptionalUIBlockingContext } from \"./UIBlockingContext\";\nimport type { UIBlockingStore } from \"../store/uiBlockingStore.types\";\n\n/**\n * Hook to get the optional context store (returns null if not inside provider)\n * @internal\n */\nfunction useOptionalContextStore(): StoreApi<UIBlockingStore> | null {\n return useOptionalUIBlockingContext();\n}\n\n/**\n * Hook that resolves to either the context store or global store\n *\n * This hook automatically uses the store from UIBlockingProvider if available,\n * otherwise falls back to the global store. This enables both patterns:\n *\n * 1. Global store (default behavior, no Provider needed)\n * 2. Context store (for SSR, testing, micro-frontends)\n *\n * @returns The resolved store API\n */\nexport function useResolvedStoreApi(): StoreApi<UIBlockingStore> {\n const contextStore = useOptionalContextStore();\n // Return context store if inside Provider, otherwise global store\n return contextStore ?? uiBlockingStoreApi;\n}\n\n/**\n * Hook to use the resolved store with a selector\n *\n * Automatically applies shallow comparison to prevent unnecessary re-renders.\n *\n * @param selector - Selector function to pick state from the store\n * @returns Selected state value\n */\nexport function useResolvedValue<T>(selector: (state: UIBlockingStore) => T): T {\n const store = useResolvedStoreApi();\n return useStore(store, useShallow(selector));\n}\n\n/**\n * @deprecated Use `useResolvedStoreApi`.\n */\nexport const useResolvedStore = useResolvedStoreApi;\n/**\n * @deprecated Use `useResolvedValue`.\n */\nexport const useResolvedStoreWithSelector = useResolvedValue;\n","import type { StoreApi } from \"zustand\";\nimport type { UIBlockingStore } from \"./uiBlockingStore.types\";\n\nconst storeSequences = new WeakMap<StoreApi<UIBlockingStore>, number>();\n\nexport function allocateBlockerId(store: StoreApi<UIBlockingStore>, prefix: string): string {\n let sequence = storeSequences.get(store) ?? 0;\n let blockerId: string;\n\n do {\n sequence += 1;\n blockerId = `${prefix}-${String(sequence)}`;\n } while (store.getState().activeBlockers.has(blockerId));\n\n storeSequences.set(store, sequence);\n return blockerId;\n}\n","import { useCallback } from \"react\";\nimport { useResolvedStoreApi } from \"../../context\";\nimport { allocateBlockerId } from \"../../store/blockerId.utils\";\n\nexport function useBlockerIdAllocator(): (prefix: string) => string {\n const store = useResolvedStoreApi();\n\n return useCallback((prefix: string): string => allocateBlockerId(store, prefix), [store]);\n}\n","import { useCallback } from \"react\";\nimport { useResolvedValue } from \"../../context\";\nimport { ASYNC_ACTION_PRIORITY } from \"../../store\";\nimport { useBlockerIdAllocator } from \"../useBlockerIdAllocator\";\n\n/**\n * Options for useAsyncAction hook\n */\nexport interface UseAsyncActionOptions {\n /** Timeout in milliseconds after which the blocker will be automatically removed */\n timeout?: number;\n /** Callback invoked when the blocker is automatically removed due to timeout */\n onTimeout?: (blockerId: string) => void;\n}\n\n/**\n * Wraps async functions with automatic UI blocking during execution.\n *\n * Creates a wrapper function that automatically:\n * 1. Adds a blocker before executing the async function\n * 2. Executes the async function\n * 3. Removes the blocker after completion (success or failure)\n *\n * Each invocation generates a unique blocker ID (actionId-counter), allowing\n * multiple concurrent executions of the same action without ID conflicts.\n * The blocker is removed even if the async function throws an error.\n *\n * Works with both the global store and isolated provider instances (via UIBlockingProvider).\n *\n * @template T - The return type of the async function being wrapped\n * @param actionId - Base identifier for the action. Used in blocker ID and default reason.\n * Example: \"saveForm\", \"fetchData\", \"submitOrder\"\n * @param scope - Scope(s) to block during execution. Can be a single scope or array.\n * Defaults to \"global\" if not specified.\n * @param options - Optional configuration\n * @param options.timeout - Timeout in milliseconds. Blocker auto-removes after this duration.\n * @param options.onTimeout - Callback invoked when blocker times out before async completes\n *\n * @returns Wrapper function that accepts an async function and returns a Promise with the same type\n *\n * @example\n * Basic form submission\n * ```tsx\n * function MyForm() {\n * const executeWithBlocking = useAsyncAction('saveForm', 'form');\n *\n * const handleSubmit = async (e) => {\n * e.preventDefault();\n *\n * await executeWithBlocking(async () => {\n * const response = await fetch('/api/save', {\n * method: 'POST',\n * body: JSON.stringify(formData)\n * });\n * return response.json();\n * });\n *\n * alert('Form saved!');\n * };\n *\n * return <form onSubmit={handleSubmit}>...</form>;\n * }\n * ```\n *\n * @example\n * With timeout and error handling\n * ```tsx\n * const executeWithBlocking = useAsyncAction(\n * 'fetchData',\n * ['global', 'data'],\n * {\n * timeout: 30000, // 30 seconds\n * onTimeout: (blockerId) => {\n * console.warn(`Operation ${blockerId} timed out`);\n * }\n * }\n * );\n *\n * const loadData = async () => {\n * try {\n * const data = await executeWithBlocking(async () => {\n * return await fetchDataFromAPI();\n * });\n * setData(data);\n * } catch (error) {\n * console.error('Failed to load data:', error);\n * // Blocker is automatically removed even on error\n * }\n * };\n * ```\n *\n * @example\n * Multiple concurrent actions\n * ```tsx\n * function FileUploader() {\n * const uploadWithBlocking = useAsyncAction('upload', 'uploads');\n *\n * const uploadFiles = async (files) => {\n * // Each upload gets unique blocker ID (upload-1, upload-2, etc.)\n * const promises = files.map(file =>\n * uploadWithBlocking(() => uploadFile(file))\n * );\n *\n * await Promise.all(promises);\n * };\n *\n * return <...>;\n * }\n * ```\n *\n * @example\n * Type-safe return value\n * ```tsx\n * interface UserData {\n * id: string;\n * name: string;\n * }\n *\n * function UserProfile() {\n * const executeWithBlocking = useAsyncAction<UserData>('fetchUser', 'user');\n *\n * const loadUser = async (userId: string) => {\n * const userData = await executeWithBlocking(async () => {\n * const response = await fetch(`/api/users/${userId}`);\n * return response.json(); // TypeScript knows this is UserData\n * });\n *\n * // userData is typed as UserData\n * console.log(userData.name);\n * };\n *\n * return <...>;\n * }\n * ```\n *\n * @see {@link useBlocker} for manual blocker management\n * @see {@link useIsBlocked} to check blocking state\n * @see {@link UseAsyncActionOptions} for available options\n *\n * @public\n * @since 0.6.0\n */\nexport function useAsyncAction<T = unknown>(\n actionId: string,\n scope?: string | ReadonlyArray<string>,\n options?: UseAsyncActionOptions\n): (asyncFn: () => Promise<T>) => Promise<T> {\n const allocateBlockerId = useBlockerIdAllocator();\n const { addBlocker, removeBlocker } = useResolvedValue((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 = allocateBlockerId(actionId);\n\n try {\n addBlocker(blockerId, {\n scope,\n reason: `Executing ${actionId}`,\n priority: ASYNC_ACTION_PRIORITY,\n timeout: options?.timeout,\n onTimeout: options?.onTimeout,\n });\n\n return await asyncFn();\n } finally {\n removeBlocker(blockerId);\n }\n },\n [\n actionId,\n scope,\n options?.timeout,\n options?.onTimeout,\n allocateBlockerId,\n addBlocker,\n removeBlocker,\n ]\n );\n\n return executeWithBlocking;\n}\n","import { shallow } from \"zustand/shallow\";\nimport { DEFAULT_SCOPE } from \"../../store\";\nimport type { BlockerConfig } from \"../../store\";\n\ntype BlockerConfigSnapshotValue = string | number | BlockerConfig[\"onTimeout\"] | undefined;\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\nfunction normalizeScopeSnapshot(scope?: string | ReadonlyArray<string>): ReadonlyArray<string> {\n if (scope === undefined) {\n return [DEFAULT_SCOPE];\n }\n\n if (typeof scope === \"string\") {\n return [scope];\n }\n\n return scope;\n}\n\nfunction getScopeSnapshotKey(scope?: string | ReadonlyArray<string>): string {\n return JSON.stringify(normalizeScopeSnapshot(scope));\n}\n\nfunction toBlockerConfigSnapshot(config: BlockerConfig): ReadonlyArray<BlockerConfigSnapshotValue> {\n return [\n getScopeSnapshotKey(config.scope),\n config.reason,\n config.priority,\n config.timestamp,\n config.timeout,\n config.onTimeout,\n ];\n}\n\nexport function areBlockerConfigsEqual(first: BlockerConfig, second: BlockerConfig): boolean {\n return shallow(toBlockerConfigSnapshot(first), toBlockerConfigSnapshot(second));\n}\n","import { useCallback, useEffect, useMemo, useRef } from \"react\";\nimport { useResolvedValue } from \"../../context\";\nimport { areBlockerConfigsEqual } from \"./useBlocker.utils\";\nimport type { BlockerConfig } from \"../../store\";\n\n/**\n * Automatically manages a UI blocker based on component lifecycle.\n *\n * Creates a blocker that is automatically added when the condition is true\n * and removed when the component unmounts or condition becomes false.\n * Supports scoped blocking, priorities, timeouts, and works with both\n * global store and isolated provider instances.\n *\n * @param blockerId - Unique identifier for this blocker. Must be unique within the scope.\n * @param config - Configuration object for the blocker\n * @param config.scope - Scope(s) to block. Can be a single scope string (e.g., \"form\", \"navigation\")\n * or an array of scopes (e.g., [\"form\", \"navigation\"]). Defaults to \"global\".\n * @param config.reason - Human-readable reason for blocking, displayed in DevTools and UI\n * @param config.priority - Priority level (0-100). Higher priority blockers take precedence.\n * Use 0-30 for low priority, 31-70 for medium, 71-100 for high priority.\n * @param config.timeout - Auto-removal timeout in milliseconds. Blocker will be automatically\n * removed after this duration. Use 0 or undefined for no timeout.\n * @param config.onTimeout - Callback function invoked when the blocker times out\n * @param isActive - When true, blocker is active; when false, blocker is removed.\n * Defaults to true. Use this for conditional blocking.\n *\n * @example\n * Basic form submission blocking\n * ```tsx\n * function MyForm() {\n * const [isSubmitting, setIsSubmitting] = useState(false);\n *\n * useBlocker('form-submit', {\n * scope: 'form',\n * reason: 'Submitting form...',\n * priority: 50,\n * timeout: 30000, // Auto-remove after 30 seconds\n * onTimeout: () => {\n * console.warn('Form submission timed out');\n * setIsSubmitting(false);\n * }\n * }, isSubmitting);\n *\n * return <form onSubmit={handleSubmit}>...</form>;\n * }\n * ```\n *\n * @example\n * Multiple scopes with high priority\n * ```tsx\n * useBlocker('critical-save', {\n * scope: ['form', 'navigation', 'actions'],\n * reason: 'Saving critical data...',\n * priority: 90,\n * }, isSaving);\n * ```\n *\n * @example\n * Conditional blocking based on unsaved changes\n * ```tsx\n * function Editor() {\n * const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false);\n *\n * useBlocker('unsaved-changes', {\n * scope: 'navigation',\n * reason: 'You have unsaved changes',\n * priority: 80,\n * }, hasUnsavedChanges);\n *\n * return <div>...</div>;\n * }\n * ```\n *\n * @see {@link useIsBlocked} to check if a scope is currently blocked\n * @see {@link useBlockingInfo} to get detailed blocker information\n * @see {@link useAsyncAction} for async operation wrapping with automatic blocking\n * @see {@link useConfirmableBlocker} for blockers that require user confirmation\n *\n * @public\n * @since 0.6.0\n */\nexport function useBlocker(blockerId: string, config: BlockerConfig, isActive = true): void {\n const { addBlocker, removeBlocker, updateBlocker } = useResolvedValue((state) => ({\n addBlocker: state.addBlocker,\n removeBlocker: state.removeBlocker,\n updateBlocker: state.updateBlocker,\n }));\n const lastConfigRef = useRef<BlockerConfig | null>(null);\n const onTimeoutRef = useRef(config.onTimeout);\n\n onTimeoutRef.current = config.onTimeout;\n\n const handleTimeout = useCallback((id: string): void => {\n onTimeoutRef.current?.(id);\n }, []);\n\n const storeConfig = useMemo<BlockerConfig>(\n () => ({\n ...config,\n onTimeout: config.onTimeout ? handleTimeout : undefined,\n }),\n [config, handleTimeout]\n );\n\n useEffect(() => {\n if (!isActive || !blockerId) {\n return;\n }\n\n addBlocker(blockerId, storeConfig);\n lastConfigRef.current = storeConfig;\n\n return () => {\n lastConfigRef.current = null;\n removeBlocker(blockerId);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [blockerId, isActive, addBlocker, removeBlocker]);\n\n useEffect(() => {\n if (!isActive || !blockerId) {\n return;\n }\n\n if (\n lastConfigRef.current !== null &&\n areBlockerConfigsEqual(lastConfigRef.current, storeConfig)\n ) {\n return;\n }\n\n updateBlocker(blockerId, storeConfig);\n lastConfigRef.current = storeConfig;\n }, [blockerId, storeConfig, isActive, updateBlocker]);\n}\n","import { useMemo } from \"react\";\nimport { useStore } from \"zustand\";\nimport { useResolvedStoreApi } from \"../../context\";\nimport { DEFAULT_SCOPE } from \"../../store\";\nimport type { BlockerInfo } from \"../../store\";\n\n/**\n * Gets detailed information about all active blockers for a specific scope.\n *\n * Returns an array of blocker information objects, sorted by priority (highest first).\n * Each blocker object contains id, reason, priority, and scope information.\n * The hook automatically re-renders when blockers are added, removed, or updated.\n *\n * Uses memoization to provide a stable reference - only re-renders when the actual\n * blocker list changes, not on every store update. This makes it efficient for\n * rendering lists of blockers.\n *\n * Works with both the global store and isolated provider instances (via UIBlockingProvider).\n *\n * @param scope - Scope to get blocking information for. Defaults to \"global\" if not specified.\n * @returns Array of {@link BlockerInfo} objects, sorted by priority (highest to lowest)\n *\n * @example\n * Display list of active blockers\n * ```tsx\n * function BlockerList() {\n * const blockers = useBlockingInfo('form');\n *\n * if (blockers.length === 0) {\n * return <div>No active blockers</div>;\n * }\n *\n * return (\n * <ul>\n * {blockers.map((blocker) => (\n * <li key={blocker.id}>\n * {blocker.reason} (Priority: {blocker.priority})\n * </li>\n * ))}\n * </ul>\n * );\n * }\n * ```\n *\n * @example\n * Show highest priority blocker reason\n * ```tsx\n * function BlockingBanner() {\n * const blockers = useBlockingInfo('global');\n *\n * // blockers are already sorted by priority (highest first)\n * const topBlocker = blockers[0];\n *\n * if (!topBlocker) {\n * return null;\n * }\n *\n * return <div className=\"banner\">{topBlocker.reason}</div>;\n * }\n * ```\n *\n * @example\n * Count active blockers\n * ```tsx\n * function BlockerCount() {\n * const formBlockers = useBlockingInfo('form');\n * const navBlockers = useBlockingInfo('navigation');\n *\n * const total = formBlockers.length + navBlockers.length;\n *\n * return <div>{total} active blockers</div>;\n * }\n * ```\n *\n * @see {@link useIsBlocked} for a simple boolean check\n * @see {@link useBlocker} to create blockers\n * @see {@link BlockerInfo} for the structure of blocker information objects\n *\n * @public\n * @since 0.6.0\n */\nexport function useBlockingInfo(scope: string = DEFAULT_SCOPE): ReadonlyArray<BlockerInfo> {\n const store = useResolvedStoreApi();\n\n // Subscribe to the activeBlockers Map to detect changes\n const activeBlockers = useStore(store, (state) => state.activeBlockers);\n\n // Recompute blockers only when activeBlockers or scope changes\n return useMemo(() => {\n return store.getState().getBlockingInfo(scope);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [activeBlockers, scope, store]);\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 { useResolvedValue } from \"../../context\";\nimport { createBlockerConfig } from \"../useBlocker\";\nimport { useConfigRef } from \"../useConfigRef\";\nimport { ConditionalBlockerConfig } from \"./useConditionalBlocker.types\";\n\nconst DEFAULT_CHECK_INTERVAL = 1000;\n\n/**\n * Blocks UI based on a dynamic condition that is periodically evaluated.\n *\n * Periodically checks a condition function and automatically adds or removes\n * a blocker based on the result. Useful for blocking based on application state,\n * network status, feature flags, or any other dynamic condition.\n *\n * The condition function receives optional state and returns a boolean.\n * It's evaluated immediately on mount and then at the specified interval.\n * The blocker is added/removed automatically as the condition changes.\n *\n * Works with both the global store and isolated provider instances (via UIBlockingProvider).\n *\n * @template TState - Type of the state object passed to the condition function\n * @param blockerId - Unique identifier for this conditional blocker\n * @param config - Configuration for conditional blocking\n * @param config.condition - Function that returns true to block, false to unblock.\n * Receives the `state` object as parameter.\n * @param config.state - Optional state object passed to the condition function\n * @param config.checkInterval - How often to check the condition in milliseconds.\n * Defaults to 1000ms (1 second). Lower values mean\n * more responsive blocking but higher CPU usage.\n * @param config.scope - Scope(s) to block when condition is true\n * @param config.reason - Reason for blocking (displayed to users)\n * @param config.priority - Optional blocker priority (0-100)\n *\n * @example\n * Block based on network status\n * ```tsx\n * function OfflineBlocker() {\n * const [isOnline, setIsOnline] = useState(navigator.onLine);\n *\n * useEffect(() => {\n * const handleOnline = () => setIsOnline(true);\n * const handleOffline = () => setIsOnline(false);\n *\n * window.addEventListener('online', handleOnline);\n * window.addEventListener('offline', handleOffline);\n *\n * return () => {\n * window.removeEventListener('online', handleOnline);\n * window.removeEventListener('offline', handleOffline);\n * };\n * }, []);\n *\n * useConditionalBlocker('offline', {\n * condition: () => !isOnline,\n * state: { isOnline },\n * checkInterval: 500, // Check every 500ms\n * scope: 'global',\n * reason: 'No internet connection. Please check your network.',\n * priority: 95\n * });\n *\n * return <App />;\n * }\n * ```\n *\n * @example\n * Block based on feature flag\n * ```tsx\n * function FeatureFlagBlocker() {\n * const featureFlags = useFeatureFlags();\n *\n * useConditionalBlocker('feature-disabled', {\n * condition: (state) => !state.featureFlags.newFeatureEnabled,\n * state: { featureFlags },\n * checkInterval: 5000, // Check every 5 seconds\n * scope: 'new-feature',\n * reason: 'This feature is currently disabled',\n * priority: 70\n * });\n *\n * return <NewFeature />;\n * }\n * ```\n *\n * @example\n * Block during API rate limit\n * ```tsx\n * function RateLimitBlocker() {\n * const [requestCount, setRequestCount] = useState(0);\n * const [resetTime, setResetTime] = useState<number | null>(null);\n *\n * useConditionalBlocker('rate-limit', {\n * condition: (state) => {\n * if (!state.resetTime) {\n * return false;\n * }\n * return Date.now() < state.resetTime && state.requestCount >= 100;\n * },\n * state: { requestCount, resetTime },\n * checkInterval: 1000,\n * scope: 'api',\n * reason: 'API rate limit reached. Please wait.',\n * priority: 90\n * });\n *\n * return <Dashboard />;\n * }\n * ```\n *\n * @example\n * Block based on form validation\n * ```tsx\n * function FormValidationBlocker() {\n * const { formState } = useFormContext();\n *\n * useConditionalBlocker('invalid-form', {\n * condition: (state) => !state.isValid && state.isDirty,\n * state: formState,\n * checkInterval: 500,\n * scope: 'form-submit',\n * reason: 'Please fix form errors before submitting',\n * priority: 60\n * });\n *\n * return <Form />;\n * }\n * ```\n *\n * @example\n * Without state parameter (simple condition)\n * ```tsx\n * useConditionalBlocker('low-battery', {\n * condition: () => !navigator.onLine,\n * checkInterval: 30000, // Check every 30 seconds\n * scope: 'heavy-operations',\n * reason: 'Internet connection is required for this operation',\n * priority: 80\n * });\n * ```\n *\n * @see {@link useBlocker} for simple conditional blocking with boolean\n * @see {@link useScheduledBlocker} for time-based blocking\n * @see {@link ConditionalBlockerConfig} for configuration options\n *\n * @public\n * @since 0.6.0\n */\nexport function useConditionalBlocker<TState = unknown>(\n blockerId: string,\n config: ConditionalBlockerConfig<TState>\n): void {\n const { addBlocker, removeBlocker } = useResolvedValue((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 checkInterval =\n config.checkInterval !== undefined && config.checkInterval > 0\n ? config.checkInterval\n : DEFAULT_CHECK_INTERVAL;\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 intervalRef.current = setInterval(checkCondition, checkInterval);\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 }, [checkCondition, blockerId, removeBlocker, checkInterval]);\n}\n","import { useCallback, useState } from \"react\";\nimport { useBlocker } from \"../useBlocker\";\nimport {\n ConfirmableBlockerConfig,\n UseConfirmableBlockerReturn,\n} from \"./useConfirmableBlocker.types\";\n\n/**\n * Creates a blocker that requires user confirmation before executing an action.\n *\n * Manages a confirmation dialog and blocking state for actions that need user approval.\n * The blocker is active during both the confirmation dialog display and action execution.\n *\n * Workflow:\n * 1. Call `execute()` to show confirmation dialog (blocker activated)\n * 2. User confirms โ†’ `onConfirm` callback runs (blocker remains active)\n * 3. Action completes โ†’ blocker removed\n * 4. User cancels โ†’ blocker removed, optional `onCancel` callback runs\n *\n * Works with both the global store and isolated provider instances (via UIBlockingProvider).\n *\n * @param blockerId - Unique identifier for this confirmable blocker\n * @param config - Configuration for the confirmable action\n * @param config.confirmMessage - Message to display in the confirmation dialog\n * @param config.confirmTitle - Optional dialog title (defaults to \"Confirm Action\")\n * @param config.confirmButtonText - Optional confirm button text (defaults to \"Confirm\")\n * @param config.cancelButtonText - Optional cancel button text (defaults to \"Cancel\")\n * @param config.onConfirm - Async function to execute after user confirms\n * @param config.onCancel - Optional callback when user cancels\n * @param config.scope - Scope(s) to block during confirmation and execution\n * @param config.reason - Optional custom blocking reason (defaults to confirmMessage)\n * @param config.priority - Optional blocker priority (0-100)\n *\n * @returns Object containing:\n * - `execute`: Function to trigger the confirmation dialog\n * - `isDialogOpen`: Boolean indicating if confirmation dialog is visible\n * - `isExecuting`: Boolean indicating if the confirmed action is executing\n * - `confirmConfig`: Dialog configuration (title, message, button texts)\n * - `onConfirm`: Function to call when user confirms\n * - `onCancel`: Function to call when user cancels\n *\n * @example\n * Delete confirmation with custom dialog\n * ```tsx\n * function DeleteButton({ itemId, itemName }) {\n * const confirmableDelete = useConfirmableBlocker('delete-item', {\n * confirmMessage: `Are you sure you want to delete \"${itemName}\"?`,\n * confirmTitle: 'Delete Item',\n * confirmButtonText: 'Delete',\n * cancelButtonText: 'Keep',\n * scope: ['form', 'navigation'],\n * priority: 80,\n * onConfirm: async () => {\n * await deleteItem(itemId);\n * showToast('Item deleted successfully');\n * },\n * onCancel: () => {\n * console.log('Delete cancelled');\n * }\n * });\n *\n * return (\n * <>\n * <button onClick={confirmableDelete.execute}>\n * Delete\n * </button>\n *\n * {confirmableDelete.isDialogOpen && (\n * <ConfirmDialog\n * {...confirmableDelete.confirmConfig}\n * onConfirm={confirmableDelete.onConfirm}\n * onCancel={confirmableDelete.onCancel}\n * isLoading={confirmableDelete.isExecuting}\n * />\n * )}\n * </>\n * );\n * }\n * ```\n *\n * @example\n * Simple confirmation with default dialog\n * ```tsx\n * function LogoutButton() {\n * const confirmLogout = useConfirmableBlocker('logout', {\n * confirmMessage: 'Are you sure you want to log out?',\n * scope: 'global',\n * onConfirm: async () => {\n * await api.logout();\n * navigate('/login');\n * }\n * });\n *\n * return (\n * <>\n * <button onClick={confirmLogout.execute}>Logout</button>\n *\n * {confirmLogout.isDialogOpen && (\n * <Dialog\n * title={confirmLogout.confirmConfig.title}\n * message={confirmLogout.confirmConfig.message}\n * onConfirm={confirmLogout.onConfirm}\n * onCancel={confirmLogout.onCancel}\n * />\n * )}\n * </>\n * );\n * }\n * ```\n *\n * @example\n * With loading state during execution\n * ```tsx\n * function SaveButton() {\n * const confirmSave = useConfirmableBlocker('save-changes', {\n * confirmMessage: 'Save all changes?',\n * scope: 'form',\n * onConfirm: async () => {\n * await saveAllChanges();\n * }\n * });\n *\n * return (\n * <button\n * onClick={confirmSave.execute}\n * disabled={confirmSave.isExecuting}\n * >\n * {confirmSave.isExecuting ? 'Saving...' : 'Save All'}\n * </button>\n * );\n * }\n * ```\n *\n * @see {@link useBlocker} for simple blocking without confirmation\n * @see {@link ConfirmableBlockerConfig} for configuration options\n * @see {@link UseConfirmableBlockerReturn} for return value structure\n *\n * @public\n * @since 0.6.0\n */\nexport function 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 } 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 { useResolvedValue } from \"../../context\";\n\n/**\n * Checks if one or more scopes are currently blocked.\n *\n * Returns a boolean indicating whether any of the specified scopes have active blockers.\n * The hook automatically re-renders the component when the blocking state changes,\n * ensuring your UI always reflects the current blocking state.\n *\n * Works with both the global store and isolated provider instances (via UIBlockingProvider).\n *\n * @param scope - Scope(s) to check for blocking. Can be:\n * - A single scope string (e.g., \"form\", \"navigation\", \"global\")\n * - An array of scopes (e.g., [\"form\", \"navigation\"])\n * - undefined to check the \"global\" scope\n * @returns true if ANY of the specified scopes are blocked, false otherwise\n *\n * @example\n * Basic single scope check\n * ```tsx\n * function SubmitButton() {\n * const isFormBlocked = useIsBlocked('form');\n *\n * return (\n * <button disabled={isFormBlocked}>\n * {isFormBlocked ? 'Processing...' : 'Submit'}\n * </button>\n * );\n * }\n * ```\n *\n * @example\n * Multiple scopes check\n * ```tsx\n * function NavigationLink({ href, children }) {\n * const isBlocked = useIsBlocked(['navigation', 'global']);\n *\n * return (\n * <a\n * href={href}\n * onClick={(e) => {\n * if (isBlocked) {\n * e.preventDefault();\n * alert('Navigation is currently blocked');\n * }\n * }}\n * style={{ opacity: isBlocked ? 0.5 : 1 }}\n * >\n * {children}\n * </a>\n * );\n * }\n * ```\n *\n * @example\n * Conditional rendering based on blocking state\n * ```tsx\n * function SaveIndicator() {\n * const isSaving = useIsBlocked('save');\n *\n * if (!isSaving) {\n * return null;\n * }\n *\n * return <div className=\"spinner\">Saving...</div>;\n * }\n * ```\n *\n * @see {@link useBlocker} to create a blocker\n * @see {@link useBlockingInfo} to get detailed information about active blockers\n *\n * @public\n * @since 0.6.0\n */\nexport function useIsBlocked(scope?: string | ReadonlyArray<string>): boolean {\n return useResolvedValue((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 { useResolvedValue } from \"../../context\";\nimport { createBlockerConfig } from \"../useBlocker\";\nimport { useConfigRef } from \"../useConfigRef\";\nimport { ScheduledBlockerConfig } from \"./useScheduledBlocker.types\";\nimport {\n calculateEndTime,\n isInBlockingPeriod,\n isSafeTimeout,\n isScheduleInPast,\n isValidTimestamp,\n parseDate,\n} from \"./useScheduledBlocker.utils\";\n\n/**\n * Schedules UI blocking for a specific time period (e.g., maintenance windows).\n *\n * Automatically blocks UI between specified start and end times. Useful for\n * scheduled maintenance, planned downtime, or time-based feature restrictions.\n * Supports callbacks when the blocking period starts and ends.\n *\n * Time specifications support:\n * - Date objects\n * - ISO 8601 strings (e.g., \"2024-01-15T10:00:00Z\")\n * - Unix timestamps (milliseconds since epoch)\n *\n * You can specify the end time either as an absolute time or as a duration\n * from the start time. If both are provided, duration takes precedence.\n *\n * Works with both the global store and isolated provider instances (via UIBlockingProvider).\n *\n * @param blockerId - Unique identifier for this scheduled blocker\n * @param config - Schedule configuration\n * @param config.schedule - Schedule timing configuration\n * @param config.schedule.start - When to start blocking (Date, ISO string, or timestamp)\n * @param config.schedule.end - Optional absolute end time (Date, ISO string, or timestamp)\n * @param config.schedule.duration - Optional duration in milliseconds from start time\n * @param config.scope - Scope(s) to block during the scheduled period\n * @param config.reason - Reason for blocking (displayed to users)\n * @param config.priority - Optional blocker priority (0-100)\n * @param config.onScheduleStart - Optional callback when blocking period starts\n * @param config.onScheduleEnd - Optional callback when blocking period ends\n *\n * @example\n * Maintenance window with absolute times\n * ```tsx\n * function MaintenanceWarning() {\n * useScheduledBlocker('maintenance', {\n * schedule: {\n * start: new Date('2024-01-15T02:00:00Z'),\n * end: new Date('2024-01-15T04:00:00Z'),\n * },\n * scope: 'global',\n * reason: 'System maintenance in progress',\n * priority: 95,\n * onScheduleStart: () => {\n * console.log('Maintenance started');\n * showNotification('System is now in maintenance mode');\n * },\n * onScheduleEnd: () => {\n * console.log('Maintenance completed');\n * showNotification('System is back online');\n * }\n * });\n *\n * return <div>...</div>;\n * }\n * ```\n *\n * @example\n * Short maintenance with duration\n * ```tsx\n * useScheduledBlocker('quick-maintenance', {\n * schedule: {\n * start: new Date('2024-01-15T03:00:00'),\n * duration: 15 * 60 * 1000, // 15 minutes\n * },\n * scope: ['api', 'forms'],\n * reason: 'Brief system update',\n * priority: 90\n * });\n * ```\n *\n * @example\n * Business hours enforcement\n * ```tsx\n * function BusinessHoursBlocker() {\n * const now = new Date();\n * const tomorrow9AM = new Date(now);\n * tomorrow9AM.setDate(now.getDate() + 1);\n * tomorrow9AM.setHours(9, 0, 0, 0);\n *\n * useScheduledBlocker('after-hours', {\n * schedule: {\n * start: new Date(now.getTime() + 1000), // Start immediately\n * end: tomorrow9AM,\n * },\n * scope: 'trading',\n * reason: 'Trading is only available during business hours (9 AM - 5 PM)',\n * priority: 85\n * });\n *\n * return <TradingDashboard />;\n * }\n * ```\n *\n * @example\n * Using ISO strings for scheduling\n * ```tsx\n * useScheduledBlocker('deployment', {\n * schedule: {\n * start: '2024-01-20T00:00:00Z',\n * duration: 2 * 60 * 60 * 1000, // 2 hours\n * },\n * scope: 'global',\n * reason: 'Deploying new version',\n * priority: 100,\n * onScheduleStart: () => {\n * analytics.track('deployment_started');\n * },\n * onScheduleEnd: () => {\n * analytics.track('deployment_completed');\n * window.location.reload(); // Reload to get new version\n * }\n * });\n * ```\n *\n * @see {@link useBlocker} for immediate blocking without scheduling\n * @see {@link useConditionalBlocker} for condition-based blocking\n * @see {@link ScheduledBlockerConfig} for configuration options\n * @see {@link BlockingSchedule} for schedule specification details\n *\n * @public\n * @since 0.6.0\n */\nexport function useScheduledBlocker(blockerId: string, config: ScheduledBlockerConfig): void {\n const { addBlocker, removeBlocker } = useResolvedValue((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 scheduleStart = parseDate(config.schedule.start);\n const scheduleEnd =\n config.schedule.end === undefined ? undefined : parseDate(config.schedule.end);\n const scheduleDuration = config.schedule.duration;\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 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 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 return;\n }\n }\n\n return (): void => {\n cleanup();\n removeBlocker(blockerId);\n };\n }, [\n blockerId,\n addBlocker,\n removeBlocker,\n cleanup,\n scheduleStart,\n scheduleEnd,\n scheduleDuration,\n configRef,\n ]);\n}\n","import { AnalyticsEventData } from \"./analyticsMiddleware.types\";\nimport { MiddlewareContext } from \"./middleware.types\";\n\nfunction capitalizeFirst(str: string): string {\n return str.charAt(0).toUpperCase() + str.slice(1);\n}\n\nfunction getAnalyticsWindow(): Window | undefined {\n if (typeof window === \"undefined\") {\n return undefined;\n }\n\n return window;\n}\n\nexport function 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 function trackGoogleAnalytics(action: string, eventData: AnalyticsEventData): void {\n const analyticsWindow = getAnalyticsWindow();\n\n if (analyticsWindow?.gtag) {\n analyticsWindow.gtag(\"event\", `ui_blocking_${action}`, eventData);\n }\n}\n\nexport function trackMixpanel(action: string, eventData: AnalyticsEventData): void {\n const analyticsWindow = getAnalyticsWindow();\n\n if (analyticsWindow?.mixpanel) {\n const eventName = `UI Blocking ${action.split(\"_\").map(capitalizeFirst).join(\" \")}`;\n\n analyticsWindow.mixpanel.track(eventName, eventData);\n }\n}\n\nexport function trackAmplitude(action: string, eventData: AnalyticsEventData): void {\n const analyticsWindow = getAnalyticsWindow();\n\n if (analyticsWindow?.amplitude) {\n const eventName = `UI Blocking ${action.split(\"_\").map(capitalizeFirst).join(\" \")}`;\n\n analyticsWindow.amplitude.track(eventName, eventData);\n }\n}\n\nexport function 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\n/**\n * Helper function to track events based on analytics configuration.\n * @internal\n */\nfunction 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\n/**\n * Creates middleware for tracking blocker events to analytics platforms.\n *\n * Automatically tracks all blocker actions (add, remove, update, timeout, clear)\n * to your analytics platform. Supports Google Analytics, Mixpanel, Amplitude,\n * and custom analytics providers.\n *\n * Event data includes: blockerId, action, scope, reason, priority, timestamp,\n * and duration (for remove events).\n *\n * @param config - Analytics configuration specifying provider and credentials\n *\n * @example\n * Google Analytics integration\n * ```ts\n * import { configureMiddleware, createAnalyticsMiddleware } from '@okyrychenko-dev/react-action-guard';\n *\n * const analyticsMiddleware = createAnalyticsMiddleware({\n * provider: 'ga',\n * trackingId: 'GA-XXXXX-Y'\n * });\n *\n * configureMiddleware([analyticsMiddleware]);\n * ```\n *\n * @example\n * Mixpanel integration\n * ```ts\n * const analyticsMiddleware = createAnalyticsMiddleware({\n * provider: 'mixpanel',\n * token: 'your_mixpanel_token',\n * options: {\n * debug: true\n * }\n * });\n *\n * configureMiddleware([analyticsMiddleware]);\n * ```\n *\n * @example\n * Custom analytics provider\n * ```ts\n * const analyticsMiddleware = createAnalyticsMiddleware({\n * track: (eventName, eventData) => {\n * // Send to your custom analytics\n * myAnalytics.track(eventName, {\n * ...eventData,\n * userId: getCurrentUserId()\n * });\n * }\n * });\n * ```\n *\n * @example\n * Amplitude with user properties\n * ```ts\n * const analyticsMiddleware = createAnalyticsMiddleware({\n * provider: 'amplitude',\n * apiKey: 'your_amplitude_key',\n * userId: 'user-123',\n * userProperties: {\n * plan: 'premium',\n * role: 'admin'\n * }\n * });\n * ```\n *\n * @see {@link AnalyticsConfig} for configuration options\n * @see {@link configureMiddleware} for registering middleware\n *\n * @public\n * @since 0.6.0\n */\nexport function 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\nconst CONFIGURE_MIDDLEWARE_PREFIX = \"middleware-\";\n\n/**\n * Configures and registers multiple middleware functions for the UI blocking store.\n *\n * Convenience function that registers an array of middleware at once. Each middleware\n * is automatically assigned a unique name based on its array index (\"middleware-0\",\n * \"middleware-1\", etc.). Middleware are executed in the order they are registered.\n *\n * All middleware receive {@link MiddlewareContext} containing action type, blocker ID,\n * configuration, and timestamp for each blocking event.\n *\n * @param middlewares - Array of middleware functions to register. Functions are called\n * in order for each blocking action (add, remove, update, etc.)\n *\n * @example\n * Basic usage with built-in middleware\n * ```ts\n * import { configureMiddleware, loggerMiddleware, createPerformanceMiddleware } from '@okyrychenko-dev/react-action-guard';\n *\n * configureMiddleware([\n * loggerMiddleware,\n * createPerformanceMiddleware({ threshold: 1000 })\n * ]);\n * ```\n *\n * @example\n * With custom middleware\n * ```ts\n * const customMiddleware: Middleware = (context) => {\n * if (context.action === 'add') {\n * console.log(`Blocker added: ${context.blockerId}`);\n * }\n * };\n *\n * configureMiddleware([\n * loggerMiddleware,\n * customMiddleware\n * ]);\n * ```\n *\n * @example\n * Analytics integration\n * ```ts\n * import { configureMiddleware, createAnalyticsMiddleware } from '@okyrychenko-dev/react-action-guard';\n *\n * configureMiddleware([\n * createAnalyticsMiddleware({\n * provider: 'google-analytics',\n * trackingId: 'GA-XXXXX'\n * })\n * ]);\n * ```\n *\n * @see {@link Middleware} for middleware function signature\n * @see {@link loggerMiddleware} for built-in logging middleware\n * @see {@link createAnalyticsMiddleware} for analytics tracking\n * @see {@link createPerformanceMiddleware} for performance monitoring\n *\n * @public\n * @since 0.6.0\n */\nexport function configureMiddleware(middlewares: ReadonlyArray<Middleware>): void {\n const store = uiBlockingStoreApi.getState();\n\n // Remove middleware registered by previous configureMiddleware calls.\n // Keep provider-level middlewares intact.\n store.middlewares.forEach((_, name) => {\n if (name.startsWith(CONFIGURE_MIDDLEWARE_PREFIX)) {\n store.unregisterMiddleware(name);\n }\n });\n\n middlewares.forEach((middleware, index) => {\n // Generate a unique name for each middleware\n const name = `${CONFIGURE_MIDDLEWARE_PREFIX}${index.toString()}`;\n store.registerMiddleware(name, middleware);\n });\n}\n","import { MiddlewareBlockerConfig, MiddlewareContext } from \"./middleware.types\";\n\nexport function getActionEmoji(action: string): string {\n switch (action) {\n case \"add\":\n return \"โž•\";\n case \"update\":\n return \"๐Ÿ”„\";\n case \"remove\":\n return \"โž–\";\n case \"timeout\":\n return \"โฑ๏ธ\";\n case \"clear\":\n return \"๐Ÿงน\";\n case \"clear_scope\":\n return \"๐ŸŽฏ\";\n default:\n return \"โ“\";\n }\n}\n\nfunction 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 function formatLogData(context: MiddlewareContext): Record<string, unknown> {\n const configDetails = extractConfigDetails(context.config);\n\n const logData: Record<string, unknown> = {};\n\n // Add scope for clear_scope action\n if (context.scope !== undefined) {\n logData.scope = context.scope;\n }\n\n // Add count for clear actions\n if (context.count !== undefined) {\n logData.count = context.count;\n }\n\n // Add config details\n if (Object.keys(configDetails).length > 0) {\n logData.config = configDetails;\n }\n\n // Add previous state if present\n if (context.prevState) {\n logData.prevState = extractConfigDetails(context.prevState);\n }\n\n // Return config details directly if no special fields\n if (Object.keys(logData).length === 0) {\n return configDetails;\n }\n\n return Object.keys(logData).length === 1 && logData.config ? configDetails : logData;\n}\n","import { formatLogData, getActionEmoji } from \"./loggerMiddleware.utils\";\nimport { MiddlewareContext } from \"./middleware.types\";\n\nconst LOG_PREFIX = \"[UIBlocking]\";\n\n/**\n * Built-in middleware for logging all blocking actions to the console.\n *\n * Logs every blocker action (add, remove, update, timeout, clear) with emoji\n * indicators and formatted data. Useful for debugging blocking behavior during\n * development. Register it conditionally when production logging is not desired.\n *\n * Output format: `[UIBlocking] ๐Ÿ”’ blocker-id {scope: \"form\", reason: \"...\"}`\n *\n * Emoji indicators:\n * - ๐Ÿ”’ Add\n * - ๐Ÿ”“ Remove\n * - ๐Ÿ”„ Update\n * - โฐ Timeout\n * - ๐Ÿงน Clear/ClearScope\n *\n * @example\n * Register logger middleware\n * ```ts\n * import { configureMiddleware, loggerMiddleware } from '@okyrychenko-dev/react-action-guard';\n *\n * // Enable logging for all blocking actions\n * configureMiddleware([loggerMiddleware]);\n * ```\n *\n * @example\n * Console output examples\n * ```\n * [UIBlocking] ๐Ÿ”’ save-form {scope: \"form\", reason: \"Saving...\", priority: 50}\n * [UIBlocking] ๐Ÿ”„ save-form {scope: \"form\", reason: \"Almost done...\"}\n * [UIBlocking] ๐Ÿ”“ save-form {reason: \"Saving...\"}\n * [UIBlocking] โฐ api-timeout {timeout: 30000}\n * ```\n *\n * @example\n * Production check pattern\n * ```ts\n * import { configureMiddleware, loggerMiddleware } from '@okyrychenko-dev/react-action-guard';\n * const middlewares = [];\n * if (process.env.NODE_ENV !== 'production') {\n * middlewares.push(loggerMiddleware);\n * }\n * configureMiddleware(middlewares);\n * ```\n *\n * @see {@link configureMiddleware} for registering middleware\n * @see {@link Middleware} for middleware function signature\n * @see {@link MiddlewareContext} for available context data\n *\n * @public\n * @since 0.6.0\n */\nexport function loggerMiddleware(context: MiddlewareContext): void {\n const emoji = getActionEmoji(context.action);\n const logData = formatLogData(context);\n\n console.log(LOG_PREFIX, emoji, context.blockerId, logData);\n}\n","export function 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\n/**\n * Helper function to handle blocker removal and duration tracking.\n * @internal\n */\nfunction 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 onSlowBlock?.(context.blockerId, duration);\n }\n}\n\n/**\n * Creates middleware for monitoring blocker performance and detecting slow blocks.\n *\n * Tracks the duration of each blocker (from add to remove) and invokes an optional\n * callback when a blocker exceeds the configured threshold. Useful for identifying\n * performance issues, stuck blockers, or operations that take too long.\n *\n * The middleware is side-effect free by default; use `onSlowBlock` for custom\n * reporting, logging, or analytics integration.\n *\n * @param config - Performance monitoring configuration\n * @param config.slowBlockThreshold - Duration in ms before considering a block \"slow\".\n * Defaults to 3000ms (3 seconds).\n * @param config.onSlowBlock - Optional callback invoked when a slow block is detected.\n * Receives blockerId and duration in milliseconds.\n *\n * @returns Middleware function for performance monitoring\n *\n * @example\n * Basic usage with default threshold\n * ```ts\n * import { configureMiddleware, createPerformanceMiddleware } from '@okyrychenko-dev/react-action-guard';\n *\n * const performanceMiddleware = createPerformanceMiddleware();\n *\n * configureMiddleware([performanceMiddleware]);\n * // Track slow blocks via onSlowBlock if any blocker lasts > 3 seconds\n * ```\n *\n * @example\n * Custom threshold and callback\n * ```ts\n * const performanceMiddleware = createPerformanceMiddleware({\n * slowBlockThreshold: 5000, // 5 seconds\n * onSlowBlock: (blockerId, duration) => {\n * console.error(`Blocker ${blockerId} took ${duration}ms`);\n *\n * // Report to error tracking\n * Sentry.captureMessage('Slow UI Blocker', {\n * extra: { blockerId, duration }\n * });\n * }\n * });\n * ```\n *\n * @example\n * With analytics integration\n * ```ts\n * const performanceMiddleware = createPerformanceMiddleware({\n * slowBlockThreshold: 2000,\n * onSlowBlock: (blockerId, duration) => {\n * // Track slow blocks in analytics\n * analytics.track('slow_blocker_detected', {\n * blocker_id: blockerId,\n * duration_ms: duration,\n * threshold_ms: 2000\n * });\n * }\n * });\n * ```\n *\n * @example\n * Development vs Production\n * ```ts\n * const performanceMiddleware = createPerformanceMiddleware({\n * // Strict threshold in development\n * slowBlockThreshold: process.env.NODE_ENV === 'production' ? 5000 : 1000,\n * onSlowBlock: (blockerId, duration) => {\n * if (process.env.NODE_ENV === 'production') {\n * // Report to error service in production\n * errorService.log({ blockerId, duration });\n * } else {\n * // Detailed logging in development\n * console.table({ blockerId, duration });\n * }\n * }\n * });\n * ```\n *\n * @see {@link PerformanceConfig} for configuration options\n * @see {@link configureMiddleware} for registering middleware\n *\n * @public\n * @since 0.6.0\n */\nexport function 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","import { type UseAsyncActionOptions, useAsyncAction } from \"./hooks/useAsyncAction\";\nimport { useBlocker } from \"./hooks/useBlocker\";\nimport { useBlockingInfo } from \"./hooks/useBlockingInfo\";\nimport { useIsBlocked } from \"./hooks/useIsBlocked\";\nimport type { BlockerConfigTyped, ScopeValue } from \"./types\";\n\n/**\n * Return type for createTypedHooks factory\n */\nexport interface TypedHooks<TScope extends string> {\n /**\n * Type-safe version of useBlocker hook\n */\n useBlocker: (blockerId: string, config: BlockerConfigTyped<TScope>, isActive?: boolean) => void;\n\n /**\n * Type-safe version of useIsBlocked hook\n */\n useIsBlocked: (scope?: ScopeValue<TScope>) => boolean;\n\n /**\n * Type-safe version of useAsyncAction hook\n */\n useAsyncAction: <T = unknown>(\n actionId: string,\n scope?: ScopeValue<TScope>,\n options?: UseAsyncActionOptions\n ) => (asyncFn: () => Promise<T>) => Promise<T>;\n\n /**\n * Type-safe version of useBlockingInfo hook\n */\n useBlockingInfo: (scope: TScope) => ReturnType<typeof useBlockingInfo>;\n}\n\n/**\n * Creates type-safe versions of all blocking hooks with your custom scope types\n *\n * @template TScope - Union type of allowed scope strings\n * @returns Object with type-safe hook functions\n *\n * @example\n * ```typescript\n * // Define your app's scopes\n * type AppScopes = \"global\" | \"form\" | \"navigation\" | \"checkout\";\n *\n * // Create typed hooks\n * const { useBlocker, useIsBlocked, useAsyncAction } = createTypedHooks<AppScopes>();\n *\n * // Now TypeScript will catch typos\n * useBlocker(\"id\", { scope: \"form\" }); // โœ“ OK\n * useBlocker(\"id\", { scope: \"typo\" }); // โœ— Type error!\n * ```\n */\nexport function createTypedHooks<TScope extends string>(): TypedHooks<TScope> {\n // TScope extends string, so all typed scopes are assignable to string | ReadonlyArray<string>\n // This allows us to pass typed values directly without casting\n return {\n useBlocker: (blockerId, config, isActive) => {\n // BlockerConfigTyped<TScope> is structurally compatible with BlockerConfig\n // because TScope extends string\n useBlocker(blockerId, config, isActive);\n },\n\n useIsBlocked: (scope) => {\n // ScopeValue<TScope> = TScope | ReadonlyArray<TScope>\n // Since TScope extends string, this is assignable to string | ReadonlyArray<string>\n return useIsBlocked(scope);\n },\n\n useAsyncAction: <T = unknown>(\n actionId: string,\n scope?: ScopeValue<TScope>,\n options?: UseAsyncActionOptions\n ) => {\n return useAsyncAction<T>(actionId, scope, options);\n },\n\n useBlockingInfo: (scope) => useBlockingInfo(scope),\n };\n}\n","import {\n UIBlockingProvider,\n useIsInsideUIBlockingProvider,\n useOptionalUIBlockingContext,\n useResolvedStoreApi,\n useResolvedValue,\n useUIBlockingContext,\n useUIBlockingStoreFromContext,\n} from \"./context\";\nimport type { StoreApi } from \"zustand\";\nimport type { UIBlockingStore } from \"./store/uiBlockingStore.types\";\n\n// Core hooks\nexport {\n useAsyncAction,\n useBlocker,\n useBlockingInfo,\n useConditionalBlocker,\n useConfirmableBlocker,\n useIsBlocked,\n useScheduledBlocker,\n} from \"./hooks\";\n\n// Hook types\nexport type {\n BlockingSchedule,\n ConditionalBlockerConfig,\n ConfirmableBlockerConfig,\n ConfirmDialogConfig,\n ScheduledBlockerConfig,\n UseAsyncActionOptions,\n UseConfirmableBlockerReturn,\n} from \"./hooks\";\n\n// Store\nexport { useUIBlockingStore, uiBlockingStoreApi } from \"./store/uiBlockingStore.store\";\nexport type { ShallowStoreBindings } from \"./store/uiBlockingStore.types\";\n\n// Store types\nexport type {\n BlockerConfig,\n BlockerInfo,\n StoredBlocker,\n UIBlockingStore,\n UIBlockingStoreActions,\n UIBlockingStoreState,\n} from \"./store/uiBlockingStore.types\";\n\n// Middleware\nexport {\n type AmplitudeConfig,\n type AnalyticsConfig,\n type AnalyticsEventData,\n type AnalyticsProvider,\n type BlockingAction,\n configureMiddleware,\n createAnalyticsMiddleware,\n createPerformanceMiddleware,\n type CustomAnalyticsConfig,\n type GoogleAnalyticsConfig,\n loggerMiddleware,\n type Middleware,\n type MiddlewareContext,\n type MixpanelConfig,\n type PerformanceConfig,\n} from \"./middleware\";\n\n// Type-safe scope utilities\nexport { createTypedHooks, type TypedHooks } from \"./createTypedHooks\";\nexport type { BlockerConfigTyped, DefaultScopes, ScopeValue } from \"./types\";\n\n// Context / Provider\nexport {\n UIBlockingProvider,\n useIsInsideUIBlockingProvider,\n useOptionalUIBlockingContext,\n useResolvedStoreApi,\n useResolvedValue,\n useUIBlockingContext,\n useUIBlockingStoreFromContext,\n};\nexport type { UIBlockingProviderProps } from \"./context\";\n\n/**\n * @deprecated Use `useOptionalUIBlockingContext`.\n */\nexport function useOptionalContext(): ReturnType<typeof useOptionalUIBlockingContext> {\n return useOptionalUIBlockingContext();\n}\n\n/**\n * @deprecated Use `useResolvedStoreApi`.\n */\nexport function useResolvedStore(): StoreApi<UIBlockingStore> {\n return useResolvedStoreApi();\n}\n\n/**\n * @deprecated Use `useResolvedValue`.\n */\nexport function useResolvedStoreWithSelector<T>(selector: (state: UIBlockingStore) => T): T {\n return useResolvedValue(selector);\n}\n"]}
1
+ {"version":3,"sources":["../src/store/scope/scope.constants.ts","../src/store/scope/scope.utils.ts","../src/store/blockingInfo/blockingInfo.utils.ts","../src/store/uiBlockingStore.constants.ts","../src/store/blockingLifecycle/blockingLifecycle.utils.ts","../src/store/blockingLifecycle/blockingLifecycle.ts","../src/store/uiBlockingStore.actions.ts","../src/context/UIBlockingContext.tsx","../src/store/uiBlockingStore.config.ts","../src/store/uiBlockingStore.store.ts","../src/context/useResolvedStore.ts","../src/context/index.ts","../src/store/blockerId.utils.ts","../src/hooks/useBlockerIdAllocator/useBlockerIdAllocator.ts","../src/hooks/useAsyncAction/useAsyncAction.ts","../src/hooks/useConfigRef.ts","../src/hooks/useActionBlocker/useActionBlocker.utils.ts","../src/hooks/useActionBlocker/useBlockerRegistration.ts","../src/hooks/useActionBlocker/useActionBlocker.ts","../src/hooks/useBlockingInfo/useBlockingInfo.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","../src/createTypedHooks.ts"],"names":["isDefined","isUndefined","isString","isReadonlyArray","isNonEmptyArray","event","replace","update","next","isFunction","devtools","createStoreProvider","createShallowStore","createResolvedStoreHooks","useCallback","allocateBlockerId","useRef","useEffect","shallow","useMemo","isNull","useState","scheduleEnd","now","isArray"],"mappings":"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","file":"index.cjs","sourcesContent":["export const DEFAULT_SCOPE = \"global\" as const;\n","import {\n type Optional,\n isDefined,\n isNonEmptyArray,\n isReadonlyArray,\n isString,\n isUndefined,\n} from \"@okyrychenko-dev/type-utils\";\nimport { DEFAULT_SCOPE } from \"./scope.constants\";\nimport type { Scope } from \"./scope.types\";\n\nconst normalizedScopeCache = new Map<string, ReadonlyArray<string>>();\nconst NORMALIZED_SCOPE_CACHE_MAX_SIZE = 256;\n\nfunction getNormalizedScopeCacheKey(scopes: ReadonlyArray<string>): string {\n return JSON.stringify(scopes);\n}\n\nfunction refreshNormalizedScopeCacheEntry(\n cacheKey: string,\n scopes: ReadonlyArray<string>\n): ReadonlyArray<string> {\n normalizedScopeCache.delete(cacheKey);\n normalizedScopeCache.set(cacheKey, scopes);\n\n return scopes;\n}\n\nfunction evictOldestNormalizedScopeCacheEntry(): void {\n for (const cacheKey of normalizedScopeCache.keys()) {\n normalizedScopeCache.delete(cacheKey);\n break;\n }\n}\n\nfunction getCachedNormalizedScope(scopes: ReadonlyArray<string>): ReadonlyArray<string> {\n const normalizedScope = Object.freeze([...new Set(scopes)].sort());\n const cacheKey = getNormalizedScopeCacheKey(normalizedScope);\n const cachedScope = normalizedScopeCache.get(cacheKey);\n\n if (isDefined(cachedScope)) {\n return refreshNormalizedScopeCacheEntry(cacheKey, cachedScope);\n }\n\n normalizedScopeCache.set(cacheKey, normalizedScope);\n\n if (normalizedScopeCache.size > NORMALIZED_SCOPE_CACHE_MAX_SIZE) {\n evictOldestNormalizedScopeCacheEntry();\n }\n\n return normalizedScope;\n}\n\n/**\n * Returns a frozen, stable, deduplicated, sorted scope list.\n * An omitted scope means global; an empty list remains empty.\n */\nexport function normalizeScope(scope?: Scope): ReadonlyArray<string> {\n if (isUndefined(scope)) {\n return getCachedNormalizedScope([DEFAULT_SCOPE]);\n }\n\n if (isString(scope)) {\n return getCachedNormalizedScope([scope]);\n }\n\n return getCachedNormalizedScope(scope);\n}\n\n/**\n * Resolves guarded-control inheritance.\n * An omitted or empty explicit scope inherits; any non-empty explicit scope wins.\n */\nexport function resolveScope(explicitScope?: Scope, inheritedScope?: Scope): Optional<Scope> {\n if (\n isUndefined(explicitScope) ||\n (isReadonlyArray(explicitScope) && !isNonEmptyArray(explicitScope))\n ) {\n return inheritedScope;\n }\n\n return explicitScope;\n}\n\nfunction matchesObservedScopes(\n blockerScope: Scope,\n observedScopes: ReadonlyArray<string>\n): boolean {\n if (!isNonEmptyArray(observedScopes)) {\n return false;\n }\n\n if (isString(blockerScope)) {\n return blockerScope === DEFAULT_SCOPE || observedScopes.includes(blockerScope);\n }\n\n return (\n blockerScope.includes(DEFAULT_SCOPE) ||\n observedScopes.some((scope) => blockerScope.includes(scope))\n );\n}\n\n/**\n * Checks ordinary observation semantics.\n * A global blocker affects every observed scope and otherwise any shared scope is a match.\n */\nexport function scopeAffectsObservation(blockerScope: Scope, observedScope: Scope): boolean {\n return matchesObservedScopes(blockerScope, normalizeScope(observedScope));\n}\n\n/** @internal Prepare one observation without repeatedly normalizing every blocker. */\nexport function createScopeObservationMatcher(\n observedScope: Scope\n): (blockerScope: Scope) => boolean {\n const observedScopes = normalizeScope(observedScope);\n\n return (blockerScope) => matchesObservedScopes(blockerScope, observedScopes);\n}\n\n/**\n * Checks targeted-clear semantics.\n * Global blockers never match a target, including the global target; otherwise any shared scope\n * is a match.\n */\nexport function scopeMatchesTarget(blockerScope: Scope, targetScope: Scope): boolean {\n const blockerScopes = normalizeScope(blockerScope);\n\n if (blockerScopes.includes(DEFAULT_SCOPE)) {\n return false;\n }\n\n const targetScopes = normalizeScope(targetScope);\n\n return targetScopes.some((scope) => blockerScopes.includes(scope));\n}\n","import { type Optional, isDefined, isString } from \"@okyrychenko-dev/type-utils\";\nimport { createScopeObservationMatcher } from \"../scope\";\nimport type { BlockingLifecycleSnapshot } from \"../blockingLifecycle\";\nimport type { Scope } from \"../scope\";\nimport type { BlockerInfo, UIBlockingStore } from \"../uiBlockingStore.types\";\n\nfunction sameScope(first: Scope, second: Scope): boolean {\n if (first === second) {\n return true;\n }\n if (isString(first) || isString(second)) {\n return false;\n }\n\n return first.length === second.length && first.every((scope, index) => scope === second[index]);\n}\n\nfunction sameBlocker(first: BlockerInfo, second: BlockerInfo): boolean {\n if (first === second) {\n return true;\n }\n\n const { id, scope, reason, priority, timestamp, timeout, onTimeout } = first;\n const {\n id: previousId,\n scope: previousScope,\n reason: previousReason,\n priority: previousPriority,\n timestamp: previousTimestamp,\n timeout: previousTimeout,\n onTimeout: previousOnTimeout,\n } = second;\n\n return (\n id === previousId &&\n sameScope(scope, previousScope) &&\n reason === previousReason &&\n priority === previousPriority &&\n timestamp === previousTimestamp &&\n timeout === previousTimeout &&\n onTimeout === previousOnTimeout\n );\n}\n\nexport function areBlockingInfosEqual(\n first: BlockingLifecycleSnapshot,\n second: BlockingLifecycleSnapshot\n): boolean {\n return (\n first === second ||\n (first.length === second.length &&\n first.every((blocker, index) => {\n const previous = second[index];\n\n return isDefined(previous) && sameBlocker(blocker, previous);\n }))\n );\n}\n\nfunction matchingBlockers(\n snapshot: BlockingLifecycleSnapshot,\n matchesScope: ReturnType<typeof createScopeObservationMatcher>\n): Array<BlockerInfo> {\n return snapshot.filter(({ scope }) => matchesScope(scope));\n}\n\nfunction orderedBlockers(blockers: Array<BlockerInfo>): BlockingLifecycleSnapshot {\n return Object.freeze(\n blockers.sort(({ priority: first }, { priority: second }) => second - first)\n );\n}\n\nexport function projectBlockingInfo(\n snapshot: BlockingLifecycleSnapshot,\n scope: Scope\n): BlockingLifecycleSnapshot {\n const matchesScope = createScopeObservationMatcher(scope);\n\n return orderedBlockers(matchingBlockers(snapshot, matchesScope));\n}\n\n/** One hook-owned last snapshot/projection; released with its selector, never cached globally. */\nexport function createBlockingInfoSelector(\n scope: Scope\n): (state: UIBlockingStore) => BlockingLifecycleSnapshot {\n const matchesScope = createScopeObservationMatcher(scope);\n let previousSnapshot: Optional<BlockingLifecycleSnapshot>;\n let previousMatches: ReadonlyArray<BlockerInfo> = [];\n let result: BlockingLifecycleSnapshot = Object.freeze([]);\n\n return ({ blockingSnapshot }) => {\n if (blockingSnapshot === previousSnapshot) {\n return result;\n }\n\n const matches = matchingBlockers(blockingSnapshot, matchesScope);\n const unchanged = areBlockingInfosEqual(matches, previousMatches);\n\n previousSnapshot = blockingSnapshot;\n\n if (!unchanged) {\n previousMatches = matches;\n result = orderedBlockers([...matches]);\n }\n\n return result;\n };\n}\n","/**\n * Default values and constants for UI Blocking Store\n */\n\nexport { DEFAULT_SCOPE } from \"./scope\";\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 { type Optional, isUndefined } from \"@okyrychenko-dev/type-utils\";\n\n/** Reject invalid delays before a registration or its existing timer is changed. */\nexport function validateTimeout(timeout: Optional<number>): void {\n if (isUndefined(timeout)) {\n return;\n }\n\n if (\n !Number.isFinite(timeout) ||\n (timeout > 0 && Date.now() + timeout > Number.MAX_SAFE_INTEGER)\n ) {\n throw new RangeError(\"Blocker timeout must be finite with a safely representable deadline\");\n }\n}\n","import { isDefined, isString, isUndefined } from \"@okyrychenko-dev/type-utils\";\nimport { projectBlockingInfo } from \"../blockingInfo\";\nimport { scopeAffectsObservation, scopeMatchesTarget } from \"../scope\";\nimport { DEFAULT_PRIORITY, DEFAULT_REASON, DEFAULT_SCOPE } from \"../uiBlockingStore.constants\";\nimport { validateTimeout } from \"./blockingLifecycle.utils\";\nimport type { Middleware } from \"../../middleware\";\nimport type { BlockerConfig, BlockerInfo } from \"../uiBlockingStore.types\";\nimport type {\n BlockingEvent,\n BlockingLifecycle,\n BlockingLifecycleSnapshot,\n PendingPublication,\n} from \"./blockingLifecycle.types\";\n\ninterface ActiveBlocker {\n registration: object;\n config: BlockerInfo;\n timeoutId?: ReturnType<typeof setTimeout>;\n}\n\nfunction copyScope(scope: string | ReadonlyArray<string>): string | ReadonlyArray<string> {\n return isString(scope) ? scope : Object.freeze([...scope]);\n}\n\nfunction publicConfig(blocker: BlockerInfo): BlockerConfig {\n const { scope, reason, priority, timestamp, timeout, onTimeout } = blocker;\n\n return { scope, reason, priority, timestamp, timeout, onTimeout };\n}\n\nfunction freezeBlocker(blocker: BlockerInfo): BlockerInfo {\n return Object.freeze({ ...blocker, scope: copyScope(blocker.scope) });\n}\n\nfunction normalizeBlocker(id: string, config: BlockerConfig): BlockerInfo {\n return {\n id,\n scope: copyScope(config.scope ?? DEFAULT_SCOPE),\n reason: config.reason ?? DEFAULT_REASON,\n priority: Math.max(0, config.priority ?? DEFAULT_PRIORITY),\n timestamp: config.timestamp ?? Date.now(),\n timeout: config.timeout,\n onTimeout: config.onTimeout,\n };\n}\n\n/** Owns one independent store's blockers, timers, snapshots, and transition events. */\nexport function createBlockingLifecycle(): BlockingLifecycle {\n const blockers = new Map<string, ActiveBlocker>();\n const subscribers = new Map<symbol, (snapshot: BlockingLifecycleSnapshot) => void>();\n const observers = new Map<symbol, Middleware>();\n const pendingPublications: Array<PendingPublication> = [];\n let snapshot: BlockingLifecycleSnapshot = Object.freeze([]);\n let isDelivering = false;\n\n function getSnapshot(): BlockingLifecycleSnapshot {\n return snapshot;\n }\n\n function deliverEvent(event: BlockingEvent): void {\n const eventObservers = [...observers];\n\n for (const [registration, observer] of eventObservers) {\n if (!observers.has(registration)) {\n continue;\n }\n\n try {\n void Promise.resolve(observer(event)).catch(() => undefined);\n } catch {\n // Diagnostics must never interrupt a lifecycle transition.\n }\n }\n }\n\n function drainPublications(): void {\n if (isDelivering) {\n return;\n }\n\n isDelivering = true;\n\n try {\n for (const publication of pendingPublications) {\n if (publication.kind === \"snapshot\") {\n for (const subscriber of subscribers.values()) {\n try {\n subscriber(publication.snapshot);\n } catch {\n // A subscriber cannot interrupt lifecycle transitions.\n }\n }\n\n if (publication.event) {\n deliverEvent(publication.event);\n }\n } else {\n deliverEvent(publication.event);\n }\n }\n } finally {\n pendingPublications.length = 0;\n isDelivering = false;\n }\n }\n\n function publish(transitionEvent?: BlockingEvent): void {\n snapshot = Object.freeze(Array.from(blockers.values(), ({ config }) => freezeBlocker(config)));\n // Keep reads current while delivering each transition's snapshot and event in order.\n pendingPublications.push({ kind: \"snapshot\", snapshot, event: transitionEvent });\n drainPublications();\n }\n\n function emit(event: BlockingEvent): void {\n pendingPublications.push({ kind: \"event\", event });\n drainPublications();\n }\n\n function event(action: BlockingEvent[\"action\"], blockerId: string): BlockingEvent {\n return { action, blockerId, timestamp: Date.now() };\n }\n\n function cancelTimeout(blocker: ActiveBlocker): void {\n if (isDefined(blocker.timeoutId)) {\n clearTimeout(blocker.timeoutId);\n }\n }\n\n function handleTimeout(id: string, blocker: ActiveBlocker): void {\n if (blockers.get(id) !== blocker) {\n return;\n }\n\n const { onTimeout } = blocker.config;\n\n try {\n onTimeout?.(id);\n } catch {\n // A user callback cannot prevent observation or cleanup.\n }\n\n const { registration } = blocker;\n const { scope, reason, priority, timeout: duration } = blocker.config;\n\n emit({\n ...event(\"timeout\", id),\n registration,\n config: { scope, reason, priority, timeout: duration },\n });\n\n if (blockers.get(id) === blocker) {\n remove(id);\n }\n }\n\n function scheduleTimeout(id: string, blocker: ActiveBlocker): void {\n const { timeout } = blocker.config;\n\n if (isUndefined(timeout) || timeout <= 0) {\n return;\n }\n\n let remaining = timeout;\n\n function scheduleChunk(): void {\n const delay = Math.min(remaining, 2_147_483_647);\n const startedAt = performance.now();\n\n blocker.timeoutId = setTimeout(() => {\n if (blockers.get(id) !== blocker) {\n return;\n }\n\n // A dispatched timer has completed its requested wait even if the\n // monotonic clock paused during sleep. Also count observable late delivery.\n remaining -= Math.max(delay, performance.now() - startedAt);\n\n if (remaining <= 0) {\n handleTimeout(id, blocker);\n\n return;\n }\n\n scheduleChunk();\n }, delay);\n }\n\n scheduleChunk();\n }\n\n function add(id: string, config: BlockerConfig = {}): void {\n validateTimeout(config.timeout);\n\n const previous = blockers.get(id);\n\n if (previous) {\n cancelTimeout(previous);\n }\n\n const blocker: ActiveBlocker = {\n config: normalizeBlocker(id, config),\n registration: Object.freeze({}),\n };\n\n blockers.set(id, blocker);\n\n scheduleTimeout(id, blocker);\n\n publish({\n ...event(\"add\", id),\n registration: blocker.registration,\n config: {\n scope: config.scope,\n reason: config.reason,\n priority: config.priority,\n timeout: config.timeout,\n },\n });\n }\n\n function applyUpdate(id: string, config: BlockerConfig, replace: boolean): void {\n const previous = blockers.get(id);\n\n if (!previous) {\n add(id, config);\n\n return;\n }\n\n const oldConfig = previous.config;\n let nextConfig: BlockerInfo;\n\n if (replace) {\n nextConfig = normalizeBlocker(id, {\n ...config,\n timestamp: config.timestamp ?? oldConfig.timestamp,\n });\n } else {\n nextConfig = {\n ...oldConfig,\n scope: copyScope(config.scope ?? oldConfig.scope),\n reason: config.reason ?? oldConfig.reason,\n priority: Math.max(0, config.priority ?? oldConfig.priority),\n timestamp: config.timestamp ?? oldConfig.timestamp,\n timeout: config.timeout ?? oldConfig.timeout,\n onTimeout: config.onTimeout ?? oldConfig.onTimeout,\n };\n }\n\n const timeoutChanged = nextConfig.timeout !== oldConfig.timeout;\n\n if (timeoutChanged) {\n validateTimeout(nextConfig.timeout);\n }\n\n let blocker = previous;\n\n if (timeoutChanged) {\n cancelTimeout(previous);\n blocker = { config: nextConfig, registration: previous.registration };\n } else {\n blocker.config = nextConfig;\n }\n\n blockers.set(id, blocker);\n\n if (timeoutChanged) {\n scheduleTimeout(id, blocker);\n }\n\n publish({\n ...event(\"update\", id),\n registration: blocker.registration,\n config: publicConfig(nextConfig),\n prevState: publicConfig(oldConfig),\n });\n }\n\n function update(id: string, config: Partial<BlockerConfig> = {}): void {\n applyUpdate(id, config, false);\n }\n\n function replace(id: string, config: BlockerConfig): void {\n applyUpdate(id, config, true);\n }\n\n function remove(id: string): void {\n const previous = blockers.get(id);\n\n if (previous) {\n cancelTimeout(previous);\n }\n\n blockers.delete(id);\n\n if (previous) {\n const config = publicConfig(previous.config);\n\n publish({\n ...event(\"remove\", id),\n registration: previous.registration,\n config,\n prevState: config,\n });\n } else {\n publish();\n }\n }\n\n function clear(): void {\n const count = blockers.size;\n\n for (const blocker of blockers.values()) {\n cancelTimeout(blocker);\n }\n\n blockers.clear();\n\n if (count > 0) {\n publish({ ...event(\"clear\", \"*\"), count });\n } else {\n publish();\n }\n }\n\n function clearScope(scope: string): void {\n let count = 0;\n\n for (const [id, blocker] of blockers) {\n if (scopeMatchesTarget(blocker.config.scope, scope)) {\n cancelTimeout(blocker);\n blockers.delete(id);\n count++;\n }\n }\n\n if (count > 0) {\n publish({ ...event(\"clear_scope\", \"*\"), scope, count });\n } else {\n publish();\n }\n }\n\n function isBlocked(scope: string | ReadonlyArray<string> = DEFAULT_SCOPE): boolean {\n for (const { config } of blockers.values()) {\n if (scopeAffectsObservation(config.scope, scope)) {\n return true;\n }\n }\n\n return false;\n }\n\n function getBlockingInfo(scope: string): BlockingLifecycleSnapshot {\n return projectBlockingInfo(getSnapshot(), scope);\n }\n\n function subscribe(listener: (snapshot: BlockingLifecycleSnapshot) => void): VoidFunction {\n const registration = Symbol();\n\n subscribers.set(registration, listener);\n\n return () => {\n subscribers.delete(registration);\n };\n }\n\n function observe(observer: Middleware): VoidFunction {\n const registration = Symbol();\n\n observers.set(registration, observer);\n\n return () => {\n observers.delete(registration);\n };\n }\n\n return {\n add,\n update,\n replace,\n remove,\n clear,\n clearScope,\n isBlocked,\n getBlockingInfo,\n getSnapshot,\n subscribe,\n observe,\n };\n}\n","import { isFunction } from \"@okyrychenko-dev/type-utils\";\nimport { devtools } from \"zustand/middleware\";\nimport { createBlockingLifecycle } from \"./blockingLifecycle\";\nimport type { DevtoolsOptions } from \"zustand/middleware\";\nimport type { BlockingLifecycle } from \"./blockingLifecycle\";\nimport type {\n BlockingStateCreator,\n DevtoolsStoreMutators,\n LifecycleActionsCreator,\n LifecycleEnhancedCreator,\n StoreMutatorStack,\n StoreUpdateArgs,\n} from \"./uiBlockingStore.actions.types\";\n\nfunction createActions(lifecycle: BlockingLifecycle): LifecycleActionsCreator {\n return () => ({\n blockingSnapshot: lifecycle.getSnapshot(),\n observeBlockingEvents: lifecycle.observe,\n addBlocker: lifecycle.add,\n updateBlocker: lifecycle.update,\n replaceBlocker: lifecycle.replace,\n removeBlocker: lifecycle.remove,\n clearAllBlockers: lifecycle.clear,\n clearBlockersForScope: lifecycle.clearScope,\n isBlocked: lifecycle.isBlocked,\n getBlockingInfo: lifecycle.getBlockingInfo,\n });\n}\n\n/** Publish lifecycle snapshots through Zustand; external writes cannot replace the projection. */\nfunction createLifecycleStateCreator<TMutators extends StoreMutatorStack>(\n enhance: LifecycleEnhancedCreator<TMutators>\n): BlockingStateCreator<TMutators> {\n return (set, get, api) => {\n const lifecycle = createBlockingLifecycle();\n\n function setWithLifecycle(...args: StoreUpdateArgs): void {\n const current = get();\n\n if (args[1] === true) {\n const [update] = args;\n const next = isFunction(update) ? update(current) : update;\n\n if (!Object.is(next, current)) {\n set({ ...next, blockingSnapshot: lifecycle.getSnapshot() }, true);\n }\n\n return;\n }\n\n const [update] = args;\n const next = isFunction(update) ? update(current) : update;\n\n if (!Object.is(next, current)) {\n set({ ...next, blockingSnapshot: lifecycle.getSnapshot() });\n }\n }\n api.setState = setWithLifecycle;\n lifecycle.subscribe((blockingSnapshot) => {\n api.setState({ blockingSnapshot });\n });\n\n return enhance(lifecycle)(setWithLifecycle, get, api);\n };\n}\nexport const createUIBlockingActions = createLifecycleStateCreator(createActions);\nexport function createUIBlockingActionsWithDevtools(\n options: DevtoolsOptions\n): BlockingStateCreator<DevtoolsStoreMutators> {\n return createLifecycleStateCreator((lifecycle) => devtools(createActions(lifecycle), options));\n}\n","import { createStoreProvider } from \"@okyrychenko-dev/react-zustand-toolkit\";\nimport { type ReactNode } from \"react\";\nimport { type StoreApi } from \"zustand\";\nimport { createUIBlockingActions } from \"../store/uiBlockingStore.actions\";\nimport type { Middleware } from \"../middleware\";\nimport type { UIBlockingStore } from \"../store/uiBlockingStore.types\";\n\n/**\n * Props for the {@link UIBlockingProvider} component.\n *\n * Configures an isolated UI blocking store instance for a subtree of your app.\n * Useful for SSR, testing, micro-frontends, or any scenario where you need\n * independent blocking state.\n *\n * @public\n * @since 0.6.0\n */\nexport interface UIBlockingProviderProps {\n children: ReactNode;\n /** Initial middlewares to register */\n middlewares?: ReadonlyArray<Middleware>;\n}\n\n/**\n * Base provider implementation created using toolkit's createStoreProvider.\n * @internal\n */\nconst {\n Provider: BaseUIBlockingProvider,\n useContextStoreApi: useUIBlockingContext,\n useContextStore: baseUseUIBlockingStoreFromContext,\n useIsInsideProvider: useIsInsideUIBlockingProvider,\n useProviderStoreOptional: useOptionalUIBlockingContext,\n} = createStoreProvider<UIBlockingStore>(() => createUIBlockingActions, \"UIBlocking\");\n\nexport function useUIBlockingStoreFromContext(): UIBlockingStore;\nexport function useUIBlockingStoreFromContext<T>(\n selector: (state: UIBlockingStore) => T,\n equalityFn?: (a: T, b: T) => boolean\n): T;\nexport function useUIBlockingStoreFromContext<T>(\n selector?: (state: UIBlockingStore) => T,\n equalityFn?: (a: T, b: T) => boolean\n): T | UIBlockingStore {\n if (selector) {\n return baseUseUIBlockingStoreFromContext(selector, equalityFn);\n }\n\n return baseUseUIBlockingStoreFromContext();\n}\n\n/**\n * Provider component for isolated UI blocking state management.\n *\n * @public\n * @since 0.6.0\n * @see {@link useUIBlockingContext} to access the store from context\n * @see {@link useIsInsideUIBlockingProvider} to check if inside a provider\n * @see {@link UIBlockingProviderProps} for prop details\n */\nexport function UIBlockingProvider({\n children,\n middlewares = [],\n}: UIBlockingProviderProps): ReactNode {\n const handleStoreInit = (store: StoreApi<UIBlockingStore>): void => {\n const { observeBlockingEvents } = store.getState();\n\n middlewares.forEach((middleware) => {\n observeBlockingEvents(middleware);\n });\n };\n\n return (\n <BaseUIBlockingProvider input={undefined} onStoreInit={handleStoreInit}>\n {children}\n </BaseUIBlockingProvider>\n );\n}\n\n/**\n * Hook to access the store API from {@link UIBlockingProvider} context.\n * Returns the Zustand store API for the nearest UIBlockingProvider ancestor.\n * Throws an error if called outside a provider.\n * Use this when you need direct access to the store API (for subscribing,\n * getting state snapshots, etc.) rather than reactive hook access.\n *\n * @public\n * @since 0.6.0\n * @see {@link useUIBlockingStoreFromContext} for reactive hook access\n * @see {@link UIBlockingProvider} for provider setup\n */\n\n/**\n * Hook to access UI blocking store state from {@link UIBlockingProvider} context.\n * Works like {@link useUIBlockingStore} but uses the provider's isolated store\n * instead of the global store. Supports selective subscriptions for performance.\n *\n * @public\n * @since 0.6.0\n * @see {@link useUIBlockingContext} for store API access\n * @see {@link UIBlockingProvider} for provider setup\n */\n\n/**\n * Hook to check if the component is inside a {@link UIBlockingProvider}.\n * Returns true if the component is rendered within a UIBlockingProvider,\n * false otherwise. Useful for conditional logic or debugging.\n *\n * @public\n * @since 0.6.0\n * @see {@link UIBlockingProvider} for provider setup\n */\n\n// Export hooks from base provider\nexport {\n useUIBlockingContext,\n useIsInsideUIBlockingProvider,\n useOptionalUIBlockingContext,\n /** @deprecated Use `useOptionalUIBlockingContext`. */\n useOptionalUIBlockingContext as useOptionalContext,\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 { createShallowStore } from \"@okyrychenko-dev/react-zustand-toolkit\";\nimport { createUIBlockingActionsWithDevtools } from \"./uiBlockingStore.actions\";\nimport { devtoolsConfig } from \"./uiBlockingStore.config\";\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 storeBindings = createShallowStore<UIBlockingStore, [[\"zustand/devtools\", never]]>(\n createUIBlockingActionsWithDevtools(devtoolsConfig)\n);\n\nconst uiBlockingStoreApi = storeBindings.store;\n\nexport function useUIBlockingStore(): UIBlockingStore;\nexport function useUIBlockingStore<T>(\n selector: (state: UIBlockingStore) => T,\n equalityFn?: (a: T, b: T) => boolean\n): T;\nexport function useUIBlockingStore<T>(\n selector?: (state: UIBlockingStore) => T,\n equalityFn?: (a: T, b: T) => boolean\n): T | UIBlockingStore {\n if (selector) {\n return storeBindings.useStore(selector, equalityFn);\n }\n\n return storeBindings.useStore();\n}\nexport { uiBlockingStoreApi };\n","import { createResolvedStoreHooks } from \"@okyrychenko-dev/react-zustand-toolkit\";\nimport { uiBlockingStoreApi } from \"../store/uiBlockingStore.store\";\nimport { useOptionalUIBlockingContext } from \"./UIBlockingContext\";\nimport type { StoreApi } from \"zustand\";\nimport type { UIBlockingStore } from \"../store/uiBlockingStore.types\";\n\nconst { useResolvedStoreApi: useToolkitStoreApi, useResolvedValue: useToolkitValue } =\n createResolvedStoreHooks(uiBlockingStoreApi, useOptionalUIBlockingContext);\n\n/**\n * Hook that resolves to either the context store or global store\n *\n * This hook automatically uses the store from UIBlockingProvider if available,\n * otherwise falls back to the global store. This enables both patterns:\n *\n * 1. Global store (default behavior, no Provider needed)\n * 2. Context store (for SSR, testing, micro-frontends)\n *\n * @returns The resolved store API\n */\nexport function useResolvedStoreApi(): StoreApi<UIBlockingStore> {\n return useToolkitStoreApi();\n}\n\n/**\n * Hook to use the resolved store with a selector\n *\n * Uses toolkit shallow comparison by default, or the supplied domain equality.\n *\n * @param selector - Selector function to pick state from the store\n * @param equalityFn - Optional comparison retaining equivalent selected values\n * @returns Selected state value\n */\nexport function useResolvedValue<T>(\n selector: (state: UIBlockingStore) => T,\n equalityFn?: (left: T, right: T) => boolean\n): T {\n return useToolkitValue(selector, equalityFn);\n}\n\n/**\n * @deprecated Use `useResolvedStoreApi`.\n */\nexport const useResolvedStore = useResolvedStoreApi;\n/**\n * @deprecated Use `useResolvedValue`.\n */\nexport const useResolvedStoreWithSelector = useResolvedValue;\n","import {\n UIBlockingProvider,\n useIsInsideUIBlockingProvider,\n useOptionalUIBlockingContext,\n useUIBlockingContext,\n useUIBlockingStoreFromContext,\n} from \"./UIBlockingContext\";\nimport { useResolvedStoreApi, useResolvedValue } from \"./useResolvedStore\";\nimport type { StoreApi } from \"zustand\";\nimport type { UIBlockingStore } from \"../store/uiBlockingStore.types\";\n\nexport {\n UIBlockingProvider,\n useIsInsideUIBlockingProvider,\n useOptionalUIBlockingContext,\n useUIBlockingContext,\n useUIBlockingStoreFromContext,\n};\nexport type { UIBlockingProviderProps } from \"./UIBlockingContext\";\nexport { useResolvedStoreApi, useResolvedValue };\n\n/**\n * @deprecated Use `useOptionalUIBlockingContext`.\n */\nexport function useOptionalContext(): ReturnType<typeof useOptionalUIBlockingContext> {\n return useOptionalUIBlockingContext();\n}\n\n/**\n * @deprecated Use `useResolvedStoreApi`.\n */\nexport function useResolvedStore(): StoreApi<UIBlockingStore> {\n return useResolvedStoreApi();\n}\n\n/**\n * @deprecated Use `useResolvedValue`.\n */\nexport function useResolvedStoreWithSelector<T>(selector: (state: UIBlockingStore) => T): T {\n return useResolvedValue(selector);\n}\n","import type { StoreApi } from \"zustand\";\nimport type { UIBlockingStore } from \"./uiBlockingStore.types\";\n\nconst storeSequences = new WeakMap<StoreApi<UIBlockingStore>, number>();\n\nexport function allocateBlockerId(store: StoreApi<UIBlockingStore>, prefix: string): string {\n let sequence = storeSequences.get(store) ?? 0;\n let blockerId: string;\n\n const { blockingSnapshot } = store.getState();\n\n do {\n sequence += 1;\n blockerId = `${prefix}-${String(sequence)}`;\n } while (blockingSnapshot.some(({ id }) => id === blockerId));\n\n storeSequences.set(store, sequence);\n\n return blockerId;\n}\n","import { useCallback } from \"react\";\nimport { useResolvedStoreApi } from \"../../context\";\nimport { allocateBlockerId } from \"../../store/blockerId.utils\";\n\nexport function useBlockerIdAllocator(): (prefix: string) => string {\n const store = useResolvedStoreApi();\n\n return useCallback((prefix: string): string => allocateBlockerId(store, prefix), [store]);\n}\n","import { useCallback } from \"react\";\nimport { useResolvedValue } from \"../../context\";\nimport { ASYNC_ACTION_PRIORITY } from \"../../store\";\nimport { useBlockerIdAllocator } from \"../useBlockerIdAllocator\";\n\n/**\n * Options for useAsyncAction hook\n */\nexport interface UseAsyncActionOptions {\n /** Blocker lifetime in milliseconds; does not cancel or settle the operation */\n timeout?: number;\n /** Callback invoked when the blocker is automatically removed due to timeout */\n onTimeout?: (blockerId: string) => void;\n}\n\n/**\n * Wraps async functions with UI blocking. Concurrent calls get unique blocker IDs;\n * each blocker is removed in finally on success or failure, even after caller unmount.\n * Tracking does not exclude concurrent execution. Timeout releases only the blocker.\n *\n * @public\n * @since 0.6.0\n * @see {@link useActionBlocker} for manual blocker management\n * @see {@link useIsBlocked} to check blocking state\n * @see {@link UseAsyncActionOptions} for available options\n */\nexport function useAsyncAction<T = unknown>(\n actionId: string,\n scope?: string | ReadonlyArray<string>,\n options?: UseAsyncActionOptions\n): (asyncFn: () => Promise<T>) => Promise<T> {\n const allocateBlockerId = useBlockerIdAllocator();\n const { addBlocker, removeBlocker } = useResolvedValue((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 = allocateBlockerId(actionId);\n\n try {\n addBlocker(blockerId, {\n scope,\n reason: `Executing ${actionId}`,\n priority: ASYNC_ACTION_PRIORITY,\n timeout: options?.timeout,\n onTimeout: options?.onTimeout,\n });\n\n return await asyncFn();\n } finally {\n removeBlocker(blockerId);\n }\n },\n [\n actionId,\n scope,\n options?.timeout,\n options?.onTimeout,\n allocateBlockerId,\n addBlocker,\n removeBlocker,\n ]\n );\n\n return executeWithBlocking;\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 { shallow } from \"zustand/shallow\";\nimport { normalizeScope } from \"../../store\";\nimport type { Optional } from \"@okyrychenko-dev/type-utils\";\nimport type { BlockerConfig } from \"../../store\";\n\ntype BlockerConfigSnapshotValue = Optional<string | number | BlockerConfig[\"onTimeout\"]>;\n\nconst activeHookRegistrations = new WeakMap<object, Map<string, number>>();\n\nexport function trackHookRegistration(store: object, blockerId: string): VoidFunction {\n if (process.env.NODE_ENV === \"production\") {\n return () => undefined;\n }\n\n const registrations = activeHookRegistrations.get(store) ?? new Map<string, number>();\n const count = registrations.get(blockerId) ?? 0;\n\n activeHookRegistrations.set(store, registrations);\n registrations.set(blockerId, count + 1);\n\n if (count > 0) {\n console.warn(\n `[react-action-guard] Multiple active useActionBlocker hooks registered ID \"${blockerId}\" in the same store. Use a unique ID per hook; shared IDs can overwrite configuration or remove another hook's blocker during cleanup.`\n );\n }\n\n return () => {\n const remaining = (registrations.get(blockerId) ?? 1) - 1;\n\n if (remaining > 0) {\n registrations.set(blockerId, remaining);\n } else {\n registrations.delete(blockerId);\n }\n\n if (registrations.size === 0) {\n activeHookRegistrations.delete(store);\n }\n };\n}\n\nfunction getScopeSnapshotKey(scope?: string | ReadonlyArray<string>): string {\n return JSON.stringify(normalizeScope(scope));\n}\n\nfunction toBlockerConfigSnapshot(config: BlockerConfig): ReadonlyArray<BlockerConfigSnapshotValue> {\n return [\n getScopeSnapshotKey(config.scope),\n config.reason,\n config.priority,\n config.timestamp,\n config.timeout,\n config.onTimeout,\n ];\n}\n\nexport function areBlockerConfigsEqual(first: BlockerConfig, second: BlockerConfig): boolean {\n return shallow(toBlockerConfigSnapshot(first), toBlockerConfigSnapshot(second));\n}\n","import { type Nullable, isDefined, isNull } from \"@okyrychenko-dev/type-utils\";\nimport { useCallback, useEffect, useMemo, useRef } from \"react\";\nimport { useResolvedStoreApi } from \"../../context\";\nimport { useConfigRef } from \"../useConfigRef\";\nimport { areBlockerConfigsEqual, trackHookRegistration } from \"./useActionBlocker.utils\";\nimport type { BlockerConfig } from \"../../store\";\nimport type {\n UseBlockerRegistrationOptions,\n UseBlockerRegistrationReturn,\n} from \"./useBlockerRegistration.types\";\n\n/** Owns registration, reactive replacement and timeout completion for activation adapters. */\nexport function useBlockerRegistration({\n blockerId,\n config,\n endEpisodeOnTimeout = false,\n}: UseBlockerRegistrationOptions): UseBlockerRegistrationReturn {\n const store = useResolvedStoreApi();\n const lastConfigRef = useRef<Nullable<BlockerConfig>>(null);\n const releaseRef = useRef<Nullable<VoidFunction>>(null);\n const expiredRef = useRef(false);\n const configRef = useConfigRef(config);\n\n const handleTimeout = useCallback(\n (id: string): void => {\n expiredRef.current = endEpisodeOnTimeout;\n configRef.current.onTimeout?.(id);\n },\n [configRef, endEpisodeOnTimeout]\n );\n\n const storeConfig = useMemo<BlockerConfig>(() => {\n const shouldTrackTimeout = endEpisodeOnTimeout && isDefined(config.timeout);\n const hasTimeoutCallback = isDefined(config.onTimeout);\n let onTimeout: BlockerConfig[\"onTimeout\"];\n\n if (shouldTrackTimeout || hasTimeoutCallback) {\n onTimeout = handleTimeout;\n }\n\n return { ...config, onTimeout };\n }, [config, handleTimeout, endEpisodeOnTimeout]);\n const storeConfigRef = useConfigRef(storeConfig);\n\n const activate = useCallback((): void => {\n if (!blockerId || !isNull(releaseRef.current)) {\n return;\n }\n\n const { addBlocker } = store.getState();\n\n expiredRef.current = false;\n releaseRef.current = trackHookRegistration(store, blockerId);\n lastConfigRef.current = storeConfigRef.current;\n\n addBlocker(blockerId, storeConfigRef.current);\n }, [blockerId, store, storeConfigRef]);\n\n const deactivate = useCallback((): void => {\n if (isNull(releaseRef.current)) {\n return;\n }\n\n const { removeBlocker } = store.getState();\n\n releaseRef.current();\n releaseRef.current = null;\n lastConfigRef.current = null;\n expiredRef.current = false;\n\n removeBlocker(blockerId);\n }, [blockerId, store]);\n\n useEffect(() => deactivate, [deactivate]);\n\n useEffect(() => {\n if (\n isNull(lastConfigRef.current) ||\n expiredRef.current ||\n areBlockerConfigsEqual(lastConfigRef.current, storeConfig)\n ) {\n return;\n }\n\n const { replaceBlocker } = store.getState();\n\n replaceBlocker(blockerId, storeConfig);\n\n lastConfigRef.current = storeConfig;\n }, [blockerId, store, storeConfig]);\n\n return { activate, deactivate };\n}\n","import { useEffect } from \"react\";\nimport { useBlockerRegistration } from \"./useBlockerRegistration\";\nimport type { BlockerConfig } from \"../../store\";\n\n/**\n * Automatically manages a UI blocker based on component lifecycle.\n *\n * @public\n * @since 0.6.0\n * @see {@link useIsBlocked} to check if a scope is currently blocked\n * @see {@link useBlockingInfo} to get detailed blocker information\n * @see {@link useAsyncAction} for async operation wrapping with automatic blocking\n * @see {@link useConfirmableBlocker} for blockers that require user confirmation\n */\nexport function useActionBlocker(blockerId: string, config: BlockerConfig, isActive = true): void {\n const { activate, deactivate } = useBlockerRegistration({ blockerId, config });\n\n useEffect(() => {\n if (!isActive) {\n return;\n }\n activate();\n\n return deactivate;\n }, [isActive, activate, deactivate]);\n}\n\n/**\n * @deprecated Use {@link useActionBlocker} to avoid confusion with React Router's `useBlocker`.\n */\nexport const useBlocker: typeof useActionBlocker = useActionBlocker;\n","import { useMemo } from \"react\";\nimport { useResolvedValue } from \"../../context\";\nimport { DEFAULT_SCOPE, normalizeScope } from \"../../store\";\nimport { areBlockingInfosEqual, createBlockingInfoSelector } from \"../../store/blockingInfo\";\nimport type { BlockerInfo } from \"../../store\";\nimport type { Scope } from \"../../store/scope\";\n\n/**\n * Gets immutable, priority-ordered information about blockers affecting the observed scopes.\n * Unrelated lifecycle changes preserve the result and do not trigger a render.\n *\n * @public\n * @since 0.6.0\n * @see {@link useIsBlocked} for a simple boolean check\n * @see {@link useActionBlocker} to create blockers\n * @see {@link BlockerInfo} for the structure of blocker information objects\n */\nexport function useBlockingInfo(\n scope: Scope = DEFAULT_SCOPE\n): ReadonlyArray<Readonly<BlockerInfo>> {\n const checkedScopes = normalizeScope(scope);\n\n const selector = useMemo(() => {\n return createBlockingInfoSelector(checkedScopes);\n }, [checkedScopes]);\n\n return useResolvedValue(selector, areBlockingInfosEqual);\n}\n","import { isUndefined } from \"@okyrychenko-dev/type-utils\";\nimport { useCallback, useEffect, useRef } from \"react\";\nimport { useBlockerRegistration } from \"../useActionBlocker\";\nimport { useConfigRef } from \"../useConfigRef\";\nimport { ConditionalBlockerConfig } from \"./useConditionalBlocker.types\";\n\nconst DEFAULT_CHECK_INTERVAL = 1000;\n\n/**\n * Blocks UI based on a dynamic condition that is periodically evaluated.\n *\n * @public\n * @since 0.6.0\n * @see {@link useActionBlocker} for simple conditional blocking with boolean\n * @see {@link useScheduledBlocker} for time-based blocking\n * @see {@link ConditionalBlockerConfig} for configuration options\n */\nexport function useConditionalBlocker<TState = unknown>(\n blockerId: string,\n config: ConditionalBlockerConfig<TState>\n): void {\n const { activate, deactivate } = useBlockerRegistration({\n blockerId,\n config,\n endEpisodeOnTimeout: true,\n });\n const isBlockedRef = useRef(false);\n const configRef = useConfigRef(config);\n\n const checkInterval =\n !isUndefined(config.checkInterval) && config.checkInterval > 0\n ? config.checkInterval\n : DEFAULT_CHECK_INTERVAL;\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 activate();\n } else {\n deactivate();\n }\n isBlockedRef.current = shouldBlock;\n }, [activate, deactivate, configRef]);\n\n useEffect(\n () => () => {\n deactivate();\n isBlockedRef.current = false;\n },\n [deactivate]\n );\n\n useEffect(() => {\n checkCondition();\n\n const interval = setInterval(checkCondition, checkInterval);\n\n return () => {\n clearInterval(interval);\n };\n }, [checkCondition, checkInterval]);\n}\n","import { useCallback, useRef, useState } from \"react\";\nimport { useActionBlocker } from \"../useActionBlocker\";\nimport {\n ConfirmableBlockerConfig,\n UseConfirmableBlockerReturn,\n} from \"./useConfirmableBlocker.types\";\n\n/**\n * Creates a blocker that requires user confirmation before executing an action.\n *\n * @public\n * @since 0.6.0\n * @see {@link useActionBlocker} for simple blocking without confirmation\n * @see {@link ConfirmableBlockerConfig} for configuration options\n * @see {@link UseConfirmableBlockerReturn} for return value structure\n */\nexport function useConfirmableBlocker(\n blockerId: string,\n config: ConfirmableBlockerConfig\n): UseConfirmableBlockerReturn {\n const [isDialogOpen, setIsDialogOpen] = useState(false);\n const [isExecuting, setIsExecuting] = useState(false);\n const executionRef = useRef<Promise<void> | null>(null);\n\n useActionBlocker(\n blockerId,\n {\n ...config,\n reason: config.reason ?? config.confirmMessage,\n },\n isDialogOpen || isExecuting\n );\n\n const execute = useCallback(() => {\n if (executionRef.current) {\n return;\n }\n\n setIsDialogOpen(true);\n }, []);\n\n const onConfirm = useCallback(async () => {\n if (executionRef.current) {\n return executionRef.current;\n }\n\n setIsDialogOpen(false);\n setIsExecuting(true);\n\n async function runConfirmation(): Promise<void> {\n try {\n await config.onConfirm();\n } finally {\n executionRef.current = null;\n setIsExecuting(false);\n }\n }\n\n // Publish ownership before invoking user code, including reentrant callbacks.\n const execution = Promise.resolve().then(runConfirmation);\n\n executionRef.current = execution;\n\n return execution;\n }, [config]);\n\n const onCancel = useCallback(() => {\n if (executionRef.current) {\n return;\n }\n\n setIsDialogOpen(false);\n config.onCancel?.();\n }, [config]);\n\n const { confirmTitle, confirmMessage, confirmButtonText, cancelButtonText } = config;\n\n const confirmConfig = {\n title: confirmTitle ?? \"Confirm Action\",\n message: confirmMessage,\n confirmText: confirmButtonText ?? \"Confirm\",\n cancelText: cancelButtonText ?? \"Cancel\",\n };\n\n return {\n execute,\n isDialogOpen,\n isExecuting,\n confirmConfig,\n onConfirm,\n onCancel,\n };\n}\n","import { useResolvedValue } from \"../../context\";\n\n/**\n * Checks if one or more scopes are currently blocked.\n *\n * @public\n * @since 0.6.0\n * @see {@link useActionBlocker} to create a blocker\n * @see {@link useBlockingInfo} to get detailed information about active blockers\n */\nexport function useIsBlocked(scope?: string | ReadonlyArray<string>): boolean {\n return useResolvedValue((state) => state.isBlocked(scope));\n}\n","import { type Optional, isUndefined } from \"@okyrychenko-dev/type-utils\";\nimport 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.isFinite(timestamp) && Math.abs(timestamp) <= 8_640_000_000_000_000;\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(schedule: BlockingSchedule, startTime: number): Optional<number> {\n if (!isUndefined(schedule.duration)) {\n return startTime + schedule.duration;\n }\n\n if (!isUndefined(schedule.end)) {\n const endTime = parseDate(schedule.end);\n\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: Optional<number>,\n now: number\n): boolean {\n if (startTime > now) {\n return false; // Not started yet\n }\n\n if (isUndefined(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/** Validate every supplied bound, including an end overridden by duration. */\nexport function isValidSchedule(schedule: BlockingSchedule, startTime: number): boolean {\n const { duration, end } = schedule;\n\n if (!isValidTimestamp(startTime)) {\n return false;\n }\n\n if (!isUndefined(end)) {\n const suppliedEnd = parseDate(end);\n\n if (!isValidTimestamp(suppliedEnd) || suppliedEnd < startTime) {\n return false;\n }\n }\n\n if (!isUndefined(duration)) {\n if (!Number.isFinite(duration) || duration < 0) {\n return false;\n }\n\n return isValidTimestamp(startTime + duration);\n }\n\n return true;\n}\n","import { isUndefined } from \"@okyrychenko-dev/type-utils\";\nimport { useCallback, useEffect, useRef } from \"react\";\nimport { useBlockerRegistration } from \"../useActionBlocker\";\nimport { useConfigRef } from \"../useConfigRef\";\nimport { ScheduledBlockerConfig } from \"./useScheduledBlocker.types\";\nimport {\n MAX_TIMEOUT_MS,\n calculateEndTime,\n isInBlockingPeriod,\n isValidSchedule,\n parseDate,\n} from \"./useScheduledBlocker.utils\";\n\n/**\n * Schedules UI blocking for a specific time period (e.g., maintenance windows).\n *\n * @public\n * @since 0.6.0\n * @see {@link useActionBlocker} for immediate blocking without scheduling\n * @see {@link useConditionalBlocker} for condition-based blocking\n * @see {@link ScheduledBlockerConfig} for configuration options\n * @see {@link BlockingSchedule} for schedule specification details\n */\nexport function useScheduledBlocker(blockerId: string, config: ScheduledBlockerConfig): void {\n const { activate, deactivate } = useBlockerRegistration({\n blockerId,\n config,\n endEpisodeOnTimeout: true,\n });\n const timeoutsRef = useRef<{\n start?: ReturnType<typeof setTimeout>;\n end?: ReturnType<typeof setTimeout>;\n }>({});\n const configRef = useConfigRef(config);\n\n const scheduleStart = parseDate(config.schedule.start);\n const scheduleEnd = isUndefined(config.schedule.end) ? undefined : parseDate(config.schedule.end);\n const scheduleDuration = config.schedule.duration;\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 if (!isValidSchedule(currentConfig.schedule, startTime)) {\n if (process.env.NODE_ENV !== \"production\") {\n console.warn(\"[react-action-guard] Invalid blocking schedule:\", currentConfig.schedule);\n }\n\n return;\n }\n\n const endTime = calculateEndTime(currentConfig.schedule, startTime);\n\n if (!isUndefined(endTime) && endTime <= startTime) {\n return;\n }\n\n const scheduleEnd = (): void => {\n if (isUndefined(endTime)) {\n return;\n }\n\n const remainingTime = endTime - Date.now();\n\n if (remainingTime > 0) {\n timeoutsRef.current.end = setTimeout(scheduleEnd, Math.min(remainingTime, MAX_TIMEOUT_MS));\n\n return;\n }\n\n try {\n configRef.current.onScheduleEnd?.();\n } finally {\n deactivate();\n }\n };\n\n const startBlocking = (): void => {\n const now = Date.now();\n const remainingTime = startTime - now;\n\n if (remainingTime > 0) {\n timeoutsRef.current.start = setTimeout(\n startBlocking,\n Math.min(remainingTime, MAX_TIMEOUT_MS)\n );\n\n return;\n }\n\n // A suspended tab can deliver this timer after the entire window elapsed.\n if (!isInBlockingPeriod(startTime, endTime, now)) {\n return;\n }\n\n const cfg = configRef.current;\n\n activate();\n scheduleEnd();\n cfg.onScheduleStart?.();\n };\n\n // If start time hasn't arrived yet\n if (startTime > now) {\n const delay = startTime - now;\n\n timeoutsRef.current.start = setTimeout(startBlocking, Math.min(delay, MAX_TIMEOUT_MS));\n }\n // If already in blocking period or should start immediately\n else {\n if (isInBlockingPeriod(startTime, endTime, now)) {\n try {\n startBlocking();\n } catch (error) {\n cleanup();\n deactivate();\n\n throw error;\n }\n }\n }\n\n return (): void => {\n cleanup();\n deactivate();\n };\n }, [activate, deactivate, cleanup, scheduleStart, scheduleEnd, scheduleDuration, configRef]);\n}\n","import { type Optional, isArray, isUndefined } from \"@okyrychenko-dev/type-utils\";\nimport { AnalyticsEventData } from \"./analyticsMiddleware.types\";\nimport { MiddlewareContext } from \"./middleware.types\";\n\nfunction capitalizeFirst(str: string): string {\n return str.charAt(0).toUpperCase() + str.slice(1);\n}\n\nfunction getAnalyticsWindow(): Optional<Window> {\n if (typeof window === \"undefined\") {\n return undefined;\n }\n\n return window;\n}\n\nexport function buildEventData(context: MiddlewareContext): AnalyticsEventData {\n const eventData: AnalyticsEventData = {\n blocker_id: context.blockerId,\n };\n const { scope, reason, priority } = context.config ?? {};\n\n if (!isUndefined(scope)) {\n eventData.scope = isArray(scope) ? scope.join(\",\") : scope;\n }\n\n if (!isUndefined(reason)) {\n eventData.reason = reason;\n }\n\n if (!isUndefined(priority)) {\n eventData.priority = priority;\n }\n\n return eventData;\n}\n\nexport function trackGoogleAnalytics(action: string, eventData: AnalyticsEventData): void {\n const analyticsWindow = getAnalyticsWindow();\n\n if (analyticsWindow?.gtag) {\n analyticsWindow.gtag(\"event\", `ui_blocking_${action}`, eventData);\n }\n}\n\nexport function trackMixpanel(action: string, eventData: AnalyticsEventData): void {\n const analyticsWindow = getAnalyticsWindow();\n\n if (analyticsWindow?.mixpanel) {\n const eventName = `UI Blocking ${action.split(\"_\").map(capitalizeFirst).join(\" \")}`;\n\n analyticsWindow.mixpanel.track(eventName, eventData);\n }\n}\n\nexport function trackAmplitude(action: string, eventData: AnalyticsEventData): void {\n const analyticsWindow = getAnalyticsWindow();\n\n if (analyticsWindow?.amplitude) {\n const eventName = `UI Blocking ${action.split(\"_\").map(capitalizeFirst).join(\" \")}`;\n\n analyticsWindow.amplitude.track(eventName, eventData);\n }\n}\n\nexport function 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\n/**\n * Helper function to track events based on analytics configuration.\n * @internal\n */\nfunction 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\n return;\n case \"mixpanel\":\n trackMixpanel(context.action, eventData);\n\n return;\n case \"amplitude\":\n trackAmplitude(context.action, eventData);\n\n return;\n }\n }\n\n if (\"track\" in config) {\n trackCustom(config.track, context.action, eventData);\n }\n}\n\n/**\n * Creates middleware for tracking blocker events to analytics platforms.\n *\n * @public\n * @since 0.6.0\n * @see {@link AnalyticsConfig} for configuration options\n * @see {@link configureMiddleware} for registering middleware\n */\nexport function 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\";\nimport type { Middleware } from \"./middleware.types\";\n\nlet configuredReleases: ReadonlyArray<VoidFunction> = [];\n\n/** Replace configured global observations without releasing independently owned observations. */\nexport function configureMiddleware(middlewares: ReadonlyArray<Middleware>): void {\n const { observeBlockingEvents } = uiBlockingStoreApi.getState();\n\n for (const release of configuredReleases) {\n release();\n }\n configuredReleases = middlewares.map(observeBlockingEvents);\n}\n","import { isNonEmptyArray, isUndefined } from \"@okyrychenko-dev/type-utils\";\nimport { MiddlewareBlockerConfig, MiddlewareContext } from \"./middleware.types\";\n\nexport function getActionEmoji(action: string): string {\n switch (action) {\n case \"add\":\n return \"โž•\";\n case \"update\":\n return \"๐Ÿ”„\";\n case \"remove\":\n return \"โž–\";\n case \"timeout\":\n return \"โฑ๏ธ\";\n case \"clear\":\n return \"๐Ÿงน\";\n case \"clear_scope\":\n return \"๐ŸŽฏ\";\n default:\n return \"โ“\";\n }\n}\n\nfunction 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 (!isUndefined(priority)) {\n details.priority = priority;\n }\n\n return details;\n}\n\nexport function formatLogData(context: MiddlewareContext): Record<string, unknown> {\n const configDetails = extractConfigDetails(context.config);\n\n const logData: Record<string, unknown> = {};\n\n // Add scope for clear_scope action\n if (!isUndefined(context.scope)) {\n logData.scope = context.scope;\n }\n\n // Add count for clear actions\n if (!isUndefined(context.count)) {\n logData.count = context.count;\n }\n\n // Add config details\n if (isNonEmptyArray(Object.keys(configDetails))) {\n logData.config = configDetails;\n }\n\n // Add previous state if present\n if (context.prevState) {\n logData.prevState = extractConfigDetails(context.prevState);\n }\n\n // Return config details directly if no special fields\n if (!isNonEmptyArray(Object.keys(logData))) {\n return configDetails;\n }\n\n return Object.keys(logData).length === 1 && logData.config ? configDetails : logData;\n}\n","import { formatLogData, getActionEmoji } from \"./loggerMiddleware.utils\";\nimport { MiddlewareContext } from \"./middleware.types\";\n\nconst LOG_PREFIX = \"[UIBlocking]\";\n\n/**\n * Built-in middleware for logging all blocking actions to the console.\n *\n * @public\n * @since 0.6.0\n * @see {@link configureMiddleware} for registering middleware\n * @see {@link Middleware} for middleware function signature\n * @see {@link MiddlewareContext} for available context data\n */\nexport function loggerMiddleware(context: MiddlewareContext): void {\n const emoji = getActionEmoji(context.action);\n const logData = formatLogData(context);\n\n console.log(LOG_PREFIX, emoji, context.blockerId, logData);\n}\n","import type { PerformanceConfig, TrackedPerformanceBlock } from \"./performanceMiddleware.types\";\n\nexport function finalizeTrackedBlocks(\n endedBlocks: ReadonlyMap<string, TrackedPerformanceBlock>,\n timestamp: number,\n threshold: number,\n onSlowBlock: PerformanceConfig[\"onSlowBlock\"]\n): void {\n for (const [id, tracked] of endedBlocks) {\n const duration = timestamp - tracked.timestamp;\n\n if (duration >= threshold) {\n try {\n onSlowBlock?.(id, duration);\n } catch {\n // One consumer failure must not prevent finalization of other lifetimes.\n }\n }\n }\n}\n","import { isDefined } from \"@okyrychenko-dev/type-utils\";\nimport { normalizeScope, scopeMatchesTarget } from \"../store/scope\";\nimport { finalizeTrackedBlocks } from \"./performanceMiddleware.utils\";\nimport type { Middleware } from \"./middleware.types\";\nimport type { PerformanceConfig, TrackedPerformanceBlock } from \"./performanceMiddleware.types\";\n\nconst DEFAULT_SLOW_BLOCK_THRESHOLD = 3000;\n\n/**\n * Measures registration lifetimes from add until removal, timeout or bulk clear.\n * Updates preserve the start; replacement adds restart it. Callback failures are isolated.\n * @public\n * @since 0.6.0\n */\nexport function createPerformanceMiddleware(config: PerformanceConfig = {}): Middleware {\n const { slowBlockThreshold = DEFAULT_SLOW_BLOCK_THRESHOLD, onSlowBlock } = config;\n const trackedBlocks = new Map<string, TrackedPerformanceBlock>();\n\n const registrations = new WeakMap<object, TrackedPerformanceBlock>();\n\n return (context) => {\n const { action, blockerId, timestamp, config: blockerConfig, scope, registration } = context;\n\n if (action === \"add\") {\n const tracked = { timestamp, scope: normalizeScope(blockerConfig?.scope), registration };\n\n trackedBlocks.set(blockerId, tracked);\n\n if (isDefined(registration)) {\n registrations.set(registration, tracked);\n }\n } else if (action === \"update\") {\n const tracked = trackedBlocks.get(blockerId);\n\n if (isDefined(tracked) && isDefined(blockerConfig?.scope)) {\n tracked.scope = normalizeScope(blockerConfig.scope);\n }\n } else {\n const endedBlocks = new Map<string, TrackedPerformanceBlock>();\n\n if (action === \"remove\" || action === \"timeout\") {\n let tracked = trackedBlocks.get(blockerId);\n\n if (isDefined(registration)) {\n tracked = registrations.get(registration);\n }\n\n if (isDefined(tracked)) {\n endedBlocks.set(blockerId, tracked);\n if (trackedBlocks.get(blockerId) === tracked) {\n trackedBlocks.delete(blockerId);\n }\n }\n } else {\n for (const [id, tracked] of trackedBlocks) {\n const cleared =\n action === \"clear\" || (isDefined(scope) && scopeMatchesTarget(tracked.scope, scope));\n\n if (cleared) {\n endedBlocks.set(id, tracked);\n trackedBlocks.delete(id);\n }\n }\n }\n\n for (const tracked of endedBlocks.values()) {\n const { registration: trackedRegistration } = tracked;\n\n if (isDefined(trackedRegistration)) {\n registrations.delete(trackedRegistration);\n }\n }\n\n finalizeTrackedBlocks(endedBlocks, timestamp, slowBlockThreshold, onSlowBlock);\n }\n };\n}\n","import { useActionBlocker } from \"./hooks/useActionBlocker\";\nimport { type UseAsyncActionOptions, useAsyncAction } from \"./hooks/useAsyncAction\";\nimport { useBlockingInfo } from \"./hooks/useBlockingInfo\";\nimport { useIsBlocked } from \"./hooks/useIsBlocked\";\nimport type { BlockerConfigTyped, ScopeValue } from \"./types\";\n\n/**\n * Return type for createTypedHooks factory\n */\nexport interface TypedHooks<TScope extends string> {\n /**\n * Type-safe action blocker hook\n */\n useActionBlocker: (\n blockerId: string,\n config: BlockerConfigTyped<TScope>,\n isActive?: boolean\n ) => void;\n\n /**\n * Backward-compatible name for useActionBlocker\n * @deprecated Use `useActionBlocker`.\n */\n useBlocker: (blockerId: string, config: BlockerConfigTyped<TScope>, isActive?: boolean) => void;\n\n /**\n * Type-safe version of useIsBlocked hook\n */\n useIsBlocked: (scope?: ScopeValue<TScope>) => boolean;\n\n /**\n * Type-safe version of useAsyncAction hook\n */\n useAsyncAction: <T = unknown>(\n actionId: string,\n scope?: ScopeValue<TScope>,\n options?: UseAsyncActionOptions\n ) => (asyncFn: () => Promise<T>) => Promise<T>;\n\n /**\n * Type-safe version of useBlockingInfo hook\n */\n useBlockingInfo: (scope: ScopeValue<TScope>) => ReturnType<typeof useBlockingInfo>;\n}\n\n/**\n * Creates type-safe versions of all blocking hooks with your custom scope types\n *\n * @template TScope - Union type of allowed scope strings\n * @returns Object with type-safe hook functions\n *\n * @example\n * ```typescript\n * // Define your app's scopes\n * type AppScopes = \"global\" | \"form\" | \"navigation\" | \"checkout\";\n *\n * // Create typed hooks\n * const { useActionBlocker, useIsBlocked, useAsyncAction } = createTypedHooks<AppScopes>();\n *\n * // Now TypeScript will catch typos\n * useActionBlocker(\"id\", { scope: \"form\" }); // โœ“ OK\n * useActionBlocker(\"id\", { scope: \"typo\" }); // โœ— Type error!\n * ```\n */\nexport function createTypedHooks<TScope extends string>(): TypedHooks<TScope> {\n // TScope extends string, so all typed scopes are assignable to string | ReadonlyArray<string>\n // This allows us to pass typed values directly without casting\n const useTypedActionBlocker = (\n blockerId: string,\n config: BlockerConfigTyped<TScope>,\n isActive?: boolean\n ): void => {\n useActionBlocker(blockerId, config, isActive);\n };\n\n return {\n useActionBlocker: useTypedActionBlocker,\n useBlocker: useTypedActionBlocker,\n\n useIsBlocked: (scope) => {\n // ScopeValue<TScope> = TScope | ReadonlyArray<TScope>\n // Since TScope extends string, this is assignable to string | ReadonlyArray<string>\n return useIsBlocked(scope);\n },\n\n useAsyncAction: <T = unknown>(\n actionId: string,\n scope?: ScopeValue<TScope>,\n options?: UseAsyncActionOptions\n ) => {\n return useAsyncAction<T>(actionId, scope, options);\n },\n\n useBlockingInfo: (scope) => useBlockingInfo(scope),\n };\n}\n"]}