- Sparkline 컴포넌트를 PriceHero 내부에서 web/components/Sparkline.tsx 로 분리·재사용 - /api/markets/indices: macro_daily 의 kospi/kosdaq N일 시계열 + 최신값/전일대비 - 홈 IndicesPanel: 두 인덱스 카드(현재값/등락/우측 sparkline) - /api/symbols/search?with_sparkline=true: 결과 한 번에 최근 30 종가 batch 조회 - SearchBox 결과 행에 mini sparkline + 현재가/등락률 인라인 표시 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
50 lines
1.2 KiB
TypeScript
50 lines
1.2 KiB
TypeScript
// 가벼운 SVG sparkline. lightweight-charts 인스턴스를 또 만들 필요 없음.
|
|
// 종가 시계열을 받아 polyline 으로 그린다. 색상은 호출부에서 결정 (KR 관행: 상승=빨강, 하락=파랑).
|
|
|
|
type Props = {
|
|
values: number[];
|
|
stroke: string;
|
|
width?: number;
|
|
height?: number;
|
|
className?: string;
|
|
};
|
|
|
|
export function Sparkline({
|
|
values,
|
|
stroke,
|
|
width = 140,
|
|
height = 44,
|
|
className,
|
|
}: Props) {
|
|
if (values.length < 2) return null;
|
|
const min = Math.min(...values);
|
|
const max = Math.max(...values);
|
|
const span = max - min || 1;
|
|
const stepX = width / (values.length - 1);
|
|
const points = values
|
|
.map((v, i) => {
|
|
const x = (i * stepX).toFixed(1);
|
|
const y = (height - ((v - min) / span) * height).toFixed(1);
|
|
return `${x},${y}`;
|
|
})
|
|
.join(" ");
|
|
return (
|
|
<svg
|
|
width={width}
|
|
height={height}
|
|
viewBox={`0 0 ${width} ${height}`}
|
|
className={`shrink-0 opacity-80 ${className ?? ""}`}
|
|
aria-hidden
|
|
>
|
|
<polyline
|
|
points={points}
|
|
fill="none"
|
|
stroke={stroke}
|
|
strokeWidth={1.5}
|
|
strokeLinejoin="round"
|
|
strokeLinecap="round"
|
|
/>
|
|
</svg>
|
|
);
|
|
}
|