ambilighter
Version:
Ambilight around the video, image or canvas HTML elements
9 lines (5 loc) • 8.29 kB
JavaScript
(function(){"use strict";var t;try{if(typeof document<"u"){var e=document.createElement("style");e.nonce=(t=document.head.querySelector("meta[property=csp-nonce]"))==null?void 0:t.content,e.appendChild(document.createTextNode(".ambi-box{display:contents;position:relative;transition:box-shadow .4s}.ambi-box__back{position:absolute;left:0;top:0;width:100%;height:100%}")),document.head.appendChild(e)}}catch(o){console.error("vite-plugin-css-injected-by-js",o)}})();
(function(a,s){typeof exports=="object"&&typeof module<"u"?s(exports):typeof define=="function"&&define.amd?define(["exports"],s):(a=typeof globalThis<"u"?globalThis:a||self,s(a.Ambilighter={}))})(this,function(a){"use strict";var M=Object.defineProperty;var T=(a,s,c)=>s in a?M(a,s,{enumerable:!0,configurable:!0,writable:!0,value:c}):a[s]=c;var u=(a,s,c)=>T(a,typeof s!="symbol"?s+"":s,c);class s{constructor(t,e){u(this,"el");u(this,"options");u(this,"canvas");try{if(!(t instanceof HTMLElement))throw new Error("Ambilighter -> constructor :: invalid element");if(typeof e!="object")throw new Error("Ambilighter -> constructor :: invalid options");this.el=t,this.options=e,this.canvas=document.createElement("canvas")}catch(r){console.error(r)}}static validate(t){return t instanceof HTMLElement}updateCanvas(...t){}onLoad(){}onUpdate(...t){}onDestroy(){}}function c(i){if(i===null)return{r:0,g:0,b:0,a:1};if(!(i instanceof ImageData))throw new Error("Ambilightify -> averageColor :: invalid image. Expected ImageData");const t=i.data,e={r:0,g:0,b:0,a:1};for(let n=0;n<t.length;n+=4){const o=t[n],g=t[n+1],f=t[n+2],E=t[n+3];e.r=e.r+o,e.g=e.g+g,e.b=e.b+f,e.a=e.a+E}const r=t.length/4;return e.r=Math.ceil(e.r/r),e.g=Math.ceil(e.g/r),e.b=Math.ceil(e.b/r),e.a=Math.ceil(e.a/r),e}function d(i,t){if(!(i instanceof HTMLCanvasElement))throw new Error("getBorderImage :: invalid canvas");const e=i.getContext("2d"),r=i.width,n=i.height;return e?e.getImageData((r-1)*t[0],(n-1)*t[1],r*t[2]||1,n*t[3]||1):null}const h={top:[0,0,1,0],bottom:[0,1,1,0],left:[0,0,0,1],right:[1,0,0,1],bottomRight:[0,0,1,1]};class p extends s{constructor(t,e){super(t,e);try{if(!(t instanceof HTMLImageElement))throw new Error("AmbilighterImage -> constructor :: invalid element");t.onload=()=>{this.update()},this.update()}catch(r){console.error(r)}return new Proxy(this,{set(r,n,o){return n==="onUpdate"&&(r[n]=o,r.update()),!0}})}static validate(t){return t instanceof HTMLImageElement}update(){this.updateCanvas(this.el);const t={frame:{top:{color:c(d(this.canvas,h.top)),radius:this.radius},bottom:{color:c(d(this.canvas,h.bottom)),radius:this.radius},left:{color:c(d(this.canvas,h.left)),radius:this.radius},right:{color:c(d(this.canvas,h.right)),radius:this.radius}},averageColor:c(d(this.canvas,h.bottomRight))};this.onUpdate(t)}updateCanvas(t){try{const e=this.canvas.getContext("2d");e&&(this.canvas.width=t.naturalWidth,this.canvas.height=t.naturalHeight,e.drawImage(t,0,0,t.naturalWidth,t.naturalHeight))}catch(e){console.error(e)}}get radius(){var t;return((t=this==null?void 0:this.options)==null?void 0:t.radius)||0}onLoad(...t){}onUpdate(...t){}onDestroy(){}}class b extends s{constructor(t,e){super(t,e);try{if(!(t instanceof HTMLVideoElement))throw new Error("AmbilighterVideo -> constructor :: invalid element");this.init()}catch(r){console.error(r)}}static validate(t){return t instanceof HTMLVideoElement}init(){this.el.addEventListener("loadedmetadata",()=>this.update()),this.el.addEventListener("timeupdate",()=>this.update())}deinit(){this.el.removeEventListener("loadedmetadata",()=>this.update()),this.el.removeEventListener("timeupdate",()=>this.update())}update(){this.updateCanvas(this.el);const t={frame:{top:{color:c(d(this.canvas,h.top)),radius:this.radius},bottom:{color:c(d(this.canvas,h.bottom)),radius:this.radius},left:{color:c(d(this.canvas,h.left)),radius:this.radius},right:{color:c(d(this.canvas,h.right)),radius:this.radius}},averageColor:c(d(this.canvas,h.bottomRight))};this.onUpdate(t)}updateCanvas(t){try{const e=this.canvas.getContext("2d");e&&(this.canvas.width=t.videoWidth,this.canvas.height=t.videoHeight,e.drawImage(t,0,0,t.videoWidth,t.videoHeight))}catch(e){console.error(e)}}get radius(){var t;return((t=this==null?void 0:this.options)==null?void 0:t.radius)||0}onLoad(...t){}onUpdate(...t){}onDestroy(){}}class v extends s{constructor(t,e){super(t,e);try{if(!(t instanceof HTMLCanvasElement))throw new Error("AmbilighterCanvas -> constructor :: invalid element")}catch(r){console.error(r)}}static validate(t){return t instanceof HTMLCanvasElement}updateCanvas(t){try{this.canvas=t}catch(e){console.error(e)}}get radius(){var t;return((t=this==null?void 0:this.options)==null?void 0:t.radius)||0}onLoad(...t){}onUpdate(...t){}onDestroy(){}}class A{static produce(t,e){return p.validate(t)?new p(t,e):b.validate(t)?new b(t,e):v.validate(t)?new v(t,e):null}}function w(i=0){return typeof i=="number"&&i>=0&&i<=255}function C(i=0){return typeof i=="number"&&i>=0&&i<=1}class l{constructor({r:t,g:e,b:r,a:n}={r:0,b:0,g:0,a:1}){u(this,"r");u(this,"g");u(this,"b");u(this,"a");this.r=w(t)?t:0,this.g=w(e)?e:0,this.b=w(r)?r:0,this.a=C(n)?n:1}toString(){return`rgba(${this.r}, ${this.g}, ${this.b}, ${this.a})`}}class ${static parseSize(t="0px"){const e=/^(-?\d+(\.\d+)?)(px|%|em|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc)$/,r=t.match(e);if(r){const n=parseFloat(r[1]),o=r[3];return{value:n,unit:o}}return null}}class y{static formatStringAttribute(t,e=""){if(typeof e!="string")throw new Error(`Formatted -> formatStringAttribute :: invalid valueDefault. Expected "string" type, got "${typeof e}"`);return typeof t!="string"?e:t}static formatNumberAttribute(t,e=0){if(typeof e!="number")throw new Error(`Formatted -> formatNumberAttribute :: invalid valueDefault. Expected "number" type, got "${typeof e}"`);return t===null||isNaN(+t)?e:+t}static formatBooleanAttribute(t,e=!1){const r=["true","false"];if(typeof e!="boolean")throw new Error(`Formatted -> formatNumberAttribute :: invalid valueDefault. Expected "boolean" type, got "${typeof e}"`);return typeof t=="string"&&r.includes(t)?t==="true":typeof t=="boolean"?t:typeof t=="string"||t===null?t!==null:e}static formatArrayAttribute(t,e=[]){let r=e;if(t!=="string"||!JSON.parse(t))throw new Error("Formatted -> formatArrayAttribute :: cannot parse val as JSON");if(r=JSON.parse(t),!(r instanceof Array))throw new Error('Formatted -> formatArrayAttribute :: invalid value. Expected "array"');return r}static formatValues(t,e="24px"){let r=t;if(t||(r=e),typeof r=="string"){if(["auto","inherit"].includes(r))return r;if(parseInt(r).toString()===r)return`${r}px`;const n=$.parseSize(r);return n?`${n.value}${n.unit}`:e}return`${r}px`}}class x extends HTMLElement{constructor(){super();u(this,"rendered",!1);u(this,"ambilighter",null)}update(){var e;try{const r=y.formatStringAttribute(this.getAttribute("target"),""),n=y.formatStringAttribute(this.getAttribute("light-to"),""),o=y.formatNumberAttribute(this.getAttribute("radius"),0),g=document.getElementById(r)||this.children[0],f=document.getElementById(n)||this.children[0],E={radius:o};g instanceof HTMLElement&&(this.ambilighter=A.produce(g,E),(e=this.ambilighter)!=null&&e.onUpdate&&(this.ambilighter.onUpdate=m=>{const L=new CustomEvent("onupdate",{detail:{data:m},bubbles:!0,composed:!0});if(f instanceof HTMLElement){const S=[`0 -${o/2}px ${o}px ${new l(m.frame.top.color).toString()}`,`${o/2}px 0 ${o}px ${new l(m.frame.right.color).toString()}`,`0 ${o/2}px ${o}px ${new l(m.frame.bottom.color).toString()}`,`-${o/2}px 0 ${o}px ${new l(m.frame.left.color).toString()}`];f.style.boxShadow=S.join(","),this.dispatchEvent(L)}}))}catch(r){console.error(r)}}render(){this.className="ambi-box",this.update(),this.attachShadow({mode:"open"}),this.shadowRoot&&(this.shadowRoot.innerHTML=`
<link rel="stylesheet" href="./src/css/ambi-box.css"></link>
<slot></slot>
`),this.rendered=!0}connectedCallback(){this.render()}disconnectedCallback(){}static get observedAttributes(){return["target","radius","light-to"]}attributeChangedCallback(){this.rendered&&this.update()}adoptedCallback(){}}customElements.define("ambi-box",x),a.AmbiBox=x,a.Ambilight=A,a.AmbilighterCanvas=v,a.AmbilighterImage=p,a.AmbilighterVideo=b,a.Color=l,Object.defineProperty(a,Symbol.toStringTag,{value:"Module"})});