"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.useAsync = useAsync;
exports.useAsyncEffect = useAsyncEffect;
exports.useClickOutside = useClickOutside;
exports.useCounter = useCounter;
exports.useDebounce = useDebounce;
exports.useFormValidation = useFormValidation;
exports.useKeyPress = useKeyPress;
exports.useLocalStorage = useLocalStorage;
exports.useMediaQuery = useMediaQuery;
exports.useOnlineStatus = useOnlineStatus;
exports.usePrevious = usePrevious;
exports.useScrollPosition = useScrollPosition;
exports.useSessionStorage = useSessionStorage;
exports.useThrottle = useThrottle;
exports.useToggle = useToggle;
exports.useWindowSize = useWindowSize;
var _react = require("react");
/**
 * React hook utilities for common patterns and state management
 */

/**
 * Hook for managing async operations with loading, error, and data states
 */
function useAsync(asyncFn, deps = []) {
  const [data, setData] = (0, _react.useState)(null);
  const [loading, setLoading] = (0, _react.useState)(false);
  const [error, setError] = (0, _react.useState)(null);
  const execute = (0, _react.useCallback)(async () => {
    setLoading(true);
    setError(null);
    try {
      const result = await asyncFn();
      setData(result);
      return result;
    } catch (err) {
      const error = err instanceof Error ? err : new Error(String(err));
      setError(error);
      throw error;
    } finally {
      setLoading(false);
    }
  }, deps);
  return {
    data,
    loading,
    error,
    execute
  };
}

/**
 * Hook for managing async operations that execute on mount
 */
function useAsyncEffect(asyncFn, deps = []) {
  const [data, setData] = (0, _react.useState)(null);
  const [loading, setLoading] = (0, _react.useState)(true);
  const [error, setError] = (0, _react.useState)(null);
  (0, _react.useEffect)(() => {
    let mounted = true;
    const execute = async () => {
      try {
        const result = await asyncFn();
        if (mounted) {
          setData(result);
          setLoading(false);
        }
      } catch (err) {
        if (mounted) {
          const error = err instanceof Error ? err : new Error(String(err));
          setError(error);
          setLoading(false);
        }
      }
    };
    execute();
    return () => {
      mounted = false;
    };
  }, deps);
  return {
    data,
    loading,
    error
  };
}

/**
 * Hook for debounced values
 */
function useDebounce(value, delay) {
  const [debouncedValue, setDebouncedValue] = (0, _react.useState)(value);
  (0, _react.useEffect)(() => {
    const handler = setTimeout(() => {
      setDebouncedValue(value);
    }, delay);
    return () => {
      clearTimeout(handler);
    };
  }, [value, delay]);
  return debouncedValue;
}

/**
 * Hook for throttled values
 */
function useThrottle(value, delay) {
  const [throttledValue, setThrottledValue] = (0, _react.useState)(value);
  const lastRun = (0, _react.useRef)(Date.now());
  (0, _react.useEffect)(() => {
    const handler = setTimeout(() => {
      if (Date.now() - lastRun.current >= delay) {
        setThrottledValue(value);
        lastRun.current = Date.now();
      }
    }, delay - (Date.now() - lastRun.current));
    return () => {
      clearTimeout(handler);
    };
  }, [value, delay]);
  return throttledValue;
}

/**
 * Hook for previous value
 */
function usePrevious(value) {
  const ref = (0, _react.useRef)(undefined);
  (0, _react.useEffect)(() => {
    ref.current = value;
  });
  return ref.current;
}

/**
 * Hook for boolean state with toggle
 */
function useToggle(initialValue = false) {
  const [value, setValue] = (0, _react.useState)(initialValue);
  const toggle = (0, _react.useCallback)(() => setValue(v => !v), []);
  const setTrue = (0, _react.useCallback)(() => setValue(true), []);
  const setFalse = (0, _react.useCallback)(() => setValue(false), []);
  return {
    value,
    toggle,
    setTrue,
    setFalse,
    setValue
  };
}

/**
 * Hook for counter state
 */
function useCounter(initialValue = 0) {
  const [count, setCount] = (0, _react.useState)(initialValue);
  const increment = (0, _react.useCallback)(() => setCount(c => c + 1), []);
  const decrement = (0, _react.useCallback)(() => setCount(c => c - 1), []);
  const reset = (0, _react.useCallback)(() => setCount(initialValue), [initialValue]);
  const setValue = (0, _react.useCallback)(value => setCount(value), []);
  return {
    count,
    increment,
    decrement,
    reset,
    setValue
  };
}

/**
 * Hook for local storage
 */
function useLocalStorage(key, initialValue) {
  const [storedValue, setStoredValue] = (0, _react.useState)(() => {
    try {
      const item = window.localStorage.getItem(key);
      return item ? JSON.parse(item) : initialValue;
    } catch (error) {
      console.error(`Error reading localStorage key "${key}":`, error);
      return initialValue;
    }
  });
  const setValue = (0, _react.useCallback)(value => {
    try {
      const valueToStore = value instanceof Function ? value(storedValue) : value;
      setStoredValue(valueToStore);
      window.localStorage.setItem(key, JSON.stringify(valueToStore));
    } catch (error) {
      console.error(`Error setting localStorage key "${key}":`, error);
    }
  }, [key, storedValue]);
  return [storedValue, setValue];
}

/**
 * Hook for session storage
 */
