TEXTBOX กล่องกว้างคงที่สไตล์ Smallpdf: คลิกเดียวได้กล่อง 30% + ลากขอบซ้าย/ขวาปรับความกว้าง (ฟอนต์คงขนาด ข้อความ wrap ใหม่)
Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
parent
9e6158ed45
commit
ca74fb1843
10 changed files with 248 additions and 41 deletions
|
|
@ -4,7 +4,7 @@ import { useEffect, useMemo, useRef } from "react";
|
|||
|
||||
import type { StampData, TextboxData, TextboxSegment } from "@/db/schema";
|
||||
import { toPx, type Point, type Size } from "@/utils/coordinates";
|
||||
import { STAMP_HEIGHT_RATIO, TEXTBOX_MAX_WIDTH_PCT } from "@/utils/geometry";
|
||||
import { STAMP_HEIGHT_RATIO, textboxMaxWidthPct } from "@/utils/geometry";
|
||||
import { STAMP_COLOR, stampFitFontSize } from "@/utils/annotation-display";
|
||||
|
||||
// TEXTBOX + STAMP overlay (F17/B2, F18/B5) — HTML overlay (z-4 กลุ่มเดียวกับ comment pins)
|
||||
|
|
@ -83,6 +83,7 @@ function TextboxEditor({
|
|||
bold,
|
||||
opacity,
|
||||
align,
|
||||
widthPct,
|
||||
enabled,
|
||||
initialText,
|
||||
initialSegments,
|
||||
|
|
@ -97,6 +98,8 @@ function TextboxEditor({
|
|||
bold?: boolean;
|
||||
opacity?: number;
|
||||
align?: "left" | "center" | "right";
|
||||
/** ความกว้างกล่องคงที่ % (กล่องใหม่/กล่องที่มี width) — ไม่มี = shrink-to-fit (แถวเดิม) */
|
||||
widthPct?: number;
|
||||
/** container ของ layer เป็น pointer-events:none — editor ต้องเปิด auto เองเมื่อใช้งานได้ */
|
||||
enabled: boolean;
|
||||
initialText: string;
|
||||
|
|
@ -140,9 +143,11 @@ function TextboxEditor({
|
|||
style={{
|
||||
left: toPx(position.x, size.width),
|
||||
top: toPx(position.y, size.height),
|
||||
// กล่องพอดีข้อความ (shrink-to-fit ของ absolute) — เริ่มเล็กตอนกดคลิกครั้งแรก
|
||||
// แล้วขยายตามที่พิมพ์ ตัดบรรทัดเมื่อยาวเกิน 50% ของความกว้างหน้าเหมือนที่ render จริง
|
||||
maxWidth: `${TEXTBOX_MAX_WIDTH_PCT}%`,
|
||||
// มี widthPct = กล่องกว้างคงที่ (สไตล์ Smallpdf — ข้อความ wrap ในกล่อง)
|
||||
// ไม่มี = shrink-to-fit หุ้มข้อความขยายตามที่พิมพ์ (แถวเดิม)
|
||||
// maxWidth บีบตามพื้นที่จริงถึงขอบขวา (ไม่ล้นกระดาษ)
|
||||
...(widthPct !== undefined ? { width: `${widthPct}%` } : null),
|
||||
maxWidth: `${textboxMaxWidthPct(position.x)}%`,
|
||||
minWidth: "1em",
|
||||
opacity: opacity ?? 1,
|
||||
pointerEvents: enabled ? "auto" : "none",
|
||||
|
|
@ -230,6 +235,8 @@ export default function TextboxStampLayer({
|
|||
bold?: boolean;
|
||||
opacity?: number;
|
||||
align?: "left" | "center" | "right";
|
||||
/** ความกว้างกล่อง default % (กล่องใหม่เป็นกล่องกว้างคงที่เสมอ) */
|
||||
widthPct?: number;
|
||||
} | null;
|
||||
onCommitComposer: (text: string, segments?: TextboxSegment[]) => void;
|
||||
onCancelComposer: () => void;
|
||||
|
|
@ -249,6 +256,7 @@ export default function TextboxStampLayer({
|
|||
bold={t.data.bold}
|
||||
opacity={t.data.opacity}
|
||||
align={t.data.align}
|
||||
widthPct={t.data.width}
|
||||
enabled={enabled}
|
||||
initialText={t.data.text}
|
||||
initialSegments={t.data.segments}
|
||||
|
|
@ -263,7 +271,10 @@ export default function TextboxStampLayer({
|
|||
style={{
|
||||
left: toPx(t.data.position.x, size.width),
|
||||
top: toPx(t.data.position.y, size.height),
|
||||
maxWidth: `${TEXTBOX_MAX_WIDTH_PCT}%`,
|
||||
// กล่อง width คงที่ (ถ้ามี) กว้างตามที่กำหนด — align จัดข้อความ*ใน*กล่องอย่างเดียว
|
||||
// (แบบ Smallpdf กล่องไม่ขยับ) · maxWidth บีบตามพื้นที่ถึงขอบขวาเหมือนเดิม
|
||||
...(t.data.width !== undefined ? { width: `${t.data.width}%` } : null),
|
||||
maxWidth: `${textboxMaxWidthPct(t.data.position.x)}%`,
|
||||
fontSize: toPx(t.data.fontSize, size.width),
|
||||
lineHeight: 1.5,
|
||||
color: t.data.color,
|
||||
|
|
@ -302,6 +313,7 @@ export default function TextboxStampLayer({
|
|||
bold={composer.bold}
|
||||
opacity={composer.opacity}
|
||||
align={composer.align}
|
||||
widthPct={composer.widthPct}
|
||||
enabled={enabled}
|
||||
initialText=""
|
||||
onSave={onCommitComposer}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue