2026-09-17 19:48:58 +07:00
|
|
|
import {
|
|
|
|
|
ArrowRight,
|
|
|
|
|
Circle,
|
|
|
|
|
EyeOff,
|
|
|
|
|
Highlighter,
|
|
|
|
|
MessageSquare,
|
|
|
|
|
Minus,
|
|
|
|
|
Pencil,
|
|
|
|
|
Square,
|
|
|
|
|
Stamp,
|
|
|
|
|
Strikethrough,
|
|
|
|
|
Type,
|
|
|
|
|
Underline,
|
|
|
|
|
} from "lucide-react";
|
|
|
|
|
|
|
|
|
|
import type {
|
|
|
|
|
AnnotationDTO,
|
|
|
|
|
DrawData,
|
|
|
|
|
HighlightData,
|
|
|
|
|
ShapeData,
|
|
|
|
|
} from "@/db/schema";
|
|
|
|
|
|
|
|
|
|
/** ไอคอนตามชนิด annotation — presentational ล้วน **ไม่มี "use client"** ให้หน้าสรุป
|
|
|
|
|
* (server component, F15) ใช้ร่วมกับ sidebar (client) ได้: lucide icon เป็น SVG
|
|
|
|
|
* component ล้วน render ฝั่ง server ได้ (ย้ายมาจาก AnnotationSidebar.tsx) */
|
|
|
|
|
export function AnnotationTypeIcon({
|
|
|
|
|
type,
|
|
|
|
|
data,
|
genesis+worker: design system Genesis ทั้งชุด + patch pdf.worker แก้ fake-space ไทย + ปิด review design/responsive/quality รอบ 2026-09-24 — (1) Genesis: ฟอนต์ General Sans self-host + DM Sans + Sarabun, AppNav 56px backdrop-blur แทน SessionBar, DotGrid หน้า login, palette/รัศมี/เงา/focus ตาม docs/DESIGN.md ครบทุกหน้า (2) postinstall scripts/patch-pdf-worker.mjs ถอด if (scaledDim) รอบ prevTransform ให้อัปเดตทุก glyph — กัน addFakeSpaces แทรก space กลางคำไทยใน PDF ที่ justify ด้วย letter-spacing + test กัน regression (tests/scripts/ + fixture thai_letterspacing.pdf, invariant #6) (3) ฟอร์มอัปโหลด + ช่องกลุ่ม typeId ทางเลือก — normDocumentGroup ที่ utils/external-file.ts เป็น single source ร่วมกับ N8 (4) token fixes: focus ring ปุ่ม pin + แถว bookmark ตามหน้า, ปุ่ม action ใน popup/composer/dialog เป็น rounded-md ทั้งคู่, selection preview เป็น tint ของ primary แทน blue-500 ดิบ, default สี shape/highlight รวมที่ utils/annotation-display, loading animate-pulse + จดข้อยกเว้น (เงา pin, font weights ของ viewer) ลง DESIGN.md (5) responsive: Export PDF max-lg:order-first ให้เห็นบน iPad, แถวบน header แถวเดียวเลื่อนได้บนจอแคบ, re-fit ความกว้างตอน toggle sidebar เฉพาะเมื่อยังไม่ซูมเอง, pin popover flip ขึ้นบนเมื่อใกล้ท้ายหน้า, toast hint ตอนสลับ tool กลางเอกสาร, ป้าย "ชนิด · ผู้ทำ" ของรายการผู้อื่นสำหรับจอสัมผัส (6) คุณภาพ: @layer ครอบ @media กันกฎ touch รั่ยไป desktop (Tailwind v3 ยก @layer ออกจาก media ทิ้ง wrapper — ยืนยันด้วย build จริง + วัดบนจอ), กฎ M5 ครอบ contenteditable กัน Safari zoom ตอนแก้ไข TEXTBOX บน iPad, COMMENT ใช้ box มาตราฐานเดียวตาม pin px จริง (render/scroll target/move-clamp/bookmark), ตัดหัวการ์ดซ้ำกับ h2 หน้ารายการ — พร้อมไฟล์ untracked ที่ postinstall/โค้ดอ้างถึงครบชุด (app/fonts/, AppNav, DotGrid, tests/) กัน fresh clone fail ที่ npm install (คำขอผู้ใช้ 2026-09-24)
Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-24 11:46:02 +07:00
|
|
|
className = "h-4 w-4 shrink-0 text-ink-soft",
|
2026-09-17 19:48:58 +07:00
|
|
|
}: {
|
|
|
|
|
type: AnnotationDTO["type"];
|
|
|
|
|
data: AnnotationDTO["data"];
|
|
|
|
|
className?: string;
|
|
|
|
|
}) {
|
|
|
|
|
if (type === "HIGHLIGHT") {
|
|
|
|
|
const style = (data as HighlightData).style ?? "highlight";
|
|
|
|
|
if (style === "underline") return <Underline className={className} />;
|
|
|
|
|
if (style === "strikethrough") return <Strikethrough className={className} />;
|
|
|
|
|
return <Highlighter className={className} />; // highlight / squiggle
|
|
|
|
|
}
|
|
|
|
|
if (type === "DRAW")
|
|
|
|
|
return (data as DrawData).pen === "highlighter" ? (
|
|
|
|
|
<Highlighter className={className} />
|
|
|
|
|
) : (
|
|
|
|
|
<Pencil className={className} />
|
|
|
|
|
);
|
|
|
|
|
if (type === "REDACTION") return <EyeOff className={className} />;
|
|
|
|
|
if (type === "TEXTBOX") return <Type className={className} />;
|
|
|
|
|
if (type === "STAMP") return <Stamp className={className} />;
|
|
|
|
|
if (type === "SHAPE") {
|
|
|
|
|
const shape = (data as ShapeData).shape;
|
|
|
|
|
if (shape === "rect") return <Square className={className} />;
|
|
|
|
|
if (shape === "ellipse") return <Circle className={className} />;
|
|
|
|
|
if (shape === "line") return <Minus className={className} />;
|
|
|
|
|
return <ArrowRight className={className} />;
|
|
|
|
|
}
|
|
|
|
|
return <MessageSquare className={className} />;
|
|
|
|
|
}
|