{"version":3,"file":"hooks.mjs","names":[],"sources":["../../src/dashboard/hooks.ts"],"sourcesContent":["'use client';\n\nimport type { Dispatch, SetStateAction } from 'react';\nimport { useCallback, useEffect, useMemo, useState, useSyncExternalStore } from 'react';\n\nexport function useMediaQuery(query: string) {\n  const list = useMemo(\n    () => (typeof window === 'undefined' ? null : window.matchMedia(query)),\n    [query],\n  );\n\n  const subscribe = useCallback(\n    (listener: () => void) => {\n      if (!list) return () => {};\n      list.addEventListener('change', listener);\n      return () => list.removeEventListener('change', listener);\n    },\n    [list],\n  );\n\n  return useSyncExternalStore(\n    subscribe,\n    () => list?.matches ?? false,\n    () => false,\n  );\n}\n\n/** Phone-width layouts. Matches `responsive.mobile` (max-width 575px). */\nexport function useIsMobile() {\n  return useMediaQuery('(max-width: 575px)');\n}\n\n/**\n * Tablet and below. Matches `responsive.laptop` (max-width 991px), which is\n * the width where a fixed console sidebar becomes a drawer.\n */\nexport function useIsCompact() {\n  return useMediaQuery('(max-width: 991px)');\n}\n\nexport function usePrefersReducedMotion() {\n  return useMediaQuery('(prefers-reduced-motion: reduce)');\n}\n\n/**\n * Reads storage after mount so the first render matches the server.\n * Omit `key` to keep the value in memory only.\n */\nexport function useLocalStorage<T>(key: string | undefined, defaultValue: T) {\n  const [value, setValue] = useState<T>(defaultValue);\n\n  useEffect(() => {\n    if (!key) return;\n    try {\n      const raw = window.localStorage.getItem(key);\n      if (raw !== null) setValue(JSON.parse(raw) as T);\n    } catch {\n      // Ignore unreadable storage and keep the default.\n    }\n  }, [key]);\n\n  const setStoredValue = useCallback<Dispatch<SetStateAction<T>>>(\n    (next) => {\n      setValue((current) => {\n        const resolved = typeof next === 'function' ? (next as (value: T) => T)(current) : next;\n        if (key) {\n          try {\n            window.localStorage.setItem(key, JSON.stringify(resolved));\n          } catch {\n            // Ignore quota and private-mode failures.\n          }\n        }\n        return resolved;\n      });\n    },\n    [key],\n  );\n\n  return [value, setStoredValue] as const;\n}\n"],"mappings":";;;AAKA,SAAgB,cAAc,OAAe;CAC3C,MAAM,OAAO,cACJ,OAAO,WAAW,cAAc,OAAO,OAAO,WAAW,KAAK,GACrE,CAAC,KAAK,CACR;CAEA,MAAM,YAAY,aACf,aAAyB;EACxB,IAAI,CAAC,MAAM,aAAa,CAAC;EACzB,KAAK,iBAAiB,UAAU,QAAQ;EACxC,aAAa,KAAK,oBAAoB,UAAU,QAAQ;CAC1D,GACA,CAAC,IAAI,CACP;CAEA,OAAO,qBACL,iBACM,MAAM,WAAW,aACjB,KACR;AACF;;;;;AAWA,SAAgB,eAAe;CAC7B,OAAO,cAAc,oBAAoB;AAC3C;AAEA,SAAgB,0BAA0B;CACxC,OAAO,cAAc,kCAAkC;AACzD;;;;;AAMA,SAAgB,gBAAmB,KAAyB,cAAiB;CAC3E,MAAM,CAAC,OAAO,YAAY,SAAY,YAAY;CAElD,gBAAgB;EACd,IAAI,CAAC,KAAK;EACV,IAAI;GACF,MAAM,MAAM,OAAO,aAAa,QAAQ,GAAG;GAC3C,IAAI,QAAQ,MAAM,SAAS,KAAK,MAAM,GAAG,CAAM;EACjD,QAAQ,CAER;CACF,GAAG,CAAC,GAAG,CAAC;CAmBR,OAAO,CAAC,OAjBe,aACpB,SAAS;EACR,UAAU,YAAY;GACpB,MAAM,WAAW,OAAO,SAAS,aAAc,KAAyB,OAAO,IAAI;GACnF,IAAI,KACF,IAAI;IACF,OAAO,aAAa,QAAQ,KAAK,KAAK,UAAU,QAAQ,CAAC;GAC3D,QAAQ,CAER;GAEF,OAAO;EACT,CAAC;CACH,GACA,CAAC,GAAG,CAGsB,CAAC;AAC/B"}