Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@georapbox/capture-photo-element

Package Overview
Dependencies
Maintainers
0
Versions
18
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@georapbox/capture-photo-element - npm Package Compare versions

Comparing version 4.0.1 to 4.1.0

17

dist/capture-photo-defined.js

@@ -1,2 +0,11 @@

Object.defineProperty({},"CapturePhoto",{get:function(){return n},set:void 0,enumerable:!0,configurable:!0});let t=(t,e,i)=>(Number.isNaN(e)&&(e=0),Number.isNaN(i)&&(i=0),Math.min(Math.max(t,Math.min(e,i)),Math.max(e,i))),e="capture-photo",i=`
/*!
* @georapbox/capture-photo-element
* A custom element that implements the MediaDevices.getUserMedia() method of the MediaDevices interface to capture a photo in the browser.
*
* @version 4.1.0
* @homepage https://github.com/georapbox/capture-photo-element#readme
* @author George Raptis <georapbox@gmail.com>
* @license MIT
*/
var u=(r,t,i)=>(Number.isNaN(t)&&(t=0),Number.isNaN(i)&&(i=0),Math.min(Math.max(r,Math.min(t,i)),Math.max(t,i)));var a="capture-photo",g=`
:host {

@@ -26,4 +35,4 @@ display: block;

}
`,o=document.createElement("template");o.innerHTML=`
<style>${i}</style>
`,d=document.createElement("template");d.innerHTML=`
<style>${g}</style>

@@ -53,3 +62,3 @@ <video part="video" playsinline></video>

