{"version":3,"sources":["../../src/use-permission/index.ts"],"sourcesContent":["import { useEffect, useRef } from 'react'\nimport { useEventListener } from '../use-event-listener'\nimport { useLatest } from '../use-latest'\nimport { useStableFn } from '../use-stable-fn'\nimport { useSupported } from '../use-supported'\nimport { useUpdateDeepCompareEffect } from '../use-update-deep-compare-effect'\nimport { createSingletonPromise, isString } from '../utils/basic'\n\nimport type { RefObject } from 'react'\n\ntype DescriptorNamePolyfill =\n  | 'accelerometer'\n  | 'accessibility-events'\n  | 'ambient-light-sensor'\n  | 'background-sync'\n  | 'camera'\n  | 'clipboard-read'\n  | 'clipboard-write'\n  | 'gyroscope'\n  | 'magnetometer'\n  | 'microphone'\n  | 'notifications'\n  | 'payment-handler'\n  | 'persistent-storage'\n  | 'push'\n  | 'speaker'\n\nexport type GeneralPermissionDescriptor = PermissionDescriptor | { name: DescriptorNamePolyfill }\nexport type PermissionDesc = GeneralPermissionDescriptor | GeneralPermissionDescriptor['name'] | false\n\nexport interface UsePermissionOptions<Controls extends boolean> {\n  /**\n   * Expose more controls\n   *\n   * @defaultValue false\n   */\n  controls?: Controls\n  /**\n   * Whether to query immediately\n   *\n   * @defaultValue true\n   */\n  immediate?: boolean\n  /**\n   *\n   */\n  onStateChange?: (state: PermissionState) => void\n}\n\nexport type UsePermissionReturns<Controls extends boolean> = Controls extends true\n  ? {\n      /**\n       * if the permission is supported\n       */\n      isSupported: boolean\n      /**\n       * Query the permission status\n       */\n      stateRef: RefObject<PermissionState | null>\n      /**\n       * Query the permission status\n       */\n      query(): Promise<PermissionStatus | null>\n    }\n  : RefObject<PermissionState | null>\n\n/**\n * A React Hook that helps to query the permission status of a browser feature.\n */\nexport function usePermission(\n  permissionDesc: PermissionDesc,\n  options?: UsePermissionOptions<false>,\n): UsePermissionReturns<false>\nexport function usePermission(\n  permissionDesc: PermissionDesc,\n  options: UsePermissionOptions<true>,\n): UsePermissionReturns<true>\nexport function usePermission(\n  permissionDesc: PermissionDesc,\n  options: UsePermissionOptions<boolean> = {},\n): UsePermissionReturns<boolean> {\n  const { controls: exposeControls = false, immediate = true, onStateChange } = options\n\n  const desc = permissionDesc\n    ? isString(permissionDesc)\n      ? ({ name: permissionDesc } as PermissionDescriptor)\n      : (permissionDesc as PermissionDescriptor)\n    : false\n\n  const isSupported = useSupported(() => 'permissions' in navigator)\n  const permissionStatusRef = useRef<PermissionStatus | null>(null)\n  const stateRef = useRef<PermissionState | null>(null)\n\n  const latest = useLatest({ isSupported, desc: desc as PermissionDescriptor | false })\n\n  const onPermissionStatusChange = useStableFn(() => {\n    const { state } = permissionStatusRef.current || {}\n    const preState = stateRef.current\n    if (state && preState !== state) {\n      stateRef.current = state\n      onStateChange?.(stateRef.current)\n    }\n  })\n\n  const requestPermission = useStableFn(\n    createSingletonPromise(async () => {\n      const { desc } = latest.current\n\n      if (!desc) return null\n\n      if (!permissionStatusRef.current) {\n        try {\n          permissionStatusRef.current = await navigator.permissions.query(desc)\n          onPermissionStatusChange()\n        } catch {\n          stateRef.current = 'prompt'\n          onPermissionStatusChange()\n        }\n      }\n\n      return permissionStatusRef.current\n    }),\n  )\n\n  const query = useStableFn(() => {\n    const { desc, isSupported } = latest.current\n\n    if (!isSupported || !desc) {\n      return Promise.resolve(null)\n    }\n\n    return requestPermission()\n  })\n\n  useEffect(() => {\n    if (isSupported) {\n      immediate && query()\n    }\n  }, [isSupported, immediate])\n\n  // biome-ignore lint/correctness/useExhaustiveDependencies: effect need to re-run when desc changes\n  useUpdateDeepCompareEffect(() => void query(), [desc])\n\n  useEventListener(permissionStatusRef, 'change', onPermissionStatusChange)\n\n  return exposeControls ? { stateRef, isSupported, query } : stateRef\n}\n"],"names":["usePermission","permissionDesc","options","exposeControls","controls","immediate","onStateChange","desc","isString","name","isSupported","useSupported","navigator","permissionStatusRef","useRef","stateRef","latest","useLatest","onPermissionStatusChange","useStableFn","state","current","preState","requestPermission","createSingletonPromise","permissions","query","Promise","resolve","useEffect","useUpdateDeepCompareEffect","useEventListener"],"mappings":";;;;+BA6EgBA;;;eAAAA;;;qBA7EkB;gCACD;yBACP;2BACE;4BACC;0CACc;qBACM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuE1C,SAASA,cACdC,cAA8B;QAC9BC,UAAAA,iEAAyC,CAAC;IAE1C,IAAkBC,MAA4DD,QAAtEE,UAAUD,iBAAAA,iBAAiB,QAAjBA,0BAA4DD,QAApCG,WAAAA,4CAAY,2BAAMC,gBAAkBJ,QAAlBI;IAE5D,IAAMC,OAAON,iBACTO,IAAAA,eAAQ,EAACP,kBACN;QAAEQ,MAAMR;IAAe,IACvBA,iBACH;IAEJ,IAAMS,cAAcC,IAAAA,0BAAY,EAAC;eAAM,iBAAiBC;;IACxD,IAAMC,sBAAsBC,IAAAA,aAAM,EAA0B;IAC5D,IAAMC,WAAWD,IAAAA,aAAM,EAAyB;IAEhD,IAAME,SAASC,IAAAA,oBAAS,EAAC;QAAEP,aAAAA;QAAaH,MAAMA;IAAqC;IAEnF,IAAMW,2BAA2BC,IAAAA,wBAAW,EAAC;QAC3C,IAAM,AAAEC,QAAUP,CAAAA,oBAAoBQ,OAAO,IAAI,CAAC,CAAA,EAA1CD;QACR,IAAME,WAAWP,SAASM,OAAO;QACjC,IAAID,SAASE,aAAaF,OAAO;YAC/BL,SAASM,OAAO,GAAGD;YACnBd,0BAAAA,oCAAAA,cAAgBS,SAASM,OAAO;QAClC;IACF;IAEA,IAAME,oBAAoBJ,IAAAA,wBAAW,EACnCK,IAAAA,6BAAsB,EAAC;;gBACbjB;;;;wBAAAA,OAASS,OAAOK,OAAO,CAAvBd;wBAER,IAAI,CAACA,MAAM;;4BAAO;;6BAEd,CAACM,oBAAoBQ,OAAO,EAA5B;;;;;;;;;;;;wBAE8B;;4BAAMT,UAAUa,WAAW,CAACC,KAAK,CAACnB;;;wBAAhEM,oBAAoBQ,OAAO,GAAG;wBAC9BH;;;;;;;wBAEAH,SAASM,OAAO,GAAG;wBACnBH;;;;;;wBAIJ;;4BAAOL,oBAAoBQ,OAAO;;;;QACpC;;IAGF,IAAMK,QAAQP,IAAAA,wBAAW,EAAC;QACxB,IAA8BH,kBAAAA,OAAOK,OAAO,EAApCd,OAAsBS,gBAAtBT,MAAMG,cAAgBM,gBAAhBN;QAEd,IAAI,CAACA,eAAe,CAACH,MAAM;YACzB,OAAOoB,QAAQC,OAAO,CAAC;QACzB;QAEA,OAAOL;IACT;IAEAM,IAAAA,gBAAS,EAAC;QACR,IAAInB,aAAa;YACfL,aAAaqB;QACf;IACF,GAAG;QAAChB;QAAaL;KAAU;IAE3B,mGAAmG;IACnGyB,IAAAA,sDAA0B,EAAC;eAAM,KAAKJ;OAAS;QAACnB;KAAK;IAErDwB,IAAAA,kCAAgB,EAAClB,qBAAqB,UAAUK;IAEhD,OAAOf,iBAAiB;QAAEY,UAAAA;QAAUL,aAAAA;QAAagB,OAAAA;IAAM,IAAIX;AAC7D"}