@wcstack/camera 4.12.0 → 4.14.0

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.
package/dist/auto.min.js CHANGED
@@ -1,2 +1,2 @@
1
- const e={tagNames:{camera:"wcs-camera",recorder:"wcs-recorder"}};var t="@wcstack/camera",i="4.12.0";const s=new Set(["camera","microphone","geolocation","midi","clipboard-read","clipboard-write","screen-wake-lock","idle-detection","accelerometer","gyroscope","magnetometer","ambient-light-sensor","display-capture"]);function r(e){const t=globalThis;if(!1===t.isSecureContext)return"insecure-context";if(!s.has(e))return null;const i=t.document?.permissionsPolicy??t.document?.featurePolicy;if(void 0===i||"function"!=typeof i.allowsFeature)return null;try{return i.allowsFeature(e)?null:"policy-blocked"}catch{return null}}function n(e,t,i){return"insecure-context"===i?`${e} needs a secure context (https:, or http://localhost), and this page is not one.`:`${e} is turned off for this page by a Permissions-Policy: the server's Permissions-Policy header, or an <iframe> without allow="${t}". The browser's site settings cannot change that.`}function a(){return"undefined"!=typeof navigator&&!!navigator.mediaDevices&&"function"==typeof navigator.mediaDevices.getUserMedia}function o(e){if(e&&"object"==typeof e&&"name"in e){const t=String(e.name)||"Error";return{name:t,message:"message"in e&&e.message?String(e.message):`Media request failed: ${t}.`}}return{name:"Error",message:"Media request failed."}}function c(){const e=r("camera");return{name:"unsupported",message:"insecure-context"===e?n("getUserMedia","camera",e):"getUserMedia is not available in this browser."}}function d(e){if(e)for(const t of e.getTracks())t.stop()}async function h(){if(!a()||"function"!=typeof navigator.mediaDevices.enumerateDevices)return[];try{return(await navigator.mediaDevices.enumerateDevices()).filter(e=>"videoinput"===e.kind).map(e=>({deviceId:e.deviceId,label:e.label,groupId:e.groupId,kind:e.kind}))}catch{return[]}}class u{_name;_onChange;_status=null;_gen=0;_subscribed=!1;constructor(e,t){this._name=e,this._onChange=t}observe(){if(this._subscribed)return Promise.resolve();if("undefined"==typeof navigator||!navigator.permissions||"function"!=typeof navigator.permissions.query)return this._onChange("unsupported"),Promise.resolve();this._subscribed=!0;const e=++this._gen;return navigator.permissions.query({name:this._name}).then(t=>{e===this._gen&&(this._status=t,this._onChange(t.state),t.addEventListener("change",this._onStatusChange))},()=>{e===this._gen&&this._onChange("unsupported")})}dispose(){this._subscribed=!1,this._gen++,this._status&&(this._status.removeEventListener("change",this._onStatusChange),this._status=null)}_onStatusChange=e=>{const t=e.target;this._onChange(t.state)}}const l=new WeakMap;function m(e){const t=(l.get(e)??0)-1;t>0?l.set(e,t):l.delete(e)}const _="capability-missing",g="not-allowed",p="not-found",v="not-readable",b="invalid-argument",f="invalid-state",w="aborted",y="media-error";function P(e){const{name:t,message:i}=e;return"unsupported"===t?{code:_,phase:"probe",recoverable:!1,message:i}:"NotAllowedError"===t||"SecurityError"===t?{code:g,phase:"start",recoverable:!1,message:i}:"NotFoundError"===t?{code:p,phase:"start",recoverable:!1,message:i}:"NotReadableError"===t?{code:v,phase:"start",recoverable:!1,message:i}:"OverconstrainedError"===t||"NotSupportedError"===t?{code:b,phase:"start",recoverable:!1,message:i}:"NoStreamError"===t?{code:f,phase:"start",recoverable:!1,message:i}:"AbortError"===t?{code:w,phase:"execute",recoverable:!0,message:i}:{code:y,phase:"execute",recoverable:!1,message:i}}class S extends EventTarget{static wcBindable={protocol:"wc-bindable",version:1,properties:[{name:"active",event:"wcs-camera:active-changed",semantics:"state"},{name:"permission",event:"wcs-camera:permission-changed",semantics:"state"},{name:"audioPermission",event:"wcs-camera:audio-permission-changed",semantics:"state"},{name:"deviceId",event:"wcs-camera:device-changed",semantics:"state"},{name:"devices",event:"wcs-camera:devices-changed",semantics:"state"},{name:"error",event:"wcs-camera:error",semantics:"state"},{name:"errorInfo",event:"wcs-camera:error-info-changed",semantics:"state"},{name:"streamReady",event:"wcs-camera:stream-ready",semantics:"handle",getter:e=>e.detail},{name:"ended",event:"wcs-camera:ended",semantics:"event",getter:e=>e.detail}],commands:[{name:"start"},{name:"stop"},{name:"switchCamera"}]};_target;_active=!1;_permission="prompt";_audioPermission=null;_deviceId=null;_devices=[];_error=null;_errorInfo=null;_stream=null;_desired=!1;_constraints={};_gen=0;_subscribed=!1;_camWatcher=null;_micWatcher=null;_ready=Promise.resolve();_toldKeepAlive=!1;constructor(e){super(),this._target=e??this}get active(){return this._active}get permission(){return this._permission}get audioPermission(){return this._audioPermission}get deviceId(){return this._deviceId}get devices(){return this._devices}get error(){return this._error}get errorInfo(){return this._errorInfo}get ready(){return this._ready}_setActive(e){this._active!==e&&(this._active=e,this._dispatch("wcs-camera:active-changed",e))}_setPermission(e){this._permission!==e&&(this._permission=e,this._dispatch("wcs-camera:permission-changed",e))}_setAudioPermission(e){this._audioPermission!==e&&(this._audioPermission=e,this._dispatch("wcs-camera:audio-permission-changed",e))}_setDeviceId(e){this._deviceId!==e&&(this._deviceId=e,this._dispatch("wcs-camera:device-changed",e))}_setDevices(e){this._devicesEqual(this._devices,e)||(this._devices=e,this._dispatch("wcs-camera:devices-changed",e))}_setError(e){null===e&&null===this._error||(this._error=e,this._commitErrorInfo(null===e?null:P(e)),this._dispatch("wcs-camera:error",e))}_commitErrorInfo(e){this._errorInfo=e,this._dispatch("wcs-camera:error-info-changed",e)}_dispatch(e,t){this._target.dispatchEvent(new CustomEvent(e,{detail:t,bubbles:!0}))}_devicesEqual(e,t){if(e.length!==t.length)return!1;for(let i=0;i<e.length;i++)if(e[i].deviceId!==t[i].deviceId||e[i].label!==t[i].label)return!1;return!0}observe(e){return this._constraints={...e},this._subscribed?this._ready=this._ready.then(()=>this._reconcileAudioWatcher()):(this._subscribed=!0,this._ready=this._initPermissions()),this._ready}start(){this._desired=!0,this._restart()}stop(){this._desired=!1,this._release()}switchCamera(){const e="environment"===this._constraints.facingMode?"user":"environment";this._constraints={...this._constraints,facingMode:e,deviceId:void 0},this._desired&&this._restart()}suspend(){var e;this._gen++,this._stream&&(e=this._stream,l.has(e)&&this._warnKeepAlive(),this._release())}_warnKeepAlive(){this._toldKeepAlive||(this._toldKeepAlive=!0,console.warn("[@wcstack/camera] [wcs/camera-keep-alive-missing] The page was hidden while this camera's stream was being recorded, so the camera stopped the stream and the recording ended with it. Keep the camera on while recording: bind keepAlive to the recording flag (keepAlive: <recording path>). (Said once per element.)",this._target))}resume(){this._desired&&!this._active&&this._restart()}dispose(){this._subscribed=!1,this._gen++,this._desired=!1,this._release(),a()&&"function"==typeof navigator.mediaDevices.removeEventListener&&navigator.mediaDevices.removeEventListener("devicechange",this._onDeviceChange),this._camWatcher?.dispose(),this._micWatcher?.dispose(),this._camWatcher=null,this._micWatcher=null}_initPermissions(){if(!a())return this._setPermission("unsupported"),Promise.resolve();const e=[];return null!==r("camera")?this._setPermission("unsupported"):(this._camWatcher=new u("camera",e=>this._setPermission(e)),e.push(this._camWatcher.observe())),this._constraints.audio?e.push(this._watchMicrophone()):this._setAudioPermission(null),"function"==typeof navigator.mediaDevices.addEventListener&&navigator.mediaDevices.addEventListener("devicechange",this._onDeviceChange),Promise.all(e).then(()=>{})}_onDeviceChange=()=>{h().then(e=>{this._subscribed&&this._setDevices(e)})};_reconcileAudioWatcher(){return this._constraints.audio&&!this._micWatcher&&a()?this._watchMicrophone():(this._constraints.audio||!this._micWatcher&&null===this._audioPermission||(this._micWatcher?.dispose(),this._micWatcher=null,this._setAudioPermission(null)),Promise.resolve())}_watchMicrophone(){return null!==r("microphone")?(this._setAudioPermission("unsupported"),Promise.resolve()):(this._micWatcher=new u("microphone",e=>this._setAudioPermission(e)),this._micWatcher.observe())}_restart(){this._release(),this._acquire()}async _acquire(){const e=++this._gen,t=a()?function(e){const t=r("camera");if(null!==t)return{device:"camera",error:{name:"unsupported",message:n("The camera","camera",t)}};const i=e?r("microphone"):null;return null!==i?{device:"microphone",error:{name:"unsupported",message:n("The microphone","microphone",i)}}:null}(!!this._constraints.audio):null;if(null!==t)return this._setError(t.error),"camera"===t.device?this._setPermission("unsupported"):this._setAudioPermission("unsupported"),this._desired=!1,void this._setActive(!1);const i=function(e){const t={};return e.deviceId?t.deviceId={exact:e.deviceId}:e.facingMode&&(t.facingMode=e.facingMode),"number"==typeof e.width&&(t.width=e.width),"number"==typeof e.height&&(t.height=e.height),{video:!(Object.keys(t).length>0)||t,audio:!0===e.audio}}(this._constraints),{stream:s,error:u}=await async function(e){if(!a())return{error:c()};try{return{stream:await navigator.mediaDevices.getUserMedia(e)}}catch(e){return{error:o(e)}}}(i);if(e!==this._gen)return void d(s??null);if(u)return this._setError(u),"NotAllowedError"===u.name?(this._setPermission("denied"),this._desired=!1):"unsupported"===u.name&&(this._setPermission("unsupported"),this._desired=!1),void this._setActive(!1);const l=s;this._stream=l;for(const e of l.getTracks())e.addEventListener("ended",this._onTrackEnded);this._setError(null),this._setPermission("granted"),this._constraints.audio&&l.getAudioTracks().length>0&&this._setAudioPermission("granted"),this._updateDeviceId(l),this._setActive(!0),this._dispatch("wcs-camera:stream-ready",l);const m=await h();e===this._gen&&this._setDevices(m)}_release(){if(this._stream){for(const e of this._stream.getTracks())e.removeEventListener("ended",this._onTrackEnded);d(this._stream),this._stream=null,this._setActive(!1)}}_onTrackEnded=()=>{this._release(),this._dispatch("wcs-camera:ended",null)};_updateDeviceId(e){const t=e.getVideoTracks()[0];if(t&&"function"==typeof t.getSettings){const e=t.getSettings();this._setDeviceId(e.deviceId??null)}}}function A(e,t){let i=Object.getPrototypeOf(e);for(;null!==i;){const e=Object.getOwnPropertyDescriptor(i,t);if(void 0!==e)return"function"==typeof e.get||"function"==typeof e.set;i=Object.getPrototypeOf(i)}return!1}const k=new WeakSet;function E(e,t,i){if(k.has(e))return;k.add(e);const s=e.localName??"element";console.warn(`[wcs/input-as-attribute] <${s}> has the attribute ${t}="${i}": an object was written as an attribute, so the element did not receive it. A framework does that when the property is set before the element's definition loads (React 19), or when told to (Vue's .attr). Load the definition before rendering, or assign the property through a ref (Vue: .prop). (Said once per element.)`,e)}function T(e){const t=e.constructor?.wcBindable,i=t?.inputs;if(void 0===i)return;const s=e.getAttribute;for(const t of i){const i=t.name,r="function"==typeof s?s.call(e,i.toLowerCase()):null;if(null!==r&&r.startsWith("[object ")&&E(e,i,r),!Object.prototype.hasOwnProperty.call(e,i))continue;if(!A(e,i))continue;const n=e,a=n[i];delete n[i],n[i]=a}}const I=new WeakMap;function C(e,t){let i=I.get(e);return void 0===i&&(i=new Map,I.set(e,i)),i.has(t)||i.set(t,e.getAttribute(t)),i.get(t)}function R(e,t,i){null===i?e.removeAttribute(t):e.setAttribute(t,i)}function L(e,t,i){const s=C(e,t);R(e,t,void 0===i?s:null===i?null:String(i))}function M(e,t,i){const s=C(e,t);R(e,t,void 0===i?s:i?"":null)}const N=":host{display:inline-block}video{display:block;width:100%;height:100%}";let j;class B extends HTMLElement{static hasConnectedCallbackPromise=!0;static wcBindable={...S.wcBindable,inputs:[{name:"audio",attribute:"audio"},{name:"facingMode",attribute:"facing-mode"},{name:"deviceId",attribute:"device-id"},{name:"width",attribute:"width"},{name:"height",attribute:"height"},{name:"autostart",attribute:"autostart"},{name:"keepAlive",attribute:"keep-alive"}],commands:S.wcBindable.commands};static observedAttributes=["facing-mode","device-id","audio","width","height"];_core;_video;_connectedCallbackPromise=Promise.resolve();_connectResolve=null;_acquirePending=!1;_autostartCancelled=!1;_connected=!1;_batchingAttrs=!1;_internals=null;constructor(){super(),this._core=new S(this);const e=this.attachShadow({mode:"open"});!function(e){if(void 0===j)try{j=new CSSStyleSheet,j.replaceSync(N)}catch{j=null}if(null!==j&&Array.isArray(e.adoptedStyleSheets))return void(e.adoptedStyleSheets=[j]);const t=document.createElement("style");t.textContent=N,e.append(t)}(e),this._video=document.createElement("video"),this._video.autoplay=!0,this._video.muted=!0,this._video.setAttribute("playsinline",""),this._video.setAttribute("part","video"),e.append(this._video),this.addEventListener("wcs-camera:stream-ready",this._onStreamReady),this.addEventListener("wcs-camera:active-changed",this._onActiveChanged),this._internals=this._initInternals(),this._wireStates({"wcs-camera:active-changed":e=>({active:!0===e}),"wcs-camera:error":e=>({error:null!=e})})}get debugStates(){return this._internals?[...this._internals.states]:[]}_initInternals(){try{if("function"!=typeof this.attachInternals)return null;const e=this.attachInternals();return e.states.add("wcs-probe"),e.states.delete("wcs-probe"),e}catch{return null}}_wireStates(e){if(null===this._internals)return;const t=this._internals.states;for(const[i,s]of Object.entries(e))this.addEventListener(i,e=>{const i=this.hasAttribute("debug-states");for(const[r,n]of Object.entries(s(e.detail))){try{n?t.add(r):t.delete(r)}catch{}i&&this.toggleAttribute(`data-wcs-state-${r}`,n)}})}get audio(){return this.hasAttribute("audio")}set audio(e){M(this,"audio",e)}get facingMode(){return"environment"===this.getAttribute("facing-mode")?"environment":"user"}set facingMode(e){L(this,"facing-mode",e)}get deviceId(){return this._core.deviceId??this.getAttribute("device-id")??""}set deviceId(e){L(this,"device-id",e)}get width(){return this._numberAttr("width")}set width(e){L(this,"width",e)}get height(){return this._numberAttr("height")}set height(e){L(this,"height",e)}get autostart(){return this.hasAttribute("autostart")}set autostart(e){M(this,"autostart",e)}get keepAlive(){return this.hasAttribute("keep-alive")}set keepAlive(e){M(this,"keep-alive",e)}get videoElement(){return this._video}get active(){return this._core.active}get permission(){return this._core.permission}get audioPermission(){return this._core.audioPermission}get devices(){return this._core.devices}get error(){return this._core.error}get errorInfo(){return this._core.errorInfo}get connectedCallbackPromise(){return this._connectedCallbackPromise}start(){this._connected&&this._core.observe(this._constraints()),this._core.start()}stop(){null!==this._connectResolve&&(this._autostartCancelled=!0),this._core.stop()}switchCamera(){const e="environment"===this.facingMode?"user":"environment";this._batchingAttrs=!0;try{this.removeAttribute("device-id"),this.setAttribute("facing-mode",e)}finally{this._batchingAttrs=!1}this._core.observe(this._constraints()),this._core.active&&this._core.start()}_numberAttr(e){const t=this.getAttribute(e);if(null===t||""===t.trim())return NaN;const i=Number(t);return Number.isFinite(i)?i:NaN}_constraints(){const e={audio:this.audio,facingMode:this.facingMode},t=this.getAttribute("device-id");return t&&(e.deviceId=t),Number.isFinite(this.width)&&(e.width=this.width),Number.isFinite(this.height)&&(e.height=this.height),e}_onStreamReady=e=>{this._video.srcObject=e.detail};_onActiveChanged=e=>{!1===e.detail&&(this._video.srcObject=null)};_scheduleAcquire(){this._acquirePending||(this._acquirePending=!0,queueMicrotask(()=>{this._acquirePending=!1;const e=this._connectResolve;if(this._connectResolve=null,!this._connected)return;const t=this._core.observe(this._constraints());null!==e?(this.autostart&&!this._autostartCancelled&&this._core.start(),this._autostartCancelled=!1,e(t)):this._core.active&&this._core.start()}))}connectedCallback(){T(this),this._connected=!0,this._connectedCallbackPromise=new Promise(e=>{this._connectResolve=e}),this._scheduleAcquire(),document.addEventListener("visibilitychange",this._onVisibilityChange)}disconnectedCallback(){this._connected=!1,this._connectResolve?.(),this._connectResolve=null,this._autostartCancelled=!1,document.removeEventListener("visibilitychange",this._onVisibilityChange),this._core.dispose()}attributeChangedCallback(e,t,i){this._connected&&t!==i&&(this._batchingAttrs||this._scheduleAcquire())}_onVisibilityChange=()=>{this.keepAlive||("hidden"===document.visibilityState?this._core.suspend():this._core.resume())}}class U extends EventTarget{static wcBindable={protocol:"wc-bindable",version:1,properties:[{name:"recording",event:"wcs-recorder:recording-changed",semantics:"state"},{name:"paused",event:"wcs-recorder:paused-changed",semantics:"state"},{name:"duration",event:"wcs-recorder:duration-changed",semantics:"state"},{name:"mimeType",event:"wcs-recorder:mimetype-changed",semantics:"state"},{name:"blob",event:"wcs-recorder:recorded",semantics:"state",getter:e=>e.detail?.blob??null},{name:"objectURL",event:"wcs-recorder:recorded",semantics:"state",getter:e=>e.detail?.objectURL??null},{name:"error",event:"wcs-recorder:error",semantics:"state"},{name:"errorInfo",event:"wcs-recorder:error-info-changed",semantics:"state"},{name:"recorded",event:"wcs-recorder:recorded",semantics:"event",getter:e=>e.detail},{name:"dataavailable",event:"wcs-recorder:dataavailable",semantics:"event",getter:e=>e.detail}],commands:[{name:"attachStream"},{name:"start"},{name:"stop"},{name:"pause"},{name:"resume"}]};_target;_recording=!1;_paused=!1;_duration=0;_mimeType="";_blob=null;_objectURL=null;_error=null;_errorInfo=null;_recorder=null;_stream=null;_recordingStream=null;_timeslice=!1;_startTime=0;_gen=0;_closing=null;_ready=Promise.resolve();_toldNotReady=!1;constructor(e){super(),this._target=e??this}get recording(){return this._recording}get paused(){return this._paused}get duration(){return this._duration}get mimeType(){return this._mimeType}get blob(){return this._blob}get objectURL(){return this._objectURL}get error(){return this._error}get errorInfo(){return this._errorInfo}get ready(){return this._ready}_setRecording(e){this._recording!==e&&(this._recording=e,this._dispatch("wcs-recorder:recording-changed",e))}_setPaused(e){this._paused!==e&&(this._paused=e,this._dispatch("wcs-recorder:paused-changed",e))}_setDuration(e){this._duration!==e&&(this._duration=e,this._dispatch("wcs-recorder:duration-changed",e))}_setMimeType(e){this._mimeType!==e&&(this._mimeType=e,this._dispatch("wcs-recorder:mimetype-changed",e))}_setError(e){null===e&&null===this._error||(this._error=e,this._commitErrorInfo(null===e?null:P(e)),this._dispatch("wcs-recorder:error",e))}_commitErrorInfo(e){this._errorInfo=e,this._dispatch("wcs-recorder:error-info-changed",e)}_dispatch(e,t){this._target.dispatchEvent(new CustomEvent(e,{detail:t,bubbles:!0}))}attachStream(e){this._stream=e,e&&(this._toldNotReady=!1)}start(e={}){if("undefined"==typeof globalThis||"function"!=typeof globalThis.MediaRecorder)return void this._setError({name:"unsupported",message:"MediaRecorder is not available in this environment."});if(!this._stream)return this._setError({name:"NoStreamError",message:"No stream attached. Wire a camera's stream-ready to attachStream first."}),void this._warnNotReady();if(this._recording)return;const t={};let i;e.mimeType&&this._isTypeSupported(e.mimeType)&&(t.mimeType=e.mimeType),"number"==typeof e.audioBitsPerSecond&&(t.audioBitsPerSecond=e.audioBitsPerSecond),"number"==typeof e.videoBitsPerSecond&&(t.videoBitsPerSecond=e.videoBitsPerSecond);try{i=new MediaRecorder(this._stream,t)}catch(e){return void this._setError(o(e))}const s=++this._gen,r=[],n=this._stream;this._timeslice="number"==typeof e.timeslice&&e.timeslice>0;const a=()=>null!==this._closing&&this._closing.gen===s;i.ondataavailable=e=>{if((s===this._gen||a())&&e.data&&e.data.size>0){if(r.push(e.data),s!==this._gen)return;!this._mimeType&&e.data.type&&this._setMimeType(e.data.type),this._timeslice&&this._dispatch("wcs-recorder:dataavailable",e.data)}},i.onstart=()=>{s===this._gen&&i.mimeType&&this._setMimeType(i.mimeType)},i.onstop=()=>{if(m(n),this._recordingStream===n&&(this._recordingStream=null),a()){const{mimeType:e,duration:t}=this._closing;return this._closing=null,void this._assembleBlob(r,e,t)}s===this._gen&&(this._paused||this._setDuration(this._elapsed()),this._assembleBlob(r,this._mimeType,this._duration),this._setPaused(!1),this._setRecording(!1))},i.onerror=e=>{if(s!==this._gen)return;const t=e.error;this._setError(o(t??{name:"RecorderError"}))},i.onpause=()=>{s===this._gen&&(this._setDuration(this._elapsed()),this._setPaused(!0))},i.onresume=()=>{s===this._gen&&(this._startTime=this._now()-this._duration,this._setPaused(!1))},this._recorder=i,this._setError(null),this._setMimeType(i.mimeType||t.mimeType||""),this._startTime=this._now(),this._setDuration(0),i.start(this._timeslice?e.timeslice:void 0),function(e){l.set(e,(l.get(e)??0)+1)}(n),this._recordingStream=n,this._setRecording(!0)}_warnNotReady(){this._toldNotReady||(this._toldNotReady=!0,console.warn("[@wcstack/camera] [wcs/command-not-ready] start() was refused: no stream is attached, so nothing is recorded. It goes to `error` too. Wire a camera's stream to the recorder first. (Said once until a stream is attached again.)",this._target))}stop(){this._recorder&&"inactive"!==this._recorder.state&&this._recorder.stop()}pause(){this._recorder&&"recording"===this._recorder.state&&this._recorder.pause()}resume(){this._recorder&&"paused"===this._recorder.state&&this._recorder.resume()}observe(){return this._ready}dispose(){const e=this._recorder,t=null!==e&&"inactive"!==e.state;if(t&&(this._paused||this._setDuration(this._elapsed()),this._closing={gen:this._gen,mimeType:this._mimeType,duration:this._duration}),this._gen++,this._recorder=null,this._revokeUrl(),this._stream=null,this._setPaused(!1),this._setRecording(!1),t)try{e.stop()}catch{this._closing=null,this._recordingStream&&m(this._recordingStream),this._recordingStream=null}}_assembleBlob(e,t,i){const s=t||e[0]?.type||"",r=new Blob(e,s?{type:s}:void 0);this._revokeUrl();const n=this._createUrl(r);this._blob=r,this._objectURL=n;const a={blob:r,objectURL:n,mimeType:s,duration:i};this._dispatch("wcs-recorder:recorded",a)}_revokeUrl(){this._objectURL&&"undefined"!=typeof URL&&"function"==typeof URL.revokeObjectURL&&URL.revokeObjectURL(this._objectURL),this._objectURL=null}_createUrl(e){return"undefined"!=typeof URL&&"function"==typeof URL.createObjectURL?URL.createObjectURL(e):""}_isTypeSupported(e){return globalThis.MediaRecorder.isTypeSupported(e)}_now(){return performance.now()}_elapsed(){return Math.max(0,Math.round(this._now()-this._startTime))}}class D extends HTMLElement{static hasConnectedCallbackPromise=!0;static wcBindable={...U.wcBindable,inputs:[{name:"mimeType",attribute:"mime-type"},{name:"timeslice",attribute:"timeslice"},{name:"audioBitsPerSecond",attribute:"audio-bits"},{name:"videoBitsPerSecond",attribute:"video-bits"}],commands:U.wcBindable.commands};_core;_connectedCallbackPromise=Promise.resolve();_internals=null;constructor(){super(),this._core=new U(this),this._internals=this._initInternals(),this._wireStates({"wcs-recorder:recording-changed":e=>({recording:!0===e}),"wcs-recorder:paused-changed":e=>({paused:!0===e}),"wcs-recorder:error":e=>({error:null!=e})})}get debugStates(){return this._internals?[...this._internals.states]:[]}_initInternals(){try{if("function"!=typeof this.attachInternals)return null;const e=this.attachInternals();return e.states.add("wcs-probe"),e.states.delete("wcs-probe"),e}catch{return null}}_wireStates(e){if(null===this._internals)return;const t=this._internals.states;for(const[i,s]of Object.entries(e))this.addEventListener(i,e=>{const i=this.hasAttribute("debug-states");for(const[r,n]of Object.entries(s(e.detail))){try{n?t.add(r):t.delete(r)}catch{}i&&this.toggleAttribute(`data-wcs-state-${r}`,n)}})}get connectedCallbackPromise(){return this._connectedCallbackPromise}get mimeType(){return this._core.mimeType}set mimeType(e){L(this,"mime-type",e)}get timeslice(){return this._numberAttr("timeslice")}set timeslice(e){L(this,"timeslice",e)}get audioBitsPerSecond(){return this._numberAttr("audio-bits")}set audioBitsPerSecond(e){L(this,"audio-bits",e)}get videoBitsPerSecond(){return this._numberAttr("video-bits")}set videoBitsPerSecond(e){L(this,"video-bits",e)}get recording(){return this._core.recording}get paused(){return this._core.paused}get duration(){return this._core.duration}get blob(){return this._core.blob}get objectURL(){return this._core.objectURL}get error(){return this._core.error}get errorInfo(){return this._core.errorInfo}attachStream(e){this._core.attachStream(e)}start(){this._core.start(this._options())}stop(){this._core.stop()}pause(){this._core.pause()}resume(){this._core.resume()}_numberAttr(e){const t=this.getAttribute(e);if(null===t||""===t.trim())return NaN;const i=Number(t);return Number.isFinite(i)?i:NaN}_options(){const e={},t=this.getAttribute("mime-type")??"";return t&&(e.mimeType=t),Number.isFinite(this.timeslice)&&(e.timeslice=this.timeslice),Number.isFinite(this.audioBitsPerSecond)&&(e.audioBitsPerSecond=this.audioBitsPerSecond),Number.isFinite(this.videoBitsPerSecond)&&(e.videoBitsPerSecond=this.videoBitsPerSecond),e}connectedCallback(){T(this),this.style.display="none",this._connectedCallbackPromise=this._core.observe()}disconnectedCallback(){this._core.dispose()}}const W=Symbol.for("wcstack.package"),O=new WeakSet;function q(e,t){Object.defineProperty(e,W,{value:t,configurable:!0})}function $(e,t,i,s,r){if(void 0!==s&&(i===s||i.prototype instanceof s))return;const n=i[W];if(n===r||O.has(e))return;O.add(e);const a=r.slice(0,r.lastIndexOf("@"));console.warn(`[${a}] [wcs/package-twice] <${t}> is already defined by ${n??`another copy of ${a} that does not name its version`}; this copy, ${r}, does nothing. Load each package once.`)}function x(s=customElements){!function(e,t,i){for(const[s,r]of i){const i=e.get(s);void 0===i?(q(r,t),e.define(s,r)):$(e,s,i,r,t)}}(s,`${t}@${i}`,[[e.tagNames.camera,B],[e.tagNames.recorder,D]])}var F;x(F);
1
+ const e={tagNames:{camera:"wcs-camera",recorder:"wcs-recorder"}};var t="@wcstack/camera",i="4.14.0";const s=new Set(["camera","microphone","geolocation","midi","clipboard-read","clipboard-write","screen-wake-lock","idle-detection","accelerometer","gyroscope","magnetometer","ambient-light-sensor","display-capture"]);function r(e){const t=globalThis;if(!1===t.isSecureContext)return"insecure-context";if(!s.has(e))return null;const i=t.document?.permissionsPolicy??t.document?.featurePolicy;if(void 0===i||"function"!=typeof i.allowsFeature)return null;try{return i.allowsFeature(e)?null:"policy-blocked"}catch{return null}}function n(e,t,i){return"insecure-context"===i?`${e} needs a secure context (https:, or http://localhost), and this page is not one.`:`${e} is turned off for this page by a Permissions-Policy: the server's Permissions-Policy header, or an <iframe> without allow="${t}". The browser's site settings cannot change that.`}function a(){return"undefined"!=typeof navigator&&!!navigator.mediaDevices&&"function"==typeof navigator.mediaDevices.getUserMedia}function o(e){if(e&&"object"==typeof e&&"name"in e){const t=String(e.name)||"Error";return{name:t,message:"message"in e&&e.message?String(e.message):`Media request failed: ${t}.`}}return{name:"Error",message:"Media request failed."}}function c(){const e=r("camera");return{name:"unsupported",message:"insecure-context"===e?n("getUserMedia","camera",e):"getUserMedia is not available in this browser."}}function d(e){if(e)for(const t of e.getTracks())t.stop()}async function h(){if(!a()||"function"!=typeof navigator.mediaDevices.enumerateDevices)return[];try{return(await navigator.mediaDevices.enumerateDevices()).filter(e=>"videoinput"===e.kind).map(e=>({deviceId:e.deviceId,label:e.label,groupId:e.groupId,kind:e.kind}))}catch{return[]}}class u{_name;_onChange;_status=null;_gen=0;_subscribed=!1;constructor(e,t){this._name=e,this._onChange=t}observe(){if(this._subscribed)return Promise.resolve();if("undefined"==typeof navigator||!navigator.permissions||"function"!=typeof navigator.permissions.query)return this._onChange("unsupported"),Promise.resolve();this._subscribed=!0;const e=++this._gen;return navigator.permissions.query({name:this._name}).then(t=>{e===this._gen&&(this._status=t,this._onChange(t.state),t.addEventListener("change",this._onStatusChange))},()=>{e===this._gen&&this._onChange("unsupported")})}dispose(){this._subscribed=!1,this._gen++,this._status&&(this._status.removeEventListener("change",this._onStatusChange),this._status=null)}_onStatusChange=e=>{const t=e.target;this._onChange(t.state)}}const l=new WeakMap;function m(e){const t=(l.get(e)??0)-1;t>0?l.set(e,t):l.delete(e)}const _="capability-missing",g="not-allowed",p="not-found",v="not-readable",b="invalid-argument",f="invalid-state",w="aborted",y="media-error";function P(e){const{name:t,message:i}=e;return"unsupported"===t?{code:_,phase:"probe",recoverable:!1,message:i}:"NotAllowedError"===t||"SecurityError"===t?{code:g,phase:"start",recoverable:!1,message:i}:"NotFoundError"===t?{code:p,phase:"start",recoverable:!1,message:i}:"NotReadableError"===t?{code:v,phase:"start",recoverable:!1,message:i}:"OverconstrainedError"===t||"NotSupportedError"===t?{code:b,phase:"start",recoverable:!1,message:i}:"NoStreamError"===t?{code:f,phase:"start",recoverable:!1,message:i}:"AbortError"===t?{code:w,phase:"execute",recoverable:!0,message:i}:{code:y,phase:"execute",recoverable:!1,message:i}}class S extends EventTarget{static wcBindable={protocol:"wc-bindable",version:1,properties:[{name:"active",event:"wcs-camera:active-changed",semantics:"state"},{name:"permission",event:"wcs-camera:permission-changed",semantics:"state"},{name:"audioPermission",event:"wcs-camera:audio-permission-changed",semantics:"state"},{name:"deviceId",event:"wcs-camera:device-changed",semantics:"state"},{name:"devices",event:"wcs-camera:devices-changed",semantics:"state"},{name:"error",event:"wcs-camera:error",semantics:"state"},{name:"errorInfo",event:"wcs-camera:error-info-changed",semantics:"state"},{name:"streamReady",event:"wcs-camera:stream-ready",semantics:"handle",getter:e=>e.detail},{name:"ended",event:"wcs-camera:ended",semantics:"event",getter:e=>e.detail}],commands:[{name:"start"},{name:"stop"},{name:"switchCamera"}]};_target;_active=!1;_permission="prompt";_audioPermission=null;_deviceId=null;_devices=[];_error=null;_errorInfo=null;_stream=null;_desired=!1;_constraints={};_gen=0;_subscribed=!1;_camWatcher=null;_micWatcher=null;_ready=Promise.resolve();_toldKeepAlive=!1;constructor(e){super(),this._target=e??this}get active(){return this._active}get permission(){return this._permission}get audioPermission(){return this._audioPermission}get deviceId(){return this._deviceId}get devices(){return this._devices}get error(){return this._error}get errorInfo(){return this._errorInfo}get ready(){return this._ready}_setActive(e){this._active!==e&&(this._active=e,this._dispatch("wcs-camera:active-changed",e))}_setPermission(e){this._permission!==e&&(this._permission=e,this._dispatch("wcs-camera:permission-changed",e))}_setAudioPermission(e){this._audioPermission!==e&&(this._audioPermission=e,this._dispatch("wcs-camera:audio-permission-changed",e))}_setDeviceId(e){this._deviceId!==e&&(this._deviceId=e,this._dispatch("wcs-camera:device-changed",e))}_setDevices(e){this._devicesEqual(this._devices,e)||(this._devices=e,this._dispatch("wcs-camera:devices-changed",e))}_setError(e){null===e&&null===this._error||(this._error=e,this._commitErrorInfo(null===e?null:P(e)),this._dispatch("wcs-camera:error",e))}_commitErrorInfo(e){this._errorInfo=e,this._dispatch("wcs-camera:error-info-changed",e)}_dispatch(e,t){this._target.dispatchEvent(new CustomEvent(e,{detail:t,bubbles:!0}))}_devicesEqual(e,t){if(e.length!==t.length)return!1;for(let i=0;i<e.length;i++)if(e[i].deviceId!==t[i].deviceId||e[i].label!==t[i].label)return!1;return!0}observe(e){return this._constraints={...e},this._subscribed?this._ready=this._ready.then(()=>this._reconcileAudioWatcher()):(this._subscribed=!0,this._ready=this._initPermissions()),this._ready}start(){this._desired=!0,this._restart()}stop(){this._desired=!1,this._release()}switchCamera(){const e="environment"===this._constraints.facingMode?"user":"environment";this._constraints={...this._constraints,facingMode:e,deviceId:void 0},this._desired&&this._restart()}suspend(){var e;this._gen++,this._stream&&(e=this._stream,l.has(e)&&this._warnKeepAlive(),this._release())}_warnKeepAlive(){this._toldKeepAlive||(this._toldKeepAlive=!0,console.warn("[@wcstack/camera] [wcs/camera-keep-alive-missing] The page was hidden while this camera's stream was being recorded, so the camera stopped the stream and the recording ended with it. Keep the camera on while recording: bind keepAlive to the recording flag (keepAlive: <recording path>). (Said once per element.)",this._target))}resume(){this._desired&&!this._active&&this._restart()}dispose(){this._subscribed=!1,this._gen++,this._desired=!1,this._release(),a()&&"function"==typeof navigator.mediaDevices.removeEventListener&&navigator.mediaDevices.removeEventListener("devicechange",this._onDeviceChange),this._camWatcher?.dispose(),this._micWatcher?.dispose(),this._camWatcher=null,this._micWatcher=null}_initPermissions(){if(!a())return this._setPermission("unsupported"),Promise.resolve();const e=[];return null!==r("camera")?this._setPermission("unsupported"):(this._camWatcher=new u("camera",e=>this._setPermission(e)),e.push(this._camWatcher.observe())),this._constraints.audio?e.push(this._watchMicrophone()):this._setAudioPermission(null),"function"==typeof navigator.mediaDevices.addEventListener&&navigator.mediaDevices.addEventListener("devicechange",this._onDeviceChange),Promise.all(e).then(()=>{})}_onDeviceChange=()=>{h().then(e=>{this._subscribed&&this._setDevices(e)})};_reconcileAudioWatcher(){return this._constraints.audio&&!this._micWatcher&&a()?this._watchMicrophone():(this._constraints.audio||!this._micWatcher&&null===this._audioPermission||(this._micWatcher?.dispose(),this._micWatcher=null,this._setAudioPermission(null)),Promise.resolve())}_watchMicrophone(){return null!==r("microphone")?(this._setAudioPermission("unsupported"),Promise.resolve()):(this._micWatcher=new u("microphone",e=>this._setAudioPermission(e)),this._micWatcher.observe())}_restart(){this._release(),this._acquire()}async _acquire(){const e=++this._gen,t=a()?function(e){const t=r("camera");if(null!==t)return{device:"camera",error:{name:"unsupported",message:n("The camera","camera",t)}};const i=e?r("microphone"):null;return null!==i?{device:"microphone",error:{name:"unsupported",message:n("The microphone","microphone",i)}}:null}(!!this._constraints.audio):null;if(null!==t)return this._setError(t.error),"camera"===t.device?this._setPermission("unsupported"):this._setAudioPermission("unsupported"),this._desired=!1,void this._setActive(!1);const i=function(e){const t={};return e.deviceId?t.deviceId={exact:e.deviceId}:e.facingMode&&(t.facingMode=e.facingMode),"number"==typeof e.width&&(t.width=e.width),"number"==typeof e.height&&(t.height=e.height),{video:!(Object.keys(t).length>0)||t,audio:!0===e.audio}}(this._constraints),{stream:s,error:u}=await async function(e){if(!a())return{error:c()};try{return{stream:await navigator.mediaDevices.getUserMedia(e)}}catch(e){return{error:o(e)}}}(i);if(e!==this._gen)return void d(s??null);if(u)return this._setError(u),"NotAllowedError"===u.name?(this._setPermission("denied"),this._desired=!1):"unsupported"===u.name&&(this._setPermission("unsupported"),this._desired=!1),void this._setActive(!1);const l=s;this._stream=l;for(const e of l.getTracks())e.addEventListener("ended",this._onTrackEnded);this._setError(null),this._setPermission("granted"),this._constraints.audio&&l.getAudioTracks().length>0&&this._setAudioPermission("granted"),this._updateDeviceId(l),this._setActive(!0),this._dispatch("wcs-camera:stream-ready",l);const m=await h();e===this._gen&&this._setDevices(m)}_release(){if(this._stream){for(const e of this._stream.getTracks())e.removeEventListener("ended",this._onTrackEnded);d(this._stream),this._stream=null,this._setActive(!1)}}_onTrackEnded=()=>{this._release(),this._dispatch("wcs-camera:ended",null)};_updateDeviceId(e){const t=e.getVideoTracks()[0];if(t&&"function"==typeof t.getSettings){const e=t.getSettings();this._setDeviceId(e.deviceId??null)}}}function A(e,t){let i=Object.getPrototypeOf(e);for(;null!==i;){const e=Object.getOwnPropertyDescriptor(i,t);if(void 0!==e)return"function"==typeof e.get||"function"==typeof e.set;i=Object.getPrototypeOf(i)}return!1}const k=new WeakSet;function E(e,t,i){if(k.has(e))return;k.add(e);const s=e.localName??"element";console.warn(`[wcs/input-as-attribute] <${s}> has the attribute ${t}="${i}": an object was written as an attribute, so the element did not receive it. A framework does that when the property is set before the element's definition loads (React 19), or when told to (Vue's .attr). Load the definition before rendering, or assign the property through a ref (Vue: .prop). (Said once per element.)`,e)}function T(e){const t=e.constructor?.wcBindable,i=t?.inputs;if(void 0===i)return;const s=e.getAttribute;for(const t of i){const i=t.name,r="function"==typeof s?s.call(e,i.toLowerCase()):null;if(null!==r&&r.startsWith("[object ")&&E(e,i,r),!Object.prototype.hasOwnProperty.call(e,i))continue;if(!A(e,i))continue;const n=e,a=n[i];delete n[i],n[i]=a}}const I=new WeakMap;function C(e,t){let i=I.get(e);return void 0===i&&(i=new Map,I.set(e,i)),i.has(t)||i.set(t,e.getAttribute(t)),i.get(t)}function R(e,t,i){null===i?e.removeAttribute(t):e.setAttribute(t,i)}function L(e,t,i){const s=C(e,t);R(e,t,void 0===i?s:null===i?null:String(i))}function M(e,t,i){const s=C(e,t);R(e,t,void 0===i?s:i?"":null)}const N=":host{display:inline-block}video{display:block;width:100%;height:100%}";let j;class B extends HTMLElement{static hasConnectedCallbackPromise=!0;static wcBindable={...S.wcBindable,inputs:[{name:"audio",attribute:"audio"},{name:"facingMode",attribute:"facing-mode"},{name:"deviceId",attribute:"device-id"},{name:"width",attribute:"width"},{name:"height",attribute:"height"},{name:"autostart",attribute:"autostart"},{name:"keepAlive",attribute:"keep-alive"}],commands:S.wcBindable.commands};static observedAttributes=["facing-mode","device-id","audio","width","height"];_core;_video;_connectedCallbackPromise=Promise.resolve();_connectResolve=null;_acquirePending=!1;_autostartCancelled=!1;_connected=!1;_batchingAttrs=!1;_internals=null;constructor(){super(),this._core=new S(this);const e=this.attachShadow({mode:"open"});!function(e){if(void 0===j)try{j=new CSSStyleSheet,j.replaceSync(N)}catch{j=null}if(null!==j&&Array.isArray(e.adoptedStyleSheets))return void(e.adoptedStyleSheets=[j]);const t=document.createElement("style");t.textContent=N,e.append(t)}(e),this._video=document.createElement("video"),this._video.autoplay=!0,this._video.muted=!0,this._video.setAttribute("playsinline",""),this._video.setAttribute("part","video"),e.append(this._video),this.addEventListener("wcs-camera:stream-ready",this._onStreamReady),this.addEventListener("wcs-camera:active-changed",this._onActiveChanged),this._internals=this._initInternals(),this._wireStates({"wcs-camera:active-changed":e=>({active:!0===e}),"wcs-camera:error":e=>({error:null!=e})})}get debugStates(){return this._internals?[...this._internals.states]:[]}_initInternals(){try{if("function"!=typeof this.attachInternals)return null;const e=this.attachInternals();return e.states.add("wcs-probe"),e.states.delete("wcs-probe"),e}catch{return null}}_wireStates(e){if(null===this._internals)return;const t=this._internals.states;for(const[i,s]of Object.entries(e))this.addEventListener(i,e=>{const i=this.hasAttribute("debug-states");for(const[r,n]of Object.entries(s(e.detail))){try{n?t.add(r):t.delete(r)}catch{}i&&this.toggleAttribute(`data-wcs-state-${r}`,n)}})}get audio(){return this.hasAttribute("audio")}set audio(e){M(this,"audio",e)}get facingMode(){return"environment"===this.getAttribute("facing-mode")?"environment":"user"}set facingMode(e){L(this,"facing-mode",e)}get deviceId(){return this._core.deviceId??this.getAttribute("device-id")??""}set deviceId(e){L(this,"device-id",e)}get width(){return this._numberAttr("width")}set width(e){L(this,"width",e)}get height(){return this._numberAttr("height")}set height(e){L(this,"height",e)}get autostart(){return this.hasAttribute("autostart")}set autostart(e){M(this,"autostart",e)}get keepAlive(){return this.hasAttribute("keep-alive")}set keepAlive(e){M(this,"keep-alive",e)}get videoElement(){return this._video}get active(){return this._core.active}get permission(){return this._core.permission}get audioPermission(){return this._core.audioPermission}get devices(){return this._core.devices}get error(){return this._core.error}get errorInfo(){return this._core.errorInfo}get connectedCallbackPromise(){return this._connectedCallbackPromise}start(){this._connected&&this._core.observe(this._constraints()),this._core.start()}stop(){null!==this._connectResolve&&(this._autostartCancelled=!0),this._core.stop()}switchCamera(){const e="environment"===this.facingMode?"user":"environment";this._batchingAttrs=!0;try{this.removeAttribute("device-id"),this.setAttribute("facing-mode",e)}finally{this._batchingAttrs=!1}this._core.observe(this._constraints()),this._core.active&&this._core.start()}_numberAttr(e){const t=this.getAttribute(e);if(null===t||""===t.trim())return NaN;const i=Number(t);return Number.isFinite(i)?i:NaN}_constraints(){const e={audio:this.audio,facingMode:this.facingMode},t=this.getAttribute("device-id");return t&&(e.deviceId=t),Number.isFinite(this.width)&&(e.width=this.width),Number.isFinite(this.height)&&(e.height=this.height),e}_onStreamReady=e=>{this._video.srcObject=e.detail};_onActiveChanged=e=>{!1===e.detail&&(this._video.srcObject=null)};_scheduleAcquire(){this._acquirePending||(this._acquirePending=!0,queueMicrotask(()=>{this._acquirePending=!1;const e=this._connectResolve;if(this._connectResolve=null,!this._connected)return;const t=this._core.observe(this._constraints());null!==e?(this.autostart&&!this._autostartCancelled&&this._core.start(),this._autostartCancelled=!1,e(t)):this._core.active&&this._core.start()}))}connectedCallback(){T(this),this._connected=!0,this._connectedCallbackPromise=new Promise(e=>{this._connectResolve=e}),this._scheduleAcquire(),document.addEventListener("visibilitychange",this._onVisibilityChange)}disconnectedCallback(){this._connected=!1,this._connectResolve?.(),this._connectResolve=null,this._autostartCancelled=!1,document.removeEventListener("visibilitychange",this._onVisibilityChange),this._core.dispose()}attributeChangedCallback(e,t,i){this._connected&&t!==i&&(this._batchingAttrs||this._scheduleAcquire())}_onVisibilityChange=()=>{this.keepAlive||("hidden"===document.visibilityState?this._core.suspend():this._core.resume())}}class U extends EventTarget{static wcBindable={protocol:"wc-bindable",version:1,properties:[{name:"recording",event:"wcs-recorder:recording-changed",semantics:"state"},{name:"paused",event:"wcs-recorder:paused-changed",semantics:"state"},{name:"duration",event:"wcs-recorder:duration-changed",semantics:"state"},{name:"mimeType",event:"wcs-recorder:mimetype-changed",semantics:"state"},{name:"blob",event:"wcs-recorder:recorded",semantics:"state",getter:e=>e.detail?.blob??null},{name:"objectURL",event:"wcs-recorder:recorded",semantics:"state",getter:e=>e.detail?.objectURL??null},{name:"error",event:"wcs-recorder:error",semantics:"state"},{name:"errorInfo",event:"wcs-recorder:error-info-changed",semantics:"state"},{name:"recorded",event:"wcs-recorder:recorded",semantics:"event",getter:e=>e.detail},{name:"dataavailable",event:"wcs-recorder:dataavailable",semantics:"event",getter:e=>e.detail}],commands:[{name:"attachStream"},{name:"start"},{name:"stop"},{name:"pause"},{name:"resume"}]};_target;_recording=!1;_paused=!1;_duration=0;_mimeType="";_blob=null;_objectURL=null;_error=null;_errorInfo=null;_recorder=null;_stream=null;_recordingStream=null;_timeslice=!1;_startTime=0;_gen=0;_closing=null;_ready=Promise.resolve();_toldNotReady=!1;constructor(e){super(),this._target=e??this}get recording(){return this._recording}get paused(){return this._paused}get duration(){return this._duration}get mimeType(){return this._mimeType}get blob(){return this._blob}get objectURL(){return this._objectURL}get error(){return this._error}get errorInfo(){return this._errorInfo}get ready(){return this._ready}_setRecording(e){this._recording!==e&&(this._recording=e,this._dispatch("wcs-recorder:recording-changed",e))}_setPaused(e){this._paused!==e&&(this._paused=e,this._dispatch("wcs-recorder:paused-changed",e))}_setDuration(e){this._duration!==e&&(this._duration=e,this._dispatch("wcs-recorder:duration-changed",e))}_setMimeType(e){this._mimeType!==e&&(this._mimeType=e,this._dispatch("wcs-recorder:mimetype-changed",e))}_setError(e){null===e&&null===this._error||(this._error=e,this._commitErrorInfo(null===e?null:P(e)),this._dispatch("wcs-recorder:error",e))}_commitErrorInfo(e){this._errorInfo=e,this._dispatch("wcs-recorder:error-info-changed",e)}_dispatch(e,t){this._target.dispatchEvent(new CustomEvent(e,{detail:t,bubbles:!0}))}attachStream(e){this._stream=e,e&&(this._toldNotReady=!1)}start(e={}){if("undefined"==typeof globalThis||"function"!=typeof globalThis.MediaRecorder)return void this._setError({name:"unsupported",message:"MediaRecorder is not available in this environment."});if(!this._stream)return this._setError({name:"NoStreamError",message:"No stream attached. Wire a camera's stream-ready to attachStream first."}),void this._warnNotReady();if(this._recording)return;const t={};let i;e.mimeType&&this._isTypeSupported(e.mimeType)&&(t.mimeType=e.mimeType),"number"==typeof e.audioBitsPerSecond&&(t.audioBitsPerSecond=e.audioBitsPerSecond),"number"==typeof e.videoBitsPerSecond&&(t.videoBitsPerSecond=e.videoBitsPerSecond);try{i=new MediaRecorder(this._stream,t)}catch(e){return void this._setError(o(e))}const s=++this._gen,r=[],n=this._stream;this._timeslice="number"==typeof e.timeslice&&e.timeslice>0;const a=()=>null!==this._closing&&this._closing.gen===s;i.ondataavailable=e=>{if((s===this._gen||a())&&e.data&&e.data.size>0){if(r.push(e.data),s!==this._gen)return;!this._mimeType&&e.data.type&&this._setMimeType(e.data.type),this._timeslice&&this._dispatch("wcs-recorder:dataavailable",e.data)}},i.onstart=()=>{s===this._gen&&i.mimeType&&this._setMimeType(i.mimeType)},i.onstop=()=>{if(m(n),this._recordingStream===n&&(this._recordingStream=null),a()){const{mimeType:e,duration:t}=this._closing;return this._closing=null,void this._assembleBlob(r,e,t)}s===this._gen&&(this._paused||this._setDuration(this._elapsed()),this._assembleBlob(r,this._mimeType,this._duration),this._setPaused(!1),this._setRecording(!1))},i.onerror=e=>{if(s!==this._gen)return;const t=e.error;this._setError(o(t??{name:"RecorderError"}))},i.onpause=()=>{s===this._gen&&(this._setDuration(this._elapsed()),this._setPaused(!0))},i.onresume=()=>{s===this._gen&&(this._startTime=this._now()-this._duration,this._setPaused(!1))},this._recorder=i,this._setError(null),this._setMimeType(i.mimeType||t.mimeType||""),this._startTime=this._now(),this._setDuration(0),i.start(this._timeslice?e.timeslice:void 0),function(e){l.set(e,(l.get(e)??0)+1)}(n),this._recordingStream=n,this._setRecording(!0)}_warnNotReady(){this._toldNotReady||(this._toldNotReady=!0,console.warn("[@wcstack/camera] [wcs/command-not-ready] start() was refused: no stream is attached, so nothing is recorded. It goes to `error` too. Wire a camera's stream to the recorder first. (Said once until a stream is attached again.)",this._target))}stop(){this._recorder&&"inactive"!==this._recorder.state&&this._recorder.stop()}pause(){this._recorder&&"recording"===this._recorder.state&&this._recorder.pause()}resume(){this._recorder&&"paused"===this._recorder.state&&this._recorder.resume()}observe(){return this._ready}dispose(){const e=this._recorder,t=null!==e&&"inactive"!==e.state;if(t&&(this._paused||this._setDuration(this._elapsed()),this._closing={gen:this._gen,mimeType:this._mimeType,duration:this._duration}),this._gen++,this._recorder=null,this._revokeUrl(),this._stream=null,this._setPaused(!1),this._setRecording(!1),t)try{e.stop()}catch{this._closing=null,this._recordingStream&&m(this._recordingStream),this._recordingStream=null}}_assembleBlob(e,t,i){const s=t||e[0]?.type||"",r=new Blob(e,s?{type:s}:void 0);this._revokeUrl();const n=this._createUrl(r);this._blob=r,this._objectURL=n;const a={blob:r,objectURL:n,mimeType:s,duration:i};this._dispatch("wcs-recorder:recorded",a)}_revokeUrl(){this._objectURL&&"undefined"!=typeof URL&&"function"==typeof URL.revokeObjectURL&&URL.revokeObjectURL(this._objectURL),this._objectURL=null}_createUrl(e){return"undefined"!=typeof URL&&"function"==typeof URL.createObjectURL?URL.createObjectURL(e):""}_isTypeSupported(e){return globalThis.MediaRecorder.isTypeSupported(e)}_now(){return performance.now()}_elapsed(){return Math.max(0,Math.round(this._now()-this._startTime))}}class D extends HTMLElement{static hasConnectedCallbackPromise=!0;static wcBindable={...U.wcBindable,inputs:[{name:"mimeType",attribute:"mime-type"},{name:"timeslice",attribute:"timeslice"},{name:"audioBitsPerSecond",attribute:"audio-bits"},{name:"videoBitsPerSecond",attribute:"video-bits"}],commands:U.wcBindable.commands};_core;_connectedCallbackPromise=Promise.resolve();_internals=null;constructor(){super(),this._core=new U(this),this._internals=this._initInternals(),this._wireStates({"wcs-recorder:recording-changed":e=>({recording:!0===e}),"wcs-recorder:paused-changed":e=>({paused:!0===e}),"wcs-recorder:error":e=>({error:null!=e})})}get debugStates(){return this._internals?[...this._internals.states]:[]}_initInternals(){try{if("function"!=typeof this.attachInternals)return null;const e=this.attachInternals();return e.states.add("wcs-probe"),e.states.delete("wcs-probe"),e}catch{return null}}_wireStates(e){if(null===this._internals)return;const t=this._internals.states;for(const[i,s]of Object.entries(e))this.addEventListener(i,e=>{const i=this.hasAttribute("debug-states");for(const[r,n]of Object.entries(s(e.detail))){try{n?t.add(r):t.delete(r)}catch{}i&&this.toggleAttribute(`data-wcs-state-${r}`,n)}})}get connectedCallbackPromise(){return this._connectedCallbackPromise}get mimeType(){return this._core.mimeType}set mimeType(e){L(this,"mime-type",e)}get timeslice(){return this._numberAttr("timeslice")}set timeslice(e){L(this,"timeslice",e)}get audioBitsPerSecond(){return this._numberAttr("audio-bits")}set audioBitsPerSecond(e){L(this,"audio-bits",e)}get videoBitsPerSecond(){return this._numberAttr("video-bits")}set videoBitsPerSecond(e){L(this,"video-bits",e)}get recording(){return this._core.recording}get paused(){return this._core.paused}get duration(){return this._core.duration}get blob(){return this._core.blob}get objectURL(){return this._core.objectURL}get error(){return this._core.error}get errorInfo(){return this._core.errorInfo}attachStream(e){this._core.attachStream(e)}start(){this._core.start(this._options())}stop(){this._core.stop()}pause(){this._core.pause()}resume(){this._core.resume()}_numberAttr(e){const t=this.getAttribute(e);if(null===t||""===t.trim())return NaN;const i=Number(t);return Number.isFinite(i)?i:NaN}_options(){const e={},t=this.getAttribute("mime-type")??"";return t&&(e.mimeType=t),Number.isFinite(this.timeslice)&&(e.timeslice=this.timeslice),Number.isFinite(this.audioBitsPerSecond)&&(e.audioBitsPerSecond=this.audioBitsPerSecond),Number.isFinite(this.videoBitsPerSecond)&&(e.videoBitsPerSecond=this.videoBitsPerSecond),e}connectedCallback(){T(this),this.style.display="none",this._connectedCallbackPromise=this._core.observe()}disconnectedCallback(){this._core.dispose()}}const W=Symbol.for("wcstack.package"),O=new WeakSet;function q(e,t){Object.defineProperty(e,W,{value:t,configurable:!0})}function $(e,t,i,s,r){if(void 0!==s&&(i===s||i.prototype instanceof s))return;const n=i[W];if(n===r||O.has(e))return;O.add(e);const a=r.slice(0,r.lastIndexOf("@"));console.warn(`[${a}] [wcs/package-twice] <${t}> is already defined by ${n??`another copy of ${a} that does not name its version`}; this copy, ${r}, does nothing. Load each package once.`)}function x(s=customElements){!function(e,t,i){for(const[s,r]of i){const i=e.get(s);void 0===i?(q(r,t),e.define(s,r)):$(e,s,i,r,t)}}(s,`${t}@${i}`,[[e.tagNames.camera,B],[e.tagNames.recorder,D]])}var F;x(F);
2
2
  //# sourceMappingURL=auto.min.js.map
package/dist/index.esm.js CHANGED
@@ -62,7 +62,7 @@ function setConfig(partialConfig) {
62
62
  frozenConfig = null;
63
63
  }
64
64
 
65
- var pkg = {"name":"@wcstack/camera","version":"4.12.0"};
65
+ var pkg = {"name":"@wcstack/camera","version":"4.14.0"};
66
66
 
67
67
  // ===========================================================================
68
68
  // AUTO-GENERATED FILE - DO NOT EDIT.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wcstack/camera",
3
- "version": "4.12.0",
3
+ "version": "4.14.0",
4
4
  "description": "Declarative camera capture and media recording for Web Components. Binds live MediaStream handles directly to elements (never through serializable state) via getUserMedia + MediaRecorder.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.esm.js",