'use client'; import { memo, type ReactNode } from 'react'; import type { FdiToothId } from '@/types/treatment'; import type { ToothShapeKind } from '@/components/treatment/fdiToothMeta'; import type { FdiChartDesignId } from '@/components/ui/treatment/fdiChartDesigns'; import { getToothGlyphPaint } from '@/components/ui/treatment/toothGlyphPaint'; import type { ToothGlyphPaint } from '@/components/ui/treatment/toothGlyphPaint'; import { getToothPathModel, type ToothPathModel } from '@/components/ui/treatment/toothPathModel'; import { getTextbookToothPathModel } from '@/components/ui/treatment/toothPathModelTextbook'; import { wireframeInnerScale, wireframeOriginY } from '@/components/ui/treatment/toothGlyphStructural'; interface ToothGlyphProps { fdi: FdiToothId; kind: ToothShapeKind; gradientId: string; selected: boolean; upper?: boolean; mirrored?: boolean; upsideDown?: boolean; className?: string; variant?: FdiChartDesignId; } function filledSilhouette( model: ToothPathModel, crownFill: string, rootFill: string, stroke: string, strokeW: number, ): ReactNode { return ( <> {model.roots.map((d, i) => ( ))} ); } function detailOnly(model: ToothPathModel, stroke: string, strokeW: number): ReactNode { if (!model.detailStroke) return null; const { d, widthScale } = model.detailStroke; return ; } function renderClinicalFill(model: ToothPathModel, paint: ToothGlyphPaint): ReactNode { const { crownFill, rootFill, stroke, strokeW } = paint; return ( <> {filledSilhouette(model, crownFill, rootFill, stroke, strokeW)} {detailOnly(model, stroke, strokeW)} ); } function renderWireframe(model: ToothPathModel, paint: ToothGlyphPaint, kind: ToothShapeKind): ReactNode { const { stroke, strokeW } = paint; const outer = paint.wireOuter ?? '#f8fafc'; const innerCol = paint.wireInner ?? '#64748b'; const s = wireframeInnerScale(kind); const crownOy = wireframeOriginY('crown', kind); const rootOy = wireframeOriginY('root', kind); const rootScale = (i: number) => s - (model.roots.length > 1 ? i * 0.018 : 0); return ( <> {model.roots.map((d, i) => ( ))} {detailOnly(model, stroke, strokeW)} ); } /** Clinical uses FDI-specific paths; wireframe uses textbook silhouettes + line sculpture (original combo). */ export const ToothGlyph = memo(function ToothGlyph({ fdi, kind, gradientId, selected, upper, mirrored, upsideDown, className = 'w-8 h-[4.85rem]', variant = 'clinical', }: ToothGlyphProps) { const lastDigit = Number(fdi[1]); const model: ToothPathModel | null = variant === 'clinical' ? getToothPathModel(fdi, kind, upper) : getTextbookToothPathModel(kind, upper, lastDigit); const paint = getToothGlyphPaint(variant, gradientId, selected); const { showClinicalGradient, filter, structuralMode } = paint; if (!model) { return ( ? ); } const body = structuralMode === 'wireframe' ? renderWireframe(model, paint, kind) : renderClinicalFill(model, paint); return ( {showClinicalGradient && ( )} {body} ); });