@zumer/orbit 2.0.1 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/orbit.min.js CHANGED
@@ -1,10 +1,10 @@
1
1
  /*
2
2
  * orbit
3
- * v.2.0.1
3
+ * v.2.1.0
4
4
  * Author Juan Martin Muda - Zumerlab
5
5
  * License MIT
6
6
  */
7
- (()=>{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=`
7
+ (()=>{var w=Symbol.for("zumer.orbit.layout.state.v1"),q=Symbol.for("zumer.orbit.layout.registry.v1"),j=Symbol.for("zumer.orbit.layout.probe.v1"),F="o-arc, o-progress",U={subtree:!0,childList:!0,characterData:!0,attributes:!0,attributeOldValue:!0};function M(i){var t;for(let r of i.classList||[])if(/^orbit-\d+$/.test(r))return Number(r.slice(6));return(t=i.classList)!=null&&t.contains("orbit")?null:void 0}var Z=Symbol.for("zumer.orbit.warned.v1");function p(i,t,r){let s=i[Z]||(i[Z]=new Set);s.has(t)||(s.add(t),console.warn(`[orbit] ${r}`))}function G(i,t){var r,s;for(let e=i;e;e=e.parentElement||((r=e.getRootNode)==null?void 0:r.call(e).host))if((s=e.matches)!=null&&s.call(e,t))return e;return null}var Q=".satellite, .vector, .side, o-arc, o-progress";function P(i){let t=[...i.classList].slice(0,3).map(r=>"."+r).join("");return`<${i.localName}${t?" "+t:""}>`}function tt(i){let t=i.parentElement,r=G(t.parentElement,".bigbang, .satellite");r?r.getClientRects().length&&(!r.clientWidth||!r.clientHeight)&&p(r,"empty",`${P(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 s=i.querySelector(":scope > o-arc, :scope > o-progress");if(s){let e=i.ownerDocument.defaultView.getComputedStyle(i),n=e.getPropertyValue("--o-ellipse-x").trim(),o=e.getPropertyValue("--o-ellipse-y").trim();(n&&Number(n)!==1||o&&Number(o)!==1)&&p(i,"ellipse-visual",`${P(s)} is on ${P(i)}, 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(G(i,".dev-orbit")){for(let e of i.children)if(M(e)!==void 0)p(e,"nested-ring",`${P(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",`${P(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",`${P(n)} sits directly in a .satellite. Put content in a .capsule so it stays upright and centered.`)}}function v(i,t,r){let s=String(r);i.style.getPropertyValue(t)!==s&&i.style.setProperty(t,s)}function y(i,t,r=0,s="number"){let e=String(t||"").trim();if(!e)return r;if(s==="number"&&/^[+-]?(?:\d+\.?\d*|\.\d+)$/.test(e))return Number(e);let n=e.match(/^([+-]?(?:\d+\.?\d*|\.\d+))(deg|rad|grad|turn)?$/);if(s==="angle"&&n)return Number(n[1])*({deg:1,rad:180/Math.PI,grad:.9,turn:360}[n[2]]||1);let o=i.ownerDocument;if(!(o!=null&&o.documentElement))return r;let l=o[j];l||(l=o.createElement("span"),l.setAttribute("data-orbit-measure",""),l.setAttribute("aria-hidden","true"),l.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(l),Object.defineProperty(o,j,{value:l,configurable:!0}));let a=s==="angle"?"rotate":"scale";if(l.style.removeProperty(a),l.style.setProperty(a,e,"important"),!l.style.getPropertyValue(a))return r;let c=o.defaultView.getComputedStyle(l).getPropertyValue(a),u=parseFloat(c);return Number.isFinite(u)?u:r}function et(i){if(i.localName==="o-arc")return i.hasAttribute("start")?null:"arc";for(let t of["satellite","vector","side"])if(i.classList.contains(t))return t;return null}function rt(i){let t={arc:0,satellite:0,vector:0,side:0};for(let n of i.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),s=t.satellite||t.vector,e=t.side?String(t.side):s?`max(1, ${r} - var(--o-fit-range, 0))`:String(r);v(i,"--o-layout-angle",`calc(var(--o-range, 360deg) / ${e})`)}function K(i){return(i==null?void 0:i.nodeType)===9||(i==null?void 0:i.nodeType)===11&&!!i.host}function E(i){var r;if(K(i))return i;let t=(r=i==null?void 0:i.getRootNode)==null?void 0:r.call(i);return K(t)?t:null}function D(i,t){var r,s;for(let e=t;e;e=(r=e.getRootNode)==null?void 0:r.call(e).host)if(i===e||(s=i.contains)!=null&&s.call(i,e))return!0;return!1}function it(i){return i[q]||Object.defineProperty(i,q,{value:{states:new Set},configurable:!0}),i[q]}function I(i){i.frame<0?i.view.clearTimeout(-i.frame):i.frame&&i.view.cancelAnimationFrame(i.frame),i.frame=0}function X(i){for(let t of i.waiters.splice(0))t()}function W(i){if(!i.disposed){i.disposed=!0,I(i),X(i),i.observer.disconnect(),i.resize.disconnect();for(let t of i.listeners)t();i.rings.clear(),i.visuals.clear(),i.dirty.clear(),i.registry.states.delete(i),i.scope[w]===i&&delete i.scope[w]}}function H(i){for(let t of i.states)t.scope.host&&!t.scope.host.isConnected&&W(t)}function R(i,t=i.scope){for(let r of i.registry.states)r!==i&&r.scope.host&&D(t,r.scope.host)&&(r.all=!0,r.queue())}function st(i){return i.nodeType!==1||i.hasAttribute("data-orbit-measure")?!1:M(i)!==void 0||i.matches(".gravity-spot, o-arc, o-progress")?!0:!!i.querySelector(".gravity-spot, .orbit, [data-orbit-ring], o-arc, o-progress")}function nt(i){return i.nodeType===1&&(i.matches('style, link[rel~="stylesheet"]')||!!i.querySelector('style, link[rel~="stylesheet"]'))}function ot(i,t){if(i.type==="childList")return[...i.addedNodes,...i.removedNodes].some(st);if(i.attributeName!=="class")return!1;let r=i.target;return t.rings.has(r)||r.classList.contains("gravity-spot")||M(r)!==void 0||(i.oldValue||"").split(/\s+/).some(s=>s==="gravity-spot"||s==="orbit"||/^orbit-\d+$/.test(s))}function at(i){let t=i.nodeType===9?i:i.ownerDocument,r=t.defaultView,s=it(t),e={scope:i,doc:t,view:r,registry:s,rings:new Set,visuals:new Set,dirty:new Set,scan:!0,all:!0,frame:0,disposed:!1,listeners:[],waiters:[]},n=(a,c,u,h)=>{a==null||a.addEventListener(c,u,h),e.listeners.push(()=>a==null?void 0:a.removeEventListener(c,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=()=>ct(e),e.invalidate=(a=i,c=!0)=>{var u,h;if(c&&(a===i||a===t.documentElement||a===t.head))e.all=!0;else{for(let d of e.rings)(d===a||d.contains(a)||c&&((u=a.contains)!=null&&u.call(a,d)))&&e.dirty.add(d);for(let d of e.visuals)(d===a||d.contains(a)||c&&((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 c,u;if(a.some(h=>h.type==="childList")&&H(s),!e.disposed)for(let h of a){let d=h.target.nodeType===3?h.target.parentElement:h.target;if(!d||(c=d.hasAttribute)!=null&&c.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,R(e)):h.type==="attributes"&&R(e,d),e.invalidate(d,h.type==="attributes"||g)}}),e.observer.observe(i,U),e.resize=new r.ResizeObserver(a=>{for(let c of a)e.dirty.add(c.target);o()});let l=()=>{e.all=!0,R(e),o()};n(t,"visibilitychange",()=>{t.visibilityState==="hidden"&&e.frame>0&&(I(e),o())}),i===t&&(n(r,"resize",l),n(t.fonts,"loadingdone",l)),n(i,"load",a=>{a.target.localName==="link"&&l()},!0);for(let a of["pointerover","pointerout","focusin","focusout"])n(i,a,c=>{e.invalidate(c.target),R(e,c.target)},!0);return Object.defineProperty(i,w,{value:e,configurable:!0}),s.states.add(e),o(),e}function N(i){let t=i.nodeType===9?i:i.ownerDocument;if(!(t!=null&&t.defaultView)||!t.documentElement||i.host&&!i.host.isConnected)return null;if(i[w]&&i[w].doc!==t&&W(i[w]),i.host){let r=E(i.host);r&&N(r)}return i[w]||at(i)}function lt(i){let t=new Set,r=new Map;for(let e of i.scope.querySelectorAll(".gravity-spot > *")){let n=M(e);if(n===void 0)continue;let o=r.get(e.parentElement)||0;e.classList.contains("orbit")&&r.set(e.parentElement,++o);let l=n===null?o:n;e.setAttribute("data-orbit-ring",""),v(e,"--o-layout-number",l===0?1e-5:l),t.add(e),i.dirty.add(e),i.rings.has(e)||i.resize.observe(e)}for(let e of i.rings)if(!t.has(e)){i.resize.unobserve(e),e.removeAttribute("data-orbit-ring");for(let n of["--o-layout-number","--o-layout-angle"])e.style.removeProperty(n)}i.rings=t;let s=new Set(i.scope.querySelectorAll(F));for(let e of i.visuals)s.has(e)||i.resize.unobserve(e);for(let e of s)i.visuals.has(e)||(i.resize.observe(e),i.dirty.add(e));i.visuals=s,i.scan=!1}function ct(i){if(i.disposed)return;if(i.scope.host&&!i.scope.host.isConnected){W(i);return}i.observer.disconnect();let t=[];try{i.scan&&lt(i);let r=i.all?new Set([...i.rings,...i.visuals]):i.dirty,s=new Set;for(let e of r)if(e.isConnected)if(i.rings.has(e)){rt(e),tt(e);for(let n of e.querySelectorAll(F))s.add(n)}else i.visuals.has(e)&&s.add(e);for(let e of i.visuals)s.has(e)&&e.update&&(e.update(),t.push(e));i.dirty=new Set,i.all=!1}finally{i.disposed||i.observer.observe(i.scope,U)}for(let r of t)r.dispatchEvent(new i.view.Event("o-rendered",{bubbles:!0,composed:!0}));i.frame||X(i)}function T(i=globalThis.document){var s;let t=E(i);if(!t)return;let r=N(t);r&&((s=i==null?void 0:i.matches)!=null&&s.call(i,F)&&!r.visuals.has(i)&&(r.scan=!0),r.invalidate(i||t))}function _(i=globalThis.document){let t=E(i);if(!t)return;let r=N(t);if(r){H(r.registry);for(let s of r.registry.states)s!==r&&(!s.scope.host||!D(i,s.scope.host))||(s.scan=!0,s.all=!0,I(s),s.flush())}}function Y(i=globalThis.document){let t=E(i),r=t&&N(t);if(!r)return Promise.resolve();H(r.registry);let s=[...r.registry.states].filter(e=>e===r||e.scope.host&&D(i,e.scope.host));return Promise.all(s.map(e=>new Promise(n=>{e.waiters.push(n),e.queue()}))).then(()=>{})}var S=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}T(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,s=0){return y(this,t.getPropertyValue(r),s)}readAngle(t,r,s=0){return y(this,t.getPropertyValue(r),s,"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(t){let r=this.getAttribute("max");if(r===null){let e=t==null?void 0:t.getPropertyValue("--o-max").trim();if(!e)return 100;let n=y(this,e,NaN);return n>0?n:(p(this,"o-max:"+e,`--o-max: ${e} on <${this.localName}> must be a positive number, so nothing is drawn.`),0)}let s=Number(r);return s>0?s:(p(this,"max:"+r,`<${this.localName} max="${r}"> must be a positive number, so nothing is drawn.`),0)}getCommonAttributes(t){var g;let r=t.ownerDocument.defaultView.getComputedStyle(t),s=parseFloat(r.getPropertyValue("r")),e=Math.max(0,Number.isFinite(s)?s:(((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)),l=Math.max(0,this.readNumber(r,"--o-stroke-width",1)),a=t.getAttribute("shape")||"none",c=Math.max(0,e/n*o-l+.3),u=e>0?Math.min(49.999,c*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:c,realRadius:d,arcAngle:0,shape:a,arcHeightPercentage:u,orbitNumber:n,size:o,strokeWidth:l,style:r}}getProgressAngle(t,r,s=100){return!Number.isFinite(r)||!Number.isFinite(s)||s<=0?0:Math.min(1,Math.max(0,r/s))*Math.max(0,Math.min(360,t))}arcPoint(t,r,s=0,e=0){let n=t+s,o=r+e*Math.PI/180;return{x:50+n*Math.cos(o),y:50+n*Math.sin(o)}}calculateCommonArcParameters(t,r,s,e,n,o,l,a=0){let c=Math.PI/2,u=Math.max(0,Math.min(360,t))*Math.PI/180,h=r+s,d=Math.max(.001,r-s),g=Math.min(u*.49,(a+o*1.25)/e/h),x=Math.min(u*.49,(a+o*1.25)/e/d),A=g-c,b=u-g-c,m=x-c,$=u-x-c,f=this.arcPoint(h,A),k=this.arcPoint(h,b),z=this.arcPoint(d,m),O=this.arcPoint(d,$);return{upperArcStart:f,upperArcEnd:k,innerArcStart:z,innerArcEnd:O,bigRadius:h,smallRadius:d,radius:r,upperAngleStart:A,upperAngleEnd:b,innerAngleStart:m,innerAngleEnd:$}}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 s=this.arcPoint(t,r);return`${s.x},${s.y}`}arcTo(t,r,s){let e=Math.max(1,Math.ceil(Math.abs(s-r)/(Math.PI/2)-1e-9)),n=s>=r?1:0,o="";for(let l=1;l<=e;l++)o+=` A ${t},${t} 0 0 ${n} ${this.pt(t,r+(s-r)*l/e)}`;return o}linePath(t,r,s){return`M ${this.pt(t,r)}${this.arcTo(t,r,s)}`}ending(t,r){let{bigRadius:s,smallRadius:e}=t,n=(s-e)/2,o=(s+e)/2,l=Math.min(t.upperAngleEnd-t.upperAngleStart,t.innerAngleEnd-t.innerAngleStart),a=Math.max(0,Math.min(n*r,l*e*.49));return{h:n,middle:o,length:a,angle:a/o}}generateDefaultPath(t){let{bigRadius:r,smallRadius:s,upperAngleStart:e,upperAngleEnd:n,innerAngleStart:o,innerAngleEnd:l}=t;return`M ${this.pt(r,e)}${this.arcTo(r,e,n)} L ${this.pt(s,l)}${this.arcTo(s,l,o)} Z`}generateRoundedPath(t){let{bigRadius:r,smallRadius:s,upperAngleStart:e,upperAngleEnd:n,innerAngleStart:o,innerAngleEnd:l}=t,{length:a}=this.ending(t,.5),c=(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+=`${c(r-a,n)} L ${this.pt(s+a,l)}${c(s,l-a/s)}`,u+=this.arcTo(s,l-a/s,o+a/s),u+=`${c(s+a,o)} L ${this.pt(r-a,e)}${c(r,e+a/r)} Z`,u}generateCirclePath(t,r){let{bigRadius:s,smallRadius:e,upperAngleStart:n,upperAngleEnd:o,innerAngleStart:l,innerAngleEnd:a}=t,c=r==="bullet"?0:1,u=`M ${this.pt(s,n)}${this.arcTo(s,n,o)} A 1,1 0 0 1 ${this.pt(e,a)}`;return u+=`${this.arcTo(e,a,l)} A 1,1 0 0 ${c} ${this.pt(s,n)} Z`,u}generateCircleBPath(t){let{bigRadius:r,smallRadius:s}=t,{h:e,angle:n}=this.ending(t,1),o=t.upperAngleStart+n,l=t.upperAngleEnd-n,a=`M ${this.pt(r,o)}${this.arcTo(r,o,l)} A ${e},${e} 0 0 1 ${this.pt(s,l)}`;return a+=`${this.arcTo(s,l,o)} A ${e},${e} 0 0 1 ${this.pt(r,o)} Z`,a}generateArrowPath(t){let{bigRadius:r,smallRadius:s}=t,{middle:e,angle:n}=this.ending(t,1.6),o=t.upperAngleStart,l=t.upperAngleEnd,a=`M ${this.pt(r,o)}${this.arcTo(r,o,l-n)}`;return a+=` L ${this.pt(e,l)} L ${this.pt(s,l-n)}`,a+=`${this.arcTo(s,l-n,o)} L ${this.pt(e,o+n)} Z`,a}generateSlashPath(t,r){let{bigRadius:s,smallRadius:e}=t,{angle:n}=this.ending(t,1),o=t.upperAngleStart,l=t.upperAngleEnd,[a,c,u,h]=r==="backslash"?[o,l-n,o+n,l]:[o+n,l,o,l-n];return`M ${this.pt(s,a)}${this.arcTo(s,a,c)} L ${this.pt(e,h)}${this.arcTo(e,h,u)} Z`}generateZigzagPath(t){let{bigRadius:r,smallRadius:s}=t,{middle:e,angle:n}=this.ending(t,1.6),o=t.upperAngleStart,l=t.upperAngleEnd,a=`M ${this.pt(r,o+n)}${this.arcTo(r,o+n,l)}`;return a+=` L ${this.pt(e,l-n)} L ${this.pt(s,l)}`,a+=`${this.arcTo(s,l,o+n)} L ${this.pt(e,o)} Z`,a}updateHitArea(t,r,s,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>s)||!(r.orbitRadius>0)){t.removeAttribute("d");return}let o=l=>(l-90)*Math.PI/180;t.setAttribute("d",this.linePath(r.realRadius,o(s),o(Math.min(e,s+360)))),t.style.strokeWidth=`${r.arcHeight+r.strokeWidth+2*n}px`}fitCanvas(t,r){let s=this.shadowRoot.querySelector("svg"),e=t.orbitRadius/50;if(!s||!(e>0))return;let n=((t.realRadius+t.arcHeightPercentage)*e+t.strokeWidth)*(t.reach||1)+r,o=Math.max(0,Math.ceil(n-t.orbitRadius)),l=o/e;s.setAttribute("viewBox",`${-l} ${-l} ${100+2*l} ${100+2*l}`),s.style.inset=`${-o}px`}};var L=class extends S{constructor(){super(),this.attachShadow({mode:"open"}),this.shadowRoot.innerHTML=`
8
8
  <style>
9
9
  :host {
10
10
  --o-fill: var(--o-gray-light);
@@ -82,7 +82,7 @@
82
82
  <path class="progress-bg" shape-rendering="geometricPrecision" vector-effect="non-scaling-stroke"></path>
83
83
  <path class="progress-bar" shape-rendering="geometricPrecision" vector-effect="non-scaling-stroke"></path>
84
84
  </svg>
85
- `}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=`
85
+ `}update(){let t=this.getAttributes(),r=this.getAttribute("variant")==="stroke",s=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",s),this.shadowRoot.querySelector(".progress-bar").setAttribute("d",e),this.updateHitArea(this.shadowRoot.querySelector(".hit"),t,0,t.range);let n=this.parentElement;this._valueRing&&this._valueRing!==n&&this._valueRing.style.removeProperty("--o-value-angle"),this._valueRing=n,n&&v(n,"--o-value-angle",`${this.getProgressAngle(t,!1)}deg`)}disconnectedCallback(){var t;super.disconnectedCallback(),(t=this._valueRing)==null||t.style.removeProperty("--o-value-angle"),this._valueRing=null}calculateStrokeArc(t,r){let{realRadius:s}=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(s,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(t.style);return{...t,range:r,progress:e,maxValue:n}}getProgressAngle(t,r){let{range:s,progress:e,maxValue:n}=t;return r?s:super.getProgressAngle(s,e,n)}calculateArcParameters(t,r){let{shape:s,realRadius:e,arcHeightPercentage:n,orbitNumber:o,strokeWidth:l,arcHeight:a}=t,c=this.getProgressAngle(t,r);if(!(c>0)||!(t.orbitRadius>0))return"";let u=super.calculateCommonArcParameters(c,e,n,o,s,l,a);return super.generatePathData(s,u)}};var B=typeof document=="undefined"?null:document.createElement("template");B&&(B.innerHTML=`
86
86
  <style>
87
87
  :host {
88
88
  --o-fill: var(--o-gray-light);
@@ -140,9 +140,32 @@
140
140
  stroke: none;
141
141
  pointer-events: none;
142
142
  }
143
+ /* .ripple: a copy of the band grows out from the center of the ring and
144
+ fades, over and over. The band itself stays. */
145
+ #orbitWave {
146
+ display: none;
147
+ fill: var(--o-ripple-color, var(--o-fill));
148
+ stroke: none;
149
+ pointer-events: none;
150
+ transform-origin: 50px 50px;
151
+ }
152
+ :host(.ripple) #orbitWave {
153
+ display: inline;
154
+ animation: orbit-ripple var(--o-ripple-duration, 1.6s) ease-out infinite;
155
+ }
156
+ @keyframes orbit-ripple {
157
+ from { transform: scale(1); opacity: .9; }
158
+ to { transform: scale(var(--o-ripple-scale, 1.14)); opacity: 0; }
159
+ }
160
+ @media (prefers-reduced-motion: reduce) {
161
+ :host(.ripple) #orbitWave {
162
+ display: none;
163
+ }
164
+ }
143
165
  </style>
144
166
  <svg viewBox="0 0 100 100">
145
167
  <path id="orbitHit" vector-effect="non-scaling-stroke"></path>
168
+ <path id="orbitWave" shape-rendering="geometricPrecision"></path>
146
169
  <path id="orbitShape" shape-rendering="geometricPrecision" vector-effect="non-scaling-stroke"></path>
147
170
  <path id="orbitPath" shape-rendering="geometricPrecision" vector-effect="non-scaling-stroke"></path>
148
171
  <text>
@@ -150,4 +173,4 @@
150
173
  </text>
151
174
  <text id="measure" visibility="hidden" aria-hidden="true"></text>
152
175
  </svg>
153
- `);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();})();
176
+ `);var C=class extends S{constructor(){super(),this.attachShadow({mode:"open"}),this.shadowRoot.appendChild(B.content.cloneNode(!0))}update(){let t=this.getAttributes(),{fitRange:r,stacked:s}=t;if(s){let c=t.auto&&this.hasAttribute("text-anchor")&&{middle:-.5,end:-1}[t.textAnchor]||0;v(this,"--o-arc-start",`${t.stackOffset+c*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"),{dShape:l}=this.calculateArcParameters(t);n.setAttribute("d",l),this.shadowRoot.querySelector("#orbitWave").setAttribute("d",l),e.setAttribute("d",this.calculateTextArcParameters(t).dPath),this.updateHitArea(this.shadowRoot.querySelector("#orbitHit"),t,0,t.arcAngle);let a=t.textAnchor;a==="start"?(o.setAttribute("startOffset","0%"),o.setAttribute("text-anchor","start")):a==="middle"?(o.setAttribute("startOffset","50%"),o.setAttribute("text-anchor","middle")):a==="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,s){let e=(this.textContent||"").trim();!e||s||!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,s=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,l=this.getAttribute("text-anchor")||"middle",a=r.fontSize||"16px",c=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=this.hasAttribute("value"),g=this.hasAttribute("start"),x=h||d||g,A=this.readMax(r),b;h?b=this.measureTextAngle(u,t.realRadius,c):d?b=super.getProgressAngle(s,this.readValue(),A):b=Math.max(0,Math.min(360,this.readAngle(r,"--o-angle",0))),this._autoAngle=h?b:0;let m=0;if(g){if(m=A>0?this.readStart()/A*s:0,!h&&s<360){let f=Math.min(s,m+b);m=Math.max(0,m),b=Math.max(0,f-m)}}else if(x)for(let f=this.previousElementSibling;f;f=f.previousElementSibling){if(f.localName!=="o-arc"||f.hasAttribute("start"))continue;let k=this.ownerDocument.defaultView.getComputedStyle(f);if(f.getAttribute("range")==="auto")m+=f._autoAngle||0;else if(f.hasAttribute("value")){let z=this.readMax.call(f,k),O=y(f,k.getPropertyValue("--o-range"),s,"angle");m+=super.getProgressAngle(O,Number(f.getAttribute("value")),z)}else m+=y(f,k.getPropertyValue("--o-angle"),0,"angle")}let $=this.classList.contains("ripple")?Math.max(1,this.readNumber(r,"--o-ripple-scale",1.14)):1;return{...t,gap:c,max:A,arcAngle:b,stackOffset:m,flip:e,fitRange:n,length:o,fontSize:a,svgFontSize:u,textAnchor:l,auto:h,placed:g,stacked:x,reach:$}}readStart(){let t=this.getAttribute("start"),r=Number(t);return Number.isFinite(r)?r:(p(this,"start:"+t,`<o-arc start="${t}"> is not a number, so the arc starts at 0.`),0)}measureTextAngle(t,r,s){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(l){}return o>0?Math.min(360,o/r*180/Math.PI+s):0}calculateArcParameters(t){let{arcAngle:r,realRadius:s,arcHeightPercentage:e,orbitNumber:n,shape:o,strokeWidth:l,arcHeight:a,gap:c}=t;if(!(r>0)||!(t.orbitRadius>0))return{dShape:""};let u=super.calculateCommonArcParameters(r,s,e,n,o,l,a,c);return{dShape:super.generatePathData(o,u)}}calculateTextArcParameters(t){let{arcAngle:r,realRadius:s,gap:e,flip:n}=t;if(!(r>0))return{dPath:""};let o=Math.min(e*.5,r*.49),l=(o-90)*Math.PI/180,a=(r-o-90)*Math.PI/180;return{dPath:n?this.linePath(s,a,l):this.linePath(s,l,a)}}resolveAngle(t){return y(this,t,0,"angle")}calcularExpresionCSS(t){return this.resolveAngle(t)}};var V=new WeakMap,ut=/^[+-]?(?:\d+\.?\d*|\.\d+)px$/,J={refresh:_,ready:Y,resize(i){var o,l;let t=typeof i=="string"?(o=globalThis.document)==null?void 0:o.querySelector(i):i;if(!(t!=null&&t.ownerDocument))return console.error("Orbit.resize: element not found:",i),()=>{};(l=V.get(t))==null||l();let r=t.ownerDocument.defaultView,s=a=>{if(!(a>0))return;let c=0;for(let u of t.querySelectorAll(".gravity-spot")){if(!ut.test(r.getComputedStyle(u).getPropertyValue("--o-force").trim()))continue;c++;let h=String(a/500);u.style.getPropertyValue("--o-force-ratio")!==h&&u.style.setProperty("--o-force-ratio",h)}c||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."),_(t)},e=new r.ResizeObserver(a=>{for(let c of a)s(c.contentRect.width)});e.observe(t),s(t.clientWidth||t.getBoundingClientRect().width);let n=()=>{e.disconnect(),V.get(t)===n&&V.delete(t)};return V.set(t,n),n}};function ht(){typeof customElements=="undefined"||typeof document=="undefined"||(customElements.get("o-progress")||customElements.define("o-progress",L),customElements.get("o-arc")||customElements.define("o-arc",C),T(document),window.Orbit=J)}ht();})();
package/dist/orbit.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * orbit
3
- * v.2.0.1
3
+ * v.2.1.0
4
4
  * Author Juan Martin Muda - Zumerlab
5
5
  * License MIT
6
6
  */
@@ -100,7 +100,7 @@ function cssNumber(element, value, fallback = 0, type = "number") {
100
100
  return Number.isFinite(resolved) ? resolved : fallback;
101
101
  }
102
102
  function group(element) {
103
- if (element.localName === "o-arc") return "arc";
103
+ if (element.localName === "o-arc") return element.hasAttribute("start") ? null : "arc";
104
104
  for (const name of ["satellite", "vector", "side"]) if (element.classList.contains(name)) return name;
105
105
  return null;
106
106
  }
@@ -445,10 +445,22 @@ var OrbitBase = class extends (globalThis.HTMLElement || class {
445
445
  }
446
446
  return value;
447
447
  }
448
- /** The max attribute (default 100). It must be a positive number. */
449
- readMax() {
448
+ /**
449
+ * The max attribute, else --o-max from the ring or system (default 100).
450
+ * It must be a positive number.
451
+ */
452
+ readMax(style) {
450
453
  const raw = this.getAttribute("max");
451
- if (raw === null) return 100;
454
+ if (raw === null) {
455
+ const css = style == null ? void 0 : style.getPropertyValue("--o-max").trim();
456
+ if (!css) return 100;
457
+ const max2 = cssNumber(this, css, NaN);
458
+ if (!(max2 > 0)) {
459
+ warnOnce(this, "o-max:" + css, `--o-max: ${css} on <${this.localName}> must be a positive number, so nothing is drawn.`);
460
+ return 0;
461
+ }
462
+ return max2;
463
+ }
452
464
  const max = Number(raw);
453
465
  if (!(max > 0)) {
454
466
  warnOnce(this, "max:" + raw, `<${this.localName} max="${raw}"> must be a positive number, so nothing is drawn.`);
@@ -668,14 +680,15 @@ var OrbitBase = class extends (globalThis.HTMLElement || class {
668
680
  }
669
681
  /**
670
682
  * Grow the SVG canvas past the ring's box so it covers the whole band, its
671
- * stroke and touch area. Some engines (WebKit) neither paint reliably nor
672
- * hit-test SVG content that overflows its box.
683
+ * stroke and touch area, and as far as a ripple reaches (attrs.reach).
684
+ * Some engines (WebKit) neither paint reliably nor hit-test SVG content that
685
+ * overflows its box.
673
686
  */
674
687
  fitCanvas(attrs, extra) {
675
688
  const svg = this.shadowRoot.querySelector("svg");
676
689
  const scale = attrs.orbitRadius / 50;
677
690
  if (!svg || !(scale > 0)) return;
678
- const outer = (attrs.realRadius + attrs.arcHeightPercentage) * scale + attrs.strokeWidth + extra;
691
+ const outer = ((attrs.realRadius + attrs.arcHeightPercentage) * scale + attrs.strokeWidth) * (attrs.reach || 1) + extra;
679
692
  const pad = Math.max(0, Math.ceil(outer - attrs.orbitRadius));
680
693
  const units = pad / scale;
681
694
  svg.setAttribute("viewBox", `${-units} ${-units} ${100 + 2 * units} ${100 + 2 * units}`);
@@ -776,6 +789,16 @@ var OrbitProgress = class extends OrbitBase {
776
789
  this.shadowRoot.querySelector(".progress-bg").setAttribute("d", dBg);
777
790
  this.shadowRoot.querySelector(".progress-bar").setAttribute("d", dBar);
778
791
  this.updateHitArea(this.shadowRoot.querySelector(".hit"), attrs, 0, attrs.range);
792
+ const ring = this.parentElement;
793
+ if (this._valueRing && this._valueRing !== ring) this._valueRing.style.removeProperty("--o-value-angle");
794
+ this._valueRing = ring;
795
+ if (ring) setLayoutProperty(ring, "--o-value-angle", `${this.getProgressAngle(attrs, false)}deg`);
796
+ }
797
+ disconnectedCallback() {
798
+ var _a;
799
+ super.disconnectedCallback();
800
+ (_a = this._valueRing) == null ? void 0 : _a.style.removeProperty("--o-value-angle");
801
+ this._valueRing = null;
779
802
  }
780
803
  /**
781
804
  * variant="stroke": open arc along the orbit radius (no closed band),
@@ -793,7 +816,7 @@ var OrbitProgress = class extends OrbitBase {
793
816
  const range = Math.max(0, Math.min(360, this.readAngle(common.style, "--o-range", 360)));
794
817
  const rawValue = common.style.getPropertyValue("--o-progress").trim();
795
818
  const progress = rawValue ? this.readNumber(common.style, "--o-progress", 0) : this.readValue();
796
- const maxValue = this.readMax();
819
+ const maxValue = this.readMax(common.style);
797
820
  return {
798
821
  ...common,
799
822
  range,
@@ -882,9 +905,32 @@ if (template) template.innerHTML = `
882
905
  stroke: none;
883
906
  pointer-events: none;
884
907
  }
908
+ /* .ripple: a copy of the band grows out from the center of the ring and
909
+ fades, over and over. The band itself stays. */
910
+ #orbitWave {
911
+ display: none;
912
+ fill: var(--o-ripple-color, var(--o-fill));
913
+ stroke: none;
914
+ pointer-events: none;
915
+ transform-origin: 50px 50px;
916
+ }
917
+ :host(.ripple) #orbitWave {
918
+ display: inline;
919
+ animation: orbit-ripple var(--o-ripple-duration, 1.6s) ease-out infinite;
920
+ }
921
+ @keyframes orbit-ripple {
922
+ from { transform: scale(1); opacity: .9; }
923
+ to { transform: scale(var(--o-ripple-scale, 1.14)); opacity: 0; }
924
+ }
925
+ @media (prefers-reduced-motion: reduce) {
926
+ :host(.ripple) #orbitWave {
927
+ display: none;
928
+ }
929
+ }
885
930
  </style>
886
931
  <svg viewBox="0 0 100 100">
887
932
  <path id="orbitHit" vector-effect="non-scaling-stroke"></path>
933
+ <path id="orbitWave" shape-rendering="geometricPrecision"></path>
888
934
  <path id="orbitShape" shape-rendering="geometricPrecision" vector-effect="non-scaling-stroke"></path>
889
935
  <path id="orbitPath" shape-rendering="geometricPrecision" vector-effect="non-scaling-stroke"></path>
890
936
  <text>
@@ -913,7 +959,9 @@ var OrbitArc = class extends OrbitBase {
913
959
  const orbitPath = this.shadowRoot.querySelector("#orbitPath");
914
960
  const orbitShape = this.shadowRoot.querySelector("#orbitShape");
915
961
  const textPath = this.shadowRoot.querySelector("textPath");
916
- orbitShape.setAttribute("d", this.calculateArcParameters(attrs).dShape);
962
+ const { dShape } = this.calculateArcParameters(attrs);
963
+ orbitShape.setAttribute("d", dShape);
964
+ this.shadowRoot.querySelector("#orbitWave").setAttribute("d", dShape);
917
965
  orbitPath.setAttribute("d", this.calculateTextArcParameters(attrs).dPath);
918
966
  this.updateHitArea(this.shadowRoot.querySelector("#orbitHit"), attrs, 0, attrs.arcAngle);
919
967
  const textAnchor = attrs.textAnchor;
@@ -974,26 +1022,45 @@ var OrbitArc = class extends OrbitBase {
974
1022
  const gap = Math.max(0, this.readNumber(style, "--o-gap", 1));
975
1023
  const svgFontSize = `calc(${fontSize} * (100 / (${length}) * (12 / var(--o-orbit-number)))`;
976
1024
  const auto = this.getAttribute("range") === "auto";
977
- const stacked = auto || this.hasAttribute("value");
1025
+ const valued = this.hasAttribute("value");
1026
+ const placed = this.hasAttribute("start");
1027
+ const stacked = auto || valued || placed;
1028
+ const max = this.readMax(style);
978
1029
  let arcAngle;
979
1030
  if (auto) arcAngle = this.measureTextAngle(svgFontSize, common.realRadius, gap);
980
- else if (this.hasAttribute("value")) arcAngle = super.getProgressAngle(range, this.readValue(), this.readMax());
1031
+ else if (valued) arcAngle = super.getProgressAngle(range, this.readValue(), max);
981
1032
  else arcAngle = Math.max(0, Math.min(360, this.readAngle(style, "--o-angle", 0)));
982
1033
  this._autoAngle = auto ? arcAngle : 0;
983
1034
  let stackOffset = 0;
984
- if (stacked) {
1035
+ if (placed) {
1036
+ stackOffset = max > 0 ? this.readStart() / max * range : 0;
1037
+ if (!auto && range < 360) {
1038
+ const end = Math.min(range, stackOffset + arcAngle);
1039
+ stackOffset = Math.max(0, stackOffset);
1040
+ arcAngle = Math.max(0, end - stackOffset);
1041
+ }
1042
+ } else if (stacked) {
985
1043
  for (let prev = this.previousElementSibling; prev; prev = prev.previousElementSibling) {
986
- if (prev.localName !== "o-arc") continue;
1044
+ if (prev.localName !== "o-arc" || prev.hasAttribute("start")) continue;
987
1045
  const previousStyle = this.ownerDocument.defaultView.getComputedStyle(prev);
988
1046
  if (prev.getAttribute("range") === "auto") stackOffset += prev._autoAngle || 0;
989
1047
  else if (prev.hasAttribute("value")) {
990
- const prevMax = prev.hasAttribute("max") ? Number(prev.getAttribute("max")) : 100;
1048
+ const prevMax = this.readMax.call(prev, previousStyle);
991
1049
  const prevRange = cssNumber(prev, previousStyle.getPropertyValue("--o-range"), range, "angle");
992
1050
  stackOffset += super.getProgressAngle(prevRange, Number(prev.getAttribute("value")), prevMax);
993
1051
  } else stackOffset += cssNumber(prev, previousStyle.getPropertyValue("--o-angle"), 0, "angle");
994
1052
  }
995
1053
  }
996
- return { ...common, gap, arcAngle, stackOffset, flip, fitRange, length, fontSize, svgFontSize, textAnchor, auto, stacked };
1054
+ const reach = this.classList.contains("ripple") ? Math.max(1, this.readNumber(style, "--o-ripple-scale", 1.14)) : 1;
1055
+ return { ...common, gap, max, arcAngle, stackOffset, flip, fitRange, length, fontSize, svgFontSize, textAnchor, auto, placed, stacked, reach };
1056
+ }
1057
+ /** The start attribute: where a placed arc begins, on the ring's scale. */
1058
+ readStart() {
1059
+ const raw = this.getAttribute("start");
1060
+ const start = Number(raw);
1061
+ if (Number.isFinite(start)) return start;
1062
+ warnOnce(this, "start:" + raw, `<o-arc start="${raw}"> is not a number, so the arc starts at 0.`);
1063
+ return 0;
997
1064
  }
998
1065
  /** range="auto": the angle that fits this arc's text, with half an em of room at each end. */
999
1066
  measureTextAngle(svgFontSize, radius, gap) {
@@ -11,7 +11,7 @@
11
11
  },
12
12
  {
13
13
  "name": "max",
14
- "description": "Value that fills the ring's range. Must be positive. Default: 100."
14
+ "description": "Value that fills the ring's range. Must be positive. Without it, --o-max of the ring or system. Default: 100."
15
15
  },
16
16
  {
17
17
  "name": "shape",
@@ -58,6 +58,10 @@
58
58
  "name": "hit-width",
59
59
  "description": "Extra touch area in px on each side of an interactive band. Default: 0."
60
60
  },
61
+ {
62
+ "name": "start",
63
+ "description": "Where the arc begins, on the same scale as value. A placed arc takes no slot and moves no other arc: text over a ring that already has arcs, or segments on a timeline."
64
+ },
61
65
  {
62
66
  "name": "text-anchor",
63
67
  "description": "Where curved text sits on the arc. With range=\"auto\", an explicit value anchors the arc at its angle: middle centers it, end ends it there. Default: middle.",
@@ -104,7 +108,7 @@
104
108
  },
105
109
  {
106
110
  "name": "max",
107
- "description": "Value that fills the ring's range. Must be positive. Default: 100."
111
+ "description": "Value that fills the ring's range. Must be positive. Without it, --o-max of the ring or system. Default: 100."
108
112
  },
109
113
  {
110
114
  "name": "shape",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zumer/orbit",
3
- "version": "2.0.1",
3
+ "version": "2.1.0",
4
4
  "description": "Orbit builds radial interfaces with CSS geometry and a small JavaScript layout runtime",
5
5
  "main": "./dist/orbit.js",
6
6
  "module": "./dist/orbit.mjs",
@@ -29,7 +29,7 @@
29
29
  "scripts": {
30
30
  "compile": "node esbuild.config.mjs",
31
31
  "demo": "npm run compile && node scripts/demo.mjs",
32
- "docs": "npm run compile && node scripts/docs-sync.mjs && node scripts/demo.mjs",
32
+ "docs": "npm run compile && node scripts/docs-sync.mjs && node scripts/sitemap.mjs && node scripts/demo.mjs",
33
33
  "docs:sync": "node scripts/docs-sync.mjs",
34
34
  "bump:dry": "npx @zumerbox/bump -d",
35
35
  "bump": "npx @zumerbox/bump && npx @zumerbox/changelog",