function useSessionStorage(key, initialValue) {
  const [storedValue, setStoredValue] = (0, _react.useState)(() => {
    try {
      const item = window.sessionStorage.getItem(key);
      return item ? JSON.parse(item) : initialValue;
    } catch (error) {
      console.error(`Error reading sessionStorage key "${key}":`, error);
      return initialValue;
    }
  });
  const setValue = (0, _react.useCallback)(value => {
    try {
      const valueToStore = value instanceof Function ? value(storedValue) : value;
      setStoredValue(valueToStore);
      window.sessionStorage.setItem(key, JSON.stringify(valueToStore));
    } catch (error) {
      console.error(`Error setting sessionStorage key "${key}":`, error);
    }
  }, [key, storedValue]);
  return [storedValue, setValue];
}

/**
 * Hook for window size
 */
function useWindowSize() {
  const [windowSize, setWindowSize] = (0, _react.useState)({
    width: window.innerWidth,
    height: window.innerHeight
  });
  (0, _react.useEffect)(() => {
    const handleResize = () => {
      setWindowSize({
        width: window.innerWidth,
        height: window.innerHeight
      });
    };
    window.addEventListener('resize', handleResize);
    return () => window.removeEventListener('resize', handleResize);
  }, []);
  return windowSize;
}

/**
 * Hook for scroll position
 */
function useScrollPosition() {
  const [scrollPosition, setScrollPosition] = (0, _react.useState)(0);
  (0, _react.useEffect)(() => {
    const handleScroll = () => {
      setScrollPosition(window.pageYOffset);
    };
    window.addEventListener('scroll', handleScroll);
    return () => window.removeEventListener('scroll', handleScroll);
  }, []);
  return scrollPosition;
}

/**
 * Hook for online/offline status
 */
function useOnlineStatus() {
  const [isOnline, setIsOnline] = (0, _react.useState)(navigator.onLine);
  (0, _react.useEffect)(() => {
    const handleOnline = () => setIsOnline(true);
    const handleOffline = () => setIsOnline(false);
    window.addEventListener('online', handleOnline);
    window.addEventListener('offline', handleOffline);
    return () => {
      window.removeEventListener('online', handleOnline);
      window.removeEventListener('offline', handleOffline);
    };
  }, []);
  return isOnline;
}

/**
 * Hook for media queries
 */
function useMediaQuery(query) {
  const [matches, setMatches] = (0, _react.useState)(false);
  (0, _react.useEffect)(() => {
    const media = window.matchMedia(query);
    if (media.matches !== matches) {
      setMatches(media.matches);
    }
    const listener = () => setMatches(media.matches);
    media.addEventListener('change', listener);
    return () => media.removeEventListener('change', listener);
  }, [matches, query]);
  return matches;
}

/**
 * Hook for keyboard events
 */
function useKeyPress(targetKey) {
  const [keyPressed, setKeyPressed] = (0, _react.useState)(false);
  (0, _react.useEffect)(() => {
    const downHandler = ({
      key
    }) => {
      if (key === targetKey) {
        setKeyPressed(true);
      }
    };
    const upHandler = ({
      key
    }) => {
      if (key === targetKey) {
        setKeyPressed(false);
      }
    };
    window.addEventListener('keydown', downHandler);
    window.addEventListener('keyup', upHandler);
    return () => {
      window.removeEventListener('keydown', downHandler);
      window.removeEventListener('keyup', upHandler);
    };
  }, [targetKey]);
  return keyPressed;
}

/**
 * Hook for click outside detection
 */
function useClickOutside(ref, handler) {
  (0, _react.useEffect)(() => {
    const listener = event => {
      if (!ref.current || ref.current.contains(event.target)) {
        return;
      }
      handler();
    };
    document.addEventListener('mousedown', listener);
    document.addEventListener('touchstart', listener);
    return () => {
      document.removeEventListener('mousedown', listener);
      document.removeEventListener('touchstart', listener);
    };
  }, [ref, handler]);
}

/**
 * Hook for form validation
 */
function useFormValidation(initialValues, validationSchema) {
  const [values, setValues] = (0, _react.useState)(initialValues);
  const [errors, setErrors] = (0, _react.useState)({});
  const [touched, setTouched] = (0, _react.useState)({});
  const validate = (0, _react.useCallback)(valuesToValidate => {
    return validationSchema(valuesToValidate);
  }, [validationSchema]);
  const setValue = (0, _react.useCallback)((field, value) => {
    setValues(prev => ({
      ...prev,
      [field]: value
    }));
    if (touched[field]) {
      const newErrors = validate({
        ...values,
        [field]: value
      });
      setErrors(prev => ({
        ...prev,
        [field]: newErrors[field]
      }));
    }
  }, [values, touched, validate]);
  const setTouchedField = (0, _react.useCallback)(field => {
    setTouched(prev => ({
      ...prev,
      [field]: true
    }));
    const newErrors = validate(values);
    setErrors(prev => ({
      ...prev,
      [field]: newErrors[field]
    }));
  }, [values, validate]);
  const isValid = (0, _react.useMemo)(() => {
    const validationErrors = validate(values);
    return Object.keys(validationErrors).length === 0;
  }, [values, validate]);
  return {
    values,
    errors,
    touched,
    isValid,
    setValue,
    setTouchedField,
    setValues,
    setErrors,
    setTouched
  };
}
//# sourceMappingURL=hookUtils.js.map