@zumer/orbit
Version:
Orbit builds radial interfaces with CSS geometry and a small JavaScript layout runtime
154 lines (153 loc) • 28.4 kB
JavaScript
/*
* orbit
* v.2.0.1
* Author Juan Martin Muda - Zumerlab
* License MIT
*/
(()=>{var b=Symbol.for("zumer.orbit.layout.state.v1"),C=Symbol.for("zumer.orbit.layout.registry.v1"),H=Symbol.for("zumer.orbit.layout.probe.v1"),V="o-arc, o-progress",j={subtree:!0,childList:!0,characterData:!0,attributes:!0,attributeOldValue:!0};function $(s){var t;for(let r of s.classList||[])if(/^orbit-\d+$/.test(r))return Number(r.slice(6));return(t=s.classList)!=null&&t.contains("orbit")?null:void 0}var W=Symbol.for("zumer.orbit.warned.v1");function p(s,t,r){let i=s[W]||(s[W]=new Set);i.has(t)||(i.add(t),console.warn(`[orbit] ${r}`))}function _(s,t){var r,i;for(let e=s;e;e=e.parentElement||((r=e.getRootNode)==null?void 0:r.call(e).host))if((i=e.matches)!=null&&i.call(e,t))return e;return null}var Q=".satellite, .vector, .side, o-arc, o-progress";function A(s){let t=[...s.classList].slice(0,3).map(r=>"."+r).join("");return`<${s.localName}${t?" "+t:""}>`}function tt(s){let t=s.parentElement,r=_(t.parentElement,".bigbang, .satellite");r?r.getClientRects().length&&(!r.clientWidth||!r.clientHeight)&&p(r,"empty",`${A(r)} has no size (${r.clientWidth}\xD7${r.clientHeight}px), so its system is invisible. Give it a width, or place it in a parent with a width.`):p(t,"universe",'A .gravity-spot is not inside a .bigbang, so it measures the viewport. Wrap it: <div class="bigbang"><div class="gravity-spot">\u2026</div></div>.');let i=s.querySelector(":scope > o-arc, :scope > o-progress");if(i){let e=s.ownerDocument.defaultView.getComputedStyle(s),n=e.getPropertyValue("--o-ellipse-x").trim(),o=e.getPropertyValue("--o-ellipse-y").trim();(n&&Number(n)!==1||o&&Number(o)!==1)&&p(s,"ellipse-visual",`${A(i)} is on ${A(s)}, which is stretched into an ellipse (--o-ellipse-x: ${n||1}, --o-ellipse-y: ${o||1}). Arcs and progress are drawn on circles only, so it is hidden. Put it on a round ring.`)}if(_(s,".dev-orbit")){for(let e of s.children)if($(e)!==void 0)p(e,"nested-ring",`${A(e)} is inside another ring. Rings must be direct children of .gravity-spot; to nest a system, put a .gravity-spot directly inside a .satellite.`);else if(!e.matches(Q))p(e,"ring-child",`${A(e)} is not placed by its ring. A ring holds only .satellite, .vector, .side, <o-arc> and <o-progress>; wrap content as <div class="satellite"><div class="capsule">\u2026</div></div>.`);else if(e.classList.contains("satellite"))for(let n of e.children)n.matches(".capsule, .gravity-spot, .bigbang")||p(n,"satellite-child",`${A(n)} sits directly in a .satellite. Put content in a .capsule so it stays upright and centered.`)}}function v(s,t,r){let i=String(r);s.style.getPropertyValue(t)!==i&&s.style.setProperty(t,i)}function y(s,t,r=0,i="number"){let e=String(t||"").trim();if(!e)return r;if(i==="number"&&/^[+-]?(?:\d+\.?\d*|\.\d+)$/.test(e))return Number(e);let n=e.match(/^([+-]?(?:\d+\.?\d*|\.\d+))(deg|rad|grad|turn)?$/);if(i==="angle"&&n)return Number(n[1])*({deg:1,rad:180/Math.PI,grad:.9,turn:360}[n[2]]||1);let o=s.ownerDocument;if(!(o!=null&&o.documentElement))return r;let c=o[H];c||(c=o.createElement("span"),c.setAttribute("data-orbit-measure",""),c.setAttribute("aria-hidden","true"),c.style.cssText="all:initial!important;position:fixed!important;visibility:hidden!important;pointer-events:none!important;width:0!important;height:0!important;overflow:hidden!important;",o.documentElement.appendChild(c),Object.defineProperty(o,H,{value:c,configurable:!0}));let a=i==="angle"?"rotate":"scale";if(c.style.removeProperty(a),c.style.setProperty(a,e,"important"),!c.style.getPropertyValue(a))return r;let l=o.defaultView.getComputedStyle(c).getPropertyValue(a),u=parseFloat(l);return Number.isFinite(u)?u:r}function et(s){if(s.localName==="o-arc")return"arc";for(let t of["satellite","vector","side"])if(s.classList.contains(t))return t;return null}function rt(s){let t={arc:0,satellite:0,vector:0,side:0};for(let n of s.children){let o=et(n);o?v(n,"--o-layout-index",t[o]++-(o==="side"?1:0)):n.localName==="o-progress"&&v(n,"--o-layout-index",0)}let r=Math.max(t.arc,t.satellite,t.vector,1),i=t.satellite||t.vector,e=t.side?String(t.side):i?`max(1, ${r} - var(--o-fit-range, 0))`:String(r);v(s,"--o-layout-angle",`calc(var(--o-range, 360deg) / ${e})`)}function B(s){return(s==null?void 0:s.nodeType)===9||(s==null?void 0:s.nodeType)===11&&!!s.host}function R(s){var r;if(B(s))return s;let t=(r=s==null?void 0:s.getRootNode)==null?void 0:r.call(s);return B(t)?t:null}function z(s,t){var r,i;for(let e=t;e;e=(r=e.getRootNode)==null?void 0:r.call(e).host)if(s===e||(i=s.contains)!=null&&i.call(s,e))return!0;return!1}function st(s){return s[C]||Object.defineProperty(s,C,{value:{states:new Set},configurable:!0}),s[C]}function O(s){s.frame<0?s.view.clearTimeout(-s.frame):s.frame&&s.view.cancelAnimationFrame(s.frame),s.frame=0}function Z(s){for(let t of s.waiters.splice(0))t()}function q(s){if(!s.disposed){s.disposed=!0,O(s),Z(s),s.observer.disconnect(),s.resize.disconnect();for(let t of s.listeners)t();s.rings.clear(),s.visuals.clear(),s.dirty.clear(),s.registry.states.delete(s),s.scope[b]===s&&delete s.scope[b]}}function F(s){for(let t of s.states)t.scope.host&&!t.scope.host.isConnected&&q(t)}function k(s,t=s.scope){for(let r of s.registry.states)r!==s&&r.scope.host&&z(t,r.scope.host)&&(r.all=!0,r.queue())}function it(s){return s.nodeType!==1||s.hasAttribute("data-orbit-measure")?!1:$(s)!==void 0||s.matches(".gravity-spot, o-arc, o-progress")?!0:!!s.querySelector(".gravity-spot, .orbit, [data-orbit-ring], o-arc, o-progress")}function nt(s){return s.nodeType===1&&(s.matches('style, link[rel~="stylesheet"]')||!!s.querySelector('style, link[rel~="stylesheet"]'))}function ot(s,t){if(s.type==="childList")return[...s.addedNodes,...s.removedNodes].some(it);if(s.attributeName!=="class")return!1;let r=s.target;return t.rings.has(r)||r.classList.contains("gravity-spot")||$(r)!==void 0||(s.oldValue||"").split(/\s+/).some(i=>i==="gravity-spot"||i==="orbit"||/^orbit-\d+$/.test(i))}function at(s){let t=s.nodeType===9?s:s.ownerDocument,r=t.defaultView,i=st(t),e={scope:s,doc:t,view:r,registry:i,rings:new Set,visuals:new Set,dirty:new Set,scan:!0,all:!0,frame:0,disposed:!1,listeners:[],waiters:[]},n=(a,l,u,h)=>{a==null||a.addEventListener(l,u,h),e.listeners.push(()=>a==null?void 0:a.removeEventListener(l,u,h))},o=()=>{if(e.disposed||e.frame)return;let a=()=>{e.frame=0,e.flush()};e.frame=t.visibilityState==="hidden"?-r.setTimeout(a,0):r.requestAnimationFrame(a)};e.queue=o,e.flush=()=>lt(e),e.invalidate=(a=s,l=!0)=>{var u,h;if(l&&(a===s||a===t.documentElement||a===t.head))e.all=!0;else{for(let d of e.rings)(d===a||d.contains(a)||l&&((u=a.contains)!=null&&u.call(a,d)))&&e.dirty.add(d);for(let d of e.visuals)(d===a||d.contains(a)||l&&((h=a.contains)!=null&&h.call(a,d)))&&e.dirty.add(d)}(e.all||e.dirty.size||e.scan)&&o()},e.observer=new r.MutationObserver(a=>{var l,u;if(a.some(h=>h.type==="childList")&&F(i),!e.disposed)for(let h of a){let d=h.target.nodeType===3?h.target.parentElement:h.target;if(!d||(l=d.hasAttribute)!=null&&l.call(d,"data-orbit-measure"))continue;let g=ot(h,e);g&&(e.scan=!0),h.type==="childList"&&[...h.addedNodes,...h.removedNodes].some(nt)||(u=d.closest)!=null&&u.call(d,"head, style")||d.localName==="link"?(e.all=!0,k(e)):h.type==="attributes"&&k(e,d),e.invalidate(d,h.type==="attributes"||g)}}),e.observer.observe(s,j),e.resize=new r.ResizeObserver(a=>{for(let l of a)e.dirty.add(l.target);o()});let c=()=>{e.all=!0,k(e),o()};n(t,"visibilitychange",()=>{t.visibilityState==="hidden"&&e.frame>0&&(O(e),o())}),s===t&&(n(r,"resize",c),n(t.fonts,"loadingdone",c)),n(s,"load",a=>{a.target.localName==="link"&&c()},!0);for(let a of["pointerover","pointerout","focusin","focusout"])n(s,a,l=>{e.invalidate(l.target),k(e,l.target)},!0);return Object.defineProperty(s,b,{value:e,configurable:!0}),i.states.add(e),o(),e}function M(s){let t=s.nodeType===9?s:s.ownerDocument;if(!(t!=null&&t.defaultView)||!t.documentElement||s.host&&!s.host.isConnected)return null;if(s[b]&&s[b].doc!==t&&q(s[b]),s.host){let r=R(s.host);r&&M(r)}return s[b]||at(s)}function ct(s){let t=new Set,r=new Map;for(let e of s.scope.querySelectorAll(".gravity-spot > *")){let n=$(e);if(n===void 0)continue;let o=r.get(e.parentElement)||0;e.classList.contains("orbit")&&r.set(e.parentElement,++o);let c=n===null?o:n;e.setAttribute("data-orbit-ring",""),v(e,"--o-layout-number",c===0?1e-5:c),t.add(e),s.dirty.add(e),s.rings.has(e)||s.resize.observe(e)}for(let e of s.rings)if(!t.has(e)){s.resize.unobserve(e),e.removeAttribute("data-orbit-ring");for(let n of["--o-layout-number","--o-layout-angle"])e.style.removeProperty(n)}s.rings=t;let i=new Set(s.scope.querySelectorAll(V));for(let e of s.visuals)i.has(e)||s.resize.unobserve(e);for(let e of i)s.visuals.has(e)||(s.resize.observe(e),s.dirty.add(e));s.visuals=i,s.scan=!1}function lt(s){if(s.disposed)return;if(s.scope.host&&!s.scope.host.isConnected){q(s);return}s.observer.disconnect();let t=[];try{s.scan&&ct(s);let r=s.all?new Set([...s.rings,...s.visuals]):s.dirty,i=new Set;for(let e of r)if(e.isConnected)if(s.rings.has(e)){rt(e),tt(e);for(let n of e.querySelectorAll(V))i.add(n)}else s.visuals.has(e)&&i.add(e);for(let e of s.visuals)i.has(e)&&e.update&&(e.update(),t.push(e));s.dirty=new Set,s.all=!1}finally{s.disposed||s.observer.observe(s.scope,j)}for(let r of t)r.dispatchEvent(new s.view.Event("o-rendered",{bubbles:!0,composed:!0}));s.frame||Z(s)}function E(s=globalThis.document){var i;let t=R(s);if(!t)return;let r=M(t);r&&((i=s==null?void 0:s.matches)!=null&&i.call(s,V)&&!r.visuals.has(s)&&(r.scan=!0),r.invalidate(s||t))}function D(s=globalThis.document){let t=R(s);if(!t)return;let r=M(t);if(r){F(r.registry);for(let i of r.registry.states)i!==r&&(!i.scope.host||!z(s,i.scope.host))||(i.scan=!0,i.all=!0,O(i),i.flush())}}function G(s=globalThis.document){let t=R(s),r=t&&M(t);if(!r)return Promise.resolve();F(r.registry);let i=[...r.registry.states].filter(e=>e===r||e.scope.host&&z(s,e.scope.host));return Promise.all(i.map(e=>new Promise(n=>{e.waiters.push(n),e.queue()}))).then(()=>{})}var w=class extends(globalThis.HTMLElement||class{}){constructor(){super()}connectedCallback(){for(let t of["value","max"])if(Object.prototype.hasOwnProperty.call(this,t)){let r=this[t];delete this[t],this[t]=r}E(this)}get value(){let t=this.getAttribute("value");return t===null||t.trim()===""?null:Number(t)}set value(t){t==null||t===""?this.removeAttribute("value"):this.setAttribute("value",String(t))}get max(){let t=this.getAttribute("max");return t===null?100:Number(t)}set max(t){t==null||t===""?this.removeAttribute("max"):this.setAttribute("max",String(t))}disconnectedCallback(){this._textFrame&&this.ownerDocument.defaultView.cancelAnimationFrame(this._textFrame),this._textFrame=0}readNumber(t,r,i=0){return y(this,t.getPropertyValue(r),i)}readAngle(t,r,i=0){return y(this,t.getPropertyValue(r),i,"angle")}readValue(){let t=this.getAttribute("value");if(t===null||t.trim()==="")return 0;let r=Number(t);return Number.isFinite(r)?r:(p(this,"value:"+t,`<${this.localName} value="${t}"> is not a number, so nothing is drawn.`),0)}readMax(){let t=this.getAttribute("max");if(t===null)return 100;let r=Number(t);return r>0?r:(p(this,"max:"+t,`<${this.localName} max="${t}"> must be a positive number, so nothing is drawn.`),0)}getCommonAttributes(t){var g;let r=t.ownerDocument.defaultView.getComputedStyle(t),i=parseFloat(r.getPropertyValue("r")),e=Math.max(0,Number.isFinite(i)?i:(((g=t.parentElement)==null?void 0:g.clientWidth)||0)/2),n=Math.max(1e-5,this.readNumber(r,"--o-orbit-number",1)),o=Math.max(0,this.readNumber(r,"--o-size-ratio",1)),c=Math.max(0,this.readNumber(r,"--o-stroke-width",1)),a=t.getAttribute("shape")||"none",l=Math.max(0,e/n*o-c+.3),u=e>0?Math.min(49.999,l*25/e):0,h=0;t.classList.contains("outer-orbit")?h=u:t.classList.contains("quarter-outer-orbit")?h=u*-.5:t.classList.contains("inner-orbit")?h=u*-1:t.classList.contains("quarter-inner-orbit")&&(h=u*.5);let d=50+h;return{orbitRadius:e,arcHeight:l,realRadius:d,arcAngle:0,shape:a,arcHeightPercentage:u,orbitNumber:n,size:o,strokeWidth:c,style:r}}getProgressAngle(t,r,i=100){return!Number.isFinite(r)||!Number.isFinite(i)||i<=0?0:Math.min(1,Math.max(0,r/i))*Math.max(0,Math.min(360,t))}arcPoint(t,r,i=0,e=0){let n=t+i,o=r+e*Math.PI/180;return{x:50+n*Math.cos(o),y:50+n*Math.sin(o)}}calculateCommonArcParameters(t,r,i,e,n,o,c,a=0){let l=Math.PI/2,u=Math.max(0,Math.min(360,t))*Math.PI/180,h=r+i,d=Math.max(.001,r-i),g=Math.min(u*.49,(a+o*1.25)/e/h),m=Math.min(u*.49,(a+o*1.25)/e/d),f=g-l,x=u-g-l,P=m-l,S=u-m-l,U=this.arcPoint(h,f),X=this.arcPoint(h,x),Y=this.arcPoint(d,P),J=this.arcPoint(d,S);return{upperArcStart:U,upperArcEnd:X,innerArcStart:Y,innerArcEnd:J,bigRadius:h,smallRadius:d,radius:r,upperAngleStart:f,upperAngleEnd:x,innerAngleStart:P,innerAngleEnd:S}}generatePathData(t,r){switch(t){case"rounded":return this.generateRoundedPath(r);case"circle":case"circle-a":case"bullet":return this.generateCirclePath(r,t);case"circle-b":return this.generateCircleBPath(r);case"arrow":return this.generateArrowPath(r);case"backslash":case"slash":return this.generateSlashPath(r,t);case"zigzag":return this.generateZigzagPath(r);default:return this.generateDefaultPath(r)}}pt(t,r){let i=this.arcPoint(t,r);return`${i.x},${i.y}`}arcTo(t,r,i){let e=Math.max(1,Math.ceil(Math.abs(i-r)/(Math.PI/2)-1e-9)),n=i>=r?1:0,o="";for(let c=1;c<=e;c++)o+=` A ${t},${t} 0 0 ${n} ${this.pt(t,r+(i-r)*c/e)}`;return o}linePath(t,r,i){return`M ${this.pt(t,r)}${this.arcTo(t,r,i)}`}ending(t,r){let{bigRadius:i,smallRadius:e}=t,n=(i-e)/2,o=(i+e)/2,c=Math.min(t.upperAngleEnd-t.upperAngleStart,t.innerAngleEnd-t.innerAngleStart),a=Math.max(0,Math.min(n*r,c*e*.49));return{h:n,middle:o,length:a,angle:a/o}}generateDefaultPath(t){let{bigRadius:r,smallRadius:i,upperAngleStart:e,upperAngleEnd:n,innerAngleStart:o,innerAngleEnd:c}=t;return`M ${this.pt(r,e)}${this.arcTo(r,e,n)} L ${this.pt(i,c)}${this.arcTo(i,c,o)} Z`}generateRoundedPath(t){let{bigRadius:r,smallRadius:i,upperAngleStart:e,upperAngleEnd:n,innerAngleStart:o,innerAngleEnd:c}=t,{length:a}=this.ending(t,.5),l=(h,d)=>` A ${a},${a} 0 0 1 ${this.pt(h,d)}`,u=`M ${this.pt(r,e+a/r)}${this.arcTo(r,e+a/r,n-a/r)}`;return u+=`${l(r-a,n)} L ${this.pt(i+a,c)}${l(i,c-a/i)}`,u+=this.arcTo(i,c-a/i,o+a/i),u+=`${l(i+a,o)} L ${this.pt(r-a,e)}${l(r,e+a/r)} Z`,u}generateCirclePath(t,r){let{bigRadius:i,smallRadius:e,upperAngleStart:n,upperAngleEnd:o,innerAngleStart:c,innerAngleEnd:a}=t,l=r==="bullet"?0:1,u=`M ${this.pt(i,n)}${this.arcTo(i,n,o)} A 1,1 0 0 1 ${this.pt(e,a)}`;return u+=`${this.arcTo(e,a,c)} A 1,1 0 0 ${l} ${this.pt(i,n)} Z`,u}generateCircleBPath(t){let{bigRadius:r,smallRadius:i}=t,{h:e,angle:n}=this.ending(t,1),o=t.upperAngleStart+n,c=t.upperAngleEnd-n,a=`M ${this.pt(r,o)}${this.arcTo(r,o,c)} A ${e},${e} 0 0 1 ${this.pt(i,c)}`;return a+=`${this.arcTo(i,c,o)} A ${e},${e} 0 0 1 ${this.pt(r,o)} Z`,a}generateArrowPath(t){let{bigRadius:r,smallRadius:i}=t,{middle:e,angle:n}=this.ending(t,1.6),o=t.upperAngleStart,c=t.upperAngleEnd,a=`M ${this.pt(r,o)}${this.arcTo(r,o,c-n)}`;return a+=` L ${this.pt(e,c)} L ${this.pt(i,c-n)}`,a+=`${this.arcTo(i,c-n,o)} L ${this.pt(e,o+n)} Z`,a}generateSlashPath(t,r){let{bigRadius:i,smallRadius:e}=t,{angle:n}=this.ending(t,1),o=t.upperAngleStart,c=t.upperAngleEnd,[a,l,u,h]=r==="backslash"?[o,c-n,o+n,c]:[o+n,c,o,c-n];return`M ${this.pt(i,a)}${this.arcTo(i,a,l)} L ${this.pt(e,h)}${this.arcTo(e,h,u)} Z`}generateZigzagPath(t){let{bigRadius:r,smallRadius:i}=t,{middle:e,angle:n}=this.ending(t,1.6),o=t.upperAngleStart,c=t.upperAngleEnd,a=`M ${this.pt(r,o+n)}${this.arcTo(r,o+n,c)}`;return a+=` L ${this.pt(e,c-n)} L ${this.pt(i,c)}`,a+=`${this.arcTo(i,c,o+n)} L ${this.pt(e,o)} Z`,a}updateHitArea(t,r,i,e){let n=Math.max(0,Number(this.getAttribute("hit-width"))||0);if(this.fitCanvas(r,this.hasAttribute("interactive")?n:0),!this.hasAttribute("interactive")||!(e>i)||!(r.orbitRadius>0)){t.removeAttribute("d");return}let o=c=>(c-90)*Math.PI/180;t.setAttribute("d",this.linePath(r.realRadius,o(i),o(Math.min(e,i+360)))),t.style.strokeWidth=`${r.arcHeight+r.strokeWidth+2*n}px`}fitCanvas(t,r){let i=this.shadowRoot.querySelector("svg"),e=t.orbitRadius/50;if(!i||!(e>0))return;let n=(t.realRadius+t.arcHeightPercentage)*e+t.strokeWidth+r,o=Math.max(0,Math.ceil(n-t.orbitRadius)),c=o/e;i.setAttribute("viewBox",`${-c} ${-c} ${100+2*c} ${100+2*c}`),i.style.inset=`${-o}px`}};var T=class extends w{constructor(){super(),this.attachShadow({mode:"open"}),this.shadowRoot.innerHTML=`
<style>
:host {
--o-fill: var(--o-gray-light);
--o-stroke: var(--o-fill);
--o-stroke-width: 1;
--o-back-fill: transparent;
--o-back-stroke: none;
--o-back-stroke-width: 1;
}
svg {
position: absolute;
inset: 0;
width: auto;
height: auto;
overflow: visible;
pointer-events: none;
}
/* Display element by default: never steals clicks (see orbit-arc).
Interaction is opt-in via the "interactive" attribute. */
svg * {
pointer-events: none;
}
:host([interactive]) svg * {
pointer-events: visiblePainted;
}
/* The touch area covers the whole track, whatever its colors. */
.hit {
fill: none;
stroke: transparent;
}
:host([interactive]) .hit {
pointer-events: stroke;
}
:host([interactive]) {
cursor: pointer;
}
.progress-bar {
fill: var(--o-fill);
stroke: var(--o-stroke);
stroke-width: var(--o-stroke-width);
transition: fill 0.25s, stroke 0.25s;
stroke-linejoin: round;
}
.progress-bg {
fill: var(--o-back-fill);
stroke: var(--o-back-stroke);
stroke-width: var(--o-back-stroke-width);
}
/* variant="stroke": the thin, legible gauge.
The default band is a FILLED donut wedge, so everyone building a
thin gauge tripped on --o-fill/--o-back-fill. With this variant the
paths are open arcs and the data color lives where you expect it:
--o-stroke for the bar, --o-back-stroke for the track. */
/* The stroke variant draws a 2px bar over a gray 1px track unless you
set your own values on the element. */
:host([variant="stroke"]) {
--o-stroke-width: 2;
--o-back-stroke: var(--o-gray-light);
}
:host([variant="stroke"]) .progress-bar {
fill: none;
stroke: var(--o-stroke);
stroke-width: var(--o-stroke-width, 2);
stroke-linecap: round;
}
:host([variant="stroke"]) .progress-bg {
fill: none;
stroke: var(--o-back-stroke, var(--o-gray-light));
stroke-width: var(--o-back-stroke-width, 1);
stroke-linecap: round;
}
</style>
<svg viewBox="0 0 100 100">
<path class="hit" vector-effect="non-scaling-stroke"></path>
<path class="progress-bg" shape-rendering="geometricPrecision" vector-effect="non-scaling-stroke"></path>
<path class="progress-bar" shape-rendering="geometricPrecision" vector-effect="non-scaling-stroke"></path>
</svg>
`}update(){let t=this.getAttributes(),r=this.getAttribute("variant")==="stroke",i=r?this.calculateStrokeArc(t,!0):this.calculateArcParameters(t,!0),e=r?this.calculateStrokeArc(t,!1):this.calculateArcParameters(t,!1);this.shadowRoot.querySelector(".progress-bg").setAttribute("d",i),this.shadowRoot.querySelector(".progress-bar").setAttribute("d",e),this.updateHitArea(this.shadowRoot.querySelector(".hit"),t,0,t.range)}calculateStrokeArc(t,r){let{realRadius:i}=t,e=Math.max(0,Math.min(this.getProgressAngle(t,r),360));if(!(e>0)||!(t.orbitRadius>0))return"";let n=-Math.PI/2;return this.linePath(i,n,n+e*Math.PI/180)}getAttributes(){let t=super.getCommonAttributes(this),r=Math.max(0,Math.min(360,this.readAngle(t.style,"--o-range",360))),e=t.style.getPropertyValue("--o-progress").trim()?this.readNumber(t.style,"--o-progress",0):this.readValue(),n=this.readMax();return{...t,range:r,progress:e,maxValue:n}}getProgressAngle(t,r){let{range:i,progress:e,maxValue:n}=t;return r?i:super.getProgressAngle(i,e,n)}calculateArcParameters(t,r){let{shape:i,realRadius:e,arcHeightPercentage:n,orbitNumber:o,strokeWidth:c,arcHeight:a}=t,l=this.getProgressAngle(t,r);if(!(l>0)||!(t.orbitRadius>0))return"";let u=super.calculateCommonArcParameters(l,e,n,o,i,c,a);return super.generatePathData(i,u)}};var I=typeof document=="undefined"?null:document.createElement("template");I&&(I.innerHTML=`
<style>
:host {
--o-fill: var(--o-gray-light);
--o-stroke: var(--o-fill);
--o-stroke-width: 1;
--o-color: currentcolor;
}
svg {
position: absolute;
inset: 0;
width: auto;
height: auto;
overflow: visible;
pointer-events: none;
}
/* Arcs are display elements by default: they must NOT steal clicks from
satellites/controls nearby (a painted arc used to capture clicks even
at opacity 0, and pointer-events:none on the host could not pierce the
shadow). Interaction is opt-in via the "interactive" attribute. */
svg * {
pointer-events: none;
}
:host([interactive]) svg * {
pointer-events: visiblePainted;
}
/* Text lets the pointer through to the band under it: WebKit fires no
click on SVG text inside a shadow root. */
:host([interactive]) svg text,
:host([interactive]) svg textPath {
pointer-events: none;
}
/* The touch area catches the pointer even where the band is transparent. */
#orbitHit {
fill: none;
stroke: transparent;
}
:host([interactive]) #orbitHit {
pointer-events: stroke;
}
:host([interactive]) {
cursor: pointer;
}
#orbitShape {
fill: var(--o-fill);
stroke: var(--o-stroke);
stroke-width: var(--o-stroke-width);
transition: fill 0.25s, stroke 0.25s;
}
text {
fill: var(--o-color);
}
/* Guides for text: never painted and never under the pointer. */
#orbitPath, #measure {
fill: none;
stroke: none;
pointer-events: none;
}
</style>
<svg viewBox="0 0 100 100">
<path id="orbitHit" vector-effect="non-scaling-stroke"></path>
<path id="orbitShape" shape-rendering="geometricPrecision" vector-effect="non-scaling-stroke"></path>
<path id="orbitPath" shape-rendering="geometricPrecision" vector-effect="non-scaling-stroke"></path>
<text>
<textPath href="#orbitPath" alignment-baseline="middle"></textPath>
</text>
<text id="measure" visibility="hidden" aria-hidden="true"></text>
</svg>
`);var L=class extends w{constructor(){super(),this.attachShadow({mode:"open"}),this.shadowRoot.appendChild(I.content.cloneNode(!0))}update(){let t=this.getAttributes(),{fitRange:r,stacked:i}=t;if(i){let a=t.auto&&this.hasAttribute("text-anchor")&&{middle:-.5,end:-1}[t.textAnchor]||0;v(this,"--o-arc-start",`${t.stackOffset+a*t.arcAngle}deg`),v(this,"--o_stack",t.stackOffset+t.arcAngle)}else this.style.removeProperty("--o-arc-start"),this.style.removeProperty("--o_stack");let e=this.shadowRoot.querySelector("#orbitPath"),n=this.shadowRoot.querySelector("#orbitShape"),o=this.shadowRoot.querySelector("textPath");n.setAttribute("d",this.calculateArcParameters(t).dShape),e.setAttribute("d",this.calculateTextArcParameters(t).dPath),this.updateHitArea(this.shadowRoot.querySelector("#orbitHit"),t,0,t.arcAngle);let c=t.textAnchor;c==="start"?(o.setAttribute("startOffset","0%"),o.setAttribute("text-anchor","start")):c==="middle"?(o.setAttribute("startOffset","50%"),o.setAttribute("text-anchor","middle")):c==="end"&&(o.setAttribute("startOffset","100%"),o.setAttribute("text-anchor","end")),r?o.parentElement.setAttribute("textLength",e.getTotalLength()):o.parentElement.removeAttribute("textLength"),o.parentElement.style.fontSize=t.svgFontSize,o.textContent=this.textContent,t.auto||this.warnIfTextOverflows(e,o,r)}warnIfTextOverflows(t,r,i){let e=(this.textContent||"").trim();!e||i||!this.isConnected||(this._textFrame&&this.ownerDocument.defaultView.cancelAnimationFrame(this._textFrame),this._textFrame=this.ownerDocument.defaultView.requestAnimationFrame(()=>{if(this._textFrame=0,!!this.isConnected)try{let n=t.getTotalLength(),o=r.parentElement.getComputedTextLength();n>0&&o>n&&this._truncWarned!==e&&(this._truncWarned=e,console.warn(`[orbit] <o-arc> text "${e.length>34?e.slice(0,34)+"\u2026":e}" overflows its arc (${Math.round(o)} > ${Math.round(n)} units) and will clip. Shorten the text, widen --o-range, add range="auto" to fit the arc to the text, or fit-range to squeeze it.`))}catch(n){}}))}getAttributes(){let t=super.getCommonAttributes(this),{style:r}=t,i=Math.max(0,Math.min(360,this.readAngle(r,"--o-range",360))),e=this.hasAttribute("flip")||this.classList.contains("flip"),n=this.hasAttribute("fit-range")||this.classList.contains("fit-range"),o=t.orbitRadius*24/t.orbitNumber||100,c=this.getAttribute("text-anchor")||"middle",a=r.fontSize||"16px",l=Math.max(0,this.readNumber(r,"--o-gap",1)),u=`calc(${a} * (100 / (${o}) * (12 / var(--o-orbit-number)))`,h=this.getAttribute("range")==="auto",d=h||this.hasAttribute("value"),g;h?g=this.measureTextAngle(u,t.realRadius,l):this.hasAttribute("value")?g=super.getProgressAngle(i,this.readValue(),this.readMax()):g=Math.max(0,Math.min(360,this.readAngle(r,"--o-angle",0))),this._autoAngle=h?g:0;let m=0;if(d)for(let f=this.previousElementSibling;f;f=f.previousElementSibling){if(f.localName!=="o-arc")continue;let x=this.ownerDocument.defaultView.getComputedStyle(f);if(f.getAttribute("range")==="auto")m+=f._autoAngle||0;else if(f.hasAttribute("value")){let P=f.hasAttribute("max")?Number(f.getAttribute("max")):100,S=y(f,x.getPropertyValue("--o-range"),i,"angle");m+=super.getProgressAngle(S,Number(f.getAttribute("value")),P)}else m+=y(f,x.getPropertyValue("--o-angle"),0,"angle")}return{...t,gap:l,arcAngle:g,stackOffset:m,flip:e,fitRange:n,length:o,fontSize:a,svgFontSize:u,textAnchor:c,auto:h,stacked:d}}measureTextAngle(t,r,i){let e=(this.textContent||"").trim();if(!e||!(r>0))return 0;let n=this.shadowRoot.querySelector("#measure");n.style.fontSize=t,n.textContent=e;let o=0;try{o=n.getComputedTextLength()+parseFloat(this.ownerDocument.defaultView.getComputedStyle(n).fontSize)}catch(c){}return o>0?Math.min(360,o/r*180/Math.PI+i):0}calculateArcParameters(t){let{arcAngle:r,realRadius:i,arcHeightPercentage:e,orbitNumber:n,shape:o,strokeWidth:c,arcHeight:a,gap:l}=t;if(!(r>0)||!(t.orbitRadius>0))return{dShape:""};let u=super.calculateCommonArcParameters(r,i,e,n,o,c,a,l);return{dShape:super.generatePathData(o,u)}}calculateTextArcParameters(t){let{arcAngle:r,realRadius:i,gap:e,flip:n}=t;if(!(r>0))return{dPath:""};let o=Math.min(e*.5,r*.49),c=(o-90)*Math.PI/180,a=(r-o-90)*Math.PI/180;return{dPath:n?this.linePath(i,a,c):this.linePath(i,c,a)}}resolveAngle(t){return y(this,t,0,"angle")}calcularExpresionCSS(t){return this.resolveAngle(t)}};var N=new WeakMap,ut=/^[+-]?(?:\d+\.?\d*|\.\d+)px$/,K={refresh:D,ready:G,resize(s){var o,c;let t=typeof s=="string"?(o=globalThis.document)==null?void 0:o.querySelector(s):s;if(!(t!=null&&t.ownerDocument))return console.error("Orbit.resize: element not found:",s),()=>{};(c=N.get(t))==null||c();let r=t.ownerDocument.defaultView,i=a=>{if(!(a>0))return;let l=0;for(let u of t.querySelectorAll(".gravity-spot")){if(!ut.test(r.getComputedStyle(u).getPropertyValue("--o-force").trim()))continue;l++;let h=String(a/500);u.style.getPropertyValue("--o-force-ratio")!==h&&u.style.setProperty("--o-force-ratio",h)}l||p(t,"resize","Orbit.resize() has nothing to do here: every .bigbang already scales with its container. It only scales systems that set a fixed px --o-force."),D(t)},e=new r.ResizeObserver(a=>{for(let l of a)i(l.contentRect.width)});e.observe(t),i(t.clientWidth||t.getBoundingClientRect().width);let n=()=>{e.disconnect(),N.get(t)===n&&N.delete(t)};return N.set(t,n),n}};function ht(){typeof customElements=="undefined"||typeof document=="undefined"||(customElements.get("o-progress")||customElements.define("o-progress",T),customElements.get("o-arc")||customElements.define("o-arc",L),E(document),window.Orbit=K)}ht();})();