@graphysdk/geom-boxplot 0.1.1-beta.1794327284843 → 0.1.1-beta.1794395798194
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1 -1
- package/dist/index.mjs +227 -173
- package/dist/renderer/utils/box-geometry.d.ts +0 -2
- package/dist/utils/read-boxplot.d.ts +2 -2
- package/package.json +4 -4
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});let a=require("@graphysdk/react"),S=require("react"),f=require("react/jsx-runtime");var x={q1:"boxplotQ1",median:"boxplotMedian",q3:"boxplotQ3",lowerWhisker:"boxplotLowerWhisker",upperWhisker:"boxplotUpperWhisker",count:"boxplotCount",mean:"boxplotMean",notchLower:"boxplotNotchLower",notchUpper:"boxplotNotchUpper",relativeWidth:"boxplotRelativeWidth",outlier:"boxplotOutlier"},B=e=>(e.start+e.end)/2,$=(e,t)=>{const r=t==="x"?(0,a.getXMin)(e):(0,a.getYMin)(e),o=t==="x"?(0,a.getXMax)(e):(0,a.getYMax)(e),n=t==="x"?(0,a.getYMin)(e):(0,a.getXMin)(e),s=t==="x"?(0,a.getYMax)(e):(0,a.getXMax)(e),i=(0,a.getScaledAesthetic)(e,"q1"),u=(0,a.getScaledAesthetic)(e,"median"),c=(0,a.getScaledAesthetic)(e,"q3");if(r===null||o===null||n===null||s===null||u===null||i===null||c===null)return null;const l=T(e,"notchLower"),d=T(e,"notchUpper"),[m,k]=ne(r,o,e);return{observation:e,start:m,end:k,lowerWhisker:n,q1:i,median:u,q3:c,upperWhisker:s,mean:T(e,"mean"),notch:l===null||d===null?null:{lower:l,upper:d}}},X=(e,t)=>{const r=t==="x"?(0,a.getXMin)(e):(0,a.getYMin)(e),o=t==="x"?(0,a.getXMax)(e):(0,a.getYMax)(e),n=(0,a.getScaledAesthetic)(e,"outlier");return r===null||o===null||n===null?null:{observation:e,band:B({start:r,end:o}),value:n}},W=(e,t)=>{const r=[],o=[];for(const n of e){const s=$(n,t);if(s!==null){r.push(s);continue}const i=X(n,t);i!==null&&o.push(i)}return{boxes:r,outliers:o}},T=(e,t)=>(0,a.getScaledAesthetic)(e,t)??null,ne=(e,t,r)=>{const o=r[x.relativeWidth];if(typeof o!="number")return[e,t];const n=(e+t)/2,s=(t-e)*o/2;return[n-s,n+s]},b=1.5,F=e=>e==="min-max"||typeof e=="number"&&Number.isFinite(e)&&e>=0,ae=1.58,se=(e,t)=>{if(e.length===0)return null;const r=[...e].sort((m,k)=>m-k),o=_(r,.25),n=_(r,.5),s=_(r,.75),i=t==="min-max"?1/0:t*(s-o),u=o-i,c=s+i,l=r.filter(m=>m>=u&&m<=c),d=ae*(s-o)/Math.sqrt(e.length);return{lowerWhisker:Math.min(l[0]??o,o),q1:o,median:n,q3:s,upperWhisker:Math.max(l[l.length-1]??s,s),count:e.length,mean:r.reduce((m,k)=>m+k,0)/r.length,notchLower:n-d,notchUpper:n+d}},_=(e,t)=>{const r=(e.length-1)*t,o=Math.floor(r),n=e[o]??0;return n+((e[o+1]??n)-n)*(r-o)},H={q1:x.q1,median:x.median,q3:x.q3,lowerWhisker:x.lowerWhisker,upperWhisker:x.upperWhisker,count:x.count,outlier:x.outlier},z=new Set([...Object.keys(H),"mean","notchLower","notchUpper"]),ie=class extends a.Stat{constructor(...e){super(...e),this.type="boxplot",this.computedAesthetics=z}computeStat({data:e,mapping:t,params:r}){const o=(0,a.readVariableName)(t.x),n=(0,a.readVariableName)(t.y);if(o===null||n===null||!e.hasVariable(o)||!e.hasVariable(n))return{data:e,mapping:{}};if(e.size()>0&&e.getType(n)!=="numeric"){const i=e.getType(n);throw new a.UserInputError({code:"INCOMPATIBLE_TYPE",message:`'boxplot' stat requires a numeric 'y' (got '${i}' for variable '${n}')`,context:{aesthetic:"y",variableName:n,variableType:i},suggestion:"Map the raw values to 'y', or summarised columns under stat 'identity'."})}const s=r?.extent;return{data:le({data:e,xVariable:o,yVariable:n,groupVariables:(0,a.getGroupVariables)(e,t).filter(i=>i!==o),extent:F(s)?s:b}),mapping:H}}},le=({data:e,xVariable:t,yVariable:r,groupVariables:o,extent:n})=>{const s=ue(e,t,r,o),i=e.getVariableNames(),u=new Map(i.map(p=>[p,e.getValues(p)])),c=new Map(i.map(p=>[p,[]])),l={q1:[],median:[],q3:[],lowerWhisker:[],upperWhisker:[],count:[],mean:[],notchLower:[],notchUpper:[],outlier:[]},d=[];for(const p of s){const v=se(p.values,n);if(v===null)continue;for(const h of i)c.get(h)?.push(ce(u.get(h)??[],p.indices));l.q1.push(v.q1),l.median.push(v.median),l.q3.push(v.q3),l.lowerWhisker.push(v.lowerWhisker),l.upperWhisker.push(v.upperWhisker),l.count.push(v.count),l.mean.push(v.mean),l.notchLower.push(v.notchLower),l.notchUpper.push(v.notchUpper),l.outlier.push(null);const w={low:v.lowerWhisker,high:v.upperWhisker};p.indices.forEach((h,y)=>{const M=p.values[y];M!==void 0&&(M<w.low||M>w.high)&&d.push({index:h,value:M})})}for(const{index:p,value:v}of d){for(const w of i)c.get(w)?.push(u.get(w)?.[p]??null);l.q1.push(null),l.median.push(null),l.q3.push(null),l.lowerWhisker.push(null),l.upperWhisker.push(null),l.count.push(null),l.mean.push(null),l.notchLower.push(null),l.notchUpper.push(null),l.outlier.push(v)}const m=e.getValueFormat(r),k=Object.fromEntries(i.map(p=>[p,{type:e.getType(p),values:c.get(p)??[],valueFormat:e.getValueFormat(p)}]));for(const[p,v]of Object.entries(l)){const w=x[p];k[w]=p==="count"?{type:"numeric",values:v}:{type:"numeric",values:v,valueFormat:m}}return new a.Dataset(k,e.parsingLocale)},ue=(e,t,r,o)=>{const n=[t,...o].map(u=>e.getValues(u)),s=e.getValues(r,{type:"numeric"}),i=new Map;return s.forEach((u,c)=>{if(u===null||!Number.isFinite(u))return;const l=n.map(m=>V(m[c]??null)).join("\0"),d=i.get(l)??{indices:[],values:[]};d.indices.push(c),d.values.push(u),i.set(l,d)}),[...i.values()]},ce=(e,t)=>{const r=e[t[0]??-1]??null,o=V(r);return t.every(n=>V(e[n]??null)===o)?r:null},V=e=>e===null?"\0null":e instanceof Date?`date:${e.getTime()}`:`${typeof e}:${String(e)}`,Y=.6,he=1,de=2,pe=1.5,me=7,ve=1,ge=7,fe=1.5,ke=["q1","median","q3"],ye={strokeWidth:"pixels"},q={stroke:"color",alpha:"unitInterval",strokeWidth:"pixels",dashArray:"dashArray"},C={fill:"color",fillAlpha:"unitInterval",stroke:"color",alpha:"unitInterval",size:"pixels",strokeWidth:"pixels",symbol:"pointSymbol"},Q=class extends a.Geom{constructor(...e){super(...e),this.type="boxplot",this.defaultParams={extent:b,outliers:!0,notch:!1,showMean:!1,varwidth:!1},this.defaultStat=new ie,this.derivedVariables=Object.values(x),this.positionRoles=[{axis:"x",role:"point",valueKind:"value"},{axis:"y",role:"min",valueKind:"value",aesthetic:"lowerWhisker"},{axis:"y",role:"max",valueKind:"value",aesthetic:"upperWhisker"},{axis:"y",role:"scalar",valueKind:"value",aesthetic:"q1"},{axis:"y",role:"scalar",valueKind:"value",aesthetic:"median"},{axis:"y",role:"scalar",valueKind:"value",aesthetic:"q3"},{axis:"y",role:"scalar",valueKind:"value",aesthetic:"outlier"},{axis:"y",role:"scalar",valueKind:"value",aesthetic:"mean"},{axis:"y",role:"scalar",valueKind:"value",aesthetic:"notchLower"},{axis:"y",role:"scalar",valueKind:"value",aesthetic:"notchUpper"}],this.aesthetics=[{kind:"visual",name:"color"},{kind:"data",name:"y"},{kind:"data",name:"count"}],this.defaultPosition="dodge",this.supportedPositions=["identity","dodge"],this.supportedCoordTypes=["cartesian","flip"],this.scaleConstraints={requireMainAxisBands:!0},this.grid={cartesian:{hideGridX:!0},flip:{hideGridX:!0}},this.legend={suppressWhenSingleItem:!0},this.spatialKind="rects",this.highlightStrategy="observationRerender",this.tooltip=[{key:"Upper whisker",aesthetic:"upperWhisker",optional:!0},{key:"Q3",aesthetic:"q3",optional:!0},{key:"Median",aesthetic:"median",optional:!0},{key:"Q1",aesthetic:"q1",optional:!0},{key:"Lower whisker",aesthetic:"lowerWhisker",optional:!0},{key:"Count",aesthetic:"count",optional:!0},{key:"Mean",aesthetic:"mean",optional:!0},{key:"Outlier",aesthetic:"outlier",optional:!0}],this.styleTarget=(0,a.defineGeomStyleTarget)({observation:{vocabulary:ye,aesthetics:{fill:"color"},rest:{fill:(0,a.token)("geom"),fillAlpha:1,stroke:(0,a.token)("geomBorder"),strokeWidth:he}},parts:{median:{vocabulary:q,rest:{stroke:(0,a.token)("graphBackground"),alpha:1,strokeWidth:de,dashArray:[]}},whisker:{vocabulary:q,aesthetics:{stroke:"color"},rest:{stroke:(0,a.token)("geom"),alpha:1,strokeWidth:pe,dashArray:[]}},cap:{vocabulary:q,aesthetics:{stroke:"color"},rest:{stroke:(0,a.token)("geom"),alpha:1,strokeWidth:0,dashArray:[]}},outlier:{vocabulary:C,aesthetics:{fill:"color"},rest:{fill:(0,a.token)("geom"),fillAlpha:1,stroke:(0,a.token)("graphBackground"),alpha:1,size:me,strokeWidth:ve}},mean:{vocabulary:C,aesthetics:{stroke:"color"},rest:{fill:(0,a.token)("graphBackground"),fillAlpha:1,stroke:(0,a.token)("geom"),alpha:1,size:ge,strokeWidth:fe}}}}),this.resolveBandFraction=t=>R(t),this.resolveValueSource=t=>t.median??{variable:x.median},this.validateMapping=({mapping:t,computedAesthetics:r})=>r.has("y")?[{code:"CONFLICTING_STAT_MAPPING",message:"boxplot geom draws a summary, not a single 'y'; use the 'boxplot' stat or 'identity'"}]:r.has("median")?[...[...z].filter(o=>t[o]!==void 0).map(o=>({code:"CONFLICTING_STAT_MAPPING",message:`boxplot stat computes '${o}' from 'y'; remove its mapping, or set the layer's stat to 'identity'`})),...t.y===void 0?[{code:"MISSING_AESTHETIC",message:"boxplot stat summarises 'y'; map it to the raw values"}]:[]]:ke.filter(o=>t[o]===void 0).map(o=>({code:"MISSING_AESTHETIC",message:`boxplot geom requires '${o}' when its data is already summarised`,context:{aesthetic:o}})),this.resolveAnchorPosition=(t,{coordSystem:r})=>{const o=(0,a.readMainAxis)(r),n=xe(t,o);return n===null?null:o==="x"?{x:n.band,y:n.value}:{x:n.value,y:n.band}}}resolveParams(e){const{extent:t,width:r,...o}=super.resolveParams(e);return{...o,extent:this.resolveExtent(t,e.diagnostics),...this.resolveWidth(r,e.diagnostics)}}compile({data:e,mapping:t,params:r}){const o=P(e,t.lowerWhisker),n=P(e,t.upperWhisker);if(o===null||n===null)return{data:e,mapping:{}};const{outliers:s,notch:i,showMean:u,varwidth:c}=r,l=P(e,t.outlier),d=s===!1&&l!==null?Se(e,l):e,m=P(d,t.count),k=R(r)/2;return{data:d.addVariable(x.relativeWidth,"numeric",c===!0&&m!==null?we(d,m):Me(d)).addVariable(a.POSITION_VARIABLES.yMin,"numeric",D(d,o,l)).addVariable(a.POSITION_VARIABLES.yMax,"numeric",D(d,n,l)).addConstantVariable(a.POSITION_VARIABLES.xMin,"numeric",-k).addConstantVariable(a.POSITION_VARIABLES.xMax,"numeric",k),mapping:{...t.y===void 0&&{y:t.median},...u===!0&&t.mean===void 0&&d.hasVariable(x.mean)&&{mean:x.mean},...i===!0&&t.notchLower===void 0&&d.hasVariable(x.notchLower)&&{notchLower:x.notchLower,notchUpper:x.notchUpper}}}}resolveExtent(e,t){return F(e)?e:(t?.addWarning({code:"INVALID_GEOM_PARAM",message:`Boxplot extent must be a non-negative number or 'min-max', got ${String(e)}; falling back to ${b}.`,context:{geom:this.type,param:"extent",expected:"extent >= 0 or 'min-max'",actual:String(e)},suggestion:"Set params.extent to a number of interquartile ranges, or 'min-max'."}),b)}resolveWidth(e,t){if(e===void 0)return{};const r=typeof e=="number"&&Number.isFinite(e)?e:null;if(r!==null&&r>0&&r<=1)return{width:r};const o=r!==null&&r>1?1:void 0;return t?.addWarning({code:"INVALID_GEOM_PARAM",message:`Boxplot width must be a fraction in (0, 1], got ${String(e)}; falling back to ${o??Y}.`,context:{geom:this.type,param:"width",expected:"0 < width <= 1",actual:r??String(e)},suggestion:"Set params.width to a fraction of the category band in (0, 1]."}),o!==void 0?{width:o}:{}}},xe=(e,t)=>{const r=$(e,t);if(r!==null)return{band:B(r),value:r.median};const o=X(e,t);return o===null?null:{band:o.band,value:o.value}},R=({width:e})=>e??Y,we=(e,t)=>{const r=e.getValues(t,{type:"numeric"}),o=Math.max(0,...r.map(n=>n??0));return r.map(n=>n===null||o===0?null:Math.sqrt(n/o))},Me=e=>Array.from({length:e.size()},()=>null),D=(e,t,r)=>{const o=r===null?[]:e.getValues(r,{type:"numeric"});return e.getValues(t,{type:"numeric"}).map((n,s)=>n??o[s]??null)},Se=(e,t)=>{const r=e.getValues(t,{type:"numeric"});return e.take(r.flatMap((o,n)=>o===null?[n]:[]))},P=(e,t)=>{const r=(0,a.readVariableName)(t);return r!==null&&e.hasVariable(r)?r:null},We=5e-4,Ie=.5,Oe=.5,Z=(e,t)=>{const r=(e.q1+e.q3)/2,o=Math.max(Math.abs(e.q3-e.q1),We)/2,n=g(t,e.start,r-o),s=g(t,e.end,r+o),[i,u]=K(n.x,s.x),[c,l]=K(n.y,s.y);return{x:i,y:c,width:u-i,height:l-c}},J=(e,t)=>{if(e.notch===null)return null;const{lower:r,upper:o}=e.notch,[n,s]=te(e);return[g(t,e.start,e.q1),g(t,e.start,r),g(t,n,e.median),g(t,e.start,o),g(t,e.start,e.q3),g(t,e.end,e.q3),g(t,e.end,o),g(t,s,e.median),g(t,e.end,r),g(t,e.end,e.q1)]},Pe=(e,t)=>{const[r,o]=e.notch===null?[e.start,e.end]:te(e);return{from:g(t,r,e.median),to:g(t,o,e.median)}},ee=(e,t)=>e.mean===null?null:g(t,B(e),e.mean),te=e=>{const t=(e.end-e.start)*(1-Oe)/2;return[e.start+t,e.end-t]},re=(e,t)=>{const r=B(e),o=(e.end-e.start)*Ie/2;return[{side:"lower",quartile:e.q1,reach:e.lowerWhisker},{side:"upper",quartile:e.q3,reach:e.upperWhisker}].filter(({quartile:n,reach:s})=>n!==s).map(({side:n,quartile:s,reach:i})=>({side:n,stem:{from:g(t,r,s),to:g(t,r,i)},cap:{from:g(t,r-o,i),to:g(t,r+o,i)}}))},g=(e,t,r)=>{const o=(0,a.composePoint)(e,{main:t,cross:r});return{x:(0,a.toViewBoxX)(o.x),y:(0,a.toViewBoxY)(o.y)}},K=(e,t)=>e<=t?[e,t]:[t,e],O=(e,t)=>({x:e.x*t.width,y:e.y*t.height}),N=(e,t)=>`${e.map((r,o)=>{const{x:n,y:s}=O(r,t);return`${o===0?"M":"L"}${n},${s}`}).join("")}Z`,be=(e,t)=>N([{x:e.x,y:e.y},{x:e.x+e.width,y:e.y},{x:e.x+e.width,y:e.y+e.height},{x:e.x,y:e.y+e.height}],t),Be=(e,t)=>{const r=O(e.from,t),o=O(e.to,t);return`M${r.x},${r.y}L${o.x},${o.y}`},Ee=({layer:e,coordSystem:t,panelRect:r,styleReaders:o})=>{const n=(0,a.readMainAxis)(t),{boxes:s,outliers:i}=W(e.data,n),u=s.map(h=>{const y=J(h,n);return y!==null?{kind:"region",pathData:N(y,r)}:{kind:"region",pathData:be(Z(h,n),r)}}),c=o.part("whisker"),l=o.part("cap"),d=s.flatMap(h=>re(h,n).flatMap(y=>[{segment:y.stem,readers:c},{segment:y.cap,readers:l}].flatMap(({segment:M,readers:E})=>{const I=E?.get("strokeWidth",h.observation)??0;return I>0?[{kind:"stroke",pathData:Be(M,r),width:I}]:[]}))),m=o.part("outlier"),k=m===void 0?[]:i.map(h=>({center:O(g(n,h.band,h.value),r),size:j(m,h.observation)})),p=o.part("mean"),v=p===void 0?[]:s.flatMap(h=>{const y=ee(h,n);return y===null?[]:[{center:O(y,r),size:j(p,h.observation)}]}),w=(0,a.buildDotsEditOutlineShapes)([...k,...v]);return[...d,...u,...w]},j=(e,t)=>(e.get("size",t)??0)+(e.get("strokeWidth",t)??0),A=e=>{const t=(0,a.createStableKeyGenerator)(e.data,e.mapping,e.id),r=(0,a.readVariableName)(e.mapping.outlier),o=n=>`${t(n.observation)}-outlier-${String(r===null?n.value:n.observation[r])}`;return{readBoxKey:t,readOutlierKeys:n=>{const s=new Map;return n.map(i=>{const u=o(i),c=s.get(u)??0;return s.set(u,c+1),c===0?u:`${u}-${c}`})}}},Te=(e,t,r)=>{const o=e.data.getVariableNames(),n=i=>JSON.stringify(o.map(u=>i.observation[u]??null)),s=new Set(r.map(n));return t.filter(i=>s.has(n(i)))},oe=(e,t,r)=>{const o=new Set(t.map(n=>r(n.observation)));return e.filter(n=>o.has(r(n.observation)))},L=({boxes:e,outliers:t,mainAxis:r,panelSize:o,source:n,styleReaders:s,keys:i,hovered:u,animateTransitions:c=!1})=>{const l=u===void 0?void 0:"hovered",d=s.part("whisker"),m=s.part("cap"),k=s.part("median"),p=s.part("mean"),v=s.part("outlier"),w=i.readOutlierKeys(t);return(0,f.jsxs)(f.Fragment,{children:[e.flatMap(h=>re(h,r).flatMap(y=>[{piece:"stem",testId:"boxplot-whisker",readers:d},{piece:"cap",testId:"boxplot-cap",readers:m}].map(({piece:M,testId:E,readers:I})=>I===void 0?null:(0,f.jsx)(G,{testId:E,segment:y[M],observation:h.observation,readers:I,state:l,animateTransitions:c},`${i.readBoxKey(h.observation)}-${y.side}-${M}`)))),(0,f.jsx)(a.GeomOverpaint,{styleReaders:s,state:l,children:e.map(h=>(0,f.jsx)(_e,{box:h,mainAxis:r,panelSize:o,source:n,styleReaders:s,state:l,animateTransitions:c},i.readBoxKey(h.observation)))}),k&&e.map(h=>(0,f.jsx)(G,{testId:"boxplot-median",segment:Pe(h,r),observation:h.observation,readers:k,state:l,animateTransitions:c},i.readBoxKey(h.observation))),p&&e.map(h=>{const y=ee(h,r);return y===null?null:(0,f.jsx)(U,{testId:"boxplot-mean",centre:y,observation:h.observation,readers:p,state:l,animateTransitions:c},i.readBoxKey(h.observation))}),v&&t.map((h,y)=>(0,f.jsx)(U,{testId:"boxplot-outlier",centre:g(r,h.band,h.value),observation:h.observation,readers:v,state:l,animateTransitions:c},w[y]))]})},G=({testId:e,segment:t,observation:r,readers:o,state:n,animateTransitions:s})=>{const i=o.get("strokeWidth",r,n)??0,u=o.get("stroke",r,n);return(0,f.jsx)(a.GeomLine,{"data-testid":e,x1:(0,a.toPercent)(t.from.x),y1:(0,a.toPercent)(t.from.y),x2:(0,a.toPercent)(t.to.x),y2:(0,a.toPercent)(t.to.y),stroke:u===void 0?void 0:(0,a.toPaintColor)(u),strokeOpacity:o.get("alpha",r,n),strokeWidth:i,strokeDasharray:(0,a.toStrokeDasharray)(o.get("dashArray",r,n),i),animateTransitions:s})},_e=({box:e,mainAxis:t,panelSize:r,source:o,styleReaders:n,state:s,animateTransitions:i})=>{const u=n.get("fill",e.observation,s),c=n.get("stroke",e.observation,s),l={fill:u===void 0?void 0:(0,a.toPaintColor)(u),opacity:n.get("alpha",e.observation,s),fillOpacity:n.get("fillAlpha",e.observation,s),stroke:c===void 0?void 0:(0,a.toPaintColor)(c),strokeOpacity:n.get("strokeAlpha",e.observation,s),strokeWidth:n.get("strokeWidth",e.observation,s),effects:(0,a.readGeomEffects)(n,e.observation,s),animateTransitions:i},d=J(e,t);if(d!==null)return(0,f.jsx)(a.GeomPath,{"data-testid":"boxplot-box",d:N(d,r),source:o,...l});const m=Z(e,t);return(0,f.jsx)(a.GeomRect,{"data-testid":"boxplot-box",x:(0,a.toPercent)(m.x),y:(0,a.toPercent)(m.y),width:(0,a.toPercent)(m.width),height:(0,a.toPercent)(m.height),cornerRadius:n.get("cornerRadius",e.observation,s),...l})},U=({testId:e,centre:t,observation:r,readers:o,state:n,animateTransitions:s})=>{const i=o.get("fill",r,n),u=o.get("stroke",r,n);return(0,f.jsx)(a.GeomCircle,{"data-testid":e,cx:(0,a.toPercent)(t.x),cy:(0,a.toPercent)(t.y),r:(o.get("size",r,n)??0)/2,fill:i===void 0?void 0:(0,a.toPaintColor)(i),opacity:o.get("alpha",r,n),fillOpacity:o.get("fillAlpha",r,n),stroke:u===void 0?void 0:(0,a.toPaintColor)(u),strokeWidth:o.get("strokeWidth",r,n),symbol:o.get("symbol",r,n),animateTransitions:s})},qe=({layer:e,sourceLayer:t,mainAxis:r,styleReaders:o})=>{const n=(0,a.useGeomPanelSize)(),s=(0,S.useMemo)(()=>A(t),[t]),i=(0,S.useMemo)(()=>W(t.data,r).outliers,[t.data,r]),{boxes:u,outliers:c}=(0,S.useMemo)(()=>{const l=W(e.data,r),d=new Set(Te(t,i,l.outliers)),m=new Set(oe(i,l.boxes,s.readBoxKey)),k=i.filter(p=>m.has(p)||d.has(p));return{boxes:l.boxes,outliers:k}},[e.data,r,t,i,s]);return(0,f.jsx)(L,{boxes:u,outliers:c,mainAxis:r,panelSize:n,source:t,styleReaders:o,keys:s})},Ve=({layer:e,primary:t,mainAxis:r,styleReaders:o})=>{const n=(0,a.useGeomPanelSize)(),s=(0,S.useMemo)(()=>W(e.data,r).outliers,[e.data,r]),i=(0,S.useMemo)(()=>A(e),[e]),{boxes:u,outliers:c}=W([t.observation],r);return(0,f.jsx)("g",{"data-testid":"hovered-boxes",children:(0,f.jsx)(L,{boxes:u,outliers:u.length>0?oe(s,u,i.readBoxKey):c,mainAxis:r,panelSize:n,source:e,styleReaders:o,keys:i,hovered:t.observation})})},Ne=({layer:e,mainAxis:t,styleReaders:r,animateTransitions:o,intro:n})=>{const s=(0,a.useGeomPanelSize)(),{boxes:i,outliers:u}=(0,S.useMemo)(()=>W(e.data,t),[e.data,t]),c=(0,f.jsx)(L,{boxes:i,outliers:u,mainAxis:t,panelSize:s,source:e,styleReaders:r,keys:(0,S.useMemo)(()=>A(e),[e]),animateTransitions:o});return n==null?c:(0,f.jsx)(a.IntroFade,{intro:{type:"fade",layerId:n.layerId,durationSeconds:n.durationSeconds},children:c})},Ae=(0,a.defineGeomRenderer)(new Q,{coord:"cartesian",swatchShape:"square",overpaintPlacement:"manual",guideMode:"band",render:({layer:e,coordSystem:t,styleReaders:r,animateTransitions:o,intro:n})=>(0,f.jsx)(Ne,{layer:e,mainAxis:(0,a.readMainAxis)(t),styleReaders:r,animateTransitions:o,intro:n}),renderHighlight:({layer:e,sourceLayer:t,coordSystem:r,styleReaders:o})=>(0,f.jsx)(qe,{layer:e,sourceLayer:t,mainAxis:(0,a.readMainAxis)(r),styleReaders:o}),renderHover:({layer:e,primary:t,coordSystem:r,styleReaders:o})=>(0,f.jsx)(Ve,{layer:e,primary:t,mainAxis:(0,a.readMainAxis)(r),styleReaders:o}),getEditOutlineShapes:Ee});exports.BOXPLOT_VARIABLES=x;exports.BoxplotGeom=Q;exports.boxplot=Ae;
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});let a=require("@graphysdk/react"),M=require("react"),g=require("react/jsx-runtime");var y={q1:"boxplotQ1",median:"boxplotMedian",q3:"boxplotQ3",lowerWhisker:"boxplotLowerWhisker",upperWhisker:"boxplotUpperWhisker",count:"boxplotCount",mean:"boxplotMean",notchLower:"boxplotNotchLower",notchUpper:"boxplotNotchUpper",relativeWidth:"boxplotRelativeWidth",outlier:"boxplotOutlier"},b=e=>(e.start+e.end)/2,U=(e,t)=>{const r=t==="x"?(0,a.getXMin)(e):(0,a.getYMin)(e),o=t==="x"?(0,a.getXMax)(e):(0,a.getYMax)(e),n=t==="x"?(0,a.getYMin)(e):(0,a.getXMin)(e),s=t==="x"?(0,a.getYMax)(e):(0,a.getXMax)(e),i=(0,a.getScaledAesthetic)(e,"q1"),c=(0,a.getScaledAesthetic)(e,"median"),u=(0,a.getScaledAesthetic)(e,"q3");if(r===null||o===null||n===null||s===null||c===null||i===null||u===null)return null;const l=oe(i,u,t),d=T(e,"notchLower"),m=T(e,"notchUpper"),[f,p]=ne(r,o,e);return{observation:e,start:f,end:p,lowerWhisker:l?n:s,q1:i,median:c,q3:u,upperWhisker:l?s:n,mean:T(e,"mean"),notch:d===null||m===null?null:{lower:d,upper:m}}},$=(e,t)=>{const r=t==="x"?(0,a.getXMin)(e):(0,a.getYMin)(e),o=t==="x"?(0,a.getXMax)(e):(0,a.getYMax)(e),n=(0,a.getScaledAesthetic)(e,"outlier");return r===null||o===null||n===null?null:{observation:e,band:b({start:r,end:o}),value:n}},P=(e,t)=>{const r=[],o=[];for(const n of e){const s=U(n,t);if(s!==null){r.push(s);continue}const i=$(n,t);i!==null&&o.push(i)}return{boxes:r,outliers:o}},oe=(e,t,r)=>e===t?r==="y":e<t,T=(e,t)=>(0,a.getScaledAesthetic)(e,t)??null,ne=(e,t,r)=>{const o=r[y.relativeWidth];if(typeof o!="number")return[e,t];const n=(e+t)/2,s=(t-e)*o/2;return[n-s,n+s]},O=1.5,X=e=>e==="min-max"||typeof e=="number"&&Number.isFinite(e)&&e>=0,ae=1.58,se=(e,t)=>{if(e.length===0)return null;const r=[...e].sort((m,f)=>m-f),o=_(r,.25),n=_(r,.5),s=_(r,.75),i=t==="min-max"?1/0:t*(s-o),c=o-i,u=s+i,l=r.filter(m=>m>=c&&m<=u),d=ae*(s-o)/Math.sqrt(e.length);return{lowerWhisker:Math.min(l[0]??o,o),q1:o,median:n,q3:s,upperWhisker:Math.max(l[l.length-1]??s,s),count:e.length,mean:r.reduce((m,f)=>m+f,0)/r.length,notchLower:n-d,notchUpper:n+d}},_=(e,t)=>{const r=(e.length-1)*t,o=Math.floor(r),n=e[o]??0;return n+((e[o+1]??n)-n)*(r-o)},F={q1:y.q1,median:y.median,q3:y.q3,lowerWhisker:y.lowerWhisker,upperWhisker:y.upperWhisker,count:y.count,outlier:y.outlier},H=new Set([...Object.keys(F),"mean","notchLower","notchUpper"]),ie=class extends a.Stat{constructor(...e){super(...e),this.type="boxplot",this.computedAesthetics=H}computeStat({data:e,mapping:t,params:r}){const o=(0,a.readVariableName)(t.x),n=(0,a.readVariableName)(t.y);if(o===null||n===null||!e.hasVariable(o)||!e.hasVariable(n))return{data:e,mapping:{}};if(e.size()>0&&e.getType(n)!=="numeric"){const i=e.getType(n);throw new a.UserInputError({code:"INCOMPATIBLE_TYPE",message:`'boxplot' stat requires a numeric 'y' (got '${i}' for variable '${n}')`,context:{aesthetic:"y",variableName:n,variableType:i},suggestion:"Map the raw values to 'y', or summarised columns under stat 'identity'."})}const s=r?.extent;return{data:le({data:e,xVariable:o,yVariable:n,groupVariables:(0,a.getGroupVariables)(e,t).filter(i=>i!==o),extent:X(s)?s:O}),mapping:F}}},le=({data:e,xVariable:t,yVariable:r,groupVariables:o,extent:n})=>{const s=ce(e,t,r,o),i=e.getVariableNames(),c=new Map(i.map(p=>[p,e.getValues(p)])),u=new Map(i.map(p=>[p,[]])),l={q1:[],median:[],q3:[],lowerWhisker:[],upperWhisker:[],count:[],mean:[],notchLower:[],notchUpper:[],outlier:[]},d=[];for(const p of s){const v=se(p.values,n);if(v===null)continue;for(const h of i)u.get(h)?.push(ue(c.get(h)??[],p.indices));l.q1.push(v.q1),l.median.push(v.median),l.q3.push(v.q3),l.lowerWhisker.push(v.lowerWhisker),l.upperWhisker.push(v.upperWhisker),l.count.push(v.count),l.mean.push(v.mean),l.notchLower.push(v.notchLower),l.notchUpper.push(v.notchUpper),l.outlier.push(null);const x={low:v.lowerWhisker,high:v.upperWhisker};p.indices.forEach((h,k)=>{const w=p.values[k];w!==void 0&&(w<x.low||w>x.high)&&d.push({index:h,value:w})})}for(const{index:p,value:v}of d){for(const x of i)u.get(x)?.push(c.get(x)?.[p]??null);l.q1.push(null),l.median.push(null),l.q3.push(null),l.lowerWhisker.push(null),l.upperWhisker.push(null),l.count.push(null),l.mean.push(null),l.notchLower.push(null),l.notchUpper.push(null),l.outlier.push(v)}const m=e.getValueFormat(r),f=Object.fromEntries(i.map(p=>[p,{type:e.getType(p),values:u.get(p)??[],valueFormat:e.getValueFormat(p)}]));for(const[p,v]of Object.entries(l)){const x=y[p];f[x]=p==="count"?{type:"numeric",values:v}:{type:"numeric",values:v,valueFormat:m}}return new a.Dataset(f,e.parsingLocale)},ce=(e,t,r,o)=>{const n=[t,...o].map(c=>e.getValues(c)),s=e.getValues(r,{type:"numeric"}),i=new Map;return s.forEach((c,u)=>{if(c===null||!Number.isFinite(c))return;const l=n.map(m=>q(m[u]??null)).join("\0"),d=i.get(l)??{indices:[],values:[]};d.indices.push(u),d.values.push(c),i.set(l,d)}),[...i.values()]},ue=(e,t)=>{const r=e[t[0]??-1]??null,o=q(r);return t.every(n=>q(e[n]??null)===o)?r:null},q=e=>e===null?"\0null":e instanceof Date?`date:${e.getTime()}`:`${typeof e}:${String(e)}`,z=.6,he=1,de=2,pe=1.5,me=7,ve=1,ge=7,fe=1.5,ke=["q1","median","q3"],ye={strokeWidth:"pixels"},B={stroke:"color",alpha:"unitInterval",strokeWidth:"pixels",dashArray:"dashArray"},L={fill:"color",fillAlpha:"unitInterval",stroke:"color",alpha:"unitInterval",size:"pixels",strokeWidth:"pixels",symbol:"pointSymbol"},Y=class extends a.Geom{constructor(...e){super(...e),this.type="boxplot",this.defaultParams={extent:O,outliers:!0,notch:!1,showMean:!1,varwidth:!1},this.defaultStat=new ie,this.derivedVariables=Object.values(y),this.positionRoles=[{axis:"x",role:"point",valueKind:"value"},{axis:"y",role:"min",valueKind:"value",aesthetic:"lowerWhisker"},{axis:"y",role:"max",valueKind:"value",aesthetic:"upperWhisker"},{axis:"y",role:"scalar",valueKind:"value",aesthetic:"q1"},{axis:"y",role:"scalar",valueKind:"value",aesthetic:"median"},{axis:"y",role:"scalar",valueKind:"value",aesthetic:"q3"},{axis:"y",role:"scalar",valueKind:"value",aesthetic:"outlier"},{axis:"y",role:"scalar",valueKind:"value",aesthetic:"mean"},{axis:"y",role:"scalar",valueKind:"value",aesthetic:"notchLower"},{axis:"y",role:"scalar",valueKind:"value",aesthetic:"notchUpper"}],this.aesthetics=[{kind:"visual",name:"color"},{kind:"data",name:"y"},{kind:"data",name:"count"}],this.defaultPosition="dodge",this.supportedPositions=["identity","dodge"],this.supportedCoordTypes=["cartesian","flip"],this.scaleConstraints={requireMainAxisBands:!0},this.grid={cartesian:{hideGridX:!0},flip:{hideGridX:!0}},this.legend={suppressWhenSingleItem:!0},this.spatialKind="rects",this.highlightStrategy="observationRerender",this.tooltip=[{key:"Upper whisker",aesthetic:"upperWhisker",optional:!0},{key:"Q3",aesthetic:"q3",optional:!0},{key:"Median",aesthetic:"median",optional:!0},{key:"Q1",aesthetic:"q1",optional:!0},{key:"Lower whisker",aesthetic:"lowerWhisker",optional:!0},{key:"Count",aesthetic:"count",optional:!0},{key:"Mean",aesthetic:"mean",optional:!0},{key:"Outlier",aesthetic:"outlier",optional:!0}],this.styleTarget=(0,a.defineGeomStyleTarget)({observation:{vocabulary:ye,aesthetics:{fill:"color"},rest:{fill:(0,a.token)("geom"),fillAlpha:1,stroke:(0,a.token)("geomBorder"),strokeWidth:he}},parts:{median:{vocabulary:B,rest:{stroke:(0,a.token)("graphBackground"),alpha:1,strokeWidth:de,dashArray:[]}},whisker:{vocabulary:B,aesthetics:{stroke:"color"},rest:{stroke:(0,a.token)("geom"),alpha:1,strokeWidth:pe,dashArray:[]}},cap:{vocabulary:B,aesthetics:{stroke:"color"},rest:{stroke:(0,a.token)("geom"),alpha:1,strokeWidth:0,dashArray:[]}},outlier:{vocabulary:L,aesthetics:{fill:"color"},rest:{fill:(0,a.token)("geom"),fillAlpha:1,stroke:(0,a.token)("graphBackground"),alpha:1,size:me,strokeWidth:ve}},mean:{vocabulary:L,aesthetics:{stroke:"color"},rest:{fill:(0,a.token)("graphBackground"),fillAlpha:1,stroke:(0,a.token)("geom"),alpha:1,size:ge,strokeWidth:fe}}}}),this.resolveBandFraction=t=>C(t),this.resolveValueSource=t=>t.median??{variable:y.median},this.validateMapping=({mapping:t,computedAesthetics:r})=>r.has("y")?[{code:"CONFLICTING_STAT_MAPPING",message:"boxplot geom draws a summary, not a single 'y'; use the 'boxplot' stat or 'identity'"}]:r.has("median")?[...[...H].filter(o=>t[o]!==void 0).map(o=>({code:"CONFLICTING_STAT_MAPPING",message:`boxplot stat computes '${o}' from 'y'; remove its mapping, or set the layer's stat to 'identity'`})),...t.y===void 0?[{code:"MISSING_AESTHETIC",message:"boxplot stat summarises 'y'; map it to the raw values"}]:[]]:ke.filter(o=>t[o]===void 0).map(o=>({code:"MISSING_AESTHETIC",message:`boxplot geom requires '${o}' when its data is already summarised`,context:{aesthetic:o}})),this.resolveAnchorPosition=(t,{coordSystem:r})=>{const o=(0,a.readMainAxis)(r),n=xe(t,o);return n===null?null:o==="x"?{x:n.band,y:n.value}:{x:n.value,y:n.band}}}resolveParams(e){const{extent:t,width:r,...o}=super.resolveParams(e);return{...o,extent:this.resolveExtent(t,e.diagnostics),...this.resolveWidth(r,e.diagnostics)}}compile({data:e,mapping:t,params:r}){const o=I(e,t.lowerWhisker),n=I(e,t.upperWhisker);if(o===null||n===null)return{data:e,mapping:{}};const{outliers:s,notch:i,showMean:c,varwidth:u}=r,l=I(e,t.outlier),d=s===!1&&l!==null?Pe(e,l):e,m=I(d,t.count),f=C(r)/2;return{data:d.addVariable(y.relativeWidth,"numeric",u===!0&&m!==null?we(d,m):Me(d)).addVariable(a.POSITION_VARIABLES.yMin,"numeric",R(d,o,l)).addVariable(a.POSITION_VARIABLES.yMax,"numeric",R(d,n,l)).addConstantVariable(a.POSITION_VARIABLES.xMin,"numeric",-f).addConstantVariable(a.POSITION_VARIABLES.xMax,"numeric",f),mapping:{...t.y===void 0&&{y:t.median},...c===!0&&t.mean===void 0&&d.hasVariable(y.mean)&&{mean:y.mean},...i===!0&&t.notchLower===void 0&&d.hasVariable(y.notchLower)&&{notchLower:y.notchLower,notchUpper:y.notchUpper}}}}resolveExtent(e,t){return X(e)?e:(t?.addWarning({code:"INVALID_GEOM_PARAM",message:`Boxplot extent must be a non-negative number or 'min-max', got ${String(e)}; falling back to ${O}.`,context:{geom:this.type,param:"extent",expected:"extent >= 0 or 'min-max'",actual:String(e)},suggestion:"Set params.extent to a number of interquartile ranges, or 'min-max'."}),O)}resolveWidth(e,t){if(e===void 0)return{};const r=typeof e=="number"&&Number.isFinite(e)?e:null;if(r!==null&&r>0&&r<=1)return{width:r};const o=r!==null&&r>1?1:void 0;return t?.addWarning({code:"INVALID_GEOM_PARAM",message:`Boxplot width must be a fraction in (0, 1], got ${String(e)}; falling back to ${o??z}.`,context:{geom:this.type,param:"width",expected:"0 < width <= 1",actual:r??String(e)},suggestion:"Set params.width to a fraction of the category band in (0, 1]."}),o!==void 0?{width:o}:{}}},xe=(e,t)=>{const r=U(e,t);if(r!==null)return{band:b(r),value:r.median};const o=$(e,t);return o===null?null:{band:o.band,value:o.value}},C=({width:e})=>e??z,we=(e,t)=>{const r=e.getValues(t,{type:"numeric"}),o=Math.max(0,...r.map(n=>n??0));return r.map(n=>n===null||o===0?null:Math.sqrt(n/o))},Me=e=>Array.from({length:e.size()},()=>null),R=(e,t,r)=>{const o=r===null?[]:e.getValues(r,{type:"numeric"});return e.getValues(t,{type:"numeric"}).map((n,s)=>n??o[s]??null)},Pe=(e,t)=>{const r=e.getValues(t,{type:"numeric"});return e.take(r.flatMap((o,n)=>o===null?[n]:[]))},I=(e,t)=>{const r=(0,a.readVariableName)(t);return r!==null&&e.hasVariable(r)?r:null},Se=5e-4,We=.5,Ie=.5,Q=(e,t)=>{const r=(e.q1+e.q3)/2,o=Math.max(Math.abs(e.q3-e.q1),Se)/2,n=(0,a.composePoint)(t,{main:e.start,cross:r-o}),s=(0,a.composePoint)(t,{main:e.end,cross:r+o}),[i,c]=D(n.x,s.x),[u,l]=D(n.y,s.y);return{x:i,y:u,width:c-i,height:l-u}},Z=(e,t)=>{if(e.notch===null)return null;const{lower:r,upper:o}=e.notch,[n,s]=ee(e);return[(0,a.composePoint)(t,{main:e.start,cross:e.q1}),(0,a.composePoint)(t,{main:e.start,cross:r}),(0,a.composePoint)(t,{main:n,cross:e.median}),(0,a.composePoint)(t,{main:e.start,cross:o}),(0,a.composePoint)(t,{main:e.start,cross:e.q3}),(0,a.composePoint)(t,{main:e.end,cross:e.q3}),(0,a.composePoint)(t,{main:e.end,cross:o}),(0,a.composePoint)(t,{main:s,cross:e.median}),(0,a.composePoint)(t,{main:e.end,cross:r}),(0,a.composePoint)(t,{main:e.end,cross:e.q1})]},Oe=(e,t)=>{const[r,o]=e.notch===null?[e.start,e.end]:ee(e);return{from:(0,a.composePoint)(t,{main:r,cross:e.median}),to:(0,a.composePoint)(t,{main:o,cross:e.median})}},J=(e,t)=>e.mean===null?null:(0,a.composePoint)(t,{main:b(e),cross:e.mean}),ee=e=>{const t=(e.end-e.start)*(1-Ie)/2;return[e.start+t,e.end-t]},te=(e,t)=>{const r=b(e),o=(e.end-e.start)*We/2;return[{side:"lower",quartile:e.q1,reach:e.lowerWhisker},{side:"upper",quartile:e.q3,reach:e.upperWhisker}].filter(({quartile:n,reach:s})=>n!==s).map(({side:n,quartile:s,reach:i})=>({side:n,stem:{from:(0,a.composePoint)(t,{main:r,cross:s}),to:(0,a.composePoint)(t,{main:r,cross:i})},cap:{from:(0,a.composePoint)(t,{main:r-o,cross:i}),to:(0,a.composePoint)(t,{main:r+o,cross:i})}}))},D=(e,t)=>e<=t?[e,t]:[t,e],W=(e,t)=>({x:e.x*t.width,y:e.y*t.height}),A=(e,t)=>`${e.map((r,o)=>{const{x:n,y:s}=W(r,t);return`${o===0?"M":"L"}${n},${s}`}).join("")}Z`,be=(e,t)=>A([{x:e.x,y:e.y},{x:e.x+e.width,y:e.y},{x:e.x+e.width,y:e.y+e.height},{x:e.x,y:e.y+e.height}],t),Ee=(e,t)=>{const r=W(e.from,t),o=W(e.to,t);return`M${r.x},${r.y}L${o.x},${o.y}`},Te=({layer:e,coordSystem:t,panelRect:r,styleReaders:o})=>{const n=(0,a.readMainAxis)(t),{boxes:s,outliers:i}=P(e.data,n),c=s.map(h=>{const k=Z(h,n);return k!==null?{kind:"region",pathData:A(k,r)}:{kind:"region",pathData:be(Q(h,n),r)}}),u=o.part("whisker"),l=o.part("cap"),d=s.flatMap(h=>te(h,n).flatMap(k=>[{segment:k.stem,readers:u},{segment:k.cap,readers:l}].flatMap(({segment:w,readers:E})=>{const S=E?.get("strokeWidth",h.observation)??0;return S>0?[{kind:"stroke",pathData:Ee(w,r),width:S}]:[]}))),m=o.part("outlier"),f=m===void 0?[]:i.map(h=>({center:W((0,a.composePoint)(n,{main:h.band,cross:h.value}),r),size:K(m,h.observation)})),p=o.part("mean"),v=p===void 0?[]:s.flatMap(h=>{const k=J(h,n);return k===null?[]:[{center:W(k,r),size:K(p,h.observation)}]}),x=(0,a.buildDotsEditOutlineShapes)([...f,...v]);return[...d,...c,...x]},K=(e,t)=>(e.get("size",t)??0)+(e.get("strokeWidth",t)??0),N=e=>{const t=(0,a.createStableKeyGenerator)(e.data,e.mapping,e.id),r=(0,a.readVariableName)(e.mapping.outlier),o=n=>`${t(n.observation)}-outlier-${String(r===null?n.value:n.observation[r])}`;return{readBoxKey:t,readOutlierKeys:n=>{const s=new Map;return n.map(i=>{const c=o(i),u=s.get(c)??0;return s.set(c,u+1),u===0?c:`${c}-${u}`})}}},_e=(e,t,r)=>{const o=e.data.getVariableNames(),n=i=>JSON.stringify(o.map(c=>i.observation[c]??null)),s=new Set(r.map(n));return t.filter(i=>s.has(n(i)))},re=(e,t,r)=>{const o=new Set(t.map(n=>r(n.observation)));return e.filter(n=>o.has(r(n.observation)))},V=({boxes:e,outliers:t,mainAxis:r,panelSize:o,source:n,styleReaders:s,keys:i,hovered:c,animateTransitions:u=!1})=>{const l=c===void 0?void 0:"hovered",d=s.part("whisker"),m=s.part("cap"),f=s.part("median"),p=s.part("mean"),v=s.part("outlier"),x=i.readOutlierKeys(t);return(0,g.jsxs)(g.Fragment,{children:[e.flatMap(h=>te(h,r).flatMap(k=>[{piece:"stem",testId:"boxplot-whisker",readers:d},{piece:"cap",testId:"boxplot-cap",readers:m}].map(({piece:w,testId:E,readers:S})=>S===void 0?null:(0,g.jsx)(j,{testId:E,segment:k[w],observation:h.observation,readers:S,state:l,animateTransitions:u},`${i.readBoxKey(h.observation)}-${k.side}-${w}`)))),(0,g.jsx)(a.GeomOverpaint,{styleReaders:s,state:l,children:e.map(h=>(0,g.jsx)(Be,{box:h,mainAxis:r,panelSize:o,source:n,styleReaders:s,state:l,animateTransitions:u},i.readBoxKey(h.observation)))}),f&&e.map(h=>(0,g.jsx)(j,{testId:"boxplot-median",segment:Oe(h,r),observation:h.observation,readers:f,state:l,animateTransitions:u},i.readBoxKey(h.observation))),p&&e.map(h=>{const k=J(h,r);return k===null?null:(0,g.jsx)(G,{testId:"boxplot-mean",centre:k,observation:h.observation,readers:p,state:l,animateTransitions:u},i.readBoxKey(h.observation))}),v&&t.map((h,k)=>(0,g.jsx)(G,{testId:"boxplot-outlier",centre:(0,a.composePoint)(r,{main:h.band,cross:h.value}),observation:h.observation,readers:v,state:l,animateTransitions:u},x[k]))]})},j=({testId:e,segment:t,observation:r,readers:o,state:n,animateTransitions:s})=>{const i=o.get("strokeWidth",r,n)??0,c=o.get("stroke",r,n);return(0,g.jsx)(a.GeomLine,{"data-testid":e,x1:(0,a.toPercent)(t.from.x),y1:(0,a.toPercent)(t.from.y),x2:(0,a.toPercent)(t.to.x),y2:(0,a.toPercent)(t.to.y),stroke:c===void 0?void 0:(0,a.toPaintColor)(c),strokeOpacity:o.get("alpha",r,n),strokeWidth:i,strokeDasharray:(0,a.toStrokeDasharray)(o.get("dashArray",r,n),i),animateTransitions:s})},Be=({box:e,mainAxis:t,panelSize:r,source:o,styleReaders:n,state:s,animateTransitions:i})=>{const c=n.get("fill",e.observation,s),u=n.get("stroke",e.observation,s),l={fill:c===void 0?void 0:(0,a.toPaintColor)(c),opacity:n.get("alpha",e.observation,s),fillOpacity:n.get("fillAlpha",e.observation,s),stroke:u===void 0?void 0:(0,a.toPaintColor)(u),strokeOpacity:n.get("strokeAlpha",e.observation,s),strokeWidth:n.get("strokeWidth",e.observation,s),effects:(0,a.readGeomEffects)(n,e.observation,s),animateTransitions:i},d=Z(e,t);if(d!==null)return(0,g.jsx)(a.GeomPath,{"data-testid":"boxplot-box",d:A(d,r),source:o,...l});const m=Q(e,t);return(0,g.jsx)(a.GeomRect,{"data-testid":"boxplot-box",x:(0,a.toPercent)(m.x),y:(0,a.toPercent)(m.y),width:(0,a.toPercent)(m.width),height:(0,a.toPercent)(m.height),cornerRadius:n.get("cornerRadius",e.observation,s),...l})},G=({testId:e,centre:t,observation:r,readers:o,state:n,animateTransitions:s})=>{const i=o.get("fill",r,n),c=o.get("stroke",r,n);return(0,g.jsx)(a.GeomCircle,{"data-testid":e,cx:(0,a.toPercent)(t.x),cy:(0,a.toPercent)(t.y),r:(o.get("size",r,n)??0)/2,fill:i===void 0?void 0:(0,a.toPaintColor)(i),opacity:o.get("alpha",r,n),fillOpacity:o.get("fillAlpha",r,n),stroke:c===void 0?void 0:(0,a.toPaintColor)(c),strokeWidth:o.get("strokeWidth",r,n),symbol:o.get("symbol",r,n),animateTransitions:s})},qe=({layer:e,sourceLayer:t,mainAxis:r,styleReaders:o})=>{const n=(0,a.useGeomPanelSize)(),s=(0,M.useMemo)(()=>N(t),[t]),i=(0,M.useMemo)(()=>P(t.data,r).outliers,[t.data,r]),{boxes:c,outliers:u}=(0,M.useMemo)(()=>{const l=P(e.data,r),d=new Set(_e(t,i,l.outliers)),m=new Set(re(i,l.boxes,s.readBoxKey)),f=i.filter(p=>m.has(p)||d.has(p));return{boxes:l.boxes,outliers:f}},[e.data,r,t,i,s]);return(0,g.jsx)(V,{boxes:c,outliers:u,mainAxis:r,panelSize:n,source:t,styleReaders:o,keys:s})},Ae=({layer:e,primary:t,mainAxis:r,styleReaders:o})=>{const n=(0,a.useGeomPanelSize)(),s=(0,M.useMemo)(()=>P(e.data,r).outliers,[e.data,r]),i=(0,M.useMemo)(()=>N(e),[e]),{boxes:c,outliers:u}=P([t.observation],r);return(0,g.jsx)("g",{"data-testid":"hovered-boxes",children:(0,g.jsx)(V,{boxes:c,outliers:c.length>0?re(s,c,i.readBoxKey):u,mainAxis:r,panelSize:n,source:e,styleReaders:o,keys:i,hovered:t.observation})})},Ne=({layer:e,mainAxis:t,styleReaders:r,animateTransitions:o,intro:n})=>{const s=(0,a.useGeomPanelSize)(),{boxes:i,outliers:c}=(0,M.useMemo)(()=>P(e.data,t),[e.data,t]),u=(0,g.jsx)(V,{boxes:i,outliers:c,mainAxis:t,panelSize:s,source:e,styleReaders:r,keys:(0,M.useMemo)(()=>N(e),[e]),animateTransitions:o});return n==null?u:(0,g.jsx)(a.IntroFade,{intro:{type:"fade",layerId:n.layerId,durationSeconds:n.durationSeconds},children:u})},Ve=(0,a.defineGeomRenderer)(new Y,{coord:"cartesian",swatchShape:"square",overpaintPlacement:"manual",guideMode:"band",render:({layer:e,coordSystem:t,styleReaders:r,animateTransitions:o,intro:n})=>(0,g.jsx)(Ne,{layer:e,mainAxis:(0,a.readMainAxis)(t),styleReaders:r,animateTransitions:o,intro:n}),renderHighlight:({layer:e,sourceLayer:t,coordSystem:r,styleReaders:o})=>(0,g.jsx)(qe,{layer:e,sourceLayer:t,mainAxis:(0,a.readMainAxis)(r),styleReaders:o}),renderHover:({layer:e,primary:t,coordSystem:r,styleReaders:o})=>(0,g.jsx)(Ae,{layer:e,primary:t,mainAxis:(0,a.readMainAxis)(r),styleReaders:o}),getEditOutlineShapes:Te});exports.BOXPLOT_VARIABLES=y;exports.BoxplotGeom=Y;exports.boxplot=Ve;
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { Dataset as me, Geom as ve, GeomCircle as ge, GeomLine as fe, GeomOverpaint as ye, GeomPath as ke, GeomRect as we, IntroFade as xe, POSITION_VARIABLES as _, Stat as We, UserInputError as Me, buildDotsEditOutlineShapes as Se, composePoint as
|
|
1
|
+
import { Dataset as me, Geom as ve, GeomCircle as ge, GeomLine as fe, GeomOverpaint as ye, GeomPath as ke, GeomRect as we, IntroFade as xe, POSITION_VARIABLES as _, Stat as We, UserInputError as Me, buildDotsEditOutlineShapes as Se, composePoint as v, createStableKeyGenerator as Ie, defineGeomRenderer as Oe, defineGeomStyleTarget as be, getGroupVariables as Ee, getScaledAesthetic as b, getXMax as R, getXMin as K, getYMax as U, getYMin as $, readGeomEffects as Te, readMainAxis as E, readVariableName as N, toPaintColor as T, toPercent as x, toStrokeDasharray as Be, token as M, useGeomPanelSize as F } from "@graphysdk/react";
|
|
2
2
|
import { useMemo as S } from "react";
|
|
3
|
-
import { Fragment as
|
|
3
|
+
import { Fragment as _e, jsx as y, jsxs as qe } from "react/jsx-runtime";
|
|
4
4
|
var k = {
|
|
5
5
|
q1: "boxplotQ1",
|
|
6
6
|
median: "boxplotMedian",
|
|
@@ -13,30 +13,30 @@ var k = {
|
|
|
13
13
|
notchUpper: "boxplotNotchUpper",
|
|
14
14
|
relativeWidth: "boxplotRelativeWidth",
|
|
15
15
|
outlier: "boxplotOutlier"
|
|
16
|
-
},
|
|
17
|
-
const r = t === "x" ? K(e) : $(e), o = t === "x" ?
|
|
18
|
-
if (r === null || o === null || n === null || a === null ||
|
|
19
|
-
const
|
|
16
|
+
}, V = (e) => (e.start + e.end) / 2, re = (e, t) => {
|
|
17
|
+
const r = t === "x" ? K(e) : $(e), o = t === "x" ? R(e) : U(e), n = t === "x" ? $(e) : K(e), a = t === "x" ? U(e) : R(e), s = b(e, "q1"), l = b(e, "median"), u = b(e, "q3");
|
|
18
|
+
if (r === null || o === null || n === null || a === null || l === null || s === null || u === null) return null;
|
|
19
|
+
const i = Pe(s, u, t), h = C(e, "notchLower"), p = C(e, "notchUpper"), [g, d] = Ne(r, o, e);
|
|
20
20
|
return {
|
|
21
21
|
observation: e,
|
|
22
|
-
start:
|
|
23
|
-
end:
|
|
24
|
-
lowerWhisker: n,
|
|
22
|
+
start: g,
|
|
23
|
+
end: d,
|
|
24
|
+
lowerWhisker: i ? n : a,
|
|
25
25
|
q1: s,
|
|
26
|
-
median:
|
|
26
|
+
median: l,
|
|
27
27
|
q3: u,
|
|
28
|
-
upperWhisker: a,
|
|
28
|
+
upperWhisker: i ? a : n,
|
|
29
29
|
mean: C(e, "mean"),
|
|
30
|
-
notch:
|
|
31
|
-
lower:
|
|
32
|
-
upper:
|
|
30
|
+
notch: h === null || p === null ? null : {
|
|
31
|
+
lower: h,
|
|
32
|
+
upper: p
|
|
33
33
|
}
|
|
34
34
|
};
|
|
35
35
|
}, oe = (e, t) => {
|
|
36
|
-
const r = t === "x" ? K(e) : $(e), o = t === "x" ?
|
|
36
|
+
const r = t === "x" ? K(e) : $(e), o = t === "x" ? R(e) : U(e), n = b(e, "outlier");
|
|
37
37
|
return r === null || o === null || n === null ? null : {
|
|
38
38
|
observation: e,
|
|
39
|
-
band:
|
|
39
|
+
band: V({
|
|
40
40
|
start: r,
|
|
41
41
|
end: o
|
|
42
42
|
}),
|
|
@@ -57,20 +57,20 @@ var k = {
|
|
|
57
57
|
boxes: r,
|
|
58
58
|
outliers: o
|
|
59
59
|
};
|
|
60
|
-
}, C = (e, t) => b(e, t) ?? null,
|
|
60
|
+
}, Pe = (e, t, r) => e === t ? r === "y" : e < t, C = (e, t) => b(e, t) ?? null, Ne = (e, t, r) => {
|
|
61
61
|
const o = r[k.relativeWidth];
|
|
62
62
|
if (typeof o != "number") return [e, t];
|
|
63
63
|
const n = (e + t) / 2, a = (t - e) * o / 2;
|
|
64
64
|
return [n - a, n + a];
|
|
65
|
-
}, P = 1.5, ne = (e) => e === "min-max" || typeof e == "number" && Number.isFinite(e) && e >= 0,
|
|
65
|
+
}, P = 1.5, ne = (e) => e === "min-max" || typeof e == "number" && Number.isFinite(e) && e >= 0, Ve = 1.58, Le = (e, t) => {
|
|
66
66
|
if (e.length === 0) return null;
|
|
67
|
-
const r = [...e].sort((p, g) => p - g), o = D(r, 0.25), n = D(r, 0.5), a = D(r, 0.75), s = t === "min-max" ? 1 / 0 : t * (a - o),
|
|
67
|
+
const r = [...e].sort((p, g) => p - g), o = D(r, 0.25), n = D(r, 0.5), a = D(r, 0.75), s = t === "min-max" ? 1 / 0 : t * (a - o), l = o - s, u = a + s, i = r.filter((p) => p >= l && p <= u), h = Ve * (a - o) / Math.sqrt(e.length);
|
|
68
68
|
return {
|
|
69
|
-
lowerWhisker: Math.min(
|
|
69
|
+
lowerWhisker: Math.min(i[0] ?? o, o),
|
|
70
70
|
q1: o,
|
|
71
71
|
median: n,
|
|
72
72
|
q3: a,
|
|
73
|
-
upperWhisker: Math.max(
|
|
73
|
+
upperWhisker: Math.max(i[i.length - 1] ?? a, a),
|
|
74
74
|
count: e.length,
|
|
75
75
|
mean: r.reduce((p, g) => p + g, 0) / r.length,
|
|
76
76
|
notchLower: n - h,
|
|
@@ -92,12 +92,12 @@ var k = {
|
|
|
92
92
|
"mean",
|
|
93
93
|
"notchLower",
|
|
94
94
|
"notchUpper"
|
|
95
|
-
]),
|
|
95
|
+
]), Ce = class extends We {
|
|
96
96
|
constructor(...e) {
|
|
97
97
|
super(...e), this.type = "boxplot", this.computedAesthetics = se;
|
|
98
98
|
}
|
|
99
99
|
computeStat({ data: e, mapping: t, params: r }) {
|
|
100
|
-
const o =
|
|
100
|
+
const o = N(t.x), n = N(t.y);
|
|
101
101
|
if (o === null || n === null || !e.hasVariable(o) || !e.hasVariable(n)) return {
|
|
102
102
|
data: e,
|
|
103
103
|
mapping: {}
|
|
@@ -117,18 +117,18 @@ var k = {
|
|
|
117
117
|
}
|
|
118
118
|
const a = r?.extent;
|
|
119
119
|
return {
|
|
120
|
-
data:
|
|
120
|
+
data: De({
|
|
121
121
|
data: e,
|
|
122
122
|
xVariable: o,
|
|
123
123
|
yVariable: n,
|
|
124
|
-
groupVariables:
|
|
124
|
+
groupVariables: Ee(e, t).filter((s) => s !== o),
|
|
125
125
|
extent: ne(a) ? a : P
|
|
126
126
|
}),
|
|
127
127
|
mapping: ae
|
|
128
128
|
};
|
|
129
129
|
}
|
|
130
|
-
},
|
|
131
|
-
const a =
|
|
130
|
+
}, De = ({ data: e, xVariable: t, yVariable: r, groupVariables: o, extent: n }) => {
|
|
131
|
+
const a = Ae(e, t, r, o), s = e.getVariableNames(), l = new Map(s.map((d) => [d, e.getValues(d)])), u = new Map(s.map((d) => [d, []])), i = {
|
|
132
132
|
q1: [],
|
|
133
133
|
median: [],
|
|
134
134
|
q3: [],
|
|
@@ -141,10 +141,10 @@ var k = {
|
|
|
141
141
|
outlier: []
|
|
142
142
|
}, h = [];
|
|
143
143
|
for (const d of a) {
|
|
144
|
-
const m =
|
|
144
|
+
const m = Le(d.values, n);
|
|
145
145
|
if (m === null) continue;
|
|
146
|
-
for (const c of s) u.get(c)?.push(
|
|
147
|
-
|
|
146
|
+
for (const c of s) u.get(c)?.push(Re(l.get(c) ?? [], d.indices));
|
|
147
|
+
i.q1.push(m.q1), i.median.push(m.median), i.q3.push(m.q3), i.lowerWhisker.push(m.lowerWhisker), i.upperWhisker.push(m.upperWhisker), i.count.push(m.count), i.mean.push(m.mean), i.notchLower.push(m.notchLower), i.notchUpper.push(m.notchUpper), i.outlier.push(null);
|
|
148
148
|
const w = {
|
|
149
149
|
low: m.lowerWhisker,
|
|
150
150
|
high: m.upperWhisker
|
|
@@ -158,15 +158,15 @@ var k = {
|
|
|
158
158
|
});
|
|
159
159
|
}
|
|
160
160
|
for (const { index: d, value: m } of h) {
|
|
161
|
-
for (const w of s) u.get(w)?.push(
|
|
162
|
-
|
|
161
|
+
for (const w of s) u.get(w)?.push(l.get(w)?.[d] ?? null);
|
|
162
|
+
i.q1.push(null), i.median.push(null), i.q3.push(null), i.lowerWhisker.push(null), i.upperWhisker.push(null), i.count.push(null), i.mean.push(null), i.notchLower.push(null), i.notchUpper.push(null), i.outlier.push(m);
|
|
163
163
|
}
|
|
164
164
|
const p = e.getValueFormat(r), g = Object.fromEntries(s.map((d) => [d, {
|
|
165
165
|
type: e.getType(d),
|
|
166
166
|
values: u.get(d) ?? [],
|
|
167
167
|
valueFormat: e.getValueFormat(d)
|
|
168
168
|
}]));
|
|
169
|
-
for (const [d, m] of Object.entries(
|
|
169
|
+
for (const [d, m] of Object.entries(i)) {
|
|
170
170
|
const w = k[d];
|
|
171
171
|
g[w] = d === "count" ? {
|
|
172
172
|
type: "numeric",
|
|
@@ -178,29 +178,29 @@ var k = {
|
|
|
178
178
|
};
|
|
179
179
|
}
|
|
180
180
|
return new me(g, e.parsingLocale);
|
|
181
|
-
},
|
|
182
|
-
const n = [t, ...o].map((
|
|
183
|
-
return a.forEach((
|
|
184
|
-
if (
|
|
185
|
-
const
|
|
181
|
+
}, Ae = (e, t, r, o) => {
|
|
182
|
+
const n = [t, ...o].map((l) => e.getValues(l)), a = e.getValues(r, { type: "numeric" }), s = /* @__PURE__ */ new Map();
|
|
183
|
+
return a.forEach((l, u) => {
|
|
184
|
+
if (l === null || !Number.isFinite(l)) return;
|
|
185
|
+
const i = n.map((p) => G(p[u] ?? null)).join("\0"), h = s.get(i) ?? {
|
|
186
186
|
indices: [],
|
|
187
187
|
values: []
|
|
188
188
|
};
|
|
189
|
-
h.indices.push(u), h.values.push(
|
|
189
|
+
h.indices.push(u), h.values.push(l), s.set(i, h);
|
|
190
190
|
}), [...s.values()];
|
|
191
|
-
},
|
|
191
|
+
}, Re = (e, t) => {
|
|
192
192
|
const r = e[t[0] ?? -1] ?? null, o = G(r);
|
|
193
193
|
return t.every((n) => G(e[n] ?? null) === o) ? r : null;
|
|
194
|
-
}, G = (e) => e === null ? "\0null" : e instanceof Date ? `date:${e.getTime()}` : `${typeof e}:${String(e)}`,
|
|
194
|
+
}, G = (e) => e === null ? "\0null" : e instanceof Date ? `date:${e.getTime()}` : `${typeof e}:${String(e)}`, ie = 0.6, Ke = 1, Ue = 2, $e = 1.5, Ge = 7, Fe = 1, He = 7, Xe = 1.5, ze = [
|
|
195
195
|
"q1",
|
|
196
196
|
"median",
|
|
197
197
|
"q3"
|
|
198
|
-
],
|
|
198
|
+
], je = { strokeWidth: "pixels" }, A = {
|
|
199
199
|
stroke: "color",
|
|
200
200
|
alpha: "unitInterval",
|
|
201
201
|
strokeWidth: "pixels",
|
|
202
202
|
dashArray: "dashArray"
|
|
203
|
-
},
|
|
203
|
+
}, j = {
|
|
204
204
|
fill: "color",
|
|
205
205
|
fillAlpha: "unitInterval",
|
|
206
206
|
stroke: "color",
|
|
@@ -208,7 +208,7 @@ var k = {
|
|
|
208
208
|
size: "pixels",
|
|
209
209
|
strokeWidth: "pixels",
|
|
210
210
|
symbol: "pointSymbol"
|
|
211
|
-
},
|
|
211
|
+
}, Ye = class extends ve {
|
|
212
212
|
constructor(...e) {
|
|
213
213
|
super(...e), this.type = "boxplot", this.defaultParams = {
|
|
214
214
|
extent: P,
|
|
@@ -216,7 +216,7 @@ var k = {
|
|
|
216
216
|
notch: !1,
|
|
217
217
|
showMean: !1,
|
|
218
218
|
varwidth: !1
|
|
219
|
-
}, this.defaultStat = new
|
|
219
|
+
}, this.defaultStat = new Ce(), this.derivedVariables = Object.values(k), this.positionRoles = [
|
|
220
220
|
{
|
|
221
221
|
axis: "x",
|
|
222
222
|
role: "point",
|
|
@@ -333,39 +333,39 @@ var k = {
|
|
|
333
333
|
aesthetic: "outlier",
|
|
334
334
|
optional: !0
|
|
335
335
|
}
|
|
336
|
-
], this.styleTarget =
|
|
336
|
+
], this.styleTarget = be({
|
|
337
337
|
observation: {
|
|
338
|
-
vocabulary:
|
|
338
|
+
vocabulary: je,
|
|
339
339
|
aesthetics: { fill: "color" },
|
|
340
340
|
rest: {
|
|
341
341
|
fill: M("geom"),
|
|
342
342
|
fillAlpha: 1,
|
|
343
343
|
stroke: M("geomBorder"),
|
|
344
|
-
strokeWidth:
|
|
344
|
+
strokeWidth: Ke
|
|
345
345
|
}
|
|
346
346
|
},
|
|
347
347
|
parts: {
|
|
348
348
|
median: {
|
|
349
|
-
vocabulary:
|
|
349
|
+
vocabulary: A,
|
|
350
350
|
rest: {
|
|
351
351
|
stroke: M("graphBackground"),
|
|
352
352
|
alpha: 1,
|
|
353
|
-
strokeWidth:
|
|
353
|
+
strokeWidth: Ue,
|
|
354
354
|
dashArray: []
|
|
355
355
|
}
|
|
356
356
|
},
|
|
357
357
|
whisker: {
|
|
358
|
-
vocabulary:
|
|
358
|
+
vocabulary: A,
|
|
359
359
|
aesthetics: { stroke: "color" },
|
|
360
360
|
rest: {
|
|
361
361
|
stroke: M("geom"),
|
|
362
362
|
alpha: 1,
|
|
363
|
-
strokeWidth:
|
|
363
|
+
strokeWidth: $e,
|
|
364
364
|
dashArray: []
|
|
365
365
|
}
|
|
366
366
|
},
|
|
367
367
|
cap: {
|
|
368
|
-
vocabulary:
|
|
368
|
+
vocabulary: A,
|
|
369
369
|
aesthetics: { stroke: "color" },
|
|
370
370
|
rest: {
|
|
371
371
|
stroke: M("geom"),
|
|
@@ -375,31 +375,31 @@ var k = {
|
|
|
375
375
|
}
|
|
376
376
|
},
|
|
377
377
|
outlier: {
|
|
378
|
-
vocabulary:
|
|
378
|
+
vocabulary: j,
|
|
379
379
|
aesthetics: { fill: "color" },
|
|
380
380
|
rest: {
|
|
381
381
|
fill: M("geom"),
|
|
382
382
|
fillAlpha: 1,
|
|
383
383
|
stroke: M("graphBackground"),
|
|
384
384
|
alpha: 1,
|
|
385
|
-
size:
|
|
386
|
-
strokeWidth:
|
|
385
|
+
size: Ge,
|
|
386
|
+
strokeWidth: Fe
|
|
387
387
|
}
|
|
388
388
|
},
|
|
389
389
|
mean: {
|
|
390
|
-
vocabulary:
|
|
390
|
+
vocabulary: j,
|
|
391
391
|
aesthetics: { stroke: "color" },
|
|
392
392
|
rest: {
|
|
393
393
|
fill: M("graphBackground"),
|
|
394
394
|
fillAlpha: 1,
|
|
395
395
|
stroke: M("geom"),
|
|
396
396
|
alpha: 1,
|
|
397
|
-
size:
|
|
398
|
-
strokeWidth:
|
|
397
|
+
size: He,
|
|
398
|
+
strokeWidth: Xe
|
|
399
399
|
}
|
|
400
400
|
}
|
|
401
401
|
}
|
|
402
|
-
}), this.resolveBandFraction = (t) =>
|
|
402
|
+
}), this.resolveBandFraction = (t) => Y(t), this.resolveValueSource = (t) => t.median ?? { variable: k.median }, this.validateMapping = ({ mapping: t, computedAesthetics: r }) => r.has("y") ? [{
|
|
403
403
|
code: "CONFLICTING_STAT_MAPPING",
|
|
404
404
|
message: "boxplot geom draws a summary, not a single 'y'; use the 'boxplot' stat or 'identity'"
|
|
405
405
|
}] : r.has("median") ? [...[...se].filter((o) => t[o] !== void 0).map((o) => ({
|
|
@@ -408,12 +408,12 @@ var k = {
|
|
|
408
408
|
})), ...t.y === void 0 ? [{
|
|
409
409
|
code: "MISSING_AESTHETIC",
|
|
410
410
|
message: "boxplot stat summarises 'y'; map it to the raw values"
|
|
411
|
-
}] : []] :
|
|
411
|
+
}] : []] : ze.filter((o) => t[o] === void 0).map((o) => ({
|
|
412
412
|
code: "MISSING_AESTHETIC",
|
|
413
413
|
message: `boxplot geom requires '${o}' when its data is already summarised`,
|
|
414
414
|
context: { aesthetic: o }
|
|
415
415
|
})), this.resolveAnchorPosition = (t, { coordSystem: r }) => {
|
|
416
|
-
const o = E(r), n =
|
|
416
|
+
const o = E(r), n = Qe(t, o);
|
|
417
417
|
return n === null ? null : o === "x" ? {
|
|
418
418
|
x: n.band,
|
|
419
419
|
y: n.value
|
|
@@ -437,12 +437,12 @@ var k = {
|
|
|
437
437
|
data: e,
|
|
438
438
|
mapping: {}
|
|
439
439
|
};
|
|
440
|
-
const { outliers: a, notch: s, showMean:
|
|
440
|
+
const { outliers: a, notch: s, showMean: l, varwidth: u } = r, i = q(e, t.outlier), h = a === !1 && i !== null ? et(e, i) : e, p = q(h, t.count), g = Y(r) / 2;
|
|
441
441
|
return {
|
|
442
|
-
data: h.addVariable(k.relativeWidth, "numeric", u === !0 && p !== null ?
|
|
442
|
+
data: h.addVariable(k.relativeWidth, "numeric", u === !0 && p !== null ? Ze(h, p) : Je(h)).addVariable(_.yMin, "numeric", Q(h, o, i)).addVariable(_.yMax, "numeric", Q(h, n, i)).addConstantVariable(_.xMin, "numeric", -g).addConstantVariable(_.xMax, "numeric", g),
|
|
443
443
|
mapping: {
|
|
444
444
|
...t.y === void 0 && { y: t.median },
|
|
445
|
-
...
|
|
445
|
+
...l === !0 && t.mean === void 0 && h.hasVariable(k.mean) && { mean: k.mean },
|
|
446
446
|
...s === !0 && t.notchLower === void 0 && h.hasVariable(k.notchLower) && {
|
|
447
447
|
notchLower: k.notchLower,
|
|
448
448
|
notchUpper: k.notchUpper
|
|
@@ -470,7 +470,7 @@ var k = {
|
|
|
470
470
|
const o = r !== null && r > 1 ? 1 : void 0;
|
|
471
471
|
return t?.addWarning({
|
|
472
472
|
code: "INVALID_GEOM_PARAM",
|
|
473
|
-
message: `Boxplot width must be a fraction in (0, 1], got ${String(e)}; falling back to ${o ??
|
|
473
|
+
message: `Boxplot width must be a fraction in (0, 1], got ${String(e)}; falling back to ${o ?? ie}.`,
|
|
474
474
|
context: {
|
|
475
475
|
geom: this.type,
|
|
476
476
|
param: "width",
|
|
@@ -480,10 +480,10 @@ var k = {
|
|
|
480
480
|
suggestion: "Set params.width to a fraction of the category band in (0, 1]."
|
|
481
481
|
}), o !== void 0 ? { width: o } : {};
|
|
482
482
|
}
|
|
483
|
-
},
|
|
483
|
+
}, Qe = (e, t) => {
|
|
484
484
|
const r = re(e, t);
|
|
485
485
|
if (r !== null) return {
|
|
486
|
-
band:
|
|
486
|
+
band: V(r),
|
|
487
487
|
value: r.median
|
|
488
488
|
};
|
|
489
489
|
const o = oe(e, t);
|
|
@@ -491,52 +491,97 @@ var k = {
|
|
|
491
491
|
band: o.band,
|
|
492
492
|
value: o.value
|
|
493
493
|
};
|
|
494
|
-
},
|
|
494
|
+
}, Y = ({ width: e }) => e ?? ie, Ze = (e, t) => {
|
|
495
495
|
const r = e.getValues(t, { type: "numeric" }), o = Math.max(0, ...r.map((n) => n ?? 0));
|
|
496
496
|
return r.map((n) => n === null || o === 0 ? null : Math.sqrt(n / o));
|
|
497
|
-
},
|
|
497
|
+
}, Je = (e) => Array.from({ length: e.size() }, () => null), Q = (e, t, r) => {
|
|
498
498
|
const o = r === null ? [] : e.getValues(r, { type: "numeric" });
|
|
499
499
|
return e.getValues(t, { type: "numeric" }).map((n, a) => n ?? o[a] ?? null);
|
|
500
|
-
},
|
|
500
|
+
}, et = (e, t) => {
|
|
501
501
|
const r = e.getValues(t, { type: "numeric" });
|
|
502
502
|
return e.take(r.flatMap((o, n) => o === null ? [n] : []));
|
|
503
503
|
}, q = (e, t) => {
|
|
504
|
-
const r =
|
|
504
|
+
const r = N(t);
|
|
505
505
|
return r !== null && e.hasVariable(r) ? r : null;
|
|
506
|
-
},
|
|
507
|
-
const r = (e.q1 + e.q3) / 2, o = Math.max(Math.abs(e.q3 - e.q1),
|
|
506
|
+
}, tt = 5e-4, rt = 0.5, ot = 0.5, le = (e, t) => {
|
|
507
|
+
const r = (e.q1 + e.q3) / 2, o = Math.max(Math.abs(e.q3 - e.q1), tt) / 2, n = v(t, {
|
|
508
|
+
main: e.start,
|
|
509
|
+
cross: r - o
|
|
510
|
+
}), a = v(t, {
|
|
511
|
+
main: e.end,
|
|
512
|
+
cross: r + o
|
|
513
|
+
}), [s, l] = Z(n.x, a.x), [u, i] = Z(n.y, a.y);
|
|
508
514
|
return {
|
|
509
515
|
x: s,
|
|
510
516
|
y: u,
|
|
511
|
-
width:
|
|
512
|
-
height:
|
|
517
|
+
width: l - s,
|
|
518
|
+
height: i - u
|
|
513
519
|
};
|
|
514
520
|
}, ue = (e, t) => {
|
|
515
521
|
if (e.notch === null) return null;
|
|
516
522
|
const { lower: r, upper: o } = e.notch, [n, a] = he(e);
|
|
517
523
|
return [
|
|
518
|
-
v(t,
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
v(t,
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
v(t,
|
|
527
|
-
|
|
524
|
+
v(t, {
|
|
525
|
+
main: e.start,
|
|
526
|
+
cross: e.q1
|
|
527
|
+
}),
|
|
528
|
+
v(t, {
|
|
529
|
+
main: e.start,
|
|
530
|
+
cross: r
|
|
531
|
+
}),
|
|
532
|
+
v(t, {
|
|
533
|
+
main: n,
|
|
534
|
+
cross: e.median
|
|
535
|
+
}),
|
|
536
|
+
v(t, {
|
|
537
|
+
main: e.start,
|
|
538
|
+
cross: o
|
|
539
|
+
}),
|
|
540
|
+
v(t, {
|
|
541
|
+
main: e.start,
|
|
542
|
+
cross: e.q3
|
|
543
|
+
}),
|
|
544
|
+
v(t, {
|
|
545
|
+
main: e.end,
|
|
546
|
+
cross: e.q3
|
|
547
|
+
}),
|
|
548
|
+
v(t, {
|
|
549
|
+
main: e.end,
|
|
550
|
+
cross: o
|
|
551
|
+
}),
|
|
552
|
+
v(t, {
|
|
553
|
+
main: a,
|
|
554
|
+
cross: e.median
|
|
555
|
+
}),
|
|
556
|
+
v(t, {
|
|
557
|
+
main: e.end,
|
|
558
|
+
cross: r
|
|
559
|
+
}),
|
|
560
|
+
v(t, {
|
|
561
|
+
main: e.end,
|
|
562
|
+
cross: e.q1
|
|
563
|
+
})
|
|
528
564
|
];
|
|
529
|
-
},
|
|
565
|
+
}, nt = (e, t) => {
|
|
530
566
|
const [r, o] = e.notch === null ? [e.start, e.end] : he(e);
|
|
531
567
|
return {
|
|
532
|
-
from: v(t,
|
|
533
|
-
|
|
568
|
+
from: v(t, {
|
|
569
|
+
main: r,
|
|
570
|
+
cross: e.median
|
|
571
|
+
}),
|
|
572
|
+
to: v(t, {
|
|
573
|
+
main: o,
|
|
574
|
+
cross: e.median
|
|
575
|
+
})
|
|
534
576
|
};
|
|
535
|
-
}, ce = (e, t) => e.mean === null ? null : v(t,
|
|
536
|
-
|
|
577
|
+
}, ce = (e, t) => e.mean === null ? null : v(t, {
|
|
578
|
+
main: V(e),
|
|
579
|
+
cross: e.mean
|
|
580
|
+
}), he = (e) => {
|
|
581
|
+
const t = (e.end - e.start) * (1 - ot) / 2;
|
|
537
582
|
return [e.start + t, e.end - t];
|
|
538
583
|
}, de = (e, t) => {
|
|
539
|
-
const r =
|
|
584
|
+
const r = V(e), o = (e.end - e.start) * rt / 2;
|
|
540
585
|
return [{
|
|
541
586
|
side: "lower",
|
|
542
587
|
quartile: e.q1,
|
|
@@ -548,30 +593,33 @@ var k = {
|
|
|
548
593
|
}].filter(({ quartile: n, reach: a }) => n !== a).map(({ side: n, quartile: a, reach: s }) => ({
|
|
549
594
|
side: n,
|
|
550
595
|
stem: {
|
|
551
|
-
from: v(t,
|
|
552
|
-
|
|
596
|
+
from: v(t, {
|
|
597
|
+
main: r,
|
|
598
|
+
cross: a
|
|
599
|
+
}),
|
|
600
|
+
to: v(t, {
|
|
601
|
+
main: r,
|
|
602
|
+
cross: s
|
|
603
|
+
})
|
|
553
604
|
},
|
|
554
605
|
cap: {
|
|
555
|
-
from: v(t,
|
|
556
|
-
|
|
606
|
+
from: v(t, {
|
|
607
|
+
main: r - o,
|
|
608
|
+
cross: s
|
|
609
|
+
}),
|
|
610
|
+
to: v(t, {
|
|
611
|
+
main: r + o,
|
|
612
|
+
cross: s
|
|
613
|
+
})
|
|
557
614
|
}
|
|
558
615
|
}));
|
|
559
|
-
},
|
|
560
|
-
const o = Ie(e, {
|
|
561
|
-
main: t,
|
|
562
|
-
cross: r
|
|
563
|
-
});
|
|
564
|
-
return {
|
|
565
|
-
x: qe(o.x),
|
|
566
|
-
y: Pe(o.y)
|
|
567
|
-
};
|
|
568
|
-
}, Z = (e, t) => e <= t ? [e, t] : [t, e], T = (e, t) => ({
|
|
616
|
+
}, Z = (e, t) => e <= t ? [e, t] : [t, e], B = (e, t) => ({
|
|
569
617
|
x: e.x * t.width,
|
|
570
618
|
y: e.y * t.height
|
|
571
|
-
}),
|
|
572
|
-
const { x: n, y: a } =
|
|
619
|
+
}), H = (e, t) => `${e.map((r, o) => {
|
|
620
|
+
const { x: n, y: a } = B(r, t);
|
|
573
621
|
return `${o === 0 ? "M" : "L"}${n},${a}`;
|
|
574
|
-
}).join("")}Z`,
|
|
622
|
+
}).join("")}Z`, at = (e, t) => H([
|
|
575
623
|
{
|
|
576
624
|
x: e.x,
|
|
577
625
|
y: e.y
|
|
@@ -588,68 +636,71 @@ var k = {
|
|
|
588
636
|
x: e.x,
|
|
589
637
|
y: e.y + e.height
|
|
590
638
|
}
|
|
591
|
-
], t),
|
|
592
|
-
const r =
|
|
639
|
+
], t), st = (e, t) => {
|
|
640
|
+
const r = B(e.from, t), o = B(e.to, t);
|
|
593
641
|
return `M${r.x},${r.y}L${o.x},${o.y}`;
|
|
594
|
-
},
|
|
595
|
-
const n = E(t), { boxes: a, outliers: s } = I(e.data, n),
|
|
642
|
+
}, it = ({ layer: e, coordSystem: t, panelRect: r, styleReaders: o }) => {
|
|
643
|
+
const n = E(t), { boxes: a, outliers: s } = I(e.data, n), l = a.map((c) => {
|
|
596
644
|
const f = ue(c, n);
|
|
597
645
|
return f !== null ? {
|
|
598
646
|
kind: "region",
|
|
599
|
-
pathData:
|
|
647
|
+
pathData: H(f, r)
|
|
600
648
|
} : {
|
|
601
649
|
kind: "region",
|
|
602
|
-
pathData:
|
|
650
|
+
pathData: at(le(c, n), r)
|
|
603
651
|
};
|
|
604
|
-
}), u = o.part("whisker"),
|
|
652
|
+
}), u = o.part("whisker"), i = o.part("cap"), h = a.flatMap((c) => de(c, n).flatMap((f) => [{
|
|
605
653
|
segment: f.stem,
|
|
606
654
|
readers: u
|
|
607
655
|
}, {
|
|
608
656
|
segment: f.cap,
|
|
609
|
-
readers:
|
|
657
|
+
readers: i
|
|
610
658
|
}].flatMap(({ segment: W, readers: L }) => {
|
|
611
659
|
const O = L?.get("strokeWidth", c.observation) ?? 0;
|
|
612
660
|
return O > 0 ? [{
|
|
613
661
|
kind: "stroke",
|
|
614
|
-
pathData:
|
|
662
|
+
pathData: st(W, r),
|
|
615
663
|
width: O
|
|
616
664
|
}] : [];
|
|
617
665
|
}))), p = o.part("outlier"), g = p === void 0 ? [] : s.map((c) => ({
|
|
618
|
-
center:
|
|
666
|
+
center: B(v(n, {
|
|
667
|
+
main: c.band,
|
|
668
|
+
cross: c.value
|
|
669
|
+
}), r),
|
|
619
670
|
size: J(p, c.observation)
|
|
620
671
|
})), d = o.part("mean"), m = d === void 0 ? [] : a.flatMap((c) => {
|
|
621
672
|
const f = ce(c, n);
|
|
622
673
|
return f === null ? [] : [{
|
|
623
|
-
center:
|
|
674
|
+
center: B(f, r),
|
|
624
675
|
size: J(d, c.observation)
|
|
625
676
|
}];
|
|
626
677
|
}), w = Se([...g, ...m]);
|
|
627
678
|
return [
|
|
628
679
|
...h,
|
|
629
|
-
...
|
|
680
|
+
...l,
|
|
630
681
|
...w
|
|
631
682
|
];
|
|
632
|
-
}, J = (e, t) => (e.get("size", t) ?? 0) + (e.get("strokeWidth", t) ?? 0),
|
|
633
|
-
const t =
|
|
683
|
+
}, J = (e, t) => (e.get("size", t) ?? 0) + (e.get("strokeWidth", t) ?? 0), X = (e) => {
|
|
684
|
+
const t = Ie(e.data, e.mapping, e.id), r = N(e.mapping.outlier), o = (n) => `${t(n.observation)}-outlier-${String(r === null ? n.value : n.observation[r])}`;
|
|
634
685
|
return {
|
|
635
686
|
readBoxKey: t,
|
|
636
687
|
readOutlierKeys: (n) => {
|
|
637
688
|
const a = /* @__PURE__ */ new Map();
|
|
638
689
|
return n.map((s) => {
|
|
639
|
-
const
|
|
640
|
-
return a.set(
|
|
690
|
+
const l = o(s), u = a.get(l) ?? 0;
|
|
691
|
+
return a.set(l, u + 1), u === 0 ? l : `${l}-${u}`;
|
|
641
692
|
});
|
|
642
693
|
}
|
|
643
694
|
};
|
|
644
|
-
},
|
|
645
|
-
const o = e.data.getVariableNames(), n = (s) => JSON.stringify(o.map((
|
|
695
|
+
}, lt = (e, t, r) => {
|
|
696
|
+
const o = e.data.getVariableNames(), n = (s) => JSON.stringify(o.map((l) => s.observation[l] ?? null)), a = new Set(r.map(n));
|
|
646
697
|
return t.filter((s) => a.has(n(s)));
|
|
647
698
|
}, pe = (e, t, r) => {
|
|
648
699
|
const o = new Set(t.map((n) => r(n.observation)));
|
|
649
700
|
return e.filter((n) => o.has(r(n.observation)));
|
|
650
|
-
}, z = ({ boxes: e, outliers: t, mainAxis: r, panelSize: o, source: n, styleReaders: a, keys: s, hovered:
|
|
651
|
-
const
|
|
652
|
-
return /* @__PURE__ */
|
|
701
|
+
}, z = ({ boxes: e, outliers: t, mainAxis: r, panelSize: o, source: n, styleReaders: a, keys: s, hovered: l, animateTransitions: u = !1 }) => {
|
|
702
|
+
const i = l === void 0 ? void 0 : "hovered", h = a.part("whisker"), p = a.part("cap"), g = a.part("median"), d = a.part("mean"), m = a.part("outlier"), w = s.readOutlierKeys(t);
|
|
703
|
+
return /* @__PURE__ */ qe(_e, { children: [
|
|
653
704
|
e.flatMap((c) => de(c, r).flatMap((f) => [{
|
|
654
705
|
piece: "stem",
|
|
655
706
|
testId: "boxplot-whisker",
|
|
@@ -663,28 +714,28 @@ var k = {
|
|
|
663
714
|
segment: f[W],
|
|
664
715
|
observation: c.observation,
|
|
665
716
|
readers: O,
|
|
666
|
-
state:
|
|
717
|
+
state: i,
|
|
667
718
|
animateTransitions: u
|
|
668
719
|
}, `${s.readBoxKey(c.observation)}-${f.side}-${W}`)))),
|
|
669
720
|
/* @__PURE__ */ y(ye, {
|
|
670
721
|
styleReaders: a,
|
|
671
|
-
state:
|
|
672
|
-
children: e.map((c) => /* @__PURE__ */ y(
|
|
722
|
+
state: i,
|
|
723
|
+
children: e.map((c) => /* @__PURE__ */ y(ut, {
|
|
673
724
|
box: c,
|
|
674
725
|
mainAxis: r,
|
|
675
726
|
panelSize: o,
|
|
676
727
|
source: n,
|
|
677
728
|
styleReaders: a,
|
|
678
|
-
state:
|
|
729
|
+
state: i,
|
|
679
730
|
animateTransitions: u
|
|
680
731
|
}, s.readBoxKey(c.observation)))
|
|
681
732
|
}),
|
|
682
733
|
g && e.map((c) => /* @__PURE__ */ y(ee, {
|
|
683
734
|
testId: "boxplot-median",
|
|
684
|
-
segment:
|
|
735
|
+
segment: nt(c, r),
|
|
685
736
|
observation: c.observation,
|
|
686
737
|
readers: g,
|
|
687
|
-
state:
|
|
738
|
+
state: i,
|
|
688
739
|
animateTransitions: u
|
|
689
740
|
}, s.readBoxKey(c.observation))),
|
|
690
741
|
d && e.map((c) => {
|
|
@@ -694,39 +745,42 @@ var k = {
|
|
|
694
745
|
centre: f,
|
|
695
746
|
observation: c.observation,
|
|
696
747
|
readers: d,
|
|
697
|
-
state:
|
|
748
|
+
state: i,
|
|
698
749
|
animateTransitions: u
|
|
699
750
|
}, s.readBoxKey(c.observation));
|
|
700
751
|
}),
|
|
701
752
|
m && t.map((c, f) => /* @__PURE__ */ y(te, {
|
|
702
753
|
testId: "boxplot-outlier",
|
|
703
|
-
centre: v(r,
|
|
754
|
+
centre: v(r, {
|
|
755
|
+
main: c.band,
|
|
756
|
+
cross: c.value
|
|
757
|
+
}),
|
|
704
758
|
observation: c.observation,
|
|
705
759
|
readers: m,
|
|
706
|
-
state:
|
|
760
|
+
state: i,
|
|
707
761
|
animateTransitions: u
|
|
708
762
|
}, w[f]))
|
|
709
763
|
] });
|
|
710
764
|
}, ee = ({ testId: e, segment: t, observation: r, readers: o, state: n, animateTransitions: a }) => {
|
|
711
|
-
const s = o.get("strokeWidth", r, n) ?? 0,
|
|
765
|
+
const s = o.get("strokeWidth", r, n) ?? 0, l = o.get("stroke", r, n);
|
|
712
766
|
return /* @__PURE__ */ y(fe, {
|
|
713
767
|
"data-testid": e,
|
|
714
768
|
x1: x(t.from.x),
|
|
715
769
|
y1: x(t.from.y),
|
|
716
770
|
x2: x(t.to.x),
|
|
717
771
|
y2: x(t.to.y),
|
|
718
|
-
stroke:
|
|
772
|
+
stroke: l === void 0 ? void 0 : T(l),
|
|
719
773
|
strokeOpacity: o.get("alpha", r, n),
|
|
720
774
|
strokeWidth: s,
|
|
721
|
-
strokeDasharray:
|
|
775
|
+
strokeDasharray: Be(o.get("dashArray", r, n), s),
|
|
722
776
|
animateTransitions: a
|
|
723
777
|
});
|
|
724
|
-
},
|
|
725
|
-
const
|
|
726
|
-
fill:
|
|
778
|
+
}, ut = ({ box: e, mainAxis: t, panelSize: r, source: o, styleReaders: n, state: a, animateTransitions: s }) => {
|
|
779
|
+
const l = n.get("fill", e.observation, a), u = n.get("stroke", e.observation, a), i = {
|
|
780
|
+
fill: l === void 0 ? void 0 : T(l),
|
|
727
781
|
opacity: n.get("alpha", e.observation, a),
|
|
728
782
|
fillOpacity: n.get("fillAlpha", e.observation, a),
|
|
729
|
-
stroke: u === void 0 ? void 0 :
|
|
783
|
+
stroke: u === void 0 ? void 0 : T(u),
|
|
730
784
|
strokeOpacity: n.get("strokeAlpha", e.observation, a),
|
|
731
785
|
strokeWidth: n.get("strokeWidth", e.observation, a),
|
|
732
786
|
effects: Te(n, e.observation, a),
|
|
@@ -734,11 +788,11 @@ var k = {
|
|
|
734
788
|
}, h = ue(e, t);
|
|
735
789
|
if (h !== null) return /* @__PURE__ */ y(ke, {
|
|
736
790
|
"data-testid": "boxplot-box",
|
|
737
|
-
d:
|
|
791
|
+
d: H(h, r),
|
|
738
792
|
source: o,
|
|
739
|
-
...
|
|
793
|
+
...i
|
|
740
794
|
});
|
|
741
|
-
const p =
|
|
795
|
+
const p = le(e, t);
|
|
742
796
|
return /* @__PURE__ */ y(we, {
|
|
743
797
|
"data-testid": "boxplot-box",
|
|
744
798
|
x: x(p.x),
|
|
@@ -746,28 +800,28 @@ var k = {
|
|
|
746
800
|
width: x(p.width),
|
|
747
801
|
height: x(p.height),
|
|
748
802
|
cornerRadius: n.get("cornerRadius", e.observation, a),
|
|
749
|
-
...
|
|
803
|
+
...i
|
|
750
804
|
});
|
|
751
805
|
}, te = ({ testId: e, centre: t, observation: r, readers: o, state: n, animateTransitions: a }) => {
|
|
752
|
-
const s = o.get("fill", r, n),
|
|
806
|
+
const s = o.get("fill", r, n), l = o.get("stroke", r, n);
|
|
753
807
|
return /* @__PURE__ */ y(ge, {
|
|
754
808
|
"data-testid": e,
|
|
755
809
|
cx: x(t.x),
|
|
756
810
|
cy: x(t.y),
|
|
757
811
|
r: (o.get("size", r, n) ?? 0) / 2,
|
|
758
|
-
fill: s === void 0 ? void 0 :
|
|
812
|
+
fill: s === void 0 ? void 0 : T(s),
|
|
759
813
|
opacity: o.get("alpha", r, n),
|
|
760
814
|
fillOpacity: o.get("fillAlpha", r, n),
|
|
761
|
-
stroke:
|
|
815
|
+
stroke: l === void 0 ? void 0 : T(l),
|
|
762
816
|
strokeWidth: o.get("strokeWidth", r, n),
|
|
763
817
|
symbol: o.get("symbol", r, n),
|
|
764
818
|
animateTransitions: a
|
|
765
819
|
});
|
|
766
|
-
},
|
|
767
|
-
const n = F(), a = S(() =>
|
|
768
|
-
const
|
|
820
|
+
}, ct = ({ layer: e, sourceLayer: t, mainAxis: r, styleReaders: o }) => {
|
|
821
|
+
const n = F(), a = S(() => X(t), [t]), s = S(() => I(t.data, r).outliers, [t.data, r]), { boxes: l, outliers: u } = S(() => {
|
|
822
|
+
const i = I(e.data, r), h = new Set(lt(t, s, i.outliers)), p = new Set(pe(s, i.boxes, a.readBoxKey)), g = s.filter((d) => p.has(d) || h.has(d));
|
|
769
823
|
return {
|
|
770
|
-
boxes:
|
|
824
|
+
boxes: i.boxes,
|
|
771
825
|
outliers: g
|
|
772
826
|
};
|
|
773
827
|
}, [
|
|
@@ -778,7 +832,7 @@ var k = {
|
|
|
778
832
|
a
|
|
779
833
|
]);
|
|
780
834
|
return /* @__PURE__ */ y(z, {
|
|
781
|
-
boxes:
|
|
835
|
+
boxes: l,
|
|
782
836
|
outliers: u,
|
|
783
837
|
mainAxis: r,
|
|
784
838
|
panelSize: n,
|
|
@@ -786,13 +840,13 @@ var k = {
|
|
|
786
840
|
styleReaders: o,
|
|
787
841
|
keys: a
|
|
788
842
|
});
|
|
789
|
-
},
|
|
790
|
-
const n = F(), a = S(() => I(e.data, r).outliers, [e.data, r]), s = S(() =>
|
|
843
|
+
}, ht = ({ layer: e, primary: t, mainAxis: r, styleReaders: o }) => {
|
|
844
|
+
const n = F(), a = S(() => I(e.data, r).outliers, [e.data, r]), s = S(() => X(e), [e]), { boxes: l, outliers: u } = I([t.observation], r);
|
|
791
845
|
return /* @__PURE__ */ y("g", {
|
|
792
846
|
"data-testid": "hovered-boxes",
|
|
793
847
|
children: /* @__PURE__ */ y(z, {
|
|
794
|
-
boxes:
|
|
795
|
-
outliers:
|
|
848
|
+
boxes: l,
|
|
849
|
+
outliers: l.length > 0 ? pe(a, l, s.readBoxKey) : u,
|
|
796
850
|
mainAxis: r,
|
|
797
851
|
panelSize: n,
|
|
798
852
|
source: e,
|
|
@@ -801,15 +855,15 @@ var k = {
|
|
|
801
855
|
hovered: t.observation
|
|
802
856
|
})
|
|
803
857
|
});
|
|
804
|
-
},
|
|
805
|
-
const a = F(), { boxes: s, outliers:
|
|
858
|
+
}, dt = ({ layer: e, mainAxis: t, styleReaders: r, animateTransitions: o, intro: n }) => {
|
|
859
|
+
const a = F(), { boxes: s, outliers: l } = S(() => I(e.data, t), [e.data, t]), u = /* @__PURE__ */ y(z, {
|
|
806
860
|
boxes: s,
|
|
807
|
-
outliers:
|
|
861
|
+
outliers: l,
|
|
808
862
|
mainAxis: t,
|
|
809
863
|
panelSize: a,
|
|
810
864
|
source: e,
|
|
811
865
|
styleReaders: r,
|
|
812
|
-
keys: S(() =>
|
|
866
|
+
keys: S(() => X(e), [e]),
|
|
813
867
|
animateTransitions: o
|
|
814
868
|
});
|
|
815
869
|
return n == null ? u : /* @__PURE__ */ y(xe, {
|
|
@@ -820,34 +874,34 @@ var k = {
|
|
|
820
874
|
},
|
|
821
875
|
children: u
|
|
822
876
|
});
|
|
823
|
-
},
|
|
877
|
+
}, gt = Oe(new Ye(), {
|
|
824
878
|
coord: "cartesian",
|
|
825
879
|
swatchShape: "square",
|
|
826
880
|
overpaintPlacement: "manual",
|
|
827
881
|
guideMode: "band",
|
|
828
|
-
render: ({ layer: e, coordSystem: t, styleReaders: r, animateTransitions: o, intro: n }) => /* @__PURE__ */ y(
|
|
882
|
+
render: ({ layer: e, coordSystem: t, styleReaders: r, animateTransitions: o, intro: n }) => /* @__PURE__ */ y(dt, {
|
|
829
883
|
layer: e,
|
|
830
884
|
mainAxis: E(t),
|
|
831
885
|
styleReaders: r,
|
|
832
886
|
animateTransitions: o,
|
|
833
887
|
intro: n
|
|
834
888
|
}),
|
|
835
|
-
renderHighlight: ({ layer: e, sourceLayer: t, coordSystem: r, styleReaders: o }) => /* @__PURE__ */ y(
|
|
889
|
+
renderHighlight: ({ layer: e, sourceLayer: t, coordSystem: r, styleReaders: o }) => /* @__PURE__ */ y(ct, {
|
|
836
890
|
layer: e,
|
|
837
891
|
sourceLayer: t,
|
|
838
892
|
mainAxis: E(r),
|
|
839
893
|
styleReaders: o
|
|
840
894
|
}),
|
|
841
|
-
renderHover: ({ layer: e, primary: t, coordSystem: r, styleReaders: o }) => /* @__PURE__ */ y(
|
|
895
|
+
renderHover: ({ layer: e, primary: t, coordSystem: r, styleReaders: o }) => /* @__PURE__ */ y(ht, {
|
|
842
896
|
layer: e,
|
|
843
897
|
primary: t,
|
|
844
898
|
mainAxis: E(r),
|
|
845
899
|
styleReaders: o
|
|
846
900
|
}),
|
|
847
|
-
getEditOutlineShapes:
|
|
901
|
+
getEditOutlineShapes: it
|
|
848
902
|
});
|
|
849
903
|
export {
|
|
850
904
|
k as BOXPLOT_VARIABLES,
|
|
851
|
-
|
|
852
|
-
|
|
905
|
+
Ye as BoxplotGeom,
|
|
906
|
+
gt as boxplot
|
|
853
907
|
};
|
|
@@ -32,5 +32,3 @@ export declare const readMedianSegment: (box: Box, mainAxis: MainAxis) => ViewBo
|
|
|
32
32
|
export declare const readMeanPoint: (box: Box, mainAxis: MainAxis) => XYPoint | null;
|
|
33
33
|
/** The whiskers that reach past the box; one that ends on its quartile draws nothing. */
|
|
34
34
|
export declare const readWhiskers: (box: Box, mainAxis: MainAxis) => Whisker[];
|
|
35
|
-
/** A point placed by its main-axis and value-axis fractions, in the view box. */
|
|
36
|
-
export declare const toViewBox: (mainAxis: MainAxis, main: number, cross: number) => XYPoint;
|
|
@@ -18,7 +18,7 @@ export interface Box {
|
|
|
18
18
|
upper: number;
|
|
19
19
|
} | null;
|
|
20
20
|
}
|
|
21
|
-
/** A value past its box's whiskers, standing on the box's
|
|
21
|
+
/** A value past its box's whiskers, standing on the box's center line. */
|
|
22
22
|
export interface Outlier {
|
|
23
23
|
observation: Observation;
|
|
24
24
|
/** The centre of its box's share of the band. */
|
|
@@ -29,7 +29,7 @@ export interface Boxplot {
|
|
|
29
29
|
boxes: Box[];
|
|
30
30
|
outliers: Outlier[];
|
|
31
31
|
}
|
|
32
|
-
/** The
|
|
32
|
+
/** The center line a box's whiskers and outliers stand on. */
|
|
33
33
|
export declare const readBoxCentre: (box: Pick<Box, "start" | "end">) => number;
|
|
34
34
|
/**
|
|
35
35
|
* Reads where a box sits. The flip is already baked into the position columns, so under `coord.flip()` the
|
package/package.json
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"boxplot",
|
|
14
14
|
"box-plot"
|
|
15
15
|
],
|
|
16
|
-
"version": "0.1.1-beta.
|
|
16
|
+
"version": "0.1.1-beta.1794395798194",
|
|
17
17
|
"type": "module",
|
|
18
18
|
"sideEffects": false,
|
|
19
19
|
"types": "./dist/index.d.ts",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
},
|
|
33
33
|
"peerDependencies": {
|
|
34
34
|
"react": "^19.0.0",
|
|
35
|
-
"@graphysdk/react": "^1.9.0-beta.
|
|
35
|
+
"@graphysdk/react": "^1.9.0-beta.1794395798194"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@testing-library/react": "^16.3.1",
|
|
@@ -44,8 +44,8 @@
|
|
|
44
44
|
"vite": "^8.1.5",
|
|
45
45
|
"vite-plugin-dts": "^4.5.4",
|
|
46
46
|
"vitest": "^4.1.11",
|
|
47
|
-
"@graphysdk/react": "1.9.0-beta.
|
|
48
|
-
"@graphysdk/viz-engine": "1.9.0-beta.
|
|
47
|
+
"@graphysdk/react": "1.9.0-beta.1794395798194",
|
|
48
|
+
"@graphysdk/viz-engine": "1.9.0-beta.1794395798194",
|
|
49
49
|
"@graphytools/eslint-config": "0.0.1",
|
|
50
50
|
"@graphytools/typescript-config": "0.0.1",
|
|
51
51
|
"@graphytools/vitest-config": "1.0.0"
|