@webcam/react 1.0.1 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/README.md +81 -130
  2. package/dist/cjs/_virtual/_rolldown/runtime.cjs +1 -0
  3. package/dist/cjs/components/Webcam/Webcam.cjs +2 -0
  4. package/dist/cjs/components/Webcam/Webcam.cjs.map +1 -0
  5. package/dist/cjs/components/Webcam/hooks/useWebcam.cjs +2 -0
  6. package/dist/cjs/components/Webcam/hooks/useWebcam.cjs.map +1 -0
  7. package/dist/cjs/index.cjs +1 -0
  8. package/dist/cjs/utils/helpers/animationFrame.cjs +2 -0
  9. package/dist/cjs/utils/helpers/animationFrame.cjs.map +1 -0
  10. package/dist/cjs/utils/hooks/useAnimationFrame.cjs +2 -0
  11. package/dist/cjs/utils/hooks/useAnimationFrame.cjs.map +1 -0
  12. package/dist/components/Webcam/Webcam.d.ts +34 -0
  13. package/dist/components/Webcam/hooks/index.d.ts +1 -0
  14. package/dist/components/Webcam/hooks/useWebcam.d.ts +38 -0
  15. package/dist/components/index.d.ts +2 -0
  16. package/dist/esm/components/Webcam/Webcam.mjs +51 -0
  17. package/dist/esm/components/Webcam/Webcam.mjs.map +1 -0
  18. package/dist/esm/components/Webcam/hooks/useWebcam.mjs +76 -0
  19. package/dist/esm/components/Webcam/hooks/useWebcam.mjs.map +1 -0
  20. package/dist/esm/index.mjs +5 -0
  21. package/dist/esm/utils/helpers/animationFrame.mjs +6 -0
  22. package/dist/esm/utils/helpers/animationFrame.mjs.map +1 -0
  23. package/dist/esm/utils/hooks/useAnimationFrame.mjs +33 -0
  24. package/dist/esm/utils/hooks/useAnimationFrame.mjs.map +1 -0
  25. package/dist/index.d.mts +4 -0
  26. package/dist/index.d.ts +3 -76
  27. package/dist/utils/helpers/animationFrame.d.ts +2 -0
  28. package/dist/utils/helpers/index.d.ts +1 -0
  29. package/dist/utils/hooks/index.d.ts +1 -0
  30. package/dist/utils/hooks/useAnimationFrame.d.ts +11 -0
  31. package/package.json +70 -72
  32. package/dist/cjs/components/Webcam/Webcam.js +0 -3
  33. package/dist/cjs/components/Webcam/Webcam.js.map +0 -1
  34. package/dist/cjs/components/Webcam/hooks/index.js +0 -3
  35. package/dist/cjs/components/Webcam/hooks/index.js.map +0 -1
  36. package/dist/cjs/components/Webcam/hooks/useWebcam.js +0 -3
  37. package/dist/cjs/components/Webcam/hooks/useWebcam.js.map +0 -1
  38. package/dist/cjs/components/index.js +0 -3
  39. package/dist/cjs/components/index.js.map +0 -1
  40. package/dist/cjs/index-a4e0b8ec.js +0 -3
  41. package/dist/cjs/index-a4e0b8ec.js.map +0 -1
  42. package/dist/cjs/index.js +0 -3
  43. package/dist/cjs/index.js.map +0 -1
  44. package/dist/cjs/useMediaStream-4231673b.js +0 -7
  45. package/dist/cjs/useMediaStream-4231673b.js.map +0 -1
  46. package/dist/cjs/utils/helpers/animationFrame.js +0 -3
  47. package/dist/cjs/utils/helpers/animationFrame.js.map +0 -1
  48. package/dist/cjs/utils/helpers/index.js +0 -3
  49. package/dist/cjs/utils/helpers/index.js.map +0 -1
  50. package/dist/cjs/utils/hooks/index.js +0 -3
  51. package/dist/cjs/utils/hooks/index.js.map +0 -1
  52. package/dist/cjs/utils/hooks/useAnimationFrame.js +0 -3
  53. package/dist/cjs/utils/hooks/useAnimationFrame.js.map +0 -1
  54. package/dist/cjs/utils/hooks/useIsomorphicLayoutEffect.js +0 -3
  55. package/dist/cjs/utils/hooks/useIsomorphicLayoutEffect.js.map +0 -1
  56. package/dist/cjs/utils/hooks/useMediaStream.js +0 -3
  57. package/dist/cjs/utils/hooks/useMediaStream.js.map +0 -1
  58. package/dist/esm/components/Webcam/Webcam.js +0 -3
  59. package/dist/esm/components/Webcam/Webcam.js.map +0 -1
  60. package/dist/esm/components/Webcam/hooks/index.js +0 -3
  61. package/dist/esm/components/Webcam/hooks/index.js.map +0 -1
  62. package/dist/esm/components/Webcam/hooks/useWebcam.js +0 -3
  63. package/dist/esm/components/Webcam/hooks/useWebcam.js.map +0 -1
  64. package/dist/esm/components/index.js +0 -3
  65. package/dist/esm/components/index.js.map +0 -1
  66. package/dist/esm/index-022e8735.js +0 -5
  67. package/dist/esm/index-022e8735.js.map +0 -1
  68. package/dist/esm/index.js +0 -4
  69. package/dist/esm/index.js.map +0 -1
  70. package/dist/esm/useMediaStream-4f24b75b.js +0 -6
  71. package/dist/esm/useMediaStream-4f24b75b.js.map +0 -1
  72. package/dist/esm/utils/helpers/animationFrame.js +0 -3
  73. package/dist/esm/utils/helpers/animationFrame.js.map +0 -1
  74. package/dist/esm/utils/helpers/index.js +0 -3
  75. package/dist/esm/utils/helpers/index.js.map +0 -1
  76. package/dist/esm/utils/hooks/index.js +0 -3
  77. package/dist/esm/utils/hooks/index.js.map +0 -1
  78. package/dist/esm/utils/hooks/useAnimationFrame.js +0 -3
  79. package/dist/esm/utils/hooks/useAnimationFrame.js.map +0 -1
  80. package/dist/esm/utils/hooks/useIsomorphicLayoutEffect.js +0 -3
  81. package/dist/esm/utils/hooks/useIsomorphicLayoutEffect.js.map +0 -1
  82. package/dist/esm/utils/hooks/useMediaStream.js +0 -3
  83. package/dist/esm/utils/hooks/useMediaStream.js.map +0 -1
