{"version":3,"file":"index.mjs","names":[],"sources":["../../../src/hooks/useGeolocation/index.ts"],"sourcesContent":["import { useState, useEffect, useCallback, useRef, useMemo } from 'react';\n\ntype GeolocationData = GeolocationPosition['coords'] & { timestamp: number };\n\ninterface GeolocationState {\n  data: GeolocationData | null;\n  error: GeolocationPositionError | Error | null;\n  loading: boolean;\n  isWatching: boolean;\n}\n\ninterface UseGeolocationOptions extends PositionOptions {\n  mountBehavior?: 'watch' | 'get';\n}\n\ninterface UseGeolocationReturn extends GeolocationState {\n  get: () => void;\n  watch: () => void;\n  stopWatch: () => void;\n}\n\n/**\n * @description 브라우저의 Geolocation API를 활용하여 사용자의 현재 위치 정보를 가져오는 커스텀 훅입니다.\n *\n * 위치 정보를 한 번만 가져오거나(`get`) 실시간으로 추적(`watch`)할 수 있습니다.\n *\n * @param {UseGeolocationOptions} options - Geolocation API 옵션\n * @param {boolean} [options.enableHighAccuracy=false] - 높은 정확도의 위치 정보를 요청할지 여부\n * @param {number} [options.timeout=Infinity] - 위치 정보를 가져오는 데 허용되는 최대 시간 (밀리초)\n * @param {number} [options.maximumAge=0] - 캐시된 위치 정보의 최대 수명 (밀리초)\n * @param {'watch' | 'get'} [options.mountBehavior='get'] - 훅이 마운트될 때 위치 정보를 가져오는 방식\n *\n * @returns {UseGeolocationReturn} 위치 정보 상태 및 제어 함수\n *\n * @example\n * const location = useGeolocation();\n * const { data, error, loading, isWatching, get, watch, stopWatch } = location;\n *\n * @example\n * // 훅이 마운트될 때 위치 정보를 가져오는 방식을 실시간으로 설정\n * const location = useGeolocation({ mountBehavior: 'watch' });\n *\n * @example\n * // 훅이 마운트될 때 위치 정보를 가져오는 방식을 한 번만 설정\n * const location = useGeolocation({ mountBehavior: 'get' });\n */\nexport function useGeolocation(\n  options: UseGeolocationOptions = {}\n): UseGeolocationReturn {\n  const {\n    enableHighAccuracy = false,\n    timeout = Infinity,\n    maximumAge = 0,\n    mountBehavior = 'get',\n  } = options;\n\n  const watchId = useRef<number | null>(null);\n\n  const positionOptions = useMemo(() => {\n    return {\n      enableHighAccuracy,\n      timeout,\n      maximumAge,\n    };\n  }, [enableHighAccuracy, timeout, maximumAge]);\n\n  const [state, setState] = useState<GeolocationState>({\n    data: null,\n    error: null,\n    loading: !!mountBehavior,\n    isWatching: mountBehavior === 'watch',\n  });\n\n  const handleSuccess = useCallback((position: GeolocationPosition) => {\n    setState((prev) => ({\n      ...prev,\n      data: { ...position.coords, timestamp: position.timestamp },\n      error: null,\n      loading: false,\n    }));\n  }, []);\n\n  const handleError = useCallback((error: GeolocationPositionError) => {\n    setState((prev) => ({\n      ...prev,\n      error,\n      loading: false,\n    }));\n  }, []);\n\n  const checkGeolocationSupport = useCallback(() => {\n    if (typeof window === 'undefined' || navigator.geolocation == null) {\n      setState((prev) => ({\n        ...prev,\n        loading: false,\n        error: new Error('Geolocation을 지원하는 환경이 아닙니다.'),\n      }));\n      return false;\n    }\n    return true;\n  }, []);\n\n  const get = useCallback(() => {\n    if (!checkGeolocationSupport()) {\n      return;\n    }\n\n    setState((prev) => ({ ...prev, loading: true }));\n\n    navigator.geolocation.getCurrentPosition(\n      handleSuccess,\n      handleError,\n      positionOptions\n    );\n  }, [checkGeolocationSupport, handleSuccess, handleError, positionOptions]);\n\n  const watch = useCallback(() => {\n    if (!checkGeolocationSupport()) {\n      return;\n    }\n\n    setState((prev) => ({ ...prev, isWatching: true }));\n\n    watchId.current = navigator.geolocation.watchPosition(\n      handleSuccess,\n      handleError,\n      positionOptions\n    );\n  }, [checkGeolocationSupport, handleSuccess, handleError, positionOptions]);\n\n  const stopWatch = useCallback(() => {\n    if (watchId.current != null) {\n      navigator.geolocation.clearWatch(watchId.current);\n      watchId.current = null;\n      setState((prev) => ({ ...prev, isWatching: false }));\n    }\n  }, []);\n\n  useEffect(() => {\n    if (mountBehavior === 'watch') {\n      watch();\n    } else if (mountBehavior === 'get') {\n      get();\n    }\n\n    return stopWatch;\n  }, [mountBehavior, get, watch, stopWatch]);\n\n  return {\n    ...state,\n    get,\n    watch,\n    stopWatch,\n  };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AA8CA,SAAgB,eACd,UAAiC,EAAE,EACb;CACtB,MAAM,EACJ,qBAAqB,OACrB,UAAU,UACV,aAAa,GACb,gBAAgB,UACd;CAEJ,MAAM,UAAU,OAAsB,KAAK;CAE3C,MAAM,kBAAkB,cAAc;EACpC,OAAO;GACL;GACA;GACA;GACD;IACA;EAAC;EAAoB;EAAS;EAAW,CAAC;CAE7C,MAAM,CAAC,OAAO,YAAY,SAA2B;EACnD,MAAM;EACN,OAAO;EACP,SAAS,CAAC,CAAC;EACX,YAAY,kBAAkB;EAC/B,CAAC;CAEF,MAAM,gBAAgB,aAAa,aAAkC;EACnE,UAAU,UAAU;GAClB,GAAG;GACH,MAAM;IAAE,GAAG,SAAS;IAAQ,WAAW,SAAS;IAAW;GAC3D,OAAO;GACP,SAAS;GACV,EAAE;IACF,EAAE,CAAC;CAEN,MAAM,cAAc,aAAa,UAAoC;EACnE,UAAU,UAAU;GAClB,GAAG;GACH;GACA,SAAS;GACV,EAAE;IACF,EAAE,CAAC;CAEN,MAAM,0BAA0B,kBAAkB;EAChD,IAAI,OAAO,WAAW,eAAe,UAAU,eAAe,MAAM;GAClE,UAAU,UAAU;IAClB,GAAG;IACH,SAAS;IACT,uBAAO,IAAI,MAAM,8BAA8B;IAChD,EAAE;GACH,OAAO;;EAET,OAAO;IACN,EAAE,CAAC;CAEN,MAAM,MAAM,kBAAkB;EAC5B,IAAI,CAAC,yBAAyB,EAC5B;EAGF,UAAU,UAAU;GAAE,GAAG;GAAM,SAAS;GAAM,EAAE;EAEhD,UAAU,YAAY,mBACpB,eACA,aACA,gBACD;IACA;EAAC;EAAyB;EAAe;EAAa;EAAgB,CAAC;CAE1E,MAAM,QAAQ,kBAAkB;EAC9B,IAAI,CAAC,yBAAyB,EAC5B;EAGF,UAAU,UAAU;GAAE,GAAG;GAAM,YAAY;GAAM,EAAE;EAEnD,QAAQ,UAAU,UAAU,YAAY,cACtC,eACA,aACA,gBACD;IACA;EAAC;EAAyB;EAAe;EAAa;EAAgB,CAAC;CAE1E,MAAM,YAAY,kBAAkB;EAClC,IAAI,QAAQ,WAAW,MAAM;GAC3B,UAAU,YAAY,WAAW,QAAQ,QAAQ;GACjD,QAAQ,UAAU;GAClB,UAAU,UAAU;IAAE,GAAG;IAAM,YAAY;IAAO,EAAE;;IAErD,EAAE,CAAC;CAEN,gBAAgB;EACd,IAAI,kBAAkB,SACpB,OAAO;OACF,IAAI,kBAAkB,OAC3B,KAAK;EAGP,OAAO;IACN;EAAC;EAAe;EAAK;EAAO;EAAU,CAAC;CAE1C,OAAO;EACL,GAAG;EACH;EACA;EACA;EACD"}