bezel-charts 1.3.0 → 1.4.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.
@@ -0,0 +1,2 @@
1
+ /*! Bezel Charts v1.4.0 | MIT | github.com/ShazMoghaddam/bezel-charts */
2
+ var g={dark:{tile:"#15151d",bezel:"#000000",fg:"#f2f1f7",muted:"#8c8aa0",grid:"#2a2935",up:"#5EE6C8",down:"#F675A8",palette:["#9FA1FF","#F675A8","#5EE6C8","#FFC857","#7CC4FF","#FF8A5B"]},light:{tile:"#ffffff",bezel:"#000000",fg:"#17161f",muted:"#6b6980",grid:"#e8e6ef",up:"#12a383",down:"#d63f7c",palette:["#6E70F0","#E2508C","#16A884","#D99A0E","#2F8FE0","#EE6431"]}};var x="ui-sans-serif,system-ui,-apple-system,'Segoe UI',Roboto,Helvetica,Arial,sans-serif",w="ui-monospace,SFMono-Regular,Menlo,Consolas,monospace",W=0;function nt(t){return"bzc"+t+(++W).toString(36)+Math.random().toString(36).slice(2,6)}function h(t){return String(t??"").replace(/[&<>"']/g,function(e){return{"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"}[e]})}function s(t){return Math.round(t*100)/100}function u(t,e,r){return Math.max(e,Math.min(r,t))}function v(t,e){var r=parseFloat(t);return isFinite(r)?r:e}function c(t){return t!=null&&t!==""}function T(t){return Array.isArray(t)?t.map(function(e){var r=+e;return isFinite(r)?r:0}):c(t)?String(t).split(/[\s,;]+/).filter(Boolean).map(function(e){var r=+e;return isFinite(r)?r:0}):[]}function V(t){return Array.isArray(t)?t.map(String):c(t)?String(t).split(",").map(function(e){return e.trim()}):[]}function at(t){return Array.isArray(t)?Array.isArray(t[0])?t.map(T):[T(t)]:c(t)?String(t).split("|").map(T).filter(function(e){return e.length}):[]}function Y(t){return t.reduce(function(e,r){return e+r},0)}function ot(t,e,r){return String(t).length*e*(r?.6:.56)}function st(t,e){return t=String(t),t.length>e?t.slice(0,Math.max(1,e-1))+"\u2026":t}function C(t){return t===!0||t===""||t==="true"||t==="1"}function k(t,e,r){if(!isFinite(t))return"\u2013";var i=Math.abs(t),n;c(e.decimals)?n=u(parseInt(e.decimals,10)||0,0,6):n=t%1===0?0:i<10?2:i<100?1:0;var a={maximumFractionDigits:n,minimumFractionDigits:c(e.decimals)?n:0};(C(e.compact)||r)&&i>=1e4&&(a={notation:"compact",maximumFractionDigits:1});var o;try{o=new Intl.NumberFormat(e.lang||"en-GB",a).format(i)}catch{o=String(s(i))}return(t<0?"\u2212":"")+(e.prefix||"")+o+(e.suffix||"")}function lt(t,e){if(!t.length)return"";for(var r="M"+s(t[0][0])+","+s(t[0][1]),i=1;i<t.length;i++){var n=t[i-1],a=t[i];if(e)r+="L"+s(a[0])+","+s(a[1]);else{var o=(n[0]+a[0])/2;r+="C"+s(o)+","+s(n[1])+" "+s(o)+","+s(a[1])+" "+s(a[0])+","+s(a[1])}}return r}function p(t,e,r,i){return'<text x="'+s(t)+'" y="'+s(e)+'" '+(i||"")+">"+h(r)+"</text>"}function F(t,e,r,i){return'fill="'+(i||t.muted)+'" font-family="'+w+'" font-size="'+(e||10)+'"'+(r?" "+r:"")}function ct(t,e,r,i,n){return'<rect class="bzc-hit" x="'+s(t)+'" y="'+s(e)+'" width="'+s(Math.max(1,r))+'" height="'+s(Math.max(1,i))+'" fill="#000" fill-opacity="0" data-tip="'+h(n)+'"/>'}function ht(t,e,r){return t.animate?' class="'+e+'"'+(r?' style="animation-delay:'+s(r)+'s"':""):""}function ut(t,e){var r=V(t.color).filter(Boolean);return r.length?r:e.palette}function dt(t,e,r,i,n){return p(e+i/2,r+n/2+4,"No data yet",'text-anchor="middle" fill="'+t.muted+'" font-family="'+x+'" font-size="13"')}function ft(t,e){return c(t.notes)?String(t.notes).split(";").map(function(r){var i=r.indexOf(":");if(i<0)return null;var n=r.slice(0,i).trim(),a=r.slice(i+1).trim(),o=e.map(String).indexOf(n);return o<0&&String(parseInt(n,10))===n&&(o=parseInt(n,10)),o>=0&&a?{i:o,text:a}:null}).filter(Boolean):[]}function mt(t,e,r,i,n){var a=(c(t.goalLabel)?t.goalLabel:"Goal")+" "+k(v(t.goal,0),t);return'<line x1="'+s(r)+'" x2="'+s(i)+'" y1="'+s(n)+'" y2="'+s(n)+'" stroke="'+e.fg+'" stroke-opacity=".55" stroke-width="1.25" stroke-dasharray="4 4"/>'+p(i,n-5,a,F(e,10,'text-anchor="end"'))}function pt(t,e,r){var i=String(c(e.stat)?e.stat:r||"").toLowerCase();if(!i||i==="none"||!t.length)return null;var n=Y(t),a={last:t[t.length-1],total:n,sum:n,average:n/t.length,avg:n/t.length,max:Math.max.apply(null,t),min:Math.min.apply(null,t)};if(!(i in a))return null;var o=null;return i==="last"&&t.length>1&&e.delta!=="none"&&(o=t[t.length-1]-t[0]),{val:a[i],delta:o}}var N=["spark","line","area","bars","scatter","ring","donut","gauge","progress","heatmap"],A={};function wt(t,e){A[t]=e}var X=t=>t.replace(/-([a-z])/g,(e,r)=>r.toUpperCase());function U(t,e){if(!A[t])throw new Error(N.includes(t)?`Bezel Charts: the ${t} chart isn't loaded. Add import 'bezel-charts/${t}', or load dist/charts/${t}.js.`:`Bezel Charts: unknown chart type "${t}". Choose one of: ${N.join(", ")}.`);let r={};for(let[i,n]of Object.entries(e))r[X(i)]=n;return r}function S(t,e={}){let r=U(t,e);r.animate=C(r.animate),r.frame=r.frame==="none"?"none":"bezel";let i=r.theme==="light"||r.theme==="dark"?r.theme:r.autoTheme||"dark";return A[t](r,g[i])}function j(t,e={}){return A[t].table(U(t,e))}function $(t){return t.replace(/<rect class="bzc-hit"[^>]*\/>/g,"").replace(/<circle[^>]* class="bzc-hit"[^>]*\/>/g,"").replace(/ data-tip="[^"]*"/g,"")}function yt(t,e={}){return $(S(t,{...e,animate:!1}))}var q=["type","values","labels","series","heading","prefix","suffix","decimals","compact","color","theme","frame","width","height","goal","goal-label","notes","show-values","stat","delta","delta-label","max","min","value","zones","horizontal","straight","zero","start","lang","corners","background","center-label","highlight","x","y","x-label","y-label","trend","static","no-tooltips","stacked","angle-labels","dash","markers","patterns"],_=`:host{display:block;position:relative;max-width:100%}:host([hidden]){display:none}svg{display:block;max-width:100%;height:auto;overflow:visible}.tip{position:absolute;left:0;top:0;pointer-events:none;background:#0b0b10;color:#f2f1f7;font:600 12px/1.5 ${w};padding:7px 10px;border-radius:10px;white-space:pre;opacity:0;transform:translate(-50%,calc(-100% - 12px));transition:opacity .12s;z-index:3;border:1px solid #2a2935;box-shadow:0 8px 24px rgba(0,0,0,.35)}.tip.on{opacity:1}.c{outline:none}.c:focus-visible{outline:2px solid #fff;outline-offset:3px;box-shadow:0 0 0 7px #000}.k{stroke:currentColor;stroke-width:2;stroke-opacity:1}.sr{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}@media (forced-colors:active){.c:focus-visible{outline-color:Highlight}}`,Q={ArrowLeft:-1,ArrowUp:-1,ArrowRight:1,ArrowDown:1},J=()=>typeof matchMedia=="function"?matchMedia("(prefers-color-scheme: dark)"):null,K=()=>{let t=typeof document<"u"&&document.documentElement?.getAttribute?.("data-theme");return t==="light"||t==="dark"?t:null},R=new Set;typeof MutationObserver=="function"&&typeof document<"u"&&document.documentElement&&new MutationObserver(()=>R.forEach(t=>t.refresh())).observe(document.documentElement,{attributes:!0,attributeFilter:["data-theme"]});var Z=typeof HTMLElement>"u"?class{}:HTMLElement,z=class extends Z{static get observedAttributes(){return q}static get themes(){return g}get resolvedTheme(){let e=this.getAttribute("theme");return e==="light"||e==="dark"?e:this.options.autoTheme}get chartType(){return this.getAttribute("type")||"spark"}connectedCallback(){this.shadowRoot||(this.attachShadow({mode:"open"}).innerHTML=`<style>${_}</style><div class="c" role="group" aria-roledescription="chart"></div><p class="sr" id="h">Use the arrow keys to step through the values.</p><div class="tip" aria-hidden="true"></div><div class="sr" aria-live="polite"></div><div class="sr"></div>`,[,this.#t,,this.#r,this.#s,this.#h]=this.shadowRoot.children,this.shadowRoot.addEventListener("pointermove",e=>this.#d(e)),this.shadowRoot.addEventListener("pointerdown",e=>this.#d(e)),this.addEventListener("pointerleave",()=>this.#r.classList.remove("on")),this.#t.addEventListener("keydown",e=>this.#g(e)),this.#t.addEventListener("blur",()=>this.#b())),R.add(this),this.#i=J(),this.#i?.addEventListener?.("change",this.#u),typeof ResizeObserver=="function"?(this.#o=new ResizeObserver(([e])=>{let r=Math.round(e.contentRect.width);(!this.#n||!this.hasAttribute("width")&&r>0&&Math.abs(r-this.#l)>1)&&this.#a()}),this.#o.observe(this)):this.#a()}disconnectedCallback(){R.delete(this),this.#o?.disconnect(),this.#i?.removeEventListener?.("change",this.#u)}attributeChangedCallback(){!this.#n||this.#c||(this.#c=!0,queueMicrotask(()=>{this.#c=!1,this.#a()}))}get options(){let e={};for(let r of q)this.hasAttribute(r)&&(e[r]=this.getAttribute(r));return e.width||(e.width=this.#l||360),e.autoTheme=K()||(this.#i?this.#i.matches?"dark":"light":"dark"),e}refresh(){this.#n&&this.#a()}toSVG(e={}){return $(S(this.chartType,{...this.options,...e,animate:!1}))}download(e){let r=URL.createObjectURL(new Blob([this.toSVG()],{type:"image/svg+xml"})),i=Object.assign(document.createElement("a"),{href:r,download:`${(e||this.getAttribute("heading")||this.chartType).replace(/[^\w-]+/g,"-").toLowerCase()}.svg`});document.body.append(i),i.click(),i.remove(),setTimeout(()=>URL.revokeObjectURL(r),1e3)}#o=null;#t=null;#r=null;#s=null;#h=null;#e=-1;#i=null;#l=0;#n=!1;#c=!1;#u=()=>{let e=this.getAttribute("theme");(!e||e==="auto")&&this.refresh()};#a(){if(!this.shadowRoot)return;let e=Math.round(this.getBoundingClientRect?.().width||0);this.#l=e>0?e:360;let r=this.options;r.animate=!this.#n&&!this.hasAttribute("static");let i,n=null;try{i=S(this.chartType,r),n=j(this.chartType,r)}catch(d){i=`<p style="font:13px ${x};color:#d63f7c">${h(d.message)}</p>`}let a=this.#t;a.innerHTML=i.replace(/<title>[\s\S]*?<\/title>/,"");let o=a.querySelector("svg");o?(a.setAttribute("aria-label",o.getAttribute("aria-label")),o.removeAttribute("role"),o.removeAttribute("aria-label"),o.setAttribute("aria-hidden","true")):a.removeAttribute("aria-label");let l=!!o&&!this.hasAttribute("no-tooltips");l?(a.setAttribute("tabindex","0"),a.setAttribute("aria-describedby","h")):(a.removeAttribute("tabindex"),a.removeAttribute("aria-describedby")),a.style.color=g[r.theme==="light"||r.theme==="dark"?r.theme:r.autoTheme].fg,a.style.borderRadius=`${r.frame==="none"?4:u(+r.corners||22,0,60)}px`,this.#h.innerHTML=n&&n.rows.length?tt(r.heading,n):"",this.#e>=0&&l&&this.shadowRoot.activeElement===a?this.#p(this.#e):this.#e=-1,this.#n=!0,this.dispatchEvent(new CustomEvent("bezel-render",{bubbles:!0}))}#d(e){if(this.hasAttribute("no-tooltips"))return;let r=e.target?.closest?.("[data-tip]");if(!r){this.#r.classList.remove("on");return}this.#f(r,e.clientX,e.clientY)}#f(e,r,i){let n=this.#r;n.textContent=e.getAttribute("data-tip");let a=this.getBoundingClientRect?.()||{left:0,top:0,width:0},o=n.offsetWidth/2;n.style.left=`${u(r-a.left,o,Math.max(o,a.width-o))}px`,n.style.top=`${i-a.top}px`,n.classList.add("on")}#m(){return[...this.#t.querySelectorAll("[data-tip]:not([data-skip])")]}#g(e){let r=this.#m(),i=r.length;if(!i)return;let n=this.#e,a=Q[e.key];if(a)this.chartType==="heatmap"&&/Left|Right/.test(e.key)&&(a*=7),n=n<0?a>0?0:i-1:u(n+a,0,i-1);else if(e.key==="Home"||e.key==="End")n=e.key==="Home"?0:i-1;else{e.key==="Escape"&&this.#b();return}e.preventDefault(),this.#p(n,!0)}#p(e,r){let i=this.#m();if(!i.length)return;e=u(e,0,i.length-1),this.#t.querySelector(".k")?.classList.remove("k");let n=i[e],a=n.getBoundingClientRect?.()||{left:0,top:0,width:0};n.classList.add("k"),this.#e=e,this.#f(n,a.left+a.width/2,a.top),r&&(this.#s.textContent=`${n.getAttribute("data-tip").replace(/\n/g,", ")}. ${e+1} of ${i.length}`)}#b(){this.#t.querySelector(".k")?.classList.remove("k"),this.#r.classList.remove("on"),this.#s.textContent="",this.#e=-1}};function tt(t,{head:e,rows:r}){let i=n=>n.map((a,o)=>o?`<td>${h(a)}</td>`:`<th scope="row">${h(a)}</th>`).join("");return`<table><caption>${h(t||"Chart data")}</caption><thead><tr>${e.map(n=>`<th scope="col">${h(n)}</th>`).join("")}</tr></thead><tbody>${r.map(n=>`<tr>${i(n)}</tr>`).join("")}</tbody></table>`}function zt(t){typeof customElements>"u"||typeof HTMLElement>"u"||(customElements.get(`bezel-${t}`)||customElements.define(`bezel-${t}`,class extends z{get chartType(){return t}}),customElements.get("bezel-chart")||customElements.define("bezel-chart",class extends z{}))}function et(t){var e=Math.round(u(v(t.width,360),160,2400)),r=t.frame==="none"?0:4,i=t.frame==="none"?8:20;return{W:e,b:r,P:i,w:e-2*(r+i)}}var rt=".bzc-a{animation:bzc-in .6s ease both}.bzc-d{animation:bzc-draw 1.1s cubic-bezier(.3,.7,.2,1) both}.bzc-g{transform-box:fill-box;transform-origin:50% 100%;animation:bzc-grow .7s cubic-bezier(.2,.8,.2,1) both}.bzc-gn{transform-box:fill-box;transform-origin:50% 0;animation:bzc-grow .7s cubic-bezier(.2,.8,.2,1) both}.bzc-gx{transform-box:fill-box;transform-origin:0 50%;animation:bzc-growx .8s cubic-bezier(.2,.8,.2,1) both}.bzc-s{animation:bzc-sweep 1.1s cubic-bezier(.2,.8,.2,1) both}@keyframes bzc-in{from{opacity:0}}@keyframes bzc-draw{from{stroke-dashoffset:1}}@keyframes bzc-grow{from{transform:scaleY(0)}}@keyframes bzc-growx{from{transform:scaleX(0)}}@keyframes bzc-sweep{from{stroke-dasharray:0 100}}@media (prefers-reduced-motion:reduce){[class^=bzc-]{animation:none!important}}";function Ft(t,e,r,i,n){var a=et(t),o=a.W,l=a.b,d=a.P,O=a.w,E=u(v(t.corners,22),0,60),f=l+d,y="";c(t.heading)&&(y+=p(l+d,f+10,String(t.heading).toUpperCase(),F(e,11,'font-weight="600" letter-spacing="1.3"')),f+=24);var m=n&&n.stat;if(m){if(y+=p(l+d,f+30,k(m.val,t),'fill="'+e.fg+'" font-family="'+x+'" font-size="32" font-weight="800" letter-spacing="-0.5"'),m.delta!=null){var M=m.delta>0,H=m.delta===0,I=t.delta==="inverse"?!M:M,D=H?e.muted:I?e.up:e.down,P=(H?"\u25CF ":M?"\u25B2 ":"\u25BC ")+k(Math.abs(m.delta),t)+" "+(c(t.deltaLabel)?t.deltaLabel:"since start");y+=p(l+d+O,f+28,P,'text-anchor="end" fill="'+D+'" font-family="'+w+'" font-size="11" font-weight="600"')}f+=44}var G=i(l+d,f,O,r),b=Math.round(f+r+d+l),L="";t.frame!=="none"?L='<rect width="'+o+'" height="'+b+'" rx="'+E+'" fill="'+e.bezel+'"/><rect x="'+l+'" y="'+l+'" width="'+(o-2*l)+'" height="'+(b-2*l)+'" rx="'+Math.max(0,E-l)+'" fill="'+(t.background||e.tile)+'"/>':c(t.background)&&(L='<rect width="'+o+'" height="'+b+'" rx="'+E+'" fill="'+t.background+'"/>');var B=(c(t.heading)?t.heading+": ":"")+(n&&n.summary||"chart");return'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 '+o+" "+b+'" width="'+o+'" height="'+b+'" role="img" aria-label="'+h(B)+'"><title>'+h(B)+"</title>"+(t.animate?"<style>"+rt+"</style>":"")+L+y+G+"</svg>"}export{x as a,w as b,nt as c,h as d,s as e,u as f,v as g,c as h,T as i,V as j,at as k,Y as l,ot as m,st as n,C as o,k as p,lt as q,p as r,F as s,ct as t,ht as u,ut as v,dt as w,ft as x,mt as y,pt as z,et as A,Ft as B,wt as C,S as D,yt as E,z as F,zt as G};
@@ -1,2 +1,2 @@
1
- /*! Bezel Charts v1.3.0 | MIT | github.com/ShazMoghaddam/bezel-charts */
2
- import{a as w,e,j as d,k as x,m as g,p as v,r as L}from"./shared-L67BQ555.js";function m(r,t,a){if(r===t)if(r===0)t=1;else{var n=Math.abs(r)*.1;r-=n,t+=n}for(var l=(t-r)/(a||4),i=Math.pow(10,Math.floor(Math.log10(l))),u=l/i,o=(u<=1?1:u<=2?2:u<=5?5:10)*i,f=Math.floor(r/o)*o,h=Math.ceil(t/o)*o,s=[],c=f;c<=h+o/2;c+=o)s.push(+c.toFixed(10));return{lo:f,hi:h,ticks:s}}function E(r,t,a,n,l,i,u,o){var f=n,h=l,s="",c=o||13;return r.forEach(function(p,M){var S=c+g(p,12)+16;f>n&&f+S-16>n+i&&(f=n,h+=20),s+=(u?u(M,f,h):'<circle cx="'+e(f+4)+'" cy="'+e(h+6)+'" r="4" fill="'+t[M%t.length]+'"/>')+L(f+c,h+10,p,'fill="'+a.fg+'" font-family="'+w+'" font-size="12"'),f+=S}),{svg:s,height:h-l+24}}var T={solid:"",dashed:"7 5",dotted:"1 5",dashdot:"9 4 1 4"},A=["circle","square","triangle","diamond"],H=["solid","stripes","dots","grid"];function O(r,t,a){if(r==null||r===!1||r==="none"||r==="false")return null;var n=r===!0||r===""||r==="auto"?t:d(r).map(function(l){return t.indexOf(l)<0?a:l});return n.length?function(l){return n[l%n.length]}:null}function q(r,t,a,n,l){var i=n*1.15,u=n*.85;return r==="square"?'<rect x="'+e(t-u)+'" y="'+e(a-u)+'" width="'+e(2*u)+'" height="'+e(2*u)+'" rx="1"'+l+"/>":r==="triangle"?'<path d="M'+e(t)+","+e(a-i)+"L"+e(t+i)+","+e(a+u)+"L"+e(t-i)+","+e(a+u)+'Z"'+l+"/>":r==="diamond"?'<path d="M'+e(t)+","+e(a-i*1.1)+"L"+e(t+i)+","+e(a)+"L"+e(t)+","+e(a+i*1.1)+"L"+e(t-i)+","+e(a)+'Z"'+l+"/>":'<circle cx="'+e(t)+'" cy="'+e(a)+'" r="'+e(n)+'"'+l+"/>"}function N(r,t,a,n){var l=' stroke="'+n+'" stroke-opacity=".55" stroke-width="1.5"';return'<pattern id="'+r+'" width="6" height="6" patternUnits="userSpaceOnUse"'+(t==="dots"?"":' patternTransform="rotate(45)"')+'><rect width="6" height="6" fill="'+a+'"/>'+(t==="dots"?'<circle cx="3" cy="3" r="1.3" fill="'+n+'" fill-opacity=".55"/>':'<path d="M3,0V6'+(t==="grid"?"M0,3H6":"")+'"'+l+"/>")+"</pattern>"}function P(r){return Math.max.apply(null,r.map(function(t){return g(t,10,!0)}))+10}function U(r,t){for(var a=x(r.values),n=d(r.series),l=d(r.labels),i=[],u=Math.max.apply(null,[0].concat(a.map(function(c){return c.length}))),o=0;o<u;o++){var f=[l[o]||"#"+(o+1)],h=0;a.forEach(function(c){f.push(o<c.length?v(c[o],r):""),h+=o<c.length?c[o]:0}),t&&f.push(v(h,r)),i.push(f)}var s=a.length>1||n.length?a.map(function(c,p){return n[p]||"Series "+(p+1)}):["Value"];return{head:["Label"].concat(s,t?["Total"]:[]),rows:i}}export{m as a,E as b,T as c,A as d,H as e,O as f,q as g,N as h,P as i,U as j};
1
+ /*! Bezel Charts v1.4.0 | MIT | github.com/ShazMoghaddam/bezel-charts */
2
+ import{a as w,e,j as d,k as x,m as g,p as v,r as L}from"./shared-4QPUIMAU.js";function m(r,t,a){if(r===t)if(r===0)t=1;else{var n=Math.abs(r)*.1;r-=n,t+=n}for(var l=(t-r)/(a||4),i=Math.pow(10,Math.floor(Math.log10(l))),u=l/i,o=(u<=1?1:u<=2?2:u<=5?5:10)*i,f=Math.floor(r/o)*o,h=Math.ceil(t/o)*o,s=[],c=f;c<=h+o/2;c+=o)s.push(+c.toFixed(10));return{lo:f,hi:h,ticks:s}}function E(r,t,a,n,l,i,u,o){var f=n,h=l,s="",c=o||13;return r.forEach(function(p,M){var S=c+g(p,12)+16;f>n&&f+S-16>n+i&&(f=n,h+=20),s+=(u?u(M,f,h):'<circle cx="'+e(f+4)+'" cy="'+e(h+6)+'" r="4" fill="'+t[M%t.length]+'"/>')+L(f+c,h+10,p,'fill="'+a.fg+'" font-family="'+w+'" font-size="12"'),f+=S}),{svg:s,height:h-l+24}}var T={solid:"",dashed:"7 5",dotted:"1 5",dashdot:"9 4 1 4"},A=["circle","square","triangle","diamond"],H=["solid","stripes","dots","grid"];function O(r,t,a){if(r==null||r===!1||r==="none"||r==="false")return null;var n=r===!0||r===""||r==="auto"?t:d(r).map(function(l){return t.indexOf(l)<0?a:l});return n.length?function(l){return n[l%n.length]}:null}function q(r,t,a,n,l){var i=n*1.15,u=n*.85;return r==="square"?'<rect x="'+e(t-u)+'" y="'+e(a-u)+'" width="'+e(2*u)+'" height="'+e(2*u)+'" rx="1"'+l+"/>":r==="triangle"?'<path d="M'+e(t)+","+e(a-i)+"L"+e(t+i)+","+e(a+u)+"L"+e(t-i)+","+e(a+u)+'Z"'+l+"/>":r==="diamond"?'<path d="M'+e(t)+","+e(a-i*1.1)+"L"+e(t+i)+","+e(a)+"L"+e(t)+","+e(a+i*1.1)+"L"+e(t-i)+","+e(a)+'Z"'+l+"/>":'<circle cx="'+e(t)+'" cy="'+e(a)+'" r="'+e(n)+'"'+l+"/>"}function N(r,t,a,n){var l=' stroke="'+n+'" stroke-opacity=".55" stroke-width="1.5"';return'<pattern id="'+r+'" width="6" height="6" patternUnits="userSpaceOnUse"'+(t==="dots"?"":' patternTransform="rotate(45)"')+'><rect width="6" height="6" fill="'+a+'"/>'+(t==="dots"?'<circle cx="3" cy="3" r="1.3" fill="'+n+'" fill-opacity=".55"/>':'<path d="M3,0V6'+(t==="grid"?"M0,3H6":"")+'"'+l+"/>")+"</pattern>"}function P(r){return Math.max.apply(null,r.map(function(t){return g(t,10,!0)}))+10}function U(r,t){for(var a=x(r.values),n=d(r.series),l=d(r.labels),i=[],u=Math.max.apply(null,[0].concat(a.map(function(c){return c.length}))),o=0;o<u;o++){var f=[l[o]||"#"+(o+1)],h=0;a.forEach(function(c){f.push(o<c.length?v(c[o],r):""),h+=o<c.length?c[o]:0}),t&&f.push(v(h,r)),i.push(f)}var s=a.length>1||n.length?a.map(function(c,p){return n[p]||"Series "+(p+1)}):["Value"];return{head:["Label"].concat(s,t?["Total"]:[]),rows:i}}export{m as a,E as b,T as c,A as d,H as e,O as f,q as g,N as h,P as i,U as j};
@@ -0,0 +1,2 @@
1
+ /*! Bezel Charts v1.4.0 | MIT | github.com/ShazMoghaddam/bezel-charts */
2
+ import{a as q,b as B,c as C,g as Y}from"./shared-APAAEWNX.js";import{e as p,f as H,h as L,m as S,r as M,s as b,t as K,u as X,y as W}from"./shared-4QPUIMAU.js";function Q(e,t,r,i,l,h,u){var a="",n=l,s=r.n,k=r.labels;if(r.names){var c=B(r.names,r.pal,t,i,n,h,r.key,r.kw);a+=c.svg,n+=c.height}var f=r.lo,v=r.hi;L(e.goal)&&(f=Math.min(f,+e.goal),v=Math.max(v,+e.goal)),r.zero&&(f=Math.min(0,f),v=Math.max(0,v));var g=q(f,v,4),F=g.ticks.map(r.tick),A=Math.max.apply(null,F.map(function(o){return S(o,10,!0)}))+10,G=k.length?20:4,m=i+A,d=h-A,y=u-(n-l)-G,z=function(o){return s===1?m+d/2:m+o*d/(s-1)},D=function(o){return n+y-(o-g.lo)/(g.hi-g.lo)*y};if(g.ticks.forEach(function(o,w){var E=D(o);a+='<line x1="'+p(m)+'" x2="'+p(m+d)+'" y1="'+p(E)+'" y2="'+p(E)+'" stroke="'+t.grid+'"'+(o===0?"":' stroke-dasharray="2 4"')+"/>"+M(m-8,E+3.5,F[w],b(t,10,'text-anchor="end"'))}),k.length){for(var I=Math.max(1,Math.ceil(s*(Math.max.apply(null,k.map(function(o){return S(o,10,!0)}))+10)/d)),x=0;x<s;x+=I)if(k[x]!=null){var J=s>1&&x===0?"start":s>1&&x===s-1?"end":"middle";a+=M(z(x),n+y+15,k[x],b(t,10,'text-anchor="'+J+'"'))}}return r.notes.forEach(function(o){if(!(o.i>=s)){var w=z(o.i);a+='<line x1="'+p(w)+'" x2="'+p(w)+'" y1="'+p(n+12)+'" y2="'+p(n+y)+'" stroke="'+t.fg+'" stroke-opacity=".4" stroke-dasharray="3 3"/>'+M(H(w,m+30,m+d-30),n+8,o.text,b(t,10,'text-anchor="middle"',t.fg))}}),{svg:a,X:z,Y:D,px:m,pw:d,top:n,ph:y}}function R(e,t,r,i,l){for(var h=L(e.goal)?W(e,t,r.px,r.px+r.pw,r.Y(+e.goal)):"",u=i>1?r.pw/(i-1):r.pw,a=0;a<i;a++)h+=K(r.X(a)-u/2,r.top,u,r.ph,l(a));return h}function T(e,t,r,i){return function(l,h,u){var a=e[l%e.length],n=t?C[t(l)]:"",s=r?r(l):"none";return'<line x1="'+p(h)+'" x2="'+p(h+18)+'" y1="'+p(u+6)+'" y2="'+p(u+6)+'" stroke="'+a+'" stroke-width="2.5" stroke-linecap="round"'+(n?' stroke-dasharray="'+n+'"':"")+"/>"+(s!=="none"?Y(s,h+9,u+6,3.5,' fill="'+a+'" stroke="'+i+'" stroke-width="1.5"'):"")}}function U(e,t,r,i,l){return l?'<path d="'+t+'" fill="none" stroke="'+r+'" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="'+l+'"'+X(e,"bzc-a",i*.15)+"/>":'<path d="'+t+'" fill="none" stroke="'+r+'" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" pathLength="1" style="stroke-dasharray:1'+(e.animate?";animation-delay:"+i*.15+"s":"")+'"'+(e.animate?' class="bzc-d"':"")+"/>"}function V(e,t,r,i,l,h,u,a){var n="",s=Math.ceil(r.length/40);return r.forEach(function(k,c){(c%s===0||c===r.length-1)&&(n+=Y(t,i(c),l(k),3.5,' fill="'+h+'" stroke="'+u+'" stroke-width="1.5"'+X(e,"bzc-a",.6+a*.15)))}),n}export{Q as a,R as b,T as c,U as d,V as e};
@@ -1,2 +1,2 @@
1
- /*! Bezel Charts v1.3.0 | MIT | github.com/ShazMoghaddam/bezel-charts */
2
- import{B as H,C as J,D as U,E as W,F as _,G as K,c as I,e as n,f as N,g as P,h as y,i as b,j as x,o as L,p as h,q as X,r as M,s as E,t as Y,u as z,v as Z,w as q,x as A,y as D,z as F}from"./shared-L67BQ555.js";function k(t,l){var r=b(t.values),o=Z(t,l)[0],Q=P(t.height,64),G=x(t.labels),R=A(t,G),T=F(r,t,"last");return H(t,l,Q,function(i,c,p,f){if(!r.length)return q(l,i,c,p,f);var v=r.length===1?[r[0],r[0]]:r,u=Math.min.apply(null,v),m=Math.max.apply(null,v);y(t.goal)&&(u=Math.min(u,+t.goal),m=Math.max(m,+t.goal));var V=(m-u||Math.abs(m)||1)*.12;u-=V,m+=V;var O=function(a){return i+a*p/(v.length-1)},S=function(a){return c+f-(a-u)/(m-u)*f},d=v.map(function(a,e){return[O(e),S(a)]}),j=X(d,L(t.straight)),B=I("g"),g=d[d.length-1],s='<defs><linearGradient id="'+B+'" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="'+o+'" stop-opacity=".32"/><stop offset="1" stop-color="'+o+'" stop-opacity="0"/></linearGradient></defs>';[1/3,2/3].forEach(function(a){s+='<line x1="'+i+'" x2="'+(i+p)+'" y1="'+n(c+f*a)+'" y2="'+n(c+f*a)+'" stroke="'+l.grid+'" stroke-dasharray="2 4"/>'}),s+='<path d="'+j+"L"+n(g[0])+","+(c+f)+"L"+i+","+(c+f)+'Z" fill="url(#'+B+')"'+z(t,"bzc-a")+"/>",s+='<path d="'+j+'" fill="none" stroke="'+o+'" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" pathLength="1" style="stroke-dasharray:1"'+z(t,"bzc-d")+"/>",y(t.goal)&&(s+=D(t,l,i,i+p,S(+t.goal))),R.forEach(function(a){if(!(a.i>=r.length)){var e=d[a.i];s+='<circle cx="'+n(e[0])+'" cy="'+n(e[1])+'" r="3.5" fill="'+l.fg+'"/>'+M(N(e[0],i+30,i+p-30),e[1]-9,a.text,E(l,10,'text-anchor="middle"',l.fg))}}),s+='<circle cx="'+n(g[0])+'" cy="'+n(g[1])+'" r="9" fill="'+o+'" fill-opacity=".25"/><circle cx="'+n(g[0])+'" cy="'+n(g[1])+'" r="4.5" fill="'+o+'"/>',L(t.showValues)&&d.forEach(function(a,e){e<r.length&&(s+=M(a[0],a[1]-8,h(r[e],t,!0),E(l,9,'text-anchor="middle"')))});var C=r.length>1?p/(r.length-1):p;return r.forEach(function(a,e){s+=Y(O(e)-C/2,c-6,C,f+12,(G[e]||"#"+(e+1))+": "+h(a,t))}),s},{stat:T,summary:r.length?"latest "+h(r[r.length-1],t):"no data"})}k.table=function(t){var l=x(t.labels);return{head:["Label","Value"],rows:b(t.values).map(function(r,o){return[l[o]||"#"+(o+1),h(r,t)]})}};J("spark",k);K("spark");export{_ as BezelChart,U as render,W as toSVG};
1
+ /*! Bezel Charts v1.4.0 | MIT | github.com/ShazMoghaddam/bezel-charts */
2
+ import{B as H,C as J,D as U,E as W,F as _,G as K,c as I,e as n,f as N,g as P,h as y,i as b,j as x,o as L,p as h,q as X,r as M,s as E,t as Y,u as z,v as Z,w as q,x as A,y as D,z as F}from"./shared-4QPUIMAU.js";function k(t,l){var r=b(t.values),o=Z(t,l)[0],Q=P(t.height,64),G=x(t.labels),R=A(t,G),T=F(r,t,"last");return H(t,l,Q,function(i,c,p,f){if(!r.length)return q(l,i,c,p,f);var v=r.length===1?[r[0],r[0]]:r,u=Math.min.apply(null,v),m=Math.max.apply(null,v);y(t.goal)&&(u=Math.min(u,+t.goal),m=Math.max(m,+t.goal));var V=(m-u||Math.abs(m)||1)*.12;u-=V,m+=V;var O=function(a){return i+a*p/(v.length-1)},S=function(a){return c+f-(a-u)/(m-u)*f},d=v.map(function(a,e){return[O(e),S(a)]}),j=X(d,L(t.straight)),B=I("g"),g=d[d.length-1],s='<defs><linearGradient id="'+B+'" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="'+o+'" stop-opacity=".32"/><stop offset="1" stop-color="'+o+'" stop-opacity="0"/></linearGradient></defs>';[1/3,2/3].forEach(function(a){s+='<line x1="'+i+'" x2="'+(i+p)+'" y1="'+n(c+f*a)+'" y2="'+n(c+f*a)+'" stroke="'+l.grid+'" stroke-dasharray="2 4"/>'}),s+='<path d="'+j+"L"+n(g[0])+","+(c+f)+"L"+i+","+(c+f)+'Z" fill="url(#'+B+')"'+z(t,"bzc-a")+"/>",s+='<path d="'+j+'" fill="none" stroke="'+o+'" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" pathLength="1" style="stroke-dasharray:1"'+z(t,"bzc-d")+"/>",y(t.goal)&&(s+=D(t,l,i,i+p,S(+t.goal))),R.forEach(function(a){if(!(a.i>=r.length)){var e=d[a.i];s+='<circle cx="'+n(e[0])+'" cy="'+n(e[1])+'" r="3.5" fill="'+l.fg+'"/>'+M(N(e[0],i+30,i+p-30),e[1]-9,a.text,E(l,10,'text-anchor="middle"',l.fg))}}),s+='<circle cx="'+n(g[0])+'" cy="'+n(g[1])+'" r="9" fill="'+o+'" fill-opacity=".25"/><circle cx="'+n(g[0])+'" cy="'+n(g[1])+'" r="4.5" fill="'+o+'"/>',L(t.showValues)&&d.forEach(function(a,e){e<r.length&&(s+=M(a[0],a[1]-8,h(r[e],t,!0),E(l,9,'text-anchor="middle"')))});var C=r.length>1?p/(r.length-1):p;return r.forEach(function(a,e){s+=Y(O(e)-C/2,c-6,C,f+12,(G[e]||"#"+(e+1))+": "+h(a,t))}),s},{stat:T,summary:r.length?"latest "+h(r[r.length-1],t):"no data"})}k.table=function(t){var l=x(t.labels);return{head:["Label","Value"],rows:b(t.values).map(function(r,o){return[l[o]||"#"+(o+1),h(r,t)]})}};J("spark",k);K("spark");export{_ as BezelChart,U as render,W as toSVG};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "bezel-charts",
3
- "version": "1.3.0",
4
- "description": "Small, polished charts as zero-dependency web components. Sparklines, lines, bars, rings, donuts, gauges, progress bars and heatmaps, with one-click static SVG export for READMEs.",
3
+ "version": "1.4.0",
4
+ "description": "Small, polished charts as zero-dependency web components. Sparklines, lines, areas, bars, rings, donuts, gauges, progress bars and heatmaps, with one-click static SVG export for READMEs.",
5
5
  "type": "module",
6
6
  "main": "dist/bezel-charts.js",
7
7
  "module": "dist/bezel-charts.js",
@@ -9,6 +9,7 @@
9
9
  ".": "./dist/bezel-charts.js",
10
10
  "./spark": "./dist/charts/spark.js",
11
11
  "./line": "./dist/charts/line.js",
12
+ "./area": "./dist/charts/area.js",
12
13
  "./bars": "./dist/charts/bars.js",
13
14
  "./scatter": "./dist/charts/scatter.js",
14
15
  "./ring": "./dist/charts/ring.js",
@@ -0,0 +1,97 @@
1
+ import { newId, r2, num, list, series, bool, fmt, pathOf, text, small, palette, emptyState, parseNotes, statOf } from '../core/util.js';
2
+ import { seriesTable, styleOf, pattern, DASHES, SHAPES, PATTERNS } from '../core/series.js';
3
+ import { xyFrame, xyFinish, lineKey, seriesLine, pointMarks } from '../core/xy.js';
4
+ import { tile } from '../core/tile.js';
5
+
6
+ /**
7
+ * Areas over time. Several series overlap as see-through fills; `stacked` piles them so the top edge is the total,
8
+ * and stacked="percent" scales each column to 100% to show shares. The axis always includes zero, since an area's
9
+ * height reads as an amount.
10
+ */
11
+ export default function area(o, th) {
12
+ var S = series(o.values), names = list(o.series), labels = list(o.labels), pal = palette(o, th);
13
+ var h = num(o.height, 170), k = S.length, n = Math.max.apply(null, [0].concat(S.map(function (s) { return s.length; })));
14
+ var mode = k > 1 ? (o.stacked === 'percent' ? 'percent' : bool(o.stacked) ? 'stack' : '') : '';
15
+ var notes = parseNotes(o, labels), multi = k > 1 || names.length > 0;
16
+ var nameOf = function (j) { return names[j] || 'Series ' + (j + 1); };
17
+ var val = function (j, i) { return i < S[j].length ? S[j][i] : 0; };
18
+
19
+ // Where each band starts and ends in every column. In a stack, positive parts pile up from zero and negative parts
20
+ // down from it, as stacked bars do. In a percent stack, each column's positive parts are scaled to add up to 100.
21
+ var lows = S.map(function () { return []; }), highs = S.map(function () { return []; }), totals = [], pos = [];
22
+ for (var i = 0; i < n; i++) {
23
+ var up = 0, down = 0, t = 0, p = 0;
24
+ for (var j = 0; j < k; j++) { t += val(j, i); p += Math.max(0, val(j, i)); }
25
+ totals.push(t); pos.push(p);
26
+ for (j = 0; j < k; j++) {
27
+ var v = mode === 'percent' ? (p ? Math.max(0, val(j, i)) / p * 100 : 0) : val(j, i);
28
+ if (!mode) { lows[j].push(0); highs[j].push(v); }
29
+ else if (v >= 0) { lows[j].push(up); up += v; highs[j].push(up); }
30
+ else { lows[j].push(down); down += v; highs[j].push(down); }
31
+ }
32
+ }
33
+ var edges = [].concat.apply([], lows.concat(highs));
34
+
35
+ var dashOf = styleOf(o.dash, Object.keys(DASHES), 'solid'), markOf = styleOf(o.markers, SHAPES, 'none');
36
+ var patOf = k > 1 ? styleOf(o.patterns, PATTERNS, 'solid') : null, bg = o.background || th.tile, defs = '', fills = [];
37
+ for (var q = 0; patOf && q < k; q++) {
38
+ if (patOf(q) === 'solid') continue;
39
+ var pid = newId('g');
40
+ defs += pattern(pid, patOf(q), pal[q % pal.length], bg);
41
+ fills[q] = 'url(#' + pid + ')';
42
+ }
43
+ // The legend shows each band's pattern, or a sample of its edge when lines have dashes or markers.
44
+ var key = patOf
45
+ ? function (j, x, y) { return '<rect x="' + r2(x) + '" y="' + r2(y + 1) + '" width="10" height="10" rx="2" fill="' + (fills[j] || pal[j % pal.length]) + '"/>'; }
46
+ : (dashOf || markOf) && lineKey(pal, dashOf, markOf, bg);
47
+ var share = function (j, i) { return pos[i] ? Math.round(Math.max(0, val(j, i)) / pos[i] * 100) : 0; };
48
+
49
+ return tile(o, th, h, function (x0, y0, w, h) {
50
+ if (!n) return emptyState(th, x0, y0, w, h);
51
+ var f = xyFrame(o, th, {
52
+ n: n, names: multi ? S.map(function (_, j) { return nameOf(j); }) : null, pal: pal, key: key, kw: key && (patOf ? 15 : 24),
53
+ lo: Math.min.apply(null, edges), hi: Math.max.apply(null, edges), zero: true, labels: labels, notes: notes,
54
+ tick: mode === 'percent' ? function (t) { return fmt(t, { lang: o.lang }, true) + '%'; } : function (t) { return fmt(t, o, true); },
55
+ }, x0, y0, w, h);
56
+ var s = (defs ? '<defs>' + defs + '</defs>' : '') + f.svg, X = f.X, Y = f.Y;
57
+ // One value stretches across the chart, like a line chart does.
58
+ var pts = function (ys) {
59
+ var P = ys.map(function (y, i) { return [X(i), Y(y)]; });
60
+ return P.length === 1 ? [[f.px, P[0][1]], [f.px + f.pw, P[0][1]]] : P;
61
+ };
62
+ var straight = bool(o.straight), alpha = mode ? '.8' : '.22';
63
+ var shown = function (j) { return mode ? highs[j] : S[j]; };
64
+ // Fills first, so no band covers another's edge.
65
+ S.forEach(function (_, j) {
66
+ var top = pts(shown(j)), base = pts(mode ? lows[j] : shown(j).map(function () { return 0; })).reverse();
67
+ s += '<path d="' + pathOf(top, straight) + pathOf(base, straight).replace(/^M/, 'L') + 'Z" fill="' + (fills[j] || pal[j % pal.length]) +
68
+ '" fill-opacity="' + alpha + '"' + (o.animate ? ' class="bzc-a" style="animation-delay:' + r2(j * 0.1) + 's"' : '') + '/>';
69
+ });
70
+ S.forEach(function (_, j) {
71
+ var c = pal[j % pal.length], ys = shown(j), P = pts(ys), mk = markOf ? markOf(j) : 'none';
72
+ s += seriesLine(o, pathOf(P, straight), c, j, dashOf ? DASHES[dashOf(j)] : '');
73
+ if (mk !== 'none') s += pointMarks(o, mk, ys, X, Y, c, bg, j);
74
+ else if (!mode) s += '<circle cx="' + r2(P[P.length - 1][0]) + '" cy="' + r2(P[P.length - 1][1]) + '" r="4" fill="' + c + '" stroke="' + bg + '" stroke-width="2"/>';
75
+ if (bool(o.showValues) && !mode) ys.forEach(function (y, i) { s += text(X(i), Y(y) - 8, fmt(y, o, true), small(th, 9, 'text-anchor="middle"')); });
76
+ });
77
+ // A stack writes its total above each column. Every column of a percent stack is 100%, so it writes nothing.
78
+ if (bool(o.showValues) && mode === 'stack') {
79
+ totals.forEach(function (t, i) {
80
+ var top = Math.max.apply(null, highs.map(function (hs) { return hs[i]; }).concat([0]));
81
+ s += text(X(i), Y(top) - 8, fmt(t, o, true), small(th, 9, 'text-anchor="middle"'));
82
+ });
83
+ }
84
+ return s + xyFinish(o, th, f, n, function (i) {
85
+ var tip = labels[i] || '#' + (i + 1);
86
+ S.forEach(function (ser, j) {
87
+ if (i < ser.length) tip += '\n' + (multi ? nameOf(j) + ': ' : '') + fmt(ser[i], o) + (mode === 'percent' ? ' (' + share(j, i) + '%)' : '');
88
+ });
89
+ return tip + (mode ? '\nTotal: ' + fmt(totals[i], o) : '');
90
+ });
91
+ }, {
92
+ stat: statOf(mode ? totals : S[0] || [], o, ''),
93
+ summary: k + ' series ' + (mode === 'percent' ? 'as shares of each total' : mode ? 'stacked' : 'filled') + ' over ' + n + ' points',
94
+ });
95
+ }
96
+
97
+ area.table = function (o) { var S = series(o.values); return seriesTable(o, S.length > 1 && (o.stacked === 'percent' || bool(o.stacked))); };
@@ -1,5 +1,6 @@
1
- import { newId, r2, clamp, num, has, list, series, tw, bool, fmt, pathOf, text, small, hit, anim, palette, emptyState, parseNotes, goalLine, statOf } from '../core/util.js';
2
- import { niceScale, legend, seriesTable, styleOf, marker, DASHES, SHAPES } from '../core/series.js';
1
+ import { newId, r2, num, list, series, bool, fmt, pathOf, text, small, anim, palette, emptyState, parseNotes, statOf } from '../core/util.js';
2
+ import { seriesTable, styleOf, DASHES, SHAPES } from '../core/series.js';
3
+ import { xyFrame, xyFinish, lineKey, seriesLine, pointMarks } from '../core/xy.js';
3
4
  import { tile } from '../core/tile.js';
4
5
 
5
6
  export default function line(o, th) {
@@ -10,49 +11,17 @@ export default function line(o, th) {
10
11
  var dashOf = styleOf(o.dash, Object.keys(DASHES), 'solid'), markOf = styleOf(o.markers, SHAPES, 'none');
11
12
  var bg = o.background || th.tile;
12
13
  // With dashes or markers, the legend shows a short sample of each line instead of a dot.
13
- var key = (dashOf || markOf) && function (k, x, y) {
14
- var c = pal[k % pal.length], dk = dashOf ? DASHES[dashOf(k)] : '', mk = markOf ? markOf(k) : 'none';
15
- return '<line x1="' + r2(x) + '" x2="' + r2(x + 18) + '" y1="' + r2(y + 6) + '" y2="' + r2(y + 6) + '" stroke="' + c + '" stroke-width="2.5" stroke-linecap="round"' +
16
- (dk ? ' stroke-dasharray="' + dk + '"' : '') + '/>' + (mk !== 'none' ? marker(mk, x + 9, y + 6, 3.5, ' fill="' + c + '" stroke="' + bg + '" stroke-width="1.5"') : '');
17
- };
14
+ var key = (dashOf || markOf) && lineKey(pal, dashOf, markOf, bg);
15
+ var nameOf = function (k) { return names[k] || 'Series ' + (k + 1); };
18
16
  return tile(o, th, h, function (x0, y0, w, h) {
19
17
  if (!n) return emptyState(th, x0, y0, w, h);
20
- var s = '', top = y0;
21
- if (multi) {
22
- var lg = legend(S.map(function (_, k) { return names[k] || 'Series ' + (k + 1); }), pal, th, x0, top, w, key, key && 24);
23
- s += lg.svg;
24
- top += lg.height;
25
- }
26
18
  var all = [].concat.apply([], S);
27
- var mn = Math.min.apply(null, all), mx = Math.max.apply(null, all);
28
- if (has(o.goal)) { mn = Math.min(mn, +o.goal); mx = Math.max(mx, +o.goal); }
29
- if (bool(o.zero)) { mn = Math.min(0, mn); mx = Math.max(0, mx); }
30
- var sc = niceScale(mn, mx, 4);
31
- var tl = sc.ticks.map(function (t) { return fmt(t, o, true); });
32
- var axisW = Math.max.apply(null, tl.map(function (t) { return tw(t, 10, true); })) + 10;
33
- var bottom = labels.length ? 20 : 4;
34
- var px = x0 + axisW, pw = w - axisW, ph = h - (top - y0) - bottom;
35
- var X = function (i) { return n === 1 ? px + pw / 2 : px + i * pw / (n - 1); };
36
- var Y = function (v) { return top + ph - (v - sc.lo) / (sc.hi - sc.lo) * ph; };
37
- sc.ticks.forEach(function (t, i) {
38
- var y = Y(t);
39
- s += '<line x1="' + r2(px) + '" x2="' + r2(px + pw) + '" y1="' + r2(y) + '" y2="' + r2(y) + '" stroke="' + th.grid + '"' + (t === 0 ? '' : ' stroke-dasharray="2 4"') + '/>' +
40
- text(px - 8, y + 3.5, tl[i], small(th, 10, 'text-anchor="end"'));
41
- });
42
- if (labels.length) {
43
- var every = Math.max(1, Math.ceil(n * (Math.max.apply(null, labels.map(function (l) { return tw(l, 10, true); })) + 10) / pw));
44
- for (var i = 0; i < n; i += every) {
45
- if (labels[i] == null) continue;
46
- var anchor = n > 1 && i === 0 ? 'start' : n > 1 && i === n - 1 ? 'end' : 'middle';
47
- s += text(X(i), top + ph + 15, labels[i], small(th, 10, 'text-anchor="' + anchor + '"'));
48
- }
49
- }
50
- notes.forEach(function (nt) {
51
- if (nt.i >= n) return;
52
- var x = X(nt.i);
53
- s += '<line x1="' + r2(x) + '" x2="' + r2(x) + '" y1="' + r2(top + 12) + '" y2="' + r2(top + ph) + '" stroke="' + th.fg + '" stroke-opacity=".4" stroke-dasharray="3 3"/>' +
54
- text(clamp(x, px + 30, px + pw - 30), top + 8, nt.text, small(th, 10, 'text-anchor="middle"', th.fg));
55
- });
19
+ var f = xyFrame(o, th, {
20
+ n: n, names: multi ? S.map(function (_, k) { return nameOf(k); }) : null, pal: pal, key: key, kw: key && 24,
21
+ lo: Math.min.apply(null, all), hi: Math.max.apply(null, all), zero: bool(o.zero), labels: labels, notes: notes,
22
+ tick: function (t) { return fmt(t, o, true); },
23
+ }, x0, y0, w, h);
24
+ var s = f.svg, X = f.X, Y = f.Y, px = f.px, pw = f.pw, top = f.top, ph = f.ph;
56
25
  S.forEach(function (v, k) {
57
26
  var c = pal[k % pal.length];
58
27
  var P = v.map(function (y, i) { return [X(i), Y(y)]; });
@@ -63,31 +32,21 @@ export default function line(o, th) {
63
32
  s += '<defs><linearGradient id="' + g + '" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="' + c + '" stop-opacity=".26"/><stop offset="1" stop-color="' + c + '" stop-opacity="0"/></linearGradient></defs>' +
64
33
  '<path d="' + d + 'L' + r2(last[0]) + ',' + r2(top + ph) + 'L' + r2(P[0][0]) + ',' + r2(top + ph) + 'Z" fill="url(#' + g + ')"' + anim(o, 'bzc-a') + '/>';
65
34
  }
66
- var dk = dashOf ? DASHES[dashOf(k)] : '', mk = markOf ? markOf(k) : 'none';
67
- // The draw-in animation is itself a dash, so dashed lines fade in instead.
68
- s += dk
69
- ? '<path d="' + d + '" fill="none" stroke="' + c + '" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="' + dk + '"' + anim(o, 'bzc-a', k * 0.15) + '/>'
70
- : '<path d="' + d + '" fill="none" stroke="' + c + '" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" pathLength="1" style="stroke-dasharray:1' + (o.animate ? ';animation-delay:' + k * 0.15 + 's' : '') + '"' + (o.animate ? ' class="bzc-d"' : '') + '/>';
35
+ var mk = markOf ? markOf(k) : 'none';
36
+ s += seriesLine(o, d, c, k, dashOf ? DASHES[dashOf(k)] : '');
71
37
  if (mk !== 'none') {
72
- // Long series get a marker on every few points, and always on the last.
73
- var every = Math.ceil(v.length / 40);
74
- v.forEach(function (y, i) {
75
- if (i % every === 0 || i === v.length - 1) s += marker(mk, X(i), Y(y), 3.5, ' fill="' + c + '" stroke="' + bg + '" stroke-width="1.5"' + anim(o, 'bzc-a', 0.6 + k * 0.15));
76
- });
38
+ s += pointMarks(o, mk, v, X, Y, c, bg, k);
77
39
  } else {
78
40
  var e = P[P.length - 1];
79
41
  s += '<circle cx="' + r2(e[0]) + '" cy="' + r2(e[1]) + '" r="4" fill="' + c + '" stroke="' + bg + '" stroke-width="2"/>';
80
42
  }
81
43
  if (bool(o.showValues)) v.forEach(function (y, i) { s += text(X(i), Y(y) - 8, fmt(y, o, true), small(th, 9, 'text-anchor="middle"')); });
82
44
  });
83
- if (has(o.goal)) s += goalLine(o, th, px, px + pw, Y(+o.goal));
84
- var step = n > 1 ? pw / (n - 1) : pw;
85
- for (var j = 0; j < n; j++) {
45
+ return s + xyFinish(o, th, f, n, function (j) {
86
46
  var tip = labels[j] || '#' + (j + 1);
87
- S.forEach(function (v, k) { if (j < v.length) tip += '\n' + (multi ? (names[k] || 'Series ' + (k + 1)) + ': ' : '') + fmt(v[j], o); });
88
- s += hit(X(j) - step / 2, top, step, ph, tip);
89
- }
90
- return s;
47
+ S.forEach(function (v, k) { if (j < v.length) tip += '\n' + (multi ? nameOf(k) + ': ' : '') + fmt(v[j], o); });
48
+ return tip;
49
+ });
91
50
  }, { stat: st, summary: S.length + ' series over ' + n + ' points' });
92
51
  }
93
52
 
package/src/core/xy.js ADDED
@@ -0,0 +1,81 @@
1
+ /** The axis frame and series lines line and area charts share. Kept apart so other charts don't load them. */
2
+ import { r2, clamp, has, tw, text, small, hit, anim, goalLine } from './util.js';
3
+ import { niceScale, legend, marker, DASHES } from './series.js';
4
+
5
+ /**
6
+ * The frame line and area charts share: the legend, the value axis with its gridlines, labels along the bottom and notes.
7
+ * c holds n (points), names (legend names, or null for no legend), pal, key and kw (legend swatches), lo and hi (the data
8
+ * range), zero (keep zero on the axis), labels, notes and tick (formats an axis number).
9
+ * Returns the SVG so far, the scales X(i) and Y(v), and the plot box: px, pw, top, ph.
10
+ */
11
+ export function xyFrame(o, th, c, x0, y0, w, h) {
12
+ var s = '', top = y0, n = c.n, labels = c.labels;
13
+ if (c.names) {
14
+ var lg = legend(c.names, c.pal, th, x0, top, w, c.key, c.kw);
15
+ s += lg.svg;
16
+ top += lg.height;
17
+ }
18
+ var mn = c.lo, mx = c.hi;
19
+ if (has(o.goal)) { mn = Math.min(mn, +o.goal); mx = Math.max(mx, +o.goal); }
20
+ if (c.zero) { mn = Math.min(0, mn); mx = Math.max(0, mx); }
21
+ var sc = niceScale(mn, mx, 4);
22
+ var tl = sc.ticks.map(c.tick);
23
+ var axisW = Math.max.apply(null, tl.map(function (t) { return tw(t, 10, true); })) + 10;
24
+ var bottom = labels.length ? 20 : 4;
25
+ var px = x0 + axisW, pw = w - axisW, ph = h - (top - y0) - bottom;
26
+ var X = function (i) { return n === 1 ? px + pw / 2 : px + i * pw / (n - 1); };
27
+ var Y = function (v) { return top + ph - (v - sc.lo) / (sc.hi - sc.lo) * ph; };
28
+ sc.ticks.forEach(function (t, i) {
29
+ var y = Y(t);
30
+ s += '<line x1="' + r2(px) + '" x2="' + r2(px + pw) + '" y1="' + r2(y) + '" y2="' + r2(y) + '" stroke="' + th.grid + '"' + (t === 0 ? '' : ' stroke-dasharray="2 4"') + '/>' +
31
+ text(px - 8, y + 3.5, tl[i], small(th, 10, 'text-anchor="end"'));
32
+ });
33
+ if (labels.length) {
34
+ var every = Math.max(1, Math.ceil(n * (Math.max.apply(null, labels.map(function (l) { return tw(l, 10, true); })) + 10) / pw));
35
+ for (var i = 0; i < n; i += every) {
36
+ if (labels[i] == null) continue;
37
+ var anchor = n > 1 && i === 0 ? 'start' : n > 1 && i === n - 1 ? 'end' : 'middle';
38
+ s += text(X(i), top + ph + 15, labels[i], small(th, 10, 'text-anchor="' + anchor + '"'));
39
+ }
40
+ }
41
+ c.notes.forEach(function (nt) {
42
+ if (nt.i >= n) return;
43
+ var x = X(nt.i);
44
+ s += '<line x1="' + r2(x) + '" x2="' + r2(x) + '" y1="' + r2(top + 12) + '" y2="' + r2(top + ph) + '" stroke="' + th.fg + '" stroke-opacity=".4" stroke-dasharray="3 3"/>' +
45
+ text(clamp(x, px + 30, px + pw - 30), top + 8, nt.text, small(th, 10, 'text-anchor="middle"', th.fg));
46
+ });
47
+ return { svg: s, X: X, Y: Y, px: px, pw: pw, top: top, ph: ph };
48
+ }
49
+
50
+ /** The goal line, then one hover column per point, centred on it. tip(j) gives each column's tooltip. */
51
+ export function xyFinish(o, th, f, n, tip) {
52
+ var s = has(o.goal) ? goalLine(o, th, f.px, f.px + f.pw, f.Y(+o.goal)) : '';
53
+ var step = n > 1 ? f.pw / (n - 1) : f.pw;
54
+ for (var j = 0; j < n; j++) s += hit(f.X(j) - step / 2, f.top, step, f.ph, tip(j));
55
+ return s;
56
+ }
57
+
58
+ /** A legend swatch for a line: a short sample with its dash and marker. */
59
+ export function lineKey(pal, dashOf, markOf, bg) {
60
+ return function (k, x, y) {
61
+ var c = pal[k % pal.length], dk = dashOf ? DASHES[dashOf(k)] : '', mk = markOf ? markOf(k) : 'none';
62
+ return '<line x1="' + r2(x) + '" x2="' + r2(x + 18) + '" y1="' + r2(y + 6) + '" y2="' + r2(y + 6) + '" stroke="' + c + '" stroke-width="2.5" stroke-linecap="round"' +
63
+ (dk ? ' stroke-dasharray="' + dk + '"' : '') + '/>' + (mk !== 'none' ? marker(mk, x + 9, y + 6, 3.5, ' fill="' + c + '" stroke="' + bg + '" stroke-width="1.5"') : '');
64
+ };
65
+ }
66
+
67
+ /** A series line along path d. The draw-in animation is itself a dash, so dashed lines fade in instead. */
68
+ export function seriesLine(o, d, c, k, dk) {
69
+ return dk
70
+ ? '<path d="' + d + '" fill="none" stroke="' + c + '" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="' + dk + '"' + anim(o, 'bzc-a', k * 0.15) + '/>'
71
+ : '<path d="' + d + '" fill="none" stroke="' + c + '" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" pathLength="1" style="stroke-dasharray:1' + (o.animate ? ';animation-delay:' + k * 0.15 + 's' : '') + '"' + (o.animate ? ' class="bzc-d"' : '') + '/>';
72
+ }
73
+
74
+ /** Markers on a series' points. Long series get one on every few points, and always on the last. */
75
+ export function pointMarks(o, mk, ys, X, Y, c, bg, k) {
76
+ var s = '', every = Math.ceil(ys.length / 40);
77
+ ys.forEach(function (y, i) {
78
+ if (i % every === 0 || i === ys.length - 1) s += marker(mk, X(i), Y(y), 3.5, ' fill="' + c + '" stroke="' + bg + '" stroke-width="1.5"' + anim(o, 'bzc-a', 0.6 + k * 0.15));
79
+ });
80
+ return s;
81
+ }
@@ -0,0 +1,10 @@
1
+ /** <bezel-area> on its own: import 'bezel-charts/area', or load dist/charts/area.js. */
2
+ import area from '../charts/area.js';
3
+ import { register } from '../render.js';
4
+ import { define } from '../element.js';
5
+
6
+ register('area', area);
7
+ define('area');
8
+
9
+ export { render, toSVG } from '../render.js';
10
+ export { BezelChart } from '../element.js';
package/src/index.js CHANGED
@@ -6,6 +6,7 @@
6
6
  // Each entry registers its chart and defines its tag. Pages that only need a few charts can import those entries instead.
7
7
  import './entries/spark.js';
8
8
  import './entries/line.js';
9
+ import './entries/area.js';
9
10
  import './entries/bars.js';
10
11
  import './entries/scatter.js';
11
12
  import './entries/ring.js';
@@ -17,6 +18,6 @@ import { NAMES, render, toSVG } from './render.js';
17
18
  import { THEMES } from './core/themes.js';
18
19
  import { BezelChart } from './element.js';
19
20
 
20
- export const version = '1.3.0';
21
+ export const version = '1.4.0';
21
22
  export const types = NAMES.slice();
22
23
  export { render, toSVG, BezelChart, THEMES as themes };
package/src/render.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import { THEMES } from './core/themes.js';
3
3
  import { bool } from './core/util.js';
4
4
  /** Every chart type, in the order the full bundle loads them. */
5
- export const NAMES = ['spark', 'line', 'bars', 'scatter', 'ring', 'donut', 'gauge', 'progress', 'heatmap'];
5
+ export const NAMES = ['spark', 'line', 'area', 'bars', 'scatter', 'ring', 'donut', 'gauge', 'progress', 'heatmap'];
6
6
 
7
7
  /** The renderers loaded so far. Each chart's entry file adds its own, so a page only loads the charts it uses. */
8
8
  export const TYPES = {};
@@ -1,2 +0,0 @@
1
- /*! Bezel Charts v1.3.0 | MIT | github.com/ShazMoghaddam/bezel-charts */
2
- var g={dark:{tile:"#15151d",bezel:"#000000",fg:"#f2f1f7",muted:"#8c8aa0",grid:"#2a2935",up:"#5EE6C8",down:"#F675A8",palette:["#9FA1FF","#F675A8","#5EE6C8","#FFC857","#7CC4FF","#FF8A5B"]},light:{tile:"#ffffff",bezel:"#000000",fg:"#17161f",muted:"#6b6980",grid:"#e8e6ef",up:"#12a383",down:"#d63f7c",palette:["#6E70F0","#E2508C","#16A884","#D99A0E","#2F8FE0","#EE6431"]}};var x="ui-sans-serif,system-ui,-apple-system,'Segoe UI',Roboto,Helvetica,Arial,sans-serif",w="ui-monospace,SFMono-Regular,Menlo,Consolas,monospace",W=0;function nt(t){return"bzc"+t+(++W).toString(36)+Math.random().toString(36).slice(2,6)}function h(t){return String(t??"").replace(/[&<>"']/g,function(e){return{"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"}[e]})}function s(t){return Math.round(t*100)/100}function u(t,e,r){return Math.max(e,Math.min(r,t))}function v(t,e){var r=parseFloat(t);return isFinite(r)?r:e}function c(t){return t!=null&&t!==""}function T(t){return Array.isArray(t)?t.map(function(e){var r=+e;return isFinite(r)?r:0}):c(t)?String(t).split(/[\s,;]+/).filter(Boolean).map(function(e){var r=+e;return isFinite(r)?r:0}):[]}function V(t){return Array.isArray(t)?t.map(String):c(t)?String(t).split(",").map(function(e){return e.trim()}):[]}function at(t){return Array.isArray(t)?Array.isArray(t[0])?t.map(T):[T(t)]:c(t)?String(t).split("|").map(T).filter(function(e){return e.length}):[]}function Y(t){return t.reduce(function(e,r){return e+r},0)}function ot(t,e,r){return String(t).length*e*(r?.6:.56)}function st(t,e){return t=String(t),t.length>e?t.slice(0,Math.max(1,e-1))+"\u2026":t}function C(t){return t===!0||t===""||t==="true"||t==="1"}function k(t,e,r){if(!isFinite(t))return"\u2013";var i=Math.abs(t),n;c(e.decimals)?n=u(parseInt(e.decimals,10)||0,0,6):n=t%1===0?0:i<10?2:i<100?1:0;var a={maximumFractionDigits:n,minimumFractionDigits:c(e.decimals)?n:0};(C(e.compact)||r)&&i>=1e4&&(a={notation:"compact",maximumFractionDigits:1});var o;try{o=new Intl.NumberFormat(e.lang||"en-GB",a).format(i)}catch{o=String(s(i))}return(t<0?"\u2212":"")+(e.prefix||"")+o+(e.suffix||"")}function lt(t,e){if(!t.length)return"";for(var r="M"+s(t[0][0])+","+s(t[0][1]),i=1;i<t.length;i++){var n=t[i-1],a=t[i];if(e)r+="L"+s(a[0])+","+s(a[1]);else{var o=(n[0]+a[0])/2;r+="C"+s(o)+","+s(n[1])+" "+s(o)+","+s(a[1])+" "+s(a[0])+","+s(a[1])}}return r}function p(t,e,r,i){return'<text x="'+s(t)+'" y="'+s(e)+'" '+(i||"")+">"+h(r)+"</text>"}function F(t,e,r,i){return'fill="'+(i||t.muted)+'" font-family="'+w+'" font-size="'+(e||10)+'"'+(r?" "+r:"")}function ct(t,e,r,i,n){return'<rect class="bzc-hit" x="'+s(t)+'" y="'+s(e)+'" width="'+s(Math.max(1,r))+'" height="'+s(Math.max(1,i))+'" fill="#000" fill-opacity="0" data-tip="'+h(n)+'"/>'}function ht(t,e,r){return t.animate?' class="'+e+'"'+(r?' style="animation-delay:'+s(r)+'s"':""):""}function ut(t,e){var r=V(t.color).filter(Boolean);return r.length?r:e.palette}function dt(t,e,r,i,n){return p(e+i/2,r+n/2+4,"No data yet",'text-anchor="middle" fill="'+t.muted+'" font-family="'+x+'" font-size="13"')}function ft(t,e){return c(t.notes)?String(t.notes).split(";").map(function(r){var i=r.indexOf(":");if(i<0)return null;var n=r.slice(0,i).trim(),a=r.slice(i+1).trim(),o=e.map(String).indexOf(n);return o<0&&String(parseInt(n,10))===n&&(o=parseInt(n,10)),o>=0&&a?{i:o,text:a}:null}).filter(Boolean):[]}function mt(t,e,r,i,n){var a=(c(t.goalLabel)?t.goalLabel:"Goal")+" "+k(v(t.goal,0),t);return'<line x1="'+s(r)+'" x2="'+s(i)+'" y1="'+s(n)+'" y2="'+s(n)+'" stroke="'+e.fg+'" stroke-opacity=".55" stroke-width="1.25" stroke-dasharray="4 4"/>'+p(i,n-5,a,F(e,10,'text-anchor="end"'))}function pt(t,e,r){var i=String(c(e.stat)?e.stat:r||"").toLowerCase();if(!i||i==="none"||!t.length)return null;var n=Y(t),a={last:t[t.length-1],total:n,sum:n,average:n/t.length,avg:n/t.length,max:Math.max.apply(null,t),min:Math.min.apply(null,t)};if(!(i in a))return null;var o=null;return i==="last"&&t.length>1&&e.delta!=="none"&&(o=t[t.length-1]-t[0]),{val:a[i],delta:o}}var N=["spark","line","bars","scatter","ring","donut","gauge","progress","heatmap"],A={};function wt(t,e){A[t]=e}var X=t=>t.replace(/-([a-z])/g,(e,r)=>r.toUpperCase());function U(t,e){if(!A[t])throw new Error(N.includes(t)?`Bezel Charts: the ${t} chart isn't loaded. Add import 'bezel-charts/${t}', or load dist/charts/${t}.js.`:`Bezel Charts: unknown chart type "${t}". Choose one of: ${N.join(", ")}.`);let r={};for(let[i,n]of Object.entries(e))r[X(i)]=n;return r}function S(t,e={}){let r=U(t,e);r.animate=C(r.animate),r.frame=r.frame==="none"?"none":"bezel";let i=r.theme==="light"||r.theme==="dark"?r.theme:r.autoTheme||"dark";return A[t](r,g[i])}function j(t,e={}){return A[t].table(U(t,e))}function $(t){return t.replace(/<rect class="bzc-hit"[^>]*\/>/g,"").replace(/<circle[^>]* class="bzc-hit"[^>]*\/>/g,"").replace(/ data-tip="[^"]*"/g,"")}function yt(t,e={}){return $(S(t,{...e,animate:!1}))}var q=["type","values","labels","series","heading","prefix","suffix","decimals","compact","color","theme","frame","width","height","goal","goal-label","notes","show-values","stat","delta","delta-label","max","min","value","zones","horizontal","straight","zero","start","lang","corners","background","center-label","highlight","x","y","x-label","y-label","trend","static","no-tooltips","stacked","angle-labels","dash","markers","patterns"],_=`:host{display:block;position:relative;max-width:100%}:host([hidden]){display:none}svg{display:block;max-width:100%;height:auto;overflow:visible}.tip{position:absolute;left:0;top:0;pointer-events:none;background:#0b0b10;color:#f2f1f7;font:600 12px/1.5 ${w};padding:7px 10px;border-radius:10px;white-space:pre;opacity:0;transform:translate(-50%,calc(-100% - 12px));transition:opacity .12s;z-index:3;border:1px solid #2a2935;box-shadow:0 8px 24px rgba(0,0,0,.35)}.tip.on{opacity:1}.c{outline:none}.c:focus-visible{outline:2px solid #fff;outline-offset:3px;box-shadow:0 0 0 7px #000}.k{stroke:currentColor;stroke-width:2;stroke-opacity:1}.sr{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}@media (forced-colors:active){.c:focus-visible{outline-color:Highlight}}`,Q={ArrowLeft:-1,ArrowUp:-1,ArrowRight:1,ArrowDown:1},J=()=>typeof matchMedia=="function"?matchMedia("(prefers-color-scheme: dark)"):null,K=()=>{let t=typeof document<"u"&&document.documentElement?.getAttribute?.("data-theme");return t==="light"||t==="dark"?t:null},R=new Set;typeof MutationObserver=="function"&&typeof document<"u"&&document.documentElement&&new MutationObserver(()=>R.forEach(t=>t.refresh())).observe(document.documentElement,{attributes:!0,attributeFilter:["data-theme"]});var Z=typeof HTMLElement>"u"?class{}:HTMLElement,z=class extends Z{static get observedAttributes(){return q}static get themes(){return g}get resolvedTheme(){let e=this.getAttribute("theme");return e==="light"||e==="dark"?e:this.options.autoTheme}get chartType(){return this.getAttribute("type")||"spark"}connectedCallback(){this.shadowRoot||(this.attachShadow({mode:"open"}).innerHTML=`<style>${_}</style><div class="c" role="group" aria-roledescription="chart"></div><p class="sr" id="h">Use the arrow keys to step through the values.</p><div class="tip" aria-hidden="true"></div><div class="sr" aria-live="polite"></div><div class="sr"></div>`,[,this.#t,,this.#r,this.#s,this.#h]=this.shadowRoot.children,this.shadowRoot.addEventListener("pointermove",e=>this.#d(e)),this.shadowRoot.addEventListener("pointerdown",e=>this.#d(e)),this.addEventListener("pointerleave",()=>this.#r.classList.remove("on")),this.#t.addEventListener("keydown",e=>this.#g(e)),this.#t.addEventListener("blur",()=>this.#b())),R.add(this),this.#i=J(),this.#i?.addEventListener?.("change",this.#u),typeof ResizeObserver=="function"?(this.#o=new ResizeObserver(([e])=>{let r=Math.round(e.contentRect.width);(!this.#n||!this.hasAttribute("width")&&r>0&&Math.abs(r-this.#l)>1)&&this.#a()}),this.#o.observe(this)):this.#a()}disconnectedCallback(){R.delete(this),this.#o?.disconnect(),this.#i?.removeEventListener?.("change",this.#u)}attributeChangedCallback(){!this.#n||this.#c||(this.#c=!0,queueMicrotask(()=>{this.#c=!1,this.#a()}))}get options(){let e={};for(let r of q)this.hasAttribute(r)&&(e[r]=this.getAttribute(r));return e.width||(e.width=this.#l||360),e.autoTheme=K()||(this.#i?this.#i.matches?"dark":"light":"dark"),e}refresh(){this.#n&&this.#a()}toSVG(e={}){return $(S(this.chartType,{...this.options,...e,animate:!1}))}download(e){let r=URL.createObjectURL(new Blob([this.toSVG()],{type:"image/svg+xml"})),i=Object.assign(document.createElement("a"),{href:r,download:`${(e||this.getAttribute("heading")||this.chartType).replace(/[^\w-]+/g,"-").toLowerCase()}.svg`});document.body.append(i),i.click(),i.remove(),setTimeout(()=>URL.revokeObjectURL(r),1e3)}#o=null;#t=null;#r=null;#s=null;#h=null;#e=-1;#i=null;#l=0;#n=!1;#c=!1;#u=()=>{let e=this.getAttribute("theme");(!e||e==="auto")&&this.refresh()};#a(){if(!this.shadowRoot)return;let e=Math.round(this.getBoundingClientRect?.().width||0);this.#l=e>0?e:360;let r=this.options;r.animate=!this.#n&&!this.hasAttribute("static");let i,n=null;try{i=S(this.chartType,r),n=j(this.chartType,r)}catch(d){i=`<p style="font:13px ${x};color:#d63f7c">${h(d.message)}</p>`}let a=this.#t;a.innerHTML=i.replace(/<title>[\s\S]*?<\/title>/,"");let o=a.querySelector("svg");o?(a.setAttribute("aria-label",o.getAttribute("aria-label")),o.removeAttribute("role"),o.removeAttribute("aria-label"),o.setAttribute("aria-hidden","true")):a.removeAttribute("aria-label");let l=!!o&&!this.hasAttribute("no-tooltips");l?(a.setAttribute("tabindex","0"),a.setAttribute("aria-describedby","h")):(a.removeAttribute("tabindex"),a.removeAttribute("aria-describedby")),a.style.color=g[r.theme==="light"||r.theme==="dark"?r.theme:r.autoTheme].fg,a.style.borderRadius=`${r.frame==="none"?4:u(+r.corners||22,0,60)}px`,this.#h.innerHTML=n&&n.rows.length?tt(r.heading,n):"",this.#e>=0&&l&&this.shadowRoot.activeElement===a?this.#p(this.#e):this.#e=-1,this.#n=!0,this.dispatchEvent(new CustomEvent("bezel-render",{bubbles:!0}))}#d(e){if(this.hasAttribute("no-tooltips"))return;let r=e.target?.closest?.("[data-tip]");if(!r){this.#r.classList.remove("on");return}this.#f(r,e.clientX,e.clientY)}#f(e,r,i){let n=this.#r;n.textContent=e.getAttribute("data-tip");let a=this.getBoundingClientRect?.()||{left:0,top:0,width:0},o=n.offsetWidth/2;n.style.left=`${u(r-a.left,o,Math.max(o,a.width-o))}px`,n.style.top=`${i-a.top}px`,n.classList.add("on")}#m(){return[...this.#t.querySelectorAll("[data-tip]:not([data-skip])")]}#g(e){let r=this.#m(),i=r.length;if(!i)return;let n=this.#e,a=Q[e.key];if(a)this.chartType==="heatmap"&&/Left|Right/.test(e.key)&&(a*=7),n=n<0?a>0?0:i-1:u(n+a,0,i-1);else if(e.key==="Home"||e.key==="End")n=e.key==="Home"?0:i-1;else{e.key==="Escape"&&this.#b();return}e.preventDefault(),this.#p(n,!0)}#p(e,r){let i=this.#m();if(!i.length)return;e=u(e,0,i.length-1),this.#t.querySelector(".k")?.classList.remove("k");let n=i[e],a=n.getBoundingClientRect?.()||{left:0,top:0,width:0};n.classList.add("k"),this.#e=e,this.#f(n,a.left+a.width/2,a.top),r&&(this.#s.textContent=`${n.getAttribute("data-tip").replace(/\n/g,", ")}. ${e+1} of ${i.length}`)}#b(){this.#t.querySelector(".k")?.classList.remove("k"),this.#r.classList.remove("on"),this.#s.textContent="",this.#e=-1}};function tt(t,{head:e,rows:r}){let i=n=>n.map((a,o)=>o?`<td>${h(a)}</td>`:`<th scope="row">${h(a)}</th>`).join("");return`<table><caption>${h(t||"Chart data")}</caption><thead><tr>${e.map(n=>`<th scope="col">${h(n)}</th>`).join("")}</tr></thead><tbody>${r.map(n=>`<tr>${i(n)}</tr>`).join("")}</tbody></table>`}function zt(t){typeof customElements>"u"||typeof HTMLElement>"u"||(customElements.get(`bezel-${t}`)||customElements.define(`bezel-${t}`,class extends z{get chartType(){return t}}),customElements.get("bezel-chart")||customElements.define("bezel-chart",class extends z{}))}function et(t){var e=Math.round(u(v(t.width,360),160,2400)),r=t.frame==="none"?0:4,i=t.frame==="none"?8:20;return{W:e,b:r,P:i,w:e-2*(r+i)}}var rt=".bzc-a{animation:bzc-in .6s ease both}.bzc-d{animation:bzc-draw 1.1s cubic-bezier(.3,.7,.2,1) both}.bzc-g{transform-box:fill-box;transform-origin:50% 100%;animation:bzc-grow .7s cubic-bezier(.2,.8,.2,1) both}.bzc-gn{transform-box:fill-box;transform-origin:50% 0;animation:bzc-grow .7s cubic-bezier(.2,.8,.2,1) both}.bzc-gx{transform-box:fill-box;transform-origin:0 50%;animation:bzc-growx .8s cubic-bezier(.2,.8,.2,1) both}.bzc-s{animation:bzc-sweep 1.1s cubic-bezier(.2,.8,.2,1) both}@keyframes bzc-in{from{opacity:0}}@keyframes bzc-draw{from{stroke-dashoffset:1}}@keyframes bzc-grow{from{transform:scaleY(0)}}@keyframes bzc-growx{from{transform:scaleX(0)}}@keyframes bzc-sweep{from{stroke-dasharray:0 100}}@media (prefers-reduced-motion:reduce){[class^=bzc-]{animation:none!important}}";function Ft(t,e,r,i,n){var a=et(t),o=a.W,l=a.b,d=a.P,O=a.w,E=u(v(t.corners,22),0,60),f=l+d,y="";c(t.heading)&&(y+=p(l+d,f+10,String(t.heading).toUpperCase(),F(e,11,'font-weight="600" letter-spacing="1.3"')),f+=24);var m=n&&n.stat;if(m){if(y+=p(l+d,f+30,k(m.val,t),'fill="'+e.fg+'" font-family="'+x+'" font-size="32" font-weight="800" letter-spacing="-0.5"'),m.delta!=null){var M=m.delta>0,H=m.delta===0,I=t.delta==="inverse"?!M:M,D=H?e.muted:I?e.up:e.down,P=(H?"\u25CF ":M?"\u25B2 ":"\u25BC ")+k(Math.abs(m.delta),t)+" "+(c(t.deltaLabel)?t.deltaLabel:"since start");y+=p(l+d+O,f+28,P,'text-anchor="end" fill="'+D+'" font-family="'+w+'" font-size="11" font-weight="600"')}f+=44}var G=i(l+d,f,O,r),b=Math.round(f+r+d+l),L="";t.frame!=="none"?L='<rect width="'+o+'" height="'+b+'" rx="'+E+'" fill="'+e.bezel+'"/><rect x="'+l+'" y="'+l+'" width="'+(o-2*l)+'" height="'+(b-2*l)+'" rx="'+Math.max(0,E-l)+'" fill="'+(t.background||e.tile)+'"/>':c(t.background)&&(L='<rect width="'+o+'" height="'+b+'" rx="'+E+'" fill="'+t.background+'"/>');var B=(c(t.heading)?t.heading+": ":"")+(n&&n.summary||"chart");return'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 '+o+" "+b+'" width="'+o+'" height="'+b+'" role="img" aria-label="'+h(B)+'"><title>'+h(B)+"</title>"+(t.animate?"<style>"+rt+"</style>":"")+L+y+G+"</svg>"}export{x as a,w as b,nt as c,h as d,s as e,u as f,v as g,c as h,T as i,V as j,at as k,Y as l,ot as m,st as n,C as o,k as p,lt as q,p as r,F as s,ct as t,ht as u,ut as v,dt as w,ft as x,mt as y,pt as z,et as A,Ft as B,wt as C,S as D,yt as E,z as F,zt as G};