@graphique/geom-area
Version:
For area charts, stacked area charts, or streamgraphs
2 lines • 16.1 kB
JavaScript
import K,{useEffect as Oe,useMemo as f,useState as xt,useCallback as bt}from"react";import{useGG as vt,themeState as Ot,generateID as At,EventArea as Gt,isDate as Ae,widen as Tt,yScaleState as Lt,zoomState as Et,defaultScheme as ze,fillScaleState as Nt,strokeScaleState as Vt}from"@graphique/graphique";import{Animate as Pt}from"react-move";import{easeCubic as Ge}from"d3-ease";import{scaleOrdinal as $e}from"d3-scale";import{interpolate as wt}from"d3-interpolate";import{interpolatePath as Mt}from"d3-interpolate-path";import{area as We,curveLinear as Xe,stack as Ct,stackOffsetDiverging as It,stackOffsetWiggle as Yt,stackOffsetExpand as _t,stackOrderNone as Ft}from"d3-shape";import{min as Se,max as le,sum as zt,extent as $t}from"d3-array";import{useAtom as ue}from"jotai";var Pe=(r=>(r.IDENTITY="identity",r.STACK="stack",r.FILL="fill",r.STREAM="stream",r))(Pe||{});import Q,{useMemo as R}from"react";import{useGG as ft,tooltipState as pt,themeState as yt,XTooltip as dt,YTooltip as gt,TooltipContainer as St,TooltipPosition as kt}from"@graphique/graphique";import{useAtom as Ie}from"jotai";import{mean as Ye,sum as ht,min as _e,max as Dt}from"d3-array";import q from"react";import{TooltipContainer as ot,formatMissing as nt,themeState as at}from"@graphique/graphique";import{useAtom as it}from"jotai";var we=({data:l,hasXAxisTooltip:i,geomID:w})=>{let x=l&&l[0]?l[0]?.formattedX:void 0,[{tooltip:r}]=it(at);return l?q.createElement(ot,null,!i&&x&&q.createElement("div",{style:{marginTop:2,marginBottom:l.length===1?2:6,fontSize:r?.xLabel?.fontSize||r?.font?.size,color:"#555"}},x),l.map((b,g)=>{let k=nt(b.group);return q.createElement("div",{key:`group-tooltip-${b.label||k}-${w}-${g.toString()}`},q.createElement("div",{style:{marginTop:3,marginBottom:l.length<g+1?3:2,display:"flex",alignItems:"center"}},(b.label||b.group)&&q.createElement(q.Fragment,null,b.mark,q.createElement("div",{style:{display:"flex",alignItems:"flex-end",marginLeft:4}},q.createElement("div",{style:{marginRight:5}},q.createElement("span",{style:{fontSize:r?.groupLabel?.fontSize||r?.font?.size}},b.label||k," ")))),q.createElement("div",{style:{fontWeight:500,fontSize:r?.yLabel?.fontSize||(r?.font?.size||12)+1}},b.formattedY)))})):null};import ne,{useMemo as Me}from"react";import{useGG as st,tooltipState as lt,themeState as ut,formatMissing as mt}from"@graphique/graphique";import{useAtom as Ce}from"jotai";import{min as ct}from"d3-array";var de=({x:l,y:i,y0:w,y1:x,aes:r,markerRadius:b,markerStroke:g,stackedData:k,position:A})=>{let{ggState:M}=st()||{},{scales:G,copiedScales:p,width:s,height:v,margin:u,id:U}=M||{},[{datum:V}]=Ce(lt),[{defaultFill:L,geoms:n}]=Ce(ut)||{},{area:m}=n||{},c=Me(()=>ct([V&&l(V[0]),s-(u?.right??0)]),[V,l,s]),z=Me(()=>r?.y1?x:i,[x,i,r]);return v&&u?ne.createElement(ne.Fragment,null,c&&V&&ne.createElement("g",{className:`__gg-tooltip-${U}`,style:{transform:`translateX(${c}px)`}},ne.createElement("line",{y1:v-u.bottom,y2:u.top,strokeDasharray:2,stroke:"#888",strokeWidth:1.5,style:{pointerEvents:"none"},"data-testid":"__gg_geom_area_marker"}),V.map((h,y)=>{let E=p?.groupAccessor?mt(p?.groupAccessor(h)):"__group",B=G?.groups?G.groups.includes(E):!0,W=[i(h)];if(!B)W=[];else if(k){let C=k.find(e=>r.x&&e.group===E&&Number(e.x)===Number(r.x(h)));A==="stream"&&(W=[G?.yScale(C?.y0),G?.yScale(C?.y1)]),["stack","fill"].includes(A)&&(W=[G?.yScale(C?.y1)])}else r.y0&&r.y1&&(W=[w(h),x(h)]);let $=m?.fill&&!["none","transparent"].includes(m?.fill??"")?m.fill:m?.fillScale&&r.fill&&m.fillScale(r.fill(h))||(p?.fillScale&&r?.fill?p.fillScale(r.fill(h)):(m?.stroke||m?.strokeScale&&r.stroke&&m.strokeScale(r.stroke(h))||p?.strokeScale?.(r?.stroke?.(h)))??L);return W?.map((C,e)=>{let d=A==="fill"||C<=p?.yScale.range()[0]&&C>=p?.yScale.range()[1];return typeof z(h)<"u"&&d&&ne.createElement("g",{key:`marker-${p?.groups?p.groups[y]:y}-${e.toString()}`,style:{pointerEvents:"none"}},ne.createElement("circle",{r:b*2+.5,fill:$,cy:C,fillOpacity:Math.min(.5,Math.max((m?.strokeOpacity||.9)-.35,0))}),ne.createElement("circle",{r:b,fill:$,stroke:g,strokeWidth:b/3.2,cy:C,fillOpacity:m?.strokeOpacity||.9,strokeOpacity:.7,"data-testid":"__gg_geom_area_marker_point"}))})}))):null};var ve=({x:l,y:i,y0:w,y1:x,aes:r,geomID:b,position:g})=>{let{ggState:k}=ft()||{},{id:A,scales:M,copiedScales:G,width:p,height:s,margin:v}=k||{height:0},[{datum:u,position:U,xAxis:V,xFormat:L,yFormat:n,content:m}]=Ie(pt),[{geoms:c,defaultStroke:z,defaultFill:h}]=Ie(yt),{area:y}=c||{},E=R(()=>_e([u&&l(u[0]),p-(v?.right??0)]),[u,l,p]),B=R(()=>u?.some(x)||u?.some(i),[u,i,x]),W=R(()=>M?.groups?u?.filter(S=>{let T=M?.groupAccessor?.(S);return M?.groups?.includes(T)&&T}):u,[u,c,M]),$=R(()=>y?.groupAccessor||(()=>"__group"),[y]),C=R(()=>W&&Ye(W.map((ee,S,T)=>{let H;if(g==="stack"){let J=T.slice(0,S+1).map(r.y).reduce((P,N)=>P+N,0);H=M?.yScale(J)}else if(g==="fill"&&r?.y){let J=T.slice(0,S+1).map(P=>r.y(P)/ht(T,r.y)).reduce((P,N)=>P+N,0);H=M?.yScale(J)}else r.y0&&r.y1?H=Ye([w(ee),x(ee)]):H=i(ee);return H}))||0,[W,i,w,x]),e=Dt([0,_e([C,s])]),d=R(()=>g==="stream"?(s-v.top-v.bottom)/2:e,[g,e]),Z=R(()=>u&&u[0]&&r?.x&&r.x(u[0]),[u,r]),me=G?.fillScale?.domain(),ce=R(()=>W?.filter(S=>r?.y1&&typeof r.y1(S)<"u"&&r.y1(S)!==null||r?.y&&typeof r.y(S)<"u"&&r.y(S)!==null).sort((S,T)=>me.indexOf(String($(S)))-me.indexOf(String($(T)))).map(S=>{let T=M?.groupAccessor?.(S),H=T==="__group",J;r?.y&&(J=n?n(r.y(S)):r.y(S)),r?.y1&&(J=n?n(r.y1(S)):r.y1(S));let P=Q.createElement("svg",{width:15,height:15},Q.createElement("rect",{transform:"translate(1, 1)",width:12,height:12,fill:y?.fill||y?.fillScale&&y.fillScale(T)||(G?.fillScale?G.fillScale(T):h),stroke:y?.stroke||y?.strokeScale&&y.strokeScale(T)||(G?.strokeScale?G.strokeScale(T):void 0),strokeDasharray:y?.strokeDasharray||(G?.strokeDasharrayScale?G.strokeDasharrayScale(T):void 0),strokeWidth:.6,fillOpacity:y?.fillOpacity,strokeOpacity:y?.strokeOpacity}));return{group:H?void 0:T,mark:T&&!H?P:void 0,datum:u,x:Z,y:(r?.y1&&r?.y1(S))??(r?.y&&r.y(S)),formattedY:J,formattedX:L?L(Z):String(Z)}}),[W,Z,r,n,L,G,c,z]),ke=m?Q.createElement("div",null,m(ce)):Q.createElement(we,{data:ce,hasXAxisTooltip:!!V,geomID:b});return u?Q.createElement(Q.Fragment,null,V&&v&&E&&Q.createElement(dt,{id:A,left:E,top:-v.bottom,value:typeof V=="boolean"?Q.createElement(St,null,L&&L(Z)):V(Z)}),E&&B&&Q.createElement(gt,{id:A,left:E,top:U===kt.DATA?-(s-d):-s,value:ke,wait:!0})):null};var ge="GeomArea",Fe=({geomAes:l,shouldStack:i,position:w})=>{if(i&&!l?.y)throw new Error(`${ge}: aes.y is required when using position="${w}"`);if(l?.y1&&!l?.y0)throw new Error(`${ge}: aes.y1 can only be specified when combined with aes.y0`);if(l?.y0&&!l.y1&&!l.y)throw new Error(`${ge}: aes.y0 needs to be specified with aes.y1 or aes.y`);if(!l?.y&&!(l?.y0&&l?.y1))throw new Error(`${ge}: need to specify at least aes.y, or some combination of (aes.y, aes.y0) | (aes.y0, aes.y1)`)};var Ke=({data:l,aes:i,brushAction:w,curve:x=Xe,onDatumFocus:r,onDatumSelection:b,onExit:g,attr:k,showTooltip:A=!0,showLineMarker:M=!0,markerRadius:G=3.5,markerStroke:p="#fff",position:s="identity",isAnimated:v=!0})=>{let{ggState:u}=vt()||{},{id:U,data:V,aes:L,scales:n,copiedScales:m}=u||{},[c,z]=ue(Ot),[{values:h,domain:y}]=ue(Nt),[{values:E,domain:B}]=ue(Vt),[,W]=ue(Lt),[{xDomain:$,yDomain:C}]=ue(Et),e=f(()=>i?{...L,...i}:L,[L,i]),d=l||V,Z=f(()=>d?.filter(t=>{if(!$?.current)return!0;let o=e?.x?.(t);return o&&o>=$?.current?.[0]&&o<=$?.current?.[1]}),[d,$?.current,e.x]),me=f(()=>{let t=d?d.filter(o=>e?.x&&(e?.x(o)===null||typeof e?.x(o)>"u"||Number.isNaN(e.x(o)?.valueOf())||Ae(e.x(o))&&e.x(o)?.valueOf()===0)):[];return d&&t.length===d.length},[d,e]),ce=f(()=>{let t=d?d.filter(o=>!e.y0&&!e.y1&&e?.y&&(e.y(o)===null||typeof e.y(o)>"u"||Number.isNaN(e.y(o)?.valueOf()))||e.y0&&(e.y0(o)===null||typeof e.y0(o)>"u"||Number.isNaN(e.y0(o)?.valueOf()))||e.y1&&(e.y1(o)===null||typeof e.y1(o)>"u"||Number.isNaN(e.y1(o)?.valueOf()))):[];return d&&t.length===d.length},[d]),{defaultFill:ke,defaultStroke:ee,animationDuration:S}=c,T=f(()=>At(),[]),[H,J]=xt(!0);Oe(()=>{let t=setTimeout(()=>J(!1),0);return()=>clearTimeout(t)},[]);let P=f(()=>["stack","fill","stream"].includes(s),[s]),N=f(()=>e?.group??e?.fill?e?.group??e?.fill:n?.groupAccessor??(()=>"__group"),[e]),I=f(()=>{if(N)return Array.from(new Set(d?.map(N)))},[d,N]),Je=f(()=>m?.fillScale?.domain(),[m]),Qe=f(()=>m?.strokeScale?.domain(),[m]),fe=f(()=>t=>e?.x&&n?.xScale&&n.xScale(e?.x(t)),[n,e]),he=f(()=>t=>e?.y&&n?.yScale&&n.yScale(e?.y(t)),[n,e]),Te=f(()=>s==="fill"?_t:s==="stream"?Yt:It,[s]),Le=f(()=>Ft,[s]);Fe({geomAes:e,position:s,shouldStack:P});let te=f(()=>{if(I&&e.fill)return $e().domain(y||Je||I).range(h||ze)},[e,h,y]),re=f(()=>{if(I&&e.stroke)return $e().domain(B||Qe||I).range(E||ze)},[e,B]),j=f(()=>d&&e?.x&&e?.y&&N&&I?Ct().keys([...y||I].reverse()).order(Le).offset(Te)(Tt(d,e.x,N,e.y)).map(D=>{let Y=D.key;return D.map(X=>({group:Y,x:X.data.key,y0:X[0],y1:X[1]})).flat()}).flat().sort((D,Y)=>D.x-Y.x):null,[d,e,Te,Le]),Ee=f(()=>s==="stream"&&!!j,[j,s]),Ne=bt(t=>{let o=[0,1],D=[0,1];if(!N&&!I&&!e.y0&&!e.y1&&(D=[0,o[1]]),!N&&!I&&(D=o),N&&I&&t&&e?.x){let Y=I.map(_=>le(t.filter(F=>N(F)===_),F=>(P?e.y||(()=>{}):e.y1||e.y||(()=>{}))(F))),X=I.map(_=>Se(t.filter(F=>N(F)===_),F=>(e.y0||(()=>{}))(F)));if(["stack"].includes(s))return[0,le([zt(Y),o[1]])];if(s==="fill")return[0,1];if(Ee){let _=$?.current?j.filter(a=>a.x>=$?.current?.[0]&&a.x<=$?.current?.[1]):j,F=Se(_,a=>a.y0),oe=le(_,a=>a.y1);return[F,oe]}if(s==="identity"){let _=t?.map(ie=>{let be=e?.y?e.y(ie):void 0,tt=e?.y0?e.y0(ie):void 0,rt=e?.y1?e.y1(ie):void 0;return[be,tt,rt]}),F=_?$t(_.flat()):[0,1],oe=e?.y0&&e?.y1&&!e.y?Se([X].flat()):Se([0,F[0]]),a=le([!e.y0&&!e.y1&&0,le([Y,o[1]].flat())]);D=[oe,a]}}return D},[s,e,P,I,Ee,j,$?.current]),se=f(()=>C?.original&&!C?.current?C?.original:Z?Ne(Z):[0,1],[Z,C]);Oe(()=>{W(t=>({...t,domain:se}))},[se]);let pe=f(()=>t=>e?.y0&&n?.yScale&&n.yScale(e.y0(t)),[n,e]),ye=f(()=>t=>e?.y1&&n?.yScale&&n.yScale(e.y1(t)),[n,e]),De=f(()=>We().x(t=>n?.xScale(t.x)).y0(t=>n?.yScale?.(t.y0)).y1(t=>n?.yScale?.(t.y1)).defined(t=>{let o=t,D=Ae(o.x)?o.x.valueOf():o.x,Y=typeof D<"u"&&typeof o.y0<"u"&&typeof o.y1<"u",X=!Number.isNaN(D)&&!Number.isNaN(o.y0)&&!Number.isNaN(o.y1);return Y&&X}).curve(x),[x,n,e,i,se]),xe=f(()=>We().x(t=>fe(t)).y0(t=>i?.y0?pe(t):n?.yScale(0)).y1(t=>i?.y1?ye(t):he(t)).defined(t=>{let o=e.x&&(Ae(e.x(t))?e.x(t)?.valueOf():e.x(t)),D=e.y0&&e.y1?e.y0(t):e.y&&e.y(t),Y=e.y0&&e.y1?e.y1(t):e.y&&e.y(t),X=typeof o<"u"&&typeof D<"u"&&D!==null&&typeof Y<"u"&&Y!==null,_=!Number.isNaN(o)&&!Number.isNaN(D)&&!Number.isNaN(Y);return X&&_}).curve(x||Xe),[x,e,i,n,se]),O={...{fillOpacity:1,strokeOpacity:1,strokeWidth:0},...k},Ve=f(()=>k?.style?.fillOpacity||k?.style?.opacity||k?.opacity||k?.fillOpacity,[k]);Oe(()=>{z(t=>({...t,geoms:{...t.geoms,area:{position:s,fillOpacity:Ve,stroke:O.stroke,fill:O.fill,fillScale:te,strokeScale:re,groupAccessor:N??e?.fill??e?.group,usableGroups:I,y0:pe,y1:ye,strokeWidth:O?.style?.strokeWidth||O?.strokeWidth,strokeOpacity:O?.style?.strokeOpacity||O?.strokeOpacity,strokeDasharray:O?.style?.strokeDasharray||O?.strokeDasharray}}}))},[Ve,z,k,s,P,N,te,re]);let Re=f(()=>P?!!j:!0,[j,P]),et=f(()=>t=>j?j.filter(D=>D.group===t):[],[j,n,e,s]);return!H&&!me&&!ce&&Re?K.createElement(K.Fragment,null,d&&I&&N?I.map(t=>{let o=d.filter(a=>N(a)===t),D=et(t),Y=te&&e?.fill?Array.from(new Set(o.map(a=>e.fill&&e.fill(a)))):void 0,X=O.fill||te&&te(t)||(m?.fillScale?m.fillScale(t):ke);Y&&te&&Y.forEach(a=>{X=te(a)});let _=re&&e?.stroke?Array.from(new Set(o.map(a=>e.stroke&&e.stroke(a)))):void 0,F=O.stroke||re&&re(t)||(m?.strokeScale?m.strokeScale(t):ee);_&&re&&_.forEach(a=>{F=re(a)});let oe=O.strokeDasharray||(m?.strokeDasharrayScale?m.strokeDasharrayScale(t):void 0);return K.createElement(Pt,{key:`${T}-${t}`,start:{path:P?De(D):xe(o),fill:"transparent",stroke:"transparent",strokeOpacity:0,fillOpacity:0},enter:()=>{let a=P?De(D):xe(o);return{path:v?[a]:a,fill:X,stroke:F,fillOpacity:v?[O.fillOpacity]:O.fillOpacity,strokeOpacity:v?[O.strokeOpacity]:O.strokeOpacity,timing:{duration:S,ease:Ge}}},update:()=>{let a=P?De(D):xe(o);return{path:v?[a]:a,fill:X,stroke:F,fillOpacity:v?[O.fillOpacity]:O.fillOpacity,strokeOpacity:v?[O.strokeOpacity]:O.strokeOpacity,timing:{duration:S,ease:Ge}}},leave:()=>({fill:v?["transparent"]:"transparent",stroke:v?["transparent"]:"transparent",timing:{duration:S,ease:Ge}}),interpolation:(a,ie,be)=>be==="path"?Mt(a,ie):wt(a,ie)},a=>K.createElement("path",{...k,d:a.path,fill:a.fill,fillOpacity:a.fillOpacity,stroke:a.stroke,strokeOpacity:a.strokeOpacity,strokeWidth:O.strokeWidth,strokeDasharray:oe,style:{pointerEvents:"none",...O?.style},"data-testid":"__gg_geom_area",clipPath:`url(#__gg_canvas_${U})`}))}):K.createElement(K.Fragment,null),(A||w)&&K.createElement(K.Fragment,null,K.createElement(Gt,{data:d,aes:e,group:"x",x:fe,y:()=>0,onDatumFocus:r,onMouseLeave:()=>{g&&g()},onClick:b?({d:t,i:o})=>{b(t,o)}:void 0,showTooltip:A,brushAction:w,customYExtent:se,getYValExtent:Ne}),A&&K.createElement(K.Fragment,null,M&&K.createElement(de,{x:fe,y:he,y0:pe,y1:ye,aes:e,markerRadius:G,markerStroke:p,stackedData:j,position:s}),K.createElement(ve,{x:fe,y:he,y0:pe,y1:ye,aes:e,geomID:T,position:s})))):null};Ke.displayName="GeomArea";import Ze from"react";import{useGG as Ut,themeState as Zt,LegendOrientation as qt}from"@graphique/graphique";import{useAtom as Jt}from"jotai";import ae,{useState as Wt,useEffect as Xt,useMemo as Be}from"react";import{useGG as Kt,themeState as Bt,fillScaleState as Ht,formatMissing as jt,LegendOrientation as He}from"@graphique/graphique";import{useAtom as je}from"jotai";var Ue=({legendData:l,legendScales:i,orientation:w=He.V,labelFormat:x,fontSize:r=12,onSelection:b})=>{let[g,k]=Wt(i.groups||i.fillScale?.domain()||[]),[{geoms:A,defaultFill:M,legend:G}]=je(Bt),[{domain:p}]=je(Ht),s=Be(()=>p||i.groups||i.fillScale?.domain(),[p,i]),{ggState:v,updateData:u}=Kt()||{},{scales:U,data:V}=v||{};Xt(()=>{k(U?.groups||[])},[U,V]);let L=Be(()=>U.groupAccessor||void 0,[U]),n=w===He.H,m=c=>{let z=g,h;z.includes(c)?z.length===1?h=s:h=z.filter(E=>E!==c):h=[...z,c],k(h);let y=Array.from(new Set(V?.map(E=>L?L(E):void 0)));if(b&&b(c),V&&u&&L){let E;y.includes(c)?y.length===1?E=l:E=V.filter(B=>L(B)!==c):E=l.filter(B=>y.includes(L(B))||L(B)===c),u(E)}};return ae.createElement("div",{style:{marginTop:8,display:"flex",flexDirection:n?"row":"column",flexWrap:"wrap",alignItems:n?"center":void 0}},A?.area&&s?.map((c,z,h)=>ae.createElement("div",{key:c,style:{display:"flex",alignItems:"center",marginBottom:n?6:2}},ae.createElement("div",{tabIndex:0,role:"button",style:{cursor:"pointer",marginRight:z<h.length-1&&n?12:2,fontSize:r,opacity:g.includes(c)?1:.5,transition:"opacity 200ms",display:"flex",alignItems:"center"},onKeyDown:y=>{["Enter"," "].includes(y.key)&&m(c)},onClick:()=>m(c)},ae.createElement("div",{style:{display:"flex",alignItems:"center",justifyContent:"center"}},ae.createElement("svg",{width:14,height:14},ae.createElement("rect",{width:14,height:14,fill:A?.area?.fill||(i.fillScale?i.fillScale(c):M),stroke:A?.area?.stroke||(i.strokeScale?i.strokeScale(c):"none"),strokeWidth:1.8,fillOpacity:g.includes(c)?A?.area?.fillOpacity:.5,strokeOpacity:g.includes(c)?A?.area?.strokeOpacity:.5,style:{transition:"fill-opacity 200ms"}}))),ae.createElement("div",{style:{marginLeft:4,fontSize:r,color:G?.labelColor??"currentcolor"}},x?x(c,z):jt(c))))))};var qe=({title:l,orientation:i=qt.V,format:w,onSelection:x,style:r})=>{let{ggState:b}=Ut()||{},{copiedScales:g,copiedData:k,aes:A}=b||{},[{font:M,geoms:G}]=Jt(Zt),{area:p}=G||{},{groups:s}=g||{},v=p?.fillScale||A?.fill||A?.stroke||A?.strokeDasharray,{fontSize:u}={...r};return v?Ze.createElement("div",{style:{marginTop:12,fontFamily:M?.family,...r}},l,k&&(g||p?.fillScale)&&(s||p?.usableGroups)?Ze.createElement(Ue,{legendData:k,orientation:i,legendScales:{...g,strokeScale:p?p.strokeScale:g?.strokeScale,fillScale:p?p.fillScale:g?.fillScale},labelFormat:w,fontSize:u,onSelection:x}):null):null};export{Ke as GeomArea,qe as Legend,Pe as Position};
//# sourceMappingURL=index.js.map