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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1,8 +1,9 @@
1
1
  'use strict';
2
2
 
3
3
  var react = require('react');
4
- var zustand = require('zustand');
5
4
  var middleware = require('zustand/middleware');
5
+ var zustand = require('zustand');
6
+ var shallow = require('zustand/shallow');
6
7
 
7
8
  // src/hooks/useAsyncAction/useAsyncAction.ts
8
9
 
@@ -12,8 +13,13 @@ var DEFAULT_REASON = "Unknown";
12
13
  var DEFAULT_PRIORITY = 0;
13
14
  var ASYNC_ACTION_PRIORITY = 20;
14
15
  var DEVTOOLS_NAME = "UIBlocking";
15
-
16
- // src/store/uiBlockingStore.utils.ts
16
+ function createShallowStore(storeCreator) {
17
+ const storeApi = zustand.createStore(storeCreator);
18
+ const useScopedStore = (selector) => {
19
+ return zustand.useStore(storeApi, shallow.useShallow(selector));
20
+ };
21
+ return { useStore: useScopedStore, useStoreApi: storeApi };
22
+ }
17
23
  function normalizeScopeToArray(scope) {
18
24
  if (typeof scope === "string") {
19
25
  return [scope];
@@ -178,13 +184,14 @@ var devtoolsConfig = {
178
184
  };
179
185
 
180
186
  // src/store/uiBlockingStore.store.ts
181
- var useUIBlockingStore = zustand.create()(
182
- middleware.devtools(createUIBlockingActions, devtoolsConfig)
183
- );
187
+ var { useStore: useUIBlockingStore, useStoreApi: uiBlockingStoreApi } = createShallowStore(middleware.devtools(createUIBlockingActions, devtoolsConfig));
184
188
 
185
189
  // src/hooks/useAsyncAction/useAsyncAction.ts
186
190
  var useAsyncAction = (actionId, scope) => {
187
- const { addBlocker, removeBlocker } = useUIBlockingStore();
191
+ const { addBlocker, removeBlocker } = useUIBlockingStore((state) => ({
192
+ addBlocker: state.addBlocker,
193
+ removeBlocker: state.removeBlocker
194
+ }));
188
195
  const executeWithBlocking = react.useCallback(
189
196
  async (asyncFn) => {
190
197
  const blockerId = `${actionId}-${Date.now().toString()}`;
@@ -204,7 +211,10 @@ var useAsyncAction = (actionId, scope) => {
204
211
  return executeWithBlocking;
205
212
  };
206
213
  var useBlocker = (blockerId, config, isActive = true) => {
207
- const { addBlocker, removeBlocker } = useUIBlockingStore();
214
+ const { addBlocker, removeBlocker } = useUIBlockingStore((state) => ({
215
+ addBlocker: state.addBlocker,
216
+ removeBlocker: state.removeBlocker
217
+ }));
208
218
  react.useEffect(() => {
209
219
  if (!isActive || !blockerId) {
210
220
  return;
@@ -234,7 +244,10 @@ function useConfigRef(config) {
234
244
 
235
245
  // src/hooks/useConditionalBlocker/useConditionalBlocker.ts
236
246
  var useConditionalBlocker = (blockerId, config) => {
237
- const { addBlocker, removeBlocker } = useUIBlockingStore();
247
+ const { addBlocker, removeBlocker } = useUIBlockingStore((state) => ({
248
+ addBlocker: state.addBlocker,
249
+ removeBlocker: state.removeBlocker
250
+ }));
238
251
  const intervalRef = react.useRef(null);
239
252
  const isBlockedRef = react.useRef(false);
240
253
  const configRef = useConfigRef(config);
@@ -356,7 +369,10 @@ function isScheduleInPast(startTime, endTime, now) {
356
369
 
357
370
  // src/hooks/useScheduledBlocker/useScheduledBlocker.ts
358
371
  var useScheduledBlocker = (blockerId, config) => {
359
- const { addBlocker, removeBlocker } = useUIBlockingStore();
372
+ const { addBlocker, removeBlocker } = useUIBlockingStore((state) => ({
373
+ addBlocker: state.addBlocker,
374
+ removeBlocker: state.removeBlocker
375
+ }));
360
376
  const timeoutsRef = react.useRef({});
361
377
  const configRef = useConfigRef(config);
362
378
  const cleanup = react.useCallback(() => {
@@ -578,6 +594,7 @@ var createPerformanceMiddleware = (config = {}) => {
578
594
  exports.createAnalyticsMiddleware = createAnalyticsMiddleware;
579
595
  exports.createPerformanceMiddleware = createPerformanceMiddleware;
580
596
  exports.loggerMiddleware = loggerMiddleware;
597
+ exports.uiBlockingStoreApi = uiBlockingStoreApi;
581
598
  exports.useAsyncAction = useAsyncAction;
582
599
  exports.useBlocker = useBlocker;
583
600
  exports.useConditionalBlocker = useConditionalBlocker;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/store/uiBlockingStore.constants.ts","../src/store/uiBlockingStore.utils.ts","../src/store/uiBlockingStore.actions.ts","../src/store/uiBlockingStore.config.ts","../src/store/uiBlockingStore.store.ts","../src/hooks/useAsyncAction/useAsyncAction.ts","../src/hooks/useBlocker/useBlocker.ts","../src/hooks/useBlocker/useBlocker.utils.ts","../src/hooks/useConfigRef.ts","../src/hooks/useConditionalBlocker/useConditionalBlocker.ts","../src/hooks/useConfirmableBlocker/useConfirmableBlocker.ts","../src/hooks/useIsBlocked/useIsBlocked.ts","../src/hooks/useScheduledBlocker/useScheduledBlocker.utils.ts","../src/hooks/useScheduledBlocker/useScheduledBlocker.ts","../src/middleware/analyticsMiddleware.utils.ts","../src/middleware/analyticsMiddleware.ts","../src/middleware/loggerMiddleware.utils.ts","../src/middleware/loggerMiddleware.ts","../src/middleware/performanceMiddleware.utils.ts","../src/middleware/performanceMiddleware.ts"],"names":["create","devtools","useCallback","useEffect","useRef","useState"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Default values and constants for UI Blocking Store\n */\n\n/**\n * Default scope for blockers\n */\nexport const DEFAULT_SCOPE = \"global\" as const;\n\n/**\n * Default reason when none is provided\n */\nexport const DEFAULT_REASON = \"Unknown\" as const;\n\n/**\n * Default priority for blockers\n */\nexport const DEFAULT_PRIORITY = 0 as const;\n\n/**\n * Default priority for async actions\n */\nexport const ASYNC_ACTION_PRIORITY = 20 as const;\n\n/**\n * DevTools store name\n */\nexport const DEVTOOLS_NAME = \"UIBlocking\" as const;\n","/**\n * Normalize scope to array format\n *\n * @param scope - Single scope or array of scopes\n * @returns Array of scopes\n *\n * @internal\n */\nexport function normalizeScopeToArray(scope: string | ReadonlyArray<string>): Array<string> {\n if (typeof scope === \"string\") {\n return [scope];\n }\n return Array.from(scope);\n}\n","import { Middleware, MiddlewareContext } from \"../middleware\";\nimport { DEFAULT_PRIORITY, DEFAULT_REASON, DEFAULT_SCOPE } from \"./uiBlockingStore.constants\";\nimport { normalizeScopeToArray } from \"./uiBlockingStore.utils\";\nimport type {\n BlockerConfig,\n BlockerInfo,\n StoredBlocker,\n UIBlockingStore,\n} from \"./uiBlockingStore.types\";\nimport type { StateCreator } from \"zustand\";\n\n/**\n * UI Blocking Store Slice\n *\n * Implements the state and actions for UI blocking management.\n * This slice follows the Zustand slice pattern for better code organization.\n */\nexport const createUIBlockingActions: StateCreator<UIBlockingStore, [], [], UIBlockingStore> = (\n set,\n get\n) => ({\n // State\n activeBlockers: new Map(),\n middlewares: new Map(),\n\n registerMiddleware: (name: string, middleware: Middleware) => {\n set((state) => {\n const newMiddlewares = new Map(state.middlewares);\n newMiddlewares.set(name, middleware);\n return { middlewares: newMiddlewares };\n });\n console.log(`[UIBlocking] Registered middleware: ${name}`);\n },\n\n unregisterMiddleware: (name: string) => {\n set((state) => {\n const newMiddlewares = new Map(state.middlewares);\n newMiddlewares.delete(name);\n return { middlewares: newMiddlewares };\n });\n console.log(`[UIBlocking] Unregistered middleware: ${name}`);\n },\n\n runMiddlewares: async (context: MiddlewareContext) => {\n const { middlewares } = get();\n\n for (const [name, middleware] of middlewares) {\n try {\n await middleware(context);\n } catch (error) {\n console.error(`[UIBlocking] Middleware \"${name}\" error:`, error);\n }\n }\n },\n\n // Actions\n /**\n * Add a blocker to the store\n *\n * @param id - Unique blocker identifier\n * @param config - Optional blocker configuration\n *\n */\n addBlocker: (id: string, config: BlockerConfig = {}): void => {\n set((state) => {\n const newBlockers = new Map(state.activeBlockers);\n const storedBlocker: StoredBlocker = {\n scope: config.scope ?? DEFAULT_SCOPE,\n reason: config.reason ?? DEFAULT_REASON,\n priority: config.priority ?? DEFAULT_PRIORITY,\n timestamp: config.timestamp ?? Date.now(),\n };\n newBlockers.set(id, storedBlocker);\n\n return { activeBlockers: newBlockers };\n });\n\n void get().runMiddlewares({\n action: \"add\",\n blockerId: id,\n config: {\n scope: config.scope,\n reason: config.reason,\n priority: config.priority,\n },\n timestamp: Date.now(),\n });\n },\n\n /**\n * Remove a blocker from the store\n *\n * @param id - Blocker identifier to remove\n *\n */\n removeBlocker: (id: string): void => {\n const prevBlocker = get().activeBlockers.get(id);\n\n set((state) => {\n const newBlockers = new Map(state.activeBlockers);\n newBlockers.delete(id);\n\n return { activeBlockers: newBlockers };\n });\n\n if (prevBlocker) {\n void get().runMiddlewares({\n action: \"remove\",\n blockerId: id,\n config: prevBlocker,\n timestamp: Date.now(),\n prevState: prevBlocker,\n });\n }\n },\n\n /**\n * Check if a scope is currently blocked\n *\n * @param scope - Scope or array of scopes to check (default: \"global\")\n * @returns True if any of the scopes are blocked\n *\n */\n isBlocked: (scope: string | ReadonlyArray<string> = DEFAULT_SCOPE): boolean => {\n const { activeBlockers } = get();\n const scopes = normalizeScopeToArray(scope);\n\n for (const [, blocker] of activeBlockers) {\n // Global blocking blocks everything\n if (blocker.scope === DEFAULT_SCOPE) {\n return true;\n }\n\n // Check scope intersection\n const blockerScopes = normalizeScopeToArray(blocker.scope);\n\n if (scopes.some((s) => blockerScopes.includes(s))) {\n return true;\n }\n }\n\n return false;\n },\n\n /**\n * Get detailed blocking information for a specific scope\n *\n * @param scope - Scope to get blocking information for\n * @returns Array of blockers affecting the scope, sorted by priority (highest first)\n *\n */\n getBlockingInfo: (scope: string): ReadonlyArray<BlockerInfo> => {\n const { activeBlockers } = get();\n const blockers: Array<BlockerInfo> = [];\n\n for (const [id, blocker] of activeBlockers) {\n const blockerScopes = normalizeScopeToArray(blocker.scope);\n\n if (blocker.scope === DEFAULT_SCOPE || blockerScopes.includes(scope)) {\n blockers.push({ id, ...blocker });\n }\n }\n\n return blockers.sort((a, b) => b.priority - a.priority);\n },\n\n /**\n * Clear all blockers from the store\n */\n clearAllBlockers: (): void => {\n set({ activeBlockers: new Map() });\n },\n\n /**\n * Clear all blockers for a specific scope\n *\n * @param scope - Scope to clear blockers for\n *\n */\n clearBlockersForScope: (scope: string): void => {\n set((state) => {\n const newBlockers = new Map();\n\n for (const [id, blocker] of state.activeBlockers) {\n const blockerScopes = normalizeScopeToArray(blocker.scope);\n\n if (!blockerScopes.includes(scope)) {\n newBlockers.set(id, blocker);\n }\n }\n\n return { activeBlockers: newBlockers };\n });\n },\n});\n","import { DEVTOOLS_NAME } from \"./uiBlockingStore.constants\";\nimport type { DevtoolsOptions } from \"zustand/middleware\";\n\n/**\n * DevTools configuration for UI Blocking Store\n *\n * Enables Redux DevTools integration only in development mode\n * for better debugging experience without production overhead.\n */\nexport const devtoolsConfig: DevtoolsOptions = {\n name: DEVTOOLS_NAME,\n enabled: process.env.NODE_ENV !== \"production\",\n};\n","import { create } from \"zustand\";\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 *\n */\nexport const useUIBlockingStore = create<UIBlockingStore>()(\n devtools(createUIBlockingActions, devtoolsConfig)\n);\n","import { useCallback } from \"react\";\nimport { ASYNC_ACTION_PRIORITY, useUIBlockingStore } from \"../../store\";\n\n/**\n * Hook to wrap async functions with automatic blocking/unblocking\n *\n * Creates a wrapper function that automatically adds a blocker before executing\n * the async function and removes it after completion (success or failure).\n *\n * @template T - The return type of the async function\n * @param actionId - Unique identifier for the action (used in blocker ID and reason)\n * @param scope - Scope(s) to block during execution (default: \"global\")\n * @returns Function that wraps async functions with blocking behavior\n *\n */\nexport const useAsyncAction = <T = unknown>(\n actionId: string,\n scope?: string | ReadonlyArray<string>\n): ((asyncFn: () => Promise<T>) => Promise<T>) => {\n const { addBlocker, removeBlocker } = useUIBlockingStore();\n\n const executeWithBlocking = useCallback(\n async (asyncFn: () => Promise<T>): Promise<T> => {\n const blockerId = `${actionId}-${Date.now().toString()}`;\n\n try {\n addBlocker(blockerId, {\n scope,\n reason: `Executing ${actionId}`,\n priority: ASYNC_ACTION_PRIORITY,\n });\n\n return await asyncFn();\n } finally {\n removeBlocker(blockerId);\n }\n },\n [actionId, scope, addBlocker, removeBlocker]\n );\n\n return executeWithBlocking;\n};\n","import { useEffect } from \"react\";\nimport { type BlockerConfig, useUIBlockingStore } from \"../../store\";\n\n/**\n * Hook to automatically add and remove a blocker based on component lifecycle\n *\n * Automatically adds a blocker when the component mounts (or when activated)\n * and removes it when the component unmounts (or when deactivated).\n *\n * @param blockerId - Unique identifier for the blocker\n * @param config - Blocker configuration (scope, reason, priority)\n * @param isActive - Whether the blocker is currently active (default: true)\n *\n */\nexport const useBlocker = (blockerId: string, config: BlockerConfig, isActive = true): void => {\n const { addBlocker, removeBlocker } = useUIBlockingStore();\n\n useEffect(() => {\n if (!isActive || !blockerId) {\n return;\n }\n\n addBlocker(blockerId, config);\n\n return () => {\n removeBlocker(blockerId);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [blockerId, isActive, addBlocker, removeBlocker]);\n};\n","import { BlockerConfig } from \"../../store\";\n\n/**\n * Creates a blocker configuration object from partial config.\n * Filters out undefined values to create a clean BlockerConfig.\n *\n * @param config - Partial blocker configuration\n * @returns Complete BlockerConfig object\n *\n */\nexport function createBlockerConfig(config: {\n scope?: string | ReadonlyArray<string>;\n reason?: string;\n priority?: number;\n}): BlockerConfig {\n return {\n scope: config.scope,\n reason: config.reason,\n priority: config.priority,\n };\n}\n","import { RefObject, useEffect, useRef } from \"react\";\n\n/**\n * Keeps a ref updated with the latest config value.\n * Useful for accessing current config in callbacks without stale closures.\n *\n * @param config - Configuration object to track\n * @returns Mutable ref that always contains the latest config\n *\n */\nexport function useConfigRef<T>(config: T): RefObject<T> {\n const configRef = useRef(config);\n\n useEffect(() => {\n configRef.current = config;\n }, [config]);\n\n return configRef;\n}\n","import { useCallback, useEffect, useRef } from \"react\";\nimport { useUIBlockingStore } from \"../../store\";\nimport { createBlockerConfig } from \"../useBlocker\";\nimport { useConfigRef } from \"../useConfigRef\";\nimport { ConditionalBlockerConfig } from \"./useConditionalBlocker.types\";\n\n/**\n * Hook for conditional blocking based on a condition function.\n *\n * Periodically checks a condition and blocks/unblocks based on the result.\n * The condition is evaluated at the specified interval (default 1000ms).\n *\n * @param blockerId - Unique identifier for this blocker\n * @param config - Configuration including condition function and check interval\n *\n */\nexport const useConditionalBlocker = <TState = unknown>(\n blockerId: string,\n config: ConditionalBlockerConfig<TState>\n): void => {\n const { addBlocker, removeBlocker } = useUIBlockingStore();\n const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);\n const isBlockedRef = useRef(false);\n const configRef = useConfigRef(config);\n\n const checkCondition = useCallback(() => {\n const currentConfig = configRef.current;\n const shouldBlock = currentConfig.condition(currentConfig.state);\n\n // No state change needed\n if (shouldBlock === isBlockedRef.current) {\n return;\n }\n\n if (shouldBlock) {\n addBlocker(blockerId, createBlockerConfig(currentConfig));\n } else {\n removeBlocker(blockerId);\n }\n isBlockedRef.current = shouldBlock;\n }, [blockerId, addBlocker, removeBlocker, configRef]);\n\n useEffect(() => {\n checkCondition();\n\n const interval = configRef.current.checkInterval ?? 1000;\n intervalRef.current = setInterval(checkCondition, interval);\n\n return (): void => {\n if (intervalRef.current) {\n clearInterval(intervalRef.current);\n intervalRef.current = null;\n }\n if (isBlockedRef.current) {\n removeBlocker(blockerId);\n isBlockedRef.current = false;\n }\n };\n // configRef is stable and doesn't need to be in dependencies\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [checkCondition, blockerId, removeBlocker]);\n};\n","import { useCallback, useState } from \"react\";\nimport { useBlocker } from \"../useBlocker\";\nimport {\n ConfirmableBlockerConfig,\n UseConfirmableBlockerReturn,\n} from \"./useConfirmableBlocker.types\";\n\n/**\n * Hook for creating a confirmable action with blocking UI\n *\n */\nexport const useConfirmableBlocker = (\n blockerId: string,\n config: ConfirmableBlockerConfig\n): UseConfirmableBlockerReturn => {\n const [isDialogOpen, setIsDialogOpen] = useState(false);\n const [isExecuting, setIsExecuting] = useState(false);\n\n useBlocker(\n blockerId,\n {\n ...config,\n reason: config.reason ?? config.confirmMessage,\n },\n isDialogOpen || isExecuting\n );\n\n const execute = useCallback(() => {\n setIsDialogOpen(true);\n }, []);\n\n const onConfirm = useCallback(async () => {\n setIsDialogOpen(false);\n setIsExecuting(true);\n\n try {\n await config.onConfirm();\n } catch (error) {\n console.error(\"[UIBlocking] Confirmable action error:\", error);\n throw error;\n } finally {\n setIsExecuting(false);\n }\n }, [config]);\n\n const onCancel = useCallback(() => {\n setIsDialogOpen(false);\n config.onCancel?.();\n }, [config]);\n\n return {\n execute,\n isDialogOpen,\n isExecuting,\n confirmConfig: {\n title: config.confirmTitle ?? \"Confirm Action\",\n message: config.confirmMessage,\n confirmText: config.confirmButtonText ?? \"Confirm\",\n cancelText: config.cancelButtonText ?? \"Cancel\",\n },\n onConfirm,\n onCancel,\n };\n};\n","import { useUIBlockingStore } from \"../../store\";\n\n/**\n * Hook to check if a scope is currently blocked\n *\n * Returns a boolean indicating whether the specified scope(s) are blocked.\n * Automatically re-renders when the blocking state changes.\n *\n * @param scope - Scope or array of scopes to check (default: \"global\")\n * @returns True if any of the specified scopes are blocked\n *\n */\nexport const useIsBlocked = (scope?: string | ReadonlyArray<string>): boolean => {\n return useUIBlockingStore((state) => state.isBlocked(scope));\n};\n","import type { BlockingSchedule } from \"./useScheduledBlocker.types\";\n\n/**\n * Maximum safe timeout value for setTimeout in JavaScript (~24.8 days).\n * Values larger than this will cause setTimeout to trigger immediately.\n */\nexport const MAX_TIMEOUT_MS = 2147483647;\n\n/**\n * Validates a date value and converts it to timestamp.\n *\n * @param date - Date value as string, Date object, or number\n * @returns Timestamp in milliseconds, or NaN if invalid\n */\nexport function parseDate(date: string | Date | number): number {\n return new Date(date).getTime();\n}\n\n/**\n * Validates if a timestamp is valid (not NaN).\n *\n * @param timestamp - Timestamp to validate\n * @returns True if valid, false otherwise\n */\nexport function isValidTimestamp(timestamp: number): boolean {\n return !Number.isNaN(timestamp);\n}\n\n/**\n * Calculates the end time based on schedule configuration.\n * Duration takes precedence over end time if both are provided.\n *\n * @param schedule - Blocking schedule configuration\n * @param startTime - Start time in milliseconds\n * @returns End time in milliseconds, or undefined if not specified\n */\nexport function calculateEndTime(\n schedule: BlockingSchedule,\n startTime: number\n): number | undefined {\n if (schedule.duration) {\n return startTime + schedule.duration;\n }\n\n if (schedule.end) {\n const endTime = parseDate(schedule.end);\n return isValidTimestamp(endTime) ? endTime : undefined;\n }\n\n return undefined;\n}\n\n/**\n * Validates if a delay is within the safe setTimeout range.\n *\n * @param delay - Delay in milliseconds\n * @returns True if delay is safe to use with setTimeout\n */\nexport function isSafeTimeout(delay: number): boolean {\n return delay > 0 && delay <= MAX_TIMEOUT_MS;\n}\n\n/**\n * Determines if the current time is within a blocking schedule.\n *\n * @param startTime - Schedule start time in milliseconds\n * @param endTime - Schedule end time in milliseconds (optional)\n * @param now - Current time in milliseconds\n * @returns True if currently in the blocking period\n */\nexport function isInBlockingPeriod(\n startTime: number,\n endTime: number | undefined,\n now: number\n): boolean {\n if (startTime > now) {\n return false; // Not started yet\n }\n\n if (!endTime) {\n return true; // No end time means block indefinitely\n }\n\n return endTime > now; // Check if end time hasn't passed\n}\n\n/**\n * Checks if a schedule is completely in the past.\n *\n * @param startTime - Schedule start time in milliseconds\n * @param endTime - Schedule end time in milliseconds (optional)\n * @param now - Current time in milliseconds\n * @returns True if the schedule is in the past\n */\nexport function isScheduleInPast(\n startTime: number,\n endTime: number | undefined,\n now: number\n): boolean {\n if (!endTime) {\n return false; // No end time means it can still be active\n }\n\n return endTime <= now && startTime <= now;\n}\n","import { useCallback, useEffect, useRef } from \"react\";\nimport { useUIBlockingStore } from \"../../store\";\nimport { createBlockerConfig } from \"../useBlocker\";\nimport { useConfigRef } from \"../useConfigRef\";\nimport { ScheduledBlockerConfig } from \"./useScheduledBlocker.types\";\nimport {\n MAX_TIMEOUT_MS,\n calculateEndTime,\n isInBlockingPeriod,\n isSafeTimeout,\n isScheduleInPast,\n isValidTimestamp,\n parseDate,\n} from \"./useScheduledBlocker.utils\";\n\n/**\n * Hook for scheduling UI blocking for a specific time period.\n *\n * Blocks UI during a scheduled maintenance window or time period.\n * Supports start/end times as Date objects, ISO strings, or timestamps.\n * If both duration and end are provided, duration takes precedence.\n *\n * @param blockerId - Unique identifier for this blocker\n * @param config - Configuration including schedule and callbacks\n *\n */\nexport const useScheduledBlocker = (blockerId: string, config: ScheduledBlockerConfig): void => {\n const { addBlocker, removeBlocker } = useUIBlockingStore();\n const timeoutsRef = useRef<{\n start?: ReturnType<typeof setTimeout>;\n end?: ReturnType<typeof setTimeout>;\n }>({});\n const configRef = useConfigRef(config);\n\n const cleanup = useCallback(() => {\n if (timeoutsRef.current.start) {\n clearTimeout(timeoutsRef.current.start);\n timeoutsRef.current.start = undefined;\n }\n if (timeoutsRef.current.end) {\n clearTimeout(timeoutsRef.current.end);\n timeoutsRef.current.end = undefined;\n }\n }, []);\n\n useEffect(() => {\n const currentConfig = configRef.current;\n const startTime = parseDate(currentConfig.schedule.start);\n const now = Date.now();\n\n // Validate start time\n if (!isValidTimestamp(startTime)) {\n console.error(`[UIBlocking] Invalid start time for blocker \"${blockerId}\"`);\n return;\n }\n\n const scheduleEnd = (): void => {\n const endTime = calculateEndTime(currentConfig.schedule, startTime);\n if (!endTime) {\n return;\n }\n\n const remainingTime = endTime - Date.now();\n if (remainingTime > 0) {\n timeoutsRef.current.end = setTimeout(() => {\n configRef.current.onScheduleEnd?.();\n removeBlocker(blockerId);\n }, remainingTime);\n }\n };\n\n const startBlocking = (): void => {\n const cfg = configRef.current;\n addBlocker(blockerId, createBlockerConfig(cfg));\n cfg.onScheduleStart?.();\n scheduleEnd();\n };\n\n // If start time hasn't arrived yet\n if (startTime > now) {\n const delay = startTime - now;\n\n if (!isSafeTimeout(delay)) {\n console.warn(\n `[UIBlocking] Schedule delay exceeds maximum timeout (${MAX_TIMEOUT_MS.toString()}ms) for blocker \"${blockerId}\"`\n );\n return;\n }\n\n timeoutsRef.current.start = setTimeout(startBlocking, delay);\n }\n // If already in blocking period or should start immediately\n else {\n const endTime = calculateEndTime(currentConfig.schedule, startTime);\n\n if (isInBlockingPeriod(startTime, endTime, now)) {\n startBlocking();\n } else if (isScheduleInPast(startTime, endTime, now)) {\n console.warn(`[UIBlocking] Schedule is in the past for blocker \"${blockerId}\"`);\n }\n }\n\n return (): void => {\n cleanup();\n removeBlocker(blockerId);\n };\n // configRef is stable and doesn't need to be in dependencies\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [blockerId, addBlocker, removeBlocker, cleanup]);\n};\n","import { AnalyticsEventData } from \"./analyticsMiddleware.types\";\nimport { MiddlewareContext } from \"./middleware.types\";\n\nconst capitalizeFirst = (str: string): string => {\n return str.charAt(0).toUpperCase() + str.slice(1);\n};\n\nexport const buildEventData = (context: MiddlewareContext): AnalyticsEventData => {\n const eventData: AnalyticsEventData = {\n blocker_id: context.blockerId,\n };\n const { scope, reason, priority } = context.config ?? {};\n\n if (scope !== undefined) {\n eventData.scope = Array.isArray(scope) ? scope.join(\",\") : scope;\n }\n\n if (reason !== undefined) {\n eventData.reason = reason;\n }\n\n if (priority !== undefined) {\n eventData.priority = priority;\n }\n\n return eventData;\n};\n\nexport const trackGoogleAnalytics = (action: string, eventData: AnalyticsEventData): void => {\n if (window.gtag) {\n window.gtag(\"event\", `ui_blocking_${action}`, eventData);\n }\n};\n\nexport const trackMixpanel = (action: string, eventData: AnalyticsEventData): void => {\n if (window.mixpanel) {\n const eventName = `UI Blocking ${action.split(\"_\").map(capitalizeFirst).join(\" \")}`;\n\n window.mixpanel.track(eventName, eventData);\n }\n};\n\nexport const trackAmplitude = (action: string, eventData: AnalyticsEventData): void => {\n if (window.amplitude) {\n const eventName = `UI Blocking ${action.split(\"_\").map(capitalizeFirst).join(\" \")}`;\n\n window.amplitude.track(eventName, eventData);\n }\n};\n\nexport const trackCustom = (\n trackFn: (event: string, data: AnalyticsEventData) => void,\n action: string,\n eventData: AnalyticsEventData\n): void => {\n try {\n trackFn(`ui_blocking_${action}`, eventData);\n } catch {\n // Silently ignore errors in custom tracker\n }\n};\n","import { AnalyticsConfig, AnalyticsEventData } from \"./analyticsMiddleware.types\";\nimport {\n buildEventData,\n trackAmplitude,\n trackCustom,\n trackGoogleAnalytics,\n trackMixpanel,\n} from \"./analyticsMiddleware.utils\";\nimport { Middleware, MiddlewareContext } from \"./middleware.types\";\n\nconst trackEvent = (\n config: AnalyticsConfig,\n context: MiddlewareContext,\n eventData: AnalyticsEventData\n): void => {\n if (\"provider\" in config) {\n switch (config.provider) {\n case \"ga\":\n trackGoogleAnalytics(context.action, eventData);\n return;\n case \"mixpanel\":\n trackMixpanel(context.action, eventData);\n return;\n case \"amplitude\":\n trackAmplitude(context.action, eventData);\n return;\n }\n }\n\n if (\"track\" in config) {\n trackCustom(config.track, context.action, eventData);\n }\n};\n\nexport const createAnalyticsMiddleware = (config: AnalyticsConfig): Middleware => {\n return (context) => {\n const eventData = buildEventData(context);\n\n trackEvent(config, context, eventData);\n };\n};\n","import { MiddlewareBlockerConfig, MiddlewareContext } from \"./middleware.types\";\n\nexport const getActionEmoji = (action: string): string => {\n switch (action) {\n case \"add\":\n return \"➕\";\n case \"remove\":\n return \"➖\";\n case \"update\":\n return \"🔄\";\n case \"cancel\":\n return \"❌\";\n case \"timeout\":\n return \"⏱️\";\n default:\n return \"❓\";\n }\n};\n\nconst extractConfigDetails = (config?: MiddlewareBlockerConfig): Record<string, unknown> => {\n if (!config) {\n return {};\n }\n\n const { scope, reason, priority } = config;\n\n const details: Record<string, unknown> = {\n scope,\n reason,\n };\n\n if (priority !== undefined) {\n details.priority = priority;\n }\n\n return details;\n};\n\nexport const formatLogData = (context: MiddlewareContext): Record<string, unknown> => {\n const configDetails = extractConfigDetails(context.config);\n\n if (context.prevState) {\n return {\n config: configDetails,\n prevState: extractConfigDetails(context.prevState),\n };\n }\n\n return configDetails;\n};\n","import { formatLogData, getActionEmoji } from \"./loggerMiddleware.utils\";\nimport { Middleware } from \"./middleware.types\";\n\nconst LOG_PREFIX = \"[UIBlocking]\";\n\nexport const loggerMiddleware: Middleware = (context) => {\n const emoji = getActionEmoji(context.action);\n const logData = formatLogData(context);\n\n console.log(LOG_PREFIX, emoji, context.blockerId, logData);\n};\n","export const handleAddAction = (\n blockerId: string,\n timestamp: number,\n blockStartTimes: Map<string, number>\n): void => {\n blockStartTimes.set(blockerId, timestamp);\n};\n","import { Middleware, MiddlewareContext } from \"./middleware.types\";\nimport { PerformanceConfig } from \"./performanceMiddleware.types\";\nimport { handleAddAction } from \"./performanceMiddleware.utils\";\n\nconst DEFAULT_SLOW_BLOCK_THRESHOLD = 3000;\nconst ACTION_ADD = \"add\";\nconst ACTION_REMOVE = \"remove\";\n\nconst handleRemoveAction = (\n context: MiddlewareContext,\n blockStartTimes: Map<string, number>,\n slowBlockThreshold: number,\n onSlowBlock?: (blockerId: string, duration: number) => void\n): void => {\n const startTime = blockStartTimes.get(context.blockerId);\n\n if (startTime === undefined) {\n return;\n }\n\n const duration = context.timestamp - startTime;\n blockStartTimes.delete(context.blockerId);\n\n if (duration >= slowBlockThreshold) {\n console.warn(\n `[UIBlocking] Slow block detected: \"${context.blockerId}\" took ${duration.toString()}ms`\n );\n\n onSlowBlock?.(context.blockerId, duration);\n }\n};\n\nexport const createPerformanceMiddleware = (config: PerformanceConfig = {}): Middleware => {\n const { slowBlockThreshold = DEFAULT_SLOW_BLOCK_THRESHOLD, onSlowBlock } = config;\n const blockStartTimes = new Map<string, number>();\n\n return (context) => {\n if (context.action === ACTION_ADD) {\n handleAddAction(context.blockerId, context.timestamp, blockStartTimes);\n } else if (context.action === ACTION_REMOVE) {\n handleRemoveAction(context, blockStartTimes, slowBlockThreshold, onSlowBlock);\n }\n };\n};\n"]}
1
+ {"version":3,"sources":["../src/store/uiBlockingStore.constants.ts","../src/store/uiBlockingStore.utils.ts","../src/store/uiBlockingStore.actions.ts","../src/store/uiBlockingStore.config.ts","../src/store/uiBlockingStore.store.ts","../src/hooks/useAsyncAction/useAsyncAction.ts","../src/hooks/useBlocker/useBlocker.ts","../src/hooks/useBlocker/useBlocker.utils.ts","../src/hooks/useConfigRef.ts","../src/hooks/useConditionalBlocker/useConditionalBlocker.ts","../src/hooks/useConfirmableBlocker/useConfirmableBlocker.ts","../src/hooks/useIsBlocked/useIsBlocked.ts","../src/hooks/useScheduledBlocker/useScheduledBlocker.utils.ts","../src/hooks/useScheduledBlocker/useScheduledBlocker.ts","../src/middleware/analyticsMiddleware.utils.ts","../src/middleware/analyticsMiddleware.ts","../src/middleware/loggerMiddleware.utils.ts","../src/middleware/loggerMiddleware.ts","../src/middleware/performanceMiddleware.utils.ts","../src/middleware/performanceMiddleware.ts"],"names":["createStore","useStore","useShallow","devtools","useCallback","useEffect","useRef","useState"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Default values and constants for UI Blocking Store\n */\n\n/**\n * Default scope for blockers\n */\nexport const DEFAULT_SCOPE = \"global\" as const;\n\n/**\n * Default reason when none is provided\n */\nexport const DEFAULT_REASON = \"Unknown\" as const;\n\n/**\n * Default priority for blockers\n */\nexport const DEFAULT_PRIORITY = 0 as const;\n\n/**\n * Default priority for async actions\n */\nexport const ASYNC_ACTION_PRIORITY = 20 as const;\n\n/**\n * DevTools store name\n */\nexport const DEVTOOLS_NAME = \"UIBlocking\" as const;\n","import { StateCreator, StoreApi, StoreMutators, createStore, useStore } from \"zustand\";\nimport { useShallow } from \"zustand/shallow\";\n\n/**\n * Creates a Zustand store with automatic shallow comparison for all selectors\n *\n * This utility wraps the standard Zustand store creation and automatically applies\n * `useShallow` to all selectors, preventing unnecessary re-renders when selected\n * values haven't changed (shallow equality).\n *\n * @template StoreState - The type of the store state\n * @template TMutators - Array of middleware mutators (e.g., devtools, persist)\n *\n * @param storeCreator - The state creator function for Zustand\n * @returns Object containing the store hook and store API\n *\n * @see https://docs.pmnd.rs/zustand/guides/prevent-rerenders-with-use-shallow\n */\nexport function createShallowStore<\n StoreState,\n TMutators extends Array<[keyof StoreMutators<StoreState, StoreState>, unknown]> = [],\n>(\n storeCreator: StateCreator<StoreState, [], TMutators, StoreState>\n): {\n useStore: <T>(selector: (state: StoreState) => T) => T;\n useStoreApi: StoreApi<StoreState>;\n} {\n const storeApi: StoreApi<StoreState> = createStore<StoreState, TMutators>(storeCreator);\n\n const useScopedStore = <T>(selector: (state: StoreState) => T): T => {\n return useStore(storeApi, useShallow(selector));\n };\n\n return { useStore: useScopedStore, useStoreApi: storeApi };\n}\n\n/**\n * Normalize scope to array format\n *\n * @param scope - Single scope or array of scopes\n * @returns Array of scopes\n *\n * @internal\n */\nexport function normalizeScopeToArray(scope: string | ReadonlyArray<string>): Array<string> {\n if (typeof scope === \"string\") {\n return [scope];\n }\n return Array.from(scope);\n}\n","import { Middleware, MiddlewareContext } from \"../middleware\";\nimport { DEFAULT_PRIORITY, DEFAULT_REASON, DEFAULT_SCOPE } from \"./uiBlockingStore.constants\";\nimport { normalizeScopeToArray } from \"./uiBlockingStore.utils\";\nimport type {\n BlockerConfig,\n BlockerInfo,\n StoredBlocker,\n UIBlockingStore,\n} from \"./uiBlockingStore.types\";\nimport type { StateCreator } from \"zustand\";\n\n/**\n * UI Blocking Store Slice\n *\n * Implements the state and actions for UI blocking management.\n * This slice follows the Zustand slice pattern for better code organization.\n */\nexport const createUIBlockingActions: StateCreator<UIBlockingStore, [], [], UIBlockingStore> = (\n set,\n get\n) => ({\n // State\n activeBlockers: new Map(),\n middlewares: new Map(),\n\n registerMiddleware: (name: string, middleware: Middleware) => {\n set((state) => {\n const newMiddlewares = new Map(state.middlewares);\n newMiddlewares.set(name, middleware);\n return { middlewares: newMiddlewares };\n });\n console.log(`[UIBlocking] Registered middleware: ${name}`);\n },\n\n unregisterMiddleware: (name: string) => {\n set((state) => {\n const newMiddlewares = new Map(state.middlewares);\n newMiddlewares.delete(name);\n return { middlewares: newMiddlewares };\n });\n console.log(`[UIBlocking] Unregistered middleware: ${name}`);\n },\n\n runMiddlewares: async (context: MiddlewareContext) => {\n const { middlewares } = get();\n\n for (const [name, middleware] of middlewares) {\n try {\n await middleware(context);\n } catch (error) {\n console.error(`[UIBlocking] Middleware \"${name}\" error:`, error);\n }\n }\n },\n\n // Actions\n /**\n * Add a blocker to the store\n *\n * @param id - Unique blocker identifier\n * @param config - Optional blocker configuration\n *\n */\n addBlocker: (id: string, config: BlockerConfig = {}): void => {\n set((state) => {\n const newBlockers = new Map(state.activeBlockers);\n const storedBlocker: StoredBlocker = {\n scope: config.scope ?? DEFAULT_SCOPE,\n reason: config.reason ?? DEFAULT_REASON,\n priority: config.priority ?? DEFAULT_PRIORITY,\n timestamp: config.timestamp ?? Date.now(),\n };\n newBlockers.set(id, storedBlocker);\n\n return { activeBlockers: newBlockers };\n });\n\n void get().runMiddlewares({\n action: \"add\",\n blockerId: id,\n config: {\n scope: config.scope,\n reason: config.reason,\n priority: config.priority,\n },\n timestamp: Date.now(),\n });\n },\n\n /**\n * Remove a blocker from the store\n *\n * @param id - Blocker identifier to remove\n *\n */\n removeBlocker: (id: string): void => {\n const prevBlocker = get().activeBlockers.get(id);\n\n set((state) => {\n const newBlockers = new Map(state.activeBlockers);\n newBlockers.delete(id);\n\n return { activeBlockers: newBlockers };\n });\n\n if (prevBlocker) {\n void get().runMiddlewares({\n action: \"remove\",\n blockerId: id,\n config: prevBlocker,\n timestamp: Date.now(),\n prevState: prevBlocker,\n });\n }\n },\n\n /**\n * Check if a scope is currently blocked\n *\n * @param scope - Scope or array of scopes to check (default: \"global\")\n * @returns True if any of the scopes are blocked\n *\n */\n isBlocked: (scope: string | ReadonlyArray<string> = DEFAULT_SCOPE): boolean => {\n const { activeBlockers } = get();\n const scopes = normalizeScopeToArray(scope);\n\n for (const [, blocker] of activeBlockers) {\n // Global blocking blocks everything\n if (blocker.scope === DEFAULT_SCOPE) {\n return true;\n }\n\n // Check scope intersection\n const blockerScopes = normalizeScopeToArray(blocker.scope);\n\n if (scopes.some((s) => blockerScopes.includes(s))) {\n return true;\n }\n }\n\n return false;\n },\n\n /**\n * Get detailed blocking information for a specific scope\n *\n * @param scope - Scope to get blocking information for\n * @returns Array of blockers affecting the scope, sorted by priority (highest first)\n *\n */\n getBlockingInfo: (scope: string): ReadonlyArray<BlockerInfo> => {\n const { activeBlockers } = get();\n const blockers: Array<BlockerInfo> = [];\n\n for (const [id, blocker] of activeBlockers) {\n const blockerScopes = normalizeScopeToArray(blocker.scope);\n\n if (blocker.scope === DEFAULT_SCOPE || blockerScopes.includes(scope)) {\n blockers.push({ id, ...blocker });\n }\n }\n\n return blockers.sort((a, b) => b.priority - a.priority);\n },\n\n /**\n * Clear all blockers from the store\n */\n clearAllBlockers: (): void => {\n set({ activeBlockers: new Map() });\n },\n\n /**\n * Clear all blockers for a specific scope\n *\n * @param scope - Scope to clear blockers for\n *\n */\n clearBlockersForScope: (scope: string): void => {\n set((state) => {\n const newBlockers = new Map();\n\n for (const [id, blocker] of state.activeBlockers) {\n const blockerScopes = normalizeScopeToArray(blocker.scope);\n\n if (!blockerScopes.includes(scope)) {\n newBlockers.set(id, blocker);\n }\n }\n\n return { activeBlockers: newBlockers };\n });\n },\n});\n","import { DEVTOOLS_NAME } from \"./uiBlockingStore.constants\";\nimport type { DevtoolsOptions } from \"zustand/middleware\";\n\n/**\n * DevTools configuration for UI Blocking Store\n *\n * Enables Redux DevTools integration only in development mode\n * for better debugging experience without production overhead.\n */\nexport const devtoolsConfig: DevtoolsOptions = {\n name: DEVTOOLS_NAME,\n enabled: process.env.NODE_ENV !== \"production\",\n};\n","import { devtools } from \"zustand/middleware\";\nimport { createUIBlockingActions } from \"./uiBlockingStore.actions\";\nimport { devtoolsConfig } from \"./uiBlockingStore.config\";\nimport { createShallowStore } from \"./uiBlockingStore.utils\";\nimport type { UIBlockingStore } from \"./uiBlockingStore.types\";\n\n/**\n * UI Blocking Store\n *\n * Global Zustand store for managing UI blocking state across the application.\n *\n * Features:\n * - Priority-based blocking system\n * - Scope-based blocking (global, specific areas, or multiple scopes)\n * - Automatic cleanup on unmount (when using hooks)\n * - DevTools integration for debugging\n * - Automatic shallow comparison for selectors\n *\n */\nconst { useStore: useUIBlockingStore, useStoreApi: uiBlockingStoreApi } = createShallowStore<\n UIBlockingStore,\n [[\"zustand/devtools\", never]]\n>(devtools(createUIBlockingActions, devtoolsConfig));\n\nexport { useUIBlockingStore, uiBlockingStoreApi };\n","import { useCallback } from \"react\";\nimport { ASYNC_ACTION_PRIORITY, useUIBlockingStore } from \"../../store\";\n\n/**\n * Hook to wrap async functions with automatic blocking/unblocking\n *\n * Creates a wrapper function that automatically adds a blocker before executing\n * the async function and removes it after completion (success or failure).\n *\n * @template T - The return type of the async function\n * @param actionId - Unique identifier for the action (used in blocker ID and reason)\n * @param scope - Scope(s) to block during execution (default: \"global\")\n * @returns Function that wraps async functions with blocking behavior\n *\n */\nexport const useAsyncAction = <T = unknown>(\n actionId: string,\n scope?: string | ReadonlyArray<string>\n): ((asyncFn: () => Promise<T>) => Promise<T>) => {\n const { addBlocker, removeBlocker } = useUIBlockingStore((state) => ({\n addBlocker: state.addBlocker,\n removeBlocker: state.removeBlocker,\n }));\n\n const executeWithBlocking = useCallback(\n async (asyncFn: () => Promise<T>): Promise<T> => {\n const blockerId = `${actionId}-${Date.now().toString()}`;\n\n try {\n addBlocker(blockerId, {\n scope,\n reason: `Executing ${actionId}`,\n priority: ASYNC_ACTION_PRIORITY,\n });\n\n return await asyncFn();\n } finally {\n removeBlocker(blockerId);\n }\n },\n [actionId, scope, addBlocker, removeBlocker]\n );\n\n return executeWithBlocking;\n};\n","import { useEffect } from \"react\";\nimport { type BlockerConfig, useUIBlockingStore } from \"../../store\";\n\n/**\n * Hook to automatically add and remove a blocker based on component lifecycle\n *\n * Automatically adds a blocker when the component mounts (or when activated)\n * and removes it when the component unmounts (or when deactivated).\n *\n * @param blockerId - Unique identifier for the blocker\n * @param config - Blocker configuration (scope, reason, priority)\n * @param isActive - Whether the blocker is currently active (default: true)\n *\n */\nexport const useBlocker = (blockerId: string, config: BlockerConfig, isActive = true): void => {\n const { addBlocker, removeBlocker } = useUIBlockingStore((state) => ({\n addBlocker: state.addBlocker,\n removeBlocker: state.removeBlocker,\n }));\n\n useEffect(() => {\n if (!isActive || !blockerId) {\n return;\n }\n\n addBlocker(blockerId, config);\n\n return () => {\n removeBlocker(blockerId);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [blockerId, isActive, addBlocker, removeBlocker]);\n};\n","import { BlockerConfig } from \"../../store\";\n\n/**\n * Creates a blocker configuration object from partial config.\n * Filters out undefined values to create a clean BlockerConfig.\n *\n * @param config - Partial blocker configuration\n * @returns Complete BlockerConfig object\n *\n */\nexport function createBlockerConfig(config: {\n scope?: string | ReadonlyArray<string>;\n reason?: string;\n priority?: number;\n}): BlockerConfig {\n return {\n scope: config.scope,\n reason: config.reason,\n priority: config.priority,\n };\n}\n","import { RefObject, useEffect, useRef } from \"react\";\n\n/**\n * Keeps a ref updated with the latest config value.\n * Useful for accessing current config in callbacks without stale closures.\n *\n * @param config - Configuration object to track\n * @returns Mutable ref that always contains the latest config\n *\n */\nexport function useConfigRef<T>(config: T): RefObject<T> {\n const configRef = useRef(config);\n\n useEffect(() => {\n configRef.current = config;\n }, [config]);\n\n return configRef;\n}\n","import { useCallback, useEffect, useRef } from \"react\";\nimport { useUIBlockingStore } from \"../../store\";\nimport { createBlockerConfig } from \"../useBlocker\";\nimport { useConfigRef } from \"../useConfigRef\";\nimport { ConditionalBlockerConfig } from \"./useConditionalBlocker.types\";\n\n/**\n * Hook for conditional blocking based on a condition function.\n *\n * Periodically checks a condition and blocks/unblocks based on the result.\n * The condition is evaluated at the specified interval (default 1000ms).\n *\n * @param blockerId - Unique identifier for this blocker\n * @param config - Configuration including condition function and check interval\n *\n */\nexport const useConditionalBlocker = <TState = unknown>(\n blockerId: string,\n config: ConditionalBlockerConfig<TState>\n): void => {\n const { addBlocker, removeBlocker } = useUIBlockingStore((state) => ({\n addBlocker: state.addBlocker,\n removeBlocker: state.removeBlocker,\n }));\n const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);\n const isBlockedRef = useRef(false);\n const configRef = useConfigRef(config);\n\n const checkCondition = useCallback(() => {\n const currentConfig = configRef.current;\n const shouldBlock = currentConfig.condition(currentConfig.state);\n\n // No state change needed\n if (shouldBlock === isBlockedRef.current) {\n return;\n }\n\n if (shouldBlock) {\n addBlocker(blockerId, createBlockerConfig(currentConfig));\n } else {\n removeBlocker(blockerId);\n }\n isBlockedRef.current = shouldBlock;\n }, [blockerId, addBlocker, removeBlocker, configRef]);\n\n useEffect(() => {\n checkCondition();\n\n const interval = configRef.current.checkInterval ?? 1000;\n intervalRef.current = setInterval(checkCondition, interval);\n\n return (): void => {\n if (intervalRef.current) {\n clearInterval(intervalRef.current);\n intervalRef.current = null;\n }\n if (isBlockedRef.current) {\n removeBlocker(blockerId);\n isBlockedRef.current = false;\n }\n };\n // configRef is stable and doesn't need to be in dependencies\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [checkCondition, blockerId, removeBlocker]);\n};\n","import { useCallback, useState } from \"react\";\nimport { useBlocker } from \"../useBlocker\";\nimport {\n ConfirmableBlockerConfig,\n UseConfirmableBlockerReturn,\n} from \"./useConfirmableBlocker.types\";\n\n/**\n * Hook for creating a confirmable action with blocking UI\n *\n */\nexport const useConfirmableBlocker = (\n blockerId: string,\n config: ConfirmableBlockerConfig\n): UseConfirmableBlockerReturn => {\n const [isDialogOpen, setIsDialogOpen] = useState(false);\n const [isExecuting, setIsExecuting] = useState(false);\n\n useBlocker(\n blockerId,\n {\n ...config,\n reason: config.reason ?? config.confirmMessage,\n },\n isDialogOpen || isExecuting\n );\n\n const execute = useCallback(() => {\n setIsDialogOpen(true);\n }, []);\n\n const onConfirm = useCallback(async () => {\n setIsDialogOpen(false);\n setIsExecuting(true);\n\n try {\n await config.onConfirm();\n } catch (error) {\n console.error(\"[UIBlocking] Confirmable action error:\", error);\n throw error;\n } finally {\n setIsExecuting(false);\n }\n }, [config]);\n\n const onCancel = useCallback(() => {\n setIsDialogOpen(false);\n config.onCancel?.();\n }, [config]);\n\n return {\n execute,\n isDialogOpen,\n isExecuting,\n confirmConfig: {\n title: config.confirmTitle ?? \"Confirm Action\",\n message: config.confirmMessage,\n confirmText: config.confirmButtonText ?? \"Confirm\",\n cancelText: config.cancelButtonText ?? \"Cancel\",\n },\n onConfirm,\n onCancel,\n };\n};\n","import { useUIBlockingStore } from \"../../store\";\n\n/**\n * Hook to check if a scope is currently blocked\n *\n * Returns a boolean indicating whether the specified scope(s) are blocked.\n * Automatically re-renders when the blocking state changes.\n *\n * @param scope - Scope or array of scopes to check (default: \"global\")\n * @returns True if any of the specified scopes are blocked\n *\n */\nexport const useIsBlocked = (scope?: string | ReadonlyArray<string>): boolean => {\n return useUIBlockingStore((state) => state.isBlocked(scope));\n};\n","import type { BlockingSchedule } from \"./useScheduledBlocker.types\";\n\n/**\n * Maximum safe timeout value for setTimeout in JavaScript (~24.8 days).\n * Values larger than this will cause setTimeout to trigger immediately.\n */\nexport const MAX_TIMEOUT_MS = 2147483647;\n\n/**\n * Validates a date value and converts it to timestamp.\n *\n * @param date - Date value as string, Date object, or number\n * @returns Timestamp in milliseconds, or NaN if invalid\n */\nexport function parseDate(date: string | Date | number): number {\n return new Date(date).getTime();\n}\n\n/**\n * Validates if a timestamp is valid (not NaN).\n *\n * @param timestamp - Timestamp to validate\n * @returns True if valid, false otherwise\n */\nexport function isValidTimestamp(timestamp: number): boolean {\n return !Number.isNaN(timestamp);\n}\n\n/**\n * Calculates the end time based on schedule configuration.\n * Duration takes precedence over end time if both are provided.\n *\n * @param schedule - Blocking schedule configuration\n * @param startTime - Start time in milliseconds\n * @returns End time in milliseconds, or undefined if not specified\n */\nexport function calculateEndTime(\n schedule: BlockingSchedule,\n startTime: number\n): number | undefined {\n if (schedule.duration) {\n return startTime + schedule.duration;\n }\n\n if (schedule.end) {\n const endTime = parseDate(schedule.end);\n return isValidTimestamp(endTime) ? endTime : undefined;\n }\n\n return undefined;\n}\n\n/**\n * Validates if a delay is within the safe setTimeout range.\n *\n * @param delay - Delay in milliseconds\n * @returns True if delay is safe to use with setTimeout\n */\nexport function isSafeTimeout(delay: number): boolean {\n return delay > 0 && delay <= MAX_TIMEOUT_MS;\n}\n\n/**\n * Determines if the current time is within a blocking schedule.\n *\n * @param startTime - Schedule start time in milliseconds\n * @param endTime - Schedule end time in milliseconds (optional)\n * @param now - Current time in milliseconds\n * @returns True if currently in the blocking period\n */\nexport function isInBlockingPeriod(\n startTime: number,\n endTime: number | undefined,\n now: number\n): boolean {\n if (startTime > now) {\n return false; // Not started yet\n }\n\n if (!endTime) {\n return true; // No end time means block indefinitely\n }\n\n return endTime > now; // Check if end time hasn't passed\n}\n\n/**\n * Checks if a schedule is completely in the past.\n *\n * @param startTime - Schedule start time in milliseconds\n * @param endTime - Schedule end time in milliseconds (optional)\n * @param now - Current time in milliseconds\n * @returns True if the schedule is in the past\n */\nexport function isScheduleInPast(\n startTime: number,\n endTime: number | undefined,\n now: number\n): boolean {\n if (!endTime) {\n return false; // No end time means it can still be active\n }\n\n return endTime <= now && startTime <= now;\n}\n","import { useCallback, useEffect, useRef } from \"react\";\nimport { useUIBlockingStore } from \"../../store\";\nimport { createBlockerConfig } from \"../useBlocker\";\nimport { useConfigRef } from \"../useConfigRef\";\nimport { ScheduledBlockerConfig } from \"./useScheduledBlocker.types\";\nimport {\n MAX_TIMEOUT_MS,\n calculateEndTime,\n isInBlockingPeriod,\n isSafeTimeout,\n isScheduleInPast,\n isValidTimestamp,\n parseDate,\n} from \"./useScheduledBlocker.utils\";\n\n/**\n * Hook for scheduling UI blocking for a specific time period.\n *\n * Blocks UI during a scheduled maintenance window or time period.\n * Supports start/end times as Date objects, ISO strings, or timestamps.\n * If both duration and end are provided, duration takes precedence.\n *\n * @param blockerId - Unique identifier for this blocker\n * @param config - Configuration including schedule and callbacks\n *\n */\nexport const useScheduledBlocker = (blockerId: string, config: ScheduledBlockerConfig): void => {\n const { addBlocker, removeBlocker } = useUIBlockingStore((state) => ({\n addBlocker: state.addBlocker,\n removeBlocker: state.removeBlocker,\n }));\n const timeoutsRef = useRef<{\n start?: ReturnType<typeof setTimeout>;\n end?: ReturnType<typeof setTimeout>;\n }>({});\n const configRef = useConfigRef(config);\n\n const cleanup = useCallback(() => {\n if (timeoutsRef.current.start) {\n clearTimeout(timeoutsRef.current.start);\n timeoutsRef.current.start = undefined;\n }\n if (timeoutsRef.current.end) {\n clearTimeout(timeoutsRef.current.end);\n timeoutsRef.current.end = undefined;\n }\n }, []);\n\n useEffect(() => {\n const currentConfig = configRef.current;\n const startTime = parseDate(currentConfig.schedule.start);\n const now = Date.now();\n\n // Validate start time\n if (!isValidTimestamp(startTime)) {\n console.error(`[UIBlocking] Invalid start time for blocker \"${blockerId}\"`);\n return;\n }\n\n const scheduleEnd = (): void => {\n const endTime = calculateEndTime(currentConfig.schedule, startTime);\n if (!endTime) {\n return;\n }\n\n const remainingTime = endTime - Date.now();\n if (remainingTime > 0) {\n timeoutsRef.current.end = setTimeout(() => {\n configRef.current.onScheduleEnd?.();\n removeBlocker(blockerId);\n }, remainingTime);\n }\n };\n\n const startBlocking = (): void => {\n const cfg = configRef.current;\n addBlocker(blockerId, createBlockerConfig(cfg));\n cfg.onScheduleStart?.();\n scheduleEnd();\n };\n\n // If start time hasn't arrived yet\n if (startTime > now) {\n const delay = startTime - now;\n\n if (!isSafeTimeout(delay)) {\n console.warn(\n `[UIBlocking] Schedule delay exceeds maximum timeout (${MAX_TIMEOUT_MS.toString()}ms) for blocker \"${blockerId}\"`\n );\n return;\n }\n\n timeoutsRef.current.start = setTimeout(startBlocking, delay);\n }\n // If already in blocking period or should start immediately\n else {\n const endTime = calculateEndTime(currentConfig.schedule, startTime);\n\n if (isInBlockingPeriod(startTime, endTime, now)) {\n startBlocking();\n } else if (isScheduleInPast(startTime, endTime, now)) {\n console.warn(`[UIBlocking] Schedule is in the past for blocker \"${blockerId}\"`);\n }\n }\n\n return (): void => {\n cleanup();\n removeBlocker(blockerId);\n };\n // configRef is stable and doesn't need to be in dependencies\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [blockerId, addBlocker, removeBlocker, cleanup]);\n};\n","import { AnalyticsEventData } from \"./analyticsMiddleware.types\";\nimport { MiddlewareContext } from \"./middleware.types\";\n\nconst capitalizeFirst = (str: string): string => {\n return str.charAt(0).toUpperCase() + str.slice(1);\n};\n\nexport const buildEventData = (context: MiddlewareContext): AnalyticsEventData => {\n const eventData: AnalyticsEventData = {\n blocker_id: context.blockerId,\n };\n const { scope, reason, priority } = context.config ?? {};\n\n if (scope !== undefined) {\n eventData.scope = Array.isArray(scope) ? scope.join(\",\") : scope;\n }\n\n if (reason !== undefined) {\n eventData.reason = reason;\n }\n\n if (priority !== undefined) {\n eventData.priority = priority;\n }\n\n return eventData;\n};\n\nexport const trackGoogleAnalytics = (action: string, eventData: AnalyticsEventData): void => {\n if (window.gtag) {\n window.gtag(\"event\", `ui_blocking_${action}`, eventData);\n }\n};\n\nexport const trackMixpanel = (action: string, eventData: AnalyticsEventData): void => {\n if (window.mixpanel) {\n const eventName = `UI Blocking ${action.split(\"_\").map(capitalizeFirst).join(\" \")}`;\n\n window.mixpanel.track(eventName, eventData);\n }\n};\n\nexport const trackAmplitude = (action: string, eventData: AnalyticsEventData): void => {\n if (window.amplitude) {\n const eventName = `UI Blocking ${action.split(\"_\").map(capitalizeFirst).join(\" \")}`;\n\n window.amplitude.track(eventName, eventData);\n }\n};\n\nexport const trackCustom = (\n trackFn: (event: string, data: AnalyticsEventData) => void,\n action: string,\n eventData: AnalyticsEventData\n): void => {\n try {\n trackFn(`ui_blocking_${action}`, eventData);\n } catch {\n // Silently ignore errors in custom tracker\n }\n};\n","import { AnalyticsConfig, AnalyticsEventData } from \"./analyticsMiddleware.types\";\nimport {\n buildEventData,\n trackAmplitude,\n trackCustom,\n trackGoogleAnalytics,\n trackMixpanel,\n} from \"./analyticsMiddleware.utils\";\nimport { Middleware, MiddlewareContext } from \"./middleware.types\";\n\nconst trackEvent = (\n config: AnalyticsConfig,\n context: MiddlewareContext,\n eventData: AnalyticsEventData\n): void => {\n if (\"provider\" in config) {\n switch (config.provider) {\n case \"ga\":\n trackGoogleAnalytics(context.action, eventData);\n return;\n case \"mixpanel\":\n trackMixpanel(context.action, eventData);\n return;\n case \"amplitude\":\n trackAmplitude(context.action, eventData);\n return;\n }\n }\n\n if (\"track\" in config) {\n trackCustom(config.track, context.action, eventData);\n }\n};\n\nexport const createAnalyticsMiddleware = (config: AnalyticsConfig): Middleware => {\n return (context) => {\n const eventData = buildEventData(context);\n\n trackEvent(config, context, eventData);\n };\n};\n","import { MiddlewareBlockerConfig, MiddlewareContext } from \"./middleware.types\";\n\nexport const getActionEmoji = (action: string): string => {\n switch (action) {\n case \"add\":\n return \"➕\";\n case \"remove\":\n return \"➖\";\n case \"update\":\n return \"🔄\";\n case \"cancel\":\n return \"❌\";\n case \"timeout\":\n return \"⏱️\";\n default:\n return \"❓\";\n }\n};\n\nconst extractConfigDetails = (config?: MiddlewareBlockerConfig): Record<string, unknown> => {\n if (!config) {\n return {};\n }\n\n const { scope, reason, priority } = config;\n\n const details: Record<string, unknown> = {\n scope,\n reason,\n };\n\n if (priority !== undefined) {\n details.priority = priority;\n }\n\n return details;\n};\n\nexport const formatLogData = (context: MiddlewareContext): Record<string, unknown> => {\n const configDetails = extractConfigDetails(context.config);\n\n if (context.prevState) {\n return {\n config: configDetails,\n prevState: extractConfigDetails(context.prevState),\n };\n }\n\n return configDetails;\n};\n","import { formatLogData, getActionEmoji } from \"./loggerMiddleware.utils\";\nimport { Middleware } from \"./middleware.types\";\n\nconst LOG_PREFIX = \"[UIBlocking]\";\n\nexport const loggerMiddleware: Middleware = (context) => {\n const emoji = getActionEmoji(context.action);\n const logData = formatLogData(context);\n\n console.log(LOG_PREFIX, emoji, context.blockerId, logData);\n};\n","export const handleAddAction = (\n blockerId: string,\n timestamp: number,\n blockStartTimes: Map<string, number>\n): void => {\n blockStartTimes.set(blockerId, timestamp);\n};\n","import { Middleware, MiddlewareContext } from \"./middleware.types\";\nimport { PerformanceConfig } from \"./performanceMiddleware.types\";\nimport { handleAddAction } from \"./performanceMiddleware.utils\";\n\nconst DEFAULT_SLOW_BLOCK_THRESHOLD = 3000;\nconst ACTION_ADD = \"add\";\nconst ACTION_REMOVE = \"remove\";\n\nconst handleRemoveAction = (\n context: MiddlewareContext,\n blockStartTimes: Map<string, number>,\n slowBlockThreshold: number,\n onSlowBlock?: (blockerId: string, duration: number) => void\n): void => {\n const startTime = blockStartTimes.get(context.blockerId);\n\n if (startTime === undefined) {\n return;\n }\n\n const duration = context.timestamp - startTime;\n blockStartTimes.delete(context.blockerId);\n\n if (duration >= slowBlockThreshold) {\n console.warn(\n `[UIBlocking] Slow block detected: \"${context.blockerId}\" took ${duration.toString()}ms`\n );\n\n onSlowBlock?.(context.blockerId, duration);\n }\n};\n\nexport const createPerformanceMiddleware = (config: PerformanceConfig = {}): Middleware => {\n const { slowBlockThreshold = DEFAULT_SLOW_BLOCK_THRESHOLD, onSlowBlock } = config;\n const blockStartTimes = new Map<string, number>();\n\n return (context) => {\n if (context.action === ACTION_ADD) {\n handleAddAction(context.blockerId, context.timestamp, blockStartTimes);\n } else if (context.action === ACTION_REMOVE) {\n handleRemoveAction(context, blockStartTimes, slowBlockThreshold, onSlowBlock);\n }\n };\n};\n"]}
package/dist/index.d.cts CHANGED
@@ -112,25 +112,11 @@ type UIBlockingStore = UIBlockingStoreState & UIBlockingStoreActions;
112
112
  * - Scope-based blocking (global, specific areas, or multiple scopes)
113
113
  * - Automatic cleanup on unmount (when using hooks)
114
114
  * - DevTools integration for debugging
115
+ * - Automatic shallow comparison for selectors
115
116
  *
116
117
  */
117
- declare const useUIBlockingStore: zustand.UseBoundStore<Omit<zustand.StoreApi<UIBlockingStore>, "setState" | "devtools"> & {
118
- setState(partial: UIBlockingStore | Partial<UIBlockingStore> | ((state: UIBlockingStore) => UIBlockingStore | Partial<UIBlockingStore>), replace?: false | undefined, action?: (string | {
119
- [x: string]: unknown;
120
- [x: number]: unknown;
121
- [x: symbol]: unknown;
122
- type: string;
123
- }) | undefined): void;
124
- setState(state: UIBlockingStore | ((state: UIBlockingStore) => UIBlockingStore), replace: true, action?: (string | {
125
- [x: string]: unknown;
126
- [x: number]: unknown;
127
- [x: symbol]: unknown;
128
- type: string;
129
- }) | undefined): void;
130
- devtools: {
131
- cleanup: () => void;
132
- };
133
- }>;
118
+ declare const useUIBlockingStore: <T>(selector: (state: UIBlockingStore) => T) => T;
119
+ declare const uiBlockingStoreApi: zustand.StoreApi<UIBlockingStore>;
134
120
 
135
121
  /**
136
122
  * Hook to automatically add and remove a blocker based on component lifecycle
@@ -275,4 +261,4 @@ interface ScheduledBlockerConfig extends BlockerConfig {
275
261
  */
276
262
  declare const useScheduledBlocker: (blockerId: string, config: ScheduledBlockerConfig) => void;
277
263
 
278
- export { type AmplitudeConfig, type AnalyticsConfig, type AnalyticsEventData, type AnalyticsProvider, type BlockerConfig, type BlockerInfo, type BlockingAction, type BlockingSchedule, type ConditionalBlockerConfig, type ConfirmDialogConfig, type ConfirmableBlockerConfig, type CustomAnalyticsConfig, type GoogleAnalyticsConfig, type Middleware, type MiddlewareContext, type MixpanelConfig, type PerformanceConfig, type ScheduledBlockerConfig, type StoredBlocker, type UIBlockingStore, type UIBlockingStoreActions, type UIBlockingStoreState, type UseConfirmableBlockerReturn, createAnalyticsMiddleware, createPerformanceMiddleware, loggerMiddleware, useAsyncAction, useBlocker, useConditionalBlocker, useConfirmableBlocker, useIsBlocked, useScheduledBlocker, useUIBlockingStore };
264
+ export { type AmplitudeConfig, type AnalyticsConfig, type AnalyticsEventData, type AnalyticsProvider, type BlockerConfig, type BlockerInfo, type BlockingAction, type BlockingSchedule, type ConditionalBlockerConfig, type ConfirmDialogConfig, type ConfirmableBlockerConfig, type CustomAnalyticsConfig, type GoogleAnalyticsConfig, type Middleware, type MiddlewareContext, type MixpanelConfig, type PerformanceConfig, type ScheduledBlockerConfig, type StoredBlocker, type UIBlockingStore, type UIBlockingStoreActions, type UIBlockingStoreState, type UseConfirmableBlockerReturn, createAnalyticsMiddleware, createPerformanceMiddleware, loggerMiddleware, uiBlockingStoreApi, useAsyncAction, useBlocker, useConditionalBlocker, useConfirmableBlocker, useIsBlocked, useScheduledBlocker, useUIBlockingStore };
package/dist/index.d.ts CHANGED
@@ -112,25 +112,11 @@ type UIBlockingStore = UIBlockingStoreState & UIBlockingStoreActions;
112
112
  * - Scope-based blocking (global, specific areas, or multiple scopes)
113
113
  * - Automatic cleanup on unmount (when using hooks)
114
114
  * - DevTools integration for debugging
115
+ * - Automatic shallow comparison for selectors
115
116
  *
116
117
  */
117
- declare const useUIBlockingStore: zustand.UseBoundStore<Omit<zustand.StoreApi<UIBlockingStore>, "setState" | "devtools"> & {
118
- setState(partial: UIBlockingStore | Partial<UIBlockingStore> | ((state: UIBlockingStore) => UIBlockingStore | Partial<UIBlockingStore>), replace?: false | undefined, action?: (string | {
119
- [x: string]: unknown;
120
- [x: number]: unknown;
121
- [x: symbol]: unknown;
122
- type: string;
123
- }) | undefined): void;
124
- setState(state: UIBlockingStore | ((state: UIBlockingStore) => UIBlockingStore), replace: true, action?: (string | {
125
- [x: string]: unknown;
126
- [x: number]: unknown;
127
- [x: symbol]: unknown;
128
- type: string;
129
- }) | undefined): void;
130
- devtools: {
131
- cleanup: () => void;
132
- };
133
- }>;
118
+ declare const useUIBlockingStore: <T>(selector: (state: UIBlockingStore) => T) => T;
119
+ declare const uiBlockingStoreApi: zustand.StoreApi<UIBlockingStore>;
134
120
 
135
121
  /**
136
122
  * Hook to automatically add and remove a blocker based on component lifecycle
@@ -275,4 +261,4 @@ interface ScheduledBlockerConfig extends BlockerConfig {
275
261
  */
276
262
  declare const useScheduledBlocker: (blockerId: string, config: ScheduledBlockerConfig) => void;
277
263
 
278
- export { type AmplitudeConfig, type AnalyticsConfig, type AnalyticsEventData, type AnalyticsProvider, type BlockerConfig, type BlockerInfo, type BlockingAction, type BlockingSchedule, type ConditionalBlockerConfig, type ConfirmDialogConfig, type ConfirmableBlockerConfig, type CustomAnalyticsConfig, type GoogleAnalyticsConfig, type Middleware, type MiddlewareContext, type MixpanelConfig, type PerformanceConfig, type ScheduledBlockerConfig, type StoredBlocker, type UIBlockingStore, type UIBlockingStoreActions, type UIBlockingStoreState, type UseConfirmableBlockerReturn, createAnalyticsMiddleware, createPerformanceMiddleware, loggerMiddleware, useAsyncAction, useBlocker, useConditionalBlocker, useConfirmableBlocker, useIsBlocked, useScheduledBlocker, useUIBlockingStore };
264
+ export { type AmplitudeConfig, type AnalyticsConfig, type AnalyticsEventData, type AnalyticsProvider, type BlockerConfig, type BlockerInfo, type BlockingAction, type BlockingSchedule, type ConditionalBlockerConfig, type ConfirmDialogConfig, type ConfirmableBlockerConfig, type CustomAnalyticsConfig, type GoogleAnalyticsConfig, type Middleware, type MiddlewareContext, type MixpanelConfig, type PerformanceConfig, type ScheduledBlockerConfig, type StoredBlocker, type UIBlockingStore, type UIBlockingStoreActions, type UIBlockingStoreState, type UseConfirmableBlockerReturn, createAnalyticsMiddleware, createPerformanceMiddleware, loggerMiddleware, uiBlockingStoreApi, useAsyncAction, useBlocker, useConditionalBlocker, useConfirmableBlocker, useIsBlocked, useScheduledBlocker, useUIBlockingStore };
package/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { useCallback, useEffect, useRef, useState } from 'react';
2
- import { create } from 'zustand';
3
2
  import { devtools } from 'zustand/middleware';
3
+ import { createStore, useStore } from 'zustand';
4
+ import { useShallow } from 'zustand/shallow';
4
5
 
5
6
  // src/hooks/useAsyncAction/useAsyncAction.ts
6
7
 
@@ -10,8 +11,13 @@ var DEFAULT_REASON = "Unknown";
10
11
  var DEFAULT_PRIORITY = 0;
11
12
  var ASYNC_ACTION_PRIORITY = 20;
12
13
  var DEVTOOLS_NAME = "UIBlocking";
13
-
14
- // src/store/uiBlockingStore.utils.ts
14
+ function createShallowStore(storeCreator) {
15
+ const storeApi = createStore(storeCreator);
16
+ const useScopedStore = (selector) => {
17
+ return useStore(storeApi, useShallow(selector));
18
+ };
19
+ return { useStore: useScopedStore, useStoreApi: storeApi };
20
+ }
15
21
  function normalizeScopeToArray(scope) {
16
22
  if (typeof scope === "string") {
17
23
  return [scope];
@@ -176,13 +182,14 @@ var devtoolsConfig = {
176
182
  };
177
183
 
178
184
  // src/store/uiBlockingStore.store.ts
179
- var useUIBlockingStore = create()(
180
- devtools(createUIBlockingActions, devtoolsConfig)
181
- );
185
+ var { useStore: useUIBlockingStore, useStoreApi: uiBlockingStoreApi } = createShallowStore(devtools(createUIBlockingActions, devtoolsConfig));
182
186
 
183
187
  // src/hooks/useAsyncAction/useAsyncAction.ts
184
188
  var useAsyncAction = (actionId, scope) => {
185
- const { addBlocker, removeBlocker } = useUIBlockingStore();
189
+ const { addBlocker, removeBlocker } = useUIBlockingStore((state) => ({
190
+ addBlocker: state.addBlocker,
191
+ removeBlocker: state.removeBlocker
192
+ }));
186
193
  const executeWithBlocking = useCallback(
187
194
  async (asyncFn) => {
188
195
  const blockerId = `${actionId}-${Date.now().toString()}`;
@@ -202,7 +209,10 @@ var useAsyncAction = (actionId, scope) => {
202
209
  return executeWithBlocking;
203
210
  };
204
211
  var useBlocker = (blockerId, config, isActive = true) => {
205
- const { addBlocker, removeBlocker } = useUIBlockingStore();
212
+ const { addBlocker, removeBlocker } = useUIBlockingStore((state) => ({
213
+ addBlocker: state.addBlocker,
214
+ removeBlocker: state.removeBlocker
215
+ }));
206
216
  useEffect(() => {
207
217
  if (!isActive || !blockerId) {
208
218
  return;
@@ -232,7 +242,10 @@ function useConfigRef(config) {
232
242
 
233
243
  // src/hooks/useConditionalBlocker/useConditionalBlocker.ts
234
244
  var useConditionalBlocker = (blockerId, config) => {
235
- const { addBlocker, removeBlocker } = useUIBlockingStore();
245
+ const { addBlocker, removeBlocker } = useUIBlockingStore((state) => ({
246
+ addBlocker: state.addBlocker,
247
+ removeBlocker: state.removeBlocker
248
+ }));
236
249
  const intervalRef = useRef(null);
237
250
  const isBlockedRef = useRef(false);
238
251
  const configRef = useConfigRef(config);
@@ -354,7 +367,10 @@ function isScheduleInPast(startTime, endTime, now) {
354
367
 
355
368
  // src/hooks/useScheduledBlocker/useScheduledBlocker.ts
356
369
  var useScheduledBlocker = (blockerId, config) => {
357
- const { addBlocker, removeBlocker } = useUIBlockingStore();
370
+ const { addBlocker, removeBlocker } = useUIBlockingStore((state) => ({
371
+ addBlocker: state.addBlocker,
372
+ removeBlocker: state.removeBlocker
373
+ }));
358
374
  const timeoutsRef = useRef({});
359
375
  const configRef = useConfigRef(config);
360
376
  const cleanup = useCallback(() => {
@@ -573,6 +589,6 @@ var createPerformanceMiddleware = (config = {}) => {
573
589
  };
574
590
  };
575
591
 
576
- export { createAnalyticsMiddleware, createPerformanceMiddleware, loggerMiddleware, useAsyncAction, useBlocker, useConditionalBlocker, useConfirmableBlocker, useIsBlocked, useScheduledBlocker, useUIBlockingStore };
592
+ export { createAnalyticsMiddleware, createPerformanceMiddleware, loggerMiddleware, uiBlockingStoreApi, useAsyncAction, useBlocker, useConditionalBlocker, useConfirmableBlocker, useIsBlocked, useScheduledBlocker, useUIBlockingStore };
577
593
  //# sourceMappingURL=index.js.map
578
594
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/store/uiBlockingStore.constants.ts","../src/store/uiBlockingStore.utils.ts","../src/store/uiBlockingStore.actions.ts","../src/store/uiBlockingStore.config.ts","../src/store/uiBlockingStore.store.ts","../src/hooks/useAsyncAction/useAsyncAction.ts","../src/hooks/useBlocker/useBlocker.ts","../src/hooks/useBlocker/useBlocker.utils.ts","../src/hooks/useConfigRef.ts","../src/hooks/useConditionalBlocker/useConditionalBlocker.ts","../src/hooks/useConfirmableBlocker/useConfirmableBlocker.ts","../src/hooks/useIsBlocked/useIsBlocked.ts","../src/hooks/useScheduledBlocker/useScheduledBlocker.utils.ts","../src/hooks/useScheduledBlocker/useScheduledBlocker.ts","../src/middleware/analyticsMiddleware.utils.ts","../src/middleware/analyticsMiddleware.ts","../src/middleware/loggerMiddleware.utils.ts","../src/middleware/loggerMiddleware.ts","../src/middleware/performanceMiddleware.utils.ts","../src/middleware/performanceMiddleware.ts"],"names":["useEffect","useRef","useCallback"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Default values and constants for UI Blocking Store\n */\n\n/**\n * Default scope for blockers\n */\nexport const DEFAULT_SCOPE = \"global\" as const;\n\n/**\n * Default reason when none is provided\n */\nexport const DEFAULT_REASON = \"Unknown\" as const;\n\n/**\n * Default priority for blockers\n */\nexport const DEFAULT_PRIORITY = 0 as const;\n\n/**\n * Default priority for async actions\n */\nexport const ASYNC_ACTION_PRIORITY = 20 as const;\n\n/**\n * DevTools store name\n */\nexport const DEVTOOLS_NAME = \"UIBlocking\" as const;\n","/**\n * Normalize scope to array format\n *\n * @param scope - Single scope or array of scopes\n * @returns Array of scopes\n *\n * @internal\n */\nexport function normalizeScopeToArray(scope: string | ReadonlyArray<string>): Array<string> {\n if (typeof scope === \"string\") {\n return [scope];\n }\n return Array.from(scope);\n}\n","import { Middleware, MiddlewareContext } from \"../middleware\";\nimport { DEFAULT_PRIORITY, DEFAULT_REASON, DEFAULT_SCOPE } from \"./uiBlockingStore.constants\";\nimport { normalizeScopeToArray } from \"./uiBlockingStore.utils\";\nimport type {\n BlockerConfig,\n BlockerInfo,\n StoredBlocker,\n UIBlockingStore,\n} from \"./uiBlockingStore.types\";\nimport type { StateCreator } from \"zustand\";\n\n/**\n * UI Blocking Store Slice\n *\n * Implements the state and actions for UI blocking management.\n * This slice follows the Zustand slice pattern for better code organization.\n */\nexport const createUIBlockingActions: StateCreator<UIBlockingStore, [], [], UIBlockingStore> = (\n set,\n get\n) => ({\n // State\n activeBlockers: new Map(),\n middlewares: new Map(),\n\n registerMiddleware: (name: string, middleware: Middleware) => {\n set((state) => {\n const newMiddlewares = new Map(state.middlewares);\n newMiddlewares.set(name, middleware);\n return { middlewares: newMiddlewares };\n });\n console.log(`[UIBlocking] Registered middleware: ${name}`);\n },\n\n unregisterMiddleware: (name: string) => {\n set((state) => {\n const newMiddlewares = new Map(state.middlewares);\n newMiddlewares.delete(name);\n return { middlewares: newMiddlewares };\n });\n console.log(`[UIBlocking] Unregistered middleware: ${name}`);\n },\n\n runMiddlewares: async (context: MiddlewareContext) => {\n const { middlewares } = get();\n\n for (const [name, middleware] of middlewares) {\n try {\n await middleware(context);\n } catch (error) {\n console.error(`[UIBlocking] Middleware \"${name}\" error:`, error);\n }\n }\n },\n\n // Actions\n /**\n * Add a blocker to the store\n *\n * @param id - Unique blocker identifier\n * @param config - Optional blocker configuration\n *\n */\n addBlocker: (id: string, config: BlockerConfig = {}): void => {\n set((state) => {\n const newBlockers = new Map(state.activeBlockers);\n const storedBlocker: StoredBlocker = {\n scope: config.scope ?? DEFAULT_SCOPE,\n reason: config.reason ?? DEFAULT_REASON,\n priority: config.priority ?? DEFAULT_PRIORITY,\n timestamp: config.timestamp ?? Date.now(),\n };\n newBlockers.set(id, storedBlocker);\n\n return { activeBlockers: newBlockers };\n });\n\n void get().runMiddlewares({\n action: \"add\",\n blockerId: id,\n config: {\n scope: config.scope,\n reason: config.reason,\n priority: config.priority,\n },\n timestamp: Date.now(),\n });\n },\n\n /**\n * Remove a blocker from the store\n *\n * @param id - Blocker identifier to remove\n *\n */\n removeBlocker: (id: string): void => {\n const prevBlocker = get().activeBlockers.get(id);\n\n set((state) => {\n const newBlockers = new Map(state.activeBlockers);\n newBlockers.delete(id);\n\n return { activeBlockers: newBlockers };\n });\n\n if (prevBlocker) {\n void get().runMiddlewares({\n action: \"remove\",\n blockerId: id,\n config: prevBlocker,\n timestamp: Date.now(),\n prevState: prevBlocker,\n });\n }\n },\n\n /**\n * Check if a scope is currently blocked\n *\n * @param scope - Scope or array of scopes to check (default: \"global\")\n * @returns True if any of the scopes are blocked\n *\n */\n isBlocked: (scope: string | ReadonlyArray<string> = DEFAULT_SCOPE): boolean => {\n const { activeBlockers } = get();\n const scopes = normalizeScopeToArray(scope);\n\n for (const [, blocker] of activeBlockers) {\n // Global blocking blocks everything\n if (blocker.scope === DEFAULT_SCOPE) {\n return true;\n }\n\n // Check scope intersection\n const blockerScopes = normalizeScopeToArray(blocker.scope);\n\n if (scopes.some((s) => blockerScopes.includes(s))) {\n return true;\n }\n }\n\n return false;\n },\n\n /**\n * Get detailed blocking information for a specific scope\n *\n * @param scope - Scope to get blocking information for\n * @returns Array of blockers affecting the scope, sorted by priority (highest first)\n *\n */\n getBlockingInfo: (scope: string): ReadonlyArray<BlockerInfo> => {\n const { activeBlockers } = get();\n const blockers: Array<BlockerInfo> = [];\n\n for (const [id, blocker] of activeBlockers) {\n const blockerScopes = normalizeScopeToArray(blocker.scope);\n\n if (blocker.scope === DEFAULT_SCOPE || blockerScopes.includes(scope)) {\n blockers.push({ id, ...blocker });\n }\n }\n\n return blockers.sort((a, b) => b.priority - a.priority);\n },\n\n /**\n * Clear all blockers from the store\n */\n clearAllBlockers: (): void => {\n set({ activeBlockers: new Map() });\n },\n\n /**\n * Clear all blockers for a specific scope\n *\n * @param scope - Scope to clear blockers for\n *\n */\n clearBlockersForScope: (scope: string): void => {\n set((state) => {\n const newBlockers = new Map();\n\n for (const [id, blocker] of state.activeBlockers) {\n const blockerScopes = normalizeScopeToArray(blocker.scope);\n\n if (!blockerScopes.includes(scope)) {\n newBlockers.set(id, blocker);\n }\n }\n\n return { activeBlockers: newBlockers };\n });\n },\n});\n","import { DEVTOOLS_NAME } from \"./uiBlockingStore.constants\";\nimport type { DevtoolsOptions } from \"zustand/middleware\";\n\n/**\n * DevTools configuration for UI Blocking Store\n *\n * Enables Redux DevTools integration only in development mode\n * for better debugging experience without production overhead.\n */\nexport const devtoolsConfig: DevtoolsOptions = {\n name: DEVTOOLS_NAME,\n enabled: process.env.NODE_ENV !== \"production\",\n};\n","import { create } from \"zustand\";\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 *\n */\nexport const useUIBlockingStore = create<UIBlockingStore>()(\n devtools(createUIBlockingActions, devtoolsConfig)\n);\n","import { useCallback } from \"react\";\nimport { ASYNC_ACTION_PRIORITY, useUIBlockingStore } from \"../../store\";\n\n/**\n * Hook to wrap async functions with automatic blocking/unblocking\n *\n * Creates a wrapper function that automatically adds a blocker before executing\n * the async function and removes it after completion (success or failure).\n *\n * @template T - The return type of the async function\n * @param actionId - Unique identifier for the action (used in blocker ID and reason)\n * @param scope - Scope(s) to block during execution (default: \"global\")\n * @returns Function that wraps async functions with blocking behavior\n *\n */\nexport const useAsyncAction = <T = unknown>(\n actionId: string,\n scope?: string | ReadonlyArray<string>\n): ((asyncFn: () => Promise<T>) => Promise<T>) => {\n const { addBlocker, removeBlocker } = useUIBlockingStore();\n\n const executeWithBlocking = useCallback(\n async (asyncFn: () => Promise<T>): Promise<T> => {\n const blockerId = `${actionId}-${Date.now().toString()}`;\n\n try {\n addBlocker(blockerId, {\n scope,\n reason: `Executing ${actionId}`,\n priority: ASYNC_ACTION_PRIORITY,\n });\n\n return await asyncFn();\n } finally {\n removeBlocker(blockerId);\n }\n },\n [actionId, scope, addBlocker, removeBlocker]\n );\n\n return executeWithBlocking;\n};\n","import { useEffect } from \"react\";\nimport { type BlockerConfig, useUIBlockingStore } from \"../../store\";\n\n/**\n * Hook to automatically add and remove a blocker based on component lifecycle\n *\n * Automatically adds a blocker when the component mounts (or when activated)\n * and removes it when the component unmounts (or when deactivated).\n *\n * @param blockerId - Unique identifier for the blocker\n * @param config - Blocker configuration (scope, reason, priority)\n * @param isActive - Whether the blocker is currently active (default: true)\n *\n */\nexport const useBlocker = (blockerId: string, config: BlockerConfig, isActive = true): void => {\n const { addBlocker, removeBlocker } = useUIBlockingStore();\n\n useEffect(() => {\n if (!isActive || !blockerId) {\n return;\n }\n\n addBlocker(blockerId, config);\n\n return () => {\n removeBlocker(blockerId);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [blockerId, isActive, addBlocker, removeBlocker]);\n};\n","import { BlockerConfig } from \"../../store\";\n\n/**\n * Creates a blocker configuration object from partial config.\n * Filters out undefined values to create a clean BlockerConfig.\n *\n * @param config - Partial blocker configuration\n * @returns Complete BlockerConfig object\n *\n */\nexport function createBlockerConfig(config: {\n scope?: string | ReadonlyArray<string>;\n reason?: string;\n priority?: number;\n}): BlockerConfig {\n return {\n scope: config.scope,\n reason: config.reason,\n priority: config.priority,\n };\n}\n","import { RefObject, useEffect, useRef } from \"react\";\n\n/**\n * Keeps a ref updated with the latest config value.\n * Useful for accessing current config in callbacks without stale closures.\n *\n * @param config - Configuration object to track\n * @returns Mutable ref that always contains the latest config\n *\n */\nexport function useConfigRef<T>(config: T): RefObject<T> {\n const configRef = useRef(config);\n\n useEffect(() => {\n configRef.current = config;\n }, [config]);\n\n return configRef;\n}\n","import { useCallback, useEffect, useRef } from \"react\";\nimport { useUIBlockingStore } from \"../../store\";\nimport { createBlockerConfig } from \"../useBlocker\";\nimport { useConfigRef } from \"../useConfigRef\";\nimport { ConditionalBlockerConfig } from \"./useConditionalBlocker.types\";\n\n/**\n * Hook for conditional blocking based on a condition function.\n *\n * Periodically checks a condition and blocks/unblocks based on the result.\n * The condition is evaluated at the specified interval (default 1000ms).\n *\n * @param blockerId - Unique identifier for this blocker\n * @param config - Configuration including condition function and check interval\n *\n */\nexport const useConditionalBlocker = <TState = unknown>(\n blockerId: string,\n config: ConditionalBlockerConfig<TState>\n): void => {\n const { addBlocker, removeBlocker } = useUIBlockingStore();\n const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);\n const isBlockedRef = useRef(false);\n const configRef = useConfigRef(config);\n\n const checkCondition = useCallback(() => {\n const currentConfig = configRef.current;\n const shouldBlock = currentConfig.condition(currentConfig.state);\n\n // No state change needed\n if (shouldBlock === isBlockedRef.current) {\n return;\n }\n\n if (shouldBlock) {\n addBlocker(blockerId, createBlockerConfig(currentConfig));\n } else {\n removeBlocker(blockerId);\n }\n isBlockedRef.current = shouldBlock;\n }, [blockerId, addBlocker, removeBlocker, configRef]);\n\n useEffect(() => {\n checkCondition();\n\n const interval = configRef.current.checkInterval ?? 1000;\n intervalRef.current = setInterval(checkCondition, interval);\n\n return (): void => {\n if (intervalRef.current) {\n clearInterval(intervalRef.current);\n intervalRef.current = null;\n }\n if (isBlockedRef.current) {\n removeBlocker(blockerId);\n isBlockedRef.current = false;\n }\n };\n // configRef is stable and doesn't need to be in dependencies\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [checkCondition, blockerId, removeBlocker]);\n};\n","import { useCallback, useState } from \"react\";\nimport { useBlocker } from \"../useBlocker\";\nimport {\n ConfirmableBlockerConfig,\n UseConfirmableBlockerReturn,\n} from \"./useConfirmableBlocker.types\";\n\n/**\n * Hook for creating a confirmable action with blocking UI\n *\n */\nexport const useConfirmableBlocker = (\n blockerId: string,\n config: ConfirmableBlockerConfig\n): UseConfirmableBlockerReturn => {\n const [isDialogOpen, setIsDialogOpen] = useState(false);\n const [isExecuting, setIsExecuting] = useState(false);\n\n useBlocker(\n blockerId,\n {\n ...config,\n reason: config.reason ?? config.confirmMessage,\n },\n isDialogOpen || isExecuting\n );\n\n const execute = useCallback(() => {\n setIsDialogOpen(true);\n }, []);\n\n const onConfirm = useCallback(async () => {\n setIsDialogOpen(false);\n setIsExecuting(true);\n\n try {\n await config.onConfirm();\n } catch (error) {\n console.error(\"[UIBlocking] Confirmable action error:\", error);\n throw error;\n } finally {\n setIsExecuting(false);\n }\n }, [config]);\n\n const onCancel = useCallback(() => {\n setIsDialogOpen(false);\n config.onCancel?.();\n }, [config]);\n\n return {\n execute,\n isDialogOpen,\n isExecuting,\n confirmConfig: {\n title: config.confirmTitle ?? \"Confirm Action\",\n message: config.confirmMessage,\n confirmText: config.confirmButtonText ?? \"Confirm\",\n cancelText: config.cancelButtonText ?? \"Cancel\",\n },\n onConfirm,\n onCancel,\n };\n};\n","import { useUIBlockingStore } from \"../../store\";\n\n/**\n * Hook to check if a scope is currently blocked\n *\n * Returns a boolean indicating whether the specified scope(s) are blocked.\n * Automatically re-renders when the blocking state changes.\n *\n * @param scope - Scope or array of scopes to check (default: \"global\")\n * @returns True if any of the specified scopes are blocked\n *\n */\nexport const useIsBlocked = (scope?: string | ReadonlyArray<string>): boolean => {\n return useUIBlockingStore((state) => state.isBlocked(scope));\n};\n","import type { BlockingSchedule } from \"./useScheduledBlocker.types\";\n\n/**\n * Maximum safe timeout value for setTimeout in JavaScript (~24.8 days).\n * Values larger than this will cause setTimeout to trigger immediately.\n */\nexport const MAX_TIMEOUT_MS = 2147483647;\n\n/**\n * Validates a date value and converts it to timestamp.\n *\n * @param date - Date value as string, Date object, or number\n * @returns Timestamp in milliseconds, or NaN if invalid\n */\nexport function parseDate(date: string | Date | number): number {\n return new Date(date).getTime();\n}\n\n/**\n * Validates if a timestamp is valid (not NaN).\n *\n * @param timestamp - Timestamp to validate\n * @returns True if valid, false otherwise\n */\nexport function isValidTimestamp(timestamp: number): boolean {\n return !Number.isNaN(timestamp);\n}\n\n/**\n * Calculates the end time based on schedule configuration.\n * Duration takes precedence over end time if both are provided.\n *\n * @param schedule - Blocking schedule configuration\n * @param startTime - Start time in milliseconds\n * @returns End time in milliseconds, or undefined if not specified\n */\nexport function calculateEndTime(\n schedule: BlockingSchedule,\n startTime: number\n): number | undefined {\n if (schedule.duration) {\n return startTime + schedule.duration;\n }\n\n if (schedule.end) {\n const endTime = parseDate(schedule.end);\n return isValidTimestamp(endTime) ? endTime : undefined;\n }\n\n return undefined;\n}\n\n/**\n * Validates if a delay is within the safe setTimeout range.\n *\n * @param delay - Delay in milliseconds\n * @returns True if delay is safe to use with setTimeout\n */\nexport function isSafeTimeout(delay: number): boolean {\n return delay > 0 && delay <= MAX_TIMEOUT_MS;\n}\n\n/**\n * Determines if the current time is within a blocking schedule.\n *\n * @param startTime - Schedule start time in milliseconds\n * @param endTime - Schedule end time in milliseconds (optional)\n * @param now - Current time in milliseconds\n * @returns True if currently in the blocking period\n */\nexport function isInBlockingPeriod(\n startTime: number,\n endTime: number | undefined,\n now: number\n): boolean {\n if (startTime > now) {\n return false; // Not started yet\n }\n\n if (!endTime) {\n return true; // No end time means block indefinitely\n }\n\n return endTime > now; // Check if end time hasn't passed\n}\n\n/**\n * Checks if a schedule is completely in the past.\n *\n * @param startTime - Schedule start time in milliseconds\n * @param endTime - Schedule end time in milliseconds (optional)\n * @param now - Current time in milliseconds\n * @returns True if the schedule is in the past\n */\nexport function isScheduleInPast(\n startTime: number,\n endTime: number | undefined,\n now: number\n): boolean {\n if (!endTime) {\n return false; // No end time means it can still be active\n }\n\n return endTime <= now && startTime <= now;\n}\n","import { useCallback, useEffect, useRef } from \"react\";\nimport { useUIBlockingStore } from \"../../store\";\nimport { createBlockerConfig } from \"../useBlocker\";\nimport { useConfigRef } from \"../useConfigRef\";\nimport { ScheduledBlockerConfig } from \"./useScheduledBlocker.types\";\nimport {\n MAX_TIMEOUT_MS,\n calculateEndTime,\n isInBlockingPeriod,\n isSafeTimeout,\n isScheduleInPast,\n isValidTimestamp,\n parseDate,\n} from \"./useScheduledBlocker.utils\";\n\n/**\n * Hook for scheduling UI blocking for a specific time period.\n *\n * Blocks UI during a scheduled maintenance window or time period.\n * Supports start/end times as Date objects, ISO strings, or timestamps.\n * If both duration and end are provided, duration takes precedence.\n *\n * @param blockerId - Unique identifier for this blocker\n * @param config - Configuration including schedule and callbacks\n *\n */\nexport const useScheduledBlocker = (blockerId: string, config: ScheduledBlockerConfig): void => {\n const { addBlocker, removeBlocker } = useUIBlockingStore();\n const timeoutsRef = useRef<{\n start?: ReturnType<typeof setTimeout>;\n end?: ReturnType<typeof setTimeout>;\n }>({});\n const configRef = useConfigRef(config);\n\n const cleanup = useCallback(() => {\n if (timeoutsRef.current.start) {\n clearTimeout(timeoutsRef.current.start);\n timeoutsRef.current.start = undefined;\n }\n if (timeoutsRef.current.end) {\n clearTimeout(timeoutsRef.current.end);\n timeoutsRef.current.end = undefined;\n }\n }, []);\n\n useEffect(() => {\n const currentConfig = configRef.current;\n const startTime = parseDate(currentConfig.schedule.start);\n const now = Date.now();\n\n // Validate start time\n if (!isValidTimestamp(startTime)) {\n console.error(`[UIBlocking] Invalid start time for blocker \"${blockerId}\"`);\n return;\n }\n\n const scheduleEnd = (): void => {\n const endTime = calculateEndTime(currentConfig.schedule, startTime);\n if (!endTime) {\n return;\n }\n\n const remainingTime = endTime - Date.now();\n if (remainingTime > 0) {\n timeoutsRef.current.end = setTimeout(() => {\n configRef.current.onScheduleEnd?.();\n removeBlocker(blockerId);\n }, remainingTime);\n }\n };\n\n const startBlocking = (): void => {\n const cfg = configRef.current;\n addBlocker(blockerId, createBlockerConfig(cfg));\n cfg.onScheduleStart?.();\n scheduleEnd();\n };\n\n // If start time hasn't arrived yet\n if (startTime > now) {\n const delay = startTime - now;\n\n if (!isSafeTimeout(delay)) {\n console.warn(\n `[UIBlocking] Schedule delay exceeds maximum timeout (${MAX_TIMEOUT_MS.toString()}ms) for blocker \"${blockerId}\"`\n );\n return;\n }\n\n timeoutsRef.current.start = setTimeout(startBlocking, delay);\n }\n // If already in blocking period or should start immediately\n else {\n const endTime = calculateEndTime(currentConfig.schedule, startTime);\n\n if (isInBlockingPeriod(startTime, endTime, now)) {\n startBlocking();\n } else if (isScheduleInPast(startTime, endTime, now)) {\n console.warn(`[UIBlocking] Schedule is in the past for blocker \"${blockerId}\"`);\n }\n }\n\n return (): void => {\n cleanup();\n removeBlocker(blockerId);\n };\n // configRef is stable and doesn't need to be in dependencies\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [blockerId, addBlocker, removeBlocker, cleanup]);\n};\n","import { AnalyticsEventData } from \"./analyticsMiddleware.types\";\nimport { MiddlewareContext } from \"./middleware.types\";\n\nconst capitalizeFirst = (str: string): string => {\n return str.charAt(0).toUpperCase() + str.slice(1);\n};\n\nexport const buildEventData = (context: MiddlewareContext): AnalyticsEventData => {\n const eventData: AnalyticsEventData = {\n blocker_id: context.blockerId,\n };\n const { scope, reason, priority } = context.config ?? {};\n\n if (scope !== undefined) {\n eventData.scope = Array.isArray(scope) ? scope.join(\",\") : scope;\n }\n\n if (reason !== undefined) {\n eventData.reason = reason;\n }\n\n if (priority !== undefined) {\n eventData.priority = priority;\n }\n\n return eventData;\n};\n\nexport const trackGoogleAnalytics = (action: string, eventData: AnalyticsEventData): void => {\n if (window.gtag) {\n window.gtag(\"event\", `ui_blocking_${action}`, eventData);\n }\n};\n\nexport const trackMixpanel = (action: string, eventData: AnalyticsEventData): void => {\n if (window.mixpanel) {\n const eventName = `UI Blocking ${action.split(\"_\").map(capitalizeFirst).join(\" \")}`;\n\n window.mixpanel.track(eventName, eventData);\n }\n};\n\nexport const trackAmplitude = (action: string, eventData: AnalyticsEventData): void => {\n if (window.amplitude) {\n const eventName = `UI Blocking ${action.split(\"_\").map(capitalizeFirst).join(\" \")}`;\n\n window.amplitude.track(eventName, eventData);\n }\n};\n\nexport const trackCustom = (\n trackFn: (event: string, data: AnalyticsEventData) => void,\n action: string,\n eventData: AnalyticsEventData\n): void => {\n try {\n trackFn(`ui_blocking_${action}`, eventData);\n } catch {\n // Silently ignore errors in custom tracker\n }\n};\n","import { AnalyticsConfig, AnalyticsEventData } from \"./analyticsMiddleware.types\";\nimport {\n buildEventData,\n trackAmplitude,\n trackCustom,\n trackGoogleAnalytics,\n trackMixpanel,\n} from \"./analyticsMiddleware.utils\";\nimport { Middleware, MiddlewareContext } from \"./middleware.types\";\n\nconst trackEvent = (\n config: AnalyticsConfig,\n context: MiddlewareContext,\n eventData: AnalyticsEventData\n): void => {\n if (\"provider\" in config) {\n switch (config.provider) {\n case \"ga\":\n trackGoogleAnalytics(context.action, eventData);\n return;\n case \"mixpanel\":\n trackMixpanel(context.action, eventData);\n return;\n case \"amplitude\":\n trackAmplitude(context.action, eventData);\n return;\n }\n }\n\n if (\"track\" in config) {\n trackCustom(config.track, context.action, eventData);\n }\n};\n\nexport const createAnalyticsMiddleware = (config: AnalyticsConfig): Middleware => {\n return (context) => {\n const eventData = buildEventData(context);\n\n trackEvent(config, context, eventData);\n };\n};\n","import { MiddlewareBlockerConfig, MiddlewareContext } from \"./middleware.types\";\n\nexport const getActionEmoji = (action: string): string => {\n switch (action) {\n case \"add\":\n return \"➕\";\n case \"remove\":\n return \"➖\";\n case \"update\":\n return \"🔄\";\n case \"cancel\":\n return \"❌\";\n case \"timeout\":\n return \"⏱️\";\n default:\n return \"❓\";\n }\n};\n\nconst extractConfigDetails = (config?: MiddlewareBlockerConfig): Record<string, unknown> => {\n if (!config) {\n return {};\n }\n\n const { scope, reason, priority } = config;\n\n const details: Record<string, unknown> = {\n scope,\n reason,\n };\n\n if (priority !== undefined) {\n details.priority = priority;\n }\n\n return details;\n};\n\nexport const formatLogData = (context: MiddlewareContext): Record<string, unknown> => {\n const configDetails = extractConfigDetails(context.config);\n\n if (context.prevState) {\n return {\n config: configDetails,\n prevState: extractConfigDetails(context.prevState),\n };\n }\n\n return configDetails;\n};\n","import { formatLogData, getActionEmoji } from \"./loggerMiddleware.utils\";\nimport { Middleware } from \"./middleware.types\";\n\nconst LOG_PREFIX = \"[UIBlocking]\";\n\nexport const loggerMiddleware: Middleware = (context) => {\n const emoji = getActionEmoji(context.action);\n const logData = formatLogData(context);\n\n console.log(LOG_PREFIX, emoji, context.blockerId, logData);\n};\n","export const handleAddAction = (\n blockerId: string,\n timestamp: number,\n blockStartTimes: Map<string, number>\n): void => {\n blockStartTimes.set(blockerId, timestamp);\n};\n","import { Middleware, MiddlewareContext } from \"./middleware.types\";\nimport { PerformanceConfig } from \"./performanceMiddleware.types\";\nimport { handleAddAction } from \"./performanceMiddleware.utils\";\n\nconst DEFAULT_SLOW_BLOCK_THRESHOLD = 3000;\nconst ACTION_ADD = \"add\";\nconst ACTION_REMOVE = \"remove\";\n\nconst handleRemoveAction = (\n context: MiddlewareContext,\n blockStartTimes: Map<string, number>,\n slowBlockThreshold: number,\n onSlowBlock?: (blockerId: string, duration: number) => void\n): void => {\n const startTime = blockStartTimes.get(context.blockerId);\n\n if (startTime === undefined) {\n return;\n }\n\n const duration = context.timestamp - startTime;\n blockStartTimes.delete(context.blockerId);\n\n if (duration >= slowBlockThreshold) {\n console.warn(\n `[UIBlocking] Slow block detected: \"${context.blockerId}\" took ${duration.toString()}ms`\n );\n\n onSlowBlock?.(context.blockerId, duration);\n }\n};\n\nexport const createPerformanceMiddleware = (config: PerformanceConfig = {}): Middleware => {\n const { slowBlockThreshold = DEFAULT_SLOW_BLOCK_THRESHOLD, onSlowBlock } = config;\n const blockStartTimes = new Map<string, number>();\n\n return (context) => {\n if (context.action === ACTION_ADD) {\n handleAddAction(context.blockerId, context.timestamp, blockStartTimes);\n } else if (context.action === ACTION_REMOVE) {\n handleRemoveAction(context, blockStartTimes, slowBlockThreshold, onSlowBlock);\n }\n };\n};\n"]}
1
+ {"version":3,"sources":["../src/store/uiBlockingStore.constants.ts","../src/store/uiBlockingStore.utils.ts","../src/store/uiBlockingStore.actions.ts","../src/store/uiBlockingStore.config.ts","../src/store/uiBlockingStore.store.ts","../src/hooks/useAsyncAction/useAsyncAction.ts","../src/hooks/useBlocker/useBlocker.ts","../src/hooks/useBlocker/useBlocker.utils.ts","../src/hooks/useConfigRef.ts","../src/hooks/useConditionalBlocker/useConditionalBlocker.ts","../src/hooks/useConfirmableBlocker/useConfirmableBlocker.ts","../src/hooks/useIsBlocked/useIsBlocked.ts","../src/hooks/useScheduledBlocker/useScheduledBlocker.utils.ts","../src/hooks/useScheduledBlocker/useScheduledBlocker.ts","../src/middleware/analyticsMiddleware.utils.ts","../src/middleware/analyticsMiddleware.ts","../src/middleware/loggerMiddleware.utils.ts","../src/middleware/loggerMiddleware.ts","../src/middleware/performanceMiddleware.utils.ts","../src/middleware/performanceMiddleware.ts"],"names":["useEffect","useRef","useCallback"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Default values and constants for UI Blocking Store\n */\n\n/**\n * Default scope for blockers\n */\nexport const DEFAULT_SCOPE = \"global\" as const;\n\n/**\n * Default reason when none is provided\n */\nexport const DEFAULT_REASON = \"Unknown\" as const;\n\n/**\n * Default priority for blockers\n */\nexport const DEFAULT_PRIORITY = 0 as const;\n\n/**\n * Default priority for async actions\n */\nexport const ASYNC_ACTION_PRIORITY = 20 as const;\n\n/**\n * DevTools store name\n */\nexport const DEVTOOLS_NAME = \"UIBlocking\" as const;\n","import { StateCreator, StoreApi, StoreMutators, createStore, useStore } from \"zustand\";\nimport { useShallow } from \"zustand/shallow\";\n\n/**\n * Creates a Zustand store with automatic shallow comparison for all selectors\n *\n * This utility wraps the standard Zustand store creation and automatically applies\n * `useShallow` to all selectors, preventing unnecessary re-renders when selected\n * values haven't changed (shallow equality).\n *\n * @template StoreState - The type of the store state\n * @template TMutators - Array of middleware mutators (e.g., devtools, persist)\n *\n * @param storeCreator - The state creator function for Zustand\n * @returns Object containing the store hook and store API\n *\n * @see https://docs.pmnd.rs/zustand/guides/prevent-rerenders-with-use-shallow\n */\nexport function createShallowStore<\n StoreState,\n TMutators extends Array<[keyof StoreMutators<StoreState, StoreState>, unknown]> = [],\n>(\n storeCreator: StateCreator<StoreState, [], TMutators, StoreState>\n): {\n useStore: <T>(selector: (state: StoreState) => T) => T;\n useStoreApi: StoreApi<StoreState>;\n} {\n const storeApi: StoreApi<StoreState> = createStore<StoreState, TMutators>(storeCreator);\n\n const useScopedStore = <T>(selector: (state: StoreState) => T): T => {\n return useStore(storeApi, useShallow(selector));\n };\n\n return { useStore: useScopedStore, useStoreApi: storeApi };\n}\n\n/**\n * Normalize scope to array format\n *\n * @param scope - Single scope or array of scopes\n * @returns Array of scopes\n *\n * @internal\n */\nexport function normalizeScopeToArray(scope: string | ReadonlyArray<string>): Array<string> {\n if (typeof scope === \"string\") {\n return [scope];\n }\n return Array.from(scope);\n}\n","import { Middleware, MiddlewareContext } from \"../middleware\";\nimport { DEFAULT_PRIORITY, DEFAULT_REASON, DEFAULT_SCOPE } from \"./uiBlockingStore.constants\";\nimport { normalizeScopeToArray } from \"./uiBlockingStore.utils\";\nimport type {\n BlockerConfig,\n BlockerInfo,\n StoredBlocker,\n UIBlockingStore,\n} from \"./uiBlockingStore.types\";\nimport type { StateCreator } from \"zustand\";\n\n/**\n * UI Blocking Store Slice\n *\n * Implements the state and actions for UI blocking management.\n * This slice follows the Zustand slice pattern for better code organization.\n */\nexport const createUIBlockingActions: StateCreator<UIBlockingStore, [], [], UIBlockingStore> = (\n set,\n get\n) => ({\n // State\n activeBlockers: new Map(),\n middlewares: new Map(),\n\n registerMiddleware: (name: string, middleware: Middleware) => {\n set((state) => {\n const newMiddlewares = new Map(state.middlewares);\n newMiddlewares.set(name, middleware);\n return { middlewares: newMiddlewares };\n });\n console.log(`[UIBlocking] Registered middleware: ${name}`);\n },\n\n unregisterMiddleware: (name: string) => {\n set((state) => {\n const newMiddlewares = new Map(state.middlewares);\n newMiddlewares.delete(name);\n return { middlewares: newMiddlewares };\n });\n console.log(`[UIBlocking] Unregistered middleware: ${name}`);\n },\n\n runMiddlewares: async (context: MiddlewareContext) => {\n const { middlewares } = get();\n\n for (const [name, middleware] of middlewares) {\n try {\n await middleware(context);\n } catch (error) {\n console.error(`[UIBlocking] Middleware \"${name}\" error:`, error);\n }\n }\n },\n\n // Actions\n /**\n * Add a blocker to the store\n *\n * @param id - Unique blocker identifier\n * @param config - Optional blocker configuration\n *\n */\n addBlocker: (id: string, config: BlockerConfig = {}): void => {\n set((state) => {\n const newBlockers = new Map(state.activeBlockers);\n const storedBlocker: StoredBlocker = {\n scope: config.scope ?? DEFAULT_SCOPE,\n reason: config.reason ?? DEFAULT_REASON,\n priority: config.priority ?? DEFAULT_PRIORITY,\n timestamp: config.timestamp ?? Date.now(),\n };\n newBlockers.set(id, storedBlocker);\n\n return { activeBlockers: newBlockers };\n });\n\n void get().runMiddlewares({\n action: \"add\",\n blockerId: id,\n config: {\n scope: config.scope,\n reason: config.reason,\n priority: config.priority,\n },\n timestamp: Date.now(),\n });\n },\n\n /**\n * Remove a blocker from the store\n *\n * @param id - Blocker identifier to remove\n *\n */\n removeBlocker: (id: string): void => {\n const prevBlocker = get().activeBlockers.get(id);\n\n set((state) => {\n const newBlockers = new Map(state.activeBlockers);\n newBlockers.delete(id);\n\n return { activeBlockers: newBlockers };\n });\n\n if (prevBlocker) {\n void get().runMiddlewares({\n action: \"remove\",\n blockerId: id,\n config: prevBlocker,\n timestamp: Date.now(),\n prevState: prevBlocker,\n });\n }\n },\n\n /**\n * Check if a scope is currently blocked\n *\n * @param scope - Scope or array of scopes to check (default: \"global\")\n * @returns True if any of the scopes are blocked\n *\n */\n isBlocked: (scope: string | ReadonlyArray<string> = DEFAULT_SCOPE): boolean => {\n const { activeBlockers } = get();\n const scopes = normalizeScopeToArray(scope);\n\n for (const [, blocker] of activeBlockers) {\n // Global blocking blocks everything\n if (blocker.scope === DEFAULT_SCOPE) {\n return true;\n }\n\n // Check scope intersection\n const blockerScopes = normalizeScopeToArray(blocker.scope);\n\n if (scopes.some((s) => blockerScopes.includes(s))) {\n return true;\n }\n }\n\n return false;\n },\n\n /**\n * Get detailed blocking information for a specific scope\n *\n * @param scope - Scope to get blocking information for\n * @returns Array of blockers affecting the scope, sorted by priority (highest first)\n *\n */\n getBlockingInfo: (scope: string): ReadonlyArray<BlockerInfo> => {\n const { activeBlockers } = get();\n const blockers: Array<BlockerInfo> = [];\n\n for (const [id, blocker] of activeBlockers) {\n const blockerScopes = normalizeScopeToArray(blocker.scope);\n\n if (blocker.scope === DEFAULT_SCOPE || blockerScopes.includes(scope)) {\n blockers.push({ id, ...blocker });\n }\n }\n\n return blockers.sort((a, b) => b.priority - a.priority);\n },\n\n /**\n * Clear all blockers from the store\n */\n clearAllBlockers: (): void => {\n set({ activeBlockers: new Map() });\n },\n\n /**\n * Clear all blockers for a specific scope\n *\n * @param scope - Scope to clear blockers for\n *\n */\n clearBlockersForScope: (scope: string): void => {\n set((state) => {\n const newBlockers = new Map();\n\n for (const [id, blocker] of state.activeBlockers) {\n const blockerScopes = normalizeScopeToArray(blocker.scope);\n\n if (!blockerScopes.includes(scope)) {\n newBlockers.set(id, blocker);\n }\n }\n\n return { activeBlockers: newBlockers };\n });\n },\n});\n","import { DEVTOOLS_NAME } from \"./uiBlockingStore.constants\";\nimport type { DevtoolsOptions } from \"zustand/middleware\";\n\n/**\n * DevTools configuration for UI Blocking Store\n *\n * Enables Redux DevTools integration only in development mode\n * for better debugging experience without production overhead.\n */\nexport const devtoolsConfig: DevtoolsOptions = {\n name: DEVTOOLS_NAME,\n enabled: process.env.NODE_ENV !== \"production\",\n};\n","import { devtools } from \"zustand/middleware\";\nimport { createUIBlockingActions } from \"./uiBlockingStore.actions\";\nimport { devtoolsConfig } from \"./uiBlockingStore.config\";\nimport { createShallowStore } from \"./uiBlockingStore.utils\";\nimport type { UIBlockingStore } from \"./uiBlockingStore.types\";\n\n/**\n * UI Blocking Store\n *\n * Global Zustand store for managing UI blocking state across the application.\n *\n * Features:\n * - Priority-based blocking system\n * - Scope-based blocking (global, specific areas, or multiple scopes)\n * - Automatic cleanup on unmount (when using hooks)\n * - DevTools integration for debugging\n * - Automatic shallow comparison for selectors\n *\n */\nconst { useStore: useUIBlockingStore, useStoreApi: uiBlockingStoreApi } = createShallowStore<\n UIBlockingStore,\n [[\"zustand/devtools\", never]]\n>(devtools(createUIBlockingActions, devtoolsConfig));\n\nexport { useUIBlockingStore, uiBlockingStoreApi };\n","import { useCallback } from \"react\";\nimport { ASYNC_ACTION_PRIORITY, useUIBlockingStore } from \"../../store\";\n\n/**\n * Hook to wrap async functions with automatic blocking/unblocking\n *\n * Creates a wrapper function that automatically adds a blocker before executing\n * the async function and removes it after completion (success or failure).\n *\n * @template T - The return type of the async function\n * @param actionId - Unique identifier for the action (used in blocker ID and reason)\n * @param scope - Scope(s) to block during execution (default: \"global\")\n * @returns Function that wraps async functions with blocking behavior\n *\n */\nexport const useAsyncAction = <T = unknown>(\n actionId: string,\n scope?: string | ReadonlyArray<string>\n): ((asyncFn: () => Promise<T>) => Promise<T>) => {\n const { addBlocker, removeBlocker } = useUIBlockingStore((state) => ({\n addBlocker: state.addBlocker,\n removeBlocker: state.removeBlocker,\n }));\n\n const executeWithBlocking = useCallback(\n async (asyncFn: () => Promise<T>): Promise<T> => {\n const blockerId = `${actionId}-${Date.now().toString()}`;\n\n try {\n addBlocker(blockerId, {\n scope,\n reason: `Executing ${actionId}`,\n priority: ASYNC_ACTION_PRIORITY,\n });\n\n return await asyncFn();\n } finally {\n removeBlocker(blockerId);\n }\n },\n [actionId, scope, addBlocker, removeBlocker]\n );\n\n return executeWithBlocking;\n};\n","import { useEffect } from \"react\";\nimport { type BlockerConfig, useUIBlockingStore } from \"../../store\";\n\n/**\n * Hook to automatically add and remove a blocker based on component lifecycle\n *\n * Automatically adds a blocker when the component mounts (or when activated)\n * and removes it when the component unmounts (or when deactivated).\n *\n * @param blockerId - Unique identifier for the blocker\n * @param config - Blocker configuration (scope, reason, priority)\n * @param isActive - Whether the blocker is currently active (default: true)\n *\n */\nexport const useBlocker = (blockerId: string, config: BlockerConfig, isActive = true): void => {\n const { addBlocker, removeBlocker } = useUIBlockingStore((state) => ({\n addBlocker: state.addBlocker,\n removeBlocker: state.removeBlocker,\n }));\n\n useEffect(() => {\n if (!isActive || !blockerId) {\n return;\n }\n\n addBlocker(blockerId, config);\n\n return () => {\n removeBlocker(blockerId);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [blockerId, isActive, addBlocker, removeBlocker]);\n};\n","import { BlockerConfig } from \"../../store\";\n\n/**\n * Creates a blocker configuration object from partial config.\n * Filters out undefined values to create a clean BlockerConfig.\n *\n * @param config - Partial blocker configuration\n * @returns Complete BlockerConfig object\n *\n */\nexport function createBlockerConfig(config: {\n scope?: string | ReadonlyArray<string>;\n reason?: string;\n priority?: number;\n}): BlockerConfig {\n return {\n scope: config.scope,\n reason: config.reason,\n priority: config.priority,\n };\n}\n","import { RefObject, useEffect, useRef } from \"react\";\n\n/**\n * Keeps a ref updated with the latest config value.\n * Useful for accessing current config in callbacks without stale closures.\n *\n * @param config - Configuration object to track\n * @returns Mutable ref that always contains the latest config\n *\n */\nexport function useConfigRef<T>(config: T): RefObject<T> {\n const configRef = useRef(config);\n\n useEffect(() => {\n configRef.current = config;\n }, [config]);\n\n return configRef;\n}\n","import { useCallback, useEffect, useRef } from \"react\";\nimport { useUIBlockingStore } from \"../../store\";\nimport { createBlockerConfig } from \"../useBlocker\";\nimport { useConfigRef } from \"../useConfigRef\";\nimport { ConditionalBlockerConfig } from \"./useConditionalBlocker.types\";\n\n/**\n * Hook for conditional blocking based on a condition function.\n *\n * Periodically checks a condition and blocks/unblocks based on the result.\n * The condition is evaluated at the specified interval (default 1000ms).\n *\n * @param blockerId - Unique identifier for this blocker\n * @param config - Configuration including condition function and check interval\n *\n */\nexport const useConditionalBlocker = <TState = unknown>(\n blockerId: string,\n config: ConditionalBlockerConfig<TState>\n): void => {\n const { addBlocker, removeBlocker } = useUIBlockingStore((state) => ({\n addBlocker: state.addBlocker,\n removeBlocker: state.removeBlocker,\n }));\n const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);\n const isBlockedRef = useRef(false);\n const configRef = useConfigRef(config);\n\n const checkCondition = useCallback(() => {\n const currentConfig = configRef.current;\n const shouldBlock = currentConfig.condition(currentConfig.state);\n\n // No state change needed\n if (shouldBlock === isBlockedRef.current) {\n return;\n }\n\n if (shouldBlock) {\n addBlocker(blockerId, createBlockerConfig(currentConfig));\n } else {\n removeBlocker(blockerId);\n }\n isBlockedRef.current = shouldBlock;\n }, [blockerId, addBlocker, removeBlocker, configRef]);\n\n useEffect(() => {\n checkCondition();\n\n const interval = configRef.current.checkInterval ?? 1000;\n intervalRef.current = setInterval(checkCondition, interval);\n\n return (): void => {\n if (intervalRef.current) {\n clearInterval(intervalRef.current);\n intervalRef.current = null;\n }\n if (isBlockedRef.current) {\n removeBlocker(blockerId);\n isBlockedRef.current = false;\n }\n };\n // configRef is stable and doesn't need to be in dependencies\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [checkCondition, blockerId, removeBlocker]);\n};\n","import { useCallback, useState } from \"react\";\nimport { useBlocker } from \"../useBlocker\";\nimport {\n ConfirmableBlockerConfig,\n UseConfirmableBlockerReturn,\n} from \"./useConfirmableBlocker.types\";\n\n/**\n * Hook for creating a confirmable action with blocking UI\n *\n */\nexport const useConfirmableBlocker = (\n blockerId: string,\n config: ConfirmableBlockerConfig\n): UseConfirmableBlockerReturn => {\n const [isDialogOpen, setIsDialogOpen] = useState(false);\n const [isExecuting, setIsExecuting] = useState(false);\n\n useBlocker(\n blockerId,\n {\n ...config,\n reason: config.reason ?? config.confirmMessage,\n },\n isDialogOpen || isExecuting\n );\n\n const execute = useCallback(() => {\n setIsDialogOpen(true);\n }, []);\n\n const onConfirm = useCallback(async () => {\n setIsDialogOpen(false);\n setIsExecuting(true);\n\n try {\n await config.onConfirm();\n } catch (error) {\n console.error(\"[UIBlocking] Confirmable action error:\", error);\n throw error;\n } finally {\n setIsExecuting(false);\n }\n }, [config]);\n\n const onCancel = useCallback(() => {\n setIsDialogOpen(false);\n config.onCancel?.();\n }, [config]);\n\n return {\n execute,\n isDialogOpen,\n isExecuting,\n confirmConfig: {\n title: config.confirmTitle ?? \"Confirm Action\",\n message: config.confirmMessage,\n confirmText: config.confirmButtonText ?? \"Confirm\",\n cancelText: config.cancelButtonText ?? \"Cancel\",\n },\n onConfirm,\n onCancel,\n };\n};\n","import { useUIBlockingStore } from \"../../store\";\n\n/**\n * Hook to check if a scope is currently blocked\n *\n * Returns a boolean indicating whether the specified scope(s) are blocked.\n * Automatically re-renders when the blocking state changes.\n *\n * @param scope - Scope or array of scopes to check (default: \"global\")\n * @returns True if any of the specified scopes are blocked\n *\n */\nexport const useIsBlocked = (scope?: string | ReadonlyArray<string>): boolean => {\n return useUIBlockingStore((state) => state.isBlocked(scope));\n};\n","import type { BlockingSchedule } from \"./useScheduledBlocker.types\";\n\n/**\n * Maximum safe timeout value for setTimeout in JavaScript (~24.8 days).\n * Values larger than this will cause setTimeout to trigger immediately.\n */\nexport const MAX_TIMEOUT_MS = 2147483647;\n\n/**\n * Validates a date value and converts it to timestamp.\n *\n * @param date - Date value as string, Date object, or number\n * @returns Timestamp in milliseconds, or NaN if invalid\n */\nexport function parseDate(date: string | Date | number): number {\n return new Date(date).getTime();\n}\n\n/**\n * Validates if a timestamp is valid (not NaN).\n *\n * @param timestamp - Timestamp to validate\n * @returns True if valid, false otherwise\n */\nexport function isValidTimestamp(timestamp: number): boolean {\n return !Number.isNaN(timestamp);\n}\n\n/**\n * Calculates the end time based on schedule configuration.\n * Duration takes precedence over end time if both are provided.\n *\n * @param schedule - Blocking schedule configuration\n * @param startTime - Start time in milliseconds\n * @returns End time in milliseconds, or undefined if not specified\n */\nexport function calculateEndTime(\n schedule: BlockingSchedule,\n startTime: number\n): number | undefined {\n if (schedule.duration) {\n return startTime + schedule.duration;\n }\n\n if (schedule.end) {\n const endTime = parseDate(schedule.end);\n return isValidTimestamp(endTime) ? endTime : undefined;\n }\n\n return undefined;\n}\n\n/**\n * Validates if a delay is within the safe setTimeout range.\n *\n * @param delay - Delay in milliseconds\n * @returns True if delay is safe to use with setTimeout\n */\nexport function isSafeTimeout(delay: number): boolean {\n return delay > 0 && delay <= MAX_TIMEOUT_MS;\n}\n\n/**\n * Determines if the current time is within a blocking schedule.\n *\n * @param startTime - Schedule start time in milliseconds\n * @param endTime - Schedule end time in milliseconds (optional)\n * @param now - Current time in milliseconds\n * @returns True if currently in the blocking period\n */\nexport function isInBlockingPeriod(\n startTime: number,\n endTime: number | undefined,\n now: number\n): boolean {\n if (startTime > now) {\n return false; // Not started yet\n }\n\n if (!endTime) {\n return true; // No end time means block indefinitely\n }\n\n return endTime > now; // Check if end time hasn't passed\n}\n\n/**\n * Checks if a schedule is completely in the past.\n *\n * @param startTime - Schedule start time in milliseconds\n * @param endTime - Schedule end time in milliseconds (optional)\n * @param now - Current time in milliseconds\n * @returns True if the schedule is in the past\n */\nexport function isScheduleInPast(\n startTime: number,\n endTime: number | undefined,\n now: number\n): boolean {\n if (!endTime) {\n return false; // No end time means it can still be active\n }\n\n return endTime <= now && startTime <= now;\n}\n","import { useCallback, useEffect, useRef } from \"react\";\nimport { useUIBlockingStore } from \"../../store\";\nimport { createBlockerConfig } from \"../useBlocker\";\nimport { useConfigRef } from \"../useConfigRef\";\nimport { ScheduledBlockerConfig } from \"./useScheduledBlocker.types\";\nimport {\n MAX_TIMEOUT_MS,\n calculateEndTime,\n isInBlockingPeriod,\n isSafeTimeout,\n isScheduleInPast,\n isValidTimestamp,\n parseDate,\n} from \"./useScheduledBlocker.utils\";\n\n/**\n * Hook for scheduling UI blocking for a specific time period.\n *\n * Blocks UI during a scheduled maintenance window or time period.\n * Supports start/end times as Date objects, ISO strings, or timestamps.\n * If both duration and end are provided, duration takes precedence.\n *\n * @param blockerId - Unique identifier for this blocker\n * @param config - Configuration including schedule and callbacks\n *\n */\nexport const useScheduledBlocker = (blockerId: string, config: ScheduledBlockerConfig): void => {\n const { addBlocker, removeBlocker } = useUIBlockingStore((state) => ({\n addBlocker: state.addBlocker,\n removeBlocker: state.removeBlocker,\n }));\n const timeoutsRef = useRef<{\n start?: ReturnType<typeof setTimeout>;\n end?: ReturnType<typeof setTimeout>;\n }>({});\n const configRef = useConfigRef(config);\n\n const cleanup = useCallback(() => {\n if (timeoutsRef.current.start) {\n clearTimeout(timeoutsRef.current.start);\n timeoutsRef.current.start = undefined;\n }\n if (timeoutsRef.current.end) {\n clearTimeout(timeoutsRef.current.end);\n timeoutsRef.current.end = undefined;\n }\n }, []);\n\n useEffect(() => {\n const currentConfig = configRef.current;\n const startTime = parseDate(currentConfig.schedule.start);\n const now = Date.now();\n\n // Validate start time\n if (!isValidTimestamp(startTime)) {\n console.error(`[UIBlocking] Invalid start time for blocker \"${blockerId}\"`);\n return;\n }\n\n const scheduleEnd = (): void => {\n const endTime = calculateEndTime(currentConfig.schedule, startTime);\n if (!endTime) {\n return;\n }\n\n const remainingTime = endTime - Date.now();\n if (remainingTime > 0) {\n timeoutsRef.current.end = setTimeout(() => {\n configRef.current.onScheduleEnd?.();\n removeBlocker(blockerId);\n }, remainingTime);\n }\n };\n\n const startBlocking = (): void => {\n const cfg = configRef.current;\n addBlocker(blockerId, createBlockerConfig(cfg));\n cfg.onScheduleStart?.();\n scheduleEnd();\n };\n\n // If start time hasn't arrived yet\n if (startTime > now) {\n const delay = startTime - now;\n\n if (!isSafeTimeout(delay)) {\n console.warn(\n `[UIBlocking] Schedule delay exceeds maximum timeout (${MAX_TIMEOUT_MS.toString()}ms) for blocker \"${blockerId}\"`\n );\n return;\n }\n\n timeoutsRef.current.start = setTimeout(startBlocking, delay);\n }\n // If already in blocking period or should start immediately\n else {\n const endTime = calculateEndTime(currentConfig.schedule, startTime);\n\n if (isInBlockingPeriod(startTime, endTime, now)) {\n startBlocking();\n } else if (isScheduleInPast(startTime, endTime, now)) {\n console.warn(`[UIBlocking] Schedule is in the past for blocker \"${blockerId}\"`);\n }\n }\n\n return (): void => {\n cleanup();\n removeBlocker(blockerId);\n };\n // configRef is stable and doesn't need to be in dependencies\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [blockerId, addBlocker, removeBlocker, cleanup]);\n};\n","import { AnalyticsEventData } from \"./analyticsMiddleware.types\";\nimport { MiddlewareContext } from \"./middleware.types\";\n\nconst capitalizeFirst = (str: string): string => {\n return str.charAt(0).toUpperCase() + str.slice(1);\n};\n\nexport const buildEventData = (context: MiddlewareContext): AnalyticsEventData => {\n const eventData: AnalyticsEventData = {\n blocker_id: context.blockerId,\n };\n const { scope, reason, priority } = context.config ?? {};\n\n if (scope !== undefined) {\n eventData.scope = Array.isArray(scope) ? scope.join(\",\") : scope;\n }\n\n if (reason !== undefined) {\n eventData.reason = reason;\n }\n\n if (priority !== undefined) {\n eventData.priority = priority;\n }\n\n return eventData;\n};\n\nexport const trackGoogleAnalytics = (action: string, eventData: AnalyticsEventData): void => {\n if (window.gtag) {\n window.gtag(\"event\", `ui_blocking_${action}`, eventData);\n }\n};\n\nexport const trackMixpanel = (action: string, eventData: AnalyticsEventData): void => {\n if (window.mixpanel) {\n const eventName = `UI Blocking ${action.split(\"_\").map(capitalizeFirst).join(\" \")}`;\n\n window.mixpanel.track(eventName, eventData);\n }\n};\n\nexport const trackAmplitude = (action: string, eventData: AnalyticsEventData): void => {\n if (window.amplitude) {\n const eventName = `UI Blocking ${action.split(\"_\").map(capitalizeFirst).join(\" \")}`;\n\n window.amplitude.track(eventName, eventData);\n }\n};\n\nexport const trackCustom = (\n trackFn: (event: string, data: AnalyticsEventData) => void,\n action: string,\n eventData: AnalyticsEventData\n): void => {\n try {\n trackFn(`ui_blocking_${action}`, eventData);\n } catch {\n // Silently ignore errors in custom tracker\n }\n};\n","import { AnalyticsConfig, AnalyticsEventData } from \"./analyticsMiddleware.types\";\nimport {\n buildEventData,\n trackAmplitude,\n trackCustom,\n trackGoogleAnalytics,\n trackMixpanel,\n} from \"./analyticsMiddleware.utils\";\nimport { Middleware, MiddlewareContext } from \"./middleware.types\";\n\nconst trackEvent = (\n config: AnalyticsConfig,\n context: MiddlewareContext,\n eventData: AnalyticsEventData\n): void => {\n if (\"provider\" in config) {\n switch (config.provider) {\n case \"ga\":\n trackGoogleAnalytics(context.action, eventData);\n return;\n case \"mixpanel\":\n trackMixpanel(context.action, eventData);\n return;\n case \"amplitude\":\n trackAmplitude(context.action, eventData);\n return;\n }\n }\n\n if (\"track\" in config) {\n trackCustom(config.track, context.action, eventData);\n }\n};\n\nexport const createAnalyticsMiddleware = (config: AnalyticsConfig): Middleware => {\n return (context) => {\n const eventData = buildEventData(context);\n\n trackEvent(config, context, eventData);\n };\n};\n","import { MiddlewareBlockerConfig, MiddlewareContext } from \"./middleware.types\";\n\nexport const getActionEmoji = (action: string): string => {\n switch (action) {\n case \"add\":\n return \"➕\";\n case \"remove\":\n return \"➖\";\n case \"update\":\n return \"🔄\";\n case \"cancel\":\n return \"❌\";\n case \"timeout\":\n return \"⏱️\";\n default:\n return \"❓\";\n }\n};\n\nconst extractConfigDetails = (config?: MiddlewareBlockerConfig): Record<string, unknown> => {\n if (!config) {\n return {};\n }\n\n const { scope, reason, priority } = config;\n\n const details: Record<string, unknown> = {\n scope,\n reason,\n };\n\n if (priority !== undefined) {\n details.priority = priority;\n }\n\n return details;\n};\n\nexport const formatLogData = (context: MiddlewareContext): Record<string, unknown> => {\n const configDetails = extractConfigDetails(context.config);\n\n if (context.prevState) {\n return {\n config: configDetails,\n prevState: extractConfigDetails(context.prevState),\n };\n }\n\n return configDetails;\n};\n","import { formatLogData, getActionEmoji } from \"./loggerMiddleware.utils\";\nimport { Middleware } from \"./middleware.types\";\n\nconst LOG_PREFIX = \"[UIBlocking]\";\n\nexport const loggerMiddleware: Middleware = (context) => {\n const emoji = getActionEmoji(context.action);\n const logData = formatLogData(context);\n\n console.log(LOG_PREFIX, emoji, context.blockerId, logData);\n};\n","export const handleAddAction = (\n blockerId: string,\n timestamp: number,\n blockStartTimes: Map<string, number>\n): void => {\n blockStartTimes.set(blockerId, timestamp);\n};\n","import { Middleware, MiddlewareContext } from \"./middleware.types\";\nimport { PerformanceConfig } from \"./performanceMiddleware.types\";\nimport { handleAddAction } from \"./performanceMiddleware.utils\";\n\nconst DEFAULT_SLOW_BLOCK_THRESHOLD = 3000;\nconst ACTION_ADD = \"add\";\nconst ACTION_REMOVE = \"remove\";\n\nconst handleRemoveAction = (\n context: MiddlewareContext,\n blockStartTimes: Map<string, number>,\n slowBlockThreshold: number,\n onSlowBlock?: (blockerId: string, duration: number) => void\n): void => {\n const startTime = blockStartTimes.get(context.blockerId);\n\n if (startTime === undefined) {\n return;\n }\n\n const duration = context.timestamp - startTime;\n blockStartTimes.delete(context.blockerId);\n\n if (duration >= slowBlockThreshold) {\n console.warn(\n `[UIBlocking] Slow block detected: \"${context.blockerId}\" took ${duration.toString()}ms`\n );\n\n onSlowBlock?.(context.blockerId, duration);\n }\n};\n\nexport const createPerformanceMiddleware = (config: PerformanceConfig = {}): Middleware => {\n const { slowBlockThreshold = DEFAULT_SLOW_BLOCK_THRESHOLD, onSlowBlock } = config;\n const blockStartTimes = new Map<string, number>();\n\n return (context) => {\n if (context.action === ACTION_ADD) {\n handleAddAction(context.blockerId, context.timestamp, blockStartTimes);\n } else if (context.action === ACTION_REMOVE) {\n handleRemoveAction(context, blockStartTimes, slowBlockThreshold, onSlowBlock);\n }\n };\n};\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@okyrychenko-dev/react-action-guard",
3
- "version": "0.2.3",
3
+ "version": "0.3.1",
4
4
  "type": "module",
5
5
  "description": "Elegant UI blocking management for React applications with priorities, scopes, and automatic cleanup",
6
6
  "main": "./dist/index.js",