@okyrychenko-dev/react-action-guard 0.6.1 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -36,8 +36,8 @@ pnpm add @okyrychenko-dev/react-action-guard zustand
36
36
 
37
37
  This package requires the following peer dependencies:
38
38
 
39
- - [React](https://react.dev/) ^17.0.0 || ^18.0.0 || ^19.0.0
40
- - [Zustand](https://zustand-demo.pmnd.rs/) ^4.5.7 || ^5.0.0 - State management library
39
+ - [React](https://react.dev/) ^18.0.0 || ^19.0.0
40
+ - [Zustand](https://zustand-demo.pmnd.rs/) ^5.0.0 - State management library
41
41
 
42
42
  ## Quick Start
43
43
 
package/dist/index.cjs CHANGED
@@ -24,16 +24,18 @@ function normalizeScopeToArray(scope) {
24
24
  }
25
25
 
26
26
  // src/store/uiBlockingStore.actions.ts
27
- var normalizePriority = (priority, fallback = DEFAULT_PRIORITY) => {
27
+ function normalizePriority(priority, fallback = DEFAULT_PRIORITY) {
28
28
  return priority !== void 0 ? Math.max(0, priority) : fallback;
29
- };
30
- var createMiddlewareContext = (action, blockerId, config, prevState) => ({
31
- action,
32
- blockerId,
33
- config,
34
- timestamp: Date.now(),
35
- ...prevState && { prevState }
36
- });
29
+ }
30
+ function createMiddlewareContext(action, blockerId, config, prevState) {
31
+ return {
32
+ action,
33
+ blockerId,
34
+ config,
35
+ timestamp: Date.now(),
36
+ ...prevState && { prevState }
37
+ };
38
+ }
37
39
  var createUIBlockingActions = (set, get) => ({
38
40
  // State
39
41
  activeBlockers: /* @__PURE__ */ new Map(),
@@ -65,14 +67,14 @@ var createUIBlockingActions = (set, get) => ({
65
67
  // Actions
66
68
  /**
67
69
  * Adds a new blocker or overwrites an existing one.
68
- *
70
+ *
69
71
  * If a blocker with the same ID already exists, it will be replaced and any
70
72
  * existing timeout will be cleared. The blocker is active immediately after
71
73
  * being added. Triggers middleware with 'add' action.
72
- *
74
+ *
73
75
  * @param id - Unique identifier for the blocker. Must be unique within the store.
74
76
  * @param config - Blocker configuration. All fields are optional with defaults applied.
75
- *
77
+ *
76
78
  * @example
77
79
  * Basic usage
78
80
  * ```ts
@@ -82,7 +84,7 @@ var createUIBlockingActions = (set, get) => ({
82
84
  * priority: 70
83
85
  * });
84
86
  * ```
85
- *
87
+ *
86
88
  * @example
87
89
  * With timeout
88
90
  * ```ts
@@ -93,7 +95,7 @@ var createUIBlockingActions = (set, get) => ({
93
95
  * onTimeout: (id) => console.warn(`${id} timed out`)
94
96
  * });
95
97
  * ```
96
- *
98
+ *
97
99
  * @see {@link removeBlocker} to remove a blocker
98
100
  * @see {@link updateBlocker} to update an existing blocker
99
101
  */
@@ -144,13 +146,13 @@ var createUIBlockingActions = (set, get) => ({
144
146
  },
145
147
  /**
146
148
  * Updates an existing blocker or creates it if it doesn't exist.
147
- *
149
+ *
148
150
  * Merges the provided configuration with existing blocker data. If the timeout
149
151
  * is changed, the timeout timer is restarted. Triggers middleware with 'update' action.
150
- *
152
+ *
151
153
  * @param id - Identifier of the blocker to update
152
154
  * @param config - Partial configuration to merge with existing blocker data
153
- *
155
+ *
154
156
  * @example
155
157
  * Update blocker reason
156
158
  * ```ts
@@ -158,7 +160,7 @@ var createUIBlockingActions = (set, get) => ({
158
160
  * reason: 'Saving additional data...'
159
161
  * });
160
162
  * ```
161
- *
163
+ *
162
164
  * @example
163
165
  * Extend timeout
164
166
  * ```ts
@@ -166,7 +168,7 @@ var createUIBlockingActions = (set, get) => ({
166
168
  * timeout: 60000 // Extend to 60 seconds
167
169
  * });
168
170
  * ```
169
- *
171
+ *
170
172
  * @see {@link addBlocker} to create a new blocker
171
173
  */
172
174
  updateBlocker: (id, config = {}) => {
@@ -242,12 +244,12 @@ var createUIBlockingActions = (set, get) => ({
242
244
  },
243
245
  /**
244
246
  * Removes a blocker from the store.
245
- *
247
+ *
246
248
  * Clears any associated timeout and triggers middleware with 'remove' action.
247
249
  * Safe to call even if the blocker doesn't exist (no-op in that case).
248
- *
250
+ *
249
251
  * @param id - Identifier of the blocker to remove
250
- *
252
+ *
251
253
  * @example
252
254
  * ```ts
253
255
  * // Add and remove a blocker
@@ -255,7 +257,7 @@ var createUIBlockingActions = (set, get) => ({
255
257
  * // ... later
256
258
  * store.getState().removeBlocker('temp');
257
259
  * ```
258
- *
260
+ *
259
261
  * @see {@link addBlocker} to add a blocker
260
262
  * @see {@link clearAllBlockers} to remove all blockers at once
261
263
  */
@@ -275,28 +277,28 @@ var createUIBlockingActions = (set, get) => ({
275
277
  },
276
278
  /**
277
279
  * Checks if one or more scopes are currently blocked.
278
- *
280
+ *
279
281
  * Returns true if ANY blocker affects the specified scope(s). Global scope
280
282
  * blockers will cause this to return true for any scope check.
281
- *
283
+ *
282
284
  * @param scope - Scope(s) to check. Defaults to "global" if not specified.
283
285
  * Can be a single scope string or array of scopes.
284
286
  * @returns true if any of the specified scopes are currently blocked
285
- *
287
+ *
286
288
  * @example
287
289
  * Single scope check
288
290
  * ```ts
289
291
  * const isFormBlocked = store.getState().isBlocked('form');
290
292
  * console.log(isFormBlocked); // true or false
291
293
  * ```
292
- *
294
+ *
293
295
  * @example
294
296
  * Multiple scopes check
295
297
  * ```ts
296
298
  * const isBlocked = store.getState().isBlocked(['form', 'navigation']);
297
299
  * // Returns true if either 'form' OR 'navigation' has active blockers
298
300
  * ```
299
- *
301
+ *
300
302
  * @see {@link getBlockingInfo} for detailed blocker information
301
303
  */
302
304
  isBlocked: (scope = DEFAULT_SCOPE) => {
@@ -315,14 +317,14 @@ var createUIBlockingActions = (set, get) => ({
315
317
  },
316
318
  /**
317
319
  * Gets detailed information about all blockers affecting a specific scope.
318
- *
320
+ *
319
321
  * Returns an array of blocker objects sorted by priority (highest first).
320
322
  * Includes global blockers and scope-specific blockers. Each blocker object
321
323
  * contains id, reason, priority, scope, timestamp, and timeout information.
322
- *
324
+ *
323
325
  * @param scope - Scope to get blocking information for
324
326
  * @returns Array of {@link BlockerInfo} objects, sorted by priority descending
325
- *
327
+ *
326
328
  * @example
327
329
  * Display blocker details
328
330
  * ```ts
@@ -332,7 +334,7 @@ var createUIBlockingActions = (set, get) => ({
332
334
  * console.log(`Priority: ${blocker.priority}`);
333
335
  * });
334
336
  * ```
335
- *
337
+ *
336
338
  * @example
337
339
  * Get highest priority blocker
338
340
  * ```ts
@@ -342,7 +344,7 @@ var createUIBlockingActions = (set, get) => ({
342
344
  * console.log(`Top blocker: ${topBlocker.reason}`);
343
345
  * }
344
346
  * ```
345
- *
347
+ *
346
348
  * @see {@link isBlocked} for a simple boolean check
347
349
  * @see {@link BlockerInfo} for the structure of returned objects
348
350
  */
@@ -359,16 +361,16 @@ var createUIBlockingActions = (set, get) => ({
359
361
  },
360
362
  /**
361
363
  * Removes all active blockers from the store.
362
- *
364
+ *
363
365
  * Clears all timeouts and triggers middleware with 'clear' action.
364
366
  * Useful for resetting the blocking state.
365
- *
367
+ *
366
368
  * @example
367
369
  * ```ts
368
370
  * // Clear all blockers on logout
369
371
  * store.getState().clearAllBlockers();
370
372
  * ```
371
- *
373
+ *
372
374
  * @see {@link clearBlockersForScope} to clear blockers for a specific scope
373
375
  */
374
376
  clearAllBlockers: () => {
@@ -391,26 +393,26 @@ var createUIBlockingActions = (set, get) => ({
391
393
  },
392
394
  /**
393
395
  * Removes all blockers that affect a specific scope.
394
- *
396
+ *
395
397
  * Clears timeouts for removed blockers and triggers middleware with
396
398
  * 'clear_scope' action. Global scope blockers are NOT cleared by this method.
397
- *
399
+ *
398
400
  * @param scope - Scope to clear blockers for
399
- *
401
+ *
400
402
  * @example
401
403
  * Clear form blockers
402
404
  * ```ts
403
405
  * // Clear all blockers affecting 'form' scope
404
406
  * store.getState().clearBlockersForScope('form');
405
407
  * ```
406
- *
408
+ *
407
409
  * @example
408
410
  * Clear on navigation
409
411
  * ```ts
410
412
  * // Clear navigation blockers when user navigates away
411
413
  * store.getState().clearBlockersForScope('navigation');
412
414
  * ```
413
- *
415
+ *
414
416
  * @see {@link clearAllBlockers} to clear all blockers
415
417
  */
416
418
  clearBlockersForScope: (scope) => {
@@ -498,7 +500,7 @@ function useResolvedStoreWithSelector(selector) {
498
500
  }
499
501
 
500
502
  // src/hooks/useAsyncAction/useAsyncAction.ts
501
- var useAsyncAction = (actionId, scope, options) => {
503
+ function useAsyncAction(actionId, scope, options) {
502
504
  const { addBlocker, removeBlocker } = useResolvedStoreWithSelector((state) => ({
503
505
  addBlocker: state.addBlocker,
504
506
  removeBlocker: state.removeBlocker
@@ -524,8 +526,8 @@ var useAsyncAction = (actionId, scope, options) => {
524
526
  [actionId, scope, options?.timeout, options?.onTimeout, addBlocker, removeBlocker]
525
527
  );
526
528
  return executeWithBlocking;
527
- };
528
- var useBlocker = (blockerId, config, isActive = true) => {
529
+ }
530
+ function useBlocker(blockerId, config, isActive = true) {
529
531
  const { addBlocker, removeBlocker } = useResolvedStoreWithSelector((state) => ({
530
532
  addBlocker: state.addBlocker,
531
533
  removeBlocker: state.removeBlocker
@@ -539,7 +541,7 @@ var useBlocker = (blockerId, config, isActive = true) => {
539
541
  removeBlocker(blockerId);
540
542
  };
541
543
  }, [blockerId, isActive, addBlocker, removeBlocker]);
542
- };
544
+ }
543
545
 
544
546
  // src/hooks/useBlocker/useBlocker.utils.ts
545
547
  function createBlockerConfig(config) {
@@ -549,13 +551,13 @@ function createBlockerConfig(config) {
549
551
  priority: config.priority
550
552
  };
551
553
  }
552
- var useBlockingInfo = (scope = DEFAULT_SCOPE) => {
554
+ function useBlockingInfo(scope = DEFAULT_SCOPE) {
553
555
  const store = useResolvedStore();
554
556
  const activeBlockers = zustand.useStore(store, (state) => state.activeBlockers);
555
557
  return react.useMemo(() => {
556
558
  return store.getState().getBlockingInfo(scope);
557
559
  }, [activeBlockers, scope, store]);
558
- };
560
+ }
559
561
  function useConfigRef(config) {
560
562
  const configRef = react.useRef(config);
561
563
  react.useEffect(() => {
@@ -565,7 +567,7 @@ function useConfigRef(config) {
565
567
  }
566
568
 
567
569
  // src/hooks/useConditionalBlocker/useConditionalBlocker.ts
568
- var useConditionalBlocker = (blockerId, config) => {
570
+ function useConditionalBlocker(blockerId, config) {
569
571
  const { addBlocker, removeBlocker } = useResolvedStoreWithSelector((state) => ({
570
572
  addBlocker: state.addBlocker,
571
573
  removeBlocker: state.removeBlocker
@@ -601,8 +603,8 @@ var useConditionalBlocker = (blockerId, config) => {
601
603
  }
602
604
  };
603
605
  }, [checkCondition, blockerId, removeBlocker]);
604
- };
605
- var useConfirmableBlocker = (blockerId, config) => {
606
+ }
607
+ function useConfirmableBlocker(blockerId, config) {
606
608
  const [isDialogOpen, setIsDialogOpen] = react.useState(false);
607
609
  const [isExecuting, setIsExecuting] = react.useState(false);
608
610
  useBlocker(
@@ -645,12 +647,12 @@ var useConfirmableBlocker = (blockerId, config) => {
645
647
  onConfirm,
646
648
  onCancel
647
649
  };
648
- };
650
+ }
649
651
 
650
652
  // src/hooks/useIsBlocked/useIsBlocked.ts
651
- var useIsBlocked = (scope) => {
653
+ function useIsBlocked(scope) {
652
654
  return useResolvedStoreWithSelector((state) => state.isBlocked(scope));
653
- };
655
+ }
654
656
 
655
657
  // src/hooks/useScheduledBlocker/useScheduledBlocker.utils.ts
656
658
  var MAX_TIMEOUT_MS = 2147483647;
@@ -690,7 +692,7 @@ function isScheduleInPast(startTime, endTime, now) {
690
692
  }
691
693
 
692
694
  // src/hooks/useScheduledBlocker/useScheduledBlocker.ts
693
- var useScheduledBlocker = (blockerId, config) => {
695
+ function useScheduledBlocker(blockerId, config) {
694
696
  const { addBlocker, removeBlocker } = useResolvedStoreWithSelector((state) => ({
695
697
  addBlocker: state.addBlocker,
696
698
  removeBlocker: state.removeBlocker
@@ -756,13 +758,13 @@ var useScheduledBlocker = (blockerId, config) => {
756
758
  removeBlocker(blockerId);
757
759
  };
758
760
  }, [blockerId, addBlocker, removeBlocker, cleanup]);
759
- };
761
+ }
760
762
 
761
763
  // src/middleware/analyticsMiddleware.utils.ts
762
- var capitalizeFirst = (str) => {
764
+ function capitalizeFirst(str) {
763
765
  return str.charAt(0).toUpperCase() + str.slice(1);
764
- };
765
- var buildEventData = (context) => {
766
+ }
767
+ function buildEventData(context) {
766
768
  const eventData = {
767
769
  blocker_id: context.blockerId
768
770
  };
@@ -777,33 +779,33 @@ var buildEventData = (context) => {
777
779
  eventData.priority = priority;
778
780
  }
779
781
  return eventData;
780
- };
781
- var trackGoogleAnalytics = (action, eventData) => {
782
+ }
783
+ function trackGoogleAnalytics(action, eventData) {
782
784
  if (window.gtag) {
783
785
  window.gtag("event", `ui_blocking_${action}`, eventData);
784
786
  }
785
- };
786
- var trackMixpanel = (action, eventData) => {
787
+ }
788
+ function trackMixpanel(action, eventData) {
787
789
  if (window.mixpanel) {
788
790
  const eventName = `UI Blocking ${action.split("_").map(capitalizeFirst).join(" ")}`;
789
791
  window.mixpanel.track(eventName, eventData);
790
792
  }
791
- };
792
- var trackAmplitude = (action, eventData) => {
793
+ }
794
+ function trackAmplitude(action, eventData) {
793
795
  if (window.amplitude) {
794
796
  const eventName = `UI Blocking ${action.split("_").map(capitalizeFirst).join(" ")}`;
795
797
  window.amplitude.track(eventName, eventData);
796
798
  }
797
- };
798
- var trackCustom = (trackFn, action, eventData) => {
799
+ }
800
+ function trackCustom(trackFn, action, eventData) {
799
801
  try {
800
802
  trackFn(`ui_blocking_${action}`, eventData);
801
803
  } catch {
802
804
  }
803
- };
805
+ }
804
806
 
805
807
  // src/middleware/analyticsMiddleware.ts
806
- var trackEvent = (config, context, eventData) => {
808
+ function trackEvent(config, context, eventData) {
807
809
  if ("provider" in config) {
808
810
  switch (config.provider) {
809
811
  case "ga":
@@ -820,13 +822,13 @@ var trackEvent = (config, context, eventData) => {
820
822
  if ("track" in config) {
821
823
  trackCustom(config.track, context.action, eventData);
822
824
  }
823
- };
824
- var createAnalyticsMiddleware = (config) => {
825
+ }
826
+ function createAnalyticsMiddleware(config) {
825
827
  return (context) => {
826
828
  const eventData = buildEventData(context);
827
829
  trackEvent(config, context, eventData);
828
830
  };
829
- };
831
+ }
830
832
 
831
833
  // src/middleware/configureMiddleware.ts
832
834
  function configureMiddleware(middlewares) {
@@ -838,7 +840,7 @@ function configureMiddleware(middlewares) {
838
840
  }
839
841
 
840
842
  // src/middleware/loggerMiddleware.utils.ts
841
- var getActionEmoji = (action) => {
843
+ function getActionEmoji(action) {
842
844
  switch (action) {
843
845
  case "add":
844
846
  return "\u2795";
@@ -855,8 +857,8 @@ var getActionEmoji = (action) => {
855
857
  default:
856
858
  return "\u2753";
857
859
  }
858
- };
859
- var extractConfigDetails = (config) => {
860
+ }
861
+ function extractConfigDetails(config) {
860
862
  if (!config) {
861
863
  return {};
862
864
  }
@@ -869,8 +871,8 @@ var extractConfigDetails = (config) => {
869
871
  details.priority = priority;
870
872
  }
871
873
  return details;
872
- };
873
- var formatLogData = (context) => {
874
+ }
875
+ function formatLogData(context) {
874
876
  const configDetails = extractConfigDetails(context.config);
875
877
  const logData = {};
876
878
  if (context.scope !== void 0) {
@@ -889,26 +891,26 @@ var formatLogData = (context) => {
889
891
  return configDetails;
890
892
  }
891
893
  return Object.keys(logData).length === 1 && logData.config ? configDetails : logData;
892
- };
894
+ }
893
895
 
894
896
  // src/middleware/loggerMiddleware.ts
895
897
  var LOG_PREFIX = "[UIBlocking]";
896
- var loggerMiddleware = (context) => {
898
+ function loggerMiddleware(context) {
897
899
  const emoji = getActionEmoji(context.action);
898
900
  const logData = formatLogData(context);
899
901
  console.log(LOG_PREFIX, emoji, context.blockerId, logData);
900
- };
902
+ }
901
903
 
902
904
  // src/middleware/performanceMiddleware.utils.ts
903
- var handleAddAction = (blockerId, timestamp, blockStartTimes) => {
905
+ function handleAddAction(blockerId, timestamp, blockStartTimes) {
904
906
  blockStartTimes.set(blockerId, timestamp);
905
- };
907
+ }
906
908
 
907
909
  // src/middleware/performanceMiddleware.ts
908
910
  var DEFAULT_SLOW_BLOCK_THRESHOLD = 3e3;
909
911
  var ACTION_ADD = "add";
910
912
  var ACTION_REMOVE = "remove";
911
- var handleRemoveAction = (context, blockStartTimes, slowBlockThreshold, onSlowBlock) => {
913
+ function handleRemoveAction(context, blockStartTimes, slowBlockThreshold, onSlowBlock) {
912
914
  const startTime = blockStartTimes.get(context.blockerId);
913
915
  if (startTime === void 0) {
914
916
  return;
@@ -921,8 +923,8 @@ var handleRemoveAction = (context, blockStartTimes, slowBlockThreshold, onSlowBl
921
923
  );
922
924
  onSlowBlock?.(context.blockerId, duration);
923
925
  }
924
- };
925
- var createPerformanceMiddleware = (config = {}) => {
926
+ }
927
+ function createPerformanceMiddleware(config = {}) {
926
928
  const { slowBlockThreshold = DEFAULT_SLOW_BLOCK_THRESHOLD, onSlowBlock } = config;
927
929
  const blockStartTimes = /* @__PURE__ */ new Map();
928
930
  return (context) => {
@@ -932,7 +934,7 @@ var createPerformanceMiddleware = (config = {}) => {
932
934
  handleRemoveAction(context, blockStartTimes, slowBlockThreshold, onSlowBlock);
933
935
  }
934
936
  };
935
- };
937
+ }
936
938
 
937
939
  // src/createTypedHooks.ts
938
940
  function createTypedHooks() {