UNPKG

@graphique/geom-label

Version:

For creating labels based on data in Graphique

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