<div part="output-container" id="output"></div>
`;class n extends HTMLElement{#t={};#e=null;#i=null;#o=null;#n=null;#a=null;#s=null;#r=null;#l=null;constructor(){super(),this.#t=this.getSupportedConstraints(),this.shadowRoot||this.attachShadow({mode:"open"}).appendChild(o.content.cloneNode(!0))}static get observedAttributes(){return["no-image","facing-mode","camera-resolution","pan","tilt","zoom"]}attributeChangedCallback(t,e,i){if(!this.isConnected)return;let o=this.getTrackCapabilities(),n=this.getTrackSettings();if("no-image"===t&&e!==i&&this.#u(),"facing-mode"===t&&e!==i&&"facingMode"in this.#t){let t=["user","environment"].includes(this.facingMode||"");"facingMode"in n&&t&&(this.stopVideoStream(),this.startVideoStream())}if("camera-resolution"===t&&e!==i&&"string"==typeof this.cameraResolution&&this.cameraResolution.trim().length>0){let[t=0,e=0]=this.cameraResolution.split("x").map(t=>Number(t));if(t>0&&e>0&&"width"in o&&"height"in o){let i=!!(o.width?.min&&o.width?.max)&&t>=o?.width?.min&&t<=o?.width?.max,a=!!(o.height?.min&&o.height?.max)&&e>=o?.height?.min&&e<=o?.height?.max;"width"in n&&"height"in n&&i&&a&&(this.stopVideoStream(),this.startVideoStream())}}if("pan"===t&&e!==i&&"pan"in this.#t){let t=!!("pan"in o&&o.pan?.min&&o.pan?.max)&&this.pan>=o.pan.min&&this.pan<=o.pan.max;"pan"in n&&"number"==typeof this.pan&&t&&this.#h("pan",this.pan)}if("tilt"===t&&e!==i&&"tilt"in this.#t){let t=!!("tilt"in o&&o.tilt?.min&&o.tilt?.max)&&this.tilt>=o.tilt.min&&this.tilt<=o.tilt.max;"tilt"in n&&"number"==typeof this.tilt&&t&&this.#h("tilt",this.tilt)}if("zoom"===t&&e!==i&&"zoom"in this.#t){let t=!!("zoom"in o&&o.zoom?.min&&o.zoom?.max)&&this.zoom>=o.zoom.min&&this.zoom<=o.zoom.max;"zoom"in n&&"number"==typeof this.zoom&&t&&this.#h("zoom",this.zoom)}}connectedCallback(){if(this.#d("autpoPlay"),this.#d("noImage"),this.#d("facingMode"),this.#d("cameraResolution"),this.#d("pan"),this.#d("tilt"),this.#d("zoom"),this.#d("calculateFileSize"),this.#i=this.shadowRoot?.querySelector("canvas")||null,this.#o=this.shadowRoot?.getElementById("output")||null,this.#n=this.shadowRoot?.querySelector("video")||null,this.#a=this.shadowRoot?.querySelector('slot[name="capture-button"]')||null,this.#s=this.#c(),this.#r=this.shadowRoot?.querySelector('slot[name="facing-mode-button"]')||null,this.#l=this.#m(),this.#n?.addEventListener("loadedmetadata",this.#p),this.#a?.addEventListener("slotchange",this.#g),this.#s?.addEventListener("click",this.#b),this.#r?.addEventListener("slotchange",this.#f),this.#l?.addEventListener("click",this.#v),!n.isSupported())return this.dispatchEvent(new CustomEvent(`${e}:error`,{bubbles:!0,composed:!0,detail:{error:{name:"NotSupportedError",message:"Not supported"}}}));this.autoPlay&&this.startVideoStream()}disconnectedCallback(){this.stopVideoStream(),this.#l?.removeEventListener("click",this.#v),this.#s?.removeEventListener("click",this.#b),this.#n?.removeEventListener("canplay",this.#p),this.#a?.removeEventListener("slotchange",this.#g),this.#r?.removeEventListener("slotchange",this.#f)}get autoPlay(){return this.hasAttribute("auto-play")}set autoPlay(t){this.toggleAttribute("auto-play",!!t)}get noImage(){return this.hasAttribute("no-image")}set noImage(t){this.toggleAttribute("no-image",!!t)}get facingMode(){return this.getAttribute("facing-mode")||"user"}set facingMode(t){this.setAttribute("facing-mode",t)}get cameraResolution(){return this.getAttribute("camera-resolution")||""}set cameraResolution(t){this.setAttribute("camera-resolution",t)}get pan(){return Number(this.getAttribute("pan"))||0}set pan(t){this.setAttribute("pan",null!=t?t.toString():t)}get tilt(){return Number(this.getAttribute("tilt"))||0}set tilt(t){this.setAttribute("tilt",null!=t?t.toString():t)}get zoom(){return Number(this.getAttribute("zoom"))||1}set zoom(t){this.setAttribute("zoom",null!=t?t.toString():t)}get loading(){return this.hasAttribute("loading")}get calculateFileSize(){return this.hasAttribute("calculate-file-size")}set calculateFileSize(t){this.toggleAttribute("calculate-file-size",!!t)}#v=t=>{t.preventDefault(),this.loading||(this.facingMode="user"!==this.facingMode&&this.facingMode?"user":"environment")};#b=t=>{t.preventDefault(),this.capture()};#p=t=>{let i=t.target;i.play().then(()=>{this.dispatchEvent(new CustomEvent(`${e}:video-play`,{bubbles:!0,composed:!0,detail:{video:i}}))}).catch(t=>{this.dispatchEvent(new CustomEvent(`${e}:error`,{bubbles:!0,composed:!0,detail:{error:t}}))}).finally(()=>{this.removeAttribute("loading")})};#u(){this.#o&&Array.from(this.#o.childNodes).forEach(t=>t.remove())}#h(e,i){if(!this.#e||!e||!i)return;let[o]=this.#e.getVideoTracks(),n=this.getTrackCapabilities();e in this.getTrackSettings()&&o.applyConstraints({advanced:[{[e]:t(Number(i),n[e]?.min||1,n[e]?.max||1)}]})}#g=t=>{t.target?.name==="capture-button"&&(this.#s?.removeEventListener("click",this.#b),this.#s=this.#c(),this.#s&&(this.#s.addEventListener("click",this.#b),"BUTTON"===this.#s.nodeName||this.#s.hasAttribute("role")||this.#s.setAttribute("role","button")))};#f=t=>{t.target?.name==="facing-mode-button"&&(this.#l?.removeEventListener("click",this.#v),this.#l=this.#m(),this.#l&&(this.#l.addEventListener("click",this.#v),"BUTTON"===this.#l.nodeName||this.#l.hasAttribute("role")||this.#l.setAttribute("role","button")))};#m(){return this.#r&&this.#r.assignedElements({flatten:!0}).find(t=>"BUTTON"===t.nodeName||"facing-mode-button"===t.getAttribute("slot"))||null}#c(){return this.#a&&this.#a.assignedElements({flatten:!0}).find(t=>"BUTTON"===t.nodeName||"capture-button"===t.getAttribute("slot"))||null}#d(t){if(Object.prototype.hasOwnProperty.call(this,t)){let e=this[t];delete this[t],this[t]=e}}async startVideoStream(){if(!n.isSupported()||this.#e)return;this.setAttribute("loading","");let t={video:{facingMode:{ideal:this.facingMode||"user"},pan:!0,tilt:!0,zoom:!0},audio:!1};if("string"==typeof this.cameraResolution&&this.cameraResolution.trim().length>0){let[e=0,i=0]=this.cameraResolution.split("x").map(t=>Number(t));e>0&&i>0&&(t.video.width=e,t.video.height=i)}try{this.#e=await navigator.mediaDevices.getUserMedia(t),this.#n&&(this.#n.srcObject=this.#e),this.#h("pan",this.pan),this.#h("tilt",this.tilt),this.#h("zoom",this.zoom);let e=this.getTrackSettings();"facingMode"in e&&this.#r&&(this.#r.hidden=!1)}catch(t){this.dispatchEvent(new CustomEvent(`${e}:error`,{bubbles:!0,composed:!0,detail:{error:t}}))}finally{this.removeAttribute("loading")}}stopVideoStream(){if(!this.#n||!this.#e)return;let[t]=this.#e.getVideoTracks();t?.stop(),this.#n.srcObject=null,this.#e=null}async capture(){if(!this.loading&&this.#i&&this.#n)try{let t=this.#i.getContext("2d"),i=this.#n.videoWidth,o=this.#n.videoHeight;this.#i.width=i,this.#i.height=o,t?.drawImage(this.#n,0,0,i,o);let n=this.#i.toDataURL("image/png");if("string"==typeof n&&n.includes("data:image")){if(!this.noImage){let t=new Image;t.src=n,t.width=i,t.height=o,t.setAttribute("part","output-image"),this.#u(),this.#o?.appendChild(t)}let t={dataURI:n,width:i,height:o};if(this.calculateFileSize)try{let e=await fetch(n),i=(await e.blob()).size;i&&(t.size=i)}catch(t){}this.dispatchEvent(new CustomEvent(`${e}:success`,{bubbles:!0,composed:!0,detail:t}))}}catch(t){this.dispatchEvent(new CustomEvent(`${e}:error`,{bubbles:!0,composed:!0,detail:{error:t}}))}}getSupportedConstraints(){return n.isSupported()&&navigator.mediaDevices.getSupportedConstraints()||{}}getTrackCapabilities(){if(!this.#e)return{};let[t]=this.#e.getVideoTracks();return t&&"function"==typeof t.getCapabilities&&t.getCapabilities()||{}}getTrackSettings(){if(!this.#e)return{};let[t]=this.#e.getVideoTracks();return t&&"function"==typeof t.getSettings&&t.getSettings()||{}}static isSupported(){return!!navigator.mediaDevices?.getUserMedia}static defineCustomElement(t=e){"undefined"==typeof window||window.customElements.get(t)||window.customElements.define(t,n)}}n.defineCustomElement();export{n as CapturePhoto};
`;var l=class r extends HTMLElement{#r={};#t=null;#h=null;#l=null;#e=null;#c=null;#i=null;#n=null;#s=null;constructor(){super(),this.#r=this.getSupportedConstraints(),this.shadowRoot||this.attachShadow({mode:"open"}).appendChild(d.content.cloneNode(!0))}static get observedAttributes(){return["no-image","facing-mode","camera-resolution","pan","tilt","zoom","torch"]}attributeChangedCallback(t,i,s){if(!this.isConnected)return;let e=this.getTrackCapabilities(),n=this.getTrackSettings();if(t==="no-image"&&i!==s&&this.#g(),t==="facing-mode"&&i!==s&&"facingMode"in this.#r){let o=["user","environment"].includes(this.facingMode||"");"facingMode"in n&&o&&this.#y()}if(t==="camera-resolution"&&i!==s&&typeof this.cameraResolution=="string"&&this.cameraResolution.trim().length>0){let[o=0,c=0]=this.cameraResolution.split("x").map(h=>Number(h));if(o>0&&c>0&&"width"in e&&"height"in e){let h=e.width?.min&&e.width?.max?o>=e?.width?.min&&o<=e?.width?.max:!1,m=e.height?.min&&e.height?.max?c>=e?.height?.min&&c<=e?.height?.max:!1;"width"in n&&"height"in n&&h&&m&&this.#y()}}if(t==="pan"&&i!==s&&"pan"in this.#r){let o="pan"in e&&e.pan?.min&&e.pan?.max?this.pan>=e.pan.min&&this.pan<=e.pan.max:!1;typeof this.pan=="number"&&o&&this.#a("pan",this.pan)}if(t==="tilt"&&i!==s&&"tilt"in this.#r){let o="tilt"in e&&e.tilt?.min&&e.tilt?.max?this.tilt>=e.tilt.min&&this.tilt<=e.tilt.max:!1;typeof this.tilt=="number"&&o&&this.#a("tilt",this.tilt)}if(t==="zoom"&&i!==s&&"zoom"in this.#r){let o="zoom"in e&&e.zoom?.min&&e.zoom?.max?this.zoom>=e.zoom.min&&this.zoom<=e.zoom.max:!1;typeof this.zoom=="number"&&o&&this.#a("zoom",this.zoom)}t==="torch"&&i!==s&&"torch"in this.#r&&this.#a("torch",this.torch)}connectedCallback(){if(this.#o("autpoPlay"),this.#o("noImage"),this.#o("facingMode"),this.#o("cameraResolution"),this.#o("pan"),this.#o("tilt"),this.#o("zoom"),this.#o("torch"),this.#o("calculateFileSize"),this.#h=this.shadowRoot?.querySelector("canvas")||null,this.#l=this.shadowRoot?.getElementById("output")||null,this.#e=this.shadowRoot?.querySelector("video")||null,this.#c=this.shadowRoot?.querySelector('slot[name="capture-button"]')||null,this.#i=this.#v(),this.#n=this.shadowRoot?.querySelector('slot[name="facing-mode-button"]')||null,this.#s=this.#b(),this.#e?.addEventListener("loadedmetadata",this.#m),this.#c?.addEventListener("slotchange",this.#p),this.#i?.addEventListener("click",this.#d),this.#n?.addEventListener("slotchange",this.#f),this.#s?.addEventListener("click",this.#u),!r.isSupported())return this.dispatchEvent(new CustomEvent(`${a}:error`,{bubbles:!0,composed:!0,detail:{error:{name:"NotSupportedError",message:"Not supported"}}}));this.autoPlay&&this.startVideoStream()}disconnectedCallback(){this.stopVideoStream(),this.#s?.removeEventListener("click",this.#u),this.#i?.removeEventListener("click",this.#d),this.#e?.removeEventListener("canplay",this.#m),this.#c?.removeEventListener("slotchange",this.#p),this.#n?.removeEventListener("slotchange",this.#f)}get autoPlay(){return this.hasAttribute("auto-play")}set autoPlay(t){this.toggleAttribute("auto-play",!!t)}get noImage(){return this.hasAttribute("no-image")}set noImage(t){this.toggleAttribute("no-image",!!t)}get facingMode(){return this.getAttribute("facing-mode")||"user"}set facingMode(t){this.setAttribute("facing-mode",t)}get cameraResolution(){return this.getAttribute("camera-resolution")||""}set cameraResolution(t){this.setAttribute("camera-resolution",t)}get pan(){return Number(this.getAttribute("pan"))||0}set pan(t){this.setAttribute("pan",t!=null?t.toString():t)}get tilt(){return Number(this.getAttribute("tilt"))||0}set tilt(t){this.setAttribute("tilt",t!=null?t.toString():t)}get zoom(){return Number(this.getAttribute("zoom"))||1}set zoom(t){this.setAttribute("zoom",t!=null?t.toString():t)}get torch(){return this.hasAttribute("torch")}set torch(t){this.toggleAttribute("torch",!!t)}get loading(){return this.hasAttribute("loading")}get calculateFileSize(){return this.hasAttribute("calculate-file-size")}set calculateFileSize(t){this.toggleAttribute("calculate-file-size",!!t)}#u=t=>{t.preventDefault(),!this.loading&&(this.facingMode=this.facingMode==="user"||!this.facingMode?"environment":"user")};#d=t=>{t.preventDefault(),this.capture()};#m=t=>{let i=t.target;i.play().then(()=>{this.dispatchEvent(new CustomEvent(`${a}:video-play`,{bubbles:!0,composed:!0,detail:{video:i}}))}).catch(s=>{this.dispatchEvent(new CustomEvent(`${a}:error`,{bubbles:!0,composed:!0,detail:{error:s}}))}).finally(()=>{this.removeAttribute("loading")})};#g(){this.#l&&Array.from(this.#l.childNodes).forEach(t=>t.remove())}#a(t,i){if(!this.#t)return;let[s]=this.#t.getVideoTracks(),e=this.getTrackCapabilities(),n=this.getTrackSettings(),o=t==="pan"||t==="tilt"||t==="zoom"?u(Number(i),e[t]?.min||1,e[t]?.max||1):i;t in n&&s.applyConstraints({advanced:[{[t]:o}]}).catch(()=>{})}#p=t=>{t.target?.name==="capture-button"&&(this.#i?.removeEventListener("click",this.#d),this.#i=this.#v(),this.#i&&(this.#i.addEventListener("click",this.#d),this.#i.nodeName!=="BUTTON"&&!this.#i.hasAttribute("role")&&this.#i.setAttribute("role","button")))};#f=t=>{t.target?.name==="facing-mode-button"&&(this.#s?.removeEventListener("click",this.#u),this.#s=this.#b(),this.#s&&(this.#s.addEventListener("click",this.#u),this.#s.nodeName!=="BUTTON"&&!this.#s.hasAttribute("role")&&this.#s.setAttribute("role","button")))};#b(){return this.#n&&this.#n.assignedElements({flatten:!0}).find(t=>t.nodeName==="BUTTON"||t.getAttribute("slot")==="facing-mode-button")||null}#v(){return this.#c&&this.#c.assignedElements({flatten:!0}).find(t=>t.nodeName==="BUTTON"||t.getAttribute("slot")==="capture-button")||null}#y(){this.stopVideoStream(),this.startVideoStream()}#o(t){let i=this;if(Object.prototype.hasOwnProperty.call(i,t)){let s=i[t];delete i[t],i[t]=s}}async startVideoStream(){if(!r.isSupported()||this.#t)return;this.setAttribute("loading","");let t={video:{facingMode:{ideal:this.facingMode||"user"},pan:!0,tilt:!0,zoom:!0,torch:this.torch},audio:!1};if(typeof this.cameraResolution=="string"&&this.cameraResolution.trim().length>0){let[i=0,s=0]=this.cameraResolution.split("x").map(e=>Number(e));i>0&&s>0&&(t.video.width=i,t.video.height=s)}try{this.#t=await navigator.mediaDevices.getUserMedia(t),this.#e&&(this.#e.srcObject=this.#t),this.#a("pan",this.pan),this.#a("tilt",this.tilt),this.#a("zoom",this.zoom),"facingMode"in this.getTrackSettings()&&this.#n&&(this.#n.hidden=!1)}catch(i){this.dispatchEvent(new CustomEvent(`${a}:error`,{bubbles:!0,composed:!0,detail:{error:i}}))}finally{this.removeAttribute("loading")}}stopVideoStream(){if(!this.#e||!this.#t)return;let[t]=this.#t.getVideoTracks();t?.stop(),this.#e.srcObject=null,this.#t=null}async capture(){if(!(this.loading||!this.#h||!this.#e))try{let t=this.#h.getContext("2d"),i=this.#e.videoWidth,s=this.#e.videoHeight;this.#h.width=i,this.#h.height=s,t?.drawImage(this.#e,0,0,i,s);let e=this.#h.toDataURL("image/png");if(typeof e=="string"&&e.includes("data:image")){if(!this.noImage){let o=new Image;o.src=e,o.width=i,o.height=s,o.alt="Captured photo",o.setAttribute("part","output-image"),this.#g(),this.#l?.appendChild(o)}let n={dataURI:e,width:i,height:s};if(this.calculateFileSize)try{let h=(await(await fetch(e)).blob()).size;h&&(n.size=h)}catch{}this.dispatchEvent(new CustomEvent(`${a}:success`,{bubbles:!0,composed:!0,detail:n}))}}catch(t){this.dispatchEvent(new CustomEvent(`${a}:error`,{bubbles:!0,composed:!0,detail:{error:t}}))}}getSupportedConstraints(){return r.isSupported()?navigator.mediaDevices.getSupportedConstraints()||{}:{}}getTrackCapabilities(){if(!this.#t)return{};let[t]=this.#t.getVideoTracks();return t&&typeof t.getCapabilities=="function"?t.getCapabilities()||{}:{}}getTrackSettings(){if(!this.#t)return{};let[t]=this.#t.getVideoTracks();return t&&typeof t.getSettings=="function"?t.getSettings()||{}:{}}static isSupported(){return!!navigator.mediaDevices?.getUserMedia}static defineCustomElement(t=a){typeof window<"u"&&!window.customElements.get(t)&&window.customElements.define(t,r)}};l.defineCustomElement();export{l as CapturePhoto};
//# sourceMappingURL=capture-photo-defined.js.map

@@ -39,2 +39,3 @@ /**

zoom: boolean;
torch: boolean;
};

@@ -60,2 +61,3 @@ /**

* @property {number} zoom - The zoom value of the camera.
* @property {boolean} torch - Whether or not the fill light is connected.
* @property {boolean} loading - Whether or not the video stream is loading.

@@ -71,2 +73,3 @@ * @property {boolean} calculateFileSize - Whether or not to calculate the file size of the captured image.

* @atttribute {number} zoom - Reflects the zoom property.
* @atttribute {boolean} torch - Reflects the torch property.
* @atttribute {boolean} loading - Reflects the loading property.

@@ -178,3 +181,9 @@ * @atttribute {boolean} calculate-file-size - Reflects the calculateFileSize property.

get zoom(): number;
set torch(value: boolean);
/**
* @type {boolean} torch - Whether or not the fill light is connected.
* @attribute torch - Reflects the torch attribute.
*/
get torch(): boolean;
/**
* @type {boolean} loading - Whether or not the video stream is loading.

@@ -181,0 +190,0 @@ * @attribute loading - Reflects the loading attribute.

@@ -1,2 +0,11 @@

let t=(t,e,i)=>(Number.isNaN(e)&&(e=0),Number.isNaN(i)&&(i=0),Math.min(Math.max(t,Math.min(e,i)),Math.max(e,i))),e="capture-photo",i=`
/*!
* @georapbox/capture-photo-element
* A custom element that implements the MediaDevices.getUserMedia() method of the MediaDevices interface to capture a photo in the browser.
*
* @version 4.1.0
* @homepage https://github.com/georapbox/capture-photo-element#readme
* @author George Raptis <georapbox@gmail.com>
* @license MIT
*/
var l=(r,t,i)=>(Number.isNaN(t)&&(t=0),Number.isNaN(i)&&(i=0),Math.min(Math.max(r,Math.min(t,i)),Math.max(t,i)));var a="capture-photo",g=`
:host {

@@ -26,4 +35,4 @@ display: block;

}
`,o=document.createElement("template");o.innerHTML=`
<style>${i}</style>
`,d=document.createElement("template");d.innerHTML=`
<style>${g}</style>

@@ -53,3 +62,3 @@ <video part="video" playsinline></video>

<div part="output-container" id="output"></div>
`;class n extends HTMLElement{#t={};#e=null;#i=null;#o=null;#n=null;#a=null;#s=null;#r=null;#l=null;constructor(){super(),this.#t=this.getSupportedConstraints(),this.shadowRoot||this.attachShadow({mode:"open"}).appendChild(o.content.cloneNode(!0))}static get observedAttributes(){return["no-image","facing-mode","camera-resolution","pan","tilt","zoom"]}attributeChangedCallback(t,e,i){if(!this.isConnected)return;let o=this.getTrackCapabilities(),n=this.getTrackSettings();if("no-image"===t&&e!==i&&this.#u(),"facing-mode"===t&&e!==i&&"facingMode"in this.#t){let t=["user","environment"].includes(this.facingMode||"");"facingMode"in n&&t&&(this.stopVideoStream(),this.startVideoStream())}if("camera-resolution"===t&&e!==i&&"string"==typeof this.cameraResolution&&this.cameraResolution.trim().length>0){let[t=0,e=0]=this.cameraResolution.split("x").map(t=>Number(t));if(t>0&&e>0&&"width"in o&&"height"in o){let i=!!(o.width?.min&&o.width?.max)&&t>=o?.width?.min&&t<=o?.width?.max,a=!!(o.height?.min&&o.height?.max)&&e>=o?.height?.min&&e<=o?.height?.max;"width"in n&&"height"in n&&i&&a&&(this.stopVideoStream(),this.startVideoStream())}}if("pan"===t&&e!==i&&"pan"in this.#t){let t=!!("pan"in o&&o.pan?.min&&o.pan?.max)&&this.pan>=o.pan.min&&this.pan<=o.pan.max;"pan"in n&&"number"==typeof this.pan&&t&&this.#h("pan",this.pan)}if("tilt"===t&&e!==i&&"tilt"in this.#t){let t=!!("tilt"in o&&o.tilt?.min&&o.tilt?.max)&&this.tilt>=o.tilt.min&&this.tilt<=o.tilt.max;"tilt"in n&&"number"==typeof this.tilt&&t&&this.#h("tilt",this.tilt)}if("zoom"===t&&e!==i&&"zoom"in this.#t){let t=!!("zoom"in o&&o.zoom?.min&&o.zoom?.max)&&this.zoom>=o.zoom.min&&this.zoom<=o.zoom.max;"zoom"in n&&"number"==typeof this.zoom&&t&&this.#h("zoom",this.zoom)}}connectedCallback(){if(this.#d("autpoPlay"),this.#d("noImage"),this.#d("facingMode"),this.#d("cameraResolution"),this.#d("pan"),this.#d("tilt"),this.#d("zoom"),this.#d("calculateFileSize"),this.#i=this.shadowRoot?.querySelector("canvas")||null,this.#o=this.shadowRoot?.getElementById("output")||null,this.#n=this.shadowRoot?.querySelector("video")||null,this.#a=this.shadowRoot?.querySelector('slot[name="capture-button"]')||null,this.#s=this.#c(),this.#r=this.shadowRoot?.querySelector('slot[name="facing-mode-button"]')||null,this.#l=this.#m(),this.#n?.addEventListener("loadedmetadata",this.#p),this.#a?.addEventListener("slotchange",this.#g),this.#s?.addEventListener("click",this.#b),this.#r?.addEventListener("slotchange",this.#f),this.#l?.addEventListener("click",this.#v),!n.isSupported())return this.dispatchEvent(new CustomEvent(`${e}:error`,{bubbles:!0,composed:!0,detail:{error:{name:"NotSupportedError",message:"Not supported"}}}));this.autoPlay&&this.startVideoStream()}disconnectedCallback(){this.stopVideoStream(),this.#l?.removeEventListener("click",this.#v),this.#s?.removeEventListener("click",this.#b),this.#n?.removeEventListener("canplay",this.#p),this.#a?.removeEventListener("slotchange",this.#g),this.#r?.removeEventListener("slotchange",this.#f)}get autoPlay(){return this.hasAttribute("auto-play")}set autoPlay(t){this.toggleAttribute("auto-play",!!t)}get noImage(){return this.hasAttribute("no-image")}set noImage(t){this.toggleAttribute("no-image",!!t)}get facingMode(){return this.getAttribute("facing-mode")||"user"}set facingMode(t){this.setAttribute("facing-mode",t)}get cameraResolution(){return this.getAttribute("camera-resolution")||""}set cameraResolution(t){this.setAttribute("camera-resolution",t)}get pan(){return Number(this.getAttribute("pan"))||0}set pan(t){this.setAttribute("pan",null!=t?t.toString():t)}get tilt(){return Number(this.getAttribute("tilt"))||0}set tilt(t){this.setAttribute("tilt",null!=t?t.toString():t)}get zoom(){return Number(this.getAttribute("zoom"))||1}set zoom(t){this.setAttribute("zoom",null!=t?t.toString():t)}get loading(){return this.hasAttribute("loading")}get calculateFileSize(){return this.hasAttribute("calculate-file-size")}set calculateFileSize(t){this.toggleAttribute("calculate-file-size",!!t)}#v=t=>{t.preventDefault(),this.loading||(this.facingMode="user"!==this.facingMode&&this.facingMode?"user":"environment")};#b=t=>{t.preventDefault(),this.capture()};#p=t=>{let i=t.target;i.play().then(()=>{this.dispatchEvent(new CustomEvent(`${e}:video-play`,{bubbles:!0,composed:!0,detail:{video:i}}))}).catch(t=>{this.dispatchEvent(new CustomEvent(`${e}:error`,{bubbles:!0,composed:!0,detail:{error:t}}))}).finally(()=>{this.removeAttribute("loading")})};#u(){this.#o&&Array.from(this.#o.childNodes).forEach(t=>t.remove())}#h(e,i){if(!this.#e||!e||!i)return;let[o]=this.#e.getVideoTracks(),n=this.getTrackCapabilities();e in this.getTrackSettings()&&o.applyConstraints({advanced:[{[e]:t(Number(i),n[e]?.min||1,n[e]?.max||1)}]})}#g=t=>{t.target?.name==="capture-button"&&(this.#s?.removeEventListener("click",this.#b),this.#s=this.#c(),this.#s&&(this.#s.addEventListener("click",this.#b),"BUTTON"===this.#s.nodeName||this.#s.hasAttribute("role")||this.#s.setAttribute("role","button")))};#f=t=>{t.target?.name==="facing-mode-button"&&(this.#l?.removeEventListener("click",this.#v),this.#l=this.#m(),this.#l&&(this.#l.addEventListener("click",this.#v),"BUTTON"===this.#l.nodeName||this.#l.hasAttribute("role")||this.#l.setAttribute("role","button")))};#m(){return this.#r&&this.#r.assignedElements({flatten:!0}).find(t=>"BUTTON"===t.nodeName||"facing-mode-button"===t.getAttribute("slot"))||null}#c(){return this.#a&&this.#a.assignedElements({flatten:!0}).find(t=>"BUTTON"===t.nodeName||"capture-button"===t.getAttribute("slot"))||null}#d(t){if(Object.prototype.hasOwnProperty.call(this,t)){let e=this[t];delete this[t],this[t]=e}}async startVideoStream(){if(!n.isSupported()||this.#e)return;this.setAttribute("loading","");let t={video:{facingMode:{ideal:this.facingMode||"user"},pan:!0,tilt:!0,zoom:!0},audio:!1};if("string"==typeof this.cameraResolution&&this.cameraResolution.trim().length>0){let[e=0,i=0]=this.cameraResolution.split("x").map(t=>Number(t));e>0&&i>0&&(t.video.width=e,t.video.height=i)}try{this.#e=await navigator.mediaDevices.getUserMedia(t),this.#n&&(this.#n.srcObject=this.#e),this.#h("pan",this.pan),this.#h("tilt",this.tilt),this.#h("zoom",this.zoom);let e=this.getTrackSettings();"facingMode"in e&&this.#r&&(this.#r.hidden=!1)}catch(t){this.dispatchEvent(new CustomEvent(`${e}:error`,{bubbles:!0,composed:!0,detail:{error:t}}))}finally{this.removeAttribute("loading")}}stopVideoStream(){if(!this.#n||!this.#e)return;let[t]=this.#e.getVideoTracks();t?.stop(),this.#n.srcObject=null,this.#e=null}async capture(){if(!this.loading&&this.#i&&this.#n)try{let t=this.#i.getContext("2d"),i=this.#n.videoWidth,o=this.#n.videoHeight;this.#i.width=i,this.#i.height=o,t?.drawImage(this.#n,0,0,i,o);let n=this.#i.toDataURL("image/png");if("string"==typeof n&&n.includes("data:image")){if(!this.noImage){let t=new Image;t.src=n,t.width=i,t.height=o,t.setAttribute("part","output-image"),this.#u(),this.#o?.appendChild(t)}let t={dataURI:n,width:i,height:o};if(this.calculateFileSize)try{let e=await fetch(n),i=(await e.blob()).size;i&&(t.size=i)}catch(t){}this.dispatchEvent(new CustomEvent(`${e}:success`,{bubbles:!0,composed:!0,detail:t}))}}catch(t){this.dispatchEvent(new CustomEvent(`${e}:error`,{bubbles:!0,composed:!0,detail:{error:t}}))}}getSupportedConstraints(){return n.isSupported()&&navigator.mediaDevices.getSupportedConstraints()||{}}getTrackCapabilities(){if(!this.#e)return{};let[t]=this.#e.getVideoTracks();return t&&"function"==typeof t.getCapabilities&&t.getCapabilities()||{}}getTrackSettings(){if(!this.#e)return{};let[t]=this.#e.getVideoTracks();return t&&"function"==typeof t.getSettings&&t.getSettings()||{}}static isSupported(){return!!navigator.mediaDevices?.getUserMedia}static defineCustomElement(t=e){"undefined"==typeof window||window.customElements.get(t)||window.customElements.define(t,n)}}export{n as CapturePhoto};
`;var u=class r extends HTMLElement{#r={};#t=null;#h=null;#l=null;#e=null;#c=null;#i=null;#n=null;#s=null;constructor(){super(),this.#r=this.getSupportedConstraints(),this.shadowRoot||this.attachShadow({mode:"open"}).appendChild(d.content.cloneNode(!0))}static get observedAttributes(){return["no-image","facing-mode","camera-resolution","pan","tilt","zoom","torch"]}attributeChangedCallback(t,i,s){if(!this.isConnected)return;let e=this.getTrackCapabilities(),n=this.getTrackSettings();if(t==="no-image"&&i!==s&&this.#g(),t==="facing-mode"&&i!==s&&"facingMode"in this.#r){let o=["user","environment"].includes(this.facingMode||"");"facingMode"in n&&o&&this.#y()}if(t==="camera-resolution"&&i!==s&&typeof this.cameraResolution=="string"&&this.cameraResolution.trim().length>0){let[o=0,c=0]=this.cameraResolution.split("x").map(h=>Number(h));if(o>0&&c>0&&"width"in e&&"height"in e){let h=e.width?.min&&e.width?.max?o>=e?.width?.min&&o<=e?.width?.max:!1,m=e.height?.min&&e.height?.max?c>=e?.height?.min&&c<=e?.height?.max:!1;"width"in n&&"height"in n&&h&&m&&this.#y()}}if(t==="pan"&&i!==s&&"pan"in this.#r){let o="pan"in e&&e.pan?.min&&e.pan?.max?this.pan>=e.pan.min&&this.pan<=e.pan.max:!1;typeof this.pan=="number"&&o&&this.#a("pan",this.pan)}if(t==="tilt"&&i!==s&&"tilt"in this.#r){let o="tilt"in e&&e.tilt?.min&&e.tilt?.max?this.tilt>=e.tilt.min&&this.tilt<=e.tilt.max:!1;typeof this.tilt=="number"&&o&&this.#a("tilt",this.tilt)}if(t==="zoom"&&i!==s&&"zoom"in this.#r){let o="zoom"in e&&e.zoom?.min&&e.zoom?.max?this.zoom>=e.zoom.min&&this.zoom<=e.zoom.max:!1;typeof this.zoom=="number"&&o&&this.#a("zoom",this.zoom)}t==="torch"&&i!==s&&"torch"in this.#r&&this.#a("torch",this.torch)}connectedCallback(){if(this.#o("autpoPlay"),this.#o("noImage"),this.#o("facingMode"),this.#o("cameraResolution"),this.#o("pan"),this.#o("tilt"),this.#o("zoom"),this.#o("torch"),this.#o("calculateFileSize"),this.#h=this.shadowRoot?.querySelector("canvas")||null,this.#l=this.shadowRoot?.getElementById("output")||null,this.#e=this.shadowRoot?.querySelector("video")||null,this.#c=this.shadowRoot?.querySelector('slot[name="capture-button"]')||null,this.#i=this.#v(),this.#n=this.shadowRoot?.querySelector('slot[name="facing-mode-button"]')||null,this.#s=this.#b(),this.#e?.addEventListener("loadedmetadata",this.#m),this.#c?.addEventListener("slotchange",this.#p),this.#i?.addEventListener("click",this.#d),this.#n?.addEventListener("slotchange",this.#f),this.#s?.addEventListener("click",this.#u),!r.isSupported())return this.dispatchEvent(new CustomEvent(`${a}:error`,{bubbles:!0,composed:!0,detail:{error:{name:"NotSupportedError",message:"Not supported"}}}));this.autoPlay&&this.startVideoStream()}disconnectedCallback(){this.stopVideoStream(),this.#s?.removeEventListener("click",this.#u),this.#i?.removeEventListener("click",this.#d),this.#e?.removeEventListener("canplay",this.#m),this.#c?.removeEventListener("slotchange",this.#p),this.#n?.removeEventListener("slotchange",this.#f)}get autoPlay(){return this.hasAttribute("auto-play")}set autoPlay(t){this.toggleAttribute("auto-play",!!t)}get noImage(){return this.hasAttribute("no-image")}set noImage(t){this.toggleAttribute("no-image",!!t)}get facingMode(){return this.getAttribute("facing-mode")||"user"}set facingMode(t){this.setAttribute("facing-mode",t)}get cameraResolution(){return this.getAttribute("camera-resolution")||""}set cameraResolution(t){this.setAttribute("camera-resolution",t)}get pan(){return Number(this.getAttribute("pan"))||0}set pan(t){this.setAttribute("pan",t!=null?t.toString():t)}get tilt(){return Number(this.getAttribute("tilt"))||0}set tilt(t){this.setAttribute("tilt",t!=null?t.toString():t)}get zoom(){return Number(this.getAttribute("zoom"))||1}set zoom(t){this.setAttribute("zoom",t!=null?t.toString():t)}get torch(){return this.hasAttribute("torch")}set torch(t){this.toggleAttribute("torch",!!t)}get loading(){return this.hasAttribute("loading")}get calculateFileSize(){return this.hasAttribute("calculate-file-size")}set calculateFileSize(t){this.toggleAttribute("calculate-file-size",!!t)}#u=t=>{t.preventDefault(),!this.loading&&(this.facingMode=this.facingMode==="user"||!this.facingMode?"environment":"user")};#d=t=>{t.preventDefault(),this.capture()};#m=t=>{let i=t.target;i.play().then(()=>{this.dispatchEvent(new CustomEvent(`${a}:video-play`,{bubbles:!0,composed:!0,detail:{video:i}}))}).catch(s=>{this.dispatchEvent(new CustomEvent(`${a}:error`,{bubbles:!0,composed:!0,detail:{error:s}}))}).finally(()=>{this.removeAttribute("loading")})};#g(){this.#l&&Array.from(this.#l.childNodes).forEach(t=>t.remove())}#a(t,i){if(!this.#t)return;let[s]=this.#t.getVideoTracks(),e=this.getTrackCapabilities(),n=this.getTrackSettings(),o=t==="pan"||t==="tilt"||t==="zoom"?l(Number(i),e[t]?.min||1,e[t]?.max||1):i;t in n&&s.applyConstraints({advanced:[{[t]:o}]}).catch(()=>{})}#p=t=>{t.target?.name==="capture-button"&&(this.#i?.removeEventListener("click",this.#d),this.#i=this.#v(),this.#i&&(this.#i.addEventListener("click",this.#d),this.#i.nodeName!=="BUTTON"&&!this.#i.hasAttribute("role")&&this.#i.setAttribute("role","button")))};#f=t=>{t.target?.name==="facing-mode-button"&&(this.#s?.removeEventListener("click",this.#u),this.#s=this.#b(),this.#s&&(this.#s.addEventListener("click",this.#u),this.#s.nodeName!=="BUTTON"&&!this.#s.hasAttribute("role")&&this.#s.setAttribute("role","button")))};#b(){return this.#n&&this.#n.assignedElements({flatten:!0}).find(t=>t.nodeName==="BUTTON"||t.getAttribute("slot")==="facing-mode-button")||null}#v(){return this.#c&&this.#c.assignedElements({flatten:!0}).find(t=>t.nodeName==="BUTTON"||t.getAttribute("slot")==="capture-button")||null}#y(){this.stopVideoStream(),this.startVideoStream()}#o(t){let i=this;if(Object.prototype.hasOwnProperty.call(i,t)){let s=i[t];delete i[t],i[t]=s}}async startVideoStream(){if(!r.isSupported()||this.#t)return;this.setAttribute("loading","");let t={video:{facingMode:{ideal:this.facingMode||"user"},pan:!0,tilt:!0,zoom:!0,torch:this.torch},audio:!1};if(typeof this.cameraResolution=="string"&&this.cameraResolution.trim().length>0){let[i=0,s=0]=this.cameraResolution.split("x").map(e=>Number(e));i>0&&s>0&&(t.video.width=i,t.video.height=s)}try{this.#t=await navigator.mediaDevices.getUserMedia(t),this.#e&&(this.#e.srcObject=this.#t),this.#a("pan",this.pan),this.#a("tilt",this.tilt),this.#a("zoom",this.zoom),"facingMode"in this.getTrackSettings()&&this.#n&&(this.#n.hidden=!1)}catch(i){this.dispatchEvent(new CustomEvent(`${a}:error`,{bubbles:!0,composed:!0,detail:{error:i}}))}finally{this.removeAttribute("loading")}}stopVideoStream(){if(!this.#e||!this.#t)return;let[t]=this.#t.getVideoTracks();t?.stop(),this.#e.srcObject=null,this.#t=null}async capture(){if(!(this.loading||!this.#h||!this.#e))try{let t=this.#h.getContext("2d"),i=this.#e.videoWidth,s=this.#e.videoHeight;this.#h.width=i,this.#h.height=s,t?.drawImage(this.#e,0,0,i,s);let e=this.#h.toDataURL("image/png");if(typeof e=="string"&&e.includes("data:image")){if(!this.noImage){let o=new Image;o.src=e,o.width=i,o.height=s,o.alt="Captured photo",o.setAttribute("part","output-image"),this.#g(),this.#l?.appendChild(o)}let n={dataURI:e,width:i,height:s};if(this.calculateFileSize)try{let h=(await(await fetch(e)).blob()).size;h&&(n.size=h)}catch{}this.dispatchEvent(new CustomEvent(`${a}:success`,{bubbles:!0,composed:!0,detail:n}))}}catch(t){this.dispatchEvent(new CustomEvent(`${a}:error`,{bubbles:!0,composed:!0,detail:{error:t}}))}}getSupportedConstraints(){return r.isSupported()?navigator.mediaDevices.getSupportedConstraints()||{}:{}}getTrackCapabilities(){if(!this.#t)return{};let[t]=this.#t.getVideoTracks();return t&&typeof t.getCapabilities=="function"?t.getCapabilities()||{}:{}}getTrackSettings(){if(!this.#t)return{};let[t]=this.#t.getVideoTracks();return t&&typeof t.getSettings=="function"?t.getSettings()||{}:{}}static isSupported(){return!!navigator.mediaDevices?.getUserMedia}static defineCustomElement(t=a){typeof window<"u"&&!window.customElements.get(t)&&window.customElements.define(t,r)}};export{u as CapturePhoto};
//# sourceMappingURL=capture-photo.js.map
{
"name": "@georapbox/capture-photo-element",
"version": "4.0.1",
"version": "4.1.0",
"description": "A custom element that implements the MediaDevices.getUserMedia() method of the MediaDevices interface to capture a photo in the browser.",

@@ -10,26 +10,2 @@ "main": "dist/capture-photo.js",

"types": "dist/capture-photo.d.ts",
"targets": {
"capture-photo": {
"context": "browser",
"outputFormat": "esmodule",
"source": "src/capture-photo.js",
"optimize": true,
"isLibrary": true,
"distDir": "dist",
"engines": {
"browsers": "> 0.5%, last 2 versions, not dead"
}
},
"capture-photo-defined": {
"context": "browser",
"outputFormat": "esmodule",
"source": "src/capture-photo-defined.js",
"optimize": true,
"isLibrary": true,
"distDir": "dist",
"engines": {
"browsers": "> 0.5%, last 2 versions, not dead"
}
}
},
"files": [

@@ -40,3 +16,4 @@ "/src",

"scripts": {
"lint": "eslint . --ext .js",
"lint": "eslint",
"format": "prettier --ignore-unknown --write .",
"test": "web-test-runner",

@@ -46,7 +23,9 @@ "test:watch": "npm run test -- --watch",

"types": "tsc --project tsconfig.json",
"dev:parcel": "parcel watch",
"dev": "npm-run-all clean dev:parcel",
"build:parcel": "parcel build",
"build": "npm-run-all clean build:parcel",
"clean": "rimraf dist .parcel-cache",
"dev:esbuild": "node ./scripts/dev.mjs",
"dev": "npm-run-all clean dev:esbuild",
"serve:dev": "web-dev-server --node-resolve --open /docs/ --watch",
"start": "npm-run-all --parallel \"serve:dev -- {1}\" dev",
"build:esbuild": "node ./scripts/build.mjs",
"build": "npm-run-all clean build:esbuild",
"clean": "rimraf dist",
"prepare": "npm-run-all clean lint test build types"

@@ -73,14 +52,21 @@ },

"devDependencies": {
"@eslint/js": "~9.9.0",
"@esm-bundle/chai": "~4.3.4-fix.0",
"@open-wc/testing": "~4.0.0",
"@web/test-runner": "~0.18.0",
"@web/dev-server": "~0.4.6",
"@web/test-runner": "~0.18.3",
"@web/test-runner-playwright": "~0.11.0",
"eslint": "~8.56.0",
"eslint-plugin-wc": "~2.0.4",
"esbuild": "~0.23.1",
"eslint": "~9.9.0",
"eslint-plugin-wc": "~2.1.0",
"globals": "~15.9.0",
"npm-run-all": "~4.1.5",
"parcel": "~2.9.3",
"rimraf": "~5.0.5",
"sinon": "~17.0.1",
"typescript": "~5.3.3"
"prettier": "~3.3.3",
"rimraf": "~6.0.1",
"sinon": "~18.0.0",
"typescript": "~5.5.4"
},
"publishConfig": {
"access": "public"
}
}

@@ -8,3 +8,3 @@ [![npm version](https://img.shields.io/npm/v/@georapbox/capture-photo-element.svg)](https://www.npmjs.com/package/@georapbox/capture-photo-element)

[constraints]: https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia#parameters
[license]: https://georapbox.mit-license.org/@2022
[license]: https://github.com/georapbox/capture-photo-element/blob/main/LICENSE
[changelog]: https://github.com/georapbox/capture-photo-element/blob/main/CHANGELOG.md

@@ -89,2 +89,3 @@

| `zoom`<sup>1</sup> | ✓ | Number | - | `1` | Defines the camera's zoom level if supported by the camera hardware. You can access the min & max supported values for zoom level, using `getTrackCapabilities().zoom`. |
| `torch`<sup>1</sup> | ✓ | Boolean | - | `false` | Determines if the camera's fill light should be turned on if supported by the camera hardware. This works only when `facingMode` is set to `environment`. You can access the supported values for torch, using `getTrackCapabilities().torch`. **NOTE:** The support for this feature is known to be limited and heavily dependent on the device, browser, and operating system. |
| `loading` | ✓ | Boolean | - | `false` | **Readonly**. Indicates if the component is ready for interaction. It is used internally but is also exposed as a readonly property for purposes such as styling, etc. |

@@ -169,4 +170,51 @@ | `calculateFileSize`<br>*`calculate-file-size`* | ✓ | Boolean | - | `false` | Indicates if the component should calculate the file size of the generated image. If set to `true` the file size (in bytes) will be included in the event detail object when the `capture-photo:success` event is fired. The reason for not calculating the file size by default is that it might be an "expensive" operation, especially for large images, therefore it is recommended to set this property to `true` only if you need the file size. |

## Development setup
### Prerequisites
The project requires `Node.js` and `npm` to be installed on your environment. Preferrably, use [nvm](https://github.com/nvm-sh/nvm) Node Version Manager and use the version of Node.js specified in the `.nvmrc` file by running `nvm use`.
### Install dependencies
Install the project dependencies by running the following command.
```sh
npm install
```
### Build for development
Watch for changes and start a development server by running the following command.
```sh
npm start
```
### Linting
Lint the code by running the following command.
```sh
npm run lint
```
### Testing
Run the tests by running any of the following commands.
```sh
npm test
npm run test:watch # watch mode
```
### Build for production
Create a production build by running the following command.
```sh
npm run build
```
## License
[The MIT License (MIT)][license]

@@ -22,3 +22,3 @@ // @ts-check

* @typedef {Object} ExtendedMediaTrackConstraints
* @property {MediaTrackConstraints & {pan: boolean, tilt: boolean, zoom: boolean}} video - The video constraints.
* @property {MediaTrackConstraints & {pan: boolean, tilt: boolean, zoom: boolean, torch: boolean}} video - The video constraints.
* @property {MediaTrackConstraints | boolean} audio - The audio constraints.

@@ -31,3 +31,3 @@ */

const styles = /* css */`
const styles = /* css */ `
:host {

@@ -61,3 +61,3 @@ display: block;

template.innerHTML = /* html */`
template.innerHTML = /* html */ `
<style>${styles}</style>

@@ -104,2 +104,3 @@

* @property {number} zoom - The zoom value of the camera.
* @property {boolean} torch - Whether or not the fill light is connected.
* @property {boolean} loading - Whether or not the video stream is loading.

@@ -115,2 +116,3 @@ * @property {boolean} calculateFileSize - Whether or not to calculate the file size of the captured image.

* @atttribute {number} zoom - Reflects the zoom property.
* @atttribute {boolean} torch - Reflects the torch property.
* @atttribute {boolean} loading - Reflects the loading property.

@@ -186,3 +188,3 @@ * @atttribute {boolean} calculate-file-size - Reflects the calculateFileSize property.

static get observedAttributes() {
return ['no-image', 'facing-mode', 'camera-resolution', 'pan', 'tilt', 'zoom'];
return ['no-image', 'facing-mode', 'camera-resolution', 'pan', 'tilt', 'zoom', 'torch'];
}

@@ -214,4 +216,3 @@

if ('facingMode' in trackSettings && isValidFacingMode) {
this.stopVideoStream();
this.startVideoStream();
this.#restartVideoStream();
}

@@ -225,13 +226,14 @@ }

if (width > 0 && height > 0 && 'width' in trackCapabilities && 'height' in trackCapabilities) {
const widthInAllowedRange = trackCapabilities.width?.min && trackCapabilities.width?.max
? width >= trackCapabilities?.width?.min && width <= trackCapabilities?.width?.max
: false;
const widthInAllowedRange =
trackCapabilities.width?.min && trackCapabilities.width?.max
? width >= trackCapabilities?.width?.min && width <= trackCapabilities?.width?.max
: false;
const heightInAllowedRange = trackCapabilities.height?.min && trackCapabilities.height?.max
? height >= trackCapabilities?.height?.min && height <= trackCapabilities?.height?.max
: false;
const heightInAllowedRange =
trackCapabilities.height?.min && trackCapabilities.height?.max
? height >= trackCapabilities?.height?.min && height <= trackCapabilities?.height?.max
: false;
if ('width' in trackSettings && 'height' in trackSettings && widthInAllowedRange && heightInAllowedRange) {
this.stopVideoStream();
this.startVideoStream();
this.#restartVideoStream();
}

@@ -243,8 +245,9 @@ }

if (name === 'pan' && oldValue !== newValue && 'pan' in this.#supportedConstraints) {
const panInAllowedRange = 'pan' in trackCapabilities && trackCapabilities.pan?.min && trackCapabilities.pan?.max
? this.pan >= trackCapabilities.pan.min && this.pan <= trackCapabilities.pan.max
: false;
const panInAllowedRange =
'pan' in trackCapabilities && trackCapabilities.pan?.min && trackCapabilities.pan?.max
? this.pan >= trackCapabilities.pan.min && this.pan <= trackCapabilities.pan.max
: false;
if ('pan' in trackSettings && typeof this.pan === 'number' && panInAllowedRange) {
this.#applyPTZ('pan', this.pan);
if (typeof this.pan === 'number' && panInAllowedRange) {
this.#applyConstraint('pan', this.pan);
}

@@ -254,8 +257,9 @@ }

if (name === 'tilt' && oldValue !== newValue && 'tilt' in this.#supportedConstraints) {
const tiltInAllowedRange = 'tilt' in trackCapabilities && trackCapabilities.tilt?.min && trackCapabilities.tilt?.max
? this.tilt >= trackCapabilities.tilt.min && this.tilt <= trackCapabilities.tilt.max
: false;
const tiltInAllowedRange =
'tilt' in trackCapabilities && trackCapabilities.tilt?.min && trackCapabilities.tilt?.max
? this.tilt >= trackCapabilities.tilt.min && this.tilt <= trackCapabilities.tilt.max
: false;
if ('tilt' in trackSettings && typeof this.tilt === 'number' && tiltInAllowedRange) {
this.#applyPTZ('tilt', this.tilt);
if (typeof this.tilt === 'number' && tiltInAllowedRange) {
this.#applyConstraint('tilt', this.tilt);
}

@@ -265,10 +269,15 @@ }

if (name === 'zoom' && oldValue !== newValue && 'zoom' in this.#supportedConstraints) {
const zoomInAllowedRange = 'zoom' in trackCapabilities && trackCapabilities.zoom?.min && trackCapabilities.zoom?.max
? this.zoom >= trackCapabilities.zoom.min && this.zoom <= trackCapabilities.zoom.max
: false;
const zoomInAllowedRange =
'zoom' in trackCapabilities && trackCapabilities.zoom?.min && trackCapabilities.zoom?.max
? this.zoom >= trackCapabilities.zoom.min && this.zoom <= trackCapabilities.zoom.max
: false;
if ('zoom' in trackSettings && typeof this.zoom === 'number' && zoomInAllowedRange) {
this.#applyPTZ('zoom', this.zoom);
if (typeof this.zoom === 'number' && zoomInAllowedRange) {
this.#applyConstraint('zoom', this.zoom);
}
}
if (name === 'torch' && oldValue !== newValue && 'torch' in this.#supportedConstraints) {
this.#applyConstraint('torch', this.torch);
}
}

@@ -287,2 +296,3 @@

this.#upgradeProperty('zoom');
this.#upgradeProperty('torch');
this.#upgradeProperty('calculateFileSize');

@@ -305,12 +315,14 @@

if (!CapturePhoto.isSupported()) {
return this.dispatchEvent(new CustomEvent(`${COMPONENT_NAME}:error`, {
bubbles: true,
composed: true,
detail: {
error: {
name: 'NotSupportedError',
message: 'Not supported'
return this.dispatchEvent(
new CustomEvent(`${COMPONENT_NAME}:error`, {
bubbles: true,
composed: true,
detail: {
error: {
name: 'NotSupportedError',
message: 'Not supported'
}
}
}
}));
})
);
}

@@ -420,2 +432,14 @@

/**
* @type {boolean} torch - Whether or not the fill light is connected.
* @attribute torch - Reflects the torch attribute.
*/
get torch() {
return this.hasAttribute('torch');
}
set torch(value) {
this.toggleAttribute('torch', !!value);
}
/**
* @type {boolean} loading - Whether or not the video stream is loading.

@@ -473,17 +497,27 @@ * @attribute loading - Reflects the loading attribute.

video.play().then(() => {
this.dispatchEvent(new CustomEvent(`${COMPONENT_NAME}:video-play`, {
bubbles: true,
composed: true,
detail: { video }
}));
}).catch(/** @param {Error} error */error => {
this.dispatchEvent(new CustomEvent(`${COMPONENT_NAME}:error`, {
bubbles: true,
composed: true,
detail: { error }
}));
}).finally(() => {
this.removeAttribute('loading');
});
video
.play()
.then(() => {
this.dispatchEvent(
new CustomEvent(`${COMPONENT_NAME}:video-play`, {
bubbles: true,
composed: true,
detail: { video }
})
);
})
.catch(
/** @param {Error} error */ error => {
this.dispatchEvent(
new CustomEvent(`${COMPONENT_NAME}:error`, {
bubbles: true,
composed: true,
detail: { error }
})
);
}
)
.finally(() => {
this.removeAttribute('loading');
});
};

@@ -503,9 +537,9 @@

/**
* Applies the pan, tilt or zoom constraint.
* Applies a constraint to the video track.
*
* @param {'pan' | 'tilt' | 'zoom'} constraintName - The name of the constraint.
* @param {number} constraintValue - The value of the constraint.
* @param {string} constraint - The name of the constraint.
* @param {any} value - The value of the constraint.
*/
#applyPTZ(constraintName, constraintValue) {
if (!this.#stream || !constraintName || !constraintValue) {
#applyConstraint(constraint, value) {
if (!this.#stream) {
return;

@@ -519,8 +553,15 @@ }

if (constraintName in trackSettings) {
track.applyConstraints({
advanced: [{
[constraintName]: clamp(Number(constraintValue), trackCapabilities[constraintName]?.min || 1, trackCapabilities[constraintName]?.max || 1)
}]
});
const constraintValue =
constraint === 'pan' || constraint === 'tilt' || constraint === 'zoom'
? clamp(Number(value), trackCapabilities[constraint]?.min || 1, trackCapabilities[constraint]?.max || 1)
: value;
if (constraint in trackSettings) {
track
.applyConstraints({
advanced: [{ [constraint]: constraintValue }]
})
.catch(() => {
// Fail silently...
});
}

@@ -579,5 +620,7 @@ }

return this.#facingModeButtonSlot.assignedElements({ flatten: true }).find(el => {
return el.nodeName === 'BUTTON' || el.getAttribute('slot') === 'facing-mode-button';
}) || null;
return (
this.#facingModeButtonSlot.assignedElements({ flatten: true }).find(el => {
return el.nodeName === 'BUTTON' || el.getAttribute('slot') === 'facing-mode-button';
}) || null
);
}

@@ -595,8 +638,18 @@

return this.#captureButtonSlot.assignedElements({ flatten: true }).find(el => {
return el.nodeName === 'BUTTON' || el.getAttribute('slot') === 'capture-button';
}) || null;
return (
this.#captureButtonSlot.assignedElements({ flatten: true }).find(el => {
return el.nodeName === 'BUTTON' || el.getAttribute('slot') === 'capture-button';
}) || null
);
}
/**
* Restarts the video stream.
*/
#restartVideoStream() {
this.stopVideoStream();
this.startVideoStream();
}
/**
* This is to safe guard against cases where, for instance, a framework may have added the element to the page and

@@ -608,3 +661,3 @@ * set a value on one of its properties, but lazy loaded its definition. Without this guard, the upgraded element would

*
* @param {'autpoPlay' | 'noImage' | 'facingMode' | 'cameraResolution' | 'pan' | 'tilt' | 'zoom' | 'calculateFileSize'} prop
* @param {'autpoPlay' | 'noImage' | 'facingMode' | 'cameraResolution' | 'pan' | 'tilt' | 'zoom' | 'calculateFileSize' | 'torch'} prop
*/

@@ -642,3 +695,4 @@ #upgradeProperty(prop) {

tilt: true,
zoom: true
zoom: true,
torch: this.torch
},

@@ -664,5 +718,5 @@ audio: false

this.#applyPTZ('pan', this.pan);
this.#applyPTZ('tilt', this.tilt);
this.#applyPTZ('zoom', this.zoom);
this.#applyConstraint('pan', this.pan);
this.#applyConstraint('tilt', this.tilt);
this.#applyConstraint('zoom', this.zoom);

@@ -675,7 +729,9 @@ const trackSettings = this.getTrackSettings();

} catch (error) {
this.dispatchEvent(new CustomEvent(`${COMPONENT_NAME}:error`, {
bubbles: true,
composed: true,
detail: { error }
}));
this.dispatchEvent(
new CustomEvent(`${COMPONENT_NAME}:error`, {
bubbles: true,
composed: true,
detail: { error }
})
);
} finally {

@@ -726,2 +782,3 @@ this.removeAttribute('loading');

image.height = height;
image.alt = 'Captured photo';
image.setAttribute('part', 'output-image');

@@ -744,3 +801,3 @@ this.#emptyOutputElement();

}
} catch (err) {
} catch {
// Fail silently...

@@ -750,14 +807,18 @@ }

this.dispatchEvent(new CustomEvent(`${COMPONENT_NAME}:success`, {
this.dispatchEvent(
new CustomEvent(`${COMPONENT_NAME}:success`, {
bubbles: true,
composed: true,
detail: eventDetail
})
);
}
} catch (error) {
this.dispatchEvent(
new CustomEvent(`${COMPONENT_NAME}:error`, {
bubbles: true,
composed: true,
detail: eventDetail
}));
}
} catch (error) {
this.dispatchEvent(new CustomEvent(`${COMPONENT_NAME}:error`, {
bubbles: true,
composed: true,
detail: { error }
}));
detail: { error }
})
);
}

@@ -764,0 +825,0 @@ }

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc