@xom11/whiteboard 0.30.0 → 0.31.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/dist/ai.d.mts +226 -32
- package/dist/ai.d.ts +226 -32
- package/dist/ai.js +5126 -351
- package/dist/ai.js.map +1 -1
- package/dist/ai.mjs +4970 -352
- package/dist/ai.mjs.map +1 -1
- package/dist/catalog.json +5 -5
- package/dist/{chunk-V3YJ6JFL.mjs → chunk-44JY2AKC.mjs} +3 -3
- package/dist/{chunk-V3YJ6JFL.mjs.map → chunk-44JY2AKC.mjs.map} +1 -1
- package/dist/{chunk-XVVLT6B3.mjs → chunk-BMYC2ILT.mjs} +4 -4
- package/dist/{chunk-XVVLT6B3.mjs.map → chunk-BMYC2ILT.mjs.map} +1 -1
- package/dist/{chunk-PPKHCRRE.mjs → chunk-C76SOFXF.mjs} +3 -3
- package/dist/{chunk-PPKHCRRE.mjs.map → chunk-C76SOFXF.mjs.map} +1 -1
- package/dist/{chunk-IHUFOV7L.mjs → chunk-CH6SFONH.mjs} +15 -3
- package/dist/chunk-CH6SFONH.mjs.map +1 -0
- package/dist/{chunk-SF3U7ZF4.mjs → chunk-DWIEVCGK.mjs} +180 -15
- package/dist/chunk-DWIEVCGK.mjs.map +1 -0
- package/dist/{chunk-SZDAS7LK.mjs → chunk-IE2GGHNF.mjs} +131 -81
- package/dist/chunk-IE2GGHNF.mjs.map +1 -0
- package/dist/{chunk-ZTQBUKLJ.mjs → chunk-JJ4FPCBE.mjs} +142 -22
- package/dist/chunk-JJ4FPCBE.mjs.map +1 -0
- package/dist/{chunk-QRUAEXLR.mjs → chunk-K5BS2H56.mjs} +5 -5
- package/dist/{chunk-QRUAEXLR.mjs.map → chunk-K5BS2H56.mjs.map} +1 -1
- package/dist/{chunk-BNBOIDO5.mjs → chunk-K7VJU7LQ.mjs} +3 -3
- package/dist/{chunk-BNBOIDO5.mjs.map → chunk-K7VJU7LQ.mjs.map} +1 -1
- package/dist/{chunk-H22OZYTW.mjs → chunk-KOXOC2FI.mjs} +48 -39
- package/dist/chunk-KOXOC2FI.mjs.map +1 -0
- package/dist/{chunk-CXHNVYMD.mjs → chunk-KWDBVLST.mjs} +5 -5
- package/dist/{chunk-CXHNVYMD.mjs.map → chunk-KWDBVLST.mjs.map} +1 -1
- package/dist/{chunk-OQIQNKPQ.mjs → chunk-LTLLQUMN.mjs} +4 -4
- package/dist/{chunk-OQIQNKPQ.mjs.map → chunk-LTLLQUMN.mjs.map} +1 -1
- package/dist/{chunk-QGNU34T7.mjs → chunk-QLQ4MJNO.mjs} +10 -4
- package/dist/chunk-QLQ4MJNO.mjs.map +1 -0
- package/dist/{chunk-BU5KLO3P.mjs → chunk-T3N4BSJV.mjs} +4 -4
- package/dist/{chunk-BU5KLO3P.mjs.map → chunk-T3N4BSJV.mjs.map} +1 -1
- package/dist/{chunk-5JM35CXV.mjs → chunk-TMRFSOM7.mjs} +4 -4
- package/dist/{chunk-5JM35CXV.mjs.map → chunk-TMRFSOM7.mjs.map} +1 -1
- package/dist/geometry-2d.d.mts +1 -1
- package/dist/geometry-2d.d.ts +1 -1
- package/dist/geometry-2d.js +449 -172
- package/dist/geometry-2d.js.map +1 -1
- package/dist/geometry-2d.mjs +5 -5
- package/dist/geometry-3d.d.mts +1 -1
- package/dist/geometry-3d.d.ts +1 -1
- package/dist/geometry-3d.js +172 -22
- package/dist/geometry-3d.js.map +1 -1
- package/dist/geometry-3d.mjs +4 -4
- package/dist/graph-2d.d.mts +1 -1
- package/dist/graph-2d.d.ts +1 -1
- package/dist/graph-2d.js +307 -100
- package/dist/graph-2d.js.map +1 -1
- package/dist/graph-2d.mjs +7 -7
- package/dist/{host-HOSJHQ5H.mjs → host-4FIUNIDQ.mjs} +13 -12
- package/dist/host-4FIUNIDQ.mjs.map +1 -0
- package/dist/{host-2ISGVO7O.mjs → host-4ZB4XD4S.mjs} +9 -8
- package/dist/host-4ZB4XD4S.mjs.map +1 -0
- package/dist/{host-ZQCDAT6O.mjs → host-H2IGOKJU.mjs} +3 -3
- package/dist/{host-ZQCDAT6O.mjs.map → host-H2IGOKJU.mjs.map} +1 -1
- package/dist/{host-3UFGFMJ2.mjs → host-KMWP7KBT.mjs} +90 -43
- package/dist/host-KMWP7KBT.mjs.map +1 -0
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +453 -174
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +21 -21
- package/dist/latex.d.mts +1 -1
- package/dist/latex.d.ts +1 -1
- package/dist/latex.js +8 -2
- package/dist/latex.js.map +1 -1
- package/dist/latex.mjs +1 -1
- package/dist/render-NMS7OAV6.mjs +10 -0
- package/dist/{render-ZX2O2IK7.mjs.map → render-NMS7OAV6.mjs.map} +1 -1
- package/dist/serialize-PGHQZEPV.mjs +9 -0
- package/dist/{serialize-N4G6RFBB.mjs.map → serialize-PGHQZEPV.mjs.map} +1 -1
- package/dist/{types-C3FjpoUi.d.ts → types-tePd94vW.d.mts} +8 -0
- package/dist/{types-C3FjpoUi.d.mts → types-tePd94vW.d.ts} +8 -0
- package/package.json +1 -1
- package/dist/chunk-H22OZYTW.mjs.map +0 -1
- package/dist/chunk-IHUFOV7L.mjs.map +0 -1
- package/dist/chunk-QGNU34T7.mjs.map +0 -1
- package/dist/chunk-SF3U7ZF4.mjs.map +0 -1
- package/dist/chunk-SZDAS7LK.mjs.map +0 -1
- package/dist/chunk-ZTQBUKLJ.mjs.map +0 -1
- package/dist/host-2ISGVO7O.mjs.map +0 -1
- package/dist/host-3UFGFMJ2.mjs.map +0 -1
- package/dist/host-HOSJHQ5H.mjs.map +0 -1
- package/dist/render-ZX2O2IK7.mjs +0 -10
- package/dist/serialize-N4G6RFBB.mjs +0 -9
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/stamps/latex/editor/LeftPanel.tsx","../src/stamps/latex/editor/EditorPopover.tsx","../src/stamps/latex/host.tsx"],"names":["EditorPopover","jsxs","jsx","forwardRef","LatexStampHost","useRef","useState","useCallback","useImperativeHandle","Fragment"],"mappings":"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","file":"host-ZQCDAT6O.mjs","sourcesContent":["'use client';\n\nimport React from 'react';\n\n// ---------- Shared shell (latex copy — geometry copy stays in src/stamp/StampLeftPanel.tsx) ----------\n\ninterface ShellProps {\n title: string;\n icon: React.ReactNode;\n onClose: () => void;\n children: React.ReactNode;\n isMobile?: boolean;\n drawerOpen?: boolean;\n onDrawerClose?: () => void;\n}\n\nfunction Shell({ title, icon, onClose, children, isMobile, drawerOpen, onDrawerClose }: ShellProps) {\n const mobileAttrs = isMobile\n ? {\n 'data-mobile-drawer': 'true',\n 'data-drawer-state': drawerOpen ? 'open' : 'closed',\n }\n : {};\n const handleHeaderClose = () => {\n if (isMobile) onDrawerClose?.();\n else onClose();\n };\n return (\n <>\n {isMobile && drawerOpen && (\n <div\n className=\"stamp-drawer-backdrop\"\n onPointerDown={onDrawerClose}\n aria-hidden=\"true\"\n />\n )}\n <aside\n role=\"complementary\"\n aria-label={title}\n aria-hidden={isMobile && !drawerOpen ? 'true' : undefined}\n data-testid=\"stamp-left-panel\"\n data-stamp-area=\"true\"\n {...mobileAttrs}\n className={\n isMobile\n ? 'stamp-drawer-mobile flex flex-col border-r border-slate-200 bg-white shadow-md'\n : 'absolute left-0 top-0 z-30 flex h-full w-60 flex-col border-r border-slate-200 bg-white shadow-md animate-in slide-in-from-left duration-200'\n }\n >\n <header className=\"flex items-center justify-between border-b border-slate-200 bg-gradient-to-r from-slate-50 to-white px-3 py-2\">\n <h3 className=\"flex items-center gap-2 text-sm font-semibold text-slate-800\">\n <span className=\"text-base leading-none\">{icon}</span>\n {title}\n </h3>\n <button\n onClick={handleHeaderClose}\n aria-label={isMobile ? 'Đóng ngăn công cụ' : 'Đóng'}\n className=\"rounded p-1 text-slate-500 transition hover:bg-slate-100 hover:text-slate-800\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n </svg>\n </button>\n </header>\n <div className=\"min-h-0 flex-1 overflow-y-auto p-3 space-y-4\">{children}</div>\n </aside>\n </>\n );\n}\n\nfunction Section({ label, children }: { label: string; children: React.ReactNode }) {\n return (\n <section>\n <h4 className=\"mb-1.5 text-[10px] font-semibold uppercase tracking-wider text-slate-500\">\n {label}\n </h4>\n {children}\n </section>\n );\n}\n\n// ---------- LaTeX left panel ----------\n\ninterface LatexLeftPanelProps {\n displayMode: boolean;\n onDisplayModeChange: (b: boolean) => void;\n onInsertSnippet: (snippet: string) => void;\n onClose: () => void;\n isMobile?: boolean;\n drawerOpen?: boolean;\n onDrawerClose?: () => void;\n}\n\ninterface SnippetDef {\n label: string;\n preview: string;\n snippet: string;\n}\n\nconst SNIPPETS: { group: string; items: SnippetDef[] }[] = [\n {\n group: 'Phân số & luỹ thừa',\n items: [\n { label: 'Phân số', preview: 'a⁄b', snippet: '\\\\frac{a}{b}' },\n { label: 'Luỹ thừa', preview: 'x²', snippet: '^{2}' },\n { label: 'Chỉ số', preview: 'x₁', snippet: '_{1}' },\n { label: 'Căn', preview: '√x', snippet: '\\\\sqrt{x}' },\n { label: 'Căn n', preview: 'ⁿ√x', snippet: '\\\\sqrt[n]{x}' },\n ],\n },\n {\n group: 'Tổng & tích phân',\n items: [\n { label: 'Tổng', preview: 'Σ', snippet: '\\\\sum_{i=1}^{n}' },\n { label: 'Tích', preview: 'Π', snippet: '\\\\prod_{i=1}^{n}' },\n { label: 'Tích phân', preview: '∫', snippet: '\\\\int_{a}^{b}' },\n { label: 'Giới hạn', preview: 'lim', snippet: '\\\\lim_{x \\\\to 0}' },\n ],\n },\n {\n group: 'Ký hiệu',\n items: [\n { label: 'α', preview: 'α', snippet: '\\\\alpha' },\n { label: 'β', preview: 'β', snippet: '\\\\beta' },\n { label: 'π', preview: 'π', snippet: '\\\\pi' },\n { label: 'θ', preview: 'θ', snippet: '\\\\theta' },\n { label: '≠', preview: '≠', snippet: '\\\\neq' },\n { label: '≤', preview: '≤', snippet: '\\\\leq' },\n { label: '≥', preview: '≥', snippet: '\\\\geq' },\n { label: '∞', preview: '∞', snippet: '\\\\infty' },\n { label: '→', preview: '→', snippet: '\\\\to' },\n ],\n },\n];\n\nexport function LeftPanel({\n displayMode,\n onDisplayModeChange,\n onInsertSnippet,\n onClose,\n isMobile,\n drawerOpen,\n onDrawerClose,\n}: LatexLeftPanelProps) {\n return (\n <Shell\n title=\"Công thức LaTeX\"\n icon=\"∑\"\n onClose={onClose}\n isMobile={isMobile}\n drawerOpen={drawerOpen}\n onDrawerClose={onDrawerClose}\n >\n <Section label=\"Chế độ hiển thị\">\n <div className=\"grid grid-cols-2 gap-1.5\">\n <button\n type=\"button\"\n onClick={() => onDisplayModeChange(false)}\n aria-pressed={!displayMode}\n className={[\n 'rounded-md border px-2 py-1.5 text-xs transition',\n !displayMode\n ? 'border-emerald-500 bg-emerald-50 text-emerald-700 ring-1 ring-emerald-300'\n : 'border-slate-200 bg-white text-slate-700 hover:border-slate-300 hover:bg-slate-50',\n ].join(' ')}\n >\n <span className=\"block font-medium\">Inline</span>\n <span className=\"block text-[10px] text-slate-500\">$ ... $</span>\n </button>\n <button\n type=\"button\"\n onClick={() => onDisplayModeChange(true)}\n aria-pressed={displayMode}\n className={[\n 'rounded-md border px-2 py-1.5 text-xs transition',\n displayMode\n ? 'border-emerald-500 bg-emerald-50 text-emerald-700 ring-1 ring-emerald-300'\n : 'border-slate-200 bg-white text-slate-700 hover:border-slate-300 hover:bg-slate-50',\n ].join(' ')}\n >\n <span className=\"block font-medium\">Block</span>\n <span className=\"block text-[10px] text-slate-500\">$$ ... $$</span>\n </button>\n </div>\n </Section>\n\n {SNIPPETS.map((group) => (\n <Section key={group.group} label={group.group}>\n <div className=\"flex flex-wrap gap-1\">\n {group.items.map((s) => (\n <button\n key={s.snippet}\n type=\"button\"\n data-snippet={s.snippet}\n onClick={() => onInsertSnippet(s.snippet)}\n title={s.snippet}\n className=\"rounded border border-slate-200 bg-white px-2 py-1 text-xs text-slate-700 transition hover:border-emerald-300 hover:bg-emerald-50 hover:text-emerald-700\"\n >\n {s.preview}\n </button>\n ))}\n </div>\n </Section>\n ))}\n\n <Section label=\"Phím tắt\">\n <div className=\"flex flex-wrap gap-2 text-[11px] text-slate-600\">\n <span className=\"inline-flex items-center gap-1\">\n <kbd className=\"rounded border border-slate-300 bg-slate-50 px-1.5 py-0.5 font-mono\">Enter</kbd>\n chèn\n </span>\n <span className=\"inline-flex items-center gap-1\">\n <kbd className=\"rounded border border-slate-300 bg-slate-50 px-1.5 py-0.5 font-mono\">Esc</kbd>\n đóng\n </span>\n </div>\n </Section>\n </Shell>\n );\n}\n\n// Back-compat alias\nexport { LeftPanel as LatexLeftPanel };\n","'use client';\nimport React, {\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useRef,\n useState,\n} from 'react';\nimport { renderLatexToSvg } from '../render';\n\ninterface Props {\n /**\n * Legacy: vị trí absolute x/y nếu cần (test). Khi cả 2 = 0 và `centered` !== false,\n * popover sẽ tự center floating ở giữa khu vực bảng. Khi `withLeftPanel` = true,\n * vị trí center được offset 120px để chừa chỗ panel trái.\n */\n x: number;\n y: number;\n initialValue: string;\n onInsert: (svgString: string, src: string, displayMode: boolean) => void;\n onClose: () => void;\n /** Khi controlled từ parent (StampLeftPanel), parent set giá trị này. */\n displayMode?: boolean;\n onDisplayModeChange?: (b: boolean) => void;\n /** Khi true, position center offset cho panel trái. */\n withLeftPanel?: boolean;\n /** Mobile mode: full-screen + hamburger header. */\n isMobile?: boolean;\n /** Trigger mở snippet drawer trên mobile. */\n onOpenDrawer?: () => void;\n}\n\nexport interface EditorPopoverHandle {\n /** Chèn snippet vào vị trí con trỏ trong textbox. */\n insertAtCursor: (snippet: string) => void;\n /** Có content hợp lệ để chèn không (input không rỗng + preview ok). */\n hasContent: () => boolean;\n /** Trigger insert programmatically — return true nếu chèn thành công. */\n tryInsert: () => boolean;\n}\n\nconst DEBOUNCE_MS = 100;\n\nexport const EditorPopover = forwardRef<EditorPopoverHandle, Props>(function EditorPopover(\n {\n x,\n y,\n initialValue,\n onInsert,\n onClose,\n displayMode: controlledDisplayMode,\n onDisplayModeChange,\n withLeftPanel = false,\n isMobile = false,\n onOpenDrawer,\n },\n ref,\n) {\n const [value, setValue] = useState(initialValue);\n const [internalDisplayMode] = useState(false);\n const displayMode = controlledDisplayMode ?? internalDisplayMode;\n // onDisplayModeChange chỉ dùng khi controlled từ parent — không cần local setter\n void onDisplayModeChange;\n\n const [previewSvg, setPreviewSvg] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const inputRef = useRef<HTMLInputElement>(null);\n\n useEffect(() => {\n if (debounceRef.current) clearTimeout(debounceRef.current);\n debounceRef.current = setTimeout(async () => {\n try {\n const svg = await renderLatexToSvg(value, displayMode);\n setPreviewSvg(svg);\n setError(null);\n } catch (err) {\n setPreviewSvg(null);\n setError((err as Error).message);\n }\n }, DEBOUNCE_MS);\n return () => {\n if (debounceRef.current) clearTimeout(debounceRef.current);\n };\n }, [value, displayMode]);\n\n const handleInsert = useCallback(() => {\n if (!previewSvg) return;\n onInsert(previewSvg, value, displayMode);\n }, [previewSvg, value, displayMode, onInsert]);\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (e.key === 'Escape') onClose();\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n handleInsert();\n }\n },\n [onClose, handleInsert],\n );\n\n // Imperative API: snippet button trong panel trái gọi vào, click-outside auto-insert.\n useImperativeHandle(\n ref,\n () => ({\n insertAtCursor: (snippet: string) => {\n const el = inputRef.current;\n if (!el) {\n setValue((v) => v + snippet);\n return;\n }\n const start = el.selectionStart ?? value.length;\n const end = el.selectionEnd ?? value.length;\n const next = value.slice(0, start) + snippet + value.slice(end);\n setValue(next);\n requestAnimationFrame(() => {\n el.focus();\n const pos = start + snippet.length;\n try {\n el.setSelectionRange(pos, pos);\n } catch {\n /* ignore */\n }\n });\n },\n hasContent: () => value.trim().length > 0 && !!previewSvg && !error,\n tryInsert: () => {\n if (!previewSvg || error || !value.trim()) return false;\n onInsert(previewSvg, value, displayMode);\n return true;\n },\n }),\n [value, previewSvg, error, displayMode, onInsert],\n );\n\n // Position: nếu x/y > 0 → dùng legacy absolute (cho tests cũ). Còn không thì center floating.\n const isLegacyPosition = x > 0 || y > 0;\n const wrapperStyle: React.CSSProperties = isMobile\n ? { position: 'fixed', inset: 0, zIndex: 50 }\n : isLegacyPosition\n ? { position: 'absolute', top: y, left: x, zIndex: 50 }\n : {\n position: 'absolute',\n top: '50%',\n left: withLeftPanel ? 'calc(50% + 120px)' : '50%',\n transform: 'translate(-50%, -50%)',\n zIndex: 50,\n };\n\n return (\n <div\n style={wrapperStyle}\n data-stamp-area=\"true\"\n data-mobile-editor={isMobile ? 'true' : undefined}\n className={\n isMobile\n ? 'flex h-full w-full flex-col bg-white'\n : 'w-[420px] max-w-[calc(100vw-280px)] rounded-lg border border-slate-300 bg-white shadow-2xl ring-1 ring-black/5'\n }\n role=\"dialog\"\n aria-label=\"Nhập công thức LaTeX\"\n >\n <header className={`flex items-center gap-2 border-b border-slate-200 bg-gradient-to-r from-indigo-600 to-purple-600 px-3 py-2 text-white${isMobile ? '' : ' rounded-t-lg'}`}>\n {isMobile && (\n <button\n type=\"button\"\n onClick={onOpenDrawer}\n aria-label=\"Mở ngăn snippet\"\n className=\"-ml-1 inline-flex h-10 w-10 items-center justify-center rounded transition hover:bg-white/15\"\n >\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <line x1=\"4\" y1=\"6\" x2=\"20\" y2=\"6\" />\n <line x1=\"4\" y1=\"12\" x2=\"20\" y2=\"12\" />\n <line x1=\"4\" y1=\"18\" x2=\"20\" y2=\"18\" />\n </svg>\n </button>\n )}\n <h3 className=\"flex flex-1 items-center gap-2 text-sm font-semibold\">\n <span className=\"text-base leading-none\">∑</span>\n Công thức LaTeX\n </h3>\n {isMobile && (\n <button\n type=\"button\"\n onClick={handleInsert}\n disabled={!previewSvg || !!error}\n data-testid=\"latex-insert-btn-mobile\"\n className=\"rounded bg-white/15 px-3 py-1.5 text-xs font-semibold transition hover:bg-white/25 disabled:opacity-50\"\n >\n Chèn\n </button>\n )}\n <button\n onClick={onClose}\n aria-label=\"Đóng\"\n className=\"inline-flex h-9 w-9 items-center justify-center rounded transition hover:bg-white/15\"\n >\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n </svg>\n </button>\n </header>\n <div className={`space-y-2 p-3${isMobile ? ' flex min-h-0 flex-1 flex-col' : ''}`}>\n <input\n ref={inputRef}\n type=\"text\"\n role=\"textbox\"\n value={value}\n onChange={(e) => setValue(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder=\"Vd: \\frac{a^2+b^2}{c}\"\n className={`w-full rounded border border-slate-300 px-2 py-1.5 font-mono outline-none focus:border-indigo-400 focus:ring-2 focus:ring-indigo-200${\n isMobile ? ' min-h-[44px] text-base' : ' text-sm'\n }`}\n autoFocus\n />\n <div\n className={[\n 'flex items-center justify-center rounded border p-3 text-center',\n isMobile ? 'min-h-0 flex-1 overflow-auto' : 'min-h-[64px]',\n error ? 'border-rose-300 bg-rose-50 text-rose-700' : 'border-slate-200 bg-slate-50',\n ].join(' ')}\n >\n {error ? (\n <span className=\"text-xs\">Lỗi: {error.slice(0, 80)}</span>\n ) : previewSvg ? (\n <span dangerouslySetInnerHTML={{ __html: previewSvg }} />\n ) : (\n <span className=\"text-xs text-slate-400\">(xem trước)</span>\n )}\n </div>\n {!isMobile && (\n <div className=\"flex items-center justify-between\">\n <span className=\"text-[11px] text-slate-500\">\n {displayMode ? 'Block' : 'Inline'} · Enter để chèn\n </span>\n <div className=\"flex gap-2\">\n <button\n onClick={onClose}\n className=\"rounded border border-slate-300 bg-white px-3 py-1 text-xs font-medium text-slate-700 transition hover:bg-slate-100\"\n >\n Huỷ\n </button>\n <button\n onClick={handleInsert}\n disabled={!previewSvg || !!error}\n className=\"rounded bg-indigo-600 px-3 py-1 text-xs font-medium text-white transition hover:bg-indigo-700 disabled:opacity-50\"\n >\n Chèn\n </button>\n </div>\n </div>\n )}\n {isMobile && (\n <div className=\"text-center text-[11px] text-slate-500\">\n {displayMode ? 'Block' : 'Inline'} · Bấm Chèn ở thanh trên\n </div>\n )}\n </div>\n </div>\n );\n});\n\n// Back-compat aliases\nexport { EditorPopover as LatexEditorPopover };\nexport type { EditorPopoverHandle as LatexEditorHandle };\n","'use client';\n\nimport {\n forwardRef,\n useCallback,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { LeftPanel as LatexLeftPanel } from './editor/LeftPanel';\nimport {\n EditorPopover as LatexEditorPopover,\n type EditorPopoverHandle as LatexEditorHandle,\n} from './editor/EditorPopover';\nimport { insertStampImage } from '../shared/insertImage';\nimport { useIsMobile } from '../shared/useIsMobile';\nimport { isLatexCustomData, type LatexCustomData } from './types';\nimport type { StampHostProps, StampHostHandle } from '../shared/types';\n\nexport const LatexStampHost = forwardRef<StampHostHandle, StampHostProps>(\n function LatexStampHost({ api, editingElement, onClose }, ref) {\n const editorRef = useRef<LatexEditorHandle | null>(null);\n const { isMobile } = useIsMobile();\n const [drawerOpen, setDrawerOpen] = useState(false);\n\n const initial = useMemo(() => {\n if (editingElement && isLatexCustomData(editingElement.customData)) {\n return {\n initialValue: editingElement.customData.src,\n displayMode: !!editingElement.customData.displayMode,\n };\n }\n return { initialValue: '', displayMode: false };\n }, [editingElement]);\n\n const [displayMode, setDisplayMode] = useState(initial.displayMode);\n\n const handleInsert = useCallback(\n async (svgString: string, src: string, dm: boolean) => {\n if (!api) return;\n try {\n await insertStampImage(api, {\n svgString,\n makeCustomData: (): LatexCustomData => ({\n kind: 'latex',\n version: 1,\n src,\n displayMode: dm,\n }),\n editingElementId: editingElement?.id ?? null,\n });\n } catch (err) {\n console.error('Latex insert failed:', err);\n }\n onClose();\n },\n [api, editingElement?.id, onClose],\n );\n\n useImperativeHandle(\n ref,\n () => ({\n tryInsert: () => editorRef.current?.tryInsert() ?? false,\n hasContent: () => editorRef.current?.hasContent() ?? false,\n }),\n [],\n );\n\n return (\n <>\n <LatexLeftPanel\n displayMode={displayMode}\n onDisplayModeChange={setDisplayMode}\n onInsertSnippet={(s) => editorRef.current?.insertAtCursor(s)}\n onClose={onClose}\n isMobile={isMobile}\n drawerOpen={drawerOpen}\n onDrawerClose={() => setDrawerOpen(false)}\n />\n <LatexEditorPopover\n ref={editorRef}\n x={0}\n y={0}\n initialValue={initial.initialValue}\n displayMode={displayMode}\n onDisplayModeChange={setDisplayMode}\n onInsert={handleInsert}\n onClose={onClose}\n withLeftPanel={!isMobile}\n isMobile={isMobile}\n onOpenDrawer={() => setDrawerOpen(true)}\n />\n </>\n );\n },\n);\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/stamps/latex/editor/LeftPanel.tsx","../src/stamps/latex/editor/EditorPopover.tsx","../src/stamps/latex/host.tsx"],"names":["EditorPopover","jsxs","jsx","forwardRef","LatexStampHost","useRef","useState","useCallback","useImperativeHandle","Fragment"],"mappings":"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","file":"host-H2IGOKJU.mjs","sourcesContent":["'use client';\n\nimport React from 'react';\n\n// ---------- Shared shell (latex copy — geometry copy stays in src/stamp/StampLeftPanel.tsx) ----------\n\ninterface ShellProps {\n title: string;\n icon: React.ReactNode;\n onClose: () => void;\n children: React.ReactNode;\n isMobile?: boolean;\n drawerOpen?: boolean;\n onDrawerClose?: () => void;\n}\n\nfunction Shell({ title, icon, onClose, children, isMobile, drawerOpen, onDrawerClose }: ShellProps) {\n const mobileAttrs = isMobile\n ? {\n 'data-mobile-drawer': 'true',\n 'data-drawer-state': drawerOpen ? 'open' : 'closed',\n }\n : {};\n const handleHeaderClose = () => {\n if (isMobile) onDrawerClose?.();\n else onClose();\n };\n return (\n <>\n {isMobile && drawerOpen && (\n <div\n className=\"stamp-drawer-backdrop\"\n onPointerDown={onDrawerClose}\n aria-hidden=\"true\"\n />\n )}\n <aside\n role=\"complementary\"\n aria-label={title}\n aria-hidden={isMobile && !drawerOpen ? 'true' : undefined}\n data-testid=\"stamp-left-panel\"\n data-stamp-area=\"true\"\n {...mobileAttrs}\n className={\n isMobile\n ? 'stamp-drawer-mobile flex flex-col border-r border-slate-200 bg-white shadow-md'\n : 'absolute left-0 top-0 z-30 flex h-full w-60 flex-col border-r border-slate-200 bg-white shadow-md animate-in slide-in-from-left duration-200'\n }\n >\n <header className=\"flex items-center justify-between border-b border-slate-200 bg-gradient-to-r from-slate-50 to-white px-3 py-2\">\n <h3 className=\"flex items-center gap-2 text-sm font-semibold text-slate-800\">\n <span className=\"text-base leading-none\">{icon}</span>\n {title}\n </h3>\n <button\n onClick={handleHeaderClose}\n aria-label={isMobile ? 'Đóng ngăn công cụ' : 'Đóng'}\n className=\"rounded p-1 text-slate-500 transition hover:bg-slate-100 hover:text-slate-800\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n </svg>\n </button>\n </header>\n <div className=\"min-h-0 flex-1 overflow-y-auto p-3 space-y-4\">{children}</div>\n </aside>\n </>\n );\n}\n\nfunction Section({ label, children }: { label: string; children: React.ReactNode }) {\n return (\n <section>\n <h4 className=\"mb-1.5 text-[10px] font-semibold uppercase tracking-wider text-slate-500\">\n {label}\n </h4>\n {children}\n </section>\n );\n}\n\n// ---------- LaTeX left panel ----------\n\ninterface LatexLeftPanelProps {\n displayMode: boolean;\n onDisplayModeChange: (b: boolean) => void;\n onInsertSnippet: (snippet: string) => void;\n onClose: () => void;\n isMobile?: boolean;\n drawerOpen?: boolean;\n onDrawerClose?: () => void;\n}\n\ninterface SnippetDef {\n label: string;\n preview: string;\n snippet: string;\n}\n\nconst SNIPPETS: { group: string; items: SnippetDef[] }[] = [\n {\n group: 'Phân số & luỹ thừa',\n items: [\n { label: 'Phân số', preview: 'a⁄b', snippet: '\\\\frac{a}{b}' },\n { label: 'Luỹ thừa', preview: 'x²', snippet: '^{2}' },\n { label: 'Chỉ số', preview: 'x₁', snippet: '_{1}' },\n { label: 'Căn', preview: '√x', snippet: '\\\\sqrt{x}' },\n { label: 'Căn n', preview: 'ⁿ√x', snippet: '\\\\sqrt[n]{x}' },\n ],\n },\n {\n group: 'Tổng & tích phân',\n items: [\n { label: 'Tổng', preview: 'Σ', snippet: '\\\\sum_{i=1}^{n}' },\n { label: 'Tích', preview: 'Π', snippet: '\\\\prod_{i=1}^{n}' },\n { label: 'Tích phân', preview: '∫', snippet: '\\\\int_{a}^{b}' },\n { label: 'Giới hạn', preview: 'lim', snippet: '\\\\lim_{x \\\\to 0}' },\n ],\n },\n {\n group: 'Ký hiệu',\n items: [\n { label: 'α', preview: 'α', snippet: '\\\\alpha' },\n { label: 'β', preview: 'β', snippet: '\\\\beta' },\n { label: 'π', preview: 'π', snippet: '\\\\pi' },\n { label: 'θ', preview: 'θ', snippet: '\\\\theta' },\n { label: '≠', preview: '≠', snippet: '\\\\neq' },\n { label: '≤', preview: '≤', snippet: '\\\\leq' },\n { label: '≥', preview: '≥', snippet: '\\\\geq' },\n { label: '∞', preview: '∞', snippet: '\\\\infty' },\n { label: '→', preview: '→', snippet: '\\\\to' },\n ],\n },\n];\n\nexport function LeftPanel({\n displayMode,\n onDisplayModeChange,\n onInsertSnippet,\n onClose,\n isMobile,\n drawerOpen,\n onDrawerClose,\n}: LatexLeftPanelProps) {\n return (\n <Shell\n title=\"Công thức LaTeX\"\n icon=\"∑\"\n onClose={onClose}\n isMobile={isMobile}\n drawerOpen={drawerOpen}\n onDrawerClose={onDrawerClose}\n >\n <Section label=\"Chế độ hiển thị\">\n <div className=\"grid grid-cols-2 gap-1.5\">\n <button\n type=\"button\"\n onClick={() => onDisplayModeChange(false)}\n aria-pressed={!displayMode}\n className={[\n 'rounded-md border px-2 py-1.5 text-xs transition',\n !displayMode\n ? 'border-emerald-500 bg-emerald-50 text-emerald-700 ring-1 ring-emerald-300'\n : 'border-slate-200 bg-white text-slate-700 hover:border-slate-300 hover:bg-slate-50',\n ].join(' ')}\n >\n <span className=\"block font-medium\">Inline</span>\n <span className=\"block text-[10px] text-slate-500\">$ ... $</span>\n </button>\n <button\n type=\"button\"\n onClick={() => onDisplayModeChange(true)}\n aria-pressed={displayMode}\n className={[\n 'rounded-md border px-2 py-1.5 text-xs transition',\n displayMode\n ? 'border-emerald-500 bg-emerald-50 text-emerald-700 ring-1 ring-emerald-300'\n : 'border-slate-200 bg-white text-slate-700 hover:border-slate-300 hover:bg-slate-50',\n ].join(' ')}\n >\n <span className=\"block font-medium\">Block</span>\n <span className=\"block text-[10px] text-slate-500\">$$ ... $$</span>\n </button>\n </div>\n </Section>\n\n {SNIPPETS.map((group) => (\n <Section key={group.group} label={group.group}>\n <div className=\"flex flex-wrap gap-1\">\n {group.items.map((s) => (\n <button\n key={s.snippet}\n type=\"button\"\n data-snippet={s.snippet}\n onClick={() => onInsertSnippet(s.snippet)}\n title={s.snippet}\n className=\"rounded border border-slate-200 bg-white px-2 py-1 text-xs text-slate-700 transition hover:border-emerald-300 hover:bg-emerald-50 hover:text-emerald-700\"\n >\n {s.preview}\n </button>\n ))}\n </div>\n </Section>\n ))}\n\n <Section label=\"Phím tắt\">\n <div className=\"flex flex-wrap gap-2 text-[11px] text-slate-600\">\n <span className=\"inline-flex items-center gap-1\">\n <kbd className=\"rounded border border-slate-300 bg-slate-50 px-1.5 py-0.5 font-mono\">Enter</kbd>\n chèn\n </span>\n <span className=\"inline-flex items-center gap-1\">\n <kbd className=\"rounded border border-slate-300 bg-slate-50 px-1.5 py-0.5 font-mono\">Esc</kbd>\n đóng\n </span>\n </div>\n </Section>\n </Shell>\n );\n}\n\n// Back-compat alias\nexport { LeftPanel as LatexLeftPanel };\n","'use client';\nimport React, {\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useRef,\n useState,\n} from 'react';\nimport { renderLatexToSvg } from '../render';\n\ninterface Props {\n /**\n * Legacy: vị trí absolute x/y nếu cần (test). Khi cả 2 = 0 và `centered` !== false,\n * popover sẽ tự center floating ở giữa khu vực bảng. Khi `withLeftPanel` = true,\n * vị trí center được offset 120px để chừa chỗ panel trái.\n */\n x: number;\n y: number;\n initialValue: string;\n onInsert: (svgString: string, src: string, displayMode: boolean) => void;\n onClose: () => void;\n /** Khi controlled từ parent (StampLeftPanel), parent set giá trị này. */\n displayMode?: boolean;\n onDisplayModeChange?: (b: boolean) => void;\n /** Khi true, position center offset cho panel trái. */\n withLeftPanel?: boolean;\n /** Mobile mode: full-screen + hamburger header. */\n isMobile?: boolean;\n /** Trigger mở snippet drawer trên mobile. */\n onOpenDrawer?: () => void;\n}\n\nexport interface EditorPopoverHandle {\n /** Chèn snippet vào vị trí con trỏ trong textbox. */\n insertAtCursor: (snippet: string) => void;\n /** Có content hợp lệ để chèn không (input không rỗng + preview ok). */\n hasContent: () => boolean;\n /** Trigger insert programmatically — return true nếu chèn thành công. */\n tryInsert: () => boolean;\n}\n\nconst DEBOUNCE_MS = 100;\n\nexport const EditorPopover = forwardRef<EditorPopoverHandle, Props>(function EditorPopover(\n {\n x,\n y,\n initialValue,\n onInsert,\n onClose,\n displayMode: controlledDisplayMode,\n onDisplayModeChange,\n withLeftPanel = false,\n isMobile = false,\n onOpenDrawer,\n },\n ref,\n) {\n const [value, setValue] = useState(initialValue);\n const [internalDisplayMode] = useState(false);\n const displayMode = controlledDisplayMode ?? internalDisplayMode;\n // onDisplayModeChange chỉ dùng khi controlled từ parent — không cần local setter\n void onDisplayModeChange;\n\n const [previewSvg, setPreviewSvg] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const inputRef = useRef<HTMLInputElement>(null);\n\n useEffect(() => {\n if (debounceRef.current) clearTimeout(debounceRef.current);\n debounceRef.current = setTimeout(async () => {\n try {\n const svg = await renderLatexToSvg(value, displayMode);\n setPreviewSvg(svg);\n setError(null);\n } catch (err) {\n setPreviewSvg(null);\n setError((err as Error).message);\n }\n }, DEBOUNCE_MS);\n return () => {\n if (debounceRef.current) clearTimeout(debounceRef.current);\n };\n }, [value, displayMode]);\n\n const handleInsert = useCallback(() => {\n if (!previewSvg) return;\n onInsert(previewSvg, value, displayMode);\n }, [previewSvg, value, displayMode, onInsert]);\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (e.key === 'Escape') onClose();\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n handleInsert();\n }\n },\n [onClose, handleInsert],\n );\n\n // Imperative API: snippet button trong panel trái gọi vào, click-outside auto-insert.\n useImperativeHandle(\n ref,\n () => ({\n insertAtCursor: (snippet: string) => {\n const el = inputRef.current;\n if (!el) {\n setValue((v) => v + snippet);\n return;\n }\n const start = el.selectionStart ?? value.length;\n const end = el.selectionEnd ?? value.length;\n const next = value.slice(0, start) + snippet + value.slice(end);\n setValue(next);\n requestAnimationFrame(() => {\n el.focus();\n const pos = start + snippet.length;\n try {\n el.setSelectionRange(pos, pos);\n } catch {\n /* ignore */\n }\n });\n },\n hasContent: () => value.trim().length > 0 && !!previewSvg && !error,\n tryInsert: () => {\n if (!previewSvg || error || !value.trim()) return false;\n onInsert(previewSvg, value, displayMode);\n return true;\n },\n }),\n [value, previewSvg, error, displayMode, onInsert],\n );\n\n // Position: nếu x/y > 0 → dùng legacy absolute (cho tests cũ). Còn không thì center floating.\n const isLegacyPosition = x > 0 || y > 0;\n const wrapperStyle: React.CSSProperties = isMobile\n ? { position: 'fixed', inset: 0, zIndex: 50 }\n : isLegacyPosition\n ? { position: 'absolute', top: y, left: x, zIndex: 50 }\n : {\n position: 'absolute',\n top: '50%',\n left: withLeftPanel ? 'calc(50% + 120px)' : '50%',\n transform: 'translate(-50%, -50%)',\n zIndex: 50,\n };\n\n return (\n <div\n style={wrapperStyle}\n data-stamp-area=\"true\"\n data-mobile-editor={isMobile ? 'true' : undefined}\n className={\n isMobile\n ? 'flex h-full w-full flex-col bg-white'\n : 'w-[420px] max-w-[calc(100vw-280px)] rounded-lg border border-slate-300 bg-white shadow-2xl ring-1 ring-black/5'\n }\n role=\"dialog\"\n aria-label=\"Nhập công thức LaTeX\"\n >\n <header className={`flex items-center gap-2 border-b border-slate-200 bg-gradient-to-r from-indigo-600 to-purple-600 px-3 py-2 text-white${isMobile ? '' : ' rounded-t-lg'}`}>\n {isMobile && (\n <button\n type=\"button\"\n onClick={onOpenDrawer}\n aria-label=\"Mở ngăn snippet\"\n className=\"-ml-1 inline-flex h-10 w-10 items-center justify-center rounded transition hover:bg-white/15\"\n >\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <line x1=\"4\" y1=\"6\" x2=\"20\" y2=\"6\" />\n <line x1=\"4\" y1=\"12\" x2=\"20\" y2=\"12\" />\n <line x1=\"4\" y1=\"18\" x2=\"20\" y2=\"18\" />\n </svg>\n </button>\n )}\n <h3 className=\"flex flex-1 items-center gap-2 text-sm font-semibold\">\n <span className=\"text-base leading-none\">∑</span>\n Công thức LaTeX\n </h3>\n {isMobile && (\n <button\n type=\"button\"\n onClick={handleInsert}\n disabled={!previewSvg || !!error}\n data-testid=\"latex-insert-btn-mobile\"\n className=\"rounded bg-white/15 px-3 py-1.5 text-xs font-semibold transition hover:bg-white/25 disabled:opacity-50\"\n >\n Chèn\n </button>\n )}\n <button\n onClick={onClose}\n aria-label=\"Đóng\"\n className=\"inline-flex h-9 w-9 items-center justify-center rounded transition hover:bg-white/15\"\n >\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n </svg>\n </button>\n </header>\n <div className={`space-y-2 p-3${isMobile ? ' flex min-h-0 flex-1 flex-col' : ''}`}>\n <input\n ref={inputRef}\n type=\"text\"\n role=\"textbox\"\n value={value}\n onChange={(e) => setValue(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder=\"Vd: \\frac{a^2+b^2}{c}\"\n className={`w-full rounded border border-slate-300 px-2 py-1.5 font-mono outline-none focus:border-indigo-400 focus:ring-2 focus:ring-indigo-200${\n isMobile ? ' min-h-[44px] text-base' : ' text-sm'\n }`}\n autoFocus\n />\n <div\n className={[\n 'flex items-center justify-center rounded border p-3 text-center',\n isMobile ? 'min-h-0 flex-1 overflow-auto' : 'min-h-[64px]',\n error ? 'border-rose-300 bg-rose-50 text-rose-700' : 'border-slate-200 bg-slate-50',\n ].join(' ')}\n >\n {error ? (\n <span className=\"text-xs\">Lỗi: {error.slice(0, 80)}</span>\n ) : previewSvg ? (\n <span dangerouslySetInnerHTML={{ __html: previewSvg }} />\n ) : (\n <span className=\"text-xs text-slate-400\">(xem trước)</span>\n )}\n </div>\n {!isMobile && (\n <div className=\"flex items-center justify-between\">\n <span className=\"text-[11px] text-slate-500\">\n {displayMode ? 'Block' : 'Inline'} · Enter để chèn\n </span>\n <div className=\"flex gap-2\">\n <button\n onClick={onClose}\n className=\"rounded border border-slate-300 bg-white px-3 py-1 text-xs font-medium text-slate-700 transition hover:bg-slate-100\"\n >\n Huỷ\n </button>\n <button\n onClick={handleInsert}\n disabled={!previewSvg || !!error}\n className=\"rounded bg-indigo-600 px-3 py-1 text-xs font-medium text-white transition hover:bg-indigo-700 disabled:opacity-50\"\n >\n Chèn\n </button>\n </div>\n </div>\n )}\n {isMobile && (\n <div className=\"text-center text-[11px] text-slate-500\">\n {displayMode ? 'Block' : 'Inline'} · Bấm Chèn ở thanh trên\n </div>\n )}\n </div>\n </div>\n );\n});\n\n// Back-compat aliases\nexport { EditorPopover as LatexEditorPopover };\nexport type { EditorPopoverHandle as LatexEditorHandle };\n","'use client';\n\nimport {\n forwardRef,\n useCallback,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { LeftPanel as LatexLeftPanel } from './editor/LeftPanel';\nimport {\n EditorPopover as LatexEditorPopover,\n type EditorPopoverHandle as LatexEditorHandle,\n} from './editor/EditorPopover';\nimport { insertStampImage } from '../shared/insertImage';\nimport { useIsMobile } from '../shared/useIsMobile';\nimport { isLatexCustomData, type LatexCustomData } from './types';\nimport type { StampHostProps, StampHostHandle } from '../shared/types';\n\nexport const LatexStampHost = forwardRef<StampHostHandle, StampHostProps>(\n function LatexStampHost({ api, editingElement, onClose }, ref) {\n const editorRef = useRef<LatexEditorHandle | null>(null);\n const { isMobile } = useIsMobile();\n const [drawerOpen, setDrawerOpen] = useState(false);\n\n const initial = useMemo(() => {\n if (editingElement && isLatexCustomData(editingElement.customData)) {\n return {\n initialValue: editingElement.customData.src,\n displayMode: !!editingElement.customData.displayMode,\n };\n }\n return { initialValue: '', displayMode: false };\n }, [editingElement]);\n\n const [displayMode, setDisplayMode] = useState(initial.displayMode);\n\n const handleInsert = useCallback(\n async (svgString: string, src: string, dm: boolean) => {\n if (!api) return;\n try {\n await insertStampImage(api, {\n svgString,\n makeCustomData: (): LatexCustomData => ({\n kind: 'latex',\n version: 1,\n src,\n displayMode: dm,\n }),\n editingElementId: editingElement?.id ?? null,\n });\n } catch (err) {\n console.error('Latex insert failed:', err);\n }\n onClose();\n },\n [api, editingElement?.id, onClose],\n );\n\n useImperativeHandle(\n ref,\n () => ({\n tryInsert: () => editorRef.current?.tryInsert() ?? false,\n hasContent: () => editorRef.current?.hasContent() ?? false,\n }),\n [],\n );\n\n return (\n <>\n <LatexLeftPanel\n displayMode={displayMode}\n onDisplayModeChange={setDisplayMode}\n onInsertSnippet={(s) => editorRef.current?.insertAtCursor(s)}\n onClose={onClose}\n isMobile={isMobile}\n drawerOpen={drawerOpen}\n onDrawerClose={() => setDrawerOpen(false)}\n />\n <LatexEditorPopover\n ref={editorRef}\n x={0}\n y={0}\n initialValue={initial.initialValue}\n displayMode={displayMode}\n onDisplayModeChange={setDisplayMode}\n onInsert={handleInsert}\n onClose={onClose}\n withLeftPanel={!isMobile}\n isMobile={isMobile}\n onOpenDrawer={() => setDrawerOpen(true)}\n />\n </>\n );\n },\n);\n"]}
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { useChordShortcut } from './chunk-HNQLZIEP.mjs';
|
|
3
3
|
import { useToolStateMachine } from './chunk-NVJ7K3DK.mjs';
|
|
4
|
-
import { safeJsx, initJxgBoard, attachJxgWheelZoom, useToast, ToastHost, STAMP_PANEL_DESKTOP, ToastProvider, useStampStore, StampLeftPanel, ObjectRow } from './chunk-
|
|
5
|
-
import { serializeBoard, renderGeometrySvgFromState, isGeometryCustomData, deserializeBoard } from './chunk-
|
|
4
|
+
import { safeJsx, initJxgBoard, attachJxgWheelZoom, useToast, ToastHost, STAMP_PANEL_DESKTOP, ToastProvider, useStampStore, StampLeftPanel, ObjectRow } from './chunk-LTLLQUMN.mjs';
|
|
5
|
+
import { isDefaultBbox, autoFitBoardToContent, serializeBoard, renderGeometrySvgFromState, isGeometryCustomData, deserializeBoard } from './chunk-KOXOC2FI.mjs';
|
|
6
6
|
import { themeLabel, paletteFor, themeAxis, themeGrid } from './chunk-R5FL6S7L.mjs';
|
|
7
|
-
import { JxgRenderer } from './chunk-
|
|
7
|
+
import { JxgRenderer } from './chunk-IE2GGHNF.mjs';
|
|
8
8
|
import './chunk-ICR4CVOE.mjs';
|
|
9
|
-
import { nextLabel, useEditorState, listObjects } from './chunk-
|
|
10
|
-
import './chunk-
|
|
11
|
-
import { validateFile, fileToImagePart, describeDsl } from './chunk-
|
|
9
|
+
import { nextLabel, useEditorState, listObjects } from './chunk-JJ4FPCBE.mjs';
|
|
10
|
+
import './chunk-CH6SFONH.mjs';
|
|
11
|
+
import { validateFile, fileToImagePart, describeDsl } from './chunk-DWIEVCGK.mjs';
|
|
12
12
|
import { handleExtractProblem } from './chunk-QK6OVDLC.mjs';
|
|
13
13
|
import { DEFAULT_VIEW_2D } from './chunk-73Q7ADVL.mjs';
|
|
14
14
|
import './chunk-B4NJJZFR.mjs';
|
|
15
15
|
import { useIsMobile } from './chunk-P2AOIF7S.mjs';
|
|
16
|
-
import { insertStampImage } from './chunk-
|
|
16
|
+
import { insertStampImage } from './chunk-QLQ4MJNO.mjs';
|
|
17
17
|
import './chunk-5UTGXHLJ.mjs';
|
|
18
18
|
import { __export } from './chunk-J5LGTIGS.mjs';
|
|
19
19
|
import { forwardRef, useRef, useId, useState, useEffect, useCallback, useImperativeHandle, useMemo, useLayoutEffect } from 'react';
|
|
@@ -331,41 +331,48 @@ var Icon = {
|
|
|
331
331
|
/* @__PURE__ */ jsx("circle", { cx: "4", cy: "4", r: "1.7", fill: C_POINT })
|
|
332
332
|
] }),
|
|
333
333
|
// ===== Nâng cao / kind chưa có icon =====
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
/* @__PURE__ */ jsx("
|
|
334
|
+
// Hệ màu đồng bộ: XANH = input click sẵn, ĐỎ = output suy ra. Toạ độ tính để
|
|
335
|
+
// điểm nằm ĐÚNG trên đường tròn/cung/tiếp tuyến (không trôi nổi).
|
|
336
|
+
excenter: /* @__PURE__ */ jsxs("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
337
|
+
/* @__PURE__ */ jsx("polygon", { points: "12,3 15,15 9,15", stroke: "currentColor", strokeWidth: "1.4", fill: "none" }),
|
|
338
|
+
/* @__PURE__ */ jsx("line", { x1: "9", y1: "15", x2: "8", y2: "18.9", stroke: "#94a3b8", strokeWidth: "1", strokeDasharray: "1.6 1.6" }),
|
|
339
|
+
/* @__PURE__ */ jsx("line", { x1: "15", y1: "15", x2: "16", y2: "18.9", stroke: "#94a3b8", strokeWidth: "1", strokeDasharray: "1.6 1.6" }),
|
|
340
|
+
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "18.9", r: "3.8", stroke: "currentColor", strokeWidth: "1.3" }),
|
|
341
|
+
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "3", r: "1.6", fill: C_POINT }),
|
|
342
|
+
/* @__PURE__ */ jsx("circle", { cx: "9", cy: "15", r: "1.6", fill: C_POINT }),
|
|
343
|
+
/* @__PURE__ */ jsx("circle", { cx: "15", cy: "15", r: "1.6", fill: C_POINT }),
|
|
344
|
+
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "18.9", r: "2.2", fill: C_CONSTRUCT })
|
|
338
345
|
] }),
|
|
339
|
-
tangencyPoint: /* @__PURE__ */ jsxs("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", children: [
|
|
340
|
-
/* @__PURE__ */ jsx("circle", { cx: "
|
|
341
|
-
/* @__PURE__ */ jsx("line", { x1: "16.5", y1: "3", x2: "16.5", y2: "
|
|
342
|
-
/* @__PURE__ */ jsx("circle", { cx: "16.5", cy: "12", r: "2.
|
|
346
|
+
tangencyPoint: /* @__PURE__ */ jsxs("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", strokeLinecap: "round", children: [
|
|
347
|
+
/* @__PURE__ */ jsx("circle", { cx: "9.5", cy: "12", r: "7", stroke: "currentColor", strokeWidth: "1.4" }),
|
|
348
|
+
/* @__PURE__ */ jsx("line", { x1: "16.5", y1: "3.5", x2: "16.5", y2: "20.5", stroke: "currentColor", strokeWidth: "1.4" }),
|
|
349
|
+
/* @__PURE__ */ jsx("circle", { cx: "16.5", cy: "12", r: "2.3", fill: C_CONSTRUCT })
|
|
343
350
|
] }),
|
|
344
|
-
secondIntersection: /* @__PURE__ */ jsxs("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", children: [
|
|
345
|
-
/* @__PURE__ */ jsx("circle", { cx: "11", cy: "12", r: "6.5", stroke: "currentColor", strokeWidth: "1.
|
|
346
|
-
/* @__PURE__ */ jsx("line", { x1: "2", y1: "8", x2: "
|
|
347
|
-
/* @__PURE__ */ jsx("circle", { cx: "
|
|
348
|
-
/* @__PURE__ */ jsx("circle", { cx: "
|
|
351
|
+
secondIntersection: /* @__PURE__ */ jsxs("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", strokeLinecap: "round", children: [
|
|
352
|
+
/* @__PURE__ */ jsx("circle", { cx: "11", cy: "12", r: "6.5", stroke: "currentColor", strokeWidth: "1.4" }),
|
|
353
|
+
/* @__PURE__ */ jsx("line", { x1: "2.4", y1: "8.2", x2: "20.4", y2: "11.4", stroke: "currentColor", strokeWidth: "1.4" }),
|
|
354
|
+
/* @__PURE__ */ jsx("circle", { cx: "5.37", cy: "8.75", r: "1.8", fill: C_POINT }),
|
|
355
|
+
/* @__PURE__ */ jsx("circle", { cx: "17.4", cy: "10.87", r: "2.4", fill: C_CONSTRUCT })
|
|
349
356
|
] }),
|
|
350
357
|
arcMidpoint: /* @__PURE__ */ jsxs("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", strokeLinecap: "round", children: [
|
|
351
|
-
/* @__PURE__ */ jsx("path", { d: "M4 17 A
|
|
352
|
-
/* @__PURE__ */ jsx("circle", { cx: "4", cy: "17", r: "1.
|
|
353
|
-
/* @__PURE__ */ jsx("circle", { cx: "20", cy: "17", r: "1.
|
|
354
|
-
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "
|
|
358
|
+
/* @__PURE__ */ jsx("path", { d: "M4 17 A 8.5 8.5 0 0 1 20 17", stroke: "currentColor", strokeWidth: "1.6", fill: "none" }),
|
|
359
|
+
/* @__PURE__ */ jsx("circle", { cx: "4", cy: "17", r: "1.8", fill: C_POINT }),
|
|
360
|
+
/* @__PURE__ */ jsx("circle", { cx: "20", cy: "17", r: "1.8", fill: C_POINT }),
|
|
361
|
+
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "11.4", r: "2.3", fill: C_CONSTRUCT })
|
|
355
362
|
] }),
|
|
356
363
|
circleIntersection: /* @__PURE__ */ jsxs("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", children: [
|
|
357
|
-
/* @__PURE__ */ jsx("circle", { cx: "9", cy: "12", r: "6", stroke: "currentColor", strokeWidth: "1.
|
|
358
|
-
/* @__PURE__ */ jsx("circle", { cx: "15", cy: "12", r: "6", stroke: "currentColor", strokeWidth: "1.
|
|
359
|
-
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "
|
|
360
|
-
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "
|
|
364
|
+
/* @__PURE__ */ jsx("circle", { cx: "9", cy: "12", r: "6", stroke: "currentColor", strokeWidth: "1.4" }),
|
|
365
|
+
/* @__PURE__ */ jsx("circle", { cx: "15", cy: "12", r: "6", stroke: "currentColor", strokeWidth: "1.4" }),
|
|
366
|
+
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "6.8", r: "2", fill: C_CONSTRUCT }),
|
|
367
|
+
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "17.2", r: "2", fill: C_CONSTRUCT })
|
|
361
368
|
] }),
|
|
362
369
|
tangentPointExt: /* @__PURE__ */ jsxs("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", strokeLinecap: "round", children: [
|
|
363
|
-
/* @__PURE__ */ jsx("circle", { cx: "
|
|
364
|
-
/* @__PURE__ */ jsx("
|
|
365
|
-
/* @__PURE__ */ jsx("line", { x1: "3
|
|
366
|
-
/* @__PURE__ */ jsx("
|
|
367
|
-
/* @__PURE__ */ jsx("circle", { cx: "
|
|
368
|
-
/* @__PURE__ */ jsx("circle", { cx: "
|
|
370
|
+
/* @__PURE__ */ jsx("circle", { cx: "13", cy: "12", r: "6", stroke: "currentColor", strokeWidth: "1.4" }),
|
|
371
|
+
/* @__PURE__ */ jsx("line", { x1: "3", y1: "12", x2: "11.8", y2: "18.6", stroke: "currentColor", strokeWidth: "1.3" }),
|
|
372
|
+
/* @__PURE__ */ jsx("line", { x1: "3", y1: "12", x2: "11.8", y2: "5.4", stroke: "currentColor", strokeWidth: "1.3" }),
|
|
373
|
+
/* @__PURE__ */ jsx("circle", { cx: "3", cy: "12", r: "2", fill: C_POINT }),
|
|
374
|
+
/* @__PURE__ */ jsx("circle", { cx: "9.4", cy: "16.8", r: "1.8", fill: C_CONSTRUCT }),
|
|
375
|
+
/* @__PURE__ */ jsx("circle", { cx: "9.4", cy: "7.2", r: "1.8", fill: C_CONSTRUCT })
|
|
369
376
|
] }),
|
|
370
377
|
circleCR: /* @__PURE__ */ jsxs("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", children: [
|
|
371
378
|
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "7.5", stroke: "currentColor", strokeWidth: "1.3" }),
|
|
@@ -376,9 +383,11 @@ var Icon = {
|
|
|
376
383
|
/* @__PURE__ */ jsx("path", { d: "M3 19 L12 4 L21 19 Z", stroke: "currentColor", strokeWidth: "1.3", strokeLinejoin: "round" }),
|
|
377
384
|
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "14", r: "4.2", fill: "none", stroke: C_CONSTRUCT, strokeWidth: "1.3" })
|
|
378
385
|
] }),
|
|
379
|
-
excircle: /* @__PURE__ */ jsxs("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", children: [
|
|
380
|
-
/* @__PURE__ */ jsx("
|
|
381
|
-
/* @__PURE__ */ jsx("
|
|
386
|
+
excircle: /* @__PURE__ */ jsxs("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
387
|
+
/* @__PURE__ */ jsx("polygon", { points: "12,3 15,15 9,15", stroke: "currentColor", strokeWidth: "1.4", fill: "none" }),
|
|
388
|
+
/* @__PURE__ */ jsx("line", { x1: "9", y1: "15", x2: "8", y2: "18.9", stroke: "#94a3b8", strokeWidth: "1", strokeDasharray: "1.6 1.6" }),
|
|
389
|
+
/* @__PURE__ */ jsx("line", { x1: "15", y1: "15", x2: "16", y2: "18.9", stroke: "#94a3b8", strokeWidth: "1", strokeDasharray: "1.6 1.6" }),
|
|
390
|
+
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "18.9", r: "3.8", stroke: C_CONSTRUCT, strokeWidth: "1.5", fill: C_CONSTRUCT, fillOpacity: "0.12" })
|
|
382
391
|
] }),
|
|
383
392
|
pointOn: /* @__PURE__ */ jsxs("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", children: [
|
|
384
393
|
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "7.5", stroke: "currentColor", strokeWidth: "1.3" }),
|
|
@@ -2123,11 +2132,11 @@ function buildObjectSnapshot(state, id, anchorScreen) {
|
|
|
2123
2132
|
const obj = state.objects[id];
|
|
2124
2133
|
if (!obj) return null;
|
|
2125
2134
|
const k = obj.kind;
|
|
2126
|
-
if (k !== "point" && k !== "line" && k !== "circle" && k !== "segment" && k !== "ray" && k !== "vector") {
|
|
2135
|
+
if (k !== "point" && k !== "line" && k !== "circle" && k !== "segment" && k !== "ray" && k !== "vector" && k !== "intersection") {
|
|
2127
2136
|
return null;
|
|
2128
2137
|
}
|
|
2129
2138
|
const a = obj.attrs;
|
|
2130
|
-
const jKind = k === "point" ? "point" : k === "circle" ? "circle" : "line";
|
|
2139
|
+
const jKind = k === "point" || k === "intersection" ? "point" : k === "circle" ? "circle" : "line";
|
|
2131
2140
|
return {
|
|
2132
2141
|
id,
|
|
2133
2142
|
kind: jKind,
|
|
@@ -2703,6 +2712,11 @@ var MiniBoard2D = forwardRef(function MiniBoard2D2({ onReady, store, selectedToo
|
|
|
2703
2712
|
rendererRef.current = new JxgRenderer(store, board, {
|
|
2704
2713
|
theme: paletteFor(isDarkRef.current)
|
|
2705
2714
|
});
|
|
2715
|
+
if (isDefaultBbox(initialView.bbox)) {
|
|
2716
|
+
const el = containerRef.current;
|
|
2717
|
+
const aspect = el && el.clientHeight > 0 ? el.clientWidth / el.clientHeight : 1;
|
|
2718
|
+
safeJsx("MiniBoard.autoFit", () => autoFitBoardToContent(board, aspect));
|
|
2719
|
+
}
|
|
2706
2720
|
if (containerRef.current) {
|
|
2707
2721
|
wheelCleanup = attachJxgWheelZoom(containerRef.current, board, "MiniBoard.2d");
|
|
2708
2722
|
}
|
|
@@ -3272,6 +3286,7 @@ function useAiFigure(generator) {
|
|
|
3272
3286
|
const [prompt, setPrompt] = useState("");
|
|
3273
3287
|
const [isLoading, setIsLoading] = useState(false);
|
|
3274
3288
|
const [error, setError] = useState(null);
|
|
3289
|
+
const [notice, setNotice] = useState(null);
|
|
3275
3290
|
const [tokens, setTokens] = useState(0);
|
|
3276
3291
|
const abortRef = useRef(null);
|
|
3277
3292
|
const requestIdRef = useRef(0);
|
|
@@ -3292,6 +3307,7 @@ function useAiFigure(generator) {
|
|
|
3292
3307
|
abortRef.current = controller;
|
|
3293
3308
|
setIsLoading(true);
|
|
3294
3309
|
setError(null);
|
|
3310
|
+
setNotice(null);
|
|
3295
3311
|
setTokens(0);
|
|
3296
3312
|
try {
|
|
3297
3313
|
const generated = await generator(problem, {
|
|
@@ -3305,6 +3321,7 @@ function useAiFigure(generator) {
|
|
|
3305
3321
|
setError(generated.message);
|
|
3306
3322
|
return null;
|
|
3307
3323
|
}
|
|
3324
|
+
if (generated.partial) setNotice(generated.partial.message);
|
|
3308
3325
|
return generated.state;
|
|
3309
3326
|
} catch (caught) {
|
|
3310
3327
|
if (controller.signal.aborted || caught instanceof DOMException && caught.name === "AbortError") {
|
|
@@ -3331,6 +3348,7 @@ function useAiFigure(generator) {
|
|
|
3331
3348
|
setPrompt,
|
|
3332
3349
|
isLoading,
|
|
3333
3350
|
error,
|
|
3351
|
+
notice,
|
|
3334
3352
|
submit,
|
|
3335
3353
|
cancel,
|
|
3336
3354
|
tokens
|
|
@@ -3374,6 +3392,7 @@ function AiFigurePrompt({ generator, onGenerated }) {
|
|
|
3374
3392
|
setPrompt,
|
|
3375
3393
|
isLoading,
|
|
3376
3394
|
error,
|
|
3395
|
+
notice,
|
|
3377
3396
|
submit,
|
|
3378
3397
|
cancel,
|
|
3379
3398
|
tokens
|
|
@@ -3387,6 +3406,10 @@ function AiFigurePrompt({ generator, onGenerated }) {
|
|
|
3387
3406
|
const id = setInterval(() => setElapsed((s) => s + 1), 1e3);
|
|
3388
3407
|
return () => clearInterval(id);
|
|
3389
3408
|
}, [isLoading]);
|
|
3409
|
+
const [noticeDismissed, setNoticeDismissed] = useState(false);
|
|
3410
|
+
useEffect(() => {
|
|
3411
|
+
setNoticeDismissed(false);
|
|
3412
|
+
}, [notice]);
|
|
3390
3413
|
const [image, setImage] = useState(null);
|
|
3391
3414
|
const [ocrLoading, setOcrLoading] = useState(false);
|
|
3392
3415
|
const [ocrError, setOcrError] = useState(null);
|
|
@@ -3602,7 +3625,30 @@ function AiFigurePrompt({ generator, onGenerated }) {
|
|
|
3602
3625
|
}
|
|
3603
3626
|
),
|
|
3604
3627
|
ocrError && /* @__PURE__ */ jsx("p", { role: "alert", className: "mt-1 px-1 text-xs text-red-600", children: ocrError }),
|
|
3605
|
-
error && /* @__PURE__ */ jsx("p", { role: "alert", className: "mt-1 px-1 text-xs text-red-600", children: error })
|
|
3628
|
+
error && /* @__PURE__ */ jsx("p", { role: "alert", className: "mt-1 px-1 text-xs text-red-600", children: error }),
|
|
3629
|
+
notice && !noticeDismissed && /* @__PURE__ */ jsxs(
|
|
3630
|
+
"div",
|
|
3631
|
+
{
|
|
3632
|
+
role: "status",
|
|
3633
|
+
"data-testid": "geometry-ai-partial-notice",
|
|
3634
|
+
className: "relative mt-2 whitespace-pre-wrap rounded-lg border border-amber-200 bg-amber-50 py-2 pl-3 pr-8 text-xs leading-relaxed text-amber-800",
|
|
3635
|
+
children: [
|
|
3636
|
+
notice,
|
|
3637
|
+
/* @__PURE__ */ jsx(
|
|
3638
|
+
"button",
|
|
3639
|
+
{
|
|
3640
|
+
type: "button",
|
|
3641
|
+
onClick: () => setNoticeDismissed(true),
|
|
3642
|
+
"aria-label": "\u0110\xF3ng th\xF4ng b\xE1o",
|
|
3643
|
+
title: "\u0110\xF3ng th\xF4ng b\xE1o",
|
|
3644
|
+
"data-testid": "geometry-ai-partial-dismiss",
|
|
3645
|
+
className: "absolute right-1 top-1 flex h-5 w-5 items-center justify-center rounded text-amber-500 transition hover:bg-amber-100 hover:text-amber-800",
|
|
3646
|
+
children: "\xD7"
|
|
3647
|
+
}
|
|
3648
|
+
)
|
|
3649
|
+
]
|
|
3650
|
+
}
|
|
3651
|
+
)
|
|
3606
3652
|
] });
|
|
3607
3653
|
}
|
|
3608
3654
|
|
|
@@ -4111,7 +4157,8 @@ var GeometryStampHost = forwardRef(
|
|
|
4111
4157
|
version: 1,
|
|
4112
4158
|
jsonState
|
|
4113
4159
|
}),
|
|
4114
|
-
editingElementId: editingElement?.id ?? null
|
|
4160
|
+
editingElementId: editingElement?.id ?? null,
|
|
4161
|
+
preserveExistingSize: true
|
|
4115
4162
|
});
|
|
4116
4163
|
} catch (err) {
|
|
4117
4164
|
console.error("Geometry insert failed:", err);
|
|
@@ -4199,5 +4246,5 @@ var GeometryStampHost = forwardRef(
|
|
|
4199
4246
|
);
|
|
4200
4247
|
|
|
4201
4248
|
export { GeometryStampHost };
|
|
4202
|
-
//# sourceMappingURL=host-
|
|
4203
|
-
//# sourceMappingURL=host-
|
|
4249
|
+
//# sourceMappingURL=host-KMWP7KBT.mjs.map
|
|
4250
|
+
//# sourceMappingURL=host-KMWP7KBT.mjs.map
|