package/README.md CHANGED
@@ -1,130 +1,81 @@
1
- # 📸 Webcam React
2
-
3
- Ultimate tool for working with media stream in your React application
4
-
5
- ## References
6
-
7
- - [**Demo**](https://react-webcam-ultimate.vercel.app/en/react)
8
- - [**Web API**](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia)
9
- - [**Browser Сompatibility**](https://caniuse.com/stream)
10
-
11
- ## Installation
12
-
13
- Install with [npm](https://www.npmjs.com/) or [yarn](https://yarnpkg.com/)
14
-
15
- ```shell
16
- npm i @webcam/react
17
- # or
18
- yarn add @webcam/react
19
- ```
20
-
21
- ## 🦉 Philosophy
22
-
23
- 📸 **Webcam React** is a package that includes ready-made solutions for common cases of setting up and using a media stream from your webcam using Web API. Our goal is to create simple and flexible tools that allow users to create, test and maintain their products.
24
-
25
- ## Features
26
-
27
- - TypeScript support out of the box - full typed package
28
- - Webcam Snapshots - creating an image from a video stream
29
- - Media Stream Handling - request, errors, update, stop, etc
30
- - Advanced Video Settings - selecting camera type and resolution
31
- - Legacy API Support - outdated implementations for each browser
32
- - React Apps Support - component and hooks for working with playing a media stream
33
-
34
- ## Usage
35
-
36
- ```jsx
37
- import React from 'react';
38
- import ReactDOM from 'react-dom';
39
- import { Webcam } from '@webcam/react';
40
-
41
- const App = () => (
42
- <Webcam />
43
- );
44
-
45
- const root = ReactDOM.createRoot(document.getElementById('root'));
46
- root.render(<App/>);
47
- ```
48
-
49
- ### How to get webcam snapshot
50
-
51
- Returns a base64 encoded string of the current video stream frame in the specified format and quality.
52
-
53
- ```jsx
54
- import { Webcam } from '@webcam/react';
55
-
56
- const YourComponent = () => (
57
- <Webcam mirrored>
58
- {({ getSnapshot }) => (
59
- <button onClick={() => getSnapshot({ quality: 0.8 })}>
60
- Make photo
61
- </button>
62
- )}
63
- </Webcam>
64
- );
65
- ```
66
-
67
- ## API
68
-
69
- You can pass any supported [properties](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video) to the underlying video tag (eg `autoPlay`, `className`, etc). However, for convenience, the component uses its own values for these properties, but you can reassign them without any problems:
70
- | **Prop** | **Type** | **Default** | **Note** |
71
- | ------------------------- | -------- | ------------ | --------------------------------------------------------------------------------------- |
72
- | muted | boolean | true | excludes audio constraints from the MediaStream request |
73
- | autoPlay | boolean | true | |
74
- | playsInline | boolean | true | |
75
- | controls | boolean | false | |
76
-
77
- The component also supports many properties for more specific work:
78
- | **Prop** | **Type** | **Default** | **Note** |
79
- | ------------------------- | -------- | ------------ | --------------------------------------------------------------------------------------- |
80
- | mirrored | boolean | false | show camera preview and get the screenshot mirrored |
81
- | mainCamera | boolean \| object | false | should use a main camera (requires Navigator.mediaDevices.enumerateDevices) |
82
- | frontCamera | boolean | false | should use a front camera (MediaTrackConstraints['facingFront'] === 'user') |
83
- | applyConstraints | boolean | false | should new constraints be applied to the media stream |
84
- | cameraResolutionMode | string | 'ideal' | video track resolution mode - `('min' \| 'max' \| 'ideal' \| 'exact')` |
85
- | cameraResolutionType | string | | video track resolution size - `('UHD' \| 'QHD' \| 'FHD' \| 'HD')` |
86
- | requestTimeLimit | number | | limiting the media stream request by time |
87
- | onStreamRequest | function | | callback for when component requests a media stream |
88
- | onStreamStart | function | | callback for when component starts a media stream |
89
- | onStreamStop | function | | callback for when component stops a media stream |
90
- | onStreamError | function | | callback for when component can't receive a media stream |
91
- | audioConstraints | object ||[MediaStreamConstraints['audio']](https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackConstraints)|
92
- | videoConstraints | object ||[MediaStreamConstraints['video']](https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackConstraints)|
93
- | stream | object ||external [MediaStream](https://developer.mozilla.org/en-US/docs/Web/API/MediaStream) (turns off internal media stream handling logic)|
94
-
95
- ## ✨ Contributors
96
-
97
- <table>
98
- <tr>
99
- <td align="center" style="word-wrap: break-word; width: 100; height: 100">
100
- <a href="https://github.com/michael-mir">
101
- <img src="https://avatars.githubusercontent.com/u/88126915?v=4"
102
- width="100;"
103
- alt="michael-mir" />
104
- <br />
105
- <sub style="font-size:13px"><b>🌶️ michael-mir</b></sub>
106
- </a>
107
- </td>
108
- <td align="center" style="word-wrap: break-word; width: 100; height: 100">
109
- <a href="https://github.com/debabin">
110
- <img src="https://avatars.githubusercontent.com/u/45297354?v=4"
111
- width="100;"
112
- alt="debabin" />
113
- <br />
114
- <sub style="font-size:13px"><b>🧊 debabin</b></sub>
115
- </a>
116
- </td>
117
- <td align="center" style="word-wrap: break-word; width: 100.0; height: 100.0">
118
- <a href="https://github.com/RiceWithMeat">
119
- <img src="https://avatars.githubusercontent.com/u/47690223?v=4"
120
- width="100;"
121
- alt="RiceWithMeat" />
122
- <br />
123
- <sub style="font-size:13px"><b>🐘 RiceWithMeat</b></sub>
124
- </a>
125
- </td>
126
- </tr>
127
- </table>
128
-
129
-
130
-
1
+ <div align="center">
2
+ <h1>Webcam React</h1>
3
+
4
+ <a href="https://www.npmjs.com/package/@webcam/react"><img alt="NPM version" src="https://img.shields.io/npm/v/@webcam/react.svg?style=for-the-badge&labelColor=000000"></a>
5
+ <a href="https://github.com/siberiacancode/webcam/blob/main/LICENSE"><img alt="License" src="https://img.shields.io/npm/l/@webcam/react.svg?style=for-the-badge&labelColor=000000"></a>
6
+ <a href="https://siberiacancode.github.io/reactuse/"><img alt="reactuse" src="https://img.shields.io/badge/reactuse-blueviolet.svg?style=for-the-badge&logo=npm&labelColor=000000&logoWidth=20"></a>
7
+ <a href="https://github.com/siberiacancode/webcam/discussions"><img alt="Join the community on GitHub" src="https://img.shields.io/badge/Join%20the%20community-blueviolet.svg?style=for-the-badge&logo=React&labelColor=000000&logoWidth=20"></a>
8
+
9
+ </div>
10
+
11
+ Webcam React is a powerful library that provides easy integration of webcam and media stream features into your React applications. Built with **TypeScript-first** approach, **SSR compatibility**, and **tree-shaking optimization** - everything you need to request, display, and manage camera streams in a modern React app.
12
+
13
+ ## Supported Features
14
+
15
+ - **Live webcam preview** - render media streams with a simple React component
16
+ - **Snapshots** - capture the current frame as base64 image data
17
+ - **Constraint controls** - configure camera source, resolution, facing mode, and more
18
+ - **Stream lifecycle hooks** - react to request, start, stop, and error events
19
+ - **External stream support** - attach an existing `MediaStream` when needed
20
+
21
+ ## Documentation
22
+
23
+ Visit https://react-webcam-ultimate.vercel.app/en/react to view the full documentation.
24
+
25
+ ## Getting Started
26
+
27
+ ```bash
28
+ npm install @webcam/react
29
+ ```
30
+
31
+ ```tsx
32
+ import React from 'react';
33
+ import ReactDOM from 'react-dom/client';
34
+ import { Webcam } from '@webcam/react';
35
+
36
+ const App = () => (
37
+ <Webcam
38
+ mirrored
39
+ cameraResolutionType='FHD'
40
+ onStreamError={(error) => console.error(error)}
41
+ />
42
+ );
43
+
44
+ ReactDOM.createRoot(document.getElementById('root')!).render(
45
+ <React.StrictMode>
46
+ <App />
47
+ </React.StrictMode>
48
+ );
49
+ ```
50
+
51
+ Create a component to use webcam snapshots:
52
+
53
+ ```tsx
54
+ import { Webcam } from '@webcam/react';
55
+
56
+ export const Camera = () => {
57
+ return (
58
+ <Webcam mirrored>
59
+ {({ getSnapshot }) => (
60
+ <button type="button" onClick={() => getSnapshot({ quality: 0.8 })}>
61
+ Make photo
62
+ </button>
63
+ )}
64
+ </Webcam>
65
+ );
66
+ };
67
+ ```
68
+
69
+ ## Reactuse
70
+
71
+ Reactuse delivers **production-ready hooks** that solve real-world problems. Built with **TypeScript-first** approach, **SSR compatibility**, and **tree-shaking optimization** - everything you need to build modern React applications. Improve your react applications with our library 📦 designed for comfort and speed.
72
+
73
+ ## Documentation
74
+
75
+ Visit https://reactuse.org to view the full documentation.
76
+
77
+ ## Getting Started
78
+
79
+ ```bash
80
+ npm install @siberiacancode/reactuse
81
+ ```
@@ -0,0 +1 @@
1
+ var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,a)=>(a=n==null?{}:e(i(n)),o(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));exports.__toESM=s;
@@ -0,0 +1,2 @@
1
+ const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("./hooks/useWebcam.cjs");let n=require("@webcam/core"),r=require("react");r=e.__toESM(r,1);let i=require("react/jsx-runtime");var a=({ref:e,stream:a,cameraResolutionMode:o,cameraResolutionType:s,videoConstraints:c,audioConstraints:l,requestTimeLimit:u,frontCamera:d,mainCamera:f,mirrored:p=!0,muted:m=!0,style:h={},children:g,onLoadedMetadata:_,onRequest:v,onError:y,onStart:b,onStop:x,...S})=>{let C=(0,r.useRef)(null),w=e??C;return t.useWebcam(w,{stream:a,requestTimeLimit:u,onRequest:v,onError:y,onStart:b,onStop:x,videoConstraints:c,audioConstraints:l,cameraResolutionMode:o,cameraResolutionType:s,frontCamera:d,mainCamera:f,muted:m}),(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(`video`,{autoPlay:!0,playsInline:!0,ref:w,style:{...h,...p&&{transform:`${h.transform?`${h.transform} `:``}scaleX(-1)`}},controls:!1,muted:m,onLoadedMetadata:e=>{_?.(e),e.currentTarget.play()},...S}),typeof g==`function`?g({element:w.current,getCanvas:e=>w.current?(0,n.getVideoFrameCanvas)(w.current,{...e,mirrored:p}):void 0,getSnapshot:e=>w.current?(0,n.getWebcamSnapshot)(w.current,{...e,mirrored:p}):void 0}):g]})};exports.Webcam=a;
2
+ //# sourceMappingURL=Webcam.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Webcam.cjs","names":[],"sources":["../../../../src/components/Webcam/Webcam.tsx"],"sourcesContent":["import type {\n GetVideoFrameCanvasOptions,\n GetWebcamSnapshotOptions,\n MediaTrackConstraintsOptions\n} from '@webcam/core';\nimport type { ComponentProps, ReactNode, RefObject } from 'react';\n\nimport { getVideoFrameCanvas, getWebcamSnapshot } from '@webcam/core';\nimport React, { useRef } from 'react';\n\nimport { useWebcam } from './hooks';\n\nexport type WebcamRenderProps = (options: {\n getCanvas: (options?: GetVideoFrameCanvasOptions) => HTMLCanvasElement | undefined;\n getSnapshot: (options?: GetWebcamSnapshotOptions) => string | undefined;\n element: HTMLVideoElement | null;\n}) => ReactNode;\n\ninterface BaseWebcamProps\n extends Omit<ComponentProps<'video'>, 'children' | 'onError'>, MediaTrackConstraintsOptions {\n audioConstraints?: MediaTrackConstraints;\n children?: ReactNode | WebcamRenderProps;\n mirrored?: boolean;\n ref?: RefObject<HTMLVideoElement>;\n requestTimeLimit?: number;\n videoConstraints?: MediaTrackConstraints;\n onError?: (error: Error) => void;\n onRequest?: () => void;\n onStart?: (stream: MediaStream) => void;\n onStop?: (stream?: MediaStream) => void;\n}\n\ninterface WebcamPropsWithInternalStream extends BaseWebcamProps {\n stream?: undefined;\n}\n\ninterface WebcamPropsWithExternalStream extends BaseWebcamProps {\n stream?: MediaStream;\n}\n\nexport type WebcamProps = WebcamPropsWithExternalStream | WebcamPropsWithInternalStream;\n\n/**\n * Renders the Webcam component and handles the requesting and displaying of the media stream\n *\n * @param {WebcamProps} props - The props for the Webcam component\n * @return {ReactElement} The rendered Webcam component\n */\nexport const Webcam = ({\n ref,\n stream,\n cameraResolutionMode,\n cameraResolutionType,\n videoConstraints,\n audioConstraints,\n requestTimeLimit,\n frontCamera,\n mainCamera,\n mirrored = true,\n muted = true,\n style = {},\n children,\n onLoadedMetadata,\n onRequest,\n onError,\n onStart,\n onStop,\n ...props\n}: WebcamProps) => {\n const internalVideoRef = useRef<HTMLVideoElement | null>(null);\n const videoRef = ref ?? internalVideoRef;\n\n useWebcam(videoRef, {\n stream,\n requestTimeLimit,\n onRequest,\n onError,\n onStart,\n onStop,\n videoConstraints,\n audioConstraints,\n cameraResolutionMode,\n cameraResolutionType,\n frontCamera,\n mainCamera,\n muted\n });\n\n return (\n <>\n <video\n autoPlay\n playsInline\n ref={videoRef}\n style={{\n ...style,\n ...(mirrored && {\n transform: `${style.transform ? `${style.transform} ` : ''}scaleX(-1)`\n })\n }}\n controls={false}\n muted={muted}\n onLoadedMetadata={(event) => {\n onLoadedMetadata?.(event);\n event.currentTarget.play();\n }}\n {...props}\n />\n {typeof children === 'function'\n ? children({\n element: videoRef.current,\n getCanvas: (options?: GetVideoFrameCanvasOptions) =>\n videoRef.current\n ? getVideoFrameCanvas(videoRef.current, { ...options, mirrored })\n : undefined,\n getSnapshot: (options?: GetWebcamSnapshotOptions) =>\n videoRef.current\n ? getWebcamSnapshot(videoRef.current, { ...options, mirrored })\n : undefined\n })\n : children}\n </>\n );\n};\n"],"mappings":"gMAgDA,IAAa,GAAU,CACrB,MACA,SACA,uBACA,uBACA,mBACA,mBACA,mBACA,cACA,aACA,WAAW,GACX,QAAQ,GACR,QAAQ,CAAC,EACT,WACA,mBACA,YACA,UACA,UACA,SACA,GAAG,KACc,CACjB,IAAM,GAAA,EAAA,EAAA,OAAA,CAAmD,IAAI,EACvD,EAAW,GAAO,EAkBxB,OAhBA,EAAA,UAAU,EAAU,CAClB,SACA,mBACA,YACA,UACA,UACA,SACA,mBACA,mBACA,uBACA,uBACA,cACA,aACA,OACF,CAAC,GAGC,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,QAAD,CACE,SAAA,GACA,YAAA,GACA,IAAK,EACL,MAAO,CACL,GAAG,EACH,GAAI,GAAY,CACd,UAAW,GAAG,EAAM,UAAY,GAAG,EAAM,UAAU,GAAK,GAAG,WAC7D,CACF,EACA,SAAU,GACH,QACP,iBAAmB,GAAU,CAC3B,IAAmB,CAAK,EACxB,EAAM,cAAc,KAAK,CAC3B,EACA,GAAI,CACL,CAAA,EACA,OAAO,GAAa,WACjB,EAAS,CACP,QAAS,EAAS,QAClB,UAAY,GACV,EAAS,SAAA,EAAA,EAAA,oBAAA,CACe,EAAS,QAAS,CAAE,GAAG,EAAS,UAAS,CAAC,EAC9D,IAAA,GACN,YAAc,GACZ,EAAS,SAAA,EAAA,EAAA,kBAAA,CACa,EAAS,QAAS,CAAE,GAAG,EAAS,UAAS,CAAC,EAC5D,IAAA,EACR,CAAC,EACD,CACJ,CAAA,CAAA,CAEN"}
@@ -0,0 +1,2 @@
1
+ let e=require("@siberiacancode/reactuse"),t=require("@webcam/core"),n=require("react");var r=((...r)=>{let i=(0,e.isTarget)(r[0])?r[0]:void 0,{stream:a,videoConstraints:o,audioConstraints:s,cameraResolutionMode:c,cameraResolutionType:l,frontCamera:u,mainCamera:d,muted:f,onRequest:p,onError:m,onStart:h,onStop:g}=(i?r[1]:r[0])??{},_=(0,e.useRefState)(),v=i??_,y=(0,e.useMediaStream)(v,{immediately:!1,onStart:h,onStop:g,onError:m}),b=()=>(0,t.getMediaStreamConstraints)({constraints:{video:o,audio:s},options:{cameraResolutionMode:c,cameraResolutionType:l,frontCamera:u,mainCamera:d,muted:f}});return(0,e.useMount)(()=>{a||(async()=>{p?.();let e=await b();y.start(e)})()}),(0,e.useDidUpdate)(()=>{a||(async()=>{p?.();let e=await b();if(y.stream){await y.apply(e)||y.start(e);return}y.start(e)})()},[o,s,c,l,u,d,f]),(0,n.useEffect)(()=>{if(!a)return;let t=e.isTarget.getElement(v);if(t)return t.srcObject=a,h?.(a),()=>{g?.(a)}},[a,i&&e.isTarget.getRawElement(i),_.state]),(0,e.useUnmount)(()=>{a||y.stop()}),i?{stream:a??y.stream,start:y.start,apply:y.apply,stop:y.stop}:{stream:a??y.stream,start:y.start,apply:y.apply,stop:y.stop,ref:_}});exports.useWebcam=r;
2
+ //# sourceMappingURL=useWebcam.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useWebcam.cjs","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":"uFAqDA,IAAa,IAAc,GAAG,IAAkB,CAC9C,IAAM,GAAA,EAAA,EAAA,SAAA,CAAmB,EAAO,EAAE,EAAI,EAAO,GAAK,IAAA,GAG5C,CACJ,OAAQ,EACR,mBACA,mBACA,uBACA,uBACA,cACA,aACA,QACA,YACA,UACA,UACA,WAdgB,EAAS,EAAO,GAAK,EAAO,KAA2B,CAAC,EAiBpE,GAAA,EAAA,EAAA,YAAA,CAA4C,EAC5C,EAAe,GAAU,EAEzB,GAAA,EAAA,EAAA,eAAA,CAA6B,EAAa,CAC9C,YAAa,GACb,UACA,SACA,SACF,CAAiC,EAE3B,OAAA,EAAA,EAAA,0BAAA,CACsB,CACxB,YAAa,CACX,MAAO,EACP,MAAO,CACT,EACA,QAAS,CACP,uBACA,uBACA,cACA,aACA,OACF,CACF,CAAC,EAkEH,OAhEA,EAAA,EAAA,SAAA,KAAe,CACT,IAOJ,SANwB,CACtB,IAAY,EACZ,IAAM,EAAc,MAAM,EAAkB,EAC5C,EAAY,MAAM,CAAW,CAC/B,EAEA,CAAI,CACN,CAAC,GAED,EAAA,EAAA,aAAA,KAAmB,CACb,IAeJ,SAbwB,CACtB,IAAY,EACZ,IAAM,EAAc,MAAM,EAAkB,EAE5C,GAAI,EAAY,OAAQ,CAEjB,MADY,EAAY,MAAM,CAAW,GACrC,EAAY,MAAM,CAAW,EACtC,MACF,CAEA,EAAY,MAAM,CAAW,CAC/B,EAEA,CAAI,CACN,EAAG,CACD,EACA,EACA,EACA,EACA,EACA,EACA,CACF,CAAC,GAED,EAAA,EAAA,UAAA,KAAgB,CACd,GAAI,CAAC,EAAgB,OAErB,IAAM,EAAU,EAAA,SAAS,WAAW,CAAW,EAC1C,KAKL,MAHA,GAAQ,UAAY,EACpB,IAAU,CAAc,MAEX,CACX,IAAS,CAAc,CACzB,CACF,EAAG,CAAC,EAAgB,GAAU,EAAA,SAAS,cAAc,CAAM,EAAG,EAAY,KAAK,CAAC,GAEhF,EAAA,EAAA,WAAA,KAAiB,CACX,GACJ,EAAY,KAAK,CACnB,CAAC,EAEG,EACK,CACL,OAAQ,GAAkB,EAAY,OACtC,MAAO,EAAY,MACnB,MAAO,EAAY,MACnB,KAAM,EAAY,IACpB,EACK,CACL,OAAQ,GAAkB,EAAY,OACtC,MAAO,EAAY,MACnB,MAAO,EAAY,MACnB,KAAM,EAAY,KAClB,IAAK,CACP,CACF"}
@@ -0,0 +1 @@
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./components/Webcam/hooks/useWebcam.cjs"),t=require("./components/Webcam/Webcam.cjs"),n=require("./utils/hooks/useAnimationFrame.cjs");let r=require("@webcam/core");exports.Webcam=t.Webcam,Object.defineProperty(exports,"applyMediaStreamConstraints",{enumerable:!0,get:function(){return r.applyMediaStreamConstraints}}),Object.defineProperty(exports,"canGetUserMedia",{enumerable:!0,get:function(){return r.canGetUserMedia}}),Object.defineProperty(exports,"getDevices",{enumerable:!0,get:function(){return r.getDevices}}),Object.defineProperty(exports,"getMediaStream",{enumerable:!0,get:function(){return r.getMediaStream}}),Object.defineProperty(exports,"getMediaStreamConstraints",{enumerable:!0,get:function(){return r.getMediaStreamConstraints}}),Object.defineProperty(exports,"getVideoFrameCanvas",{enumerable:!0,get:function(){return r.getVideoFrameCanvas}}),Object.defineProperty(exports,"getWebcamSnapshot",{enumerable:!0,get:function(){return r.getWebcamSnapshot}}),Object.defineProperty(exports,"stopMediaStream",{enumerable:!0,get:function(){return r.stopMediaStream}}),exports.useAnimationFrame=n.useAnimationFrame,exports.useWebcam=e.useWebcam;
@@ -0,0 +1,2 @@
1
+ var e=window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||window.msRequestAnimationFrame,t=window.cancelAnimationFrame||window.mozCancelAnimationFrame||window.webkitCancelAnimationFrame||window.msCancelAnimationFrame;exports.cancelAnimationFrame=t,exports.requestAnimationFrame=e;
2
+ //# sourceMappingURL=animationFrame.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"animationFrame.cjs","names":[],"sources":["../../../../src/utils/helpers/animationFrame.ts"],"sourcesContent":["// ✅ important\n// Implementations for each browser need to be supported\nexport const requestAnimationFrame =\n window.requestAnimationFrame ||\n window.mozRequestAnimationFrame ||\n window.webkitRequestAnimationFrame ||\n window.msRequestAnimationFrame;\n\nexport const cancelAnimationFrame =\n window.cancelAnimationFrame ||\n window.mozCancelAnimationFrame ||\n window.webkitCancelAnimationFrame ||\n window.msCancelAnimationFrame;\n"],"mappings":"AAEA,IAAa,EACX,OAAO,uBACP,OAAO,0BACP,OAAO,6BACP,OAAO,wBAEI,EACX,OAAO,sBACP,OAAO,yBACP,OAAO,4BACP,OAAO"}
@@ -0,0 +1,2 @@
1
+ const e=require("../helpers/animationFrame.cjs");let t=require("@siberiacancode/reactuse"),n=require("react");var r=(r,i)=>{let a=(0,n.useRef)(void 0),o=(0,n.useRef)(void 0),s=(0,n.useRef)(r);(0,t.useIsomorphicLayoutEffect)(()=>{s.current=r},[r]);let c=t=>{if(t){if(o.current=t,o.current===void 0)return;s.current(t-o.current)}a.current=e.requestAnimationFrame(c)},l=()=>{a.current&&e.cancelAnimationFrame(a.current)};return(0,n.useEffect)(()=>{if(i){a.current=e.requestAnimationFrame(c);return}return l(),()=>l()},[i]),{request:c,cancel:l}};exports.useAnimationFrame=r;
2
+ //# sourceMappingURL=useAnimationFrame.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAnimationFrame.cjs","names":[],"sources":["../../../../src/utils/hooks/useAnimationFrame.ts"],"sourcesContent":["import { useIsomorphicLayoutEffect } from '@siberiacancode/reactuse';\nimport { useEffect, useRef } from 'react';\n\nimport { cancelAnimationFrame, requestAnimationFrame } from '../helpers';\n\n/**\n * Helps request and cancel animation frame\n *\n * @param {Function} callback - frame request callback\n * @param {boolean} active - should animation frame be requested\n * @return {object} request/cancel animation frame handlers\n */\nexport const useAnimationFrame = (callback: (time: number) => void, active?: boolean) => {\n const animationFrameRequestRef = useRef<number>(undefined);\n const previousTimestampRef = useRef<number>(undefined);\n const savedHandlerRef = useRef(callback);\n\n useIsomorphicLayoutEffect(() => {\n savedHandlerRef.current = callback;\n }, [callback]);\n\n const onFrameRequest = (timestamp?: DOMHighResTimeStamp) => {\n if (timestamp) {\n previousTimestampRef.current = timestamp;\n if (previousTimestampRef.current === undefined) return;\n savedHandlerRef.current(timestamp - previousTimestampRef.current);\n }\n\n animationFrameRequestRef.current = requestAnimationFrame(onFrameRequest);\n };\n\n const onFrameCancel = () => {\n if (!animationFrameRequestRef.current) return;\n cancelAnimationFrame(animationFrameRequestRef.current);\n };\n\n useEffect(() => {\n if (active) {\n animationFrameRequestRef.current = requestAnimationFrame(onFrameRequest);\n return;\n }\n\n onFrameCancel();\n return () => onFrameCancel();\n }, [active]);\n\n return {\n request: onFrameRequest,\n cancel: onFrameCancel\n };\n};\n"],"mappings":"8GAYA,IAAa,GAAqB,EAAkC,IAAqB,CACvF,IAAM,GAAA,EAAA,EAAA,OAAA,CAA0C,IAAA,EAAS,EACnD,GAAA,EAAA,EAAA,OAAA,CAAsC,IAAA,EAAS,EAC/C,GAAA,EAAA,EAAA,OAAA,CAAyB,CAAQ,GAEvC,EAAA,EAAA,0BAAA,KAAgC,CAC9B,EAAgB,QAAU,CAC5B,EAAG,CAAC,CAAQ,CAAC,EAEb,IAAM,EAAkB,GAAoC,CAC1D,GAAI,EAAW,CAEb,GADA,EAAqB,QAAU,EAC3B,EAAqB,UAAY,IAAA,GAAW,OAChD,EAAgB,QAAQ,EAAY,EAAqB,OAAO,CAClE,CAEA,EAAyB,QAAU,EAAA,sBAAsB,CAAc,CACzE,EAEM,MAAsB,CACrB,EAAyB,SAC9B,EAAA,qBAAqB,EAAyB,OAAO,CACvD,EAYA,OAVA,EAAA,EAAA,UAAA,KAAgB,CACd,GAAI,EAAQ,CACV,EAAyB,QAAU,EAAA,sBAAsB,CAAc,EACvE,MACF,CAGA,OADA,EAAc,MACD,EAAc,CAC7B,EAAG,CAAC,CAAM,CAAC,EAEJ,CACL,QAAS,EACT,OAAQ,CACV,CACF"}
@@ -0,0 +1,34 @@
1
+ import { GetVideoFrameCanvasOptions, GetWebcamSnapshotOptions, MediaTrackConstraintsOptions } from '@webcam/core';
2
+ import { ComponentProps, ReactNode, RefObject, default as React } from 'react';
3
+ export type WebcamRenderProps = (options: {
4
+ getCanvas: (options?: GetVideoFrameCanvasOptions) => HTMLCanvasElement | undefined;
5
+ getSnapshot: (options?: GetWebcamSnapshotOptions) => string | undefined;
6
+ element: HTMLVideoElement | null;
7
+ }) => ReactNode;
8
+ interface BaseWebcamProps extends Omit<ComponentProps<'video'>, 'children' | 'onError'>, MediaTrackConstraintsOptions {
9
+ audioConstraints?: MediaTrackConstraints;
10
+ children?: ReactNode | WebcamRenderProps;
11
+ mirrored?: boolean;
12
+ ref?: RefObject<HTMLVideoElement>;
13
+ requestTimeLimit?: number;
14
+ videoConstraints?: MediaTrackConstraints;
15
+ onError?: (error: Error) => void;
16
+ onRequest?: () => void;
17
+ onStart?: (stream: MediaStream) => void;
18
+ onStop?: (stream?: MediaStream) => void;
19
+ }
20
+ interface WebcamPropsWithInternalStream extends BaseWebcamProps {
21
+ stream?: undefined;
22
+ }
23
+ interface WebcamPropsWithExternalStream extends BaseWebcamProps {
24
+ stream?: MediaStream;
25
+ }
26
+ export type WebcamProps = WebcamPropsWithExternalStream | WebcamPropsWithInternalStream;
27
+ /**
28
+ * Renders the Webcam component and handles the requesting and displaying of the media stream
29
+ *
30
+ * @param {WebcamProps} props - The props for the Webcam component
31
+ * @return {ReactElement} The rendered Webcam component
32
+ */
33
+ export declare const Webcam: ({ ref, stream, cameraResolutionMode, cameraResolutionType, videoConstraints, audioConstraints, requestTimeLimit, frontCamera, mainCamera, mirrored, muted, style, children, onLoadedMetadata, onRequest, onError, onStart, onStop, ...props }: WebcamProps) => React.JSX.Element;
34
+ export {};
@@ -0,0 +1 @@
1
+ export * from './useWebcam';
@@ -0,0 +1,38 @@
1
+ import { HookTarget, StateRef } from '@siberiacancode/reactuse';
2
+ import { MediaTrackConstraintsOptions } from '@webcam/core';
3
+ export interface UseWebcamParams extends MediaTrackConstraintsOptions {
4
+ audioConstraints?: MediaTrackConstraints;
5
+ requestTimeLimit?: number;
6
+ stream?: MediaStream;
7
+ videoConstraints?: MediaTrackConstraints;
8
+ onError?: (error: Error) => void;
9
+ onRequest?: () => void;
10
+ onStart?: (stream: MediaStream) => void;
11
+ onStop?: (stream?: MediaStream) => void;
12
+ }
13
+ export interface UseWebcamReturn {
14
+ stream?: MediaStream;
15
+ apply: (constraints: MediaStreamConstraints) => Promise<boolean>;
16
+ start: (constraints?: MediaStreamConstraints) => Promise<MediaStream | undefined>;
17
+ stop: () => void;
18
+ }
19
+ export interface UseWebcam {
20
+ (target: HookTarget, params?: UseWebcamParams): UseWebcamReturn;
21
+ (params?: UseWebcamParams): UseWebcamReturn & {
22
+ ref: StateRef<HTMLVideoElement>;
23
+ };
24
+ }
25
+ /**
26
+ * @name useWebcam
27
+ * @description - Hook that manages a webcam media stream for a video element
28
+ *
29
+ * @overload
30
+ * @param {HookTarget} target The target video element the stream will be attached to
31
+ * @param {UseWebcamParams} [params] The webcam parameters
32
+ * @returns {UseWebcamReturn} An object containing the stream and controls
33
+ *
34
+ * @overload
35
+ * @param {UseWebcamParams} [params] The webcam parameters
36
+ * @returns {UseWebcamReturn & { ref: StateRef<HTMLVideoElement> }} An object containing the stream, controls and ref
37
+ */
38
+ export declare const useWebcam: UseWebcam;
@@ -0,0 +1,2 @@
1
+ export * from './Webcam/hooks';
2
+ export * from './Webcam/Webcam';
@@ -0,0 +1,51 @@
1
+ import { useWebcam as e } from "./hooks/useWebcam.mjs";
2
+ import { getVideoFrameCanvas as t, getWebcamSnapshot as n } from "@webcam/core";
3
+ import { useRef as r } from "react";
4
+ import { Fragment as i, jsx as a, jsxs as o } from "react/jsx-runtime";
5
+ //#region src/components/Webcam/Webcam.tsx
6
+ var s = ({ ref: s, stream: c, cameraResolutionMode: l, cameraResolutionType: u, videoConstraints: d, audioConstraints: f, requestTimeLimit: p, frontCamera: m, mainCamera: h, mirrored: g = !0, muted: _ = !0, style: v = {}, children: y, onLoadedMetadata: b, onRequest: x, onError: S, onStart: C, onStop: w, ...T }) => {
7
+ let E = r(null), D = s ?? E;
8
+ return e(D, {
9
+ stream: c,
10
+ requestTimeLimit: p,
11
+ onRequest: x,
12
+ onError: S,
13
+ onStart: C,
14
+ onStop: w,
15
+ videoConstraints: d,
16
+ audioConstraints: f,
17
+ cameraResolutionMode: l,
18
+ cameraResolutionType: u,
19
+ frontCamera: m,
20
+ mainCamera: h,
21
+ muted: _
22
+ }), /* @__PURE__ */ o(i, { children: [/* @__PURE__ */ a("video", {
23
+ autoPlay: !0,
24
+ playsInline: !0,
25
+ ref: D,
26
+ style: {
27
+ ...v,
28
+ ...g && { transform: `${v.transform ? `${v.transform} ` : ""}scaleX(-1)` }
29
+ },
30
+ controls: !1,
31
+ muted: _,
32
+ onLoadedMetadata: (e) => {
33
+ b?.(e), e.currentTarget.play();
34
+ },
35
+ ...T
36
+ }), typeof y == "function" ? y({
37
+ element: D.current,
38
+ getCanvas: (e) => D.current ? t(D.current, {
39
+ ...e,
40
+ mirrored: g
41
+ }) : void 0,
42
+ getSnapshot: (e) => D.current ? n(D.current, {
43
+ ...e,
44
+ mirrored: g
45
+ }) : void 0
46
+ }) : y] });
47
+ };
48
+ //#endregion
49
+ export { s as Webcam };
50
+
51
+ //# sourceMappingURL=Webcam.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Webcam.mjs","names":[],"sources":["../../../../src/components/Webcam/Webcam.tsx"],"sourcesContent":["import type {\n GetVideoFrameCanvasOptions,\n GetWebcamSnapshotOptions,\n MediaTrackConstraintsOptions\n} from '@webcam/core';\nimport type { ComponentProps, ReactNode, RefObject } from 'react';\n\nimport { getVideoFrameCanvas, getWebcamSnapshot } from '@webcam/core';\nimport React, { useRef } from 'react';\n\nimport { useWebcam } from './hooks';\n\nexport type WebcamRenderProps = (options: {\n getCanvas: (options?: GetVideoFrameCanvasOptions) => HTMLCanvasElement | undefined;\n getSnapshot: (options?: GetWebcamSnapshotOptions) => string | undefined;\n element: HTMLVideoElement | null;\n}) => ReactNode;\n\ninterface BaseWebcamProps\n extends Omit<ComponentProps<'video'>, 'children' | 'onError'>, MediaTrackConstraintsOptions {\n audioConstraints?: MediaTrackConstraints;\n children?: ReactNode | WebcamRenderProps;\n mirrored?: boolean;\n ref?: RefObject<HTMLVideoElement>;\n requestTimeLimit?: number;\n videoConstraints?: MediaTrackConstraints;\n onError?: (error: Error) => void;\n onRequest?: () => void;\n onStart?: (stream: MediaStream) => void;\n onStop?: (stream?: MediaStream) => void;\n}\n\ninterface WebcamPropsWithInternalStream extends BaseWebcamProps {\n stream?: undefined;\n}\n\ninterface WebcamPropsWithExternalStream extends BaseWebcamProps {\n stream?: MediaStream;\n}\n\nexport type WebcamProps = WebcamPropsWithExternalStream | WebcamPropsWithInternalStream;\n\n/**\n * Renders the Webcam component and handles the requesting and displaying of the media stream\n *\n * @param {WebcamProps} props - The props for the Webcam component\n * @return {ReactElement} The rendered Webcam component\n */\nexport const Webcam = ({\n ref,\n stream,\n cameraResolutionMode,\n cameraResolutionType,\n videoConstraints,\n audioConstraints,\n requestTimeLimit,\n frontCamera,\n mainCamera,\n mirrored = true,\n muted = true,\n style = {},\n children,\n onLoadedMetadata,\n onRequest,\n onError,\n onStart,\n onStop,\n ...props\n}: WebcamProps) => {\n const internalVideoRef = useRef<HTMLVideoElement | null>(null);\n const videoRef = ref ?? internalVideoRef;\n\n useWebcam(videoRef, {\n stream,\n requestTimeLimit,\n onRequest,\n onError,\n onStart,\n onStop,\n videoConstraints,\n audioConstraints,\n cameraResolutionMode,\n cameraResolutionType,\n frontCamera,\n mainCamera,\n muted\n });\n\n return (\n <>\n <video\n autoPlay\n playsInline\n ref={videoRef}\n style={{\n ...style,\n ...(mirrored && {\n transform: `${style.transform ? `${style.transform} ` : ''}scaleX(-1)`\n })\n }}\n controls={false}\n muted={muted}\n onLoadedMetadata={(event) => {\n onLoadedMetadata?.(event);\n event.currentTarget.play();\n }}\n {...props}\n />\n {typeof children === 'function'\n ? children({\n element: videoRef.current,\n getCanvas: (options?: GetVideoFrameCanvasOptions) =>\n videoRef.current\n ? getVideoFrameCanvas(videoRef.current, { ...options, mirrored })\n : undefined,\n getSnapshot: (options?: GetWebcamSnapshotOptions) =>\n videoRef.current\n ? getWebcamSnapshot(videoRef.current, { ...options, mirrored })\n : undefined\n })\n : children}\n </>\n );\n};\n"],"mappings":";;;;;AAgDA,IAAa,KAAU,EACrB,QACA,WACA,yBACA,yBACA,qBACA,qBACA,qBACA,gBACA,eACA,cAAW,IACX,WAAQ,IACR,WAAQ,CAAC,GACT,aACA,qBACA,cACA,YACA,YACA,WACA,GAAG,QACc;CACjB,IAAM,IAAmB,EAAgC,IAAI,GACvD,IAAW,KAAO;CAkBxB,OAhBA,EAAU,GAAU;EAClB;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CAAC,GAGC,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,SAAD;EACE,UAAA;EACA,aAAA;EACA,KAAK;EACL,OAAO;GACL,GAAG;GACH,GAAI,KAAY,EACd,WAAW,GAAG,EAAM,YAAY,GAAG,EAAM,UAAU,KAAK,GAAG,YAC7D;EACF;EACA,UAAU;EACH;EACP,mBAAmB,MAAU;GAE3B,AADA,IAAmB,CAAK,GACxB,EAAM,cAAc,KAAK;EAC3B;EACA,GAAI;CACL,CAAA,GACA,OAAO,KAAa,aACjB,EAAS;EACP,SAAS,EAAS;EAClB,YAAY,MACV,EAAS,UACL,EAAoB,EAAS,SAAS;GAAE,GAAG;GAAS;EAAS,CAAC,IAC9D,KAAA;EACN,cAAc,MACZ,EAAS,UACL,EAAkB,EAAS,SAAS;GAAE,GAAG;GAAS;EAAS,CAAC,IAC5D,KAAA;CACR,CAAC,IACD,CACJ,EAAA,CAAA;AAEN"}
@@ -0,0 +1,76 @@
1
+ import { isTarget as e, useDidUpdate as t, useMediaStream as n, useMount as r, useRefState as i, useUnmount as a } from "@siberiacancode/reactuse";
2
+ import { getMediaStreamConstraints as o } from "@webcam/core";
3
+ import { useEffect as s } from "react";
4
+ //#region src/components/Webcam/hooks/useWebcam.ts
5
+ var c = ((...c) => {
6
+ let l = e(c[0]) ? c[0] : void 0, { stream: u, videoConstraints: d, audioConstraints: f, cameraResolutionMode: p, cameraResolutionType: m, frontCamera: h, mainCamera: g, muted: _, onRequest: v, onError: y, onStart: b, onStop: x } = (l ? c[1] : c[0]) ?? {}, S = i(), C = l ?? S, w = n(C, {
7
+ immediately: !1,
8
+ onStart: b,
9
+ onStop: x,
10
+ onError: y
11
+ }), T = () => o({
12
+ constraints: {
13
+ video: d,
14
+ audio: f
15
+ },
16
+ options: {
17
+ cameraResolutionMode: p,
18
+ cameraResolutionType: m,
19
+ frontCamera: h,
20
+ mainCamera: g,
21
+ muted: _
22
+ }
23
+ });
24
+ return r(() => {
25
+ u || (async () => {
26
+ v?.();
27
+ let e = await T();
28
+ w.start(e);
29
+ })();
30
+ }), t(() => {
31
+ u || (async () => {
32
+ v?.();
33
+ let e = await T();
34
+ if (w.stream) {
35
+ await w.apply(e) || w.start(e);
36
+ return;
37
+ }
38
+ w.start(e);
39
+ })();
40
+ }, [
41
+ d,
42
+ f,
43
+ p,
44
+ m,
45
+ h,
46
+ g,
47
+ _
48
+ ]), s(() => {
49
+ if (!u) return;
50
+ let t = e.getElement(C);
51
+ if (t) return t.srcObject = u, b?.(u), () => {
52
+ x?.(u);
53
+ };
54
+ }, [
55
+ u,
56
+ l && e.getRawElement(l),
57
+ S.state
58
+ ]), a(() => {
59
+ u || w.stop();
60
+ }), l ? {
61
+ stream: u ?? w.stream,
62
+ start: w.start,
63
+ apply: w.apply,
64
+ stop: w.stop
65
+ } : {
66
+ stream: u ?? w.stream,
67
+ start: w.start,
68
+ apply: w.apply,
69
+ stop: w.stop,
70
+ ref: S
71
+ };
72
+ });
73
+ //#endregion
74
+ export { c as useWebcam };
75
+
76
+ //# sourceMappingURL=useWebcam.mjs.map
@@ -0,0 +1 @@
1
+ {"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"}
@@ -0,0 +1,5 @@
1
+ import { useWebcam as e } from "./components/Webcam/hooks/useWebcam.mjs";
2
+ import { Webcam as t } from "./components/Webcam/Webcam.mjs";
3
+ import { useAnimationFrame as n } from "./utils/hooks/useAnimationFrame.mjs";
4
+ import { applyMediaStreamConstraints as r, canGetUserMedia as i, getDevices as a, getMediaStream as o, getMediaStreamConstraints as s, getVideoFrameCanvas as c, getWebcamSnapshot as l, stopMediaStream as u } from "@webcam/core";
5
+ export { t as Webcam, r as applyMediaStreamConstraints, i as canGetUserMedia, a as getDevices, o as getMediaStream, s as getMediaStreamConstraints, c as getVideoFrameCanvas, l as getWebcamSnapshot, u as stopMediaStream, n as useAnimationFrame, e as useWebcam };
@@ -0,0 +1,6 @@
1
+ //#region src/utils/helpers/animationFrame.ts
2
+ var e = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame, t = window.cancelAnimationFrame || window.mozCancelAnimationFrame || window.webkitCancelAnimationFrame || window.msCancelAnimationFrame;
3
+ //#endregion
4
+ export { t as cancelAnimationFrame, e as requestAnimationFrame };
5
+
6
+ //# sourceMappingURL=animationFrame.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"animationFrame.mjs","names":[],"sources":["../../../../src/utils/helpers/animationFrame.ts"],"sourcesContent":["// ✅ important\n// Implementations for each browser need to be supported\nexport const requestAnimationFrame =\n window.requestAnimationFrame ||\n window.mozRequestAnimationFrame ||\n window.webkitRequestAnimationFrame ||\n window.msRequestAnimationFrame;\n\nexport const cancelAnimationFrame =\n window.cancelAnimationFrame ||\n window.mozCancelAnimationFrame ||\n window.webkitCancelAnimationFrame ||\n window.msCancelAnimationFrame;\n"],"mappings":";AAEA,IAAa,IACX,OAAO,yBACP,OAAO,4BACP,OAAO,+BACP,OAAO,yBAEI,IACX,OAAO,wBACP,OAAO,2BACP,OAAO,8BACP,OAAO"}
@@ -0,0 +1,33 @@
1
+ import { cancelAnimationFrame as e, requestAnimationFrame as t } from "../helpers/animationFrame.mjs";
2
+ import { useIsomorphicLayoutEffect as n } from "@siberiacancode/reactuse";
3
+ import { useEffect as r, useRef as i } from "react";
4
+ //#region src/utils/hooks/useAnimationFrame.ts
5
+ var a = (a, o) => {
6
+ let s = i(void 0), c = i(void 0), l = i(a);
7
+ n(() => {
8
+ l.current = a;
9
+ }, [a]);
10
+ let u = (e) => {
11
+ if (e) {
12
+ if (c.current = e, c.current === void 0) return;
13
+ l.current(e - c.current);
14
+ }
15
+ s.current = t(u);
16
+ }, d = () => {
17
+ s.current && e(s.current);
18
+ };
19
+ return r(() => {
20
+ if (o) {
21
+ s.current = t(u);
22
+ return;
23
+ }
24
+ return d(), () => d();
25
+ }, [o]), {
26
+ request: u,
27
+ cancel: d
28
+ };
29
+ };
30
+ //#endregion
31
+ export { a as useAnimationFrame };
32
+
33
+ //# sourceMappingURL=useAnimationFrame.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAnimationFrame.mjs","names":[],"sources":["../../../../src/utils/hooks/useAnimationFrame.ts"],"sourcesContent":["import { useIsomorphicLayoutEffect } from '@siberiacancode/reactuse';\nimport { useEffect, useRef } from 'react';\n\nimport { cancelAnimationFrame, requestAnimationFrame } from '../helpers';\n\n/**\n * Helps request and cancel animation frame\n *\n * @param {Function} callback - frame request callback\n * @param {boolean} active - should animation frame be requested\n * @return {object} request/cancel animation frame handlers\n */\nexport const useAnimationFrame = (callback: (time: number) => void, active?: boolean) => {\n const animationFrameRequestRef = useRef<number>(undefined);\n const previousTimestampRef = useRef<number>(undefined);\n const savedHandlerRef = useRef(callback);\n\n useIsomorphicLayoutEffect(() => {\n savedHandlerRef.current = callback;\n }, [callback]);\n\n const onFrameRequest = (timestamp?: DOMHighResTimeStamp) => {\n if (timestamp) {\n previousTimestampRef.current = timestamp;\n if (previousTimestampRef.current === undefined) return;\n savedHandlerRef.current(timestamp - previousTimestampRef.current);\n }\n\n animationFrameRequestRef.current = requestAnimationFrame(onFrameRequest);\n };\n\n const onFrameCancel = () => {\n if (!animationFrameRequestRef.current) return;\n cancelAnimationFrame(animationFrameRequestRef.current);\n };\n\n useEffect(() => {\n if (active) {\n animationFrameRequestRef.current = requestAnimationFrame(onFrameRequest);\n return;\n }\n\n onFrameCancel();\n return () => onFrameCancel();\n }, [active]);\n\n return {\n request: onFrameRequest,\n cancel: onFrameCancel\n };\n};\n"],"mappings":";;;;AAYA,IAAa,KAAqB,GAAkC,MAAqB;CACvF,IAAM,IAA2B,EAAe,KAAA,CAAS,GACnD,IAAuB,EAAe,KAAA,CAAS,GAC/C,IAAkB,EAAO,CAAQ;CAEvC,QAAgC;EAC9B,EAAgB,UAAU;CAC5B,GAAG,CAAC,CAAQ,CAAC;CAEb,IAAM,KAAkB,MAAoC;EAC1D,IAAI,GAAW;GAEb,IADA,EAAqB,UAAU,GAC3B,EAAqB,YAAY,KAAA,GAAW;GAChD,EAAgB,QAAQ,IAAY,EAAqB,OAAO;EAClE;EAEA,EAAyB,UAAU,EAAsB,CAAc;CACzE,GAEM,UAAsB;EACrB,EAAyB,WAC9B,EAAqB,EAAyB,OAAO;CACvD;CAYA,OAVA,QAAgB;EACd,IAAI,GAAQ;GACV,EAAyB,UAAU,EAAsB,CAAc;GACvE;EACF;EAGA,OADA,EAAc,SACD,EAAc;CAC7B,GAAG,CAAC,CAAM,CAAC,GAEJ;EACL,SAAS;EACT,QAAQ;CACV;AACF"}
@@ -0,0 +1,4 @@
1
+ export { useWebcam } from './components/Webcam/hooks';
2
+ export { Webcam } from './components/Webcam/Webcam';
3
+ export { useAnimationFrame } from './utils/hooks';
4
+ export { applyMediaStreamConstraints, canGetUserMedia, getDevices, getMediaStream, getMediaStreamConstraints, getVideoFrameCanvas, getWebcamSnapshot, stopMediaStream } from '@webcam/core';