{"version":3,"file":"useWebcam.mjs","names":[],"sources":["../../../../../src/components/Webcam/hooks/useWebcam.ts"],"sourcesContent":["import type { HookTarget, StateRef, UseMediaStreamOptions } from '@siberiacancode/reactuse';\nimport type { MediaTrackConstraintsOptions } from '@webcam/core';\n\nimport {\n  isTarget,\n  useDidUpdate,\n  useMediaStream,\n  useMount,\n  useRefState,\n  useUnmount\n} from '@siberiacancode/reactuse';\nimport { getMediaStreamConstraints } from '@webcam/core';\nimport { useEffect } from 'react';\n\nexport interface UseWebcamParams extends MediaTrackConstraintsOptions {\n  audioConstraints?: MediaTrackConstraints;\n  requestTimeLimit?: number;\n  stream?: MediaStream;\n  videoConstraints?: MediaTrackConstraints;\n  onError?: (error: Error) => void;\n  onRequest?: () => void;\n  onStart?: (stream: MediaStream) => void;\n  onStop?: (stream?: MediaStream) => void;\n}\n\nexport interface UseWebcamReturn {\n  stream?: MediaStream;\n  apply: (constraints: MediaStreamConstraints) => Promise<boolean>;\n  start: (constraints?: MediaStreamConstraints) => Promise<MediaStream | undefined>;\n  stop: () => void;\n}\n\nexport interface UseWebcam {\n  (target: HookTarget, params?: UseWebcamParams): UseWebcamReturn;\n\n  (params?: UseWebcamParams): UseWebcamReturn & {\n    ref: StateRef<HTMLVideoElement>;\n  };\n}\n\n/**\n * @name useWebcam\n * @description - Hook that manages a webcam media stream for a video element\n *\n * @overload\n * @param {HookTarget} target The target video element the stream will be attached to\n * @param {UseWebcamParams} [params] The webcam parameters\n * @returns {UseWebcamReturn} An object containing the stream and controls\n *\n * @overload\n * @param {UseWebcamParams} [params] The webcam parameters\n * @returns {UseWebcamReturn & { ref: StateRef<HTMLVideoElement> }} An object containing the stream, controls and ref\n */\nexport const useWebcam = ((...params: any[]) => {\n  const target = (isTarget(params[0]) ? params[0] : undefined) as HookTarget | undefined;\n  const options = ((target ? params[1] : params[0]) as UseWebcamParams) ?? {};\n\n  const {\n    stream: externalStream,\n    videoConstraints,\n    audioConstraints,\n    cameraResolutionMode,\n    cameraResolutionType,\n    frontCamera,\n    mainCamera,\n    muted,\n    onRequest,\n    onError,\n    onStart,\n    onStop\n  } = options;\n\n  const internalRef = useRefState<HTMLVideoElement>();\n  const resolvedRef = (target ?? internalRef) as HookTarget;\n\n  const mediaStream = useMediaStream(resolvedRef, {\n    immediately: false,\n    onStart,\n    onStop,\n    onError\n  } satisfies UseMediaStreamOptions);\n\n  const createConstraints = () =>\n    getMediaStreamConstraints({\n      constraints: {\n        video: videoConstraints,\n        audio: audioConstraints\n      },\n      options: {\n        cameraResolutionMode,\n        cameraResolutionType,\n        frontCamera,\n        mainCamera,\n        muted\n      }\n    });\n\n  useMount(() => {\n    if (externalStream) return;\n    const run = async () => {\n      onRequest?.();\n      const constraints = await createConstraints();\n      mediaStream.start(constraints);\n    };\n\n    run();\n  });\n\n  useDidUpdate(() => {\n    if (externalStream) return;\n\n    const run = async () => {\n      onRequest?.();\n      const constraints = await createConstraints();\n\n      if (mediaStream.stream) {\n        const ok = await mediaStream.apply(constraints);\n        if (!ok) mediaStream.start(constraints);\n        return;\n      }\n\n      mediaStream.start(constraints);\n    };\n\n    run();\n  }, [\n    videoConstraints,\n    audioConstraints,\n    cameraResolutionMode,\n    cameraResolutionType,\n    frontCamera,\n    mainCamera,\n    muted\n  ]);\n\n  useEffect(() => {\n    if (!externalStream) return;\n\n    const element = isTarget.getElement(resolvedRef) as HTMLVideoElement | null;\n    if (!element) return;\n\n    element.srcObject = externalStream;\n    onStart?.(externalStream);\n\n    return () => {\n      onStop?.(externalStream);\n    };\n  }, [externalStream, target && isTarget.getRawElement(target), internalRef.state]);\n\n  useUnmount(() => {\n    if (externalStream) return;\n    mediaStream.stop();\n  });\n\n  if (target)\n    return {\n      stream: externalStream ?? mediaStream.stream,\n      start: mediaStream.start,\n      apply: mediaStream.apply,\n      stop: mediaStream.stop\n    };\n  return {\n    stream: externalStream ?? mediaStream.stream,\n    start: mediaStream.start,\n    apply: mediaStream.apply,\n    stop: mediaStream.stop,\n    ref: internalRef\n  };\n}) as UseWebcam;\n"],"mappings":";;;;AAqDA,IAAa,MAAc,GAAG,MAAkB;CAC9C,IAAM,IAAU,EAAS,EAAO,EAAE,IAAI,EAAO,KAAK,KAAA,GAG5C,EACJ,QAAQ,GACR,qBACA,qBACA,yBACA,yBACA,gBACA,eACA,UACA,cACA,YACA,YACA,eAdgB,IAAS,EAAO,KAAK,EAAO,OAA2B,CAAC,GAiBpE,IAAc,EAA8B,GAC5C,IAAe,KAAU,GAEzB,IAAc,EAAe,GAAa;EAC9C,aAAa;EACb;EACA;EACA;CACF,CAAiC,GAE3B,UACJ,EAA0B;EACxB,aAAa;GACX,OAAO;GACP,OAAO;EACT;EACA,SAAS;GACP;GACA;GACA;GACA;GACA;EACF;CACF,CAAC;CAkEH,OAhEA,QAAe;EACT,MAOJ,YANwB;GACtB,IAAY;GACZ,IAAM,IAAc,MAAM,EAAkB;GAC5C,EAAY,MAAM,CAAW;EAC/B,EAEA,CAAI;CACN,CAAC,GAED,QAAmB;EACb,MAeJ,YAbwB;GACtB,IAAY;GACZ,IAAM,IAAc,MAAM,EAAkB;GAE5C,IAAI,EAAY,QAAQ;IAEtB,AAAK,MADY,EAAY,MAAM,CAAW,KACrC,EAAY,MAAM,CAAW;IACtC;GACF;GAEA,EAAY,MAAM,CAAW;EAC/B,EAEA,CAAI;CACN,GAAG;EACD;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CAAC,GAED,QAAgB;EACd,IAAI,CAAC,GAAgB;EAErB,IAAM,IAAU,EAAS,WAAW,CAAW;EAC1C,OAKL,OAHA,EAAQ,YAAY,GACpB,IAAU,CAAc,SAEX;GACX,IAAS,CAAc;EACzB;CACF,GAAG;EAAC;EAAgB,KAAU,EAAS,cAAc,CAAM;EAAG,EAAY;CAAK,CAAC,GAEhF,QAAiB;EACX,KACJ,EAAY,KAAK;CACnB,CAAC,GAEG,IACK;EACL,QAAQ,KAAkB,EAAY;EACtC,OAAO,EAAY;EACnB,OAAO,EAAY;EACnB,MAAM,EAAY;CACpB,IACK;EACL,QAAQ,KAAkB,EAAY;EACtC,OAAO,EAAY;EACnB,OAAO,EAAY;EACnB,MAAM,EAAY;EAClB,KAAK;CACP;AACF"}