@xom11/whiteboard 0.10.1 → 0.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +67 -0
- package/dist/{ExcalidrawWithMenus-EAVPOPJZ.mjs → ExcalidrawWithMenus-KBLDWPM2.mjs} +2 -3
- package/dist/ExcalidrawWithMenus-KBLDWPM2.mjs.map +1 -0
- package/dist/catalog.json +57 -0
- package/dist/{chunk-PWIMZIB6.mjs → chunk-2SKXRBGS.mjs} +7 -8
- package/dist/chunk-2SKXRBGS.mjs.map +1 -0
- package/dist/chunk-33PEN2WC.mjs +57 -0
- package/dist/chunk-33PEN2WC.mjs.map +1 -0
- package/dist/chunk-3KBL77M6.mjs +127 -0
- package/dist/chunk-3KBL77M6.mjs.map +1 -0
- package/dist/chunk-5UTGXHLJ.mjs +57 -0
- package/dist/chunk-5UTGXHLJ.mjs.map +1 -0
- package/dist/chunk-6XUPIGVD.mjs +467 -0
- package/dist/chunk-6XUPIGVD.mjs.map +1 -0
- package/dist/chunk-7WG2KDRF.mjs +28 -0
- package/dist/chunk-7WG2KDRF.mjs.map +1 -0
- package/dist/chunk-FZY33J6Z.mjs +95 -0
- package/dist/chunk-FZY33J6Z.mjs.map +1 -0
- package/dist/chunk-HNQLZIEP.mjs +78 -0
- package/dist/chunk-HNQLZIEP.mjs.map +1 -0
- package/dist/chunk-NVJ7K3DK.mjs +29 -0
- package/dist/chunk-NVJ7K3DK.mjs.map +1 -0
- package/dist/chunk-O4WIZFRQ.mjs +11 -0
- package/dist/chunk-O4WIZFRQ.mjs.map +1 -0
- package/dist/{chunk-YVJP7NRG.mjs → chunk-O6QTYAKE.mjs} +7 -9
- package/dist/chunk-O6QTYAKE.mjs.map +1 -0
- package/dist/chunk-R5FL6S7L.mjs +22 -0
- package/dist/chunk-R5FL6S7L.mjs.map +1 -0
- package/dist/chunk-RBUILBX3.mjs +388 -0
- package/dist/chunk-RBUILBX3.mjs.map +1 -0
- package/dist/chunk-RD34F5PM.mjs +57 -0
- package/dist/chunk-RD34F5PM.mjs.map +1 -0
- package/dist/{chunk-7P7SQFOW.mjs → chunk-RXOFO64U.mjs} +3 -3
- package/dist/chunk-RXOFO64U.mjs.map +1 -0
- package/dist/chunk-TOOHCAWP.mjs +1167 -0
- package/dist/chunk-TOOHCAWP.mjs.map +1 -0
- package/dist/{chunk-C6SCVOMC.mjs → chunk-TQYQVXNW.mjs} +5 -41
- package/dist/chunk-TQYQVXNW.mjs.map +1 -0
- package/dist/chunk-VBJLUHCY.mjs +23 -0
- package/dist/chunk-VBJLUHCY.mjs.map +1 -0
- package/dist/chunk-VRWZILTG.mjs +205 -0
- package/dist/chunk-VRWZILTG.mjs.map +1 -0
- package/dist/chunk-XVSO7FBM.mjs +61 -0
- package/dist/chunk-XVSO7FBM.mjs.map +1 -0
- package/dist/geometry-2d.d.mts +3 -6
- package/dist/geometry-2d.d.ts +3 -6
- package/dist/geometry-2d.js +5069 -2651
- package/dist/geometry-2d.js.map +1 -1
- package/dist/geometry-2d.mjs +8 -4
- package/dist/geometry-3d.d.mts +4 -7
- package/dist/geometry-3d.d.ts +4 -7
- package/dist/geometry-3d.js +3053 -2150
- package/dist/geometry-3d.js.map +1 -1
- package/dist/geometry-3d.mjs +7 -4
- package/dist/graph-2d.d.mts +4 -7
- package/dist/graph-2d.d.ts +4 -7
- package/dist/graph-2d.js +3363 -1670
- package/dist/graph-2d.js.map +1 -1
- package/dist/graph-2d.mjs +10 -3
- package/dist/host-3N4E4KJH.mjs +1142 -0
- package/dist/host-3N4E4KJH.mjs.map +1 -0
- package/dist/{host-Z3TEJKZA.mjs → host-6SNSZ332.mjs} +4 -4
- package/dist/{host-Z3TEJKZA.mjs.map → host-6SNSZ332.mjs.map} +1 -1
- package/dist/host-EVJT3LIF.mjs +3198 -0
- package/dist/host-EVJT3LIF.mjs.map +1 -0
- package/dist/host-HN4X3TBC.mjs +2374 -0
- package/dist/host-HN4X3TBC.mjs.map +1 -0
- package/dist/index.css +4 -1
- package/dist/index.css.map +1 -1
- package/dist/index.d.mts +675 -19
- package/dist/index.d.ts +675 -19
- package/dist/index.js +11764 -9417
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1492 -335
- package/dist/index.mjs.map +1 -1
- package/dist/latex.d.mts +3 -4
- package/dist/latex.d.ts +3 -4
- package/dist/latex.js +33 -18
- package/dist/latex.js.map +1 -1
- package/dist/latex.mjs +2 -3
- package/dist/render-OCVGDKK6.mjs +8 -0
- package/dist/render-OCVGDKK6.mjs.map +1 -0
- package/dist/serialize-GKN6OVPM.mjs +6 -0
- package/dist/serialize-GKN6OVPM.mjs.map +1 -0
- package/dist/{types-CinstD7T.d.mts → types-rA4slL08.d.mts} +69 -4
- package/dist/{types-CinstD7T.d.ts → types-rA4slL08.d.ts} +69 -4
- package/package.json +24 -5
- package/dist/ExcalidrawWithMenus-EAVPOPJZ.mjs.map +0 -1
- package/dist/chunk-74VEEZBV.mjs +0 -619
- package/dist/chunk-74VEEZBV.mjs.map +0 -1
- package/dist/chunk-7P7SQFOW.mjs.map +0 -1
- package/dist/chunk-BJTO5JO5.mjs +0 -11
- package/dist/chunk-BJTO5JO5.mjs.map +0 -1
- package/dist/chunk-C6SCVOMC.mjs.map +0 -1
- package/dist/chunk-D257NCQW.mjs +0 -58
- package/dist/chunk-D257NCQW.mjs.map +0 -1
- package/dist/chunk-G7FR3AIV.mjs +0 -193
- package/dist/chunk-G7FR3AIV.mjs.map +0 -1
- package/dist/chunk-HTBLO5JO.mjs +0 -41
- package/dist/chunk-HTBLO5JO.mjs.map +0 -1
- package/dist/chunk-PWIMZIB6.mjs.map +0 -1
- package/dist/chunk-SBDMF4NQ.mjs +0 -212
- package/dist/chunk-SBDMF4NQ.mjs.map +0 -1
- package/dist/chunk-WQOABS6N.mjs +0 -197
- package/dist/chunk-WQOABS6N.mjs.map +0 -1
- package/dist/chunk-YVJP7NRG.mjs.map +0 -1
- package/dist/host-N6ACNJKI.mjs +0 -3226
- package/dist/host-N6ACNJKI.mjs.map +0 -1
- package/dist/host-NKGV6RF2.mjs +0 -1134
- package/dist/host-NKGV6RF2.mjs.map +0 -1
- package/dist/host-XVK7UCRE.mjs +0 -2908
- package/dist/host-XVK7UCRE.mjs.map +0 -1
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/serialize.ts","../src/stamps/shared/registry.ts","../src/stamps/shared/ToolbarInjector.tsx","../src/stamps/shared/useShortcuts.ts","../src/pdf/PdfImporterButton.tsx","../src/pdf/parseRange.ts","../src/pdf/rasterize.ts","../src/pdf/PageRangeDialog.tsx","../src/pdf/insertPdfPages.ts","../src/stamps/shared/useStampDoubleClick.ts","../src/stamps/shared/useStampShortcutBlocker.ts","../src/stamps/shared/useStampClickOutside.ts","../src/stamps/shared/restoreStampFiles.ts","../src/core/persistence/validation.ts","../src/core/persistence/sceneStore.ts","../src/core/persistence/fileStore.ts","../src/Whiteboard.tsx"],"names":["useEffect","POPOVER_SELECTOR","useState","useRef","jsx","jsxs","Fragment","createPortal","useMemo","useCallback"],"mappings":"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","file":"index.mjs","sourcesContent":["import type { AppState } from '@excalidraw/excalidraw/types';\nimport type { SyncableAppState } from './types';\n\nexport function pickSyncableAppState(s: AppState): SyncableAppState {\n return {\n viewBackgroundColor: s.viewBackgroundColor,\n zoom: s.zoom,\n scrollX: s.scrollX,\n scrollY: s.scrollY,\n gridSize: s.gridSize ?? null,\n theme: s.theme,\n };\n}\n","import { geometryStamp } from '../geometry-2d';\nimport { latexStamp } from '../latex';\nimport { geometry3dStamp } from '../geometry-3d';\nimport { graph2dStamp } from '../graph-2d';\nimport type { StampType } from './types';\n\nexport { geometryStamp, type GeometryCustomData, isGeometryCustomData } from '../geometry-2d';\nexport { latexStamp, type LatexCustomData, isLatexCustomData } from '../latex';\nexport {\n geometry3dStamp,\n type Geometry3DCustomData,\n isGeometry3DCustomData,\n} from '../geometry-3d';\nexport { graph2dStamp, type Graph2DCustomData, isGraph2DCustomData } from '../graph-2d';\nexport type { StampType, BaseStampCustomData } from './types';\n\n/** Stamp ổn định, sẵn sàng production. */\nexport const STABLE_STAMPS: ReadonlyArray<StampType> = Object.freeze([\n geometryStamp,\n latexStamp,\n]);\n\n/** Stamp experimental — chưa ổn định cho production. Consumer phải opt-in. */\nexport const EXPERIMENTAL_STAMPS: ReadonlyArray<StampType> = Object.freeze([\n geometry3dStamp,\n graph2dStamp,\n]);\n\n/** Tất cả stamp (stable + experimental). Dùng khi consumer muốn full feature. */\nexport const ALL_STAMPS: ReadonlyArray<StampType> = Object.freeze([\n ...STABLE_STAMPS,\n ...EXPERIMENTAL_STAMPS,\n]);\n\n/**\n * Set stamp mặc định cho Whiteboard = ALL_STAMPS (bật tất cả tool).\n * Consumer muốn ẩn experimental: `<Whiteboard stamps={STABLE_STAMPS} />`.\n *\n * Để thêm 1 stamp mới (vd chart):\n * 1. Tạo `src/stamps/chart/index.tsx` export `chartStamp: StampType`.\n * 2. Import + add vào STABLE_STAMPS (production-ready) hoặc\n * EXPERIMENTAL_STAMPS (chưa ổn định) ở file này.\n * 3. Re-export `chartStamp` từ `src/stamps/index.ts` + `src/index.ts`.\n */\nexport const DEFAULT_STAMPS: ReadonlyArray<StampType> = ALL_STAMPS;\n\n/** Tìm stamp tương ứng với customData của element. null nếu không match. */\nexport function findStampForCustomData(\n data: unknown,\n stamps: ReadonlyArray<StampType> = DEFAULT_STAMPS,\n): StampType | null {\n for (const s of stamps) {\n if (s.matchesCustomData(data)) return s;\n }\n return null;\n}\n\n/** isMathStamp version dựa trên registry. */\nexport function isStampElement<T extends { customData?: unknown }>(\n element: T,\n stamps: ReadonlyArray<StampType> = DEFAULT_STAMPS,\n): boolean {\n return findStampForCustomData(element.customData, stamps) !== null;\n}\n","'use client';\n\nimport { useEffect, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { DEFAULT_STAMPS } from './registry';\nimport type { StampType } from './types';\n\ninterface Props {\n /** Bật/tắt theo role. Khi disabled → không mount portal. */\n enabled: boolean;\n /** Kind stamp đang active, hoặc null nếu không có stamp nào mở. */\n activeStampKind: string | null;\n /** Toggle stamp theo kind. */\n onToggle: (kind: string) => void;\n /** Danh sách stamp đăng ký. Mặc định DEFAULT_STAMPS. */\n stamps?: ReadonlyArray<StampType>;\n}\n\nconst MENU_WRAPPER_ID = 'stamp-menu-portal-wrapper';\n/**\n * Excalidraw 0.18 áp dụng class `App-toolbar__extra-tools-dropdown` lên\n * popover wrapper của More tools cho cả desktop lẫn mobile. Mobile có\n * thêm modifier `dropdown-menu--mobile`. Selector này cover cả hai mode.\n */\nconst POPOVER_SELECTOR =\n '.App-toolbar__extra-tools-dropdown .dropdown-menu-container';\n\n/**\n * Inject stamp buttons vào popover \"More tools\" của Excalidraw.\n *\n * v0.7.0: thay vì inject inline vào main toolbar (desktop) hoặc dropdown\n * riêng cho mobile, ta chỉ inject vào dropdown-menu-container bên trong\n * popover của Excalidraw. Selector cover cả desktop lẫn mobile vì hai\n * mode dùng cùng cấu trúc DOM (DropdownMenu.Content).\n *\n * Popover mount/unmount theo trigger click → MutationObserver dò DOM,\n * mount lại wrapper khi cần.\n */\nexport function ToolbarInjector({\n enabled,\n activeStampKind,\n onToggle,\n stamps = DEFAULT_STAMPS,\n}: Props) {\n const [menuMount, setMenuMount] = useState<HTMLElement | null>(null);\n const menuMountRef = useRef<HTMLElement | null>(null);\n\n useEffect(() => {\n if (!enabled) {\n if (menuMountRef.current !== null) {\n menuMountRef.current = null;\n setMenuMount(null);\n }\n document.getElementById(MENU_WRAPPER_ID)?.remove();\n return;\n }\n\n let cancelled = false;\n let observer: MutationObserver | null = null;\n let rafId: number | null = null;\n let observedRoot: Element | null = null;\n\n const apply = (next: HTMLElement | null) => {\n if (cancelled || menuMountRef.current === next) return;\n menuMountRef.current = next;\n queueMicrotask(() => {\n if (!cancelled) setMenuMount(next);\n });\n };\n\n const findMenu = () => {\n if (cancelled) return;\n const container = document.querySelector<HTMLElement>(POPOVER_SELECTOR);\n if (!container) {\n apply(null);\n return;\n }\n let wrapper = container.querySelector<HTMLDivElement>('#' + MENU_WRAPPER_ID);\n if (!wrapper) {\n wrapper = document.createElement('div');\n wrapper.id = MENU_WRAPPER_ID;\n wrapper.setAttribute('data-stamp-menu', 'true');\n wrapper.setAttribute('data-stamp-area', 'true');\n wrapper.style.display = 'contents';\n container.insertBefore(wrapper, container.firstChild);\n }\n apply(wrapper);\n };\n\n /**\n * Scope observer xuống `.excalidraw` để giảm tần suất callback trigger\n * (mutation ở các node ngoài Excalidraw không liên quan tới popover).\n * Nếu `.excalidraw` chưa mount → tạm observe `document.body` để bắt\n * lúc nó xuất hiện, rồi switch sang root nhỏ hơn.\n */\n const attachObserver = () => {\n if (cancelled) return;\n const excalidraw = document.querySelector<HTMLElement>('.excalidraw');\n const nextRoot: Element = excalidraw ?? document.body;\n if (observedRoot === nextRoot) return;\n observer?.disconnect();\n observedRoot = nextRoot;\n observer = new MutationObserver(onMutation);\n observer.observe(nextRoot, { childList: true, subtree: true });\n };\n\n /**\n * rAF debounce: gộp nhiều mutation cùng tick thành 1 lần xử lý.\n * Excalidraw có thể trigger hàng chục mutation khi mở/đóng popover —\n * mỗi pass chỉ tốn 1 lần querySelector + DOM insert.\n */\n const onMutation = () => {\n if (rafId != null) return;\n rafId = requestAnimationFrame(() => {\n rafId = null;\n if (cancelled) return;\n // Nếu đang observe body mà giờ `.excalidraw` đã mount → switch sang nó.\n if (observedRoot !== document.querySelector('.excalidraw')) {\n attachObserver();\n }\n findMenu();\n });\n };\n\n findMenu();\n attachObserver();\n\n return () => {\n cancelled = true;\n if (rafId != null) {\n cancelAnimationFrame(rafId);\n rafId = null;\n }\n observer?.disconnect();\n observer = null;\n observedRoot = null;\n document.getElementById(MENU_WRAPPER_ID)?.remove();\n };\n }, [enabled]);\n\n if (!enabled || !menuMount) return null;\n\n const closePopover = () => {\n const trigger = document.querySelector<HTMLButtonElement>(\n '.App-toolbar__extra-tools-trigger',\n );\n trigger?.click();\n };\n\n return createPortal(\n <>\n {stamps.map((stamp) => {\n const { displayLabel, shortcut } = splitTitleAndShortcut(\n stamp.toolbarTitle,\n stamp.toolbarLabel,\n );\n return (\n <StampMenuItem\n key={stamp.kind}\n icon={stamp.toolbarIcon}\n label={displayLabel}\n ariaLabel={stamp.toolbarTitle}\n shortcut={shortcut}\n active={activeStampKind === stamp.kind}\n onClick={() => {\n onToggle(stamp.kind);\n closePopover();\n }}\n dataTestId={stamp.toolbarTestId}\n />\n );\n })}\n <div\n aria-hidden=\"true\"\n style={{\n height: 1,\n background: 'var(--default-border-color, rgba(0,0,0,0.08))',\n margin: '6px 4px',\n }}\n />\n </>,\n menuMount,\n );\n}\n\n/**\n * Tách \"(X)\" cuối toolbarTitle thành shortcut hiển thị riêng ở góc phải\n * (giống các tool gốc Excalidraw: Frame F, Laser K, ...). Nếu title không\n * có pattern \"(...)\", fallback dùng toolbarLabel.\n */\nfunction splitTitleAndShortcut(\n title: string,\n fallbackShortcut: string,\n): { displayLabel: string; shortcut: string } {\n const match = title.match(/^(.*?)\\s*\\(([^()]+)\\)\\s*$/);\n if (match) {\n return { displayLabel: match[1].trim(), shortcut: match[2].trim() };\n }\n return { displayLabel: title, shortcut: fallbackShortcut };\n}\n\ninterface StampMenuItemProps {\n icon: React.ReactNode;\n label: string;\n ariaLabel: string;\n shortcut: string;\n active: boolean;\n onClick: () => void;\n dataTestId?: string;\n}\n\nfunction StampMenuItem({\n icon,\n label,\n ariaLabel,\n shortcut,\n active,\n onClick,\n dataTestId,\n}: StampMenuItemProps) {\n const className = [\n 'dropdown-menu-item',\n 'dropdown-menu-item-base',\n active ? 'dropdown-menu-item--selected' : '',\n ]\n .filter(Boolean)\n .join(' ');\n return (\n <button\n type=\"button\"\n onClick={onClick}\n title={ariaLabel}\n aria-label={ariaLabel}\n aria-pressed={active}\n data-testid={dataTestId}\n className={className}\n >\n <div className=\"dropdown-menu-item__icon\" aria-hidden=\"true\">\n {icon}\n </div>\n <div className=\"dropdown-menu-item__text\">{label}</div>\n {shortcut ? (\n <div className=\"dropdown-menu-item__shortcut\">{shortcut}</div>\n ) : null}\n </button>\n );\n}\n","import { useEffect } from 'react';\nimport { DEFAULT_STAMPS } from './registry';\nimport type { StampType } from './types';\n\ninterface Options {\n enabled: boolean;\n /** Toggle stamp theo kind khi user bấm shortcut tương ứng. */\n onToggle: (kind: string) => void;\n /** Registry. Mặc định DEFAULT_STAMPS. */\n stamps?: ReadonlyArray<StampType>;\n}\n\nfunction isEditableTarget(t: EventTarget | null): boolean {\n if (!t || !(t instanceof HTMLElement)) return false;\n if (t.isContentEditable) return true;\n const tag = t.tagName;\n return tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT';\n}\n\n/**\n * Bind keyboard shortcut cho mỗi stamp trong registry. Capture phase +\n * stopPropagation để chặn trước Excalidraw's bubble-phase handlers (Excalidraw\n * dùng `L` cho Line tool, nếu không chặn → bấm L lại chuyển tool thay vì\n * toggle LaTeX panel).\n */\nexport function useShortcuts({\n enabled,\n onToggle,\n stamps = DEFAULT_STAMPS,\n}: Options): void {\n useEffect(() => {\n if (!enabled) return;\n const keyToKind = new Map<string, string>();\n for (const s of stamps) keyToKind.set(s.shortcutKey, s.kind);\n\n const handler = (e: KeyboardEvent) => {\n if (e.metaKey || e.ctrlKey || e.altKey) return;\n if (isEditableTarget(e.target)) return;\n const key = e.key.toLowerCase();\n const kind = keyToKind.get(key);\n if (!kind) return;\n e.preventDefault();\n e.stopPropagation();\n onToggle(kind);\n };\n window.addEventListener('keydown', handler, { capture: true });\n return () => window.removeEventListener('keydown', handler, { capture: true });\n }, [enabled, onToggle, stamps]);\n}\n","'use client';\n\nimport { useEffect, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\n\ninterface Props {\n enabled: boolean;\n onPick: (file: File) => void;\n}\n\nconst WRAPPER_ID = 'pdf-import-portal-wrapper';\nconst POPOVER_SELECTOR =\n '.App-toolbar__extra-tools-dropdown .dropdown-menu-container';\n\n/**\n * Button \"Chèn PDF\" portal vào More tools dropdown của Excalidraw, ngay\n * dưới các stamp buttons. Click → mở native file picker (hidden input).\n *\n * Tách riêng khỏi ToolbarInjector vì PDF không phải stamp (không có Host,\n * không re-edit). Cùng pattern observer như ToolbarInjector để bắt\n * popover mount/unmount.\n */\nexport function PdfImporterButton({ enabled, onPick }: Props) {\n const [mount, setMount] = useState<HTMLElement | null>(null);\n const mountRef = useRef<HTMLElement | null>(null);\n const inputRef = useRef<HTMLInputElement | null>(null);\n\n useEffect(() => {\n if (!enabled) {\n mountRef.current = null;\n setMount(null);\n document.getElementById(WRAPPER_ID)?.remove();\n return;\n }\n\n let cancelled = false;\n let observer: MutationObserver | null = null;\n let rafId: number | null = null;\n let observedRoot: Element | null = null;\n\n const apply = (next: HTMLElement | null) => {\n if (cancelled || mountRef.current === next) return;\n mountRef.current = next;\n queueMicrotask(() => {\n if (!cancelled) setMount(next);\n });\n };\n\n const findMenu = () => {\n if (cancelled) return;\n const container = document.querySelector<HTMLElement>(POPOVER_SELECTOR);\n if (!container) {\n apply(null);\n return;\n }\n let wrapper = container.querySelector<HTMLDivElement>('#' + WRAPPER_ID);\n if (!wrapper) {\n wrapper = document.createElement('div');\n wrapper.id = WRAPPER_ID;\n wrapper.setAttribute('data-pdf-import', 'true');\n wrapper.style.display = 'contents';\n // Append cuối để PDF button nằm sau stamps + divider.\n container.appendChild(wrapper);\n }\n apply(wrapper);\n };\n\n const attachObserver = () => {\n if (cancelled) return;\n const excalidraw = document.querySelector<HTMLElement>('.excalidraw');\n const nextRoot: Element = excalidraw ?? document.body;\n if (observedRoot === nextRoot) return;\n observer?.disconnect();\n observedRoot = nextRoot;\n observer = new MutationObserver(onMutation);\n observer.observe(nextRoot, { childList: true, subtree: true });\n };\n\n const onMutation = () => {\n if (rafId != null) return;\n rafId = requestAnimationFrame(() => {\n rafId = null;\n if (cancelled) return;\n if (observedRoot !== document.querySelector('.excalidraw')) {\n attachObserver();\n }\n findMenu();\n });\n };\n\n findMenu();\n attachObserver();\n\n return () => {\n cancelled = true;\n if (rafId != null) cancelAnimationFrame(rafId);\n observer?.disconnect();\n document.getElementById(WRAPPER_ID)?.remove();\n };\n }, [enabled]);\n\n const closePopover = () => {\n const trigger = document.querySelector<HTMLButtonElement>(\n '.App-toolbar__extra-tools-trigger',\n );\n trigger?.click();\n };\n\n const handleClick = () => {\n inputRef.current?.click();\n };\n\n const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (file) onPick(file);\n // Reset để chọn lại cùng file lần sau vẫn fire onChange.\n e.target.value = '';\n closePopover();\n };\n\n if (!enabled || !mount) {\n // Vẫn render hidden input để parent có thể gọi qua ref nếu muốn — nhưng\n // không cần. Giữ null khi chưa mount để tránh DOM thừa.\n return (\n <input\n ref={inputRef}\n type=\"file\"\n accept=\"application/pdf,.pdf\"\n style={{ display: 'none' }}\n onChange={handleFileChange}\n />\n );\n }\n\n return (\n <>\n <input\n ref={inputRef}\n type=\"file\"\n accept=\"application/pdf,.pdf\"\n style={{ display: 'none' }}\n onChange={handleFileChange}\n />\n {createPortal(\n <button\n type=\"button\"\n onClick={handleClick}\n title=\"Chèn PDF (P)\"\n aria-label=\"Chèn PDF\"\n data-testid=\"pdf-import-button\"\n className=\"dropdown-menu-item dropdown-menu-item-base\"\n >\n <div className=\"dropdown-menu-item__icon\" aria-hidden=\"true\">\n <PdfIcon />\n </div>\n <div className=\"dropdown-menu-item__text\">Chèn PDF</div>\n <div className=\"dropdown-menu-item__shortcut\">P</div>\n </button>,\n mount,\n )}\n </>\n );\n}\n\nfunction PdfIcon() {\n return (\n <svg\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.6\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M14 3H7a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8z\" />\n <path d=\"M14 3v5h5\" />\n <text x=\"7.5\" y=\"17\" fontSize=\"6\" fontFamily=\"sans-serif\" fontWeight=\"700\" stroke=\"none\" fill=\"currentColor\">\n PDF\n </text>\n </svg>\n );\n}\n","/**\n * Parse chuỗi range trang dạng \"1,3,5-10\" → array số 1-based đã sort + dedupe.\n *\n * - Tokens cách nhau bằng dấu phẩy hoặc khoảng trắng.\n * - Token có gạch \"-\" → range inclusive (5-10 = [5,6,7,8,9,10]).\n * - Khoảng trắng quanh số bị bỏ qua.\n * - Empty / chỉ space → [].\n *\n * Throws `Error` với message tiếng Việt khi:\n * - Token không phải số / không phải range hợp lệ.\n * - Số <= 0 hoặc > totalPages.\n * - Range đảo ngược (vd \"10-5\") — coi là lỗi user thay vì auto-reverse để\n * tránh nuốt typo.\n */\nexport function parsePageRange(input: string, totalPages: number): number[] {\n if (!Number.isInteger(totalPages) || totalPages <= 0) {\n throw new Error('Số trang phải là số nguyên dương.');\n }\n const trimmed = input.trim();\n if (trimmed === '') return [];\n\n const tokens = trimmed\n .split(/[,\\s]+/)\n .map((t) => t.trim())\n .filter((t) => t.length > 0);\n\n const set = new Set<number>();\n\n for (const token of tokens) {\n if (token.includes('-')) {\n const parts = token.split('-');\n if (parts.length !== 2) {\n throw new Error(`Khoảng trang không hợp lệ: \"${token}\".`);\n }\n const start = parseStrictInt(parts[0]);\n const end = parseStrictInt(parts[1]);\n if (start === null || end === null) {\n throw new Error(`Khoảng trang không hợp lệ: \"${token}\".`);\n }\n if (start > end) {\n throw new Error(`Khoảng trang ngược: \"${token}\" (đầu > cuối).`);\n }\n if (start < 1 || end > totalPages) {\n throw new Error(\n `Khoảng trang vượt giới hạn: \"${token}\". PDF có ${totalPages} trang.`,\n );\n }\n for (let i = start; i <= end; i++) set.add(i);\n } else {\n const n = parseStrictInt(token);\n if (n === null) {\n throw new Error(`Số trang không hợp lệ: \"${token}\".`);\n }\n if (n < 1 || n > totalPages) {\n throw new Error(\n `Số trang vượt giới hạn: ${n}. PDF có ${totalPages} trang.`,\n );\n }\n set.add(n);\n }\n }\n\n return Array.from(set).sort((a, b) => a - b);\n}\n\nfunction parseStrictInt(s: string): number | null {\n if (!/^-?\\d+$/.test(s)) return null;\n const n = Number(s);\n return Number.isInteger(n) ? n : null;\n}\n","/**\n * Rasterize PDF → PNG dataURLs cho từng trang.\n *\n * Worker config:\n * - pdfjs-dist 5.x cần `GlobalWorkerOptions.workerSrc` (URL tới worker .mjs).\n * - Mặc định trỏ CDN (jsdelivr). Consumer có thể override qua\n * `configurePdfWorker(src)` trước khi gọi rasterize lần đầu.\n * - Lý do CDN thay vì bundled worker: tsup không có cách clean để emit\n * worker chunk ra cùng dist/ với URL ổn định, và consumer (Next.js)\n * có thể self-host nếu cần offline.\n *\n * Lazy import pdfjs-dist để không phình bundle khi user không dùng PDF.\n */\nimport type { PDFDocumentProxy, PDFPageProxy } from 'pdfjs-dist';\n\nlet workerSrcOverride: string | null = null;\nlet pdfjsCache: typeof import('pdfjs-dist') | null = null;\n\n/**\n * Override workerSrc trước khi rasterize. Gọi từ consumer khi cần self-host\n * worker file (vd offline mode, CSP cấm CDN).\n *\n * Mặc định nếu không gọi: dùng CDN jsdelivr theo version pdfjs-dist đã cài.\n */\nexport function configurePdfWorker(workerSrc: string): void {\n workerSrcOverride = workerSrc;\n if (pdfjsCache) {\n pdfjsCache.GlobalWorkerOptions.workerSrc = workerSrc;\n }\n}\n\nasync function loadPdfjs(): Promise<typeof import('pdfjs-dist')> {\n if (pdfjsCache) return pdfjsCache;\n const mod = await import('pdfjs-dist');\n const workerSrc =\n workerSrcOverride ??\n `https://cdn.jsdelivr.net/npm/pdfjs-dist@${mod.version}/build/pdf.worker.min.mjs`;\n mod.GlobalWorkerOptions.workerSrc = workerSrc;\n pdfjsCache = mod;\n return mod;\n}\n\nexport interface RasterizedPage {\n pageNumber: number;\n dataURL: string;\n width: number;\n height: number;\n mimeType: 'image/png';\n}\n\nexport interface RasterizeOptions {\n /** Scale render. Mặc định 2 (HiDPI sharp). */\n scale?: number;\n /** Danh sách trang 1-based. Mặc định: tất cả. */\n pages?: number[];\n /** Callback progress sau mỗi page. */\n onProgress?: (done: number, total: number) => void;\n /** AbortSignal để cancel giữa chừng. */\n signal?: AbortSignal;\n}\n\n/**\n * Load PDF chỉ để lấy `numPages` (vd hiển thị tổng số trang trên dialog).\n * Caller phải tự đóng document bằng `closePdfDocument(doc)` khi xong.\n */\nexport async function loadPdfDocument(source: File | Blob | ArrayBuffer): Promise<PDFDocumentProxy> {\n const pdfjs = await loadPdfjs();\n const data = source instanceof ArrayBuffer ? source : await source.arrayBuffer();\n const task = pdfjs.getDocument({ data: new Uint8Array(data) });\n return task.promise;\n}\n\nexport async function closePdfDocument(doc: PDFDocumentProxy): Promise<void> {\n try {\n await doc.cleanup();\n await doc.destroy();\n } catch {\n /* ignore — best-effort cleanup */\n }\n}\n\n/**\n * Render danh sách trang ra PNG dataURL.\n *\n * Lưu ý:\n * - Sử dụng `OffscreenCanvas` nếu có (browser hiện đại) để không touch DOM,\n * fallback `<canvas>` document.createElement.\n * - Mỗi page render xong sẽ release canvas (cho GC sớm với PDF nhiều trang).\n */\nexport async function rasterizePdf(\n doc: PDFDocumentProxy,\n options: RasterizeOptions = {},\n): Promise<RasterizedPage[]> {\n const scale = options.scale ?? 2;\n const total = doc.numPages;\n const pages = options.pages ?? Array.from({ length: total }, (_, i) => i + 1);\n const signal = options.signal;\n\n const result: RasterizedPage[] = [];\n for (let i = 0; i < pages.length; i++) {\n if (signal?.aborted) {\n throw new DOMException('Rasterize PDF bị huỷ.', 'AbortError');\n }\n const pageNum = pages[i];\n const page = await doc.getPage(pageNum);\n try {\n const rendered = await renderPageToPng(page, scale);\n result.push({ pageNumber: pageNum, mimeType: 'image/png', ...rendered });\n } finally {\n page.cleanup();\n }\n options.onProgress?.(i + 1, pages.length);\n }\n return result;\n}\n\nasync function renderPageToPng(\n page: PDFPageProxy,\n scale: number,\n): Promise<{ dataURL: string; width: number; height: number }> {\n const viewport = page.getViewport({ scale });\n const width = Math.ceil(viewport.width);\n const height = Math.ceil(viewport.height);\n\n const canvas = document.createElement('canvas');\n canvas.width = width;\n canvas.height = height;\n const ctx = canvas.getContext('2d');\n if (!ctx) throw new Error('Không lấy được 2D context của canvas.');\n await page.render({ canvasContext: ctx, viewport, canvas }).promise;\n const dataURL = canvas.toDataURL('image/png');\n return { dataURL, width, height };\n}\n\n/**\n * Render thumbnail nhẹ cho 1 trang — JPEG 0.7 quality + scale nhỏ (mặc định\n * 0.3). Tối ưu cho preview grid: ~10KB/thumb thay vì ~500KB PNG full scale.\n */\nexport async function renderPageThumbnail(\n page: PDFPageProxy,\n scale = 0.3,\n quality = 0.7,\n): Promise<{ dataURL: string; width: number; height: number }> {\n const viewport = page.getViewport({ scale });\n const width = Math.ceil(viewport.width);\n const height = Math.ceil(viewport.height);\n\n const canvas = document.createElement('canvas');\n canvas.width = width;\n canvas.height = height;\n const ctx = canvas.getContext('2d');\n if (!ctx) throw new Error('Không lấy được 2D context của canvas.');\n // Nền trắng vì JPEG không support alpha.\n ctx.fillStyle = '#ffffff';\n ctx.fillRect(0, 0, width, height);\n await page.render({ canvasContext: ctx, viewport, canvas }).promise;\n const dataURL = canvas.toDataURL('image/jpeg', quality);\n return { dataURL, width, height };\n}\n\n/**\n * Render thumbnails cho tất cả trang với concurrency. Callback `onEach` được\n * gọi sau mỗi trang xong (theo thứ tự completion, không phải pageNumber) để\n * UI có thể progressive update. Tôn trọng `signal` để cancel sớm.\n */\nexport async function renderAllThumbnails(\n doc: PDFDocumentProxy,\n onEach: (pageNumber: number, dataURL: string, width: number, height: number) => void,\n options: { scale?: number; quality?: number; concurrency?: number; signal?: AbortSignal } = {},\n): Promise<void> {\n const total = doc.numPages;\n const scale = options.scale ?? 0.3;\n const quality = options.quality ?? 0.7;\n const concurrency = Math.max(1, options.concurrency ?? 3);\n const signal = options.signal;\n let next = 1;\n\n async function worker() {\n while (true) {\n if (signal?.aborted) return;\n const pageNum = next++;\n if (pageNum > total) return;\n const page = await doc.getPage(pageNum);\n try {\n if (signal?.aborted) return;\n const { dataURL, width, height } = await renderPageThumbnail(page, scale, quality);\n if (signal?.aborted) return;\n onEach(pageNum, dataURL, width, height);\n } finally {\n page.cleanup();\n }\n }\n }\n\n await Promise.all(\n Array.from({ length: Math.min(concurrency, total) }, () => worker()),\n );\n}\n","'use client';\n\nimport { useEffect, useMemo, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport type { PDFDocumentProxy } from 'pdfjs-dist';\nimport { parsePageRange } from './parseRange';\nimport { renderAllThumbnails } from './rasterize';\n\ninterface Props {\n doc: PDFDocumentProxy;\n fileName: string;\n onConfirm: (pages: number[]) => void;\n onCancel: () => void;\n}\n\ninterface ThumbInfo {\n dataURL: string;\n width: number;\n height: number;\n}\n\n/**\n * Set<number> → chuỗi range compact dạng \"1-3,5,7-9\".\n * Dùng cho hiển thị + sync ngược về text input khi user click thumbnails.\n */\nfunction serializeSelection(pages: number[]): string {\n if (pages.length === 0) return '';\n const sorted = [...pages].sort((a, b) => a - b);\n const groups: string[] = [];\n let start = sorted[0];\n let prev = start;\n for (let i = 1; i < sorted.length; i++) {\n const n = sorted[i];\n if (n === prev + 1) {\n prev = n;\n } else {\n groups.push(start === prev ? `${start}` : `${start}-${prev}`);\n start = n;\n prev = n;\n }\n }\n groups.push(start === prev ? `${start}` : `${start}-${prev}`);\n return groups.join(',');\n}\n\n/**\n * Modal chọn trang PDF với thumbnail grid.\n *\n * Hai chiều sync:\n * - Gõ text input → parse → update selectedSet → highlight thumbnails.\n * - Click thumbnail → toggle pageNum trong selectedSet → re-serialize text.\n *\n * Source of truth: `selectedSet`. Text input là derived view (user-editable).\n * Khi user đang gõ (focus) → giữ raw `inputValue`, không overwrite. Chỉ\n * re-derive text khi click thumbnail HOẶC input mất focus với value valid.\n */\nexport function PageRangeDialog({ doc, fileName, onConfirm, onCancel }: Props) {\n const totalPages = doc.numPages;\n const defaultPages = useMemo(\n () => Array.from({ length: totalPages }, (_, i) => i + 1),\n [totalPages],\n );\n\n const [selectedSet, setSelectedSet] = useState<Set<number>>(\n () => new Set(defaultPages),\n );\n const [inputValue, setInputValue] = useState(serializeSelection(defaultPages));\n const [inputError, setInputError] = useState<string | null>(null);\n const [thumbs, setThumbs] = useState<Record<number, ThumbInfo>>({});\n const [thumbProgress, setThumbProgress] = useState(0);\n const inputRef = useRef<HTMLInputElement | null>(null);\n\n // ---- Render thumbnails khi mount ----\n useEffect(() => {\n const ctrl = new AbortController();\n void renderAllThumbnails(\n doc,\n (pageNum, dataURL, width, height) => {\n setThumbs((prev) => ({ ...prev, [pageNum]: { dataURL, width, height } }));\n setThumbProgress((prev) => prev + 1);\n },\n { scale: 0.3, quality: 0.7, concurrency: 3, signal: ctrl.signal },\n ).catch((err) => {\n if (ctrl.signal.aborted) return;\n console.warn('[PageRangeDialog] render thumbnails lỗi:', err);\n });\n return () => ctrl.abort();\n }, [doc]);\n\n // ---- Esc đóng dialog ----\n useEffect(() => {\n const onKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n e.preventDefault();\n e.stopPropagation();\n onCancel();\n }\n };\n window.addEventListener('keydown', onKey, { capture: true });\n return () => window.removeEventListener('keydown', onKey, { capture: true });\n }, [onCancel]);\n\n // ---- Text input handlers ----\n const handleInputChange = (next: string) => {\n setInputValue(next);\n try {\n const pages = parsePageRange(next, totalPages);\n setInputError(null);\n setSelectedSet(new Set(pages));\n } catch (e) {\n setInputError((e as Error).message);\n }\n };\n\n // ---- Thumbnail click handler ----\n const toggleThumb = (pageNum: number) => {\n setSelectedSet((prev) => {\n const next = new Set(prev);\n if (next.has(pageNum)) next.delete(pageNum);\n else next.add(pageNum);\n const serialized = serializeSelection([...next]);\n setInputValue(serialized);\n setInputError(null);\n return next;\n });\n };\n\n // ---- Quick select helpers ----\n const selectAll = () => {\n setSelectedSet(new Set(defaultPages));\n setInputValue(serializeSelection(defaultPages));\n setInputError(null);\n };\n\n const clearAll = () => {\n setSelectedSet(new Set());\n setInputValue('');\n setInputError(null);\n };\n\n const canSubmit = inputError === null && selectedSet.size > 0;\n const sortedSelected = useMemo(\n () => [...selectedSet].sort((a, b) => a - b),\n [selectedSet],\n );\n\n const handleSubmit = () => {\n if (!canSubmit) return;\n onConfirm(sortedSelected);\n };\n\n return createPortal(\n <div\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"pdf-range-title\"\n style={{\n position: 'fixed',\n inset: 0,\n background: 'rgba(0,0,0,0.55)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n zIndex: 10000,\n }}\n onClick={(e) => {\n if (e.target === e.currentTarget) onCancel();\n }}\n >\n <div\n style={{\n background: 'var(--popup-bg-color, #fff)',\n color: 'var(--text-primary-color, #1b1b1f)',\n borderRadius: 12,\n padding: '20px 22px',\n width: 'min(880px, 92vw)',\n maxHeight: '88vh',\n boxShadow: '0 12px 40px rgba(0,0,0,0.3)',\n fontFamily: 'inherit',\n display: 'flex',\n flexDirection: 'column',\n gap: 12,\n }}\n onClick={(e) => e.stopPropagation()}\n >\n <div>\n <h2\n id=\"pdf-range-title\"\n style={{ margin: 0, fontSize: 16, fontWeight: 600, lineHeight: 1.3 }}\n >\n Chèn PDF\n </h2>\n <p style={{ margin: '4px 0 0', fontSize: 12, opacity: 0.7 }}>\n {fileName} — {totalPages} trang\n {thumbProgress < totalPages && (\n <> · đang tải preview {thumbProgress}/{totalPages}…</>\n )}\n </p>\n </div>\n\n <div style={{ display: 'flex', alignItems: 'flex-start', gap: 10 }}>\n <div style={{ flex: 1 }}>\n <label\n style={{ display: 'block', fontSize: 12, marginBottom: 4, opacity: 0.75 }}\n >\n Trang cần chèn (vd: 1,3,5-10) — hoặc click thumbnail bên dưới\n </label>\n <input\n ref={inputRef}\n type=\"text\"\n value={inputValue}\n onChange={(e) => handleInputChange(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n handleSubmit();\n }\n }}\n style={{\n width: '100%',\n boxSizing: 'border-box',\n padding: '8px 10px',\n fontSize: 14,\n borderRadius: 6,\n border: `1px solid ${inputError ? '#dc2626' : 'rgba(0,0,0,0.2)'}`,\n outline: 'none',\n background: 'var(--input-bg-color, #fff)',\n color: 'inherit',\n fontFamily: 'ui-monospace, SFMono-Regular, Menlo, monospace',\n }}\n />\n </div>\n <div style={{ display: 'flex', gap: 6, paddingTop: 18 }}>\n <button\n type=\"button\"\n onClick={selectAll}\n style={quickBtnStyle}\n title=\"Chọn tất cả trang\"\n >\n Tất cả\n </button>\n <button\n type=\"button\"\n onClick={clearAll}\n style={quickBtnStyle}\n title=\"Bỏ chọn tất cả\"\n >\n Bỏ hết\n </button>\n </div>\n </div>\n\n <div style={{ minHeight: 18, fontSize: 12 }} data-testid=\"pdf-range-status\">\n {inputError ? (\n <span style={{ color: '#dc2626' }}>{inputError}</span>\n ) : (\n <span style={{ opacity: 0.75 }}>\n Đã chọn <strong>{selectedSet.size}</strong> / {totalPages} trang\n </span>\n )}\n </div>\n\n <div\n style={{\n flex: 1,\n minHeight: 240,\n maxHeight: '60vh',\n overflow: 'auto',\n padding: 8,\n background: 'rgba(0,0,0,0.04)',\n borderRadius: 8,\n display: 'grid',\n gridTemplateColumns: 'repeat(auto-fill, minmax(120px, 1fr))',\n gap: 10,\n alignContent: 'start',\n }}\n >\n {Array.from({ length: totalPages }, (_, i) => i + 1).map((pageNum) => {\n const thumb = thumbs[pageNum];\n const selected = selectedSet.has(pageNum);\n return (\n <ThumbnailItem\n key={pageNum}\n pageNum={pageNum}\n thumb={thumb}\n selected={selected}\n onToggle={() => toggleThumb(pageNum)}\n />\n );\n })}\n </div>\n\n <div\n style={{\n display: 'flex',\n justifyContent: 'flex-end',\n gap: 8,\n paddingTop: 4,\n }}\n >\n <button\n type=\"button\"\n onClick={onCancel}\n style={{\n padding: '8px 14px',\n fontSize: 13,\n borderRadius: 6,\n border: '1px solid rgba(0,0,0,0.15)',\n background: 'transparent',\n color: 'inherit',\n cursor: 'pointer',\n }}\n >\n Huỷ\n </button>\n <button\n type=\"button\"\n onClick={handleSubmit}\n disabled={!canSubmit}\n style={{\n padding: '8px 16px',\n fontSize: 13,\n borderRadius: 6,\n border: 'none',\n background: canSubmit ? '#4f46e5' : 'rgba(0,0,0,0.15)',\n color: '#fff',\n cursor: canSubmit ? 'pointer' : 'not-allowed',\n fontWeight: 500,\n }}\n >\n Chèn {selectedSet.size > 0 ? `${selectedSet.size} trang` : ''}\n </button>\n </div>\n </div>\n </div>,\n document.body,\n );\n}\n\nconst quickBtnStyle: React.CSSProperties = {\n padding: '7px 10px',\n fontSize: 12,\n borderRadius: 6,\n border: '1px solid rgba(0,0,0,0.15)',\n background: 'transparent',\n color: 'inherit',\n cursor: 'pointer',\n whiteSpace: 'nowrap',\n};\n\ninterface ThumbProps {\n pageNum: number;\n thumb: ThumbInfo | undefined;\n selected: boolean;\n onToggle: () => void;\n}\n\nfunction ThumbnailItem({ pageNum, thumb, selected, onToggle }: ThumbProps) {\n const aspect = thumb ? thumb.width / thumb.height : 0.77; // A4 portrait default\n return (\n <button\n type=\"button\"\n onClick={onToggle}\n aria-pressed={selected}\n aria-label={`Trang ${pageNum}${selected ? ' (đã chọn)' : ''}`}\n title={`Trang ${pageNum}`}\n style={{\n position: 'relative',\n padding: 0,\n background: '#fff',\n border: `2px solid ${selected ? '#4f46e5' : 'rgba(0,0,0,0.12)'}`,\n borderRadius: 6,\n overflow: 'hidden',\n cursor: 'pointer',\n boxShadow: selected ? '0 0 0 3px rgba(79,70,229,0.18)' : 'none',\n transition: 'border-color 80ms ease, box-shadow 80ms ease',\n }}\n >\n <div\n style={{\n width: '100%',\n aspectRatio: aspect.toString(),\n background: '#f5f5f5',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n {thumb ? (\n // eslint-disable-next-line @next/next/no-img-element\n <img\n src={thumb.dataURL}\n alt=\"\"\n style={{ width: '100%', height: '100%', display: 'block', objectFit: 'contain' }}\n draggable={false}\n />\n ) : (\n <div style={{ fontSize: 11, opacity: 0.5 }}>…</div>\n )}\n </div>\n <div\n style={{\n position: 'absolute',\n bottom: 4,\n left: 4,\n fontSize: 10,\n fontWeight: 600,\n padding: '2px 6px',\n borderRadius: 4,\n background: selected ? '#4f46e5' : 'rgba(0,0,0,0.6)',\n color: '#fff',\n }}\n >\n {pageNum}\n </div>\n {selected && (\n <div\n aria-hidden=\"true\"\n style={{\n position: 'absolute',\n top: 4,\n right: 4,\n width: 18,\n height: 18,\n borderRadius: '50%',\n background: '#4f46e5',\n color: '#fff',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: 11,\n fontWeight: 700,\n boxShadow: '0 1px 3px rgba(0,0,0,0.3)',\n }}\n >\n ✓\n </div>\n )}\n </button>\n );\n}\n","import type { ExcalidrawElement } from '../types';\nimport { closePdfDocument, loadPdfDocument, rasterizePdf, type RasterizedPage } from './rasterize';\n\n// Excalidraw imperative API — không có public type chính xác.\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype ExApi = any;\n\n/** Khoảng cách dọc giữa các trang PDF khi xếp dọc, ở scene units. */\nconst PAGE_GAP = 24;\n\n/** Scale render mặc định (HiDPI sharp). */\nconst DEFAULT_SCALE = 2;\n\nexport interface InsertRasterizedPagesOptions {\n /** Scale dùng khi rasterize (để chia pixel → scene units). */\n scale: number;\n /** Toạ độ scene gốc cho page đầu tiên. Bỏ qua → giữa viewport. */\n origin?: { x: number; y: number };\n}\n\nexport interface InsertRasterizedPagesResult {\n insertedElementIds: string[];\n fileIds: string[];\n}\n\n/**\n * Chèn array `RasterizedPage` đã có sẵn vào scene. Tách ra để Whiteboard\n * có thể: load doc → hỏi user range → rasterize → insert mà không phải gọi\n * insertPdfPages (load lại từ ArrayBuffer 2 lần).\n */\nexport function insertRasterizedPagesIntoScene(\n api: ExApi,\n rendered: RasterizedPage[],\n options: InsertRasterizedPagesOptions,\n): InsertRasterizedPagesResult {\n if (!api) throw new Error('Excalidraw API chưa sẵn sàng.');\n if (rendered.length === 0) return { insertedElementIds: [], fileIds: [] };\n\n const { scale } = options;\n const filesPayload = rendered.map((p) => ({\n id: generateFileId(),\n dataURL: p.dataURL,\n mimeType: p.mimeType,\n created: Date.now(),\n }));\n api.addFiles(filesPayload);\n\n const origin = options.origin ?? getViewportCenter(api);\n const sceneSizes = rendered.map((p) => pixelsToSceneSize(p.width, p.height, scale));\n const maxSceneWidth = Math.max(...sceneSizes.map((s) => s.width));\n const baseX = origin.x - maxSceneWidth / 2;\n let cursorY = origin.y - sceneSizes[0].height / 2;\n\n const newElements = rendered.map((_, i) => {\n const { width, height } = sceneSizes[i];\n const x = baseX + (maxSceneWidth - width) / 2;\n const y = cursorY;\n cursorY = y + height + PAGE_GAP;\n return buildPdfImageElement(filesPayload[i].id, x, y, width, height);\n });\n\n const existing = api.getSceneElements() as readonly ExcalidrawElement[];\n api.updateScene({\n elements: [...existing, ...newElements],\n appState: { selectedElementIds: {}, croppingElementId: null },\n });\n\n return {\n insertedElementIds: newElements.map((e) => e.id),\n fileIds: filesPayload.map((f) => f.id),\n };\n}\n\n/**\n * Excalidraw lưu width/height theo \"scene units\". File PDF rasterize ở scale 2\n * → pixel = 2 × scene unit. Chia lại để stamp hiển thị đúng kích thước\n * gốc của trang PDF (giấy A4 ≈ 595×842 scene units ở 72 DPI).\n */\nfunction pixelsToSceneSize(pxWidth: number, pxHeight: number, scale: number) {\n return { width: pxWidth / scale, height: pxHeight / scale };\n}\n\nexport interface InsertPdfPagesOptions {\n /** Trang cần chèn (1-based). Bỏ qua → chèn tất cả. */\n pages?: number[];\n /** Scale rasterize. Mặc định 2. */\n scale?: number;\n /** Toạ độ scene gốc cho page đầu tiên. Bỏ qua → giữa viewport. */\n origin?: { x: number; y: number };\n /** Progress callback. */\n onProgress?: (done: number, total: number) => void;\n /** AbortSignal. */\n signal?: AbortSignal;\n}\n\nexport interface InsertPdfPagesResult {\n insertedElementIds: string[];\n pages: RasterizedPage[];\n}\n\n/**\n * Tạo image element cho 1 trang đã rasterize. Trả về object đủ field cho\n * Excalidraw `updateScene`. Lấy `fileId` từ caller để có thể batch addFiles\n * trước khi update elements.\n */\nfunction buildPdfImageElement(\n fileId: string,\n x: number,\n y: number,\n width: number,\n height: number,\n) {\n return {\n type: 'image' as const,\n id: 'pdf_' + Date.now() + '_' + Math.random().toString(36).slice(2, 8),\n x,\n y,\n width,\n height,\n fileId,\n angle: 0,\n strokeColor: 'transparent',\n backgroundColor: 'transparent',\n fillStyle: 'solid',\n strokeWidth: 1,\n strokeStyle: 'solid',\n roughness: 0,\n opacity: 100,\n groupIds: [],\n roundness: null,\n seed: Math.floor(Math.random() * 1e9),\n versionNonce: 0,\n version: 1,\n isDeleted: false,\n boundElements: null,\n updated: Date.now(),\n link: null,\n locked: false,\n status: 'saved',\n scale: [1, 1],\n };\n}\n\nfunction generateFileId(): string {\n return 'pdf_' + Date.now() + '_' + Math.random().toString(36).slice(2, 10);\n}\n\nfunction getViewportCenter(api: ExApi): { x: number; y: number } {\n const appState = api?.getAppState?.() ?? {\n scrollX: 0,\n scrollY: 0,\n width: 800,\n height: 600,\n zoom: { value: 1 },\n };\n const zoom = appState.zoom?.value ?? 1;\n return {\n x: appState.scrollX + (appState.width ?? 800) / 2 / zoom,\n y: appState.scrollY + (appState.height ?? 600) / 2 / zoom,\n };\n}\n\n/**\n * High-level: rasterize PDF + insert thành nhiều image element xếp dọc.\n *\n * Flow:\n * 1. loadPdfDocument(source) → PDFDocumentProxy\n * 2. rasterizePdf(doc, {pages, scale}) → RasterizedPage[]\n * 3. Tạo fileId cho từng page, gọi api.addFiles batch.\n * 4. Tính position: page 1 trung tâm viewport (hoặc origin), các page sau\n * xếp dưới, cách PAGE_GAP.\n * 5. api.updateScene({ elements: [...cũ, ...mới] })\n *\n * Không serialize PDF bytes — sau insert, các page là image element thuần,\n * không thể re-edit qua double-click (theo design quyết định).\n */\nexport async function insertPdfPages(\n api: ExApi,\n source: File | Blob | ArrayBuffer,\n options: InsertPdfPagesOptions = {},\n): Promise<InsertPdfPagesResult> {\n if (!api) throw new Error('Excalidraw API chưa sẵn sàng.');\n\n const scale = options.scale ?? DEFAULT_SCALE;\n const doc = await loadPdfDocument(source);\n let rendered: RasterizedPage[];\n try {\n rendered = await rasterizePdf(doc, {\n pages: options.pages,\n scale,\n onProgress: options.onProgress,\n signal: options.signal,\n });\n } finally {\n void closePdfDocument(doc);\n }\n\n const { insertedElementIds } = insertRasterizedPagesIntoScene(api, rendered, {\n scale,\n origin: options.origin,\n });\n return { insertedElementIds, pages: rendered };\n}\n","import { useCallback, useRef } from 'react';\nimport { findStampForCustomData } from './registry';\nimport type { StampType } from './types';\n\nconst DOUBLE_CLICK_MS = 400;\n\ninterface Opts {\n enabled: boolean;\n stamps: ReadonlyArray<StampType>;\n onOpen: (\n kind: string,\n editingElement: { id: string; customData: unknown },\n ) => void;\n}\n\n/**\n * Trả về handler cho Excalidraw `onPointerDown`. Phát hiện double-click vào\n * image element thuộc một stamp đã đăng ký → gọi `onOpen(kind, element)`.\n */\nexport function useStampDoubleClick({ enabled, stamps, onOpen }: Opts) {\n const lastClickRef = useRef<{ time: number; elementId: string | null }>({\n time: 0,\n elementId: null,\n });\n\n return useCallback(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (_activeTool: any, pointerDownState: any) => {\n if (!enabled) return;\n const hitElement = pointerDownState?.hit?.element;\n if (!hitElement || hitElement.type !== 'image') return;\n const stamp = findStampForCustomData(hitElement.customData, stamps);\n if (!stamp) return;\n const now = Date.now();\n const isDouble =\n lastClickRef.current.elementId === hitElement.id &&\n now - lastClickRef.current.time < DOUBLE_CLICK_MS;\n lastClickRef.current = { time: now, elementId: hitElement.id };\n if (!isDouble) return;\n onOpen(stamp.kind, {\n id: hitElement.id,\n customData: hitElement.customData,\n });\n },\n [enabled, stamps, onOpen],\n );\n}\n","import { useEffect, useMemo } from 'react';\nimport type { StampType } from './types';\n\nconst ALLOWED_KEYS = new Set([\n 'Tab', 'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight',\n 'Shift', 'Control', 'Alt', 'Meta', 'CapsLock',\n 'Home', 'End', 'PageUp', 'PageDown',\n]);\n\nfunction isEditable(el: EventTarget | null): boolean {\n if (!(el instanceof HTMLElement)) return false;\n if (el.isContentEditable) return true;\n const tag = el.tagName;\n return tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT';\n}\n\ninterface Opts {\n /** Active stamp kind. Null = no blocker. */\n activeStamp: string | null;\n /** Stamps đăng ký để allow shortcut keys của chúng đi qua. */\n stamps: ReadonlyArray<StampType>;\n}\n\n/**\n * Khi 1 stamp panel đang mở, block hoàn toàn các phím tắt Excalidraw\n * (1-9, V, R, D...) bằng cách prevent + stop tại capture phase. Cho phép qua:\n * Tab/Arrow/Modifier, Escape, và phím tắt đã đăng ký bởi stamps (V/G/L/D...).\n */\nexport function useStampShortcutBlocker({ activeStamp, stamps }: Opts) {\n const shortcutKeys = useMemo(\n () => new Set(stamps.map((s) => s.shortcutKey.toLowerCase())),\n [stamps],\n );\n\n useEffect(() => {\n if (!activeStamp) return;\n\n const blocker = (e: KeyboardEvent) => {\n if (isEditable(e.target)) return;\n if (e.ctrlKey || e.metaKey) return;\n if (ALLOWED_KEYS.has(e.key)) return;\n if (e.key === 'Escape') return;\n if (shortcutKeys.has(e.key.toLowerCase())) return;\n e.preventDefault();\n e.stopPropagation();\n };\n window.addEventListener('keydown', blocker, { capture: true });\n return () => window.removeEventListener('keydown', blocker, { capture: true });\n }, [activeStamp, shortcutKeys]);\n}\n","import { useEffect, type RefObject } from 'react';\nimport type { StampHostHandle } from './types';\n\ninterface Opts {\n /** Active stamp. Null = no listener. */\n activeStamp: string | null;\n /** Ref tới Host imperative API (tryInsert / hasContent). */\n hostRef: RefObject<StampHostHandle | null>;\n /** Callback đóng panel. */\n onClose: () => void;\n}\n\n/**\n * Khi 1 stamp panel mở, lắng nghe pointer/mouse-down toàn document. Nếu\n * điểm click không nằm trong vùng `[data-stamp-area=\"true\"]`, gọi\n * `hostRef.tryInsert()` để auto-commit (nếu có nội dung) rồi `onClose()`.\n */\nexport function useStampClickOutside({ activeStamp, hostRef, onClose }: Opts) {\n useEffect(() => {\n if (!activeStamp) return;\n let lastFire = 0;\n const handler = (e: MouseEvent) => {\n const target = e.target as HTMLElement | null;\n if (!target) return;\n if (target.closest('[data-stamp-area=\"true\"]')) return;\n const now = Date.now();\n if (now - lastFire < 50) return;\n lastFire = now;\n hostRef.current?.tryInsert();\n onClose();\n };\n window.addEventListener('pointerdown', handler, { capture: true });\n window.addEventListener('mousedown', handler, { capture: true });\n return () => {\n window.removeEventListener('pointerdown', handler, { capture: true });\n window.removeEventListener('mousedown', handler, { capture: true });\n };\n }, [activeStamp, hostRef, onClose]);\n}\n","// Regenerate Excalidraw BinaryFiles for stamp elements after page reload.\n//\n// Why this exists: VideoRoom only persists the Excalidraw scene (elements +\n// appState) to sessionStorage; binary files (the SVG dataURLs for stamp\n// images) are NOT persisted. After reload, elements still reference a fileId\n// via customData, but the file payload is missing — Excalidraw renders the\n// image area as an empty placeholder.\n//\n// Strategy: tra registry để tìm StampType khớp customData.kind. Nếu stamp có\n// `restoreFileFromCustomData`, gọi trực tiếp với full element (stamp tự lấy\n// fileId + render). Ngược lại, fallback sang `renderSvgFromCustomData` (path\n// cũ: filter type=image + fileId + kiểm tra existing files).\n//\n// Excalidraw key trên fileId chứ không phải hash dataURL nên nếu kết quả\n// render có sai khác nhỏ (vd thứ tự element) cũng không ảnh hưởng.\n//\n// Theme: stamps được render với LIGHT palette (nét đậm). Excalidraw áp dụng\n// `filter: invert(...)` lên canvas trong dark mode → nét tự đảo sáng. KHÔNG\n// cần force regenerate khi user toggle theme.\n\nimport { DEFAULT_STAMPS, findStampForCustomData } from './registry';\nimport type { StampType } from './types';\n\ninterface ElementLike {\n id: string;\n type?: string;\n fileId?: string | null;\n customData?: unknown;\n}\n\ninterface AddFileRecord {\n id: string;\n dataURL: string;\n mimeType: string;\n created: number;\n}\n\nfunction svgToDataURL(svg: string): string {\n const utf8 = unescape(encodeURIComponent(svg));\n return 'data:image/svg+xml;base64,' + btoa(utf8);\n}\n\nasync function buildFileForStamp(\n fileId: string,\n customData: unknown,\n stamp: StampType,\n): Promise<AddFileRecord | null> {\n try {\n const svg = await stamp.renderSvgFromCustomData(customData);\n return { id: fileId, dataURL: svgToDataURL(svg), mimeType: 'image/svg+xml', created: Date.now() };\n } catch (err) {\n console.warn('Stamp restore failed for', fileId, '(' + stamp.kind + ')', err);\n return null;\n }\n}\n\n/**\n * Find stamp elements whose binary file is missing from Excalidraw, then\n * regenerate via registry dispatch. Idempotent: safe to call on every scene\n * update.\n *\n * Stamps that implement `restoreFileFromCustomData` are handled via the new\n * registry-driven path (stamp receives the full element and returns the file\n * record). Stamps that only implement `renderSvgFromCustomData` use the legacy\n * path (filter type=image + fileId, skip already-present files).\n *\n * @param api Excalidraw imperative API.\n * @param elements Tất cả elements trong scene.\n * @param stamps Registry. Default = DEFAULT_STAMPS.\n */\nexport async function restoreMissingStampFiles(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n api: any,\n elements: readonly ElementLike[],\n stamps: ReadonlyArray<StampType> = DEFAULT_STAMPS,\n): Promise<void> {\n if (!api) return;\n\n const filesToAdd: AddFileRecord[] = [];\n\n // --- New registry-driven path: stamp.restoreFileFromCustomData ---\n const newPathHandled = new Set<string>();\n for (const el of elements) {\n const stamp = findStampForCustomData(el.customData, stamps);\n if (!stamp?.restoreFileFromCustomData) continue;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const restored = await stamp.restoreFileFromCustomData(el as any);\n if (!restored) continue;\n newPathHandled.add(el.id);\n filesToAdd.push({\n id: restored.fileId,\n dataURL: restored.dataURL,\n mimeType: restored.mimeType,\n created: Date.now(),\n });\n }\n\n // --- Legacy path: stamp.renderSvgFromCustomData (type=image + fileId filter) ---\n const existing = (typeof api.getFiles === 'function') ? api.getFiles() : {};\n const seen = new Set<string>();\n for (const el of elements) {\n if (newPathHandled.has(el.id)) continue;\n if (el.type !== 'image') continue;\n if (!el.fileId) continue;\n if (existing && existing[el.fileId]) continue;\n if (seen.has(el.fileId)) continue;\n const stamp = findStampForCustomData(el.customData, stamps);\n if (!stamp) continue;\n seen.add(el.fileId);\n const built = await buildFileForStamp(el.fileId, el.customData, stamp);\n if (built) filesToAdd.push(built);\n }\n\n if (filesToAdd.length > 0) {\n try { api.addFiles(filesToAdd); } catch (err) { console.warn('addFiles failed:', err); }\n }\n}\n","/**\n * Hardening helpers cho persistence layer:\n *\n * - validateStorageKey: chặn ký tự lạ trong storageKey (consumer-supplied) trước khi\n * ghép vào key prefix (`whiteboard:scene:<key>`) hoặc dùng làm index trong IndexedDB.\n * - safeParseScene: parse JSON với reviver loại bỏ `__proto__/constructor/prototype`\n * để chặn prototype pollution, check max nesting depth, whitelist top-level keys.\n *\n * Các helper này không phụ thuộc DOM nên test được trong jsdom hoặc node thuần.\n */\n\nconst STORAGE_KEY_RE = /^[a-zA-Z0-9_-]{1,128}$/;\n\n/**\n * Validate storageKey từ consumer.\n *\n * Format cho phép: chữ + số + underscore + dash, 1..128 ký tự.\n * Throw nếu không hợp lệ — caller bị buộc handle hoặc crash sớm.\n */\nexport function validateStorageKey(key: unknown): string {\n if (typeof key !== 'string' || !STORAGE_KEY_RE.test(key)) {\n const sample = key === undefined ? 'undefined' : String(key).slice(0, 32);\n throw new Error(\n `[whiteboard] Invalid storageKey: must match ${STORAGE_KEY_RE} (got: ${sample})`,\n );\n }\n return key;\n}\n\nconst DANGEROUS_KEYS = new Set(['__proto__', 'constructor', 'prototype']);\n\n/**\n * Reviver dùng cho `JSON.parse`: drop bất kỳ key nào trong DANGEROUS_KEYS,\n * tránh prototype pollution khi parse dữ liệu không tin cậy từ localStorage.\n */\nfunction sanitizingReviver(_key: string, value: unknown): unknown {\n if (DANGEROUS_KEYS.has(_key)) return undefined;\n return value;\n}\n\n/** Max nesting depth cho scene tree (object/array). */\nexport const MAX_NESTED_DEPTH = 64;\n\nfunction depthExceeds(v: unknown, max: number, depth = 0): boolean {\n if (depth > max) return true;\n if (v === null || typeof v !== 'object') return false;\n const children = Array.isArray(v)\n ? v\n : Object.values(v as Record<string, unknown>);\n for (const child of children) {\n if (depthExceeds(child, max, depth + 1)) return true;\n }\n return false;\n}\n\nconst ALLOWED_TOP_LEVEL_KEYS = new Set(['version', 'elements', 'appState', 'savedAt']);\n\n/** Shape của scene đã được validate (chưa check version + element shape — caller lo). */\nexport interface ParsedScene {\n version?: unknown;\n elements: unknown[];\n appState: Record<string, unknown>;\n savedAt?: unknown;\n}\n\nfunction isPlainObject(v: unknown): v is Record<string, unknown> {\n return typeof v === 'object' && v !== null && !Array.isArray(v);\n}\n\n/**\n * Parse + sanitize raw JSON string từ localStorage.\n *\n * 1. JSON.parse với reviver strip dangerous keys.\n * 2. Reject nếu nested depth vượt MAX_NESTED_DEPTH.\n * 3. Whitelist top-level keys (drop extras).\n * 4. `elements` phải là array, mỗi item là object có `id: string` + `type: string`.\n *\n * Trả về `null` nếu bất kỳ check nào fail (caller handle như \"no data\").\n */\nexport function safeParseScene(raw: string): ParsedScene | null {\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw, sanitizingReviver);\n } catch {\n return null;\n }\n if (!isPlainObject(parsed)) return null;\n if (depthExceeds(parsed, MAX_NESTED_DEPTH)) return null;\n\n // Whitelist top-level keys.\n const safe: Record<string, unknown> = {};\n for (const k of Object.keys(parsed)) {\n if (ALLOWED_TOP_LEVEL_KEYS.has(k)) safe[k] = parsed[k];\n }\n\n if (!Array.isArray(safe.elements)) return null;\n for (const el of safe.elements as unknown[]) {\n if (!isPlainObject(el)) return null;\n if (typeof el.id !== 'string' || typeof el.type !== 'string') return null;\n }\n\n const appState = isPlainObject(safe.appState) ? safe.appState : {};\n\n return {\n version: safe.version,\n elements: safe.elements as unknown[],\n appState,\n savedAt: safe.savedAt,\n };\n}\n","import type { ExcalidrawElement, SyncableAppState } from '../../types';\nimport { safeParseScene, validateStorageKey } from './validation';\n\nconst PREFIX = 'whiteboard:scene:';\nconst SCHEMA_VERSION = 1 as const;\n\nexport interface StoredScene {\n version: typeof SCHEMA_VERSION;\n elements: readonly ExcalidrawElement[];\n appState: Partial<SyncableAppState>;\n savedAt: number;\n}\n\nfunction fullKey(key: string): string {\n return PREFIX + key;\n}\n\nexport function readScene(key: string): StoredScene | null {\n const validKey = validateStorageKey(key);\n if (typeof window === 'undefined') return null;\n const raw = window.localStorage.getItem(fullKey(validKey));\n if (!raw) return null;\n const parsed = safeParseScene(raw);\n if (!parsed) {\n console.warn('[whiteboard] scene parse/validation failed, clear:', validKey);\n try {\n window.localStorage.removeItem(fullKey(validKey));\n } catch { /* ignore */ }\n return null;\n }\n if (parsed.version !== SCHEMA_VERSION) {\n // Cố ý KHÔNG xoá entry — version mismatch có thể là dữ liệu của client\n // mới hơn (user vừa downgrade). Giữ lại để client tương ứng đọc được sau.\n console.warn(\n `[whiteboard] scene version ${parsed.version} không khớp ${SCHEMA_VERSION}, bỏ qua.`,\n );\n return null;\n }\n return {\n version: SCHEMA_VERSION,\n elements: parsed.elements as readonly ExcalidrawElement[],\n appState: parsed.appState as Partial<SyncableAppState>,\n savedAt: typeof parsed.savedAt === 'number' ? parsed.savedAt : Date.now(),\n };\n}\n\nexport function writeScene(\n key: string,\n payload: { elements: readonly ExcalidrawElement[]; appState: Partial<SyncableAppState> },\n): void {\n const validKey = validateStorageKey(key);\n if (typeof window === 'undefined') return;\n const record: StoredScene = {\n version: SCHEMA_VERSION,\n elements: payload.elements,\n appState: payload.appState,\n savedAt: Date.now(),\n };\n try {\n window.localStorage.setItem(fullKey(validKey), JSON.stringify(record));\n } catch (err) {\n console.warn('[whiteboard] scene write failed:', err);\n }\n}\n\nexport function clearScene(key: string): void {\n const validKey = validateStorageKey(key);\n if (typeof window === 'undefined') return;\n try {\n window.localStorage.removeItem(fullKey(validKey));\n } catch { /* ignore */ }\n}\n","import type { BinaryFiles } from '../../types';\nimport { validateStorageKey } from './validation';\n\nconst DB_NAME = 'whiteboard-files';\nconst DB_VERSION = 1;\nconst STORE = 'files';\n\ninterface FileRecord {\n id: string;\n storageKey: string;\n dataURL: string;\n mimeType: string;\n created: number;\n savedAt: number;\n}\n\nlet dbPromise: Promise<IDBDatabase> | null = null;\nlet idbDisabled = false;\n\nfunction openDb(): Promise<IDBDatabase> {\n if (idbDisabled) return Promise.reject(new Error('IndexedDB disabled'));\n if (dbPromise) return dbPromise;\n dbPromise = new Promise((resolve, reject) => {\n if (typeof indexedDB === 'undefined') {\n idbDisabled = true;\n reject(new Error('indexedDB undefined'));\n return;\n }\n const req = indexedDB.open(DB_NAME, DB_VERSION);\n req.onupgradeneeded = () => {\n const db = req.result;\n if (!db.objectStoreNames.contains(STORE)) {\n const store = db.createObjectStore(STORE, { keyPath: 'id' });\n store.createIndex('storageKey', 'storageKey', { unique: false });\n }\n };\n req.onsuccess = () => resolve(req.result);\n req.onerror = () => {\n idbDisabled = true;\n reject(req.error ?? new Error('IDB open failed'));\n };\n });\n return dbPromise;\n}\n\nasync function withStore<T>(\n mode: IDBTransactionMode,\n fn: (\n store: IDBObjectStore,\n setResult: (value: T) => void,\n fail: (error: unknown) => void,\n ) => void,\n fallback: T,\n): Promise<T> {\n let db: IDBDatabase;\n try {\n db = await openDb();\n } catch {\n return fallback;\n }\n return new Promise<T>((resolve, reject) => {\n const tx = db.transaction(STORE, mode);\n const store = tx.objectStore(STORE);\n let result = fallback;\n try {\n fn(\n store,\n (value) => {\n result = value;\n },\n reject,\n );\n } catch (err) {\n reject(err);\n return;\n }\n tx.oncomplete = () => resolve(result);\n tx.onerror = () => {\n console.warn('[whiteboard] IDB tx error:', tx.error);\n reject(tx.error ?? new Error('IDB tx error'));\n };\n tx.onabort = () => reject(tx.error ?? new Error('IDB tx aborted'));\n });\n}\n\nexport async function readFiles(storageKey: string): Promise<BinaryFiles> {\n const validKey = validateStorageKey(storageKey);\n try {\n return await withStore(\n 'readonly',\n (store, setResult, fail) => {\n const out: BinaryFiles = {};\n const req = store.index('storageKey').openCursor(IDBKeyRange.only(validKey));\n req.onsuccess = () => {\n const cursor = req.result;\n if (!cursor) {\n setResult(out);\n return;\n }\n const record = cursor.value as FileRecord;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (out as any)[record.id] = {\n dataURL: record.dataURL,\n mimeType: record.mimeType,\n created: record.created,\n };\n cursor.continue();\n };\n req.onerror = () => fail(req.error);\n },\n {},\n );\n } catch (err) {\n console.warn('[whiteboard] readFiles failed:', err);\n return {};\n }\n}\n\nexport async function writeFiles(storageKey: string, files: BinaryFiles): Promise<void> {\n const validKey = validateStorageKey(storageKey);\n const entries = Object.entries(files);\n if (entries.length === 0) return;\n try {\n await withStore<void>(\n 'readwrite',\n (store, setResult, fail) => {\n let pending = entries.length;\n const finishOne = () => {\n pending -= 1;\n if (pending === 0) setResult(undefined);\n };\n\n const now = Date.now();\n for (const [id, f] of entries) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const ff = f as any;\n const getReq = store.get(id);\n getReq.onsuccess = () => {\n if (getReq.result) {\n finishOne();\n return;\n }\n const rec: FileRecord = {\n id,\n storageKey: validKey,\n dataURL: ff.dataURL,\n mimeType: ff.mimeType,\n created: ff.created ?? now,\n savedAt: now,\n };\n const putReq = store.put(rec);\n putReq.onsuccess = finishOne;\n putReq.onerror = () => fail(putReq.error);\n };\n getReq.onerror = () => fail(getReq.error);\n };\n },\n undefined,\n );\n } catch (err) {\n console.warn('[whiteboard] writeFiles failed:', err);\n }\n}\n\nexport async function pruneFiles(\n storageKey: string,\n keepIds: ReadonlySet<string>,\n): Promise<void> {\n const validKey = validateStorageKey(storageKey);\n try {\n await withStore<void>(\n 'readwrite',\n (store, setResult, fail) => {\n const req = store.index('storageKey').openCursor(IDBKeyRange.only(validKey));\n req.onsuccess = () => {\n const cursor = req.result;\n if (!cursor) {\n setResult(undefined);\n return;\n }\n const record = cursor.value as FileRecord;\n if (keepIds.has(record.id)) {\n cursor.continue();\n return;\n }\n const deleteReq = cursor.delete();\n deleteReq.onsuccess = () => cursor.continue();\n deleteReq.onerror = () => fail(deleteReq.error);\n };\n req.onerror = () => fail(req.error);\n },\n undefined,\n );\n } catch (err) {\n console.warn('[whiteboard] pruneFiles failed:', err);\n }\n}\n\nexport async function clearAll(storageKey: string): Promise<void> {\n const validKey = validateStorageKey(storageKey);\n try {\n await withStore<void>(\n 'readwrite',\n (store, setResult, fail) => {\n const req = store.index('storageKey').openCursor(IDBKeyRange.only(validKey));\n req.onsuccess = () => {\n const cursor = req.result;\n if (!cursor) {\n setResult(undefined);\n return;\n }\n const deleteReq = cursor.delete();\n deleteReq.onsuccess = () => cursor.continue();\n deleteReq.onerror = () => fail(deleteReq.error);\n };\n req.onerror = () => fail(req.error);\n },\n undefined,\n );\n } catch (err) {\n console.warn('[whiteboard] clearAll failed:', err);\n }\n}\n","'use client';\n\nimport { lazy, Suspense, useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport type {\n ExcalidrawElement,\n BinaryFiles,\n ExcalidrawSceneSnapshot,\n SyncableAppState,\n} from './types';\nimport { pickSyncableAppState } from './serialize';\nimport {\n isStampElement,\n DEFAULT_STAMPS,\n findStampForCustomData,\n type StampType,\n} from './stamps/shared/registry';\nimport { ToolbarInjector } from './stamps/shared/ToolbarInjector';\nimport { useShortcuts } from './stamps/shared/useShortcuts';\nimport { PdfImporterButton } from './pdf/PdfImporterButton';\nimport { PageRangeDialog } from './pdf/PageRangeDialog';\nimport {\n loadPdfDocument,\n closePdfDocument,\n rasterizePdf,\n} from './pdf/rasterize';\nimport { insertRasterizedPagesIntoScene } from './pdf/insertPdfPages';\nimport type { PDFDocumentProxy } from 'pdfjs-dist';\nimport { useStampDoubleClick } from './stamps/shared/useStampDoubleClick';\nimport { useStampShortcutBlocker } from './stamps/shared/useStampShortcutBlocker';\nimport { useStampClickOutside } from './stamps/shared/useStampClickOutside';\nimport { restoreMissingStampFiles } from './stamps/shared/restoreStampFiles';\nimport type { StampHostHandle } from './stamps/shared/types';\nimport { readScene, writeScene } from './core/persistence/sceneStore';\nimport { readFiles, writeFiles, pruneFiles } from './core/persistence/fileStore';\nimport '@excalidraw/excalidraw/index.css';\nimport './stamps/shared/stamp.css';\n\nconst Excalidraw = lazy(() =>\n import('./ExcalidrawWithMenus').then((m) => ({ default: m.ExcalidrawWithMenus })),\n);\n\nconst ExcalidrawLoadingFallback = () => (\n <div className=\"flex h-full items-center justify-center text-sm text-gray-500\">\n Đang tải bảng…\n </div>\n);\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype ExApi = any;\n\nconst SYNC_THROTTLE_MS = 200;\n\n/** Element đang re-edit (double-click) — đủ tối thiểu để Host parse customData. */\ninterface EditingElement {\n id: string;\n customData: unknown;\n}\n\nexport interface WhiteboardProps {\n /**\n * Storage key cho persist client-side.\n * - Scene -> localStorage['whiteboard:scene:'+storageKey]\n * - Files raster -> IndexedDB 'whiteboard-files' index theo storageKey\n * - Default: 'default'\n * - Truyen `null` de tat persist (consumer drive state qua onApi).\n */\n storageKey?: string | null;\n\n /** View-only (Excalidraw viewModeEnabled). Default false. */\n readOnly?: boolean;\n\n /** Local edits -> consumer broadcast. Optional. */\n onSceneChange?: (snapshot: ExcalidrawSceneSnapshot) => void;\n onFilesChange?: (files: BinaryFiles, newFileIds: string[]) => void;\n\n /** Excalidraw imperative API. Consumer dung inject remote scene khi can. */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n onApi?: (api: any) => void;\n\n /** Excalidraw UI language. Defaults to 'vi-VN'. See @excalidraw/excalidraw locales. */\n langCode?: string;\n\n /**\n * Danh sách stamp đăng ký. Mỗi stamp khai báo phím tắt + toolbar button +\n * Host component (UI editing). Mặc định DEFAULT_STAMPS (= ALL_STAMPS,\n * gồm geometry + latex + geometry3d + graph2d).\n * Truyền `[...DEFAULT_STAMPS, customStamp]` để thêm stamp mới hoặc\n * `STABLE_STAMPS` để chỉ bật stamp ổn định.\n */\n stamps?: ReadonlyArray<StampType>;\n}\n\nexport function Whiteboard({\n storageKey = 'default',\n readOnly = false,\n onSceneChange,\n onFilesChange,\n onApi,\n langCode = 'vi-VN',\n stamps = DEFAULT_STAMPS,\n}: WhiteboardProps) {\n const [api, setApi] = useState<ExApi | null>(null);\n const apiRef = useRef<ExApi | null>(null);\n const [isDarkTheme, setIsDarkTheme] = useState(false);\n const isDarkThemeRef = useRef(false);\n const knownFileIdsRef = useRef<Set<string>>(new Set());\n const lastSceneHashRef = useRef<string>('');\n const sceneThrottleRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const fileThrottleRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const pruneThrottleRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const latestSceneRef = useRef<{\n elements: readonly ExcalidrawElement[];\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n appState: any;\n } | null>(null);\n const pendingFilesRef = useRef<BinaryFiles>({});\n // Cached hashElementsVersion để flushScene chạy sync trong unmount cleanup\n // (cleanup không thể await dynamic import).\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const hashElementsVersionRef = useRef<((elements: readonly ExcalidrawElement[]) => any) | null>(null);\n // Stamps prop có thể thay đổi — capture vào ref để callback trong setTimeout\n // không bị stale closure.\n const stampsRef = useRef(stamps);\n stampsRef.current = stamps;\n const persistEnabled = typeof storageKey === 'string' && storageKey.length > 0;\n const persistKeyRef = useRef(storageKey);\n persistKeyRef.current = storageKey;\n // Lưu callback refs để cleanup unmount truy cập được mà không bị stale closure\n // (props onSceneChange/onFilesChange có thể thay đổi).\n const onSceneChangeRef = useRef(onSceneChange);\n onSceneChangeRef.current = onSceneChange;\n const onFilesChangeRef = useRef(onFilesChange);\n onFilesChangeRef.current = onFilesChange;\n const persistEnabledRef = useRef(persistEnabled);\n persistEnabledRef.current = persistEnabled;\n\n const persistedInitial = useMemo(\n () => (persistEnabled ? readScene(storageKey as string) : null),\n [persistEnabled, storageKey],\n );\n const effectiveInitialScene: ExcalidrawSceneSnapshot | null = persistedInitial\n ? {\n elements: persistedInitial.elements,\n appState: persistedInitial.appState as SyncableAppState,\n }\n : null;\n\n // ---- Stamp state (registry-driven) ----\n const [activeStamp, setActiveStamp] = useState<string | null>(null);\n const activeStampRef = useRef(activeStamp);\n activeStampRef.current = activeStamp;\n const [editingElement, setEditingElement] = useState<EditingElement | null>(null);\n const hostRef = useRef<StampHostHandle | null>(null);\n\n // ---- PDF import state ----\n // Sau khi user pick file, load doc lấy numPages → mở dialog hỏi range.\n // Giữ doc instance để rasterize ngay (tránh load lại từ ArrayBuffer).\n const [pdfPending, setPdfPending] = useState<{\n doc: PDFDocumentProxy;\n fileName: string;\n totalPages: number;\n } | null>(null);\n const [pdfBusy, setPdfBusy] = useState(false);\n\n const handledCropIdRef = useRef<string | null>(null);\n const prevExcalidrawToolRef = useRef<string>('selection');\n\n const stampByKind = useMemo(() => {\n const m = new Map<string, StampType>();\n for (const s of stamps) m.set(s.kind, s);\n return m;\n }, [stamps]);\n\n const activeStampDef = activeStamp ? stampByKind.get(activeStamp) ?? null : null;\n const HostComponent = activeStampDef?.Host ?? null;\n\n // ---- Open / close helpers ----\n const openStamp = useCallback(\n (kind: string, element: EditingElement | null = null) => {\n if (readOnly) return;\n if (!stampByKind.has(kind)) return;\n setEditingElement(element);\n setActiveStamp(kind);\n },\n [readOnly, stampByKind],\n );\n\n const closeStamp = useCallback(() => {\n setActiveStamp(null);\n setEditingElement(null);\n }, []);\n\n const toggleStampByKind = useCallback(\n (kind: string) => {\n if (activeStamp === kind) closeStamp();\n else openStamp(kind);\n },\n [activeStamp, openStamp, closeStamp],\n );\n\n // ---- Capture local changes ----\n const handleChange = useCallback(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (elements: readonly ExcalidrawElement[], appState: any, files: BinaryFiles) => {\n // Sync theme từ Excalidraw appState -> React state.\n // Excalidraw 0.18 gọi onChange đồng bộ trong state-updater của họ\n // (React 19 / Next.js 16 sẽ warn: \"scheduled from inside an update\n // function\"). Bail-out qua ref + defer setState bằng queueMicrotask để\n // setState chạy SAU commit của Excalidraw, không nằm trong updater.\n const nextDark = appState?.theme === 'dark';\n if (isDarkThemeRef.current !== nextDark) {\n isDarkThemeRef.current = nextDark;\n queueMicrotask(() => setIsDarkTheme(nextDark));\n }\n\n if (readOnly) return;\n latestSceneRef.current = { elements, appState };\n\n // Intercept Excalidraw crop-image flow cho math stamps: khi user double-click\n // 1 stamp, Excalidraw set appState.croppingElementId. Ta dismiss crop mode +\n // mở Host editor tương ứng. handlePointerDown phát hiện double-click sớm\n // hơn — đây là fallback (đặc biệt khi click rơi vào selection handle).\n const cropId = appState?.croppingElementId as string | null | undefined;\n if (cropId && cropId !== handledCropIdRef.current && api) {\n const el = elements.find((e: ExcalidrawElement) => e.id === cropId);\n if (el) {\n const stamp = findStampForCustomData((el as { customData?: unknown }).customData, stamps);\n if (stamp) {\n handledCropIdRef.current = cropId;\n // Defer cả updateScene + openStamp ra khỏi commit-phase của\n // Excalidraw — nếu chạy đồng bộ, React 19 warn \"update scheduled\n // from inside an update function\" (handleChange chạy trong updater\n // của Excalidraw).\n const elId = el.id;\n const elCustom = (el as { customData?: unknown }).customData;\n const stampKind = stamp.kind;\n queueMicrotask(() => {\n try {\n api.updateScene({\n appState: { croppingElementId: null, selectedElementIds: {} },\n });\n } catch { /* ignore */ }\n openStamp(stampKind, { id: elId, customData: elCustom });\n });\n return;\n }\n }\n }\n if (!cropId) {\n handledCropIdRef.current = null;\n }\n\n const fileIds = Object.keys(files);\n const newIds = fileIds.filter((id) => !knownFileIdsRef.current.has(id));\n if (newIds.length > 0) {\n newIds.forEach((id) => knownFileIdsRef.current.add(id));\n onFilesChange?.(files, newIds);\n }\n\n if (!sceneThrottleRef.current) {\n sceneThrottleRef.current = setTimeout(async () => {\n sceneThrottleRef.current = null;\n try {\n const mod = await import('@excalidraw/excalidraw');\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n hashElementsVersionRef.current = (mod as any).hashElementsVersion;\n } catch (err) {\n console.warn('[whiteboard] import excalidraw để flush scene thất bại:', err);\n return;\n }\n flushSceneRef.current();\n }, SYNC_THROTTLE_MS);\n }\n\n // File throttle (1s): lưu raster vào IDB, bỏ math-stamp files.\n if (persistEnabled && newIds.length > 0) {\n for (const id of newIds) {\n if (files[id]) pendingFilesRef.current[id] = files[id];\n }\n if (!fileThrottleRef.current) {\n fileThrottleRef.current = setTimeout(() => {\n fileThrottleRef.current = null;\n flushFilesRef.current();\n }, 1000);\n }\n }\n\n // Prune throttle (2s): dọn orphan raster sau khi xoá element.\n if (persistEnabled && !pruneThrottleRef.current) {\n pruneThrottleRef.current = setTimeout(() => {\n pruneThrottleRef.current = null;\n flushPruneRef.current();\n }, 2000);\n }\n },\n [readOnly, api, onSceneChange, onFilesChange, persistEnabled, storageKey, stamps, openStamp],\n );\n\n // ---- Flush helpers (gọi từ setTimeout VÀ unmount cleanup) ----\n // Lưu vào ref để cleanup luôn dùng version mới nhất (closure-stable).\n const flushSceneRef = useRef<() => void>(() => undefined);\n flushSceneRef.current = () => {\n try {\n const latestScene = latestSceneRef.current;\n if (!latestScene) return;\n const liveElements = latestScene.elements.filter((e) => !e.isDeleted) as readonly ExcalidrawElement[];\n const liveAppState = pickSyncableAppState(latestScene.appState);\n const hashFn = hashElementsVersionRef.current;\n // Nếu chưa load module → bỏ qua hash dedupe, cứ ghi (correctness > perf trong unmount path).\n const elementHash = hashFn ? hashFn(liveElements) : liveElements.map((e) => e.id).join('|');\n const sceneHash = `${elementHash}:${JSON.stringify(liveAppState)}`;\n if (sceneHash === lastSceneHashRef.current) return;\n lastSceneHashRef.current = sceneHash;\n onSceneChangeRef.current?.({ elements: liveElements, appState: liveAppState });\n if (persistEnabledRef.current) {\n writeScene(persistKeyRef.current as string, {\n elements: liveElements,\n appState: liveAppState,\n });\n }\n } catch (err) {\n console.warn('[whiteboard] flushScene thất bại:', err);\n }\n };\n\n const flushFilesRef = useRef<() => void>(() => undefined);\n flushFilesRef.current = () => {\n try {\n const pending = pendingFilesRef.current;\n pendingFilesRef.current = {};\n if (Object.keys(pending).length === 0) return;\n const currentElements = (apiRef.current?.getSceneElements?.()\n ?? latestSceneRef.current?.elements\n ?? []) as readonly ExcalidrawElement[];\n const stampIds = new Set<string>();\n for (const el of currentElements) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const fid = (el as any).fileId as string | undefined;\n if (fid && isStampElement(el)) stampIds.add(fid);\n }\n const raster: BinaryFiles = {};\n for (const [id, f] of Object.entries(pending)) {\n if (!stampIds.has(id)) raster[id] = f;\n }\n if (Object.keys(raster).length > 0) {\n void writeFiles(persistKeyRef.current as string, raster);\n }\n } catch (err) {\n console.warn('[whiteboard] flushFiles thất bại:', err);\n }\n };\n\n const flushPruneRef = useRef<() => void>(() => undefined);\n flushPruneRef.current = () => {\n try {\n const currentElements = (apiRef.current?.getSceneElements?.()\n ?? latestSceneRef.current?.elements\n ?? []) as readonly ExcalidrawElement[];\n const keep = new Set<string>();\n for (const el of currentElements) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const fid = (el as any).fileId as string | undefined;\n if (fid && !isStampElement(el)) keep.add(fid);\n }\n void pruneFiles(persistKeyRef.current as string, keep);\n } catch (err) {\n console.warn('[whiteboard] flushPrune thất bại:', err);\n }\n };\n\n // ---- Mount: load persisted raster files từ IDB -> addFiles ----\n useEffect(() => {\n if (!api || !persistEnabled) return;\n let cancelled = false;\n void readFiles(storageKey as string).then(\n (files) => {\n // Recheck cancelled NGAY khi promise resolve — IDB onsuccess có thể\n // fire sau component unmount (tx microtask).\n if (cancelled) return;\n const entries = Object.entries(files);\n if (entries.length === 0) return;\n // Recheck một lần nữa trước khi gọi api.addFiles để chắc chắn\n // không invoke API trên instance đã teardown.\n if (cancelled) return;\n try {\n api.addFiles(\n entries.map(([id, f]) => ({\n id,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n dataURL: (f as any).dataURL,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n mimeType: (f as any).mimeType,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n created: (f as any).created ?? Date.now(),\n })),\n );\n if (cancelled) return;\n entries.forEach(([id]) => knownFileIdsRef.current.add(id));\n } catch (err) {\n if (cancelled) return;\n console.warn('[whiteboard] addFiles từ IDB thất bại:', err);\n }\n },\n (err) => {\n if (cancelled) return;\n console.warn('[whiteboard] readFiles thất bại:', err);\n },\n );\n return () => {\n cancelled = true;\n };\n }, [api, persistEnabled, storageKey]);\n\n useEffect(() => {\n if (!api) return;\n let cancelled = false;\n const run = async () => {\n if (cancelled) return;\n try {\n const elements = api.getSceneElements();\n if (!elements || elements.length === 0) return;\n if (cancelled) return;\n // Đọc stamps từ ref — props có thể đã thay đổi sau setTimeout 400ms,\n // closure-captured `stamps` sẽ stale.\n await restoreMissingStampFiles(api, elements, stampsRef.current);\n } catch (err) {\n if (cancelled) return;\n console.warn('Math stamp restore pass failed:', err);\n }\n };\n void run();\n const t = setTimeout(() => {\n void run();\n }, 400);\n return () => {\n cancelled = true;\n clearTimeout(t);\n };\n }, [api, persistedInitial]);\n\n // Unmount cleanup: flush pending writes TRƯỚC khi clearTimeout để không\n // mất scene/file write cuối khi user navigate giữa throttle window.\n useEffect(\n () => () => {\n if (sceneThrottleRef.current) {\n clearTimeout(sceneThrottleRef.current);\n sceneThrottleRef.current = null;\n flushSceneRef.current();\n }\n if (fileThrottleRef.current) {\n clearTimeout(fileThrottleRef.current);\n fileThrottleRef.current = null;\n flushFilesRef.current();\n }\n if (pruneThrottleRef.current) {\n clearTimeout(pruneThrottleRef.current);\n pruneThrottleRef.current = null;\n flushPruneRef.current();\n }\n },\n [],\n );\n\n // ---- Double-click detection for re-edit ----\n const handlePointerDown = useStampDoubleClick({\n enabled: !readOnly,\n stamps,\n onOpen: openStamp,\n });\n\n // ---- Keyboard shortcuts: đọc registry, mỗi stamp tự khai báo phím tắt ----\n useShortcuts({\n enabled: !readOnly,\n onToggle: toggleStampByKind,\n stamps,\n });\n\n // ---- Sync Excalidraw activeTool với activeStamp ----\n useEffect(() => {\n if (!api) return;\n if (activeStamp) {\n try {\n const cur = api.getAppState?.()?.activeTool?.type ?? 'selection';\n if (cur && cur !== 'hand') prevExcalidrawToolRef.current = cur;\n api.setActiveTool?.({ type: 'hand' });\n } catch { /* ignore */ }\n } else {\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n api.setActiveTool?.({ type: prevExcalidrawToolRef.current as any });\n } catch { /* ignore */ }\n }\n }, [activeStamp, api]);\n\n // ---- Block Excalidraw shortcuts khi stamp panel đang mở ----\n useStampShortcutBlocker({ activeStamp, stamps });\n\n // ---- Esc đóng panel (capture phase để chạy TRƯỚC Excalidraw) ----\n useEffect(() => {\n if (!activeStamp) return;\n const onKey = (e: KeyboardEvent) => {\n if (e.key !== 'Escape') return;\n const ae = document.activeElement as HTMLElement | null;\n if (ae && (ae.tagName === 'TEXTAREA' || ae.isContentEditable)) {\n return;\n }\n e.preventDefault();\n e.stopPropagation();\n closeStamp();\n };\n window.addEventListener('keydown', onKey, { capture: true });\n return () => window.removeEventListener('keydown', onKey, { capture: true });\n }, [activeStamp, closeStamp]);\n\n useStampClickOutside({ activeStamp, hostRef, onClose: closeStamp });\n\n // ---- PDF import handlers ----\n const handlePdfPick = useCallback(\n async (file: File) => {\n if (readOnly || pdfBusy) return;\n setPdfBusy(true);\n try {\n const doc = await loadPdfDocument(file);\n setPdfPending({ doc, fileName: file.name, totalPages: doc.numPages });\n } catch (err) {\n console.warn('[whiteboard] Đọc PDF thất bại:', err);\n window.alert('Không đọc được PDF. File có thể đã hỏng hoặc bị mật khẩu bảo vệ.');\n } finally {\n setPdfBusy(false);\n }\n },\n [readOnly, pdfBusy],\n );\n\n const handlePdfConfirm = useCallback(\n async (pages: number[]) => {\n if (!pdfPending || !api) return;\n const { doc } = pdfPending;\n setPdfPending(null);\n setPdfBusy(true);\n const scale = 2;\n try {\n const rendered = await rasterizePdf(doc, { pages, scale });\n await closePdfDocument(doc);\n insertRasterizedPagesIntoScene(api, rendered, { scale });\n } catch (err) {\n console.warn('[whiteboard] Chèn PDF thất bại:', err);\n window.alert('Chèn PDF thất bại. Xem console để biết chi tiết.');\n } finally {\n setPdfBusy(false);\n }\n },\n [pdfPending, api],\n );\n\n const handlePdfCancel = useCallback(() => {\n if (pdfPending) {\n void closePdfDocument(pdfPending.doc);\n }\n setPdfPending(null);\n }, [pdfPending]);\n\n // ---- Drop handler: bắt PDF file kéo vào canvas TRƯỚC Excalidraw ----\n // Excalidraw không hiểu application/pdf → mặc định sẽ reject (toast lỗi).\n // Capture phase + preventDefault để ngắt sớm rồi tự xử lý.\n useEffect(() => {\n if (readOnly) return;\n const root = document.querySelector<HTMLElement>('.excalidraw');\n if (!root) return;\n\n const onDragOver = (e: DragEvent) => {\n const items = e.dataTransfer?.items;\n if (!items) return;\n for (let i = 0; i < items.length; i++) {\n if (items[i].kind === 'file' && items[i].type === 'application/pdf') {\n e.preventDefault();\n e.stopPropagation();\n if (e.dataTransfer) e.dataTransfer.dropEffect = 'copy';\n return;\n }\n }\n };\n\n const onDrop = (e: DragEvent) => {\n const files = e.dataTransfer?.files;\n if (!files || files.length === 0) return;\n const pdf = Array.from(files).find((f) => f.type === 'application/pdf');\n if (!pdf) return;\n e.preventDefault();\n e.stopPropagation();\n void handlePdfPick(pdf);\n };\n\n root.addEventListener('dragover', onDragOver, { capture: true });\n root.addEventListener('drop', onDrop, { capture: true });\n return () => {\n root.removeEventListener('dragover', onDragOver, { capture: true });\n root.removeEventListener('drop', onDrop, { capture: true });\n };\n }, [readOnly, handlePdfPick, api]);\n\n return (\n <div className={`relative h-full w-full${isDarkTheme ? ' theme--dark' : ''}`}>\n <Suspense fallback={<ExcalidrawLoadingFallback />}>\n <Excalidraw\n excalidrawAPI={(a: ExApi) => {\n // Excalidraw có thể gọi callback này đồng bộ trong commit-phase của\n // họ. Bail-out qua ref + defer setApi để tránh \"update scheduled\n // from inside an update function\" trên React 19 / Next.js 16.\n if (apiRef.current === a) return;\n apiRef.current = a;\n queueMicrotask(() => {\n setApi(a);\n onApi?.(a);\n });\n }}\n langCode={langCode}\n viewModeEnabled={readOnly}\n initialData={\n effectiveInitialScene\n ? {\n elements: effectiveInitialScene.elements,\n appState: {\n ...effectiveInitialScene.appState,\n gridSize: effectiveInitialScene.appState.gridSize ?? undefined,\n },\n }\n : { appState: { viewBackgroundColor: '#ffffff' } }\n }\n onChange={handleChange}\n onPointerDown={handlePointerDown}\n />\n </Suspense>\n\n <ToolbarInjector\n enabled={!readOnly}\n activeStampKind={activeStamp}\n onToggle={toggleStampByKind}\n stamps={stamps}\n />\n\n <PdfImporterButton enabled={!readOnly} onPick={handlePdfPick} />\n\n {pdfPending && (\n <PageRangeDialog\n doc={pdfPending.doc}\n fileName={pdfPending.fileName}\n onConfirm={handlePdfConfirm}\n onCancel={handlePdfCancel}\n />\n )}\n\n {pdfBusy && !pdfPending && (\n <div\n aria-live=\"polite\"\n role=\"status\"\n style={{\n position: 'fixed',\n bottom: 16,\n right: 16,\n padding: '8px 14px',\n background: 'rgba(0,0,0,0.75)',\n color: '#fff',\n borderRadius: 6,\n fontSize: 12,\n zIndex: 10000,\n }}\n >\n Đang xử lý PDF…\n </div>\n )}\n\n {HostComponent && (\n <HostComponent\n ref={hostRef}\n api={api}\n editingElement={editingElement}\n onClose={closeStamp}\n isDark={isDarkTheme}\n />\n )}\n </div>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/stamps/shared/catalog.ts","../src/stamps/shared/registry.ts","../src/stamps/shared/ToolbarInjector.tsx","../src/stamps/shared/useShortcuts.ts","../src/pdf/PdfImporterButton.tsx","../src/pdf/parseRange.ts","../src/pdf/rasterize.ts","../src/pdf/PageRangeDialog.tsx","../src/stamps/shared/useStampDoubleClick.ts","../src/stamps/shared/useStampShortcutBlocker.ts","../src/stamps/shared/useStampClickOutside.ts","../src/hooks/useExcalidrawApi.ts","../src/hooks/useActiveStamp.ts","../src/pdf/insertPdfPages.ts","../src/hooks/usePdfImporter.ts","../src/serialize.ts","../src/stamps/shared/restoreStampFiles.ts","../src/core/persistence/validation.ts","../src/core/persistence/sceneStore.ts","../src/core/persistence/fileStore.ts","../src/hooks/useScenePersist.ts","../src/Whiteboard.tsx","../src/stamps/geometry-2d/dsl/schema.ts","../src/stamps/geometry-2d/dsl/transpile/errors.ts","../src/stamps/geometry-2d/dsl/transpile/symbols.ts","../src/stamps/geometry-2d/dsl/transpile/refs.ts","../src/stamps/geometry-2d/dsl/transpile/cycles.ts","../src/stamps/geometry-2d/dsl/transpile/ids.ts","../src/stamps/geometry-2d/dsl/transpile/emitPoint.ts","../src/stamps/geometry-2d/dsl/transpile/emitShape.ts","../src/stamps/geometry-2d/dsl/transpile.ts","../src/stamps/geometry-2d/ai/provider.ts","../src/stamps/geometry-2d/dsl/fixtures/triangle-equilateral.ts","../src/stamps/geometry-2d/dsl/fixtures/triangle-median.ts","../src/stamps/geometry-2d/dsl/fixtures/triangle-altitude.ts","../src/stamps/geometry-2d/dsl/fixtures/triangle-centroid.ts","../src/stamps/geometry-2d/dsl/fixtures/triangle-orthocenter.ts","../src/stamps/geometry-2d/dsl/fixtures/triangle-circumcircle.ts","../src/stamps/geometry-2d/dsl/fixtures/triangle-incircle.ts","../src/stamps/geometry-2d/dsl/fixtures/parallelogram.ts","../src/stamps/geometry-2d/dsl/fixtures/two-circles-intersect.ts","../src/stamps/geometry-2d/ai/prompt.ts","../src/stamps/geometry-2d/ai/tools.ts","../src/stamps/geometry-2d/ai/buildFigure.ts"],"names":["useEffect","POPOVER_SELECTOR","useState","useRef","jsx","jsxs","Fragment","createPortal","useMemo","useCallback","fixture","z"],"mappings":"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","file":"index.mjs","sourcesContent":["// src/stamps/shared/catalog.ts\n//\n// STAMP_CATALOG — manifest tra cứu mọi stamp có sẵn trong package (B½.1,\n// issue #29). Consumer build admin UI / picker / docs page chỉ cần import\n// hằng số này; không phải tự đọc source.\n//\n// `bundleSize` được populate bởi `scripts/build-catalog.mjs` (chạy postbuild)\n// — số đo gzip size thực tế của `dist/{kind}.mjs`. Build script replace giá\n// trị placeholder `{ js: 0, css: 0 }` thành số KB chính xác đồng thời ghi\n// `dist/catalog.json` để consumer có thể fetch runtime nếu cần.\n//\n// Khi thêm stamp mới (xem `docs/superpowers/specs/add-new-stamp-howto.md`),\n// thêm entry vào mảng này — entry phải match `stamp.kind` của registry.\n\n/**\n * Mô tả 1 stamp trong catalog. Bundle size đo bằng KB (kilobytes) gzip — tính\n * trên file entry `dist/{id}.mjs`. Đây là bound trên: code thực sự nạp khi\n * user dùng stamp có thể nhỏ hơn nếu shared chunks đã load cho stamp khác.\n */\nexport interface StampCatalogEntry {\n /** Khớp với `StampType.kind`. Vd 'geometry', 'latex', 'geometry3d', 'graph2d'. */\n id: string;\n /** Tên hiển thị cho admin UI (tiếng Việt). */\n title: string;\n /** Phiên bản schema customData. Bump khi BREAKING change format. */\n version: number;\n /** true nếu stamp chưa production-ready (EXPERIMENTAL_STAMPS). */\n experimental: boolean;\n /** Dependency runtime mà consumer phải cài qua peerDependency. */\n runtimeDeps: ReadonlyArray<string>;\n /** Size dist/{id}.{mjs,css} sau gzip (KB). Populated postbuild. */\n bundleSize: { js: number; css: number };\n}\n\n/**\n * Catalog tĩnh của 4 stamps hiện tại. `bundleSize` ở đây là PLACEHOLDER —\n * `scripts/build-catalog.mjs` sẽ override giá trị này trong `dist/`. Tại\n * source (chạy jest / dev), bundleSize sẽ là 0 — đừng dùng cho quyết định\n * production, chỉ dùng entries trong build artifact.\n */\nexport const STAMP_CATALOG: ReadonlyArray<StampCatalogEntry> = Object.freeze([\n {\n id: 'geometry',\n title: 'Hình học 2D (JSXGraph)',\n version: 1,\n experimental: false,\n runtimeDeps: ['jsxgraph'],\n bundleSize: { js: 0, css: 0 },\n },\n {\n id: 'latex',\n title: 'Công thức LaTeX (KaTeX)',\n version: 1,\n experimental: false,\n runtimeDeps: ['katex'],\n bundleSize: { js: 0, css: 0 },\n },\n {\n id: 'geometry3d',\n title: 'Hình học 3D (JSXGraph view3d)',\n version: 2,\n experimental: true,\n runtimeDeps: ['jsxgraph'],\n bundleSize: { js: 0, css: 0 },\n },\n {\n id: 'graph2d',\n title: 'Đồ thị hàm số 2D (JSXGraph)',\n version: 2,\n experimental: true,\n runtimeDeps: ['jsxgraph'],\n bundleSize: { js: 0, css: 0 },\n },\n]);\n\n/** Lấy entry theo stamp.kind. Trả null nếu không có. */\nexport function findCatalogEntry(id: string): StampCatalogEntry | null {\n return STAMP_CATALOG.find((entry) => entry.id === id) ?? null;\n}\n","import { geometryStamp } from '../geometry-2d';\nimport { latexStamp } from '../latex';\nimport { geometry3dStamp } from '../geometry-3d';\nimport { graph2dStamp } from '../graph-2d';\nimport type { StampType } from './types';\n\nexport { geometryStamp, type GeometryCustomData } from '../geometry-2d';\nexport { latexStamp, type LatexCustomData } from '../latex';\nexport { geometry3dStamp, type Geometry3DCustomData } from '../geometry-3d';\nexport { graph2dStamp, type Graph2DCustomData } from '../graph-2d';\nexport type { StampType, BaseStampCustomData } from './types';\nexport {\n STAMP_CATALOG,\n findCatalogEntry,\n type StampCatalogEntry,\n} from './catalog';\n\n/** Stamp ổn định, sẵn sàng production. */\nexport const STABLE_STAMPS: ReadonlyArray<StampType> = Object.freeze([\n geometryStamp,\n latexStamp,\n]);\n\n/** Stamp experimental — chưa ổn định cho production. Consumer phải opt-in. */\nexport const EXPERIMENTAL_STAMPS: ReadonlyArray<StampType> = Object.freeze([\n geometry3dStamp,\n graph2dStamp,\n]);\n\n/** Tất cả stamp (stable + experimental). */\nexport const ALL_STAMPS: ReadonlyArray<StampType> = Object.freeze([\n ...STABLE_STAMPS,\n ...EXPERIMENTAL_STAMPS,\n]);\n\nexport const DEFAULT_STAMPS: ReadonlyArray<StampType> = ALL_STAMPS;\n\n/** Tìm stamp tương ứng với customData của element. null nếu không match. */\nexport function findStampForCustomData(\n data: unknown,\n stamps: ReadonlyArray<StampType> = DEFAULT_STAMPS,\n): StampType | null {\n for (const s of stamps) {\n if (s.matchesCustomData(data)) return s;\n }\n return null;\n}\n\n/** isMathStamp version dựa trên registry. */\nexport function isStampElement<T extends { customData?: unknown }>(\n element: T,\n stamps: ReadonlyArray<StampType> = DEFAULT_STAMPS,\n): boolean {\n return findStampForCustomData(element.customData, stamps) !== null;\n}\n","'use client';\n\nimport { useEffect, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { DEFAULT_STAMPS } from './registry';\nimport type { StampType } from './types';\n\ninterface Props {\n /** Bật/tắt theo role. Khi disabled → không mount portal. */\n enabled: boolean;\n /** Kind stamp đang active, hoặc null nếu không có stamp nào mở. */\n activeStampKind: string | null;\n /** Toggle stamp theo kind. */\n onToggle: (kind: string) => void;\n /** Danh sách stamp đăng ký. Mặc định DEFAULT_STAMPS. */\n stamps?: ReadonlyArray<StampType>;\n}\n\nconst MENU_WRAPPER_ID = 'stamp-menu-portal-wrapper';\n/**\n * Excalidraw 0.18 áp dụng class `App-toolbar__extra-tools-dropdown` lên\n * popover wrapper của More tools cho cả desktop lẫn mobile. Mobile có\n * thêm modifier `dropdown-menu--mobile`. Selector này cover cả hai mode.\n */\nconst POPOVER_SELECTOR =\n '.App-toolbar__extra-tools-dropdown .dropdown-menu-container';\n\n/**\n * Inject stamp buttons vào popover \"More tools\" của Excalidraw.\n *\n * v0.7.0: thay vì inject inline vào main toolbar (desktop) hoặc dropdown\n * riêng cho mobile, ta chỉ inject vào dropdown-menu-container bên trong\n * popover của Excalidraw. Selector cover cả desktop lẫn mobile vì hai\n * mode dùng cùng cấu trúc DOM (DropdownMenu.Content).\n *\n * Popover mount/unmount theo trigger click → MutationObserver dò DOM,\n * mount lại wrapper khi cần.\n */\nexport function ToolbarInjector({\n enabled,\n activeStampKind,\n onToggle,\n stamps = DEFAULT_STAMPS,\n}: Props) {\n const [menuMount, setMenuMount] = useState<HTMLElement | null>(null);\n const menuMountRef = useRef<HTMLElement | null>(null);\n\n useEffect(() => {\n if (!enabled) {\n if (menuMountRef.current !== null) {\n menuMountRef.current = null;\n setMenuMount(null);\n }\n document.getElementById(MENU_WRAPPER_ID)?.remove();\n return;\n }\n\n let cancelled = false;\n let observer: MutationObserver | null = null;\n let rafId: number | null = null;\n let observedRoot: Element | null = null;\n\n const apply = (next: HTMLElement | null) => {\n if (cancelled || menuMountRef.current === next) return;\n menuMountRef.current = next;\n queueMicrotask(() => {\n if (!cancelled) setMenuMount(next);\n });\n };\n\n const findMenu = () => {\n if (cancelled) return;\n const container = document.querySelector<HTMLElement>(POPOVER_SELECTOR);\n if (!container) {\n apply(null);\n return;\n }\n let wrapper = container.querySelector<HTMLDivElement>('#' + MENU_WRAPPER_ID);\n if (!wrapper) {\n wrapper = document.createElement('div');\n wrapper.id = MENU_WRAPPER_ID;\n wrapper.setAttribute('data-stamp-menu', 'true');\n wrapper.setAttribute('data-stamp-area', 'true');\n wrapper.style.display = 'contents';\n container.insertBefore(wrapper, container.firstChild);\n }\n apply(wrapper);\n };\n\n /**\n * Scope observer xuống `.excalidraw` để giảm tần suất callback trigger\n * (mutation ở các node ngoài Excalidraw không liên quan tới popover).\n * Nếu `.excalidraw` chưa mount → tạm observe `document.body` để bắt\n * lúc nó xuất hiện, rồi switch sang root nhỏ hơn.\n */\n const attachObserver = () => {\n if (cancelled) return;\n const excalidraw = document.querySelector<HTMLElement>('.excalidraw');\n const nextRoot: Element = excalidraw ?? document.body;\n if (observedRoot === nextRoot) return;\n observer?.disconnect();\n observedRoot = nextRoot;\n observer = new MutationObserver(onMutation);\n observer.observe(nextRoot, { childList: true, subtree: true });\n };\n\n /**\n * rAF debounce: gộp nhiều mutation cùng tick thành 1 lần xử lý.\n * Excalidraw có thể trigger hàng chục mutation khi mở/đóng popover —\n * mỗi pass chỉ tốn 1 lần querySelector + DOM insert.\n */\n const onMutation = () => {\n if (rafId != null) return;\n rafId = requestAnimationFrame(() => {\n rafId = null;\n if (cancelled) return;\n // Nếu đang observe body mà giờ `.excalidraw` đã mount → switch sang nó.\n if (observedRoot !== document.querySelector('.excalidraw')) {\n attachObserver();\n }\n findMenu();\n });\n };\n\n findMenu();\n attachObserver();\n\n return () => {\n cancelled = true;\n if (rafId != null) {\n cancelAnimationFrame(rafId);\n rafId = null;\n }\n observer?.disconnect();\n observer = null;\n observedRoot = null;\n document.getElementById(MENU_WRAPPER_ID)?.remove();\n };\n }, [enabled]);\n\n if (!enabled || !menuMount) return null;\n\n const closePopover = () => {\n const trigger = document.querySelector<HTMLButtonElement>(\n '.App-toolbar__extra-tools-trigger',\n );\n trigger?.click();\n };\n\n return createPortal(\n <>\n {stamps.map((stamp) => {\n const { displayLabel, shortcut } = splitTitleAndShortcut(\n stamp.toolbarTitle,\n stamp.toolbarLabel,\n );\n return (\n <StampMenuItem\n key={stamp.kind}\n icon={stamp.toolbarIcon}\n label={displayLabel}\n ariaLabel={stamp.toolbarTitle}\n shortcut={shortcut}\n active={activeStampKind === stamp.kind}\n onClick={() => {\n onToggle(stamp.kind);\n closePopover();\n }}\n dataTestId={stamp.toolbarTestId}\n />\n );\n })}\n <div\n aria-hidden=\"true\"\n style={{\n height: 1,\n background: 'var(--default-border-color, rgba(0,0,0,0.08))',\n margin: '6px 4px',\n }}\n />\n </>,\n menuMount,\n );\n}\n\n/**\n * Tách \"(X)\" cuối toolbarTitle thành shortcut hiển thị riêng ở góc phải\n * (giống các tool gốc Excalidraw: Frame F, Laser K, ...). Nếu title không\n * có pattern \"(...)\", fallback dùng toolbarLabel.\n */\nfunction splitTitleAndShortcut(\n title: string,\n fallbackShortcut: string,\n): { displayLabel: string; shortcut: string } {\n const match = title.match(/^(.*?)\\s*\\(([^()]+)\\)\\s*$/);\n if (match) {\n return { displayLabel: match[1].trim(), shortcut: match[2].trim() };\n }\n return { displayLabel: title, shortcut: fallbackShortcut };\n}\n\ninterface StampMenuItemProps {\n icon: React.ReactNode;\n label: string;\n ariaLabel: string;\n shortcut: string;\n active: boolean;\n onClick: () => void;\n dataTestId?: string;\n}\n\nfunction StampMenuItem({\n icon,\n label,\n ariaLabel,\n shortcut,\n active,\n onClick,\n dataTestId,\n}: StampMenuItemProps) {\n const className = [\n 'dropdown-menu-item',\n 'dropdown-menu-item-base',\n active ? 'dropdown-menu-item--selected' : '',\n ]\n .filter(Boolean)\n .join(' ');\n return (\n <button\n type=\"button\"\n onClick={onClick}\n title={ariaLabel}\n aria-label={ariaLabel}\n aria-pressed={active}\n data-testid={dataTestId}\n className={className}\n >\n <div className=\"dropdown-menu-item__icon\" aria-hidden=\"true\">\n {icon}\n </div>\n <div className=\"dropdown-menu-item__text\">{label}</div>\n {shortcut ? (\n <div className=\"dropdown-menu-item__shortcut\">{shortcut}</div>\n ) : null}\n </button>\n );\n}\n","import { useEffect } from 'react';\nimport { DEFAULT_STAMPS } from './registry';\nimport type { StampType } from './types';\n\ninterface Options {\n enabled: boolean;\n /** Toggle stamp theo kind khi user bấm shortcut tương ứng. */\n onToggle: (kind: string) => void;\n /** Registry. Mặc định DEFAULT_STAMPS. */\n stamps?: ReadonlyArray<StampType>;\n}\n\nfunction isEditableTarget(t: EventTarget | null): boolean {\n if (!t || !(t instanceof HTMLElement)) return false;\n if (t.isContentEditable) return true;\n const tag = t.tagName;\n return tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT';\n}\n\n/**\n * Bind keyboard shortcut cho mỗi stamp trong registry. Capture phase +\n * stopPropagation để chặn trước Excalidraw's bubble-phase handlers (Excalidraw\n * dùng `L` cho Line tool, nếu không chặn → bấm L lại chuyển tool thay vì\n * toggle LaTeX panel).\n */\nexport function useShortcuts({\n enabled,\n onToggle,\n stamps = DEFAULT_STAMPS,\n}: Options): void {\n useEffect(() => {\n if (!enabled) return;\n const keyToKind = new Map<string, string>();\n for (const s of stamps) keyToKind.set(s.shortcutKey, s.kind);\n\n const handler = (e: KeyboardEvent) => {\n if (e.metaKey || e.ctrlKey || e.altKey) return;\n if (isEditableTarget(e.target)) return;\n const key = e.key.toLowerCase();\n const kind = keyToKind.get(key);\n if (!kind) return;\n e.preventDefault();\n e.stopPropagation();\n onToggle(kind);\n };\n window.addEventListener('keydown', handler, { capture: true });\n return () => window.removeEventListener('keydown', handler, { capture: true });\n }, [enabled, onToggle, stamps]);\n}\n","'use client';\n\nimport { useEffect, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\n\ninterface Props {\n enabled: boolean;\n onPick: (file: File) => void;\n}\n\nconst WRAPPER_ID = 'pdf-import-portal-wrapper';\nconst POPOVER_SELECTOR =\n '.App-toolbar__extra-tools-dropdown .dropdown-menu-container';\n\n/**\n * Button \"Chèn PDF\" portal vào More tools dropdown của Excalidraw, ngay\n * dưới các stamp buttons. Click → mở native file picker (hidden input).\n *\n * Tách riêng khỏi ToolbarInjector vì PDF không phải stamp (không có Host,\n * không re-edit). Cùng pattern observer như ToolbarInjector để bắt\n * popover mount/unmount.\n */\nexport function PdfImporterButton({ enabled, onPick }: Props) {\n const [mount, setMount] = useState<HTMLElement | null>(null);\n const mountRef = useRef<HTMLElement | null>(null);\n const inputRef = useRef<HTMLInputElement | null>(null);\n\n useEffect(() => {\n if (!enabled) {\n mountRef.current = null;\n setMount(null);\n document.getElementById(WRAPPER_ID)?.remove();\n return;\n }\n\n let cancelled = false;\n let observer: MutationObserver | null = null;\n let rafId: number | null = null;\n let observedRoot: Element | null = null;\n\n const apply = (next: HTMLElement | null) => {\n if (cancelled || mountRef.current === next) return;\n mountRef.current = next;\n queueMicrotask(() => {\n if (!cancelled) setMount(next);\n });\n };\n\n const findMenu = () => {\n if (cancelled) return;\n const container = document.querySelector<HTMLElement>(POPOVER_SELECTOR);\n if (!container) {\n apply(null);\n return;\n }\n let wrapper = container.querySelector<HTMLDivElement>('#' + WRAPPER_ID);\n if (!wrapper) {\n wrapper = document.createElement('div');\n wrapper.id = WRAPPER_ID;\n wrapper.setAttribute('data-pdf-import', 'true');\n wrapper.style.display = 'contents';\n // Append cuối để PDF button nằm sau stamps + divider.\n container.appendChild(wrapper);\n }\n apply(wrapper);\n };\n\n const attachObserver = () => {\n if (cancelled) return;\n const excalidraw = document.querySelector<HTMLElement>('.excalidraw');\n const nextRoot: Element = excalidraw ?? document.body;\n if (observedRoot === nextRoot) return;\n observer?.disconnect();\n observedRoot = nextRoot;\n observer = new MutationObserver(onMutation);\n observer.observe(nextRoot, { childList: true, subtree: true });\n };\n\n const onMutation = () => {\n if (rafId != null) return;\n rafId = requestAnimationFrame(() => {\n rafId = null;\n if (cancelled) return;\n if (observedRoot !== document.querySelector('.excalidraw')) {\n attachObserver();\n }\n findMenu();\n });\n };\n\n findMenu();\n attachObserver();\n\n return () => {\n cancelled = true;\n if (rafId != null) cancelAnimationFrame(rafId);\n observer?.disconnect();\n document.getElementById(WRAPPER_ID)?.remove();\n };\n }, [enabled]);\n\n const closePopover = () => {\n const trigger = document.querySelector<HTMLButtonElement>(\n '.App-toolbar__extra-tools-trigger',\n );\n trigger?.click();\n };\n\n const handleClick = () => {\n inputRef.current?.click();\n };\n\n const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (file) onPick(file);\n // Reset để chọn lại cùng file lần sau vẫn fire onChange.\n e.target.value = '';\n closePopover();\n };\n\n if (!enabled || !mount) {\n // Vẫn render hidden input để parent có thể gọi qua ref nếu muốn — nhưng\n // không cần. Giữ null khi chưa mount để tránh DOM thừa.\n return (\n <input\n ref={inputRef}\n type=\"file\"\n accept=\"application/pdf,.pdf\"\n style={{ display: 'none' }}\n onChange={handleFileChange}\n />\n );\n }\n\n return (\n <>\n <input\n ref={inputRef}\n type=\"file\"\n accept=\"application/pdf,.pdf\"\n style={{ display: 'none' }}\n onChange={handleFileChange}\n />\n {createPortal(\n <button\n type=\"button\"\n onClick={handleClick}\n title=\"Chèn PDF (P)\"\n aria-label=\"Chèn PDF\"\n data-testid=\"pdf-import-button\"\n className=\"dropdown-menu-item dropdown-menu-item-base\"\n >\n <div className=\"dropdown-menu-item__icon\" aria-hidden=\"true\">\n <PdfIcon />\n </div>\n <div className=\"dropdown-menu-item__text\">Chèn PDF</div>\n <div className=\"dropdown-menu-item__shortcut\">P</div>\n </button>,\n mount,\n )}\n </>\n );\n}\n\nfunction PdfIcon() {\n return (\n <svg\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.6\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M14 3H7a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8z\" />\n <path d=\"M14 3v5h5\" />\n <text x=\"7.5\" y=\"17\" fontSize=\"6\" fontFamily=\"sans-serif\" fontWeight=\"700\" stroke=\"none\" fill=\"currentColor\">\n PDF\n </text>\n </svg>\n );\n}\n","/**\n * Parse chuỗi range trang dạng \"1,3,5-10\" → array số 1-based đã sort + dedupe.\n *\n * - Tokens cách nhau bằng dấu phẩy hoặc khoảng trắng.\n * - Token có gạch \"-\" → range inclusive (5-10 = [5,6,7,8,9,10]).\n * - Khoảng trắng quanh số bị bỏ qua.\n * - Empty / chỉ space → [].\n *\n * Throws `Error` với message tiếng Việt khi:\n * - Token không phải số / không phải range hợp lệ.\n * - Số <= 0 hoặc > totalPages.\n * - Range đảo ngược (vd \"10-5\") — coi là lỗi user thay vì auto-reverse để\n * tránh nuốt typo.\n */\nexport function parsePageRange(input: string, totalPages: number): number[] {\n if (!Number.isInteger(totalPages) || totalPages <= 0) {\n throw new Error('Số trang phải là số nguyên dương.');\n }\n const trimmed = input.trim();\n if (trimmed === '') return [];\n\n const tokens = trimmed\n .split(/[,\\s]+/)\n .map((t) => t.trim())\n .filter((t) => t.length > 0);\n\n const set = new Set<number>();\n\n for (const token of tokens) {\n if (token.includes('-')) {\n const parts = token.split('-');\n if (parts.length !== 2) {\n throw new Error(`Khoảng trang không hợp lệ: \"${token}\".`);\n }\n const start = parseStrictInt(parts[0]);\n const end = parseStrictInt(parts[1]);\n if (start === null || end === null) {\n throw new Error(`Khoảng trang không hợp lệ: \"${token}\".`);\n }\n if (start > end) {\n throw new Error(`Khoảng trang ngược: \"${token}\" (đầu > cuối).`);\n }\n if (start < 1 || end > totalPages) {\n throw new Error(\n `Khoảng trang vượt giới hạn: \"${token}\". PDF có ${totalPages} trang.`,\n );\n }\n for (let i = start; i <= end; i++) set.add(i);\n } else {\n const n = parseStrictInt(token);\n if (n === null) {\n throw new Error(`Số trang không hợp lệ: \"${token}\".`);\n }\n if (n < 1 || n > totalPages) {\n throw new Error(\n `Số trang vượt giới hạn: ${n}. PDF có ${totalPages} trang.`,\n );\n }\n set.add(n);\n }\n }\n\n return Array.from(set).sort((a, b) => a - b);\n}\n\nfunction parseStrictInt(s: string): number | null {\n if (!/^-?\\d+$/.test(s)) return null;\n const n = Number(s);\n return Number.isInteger(n) ? n : null;\n}\n","/**\n * Rasterize PDF → PNG dataURLs cho từng trang.\n *\n * Worker config:\n * - pdfjs-dist 5.x cần `GlobalWorkerOptions.workerSrc` (URL tới worker .mjs).\n * - Mặc định trỏ CDN (jsdelivr). Consumer có thể override qua\n * `configurePdfWorker(src)` trước khi gọi rasterize lần đầu.\n * - Lý do CDN thay vì bundled worker: tsup không có cách clean để emit\n * worker chunk ra cùng dist/ với URL ổn định, và consumer (Next.js)\n * có thể self-host nếu cần offline.\n *\n * Lazy import pdfjs-dist để không phình bundle khi user không dùng PDF.\n */\nimport type { PDFDocumentProxy, PDFPageProxy } from 'pdfjs-dist';\n\nlet workerSrcOverride: string | null = null;\nlet pdfjsCache: typeof import('pdfjs-dist') | null = null;\n\n/**\n * Override workerSrc trước khi rasterize. Gọi từ consumer khi cần self-host\n * worker file (vd offline mode, CSP cấm CDN).\n *\n * Mặc định nếu không gọi: dùng CDN jsdelivr theo version pdfjs-dist đã cài.\n */\nexport function configurePdfWorker(workerSrc: string): void {\n workerSrcOverride = workerSrc;\n if (pdfjsCache) {\n pdfjsCache.GlobalWorkerOptions.workerSrc = workerSrc;\n }\n}\n\nasync function loadPdfjs(): Promise<typeof import('pdfjs-dist')> {\n if (pdfjsCache) return pdfjsCache;\n const mod = await import('pdfjs-dist');\n const workerSrc =\n workerSrcOverride ??\n `https://cdn.jsdelivr.net/npm/pdfjs-dist@${mod.version}/build/pdf.worker.min.mjs`;\n mod.GlobalWorkerOptions.workerSrc = workerSrc;\n pdfjsCache = mod;\n return mod;\n}\n\nexport interface RasterizedPage {\n pageNumber: number;\n dataURL: string;\n width: number;\n height: number;\n mimeType: 'image/png';\n}\n\nexport interface RasterizeOptions {\n /** Scale render. Mặc định 2 (HiDPI sharp). */\n scale?: number;\n /** Danh sách trang 1-based. Mặc định: tất cả. */\n pages?: number[];\n /** Callback progress sau mỗi page. */\n onProgress?: (done: number, total: number) => void;\n /** AbortSignal để cancel giữa chừng. */\n signal?: AbortSignal;\n}\n\n/**\n * Load PDF chỉ để lấy `numPages` (vd hiển thị tổng số trang trên dialog).\n * Caller phải tự đóng document bằng `closePdfDocument(doc)` khi xong.\n */\nexport async function loadPdfDocument(source: File | Blob | ArrayBuffer): Promise<PDFDocumentProxy> {\n const pdfjs = await loadPdfjs();\n const data = source instanceof ArrayBuffer ? source : await source.arrayBuffer();\n const task = pdfjs.getDocument({ data: new Uint8Array(data) });\n return task.promise;\n}\n\nexport async function closePdfDocument(doc: PDFDocumentProxy): Promise<void> {\n try {\n await doc.cleanup();\n await doc.destroy();\n } catch {\n /* ignore — best-effort cleanup */\n }\n}\n\n/**\n * Render danh sách trang ra PNG dataURL.\n *\n * Lưu ý:\n * - Sử dụng `OffscreenCanvas` nếu có (browser hiện đại) để không touch DOM,\n * fallback `<canvas>` document.createElement.\n * - Mỗi page render xong sẽ release canvas (cho GC sớm với PDF nhiều trang).\n */\nexport async function rasterizePdf(\n doc: PDFDocumentProxy,\n options: RasterizeOptions = {},\n): Promise<RasterizedPage[]> {\n const scale = options.scale ?? 2;\n const total = doc.numPages;\n const pages = options.pages ?? Array.from({ length: total }, (_, i) => i + 1);\n const signal = options.signal;\n\n const result: RasterizedPage[] = [];\n for (let i = 0; i < pages.length; i++) {\n if (signal?.aborted) {\n throw new DOMException('Rasterize PDF bị huỷ.', 'AbortError');\n }\n const pageNum = pages[i];\n const page = await doc.getPage(pageNum);\n try {\n const rendered = await renderPageToPng(page, scale);\n result.push({ pageNumber: pageNum, mimeType: 'image/png', ...rendered });\n } finally {\n page.cleanup();\n }\n options.onProgress?.(i + 1, pages.length);\n }\n return result;\n}\n\nasync function renderPageToPng(\n page: PDFPageProxy,\n scale: number,\n): Promise<{ dataURL: string; width: number; height: number }> {\n const viewport = page.getViewport({ scale });\n const width = Math.ceil(viewport.width);\n const height = Math.ceil(viewport.height);\n\n const canvas = document.createElement('canvas');\n canvas.width = width;\n canvas.height = height;\n const ctx = canvas.getContext('2d');\n if (!ctx) throw new Error('Không lấy được 2D context của canvas.');\n await page.render({ canvasContext: ctx, viewport, canvas }).promise;\n const dataURL = canvas.toDataURL('image/png');\n return { dataURL, width, height };\n}\n\n/**\n * Render thumbnail nhẹ cho 1 trang — JPEG 0.7 quality + scale nhỏ (mặc định\n * 0.3). Tối ưu cho preview grid: ~10KB/thumb thay vì ~500KB PNG full scale.\n */\nexport async function renderPageThumbnail(\n page: PDFPageProxy,\n scale = 0.3,\n quality = 0.7,\n): Promise<{ dataURL: string; width: number; height: number }> {\n const viewport = page.getViewport({ scale });\n const width = Math.ceil(viewport.width);\n const height = Math.ceil(viewport.height);\n\n const canvas = document.createElement('canvas');\n canvas.width = width;\n canvas.height = height;\n const ctx = canvas.getContext('2d');\n if (!ctx) throw new Error('Không lấy được 2D context của canvas.');\n // Nền trắng vì JPEG không support alpha.\n ctx.fillStyle = '#ffffff';\n ctx.fillRect(0, 0, width, height);\n await page.render({ canvasContext: ctx, viewport, canvas }).promise;\n const dataURL = canvas.toDataURL('image/jpeg', quality);\n return { dataURL, width, height };\n}\n\n/**\n * Render thumbnails cho tất cả trang với concurrency. Callback `onEach` được\n * gọi sau mỗi trang xong (theo thứ tự completion, không phải pageNumber) để\n * UI có thể progressive update. Tôn trọng `signal` để cancel sớm.\n */\nexport async function renderAllThumbnails(\n doc: PDFDocumentProxy,\n onEach: (pageNumber: number, dataURL: string, width: number, height: number) => void,\n options: { scale?: number; quality?: number; concurrency?: number; signal?: AbortSignal } = {},\n): Promise<void> {\n const total = doc.numPages;\n const scale = options.scale ?? 0.3;\n const quality = options.quality ?? 0.7;\n const concurrency = Math.max(1, options.concurrency ?? 3);\n const signal = options.signal;\n let next = 1;\n\n async function worker() {\n while (true) {\n if (signal?.aborted) return;\n const pageNum = next++;\n if (pageNum > total) return;\n const page = await doc.getPage(pageNum);\n try {\n if (signal?.aborted) return;\n const { dataURL, width, height } = await renderPageThumbnail(page, scale, quality);\n if (signal?.aborted) return;\n onEach(pageNum, dataURL, width, height);\n } finally {\n page.cleanup();\n }\n }\n }\n\n await Promise.all(\n Array.from({ length: Math.min(concurrency, total) }, () => worker()),\n );\n}\n","'use client';\n/* eslint-disable max-lines -- TODO Tier B: extract sub-components/hooks (issue #30) */\n\nimport { useEffect, useMemo, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport type { PDFDocumentProxy } from 'pdfjs-dist';\nimport { parsePageRange } from './parseRange';\nimport { renderAllThumbnails } from './rasterize';\n\ninterface Props {\n doc: PDFDocumentProxy;\n fileName: string;\n onConfirm: (pages: number[]) => void;\n onCancel: () => void;\n}\n\ninterface ThumbInfo {\n dataURL: string;\n width: number;\n height: number;\n}\n\n/**\n * Set<number> → chuỗi range compact dạng \"1-3,5,7-9\".\n * Dùng cho hiển thị + sync ngược về text input khi user click thumbnails.\n */\nfunction serializeSelection(pages: number[]): string {\n if (pages.length === 0) return '';\n const sorted = [...pages].sort((a, b) => a - b);\n const groups: string[] = [];\n let start = sorted[0];\n let prev = start;\n for (let i = 1; i < sorted.length; i++) {\n const n = sorted[i];\n if (n === prev + 1) {\n prev = n;\n } else {\n groups.push(start === prev ? `${start}` : `${start}-${prev}`);\n start = n;\n prev = n;\n }\n }\n groups.push(start === prev ? `${start}` : `${start}-${prev}`);\n return groups.join(',');\n}\n\n/**\n * Modal chọn trang PDF với thumbnail grid.\n *\n * Hai chiều sync:\n * - Gõ text input → parse → update selectedSet → highlight thumbnails.\n * - Click thumbnail → toggle pageNum trong selectedSet → re-serialize text.\n *\n * Source of truth: `selectedSet`. Text input là derived view (user-editable).\n * Khi user đang gõ (focus) → giữ raw `inputValue`, không overwrite. Chỉ\n * re-derive text khi click thumbnail HOẶC input mất focus với value valid.\n */\nexport function PageRangeDialog({ doc, fileName, onConfirm, onCancel }: Props) {\n const totalPages = doc.numPages;\n const defaultPages = useMemo(\n () => Array.from({ length: totalPages }, (_, i) => i + 1),\n [totalPages],\n );\n\n const [selectedSet, setSelectedSet] = useState<Set<number>>(\n () => new Set(defaultPages),\n );\n const [inputValue, setInputValue] = useState(serializeSelection(defaultPages));\n const [inputError, setInputError] = useState<string | null>(null);\n const [thumbs, setThumbs] = useState<Record<number, ThumbInfo>>({});\n const [thumbProgress, setThumbProgress] = useState(0);\n const inputRef = useRef<HTMLInputElement | null>(null);\n\n // ---- Render thumbnails khi mount ----\n useEffect(() => {\n const ctrl = new AbortController();\n void renderAllThumbnails(\n doc,\n (pageNum, dataURL, width, height) => {\n setThumbs((prev) => ({ ...prev, [pageNum]: { dataURL, width, height } }));\n setThumbProgress((prev) => prev + 1);\n },\n { scale: 0.3, quality: 0.7, concurrency: 3, signal: ctrl.signal },\n ).catch((err) => {\n if (ctrl.signal.aborted) return;\n console.warn('[PageRangeDialog] render thumbnails lỗi:', err);\n });\n return () => ctrl.abort();\n }, [doc]);\n\n // ---- Esc đóng dialog ----\n useEffect(() => {\n const onKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n e.preventDefault();\n e.stopPropagation();\n onCancel();\n }\n };\n window.addEventListener('keydown', onKey, { capture: true });\n return () => window.removeEventListener('keydown', onKey, { capture: true });\n }, [onCancel]);\n\n // ---- Text input handlers ----\n const handleInputChange = (next: string) => {\n setInputValue(next);\n try {\n const pages = parsePageRange(next, totalPages);\n setInputError(null);\n setSelectedSet(new Set(pages));\n } catch (e) {\n setInputError((e as Error).message);\n }\n };\n\n // ---- Thumbnail click handler ----\n const toggleThumb = (pageNum: number) => {\n setSelectedSet((prev) => {\n const next = new Set(prev);\n if (next.has(pageNum)) next.delete(pageNum);\n else next.add(pageNum);\n const serialized = serializeSelection([...next]);\n setInputValue(serialized);\n setInputError(null);\n return next;\n });\n };\n\n // ---- Quick select helpers ----\n const selectAll = () => {\n setSelectedSet(new Set(defaultPages));\n setInputValue(serializeSelection(defaultPages));\n setInputError(null);\n };\n\n const clearAll = () => {\n setSelectedSet(new Set());\n setInputValue('');\n setInputError(null);\n };\n\n const canSubmit = inputError === null && selectedSet.size > 0;\n const sortedSelected = useMemo(\n () => [...selectedSet].sort((a, b) => a - b),\n [selectedSet],\n );\n\n const handleSubmit = () => {\n if (!canSubmit) return;\n onConfirm(sortedSelected);\n };\n\n return createPortal(\n <div\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"pdf-range-title\"\n style={{\n position: 'fixed',\n inset: 0,\n background: 'rgba(0,0,0,0.55)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n zIndex: 10000,\n }}\n onClick={(e) => {\n if (e.target === e.currentTarget) onCancel();\n }}\n >\n <div\n style={{\n background: 'var(--popup-bg-color, #fff)',\n color: 'var(--text-primary-color, #1b1b1f)',\n borderRadius: 12,\n padding: '20px 22px',\n width: 'min(880px, 92vw)',\n maxHeight: '88vh',\n boxShadow: '0 12px 40px rgba(0,0,0,0.3)',\n fontFamily: 'inherit',\n display: 'flex',\n flexDirection: 'column',\n gap: 12,\n }}\n onClick={(e) => e.stopPropagation()}\n >\n <div>\n <h2\n id=\"pdf-range-title\"\n style={{ margin: 0, fontSize: 16, fontWeight: 600, lineHeight: 1.3 }}\n >\n Chèn PDF\n </h2>\n <p style={{ margin: '4px 0 0', fontSize: 12, opacity: 0.7 }}>\n {fileName} — {totalPages} trang\n {thumbProgress < totalPages && (\n <> · đang tải preview {thumbProgress}/{totalPages}…</>\n )}\n </p>\n </div>\n\n <div style={{ display: 'flex', alignItems: 'flex-start', gap: 10 }}>\n <div style={{ flex: 1 }}>\n <label\n style={{ display: 'block', fontSize: 12, marginBottom: 4, opacity: 0.75 }}\n >\n Trang cần chèn (vd: 1,3,5-10) — hoặc click thumbnail bên dưới\n </label>\n <input\n ref={inputRef}\n type=\"text\"\n value={inputValue}\n onChange={(e) => handleInputChange(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n handleSubmit();\n }\n }}\n style={{\n width: '100%',\n boxSizing: 'border-box',\n padding: '8px 10px',\n fontSize: 14,\n borderRadius: 6,\n border: `1px solid ${inputError ? '#dc2626' : 'rgba(0,0,0,0.2)'}`,\n outline: 'none',\n background: 'var(--input-bg-color, #fff)',\n color: 'inherit',\n fontFamily: 'ui-monospace, SFMono-Regular, Menlo, monospace',\n }}\n />\n </div>\n <div style={{ display: 'flex', gap: 6, paddingTop: 18 }}>\n <button\n type=\"button\"\n onClick={selectAll}\n style={quickBtnStyle}\n title=\"Chọn tất cả trang\"\n >\n Tất cả\n </button>\n <button\n type=\"button\"\n onClick={clearAll}\n style={quickBtnStyle}\n title=\"Bỏ chọn tất cả\"\n >\n Bỏ hết\n </button>\n </div>\n </div>\n\n <div style={{ minHeight: 18, fontSize: 12 }} data-testid=\"pdf-range-status\">\n {inputError ? (\n <span style={{ color: '#dc2626' }}>{inputError}</span>\n ) : (\n <span style={{ opacity: 0.75 }}>\n Đã chọn <strong>{selectedSet.size}</strong> / {totalPages} trang\n </span>\n )}\n </div>\n\n <div\n style={{\n flex: 1,\n minHeight: 240,\n maxHeight: '60vh',\n overflow: 'auto',\n padding: 8,\n background: 'rgba(0,0,0,0.04)',\n borderRadius: 8,\n display: 'grid',\n gridTemplateColumns: 'repeat(auto-fill, minmax(120px, 1fr))',\n gap: 10,\n alignContent: 'start',\n }}\n >\n {Array.from({ length: totalPages }, (_, i) => i + 1).map((pageNum) => {\n const thumb = thumbs[pageNum];\n const selected = selectedSet.has(pageNum);\n return (\n <ThumbnailItem\n key={pageNum}\n pageNum={pageNum}\n thumb={thumb}\n selected={selected}\n onToggle={() => toggleThumb(pageNum)}\n />\n );\n })}\n </div>\n\n <div\n style={{\n display: 'flex',\n justifyContent: 'flex-end',\n gap: 8,\n paddingTop: 4,\n }}\n >\n <button\n type=\"button\"\n onClick={onCancel}\n style={{\n padding: '8px 14px',\n fontSize: 13,\n borderRadius: 6,\n border: '1px solid rgba(0,0,0,0.15)',\n background: 'transparent',\n color: 'inherit',\n cursor: 'pointer',\n }}\n >\n Huỷ\n </button>\n <button\n type=\"button\"\n onClick={handleSubmit}\n disabled={!canSubmit}\n style={{\n padding: '8px 16px',\n fontSize: 13,\n borderRadius: 6,\n border: 'none',\n background: canSubmit ? '#4f46e5' : 'rgba(0,0,0,0.15)',\n color: '#fff',\n cursor: canSubmit ? 'pointer' : 'not-allowed',\n fontWeight: 500,\n }}\n >\n Chèn {selectedSet.size > 0 ? `${selectedSet.size} trang` : ''}\n </button>\n </div>\n </div>\n </div>,\n document.body,\n );\n}\n\nconst quickBtnStyle: React.CSSProperties = {\n padding: '7px 10px',\n fontSize: 12,\n borderRadius: 6,\n border: '1px solid rgba(0,0,0,0.15)',\n background: 'transparent',\n color: 'inherit',\n cursor: 'pointer',\n whiteSpace: 'nowrap',\n};\n\ninterface ThumbProps {\n pageNum: number;\n thumb: ThumbInfo | undefined;\n selected: boolean;\n onToggle: () => void;\n}\n\nfunction ThumbnailItem({ pageNum, thumb, selected, onToggle }: ThumbProps) {\n const aspect = thumb ? thumb.width / thumb.height : 0.77; // A4 portrait default\n return (\n <button\n type=\"button\"\n onClick={onToggle}\n aria-pressed={selected}\n aria-label={`Trang ${pageNum}${selected ? ' (đã chọn)' : ''}`}\n title={`Trang ${pageNum}`}\n style={{\n position: 'relative',\n padding: 0,\n background: '#fff',\n border: `2px solid ${selected ? '#4f46e5' : 'rgba(0,0,0,0.12)'}`,\n borderRadius: 6,\n overflow: 'hidden',\n cursor: 'pointer',\n boxShadow: selected ? '0 0 0 3px rgba(79,70,229,0.18)' : 'none',\n transition: 'border-color 80ms ease, box-shadow 80ms ease',\n }}\n >\n <div\n style={{\n width: '100%',\n aspectRatio: aspect.toString(),\n background: '#f5f5f5',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n {thumb ? (\n <img\n src={thumb.dataURL}\n alt=\"\"\n style={{ width: '100%', height: '100%', display: 'block', objectFit: 'contain' }}\n draggable={false}\n />\n ) : (\n <div style={{ fontSize: 11, opacity: 0.5 }}>…</div>\n )}\n </div>\n <div\n style={{\n position: 'absolute',\n bottom: 4,\n left: 4,\n fontSize: 10,\n fontWeight: 600,\n padding: '2px 6px',\n borderRadius: 4,\n background: selected ? '#4f46e5' : 'rgba(0,0,0,0.6)',\n color: '#fff',\n }}\n >\n {pageNum}\n </div>\n {selected && (\n <div\n aria-hidden=\"true\"\n style={{\n position: 'absolute',\n top: 4,\n right: 4,\n width: 18,\n height: 18,\n borderRadius: '50%',\n background: '#4f46e5',\n color: '#fff',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: 11,\n fontWeight: 700,\n boxShadow: '0 1px 3px rgba(0,0,0,0.3)',\n }}\n >\n ✓\n </div>\n )}\n </button>\n );\n}\n","import { useCallback, useRef } from 'react';\nimport { findStampForCustomData } from './registry';\nimport type { StampType } from './types';\n\nconst DOUBLE_CLICK_MS = 400;\n\ninterface Opts {\n enabled: boolean;\n stamps: ReadonlyArray<StampType>;\n onOpen: (\n kind: string,\n editingElement: { id: string; customData: unknown },\n ) => void;\n}\n\n/**\n * Trả về handler cho Excalidraw `onPointerDown`. Phát hiện double-click vào\n * image element thuộc một stamp đã đăng ký → gọi `onOpen(kind, element)`.\n */\nexport function useStampDoubleClick({ enabled, stamps, onOpen }: Opts) {\n const lastClickRef = useRef<{ time: number; elementId: string | null }>({\n time: 0,\n elementId: null,\n });\n\n return useCallback(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (_activeTool: any, pointerDownState: any) => {\n if (!enabled) return;\n const hitElement = pointerDownState?.hit?.element;\n if (!hitElement || hitElement.type !== 'image') return;\n const stamp = findStampForCustomData(hitElement.customData, stamps);\n if (!stamp) return;\n const now = Date.now();\n const isDouble =\n lastClickRef.current.elementId === hitElement.id &&\n now - lastClickRef.current.time < DOUBLE_CLICK_MS;\n lastClickRef.current = { time: now, elementId: hitElement.id };\n if (!isDouble) return;\n onOpen(stamp.kind, {\n id: hitElement.id,\n customData: hitElement.customData,\n });\n },\n [enabled, stamps, onOpen],\n );\n}\n","import { useEffect, useMemo } from 'react';\nimport type { StampType } from './types';\n\nconst ALLOWED_KEYS = new Set([\n 'Tab', 'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight',\n 'Shift', 'Control', 'Alt', 'Meta', 'CapsLock',\n 'Home', 'End', 'PageUp', 'PageDown',\n]);\n\nfunction isEditable(el: EventTarget | null): boolean {\n if (!(el instanceof HTMLElement)) return false;\n if (el.isContentEditable) return true;\n const tag = el.tagName;\n return tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT';\n}\n\ninterface Opts {\n /** Active stamp kind. Null = no blocker. */\n activeStamp: string | null;\n /** Stamps đăng ký để allow shortcut keys của chúng đi qua. */\n stamps: ReadonlyArray<StampType>;\n}\n\n/**\n * Khi 1 stamp panel đang mở, block hoàn toàn các phím tắt Excalidraw\n * (1-9, V, R, D...) bằng cách prevent + stop tại capture phase. Cho phép qua:\n * Tab/Arrow/Modifier, Escape, và phím tắt đã đăng ký bởi stamps (V/G/L/D...).\n */\nexport function useStampShortcutBlocker({ activeStamp, stamps }: Opts) {\n const shortcutKeys = useMemo(\n () => new Set(stamps.map((s) => s.shortcutKey.toLowerCase())),\n [stamps],\n );\n\n useEffect(() => {\n if (!activeStamp) return;\n\n const blocker = (e: KeyboardEvent) => {\n if (isEditable(e.target)) return;\n if (e.ctrlKey || e.metaKey) return;\n if (ALLOWED_KEYS.has(e.key)) return;\n if (e.key === 'Escape') return;\n if (shortcutKeys.has(e.key.toLowerCase())) return;\n e.preventDefault();\n e.stopPropagation();\n };\n window.addEventListener('keydown', blocker, { capture: true });\n return () => window.removeEventListener('keydown', blocker, { capture: true });\n }, [activeStamp, shortcutKeys]);\n}\n","import { useEffect, type RefObject } from 'react';\nimport type { StampHostHandle } from './types';\n\ninterface Opts {\n /** Active stamp. Null = no listener. */\n activeStamp: string | null;\n /** Ref tới Host imperative API (tryInsert / hasContent). */\n hostRef: RefObject<StampHostHandle | null>;\n /** Callback đóng panel. */\n onClose: () => void;\n}\n\n/**\n * Khi 1 stamp panel mở, lắng nghe pointer/mouse-down toàn document. Nếu\n * điểm click không nằm trong vùng `[data-stamp-area=\"true\"]`, gọi\n * `hostRef.tryInsert()` để auto-commit (nếu có nội dung) rồi `onClose()`.\n */\nexport function useStampClickOutside({ activeStamp, hostRef, onClose }: Opts) {\n useEffect(() => {\n if (!activeStamp) return;\n let lastFire = 0;\n const handler = (e: MouseEvent) => {\n const target = e.target as HTMLElement | null;\n if (!target) return;\n if (target.closest('[data-stamp-area=\"true\"]')) return;\n const now = Date.now();\n if (now - lastFire < 50) return;\n lastFire = now;\n hostRef.current?.tryInsert();\n onClose();\n };\n window.addEventListener('pointerdown', handler, { capture: true });\n window.addEventListener('mousedown', handler, { capture: true });\n return () => {\n window.removeEventListener('pointerdown', handler, { capture: true });\n window.removeEventListener('mousedown', handler, { capture: true });\n };\n }, [activeStamp, hostRef, onClose]);\n}\n","import { type MutableRefObject, useCallback, useRef, useState } from 'react';\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype ExApi = any;\n\nexport interface UseExcalidrawApiOptions {\n onApi?: (api: ExApi) => void;\n}\n\nexport interface UseExcalidrawApiResult {\n api: ExApi | null;\n apiRef: MutableRefObject<ExApi | null>;\n isDark: boolean;\n isDarkRef: MutableRefObject<boolean>;\n /** Gắn vào Excalidraw prop `excalidrawAPI`. Defer setState qua microtask\n * để tránh React 19 \"update from inside an update function\" warning. */\n setApiFromExcalidraw: (api: ExApi) => void;\n /** Gọi từ onChange. Bail-out qua ref + defer setState. */\n syncThemeFromAppState: (appState: { theme?: string } | undefined) => void;\n}\n\nexport function useExcalidrawApi(\n opts: UseExcalidrawApiOptions = {},\n): UseExcalidrawApiResult {\n const { onApi } = opts;\n const [api, setApi] = useState<ExApi | null>(null);\n const apiRef = useRef<ExApi | null>(null);\n const [isDark, setIsDark] = useState(false);\n const isDarkRef = useRef(false);\n const onApiRef = useRef(onApi);\n onApiRef.current = onApi;\n\n const setApiFromExcalidraw = useCallback((a: ExApi) => {\n if (apiRef.current === a) return;\n apiRef.current = a;\n queueMicrotask(() => {\n setApi(a);\n onApiRef.current?.(a);\n });\n }, []);\n\n const syncThemeFromAppState = useCallback(\n (appState: { theme?: string } | undefined) => {\n const next = appState?.theme === 'dark';\n if (isDarkRef.current !== next) {\n isDarkRef.current = next;\n queueMicrotask(() => setIsDark(next));\n }\n },\n [],\n );\n\n return { api, apiRef, isDark, isDarkRef, setApiFromExcalidraw, syncThemeFromAppState };\n}\n","import { useCallback, useMemo, useState } from 'react';\nimport type { StampType } from '../stamps/shared/registry';\n\nexport interface EditingElement {\n id: string;\n customData: unknown;\n}\n\nexport interface UseActiveStampOptions {\n readOnly: boolean;\n stamps: ReadonlyArray<StampType>;\n}\n\nexport interface UseActiveStampResult {\n activeStamp: string | null;\n editingElement: EditingElement | null;\n stampByKind: Map<string, StampType>;\n activeStampDef: StampType | null;\n HostComponent: StampType['Host'] | null;\n openStamp: (kind: string, element?: EditingElement | null) => void;\n closeStamp: () => void;\n toggleStampByKind: (kind: string) => void;\n}\n\nexport function useActiveStamp(opts: UseActiveStampOptions): UseActiveStampResult {\n const { readOnly, stamps } = opts;\n const [activeStamp, setActiveStamp] = useState<string | null>(null);\n const [editingElement, setEditingElement] = useState<EditingElement | null>(null);\n\n const stampByKind = useMemo(() => {\n const m = new Map<string, StampType>();\n for (const s of stamps) m.set(s.kind, s);\n return m;\n }, [stamps]);\n\n const activeStampDef = activeStamp ? stampByKind.get(activeStamp) ?? null : null;\n const HostComponent = activeStampDef?.Host ?? null;\n\n const openStamp = useCallback(\n (kind: string, element: EditingElement | null = null) => {\n if (readOnly) return;\n if (!stampByKind.has(kind)) return;\n setEditingElement(element);\n setActiveStamp(kind);\n },\n [readOnly, stampByKind],\n );\n\n const closeStamp = useCallback(() => {\n setActiveStamp(null);\n setEditingElement(null);\n }, []);\n\n const toggleStampByKind = useCallback(\n (kind: string) => {\n setActiveStamp((cur) => {\n if (cur === kind) {\n setEditingElement(null);\n return null;\n }\n if (readOnly) return cur;\n if (!stampByKind.has(kind)) return cur;\n setEditingElement(null);\n return kind;\n });\n },\n [readOnly, stampByKind],\n );\n\n return {\n activeStamp,\n editingElement,\n stampByKind,\n activeStampDef,\n HostComponent,\n openStamp,\n closeStamp,\n toggleStampByKind,\n };\n}\n","import type { ExcalidrawElement } from '../types';\nimport { closePdfDocument, loadPdfDocument, rasterizePdf, type RasterizedPage } from './rasterize';\n\n// Excalidraw imperative API — không có public type chính xác.\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype ExApi = any;\n\n/** Khoảng cách dọc giữa các trang PDF khi xếp dọc, ở scene units. */\nconst PAGE_GAP = 24;\n\n/** Scale render mặc định (HiDPI sharp). */\nconst DEFAULT_SCALE = 2;\n\nexport interface InsertRasterizedPagesOptions {\n /** Scale dùng khi rasterize (để chia pixel → scene units). */\n scale: number;\n /** Toạ độ scene gốc cho page đầu tiên. Bỏ qua → giữa viewport. */\n origin?: { x: number; y: number };\n}\n\nexport interface InsertRasterizedPagesResult {\n insertedElementIds: string[];\n fileIds: string[];\n}\n\n/**\n * Chèn array `RasterizedPage` đã có sẵn vào scene. Tách ra để Whiteboard\n * có thể: load doc → hỏi user range → rasterize → insert mà không phải gọi\n * insertPdfPages (load lại từ ArrayBuffer 2 lần).\n */\nexport function insertRasterizedPagesIntoScene(\n api: ExApi,\n rendered: RasterizedPage[],\n options: InsertRasterizedPagesOptions,\n): InsertRasterizedPagesResult {\n if (!api) throw new Error('Excalidraw API chưa sẵn sàng.');\n if (rendered.length === 0) return { insertedElementIds: [], fileIds: [] };\n\n const { scale } = options;\n const filesPayload = rendered.map((p) => ({\n id: generateFileId(),\n dataURL: p.dataURL,\n mimeType: p.mimeType,\n created: Date.now(),\n }));\n api.addFiles(filesPayload);\n\n const origin = options.origin ?? getViewportCenter(api);\n const sceneSizes = rendered.map((p) => pixelsToSceneSize(p.width, p.height, scale));\n const maxSceneWidth = Math.max(...sceneSizes.map((s) => s.width));\n const baseX = origin.x - maxSceneWidth / 2;\n let cursorY = origin.y - sceneSizes[0].height / 2;\n\n const newElements = rendered.map((_, i) => {\n const { width, height } = sceneSizes[i];\n const x = baseX + (maxSceneWidth - width) / 2;\n const y = cursorY;\n cursorY = y + height + PAGE_GAP;\n return buildPdfImageElement(filesPayload[i].id, x, y, width, height);\n });\n\n const existing = api.getSceneElements() as readonly ExcalidrawElement[];\n api.updateScene({\n elements: [...existing, ...newElements],\n appState: { selectedElementIds: {}, croppingElementId: null },\n });\n\n return {\n insertedElementIds: newElements.map((e) => e.id),\n fileIds: filesPayload.map((f) => f.id),\n };\n}\n\n/**\n * Excalidraw lưu width/height theo \"scene units\". File PDF rasterize ở scale 2\n * → pixel = 2 × scene unit. Chia lại để stamp hiển thị đúng kích thước\n * gốc của trang PDF (giấy A4 ≈ 595×842 scene units ở 72 DPI).\n */\nfunction pixelsToSceneSize(pxWidth: number, pxHeight: number, scale: number) {\n return { width: pxWidth / scale, height: pxHeight / scale };\n}\n\nexport interface InsertPdfPagesOptions {\n /** Trang cần chèn (1-based). Bỏ qua → chèn tất cả. */\n pages?: number[];\n /** Scale rasterize. Mặc định 2. */\n scale?: number;\n /** Toạ độ scene gốc cho page đầu tiên. Bỏ qua → giữa viewport. */\n origin?: { x: number; y: number };\n /** Progress callback. */\n onProgress?: (done: number, total: number) => void;\n /** AbortSignal. */\n signal?: AbortSignal;\n}\n\nexport interface InsertPdfPagesResult {\n insertedElementIds: string[];\n pages: RasterizedPage[];\n}\n\n/**\n * Tạo image element cho 1 trang đã rasterize. Trả về object đủ field cho\n * Excalidraw `updateScene`. Lấy `fileId` từ caller để có thể batch addFiles\n * trước khi update elements.\n */\nfunction buildPdfImageElement(\n fileId: string,\n x: number,\n y: number,\n width: number,\n height: number,\n) {\n return {\n type: 'image' as const,\n id: 'pdf_' + Date.now() + '_' + Math.random().toString(36).slice(2, 8),\n x,\n y,\n width,\n height,\n fileId,\n angle: 0,\n strokeColor: 'transparent',\n backgroundColor: 'transparent',\n fillStyle: 'solid',\n strokeWidth: 1,\n strokeStyle: 'solid',\n roughness: 0,\n opacity: 100,\n groupIds: [],\n roundness: null,\n seed: Math.floor(Math.random() * 1e9),\n versionNonce: 0,\n version: 1,\n isDeleted: false,\n boundElements: null,\n updated: Date.now(),\n link: null,\n locked: false,\n status: 'saved',\n scale: [1, 1],\n };\n}\n\nfunction generateFileId(): string {\n return 'pdf_' + Date.now() + '_' + Math.random().toString(36).slice(2, 10);\n}\n\nfunction getViewportCenter(api: ExApi): { x: number; y: number } {\n const appState = api?.getAppState?.() ?? {\n scrollX: 0,\n scrollY: 0,\n width: 800,\n height: 600,\n zoom: { value: 1 },\n };\n const zoom = appState.zoom?.value ?? 1;\n return {\n x: appState.scrollX + (appState.width ?? 800) / 2 / zoom,\n y: appState.scrollY + (appState.height ?? 600) / 2 / zoom,\n };\n}\n\n/**\n * High-level: rasterize PDF + insert thành nhiều image element xếp dọc.\n *\n * Flow:\n * 1. loadPdfDocument(source) → PDFDocumentProxy\n * 2. rasterizePdf(doc, {pages, scale}) → RasterizedPage[]\n * 3. Tạo fileId cho từng page, gọi api.addFiles batch.\n * 4. Tính position: page 1 trung tâm viewport (hoặc origin), các page sau\n * xếp dưới, cách PAGE_GAP.\n * 5. api.updateScene({ elements: [...cũ, ...mới] })\n *\n * Không serialize PDF bytes — sau insert, các page là image element thuần,\n * không thể re-edit qua double-click (theo design quyết định).\n */\nexport async function insertPdfPages(\n api: ExApi,\n source: File | Blob | ArrayBuffer,\n options: InsertPdfPagesOptions = {},\n): Promise<InsertPdfPagesResult> {\n if (!api) throw new Error('Excalidraw API chưa sẵn sàng.');\n\n const scale = options.scale ?? DEFAULT_SCALE;\n const doc = await loadPdfDocument(source);\n let rendered: RasterizedPage[];\n try {\n rendered = await rasterizePdf(doc, {\n pages: options.pages,\n scale,\n onProgress: options.onProgress,\n signal: options.signal,\n });\n } finally {\n void closePdfDocument(doc);\n }\n\n const { insertedElementIds } = insertRasterizedPagesIntoScene(api, rendered, {\n scale,\n origin: options.origin,\n });\n return { insertedElementIds, pages: rendered };\n}\n","import { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';\nimport type { PDFDocumentProxy } from 'pdfjs-dist';\nimport {\n loadPdfDocument,\n closePdfDocument,\n rasterizePdf,\n} from '../pdf/rasterize';\nimport { insertRasterizedPagesIntoScene } from '../pdf/insertPdfPages';\n\n// Excalidraw imperative API — không có public type chính xác.\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype ExApi = any;\n\nexport interface PdfPendingState {\n doc: PDFDocumentProxy;\n fileName: string;\n totalPages: number;\n}\n\nexport interface UsePdfImporterOptions {\n readOnly: boolean;\n api: ExApi | null;\n}\n\nexport interface UsePdfImporterResult {\n pdfPending: PdfPendingState | null;\n pdfBusy: boolean;\n handlePdfPick: (file: File) => Promise<void>;\n handlePdfConfirm: (pages: number[]) => Promise<void>;\n handlePdfCancel: () => void;\n}\n\nexport function usePdfImporter(opts: UsePdfImporterOptions): UsePdfImporterResult {\n const { readOnly, api } = opts;\n const [pdfPending, setPdfPending] = useState<PdfPendingState | null>(null);\n const [pdfBusy, setPdfBusy] = useState(false);\n\n const handlePdfPick = useCallback(\n async (file: File) => {\n if (readOnly || pdfBusy) return;\n setPdfBusy(true);\n try {\n const doc = await loadPdfDocument(file);\n setPdfPending({ doc, fileName: file.name, totalPages: doc.numPages });\n } catch (err) {\n console.warn('[whiteboard] Đọc PDF thất bại:', err);\n window.alert('Không đọc được PDF. File có thể đã hỏng hoặc bị mật khẩu bảo vệ.');\n } finally {\n setPdfBusy(false);\n }\n },\n [readOnly, pdfBusy],\n );\n\n const handlePdfPickRef = useRef(handlePdfPick);\n useLayoutEffect(() => {\n handlePdfPickRef.current = handlePdfPick;\n });\n\n const handlePdfConfirm = useCallback(\n async (pages: number[]) => {\n if (!pdfPending || !api) return;\n const { doc } = pdfPending;\n setPdfPending(null);\n setPdfBusy(true);\n const scale = 2;\n try {\n const rendered = await rasterizePdf(doc, { pages, scale });\n await closePdfDocument(doc);\n insertRasterizedPagesIntoScene(api, rendered, { scale });\n } catch (err) {\n console.warn('[whiteboard] Chèn PDF thất bại:', err);\n window.alert('Chèn PDF thất bại. Xem console để biết chi tiết.');\n } finally {\n setPdfBusy(false);\n }\n },\n [pdfPending, api],\n );\n\n const handlePdfCancel = useCallback(() => {\n if (pdfPending) {\n void closePdfDocument(pdfPending.doc);\n }\n setPdfPending(null);\n }, [pdfPending]);\n\n // Drop handler: catch application/pdf trước Excalidraw (nó reject PDF).\n useEffect(() => {\n if (readOnly) return;\n const root = document.querySelector<HTMLElement>('.excalidraw');\n if (!root) return;\n\n const onDragOver = (e: DragEvent) => {\n const items = e.dataTransfer?.items;\n if (!items) return;\n for (let i = 0; i < items.length; i++) {\n if (items[i].kind === 'file' && items[i].type === 'application/pdf') {\n e.preventDefault();\n e.stopPropagation();\n if (e.dataTransfer) e.dataTransfer.dropEffect = 'copy';\n return;\n }\n }\n };\n\n const onDrop = (e: DragEvent) => {\n const files = e.dataTransfer?.files;\n if (!files || files.length === 0) return;\n const pdf = Array.from(files).find((f) => f.type === 'application/pdf');\n if (!pdf) return;\n e.preventDefault();\n e.stopPropagation();\n void handlePdfPickRef.current(pdf);\n };\n\n root.addEventListener('dragover', onDragOver, { capture: true });\n root.addEventListener('drop', onDrop, { capture: true });\n return () => {\n root.removeEventListener('dragover', onDragOver, { capture: true });\n root.removeEventListener('drop', onDrop, { capture: true });\n };\n }, [readOnly, api]);\n\n return { pdfPending, pdfBusy, handlePdfPick, handlePdfConfirm, handlePdfCancel };\n}\n","import type { AppState } from '@excalidraw/excalidraw/types';\nimport type { SyncableAppState } from './types';\n\nexport function pickSyncableAppState(s: AppState): SyncableAppState {\n return {\n viewBackgroundColor: s.viewBackgroundColor,\n zoom: s.zoom,\n scrollX: s.scrollX,\n scrollY: s.scrollY,\n gridSize: s.gridSize ?? null,\n theme: s.theme,\n };\n}\n","// Regenerate Excalidraw BinaryFiles for stamp elements after page reload.\n//\n// Why this exists: VideoRoom only persists the Excalidraw scene (elements +\n// appState) to sessionStorage; binary files (the SVG dataURLs for stamp\n// images) are NOT persisted. After reload, elements still reference a fileId\n// via customData, but the file payload is missing — Excalidraw renders the\n// image area as an empty placeholder.\n//\n// Strategy: tra registry để tìm StampType khớp customData.kind. Nếu stamp có\n// `restoreFileFromCustomData`, gọi trực tiếp với full element (stamp tự lấy\n// fileId + render). Ngược lại, fallback sang `renderSvgFromCustomData` (path\n// cũ: filter type=image + fileId + kiểm tra existing files).\n//\n// Excalidraw key trên fileId chứ không phải hash dataURL nên nếu kết quả\n// render có sai khác nhỏ (vd thứ tự element) cũng không ảnh hưởng.\n//\n// Theme: stamps được render với LIGHT palette (nét đậm). Excalidraw áp dụng\n// `filter: invert(...)` lên canvas trong dark mode → nét tự đảo sáng. KHÔNG\n// cần force regenerate khi user toggle theme.\n\nimport { DEFAULT_STAMPS, findStampForCustomData } from './registry';\nimport type { StampType } from './types';\n\ninterface ElementLike {\n id: string;\n type?: string;\n fileId?: string | null;\n customData?: unknown;\n}\n\ninterface AddFileRecord {\n id: string;\n dataURL: string;\n mimeType: string;\n created: number;\n}\n\nfunction svgToDataURL(svg: string): string {\n const utf8 = unescape(encodeURIComponent(svg));\n return 'data:image/svg+xml;base64,' + btoa(utf8);\n}\n\nasync function buildFileForStamp(\n fileId: string,\n customData: unknown,\n stamp: StampType,\n): Promise<AddFileRecord | null> {\n try {\n if (!stamp.matchesCustomData(customData)) return null;\n const svg = await stamp.renderSvgFromCustomData(customData);\n return { id: fileId, dataURL: svgToDataURL(svg), mimeType: 'image/svg+xml', created: Date.now() };\n } catch (err) {\n console.warn('Stamp restore failed for', fileId, '(' + stamp.kind + ')', err);\n return null;\n }\n}\n\n/**\n * Find stamp elements whose binary file is missing from Excalidraw, then\n * regenerate via registry dispatch. Idempotent: safe to call on every scene\n * update.\n *\n * Stamps that implement `restoreFileFromCustomData` are handled via the new\n * registry-driven path (stamp receives the full element and returns the file\n * record). Stamps that only implement `renderSvgFromCustomData` use the legacy\n * path (filter type=image + fileId, skip already-present files).\n *\n * @param api Excalidraw imperative API.\n * @param elements Tất cả elements trong scene.\n * @param stamps Registry. Default = DEFAULT_STAMPS.\n */\nexport async function restoreMissingStampFiles(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n api: any,\n elements: readonly ElementLike[],\n stamps: ReadonlyArray<StampType> = DEFAULT_STAMPS,\n): Promise<void> {\n if (!api) return;\n\n const filesToAdd: AddFileRecord[] = [];\n\n // --- New registry-driven path: stamp.restoreFileFromCustomData ---\n const newPathHandled = new Set<string>();\n for (const el of elements) {\n const stamp = findStampForCustomData(el.customData, stamps);\n if (!stamp?.restoreFileFromCustomData) continue;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const restored = await stamp.restoreFileFromCustomData(el as any);\n if (!restored) continue;\n newPathHandled.add(el.id);\n filesToAdd.push({\n id: restored.fileId,\n dataURL: restored.dataURL,\n mimeType: restored.mimeType,\n created: Date.now(),\n });\n }\n\n // --- Legacy path: stamp.renderSvgFromCustomData (type=image + fileId filter) ---\n const existing = (typeof api.getFiles === 'function') ? api.getFiles() : {};\n const seen = new Set<string>();\n for (const el of elements) {\n if (newPathHandled.has(el.id)) continue;\n if (el.type !== 'image') continue;\n if (!el.fileId) continue;\n if (existing && existing[el.fileId]) continue;\n if (seen.has(el.fileId)) continue;\n const stamp = findStampForCustomData(el.customData, stamps);\n if (!stamp) continue;\n seen.add(el.fileId);\n const built = await buildFileForStamp(el.fileId, el.customData, stamp);\n if (built) filesToAdd.push(built);\n }\n\n if (filesToAdd.length > 0) {\n try { api.addFiles(filesToAdd); } catch (err) { console.warn('addFiles failed:', err); }\n }\n}\n","/**\n * Hardening helpers cho persistence layer:\n *\n * - validateStorageKey: chặn ký tự lạ trong storageKey (consumer-supplied) trước khi\n * ghép vào key prefix (`whiteboard:scene:<key>`) hoặc dùng làm index trong IndexedDB.\n * - safeParseScene: parse JSON với reviver loại bỏ `__proto__/constructor/prototype`\n * để chặn prototype pollution, check max nesting depth, whitelist top-level keys.\n *\n * Các helper này không phụ thuộc DOM nên test được trong jsdom hoặc node thuần.\n */\n\nconst STORAGE_KEY_RE = /^[a-zA-Z0-9_-]{1,128}$/;\n\n/**\n * Validate storageKey từ consumer.\n *\n * Format cho phép: chữ + số + underscore + dash, 1..128 ký tự.\n * Throw nếu không hợp lệ — caller bị buộc handle hoặc crash sớm.\n */\nexport function validateStorageKey(key: unknown): string {\n if (typeof key !== 'string' || !STORAGE_KEY_RE.test(key)) {\n const sample = key === undefined ? 'undefined' : String(key).slice(0, 32);\n throw new Error(\n `[whiteboard] Invalid storageKey: must match ${STORAGE_KEY_RE} (got: ${sample})`,\n );\n }\n return key;\n}\n\nconst DANGEROUS_KEYS = new Set(['__proto__', 'constructor', 'prototype']);\n\n/**\n * Reviver dùng cho `JSON.parse`: drop bất kỳ key nào trong DANGEROUS_KEYS,\n * tránh prototype pollution khi parse dữ liệu không tin cậy từ localStorage.\n */\nfunction sanitizingReviver(_key: string, value: unknown): unknown {\n if (DANGEROUS_KEYS.has(_key)) return undefined;\n return value;\n}\n\n/** Max nesting depth cho scene tree (object/array). */\nexport const MAX_NESTED_DEPTH = 64;\n\nfunction depthExceeds(v: unknown, max: number, depth = 0): boolean {\n if (depth > max) return true;\n if (v === null || typeof v !== 'object') return false;\n const children = Array.isArray(v)\n ? v\n : Object.values(v as Record<string, unknown>);\n for (const child of children) {\n if (depthExceeds(child, max, depth + 1)) return true;\n }\n return false;\n}\n\nconst ALLOWED_TOP_LEVEL_KEYS = new Set(['version', 'elements', 'appState', 'savedAt']);\n\n/** Shape của scene đã được validate (chưa check version + element shape — caller lo). */\nexport interface ParsedScene {\n version?: unknown;\n elements: unknown[];\n appState: Record<string, unknown>;\n savedAt?: unknown;\n}\n\nfunction isPlainObject(v: unknown): v is Record<string, unknown> {\n return typeof v === 'object' && v !== null && !Array.isArray(v);\n}\n\n/**\n * Parse + sanitize raw JSON string từ localStorage.\n *\n * 1. JSON.parse với reviver strip dangerous keys.\n * 2. Reject nếu nested depth vượt MAX_NESTED_DEPTH.\n * 3. Whitelist top-level keys (drop extras).\n * 4. `elements` phải là array, mỗi item là object có `id: string` + `type: string`.\n *\n * Trả về `null` nếu bất kỳ check nào fail (caller handle như \"no data\").\n */\nexport function safeParseScene(raw: string): ParsedScene | null {\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw, sanitizingReviver);\n } catch {\n return null;\n }\n if (!isPlainObject(parsed)) return null;\n if (depthExceeds(parsed, MAX_NESTED_DEPTH)) return null;\n\n // Whitelist top-level keys.\n const safe: Record<string, unknown> = {};\n for (const k of Object.keys(parsed)) {\n if (ALLOWED_TOP_LEVEL_KEYS.has(k)) safe[k] = parsed[k];\n }\n\n if (!Array.isArray(safe.elements)) return null;\n for (const el of safe.elements as unknown[]) {\n if (!isPlainObject(el)) return null;\n if (typeof el.id !== 'string' || typeof el.type !== 'string') return null;\n }\n\n const appState = isPlainObject(safe.appState) ? safe.appState : {};\n\n return {\n version: safe.version,\n elements: safe.elements as unknown[],\n appState,\n savedAt: safe.savedAt,\n };\n}\n","import type { ExcalidrawElement, SyncableAppState } from '../../types';\nimport { safeParseScene, validateStorageKey } from './validation';\n\nconst PREFIX = 'whiteboard:scene:';\nconst SCHEMA_VERSION = 1 as const;\n\nexport interface StoredScene {\n version: typeof SCHEMA_VERSION;\n elements: readonly ExcalidrawElement[];\n appState: Partial<SyncableAppState>;\n savedAt: number;\n}\n\nfunction fullKey(key: string): string {\n return PREFIX + key;\n}\n\nexport function readScene(key: string): StoredScene | null {\n const validKey = validateStorageKey(key);\n if (typeof window === 'undefined') return null;\n const raw = window.localStorage.getItem(fullKey(validKey));\n if (!raw) return null;\n const parsed = safeParseScene(raw);\n if (!parsed) {\n console.warn('[whiteboard] scene parse/validation failed, clear:', validKey);\n try {\n window.localStorage.removeItem(fullKey(validKey));\n } catch { /* ignore */ }\n return null;\n }\n if (parsed.version !== SCHEMA_VERSION) {\n // Cố ý KHÔNG xoá entry — version mismatch có thể là dữ liệu của client\n // mới hơn (user vừa downgrade). Giữ lại để client tương ứng đọc được sau.\n console.warn(\n `[whiteboard] scene version ${parsed.version} không khớp ${SCHEMA_VERSION}, bỏ qua.`,\n );\n return null;\n }\n return {\n version: SCHEMA_VERSION,\n elements: parsed.elements as readonly ExcalidrawElement[],\n appState: parsed.appState as Partial<SyncableAppState>,\n savedAt: typeof parsed.savedAt === 'number' ? parsed.savedAt : Date.now(),\n };\n}\n\nexport function writeScene(\n key: string,\n payload: { elements: readonly ExcalidrawElement[]; appState: Partial<SyncableAppState> },\n): void {\n const validKey = validateStorageKey(key);\n if (typeof window === 'undefined') return;\n const record: StoredScene = {\n version: SCHEMA_VERSION,\n elements: payload.elements,\n appState: payload.appState,\n savedAt: Date.now(),\n };\n try {\n window.localStorage.setItem(fullKey(validKey), JSON.stringify(record));\n } catch (err) {\n console.warn('[whiteboard] scene write failed:', err);\n }\n}\n\nexport function clearScene(key: string): void {\n const validKey = validateStorageKey(key);\n if (typeof window === 'undefined') return;\n try {\n window.localStorage.removeItem(fullKey(validKey));\n } catch { /* ignore */ }\n}\n","import type { BinaryFiles } from '../../types';\nimport { validateStorageKey } from './validation';\n\nconst DB_NAME = 'whiteboard-files';\nconst DB_VERSION = 1;\nconst STORE = 'files';\n\ninterface FileRecord {\n id: string;\n storageKey: string;\n dataURL: string;\n mimeType: string;\n created: number;\n savedAt: number;\n}\n\nlet dbPromise: Promise<IDBDatabase> | null = null;\nlet idbDisabled = false;\n\nfunction openDb(): Promise<IDBDatabase> {\n if (idbDisabled) return Promise.reject(new Error('IndexedDB disabled'));\n if (dbPromise) return dbPromise;\n dbPromise = new Promise((resolve, reject) => {\n if (typeof indexedDB === 'undefined') {\n idbDisabled = true;\n reject(new Error('indexedDB undefined'));\n return;\n }\n const req = indexedDB.open(DB_NAME, DB_VERSION);\n req.onupgradeneeded = () => {\n const db = req.result;\n if (!db.objectStoreNames.contains(STORE)) {\n const store = db.createObjectStore(STORE, { keyPath: 'id' });\n store.createIndex('storageKey', 'storageKey', { unique: false });\n }\n };\n req.onsuccess = () => resolve(req.result);\n req.onerror = () => {\n idbDisabled = true;\n reject(req.error ?? new Error('IDB open failed'));\n };\n });\n return dbPromise;\n}\n\nasync function withStore<T>(\n mode: IDBTransactionMode,\n fn: (\n store: IDBObjectStore,\n setResult: (value: T) => void,\n fail: (error: unknown) => void,\n ) => void,\n fallback: T,\n): Promise<T> {\n let db: IDBDatabase;\n try {\n db = await openDb();\n } catch {\n return fallback;\n }\n return new Promise<T>((resolve, reject) => {\n const tx = db.transaction(STORE, mode);\n const store = tx.objectStore(STORE);\n let result = fallback;\n try {\n fn(\n store,\n (value) => {\n result = value;\n },\n reject,\n );\n } catch (err) {\n reject(err);\n return;\n }\n tx.oncomplete = () => resolve(result);\n tx.onerror = () => {\n console.warn('[whiteboard] IDB tx error:', tx.error);\n reject(tx.error ?? new Error('IDB tx error'));\n };\n tx.onabort = () => reject(tx.error ?? new Error('IDB tx aborted'));\n });\n}\n\nexport async function readFiles(storageKey: string): Promise<BinaryFiles> {\n const validKey = validateStorageKey(storageKey);\n try {\n return await withStore(\n 'readonly',\n (store, setResult, fail) => {\n const out: BinaryFiles = {};\n const req = store.index('storageKey').openCursor(IDBKeyRange.only(validKey));\n req.onsuccess = () => {\n const cursor = req.result;\n if (!cursor) {\n setResult(out);\n return;\n }\n const record = cursor.value as FileRecord;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (out as any)[record.id] = {\n dataURL: record.dataURL,\n mimeType: record.mimeType,\n created: record.created,\n };\n cursor.continue();\n };\n req.onerror = () => fail(req.error);\n },\n {},\n );\n } catch (err) {\n console.warn('[whiteboard] readFiles failed:', err);\n return {};\n }\n}\n\nexport async function writeFiles(storageKey: string, files: BinaryFiles): Promise<void> {\n const validKey = validateStorageKey(storageKey);\n const entries = Object.entries(files);\n if (entries.length === 0) return;\n try {\n await withStore<void>(\n 'readwrite',\n (store, setResult, fail) => {\n let pending = entries.length;\n const finishOne = () => {\n pending -= 1;\n if (pending === 0) setResult(undefined);\n };\n\n const now = Date.now();\n for (const [id, f] of entries) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const ff = f as any;\n const getReq = store.get(id);\n getReq.onsuccess = () => {\n if (getReq.result) {\n finishOne();\n return;\n }\n const rec: FileRecord = {\n id,\n storageKey: validKey,\n dataURL: ff.dataURL,\n mimeType: ff.mimeType,\n created: ff.created ?? now,\n savedAt: now,\n };\n const putReq = store.put(rec);\n putReq.onsuccess = finishOne;\n putReq.onerror = () => fail(putReq.error);\n };\n getReq.onerror = () => fail(getReq.error);\n };\n },\n undefined,\n );\n } catch (err) {\n console.warn('[whiteboard] writeFiles failed:', err);\n }\n}\n\nexport async function pruneFiles(\n storageKey: string,\n keepIds: ReadonlySet<string>,\n): Promise<void> {\n const validKey = validateStorageKey(storageKey);\n try {\n await withStore<void>(\n 'readwrite',\n (store, setResult, fail) => {\n const req = store.index('storageKey').openCursor(IDBKeyRange.only(validKey));\n req.onsuccess = () => {\n const cursor = req.result;\n if (!cursor) {\n setResult(undefined);\n return;\n }\n const record = cursor.value as FileRecord;\n if (keepIds.has(record.id)) {\n cursor.continue();\n return;\n }\n const deleteReq = cursor.delete();\n deleteReq.onsuccess = () => cursor.continue();\n deleteReq.onerror = () => fail(deleteReq.error);\n };\n req.onerror = () => fail(req.error);\n },\n undefined,\n );\n } catch (err) {\n console.warn('[whiteboard] pruneFiles failed:', err);\n }\n}\n\nexport async function clearAll(storageKey: string): Promise<void> {\n const validKey = validateStorageKey(storageKey);\n try {\n await withStore<void>(\n 'readwrite',\n (store, setResult, fail) => {\n const req = store.index('storageKey').openCursor(IDBKeyRange.only(validKey));\n req.onsuccess = () => {\n const cursor = req.result;\n if (!cursor) {\n setResult(undefined);\n return;\n }\n const deleteReq = cursor.delete();\n deleteReq.onsuccess = () => cursor.continue();\n deleteReq.onerror = () => fail(deleteReq.error);\n };\n req.onerror = () => fail(req.error);\n },\n undefined,\n );\n } catch (err) {\n console.warn('[whiteboard] clearAll failed:', err);\n }\n}\n","'use client';\nimport { useEffect, useMemo, useRef } from 'react';\nimport type {\n ExcalidrawElement,\n BinaryFiles,\n ExcalidrawSceneSnapshot,\n SyncableAppState,\n} from '../types';\nimport { pickSyncableAppState } from '../serialize';\nimport { isStampElement, type StampType } from '../stamps/shared/registry';\nimport { restoreMissingStampFiles } from '../stamps/shared/restoreStampFiles';\nimport { readScene, writeScene } from '../core/persistence/sceneStore';\nimport { readFiles, writeFiles, pruneFiles } from '../core/persistence/fileStore';\n\nconst SYNC_THROTTLE_MS = 200;\nconst FILE_THROTTLE_MS = 1000;\nconst PRUNE_THROTTLE_MS = 2000;\nconst RESTORE_PASS_DELAY_MS = 400;\n\nexport interface UseScenePersistOptions {\n storageKey: string | null;\n initialScene?: ExcalidrawSceneSnapshot | null;\n initialFiles?: BinaryFiles;\n readOnly: boolean;\n onSceneChange?: (snapshot: ExcalidrawSceneSnapshot) => void;\n onFilesChange?: (files: BinaryFiles, newFileIds: string[]) => void;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n api: any;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n apiRef: React.MutableRefObject<any>;\n stamps: ReadonlyArray<StampType>;\n}\n\nexport interface UseScenePersistResult {\n effectiveInitialScene: ExcalidrawSceneSnapshot | null;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n onSceneTick: (elements: readonly ExcalidrawElement[], appState: any, files: BinaryFiles) => void;\n}\n\n// Bundle toàn bộ persist orchestration cho Whiteboard:\n// - effectiveInitialScene: precedence initialScene > localStorage > blank.\n// - onSceneTick: gọi từ Excalidraw onChange (sau theme-sync + crop intercept).\n// Track new fileIds, throttle scene/file/prune writes.\n// - Mount: load initialFiles (server) + IDB raster + restoreMissingStampFiles.\n// - Unmount: flush mọi pending write trước teardown.\nexport function useScenePersist(opts: UseScenePersistOptions): UseScenePersistResult {\n const {\n storageKey,\n initialScene,\n initialFiles,\n readOnly,\n onSceneChange,\n onFilesChange,\n api,\n apiRef,\n stamps,\n } = opts;\n\n const persistEnabled = typeof storageKey === 'string' && storageKey.length > 0;\n\n const knownFileIdsRef = useRef<Set<string>>(new Set());\n const lastSceneHashRef = useRef<string>('');\n const sceneThrottleRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const fileThrottleRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const pruneThrottleRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const latestSceneRef = useRef<{\n elements: readonly ExcalidrawElement[];\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n appState: any;\n } | null>(null);\n const pendingFilesRef = useRef<BinaryFiles>({});\n // Cached hashElementsVersion để flushScene chạy sync trong unmount cleanup\n // (cleanup không thể await dynamic import).\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const hashElementsVersionRef = useRef<((elements: readonly ExcalidrawElement[]) => any) | null>(null);\n\n const stampsRef = useRef(stamps);\n stampsRef.current = stamps;\n const persistKeyRef = useRef(storageKey);\n persistKeyRef.current = storageKey;\n const onSceneChangeRef = useRef(onSceneChange);\n onSceneChangeRef.current = onSceneChange;\n const onFilesChangeRef = useRef(onFilesChange);\n onFilesChangeRef.current = onFilesChange;\n const persistEnabledRef = useRef(persistEnabled);\n persistEnabledRef.current = persistEnabled;\n\n const persistedInitial = useMemo(\n () => (persistEnabled ? readScene(storageKey as string) : null),\n [persistEnabled, storageKey],\n );\n const effectiveInitialScene: ExcalidrawSceneSnapshot | null =\n initialScene !== undefined\n ? initialScene\n : persistedInitial\n ? {\n elements: persistedInitial.elements,\n appState: persistedInitial.appState as SyncableAppState,\n }\n : null;\n\n const flushSceneRef = useRef<() => void>(() => undefined);\n flushSceneRef.current = () => {\n try {\n const latestScene = latestSceneRef.current;\n if (!latestScene) return;\n const liveElements = latestScene.elements.filter((e) => !e.isDeleted) as readonly ExcalidrawElement[];\n const liveAppState = pickSyncableAppState(latestScene.appState);\n const hashFn = hashElementsVersionRef.current;\n // Chưa load module → bỏ qua hash dedupe, ghi luôn (correctness > perf khi unmount).\n const elementHash = hashFn ? hashFn(liveElements) : liveElements.map((e) => e.id).join('|');\n const sceneHash = `${elementHash}:${JSON.stringify(liveAppState)}`;\n if (sceneHash === lastSceneHashRef.current) return;\n lastSceneHashRef.current = sceneHash;\n onSceneChangeRef.current?.({ elements: liveElements, appState: liveAppState });\n if (persistEnabledRef.current) {\n writeScene(persistKeyRef.current as string, {\n elements: liveElements,\n appState: liveAppState,\n });\n }\n } catch (err) {\n console.warn('[whiteboard] flushScene thất bại:', err);\n }\n };\n\n const flushFilesRef = useRef<() => void>(() => undefined);\n flushFilesRef.current = () => {\n try {\n const pending = pendingFilesRef.current;\n pendingFilesRef.current = {};\n if (Object.keys(pending).length === 0) return;\n const currentElements = (apiRef.current?.getSceneElements?.()\n ?? latestSceneRef.current?.elements\n ?? []) as readonly ExcalidrawElement[];\n const stampIds = new Set<string>();\n for (const el of currentElements) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const fid = (el as any).fileId as string | undefined;\n if (fid && isStampElement(el)) stampIds.add(fid);\n }\n const raster: BinaryFiles = {};\n for (const [id, f] of Object.entries(pending)) {\n if (!stampIds.has(id)) raster[id] = f;\n }\n if (Object.keys(raster).length > 0) {\n void writeFiles(persistKeyRef.current as string, raster);\n }\n } catch (err) {\n console.warn('[whiteboard] flushFiles thất bại:', err);\n }\n };\n\n const flushPruneRef = useRef<() => void>(() => undefined);\n flushPruneRef.current = () => {\n try {\n const currentElements = (apiRef.current?.getSceneElements?.()\n ?? latestSceneRef.current?.elements\n ?? []) as readonly ExcalidrawElement[];\n const keep = new Set<string>();\n for (const el of currentElements) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const fid = (el as any).fileId as string | undefined;\n if (fid && !isStampElement(el)) keep.add(fid);\n }\n void pruneFiles(persistKeyRef.current as string, keep);\n } catch (err) {\n console.warn('[whiteboard] flushPrune thất bại:', err);\n }\n };\n\n const onSceneTick: UseScenePersistResult['onSceneTick'] = (elements, appState, files) => {\n if (readOnly) return;\n latestSceneRef.current = { elements, appState };\n\n const fileIds = Object.keys(files);\n const newIds = fileIds.filter((id) => !knownFileIdsRef.current.has(id));\n if (newIds.length > 0) {\n newIds.forEach((id) => knownFileIdsRef.current.add(id));\n onFilesChangeRef.current?.(files, newIds);\n }\n\n if (!sceneThrottleRef.current) {\n sceneThrottleRef.current = setTimeout(async () => {\n sceneThrottleRef.current = null;\n try {\n const mod = await import('@excalidraw/excalidraw');\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n hashElementsVersionRef.current = (mod as any).hashElementsVersion;\n } catch (err) {\n console.warn('[whiteboard] import excalidraw để flush scene thất bại:', err);\n return;\n }\n flushSceneRef.current();\n }, SYNC_THROTTLE_MS);\n }\n\n if (persistEnabled && newIds.length > 0) {\n for (const id of newIds) {\n if (files[id]) pendingFilesRef.current[id] = files[id];\n }\n if (!fileThrottleRef.current) {\n fileThrottleRef.current = setTimeout(() => {\n fileThrottleRef.current = null;\n flushFilesRef.current();\n }, FILE_THROTTLE_MS);\n }\n }\n\n if (persistEnabled && !pruneThrottleRef.current) {\n pruneThrottleRef.current = setTimeout(() => {\n pruneThrottleRef.current = null;\n flushPruneRef.current();\n }, PRUNE_THROTTLE_MS);\n }\n };\n\n // Mount: load initialFiles (server) → addFiles 1 lần khi api ready.\n const initialFilesAddedRef = useRef(false);\n useEffect(() => {\n if (!api || initialFilesAddedRef.current) return;\n initialFilesAddedRef.current = true;\n if (!initialFiles) return;\n const entries = Object.entries(initialFiles);\n if (entries.length === 0) return;\n try {\n api.addFiles(\n entries.map(([id, f]) => ({\n id,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n dataURL: (f as any).dataURL,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n mimeType: (f as any).mimeType,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n created: (f as any).created ?? Date.now(),\n })),\n );\n entries.forEach(([id]) => knownFileIdsRef.current.add(id));\n } catch (err) {\n console.warn('[whiteboard] addFiles initialFiles thất bại:', err);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [api]);\n\n // Mount: load persisted raster files từ IDB → addFiles.\n useEffect(() => {\n if (!api || !persistEnabled) return;\n let cancelled = false;\n void readFiles(storageKey as string).then(\n (files) => {\n // Recheck cancelled — IDB onsuccess có thể fire sau component unmount.\n if (cancelled) return;\n const entries = Object.entries(files);\n if (entries.length === 0) return;\n if (cancelled) return;\n try {\n api.addFiles(\n entries.map(([id, f]) => ({\n id,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n dataURL: (f as any).dataURL,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n mimeType: (f as any).mimeType,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n created: (f as any).created ?? Date.now(),\n })),\n );\n if (cancelled) return;\n entries.forEach(([id]) => knownFileIdsRef.current.add(id));\n } catch (err) {\n if (cancelled) return;\n console.warn('[whiteboard] addFiles từ IDB thất bại:', err);\n }\n },\n (err) => {\n if (cancelled) return;\n console.warn('[whiteboard] readFiles thất bại:', err);\n },\n );\n return () => {\n cancelled = true;\n };\n }, [api, persistEnabled, storageKey]);\n\n useEffect(() => {\n if (!api) return;\n let cancelled = false;\n const run = async () => {\n if (cancelled) return;\n try {\n const elements = api.getSceneElements();\n if (!elements || elements.length === 0) return;\n if (cancelled) return;\n // stamps đọc từ ref — props có thể đã đổi sau 400ms, closure stale.\n await restoreMissingStampFiles(api, elements, stampsRef.current);\n } catch (err) {\n if (cancelled) return;\n console.warn('Math stamp restore pass failed:', err);\n }\n };\n void run();\n const t = setTimeout(() => {\n void run();\n }, RESTORE_PASS_DELAY_MS);\n return () => {\n cancelled = true;\n clearTimeout(t);\n };\n }, [api, persistedInitial]);\n\n // Unmount cleanup: flush pending writes TRƯỚC khi clearTimeout để không\n // mất scene/file write cuối khi user navigate giữa throttle window.\n useEffect(\n () => () => {\n if (sceneThrottleRef.current) {\n clearTimeout(sceneThrottleRef.current);\n sceneThrottleRef.current = null;\n flushSceneRef.current();\n }\n if (fileThrottleRef.current) {\n clearTimeout(fileThrottleRef.current);\n fileThrottleRef.current = null;\n flushFilesRef.current();\n }\n if (pruneThrottleRef.current) {\n clearTimeout(pruneThrottleRef.current);\n pruneThrottleRef.current = null;\n flushPruneRef.current();\n }\n },\n [],\n );\n\n return { effectiveInitialScene, onSceneTick };\n}\n","'use client';\n\nimport { lazy, Suspense, useCallback, useEffect, useRef } from 'react';\nimport type {\n ExcalidrawElement,\n BinaryFiles,\n ExcalidrawSceneSnapshot,\n} from './types';\nimport {\n DEFAULT_STAMPS,\n findStampForCustomData,\n type StampType,\n} from './stamps/shared/registry';\nimport { ToolbarInjector } from './stamps/shared/ToolbarInjector';\nimport { useShortcuts } from './stamps/shared/useShortcuts';\nimport { PdfImporterButton } from './pdf/PdfImporterButton';\nimport { PageRangeDialog } from './pdf/PageRangeDialog';\nimport { useStampDoubleClick } from './stamps/shared/useStampDoubleClick';\nimport { useStampShortcutBlocker } from './stamps/shared/useStampShortcutBlocker';\nimport { useStampClickOutside } from './stamps/shared/useStampClickOutside';\nimport type { GenerateGeometryFigure, StampHostHandle } from './stamps/shared/types';\nimport { useExcalidrawApi } from './hooks/useExcalidrawApi';\nimport { useActiveStamp } from './hooks/useActiveStamp';\nimport { usePdfImporter } from './hooks/usePdfImporter';\nimport { useScenePersist } from './hooks/useScenePersist';\nimport '@excalidraw/excalidraw/index.css';\nimport './stamps/shared/stamp.css';\n\nconst Excalidraw = lazy(() =>\n import('./ExcalidrawWithMenus').then((m) => ({ default: m.ExcalidrawWithMenus })),\n);\n\nconst ExcalidrawLoadingFallback = () => (\n <div className=\"flex h-full items-center justify-center text-sm text-gray-500\">\n Đang tải bảng…\n </div>\n);\n\nexport interface WhiteboardProps {\n /**\n * Storage key cho persist client-side.\n * - Scene -> localStorage['whiteboard:scene:'+storageKey]\n * - Files raster -> IndexedDB 'whiteboard-files' index theo storageKey\n * - Default: 'default'\n * - Truyen `null` de tat persist (consumer drive state qua onApi).\n */\n storageKey?: string | null;\n\n /** View-only (Excalidraw viewModeEnabled). Default false. */\n readOnly?: boolean;\n\n /** Local edits -> consumer broadcast. Optional. */\n onSceneChange?: (snapshot: ExcalidrawSceneSnapshot) => void;\n onFilesChange?: (files: BinaryFiles, newFileIds: string[]) => void;\n\n /** Excalidraw imperative API. Consumer dung inject remote scene khi can. */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n onApi?: (api: any) => void;\n\n /** Excalidraw UI language. Defaults to 'vi-VN'. See @excalidraw/excalidraw locales. */\n langCode?: string;\n\n /**\n * Danh sách stamp đăng ký. Mỗi stamp khai báo phím tắt + toolbar button +\n * Host component (UI editing). Mặc định DEFAULT_STAMPS (= ALL_STAMPS,\n * gồm geometry + latex + geometry3d + graph2d).\n * Truyền `[...DEFAULT_STAMPS, customStamp]` để thêm stamp mới hoặc\n * `STABLE_STAMPS` để chỉ bật stamp ổn định.\n */\n stamps?: ReadonlyArray<StampType>;\n\n /**\n * Snapshot từ server. Precedence: `initialScene` > localStorage > blank.\n * - `undefined` (default) → đọc từ localStorage qua `storageKey`\n * - `null` → explicit blank, bỏ qua localStorage\n * - object → dùng làm initialData của Excalidraw, bỏ qua localStorage\n *\n * Dùng để load board từ server. Thường đi cùng `storageKey={null}` để\n * tránh localStorage stale override server data.\n */\n initialScene?: ExcalidrawSceneSnapshot | null;\n\n /**\n * Binary files (raster, base64) từ server. Add vào Excalidraw đúng 1 lần\n * khi api ready. Dùng kèm `initialScene` cho flow load-from-server.\n * Nếu cần inject files động về sau, dùng `onApi` rồi gọi `api.addFiles`.\n */\n initialFiles?: BinaryFiles;\n\n /**\n * Opt-in bridge for the geometry editor AI prompt. This callback should call\n * `generateFigure()` on a server boundary so API credentials never reach the browser.\n */\n generateGeometryFigure?: GenerateGeometryFigure;\n}\n\nexport function Whiteboard({\n storageKey = 'default',\n readOnly = false,\n onSceneChange,\n onFilesChange,\n onApi,\n langCode = 'vi-VN',\n stamps = DEFAULT_STAMPS,\n initialScene,\n initialFiles,\n generateGeometryFigure,\n}: WhiteboardProps) {\n const { api, apiRef, isDark, setApiFromExcalidraw, syncThemeFromAppState } =\n useExcalidrawApi({ onApi });\n\n const {\n activeStamp,\n editingElement,\n HostComponent,\n openStamp,\n closeStamp,\n toggleStampByKind,\n } = useActiveStamp({ readOnly, stamps });\n\n const {\n pdfPending,\n pdfBusy,\n handlePdfPick,\n handlePdfConfirm,\n handlePdfCancel,\n } = usePdfImporter({ readOnly, api });\n\n const { effectiveInitialScene, onSceneTick } = useScenePersist({\n storageKey,\n initialScene,\n initialFiles,\n readOnly,\n onSceneChange,\n onFilesChange,\n api,\n apiRef,\n stamps,\n });\n\n const hostRef = useRef<StampHostHandle | null>(null);\n const handledCropIdRef = useRef<string | null>(null);\n const prevExcalidrawToolRef = useRef<string>('selection');\n\n // Capture local changes: theme sync → crop intercept (re-edit) → persist tick.\n const handleChange = useCallback(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (elements: readonly ExcalidrawElement[], appState: any, files: BinaryFiles) => {\n syncThemeFromAppState(appState);\n\n if (readOnly) return;\n\n // Intercept Excalidraw crop-image flow cho stamps: khi user double-click\n // 1 stamp, Excalidraw set appState.croppingElementId. Ta dismiss crop mode +\n // mở Host editor tương ứng. handlePointerDown phát hiện double-click sớm\n // hơn — đây là fallback (đặc biệt khi click rơi vào selection handle).\n const cropId = appState?.croppingElementId as string | null | undefined;\n if (cropId && cropId !== handledCropIdRef.current && api) {\n const el = elements.find((e: ExcalidrawElement) => e.id === cropId);\n if (el) {\n const stamp = findStampForCustomData((el as { customData?: unknown }).customData, stamps);\n if (stamp) {\n handledCropIdRef.current = cropId;\n // Defer updateScene + openStamp ra khỏi commit-phase của Excalidraw —\n // chạy đồng bộ sẽ trigger React 19 warn \"update scheduled from inside\n // an update function\" (handleChange chạy trong updater).\n const elId = el.id;\n const elCustom = (el as { customData?: unknown }).customData;\n const stampKind = stamp.kind;\n queueMicrotask(() => {\n try {\n api.updateScene({\n appState: { croppingElementId: null, selectedElementIds: {} },\n });\n } catch { /* ignore */ }\n openStamp(stampKind, { id: elId, customData: elCustom });\n });\n return;\n }\n }\n }\n if (!cropId) {\n handledCropIdRef.current = null;\n }\n\n onSceneTick(elements, appState, files);\n },\n [readOnly, api, stamps, openStamp, syncThemeFromAppState, onSceneTick],\n );\n\n // Double-click detection for re-edit.\n const handlePointerDown = useStampDoubleClick({\n enabled: !readOnly,\n stamps,\n onOpen: openStamp,\n });\n\n // Keyboard shortcuts: đọc registry, mỗi stamp tự khai báo phím tắt.\n useShortcuts({\n enabled: !readOnly,\n onToggle: toggleStampByKind,\n stamps,\n });\n\n // Sync Excalidraw activeTool với activeStamp.\n useEffect(() => {\n if (!api) return;\n if (activeStamp) {\n try {\n const cur = api.getAppState?.()?.activeTool?.type ?? 'selection';\n if (cur && cur !== 'hand') prevExcalidrawToolRef.current = cur;\n api.setActiveTool?.({ type: 'hand' });\n } catch { /* ignore */ }\n } else {\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n api.setActiveTool?.({ type: prevExcalidrawToolRef.current as any });\n } catch { /* ignore */ }\n }\n }, [activeStamp, api]);\n\n // Block Excalidraw shortcuts khi stamp panel đang mở.\n useStampShortcutBlocker({ activeStamp, stamps });\n\n // Esc đóng panel (capture phase để chạy TRƯỚC Excalidraw).\n useEffect(() => {\n if (!activeStamp) return;\n const onKey = (e: KeyboardEvent) => {\n if (e.key !== 'Escape') return;\n const ae = document.activeElement as HTMLElement | null;\n if (ae && (ae.tagName === 'TEXTAREA' || ae.isContentEditable)) {\n return;\n }\n e.preventDefault();\n e.stopPropagation();\n closeStamp();\n };\n window.addEventListener('keydown', onKey, { capture: true });\n return () => window.removeEventListener('keydown', onKey, { capture: true });\n }, [activeStamp, closeStamp]);\n\n useStampClickOutside({ activeStamp, hostRef, onClose: closeStamp });\n\n return (\n <div className={`relative h-full w-full${isDark ? ' theme--dark' : ''}`}>\n <Suspense fallback={<ExcalidrawLoadingFallback />}>\n <Excalidraw\n excalidrawAPI={setApiFromExcalidraw}\n langCode={langCode}\n viewModeEnabled={readOnly}\n initialData={\n effectiveInitialScene\n ? {\n elements: effectiveInitialScene.elements,\n appState: {\n ...effectiveInitialScene.appState,\n gridSize: effectiveInitialScene.appState.gridSize ?? undefined,\n },\n }\n : { appState: { viewBackgroundColor: '#ffffff' } }\n }\n onChange={handleChange}\n onPointerDown={handlePointerDown}\n />\n </Suspense>\n\n <ToolbarInjector\n enabled={!readOnly}\n activeStampKind={activeStamp}\n onToggle={toggleStampByKind}\n stamps={stamps}\n />\n\n <PdfImporterButton enabled={!readOnly} onPick={handlePdfPick} />\n\n {pdfPending && (\n <PageRangeDialog\n doc={pdfPending.doc}\n fileName={pdfPending.fileName}\n onConfirm={handlePdfConfirm}\n onCancel={handlePdfCancel}\n />\n )}\n\n {pdfBusy && !pdfPending && (\n <div\n aria-live=\"polite\"\n role=\"status\"\n style={{\n position: 'fixed',\n bottom: 16,\n right: 16,\n padding: '8px 14px',\n background: 'rgba(0,0,0,0.75)',\n color: '#fff',\n borderRadius: 6,\n fontSize: 12,\n zIndex: 10000,\n }}\n >\n Đang xử lý PDF…\n </div>\n )}\n\n {HostComponent && (\n <HostComponent\n ref={hostRef}\n api={api}\n editingElement={editingElement}\n onClose={closeStamp}\n isDark={isDark}\n generateGeometryFigure={generateGeometryFigure}\n />\n )}\n </div>\n );\n}\n","// src/stamps/geometry-2d/dsl/schema.ts\nimport { z } from 'zod';\n\n// Label-style name: chữ cái Latin đầu, cho phép unicode prime (') + subscript ₀-₉.\n// Max length 12 ký tự. Phân biệt hoa/thường.\nexport const NameZ = z\n .string()\n .regex(/^[A-Za-z][A-Za-z0-9_'₀-₉]{0,11}$/);\n\nexport const DslPoint = z.discriminatedUnion('kind', [\n z.object({ name: NameZ, kind: z.literal('free'),\n x: z.number().finite(), y: z.number().finite() }),\n z.object({ name: NameZ, kind: z.literal('midpoint'),\n p1: NameZ, p2: NameZ }),\n z.object({ name: NameZ, kind: z.literal('onSegment'),\n segmentId: NameZ, t: z.number().min(0).max(1) }),\n z.object({ name: NameZ, kind: z.literal('onLine'),\n lineId: NameZ, t: z.number().finite() }),\n z.object({ name: NameZ, kind: z.literal('onCircle'),\n circleId: NameZ, theta: z.number().finite() }),\n z.object({ name: NameZ, kind: z.literal('perpFoot'),\n from: NameZ, onLine: NameZ }),\n z.object({ name: NameZ, kind: z.literal('circumcenter'),\n vertices: z.tuple([NameZ, NameZ, NameZ]) }),\n z.object({ name: NameZ, kind: z.literal('incenter'),\n vertices: z.tuple([NameZ, NameZ, NameZ]) }),\n z.object({ name: NameZ, kind: z.literal('centroid'),\n vertices: z.tuple([NameZ, NameZ, NameZ]) }),\n z.object({ name: NameZ, kind: z.literal('orthocenter'),\n vertices: z.tuple([NameZ, NameZ, NameZ]) }),\n z.object({ name: NameZ, kind: z.literal('intersection'),\n ref1: NameZ, ref2: NameZ,\n branch: z.union([z.literal(0), z.literal(1)]).optional() }),\n]);\n\nexport const DslShape = z.discriminatedUnion('kind', [\n z.object({ name: NameZ, kind: z.literal('segment'),\n p1: NameZ, p2: NameZ }),\n z.object({ name: NameZ, kind: z.literal('line'),\n p1: NameZ, p2: NameZ }),\n z.object({ name: NameZ, kind: z.literal('ray'),\n origin: NameZ, through: NameZ }),\n z.object({ name: NameZ, kind: z.literal('polygon'),\n vertices: z.array(NameZ).min(3) }),\n // Line constructions\n z.object({ name: NameZ, kind: z.literal('perpendicular'),\n throughPoint: NameZ, toLine: NameZ }),\n z.object({ name: NameZ, kind: z.literal('parallel'),\n throughPoint: NameZ, toLine: NameZ }),\n z.object({ name: NameZ, kind: z.literal('perpBisector'),\n p1: NameZ, p2: NameZ }),\n z.object({ name: NameZ, kind: z.literal('angleBisector'),\n p1: NameZ, vertex: NameZ, p2: NameZ }),\n z.object({ name: NameZ, kind: z.literal('tangent'),\n throughPoint: NameZ, toCircle: NameZ,\n branch: z.union([z.literal(0), z.literal(1), z.literal('on')]).optional() }),\n // Circle constructions\n z.object({ name: NameZ, kind: z.literal('circleCP'),\n center: NameZ, surfacePoint: NameZ }),\n z.object({ name: NameZ, kind: z.literal('circle3'),\n p1: NameZ, p2: NameZ, p3: NameZ }),\n]);\n\nexport const DslInput = z.object({\n version: z.literal(1),\n points: z.array(DslPoint),\n shapes: z.array(DslShape).default([]),\n});\n\nexport type DslPointT = z.infer<typeof DslPoint>;\nexport type DslShapeT = z.infer<typeof DslShape>;\nexport type DslInputT = z.infer<typeof DslInput>;\n","// src/stamps/geometry-2d/dsl/transpile/errors.ts\nimport type { State } from '../../../../core/scene/types';\n\nexport type TranspileErrorCode =\n | 'SCHEMA'\n | 'DUPLICATE_NAME'\n | 'UNKNOWN_REF'\n | 'KIND_MISMATCH'\n | 'CYCLE';\n\nexport interface TranspileError {\n code: TranspileErrorCode;\n message: string;\n path?: string[];\n hint?: string;\n}\n\nexport type TranspileResult =\n | { ok: true; state: State }\n | { ok: false; errors: TranspileError[] };\n\nexport function mkError(\n code: TranspileErrorCode,\n message: string,\n opts?: { path?: string[]; hint?: string },\n): TranspileError {\n return { code, message, path: opts?.path, hint: opts?.hint };\n}\n","// src/stamps/geometry-2d/dsl/transpile/symbols.ts\nimport type { DslInputT, DslPointT, DslShapeT } from '../schema';\nimport { mkError, type TranspileError } from './errors';\n\nexport type Role = 'point' | 'shape';\n\nexport interface Symbol {\n name: string;\n role: Role;\n entity: DslPointT | DslShapeT;\n index: number; // vị trí trong list nguyên thuỷ (cho deterministic id assign sau)\n}\n\nexport interface SymbolResult {\n symbols: Map<string, Symbol>;\n errors: TranspileError[];\n}\n\nexport function buildSymbols(dsl: DslInputT): SymbolResult {\n const symbols = new Map<string, Symbol>();\n const errors: TranspileError[] = [];\n let counter = 0;\n\n for (const p of dsl.points) {\n if (symbols.has(p.name)) {\n errors.push(mkError('DUPLICATE_NAME', `Tên trùng: \"${p.name}\"`, { path: [p.name] }));\n continue;\n }\n symbols.set(p.name, { name: p.name, role: 'point', entity: p, index: counter++ });\n }\n\n for (const s of dsl.shapes) {\n if (symbols.has(s.name)) {\n errors.push(mkError('DUPLICATE_NAME', `Tên trùng: \"${s.name}\"`, { path: [s.name] }));\n continue;\n }\n symbols.set(s.name, { name: s.name, role: 'shape', entity: s, index: counter++ });\n }\n\n return { symbols, errors };\n}\n","// src/stamps/geometry-2d/dsl/transpile/refs.ts\nimport type { DslInputT, DslPointT, DslShapeT } from '../schema';\nimport type { Symbol } from './symbols';\nimport { mkError, type TranspileError } from './errors';\n\n// \"Point-like\" = DslPoint of any kind. State sẽ emit `kind: 'point'` hoặc\n// `kind: 'intersection'`; cả hai visualize as points.\nfunction isPointLike(sym: Symbol | undefined): boolean {\n return !!sym && sym.role === 'point';\n}\n\n// \"Line-like\" gồm: line / segment / ray + 5 line-constructions.\nconst LINE_LIKE_SHAPE_KINDS = new Set<DslShapeT['kind']>([\n 'line', 'segment', 'ray',\n 'perpendicular', 'parallel', 'perpBisector', 'angleBisector', 'tangent',\n]);\n\nconst CIRCLE_KINDS = new Set<DslShapeT['kind']>(['circleCP', 'circle3']);\n\nfunction isLineLike(sym: Symbol | undefined): boolean {\n if (!sym || sym.role !== 'shape') return false;\n return LINE_LIKE_SHAPE_KINDS.has((sym.entity as DslShapeT).kind);\n}\n\nfunction isCircleLike(sym: Symbol | undefined): boolean {\n if (!sym || sym.role !== 'shape') return false;\n return CIRCLE_KINDS.has((sym.entity as DslShapeT).kind);\n}\n\nfunction isSegmentExact(sym: Symbol | undefined): boolean {\n return !!sym && sym.role === 'shape' && (sym.entity as DslShapeT).kind === 'segment';\n}\n\nexport interface RefsResult {\n errors: TranspileError[];\n}\n\nexport function validateRefs(dsl: DslInputT, symbols: Map<string, Symbol>): RefsResult {\n const errors: TranspileError[] = [];\n\n const check = (\n owner: string,\n field: string,\n refName: string,\n predicate: (s: Symbol | undefined) => boolean,\n expected: string,\n ) => {\n const sym = symbols.get(refName);\n if (!sym) {\n errors.push(mkError('UNKNOWN_REF',\n `${owner}.${field} tham chiếu \"${refName}\" không tồn tại`,\n { path: [owner, field] }));\n return;\n }\n if (!predicate(sym)) {\n errors.push(mkError('KIND_MISMATCH',\n `${owner}.${field}=\"${refName}\" sai kiểu (cần ${expected}, gặp ${sym.role === 'point' ? 'point' : (sym.entity as DslShapeT).kind})`,\n { path: [owner, field] }));\n }\n };\n\n for (const p of dsl.points) {\n switch (p.kind) {\n case 'free': break;\n case 'midpoint':\n check(p.name, 'p1', p.p1, isPointLike, 'point');\n check(p.name, 'p2', p.p2, isPointLike, 'point');\n break;\n case 'onSegment':\n check(p.name, 'segmentId', p.segmentId, isSegmentExact, 'segment');\n break;\n case 'onLine':\n check(p.name, 'lineId', p.lineId, isLineLike, 'line-like');\n break;\n case 'onCircle':\n check(p.name, 'circleId', p.circleId, isCircleLike, 'circle');\n break;\n case 'perpFoot':\n check(p.name, 'from', p.from, isPointLike, 'point');\n check(p.name, 'onLine', p.onLine, isLineLike, 'line-like');\n break;\n case 'circumcenter':\n case 'incenter':\n case 'centroid':\n case 'orthocenter':\n for (let i = 0; i < 3; i++) {\n check(p.name, `vertices[${i}]`, p.vertices[i], isPointLike, 'point');\n }\n break;\n case 'intersection': {\n const refPredicate = (s: Symbol | undefined) => isLineLike(s) || isCircleLike(s);\n check(p.name, 'ref1', p.ref1, refPredicate, 'line-like hoặc circle');\n check(p.name, 'ref2', p.ref2, refPredicate, 'line-like hoặc circle');\n break;\n }\n }\n }\n\n for (const s of dsl.shapes) {\n switch (s.kind) {\n case 'segment':\n case 'line':\n check(s.name, 'p1', s.p1, isPointLike, 'point');\n check(s.name, 'p2', s.p2, isPointLike, 'point');\n break;\n case 'ray':\n check(s.name, 'origin', s.origin, isPointLike, 'point');\n check(s.name, 'through', s.through, isPointLike, 'point');\n break;\n case 'polygon':\n s.vertices.forEach((v, i) =>\n check(s.name, `vertices[${i}]`, v, isPointLike, 'point'));\n break;\n case 'perpendicular':\n case 'parallel':\n check(s.name, 'throughPoint', s.throughPoint, isPointLike, 'point');\n check(s.name, 'toLine', s.toLine, isLineLike, 'line-like');\n break;\n case 'perpBisector':\n check(s.name, 'p1', s.p1, isPointLike, 'point');\n check(s.name, 'p2', s.p2, isPointLike, 'point');\n break;\n case 'angleBisector':\n check(s.name, 'p1', s.p1, isPointLike, 'point');\n check(s.name, 'vertex', s.vertex, isPointLike, 'point');\n check(s.name, 'p2', s.p2, isPointLike, 'point');\n break;\n case 'tangent':\n check(s.name, 'throughPoint', s.throughPoint, isPointLike, 'point');\n check(s.name, 'toCircle', s.toCircle, isCircleLike, 'circle');\n break;\n case 'circleCP':\n check(s.name, 'center', s.center, isPointLike, 'point');\n check(s.name, 'surfacePoint', s.surfacePoint, isPointLike, 'point');\n break;\n case 'circle3':\n check(s.name, 'p1', s.p1, isPointLike, 'point');\n check(s.name, 'p2', s.p2, isPointLike, 'point');\n check(s.name, 'p3', s.p3, isPointLike, 'point');\n break;\n }\n }\n\n return { errors };\n}\n\n// Helper export cho cycles.ts: collect refs cho mỗi entity (name) trả về list ref names.\nexport function collectRefs(entity: DslPointT | DslShapeT): string[] {\n if ('kind' in entity) {\n switch (entity.kind) {\n case 'free': return [];\n case 'midpoint': return [entity.p1, entity.p2];\n case 'onSegment': return [entity.segmentId];\n case 'onLine': return [entity.lineId];\n case 'onCircle': return [entity.circleId];\n case 'perpFoot': return [entity.from, entity.onLine];\n case 'circumcenter':\n case 'incenter':\n case 'centroid':\n case 'orthocenter': return [...entity.vertices];\n case 'intersection': return [entity.ref1, entity.ref2];\n case 'segment':\n case 'line': return [entity.p1, entity.p2];\n case 'ray': return [entity.origin, entity.through];\n case 'polygon': return [...entity.vertices];\n case 'perpendicular':\n case 'parallel': return [entity.throughPoint, entity.toLine];\n case 'perpBisector': return [entity.p1, entity.p2];\n case 'angleBisector':return [entity.p1, entity.vertex, entity.p2];\n case 'tangent': return [entity.throughPoint, entity.toCircle];\n case 'circleCP': return [entity.center, entity.surfacePoint];\n case 'circle3': return [entity.p1, entity.p2, entity.p3];\n }\n }\n return [];\n}\n","// src/stamps/geometry-2d/dsl/transpile/cycles.ts\nimport type { Symbol } from './symbols';\nimport { collectRefs } from './refs';\nimport { mkError, type TranspileError } from './errors';\n\ntype Color = 'white' | 'gray' | 'black';\n\nexport interface CyclesResult {\n errors: TranspileError[];\n}\n\nexport function detectCycles(symbols: Map<string, Symbol>): CyclesResult {\n const color = new Map<string, Color>();\n const parent = new Map<string, string | null>();\n const errors: TranspileError[] = [];\n const reportedCycles = new Set<string>();\n\n for (const name of symbols.keys()) color.set(name, 'white');\n\n function reportCycle(start: string, hit: string) {\n // reconstruct chain hit ← ... ← start\n const chain: string[] = [start];\n let cur: string | null | undefined = parent.get(start);\n while (cur && cur !== hit && chain.length < symbols.size + 2) {\n chain.push(cur);\n cur = parent.get(cur);\n }\n chain.push(hit);\n // normalize cho dedupe (rotate min-first)\n const minIdx = chain.indexOf(chain.reduce((a, b) => (a < b ? a : b)));\n const rotated = [...chain.slice(minIdx), ...chain.slice(0, minIdx)];\n const key = rotated.join('→');\n if (reportedCycles.has(key)) return;\n reportedCycles.add(key);\n errors.push(mkError('CYCLE',\n `Phụ thuộc vòng: ${chain.reverse().join(' → ')}`,\n { path: [...chain], hint: 'Kiểm tra lại quan hệ midpoint/perpFoot/intersection.' }));\n }\n\n function dfs(name: string) {\n color.set(name, 'gray');\n const sym = symbols.get(name);\n if (sym) {\n for (const ref of collectRefs(sym.entity)) {\n if (!symbols.has(ref)) continue; // unknown — refs.ts handle\n const c = color.get(ref);\n if (c === 'gray') {\n reportCycle(name, ref);\n continue;\n }\n if (c === 'white') {\n parent.set(ref, name);\n dfs(ref);\n }\n }\n }\n color.set(name, 'black');\n }\n\n for (const name of symbols.keys()) {\n if (color.get(name) === 'white') {\n parent.set(name, null);\n dfs(name);\n }\n }\n\n return { errors };\n}\n","// src/stamps/geometry-2d/dsl/transpile/ids.ts\nimport type { DslPointT, DslShapeT } from '../schema';\nimport type { Symbol } from './symbols';\n\ntype Prefix = 'p' | 'i' | 's' | 'l' | 'r' | 'poly' | 'c';\n\nfunction prefixFor(sym: Symbol): Prefix {\n if (sym.role === 'point') {\n const p = sym.entity as DslPointT;\n return p.kind === 'intersection' ? 'i' : 'p';\n }\n const s = sym.entity as DslShapeT;\n switch (s.kind) {\n case 'segment': return 's';\n case 'ray': return 'r';\n case 'polygon': return 'poly';\n case 'circleCP':\n case 'circle3': return 'c';\n // line + 5 line-constructions all share 'l'\n case 'line':\n case 'perpendicular':\n case 'parallel':\n case 'perpBisector':\n case 'angleBisector':\n case 'tangent': return 'l';\n }\n}\n\nexport function assignIds(symbols: Map<string, Symbol>): Map<string, string> {\n const counters: Record<Prefix, number> = { p: 0, i: 0, s: 0, l: 0, r: 0, poly: 0, c: 0 };\n const ids = new Map<string, string>();\n // Insertion order của Map khớp DSL order (points first, shapes after) — buildSymbols guarantee.\n for (const [name, sym] of symbols.entries()) {\n const prefix = prefixFor(sym);\n counters[prefix] += 1;\n ids.set(name, `${prefix}${counters[prefix]}`);\n }\n return ids;\n}\n","// src/stamps/geometry-2d/dsl/transpile/emitPoint.ts\nimport type { SceneObject } from '../../../../core/scene/types';\nimport type { DslPointT } from '../schema';\n\nexport type EntityKindHint =\n | 'point'\n | 'line' // DslShape 'line'\n | 'segment'\n | 'ray'\n | 'lineConstruction' // perpendicular/parallel/perpBisector/angleBisector/tangent\n | 'circle';\n\nfunction resolveId(ids: Map<string, string>, name: string): string {\n const id = ids.get(name);\n if (!id) throw new Error(`emitPoint: id not assigned for \"${name}\"`);\n return id;\n}\n\nexport function emitPoint(\n p: DslPointT,\n ids: Map<string, string>,\n kindHints: Map<string, EntityKindHint>,\n): SceneObject {\n const baseId = resolveId(ids, p.name);\n\n const baseFields = {\n label: p.name,\n visible: true,\n locked: false,\n layer: 'default',\n schemaVersion: 1,\n };\n\n if (p.kind === 'intersection') {\n const r1Hint = kindHints.get(p.ref1);\n const r2Hint = kindHints.get(p.ref2);\n const r1IsCircle = r1Hint === 'circle';\n const r2IsCircle = r2Hint === 'circle';\n let intersectKind: 'lineLine' | 'lineCircle' | 'circleCircle';\n if (r1IsCircle && r2IsCircle) intersectKind = 'circleCircle';\n else if (r1IsCircle || r2IsCircle) intersectKind = 'lineCircle';\n else intersectKind = 'lineLine';\n\n const attrs: Record<string, unknown> = {\n kind: intersectKind,\n ref1: resolveId(ids, p.ref1),\n ref2: resolveId(ids, p.ref2),\n };\n if (intersectKind !== 'lineLine') {\n attrs.branch = p.branch ?? 0;\n }\n return {\n id: baseId,\n kind: 'intersection',\n ...baseFields,\n attrs,\n };\n }\n\n let constraint: Record<string, unknown>;\n switch (p.kind) {\n case 'free':\n constraint = { kind: 'free', x: p.x, y: p.y };\n break;\n case 'midpoint':\n constraint = { kind: 'midpoint', p1: resolveId(ids, p.p1), p2: resolveId(ids, p.p2) };\n break;\n case 'onSegment':\n constraint = { kind: 'onSegment', segmentId: resolveId(ids, p.segmentId), t: p.t };\n break;\n case 'onLine':\n constraint = { kind: 'onLine', lineId: resolveId(ids, p.lineId), t: p.t };\n break;\n case 'onCircle':\n constraint = { kind: 'onCircle', circleId: resolveId(ids, p.circleId), theta: p.theta };\n break;\n case 'perpFoot':\n constraint = { kind: 'perpFoot', from: resolveId(ids, p.from), onLine: resolveId(ids, p.onLine) };\n break;\n case 'circumcenter':\n case 'incenter':\n case 'centroid':\n case 'orthocenter':\n constraint = {\n kind: p.kind,\n vertices: [resolveId(ids, p.vertices[0]), resolveId(ids, p.vertices[1]), resolveId(ids, p.vertices[2])],\n };\n break;\n }\n\n return {\n id: baseId,\n kind: 'point',\n ...baseFields,\n attrs: { constraint },\n };\n}\n","// src/stamps/geometry-2d/dsl/transpile/emitShape.ts\nimport type { SceneObject } from '../../../../core/scene/types';\nimport type { DslShapeT } from '../schema';\n\nfunction r(ids: Map<string, string>, name: string): string {\n const id = ids.get(name);\n if (!id) throw new Error(`emitShape: id not assigned for \"${name}\"`);\n return id;\n}\n\nexport function emitShape(s: DslShapeT, ids: Map<string, string>): SceneObject {\n const id = r(ids, s.name);\n const base = {\n label: s.name,\n visible: true,\n locked: false,\n layer: 'default',\n schemaVersion: 1,\n };\n\n switch (s.kind) {\n case 'segment':\n return { id, kind: 'segment', ...base, attrs: { p1: r(ids, s.p1), p2: r(ids, s.p2) } };\n\n case 'line':\n return { id, kind: 'line', ...base, attrs: { p1: r(ids, s.p1), p2: r(ids, s.p2) } };\n\n case 'ray':\n return { id, kind: 'ray', ...base, attrs: { origin: r(ids, s.origin), through: r(ids, s.through) } };\n\n case 'polygon':\n return { id, kind: 'polygon', ...base, attrs: { vertices: s.vertices.map((v) => r(ids, v)) } };\n\n case 'perpendicular':\n case 'parallel':\n return {\n id, kind: 'line', ...base,\n attrs: { construction: { kind: s.kind, throughPoint: r(ids, s.throughPoint), toLine: r(ids, s.toLine) } },\n };\n\n case 'perpBisector':\n return {\n id, kind: 'line', ...base,\n attrs: { construction: { kind: 'perpBisector', p1: r(ids, s.p1), p2: r(ids, s.p2) } },\n };\n\n case 'angleBisector':\n return {\n id, kind: 'line', ...base,\n attrs: { construction: { kind: 'angleBisector', p1: r(ids, s.p1), vertex: r(ids, s.vertex), p2: r(ids, s.p2) } },\n };\n\n case 'tangent': {\n const construction: Record<string, unknown> = {\n kind: 'tangent',\n throughPoint: r(ids, s.throughPoint),\n toCircle: r(ids, s.toCircle),\n };\n if (s.branch !== undefined) construction.branch = s.branch;\n return { id, kind: 'line', ...base, attrs: { construction } };\n }\n\n case 'circleCP':\n return {\n id, kind: 'circle', ...base,\n attrs: { center: r(ids, s.center), surfacePoint: r(ids, s.surfacePoint) },\n };\n\n case 'circle3':\n return {\n id, kind: 'circle', ...base,\n attrs: { construction: { kind: 'circumscribed', p1: r(ids, s.p1), p2: r(ids, s.p2), p3: r(ids, s.p3) } },\n };\n }\n}\n","// src/stamps/geometry-2d/dsl/transpile.ts\nimport type { SceneObject, State } from '../../../core/scene/types';\nimport { createEmptyState } from '../../../core/scene/types';\nimport { DslInput, type DslPointT, type DslShapeT } from './schema';\nimport { buildSymbols } from './transpile/symbols';\nimport { validateRefs } from './transpile/refs';\nimport { detectCycles } from './transpile/cycles';\nimport { assignIds } from './transpile/ids';\nimport { emitPoint, type EntityKindHint } from './transpile/emitPoint';\nimport { emitShape } from './transpile/emitShape';\nimport { mkError, type TranspileError, type TranspileResult } from './transpile/errors';\n\nfunction hintOf(entity: DslPointT | DslShapeT): EntityKindHint {\n // points (including intersection) are point-like at scene level.\n if ('kind' in entity) {\n switch (entity.kind) {\n case 'free': case 'midpoint': case 'onSegment': case 'onLine':\n case 'onCircle': case 'perpFoot': case 'circumcenter':\n case 'incenter': case 'centroid': case 'orthocenter': case 'intersection':\n return 'point';\n case 'segment': return 'segment';\n case 'line': return 'line';\n case 'ray': return 'ray';\n case 'polygon': return 'point'; // not used as ref target in MVP\n case 'perpendicular': case 'parallel': case 'perpBisector':\n case 'angleBisector': case 'tangent':\n return 'lineConstruction';\n case 'circleCP': case 'circle3':\n return 'circle';\n }\n }\n return 'point';\n}\n\nexport function transpile(dslRaw: unknown): TranspileResult {\n // Stage 1: schema parse\n const parsed = DslInput.safeParse(dslRaw);\n if (!parsed.success) {\n const errors: TranspileError[] = parsed.error.issues.map((iss) =>\n mkError('SCHEMA', iss.message, { path: iss.path.map(String) }),\n );\n return { ok: false, errors };\n }\n const dsl = parsed.data;\n\n // Stage 2-4: collect errors\n const { symbols, errors: dupErrors } = buildSymbols(dsl);\n const { errors: refErrors } = validateRefs(dsl, symbols);\n const { errors: cycleErrors } = detectCycles(symbols);\n\n const allErrors = [...dupErrors, ...refErrors, ...cycleErrors];\n if (allErrors.length > 0) return { ok: false, errors: allErrors };\n\n // Stage 5: id assignment\n const ids = assignIds(symbols);\n\n // Build kindHints (DSL name → EntityKindHint) cho intersection inference.\n const kindHints = new Map<string, EntityKindHint>();\n for (const [name, sym] of symbols.entries()) {\n kindHints.set(name, hintOf(sym.entity));\n }\n\n // Stage 6: emit\n const objects: Record<string, SceneObject> = {};\n const order: string[] = [];\n\n for (const p of dsl.points) {\n const obj = emitPoint(p, ids, kindHints);\n objects[obj.id] = obj;\n order.push(obj.id);\n }\n for (const s of dsl.shapes) {\n const obj = emitShape(s, ids);\n objects[obj.id] = obj;\n order.push(obj.id);\n }\n\n const empty = createEmptyState('2d');\n const state: State = {\n objects,\n order,\n counter: order.length,\n meta: empty.meta,\n };\n return { ok: true, state };\n}\n","// src/stamps/geometry-2d/ai/provider.ts\nimport Anthropic from '@anthropic-ai/sdk';\n\nexport interface ProviderSystemBlock {\n type: 'text';\n text: string;\n cache_control?: { type: 'ephemeral' };\n}\n\nexport interface ProviderToolDef {\n name: string;\n description: string;\n input_schema: unknown;\n}\n\nexport interface ProviderCallArgs {\n apiKey: string;\n model: string;\n maxTokens: number;\n system: ProviderSystemBlock[];\n tools: ProviderToolDef[];\n toolChoice: { type: 'any' } | { type: 'tool'; name: string };\n messages: Array<{ role: 'user' | 'assistant'; content: string }>;\n signal?: AbortSignal;\n}\n\nexport interface ProviderUsage {\n input_tokens: number;\n output_tokens: number;\n cache_read_input_tokens?: number;\n cache_creation_input_tokens?: number;\n}\n\nexport type ProviderContentBlock =\n | { type: 'text'; text: string }\n | { type: 'tool_use'; id: string; name: string; input: unknown };\n\nexport interface ProviderResponse {\n content: ProviderContentBlock[];\n stop_reason: string;\n usage: ProviderUsage;\n}\n\nexport async function callProvider(args: ProviderCallArgs): Promise<ProviderResponse> {\n const client = new Anthropic({ apiKey: args.apiKey });\n const resp = await client.messages.create(\n {\n model: args.model,\n max_tokens: args.maxTokens,\n system: args.system,\n tools: args.tools as never,\n tool_choice: args.toolChoice,\n messages: args.messages,\n },\n args.signal ? { signal: args.signal } : undefined,\n );\n return resp as unknown as ProviderResponse;\n}\n","// src/stamps/geometry-2d/dsl/fixtures/triangle-equilateral.ts\nimport type { DslInputT } from '../schema';\n\nexport const fixture: { problem: string; dsl: DslInputT } = {\n problem: 'Cho tam giác đều ABC cạnh 4.',\n dsl: {\n version: 1,\n points: [\n { name: 'A', kind: 'free', x: 0, y: 0 },\n { name: 'B', kind: 'free', x: 4, y: 0 },\n { name: 'C', kind: 'free', x: 2, y: 3.464 },\n ],\n shapes: [\n { name: 'ABC', kind: 'polygon', vertices: ['A', 'B', 'C'] },\n ],\n },\n};\n","// src/stamps/geometry-2d/dsl/fixtures/triangle-median.ts\nimport type { DslInputT } from '../schema';\n\nexport const fixture: { problem: string; dsl: DslInputT } = {\n problem: 'Tam giác ABC, M là trung điểm BC. Vẽ AM.',\n dsl: {\n version: 1,\n points: [\n { name: 'A', kind: 'free', x: 0, y: 3 },\n { name: 'B', kind: 'free', x: -2, y: 0 },\n { name: 'C', kind: 'free', x: 3, y: 0 },\n { name: 'M', kind: 'midpoint', p1: 'B', p2: 'C' },\n ],\n shapes: [\n { name: 'ABC', kind: 'polygon', vertices: ['A', 'B', 'C'] },\n { name: 'AM', kind: 'segment', p1: 'A', p2: 'M' },\n ],\n },\n};\n","// src/stamps/geometry-2d/dsl/fixtures/triangle-altitude.ts\nimport type { DslInputT } from '../schema';\n\nexport const fixture: { problem: string; dsl: DslInputT } = {\n problem: 'Tam giác ABC, AH là đường cao xuống BC.',\n dsl: {\n version: 1,\n points: [\n { name: 'A', kind: 'free', x: 1, y: 3 },\n { name: 'B', kind: 'free', x: -2, y: 0 },\n { name: 'C', kind: 'free', x: 3, y: 0 },\n { name: 'H', kind: 'perpFoot', from: 'A', onLine: 'BC' },\n ],\n shapes: [\n { name: 'ABC', kind: 'polygon', vertices: ['A', 'B', 'C'] },\n { name: 'BC', kind: 'segment', p1: 'B', p2: 'C' },\n { name: 'AH', kind: 'segment', p1: 'A', p2: 'H' },\n ],\n },\n};\n","// src/stamps/geometry-2d/dsl/fixtures/triangle-centroid.ts\nimport type { DslInputT } from '../schema';\n\nexport const fixture: { problem: string; dsl: DslInputT } = {\n problem: 'Tam giác ABC, G là trọng tâm.',\n dsl: {\n version: 1,\n points: [\n { name: 'A', kind: 'free', x: 0, y: 3 },\n { name: 'B', kind: 'free', x: -2, y: 0 },\n { name: 'C', kind: 'free', x: 3, y: 0 },\n { name: 'G', kind: 'centroid', vertices: ['A', 'B', 'C'] },\n ],\n shapes: [\n { name: 'ABC', kind: 'polygon', vertices: ['A', 'B', 'C'] },\n ],\n },\n};\n","// src/stamps/geometry-2d/dsl/fixtures/triangle-orthocenter.ts\nimport type { DslInputT } from '../schema';\n\nexport const fixture: { problem: string; dsl: DslInputT } = {\n problem: 'Tam giác ABC, H là trực tâm.',\n dsl: {\n version: 1,\n points: [\n { name: 'A', kind: 'free', x: 0, y: 3 },\n { name: 'B', kind: 'free', x: -2, y: 0 },\n { name: 'C', kind: 'free', x: 3, y: 0 },\n { name: 'H', kind: 'orthocenter', vertices: ['A', 'B', 'C'] },\n ],\n shapes: [\n { name: 'ABC', kind: 'polygon', vertices: ['A', 'B', 'C'] },\n ],\n },\n};\n","// src/stamps/geometry-2d/dsl/fixtures/triangle-circumcircle.ts\nimport type { DslInputT } from '../schema';\n\nexport const fixture: { problem: string; dsl: DslInputT } = {\n problem: 'Tam giác ABC nội tiếp đường tròn tâm O.',\n dsl: {\n version: 1,\n points: [\n { name: 'A', kind: 'free', x: 0, y: 3 },\n { name: 'B', kind: 'free', x: -2, y: 0 },\n { name: 'C', kind: 'free', x: 3, y: 0 },\n { name: 'O', kind: 'circumcenter', vertices: ['A', 'B', 'C'] },\n ],\n shapes: [\n { name: 'ABC', kind: 'polygon', vertices: ['A', 'B', 'C'] },\n { name: 'k', kind: 'circle3', p1: 'A', p2: 'B', p3: 'C' },\n ],\n },\n};\n","// src/stamps/geometry-2d/dsl/fixtures/triangle-incircle.ts\nimport type { DslInputT } from '../schema';\n\nexport const fixture: { problem: string; dsl: DslInputT } = {\n problem: 'Tam giác ABC, I là tâm nội tiếp, đường tròn (I) tiếp xúc BC tại D.',\n dsl: {\n version: 1,\n points: [\n { name: 'A', kind: 'free', x: 0, y: 3 },\n { name: 'B', kind: 'free', x: -2, y: 0 },\n { name: 'C', kind: 'free', x: 3, y: 0 },\n { name: 'I', kind: 'incenter', vertices: ['A', 'B', 'C'] },\n { name: 'D', kind: 'perpFoot', from: 'I', onLine: 'BC' },\n ],\n shapes: [\n { name: 'ABC', kind: 'polygon', vertices: ['A', 'B', 'C'] },\n { name: 'BC', kind: 'segment', p1: 'B', p2: 'C' },\n { name: 'incircle', kind: 'circleCP', center: 'I', surfacePoint: 'D' },\n ],\n },\n};\n","// src/stamps/geometry-2d/dsl/fixtures/parallelogram.ts\nimport type { DslInputT } from '../schema';\n\nexport const fixture: { problem: string; dsl: DslInputT } = {\n problem: 'Hình bình hành ABCD, hai đường chéo AC, BD cắt nhau tại O.',\n dsl: {\n version: 1,\n points: [\n { name: 'A', kind: 'free', x: 0, y: 0 },\n { name: 'B', kind: 'free', x: 4, y: 0 },\n { name: 'C', kind: 'free', x: 5, y: 2 },\n { name: 'D', kind: 'free', x: 1, y: 2 },\n { name: 'O', kind: 'intersection', ref1: 'AC', ref2: 'BD' },\n ],\n shapes: [\n { name: 'ABCD', kind: 'polygon', vertices: ['A', 'B', 'C', 'D'] },\n { name: 'AC', kind: 'segment', p1: 'A', p2: 'C' },\n { name: 'BD', kind: 'segment', p1: 'B', p2: 'D' },\n ],\n },\n};\n","// src/stamps/geometry-2d/dsl/fixtures/two-circles-intersect.ts\nimport type { DslInputT } from '../schema';\n\nexport const fixture: { problem: string; dsl: DslInputT } = {\n problem: 'Hai đường tròn (O₁), (O₂) cắt nhau tại P, Q.',\n dsl: {\n version: 1,\n points: [\n { name: 'O1', kind: 'free', x: 0, y: 0 },\n { name: 'A1', kind: 'free', x: 2, y: 0 },\n { name: 'O2', kind: 'free', x: 3, y: 0 },\n { name: 'A2', kind: 'free', x: 5, y: 0 },\n { name: 'P', kind: 'intersection', ref1: 'k1', ref2: 'k2', branch: 0 },\n { name: 'Q', kind: 'intersection', ref1: 'k1', ref2: 'k2', branch: 1 },\n ],\n shapes: [\n { name: 'k1', kind: 'circleCP', center: 'O1', surfacePoint: 'A1' },\n { name: 'k2', kind: 'circleCP', center: 'O2', surfacePoint: 'A2' },\n ],\n },\n};\n","// src/stamps/geometry-2d/ai/prompt.ts\nimport { fixture as eq } from '../dsl/fixtures/triangle-equilateral';\nimport { fixture as md } from '../dsl/fixtures/triangle-median';\nimport { fixture as alt } from '../dsl/fixtures/triangle-altitude';\nimport { fixture as ce } from '../dsl/fixtures/triangle-centroid';\nimport { fixture as oc } from '../dsl/fixtures/triangle-orthocenter';\nimport { fixture as cc } from '../dsl/fixtures/triangle-circumcircle';\nimport { fixture as ic } from '../dsl/fixtures/triangle-incircle';\nimport { fixture as par } from '../dsl/fixtures/parallelogram';\nimport { fixture as two } from '../dsl/fixtures/two-circles-intersect';\n\nconst FIXTURES = [eq, md, alt, ce, oc, cc, ic, par, two];\n\nexport function buildSystemPrompt(): string {\n const examples = FIXTURES.map((f, i) =>\n `### Ví dụ ${i + 1}\\n**Đề:** ${f.problem}\\n**DSL:**\\n\\`\\`\\`json\\n${JSON.stringify(f.dsl, null, 2)}\\n\\`\\`\\``,\n ).join('\\n\\n');\n\n return `Bạn là trợ lý vẽ hình học 2D cho học sinh THCS và lớp 10 Việt Nam.\n\n## Nhiệm vụ\nĐọc đề bài tiếng Việt → emit DSL JSON mô tả hình. Hệ thống sẽ render hình từ DSL.\n\n## Quy tắc\n1. Dùng tool \\`build_figure\\` khi vẽ được. Dùng tool \\`refuse\\` khi không vẽ được hoặc đề ngoài phạm vi (3D, lượng giác, phép biến hình lớp 11+, đại số).\n2. Ưu tiên derived points (midpoint, perpFoot, circumcenter, ...) thay vì tự compute toạ độ.\n3. Anchor (free) chỉ dùng cho điểm gốc (thường A, B, C của tam giác). Đặt coord hợp lý quanh gốc (-5..5).\n4. Mọi điểm + hình phải có \\`name\\` (label \"A\", \"M\", \"O₁\", ...). Tham chiếu bằng name, không phải id.\n5. Tam giác: emit cả \\`polygon\\` (vẽ viền) + segment/đường phụ riêng nếu đề yêu cầu (đường cao, trung tuyến).\n6. Đường tròn (O; R) cho trước bán kính số: emit anchor helper trên đường tròn rồi dùng \\`circleCP\\` (DSL không hỗ trợ radius numeric trực tiếp).\n7. Nếu đề mơ hồ: chọn case phổ biến nhất, không hỏi lại.\n\n## Primitives sẵn có\n**Points:** free, midpoint, onSegment, onLine, onCircle, perpFoot, circumcenter, incenter, centroid, orthocenter, intersection\n**Shapes:** segment, line, ray, polygon, perpendicular, parallel, perpBisector, angleBisector, tangent, circleCP, circle3\n\n## 9 ví dụ\n${examples}\n\n## Khi không vẽ được\nGọi \\`refuse\\` với \\`reason\\` tiếng Việt giải thích cụ thể (vd: \"Đề thuộc lớp 11, ngoài phạm vi MVP\" hoặc \"Đề không rõ vị trí điểm M\").`;\n}\n","// src/stamps/geometry-2d/ai/tools.ts\nimport { z } from 'zod';\nimport { zodToJsonSchema } from 'zod-to-json-schema';\nimport { DslInput } from '../dsl';\n\nexport const BUILD_FIGURE_TOOL = {\n name: 'build_figure',\n description: 'Vẽ hình học 2D theo đề bài. Emit DSL JSON mô tả các điểm và hình.',\n input_schema: zodToJsonSchema(DslInput, {\n target: 'jsonSchema7',\n $refStrategy: 'none',\n }),\n} as const;\n\nconst RefuseInputZ = z.object({\n reason: z.string().min(1).describe('Lý do không vẽ được (tiếng Việt)'),\n});\n\nexport const REFUSE_TOOL = {\n name: 'refuse',\n description: 'Từ chối khi không vẽ được hoặc đề ngoài phạm vi (3D, lượng giác, lớp 11+).',\n input_schema: zodToJsonSchema(RefuseInputZ, { target: 'jsonSchema7' }),\n} as const;\n\nexport const TOOLS = [BUILD_FIGURE_TOOL, REFUSE_TOOL];\n","// src/stamps/geometry-2d/ai/buildFigure.ts\nimport type { State as SceneState } from '../../../core/scene/types';\nimport type { DslInputT, TranspileError } from '../dsl';\nimport { transpile } from '../dsl';\nimport { callProvider, type ProviderResponse } from './provider';\nimport { buildSystemPrompt } from './prompt';\nimport { TOOLS } from './tools';\n\nconst DEFAULT_MODEL = 'claude-opus-4-7';\nconst DEFAULT_MAX_TOKENS = 8192;\n\nexport interface GenerateOptions {\n apiKey: string;\n model?: string;\n maxTokens?: number;\n enableCaching?: boolean;\n signal?: AbortSignal;\n}\n\nexport interface TokenUsage {\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens: number;\n cacheCreationTokens: number;\n}\n\nexport type GenerateResult =\n | { ok: true; state: SceneState; dsl: DslInputT; usage: TokenUsage }\n | { ok: false; reason: 'refused'; message: string; usage?: TokenUsage }\n | { ok: false; reason: 'parse_error'; message: string; raw?: unknown; usage?: TokenUsage }\n | { ok: false; reason: 'transpile_error'; message: string; errors: TranspileError[]; dsl: unknown; usage?: TokenUsage }\n | { ok: false; reason: 'api_error'; message: string; status?: number };\n\nfunction toUsage(u: ProviderResponse['usage']): TokenUsage {\n return {\n inputTokens: u.input_tokens,\n outputTokens: u.output_tokens,\n cacheReadTokens: u.cache_read_input_tokens ?? 0,\n cacheCreationTokens: u.cache_creation_input_tokens ?? 0,\n };\n}\n\nexport async function generateFigure(\n problem: string,\n opts: GenerateOptions,\n): Promise<GenerateResult> {\n if (!opts.apiKey) {\n return { ok: false, reason: 'api_error', message: 'apiKey bắt buộc' };\n }\n if (!problem || !problem.trim()) {\n return { ok: false, reason: 'api_error', message: 'Đề bài rỗng' };\n }\n\n const systemText = buildSystemPrompt();\n const enableCaching = opts.enableCaching !== false;\n const systemBlock = enableCaching\n ? { type: 'text' as const, text: systemText, cache_control: { type: 'ephemeral' as const } }\n : { type: 'text' as const, text: systemText };\n\n let response: ProviderResponse;\n try {\n response = await callProvider({\n apiKey: opts.apiKey,\n model: opts.model ?? DEFAULT_MODEL,\n maxTokens: opts.maxTokens ?? DEFAULT_MAX_TOKENS,\n system: [systemBlock],\n tools: TOOLS as never,\n toolChoice: { type: 'any' },\n messages: [{ role: 'user', content: problem }],\n signal: opts.signal,\n });\n } catch (e) {\n const err = e as { message?: string; status?: number };\n return {\n ok: false,\n reason: 'api_error',\n message: err.message ?? 'Lỗi gọi Claude API',\n ...(err.status !== undefined ? { status: err.status } : {}),\n };\n }\n\n const usage = toUsage(response.usage);\n\n const toolUse = response.content.find((c) => c.type === 'tool_use');\n if (!toolUse || toolUse.type !== 'tool_use') {\n const text = response.content.find((c) => c.type === 'text');\n const textStr = text?.type === 'text' ? text.text : '(empty)';\n return {\n ok: false,\n reason: 'parse_error',\n message: 'AI không gọi tool nào. Response: ' + textStr,\n raw: response.content,\n usage,\n };\n }\n\n if (toolUse.name === 'refuse') {\n const input = toolUse.input as { reason?: string };\n return {\n ok: false,\n reason: 'refused',\n message: input.reason ?? 'AI từ chối không nêu lý do',\n usage,\n };\n }\n\n if (toolUse.name !== 'build_figure') {\n return {\n ok: false,\n reason: 'parse_error',\n message: `Tool không xác định: \"${toolUse.name}\"`,\n raw: toolUse,\n usage,\n };\n }\n\n const tResult = transpile(toolUse.input);\n if (!tResult.ok) {\n return {\n ok: false,\n reason: 'transpile_error',\n message: 'DSL từ AI không hợp lệ',\n errors: tResult.errors,\n dsl: toolUse.input,\n usage,\n };\n }\n\n return {\n ok: true,\n state: tResult.state,\n dsl: toolUse.input as DslInputT,\n usage,\n };\n}\n"]}
|