`backend` 옆에 `front` 가 있을 이유가 없었다. negosium 의 negodata/front 를 그대로 베꼈고 그게 왜 front 인지는 따져보지 않았다 — 근거 없이 들여온 이름이라 바로잡는다. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019uYhHQdssRubirPirrdJJC
176 lines
5.7 KiB
XML
176 lines
5.7 KiB
XML
/**
|
||
* 배리에이션 와이어프레임 썸네일.
|
||
*
|
||
* 사장님은 "InfoTable" 이라는 이름으로 고르지 않는다 — 모양을 보고 고른다.
|
||
* 그래서 배리에이션 카드에는 반드시 그림이 붙고, 그 그림은 여기 한 곳에서만 그린다.
|
||
*/
|
||
import type {ThumbKey} from './types';
|
||
|
||
const BOX = 'fill-stone-300';
|
||
const LINE = 'fill-stone-200';
|
||
const ACCENT = 'fill-stone-500';
|
||
|
||
/** 40×28 좌표계 위에 회색 블록으로 레이아웃 얼개만 그린다. */
|
||
const SHAPES: Record<ThumbKey, React.ReactNode> = {
|
||
fullbleed: (
|
||
<>
|
||
<rect x="0" y="0" width="40" height="28" className={BOX} />
|
||
<rect x="3" y="18" width="20" height="3" className={ACCENT} />
|
||
<rect x="3" y="23" width="12" height="2" className={LINE} />
|
||
</>
|
||
),
|
||
split: (
|
||
<>
|
||
<rect x="2" y="6" width="16" height="3" className={ACCENT} />
|
||
<rect x="2" y="12" width="14" height="2" className={LINE} />
|
||
<rect x="2" y="16" width="10" height="2" className={LINE} />
|
||
<rect x="22" y="5" width="16" height="18" className={BOX} />
|
||
</>
|
||
),
|
||
stack: (
|
||
<>
|
||
<rect x="2" y="3" width="36" height="12" className={BOX} />
|
||
<rect x="2" y="18" width="24" height="2.5" className={ACCENT} />
|
||
<rect x="2" y="22" width="34" height="2" className={LINE} />
|
||
</>
|
||
),
|
||
centered: (
|
||
<>
|
||
<rect x="14" y="5" width="12" height="2" className={LINE} />
|
||
<rect x="9" y="10" width="22" height="3" className={ACCENT} />
|
||
<rect x="6" y="17" width="28" height="2" className={LINE} />
|
||
<rect x="10" y="21" width="20" height="2" className={LINE} />
|
||
</>
|
||
),
|
||
grid: (
|
||
<>
|
||
{[2, 11, 20, 29].map((x) =>
|
||
[4, 15].map((y) => (
|
||
<rect key={`${x}-${y}`} x={x} y={y} width="8" height="8" className={BOX} />
|
||
)),
|
||
)}
|
||
</>
|
||
),
|
||
masonry: (
|
||
<>
|
||
<rect x="2" y="3" width="11" height="13" className={BOX} />
|
||
<rect x="2" y="18" width="11" height="7" className={BOX} />
|
||
<rect x="15" y="3" width="11" height="8" className={BOX} />
|
||
<rect x="15" y="13" width="11" height="12" className={BOX} />
|
||
<rect x="28" y="3" width="10" height="14" className={BOX} />
|
||
<rect x="28" y="19" width="10" height="6" className={BOX} />
|
||
</>
|
||
),
|
||
carousel: (
|
||
<>
|
||
<rect x="1" y="6" width="6" height="14" className={LINE} />
|
||
<rect x="9" y="4" width="22" height="18" className={BOX} />
|
||
<rect x="33" y="6" width="6" height="14" className={LINE} />
|
||
<rect x="17" y="24" width="6" height="1.5" className={ACCENT} />
|
||
</>
|
||
),
|
||
list: (
|
||
<>
|
||
{[3, 11, 19].map((y) => (
|
||
<g key={y}>
|
||
<rect x="2" y={y} width="9" height="6" className={BOX} />
|
||
<rect x="13" y={y + 1} width="16" height="2" className={ACCENT} />
|
||
<rect x="13" y={y + 4} width="22" height="1.5" className={LINE} />
|
||
</g>
|
||
))}
|
||
</>
|
||
),
|
||
table: (
|
||
<>
|
||
<rect x="2" y="3" width="36" height="4" className={ACCENT} />
|
||
{[9, 14, 19, 24].map((y) => (
|
||
<g key={y}>
|
||
<rect x="2" y={y} width="14" height="2" className={LINE} />
|
||
<rect x="20" y={y} width="18" height="2" className={LINE} />
|
||
</g>
|
||
))}
|
||
</>
|
||
),
|
||
cards: (
|
||
<>
|
||
{[2, 21].map((x) =>
|
||
[3, 15].map((y) => (
|
||
<g key={`${x}-${y}`}>
|
||
<rect x={x} y={y} width="17" height="9" className={LINE} />
|
||
<rect x={x + 2} y={y + 2} width="9" height="2" className={ACCENT} />
|
||
<rect x={x + 2} y={y + 5.5} width="13" height="1.5" className={BOX} />
|
||
</g>
|
||
)),
|
||
)}
|
||
</>
|
||
),
|
||
accordion: (
|
||
<>
|
||
<rect x="2" y="3" width="36" height="4" className={ACCENT} />
|
||
<rect x="2" y="9" width="36" height="7" className={LINE} />
|
||
<rect x="2" y="18" width="36" height="4" className={ACCENT} />
|
||
<rect x="2" y="24" width="36" height="2" className={LINE} />
|
||
</>
|
||
),
|
||
'two-column': (
|
||
<>
|
||
{[2, 21].map((x) => (
|
||
<g key={x}>
|
||
<rect x={x} y="4" width="17" height="2.5" className={ACCENT} />
|
||
<rect x={x} y="8.5" width="15" height="1.5" className={LINE} />
|
||
<rect x={x} y="15" width="17" height="2.5" className={ACCENT} />
|
||
<rect x={x} y="19.5" width="15" height="1.5" className={LINE} />
|
||
</g>
|
||
))}
|
||
</>
|
||
),
|
||
banner: (
|
||
<>
|
||
<rect x="0" y="8" width="40" height="12" className={ACCENT} />
|
||
<rect x="4" y="11" width="16" height="2.5" className="fill-white/80" />
|
||
<rect x="26" y="11" width="10" height="5" className="fill-white/90" />
|
||
</>
|
||
),
|
||
form: (
|
||
<>
|
||
<rect x="2" y="3" width="20" height="2.5" className={ACCENT} />
|
||
<rect x="2" y="8" width="17" height="4" className={LINE} />
|
||
<rect x="21" y="8" width="17" height="4" className={LINE} />
|
||
<rect x="2" y="14" width="36" height="6" className={LINE} />
|
||
<rect x="2" y="22" width="36" height="4" className={ACCENT} />
|
||
</>
|
||
),
|
||
timeline: (
|
||
<>
|
||
<rect x="5" y="3" width="1.5" height="22" className={LINE} />
|
||
{[4, 12, 20].map((y) => (
|
||
<g key={y}>
|
||
<circle cx="5.75" cy={y + 1.5} r="2" className={ACCENT} />
|
||
<rect x="11" y={y} width="14" height="2" className={ACCENT} />
|
||
<rect x="11" y={y + 3.5} width="24" height="1.5" className={LINE} />
|
||
</g>
|
||
))}
|
||
</>
|
||
),
|
||
compact: (
|
||
<>
|
||
<rect x="2" y="8" width="12" height="2.5" className={ACCENT} />
|
||
<rect x="2" y="13" width="36" height="6" className={LINE} />
|
||
</>
|
||
),
|
||
};
|
||
|
||
export function VariantThumb({thumb, className}: {thumb: ThumbKey; className?: string}) {
|
||
return (
|
||
<svg
|
||
viewBox="0 0 40 28"
|
||
role="presentation"
|
||
className={className}
|
||
preserveAspectRatio="xMidYMid meet"
|
||
>
|
||
<rect x="0" y="0" width="40" height="28" className="fill-white" />
|
||
{SHAPES[thumb]}
|
||
</svg>
|
||
);
|
||
}
|