react-simplikit 0.0.38 → 0.0.40

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.
@@ -42,6 +42,6 @@ type Props<Tag extends ElementType> = React.ComponentPropsWithoutRef<Tag> & UseI
42
42
  */
43
43
  declare const ImpressionArea: <T extends ElementType = "div">(props: Props<T> & {
44
44
  ref?: Ref<Element<T>>;
45
- }) => React.ReactNode;
45
+ }) => React.ReactElement;
46
46
 
47
47
  export { ImpressionArea };
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/hooks/useConditionalEffect/index.ts
21
+ var useConditionalEffect_exports = {};
22
+ __export(useConditionalEffect_exports, {
23
+ useConditionalEffect: () => useConditionalEffect
24
+ });
25
+ module.exports = __toCommonJS(useConditionalEffect_exports);
26
+
27
+ // src/hooks/useConditionalEffect/useConditionalEffect.ts
28
+ var import_react = require("react");
29
+ function useConditionalEffect(effect, deps, condition) {
30
+ const prevDepsRef = (0, import_react.useRef)(void 0);
31
+ const memoizedCondition = (0, import_react.useCallback)(condition, deps);
32
+ if (deps.length === 0) {
33
+ console.warn(
34
+ "useConditionalEffect received an empty dependency array. This may indicate missing dependencies and could lead to unexpected behavior."
35
+ );
36
+ }
37
+ const shouldRun = memoizedCondition(prevDepsRef.current, deps);
38
+ (0, import_react.useEffect)(() => {
39
+ if (shouldRun) {
40
+ const cleanup = effect();
41
+ prevDepsRef.current = deps;
42
+ return cleanup;
43
+ }
44
+ prevDepsRef.current = deps;
45
+ }, deps);
46
+ }
47
+ // Annotate the CommonJS export names for ESM import in node:
48
+ 0 && (module.exports = {
49
+ useConditionalEffect
50
+ });
@@ -0,0 +1,43 @@
1
+ import { DependencyList, EffectCallback } from 'react';
2
+
3
+ /**
4
+ * @description
5
+ * `useConditionalEffect` is a React hook that conditionally executes effects based on a predicate function.
6
+ * This provides more control over when effects run beyond just dependency changes.
7
+ *
8
+ * @param {EffectCallback} effect - The effect callback to run.
9
+ * @param {DependencyList} deps - Dependencies array, similar to useEffect.
10
+ * @param {(prevDeps: T | undefined, currentDeps: T) => boolean} condition - Function that determines if the effect should run based on previous and current deps.
11
+ * - On the initial render, `prevDeps` will be `undefined`. Your `condition` function should handle this case.
12
+ * - If you want your effect to run on the initial render, return `true` when `prevDeps` is `undefined`.
13
+ * - If you don't want your effect to run on the initial render, return `false` when `prevDeps` is `undefined`.
14
+ *
15
+ * @example
16
+ * import { useConditionalEffect } from 'react-simplikit';
17
+ *
18
+ * function Component() {
19
+ * const [count, setCount] = useState(0);
20
+ *
21
+ * // Only run effect when count increases
22
+ * useConditionalEffect(
23
+ * () => {
24
+ * console.log(`Count increased to ${count}`);
25
+ * },
26
+ * [count],
27
+ * (prevDeps, currentDeps) => {
28
+ * // Only run when count is defined and has increased
29
+ * return prevDeps && currentDeps[0] > prevDeps[0];
30
+ * }
31
+ * );
32
+ *
33
+ * return (
34
+ * <button onClick={() => setCount(prev => prev + 1)}>
35
+ * Increment: {count}
36
+ * </button>
37
+ * );
38
+ * }
39
+ *
40
+ */
41
+ declare function useConditionalEffect<T extends DependencyList>(effect: EffectCallback, deps: T, condition: (prevDeps: T | undefined, currentDeps: T) => boolean): void;
42
+
43
+ export { useConditionalEffect };
package/dist/index.cjs CHANGED
@@ -29,6 +29,7 @@ __export(index_exports, {
29
29
  useAsyncEffect: () => useAsyncEffect,
30
30
  useBooleanState: () => useBooleanState,
31
31
  useCallbackOncePerRender: () => useCallbackOncePerRender,
32
+ useConditionalEffect: () => useConditionalEffect,
32
33
  useControlledState: () => useControlledState,
33
34
  useCounter: () => useCounter,
34
35
  useDebounce: () => useDebounce,
@@ -381,18 +382,39 @@ function useCallbackOncePerRender(callback, deps) {
381
382
  });
382
383
  }
383
384
 
384
- // src/hooks/useControlledState/useControlledState.ts
385
+ // src/hooks/useConditionalEffect/useConditionalEffect.ts
385
386
  var import_react12 = require("react");
