@vielzeug/prism 3.0.0 → 26.10.1
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/README.md +2 -2
- package/dist/_dev.cjs +1 -1
- package/dist/_dev.cjs.map +1 -1
- package/dist/_dev.js +1 -5
- package/dist/_dev.js.map +1 -1
- package/dist/animation/easing.cjs +1 -1
- package/dist/animation/easing.cjs.map +1 -1
- package/dist/animation/easing.js +1 -13
- package/dist/animation/easing.js.map +1 -1
- package/dist/animation/motion.cjs +1 -1
- package/dist/animation/motion.cjs.map +1 -1
- package/dist/animation/motion.js +1 -12
- package/dist/animation/motion.js.map +1 -1
- package/dist/animation/transition.cjs +1 -1
- package/dist/animation/transition.cjs.map +1 -1
- package/dist/animation/transition.js +1 -28
- package/dist/animation/transition.js.map +1 -1
- package/dist/animation/tween.cjs +1 -1
- package/dist/animation/tween.cjs.map +1 -1
- package/dist/animation/tween.js +1 -7
- package/dist/animation/tween.js.map +1 -1
- package/dist/axes/axis.cjs +1 -1
- package/dist/axes/axis.cjs.map +1 -1
- package/dist/axes/axis.d.ts +2 -2
- package/dist/axes/axis.d.ts.map +1 -1
- package/dist/axes/axis.js +1 -63
- package/dist/axes/axis.js.map +1 -1
- package/dist/axes/grid.cjs +1 -1
- package/dist/axes/grid.cjs.map +1 -1
- package/dist/axes/grid.js +1 -29
- package/dist/axes/grid.js.map +1 -1
- package/dist/axes/scale-utils.cjs +1 -1
- package/dist/axes/scale-utils.cjs.map +1 -1
- package/dist/axes/scale-utils.d.ts +1 -1
- package/dist/axes/scale-utils.js +1 -10
- package/dist/axes/scale-utils.js.map +1 -1
- package/dist/charts/area/area-chart.cjs +1 -1
- package/dist/charts/area/area-chart.cjs.map +1 -1
- package/dist/charts/area/area-chart.d.ts.map +1 -1
- package/dist/charts/area/area-chart.js +1 -57
- package/dist/charts/area/area-chart.js.map +1 -1
- package/dist/charts/area/area-renderer.cjs +1 -1
- package/dist/charts/area/area-renderer.cjs.map +1 -1
- package/dist/charts/area/area-renderer.d.ts +4 -2
- package/dist/charts/area/area-renderer.d.ts.map +1 -1
- package/dist/charts/area/area-renderer.js +1 -73
- package/dist/charts/area/area-renderer.js.map +1 -1
- package/dist/charts/bar/bar-chart.cjs +1 -1
- package/dist/charts/bar/bar-chart.cjs.map +1 -1
- package/dist/charts/bar/bar-chart.d.ts.map +1 -1
- package/dist/charts/bar/bar-chart.js +1 -169
- package/dist/charts/bar/bar-chart.js.map +1 -1
- package/dist/charts/bar/bar-hit-test.cjs +1 -1
- package/dist/charts/bar/bar-hit-test.cjs.map +1 -1
- package/dist/charts/bar/bar-hit-test.d.ts +0 -5
- package/dist/charts/bar/bar-hit-test.d.ts.map +1 -1
- package/dist/charts/bar/bar-hit-test.js +1 -29
- package/dist/charts/bar/bar-hit-test.js.map +1 -1
- package/dist/charts/bar/bar-renderer.cjs +1 -1
- package/dist/charts/bar/bar-renderer.cjs.map +1 -1
- package/dist/charts/bar/bar-renderer.d.ts +1 -1
- package/dist/charts/bar/bar-renderer.d.ts.map +1 -1
- package/dist/charts/bar/bar-renderer.js +1 -106
- package/dist/charts/bar/bar-renderer.js.map +1 -1
- package/dist/charts/line/line-chart.cjs +1 -1
- package/dist/charts/line/line-chart.cjs.map +1 -1
- package/dist/charts/line/line-chart.d.ts.map +1 -1
- package/dist/charts/line/line-chart.js +1 -58
- package/dist/charts/line/line-chart.js.map +1 -1
- package/dist/charts/line/line-renderer.cjs +1 -1
- package/dist/charts/line/line-renderer.cjs.map +1 -1
- package/dist/charts/line/line-renderer.d.ts +3 -2
- package/dist/charts/line/line-renderer.d.ts.map +1 -1
- package/dist/charts/line/line-renderer.js +1 -100
- package/dist/charts/line/line-renderer.js.map +1 -1
- package/dist/charts/pie/pie-chart.cjs +1 -1
- package/dist/charts/pie/pie-chart.cjs.map +1 -1
- package/dist/charts/pie/pie-chart.d.ts.map +1 -1
- package/dist/charts/pie/pie-chart.js +1 -165
- package/dist/charts/pie/pie-chart.js.map +1 -1
- package/dist/charts/pie/pie-renderer.cjs +1 -1
- package/dist/charts/pie/pie-renderer.cjs.map +1 -1
- package/dist/charts/pie/pie-renderer.d.ts.map +1 -1
- package/dist/charts/pie/pie-renderer.js +1 -76
- package/dist/charts/pie/pie-renderer.js.map +1 -1
- package/dist/charts/radar/index.d.ts +2 -0
- package/dist/charts/radar/index.d.ts.map +1 -0
- package/dist/charts/radar/radar-chart.cjs +2 -0
- package/dist/charts/radar/radar-chart.cjs.map +1 -0
- package/dist/charts/radar/radar-chart.d.ts +3 -0
- package/dist/charts/radar/radar-chart.d.ts.map +1 -0
- package/dist/charts/radar/radar-chart.js +2 -0
- package/dist/charts/radar/radar-chart.js.map +1 -0
- package/dist/charts/radar/radar-geometry.cjs +2 -0
- package/dist/charts/radar/radar-geometry.cjs.map +1 -0
- package/dist/charts/radar/radar-geometry.d.ts +22 -0
- package/dist/charts/radar/radar-geometry.d.ts.map +1 -0
- package/dist/charts/radar/radar-geometry.js +2 -0
- package/dist/charts/radar/radar-geometry.js.map +1 -0
- package/dist/charts/sparkline/sparkline.cjs +1 -1
- package/dist/charts/sparkline/sparkline.cjs.map +1 -1
- package/dist/charts/sparkline/sparkline.d.ts.map +1 -1
- package/dist/charts/sparkline/sparkline.js +1 -191
- package/dist/charts/sparkline/sparkline.js.map +1 -1
- package/dist/core/cartesian-model.cjs +1 -1
- package/dist/core/cartesian-model.cjs.map +1 -1
- package/dist/core/cartesian-model.js +1 -30
- package/dist/core/cartesian-model.js.map +1 -1
- package/dist/core/cartesian-scales.cjs +1 -1
- package/dist/core/cartesian-scales.cjs.map +1 -1
- package/dist/core/cartesian-scales.js +1 -37
- package/dist/core/cartesian-scales.js.map +1 -1
- package/dist/core/chart-base.cjs +1 -1
- package/dist/core/chart-base.cjs.map +1 -1
- package/dist/core/chart-base.d.ts +9 -0
- package/dist/core/chart-base.d.ts.map +1 -1
- package/dist/core/chart-base.js +1 -53
- package/dist/core/chart-base.js.map +1 -1
- package/dist/core/chart-scaffold.cjs +1 -1
- package/dist/core/chart-scaffold.cjs.map +1 -1
- package/dist/core/chart-scaffold.d.ts +7 -3
- package/dist/core/chart-scaffold.d.ts.map +1 -1
- package/dist/core/chart-scaffold.js +1 -89
- package/dist/core/chart-scaffold.js.map +1 -1
- package/dist/core/ids.cjs +2 -0
- package/dist/core/ids.cjs.map +1 -0
- package/dist/core/ids.d.ts +3 -0
- package/dist/core/ids.d.ts.map +1 -0
- package/dist/core/ids.js +2 -0
- package/dist/core/ids.js.map +1 -0
- package/dist/core/layout.cjs +1 -1
- package/dist/core/layout.cjs.map +1 -1
- package/dist/core/layout.js +1 -22
- package/dist/core/layout.js.map +1 -1
- package/dist/core/polar.cjs +2 -0
- package/dist/core/polar.cjs.map +1 -0
- package/dist/core/polar.d.ts +5 -0
- package/dist/core/polar.d.ts.map +1 -0
- package/dist/core/polar.js +2 -0
- package/dist/core/polar.js.map +1 -0
- package/dist/core/responsive.cjs +1 -1
- package/dist/core/responsive.cjs.map +1 -1
- package/dist/core/responsive.js +1 -19
- package/dist/core/responsive.js.map +1 -1
- package/dist/devtools/index.d.ts +1 -1
- package/dist/devtools.cjs +1 -1
- package/dist/devtools.cjs.map +1 -1
- package/dist/devtools.js +1 -18
- package/dist/devtools.js.map +1 -1
- package/dist/errors.cjs +1 -1
- package/dist/errors.cjs.map +1 -1
- package/dist/errors.d.ts +1 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +1 -9
- package/dist/errors.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -11
- package/dist/interaction/announcer.cjs +2 -0
- package/dist/interaction/announcer.cjs.map +1 -0
- package/dist/interaction/announcer.d.ts +13 -0
- package/dist/interaction/announcer.d.ts.map +1 -0
- package/dist/interaction/announcer.js +2 -0
- package/dist/interaction/announcer.js.map +1 -0
- package/dist/interaction/crosshair.cjs +1 -1
- package/dist/interaction/crosshair.cjs.map +1 -1
- package/dist/interaction/crosshair.d.ts +1 -5
- package/dist/interaction/crosshair.d.ts.map +1 -1
- package/dist/interaction/crosshair.js +1 -45
- package/dist/interaction/crosshair.js.map +1 -1
- package/dist/interaction/events.cjs +1 -1
- package/dist/interaction/events.cjs.map +1 -1
- package/dist/interaction/events.js +1 -11
- package/dist/interaction/events.js.map +1 -1
- package/dist/interaction/legend.cjs +1 -1
- package/dist/interaction/legend.cjs.map +1 -1
- package/dist/interaction/legend.js +1 -30
- package/dist/interaction/legend.js.map +1 -1
- package/dist/interaction/series-interaction.cjs +1 -1
- package/dist/interaction/series-interaction.cjs.map +1 -1
- package/dist/interaction/series-interaction.d.ts +11 -1
- package/dist/interaction/series-interaction.d.ts.map +1 -1
- package/dist/interaction/series-interaction.js +1 -97
- package/dist/interaction/series-interaction.js.map +1 -1
- package/dist/interaction/tooltip.cjs +1 -1
- package/dist/interaction/tooltip.cjs.map +1 -1
- package/dist/interaction/tooltip.d.ts +12 -1
- package/dist/interaction/tooltip.d.ts.map +1 -1
- package/dist/interaction/tooltip.js +1 -63
- package/dist/interaction/tooltip.js.map +1 -1
- package/dist/prism.cjs +1 -1
- package/dist/prism.cjs.map +1 -1
- package/dist/prism.iife.js +1 -1
- package/dist/prism.iife.js.map +1 -1
- package/dist/prism.js +1 -1
- package/dist/prism.js.map +1 -1
- package/dist/scales/band.cjs +1 -1
- package/dist/scales/band.cjs.map +1 -1
- package/dist/scales/band.js +1 -39
- package/dist/scales/band.js.map +1 -1
- package/dist/scales/linear.cjs +1 -1
- package/dist/scales/linear.cjs.map +1 -1
- package/dist/scales/linear.js +1 -43
- package/dist/scales/linear.js.map +1 -1
- package/dist/scales/time.cjs +1 -1
- package/dist/scales/time.cjs.map +1 -1
- package/dist/scales/time.js +1 -61
- package/dist/scales/time.js.map +1 -1
- package/dist/svg/element.cjs +1 -1
- package/dist/svg/element.cjs.map +1 -1
- package/dist/svg/element.js +1 -22
- package/dist/svg/element.js.map +1 -1
- package/dist/svg/path.cjs +1 -1
- package/dist/svg/path.cjs.map +1 -1
- package/dist/svg/path.js +1 -48
- package/dist/svg/path.js.map +1 -1
- package/dist/svg/text.cjs +1 -1
- package/dist/svg/text.cjs.map +1 -1
- package/dist/svg/text.d.ts +1 -0
- package/dist/svg/text.d.ts.map +1 -1
- package/dist/svg/text.js +1 -9
- package/dist/svg/text.js.map +1 -1
- package/dist/theme/index.cjs +1 -1
- package/dist/theme/index.cjs.map +1 -1
- package/dist/theme/index.js +1 -19
- package/dist/theme/index.js.map +1 -1
- package/dist/theme/prism.css +214 -7
- package/dist/types.d.ts +65 -5
- package/dist/types.d.ts.map +1 -1
- package/package.json +6 -5
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import"../../_dev.js";import{createSvgElement as e,setAttributes as t}from"../../svg/element.js";import{describeValues as n}from"../../interaction/announcer.js";import{comparisonContent as r}from"../../interaction/tooltip.js";import{createRadialScaffold as i}from"../../core/chart-scaffold.js";import{seriesColor as a}from"../../theme/index.js";import{resolveEasing as o}from"../../animation/easing.js";import{resolveMotion as s}from"../../animation/motion.js";import{tweenNumber as c}from"../../animation/tween.js";import{uniqueId as l}from"../../core/ids.js";import{polarX as u,polarY as d}from"../../core/polar.js";import{axisAngles as f,closedPath as p,fitRadius as m,labelPlacement as h,nearestAxis as g,normalize as _,radarPoints as v,resolveAxisDomains as y,ringPath as b,toRadians as x}from"./radar-geometry.js";var S=11,C=12,w=10,T={ArrowDown:1,ArrowLeft:-1,ArrowRight:1,ArrowUp:-1};function resolveGrid(e){return e===!1?null:{bands:!0,labels:!1,levels:4,shape:`polygon`,...typeof e==`object`?e:{}}}function createRadarChart(E,D){let{axes:O}=D,k=D.curve??`linear`,A=D.fill??`solid`,j=D.showPoints??!0,M=resolveGrid(D.grid),N=x(D.startAngle??0),P=f(O.length,N),F=C+(D.showValues?w:0),I=l(`prism-radar`),L=D.series,R=e(`g`,{class:`prism-radar`}),z=e(`defs`),B=e(`g`,{"aria-hidden":`true`,class:`prism-radar-grid`}),V=e(`g`,{class:`prism-radar-series-group`}),H=e(`g`,{"aria-hidden":`true`,class:`prism-radar-labels`});R.append(z,B,V,H);let U=[],W=null,G=-1,K={cx:0,cy:0,radius:0},datumAt=(e,t)=>e.data.find(e=>e.key===O[t].key),valuesAt=e=>L.map(t=>({datum:datumAt(t,e),series:t})),formatValue=(e,t)=>O[e].format?.(t)??String(t),describe=e=>n(O[e].label,valuesAt(e),t=>formatValue(e,t));function draw(e){let{cx:n,cy:r,radius:i}=K;e.forEach((e,a)=>{let o=V.children[a];if(!o)return;let s=v(e,n,r,i,P);o.querySelector(`.prism-radar-area`)?.setAttribute(`d`,p(s,k)),o.querySelectorAll(`.prism-radar-point`).forEach((e,n)=>{t(e,{cx:s[n].x,cy:s[n].y})}),o.querySelectorAll(`.prism-radar-value`).forEach((a,o)=>{let s=i*e[o]+w;t(a,{x:u(n,s,P[o]),y:d(r,s,P[o])})})})}function renderGrid(t){if(B.replaceChildren(),!M)return;let{cx:n,cy:r,radius:i}=K,a=Math.max(1,Math.round(M.levels)),o=Array.from({length:a},(e,t)=>b(M.shape,n,r,i*(t+1)/a,P));if(M.bands)for(let t=a-1;t>=0;t-=2)B.appendChild(e(`path`,{class:`prism-radar-band`,d:`${o[t]}${o[t-1]??``}`,"fill-rule":`evenodd`}));for(let t of o)B.appendChild(e(`path`,{class:`prism-radar-ring`,d:t,fill:`none`}));P.forEach((t,a)=>{B.appendChild(e(`line`,{class:`prism-radar-spoke`,"data-axis":a,x1:n,x2:u(n,i,t),y1:r,y2:d(r,i,t)}))});let[s,c]=t[0],l=t.every(([e,t])=>e===s&&t===c);if(!M.labels||!l)return;let f=P[0]+Math.PI/P.length;for(let t=1;t<=a;t++){let o=i*t/a,l=e(`text`,{class:`prism-radar-level`,"dominant-baseline":`middle`,"text-anchor":`middle`,x:u(n,o,f),y:d(r,o,f)});l.textContent=formatValue(0,Math.round((s+(c-s)*t/a)*100)/100),B.appendChild(l)}}function renderLabels(){H.replaceChildren();let{cx:t,cy:n,radius:r}=K;O.forEach((i,a)=>{let{anchor:o,baseline:s}=h(P[a]),c=e(`text`,{class:`prism-radar-axis-label`,"dominant-baseline":s,"text-anchor":o,x:u(t,r+F,P[a]),y:d(n,r+F,P[a])});c.textContent=i.label,H.appendChild(c)})}function renderSeries(){let{cx:n,cy:r,radius:i}=K;for(z.replaceChildren();V.children.length>L.length;)V.lastChild?.remove();L.forEach((o,s)=>{let c=o.color??a(s),l=V.children[s];l||(l=e(`g`,{class:`prism-radar-series`}),V.appendChild(l)),l.replaceChildren();let u=e(`path`,{class:`prism-radar-area prism-radar-area--${A}`,stroke:c,"stroke-linejoin":`round`,"stroke-width":2});if(A===`gradient`){let a=`${I}-fill-${s}`,o=e(`radialGradient`,{cx:n,cy:r,gradientUnits:`userSpaceOnUse`,id:a,r:i});for(let[t,n]of[[0,.08],[1,.55]])o.appendChild(e(`stop`,{offset:t,"stop-color":c,"stop-opacity":n,style:`stop-color:${c}`}));z.appendChild(o),t(u,{fill:`url(#${a})`})}else t(u,{fill:A===`none`?`none`:c,"fill-opacity":.25});l.appendChild(u),j&&O.forEach((t,n)=>{let r=!Number.isFinite(datumAt(o,n)?.value);l.appendChild(e(`circle`,{class:`prism-radar-point${r?` prism-radar-point--missing`:``}`,"data-axis":n,fill:r?`none`:c,r:3,stroke:c}))}),D.showValues&&O.forEach((t,n)=>{let r=datumAt(o,n),{anchor:i,baseline:a}=h(P[n]),s=e(`text`,{"aria-hidden":`true`,class:`prism-radar-value`,"dominant-baseline":a,"text-anchor":i});s.textContent=r&&Number.isFinite(r.value)?formatValue(n,r.value):``,l.appendChild(s)})})}function setActive(e){G=e;for(let t of R.querySelectorAll(`[data-axis]`)){let n=Number(t.getAttribute(`data-axis`))===e;t.classList.toggle(t.tagName===`line`?`prism-radar-spoke--active`:`prism-radar-point--active`,n)}}function animateTo(e){W!==null&&(cancelAnimationFrame(W),W=null);let t=e.map((e,t)=>e.map((e,n)=>U[t]?.[n]??0)),n=s(D.transition,400),r=o(n.easing??`ease-out`),i=t.every((t,n)=>t.every((t,r)=>t===e[n][r]));if(n.duration===0||i){U=e,draw(e);return}let a=null,frame=i=>{a===null&&(a=i);let o=i-a,s=!0;U=e.map((e,i)=>{let a=Math.max(0,Math.min(1,(o-i*n.stagger)/n.duration));return a<1&&(s=!1),e.map((e,n)=>c(t[i][n],e,r(a)))}),draw(U),W=s?null:requestAnimationFrame(frame)};W=requestAnimationFrame(frame)}let q;try{return q=i(E,{a11y:D.a11y,legend:D.legend,tooltip:D.tooltip},e=>{let{legend:t,svg:n,tooltip:i}=e;if(n.contains(R)||n.appendChild(R),i?.hide(),t?.update(L.map((e,t)=>({color:e.color??a(t),name:e.name}))),O.length<3){for(let e of[z,B,V,H])e.replaceChildren();U=[];return}let{height:o,width:s}=e.dimensions,c=m(s,o,O.map(e=>e.label),P,S,F);K={cx:s/2,cy:o/2,radius:c};let l=y(O,L,D.domain);renderGrid(l),renderLabels(),renderSeries(),animateTo(L.map(e=>O.map((t,n)=>{let r=datumAt(e,n)?.value;return r!==void 0&&Number.isFinite(r)?_(r,l[n]):0}))),setActive(G);let eventFor=(e,t)=>({axis:O[e],index:e,originalEvent:t,values:valuesAt(e)}),activate=(t,o)=>{setActive(t),D.onHover?.(eventFor(t,o));let s=describe(t);if(!i){e.announcer.announce(s);return}let c=Math.max(0,...U.map(e=>e[t]??0)),l=n.getBoundingClientRect(),f=E.getBoundingClientRect(),p=valuesAt(t),m=p.find(e=>e.datum)?.datum,h=p.flatMap(({datum:e,series:n})=>e?[{color:n.color??a(L.indexOf(n)),name:n.name,value:formatValue(t,e.value)}]:[]);i.show(u(K.cx,K.radius*c,P[t])+(l.left-f.left),d(K.cy,K.radius*c,P[t])+(l.top-f.top),{key:O[t].key,meta:{axis:O[t],text:s,values:p},value:m?.value??0},{color:L[0]?.color??a(0),data:[],name:O[t].label},r(n.ownerDocument,O[t].label,h,s))},deactivate=()=>{setActive(-1),D.onHover?.(null),i?.hide(),e.announcer.clear()},hitIndex=e=>{let t=n.getBoundingClientRect(),r=e.clientX-t.left-K.cx,i=e.clientY-t.top-K.cy;return Math.hypot(r,i)>K.radius+F+22?-1:g(r,i,O.length,N)};return{onClick(e){let t=hitIndex(e);t>=0&&D.onClick?.(eventFor(t,e))},onKeyDown(e){let t=T[e.key];t===void 0?(e.key===`Enter`||e.key===` `)&&G>=0&&D.onClick?(e.preventDefault(),D.onClick(eventFor(G,e))):e.key===`Escape`&&deactivate():(e.preventDefault(),activate(G<0?0:(G+t+O.length)%O.length,e))},onMouseLeave:deactivate,onMouseMove(e){let t=hitIndex(e);t<0?G>=0&&deactivate():t!==G&&activate(t,e)}}},e=>{L=e}),{get disposalSignal(){return q.disposalSignal},dispose(){W!==null&&(cancelAnimationFrame(W),W=null),q.dispose()},get disposed(){return q.disposed},el:q.el,update(e){q.update(e)},[Symbol.dispose](){this.dispose()}}}catch(e){throw q?.dispose(),e}}export{createRadarChart};
|
|
2
|
+
//# sourceMappingURL=radar-chart.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"radar-chart.js","names":[],"sources":["../../../src/charts/radar/radar-chart.ts"],"sourcesContent":["import { devOnly, warn } from '../../_dev';\nimport { resolveEasing } from '../../animation/easing';\nimport { resolveMotion } from '../../animation/motion';\nimport { tweenNumber } from '../../animation/tween';\nimport type { ChartEventHandlers } from '../../core/chart-scaffold';\nimport { createRadialScaffold } from '../../core/chart-scaffold';\nimport { uniqueId } from '../../core/ids';\nimport { polarX, polarY } from '../../core/polar';\nimport { describeValues } from '../../interaction/announcer';\nimport { comparisonContent } from '../../interaction/tooltip';\nimport { createSvgElement, setAttributes } from '../../svg/element';\nimport { seriesColor } from '../../theme';\nimport type {\n ChartHandle,\n RadarAxisConfig,\n RadarAxisValue,\n RadarChartConfig,\n RadarEvent,\n RadarGridConfig,\n RadarSeriesConfig,\n} from '../../types';\nimport {\n axisAngles,\n closedPath,\n fitRadius,\n labelPlacement,\n nearestAxis,\n normalize,\n radarPoints,\n resolveAxisDomains,\n ringPath,\n toRadians,\n} from './radar-geometry';\n\n/** Default `--prism-font-size-label` (0.6875rem) in px, used to reserve label room. */\nconst LABEL_FONT_SIZE = 11;\nconst LABEL_GAP = 12;\nconst VALUE_OFFSET = 10;\nconst ARROW_STEPS: Record<string, number> = { ArrowDown: 1, ArrowLeft: -1, ArrowRight: 1, ArrowUp: -1 };\n\nfunction warnOnInvalid(axes: readonly RadarAxisConfig[], series: readonly RadarSeriesConfig[]): void {\n devOnly(() => {\n if (axes.length < 3) warn(`Radar chart needs at least 3 axes, received ${axes.length}.`);\n\n const keys = new Set(axes.map((axis) => axis.key));\n\n if (keys.size !== axes.length) warn('Radar chart axis keys must be unique.');\n\n for (const s of series) {\n for (const d of s.data) {\n if (!keys.has(d.key)) warn(`Radar series \"${s.name}\" has a value for unknown axis \"${d.key}\".`);\n }\n }\n });\n}\n\nfunction resolveGrid(grid: RadarChartConfig['grid']): Required<RadarGridConfig> | null {\n if (grid === false) return null;\n\n return { bands: true, labels: false, levels: 4, shape: 'polygon', ...(typeof grid === 'object' ? grid : {}) };\n}\n\nexport function createRadarChart(container: HTMLElement, config: RadarChartConfig): ChartHandle<RadarSeriesConfig[]> {\n const { axes } = config;\n const curve = config.curve ?? 'linear';\n const fill = config.fill ?? 'solid';\n const showPoints = config.showPoints ?? true;\n const grid = resolveGrid(config.grid);\n const startAngle = toRadians(config.startAngle ?? 0);\n const angles = axisAngles(axes.length, startAngle);\n const labelGap = LABEL_GAP + (config.showValues ? VALUE_OFFSET : 0);\n const id = uniqueId('prism-radar');\n let series = config.series;\n\n warnOnInvalid(axes, series);\n\n const root = createSvgElement('g', { class: 'prism-radar' });\n const defs = createSvgElement('defs');\n const gridGroup = createSvgElement('g', { 'aria-hidden': 'true', class: 'prism-radar-grid' });\n const seriesGroup = createSvgElement('g', { class: 'prism-radar-series-group' });\n const labelGroup = createSvgElement('g', { 'aria-hidden': 'true', class: 'prism-radar-labels' });\n\n root.append(defs, gridGroup, seriesGroup, labelGroup);\n\n let drawn: number[][] = [];\n let activeRaf: number | null = null;\n let activeIndex = -1;\n let layout = { cx: 0, cy: 0, radius: 0 };\n\n const datumAt = (s: RadarSeriesConfig, index: number) => s.data.find((d) => d.key === axes[index].key);\n const valuesAt = (index: number): RadarAxisValue[] => series.map((s) => ({ datum: datumAt(s, index), series: s }));\n const formatValue = (index: number, value: number): string => axes[index].format?.(value) ?? String(value);\n const describe = (index: number): string =>\n describeValues(axes[index].label, valuesAt(index), (value) => formatValue(index, value));\n\n function draw(fractions: number[][]): void {\n const { cx, cy, radius } = layout;\n\n fractions.forEach((row, i) => {\n const group = seriesGroup.children[i];\n\n if (!group) return;\n\n const points = radarPoints(row, cx, cy, radius, angles);\n\n group.querySelector('.prism-radar-area')?.setAttribute('d', closedPath(points, curve));\n group.querySelectorAll<SVGCircleElement>('.prism-radar-point').forEach((dot, j) => {\n setAttributes(dot, { cx: points[j].x, cy: points[j].y });\n });\n group.querySelectorAll<SVGTextElement>('.prism-radar-value').forEach((text, j) => {\n const r = radius * row[j] + VALUE_OFFSET;\n\n setAttributes(text, { x: polarX(cx, r, angles[j]), y: polarY(cy, r, angles[j]) });\n });\n });\n }\n\n function renderGrid(domains: [number, number][]): void {\n gridGroup.replaceChildren();\n\n if (!grid) return;\n\n const { cx, cy, radius } = layout;\n const levels = Math.max(1, Math.round(grid.levels));\n const rings = Array.from({ length: levels }, (_, k) =>\n ringPath(grid.shape, cx, cy, (radius * (k + 1)) / levels, angles),\n );\n\n if (grid.bands) {\n // Shade alternate rings, starting from the outermost.\n for (let k = levels - 1; k >= 0; k -= 2) {\n gridGroup.appendChild(\n createSvgElement('path', {\n class: 'prism-radar-band',\n d: `${rings[k]}${rings[k - 1] ?? ''}`,\n 'fill-rule': 'evenodd',\n }),\n );\n }\n }\n\n for (const d of rings)\n gridGroup.appendChild(createSvgElement('path', { class: 'prism-radar-ring', d, fill: 'none' }));\n\n angles.forEach((angle, i) => {\n gridGroup.appendChild(\n createSvgElement('line', {\n class: 'prism-radar-spoke',\n 'data-axis': i,\n x1: cx,\n x2: polarX(cx, radius, angle),\n y1: cy,\n y2: polarY(cy, radius, angle),\n }),\n );\n });\n\n const [d0, d1] = domains[0];\n const shared = domains.every(([a, b]) => a === d0 && b === d1);\n\n if (!grid.labels || !shared) return;\n\n // Between the first two spokes, so level values never collide with vertex values.\n const angle = angles[0] + Math.PI / angles.length;\n\n for (let k = 1; k <= levels; k++) {\n const r = (radius * k) / levels;\n const text = createSvgElement('text', {\n class: 'prism-radar-level',\n 'dominant-baseline': 'middle',\n 'text-anchor': 'middle',\n x: polarX(cx, r, angle),\n y: polarY(cy, r, angle),\n });\n\n text.textContent = formatValue(0, Math.round((d0 + ((d1 - d0) * k) / levels) * 100) / 100);\n gridGroup.appendChild(text);\n }\n }\n\n function renderLabels(): void {\n labelGroup.replaceChildren();\n\n const { cx, cy, radius } = layout;\n\n axes.forEach((axis, i) => {\n const { anchor, baseline } = labelPlacement(angles[i]);\n const text = createSvgElement('text', {\n class: 'prism-radar-axis-label',\n 'dominant-baseline': baseline,\n 'text-anchor': anchor,\n x: polarX(cx, radius + labelGap, angles[i]),\n y: polarY(cy, radius + labelGap, angles[i]),\n });\n\n text.textContent = axis.label;\n labelGroup.appendChild(text);\n });\n }\n\n function renderSeries(): void {\n const { cx, cy, radius } = layout;\n\n defs.replaceChildren();\n\n while (seriesGroup.children.length > series.length) seriesGroup.lastChild?.remove();\n\n series.forEach((s, i) => {\n const color = s.color ?? seriesColor(i);\n let group = seriesGroup.children[i] as SVGGElement | undefined;\n\n if (!group) {\n group = createSvgElement('g', { class: 'prism-radar-series' });\n seriesGroup.appendChild(group);\n }\n\n group.replaceChildren();\n\n const area = createSvgElement('path', {\n class: `prism-radar-area prism-radar-area--${fill}`,\n stroke: color,\n 'stroke-linejoin': 'round',\n 'stroke-width': 2,\n });\n\n if (fill === 'gradient') {\n const gradientId = `${id}-fill-${i}`;\n const gradient = createSvgElement('radialGradient', {\n cx,\n cy,\n gradientUnits: 'userSpaceOnUse',\n id: gradientId,\n r: radius,\n });\n\n for (const [offset, opacity] of [\n [0, 0.08],\n [1, 0.55],\n ]) {\n gradient.appendChild(\n createSvgElement('stop', {\n offset,\n 'stop-color': color,\n 'stop-opacity': opacity,\n style: `stop-color:${color}`,\n }),\n );\n }\n\n defs.appendChild(gradient);\n setAttributes(area, { fill: `url(#${gradientId})` });\n } else {\n setAttributes(area, { fill: fill === 'none' ? 'none' : color, 'fill-opacity': 0.25 });\n }\n\n group.appendChild(area);\n\n if (showPoints) {\n axes.forEach((_, j) => {\n const missing = !Number.isFinite(datumAt(s, j)?.value);\n\n group.appendChild(\n createSvgElement('circle', {\n class: `prism-radar-point${missing ? ' prism-radar-point--missing' : ''}`,\n 'data-axis': j,\n fill: missing ? 'none' : color,\n r: 3,\n stroke: color,\n }),\n );\n });\n }\n\n if (config.showValues) {\n axes.forEach((_, j) => {\n const datum = datumAt(s, j);\n const { anchor, baseline } = labelPlacement(angles[j]);\n const text = createSvgElement('text', {\n 'aria-hidden': 'true',\n class: 'prism-radar-value',\n 'dominant-baseline': baseline,\n 'text-anchor': anchor,\n });\n\n text.textContent = datum && Number.isFinite(datum.value) ? formatValue(j, datum.value) : '';\n group.appendChild(text);\n });\n }\n });\n }\n\n function setActive(index: number): void {\n activeIndex = index;\n for (const el of root.querySelectorAll('[data-axis]')) {\n const active = Number(el.getAttribute('data-axis')) === index;\n\n el.classList.toggle(el.tagName === 'line' ? 'prism-radar-spoke--active' : 'prism-radar-point--active', active);\n }\n }\n\n function animateTo(targets: number[][]): void {\n if (activeRaf !== null) {\n cancelAnimationFrame(activeRaf);\n activeRaf = null;\n }\n\n const from = targets.map((row, i) => row.map((_, j) => drawn[i]?.[j] ?? 0));\n const motion = resolveMotion(config.transition, 400);\n const easing = resolveEasing(motion.easing ?? 'ease-out');\n const unchanged = from.every((row, i) => row.every((v, j) => v === targets[i][j]));\n\n if (motion.duration === 0 || unchanged) {\n drawn = targets;\n draw(targets);\n\n return;\n }\n\n let start: number | null = null;\n\n const frame = (ts: number): void => {\n if (start === null) start = ts;\n\n const elapsed = ts - start;\n let done = true;\n\n drawn = targets.map((row, i) => {\n const raw = Math.max(0, Math.min(1, (elapsed - i * motion.stagger) / motion.duration));\n\n if (raw < 1) done = false;\n\n return row.map((to, j) => tweenNumber(from[i][j], to, easing(raw)));\n });\n draw(drawn);\n activeRaf = done ? null : requestAnimationFrame(frame);\n };\n\n activeRaf = requestAnimationFrame(frame);\n }\n\n let handle: ChartHandle<RadarSeriesConfig[]> | undefined;\n\n try {\n handle = createRadialScaffold(\n container,\n { a11y: config.a11y, legend: config.legend, tooltip: config.tooltip },\n (ctx): ChartEventHandlers | undefined => {\n const { legend, svg, tooltip } = ctx;\n\n if (!svg.contains(root)) svg.appendChild(root);\n\n tooltip?.hide();\n legend?.update(series.map((s, i) => ({ color: s.color ?? seriesColor(i), name: s.name })));\n\n if (axes.length < 3) {\n for (const group of [defs, gridGroup, seriesGroup, labelGroup]) group.replaceChildren();\n drawn = [];\n\n return undefined;\n }\n\n const { height, width } = ctx.dimensions;\n const radius = fitRadius(\n width,\n height,\n axes.map((axis) => axis.label),\n angles,\n LABEL_FONT_SIZE,\n labelGap,\n );\n\n layout = { cx: width / 2, cy: height / 2, radius };\n\n const domains = resolveAxisDomains(axes, series, config.domain);\n\n renderGrid(domains);\n renderLabels();\n renderSeries();\n animateTo(\n series.map((s) =>\n axes.map((_, j) => {\n const value = datumAt(s, j)?.value;\n\n return value !== undefined && Number.isFinite(value) ? normalize(value, domains[j]) : 0;\n }),\n ),\n );\n setActive(activeIndex);\n\n const eventFor = (index: number, originalEvent: Event): RadarEvent => ({\n axis: axes[index],\n index,\n originalEvent,\n values: valuesAt(index),\n });\n\n const activate = (index: number, originalEvent: Event): void => {\n setActive(index);\n config.onHover?.(eventFor(index, originalEvent));\n\n const text = describe(index);\n\n if (!tooltip) {\n ctx.announcer.announce(text);\n\n return;\n }\n\n const reach = Math.max(0, ...drawn.map((row) => row[index] ?? 0));\n const svgRect = svg.getBoundingClientRect();\n const containerRect = container.getBoundingClientRect();\n const values = valuesAt(index);\n const first = values.find((v) => v.datum)?.datum;\n const rows = values.flatMap(({ datum, series: s }) =>\n datum\n ? [\n {\n color: s.color ?? seriesColor(series.indexOf(s)),\n name: s.name,\n value: formatValue(index, datum.value),\n },\n ]\n : [],\n );\n\n tooltip.show(\n polarX(layout.cx, layout.radius * reach, angles[index]) + (svgRect.left - containerRect.left),\n polarY(layout.cy, layout.radius * reach, angles[index]) + (svgRect.top - containerRect.top),\n { key: axes[index].key, meta: { axis: axes[index], text, values }, value: first?.value ?? 0 },\n { color: series[0]?.color ?? seriesColor(0), data: [], name: axes[index].label },\n comparisonContent(svg.ownerDocument, axes[index].label, rows, text),\n );\n };\n\n const deactivate = (): void => {\n setActive(-1);\n config.onHover?.(null);\n tooltip?.hide();\n ctx.announcer.clear();\n };\n\n const hitIndex = (event: MouseEvent): number => {\n const rect = svg.getBoundingClientRect();\n const dx = event.clientX - rect.left - layout.cx;\n const dy = event.clientY - rect.top - layout.cy;\n\n if (Math.hypot(dx, dy) > layout.radius + labelGap + LABEL_FONT_SIZE * 2) return -1;\n\n return nearestAxis(dx, dy, axes.length, startAngle);\n };\n\n return {\n onClick(event) {\n const index = hitIndex(event);\n\n if (index >= 0) config.onClick?.(eventFor(index, event));\n },\n onKeyDown(event) {\n const step = ARROW_STEPS[event.key];\n\n if (step !== undefined) {\n event.preventDefault();\n activate(activeIndex < 0 ? 0 : (activeIndex + step + axes.length) % axes.length, event);\n } else if ((event.key === 'Enter' || event.key === ' ') && activeIndex >= 0 && config.onClick) {\n event.preventDefault();\n config.onClick(eventFor(activeIndex, event));\n } else if (event.key === 'Escape') {\n deactivate();\n }\n },\n onMouseLeave: deactivate,\n onMouseMove(event) {\n const index = hitIndex(event);\n\n if (index < 0) {\n if (activeIndex >= 0) deactivate();\n } else if (index !== activeIndex) {\n activate(index, event);\n }\n },\n };\n },\n (next) => {\n series = next;\n warnOnInvalid(axes, series);\n },\n );\n\n return {\n get disposalSignal(): AbortSignal {\n return handle!.disposalSignal;\n },\n\n dispose() {\n if (activeRaf !== null) {\n cancelAnimationFrame(activeRaf);\n activeRaf = null;\n }\n\n handle!.dispose();\n },\n\n get disposed(): boolean {\n return handle!.disposed;\n },\n\n el: handle!.el,\n\n update(next) {\n handle!.update(next);\n },\n\n [Symbol.dispose]() {\n this.dispose();\n },\n };\n } catch (error) {\n handle?.dispose();\n throw error;\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require("../../svg/text.cjs"),t=require("../../scales/linear.cjs"),n=require("../../core/polar.cjs");var r=2*Math.PI;function toRadians(e){return e*Math.PI/180}function axisAngles(e,t=0){return Array.from({length:e},(n,i)=>t+i*r/e)}function resolveAxisDomains(e,n,r){let i=r;if(!i){let e=n.flatMap(e=>e.data.map(e=>e.value)).filter(Number.isFinite),r=Math.min(0,...e),a=e.length?Math.max(...e):1;i=t.linearScale({domain:[r,a>r?a:r+1],range:[0,1]}).domain}return e.map(e=>[e.min??i[0],e.max??i[1]])}function normalize(e,[t,n]){return n===t?0:Math.max(0,Math.min(1,(e-t)/(n-t)))}function radarPoints(e,t,r,i,a){return e.map((e,o)=>({x:n.polarX(t,i*e,a[o]),y:n.polarY(r,i*e,a[o])}))}function closedPath(e,t=`linear`){let n=e.length;if(n===0)return``;let[r]=e;if(t===`linear`||n<3)return`M${r.x},${r.y}${e.slice(1).map(e=>`L${e.x},${e.y}`).join(``)}Z`;let i=`M${r.x},${r.y}`;for(let t=0;t<n;t++){let r=e[(t-1+n)%n],a=e[t],o=e[(t+1)%n],s=e[(t+2)%n];i+=`C${a.x+(o.x-r.x)/6},${a.y+(o.y-r.y)/6} ${o.x-(s.x-a.x)/6},${o.y-(s.y-a.y)/6} ${o.x},${o.y}`}return`${i}Z`}function ringPath(e,t,n,r,i){return r<=0?``:e===`circle`?`M${t},${n-r}A${r},${r} 0 1 1 ${t},${n+r}A${r},${r} 0 1 1 ${t},${n-r}Z`:closedPath(radarPoints(i.map(()=>1),t,n,r,i))}function labelPlacement(e){let t=Math.sin(e),n=Math.cos(e);return{anchor:Math.abs(t)<.1?`middle`:t>0?`start`:`end`,baseline:n>.9?`auto`:n<-.9?`hanging`:`middle`}}function fitRadius(t,n,r,i,a,o){let s=0;r.forEach((t,n)=>{labelPlacement(i[n]).anchor!==`middle`&&(s=Math.max(s,e.estimateTextWidth(t,a)))});let c=a*1.3;return Math.max(8,Math.min(t/2-o-s,n/2-o-c))}function nearestAxis(e,t,n,i=0){if(n===0)return-1;let a=r/n,o=((Math.atan2(e,-t)-i)%r+r)%r;return Math.round(o/a)%n}exports.axisAngles=axisAngles,exports.closedPath=closedPath,exports.fitRadius=fitRadius,exports.labelPlacement=labelPlacement,exports.nearestAxis=nearestAxis,exports.normalize=normalize,exports.radarPoints=radarPoints,exports.resolveAxisDomains=resolveAxisDomains,exports.ringPath=ringPath,exports.toRadians=toRadians;
|
|
2
|
+
//# sourceMappingURL=radar-geometry.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"radar-geometry.cjs","names":[],"sources":["../../../src/charts/radar/radar-geometry.ts"],"sourcesContent":["import { polarX, polarY } from '../../core/polar';\nimport { linearScale } from '../../scales/linear';\nimport type { Point } from '../../svg/path';\nimport { estimateTextWidth } from '../../svg/text';\nimport type { RadarAxisConfig, RadarSeriesConfig } from '../../types';\n\nconst TWO_PI = 2 * Math.PI;\n\nexport type LabelAnchor = 'end' | 'middle' | 'start';\nexport type LabelBaseline = 'auto' | 'hanging' | 'middle';\n\nexport function toRadians(degrees: number): number {\n return (degrees * Math.PI) / 180;\n}\n\nexport function axisAngles(count: number, startAngle = 0): number[] {\n return Array.from({ length: count }, (_, i) => startAngle + (i * TWO_PI) / count);\n}\n\n/** Per-axis `[min, max]`: axis overrides win over `domain`, which wins over a nice range around the data. */\nexport function resolveAxisDomains(\n axes: readonly RadarAxisConfig[],\n series: readonly RadarSeriesConfig[],\n domain?: [number, number],\n): [number, number][] {\n let shared = domain;\n\n if (!shared) {\n const values = series.flatMap((s) => s.data.map((d) => d.value)).filter(Number.isFinite);\n const min = Math.min(0, ...values);\n const max = values.length ? Math.max(...values) : 1;\n\n shared = linearScale({ domain: [min, max > min ? max : min + 1], range: [0, 1] }).domain as [number, number];\n }\n\n return axes.map((axis) => [axis.min ?? shared[0], axis.max ?? shared[1]]);\n}\n\nexport function normalize(value: number, [min, max]: readonly [number, number]): number {\n if (max === min) return 0;\n\n return Math.max(0, Math.min(1, (value - min) / (max - min)));\n}\n\nexport function radarPoints(\n fractions: readonly number[],\n cx: number,\n cy: number,\n radius: number,\n angles: readonly number[],\n): Point[] {\n return fractions.map((f, i) => ({ x: polarX(cx, radius * f, angles[i]), y: polarY(cy, radius * f, angles[i]) }));\n}\n\n/** Closed outline through every point; `rounded` uses a closed Catmull–Rom spline. */\nexport function closedPath(points: readonly Point[], curve: 'linear' | 'rounded' = 'linear'): string {\n const n = points.length;\n\n if (n === 0) return '';\n\n const [first] = points;\n\n if (curve === 'linear' || n < 3) {\n return `M${first.x},${first.y}${points\n .slice(1)\n .map((p) => `L${p.x},${p.y}`)\n .join('')}Z`;\n }\n\n let d = `M${first.x},${first.y}`;\n\n for (let i = 0; i < n; i++) {\n const p0 = points[(i - 1 + n) % n];\n const p1 = points[i];\n const p2 = points[(i + 1) % n];\n const p3 = points[(i + 2) % n];\n\n d += `C${p1.x + (p2.x - p0.x) / 6},${p1.y + (p2.y - p0.y) / 6} ${p2.x - (p3.x - p1.x) / 6},${p2.y - (p3.y - p1.y) / 6} ${p2.x},${p2.y}`;\n }\n\n return `${d}Z`;\n}\n\nexport function ringPath(\n shape: 'circle' | 'polygon',\n cx: number,\n cy: number,\n r: number,\n angles: readonly number[],\n): string {\n if (r <= 0) return '';\n\n if (shape === 'circle') return `M${cx},${cy - r}A${r},${r} 0 1 1 ${cx},${cy + r}A${r},${r} 0 1 1 ${cx},${cy - r}Z`;\n\n return closedPath(\n radarPoints(\n angles.map(() => 1),\n cx,\n cy,\n r,\n angles,\n ),\n );\n}\n\nexport function labelPlacement(angle: number): { anchor: LabelAnchor; baseline: LabelBaseline } {\n const sin = Math.sin(angle);\n const cos = Math.cos(angle);\n\n return {\n anchor: Math.abs(sin) < 0.1 ? 'middle' : sin > 0 ? 'start' : 'end',\n baseline: cos > 0.9 ? 'auto' : cos < -0.9 ? 'hanging' : 'middle',\n };\n}\n\n/** Largest radius that leaves room for the axis labels around it. */\nexport function fitRadius(\n width: number,\n height: number,\n labels: readonly string[],\n angles: readonly number[],\n fontSize: number,\n gap: number,\n): number {\n let side = 0;\n\n labels.forEach((label, i) => {\n if (labelPlacement(angles[i]).anchor !== 'middle') side = Math.max(side, estimateTextWidth(label, fontSize));\n });\n\n const lineHeight = fontSize * 1.3;\n\n return Math.max(8, Math.min(width / 2 - gap - side, height / 2 - gap - lineHeight));\n}\n\n/** Index of the axis closest in angle to the offset `(dx, dy)` from the centre. */\nexport function nearestAxis(dx: number, dy: number, count: number, startAngle = 0): number {\n if (count === 0) return -1;\n\n const step = TWO_PI / count;\n const angle = (((Math.atan2(dx, -dy) - startAngle) % TWO_PI) + TWO_PI) % TWO_PI;\n\n return Math.round(angle / step) % count;\n}\n"],"mappings":"6GAMA,IAAM,EAAS,EAAI,KAAK,GAKxB,SAAgB,UAAU,EAAyB,CACjD,OAAQ,EAAU,KAAK,GAAM,GAC/B,CAEA,SAAgB,WAAW,EAAe,EAAa,EAAa,CAClE,OAAO,MAAM,KAAK,CAAE,OAAQ,CAAM,GAAI,EAAG,IAAM,EAAc,EAAI,EAAU,CAAK,CAClF,CAGA,SAAgB,mBACd,EACA,EACA,EACoB,CACpB,IAAI,EAAS,EAEb,GAAI,CAAC,EAAQ,CACX,IAAM,EAAS,EAAO,QAAS,GAAM,EAAE,KAAK,IAAK,GAAM,EAAE,KAAK,CAAC,CAAC,CAAC,OAAO,OAAO,QAAQ,EACjF,EAAM,KAAK,IAAI,EAAG,GAAG,CAAM,EAC3B,EAAM,EAAO,OAAS,KAAK,IAAI,GAAG,CAAM,EAAI,EAElD,EAAS,EAAA,YAAY,CAAE,OAAQ,CAAC,EAAK,EAAM,EAAM,EAAM,EAAM,CAAC,EAAG,MAAO,CAAC,EAAG,CAAC,CAAE,CAAC,CAAC,CAAC,MACpF,CAEA,OAAO,EAAK,IAAK,GAAS,CAAC,EAAK,KAAO,EAAO,GAAI,EAAK,KAAO,EAAO,EAAE,CAAC,CAC1E,CAEA,SAAgB,UAAU,EAAe,CAAC,EAAK,GAAyC,CAGtF,OAFI,IAAQ,EAAY,EAEjB,KAAK,IAAI,EAAG,KAAK,IAAI,GAAI,EAAQ,IAAQ,EAAM,EAAI,CAAC,CAC7D,CAEA,SAAgB,YACd,EACA,EACA,EACA,EACA,EACS,CACT,OAAO,EAAU,KAAK,EAAG,KAAO,CAAE,EAAG,EAAA,OAAO,EAAI,EAAS,EAAG,EAAO,EAAE,EAAG,EAAG,EAAA,OAAO,EAAI,EAAS,EAAG,EAAO,EAAE,CAAE,EAAE,CACjH,CAGA,SAAgB,WAAW,EAA0B,EAA8B,SAAkB,CACnG,IAAM,EAAI,EAAO,OAEjB,GAAI,IAAM,EAAG,MAAO,GAEpB,GAAM,CAAC,GAAS,EAEhB,GAAI,IAAU,UAAY,EAAI,EAC5B,MAAO,IAAI,EAAM,EAAE,GAAG,EAAM,IAAI,EAC7B,MAAM,CAAC,CAAC,CACR,IAAK,GAAM,IAAI,EAAE,EAAE,GAAG,EAAE,GAAG,CAAC,CAC5B,KAAK,EAAE,EAAE,GAGd,IAAI,EAAI,IAAI,EAAM,EAAE,GAAG,EAAM,IAE7B,IAAK,IAAI,EAAI,EAAG,EAAI,EAAG,IAAK,CAC1B,IAAM,EAAK,GAAQ,EAAI,EAAI,GAAK,GAC1B,EAAK,EAAO,GACZ,EAAK,GAAQ,EAAI,GAAK,GACtB,EAAK,GAAQ,EAAI,GAAK,GAE5B,GAAK,IAAI,EAAG,GAAK,EAAG,EAAI,EAAG,GAAK,EAAE,GAAG,EAAG,GAAK,EAAG,EAAI,EAAG,GAAK,EAAE,GAAG,EAAG,GAAK,EAAG,EAAI,EAAG,GAAK,EAAE,GAAG,EAAG,GAAK,EAAG,EAAI,EAAG,GAAK,EAAE,GAAG,EAAG,EAAE,GAAG,EAAG,GACtI,CAEA,MAAO,GAAG,EAAE,EACd,CAEA,SAAgB,SACd,EACA,EACA,EACA,EACA,EACQ,CAKR,OAJI,GAAK,EAAU,GAEf,IAAU,SAAiB,IAAI,EAAG,GAAG,EAAK,EAAE,GAAG,EAAE,GAAG,EAAE,SAAS,EAAG,GAAG,EAAK,EAAE,GAAG,EAAE,GAAG,EAAE,SAAS,EAAG,GAAG,EAAK,EAAE,GAEzG,WACL,YACE,EAAO,QAAU,CAAC,EAClB,EACA,EACA,EACA,CACF,CACF,CACF,CAEA,SAAgB,eAAe,EAAiE,CAC9F,IAAM,EAAM,KAAK,IAAI,CAAK,EACpB,EAAM,KAAK,IAAI,CAAK,EAE1B,MAAO,CACL,OAAQ,KAAK,IAAI,CAAG,EAAI,GAAM,SAAW,EAAM,EAAI,QAAU,MAC7D,SAAU,EAAM,GAAM,OAAS,EAAM,IAAO,UAAY,QAC1D,CACF,CAGA,SAAgB,UACd,EACA,EACA,EACA,EACA,EACA,EACQ,CACR,IAAI,EAAO,EAEX,EAAO,SAAS,EAAO,IAAM,CACvB,eAAe,EAAO,EAAE,CAAC,CAAC,SAAW,WAAU,EAAO,KAAK,IAAI,EAAM,EAAA,kBAAkB,EAAO,CAAQ,CAAC,EAC7G,CAAC,EAED,IAAM,EAAa,EAAW,IAE9B,OAAO,KAAK,IAAI,EAAG,KAAK,IAAI,EAAQ,EAAI,EAAM,EAAM,EAAS,EAAI,EAAM,CAAU,CAAC,CACpF,CAGA,SAAgB,YAAY,EAAY,EAAY,EAAe,EAAa,EAAW,CACzF,GAAI,IAAU,EAAG,MAAO,GAExB,IAAM,EAAO,EAAS,EAChB,IAAW,KAAK,MAAM,EAAI,CAAC,CAAE,EAAI,GAAc,EAAU,GAAU,EAEzE,OAAO,KAAK,MAAM,EAAQ,CAAI,EAAI,CACpC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Point } from '../../svg/path';
|
|
2
|
+
import type { RadarAxisConfig, RadarSeriesConfig } from '../../types';
|
|
3
|
+
export type LabelAnchor = 'end' | 'middle' | 'start';
|
|
4
|
+
export type LabelBaseline = 'auto' | 'hanging' | 'middle';
|
|
5
|
+
export declare function toRadians(degrees: number): number;
|
|
6
|
+
export declare function axisAngles(count: number, startAngle?: number): number[];
|
|
7
|
+
/** Per-axis `[min, max]`: axis overrides win over `domain`, which wins over a nice range around the data. */
|
|
8
|
+
export declare function resolveAxisDomains(axes: readonly RadarAxisConfig[], series: readonly RadarSeriesConfig[], domain?: [number, number]): [number, number][];
|
|
9
|
+
export declare function normalize(value: number, [min, max]: readonly [number, number]): number;
|
|
10
|
+
export declare function radarPoints(fractions: readonly number[], cx: number, cy: number, radius: number, angles: readonly number[]): Point[];
|
|
11
|
+
/** Closed outline through every point; `rounded` uses a closed Catmull–Rom spline. */
|
|
12
|
+
export declare function closedPath(points: readonly Point[], curve?: 'linear' | 'rounded'): string;
|
|
13
|
+
export declare function ringPath(shape: 'circle' | 'polygon', cx: number, cy: number, r: number, angles: readonly number[]): string;
|
|
14
|
+
export declare function labelPlacement(angle: number): {
|
|
15
|
+
anchor: LabelAnchor;
|
|
16
|
+
baseline: LabelBaseline;
|
|
17
|
+
};
|
|
18
|
+
/** Largest radius that leaves room for the axis labels around it. */
|
|
19
|
+
export declare function fitRadius(width: number, height: number, labels: readonly string[], angles: readonly number[], fontSize: number, gap: number): number;
|
|
20
|
+
/** Index of the axis closest in angle to the offset `(dx, dy)` from the centre. */
|
|
21
|
+
export declare function nearestAxis(dx: number, dy: number, count: number, startAngle?: number): number;
|
|
22
|
+
//# sourceMappingURL=radar-geometry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"radar-geometry.d.ts","sourceRoot":"","sources":["../../../src/charts/radar/radar-geometry.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAE5C,OAAO,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAItE,MAAM,MAAM,WAAW,GAAG,KAAK,GAAG,QAAQ,GAAG,OAAO,CAAC;AACrD,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,SAAS,GAAG,QAAQ,CAAC;AAE1D,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,SAAI,GAAG,MAAM,EAAE,CAElE;AAED,6GAA6G;AAC7G,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,SAAS,eAAe,EAAE,EAChC,MAAM,EAAE,SAAS,iBAAiB,EAAE,EACpC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,GACxB,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAYpB;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAItF;AAED,wBAAgB,WAAW,CACzB,SAAS,EAAE,SAAS,MAAM,EAAE,EAC5B,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,SAAS,MAAM,EAAE,GACxB,KAAK,EAAE,CAET;AAED,sFAAsF;AACtF,wBAAgB,UAAU,CAAC,MAAM,EAAE,SAAS,KAAK,EAAE,EAAE,KAAK,GAAE,QAAQ,GAAG,SAAoB,GAAG,MAAM,CA0BnG;AAED,wBAAgB,QAAQ,CACtB,KAAK,EAAE,QAAQ,GAAG,SAAS,EAC3B,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,CAAC,EAAE,MAAM,EACT,MAAM,EAAE,SAAS,MAAM,EAAE,GACxB,MAAM,CAcR;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,QAAQ,EAAE,aAAa,CAAA;CAAE,CAQ9F;AAED,qEAAqE;AACrE,wBAAgB,SAAS,CACvB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,SAAS,MAAM,EAAE,EACzB,MAAM,EAAE,SAAS,MAAM,EAAE,EACzB,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,GACV,MAAM,CAUR;AAED,mFAAmF;AACnF,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,SAAI,GAAG,MAAM,CAOzF"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{estimateTextWidth as e}from"../../svg/text.js";import{linearScale as t}from"../../scales/linear.js";import{polarX as n,polarY as r}from"../../core/polar.js";var i=2*Math.PI;function toRadians(e){return e*Math.PI/180}function axisAngles(e,t=0){return Array.from({length:e},(n,r)=>t+r*i/e)}function resolveAxisDomains(e,n,r){let i=r;if(!i){let e=n.flatMap(e=>e.data.map(e=>e.value)).filter(Number.isFinite),r=Math.min(0,...e),a=e.length?Math.max(...e):1;i=t({domain:[r,a>r?a:r+1],range:[0,1]}).domain}return e.map(e=>[e.min??i[0],e.max??i[1]])}function normalize(e,[t,n]){return n===t?0:Math.max(0,Math.min(1,(e-t)/(n-t)))}function radarPoints(e,t,i,a,o){return e.map((e,s)=>({x:n(t,a*e,o[s]),y:r(i,a*e,o[s])}))}function closedPath(e,t=`linear`){let n=e.length;if(n===0)return``;let[r]=e;if(t===`linear`||n<3)return`M${r.x},${r.y}${e.slice(1).map(e=>`L${e.x},${e.y}`).join(``)}Z`;let i=`M${r.x},${r.y}`;for(let t=0;t<n;t++){let r=e[(t-1+n)%n],a=e[t],o=e[(t+1)%n],s=e[(t+2)%n];i+=`C${a.x+(o.x-r.x)/6},${a.y+(o.y-r.y)/6} ${o.x-(s.x-a.x)/6},${o.y-(s.y-a.y)/6} ${o.x},${o.y}`}return`${i}Z`}function ringPath(e,t,n,r,i){return r<=0?``:e===`circle`?`M${t},${n-r}A${r},${r} 0 1 1 ${t},${n+r}A${r},${r} 0 1 1 ${t},${n-r}Z`:closedPath(radarPoints(i.map(()=>1),t,n,r,i))}function labelPlacement(e){let t=Math.sin(e),n=Math.cos(e);return{anchor:Math.abs(t)<.1?`middle`:t>0?`start`:`end`,baseline:n>.9?`auto`:n<-.9?`hanging`:`middle`}}function fitRadius(t,n,r,i,a,o){let s=0;r.forEach((t,n)=>{labelPlacement(i[n]).anchor!==`middle`&&(s=Math.max(s,e(t,a)))});let c=a*1.3;return Math.max(8,Math.min(t/2-o-s,n/2-o-c))}function nearestAxis(e,t,n,r=0){if(n===0)return-1;let a=i/n,o=((Math.atan2(e,-t)-r)%i+i)%i;return Math.round(o/a)%n}export{axisAngles,closedPath,fitRadius,labelPlacement,nearestAxis,normalize,radarPoints,resolveAxisDomains,ringPath,toRadians};
|
|
2
|
+
//# sourceMappingURL=radar-geometry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"radar-geometry.js","names":[],"sources":["../../../src/charts/radar/radar-geometry.ts"],"sourcesContent":["import { polarX, polarY } from '../../core/polar';\nimport { linearScale } from '../../scales/linear';\nimport type { Point } from '../../svg/path';\nimport { estimateTextWidth } from '../../svg/text';\nimport type { RadarAxisConfig, RadarSeriesConfig } from '../../types';\n\nconst TWO_PI = 2 * Math.PI;\n\nexport type LabelAnchor = 'end' | 'middle' | 'start';\nexport type LabelBaseline = 'auto' | 'hanging' | 'middle';\n\nexport function toRadians(degrees: number): number {\n return (degrees * Math.PI) / 180;\n}\n\nexport function axisAngles(count: number, startAngle = 0): number[] {\n return Array.from({ length: count }, (_, i) => startAngle + (i * TWO_PI) / count);\n}\n\n/** Per-axis `[min, max]`: axis overrides win over `domain`, which wins over a nice range around the data. */\nexport function resolveAxisDomains(\n axes: readonly RadarAxisConfig[],\n series: readonly RadarSeriesConfig[],\n domain?: [number, number],\n): [number, number][] {\n let shared = domain;\n\n if (!shared) {\n const values = series.flatMap((s) => s.data.map((d) => d.value)).filter(Number.isFinite);\n const min = Math.min(0, ...values);\n const max = values.length ? Math.max(...values) : 1;\n\n shared = linearScale({ domain: [min, max > min ? max : min + 1], range: [0, 1] }).domain as [number, number];\n }\n\n return axes.map((axis) => [axis.min ?? shared[0], axis.max ?? shared[1]]);\n}\n\nexport function normalize(value: number, [min, max]: readonly [number, number]): number {\n if (max === min) return 0;\n\n return Math.max(0, Math.min(1, (value - min) / (max - min)));\n}\n\nexport function radarPoints(\n fractions: readonly number[],\n cx: number,\n cy: number,\n radius: number,\n angles: readonly number[],\n): Point[] {\n return fractions.map((f, i) => ({ x: polarX(cx, radius * f, angles[i]), y: polarY(cy, radius * f, angles[i]) }));\n}\n\n/** Closed outline through every point; `rounded` uses a closed Catmull–Rom spline. */\nexport function closedPath(points: readonly Point[], curve: 'linear' | 'rounded' = 'linear'): string {\n const n = points.length;\n\n if (n === 0) return '';\n\n const [first] = points;\n\n if (curve === 'linear' || n < 3) {\n return `M${first.x},${first.y}${points\n .slice(1)\n .map((p) => `L${p.x},${p.y}`)\n .join('')}Z`;\n }\n\n let d = `M${first.x},${first.y}`;\n\n for (let i = 0; i < n; i++) {\n const p0 = points[(i - 1 + n) % n];\n const p1 = points[i];\n const p2 = points[(i + 1) % n];\n const p3 = points[(i + 2) % n];\n\n d += `C${p1.x + (p2.x - p0.x) / 6},${p1.y + (p2.y - p0.y) / 6} ${p2.x - (p3.x - p1.x) / 6},${p2.y - (p3.y - p1.y) / 6} ${p2.x},${p2.y}`;\n }\n\n return `${d}Z`;\n}\n\nexport function ringPath(\n shape: 'circle' | 'polygon',\n cx: number,\n cy: number,\n r: number,\n angles: readonly number[],\n): string {\n if (r <= 0) return '';\n\n if (shape === 'circle') return `M${cx},${cy - r}A${r},${r} 0 1 1 ${cx},${cy + r}A${r},${r} 0 1 1 ${cx},${cy - r}Z`;\n\n return closedPath(\n radarPoints(\n angles.map(() => 1),\n cx,\n cy,\n r,\n angles,\n ),\n );\n}\n\nexport function labelPlacement(angle: number): { anchor: LabelAnchor; baseline: LabelBaseline } {\n const sin = Math.sin(angle);\n const cos = Math.cos(angle);\n\n return {\n anchor: Math.abs(sin) < 0.1 ? 'middle' : sin > 0 ? 'start' : 'end',\n baseline: cos > 0.9 ? 'auto' : cos < -0.9 ? 'hanging' : 'middle',\n };\n}\n\n/** Largest radius that leaves room for the axis labels around it. */\nexport function fitRadius(\n width: number,\n height: number,\n labels: readonly string[],\n angles: readonly number[],\n fontSize: number,\n gap: number,\n): number {\n let side = 0;\n\n labels.forEach((label, i) => {\n if (labelPlacement(angles[i]).anchor !== 'middle') side = Math.max(side, estimateTextWidth(label, fontSize));\n });\n\n const lineHeight = fontSize * 1.3;\n\n return Math.max(8, Math.min(width / 2 - gap - side, height / 2 - gap - lineHeight));\n}\n\n/** Index of the axis closest in angle to the offset `(dx, dy)` from the centre. */\nexport function nearestAxis(dx: number, dy: number, count: number, startAngle = 0): number {\n if (count === 0) return -1;\n\n const step = TWO_PI / count;\n const angle = (((Math.atan2(dx, -dy) - startAngle) % TWO_PI) + TWO_PI) % TWO_PI;\n\n return Math.round(angle / step) % count;\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require("../../svg/element.cjs"),t=require("../../errors.cjs"),n=require("../../core/chart-base.cjs"),r=require("../../animation/easing.cjs"),i=require("../../animation/motion.cjs"),a=require("../../animation/tween.cjs"),o=require("../../svg/path.cjs");function
|
|
1
|
+
require("../../_dev.cjs");const e=require("../../svg/element.cjs"),t=require("../../errors.cjs"),n=require("../../core/chart-base.cjs"),r=require("../../animation/easing.cjs"),i=require("../../animation/motion.cjs"),a=require("../../animation/tween.cjs"),o=require("../../core/ids.cjs"),s=require("../../svg/path.cjs");var c=5;function buildTopPoints(e,t,n){if(e.length===0)return[];let r=t/Math.max(1,e.length-1),i=Math.min(...e),a=Math.max(...e)-i||1;return e.map((e,t)=>({x:t*r,y:n-(e-i)/a*n}))}function buildAreaPath(e,t,n,r=`linear`){if(e.length===0)return``;let i=buildTopPoints(e,t,n),a=i.map(e=>({x:e.x,y:n}));return s.areaPath(i,a,r??`linear`)}function buildPath(e,t,n,r){if(e.length===0)return``;let i=buildTopPoints(e,t,n);return r===`monotone`?s.monotonePath(i):r===`step`?s.stepPath(i):s.linePath(i)}function renderSparkBars(t,n,o,s,c,l,u){let d=n.length,f=Math.max(1,o/d-1),p=o/d,m=Math.min(0,...n),h=Math.max(...n)-m||1,g=i.resolveMotion(l,0),_=g.duration,v=r.resolveEasing(g.easing);for(;t.children.length>d;){let e=t.lastElementChild;e&&t.removeChild(e)}for(let r=0;r<d;r++){let i=Math.max(1,(n[r]-m)/h*s),o=s-i,l=t.children[r];if(l||(l=e.createSvgElement(`rect`,{class:`prism-spark-bar`}),t.appendChild(l)),e.setAttributes(l,{fill:c,width:f,x:r*p}),_>0&&!l.hasAttribute(`data-init`)){l.setAttribute(`data-init`,`1`),e.setAttributes(l,{height:0,y:s});let t=null,n={h:0,y:s},r={h:i,y:o},frame=i=>{if(u?.aborted)return;t===null&&(t=i);let o=v(Math.min(1,(i-t)/_));e.setAttributes(l,{height:a.tweenNumber(n.h,r.h,o),y:a.tweenNumber(n.y,r.y,o)}),o<1&&requestAnimationFrame(frame)};requestAnimationFrame(frame)}else l.setAttribute(`data-init`,`1`),e.setAttributes(l,{height:i,y:o})}}function isStackData(e){return e.length>0&&e[0]!==null&&typeof e[0]==`object`}function buildRoundedStackRect(e,t,n,r,i,a,o){let s=Math.min(i,n/2,r/2),c=a?s:0,l=a?s:0,u=o?s:0,d=o?s:0;return[`M${e+c},${t}`,`H${e+n-u}`,u?`Q${e+n},${t} ${e+n},${t+u}`:``,`V${t+r-d}`,d?`Q${e+n},${t+r} ${e+n-d},${t+r}`:``,`H${e+l}`,l?`Q${e},${t+r} ${e},${t+r-l}`:``,`V${t+c}`,c?`Q${e},${t} ${e+c},${t}`:``,`Z`].filter(Boolean).join(``)}function defaultStackColor(e){return`var(--prism-color-${e%8+1})`}function createSparkline(r,i){let a=i.variant??`line`,s=i.color??`var(--prism-color-1)`,l=i.curve??`linear`,u=i.strokeWidth??1.5,d=i.fillOpacity,f=i.showEndPoint??!0,p=o.uniqueId(`prism-spark-fill`),m=i.data,h=n.createChartBase(r,{a11y:i.a11y,margin:{bottom:0,left:0,right:0,top:0}},renderAll),{svg:g}=h;g.classList.add(`prism-sparkline`);let _=e.createSvgElement(`g`,{class:`prism-spark-inner`});g.appendChild(_);let cleanupInteraction;function plotArea(){let{height:e,width:t}=h.dimensions,n=a===`line`||a===`area`?c:0;return{h:Math.max(1,e-n*2),inset:n,w:Math.max(1,t-n*2)}}function renderAll(){let{height:t,width:n}=h.dimensions,r=plotArea();for(;_.firstChild;)_.removeChild(_.firstChild);if(_.setAttribute(`transform`,`translate(${r.inset},${r.inset})`),m.length!==0){if(!isStackData(m)&&m.some(e=>!Number.isFinite(e)),a===`stack`&&isStackData(m)){let r=e.createSvgElement(`g`,{class:`prism-spark-stack`});_.appendChild(r);let a=i.cornerRadius??4,o=m,s=o.reduce((e,t)=>e+Math.max(0,t.value),0);if(s>0){let c=(i.padPixels??0)/2,l=0;o.forEach((i,u)=>{let d=Math.round(l);l+=Math.max(0,i.value)/s*n;let f=u===o.length-1?n:Math.round(l),p=u===0,m=u===o.length-1,h=buildRoundedStackRect(d+(p?0:c),0,Math.max(0,f-d-(p?0:c)-(m?0:c)),t,a,p,m),g=e.createSvgElement(`path`,{class:`prism-spark-stack-segment`});e.setAttributes(g,{d:h,fill:i.color??defaultStackColor(u)}),r.appendChild(g)})}}else if(a===`bar`){let r=e.createSvgElement(`g`,{class:`prism-spark-bars`});_.appendChild(r),renderSparkBars(r,m,n,t,s,i.transition,v.signal)}else{if(a===`area`){let t=e.createSvgElement(`defs`),n=e.createSvgElement(`linearGradient`,{id:p,x1:0,x2:0,y1:0,y2:1});for(let[t,r]of[[0,`prism-spark-stop-top`],[1,`prism-spark-stop-bottom`]]){let i=e.createSvgElement(`stop`,{class:r,offset:t,"stop-color":s});i.style.stopColor=s,n.appendChild(i)}t.appendChild(n),_.appendChild(t);let i=e.createSvgElement(`path`,{class:`prism-spark-fill`}),a=buildAreaPath(m,r.w,r.h,l);e.setAttributes(i,{d:a,fill:`url(#${p})`,stroke:`none`}),i.style.fillOpacity=d===void 0?``:String(d),_.appendChild(i)}let t=e.createSvgElement(`path`,{class:`prism-spark-line`}),n=buildPath(m,r.w,r.h,l);e.setAttributes(t,{d:n,fill:`none`,stroke:s,"stroke-width":u}),_.appendChild(t);let i=buildTopPoints(m,r.w,r.h).at(-1);f&&i&&_.appendChild(e.createSvgElement(`circle`,{class:`prism-spark-end`,cx:i.x,cy:i.y,fill:s,r:2.5}))}isStackData(m)||attachInteraction(m)}}function attachInteraction(t){if(cleanupInteraction?.(),cleanupInteraction=void 0,!i.onHover&&!i.onClick||t.length<=1)return;let{h:n,inset:r,w:o}=plotArea();g.style.cursor=`crosshair`;let c=o/(t.length-1),l=a===`bar`?[]:buildTopPoints(t,o,n),u=e.createSvgElement(`circle`,{class:`prism-spark-marker`,fill:s,r:3.5}),indexAt=e=>Math.max(0,Math.min(t.length-1,Math.round((e-g.getBoundingClientRect().left-r)/c)));u.style.display=`none`,_.appendChild(u);let handleMove=n=>{let r=indexAt(n.clientX),a=l[r];a&&(e.setAttributes(u,{cx:a.x,cy:a.y}),u.style.display=``),i.onHover?.(r,t[r])},handleLeave=()=>{u.style.display=`none`,i.onHover?.(null,null)},handleClick=e=>{if(!i.onClick)return;let n=indexAt(e.clientX);i.onClick(n,t[n])};g.addEventListener(`mousemove`,handleMove),g.addEventListener(`mouseleave`,handleLeave),g.addEventListener(`click`,handleClick),cleanupInteraction=()=>{g.removeEventListener(`mousemove`,handleMove),g.removeEventListener(`mouseleave`,handleLeave),g.removeEventListener(`click`,handleClick)}}let v=new AbortController,y=!1;try{return renderAll(),{get disposalSignal(){return v.signal},dispose(){y||(y=!0,v.abort(),cleanupInteraction?.(),h.dispose())},get disposed(){return y},el:g,update(e){if(y)throw new t.PrismRenderError(`Cannot update a disposed chart.`);m=e,renderAll()},[Symbol.dispose](){this.dispose()}}}catch(e){throw v.abort(),cleanupInteraction?.(),h.dispose(),e instanceof t.PrismRenderError?e:new t.PrismRenderError(`Failed to render chart.`,{cause:e})}}exports.createSparkline=createSparkline;
|
|
2
2
|
//# sourceMappingURL=sparkline.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sparkline.cjs","names":[],"sources":["../../../src/charts/sparkline/sparkline.ts"],"sourcesContent":["import { resolveEasing } from '../../animation/easing';\nimport { resolveMotion } from '../../animation/motion';\nimport { tweenNumber } from '../../animation/tween';\nimport { createChartBase } from '../../core/chart-base';\nimport { PrismRenderError } from '../../errors';\nimport { createSvgElement, setAttributes } from '../../svg/element';\nimport type { Point } from '../../svg/path';\nimport { areaPath, linePath, monotonePath, stepPath } from '../../svg/path';\nimport type { ChartHandle, SparklineConfig, StackSegment } from '../../types';\n\nfunction buildTopPoints(data: number[], width: number, height: number): Point[] {\n if (data.length === 0) return [];\n\n const xStep = width / Math.max(1, data.length - 1);\n const min = Math.min(...data);\n const max = Math.max(...data);\n const yRange = max - min || 1;\n\n return data.map((v, i) => ({\n x: i * xStep,\n y: height - ((v - min) / yRange) * height,\n }));\n}\n\nfunction buildAreaPath(\n data: number[],\n width: number,\n height: number,\n curve: SparklineConfig['curve'] = 'linear',\n): string {\n if (data.length === 0) return '';\n\n const top = buildTopPoints(data, width, height);\n const bottom = top.map((p) => ({ x: p.x, y: height }));\n\n return areaPath(top, bottom, curve ?? 'linear');\n}\n\nfunction buildPath(data: number[], width: number, height: number, curve: SparklineConfig['curve']): string {\n if (data.length === 0) return '';\n\n const points = buildTopPoints(data, width, height);\n\n return curve === 'monotone' ? monotonePath(points) : curve === 'step' ? stepPath(points) : linePath(points);\n}\n\nfunction renderSparkBars(\n parent: SVGGElement,\n data: number[],\n width: number,\n height: number,\n color: string,\n transition?: SparklineConfig['transition'],\n disposalSignal?: AbortSignal,\n): void {\n const count = data.length;\n const barW = Math.max(1, width / count - 1);\n const gap = width / count;\n const min = Math.min(0, ...data);\n const max = Math.max(...data);\n const yRange = max - min || 1;\n const motion = resolveMotion(transition, 0);\n const dur = motion.duration;\n const easing = resolveEasing(motion.easing);\n\n while (parent.children.length > count) {\n const last = parent.lastElementChild;\n\n if (last) parent.removeChild(last);\n }\n\n for (let i = 0; i < count; i++) {\n const finalH = Math.max(1, ((data[i] - min) / yRange) * height);\n const finalY = height - finalH;\n\n let rect = parent.children[i] as SVGRectElement | undefined;\n\n if (!rect) {\n rect = createSvgElement('rect', { class: 'prism-spark-bar' });\n parent.appendChild(rect);\n }\n\n setAttributes(rect, { fill: color, width: barW, x: i * gap });\n\n if (dur > 0 && !rect.hasAttribute('data-init')) {\n rect.setAttribute('data-init', '1');\n setAttributes(rect, { height: 0, y: height });\n\n let start: number | null = null;\n const from = { h: 0, y: height };\n const to = { h: finalH, y: finalY };\n\n const frame = (ts: number) => {\n if (disposalSignal?.aborted) return;\n\n if (start === null) start = ts;\n\n const t = easing(Math.min(1, (ts - start) / dur));\n\n setAttributes(rect!, {\n height: tweenNumber(from.h, to.h, t),\n y: tweenNumber(from.y, to.y, t),\n });\n\n if (t < 1) requestAnimationFrame(frame);\n };\n\n requestAnimationFrame(frame);\n } else {\n rect.setAttribute('data-init', '1');\n setAttributes(rect, { height: finalH, y: finalY });\n }\n }\n}\n\nfunction isStackData(data: number[] | StackSegment[]): data is StackSegment[] {\n return data.length > 0 && data[0] !== null && typeof data[0] === 'object';\n}\n\nfunction buildRoundedStackRect(\n x: number,\n y: number,\n w: number,\n h: number,\n r: number,\n roundLeft: boolean,\n roundRight: boolean,\n): string {\n const maxR = Math.min(r, w / 2, h / 2);\n const tl = roundLeft ? maxR : 0;\n const bl = roundLeft ? maxR : 0;\n const tr = roundRight ? maxR : 0;\n const br = roundRight ? maxR : 0;\n\n return [\n `M${x + tl},${y}`,\n `H${x + w - tr}`,\n tr ? `Q${x + w},${y} ${x + w},${y + tr}` : '',\n `V${y + h - br}`,\n br ? `Q${x + w},${y + h} ${x + w - br},${y + h}` : '',\n `H${x + bl}`,\n bl ? `Q${x},${y + h} ${x},${y + h - bl}` : '',\n `V${y + tl}`,\n tl ? `Q${x},${y} ${x + tl},${y}` : '',\n 'Z',\n ]\n .filter(Boolean)\n .join('');\n}\n\nfunction defaultStackColor(i: number): string {\n return `var(--prism-color-${(i % 8) + 1})`;\n}\n\nexport function createSparkline(\n container: HTMLElement,\n config: SparklineConfig,\n): ChartHandle<number[] | StackSegment[]> {\n const variant = config.variant ?? 'line';\n const color = config.color ?? 'var(--prism-color-1)';\n const curve = config.curve ?? 'linear';\n const strokeWidth = config.strokeWidth ?? 1.5;\n const fillOpacity = config.fillOpacity ?? 0.2;\n let data = config.data;\n\n const base = createChartBase(\n container,\n {\n a11y: config.a11y,\n margin: { bottom: 0, left: 0, right: 0, top: 0 },\n },\n renderAll,\n );\n\n const { svg } = base;\n\n svg.classList.add('prism-sparkline');\n\n const innerGroup = createSvgElement('g', { class: 'prism-spark-inner' });\n\n svg.appendChild(innerGroup);\n\n let cleanupInteraction: (() => void) | undefined;\n\n function renderAll(): void {\n const { height: h, width: w } = base.dimensions;\n\n while (innerGroup.firstChild) innerGroup.removeChild(innerGroup.firstChild);\n\n if (data.length === 0) return;\n\n if (variant === 'stack' && isStackData(data)) {\n const stackGroup = createSvgElement('g', { class: 'prism-spark-stack' });\n\n innerGroup.appendChild(stackGroup);\n\n const cornerRadius = config.cornerRadius ?? 4;\n const segs = data as StackSegment[];\n const total = segs.reduce((s, d) => s + Math.max(0, d.value), 0);\n\n if (total > 0) {\n const half = (config.padPixels ?? 0) / 2;\n let xAcc = 0;\n\n segs.forEach((seg, i) => {\n const xStart = Math.round(xAcc);\n\n xAcc += (Math.max(0, seg.value) / total) * w;\n\n const xEnd = i === segs.length - 1 ? w : Math.round(xAcc);\n const isFirst = i === 0;\n const isLast = i === segs.length - 1;\n const drawX = xStart + (isFirst ? 0 : half);\n const drawW = Math.max(0, xEnd - xStart - (isFirst ? 0 : half) - (isLast ? 0 : half));\n const d = buildRoundedStackRect(drawX, 0, drawW, h, cornerRadius, isFirst, isLast);\n const path = createSvgElement('path', { class: 'prism-spark-stack-segment' });\n\n setAttributes(path, { d, fill: seg.color ?? defaultStackColor(i) });\n stackGroup.appendChild(path);\n });\n }\n } else if (variant === 'bar') {\n const barsGroup = createSvgElement('g', { class: 'prism-spark-bars' });\n\n innerGroup.appendChild(barsGroup);\n renderSparkBars(barsGroup, data as number[], w, h, color, config.transition, ac.signal);\n } else {\n if (variant === 'area') {\n const fill = createSvgElement('path', { class: 'prism-spark-fill' });\n const fillD = buildAreaPath(data as number[], w, h, curve);\n\n setAttributes(fill, { d: fillD, fill: color, 'fill-opacity': fillOpacity, stroke: 'none' });\n innerGroup.appendChild(fill);\n }\n\n const path = createSvgElement('path', { class: 'prism-spark-line' });\n const pathD = buildPath(data as number[], w, h, curve);\n\n setAttributes(path, { d: pathD, fill: 'none', stroke: color, 'stroke-width': strokeWidth });\n innerGroup.appendChild(path);\n }\n\n if (!isStackData(data)) attachInteraction(data as number[]);\n }\n\n function attachInteraction(data: number[]): void {\n cleanupInteraction?.();\n cleanupInteraction = undefined;\n\n if (!config.onHover && !config.onClick) return;\n\n if (data.length <= 1) return;\n\n const { width: w } = base.dimensions;\n\n svg.style.cursor = 'crosshair';\n\n const xStep = w / (data.length - 1);\n\n const handleMove = (e: MouseEvent) => {\n const rect = svg.getBoundingClientRect();\n const relX = e.clientX - rect.left;\n const idx = Math.max(0, Math.min(data.length - 1, Math.round(relX / xStep)));\n\n config.onHover?.(idx, data[idx]);\n };\n\n const handleLeave = () => config.onHover?.(null, null);\n\n const handleClick = (e: MouseEvent) => {\n if (!config.onClick) return;\n\n const rect = svg.getBoundingClientRect();\n const relX = e.clientX - rect.left;\n const idx = Math.max(0, Math.min(data.length - 1, Math.round(relX / xStep)));\n\n config.onClick(idx, data[idx]);\n };\n\n svg.addEventListener('mousemove', handleMove);\n svg.addEventListener('mouseleave', handleLeave);\n svg.addEventListener('click', handleClick);\n\n cleanupInteraction = () => {\n svg.removeEventListener('mousemove', handleMove);\n svg.removeEventListener('mouseleave', handleLeave);\n svg.removeEventListener('click', handleClick);\n };\n }\n\n const ac = new AbortController();\n let isDisposed = false;\n\n try {\n renderAll();\n\n return {\n get disposalSignal(): AbortSignal {\n return ac.signal;\n },\n\n dispose() {\n if (isDisposed) return;\n\n isDisposed = true;\n ac.abort();\n cleanupInteraction?.();\n base.dispose();\n },\n\n get disposed(): boolean {\n return isDisposed;\n },\n\n el: svg,\n\n update(next) {\n if (isDisposed) throw new PrismRenderError('Cannot update a disposed chart.');\n data = next;\n renderAll();\n },\n\n [Symbol.dispose]() {\n this.dispose();\n },\n };\n } catch (error) {\n ac.abort();\n cleanupInteraction?.();\n base.dispose();\n throw error instanceof PrismRenderError ? error : new PrismRenderError('Failed to render chart.', { cause: error });\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"sparkline.cjs","names":[],"sources":["../../../src/charts/sparkline/sparkline.ts"],"sourcesContent":["import { warn } from '../../_dev';\nimport { resolveEasing } from '../../animation/easing';\nimport { resolveMotion } from '../../animation/motion';\nimport { tweenNumber } from '../../animation/tween';\nimport { createChartBase } from '../../core/chart-base';\nimport { uniqueId } from '../../core/ids';\nimport { PrismRenderError } from '../../errors';\nimport { createSvgElement, setAttributes } from '../../svg/element';\nimport type { Point } from '../../svg/path';\nimport { areaPath, linePath, monotonePath, stepPath } from '../../svg/path';\nimport type { ChartHandle, SparklineConfig, StackSegment } from '../../types';\n\n/** Fits the 3.5px hover marker plus its ring inside the SVG. */\nconst PLOT_INSET = 5;\n\nfunction buildTopPoints(data: number[], width: number, height: number): Point[] {\n if (data.length === 0) return [];\n\n const xStep = width / Math.max(1, data.length - 1);\n const min = Math.min(...data);\n const max = Math.max(...data);\n const yRange = max - min || 1;\n\n return data.map((v, i) => ({\n x: i * xStep,\n y: height - ((v - min) / yRange) * height,\n }));\n}\n\nfunction buildAreaPath(\n data: number[],\n width: number,\n height: number,\n curve: SparklineConfig['curve'] = 'linear',\n): string {\n if (data.length === 0) return '';\n\n const top = buildTopPoints(data, width, height);\n const bottom = top.map((p) => ({ x: p.x, y: height }));\n\n return areaPath(top, bottom, curve ?? 'linear');\n}\n\nfunction buildPath(data: number[], width: number, height: number, curve: SparklineConfig['curve']): string {\n if (data.length === 0) return '';\n\n const points = buildTopPoints(data, width, height);\n\n return curve === 'monotone' ? monotonePath(points) : curve === 'step' ? stepPath(points) : linePath(points);\n}\n\nfunction renderSparkBars(\n parent: SVGGElement,\n data: number[],\n width: number,\n height: number,\n color: string,\n transition?: SparklineConfig['transition'],\n disposalSignal?: AbortSignal,\n): void {\n const count = data.length;\n const barW = Math.max(1, width / count - 1);\n const gap = width / count;\n const min = Math.min(0, ...data);\n const max = Math.max(...data);\n const yRange = max - min || 1;\n const motion = resolveMotion(transition, 0);\n const dur = motion.duration;\n const easing = resolveEasing(motion.easing);\n\n while (parent.children.length > count) {\n const last = parent.lastElementChild;\n\n if (last) parent.removeChild(last);\n }\n\n for (let i = 0; i < count; i++) {\n const finalH = Math.max(1, ((data[i] - min) / yRange) * height);\n const finalY = height - finalH;\n\n let rect = parent.children[i] as SVGRectElement | undefined;\n\n if (!rect) {\n rect = createSvgElement('rect', { class: 'prism-spark-bar' });\n parent.appendChild(rect);\n }\n\n setAttributes(rect, { fill: color, width: barW, x: i * gap });\n\n if (dur > 0 && !rect.hasAttribute('data-init')) {\n rect.setAttribute('data-init', '1');\n setAttributes(rect, { height: 0, y: height });\n\n let start: number | null = null;\n const from = { h: 0, y: height };\n const to = { h: finalH, y: finalY };\n\n const frame = (ts: number) => {\n if (disposalSignal?.aborted) return;\n\n if (start === null) start = ts;\n\n const t = easing(Math.min(1, (ts - start) / dur));\n\n setAttributes(rect!, {\n height: tweenNumber(from.h, to.h, t),\n y: tweenNumber(from.y, to.y, t),\n });\n\n if (t < 1) requestAnimationFrame(frame);\n };\n\n requestAnimationFrame(frame);\n } else {\n rect.setAttribute('data-init', '1');\n setAttributes(rect, { height: finalH, y: finalY });\n }\n }\n}\n\nfunction isStackData(data: number[] | StackSegment[]): data is StackSegment[] {\n return data.length > 0 && data[0] !== null && typeof data[0] === 'object';\n}\n\nfunction buildRoundedStackRect(\n x: number,\n y: number,\n w: number,\n h: number,\n r: number,\n roundLeft: boolean,\n roundRight: boolean,\n): string {\n const maxR = Math.min(r, w / 2, h / 2);\n const tl = roundLeft ? maxR : 0;\n const bl = roundLeft ? maxR : 0;\n const tr = roundRight ? maxR : 0;\n const br = roundRight ? maxR : 0;\n\n return [\n `M${x + tl},${y}`,\n `H${x + w - tr}`,\n tr ? `Q${x + w},${y} ${x + w},${y + tr}` : '',\n `V${y + h - br}`,\n br ? `Q${x + w},${y + h} ${x + w - br},${y + h}` : '',\n `H${x + bl}`,\n bl ? `Q${x},${y + h} ${x},${y + h - bl}` : '',\n `V${y + tl}`,\n tl ? `Q${x},${y} ${x + tl},${y}` : '',\n 'Z',\n ]\n .filter(Boolean)\n .join('');\n}\n\nfunction defaultStackColor(i: number): string {\n return `var(--prism-color-${(i % 8) + 1})`;\n}\n\nexport function createSparkline(\n container: HTMLElement,\n config: SparklineConfig,\n): ChartHandle<number[] | StackSegment[]> {\n const variant = config.variant ?? 'line';\n const color = config.color ?? 'var(--prism-color-1)';\n const curve = config.curve ?? 'linear';\n const strokeWidth = config.strokeWidth ?? 1.5;\n const fillOpacity = config.fillOpacity;\n const showEndPoint = config.showEndPoint ?? true;\n const gradientId = uniqueId('prism-spark-fill');\n let data = config.data;\n\n const base = createChartBase(\n container,\n {\n a11y: config.a11y,\n margin: { bottom: 0, left: 0, right: 0, top: 0 },\n },\n renderAll,\n );\n\n const { svg } = base;\n\n svg.classList.add('prism-sparkline');\n\n const innerGroup = createSvgElement('g', { class: 'prism-spark-inner' });\n\n svg.appendChild(innerGroup);\n\n let cleanupInteraction: (() => void) | undefined;\n\n /** Line and area plots are inset so dots on the first and last values are not clipped. */\n function plotArea(): { h: number; inset: number; w: number } {\n const { height, width } = base.dimensions;\n const inset = variant === 'line' || variant === 'area' ? PLOT_INSET : 0;\n\n return { h: Math.max(1, height - inset * 2), inset, w: Math.max(1, width - inset * 2) };\n }\n\n function renderAll(): void {\n const { height: h, width: w } = base.dimensions;\n const plot = plotArea();\n\n while (innerGroup.firstChild) innerGroup.removeChild(innerGroup.firstChild);\n\n innerGroup.setAttribute('transform', `translate(${plot.inset},${plot.inset})`);\n\n if (data.length === 0) return;\n\n if (!isStackData(data) && data.some((v) => !Number.isFinite(v))) {\n warn('createSparkline: data contains non-finite values; they are drawn as the minimum.');\n }\n\n if (variant === 'stack' && isStackData(data)) {\n const stackGroup = createSvgElement('g', { class: 'prism-spark-stack' });\n\n innerGroup.appendChild(stackGroup);\n\n const cornerRadius = config.cornerRadius ?? 4;\n const segs = data as StackSegment[];\n const total = segs.reduce((s, d) => s + Math.max(0, d.value), 0);\n\n if (total > 0) {\n const half = (config.padPixels ?? 0) / 2;\n let xAcc = 0;\n\n segs.forEach((seg, i) => {\n const xStart = Math.round(xAcc);\n\n xAcc += (Math.max(0, seg.value) / total) * w;\n\n const xEnd = i === segs.length - 1 ? w : Math.round(xAcc);\n const isFirst = i === 0;\n const isLast = i === segs.length - 1;\n const drawX = xStart + (isFirst ? 0 : half);\n const drawW = Math.max(0, xEnd - xStart - (isFirst ? 0 : half) - (isLast ? 0 : half));\n const d = buildRoundedStackRect(drawX, 0, drawW, h, cornerRadius, isFirst, isLast);\n const path = createSvgElement('path', { class: 'prism-spark-stack-segment' });\n\n setAttributes(path, { d, fill: seg.color ?? defaultStackColor(i) });\n stackGroup.appendChild(path);\n });\n }\n } else if (variant === 'bar') {\n const barsGroup = createSvgElement('g', { class: 'prism-spark-bars' });\n\n innerGroup.appendChild(barsGroup);\n renderSparkBars(barsGroup, data as number[], w, h, color, config.transition, ac.signal);\n } else {\n if (variant === 'area') {\n const defs = createSvgElement('defs');\n const gradient = createSvgElement('linearGradient', { id: gradientId, x1: 0, x2: 0, y1: 0, y2: 1 });\n\n for (const [offset, className] of [\n [0, 'prism-spark-stop-top'],\n [1, 'prism-spark-stop-bottom'],\n ] as const) {\n const stop = createSvgElement('stop', { class: className, offset, 'stop-color': color });\n\n stop.style.stopColor = color;\n gradient.appendChild(stop);\n }\n\n defs.appendChild(gradient);\n innerGroup.appendChild(defs);\n\n const fill = createSvgElement('path', { class: 'prism-spark-fill' });\n const fillD = buildAreaPath(data as number[], plot.w, plot.h, curve);\n\n setAttributes(fill, { d: fillD, fill: `url(#${gradientId})`, stroke: 'none' });\n fill.style.fillOpacity = fillOpacity === undefined ? '' : String(fillOpacity);\n innerGroup.appendChild(fill);\n }\n\n const path = createSvgElement('path', { class: 'prism-spark-line' });\n const pathD = buildPath(data as number[], plot.w, plot.h, curve);\n\n setAttributes(path, { d: pathD, fill: 'none', stroke: color, 'stroke-width': strokeWidth });\n innerGroup.appendChild(path);\n\n const end = buildTopPoints(data as number[], plot.w, plot.h).at(-1);\n\n if (showEndPoint && end) {\n innerGroup.appendChild(\n createSvgElement('circle', { class: 'prism-spark-end', cx: end.x, cy: end.y, fill: color, r: 2.5 }),\n );\n }\n }\n\n if (!isStackData(data)) attachInteraction(data as number[]);\n }\n\n function attachInteraction(data: number[]): void {\n cleanupInteraction?.();\n cleanupInteraction = undefined;\n\n if (!config.onHover && !config.onClick) return;\n\n if (data.length <= 1) return;\n\n const { h, inset, w } = plotArea();\n\n svg.style.cursor = 'crosshair';\n\n const xStep = w / (data.length - 1);\n const points = variant === 'bar' ? [] : buildTopPoints(data, w, h);\n const marker = createSvgElement('circle', { class: 'prism-spark-marker', fill: color, r: 3.5 });\n const indexAt = (clientX: number): number =>\n Math.max(0, Math.min(data.length - 1, Math.round((clientX - svg.getBoundingClientRect().left - inset) / xStep)));\n\n marker.style.display = 'none';\n innerGroup.appendChild(marker);\n\n const handleMove = (e: MouseEvent) => {\n const idx = indexAt(e.clientX);\n const point = points[idx];\n\n if (point) {\n setAttributes(marker, { cx: point.x, cy: point.y });\n marker.style.display = '';\n }\n\n config.onHover?.(idx, data[idx]);\n };\n\n const handleLeave = () => {\n marker.style.display = 'none';\n config.onHover?.(null, null);\n };\n\n const handleClick = (e: MouseEvent) => {\n if (!config.onClick) return;\n\n const idx = indexAt(e.clientX);\n\n config.onClick(idx, data[idx]);\n };\n\n svg.addEventListener('mousemove', handleMove);\n svg.addEventListener('mouseleave', handleLeave);\n svg.addEventListener('click', handleClick);\n\n cleanupInteraction = () => {\n svg.removeEventListener('mousemove', handleMove);\n svg.removeEventListener('mouseleave', handleLeave);\n svg.removeEventListener('click', handleClick);\n };\n }\n\n const ac = new AbortController();\n let isDisposed = false;\n\n try {\n renderAll();\n\n return {\n get disposalSignal(): AbortSignal {\n return ac.signal;\n },\n\n dispose() {\n if (isDisposed) return;\n\n isDisposed = true;\n ac.abort();\n cleanupInteraction?.();\n base.dispose();\n },\n\n get disposed(): boolean {\n return isDisposed;\n },\n\n el: svg,\n\n update(next) {\n if (isDisposed) throw new PrismRenderError('Cannot update a disposed chart.');\n data = next;\n renderAll();\n },\n\n [Symbol.dispose]() {\n this.dispose();\n },\n };\n } catch (error) {\n ac.abort();\n cleanupInteraction?.();\n base.dispose();\n throw error instanceof PrismRenderError ? error : new PrismRenderError('Failed to render chart.', { cause: error });\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sparkline.d.ts","sourceRoot":"","sources":["../../../src/charts/sparkline/sparkline.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"sparkline.d.ts","sourceRoot":"","sources":["../../../src/charts/sparkline/sparkline.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAqJ9E,wBAAgB,eAAe,CAC7B,SAAS,EAAE,WAAW,EACtB,MAAM,EAAE,eAAe,GACtB,WAAW,CAAC,MAAM,EAAE,GAAG,YAAY,EAAE,CAAC,CAqOxC"}
|
|
@@ -1,192 +1,2 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { PrismRenderError as n } from "../../errors.js";
|
|
3
|
-
import { createChartBase as r } from "../../core/chart-base.js";
|
|
4
|
-
import { resolveEasing as i } from "../../animation/easing.js";
|
|
5
|
-
import { resolveMotion as a } from "../../animation/motion.js";
|
|
6
|
-
import { tweenNumber as o } from "../../animation/tween.js";
|
|
7
|
-
import { areaPath as s, linePath as c, monotonePath as l, stepPath as u } from "../../svg/path.js";
|
|
8
|
-
//#region src/charts/sparkline/sparkline.ts
|
|
9
|
-
function d(e, t, n) {
|
|
10
|
-
if (e.length === 0) return [];
|
|
11
|
-
let r = t / Math.max(1, e.length - 1), i = Math.min(...e), a = Math.max(...e) - i || 1;
|
|
12
|
-
return e.map((e, t) => ({
|
|
13
|
-
x: t * r,
|
|
14
|
-
y: n - (e - i) / a * n
|
|
15
|
-
}));
|
|
16
|
-
}
|
|
17
|
-
function f(e, t, n, r = "linear") {
|
|
18
|
-
if (e.length === 0) return "";
|
|
19
|
-
let i = d(e, t, n), a = i.map((e) => ({
|
|
20
|
-
x: e.x,
|
|
21
|
-
y: n
|
|
22
|
-
}));
|
|
23
|
-
return s(i, a, r ?? "linear");
|
|
24
|
-
}
|
|
25
|
-
function p(e, t, n, r) {
|
|
26
|
-
if (e.length === 0) return "";
|
|
27
|
-
let i = d(e, t, n);
|
|
28
|
-
return r === "monotone" ? l(i) : r === "step" ? u(i) : c(i);
|
|
29
|
-
}
|
|
30
|
-
function m(n, r, s, c, l, u, d) {
|
|
31
|
-
let f = r.length, p = Math.max(1, s / f - 1), m = s / f, h = Math.min(0, ...r), g = Math.max(...r) - h || 1, _ = a(u, 0), v = _.duration, y = i(_.easing);
|
|
32
|
-
for (; n.children.length > f;) {
|
|
33
|
-
let e = n.lastElementChild;
|
|
34
|
-
e && n.removeChild(e);
|
|
35
|
-
}
|
|
36
|
-
for (let i = 0; i < f; i++) {
|
|
37
|
-
let a = Math.max(1, (r[i] - h) / g * c), s = c - a, u = n.children[i];
|
|
38
|
-
if (u || (u = e("rect", { class: "prism-spark-bar" }), n.appendChild(u)), t(u, {
|
|
39
|
-
fill: l,
|
|
40
|
-
width: p,
|
|
41
|
-
x: i * m
|
|
42
|
-
}), v > 0 && !u.hasAttribute("data-init")) {
|
|
43
|
-
u.setAttribute("data-init", "1"), t(u, {
|
|
44
|
-
height: 0,
|
|
45
|
-
y: c
|
|
46
|
-
});
|
|
47
|
-
let e = null, n = {
|
|
48
|
-
h: 0,
|
|
49
|
-
y: c
|
|
50
|
-
}, r = {
|
|
51
|
-
h: a,
|
|
52
|
-
y: s
|
|
53
|
-
}, i = (a) => {
|
|
54
|
-
if (d?.aborted) return;
|
|
55
|
-
e === null && (e = a);
|
|
56
|
-
let s = y(Math.min(1, (a - e) / v));
|
|
57
|
-
t(u, {
|
|
58
|
-
height: o(n.h, r.h, s),
|
|
59
|
-
y: o(n.y, r.y, s)
|
|
60
|
-
}), s < 1 && requestAnimationFrame(i);
|
|
61
|
-
};
|
|
62
|
-
requestAnimationFrame(i);
|
|
63
|
-
} else u.setAttribute("data-init", "1"), t(u, {
|
|
64
|
-
height: a,
|
|
65
|
-
y: s
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
function h(e) {
|
|
70
|
-
return e.length > 0 && e[0] !== null && typeof e[0] == "object";
|
|
71
|
-
}
|
|
72
|
-
function g(e, t, n, r, i, a, o) {
|
|
73
|
-
let s = Math.min(i, n / 2, r / 2), c = a ? s : 0, l = a ? s : 0, u = o ? s : 0, d = o ? s : 0;
|
|
74
|
-
return [
|
|
75
|
-
`M${e + c},${t}`,
|
|
76
|
-
`H${e + n - u}`,
|
|
77
|
-
u ? `Q${e + n},${t} ${e + n},${t + u}` : "",
|
|
78
|
-
`V${t + r - d}`,
|
|
79
|
-
d ? `Q${e + n},${t + r} ${e + n - d},${t + r}` : "",
|
|
80
|
-
`H${e + l}`,
|
|
81
|
-
l ? `Q${e},${t + r} ${e},${t + r - l}` : "",
|
|
82
|
-
`V${t + c}`,
|
|
83
|
-
c ? `Q${e},${t} ${e + c},${t}` : "",
|
|
84
|
-
"Z"
|
|
85
|
-
].filter(Boolean).join("");
|
|
86
|
-
}
|
|
87
|
-
function _(e) {
|
|
88
|
-
return `var(--prism-color-${e % 8 + 1})`;
|
|
89
|
-
}
|
|
90
|
-
function v(i, a) {
|
|
91
|
-
let o = a.variant ?? "line", s = a.color ?? "var(--prism-color-1)", c = a.curve ?? "linear", l = a.strokeWidth ?? 1.5, u = a.fillOpacity ?? .2, d = a.data, v = r(i, {
|
|
92
|
-
a11y: a.a11y,
|
|
93
|
-
margin: {
|
|
94
|
-
bottom: 0,
|
|
95
|
-
left: 0,
|
|
96
|
-
right: 0,
|
|
97
|
-
top: 0
|
|
98
|
-
}
|
|
99
|
-
}, S), { svg: y } = v;
|
|
100
|
-
y.classList.add("prism-sparkline");
|
|
101
|
-
let b = e("g", { class: "prism-spark-inner" });
|
|
102
|
-
y.appendChild(b);
|
|
103
|
-
let x;
|
|
104
|
-
function S() {
|
|
105
|
-
let { height: n, width: r } = v.dimensions;
|
|
106
|
-
for (; b.firstChild;) b.removeChild(b.firstChild);
|
|
107
|
-
if (d.length !== 0) {
|
|
108
|
-
if (o === "stack" && h(d)) {
|
|
109
|
-
let i = e("g", { class: "prism-spark-stack" });
|
|
110
|
-
b.appendChild(i);
|
|
111
|
-
let o = a.cornerRadius ?? 4, s = d, c = s.reduce((e, t) => e + Math.max(0, t.value), 0);
|
|
112
|
-
if (c > 0) {
|
|
113
|
-
let l = (a.padPixels ?? 0) / 2, u = 0;
|
|
114
|
-
s.forEach((a, d) => {
|
|
115
|
-
let f = Math.round(u);
|
|
116
|
-
u += Math.max(0, a.value) / c * r;
|
|
117
|
-
let p = d === s.length - 1 ? r : Math.round(u), m = d === 0, h = d === s.length - 1, v = g(f + (m ? 0 : l), 0, Math.max(0, p - f - (m ? 0 : l) - (h ? 0 : l)), n, o, m, h), y = e("path", { class: "prism-spark-stack-segment" });
|
|
118
|
-
t(y, {
|
|
119
|
-
d: v,
|
|
120
|
-
fill: a.color ?? _(d)
|
|
121
|
-
}), i.appendChild(y);
|
|
122
|
-
});
|
|
123
|
-
}
|
|
124
|
-
} else if (o === "bar") {
|
|
125
|
-
let t = e("g", { class: "prism-spark-bars" });
|
|
126
|
-
b.appendChild(t), m(t, d, r, n, s, a.transition, w.signal);
|
|
127
|
-
} else {
|
|
128
|
-
if (o === "area") {
|
|
129
|
-
let i = e("path", { class: "prism-spark-fill" }), a = f(d, r, n, c);
|
|
130
|
-
t(i, {
|
|
131
|
-
d: a,
|
|
132
|
-
fill: s,
|
|
133
|
-
"fill-opacity": u,
|
|
134
|
-
stroke: "none"
|
|
135
|
-
}), b.appendChild(i);
|
|
136
|
-
}
|
|
137
|
-
let i = e("path", { class: "prism-spark-line" }), a = p(d, r, n, c);
|
|
138
|
-
t(i, {
|
|
139
|
-
d: a,
|
|
140
|
-
fill: "none",
|
|
141
|
-
stroke: s,
|
|
142
|
-
"stroke-width": l
|
|
143
|
-
}), b.appendChild(i);
|
|
144
|
-
}
|
|
145
|
-
h(d) || C(d);
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
function C(e) {
|
|
149
|
-
if (x?.(), x = void 0, !a.onHover && !a.onClick || e.length <= 1) return;
|
|
150
|
-
let { width: t } = v.dimensions;
|
|
151
|
-
y.style.cursor = "crosshair";
|
|
152
|
-
let n = t / (e.length - 1), r = (t) => {
|
|
153
|
-
let r = y.getBoundingClientRect(), i = t.clientX - r.left, o = Math.max(0, Math.min(e.length - 1, Math.round(i / n)));
|
|
154
|
-
a.onHover?.(o, e[o]);
|
|
155
|
-
}, i = () => a.onHover?.(null, null), o = (t) => {
|
|
156
|
-
if (!a.onClick) return;
|
|
157
|
-
let r = y.getBoundingClientRect(), i = t.clientX - r.left, o = Math.max(0, Math.min(e.length - 1, Math.round(i / n)));
|
|
158
|
-
a.onClick(o, e[o]);
|
|
159
|
-
};
|
|
160
|
-
y.addEventListener("mousemove", r), y.addEventListener("mouseleave", i), y.addEventListener("click", o), x = () => {
|
|
161
|
-
y.removeEventListener("mousemove", r), y.removeEventListener("mouseleave", i), y.removeEventListener("click", o);
|
|
162
|
-
};
|
|
163
|
-
}
|
|
164
|
-
let w = new AbortController(), T = !1;
|
|
165
|
-
try {
|
|
166
|
-
return S(), {
|
|
167
|
-
get disposalSignal() {
|
|
168
|
-
return w.signal;
|
|
169
|
-
},
|
|
170
|
-
dispose() {
|
|
171
|
-
T || (T = !0, w.abort(), x?.(), v.dispose());
|
|
172
|
-
},
|
|
173
|
-
get disposed() {
|
|
174
|
-
return T;
|
|
175
|
-
},
|
|
176
|
-
el: y,
|
|
177
|
-
update(e) {
|
|
178
|
-
if (T) throw new n("Cannot update a disposed chart.");
|
|
179
|
-
d = e, S();
|
|
180
|
-
},
|
|
181
|
-
[Symbol.dispose]() {
|
|
182
|
-
this.dispose();
|
|
183
|
-
}
|
|
184
|
-
};
|
|
185
|
-
} catch (e) {
|
|
186
|
-
throw w.abort(), x?.(), v.dispose(), e instanceof n ? e : new n("Failed to render chart.", { cause: e });
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
//#endregion
|
|
190
|
-
export { v as createSparkline };
|
|
191
|
-
|
|
1
|
+
import"../../_dev.js";import{createSvgElement as e,setAttributes as t}from"../../svg/element.js";import{PrismRenderError as n}from"../../errors.js";import{createChartBase as r}from"../../core/chart-base.js";import{resolveEasing as i}from"../../animation/easing.js";import{resolveMotion as a}from"../../animation/motion.js";import{tweenNumber as o}from"../../animation/tween.js";import{uniqueId as s}from"../../core/ids.js";import{areaPath as c,linePath as l,monotonePath as u,stepPath as d}from"../../svg/path.js";var f=5;function buildTopPoints(e,t,n){if(e.length===0)return[];let r=t/Math.max(1,e.length-1),i=Math.min(...e),a=Math.max(...e)-i||1;return e.map((e,t)=>({x:t*r,y:n-(e-i)/a*n}))}function buildAreaPath(e,t,n,r=`linear`){if(e.length===0)return``;let i=buildTopPoints(e,t,n),a=i.map(e=>({x:e.x,y:n}));return c(i,a,r??`linear`)}function buildPath(e,t,n,r){if(e.length===0)return``;let i=buildTopPoints(e,t,n);return r===`monotone`?u(i):r===`step`?d(i):l(i)}function renderSparkBars(n,r,s,c,l,u,d){let f=r.length,p=Math.max(1,s/f-1),m=s/f,h=Math.min(0,...r),g=Math.max(...r)-h||1,_=a(u,0),v=_.duration,y=i(_.easing);for(;n.children.length>f;){let e=n.lastElementChild;e&&n.removeChild(e)}for(let i=0;i<f;i++){let a=Math.max(1,(r[i]-h)/g*c),s=c-a,u=n.children[i];if(u||(u=e(`rect`,{class:`prism-spark-bar`}),n.appendChild(u)),t(u,{fill:l,width:p,x:i*m}),v>0&&!u.hasAttribute(`data-init`)){u.setAttribute(`data-init`,`1`),t(u,{height:0,y:c});let e=null,n={h:0,y:c},r={h:a,y:s},frame=i=>{if(d?.aborted)return;e===null&&(e=i);let a=y(Math.min(1,(i-e)/v));t(u,{height:o(n.h,r.h,a),y:o(n.y,r.y,a)}),a<1&&requestAnimationFrame(frame)};requestAnimationFrame(frame)}else u.setAttribute(`data-init`,`1`),t(u,{height:a,y:s})}}function isStackData(e){return e.length>0&&e[0]!==null&&typeof e[0]==`object`}function buildRoundedStackRect(e,t,n,r,i,a,o){let s=Math.min(i,n/2,r/2),c=a?s:0,l=a?s:0,u=o?s:0,d=o?s:0;return[`M${e+c},${t}`,`H${e+n-u}`,u?`Q${e+n},${t} ${e+n},${t+u}`:``,`V${t+r-d}`,d?`Q${e+n},${t+r} ${e+n-d},${t+r}`:``,`H${e+l}`,l?`Q${e},${t+r} ${e},${t+r-l}`:``,`V${t+c}`,c?`Q${e},${t} ${e+c},${t}`:``,`Z`].filter(Boolean).join(``)}function defaultStackColor(e){return`var(--prism-color-${e%8+1})`}function createSparkline(i,a){let o=a.variant??`line`,c=a.color??`var(--prism-color-1)`,l=a.curve??`linear`,u=a.strokeWidth??1.5,d=a.fillOpacity,p=a.showEndPoint??!0,m=s(`prism-spark-fill`),h=a.data,g=r(i,{a11y:a.a11y,margin:{bottom:0,left:0,right:0,top:0}},renderAll),{svg:_}=g;_.classList.add(`prism-sparkline`);let v=e(`g`,{class:`prism-spark-inner`});_.appendChild(v);let cleanupInteraction;function plotArea(){let{height:e,width:t}=g.dimensions,n=o===`line`||o===`area`?f:0;return{h:Math.max(1,e-n*2),inset:n,w:Math.max(1,t-n*2)}}function renderAll(){let{height:n,width:r}=g.dimensions,i=plotArea();for(;v.firstChild;)v.removeChild(v.firstChild);if(v.setAttribute(`transform`,`translate(${i.inset},${i.inset})`),h.length!==0){if(!isStackData(h)&&h.some(e=>!Number.isFinite(e)),o===`stack`&&isStackData(h)){let i=e(`g`,{class:`prism-spark-stack`});v.appendChild(i);let o=a.cornerRadius??4,s=h,c=s.reduce((e,t)=>e+Math.max(0,t.value),0);if(c>0){let l=(a.padPixels??0)/2,u=0;s.forEach((a,d)=>{let f=Math.round(u);u+=Math.max(0,a.value)/c*r;let p=d===s.length-1?r:Math.round(u),m=d===0,h=d===s.length-1,g=buildRoundedStackRect(f+(m?0:l),0,Math.max(0,p-f-(m?0:l)-(h?0:l)),n,o,m,h),_=e(`path`,{class:`prism-spark-stack-segment`});t(_,{d:g,fill:a.color??defaultStackColor(d)}),i.appendChild(_)})}}else if(o===`bar`){let t=e(`g`,{class:`prism-spark-bars`});v.appendChild(t),renderSparkBars(t,h,r,n,c,a.transition,y.signal)}else{if(o===`area`){let n=e(`defs`),r=e(`linearGradient`,{id:m,x1:0,x2:0,y1:0,y2:1});for(let[t,n]of[[0,`prism-spark-stop-top`],[1,`prism-spark-stop-bottom`]]){let i=e(`stop`,{class:n,offset:t,"stop-color":c});i.style.stopColor=c,r.appendChild(i)}n.appendChild(r),v.appendChild(n);let a=e(`path`,{class:`prism-spark-fill`}),o=buildAreaPath(h,i.w,i.h,l);t(a,{d:o,fill:`url(#${m})`,stroke:`none`}),a.style.fillOpacity=d===void 0?``:String(d),v.appendChild(a)}let n=e(`path`,{class:`prism-spark-line`}),r=buildPath(h,i.w,i.h,l);t(n,{d:r,fill:`none`,stroke:c,"stroke-width":u}),v.appendChild(n);let a=buildTopPoints(h,i.w,i.h).at(-1);p&&a&&v.appendChild(e(`circle`,{class:`prism-spark-end`,cx:a.x,cy:a.y,fill:c,r:2.5}))}isStackData(h)||attachInteraction(h)}}function attachInteraction(n){if(cleanupInteraction?.(),cleanupInteraction=void 0,!a.onHover&&!a.onClick||n.length<=1)return;let{h:r,inset:i,w:s}=plotArea();_.style.cursor=`crosshair`;let l=s/(n.length-1),u=o===`bar`?[]:buildTopPoints(n,s,r),d=e(`circle`,{class:`prism-spark-marker`,fill:c,r:3.5}),indexAt=e=>Math.max(0,Math.min(n.length-1,Math.round((e-_.getBoundingClientRect().left-i)/l)));d.style.display=`none`,v.appendChild(d);let handleMove=e=>{let r=indexAt(e.clientX),i=u[r];i&&(t(d,{cx:i.x,cy:i.y}),d.style.display=``),a.onHover?.(r,n[r])},handleLeave=()=>{d.style.display=`none`,a.onHover?.(null,null)},handleClick=e=>{if(!a.onClick)return;let t=indexAt(e.clientX);a.onClick(t,n[t])};_.addEventListener(`mousemove`,handleMove),_.addEventListener(`mouseleave`,handleLeave),_.addEventListener(`click`,handleClick),cleanupInteraction=()=>{_.removeEventListener(`mousemove`,handleMove),_.removeEventListener(`mouseleave`,handleLeave),_.removeEventListener(`click`,handleClick)}}let y=new AbortController,b=!1;try{return renderAll(),{get disposalSignal(){return y.signal},dispose(){b||(b=!0,y.abort(),cleanupInteraction?.(),g.dispose())},get disposed(){return b},el:_,update(e){if(b)throw new n(`Cannot update a disposed chart.`);h=e,renderAll()},[Symbol.dispose](){this.dispose()}}}catch(e){throw y.abort(),cleanupInteraction?.(),g.dispose(),e instanceof n?e:new n(`Failed to render chart.`,{cause:e})}}export{createSparkline};
|
|
192
2
|
//# sourceMappingURL=sparkline.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sparkline.js","names":[],"sources":["../../../src/charts/sparkline/sparkline.ts"],"sourcesContent":["import { resolveEasing } from '../../animation/easing';\nimport { resolveMotion } from '../../animation/motion';\nimport { tweenNumber } from '../../animation/tween';\nimport { createChartBase } from '../../core/chart-base';\nimport { PrismRenderError } from '../../errors';\nimport { createSvgElement, setAttributes } from '../../svg/element';\nimport type { Point } from '../../svg/path';\nimport { areaPath, linePath, monotonePath, stepPath } from '../../svg/path';\nimport type { ChartHandle, SparklineConfig, StackSegment } from '../../types';\n\nfunction buildTopPoints(data: number[], width: number, height: number): Point[] {\n if (data.length === 0) return [];\n\n const xStep = width / Math.max(1, data.length - 1);\n const min = Math.min(...data);\n const max = Math.max(...data);\n const yRange = max - min || 1;\n\n return data.map((v, i) => ({\n x: i * xStep,\n y: height - ((v - min) / yRange) * height,\n }));\n}\n\nfunction buildAreaPath(\n data: number[],\n width: number,\n height: number,\n curve: SparklineConfig['curve'] = 'linear',\n): string {\n if (data.length === 0) return '';\n\n const top = buildTopPoints(data, width, height);\n const bottom = top.map((p) => ({ x: p.x, y: height }));\n\n return areaPath(top, bottom, curve ?? 'linear');\n}\n\nfunction buildPath(data: number[], width: number, height: number, curve: SparklineConfig['curve']): string {\n if (data.length === 0) return '';\n\n const points = buildTopPoints(data, width, height);\n\n return curve === 'monotone' ? monotonePath(points) : curve === 'step' ? stepPath(points) : linePath(points);\n}\n\nfunction renderSparkBars(\n parent: SVGGElement,\n data: number[],\n width: number,\n height: number,\n color: string,\n transition?: SparklineConfig['transition'],\n disposalSignal?: AbortSignal,\n): void {\n const count = data.length;\n const barW = Math.max(1, width / count - 1);\n const gap = width / count;\n const min = Math.min(0, ...data);\n const max = Math.max(...data);\n const yRange = max - min || 1;\n const motion = resolveMotion(transition, 0);\n const dur = motion.duration;\n const easing = resolveEasing(motion.easing);\n\n while (parent.children.length > count) {\n const last = parent.lastElementChild;\n\n if (last) parent.removeChild(last);\n }\n\n for (let i = 0; i < count; i++) {\n const finalH = Math.max(1, ((data[i] - min) / yRange) * height);\n const finalY = height - finalH;\n\n let rect = parent.children[i] as SVGRectElement | undefined;\n\n if (!rect) {\n rect = createSvgElement('rect', { class: 'prism-spark-bar' });\n parent.appendChild(rect);\n }\n\n setAttributes(rect, { fill: color, width: barW, x: i * gap });\n\n if (dur > 0 && !rect.hasAttribute('data-init')) {\n rect.setAttribute('data-init', '1');\n setAttributes(rect, { height: 0, y: height });\n\n let start: number | null = null;\n const from = { h: 0, y: height };\n const to = { h: finalH, y: finalY };\n\n const frame = (ts: number) => {\n if (disposalSignal?.aborted) return;\n\n if (start === null) start = ts;\n\n const t = easing(Math.min(1, (ts - start) / dur));\n\n setAttributes(rect!, {\n height: tweenNumber(from.h, to.h, t),\n y: tweenNumber(from.y, to.y, t),\n });\n\n if (t < 1) requestAnimationFrame(frame);\n };\n\n requestAnimationFrame(frame);\n } else {\n rect.setAttribute('data-init', '1');\n setAttributes(rect, { height: finalH, y: finalY });\n }\n }\n}\n\nfunction isStackData(data: number[] | StackSegment[]): data is StackSegment[] {\n return data.length > 0 && data[0] !== null && typeof data[0] === 'object';\n}\n\nfunction buildRoundedStackRect(\n x: number,\n y: number,\n w: number,\n h: number,\n r: number,\n roundLeft: boolean,\n roundRight: boolean,\n): string {\n const maxR = Math.min(r, w / 2, h / 2);\n const tl = roundLeft ? maxR : 0;\n const bl = roundLeft ? maxR : 0;\n const tr = roundRight ? maxR : 0;\n const br = roundRight ? maxR : 0;\n\n return [\n `M${x + tl},${y}`,\n `H${x + w - tr}`,\n tr ? `Q${x + w},${y} ${x + w},${y + tr}` : '',\n `V${y + h - br}`,\n br ? `Q${x + w},${y + h} ${x + w - br},${y + h}` : '',\n `H${x + bl}`,\n bl ? `Q${x},${y + h} ${x},${y + h - bl}` : '',\n `V${y + tl}`,\n tl ? `Q${x},${y} ${x + tl},${y}` : '',\n 'Z',\n ]\n .filter(Boolean)\n .join('');\n}\n\nfunction defaultStackColor(i: number): string {\n return `var(--prism-color-${(i % 8) + 1})`;\n}\n\nexport function createSparkline(\n container: HTMLElement,\n config: SparklineConfig,\n): ChartHandle<number[] | StackSegment[]> {\n const variant = config.variant ?? 'line';\n const color = config.color ?? 'var(--prism-color-1)';\n const curve = config.curve ?? 'linear';\n const strokeWidth = config.strokeWidth ?? 1.5;\n const fillOpacity = config.fillOpacity ?? 0.2;\n let data = config.data;\n\n const base = createChartBase(\n container,\n {\n a11y: config.a11y,\n margin: { bottom: 0, left: 0, right: 0, top: 0 },\n },\n renderAll,\n );\n\n const { svg } = base;\n\n svg.classList.add('prism-sparkline');\n\n const innerGroup = createSvgElement('g', { class: 'prism-spark-inner' });\n\n svg.appendChild(innerGroup);\n\n let cleanupInteraction: (() => void) | undefined;\n\n function renderAll(): void {\n const { height: h, width: w } = base.dimensions;\n\n while (innerGroup.firstChild) innerGroup.removeChild(innerGroup.firstChild);\n\n if (data.length === 0) return;\n\n if (variant === 'stack' && isStackData(data)) {\n const stackGroup = createSvgElement('g', { class: 'prism-spark-stack' });\n\n innerGroup.appendChild(stackGroup);\n\n const cornerRadius = config.cornerRadius ?? 4;\n const segs = data as StackSegment[];\n const total = segs.reduce((s, d) => s + Math.max(0, d.value), 0);\n\n if (total > 0) {\n const half = (config.padPixels ?? 0) / 2;\n let xAcc = 0;\n\n segs.forEach((seg, i) => {\n const xStart = Math.round(xAcc);\n\n xAcc += (Math.max(0, seg.value) / total) * w;\n\n const xEnd = i === segs.length - 1 ? w : Math.round(xAcc);\n const isFirst = i === 0;\n const isLast = i === segs.length - 1;\n const drawX = xStart + (isFirst ? 0 : half);\n const drawW = Math.max(0, xEnd - xStart - (isFirst ? 0 : half) - (isLast ? 0 : half));\n const d = buildRoundedStackRect(drawX, 0, drawW, h, cornerRadius, isFirst, isLast);\n const path = createSvgElement('path', { class: 'prism-spark-stack-segment' });\n\n setAttributes(path, { d, fill: seg.color ?? defaultStackColor(i) });\n stackGroup.appendChild(path);\n });\n }\n } else if (variant === 'bar') {\n const barsGroup = createSvgElement('g', { class: 'prism-spark-bars' });\n\n innerGroup.appendChild(barsGroup);\n renderSparkBars(barsGroup, data as number[], w, h, color, config.transition, ac.signal);\n } else {\n if (variant === 'area') {\n const fill = createSvgElement('path', { class: 'prism-spark-fill' });\n const fillD = buildAreaPath(data as number[], w, h, curve);\n\n setAttributes(fill, { d: fillD, fill: color, 'fill-opacity': fillOpacity, stroke: 'none' });\n innerGroup.appendChild(fill);\n }\n\n const path = createSvgElement('path', { class: 'prism-spark-line' });\n const pathD = buildPath(data as number[], w, h, curve);\n\n setAttributes(path, { d: pathD, fill: 'none', stroke: color, 'stroke-width': strokeWidth });\n innerGroup.appendChild(path);\n }\n\n if (!isStackData(data)) attachInteraction(data as number[]);\n }\n\n function attachInteraction(data: number[]): void {\n cleanupInteraction?.();\n cleanupInteraction = undefined;\n\n if (!config.onHover && !config.onClick) return;\n\n if (data.length <= 1) return;\n\n const { width: w } = base.dimensions;\n\n svg.style.cursor = 'crosshair';\n\n const xStep = w / (data.length - 1);\n\n const handleMove = (e: MouseEvent) => {\n const rect = svg.getBoundingClientRect();\n const relX = e.clientX - rect.left;\n const idx = Math.max(0, Math.min(data.length - 1, Math.round(relX / xStep)));\n\n config.onHover?.(idx, data[idx]);\n };\n\n const handleLeave = () => config.onHover?.(null, null);\n\n const handleClick = (e: MouseEvent) => {\n if (!config.onClick) return;\n\n const rect = svg.getBoundingClientRect();\n const relX = e.clientX - rect.left;\n const idx = Math.max(0, Math.min(data.length - 1, Math.round(relX / xStep)));\n\n config.onClick(idx, data[idx]);\n };\n\n svg.addEventListener('mousemove', handleMove);\n svg.addEventListener('mouseleave', handleLeave);\n svg.addEventListener('click', handleClick);\n\n cleanupInteraction = () => {\n svg.removeEventListener('mousemove', handleMove);\n svg.removeEventListener('mouseleave', handleLeave);\n svg.removeEventListener('click', handleClick);\n };\n }\n\n const ac = new AbortController();\n let isDisposed = false;\n\n try {\n renderAll();\n\n return {\n get disposalSignal(): AbortSignal {\n return ac.signal;\n },\n\n dispose() {\n if (isDisposed) return;\n\n isDisposed = true;\n ac.abort();\n cleanupInteraction?.();\n base.dispose();\n },\n\n get disposed(): boolean {\n return isDisposed;\n },\n\n el: svg,\n\n update(next) {\n if (isDisposed) throw new PrismRenderError('Cannot update a disposed chart.');\n data = next;\n renderAll();\n },\n\n [Symbol.dispose]() {\n this.dispose();\n },\n };\n } catch (error) {\n ac.abort();\n cleanupInteraction?.();\n base.dispose();\n throw error instanceof PrismRenderError ? error : new PrismRenderError('Failed to render chart.', { cause: error });\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"sparkline.js","names":[],"sources":["../../../src/charts/sparkline/sparkline.ts"],"sourcesContent":["import { warn } from '../../_dev';\nimport { resolveEasing } from '../../animation/easing';\nimport { resolveMotion } from '../../animation/motion';\nimport { tweenNumber } from '../../animation/tween';\nimport { createChartBase } from '../../core/chart-base';\nimport { uniqueId } from '../../core/ids';\nimport { PrismRenderError } from '../../errors';\nimport { createSvgElement, setAttributes } from '../../svg/element';\nimport type { Point } from '../../svg/path';\nimport { areaPath, linePath, monotonePath, stepPath } from '../../svg/path';\nimport type { ChartHandle, SparklineConfig, StackSegment } from '../../types';\n\n/** Fits the 3.5px hover marker plus its ring inside the SVG. */\nconst PLOT_INSET = 5;\n\nfunction buildTopPoints(data: number[], width: number, height: number): Point[] {\n if (data.length === 0) return [];\n\n const xStep = width / Math.max(1, data.length - 1);\n const min = Math.min(...data);\n const max = Math.max(...data);\n const yRange = max - min || 1;\n\n return data.map((v, i) => ({\n x: i * xStep,\n y: height - ((v - min) / yRange) * height,\n }));\n}\n\nfunction buildAreaPath(\n data: number[],\n width: number,\n height: number,\n curve: SparklineConfig['curve'] = 'linear',\n): string {\n if (data.length === 0) return '';\n\n const top = buildTopPoints(data, width, height);\n const bottom = top.map((p) => ({ x: p.x, y: height }));\n\n return areaPath(top, bottom, curve ?? 'linear');\n}\n\nfunction buildPath(data: number[], width: number, height: number, curve: SparklineConfig['curve']): string {\n if (data.length === 0) return '';\n\n const points = buildTopPoints(data, width, height);\n\n return curve === 'monotone' ? monotonePath(points) : curve === 'step' ? stepPath(points) : linePath(points);\n}\n\nfunction renderSparkBars(\n parent: SVGGElement,\n data: number[],\n width: number,\n height: number,\n color: string,\n transition?: SparklineConfig['transition'],\n disposalSignal?: AbortSignal,\n): void {\n const count = data.length;\n const barW = Math.max(1, width / count - 1);\n const gap = width / count;\n const min = Math.min(0, ...data);\n const max = Math.max(...data);\n const yRange = max - min || 1;\n const motion = resolveMotion(transition, 0);\n const dur = motion.duration;\n const easing = resolveEasing(motion.easing);\n\n while (parent.children.length > count) {\n const last = parent.lastElementChild;\n\n if (last) parent.removeChild(last);\n }\n\n for (let i = 0; i < count; i++) {\n const finalH = Math.max(1, ((data[i] - min) / yRange) * height);\n const finalY = height - finalH;\n\n let rect = parent.children[i] as SVGRectElement | undefined;\n\n if (!rect) {\n rect = createSvgElement('rect', { class: 'prism-spark-bar' });\n parent.appendChild(rect);\n }\n\n setAttributes(rect, { fill: color, width: barW, x: i * gap });\n\n if (dur > 0 && !rect.hasAttribute('data-init')) {\n rect.setAttribute('data-init', '1');\n setAttributes(rect, { height: 0, y: height });\n\n let start: number | null = null;\n const from = { h: 0, y: height };\n const to = { h: finalH, y: finalY };\n\n const frame = (ts: number) => {\n if (disposalSignal?.aborted) return;\n\n if (start === null) start = ts;\n\n const t = easing(Math.min(1, (ts - start) / dur));\n\n setAttributes(rect!, {\n height: tweenNumber(from.h, to.h, t),\n y: tweenNumber(from.y, to.y, t),\n });\n\n if (t < 1) requestAnimationFrame(frame);\n };\n\n requestAnimationFrame(frame);\n } else {\n rect.setAttribute('data-init', '1');\n setAttributes(rect, { height: finalH, y: finalY });\n }\n }\n}\n\nfunction isStackData(data: number[] | StackSegment[]): data is StackSegment[] {\n return data.length > 0 && data[0] !== null && typeof data[0] === 'object';\n}\n\nfunction buildRoundedStackRect(\n x: number,\n y: number,\n w: number,\n h: number,\n r: number,\n roundLeft: boolean,\n roundRight: boolean,\n): string {\n const maxR = Math.min(r, w / 2, h / 2);\n const tl = roundLeft ? maxR : 0;\n const bl = roundLeft ? maxR : 0;\n const tr = roundRight ? maxR : 0;\n const br = roundRight ? maxR : 0;\n\n return [\n `M${x + tl},${y}`,\n `H${x + w - tr}`,\n tr ? `Q${x + w},${y} ${x + w},${y + tr}` : '',\n `V${y + h - br}`,\n br ? `Q${x + w},${y + h} ${x + w - br},${y + h}` : '',\n `H${x + bl}`,\n bl ? `Q${x},${y + h} ${x},${y + h - bl}` : '',\n `V${y + tl}`,\n tl ? `Q${x},${y} ${x + tl},${y}` : '',\n 'Z',\n ]\n .filter(Boolean)\n .join('');\n}\n\nfunction defaultStackColor(i: number): string {\n return `var(--prism-color-${(i % 8) + 1})`;\n}\n\nexport function createSparkline(\n container: HTMLElement,\n config: SparklineConfig,\n): ChartHandle<number[] | StackSegment[]> {\n const variant = config.variant ?? 'line';\n const color = config.color ?? 'var(--prism-color-1)';\n const curve = config.curve ?? 'linear';\n const strokeWidth = config.strokeWidth ?? 1.5;\n const fillOpacity = config.fillOpacity;\n const showEndPoint = config.showEndPoint ?? true;\n const gradientId = uniqueId('prism-spark-fill');\n let data = config.data;\n\n const base = createChartBase(\n container,\n {\n a11y: config.a11y,\n margin: { bottom: 0, left: 0, right: 0, top: 0 },\n },\n renderAll,\n );\n\n const { svg } = base;\n\n svg.classList.add('prism-sparkline');\n\n const innerGroup = createSvgElement('g', { class: 'prism-spark-inner' });\n\n svg.appendChild(innerGroup);\n\n let cleanupInteraction: (() => void) | undefined;\n\n /** Line and area plots are inset so dots on the first and last values are not clipped. */\n function plotArea(): { h: number; inset: number; w: number } {\n const { height, width } = base.dimensions;\n const inset = variant === 'line' || variant === 'area' ? PLOT_INSET : 0;\n\n return { h: Math.max(1, height - inset * 2), inset, w: Math.max(1, width - inset * 2) };\n }\n\n function renderAll(): void {\n const { height: h, width: w } = base.dimensions;\n const plot = plotArea();\n\n while (innerGroup.firstChild) innerGroup.removeChild(innerGroup.firstChild);\n\n innerGroup.setAttribute('transform', `translate(${plot.inset},${plot.inset})`);\n\n if (data.length === 0) return;\n\n if (!isStackData(data) && data.some((v) => !Number.isFinite(v))) {\n warn('createSparkline: data contains non-finite values; they are drawn as the minimum.');\n }\n\n if (variant === 'stack' && isStackData(data)) {\n const stackGroup = createSvgElement('g', { class: 'prism-spark-stack' });\n\n innerGroup.appendChild(stackGroup);\n\n const cornerRadius = config.cornerRadius ?? 4;\n const segs = data as StackSegment[];\n const total = segs.reduce((s, d) => s + Math.max(0, d.value), 0);\n\n if (total > 0) {\n const half = (config.padPixels ?? 0) / 2;\n let xAcc = 0;\n\n segs.forEach((seg, i) => {\n const xStart = Math.round(xAcc);\n\n xAcc += (Math.max(0, seg.value) / total) * w;\n\n const xEnd = i === segs.length - 1 ? w : Math.round(xAcc);\n const isFirst = i === 0;\n const isLast = i === segs.length - 1;\n const drawX = xStart + (isFirst ? 0 : half);\n const drawW = Math.max(0, xEnd - xStart - (isFirst ? 0 : half) - (isLast ? 0 : half));\n const d = buildRoundedStackRect(drawX, 0, drawW, h, cornerRadius, isFirst, isLast);\n const path = createSvgElement('path', { class: 'prism-spark-stack-segment' });\n\n setAttributes(path, { d, fill: seg.color ?? defaultStackColor(i) });\n stackGroup.appendChild(path);\n });\n }\n } else if (variant === 'bar') {\n const barsGroup = createSvgElement('g', { class: 'prism-spark-bars' });\n\n innerGroup.appendChild(barsGroup);\n renderSparkBars(barsGroup, data as number[], w, h, color, config.transition, ac.signal);\n } else {\n if (variant === 'area') {\n const defs = createSvgElement('defs');\n const gradient = createSvgElement('linearGradient', { id: gradientId, x1: 0, x2: 0, y1: 0, y2: 1 });\n\n for (const [offset, className] of [\n [0, 'prism-spark-stop-top'],\n [1, 'prism-spark-stop-bottom'],\n ] as const) {\n const stop = createSvgElement('stop', { class: className, offset, 'stop-color': color });\n\n stop.style.stopColor = color;\n gradient.appendChild(stop);\n }\n\n defs.appendChild(gradient);\n innerGroup.appendChild(defs);\n\n const fill = createSvgElement('path', { class: 'prism-spark-fill' });\n const fillD = buildAreaPath(data as number[], plot.w, plot.h, curve);\n\n setAttributes(fill, { d: fillD, fill: `url(#${gradientId})`, stroke: 'none' });\n fill.style.fillOpacity = fillOpacity === undefined ? '' : String(fillOpacity);\n innerGroup.appendChild(fill);\n }\n\n const path = createSvgElement('path', { class: 'prism-spark-line' });\n const pathD = buildPath(data as number[], plot.w, plot.h, curve);\n\n setAttributes(path, { d: pathD, fill: 'none', stroke: color, 'stroke-width': strokeWidth });\n innerGroup.appendChild(path);\n\n const end = buildTopPoints(data as number[], plot.w, plot.h).at(-1);\n\n if (showEndPoint && end) {\n innerGroup.appendChild(\n createSvgElement('circle', { class: 'prism-spark-end', cx: end.x, cy: end.y, fill: color, r: 2.5 }),\n );\n }\n }\n\n if (!isStackData(data)) attachInteraction(data as number[]);\n }\n\n function attachInteraction(data: number[]): void {\n cleanupInteraction?.();\n cleanupInteraction = undefined;\n\n if (!config.onHover && !config.onClick) return;\n\n if (data.length <= 1) return;\n\n const { h, inset, w } = plotArea();\n\n svg.style.cursor = 'crosshair';\n\n const xStep = w / (data.length - 1);\n const points = variant === 'bar' ? [] : buildTopPoints(data, w, h);\n const marker = createSvgElement('circle', { class: 'prism-spark-marker', fill: color, r: 3.5 });\n const indexAt = (clientX: number): number =>\n Math.max(0, Math.min(data.length - 1, Math.round((clientX - svg.getBoundingClientRect().left - inset) / xStep)));\n\n marker.style.display = 'none';\n innerGroup.appendChild(marker);\n\n const handleMove = (e: MouseEvent) => {\n const idx = indexAt(e.clientX);\n const point = points[idx];\n\n if (point) {\n setAttributes(marker, { cx: point.x, cy: point.y });\n marker.style.display = '';\n }\n\n config.onHover?.(idx, data[idx]);\n };\n\n const handleLeave = () => {\n marker.style.display = 'none';\n config.onHover?.(null, null);\n };\n\n const handleClick = (e: MouseEvent) => {\n if (!config.onClick) return;\n\n const idx = indexAt(e.clientX);\n\n config.onClick(idx, data[idx]);\n };\n\n svg.addEventListener('mousemove', handleMove);\n svg.addEventListener('mouseleave', handleLeave);\n svg.addEventListener('click', handleClick);\n\n cleanupInteraction = () => {\n svg.removeEventListener('mousemove', handleMove);\n svg.removeEventListener('mouseleave', handleLeave);\n svg.removeEventListener('click', handleClick);\n };\n }\n\n const ac = new AbortController();\n let isDisposed = false;\n\n try {\n renderAll();\n\n return {\n get disposalSignal(): AbortSignal {\n return ac.signal;\n },\n\n dispose() {\n if (isDisposed) return;\n\n isDisposed = true;\n ac.abort();\n cleanupInteraction?.();\n base.dispose();\n },\n\n get disposed(): boolean {\n return isDisposed;\n },\n\n el: svg,\n\n update(next) {\n if (isDisposed) throw new PrismRenderError('Cannot update a disposed chart.');\n data = next;\n renderAll();\n },\n\n [Symbol.dispose]() {\n this.dispose();\n },\n };\n } catch (error) {\n ac.abort();\n cleanupInteraction?.();\n base.dispose();\n throw error instanceof PrismRenderError ? error : new PrismRenderError('Failed to render chart.', { cause: error });\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
require("../_dev.cjs");function
|
|
1
|
+
require("../_dev.cjs");function keyId(e){return e instanceof Date?`date:${e.getTime()}`:`${typeof e}:${String(e)}`}function normalizeCartesianSeries(e,t){let n=[],r=new Map;return{domain:n,labels:r,series:e.map((e,i)=>{let a=new Map;for(let o of t[i]??[]){let t=keyId(o.key);if(a.has(t)){`${String(o.key)}${e.name}`;continue}a.set(t,o),r.has(t)||(r.set(t,o.key),n.push(t))}return{byKey:a,config:e}})}}exports.keyId=keyId,exports.normalizeCartesianSeries=normalizeCartesianSeries;
|
|
2
2
|
//# sourceMappingURL=cartesian-model.cjs.map
|