src/blackrock/DitherChart.tsx
import {Card} from '@whop/react/components';
import {FillPattern} from '../lib/dither/fill';
import {number,time} from './api';
import './dither-chart.css';
/** One set per chart, with a React useId prefix to avoid collisions in dossiers. */
export function ChartPatterns({id}:{id:string}){
return <defs>
<FillPattern id={`${id}-buy`} fill="dotted" cell={1.5} color="var(--green-11)"/>
<FillPattern id={`${id}-sell`} fill="hatched" cell={1.5} color="var(--amber-11)"/>
<FillPattern id={`${id}-volume`} fill="dotted" cell={1.5} color="var(--blue-11)"/>
<FillPattern id={`${id}-price`} fill="gradient" level={.125} cell={1.5} color="var(--blue-10)"/>
<FillPattern id={`${id}-rise`} fill="dotted" cell={1.5} color="var(--green-11)"/>
<FillPattern id={`${id}-fall`} fill="hatched" cell={1.5} color="var(--red-11)"/>
</defs>;
}
/** Static bodies with solid caps; tiny bars retain their true geometry and a solid fill. */
export function DitherBar({x,y,width,height,pattern,color,horizontal=false,negative=false,label,onPick}:any){
if(![x,y,width,height].every(Number.isFinite)||width===0||height===0)return null;
const w=Math.abs(width),h=Math.abs(height),left=Math.min(x,x+width),top=Math.min(y,y+height);
const tiny=Math.min(w,h)<6;
return <g className={`dither-data-bar ${onPick?'dither-data-bar-action':''}`} role={onPick?'button':undefined} tabIndex={onPick?0:undefined} aria-label={label} onClick={onPick} onKeyDown={onPick?e=>{if(e.key==='Enter'||e.key===' '){e.preventDefault();onPick();}}:undefined}>
<rect x={left} y={top} width={w} height={h} fill={color} opacity={tiny?1:.14}/>
{!tiny&&<><rect className="dither-bar-body" x={left} y={top} width={w} height={h} fill={`url(#${pattern})`}/><rect x={horizontal?(negative?left:left+w-Math.min(2,w)):left} y={horizontal?top:top} width={horizontal?Math.min(2,w):w} height={horizontal?h:Math.min(2,h)} fill={color}/></>}
</g>;
}
export function ChartTooltip({active,payload,label,dates=true,unit='GP',labelFormat}:any){
if(!active||!payload?.length)return null;
return <Card className="dither-chart-tooltip" size="1"><strong>{labelFormat?labelFormat(label):dates?time(label):label}</strong>{payload.filter((p:any)=>p.value!=null).map((p:any)=><div key={p.dataKey}><span>{p.name}</span><b>{number(p.value)} {unit}</b></div>)}</Card>;
}