UNPKG

@graphique/geom-point

Version:

For points, scatterplots, and bubbles

2 lines 16.4 kB
import B,{useState as Vt,useEffect as pt,useMemo as I,useCallback as Et,useRef as ue}from"react";import{NodeGroup as ce}from"react-move";import{easeCubic as kt}from"d3-ease";import{scaleSqrt as me}from"d3-scale";import{extent as pe}from"d3-array";import{interpolate as fe}from"d3-interpolate";import{useAtom as at}from"jotai";import{useGG as de,focusNodes as Ft,unfocusNodes as ye,EventArea as ge,themeState as Se,radiusScaleState as xe,zoomState as be,xScaleState as ve,yScaleState as ke,isDate as Mt,defineGroupAccessor as It,usePageVisibility as he}from"@graphique/graphique";var Lt=(y=>(y.DATA="data",y.BOTTOM="bottom",y))(Lt||{}),Tt=(y=>(y.L="left",y.R="right",y))(Tt||{});import mt,{useMemo as st}from"react";import{useAtom as wt}from"jotai";import{useGG as ie,tooltipState as se,labelsState as ae,YTooltip as le}from"@graphique/graphique";import M,{useState as Qt,useEffect as Rt}from"react";import{useAtom as At}from"jotai";import{labelsState as te,TooltipContainer as ee,formatMissing as oe,themeState as ne,nodeToString as re}from"@graphique/graphique";var Pt=({data:r})=>{let[{x:s,y}]=At(te),[{tooltip:f}]=At(ne),[i,L]=Qt("");return Rt(()=>{let d=setTimeout(()=>L(re(y)));return()=>clearTimeout(d)},[y]),r?M.createElement(ee,null,r.map(d=>{let S=oe(d.group);return M.createElement("div",{key:`group-tooltip-${d.label||S}`},M.createElement("div",{style:{marginTop:4,marginBottom:4}},(d.label||d.group!=="__group")&&M.createElement(M.Fragment,null,d.mark,M.createElement("div",{style:{display:"flex",alignItems:"flex-end",fontWeight:500}},M.createElement("div",{style:{marginBottom:4}},M.createElement("span",{style:{fontSize:f?.groupLabel?.fontSize||f?.font?.size}},d.formattedMeasure||S)))),M.createElement("div",{style:{display:"flex",marginBottom:2}},s&&M.createElement("div",{style:{fontSize:f?.xLabel?.fontSize||f?.font?.size}},`${s}:`),M.createElement("div",{style:{marginLeft:1,fontWeight:500,fontSize:f?.xLabel?.fontSize||(f?.font?.size||12)+1}},d.formattedX)),M.createElement("div",{style:{display:"flex"}},i&&M.createElement("div",{style:{fontSize:f?.yLabel?.fontSize||f?.font?.size}},`${i}:`),M.createElement("div",{style:{marginLeft:1,fontWeight:500,fontSize:f?.yLabel?.fontSize||(f?.font?.size||12)+1}},d.formattedY))))})):null};var vt=({aes:r,group:s})=>{let{ggState:y}=ie()||{},{id:f,scales:i,height:L,width:d}=y||{width:0,height:0},[{datum:S,position:k,xFormat:G,yFormat:z,measureFormat:T,content:V}]=wt(se),[{x:u,y:C}]=wt(ae),l=st(()=>S&&S[0],[S]),o=st(()=>{let g={given:l&&r?.label&&r.label(l),keyed:l&&r?.key&&r.key(l)};return g?.given||g?.keyed},[r,l]),h=i?.xScale,n=i?.yScale,P=st(()=>i?.xScale.bandwidth?i?.xScale.bandwidth()/2:0,[i]),c=st(()=>i?.yScale?.bandwidth?i.yScale.bandwidth()/2:0,[i]),D=st(()=>l&&s&&s(l),[l,s]),b=[{x:l&&r?.x&&h&&h(r.x(l)),y:l&&r?.y&&n&&n(r.y(l)),xLab:u,yLab:C,formattedX:l&&r?.x&&(G?G(r.x(l)):r.x(l)),formattedY:l&&r?.y&&(z?z(r.y(l)):r.y(l)),group:D,label:o,formattedMeasure:T&&(o||String(D))&&T(o||D),datum:S,containerWidth:d}],E=V?l&&mt.createElement("div",null,V(b)):l&&mt.createElement(Pt,{data:b});return l&&b[0].x!==void 0&&b[0].y!==void 0?mt.createElement("div",null,mt.createElement(le,{id:f,left:(b[0].x||0)+P,top:k==="data"?-(L-(b[0].y||0)-c):-L,value:E})):null};var _t=({data:r,aes:s,focusedStyle:y,unfocusedStyle:f,attr:i,focusedKeys:L=[],onDatumFocus:d,onDatumSelection:S,entrance:k="bottom",onExit:G,showTooltip:z=!0,brushAction:T,isClipped:V=!1,isAnimated:u=!0})=>{let{ggState:C}=de()||{},{id:l,data:o,aes:h,scales:n,copiedScales:P,height:c,margin:D}=C||{},[b,E]=at(Se),[m]=at(xe),[{xDomain:g,yDomain:F}]=at(be),[{isFixed:Y}]=at(ve),[{isFixed:p}]=at(ke),x=he(),a={...{r:3.5,fillOpacity:1,strokeOpacity:1},...i},{domain:X,range:ot}=m||{},{defaultFill:Q,animationDuration:q}=b,_=I(()=>r||o,[o,r]),e=I(()=>s?{...h,...s}:h,[h,s]),O=I(()=>e&&It(e),[e,It]),j=Et(t=>`${e?.x&&e.x(t)}-${e?.y&&e.y(t)}-${O&&O(t)}`,[e,O]),$=Et(t=>e?.key?e.key(t):j(t),[e,O,j]),Z=I(()=>_?_.filter(t=>e?.x&&(e.x(t)===null||typeof e.x(t)>"u"||Mt(e.x(t))&&Number.isNaN(e.x(t)?.valueOf()))):[],[_,e]),W=I(()=>_?_.filter(t=>e?.y&&(e.y(t)===null||typeof e.y(t)>"u")):[],[_]),U=I(()=>L.filter(t=>t),[L]),K=I(()=>{let t=_?.filter(w=>e?.x&&e?.x(w)!==null&&!(typeof e?.x(w)>"u")&&(Mt(e?.x(w))?!Number.isNaN(e?.x(w)?.valueOf()):!0)&&e.y&&e.y(w)!==null&&!(typeof e.y(w)>"u"));return Array.from(new Set(t?.map(w=>$(w)))).flatMap(w=>{let N=t?.filter(bt=>$(bt)===w);return N&&N.length>1?N.map((bt,Jt)=>({...bt,gg_gen_index:Jt})):N?.flat()})},[_,$]),Xt=I(()=>K.map(j).join(""),[K,j]),[ut,Zt]=Vt(!0);pt(()=>{let t=setTimeout(()=>Zt(!1),0);return()=>clearTimeout(t)},[]),pt(()=>{ut&&Z.length>0&&console.warn(`Ignoring ${Z.length} points with missing x values.`),ut&&W.length>0&&console.warn(`Ignoring ${W.length} points with missing y values.`)},[ut,Z,W]);let gt=I(()=>c&&D?c-D.bottom:void 0,[c,D]);pt(()=>{E(t=>({...t,geoms:{...t.geoms,point:{fillOpacity:a.style?.fillOpacity||a.fillOpacity,stroke:a.stroke,strokeWidth:a.style?.strokeWidth||a.strokeWidth,strokeOpacity:a.style?.strokeOpacity||a.strokeOpacity,size:e?.size}}}))},[i,E]);let ct={transition:"fill-opacity 200ms",fillOpacity:a.fillOpacity,strokeOpacity:a.strokeOpacity,...a.style},St={...ct,...y},xt={...ct,fillOpacity:.2,strokeOpacity:.2,...f},nt=I(()=>t=>a.fill||(e?.fill&&P?.fillScale?P.fillScale(e.fill(t)):Q),[e,P,a,Q]),rt=I(()=>t=>a.stroke||(e?.stroke&&P?.strokeScale?P.strokeScale(e.stroke(t)):"none"),[e,P,a]),H=I(()=>{if(K&&e?.size&&ot){let t=X&&X[0]&&X[1]?X:pe(K,e.size);return me().domain(t).range(ot).unknown([a.r])}return()=>a.r},[a,e,K,ot,X]),R=I(()=>n?.xScale.bandwidth?t=>(n?.xScale(e?.x&&e.x(t))||0)+n?.xScale.bandwidth()/2+.9:t=>n?.xScale&&e?.x&&(n.xScale(e.x(t))||0),[n,e]),tt=I(()=>n?.yScale.bandwidth?t=>(n?.yScale(e?.y&&e.y(t))||0)+n?.yScale.bandwidth()/2:t=>n?.yScale&&e?.y&&(n.yScale(e.y(t))||0),[n,e]),zt=ue(null),it=zt.current?.getElementsByTagName("circle"),[Ut,Ct]=Vt(V||Y||p);return pt(()=>{if(g?.current||F?.current)Ct(!0);else{let t=setTimeout(()=>Ct(V),q);return()=>clearTimeout(t)}},[Y,p,g?.current,F?.current,q]),B.createElement(B.Fragment,null,B.createElement("g",{ref:zt,clipPath:Ut?`url(#__gg_canvas_${l})`:void 0},!ut&&x&&B.createElement(ce,{data:[...K],keyAccessor:t=>e?.key?$(t):`${$(t)}-${t.gg_gen_index}`,start:t=>({cx:R(t),cy:k==="data"?tt(t):gt,fill:nt(t),stroke:rt(t),r:0,fillOpacity:0,strokeOpacity:0}),enter:t=>({cx:u?[R(t)]:R(t),cy:u?[tt(t)]:tt(t),r:u?[i?.r??(e?.size?H(e.size(t)):H(t))]:i?.r??(e?.size?H(e.size(t)):H(t)),fill:u?[nt(t)]:nt(t),stroke:u?[rt(t)]:rt(t),fillOpacity:u?[a.fillOpacity]:a.fillOpacity,strokeOpacity:u?[a.strokeOpacity]:a.strokeOpacity,timing:{duration:q,ease:kt}}),update:t=>({cx:u?[R(t)]:R(t),cy:u?[tt(t)]:tt(t),r:u?[i?.r??(e?.size?H(e.size(t)):H(t))]:i?.r??(e?.size?H(e.size(t)):H(t)),fill:u?[nt(t)]:nt(t),stroke:u?[rt(t)]:rt(t),fillOpacity:u?[a.fillOpacity]:a.fillOpacity,strokeOpacity:u?[a.strokeOpacity]:a.strokeOpacity,timing:{duration:q,ease:kt}}),leave:()=>({fill:u?["transparent"]:"transparent",stroke:u?["transparent"]:"transparent",cy:u?[gt]:gt,timing:{duration:q,ease:kt}}),interpolation:(t,A)=>fe(t,A)},t=>B.createElement(B.Fragment,null,t.map(({state:A,key:w})=>{let N={};return U.includes(w)&&(N=St),U?.length>0&&!U.includes(w)&&(N=xt),B.createElement("circle",{key:w,...i,r:A.r>=0?A.r:a.r,fill:A.fill,stroke:A.stroke,cx:A.cx,cy:A.cy,fillOpacity:A.fillOpacity,strokeOpacity:A.strokeOpacity,style:{pointerEvents:"none",...ct,...N},"data-testid":"__gg_geom_point"})})))),(z||T)&&e&&B.createElement(B.Fragment,null,B.createElement(ge,{data:K,showTooltip:z,brushAction:T,aes:e,x:R,y:tt,onDatumFocus:d,onMouseOver:({i:t})=>{let A=K.flatMap((w,N)=>U.includes($(w))?N:[]);it&&Ft({nodes:it,focusedIndex:[...A,...[t].flat()],focusedStyles:St,unfocusedStyles:xt})},onClick:S?({d:t,i:A})=>{S(t,A)}:void 0,onMouseLeave:()=>{it&&(ye({nodes:it,baseStyles:ct}),U&&U.length&&Ft({nodes:it,focusedIndex:K.flatMap((t,A)=>U.includes($(t))?A:[]),focusedStyles:St,unfocusedStyles:xt})),G&&G()},positionKeys:Xt}),z&&B.createElement(vt,{aes:e,group:O})))};_t.displayName="GeomPoint";import Ot from"react";import{useGG as $e,themeState as Be,LegendOrientation as Ne}from"@graphique/graphique";import{useAtom as je}from"jotai";import J,{useState as De,useEffect as Oe}from"react";import{useGG as Ge,themeState as ze,fillScaleState as Ce,strokeScaleState as Le,formatMissing as Te}from"@graphique/graphique";import{useAtom as ht}from"jotai";var $t=({legendData:r,legendScales:s,orientation:y,labelFormat:f,fontSize:i=12,onSelection:L})=>{let[d,S]=De(s.groups||[]),[{geoms:k,legend:G}]=ht(ze),[{domain:z}]=ht(Ce),[{domain:T}]=ht(Le),V=z||T||s.groups,{ggState:u,updateData:C}=Ge()||{},{scales:l,data:o}=u||{};Oe(()=>{S(l?.groups||[])},[l,o]);let h=s.groupAccessor?s.groupAccessor:()=>s.groups&&s.groups[0],n=y==="horizontal",P=c=>{let D=d,b;D.includes(c)?D.length===1?b=s.groups:b=D.filter(m=>m!==c):b=[...D,c],S(b);let E=Array.from(new Set(o?.map(m=>h(m))));if(L&&L(c),o&&C){let m;E.includes(c)?E.length===1?m=r:m=o.filter(g=>h(g)!==c):m=r.filter(g=>E.includes(h(g))||h(g)===c),C(m)}};return J.createElement("div",{style:{marginTop:8,display:"flex",flexDirection:n?"row":"column",flexWrap:"wrap",alignItems:n?"center":void 0}},k?.point?.fillOpacity&&V?.map((c,D,b)=>J.createElement("div",{key:c,style:{display:"flex",alignItems:"center",marginBottom:n?6:2}},J.createElement("div",{tabIndex:0,role:"button",style:{cursor:"pointer",marginRight:D<b.length-1&&n?12:2,fontSize:i,opacity:d.includes(c)?1:.5,transition:"opacity 200ms",display:"flex",alignItems:"center"},onKeyPress:E=>{["Enter"," "].includes(E.key)&&P(c)},onClick:()=>P(c)},J.createElement("div",{style:{display:"flex",alignItems:"center",justifyContent:"center"}},J.createElement("svg",{width:12,height:12},J.createElement("circle",{r:4,cx:6,cy:6,fill:k?.point?.fill||(s.fillScale?s.fillScale(c):"none"),stroke:k?.point?.stroke||(s.strokeScale?s.strokeScale(c):"none"),strokeWidth:1.8,fillOpacity:d.includes(c)?k?.point?.fillOpacity:.5,strokeOpacity:d.includes(c)?k?.point?.strokeOpacity:.5,style:{transition:"fill-opacity 200ms"}}))),J.createElement("div",{style:{marginLeft:4,fontSize:i,color:G?.labelColor??"currentcolor"}},f?f(c,D):Te(c))))))};import et,{useCallback as Ae,useEffect as Bt,useState as Pe,useRef as lt}from"react";import{useAtom as Dt}from"jotai";import{themeState as we,fillScaleState as Ve,strokeScaleState as Ee}from"@graphique/graphique";import{interpolateRound as Fe}from"d3-interpolate";import{select as ft}from"d3-selection";import{axisBottom as Nt}from"d3-axis";import{range as Me,quantile as Ie}from"d3-array";import{transition as _e}from"d3-transition";var jt=({scales:r,tickFormat:s,width:y,tickSize:f=6,height:i=30+f,margin:L,numTicks:d,fontSize:S=10})=>{let k=lt(null),G=lt(null),z=lt(null),T=lt(null),V=lt(null),u=r?.fillScale||r?.strokeScale,[{geoms:C,font:l,legend:o,animationDuration:h}]=Dt(we),[{reverse:n}]=Dt(Ve),[{reverse:P}]=Dt(Ee),[c,D]=Pe(!0);Bt(()=>{let F=setTimeout(()=>D(!1),0);return()=>clearTimeout(F)},[]);let b=n||P,E=256,m={top:4,right:0,bottom:16+f,left:0,...L},g=Ae((F,Y)=>{if(k.current&&G.current&&z.current&&T.current&&V.current){let p=(O,j,$)=>{let Z=O.getContext("2d");for(let W=0;W<$;W+=1)Z&&j&&(Z.fillStyle=j(W/($-1)),Z.fillRect(b?$-W:W,0,1,1));return O},x=h??1e3,v,a,X=O=>O.selectAll(".tick line").attr("y1",m.top+m.bottom-i),ot=ft(G.current),Q=ft(z.current),q=ft(T.current),_=ft(V.current),e=_e().duration(x);if(!F?.interpolate){if(F?.interpolator){if(v=Object.assign(F.copy().interpolator(Fe(m.left,y-m.right)),{range(){return[m.left,y-m.right]}}),_.attr("x",m.left).attr("y",m.top).attr("width",y-m.left-m.right).attr("height",i-m.top-m.bottom).attr("preserveAspectRatio","none").attr("xlink:href",p(G.current,F.interpolator(),E).toDataURL()),c&&_.style("opacity",0).transition(e).style("opacity",r?.fillScale&&C?.point?.fillOpacity||r?.strokeScale&&C?.point?.strokeOpacity||void 0),!v.ticks&&a===void 0){let O=Math.round(d+1);a=Me(O).map(j=>Ie(F.domain(),j/(O-1)))}ot.remove()}}b&&v.domain(v.domain().reverse()),Q.attr("transform",`translate(0,${i-m.bottom})`).transition(e).call(Nt(v).ticks(d,typeof s=="string"?s:void 0).tickFormat(typeof s=="function"?s:void 0).tickSize(f).tickValues(a)),Q.call(O=>O.select(".domain").remove()).selectAll("line").attr("stroke",o?.tickColor||"currentColor").style("opacity",o?.tickColor?1:.85),Q.selectAll(".tick").select("text").style("font-family",Y||"sans-serif").style("font-size",S).attr("fill",o?.labelColor||"currentColor").style("opacity",o?.labelColor?1:.85),q.attr("transform",`translate(0,${i-m.bottom})`).transition(e).call(Nt(v).ticks(d,typeof s=="string"?s:void 0).tickSize(1).tickFormat(()=>"")).selectAll("line").attr("stroke","#111"),q.call(O=>O.select(".domain").remove()).call(O=>O.selectAll(".tick").select("text").remove()).call(X)}},[y,i,d,s,f,m,o,C,r,S,c,b,h]);return Bt(()=>{g(u,l?.family)},[l,u,g]),et.createElement("div",null,l?.family&&et.createElement("svg",{ref:k,width:y,height:i,viewBox:`0 0 ${y} ${i}`,style:{overflow:"visible",display:"block"}},et.createElement("image",{ref:V}),et.createElement("g",{ref:z}),et.createElement("g",{ref:T})),et.createElement("canvas",{ref:G,width:E,height:1}))};var Wt=({title:r,style:s,orientation:y=Ne.V,format:f,width:i=320,numTicks:L=i/64,onSelection:d})=>{let{ggState:S}=$e()||{},{copiedScales:k,copiedData:G,aes:z}=S||{},[{font:T}]=je(Be),{groups:V}=k||{},u=z?.fill||z?.stroke,{fontSize:C}={...s};return u?Ot.createElement("div",{style:{fontFamily:T?.family,...s}},r,G&&k&&V?Ot.createElement($t,{legendData:G,orientation:y,legendScales:k,labelFormat:f,fontSize:C,onSelection:d}):Ot.createElement(jt,{scales:k,tickFormat:f,numTicks:L,fontSize:C,width:i})):null};import dt,{useEffect as Kt,useState as We,useMemo as yt,useRef as Ke}from"react";import{useAtom as Yt}from"jotai";import{select as Gt}from"d3-selection";import{extent as qt,max as Ye}from"d3-array";import{useGG as qe,radiusScaleState as He,themeState as Xe}from"@graphique/graphique";import{scaleSqrt as Ze}from"d3-scale";import{transition as Ue}from"d3-transition";var Ht=({labelDirection:r="right",radiiVals:s,width:y=120,numCircles:f=3,format:i,style:L,title:d})=>{let[{domain:S,range:k}]=Yt(He)||{},[{font:G,animationDuration:z,geoms:T}]=Yt(Xe)||{},{ggState:V}=qe()||{},{data:u}=V||{},C=Ke(null),l=yt(()=>S&&S[0]&&S[1]?S:u&&T?.point?.size?qt(u,T.point.size):[],[u,T,S]),o=yt(()=>Ze().domain(l).range(k),[l,k]),h=yt(()=>{let g=o.ticks();return(s||(f===3?[g[0],g[3],g[g.length-1]]:qt(g))).filter(F=>F>=l[0])},[s,f,o]),n=yt(()=>Ye(h)||0,[h]),{fontSize:P,color:c}={...L},[D,b]=We(!0);Kt(()=>{let g=setTimeout(()=>b(!1),5);return()=>clearTimeout(g)},[]),Kt(()=>{let g=h.map(p=>({value:p,r:o(p)<0?0:o(p)})),F=z??1e3,Y=Ue().duration(F);Gt(C.current).selectAll("circle").attr("fill","transparent").attr("stroke","currentColor").style("opacity",.6).attr("stroke-width",1.5).attr("stroke-dasharray","0.05 4").attr("stroke-linecap","round").attr("cx",0).data(g,(p,x)=>x).join(p=>p.append("circle").attr("r",0).attr("cy",o(n)),p=>p.call(x=>x.transition(Y).attr("r",v=>v.r).attr("cy",v=>v.value===n?0:o(n)-v.r))),Gt(C.current).selectAll("line").attr("stroke","currentColor").attr("x1",(p,x)=>r==="right"?p.r/2+(x+15)*.5-(x+1)*2:-(p.r/2+(x+15)*.5-(x+1)*2)).attr("x2",r==="right"?o(n)+15:-o(n)-12).data(g,(p,x)=>x).join(p=>p.append("line").attr("y1",o(n)).attr("y2",o(n)).style("opacity",0),p=>p.call(x=>x.transition(Y).attr("x1",(v,a)=>r==="right"?v.r/2+(a+15)*.5-(a+1)*2:-(v.r/2+(a+15)*.5-(a+1)*2)).attr("y1",v=>o(n)-2*v.r+3).attr("y2",v=>o(n)-2*v.r+3).style("opacity",.25))),Gt(C.current).selectAll("text").data(g,(p,x)=>x).attr("x",r==="right"?o(n)+18:-o(n)-15).style("font-size",P||10).attr("dominant-baseline","central").attr("text-anchor",r==="right"?"start":"end").attr("fill",c||"currentColor").text((p,x)=>i?i(p.value,x):p.value.toLocaleString()).join(p=>p.append("text").attr("y",o(n)).style("opacity",0),p=>p.call(x=>x.transition(Y).attr("x",r==="right"?o(n)+18:-o(n)-15).attr("y",v=>o(n)-2*v.r+3).style("opacity",.85)))},[D,o,h,G,i,r,n,P,c,z]);let E=r==="right"?o(n)+2:y-o(n)-2,m=o(n)+2;return o.domain()[0]&&o.domain()[1]?dt.createElement("div",{style:{fontFamily:G?.family,...L}},d,dt.createElement("div",{style:{marginTop:8}},dt.createElement("svg",{height:o(n)*2+4,width:y},dt.createElement("g",{style:{transform:`translate(${E}px, ${m}px)`},ref:C})))):null};export{Lt as Entrance,_t as GeomPoint,Wt as Legend,Tt as SizeLabelDirection,Ht as SizeLegend}; //# sourceMappingURL=index.js.map