387
+ function useConditionalEffect(effect, deps, condition) {
388
+ const prevDepsRef = (0, import_react12.useRef)(void 0);
389
+ const memoizedCondition = (0, import_react12.useCallback)(condition, deps);
390
+ if (deps.length === 0) {
391
+ console.warn(
392
+ "useConditionalEffect received an empty dependency array. This may indicate missing dependencies and could lead to unexpected behavior."
393
+ );
394
+ }
395
+ const shouldRun = memoizedCondition(prevDepsRef.current, deps);
396
+ (0, import_react12.useEffect)(() => {
397
+ if (shouldRun) {
398
+ const cleanup = effect();
399
+ prevDepsRef.current = deps;
400
+ return cleanup;
401
+ }
402
+ prevDepsRef.current = deps;
403
+ }, deps);
404
+ }
405
+
406
+ // src/hooks/useControlledState/useControlledState.ts
407
+ var import_react13 = require("react");
386
408
  function useControlledState({
387
409
  value: valueProp,
388
410
  defaultValue,
389
411
  onChange,
390
412
  equalityFn = Object.is
391
413
  }) {
392
- const [uncontrolledState, setUncontrolledState] = (0, import_react12.useState)(defaultValue);
414
+ const [uncontrolledState, setUncontrolledState] = (0, import_react13.useState)(defaultValue);
393
415
  const controlled = valueProp !== void 0;
394
416
  const value = controlled ? valueProp : uncontrolledState;
395
- const setValue = (0, import_react12.useCallback)(
417
+ const setValue = (0, import_react13.useCallback)(
396
418
  (next) => {
397
419
  const nextValue = isSetStateAction(next) ? next(value) : next;
398
420
  if (equalityFn(value, nextValue) === true) return;
@@ -409,7 +431,7 @@ function isSetStateAction(next) {
409
431
  }
410
432
 
411
433
  // src/hooks/useCounter/useCounter.ts
412
- var import_react13 = require("react");
434
+ var import_react14 = require("react");
413
435
  function useCounter(initialValue = 0, { min, max, step = 1 } = {}) {
414
436
  const validateValue = (value) => {
415
437
  let validatedValue = value;
@@ -421,9 +443,9 @@ function useCounter(initialValue = 0, { min, max, step = 1 } = {}) {
421
443
  }
422
444
  return validatedValue;
423
445
  };
424
- const [count, setCountState] = (0, import_react13.useState)(() => validateValue(initialValue));
425
- const validateValueMemoized = (0, import_react13.useCallback)(validateValue, [min, max]);
426
- const setCount = (0, import_react13.useCallback)(
446
+ const [count, setCountState] = (0, import_react14.useState)(() => validateValue(initialValue));
447
+ const validateValueMemoized = (0, import_react14.useCallback)(validateValue, [min, max]);
448
+ const setCount = (0, import_react14.useCallback)(
427
449
  (value) => {
428
450
  setCountState((prev) => {
429
451
  const nextValue = typeof value === "function" ? value(prev) : value;
@@ -432,13 +454,13 @@ function useCounter(initialValue = 0, { min, max, step = 1 } = {}) {
432
454
  },
433
455
  [validateValueMemoized]
434
456
  );
435
- const increment = (0, import_react13.useCallback)(() => {
457
+ const increment = (0, import_react14.useCallback)(() => {
436
458
  setCount((prev) => prev + step);
437
459
  }, [setCount, step]);
438
- const decrement = (0, import_react13.useCallback)(() => {
460
+ const decrement = (0, import_react14.useCallback)(() => {
439
461
  setCount((prev) => prev - step);
440
462
  }, [setCount, step]);
441
- const reset = (0, import_react13.useCallback)(() => {
463
+ const reset = (0, import_react14.useCallback)(() => {
442
464
  setCount(initialValue);
443
465
  }, [setCount, initialValue]);
444
466
  return {
@@ -451,12 +473,12 @@ function useCounter(initialValue = 0, { min, max, step = 1 } = {}) {
451
473
  }
452
474
 
453
475
  // src/hooks/useDebounce/useDebounce.ts
454
- var import_react14 = require("react");
455
476
  var import_react15 = require("react");
477
+ var import_react16 = require("react");
456
478
  function useDebounce(callback, wait, options = {}) {
457
479
  const preservedCallback = usePreservedCallback(callback);
458
480
  const { leading = false, trailing = true } = options;
459
- const edges = (0, import_react15.useMemo)(() => {
481
+ const edges = (0, import_react16.useMemo)(() => {
460
482
  const _edges = [];
461
483
  if (leading) {
462
484
  _edges.push("leading");
@@ -466,10 +488,10 @@ function useDebounce(callback, wait, options = {}) {
466
488
  }
467
489
  return _edges;
468
490
  }, [leading, trailing]);
469
- const debounced = (0, import_react15.useMemo)(() => {
491
+ const debounced = (0, import_react16.useMemo)(() => {
470
492
  return debounce(preservedCallback, wait, { edges });
471
493
  }, [preservedCallback, wait, edges]);
472
- (0, import_react14.useEffect)(() => {
494
+ (0, import_react15.useEffect)(() => {
473
495
  return () => {
474
496
  debounced.cancel();
475
497
  };
@@ -478,21 +500,21 @@ function useDebounce(callback, wait, options = {}) {
478
500
  }
479
501
 
480
502
  // src/hooks/useDoubleClick/useDoubleClick.ts
481
- var import_react16 = require("react");
503
+ var import_react17 = require("react");
482
504
  function useDoubleClick({
483
505
  delay = 250,
484
506
  click,
485
507
  doubleClick
486
508
  }) {
487
- const clickTimeout = (0, import_react16.useRef)(null);
509
+ const clickTimeout = (0, import_react17.useRef)(null);
488
510
  const clearClickTimeout = usePreservedCallback(() => {
489
511
  if (clickTimeout.current != null) {
490
512
  window.clearTimeout(clickTimeout.current);
491
513
  clickTimeout.current = null;
492
514
  }
493
515
  });
494
- (0, import_react16.useEffect)(() => () => clearClickTimeout(), [clearClickTimeout]);
495
- const handleEvent = (0, import_react16.useCallback)(
516
+ (0, import_react17.useEffect)(() => () => clearClickTimeout(), [clearClickTimeout]);
517
+ const handleEvent = (0, import_react17.useCallback)(
496
518
  (event) => {
497
519
  clearClickTimeout();
498
520
  if (click && event.detail === 1) {
@@ -510,7 +532,7 @@ function useDoubleClick({
510
532
  }
511
533
 
512
534
  // src/hooks/useGeolocation/useGeolocation.ts
513
- var import_react17 = require("react");
535
+ var import_react18 = require("react");
514
536
  var CustomGeoLocationError = class extends Error {
515
537
  code;
516
538
  constructor({ code, message }) {
@@ -524,14 +546,14 @@ var GeolocationMountBehavior = {
524
546
  WATCH: "watch"
525
547
  };
526
548
  function useGeolocation(options) {
527
- const [state, setState] = (0, import_react17.useState)({
549
+ const [state, setState] = (0, import_react18.useState)({
528
550
  loading: !!options?.mountBehavior,
529
551
  error: null,
530
552
  data: null
531
553
  });
532
- const [isTracking, setIsTracking] = (0, import_react17.useState)(false);
533
- const watchIdRef = (0, import_react17.useRef)(null);
534
- const checkGeolocationSupport = (0, import_react17.useCallback)(() => {
554
+ const [isTracking, setIsTracking] = (0, import_react18.useState)(false);
555
+ const watchIdRef = (0, import_react18.useRef)(null);
556
+ const checkGeolocationSupport = (0, import_react18.useCallback)(() => {
535
557
  if (typeof window === "undefined" || navigator.geolocation === void 0) {
536
558
  setState((prev) => ({
537
559
  ...prev,
@@ -545,7 +567,7 @@ function useGeolocation(options) {
545
567
  }
546
568
  return true;
547
569
  }, []);
548
- const handleSuccess = (0, import_react17.useCallback)((position) => {
570
+ const handleSuccess = (0, import_react18.useCallback)((position) => {
549
571
  const { coords } = position;
550
572
  setState((prev) => ({
551
573
  ...prev,
@@ -563,7 +585,7 @@ function useGeolocation(options) {
563
585
  }
564
586
  }));
565
587
  }, []);
566
- const handleError = (0, import_react17.useCallback)((error) => {
588
+ const handleError = (0, import_react18.useCallback)((error) => {
567
589
  const { code, message } = error;
568
590
  setState((prev) => ({
569
591
  ...prev,
@@ -571,7 +593,7 @@ function useGeolocation(options) {
571
593
  error: new CustomGeoLocationError({ code, message })
572
594
  }));
573
595
  }, []);
574
- const getGeolocationOptions = (0, import_react17.useCallback)(
596
+ const getGeolocationOptions = (0, import_react18.useCallback)(
575
597
  () => ({
576
598
  enableHighAccuracy: options?.enableHighAccuracy,
577
599
  maximumAge: options?.maximumAge,
@@ -579,14 +601,14 @@ function useGeolocation(options) {
579
601
  }),
580
602
  [options?.enableHighAccuracy, options?.maximumAge, options?.timeout]
581
603
  );
582
- const getCurrentPosition = (0, import_react17.useCallback)(() => {
604
+ const getCurrentPosition = (0, import_react18.useCallback)(() => {
583
605
  if (!checkGeolocationSupport()) {
584
606
  return;
585
607
  }
586
608
  setState((prev) => ({ ...prev, loading: true }));
587
609
  navigator.geolocation.getCurrentPosition(handleSuccess, handleError, getGeolocationOptions());
588
610
  }, [handleSuccess, handleError, getGeolocationOptions, checkGeolocationSupport]);
589
- const startTracking = (0, import_react17.useCallback)(() => {
611
+ const startTracking = (0, import_react18.useCallback)(() => {
590
612
  if (!checkGeolocationSupport()) {
591
613
  return;
592
614
  }
@@ -603,7 +625,7 @@ function useGeolocation(options) {
603
625
  getGeolocationOptions()
604
626
  );
605
627
  }, [handleSuccess, handleError, getGeolocationOptions, checkGeolocationSupport]);
606
- const stopTracking = (0, import_react17.useCallback)(() => {
628
+ const stopTracking = (0, import_react18.useCallback)(() => {
607
629
  if (watchIdRef.current === null) {
608
630
  return;
609
631
  }
@@ -611,7 +633,7 @@ function useGeolocation(options) {
611
633
  watchIdRef.current = null;
612
634
  setIsTracking(false);
613
635
  }, []);
614
- (0, import_react17.useEffect)(() => {
636
+ (0, import_react18.useEffect)(() => {
615
637
  if (options?.mountBehavior === GeolocationMountBehavior.WATCH) {
616
638
  startTracking();
617
639
  } else if (options?.mountBehavior === GeolocationMountBehavior.GET) {
@@ -634,10 +656,10 @@ function useGeolocation(options) {
634
656
  }
635
657
 
636
658
  // src/hooks/useInputState/useInputState.ts
637
- var import_react18 = require("react");
659
+ var import_react19 = require("react");
638
660
  function useInputState(initialValue = "", transformValue = echo) {
639
- const [value, setValue] = (0, import_react18.useState)(initialValue);
640
- const handleValueChange = (0, import_react18.useCallback)(
661
+ const [value, setValue] = (0, import_react19.useState)(initialValue);
662
+ const handleValueChange = (0, import_react19.useCallback)(
641
663
  ({ target: { value: value2 } }) => {
642
664
  setValue(transformValue(value2));
643
665
  },
@@ -650,18 +672,18 @@ function echo(v) {
650
672
  }
651
673
 
652
674
  // src/hooks/useInterval/useInterval.ts
653
- var import_react19 = require("react");
675
+ var import_react20 = require("react");
654
676
  function useInterval(callback, options) {
655
677
  const delay = typeof options === "number" ? options : options.delay;
656
678
  const immediate = typeof options === "number" ? false : options.immediate;
657
679
  const enabled = typeof options === "number" ? true : options.enabled ?? true;
658
680
  const preservedCallback = usePreservedCallback(callback);
659
- (0, import_react19.useEffect)(() => {
681
+ (0, import_react20.useEffect)(() => {
660
682
  if (immediate === true && enabled) {
661
683
  preservedCallback();
662
684
  }
663
685
  }, [immediate, preservedCallback, enabled]);
664
- (0, import_react19.useEffect)(() => {
686
+ (0, import_react20.useEffect)(() => {
665
687
  if (!enabled) {
666
688
  return;
667
689
  }
@@ -671,16 +693,16 @@ function useInterval(callback, options) {
671
693
  }
672
694
 
673
695
  // src/hooks/useIsomorphicLayoutEffect/useIsomorphicLayoutEffect.ts
674
- var import_react20 = require("react");
696
+ var import_react21 = require("react");
675
697
  var isServer = typeof window === "undefined";
676
- var useIsomorphicLayoutEffect = isServer ? import_react20.useEffect : import_react20.useLayoutEffect;
698
+ var useIsomorphicLayoutEffect = isServer ? import_react21.useEffect : import_react21.useLayoutEffect;
677
699
 
678
700
  // src/hooks/useLoading/useLoading.ts
679
- var import_react21 = require("react");
701
+ var import_react22 = require("react");
680
702
  function useLoading() {
681
- const [loading, setLoading] = (0, import_react21.useState)(false);
703
+ const [loading, setLoading] = (0, import_react22.useState)(false);
682
704
  const ref = useIsMountedRef();
683
- const startTransition = (0, import_react21.useCallback)(
705
+ const startTransition = (0, import_react22.useCallback)(
684
706
  async (promise) => {
685
707
  try {
686
708
  setLoading(true);
@@ -694,11 +716,11 @@ function useLoading() {
694
716
  },
695
717
  [ref.isMounted]
696
718
  );
697
- return (0, import_react21.useMemo)(() => [loading, startTransition], [loading, startTransition]);
719
+ return (0, import_react22.useMemo)(() => [loading, startTransition], [loading, startTransition]);
698
720
  }
699
721
  function useIsMountedRef() {
700
- const ref = (0, import_react21.useRef)({ isMounted: true }).current;
701
- (0, import_react21.useEffect)(() => {
722
+ const ref = (0, import_react22.useRef)({ isMounted: true }).current;
723
+ (0, import_react22.useEffect)(() => {
702
724
  ref.isMounted = true;
703
725
  return () => {
704
726
  ref.isMounted = false;
@@ -708,18 +730,18 @@ function useIsMountedRef() {
708
730
  }
709
731
 
710
732
  // src/hooks/useLongPress/useLongPress.ts
711
- var import_react22 = require("react");
733
+ var import_react23 = require("react");
712
734
  function useLongPress(onLongPress, { delay = 500, moveThreshold, onClick, onLongPressEnd } = {}) {
713
- const timeoutRef = (0, import_react22.useRef)(null);
714
- const isLongPressActiveRef = (0, import_react22.useRef)(false);
715
- const initialPositionRef = (0, import_react22.useRef)({ x: 0, y: 0 });
735
+ const timeoutRef = (0, import_react23.useRef)(null);
736
+ const isLongPressActiveRef = (0, import_react23.useRef)(false);
737
+ const initialPositionRef = (0, import_react23.useRef)({ x: 0, y: 0 });
716
738
  const preservedOnLongPress = usePreservedCallback(onLongPress);
717
739
  const preservedOnClick = usePreservedCallback(onClick || (() => {
718
740
  }));
719
741
  const preservedOnLongPressEnd = usePreservedCallback(onLongPressEnd || (() => {
720
742
  }));
721
743
  const hasThreshold = moveThreshold?.x !== void 0 || moveThreshold?.y !== void 0;
722
- const getClientPosition = (0, import_react22.useCallback)((event) => {
744
+ const getClientPosition = (0, import_react23.useCallback)((event) => {
723
745
  if ("touches" in event.nativeEvent) {
724
746
  const touch = event.nativeEvent.touches[0];
725
747
  return { x: touch.clientX, y: touch.clientY };
@@ -729,7 +751,7 @@ function useLongPress(onLongPress, { delay = 500, moveThreshold, onClick, onLong
729
751
  y: event.nativeEvent.clientY
730
752
  };
731
753
  }, []);
732
- const isMovedBeyondThreshold = (0, import_react22.useCallback)(
754
+ const isMovedBeyondThreshold = (0, import_react23.useCallback)(
733
755
  (event) => {
734
756
  const { x, y } = getClientPosition(event);
735
757
  const deltaX = Math.abs(x - initialPositionRef.current.x);
@@ -738,13 +760,13 @@ function useLongPress(onLongPress, { delay = 500, moveThreshold, onClick, onLong
738
760
  },
739
761
  [getClientPosition, moveThreshold]
740
762
  );
741
- const cancelLongPress = (0, import_react22.useCallback)(() => {
763
+ const cancelLongPress = (0, import_react23.useCallback)(() => {
742
764
  if (timeoutRef.current !== null) {
743
765
  window.clearTimeout(timeoutRef.current);
744
766
  timeoutRef.current = null;
745
767
  }
746
768
  }, []);
747
- const handlePressStart = (0, import_react22.useCallback)(
769
+ const handlePressStart = (0, import_react23.useCallback)(
748
770
  (event) => {
749
771
  cancelLongPress();
750
772
  const position = getClientPosition(event);
@@ -757,7 +779,7 @@ function useLongPress(onLongPress, { delay = 500, moveThreshold, onClick, onLong
757
779
  },
758
780
  [cancelLongPress, delay, getClientPosition, preservedOnLongPress]
759
781
  );
760
- const handlePressEnd = (0, import_react22.useCallback)(
782
+ const handlePressEnd = (0, import_react23.useCallback)(
761
783
  (event) => {
762
784
  if (isLongPressActiveRef.current) {
763
785
  preservedOnLongPressEnd(event);
@@ -769,7 +791,7 @@ function useLongPress(onLongPress, { delay = 500, moveThreshold, onClick, onLong
769
791
  },
770
792
  [cancelLongPress, preservedOnClick, preservedOnLongPressEnd]
771
793
  );
772
- const handlePressMove = (0, import_react22.useCallback)(
794
+ const handlePressMove = (0, import_react23.useCallback)(
773
795
  (event) => {
774
796
  if (timeoutRef.current !== null && isMovedBeyondThreshold(event)) {
775
797
  cancelLongPress();
@@ -788,13 +810,13 @@ function useLongPress(onLongPress, { delay = 500, moveThreshold, onClick, onLong
788
810
  }
789
811
 
790
812
  // src/hooks/useMap/useMap.ts
791
- var import_react24 = require("react");
813
+ var import_react25 = require("react");
792
814
 
793
815
  // src/hooks/usePreservedReference/usePreservedReference.ts
794
- var import_react23 = require("react");
816
+ var import_react24 = require("react");
795
817
  function usePreservedReference(value, areValuesEqual = areDeeplyEqual) {
796
- const ref = (0, import_react23.useRef)(value);
797
- return (0, import_react23.useMemo)(() => {
818
+ const ref = (0, import_react24.useRef)(value);
819
+ return (0, import_react24.useMemo)(() => {
798
820
  if (!areValuesEqual(ref.current, value)) {
799
821
  ref.current = value;
800
822
  }
@@ -807,38 +829,38 @@ function areDeeplyEqual(x, y) {
807
829
 
808
830
  // src/hooks/useMap/useMap.ts
809
831
  function useMap(initialState = /* @__PURE__ */ new Map()) {
810
- const [map, setMap] = (0, import_react24.useState)(() => new Map(initialState));
832
+ const [map, setMap] = (0, import_react25.useState)(() => new Map(initialState));
811
833
  const preservedInitialState = usePreservedReference(initialState);
812
- const set = (0, import_react24.useCallback)((key, value) => {
834
+ const set = (0, import_react25.useCallback)((key, value) => {
813
835
  setMap((prev) => {
814
836
  const nextMap = new Map(prev);
815
837
  nextMap.set(key, value);
816
838
  return nextMap;
817
839
  });
818
840
  }, []);
819
- const setAll = (0, import_react24.useCallback)((entries) => {
841
+ const setAll = (0, import_react25.useCallback)((entries) => {
820
842
  setMap(() => new Map(entries));
821
843
  }, []);
822
- const remove = (0, import_react24.useCallback)((key) => {
844
+ const remove = (0, import_react25.useCallback)((key) => {
823
845
  setMap((prev) => {
824
846
  const nextMap = new Map(prev);
825
847
  nextMap.delete(key);
826
848
  return nextMap;
827
849
  });
828
850
  }, []);
829
- const reset = (0, import_react24.useCallback)(() => {
851
+ const reset = (0, import_react25.useCallback)(() => {
830
852
  setMap(() => new Map(preservedInitialState));
831
853
  }, [preservedInitialState]);
832
- const actions = (0, import_react24.useMemo)(() => {
854
+ const actions = (0, import_react25.useMemo)(() => {
833
855
  return { set, setAll, remove, reset };
834
856
  }, [set, setAll, remove, reset]);
835
857
  return [map, actions];
836
858
  }
837
859
 
838
860
  // src/hooks/useOutsideClickEffect/useOutsideClickEffect.ts
839
- var import_react25 = require("react");
861
+ var import_react26 = require("react");
840
862
  function useOutsideClickEffect(container, callback) {
841
- const containers = (0, import_react25.useRef)([]);
863
+ const containers = (0, import_react26.useRef)([]);
842
864
  const handleDocumentClick = usePreservedCallback(({ target }) => {
843
865
  if (target === null) {
844
866
  return;
@@ -851,10 +873,10 @@ function useOutsideClickEffect(container, callback) {
851
873
  }
852
874
  callback();
853
875
  });
854
- (0, import_react25.useEffect)(() => {
876
+ (0, import_react26.useEffect)(() => {
855
877
  containers.current = [container].flat(1).filter((item) => item != null);
856
878
  }, [container]);
857
- (0, import_react25.useEffect)(() => {
879
+ (0, import_react26.useEffect)(() => {
858
880
  document.addEventListener("click", handleDocumentClick);
859
881
  return () => {
860
882
  document.removeEventListener("click", handleDocumentClick);
@@ -863,12 +885,12 @@ function useOutsideClickEffect(container, callback) {
863
885
  }
864
886
 
865
887
  // src/hooks/usePrevious/usePrevious.ts
866
- var import_react26 = require("react");
888
+ var import_react27 = require("react");
867
889
  var strictEquals = (prev, next) => prev === next;
868
890
  function usePrevious(state, compare = strictEquals) {
869
- const prevRef = (0, import_react26.useRef)(state);
870
- const currentRef = (0, import_react26.useRef)(state);
871
- const isFirstRender = (0, import_react26.useRef)(true);
891
+ const prevRef = (0, import_react27.useRef)(state);
892
+ const currentRef = (0, import_react27.useRef)(state);
893
+ const isFirstRender = (0, import_react27.useRef)(true);
872
894
  if (isFirstRender.current) {
873
895
  isFirstRender.current = false;
874
896
  return prevRef.current;
@@ -881,7 +903,7 @@ function usePrevious(state, compare = strictEquals) {
881
903
  }
882
904
 
883
905
  // src/hooks/useStorageState/useStorageState.ts
884
- var import_react27 = require("react");
906
+ var import_react28 = require("react");
885
907
 
886
908
  // src/hooks/useStorageState/storage.ts
887
909
  var MemoStorage = class {
@@ -993,11 +1015,11 @@ function useStorageState(key, {
993
1015
  ...options
994
1016
  } = {}) {
995
1017
  const serializedDefaultValue = defaultValue;
996
- const cache = (0, import_react27.useRef)({
1018
+ const cache = (0, import_react28.useRef)({
997
1019
  data: null,
998
1020
  parsed: serializedDefaultValue
999
1021
  });
1000
- const getSnapshot = (0, import_react27.useCallback)(() => {
1022
+ const getSnapshot = (0, import_react28.useCallback)(() => {
1001
1023
  const deserializer = "deserializer" in options ? options.deserializer : JSON.parse;
1002
1024
  const data = storage.get(key);
1003
1025
  if (data !== cache.current.data) {
@@ -1010,7 +1032,7 @@ function useStorageState(key, {
1010
1032
  }
1011
1033
  return cache.current.parsed;
1012
1034
  }, [defaultValue, key, storage]);
1013
- const storageState = (0, import_react27.useSyncExternalStore)(
1035
+ const storageState = (0, import_react28.useSyncExternalStore)(
1014
1036
  (onStoreChange) => {
1015
1037
  listeners.add(onStoreChange);
1016
1038
  const handler = (event) => {
@@ -1027,7 +1049,7 @@ function useStorageState(key, {
1027
1049
  () => getSnapshot(),
1028
1050
  () => serializedDefaultValue
1029
1051
  );
1030
- const setStorageState = (0, import_react27.useCallback)(
1052
+ const setStorageState = (0, import_react28.useCallback)(
1031
1053
  (value) => {
1032
1054
  const serializer = "serializer" in options ? options.serializer : JSON.stringify;
1033
1055
  const nextValue = typeof value === "function" ? value(getSnapshot()) : value;
@@ -1040,14 +1062,14 @@ function useStorageState(key, {
1040
1062
  },
1041
1063
  [getSnapshot, key, storage]
1042
1064
  );
1043
- const refreshStorageState = (0, import_react27.useCallback)(() => {
1065
+ const refreshStorageState = (0, import_react28.useCallback)(() => {
1044
1066
  setStorageState(getSnapshot());
1045
1067
  }, [storage, getSnapshot, setStorageState]);
1046
1068
  return ensureSerializable([storageState, setStorageState, refreshStorageState]);
1047
1069
  }
1048
1070
 
1049
1071
  // src/hooks/useThrottle/useThrottle.ts
1050
- var import_react28 = require("react");
1072
+ var import_react29 = require("react");
1051
1073
 
1052
1074
  // src/hooks/useThrottle/throttle.ts
1053
1075
  function throttle(func, throttleMs, { edges = ["leading", "trailing"] } = {}) {
@@ -1072,11 +1094,11 @@ function throttle(func, throttleMs, { edges = ["leading", "trailing"] } = {}) {
1072
1094
  function useThrottle(callback, wait, options) {
1073
1095
  const preservedCallback = usePreservedCallback(callback);
1074
1096
  const preservedOptions = usePreservedReference(options ?? {});
1075
- const throttledCallback = (0, import_react28.useMemo)(
1097
+ const throttledCallback = (0, import_react29.useMemo)(
1076
1098
  () => throttle(preservedCallback, wait, preservedOptions),
1077
1099
  [preservedOptions, preservedCallback, wait]
1078
1100
  );
1079
- (0, import_react28.useEffect)(() => {
1101
+ (0, import_react29.useEffect)(() => {
1080
1102
  return () => {
1081
1103
  throttledCallback.cancel();
1082
1104
  };
@@ -1085,29 +1107,29 @@ function useThrottle(callback, wait, options) {
1085
1107
  }
1086
1108
 
1087
1109
  // src/hooks/useTimeout/useTimeout.ts
1088
- var import_react29 = require("react");
1110
+ var import_react30 = require("react");
1089
1111
  function useTimeout(callback, delay = 0) {
1090
1112
  const preservedCallback = usePreservedCallback(callback);
1091
- (0, import_react29.useEffect)(() => {
1113
+ (0, import_react30.useEffect)(() => {
1092
1114
  const timeoutId = window.setTimeout(preservedCallback, delay);
1093
1115
  return () => window.clearTimeout(timeoutId);
1094
1116
  }, [delay, preservedCallback]);
1095
1117
  }
1096
1118
 
1097
1119
  // src/hooks/useToggle/useToggle.ts
1098
- var import_react30 = require("react");
1120
+ var import_react31 = require("react");
1099
1121
  function useToggle(initialValue = false) {
1100
- return (0, import_react30.useReducer)(toggle, initialValue);
1122
+ return (0, import_react31.useReducer)(toggle, initialValue);
1101
1123
  }
1102
1124
  var toggle = (state) => !state;
1103
1125
 
1104
1126
  // src/utils/buildContext/buildContext.tsx
1105
- var import_react31 = require("react");
1127
+ var import_react32 = require("react");
1106
1128
  var import_jsx_runtime3 = require("react/jsx-runtime");
1107
1129
  function buildContext(contextName, defaultContextValues) {
1108
- const Context = (0, import_react31.createContext)(defaultContextValues ?? void 0);
1130
+ const Context = (0, import_react32.createContext)(defaultContextValues ?? void 0);
1109
1131
  function Provider({ children, ...contextValues }) {
1110
- const value = (0, import_react31.useMemo)(
1132
+ const value = (0, import_react32.useMemo)(
1111
1133
  () => Object.keys(contextValues).length > 0 ? contextValues : null,
1112
1134
  // eslint-disable-next-line react-hooks/exhaustive-deps
1113
1135
  [...Object.values(contextValues)]
@@ -1115,7 +1137,7 @@ function buildContext(contextName, defaultContextValues) {
1115
1137
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Context.Provider, { value, children });
1116
1138
  }
1117
1139
  function useInnerContext() {
1118
- const context = (0, import_react31.useContext)(Context);
1140
+ const context = (0, import_react32.useContext)(Context);
1119
1141
  if (context != null) {
1120
1142
  return context;
1121
1143
  }
@@ -1178,6 +1200,7 @@ function mergeFunction(a, b) {
1178
1200
  useAsyncEffect,
1179
1201
  useBooleanState,
1180
1202
  useCallbackOncePerRender,
1203
+ useConditionalEffect,
1181
1204
  useControlledState,
1182
1205
  useCounter,
1183
1206
  useDebounce,
package/dist/index.d.cts CHANGED
@@ -4,6 +4,7 @@ export { SwitchCase } from './components/SwitchCase/index.cjs';
4
4
  export { useAsyncEffect } from './hooks/useAsyncEffect/index.cjs';
5
5
  export { useBooleanState } from './hooks/useBooleanState/index.cjs';
6
6
  export { useCallbackOncePerRender } from './hooks/useCallbackOncePerRender/index.cjs';
7
+ export { useConditionalEffect } from './hooks/useConditionalEffect/index.cjs';
7
8
  export { useControlledState } from './hooks/useControlledState/index.cjs';
8
9
  export { useCounter } from './hooks/useCounter/index.cjs';
9
10
  export { useDebounce } from './hooks/useDebounce/index.cjs';
@@ -42,6 +42,6 @@ type Props<Tag extends ElementType> = React.ComponentPropsWithoutRef<Tag> & UseI
42
42
  */
43
43
  declare const ImpressionArea: <T extends ElementType = "div">(props: Props<T> & {
44
44
  ref?: Ref<Element<T>>;
45
- }) => React.ReactNode;
45
+ }) => React.ReactElement;
46
46
 
47
47
  export { ImpressionArea };
@@ -0,0 +1,43 @@
1
+ import { DependencyList, EffectCallback } from 'react';
2
+
3
+ /**
4
+ * @description
5
+ * `useConditionalEffect` is a React hook that conditionally executes effects based on a predicate function.
6
+ * This provides more control over when effects run beyond just dependency changes.
7
+ *
8
+ * @param {EffectCallback} effect - The effect callback to run.
9
+ * @param {DependencyList} deps - Dependencies array, similar to useEffect.
10
+ * @param {(prevDeps: T | undefined, currentDeps: T) => boolean} condition - Function that determines if the effect should run based on previous and current deps.
11
+ * - On the initial render, `prevDeps` will be `undefined`. Your `condition` function should handle this case.
12
+ * - If you want your effect to run on the initial render, return `true` when `prevDeps` is `undefined`.
13
+ * - If you don't want your effect to run on the initial render, return `false` when `prevDeps` is `undefined`.
14
+ *
15
+ * @example
16
+ * import { useConditionalEffect } from 'react-simplikit';
17
+ *
18
+ * function Component() {
19
+ * const [count, setCount] = useState(0);
20
+ *
21
+ * // Only run effect when count increases
22
+ * useConditionalEffect(
23
+ * () => {
24
+ * console.log(`Count increased to ${count}`);
25
+ * },
26
+ * [count],
27
+ * (prevDeps, currentDeps) => {
28
+ * // Only run when count is defined and has increased
29
+ * return prevDeps && currentDeps[0] > prevDeps[0];
30
+ * }
31
+ * );
32
+ *
33
+ * return (
34
+ * <button onClick={() => setCount(prev => prev + 1)}>
35
+ * Increment: {count}
36
+ * </button>
37
+ * );
38
+ * }
39
+ *
40
+ */
41
+ declare function useConditionalEffect<T extends DependencyList>(effect: EffectCallback, deps: T, condition: (prevDeps: T | undefined, currentDeps: T) => boolean): void;
42
+
43
+ export { useConditionalEffect };
@@ -0,0 +1,23 @@
1
+ // src/hooks/useConditionalEffect/useConditionalEffect.ts
2
+ import { useCallback, useEffect, useRef } from "react";
3
+ function useConditionalEffect(effect, deps, condition) {
4
+ const prevDepsRef = useRef(void 0);
5
+ const memoizedCondition = useCallback(condition, deps);
6
+ if (deps.length === 0) {
7
+ console.warn(
8
+ "useConditionalEffect received an empty dependency array. This may indicate missing dependencies and could lead to unexpected behavior."
9
+ );
10
+ }
11
+ const shouldRun = memoizedCondition(prevDepsRef.current, deps);
12
+ useEffect(() => {
13
+ if (shouldRun) {
14
+ const cleanup = effect();
15
+ prevDepsRef.current = deps;
16
+ return cleanup;
17
+ }
18
+ prevDepsRef.current = deps;
19
+ }, deps);
20
+ }
21
+ export {
22
+ useConditionalEffect
23
+ };
package/esm/index.d.ts CHANGED
@@ -4,6 +4,7 @@ export { SwitchCase } from './components/SwitchCase/index.js';
4
4
  export { useAsyncEffect } from './hooks/useAsyncEffect/index.js';
5
5
  export { useBooleanState } from './hooks/useBooleanState/index.js';
6
6
  export { useCallbackOncePerRender } from './hooks/useCallbackOncePerRender/index.js';
7
+ export { useConditionalEffect } from './hooks/useConditionalEffect/index.js';
7
8
  export { useControlledState } from './hooks/useControlledState/index.js';
8
9
  export { useCounter } from './hooks/useCounter/index.js';
9
10
  export { useDebounce } from './hooks/useDebounce/index.js';
package/esm/index.js CHANGED
@@ -323,8 +323,29 @@ function useCallbackOncePerRender(callback, deps) {
323
323
  });
324
324
  }
325
325
 
326
+ // src/hooks/useConditionalEffect/useConditionalEffect.ts
327
+ import { useCallback as useCallback6, useEffect as useEffect6, useRef as useRef6 } from "react";
328
+ function useConditionalEffect(effect, deps, condition) {
329
+ const prevDepsRef = useRef6(void 0);
330
+ const memoizedCondition = useCallback6(condition, deps);
331
+ if (deps.length === 0) {
332
+ console.warn(
333
+ "useConditionalEffect received an empty dependency array. This may indicate missing dependencies and could lead to unexpected behavior."
334
+ );
335
+ }
336
+ const shouldRun = memoizedCondition(prevDepsRef.current, deps);
337
+ useEffect6(() => {
338
+ if (shouldRun) {
339
+ const cleanup = effect();
340
+ prevDepsRef.current = deps;
341
+ return cleanup;
342
+ }
343
+ prevDepsRef.current = deps;
344
+ }, deps);
345
+ }
346
+
326
347
  // src/hooks/useControlledState/useControlledState.ts
327
- import { useCallback as useCallback6, useState as useState2 } from "react";
348
+ import { useCallback as useCallback7, useState as useState2 } from "react";
328
349
  function useControlledState({
329
350
  value: valueProp,
330
351
  defaultValue,
@@ -334,7 +355,7 @@ function useControlledState({
334
355
  const [uncontrolledState, setUncontrolledState] = useState2(defaultValue);
335
356
  const controlled = valueProp !== void 0;
336
357
  const value = controlled ? valueProp : uncontrolledState;
337
- const setValue = useCallback6(
358
+ const setValue = useCallback7(
338
359
  (next) => {
339
360
  const nextValue = isSetStateAction(next) ? next(value) : next;
340
361
  if (equalityFn(value, nextValue) === true) return;
@@ -351,7 +372,7 @@ function isSetStateAction(next) {
351
372
  }
352
373
 
353
374
  // src/hooks/useCounter/useCounter.ts
354
- import { useCallback as useCallback7, useState as useState3 } from "react";
375
+ import { useCallback as useCallback8, useState as useState3 } from "react";
355
376
  function useCounter(initialValue = 0, { min, max, step = 1 } = {}) {
356
377
  const validateValue = (value) => {
357
378
  let validatedValue = value;
@@ -364,8 +385,8 @@ function useCounter(initialValue = 0, { min, max, step = 1 } = {}) {
364
385
  return validatedValue;
365
386
  };
366
387
  const [count, setCountState] = useState3(() => validateValue(initialValue));
367
- const validateValueMemoized = useCallback7(validateValue, [min, max]);
368
- const setCount = useCallback7(
388
+ const validateValueMemoized = useCallback8(validateValue, [min, max]);
389
+ const setCount = useCallback8(
369
390
  (value) => {
370
391
  setCountState((prev) => {
371
392
  const nextValue = typeof value === "function" ? value(prev) : value;
@@ -374,13 +395,13 @@ function useCounter(initialValue = 0, { min, max, step = 1 } = {}) {
374
395
  },
375
396
  [validateValueMemoized]
376
397
  );
377
- const increment = useCallback7(() => {
398
+ const increment = useCallback8(() => {
378
399
  setCount((prev) => prev + step);
379
400
  }, [setCount, step]);
380
- const decrement = useCallback7(() => {
401
+ const decrement = useCallback8(() => {
381
402
  setCount((prev) => prev - step);
382
403
  }, [setCount, step]);
383
- const reset = useCallback7(() => {
404
+ const reset = useCallback8(() => {
384
405
  setCount(initialValue);
385
406
  }, [setCount, initialValue]);
386
407
  return {
@@ -393,7 +414,7 @@ function useCounter(initialValue = 0, { min, max, step = 1 } = {}) {
393
414
  }
394
415
 
395
416
  // src/hooks/useDebounce/useDebounce.ts
396
- import { useEffect as useEffect6 } from "react";
417
+ import { useEffect as useEffect7 } from "react";
397
418
  import { useMemo as useMemo3 } from "react";
398
419
  function useDebounce(callback, wait, options = {}) {
399
420
  const preservedCallback = usePreservedCallback(callback);
@@ -411,7 +432,7 @@ function useDebounce(callback, wait, options = {}) {
411
432
  const debounced = useMemo3(() => {
412
433
  return debounce(preservedCallback, wait, { edges });
413
434
  }, [preservedCallback, wait, edges]);
414
- useEffect6(() => {
435
+ useEffect7(() => {
415
436
  return () => {
416
437
  debounced.cancel();
417
438
  };
@@ -420,21 +441,21 @@ function useDebounce(callback, wait, options = {}) {
420
441
  }
421
442
 
422
443
  // src/hooks/useDoubleClick/useDoubleClick.ts
423
- import { useCallback as useCallback8, useEffect as useEffect7, useRef as useRef6 } from "react";
444
+ import { useCallback as useCallback9, useEffect as useEffect8, useRef as useRef7 } from "react";
424
445
  function useDoubleClick({
425
446
  delay = 250,
426
447
  click,
427
448
  doubleClick
428
449
  }) {
429
- const clickTimeout = useRef6(null);
450
+ const clickTimeout = useRef7(null);
430
451
  const clearClickTimeout = usePreservedCallback(() => {
431
452
  if (clickTimeout.current != null) {
432
453
  window.clearTimeout(clickTimeout.current);
433
454
  clickTimeout.current = null;
434
455
  }
435
456
  });
436
- useEffect7(() => () => clearClickTimeout(), [clearClickTimeout]);
437
- const handleEvent = useCallback8(
457
+ useEffect8(() => () => clearClickTimeout(), [clearClickTimeout]);
458
+ const handleEvent = useCallback9(
438
459
  (event) => {
439
460
  clearClickTimeout();
440
461
  if (click && event.detail === 1) {
@@ -452,7 +473,7 @@ function useDoubleClick({
452
473
  }
453
474
 
454
475
  // src/hooks/useGeolocation/useGeolocation.ts
455
- import { useCallback as useCallback9, useEffect as useEffect8, useRef as useRef7, useState as useState4 } from "react";
476
+ import { useCallback as useCallback10, useEffect as useEffect9, useRef as useRef8, useState as useState4 } from "react";
456
477
  var CustomGeoLocationError = class extends Error {
457
478
  code;
458
479
  constructor({ code, message }) {
@@ -472,8 +493,8 @@ function useGeolocation(options) {
472
493
  data: null
473
494
  });
474
495
  const [isTracking, setIsTracking] = useState4(false);
475
- const watchIdRef = useRef7(null);
476
- const checkGeolocationSupport = useCallback9(() => {
496
+ const watchIdRef = useRef8(null);
497
+ const checkGeolocationSupport = useCallback10(() => {
477
498
  if (typeof window === "undefined" || navigator.geolocation === void 0) {
478
499
  setState((prev) => ({
479
500
  ...prev,
@@ -487,7 +508,7 @@ function useGeolocation(options) {
487
508
  }
488
509
  return true;
489
510
  }, []);
490
- const handleSuccess = useCallback9((position) => {
511
+ const handleSuccess = useCallback10((position) => {
491
512
  const { coords } = position;
492
513
  setState((prev) => ({
493
514
  ...prev,
@@ -505,7 +526,7 @@ function useGeolocation(options) {
505
526
  }
506
527
  }));
507
528
  }, []);
508
- const handleError = useCallback9((error) => {
529
+ const handleError = useCallback10((error) => {
509
530
  const { code, message } = error;
510
531
  setState((prev) => ({
511
532
  ...prev,
@@ -513,7 +534,7 @@ function useGeolocation(options) {
513
534
  error: new CustomGeoLocationError({ code, message })
514
535
  }));
515
536
  }, []);
516
- const getGeolocationOptions = useCallback9(
537
+ const getGeolocationOptions = useCallback10(
517
538
  () => ({
518
539
  enableHighAccuracy: options?.enableHighAccuracy,
519
540
  maximumAge: options?.maximumAge,
@@ -521,14 +542,14 @@ function useGeolocation(options) {
521
542
  }),
522
543
  [options?.enableHighAccuracy, options?.maximumAge, options?.timeout]
523
544
  );
524
- const getCurrentPosition = useCallback9(() => {
545
+ const getCurrentPosition = useCallback10(() => {
525
546
  if (!checkGeolocationSupport()) {
526
547
  return;
527
548
  }
528
549
  setState((prev) => ({ ...prev, loading: true }));
529
550
  navigator.geolocation.getCurrentPosition(handleSuccess, handleError, getGeolocationOptions());
530
551
  }, [handleSuccess, handleError, getGeolocationOptions, checkGeolocationSupport]);
531
- const startTracking = useCallback9(() => {
552
+ const startTracking = useCallback10(() => {
532
553
  if (!checkGeolocationSupport()) {
533
554
  return;
534
555
  }
@@ -545,7 +566,7 @@ function useGeolocation(options) {
545
566
  getGeolocationOptions()
546
567
  );
547
568
  }, [handleSuccess, handleError, getGeolocationOptions, checkGeolocationSupport]);
548
- const stopTracking = useCallback9(() => {
569
+ const stopTracking = useCallback10(() => {
549
570
  if (watchIdRef.current === null) {
550
571
  return;
551
572
  }
@@ -553,7 +574,7 @@ function useGeolocation(options) {
553
574
  watchIdRef.current = null;
554
575
  setIsTracking(false);
555
576
  }, []);
556
- useEffect8(() => {
577
+ useEffect9(() => {
557
578
  if (options?.mountBehavior === GeolocationMountBehavior.WATCH) {
558
579
  startTracking();
559
580
  } else if (options?.mountBehavior === GeolocationMountBehavior.GET) {
@@ -576,10 +597,10 @@ function useGeolocation(options) {
576
597
  }
577
598
 
578
599
  // src/hooks/useInputState/useInputState.ts
579
- import { useCallback as useCallback10, useState as useState5 } from "react";
600
+ import { useCallback as useCallback11, useState as useState5 } from "react";
580
601
  function useInputState(initialValue = "", transformValue = echo) {
581
602
  const [value, setValue] = useState5(initialValue);
582
- const handleValueChange = useCallback10(
603
+ const handleValueChange = useCallback11(
583
604
  ({ target: { value: value2 } }) => {
584
605
  setValue(transformValue(value2));
585
606
  },
@@ -592,18 +613,18 @@ function echo(v) {
592
613
  }
593
614
 
594
615
  // src/hooks/useInterval/useInterval.ts
595
- import { useEffect as useEffect9 } from "react";
616
+ import { useEffect as useEffect10 } from "react";
596
617
  function useInterval(callback, options) {
597
618
  const delay = typeof options === "number" ? options : options.delay;
598
619
  const immediate = typeof options === "number" ? false : options.immediate;
599
620
  const enabled = typeof options === "number" ? true : options.enabled ?? true;
600
621
  const preservedCallback = usePreservedCallback(callback);
601
- useEffect9(() => {
622
+ useEffect10(() => {
602
623
  if (immediate === true && enabled) {
603
624
  preservedCallback();
604
625
  }
605
626
  }, [immediate, preservedCallback, enabled]);
606
- useEffect9(() => {
627
+ useEffect10(() => {
607
628
  if (!enabled) {
608
629
  return;
609
630
  }
@@ -613,16 +634,16 @@ function useInterval(callback, options) {
613
634
  }
614
635
 
615
636
  // src/hooks/useIsomorphicLayoutEffect/useIsomorphicLayoutEffect.ts
616
- import { useEffect as useEffect10, useLayoutEffect } from "react";
637
+ import { useEffect as useEffect11, useLayoutEffect } from "react";
617
638
  var isServer = typeof window === "undefined";
618
- var useIsomorphicLayoutEffect = isServer ? useEffect10 : useLayoutEffect;
639
+ var useIsomorphicLayoutEffect = isServer ? useEffect11 : useLayoutEffect;
619
640
 
620
641
  // src/hooks/useLoading/useLoading.ts
621
- import { useCallback as useCallback11, useEffect as useEffect11, useMemo as useMemo4, useRef as useRef8, useState as useState6 } from "react";
642
+ import { useCallback as useCallback12, useEffect as useEffect12, useMemo as useMemo4, useRef as useRef9, useState as useState6 } from "react";
622
643
  function useLoading() {
623
644
  const [loading, setLoading] = useState6(false);
624
645
  const ref = useIsMountedRef();
625
- const startTransition = useCallback11(
646
+ const startTransition = useCallback12(
626
647
  async (promise) => {
627
648
  try {
628
649
  setLoading(true);
@@ -639,8 +660,8 @@ function useLoading() {
639
660
  return useMemo4(() => [loading, startTransition], [loading, startTransition]);
640
661
  }
641
662
  function useIsMountedRef() {
642
- const ref = useRef8({ isMounted: true }).current;
643
- useEffect11(() => {
663
+ const ref = useRef9({ isMounted: true }).current;
664
+ useEffect12(() => {
644
665
  ref.isMounted = true;
645
666
  return () => {
646
667
  ref.isMounted = false;
@@ -650,18 +671,18 @@ function useIsMountedRef() {
650
671
  }
651
672
 
652
673
  // src/hooks/useLongPress/useLongPress.ts
653
- import { useCallback as useCallback12, useRef as useRef9 } from "react";
674
+ import { useCallback as useCallback13, useRef as useRef10 } from "react";
654
675
  function useLongPress(onLongPress, { delay = 500, moveThreshold, onClick, onLongPressEnd } = {}) {
655
- const timeoutRef = useRef9(null);
656
- const isLongPressActiveRef = useRef9(false);
657
- const initialPositionRef = useRef9({ x: 0, y: 0 });
676
+ const timeoutRef = useRef10(null);
677
+ const isLongPressActiveRef = useRef10(false);
678
+ const initialPositionRef = useRef10({ x: 0, y: 0 });
658
679
  const preservedOnLongPress = usePreservedCallback(onLongPress);
659
680
  const preservedOnClick = usePreservedCallback(onClick || (() => {
660
681
  }));
661
682
  const preservedOnLongPressEnd = usePreservedCallback(onLongPressEnd || (() => {
662
683
  }));
663
684
  const hasThreshold = moveThreshold?.x !== void 0 || moveThreshold?.y !== void 0;
664
- const getClientPosition = useCallback12((event) => {
685
+ const getClientPosition = useCallback13((event) => {
665
686
  if ("touches" in event.nativeEvent) {
666
687
  const touch = event.nativeEvent.touches[0];
667
688
  return { x: touch.clientX, y: touch.clientY };
@@ -671,7 +692,7 @@ function useLongPress(onLongPress, { delay = 500, moveThreshold, onClick, onLong
671
692
  y: event.nativeEvent.clientY
672
693
  };
673
694
  }, []);
674
- const isMovedBeyondThreshold = useCallback12(
695
+ const isMovedBeyondThreshold = useCallback13(
675
696
  (event) => {
676
697
  const { x, y } = getClientPosition(event);
677
698
  const deltaX = Math.abs(x - initialPositionRef.current.x);
@@ -680,13 +701,13 @@ function useLongPress(onLongPress, { delay = 500, moveThreshold, onClick, onLong
680
701
  },
681
702
  [getClientPosition, moveThreshold]
682
703
  );
683
- const cancelLongPress = useCallback12(() => {
704
+ const cancelLongPress = useCallback13(() => {
684
705
  if (timeoutRef.current !== null) {
685
706
  window.clearTimeout(timeoutRef.current);
686
707
  timeoutRef.current = null;
687
708
  }
688
709
  }, []);
689
- const handlePressStart = useCallback12(
710
+ const handlePressStart = useCallback13(
690
711
  (event) => {
691
712
  cancelLongPress();
692
713
  const position = getClientPosition(event);
@@ -699,7 +720,7 @@ function useLongPress(onLongPress, { delay = 500, moveThreshold, onClick, onLong
699
720
  },
700
721
  [cancelLongPress, delay, getClientPosition, preservedOnLongPress]
701
722
  );
702
- const handlePressEnd = useCallback12(
723
+ const handlePressEnd = useCallback13(
703
724
  (event) => {
704
725
  if (isLongPressActiveRef.current) {
705
726
  preservedOnLongPressEnd(event);
@@ -711,7 +732,7 @@ function useLongPress(onLongPress, { delay = 500, moveThreshold, onClick, onLong
711
732
  },
712
733
  [cancelLongPress, preservedOnClick, preservedOnLongPressEnd]
713
734
  );
714
- const handlePressMove = useCallback12(
735
+ const handlePressMove = useCallback13(
715
736
  (event) => {
716
737
  if (timeoutRef.current !== null && isMovedBeyondThreshold(event)) {
717
738
  cancelLongPress();
@@ -730,12 +751,12 @@ function useLongPress(onLongPress, { delay = 500, moveThreshold, onClick, onLong
730
751
  }
731
752
 
732
753
  // src/hooks/useMap/useMap.ts
733
- import { useCallback as useCallback13, useMemo as useMemo6, useState as useState7 } from "react";
754
+ import { useCallback as useCallback14, useMemo as useMemo6, useState as useState7 } from "react";
734
755
 
735
756
  // src/hooks/usePreservedReference/usePreservedReference.ts
736
- import { useMemo as useMemo5, useRef as useRef10 } from "react";
757
+ import { useMemo as useMemo5, useRef as useRef11 } from "react";
737
758
  function usePreservedReference(value, areValuesEqual = areDeeplyEqual) {
738
- const ref = useRef10(value);
759
+ const ref = useRef11(value);
739
760
  return useMemo5(() => {
740
761
  if (!areValuesEqual(ref.current, value)) {
741
762
  ref.current = value;
@@ -751,24 +772,24 @@ function areDeeplyEqual(x, y) {
751
772
  function useMap(initialState = /* @__PURE__ */ new Map()) {
752
773
  const [map, setMap] = useState7(() => new Map(initialState));
753
774
  const preservedInitialState = usePreservedReference(initialState);
754
- const set = useCallback13((key, value) => {
775
+ const set = useCallback14((key, value) => {
755
776
  setMap((prev) => {
756
777
  const nextMap = new Map(prev);
757
778
  nextMap.set(key, value);
758
779
  return nextMap;
759
780
  });
760
781
  }, []);
761
- const setAll = useCallback13((entries) => {
782
+ const setAll = useCallback14((entries) => {
762
783
  setMap(() => new Map(entries));
763
784
  }, []);
764
- const remove = useCallback13((key) => {
785
+ const remove = useCallback14((key) => {
765
786
  setMap((prev) => {
766
787
  const nextMap = new Map(prev);
767
788
  nextMap.delete(key);
768
789
  return nextMap;
769
790
  });
770
791
  }, []);
771
- const reset = useCallback13(() => {
792
+ const reset = useCallback14(() => {
772
793
  setMap(() => new Map(preservedInitialState));
773
794
  }, [preservedInitialState]);
774
795
  const actions = useMemo6(() => {
@@ -778,9 +799,9 @@ function useMap(initialState = /* @__PURE__ */ new Map()) {
778
799
  }
779
800
 
780
801
  // src/hooks/useOutsideClickEffect/useOutsideClickEffect.ts
781
- import { useEffect as useEffect12, useRef as useRef11 } from "react";
802
+ import { useEffect as useEffect13, useRef as useRef12 } from "react";
782
803
  function useOutsideClickEffect(container, callback) {
783
- const containers = useRef11([]);
804
+ const containers = useRef12([]);
784
805
  const handleDocumentClick = usePreservedCallback(({ target }) => {
785
806
  if (target === null) {
786
807
  return;
@@ -793,10 +814,10 @@ function useOutsideClickEffect(container, callback) {
793
814
  }
794
815
  callback();
795
816
  });
796
- useEffect12(() => {
817
+ useEffect13(() => {
797
818
  containers.current = [container].flat(1).filter((item) => item != null);
798
819
  }, [container]);
799
- useEffect12(() => {
820
+ useEffect13(() => {
800
821
  document.addEventListener("click", handleDocumentClick);
801
822
  return () => {
802
823
  document.removeEventListener("click", handleDocumentClick);
@@ -805,12 +826,12 @@ function useOutsideClickEffect(container, callback) {
805
826
  }
806
827
 
807
828
  // src/hooks/usePrevious/usePrevious.ts
808
- import { useRef as useRef12 } from "react";
829
+ import { useRef as useRef13 } from "react";
809
830
  var strictEquals = (prev, next) => prev === next;
810
831
  function usePrevious(state, compare = strictEquals) {
811
- const prevRef = useRef12(state);
812
- const currentRef = useRef12(state);
813
- const isFirstRender = useRef12(true);
832
+ const prevRef = useRef13(state);
833
+ const currentRef = useRef13(state);
834
+ const isFirstRender = useRef13(true);
814
835
  if (isFirstRender.current) {
815
836
  isFirstRender.current = false;
816
837
  return prevRef.current;
@@ -823,7 +844,7 @@ function usePrevious(state, compare = strictEquals) {
823
844
  }
824
845
 
825
846
  // src/hooks/useStorageState/useStorageState.ts
826
- import { useCallback as useCallback14, useRef as useRef13, useSyncExternalStore } from "react";
847
+ import { useCallback as useCallback15, useRef as useRef14, useSyncExternalStore } from "react";
827
848
 
828
849
  // src/hooks/useStorageState/storage.ts
829
850
  var MemoStorage = class {
@@ -935,11 +956,11 @@ function useStorageState(key, {
935
956
  ...options
936
957
  } = {}) {
937
958
  const serializedDefaultValue = defaultValue;
938
- const cache = useRef13({
959
+ const cache = useRef14({
939
960
  data: null,
940
961
  parsed: serializedDefaultValue
941
962
  });
942
- const getSnapshot = useCallback14(() => {
963
+ const getSnapshot = useCallback15(() => {
943
964
  const deserializer = "deserializer" in options ? options.deserializer : JSON.parse;
944
965
  const data = storage.get(key);
945
966
  if (data !== cache.current.data) {
@@ -969,7 +990,7 @@ function useStorageState(key, {
969
990
  () => getSnapshot(),
970
991
  () => serializedDefaultValue
971
992
  );
972
- const setStorageState = useCallback14(
993
+ const setStorageState = useCallback15(
973
994
  (value) => {
974
995
  const serializer = "serializer" in options ? options.serializer : JSON.stringify;
975
996
  const nextValue = typeof value === "function" ? value(getSnapshot()) : value;
@@ -982,14 +1003,14 @@ function useStorageState(key, {
982
1003
  },
983
1004
  [getSnapshot, key, storage]
984
1005
  );
985
- const refreshStorageState = useCallback14(() => {
1006
+ const refreshStorageState = useCallback15(() => {
986
1007
  setStorageState(getSnapshot());
987
1008
  }, [storage, getSnapshot, setStorageState]);
988
1009
  return ensureSerializable([storageState, setStorageState, refreshStorageState]);
989
1010
  }
990
1011
 
991
1012
  // src/hooks/useThrottle/useThrottle.ts
992
- import { useEffect as useEffect13, useMemo as useMemo7 } from "react";
1013
+ import { useEffect as useEffect14, useMemo as useMemo7 } from "react";
993
1014
 
994
1015
  // src/hooks/useThrottle/throttle.ts
995
1016
  function throttle(func, throttleMs, { edges = ["leading", "trailing"] } = {}) {
@@ -1018,7 +1039,7 @@ function useThrottle(callback, wait, options) {
1018
1039
  () => throttle(preservedCallback, wait, preservedOptions),
1019
1040
  [preservedOptions, preservedCallback, wait]
1020
1041
  );
1021
- useEffect13(() => {
1042
+ useEffect14(() => {
1022
1043
  return () => {
1023
1044
  throttledCallback.cancel();
1024
1045
  };
@@ -1027,10 +1048,10 @@ function useThrottle(callback, wait, options) {
1027
1048
  }
1028
1049
 
1029
1050
  // src/hooks/useTimeout/useTimeout.ts
1030
- import { useEffect as useEffect14 } from "react";
1051
+ import { useEffect as useEffect15 } from "react";
1031
1052
  function useTimeout(callback, delay = 0) {
1032
1053
  const preservedCallback = usePreservedCallback(callback);
1033
- useEffect14(() => {
1054
+ useEffect15(() => {
1034
1055
  const timeoutId = window.setTimeout(preservedCallback, delay);
1035
1056
  return () => window.clearTimeout(timeoutId);
1036
1057
  }, [delay, preservedCallback]);
@@ -1119,6 +1140,7 @@ export {
1119
1140
  useAsyncEffect,
1120
1141
  useBooleanState,
1121
1142
  useCallbackOncePerRender,
1143
+ useConditionalEffect,
1122
1144
  useControlledState,
1123
1145
  useCounter,
1124
1146
  useDebounce,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-simplikit",
3
- "version": "0.0.38",
3
+ "version": "0.0.40",
4
4
  "main": "./dist/index.cjs",
5
5
  "type": "module",
6
6
  "sideEffects": false,