@gullerya/callout
Version:
callout engine
1 lines • 4.93 kB
JavaScript
const t=Symbol("parent.key"),e=Symbol("target.key"),n=Symbol("shape.key"),o=Symbol("sc.key"),r=Symbol("td.key"),i=Symbol("render.key"),s=Object.freeze({circle:"circle",oval:"oval",box:"box"}),a=s.circle,h=[0,0,0,.8],l=333,c=Object.freeze({shape:s.circle,shadowColor:h,transitionDuration:l});export{s as SHAPES,d as spotlight};function d(e,n,o){const r=Object.assign({},c,o,{target:e,parent:n||document.body});!function(t){if(t.target&&(t.target.nodeType!==Node.ELEMENT_NODE||t.target===document.body))throw new Error("invalid target ("+t.target+")");if(!t.parent||t.parent.nodeType!==Node.ELEMENT_NODE)throw new Error("invalid parent ("+t.parent+")");if(t.target&&(!t.parent.contains(t.target)||t.parent===t.target))throw new Error("target MUST be a child of a given parent; they MAY NOT be the same element");t.shape&&t.shape in s||(console.error("invalid shape ("+t.shape+"), falling back to the default ("+a+")"),t.shape=a);g(t.shadowColor)||(console.error("invalid shadow color ("+t.shadowColor+"), falling back to the default ("+h+")"),t.transitionDuration=l);u(t.transitionDuration)||(console.error("invalid transition duration ("+t.transitionDuration+"), falling back to the default ("+l+")"),t.transitionDuration=l)}(r);const i=document.createElement("spotlight-scene");return i[t]=r.parent,i.shape=r.shape,i.shadowColor=r.shadowColor,i.transitionDuration=r.transitionDuration,r.target&&(i.target=r.target),i[t].appendChild(i),i}const p=document.createElement("template");function g(t){return t&&Array.isArray(t)&&4===t.length&&t.every((t,e)=>"number"==typeof t&&!isNaN(t)&&(3===e?t>0&&t<1:t>=0&&t<=255))}function u(t){return t&&"number"==typeof t&&!isNaN(t)}p.innerHTML='\n\t<style>\n\t\t:host {\n\t\t\tposition: absolute;\n\t\t\ttop: 0;\n\t\t\tleft: 0;\n\t\t\tright: 0;\n\t\t\tbottom: 0;\n\t\t\tz-index: 999;\n\t\t\toverflow: hidden;\n\t\t}\n\n\t\t:host(.shown) .spotlight {\n\t\t\tborder-color: var(--s-c);\n\t\t}\n\t\t:host(.shown) .inner-fence {\n\t\t\tborder-color: rgba(255, 255, 0, 1);\n\t\t\tbox-shadow: 0 0 36px rgba(255, 255, 0, 0.3);\n\t\t}\n\n\t\t.spotlight {\n\t\t\tposition: absolute;\n\t\t\tborder: 8000px solid;\n\t\t\tborder-color: rgba(0, 0, 0, 0);\n\t\t\ttransform: translate(-50%, -50%);\n\t\t\ttransition-property: top, left, width, height, border-color;\n\t\t\ttransition-duration: var(--t-d);\n\t\t}\n\n\t\t.inner-fence {\n\t\t\tposition: absolute;\n\t\t\ttop: 50%;\n\t\t\tleft: 50%;\n\t\t\twidth: calc(100% - 2px);\n\t\t\theight: calc(100% - 2px);\n\t\t\ttransform: translate(-50%, -50%);\n\t\t\tborder: 3px solid;\n\t\t\tborder-color: rgba(255, 255, 0, 0);\n\t\t\ttransition-property: top, left, width, height, border-color;\n\t\t\ttransition-duration: var(--t-d);\n\t\t}\n\n\t\t.box,\n\t\t.box > .inner-fence {\n\t\t\tborder-radius: 8024px;\n\t\t}\n\n\t\t.oval,\n\t\t.oval > .inner-fence {\n\t\t\tborder-radius: 50%;\n\t\t}\n\n\t\t.circle,\n\t\t.circle > .inner-fence {\n\t\t\tborder-radius: 50%;\n\t\t}\n\t</style>\n\n\t<div class="spotlight">\n\t\t<div class="inner-fence"></div>\n\t</div>\n',customElements.define("spotlight-scene",class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}).appendChild(p.content.cloneNode(!0))}connectedCallback(){this.offsetWidth&&this.classList.add("shown")}get parent(){return this[t]}get shape(){return this[n]}set shape(t){this[n]!==t&&(this[n]=t,this[i]())}get shadowColor(){return this[o]}set shadowColor(t){g(t)?(this[o]=t,this.shadowRoot.host.style.setProperty("--s-c","rgba("+this[o]+")")):console.error("invalid shadow color ("+t+"), staying on the present value ("+this[o]+")")}get transitionDuration(){return this[r]}set transitionDuration(t){u(t)?(this[r]=t,this.shadowRoot.host.style.setProperty("--t-d",this[r]+"ms")):console.error("invalid transition duration ("+t+"), staying on the present value ("+this[r]+")")}get target(){return this[e]}set target(t){this.moveTo(t)}moveTo(n){if(this[e]===n)return Promise.resolve();if(!n||n.nodeType!==Node.ELEMENT_NODE||n===document.body)throw new Error("invalid target");if(!this[t].contains(n)||this[t]===n)throw new Error("target MUST be a child of a given parent; they MAY NOT be the same element");return this[e]=n,this[i]()}close(){return this.classList.remove("shown"),new Promise(t=>{setTimeout(()=>{this.remove(),t()},this[r])})}getBoundingClientRect(){return this.shadowRoot.querySelector(".inner-fence").getBoundingClientRect()}[i](){if(!this[e])return;const t=this[e].getBoundingClientRect();let o,i,a;switch(this[n]){case s.box:o=t.width+24,i=t.height+24,a=s.box;break;case s.oval:o=t.width*Math.pow(2,.5),i=t.height*Math.pow(2,.5),a=s.oval;break;case s.circle:default:o=i=Math.pow(Math.pow(t.width,2)+Math.pow(t.height,2),.5)+12,a=s.circle}const h=this.shadowRoot.querySelector(".spotlight");return new Promise(e=>{h.className="spotlight "+a,Object.assign(h.style,{top:t.y+t.height/2+"px",left:t.x+t.width/2+"px",width:o+"px",height:i+"px"}),setTimeout(e,this[r])})}});